diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..584a6fcd --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +*.[oa] +*~ +*.so +*.bak +*-orig +*-sav +foo* +goo* +node.log +Makefile +conf.h +config.status +config.cache +debug.html +ofitsy.js +TODO +BUGS +.DS_Store +js/.DS_Store +astroem/.DS_Store +a.out.dSym/ +archive/ +fits/ +hera/ +kes75/ +nan/ +net/ +notes/ +old/ +png/ +rites/ +sfs/ +smartx/ +test/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..bdd1bdce --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +JS9 is distributed under the terms of The MIT License (MIT), reproduced below. + +Copyright (c) 2014 Smithsonian Institution + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..79e0977a --- /dev/null +++ b/Makefile.in @@ -0,0 +1,475 @@ +# +# This file is a Makefile for HOSTIP. If it has the name "Makefile.in" +# then it is a template for a Makefile; to generate the actual Makefile, +# run "./configure", which is a configuration script generated by the +# "autoconf" program (constructs like "@foo@" will get replaced in the +# actual Makefile. +# + +PACKAGE = @PACKAGE_NAME@ +VERSION = @PACKAGE_VERSION@ +DISTNAME = ${PACKAGE}-${VERSION} +DDISTNAME = ${PACKAGE}-data + +DISTDIR = ../export +FTPDIR = ../ftp + +#---------------------------------------------------------------- +# Things you can change to personalize the Makefile for your own +# site (you can make these changes in either Makefile.in or +# Makefile, but changes to Makefile will get lost if you re-run +# the configuration script). +#---------------------------------------------------------------- + +# Default top-level directories in which to install architecture- +# specific files (exec_prefix) and machine-independent files such +# as scripts (prefix). The values specified here may be overridden +# at configure-time with the --exec-prefix and --prefix options +# to the "configure" script. + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +# The following definition can be set to non-null for special systems +# like AFS with replication. It allows the pathnames used for installation +# to be different than those used for actually reference files at +# run-time. INSTALL_ROOT is prepended to $prefix and $exec_prefix +# when installing files. +INSTALL_ROOT = + +# Directory in which to install the .a or .so binary for the TPOS library: +LIB_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/lib + +# Directory in which to install the program wish: +BIN_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/bin + +# Directory in which to install the include file tpos.h: +INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/include + +# Top-level directory for manual entries: +MAN_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/man + +# Directory in which to install manual entry for TPOS programs: +MAN1_INSTALL_DIR = $(MAN_INSTALL_DIR)/man1 + +# Directory in which to install manual entries for TPOS's C library +# procedures: +MAN3_INSTALL_DIR = $(MAN_INSTALL_DIR)/man3 + +# extra Libs required to link (e.g. socket libraries) +LIBS = @FUNLIB@ @PNGLIB@ @EXTRA_LIBS@ -lm + +INCS = @FUNINC@ @PNGINC@ + +# To change the compiler switches, for example to change from -O +# to -g, change the following line: +CFLAGS = @CFLAGS@ + +# To add ld switches, change the following line: +LDFLAGS = @LDFLAGS@ + +# Some versions of make, like SGI's, use the following variable to +# determine which shell to use for executing commands: +SHELL = /bin/sh + +# There are just too many different versions of "install" around; +# better to use the install-sh script that comes with the distribution, +# which is slower but guaranteed to work. + +INSTALL = @srcdir@/install-sh -c +INSTALL_PROGRAM = ${INSTALL} +INSTALL_DATA = ${INSTALL} -m 644 + +#---------------------------------------------------------------- +# The information below is modified by the configure script when +# Makefile is generated from Makefile.in. You shouldn't normally +# modify any of this stuff by hand. +#---------------------------------------------------------------- + +AC_FLAGS = @DEFS@ +RANLIB = @RANLIB@ + +#---------------------------------------------------------------- +# The information below should be usable as is. The configure +# script won't modify it and you shouldn't need to modify it +# either. +#---------------------------------------------------------------- +RM = rm -f + +CP = cp -p + +CC = @CC@ + +CC_SWITCHES = ${CFLAGS} -I. ${AC_FLAGS} ${INCS} + +DEPEND_SWITCHES = ${CFLAGS} -I. ${AC_FLAGS} + +# type of backend server (or none) +HELPER = @HELPER@ +USEHELPER = @USEHELPER@ + +# where the web files go on your site +WEBDIR = @WEBDIR@ +CGIDIR = @CGIDIR@ +CGIURL = @CGIURL@ +CGIXPATH = @CGIXPATH@ +# this is for SAO install only ... I think! +SAODIR = @SAODIR@ + +WEBDIRS = plugins params js css images + +BEDIRS = node_modules analysis-plugins analysis-wrappers + +WEBFILES = js9.js js9.min.js js9-$(VERSION).js js9-$(VERSION).min.js \ + js9support.js js9support.min.js js9support.css js9plugins.js \ + js9support.txt js9.css fitsy.js fitsy.min.js \ + js9Msg.js js9Helper.js js9Prefs-default.json \ + js9Prefs.json favicon.ico index.html + +SAOFILES = index.html + +CSSFILES = css/jquery.contextMenu.css css/dhtmlwindow.css + +JSFILES = js/jquery.min.js js/jquery.contextMenu.min.js js/jquery.flot.min.js js/jquery.flot.errorbars.min.js js/jquery.flot.selection.min.js js/flot-zoom.min.js js/sprintf.min.js js/dhtmlwindow.min.js js/dhtmlwindow_blurb.js js/fabric.min.js js/pako_inflate.min.js js/astroem.js + +PLUGINFILES = plugins/archive/archive.js \ + plugins/fitsy/binning.js \ + plugins/imexam/imexam.js \ + plugins/imexam/encircled.js \ + plugins/imexam/pixtable.js \ + plugins/imexam/radproj.js \ + plugins/imexam/reghist.js \ + plugins/imexam/regstat.js \ + plugins/imexam/xyproj.js \ + plugins/imexam/3dplot.js + +PREFFILES = js9Prefs.json + +CGIFILES = js9Helper.cgi + +WEBHELP = help + +WEBDATA = fits png kes75 + +SRCS = tpos.c js9helper.c + +PROGS = tpos js9helper + +TESTPROGS = pngdisp + +INCLUDES = js9helper.h + +SCRIPTS = funhist2flot funcnts2flot fits2png + +SCRIPTS2 = js9 + +ARCFILES = js9-$(VERSION).js js9-$(VERSION).min.js js9Msg.js \ + js9.css js9Helper.js js9Prefs-default.json \ + js9basics.html js9panzoom.html js9analysis.html js9multi.html \ + js9create.html js9preload.html js9bitpix.html \ + js9onchange.html js9rgb.html js9cat.html js9plugins.html \ + index.html js9Helper-default.cgi fitsy.js + +MFILES = Makefile Makefile.in conf.h conf.h.in config.guess config.sub \ + configure configure.ac install-sh js9helper.pc.in js9.in \ + saoconfig saoprefs.sed nnode mkhelper mkjs9 \ + js9Helper-default.cgi js9load README + +all: progs-$(USEHELPER) helper + +progs-yes: $(PROGS) + +progs-no: + +testall: $(TESTPROGS) + +All: all testall + +tpos: tpos.o + $(CC) $(LDFLAGS) tpos.o -o tpos $(LIBS) + +js9helper: js9helper.o + $(CC) $(LDFLAGS) js9helper.o -o js9helper $(LIBS) + +pngdisp: pngdisp.o + $(CC) $(LDFLAGS) pngdisp.o -o pngdisp $(LIBS) + +links: FORCE + @(rm -f js9.js js9.min.js; \ + ln -s js9-$(VERSION).js js9.js; \ + ln -s js9-$(VERSION).min.js js9.min.js;) + +prefs: FORCE + @(echo "copying default preferences to js9Prefs.json"; \ + cp -p js9Prefs-default.json js9Prefs.json;) + +saoprefs: FORCE + @(echo "editing js9Prefs for SAO installations ..."; \ + sed -f saoprefs.sed < js9Prefs.json > js9Prefs-sao.json) + +helper: FORCE + @(./mkhelper "$(HELPER)" \ + "$(CGIDIR)" "$(CGIURL)" "$(CGIXPATH)"; \ + if [ x"$(USEHELPER)" = x"yes" ]; then \ + ./mkjs9 "$(WEBDIR)"; \ + fi;) + +nohelper: FORCE + @(./mkhelper none; \ + ./mkjs9 "$(WEBDIR)") + +nodejshelper: FORCE + @(./mkhelper nodejs; \ + ./mkjs9 "$(WEBDIR)") + + +cgihelper: FORCE prefs + @(./mkhelper get "$(CGIDIR)" "$(CGIURL)" "$(CGIXPATH)"; \ + ./mkjs9 "$(WEBDIR)") + +js9: FORCE + @(if [ x"$(USEHELPER)" = x"yes" ]; then \ + ./mkjs9 "$(WEBDIR)"; \ + fi;) + +minify: FORCE + @minify js9-$(VERSION).js + +js9support: FORCE + @(echo "remaking js9support ..."; minify fitsy.js; \ + echo "css files in js9support.css: " > js9support.txt; \ + echo $(CSSFILES) >> js9support.txt; \ + cat $(CSSFILES) > js9support.css; \ + echo "js files in js9support.js: " >> js9support.txt; \ + echo $(JSFILES) >> js9support.txt; \ + cat $(JSFILES) > js9support.min.js; \ + X=`echo "$(JSFILES)" | sed 's/\.min//g'`; \ + cat $$X > js9support.js; \ + echo "plugin files in js9plugins.js: " >> js9support.txt; \ + echo $(PLUGINFILES) >> js9support.txt; \ + cat $(PLUGINFILES) > js9plugins.js;) + + +js9min: FORCE + @(echo "remaking js9.min.js ..."; touch js9-$(VERSION).js; minify js9-$(VERSION).js) + +refresh: js9support js9min + +jslint: FORCE + @(jslint js9.js; jslint fitsy.js) + +archive: FORCE + @jsarchive $(ARCFILES) $(SCRIPTS) $(SRCS) + +tar: FORCE + ($(RM) config.cache; \ + cd ..; \ + tar cf - $(DISTNAME) | gzip -9 -c > $(DISTNAME).tar.gz) + +install: install-binaries install-scripts install-web + +install-binaries: FORCE + @(if [ x$(USEHELPER) = xyes ]; then \ + echo "Installing programs ..."; \ + for i in $(LIB_INSTALL_DIR) $(INCLUDE_INSTALL_DIR) $(BIN_INSTALL_DIR) ; \ + do \ + if [ ! -d $$i ] ; then \ + echo "making directory $$i"; \ + mkdir -p $$i; \ + chmod 755 $$i; \ + else true; \ + fi; \ + done; \ + for i in $(PROGS) ; \ + do \ + if [ -f $$i.exe ] ; then \ + echo "installing $$i.exe" ; \ + $(INSTALL_PROGRAM) $$i.exe $(BIN_INSTALL_DIR)/$$i.exe ; \ + elif [ -f $$i ] ; then \ + echo "installing $$i" ; \ + $(INSTALL_PROGRAM) $$i $(BIN_INSTALL_DIR)/$$i ; \ + fi; \ + done; \ + else \ + echo "nothing to install for 'binaries' (no helper configured)"; \ + fi;) + +install-scripts: $(SCRIPTS) $(SCRIPTS2) + @(if [ x$(USEHELPER) = xyes ]; then \ + echo "Installing scripts ..."; \ + for i in $(BIN_INSTALL_DIR) ; \ + do \ + if [ ! -d $$i ] ; then \ + echo "making directory $$i"; \ + mkdir -p $$i; \ + chmod 755 $$i; \ + else true; \ + fi; \ + done; \ + for i in $(SCRIPTS) $(SCRIPTS2) ; \ + do \ + if [ -f $$i ] ; then \ + echo "installing $$i" ; \ + $(INSTALL_PROGRAM) $$i $(BIN_INSTALL_DIR)/$$i ; \ + fi; \ + done; \ + else \ + echo "nothing to install for 'scripts' (no helper configured)"; \ + fi;) + +install-web: install-webdirs install-webfiles + +install-webdirs: FORCE + @(echo "Installing web directories ..."; \ + for i in $(WEBDIRS) $(WEBHELP); do \ + if [ x$(WEBDIR) != x ]; then \ + mkdir -p $(WEBDIR); \ + if [ -d $$i ] ; then \ + echo "installing web dir: $$i" ; \ + tar cf - $$i | (cd $(WEBDIR); tar xf -); \ + fi; \ + fi; \ + done; \ + if [ x$(USEHELPER) = xyes ]; then \ + echo "Installing backend helper dirs ..."; \ + for i in $(BEDIRS); do \ + if [ -d $$i ] ; then \ + echo "installing backend dir: $$i" ; \ + tar cf - $$i | (cd $(WEBDIR); tar xf -); \ + fi; \ + done; \ + fi;) + +install-webfiles: FORCE + @(echo "Installing web files ..."; \ + if [ x$(WEBDIR) != x ]; then \ + mkdir -p $(WEBDIR); \ + if [ -f $(WEBDIR)/js9Prefs.json ] ; then \ + echo "moving aside old js9Prefs.json" ; \ + mv $(WEBDIR)/js9Prefs.json{,-old}; \ + fi; \ + fi; \ + for i in $(PREFFILES) $(WEBFILES) js9*.html ; do\ + if [ x$(WEBDIR) != x ]; then \ + if [ -d $$i ] ; then \ + echo "installing web directory: $$i" ; \ + elif [ -f $$i ] ; then \ + echo "installing web file: $$i" ; \ + fi; \ + tar cf - $$i | (cd $(WEBDIR); tar xf -); \ + fi; \ + done; \ + if [ -d "$(CGIDIR)" ]; then \ + for i in $(CGIFILES) ; do\ + if [ -f $$i ]; then \ + if [ -d $$i ] ; then \ + echo "installing cgi directory: $$i" ; \ + elif [ -f $$i ] ; then \ + echo "installing cgi file: $$i" ; \ + fi; \ + tar cf - $$i | (cd $(CGIDIR); tar xf -); \ + else \ + echo "skipping cgi install: $$i"; \ + fi; \ + done; \ + else \ + echo "nothing to install in cgi (no helper configured)"; \ + fi;) + +install-webdata: FORCE + @(for i in $(WEBDATA) ; do\ + if [ x$(WEBDIR) != x ]; then \ + mkdir -p $(WEBDIR); \ + if [ -d $$i ] ; then \ + echo "installing $$i" ; \ + tar cf - $$i | (cd $(WEBDIR); tar xf -); \ + fi; \ + fi; \ + done;) + +install-sao: saoprefs + @(if [ -d "$(SAODIR)" ]; then \ + for i in $(SAOFILES) ; \ + do \ + if [ -f $$i ] ; then \ + echo "installing file: $$i" ; \ + $(CP) $$i $(SAODIR)/.; \ + fi; \ + done; \ + fi; \ + echo "installing SAO js9Prefs.json"; \ + $(CP) js9Prefs-sao.json $(WEBDIR)/js9Prefs.json; \ + if [ -d js9debugextras ]; then \ + echo "installing js9debugextras"; \ + tar cf - js9debugextras | (cd $(WEBDIR); tar xf -); \ + fi) + +install-smartx: FORCE + @(echo "install smartx"; cd smartx; make install); + +release: refresh js9support links prefs + (mkdir -p $(DISTDIR)/$(DISTNAME); \ + tar cf - $(WEBFILES) $(WEBDIRS) $(BEDIRS) $(WEBHELP) js9*.html \ + $(SRCS) $(INCLUDES) $(SCRIPTS) $(MFILES) | \ + (cd $(DISTDIR)/$(DISTNAME); tar xf -); \ + cd $(DISTDIR) ; \ + tar cf - $(DISTNAME) | gzip -c > $(DISTNAME).tar.gz; \ + rm -rf $(DISTNAME)) + +release-data: FORCE + tar cf - $(WEBDATA) | gzip -c > $(DISTDIR)/$(DDISTNAME).tar.gz; + +spell: FORCE + @(for f in index.html $(WEBHELP)/*.html; do \ + echo "spellcheck $$f ..."; \ + aspell -c $$f; \ + done) + +clean: FORCE + $(RM) *.a *.so *.dylib *.o *.exe core errs *pure* .nfs* \ + foo* *~ \#* TAGS *.E a.out errors \ + $(PROGS) $(CGIFILES) $(TESTPROGS) \ + gmon.out *.pg *.bak *js9Prefs.json-orig \ + config.info config.log ltest \ + js/*~ params/*~ \ + doc/*~ notes/*~ test/*~ help/*~ help/*.bak \ + analysis-wrappers/*~ analysis-plugins/*~ \ + plugins/*~ plugins/*/*~ \ + astroem/*~ astroem/*.o astroem/zee.js/*.o + $(RM) -rf autom4te.cache a.out.dSYM + +distclean: clean + $(RM) Makefile config.status config.cache config.log \ + $(PREFFILES) + +maintainer-clean:: clean + $(RM) config.status config.cache config.log \ + $(PREFFILES) + +Makefile: Makefile.in + $(SHELL) config.status + +make: Makefile.in + $(SHELL) config.status + +depend: FORCE + makedepend -- $(DEPEND_SWITCHES) -- $(SRCS) + +tpos.o: tpos.c $(INCL) + $(CC) -c $(CC_SWITCHES) tpos.c + +js9helper.o: js9helper.c $(INCL) + $(CC) -c $(CC_SWITCHES) js9helper.c + +pngdisp.o: pngdisp.c $(INCL) + $(CC) -c $(CC_SWITCHES) pngdisp.c + +configure: configure.ac + autoconf + +errcheck: FORCE + @-egrep 'error|warning' foo | egrep -v "^lex.*but not used" + +FORCE: + +# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/README b/README new file mode 100644 index 00000000..4ff12ff8 --- /dev/null +++ b/README @@ -0,0 +1,43 @@ +JS9 is our Web-based implementation of DS9, the de facto standard image display +for astronomy. With JS9, you can: + + - display URL-based FITS images and binary tables + - drag and drop FITS images and binary tables + - change the colormap and scale + - manipulate the contrast/bias with the mouse + - display pixel values and WCS position information + - create and manipulate geometric regions of interest + - add your own extensions using plugins and the public api + - perform local (browser-based) data analysis via plugins + - perform remote (server-side) data analysis via node.js or CGI + - display RGB composite images + - control JS9 from the command line + - print images + +The JS9 Website contains on-line documentation, demos, and downloads: + + http://js9.si.edu + +JS9 can change how we think about image display and analysis, moving +beyond the Desktop into the Web. You can simply drag and drop a FITS +image from your computer onto this JS9 display. All of basic JS9/DS9 +functionality is immediately available: zoom, pan, colormaps, scaling, +regions, WCS, etc. + +You can extend JS9 using the plugin facility in combination with the +JS9 public API. For example, you can perform browser-based analysis on +the displayed image. On the JS9 Website, click the Plugins tab, create +a region, and move it around ... + +In addition, data files loaded from the server support server-side +analysis (using the original data files on the back-end server). +Server-side analysis can be run, for example, in response to region +changes, with the results displayed back in your browser. On the JS9 +Website, click the Analysis tab, choose a task, create a region, and +move it around ... + +For installation instructions, see help/install.html. + +If you have questions, please contact us at: saord@cfa.harvard.edu. + + Eric Mandel diff --git a/acknowledge.html b/acknowledge.html new file mode 100644 index 00000000..58434aa2 --- /dev/null +++ b/acknowledge.html @@ -0,0 +1,10 @@ + + + +Development of JS9 at the +Harvard-Smithsonian Center for Astrophysics +is supported by Smithsonian Institution +and the Chandra X-ray Science Center. + + + diff --git a/analysis-plugins/fits2png.json b/analysis-plugins/fits2png.json new file mode 100644 index 00000000..9c1b6fc5 --- /dev/null +++ b/analysis-plugins/fits2png.json @@ -0,0 +1,8 @@ +[ + {"name" : "fits2png", + "title" : "Convert FITS to PNG", + "files" : "*", + "action" : "js9Xeq fits2png -js9 -odir ./png", + "hidden" : true, + "rtype" : "text"} +] \ No newline at end of file diff --git a/analysis-plugins/js9Analysis-fits.json b/analysis-plugins/js9Analysis-fits.json new file mode 100644 index 00000000..1e53d209 --- /dev/null +++ b/analysis-plugins/js9Analysis-fits.json @@ -0,0 +1,13 @@ +[ + {"name" : "fitshead", + "title" : "FITS Header(s)", + "files" : "fits", + "action" : "js9Xeq fitshead $filename", + "rtype" : "text"}, + {"name" : "macros", + "title" : "Display Macros", + "files" : "*", + "action" : "js9Xeq macros $png $id $foo $sregions $bregions", + "hidden" : true, + "rtype" : "text"} +] diff --git a/analysis-plugins/js9Analysis-funtools.json b/analysis-plugins/js9Analysis-funtools.json new file mode 100644 index 00000000..d785ccc8 --- /dev/null +++ b/analysis-plugins/js9Analysis-funtools.json @@ -0,0 +1,23 @@ +[ + {"name" : "counts", + "title" : "Counts in Regions", + "files" : "fits", + "action" : "js9Xeq counts $filename $sregions $bregions", + "rtype" : "text"}, + {"name" : "radialprofile", + "title" : "Radial Profile", + "files" : "fits", + "action" : "js9Xeq radialplot $filename $sregions $bregions", + "rtype" : "plot"}, + {"name" : "energyplot", + "title" : "Energy Spectrum", + "files" : "fits", + "action" : "js9Xeq histplot $filename[$regions] false false pi 0", + "rtype" : "plot"}, + {"name" : "histplot", + "title" : "Histogram Plot", + "files" : "fits", + "purl" : "./params/histplot.html", + "action" : "js9Xeq histplot $filename[$regions] $norm $bwidth $column $bins", + "rtype" : "plot"} +] diff --git a/analysis-wrappers/js9Xeq b/analysis-wrappers/js9Xeq new file mode 100755 index 00000000..d9f42dd2 --- /dev/null +++ b/analysis-wrappers/js9Xeq @@ -0,0 +1,126 @@ +#!/bin/sh +# set -x + +# make sure we have minimum arg count +if [ $# -lt 1 ]; then + echo "$0 [cmd] [args ...]" + exit 1 +fi + +# on entry, the following JS9 environment variables will be available: +# JS9_HOST host ip of client +# JS9_ID id (from js9 div) of client + +# if we are being called via CGI, send stderr to stdout +if [ x"$QUERY_STRING" != x ]; then + exec 2>&1 +fi + +# error handler: send to stderr(which will go to stdout for CGI) +error() { + echo "ERROR: $1" >&2 + exit 1 +} + +# process standard arguments +CMD="$1"; shift; +case $CMD in +counts) + if [ $# -eq 1 ]; then + funcnts "$1" "$2" + else + funcnts "$1" "$2" "$3" + fi + exit 0 + ;; + +fits2png) + fits2png $* + exit 0 + ;; + +fitshead) + funhead -a "$1" + exit 0 + ;; + +hist) + if [ $# -lt 4 ]; then + error "funhist filename norm width [column] [bin] [$#]" + fi + ARGS="" + FILE="$1"; shift + NORM="$1"; shift; + if [ $NORM = "true" ]; then + ARGS="$ARGS -n" + fi + WIDTH=$1; shift; + if [ $WIDTH = "true" ]; then + ARGS="$ARGS -w" + fi + if [ $# -eq 1 ]; then + funhist $ARGS "$FILE" "$1" + else + funhist $ARGS "$FILE" "$1" "$2" + fi + exit 0 + ;; + +radialplot) + if [ $# = 0 ]; then + error "funcnts filename [source] [bkgd] [$#]" + exit 1 + fi + if [ $# -eq 1 ]; then + funcnts -rG "$1" "$2" | funcnts2flot -title "$TITLE" -file "$1" + else + funcnts -rG "$1" "$2" "$3" | funcnts2flot -title "$TITLE" -file "$1" + fi + exit 0 + ;; + +histplot) + if [ $# -lt 4 ]; then + error "funhist filename norm width [column] [bin] [$#]" + exit 1 + fi + ARGS="" + FILE="$1"; shift; + NORM="$1"; shift; + if [ $NORM = "true" ]; then + ARGS="$ARGS -n" + fi + WIDTH=$1; shift + if [ $WIDTH = "true" ]; then + if [ "x$2" = x0 ]; then + error "please don't use a bin width of 0" + fi + ARGS="$ARGS -w" + fi + TITLE="`echo "$FILE" | tr [a-z] [A-Z]` Plot" + if [ $# -eq 1 ]; then + funhist $ARGS "$FILE" "$1" | + funhist2flot -title "$TITLE" -file "$FILE" + else + funhist $ARGS "$FILE" "$1" "$2" | + funhist2flot -title "$TITLE" -file "$FILE" + fi + exit 0 + ;; + +macros) + echo " + png: [$1] + id: [$2] + foo: [$3] (not expanded) + sregions: [$4] + bregions: [$5]" + exit 0 + ;; + +*) + error "unknown function: $CMD" + exit 1 + ;; +esac + diff --git a/astroem/astroem.bc b/astroem/astroem.bc new file mode 100644 index 00000000..db040607 Binary files /dev/null and b/astroem/astroem.bc differ diff --git a/astroem/astroem.js b/astroem/astroem.js new file mode 100644 index 00000000..5cb6b583 --- /dev/null +++ b/astroem/astroem.js @@ -0,0 +1,7937 @@ + +// astroem.js: astronomy utilities compiled to js + +var Astroem = (function() { + + +var Module = { + 'noExitRuntime': true +}; + + +// The Module object: Our interface to the outside world. We import +// and export values on it, and do the work to get that through +// closure compiler if necessary. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to do an eval in order to handle the closure compiler +// case, where this code here is minified but Module was defined +// elsewhere (e.g. case 4 above). We also need to check if Module +// already exists (e.g. case 3 above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module; +if (!Module) Module = (typeof Module !== 'undefined' ? Module : null) || {}; + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. +var moduleOverrides = {}; +for (var key in Module) { + if (Module.hasOwnProperty(key)) { + moduleOverrides[key] = Module[key]; + } +} + +// The environment setup code below is customized to use Module. +// *** Environment setup code *** +var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function'; +var ENVIRONMENT_IS_WEB = typeof window === 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + +if (ENVIRONMENT_IS_NODE) { + // Expose functionality in the same simple way that the shells work + // Note that we pollute the global namespace here, otherwise we break in node + if (!Module['print']) Module['print'] = function print(x) { + process['stdout'].write(x + '\n'); + }; + if (!Module['printErr']) Module['printErr'] = function printErr(x) { + process['stderr'].write(x + '\n'); + }; + + var nodeFS = require('fs'); + var nodePath = require('path'); + + Module['read'] = function read(filename, binary) { + filename = nodePath['normalize'](filename); + var ret = nodeFS['readFileSync'](filename); + // The path is absolute if the normalized version is the same as the resolved. + if (!ret && filename != nodePath['resolve'](filename)) { + filename = path.join(__dirname, '..', 'src', filename); + ret = nodeFS['readFileSync'](filename); + } + if (ret && !binary) ret = ret.toString(); + return ret; + }; + + Module['readBinary'] = function readBinary(filename) { return Module['read'](filename, true) }; + + Module['load'] = function load(f) { + globalEval(read(f)); + }; + + Module['arguments'] = process['argv'].slice(2); + + module['exports'] = Module; +} +else if (ENVIRONMENT_IS_SHELL) { + if (!Module['print']) Module['print'] = print; + if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm + + if (typeof read != 'undefined') { + Module['read'] = read; + } else { + Module['read'] = function read() { throw 'no read() available (jsc?)' }; + } + + Module['readBinary'] = function readBinary(f) { + return read(f, 'binary'); + }; + + if (typeof scriptArgs != 'undefined') { + Module['arguments'] = scriptArgs; + } else if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + + this['Module'] = Module; + + eval("if (typeof gc === 'function' && gc.toString().indexOf('[native code]') > 0) var gc = undefined"); // wipe out the SpiderMonkey shell 'gc' function, which can confuse closure (uses it as a minified name, and it is then initted to a non-falsey value unexpectedly) +} +else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + Module['read'] = function read(url) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + }; + + if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + + if (typeof console !== 'undefined') { + if (!Module['print']) Module['print'] = function print(x) { + console.log(x); + }; + if (!Module['printErr']) Module['printErr'] = function printErr(x) { + console.log(x); + }; + } else { + // Probably a worker, and without console.log. We can do very little here... + var TRY_USE_DUMP = false; + if (!Module['print']) Module['print'] = (TRY_USE_DUMP && (typeof(dump) !== "undefined") ? (function(x) { + dump(x); + }) : (function(x) { + // self.postMessage(x); // enable this if you want stdout to be sent as messages + })); + } + + if (ENVIRONMENT_IS_WEB) { + window['Module'] = Module; + } else { + Module['load'] = importScripts; + } +} +else { + // Unreachable because SHELL is dependant on the others + throw 'Unknown runtime environment. Where are we?'; +} + +function globalEval(x) { + eval.call(null, x); +} +if (!Module['load'] == 'undefined' && Module['read']) { + Module['load'] = function load(f) { + globalEval(Module['read'](f)); + }; +} +if (!Module['print']) { + Module['print'] = function(){}; +} +if (!Module['printErr']) { + Module['printErr'] = Module['print']; +} +if (!Module['arguments']) { + Module['arguments'] = []; +} +// *** Environment setup code *** + +// Closure helpers +Module.print = Module['print']; +Module.printErr = Module['printErr']; + +// Callbacks +Module['preRun'] = []; +Module['postRun'] = []; + +// Merge back in the overrides +for (var key in moduleOverrides) { + if (moduleOverrides.hasOwnProperty(key)) { + Module[key] = moduleOverrides[key]; + } +} + + + +// === Auto-generated preamble library stuff === + +//======================================== +// Runtime code shared with compiler +//======================================== + +var Runtime = { + stackSave: function () { + return STACKTOP; + }, + stackRestore: function (stackTop) { + STACKTOP = stackTop; + }, + forceAlign: function (target, quantum) { + quantum = quantum || 4; + if (quantum == 1) return target; + if (isNumber(target) && isNumber(quantum)) { + return Math.ceil(target/quantum)*quantum; + } else if (isNumber(quantum) && isPowerOfTwo(quantum)) { + return '(((' +target + ')+' + (quantum-1) + ')&' + -quantum + ')'; + } + return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum; + }, + isNumberType: function (type) { + return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES; + }, + isPointerType: function isPointerType(type) { + return type[type.length-1] == '*'; +}, + isStructType: function isStructType(type) { + if (isPointerType(type)) return false; + if (isArrayType(type)) return true; + if (/?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types + // See comment in isStructPointerType() + return type[0] == '%'; +}, + INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0}, + FLOAT_TYPES: {"float":0,"double":0}, + or64: function (x, y) { + var l = (x | 0) | (y | 0); + var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + and64: function (x, y) { + var l = (x | 0) & (y | 0); + var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + xor64: function (x, y) { + var l = (x | 0) ^ (y | 0); + var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + getNativeTypeSize: function (type) { + switch (type) { + case 'i1': case 'i8': return 1; + case 'i16': return 2; + case 'i32': return 4; + case 'i64': return 8; + case 'float': return 4; + case 'double': return 8; + default: { + if (type[type.length-1] === '*') { + return Runtime.QUANTUM_SIZE; // A pointer + } else if (type[0] === 'i') { + var bits = parseInt(type.substr(1)); + assert(bits % 8 === 0); + return bits/8; + } else { + return 0; + } + } + } + }, + getNativeFieldSize: function (type) { + return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE); + }, + dedup: function dedup(items, ident) { + var seen = {}; + if (ident) { + return items.filter(function(item) { + if (seen[item[ident]]) return false; + seen[item[ident]] = true; + return true; + }); + } else { + return items.filter(function(item) { + if (seen[item]) return false; + seen[item] = true; + return true; + }); + } +}, + set: function set() { + var args = typeof arguments[0] === 'object' ? arguments[0] : arguments; + var ret = {}; + for (var i = 0; i < args.length; i++) { + ret[args[i]] = 0; + } + return ret; +}, + STACK_ALIGN: 8, + getAlignSize: function (type, size, vararg) { + // we align i64s and doubles on 64-bit boundaries, unlike x86 + if (!vararg && (type == 'i64' || type == 'double')) return 8; + if (!type) return Math.min(size, 8); // align structures internally to 64 bits + return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE); + }, + calculateStructAlignment: function calculateStructAlignment(type) { + type.flatSize = 0; + type.alignSize = 0; + var diffs = []; + var prev = -1; + var index = 0; + type.flatIndexes = type.fields.map(function(field) { + index++; + var size, alignSize; + if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) { + size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s. + alignSize = Runtime.getAlignSize(field, size); + } else if (Runtime.isStructType(field)) { + if (field[1] === '0') { + // this is [0 x something]. When inside another structure like here, it must be at the end, + // and it adds no size + // XXX this happens in java-nbody for example... assert(index === type.fields.length, 'zero-length in the middle!'); + size = 0; + if (Types.types[field]) { + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } else { + alignSize = type.alignSize || QUANTUM_SIZE; + } + } else { + size = Types.types[field].flatSize; + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } + } else if (field[0] == 'b') { + // bN, large number field, like a [N x i8] + size = field.substr(1)|0; + alignSize = 1; + } else if (field[0] === '<') { + // vector type + size = alignSize = Types.types[field].flatSize; // fully aligned + } else if (field[0] === 'i') { + // illegal integer field, that could not be legalized because it is an internal structure field + // it is ok to have such fields, if we just use them as markers of field size and nothing more complex + size = alignSize = parseInt(field.substr(1))/8; + assert(size % 1 === 0, 'cannot handle non-byte-size field ' + field); + } else { + assert(false, 'invalid type for calculateStructAlignment'); + } + if (type.packed) alignSize = 1; + type.alignSize = Math.max(type.alignSize, alignSize); + var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory + type.flatSize = curr + size; + if (prev >= 0) { + diffs.push(curr-prev); + } + prev = curr; + return curr; + }); + if (type.name_ && type.name_[0] === '[') { + // arrays have 2 elements, so we get the proper difference. then we scale here. that way we avoid + // allocating a potentially huge array for [999999 x i8] etc. + type.flatSize = parseInt(type.name_.substr(1))*type.flatSize/2; + } + type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize); + if (diffs.length == 0) { + type.flatFactor = type.flatSize; + } else if (Runtime.dedup(diffs).length == 1) { + type.flatFactor = diffs[0]; + } + type.needsFlattening = (type.flatFactor != 1); + return type.flatIndexes; + }, + generateStructInfo: function (struct, typeName, offset) { + var type, alignment; + if (typeName) { + offset = offset || 0; + type = (typeof Types === 'undefined' ? Runtime.typeInfo : Types.types)[typeName]; + if (!type) return null; + if (type.fields.length != struct.length) { + printErr('Number of named fields must match the type for ' + typeName + ': possibly duplicate struct names. Cannot return structInfo'); + return null; + } + alignment = type.flatIndexes; + } else { + var type = { fields: struct.map(function(item) { return item[0] }) }; + alignment = Runtime.calculateStructAlignment(type); + } + var ret = { + __size__: type.flatSize + }; + if (typeName) { + struct.forEach(function(item, i) { + if (typeof item === 'string') { + ret[item] = alignment[i] + offset; + } else { + // embedded struct + var key; + for (var k in item) key = k; + ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]); + } + }); + } else { + struct.forEach(function(item, i) { + ret[item[1]] = alignment[i]; + }); + } + return ret; + }, + dynCall: function (sig, ptr, args) { + if (args && args.length) { + if (!args.splice) args = Array.prototype.slice.call(args); + args.splice(0, 0, ptr); + return Module['dynCall_' + sig].apply(null, args); + } else { + return Module['dynCall_' + sig].call(null, ptr); + } + }, + functionPointers: [], + addFunction: function (func) { + for (var i = 0; i < Runtime.functionPointers.length; i++) { + if (!Runtime.functionPointers[i]) { + Runtime.functionPointers[i] = func; + return 2*(1 + i); + } + } + throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; + }, + removeFunction: function (index) { + Runtime.functionPointers[(index-2)/2] = null; + }, + getAsmConst: function (code, numArgs) { + // code is a constant string on the heap, so we can cache these + if (!Runtime.asmConstCache) Runtime.asmConstCache = {}; + var func = Runtime.asmConstCache[code]; + if (func) return func; + var args = []; + for (var i = 0; i < numArgs; i++) { + args.push(String.fromCharCode(36) + i); // $0, $1 etc + } + var source = Pointer_stringify(code); + if (source[0] === '"') { + // tolerate EM_ASM("..code..") even though EM_ASM(..code..) is correct + if (source.indexOf('"', 1) === source.length-1) { + source = source.substr(1, source.length-2); + } else { + // something invalid happened, e.g. EM_ASM("..code($0)..", input) + abort('invalid EM_ASM input |' + source + '|. Please use EM_ASM(..code..) (no quotes) or EM_ASM({ ..code($0).. }, input) (to input values)'); + } + } + try { + var evalled = eval('(function(' + args.join(',') + '){ ' + source + ' })'); // new Function does not allow upvars in node + } catch(e) { + Module.printErr('error in executing inline EM_ASM code: ' + e + ' on: \n\n' + source + '\n\nwith args |' + args + '| (make sure to use the right one out of EM_ASM, EM_ASM_ARGS, etc.)'); + throw e; + } + return Runtime.asmConstCache[code] = evalled; + }, + warnOnce: function (text) { + if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; + if (!Runtime.warnOnce.shown[text]) { + Runtime.warnOnce.shown[text] = 1; + Module.printErr(text); + } + }, + funcWrappers: {}, + getFuncWrapper: function (func, sig) { + assert(sig); + if (!Runtime.funcWrappers[func]) { + Runtime.funcWrappers[func] = function dynCall_wrapper() { + return Runtime.dynCall(sig, func, arguments); + }; + } + return Runtime.funcWrappers[func]; + }, + UTF8Processor: function () { + var buffer = []; + var needed = 0; + this.processCChar = function (code) { + code = code & 0xFF; + + if (buffer.length == 0) { + if ((code & 0x80) == 0x00) { // 0xxxxxxx + return String.fromCharCode(code); + } + buffer.push(code); + if ((code & 0xE0) == 0xC0) { // 110xxxxx + needed = 1; + } else if ((code & 0xF0) == 0xE0) { // 1110xxxx + needed = 2; + } else { // 11110xxx + needed = 3; + } + return ''; + } + + if (needed) { + buffer.push(code); + needed--; + if (needed > 0) return ''; + } + + var c1 = buffer[0]; + var c2 = buffer[1]; + var c3 = buffer[2]; + var c4 = buffer[3]; + var ret; + if (buffer.length == 2) { + ret = String.fromCharCode(((c1 & 0x1F) << 6) | (c2 & 0x3F)); + } else if (buffer.length == 3) { + ret = String.fromCharCode(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); + } else { + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + var codePoint = ((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) | + ((c3 & 0x3F) << 6) | (c4 & 0x3F); + ret = String.fromCharCode( + Math.floor((codePoint - 0x10000) / 0x400) + 0xD800, + (codePoint - 0x10000) % 0x400 + 0xDC00); + } + buffer.length = 0; + return ret; + } + this.processJSString = function processJSString(string) { + /* TODO: use TextEncoder when present, + var encoder = new TextEncoder(); + encoder['encoding'] = "utf-8"; + var utf8Array = encoder['encode'](aMsg.data); + */ + string = unescape(encodeURIComponent(string)); + var ret = []; + for (var i = 0; i < string.length; i++) { + ret.push(string.charCodeAt(i)); + } + return ret; + } + }, + getCompilerSetting: function (name) { + throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work'; + }, + stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = (((STACKTOP)+7)&-8); return ret; }, + staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = (((STATICTOP)+7)&-8); return ret; }, + dynamicAlloc: function (size) { var ret = DYNAMICTOP;DYNAMICTOP = (DYNAMICTOP + size)|0;DYNAMICTOP = (((DYNAMICTOP)+7)&-8); if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();; return ret; }, + alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 8))*(quantum ? quantum : 8); return ret; }, + makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+((low>>>0)))+((+((high>>>0)))*(+4294967296))) : ((+((low>>>0)))+((+((high|0)))*(+4294967296)))); return ret; }, + GLOBAL_BASE: 8, + QUANTUM_SIZE: 4, + __dummy__: 0 +} + + +Module['Runtime'] = Runtime; + + + + + + + + + +//======================================== +// Runtime essentials +//======================================== + +var __THREW__ = 0; // Used in checking for thrown exceptions. + +var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort() +var EXITSTATUS = 0; + +var undef = 0; +// tempInt is used for 32-bit signed values or smaller. tempBigInt is used +// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt +var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD, tempDouble, tempFloat; +var tempI64, tempI64b; +var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9; + +function assert(condition, text) { + if (!condition) { + abort('Assertion failed: ' + text); + } +} + +var globalScope = this; + +// C calling interface. A convenient way to call C functions (in C files, or +// defined with extern "C"). +// +// Note: LLVM optimizations can inline and remove functions, after which you will not be +// able to call them. Closure can also do so. To avoid that, add your function to +// the exports using something like +// +// -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]' +// +// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C") +// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and +// 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit). +// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType, +// except that 'array' is not possible (there is no way for us to know the length of the array) +// @param args An array of the arguments to the function, as native JS values (as in returnType) +// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack). +// @return The return value, as a native JS value (as in returnType) +function ccall(ident, returnType, argTypes, args) { + return ccallFunc(getCFunc(ident), returnType, argTypes, args); +} +Module["ccall"] = ccall; + +// Returns the C function with a specified identifier (for C++, you need to do manual name mangling) +function getCFunc(ident) { + try { + var func = Module['_' + ident]; // closure exported function + if (!func) func = eval('_' + ident); // explicit lookup + } catch(e) { + } + assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)'); + return func; +} + +// Internal function that does a C call using a function, not an identifier +function ccallFunc(func, returnType, argTypes, args) { + var stack = 0; + function toC(value, type) { + if (type == 'string') { + if (value === null || value === undefined || value === 0) return 0; // null string + value = intArrayFromString(value); + type = 'array'; + } + if (type == 'array') { + if (!stack) stack = Runtime.stackSave(); + var ret = Runtime.stackAlloc(value.length); + writeArrayToMemory(value, ret); + return ret; + } + return value; + } + function fromC(value, type) { + if (type == 'string') { + return Pointer_stringify(value); + } + assert(type != 'array'); + return value; + } + var i = 0; + var cArgs = args ? args.map(function(arg) { + return toC(arg, argTypes[i++]); + }) : []; + var ret = fromC(func.apply(null, cArgs), returnType); + if (stack) Runtime.stackRestore(stack); + return ret; +} + +// Returns a native JS wrapper for a C function. This is similar to ccall, but +// returns a function you can call repeatedly in a normal way. For example: +// +// var my_function = cwrap('my_c_function', 'number', ['number', 'number']); +// alert(my_function(5, 22)); +// alert(my_function(99, 12)); +// +function cwrap(ident, returnType, argTypes) { + var func = getCFunc(ident); + return function() { + return ccallFunc(func, returnType, argTypes, Array.prototype.slice.call(arguments)); + } +} +Module["cwrap"] = cwrap; + +// Sets a value in memory in a dynamic way at run-time. Uses the +// type data. This is the same as makeSetValue, except that +// makeSetValue is done at compile-time and generates the needed +// code then, whereas this function picks the right code at +// run-time. +// Note that setValue and getValue only do *aligned* writes and reads! +// Note that ccall uses JS types as for defining types, while setValue and +// getValue need LLVM types ('i8', 'i32') - this is a lower-level operation +function setValue(ptr, value, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': HEAP8[(ptr)]=value; break; + case 'i8': HEAP8[(ptr)]=value; break; + case 'i16': HEAP16[((ptr)>>1)]=value; break; + case 'i32': HEAP32[((ptr)>>2)]=value; break; + case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= (+1) ? (tempDouble > (+0) ? ((Math_min((+(Math_floor((tempDouble)/(+4294967296)))), (+4294967295)))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/(+4294967296))))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break; + case 'float': HEAPF32[((ptr)>>2)]=value; break; + case 'double': HEAPF64[((ptr)>>3)]=value; break; + default: abort('invalid type for setValue: ' + type); + } +} +Module['setValue'] = setValue; + +// Parallel to setValue. +function getValue(ptr, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': return HEAP8[(ptr)]; + case 'i8': return HEAP8[(ptr)]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': return HEAP32[((ptr)>>2)]; + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + default: abort('invalid type for setValue: ' + type); + } + return null; +} +Module['getValue'] = getValue; + +var ALLOC_NORMAL = 0; // Tries to use _malloc() +var ALLOC_STACK = 1; // Lives for the duration of the current function call +var ALLOC_STATIC = 2; // Cannot be freed +var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk +var ALLOC_NONE = 4; // Do not allocate +Module['ALLOC_NORMAL'] = ALLOC_NORMAL; +Module['ALLOC_STACK'] = ALLOC_STACK; +Module['ALLOC_STATIC'] = ALLOC_STATIC; +Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC; +Module['ALLOC_NONE'] = ALLOC_NONE; + +// allocate(): This is for internal use. You can use it yourself as well, but the interface +// is a little tricky (see docs right below). The reason is that it is optimized +// for multiple syntaxes to save space in generated code. So you should +// normally not use allocate(), and instead allocate memory using _malloc(), +// initialize it with setValue(), and so forth. +// @slab: An array of data, or a number. If a number, then the size of the block to allocate, +// in *bytes* (note that this is sometimes confusing: the next parameter does not +// affect this!) +// @types: Either an array of types, one for each byte (or 0 if no type at that position), +// or a single type which is used for the entire block. This only matters if there +// is initial data - if @slab is a number, then this does not matter at all and is +// ignored. +// @allocator: How to allocate memory, see ALLOC_* +function allocate(slab, types, allocator, ptr) { + var zeroinit, size; + if (typeof slab === 'number') { + zeroinit = true; + size = slab; + } else { + zeroinit = false; + size = slab.length; + } + + var singleType = typeof types === 'string' ? types : null; + + var ret; + if (allocator == ALLOC_NONE) { + ret = ptr; + } else { + ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); + } + + if (zeroinit) { + var ptr = ret, stop; + assert((ret & 3) == 0); + stop = ret + (size & ~3); + for (; ptr < stop; ptr += 4) { + HEAP32[((ptr)>>2)]=0; + } + stop = ret + size; + while (ptr < stop) { + HEAP8[((ptr++)|0)]=0; + } + return ret; + } + + if (singleType === 'i8') { + if (slab.subarray || slab.slice) { + HEAPU8.set(slab, ret); + } else { + HEAPU8.set(new Uint8Array(slab), ret); + } + return ret; + } + + var i = 0, type, typeSize, previousType; + while (i < size) { + var curr = slab[i]; + + if (typeof curr === 'function') { + curr = Runtime.getFunctionIndex(curr); + } + + type = singleType || types[i]; + if (type === 0) { + i++; + continue; + } + + if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later + + setValue(ret+i, curr, type); + + // no need to look up size unless type changes, so cache it + if (previousType !== type) { + typeSize = Runtime.getNativeTypeSize(type); + previousType = type; + } + i += typeSize; + } + + return ret; +} +Module['allocate'] = allocate; + +function Pointer_stringify(ptr, /* optional */ length) { + // TODO: use TextDecoder + // Find the length, and check for UTF while doing so + var hasUtf = false; + var t; + var i = 0; + while (1) { + t = HEAPU8[(((ptr)+(i))|0)]; + if (t >= 128) hasUtf = true; + else if (t == 0 && !length) break; + i++; + if (length && i == length) break; + } + if (!length) length = i; + + var ret = ''; + + if (!hasUtf) { + var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack + var curr; + while (length > 0) { + curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); + ret = ret ? ret + curr : curr; + ptr += MAX_CHUNK; + length -= MAX_CHUNK; + } + return ret; + } + + var utf8 = new Runtime.UTF8Processor(); + for (i = 0; i < length; i++) { + t = HEAPU8[(((ptr)+(i))|0)]; + ret += utf8.processCChar(t); + } + return ret; +} +Module['Pointer_stringify'] = Pointer_stringify; + +// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns +// a copy of that string as a Javascript String object. +function UTF16ToString(ptr) { + var i = 0; + + var str = ''; + while (1) { + var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; + if (codeUnit == 0) + return str; + ++i; + // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through. + str += String.fromCharCode(codeUnit); + } +} +Module['UTF16ToString'] = UTF16ToString; + +// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', +// null-terminated and encoded in UTF16LE form. The copy will require at most (str.length*2+1)*2 bytes of space in the HEAP. +function stringToUTF16(str, outPtr) { + for(var i = 0; i < str.length; ++i) { + // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. + var codeUnit = str.charCodeAt(i); // possibly a lead surrogate + HEAP16[(((outPtr)+(i*2))>>1)]=codeUnit; + } + // Null-terminate the pointer to the HEAP. + HEAP16[(((outPtr)+(str.length*2))>>1)]=0; +} +Module['stringToUTF16'] = stringToUTF16; + +// Given a pointer 'ptr' to a null-terminated UTF32LE-encoded string in the emscripten HEAP, returns +// a copy of that string as a Javascript String object. +function UTF32ToString(ptr) { + var i = 0; + + var str = ''; + while (1) { + var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; + if (utf32 == 0) + return str; + ++i; + // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. + if (utf32 >= 0x10000) { + var ch = utf32 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } else { + str += String.fromCharCode(utf32); + } + } +} +Module['UTF32ToString'] = UTF32ToString; + +// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', +// null-terminated and encoded in UTF32LE form. The copy will require at most (str.length+1)*4 bytes of space in the HEAP, +// but can use less, since str.length does not return the number of characters in the string, but the number of UTF-16 code units in the string. +function stringToUTF32(str, outPtr) { + var iChar = 0; + for(var iCodeUnit = 0; iCodeUnit < str.length; ++iCodeUnit) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. + var codeUnit = str.charCodeAt(iCodeUnit); // possibly a lead surrogate + if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { + var trailSurrogate = str.charCodeAt(++iCodeUnit); + codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); + } + HEAP32[(((outPtr)+(iChar*4))>>2)]=codeUnit; + ++iChar; + } + // Null-terminate the pointer to the HEAP. + HEAP32[(((outPtr)+(iChar*4))>>2)]=0; +} +Module['stringToUTF32'] = stringToUTF32; + +function demangle(func) { + var i = 3; + // params, etc. + var basicTypes = { + 'v': 'void', + 'b': 'bool', + 'c': 'char', + 's': 'short', + 'i': 'int', + 'l': 'long', + 'f': 'float', + 'd': 'double', + 'w': 'wchar_t', + 'a': 'signed char', + 'h': 'unsigned char', + 't': 'unsigned short', + 'j': 'unsigned int', + 'm': 'unsigned long', + 'x': 'long long', + 'y': 'unsigned long long', + 'z': '...' + }; + var subs = []; + var first = true; + function dump(x) { + //return; + if (x) Module.print(x); + Module.print(func); + var pre = ''; + for (var a = 0; a < i; a++) pre += ' '; + Module.print (pre + '^'); + } + function parseNested() { + i++; + if (func[i] === 'K') i++; // ignore const + var parts = []; + while (func[i] !== 'E') { + if (func[i] === 'S') { // substitution + i++; + var next = func.indexOf('_', i); + var num = func.substring(i, next) || 0; + parts.push(subs[num] || '?'); + i = next+1; + continue; + } + if (func[i] === 'C') { // constructor + parts.push(parts[parts.length-1]); + i += 2; + continue; + } + var size = parseInt(func.substr(i)); + var pre = size.toString().length; + if (!size || !pre) { i--; break; } // counter i++ below us + var curr = func.substr(i + pre, size); + parts.push(curr); + subs.push(curr); + i += pre + size; + } + i++; // skip E + return parts; + } + function parse(rawList, limit, allowVoid) { // main parser + limit = limit || Infinity; + var ret = '', list = []; + function flushList() { + return '(' + list.join(', ') + ')'; + } + var name; + if (func[i] === 'N') { + // namespaced N-E + name = parseNested().join('::'); + limit--; + if (limit === 0) return rawList ? [name] : name; + } else { + // not namespaced + if (func[i] === 'K' || (first && func[i] === 'L')) i++; // ignore const and first 'L' + var size = parseInt(func.substr(i)); + if (size) { + var pre = size.toString().length; + name = func.substr(i + pre, size); + i += pre + size; + } + } + first = false; + if (func[i] === 'I') { + i++; + var iList = parse(true); + var iRet = parse(true, 1, true); + ret += iRet[0] + ' ' + name + '<' + iList.join(', ') + '>'; + } else { + ret = name; + } + paramLoop: while (i < func.length && limit-- > 0) { + //dump('paramLoop'); + var c = func[i++]; + if (c in basicTypes) { + list.push(basicTypes[c]); + } else { + switch (c) { + case 'P': list.push(parse(true, 1, true)[0] + '*'); break; // pointer + case 'R': list.push(parse(true, 1, true)[0] + '&'); break; // reference + case 'L': { // literal + i++; // skip basic type + var end = func.indexOf('E', i); + var size = end - i; + list.push(func.substr(i, size)); + i += size + 2; // size + 'EE' + break; + } + case 'A': { // array + var size = parseInt(func.substr(i)); + i += size.toString().length; + if (func[i] !== '_') throw '?'; + i++; // skip _ + list.push(parse(true, 1, true)[0] + ' [' + size + ']'); + break; + } + case 'E': break paramLoop; + default: ret += '?' + c; break paramLoop; + } + } + } + if (!allowVoid && list.length === 1 && list[0] === 'void') list = []; // avoid (void) + if (rawList) { + if (ret) { + list.push(ret + '?'); + } + return list; + } else { + return ret + flushList(); + } + } + try { + // Special-case the entry point, since its name differs from other name mangling. + if (func == 'Object._main' || func == '_main') { + return 'main()'; + } + if (typeof func === 'number') func = Pointer_stringify(func); + if (func[0] !== '_') return func; + if (func[1] !== '_') return func; // C function + if (func[2] !== 'Z') return func; + switch (func[3]) { + case 'n': return 'operator new()'; + case 'd': return 'operator delete()'; + } + return parse(); + } catch(e) { + return func; + } +} + +function demangleAll(text) { + return text.replace(/__Z[\w\d_]+/g, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']') }); +} + +function stackTrace() { + var stack = new Error().stack; + return stack ? demangleAll(stack) : '(no stack trace available)'; // Stack trace is not available at least on IE10 and Safari 6. +} + +// Memory management + +var PAGE_SIZE = 4096; +function alignMemoryPage(x) { + return (x+4095)&-4096; +} + +var HEAP; +var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; + +var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area +var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area +var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk + +function enlargeMemory() { + abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.'); +} + +var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; +var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 67108864; +var FAST_MEMORY = Module['FAST_MEMORY'] || 2097152; + +var totalMemory = 4096; +while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) { + if (totalMemory < 16*1024*1024) { + totalMemory *= 2; + } else { + totalMemory += 16*1024*1024 + } +} +if (totalMemory !== TOTAL_MEMORY) { + Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be more reasonable'); + TOTAL_MEMORY = totalMemory; +} + +// Initialize the runtime's memory +// check for full engine support (use string 'subarray' to avoid closure compiler confusion) +assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']), + 'JS engine does not provide full typed array support'); + +var buffer = new ArrayBuffer(TOTAL_MEMORY); +HEAP8 = new Int8Array(buffer); +HEAP16 = new Int16Array(buffer); +HEAP32 = new Int32Array(buffer); +HEAPU8 = new Uint8Array(buffer); +HEAPU16 = new Uint16Array(buffer); +HEAPU32 = new Uint32Array(buffer); +HEAPF32 = new Float32Array(buffer); +HEAPF64 = new Float64Array(buffer); + +// Endianness check (note: assumes compiler arch was little-endian) +HEAP32[0] = 255; +assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system'); + +Module['HEAP'] = HEAP; +Module['HEAP8'] = HEAP8; +Module['HEAP16'] = HEAP16; +Module['HEAP32'] = HEAP32; +Module['HEAPU8'] = HEAPU8; +Module['HEAPU16'] = HEAPU16; +Module['HEAPU32'] = HEAPU32; +Module['HEAPF32'] = HEAPF32; +Module['HEAPF64'] = HEAPF64; + +function callRuntimeCallbacks(callbacks) { + while(callbacks.length > 0) { + var callback = callbacks.shift(); + if (typeof callback == 'function') { + callback(); + continue; + } + var func = callback.func; + if (typeof func === 'number') { + if (callback.arg === undefined) { + Runtime.dynCall('v', func); + } else { + Runtime.dynCall('vi', func, [callback.arg]); + } + } else { + func(callback.arg === undefined ? null : callback.arg); + } + } +} + +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATMAIN__ = []; // functions called when main() is to be run +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the runtime has exited + +var runtimeInitialized = false; + +function preRun() { + // compatibility - merge in anything from Module['preRun'] at this time + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + callRuntimeCallbacks(__ATPRERUN__); +} + +function ensureInitRuntime() { + if (runtimeInitialized) return; + runtimeInitialized = true; + callRuntimeCallbacks(__ATINIT__); +} + +function preMain() { + callRuntimeCallbacks(__ATMAIN__); +} + +function exitRuntime() { + callRuntimeCallbacks(__ATEXIT__); +} + +function postRun() { + // compatibility - merge in anything from Module['postRun'] at this time + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + callRuntimeCallbacks(__ATPOSTRUN__); +} + +function addOnPreRun(cb) { + __ATPRERUN__.unshift(cb); +} +Module['addOnPreRun'] = Module.addOnPreRun = addOnPreRun; + +function addOnInit(cb) { + __ATINIT__.unshift(cb); +} +Module['addOnInit'] = Module.addOnInit = addOnInit; + +function addOnPreMain(cb) { + __ATMAIN__.unshift(cb); +} +Module['addOnPreMain'] = Module.addOnPreMain = addOnPreMain; + +function addOnExit(cb) { + __ATEXIT__.unshift(cb); +} +Module['addOnExit'] = Module.addOnExit = addOnExit; + +function addOnPostRun(cb) { + __ATPOSTRUN__.unshift(cb); +} +Module['addOnPostRun'] = Module.addOnPostRun = addOnPostRun; + +// Tools + +// This processes a JS string into a C-line array of numbers, 0-terminated. +// For LLVM-originating strings, see parser.js:parseLLVMString function +function intArrayFromString(stringy, dontAddNull, length /* optional */) { + var ret = (new Runtime.UTF8Processor()).processJSString(stringy); + if (length) { + ret.length = length; + } + if (!dontAddNull) { + ret.push(0); + } + return ret; +} +Module['intArrayFromString'] = intArrayFromString; + +function intArrayToString(array) { + var ret = []; + for (var i = 0; i < array.length; i++) { + var chr = array[i]; + if (chr > 0xFF) { + chr &= 0xFF; + } + ret.push(String.fromCharCode(chr)); + } + return ret.join(''); +} +Module['intArrayToString'] = intArrayToString; + +// Write a Javascript array to somewhere in the heap +function writeStringToMemory(string, buffer, dontAddNull) { + var array = intArrayFromString(string, dontAddNull); + var i = 0; + while (i < array.length) { + var chr = array[i]; + HEAP8[(((buffer)+(i))|0)]=chr; + i = i + 1; + } +} +Module['writeStringToMemory'] = writeStringToMemory; + +function writeArrayToMemory(array, buffer) { + for (var i = 0; i < array.length; i++) { + HEAP8[(((buffer)+(i))|0)]=array[i]; + } +} +Module['writeArrayToMemory'] = writeArrayToMemory; + +function writeAsciiToMemory(str, buffer, dontAddNull) { + for (var i = 0; i < str.length; i++) { + HEAP8[(((buffer)+(i))|0)]=str.charCodeAt(i); + } + if (!dontAddNull) HEAP8[(((buffer)+(str.length))|0)]=0; +} +Module['writeAsciiToMemory'] = writeAsciiToMemory; + +function unSign(value, bits, ignore) { + if (value >= 0) { + return value; + } + return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts + : Math.pow(2, bits) + value; +} +function reSign(value, bits, ignore) { + if (value <= 0) { + return value; + } + var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 + : Math.pow(2, bits-1); + if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that + // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors + // TODO: In i64 mode 1, resign the two parts separately and safely + value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts + } + return value; +} + +// check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 ) +if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) { + var ah = a >>> 16; + var al = a & 0xffff; + var bh = b >>> 16; + var bl = b & 0xffff; + return (al*bl + ((ah*bl + al*bh) << 16))|0; +}; +Math.imul = Math['imul']; + + +var Math_abs = Math.abs; +var Math_cos = Math.cos; +var Math_sin = Math.sin; +var Math_tan = Math.tan; +var Math_acos = Math.acos; +var Math_asin = Math.asin; +var Math_atan = Math.atan; +var Math_atan2 = Math.atan2; +var Math_exp = Math.exp; +var Math_log = Math.log; +var Math_sqrt = Math.sqrt; +var Math_ceil = Math.ceil; +var Math_floor = Math.floor; +var Math_pow = Math.pow; +var Math_imul = Math.imul; +var Math_fround = Math.fround; +var Math_min = Math.min; + +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// PRE_RUN_ADDITIONS (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled + +function addRunDependency(id) { + runDependencies++; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } +} +Module['addRunDependency'] = addRunDependency; +function removeRunDependency(id) { + runDependencies--; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } +} +Module['removeRunDependency'] = removeRunDependency; + +Module["preloadedImages"] = {}; // maps url to image data +Module["preloadedAudios"] = {}; // maps url to audio data + + +var memoryInitializer = null; + +// === Body === + + + + + +STATIC_BASE = 8; + +STATICTOP = STATIC_BASE + Runtime.alignMemory(28211); +/* global initializers */ __ATINIT__.push(); + + +/* memory initializer */ allocate([37,46,51,102,32,37,46,51,102,0,0,0,0,0,0,0,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,0,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,0,108,105,110,101,97,114,0,0,100,101,103,114,101,101,115,0,115,101,120,97,103,101,115,105,109,97,108,0,0,0,0,0,59,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,115,40,0,0,0,0,0,37,46,54,102,44,32,37,46,54,102,0,0,0,0,0,0,37,115,44,32,37,115,0,0,112,111,108,121,103,111,110,0,44,32,37,46,54,102,44,32,37,46,54,102,0,0,0,0,44,32,37,115,44,32,37,115,0,0,0,0,0,0,0,0,44,32,37,46,50,102,34,0,44,32,37,46,54,102,39,0,44,32,37,46,54,102,100,0,98,111,120,0,0,0,0,0,101,108,108,105,112,115,101,0,44,32,37,46,51,102,0,0,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,102,32,37,102], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE); +/* memory initializer */ allocate([1,0,0,0,0,0,0,0,87,67,83,73,78,73,84,78,58,32,87,67,83,32,110,97,109,101,32,37,115,32,110,111,116,32,109,97,116,99,104,101,100,32,105,110,32,70,73,84,83,32,104,101,97,100,101,114,10,0,0,0,0,0,0,0,87,67,83,78,65,77,69,0,87,67,83,65,88,69,83,0,78,65,88,73,83,0,0,0,87,67,83,68,73,77,0,0,87,67,83,73,78,73,84,58,32,78,111,32,87,67,83,65,88,69,83,44,32,78,65,88,73,83,44,32,111,114,32,87,67,83,68,73,77,32,107,101,121,119,111,114,100,0,0,0,78,65,88,73,83,49,0,0,73,77,65,71,69,87,0,0,87,67,83,73,78,73,84,58,32,78,111,32,78,65,88,73,83,49,32,111,114,32,73,77,65,71,69,87,32,107,101,121,119,111,114,100,0,0,0,0,78,65,88,73,83,50,0,0,73,77,65,71,69,72,0,0,87,67,83,73,78,73,84,58,32,78,111,32,78,65,88,73,83,50,32,111,114,32,73,77,65,71,69,72,32,107,101,121,119,111,114,100,0,0,0,0,37,100,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,77,105,115,115,105,110,103,32,107,101,121,119,111,114,100,32,37,115,32,97,115,115,117,109,101,100,32,49,10,0,0,67,84,89,80,69,0,0,0,45,84,65,66,0,0,0,0,73,78,83,84,82,85,77,69,0,0,0,0,0,0,0,0,68,69,84,69,67,84,79,82,0,0,0,0,0,0,0,0,68,67,45,70,76,65,71,0,87,67,83,68,69,80,0,0,87,67,83,73,78,73,84,58,32,100,101,112,101,110,100,101,100,32,111,110,32,87,67,83,32,99,111,117,108,100,32,110,111,116,32,98,101,32,115,101,116,0,0,0,0,0,0,0,86,83,79,85,82,67,69,0,90,83,79,85,82,67,69,0,86,69,76,79,67,73,84,89,0,0,0,0,0,0,0,0,67,84,89,80,69,49,0,0,67,84,89,80,69,50,0,0,76,65,84,0,0,0,0,0,68,69,67,0,0,0,0,0,67,84,89,80,69,51,0,0,67,84,89,80,69,52,0,0,67,85,78,73,84,49,0,0,87,65,84,49,0,0,0,0,117,110,105,116,115,0,0,0,112,105,120,101,108,0,0,0,67,85,78,73,84,50,0,0,87,65,84,50,0,0,0,0,67,82,80,73,88,49,0,0,67,82,80,73,88,50,0,0,67,82,86,65,76,49,0,0,67,82,86,65,76,50,0,0,76,79,78,80,79,76,69,0,76,65,84,80,79,76,69,0,80,82,79,74,82,48,0,0,80,82,79,74,80,37,100,0,80,86,37,100,95,49,0,0,80,86,37,100,95,50,0,0,80,86,37,100,95,51,0,0,80,86,37,100,95,37,100,0,67,68,49,95,49,0,0,0,67,68,49,95,50,0,0,0,67,68,50,95,49,0,0,0,67,68,50,95,50,0,0,0,67,79,49,95,49,0,0,0,80,76,65,84,69,0,0,0,67,79,49,95,37,100,0,0,67,79,50,95,49,0,0,0,67,79,50,95,37,100,0,0,67,68,69,76,84,49,0,0,67,68,69,76,84,50,0,0,83,69,67,80,73,88,0,0,80,73,88,83,67,65,76,69,0,0,0,0,0,0,0,0,80,73,88,83,67,65,76,49,0,0,0,0,0,0,0,0,88,80,73,88,83,73,90,69,0,0,0,0,0,0,0,0,83,69,67,80,73,88,49,0,83,69,67,80,73,88,50,0,89,80,73,88,83,73,90,69,0,0,0,0,0,0,0,0,80,73,88,83,67,65,76,50,0,0,0,0,0,0,0,0,80,67,48,48,49,48,48,49,0,0,0,0,0,0,0,0,80,67,48,48,37,49,100,48,48,37,49,100,0,0,0,0,80,67,49,95,49,0,0,0,80,67,37,49,100,95,37,49,100,0,0,0,0,0,0,0,67,82,79,84,65,50,0,0,67,82,79,84,65,49,0,0,87,67,83,73,78,73,84,58,32,115,101,116,116,105,110,103,32,67,68,69,76,84,32,116,111,32,49,0,0,0,0,0,76,73,78,69,65,82,0,0,80,73,88,69,76,0,0,0,77,74,68,45,79,66,83,0,68,65,84,69,45,79,66,83,0,0,0,0,0,0,0,0,68,65,84,69,0,0,0,0,69,80,79,67,72,0,0,0,85,84,0,0,0,0,0,0,85,84,77,73,68,0,0,0,87,67,83,73,78,73,84,67,58,32,78,111,32,105,109,97,103,101,32,115,99,97,108,101,32,102,111,114,32,87,67,83,32,37,99,0,0,0,0,0,80,76,84,82,65,72,0,0,80,76,84,82,65,77,0,0,80,76,84,82,65,83,0,0,80,76,84,68,69,67,83,78,0,0,0,0,0,0,0,0,80,76,84,68,69,67,68,0,80,76,84,68,69,67,77,0,80,76,84,68,69,67,83,0,69,81,85,73,78,79,88,0,70,75,52,0,0,0,0,0,70,75,53,0,0,0,0,0,37,50,46,48,102,58,37,50,46,48,102,58,37,53,46,51,102,32,37,99,37,50,46,48,102,58,37,50,46,48,102,58,37,53,46,51,102,32,37,115,0,0,0,0,0,0,0,0,80,76,84,83,67,65,76,69,0,0,0,0,0,0,0,0,88,80,73,88,69,76,83,90,0,0,0,0,0,0,0,0,89,80,73,88,69,76,83,90,0,0,0,0,0,0,0,0,67,78,80,73,88,49,0,0,67,78,80,73,88,50,0,0,80,80,79,49,0,0,0,0,80,80,79,37,100,0,0,0,65,77,68,88,49,0,0,0,65,77,68,88,37,100,0,0,65,77,68,89,49,0,0,0,65,77,68,89,37,100,0,0,82,65,0,0,0,0,0,0,82,65,45,45,45,68,83,83,0,0,0,0,0,0,0,0,68,69,67,45,45,68,83,83,0,0,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,78,111,32,82,65,32,119,105,116,104,32,83,69,67,80,73,88,44,32,110,111,32,87,67,83,0,0,0,0,0,0,87,67,83,73,78,73,84,32,78,111,32,68,69,67,32,119,105,116,104,32,83,69,67,80,73,88,44,32,110,111,32,87,67,83,0,0,0,0,0,0,76,79,78,71,80,79,76,69,0,0,0,0,0,0,0,0,82,65,45,45,45,84,65,78,0,0,0,0,0,0,0,0,68,69,67,45,45,84,65,78,0,0,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,78,111,32,105,109,97,103,101,32,115,99,97,108,101,0,84,65,78,0,0,0,0,0,42,69,114,114,111,114,42,58,32,105,110,99,111,114,114,101,99,116,32,108,105,110,101,97,114,32,99,111,110,118,101,114,115,105,111,110,32,105,110,32,37,115,0,0,0,0,0,0,87,65,82,78,73,78,71,58,32,83,105,103,110,105,102,105,99,97,110,116,32,105,110,97,99,99,117,114,97,99,121,32,108,105,107,101,108,121,32,116,111,32,111,99,99,117,114,32,105,110,32,112,114,111,106,101,99,116,105,111,110,0,0,0,69,81,85,73,78,79,88,37,99,0,0,0,0,0,0,0,82,65,68,69,67,83,89,83,37,99,0,0,0,0,0,0,82,65,68,69,67,83,89,83,0,0,0,0,0,0,0,0,73,67,82,83,0,0,0,0,71,65,76,0,0,0,0,0,69,67,76,0,0,0,0,0,71,65,76,65,67,84,73,67,0,0,0,0,0,0,0,0,69,67,76,73,80,84,73,67,0,0,0,0,0,0,0,0,83,71,65,76,65,67,84,67,0,0,0,0,0,0,0,0,72,69,76,73,79,69,67,76,0,0,0,0,0,0,0,0,65,76,84,65,90,0,0,0,0,0,0,0,0,0,0,0,68,69,67,0,0,0,0,0,76,79,78,71,0,0,0,0,76,73,78,69,65,82,0,0,80,73,88,69,76,0,0,0,68,69,84,0,0,0,0,0,37,45,52,115,37,52,115,0,78,80,79,76,0,0,0,0,76,65,84,0,0,0,0,0,78,80,79,76,69,0,0,0,83,80,65,45,0,0,0,0,73,77,83,89,83,0,0,0,105,109,115,121,115,0,0,0,37,46,52,102,0,0,0,0,66,49,57,53,48,0,0,0,74,50,48,48,48,0,0,0,37,115,9,37,115,0,0,0,37,115,32,37,115,0,0,0,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,42,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,9,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,32,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,9,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,32,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,9,108,111,110,103,45,110,112,97,0,0,0,0,0,0,0,32,108,111,110,103,45,110,112,97,0,0,0,0,0,0,0,9,108,111,110,103,45,115,112,97,0,0,0,0,0,0,0,32,108,111,110,103,45,115,112,97,0,0,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,67,83,95,67,79,77,77,65,78,68,0,0,0,0,0,87,67,83,95,67,79,77,77,65,78,68,37,100,0,0,0,50,48,48,48,0,0,0,0,50,48,48,48,46,48,0,0,73,67,82,83,0,0,0,0,105,99,114,115,0,0,0,0,70,75,53,0,0,0,0,0,102,107,53,0,0,0,0,0,49,57,53,48,0,0,0,0,49,57,53,48,46,48,0,0,70,75,52,0,0,0,0,0,102,107,52,0,0,0,0,0,112,105,120,101,108,0,0,0,44,66,124,35,100,255,239,63,206,4,147,55,81,230,134,63,201,87,119,237,8,231,115,63,8,49,216,60,72,85,196,190,141,82,239,197,175,26,93,190,79,75,150,130,180,74,73,190,206,4,147,55,81,230,134,191,110,20,118,229,124,255,239,63,190,2,89,23,76,127,252,190,141,82,239,197,175,26,93,62,186,92,192,248,87,85,196,190,213,61,80,36,200,25,210,61,192,143,86,244,8,231,115,191,40,252,144,126,141,121,252,190,190,45,6,62,231,255,239,63,79,75,150,130,180,74,73,62,213,61,80,36,200,25,210,61,56,97,156,141,155,85,196,190,37,201,115,125,31,14,66,191,237,156,102,129,118,135,206,63,237,128,235,138,25,225,219,191,138,238,48,88,55,255,239,63,235,42,147,208,76,230,134,63,26,132,28,8,135,230,115,63,12,31,17,83,34,137,206,191,58,234,232,184,26,217,101,191,7,35,246,9,160,24,137,63,235,42,147,208,76,230,134,191,233,248,162,28,80,255,239,63,8,168,211,46,100,125,252,190,137,181,248,20,0,227,219,63,180,173,102,157,241,125,129,191,174,14,128,184,171,87,97,63,26,132,28,8,135,230,115,191,247,97,247,252,180,122,252,190,137,77,92,117,186,255,239,63,125,150,201,34,100,255,239,63,15,157,207,213,158,230,134,191,92,113,244,103,237,229,115,191,26,77,59,180,100,85,196,62,52,175,17,131,3,27,93,190,173,87,210,121,59,74,73,190,20,1,96,210,158,230,134,63,3,186,248,225,124,255,239,63,250,59,9,220,34,127,252,190,52,175,17,131,3,27,93,62,91,229,82,109,116,85,196,62,232,167,8,110,48,27,210,189,73,225,178,117,237,229,115,63,235,19,108,31,83,119,252,190,10,30,195,64,231,255,239,63,173,87,210,121,59,74,73,62,185,158,187,181,171,23,210,189,73,125,255,4,184,85,196,62,37,201,115,125,31,14,66,191,211,48,124,68,76,137,206,191,34,223,165,212,37,227,219,63,45,6,81,239,144,255,239,63,108,197,229,21,219,230,134,191,214,96,142,220,162,229,115,191,180,174,209,114,160,135,206,63,58,234,232,184,26,217,101,191,180,173,102,157,241,125,129,191,108,197,229,21,219,230,134,63,26,73,6,169,169,255,239,63,26,238,175,96,19,128,252,190,134,170,152,74,63,225,219,191,7,35,246,9,160,24,137,63,174,14,128,184,171,87,97,63,214,96,142,220,162,229,115,63,212,213,62,153,86,117,252,190,150,50,62,6,10,0,240,63,0,0,0,0,0,0,0,0,70,75,52,50,71,65,76,58,32,66,49,57,53,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,52,50,71,65,76,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,52,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,52,58,32,66,49,57,53,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,53,50,71,65,76,58,32,74,50,48,48,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,53,50,71,65,76,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,53,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,53,58,32,74,50,48,48,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,32,37,99,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,0,0,0,0,0,0,0,69,78,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,28,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,37,115,95,49,0,0,0,0,37,115,95,37,100,0,0,0,37,115,95,48,49,0,0,0,37,115,95,48,48,49,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,48,0,0,0,0,0,0,37,100,0,0,0,0,0,0,37,37,46,37,100,102,0,0,37,48,50,100,58,37,48,50,100,58,37,48,57,46,54,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,56,46,53,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,55,46,52,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,52,46,49,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,50,100,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,57,46,54,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,56,46,53,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,55,46,52,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,52,46,49,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,50,100,0,0,0,0,0,0,0,0,37,37,37,100,46,37,100,102,0,0,0,0,0,0,0,0,37,37,37,52,100,0,0,0,37,37,37,100,100], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+4352); +/* memory initializer */ allocate([87,65,84,49,0,0,0,0,87,65,84,50,0,0,0,0,108,111,110,103,112,111,108,101,0,0,0,0,0,0,0,0,114,111,0,0,0,0,0,0,108,110,103,99,111,114,0,0,108,97,116,99,111,114,0,0,84,78,88,95,71,83,69,86,65,76,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,10,0,0,0,0,0,0,0,84,78,88,95,71,83,68,69,82,58,32,111,114,100,101,114,32,111,102,32,100,101,114,105,118,97,116,105,118,101,115,32,99,97,110,110,111,116,32,98,101,32,60,32,48,10,0,0,84,78,88,95,71,83,68,69,82,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,32,37,100,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,120,32,111,114,100,101,114,32,37,100,10,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,121,32,111,114,100,101,114,32,37,100,10,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,120,32,114,97,110,103,101,32,37,102,45,37,102,10,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,121,32,114,97,110,103,101,32,37,102,45,37,102,10,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,32,37,100,10,0,0,87,65,84,49,0,0,0,0,87,65,84,49,95,48,48,49,61,32,39,119,116,121,112,101,61,122,112,120,32,97,120,116,121,112,101,61,114,97,32,112,114,111,106,112,48,61,48,46,32,112,114,111,106,112,49,61,49,46,32,112,114,111,106,112,50,61,48,46,32,112,114,111,106,112,51,61,51,51,55,46,55,52,32,112,114,111,106,39,87,65,84,50,95,48,48,49,61,32,39,119,116,121,112,101,61,122,112,120,32,97,120,116,121,112,101,61,100,101,99,32,112,114,111,106,112,48,61,48,46,32,112,114,111,106,112,49,61,49,46,32,112,114,111,106,112,50,61,48,46,32,112,114,111,106,112,51,61,51,51,55,46,55,52,32,112,114,111,39,0,0,0,0,0,0,0,0,87,65,84,50,0,0,0,0,108,111,110,103,112,111,108,101,0,0,0,0,0,0,0,0,114,111,0,0,0,0,0,0,112,114,111,106,112,37,100,0,108,110,103,99,111,114,0,0,108,97,116,99,111,114,0,0,10,62,32,37,115,37,115,10,10,0,0,0,0,0,0,0,78,111,116,32,101,110,111,117,103,104,32,109,101,109,111,114,121,32,102,111,114,32,0,0,112,111,108,121,32,40,49,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,84,104,101,32,100,105,109,101,110,115,105,111,110,97,108,105,116,121,32,111,102,32,116,104,101,32,112,111,108,121,110,111,109,32,40,37,100,41,32,101,120,99,101,101,100,115,32,116,104,101,32,109,97,120,105,109,117,109,10,97,108,108,111,119,101,100,32,111,110,101,32,40,37,100,41,0,0,0,0,0,42,69,114,114,111,114,42,58,32,0,0,0,0,0,0,0,112,111,108,121,45,62,103,114,111,117,112,32,40,112,111,108,121,45,62,110,100,105,109,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,112,111,108,121,45,62,100,101,103,114,101,101,32,40,112,111,108,121,45,62,110,103,114,111,117,112,32,101,108,101,109,101,110,116,115,41,32,33,0,0,42,69,114,114,111,114,42,58,32,112,111,108,121,110,111,109,105,97,108,32,71,82,79,85,80,32,111,117,116,32,111,102,32,114,97,110,103,101,0,0,0,0,0,0,0,0,0,0,84,104,101,32,100,101,103,114,101,101,32,111,102,32,116,104,101,32,112,111,108,121,110,111,109,32,40,37,100,41,32,101,120,99,101,101,100,115,32,116,104,101,32,109,97,120,105,109,117,109,10,97,108,108,111,119,101,100,32,111,110,101,32,40,37,100,41,0,0,0,0,0,112,111,108,121,45,62,98,97,115,105,115,32,40,112,111,108,121,45,62,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,112,111,108,121,45,62,99,111,101,102,102,32,40,112,111,108,121,45,62,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,42,73,110,116,101,114,110,97,108,32,69,114,114,111,114,42,58,32,79,110,101,32,111,102,32,120,32,111,114,32,101,120,116,98,97,115,105,115,32,115,104,111,117,108,100,32,98,101,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,78,85,76,76,10,105,110,32,0,0,0,0,0,0,0,0,112,111,108,121,95,102,117,110,99,40,41,0,0,0,0,0,97,108,112,104,97,32,40,109,97,116,115,105,122,101,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,98,101,116,97,32,40,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,0,0,118,109,97,116,32,40,110,42,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,119,109,97,116,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,112,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,0,0,42,69,114,114,111,114,42,58,32,78,111,116,32,101,110,111,117,103,104,32,114,111,119,115,32,102,111,114,32,115,111,108,118,105,110,103,32,116,104,101,32,115,121,115,116,101,109,32,0,0,0,0,0,0,0,0,105,110,32,115,118,100,102,105,116,40,41,0,0,0,0,0,114,118,49,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,116,109,112,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,42,69,114,114,111,114,42,58,32,78,111,32,99,111,110,118,101,114,103,101,110,99,101,32,105,110,32,49,48,48,32,83,86,68,32,105,116,101,114,97,116,105,111,110,115,32,0,0,67,85,66,69,70,65,67,69,0,0,0,0,0,0,0,0,37,46,51,115,0,0,0,0,82,65,45,45,0,0,0,0,82,65,0,0,0,0,0,0,68,69,67,45,45,37,115,0,68,69,67,45,0,0,0,0,82,65,45,45,45,37,115,0,76,79,78,0,0,0,0,0,37,99,76,79,78,0,0,0,37,99,76,65,84,0,0,0,37,115,45,37,115,0,0,0,76,65,84,0,0,0,0,0,76,78,0,0,0,0,0,0,37,99,37,99,76,78,0,0,37,99,37,99,76,84,0,0,76,84,0,0,0,0,0,0,71,76,83,0,0,0,0,0,78,67,80,0,0,0,0,0,26,0,0,0,0,0,0,0,65,90,80,0,83,90,80,0,84,65,78,0,83,84,71,0,83,73,78,0,65,82,67,0,90,80,78,0,90,69,65,0,65,73,82,0,67,89,80,0,67,69,65,0,67,65,82,0,77,69,82,0,67,79,80,0,67,79,69,0,67,79,68,0,67,79,79,0,83,70,76,0,80,65,82,0,77,79,76,0,65,73,84,0,66,79,78,0,80,67,79,0,84,83,67,0,67,83,67,0,81,83,67,0,65,90,80,0,0,0,0,0,83,90,80,0,0,0,0,0,84,65,78,0,0,0,0,0,83,84,71,0,0,0,0,0,83,73,78,0,0,0,0,0,65,82,67,0,0,0,0,0,90,80,78,0,0,0,0,0,90,69,65,0,0,0,0,0,65,73,82,0,0,0,0,0,67,89,80,0,0,0,0,0,67,69,65,0,0,0,0,0,67,65,82,0,0,0,0,0,77,69,82,0,0,0,0,0,83,70,76,0,0,0,0,0,80,65,82,0,0,0,0,0,77,79,76,0,0,0,0,0,65,73,84,0,0,0,0,0,67,79,80,0,0,0,0,0,67,79,69,0,0,0,0,0,67,79,68,0,0,0,0,0,67,79,79,0,0,0,0,0,66,79,78,0,0,0,0,0,80,67,79,0,0,0,0,0,84,83,67,0,0,0,0,0,67,83,67,0,0,0,0,0,81,83,67,0,0,0,0,0,65,95,79,82,68,69,82,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,65,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,0,65,95,37,100,95,37,100,0,66,95,79,82,68,69,82,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,66,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,0,66,95,37,100,95,37,100,0,65,80,95,79,82,68,69,82,0,0,0,0,0,0,0,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,65,80,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,65,80,95,37,100,95,37,100,0,0,0,0,0,0,0,0,66,80,95,79,82,68,69,82,0,0,0,0,0,0,0,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,66,80,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,66,80,95,37,100,95,37,100,0,0,0,0,0,0,0,0,45,83,73,80,0,0,0,0,0,0,0,0,0,0,0,0,91,99,100,108,95,122,115,99,97,108,101,93,32,37,100,120,37,100,45,37,100,32,32,99,111,110,116,61,37,103,32,111,112,116,115,122,61,37,100,32,108,101,110,61,37,100,10,0,91,99,100,108,95,122,115,99,97,108,101,93,32,122,109,105,110,61,37,103,32,122,109,97,120,61,37,103,32,108,101,102,116,61,37,103,32,109,101,100,105,97,110,61,37,103,10,0,91,99,100,108,95,122,115,99,97,108,101,93,32,109,105,110,112,105,120,61,37,100,32,110,103,114,111,119,61,37,100,32,110,103,111,111,100,112,105,120,61,37,100,10,0,0,0,0,91,99,100,108,95,122,115,99,97,108,101,93,32,122,115,108,111,112,101,61,37,103,32,99,101,110,116,101,114,95,112,105,120,61,37,100,32,122,49,61,37,103,32,122,50,61,37,103,10,0,0,0,0,0,0,0,91,115,97,109,112,108,101,73,109,97,103,101,93,32,111,112,116,95,110,112,105,120,47,108,105,110,101,61,37,100,32,99,111,108,95,115,116,101,112,61,37,100,32,110,47,108,105,110,101,61,37,100,10,0,0,0,91,115,97,109,112,108,101,73,109,97,103,101,93,32,110,108,95,105,110,95,115,97,109,112,61,37,100,47,37,100,32,111,112,116,95,110,108,47,115,97,109,112,61,37,100,32,108,115,116,101,112,61,37,100,10,0,0,0,0,0,150,48,7,119,44,97,14,238,186,81,9,153,25,196,109,7,143,244,106,112,53,165,99,233,163,149,100,158,50,136,219,14,164,184,220,121,30,233,213,224,136,217,210,151,43,76,182,9,189,124,177,126,7,45,184,231,145,29,191,144,100,16,183,29,242,32,176,106,72,113,185,243,222,65,190,132,125,212,218,26,235,228,221,109,81,181,212,244,199,133,211,131,86,152,108,19,192,168,107,100,122,249,98,253,236,201,101,138,79,92,1,20,217,108,6,99,99,61,15,250,245,13,8,141,200,32,110,59,94,16,105,76,228,65,96,213,114,113,103,162,209,228,3,60,71,212,4,75,253,133,13,210,107,181,10,165,250,168,181,53,108,152,178,66,214,201,187,219,64,249,188,172,227,108,216,50,117,92,223,69,207,13,214,220,89,61,209,171,172,48,217,38,58,0,222,81,128,81,215,200,22,97,208,191,181,244,180,33,35,196,179,86,153,149,186,207,15,165,189,184,158,184,2,40,8,136,5,95,178,217,12,198,36,233,11,177,135,124,111,47,17,76,104,88,171,29,97,193,61,45,102,182,144,65,220,118,6,113,219,1,188,32,210,152,42,16,213,239,137,133,177,113,31,181,182,6,165,228,191,159,51,212,184,232,162,201,7,120,52,249,0,15,142,168,9,150,24,152,14,225,187,13,106,127,45,61,109,8,151,108,100,145,1,92,99,230,244,81,107,107,98,97,108,28,216,48,101,133,78,0,98,242,237,149,6,108,123,165,1,27,193,244,8,130,87,196,15,245,198,217,176,101,80,233,183,18,234,184,190,139,124,136,185,252,223,29,221,98,73,45,218,21,243,124,211,140,101,76,212,251,88,97,178,77,206,81,181,58,116,0,188,163,226,48,187,212,65,165,223,74,215,149,216,61,109,196,209,164,251,244,214,211,106,233,105,67,252,217,110,52,70,136,103,173,208,184,96,218,115,45,4,68,229,29,3,51,95,76,10,170,201,124,13,221,60,113,5,80,170,65,2,39,16,16,11,190,134,32,12,201,37,181,104,87,179,133,111,32,9,212,102,185,159,228,97,206,14,249,222,94,152,201,217,41,34,152,208,176,180,168,215,199,23,61,179,89,129,13,180,46,59,92,189,183,173,108,186,192,32,131,184,237,182,179,191,154,12,226,182,3,154,210,177,116,57,71,213,234,175,119,210,157,21,38,219,4,131,22,220,115,18,11,99,227,132,59,100,148,62,106,109,13,168,90,106,122,11,207,14,228,157,255,9,147,39,174,0,10,177,158,7,125,68,147,15,240,210,163,8,135,104,242,1,30,254,194,6,105,93,87,98,247,203,103,101,128,113,54,108,25,231,6,107,110,118,27,212,254,224,43,211,137,90,122,218,16,204,74,221,103,111,223,185,249,249,239,190,142,67,190,183,23,213,142,176,96,232,163,214,214,126,147,209,161,196,194,216,56,82,242,223,79,241,103,187,209,103,87,188,166,221,6,181,63,75,54,178,72,218,43,13,216,76,27,10,175,246,74,3,54,96,122,4,65,195,239,96,223,85,223,103,168,239,142,110,49,121,190,105,70,140,179,97,203,26,131,102,188,160,210,111,37,54,226,104,82,149,119,12,204,3,71,11,187,185,22,2,34,47,38,5,85,190,59,186,197,40,11,189,178,146,90,180,43,4,106,179,92,167,255,215,194,49,207,208,181,139,158,217,44,29,174,222,91,176,194,100,155,38,242,99,236,156,163,106,117,10,147,109,2,169,6,9,156,63,54,14,235,133,103,7,114,19,87,0,5,130,74,191,149,20,122,184,226,174,43,177,123,56,27,182,12,155,142,210,146,13,190,213,229,183,239,220,124,33,223,219,11,212,210,211,134,66,226,212,241,248,179,221,104,110,131,218,31,205,22,190,129,91,38,185,246,225,119,176,111,119,71,183,24,230,90,8,136,112,106,15,255,202,59,6,102,92,11,1,17,255,158,101,143,105,174,98,248,211,255,107,97,69,207,108,22,120,226,10,160,238,210,13,215,84,131,4,78,194,179,3,57,97,38,103,167,247,22,96,208,77,71,105,73,219,119,110,62,74,106,209,174,220,90,214,217,102,11,223,64,240,59,216,55,83,174,188,169,197,158,187,222,127,207,178,71,233,255,181,48,28,242,189,189,138,194,186,202,48,147,179,83,166,163,180,36,5,54,208,186,147,6,215,205,41,87,222,84,191,103,217,35,46,122,102,179,184,74,97,196,2,27,104,93,148,43,111,42,55,190,11,180,161,142,12,195,27,223,5,90,141,239,2,45,0,0,0,0,65,49,27,25,130,98,54,50,195,83,45,43,4,197,108,100,69,244,119,125,134,167,90,86,199,150,65,79,8,138,217,200,73,187,194,209,138,232,239,250,203,217,244,227,12,79,181,172,77,126,174,181,142,45,131,158,207,28,152,135,81,18,194,74,16,35,217,83,211,112,244,120,146,65,239,97,85,215,174,46,20,230,181,55,215,181,152,28,150,132,131,5,89,152,27,130,24,169,0,155,219,250,45,176,154,203,54,169,93,93,119,230,28,108,108,255,223,63,65,212,158,14,90,205,162,36,132,149,227,21,159,140,32,70,178,167,97,119,169,190,166,225,232,241,231,208,243,232,36,131,222,195,101,178,197,218,170,174,93,93,235,159,70,68,40,204,107,111,105,253,112,118,174,107,49,57,239,90,42,32,44,9,7,11,109,56,28,18,243,54,70,223,178,7,93,198,113,84,112,237,48,101,107,244,247,243,42,187,182,194,49,162,117,145,28,137,52,160,7,144,251,188,159,23,186,141,132,14,121,222,169,37,56,239,178,60,255,121,243,115,190,72,232,106,125,27,197,65,60,42,222,88,5,79,121,240,68,126,98,233,135,45,79,194,198,28,84,219,1,138,21,148,64,187,14,141,131,232,35,166,194,217,56,191,13,197,160,56,76,244,187,33,143,167,150,10,206,150,141,19,9,0,204,92,72,49,215,69,139,98,250,110,202,83,225,119,84,93,187,186,21,108,160,163,214,63,141,136,151,14,150,145,80,152,215,222,17,169,204,199,210,250,225,236,147,203,250,245,92,215,98,114,29,230,121,107,222,181,84,64,159,132,79,89,88,18,14,22,25,35,21,15,218,112,56,36,155,65,35,61,167,107,253,101,230,90,230,124,37,9,203,87,100,56,208,78,163,174,145,1,226,159,138,24,33,204,167,51,96,253,188,42,175,225,36,173,238,208,63,180,45,131,18,159,108,178,9,134,171,36,72,201,234,21,83,208,41,70,126,251,104,119,101,226,246,121,63,47,183,72,36,54,116,27,9,29,53,42,18,4,242,188,83,75,179,141,72,82,112,222,101,121,49,239,126,96,254,243,230,231,191,194,253,254,124,145,208,213,61,160,203,204,250,54,138,131,187,7,145,154,120,84,188,177,57,101,167,168,75,152,131,59,10,169,152,34,201,250,181,9,136,203,174,16,79,93,239,95,14,108,244,70,205,63,217,109,140,14,194,116,67,18,90,243,2,35,65,234,193,112,108,193,128,65,119,216,71,215,54,151,6,230,45,142,197,181,0,165,132,132,27,188,26,138,65,113,91,187,90,104,152,232,119,67,217,217,108,90,30,79,45,21,95,126,54,12,156,45,27,39,221,28,0,62,18,0,152,185,83,49,131,160,144,98,174,139,209,83,181,146,22,197,244,221,87,244,239,196,148,167,194,239,213,150,217,246,233,188,7,174,168,141,28,183,107,222,49,156,42,239,42,133,237,121,107,202,172,72,112,211,111,27,93,248,46,42,70,225,225,54,222,102,160,7,197,127,99,84,232,84,34,101,243,77,229,243,178,2,164,194,169,27,103,145,132,48,38,160,159,41,184,174,197,228,249,159,222,253,58,204,243,214,123,253,232,207,188,107,169,128,253,90,178,153,62,9,159,178,127,56,132,171,176,36,28,44,241,21,7,53,50,70,42,30,115,119,49,7,180,225,112,72,245,208,107,81,54,131,70,122,119,178,93,99,78,215,250,203,15,230,225,210,204,181,204,249,141,132,215,224,74,18,150,175,11,35,141,182,200,112,160,157,137,65,187,132,70,93,35,3,7,108,56,26,196,63,21,49,133,14,14,40,66,152,79,103,3,169,84,126,192,250,121,85,129,203,98,76,31,197,56,129,94,244,35,152,157,167,14,179,220,150,21,170,27,0,84,229,90,49,79,252,153,98,98,215,216,83,121,206,23,79,225,73,86,126,250,80,149,45,215,123,212,28,204,98,19,138,141,45,82,187,150,52,145,232,187,31,208,217,160,6,236,243,126,94,173,194,101,71,110,145,72,108,47,160,83,117,232,54,18,58,169,7,9,35,106,84,36,8,43,101,63,17,228,121,167,150,165,72,188,143,102,27,145,164,39,42,138,189,224,188,203,242,161,141,208,235,98,222,253,192,35,239,230,217,189,225,188,20,252,208,167,13,63,131,138,38,126,178,145,63,185,36,208,112,248,21,203,105,59,70,230,66,122,119,253,91,181,107,101,220,244,90,126,197,55,9,83,238,118,56,72,247,177,174,9,184,240,159,18,161,51,204,63,138,114,253,36,147,0,0,0,0,55,106,194,1,110,212,132,3,89,190,70,2,220,168,9,7,235,194,203,6,178,124,141,4,133,22,79,5,184,81,19,14,143,59,209,15,214,133,151,13,225,239,85,12,100,249,26,9,83,147,216,8,10,45,158,10,61,71,92,11,112,163,38,28,71,201,228,29,30,119,162,31,41,29,96,30,172,11,47,27,155,97,237,26,194,223,171,24,245,181,105,25,200,242,53,18,255,152,247,19,166,38,177,17,145,76,115,16,20,90,60,21,35,48,254,20,122,142,184,22,77,228,122,23,224,70,77,56,215,44,143,57,142,146,201,59,185,248,11,58,60,238,68,63,11,132,134,62,82,58,192,60,101,80,2,61,88,23,94,54,111,125,156,55,54,195,218,53,1,169,24,52,132,191,87,49,179,213,149,48,234,107,211,50,221,1,17,51,144,229,107,36,167,143,169,37,254,49,239,39,201,91,45,38,76,77,98,35,123,39,160,34,34,153,230,32,21,243,36,33,40,180,120,42,31,222,186,43,70,96,252,41,113,10,62,40,244,28,113,45,195,118,179,44,154,200,245,46,173,162,55,47,192,141,154,112,247,231,88,113,174,89,30,115,153,51,220,114,28,37,147,119,43,79,81,118,114,241,23,116,69,155,213,117,120,220,137,126,79,182,75,127,22,8,13,125,33,98,207,124,164,116,128,121,147,30,66,120,202,160,4,122,253,202,198,123,176,46,188,108,135,68,126,109,222,250,56,111,233,144,250,110,108,134,181,107,91,236,119,106,2,82,49,104,53,56,243,105,8,127,175,98,63,21,109,99,102,171,43,97,81,193,233,96,212,215,166,101,227,189,100,100,186,3,34,102,141,105,224,103,32,203,215,72,23,161,21,73,78,31,83,75,121,117,145,74,252,99,222,79,203,9,28,78,146,183,90,76,165,221,152,77,152,154,196,70,175,240,6,71,246,78,64,69,193,36,130,68,68,50,205,65,115,88,15,64,42,230,73,66,29,140,139,67,80,104,241,84,103,2,51,85,62,188,117,87,9,214,183,86,140,192,248,83,187,170,58,82,226,20,124,80,213,126,190,81,232,57,226,90,223,83,32,91,134,237,102,89,177,135,164,88,52,145,235,93,3,251,41,92,90,69,111,94,109,47,173,95,128,27,53,225,183,113,247,224,238,207,177,226,217,165,115,227,92,179,60,230,107,217,254,231,50,103,184,229,5,13,122,228,56,74,38,239,15,32,228,238,86,158,162,236,97,244,96,237,228,226,47,232,211,136,237,233,138,54,171,235,189,92,105,234,240,184,19,253,199,210,209,252,158,108,151,254,169,6,85,255,44,16,26,250,27,122,216,251,66,196,158,249,117,174,92,248,72,233,0,243,127,131,194,242,38,61,132,240,17,87,70,241,148,65,9,244,163,43,203,245,250,149,141,247,205,255,79,246,96,93,120,217,87,55,186,216,14,137,252,218,57,227,62,219,188,245,113,222,139,159,179,223,210,33,245,221,229,75,55,220,216,12,107,215,239,102,169,214,182,216,239,212,129,178,45,213,4,164,98,208,51,206,160,209,106,112,230,211,93,26,36,210,16,254,94,197,39,148,156,196,126,42,218,198,73,64,24,199,204,86,87,194,251,60,149,195,162,130,211,193,149,232,17,192,168,175,77,203,159,197,143,202,198,123,201,200,241,17,11,201,116,7,68,204,67,109,134,205,26,211,192,207,45,185,2,206,64,150,175,145,119,252,109,144,46,66,43,146,25,40,233,147,156,62,166,150,171,84,100,151,242,234,34,149,197,128,224,148,248,199,188,159,207,173,126,158,150,19,56,156,161,121,250,157,36,111,181,152,19,5,119,153,74,187,49,155,125,209,243,154,48,53,137,141,7,95,75,140,94,225,13,142,105,139,207,143,236,157,128,138,219,247,66,139,130,73,4,137,181,35,198,136,136,100,154,131,191,14,88,130,230,176,30,128,209,218,220,129,84,204,147,132,99,166,81,133,58,24,23,135,13,114,213,134,160,208,226,169,151,186,32,168,206,4,102,170,249,110,164,171,124,120,235,174,75,18,41,175,18,172,111,173,37,198,173,172,24,129,241,167,47,235,51,166,118,85,117,164,65,63,183,165,196,41,248,160,243,67,58,161,170,253,124,163,157,151,190,162,208,115,196,181,231,25,6,180,190,167,64,182,137,205,130,183,12,219,205,178,59,177,15,179,98,15,73,177,85,101,139,176,104,34,215,187,95,72,21,186,6,246,83,184,49,156,145,185,180,138,222,188,131,224,28,189,218,94,90,191,237,52,152,190,0,0,0,0,101,103,188,184,139,200,9,170,238,175,181,18,87,151,98,143,50,240,222,55,220,95,107,37,185,56,215,157,239,40,180,197,138,79,8,125,100,224,189,111,1,135,1,215,184,191,214,74,221,216,106,242,51,119,223,224,86,16,99,88,159,87,25,80,250,48,165,232,20,159,16,250,113,248,172,66,200,192,123,223,173,167,199,103,67,8,114,117,38,111,206,205,112,127,173,149,21,24,17,45,251,183,164,63,158,208,24,135,39,232,207,26,66,143,115,162,172,32,198,176,201,71,122,8,62,175,50,160,91,200,142,24,181,103,59,10,208,0,135,178,105,56,80,47,12,95,236,151,226,240,89,133,135,151,229,61,209,135,134,101,180,224,58,221,90,79,143,207,63,40,51,119,134,16,228,234,227,119,88,82,13,216,237,64,104,191,81,248,161,248,43,240,196,159,151,72,42,48,34,90,79,87,158,226,246,111,73,127,147,8,245,199,125,167,64,213,24,192,252,109,78,208,159,53,43,183,35,141,197,24,150,159,160,127,42,39,25,71,253,186,124,32,65,2,146,143,244,16,247,232,72,168,61,88,20,155,88,63,168,35,182,144,29,49,211,247,161,137,106,207,118,20,15,168,202,172,225,7,127,190,132,96,195,6,210,112,160,94,183,23,28,230,89,184,169,244,60,223,21,76,133,231,194,209,224,128,126,105,14,47,203,123,107,72,119,195,162,15,13,203,199,104,177,115,41,199,4,97,76,160,184,217,245,152,111,68,144,255,211,252,126,80,102,238,27,55,218,86,77,39,185,14,40,64,5,182,198,239,176,164,163,136,12,28,26,176,219,129,127,215,103,57,145,120,210,43,244,31,110,147,3,247,38,59,102,144,154,131,136,63,47,145,237,88,147,41,84,96,68,180,49,7,248,12,223,168,77,30,186,207,241,166,236,223,146,254,137,184,46,70,103,23,155,84,2,112,39,236,187,72,240,113,222,47,76,201,48,128,249,219,85,231,69,99,156,160,63,107,249,199,131,211,23,104,54,193,114,15,138,121,203,55,93,228,174,80,225,92,64,255,84,78,37,152,232,246,115,136,139,174,22,239,55,22,248,64,130,4,157,39,62,188,36,31,233,33,65,120,85,153,175,215,224,139,202,176,92,51,59,182,89,237,94,209,229,85,176,126,80,71,213,25,236,255,108,33,59,98,9,70,135,218,231,233,50,200,130,142,142,112,212,158,237,40,177,249,81,144,95,86,228,130,58,49,88,58,131,9,143,167,230,110,51,31,8,193,134,13,109,166,58,181,164,225,64,189,193,134,252,5,47,41,73,23,74,78,245,175,243,118,34,50,150,17,158,138,120,190,43,152,29,217,151,32,75,201,244,120,46,174,72,192,192,1,253,210,165,102,65,106,28,94,150,247,121,57,42,79,151,150,159,93,242,241,35,229,5,25,107,77,96,126,215,245,142,209,98,231,235,182,222,95,82,142,9,194,55,233,181,122,217,70,0,104,188,33,188,208,234,49,223,136,143,86,99,48,97,249,214,34,4,158,106,154,189,166,189,7,216,193,1,191,54,110,180,173,83,9,8,21,154,78,114,29,255,41,206,165,17,134,123,183,116,225,199,15,205,217,16,146,168,190,172,42,70,17,25,56,35,118,165,128,117,102,198,216,16,1,122,96,254,174,207,114,155,201,115,202,34,241,164,87,71,150,24,239,169,57,173,253,204,94,17,69,6,238,77,118,99,137,241,206,141,38,68,220,232,65,248,100,81,121,47,249,52,30,147,65,218,177,38,83,191,214,154,235,233,198,249,179,140,161,69,11,98,14,240,25,7,105,76,161,190,81,155,60,219,54,39,132,53,153,146,150,80,254,46,46,153,185,84,38,252,222,232,158,18,113,93,140,119,22,225,52,206,46,54,169,171,73,138,17,69,230,63,3,32,129,131,187,118,145,224,227,19,246,92,91,253,89,233,73,152,62,85,241,33,6,130,108,68,97,62,212,170,206,139,198,207,169,55,126,56,65,127,214,93,38,195,110,179,137,118,124,214,238,202,196,111,214,29,89,10,177,161,225,228,30,20,243,129,121,168,75,215,105,203,19,178,14,119,171,92,161,194,185,57,198,126,1,128,254,169,156,229,153,21,36,11,54,160,54,110,81,28,142,167,22,102,134,194,113,218,62,44,222,111,44,73,185,211,148,240,129,4,9,149,230,184,177,123,73,13,163,30,46,177,27,72,62,210,67,45,89,110,251,195,246,219,233,166,145,103,81,31,169,176,204,122,206,12,116,148,97,185,102,241,6,5,222,0,0,0,0,119,7,48,150,238,14,97,44,153,9,81,186,7,109,196,25,112,106,244,143,233,99,165,53,158,100,149,163,14,219,136,50,121,220,184,164,224,213,233,30,151,210,217,136,9,182,76,43,126,177,124,189,231,184,45,7,144,191,29,145,29,183,16,100,106,176,32,242,243,185,113,72,132,190,65,222,26,218,212,125,109,221,228,235,244,212,181,81,131,211,133,199,19,108,152,86,100,107,168,192,253,98,249,122,138,101,201,236,20,1,92,79,99,6,108,217,250,15,61,99,141,8,13,245,59,110,32,200,76,105,16,94,213,96,65,228,162,103,113,114,60,3,228,209,75,4,212,71,210,13,133,253,165,10,181,107,53,181,168,250,66,178,152,108,219,187,201,214,172,188,249,64,50,216,108,227,69,223,92,117,220,214,13,207,171,209,61,89,38,217,48,172,81,222,0,58,200,215,81,128,191,208,97,22,33,180,244,181,86,179,196,35,207,186,149,153,184,189,165,15,40,2,184,158,95,5,136,8,198,12,217,178,177,11,233,36,47,111,124,135,88,104,76,17,193,97,29,171,182,102,45,61,118,220,65,144,1,219,113,6,152,210,32,188,239,213,16,42,113,177,133,137,6,182,181,31,159,191,228,165,232,184,212,51,120,7,201,162,15,0,249,52,150,9,168,142,225,14,152,24,127,106,13,187,8,109,61,45,145,100,108,151,230,99,92,1,107,107,81,244,28,108,97,98,133,101,48,216,242,98,0,78,108,6,149,237,27,1,165,123,130,8,244,193,245,15,196,87,101,176,217,198,18,183,233,80,139,190,184,234,252,185,136,124,98,221,29,223,21,218,45,73,140,211,124,243,251,212,76,101,77,178,97,88,58,181,81,206,163,188,0,116,212,187,48,226,74,223,165,65,61,216,149,215,164,209,196,109,211,214,244,251,67,105,233,106,52,110,217,252,173,103,136,70,218,96,184,208,68,4,45,115,51,3,29,229,170,10,76,95,221,13,124,201,80,5,113,60,39,2,65,170,190,11,16,16,201,12,32,134,87,104,181,37,32,111,133,179,185,102,212,9,206,97,228,159,94,222,249,14,41,217,201,152,176,208,152,34,199,215,168,180,89,179,61,23,46,180,13,129,183,189,92,59,192,186,108,173,237,184,131,32,154,191,179,182,3,182,226,12,116,177,210,154,234,213,71,57,157,210,119,175,4,219,38,21,115,220,22,131,227,99,11,18,148,100,59,132,13,109,106,62,122,106,90,168,228,14,207,11,147,9,255,157,10,0,174,39,125,7,158,177,240,15,147,68,135,8,163,210,30,1,242,104,105,6,194,254,247,98,87,93,128,101,103,203,25,108,54,113,110,107,6,231,254,212,27,118,137,211,43,224,16,218,122,90,103,221,74,204,249,185,223,111,142,190,239,249,23,183,190,67,96,176,142,213,214,214,163,232,161,209,147,126,56,216,194,196,79,223,242,82,209,187,103,241,166,188,87,103,63,181,6,221,72,178,54,75,216,13,43,218,175,10,27,76,54,3,74,246,65,4,122,96,223,96,239,195,168,103,223,85,49,110,142,239,70,105,190,121,203,97,179,140,188,102,131,26,37,111,210,160,82,104,226,54,204,12,119,149,187,11,71,3,34,2,22,185,85,5,38,47,197,186,59,190,178,189,11,40,43,180,90,146,92,179,106,4,194,215,255,167,181,208,207,49,44,217,158,139,91,222,174,29,155,100,194,176,236,99,242,38,117,106,163,156,2,109,147,10,156,9,6,169,235,14,54,63,114,7,103,133,5,0,87,19,149,191,74,130,226,184,122,20,123,177,43,174,12,182,27,56,146,210,142,155,229,213,190,13,124,220,239,183,11,219,223,33,134,211,210,212,241,212,226,66,104,221,179,248,31,218,131,110,129,190,22,205,246,185,38,91,111,176,119,225,24,183,71,119,136,8,90,230,255,15,106,112,102,6,59,202,17,1,11,92,143,101,158,255,248,98,174,105,97,107,255,211,22,108,207,69,160,10,226,120,215,13,210,238,78,4,131,84,57,3,179,194,167,103,38,97,208,96,22,247,73,105,71,77,62,110,119,219,174,209,106,74,217,214,90,220,64,223,11,102,55,216,59,240,169,188,174,83,222,187,158,197,71,178,207,127,48,181,255,233,189,189,242,28,202,186,194,138,83,179,147,48,36,180,163,166,186,208,54,5,205,215,6,147,84,222,87,41,35,217,103,191,179,102,122,46,196,97,74,184,93,104,27,2,42,111,43,148,180,11,190,55,195,12,142,161,90,5,223,27,45,2,239,141,0,0,0,0,25,27,49,65,50,54,98,130,43,45,83,195,100,108,197,4,125,119,244,69,86,90,167,134,79,65,150,199,200,217,138,8,209,194,187,73,250,239,232,138,227,244,217,203,172,181,79,12,181,174,126,77,158,131,45,142,135,152,28,207,74,194,18,81,83,217,35,16,120,244,112,211,97,239,65,146,46,174,215,85,55,181,230,20,28,152,181,215,5,131,132,150,130,27,152,89,155,0,169,24,176,45,250,219,169,54,203,154,230,119,93,93,255,108,108,28,212,65,63,223,205,90,14,158,149,132,36,162,140,159,21,227,167,178,70,32,190,169,119,97,241,232,225,166,232,243,208,231,195,222,131,36,218,197,178,101,93,93,174,170,68,70,159,235,111,107,204,40,118,112,253,105,57,49,107,174,32,42,90,239,11,7,9,44,18,28,56,109,223,70,54,243,198,93,7,178,237,112,84,113,244,107,101,48,187,42,243,247,162,49,194,182,137,28,145,117,144,7,160,52,23,159,188,251,14,132,141,186,37,169,222,121,60,178,239,56,115,243,121,255,106,232,72,190,65,197,27,125,88,222,42,60,240,121,79,5,233,98,126,68,194,79,45,135,219,84,28,198,148,21,138,1,141,14,187,64,166,35,232,131,191,56,217,194,56,160,197,13,33,187,244,76,10,150,167,143,19,141,150,206,92,204,0,9,69,215,49,72,110,250,98,139,119,225,83,202,186,187,93,84,163,160,108,21,136,141,63,214,145,150,14,151,222,215,152,80,199,204,169,17,236,225,250,210,245,250,203,147,114,98,215,92,107,121,230,29,64,84,181,222,89,79,132,159,22,14,18,88,15,21,35,25,36,56,112,218,61,35,65,155,101,253,107,167,124,230,90,230,87,203,9,37,78,208,56,100,1,145,174,163,24,138,159,226,51,167,204,33,42,188,253,96,173,36,225,175,180,63,208,238,159,18,131,45,134,9,178,108,201,72,36,171,208,83,21,234,251,126,70,41,226,101,119,104,47,63,121,246,54,36,72,183,29,9,27,116,4,18,42,53,75,83,188,242,82,72,141,179,121,101,222,112,96,126,239,49,231,230,243,254,254,253,194,191,213,208,145,124,204,203,160,61,131,138,54,250,154,145,7,187,177,188,84,120,168,167,101,57,59,131,152,75,34,152,169,10,9,181,250,201,16,174,203,136,95,239,93,79,70,244,108,14,109,217,63,205,116,194,14,140,243,90,18,67,234,65,35,2,193,108,112,193,216,119,65,128,151,54,215,71,142,45,230,6,165,0,181,197,188,27,132,132,113,65,138,26,104,90,187,91,67,119,232,152,90,108,217,217,21,45,79,30,12,54,126,95,39,27,45,156,62,0,28,221,185,152,0,18,160,131,49,83,139,174,98,144,146,181,83,209,221,244,197,22,196,239,244,87,239,194,167,148,246,217,150,213,174,7,188,233,183,28,141,168,156,49,222,107,133,42,239,42,202,107,121,237,211,112,72,172,248,93,27,111,225,70,42,46,102,222,54,225,127,197,7,160,84,232,84,99,77,243,101,34,2,178,243,229,27,169,194,164,48,132,145,103,41,159,160,38,228,197,174,184,253,222,159,249,214,243,204,58,207,232,253,123,128,169,107,188,153,178,90,253,178,159,9,62,171,132,56,127,44,28,36,176,53,7,21,241,30,42,70,50,7,49,119,115,72,112,225,180,81,107,208,245,122,70,131,54,99,93,178,119,203,250,215,78,210,225,230,15,249,204,181,204,224,215,132,141,175,150,18,74,182,141,35,11,157,160,112,200,132,187,65,137,3,35,93,70,26,56,108,7,49,21,63,196,40,14,14,133,103,79,152,66,126,84,169,3,85,121,250,192,76,98,203,129,129,56,197,31,152,35,244,94,179,14,167,157,170,21,150,220,229,84,0,27,252,79,49,90,215,98,98,153,206,121,83,216,73,225,79,23,80,250,126,86,123,215,45,149,98,204,28,212,45,141,138,19,52,150,187,82,31,187,232,145,6,160,217,208,94,126,243,236,71,101,194,173,108,72,145,110,117,83,160,47,58,18,54,232,35,9,7,169,8,36,84,106,17,63,101,43,150,167,121,228,143,188,72,165,164,145,27,102,189,138,42,39,242,203,188,224,235,208,141,161,192,253,222,98,217,230,239,35,20,188,225,189,13,167,208,252,38,138,131,63,63,145,178,126,112,208,36,185,105,203,21,248,66,230,70,59,91,253,119,122,220,101,107,181,197,126,90,244,238,83,9,55,247,72,56,118,184,9,174,177,161,18,159,240,138,63,204,51,147,36,253,114,0,0,0,0,1,194,106,55,3,132,212,110,2,70,190,89,7,9,168,220,6,203,194,235,4,141,124,178,5,79,22,133,14,19,81,184,15,209,59,143,13,151,133,214,12,85,239,225,9,26,249,100,8,216,147,83,10,158,45,10,11,92,71,61,28,38,163,112,29,228,201,71,31,162,119,30,30,96,29,41,27,47,11,172,26,237,97,155,24,171,223,194,25,105,181,245,18,53,242,200,19,247,152,255,17,177,38,166,16,115,76,145,21,60,90,20,20,254,48,35,22,184,142,122,23,122,228,77,56,77,70,224,57,143,44,215,59,201,146,142,58,11,248,185,63,68,238,60,62,134,132,11,60,192,58,82,61,2,80,101,54,94,23,88,55,156,125,111,53,218,195,54,52,24,169,1,49,87,191,132,48,149,213,179,50,211,107,234,51,17,1,221,36,107,229,144,37,169,143,167,39,239,49,254,38,45,91,201,35,98,77,76,34,160,39,123,32,230,153,34,33,36,243,21,42,120,180,40,43,186,222,31,41,252,96,70,40,62,10,113,45,113,28,244,44,179,118,195,46,245,200,154,47,55,162,173,112,154,141,192,113,88,231,247,115,30,89,174,114,220,51,153,119,147,37,28,118,81,79,43,116,23,241,114,117,213,155,69,126,137,220,120,127,75,182,79,125,13,8,22,124,207,98,33,121,128,116,164,120,66,30,147,122,4,160,202,123,198,202,253,108,188,46,176,109,126,68,135,111,56,250,222,110,250,144,233,107,181,134,108,106,119,236,91,104,49,82,2,105,243,56,53,98,175,127,8,99,109,21,63,97,43,171,102,96,233,193,81,101,166,215,212,100,100,189,227,102,34,3,186,103,224,105,141,72,215,203,32,73,21,161,23,75,83,31,78,74,145,117,121,79,222,99,252,78,28,9,203,76,90,183,146,77,152,221,165,70,196,154,152,71,6,240,175,69,64,78,246,68,130,36,193,65,205,50,68,64,15,88,115,66,73,230,42,67,139,140,29,84,241,104,80,85,51,2,103,87,117,188,62,86,183,214,9,83,248,192,140,82,58,170,187,80,124,20,226,81,190,126,213,90,226,57,232,91,32,83,223,89,102,237,134,88,164,135,177,93,235,145,52,92,41,251,3,94,111,69,90,95,173,47,109,225,53,27,128,224,247,113,183,226,177,207,238,227,115,165,217,230,60,179,92,231,254,217,107,229,184,103,50,228,122,13,5,239,38,74,56,238,228,32,15,236,162,158,86,237,96,244,97,232,47,226,228,233,237,136,211,235,171,54,138,234,105,92,189,253,19,184,240,252,209,210,199,254,151,108,158,255,85,6,169,250,26,16,44,251,216,122,27,249,158,196,66,248,92,174,117,243,0,233,72,242,194,131,127,240,132,61,38,241,70,87,17,244,9,65,148,245,203,43,163,247,141,149,250,246,79,255,205,217,120,93,96,216,186,55,87,218,252,137,14,219,62,227,57,222,113,245,188,223,179,159,139,221,245,33,210,220,55,75,229,215,107,12,216,214,169,102,239,212,239,216,182,213,45,178,129,208,98,164,4,209,160,206,51,211,230,112,106,210,36,26,93,197,94,254,16,196,156,148,39,198,218,42,126,199,24,64,73,194,87,86,204,195,149,60,251,193,211,130,162,192,17,232,149,203,77,175,168,202,143,197,159,200,201,123,198,201,11,17,241,204,68,7,116,205,134,109,67,207,192,211,26,206,2,185,45,145,175,150,64,144,109,252,119,146,43,66,46,147,233,40,25,150,166,62,156,151,100,84,171,149,34,234,242,148,224,128,197,159,188,199,248,158,126,173,207,156,56,19,150,157,250,121,161,152,181,111,36,153,119,5,19,155,49,187,74,154,243,209,125,141,137,53,48,140,75,95,7,142,13,225,94,143,207,139,105,138,128,157,236,139,66,247,219,137,4,73,130,136,198,35,181,131,154,100,136,130,88,14,191,128,30,176,230,129,220,218,209,132,147,204,84,133,81,166,99,135,23,24,58,134,213,114,13,169,226,208,160,168,32,186,151,170,102,4,206,171,164,110,249,174,235,120,124,175,41,18,75,173,111,172,18,172,173,198,37,167,241,129,24,166,51,235,47,164,117,85,118,165,183,63,65,160,248,41,196,161,58,67,243,163,124,253,170,162,190,151,157,181,196,115,208,180,6,25,231,182,64,167,190,183,130,205,137,178,205,219,12,179,15,177,59,177,73,15,98,176,139,101,85,187,215,34,104,186,21,72,95,184,83,246,6,185,145,156,49,188,222,138,180,189,28,224,131,191,90,94,218,190,152,52,237,0,0,0,0,184,188,103,101,170,9,200,139,18,181,175,238,143,98,151,87,55,222,240,50,37,107,95,220,157,215,56,185,197,180,40,239,125,8,79,138,111,189,224,100,215,1,135,1,74,214,191,184,242,106,216,221,224,223,119,51,88,99,16,86,80,25,87,159,232,165,48,250,250,16,159,20,66,172,248,113,223,123,192,200,103,199,167,173,117,114,8,67,205,206,111,38,149,173,127,112,45,17,24,21,63,164,183,251,135,24,208,158,26,207,232,39,162,115,143,66,176,198,32,172,8,122,71,201,160,50,175,62,24,142,200,91,10,59,103,181,178,135,0,208,47,80,56,105,151,236,95,12,133,89,240,226,61,229,151,135,101,134,135,209,221,58,224,180,207,143,79,90,119,51,40,63,234,228,16,134,82,88,119,227,64,237,216,13,248,81,191,104,240,43,248,161,72,151,159,196,90,34,48,42,226,158,87,79,127,73,111,246,199,245,8,147,213,64,167,125,109,252,192,24,53,159,208,78,141,35,183,43,159,150,24,197,39,42,127,160,186,253,71,25,2,65,32,124,16,244,143,146,168,72,232,247,155,20,88,61,35,168,63,88,49,29,144,182,137,161,247,211,20,118,207,106,172,202,168,15,190,127,7,225,6,195,96,132,94,160,112,210,230,28,23,183,244,169,184,89,76,21,223,60,209,194,231,133,105,126,128,224,123,203,47,14,195,119,72,107,203,13,15,162,115,177,104,199,97,4,199,41,217,184,160,76,68,111,152,245,252,211,255,144,238,102,80,126,86,218,55,27,14,185,39,77,182,5,64,40,164,176,239,198,28,12,136,163,129,219,176,26,57,103,215,127,43,210,120,145,147,110,31,244,59,38,247,3,131,154,144,102,145,47,63,136,41,147,88,237,180,68,96,84,12,248,7,49,30,77,168,223,166,241,207,186,254,146,223,236,70,46,184,137,84,155,23,103,236,39,112,2,113,240,72,187,201,76,47,222,219,249,128,48,99,69,231,85], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+10336); +/* memory initializer */ allocate([107,63,160,156,211,131,199,249,193,54,104,23,121,138,15,114,228,93,55,203,92,225,80,174,78,84,255,64,246,232,152,37,174,139,136,115,22,55,239,22,4,130,64,248,188,62,39,157,33,233,31,36,153,85,120,65,139,224,215,175,51,92,176,202,237,89,182,59,85,229,209,94,71,80,126,176,255,236,25,213,98,59,33,108,218,135,70,9,200,50,233,231,112,142,142,130,40,237,158,212,144,81,249,177,130,228,86,95,58,88,49,58,167,143,9,131,31,51,110,230,13,134,193,8,181,58,166,109,189,64,225,164,5,252,134,193,23,73,41,47,175,245,78,74,50,34,118,243,138,158,17,150,152,43,190,120,32,151,217,29,120,244,201,75,192,72,174,46,210,253,1,192,106,65,102,165,247,150,94,28,79,42,57,121,93,159,150,151,229,35,241,242,77,107,25,5,245,215,126,96,231,98,209,142,95,222,182,235,194,9,142,82,122,181,233,55,104,0,70,217,208,188,33,188,136,223,49,234,48,99,86,143,34,214,249,97,154,106,158,4,7,189,166,189,191,1,193,216,173,180,110,54,21,8,9,83,29,114,78,154,165,206,41,255,183,123,134,17,15,199,225,116,146,16,217,205,42,172,190,168,56,25,17,70,128,165,118,35,216,198,102,117,96,122,1,16,114,207,174,254,202,115,201,155,87,164,241,34,239,24,150,71,253,173,57,169,69,17,94,204,118,77,238,6,206,241,137,99,220,68,38,141,100,248,65,232,249,47,121,81,65,147,30,52,83,38,177,218,235,154,214,191,179,249,198,233,11,69,161,140,25,240,14,98,161,76,105,7,60,155,81,190,132,39,54,219,150,146,153,53,46,46,254,80,38,84,185,153,158,232,222,252,140,93,113,18,52,225,22,119,169,54,46,206,17,138,73,171,3,63,230,69,187,131,129,32,227,224,145,118,91,92,246,19,73,233,89,253,241,85,62,152,108,130,6,33,212,62,97,68,198,139,206,170,126,55,169,207,214,127,65,56,110,195,38,93,124,118,137,179,196,202,238,214,89,29,214,111,225,161,177,10,243,20,30,228,75,168,121,129,19,203,105,215,171,119,14,178,185,194,161,92,1,126,198,57,156,169,254,128,36,21,153,229,54,160,54,11,142,28,81,110,134,102,22,167,62,218,113,194,44,111,222,44,148,211,185,73,9,4,129,240,177,184,230,149,163,13,73,123,27,177,46,30,67,210,62,72,251,110,89,45,233,219,246,195,81,103,145,166,204,176,169,31,116,12,206,122,102,185,97,148,222,5,6,241,0,0,0,0,0,0,0,0,1,0,0,0,4,0,4,0,8,0,4,0,2,0,0,0,4,0,5,0,16,0,8,0,2,0,0,0,4,0,6,0,32,0,32,0,2,0,0,0,4,0,4,0,16,0,16,0,3,0,0,0,8,0,16,0,32,0,32,0,3,0,0,0,8,0,16,0,128,0,128,0,3,0,0,0,8,0,32,0,128,0,0,1,3,0,0,0,32,0,128,0,2,1,0,4,3,0,0,0,32,0,2,1,2,1,0,16,3,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,58,32,0,0,0,0,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,49,46,50,46,53,0,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,117,110,101,120,112,101,99,116,101,100,32,101,110,100,32,111,102,32,102,105,108,101,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,105,110,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,99,111,109,112,114,101,115,115,101,100,32,100,97,116,97,32,101,114,114,111,114,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,100,101,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,49,46,50,46,53,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,16,0,17,0,18,0,0,0,8,0,7,0,9,0,6,0,10,0,5,0,11,0,4,0,12,0,3,0,13,0,2,0,14,0,1,0,15,0,0,0,105,110,99,111,114,114,101,99,116,32,104,101,97,100,101,114,32,99,104,101,99,107,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,105,110,118,97,108,105,100,32,119,105,110,100,111,119,32,115,105,122,101,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,104,101,97,100,101,114,32,99,114,99,32,109,105,115,109,97,116,99,104,0,0,0,0,0,105,110,118,97,108,105,100,32,98,108,111,99,107,32,116,121,112,101,0,0,0,0,0,0,105,110,118,97,108,105,100,32,115,116,111,114,101,100,32,98,108,111,99,107,32,108,101,110,103,116,104,115,0,0,0,0,116,111,111,32,109,97,110,121,32,108,101,110,103,116,104,32,111,114,32,100,105,115,116,97,110,99,101,32,115,121,109,98,111,108,115,0,0,0,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,0,0,0,105,110,118,97,108,105,100,32,98,105,116,32,108,101,110,103,116,104,32,114,101,112,101,97,116,0,0,0,0,0,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,45,45,32,109,105,115,115,105,110,103,32,101,110,100,45,111,102,45,98,108,111,99,107,0,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,115,32,115,101,116,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,192,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,160,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,224,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,144,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,208,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,176,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,240,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,200,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,168,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,232,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,152,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,216,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,184,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,248,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,196,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,164,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,228,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,148,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,212,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,180,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,244,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,204,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,172,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,236,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,156,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,220,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,188,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,252,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,194,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,162,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,226,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,146,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,210,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,178,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,242,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,202,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,170,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,234,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,154,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,218,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,186,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,250,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,198,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,166,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,230,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,150,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,214,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,182,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,246,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,206,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,174,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,238,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,158,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,222,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,190,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,254,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,193,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,161,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,225,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,145,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,209,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,177,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,241,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,201,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,169,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,233,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,153,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,217,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,185,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,249,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,197,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,165,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,229,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,149,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,213,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,181,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,245,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,205,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,173,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,237,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,157,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,221,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,189,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,253,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,195,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,163,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,227,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,147,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,211,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,179,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,243,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,203,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,171,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,235,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,155,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,219,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,187,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,251,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,199,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,167,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,231,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,151,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,215,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,183,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,247,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,207,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,175,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,239,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,159,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,223,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,191,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,255,0,16,5,1,0,23,5,1,1,19,5,17,0,27,5,1,16,17,5,5,0,25,5,1,4,21,5,65,0,29,5,1,64,16,5,3,0,24,5,1,2,20,5,33,0,28,5,1,32,18,5,9,0,26,5,1,8,22,5,129,0,64,5,0,0,16,5,2,0,23,5,129,1,19,5,25,0,27,5,1,24,17,5,7,0,25,5,1,6,21,5,97,0,29,5,1,96,16,5,4,0,24,5,1,3,20,5,49,0,28,5,1,48,18,5,13,0,26,5,1,12,22,5,193,0,64,5,0,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,13,0,15,0,17,0,19,0,23,0,27,0,31,0,35,0,43,0,51,0,59,0,67,0,83,0,99,0,115,0,131,0,163,0,195,0,227,0,2,1,0,0,0,0,0,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,17,0,17,0,17,0,17,0,18,0,18,0,18,0,18,0,19,0,19,0,19,0,19,0,20,0,20,0,20,0,20,0,21,0,21,0,21,0,21,0,16,0,73,0,195,0,0,0,1,0,2,0,3,0,4,0,5,0,7,0,9,0,13,0,17,0,25,0,33,0,49,0,65,0,97,0,129,0,193,0,1,1,129,1,1,2,1,3,1,4,1,6,1,8,1,12,1,16,1,24,1,32,1,48,1,64,1,96,0,0,0,0,16,0,16,0,16,0,16,0,17,0,17,0,18,0,18,0,19,0,19,0,20,0,20,0,21,0,21,0,22,0,22,0,23,0,23,0,24,0,24,0,25,0,25,0,26,0,26,0,27,0,27,0,28,0,28,0,29,0,29,0,64,0,64,0,0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,0,100,0,0,248,104,0,0,1,1,0,0,30,1,0,0,15,0,0,0,0,0,0,0,128,104,0,0,232,105,0,0,0,0,0,0,30,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,240,106,0,0,0,0,0,0,19,0,0,0,7,0,0,0,0,0,0,0,12,0,8,0,140,0,8,0,76,0,8,0,204,0,8,0,44,0,8,0,172,0,8,0,108,0,8,0,236,0,8,0,28,0,8,0,156,0,8,0,92,0,8,0,220,0,8,0,60,0,8,0,188,0,8,0,124,0,8,0,252,0,8,0,2,0,8,0,130,0,8,0,66,0,8,0,194,0,8,0,34,0,8,0,162,0,8,0,98,0,8,0,226,0,8,0,18,0,8,0,146,0,8,0,82,0,8,0,210,0,8,0,50,0,8,0,178,0,8,0,114,0,8,0,242,0,8,0,10,0,8,0,138,0,8,0,74,0,8,0,202,0,8,0,42,0,8,0,170,0,8,0,106,0,8,0,234,0,8,0,26,0,8,0,154,0,8,0,90,0,8,0,218,0,8,0,58,0,8,0,186,0,8,0,122,0,8,0,250,0,8,0,6,0,8,0,134,0,8,0,70,0,8,0,198,0,8,0,38,0,8,0,166,0,8,0,102,0,8,0,230,0,8,0,22,0,8,0,150,0,8,0,86,0,8,0,214,0,8,0,54,0,8,0,182,0,8,0,118,0,8,0,246,0,8,0,14,0,8,0,142,0,8,0,78,0,8,0,206,0,8,0,46,0,8,0,174,0,8,0,110,0,8,0,238,0,8,0,30,0,8,0,158,0,8,0,94,0,8,0,222,0,8,0,62,0,8,0,190,0,8,0,126,0,8,0,254,0,8,0,1,0,8,0,129,0,8,0,65,0,8,0,193,0,8,0,33,0,8,0,161,0,8,0,97,0,8,0,225,0,8,0,17,0,8,0,145,0,8,0,81,0,8,0,209,0,8,0,49,0,8,0,177,0,8,0,113,0,8,0,241,0,8,0,9,0,8,0,137,0,8,0,73,0,8,0,201,0,8,0,41,0,8,0,169,0,8,0,105,0,8,0,233,0,8,0,25,0,8,0,153,0,8,0,89,0,8,0,217,0,8,0,57,0,8,0,185,0,8,0,121,0,8,0,249,0,8,0,5,0,8,0,133,0,8,0,69,0,8,0,197,0,8,0,37,0,8,0,165,0,8,0,101,0,8,0,229,0,8,0,21,0,8,0,149,0,8,0,85,0,8,0,213,0,8,0,53,0,8,0,181,0,8,0,117,0,8,0,245,0,8,0,13,0,8,0,141,0,8,0,77,0,8,0,205,0,8,0,45,0,8,0,173,0,8,0,109,0,8,0,237,0,8,0,29,0,8,0,157,0,8,0,93,0,8,0,221,0,8,0,61,0,8,0,189,0,8,0,125,0,8,0,253,0,8,0,19,0,9,0,19,1,9,0,147,0,9,0,147,1,9,0,83,0,9,0,83,1,9,0,211,0,9,0,211,1,9,0,51,0,9,0,51,1,9,0,179,0,9,0,179,1,9,0,115,0,9,0,115,1,9,0,243,0,9,0,243,1,9,0,11,0,9,0,11,1,9,0,139,0,9,0,139,1,9,0,75,0,9,0,75,1,9,0,203,0,9,0,203,1,9,0,43,0,9,0,43,1,9,0,171,0,9,0,171,1,9,0,107,0,9,0,107,1,9,0,235,0,9,0,235,1,9,0,27,0,9,0,27,1,9,0,155,0,9,0,155,1,9,0,91,0,9,0,91,1,9,0,219,0,9,0,219,1,9,0,59,0,9,0,59,1,9,0,187,0,9,0,187,1,9,0,123,0,9,0,123,1,9,0,251,0,9,0,251,1,9,0,7,0,9,0,7,1,9,0,135,0,9,0,135,1,9,0,71,0,9,0,71,1,9,0,199,0,9,0,199,1,9,0,39,0,9,0,39,1,9,0,167,0,9,0,167,1,9,0,103,0,9,0,103,1,9,0,231,0,9,0,231,1,9,0,23,0,9,0,23,1,9,0,151,0,9,0,151,1,9,0,87,0,9,0,87,1,9,0,215,0,9,0,215,1,9,0,55,0,9,0,55,1,9,0,183,0,9,0,183,1,9,0,119,0,9,0,119,1,9,0,247,0,9,0,247,1,9,0,15,0,9,0,15,1,9,0,143,0,9,0,143,1,9,0,79,0,9,0,79,1,9,0,207,0,9,0,207,1,9,0,47,0,9,0,47,1,9,0,175,0,9,0,175,1,9,0,111,0,9,0,111,1,9,0,239,0,9,0,239,1,9,0,31,0,9,0,31,1,9,0,159,0,9,0,159,1,9,0,95,0,9,0,95,1,9,0,223,0,9,0,223,1,9,0,63,0,9,0,63,1,9,0,191,0,9,0,191,1,9,0,127,0,9,0,127,1,9,0,255,0,9,0,255,1,9,0,0,0,7,0,64,0,7,0,32,0,7,0,96,0,7,0,16,0,7,0,80,0,7,0,48,0,7,0,112,0,7,0,8,0,7,0,72,0,7,0,40,0,7,0,104,0,7,0,24,0,7,0,88,0,7,0,56,0,7,0,120,0,7,0,4,0,7,0,68,0,7,0,36,0,7,0,100,0,7,0,20,0,7,0,84,0,7,0,52,0,7,0,116,0,7,0,3,0,8,0,131,0,8,0,67,0,8,0,195,0,8,0,35,0,8,0,163,0,8,0,99,0,8,0,227,0,8,0,0,0,5,0,16,0,5,0,8,0,5,0,24,0,5,0,4,0,5,0,20,0,5,0,12,0,5,0,28,0,5,0,2,0,5,0,18,0,5,0,10,0,5,0,26,0,5,0,6,0,5,0,22,0,5,0,14,0,5,0,30,0,5,0,1,0,5,0,17,0,5,0,9,0,5,0,25,0,5,0,5,0,5,0,21,0,5,0,13,0,5,0,29,0,5,0,3,0,5,0,19,0,5,0,11,0,5,0,27,0,5,0,7,0,5,0,23,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,8,0,0,0,10,0,0,0,12,0,0,0,14,0,0,0,16,0,0,0,20,0,0,0,24,0,0,0,28,0,0,0,32,0,0,0,40,0,0,0,48,0,0,0,56,0,0,0,64,0,0,0,80,0,0,0,96,0,0,0,112,0,0,0,128,0,0,0,160,0,0,0,192,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,6,0,0,0,6,0,0,0,7,0,0,0,7,0,0,0,8,0,0,0,8,0,0,0,9,0,0,0,9,0,0,0,10,0,0,0,10,0,0,0,11,0,0,0,11,0,0,0,12,0,0,0,12,0,0,0,13,0,0,0,13,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,0,128,0,0,0,192,0,0,0,0,1,0,0,128,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,7,0,0,0,0,0,0,0,110,101,101,100,32,100,105,99,116,105,111,110,97,114,121,0,115,116,114,101,97,109,32,101,110,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,105,108,101,32,101,114,114,111,114,0,0,0,0,0,0,115,116,114,101,97,109,32,101,114,114,111,114,0,0,0,0,100,97,116,97,32,101,114,114,111,114,0,0,0,0,0,0,105,110,115,117,102,102,105,99,105,101,110,116,32,109,101,109,111,114,121,0,0,0,0,0,98,117,102,102,101,114,32,101,114,114,111,114,0,0,0,0,105,110,99,111,109,112,97,116,105,98,108,101,32,118,101,114,115,105,111,110,0,0,0,0,64,107,0,0,80,107,0,0,96,107,0,0,104,107,0,0,120,107,0,0,136,107,0,0,152,107,0,0,176,107,0,0,192,107,0,0,96,107,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,105,110,102,105,110,105,116,121,0,0,0,0,0,0,0,0,110,97,110,0,0,0,0,0,95,112,137,0,255,9,47,15,10,0,0,0,100,0,0,0,232,3,0,0,16,39,0,0,160,134,1,0,64,66,15,0,128,150,152,0,0,225,245,5], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+20576); + + + + +var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8); + +assert(tempDoublePtr % 8 == 0); + +function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much + + HEAP8[tempDoublePtr] = HEAP8[ptr]; + + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + +} + +function copyTempDouble(ptr) { + + HEAP8[tempDoublePtr] = HEAP8[ptr]; + + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + + HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; + + HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; + + HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; + + HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; + +} + + + + + var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86}; + + var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"}; + + + var ___errno_state=0;function ___setErrNo(value) { + // For convenient setting and returning of errno. + HEAP32[((___errno_state)>>2)]=value; + return value; + } + + var PATH={splitPath:function (filename) { + var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + return splitPathRe.exec(filename).slice(1); + },normalizeArray:function (parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + 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 the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + return parts; + },normalize:function (path) { + var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.substr(-1) === '/'; + // Normalize the path + path = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), !isAbsolute).join('/'); + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + return (isAbsolute ? '/' : '') + path; + },dirname:function (path) { + var result = PATH.splitPath(path), + root = result[0], + dir = result[1]; + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + return root + dir; + },basename:function (path) { + // EMSCRIPTEN return '/'' for '/', not an empty string + if (path === '/') return '/'; + var lastSlash = path.lastIndexOf('/'); + if (lastSlash === -1) return path; + return path.substr(lastSlash+1); + },extname:function (path) { + return PATH.splitPath(path)[3]; + },join:function () { + var paths = Array.prototype.slice.call(arguments, 0); + return PATH.normalize(paths.join('/')); + },join2:function (l, r) { + return PATH.normalize(l + '/' + r); + },resolve:function () { + var resolvedPath = '', + resolvedAbsolute = false; + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : FS.cwd(); + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + },relative:function (from, to) { + from = PATH.resolve(from).substr(1); + to = PATH.resolve(to).substr(1); + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + var end = arr.length - 1; + for (; end >= 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 < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + return outputParts.join('/'); + }}; + + var TTY={ttys:[],init:function () { + // https://github.com/kripken/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // currently, FS.init does not distinguish if process.stdin is a file or TTY + // // device, it always assumes it's a TTY device. because of this, we're forcing + // // process.stdin to UTF8 encoding to at least make stdin reading compatible + // // with text files until FS.init can be refactored. + // process['stdin']['setEncoding']('utf8'); + // } + },shutdown:function () { + // https://github.com/kripken/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? + // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation + // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists? + // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle + // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call + // process['stdin']['pause'](); + // } + },register:function (dev, ops) { + TTY.ttys[dev] = { input: [], output: [], ops: ops }; + FS.registerDevice(dev, TTY.stream_ops); + },stream_ops:{open:function (stream) { + var tty = TTY.ttys[stream.node.rdev]; + if (!tty) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + stream.tty = tty; + stream.seekable = false; + },close:function (stream) { + // flush any pending line data + if (stream.tty.output.length) { + stream.tty.ops.put_char(stream.tty, 10); + } + },read:function (stream, buffer, offset, length, pos /* ignored */) { + if (!stream.tty || !stream.tty.ops.get_char) { + throw new FS.ErrnoError(ERRNO_CODES.ENXIO); + } + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = stream.tty.ops.get_char(stream.tty); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + },write:function (stream, buffer, offset, length, pos) { + if (!stream.tty || !stream.tty.ops.put_char) { + throw new FS.ErrnoError(ERRNO_CODES.ENXIO); + } + for (var i = 0; i < length; i++) { + try { + stream.tty.ops.put_char(stream.tty, buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + }},default_tty_ops:{get_char:function (tty) { + if (!tty.input.length) { + var result = null; + if (ENVIRONMENT_IS_NODE) { + result = process['stdin']['read'](); + if (!result) { + if (process['stdin']['_readableState'] && process['stdin']['_readableState']['ended']) { + return null; // EOF + } + return undefined; // no data available + } + } else if (typeof window != 'undefined' && + typeof window.prompt == 'function') { + // Browser. + result = window.prompt('Input: '); // returns null on cancel + if (result !== null) { + result += '\n'; + } + } else if (typeof readline == 'function') { + // Command line. + result = readline(); + if (result !== null) { + result += '\n'; + } + } + if (!result) { + return null; + } + tty.input = intArrayFromString(result, true); + } + return tty.input.shift(); + },put_char:function (tty, val) { + if (val === null || val === 10) { + Module['print'](tty.output.join('')); + tty.output = []; + } else { + tty.output.push(TTY.utf8.processCChar(val)); + } + }},default_tty1_ops:{put_char:function (tty, val) { + if (val === null || val === 10) { + Module['printErr'](tty.output.join('')); + tty.output = []; + } else { + tty.output.push(TTY.utf8.processCChar(val)); + } + }}}; + + var MEMFS={ops_table:null,CONTENT_OWNING:1,CONTENT_FLEXIBLE:2,CONTENT_FIXED:3,mount:function (mount) { + return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + },createNode:function (parent, name, mode, dev) { + if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { + // no supported + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (!MEMFS.ops_table) { + 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, + allocate: MEMFS.stream_ops.allocate, + mmap: MEMFS.stream_ops.mmap + } + }, + 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.contents = []; + node.contentMode = MEMFS.CONTENT_FLEXIBLE; + } 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.timestamp = Date.now(); + // add the new node to the parent + if (parent) { + parent.contents[name] = node; + } + return node; + },ensureFlexible:function (node) { + if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) { + var contents = node.contents; + node.contents = Array.prototype.slice.call(contents); + node.contentMode = MEMFS.CONTENT_FLEXIBLE; + } + },node_ops:{getattr:function (node) { + var attr = {}; + // device numbers reuse inode numbers. + 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.contents.length; + } else if (FS.isLink(node.mode)) { + attr.size = node.link.length; + } else { + attr.size = 0; + } + attr.atime = new Date(node.timestamp); + attr.mtime = new Date(node.timestamp); + attr.ctime = new Date(node.timestamp); + // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), + // but this is not required by the standard. + attr.blksize = 4096; + attr.blocks = Math.ceil(attr.size / attr.blksize); + return attr; + },setattr:function (node, attr) { + if (attr.mode !== undefined) { + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + node.timestamp = attr.timestamp; + } + if (attr.size !== undefined) { + MEMFS.ensureFlexible(node); + var contents = node.contents; + if (attr.size < contents.length) contents.length = attr.size; + else while (attr.size > contents.length) contents.push(0); + } + },lookup:function (parent, name) { + throw FS.genericErrors[ERRNO_CODES.ENOENT]; + },mknod:function (parent, name, mode, dev) { + return MEMFS.createNode(parent, name, mode, dev); + },rename:function (old_node, new_dir, new_name) { + // if we're overwriting a directory at new_name, make sure it's empty. + if (FS.isDir(old_node.mode)) { + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + } + if (new_node) { + for (var i in new_node.contents) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + } + } + // do the internal rewiring + delete old_node.parent.contents[old_node.name]; + old_node.name = new_name; + new_dir.contents[new_name] = old_node; + old_node.parent = new_dir; + },unlink:function (parent, name) { + delete parent.contents[name]; + },rmdir:function (parent, name) { + var node = FS.lookupNode(parent, name); + for (var i in node.contents) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + delete parent.contents[name]; + },readdir:function (node) { + var entries = ['.', '..'] + for (var key in node.contents) { + if (!node.contents.hasOwnProperty(key)) { + continue; + } + entries.push(key); + } + return entries; + },symlink:function (parent, newname, oldpath) { + var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0); + node.link = oldpath; + return node; + },readlink:function (node) { + if (!FS.isLink(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + return node.link; + }},stream_ops:{read:function (stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (size > 8 && contents.subarray) { // non-trivial, and typed array + buffer.set(contents.subarray(position, position + size), offset); + } else + { + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } + return size; + },write:function (stream, buffer, offset, length, position, canOwn) { + var node = stream.node; + node.timestamp = Date.now(); + var contents = node.contents; + if (length && contents.length === 0 && position === 0 && buffer.subarray) { + // just replace it with the new data + if (canOwn && offset === 0) { + node.contents = buffer; // this could be a subarray of Emscripten HEAP, or allocated from some other source. + node.contentMode = (buffer.buffer === HEAP8.buffer) ? MEMFS.CONTENT_OWNING : MEMFS.CONTENT_FIXED; + } else { + node.contents = new Uint8Array(buffer.subarray(offset, offset+length)); + node.contentMode = MEMFS.CONTENT_FIXED; + } + return length; + } + MEMFS.ensureFlexible(node); + var contents = node.contents; + while (contents.length < position) contents.push(0); + for (var i = 0; i < length; i++) { + contents[position + i] = buffer[offset + i]; + } + return length; + },llseek:function (stream, offset, whence) { + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + if (FS.isFile(stream.node.mode)) { + position += stream.node.contents.length; + } + } + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + stream.ungotten = []; + stream.position = position; + return position; + },allocate:function (stream, offset, length) { + MEMFS.ensureFlexible(stream.node); + var contents = stream.node.contents; + var limit = offset + length; + while (limit > contents.length) contents.push(0); + },mmap:function (stream, buffer, offset, length, position, prot, flags) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + var ptr; + var allocated; + var contents = stream.node.contents; + // Only make a new copy when MAP_PRIVATE is specified. + if ( !(flags & 2) && + (contents.buffer === buffer || contents.buffer === buffer.buffer) ) { + // We can't emulate MAP_SHARED when the file is not backed by the buffer + // we're mapping to (e.g. the HEAP buffer). + allocated = false; + ptr = contents.byteOffset; + } else { + // Try to avoid unnecessary slices. + if (position > 0 || position + length < contents.length) { + if (contents.subarray) { + contents = contents.subarray(position, position + length); + } else { + contents = Array.prototype.slice.call(contents, position, position + length); + } + } + allocated = true; + ptr = _malloc(length); + if (!ptr) { + throw new FS.ErrnoError(ERRNO_CODES.ENOMEM); + } + buffer.set(contents, ptr); + } + return { ptr: ptr, allocated: allocated }; + }}}; + + var IDBFS={dbs:{},indexedDB:function () { + return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + },DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:function (mount) { + // reuse all of the core MEMFS functionality + return MEMFS.mount.apply(null, arguments); + },syncfs:function (mount, populate, callback) { + IDBFS.getLocalSet(mount, function(err, local) { + if (err) return callback(err); + + IDBFS.getRemoteSet(mount, function(err, remote) { + if (err) return callback(err); + + var src = populate ? remote : local; + var dst = populate ? local : remote; + + IDBFS.reconcile(src, dst, callback); + }); + }); + },getDB:function (name, callback) { + // check the cache first + var db = IDBFS.dbs[name]; + if (db) { + return callback(null, db); + } + + var req; + try { + req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION); + } catch (e) { + return callback(e); + } + req.onupgradeneeded = function(e) { + var db = e.target.result; + var transaction = e.target.transaction; + + var fileStore; + + if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) { + fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME); + } else { + fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME); + } + + fileStore.createIndex('timestamp', 'timestamp', { unique: false }); + }; + req.onsuccess = function() { + db = req.result; + + // add to the cache + IDBFS.dbs[name] = db; + callback(null, db); + }; + req.onerror = function() { + callback(this.error); + }; + },getLocalSet:function (mount, callback) { + var entries = {}; + + function isRealDir(p) { + return p !== '.' && p !== '..'; + }; + function toAbsolute(root) { + return function(p) { + return PATH.join2(root, p); + } + }; + + var check = FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint)); + + while (check.length) { + var path = check.pop(); + var stat; + + try { + stat = FS.stat(path); + } catch (e) { + return callback(e); + } + + if (FS.isDir(stat.mode)) { + check.push.apply(check, FS.readdir(path).filter(isRealDir).map(toAbsolute(path))); + } + + entries[path] = { timestamp: stat.mtime }; + } + + return callback(null, { type: 'local', entries: entries }); + },getRemoteSet:function (mount, callback) { + var entries = {}; + + IDBFS.getDB(mount.mountpoint, function(err, db) { + if (err) return callback(err); + + var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readonly'); + transaction.onerror = function() { callback(this.error); }; + + var store = transaction.objectStore(IDBFS.DB_STORE_NAME); + var index = store.index('timestamp'); + + index.openKeyCursor().onsuccess = function(event) { + var cursor = event.target.result; + + if (!cursor) { + return callback(null, { type: 'remote', db: db, entries: entries }); + } + + entries[cursor.primaryKey] = { timestamp: cursor.key }; + + cursor.continue(); + }; + }); + },loadLocalEntry:function (path, callback) { + var stat, node; + + try { + var lookup = FS.lookupPath(path); + node = lookup.node; + stat = FS.stat(path); + } catch (e) { + return callback(e); + } + + if (FS.isDir(stat.mode)) { + return callback(null, { timestamp: stat.mtime, mode: stat.mode }); + } else if (FS.isFile(stat.mode)) { + return callback(null, { timestamp: stat.mtime, mode: stat.mode, contents: node.contents }); + } else { + return callback(new Error('node type not supported')); + } + },storeLocalEntry:function (path, entry, callback) { + try { + if (FS.isDir(entry.mode)) { + FS.mkdir(path, entry.mode); + } else if (FS.isFile(entry.mode)) { + FS.writeFile(path, entry.contents, { encoding: 'binary', canOwn: true }); + } else { + return callback(new Error('node type not supported')); + } + + FS.utime(path, entry.timestamp, entry.timestamp); + } catch (e) { + return callback(e); + } + + callback(null); + },removeLocalEntry:function (path, callback) { + try { + var lookup = FS.lookupPath(path); + var stat = FS.stat(path); + + if (FS.isDir(stat.mode)) { + FS.rmdir(path); + } else if (FS.isFile(stat.mode)) { + FS.unlink(path); + } + } catch (e) { + return callback(e); + } + + callback(null); + },loadRemoteEntry:function (store, path, callback) { + var req = store.get(path); + req.onsuccess = function(event) { callback(null, event.target.result); }; + req.onerror = function() { callback(this.error); }; + },storeRemoteEntry:function (store, path, entry, callback) { + var req = store.put(entry, path); + req.onsuccess = function() { callback(null); }; + req.onerror = function() { callback(this.error); }; + },removeRemoteEntry:function (store, path, callback) { + var req = store.delete(path); + req.onsuccess = function() { callback(null); }; + req.onerror = function() { callback(this.error); }; + },reconcile:function (src, dst, callback) { + var total = 0; + + var create = []; + Object.keys(src.entries).forEach(function (key) { + var e = src.entries[key]; + var e2 = dst.entries[key]; + if (!e2 || e.timestamp > e2.timestamp) { + create.push(key); + total++; + } + }); + + var remove = []; + Object.keys(dst.entries).forEach(function (key) { + var e = dst.entries[key]; + var e2 = src.entries[key]; + if (!e2) { + remove.push(key); + total++; + } + }); + + if (!total) { + return callback(null); + } + + var errored = false; + var completed = 0; + var db = src.type === 'remote' ? src.db : dst.db; + var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite'); + var store = transaction.objectStore(IDBFS.DB_STORE_NAME); + + function done(err) { + if (err) { + if (!done.errored) { + done.errored = true; + return callback(err); + } + return; + } + if (++completed >= total) { + return callback(null); + } + }; + + transaction.onerror = function() { done(this.error); }; + + // sort paths in ascending order so directory entries are created + // before the files inside them + create.sort().forEach(function (path) { + if (dst.type === 'local') { + IDBFS.loadRemoteEntry(store, path, function (err, entry) { + if (err) return done(err); + IDBFS.storeLocalEntry(path, entry, done); + }); + } else { + IDBFS.loadLocalEntry(path, function (err, entry) { + if (err) return done(err); + IDBFS.storeRemoteEntry(store, path, entry, done); + }); + } + }); + + // sort paths in descending order so files are deleted before their + // parent directories + remove.sort().reverse().forEach(function(path) { + if (dst.type === 'local') { + IDBFS.removeLocalEntry(path, done); + } else { + IDBFS.removeRemoteEntry(store, path, done); + } + }); + }}; + + var NODEFS={isWindows:false,staticInit:function () { + NODEFS.isWindows = !!process.platform.match(/^win/); + },mount:function (mount) { + assert(ENVIRONMENT_IS_NODE); + return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0); + },createNode:function (parent, name, mode, dev) { + if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node = FS.createNode(parent, name, mode); + node.node_ops = NODEFS.node_ops; + node.stream_ops = NODEFS.stream_ops; + return node; + },getMode:function (path) { + var stat; + try { + stat = fs.lstatSync(path); + if (NODEFS.isWindows) { + // On Windows, directories return permission bits 'rw-rw-rw-', even though they have 'rwxrwxrwx', so + // propagate write bits to execute bits. + stat.mode = stat.mode | ((stat.mode & 146) >> 1); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return stat.mode; + },realPath:function (node) { + var parts = []; + while (node.parent !== node) { + parts.push(node.name); + node = node.parent; + } + parts.push(node.mount.opts.root); + parts.reverse(); + return PATH.join.apply(null, parts); + },flagsToPermissionStringMap:{0:"r",1:"r+",2:"r+",64:"r",65:"r+",66:"r+",129:"rx+",193:"rx+",514:"w+",577:"w",578:"w+",705:"wx",706:"wx+",1024:"a",1025:"a",1026:"a+",1089:"a",1090:"a+",1153:"ax",1154:"ax+",1217:"ax",1218:"ax+",4096:"rs",4098:"rs+"},flagsToPermissionString:function (flags) { + if (flags in NODEFS.flagsToPermissionStringMap) { + return NODEFS.flagsToPermissionStringMap[flags]; + } else { + return flags; + } + },node_ops:{getattr:function (node) { + var path = NODEFS.realPath(node); + var stat; + try { + stat = fs.lstatSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + // node.js v0.10.20 doesn't report blksize and blocks on Windows. Fake them with default blksize of 4096. + // See http://support.microsoft.com/kb/140365 + if (NODEFS.isWindows && !stat.blksize) { + stat.blksize = 4096; + } + if (NODEFS.isWindows && !stat.blocks) { + stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0; + } + return { + dev: stat.dev, + ino: stat.ino, + mode: stat.mode, + nlink: stat.nlink, + uid: stat.uid, + gid: stat.gid, + rdev: stat.rdev, + size: stat.size, + atime: stat.atime, + mtime: stat.mtime, + ctime: stat.ctime, + blksize: stat.blksize, + blocks: stat.blocks + }; + },setattr:function (node, attr) { + var path = NODEFS.realPath(node); + try { + if (attr.mode !== undefined) { + fs.chmodSync(path, attr.mode); + // update the common node structure mode as well + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + var date = new Date(attr.timestamp); + fs.utimesSync(path, date, date); + } + if (attr.size !== undefined) { + fs.truncateSync(path, attr.size); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },lookup:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + var mode = NODEFS.getMode(path); + return NODEFS.createNode(parent, name, mode); + },mknod:function (parent, name, mode, dev) { + var node = NODEFS.createNode(parent, name, mode, dev); + // create the backing node for this in the fs root as well + var path = NODEFS.realPath(node); + try { + if (FS.isDir(node.mode)) { + fs.mkdirSync(path, node.mode); + } else { + fs.writeFileSync(path, '', { mode: node.mode }); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return node; + },rename:function (oldNode, newDir, newName) { + var oldPath = NODEFS.realPath(oldNode); + var newPath = PATH.join2(NODEFS.realPath(newDir), newName); + try { + fs.renameSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },unlink:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.unlinkSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },rmdir:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.rmdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },readdir:function (node) { + var path = NODEFS.realPath(node); + try { + return fs.readdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },symlink:function (parent, newName, oldPath) { + var newPath = PATH.join2(NODEFS.realPath(parent), newName); + try { + fs.symlinkSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },readlink:function (node) { + var path = NODEFS.realPath(node); + try { + return fs.readlinkSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }},stream_ops:{open:function (stream) { + var path = NODEFS.realPath(stream.node); + try { + if (FS.isFile(stream.node.mode)) { + stream.nfd = fs.openSync(path, NODEFS.flagsToPermissionString(stream.flags)); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },close:function (stream) { + try { + if (FS.isFile(stream.node.mode) && stream.nfd) { + fs.closeSync(stream.nfd); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },read:function (stream, buffer, offset, length, position) { + // FIXME this is terrible. + var nbuffer = new Buffer(length); + var res; + try { + res = fs.readSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + if (res > 0) { + for (var i = 0; i < res; i++) { + buffer[offset + i] = nbuffer[i]; + } + } + return res; + },write:function (stream, buffer, offset, length, position) { + // FIXME this is terrible. + var nbuffer = new Buffer(buffer.subarray(offset, offset + length)); + var res; + try { + res = fs.writeSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return res; + },llseek:function (stream, offset, whence) { + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + if (FS.isFile(stream.node.mode)) { + try { + var stat = fs.fstatSync(stream.nfd); + position += stat.size; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + } + } + + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + stream.position = position; + return position; + }}}; + + var _stdin=allocate(1, "i32*", ALLOC_STATIC); + + var _stdout=allocate(1, "i32*", ALLOC_STATIC); + + var _stderr=allocate(1, "i32*", ALLOC_STATIC); + + function _fflush(stream) { + // int fflush(FILE *stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fflush.html + // we don't currently perform any user-space buffering of data + }var FS={root:null,mounts:[],devices:[null],streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},handleFSError:function (e) { + if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace(); + return ___setErrNo(e.errno); + },lookupPath:function (path, opts) { + path = PATH.resolve(FS.cwd(), path); + opts = opts || {}; + + var defaults = { + follow_mount: true, + recurse_count: 0 + }; + for (var key in defaults) { + if (opts[key] === undefined) { + opts[key] = defaults[key]; + } + } + + if (opts.recurse_count > 8) { // max recursive lookup of 8 + throw new FS.ErrnoError(ERRNO_CODES.ELOOP); + } + + // split the path + var parts = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), false); + + // start at the root + var current = FS.root; + var current_path = '/'; + + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + // stop resolving + break; + } + + current = FS.lookupNode(current, parts[i]); + current_path = PATH.join2(current_path, parts[i]); + + // jump to the mount's root node if this is a mountpoint + if (FS.isMountpoint(current)) { + if (!islast || (islast && opts.follow_mount)) { + current = current.mounted.root; + } + } + + // by default, lookupPath will not follow a symlink if it is the final path component. + // setting opts.follow = true will override this behavior. + if (!islast || opts.follow) { + var count = 0; + while (FS.isLink(current.mode)) { + var link = FS.readlink(current_path); + current_path = PATH.resolve(PATH.dirname(current_path), link); + + var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count }); + current = lookup.node; + + if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX). + throw new FS.ErrnoError(ERRNO_CODES.ELOOP); + } + } + } + } + + return { path: current_path, node: current }; + },getPath:function (node) { + var path; + while (true) { + if (FS.isRoot(node)) { + var mount = node.mount.mountpoint; + if (!path) return mount; + return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path; + } + path = path ? node.name + '/' + path : node.name; + node = node.parent; + } + },hashName:function (parentid, name) { + var hash = 0; + + + for (var i = 0; i < name.length; i++) { + hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; + } + return ((parentid + hash) >>> 0) % FS.nameTable.length; + },hashAddNode:function (node) { + var hash = FS.hashName(node.parent.id, node.name); + node.name_next = FS.nameTable[hash]; + FS.nameTable[hash] = node; + },hashRemoveNode:function (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:function (parent, name) { + var err = FS.mayLookup(parent); + if (err) { + throw new FS.ErrnoError(err); + } + 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; + } + } + // if we failed to find it in the cache, call into the VFS + return FS.lookup(parent, name); + },createNode:function (parent, name, mode, rdev) { + if (!FS.FSNode) { + FS.FSNode = function(parent, name, mode, rdev) { + if (!parent) { + parent = this; // root node sets parent to itself + } + this.parent = parent; + this.mount = parent.mount; + this.mounted = null; + this.id = FS.nextInode++; + this.name = name; + this.mode = mode; + this.node_ops = {}; + this.stream_ops = {}; + this.rdev = rdev; + }; + + FS.FSNode.prototype = {}; + + // compatibility + var readMode = 292 | 73; + var writeMode = 146; + + // NOTE we must use Object.defineProperties instead of individual calls to + // Object.defineProperty in order to make closure compiler happy + Object.defineProperties(FS.FSNode.prototype, { + read: { + get: function() { return (this.mode & readMode) === readMode; }, + set: function(val) { val ? this.mode |= readMode : this.mode &= ~readMode; } + }, + write: { + get: function() { return (this.mode & writeMode) === writeMode; }, + set: function(val) { val ? this.mode |= writeMode : this.mode &= ~writeMode; } + }, + isFolder: { + get: function() { return FS.isDir(this.mode); }, + }, + isDevice: { + get: function() { return FS.isChrdev(this.mode); }, + }, + }); + } + + var node = new FS.FSNode(parent, name, mode, rdev); + + FS.hashAddNode(node); + + return node; + },destroyNode:function (node) { + FS.hashRemoveNode(node); + },isRoot:function (node) { + return node === node.parent; + },isMountpoint:function (node) { + return !!node.mounted; + },isFile:function (mode) { + return (mode & 61440) === 32768; + },isDir:function (mode) { + return (mode & 61440) === 16384; + },isLink:function (mode) { + return (mode & 61440) === 40960; + },isChrdev:function (mode) { + return (mode & 61440) === 8192; + },isBlkdev:function (mode) { + return (mode & 61440) === 24576; + },isFIFO:function (mode) { + return (mode & 61440) === 4096; + },isSocket:function (mode) { + return (mode & 49152) === 49152; + },flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function (str) { + var flags = FS.flagModes[str]; + if (typeof flags === 'undefined') { + throw new Error('Unknown file open mode: ' + str); + } + return flags; + },flagsToPermissionString:function (flag) { + var accmode = flag & 2097155; + var perms = ['r', 'w', 'rw'][accmode]; + if ((flag & 512)) { + perms += 'w'; + } + return perms; + },nodePermissions:function (node, perms) { + if (FS.ignorePermissions) { + return 0; + } + // return 0 if any user, group or owner bits are set. + if (perms.indexOf('r') !== -1 && !(node.mode & 292)) { + return ERRNO_CODES.EACCES; + } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) { + return ERRNO_CODES.EACCES; + } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) { + return ERRNO_CODES.EACCES; + } + return 0; + },mayLookup:function (dir) { + return FS.nodePermissions(dir, 'x'); + },mayCreate:function (dir, name) { + try { + var node = FS.lookupNode(dir, name); + return ERRNO_CODES.EEXIST; + } catch (e) { + } + return FS.nodePermissions(dir, 'wx'); + },mayDelete:function (dir, name, isdir) { + var node; + try { + node = FS.lookupNode(dir, name); + } catch (e) { + return e.errno; + } + var err = FS.nodePermissions(dir, 'wx'); + if (err) { + return err; + } + if (isdir) { + if (!FS.isDir(node.mode)) { + return ERRNO_CODES.ENOTDIR; + } + if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { + return ERRNO_CODES.EBUSY; + } + } else { + if (FS.isDir(node.mode)) { + return ERRNO_CODES.EISDIR; + } + } + return 0; + },mayOpen:function (node, flags) { + if (!node) { + return ERRNO_CODES.ENOENT; + } + if (FS.isLink(node.mode)) { + return ERRNO_CODES.ELOOP; + } else if (FS.isDir(node.mode)) { + if ((flags & 2097155) !== 0 || // opening for write + (flags & 512)) { + return ERRNO_CODES.EISDIR; + } + } + return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); + },MAX_OPEN_FDS:4096,nextfd:function (fd_start, fd_end) { + fd_start = fd_start || 0; + fd_end = fd_end || FS.MAX_OPEN_FDS; + for (var fd = fd_start; fd <= fd_end; fd++) { + if (!FS.streams[fd]) { + return fd; + } + } + throw new FS.ErrnoError(ERRNO_CODES.EMFILE); + },getStream:function (fd) { + return FS.streams[fd]; + },createStream:function (stream, fd_start, fd_end) { + if (!FS.FSStream) { + FS.FSStream = function(){}; + FS.FSStream.prototype = {}; + // compatibility + Object.defineProperties(FS.FSStream.prototype, { + object: { + get: function() { return this.node; }, + set: function(val) { this.node = val; } + }, + isRead: { + get: function() { return (this.flags & 2097155) !== 1; } + }, + isWrite: { + get: function() { return (this.flags & 2097155) !== 0; } + }, + isAppend: { + get: function() { return (this.flags & 1024); } + } + }); + } + // clone it, so we can return an instance of FSStream + var newStream = new FS.FSStream(); + for (var p in stream) { + newStream[p] = stream[p]; + } + stream = newStream; + var fd = FS.nextfd(fd_start, fd_end); + stream.fd = fd; + FS.streams[fd] = stream; + return stream; + },closeStream:function (fd) { + FS.streams[fd] = null; + },getStreamFromPtr:function (ptr) { + return FS.streams[ptr - 1]; + },getPtrForStream:function (stream) { + return stream ? stream.fd + 1 : 0; + },chrdev_stream_ops:{open:function (stream) { + var device = FS.getDevice(stream.node.rdev); + // override node's stream ops with the device's + stream.stream_ops = device.stream_ops; + // forward the open call + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + },llseek:function () { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + }},major:function (dev) { + return ((dev) >> 8); + },minor:function (dev) { + return ((dev) & 0xff); + },makedev:function (ma, mi) { + return ((ma) << 8 | (mi)); + },registerDevice:function (dev, ops) { + FS.devices[dev] = { stream_ops: ops }; + },getDevice:function (dev) { + return FS.devices[dev]; + },getMounts:function (mount) { + var mounts = []; + var check = [mount]; + + while (check.length) { + var m = check.pop(); + + mounts.push(m); + + check.push.apply(check, m.mounts); + } + + return mounts; + },syncfs:function (populate, callback) { + if (typeof(populate) === 'function') { + callback = populate; + populate = false; + } + + var mounts = FS.getMounts(FS.root.mount); + var completed = 0; + + function done(err) { + if (err) { + if (!done.errored) { + done.errored = true; + return callback(err); + } + return; + } + if (++completed >= mounts.length) { + callback(null); + } + }; + + // sync all mounts + mounts.forEach(function (mount) { + if (!mount.type.syncfs) { + return done(null); + } + mount.type.syncfs(mount, populate, done); + }); + },mount:function (type, opts, mountpoint) { + var root = mountpoint === '/'; + var pseudo = !mountpoint; + var node; + + if (root && FS.root) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } else if (!root && !pseudo) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + mountpoint = lookup.path; // use the absolute path + node = lookup.node; + + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + + if (!FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + } + + var mount = { + type: type, + opts: opts, + mountpoint: mountpoint, + mounts: [] + }; + + // create a root node for the fs + var mountRoot = type.mount(mount); + mountRoot.mount = mount; + mount.root = mountRoot; + + if (root) { + FS.root = mountRoot; + } else if (node) { + // set as a mountpoint + node.mounted = mount; + + // add the new mount to the current mount's children + if (node.mount) { + node.mount.mounts.push(mount); + } + } + + return mountRoot; + },unmount:function (mountpoint) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + if (!FS.isMountpoint(lookup.node)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + // destroy the nodes for this mount, and all its child mounts + var node = lookup.node; + var mount = node.mounted; + var mounts = FS.getMounts(mount); + + Object.keys(FS.nameTable).forEach(function (hash) { + var current = FS.nameTable[hash]; + + while (current) { + var next = current.name_next; + + if (mounts.indexOf(current.mount) !== -1) { + FS.destroyNode(current); + } + + current = next; + } + }); + + // no longer a mountpoint + node.mounted = null; + + // remove this mount from the child mounts + var idx = node.mount.mounts.indexOf(mount); + assert(idx !== -1); + node.mount.mounts.splice(idx, 1); + },lookup:function (parent, name) { + return parent.node_ops.lookup(parent, name); + },mknod:function (path, mode, dev) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var err = FS.mayCreate(parent, name); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.mknod) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return parent.node_ops.mknod(parent, name, mode, dev); + },create:function (path, mode) { + mode = mode !== undefined ? mode : 438 /* 0666 */; + mode &= 4095; + mode |= 32768; + return FS.mknod(path, mode, 0); + },mkdir:function (path, mode) { + mode = mode !== undefined ? mode : 511 /* 0777 */; + mode &= 511 | 512; + mode |= 16384; + return FS.mknod(path, mode, 0); + },mkdev:function (path, mode, dev) { + if (typeof(dev) === 'undefined') { + dev = mode; + mode = 438 /* 0666 */; + } + mode |= 8192; + return FS.mknod(path, mode, dev); + },symlink:function (oldpath, newpath) { + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + var newname = PATH.basename(newpath); + var err = FS.mayCreate(parent, newname); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.symlink) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return parent.node_ops.symlink(parent, newname, oldpath); + },rename:function (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); + // parents must exist + var lookup, old_dir, new_dir; + try { + lookup = FS.lookupPath(old_path, { parent: true }); + old_dir = lookup.node; + lookup = FS.lookupPath(new_path, { parent: true }); + new_dir = lookup.node; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + // need to be part of the same mount + if (old_dir.mount !== new_dir.mount) { + throw new FS.ErrnoError(ERRNO_CODES.EXDEV); + } + // source must exist + var old_node = FS.lookupNode(old_dir, old_name); + // old path should not be an ancestor of the new path + var relative = PATH.relative(old_path, new_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + // new path should not be an ancestor of the old path + relative = PATH.relative(new_path, old_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + // see if the new path already exists + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + // not fatal + } + // early out if nothing needs to change + if (old_node === new_node) { + return; + } + // we'll need to delete the old entry + var isdir = FS.isDir(old_node.mode); + var err = FS.mayDelete(old_dir, old_name, isdir); + if (err) { + throw new FS.ErrnoError(err); + } + // need delete permissions if we'll be overwriting. + // need create permissions if new doesn't already exist. + err = new_node ? + FS.mayDelete(new_dir, new_name, isdir) : + FS.mayCreate(new_dir, new_name); + if (err) { + throw new FS.ErrnoError(err); + } + if (!old_dir.node_ops.rename) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + // if we are going to change the parent, check write permissions + if (new_dir !== old_dir) { + err = FS.nodePermissions(old_dir, 'w'); + if (err) { + throw new FS.ErrnoError(err); + } + } + // remove the node from the lookup hash + FS.hashRemoveNode(old_node); + // do the underlying fs rename + try { + old_dir.node_ops.rename(old_node, new_dir, new_name); + } catch (e) { + throw e; + } finally { + // add the node back to the hash (in case node_ops.rename + // changed its name) + FS.hashAddNode(old_node); + } + },rmdir:function (path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var err = FS.mayDelete(parent, name, true); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.rmdir) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + parent.node_ops.rmdir(parent, name); + FS.destroyNode(node); + },readdir:function (path) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node.node_ops.readdir) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + return node.node_ops.readdir(node); + },unlink:function (path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var err = FS.mayDelete(parent, name, false); + if (err) { + // POSIX says unlink should set EPERM, not EISDIR + if (err === ERRNO_CODES.EISDIR) err = ERRNO_CODES.EPERM; + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.unlink) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + parent.node_ops.unlink(parent, name); + FS.destroyNode(node); + },readlink:function (path) { + var lookup = FS.lookupPath(path); + var link = lookup.node; + if (!link.node_ops.readlink) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + return link.node_ops.readlink(link); + },stat:function (path, dontFollow) { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var node = lookup.node; + if (!node.node_ops.getattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return node.node_ops.getattr(node); + },lstat:function (path) { + return FS.stat(path, true); + },chmod:function (path, mode, dontFollow) { + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + node.node_ops.setattr(node, { + mode: (mode & 4095) | (node.mode & ~4095), + timestamp: Date.now() + }); + },lchmod:function (path, mode) { + FS.chmod(path, mode, true); + },fchmod:function (fd, mode) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + FS.chmod(stream.node, mode); + },chown:function (path, uid, gid, dontFollow) { + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + node.node_ops.setattr(node, { + timestamp: Date.now() + // we ignore the uid / gid for now + }); + },lchown:function (path, uid, gid) { + FS.chown(path, uid, gid, true); + },fchown:function (fd, uid, gid) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + FS.chown(stream.node, uid, gid); + },truncate:function (path, len) { + if (len < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: true }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!FS.isFile(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var err = FS.nodePermissions(node, 'w'); + if (err) { + throw new FS.ErrnoError(err); + } + node.node_ops.setattr(node, { + size: len, + timestamp: Date.now() + }); + },ftruncate:function (fd, len) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + FS.truncate(stream.node, len); + },utime:function (path, atime, mtime) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + node.node_ops.setattr(node, { + timestamp: Math.max(atime, mtime) + }); + },open:function (path, flags, mode, fd_start, fd_end) { + flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags; + mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode; + if ((flags & 64)) { + mode = (mode & 4095) | 32768; + } else { + mode = 0; + } + var node; + if (typeof path === 'object') { + node = path; + } else { + path = PATH.normalize(path); + try { + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072) + }); + node = lookup.node; + } catch (e) { + // ignore + } + } + // perhaps we need to create the node + if ((flags & 64)) { + if (node) { + // if O_CREAT and O_EXCL are set, error out if the node already exists + if ((flags & 128)) { + throw new FS.ErrnoError(ERRNO_CODES.EEXIST); + } + } else { + // node doesn't exist, try to create it + node = FS.mknod(path, mode, 0); + } + } + if (!node) { + throw new FS.ErrnoError(ERRNO_CODES.ENOENT); + } + // can't truncate a device + if (FS.isChrdev(node.mode)) { + flags &= ~512; + } + // check permissions + var err = FS.mayOpen(node, flags); + if (err) { + throw new FS.ErrnoError(err); + } + // do truncation if necessary + if ((flags & 512)) { + FS.truncate(node, 0); + } + // we've already handled these, don't pass down to the underlying vfs + flags &= ~(128 | 512); + + // register the stream with the filesystem + var stream = FS.createStream({ + node: node, + path: FS.getPath(node), // we want the absolute path to the node + flags: flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + // used by the file family libc calls (fopen, fwrite, ferror, etc.) + ungotten: [], + error: false + }, fd_start, fd_end); + // call the new stream's open function + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + if (Module['logReadFiles'] && !(flags & 1)) { + if (!FS.readFiles) FS.readFiles = {}; + if (!(path in FS.readFiles)) { + FS.readFiles[path] = 1; + Module['printErr']('read file: ' + path); + } + } + return stream; + },close:function (stream) { + try { + if (stream.stream_ops.close) { + stream.stream_ops.close(stream); + } + } catch (e) { + throw e; + } finally { + FS.closeStream(stream.fd); + } + },llseek:function (stream, offset, whence) { + if (!stream.seekable || !stream.stream_ops.llseek) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + return stream.stream_ops.llseek(stream, offset, whence); + },read:function (stream, buffer, offset, length, position) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!stream.stream_ops.read) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var seeking = true; + if (typeof position === 'undefined') { + position = stream.position; + seeking = false; + } else if (!stream.seekable) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); + if (!seeking) stream.position += bytesRead; + return bytesRead; + },write:function (stream, buffer, offset, length, position, canOwn) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!stream.stream_ops.write) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var seeking = true; + if (typeof position === 'undefined') { + position = stream.position; + seeking = false; + } else if (!stream.seekable) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + if (stream.flags & 1024) { + // seek to the end before writing in append mode + FS.llseek(stream, 0, 2); + } + var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); + if (!seeking) stream.position += bytesWritten; + return bytesWritten; + },allocate:function (stream, offset, length) { + if (offset < 0 || length <= 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (!FS.isFile(stream.node.mode) && !FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + if (!stream.stream_ops.allocate) { + throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP); + } + stream.stream_ops.allocate(stream, offset, length); + },mmap:function (stream, buffer, offset, length, position, prot, flags) { + // TODO if PROT is PROT_WRITE, make sure we have write access + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(ERRNO_CODES.EACCES); + } + if (!stream.stream_ops.mmap) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + return stream.stream_ops.mmap(stream, buffer, offset, length, position, prot, flags); + },ioctl:function (stream, cmd, arg) { + if (!stream.stream_ops.ioctl) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTTY); + } + return stream.stream_ops.ioctl(stream, cmd, arg); + },readFile:function (path, opts) { + opts = opts || {}; + opts.flags = opts.flags || 'r'; + opts.encoding = opts.encoding || 'binary'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error('Invalid encoding type "' + opts.encoding + '"'); + } + var ret; + 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') { + ret = ''; + var utf8 = new Runtime.UTF8Processor(); + for (var i = 0; i < length; i++) { + ret += utf8.processCChar(buf[i]); + } + } else if (opts.encoding === 'binary') { + ret = buf; + } + FS.close(stream); + return ret; + },writeFile:function (path, data, opts) { + opts = opts || {}; + opts.flags = opts.flags || 'w'; + opts.encoding = opts.encoding || 'utf8'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error('Invalid encoding type "' + opts.encoding + '"'); + } + var stream = FS.open(path, opts.flags, opts.mode); + if (opts.encoding === 'utf8') { + var utf8 = new Runtime.UTF8Processor(); + var buf = new Uint8Array(utf8.processJSString(data)); + FS.write(stream, buf, 0, buf.length, 0, opts.canOwn); + } else if (opts.encoding === 'binary') { + FS.write(stream, data, 0, data.length, 0, opts.canOwn); + } + FS.close(stream); + },cwd:function () { + return FS.currentPath; + },chdir:function (path) { + var lookup = FS.lookupPath(path, { follow: true }); + if (!FS.isDir(lookup.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + var err = FS.nodePermissions(lookup.node, 'x'); + if (err) { + throw new FS.ErrnoError(err); + } + FS.currentPath = lookup.path; + },createDefaultDirectories:function () { + FS.mkdir('/tmp'); + },createDefaultDevices:function () { + // create /dev + FS.mkdir('/dev'); + // setup /dev/null + FS.registerDevice(FS.makedev(1, 3), { + read: function() { return 0; }, + write: function() { return 0; } + }); + FS.mkdev('/dev/null', FS.makedev(1, 3)); + // setup /dev/tty and /dev/tty1 + // stderr needs to print output using Module['printErr'] + // so we register a second tty just for it. + 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)); + // we're not going to emulate the actual shm device, + // just create the tmp dirs that reside in it commonly + FS.mkdir('/dev/shm'); + FS.mkdir('/dev/shm/tmp'); + },createStandardStreams:function () { + // TODO deprecate the old functionality of a single + // input / output callback and that utilizes FS.createDevice + // and instead require a unique set of stream ops + + // by default, we symlink the standard streams to the + // default tty devices. however, if the standard streams + // have been overwritten we create a unique device for + // them instead. + if (Module['stdin']) { + FS.createDevice('/dev', 'stdin', Module['stdin']); + } else { + FS.symlink('/dev/tty', '/dev/stdin'); + } + if (Module['stdout']) { + FS.createDevice('/dev', 'stdout', null, Module['stdout']); + } else { + FS.symlink('/dev/tty', '/dev/stdout'); + } + if (Module['stderr']) { + FS.createDevice('/dev', 'stderr', null, Module['stderr']); + } else { + FS.symlink('/dev/tty1', '/dev/stderr'); + } + + // open default streams for the stdin, stdout and stderr devices + var stdin = FS.open('/dev/stdin', 'r'); + HEAP32[((_stdin)>>2)]=FS.getPtrForStream(stdin); + assert(stdin.fd === 0, 'invalid handle for stdin (' + stdin.fd + ')'); + + var stdout = FS.open('/dev/stdout', 'w'); + HEAP32[((_stdout)>>2)]=FS.getPtrForStream(stdout); + assert(stdout.fd === 1, 'invalid handle for stdout (' + stdout.fd + ')'); + + var stderr = FS.open('/dev/stderr', 'w'); + HEAP32[((_stderr)>>2)]=FS.getPtrForStream(stderr); + assert(stderr.fd === 2, 'invalid handle for stderr (' + stderr.fd + ')'); + },ensureErrnoError:function () { + if (FS.ErrnoError) return; + FS.ErrnoError = function ErrnoError(errno) { + this.errno = errno; + for (var key in ERRNO_CODES) { + if (ERRNO_CODES[key] === errno) { + this.code = key; + break; + } + } + this.message = ERRNO_MESSAGES[errno]; + }; + FS.ErrnoError.prototype = new Error(); + FS.ErrnoError.prototype.constructor = FS.ErrnoError; + // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info) + [ERRNO_CODES.ENOENT].forEach(function(code) { + FS.genericErrors[code] = new FS.ErrnoError(code); + FS.genericErrors[code].stack = ''; + }); + },staticInit:function () { + FS.ensureErrnoError(); + + FS.nameTable = new Array(4096); + + FS.mount(MEMFS, {}, '/'); + + FS.createDefaultDirectories(); + FS.createDefaultDevices(); + },init:function (input, output, error) { + assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); + FS.init.initialized = true; + + FS.ensureErrnoError(); + + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + Module['stdin'] = input || Module['stdin']; + Module['stdout'] = output || Module['stdout']; + Module['stderr'] = error || Module['stderr']; + + FS.createStandardStreams(); + },quit:function () { + FS.init.initialized = false; + for (var i = 0; i < FS.streams.length; i++) { + var stream = FS.streams[i]; + if (!stream) { + continue; + } + FS.close(stream); + } + },getMode:function (canRead, canWrite) { + var mode = 0; + if (canRead) mode |= 292 | 73; + if (canWrite) mode |= 146; + return mode; + },joinPath:function (parts, forceRelative) { + var path = PATH.join.apply(null, parts); + if (forceRelative && path[0] == '/') path = path.substr(1); + return path; + },absolutePath:function (relative, base) { + return PATH.resolve(base, relative); + },standardizePath:function (path) { + return PATH.normalize(path); + },findObject:function (path, dontResolveLastLink) { + var ret = FS.analyzePath(path, dontResolveLastLink); + if (ret.exists) { + return ret.object; + } else { + ___setErrNo(ret.error); + return null; + } + },analyzePath:function (path, dontResolveLastLink) { + // operate from within the context of the symlink's target + 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; + },createFolder:function (parent, name, canRead, canWrite) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var mode = FS.getMode(canRead, canWrite); + return FS.mkdir(path, mode); + },createPath:function (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) { + // ignore EEXIST + } + parent = current; + } + return current; + },createFile:function (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:function (parent, name, data, canRead, canWrite, canOwn) { + var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(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; i < len; ++i) arr[i] = data.charCodeAt(i); + data = arr; + } + // make sure we can write to the file + FS.chmod(node, mode | 146); + var stream = FS.open(node, 'w'); + FS.write(stream, data, 0, data.length, 0, canOwn); + FS.close(stream); + FS.chmod(node, mode); + } + return node; + },createDevice:function (parent, name, input, output) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var mode = FS.getMode(!!input, !!output); + if (!FS.createDevice.major) FS.createDevice.major = 64; + var dev = FS.makedev(FS.createDevice.major++, 0); + // Create a fake device that a set of stream ops to emulate + // the old behavior. + FS.registerDevice(dev, { + open: function(stream) { + stream.seekable = false; + }, + close: function(stream) { + // flush any pending line data + if (output && output.buffer && output.buffer.length) { + output(10); + } + }, + read: function(stream, buffer, offset, length, pos /* ignored */) { + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = input(); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + }, + write: function(stream, buffer, offset, length, pos) { + for (var i = 0; i < length; i++) { + try { + output(buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + } + }); + return FS.mkdev(path, mode, dev); + },createLink:function (parent, name, target, canRead, canWrite) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + return FS.symlink(target, path); + },forceLoadFile:function (obj) { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + var success = true; + if (typeof XMLHttpRequest !== 'undefined') { + throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else if (Module['read']) { + // Command-line. + try { + // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as + // read() will try to parse UTF8. + obj.contents = intArrayFromString(Module['read'](obj.url), true); + } catch (e) { + success = false; + } + } else { + throw new Error('Cannot load without read() or XMLHttpRequest.'); + } + if (!success) ___setErrNo(ERRNO_CODES.EIO); + return success; + },createLazyFile:function (parent, name, url, canRead, canWrite) { + // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. + function LazyUint8Array() { + this.lengthKnown = false; + this.chunks = []; // Loaded chunks. Index is the chunk number + } + LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = Math.floor(idx / this.chunkSize); + return this.getter(chunkNum)[chunkOffset]; + } + LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) { + this.getter = getter; + } + LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("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 chunkSize = 1024*1024; // Chunk size in bytes + + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (function(from, to) { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + if (typeof Uint8Array != 'undefined') 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)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(xhr.response || []); + } else { + return intArrayFromString(xhr.responseText || '', true); + } + }); + var lazyArray = this; + lazyArray.setDataGetter(function(chunkNum) { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); + return lazyArray.chunks[chunkNum]; + }); + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } + if (typeof XMLHttpRequest !== 'undefined') { + if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; + var lazyArray = new LazyUint8Array(); + Object.defineProperty(lazyArray, "length", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + }); + Object.defineProperty(lazyArray, "chunkSize", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + }); + + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + + var node = FS.createFile(parent, name, properties, canRead, canWrite); + // This is a total hack, but I want to get this lazy file code out of the + // core of MEMFS. If we want to keep this lazy file concept I feel it should + // be its own thin LAZYFS proxying calls to MEMFS. + if (properties.contents) { + node.contents = properties.contents; + } else if (properties.url) { + node.contents = null; + node.url = properties.url; + } + // override each stream op with one that tries to force load the lazy file first + var stream_ops = {}; + var keys = Object.keys(node.stream_ops); + keys.forEach(function(key) { + var fn = node.stream_ops[key]; + stream_ops[key] = function forceLoadLazyFile() { + if (!FS.forceLoadFile(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + return fn.apply(null, arguments); + }; + }); + // use a custom read function + stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) { + if (!FS.forceLoadFile(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (contents.slice) { // normal array + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } else { + for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR + buffer[offset + i] = contents.get(position + i); + } + } + return size; + }; + node.stream_ops = stream_ops; + return node; + },createPreloadedFile:function (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn) { + Browser.init(); + // TODO we should allow people to just pass in a complete filename instead + // of parent and name being that we just join them anyways + var fullname = name ? PATH.resolve(PATH.join2(parent, name)) : parent; + function processData(byteArray) { + function finish(byteArray) { + if (!dontCreateFile) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + } + if (onload) onload(); + removeRunDependency('cp ' + fullname); + } + var handled = false; + Module['preloadPlugins'].forEach(function(plugin) { + if (handled) return; + if (plugin['canHandle'](fullname)) { + plugin['handle'](byteArray, fullname, finish, function() { + if (onerror) onerror(); + removeRunDependency('cp ' + fullname); + }); + handled = true; + } + }); + if (!handled) finish(byteArray); + } + addRunDependency('cp ' + fullname); + if (typeof url == 'string') { + Browser.asyncLoad(url, function(byteArray) { + processData(byteArray); + }, onerror); + } else { + processData(url); + } + },indexedDB:function () { + return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + },DB_NAME:function () { + return 'EM_FS_' + window.location.pathname; + },DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function (paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = function openRequest_onupgradeneeded() { + console.log('creating db'); + var db = openRequest.result; + db.createObjectStore(FS.DB_STORE_NAME); + }; + openRequest.onsuccess = function openRequest_onsuccess() { + var db = openRequest.result; + var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite'); + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var putRequest = files.put(FS.analyzePath(path).object.contents, path); + putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) finish() }; + putRequest.onerror = function putRequest_onerror() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + },loadFilesFromDB:function (paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = onerror; // no database to load from + openRequest.onsuccess = function openRequest_onsuccess() { + var db = openRequest.result; + try { + var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly'); + } catch(e) { + onerror(e); + return; + } + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var getRequest = files.get(path); + getRequest.onsuccess = function getRequest_onsuccess() { + if (FS.analyzePath(path).exists) { + FS.unlink(path); + } + FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true); + ok++; + if (ok + fail == total) finish(); + }; + getRequest.onerror = function getRequest_onerror() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + }};function _lseek(fildes, offset, whence) { + // off_t lseek(int fildes, off_t offset, int whence); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/lseek.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + return FS.llseek(stream, offset, whence); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + + Module["_i64Subtract"] = _i64Subtract; + + var _fabsf=Math_abs; + + + + + Module["_strlen"] = _strlen; + + function __reallyNegative(x) { + return x < 0 || (x === 0 && (1/x) === -Infinity); + }function __formatString(format, varargs) { + var textIndex = format; + var argIndex = 0; + function getNextArg(type) { + // NOTE: Explicitly ignoring type safety. Otherwise this fails: + // int x = 4; printf("%c\n", (char)x); + var ret; + if (type === 'double') { + ret = (HEAP32[((tempDoublePtr)>>2)]=HEAP32[(((varargs)+(argIndex))>>2)],HEAP32[(((tempDoublePtr)+(4))>>2)]=HEAP32[(((varargs)+((argIndex)+(4)))>>2)],(+(HEAPF64[(tempDoublePtr)>>3]))); + } else if (type == 'i64') { + ret = [HEAP32[(((varargs)+(argIndex))>>2)], + HEAP32[(((varargs)+(argIndex+4))>>2)]]; + + } else { + type = 'i32'; // varargs are always i32, i64, or double + ret = HEAP32[(((varargs)+(argIndex))>>2)]; + } + argIndex += Runtime.getNativeFieldSize(type); + return ret; + } + + var ret = []; + var curr, next, currArg; + while(1) { + var startTextIndex = textIndex; + curr = HEAP8[(textIndex)]; + if (curr === 0) break; + next = HEAP8[((textIndex+1)|0)]; + if (curr == 37) { + // Handle flags. + var flagAlwaysSigned = false; + var flagLeftAlign = false; + var flagAlternative = false; + var flagZeroPad = false; + var flagPadSign = false; + flagsLoop: while (1) { + switch (next) { + case 43: + flagAlwaysSigned = true; + break; + case 45: + flagLeftAlign = true; + break; + case 35: + flagAlternative = true; + break; + case 48: + if (flagZeroPad) { + break flagsLoop; + } else { + flagZeroPad = true; + break; + } + case 32: + flagPadSign = true; + break; + default: + break flagsLoop; + } + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } + + // Handle width. + var width = 0; + if (next == 42) { + width = getNextArg('i32'); + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } else { + while (next >= 48 && next <= 57) { + width = width * 10 + (next - 48); + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } + } + + // Handle precision. + var precisionSet = false, precision = -1; + if (next == 46) { + precision = 0; + precisionSet = true; + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + if (next == 42) { + precision = getNextArg('i32'); + textIndex++; + } else { + while(1) { + var precisionChr = HEAP8[((textIndex+1)|0)]; + if (precisionChr < 48 || + precisionChr > 57) break; + precision = precision * 10 + (precisionChr - 48); + textIndex++; + } + } + next = HEAP8[((textIndex+1)|0)]; + } + if (precision < 0) { + precision = 6; // Standard default. + precisionSet = false; + } + + // Handle integer sizes. WARNING: These assume a 32-bit architecture! + var argSize; + switch (String.fromCharCode(next)) { + case 'h': + var nextNext = HEAP8[((textIndex+2)|0)]; + if (nextNext == 104) { + textIndex++; + argSize = 1; // char (actually i32 in varargs) + } else { + argSize = 2; // short (actually i32 in varargs) + } + break; + case 'l': + var nextNext = HEAP8[((textIndex+2)|0)]; + if (nextNext == 108) { + textIndex++; + argSize = 8; // long long + } else { + argSize = 4; // long + } + break; + case 'L': // long long + case 'q': // int64_t + case 'j': // intmax_t + argSize = 8; + break; + case 'z': // size_t + case 't': // ptrdiff_t + case 'I': // signed ptrdiff_t or unsigned size_t + argSize = 4; + break; + default: + argSize = null; + } + if (argSize) textIndex++; + next = HEAP8[((textIndex+1)|0)]; + + // Handle type specifier. + switch (String.fromCharCode(next)) { + case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': case 'p': { + // Integer. + var signed = next == 100 || next == 105; + argSize = argSize || 4; + var currArg = getNextArg('i' + (argSize * 8)); + var origArg = currArg; + var argText; + // Flatten i64-1 [low, high] into a (slightly rounded) double + if (argSize == 8) { + currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == 117); + } + // Truncate to requested size. + if (argSize <= 4) { + var limit = Math.pow(256, argSize) - 1; + currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8); + } + // Format the number. + var currAbsArg = Math.abs(currArg); + var prefix = ''; + if (next == 100 || next == 105) { + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else + argText = reSign(currArg, 8 * argSize, 1).toString(10); + } else if (next == 117) { + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else + argText = unSign(currArg, 8 * argSize, 1).toString(10); + currArg = Math.abs(currArg); + } else if (next == 111) { + argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8); + } else if (next == 120 || next == 88) { + prefix = (flagAlternative && currArg != 0) ? '0x' : ''; + if (argSize == 8 && i64Math) { + if (origArg[1]) { + argText = (origArg[1]>>>0).toString(16); + var lower = (origArg[0]>>>0).toString(16); + while (lower.length < 8) lower = '0' + lower; + argText += lower; + } else { + argText = (origArg[0]>>>0).toString(16); + } + } else + if (currArg < 0) { + // Represent negative numbers in hex as 2's complement. + currArg = -currArg; + argText = (currAbsArg - 1).toString(16); + var buffer = []; + for (var i = 0; i < argText.length; i++) { + buffer.push((0xF - parseInt(argText[i], 16)).toString(16)); + } + argText = buffer.join(''); + while (argText.length < argSize * 2) argText = 'f' + argText; + } else { + argText = currAbsArg.toString(16); + } + if (next == 88) { + prefix = prefix.toUpperCase(); + argText = argText.toUpperCase(); + } + } else if (next == 112) { + if (currAbsArg === 0) { + argText = '(nil)'; + } else { + prefix = '0x'; + argText = currAbsArg.toString(16); + } + } + if (precisionSet) { + while (argText.length < precision) { + argText = '0' + argText; + } + } + + // Add sign if needed + if (currArg >= 0) { + if (flagAlwaysSigned) { + prefix = '+' + prefix; + } else if (flagPadSign) { + prefix = ' ' + prefix; + } + } + + // Move sign to prefix so we zero-pad after the sign + if (argText.charAt(0) == '-') { + prefix = '-' + prefix; + argText = argText.substr(1); + } + + // Add padding. + while (prefix.length + argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad) { + argText = '0' + argText; + } else { + prefix = ' ' + prefix; + } + } + } + + // Insert the result into the buffer. + argText = prefix + argText; + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; + } + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': { + // Float. + var currArg = getNextArg('double'); + var argText; + if (isNaN(currArg)) { + argText = 'nan'; + flagZeroPad = false; + } else if (!isFinite(currArg)) { + argText = (currArg < 0 ? '-' : '') + 'inf'; + flagZeroPad = false; + } else { + var isGeneral = false; + var effectivePrecision = Math.min(precision, 20); + + // Convert g/G to f/F or e/E, as per: + // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html + if (next == 103 || next == 71) { + isGeneral = true; + precision = precision || 1; + var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10); + if (precision > exponent && exponent >= -4) { + next = ((next == 103) ? 'f' : 'F').charCodeAt(0); + precision -= exponent + 1; + } else { + next = ((next == 103) ? 'e' : 'E').charCodeAt(0); + precision--; + } + effectivePrecision = Math.min(precision, 20); + } + + if (next == 101 || next == 69) { + argText = currArg.toExponential(effectivePrecision); + // Make sure the exponent has at least 2 digits. + if (/[eE][-+]\d$/.test(argText)) { + argText = argText.slice(0, -1) + '0' + argText.slice(-1); + } + } else if (next == 102 || next == 70) { + argText = currArg.toFixed(effectivePrecision); + if (currArg === 0 && __reallyNegative(currArg)) { + argText = '-' + argText; + } + } + + var parts = argText.split('e'); + if (isGeneral && !flagAlternative) { + // Discard trailing zeros and periods. + while (parts[0].length > 1 && parts[0].indexOf('.') != -1 && + (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) { + parts[0] = parts[0].slice(0, -1); + } + } else { + // Make sure we have a period in alternative mode. + if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.'; + // Zero pad until required precision. + while (precision > effectivePrecision++) parts[0] += '0'; + } + argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : ''); + + // Capitalize 'E' if needed. + if (next == 69) argText = argText.toUpperCase(); + + // Add sign. + if (currArg >= 0) { + if (flagAlwaysSigned) { + argText = '+' + argText; + } else if (flagPadSign) { + argText = ' ' + argText; + } + } + } + + // Add padding. + while (argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) { + argText = argText[0] + '0' + argText.slice(1); + } else { + argText = (flagZeroPad ? '0' : ' ') + argText; + } + } + } + + // Adjust case. + if (next < 97) argText = argText.toUpperCase(); + + // Insert the result into the buffer. + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; + } + case 's': { + // String. + var arg = getNextArg('i8*'); + var argLength = arg ? _strlen(arg) : '(null)'.length; + if (precisionSet) argLength = Math.min(argLength, precision); + if (!flagLeftAlign) { + while (argLength < width--) { + ret.push(32); + } + } + if (arg) { + for (var i = 0; i < argLength; i++) { + ret.push(HEAPU8[((arg++)|0)]); + } + } else { + ret = ret.concat(intArrayFromString('(null)'.substr(0, argLength), true)); + } + if (flagLeftAlign) { + while (argLength < width--) { + ret.push(32); + } + } + break; + } + case 'c': { + // Character. + if (flagLeftAlign) ret.push(getNextArg('i8')); + while (--width > 0) { + ret.push(32); + } + if (!flagLeftAlign) ret.push(getNextArg('i8')); + break; + } + case 'n': { + // Write the length written so far to the next parameter. + var ptr = getNextArg('i32*'); + HEAP32[((ptr)>>2)]=ret.length; + break; + } + case '%': { + // Literal percent sign. + ret.push(curr); + break; + } + default: { + // Unknown specifiers remain untouched. + for (var i = startTextIndex; i < textIndex + 2; i++) { + ret.push(HEAP8[(i)]); + } + } + } + textIndex += 2; + // TODO: Support a/A (hex float) and m (last error) specifiers. + // TODO: Support %1${specifier} for arg selection. + } else { + ret.push(curr); + textIndex += 1; + } + } + return ret; + } + + function _malloc(bytes) { + /* Over-allocate to make sure it is byte-aligned by 8. + * This will leak memory, but this is only the dummy + * implementation (replaced by dlmalloc normally) so + * not an issue. + */ + var ptr = Runtime.dynamicAlloc(bytes + 8); + return (ptr+8) & 0xFFFFFFF8; + } + Module["_malloc"] = _malloc;function _snprintf(s, n, format, varargs) { + // int snprintf(char *restrict s, size_t n, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var result = __formatString(format, varargs); + var limit = (n === undefined) ? result.length + : Math.min(result.length, Math.max(n - 1, 0)); + if (s < 0) { + s = -s; + var buf = _malloc(limit+1); + HEAP32[((s)>>2)]=buf; + s = buf; + } + for (var i = 0; i < limit; i++) { + HEAP8[(((s)+(i))|0)]=result[i]; + } + if (limit < n || (n === undefined)) HEAP8[(((s)+(i))|0)]=0; + return result.length; + } + + + Module["_memset"] = _memset; + + + Module["_strcat"] = _strcat; + + + function _strerror_r(errnum, strerrbuf, buflen) { + if (errnum in ERRNO_MESSAGES) { + if (ERRNO_MESSAGES[errnum].length > buflen - 1) { + return ___setErrNo(ERRNO_CODES.ERANGE); + } else { + var msg = ERRNO_MESSAGES[errnum]; + writeAsciiToMemory(msg, strerrbuf); + return 0; + } + } else { + return ___setErrNo(ERRNO_CODES.EINVAL); + } + }function _strerror(errnum) { + if (!_strerror.buffer) _strerror.buffer = _malloc(256); + _strerror_r(errnum, _strerror.buffer, 256); + return _strerror.buffer; + } + + + Module["_bitshift64Shl"] = _bitshift64Shl; + + function _abort() { + Module['abort'](); + } + + + + + + + function _mkport() { throw 'TODO' }var SOCKFS={mount:function (mount) { + return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + },createSocket:function (family, type, protocol) { + var streaming = type == 1; + if (protocol) { + assert(streaming == (protocol == 6)); // if SOCK_STREAM, must be tcp + } + + // create our internal socket structure + var sock = { + family: family, + type: type, + protocol: protocol, + server: null, + peers: {}, + pending: [], + recv_queue: [], + sock_ops: SOCKFS.websocket_sock_ops + }; + + // create the filesystem node to store the socket structure + var name = SOCKFS.nextname(); + var node = FS.createNode(SOCKFS.root, name, 49152, 0); + node.sock = sock; + + // and the wrapping stream that enables library functions such + // as read and write to indirectly interact with the socket + var stream = FS.createStream({ + path: name, + node: node, + flags: FS.modeStringToFlags('r+'), + seekable: false, + stream_ops: SOCKFS.stream_ops + }); + + // map the new stream to the socket structure (sockets have a 1:1 + // relationship with a stream) + sock.stream = stream; + + return sock; + },getSocket:function (fd) { + var stream = FS.getStream(fd); + if (!stream || !FS.isSocket(stream.node.mode)) { + return null; + } + return stream.node.sock; + },stream_ops:{poll:function (stream) { + var sock = stream.node.sock; + return sock.sock_ops.poll(sock); + },ioctl:function (stream, request, varargs) { + var sock = stream.node.sock; + return sock.sock_ops.ioctl(sock, request, varargs); + },read:function (stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + var msg = sock.sock_ops.recvmsg(sock, length); + if (!msg) { + // socket is closed + return 0; + } + buffer.set(msg.buffer, offset); + return msg.buffer.length; + },write:function (stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + return sock.sock_ops.sendmsg(sock, buffer, offset, length); + },close:function (stream) { + var sock = stream.node.sock; + sock.sock_ops.close(sock); + }},nextname:function () { + if (!SOCKFS.nextname.current) { + SOCKFS.nextname.current = 0; + } + return 'socket[' + (SOCKFS.nextname.current++) + ']'; + },websocket_sock_ops:{createPeer:function (sock, addr, port) { + var ws; + + if (typeof addr === 'object') { + ws = addr; + addr = null; + port = null; + } + + if (ws) { + // for sockets that've already connected (e.g. we're the server) + // we can inspect the _socket property for the address + if (ws._socket) { + addr = ws._socket.remoteAddress; + port = ws._socket.remotePort; + } + // if we're just now initializing a connection to the remote, + // inspect the url property + else { + var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url); + if (!result) { + throw new Error('WebSocket URL must be in the format ws(s)://address:port'); + } + addr = result[1]; + port = parseInt(result[2], 10); + } + } else { + // create the actual websocket object and connect + try { + // runtimeConfig gets set to true if WebSocket runtime configuration is available. + var runtimeConfig = (Module['websocket'] && ('object' === typeof Module['websocket'])); + + // The default value is 'ws://' the replace is needed because the compiler replaces "//" comments with '#' + // comments without checking context, so we'd end up with ws:#, the replace swaps the "#" for "//" again. + var url = 'ws:#'.replace('#', '//'); + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['url']) { + url = Module['websocket']['url']; // Fetch runtime WebSocket URL config. + } + } + + if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it. + url = url + addr + ':' + port; + } + + // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set. + var subProtocols = 'binary'; // The default value is 'binary' + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['subprotocol']) { + subProtocols = Module['websocket']['subprotocol']; // Fetch runtime WebSocket subprotocol config. + } + } + + // The regex trims the string (removes spaces at the beginning and end, then splits the string by + // , into an Array. Whitespace removal is important for Websockify and ws. + subProtocols = subProtocols.replace(/^ +| +$/g,"").split(/ *, */); + + // The node ws library API for specifying optional subprotocol is slightly different than the browser's. + var opts = ENVIRONMENT_IS_NODE ? {'protocol': subProtocols.toString()} : subProtocols; + + // If node we use the ws library. + var WebSocket = ENVIRONMENT_IS_NODE ? require('ws') : window['WebSocket']; + ws = new WebSocket(url, opts); + ws.binaryType = 'arraybuffer'; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EHOSTUNREACH); + } + } + + + var peer = { + addr: addr, + port: port, + socket: ws, + dgram_send_queue: [] + }; + + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer); + + // if this is a bound dgram socket, send the port number first to allow + // us to override the ephemeral port reported to us by remotePort on the + // remote end. + if (sock.type === 2 && typeof sock.sport !== 'undefined') { + peer.dgram_send_queue.push(new Uint8Array([ + 255, 255, 255, 255, + 'p'.charCodeAt(0), 'o'.charCodeAt(0), 'r'.charCodeAt(0), 't'.charCodeAt(0), + ((sock.sport & 0xff00) >> 8) , (sock.sport & 0xff) + ])); + } + + return peer; + },getPeer:function (sock, addr, port) { + return sock.peers[addr + ':' + port]; + },addPeer:function (sock, peer) { + sock.peers[peer.addr + ':' + peer.port] = peer; + },removePeer:function (sock, peer) { + delete sock.peers[peer.addr + ':' + peer.port]; + },handlePeerEvents:function (sock, peer) { + var first = true; + + var handleOpen = function () { + try { + var queued = peer.dgram_send_queue.shift(); + while (queued) { + peer.socket.send(queued); + queued = peer.dgram_send_queue.shift(); + } + } catch (e) { + // not much we can do here in the way of proper error handling as we've already + // lied and said this data was sent. shut it down. + peer.socket.close(); + } + }; + + function handleMessage(data) { + assert(typeof data !== 'string' && data.byteLength !== undefined); // must receive an ArrayBuffer + data = new Uint8Array(data); // make a typed array view on the array buffer + + + // if this is the port message, override the peer's port with it + var wasfirst = first; + first = false; + if (wasfirst && + data.length === 10 && + data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 && + data[4] === 'p'.charCodeAt(0) && data[5] === 'o'.charCodeAt(0) && data[6] === 'r'.charCodeAt(0) && data[7] === 't'.charCodeAt(0)) { + // update the peer's port and it's key in the peer map + var newport = ((data[8] << 8) | data[9]); + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + peer.port = newport; + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + return; + } + + sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data }); + }; + + if (ENVIRONMENT_IS_NODE) { + peer.socket.on('open', handleOpen); + peer.socket.on('message', function(data, flags) { + if (!flags.binary) { + return; + } + handleMessage((new Uint8Array(data)).buffer); // copy from node Buffer -> ArrayBuffer + }); + peer.socket.on('error', function() { + // don't throw + }); + } else { + peer.socket.onopen = handleOpen; + peer.socket.onmessage = function peer_socket_onmessage(event) { + handleMessage(event.data); + }; + } + },poll:function (sock) { + if (sock.type === 1 && sock.server) { + // listen sockets should only say they're available for reading + // if there are pending clients. + return sock.pending.length ? (64 | 1) : 0; + } + + var mask = 0; + var dest = sock.type === 1 ? // we only care about the socket state for connection-based sockets + SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) : + null; + + if (sock.recv_queue.length || + !dest || // connection-less sockets are always ready to read + (dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { // let recv return 0 once closed + mask |= (64 | 1); + } + + if (!dest || // connection-less sockets are always ready to write + (dest && dest.socket.readyState === dest.socket.OPEN)) { + mask |= 4; + } + + if ((dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { + mask |= 16; + } + + return mask; + },ioctl:function (sock, request, arg) { + switch (request) { + case 21531: + var bytes = 0; + if (sock.recv_queue.length) { + bytes = sock.recv_queue[0].data.length; + } + HEAP32[((arg)>>2)]=bytes; + return 0; + default: + return ERRNO_CODES.EINVAL; + } + },close:function (sock) { + // if we've spawned a listen server, close it + if (sock.server) { + try { + sock.server.close(); + } catch (e) { + } + sock.server = null; + } + // close any peer connections + var peers = Object.keys(sock.peers); + for (var i = 0; i < peers.length; i++) { + var peer = sock.peers[peers[i]]; + try { + peer.socket.close(); + } catch (e) { + } + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + } + return 0; + },bind:function (sock, addr, port) { + if (typeof sock.saddr !== 'undefined' || typeof sock.sport !== 'undefined') { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); // already bound + } + sock.saddr = addr; + sock.sport = port || _mkport(); + // in order to emulate dgram sockets, we need to launch a listen server when + // binding on a connection-less socket + // note: this is only required on the server side + if (sock.type === 2) { + // close the existing server if it exists + if (sock.server) { + sock.server.close(); + sock.server = null; + } + // swallow error operation not supported error that occurs when binding in the + // browser where this isn't supported + try { + sock.sock_ops.listen(sock, 0); + } catch (e) { + if (!(e instanceof FS.ErrnoError)) throw e; + if (e.errno !== ERRNO_CODES.EOPNOTSUPP) throw e; + } + } + },connect:function (sock, addr, port) { + if (sock.server) { + throw new FS.ErrnoError(ERRNO_CODS.EOPNOTSUPP); + } + + // TODO autobind + // if (!sock.addr && sock.type == 2) { + // } + + // early out if we're already connected / in the middle of connecting + if (typeof sock.daddr !== 'undefined' && typeof sock.dport !== 'undefined') { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + if (dest) { + if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(ERRNO_CODES.EALREADY); + } else { + throw new FS.ErrnoError(ERRNO_CODES.EISCONN); + } + } + } + + // add the socket to our peer list and set our + // destination address / port to match + var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + sock.daddr = peer.addr; + sock.dport = peer.port; + + // always "fail" in non-blocking mode + throw new FS.ErrnoError(ERRNO_CODES.EINPROGRESS); + },listen:function (sock, backlog) { + if (!ENVIRONMENT_IS_NODE) { + throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP); + } + if (sock.server) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); // already listening + } + var WebSocketServer = require('ws').Server; + var host = sock.saddr; + sock.server = new WebSocketServer({ + host: host, + port: sock.sport + // TODO support backlog + }); + + sock.server.on('connection', function(ws) { + if (sock.type === 1) { + var newsock = SOCKFS.createSocket(sock.family, sock.type, sock.protocol); + + // create a peer on the new socket + var peer = SOCKFS.websocket_sock_ops.createPeer(newsock, ws); + newsock.daddr = peer.addr; + newsock.dport = peer.port; + + // push to queue for accept to pick up + sock.pending.push(newsock); + } else { + // create a peer on the listen socket so calling sendto + // with the listen socket and an address will resolve + // to the correct client + SOCKFS.websocket_sock_ops.createPeer(sock, ws); + } + }); + sock.server.on('closed', function() { + sock.server = null; + }); + sock.server.on('error', function() { + // don't throw + }); + },accept:function (listensock) { + if (!listensock.server) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var newsock = listensock.pending.shift(); + newsock.stream.flags = listensock.stream.flags; + return newsock; + },getname:function (sock, peer) { + var addr, port; + if (peer) { + if (sock.daddr === undefined || sock.dport === undefined) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + addr = sock.daddr; + port = sock.dport; + } else { + // TODO saddr and sport will be set for bind()'d UDP sockets, but what + // should we be returning for TCP sockets that've been connect()'d? + addr = sock.saddr || 0; + port = sock.sport || 0; + } + return { addr: addr, port: port }; + },sendmsg:function (sock, buffer, offset, length, addr, port) { + if (sock.type === 2) { + // connection-less sockets will honor the message address, + // and otherwise fall back to the bound destination address + if (addr === undefined || port === undefined) { + addr = sock.daddr; + port = sock.dport; + } + // if there was no address to fall back to, error out + if (addr === undefined || port === undefined) { + throw new FS.ErrnoError(ERRNO_CODES.EDESTADDRREQ); + } + } else { + // connection-based sockets will only use the bound + addr = sock.daddr; + port = sock.dport; + } + + // find the peer for the destination address + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port); + + // early out if not connected with a connection-based socket + if (sock.type === 1) { + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } else if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } + + // create a copy of the incoming data to send, as the WebSocket API + // doesn't work entirely with an ArrayBufferView, it'll just send + // the entire underlying buffer + var data; + if (buffer instanceof Array || buffer instanceof ArrayBuffer) { + data = buffer.slice(offset, offset + length); + } else { // ArrayBufferView + data = buffer.buffer.slice(buffer.byteOffset + offset, buffer.byteOffset + offset + length); + } + + // if we're emulating a connection-less dgram socket and don't have + // a cached connection, queue the buffer to send upon connect and + // lie, saying the data was sent now. + if (sock.type === 2) { + if (!dest || dest.socket.readyState !== dest.socket.OPEN) { + // if we're not connected, open a new connection + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + } + dest.dgram_send_queue.push(data); + return length; + } + } + + try { + // send the actual data + dest.socket.send(data); + return length; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + },recvmsg:function (sock, length) { + // http://pubs.opengroup.org/onlinepubs/7908799/xns/recvmsg.html + if (sock.type === 1 && sock.server) { + // tcp servers should not be recv()'ing on the listen socket + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + + var queued = sock.recv_queue.shift(); + if (!queued) { + if (sock.type === 1) { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + + if (!dest) { + // if we have a destination address but are not connected, error out + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + else if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + // return null if the socket has closed + return null; + } + else { + // else, our socket is in a valid state but truly has nothing available + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } else { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } + + // queued.data will be an ArrayBuffer if it's unadulterated, but if it's + // requeued TCP data it'll be an ArrayBufferView + var queuedLength = queued.data.byteLength || queued.data.length; + var queuedOffset = queued.data.byteOffset || 0; + var queuedBuffer = queued.data.buffer || queued.data; + var bytesRead = Math.min(length, queuedLength); + var res = { + buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead), + addr: queued.addr, + port: queued.port + }; + + + // push back any unread data for TCP connections + if (sock.type === 1 && bytesRead < queuedLength) { + var bytesRemaining = queuedLength - bytesRead; + queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining); + sock.recv_queue.unshift(queued); + } + + return res; + }}};function _send(fd, buf, len, flags) { + var sock = SOCKFS.getSocket(fd); + if (!sock) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + // TODO honor flags + return _write(fd, buf, len); + } + + function _pwrite(fildes, buf, nbyte, offset) { + // ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + var slab = HEAP8; + return FS.write(stream, slab, buf, nbyte, offset); + } catch (e) { + FS.handleFSError(e); + return -1; + } + }function _write(fildes, buf, nbyte) { + // ssize_t write(int fildes, const void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + + + try { + var slab = HEAP8; + return FS.write(stream, slab, buf, nbyte); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + function _fileno(stream) { + // int fileno(FILE *stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fileno.html + stream = FS.getStreamFromPtr(stream); + if (!stream) return -1; + return stream.fd; + }function _fwrite(ptr, size, nitems, stream) { + // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fwrite.html + var bytesToWrite = nitems * size; + if (bytesToWrite == 0) return 0; + var fd = _fileno(stream); + var bytesWritten = _write(fd, ptr, bytesToWrite); + if (bytesWritten == -1) { + var streamObj = FS.getStreamFromPtr(stream); + if (streamObj) streamObj.error = true; + return 0; + } else { + return Math.floor(bytesWritten / size); + } + }function _fprintf(stream, format, varargs) { + // int fprintf(FILE *restrict stream, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var result = __formatString(format, varargs); + var stack = Runtime.stackSave(); + var ret = _fwrite(allocate(result, 'i8', ALLOC_STACK), 1, result.length, stream); + Runtime.stackRestore(stack); + return ret; + } + + function _toupper(chr) { + if (chr >= 97 && chr <= 122) { + return chr - 97 + 65; + } else { + return chr; + } + } + + function _printf(format, varargs) { + // int printf(const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var stdout = HEAP32[((_stdout)>>2)]; + return _fprintf(stdout, format, varargs); + } + + function _isdigit(chr) { + return chr >= 48 && chr <= 57; + } + + function _close(fildes) { + // int close(int fildes); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/close.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + FS.close(stream); + return 0; + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + var _tan=Math_tan; + + + + Module["_strncpy"] = _strncpy; + + var _asin=Math_asin; + + + Module["_i64Add"] = _i64Add; + + var _fabs=Math_abs; + + function _open(path, oflag, varargs) { + // int open(const char *path, int oflag, ...); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html + var mode = HEAP32[((varargs)>>2)]; + path = Pointer_stringify(path); + try { + var stream = FS.open(path, oflag, mode); + return stream.fd; + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + + function _copysign(a, b) { + return __reallyNegative(a) === __reallyNegative(b) ? a : -a; + }var _copysignl=_copysign; + + var _sqrt=Math_sqrt; + + + var Browser={mainLoop:{scheduler:null,method:"",shouldPause:false,paused:false,queue:[],pause:function () { + Browser.mainLoop.shouldPause = true; + },resume:function () { + if (Browser.mainLoop.paused) { + Browser.mainLoop.paused = false; + Browser.mainLoop.scheduler(); + } + Browser.mainLoop.shouldPause = false; + },updateStatus:function () { + if (Module['setStatus']) { + var message = Module['statusMessage'] || 'Please wait...'; + var remaining = Browser.mainLoop.remainingBlockers; + var expected = Browser.mainLoop.expectedBlockers; + if (remaining) { + if (remaining < expected) { + Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')'); + } else { + Module['setStatus'](message); + } + } else { + Module['setStatus'](''); + } + } + }},isFullScreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function () { + if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers + + if (Browser.initted || ENVIRONMENT_IS_WORKER) return; + Browser.initted = true; + + try { + new Blob(); + Browser.hasBlobConstructor = true; + } catch(e) { + Browser.hasBlobConstructor = false; + console.log("warning: no blob constructor, cannot create blobs with mimetypes"); + } + Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null)); + Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined; + if (!Module.noImageDecoding && typeof Browser.URLObject === 'undefined') { + console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."); + Module.noImageDecoding = true; + } + + // Support for plugins that can process preloaded files. You can add more of these to + // your app by creating and appending to Module.preloadPlugins. + // + // Each plugin is asked if it can handle a file based on the file's name. If it can, + // it is given the file's raw data. When it is done, it calls a callback with the file's + // (possibly modified) data. For example, a plugin might decompress a file, or it + // might create some side data structure for use later (like an Image element, etc.). + + var imagePlugin = {}; + imagePlugin['canHandle'] = function imagePlugin_canHandle(name) { + return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name); + }; + imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) { + var b = null; + if (Browser.hasBlobConstructor) { + try { + b = new Blob([byteArray], { type: Browser.getMimetype(name) }); + if (b.size !== byteArray.length) { // Safari bug #118630 + // Safari's Blob can only take an ArrayBuffer + b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) }); + } + } catch(e) { + Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder'); + } + } + if (!b) { + var bb = new Browser.BlobBuilder(); + bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range + b = bb.getBlob(); + } + var url = Browser.URLObject.createObjectURL(b); + var img = new Image(); + img.onload = function img_onload() { + assert(img.complete, 'Image ' + name + ' could not be decoded'); + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + Module["preloadedImages"][name] = canvas; + Browser.URLObject.revokeObjectURL(url); + if (onload) onload(byteArray); + }; + img.onerror = function img_onerror(event) { + console.log('Image ' + url + ' could not be decoded'); + if (onerror) onerror(); + }; + img.src = url; + }; + Module['preloadPlugins'].push(imagePlugin); + + var audioPlugin = {}; + audioPlugin['canHandle'] = function audioPlugin_canHandle(name) { + return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; + }; + audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) { + var done = false; + function finish(audio) { + if (done) return; + done = true; + Module["preloadedAudios"][name] = audio; + if (onload) onload(byteArray); + } + function fail() { + if (done) return; + done = true; + Module["preloadedAudios"][name] = new Audio(); // empty shim + if (onerror) onerror(); + } + if (Browser.hasBlobConstructor) { + try { + var b = new Blob([byteArray], { type: Browser.getMimetype(name) }); + } catch(e) { + return fail(); + } + var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! + var audio = new Audio(); + audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926 + audio.onerror = function audio_onerror(event) { + if (done) return; + console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach'); + function encode64(data) { + var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + var PAD = '='; + var ret = ''; + var leftchar = 0; + var leftbits = 0; + for (var i = 0; i < data.length; i++) { + leftchar = (leftchar << 8) | data[i]; + leftbits += 8; + while (leftbits >= 6) { + var curr = (leftchar >> (leftbits-6)) & 0x3f; + leftbits -= 6; + ret += BASE[curr]; + } + } + if (leftbits == 2) { + ret += BASE[(leftchar&3) << 4]; + ret += PAD + PAD; + } else if (leftbits == 4) { + ret += BASE[(leftchar&0xf) << 2]; + ret += PAD; + } + return ret; + } + audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray); + finish(audio); // we don't wait for confirmation this worked - but it's worth trying + }; + audio.src = url; + // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror + Browser.safeSetTimeout(function() { + finish(audio); // try to use it even though it is not necessarily ready to play + }, 10000); + } else { + return fail(); + } + }; + Module['preloadPlugins'].push(audioPlugin); + + // Canvas event setup + + var canvas = Module['canvas']; + + // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module + // Module['forcedAspectRatio'] = 4 / 3; + + canvas.requestPointerLock = canvas['requestPointerLock'] || + canvas['mozRequestPointerLock'] || + canvas['webkitRequestPointerLock'] || + canvas['msRequestPointerLock'] || + function(){}; + canvas.exitPointerLock = document['exitPointerLock'] || + document['mozExitPointerLock'] || + document['webkitExitPointerLock'] || + document['msExitPointerLock'] || + function(){}; // no-op if function does not exist + canvas.exitPointerLock = canvas.exitPointerLock.bind(document); + + function pointerLockChange() { + Browser.pointerLock = document['pointerLockElement'] === canvas || + document['mozPointerLockElement'] === canvas || + document['webkitPointerLockElement'] === canvas || + document['msPointerLockElement'] === canvas; + } + + document.addEventListener('pointerlockchange', pointerLockChange, false); + document.addEventListener('mozpointerlockchange', pointerLockChange, false); + document.addEventListener('webkitpointerlockchange', pointerLockChange, false); + document.addEventListener('mspointerlockchange', pointerLockChange, false); + + if (Module['elementPointerLock']) { + canvas.addEventListener("click", function(ev) { + if (!Browser.pointerLock && canvas.requestPointerLock) { + canvas.requestPointerLock(); + ev.preventDefault(); + } + }, false); + } + },createContext:function (canvas, useWebGL, setInModule, webGLContextAttributes) { + var ctx; + var errorInfo = '?'; + function onContextCreationError(event) { + errorInfo = event.statusMessage || errorInfo; + } + try { + if (useWebGL) { + var contextAttributes = { + antialias: false, + alpha: false + }; + + if (webGLContextAttributes) { + for (var attribute in webGLContextAttributes) { + contextAttributes[attribute] = webGLContextAttributes[attribute]; + } + } + + + canvas.addEventListener('webglcontextcreationerror', onContextCreationError, false); + try { + ['experimental-webgl', 'webgl'].some(function(webglId) { + return ctx = canvas.getContext(webglId, contextAttributes); + }); + } finally { + canvas.removeEventListener('webglcontextcreationerror', onContextCreationError, false); + } + } else { + ctx = canvas.getContext('2d'); + } + if (!ctx) throw ':('; + } catch (e) { + Module.print('Could not create canvas: ' + [errorInfo, e]); + return null; + } + if (useWebGL) { + // Set the background of the WebGL canvas to black + canvas.style.backgroundColor = "black"; + + // Warn on context loss + canvas.addEventListener('webglcontextlost', function(event) { + alert('WebGL context lost. You will need to reload the page.'); + }, false); + } + if (setInModule) { + GLctx = Module.ctx = ctx; + Module.useWebGL = useWebGL; + Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); + Browser.init(); + } + return ctx; + },destroyContext:function (canvas, useWebGL, setInModule) {},fullScreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullScreen:function (lockPointer, resizeCanvas) { + Browser.lockPointer = lockPointer; + Browser.resizeCanvas = resizeCanvas; + if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true; + if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false; + + var canvas = Module['canvas']; + function fullScreenChange() { + Browser.isFullScreen = false; + var canvasContainer = canvas.parentNode; + if ((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement'] || + document['msFullScreenElement'] || document['msFullscreenElement'] || + document['webkitCurrentFullScreenElement']) === canvasContainer) { + canvas.cancelFullScreen = document['cancelFullScreen'] || + document['mozCancelFullScreen'] || + document['webkitCancelFullScreen'] || + document['msExitFullscreen'] || + document['exitFullscreen'] || + function() {}; + canvas.cancelFullScreen = canvas.cancelFullScreen.bind(document); + if (Browser.lockPointer) canvas.requestPointerLock(); + Browser.isFullScreen = true; + if (Browser.resizeCanvas) Browser.setFullScreenCanvasSize(); + } else { + + // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen + canvasContainer.parentNode.insertBefore(canvas, canvasContainer); + canvasContainer.parentNode.removeChild(canvasContainer); + + if (Browser.resizeCanvas) Browser.setWindowedCanvasSize(); + } + if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullScreen); + Browser.updateCanvasDimensions(canvas); + } + + if (!Browser.fullScreenHandlersInstalled) { + Browser.fullScreenHandlersInstalled = true; + document.addEventListener('fullscreenchange', fullScreenChange, false); + document.addEventListener('mozfullscreenchange', fullScreenChange, false); + document.addEventListener('webkitfullscreenchange', fullScreenChange, false); + document.addEventListener('MSFullscreenChange', fullScreenChange, false); + } + + // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root + var canvasContainer = document.createElement("div"); + canvas.parentNode.insertBefore(canvasContainer, canvas); + canvasContainer.appendChild(canvas); + + // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size) + canvasContainer.requestFullScreen = canvasContainer['requestFullScreen'] || + canvasContainer['mozRequestFullScreen'] || + canvasContainer['msRequestFullscreen'] || + (canvasContainer['webkitRequestFullScreen'] ? function() { canvasContainer['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null); + canvasContainer.requestFullScreen(); + },requestAnimationFrame:function requestAnimationFrame(func) { + if (typeof window === 'undefined') { // Provide fallback to setTimeout if window is undefined (e.g. in Node.js) + setTimeout(func, 1000/60); + } else { + if (!window.requestAnimationFrame) { + window.requestAnimationFrame = window['requestAnimationFrame'] || + window['mozRequestAnimationFrame'] || + window['webkitRequestAnimationFrame'] || + window['msRequestAnimationFrame'] || + window['oRequestAnimationFrame'] || + window['setTimeout']; + } + window.requestAnimationFrame(func); + } + },safeCallback:function (func) { + return function() { + if (!ABORT) return func.apply(null, arguments); + }; + },safeRequestAnimationFrame:function (func) { + return Browser.requestAnimationFrame(function() { + if (!ABORT) func(); + }); + },safeSetTimeout:function (func, timeout) { + return setTimeout(function() { + if (!ABORT) func(); + }, timeout); + },safeSetInterval:function (func, timeout) { + return setInterval(function() { + if (!ABORT) func(); + }, timeout); + },getMimetype:function (name) { + return { + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'png': 'image/png', + 'bmp': 'image/bmp', + 'ogg': 'audio/ogg', + 'wav': 'audio/wav', + 'mp3': 'audio/mpeg' + }[name.substr(name.lastIndexOf('.')+1)]; + },getUserMedia:function (func) { + if(!window.getUserMedia) { + window.getUserMedia = navigator['getUserMedia'] || + navigator['mozGetUserMedia']; + } + window.getUserMedia(func); + },getMovementX:function (event) { + return event['movementX'] || + event['mozMovementX'] || + event['webkitMovementX'] || + 0; + },getMovementY:function (event) { + return event['movementY'] || + event['mozMovementY'] || + event['webkitMovementY'] || + 0; + },getMouseWheelDelta:function (event) { + return Math.max(-1, Math.min(1, event.type === 'DOMMouseScroll' ? event.detail : -event.wheelDelta)); + },mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function (event) { // event should be mousemove, mousedown or mouseup + if (Browser.pointerLock) { + // When the pointer is locked, calculate the coordinates + // based on the movement of the mouse. + // Workaround for Firefox bug 764498 + if (event.type != 'mousemove' && + ('mozMovementX' in event)) { + Browser.mouseMovementX = Browser.mouseMovementY = 0; + } else { + Browser.mouseMovementX = Browser.getMovementX(event); + Browser.mouseMovementY = Browser.getMovementY(event); + } + + // check if SDL is available + if (typeof SDL != "undefined") { + Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; + Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; + } else { + // just add the mouse delta to the current absolut mouse position + // FIXME: ideally this should be clamped against the canvas size and zero + Browser.mouseX += Browser.mouseMovementX; + Browser.mouseY += Browser.mouseMovementY; + } + } else { + // Otherwise, calculate the movement based on the changes + // in the coordinates. + var rect = Module["canvas"].getBoundingClientRect(); + var cw = Module["canvas"].width; + var ch = Module["canvas"].height; + + // Neither .scrollX or .pageXOffset are defined in a spec, but + // we prefer .scrollX because it is currently in a spec draft. + // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/) + var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset); + var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset); + + if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') { + var touch = event.touch; + if (touch === undefined) { + return; // the "touch" property is only defined in SDL + + } + var adjustedX = touch.pageX - (scrollX + rect.left); + var adjustedY = touch.pageY - (scrollY + rect.top); + + adjustedX = adjustedX * (cw / rect.width); + adjustedY = adjustedY * (ch / rect.height); + + var coords = { x: adjustedX, y: adjustedY }; + + if (event.type === 'touchstart') { + Browser.lastTouches[touch.identifier] = coords; + Browser.touches[touch.identifier] = coords; + } else if (event.type === 'touchend' || event.type === 'touchmove') { + Browser.lastTouches[touch.identifier] = Browser.touches[touch.identifier]; + Browser.touches[touch.identifier] = { x: adjustedX, y: adjustedY }; + } + return; + } + + var x = event.pageX - (scrollX + rect.left); + var y = event.pageY - (scrollY + rect.top); + + // the canvas might be CSS-scaled compared to its backbuffer; + // SDL-using content will want mouse coordinates in terms + // of backbuffer units. + x = x * (cw / rect.width); + y = y * (ch / rect.height); + + Browser.mouseMovementX = x - Browser.mouseX; + Browser.mouseMovementY = y - Browser.mouseY; + Browser.mouseX = x; + Browser.mouseY = y; + } + },xhrLoad:function (url, onload, onerror) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = function xhr_onload() { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + } else { + onerror(); + } + }; + xhr.onerror = onerror; + xhr.send(null); + },asyncLoad:function (url, onload, onerror, noRunDep) { + Browser.xhrLoad(url, function(arrayBuffer) { + assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).'); + onload(new Uint8Array(arrayBuffer)); + if (!noRunDep) removeRunDependency('al ' + url); + }, function(event) { + if (onerror) { + onerror(); + } else { + throw 'Loading data file "' + url + '" failed.'; + } + }); + if (!noRunDep) addRunDependency('al ' + url); + },resizeListeners:[],updateResizeListeners:function () { + var canvas = Module['canvas']; + Browser.resizeListeners.forEach(function(listener) { + listener(canvas.width, canvas.height); + }); + },setCanvasSize:function (width, height, noUpdates) { + var canvas = Module['canvas']; + Browser.updateCanvasDimensions(canvas, width, height); + if (!noUpdates) Browser.updateResizeListeners(); + },windowedWidth:0,windowedHeight:0,setFullScreenCanvasSize:function () { + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags | 0x00800000; // set SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },setWindowedCanvasSize:function () { + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },updateCanvasDimensions:function (canvas, wNative, hNative) { + if (wNative && hNative) { + canvas.widthNative = wNative; + canvas.heightNative = hNative; + } else { + wNative = canvas.widthNative; + hNative = canvas.heightNative; + } + var w = wNative; + var h = hNative; + if (Module['forcedAspectRatio'] && Module['forcedAspectRatio'] > 0) { + if (w/h < Module['forcedAspectRatio']) { + w = Math.round(h * Module['forcedAspectRatio']); + } else { + h = Math.round(w / Module['forcedAspectRatio']); + } + } + if (((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement'] || + document['msFullScreenElement'] || document['msFullscreenElement'] || + document['webkitCurrentFullScreenElement']) === canvas.parentNode) && (typeof screen != 'undefined')) { + var factor = Math.min(screen.width / w, screen.height / h); + w = Math.round(w * factor); + h = Math.round(h * factor); + } + if (Browser.resizeCanvas) { + if (canvas.width != w) canvas.width = w; + if (canvas.height != h) canvas.height = h; + if (typeof canvas.style != 'undefined') { + canvas.style.removeProperty( "width"); + canvas.style.removeProperty("height"); + } + } else { + if (canvas.width != wNative) canvas.width = wNative; + if (canvas.height != hNative) canvas.height = hNative; + if (typeof canvas.style != 'undefined') { + if (w != wNative || h != hNative) { + canvas.style.setProperty( "width", w + "px", "important"); + canvas.style.setProperty("height", h + "px", "important"); + } else { + canvas.style.removeProperty( "width"); + canvas.style.removeProperty("height"); + } + } + } + }}; + + function _sprintf(s, format, varargs) { + // int sprintf(char *restrict s, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + return _snprintf(s, undefined, format, varargs); + } + + + function __exit(status) { + // void _exit(int status); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html + Module['exit'](status); + }function _exit(status) { + __exit(status); + } + + function _isspace(chr) { + return (chr == 32) || (chr >= 9 && chr <= 13); + } + + + function _fmod(x, y) { + return x % y; + }var _fmodl=_fmod; + + function _sysconf(name) { + // long sysconf(int name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/sysconf.html + switch(name) { + case 30: return PAGE_SIZE; + case 132: + case 133: + case 12: + case 137: + case 138: + case 15: + case 235: + case 16: + case 17: + case 18: + case 19: + case 20: + case 149: + case 13: + case 10: + case 236: + case 153: + case 9: + case 21: + case 22: + case 159: + case 154: + case 14: + case 77: + case 78: + case 139: + case 80: + case 81: + case 79: + case 82: + case 68: + case 67: + case 164: + case 11: + case 29: + case 47: + case 48: + case 95: + case 52: + case 51: + case 46: + return 200809; + case 27: + case 246: + case 127: + case 128: + case 23: + case 24: + case 160: + case 161: + case 181: + case 182: + case 242: + case 183: + case 184: + case 243: + case 244: + case 245: + case 165: + case 178: + case 179: + case 49: + case 50: + case 168: + case 169: + case 175: + case 170: + case 171: + case 172: + case 97: + case 76: + case 32: + case 173: + case 35: + return -1; + case 176: + case 177: + case 7: + case 155: + case 8: + case 157: + case 125: + case 126: + case 92: + case 93: + case 129: + case 130: + case 131: + case 94: + case 91: + return 1; + case 74: + case 60: + case 69: + case 70: + case 4: + return 1024; + case 31: + case 42: + case 72: + return 32; + case 87: + case 26: + case 33: + return 2147483647; + case 34: + case 1: + return 47839; + case 38: + case 36: + return 99; + case 43: + case 37: + return 2048; + case 0: return 2097152; + case 3: return 65536; + case 28: return 32768; + case 44: return 32767; + case 75: return 16384; + case 39: return 1000; + case 89: return 700; + case 71: return 256; + case 40: return 255; + case 2: return 100; + case 180: return 64; + case 25: return 20; + case 5: return 16; + case 6: return 6; + case 73: return 4; + case 84: return 1; + } + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + + + Module["_tolower"] = _tolower; + + var _atan=Math_atan; + + + function _recv(fd, buf, len, flags) { + var sock = SOCKFS.getSocket(fd); + if (!sock) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + // TODO honor flags + return _read(fd, buf, len); + } + + function _pread(fildes, buf, nbyte, offset) { + // ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + var slab = HEAP8; + return FS.read(stream, slab, buf, nbyte, offset); + } catch (e) { + FS.handleFSError(e); + return -1; + } + }function _read(fildes, buf, nbyte) { + // ssize_t read(int fildes, void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + + + try { + var slab = HEAP8; + return FS.read(stream, slab, buf, nbyte); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + function _time(ptr) { + var ret = Math.floor(Date.now()/1000); + if (ptr) { + HEAP32[((ptr)>>2)]=ret; + } + return ret; + } + + + + + + + var _environ=allocate(1, "i32*", ALLOC_STATIC);var ___environ=_environ;function ___buildEnvironment(env) { + // WARNING: Arbitrary limit! + var MAX_ENV_VALUES = 64; + var TOTAL_ENV_SIZE = 1024; + + // Statically allocate memory for the environment. + var poolPtr; + var envPtr; + if (!___buildEnvironment.called) { + ___buildEnvironment.called = true; + // Set default values. Use string keys for Closure Compiler compatibility. + ENV['USER'] = 'root'; + ENV['PATH'] = '/'; + ENV['PWD'] = '/'; + ENV['HOME'] = '/home/emscripten'; + ENV['LANG'] = 'en_US.UTF-8'; + ENV['_'] = './this.program'; + // Allocate memory. + poolPtr = allocate(TOTAL_ENV_SIZE, 'i8', ALLOC_STATIC); + envPtr = allocate(MAX_ENV_VALUES * 4, + 'i8*', ALLOC_STATIC); + HEAP32[((envPtr)>>2)]=poolPtr; + HEAP32[((_environ)>>2)]=envPtr; + } else { + envPtr = HEAP32[((_environ)>>2)]; + poolPtr = HEAP32[((envPtr)>>2)]; + } + + // Collect key=value lines. + var strings = []; + var totalSize = 0; + for (var key in env) { + if (typeof env[key] === 'string') { + var line = key + '=' + env[key]; + strings.push(line); + totalSize += line.length; + } + } + if (totalSize > TOTAL_ENV_SIZE) { + throw new Error('Environment size exceeded TOTAL_ENV_SIZE!'); + } + + // Make new. + var ptrSize = 4; + for (var i = 0; i < strings.length; i++) { + var line = strings[i]; + writeAsciiToMemory(line, poolPtr); + HEAP32[(((envPtr)+(i * ptrSize))>>2)]=poolPtr; + poolPtr += line.length + 1; + } + HEAP32[(((envPtr)+(strings.length * ptrSize))>>2)]=0; + }var ENV={};function _getenv(name) { + // char *getenv(const char *name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html + if (name === 0) return 0; + name = Pointer_stringify(name); + if (!ENV.hasOwnProperty(name)) return 0; + + if (_getenv.ret) _free(_getenv.ret); + _getenv.ret = allocate(intArrayFromString(ENV[name]), 'i8', ALLOC_NORMAL); + return _getenv.ret; + } + + + function _emscripten_memcpy_big(dest, src, num) { + HEAPU8.set(HEAPU8.subarray(src, src+num), dest); + return dest; + } + Module["_memcpy"] = _memcpy; + + var _log=Math_log; + + var _cos=Math_cos; + + var _llvm_pow_f64=Math_pow; + + function _sbrk(bytes) { + // Implement a Linux-like 'memory area' for our 'process'. + // Changes the size of the memory area by |bytes|; returns the + // address of the previous top ('break') of the memory area + // We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP + var self = _sbrk; + if (!self.called) { + DYNAMICTOP = alignMemoryPage(DYNAMICTOP); // make sure we start out aligned + self.called = true; + assert(Runtime.dynamicAlloc); + self.alloc = Runtime.dynamicAlloc; + Runtime.dynamicAlloc = function() { abort('cannot dynamically allocate, sbrk now has control') }; + } + var ret = DYNAMICTOP; + if (bytes != 0) self.alloc(bytes); + return ret; // Previous break location. + } + + function ___errno_location() { + return ___errno_state; + } + + var _BItoD=true; + + var _sin=Math_sin; + + var _atan2=Math_atan2; + + + Module["_strcpy"] = _strcpy; + + function _llvm_bswap_i32(x) { + return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24); + } + + + + function _islower(chr) { + return chr >= 97 && chr <= 122; + } + + var _exp=Math_exp; + + var _acos=Math_acos; + + function _isupper(chr) { + return chr >= 65 && chr <= 90; + } + +FS.staticInit();__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });__ATEXIT__.push({ func: function() { FS.quit() } });Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice; +___errno_state = Runtime.staticAlloc(4); HEAP32[((___errno_state)>>2)]=0; +__ATINIT__.unshift({ func: function() { TTY.init() } });__ATEXIT__.push({ func: function() { TTY.shutdown() } });TTY.utf8 = new Runtime.UTF8Processor(); +if (ENVIRONMENT_IS_NODE) { var fs = require("fs"); NODEFS.staticInit(); } +__ATINIT__.push({ func: function() { SOCKFS.root = FS.mount(SOCKFS, {}, null); } }); +Module["requestFullScreen"] = function Module_requestFullScreen(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) }; + Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) }; + Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) }; + Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() }; + Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() }; + Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() } +___buildEnvironment(ENV); +STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP); + +staticSealed = true; // seal the static portion of memory + +STACK_MAX = STACK_BASE + 5242880; + +DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX); + +assert(DYNAMIC_BASE < TOTAL_MEMORY, "TOTAL_MEMORY not big enough for stack"); + + var ctlz_i8 = allocate([8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], "i8", ALLOC_DYNAMIC); + var cttz_i8 = allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0], "i8", ALLOC_DYNAMIC); + +var Math_min = Math.min; +function invoke_iiii(index,a1,a2,a3) { + try { + return Module["dynCall_iiii"](index,a1,a2,a3); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_iddiii(index,a1,a2,a3,a4,a5) { + try { + return Module["dynCall_iddiii"](index,a1,a2,a3,a4,a5); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_vii(index,a1,a2) { + try { + Module["dynCall_vii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_iii(index,a1,a2) { + try { + return Module["dynCall_iii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function asmPrintInt(x, y) { + Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack); +} +function asmPrintFloat(x, y) { + Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack); +} +// EMSCRIPTEN_START_ASM +var asm=(function(global,env,buffer){"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=env.cttz_i8|0;var n=env.ctlz_i8|0;var o=env._stderr|0;var p=0;var q=0;var r=0;var s=0;var t=+env.NaN,u=+env.Infinity;var v=0,w=0,x=0,y=0,z=0.0,A=0,B=0,C=0,D=0.0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=0;var M=0;var N=0;var O=global.Math.floor;var P=global.Math.abs;var Q=global.Math.sqrt;var R=global.Math.pow;var S=global.Math.cos;var T=global.Math.sin;var U=global.Math.tan;var V=global.Math.acos;var W=global.Math.asin;var X=global.Math.atan;var Y=global.Math.atan2;var Z=global.Math.exp;var _=global.Math.log;var $=global.Math.ceil;var aa=global.Math.imul;var ba=env.abort;var ca=env.assert;var da=env.asmPrintInt;var ea=env.asmPrintFloat;var fa=env.min;var ga=env.invoke_iiii;var ha=env.invoke_iddiii;var ia=env.invoke_vii;var ja=env.invoke_iii;var ka=env._fabs;var la=env._sin;var ma=env._exp;var na=env._llvm_pow_f64;var oa=env._acos;var pa=env._atan2;var qa=env._fmod;var ra=env._lseek;var sa=env.__reallyNegative;var ta=env._asin;var ua=env._atan;var va=env.___buildEnvironment;var wa=env._fflush;var xa=env._pwrite;var ya=env._strerror_r;var za=env._fprintf;var Aa=env._open;var Ba=env._fabsf;var Ca=env._sbrk;var Da=env._send;var Ea=env._snprintf;var Fa=env._llvm_bswap_i32;var Ga=env._emscripten_memcpy_big;var Ha=env._fileno;var Ia=env._sysconf;var Ja=env.___setErrNo;var Ka=env._cos;var La=env._pread;var Ma=env._printf;var Na=env._sprintf;var Oa=env._log;var Pa=env._toupper;var Qa=env._write;var Ra=env._isupper;var Sa=env.___errno_location;var Ta=env._recv;var Ua=env._tan;var Va=env._copysign;var Wa=env._getenv;var Xa=env._mkport;var Ya=env.__exit;var Za=env._read;var _a=env._abort;var $a=env._islower;var ab=env._fwrite;var bb=env._time;var cb=env._isdigit;var db=env._strerror;var eb=env.__formatString;var fb=env._isspace;var gb=env._sqrt;var hb=env._exit;var ib=env._close;var jb=0.0; +// EMSCRIPTEN_START_FUNCS +function ob(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+7&-8;return b|0}function pb(){return i|0}function qb(a){a=a|0;i=a}function rb(a,b){a=a|0;b=b|0;if((p|0)==0){p=a;q=b}}function sb(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0]}function tb(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0];a[k+4|0]=a[b+4|0];a[k+5|0]=a[b+5|0];a[k+6|0]=a[b+6|0];a[k+7|0]=a[b+7|0]}function ub(a){a=a|0;E=a}function vb(a){a=a|0;F=a}function wb(a){a=a|0;G=a}function xb(a){a=a|0;H=a}function yb(a){a=a|0;I=a}function zb(a){a=a|0;J=a}function Ab(a){a=a|0;K=a}function Bb(a){a=a|0;L=a}function Cb(a){a=a|0;M=a}function Db(a){a=a|0;N=a}function Eb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;if((d|0)>0){f=Ob(b,d)|0}else{f=Pb(b)|0}b=(f|0)==0;if(!b){Xb(f,hc(f)|0)}d=c[1086]|0;if((d|0)==0){c[1086]=10;g=gg(41040)|0;c[1088]=g;if((g|0)==0){h=-4;i=e;return h|0}else{j=10}}else{j=d}d=c[1090]|0;a:do{if((d|0)<(j|0)){k=d}else{g=j;l=c[1088]|0;while(1){m=g+10|0;c[1086]=m;n=jg(l,m*4104|0)|0;c[1088]=n;if((n|0)==0){h=-3;break}m=c[1086]|0;o=c[1090]|0;if((o|0)<(m|0)){k=o;break a}else{g=m;l=n}}i=e;return h|0}}while(0);if(b){h=-1;i=e;return h|0}c[(c[1088]|0)+(k*4104|0)>>2]=f;f=c[1088]|0;c[f+(k*4104|0)+4>>2]=0;a[f+((c[1090]|0)*4104|0)+8|0]=0;c[1090]=(c[1090]|0)+1;h=k;i=e;return h|0}function Fb(b,d,e){b=b|0;d=+d;e=+e;var f=0,g=0,h=0,j=0,k=0;f=i;g=c[1088]|0;h=c[g+(b*4104|0)>>2]|0;if((h|0)==0){j=0;i=f;return j|0}k=g+(b*4104|0)+8|0;a[k]=0;dc(h,d+-1.0,e+-1.0,k,4096)|0;j=k;i=f;return j|0}function Gb(b,d,e){b=b|0;d=+d;e=+e;var f=0,g=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+4144|0;g=f+16|0;j=f+40|0;l=f+8|0;m=f;if((b|0)>0&(c[1086]|0)>(b|0)){n=(c[1088]|0)+(b*4104|0)|0}else{n=0}b=c[n>>2]|0;if((b|0)==0){o=0;i=f;return o|0}cc(b,d,e,l,m,f+32|0);e=+h[m>>3]+1.0;h[k>>3]=+h[l>>3]+1.0;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];l=g+8|0;h[k>>3]=e;c[l>>2]=c[k>>2];c[l+4>>2]=c[k+4>>2];Ea(j|0,4095,8,g|0)|0;g=n+8|0;n=a[j]|0;a:do{if(!(n<<24>>24==0)){l=j;m=n;while(1){b=l+1|0;if((fb(m<<24>>24|0)|0)==0){break}m=a[b]|0;if(m<<24>>24==0){break a}else{l=b}}m=a[l]|0;if(!(m<<24>>24==0)){b=g;p=l;q=m;while(1){m=p+1|0;r=b+1|0;a[b]=q;s=a[m]|0;if(s<<24>>24==0){break}else{b=r;p=m;q=s}}a[r]=0;if((r|0)==(g|0)){o=g;i=f;return o|0}q=r;p=r-g|0;while(1){b=q+ -1|0;if((fb(a[b]|0)|0)==0){o=g;t=14;break}a[b]=0;l=p+ -1|0;if((l|0)==0){o=g;t=14;break}else{q=b;p=l}}if((t|0)==14){i=f;return o|0}}}}while(0);a[g]=0;o=g;i=f;return o|0}function Hb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;if((b|0)>0&(c[1086]|0)>(b|0)){f=(c[1088]|0)+(b*4104|0)|0}else{f=0}b=c[f>>2]|0;if((b|0)==0){g=0;i=e;return g|0}h=f+8|0;a[h]=0;do{if((d|0)!=0?(a[d]|0)!=0:0){if(((xg(d,24)|0)!=0?(xg(d,40)|0)!=0:0)?(xg(d,56)|0)!=0:0){if(!(+oc(d)>0.0)){break}j=c[f>>2]|0}else{j=b}Xb(j,d)}}while(0);Hg(h|0,fc(c[f>>2]|0)|0,4096)|0;if((xg(h,24)|0)==0){k=h+0|0;l=24|0;m=k+9|0;do{a[k]=a[l]|0;k=k+1|0;l=l+1|0}while((k|0)<(m|0));g=h;i=e;return g|0}if((xg(h,40)|0)==0){k=h+0|0;l=40|0;m=k+9|0;do{a[k]=a[l]|0;k=k+1|0;l=l+1|0}while((k|0)<(m|0));g=h;i=e;return g|0}l=a[h]|0;if(l<<24>>24==0){g=h;i=e;return g|0}else{n=h;o=l}while(1){if(($a(o<<24>>24|0)|0)!=0){a[n]=Pa(a[n]|0)|0}l=n+1|0;k=a[l]|0;if(k<<24>>24==0){g=h;break}else{n=l;o=k}}i=e;return g|0}function Ib(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;if((b|0)>0&(c[1086]|0)>(b|0)){f=(c[1088]|0)+(b*4104|0)|0}else{f=0}b=c[f>>2]|0;if((b|0)==0){g=0;i=e;return g|0}h=f+8|0;a[h]=0;do{if((d|0)!=0?(a[d]|0)!=0:0){if((xg(d,64)|0)==0){gc(b,1)|0;c[f+4>>2]=1;break}else{gc(b,0)|0;c[f+4>>2]=0;break}}}while(0);b=c[f+4>>2]|0;if((b|0)==1){Hg(h|0,64,4095)|0}else if((b|0)==0){Hg(h|0,72,4095)|0}b=a[h]|0;if(b<<24>>24==0){g=h;i=e;return g|0}else{j=h;k=b}while(1){if((Ra(k<<24>>24|0)|0)!=0){a[j]=Jg(a[j]|0)|0}b=j+1|0;f=a[b]|0;if(f<<24>>24==0){g=h;break}else{j=b;k=f}}i=e;return g|0}function Jb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0.0,C=0.0,D=0,E=0.0,F=0.0,G=0,H=0,I=0.0,J=0.0,K=0.0;e=i;i=i+12352|0;f=e+32|0;g=e+56|0;j=e+4152|0;l=e+8248|0;m=e+48|0;n=e+52|0;o=e+24|0;p=e;q=e+8|0;r=e+16|0;if((b|0)>0&(c[1086]|0)>(b|0)){s=(c[1088]|0)+(b*4104|0)|0}else{s=0}c[m>>2]=0;c[n>>2]=0;if((c[s>>2]|0)==0){t=0;i=e;return t|0}u=Hb(b,0)|0;if(((yg(u,24)|0)!=0?(yg(u,40)|0)!=0:0)?(yg(u,56)|0)!=0:0){v=0}else{v=1}u=s+8|0;a[u]=0;b=cg(d)|0;d=fg(b,88)|0;if((d|0)!=0){w=s+4|0;x=(v|0)==0;v=d;do{d=$f(v,32)|0;if((d|0)==0){c[m>>2]=96;y=96;z=0}else{A=d+1|0;c[m>>2]=A;a[d]=0;y=A;z=v}B=+wg(y,n);if(B!=0.0?(C=+wg(c[n>>2]|0,m),C!=0.0):0){bc(c[s>>2]|0,B,C,o,p);A=(z|0)!=0;if(A){c[f>>2]=z;Ea(g|0,4096,104,f|0)|0;dg(u,g,4095)|0}d=c[w>>2]|0;if((d|0)==0){C=+h[o>>3];if(x){Tc(j,4095,C,3)}else{Uc(j,4095,C,3)}Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,128,f|0)|0;dg(u,g,4095)|0}else if((d|0)==1){C=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];d=f+8|0;h[k>>3]=C;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];Ea(g|0,4096,112,f|0)|0;dg(u,g,4095)|0}else{C=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];d=f+8|0;h[k>>3]=C;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];Ea(g|0,4096,112,f|0)|0;dg(u,g,4095)|0}d=(yg(z,136)|0)==0;C=+wg(c[m>>2]|0,n);D=C!=0.0;a:do{if(d){if(D){if(x){B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);G=c[w>>2]|0;if((G|0)==0){Tc(j,4095,+h[o>>3],3);Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,160,f|0)|0;dg(u,g,4095)|0}else if((G|0)==1){E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}else{E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}E=+wg(c[m>>2]|0,n);if(E!=0.0){B=E}else{F=E;break}}}else{B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);G=c[w>>2]|0;if((G|0)==1){E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];H=f+8|0;h[k>>3]=E;c[H>>2]=c[k>>2];c[H+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}else if((G|0)==0){Uc(j,4095,+h[o>>3],3);Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,160,f|0)|0;dg(u,g,4095)|0}else{E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}E=+wg(c[m>>2]|0,n);if(E!=0.0){B=E}else{F=E;break}}}}else{F=C}}else{if(D){B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}I=+wg(c[m>>2]|0,n);if(!(I!=0.0)){F=B;break a}J=+wg(c[n>>2]|0,m);if(!(J!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);bc(c[s>>2]|0,I,J,q,r);J=+ec(+h[o>>3],+h[p>>3],+h[q>>3],+h[r>>3])*3600.0;do{if(!(J<=60.0)){if(!(J<=3600.0)){h[k>>3]=J/3600.0;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,192,f|0)|0;dg(u,g,4095)|0;break}else{h[k>>3]=J/60.0;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,184,f|0)|0;dg(u,g,4095)|0;break}}else{h[k>>3]=J;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,176,f|0)|0;dg(u,g,4095)|0}}while(0);J=+wg(c[m>>2]|0,n);if(J!=0.0){B=J}else{F=J;break}}}else{F=C}}}while(0);if(!((yg(z,200)|0)!=0?(yg(z,208)|0)!=0:0)){if(F<0.0){C=F;while(1){B=C+6.283185307179586;if(B<0.0){C=B}else{K=B;break}}}else{K=F}h[k>>3]=K*57.29577951308232;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,216,f|0)|0;dg(u,g,4095)|0}if(A){Ea(g|0,4096,224,f|0)|0;dg(u,g,4095)|0}Ea(g|0,4096,88,f|0)|0;dg(u,g,4095)|0}v=fg(0,88)|0}while((v|0)!=0)}if((b|0)==0){t=u;i=e;return t|0}hg(b);t=u;i=e;return t|0}function Kb(a){a=a|0;var b=0,c=0.0;b=i;c=+af(a,0);i=b;return+c}function Lb(b,d,e,f,j,l,m){b=b|0;d=d|0;e=e|0;f=f|0;j=+j;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0;n=i;i=i+4128|0;o=n;p=n+20|0;q=n+16|0;r=n+24|0;bf(b,d,e,f,p,q,j,l,m);j=+g[q>>2];h[k>>3]=+g[p>>2];c[o>>2]=c[k>>2];c[o+4>>2]=c[k+4>>2];p=o+8|0;h[k>>3]=j;c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];Ea(r|0,4095,240,o|0)|0;o=a[r]|0;a:do{if(!(o<<24>>24==0)){p=r;q=o;while(1){m=p+1|0;if((fb(q<<24>>24|0)|0)==0){break}q=a[m]|0;if(q<<24>>24==0){break a}else{p=m}}q=a[p]|0;if(!(q<<24>>24==0)){m=248;l=p;f=q;while(1){q=l+1|0;s=m+1|0;a[m]=f;e=a[q]|0;if(e<<24>>24==0){break}else{m=s;l=q;f=e}}a[s]=0;if((s|0)==248){i=n;return 248}f=s;l=s-248|0;while(1){m=f+ -1|0;if((fb(a[m]|0)|0)==0){t=11;break}a[m]=0;p=l+ -1|0;if((p|0)==0){t=11;break}else{f=m;l=p}}if((t|0)==11){i=n;return 248}}}}while(0);a[248]=0;i=n;return 248}function Mb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0.0,ha=0.0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0.0,sa=0.0,ta=0.0,ua=0,va=0.0,wa=0,xa=0,ya=0.0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0.0,La=0.0,Ma=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0;e=i;i=i+1184|0;f=e+672|0;g=e+1176|0;j=e+1144|0;l=e+1112|0;m=e+1048|0;n=e+1040|0;p=e+1024|0;q=e+1032|0;r=e+1080|0;s=e+848|0;t=e;u=e+752|0;v=e+744|0;w=e+656|0;x=e+760|0;y=e+664|0;z=e+816|0;A=e+856|0;B=e+736|0;C=e+840|0;D=e+824|0;E=e+808|0;F=e+768|0;G=e+8|0;H=e+1088|0;I=e+868|0;J=e+864|0;K=e+872|0;L=e+880|0;M=e+960|0;N=e+1104|0;O=e+832|0;P=e+800|0;Q=e+728|0;R=ig(1,9336)|0;U=a[d]|0;d=U<<24>>24==32?0:U;a[N]=d;a[R+9324|0]=d;if((Oc(b,4424,N,63,M)|0)!=0){d=ig((Dg(M|0)|0)+2|0,1)|0;c[R+9320>>2]=d;Lg(d|0,M|0)|0}d=R+3984|0;c[d>>2]=0;c[R+3956>>2]=0;c[R+3924>>2]=0;c[R+3952>>2]=-1;U=R+3268|0;c[U>>2]=0;V=R+3272|0;c[V>>2]=0;h[D>>3]=0.0;h[E>>3]=0.0;W=F+8|0;X=F+16|0;Y=F+24|0;c[F+0>>2]=0;c[F+4>>2]=0;c[F+8>>2]=0;c[F+12>>2]=0;c[F+16>>2]=0;c[F+20>>2]=0;c[F+24>>2]=0;c[F+28>>2]=0;h[G>>3]=0.0;Z=R+3300|0;c[Z>>2]=0;_=R+48|0;h[_>>3]=0.0;c[K>>2]=0;Dc(b,4432,N,K)|0;$=c[K>>2]|0;if(($|0)==0){Ec(b,4432,K)|0;ba=c[K>>2]|0;if((ba|0)==0){Ec(b,4440,K)|0;ca=c[K>>2]|0;if((ca|0)==0){Ec(b,4448,K)|0;da=c[K>>2]|0}else{da=ca}}else{da=ba}}else{da=$}if((da|0)<1){_b(4456);Tb(R);ea=0;i=e;return ea|0}if((da|0)>2){c[K>>2]=2;fa=2}else{fa=da}da=R+3316|0;c[da>>2]=fa;$=R+3320|0;c[$>>2]=fa;c[R+3960>>2]=fa;fa=R+136|0;h[fa>>3]=0.0;Lc(b,4504,fa)|0;ga=+h[fa>>3];if(ga<1.0){Lc(b,4512,fa)|0;ha=+h[fa>>3]}else{ha=ga}if(ha<1.0){_b(4520);Tb(R);ea=0;i=e;return ea|0}ba=R+144|0;h[ba>>3]=0.0;Lc(b,4560,ba)|0;if(+h[ba>>3]<1.0){Lc(b,4568,ba)|0}ca=c[K>>2]|0;if((ca|0)>1){if(+h[ba>>3]<1.0){_b(4576);Tb(R);ea=0;i=e;return ea|0}else{ia=19}}else{if((ca|0)>0){ia=19}else{ja=0}}if((ia|0)==19){ca=c[o>>2]|0;ka=0;la=0;while(1){a[H+0|0]=a[4440|0]|0;a[H+1|0]=a[4441|0]|0;a[H+2|0]=a[4442|0]|0;a[H+3|0]=a[4443|0]|0;a[H+4|0]=a[4444|0]|0;a[H+5|0]=a[4445|0]|0;ma=ka+1|0;c[f>>2]=ma;Na(L|0,4616,f|0)|0;Fg(H|0,L|0)|0;do{if((Ec(b,H,J)|0)==0){if((ka|0)==0){ha=+h[fa>>3];if(ha>1.0){c[J>>2]=~~ha;break}}else if((ka|0)==1?(ha=+h[ba>>3],ha>1.0):0){c[J>>2]=~~ha;break}c[f>>2]=H;za(ca|0,4624,f|0)|0}}while(0);a[H+0|0]=a[4664|0]|0;a[H+1|0]=a[4665|0]|0;a[H+2|0]=a[4666|0]|0;a[H+3|0]=a[4667|0]|0;a[H+4|0]=a[4668|0]|0;a[H+5|0]=a[4669|0]|0;Fg(H|0,L|0)|0;if((Pc(b,H,16,L)|0)!=0?(Qc(L,4672)|0)!=0:0){c[J>>2]=0}na=((c[J>>2]|0)>1)+la|0;if((ma|0)<(c[K>>2]|0)){ka=ma;la=na}else{ja=na;break}}}c[K>>2]=ja;c[$>>2]=ja;c[da>>2]=ja;Pc(b,4680,16,R+3336|0)|0;Ec(b,4696,R+3332|0)|0;ja=R+3324|0;c[ja>>2]=kc()|0;$=R+9328|0;c[$>>2]=0;Ec(b,4712,$)|0;$=R+832|0;Eg($|0,0,648)|0;Eg(G|0,0,648)|0;la=c[K>>2]|0;ka=(la|0)>0;if(ka){ca=0;do{h[$+((aa(la,ca)|0)+ca<<3)>>3]=1.0;ca=ca+1|0}while((ca|0)<(la|0));if(ka){ca=0;do{h[G+((aa(la,ca)|0)+ca<<3)>>3]=1.0;ca=ca+1|0}while((ca|0)<(la|0));ca=R+760|0;oa=ca+0|0;pa=oa+72|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));if(ka){ka=0;while(1){h[ca+(ka<<3)>>3]=1.0;na=ka+1|0;if((na|0)<(la|0)){ka=na}else{qa=ca;break}}}else{qa=ca}}else{ia=37}}else{ia=37}if((ia|0)==37){ca=R+760|0;oa=ca+0|0;pa=oa+72|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));qa=ca}do{if((Oc(b,4720,N,63,M)|0)==0){c[R+9312>>2]=0}else{ca=Nb(b,M)|0;a[g]=ca;if(!(ca<<24>>24==95)){ca=Mb(b,g)|0;c[R+9312>>2]=ca;if((ca|0)!=0){c[ca+9316>>2]=R;break}}else{ca=c[o>>2]|0;c[f>>2]=M;za(ca|0,4368,f|0)|0;c[R+9312>>2]=0}_b(4728);Tb(R);ea=0;i=e;return ea|0}}while(0);M=R+3224|0;g=R+3232|0;c[M+0>>2]=0;c[M+4>>2]=0;c[M+8>>2]=0;c[M+12>>2]=0;do{if((Kc(b,4776,N,M)|0)==0){if((Kc(b,4784,N,g)|0)!=0){h[M>>3]=+h[g>>3]*299792.5;break}if((Lc(b,4792,M)|0)!=0){h[g>>3]=+h[M>>3]/299792.5}}else{h[g>>3]=+h[M>>3]/299792.5}}while(0);M=R+4096|0;oa=M+0|0;pa=oa+80|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));do{if((Oc(b,4808,N,16,j)|0)==0){g=a[N]|0;if(!(g<<24>>24==32|g<<24>>24==0)){c[f>>2]=g<<24>>24;Na(L|0,5368,f|0)|0;_b(L);Tb(R);ea=0;i=e;return ea|0}if((Cc(b,5408)|0)!=0){c[R+3260>>2]=29;g=Cc(b,5408)|0;Lc(g,5408,s)|0;Lc(g,5416,t)|0;Lc(g,5424,u)|0;h[R+152>>3]=(+h[s>>3]+ +h[t>>3]/60.0+ +h[u>>3]/3600.0)*15.0*3.141592653589793/180.0;a[r]=43;Pc(g,5432,1,r)|0;ha=(a[r]|0)==45?-1.0:1.0;Lc(g,5448,v)|0;Lc(g,5456,w)|0;Lc(g,5464,x)|0;h[R+160>>3]=ha*(+h[v>>3]+ +h[w>>3]/60.0+ +h[x>>3]/3600.0)*3.141592653589793/180.0;g=R+120|0;Lc(b,5472,g)|0;Ec(b,5472,I)|0;ca=R+3764|0;ka=(c[I>>2]|0)==1950?3427142:3492678;a[ca]=ka;a[ca+1|0]=ka>>8;a[ca+2|0]=ka>>16;a[ca+3|0]=ka>>24;ka=R+128|0;h[ka>>3]=+h[g>>3];Lc(b,5344,ka)|0;ha=+h[t>>3];ga=+h[u>>3];ka=a[r]|0;ra=+h[v>>3];sa=+h[w>>3];ta=+h[x>>3];h[k>>3]=+h[s>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];g=f+8|0;h[k>>3]=ha;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];g=f+16|0;h[k>>3]=ga;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];c[f+24>>2]=ka;ka=f+28|0;h[k>>3]=ra;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];ka=f+36|0;h[k>>3]=sa;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];ka=f+44|0;h[k>>3]=ta;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];c[f+52>>2]=ca;Na(R+3892|0,5496,f|0)|0;Lc(b,5544,R+168|0)|0;Lc(b,5560,R+192|0)|0;Lc(b,5576,R+200|0)|0;Lc(b,5592,R+176|0)|0;Lc(b,5600,R+184|0)|0;ca=Cc(b,5608)|0;ka=R+208|0;c[f>>2]=1;Na(H|0,5616,f|0)|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=2;Na(H|0,5616,f|0)|0;ka=R+216|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=3;Na(H|0,5616,f|0)|0;ka=R+224|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=4;Na(H|0,5616,f|0)|0;ka=R+232|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=5;Na(H|0,5616,f|0)|0;ka=R+240|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=6;Na(H|0,5616,f|0)|0;ka=R+248|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;ka=Cc(b,5624)|0;ca=R+256|0;g=0;while(1){la=g+1|0;c[f>>2]=la;Na(H|0,5632,f|0)|0;na=ca+(g<<3)|0;h[na>>3]=0.0;Lc(ka,H,na)|0;if((la|0)==20){break}else{g=la}}g=Cc(b,5640)|0;ka=R+416|0;ca=0;while(1){ma=ca+1|0;c[f>>2]=ma;Na(H|0,5648,f|0)|0;la=ka+(ca<<3)|0;h[la>>3]=0.0;Lc(g,H,la)|0;if((ma|0)==20){break}else{ca=ma}}ca=R+3312|0;c[ca>>2]=1;g=R+3449|0;a[g+0|0]=a[5656|0]|0;a[g+1|0]=a[5657|0]|0;a[g+2|0]=a[5658|0]|0;g=R+3458|0;a[g]=4408644;a[g+1|0]=17221;a[g+2|0]=67;a[g+3|0]=0;g=R+3467|0;a[g]=5460804;a[g+1|0]=21331;a[g+2|0]=83;a[g+3|0]=0;c[R+3292>>2]=0;c[R+3288>>2]=3;oa=R+3368|0;g=5664|0;pa=oa+9|0;do{a[oa]=a[g]|0;oa=oa+1|0;g=g+1|0}while((oa|0)<(pa|0));oa=R+3377|0;g=5680|0;pa=oa+9|0;do{a[oa]=a[g]|0;oa=oa+1|0;g=g+1|0}while((oa|0)<(pa|0));ta=+h[fa>>3]*.5;g=R+616|0;h[g>>3]=ta;sa=+h[ba>>3]*.5;ka=R+624|0;h[ka>>3]=sa;h[R+16>>3]=ta;h[R+24>>3]=sa;nd(ta,sa,R,z,B)|0;sa=+h[z>>3];h[R+688>>3]=sa;ta=+h[B>>3];h[R+696>>3]=ta;h[R>>3]=sa;h[R+8>>3]=ta;nd(+h[g>>3],+h[ka>>3]+1.0,R,A,C)|0;ta=+h[C>>3]- +h[B>>3];h[R+40>>3]=ta;h[R+32>>3]=-ta;Sb(R);c[ca>>2]=1;ac(R);ta=+h[_>>3]*3.141592653589793/180.0;h[P>>3]=ta;sa=+h[g>>3]+ +S(+ta);nd(sa,+h[ka>>3]+ +T(+ta),R,A,C)|0;h[qa>>3]=-+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);ta=+h[P>>3];sa=+h[g>>3]+ +T(+ta);nd(sa,+h[ka>>3]+ +S(+ta),R,A,C)|0;ta=+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[R+768>>3]=ta;Wb(R,+h[qa>>3],ta,+h[_>>3]);ua=qa;break}if(((((Cc(b,5088)|0)==0?(Cc(b,5096)|0)==0:0)?(Cc(b,5112)|0)==0:0)?(Cc(b,5128)|0)==0:0)?(Cc(b,5144)|0)==0:0){_b(5824);Tb(R);ea=0;i=e;return ea|0}h[y>>3]=0.0;Lc(b,5088,y)|0;ta=+h[y>>3];if(ta==0.0){Lc(b,5096,y)|0;va=+h[y>>3]}else{va=ta}do{if(va==0.0){Lc(b,5144,y)|0;ta=+h[y>>3];if(ta!=0.0){h[D>>3]=-ta/3600.0;Lc(b,5152,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}Lc(b,5128,y)|0;ta=+h[y>>3];if(ta!=0.0){h[D>>3]=-ta/3600.0;Lc(b,5160,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}else{Lc(b,5112,y)|0;h[D>>3]=-+h[y>>3]/3600.0;Lc(b,5176,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}}else{ta=va/3600.0;h[E>>3]=ta;h[D>>3]=-ta}}while(0);h[P>>3]=0.0;Lc(b,5256,P)|0;if(+h[_>>3]==0.0){Lc(b,5248,P)|0}Wb(R,+h[D>>3],+h[E>>3],+h[P>>3]);ca=R+616|0;h[ca>>3]=+h[fa>>3]*.5+.5;ka=R+624|0;h[ka>>3]=+h[ba>>3]*.5+.5;if((Cc(b,4904)|0)!=0){Lc(b,4904,ca)|0;Lc(b,4912,ka)|0}h[R+16>>3]=+h[ca>>3];h[R+24>>3]=+h[ka>>3];ka=R+688|0;h[ka>>3]=-999.0;if((Hc(b,5656,ka)|0)==0){_b(5696);Tb(R);ea=0;i=e;return ea|0}ca=R+696|0;h[ca>>3]=-999.0;if((Ic(b,4832,ca)|0)==0){_b(5736);Tb(R);ea=0;i=e;return ea|0}ta=+h[ka>>3];h[R>>3]=ta;sa=+h[ca>>3];h[R+8>>3]=sa;ca=R+3304|0;c[ca>>2]=0;h[R+3992>>3]=ta;h[R+4e3>>3]=sa;ka=R+4008|0;h[ka>>3]=999.0;if((Lc(b,4936,ka)|0)==0){Lc(b,5776,ka)|0}ka=R+4016|0;h[ka>>3]=999.0;Lc(b,4944,ka)|0;do{if((Lc(b,5312,O)|0)==0){ka=R+128|0;if((Mc(b,5320,ka)|0)==0){if((Mc(b,5336,ka)|0)!=0){break}if((Lc(b,5344,ka)|0)!=0){break}h[ka>>3]=+h[R+120>>3];break}Pc(b,5320,32,m)|0;if(($f(m,84)|0)==0){if((Lc(b,5352,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744;break}if((Lc(b,5360,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744}}}else{h[R+128>>3]=(+h[O>>3]+-15019.81352)/365.242198781+1900.0}}while(0);Vb(R,5792,5808)|0;c[ca>>2]=0;a[f]=0;Rb(b,R,f);Sb(R);c[R+3292>>2]=0;c[R+3288>>2]=3;c[R+3312>>2]=1;ua=qa}else{Lg(l|0,j|0)|0;ka=(Oc(b,4816,N,16,l)|0)==0;Lg(R+3368|0,j|0)|0;Lg(R+3377|0,l|0)|0;if((Qc(l,4824)|0)==0){g=(Qc(l,4832)|0)==0;wa=g?1:2}else{wa=2}g=R+3386|0;a[g]=0;Oc(b,4840,N,9,g)|0;g=R+3395|0;a[g]=0;Oc(b,4848,N,9,g)|0;if((Vb(R,j,l)|0)!=0){Tb(R);ea=0;i=e;return ea|0}g=R+3260|0;if((c[g>>2]|0)==0){ma=R+3476|0;if((Oc(b,4856,N,16,ma)|0)==0?(Yc(b,4864,4872,16,ma)|0)==0:0){a[ma]=0}if((yg(ma,4880)|0)==0){c[g>>2]=-1}if(!ka){ka=R+3508|0;if((Oc(b,4888,N,16,ka)|0)==0?(Yc(b,4896,4872,16,ka)|0)==0:0){a[ka]=0}if((yg(ma,4880)|0)==0){c[g>>2]=-1}}}ma=R+616|0;h[ma>>3]=1.0;Kc(b,4904,N,ma)|0;ka=R+624|0;h[ka>>3]=1.0;Kc(b,4912,N,ka)|0;h[R+16>>3]=+h[ma>>3];h[R+24>>3]=+h[ka>>3];la=R+688|0;h[la>>3]=0.0;Kc(b,4920,N,la)|0;na=R+696|0;h[na>>3]=0.0;Kc(b,4928,N,na)|0;xa=c[R+3884>>2]|0;if((xa|0)==7){h[na>>3]=90.0- +h[na>>3];ia=74}else if((xa|0)==8){sa=+h[na>>3]+-90.0;h[na>>3]=sa;ya=sa}else{ia=74}if((ia|0)==74){ya=+h[na>>3]}sa=+h[la>>3];h[R>>3]=sa;h[R+8>>3]=ya;la=R+3992|0;if((c[R+3304>>2]|0)==0){h[la>>3]=sa;h[R+4e3>>3]=ya}else{h[la>>3]=ya;h[R+4e3>>3]=sa}la=R+3176|0;h[la>>3]=999.0;Kc(b,4936,N,la)|0;h[R+4008>>3]=+h[la>>3];la=R+3184|0;h[la>>3]=999.0;Kc(b,4944,N,la)|0;h[R+4016>>3]=+h[la>>3];c[R+3964>>2]=ma;c[R+3972>>2]=qa;c[R+3968>>2]=$;la=R+4088|0;h[la>>3]=0.0;Kc(b,4952,N,la)|0;c[f>>2]=0;Na(H|0,4960,f|0)|0;Kc(b,H,N,M)|0;c[f>>2]=1;Na(H|0,4960,f|0)|0;la=R+4104|0;Kc(b,H,N,la)|0;c[f>>2]=2;Na(H|0,4960,f|0)|0;na=R+4112|0;Kc(b,H,N,na)|0;c[f>>2]=3;Na(H|0,4960,f|0)|0;xa=R+4120|0;Kc(b,H,N,xa)|0;c[f>>2]=4;Na(H|0,4960,f|0)|0;Aa=R+4128|0;Kc(b,H,N,Aa)|0;c[f>>2]=5;Na(H|0,4960,f|0)|0;Ba=R+4136|0;Kc(b,H,N,Ba)|0;c[f>>2]=6;Na(H|0,4960,f|0)|0;Ca=R+4144|0;Kc(b,H,N,Ca)|0;c[f>>2]=7;Na(H|0,4960,f|0)|0;Da=R+4152|0;Kc(b,H,N,Da)|0;c[f>>2]=8;Na(H|0,4960,f|0)|0;Ea=R+4160|0;Kc(b,H,N,Ea)|0;c[f>>2]=9;Na(H|0,4960,f|0)|0;Fa=R+4168|0;Kc(b,H,N,Fa)|0;c[f>>2]=wa;Na(n|0,4968,f|0)|0;c[f>>2]=wa;Na(p|0,4976,f|0)|0;c[f>>2]=wa;Na(q|0,4984,f|0)|0;Ga=c[g>>2]|0;switch(Ga|0){case 7:{c[f>>2]=wa;c[f+4>>2]=0;Na(H|0,4992,f|0)|0;Kc(b,H,N,M)|0;c[f>>2]=wa;c[f+4>>2]=1;Na(H|0,4992,f|0)|0;Kc(b,H,N,la)|0;c[f>>2]=wa;c[f+4>>2]=2;Na(H|0,4992,f|0)|0;Kc(b,H,N,na)|0;c[f>>2]=wa;c[f+4>>2]=3;Na(H|0,4992,f|0)|0;Kc(b,H,N,xa)|0;c[f>>2]=wa;c[f+4>>2]=4;Na(H|0,4992,f|0)|0;Kc(b,H,N,Aa)|0;c[f>>2]=wa;c[f+4>>2]=5;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ba)|0;c[f>>2]=wa;c[f+4>>2]=6;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ca)|0;c[f>>2]=wa;c[f+4>>2]=7;Na(H|0,4992,f|0)|0;Kc(b,H,N,Da)|0;c[f>>2]=wa;c[f+4>>2]=8;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ea)|0;c[f>>2]=wa;c[f+4>>2]=9;Na(H|0,4992,f|0)|0;Kc(b,H,N,Fa)|0;ia=97;break};case 17:case 15:case 16:case 14:case 4:case 1:{Kc(b,n,N,R+4104|0)|0;Kc(b,p,N,R+4112|0)|0;ia=97;break};case 2:{Kc(b,n,N,R+4104|0)|0;Kc(b,p,N,R+4112|0)|0;Fa=R+4120|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=90.0}Kc(b,q,N,Fa)|0;ia=97;break};case 13:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,n,N,Fa)|0;ia=97;break};case 10:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,n,N,Fa)|0;Fa=R+4112|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,p,N,Fa)|0;ia=97;break};case 9:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=90.0}Kc(b,n,N,Fa)|0;ia=97;break};case 18:{Kc(b,n,N,R+4104|0)|0;ia=97;break};default:{Ha=Ga}}if((ia|0)==97){Ha=c[g>>2]|0}do{if((Ha|0)==31){if((dd(b,R)|0)==0){Ia=c[g>>2]|0;ia=102;break}else{a[R+3374|0]=65;a[R+3375|0]=78;a[R+3383|0]=65;a[R+3384|0]=78;c[g>>2]=3;break}}else{Ia=Ha;ia=102}}while(0);a:do{if((ia|0)==102){do{if((Ia|0)==32){if((kd(b,R)|0)==0){Ja=c[g>>2]|0;break}else{a[R+3375|0]=78;a[R+3384|0]=78;c[g>>2]=7;break a}}else{Ja=Ia}}while(0);if((Ja|0)==33){a[R+3374|0]=65;a[R+3375|0]=78;a[R+3383|0]=65;a[R+3384|0]=78;c[g>>2]=3}}}while(0);if((c[ja>>2]|0)>0){Rb(b,R,N)}Sb(R);Ye(R,b);c[U>>2]=0;c[V>>2]=0;ca=Kc(b,5e3,N,F)|0;Ga=Kc(b,5008,N,W)|0;Fa=Kc(b,5016,N,X)|0;Ea=Kc(b,5024,N,Y)|0;if((c[ja>>2]|0)!=2?(Da=Cc(b,5032)|0,(Da|0)!=0):0){c[g>>2]=30;Ca=R+3467|0;a[Ca+0|0]=a[5040|0]|0;a[Ca+1|0]=a[5041|0]|0;a[Ca+2|0]=a[5042|0]|0;a[Ca+3|0]=a[5043|0]|0;a[Ca+4|0]=a[5044|0]|0;a[Ca+5|0]=a[5045|0]|0;Ca=R+256|0;Ba=0;while(1){Aa=Ba+1|0;c[f>>2]=Aa;Na(H|0,5048,f|0)|0;xa=Ca+(Ba<<3)|0;h[xa>>3]=0.0;if((Lc(Da,H,xa)|0)!=0){c[U>>2]=Aa}if((Aa|0)==20){break}else{Ba=Aa}}Ba=Cc(b,5056)|0;Da=R+416|0;Ca=0;while(1){Aa=Ca+1|0;c[f>>2]=Aa;Na(H|0,5064,f|0)|0;xa=Da+(Ca<<3)|0;h[xa>>3]=0.0;if((Lc(Ba,H,xa)|0)!=0){c[V>>2]=Aa}if((Aa|0)==20){break}else{Ca=Aa}}bd(+h[ma>>3],+h[ka>>3],R,z,B)|0;bd(+h[ma>>3],+h[ka>>3]+1.0,R,A,C)|0;sa=+h[C>>3]- +h[B>>3];Ca=R+40|0;h[Ca>>3]=sa;Ba=R+32|0;h[Ba>>3]=-sa;c[R+3312>>2]=1;ac(R);h[P>>3]=+h[_>>3]*3.141592653589793/180.0;bd(+h[ma>>3],+h[ka>>3],R,z,B)|0;sa=+h[P>>3];ta=+h[ma>>3]+ +S(+sa);bd(ta,+h[ka>>3]+ +T(+sa),R,A,C)|0;sa=-+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[qa>>3]=sa;h[Ba>>3]=sa;sa=+h[P>>3];ta=+h[ma>>3]+ +T(+sa);bd(ta,+h[ka>>3]+ +S(+sa),R,A,C)|0;sa=+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[R+768>>3]=sa;h[Ca>>3]=sa;Ca=R+56|0;h[Ca>>3]=+h[F>>3];h[R+64>>3]=+h[W>>3];h[R+72>>3]=+h[X>>3];h[R+80>>3]=+h[Y>>3];Bd(2,Ca,R+88|0)|0}else{ia=121}do{if((ia|0)==121){if((Ga|ca|Fa|Ea|0)!=0){c[Z>>2]=1;Zb(R,F);break}if((Kc(b,5072,N,D)|0)==0){h[R+32>>3]=1.0;h[R+40>>3]=1.0;h[qa>>3]=1.0;h[R+768>>3]=1.0;h[_>>3]=0.0;c[Z>>2]=0;_b(5264);break}Kc(b,5080,N,E)|0;if(!(+h[D>>3]==0.0)){if(+h[ba>>3]>1.0){sa=+h[E>>3];if(sa==0.0){ia=127}else{Ka=sa}}else{ia=154}}else{ia=127}do{if((ia|0)==127){if(((((Cc(b,5088)|0)==0?(Cc(b,5096)|0)==0:0)?(Cc(b,5112)|0)==0:0)?(Cc(b,5128)|0)==0:0)?(Cc(b,5144)|0)==0:0){ia=154;break}h[y>>3]=0.0;Lc(b,5088,y)|0;sa=+h[y>>3];if(sa==0.0){Lc(b,5096,y)|0;La=+h[y>>3]}else{La=sa}if(!(La==0.0)){if(+h[D>>3]==0.0){h[D>>3]=-La/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}sa=La/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5144,y)|0;sa=+h[y>>3];if(sa!=0.0){if(+h[D>>3]==0.0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}Lc(b,5152,y)|0;sa=+h[y>>3]/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5128,y)|0;sa=+h[y>>3];if(sa!=0.0){if(+h[D>>3]==0.0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}Lc(b,5160,y)|0;sa=+h[y>>3]/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5112,y)|0;sa=+h[y>>3];if(sa!=0.0?+h[D>>3]==0.0:0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(sa==0.0){Lc(b,5176,y)|0;ta=+h[y>>3]/3600.0;h[E>>3]=ta;Ka=ta}else{Ka=sa}}}while(0);if((ia|0)==154){Ka=+h[E>>3]}if(Ka==0.0?+h[ba>>3]>1.0:0){h[E>>3]=-+h[D>>3]}h[R+776>>3]=1.0;h[R+784>>3]=1.0;Eg(G|0,0,648)|0;Eg($|0,0,648)|0;Ca=c[K>>2]|0;if((Ca|0)>0){Ba=0;do{h[G+((aa(Ca,Ba)|0)+Ba<<3)>>3]=1.0;Ba=Ba+1|0}while((Ba|0)<(Ca|0))}if((a[N]|0)==0?(Lc(b,5192,G)|0)!=0:0){Ca=c[K>>2]|0;if((Ca|0)>0){Ba=Ca;Ca=0;Da=0;while(1){c[J>>2]=0;Aa=Ca+1|0;if((Ba|0)>0){xa=0;na=Da;while(1){la=G+(na<<3)|0;h[la>>3]=(Ca|0)==(xa|0)?1.0:0.0;c[f>>2]=Aa;c[f+4>>2]=xa+1;Na(H|0,5208,f|0)|0;Ma=na+1|0;Lc(b,H,la)|0;la=(c[J>>2]|0)+1|0;c[J>>2]=la;Oa=c[K>>2]|0;if((la|0)<(Oa|0)){xa=la;na=Ma}else{Pa=Oa;Qa=Ma;break}}}else{Pa=Ba;Qa=Da}if((Aa|0)<(Pa|0)){Ba=Pa;Ca=Aa;Da=Qa}else{break}}}$b(R,+h[D>>3],+h[E>>3],G);break}if((Kc(b,5224,N,G)|0)==0){h[P>>3]=0.0;if((wa|0)==2){Kc(b,5248,N,P)|0}else{Kc(b,5256,N,P)|0}Wb(R,+h[D>>3],+h[E>>3],+h[P>>3]);break}Da=c[K>>2]|0;if((Da|0)>0){Ca=Da;Da=0;Ba=0;while(1){c[J>>2]=0;na=Da+1|0;if((Ca|0)>0){xa=0;Ma=Ba;while(1){Oa=G+(Ma<<3)|0;h[Oa>>3]=(Da|0)==(xa|0)?1.0:0.0;c[f>>2]=na;c[f+4>>2]=xa+1;Na(H|0,5232,f|0)|0;la=Ma+1|0;Kc(b,H,N,Oa)|0;Oa=(c[J>>2]|0)+1|0;c[J>>2]=Oa;Ra=c[K>>2]|0;if((Oa|0)<(Ra|0)){xa=Oa;Ma=la}else{Sa=Ra;Ta=la;break}}}else{Sa=Ca;Ta=Ba}if((na|0)<(Sa|0)){Ca=Sa;Da=na;Ba=Ta}else{break}}}$b(R,+h[D>>3],+h[E>>3],G)}}while(0);if((c[g>>2]|0)==3?(c[da>>2]|0)==2:0){Ea=R+3168|0;Fa=c[Ea>>2]|0;if((Fa|0)!=0){rd(Fa);c[Ea>>2]=0}Ea=R+3172|0;Fa=c[Ea>>2]|0;if((Fa|0)!=0){rd(Fa);c[Ea>>2]=0}c[R+1560>>2]=0;Ea=R+1568|0;Fa=R+4344|0;ca=0;do{h[Ea+(ca<<3)>>3]=0.0;h[Fa+(ca<<3)>>3]=0.0;ca=ca+1|0}while((ca|0)!=200);c[J>>2]=0;ca=0;g=0;while(1){c[f>>2]=1;c[f+4>>2]=g;Na(H|0,4992,f|0)|0;if((Kc(b,H,N,Ea+(c[J>>2]<<3)|0)|0)==0){Ga=c[J>>2]|0;h[Ea+(Ga<<3)>>3]=0.0;Ua=Ga;Va=ca}else{Ua=c[J>>2]|0;Va=ca+1|0}g=Ua+1|0;c[J>>2]=g;if((g|0)>=100){break}else{ca=Va}}c[J>>2]=0;ca=Va;g=0;while(1){c[f>>2]=2;c[f+4>>2]=g;Na(H|0,4992,f|0)|0;if((Kc(b,H,N,Ea+((c[J>>2]|0)+100<<3)|0)|0)==0){Ga=c[J>>2]|0;h[Ea+(Ga+100<<3)>>3]=0.0;Wa=Ga;Xa=ca}else{Wa=c[J>>2]|0;Xa=ca+1|0}g=Wa+1|0;c[J>>2]=g;if((g|0)>=100){break}else{ca=Xa}}if((Xa|0)>0){ca=R+3948|0;g=R+3944|0;Ga=100;ka=0;while(1){sa=+h[Ea+(((c[ca>>2]|0)*100|0)+Ga<<3)>>3];h[Fa+(Ga<<3)>>3]=sa;ta=+h[Ea+(((c[g>>2]|0)*100|0)+Ga<<3)>>3];h[Fa+(Ga+100<<3)>>3]=ta;if((ka|0)==0){Ya=sa!=0.0|ta!=0.0?Ga+1|0:0}else{Ya=ka}if((Ga|0)>0){Ga=Ga+ -1|0;ka=Ya}else{break}}Qb(R);c[d>>2]=0}}ka=R+3467|0;if(!((Ag(ka,5296,6)|0)!=0?(Ag(ka,5304,5)|0)!=0:0)){c[R+3292>>2]=-1;c[R+3288>>2]=5}do{if((Lc(b,5312,O)|0)==0){ka=R+128|0;if((Mc(b,5320,ka)|0)==0){if((Mc(b,5336,ka)|0)!=0){break}if((Lc(b,5344,ka)|0)!=0){break}h[ka>>3]=+h[R+120>>3];break}Pc(b,5320,32,m)|0;if(($f(m,84)|0)==0){if((Lc(b,5352,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744;break}if((Lc(b,5360,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744}}}else{h[R+128>>3]=(+h[O>>3]+-15019.81352)/365.242198781+1900.0}}while(0);c[R+3312>>2]=1;ua=qa}}while(0);c[R+3964>>2]=R+616;c[R+3972>>2]=ua;c[R+3968>>2]=$;c[R+3284>>2]=1;c[R+3296>>2]=0;c[R+3328>>2]=0;Yb(R);ea=R;i=e;return ea|0}function Nb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=i;i=i+96|0;f=e;g=e+16|0;if((d|0)==0){h=0;i=e;return h|0}j=Dg(d|0)|0;k=ig(1,j+1|0)|0;if((j|0)>0){l=0;do{m=a[d+l|0]|0;if((m+ -97<<24>>24&255)<26){a[k+l|0]=(m&255)+224}else{a[k+l|0]=m}l=l+1|0}while((l|0)!=(j|0))}a[k+j|0]=0;if((Dg(k|0)|0)==1){h=a[k]|0;i=e;return h|0}j=f;c[j>>2]=1314079575;c[j+4>>2]=4541761;a[f+8|0]=0;j=f+7|0;l=95;d=0;while(1){if((d|0)>0){n=d+64&255}else{n=0}a[j]=n;if((Pc(b,f,72,g)|0)==0){o=l}else{m=Dg(g|0)|0;p=ig(1,m+1|0)|0;if((m|0)>0){q=0;do{r=a[g+q|0]|0;if((r+ -97<<24>>24&255)<26){a[p+q|0]=(r&255)+224}else{a[p+q|0]=r}q=q+1|0}while((q|0)!=(m|0))}a[p+m|0]=0;q=(yg(p,k)|0)==0;hg(p);o=q?n:l}d=d+1|0;if((d|0)==27){break}else{l=o}}hg(k);h=o;i=e;return h|0}function Ob(b,c){b=b|0;c=c|0;var d=0,e=0;d=i;i=i+16|0;e=d;a[e]=0;Bc(b,c)|0;c=Mb(b,e)|0;i=d;return c|0}function Pb(b){b=b|0;var c=0,d=0,e=0;c=i;i=i+16|0;d=c;a[d]=0;e=Mb(b,d)|0;i=c;return e|0}function Qb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;b=i;i=i+176|0;d=b+88|0;e=b+40|0;f=b+16|0;g=b+56|0;j=b+80|0;k=b+168|0;l=b+32|0;m=b+72|0;n=b+8|0;o=b;p=j;c[p>>2]=1;c[p+4>>2]=1;p=c[a+3944>>2]|0;q=c[a+3948>>2]|0;if((c[a+3316>>2]|0)!=2){i=b;return}r=a+3928|0;if((yg(r,5848)|0)!=0){i=b;return}if(+h[a+((p*100|1)<<3)+1568>>3]==0.0?+h[a+((q*100|1)<<3)+1568>>3]==0.0:0){i=b;return}s=a+9312|0;t=c[s>>2]|0;if((t|0)==0){h[l>>3]=0.0;h[m>>3]=0.0;h[n>>3]=+h[a+136>>3];h[o>>3]=+h[a+144>>3]}else{bc(t,0.0,0.0,l,m);bc(c[s>>2]|0,+h[a+136>>3],+h[a+144>>3],n,o)}if((p|0)==0){u=+h[l>>3];v=+h[m>>3];w=v;x=+h[o>>3]-v;y=u;z=+h[n>>3]-u}else{u=+h[m>>3];v=+h[l>>3];w=v;x=+h[n>>3]-v;y=u;z=+h[o>>3]-u}u=x/11.0;x=z/11.0;o=ig(288,8)|0;n=ig(144,8)|0;l=ig(144,8)|0;z=w+.5;m=g+(q<<3)|0;h[m>>3]=z;s=f+(q<<3)|0;h[s>>3]=z;z=y+.5;t=g+(p<<3)|0;h[t>>3]=z;A=f+(p<<3)|0;h[A>>3]=z;B=a+3956|0;C=e+(p<<3)|0;p=e+(q<<3)|0;q=a+4064|0;y=z;D=11;E=l;F=n;G=o;while(1){h[A>>3]=y;H=E+96|0;I=11;J=E;K=F;L=G;while(1){if((Dd(f,B,e)|0)!=0){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}h[K>>3]=+h[C>>3];h[J>>3]=+h[p>>3];Wd(q,+h[C>>3],+h[p>>3],L,L+8|0)|0;h[A>>3]=x+ +h[A>>3];if((I|0)==0){break}else{I=I+ -1|0;J=J+8|0;K=K+8|0;L=L+16|0}}h[s>>3]=u+ +h[s>>3];if((D|0)==0){break}y=+h[t>>3];D=D+ -1|0;E=H;F=F+96|0;G=G+192|0}Dd(g,B,e)|0;h[C>>3]=+h[C>>3]+.0002777777777777778;Cd(e,B,f)|0;y=+h[A>>3]- +h[t>>3];u=+h[s>>3]- +h[m>>3];x=+Q(+(y*y+u*u))*3600.0;if(!(x!=0.0)){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}u=.04/x;c[k>>2]=1;C=0;G=1;a:while(1){if((G|0)>1){rd(C)}M=qd(j,2,k,1)|0;td(M,o,n,0,144,0);F=143;E=n;D=o;while(1){x=+sd(M,D);if(+P(+(x- +h[E>>3]))>u){break}if((F|0)==0){N=26;break a}else{F=F+ -1|0;E=E+8|0;D=D+16|0}}D=c[k>>2]|0;E=D+1|0;c[k>>2]=E;if((D|0)>8){N=28;break}else{C=M;G=E}}if((N|0)==26){c[k>>2]=(c[k>>2]|0)+1}else if((N|0)==28){_b(5904);c[a+1560>>2]=1}c[a+3168>>2]=M;c[a+5944>>2]=M;Dd(g,B,e)|0;h[p>>3]=+h[p>>3]+.0002777777777777778;Cd(e,B,f)|0;u=+h[A>>3]- +h[t>>3];x=+h[s>>3]- +h[m>>3];y=+Q(+(u*u+x*x))*3600.0;if(!(y!=0.0)){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}x=.04/y;c[k>>2]=1;d=M;M=1;b:while(1){if((M|0)>1){rd(d)}O=qd(j,2,k,1)|0;td(O,o,l,0,144,0);r=143;m=l;s=o;while(1){y=+sd(O,s);if(+P(+(y- +h[m>>3]))>x){break}if((r|0)==0){N=37;break b}else{r=r+ -1|0;m=m+8|0;s=s+16|0}}s=c[k>>2]|0;m=s+1|0;c[k>>2]=m;if((s|0)>8){N=39;break}else{d=O;M=m}}if((N|0)==37){c[k>>2]=(c[k>>2]|0)+1}else if((N|0)==39){_b(5904);c[a+1560>>2]=1}c[a+3172>>2]=O;c[a+5948>>2]=O;hg(o);hg(n);hg(l);i=b;return}function Rb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0,z=0.0,A=0,B=0,C=0;f=i;i=i+144|0;g=f+24|0;j=f+28|0;k=f+32|0;l=f+112|0;m=f+96|0;n=f+8|0;o=f+64|0;p=f;c[j>>2]=0;a[k]=0;a[l]=0;q=a[e]|0;if(q<<24>>24==0){r=n;c[r>>2]=1230328133;c[r+4>>2]=5787470;s=m+0|0;t=6e3|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0))}else{c[g>>2]=q<<24>>24;Na(n|0,5968,g|0)|0;c[g>>2]=a[e]|0;Na(m|0,5984,g|0)|0}if((Pc(b,n,31,l)|0)==0?(Pc(b,5472,31,l)|0)!=0:0){g=n;c[g>>2]=1230328133;c[g+4>>2]=5787470}if((Pc(b,m,31,k)|0)==0?(Pc(b,6e3,31,k)|0)!=0:0){s=m+0|0;t=6e3|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0))}g=a[l]|0;do{if(g<<24>>24==74){e=l+1|0;h[d+120>>3]=+ug(e);c[j>>2]=vg(e)|0;c[k>>2]=3492678;v=0;w=30}else if(!(g<<24>>24==66)){if((Ec(b,n,j)|0)!=0){Lc(b,n,d+120|0)|0;v=1;w=30;break}if((Ec(b,5344,j)|0)!=0){if((c[j>>2]|0)==0){c[j>>2]=1950;h[d+120>>3]=1950.0;v=0;w=30;break}else{Lc(b,5344,d+120|0)|0;v=1;w=30;break}}if((a[k]|0)!=0){if((Ag(k,5480,3)|0)==0){h[d+120>>3]=1950.0;c[j>>2]=1950;x=0;break}if((Ag(k,6016,4)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,5488,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,6024,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,6032,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0}else{v=0;w=30}}else{v=0;w=30}}else{e=l+1|0;h[d+120>>3]=+ug(e);c[j>>2]=~~+ug(e);c[k>>2]=3427142;v=0;w=30}}while(0);do{if((w|0)==30){if((c[j>>2]|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;l=d+3449|0;if((Ag(l,5656,2)|0)!=0?(Ag(l,4832,3)|0)!=0:0){x=v;break}c[k>>2]=3492678;x=v}else{x=v}}}while(0);v=d+128|0;do{if((Mc(b,5320,v)|0)==0){if((Mc(b,5336,v)|0)==0?(Lc(b,5344,v)|0)==0:0){y=+h[d+120>>3];h[v>>3]=y;z=y}else{w=43}}else{Pc(b,5320,32,o)|0;if(($f(o,84)|0)==0){if((Lc(b,5352,p)|0)!=0){y=+h[v>>3]+ +h[p>>3]/8765.812770744;h[v>>3]=y;z=y;break}if((Lc(b,5360,p)|0)!=0){y=+h[v>>3]+ +h[p>>3]/8765.812770744;h[v>>3]=y;z=y}else{w=43}}else{w=43}}}while(0);if((w|0)==43){z=+h[v>>3]}if(z==0.0){h[v>>3]=+h[d+120>>3]}do{if((a[k]|0)==0?(Pc(b,m,31,k)|0,(a[k]|0)==0):0){if((c[d+3884>>2]|0)!=7){v=d+3764|0;if((c[j>>2]|0)>1980){a[v]=3492678;a[v+1|0]=13643;a[v+2|0]=53;a[v+3|0]=0;break}else{a[v]=3427142;a[v+1|0]=13387;a[v+2|0]=52;a[v+3|0]=0;break}}}else{w=48}}while(0);do{if((w|0)==48?(m=d+3764|0,Lg(m|0,k|0)|0,(x|0)==0):0){if((Ag(m,5480,3)|0)==0){h[d+120>>3]=1950.0;break}if((Ag(m,5488,3)|0)==0){h[d+120>>3]=2.0e3;break}if((Ag(m,6016,4)|0)==0){h[d+120>>3]=2.0e3;break}if((Ag(m,6024,3)|0)==0?(c[j>>2]|0)==0:0){h[d+120>>3]=2.0e3}}}while(0);switch(a[d+3449|0]|0){case 71:{j=d+3764|0;s=j+0|0;t=6040|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 72:{j=d+3764|0;s=j+0|0;t=6088|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 65:{j=d+3764|0;a[j+0|0]=a[6104|0]|0;a[j+1|0]=a[6105|0]|0;a[j+2|0]=a[6106|0]|0;a[j+3|0]=a[6107|0]|0;a[j+4|0]=a[6108|0]|0;a[j+5|0]=a[6109|0]|0;A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 76:{j=d+3764|0;a[j+0|0]=a[5296|0]|0;a[j+1|0]=a[5297|0]|0;a[j+2|0]=a[5298|0]|0;a[j+3|0]=a[5299|0]|0;a[j+4|0]=a[5300|0]|0;a[j+5|0]=a[5301|0]|0;a[j+6|0]=a[5302|0]|0;A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 69:{j=d+3764|0;s=j+0|0;t=6056|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 83:{j=d+3764|0;s=j+0|0;t=6072|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};default:{A=d+3764|0;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return}}}function Sb(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0;d=i;e=b+3764|0;f=c[b+3260>>2]|0;if((a[e]|0)!=0){if((f|0)==0){g=0;j=3}else{k=f}}else{g=f;j=3}if((j|0)==3){a[e+0|0]=a[5296|0]|0;a[e+1|0]=a[5297|0]|0;a[e+2|0]=a[5298|0]|0;a[e+3|0]=a[5299|0]|0;a[e+4|0]=a[5300|0]|0;a[e+5|0]=a[5301|0]|0;a[e+6|0]=a[5302|0]|0;k=g}if((k|0)==-1){a[e+0|0]=a[5304|0]|0;a[e+1|0]=a[5305|0]|0;a[e+2|0]=a[5306|0]|0;a[e+3|0]=a[5307|0]|0;a[e+4|0]=a[5308|0]|0;a[e+5|0]=a[5309|0]|0}k=nc(e)|0;c[b+3884>>2]=k;do{if((k|0)!=2){g=b+3796|0;if((k|0)==1){a[g]=3492678;a[g+1|0]=13643;a[g+2|0]=53;a[g+3|0]=0;break}else{Lg(g|0,e|0)|0;break}}else{g=b+3796|0;a[g]=3427142;a[g+1|0]=13387;a[g+2|0]=52;a[g+3|0]=0}}while(0);c[b+3888>>2]=nc(b+3796|0)|0;k=b+120|0;h[b+3872>>3]=+h[k>>3];g=b+3828|0;Lg(g|0,e|0)|0;c[b+3880>>2]=nc(g)|0;h[b+3864>>3]=+h[k>>3];i=d;return}function Tb(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){i=b;return}if((c[a+3312>>2]|0)==0){hg(a);i=b;return}d=a+9312|0;e=c[d>>2]|0;if((e|0)!=0){Tb(e);c[d>>2]=0}Ub(a);d=c[a+9320>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3980>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3976>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3168>>2]|0;if((d|0)!=0){rd(d)}d=c[a+3172>>2]|0;if((d|0)!=0){rd(d)}hg(a);i=b;return}function Ub(a){a=a|0;var b=0,d=0;b=i;d=c[1654]|0;if((d|0)!=0){hg(d);c[1654]=0}d=c[6620>>2]|0;if((d|0)!=0){hg(d);c[6620>>2]=0}d=c[6624>>2]|0;if((d|0)!=0){hg(d);c[6624>>2]=0}d=c[6628>>2]|0;if((d|0)!=0){hg(d);c[6628>>2]=0}d=c[6632>>2]|0;if((d|0)!=0){hg(d);c[6632>>2]=0}d=c[6636>>2]|0;if((d|0)!=0){hg(d);c[6636>>2]=0}d=c[6640>>2]|0;if((d|0)!=0){hg(d);c[6640>>2]=0}d=c[6644>>2]|0;if((d|0)!=0){hg(d);c[6644>>2]=0}d=c[6648>>2]|0;if((d|0)!=0){hg(d);c[6648>>2]=0}d=c[6652>>2]|0;if((d|0)!=0){hg(d);c[6652>>2]=0}if((a|0)==0){i=b;return}if((c[a+3312>>2]|0)==0){i=b;return}d=c[a+9208>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9212>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9216>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9220>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9224>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9228>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9232>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9236>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9240>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9244>>2]|0;if((d|0)==0){i=b;return}hg(d);i=b;return}function Vb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+144|0;g=f;h=f+8|0;c[h>>2]=5130572;c[h+4>>2]=5265985;c[h+8>>2]=5266003;c[h+12>>2]=5128532;c[h+16>>2]=5130579;c[h+20>>2]=4674643;c[h+24>>2]=4411969;c[h+28>>2]=5132378;c[h+32>>2]=4277594;c[h+36>>2]=5392705;c[h+40>>2]=5265731;c[h+44>>2]=5390659;c[h+48>>2]=5391693;c[h+52>>2]=4277571;c[h+56>>2]=5263171;c[h+60>>2]=4476739;c[h+64>>2]=4542275;c[h+68>>2]=5197635;c[h+72>>2]=5132098;c[h+76>>2]=5194576;c[h+80>>2]=4998739;c[h+84>>2]=5390672;c[h+88>>2]=5523777;c[h+92>>2]=5001037;c[h+96>>2]=4412227;c[h+100>>2]=4412241;c[h+104>>2]=4412244;c[h+108>>2]=5260110;c[h+112>>2]=5459015;c[h+116>>2]=5460804;c[h+120>>2]=5524560;c[h+124>>2]=5787220;c[h+128>>2]=5787738;c[h+132>>2]=5656660;if((Ag(d,6128,4)|0)==0){a[d]=1313819736;a[d+1|0]=5132108;a[d+2|0]=20047;a[d+3|0]=78}j=b+3368|0;Lg(j|0,d|0)|0;k=b+3449|0;Lg(k|0,d|0)|0;l=b+3467|0;Lg(l|0,d|0)|0;do{if((Ag(d,6136,6)|0)!=0){if((Ag(d,6144,6)|0)==0){c[b+3260>>2]=-1;break}if((Qc(d,6152)|0)!=0){c[b+3260>>2]=-1;break}m=a[d]|0;if(!(m<<24>>24==65|m<<24>>24==68|m<<24>>24==82)?(a[d+1|0]|0)!=76:0){c[b+3260>>2]=0;i=f;return 0}a[k]=m;a[b+3450|0]=a[d+1|0]|0;m=a[d+2|0]|0;n=b+3451|0;do{if(!(m<<24>>24==45)){a[n]=m;o=a[d+3|0]|0;p=b+3452|0;if(o<<24>>24==45){a[p]=0;q=4;break}else{a[p]=o;a[b+3453|0]=0;q=4;break}}else{a[n]=0;q=3}}while(0);n=((a[d+q|0]|0)==45)+q|0;m=n+((a[d+n|0]|0)==45)|0;n=m+((a[d+m|0]|0)==45)|0;m=n+((a[d+n|0]|0)==45)|0;a[l]=a[d+m|0]|0;a[b+3468|0]=a[d+(m+1)|0]|0;a[b+3469|0]=a[d+(m+2)|0]|0;a[b+3470|0]=0;c[g>>2]=k;c[g+4>>2]=l;Na(j|0,6160,g|0)|0;if((a[j]|0)==32){a[j]=45}m=b+3369|0;if((a[m]|0)==32){a[m]=45}m=b+3370|0;if((a[m]|0)==32){a[m]=45}m=b+3371|0;if((a[m]|0)==32){a[m]=45}m=b+3372|0;if((a[m]|0)==32){a[m]=45}m=b+3373|0;if((a[m]|0)==32){a[m]=45}m=b+3374|0;if((a[m]|0)==32){a[m]=45}n=b+3375|0;if((a[n]|0)==32){a[n]=45}o=b+3260|0;c[o>>2]=0;p=0;r=1;while(1){if((Ag(l,h+(r<<2)|0,3)|0)==0){c[o>>2]=r;s=r}else{s=p}r=r+1|0;if((r|0)==34){break}else{p=s}}p=b+3324|0;r=c[p>>2]|0;if((r|0)==0){c[p>>2]=3;break}else if((r|0)==1){c[p>>2]=2}else if((r|0)!=2){break}if((s|0)==31){a[m]=65;a[n]=78;c[o>>2]=3;break}else if((s|0)==32){a[m]=80;a[n]=78;c[o>>2]=7;break}else{break}}else{c[b+3260>>2]=0}}while(0);do{if((Ag(e,6168,4)|0)!=0){if((Ag(e,6192,4)|0)==0){a[e]=a[d]|0;s=e+1|0;a[s+0|0]=a[6176|0]|0;a[s+1|0]=a[6177|0]|0;a[s+2|0]=a[6178|0]|0;c[b+3264>>2]=-90;s=b+3764|0;a[s]=4280403;a[s+1|0]=16720;a[s+2|0]=65;a[s+3|0]=0;c[b+3884>>2]=8;break}else{c[b+3264>>2]=0;break}}else{a[e]=a[d]|0;s=e+1|0;a[s+0|0]=a[6176|0]|0;a[s+1|0]=a[6177|0]|0;a[s+2|0]=a[6178|0]|0;c[b+3264>>2]=90;s=b+3764|0;a[s+0|0]=a[6184|0]|0;a[s+1|0]=a[6185|0]|0;a[s+2|0]=a[6186|0]|0;a[s+3|0]=a[6187|0]|0;a[s+4|0]=a[6188|0]|0;a[s+5|0]=a[6189|0]|0;c[b+3884>>2]=7}}while(0);s=b+3377|0;Lg(s|0,e|0)|0;h=b+3458|0;Lg(h|0,e|0)|0;do{if((Ag(e,6136,6)|0)!=0){if((Ag(e,6144,6)|0)==0){c[b+3260>>2]=-1;break}j=a[e]|0;if(!(j<<24>>24==65|j<<24>>24==68|j<<24>>24==82)?(a[e+1|0]|0)!=76:0){c[b+3260>>2]=0;break}a[h]=j;j=e+1|0;a[b+3459|0]=a[j]|0;k=a[e+2|0]|0;q=b+3460|0;do{if(!(k<<24>>24==45)){a[q]=k;r=a[e+3|0]|0;p=b+3461|0;if(r<<24>>24==45){a[p]=0;t=4;break}else{a[p]=r;a[b+3462|0]=0;t=4;break}}else{a[q]=0;t=3}}while(0);q=((a[e+t|0]|0)==45)+t|0;k=q+((a[e+q|0]|0)==45)|0;q=k+((a[e+k|0]|0)==45)|0;k=q+((a[e+q|0]|0)==45)|0;a[l]=a[e+k|0]|0;a[b+3468|0]=a[e+(k+1)|0]|0;a[b+3469|0]=a[e+(k+2)|0]|0;a[b+3470|0]=0;if((Ag(d,6120,3)|0)!=0?(Ag(d+1|0,6176,3)|0)!=0:0){c[b+3304>>2]=0}else{c[b+3304>>2]=1}if((a[j]|0)!=76?(a[e]|0)!=65:0){c[b+3292>>2]=0;c[b+3288>>2]=3}else{c[b+3292>>2]=1;c[b+3288>>2]=5}c[g>>2]=h;c[g+4>>2]=l;Na(s|0,6160,g|0)|0;if((a[s]|0)==32){a[s]=45}k=b+3378|0;if((a[k]|0)==32){a[k]=45}k=b+3379|0;if((a[k]|0)==32){a[k]=45}k=b+3380|0;if((a[k]|0)==32){a[k]=45}k=b+3381|0;if((a[k]|0)==32){a[k]=45}k=b+3382|0;if((a[k]|0)==32){a[k]=45}k=b+3383|0;if((a[k]|0)==32){a[k]=45}k=b+3384|0;if((a[k]|0)==32){a[k]=45}}else{c[b+3260>>2]=0}}while(0);$e(b,d);i=f;return 0}function Wb(a,b,d,e){a=a|0;b=+b;d=+d;e=+e;var f=0,g=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0;f=i;g=c[a+3316>>2]|0;j=a+760|0;h[j>>3]=b;k=a+768|0;l=d!=0.0?d:b;h[k>>3]=l;h[a+32>>3]=b;h[a+40>>3]=l;if((g|0)>0){m=(g|0)<2?g:2;g=0;n=a+832|0;while(1){o=0;p=n;while(1){h[p>>3]=(g|0)==(o|0)?1.0:0.0;o=o+1|0;if((o|0)==(m|0)){break}else{p=p+8|0}}g=g+1|0;if((g|0)==(m|0)){break}else{n=n+(m<<3)|0}}}c[a+3300>>2]=0;m=a+48|0;if(e<0.0){q=e+360.0}else{q=e}if(!(q>=360.0)){r=q}else{r=q+-360.0}h[m>>3]=r;q=r*3.141592653589793/180.0;r=+S(+q);if(b*d>0.0){s=-q}else{s=q}q=+T(+s);s=+h[j>>3];n=a+56|0;h[n>>3]=r*s;d=+h[k>>3];b=q*+P(+d);if(s<0.0){h[a+64>>3]=-b}else{h[a+64>>3]=b}b=q*+P(+s);if(d<0.0){h[a+72>>3]=b}else{h[a+72>>3]=-b}h[a+80>>3]=r*d;Bd(2,n,a+88|0)|0;lc(a);d=+h[j>>3];j=d<0.0;if((c[a+3304>>2]|0)!=0){if(j?+h[k>>3]>0.0:0){c[a+3256>>2]=1;r=+h[m>>3];b=r+-90.0;n=a+3200|0;if(b<-180.0){h[n>>3]=b+360.0;h[a+3208>>3]=r;h[a+3216>>3]=b+360.0;i=f;return}else{h[n>>3]=b;h[a+3208>>3]=r;h[a+3216>>3]=b;i=f;return}}do{if(d>0.0){if(!(+h[k>>3]<0.0)){if(!(+h[k>>3]>0.0)){break}c[a+3256>>2]=0;b=+h[m>>3]+90.0;n=a+3200|0;if(b>180.0){r=b+-360.0;h[n>>3]=r;h[a+3208>>3]=r;h[a+3216>>3]=b+-360.0;i=f;return}else{h[n>>3]=b;h[a+3208>>3]=b;h[a+3216>>3]=b;i=f;return}}else{c[a+3256>>2]=1;b=+h[m>>3];r=b+90.0;if(r>180.0){t=r+-360.0}else{t=r}h[a+3200>>3]=t;h[a+3208>>3]=b;r=b+-90.0;n=a+3216|0;h[n>>3]=r;if(!(r<-180.0)){i=f;return}h[n>>3]=r+360.0;i=f;return}}}while(0);if(!j){i=f;return}if(!(+h[k>>3]<0.0)){i=f;return}c[a+3256>>2]=0;t=+h[m>>3];r=t+-90.0;if(r<-180.0){u=r+360.0}else{u=r}h[a+3200>>3]=u;h[a+3208>>3]=u;u=t+90.0;n=a+3216|0;h[n>>3]=u;if(!(u>180.0)){i=f;return}h[n>>3]=u+-360.0;i=f;return}if(j?+h[k>>3]>0.0:0){c[a+3256>>2]=0;u=+h[m>>3];h[a+3200>>3]=u;t=u+90.0;if(t>180.0){v=t+-360.0}else{v=t}h[a+3208>>3]=v;v=u+180.0;n=a+3216|0;h[n>>3]=v;if(!(v>180.0)){i=f;return}h[n>>3]=v+-360.0;i=f;return}do{if(d>0.0){if(!(+h[k>>3]<0.0)){if(!(+h[k>>3]>0.0)){break}c[a+3256>>2]=1;v=+h[m>>3];h[a+3200>>3]=-v;u=90.0-v;if(u>180.0){w=u+-360.0}else{w=u}h[a+3208>>3]=w;h[a+3216>>3]=v;i=f;return}c[a+3256>>2]=0;v=+h[m>>3]+180.0;if(v>180.0){x=v+-360.0}else{x=v}h[a+3200>>3]=x;v=x+90.0;if(v>180.0){y=v+-360.0}else{y=v}h[a+3208>>3]=y;v=x+180.0;n=a+3216|0;h[n>>3]=v;if(!(v>180.0)){i=f;return}h[n>>3]=v+-360.0;i=f;return}}while(0);if(!j){i=f;return}if(!(+h[k>>3]<0.0)){i=f;return}c[a+3256>>2]=1;x=+h[m>>3];y=x+180.0;if(y>180.0){z=y+-360.0}else{z=y}h[a+3200>>3]=z;y=z+90.0;if(y>180.0){A=y+-360.0}else{A=y}h[a+3208>>3]=A;A=x+90.0;m=a+3216|0;h[m>>3]=A;if(!(A>180.0)){i=f;return}h[m>>3]=A+-360.0;i=f;return}function Xb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,o=0.0;e=i;i=i+16|0;f=e;if((b|0)==0){i=e;return}g=b+3312|0;if((c[g>>2]|0)==0){i=e;return}do{if((((d|0)!=0?(a[d]|0)!=0:0)?(yg(d,6200)|0)!=0:0)?(yg(d,6208)|0)!=0:0){j=nc(d)|0;if((j|0)<0){i=e;return}l=c[b+3884>>2]|0;if((j|0)!=(l|0)&(l+ -5|0)>>>0<2){i=e;return}else{Lg(b+3796|0,d|0)|0;h[b+3872>>3]=+oc(d);m=j;break}}else{n=7}}while(0);do{if((n|0)==7){d=c[b+3884>>2]|0;j=b+3796|0;Lg(j|0,b+3764|0)|0;o=+h[b+120>>3];h[b+3872>>3]=o;if((d|0)==1){if(!(o!=2.0e3)){a[j+0|0]=a[6232|0]|0;a[j+1|0]=a[6233|0]|0;a[j+2|0]=a[6234|0]|0;a[j+3|0]=a[6235|0]|0;a[j+4|0]=a[6236|0]|0;a[j+5|0]=a[6237|0]|0;m=1;break}a[j]=74;h[k>>3]=o;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Na(b+3797|0,6216,f|0)|0;l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)!=48){m=1;break}a[l]=0;m=1;break}else if((d|0)==2){if(!(o!=1950.0)){a[j+0|0]=a[6224|0]|0;a[j+1|0]=a[6225|0]|0;a[j+2|0]=a[6226|0]|0;a[j+3|0]=a[6227|0]|0;a[j+4|0]=a[6228|0]|0;a[j+5|0]=a[6229|0]|0;m=2;break}a[j]=66;h[k>>3]=o;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Na(b+3797|0,6216,f|0)|0;l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)!=48){m=2;break}a[l]=0;m=2;break}else{m=d;break}}}while(0);c[b+3888>>2]=m;if((c[g>>2]|0)==0){i=e;return}switch(m|0){case 5:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};case 8:case 7:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};case 9:case 4:case 3:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};default:{c[b+3292>>2]=0;c[b+3288>>2]=3;i=e;return}}}function Yb(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;d=i;i=i+32|0;e=d;f=d+8|0;if((b|0)==0){i=d;return}g=b+3312|0;if((c[g>>2]|0)==0){i=d;return}h=0;a:while(1){if((h|0)==0){j=f+0|0;k=6656|0;l=j+12|0;do{a[j]=a[k]|0;j=j+1|0;k=k+1|0}while((j|0)<(l|0))}else{c[e>>2]=h;Na(f|0,6672,e|0)|0}k=c[6616+(h<<2)>>2]|0;b:do{if((k|0)!=0){if((c[g>>2]|0)!=0?(j=Dg(k|0)|0,(j|0)>0):0){l=b+(h<<2)+9208|0;m=c[l>>2]|0;if((m|0)!=0){hg(m)}m=ig(j+2|0,1)|0;c[l>>2]=m;if((m|0)!=0){n=m;m=0;do{o=a[k+m|0]|0;a[n+m|0]=o<<24>>24==95?32:o;m=m+1|0;n=c[l>>2]|0}while((m|0)!=(j|0));a[n+j|0]=0}}}else{m=Wa(f|0)|0;if((m|0)!=0){if((c[g>>2]|0)==0){break}l=Dg(m|0)|0;if((l|0)<=0){break}o=b+(h<<2)+9208|0;p=c[o>>2]|0;if((p|0)!=0){hg(p)}p=ig(l+2|0,1)|0;c[o>>2]=p;if((p|0)==0){break}else{q=p;r=0}do{p=a[m+r|0]|0;a[q+r|0]=p<<24>>24==95?32:p;r=r+1|0;q=c[o>>2]|0}while((r|0)!=(l|0));a[q+l|0]=0;break}switch(h|0){case 4:{if((c[g>>2]|0)!=0){o=b+9224|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=112;a[m+2|0]=112;a[m+3|0]=109;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};case 2:{if((c[g>>2]|0)!=0){m=b+9216|0;o=c[m>>2]|0;if((o|0)!=0){hg(o)}o=ig(13,1)|0;c[m>>2]=o;if((o|0)==0){break b}a[o]=115;a[o+1|0]=103;a[o+2|0]=115;a[o+3|0]=99;a[o+4|0]=32;a[o+5|0]=45;a[o+6|0]=97;a[o+7|0]=104;a[o+8|0]=32;a[o+9|0]=37;a[o+10|0]=115;a[o+11|0]=0;break b}break};case 3:{if((c[g>>2]|0)!=0){o=b+9220|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=116;a[m+2|0]=121;a[m+3|0]=50;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};case 5:{if((c[g>>2]|0)!=0){m=b+9228|0;o=c[m>>2]|0;if((o|0)!=0){hg(o)}o=ig(13,1)|0;c[m>>2]=o;if((o|0)==0){break b}a[o]=115;a[o+1|0]=115;a[o+2|0]=97;a[o+3|0]=111;a[o+4|0]=32;a[o+5|0]=45;a[o+6|0]=97;a[o+7|0]=104;a[o+8|0]=32;a[o+9|0]=37;a[o+10|0]=115;a[o+11|0]=0;break b}break};case 1:{if((c[g>>2]|0)!=0){o=b+9212|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=117;a[m+2|0]=97;a[m+3|0]=50;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};default:{c[b+(h<<2)+9208>>2]=0;break b}}h=h+1|0;continue a}}while(0);h=h+1|0;if((h|0)==10){break}}i=d;return}function Zb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0.0,l=0.0;d=i;if((b|0)==0){i=d;return}c[a+3300>>2]=1;e=a+56|0;h[e>>3]=+h[b>>3];f=b+8|0;h[a+64>>3]=+h[f>>3];g=b+16|0;h[a+72>>3]=+h[g>>3];j=b+24|0;h[a+80>>3]=+h[j>>3];Bd(2,e,a+88|0)|0;k=+h[b>>3];l=+h[g>>3];b=a+32|0;h[b>>3]=+Q(+(k*k+l*l));l=+h[f>>3];k=+h[j>>3];j=a+40|0;h[j>>3]=+Q(+(l*l+k*k));if((c[a+3304>>2]|0)!=0){k=+h[f>>3];h[f>>3]=-+h[g>>3];h[g>>3]=-k}lc(a);c[a+3312>>2]=1;ac(a);h[a+760>>3]=+h[b>>3];h[a+768>>3]=+h[j>>3];i=d;return}function _b(a){a=a|0;var b=0;b=i;Lg(6536,a|0)|0;i=b;return}function $b(a,b,d,e){a=a|0;b=+b;d=+d;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;f=i;if((e|0)==0){i=f;return}g=a+3316|0;j=c[g>>2]|0;if((j+ -1|0)>>>0>8){k=c[a+3320>>2]|0;c[g>>2]=k;l=k}else{l=j}j=a+760|0;h[j>>3]=b;k=a+768|0;m=d!=0.0?d:b;h[k>>3]=m;h[a+32>>3]=b;h[a+40>>3]=m;if((l|0)>0){g=0;n=e;o=a+832|0;while(1){p=n+(l<<3)|0;q=0;r=n;s=o;while(1){h[s>>3]=+h[r>>3];q=q+1|0;if((q|0)==(l|0)){break}else{r=r+8|0;s=s+8|0}}s=g+1|0;if((s|0)==(l|0)){break}else{g=s;n=p;o=o+(l<<3)|0}}m=+h[j>>3];j=a+56|0;h[j>>3]=+h[e>>3]*m;if((l|0)>1){h[a+64>>3]=+h[e+8>>3]*m;m=+h[k>>3];h[a+72>>3]=+h[e+(l<<3)>>3]*m;h[a+80>>3]=+h[e+(l+1<<3)>>3]*m;t=j}else{u=j;v=11}}else{j=a+56|0;h[j>>3]=+h[e>>3]*b;u=j;v=11}if((v|0)==11){v=a+64|0;j=a+80|0;c[v+0>>2]=0;c[v+4>>2]=0;c[v+8>>2]=0;c[v+12>>2]=0;h[j>>3]=1.0;t=u}Bd(2,t,a+88|0)|0;c[a+3300>>2]=1;Ad(a+3956|0)|0;c[a+3312>>2]=1;ac(a);i=f;return}function ac(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;b=i;i=i+64|0;d=b+48|0;e=b+24|0;f=b+16|0;g=b+40|0;j=b;k=b+32|0;l=b+8|0;if(!(+h[a+136>>3]<1.5)?!(+h[a+144>>3]<1.5):0){if((c[a+3884>>2]|0)==6){i=b;return}m=a+32|0;h[m>>3]=+P(+(+h[m>>3]));n=a+40|0;h[n>>3]=+P(+(+h[n>>3]));o=+h[a+16>>3];p=+h[a+24>>3];bc(a,o,p,e,f);q=a+3304|0;r=+h[e>>3];if((c[q>>2]|0)==0){s=+h[f>>3];e=a+3828|0;ic(a,r+ +h[m>>3],s,e,j,l,d);ic(a,r,s+ +h[n>>3],e,g,k,d)}else{s=+h[f>>3];f=a+3828|0;ic(a,r+ +h[n>>3],s,f,j,l,d);ic(a,r,s+ +h[m>>3],f,g,k,d)}s=+Y(+(+h[k>>3]-p),+(+h[g>>3]-o))*180.0/3.141592653589793;if(s<-90.0){t=s+360.0}else{t=s}h[a+3208>>3]=t;s=+Y(+(+h[l>>3]-p),+(+h[j>>3]-o))*180.0/3.141592653589793;if(s<-90.0){u=s+360.0}else{u=s}h[a+3216>>3]=u;if(t<-90.0){s=t+270.0;h[a+3200>>3]=s;v=s}else{s=t+-90.0;h[a+3200>>3]=s;v=s}j=(c[q>>2]|0)==0;if(!j){s=v+90.0;q=a+48|0;h[q>>3]=s;if(s<0.0){o=s+360.0;h[q>>3]=o;w=o}else{w=s}}else{h[a+48>>3]=v;w=v}q=a+48|0;if(w<0.0){v=w+360.0;h[q>>3]=v;x=v}else{x=w}if(x>=360.0){h[q>>3]=x+-360.0}x=u-t;w=t-u;q=w>80.0&w<100.0?1:x<280.0&x>260.0?1:x<-80.0&x>-100.0&1;c[a+3256>>2]=q;l=(q|0)!=0;if(j){if(l){i=b;return}h[m>>3]=-+h[m>>3];i=b;return}else{if(!l){i=b;return}h[n>>3]=-+h[n>>3];i=b;return}}x=+h[a+48>>3];h[a+3200>>3]=x;h[a+3208>>3]=x+90.0;h[a+3216>>3]=x+180.0;i=b;return}function bc(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0.0,x=0.0,y=0.0;g=i;i=i+144|0;j=g+104|0;k=g+56|0;l=g+8|0;m=g+40|0;n=g+136|0;o=g;p=g+48|0;q=g+96|0;r=g+88|0;if((a|0)==0){i=g;return}if((c[a+3312>>2]|0)==0){i=g;return}h[a+576>>3]=b;h[a+584>>3]=d;h[a+592>>3]=+h[815];s=a+3308|0;c[s>>2]=0;t=c[a+9312>>2]|0;if((t|0)==0){_e(a,b,d,o,p)}else{bc(t,b,d,o,p)}t=a+3260|0;u=c[t>>2]|0;do{if((u|0)==30){if((bd(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==31){if((ed(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==32){if((ld(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==29){if((nd(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else{d=+h[o>>3];b=+h[p>>3];if((c[a+3324>>2]|0)==2|(u|0)<1){if(($c(d,b,a,q,r)|0)==0){v=24;break}c[s>>2]=1;w=0.0;x=0.0;break}h[q>>3]=0.0;h[r>>3]=0.0;h[l>>3]=d;h[l+8>>3]=b;if((u+ -24|0)>>>0<3){h[l+16>>3]=+((c[1632]|0)+1|0)}else{h[l+16>>3]=+h[815]}h[l+24>>3]=1.0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;c[k+16>>2]=0;c[k+20>>2]=0;c[k+24>>2]=0;c[k+28>>2]=0;if((zd(a+3368|0,a+3924|0,l,a+3956|0,k,a+4064|0,m,n,a+688|0,a+3984|0,j)|0)==0){h[q>>3]=+h[j+(c[a+3944>>2]<<3)>>3];h[r>>3]=+h[j+(c[a+3948>>2]<<3)>>3];v=24;break}else{c[s>>2]=1;w=0.0;x=0.0;break}}}while(0);if((v|0)==24){if((c[s>>2]|0)==0){if((c[t>>2]|0)>0){mc(c[a+3884>>2]|0,c[a+3888>>2]|0,+h[a+120>>3],+h[a+3872>>3],q,r,+h[a+128>>3])}t=c[a+3264>>2]|0;if((t|0)==90){b=90.0- +h[r>>3];h[r>>3]=b;y=b}else if((t|0)==-90){b=+h[r>>3]+-90.0;h[r>>3]=b;y=b}else{y=+h[r>>3]}b=+h[q>>3];h[a+600>>3]=b;h[a+608>>3]=y;w=y;x=b}else{w=0.0;x=0.0}}h[e>>3]=x;h[f>>3]=w;f=c[a+3888>>2]|0;if((f|0)<1){i=g;return}if((f|0)==6|(f|0)==10){i=g;return}w=+h[e>>3];if(w<0.0){h[e>>3]=w+360.0;i=g;return}if(!(w>360.0)){i=g;return}h[e>>3]=w+-360.0;i=g;return}function cc(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=d|0;e=e|0;f=f|0;var g=0;g=i;ic(a,b,c,a+3828|0,d,e,f);i=g;return}function dc(b,d,e,f,g){b=b|0;d=+d;e=+e;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+96|0;k=j+16|0;l=j+8|0;m=j;n=j+56|0;o=j+24|0;if((b|0)!=0?(c[b+3312>>2]|0)!=0:0){bc(b,d,e,l,m);if((c[b+3308>>2]|0)!=0){p=f;q=p;a[q]=543581775;a[q+1|0]=2123366;a[q+2|0]=8294;a[q+3|0]=32;q=p+4|0;a[q]=7364973;a[q+1|0]=28769;a[q+2|0]=112;a[q+3|0]=0;r=1;i=j;return r|0}q=c[b+3292>>2]|0;do{if((q|0)==0){p=b+3288|0;s=c[p>>2]|0;t=(s<<1)+18|0;if((t|0)>=(g|0)){if((c[b+3296>>2]|0)==0){Hg(f|0,6336,g|0)|0;u=0;break}else{Hg(f|0,6304,g|0)|0;u=0;break}}e=+h[l>>3];if(((c[b+3888>>2]|0)+ -1|0)>>>0<2){Tc(n,32,e,s);Uc(o,32,+h[m>>3],(c[p>>2]|0)+ -1|0)}else{Uc(n,32,e,s);Uc(o,32,+h[m>>3],c[p>>2]|0)}if((c[b+3296>>2]|0)==0){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0}u=g-t|0}else if((q|0)==1){t=b+3288|0;p=c[t>>2]|0;s=(p<<1)+9|0;if((s|0)>=(g|0)){if((c[b+3296>>2]|0)==0){Hg(f|0,6280,g|0)|0;u=0;break}else{Hg(f|0,6256,g|0)|0;u=0;break}}Vc(n,32,+h[l>>3],p);Vc(o,32,+h[m>>3],c[t>>2]|0);if((c[b+3296>>2]|0)==0){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0}u=g-s|0}else{u=g}}while(0);switch(c[b+3888>>2]|0){case 5:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(q){q=s;t=q;a[t]=1953259808;a[t+1|0]=7629921;a[t+2|0]=29804;a[t+3|0]=116;t=q+4|0;a[t]=8020269;a[t+1|0]=31329;a[t+2|0]=122;a[t+3|0]=0;r=1;i=j;return r|0}else{t=s;s=t;a[s]=1953259785;a[s+1|0]=7629921;a[s+2|0]=29804;a[s+3|0]=116;s=t+4|0;a[s]=8020269;a[s+1|0]=31329;a[s+2|0]=122;a[s+3|0]=0;r=1;i=j;return r|0}break};case 4:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;t=f+(Dg(f|0)|0)|0;if(s){v=t+0|0;w=6416|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=t+0|0;w=6400|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 9:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}t=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(t){t=s;q=t;a[q]=1634496544;a[q+1|0]=6384752;a[q+2|0]=24940;a[q+3|0]=97;q=t+4|0;a[q]=7628142;a[q+1|0]=29797;a[q+2|0]=116;a[q+3|0]=0;r=1;i=j;return r|0}else{q=s;s=q;a[s]=1634496521;a[s+1|0]=6384752;a[s+2|0]=24940;a[s+3|0]=97;s=q+4|0;a[s]=7628142;a[s+1|0]=29797;a[s+2|0]=116;a[s+3|0]=0;r=1;i=j;return r|0}break};case 8:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;q=f+(Dg(f|0)|0)|0;if(s){v=q+0|0;w=6480|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=q+0|0;w=6464|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 7:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(q){v=s+0|0;w=6448|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=s+0|0;w=6432|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 1:case 2:{s=b+3796|0;if((u|0)<=((Dg(s|0)|0)+1|0)){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;t=f+(Dg(f|0)|0)|0;p=q?32:9;a[t]=p;a[t+1|0]=p>>8;Fg(f|0,s|0)|0;r=1;i=j;return r|0};case 3:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;p=f+(Dg(f|0)|0)|0;if(s){v=p+0|0;w=6384|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=p+0|0;w=6368|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};default:{w=b+3288|0;Wc(n,+h[l>>3],0,c[w>>2]|0);Wc(o,+h[m>>3],0,c[w>>2]|0);w=Dg(n|0)|0;m=w+1+(Dg(o|0)|0)|0;l=b+3476|0;v=b+3508|0;x=(Dg(l|0)|0)+2+(Dg(v|0)|0)|0;p=b+3884|0;if(((c[p>>2]|0)==6?(c[b+3328>>2]|0)==1:0)?(s=x+m|0,(u|0)>(s|0)):0){if((a[l]|0)!=0){t=n+w|0;a[t]=32;a[t+1|0]=0;Fg(n|0,l|0)|0}if((a[v]|0)==0){y=s}else{t=o+(Dg(o|0)|0)|0;a[t]=32;a[t+1|0]=0;Fg(o|0,v|0)|0;y=s}}else{y=m}m=(c[b+3296>>2]|0)!=0;do{if((u|0)>(y|0)){if(m){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0;break}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0;break}}else{if(m){Hg(f|0,6496,u|0)|0;break}else{Hg(f|0,6280,u|0)|0;break}}}while(0);if((c[p>>2]|0)!=6){r=1;i=j;return r|0}m=b+3328|0;if((c[m>>2]|0)==1){r=1;i=j;return r|0}if((u|0)>(y+7|0)?(b=f+(Dg(f|0)|0)|0,k=b,a[k]=1852402720,a[k+1|0]=7235948,a[k+2|0]=28265,a[k+3|0]=110,k=b+4|0,a[k]=7496037,a[k+1|0]=29281,a[k+2|0]=114,a[k+3|0]=0,(c[p>>2]|0)!=6):0){r=1;i=j;return r|0}if((c[m>>2]|0)!=2){r=1;i=j;return r|0}if((u|0)<=(x+7+y|0)){r=1;i=j;return r|0}if((a[l]|0)!=0){y=f+(Dg(f|0)|0)|0;a[y]=32;a[y+1|0]=0;Fg(f|0,l|0)|0}if((a[v]|0)==0){r=1;i=j;return r|0}l=f+(Dg(f|0)|0)|0;a[l]=32;a[l+1|0]=0;Fg(f|0,v|0)|0;r=1;i=j;return r|0}}}if((g|0)<=0){r=0;i=j;return r|0}a[f]=0;r=0;i=j;return r|0}function ec(a,b,c,d){a=+a;b=+b;c=+c;d=+d;var e=0,f=0,g=0;e=i;i=i+48|0;f=e+24|0;g=e;Ac(a,b,1.0,f);Ac(c,d,1.0,g);d=+h[f>>3]- +h[g>>3];c=+h[f+8>>3]- +h[g+8>>3];b=+h[f+16>>3]- +h[g+16>>3];a=(d*d+0.0+c*c+b*b)*.25;b=a>1.0?1.0:a;a=+Y(+(+Q(+b)),+(+Q(+(1.0-b))))*2.0*180.0/3.141592653589793;i=e;return+a}function fc(a){a=a|0;var b=0;if((a|0)==0){b=0}else{b=(c[a+3312>>2]|0)!=0}return(b?a+3796|0:0)|0}function gc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;if((a|0)!=0?(c[a+3312>>2]|0)!=0:0){e=a+3292|0;f=c[e>>2]|0;c[e>>2]=b;if((b|0)==1&(f|0)==0?(e=a+3288|0,(c[e>>2]|0)==3):0){c[e>>2]=6}if((b|0)==0&(f|0)==1){b=a+3288|0;if((c[b>>2]|0)==5){c[b>>2]=3;g=1}else{g=1}}else{g=f}}else{g=0}i=d;return g|0}function hc(a){a=a|0;var b=0;if((a|0)==0){b=0}else{b=(c[a+3312>>2]|0)!=0}return(b?a+3764|0:0)|0}function ic(a,b,d,e,f,g,j){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0;k=i;i=i+32|0;l=k+24|0;m=k+16|0;n=k+8|0;o=k;if((a|0)==0){i=k;return}if((c[a+3312>>2]|0)==0){i=k;return}c[j>>2]=0;h[l>>3]=b;h[m>>3]=d;p=c[a+3264>>2]|0;if((p|0)==90){h[m>>3]=90.0-d}else if((p|0)==-90){h[m>>3]=d+-90.0}if((e|0)==0){q=+h[a+120>>3];r=c[a+3884>>2]|0}else{p=nc(e)|0;q=+oc(e);r=p}h[a+592>>3]=1.0;if((r|0)>0?!((r|0)==6|(r|0)==10):0){mc(r,c[a+3884>>2]|0,q,+h[a+120>>3],l,m,+h[a+128>>3])}r=c[a+3260>>2]|0;do{if((r|0)==32){if((md(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==30){if((cd(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==29){if((od(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==31){if((fd(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else{q=+h[l>>3];s=+h[m>>3];if((c[a+3324>>2]|0)==2|(r|0)<1){if((ad(q,s,a,n,o)|0)==0){break}c[j>>2]=1;break}else{if((jc(q,s,a,n,o)|0)==0){break}c[j>>2]=1;break}}}while(0);r=c[a+9312>>2]|0;s=+h[n>>3];q=+h[o>>3];do{if((r|0)==0){Ze(a,s,q,f,g);o=c[j>>2]|0;if((o|0)==0){t=+h[f>>3];if(!(t<.5)?(u=+h[g>>3],!(u<.5)):0){if(!(t>+h[a+136>>3]+.5)?!(u>+h[a+144>>3]+.5):0){v=0;break}c[j>>2]=2;v=2;break}c[j>>2]=2;v=2}else{v=o}}else{ic(r,s,q,0,f,g,j);v=c[j>>2]|0}}while(0);c[a+3308>>2]=v;h[a+600>>3]=b;h[a+608>>3]=d;h[a+576>>3]=+h[f>>3];h[a+584>>3]=+h[g>>3];i=k;return}function jc(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+112|0;j=g+80|0;k=g+48|0;l=g+16|0;m=g+8|0;n=g;h[e>>3]=0.0;h[f>>3]=0.0;o=d+3924|0;if((c[o>>2]|0)!=137){p=d+3368|0;if((xd(c[d+3960>>2]|0,p,o)|0)==0){q=p}else{r=1;i=g;return r|0}}else{q=d+3368|0}p=d+3944|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;c[j+16>>2]=0;c[j+20>>2]=0;c[j+24>>2]=0;c[j+28>>2]=0;h[j+(c[p>>2]<<3)>>3]=a;h[j+(c[d+3948>>2]<<3)>>3]=b;p=l+16|0;c[l+0>>2]=0;c[l+4>>2]=0;c[l+8>>2]=0;c[l+12>>2]=0;h[p>>3]=1.0;h[l+24>>3]=1.0;s=k+16|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;h[s>>3]=1.0;h[k+24>>3]=1.0;s=yd(q,o,j,d+688|0,d+3984|0,m,n,d+4064|0,k,d+3956|0,l)|0;if((s|0)!=0){r=s;i=g;return r|0}h[e>>3]=+h[l>>3];h[f>>3]=+h[l+8>>3];b=+h[p>>3];if(((c[d+3260>>2]|0)+ -24|0)>>>0<3){h[d+592>>3]=b+-1.0;r=0;i=g;return r|0}else{h[d+592>>3]=b;r=0;i=g;return r|0}return 0}function kc(){return c[1528]|0}function lc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0;b=i;d=a+3316|0;e=c[d>>2]|0;f=(e|0)>2?2:e;if((f+ -1|0)>>>0>8){e=c[a+3320>>2]|0;c[d>>2]=e;g=e}else{g=f}f=aa(g<<3,g)|0;e=a+3976|0;d=c[e>>2]|0;if((d|0)==0){j=gg(f)|0;c[e>>2]=j;if((j|0)==0){i=b;return}else{k=j}}else{k=d}d=a+3980|0;if((c[d>>2]|0)==0?(j=gg(f)|0,c[d>>2]=j,(j|0)==0):0){i=b;return}j=a+3956|0;c[j>>2]=137;if((g|0)==3){l=k+0|0;m=l+72|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));f=c[e>>2]|0;h[f>>3]=+h[a+56>>3];h[f+8>>3]=+h[a+64>>3];h[f+24>>3]=+h[a+72>>3];h[f+32>>3]=+h[a+80>>3];h[f+64>>3]=1.0;n=f}else if((g|0)==2){h[k>>3]=+h[a+56>>3];h[k+8>>3]=+h[a+64>>3];h[k+16>>3]=+h[a+72>>3];h[k+24>>3]=+h[a+80>>3];n=k}else if((g|0)==4){l=k+0|0;m=l+128|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));l=c[e>>2]|0;h[l>>3]=+h[a+56>>3];h[l+8>>3]=+h[a+64>>3];h[l+32>>3]=+h[a+72>>3];h[l+40>>3]=+h[a+80>>3];h[l+80>>3]=1.0;h[l+120>>3]=1.0;n=l}else{n=k}Bd(g,n,c[d>>2]|0)|0;c[a+3964>>2]=a+616;c[a+3972>>2]=a+760;c[a+3968>>2]=a+832;c[j>>2]=137;i=b;return}function mc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=+c;d=+d;e=e|0;f=f|0;g=+g;var j=0,k=0,l=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0,s=0,t=0.0;j=i;i=i+32|0;k=j+24|0;l=j+16|0;m=j+8|0;n=j;if(c==0.0){o=(a|0)==2?1950.0:2.0e3}else{o=c}if(d==0.0){p=(b|0)==2?1950.0:2.0e3}else{p=d}q=(b|0)==11;r=(a|0)==1&q&o==2.0e3;d=r?o:(a|0)==11&q?o:p;q=r?b:a;a=(b|0)==1;r=(q|0)==11&a&d==2.0e3;p=r?d:o;s=r?b:q;if((s|0)==(b|0)&p==d){i=j;return}q=p!=d;if(q){if((s|0)==2&p!=1950.0){xc(p,1950.0,e,f)}if((s|0)==1&p!=2.0e3){yc(p,2.0e3,e,f)}}r=(b|0)==2;do{if(r){if((s|0)==3){sc(e,f);break}else if((s|0)==4){if(g>0.0){wc(e,f,g);h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);p=g+-1950.0;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{wc(e,f,1950.0);h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);h[e>>3]=+h[e>>3]+ +h[m>>3]*0.0;h[f>>3]=+h[f>>3]+ +h[n>>3]*0.0;break}}else if((s|0)==1){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);p=g+-1950.0;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);break}}else{break}}else{if((b|0)==4){if((s|0)==1){if(g>0.0){vc(e,f,g);break}else{vc(e,f,2.0e3);break}}else if((s|0)==3){uc(e,f);if(g>0.0){vc(e,f,g);break}else{vc(e,f,2.0e3);break}}else if((s|0)==2){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);p=g+-2.0e3;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];vc(e,f,g);break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);h[e>>3]=+h[e>>3]+ +h[m>>3]*-50.0;h[f>>3]=+h[f>>3]+ +h[n>>3]*-50.0;vc(e,f,1950.0);break}}else{break}}else if((b|0)==3){if((s|0)==4){if(g>0.0){wc(e,f,g)}else{wc(e,f,2.0e3)}tc(e,f);break}else if((s|0)==2){rc(e,f);break}else if((s|0)==1){tc(e,f);break}else{break}}else if((b|0)==1){if((s|0)==3){uc(e,f);break}else if((s|0)==4){if(g>0.0){wc(e,f,g);break}else{wc(e,f,2.0e3);break}}else if((s|0)==2){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);p=g+-2.0e3;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);break}}else{break}}else{break}}}while(0);if(q){if(r&d!=1950.0){xc(1950.0,d,e,f)}if(a&d!=2.0e3){yc(2.0e3,d,e,f)}}d=+h[f>>3];do{if(!(d>90.0)){if(d<-90.0){h[f>>3]=-180.0-d;g=+h[e>>3]+180.0;h[e>>3]=g;t=g;break}else{t=+h[e>>3];break}}else{h[f>>3]=180.0-d;g=+h[e>>3]+180.0;h[e>>3]=g;t=g}}while(0);if(t>360.0){h[e>>3]=t+-360.0;i=j;return}if(!(t<0.0)){i=j;return}h[e>>3]=t+360.0;i=j;return}function nc(b){b=b|0;var c=0,d=0,e=0,f=0.0;c=i;d=a[b]|0;a:do{if((((((!(d<<24>>24==106|d<<24>>24==74)?(yg(b,6688)|0)!=0:0)?(yg(b,6696)|0)!=0:0)?(yg(b,6704)|0)!=0:0)?(yg(b,6712)|0)!=0:0)?(Ag(b,6720,3)|0)!=0:0)?(Ag(b,6728,3)|0)!=0:0){if((((!(d<<24>>24==98|d<<24>>24==66)?(yg(b,6736)|0)!=0:0)?(yg(b,6744)|0)!=0:0)?(Ag(b,6752,3)|0)!=0:0)?(Ag(b,6760,3)|0)!=0:0){switch(d<<24>>24){case 105:case 73:{e=11;break a;break};case 108:case 76:{e=6;break a;break};case 101:case 69:{e=4;break a;break};case 97:case 65:{e=5;break a;break};case 110:case 78:{e=7;break a;break};case 103:case 71:{e=3;break a;break};default:{if((zg(b,6768,5)|0)==0){e=10;break a}if(d<<24>>24==112|d<<24>>24==80){e=9;break a}if((Gc(b)|0)==0){e=-1;break a}f=+ug(b);if(f>1980.0){e=1;break a}e=f>1900.0?2:-1;break a}}}else{e=2}}else{e=1}}while(0);i=c;return e|0}function oc(b){b=b|0;var c=0,d=0,e=0.0;c=i;d=a[b]|0;if(!(d<<24>>24==98|d<<24>>24==66|d<<24>>24==106|d<<24>>24==74)){if((Ag(b,6752,3)|0)!=0?(Ag(b,6760,3)|0)!=0:0){if((((Ag(b,6720,3)|0)!=0?(Ag(b,6728,3)|0)!=0:0)?(Ag(b,6704,4)|0)!=0:0)?(Ag(b,6712,4)|0)!=0:0){if((d+ -49<<24>>24&255)<2){e=+ug(b)}else{e=0.0}}else{e=2.0e3}}else{e=1950.0}}else{e=+ug(b+1|0)}i=c;return+e}function pc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0;g=i;i=i+48|0;j=g;k=+h[a>>3]*3.141592653589793/180.0;l=+h[b>>3]*3.141592653589793/180.0;m=+h[c>>3]*36.0e4;n=+h[d>>3]*36.0e4;o=+T(+k);p=+S(+k);k=+T(+l);q=+S(+l);l=p*q;r=o*q;if(m!=0.0|n!=0.0){s=-(m*r)-n*p*k;t=m*l-n*o*k;u=n*q}else{s=0.0;t=0.0;u=0.0}v=0;do{h[j+(v<<3)>>3]=+h[6776+(v*48|0)>>3]*l+0.0+ +h[6784+(v*48|0)>>3]*r+ +h[6792+(v*48|0)>>3]*k+ +h[6800+(v*48|0)>>3]*s+ +h[6808+(v*48|0)>>3]*t+ +h[6816+(v*48|0)>>3]*u;v=v+1|0}while((v|0)!=6);u=+h[j>>3];t=+h[j+8>>3];s=+h[j+16>>3];k=+Q(+(u*u+t*t+s*s));r=u*-162557.0e-11+t*-3.1919e-7+s*-1.3843e-7;l=u*r;q=u+k*-162557.0e-11-l;o=t*r;p=t+k*-3.1919e-7-o;w=s*r;r=s+k*-1.3843e-7-w;k=+Q(+(r*r+(q*q+p*p)));p=u*.001245+t*-.00158+s*-659.0e-6;q=u+k*-162557.0e-11-l;l=t+k*-3.1919e-7-o;o=s+k*-1.3843e-7-w;w=+h[j+24>>3]+k*.001245-p*q;s=k*-.00158+ +h[j+32>>3]-p*l;t=k*-659.0e-6+ +h[j+40>>3]-p*o;p=q*q+l*l;u=+Q(+p);if(!(q==0.0&l==0.0)){r=+Y(+l,+q);if(r<0.0){x=r+6.283185307179586}else{x=r}}else{x=0.0}r=+Y(+o,+u);if(u>1.0e-30){y=(t*p-o*(q*w+l*s))/(u*(o*o+p));z=(q*s-l*w)/p}else{y=n;z=m}m=+h[e>>3];if(!(m>1.0e-30)){A=x*180.0;B=A/3.141592653589793;h[a>>3]=B;C=r*180.0;D=C/3.141592653589793;h[b>>3]=D;E=z/36.0e4;h[c>>3]=E;F=y/36.0e4;h[d>>3]=F;i=g;return}h[f>>3]=(o*t+(q*w+l*s))/(k*m*21.095);h[e>>3]=+h[e>>3]/k;A=x*180.0;B=A/3.141592653589793;h[a>>3]=B;C=r*180.0;D=C/3.141592653589793;h[b>>3]=D;E=z/36.0e4;h[c>>3]=E;F=y/36.0e4;h[d>>3]=F;i=g;return}function qc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0;g=i;i=i+48|0;j=g;k=+h[a>>3]*3.141592653589793/180.0;l=+h[b>>3]*3.141592653589793/180.0;m=+h[c>>3]*36.0e4;n=+h[d>>3]*36.0e4;o=+T(+k);p=+S(+k);k=+T(+l);q=+S(+l);l=p*q;r=o*q;s=+h[f>>3];t=+h[e>>3];u=s*21.095*t;if(!(m!=0.0|n!=0.0)?!(s!=0.0&t!=0.0):0){v=-.001245;w=.00158;x=659.0e-6}else{v=-(m*r)-n*p*k+u*l+-.001245;w=m*l-n*o*k+u*r+.00158;x=n*q+u*k+659.0e-6}u=l*-162557.0e-11+r*-3.1919e-7+k*-1.3843e-7;q=u*l+(l+162557.0e-11);o=u*r+(r+3.1919e-7);p=u*k+(k+1.3843e-7);u=l*.001245+r*-.00158+k*-659.0e-6;s=v+u*l;l=w+u*r;r=x+u*k;y=0;do{h[j+(y<<3)>>3]=+h[7064+(y*48|0)>>3]*q+0.0+ +h[7072+(y*48|0)>>3]*o+ +h[7080+(y*48|0)>>3]*p+ +h[7088+(y*48|0)>>3]*s+ +h[7096+(y*48|0)>>3]*l+ +h[7104+(y*48|0)>>3]*r;y=y+1|0}while((y|0)!=6);r=+h[j>>3];l=+h[j+8>>3];s=+h[j+16>>3];p=+h[j+24>>3];o=+h[j+32>>3];q=+h[j+40>>3];k=r*r+l*l;u=+Q(+k);x=k+s*s;w=+Q(+x);v=r*p+l*o;z=v+s*q;if(!(r==0.0&l==0.0)){A=+Y(+l,+r);if(A<0.0){B=A+6.283185307179586}else{B=A}}else{B=0.0}A=+Y(+s,+u);if(u>1.0e-30){C=(k*q-s*v)/(x*u);D=(r*o-l*p)/k}else{C=n;D=m}if(!(t>1.0e-30)){E=B*180.0;F=E/3.141592653589793;h[a>>3]=F;G=A*180.0;H=G/3.141592653589793;h[b>>3]=H;I=D/36.0e4;h[c>>3]=I;J=C/36.0e4;h[d>>3]=J;i=g;return}h[f>>3]=z/(w*t*21.095);h[e>>3]=+h[e>>3]/w;E=B*180.0;F=E/3.141592653589793;h[a>>3]=F;G=A*180.0;H=G/3.141592653589793;h[b>>3]=H;I=D/36.0e4;h[c>>3]=I;J=C/36.0e4;h[d>>3]=J;i=g;return}function rc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0,x=0,y=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.066988739415+q*-.872755765852+l*-.483538914632;n=p*.492728466075+q*-.45034695802+l*.744584633283;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.867600811151+q*-.188374601723+l*.460199784784),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}n=g/15.0;d=~~n;g=(n- +(d|0))*60.0;b=~~g;if(j<0.0){u=45;v=-j}else{u=43;v=j}w=~~v;j=(v- +(w|0))*60.0;x=~~j;y=gg(32)|0;c[f>>2]=d;c[f+4>>2]=b;d=f+8|0;h[k>>3]=(g- +(b|0))*60.0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[f+16>>2]=u;c[f+20>>2]=w;c[f+24>>2]=x;w=f+28|0;h[k>>3]=(j- +(x|0))*60.0;c[w>>2]=c[k>>2];c[w+4>>2]=c[k+4>>2];Na(y|0,7648,f|0)|0;w=y+6|0;if((a[w]|0)==32){a[w]=48}w=y+20|0;if((a[w]|0)==32){a[w]=48}w=c[o>>2]|0;c[f>>2]=y;za(w|0,7360,f|0)|0;h[k>>3]=s;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];x=f+8|0;h[k>>3]=t;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];za(w|0,7392,f|0)|0;hg(y);i=e;return}function sc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0.0,x=0,y=0,z=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.066988739415+q*.492728466075+l*-.867600811151;n=p*-.872755765852+q*-.45034695802+l*-.188374601723;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.483538914632+q*.744584633283+l*.460199784784),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}d=c[o>>2]|0;h[k>>3]=g;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];b=f+8|0;h[k>>3]=j;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];za(d|0,7432,f|0)|0;j=s/15.0;b=~~j;s=(j- +(b|0))*60.0;u=~~s;if(t<0.0){v=45;w=-t}else{v=43;w=t}x=~~w;t=(w- +(x|0))*60.0;y=~~t;z=gg(32)|0;c[f>>2]=b;c[f+4>>2]=u;b=f+8|0;h[k>>3]=(s- +(u|0))*60.0;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];c[f+16>>2]=v;c[f+20>>2]=x;c[f+24>>2]=y;x=f+28|0;h[k>>3]=(t- +(y|0))*60.0;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];Na(z|0,7648,f|0)|0;x=z+6|0;if((a[x]|0)==32){a[x]=48}x=z+20|0;if((a[x]|0)==32){a[x]=48}c[f>>2]=z;za(d|0,7472,f|0)|0;hg(z);i=e;return}function tc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0,x=0,y=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.054875539726+q*-.87343710801+l*-.483834985808;n=p*.494109453312+q*-.444829589425+l*.74698225181;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.867666135858+q*-.198076386122+l*.455983795705),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}n=g/15.0;d=~~n;g=(n- +(d|0))*60.0;b=~~g;if(j<0.0){u=45;v=-j}else{u=43;v=j}w=~~v;j=(v- +(w|0))*60.0;x=~~j;y=gg(32)|0;c[f>>2]=d;c[f+4>>2]=b;d=f+8|0;h[k>>3]=(g- +(b|0))*60.0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[f+16>>2]=u;c[f+20>>2]=w;c[f+24>>2]=x;w=f+28|0;h[k>>3]=(j- +(x|0))*60.0;c[w>>2]=c[k>>2];c[w+4>>2]=c[k+4>>2];Na(y|0,7648,f|0)|0;w=y+6|0;if((a[w]|0)==32){a[w]=48}w=y+20|0;if((a[w]|0)==32){a[w]=48}w=c[o>>2]|0;c[f>>2]=y;za(w|0,7504,f|0)|0;h[k>>3]=s;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];x=f+8|0;h[k>>3]=t;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];za(w|0,7536,f|0)|0;hg(y);i=e;return}function uc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0.0,x=0,y=0,z=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.054875539726+q*.494109453312+l*-.867666135858;n=p*-.87343710801+q*-.444829589425+l*-.198076386122;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.483834985808+q*.74698225181+l*.455983795705),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}d=c[o>>2]|0;h[k>>3]=g;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];b=f+8|0;h[k>>3]=j;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];za(d|0,7576,f|0)|0;j=s/15.0;b=~~j;s=(j- +(b|0))*60.0;u=~~s;if(t<0.0){v=45;w=-t}else{v=43;w=t}x=~~w;t=(w- +(x|0))*60.0;y=~~t;z=gg(32)|0;c[f>>2]=b;c[f+4>>2]=u;b=f+8|0;h[k>>3]=(s- +(u|0))*60.0;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];c[f+16>>2]=v;c[f+20>>2]=x;c[f+24>>2]=y;x=f+28|0;h[k>>3]=(t- +(y|0))*60.0;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];Na(z|0,7648,f|0)|0;x=z+6|0;if((a[x]|0)==32){a[x]=48}x=z+20|0;if((a[x]|0)==32){a[x]=48}c[f>>2]=z;za(d|0,7616,f|0)|0;hg(z);i=e;return}function vc(a,b,c){a=a|0;b=b|0;c=+c;var d=0,e=0,f=0.0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0;d=i;i=i+80|0;e=d;if(c!=2.0e3){yc(2.0e3,c,a,b)}f=+h[a>>3]*3.141592653589793/180.0;g=+h[b>>3]*3.141592653589793/180.0;j=+S(+g);k=+S(+f)*j;l=j*+T(+f);f=+T(+g);g=(c+-2.0e3)*.01;zc(1,(g*(g*(g*.001813+-59.0e-5)+-46.815)+84381.448)*48481368110953.0e-19,0.0,0.0,e);g=+h[e>>3]*k+0.0+ +h[e+8>>3]*l+ +h[e+16>>3]*f;c=+h[e+24>>3]*k+0.0+ +h[e+32>>3]*l+ +h[e+40>>3]*f;j=+h[e+48>>3]*k+0.0+ +h[e+56>>3]*l+ +h[e+64>>3]*f;f=+Y(+c,+g);if(f<0.0){m=f+6.283185307179586}else{m=f}if(!(m>6.283185307179586)){n=m;o=g*g;p=c*c;q=o+p;r=+Q(+q);s=+Y(+j,+r);t=n*180.0;u=t/3.141592653589793;h[a>>3]=u;v=s*180.0;w=v/3.141592653589793;h[b>>3]=w;i=d;return}n=m+-6.283185307179586;o=g*g;p=c*c;q=o+p;r=+Q(+q);s=+Y(+j,+r);t=n*180.0;u=t/3.141592653589793;h[a>>3]=u;v=s*180.0;w=v/3.141592653589793;h[b>>3]=w;i=d;return}function wc(a,b,c){a=a|0;b=b|0;c=+c;var d=0,e=0,f=0.0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0;d=i;i=i+80|0;e=d;f=+h[a>>3]*3.141592653589793/180.0;g=+h[b>>3]*3.141592653589793/180.0;j=+S(+g);k=+S(+f)*j;l=j*+T(+f);f=+T(+g);g=(c+-2.0e3)*.01;zc(1,(g*(g*(g*.001813+-59.0e-5)+-46.815)+84381.448)*48481368110953.0e-19,0.0,0.0,e);g=+h[e>>3]*k+0.0+ +h[e+24>>3]*l+ +h[e+48>>3]*f;j=+h[e+8>>3]*k+0.0+ +h[e+32>>3]*l+ +h[e+56>>3]*f;m=+Y(+j,+g);if(m<0.0){n=m+6.283185307179586}else{n=m}if(n>6.283185307179586){o=n+-6.283185307179586}else{o=n}n=+Y(+(+h[e+16>>3]*k+0.0+ +h[e+40>>3]*l+ +h[e+64>>3]*f),+(+Q(+(g*g+j*j))));h[a>>3]=o*180.0/3.141592653589793;h[b>>3]=n*180.0/3.141592653589793;if(!(c!=2.0e3)){i=d;return}yc(c,2.0e3,a,b);i=d;return}function xc(a,b,c,d){a=+a;b=+b;c=c|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;e=i;i=i+80|0;f=e;g=+h[c>>3]*3.141592653589793/180.0;j=+h[d>>3]*3.141592653589793/180.0;k=(a+-1850.0)/100.0;l=(b-a)/100.0;a=l*48481368110953.0e-19;b=k*(k*59.0e-6+1.3972)+2303.5548;m=k*365.0e-6;zc(323,-(a*(b+l*(.30242-k*269.0e-6+l*.017996))),a*(k*(-.85294-m)+2005.1125+l*(-.42647-m-l*.041802)),-(a*(b+l*(k*387.0e-6+1.09478+l*.018324))),f);l=+S(+j);k=+S(+g)*l;b=l*+T(+g);g=+T(+j);j=+h[f>>3]*k+0.0+ +h[f+8>>3]*b+ +h[f+16>>3]*g;l=+h[f+24>>3]*k+0.0+ +h[f+32>>3]*b+ +h[f+40>>3]*g;a=+h[f+48>>3]*k+0.0+ +h[f+56>>3]*b+ +h[f+64>>3]*g;g=+Y(+l,+j);if(g<0.0){n=g+6.283185307179586}else{n=g}if(!(n>6.283185307179586)){o=n;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}o=n+-6.283185307179586;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}function yc(a,b,c,d){a=+a;b=+b;c=c|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;e=i;i=i+80|0;f=e;g=+h[c>>3]*3.141592653589793/180.0;j=+h[d>>3]*3.141592653589793/180.0;k=(a+-2.0e3)/100.0;l=(b-a)/100.0;a=l*48481368110953.0e-19;b=k*(1.39656-k*139.0e-6)+2306.2181;m=k*217.0e-6;zc(323,-(a*(b+l*(.30188-k*344.0e-6+l*.017998))),a*(k*(-.8533-m)+2004.3109+l*(-.42665-m-l*.041833)),-(a*(b+l*(k*66.0e-6+1.09468+l*.018203))),f);l=+S(+j);k=+S(+g)*l;b=l*+T(+g);g=+T(+j);j=k*+h[f>>3]+0.0+b*+h[f+8>>3]+g*+h[f+16>>3];l=k*+h[f+24>>3]+0.0+b*+h[f+32>>3]+g*+h[f+40>>3];a=k*+h[f+48>>3]+0.0+b*+h[f+56>>3]+g*+h[f+64>>3];g=+Y(+l,+j);if(g<0.0){n=g+6.283185307179586}else{n=g}if(!(n>6.283185307179586)){o=n;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}o=n+-6.283185307179586;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}function zc(a,b,d,e,f){a=a|0;b=+b;d=+d;e=+e;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0,B=0.0,C=0.0,D=0,E=0.0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0,L=0.0,M=0,N=0.0;g=i;i=i+192|0;j=g+144|0;k=g+72|0;l=g;m=g+168|0;n=f+8|0;h[f>>3]=1.0;o=f+16|0;h[n>>3]=0.0;h[o>>3]=0.0;p=f+24|0;h[p>>3]=0.0;h[f+32>>3]=1.0;h[f+40>>3]=0.0;h[f+48>>3]=0.0;h[f+56>>3]=0.0;h[f+64>>3]=1.0;q=(a|0)/100|0;c[m>>2]=q;if((a|0)>99){r=(aa(q,-100)|0)+a|0;s=1}else{r=a;s=0}a=(r|0)/10|0;c[m+(s<<2)>>2]=a;if((r|0)>9){t=(aa(a,-10)|0)+r|0;u=s+1|0}else{t=r;u=s}c[m+(u<<2)>>2]=t;s=((t|0)>0)+u|0;h[j>>3]=b;h[j+8>>3]=d;h[j+16>>3]=e;if((s|0)<=0){i=g;return}u=l+32|0;t=l+40|0;r=l+56|0;a=l+64|0;q=l+16|0;v=l+48|0;w=l+8|0;x=l+24|0;y=k+8|0;e=b;b=1.0;d=0.0;z=1.0;A=0;while(1){h[l>>3]=1.0;h[l+8>>3]=0.0;h[l+16>>3]=0.0;h[l+24>>3]=0.0;h[l+32>>3]=1.0;h[l+40>>3]=0.0;h[l+48>>3]=0.0;h[l+56>>3]=0.0;h[l+64>>3]=1.0;B=+T(+e);C=+S(+e);D=c[m+(A<<2)>>2]|0;do{if((D|0)!=1){h[l>>3]=C;if((D|0)==2){h[q>>3]=-B;h[v>>3]=B;h[a>>3]=C;break}else{h[w>>3]=B;h[x>>3]=-B;h[u>>3]=C;break}}else{h[u>>3]=C;h[t>>3]=B;h[r>>3]=-B;h[a>>3]=C}}while(0);C=+h[p>>3];B=+h[n>>3];E=+h[f+32>>3];F=+h[f+56>>3];G=+h[f+16>>3];H=+h[f+40>>3];D=0;do{I=D*3|0;J=+h[l+(I<<3)>>3];K=I+1|0;L=+h[l+(K<<3)>>3];M=I+2|0;N=+h[l+(M<<3)>>3];h[k+(I<<3)>>3]=J*b+0.0+L*C+N*d;h[k+(K<<3)>>3]=J*B+0.0+L*E+N*F;h[k+(M<<3)>>3]=J*G+0.0+L*H+N*z;D=D+1|0}while((D|0)!=3);H=+h[k>>3];h[f>>3]=H;h[n>>3]=+h[y>>3];h[o>>3]=+h[k+16>>3];h[f+24>>3]=+h[k+24>>3];h[f+32>>3]=+h[k+32>>3];h[f+40>>3]=+h[k+40>>3];G=+h[k+48>>3];h[f+48>>3]=G;h[f+56>>3]=+h[k+56>>3];F=+h[k+64>>3];h[f+64>>3]=F;D=A+1|0;if((D|0)==(s|0)){break}e=+h[j+(D<<3)>>3];b=H;d=G;z=F;A=D}i=g;return}function Ac(a,b,c,d){a=+a;b=+b;c=+c;d=d|0;var e=0.0;e=a*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+a);h[d>>3]=+S(+e)*c*b;h[d+8>>3]=b*+T(+e)*c;h[d+16>>3]=+T(+a)*c;return}function Bc(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;if((b|0)>0){e=b}else{c[1922]=0;e=(Cc(a,7696)|0)+80-a|0}c[1922]=e;i=d;return e|0}function Cc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;e=i;f=c[1922]|0;g=(f|0)==0?256e3:f;if((g|0)>0){h=0}else{j=0;i=e;return j|0}while(1){f=h+1|0;if((a[b+h|0]|0)<1){k=h;break}if((f|0)<(g|0)){h=f}else{k=f;break}}h=b+k|0;g=h;if((k|0)<=0){j=0;i=e;return j|0}k=b;f=b;a:while(1){b=Rc(f,d,g-f|0)|0;if((b|0)==0){j=0;l=17;break}m=(b-k|0)%80|0;n=a[b+(Dg(d|0)|0)|0]|0;do{if((m|0)<=7){if(n<<24>>24>32?!(n<<24>>24==61|n<<24>>24==127):0){o=b+1|0;break}p=0-m|0;q=b+p|0;if((p|0)<0){p=b+1|0;r=f;s=q;while(1){t=(a[s]|0)==32?r:p;u=s+1|0;if(u>>>0>>0){r=t;s=u}else{v=t;break}}}else{v=f}if(b>>>0>>0){o=v}else{j=q;l=17;break a}}else{o=b+1|0}}while(0);if(o>>>0>>0){f=o}else{j=0;l=17;break}}if((l|0)==17){i=e;return j|0}return 0}function Dc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;i=i+16|0;g=f;if((a[d]|0)<64){h=Ec(b,c,e)|0;i=f;return h|0}else{Lg(g|0,c|0)|0;j=Dg(c|0)|0;a[g+j|0]=a[d]|0;a[g+(j+1)|0]=0;h=Ec(b,g,e)|0;i=f;return h|0}return 0}function Ec(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0.0,k=0.0;f=i;g=Fc(b,d)|0;if((g|0)==0){h=0;i=f;return h|0}d=(a[g]|0)==35?g+1|0:g;if((Dg(d|0)|0)>81){Hg(7704,d|0,81)|0;a[7785|0]=0}else{Lg(7704,d|0)|0}if((Gc(7704)|0)==2){d=$f(7704,68)|0;if((d|0)!=0){a[d]=101}d=$f(7704,100)|0;if((d|0)!=0){a[d]=101}d=$f(7704,69)|0;if((d|0)!=0){a[d]=101}}j=+ug(7704);k=j+.001;if(k>2147483647.0){c[e>>2]=2147483647;h=1;i=f;return h|0}if(j>=0.0){c[e>>2]=~~k;h=1;i=f;return h|0}k=j+-.001;if(k<-2147483648.0){c[e>>2]=-2147483648;h=1;i=f;return h|0}else{c[e>>2]=~~k;h=1;i=f;return h|0}return 0}function Fc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;e=i;i=i+208|0;f=e+194|0;g=e+8|0;h=e+2|0;j=e+4|0;k=e+196|0;l=e;m=e+6|0;n=e+112|0;o=e+12|0;a[g]=39;a[g+1|0]=0;a[h]=34;a[h+1|0]=0;a[j]=91;a[j+1|0]=0;a[m]=44;a[m+1|0]=0;a[k]=93;a[k+1|0]=0;a[l]=47;a[l+1|0]=0;Hg(n|0,d|0,80)|0;d=Dg(n|0)|0;p=Dg(j|0)|0;a:do{if((p|0)!=0){if((d|0)!=0?(q=p+ -1|0,r=a[j+q|0]|0,s=d+1-p|0,t=n+s|0,(s|0)>0):0){s=(p|0)==1;u=(p|0)<3;v=n;do{b:do{if((a[v]|0)==91){if(s){w=v;x=23;break a}if((a[v+q|0]|0)==r<<24>>24){if(u){w=v;x=23;break a}else{y=1}while(1){z=y+1|0;if((a[v+y|0]|0)!=(a[j+y|0]|0)){break b}if((z|0)<(p|0)){y=z}else{w=v;x=23;break a}}}}}while(0);v=v+1|0}while(v>>>0>>0)}t=Dg(n|0)|0;v=Dg(m|0)|0;if((v|0)!=0){if((t|0)!=0?(u=v+ -1|0,r=a[m+u|0]|0,q=t+1-v|0,t=n+q|0,(q|0)>0):0){q=(v|0)==1;s=(v|0)<3;z=n;while(1){c:do{if((a[z]|0)==44){if(q){w=z;x=23;break a}if((a[z+u|0]|0)==r<<24>>24){if(s){w=z;x=23;break a}else{A=1}while(1){B=A+1|0;if((a[z+A|0]|0)!=(a[m+A|0]|0)){break c}if((B|0)<(v|0)){A=B}else{w=z;x=23;break a}}}}}while(0);B=z+1|0;if(B>>>0>>0){z=B}else{C=0;break}}}else{C=0}}else{w=n;x=23}}else{w=n;x=23}}while(0);if((x|0)==23){a[w]=0;C=w+1|0}w=Cc(b,n)|0;if((w|0)==0){D=0;i=e;return D|0}n=o+0|0;b=n+100|0;do{a[n]=0;n=n+1|0}while((n|0)<(b|0));Hg(o|0,w|0,80)|0;w=Dg(o|0)|0;n=Dg(g|0)|0;d:do{if((n|0)!=0){if((w|0)!=0?(b=a[g]|0,A=n+ -1|0,m=a[g+A|0]|0,y=w+1-n|0,p=o+y|0,(y|0)>0):0){y=(n|0)==1;j=(n|0)<3;d=o;while(1){e:do{if((a[d]|0)==b<<24>>24){if(y){E=d;break d}if((a[d+A|0]|0)==m<<24>>24){if(j){E=d;break d}else{F=1}while(1){z=F+1|0;if((a[d+F|0]|0)!=(a[g+F|0]|0)){break e}if((z|0)<(n|0)){F=z}else{E=d;break d}}}}}while(0);z=d+1|0;if(z>>>0

>>0){d=z}else{E=0;break}}}else{E=0}}else{E=o}}while(0);F=Dg(o|0)|0;n=Dg(l|0)|0;f:do{if((n|0)!=0){if((F|0)!=0?(w=a[l]|0,d=n+ -1|0,p=a[l+d|0]|0,j=F+1-n|0,m=o+j|0,(j|0)>0):0){j=(n|0)==1;A=(n|0)<3;y=o;while(1){g:do{if((a[y]|0)==w<<24>>24){if(j){G=y;break f}if((a[y+d|0]|0)==p<<24>>24){if(A){G=y;break f}else{H=1}while(1){b=H+1|0;if((a[y+H|0]|0)!=(a[l+H|0]|0)){break g}if((b|0)<(n|0)){H=b}else{G=y;break f}}}}}while(0);b=y+1|0;if(b>>>0>>0){y=b}else{G=0;break}}}else{G=0}}else{G=o}}while(0);h:do{if((E|0)==0){H=Dg(o|0)|0;n=Dg(h|0)|0;i:do{if((n|0)==0){I=o}else{if((H|0)==0){x=116;break h}l=a[h]|0;F=n+ -1|0;y=a[h+F|0]|0;m=H+1-n|0;A=o+m|0;if((m|0)<=0){x=116;break h}m=(n|0)==1;p=(n|0)<3;d=o;while(1){j:do{if((a[d]|0)==l<<24>>24){if(m){I=d;break i}if((a[d+F|0]|0)==y<<24>>24){if(p){I=d;break i}else{J=1}while(1){j=J+1|0;if((a[d+J|0]|0)!=(a[h+J|0]|0)){break j}if((j|0)<(n|0)){J=j}else{I=d;break i}}}}}while(0);j=d+1|0;if(j>>>0>>0){d=j}else{x=116;break h}}}}while(0);if((G|0)!=0&I>>>0>>0){n=I+1|0;H=Dg(n|0)|0;d=Dg(h|0)|0;if((d|0)==0){K=I;L=n;x=115;break}if((H|0)!=0?(A=a[h]|0,p=d+ -1|0,y=a[h+p|0]|0,F=H+1-d|0,H=I+(F+1)|0,(F|0)>0):0){F=(d|0)==1;m=(d|0)<3;l=n;while(1){k:do{if((a[l]|0)==A<<24>>24){if(F){K=I;L=l;x=115;break h}if((a[l+p|0]|0)==y<<24>>24){if(m){K=I;L=l;x=115;break h}else{M=1}while(1){n=M+1|0;if((a[l+M|0]|0)!=(a[h+M|0]|0)){break k}if((n|0)<(d|0)){M=n}else{K=I;L=l;x=115;break h}}}}}while(0);n=l+1|0;if(n>>>0>>0){l=n}else{N=G;break}}}else{N=G}while(1){l=N+ -1|0;if((a[l]|0)==32){N=l}else{K=I;L=N;x=115;break h}}}if((G|0)==0){l=I+1|0;H=Dg(l|0)|0;d=Dg(h|0)|0;if((d|0)==0){K=I;L=l;x=115}else{if((H|0)!=0?(m=a[h]|0,y=d+ -1|0,p=a[h+y|0]|0,F=H+1-d|0,H=I+(F+1)|0,(F|0)>0):0){F=(d|0)==1;A=(d|0)<3;n=l;do{l:do{if((a[n]|0)==m<<24>>24){if(F){K=I;L=n;x=115;break h}if((a[n+y|0]|0)==p<<24>>24){if(A){K=I;L=n;x=115;break h}else{O=1}while(1){l=O+1|0;if((a[n+O|0]|0)!=(a[h+O|0]|0)){break l}if((l|0)<(d|0)){O=l}else{K=I;L=n;x=115;break h}}}}}while(0);n=n+1|0}while(n>>>0>>0)}H=o+79|0;while(1){if((a[H]|0)==32){H=H+ -1|0}else{break}}K=I;L=H+1|0;x=115}}else{x=116}}else{if((G|0)!=0&E>>>0>>0){n=E+1|0;d=Dg(n|0)|0;A=Dg(g|0)|0;if((A|0)==0){K=E;L=n;x=115;break}if((d|0)!=0?(p=a[g]|0,y=A+ -1|0,F=a[g+y|0]|0,m=d+1-A|0,d=E+(m+1)|0,(m|0)>0):0){m=(A|0)==1;l=(A|0)<3;j=n;while(1){m:do{if((a[j]|0)==p<<24>>24){if(m){K=E;L=j;x=115;break h}if((a[j+y|0]|0)==F<<24>>24){if(l){K=E;L=j;x=115;break h}else{P=1}while(1){n=P+1|0;if((a[j+P|0]|0)!=(a[g+P|0]|0)){break m}if((n|0)<(A|0)){P=n}else{K=E;L=j;x=115;break h}}}}}while(0);n=j+1|0;if(n>>>0>>0){j=n}else{Q=G;break}}}else{Q=G}while(1){j=Q+ -1|0;if((a[j]|0)==32){Q=j}else{K=E;L=Q;x=115;break h}}}if((G|0)==0){j=E+1|0;d=Dg(j|0)|0;A=Dg(g|0)|0;if((A|0)==0){K=E;L=j;x=115}else{if((d|0)!=0?(l=a[g]|0,F=A+ -1|0,y=a[g+F|0]|0,m=d+1-A|0,d=E+(m+1)|0,(m|0)>0):0){m=(A|0)==1;p=(A|0)<3;H=j;do{n:do{if((a[H]|0)==l<<24>>24){if(m){K=E;L=H;x=115;break h}if((a[H+F|0]|0)==y<<24>>24){if(p){K=E;L=H;x=115;break h}else{R=1}while(1){j=R+1|0;if((a[H+R|0]|0)!=(a[g+R|0]|0)){break n}if((j|0)<(A|0)){R=j}else{K=E;L=H;x=115;break h}}}}}while(0);H=H+1|0}while(H>>>0>>0)}d=o+79|0;while(1){if((a[d]|0)==32){d=d+ -1|0}else{break}}K=E;L=d+1|0;x=115}}else{x=116}}}while(0);if((x|0)==115){S=K+1|0;T=L}else if((x|0)==116){L=Dg(o|0)|0;o:do{if((L|0)!=0?(K=o+L|0,(L|0)>0):0){E=o;while(1){if((a[E]|0)==61){U=E;break o}R=E+1|0;if(R>>>0>>0){E=R}else{U=0;break}}}else{U=0}}while(0);L=(U|0)==0?o+9|0:U+1|0;U=Dg(o|0)|0;p:do{if((U|0)!=0?(E=o+U|0,(U|0)>0):0){K=o;while(1){if((a[K]|0)==47){V=K;break p}d=K+1|0;if(d>>>0>>0){K=d}else{V=0;break}}}else{V=0}}while(0);S=L;T=(V|0)==0?o+79|0:V}if((c[1968]|0)==0){V=S;while(1){if((a[V]|0)==32&V>>>0>>0){V=V+1|0}else{W=V;break}}}else{W=S}a[T]=0;q:do{if((c[1968]|0)==0){S=T;while(1){V=S+ -1|0;o=a[V]|0;if(!(o<<24>>24==13|o<<24>>24==32)){break q}if(!(V>>>0>W>>>0)){break q}a[V]=0;S=V}}}while(0);T=(yg(W,7960)|0)==0;S=T?W+1|0:W;Lg(7880,S|0)|0;if((C|0)==0){D=7880;i=e;return D|0}W=Dg(C|0)|0;T=Dg(k|0)|0;r:do{if((T|0)!=0){if((W|0)!=0?(V=a[k]|0,o=T+ -1|0,L=a[k+o|0]|0,U=W+1-T|0,K=C+U|0,(U|0)>0):0){U=(T|0)==1;E=(T|0)<3;d=C;s:while(1){t:do{if((a[d]|0)==V<<24>>24){if(U){break s}if((a[d+o|0]|0)==L<<24>>24){if(E){break s}else{X=1}while(1){R=X+1|0;if((a[d+X|0]|0)!=(a[k+X|0]|0)){break t}if((R|0)<(T|0)){X=R}else{break s}}}}}while(0);R=d+1|0;if(R>>>0>>0){d=R}else{break r}}if((d|0)!=0){Y=d;x=144}}}else{Y=C;x=144}}while(0);if((x|0)==144){a[Y]=0}if((Gc(C)|0)==0){Y=Dg(C|0)|0;if((Y|0)>0){x=0;do{X=C+x|0;T=a[X]|0;if((T+ -65<<24>>24&255)<26){a[X]=(T&255)+32}x=x+1|0}while((x|0)!=(Y|0))}Y=_c(7880,C)|0;if((Y|0)==0){D=0;i=e;return D|0}Lg(7880,Y|0)|0;D=7880;i=e;return D|0}Y=vg(C)|0;a[f]=32;a[f+1|0]=0;if((Y|0)>0){C=1;x=S;while(1){Z=fg(x,f)|0;if((C|0)==(Y|0)){break}else{C=C+1|0;x=0}}if((Z|0)==0){D=0;i=e;return D|0}Lg(7880,Z|0)|0;D=7880;i=e;return D|0}if((Y|0)>=0){D=7880;i=e;return D|0}Z=0-Y|0;u:do{if((Z|0)<=1){if((S|0)==0){D=0;i=e;return D|0}else{_=S}}else{Y=1;x=S;while(1){C=$f(x,32)|0;if((C|0)==0){D=0;break}f=C+1|0;C=Y+1|0;if((C|0)<(Z|0)){Y=C;x=f}else{_=f;break u}}i=e;return D|0}}while(0);Lg(7880,_|0)|0;D=7880;i=e;return D|0}function Gc(b){b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;c=i;a:do{if((b|0)!=0?(d=a[b]|0,!(d<<24>>24==101|d<<24>>24==69|d<<24>>24==100|d<<24>>24==68)):0){e=Dg(b|0)|0;while(1){f=e+ -1|0;if((a[b+f|0]|0)==32){e=f}else{break}}if((e|0)>0){f=d;g=0;h=1;j=0;k=0;while(1){if(f<<24>>24==32){if((k|0)==0){l=g;m=h;n=0}else{o=0;break a}}else if(!(f<<24>>24==10)){b:do{if(!((f+ -48<<24>>24&255)<10)){switch(f<<24>>24){case 45:case 43:{break};case 101:case 100:case 69:case 68:case 58:case 46:{p=13;break b;break};default:{o=0;break a}}q=a[b+(j+1)|0]|0;if(q<<24>>24==43|q<<24>>24==45){o=0;break a}if((j|0)>0){switch(a[b+(j+ -1)|0]|0){case 32:case 58:case 101:case 69:case 100:case 68:{r=g;s=k;break};default:{o=0;break a}}}else{r=g;s=k}}else{p=13}}while(0);do{if((p|0)==13){p=0;if((f+ -47<<24>>24&255)<11){r=g;s=k+1|0;break}else{r=(f<<24>>24==58)+g|0;s=k;break}}}while(0);if(f<<24>>24==101|f<<24>>24==100|f<<24>>24==46){l=r;m=2;n=s}else{l=r;m=h;n=s}}else{t=g;u=h;v=k;break}q=j+1|0;if((q|0)>=(e|0)){t=l;u=m;v=n;break}f=a[b+q|0]|0;g=l;h=m;j=q;k=n}if((v|0)>0){o=(t|0)==0?u:3}else{o=0}}else{o=0}}else{o=0}}while(0);i=c;return o|0}function Hc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,j=0.0,k=0,l=0,m=0.0;e=i;f=Fc(b,c)|0;if((f|0)==0){g=0;i=e;return g|0}j=+Jc(f);c=Dg(f|0)|0;a:do{if((c|0)!=0?(b=f+c|0,(c|0)>0):0){k=f;while(1){if((a[k]|0)==58){break}l=k+1|0;if(l>>>0>>0){k=l}else{m=j;break a}}if((k|0)!=0){m=j*15.0}else{m=j}}else{m=j}}while(0);h[d>>3]=m;g=1;i=e;return g|0}function Ic(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;d=i;e=Fc(a,b)|0;if((e|0)==0){f=0}else{h[c>>3]=+Jc(e);f=1}i=d;return f|0}function Jc(b){b=b|0;var c=0,d=0.0,e=0,f=0,g=0,h=0,j=0.0,k=0,l=0.0,m=0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0,w=0.0,x=0.0;c=i;if((b|0)==0){d=0.0;i=c;return+d}e=a[b]|0;if(e<<24>>24==0){d=0.0;i=c;return+d}else{f=e;g=b}while(1){if(f<<24>>24==43){h=5;break}else if(f<<24>>24==45){j=-1.0;h=6;break}else if(!(f<<24>>24==32)){h=7;break}b=g+1|0;f=a[b]|0;g=b}if((h|0)==5){j=1.0;h=6}else if((h|0)==7){f=Dg(g|0)|0;if((g|0)==0){k=1;l=1.0;m=0}else{n=f;o=1.0;p=g;h=8}}if((h|0)==6){f=g+1|0;n=Dg(f|0)|0;o=j;p=f;h=8}a:do{if((h|0)==8){if((n|0)!=0?(f=p+n|0,(n|0)>0):0){g=p;while(1){if((a[g]|0)==44){break}b=g+1|0;if(b>>>0>>0){g=b}else{k=0;l=o;m=p;break a}}if((g|0)!=0){a[g]=32;k=0;l=o;m=p}else{k=0;l=o;m=p}}else{k=0;l=o;m=p}}}while(0);p=Dg(m|0)|0;while(1){n=p+ -1|0;if((a[m+n|0]|0)==32){p=n}else{break}}n=Dg(m|0)|0;b:do{if(!k){c:do{if((n|0)!=0?(f=m+n|0,(n|0)>0):0){b=m;while(1){if((a[b]|0)==58){break}e=b+1|0;if(e>>>0>>0){b=e}else{h=22;break c}}if((b|0)!=0){q=b}else{h=22}}else{h=22}}while(0);if((h|0)==22){if((p|0)==0){break}g=m+p|0;if((p|0)>0){r=m}else{break}while(1){if((a[r]|0)==32){break}f=r+1|0;if(f>>>0>>0){r=f}else{break b}}if((r|0)==0){break}else{q=r}}a[q]=0;o=+(vg(m)|0);a[q]=58;g=q+1|0;f=Dg(g|0)|0;d:do{if((f|0)!=0?(e=q+(f+1)|0,(f|0)>0):0){s=g;while(1){if((a[s]|0)==58){t=s;h=35;break d}u=s+1|0;if(u>>>0>>0){s=u}else{h=31;break}}}else{h=31}}while(0);e:do{if((h|0)==31){f=Dg(g|0)|0;if((f|0)!=0?(s=q+(f+1)|0,(f|0)>0):0){f=g;do{if((a[f]|0)==32){t=f;h=35;break e}f=f+1|0}while(f>>>0>>0)}s=Dg(g|0)|0;f:do{if((s|0)!=0?(f=q+(s+1)|0,(s|0)>0):0){e=g;while(1){if((a[e]|0)==46){break}b=e+1|0;if(b>>>0>>0){e=b}else{v=0.0;break f}}v=+ug(g)}else{v=0.0}}while(0);if((a[g]|0)==0){w=v;x=0.0}else{w=+(vg(g)|0);x=0.0}}}while(0);if((h|0)==35){a[t]=0;j=+(vg(g)|0);a[t]=58;w=j;x=+ug(t+1|0)}d=l*(o+w/60.0+x/3600.0);i=c;return+d}}while(0);if((Gc(m)|0)!=2){d=l*+(vg(m)|0);i=c;return+d}t=$f(m,68)|0;if((t|0)!=0){a[t]=101}t=$f(m,100)|0;if((t|0)!=0){a[t]=101}t=$f(m,69)|0;if((t|0)!=0){a[t]=101}d=l*+ug(m);i=c;return+d}function Kc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;i=i+16|0;g=f;if((a[d]|0)<64){h=Lc(b,c,e)|0;i=f;return h|0}else{Lg(g|0,c|0)|0;j=Dg(c|0)|0;a[g+j|0]=a[d]|0;a[g+(j+1)|0]=0;h=Lc(b,g,e)|0;i=f;return h|0}return 0}function Lc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;e=i;f=Fc(b,c)|0;if((f|0)==0){g=0;i=e;return g|0}c=(a[f]|0)==35?f+1|0:f;if((Dg(c|0)|0)>81){Hg(7704,c|0,81)|0;a[7785|0]=0}else{Lg(7704,c|0)|0}if((Gc(7704)|0)==2){c=$f(7704,68)|0;if((c|0)!=0){a[c]=101}c=$f(7704,100)|0;if((c|0)!=0){a[c]=101}c=$f(7704,69)|0;if((c|0)!=0){a[c]=101}}h[d>>3]=+ug(7704);g=1;i=e;return g|0}function Mc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0;f=i;g=Fc(b,d)|0;if((g|0)==0){j=0;i=f;return j|0}d=$f(g,47)|0;b=$f(g,45)|0;if(d>>>0>g>>>0){a[d]=0;k=~~+ug(g);a[d]=47;l=d+1|0;d=$f(l,47)|0;if((d|0)==0){m=$f(l,45)|0}else{m=d}if(!(m>>>0>g>>>0)){j=0;i=f;return j|0}a[m]=0;d=~~+ug(l);a[m]=47;l=~~+ug(m+1|0);m=(k|0)>31;n=m?k:l;o=m?l:k;if(n>>>0<50){p=n+2e3|0}else{p=(n|0)<100?n+1900|0:n}n=((p|0)%100|0|0)!=0|((p|0)%400|0|0)==0?(p&3|0)==0?29:28:28;c[7796>>2]=n;k=d+ -1|0;d=c[7792+(k<<2)>>2]|0;if((o|0)>(d|0)){q=d}else{q=(o|0)<1?1:o}r=(n|0)==28?365.0:366.0;n=q+ -1|0;if((k|0)>0){q=0;o=n;while(1){d=(c[7792+(q<<2)>>2]|0)+o|0;l=q+1|0;if((l|0)==(k|0)){s=d;break}else{q=l;o=d}}}else{s=n}h[e>>3]=+(p|0)+ +(s|0)/r;j=1;i=f;return j|0}if(!(b>>>0>g>>>0)){j=0;i=f;return j|0}a[b]=0;s=~~+ug(g);a[b]=45;p=b+1|0;b=$f(p,45)|0;do{if(b>>>0>g>>>0){a[b]=0;n=~~+ug(p);a[b]=45;o=b+1|0;q=$f(o,84)|0;if(q>>>0>g>>>0){a[q]=0;k=~~+ug(o);a[q]=84;t=k;u=n;v=q;break}else{t=~~+ug(o);u=n;v=q;break}}else{t=1;u=1;v=0}}while(0);b=(s|0)<32;p=b?t+1900|0:s;q=b?s:t;t=((p|0)%100|0|0)!=0|((p|0)%400|0|0)==0?(p&3|0)==0?29:28:28;c[7796>>2]=t;s=u+ -1|0;u=c[7792+(s<<2)>>2]|0;if((q|0)>(u|0)){w=u}else{w=(q|0)<1?1:q}r=(t|0)==28?365.0:366.0;t=w+ -1|0;if((s|0)>0){w=0;q=t;while(1){u=(c[7792+(w<<2)>>2]|0)+q|0;b=w+1|0;if((b|0)==(s|0)){x=u;break}else{w=b;q=u}}}else{x=t}h[e>>3]=+(p|0)+ +(x|0)/r;if(!(v>>>0>g>>>0)){j=1;i=f;return j|0}x=v+1|0;v=$f(x,58)|0;do{if(v>>>0>g>>>0){a[v]=0;p=~~+ug(x);a[v]=58;t=v+1|0;q=$f(t,58)|0;if(q>>>0>g>>>0){a[q]=0;w=~~+ug(t);a[q]=58;y=p;z=w;A=+ug(q+1|0);break}else{y=p;z=~~+ug(t);A=0.0;break}}else{y=0;z=0;A=0.0}}while(0);h[e>>3]=+h[e>>3]+(A+(+(y|0)*3600.0+ +(z|0)*60.0))/86400.0/r;j=1;i=f;return j|0}function Nc(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+32|0;h=g+8|0;j=g+16|0;k=g;c[h>>2]=d;Na(j|0,7840,h|0)|0;do{if((Cc(b,j)|0)==0){c[h>>2]=d;Na(j|0,7856,h|0)|0;if((Cc(b,j)|0)!=0){l=k;c[l>>2]=627012389;c[l+4>>2]=6566448;break}c[h>>2]=d;Na(j|0,7864,h|0)|0;if((Cc(b,j)|0)!=0){l=k;c[l>>2]=627012389;c[l+4>>2]=6566704;break}if((Cc(b,j)|0)==0){m=0;i=g;return m|0}else{l=k;c[l>>2]=627012389;c[l+4>>2]=6566704;break}}else{a[k+0|0]=a[7848|0]|0;a[k+1|0]=a[7849|0]|0;a[k+2|0]=a[7850|0]|0;a[k+3|0]=a[7851|0]|0;a[k+4|0]=a[7852|0]|0;a[k+5|0]=a[7853|0]|0}}while(0);c[1968]=1;l=1;n=e;e=f;while(1){c[h>>2]=d;c[h+4>>2]=l;Na(j|0,k|0,h|0)|0;o=Fc(b,j)|0;if((o|0)==0){p=l;break}q=Dg(o|0)|0;if((q|0)>=(n|0)){r=13;break}Lg(e|0,o|0)|0;s=l+1|0;if((s|0)<500){l=s;n=n-q|0;e=e+q|0}else{p=s;break}}do{if((r|0)==13){if((n|0)>1){Hg(e|0,o|0,n+ -1|0)|0;a[e+n|0]=0;p=l;break}else{a[f]=a[o]|0;p=l;break}}}while(0);c[1968]=0;m=(p|0)>1|0;i=g;return m|0}function Oc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;g=i;i=i+16|0;h=g;do{if((a[d]|0)<64){j=Fc(b,c)|0;if((j|0)!=0){if((Dg(j|0)|0)<(e|0)){Lg(f|0,j|0)|0;k=1;break}if((e|0)>1){Hg(f|0,j|0,e+ -1|0)|0;k=1;break}else{a[f]=a[j]|0;k=1;break}}else{k=0}}else{Lg(h|0,c|0)|0;j=Dg(c|0)|0;a[h+j|0]=a[d]|0;a[h+(j+1)|0]=0;j=Fc(b,h)|0;if((j|0)!=0){if((Dg(j|0)|0)<(e|0)){Lg(f|0,j|0)|0;k=1;break}if((e|0)>1){Hg(f|0,j|0,e+ -1|0)|0;k=1;break}else{a[f]=a[j]|0;k=1;break}}else{k=0}}}while(0);i=g;return k|0}function Pc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=i;g=Fc(b,c)|0;do{if((g|0)!=0){if((Dg(g|0)|0)<(d|0)){Lg(e|0,g|0)|0;h=1;break}if((d|0)>1){Hg(e|0,g|0,d+ -1|0)|0;h=1;break}else{a[e]=a[g]|0;h=1;break}}else{h=0}}while(0);i=f;return h|0}function Qc(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;d=i;e=Dg(b|0)|0;a:do{if(!((b|0)==0|(c|0)==0)){f=Dg(c|0)|0;if((f|0)!=0){if((e|0)!=0?(g=a[c]|0,h=f+ -1|0,j=a[c+h|0]|0,k=e+1-f|0,l=b+k|0,(k|0)>0):0){k=(f|0)==1;m=(f|0)<3;n=b;while(1){b:do{if((a[n]|0)==g<<24>>24){if(k){o=n;break a}if((a[n+h|0]|0)==j<<24>>24){if(m){o=n;break a}else{p=1}while(1){q=p+1|0;if((a[n+p|0]|0)!=(a[c+p|0]|0)){break b}if((q|0)<(f|0)){p=q}else{o=n;break a}}}}}while(0);q=n+1|0;if(q>>>0>>0){n=q}else{o=0;break}}}else{o=0}}else{o=b}}else{o=0}}while(0);i=d;return o|0}function Rc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;e=i;if((b|0)==0|(c|0)==0){f=0;i=e;return f|0}g=Dg(c|0)|0;if((g|0)==0){f=b;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}do{if((g|0)<3){h=a[c]|0;j=h<<24>>24;if(!((h+ -97<<24>>24&255)<26)){if((h+ -65<<24>>24&255)<26){k=j+32&255}else{k=h}}else{k=j+224&255}if((g|0)>1){j=a[c+1|0]|0;l=j<<24>>24;if((j+ -97<<24>>24&255)<26){m=h;n=j;o=k;p=l+224&255;q=0;break}if((j+ -65<<24>>24&255)<26){m=h;n=j;o=k;p=l+32&255;q=0}else{m=h;n=j;o=k;p=j;q=0}}else{m=h;n=32;o=k;p=32;q=0}}else{h=ig(g,1)|0;j=0;do{l=a[c+j|0]|0;r=l&255;do{if(!((l+ -97<<24>>24&255)<26)){if((l+ -65<<24>>24&255)<26){a[h+j|0]=r+32;break}else{a[h+j|0]=l;break}}else{a[h+j|0]=r+224}}while(0);j=j+1|0}while((j|0)!=(g|0));j=g+ -1|0;m=a[c]|0;n=a[c+j|0]|0;o=a[h]|0;p=a[h+j|0]|0;q=h}}while(0);k=d+1-g|0;d=b+k|0;a:do{if((k|0)>0){j=g+ -1|0;r=(g|0)>1;if((g|0)==2){l=b;while(1){s=a[l]|0;if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24?(s=a[l+j|0]|0,s<<24>>24==n<<24>>24|s<<24>>24==p<<24>>24):0){break}s=l+1|0;if(s>>>0>>0){l=s}else{break a}}if((q|0)==0){f=l;i=e;return f|0}hg(q);f=l;i=e;return f|0}else if((g|0)==1){h=b;while(1){s=a[h]|0;if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24){break}s=h+1|0;if(s>>>0>>0){h=s}else{break a}}if((q|0)==0){f=h;i=e;return f|0}hg(q);f=h;i=e;return f|0}else{l=b;b:while(1){s=a[l]|0;c:do{if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24?(t=a[l+j|0]|0,t<<24>>24==n<<24>>24|t<<24>>24==p<<24>>24):0){if(r){u=1}else{break b}while(1){t=a[l+u|0]|0;if(!(t<<24>>24==(a[c+u|0]|0))?!(t<<24>>24==(a[q+u|0]|0)):0){break c}u=u+1|0;if((u|0)>=(g|0)){break b}}}}while(0);s=l+1|0;if(s>>>0>>0){l=s}else{break a}}if((q|0)==0){f=l;i=e;return f|0}hg(q);f=l;i=e;return f|0}}}while(0);if((q|0)==0){f=0;i=e;return f|0}hg(q);f=0;i=e;return f|0}function Sc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;a:do{if(!((b|0)==0|(c|0)==0)){f=Dg(c|0)|0;if((f|0)!=0){if((d|0)!=0?(g=a[c]|0,h=f+ -1|0,j=a[c+h|0]|0,k=d+1-f|0,l=b+k|0,(k|0)>0):0){k=(f|0)==1;m=b;while(1){b:do{if((a[m]|0)==g<<24>>24){if(k){n=m;break a}if((a[m+h|0]|0)==j<<24>>24){if((f|0)<3){n=m;break a}else{o=1}while(1){p=o+1|0;if((a[m+o|0]|0)!=(a[c+o|0]|0)){break b}if((p|0)<(f|0)){o=p}else{n=m;break a}}}}}while(0);p=m+1|0;if(p>>>0>>0){m=p}else{n=0;break}}}else{n=0}}else{n=b}}else{n=0}}while(0);i=e;return n|0}function Tc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0;g=i;i=i+80|0;j=g;l=g+16|0;if(e<0.0){m=-e;n=-1.0}else{m=e;n=1.0}e=n*+qa(+m,360.0);if(e<0.0){o=e+360.0}else{o=e}e=o/15.0;p=~~e;o=(e- +(p|0))*60.0;q=~~o;e=(o- +(q|0))*60.0;do{if((f|0)<=5){if((f|0)>4){r=e>59.99999;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8008,j|0)|0;break}if((f|0)>3){s=e>59.9999;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,8032,j|0)|0;break}if((f|0)>2){r=e>59.999;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8056,j|0)|0;break}if((f|0)>1){s=e>59.99;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,8080,j|0)|0;break}if((f|0)>0){r=e>59.9;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8104,j|0)|0;break}else{s=~~(e+.5);r=(s|0)>59;t=(r&1)+q|0;u=(t|0)>59;c[j>>2]=((u&1)+p|0)%24|0;c[j+4>>2]=u?0:t;c[j+8>>2]=r?0:s;Na(l|0,8128,j|0)|0;break}}else{s=e>59.999999;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,7984,j|0)|0}}while(0);j=d+ -1|0;if((Dg(l|0)|0)<(j|0)){Lg(b|0,l|0)|0;i=g;return}else{Hg(b|0,l|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Uc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;g=i;i=i+96|0;j=g;l=g+24|0;if(e<0.0){m=-e;n=-1.0}else{m=e;n=1.0}e=n*+qa(+m,360.0);if(!(e<=-180.0)){o=e}else{o=e+360.0}if(o<0.0){p=-o;q=45}else{p=o;q=43}r=~~p;o=(p- +(r|0))*60.0;s=~~o;p=(o- +(s|0))*60.0;do{if((f|0)<=5){if((f|0)>4){t=p>59.99999;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8168,j|0)|0;break}if((f|0)>3){u=p>59.9999;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8192,j|0)|0;break}if((f|0)>2){t=p>59.999;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8216,j|0)|0;break}if((f|0)>1){u=p>59.99;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8240,j|0)|0;break}if((f|0)>0){t=p>59.9;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8264,j|0)|0;break}else{u=~~(p+.5);t=(u|0)>59;v=(t&1)+s|0;w=(v|0)>59;c[j>>2]=q&255;c[j+4>>2]=(w&1)+r;c[j+8>>2]=w?0:v;c[j+12>>2]=t?0:u;Na(l|0,8288,j|0)|0;break}}else{u=p>59.999999;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8144,j|0)|0}}while(0);j=d+ -1|0;if((Dg(l|0)|0)<(j|0)){Lg(b|0,l|0)|0;i=g;return}else{Hg(b|0,l|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Vc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0;g=i;i=i+80|0;j=g;l=g+72|0;m=g+8|0;if(e<0.0){n=-e;o=-1.0}else{n=e;o=1.0}e=o*+qa(+n,360.0);if(!(e<=-180.0)){p=e}else{p=e+360.0}q=f+4|0;if((f|0)>0){c[j>>2]=q;c[j+4>>2]=f;Na(l|0,8312,j|0)|0;h[k>>3]=p;c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];Na(m|0,l|0,j|0)|0}else{c[j>>2]=q;Na(l|0,8328,j|0)|0;c[j>>2]=~~p;Na(m|0,l|0,j|0)|0}j=d+ -1|0;if((Dg(m|0)|0)<(j|0)){Lg(b|0,m|0)|0;i=g;return}else{Hg(b|0,m|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Wc(a,b,d,e){a=a|0;b=+b;d=d|0;e=e|0;var f=0,g=0,j=0,l=0;f=i;i=i+16|0;g=f;j=f+8|0;l=(e|0)>0;if((d|0)>0){if(l){c[g>>2]=d;c[g+4>>2]=e;Na(j|0,8312,g|0)|0;h[k>>3]=b;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];Na(a|0,j|0,g|0)|0;i=f;return}else{c[g>>2]=d;Na(j|0,8336,g|0)|0;c[g>>2]=~~b;Na(a|0,j|0,g|0)|0;i=f;return}}else{if(l){c[g>>2]=e;Na(j|0,7976,g|0)|0;h[k>>3]=b;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];Na(a|0,j|0,g|0)|0;i=f;return}else{c[g>>2]=~~b;Na(a|0,7968,g|0)|0;i=f;return}}}function Xc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=i;i=i+32|0;e=d;f=_c(a,b)|0;if((f|0)==0){g=0;i=d;return g|0}Lg(e|0,f|0)|0;h[c>>3]=+ug(e);g=1;i=d;return g|0}function Yc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;g=i;h=gg(2e3)|0;if((Nc(b,c,2e3,h)|0)==0){hg(h);j=0;i=g;return j|0}c=_c(h,d)|0;do{if((c|0)!=0){if((Dg(c|0)|0)<(e|0)){Lg(f|0,c|0)|0;k=1;break}if((e|0)>1){Hg(f|0,c|0,e+ -1|0)|0;k=1;break}else{a[f]=a[c]|0;k=1;break}}else{k=0}}while(0);hg(h);j=k;i=g;return j|0}function Zc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=i;g=_c(b,c)|0;do{if((g|0)!=0){if((Dg(g|0)|0)<(d|0)){Lg(e|0,g|0)|0;h=1;break}if((d|0)>1){Hg(e|0,g|0,d+ -1|0)|0;h=1;break}else{a[e]=a[g]|0;h=1;break}}else{h=0}}while(0);i=f;return h|0}function _c(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=i;i=i+2032|0;e=d+2024|0;f=d+2018|0;g=d+2016|0;h=d+2e3|0;j=d;a[f]=91;a[f+1|0]=0;a[g]=93;a[g+1|0]=0;Lg(h|0,c|0)|0;c=Qc(h,f)|0;f=(c|0)!=0;if(f){a[c]=0;k=0}else{k=0}while(1){l=k+1|0;if((a[b+k|0]|0)==0){m=6;break}if((l|0)<57600){k=l}else{m=4;break}}if((m|0)==4){n=l;o=Dg(h|0)|0}else if((m|0)==6){l=Dg(h|0)|0;if((k|0)>0){n=k;o=l}else{p=0;i=d;return p|0}}l=b+n|0;n=l;k=b;while(1){q=Sc(k,h,n-k|0)|0;if((q|0)==0){p=0;m=34;break}r=a[q+o|0]|0;s=a[q+ -1|0]|0;if(!(r<<24>>24>32?!(r<<24>>24==61|r<<24>>24==127):0)){if((q|0)==(b|0)){t=b;m=14;break}if(s<<24>>24==9|s<<24>>24==32){t=q;m=14;break}}s=q+1|0;if(s>>>0>>0){k=s}else{p=0;m=34;break}}if((m|0)==14){if((t|0)==0){p=0;i=d;return p|0}k=t+o|0;while(1){o=a[k]|0;if(!(o<<24>>24==61|o<<24>>24==32)){break}k=k+1|0}if((k|0)==0){p=0;i=d;return p|0}Eg(j|0,0,2e3)|0;o=a[k]|0;a:do{if(o<<24>>24==34){t=k;l=0;while(1){b=t+1|0;n=a[b]|0;if(n<<24>>24==34|n<<24>>24==0){break a}if((l|0)>=2e3){break a}a[j+l|0]=n;t=b;l=l+1|0}}else{l=o;t=0;b=k;while(1){if(l<<24>>24==9|l<<24>>24==32){break a}if(!(l<<24>>24>0&(t|0)<2e3)){break a}n=b+1|0;a[j+t|0]=l;l=a[n]|0;t=t+1|0;b=n}}}while(0);if(!f){Lg(8344,j|0)|0;p=8344;i=d;return p|0}f=c+1|0;c=Qc(f,g)|0;if((c|0)==0){p=8344;i=d;return p|0}a[c]=0;c=vg(f)|0;if((c|0)<=0){p=8344;i=d;return p|0}a[e]=32;a[e+1|0]=44;a[e+2|0]=0;f=fg(j,e)|0;if((c|0)>1){j=1;while(1){g=fg(0,e)|0;k=j+1|0;if((k|0)==(c|0)){u=g;break}else{j=k}}}else{u=f}if((u|0)==0){p=8344;i=d;return p|0}Lg(8344,u|0)|0;p=8344;i=d;return p|0}else if((m|0)==34){i=d;return p|0}return 0}function $c(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0;g=i;j=c[d+3260>>2]|0;k=+h[d>>3];l=+h[d+8>>3];m=+h[d+32>>3];n=+h[d+40>>3];o=+h[d+48>>3]*3.141592653589793/180.0;p=+S(+o);q=+T(+o);r=a- +h[d+16>>3];a=b- +h[d+24>>3];do{if((c[d+3300>>2]|0)==0){if(m==0.0|n==0.0){h[e>>3]=0.0;h[f>>3]=0.0;s=2;i=g;return s|0}else{b=r*m;t=a*n;if(!(o!=0.0)){u=b;v=t;break}u=b*p-t*q;v=t*p+b*q;break}}else{u=r*+h[d+56>>3]+a*+h[d+64>>3];v=r*+h[d+72>>3]+a*+h[d+80>>3]}}while(0);w=(c[d+3304>>2]|0)==0;a=w?v:u;r=w?u:v;h[e>>3]=k+r;h[f>>3]=l+a;if((j|0)<1){s=0;i=g;return s|0}v=k*3.141592653589793/180.0;k=l*3.141592653589793/180.0;u=w?k:v;o=w?v:k;v=r*3.141592653589793/180.0;r=a*3.141592653589793/180.0;a=v*v;b=a+r*r;t=+S(+u);x=+T(+u);a:do{switch(j|0){case 11:{y=u+r;z=o+v;break};case 32:case 33:case 31:case 3:{if(b>1.0){s=1;i=g;return s|0}A=t-r*x;if(A==0.0){s=1;i=g;return s|0}else{B=o+ +Y(+v,+A);y=+X(+((r*t+x)*+S(+(B-o))/A));z=B;break a}break};case 6:{if(b>=9.869604401089369){s=1;i=g;return s|0}B=+Q(+b);A=+S(+B);if(B!=0.0){C=+T(+B)/B}else{C=1.0}B=x*A+r*t*C;if(B>1.0|B<-1.0){s=1;i=g;return s|0}D=A-x*B;A=t*v*C;if(D==0.0&A==0.0){s=1;i=g;return s|0}else{y=+W(+B);z=o+ +Y(+A,+D);break a}break};case 22:{D=n*p+m*q;A=(D==0.0?3.141592653589793:D*3.141592653589793)/180.0;D=k+A;B=+T(+k);E=+S(+k);F=+Q(+((E+1.0)*.5));G=+T(+D)/+Q(+((+S(+D)+1.0)*.5))-B/F;D=A/(G==0.0?1.0:G);G=m*p-n*q;A=(G==0.0?3.141592653589793:G*3.141592653589793)/180.0;G=A*.5;H=E*2.0*+T(+G);I=A*+Q(+((E*+S(+G)+1.0)*.5))/(H==0.0?1.0:H);if(!(v==0.0&r==0.0)){H=r+B*D/F;F=H/D;B=4.0-a/(I*I*4.0)-F*F;if(B>4.0|B<2.0){s=1;i=g;return s|0}F=+Q(+B)*.5;B=H*F/D;if(+P(+B)>1.0){s=1;i=g;return s|0}D=+W(+B);B=+S(+D);if(+P(+B)<1.0e-5){s=1;i=g;return s|0}H=v*F/(I*2.0*B);if(+P(+H)>1.0){s=1;i=g;return s|0}else{y=D;z=o+ +W(+H)*2.0;break a}}else{y=u;z=o}break};case 5:{H=(4.0-b)/(b+4.0);if(+P(+H)>1.0){s=1;i=g;return s|0}D=H+1.0;B=x*H+r*t*D*.5;if(+P(+B)>1.0){s=1;i=g;return s|0}H=+W(+B);B=+S(+H);if(+P(+B)<1.0e-5){s=1;i=g;return s|0}I=v*D/(B*2.0);if(+P(+I)>1.0){s=1;i=g;return s|0}D=+W(+I);I=+T(+H);F=+S(+D);G=x*I+1.0+t*B*F;if(+P(+G)<1.0e-5){s=1;i=g;return s|0}if(+P(+((t*I-x*B*F)*2.0/G-r))>1.0e-5){J=3.141592653589795-D}else{J=D}y=H;z=o+J;break};case 20:case 28:{H=u+r;if(+P(+H)>1.5707963267948974){s=1;i=g;return s|0}D=+S(+H);if(+P(+v)>D*6.28318530717959*.5){s=1;i=g;return s|0}if(D>1.0e-5){y=H;z=o+v/D}else{y=H;z=o}break};case 27:{H=t-r*x;if(H==0.0){s=1;i=g;return s|0}D=o+ +Y(+v,+H);G=+S(+(D-o));if(G==0.0){s=1;i=g;return s|0}F=H/G;if(F>1.0|F<-1.0){s=1;i=g;return s|0}G=+V(+F);if(u<0.0){y=-G;z=D}else{y=G;z=D}break};case 12:{D=n*p+m*q;G=D==0.0?1.0:D;D=(l*.5+45.0)*3.141592653589793/180.0;F=+_(+(+U(+D)));H=G*3.141592653589793/180.0/(+_(+(+U(+(G*.5*.01745329252+D))))-F);D=+S(+k);G=o+v/(!(D<=0.0)?D:1.0);if(+P(+(G-o))>6.28318530717959){s=1;i=g;return s|0}if(H!=0.0){K=(r+F*H)/H}else{K=0.0}y=+X(+(+Z(+K)))*2.0+-1.5707963267948974;z=G;break};case 4:{if(b>1.0){s=1;i=g;return s|0}G=+Q(+(1.0-b));H=r*t+x*G;if(H>1.0|H<-1.0){s=1;i=g;return s|0}F=t*G-r*x;if(F==0.0&v==0.0){s=1;i=g;return s|0}else{y=+W(+H);z=o+ +Y(+v,+F);break a}break};case 16:{F=1.0/+U(+u)-r;if(u<0.0){L=-F}else{L=F}y=+W(+((x*x*(1.0-(a+F*F))+1.0)*(1.0/(x*2.0))));z=o- +Y(+v,+L)/x;break};default:{y=0.0;z=0.0}}}while(0);if(z-o>3.141592653589795){M=z+-6.28318530717959}else{M=z}if(M-o<-3.141592653589795){N=M+6.28318530717959}else{N=M}if(N<0.0){O=N+6.28318530717959}else{O=N}h[e>>3]=O*180.0/3.141592653589793;h[f>>3]=y*180.0/3.141592653589793;s=0;i=g;return s|0}function ad(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0,N=0.0,O=0.0,R=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0;g=i;j=+h[d>>3];k=+h[d+8>>3];l=+h[d+16>>3];m=+h[d+24>>3];n=+h[d+32>>3];o=+h[d+40>>3];p=+h[d+48>>3]*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=c[d+3260>>2]|0;t=(s|0)>0;if(t){u=(c[d+3304>>2]|0)==0;v=j*3.141592653589793/180.0;w=k*3.141592653589793/180.0;x=u?w:v;y=u?v:w;w=a-(u?j:k);v=l*n;if(v>180.0|v<-180.0){if(w>360.0){z=a+-360.0}else{z=a}if(w<0.0){A=z+360.0}else{A=z}}else{if(w>180.0){B=a+-360.0}else{B=a}if(w<-180.0){A=B+360.0}else{A=B}}B=A*3.141592653589793/180.0;w=b*3.141592653589793/180.0;z=+S(+w);v=+T(+w);C=B-y;D=A;E=z;F=w;G=x;H=z*+T(+C);I=B;J=y;K=v;L=v*+T(+x)+z*+S(+x)*+S(+C)}else{D=a;E=0.0;F=0.0;G=0.0;H=0.0;I=0.0;J=0.0;K=0.0;L=0.0}a:do{switch(s|0){case 22:{a=(I-J)*.5;if(+P(+a)>1.5707963267948974){M=1;i=g;return M|0}C=o*q+n*r;x=(C==0.0?3.141592653589793:C*3.141592653589793)/180.0;C=k*3.141592653589793/180.0;z=x+C;v=+T(+C);y=+S(+C);C=+Q(+((y+1.0)*.5));B=+T(+z)/+Q(+((+S(+z)+1.0)*.5))-v/C;z=x/(B==0.0?1.0:B);B=n*q-o*r;x=(B==0.0?3.141592653589793:B*3.141592653589793)/180.0;B=x*.5;w=y*2.0*+T(+B);A=+S(+F);N=+Q(+((A*+S(+a)+1.0)*.5));if(+P(+N)<1.0e-5){M=3;i=g;return M|0}else{O=+T(+a)*A*x*+Q(+((y*+S(+B)+1.0)*.5))/(w==0.0?1.0:w)*2.0/N;R=z*+T(+F)/N-v*z/C;break a}break};case 3:case 32:case 33:case 31:{if(!(L<=0.0)){C=+T(+G);z=+S(+G);v=+S(+(I-J));N=K*C+E*z*v;O=H/N;R=(K*z-E*C*v)/N;break a}else{M=1;i=g;return M|0}break};case 16:{N=+U(+G);v=1.0/N;C=N*-2.0;z=N*N;w=N/3.0;N=C*C;B=(J-I)*+T(+G);y=F-G;x=v*(y*(C*.5+y*(z*.5+N*-.125+y*(w*.5+(z*C*-.25+C*N*.0625)+y*(z*.1875*N+(z*z*-.125-C*.25*w)-N*N*.0390625))))+1.0);N=B*B;if((c[d+3300>>2]|0)==0){W=n/+P(+n)}else{w=+h[d+56>>3];W=w/+P(+w)}O=(1.0-N/6.0)*B*x*W;R=v-(1.0-N*.5)*x;break};case 27:{if(G==0.0){M=1;i=g;return M|0}else{O=H;R=(+S(+G)-E*+S(+(I-J)))/+T(+G);break a}break};case 12:{x=o*q+n*r;N=x==0.0?1.0:x;x=(k*.5+45.0)*3.141592653589793/180.0;v=+_(+(+U(+x)));B=N*3.141592653589793/180.0/(+_(+(+U(+(N*.5*.01745329252+x))))-v);x=+S(+(k*3.141592653589793/180.0));N=+U(+(F*.5+.7853981633974487));if(N<1.0e-5){M=2;i=g;return M|0}else{O=(I-J)*(!(x<=0.0)?x:1.0);R=B*+_(+N)-v*B;break a}break};case 6:{B=+T(+G);v=+S(+G);N=+S(+(I-J));x=K*B+E*v*N;w=x<-1.0?-1.0:x;x=+V(+(w>1.0?1.0:w));if(x!=0.0){X=x/+T(+x)}else{X=1.0}O=H*X;R=(K*v-E*B*N)*X;break};case 20:case 28:{if(+P(+F)>1.5707963267948974){M=1;i=g;return M|0}if(+P(+G)>1.5707963267948974){M=1;i=g;return M|0}else{O=E*(I-J);R=F-G;break a}break};case 11:{O=I-J;R=F-G;break};case 4:{if(L<0.0){M=1;i=g;return M|0}else{O=H;R=K*+S(+G)-E*+T(+G)*+S(+(I-J));break a}break};case 5:{if(+P(+F)>1.5707963267948974){M=1;i=g;return M|0}N=+T(+G);B=+S(+G);v=+S(+(I-J));x=K*N+1.0+E*B*v;if(+P(+x)<1.0e-5){M=1;i=g;return M|0}else{w=2.0/x;O=H*w;R=(K*B-E*N*v)*w;break a}break};default:{O=H;R=0.0}}}while(0);if(t){Y=O*180.0/3.141592653589793;Z=R*180.0/3.141592653589793}else{Y=D-j;Z=b-k}t=(c[d+3304>>2]|0)==0;k=t?Z:Y;b=t?Y:Z;if((c[d+3300>>2]|0)==0){if(p!=0.0){$=q*b+r*k;aa=q*k-r*b}else{$=b;aa=k}if(n!=0.0){ba=$/n}else{ba=$}if(o!=0.0){ca=ba;da=aa/o}else{ca=ba;da=aa}}else{ca=b*+h[d+88>>3]+k*+h[d+96>>3];da=b*+h[d+104>>3]+k*+h[d+112>>3]}k=l+ca;h[e>>3]=k;do{if((s|0)==11){ca=+h[d+136>>3];if(k>ca){l=k-360.0/n;if(!(l>0.0)){break}h[e>>3]=l;break}if(k<0.0?(l=k+360.0/n,l<=ca):0){h[e>>3]=l}}}while(0);h[f>>3]=m+da;M=0;i=g;return M|0}function bd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0;g=i;j=c[d+3268>>2]|0;k=c[d+3272>>2]|0;l=a- +h[d+616>>3];a=b- +h[d+624>>3];b=l*l;m=a*a;n=l*b;o=a*m;p=b+m;q=+h[d+256>>3]+l*+h[d+264>>3]+a*+h[d+272>>3]+b*+h[d+280>>3]+m*+h[d+288>>3]+a*l*+h[d+296>>3];if((j|0)>6){r=q+n*+h[d+304>>3]+o*+h[d+312>>3];if((j|0)>8){s=p*+h[d+336>>3]+(r+a*b*+h[d+320>>3]+m*l*+h[d+328>>3])+p*l*+h[d+344>>3]+p*a*+h[d+352>>3]}else{s=r}}else{s=q}q=+h[d+416>>3]+l*+h[d+424>>3]+a*+h[d+432>>3]+b*+h[d+440>>3]+m*+h[d+448>>3]+a*l*+h[d+456>>3];if((k|0)>6){r=q+n*+h[d+464>>3]+o*+h[d+472>>3];if((k|0)>8){t=p*+h[d+496>>3]+(r+a*b*+h[d+480>>3]+l*m*+h[d+488>>3])+p*l*+h[d+504>>3]+p*a*+h[d+512>>3]}else{t=r}}else{t=q}q=t*3.141592653589793/180.0;t=+h[d+696>>3]*3.141592653589793/180.0;r=+U(+t);a=1.0-q*r;p=+Y(+(s*3.141592653589793/180.0/+S(+t)),+a);t=+h[d+688>>3]*3.141592653589793/180.0+p;if(!(t<0.0)){u=t;v=u*180.0;w=v/3.141592653589793;h[e>>3]=w;x=+S(+p);y=q+r;z=a/y;A=x/z;B=+X(+A);C=B*180.0;D=C/3.141592653589793;h[f>>3]=D;i=g;return 0}u=t+6.28318530717959;v=u*180.0;w=v/3.141592653589793;h[e>>3]=w;x=+S(+p);y=q+r;z=a/y;A=x/z;B=+X(+A);C=B*180.0;D=C/3.141592653589793;h[f>>3]=D;i=g;return 0}function cd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0,M=0,N=0,O=0,Q=0,R=0,T=0,V=0,W=0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0,va=0.0,wa=0.0,xa=0,ya=0.0,za=0.0,Aa=0.0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0;g=i;j=c[d+3268>>2]|0;k=c[d+3272>>2]|0;l=+U(+(b*3.141592653589793/180.0));b=+h[d+696>>3]*3.141592653589793/180.0;m=+U(+b);n=a*3.141592653589793/180.0- +h[d+688>>3]*3.141592653589793/180.0;a=+S(+n);o=(1.0-m*a/l)/(m+a/l);l=+S(+b)*+U(+n)*(1.0-m*o)*180.0/3.141592653589793;m=o*180.0/3.141592653589793;o=l*+h[d+88>>3]+m*+h[d+96>>3];n=l*+h[d+104>>3]+m*+h[d+112>>3];b=+h[d+256>>3];a=+h[d+264>>3];p=+h[d+272>>3];q=+h[d+280>>3];r=+h[d+288>>3];s=+h[d+296>>3];t=q*2.0;u=r*2.0;v=d+304|0;w=d+312|0;x=(j|0)>8;y=d+320|0;z=d+328|0;A=d+336|0;B=d+344|0;C=d+352|0;D=+h[d+416>>3];E=+h[d+424>>3];F=+h[d+432>>3];G=+h[d+440>>3];H=+h[d+448>>3];I=+h[d+456>>3];J=G*2.0;K=H*2.0;L=(k|0)>6;M=d+464|0;N=d+472|0;O=(k|0)>8;k=d+480|0;Q=d+488|0;R=d+496|0;T=d+504|0;V=d+512|0;a:do{if((j|0)>6){W=0;X=o;Y=n;while(1){Z=Y*X;_=X*X;$=Y*Y;aa=X*_;ba=Y*$;ca=Y*_;da=$*X;ea=$+_;fa=+h[v>>3];ga=+h[w>>3];ha=b+X*a+Y*p+_*q+$*r+Z*s+aa*fa+ba*ga;ia=a+X*t+Y*s+_*fa*3.0;fa=X*s+(p+Y*u)+$*ga*3.0;if(x){ga=+h[y>>3];ja=+h[z>>3];ka=+h[A>>3];la=+h[B>>3];ma=+h[C>>3];na=ka*2.0;oa=ha+ca*ga+da*ja+ea*ka+ea*X*la+ea*Y*ma;pa=($+_*3.0)*la+($*ja+(ia+Z*ga*2.0)+X*na)+Z*ma*2.0;qa=($*3.0+_)*ma+(fa+_*ga+Z*ja*2.0+Y*na+Z*la*2.0)}else{oa=ha;pa=ia;qa=fa}fa=D+X*E+Y*F+_*G+$*H+Z*I;ia=E+X*J+Y*I;ha=X*I+(F+Y*K);if(L){la=+h[M>>3];na=+h[N>>3];ja=fa+aa*la+ba*na;ba=ia+_*la*3.0;la=ha+$*na*3.0;if(O){na=+h[k>>3];aa=+h[Q>>3];ga=+h[R>>3];ma=+h[T>>3];ka=+h[V>>3];ra=ga*2.0;sa=ja+ca*na+da*aa+ea*ga+ea*X*ma+ea*Y*ka;ta=($+_*3.0)*ma+($*aa+(ba+Z*na*2.0)+X*ra)+Z*ka*2.0;ua=($*3.0+_)*ka+(la+_*na+Z*aa*2.0+Y*ra+Z*ma*2.0)}else{sa=ja;ta=ba;ua=la}}else{sa=fa;ta=ia;ua=ha}ha=oa-l;ia=sa-m;fa=pa*ua-qa*ta;la=(qa*ia-ha*ua)/fa;ba=(ha*ta-pa*ia)/fa;fa=X+la;ia=Y+ba;if(+P(+la)<5.0e-7?+P(+ba)<5.0e-7:0){va=fa;wa=ia;break a}xa=W+1|0;if((xa|0)<50){W=xa;X=fa;Y=ia}else{va=fa;wa=ia;break}}}else{W=0;Y=o;X=n;while(1){ia=X*Y;fa=Y*Y;ba=X*X;la=X*fa;ha=ba*Y;ja=ba+fa;ma=b+Y*a+X*p+fa*q+ba*r+ia*s;Z=a+Y*t+X*s;ra=Y*s+(p+X*u);aa=D+Y*E+X*F+fa*G+ba*H+ia*I;na=E+Y*J+X*I;_=Y*I+(F+X*K);if(L){ka=+h[M>>3];$=+h[N>>3];ea=aa+Y*fa*ka+X*ba*$;ga=na+fa*ka*3.0;ka=_+ba*$*3.0;if(O){$=+h[k>>3];da=+h[Q>>3];ca=+h[R>>3];ya=+h[T>>3];za=+h[V>>3];Aa=ca*2.0;Ba=ea+la*$+ha*da+ja*ca+ja*Y*ya+ja*X*za;Ca=(ba+fa*3.0)*ya+(ba*da+(ga+ia*$*2.0)+Y*Aa)+ia*za*2.0;Da=(ba*3.0+fa)*za+(ka+fa*$+ia*da*2.0+X*Aa+ia*ya*2.0)}else{Ba=ea;Ca=ga;Da=ka}}else{Ba=aa;Ca=na;Da=_}_=ma-l;ma=Ba-m;na=Z*Da-ra*Ca;aa=(ra*ma-_*Da)/na;ra=(_*Ca-Z*ma)/na;na=Y+aa;ma=X+ra;if(+P(+aa)<5.0e-7?+P(+ra)<5.0e-7:0){va=na;wa=ma;break a}xa=W+1|0;if((xa|0)<50){W=xa;Y=na;X=ma}else{va=na;wa=ma;break}}}}while(0);h[e>>3]=va+ +h[d+616>>3];va=wa+ +h[d+624>>3];h[f>>3]=va;wa=+h[e>>3];if(wa<.5){Ea=-1;i=g;return Ea|0}if(wa>+h[d+136>>3]+.5|va<.5){Ea=-1;i=g;return Ea|0}if(va>+h[d+144>>3]+.5){Ea=-1;i=g;return Ea|0}Ea=0;i=g;return Ea|0}function dd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0;d=i;e=gg(2e3)|0;f=gg(2e3)|0;Nc(a,10344,2e3,e)|0;Nc(a,10352,2e3,f)|0;a=gg(2e3)|0;g=gg(2e3)|0;j=b+3176|0;if((+h[j>>3]>360.0?(Xc(e,10360,j)|0)==0:0)?(Xc(f,10360,j)|0)==0:0){h[j>>3]=180.0}j=b+3192|0;if((Xc(e,10376,j)|0)==0?(Xc(f,10376,j)|0)==0:0){h[j>>3]=57.29577951308232}do{if((Zc(e,10384,2e3,a)|0)==0){if((Zc(f,10384,2e3,a)|0)==0){c[b+5960>>2]=0;break}else{c[b+5960>>2]=gd(a)|0;break}}else{c[b+5960>>2]=gd(a)|0}}while(0);do{if((Zc(f,10392,2e3,g)|0)==0){if((Zc(e,10392,2e3,g)|0)==0){c[b+5964>>2]=0;break}else{c[b+5964>>2]=gd(g)|0;break}}else{c[b+5964>>2]=gd(g)|0}}while(0);ac(b);hg(e);hg(f);hg(a);hg(g);if((c[b+5964>>2]|0)==0?(c[b+5960>>2]|0)==0:0){k=1;i=d;return k|0}k=0;i=d;return k|0}function ed(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0;g=i;j=a- +h[d+616>>3];a=b- +h[d+624>>3];if((c[d+3300>>2]|0)==0){b=+h[d+760>>3];if(b==0.0){k=2;l=0.0;m=0.0;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}n=+h[d+768>>3];if(n==0.0){k=2;l=0.0;m=0.0;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}o=j*b;b=a*n;n=+h[d+48>>3];if(n!=0.0){p=n*3.141592653589793/180.0;n=+S(+p);q=+T(+p);r=o*n-b*q;s=b*n+o*q}else{r=o;s=b}}else{r=j*+h[d+56>>3]+a*+h[d+64>>3];s=j*+h[d+72>>3]+a*+h[d+80>>3]}t=(c[d+3304>>2]|0)==0|0;a=(90.0- +h[d+(t<<3)+688>>3])*3.141592653589793/180.0;j=+S(+a);b=+T(+a);o=+h[d+3176>>3]*3.141592653589793/180.0;u=c[d+5960>>2]|0;if((u|0)==0){v=r}else{v=r+ +hd(u,r,s)}u=c[d+5964>>2]|0;if((u|0)==0){w=s}else{w=s+ +hd(u,r,s)}s=+Q(+(v*v+w*w));if(s==0.0){x=0.0}else{x=+Y(+v,+-w)}w=+Y(+(+h[d+3192>>3]),+s);s=+S(+w);v=+T(+w);r=x-o;o=+S(+r);x=+T(+r);q=j*s;n=b*v-q*o;if(+P(+n)<1.0e-5){y=q*(1.0-o)- +S(+(a+w))}else{y=n}n=s*x;if(y!=0.0|n!=-0.0){z=+Y(+-n,+y)}else{z=r+3.141592653589793}x=+h[d+((t^1)<<3)+688>>3];q=x+z*180.0/3.141592653589793;if(!(x>=0.0)){if(q>0.0){A=q+-360.0}else{A=q}}else{if(q<0.0){A=q+360.0}else{A=q}}if(!(A>360.0)){if(A<-360.0){B=A+360.0}else{B=A}}else{B=A+-360.0}if(+qa(+r,3.141592653589793)==0.0){r=(w+a*o)*180.0/3.141592653589793;if(r>90.0){C=180.0-r}else{C=r}if(!(C<-90.0)){k=0;l=C;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}k=0;l=-180.0-C;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}C=j*v+b*s*o;if(!(+P(+C)>.99)){k=0;l=+W(+C)*180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}o=+V(+(+Q(+(n*n+y*y))));if(!(C>=0.0)){k=0;l=o*-180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}else{k=0;l=o*180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}return 0}function fd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0,D=0,E=0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0,U=0.0,X=0.0,Z=0.0,_=0,$=0.0,aa=0.0,ba=0.0;g=i;j=d+3304|0;k=(c[j>>2]|0)==0|0;l=(a- +h[d+((k^1)<<3)+688>>3])*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+l);m=+T(+l);n=+S(+a);o=+T(+a);p=(90.0- +h[d+(k<<3)+688>>3])*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=+h[d+3176>>3];if(s==999.0){t=3.141592653589793}else{t=s*3.141592653589793/180.0}s=n*q;u=o*r-b*s;if(+P(+u)<1.0e-5){v=(1.0-b)*s- +S(+(a+p))}else{v=u}u=m*n;if(v!=0.0|u!=-0.0){w=+Y(+-u,+v)}else{w=l+-3.141592653589793}m=t+w;if(!(m>3.141592653589793)){if(m<-3.141592653589793){x=m+6.283185307179586}else{x=m}}else{x=m+-6.283185307179586}do{if(+qa(+l,3.141592653589793)==0.0){m=a+b*p;if(m>1.5707963267948966){y=3.141592653589793-m}else{y=m}if(y<-1.5707963267948966){z=-3.141592653589793-y}else{z=y}}else{m=o*q+b*n*r;if(!(+P(+m)>.99)){z=+W(+m);break}w=+V(+(+Q(+(u*u+v*v))));if(!(m>=0.0)){z=-w}else{z=w}}}while(0);v=+T(+z);do{if(v==0.0){A=0.0;B=0.0}else{u=+h[d+3192>>3]*+S(+z)/v;k=d+5960|0;C=c[k>>2]|0;D=d+5964|0;if((C|0)==0?(c[D>>2]|0)==0:0){E=(c[j>>2]|0)==0;r=u*+T(+x);n=-(u*+S(+x));A=E?r:n;B=E?n:r;break}r=u*+T(+x);n=u*+S(+x);E=C;C=1;u=r;b=-n;while(1){if((E|0)==0){F=u;G=1.0;H=0.0}else{q=u+ +hd(E,u,b);o=+id(c[k>>2]|0,u,b,1,0)+1.0;F=q;G=o;H=+id(c[k>>2]|0,u,b,0,1)}o=F-r;I=c[D>>2]|0;if((I|0)==0){J=b;K=0.0;L=1.0}else{q=b+ +hd(I,u,b);y=+id(c[D>>2]|0,u,b,1,0);J=q;K=y;L=+id(c[D>>2]|0,u,b,0,1)+1.0}y=n+J;q=G*L-H*K;if(q==0.0){M=u;N=b;break}p=(H*y-o*L)/q;a=(o*K-G*y)/q;q=u+p;l=b+a;I=+P(+p)>+P(+a);w=I?p:a;a=+P(+w);I=+P(+o)>+P(+y);p=I?o:y;I=a>+P(+p);if(!(!(+P(+(I?w:p))<2.8e-8)&(C|0)<500)){M=q;N=l;break}E=c[k>>2]|0;C=C+1|0;u=q;b=l}C=(c[j>>2]|0)==0;A=C?M:N;B=C?N:M}}while(0);if((c[d+3300>>2]|0)!=0){h[e>>3]=A*+h[d+88>>3]+B*+h[d+96>>3];h[f>>3]=A*+h[d+104>>3]+B*+h[d+112>>3];O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}M=+h[d+48>>3];if(M!=0.0){N=M*3.141592653589793/180.0;M=+S(+N);G=+T(+N);h[e>>3]=A*M+B*G;ba=B*M-A*G}else{h[e>>3]=A;ba=B}h[f>>3]=ba;ba=+h[d+32>>3];if(ba!=0.0){h[e>>3]=+h[e>>3]/ba}ba=+h[d+40>>3];if(!(ba!=0.0)){O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}h[f>>3]=+h[f>>3]/ba;O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}function gd(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=i;i=i+16|0;e=d;if((a[b+1|0]|0)==0){f=0;i=d;return f|0}g=gg(160)|0;c[e>>2]=b;j=b;k=b;b=g;g=0;l=20;a:while(1){if((a[k]|0)==0){break}m=+wg(j,e);n=c[e>>2]|0;o=a[n]|0;if(o<<24>>24==46){p=n+1|0;c[e>>2]=p;q=a[p]|0;r=p}else{q=o;r=n}if(q<<24>>24==0){break}n=g+1|0;if((n|0)<(l|0)){s=r;t=b;u=l}else{o=l+20|0;p=jg(b,o<<3)|0;s=c[e>>2]|0;t=p;u=o}h[t+(g<<3)>>3]=m;o=s;while(1){if((a[o]|0)==32){o=o+1|0}else{j=o;k=s;b=t;g=n;l=u;continue a}}}u=jd(b)|0;hg(b);f=(g|0)==0?0:u;i=d;return f|0}function hd(a,b,d){a=a|0;b=+b;d=+d;var e=0,f=0,g=0,j=0.0,k=0.0,l=0,m=0.0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0,F=0,G=0,H=0,I=0,J=0.0,K=0,L=0.0,M=0,N=0.0,O=0;e=i;f=c[a+32>>2]|0;if((f|0)==1){g=c[a+36>>2]|0;j=+h[a+8>>3];k=+h[a>>3];l=c[a+56>>2]|0;h[l>>3]=1.0;if(((g|0)!=1?(m=(j+b)*k,h[l+8>>3]=m,(g|0)>2):0)?(k=m*2.0,j=k*m+-1.0,h[l+16>>3]=j,(g|0)!=3):0){m=j;n=3;p=2;while(1){m=k*m- +h[l+(p+ -1<<3)>>3];h[l+(n<<3)>>3]=m;q=n+1|0;if((q|0)==(g|0)){break}else{r=n;n=q;p=r}}}p=c[a+40>>2]|0;m=+h[a+24>>3];k=+h[a+16>>3];n=c[a+60>>2]|0;h[n>>3]=1.0;if((p|0)!=1){j=(m+d)*k;h[n+8>>3]=j;if((p|0)>2){k=j*2.0;m=k*j+-1.0;h[n+16>>3]=m;if((p|0)==3){s=l;t=n;u=3;v=g;w=25}else{j=m;r=3;q=2;while(1){m=k*j- +h[n+(q+ -1<<3)>>3];h[n+(r<<3)>>3]=m;x=r+1|0;if((x|0)==(p|0)){y=g;z=p;A=l;B=n;w=26;break}else{C=r;j=m;r=x;q=C}}}}else{y=g;z=p;A=l;B=n;w=26}}else{s=l;t=n;u=1;v=g;w=25}}else if((f|0)==3){g=c[a+36>>2]|0;n=c[a+56>>2]|0;h[n>>3]=1.0;if((g|0)!=1?(h[n+8>>3]=b,(g|0)>2):0){j=b;l=2;do{j=j*b;h[n+(l<<3)>>3]=j;l=l+1|0}while((l|0)!=(g|0))}l=c[a+40>>2]|0;p=c[a+60>>2]|0;h[p>>3]=1.0;if((l|0)!=1){h[p+8>>3]=d;if((l|0)>2){j=d;q=2;while(1){k=j*d;h[p+(q<<3)>>3]=k;r=q+1|0;if((r|0)==(l|0)){y=g;z=l;A=n;B=p;w=26;break}else{j=k;q=r}}}else{y=g;z=l;A=n;B=p;w=26}}else{s=n;t=p;u=1;v=g;w=25}}else if((f|0)==2){f=c[a+36>>2]|0;j=+h[a+8>>3];k=+h[a>>3];g=c[a+56>>2]|0;h[g>>3]=1.0;if(((f|0)!=1?(m=(j+b)*k,h[g+8>>3]=m,(f|0)>2):0)?(k=(m*m*3.0+-1.0)*.5,h[g+16>>3]=k,(f|0)!=3):0){p=3;b=k;n=2;while(1){k=+(p|0);b=(b*m*(k*2.0+-1.0)- +h[g+(n+ -1<<3)>>3]*(k+-1.0))/k;h[g+(p<<3)>>3]=b;l=p+1|0;if((l|0)==(f|0)){break}else{q=p;p=l;n=q}}}n=c[a+40>>2]|0;b=+h[a+24>>3];m=+h[a+16>>3];p=c[a+60>>2]|0;h[p>>3]=1.0;if((n|0)!=1){k=(b+d)*m;h[p+8>>3]=k;if((n|0)>2){m=(k*k*3.0+-1.0)*.5;h[p+16>>3]=m;if((n|0)==3){s=g;t=p;u=3;v=f;w=25}else{q=3;d=m;l=2;while(1){m=+(q|0);b=(d*k*(m*2.0+-1.0)- +h[p+(l+ -1<<3)>>3]*(m+-1.0))/m;h[p+(q<<3)>>3]=b;r=q+1|0;if((r|0)==(n|0)){y=f;z=n;A=g;B=p;w=26;break}else{C=q;q=r;d=b;l=C}}}}else{y=f;z=n;A=g;B=p;w=26}}else{s=g;t=p;u=1;v=f;w=25}}else{ab(10400,33,1,c[o>>2]|0)|0;D=0.0;i=e;return+D}if((w|0)==25){E=(v|0)>(u|0)?v:u;F=t;G=u;H=s;I=v}else if((w|0)==26){if((z|0)>0){E=(y|0)>(z|0)?y:z;F=B;G=z;H=A;I=y}else{D=0.0;i=e;return+D}}y=c[a+44>>2]|0;A=a+52|0;if((y|0)==2){a=0;z=0;d=0.0;B=I;while(1){if((B|0)>0){w=c[A>>2]|0;k=0.0;v=z;s=0;while(1){k=k+ +h[w+(v<<3)>>3]*+h[H+(s<<3)>>3];s=s+1|0;if((s|0)==(B|0)){break}else{v=v+1|0}}J=k;K=B+z|0}else{J=0.0;K=z}b=d+J*+h[F+(a<<3)>>3];v=(((a+1+I|0)>(E|0))<<31>>31)+B|0;s=a+1|0;if((s|0)<(G|0)){a=s;z=K;d=b;B=v}else{D=b;break}}i=e;return+D}else if((y|0)==0){y=0;B=0;d=0.0;K=I;while(1){if((K|0)>0){z=c[A>>2]|0;J=0.0;a=B;E=0;while(1){J=J+ +h[z+(a<<3)>>3]*+h[H+(E<<3)>>3];E=E+1|0;if((E|0)==(K|0)){break}else{a=a+1|0}}L=J;M=K+B|0}else{L=0.0;M=B}k=d+L*+h[F+(y<<3)>>3];a=y+1|0;if((a|0)<(G|0)){y=a;B=M;d=k;K=1}else{D=k;break}}i=e;return+D}else{K=0;M=0;d=0.0;while(1){if((I|0)>0){B=c[A>>2]|0;L=0.0;y=M;a=0;while(1){L=L+ +h[B+(y<<3)>>3]*+h[H+(a<<3)>>3];a=a+1|0;if((a|0)==(I|0)){break}else{y=y+1|0}}N=L;O=I+M|0}else{N=0.0;O=M}J=d+N*+h[F+(K<<3)>>3];y=K+1|0;if((y|0)<(G|0)){K=y;M=O;d=J}else{D=J;break}}i=e;return+D}return 0.0}function id(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0.0,O=0,P=0,Q=0,S=0,T=0.0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0.0,$=0.0,ba=0.0,ca=0.0,da=0,ea=0.0,fa=0.0;g=i;i=i+16|0;j=g;if((a|0)==0){k=0.0;i=g;return+k}l=f|e;if((l|0)<0){ab(10440,46,1,c[o>>2]|0)|0;k=0.0;i=g;return+k}if((l|0)==0){k=+hd(a,b,d);i=g;return+k}l=gg(64)|0;m=a+36|0;n=c[m>>2]|0;p=n+ -1|0;q=(p|0)>(e|0)?e:p;p=a+40|0;e=c[p>>2]|0;r=e+ -1|0;s=(r|0)>(f|0)?f:r;r=c[a+32>>2]|0;t=l+32|0;c[t>>2]=r;if(!((r+ -1|0)>>>0<3)){u=c[o>>2]|0;c[j>>2]=r;za(u|0,10488,j|0)|0;k=0.0;i=g;return+k}j=c[a+44>>2]|0;u=l+44|0;c[u>>2]=j;do{if((j|0)==2){r=((n|0)>(e|0)?n:e)-s-q|0;v=n-q|0;w=(r|0)<(v|0)?r:v;v=(w|0)<1?1:w;w=l+36|0;c[w>>2]=v;x=e-s|0;y=(r|0)<(x|0)?r:x;x=(y|0)<1?1:y;y=l+40|0;c[y>>2]=x;r=(v|0)<(x|0)?v:x;z=(aa(x,v)|0)-((aa(r+ -1|0,r)|0)/2|0)|0;r=l+48|0;c[r>>2]=z;A=r;B=w;C=y;D=z;E=v;F=x}else if((j|0)==0){x=(q|0)>0;v=(s|0)>0;if(x&v){z=l+36|0;c[z>>2]=1;y=l+40|0;c[y>>2]=1;w=l+48|0;c[w>>2]=1;A=w;B=z;C=y;D=1;E=1;F=1;break}if(x){x=n-q|0;y=(x|0)<1?1:x;x=l+36|0;c[x>>2]=y;z=l+40|0;c[z>>2]=1;w=l+48|0;c[w>>2]=y;A=w;B=x;C=z;D=y;E=y;F=1;break}if(v){v=l+36|0;c[v>>2]=1;y=e-s|0;z=(y|0)<1?1:y;y=l+40|0;c[y>>2]=z;x=l+48|0;c[x>>2]=z;A=x;B=v;C=y;D=z;E=1;F=z;break}else{A=l+48|0;B=l+36|0;C=l+40|0;D=0;E=0;F=0;break}}else{z=n-q|0;y=(z|0)<1?1:z;z=l+36|0;c[z>>2]=y;v=e-s|0;x=(v|0)<1?1:v;v=l+40|0;c[v>>2]=x;w=aa(x,y)|0;r=l+48|0;c[r>>2]=w;A=r;B=z;C=v;D=w;E=y;F=x}}while(0);h[l>>3]=+h[a>>3];h[l+8>>3]=+h[a+8>>3];n=l+16|0;h[n>>3]=+h[a+16>>3];h[l+24>>3]=+h[a+24>>3];j=l+52|0;c[j>>2]=gg(D<<3)|0;D=l+56|0;c[D>>2]=gg(E<<3)|0;E=l+60|0;c[E>>2]=gg(F<<3)|0;F=a+48|0;x=c[F>>2]|0;y=x<<3;w=c[2632]|0;if((y|0)>(w|0)){if((w|0)>0){G=jg(c[2634]|0,y)|0}else{G=gg(y)|0}c[2634]=G;c[2632]=y;H=G;I=c[F>>2]|0}else{H=c[2634]|0;I=x}if((I|0)>0){x=c[a+52>>2]|0;a=0;do{h[H+(a<<3)>>3]=+h[x+(a<<3)>>3];a=a+1|0}while((a|0)!=(I|0))}a=c[u>>2]|0;a:do{if((a|0)==1){u=c[p>>2]|0;x=u+ -1|0;if((u|0)>(s|0)){u=c[m>>2]|0;F=c[B>>2]|0;G=aa(x,u)|0;y=aa((c[C>>2]|0)+ -1|0,F)|0;w=1-s|0;v=q+1|0;z=(u|0)<(v|0);r=(F|0)>0;J=0-u|0;K=1-q|0;L=x;x=H+(G<<3)|0;G=(c[j>>2]|0)+(y<<3)|0;while(1){y=w+L|0;if((L|0)>=(y|0)){M=L;while(1){if(r){N=+(M|0);O=0;do{P=x+(O+q<<3)|0;h[P>>3]=N*+h[P>>3];O=O+1|0}while((O|0)<(F|0))}if((M|0)>(y|0)){M=M+ -1|0}else{break}}}if(!z){M=u;while(1){y=K+M|0;O=M+ -1|0;if((M|0)>=(y|0)){P=x+(O<<3)|0;N=+h[P>>3];Q=M;while(1){S=Q+ -1|0;T=+(S|0)*N;if((Q|0)>(y|0)){N=T;Q=S}else{break}}h[P>>3]=T}if((M|0)>(v|0)){M=O}else{break}}}if(r){M=0;do{h[G+(M<<3)>>3]=+h[x+(M+q<<3)>>3];M=M+1|0}while((M|0)<(F|0))}if((L|0)>(s|0)){L=L+ -1|0;x=x+(J<<3)|0;G=G+(0-F<<3)|0}else{break}}}}else if((a|0)==2){F=c[m>>2]|0;G=c[p>>2]|0;J=((F|0)>(G|0)?F:G)+1|0;x=c[B>>2]|0;L=c[C>>2]|0;r=s+1|0;if((G|0)>=(r|0)){v=r+((x|0)>(L|0)?x:L)|0;L=1-s|0;K=q+1|0;u=1-q|0;z=G;G=H+(I<<3)|0;w=(c[j>>2]|0)+(c[A>>2]<<3)|0;while(1){M=J-z|0;Q=(M|0)<(F|0)?M:F;M=(Q|0)<0?0:Q;Q=v-z|0;y=(Q|0)<(x|0)?Q:x;Q=(y|0)<0?0:y;y=G+(0-M<<3)|0;S=w+(0-Q<<3)|0;U=L+z|0;if((z|0)>(U|0)){V=(Q|0)>0;W=q-M|0;X=z;do{X=X+ -1|0;if(V){N=+(X|0);Y=0;do{Z=G+(W+Y<<3)|0;h[Z>>3]=N*+h[Z>>3];Y=Y+1|0}while((Y|0)<(Q|0))}}while((X|0)>(U|0))}if((M|0)>=(K|0)){U=M;while(1){X=u+U|0;W=U+ -1|0;if((U|0)>=(X|0)){V=G+(W-M<<3)|0;N=+h[V>>3];Y=U;while(1){O=Y+ -1|0;_=+(O|0)*N;if((Y|0)>(X|0)){N=_;Y=O}else{break}}h[V>>3]=_}if((U|0)>(K|0)){U=W}else{break}}}if((Q|0)>0){U=q-M|0;Y=0;do{h[w+(Y-Q<<3)>>3]=+h[G+(U+Y<<3)>>3];Y=Y+1|0}while((Y|0)<(Q|0))}if((z|0)>(r|0)){z=z+ -1|0;G=y;w=S}else{break}}}}else{w=(q|0)>0;G=(s|0)>0;if(w&G){h[c[j>>2]>>3]=0.0;break}if(w){w=c[m>>2]|0;z=q+1|0;if((w|0)<(z|0)){break}r=1-q|0;K=w;w=(c[j>>2]|0)+((c[A>>2]|0)+ -1<<3)|0;while(1){u=r+K|0;L=K+ -1|0;x=H+(L<<3)|0;N=+h[x>>3];if((K|0)<(u|0)){$=N}else{ba=N;v=K;while(1){F=v+ -1|0;ca=ba*+(F|0);if((v|0)>(u|0)){ba=ca;v=F}else{break}}h[x>>3]=ca;$=ca}h[w>>3]=$;if((K|0)>(z|0)){K=L;w=w+ -8|0}else{break a}}}if(G){w=H+(I+ -1<<3)|0;K=c[j>>2]|0;z=c[p>>2]|0;r=s+1|0;if((z|0)<(r|0)){da=w}else{v=1-s|0;u=0-e|0;S=~f;y=((u|0)>(S|0)?u:S)+ -1|0;S=~z;u=I+ -3-(z+((y|0)>(S|0)?y:S))|0;S=z;z=w;while(1){w=v+S|0;if((S|0)>=(w|0)){ba=+h[z>>3];y=S;while(1){F=y+ -1|0;ea=+(F|0)*ba;if((y|0)>(w|0)){ba=ea;y=F}else{break}}h[z>>3]=ea}if((S|0)>(r|0)){S=S+ -1|0;z=z+ -8|0}else{break}}da=H+(u<<3)|0}z=c[A>>2]|0;if((z|0)>0){S=0;while(1){r=S+1|0;h[K+(S<<3)>>3]=+h[da+(r<<3)>>3];if((r|0)<(z|0)){S=r}else{break}}}}}}while(0);ea=+hd(l,b,d);if((c[t>>2]|0)==3){if((l|0)==0){k=ea;i=g;return+k}else{fa=ea}}else{d=+R(+(+h[l>>3]),+(+(q|0)));fa=ea*d*+R(+(+h[n>>3]),+(+(s|0)))}s=c[D>>2]|0;if((s|0)!=0){hg(s)}s=c[E>>2]|0;if((s|0)!=0){hg(s)}s=c[j>>2]|0;if((s|0)!=0){hg(s)}hg(l);k=fa;i=g;return+k}function jd(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,l=0.0,m=0.0,n=0,p=0.0,q=0.0,r=0,s=0,t=0;b=i;i=i+16|0;d=b;e=~~(+h[a+8>>3]+.5);if((e|0)<1){f=c[o>>2]|0;c[d>>2]=e;za(f|0,10544,d|0)|0;g=0;i=b;return g|0}f=~~(+h[a+16>>3]+.5);if((f|0)<1){j=c[o>>2]|0;c[d>>2]=f;za(j|0,10584,d|0)|0;g=0;i=b;return g|0}l=+h[a+32>>3];m=+h[a+40>>3];if(m<=l){j=c[o>>2]|0;h[k>>3]=l;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];n=d+8|0;h[k>>3]=m;c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];za(j|0,10624,d|0)|0;g=0;i=b;return g|0}p=+h[a+48>>3];q=+h[a+56>>3];if(q<=p){j=c[o>>2]|0;h[k>>3]=p;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];n=d+8|0;h[k>>3]=q;c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];za(j|0,10664,d|0)|0;g=0;i=b;return g|0}j=~~(+h[a>>3]+.5);if(!((j+ -1|0)>>>0<3)){n=c[o>>2]|0;c[d>>2]=j;za(n|0,10704,d|0)|0;g=0;i=b;return g|0}d=gg(64)|0;c[d+36>>2]=e;h[d>>3]=2.0/(m-l);h[d+8>>3]=(l+m)*-.5;c[d+40>>2]=f;h[d+16>>3]=2.0/(q-p);h[d+24>>3]=(p+q)*-.5;n=~~+h[a+24>>3];c[d+44>>2]=n;if((n|0)==1){r=aa(f,e)|0;c[d+48>>2]=r;s=r}else if((n|0)==2){r=(e|0)<(f|0)?e:f;t=(aa(f,e)|0)-((aa(r+ -1|0,r)|0)/2|0)|0;c[d+48>>2]=t;s=t}else if((n|0)==0){n=e+ -1+f|0;c[d+48>>2]=n;s=n}else{s=0}c[d+32>>2]=j;j=gg(s<<3)|0;c[d+52>>2]=j;if((s|0)>0){n=0;do{h[j+(n<<3)>>3]=+h[a+(n+8<<3)>>3];n=n+1|0}while((n|0)<(s|0))}c[d+56>>2]=gg(e<<3)|0;c[d+60>>2]=gg(f<<3)|0;g=d;i=b;return g|0}function kd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0;d=i;i=i+16|0;e=d;f=d+8|0;g=gg(2e3)|0;j=gg(2e3)|0;if((Nc(a,10744,2e3,g)|0)==0){k=gg((Dg(a|0)|0)+200|0)|0;Kg(k|0,10752,161)|0;Fg(k|0,a|0)|0;Nc(k,10744,2e3,g)|0;Nc(k,10920,2e3,j)|0;hg(k)}Nc(a,10920,2e3,j)|0;a=gg(2e3)|0;k=gg(2e3)|0;l=b+3176|0;if((+h[l>>3]>360.0?(Xc(g,10928,l)|0)==0:0)?(Xc(j,10928,l)|0)==0:0){h[l>>3]=180.0}l=b+3192|0;if((Xc(g,10944,l)|0)==0?(Xc(j,10944,l)|0)==0:0){h[l>>3]=57.29577951308232}l=0;do{c[e>>2]=l;Na(f|0,10952,e|0)|0;m=b+(l<<3)+4096|0;if((Xc(g,f,m)|0)==0){h[m>>3]=0.0}l=l+1|0}while((l|0)!=10);do{if((Zc(g,10960,2e3,a)|0)==0){if((Zc(j,10960,2e3,a)|0)==0){c[b+5960>>2]=0;break}else{c[b+5960>>2]=gd(a)|0;break}}else{c[b+5960>>2]=gd(a)|0}}while(0);do{if((Zc(j,10968,2e3,k)|0)==0){if((Zc(g,10968,2e3,k)|0)==0){c[b+5964>>2]=0;n=9;break}else{c[b+5964>>2]=gd(k)|0;n=9;break}}else{c[b+5964>>2]=gd(k)|0;n=9}}while(0);while(1){o=n+ -1|0;if(!(+h[b+(n<<3)+4096>>3]==0.0)){p=27;break}if((n|0)>0){n=o}else{p=25;break}}if((p|0)==25){c[b+3276>>2]=o}else if((p|0)==27?(c[b+3276>>2]=n,(n|0)>2):0){q=+h[b+4104>>3];p=1;r=0.0;while(1){s=+(p|0)*3.141592653589793/180.0;t=0.0;o=n;do{t=s*t+ +(o|0)*+h[b+(o<<3)+4096>>3];o=o+ -1|0}while((o|0)>0);o=p+1|0;if(t<=0.0){u=q;v=r;break}if((o|0)<181){q=t;p=o;r=s}else{u=t;v=s;break}}a:do{if(!(t<=0.0)){w=3.141592653589793}else{r=u;q=t;p=1;x=v;y=s;while(1){z=x-r*(y-x)/(q-r);A=0.0;o=n;do{A=z*A+ +(o|0)*+h[b+(o<<3)+4096>>3];o=o+ -1|0}while((o|0)>0);if(+P(+A)<1.0e-13){w=z;break a}o=A<0.0;l=p+1|0;if((l|0)<11){r=o?r:A;q=o?A:q;p=l;x=o?x:z;y=o?z:y}else{w=z;break}}}}while(0);if((n|0)>-1){p=n;s=0.0;while(1){v=w*s+ +h[b+(p<<3)+4096>>3];if((p|0)>0){p=p+ -1|0;s=v}else{B=v;break}}}else{B=0.0}h[b+3240>>3]=w;h[b+3248>>3]=B}ac(b);hg(g);hg(j);hg(a);hg(k);if((c[b+5964>>2]|0)==0?(c[b+5960>>2]|0)==0:0){C=1;i=d;return C|0}C=0;i=d;return C|0} + + + +function ld(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,U=0.0,X=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0;g=i;j=a- +h[d+616>>3];a=b- +h[d+624>>3];do{if((c[d+3300>>2]|0)==0){b=+h[d+760>>3];if(!(b==0.0)?(k=+h[d+768>>3],!(k==0.0)):0){l=j*b;b=a*k;k=+h[d+48>>3];if(!(k!=0.0)){m=l;n=b;break}o=k*3.141592653589793/180.0;k=+S(+o);p=+T(+o);m=l*k-b*p;n=b*k+l*p;break}h[e>>3]=0.0;h[f>>3]=0.0;q=2;i=g;return q|0}else{m=j*+h[d+56>>3]+a*+h[d+64>>3];n=j*+h[d+72>>3]+a*+h[d+80>>3]}}while(0);r=(c[d+3304>>2]|0)==0|0;s=r^1;a=(90.0- +h[d+(r<<3)+688>>3])*3.141592653589793/180.0;j=+S(+a);p=+T(+a);l=+h[d+3176>>3]*3.141592653589793/180.0;r=c[d+3276>>2]|0;t=c[d+5960>>2]|0;if((t|0)==0){u=m}else{u=m+ +hd(t,m,n)}t=c[d+5964>>2]|0;if((t|0)==0){v=n}else{v=n+ +hd(t,m,n)}n=+Q(+(u*u+v*v));m=n/+h[d+3192>>3];if((r|0)<1){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}a:do{if((r|0)==2){n=+h[d+4112>>3];k=+h[d+4104>>3];b=k*k-n*4.0*(+h[d+4096>>3]-m);if(b<0.0){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}o=+Q(+b);b=n*2.0;n=(o-k)/b;w=(-k-o)/b;b=nw?n:w}else{x=b}if(x<0.0){if(!(x<-1.0e-13)){y=0.0;break}h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if(x>3.141592653589793){if(x>3.141592653589893){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}else{y=3.141592653589793}}else{y=x}}else if((r|0)==1){y=(m- +h[d+4096>>3])/+h[d+4104>>3]}else{b=+h[d+4096>>3];w=+h[d+3240>>3];n=+h[d+3248>>3];if(m>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if(m>n){if(!(m>n+1.0e-13)){y=w;break}h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if((r|0)>-1){z=0;A=b;B=n;C=0.0;D=w}else{o=0.0-m;t=0;k=b;b=n;n=0.0;E=w;while(1){w=(b-m)/(b-k);if(!(w<.1)){if(w>.9){F=.9}else{F=w}}else{F=.1}w=E-(E-n)*F;if(m>0.0){if(m<1.0e-13){y=w;break a}else{G=0.0;H=b;I=w;J=E}}else{if(o<1.0e-13){y=w;break a}else{G=k;H=0.0;I=n;J=w}}K=t+1|0;if(!(+P(+(J-I))<1.0e-13)&(K|0)<100){t=K;k=G;b=H;n=I;E=J}else{y=w;break a}}}while(1){E=(B-m)/(B-A);if(!(E<.1)){if(E>.9){L=.9}else{L=E}}else{L=.1}E=D-(D-C)*L;t=r;n=0.0;while(1){n=E*n+ +h[d+(t<<3)+4096>>3];if((t|0)<=0){break}else{t=t+ -1|0}}if(n>3];R=U+Z*180.0/3.141592653589793;if(!(U>=0.0)){if(R>0.0){_=R+-360.0}else{_=R}}else{if(R<0.0){_=R+360.0}else{_=R}}if(!(_>360.0)){if(_<-360.0){$=_+360.0}else{$=_}}else{$=_+-360.0}do{if(+qa(+m,3.141592653589793)==0.0){_=(v+a*l)*180.0/3.141592653589793;if(_>90.0){aa=180.0-_}else{aa=_}if(aa<-90.0){ba=-180.0-aa}else{ba=aa}}else{_=j*u+p*y*l;if(!(+P(+_)>.99)){ba=+W(+_)*180.0/3.141592653589793;break}R=+V(+(+Q(+(D*D+X*X))));if(!(_>=0.0)){ba=R*-180.0/3.141592653589793;break}else{ba=R*180.0/3.141592653589793;break}}}while(0);h[e>>3]=$;h[f>>3]=ba;q=0;i=g;return q|0}function md(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0,U=0.0,X=0.0,Z=0.0,_=0,$=0.0,aa=0.0,ba=0.0;g=i;j=d+3304|0;k=(c[j>>2]|0)==0|0;l=(a- +h[d+((k^1)<<3)+688>>3])*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+l);m=+T(+l);n=+S(+a);o=+T(+a);p=(90.0- +h[d+(k<<3)+688>>3])*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=+h[d+3176>>3];if(s==999.0){t=3.141592653589793}else{t=s*3.141592653589793/180.0}s=n*q;u=o*r-b*s;if(+P(+u)<1.0e-5){v=(1.0-b)*s- +S(+(a+p))}else{v=u}u=m*n;if(v!=0.0|u!=-0.0){w=+Y(+-u,+v)}else{w=l+-3.141592653589793}m=t+w;if(!(m>3.141592653589793)){if(m<-3.141592653589793){x=m+6.283185307179586}else{x=m}}else{x=m+-6.283185307179586}do{if(+qa(+l,3.141592653589793)==0.0){m=a+b*p;if(m>1.5707963267948966){y=3.141592653589793-m}else{y=m}if(y<-1.5707963267948966){z=-3.141592653589793-y}else{z=y}}else{m=o*q+b*n*r;if(!(+P(+m)>.99)){z=+W(+m);break}w=+V(+(+Q(+(u*u+v*v))));if(!(m>=0.0)){z=-w}else{z=w}}}while(0);v=1.5707963267948966-z;z=(v*(v*(v*(v*(v*(v*(v*(v*(v*(v*0.0+ +h[d+4168>>3])+ +h[d+4160>>3])+ +h[d+4152>>3])+ +h[d+4144>>3])+ +h[d+4136>>3])+ +h[d+4128>>3])+ +h[d+4120>>3])+ +h[d+4112>>3])+ +h[d+4104>>3])+ +h[d+4096>>3])*+h[d+3192>>3];k=d+5960|0;A=c[k>>2]|0;B=d+5964|0;if((A|0)==0?(c[B>>2]|0)==0:0){C=(c[j>>2]|0)==0;v=z*+T(+x);u=-(z*+S(+x));D=C?v:u;E=C?u:v}else{v=z*+T(+x);u=z*+S(+x);C=A;A=1;x=v;z=-u;while(1){if((C|0)==0){F=x;G=1.0;H=0.0}else{r=x+ +hd(C,x,z);n=+id(c[k>>2]|0,x,z,1,0)+1.0;F=r;G=n;H=+id(c[k>>2]|0,x,z,0,1)}n=F-v;I=c[B>>2]|0;if((I|0)==0){J=z;K=0.0;L=1.0}else{r=z+ +hd(I,x,z);b=+id(c[B>>2]|0,x,z,1,0);J=r;K=b;L=+id(c[B>>2]|0,x,z,0,1)+1.0}b=u+J;r=G*L-H*K;if(r==0.0){M=x;N=z;break}q=(H*b-n*L)/r;o=(n*K-G*b)/r;r=x+q;y=z+o;I=+P(+q)>+P(+o);p=I?q:o;o=+P(+p);I=+P(+n)>+P(+b);q=I?n:b;I=o>+P(+q);if(!(!(+P(+(I?p:q))<2.8e-8)&(A|0)<500)){M=r;N=y;break}C=c[k>>2]|0;A=A+1|0;x=r;z=y}A=(c[j>>2]|0)==0;D=A?M:N;E=A?N:M}if((c[d+3300>>2]|0)!=0){h[e>>3]=D*+h[d+88>>3]+E*+h[d+96>>3];h[f>>3]=D*+h[d+104>>3]+E*+h[d+112>>3];O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}M=+h[d+48>>3];if(M!=0.0){N=M*3.141592653589793/180.0;M=+S(+N);z=+T(+N);h[e>>3]=D*M+E*z;ba=E*M-D*z}else{h[e>>3]=D;ba=E}h[f>>3]=ba;ba=+h[d+32>>3];if(ba!=0.0){h[e>>3]=+h[e>>3]/ba}ba=+h[d+40>>3];if(!(ba!=0.0)){O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}h[f>>3]=+h[f>>3]/ba;O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}function nd(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0;f=i;g=(+h[c+224>>3]-(+h[c+176>>3]+a+-1.0+.5)*+h[c+192>>3])/1.0e3;a=((+h[c+184>>3]+b+-1.0+.5)*+h[c+200>>3]- +h[c+248>>3])/1.0e3;b=g*g;j=a*a;k=g*b;l=a*j;m=b+j;n=(k*+h[c+496>>3]+(l*+h[c+472>>3]+(m*+h[c+464>>3]+(b*+h[c+456>>3]+(+h[c+432>>3]+(a*+h[c+416>>3]+g*+h[c+424>>3])+j*+h[c+440>>3]+a*g*+h[c+448>>3])))+g*j*+h[c+480>>3]+b*a*+h[c+488>>3])+m*a*+h[c+504>>3]+m*m*a*+h[c+512>>3])/206264.8062470964;o=+h[c+160>>3];p=+U(+o);q=1.0-n*p;r=+Y(+((l*+h[c+336>>3]+(k*+h[c+312>>3]+(m*+h[c+304>>3]+(j*+h[c+296>>3]+(+h[c+272>>3]+(g*+h[c+256>>3]+a*+h[c+264>>3])+b*+h[c+280>>3]+a*g*+h[c+288>>3])))+a*b*+h[c+320>>3]+j*g*+h[c+328>>3])+m*g*+h[c+344>>3]+m*m*g*+h[c+352>>3])/206264.8062470964/+S(+o)),+q);o=r+ +h[c+152>>3];if(!(o<0.0)){s=o;t=s/.01745329252;h[d>>3]=t;u=+S(+r);v=n+p;w=v/q;x=u*w;y=+X(+x);z=y/.01745329252;h[e>>3]=z;i=f;return 0}s=o+6.28318530717959;t=s/.01745329252;h[d>>3]=t;u=+S(+r);v=n+p;w=v/q;x=u*w;y=+X(+x);z=y/.01745329252;h[e>>3]=z;i=f;return 0}function od(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,Q=0.0,R=0.0,U=0.0,V=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0;f=i;h[d>>3]=0.0;h[e>>3]=0.0;g=b*3.141592653589793/180.0;b=+T(+g);j=+S(+g);k=c+160|0;g=+h[k>>3];if(g==0.0){l=+h[c+8>>3]*3.141592653589793/180.0;h[k>>3]=l;m=l}else{m=g}g=+T(+m);l=+S(+m);k=c+152|0;m=+h[k>>3];if(m==0.0){n=+h[c+8>>3]*3.141592653589793/180.0;h[k>>3]=n;o=n}else{o=m}m=a*3.141592653589793/180.0-o;o=+S(+m);a=b*g+j*l*o;if(a==0.0){p=1;i=f;return p|0}n=j*+T(+m)*206264.8062470964/a;m=(b*l-j*g*o)*206264.8062470964/a;a=+h[c+168>>3];if(a==0.0){p=1;i=f;return p|0}o=+h[c+256>>3];g=+h[c+264>>3];j=+h[c+272>>3];l=+h[c+280>>3];b=+h[c+288>>3];q=+h[c+296>>3];r=+h[c+304>>3];s=+h[c+312>>3];t=+h[c+320>>3];u=+h[c+328>>3];v=+h[c+336>>3];w=+h[c+344>>3];x=+h[c+352>>3];y=l*2.0;z=r*2.0;A=s*3.0;B=t*2.0;C=q*2.0;D=u*2.0;E=v*3.0;F=w*2.0;G=x*4.0;H=+h[c+416>>3];I=+h[c+424>>3];J=+h[c+432>>3];K=+h[c+440>>3];L=+h[c+448>>3];M=+h[c+456>>3];N=+h[c+464>>3];O=+h[c+472>>3];Q=+h[c+480>>3];R=+h[c+488>>3];U=+h[c+496>>3];V=+h[c+504>>3];W=+h[c+512>>3];X=M*2.0;Y=N*2.0;Z=R*2.0;_=U*3.0;$=V*2.0;aa=W*4.0;ba=K*2.0;ca=O*3.0;da=Q*2.0;k=0;ea=n/a;fa=m/a;do{a=fa*ea;ga=ea*ea;ha=fa*fa;ia=fa*ga;ja=ha*ea;ka=ha+ga;la=ka*ka;ma=ea*ga;na=fa*ha;oa=ga*ga;pa=ha*ha;qa=ha*ga*6.0;ra=ha*u+(fa*b+(o+ea*y)+ea*z+ga*A+a*B)+(ha+ga*3.0)*w+(pa+(oa*5.0+qa))*x;sa=g+ea*b+fa*C+fa*z+ga*t+a*D+ha*E+a*F+ka*a*G;ta=I+fa*L+ea*X+ea*Y+ha*Q+a*Z+ga*_+a*$+ka*a*aa;ua=ga*R+(ea*L+(H+fa*ba)+fa*Y+ha*ca+a*da)+(ha*3.0+ga)*V+(oa+(pa*5.0+qa))*W;qa=j+(ea*o+fa*g)+ga*l+a*b+ha*q+ka*r+ma*s+ia*t+ja*u+na*v+ka*ea*w+la*ea*x-n;pa=J+(fa*H+ea*I)+ha*K+a*L+ga*M+ka*N+na*O+ja*Q+ia*R+ma*U+ka*fa*V+la*fa*W-m;la=ra*ua-sa*ta;ka=(sa*pa-qa*ua)/la;ua=(qa*ta-ra*pa)/la;ea=ea+ka;fa=fa+ua;if(+P(+ka)<5.0e-7?+P(+ua)<5.0e-7:0){break}k=k+1|0}while((k|0)<50);m=+h[c+192>>3];if(m==0.0){p=1;i=f;return p|0}W=+h[c+200>>3];if(W==0.0){p=1;i=f;return p|0}V=(fa*1.0e3+ +h[c+248>>3])/W;h[d>>3]=(+h[c+224>>3]-ea*1.0e3)/m- +h[c+176>>3]+1.0+-.5;m=V- +h[c+184>>3]+1.0+-.5;h[e>>3]=m;V=+h[d>>3];if(V<.5){p=-1;i=f;return p|0}if(V>+h[c+136>>3]+.5|m<.5){p=-1;i=f;return p|0}if(m>+h[c+144>>3]+.5){p=-1;i=f;return p|0}p=0;i=f;return p|0}function pd(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;i=i+16|0;e=d;d=c[o>>2]|0;c[e>>2]=a;c[e+4>>2]=b;za(d|0,10976,e|0)|0;hb(-1)}function qd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;f=i;i=i+544|0;g=f;h=f+24|0;j=f+8|0;k=ig(1,28)|0;if((k|0)==0){pd(10992,11016)}c[k+16>>2]=b;if((b|0)>4){c[g>>2]=b;c[g+4>>2]=4;Na(h|0,11040,g|0)|0;pd(11120,h)}if((b|0)==0){l=k+12|0}else{m=gg(b<<2)|0;n=k+12|0;c[n>>2]=m;if((m|0)==0){pd(10992,11136)}m=a;a=b;o=c[n>>2]|0;while(1){p=a+ -1|0;c[o>>2]=(c[m>>2]|0)+ -1;if((p|0)==0){l=n;break}else{m=m+4|0;a=p;o=o+4|0}}}c[k+24>>2]=e;a:do{if((e|0)!=0){o=c[l>>2]|0;a=e<<2;m=gg(a)|0;c[k+20>>2]=m;if((m|0)==0){pd(10992,11176)}Eg(j|0,0,a|0)|0;b:do{if((b|0)>0){a=0;while(1){m=c[o+(a<<2)>>2]|0;if((m|0)>=(e|0)){break}n=j+(m<<2)|0;c[n>>2]=(c[n>>2]|0)+1;a=a+1|0;if((a|0)>=(b|0)){break b}}pd(11216,11256)}}while(0);o=k+8|0;c[o>>2]=1;if((e|0)>0){a=c[k+20>>2]|0;n=d;m=1;p=0;while(1){q=n+4|0;r=c[n>>2]|0;c[a+(p<<2)>>2]=r;if((r|0)>10){break}s=c[j+(p<<2)>>2]|0;if((r|0)==0){t=1;u=1}else{v=r;w=1;x=1;while(1){y=aa(x,v+s|0)|0;z=v+ -1|0;A=aa(w,v)|0;if((z|0)==0){t=A;u=y;break}else{v=z;w=A;x=y}}}x=aa(m,(u|0)/(t|0)|0)|0;c[o>>2]=x;w=p+1|0;if((w|0)<(e|0)){n=q;m=x;p=w}else{B=x;break a}}c[g>>2]=r;c[g+4>>2]=10;Na(h|0,11264,g|0)|0;pd(11120,h)}else{B=1}}else{c[k+8>>2]=1;B=1}}while(0);h=gg(B<<3)|0;c[k>>2]=h;if((h|0)==0){pd(10992,11336)}h=ig(B,8)|0;c[k+4>>2]=h;if((h|0)==0){pd(10992,11376)}else{i=f;return k|0}return 0}function rd(a){a=a|0;var b=0;b=i;if((a|0)==0){i=b;return}hg(c[a+4>>2]|0);hg(c[a>>2]|0);hg(c[a+20>>2]|0);hg(c[a+12>>2]|0);hg(a);i=b;return}function sd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0.0,z=0.0,A=0,B=0,C=0,D=0;d=i;i=i+80|0;e=d;f=d+60|0;g=d+40|0;j=c[a+16>>2]|0;k=c[a>>2]|0;l=c[a+4>>2]|0;m=c[a+12>>2]|0;n=c[a+20>>2]|0;if((j|0)!=0){o=j+ -1|0;if((o|0)!=0){p=o;o=f;q=e;do{q=q+8|0;h[q>>3]=1.0;o=o+4|0;c[o>>2]=0;p=p+ -1|0}while((p|0)!=0)}p=c[a+24>>2]|0;if((p|0)!=0){o=n;n=p;p=g;while(1){n=n+ -1|0;c[p>>2]=c[o>>2];if((n|0)==0){break}else{o=o+4|0;p=p+4|0}}}p=g+(c[m>>2]<<2)|0;o=c[p>>2]|0;if((o|0)!=0){c[p>>2]=o+ -1}}o=l+8|0;r=+h[l>>3];l=k+8|0;h[k>>3]=1.0;c[f>>2]=1;s=+h[b>>3];h[e>>3]=s;k=(c[a+8>>2]|0)+ -1|0;if((k|0)==0){t=r;i=d;return+t}if((j|0)>0){u=s;v=k;w=l;x=o;y=r}else{z=s;a=k;k=l;l=o;s=r;while(1){h[k>>3]=z;r=s+z*+h[l>>3];o=a+ -1|0;if((o|0)==0){t=r;break}z=+h[e>>3];a=o;k=k+8|0;l=l+8|0;s=r}i=d;return+t}while(1){l=w+8|0;h[w>>3]=u;k=x+8|0;s=y+u*+h[x>>3];a=0;o=f;p=m;n=b;q=e;while(1){A=g+(c[p>>2]<<2)|0;B=c[A>>2]|0;c[A>>2]=B+ -1;C=c[o>>2]|0;if((B|0)!=0){D=13;break}c[g+(c[p>>2]<<2)>>2]=C;c[o>>2]=0;h[q>>3]=1.0;B=a+1|0;if((B|0)>=(j|0)){break}a=B;o=o+4|0;p=p+4|0;n=n+8|0;q=q+8|0}if((D|0)==13?(D=0,c[o>>2]=C+1,z=+h[n>>3]*+h[q>>3],h[q>>3]=z,(a|0)!=0):0){p=a;B=q;do{B=B+ -8|0;p=p+ -1|0;h[B>>3]=z}while((p|0)!=0)}p=v+ -1|0;if((p|0)==0){t=s;break}u=+h[e>>3];v=p;w=l;x=k;y=s}i=d;return+t}function td(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0.0,D=0.0,E=0,F=0,G=0,H=0,I=0.0,J=0,K=0,L=0,M=0;j=i;i=i+32|0;k=j;l=(b|0)!=0;m=(g|0)==0;if(m&(l^1)){pd(11416,11496)}n=c[a+8>>2]|0;o=c[a+16>>2]|0;p=aa(n,n)|0;q=c[a>>2]|0;r=ig(p,8)|0;if((r|0)==0){pd(10992,11512)}p=ig(n,8)|0;if((p|0)==0){pd(10992,11544)}if((f|0)!=0){s=(n|0)==0;t=(o|0)>0;u=e;e=d;d=f;f=g;g=b;while(1){b=d+ -1|0;if(l){if(t){v=0;w=g;while(1){h[k+(v<<3)>>3]=+h[w>>3];v=v+1|0;if((v|0)==(o|0)){break}else{w=w+8|0}}x=g+(o<<3)|0}else{x=g}+sd(a,k);if(m|s){y=f;z=x}else{w=q;v=f;A=n;while(1){A=A+ -1|0;h[v>>3]=+h[w>>3];if((A|0)==0){break}else{w=w+8|0;v=v+8|0}}y=f+(n<<3)|0;z=x}}else{if(s){y=f;z=g}else{v=q;w=f;A=n;while(1){A=A+ -1|0;h[v>>3]=+h[w>>3];if((A|0)==0){break}else{v=v+8|0;w=w+8|0}}y=f+(n<<3)|0;z=g}}if((u|0)==0){B=0;C=1.0}else{B=u+8|0;C=+h[u>>3]}w=e+8|0;D=+h[e>>3];if(!s){v=n;A=r;E=q;F=p;while(1){G=v+ -1|0;H=E+8|0;I=C*+h[E>>3];J=F+8|0;h[F>>3]=+h[F>>3]+D*I;K=A;L=q;M=n;while(1){M=M+ -1|0;h[K>>3]=+h[K>>3]+I*+h[L>>3];if((M|0)==0){break}else{K=K+8|0;L=L+8|0}}if((G|0)==0){break}else{v=G;A=A+(n<<3)|0;E=H;F=J}}}if((b|0)==0){break}else{u=B;e=w;d=b;f=y;g=z}}}ud(r,p,n);hg(r);if((n|0)==0){hg(p);i=j;return}r=p;z=c[a+4>>2]|0;a=n;while(1){a=a+ -1|0;h[z>>3]=+h[r>>3];if((a|0)==0){break}else{r=r+8|0;z=z+8|0}}hg(p);i=j;return}function ud(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=i;if((vd(a,b,c)|0)==0){i=d;return}e=c<<3;f=gg(aa(e,c)|0)|0;if((f|0)==0){pd(10992,11576)}g=gg(e)|0;if((g|0)==0){pd(10992,11600)}wd(a,b,c,c,f,g);hg(f);hg(g);i=d;return}function vd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0;d=i;e=gg(c<<3)|0;if((e|0)==0){pd(10992,11624)}f=(c|0)>0;if(f){g=0;a:do{j=aa(g,c)|0;k=e+(g<<3)|0;if((g|0)>0){l=g;do{m=aa(l,c)|0;n=g;o=+h[a+(l+j<<3)>>3];do{n=n+ -1|0;o=o- +h[a+(n+j<<3)>>3]*+h[a+(n+m<<3)>>3]}while((n|0)>0);if((g|0)==(l|0)){if(o<=0.0){p=15;break a}h[k>>3]=+Q(+o)}else{h[a+((aa(l,c)|0)+g<<3)>>3]=o/+h[k>>3]}l=l+1|0}while((l|0)<(c|0))}else{l=g;do{q=+h[a+(l+j<<3)>>3];if((g|0)==(l|0)){if(q<=0.0){p=15;break a}h[k>>3]=+Q(+q)}else{h[a+((aa(l,c)|0)+g<<3)>>3]=q/+h[k>>3]}l=l+1|0}while((l|0)<(c|0))}g=g+1|0}while((g|0)<(c|0));if((p|0)==15){hg(e);r=-1;i=d;return r|0}if(f){p=0;do{g=b+(p<<3)|0;q=+h[g>>3];if((p|0)>0){l=aa(p,c)|0;k=p;s=q;while(1){j=k+ -1|0;t=s- +h[a+(j+l<<3)>>3]*+h[b+(j<<3)>>3];if((j|0)>0){k=j;s=t}else{u=t;break}}}else{u=q}h[g>>3]=u/+h[e+(p<<3)>>3];p=p+1|0}while((p|0)!=(c|0));if(f){f=c;while(1){p=f+ -1|0;k=b+(p<<3)|0;u=+h[k>>3];if((f|0)<(c|0)){l=f;s=u;while(1){t=+h[a+((aa(l,c)|0)+p<<3)>>3];v=s-t*+h[b+(l<<3)>>3];j=l+1|0;if((j|0)==(c|0)){w=v;break}else{l=j;s=v}}}else{w=u}h[k>>3]=w/+h[e+(p<<3)>>3];if((p|0)>0){f=p}else{break}}}}}hg(e);r=0;i=d;return r|0}function wd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0.0,B=0.0,C=0,D=0.0,E=0.0,F=0.0,G=0,H=0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,S=0.0,T=0,U=0,V=0,W=0,X=0.0,Y=0,Z=0,_=0,$=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0.0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0.0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0.0,Fa=0.0,Ga=0.0,Ha=0.0,Ia=0.0,Ja=0.0,Ka=0.0,La=0.0,Ma=0.0,Na=0.0,Oa=0.0,Pa=0,Qa=0,Ra=0.0,Sa=0,Ta=0.0,Ua=0,Va=0,Wa=0.0;g=i;if((c|0)<(d|0)){pd(11648,11704)}j=d<<3;k=gg(j)|0;if((k|0)==0){pd(10992,11720)}l=gg(j)|0;if((l|0)==0){pd(10992,11744)}j=(d|0)>0;a:do{if(j){m=c+1|0;n=0.0;o=0.0;p=0;q=0.0;while(1){r=p+1|0;s=d-r|0;t=k+(p<<3)|0;h[t>>3]=o*q;u=c-p|0;b:do{if((u|0)>0?(v=a+((aa(p,m)|0)<<3)|0,w=(p|0)==(c|0),!w):0){x=v;y=u;z=0.0;while(1){y=y+ -1|0;z=z+ +P(+(+h[x>>3]));if((y|0)==0){break}else{x=x+8|0}}if(z!=0.0){if(w){A=0.0}else{x=v;y=u;B=0.0;while(1){C=y+ -1|0;D=+h[x>>3]/z;h[x>>3]=D;E=B+D*D;if((C|0)==0){A=E;break}else{x=x+8|0;y=C;B=E}}}B=+h[v>>3];E=+P(+(+Q(+A)));if(!(B>=0.0)){F=-E}else{F=E}E=-F;D=B*E-A;h[v>>3]=B+F;if((r|0)!=(d|0)){y=s;x=a+((aa(r,c)|0)+p<<3)|0;while(1){y=y+ -1|0;c:do{if(!w){C=v;G=x;H=u;B=0.0;while(1){I=H+ -1|0;J=B+ +h[G>>3]*+h[C>>3];if((I|0)==0){break}C=C+8|0;G=G+8|0;H=I;B=J}B=J/D;if(!w){H=v;G=x;C=u;while(1){I=C+ -1|0;h[G>>3]=+h[G>>3]+B*+h[H>>3];if((I|0)==0){break c}H=H+8|0;G=G+8|0;C=I}}}}while(0);if((y|0)==0){break}else{x=x+(c<<3)|0}}}if(w){K=E;L=z}else{x=v;y=u;while(1){C=y+ -1|0;h[x>>3]=z*+h[x>>3];if((C|0)==0){K=E;L=z;break b}x=x+8|0;y=C}}}else{K=0.0;L=z}}else{K=0.0;L=0.0}}while(0);E=K*L;u=f+(p<<3)|0;h[u>>3]=E;if(!((p|0)>=(c|0)|(r|0)==(d|0))){y=aa(r,c)|0;x=a+(y+p<<3)|0;v=x;w=s;D=0.0;while(1){w=w+ -1|0;D=D+ +P(+(+h[v>>3]));if((w|0)==0){break}else{v=v+(c<<3)|0}}if(D!=0.0){v=x;w=s;B=0.0;while(1){w=w+ -1|0;M=+h[v>>3]/D;h[v>>3]=M;B=B+M*M;if((w|0)==0){break}else{v=v+(c<<3)|0}}M=+h[x>>3];N=+P(+(+Q(+B)));if(!(M>=0.0)){O=-N}else{O=N}N=-O;R=M*N-B;S=M+O;h[x>>3]=S;v=k+(r<<3)|0;M=S;w=x;C=s;G=v;while(1){H=C+ -1|0;h[G>>3]=M/R;I=w+(c<<3)|0;if((H|0)==0){break}M=+h[I>>3];w=I;C=H;G=G+8|0}if((r|0)==(c|0)){T=x;U=s}else{G=c-r|0;C=a+(y+r<<3)|0;while(1){w=G+ -1|0;H=x;I=C;V=s;M=0.0;while(1){W=V+ -1|0;X=M+ +h[I>>3]*+h[H>>3];if((W|0)==0){Y=C;Z=s;_=v;break}H=H+(c<<3)|0;I=I+(c<<3)|0;V=W;M=X}while(1){Z=Z+ -1|0;h[Y>>3]=+h[Y>>3]+X*+h[_>>3];if((Z|0)==0){break}else{Y=Y+(c<<3)|0;_=_+8|0}}if((w|0)==0){T=x;U=s;break}else{G=w;C=C+8|0}}}while(1){C=U+ -1|0;h[T>>3]=D*+h[T>>3];if((C|0)==0){break}T=T+(c<<3)|0;U=C}$=+h[u>>3];ba=N;ca=D}else{$=E;ba=0.0;ca=D}}else{$=E;ba=0.0;ca=0.0}M=+P(+$);z=M+ +P(+(+h[t>>3]));da=n>z?n:z;if((r|0)==(d|0)){break}else{n=da;o=ba;p=r;q=ca}}p=d+ -1|0;if(j){q=ba;m=p;C=0;G=d;s=0;while(1){do{if((m|0)<(p|0)){if(q!=0.0){x=a+(m+(aa(G,c)|0)<<3)|0;v=e+((aa(m,d)|0)+G<<3)|0;y=e+((aa(G,d)|0)+G<<3)|0;o=+h[x>>3];n=q*o;V=(s|0)==0;if(V){break}else{ea=o;fa=x;ga=s;ha=v}while(1){I=ga+ -1|0;h[ha>>3]=ea/n;H=fa+(c<<3)|0;if((I|0)==0){break}ea=+h[H>>3];fa=H;ga=I;ha=ha+8|0}if(V){break}else{ia=s;ja=y}while(1){ia=ia+ -1|0;w=x;I=s;n=0.0;H=ja;while(1){W=I+ -1|0;ka=n+ +h[w>>3]*+h[H>>3];if((W|0)==0){la=s;ma=v;na=ja;break}w=w+(c<<3)|0;I=W;n=ka;H=H+8|0}while(1){la=la+ -1|0;h[na>>3]=+h[na>>3]+ka*+h[ma>>3];if((la|0)==0){break}else{ma=ma+8|0;na=na+8|0}}if((ia|0)==0){break}else{ja=ja+(d<<3)|0}}}if((s|0)!=0){v=s;x=e+(m+(aa(G,d)|0)<<3)|0;y=e+((aa(m,d)|0)+G<<3)|0;while(1){v=v+ -1|0;h[y>>3]=0.0;h[x>>3]=0.0;if((v|0)==0){break}else{x=x+(d<<3)|0;y=y+8|0}}}}}while(0);h[e+((aa(m,d)|0)+m<<3)>>3]=1.0;s=d-m|0;C=C+1|0;if((C|0)==(d|0)){break}else{r=m;q=+h[k+(m<<3)>>3];m=m+ -1|0;G=r}}if(j){G=~d;m=~c;C=(G|0)>(m|0)?G:m;m=a+((aa(-2-C|0,c)|0)+ -2-C<<3)|0;G=-8-(c<<3)|0;s=(C+c<<3)+16|0;p=~C;C=d;r=0;while(1){t=m+(aa(G,r)|0)|0;u=s+(r<<3)|0;y=C+ -1|0;x=d-C|0;v=c-y|0;q=+h[f+(y<<3)>>3];V=(aa(y,c)|0)+y|0;H=a+(V<<3)|0;I=a+(V+c<<3)|0;V=(C|0)==(d|0);if(!V){w=I;W=x;while(1){W=W+ -1|0;h[w>>3]=0.0;if((W|0)==0){break}else{w=w+(c<<3)|0}}}d:do{if(q!=0.0){E=1.0/q;if(!V){w=v+ -1|0;W=(w|0)==0;oa=(y|0)==(c|0);pa=x;qa=I;while(1){pa=pa+ -1|0;if(W){ra=0.0}else{sa=w;ta=H;ua=qa;D=0.0;while(1){va=ta+8|0;wa=ua+8|0;N=D+ +h[va>>3]*+h[wa>>3];xa=sa+ -1|0;if((xa|0)==0){ra=N;break}else{sa=xa;ta=va;ua=wa;D=N}}}D=+h[H>>3];N=E*(ra/D);e:do{if(!oa){n=D;ua=H;ta=qa;sa=v;while(1){wa=sa+ -1|0;va=ua+8|0;h[ta>>3]=+h[ta>>3]+N*n;if((wa|0)==0){break e}n=+h[va>>3];ua=va;ta=ta+8|0;sa=wa}}}while(0);if((pa|0)==0){break}else{qa=qa+(c<<3)|0}}}if((y|0)!=(c|0)){qa=H;pa=v;while(1){oa=pa+ -1|0;h[qa>>3]=E*+h[qa>>3];if((oa|0)==0){break d}qa=qa+8|0;pa=oa}}}else{if((y|0)!=(c|0)){Eg(t|0,0,u|0)|0}}}while(0);h[H>>3]=+h[H>>3]+1.0;u=r+1|0;if((u|0)==(p|0)){break}else{C=y;r=u}}if(j){r=(c|0)==0;C=d;p=0;f:while(1){s=C+ -1|0;G=f+(s<<3)|0;m=C+ -2|0;u=f+(m<<3)|0;t=k+(m<<3)|0;v=k+(s<<3)|0;I=0;x=p;while(1){V=s;pa=x;while(1){if(!((V|0)>-1)){ya=pa;za=93;break}qa=V+ -1|0;if(da+ +P(+(+h[k+(V<<3)>>3]))==da){Aa=qa;break}if(da+ +P(+(+h[f+(qa<<3)>>3]))==da){ya=qa;za=93;break}else{V=qa;pa=qa}}g:do{if((za|0)==93){za=0;pa=a+((aa(ya,c)|0)<<3)|0;if((V|0)>(s|0)){Aa=ya}else{qa=a+((aa(V,c)|0)<<3)|0;oa=V;q=1.0;while(1){E=q*+h[k+(oa<<3)>>3];N=+P(+E);if(da+N==da){Aa=ya;break g}w=f+(oa<<3)|0;D=+h[w>>3];n=+P(+D);if(!(N>n)){if(D!=0.0){o=N/n;Ba=n*+Q(+(o*o+1.0))}else{Ba=0.0}}else{o=n/N;Ba=N*+Q(+(o*o+1.0))}h[w>>3]=Ba;o=1.0/Ba;N=D*o;D=-(E*o);if(!r){w=pa;W=qa;sa=c;while(1){sa=sa+ -1|0;o=+h[W>>3];E=+h[w>>3];h[w>>3]=o*D+N*E;h[W>>3]=N*o-E*D;if((sa|0)==0){break}else{w=w+8|0;W=W+8|0}}}if((oa|0)>=(s|0)){Aa=ya;break g}qa=qa+(c<<3)|0;oa=oa+1|0;q=D}}}}while(0);Ca=+h[G>>3];if((V|0)==(s|0)){za=105;break}if((I|0)==99){break f}q=+h[f+(V<<3)>>3];N=+h[u>>3];E=+h[t>>3];o=+h[v>>3];n=((N-Ca)*(Ca+N)+(E-o)*(E+o))/(N*o*2.0);E=+P(+n);if(E>1.0){z=1.0/E;Da=E*+Q(+(z*z+1.0))}else{Da=+Q(+(E*E+1.0))}E=+P(+Da);if(!(n>=0.0)){Ea=-E}else{Ea=E}E=((q-Ca)*(Ca+q)+o*(N/(n+Ea)-o))/q;if((V|0)>(m|0)){Fa=E;Ga=q}else{oa=a+((aa(V,c)|0)<<3)|0;o=1.0;n=E;qa=V;E=1.0;pa=e+((aa(V,d)|0)<<3)|0;N=q;while(1){W=qa+1|0;q=+h[k+(W<<3)>>3];z=+h[f+(W<<3)>>3];M=E*q;R=o*q;q=+P(+n);B=+P(+M);if(!(q>B)){if(M!=0.0){S=q/B;Ha=B*+Q(+(S*S+1.0))}else{Ha=0.0}}else{S=B/q;Ha=q*+Q(+(S*S+1.0))}h[k+(qa<<3)>>3]=Ha;S=n/Ha;q=M/Ha;M=N*S+R*q;B=R*S-N*q;R=z*q;Ia=z*S;w=pa+(d<<3)|0;sa=d;ta=w;ua=pa;while(1){sa=sa+ -1|0;z=+h[ta>>3];Ja=+h[ua>>3];h[ua>>3]=q*z+S*Ja;h[ta>>3]=S*z-q*Ja;if((sa|0)==0){break}else{ta=ta+8|0;ua=ua+8|0}}Ja=+P(+M);z=+P(+R);do{if(!(Ja>z)){if(R!=0.0){Ka=Ja/z;La=z*+Q(+(Ka*Ka+1.0));za=130;break}else{h[f+(qa<<3)>>3]=0.0;Ma=S;Na=q;break}}else{Ka=z/Ja;La=Ja*+Q(+(Ka*Ka+1.0));za=130}}while(0);if((za|0)==130){za=0;h[f+(qa<<3)>>3]=La;if(La!=0.0){Ja=1.0/La;Ma=M*Ja;Na=R*Ja}else{Ma=S;Na=q}}Ja=B*Ma+Ia*Na;z=Ia*Ma-B*Na;ua=oa+(c<<3)|0;if(!r){ta=ua;sa=oa;wa=c;while(1){wa=wa+ -1|0;Ka=+h[ta>>3];Oa=+h[sa>>3];h[sa>>3]=Na*Ka+Ma*Oa;h[ta>>3]=Ma*Ka-Na*Oa;if((wa|0)==0){break}else{ta=ta+8|0;sa=sa+8|0}}}if((qa|0)<(m|0)){oa=ua;o=Ma;n=Ja;qa=W;E=Na;pa=w;N=z}else{Fa=Ja;Ga=z;break}}}h[k+(V<<3)>>3]=0.0;h[v>>3]=Fa;h[G>>3]=Ga;pa=I+1|0;if((pa|0)<100){I=pa;x=m}else{Pa=m;break}}if((za|0)==105){za=0;if(Ca<0.0){h[G>>3]=-Ca;m=d;x=e+((aa(s,d)|0)<<3)|0;while(1){I=m+ -1|0;h[x>>3]=-+h[x>>3];if((I|0)==0){Pa=Aa;break}else{m=I;x=x+8|0}}}else{Pa=Aa}}if((s|0)>0){C=s;p=Pa}else{break a}}pd(11768,11704)}}}}}while(0);Pa=(d|0)==0;if(!Pa){Aa=d;za=f;Ca=0.0;while(1){Aa=Aa+ -1|0;Ga=+h[za>>3];Ca=Ga>Ca?Ga:Ca;if((Aa|0)==0){break}else{za=za+8|0}}Ga=Ca*1.0e-11;if(!Pa){za=d;Aa=f;while(1){za=za+ -1|0;if(+h[Aa>>3]>3]=0.0}if((za|0)==0){break}else{Aa=Aa+8|0}}if(!Pa){Pa=(c|0)==0;Aa=d;za=a;a=l;ya=f;while(1){Aa=Aa+ -1|0;Ga=+h[ya>>3];if(Ga!=0.0){if(Pa){Qa=za;Ra=0.0}else{f=za;ja=b;ia=c;Ca=0.0;while(1){ia=ia+ -1|0;Ca=Ca+ +h[f>>3]*+h[ja>>3];if((ia|0)==0){break}else{f=f+8|0;ja=ja+8|0}}Qa=za+(c<<3)|0;Ra=Ca}Sa=Qa;Ta=Ra/Ga}else{Sa=za+(c<<3)|0;Ta=0.0}h[a>>3]=Ta;if((Aa|0)==0){break}else{za=Sa;a=a+8|0;ya=ya+8|0}}}}}if(j){Ua=0;Va=e}else{hg(l);hg(k);i=g;return}while(1){e=d;Ta=0.0;j=l;ya=Va;while(1){a=e+ -1|0;Wa=Ta+ +h[ya>>3]*+h[j>>3];if((a|0)==0){break}e=a;Ta=Wa;j=j+8|0;ya=ya+(d<<3)|0}h[b+(Ua<<3)>>3]=Wa;Ua=Ua+1|0;if((Ua|0)==(d|0)){break}else{Va=Va+8|0}}hg(l);hg(k);i=g;return}function xd(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0;f=i;i=i+32|0;g=f+8|0;h=f;j=f+16|0;k=h;c[k>>2]=5260110;c[k+4>>2]=5459015;k=e+4|0;a[k]=0;a[j]=0;l=e+20|0;c[l>>2]=-1;m=e+24|0;c[m>>2]=-1;n=e+28|0;c[n>>2]=-1;do{if((b|0)>0){o=e+8|0;p=e+13|0;q=0;r=0;a:while(1){s=d+(q*9|0)|0;do{if((a[d+(q*9|0)+4|0]|0)!=45){if((yg(s,11816)|0)==0){if(!((c[n>>2]|0)==-1)){t=1;u=35;break a}c[n>>2]=q;v=r}else{v=r}}else{w=d+(q*9|0)+5|0;x=c[2992]|0;b:do{if((x|0)>0){y=0;while(1){z=y+1|0;if((Ag(w,11976+(y<<2)|0,3)|0)==0){A=y;break b}if((z|0)<(x|0)){y=z}else{A=z;break}}}else{A=0}}while(0);if((A|0)==(x|0)){y=0;while(1){z=y+1|0;if((Ag(w,h+(y<<2)|0,3)|0)==0){B=y;break}if((z|0)<2){y=z}else{B=z;break}}if((B|0)==2){v=r;break}}if((a[k]|0)!=0){if((Ag(s,j,8)|0)!=0|(r|0)==0){t=1;u=35;break a}c[r>>2]=q;a[j]=0;v=r;break}c[g>>2]=w;Na(k|0,11832,g|0)|0;if((Ag(s,11840,4)|0)==0){c[l>>2]=q;a[o+0|0]=a[11848|0]|0;a[o+1|0]=a[11849|0]|0;a[o+2|0]=a[11850|0]|0;a[p]=4408644;a[p+1|0]=17221;a[p+2|0]=67;a[p+3|0]=0;c[g>>2]=k;Na(j|0,11856,g|0)|0;v=m;break}if((Ag(s,11864,4)|0)==0){c[m>>2]=q;a[o+0|0]=a[11848|0]|0;a[o+1|0]=a[11849|0]|0;a[o+2|0]=a[11850|0]|0;a[p]=4408644;a[p+1|0]=17221;a[p+2|0]=67;a[p+3|0]=0;c[g>>2]=k;Na(j|0,11872,g|0)|0;v=l;break}y=d+(q*9|0)+1|0;if((Ag(y,11880,3)|0)==0){c[l>>2]=q;c[g>>2]=a[s]|0;Na(o|0,11888,g|0)|0;c[g>>2]=a[s]|0;Na(p|0,11896,g|0)|0;c[g>>2]=p;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=m;break}if((Ag(y,11912,3)|0)==0){c[m>>2]=q;c[g>>2]=a[s]|0;Na(o|0,11888,g|0)|0;c[g>>2]=a[s]|0;Na(p|0,11896,g|0)|0;c[g>>2]=o;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=l;break}x=d+(q*9|0)+2|0;if((Ag(x,11920,2)|0)==0){c[l>>2]=q;z=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=z;Na(o|0,11928,g|0)|0;z=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=z;Na(p|0,11936,g|0)|0;c[g>>2]=p;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=m;break}if((Ag(x,11944,2)|0)!=0){t=1;u=35;break a}c[m>>2]=q;x=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=x;Na(o|0,11928,g|0)|0;x=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=x;Na(p|0,11936,g|0)|0;c[g>>2]=o;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=l}}while(0);s=q+1|0;if((s|0)<(b|0)){q=s;r=v}else{u=30;break}}if((u|0)==30){if((a[j]|0)==0){break}else{t=1}i=f;return t|0}else if((u|0)==35){i=f;return t|0}}}while(0);if((Ag(k,11952,3)|0)==0){a[k]=4998739;a[k+1|0]=19526;a[k+2|0]=76;a[k+3|0]=0;C=137}else{C=(a[k]|0)==0?999:137}c[e>>2]=C;t=0;i=f;return t|0}function yd(b,d,e,f,g,j,k,l,m,n,o){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0,t=0,u=0.0,v=0,w=0.0,x=0.0;p=i;q=n+4|0;if((c[d>>2]|0)!=137?(xd(c[q>>2]|0,b,d)|0)!=0:0){r=1;i=p;return r|0}b=c[q>>2]|0;if((b|0)>0){q=c[d+20>>2]|0;s=d+24|0;t=0;do{if((t|0)!=(q|0)?(t|0)!=(c[s>>2]|0):0){h[m+(t<<3)>>3]=+h[e+(t<<3)>>3]- +h[f+(t<<3)>>3]}t=t+1|0}while((t|0)<(b|0))}do{if((c[d>>2]|0)!=999){b=d+4|0;do{if((yg(b,11960)|0)==0){t=g+16|0;if(+h[t>>3]==0.0){r=2;i=p;return r|0}else{a[b]=5130579;a[b+1|0]=20041;a[b+2|0]=78;a[b+3|0]=0;h[l+40>>3]=0.0;u=+Re(+h[t>>3]);h[l+48>>3]=u/+Se(+h[t>>3]);t=l+4|0;c[t>>2]=c[t>>2]>>31;break}}}while(0);t=d+20|0;f=c[t>>2]|0;s=d+24|0;q=c[s>>2]|0;v=Fd(b,+h[e+(f<<3)>>3],+h[e+(q<<3)>>3],g,j,k,l,m+(f<<3)|0,m+(q<<3)|0)|0;if((v|0)!=0){r=v;i=p;return r|0}v=c[d+28>>2]|0;if(!((v|0)==-1)){u=+h[l+24>>3];if(u==0.0){w=90.0}else{w=u*3.141592653589793*.5}q=m+(c[s>>2]<<3)|0;u=+h[q>>3];if(u>3]=w+u;h[m+(v<<3)>>3]=5.0;break}x=w*.5;if(u>x){h[q>>3]=u-w;h[m+(v<<3)>>3]=0.0;break}q=m+(c[t>>2]<<3)|0;u=+h[q>>3];if(u>w*2.5){h[q>>3]=u-w*3.0;h[m+(v<<3)>>3]=4.0;break}if(u>w*1.5){h[q>>3]=u-w*2.0;h[m+(v<<3)>>3]=3.0;break}if(u>x){h[q>>3]=u-w;h[m+(v<<3)>>3]=2.0;break}else{h[m+(v<<3)>>3]=1.0;break}}}}while(0);l=(Cd(m,n,o)|0)==0;r=l?0:4;i=p;return r|0}function zd(b,d,e,f,g,j,k,l,m,n,o){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0.0,t=0.0;p=i;if((c[d>>2]|0)!=137?(xd(c[f+4>>2]|0,b,d)|0)!=0:0){q=1;i=p;return q|0}if((Dd(e,f,g)|0)!=0){q=4;i=p;return q|0}e=c[f+4>>2]|0;if((e|0)>0){f=c[d+20>>2]|0;b=d+24|0;r=0;do{if((r|0)!=(f|0)?(r|0)!=(c[b>>2]|0):0){h[o+(r<<3)>>3]=+h[g+(r<<3)>>3]+ +h[m+(r<<3)>>3]}r=r+1|0}while((r|0)<(e|0))}if((c[d>>2]|0)!=999){e=c[d+28>>2]|0;a:do{if(!((e|0)==-1)){s=+h[g+(e<<3)>>3];r=~~(s+.5);if(+P(+(s- +(r|0)))>1.0e-10){q=3;i=p;return q|0}s=+h[j+24>>3];if(s==0.0){t=90.0}else{t=s*3.141592653589793*.5}switch(r|0){case 2:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t+ +h[r>>3];break a;break};case 4:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t*3.0+ +h[r>>3];break a;break};case 3:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t*2.0+ +h[r>>3];break a;break};case 0:{r=g+(c[d+24>>2]<<3)|0;h[r>>3]=t+ +h[r>>3];break a;break};case 5:{r=g+(c[d+24>>2]<<3)|0;h[r>>3]=+h[r>>3]-t;break a;break};case 1:{break a;break};default:{q=3;i=p;return q|0}}}}while(0);e=d+4|0;do{if((yg(e,11960)|0)==0){r=n+16|0;if(+h[r>>3]==0.0){q=2;i=p;return q|0}else{a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;h[j+40>>3]=0.0;t=+Re(+h[r>>3]);h[j+48>>3]=t/+Se(+h[r>>3]);r=j+4|0;c[r>>2]=c[r>>2]>>31;break}}}while(0);r=c[d+20>>2]|0;m=c[d+24>>2]|0;d=Gd(e,+h[g+(r<<3)>>3],+h[g+(m<<3)>>3],j,k,l,n,o+(r<<3)|0,o+(m<<3)|0)|0;if((d|0)!=0){q=d;i=p;return q|0}}q=0;i=p;return q|0}function Ad(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;b=i;d=c[a+4>>2]|0;e=aa(d<<3,d)|0;f=gg(e)|0;c[a+20>>2]=f;if((f|0)==0){g=1;i=b;return g|0}j=gg(e)|0;c[a+24>>2]=j;if((j|0)==0){hg(f);g=1;i=b;return g|0}if((d|0)>0){e=a+16|0;k=a+12|0;l=0;m=0;while(1){n=(c[e>>2]|0)+(l<<3)|0;o=c[k>>2]|0;p=m;q=0;while(1){h[f+(p<<3)>>3]=+h[n>>3]*+h[o+(p<<3)>>3];q=q+1|0;if((q|0)==(d|0)){break}else{p=p+1|0}}l=l+1|0;if((l|0)==(d|0)){break}else{m=d+m|0}}}if((Bd(d,f,j)|0)!=0){g=2;i=b;return g|0}c[a>>2]=137;g=0;i=b;return g|0}function Bd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0,x=0,y=0,z=0,A=0,B=0;e=i;f=a<<2;g=gg(f)|0;if((g|0)==0){j=1;i=e;return j|0}k=gg(f)|0;if((k|0)==0){hg(g);j=1;i=e;return j|0}f=a<<3;l=gg(f)|0;if((l|0)==0){hg(g);hg(k);j=1;i=e;return j|0}m=gg(aa(f,a)|0)|0;if((m|0)==0){hg(g);hg(k);hg(l);j=1;i=e;return j|0}f=(a|0)>0;if(f){n=a<<3;o=0;p=0;while(1){c[g+(o<<2)>>2]=o;q=l+(o<<3)|0;h[q>>3]=0.0;Kg(m+(p<<3)|0,b+(p<<3)|0,n|0)|0;r=0.0;s=p;t=0;while(1){u=+P(+(+h[b+(s<<3)>>3]));if(u>r){h[q>>3]=u;v=u}else{v=r}t=t+1|0;if((t|0)==(a|0)){break}else{r=v;s=s+1|0}}o=o+1|0;if(v==0.0){w=17;break}if((o|0)>=(a|0)){break}else{p=p+a|0}}if((w|0)==17){hg(g);hg(k);hg(l);hg(m);j=2;i=e;return j|0}if(f){w=0;while(1){p=aa(w,a)|0;o=m+(p+w<<3)|0;b=l+(w<<3)|0;n=w+1|0;s=(n|0)<(a|0);if(s){v=+P(+(+h[o>>3]))/+h[b>>3];t=n;q=w;while(1){r=+P(+(+h[m+((aa(t,a)|0)+w<<3)>>3]));u=r/+h[l+(t<<3)>>3];x=u>v;q=x?t:q;t=t+1|0;if((t|0)==(a|0)){break}else{v=x?u:v}}if((q|0)>(w|0)){t=0;x=p;y=aa(q,a)|0;while(1){z=m+(y<<3)|0;v=+h[z>>3];A=m+(x<<3)|0;h[z>>3]=+h[A>>3];h[A>>3]=v;t=t+1|0;if((t|0)==(a|0)){break}else{x=x+1|0;y=y+1|0}}y=l+(q<<3)|0;v=+h[y>>3];h[y>>3]=+h[b>>3];h[b>>3]=v;y=g+(q<<2)|0;x=c[y>>2]|0;t=g+(w<<2)|0;c[y>>2]=c[t>>2];c[t>>2]=x}if(s){x=n;do{t=aa(x,a)|0;y=m+(t+w<<3)|0;v=+h[y>>3];a:do{if(v!=0.0){u=v/+h[o>>3];h[y>>3]=u;r=u;A=n;while(1){z=m+(A+t<<3)|0;h[z>>3]=+h[z>>3]-r*+h[m+(A+p<<3)>>3];z=A+1|0;if((z|0)==(a|0)){break a}r=+h[y>>3];A=z}}}while(0);x=x+1|0}while((x|0)!=(a|0))}}if((n|0)==(a|0)){break}else{w=n}}if(f){w=0;do{c[k+(c[g+(w<<2)>>2]<<2)>>2]=w;w=w+1|0}while((w|0)!=(a|0));if(f){w=a<<3;x=0;p=0;while(1){Eg(d+(p<<3)|0,0,w|0)|0;x=x+1|0;if((x|0)==(a|0)){break}else{p=p+a|0}}if(f){f=0;do{p=c[k+(f<<2)>>2]|0;h[d+((aa(p,a)|0)+f<<3)>>3]=1.0;x=p+1|0;if((x|0)<(a|0)){w=x;while(1){if((p|0)<(w|0)){x=aa(w,a)|0;o=d+(x+f<<3)|0;v=+h[o>>3];s=p;do{v=v- +h[m+(s+x<<3)>>3]*+h[d+((aa(s,a)|0)+f<<3)>>3];h[o>>3]=v;s=s+1|0}while((s|0)!=(w|0))}s=w+1|0;if((s|0)==(a|0)){B=a;break}else{w=s}}}else{B=a}while(1){w=B+ -1|0;p=aa(w,a)|0;n=d+(p+f<<3)|0;if((B|0)<(a|0)){v=+h[n>>3];s=B;do{v=v- +h[m+(s+p<<3)>>3]*+h[d+((aa(s,a)|0)+f<<3)>>3];h[n>>3]=v;s=s+1|0}while((s|0)!=(a|0))}h[n>>3]=+h[n>>3]/+h[m+(p+w<<3)>>3];if((w|0)>0){B=w}else{break}}f=f+1|0}while((f|0)!=(a|0))}}}}}hg(g);hg(k);hg(l);hg(m);j=0;i=e;return j|0}function Cd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0,r=0;e=i;f=c[b+4>>2]|0;if((c[b>>2]|0)!=137?(Ad(b)|0)!=0:0){g=1;i=e;return g|0}j=(f|0)>0;if(!j){g=0;i=e;return g|0}k=b+24|0;l=0;m=0;while(1){n=d+(l<<3)|0;h[n>>3]=0.0;o=c[k>>2]|0;p=0.0;q=m;r=0;while(1){p=p+ +h[o+(q<<3)>>3]*+h[a+(r<<3)>>3];h[n>>3]=p;r=r+1|0;if((r|0)==(f|0)){break}else{q=q+1|0}}l=l+1|0;if((l|0)==(f|0)){break}else{m=f+m|0}}if(!j){g=0;i=e;return g|0}j=c[b+8>>2]|0;b=0;while(1){m=d+(b<<3)|0;h[m>>3]=+h[j+(b<<3)>>3]+ +h[m>>3];m=b+1|0;if((m|0)==(f|0)){g=0;break}else{b=m}}i=e;return g|0}function Dd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0;e=i;f=c[b+4>>2]|0;if((c[b>>2]|0)!=137?(Ad(b)|0)!=0:0){g=1;i=e;return g|0}if((f|0)<=0){g=0;i=e;return g|0}Eg(d|0,0,f<<3|0)|0;j=c[b+8>>2]|0;k=b+20|0;b=0;while(1){l=+h[a+(b<<3)>>3]- +h[j+(b<<3)>>3];m=c[k>>2]|0;n=0;o=b;while(1){p=d+(n<<3)|0;h[p>>3]=+h[p>>3]+l*+h[m+(o<<3)>>3];n=n+1|0;if((n|0)==(f|0)){break}else{o=o+f|0}}o=b+1|0;if((o|0)==(f|0)){g=0;break}else{b=o}}i=e;return g|0}function Ed(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0,C=0.0,D=0.0;e=i;if((Hd(a,d)|0)!=0){f=1;i=e;return f|0}a=b+8|0;g=b+24|0;j=+h[g>>3]==999.0;k=d+16|0;l=+h[k>>3];do{if(!(l==90.0)){m=+h[b+16>>3];if(j){h[g>>3]=m>3]);o=+Re(+h[g>>3]);p=+Se(+h[g>>3]);q=+Re(+h[k>>3]);r=+Se(+h[k>>3]);s=o*q;o=+Q(+(s*s+r*r));do{if(o==0.0){if(m!=0.0){f=1;i=e;return f|0}else{t=+h[b+32>>3];break}}else{u=m/o;if(+P(+u)>1.0){f=1;i=e;return f|0}v=+Xe(r,s);w=+Ue(u);u=v+w;if(!(u>180.0)){if(u<-180.0){x=u+360.0}else{x=u}}else{x=u+-360.0}u=v-w;if(!(u>180.0)){if(u<-180.0){y=u+360.0}else{y=u}}else{y=u+-360.0}d=b+32|0;u=+h[d>>3];if(+P(+(u-x))<+P(+(u-y))){z=+P(+x)<90.0000000001;A=z?x:y}else{z=+P(+y)<90.0000000001;A=z?y:x}h[d>>3]=A;t=A}}while(0);d=b+40|0;z=b+48|0;h[z>>3]=90.0-t;s=n*+Re(t);do{if(+P(+s)<1.0e-10){if(+P(+n)<1.0e-10){o=+h[a>>3];h[d>>3]=o;h[z>>3]=90.0- +h[k>>3];B=a;C=o;break}if(t>0.0){o=+h[a>>3]+ +h[g>>3]+-180.0;h[d>>3]=o;h[z>>3]=0.0;B=a;C=o;break}if(t<0.0){o=+h[a>>3]- +h[g>>3];h[d>>3]=o;h[z>>3]=180.0;B=a;C=o;break}else{B=a;C=+h[d>>3];break}}else{o=(r-m*+Se(t))/s;u=p*q/n;if(o==0.0&u==0.0){f=1;i=e;return f|0}else{w=+h[a>>3];v=w- +Xe(u,o);h[d>>3]=v;B=a;C=v;break}}}while(0);if(!(+h[B>>3]>=0.0)){if(!(C>0.0)){D=t;break}h[d>>3]=C+-360.0;D=t;break}else{if(!(C<0.0)){D=t;break}h[d>>3]=C+360.0;D=t;break}}else{if(j){h[g>>3]=180.0}n=+h[b+16>>3];h[b+32>>3]=n;h[b+40>>3]=+h[a>>3];h[b+48>>3]=90.0-n;D=n}}while(0);h[b+56>>3]=+h[g>>3];g=b+48|0;h[b+64>>3]=+Re(+h[g>>3]);h[b+72>>3]=+Se(+h[g>>3]);c[b>>2]=137;b=+P(+D)>90.0000000001;f=b?2:0;i=e;return f|0}function Fd(a,b,d,e,f,g,j,k,l){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;m=i;if((c[e>>2]|0)!=137?(Ed(a,e,j)|0)!=0:0){n=1;i=m;return n|0}Pe(b,d,e+40|0,f,g)|0;e=lb[c[j+1888>>2]&63](+h[f>>3],+h[g>>3],j,k,l)|0;if((e|0)==0){n=0;i=m;return n|0}n=(e|0)==1?2:3;i=m;return n|0}function Gd(a,b,d,e,f,g,j,k,l){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;m=i;if((c[j>>2]|0)!=137?(Ed(a,j,e)|0)!=0:0){n=1;i=m;return n|0}a=lb[c[e+1892>>2]&63](b,d,e,f,g)|0;if((a|0)==0){Qe(+h[f>>3],+h[g>>3],j+40|0,k,l)|0;n=0;i=m;return n|0}else{n=(a|0)==1?2:3;i=m;return n|0}return 0}function Hd(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;e=i;if((yg(b,12080)|0)==0){Id(d)|0;f=0;i=e;return f|0}if((yg(b,12088)|0)==0){Jd(d)|0;f=0;i=e;return f|0}if((yg(b,12096)|0)==0){a[d]=5128532;a[d+1|0]=20033;a[d+2|0]=78;a[d+3|0]=0;g=d+4|0;c[g>>2]=(c[g>>2]>>31&-206)+103;h[d+8>>3]=0.0;h[d+16>>3]=90.0;g=d+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}c[d+1888>>2]=1;c[d+1892>>2]=2;g=99;while(1){if(!(+h[d+(g<<3)+280>>3]==0.0)){j=g;break}k=g+ -1|0;if(!(+h[d+(g+100<<3)+280>>3]==0.0)){j=g;break}if((g|0)>0){g=k}else{j=k;break}}c[d+276>>2]=(j|0)<0?0:j;f=0;i=e;return f|0}if((yg(b,12104)|0)==0){a[d]=4674643;a[d+1|0]=18260;a[d+2|0]=71;a[d+3|0]=0;c[d+4>>2]=104;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=114.59155902616465;h[d+120>>3]=.008726646259971648}else{m=l*2.0;h[d+112>>3]=m;h[d+120>>3]=1.0/m}c[d+1888>>2]=3;c[d+1892>>2]=4;f=0;i=e;return f|0}if((yg(b,12112)|0)==0){a[d]=5130579;a[d+1|0]=20041;a[d+2|0]=78;a[d+3|0]=0;j=d+4|0;c[j>>2]=(c[j>>2]>>31&-210)+105;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;m=+h[j>>3];if(m==0.0){h[j>>3]=57.29577951308232;n=57.29577951308232}else{n=m}h[d+112>>3]=1.0/n;n=+h[d+40>>3];m=+h[d+48>>3];l=n*n+m*m;h[d+120>>3]=l;h[d+128>>3]=l+1.0;h[d+136>>3]=l+-1.0;c[d+1888>>2]=5;c[d+1892>>2]=6;f=0;i=e;return f|0}if((yg(b,12120)|0)==0){a[d]=4411969;a[d+1|0]=17234;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=106;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{m=l*3.141592653589793/180.0;h[d+112>>3]=m;h[d+120>>3]=1.0/m}c[d+1888>>2]=7;c[d+1892>>2]=8;f=0;i=e;return f|0}if((yg(b,12128)|0)==0){Kd(d)|0;f=0;i=e;return f|0}if((yg(b,12136)|0)==0){a[d]=4277594;a[d+1|0]=16709;a[d+2|0]=65;a[d+3|0]=0;c[d+4>>2]=108;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;m=+h[j>>3];if(m==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=114.59155902616465;h[d+120>>3]=.008726646259971648}else{l=m*2.0;h[d+112>>3]=l;h[d+120>>3]=1.0/l}c[d+1888>>2]=9;c[d+1892>>2]=10;f=0;i=e;return f|0}if((yg(b,12144)|0)==0){a[d]=5392705;a[d+1|0]=21065;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=109;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;o=57.29577951308232}else{o=l}l=o*2.0;j=d+112|0;h[j>>3]=l;o=+h[d+40>>3];do{if(!(o==90.0)){if(o>-90.0){m=+Re((90.0-o)*.5);n=m*m;p=+_(+m)*n/(1.0-n);h[d+120>>3]=p;n=.5-p;h[d+128>>3]=n;q=n;r=+h[j>>3];break}else{f=0;i=e;return f|0}}else{h[d+120>>3]=-.5;h[d+128>>3]=1.0;q=1.0;r=l}}while(0);h[d+136>>3]=q*r;h[d+144>>3]=1.0e-4;h[d+152>>3]=q*1.0e-4;h[d+160>>3]=57.29577951308232/q;c[d+1888>>2]=11;c[d+1892>>2]=12;f=0;i=e;return f|0}if((yg(b,12152)|0)==0){a[d]=5265731;a[d+1|0]=20569;a[d+2|0]=80;a[d+3|0]=0;c[d+4>>2]=201;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];do{if(q==0.0){h[g>>3]=57.29577951308232;r=+h[d+48>>3];h[d+112>>3]=r;if(r==0.0){f=0;i=e;return f|0}h[d+120>>3]=1.0/r;l=(r+ +h[d+40>>3])*57.29577951308232;h[d+128>>3]=l;if(l==0.0){f=0;i=e;return f|0}else{h[d+136>>3]=1.0/l;break}}else{l=+h[d+48>>3];r=q*l*3.141592653589793/180.0;h[d+112>>3]=r;if(r==0.0){f=0;i=e;return f|0}h[d+120>>3]=1.0/r;r=q*(l+ +h[d+40>>3]);h[d+128>>3]=r;if(r==0.0){f=0;i=e;return f|0}else{h[d+136>>3]=1.0/r;break}}}while(0);c[d+1888>>2]=13;c[d+1892>>2]=14;f=0;i=e;return f|0}if((yg(b,12160)|0)==0){a[d]=4277571;a[d+1|0]=16709;a[d+2|0]=65;a[d+3|0]=0;c[d+4>>2]=202;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;q=+h[j>>3];do{if(q==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;r=+h[d+40>>3];if(r<=0.0|r>1.0){f=0;i=e;return f|0}else{h[d+128>>3]=57.29577951308232/r;h[d+136>>3]=r/57.29577951308232;break}}else{h[d+112>>3]=q*3.141592653589793/180.0;h[d+120>>3]=57.29577951308232/q;r=+h[d+40>>3];if(r<=0.0|r>1.0){f=0;i=e;return f|0}else{h[d+128>>3]=q/r;h[d+136>>3]=r/q;break}}}while(0);c[d+1888>>2]=15;c[d+1892>>2]=16;f=0;i=e;return f|0}if((yg(b,12168)|0)==0){a[d]=5390659;a[d+1|0]=21057;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=203;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{r=q*3.141592653589793/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r}c[d+1888>>2]=17;c[d+1892>>2]=18;f=0;i=e;return f|0}if((yg(b,12176)|0)==0){a[d]=5391693;a[d+1|0]=21061;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=204;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;r=+h[j>>3];if(r==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{q=r*3.141592653589793/180.0;h[d+112>>3]=q;h[d+120>>3]=1.0/q}c[d+1888>>2]=19;c[d+1892>>2]=20;f=0;i=e;return f|0}if((yg(b,12184)|0)==0){a[d]=4998739;a[d+1|0]=19526;a[d+2|0]=76;a[d+3|0]=0;c[d+4>>2]=301;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{r=q*3.141592653589793/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r}c[d+1888>>2]=21;c[d+1892>>2]=22;f=0;i=e;return f|0}if((yg(b,12192)|0)==0){a[d]=5390672;a[d+1|0]=21057;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=302;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;r=+h[j>>3];if(r==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;h[d+128>>3]=180.0;h[d+136>>3]=.005555555555555556}else{q=r*3.141592653589793;r=q/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r;h[d+128>>3]=q;h[d+136>>3]=1.0/q}c[d+1888>>2]=23;c[d+1892>>2]=24;f=0;i=e;return f|0}if((yg(b,12200)|0)==0){a[d]=5001037;a[d+1|0]=19535;a[d+2|0]=76;a[d+3|0]=0;c[d+4>>2]=303;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;s=57.29577951308232}else{s=q}q=s*1.4142135623730951;h[d+112>>3]=q;h[d+120>>3]=q/90.0;h[d+128>>3]=1.0/q;h[d+136>>3]=90.0/s;h[d+144>>3]=.6366197723675814;c[d+1888>>2]=25;c[d+1892>>2]=26;f=0;i=e;return f|0}if((yg(b,12208)|0)==0){a[d]=5523777;a[d+1|0]=21577;a[d+2|0]=84;a[d+3|0]=0;c[d+4>>2]=401;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;s=+h[j>>3];if(s==0.0){h[j>>3]=57.29577951308232;t=57.29577951308232}else{t=s}s=t*2.0;q=t*s;h[d+112>>3]=q;t=1.0/(q*2.0);h[d+120>>3]=t;h[d+128>>3]=t*.25;h[d+136>>3]=1.0/s;c[d+1888>>2]=27;c[d+1892>>2]=28;f=0;i=e;return f|0}if((yg(b,12216)|0)==0){Ld(d)|0;f=0;i=e;return f|0}if((yg(b,12224)|0)==0){Md(d)|0;f=0;i=e;return f|0}if((yg(b,12232)|0)==0){Nd(d)|0;f=0;i=e;return f|0}if((yg(b,12240)|0)==0){Od(d)|0;f=0;i=e;return f|0}if((yg(b,12248)|0)==0){Pd(d)|0;f=0;i=e;return f|0}if((yg(b,12256)|0)==0){a[d]=5194576;a[d+1|0]=20291;a[d+2|0]=79;a[d+3|0]=0;c[d+4>>2]=602;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;s=+h[g>>3];if(s==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;h[d+128>>3]=114.59155902616465}else{t=s*3.141592653589793/180.0;h[d+112>>3]=t;h[d+120>>3]=1.0/t;h[d+128>>3]=s*2.0}c[d+1888>>2]=29;c[d+1892>>2]=30;f=0;i=e;return f|0}if((yg(b,12264)|0)==0){a[d]=4412244;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=701;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;s=+h[j>>3];if(s==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{t=s*3.141592653589793*.25;h[d+112>>3]=t;h[d+120>>3]=1.0/t}c[d+1888>>2]=31;c[d+1892>>2]=32;f=0;i=e;return f|0}if((yg(b,12272)|0)==0){a[d]=4412227;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=702;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;t=+h[g>>3];if(t==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{s=t*3.141592653589793*.25;h[d+112>>3]=s;h[d+120>>3]=1.0/s}c[d+1888>>2]=33;c[d+1892>>2]=34;f=0;i=e;return f|0}if((yg(b,12280)|0)!=0){f=1;i=e;return f|0}a[d]=4412241;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=703;b=d+8|0;g=d+24|0;c[b+0>>2]=0;c[b+4>>2]=0;c[b+8>>2]=0;c[b+12>>2]=0;s=+h[g>>3];if(s==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{t=s*3.141592653589793*.25;h[d+112>>3]=t;h[d+120>>3]=1.0/t}c[d+1888>>2]=35;c[d+1892>>2]=36;f=0;i=e;return f|0}function Id(b){b=b|0;var d=0,e=0,f=0.0,g=0.0,j=0,k=0,l=0,m=0.0,n=0.0;d=i;a[b]=5265985;a[b+1|0]=20570;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-202)+101;h[b+8>>3]=0.0;h[b+16>>3]=90.0;e=b+24|0;f=+h[e>>3];if(f==0.0){h[e>>3]=57.29577951308232;g=57.29577951308232}else{g=f}e=b+40|0;f=g*(+h[e>>3]+1.0);h[b+112>>3]=f;if(f==0.0){j=1;i=d;return j|0}k=b+48|0;f=+Re(+h[k>>3]);l=b+136|0;h[l>>3]=f;if(f==0.0){j=1;i=d;return j|0}h[b+128>>3]=1.0/f;f=+Se(+h[k>>3]);h[b+144>>3]=f;g=+h[l>>3];h[b+120>>3]=f/g;f=+h[e>>3];if(+P(+f)>1.0){h[b+152>>3]=+Ve(-1.0/f);m=+h[e>>3];n=+h[l>>3]}else{h[b+152>>3]=-90.0;m=f;n=g}g=m*n;h[b+160>>3]=g;l=+P(+g)<1.0;h[b+168>>3]=l?1.0:0.0;c[b+1888>>2]=37;c[b+1892>>2]=38;j=0;i=d;return j|0}function Jd(b){b=b|0;var d=0,e=0,f=0.0,g=0.0,j=0,k=0,l=0,m=0,n=0,o=0;d=i;a[b]=5266003;a[b+1|0]=20570;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-204)+102;h[b+8>>3]=0.0;h[b+16>>3]=90.0;e=b+24|0;f=+h[e>>3];if(f==0.0){h[e>>3]=57.29577951308232;g=57.29577951308232}else{g=f}h[b+112>>3]=1.0/g;j=b+40|0;g=+h[j>>3];k=b+56|0;f=g*+Se(+h[k>>3])+1.0;l=b+136|0;h[l>>3]=f;if(f==0.0){m=1;i=d;return m|0}f=+h[j>>3];g=f*+Re(+h[k>>3]);n=b+48|0;o=b+120|0;h[o>>3]=-(g*+Se(+h[n>>3]));g=+h[j>>3];f=g*+Re(+h[k>>3]);g=f*+Re(+h[n>>3]);h[b+128>>3]=g;f=+h[e>>3];h[b+144>>3]=f*+h[o>>3];h[b+152>>3]=f*g;g=+h[l>>3];h[b+160>>3]=f*g;f=g+-1.0;h[b+168>>3]=g*f+-1.0;if(+P(+f)<1.0){h[b+176>>3]=+Ve(1.0-g)}else{h[b+176>>3]=-90.0}c[b+1888>>2]=39;c[b+1892>>2]=40;m=0;i=d;return m|0}function Kd(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0.0,l=0.0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0.0,C=0.0,D=0.0;d=i;a[b]=5132378;a[b+1|0]=20048;a[b+2|0]=78;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-214)+107;f=b+8|0;h[f>>3]=0.0;g=b+16|0;h[g>>3]=90.0;j=b+24|0;k=+h[j>>3];if(k==0.0){h[j>>3]=57.29577951308232;l=57.29577951308232}else{l=k}m=9;while(1){if(!(+h[b+(m<<3)+32>>3]==0.0)){break}if((m|0)>0){m=m+ -1|0}else{n=6;break}}if((n|0)==6){a[b]=4411969;a[b+1|0]=17234;a[b+2|0]=67;a[b+3|0]=0;c[e>>2]=106;h[f>>3]=0.0;h[g>>3]=90.0;if(l==0.0){h[j>>3]=57.29577951308232;h[b+112>>3]=1.0;h[b+120>>3]=1.0}else{k=l*3.141592653589793/180.0;h[b+112>>3]=k;h[b+120>>3]=1.0/k}c[b+1888>>2]=7;c[b+1892>>2]=8;o=0;i=d;return o|0}c[b+272>>2]=m;c[b+1888>>2]=41;c[b+1892>>2]=42;if((m|0)<=2){o=0;i=d;return o|0}k=+h[b+40>>3];if(k<=0.0){o=1;i=d;return o|0}j=(m|0)>0;a:do{if(j){l=k;g=0;p=0.0;while(1){q=+(g|0)*3.141592653589793/180.0;r=0.0;f=m;do{r=q*r+ +(f|0)*+h[b+(f<<3)+32>>3];f=f+ -1|0}while((f|0)>0);f=g+1|0;if(r<=0.0){s=l;t=r;u=g;v=p;w=q;break a}if((f|0)<180){l=r;g=f;p=q}else{s=r;t=r;u=f;v=q;w=q;break}}}else{s=k;t=0.0;u=0;v=0.0;w=0.0}}while(0);b:do{if((u|0)==180){x=3.141592653589793}else{if(j){y=s;z=t;A=1;B=v;C=w}else{x=v-s*(w-v)/(t-s);break}while(1){k=B-y*(C-B)/(z-y);p=0.0;g=m;do{p=k*p+ +(g|0)*+h[b+(g<<3)+32>>3];g=g+ -1|0}while((g|0)>0);if(+P(+p)<1.0e-13){x=k;break b}g=p<0.0;f=A+1|0;if((f|0)<11){y=g?y:p;z=g?p:z;A=f;B=g?B:k;C=g?k:C}else{x=k;break}}}}while(0);if((m|0)>-1){A=m;C=0.0;while(1){B=x*C+ +h[b+(A<<3)+32>>3];if((A|0)>0){A=A+ -1|0;C=B}else{D=B;break}}}else{D=0.0}h[b+112>>3]=x;h[b+120>>3]=D;o=0;i=d;return o|0}function Ld(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0;d=i;a[b]=5263171;a[b+1|0]=20559;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-1002)+501;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+Se(f);h[b+112>>3]=j;if(j==0.0){k=1;i=d;return k|0}h[b+120>>3]=1.0/j;j=+h[g>>3];f=j*+Re(+h[b+48>>3]);g=b+136|0;h[g>>3]=f;if(f==0.0){k=1;i=d;return k|0}h[b+144>>3]=1.0/f;f=1.0/+Te(+h[e>>3]);h[b+152>>3]=f;h[b+128>>3]=f*+h[g>>3];c[b+1888>>2]=43;c[b+1892>>2]=44;k=0;i=d;return k|0}function Md(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0;d=i;a[b]=4542275;a[b+1|0]=17743;a[b+2|0]=69;a[b+3|0]=0;c[b+4>>2]=502;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+h[b+48>>3];k=f-j;l=f+j;j=+Se(k);f=(j+ +Se(l))*.5;m=b+112|0;h[m>>3]=f;if(f==0.0){n=1;i=d;return n|0}h[b+120>>3]=1.0/f;o=b+136|0;h[o>>3]=+h[g>>3]/f;f=+Se(k);k=f*+Se(l)+1.0;h[b+144>>3]=k;l=+h[m>>3]*2.0;h[b+152>>3]=l;f=+h[o>>3];h[b+160>>3]=f*f*k;h[b+168>>3]=1.0/(+h[g>>3]*2.0*f);h[b+176>>3]=f*+Q(+(k+l));h[b+128>>3]=f*+Q(+(k-l*+Se(+h[e>>3])));c[b+1888>>2]=45;c[b+1892>>2]=46;n=0;i=d;return n|0}function Nd(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0,m=0,n=0.0,o=0;d=i;a[b]=4476739;a[b+1|0]=17487;a[b+2|0]=68;a[b+3|0]=0;c[b+4>>2]=503;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;j=+h[g>>3];if(j==0.0){h[g>>3]=57.29577951308232;k=57.29577951308232}else{k=j}l=b+48|0;m=+h[l>>3]==0.0;j=k*+Se(f);if(m){f=j*3.141592653589793/180.0;h[b+112>>3]=f;n=f}else{f=j*+Se(+h[l>>3]);j=f/+h[l>>3];h[b+112>>3]=j;n=j}if(n==0.0){o=1;i=d;return o|0}h[b+120>>3]=1.0/n;n=+h[g>>3];j=n*+Re(+h[l>>3]);n=j*+Re(+h[e>>3]);j=n/+h[b+112>>3];h[b+128>>3]=j;h[b+136>>3]=j+ +h[e>>3];c[b+1888>>2]=47;c[b+1892>>2]=48;o=0;i=d;return o|0}function Od(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0;d=i;a[b]=5197635;a[b+1|0]=20303;a[b+2|0]=79;a[b+3|0]=0;c[b+4>>2]=504;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+h[b+48>>3];k=f-j;l=f+j;j=+Te((90.0-k)*.5);f=+Re(k);if(k==l){m=+Se(k);h[b+112>>3]=m;n=m}else{m=+Te((90.0-l)*.5);k=+_(+(+Re(l)/f))/+_(+(m/j));h[b+112>>3]=k;n=k}if(n==0.0){o=1;i=d;return o|0}h[b+120>>3]=1.0/n;k=+h[g>>3]*(f/n)/+R(+j,+n);g=b+136|0;h[g>>3]=k;if(k==0.0){o=1;i=d;return o|0}n=+Te((90.0- +h[e>>3])*.5);h[b+128>>3]=k*+R(+n,+(+h[b+112>>3]));h[b+144>>3]=1.0/+h[g>>3];c[b+1888>>2]=49;c[b+1892>>2]=50;o=0;i=d;return o|0}function Pd(b){b=b|0;var d=0,e=0,f=0,g=0.0,j=0.0,k=0.0,l=0,m=0;d=i;a[b]=5132098;a[b+1|0]=20047;a[b+2|0]=78;a[b+3|0]=0;c[b+4>>2]=601;e=b+8|0;f=b+24|0;c[e+0>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;g=+h[f>>3];if(g==0.0){h[f>>3]=57.29577951308232;h[b+120>>3]=1.0;f=b+40|0;j=+Re(+h[f>>3])*57.29577951308232;k=j/+Se(+h[f>>3]);h[b+128>>3]=k+ +h[f>>3];l=b+1888|0;c[l>>2]=51;m=b+1892|0;c[m>>2]=52;i=d;return 0}else{h[b+120>>3]=g*3.141592653589793/180.0;f=b+40|0;k=+Re(+h[f>>3]);j=k/+Se(+h[f>>3]);h[b+128>>3]=g*(j+ +h[f>>3]*3.141592653589793/180.0);l=b+1888|0;c[l>>2]=51;m=b+1892|0;c[m>>2]=52;i=d;return 0}return 0}function Qd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=101?(Id(d)|0)!=0:0){l=1;i=g;return l|0}m=+Re(a);n=+Re(b);o=m*+h[d+120>>3];k=d+40|0;p=+h[k>>3];q=n*o+(p+ +Se(b));if(q==0.0){l=2;i=g;return l|0}p=n*+h[d+112>>3]/q;h[e>>3]=p*+Se(a);h[f>>3]=-(m*p*+h[d+128>>3]);if((c[j>>2]|0)>0){if(+h[d+152>>3]>b){l=2;i=g;return l|0}if(+h[d+168>>3]>0.0?(p=+h[k>>3]/+Q(+(o*o+1.0)),+P(+p)<=1.0):0){m=+We(-o);o=+Ve(p);p=m-o;a=m+o+180.0;if(p>90.0){r=p+-360.0}else{r=p}if(a>90.0){s=a+-360.0}else{s=a}if((r>s?r:s)>b){l=2;i=g;return l|0}}}l=0;i=g;return l|0}function Rd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=101?(Id(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+136>>3]*b;m=+Q(+(a*a+l*l));if(m==0.0){h[e>>3]=0.0;n=90.0}else{h[e>>3]=+Xe(a,-l);l=m/(+h[d+112>>3]+ +h[d+144>>3]*b);b=l*+h[d+40>>3]/+Q(+(l*l+1.0));m=+Xe(1.0,l);if(+P(+b)>1.0){l=b<0.0?-90.0:90.0;if(+P(+l)>1.0000000000001){k=2;i=g;return k|0}else{o=l}}else{o=+Ve(b)}b=m-o;l=m+o+180.0;if(b>90.0){p=b+-360.0}else{p=b}if(l>90.0){q=l+-360.0}else{q=l}n=p>q?p:q}h[f>>3]=n;k=0;i=g;return k|0}function Sd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=102?(Jd(d)|0)!=0:0){l=1;i=g;return l|0}m=+Re(a);n=+Se(a);a=+Re(b);o=1.0- +Se(b);k=d+136|0;p=+h[k>>3]-o;if(p==0.0){l=2;i=g;return l|0}q=d+160|0;h[e>>3]=(n*a*+h[q>>3]-o*+h[d+144>>3])/p;h[f>>3]=-(m*a*+h[q>>3]+o*+h[d+152>>3])/p;if((c[j>>2]|0)>0){if(+h[d+176>>3]>b){l=2;i=g;return l|0}if(+P(+(+h[d+40>>3]))>1.0?(p=n*+h[d+120>>3]-m*+h[d+128>>3],m=1.0/+Q(+(+h[d+168>>3]+p*p)),+P(+m)<=1.0):0){n=+Xe(p,+h[k>>3]+-1.0);p=+Ve(m);m=n-p;o=n+p+180.0;if(m>90.0){r=m+-360.0}else{r=m}if(o>90.0){s=o+-360.0}else{s=o}if((r>s?r:s)>b){l=2;i=g;return l|0}}}l=0;i=g;return l|0}function Td(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=102?(Jd(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+112>>3];m=l*a;a=l*b;b=m*m+a*a;l=+h[d+136>>3];n=(m- +h[d+120>>3])/l;o=(a- +h[d+128>>3])/l;l=m*n+a*o;do{if(!(b<1.0e-10)){p=n*n+o*o;q=p+1.0;r=l-p;s=r*r-q*(p+(b-l-l)+-1.0);if(s<0.0){k=2;i=g;return k|0}p=+Q(+s);s=(p-r)/q;t=(-r-p)/q;q=s>t?s:t;if(q>1.0){if(q+-1.0<1.0e-13){u=1.0}else{u=s-1.0e-13?-1.0:u;if(q>1.0|q<-1.0){k=2;i=g;return k|0}else{h[f>>3]=+Ve(q);v=1.0-q;break}}else{h[f>>3]=90.0- +Q(+(b/(l+1.0)))*57.29577951308232;v=b*.5}}while(0);h[e>>3]=+Xe(m-n*v,-(a-o*v));k=0;i=g;return k|0}function Ud(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+16|0;k=j;l=e+4|0;m=c[l>>2]|0;if((((m|0)>-1?m:0-m|0)|0)!=103){a[e]=5128532;a[e+1|0]=20033;a[e+2|0]=78;a[e+3|0]=0;c[l>>2]=(m>>31&-206)+103;h[e+8>>3]=0.0;h[e+16>>3]=90.0;m=e+24|0;if(+h[m>>3]==0.0){h[m>>3]=57.29577951308232}c[e+1888>>2]=1;c[e+1892>>2]=2;m=99;while(1){if(!(+h[e+(m<<3)+280>>3]==0.0)){n=m;break}o=m+ -1|0;if(!(+h[e+(m+100<<3)+280>>3]==0.0)){n=m;break}if((m|0)>0){m=o}else{n=o;break}}c[e+276>>2]=(n|0)<0?0:n}p=+Se(d);if(p<=0.0){i=j;return 2}q=+h[e+24>>3];r=q*+Re(d)/p;h[k>>3]=r*+Se(b);n=k+8|0;h[n>>3]=-(r*+Re(b));m=c[e+1880>>2]|0;if((m|0)==0){s=+h[k>>3]}else{s=+sd(m,k)}h[f>>3]=s;f=c[e+1884>>2]|0;if((f|0)==0){t=+h[n>>3];h[g>>3]=t;u=c[l>>2]|0;v=(u|0)>0;w=p<0.0;x=v&w;y=x?2:0;i=j;return y|0}else{t=+sd(f,k);h[g>>3]=t;u=c[l>>2]|0;v=(u|0)>0;w=p<0.0;x=v&w;y=x?2:0;i=j;return y|0}return 0}function Vd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0;j=i;i=i+16|0;k=j+8|0;l=j;m=e+4|0;n=c[m>>2]|0;if((((n|0)>-1?n:0-n|0)|0)==103){o=c[e+276>>2]|0}else{a[e]=5128532;a[e+1|0]=20033;a[e+2|0]=78;a[e+3|0]=0;c[m>>2]=(n>>31&-206)+103;h[e+8>>3]=0.0;h[e+16>>3]=90.0;n=e+24|0;if(+h[n>>3]==0.0){h[n>>3]=57.29577951308232}c[e+1888>>2]=1;c[e+1892>>2]=2;n=99;while(1){if(!(+h[e+(n<<3)+280>>3]==0.0)){p=n;break}m=n+ -1|0;if(!(+h[e+(n+100<<3)+280>>3]==0.0)){p=n;break}if((n|0)>0){n=m}else{p=m;break}}n=(p|0)<0?0:p;c[e+276>>2]=n;o=n}if((o|0)==0){h[k>>3]=b;h[l>>3]=d;q=b;r=d}else{Wd(e,b,d,k,l)|0;q=+h[k>>3];r=+h[l>>3]}d=+Q(+(q*q+r*r));if(d==0.0){s=0.0;h[f>>3]=s;t=e+24|0;u=+h[t>>3];v=+Xe(u,d);h[g>>3]=v;i=j;return 0}s=+Xe(q,-r);h[f>>3]=s;t=e+24|0;u=+h[t>>3];v=+Xe(u,d);h[g>>3]=v;i=j;return 0}function Wd(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,P=0.0,R=0.0,S=0.0,T=0.0,U=0.0,V=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0,va=0.0,wa=0.0,xa=0.0,ya=0.0,za=0.0,Aa=0.0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0.0,Fa=0.0,Ga=0.0,Ha=0.0,Ia=0.0,Ja=0.0,Ka=0.0,La=0.0,Ma=0.0,Na=0.0,Oa=0.0,Pa=0.0;g=i;j=c[a+276>>2]|0;k=+h[a+1080>>3]+ +h[a+1088>>3]*b;l=+h[a+280>>3]+ +h[a+288>>3]*d;if((j|0)!=1){m=k+ +h[a+1096>>3]*d;n=l+ +h[a+296>>3]*b;if((j|0)!=2){o=b*b;p=d*d;q=+Q(+(o+p));r=m+q*+h[a+1104>>3];s=n+q*+h[a+304>>3];if((j|0)!=3){t=r+o*+h[a+1112>>3];u=s+p*+h[a+312>>3];if((j|0)!=4){v=b*d;w=t+v*+h[a+1120>>3];x=u+v*+h[a+320>>3];if((j|0)!=5){v=w+p*+h[a+1128>>3];y=x+o*+h[a+328>>3];if((j|0)!=6){z=o*b;A=v+z*+h[a+1136>>3];B=p*d;C=y+B*+h[a+336>>3];if((j|0)!=7){D=A+o*+h[a+1144>>3]*d;E=C+p*+h[a+344>>3]*b;if((j|0)!=8){F=D+p*+h[a+1152>>3]*b;G=E+o*+h[a+352>>3]*d;if((j|0)!=9){H=F+B*+h[a+1160>>3];I=G+z*+h[a+360>>3];if((j|0)!=10){J=q*q*q;K=H+J*+h[a+1168>>3];L=I+J*+h[a+368>>3];if((j|0)!=11){M=o*o;N=K+M*+h[a+1176>>3];O=p*p;P=L+O*+h[a+376>>3];if((j|0)!=12){R=N+z*+h[a+1184>>3]*d;S=P+B*+h[a+384>>3]*b;if((j|0)!=13){T=R+p*o*+h[a+1192>>3];U=S+p*o*+h[a+392>>3];if((j|0)!=14){V=T+B*+h[a+1200>>3]*b;W=U+z*+h[a+400>>3]*d;if((j|0)!=15){X=V+O*+h[a+1208>>3];Y=W+M*+h[a+408>>3];if((j|0)!=16){Z=M*b;_=X+Z*+h[a+1216>>3];$=O*d;aa=Y+$*+h[a+416>>3];if((j|0)!=17){ba=_+M*+h[a+1224>>3]*d;ca=aa+O*+h[a+424>>3]*b;if((j|0)!=18){da=ba+p*z*+h[a+1232>>3];ea=ca+o*B*+h[a+432>>3];if((j|0)!=19){fa=da+B*o*+h[a+1240>>3];ga=ea+z*p*+h[a+440>>3];if((j|0)!=20){ha=fa+O*+h[a+1248>>3]*b;ia=ga+M*+h[a+448>>3]*d;if((j|0)!=21){ja=ha+$*+h[a+1256>>3];ka=ia+Z*+h[a+456>>3];if((j|0)!=22){la=q*q*J;J=ja+la*+h[a+1264>>3];ma=ka+la*+h[a+464>>3];if((j|0)!=23){na=Z*b;oa=J+na*+h[a+1272>>3];pa=$*d;qa=ma+pa*+h[a+472>>3];if((j|0)!=24){ra=oa+Z*+h[a+1280>>3]*d;sa=qa+$*+h[a+480>>3]*b;if((j|0)!=25){ta=ra+p*M*+h[a+1288>>3];ua=sa+o*O*+h[a+488>>3];if((j|0)!=26){va=ta+B*z*+h[a+1296>>3];wa=ua+z*B*+h[a+496>>3];if((j|0)!=27){xa=va+O*o*+h[a+1304>>3];ya=wa+M*p*+h[a+504>>3];if((j|0)!=28){za=xa+$*+h[a+1312>>3]*b;Aa=ya+Z*+h[a+512>>3]*d;if((j|0)!=29){Ba=za+pa*+h[a+1320>>3];Ca=Aa+na*+h[a+520>>3];if((j|0)!=30){Da=na*b;Ea=Ba+Da*+h[a+1328>>3];Fa=pa*d;Ga=Ca+Fa*+h[a+528>>3];if((j|0)!=31){Ha=Ea+na*+h[a+1336>>3]*d;Ia=Ga+pa*+h[a+536>>3]*b;if((j|0)!=32){Ja=Ha+p*Z*+h[a+1344>>3];Ka=Ia+o*$*+h[a+544>>3];if((j|0)!=33){La=Ja+B*M*+h[a+1352>>3];Ma=Ka+z*O*+h[a+552>>3];if((j|0)!=34){Na=La+O*z*+h[a+1360>>3];z=Ma+M*B*+h[a+560>>3];if((j|0)!=35){B=Na+$*o*+h[a+1368>>3];o=z+Z*p*+h[a+568>>3];if((j|0)!=36){p=B+pa*+h[a+1376>>3]*b;b=o+na*+h[a+576>>3]*d;if((j|0)!=37){d=p+Fa*+h[a+1384>>3];Fa=b+Da*+h[a+584>>3];if((j|0)==38){Oa=d;Pa=Fa}else{Da=q*q*la;Oa=d+Da*+h[a+1392>>3];Pa=Fa+Da*+h[a+592>>3]}}else{Oa=p;Pa=b}}else{Oa=B;Pa=o}}else{Oa=Na;Pa=z}}else{Oa=La;Pa=Ma}}else{Oa=Ja;Pa=Ka}}else{Oa=Ha;Pa=Ia}}else{Oa=Ea;Pa=Ga}}else{Oa=Ba;Pa=Ca}}else{Oa=za;Pa=Aa}}else{Oa=xa;Pa=ya}}else{Oa=va;Pa=wa}}else{Oa=ta;Pa=ua}}else{Oa=ra;Pa=sa}}else{Oa=oa;Pa=qa}}else{Oa=J;Pa=ma}}else{Oa=ja;Pa=ka}}else{Oa=ha;Pa=ia}}else{Oa=fa;Pa=ga}}else{Oa=da;Pa=ea}}else{Oa=ba;Pa=ca}}else{Oa=_;Pa=aa}}else{Oa=X;Pa=Y}}else{Oa=V;Pa=W}}else{Oa=T;Pa=U}}else{Oa=R;Pa=S}}else{Oa=N;Pa=P}}else{Oa=K;Pa=L}}else{Oa=H;Pa=I}}else{Oa=F;Pa=G}}else{Oa=D;Pa=E}}else{Oa=A;Pa=C}}else{Oa=v;Pa=y}}else{Oa=w;Pa=x}}else{Oa=t;Pa=u}}else{Oa=r;Pa=s}}else{Oa=m;Pa=n}}else{Oa=k;Pa=l}h[e>>3]=Oa;h[f>>3]=Pa;i=g;return 0}function Xd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0,o=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=104){a[e]=4674643;a[e+1|0]=18260;a[e+2|0]=71;a[e+3|0]=0;c[k>>2]=104;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=3;c[e+1892>>2]=4}m=+Se(d)+1.0;if(m==0.0){n=2;i=j;return n|0}l=+h[e+112>>3];o=l*+Re(d)/m;h[f>>3]=o*+Se(b);h[g>>3]=-(o*+Re(b));n=0;i=j;return n|0}function Yd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=104){a[e]=4674643;a[e+1|0]=18260;a[e+2|0]=71;a[e+3|0]=0;c[k>>2]=104;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=3;c[e+1892>>2]=4}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0;h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=+We(q);s=r*2.0;t=90.0-s;h[g>>3]=t;i=j;return 0}n=+Xe(b,-d);h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=+We(q);s=r*2.0;t=90.0-s;h[g>>3]=t;i=j;return 0}function Zd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0;j=i;k=e+4|0;l=c[k>>2]|0;if((((l|0)>-1?l:0-l|0)|0)!=105){a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;c[k>>2]=(l>>31&-210)+105;h[e+8>>3]=0.0;h[e+16>>3]=90.0;l=e+24|0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;n=57.29577951308232}else{n=m}h[e+112>>3]=1.0/n;n=+h[e+40>>3];m=+h[e+48>>3];o=n*n+m*m;h[e+120>>3]=o;h[e+128>>3]=o+1.0;h[e+136>>3]=o+-1.0;c[e+1888>>2]=5;c[e+1892>>2]=6}o=(90.0- +P(+d))*3.141592653589793/180.0;if(o<1.0e-5){m=o*o*.5;if(d>0.0){p=o;q=m}else{p=o;q=2.0-m}}else{m=1.0- +Se(d);p=+Re(d);q=m}m=+Re(b);o=+Se(b);l=e+24|0;r=e+40|0;h[f>>3]=+h[l>>3]*(p*o+q*+h[r>>3]);f=e+48|0;h[g>>3]=-(+h[l>>3]*(p*m-q*+h[f>>3]));do{if((c[k>>2]|0)>0){if(+h[e+120>>3]==0.0){if(d<0.0){s=2}else{break}i=j;return s|0}else{if(d<-+We(o*+h[r>>3]-m*+h[f>>3])){s=2}else{break}i=j;return s|0}}}while(0);s=0;i=j;return s|0}function _d(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0;j=i;k=e+4|0;l=c[k>>2]|0;if((((l|0)>-1?l:0-l|0)|0)==105){m=+h[e+112>>3];n=+h[e+120>>3]}else{a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;c[k>>2]=(l>>31&-210)+105;h[e+8>>3]=0.0;h[e+16>>3]=90.0;l=e+24|0;o=+h[l>>3];if(o==0.0){h[l>>3]=57.29577951308232;p=57.29577951308232}else{p=o}o=1.0/p;h[e+112>>3]=o;p=+h[e+40>>3];q=+h[e+48>>3];r=p*p+q*q;h[e+120>>3]=r;h[e+128>>3]=r+1.0;h[e+136>>3]=r+-1.0;c[e+1888>>2]=5;c[e+1892>>2]=6;m=o;n=r}r=m*b;b=m*d;d=r*r+b*b;if(n==0.0){if(d!=0.0){s=+Xe(r,-b)}else{s=0.0}h[f>>3]=s;if(d<.5){h[g>>3]=+Ue(+Q(+d));t=0;i=j;return t|0}if(!(d<=1.0)){t=2;i=j;return t|0}h[g>>3]=+Ve(+Q(+(1.0-d)));t=0;i=j;return t|0}l=e+40|0;k=e+48|0;s=r*+h[l>>3]+b*+h[k>>3];do{if(!(d<1.0e-10)){m=+h[e+128>>3];o=s-n;q=o*o-m*(d-s-s+ +h[e+136>>3]);if(q<0.0){t=2;i=j;return t|0}p=+Q(+q);q=(p-o)/m;u=(-o-p)/m;m=q>u?q:u;if(m>1.0){if(m+-1.0<1.0e-13){v=1.0}else{v=q-1.0e-13?-1.0:v;if(m>1.0|m<-1.0){t=2;i=j;return t|0}else{h[g>>3]=+Ve(m);w=1.0-m;break}}else{h[g>>3]=90.0- +Q(+(d/(s+1.0)))*57.29577951308232;w=d*.5}}while(0);d=w*+h[k>>3]-b;b=r-w*+h[l>>3];if(d==0.0&b==0.0){h[f>>3]=0.0;t=0;i=j;return t|0}else{h[f>>3]=+Xe(b,d);t=0;i=j;return t|0}return 0}function $d(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==106){l=+h[e+112>>3];m=90.0-d;n=m*l;o=+Se(b);p=n*o;h[f>>3]=p;q=+Re(b);r=n*q;s=-r;h[g>>3]=s;i=j;return 0}a[e]=4411969;a[e+1|0]=17234;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=106;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;t=+h[k>>3];if(t==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;u=1.0}else{v=t*3.141592653589793/180.0;h[e+112>>3]=v;h[e+120>>3]=1.0/v;u=v}c[e+1888>>2]=7;c[e+1892>>2]=8;l=u;m=90.0-d;n=m*l;o=+Se(b);p=n*o;h[f>>3]=p;q=+Re(b);r=n*q;s=-r;h[g>>3]=s;i=j;return 0}function ae(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0,p=0.0,q=0.0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=106){a[e]=4411969;a[e+1|0]=17234;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=106;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0}else{m=l*3.141592653589793/180.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=7;c[e+1892>>2]=8}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0;h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=90.0-q;h[g>>3]=r;i=j;return 0}n=+Xe(b,-d);h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=90.0-q;h[g>>3]=r;i=j;return 0}function be(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=107?(Kd(d)|0)!=0:0){l=1;i=g;return l|0}m=(90.0-b)*3.141592653589793/180.0;b=(m*(m*(m*(m*(m*(m*(m*(m*(m*(m*0.0+ +h[d+104>>3])+ +h[d+96>>3])+ +h[d+88>>3])+ +h[d+80>>3])+ +h[d+72>>3])+ +h[d+64>>3])+ +h[d+56>>3])+ +h[d+48>>3])+ +h[d+40>>3])+ +h[d+32>>3])*+h[d+24>>3];h[e>>3]=b*+Se(a);h[f>>3]=-(b*+Re(a));if((c[j>>2]|0)>0?m>+h[d+112>>3]:0){l=2;i=g;return l|0}l=0;i=g;return l|0}function ce(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=107?(Kd(d)|0)!=0:0){k=1;i=g;return k|0}j=c[d+272>>2]|0;l=+Q(+(a*a+b*b));m=l/+h[d+24>>3];if((j|0)<1){k=1;i=g;return k|0}a:do{if((j|0)==2){l=+h[d+48>>3];n=+h[d+40>>3];o=n*n-l*4.0*(+h[d+32>>3]-m);if(o<0.0){k=2;i=g;return k|0}p=+Q(+o);o=l*2.0;l=(p-n)/o;q=(-n-p)/o;o=lq?l:q}else{r=o}if(r<0.0){if(r<-1.0e-13){k=2}else{s=0.0;break}i=g;return k|0}if(r>3.141592653589793){if(r>3.141592653589893){k=2;i=g;return k|0}else{s=3.141592653589793}}else{s=r}}else if((j|0)==1){s=(m- +h[d+32>>3])/+h[d+40>>3]}else{o=+h[d+32>>3];q=+h[d+112>>3];l=+h[d+120>>3];if(ml){if(m>l+1.0e-13){k=2}else{s=q;break}i=g;return k|0}if((j|0)>-1){t=0;u=o;v=l;w=0.0;x=q}else{p=0.0-m;y=0;n=o;o=l;l=0.0;z=q;while(1){q=(o-m)/(o-n);if(!(q<.1)){if(q>.9){A=.9}else{A=q}}else{A=.1}q=z-(z-l)*A;if(m>0.0){if(m<1.0e-13){s=q;break a}else{B=0.0;C=o;D=q;E=z}}else{if(p<1.0e-13){s=q;break a}else{B=n;C=0.0;D=l;E=q}}F=y+1|0;if(!(+P(+(E-D))<1.0e-13)&(F|0)<100){y=F;n=B;o=C;l=D;z=E}else{s=q;break a}}}while(1){z=(v-m)/(v-u);if(!(z<.1)){if(z>.9){G=.9}else{G=z}}else{G=.1}z=x-(x-w)*G;y=j;l=0.0;while(1){l=z*l+ +h[d+(y<<3)+32>>3];if((y|0)<=0){break}else{y=y+ -1|0}}if(l>3]=L;h[f>>3]=90.0-s*180.0/3.141592653589793;k=0;i=g;return k|0}function de(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==108){l=+h[e+112>>3]}else{a[e]=4277594;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=108;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;m=+h[k>>3];if(m==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648;n=114.59155902616465}else{o=m*2.0;h[e+112>>3]=o;h[e+120>>3]=1.0/o;n=o}c[e+1888>>2]=9;c[e+1892>>2]=10;l=n}n=l*+Se((90.0-d)*.5);h[f>>3]=n*+Se(b);h[g>>3]=-(n*+Re(b));i=j;return 0}function ee(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0;j=i;k=e+4|0;if((c[k>>2]|0)!=108){a[e]=4277594;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=108;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=9;c[e+1892>>2]=10}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0}else{n=+Xe(b,-d)}h[f>>3]=n;n=m*+h[e+120>>3];if(+P(+n)>1.0){if(+P(+(m- +h[e+112>>3]))<1.0e-12){o=-90.0}else{p=2;i=j;return p|0}}else{o=90.0- +Ve(n)*2.0}h[g>>3]=o;p=0;i=j;return p|0}function fe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=109){a[e]=5392705;a[e+1|0]=21065;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=109;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;m=57.29577951308232}else{m=l}l=m*2.0;k=e+112|0;h[k>>3]=l;m=+h[e+40>>3];do{if(!(m==90.0)){if(m>-90.0){n=+Re((90.0-m)*.5);o=n*n;p=+_(+n)*o/(1.0-o);h[e+120>>3]=p;o=.5-p;h[e+128>>3]=o;q=o;r=+h[k>>3];break}else{s=1;i=j;return s|0}}else{h[e+120>>3]=-.5;h[e+128>>3]=1.0;q=1.0;r=l}}while(0);h[e+136>>3]=q*r;h[e+144>>3]=1.0e-4;h[e+152>>3]=q*1.0e-4;h[e+160>>3]=57.29577951308232/q;c[e+1888>>2]=11;c[e+1892>>2]=12}do{if(!(d==90.0)){if(!(d>-90.0)){s=2;i=j;return s|0}q=90.0-d;r=q*.017453292519943295*.5;if(r<+h[e+144>>3]){t=r*+h[e+136>>3];break}else{r=+Re(q*.5);q=+Q(+(1.0-r*r))/r;l=+_(+r)/q;t=-(+h[e+112>>3]*(l+q*+h[e+120>>3]));break}}else{t=0.0}}while(0);h[f>>3]=t*+Se(b);h[g>>3]=-(t*+Re(b));s=0;i=j;return s|0}function ge(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0,A=0.0,B=0.0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==109){l=+h[e+112>>3]}else{a[e]=5392705;a[e+1|0]=21065;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=109;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;m=+h[k>>3];if(m==0.0){h[k>>3]=57.29577951308232;n=57.29577951308232}else{n=m}m=n*2.0;k=e+112|0;h[k>>3]=m;n=+h[e+40>>3];do{if(!(n==90.0)){if(n>-90.0){o=+Re((90.0-n)*.5);p=o*o;q=+_(+o)*p/(1.0-p);h[e+120>>3]=q;p=.5-q;h[e+128>>3]=p;r=p;s=+h[k>>3];break}else{t=1;i=j;return t|0}}else{h[e+120>>3]=-.5;h[e+128>>3]=1.0;r=1.0;s=m}}while(0);h[e+136>>3]=r*s;h[e+144>>3]=1.0e-4;h[e+152>>3]=r*1.0e-4;h[e+160>>3]=57.29577951308232/r;c[e+1888>>2]=11;c[e+1892>>2]=12;l=s}s=+Q(+(b*b+d*d))/l;if(s==0.0){u=0.0;v=0.0}else{do{if(!(s<+h[e+152>>3])){l=+h[e+120>>3];k=0;r=0.0;m=1.0;while(1){w=m*.5;n=+Q(+(1.0-w*w))/w;x=-(+_(+w)/n+n*l);y=k+1|0;if(s<=x){z=k;A=r;B=m;break}if((y|0)<30){k=y;r=x;m=w}else{z=y;A=x;B=w;break}}if((z|0)==30){t=2;i=j;return t|0}else{C=0;D=A;E=x;F=B;G=w}while(1){m=(E-s)/(E-D);if(!(m<.1)){if(m>.9){H=.9}else{H=m}}else{H=.1}I=G-(G-F)*H;m=+Q(+(1.0-I*I))/I;r=+_(+I)/m+m*l;m=-r;if(s>m){if(s+r<1.0e-12){J=C;break}else{K=m;L=E;M=I;N=G}}else{if(m-s<1.0e-12){J=C;break}else{K=D;L=m;M=F;N=I}}k=C+1|0;if((k|0)<100){C=k;D=K;E=L;F=M;G=N}else{J=k;break}}if((J|0)==100){t=2;i=j;return t|0}else{O=+Ue(I);break}}else{O=s*+h[e+160>>3]}}while(0);u=+Xe(b,-d);v=O}h[f>>3]=u;h[g>>3]=90.0-v*2.0;t=0;i=j;return t|0}function he(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==201){l=+h[e+40>>3]}else{a[e]=5265731;a[e+1|0]=20569;a[e+2|0]=80;a[e+3|0]=0;c[k>>2]=201;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;o=+h[e+48>>3];h[e+112>>3]=o;if(o==0.0){p=1;i=j;return p|0}h[e+120>>3]=1.0/o;q=+h[e+40>>3];r=(o+q)*57.29577951308232;h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=q;break}}else{q=+h[e+48>>3];r=n*q*3.141592653589793/180.0;h[e+112>>3]=r;if(r==0.0){p=1;i=j;return p|0}h[e+120>>3]=1.0/r;r=+h[e+40>>3];o=n*(q+r);h[e+128>>3]=o;if(o==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/o;s=r;break}}}while(0);c[e+1888>>2]=13;c[e+1892>>2]=14;l=s}s=l+ +Re(d);if(s==0.0){p=2;i=j;return p|0}h[f>>3]=+h[e+112>>3]*b;b=+h[e+128>>3];h[g>>3]=b*+Se(d)/s;p=0;i=j;return p|0}function ie(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==201){l=+h[e+120>>3]}else{a[e]=5265731;a[e+1|0]=20569;a[e+2|0]=80;a[e+3|0]=0;c[k>>2]=201;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;o=+h[e+48>>3];h[e+112>>3]=o;if(o==0.0){p=1;i=j;return p|0}q=1.0/o;h[e+120>>3]=q;r=(o+ +h[e+40>>3])*57.29577951308232;h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=q;break}}else{q=+h[e+48>>3];r=n*q*3.141592653589793/180.0;h[e+112>>3]=r;if(r==0.0){p=1;i=j;return p|0}o=1.0/r;h[e+120>>3]=o;r=n*(q+ +h[e+40>>3]);h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=o;break}}}while(0);c[e+1888>>2]=13;c[e+1892>>2]=14;l=s}h[f>>3]=l*b;b=+h[e+136>>3]*d;d=+Xe(b,1.0);h[g>>3]=d+ +Ve(b*+h[e+40>>3]/+Q(+(b*b+1.0)));p=0;i=j;return p|0}function je(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==202){l=+h[e+112>>3]}else{a[e]=4277571;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=202;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=+h[e+40>>3];if(o<=0.0|o>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=57.29577951308232/o;h[e+136>>3]=o/57.29577951308232;q=1.0;break}}else{o=n*3.141592653589793/180.0;h[e+112>>3]=o;h[e+120>>3]=57.29577951308232/n;r=+h[e+40>>3];if(r<=0.0|r>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=n/r;h[e+136>>3]=r/n;q=o;break}}}while(0);c[e+1888>>2]=15;c[e+1892>>2]=16;l=q}h[f>>3]=l*b;b=+h[e+128>>3];h[g>>3]=b*+Se(d);p=0;i=j;return p|0}function ke(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==202){l=+h[e+136>>3]}else{a[e]=4277571;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=202;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=+h[e+40>>3];if(o<=0.0|o>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=57.29577951308232/o;q=o/57.29577951308232;h[e+136>>3]=q;r=q;break}}else{h[e+112>>3]=n*3.141592653589793/180.0;h[e+120>>3]=57.29577951308232/n;q=+h[e+40>>3];if(q<=0.0|q>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=n/q;o=q/n;h[e+136>>3]=o;r=o;break}}}while(0);c[e+1888>>2]=15;c[e+1892>>2]=16;l=r}r=l*d;d=+P(+r);do{if(d>1.0){if(d>1.0000000000001){p=2;i=j;return p|0}else{s=r<0.0?-1.0:1.0;break}}else{s=r}}while(0);h[f>>3]=+h[e+120>>3]*b;h[g>>3]=+Ve(s);p=0;i=j;return p|0}function le(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==203){l=e+112|0;m=l;n=+h[l>>3];o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}a[e]=5390659;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=203;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;r=+h[l>>3];if(r==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;s=1.0}else{t=r*3.141592653589793/180.0;h[e+112>>3]=t;h[e+120>>3]=1.0/t;s=t}c[e+1888>>2]=17;c[e+1892>>2]=18;m=e+112|0;n=s;o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}function me(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==203){l=e+120|0;m=l;n=+h[l>>3];o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}a[e]=5390659;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=203;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;r=+h[l>>3];if(r==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;s=1.0}else{t=r*3.141592653589793/180.0;h[e+112>>3]=t;r=1.0/t;h[e+120>>3]=r;s=r}c[e+1888>>2]=17;c[e+1892>>2]=18;m=e+120|0;n=s;o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}function ne(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0;j=i;k=e+4|0;if((c[k>>2]|0)!=204){a[e]=5391693;a[e+1|0]=21061;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=204;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0}else{n=m*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=19;c[e+1892>>2]=20}if(d<=-90.0|d>=90.0){o=2;i=j;return o|0}h[f>>3]=+h[e+112>>3]*b;b=+h[e+24>>3];h[g>>3]=b*+_(+(+Te((d+90.0)*.5)));o=0;i=j;return o|0}function oe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0,o=0.0,p=0.0,q=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==204){l=e+24|0;m=+h[e+120>>3]}else{a[e]=5391693;a[e+1|0]=21061;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=204;k=e+8|0;n=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;o=+h[n>>3];if(o==0.0){h[n>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;p=1.0}else{q=o*3.141592653589793/180.0;h[e+112>>3]=q;o=1.0/q;h[e+120>>3]=o;p=o}c[e+1888>>2]=19;c[e+1892>>2]=20;l=n;m=p}h[f>>3]=m*b;h[g>>3]=+We(+Z(+(d/+h[l>>3])))*2.0+-90.0;i=j;return 0}function pe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==301){l=e+112|0;m=l;n=+h[l>>3];o=n*b;p=+Re(d);q=o*p;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;t=+h[l>>3];if(t==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;u=1.0}else{v=t*3.141592653589793/180.0;h[e+112>>3]=v;h[e+120>>3]=1.0/v;u=v}c[e+1888>>2]=21;c[e+1892>>2]=22;m=e+112|0;n=u;o=n*b;p=+Re(d);q=o*p;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}function qe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==301){l=+h[e+24>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=57.29577951308232}else{p=n*3.141592653589793/180.0;h[e+112>>3]=p;h[e+120>>3]=1.0/p;o=n}c[e+1888>>2]=21;c[e+1892>>2]=22;l=o}o=+S(+(d/l));m=e+120|0;if(o==0.0){q=0.0;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}q=+h[m>>3]*b/o;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}function re(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=302){a[e]=5390672;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=302;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=180.0;h[e+136>>3]=.005555555555555556}else{n=m*3.141592653589793;m=n/180.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m;h[e+128>>3]=n;h[e+136>>3]=1.0/n}c[e+1888>>2]=23;c[e+1892>>2]=24}n=+Se(d/3.0);h[f>>3]=+h[e+112>>3]*b*(1.0-n*n*4.0);h[g>>3]=n*+h[e+128>>3];i=j;return 0}function se(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==302){l=+h[e+136>>3]}else{a[e]=5390672;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=302;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=180.0;h[e+136>>3]=.005555555555555556;o=.005555555555555556}else{p=n*3.141592653589793;n=p/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;h[e+128>>3]=p;n=1.0/p;h[e+136>>3]=n;o=n}c[e+1888>>2]=23;c[e+1892>>2]=24;l=o}o=l*d;if(o>1.0|o<-1.0){q=2;i=j;return q|0}d=1.0-o*o*4.0;if(d==0.0){if(b==0.0){r=0.0}else{q=2;i=j;return q|0}}else{r=+h[e+120>>3]*b/d}h[f>>3]=r;h[g>>3]=+Ve(o)*3.0;q=0;i=j;return q|0}function te(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=303){a[e]=5001037;a[e+1|0]=19535;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=303;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;n=57.29577951308232}else{n=m}m=n*1.4142135623730951;h[e+112>>3]=m;h[e+120>>3]=m/90.0;h[e+128>>3]=1.0/m;h[e+136>>3]=90.0/n;h[e+144>>3]=.6366197723675814;c[e+1888>>2]=25;c[e+1892>>2]=26}if(+P(+d)==90.0){h[f>>3]=0.0;n=+P(+(+h[e+112>>3]));if(d<0.0){o=-n}else{o=n}h[g>>3]=o;i=j;return 0}if(d==0.0){h[f>>3]=+h[e+120>>3]*b;h[g>>3]=0.0;i=j;return 0}o=+Se(d)*3.141592653589793;l=0;d=o;n=-3.141592653589793;m=3.141592653589793;while(1){p=d-o+ +T(+d);if(p<0.0){if(p>-1.0e-13){q=d;break}else{r=d;s=m}}else{if(p<1.0e-13){q=d;break}else{r=n;s=d}}p=(r+s)*.5;k=l+1|0;if((k|0)<100){l=k;d=p;n=r;m=s}else{q=p;break}}s=q*.5;h[f>>3]=+h[e+120>>3]*b*+S(+s);h[g>>3]=+h[e+112>>3]*+T(+s);i=j;return 0}function ue(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==303){l=+h[e+24>>3]}else{a[e]=5001037;a[e+1|0]=19535;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=303;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;o=57.29577951308232}else{o=n}n=o*1.4142135623730951;h[e+112>>3]=n;h[e+120>>3]=n/90.0;h[e+128>>3]=1.0/n;h[e+136>>3]=90.0/o;h[e+144>>3]=.6366197723675814;c[e+1888>>2]=25;c[e+1892>>2]=26;l=o}o=d/l;l=2.0-o*o;if(l<=1.0e-12){if(l<-1.0e-12){p=2;i=j;return p|0}if(+P(+b)>1.0e-12){p=2;i=j;return p|0}else{q=0.0;r=0.0}}else{n=+Q(+l);q=n;r=+h[e+136>>3]*b/n}h[f>>3]=r;r=+h[e+128>>3]*d;d=+P(+r);do{if(d>1.0){if(d>1.000000000001){p=2;i=j;return p|0}else{s=(r<0.0?-1.0:1.0)+o*q/3.141592653589793;break}}else{n=+W(+r);s=n*+h[e+144>>3]+o*q/3.141592653589793}}while(0);q=+P(+s);do{if(q>1.0){if(q>1.000000000001){p=2;i=j;return p|0}else{t=s<0.0?-1.0:1.0;break}}else{t=s}}while(0);h[g>>3]=+Ve(t);p=0;i=j;return p|0}function ve(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==401){l=e+112|0}else{a[e]=5523777;a[e+1|0]=21577;a[e+2|0]=84;a[e+3|0]=0;c[k>>2]=401;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;o=57.29577951308232}else{o=n}n=o*2.0;p=o*n;m=e+112|0;h[m>>3]=p;o=1.0/(p*2.0);h[e+120>>3]=o;h[e+128>>3]=o*.25;h[e+136>>3]=1.0/n;c[e+1888>>2]=27;c[e+1892>>2]=28;l=m}n=+Re(d);o=+h[l>>3];p=b*.5;b=+Q(+(o/(n*+Re(p)+1.0)));h[f>>3]=+Se(p)*n*b*2.0;h[g>>3]=b*+Se(d);i=j;return 0}function we(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==401){l=+h[e+128>>3];m=+h[e+120>>3]}else{a[e]=5523777;a[e+1|0]=21577;a[e+2|0]=84;a[e+3|0]=0;c[k>>2]=401;k=e+8|0;n=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;o=+h[n>>3];if(o==0.0){h[n>>3]=57.29577951308232;p=57.29577951308232}else{p=o}o=p*2.0;q=p*o;h[e+112>>3]=q;p=1.0/(q*2.0);h[e+120>>3]=p;q=p*.25;h[e+128>>3]=q;h[e+136>>3]=1.0/o;c[e+1888>>2]=27;c[e+1892>>2]=28;l=q;m=p}p=1.0-b*b*l-d*d*m;if(p<0.0){if(p<-1.0e-13){r=2;i=j;return r|0}else{s=0.0}}else{s=p}p=+Q(+s);s=p*d/+h[e+24>>3];d=+P(+s);do{if(d>1.0){if(d>1.0000000000001){r=2;i=j;return r|0}else{t=s<0.0?-1.0:1.0;break}}else{t=s}}while(0);s=p*p*2.0+-1.0;d=p*b*+h[e+136>>3];if(s==0.0&d==0.0){u=0.0}else{u=+Xe(d,s)*2.0}h[f>>3]=u;h[g>>3]=+Ve(t);r=0;i=j;return r|0}function xe(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0,p=0.0,q=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=501?(Ld(d)|0)!=0:0){l=1;i=g;return l|0}m=b- +h[d+40>>3];b=+Re(m);if(b==0.0){l=2;i=g;return l|0}k=d+112|0;n=+h[k>>3]*a;o=d+128|0;a=+h[o>>3];p=+h[d+136>>3];q=a-p*+Se(m)/b;h[e>>3]=q*+Se(n);b=+h[o>>3];h[f>>3]=b-q*+Re(n);if((c[j>>2]|0)>0?q*+h[k>>3]<0.0:0){l=2;i=g;return l|0}l=0;i=g;return l|0}function ye(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=501?(Ld(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+128>>3]-b;b=+Q(+(a*a+l*l));j=d+40|0;if(+h[j>>3]<0.0){m=-b}else{m=b}if(m==0.0){n=0.0}else{n=+Xe(a/m,l/m)}h[e>>3]=n*+h[d+120>>3];n=+h[j>>3];h[f>>3]=n+ +We(+h[d+152>>3]-m*+h[d+144>>3]);k=0;i=g;return k|0}function ze(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0;g=i;if((c[d+4>>2]|0)!=502?(Md(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+112>>3]*a;if(b==-90.0){l=+h[d+176>>3]}else{a=+h[d+136>>3];m=+h[d+144>>3];n=+h[d+152>>3];l=a*+Q(+(m-n*+Se(b)))}h[e>>3]=l*+Se(k);b=+h[d+128>>3];h[f>>3]=b-l*+Re(k);j=0;i=g;return j|0}function Ae(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0;g=i;if((c[d+4>>2]|0)!=502?(Md(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){m=0.0}else{m=+Xe(a/l,k/l)}h[e>>3]=m*+h[d+120>>3];if(+P(+(l- +h[d+176>>3]))<1.0e-12){h[f>>3]=-90.0;j=0;i=g;return j|0}m=(+h[d+160>>3]-l*l)*+h[d+168>>3];if(!(+P(+m)>1.0)){h[f>>3]=+Ve(m);j=0;i=g;return j|0}if(+P(+(m+-1.0))<1.0e-12){h[f>>3]=90.0;j=0;i=g;return j|0}if(!(+P(+(m+1.0))<1.0e-12)){j=2;i=g;return j|0}h[f>>3]=-90.0;j=0;i=g;return j|0}function Be(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0;g=i;if((c[d+4>>2]|0)!=503?(Nd(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+112>>3]*a;a=+h[d+136>>3]-b;h[e>>3]=a*+Se(k);b=+h[d+128>>3];h[f>>3]=b-a*+Re(k);j=0;i=g;return j|0}function Ce(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0;g=i;if((c[d+4>>2]|0)!=503?(Nd(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){m=0.0}else{m=+Xe(a/l,k/l)}h[e>>3]=m*+h[d+120>>3];h[f>>3]=+h[d+136>>3]-l;j=0;i=g;return j|0}function De(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0;g=i;if((c[d+4>>2]|0)!=504?(Od(d)|0)!=0:0){j=1;i=g;return j|0}k=d+112|0;l=+h[k>>3];m=l*a;if(b==-90.0){if(l<0.0){n=0.0}else{j=2;i=g;return j|0}}else{l=+h[d+136>>3];a=+Te((90.0-b)*.5);n=l*+R(+a,+(+h[k>>3]))}h[e>>3]=n*+Se(m);a=+h[d+128>>3];h[f>>3]=a-n*+Re(m);j=0;i=g;return j|0}function Ee(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0;g=i;if((c[d+4>>2]|0)!=504?(Od(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){h[e>>3]=+h[d+120>>3]*0.0;if(+h[d+112>>3]<0.0){m=-90.0}else{j=2;i=g;return j|0}}else{b=+Xe(a/l,k/l);n=d+120|0;h[e>>3]=b*+h[n>>3];m=90.0- +We(+R(+(l*+h[d+144>>3]),+(+h[n>>3])))*2.0}h[f>>3]=m;j=0;i=g;return j|0}function Fe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0;j=i;k=e+4|0;l=c[k>>2]|0;if(!(+h[e+40>>3]==0.0)){if((l|0)!=601){Pd(e)|0}m=e+128|0;n=+h[m>>3]- +h[e+120>>3]*d;o=+h[e+24>>3]*b;p=o*+Re(d)/n;h[f>>3]=n*+Se(p);o=+h[m>>3];q=o-n*+Re(p);h[g>>3]=q;i=j;return 0}if((l|0)==301){l=e+112|0;r=l;s=+h[l>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;p=+h[l>>3];if(p==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;t=1.0}else{n=p*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;t=n}c[e+1888>>2]=21;c[e+1892>>2]=22;r=e+112|0;s=t}h[f>>3]=s*b*+Re(d);q=+h[r>>3]*d;h[g>>3]=q;i=j;return 0}function Ge(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0;j=i;k=e+40|0;l=+h[k>>3];m=e+4|0;n=c[m>>2]|0;if(l==0.0){if((n|0)==301){o=+h[e+24>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[m>>2]=301;m=e+8|0;p=e+24|0;c[m+0>>2]=0;c[m+4>>2]=0;c[m+8>>2]=0;c[m+12>>2]=0;q=+h[p>>3];if(q==0.0){h[p>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;r=57.29577951308232}else{s=q*3.141592653589793/180.0;h[e+112>>3]=s;h[e+120>>3]=1.0/s;r=q}c[e+1888>>2]=21;c[e+1892>>2]=22;o=r}r=+S(+(d/o));p=e+120|0;if(r==0.0){t=0.0}else{t=+h[p>>3]*b/r}h[f>>3]=t;h[g>>3]=+h[p>>3]*d;i=j;return 0}else{if((n|0)==601){u=l}else{Pd(e)|0;u=+h[k>>3]}k=e+128|0;l=+h[k>>3];t=l-d;d=+Q(+(b*b+t*t));if(u<0.0){v=-d}else{v=d}if(v==0.0){w=l;x=0.0}else{l=+Xe(b/v,t/v);w=+h[k>>3];x=l}l=(w-v)/+h[e+120>>3];h[g>>3]=l;w=+Re(l);if(w==0.0){y=0.0}else{y=x*(v/+h[e+24>>3])/w}h[f>>3]=y;i=j;return 0}return 0}function He(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=602){a[e]=5194576;a[e+1|0]=20291;a[e+2|0]=79;a[e+3|0]=0;c[k>>2]=602;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=114.59155902616465}else{n=m*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;h[e+128>>3]=m*2.0}c[e+1888>>2]=29;c[e+1892>>2]=30}m=+Re(d);n=+Se(d);o=n*b;if(n==0.0){h[f>>3]=+h[e+112>>3]*b;p=0.0;h[g>>3]=p;i=j;return 0}else{b=m/n;l=e+24|0;n=b*+h[l>>3];h[f>>3]=n*+Se(o);n=+h[l>>3];p=n*(d*3.141592653589793/180.0+b*(1.0- +Re(o)));h[g>>3]=p;i=j;return 0}return 0}function Ie(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0,y=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==602){l=+h[e+120>>3]}else{a[e]=5194576;a[e+1|0]=20291;a[e+2|0]=79;a[e+3|0]=0;c[k>>2]=602;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=114.59155902616465;o=1.0}else{p=n*3.141592653589793/180.0;h[e+112>>3]=p;q=1.0/p;h[e+120>>3]=q;h[e+128>>3]=n*2.0;o=q}c[e+1888>>2]=29;c[e+1892>>2]=30;l=o}o=+P(+(l*d));if(o<1.0e-12){h[f>>3]=l*b;h[g>>3]=0.0;i=j;return 0}if(+P(+(o+-90.0))<1.0e-12){h[f>>3]=0.0;h[g>>3]=d<0.0?-90.0:90.0;i=j;return 0}o=d>0.0?90.0:-90.0;l=b*b;m=e+112|0;q=d-o*+h[m>>3];k=e+128|0;n=-999.0;p=l+q*q;r=0;q=0.0;s=o;while(1){if(n<-100.0){t=(q+s)*.5}else{o=p/(p-n);if(!(o<.1)){if(o>.9){u=.9}else{u=o}}else{u=.1}t=s-(s-q)*u}h[g>>3]=t;v=d-t*+h[m>>3];w=+Te(t);o=l+v*(v- +h[k>>3]/w);if(+P(+o)<1.0e-12){break}if(+P(+(s-q))<1.0e-12){break}x=o>0.0;y=+h[g>>3];r=r+1|0;if((r|0)>=64){break}else{n=x?n:o;p=x?o:p;q=x?q:y;s=x?y:s}}s=+h[e+24>>3]-w*v;v=w*b;if(s==0.0&v==0.0){h[f>>3]=0.0;i=j;return 0}else{b=+Xe(v,s);h[f>>3]=b/+Se(+h[g>>3]);i=j;return 0}return 0}function Je(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=701){a[e]=4412244;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=701;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=31;c[e+1892>>2]=32}n=+Re(d);m=n*+Re(b);o=n*+Se(b);b=+Se(d);l=m>b;d=l?m:b;k=o>d;n=k?o:d;d=-m;p=n1.0){if(u>1.000000000001){z=2;i=j;return z|0}else{A=w<0.0?-1.0:1.0;break}}else{A=w}}while(0);w=+P(+y);do{if(w>1.0){if(w>1.000000000001){z=2;i=j;return z|0}else{B=y<0.0?-1.0:1.0;break}}else{B=y}}while(0);l=e+112|0;h[f>>3]=(v+A)*+h[l>>3];h[g>>3]=(x+B)*+h[l>>3];z=0;i=j;return z|0}function Ke(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==701){l=+h[e+120>>3]}else{a[e]=4412244;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=701;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=31;c[e+1892>>2]=32;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){o=r+-4.0;d=-1.0/+Q(+(b*b+(o*o+1.0)));s=d;t=o*d;u=-(b*d);break}if(r>1.0){d=r+-2.0;o=1.0/+Q(+(b*b+(d*d+1.0)));s=-(d*o);t=o;u=b*o;break}if(b>1.0){o=b+-2.0;d=1.0/+Q(+(o*o+(r*r+1.0)));s=-(o*d);t=r*d;u=d;break}if(b<-1.0){d=b+2.0;o=-1.0/+Q(+(d*d+(r*r+1.0)));l=-o;s=d*l;t=r*l;u=o;break}else{o=1.0/+Q(+(b*b+(r*r+1.0)));s=o;t=r*o;u=b*o;break}}else{o=r+-6.0;l=-1.0/+Q(+(b*b+(o*o+1.0)));d=-l;s=o*d;t=l;u=b*d}}while(0);if(s==0.0&t==0.0){v=0.0}else{v=+Xe(t,s)}h[f>>3]=v;h[g>>3]=+Ve(u);q=0;i=j;return q|0}function Le(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0,E=0.0,F=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=702){a[e]=4412227;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=702;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=33;c[e+1892>>2]=34}n=+Re(d);m=n*+Re(b);o=n*+Se(b);b=+Se(d);l=m>b;d=l?m:b;k=o>d;n=k?o:d;d=-m;p=n1.0e-16){A=u*u}else{A=0.0}if(w>1.0e-16){B=w*w}else{B=0.0}if(b>1.0e-16){C=u*w*.15384112298488617}else{C=0.0}b=o*(u+m*(u*(-.15959623456001282-m*(u*-.021776249632239342+.07591962069272995))+(w*(u*.004869491793215275+m*-.1316167116165161+n*(B*.10695946961641312+(A*-.1782512068748474+(u*.08097013086080551+.14118963479995728+w*-.2815285325050354+C))))+1.374848484992981)));o=y*(w+n*(w*(-.15959623456001282-n*(w*-.021776249632239342+.07591962069272995))+(u*(w*.004869491793215275+n*-.1316167116165161+m*(A*.10695946961641312+(B*-.1782512068748474+(u*-.2815285325050354+(w*.08097013086080551+.14118963479995728)+C))))+1.374848484992981)));C=+P(+b);do{if(C>1.0){if(C>1.0000001000000012){D=2;i=j;return D|0}else{E=b<0.0?-1.0:1.0;break}}else{E=b}}while(0);b=+P(+o);do{if(b>1.0){if(b>1.0000001000000012){D=2;i=j;return D|0}else{F=o<0.0?-1.0:1.0;break}}else{F=o}}while(0);l=e+112|0;h[f>>3]=(x+E)*+h[l>>3];h[g>>3]=+h[l>>3]*(z+F);D=0;i=j;return D|0}function Me(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==702){l=+h[e+120>>3]}else{a[e]=4412227;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=702;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=33;c[e+1892>>2]=34;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){s=3;t=r+-4.0;u=b;break}if(r>1.0){s=2;t=r+-2.0;u=b;break}if(b>1.0){s=0;t=r;u=b+-2.0;break}if(b<-1.0){s=5;t=r;u=b+2.0}else{s=1;t=r;u=b}}else{s=4;t=r+-6.0;u=b}}while(0);b=t*t;r=u*u;o=t;t=o+o*(1.0-b)*(b*(b*(b*(b*(b*(b*.025843750685453415+.25795793533325195)+-.6293006539344788)+.5485238432884216)+-.22797055542469025)+-.07629968971014023)+-.2729269564151764+r*(b*(b*(b*(b*(b*-.5302233695983887+1.715475082397461)+-1.7411445379257202)+.48051509261131287)+-.014715650118887424)+-.028194520622491837+r*(b*(b*(b*(b*-.8318046927452087+.9893810153007507)+.30803316831588745)+-.5680093765258789)+.27058160305023193+r*(b*(b*(b*.08693841099739075+-.9367857575416565)+1.5088008642196655)+-.6044155955314636+r*(b*(b*.3388744592666626+-1.4160192012786865)+.934120774269104+r*(r*.14381584525108337+(b*.5203223824501038+-.6391530632972717)))))));o=u;u=o+o*(1.0-r)*(r*(r*(r*(r*(r*(r*.025843750685453415+.25795793533325195)+-.6293006539344788)+.5485238432884216)+-.22797055542469025)+-.07629968971014023)+-.2729269564151764+b*(r*(r*(r*(r*(r*-.5302233695983887+1.715475082397461)+-1.7411445379257202)+.48051509261131287)+-.014715650118887424)+-.028194520622491837+b*(r*(r*(r*(r*-.8318046927452087+.9893810153007507)+.30803316831588745)+-.5680093765258789)+.27058160305023193+b*(r*(r*(r*.08693841099739075+-.9367857575416565)+1.5088008642196655)+-.6044155955314636+b*(r*(r*.3388744592666626+-1.4160192012786865)+.934120774269104+b*(r*.5203223824501038+-.6391530632972717+b*.14381584525108337))))));switch(s|0){case 1:{b=1.0/+Q(+(u*u+t*t+1.0));v=b;w=t*b;x=u*b;break};case 4:{b=-1.0/+Q(+(u*u+t*t+1.0));v=-t*b;w=b;x=-u*b;break};case 0:{b=1.0/+Q(+(u*u+t*t+1.0));v=-u*b;w=t*b;x=b;break};case 5:{b=-1.0/+Q(+(u*u+t*t+1.0));v=-u*b;w=-t*b;x=b;break};case 3:{b=-1.0/+Q(+(u*u+t*t+1.0));v=b;w=t*b;x=-u*b;break};case 2:{b=1.0/+Q(+(u*u+t*t+1.0));v=-t*b;w=b;x=u*b;break};default:{v=0.0;w=0.0;x=0.0}}if(v==0.0&w==0.0){y=0.0}else{y=+Xe(w,v)}h[f>>3]=y;h[g>>3]=+Ve(x);q=0;i=j;return q|0}function Ne(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0,t=0.0,u=0,v=0.0,w=0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=703){a[e]=4412241;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=703;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=35;c[e+1892>>2]=36}if(+P(+d)==90.0){h[f>>3]=0.0;n=+P(+(+h[e+112>>3]*2.0));if(d<0.0){o=-n}else{o=n}h[g>>3]=o;p=0;i=j;return p|0}o=+Re(d);n=o*+Re(b);m=o*+Se(b);o=+Se(d);l=n>o;q=l?n:o;k=m>q;r=k?m:q;q=-n;s=r180.0){z=y+-360.0}else{z=y}y=z*.017453292519943295;A=o;B=(v*v+y*y)*.5;C=0.0;D=m;E=0.0}else{A=o;B=x;C=0.0;D=m;E=0.0}break};case 3:{if(x<1.0e-8){y=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v<0.0){F=v+360.0}else{F=v}v=(180.0-F)*3.141592653589793/180.0;A=o;B=(y*y+v*v)*.5;C=4.0;D=r;E=0.0}else{A=o;B=x;C=4.0;D=r;E=0.0}break};case 0:{if(x<1.0e-8){r=(90.0-d)*3.141592653589793/180.0;A=q;B=r*r*.5;C=0.0;D=m;E=2.0}else{A=q;B=x;C=0.0;D=m;E=2.0}break};case 2:{if(x<1.0e-8){r=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v<-180.0){G=v+360.0}else{G=v}v=(90.0-G)*3.141592653589793/180.0;A=o;B=(r*r+v*v)*.5;C=2.0;D=q;E=0.0}else{A=o;B=x;C=2.0;D=q;E=0.0}break};case 4:{if(x<1.0e-8){q=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v>180.0){H=v+-360.0}else{H=v}v=H*((H+90.0)*3.141592653589793/180.0);A=o;B=(q*q+v*v)*.5;C=6.0;D=n;E=0.0}else{A=o;B=x;C=6.0;D=n;E=0.0}break};case 5:{if(x<1.0e-8){o=(d+90.0)*3.141592653589793/180.0;A=n;B=o*o*.5;C=0.0;D=m;E=-2.0}else{A=n;B=x;C=0.0;D=m;E=-2.0}break};default:{A=0.0;B=x;C=0.0;D=0.0;E=0.0}}do{if(!(D==0.0&A==0.0)){x=+P(+A);if(x<=-D){m=A/D;n=m*m+1.0;o=-+Q(+(B/(1.0-1.0/+Q(+(n+1.0)))));d=+We(m);I=o;J=o/15.0*(d- +Ve(m/+Q(+(n+n))));break}if(D>=x){x=A/D;n=x*x+1.0;m=+Q(+(B/(1.0-1.0/+Q(+(n+1.0)))));d=+We(x);I=m;J=m/15.0*(d- +Ve(x/+Q(+(n+n))));break}n=+P(+D);if(n<-A){x=D/A;d=x*x+1.0;m=-+Q(+(B/(1.0-1.0/+Q(+(d+1.0)))));o=+We(x);I=m/15.0*(o- +Ve(x/+Q(+(d+d))));J=m;break}if(A>n){n=D/A;m=n*n+1.0;d=+Q(+(B/(1.0-1.0/+Q(+(m+1.0)))));x=+We(n);I=d/15.0*(x- +Ve(n/+Q(+(m+m))));J=d}else{I=0.0;J=0.0}}else{I=0.0;J=0.0}}while(0);B=+P(+I);do{if(B>1.0){if(B>1.000000000001){p=2;i=j;return p|0}else{K=I<0.0?-1.0:1.0;break}}else{K=I}}while(0);I=+P(+J);do{if(I>1.0){if(I>1.000000000001){p=2;i=j;return p|0}else{L=J<0.0?-1.0:1.0;break}}else{L=J}}while(0);l=e+112|0;h[f>>3]=(C+K)*+h[l>>3];h[g>>3]=(E+L)*+h[l>>3];p=0;i=j;return p|0}function Oe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,S=0.0,T=0.0,U=0.0,V=0.0,W=0.0,X=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==703){l=+h[e+120>>3]}else{a[e]=4412241;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=703;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=35;c[e+1892>>2]=36;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){s=3;t=r+-4.0;u=b;break}if(r>1.0){s=2;t=r+-2.0;u=b;break}if(b>1.0){s=0;t=r;u=b+-2.0;break}if(b<-1.0){s=5;t=r;u=b+2.0}else{s=1;t=r;u=b}}else{s=4;t=r+-6.0;u=b}}while(0);e=+P(+t)>+P(+u);if(e){if(t==0.0){v=0.0;w=1.0;x=0.0;y=1.0;z=30}else{b=u*15.0/t;r=+Se(b);o=r/(+Re(b)+-.7071067811865475);b=o*o+1.0;A=t*t*(1.0-1.0/+Q(+(b+1.0)));B=o;C=b;z=28}}else{if(u==0.0){v=0.0;w=1.0;x=0.0;y=1.0;z=30}else{b=t*15.0/u;o=+Se(b);r=o/(+Re(b)+-.7071067811865475);b=r*r+1.0;A=u*u*(1.0-1.0/+Q(+(b+1.0)));B=r;C=b;z=28}}if((z|0)==28){b=1.0-A;if(b<-1.0){if(b<-1.000000000001){q=2;i=j;return q|0}else{D=B;E=-1.0;F=0.0}}else{v=B;w=b;x=A;y=C;z=30}}if((z|0)==30){D=v;E=w;F=+Q(+(x*(2.0-x)/y))}a:do{switch(s|0){case 2:{if(e){if(t>0.0){G=-F}else{G=F}H=G;I=E;J=-(D*G);break a}else{if(u<0.0){K=-F}else{K=F}H=-(D*K);I=E;J=K;break a}break};case 3:{y=-E;if(e){if(t>0.0){L=-F}else{L=F}H=y;I=L;J=-(D*L);break a}else{if(u<0.0){M=-F}else{M=F}H=y;I=-(D*M);J=M;break a}break};case 1:{if(e){if(t<0.0){N=-F}else{N=F}H=E;I=N;J=D*N;break a}else{if(u<0.0){O=-F}else{O=F}H=E;I=D*O;J=O;break a}break};case 5:{y=-E;if(e){if(t<0.0){R=-F}else{R=F}H=D*R;I=R;J=y;break a}else{if(u<0.0){S=-F}else{S=F}H=S;I=D*S;J=y;break a}break};case 4:{y=-E;if(e){if(t<0.0){T=-F}else{T=F}H=T;I=y;J=D*T;break a}else{if(u<0.0){U=-F}else{U=F}H=D*U;I=y;J=U;break a}break};case 0:{if(e){if(t<0.0){V=-F}else{V=F}H=-(D*V);I=V;J=E;break a}else{if(u>0.0){W=-F}else{W=F}H=W;I=-(D*W);J=E;break a}break};default:{H=0.0;I=0.0;J=0.0}}}while(0);if(H==0.0&I==0.0){X=0.0}else{X=+Xe(I,H)}h[f>>3]=X;h[g>>3]=+Ve(J);q=0;i=j;return q|0}function Pe(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;f=i;g=+Re(b);j=+Se(b);k=a- +h[c>>3];a=+Re(k);l=+Se(k);m=c+32|0;n=c+24|0;o=j*+h[m>>3]-a*g*+h[n>>3];if(+P(+o)<1.0e-5){p=+Re(+h[c+8>>3]+b);q=(1.0-a)*g*+h[n>>3]-p}else{q=o}o=g*l;if(q!=0.0|o!=-0.0){r=+Xe(-o,q)}else{r=k+-180.0}l=r+ +h[c+16>>3];h[d>>3]=l;if(!(l>180.0)){if(l<-180.0){h[d>>3]=l+360.0}}else{h[d>>3]=l+-360.0}if(+qa(+k,180.0)==0.0){k=a*+h[c+8>>3]+b;if(k>90.0){s=180.0-k}else{s=k}h[e>>3]=s;if(!(s<-90.0)){i=f;return 0}h[e>>3]=-180.0-s;i=f;return 0}s=j*+h[n>>3]+a*g*+h[m>>3];if(!(+P(+s)>.99)){h[e>>3]=+Ve(s);i=f;return 0}g=+Ue(+Q(+(o*o+q*q)));if(s<0.0){h[e>>3]=-g;i=f;return 0}else{h[e>>3]=g;i=f;return 0}return 0}function Qe(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;f=i;g=+Re(b);j=+Se(b);k=a- +h[c+16>>3];a=+Re(k);l=+Se(k);m=c+32|0;n=c+24|0;o=j*+h[m>>3]-a*g*+h[n>>3];if(+P(+o)<1.0e-5){p=+Re(+h[c+8>>3]+b);q=(1.0-a)*g*+h[n>>3]-p}else{q=o}o=g*l;if(q!=0.0|o!=-0.0){r=+Xe(-o,q)}else{r=k+180.0}l=r+ +h[c>>3];h[d>>3]=l;if(!(+h[c>>3]>=0.0)){if(l>0.0){r=l+-360.0;h[d>>3]=r;s=r}else{s=l}}else{if(l<0.0){r=l+360.0;h[d>>3]=r;s=r}else{s=l}}if(!(s>360.0)){if(s<-360.0){h[d>>3]=s+360.0}}else{h[d>>3]=s+-360.0}if(+qa(+k,180.0)==0.0){k=a*+h[c+8>>3]+b;if(k>90.0){t=180.0-k}else{t=k}h[e>>3]=t;if(!(t<-90.0)){i=f;return 0}h[e>>3]=-180.0-t;i=f;return 0}t=j*+h[n>>3]+a*g*+h[m>>3];if(!(+P(+t)>.99)){h[e>>3]=+Ve(t);i=f;return 0}g=+Ue(+Q(+(o*o+q*q)));if(t<0.0){h[e>>3]=-g;i=f;return 0}else{h[e>>3]=g;i=f;return 0}return 0}function Re(a){a=+a;var b=0,c=0.0,d=0.0,e=0.0;b=i;c=+qa(+a,360.0);d=+P(+c);if(!(c==0.0)){if(!(d==90.0)){if(!(d==180.0)){if(d==270.0){e=0.0}else{e=+S(+(a*.017453292519943295))}}else{e=-1.0}}else{e=0.0}}else{e=1.0}i=b;return+e}function Se(a){a=+a;var b=0,c=0.0,d=0.0;b=i;c=+qa(+(a+-90.0),360.0);if(!(c==0.0)){if(!(c==90.0)){if(!(c==180.0)){if(c==270.0){d=0.0}else{d=+T(+(a*.017453292519943295))}}else{d=-1.0}}else{d=0.0}}else{d=1.0}i=b;return+d}function Te(a){a=+a;var b=0,c=0.0,d=0.0;b=i;c=+qa(+a,360.0);if(!(c==0.0)?!(+P(+c)==180.0):0){if(!(c==45.0|c==225.0)){if(c==-135.0|c==-315.0){d=-1.0}else{d=+U(+(a*.017453292519943295))}}else{d=1.0}}else{d=0.0}i=b;return+d}function Ue(a){a=+a;var b=0,c=0.0,d=0;b=i;if(!(a>=1.0)){if(!(a==0.0)){if(a<=-1.0&a+1.0>-1.0e-10){c=180.0}else{d=5}}else{c=90.0}}else{if(a+-1.0<1.0e-10){c=0.0}else{d=5}}if((d|0)==5){c=+V(+a)*57.29577951308232}i=b;return+c}function Ve(a){a=+a;var b=0,c=0.0,d=0;b=i;if(!(a<=-1.0)){if(!(a==0.0)){if(a>=1.0&a+-1.0<1.0e-10){c=90.0}else{d=5}}else{c=0.0}}else{if(a+1.0>-1.0e-10){c=-90.0}else{d=5}}if((d|0)==5){c=+W(+a)*57.29577951308232}i=b;return+c}function We(a){a=+a;var b=0,c=0.0;b=i;if(!(a==-1.0)){if(!(a==0.0)){if(a==1.0){c=45.0}else{c=+X(+a)*57.29577951308232}}else{c=0.0}}else{c=-45.0}i=b;return+c}function Xe(a,b){a=+a;b=+b;var c=0,d=0.0,e=0;c=i;if(a==0.0){if(!(b>=0.0)){if(b<0.0){d=180.0}else{e=7}}else{d=0.0}}else{if(b==0.0){if(!(a>0.0)){if(a<0.0){d=-90.0}else{e=7}}else{d=90.0}}else{e=7}}if((e|0)==7){d=+Y(+a,+b)*57.29577951308232}i=c;return+d}function Ye(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;i=i+32|0;e=d;f=d+8|0;if((c[a+5968>>2]|0)!=1){i=d;return}g=a+3324|0;if((c[g>>2]|0)==2){c[g>>2]=3;c[a+5976>>2]=0;c[a+6784>>2]=0;c[a+7592>>2]=0;c[a+8400>>2]=0;i=d;return}g=a+5976|0;if((Ec(b,12288,g)|0)!=0){h=c[g>>2]|0;g=(h|0)<0;if(!g){j=(h<<3)+8|0;k=0;while(1){Eg(a+(k*80|0)+5984|0,0,j|0)|0;if((k|0)==(h|0)){break}else{k=k+1|0}}if(!g){g=h+1|0;k=0;j=g;while(1){if((h-k|0)>=0){l=0;do{c[e>>2]=k;c[e+4>>2]=l;Na(f|0,12360,e|0)|0;Lc(b,f,a+(k*80|0)+(l<<3)+5984|0)|0;l=l+1|0}while((l|0)!=(j|0))}k=k+1|0;if((k|0)==(g|0)){break}else{j=j+ -1|0}}}}}else{_b(12296)}j=a+6784|0;if((Ec(b,12368,j)|0)!=0){g=c[j>>2]|0;j=(g|0)<0;if(!j){k=(g<<3)+8|0;h=0;while(1){Eg(a+(h*80|0)+6792|0,0,k|0)|0;if((h|0)==(g|0)){break}else{h=h+1|0}}if(!j){j=g+1|0;h=0;k=j;while(1){if((g-h|0)>=0){l=0;do{c[e>>2]=h;c[e+4>>2]=l;Na(f|0,12440,e|0)|0;Lc(b,f,a+(h*80|0)+(l<<3)+6792|0)|0;l=l+1|0}while((l|0)!=(k|0))}h=h+1|0;if((h|0)==(j|0)){break}else{k=k+ -1|0}}}}}else{_b(12376)}k=a+7592|0;if((Ec(b,12448,k)|0)!=0){j=c[k>>2]|0;k=(j|0)<0;if(!k){h=(j<<3)+8|0;g=0;while(1){Eg(a+(g*80|0)+7600|0,0,h|0)|0;if((g|0)==(j|0)){break}else{g=g+1|0}}if(!k){k=j+1|0;g=0;h=k;while(1){if((j-g|0)>=0){l=0;do{c[e>>2]=g;c[e+4>>2]=l;Na(f|0,12528,e|0)|0;Lc(b,f,a+(g*80|0)+(l<<3)+7600|0)|0;l=l+1|0}while((l|0)!=(h|0))}g=g+1|0;if((g|0)==(k|0)){break}else{h=h+ -1|0}}}}}else{_b(12464)}h=a+8400|0;if((Ec(b,12544,h)|0)==0){_b(12560);i=d;return}k=c[h>>2]|0;h=(k|0)<0;if(h){i=d;return}g=(k<<3)+8|0;j=0;while(1){Eg(a+(j*80|0)+8408|0,0,g|0)|0;if((j|0)==(k|0)){break}else{j=j+1|0}}if(h){i=d;return}h=k+1|0;j=0;g=h;while(1){if((k-j|0)>=0){l=0;do{c[e>>2]=j;c[e+4>>2]=l;Na(f|0,12624,e|0)|0;Lc(b,f,a+(j*80|0)+(l<<3)+8408|0)|0;l=l+1|0}while((l|0)!=(g|0))}j=j+1|0;if((j|0)==(h|0)){break}else{g=g+ -1|0}}i=d;return}function Ze(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0,y=0.0,z=0.0;g=i;i=i+80|0;j=g;if((c[a+5968>>2]|0)!=1){h[e>>3]=b;k=d;h[f>>3]=k;i=g;return}l=c[a+7592>>2]|0;m=c[a+8400>>2]|0;n=b- +h[a+16>>3];o=d- +h[a+24>>3];if((l|0)>=0){p=0;while(1){q=l-p|0;r=+h[a+(q*80|0)+(p<<3)+7600>>3];s=j+(p<<3)|0;h[s>>3]=r;if((p|0)>0){t=p;u=r;do{t=t+ -1|0;u=o*u+ +h[a+(q*80|0)+(t<<3)+7600>>3]}while((t|0)>0);h[s>>3]=u}if((p|0)==(l|0)){break}else{p=p+1|0}}r=+h[j>>3];if((l|0)>0){p=l+1|0;t=l;v=r;while(1){w=n*v+ +h[j+(p-t<<3)>>3];l=t+ -1|0;if((l|0)>0){t=l;v=w}else{x=j;y=w;break}}}else{x=j;y=r}}else{x=j;y=0.0}h[e>>3]=y;if((m|0)>=0){t=0;while(1){p=m-t|0;y=+h[a+(p*80|0)+(t<<3)+8408>>3];l=j+(t<<3)|0;h[l>>3]=y;if((t|0)>0){q=t;r=y;do{q=q+ -1|0;r=o*r+ +h[a+(p*80|0)+(q<<3)+8408>>3]}while((q|0)>0);h[l>>3]=r}if((t|0)==(m|0)){break}else{t=t+1|0}}o=+h[x>>3];if((m|0)>0){t=m+1|0;a=m;u=o;while(1){y=n*u+ +h[j+(t-a<<3)>>3];m=a+ -1|0;if((m|0)>0){a=m;u=y}else{z=y;break}}}else{z=o}}else{z=+h[x>>3]}h[f>>3]=z;h[e>>3]=+h[e>>3]+b;k=+h[f>>3]+d;h[f>>3]=k;i=g;return}function _e(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0,y=0.0,z=0.0;g=i;i=i+80|0;j=g;if((c[a+5968>>2]|0)!=1){h[e>>3]=b;k=d;h[f>>3]=k;i=g;return}l=c[a+5976>>2]|0;m=c[a+6784>>2]|0;n=b- +h[a+16>>3];o=d- +h[a+24>>3];if((l|0)>=0){p=0;while(1){q=l-p|0;r=+h[a+(q*80|0)+(p<<3)+5984>>3];s=j+(p<<3)|0;h[s>>3]=r;if((p|0)>0){t=p;u=r;do{t=t+ -1|0;u=o*u+ +h[a+(q*80|0)+(t<<3)+5984>>3]}while((t|0)>0);h[s>>3]=u}if((p|0)==(l|0)){break}else{p=p+1|0}}r=+h[j>>3];if((l|0)>0){p=l+1|0;t=l;v=r;while(1){w=n*v+ +h[j+(p-t<<3)>>3];l=t+ -1|0;if((l|0)>0){t=l;v=w}else{x=j;y=w;break}}}else{x=j;y=r}}else{x=j;y=0.0}h[e>>3]=y;if((m|0)>=0){t=0;while(1){p=m-t|0;y=+h[a+(p*80|0)+(t<<3)+6792>>3];l=j+(t<<3)|0;h[l>>3]=y;if((t|0)>0){q=t;r=y;do{q=q+ -1|0;r=o*r+ +h[a+(p*80|0)+(q<<3)+6792>>3]}while((q|0)>0);h[l>>3]=r}if((t|0)==(m|0)){break}else{t=t+1|0}}o=+h[x>>3];if((m|0)>0){t=m+1|0;a=m;u=o;while(1){y=n*u+ +h[j+(t-a<<3)>>3];m=a+ -1|0;if((m|0)>0){a=m;u=y}else{z=y;break}}}else{z=o}}else{z=+h[x>>3]}h[f>>3]=z;h[e>>3]=+h[e>>3]+b;k=+h[f>>3]+d;h[f>>3]=k;i=g;return}function $e(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;if((Dg(b|0)|0)<9){c[a+5968>>2]=0;i=d;return}e=a+5968|0;if((Ag(b+8|0,12640,4)|0)==0){c[e>>2]=1;i=d;return}else{c[e>>2]=0;i=d;return}}function af(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0.0,k=0.0,l=0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;e=i;i=i+16|0;f=e;c[3162]=0;g=(d|0)==0;h=b;while(1){if((a[h]|0)==32){h=h+1|0}else{break}}b=g?f:d;j=+wg(h,b);d=c[b>>2]|0;if(($f(h,46)|0)!=0){c[3162]=46}f=a[d]|0;g=f<<24>>24;switch(f<<24>>24){case 32:case 58:case 100:case 104:case 109:{break};default:{k=j;i=e;return+k}}l=d;if((l-h|0)>=5){k=j;i=e;return+k}m=d+1|0;n=a[m]|0;if(!(((n<<24>>24)+ -48|0)>>>0<10)){if(!(n<<24>>24==32)){k=j;i=e;return+k}if(!(((a[d+2|0]|0)+ -48|0)>>>0<10)){k=j;i=e;return+k}}c[3162]=g;c[b>>2]=m;if((a[h]|0)==45){o=-j;p=-1.0}else{o=j;p=1.0}j=+wg(m,b);do{if(!(f<<24>>24==109)){m=c[b>>2]|0;h=a[m]|0;if(h<<24>>24==32|h<<24>>24==58|h<<24>>24==109?(m-l|0)<4:0){h=m+1|0;g=a[h]|0;if(!(((g<<24>>24)+ -48|0)>>>0<10)){if(!(g<<24>>24==32)){q=o;r=j;s=0.0;break}if(!(((a[m+2|0]|0)+ -48|0)>>>0<10)){q=o;r=j;s=0.0;break}}c[b>>2]=h;q=o;r=j;s=+wg(h,b)}else{q=o;r=j;s=0.0}}else{q=0.0;r=o;s=j}}while(0);k=p*(q+r/60.0+s/3600.0);i=e;return+k}function bf(a,b,d,e,f,j,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;j=j|0;l=+l;m=m|0;n=n|0;var o=0,p=0,q=0,r=0,s=0.0,t=0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0;o=i;i=i+48|0;p=o;q=o+36|0;r=o+32|0;s=l;c[r>>2]=0;if((c[58]|0)!=0){c[p>>2]=b;c[p+4>>2]=d;c[p+8>>2]=e;t=p+12|0;h[k>>3]=s;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];c[p+20>>2]=m;c[p+24>>2]=n;Ma(12656,p|0)|0}t=cf(a,e,r,b,d,m,n)|0;n=c[r>>2]|0;Zf(n,t,4,4);l=+g[n>>2];u=+g[n+(t+ -1<<2)>>2];r=t+1|0;if((r|0)<2){v=1}else{v=(r|0)/2|0}r=v+ -1|0;m=n+(r<<2)|0;w=+g[m>>2];if(((t|0)%2|0|0)!=1&(v|0)<(t|0)){x=(w+ +g[n+(v<<2)>>2])*.5}else{x=w}w=+(t|0);d=~~(w*.5);b=(d|0)<5?5:d;d=~~(w*.01+.5);e=(d|0)<1?1:d;d=df(n,t,o+40|0,q,2.5,e,5)|0;if((d|0)<(b|0)){g[f>>2]=l;y=u}else{w=+g[q>>2];if(s>0.0){z=w/s;g[q>>2]=z;A=z}else{A=w}w=x- +(r|0)*A;g[f>>2]=l>w?l:w;w=x+ +(t-v|0)*A;y=u>2]=y;if((c[58]|0)==0){hg(n);i=o;return}y=+g[m>>2];h[k>>3]=l;c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];m=p+8|0;h[k>>3]=u;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];m=p+16|0;h[k>>3]=y;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];m=p+24|0;h[k>>3]=x;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];Ma(12704,p|0)|0;c[p>>2]=b;c[p+4>>2]=e;c[p+8>>2]=d;Ma(12752,p|0)|0;x=+g[f>>2];y=+g[j>>2];h[k>>3]=+g[q>>2];c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];c[p+8>>2]=v;v=p+12|0;h[k>>3]=x;c[v>>2]=c[k>>2];c[v+4>>2]=c[k+4>>2];v=p+20|0;h[k>>3]=y;c[v>>2]=c[k>>2];c[v+4>>2]=c[k+4>>2];Ma(12800,p|0)|0;hg(n);i=o;return}function cf(d,e,f,j,k,l,m){d=d|0;e=e|0;f=f|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;n=i;i=i+16|0;o=n;p=(j|0)<(m|0)?j:m;q=(p|0)<1?1:p;p=j+ -1|0;r=(p+q|0)/(q|0)|0;s=(r|0)<2?2:r;r=(p+s|0)/(s|0)|0;p=(r|0)<1?1:r;if((c[58]|0)==0){t=1}else{c[o>>2]=q;c[o+4>>2]=s;c[o+8>>2]=p;Ma(12856,o|0)|0;t=(c[58]|0)==0}q=(l|0)/(m|0)|0;m=(q|0)<1?1:q;q=(l+ -1+p|0)/(p|0)|0;l=(q|0)>(k|0)?k:q;q=(m|0)>(l|0)?m:l;l=(k|0)/(q|0)|0;r=(l|0)<2?2:l;u=(k+ -1+r|0)/(r|0)|0;if(!t){c[o>>2]=m;c[o+4>>2]=q;c[o+8>>2]=r;c[o+12>>2]=u;Ma(12912,o|0)|0}o=aa(u,p)|0;u=gg(o<<2)|0;c[f>>2]=u;f=j<<2;q=gg(f)|0;m=(r+1|0)/2|0;if((m|0)>=(k|0)){v=0;hg(q);i=n;return v|0}t=(p|0)>0;w=(j|0)>0;x=j<<1;y=j<<3;if((e|0)==8){z=m;A=0;B=u;while(1){C=aa(z+ -1|0,j)|0;if(w){D=0;do{g[q+(D<<2)>>2]=+(a[d+(D+C)|0]|0);D=D+1|0}while((D|0)!=(j|0))}a:do{if(t){D=0;C=0;while(1){g[B+(D<<2)>>2]=+g[q+(C<<2)>>2];E=D+1|0;if((E|0)==(p|0)){break a}D=E;C=C+s|0}}}while(0);C=A+p|0;if((C|0)>(o|0)){v=C;F=29;break}D=z+r|0;if((D|0)<(k|0)){z=D;A=C;B=B+(p<<2)|0}else{v=C;F=29;break}}if((F|0)==29){hg(q);i=n;return v|0}}B=(aa(m+ -1|0,j)|0)<<2;A=(aa((l|0)>2?l:2,j)|0)<<2;l=j<<2;z=0;C=m;m=0;D=u;while(1){u=d+(B+(aa(A,z)|0))|0;if((e|0)==32){E=d+(aa(f,C+ -1|0)|0)|0;if(w){G=0;do{g[q+(G<<2)>>2]=+(c[E+(G<<2)>>2]|0);G=G+1|0}while((G|0)!=(j|0))}}else if((e|0)==-32){if(w){Kg(q|0,u|0,l|0)|0}}else if((e|0)==-64){G=d+(aa(y,C+ -1|0)|0)|0;if(w){E=0;do{g[q+(E<<2)>>2]=+h[G+(E<<3)>>3];E=E+1|0}while((E|0)!=(j|0))}}else if((e|0)==16?(E=d+(aa(x,C+ -1|0)|0)|0,w):0){G=0;do{g[q+(G<<2)>>2]=+(b[E+(G<<1)>>1]|0);G=G+1|0}while((G|0)!=(j|0))}b:do{if(t){G=0;E=0;while(1){g[D+(G<<2)>>2]=+g[q+(E<<2)>>2];u=G+1|0;if((u|0)==(p|0)){break b}G=u;E=E+s|0}}}while(0);E=m+p|0;if((E|0)>(o|0)){v=E;F=29;break}G=C+r|0;if((G|0)<(k|0)){z=z+1|0;C=G;m=E;D=D+(p<<2)|0}else{v=E;F=29;break}}if((F|0)==29){hg(q);i=n;return v|0}return 0}function df(b,c,d,e,f,h,j){b=b|0;c=c|0;d=d|0;e=e|0;f=+f;h=h|0;j=j|0;var k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0.0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0.0,D=0,E=0,F=0,G=0,H=0.0,I=0.0,J=0.0,K=0,L=0.0,M=0.0,N=0.0,O=0.0,P=0.0,R=0.0,S=0.0,T=0.0,U=0,V=0,W=0.0,X=0,Y=0,Z=0.0,_=0.0,$=0.0,ba=0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0,oa=0.0,pa=0.0,qa=0.0,ra=0,sa=0.0,ta=0.0;k=i;l=f;if((c|0)<1){m=0;i=k;return m|0}if((c|0)==1){g[d>>2]=+g[b+4>>2];g[e>>2]=0.0;m=1;i=k;return m|0}f=2.0/+(c+ -1|0);n=c<<2;o=gg(n)|0;p=gg(n)|0;n=ig(c,1)|0;q=0;while(1){g[p+(q<<2)>>2]=f*+(q|0)+-1.0;r=q+1|0;if((r|0)==(c|0)){s=0.0;t=0.0;u=0.0;v=0;break}else{q=r}}do{w=+g[p+(v<<2)>>2];x=+g[b+(v<<2)>>2];s=s+w*w;t=t+w*x;u=u+x;v=v+1|0}while((v|0)!=(c|0));x=+(c|0);w=u/x;y=t/s;v=~~(x*.5);q=(v|0)<5?5:v;if((j|0)>0){x=l;v=~h;r=~c;l=0.0;z=u;u=t;t=s;s=y;A=c;B=0;C=w;while(1){D=0;while(1){g[o+(D<<2)>>2]=+g[b+(D<<2)>>2]-(C+s*+g[p+(D<<2)>>2]);E=D+1|0;if((E|0)==(c|0)){F=0;G=0;H=0.0;I=0.0;break}else{D=E}}while(1){if((a[n+F|0]|0)==0){J=+g[o+(F<<2)>>2];K=G+1|0;L=H+J;M=I+J*J}else{K=G;L=H;M=I}F=F+1|0;if((F|0)==(c|0)){break}else{G=K;H=L;I=M}}if(!(K>>>0<2)){D=K+ -1|0;J=M/+(D|0)-L*L/+(aa(D,K)|0);if(J<0.0){N=0.0}else{N=+Q(+J)}}else{N=-999.0}J=x*N;O=-J;P=t;R=u;S=z;T=l;D=0;E=v;U=c;while(1){V=~((E|0)>(r|0)?E:r);if((a[n+D|0]|0)!=1){W=+g[o+(D<<2)>>2];if(WJ?(X=D-h|0,Y=(X|0)<0?0:X,X=D+h|0,(Y|0)<(((X|0)>(c|0)?c:X)|0)):0){W=P;Z=R;_=T;$=S;X=Y;Y=U;while(1){ba=n+X|0;do{if((a[ba]|0)!=1){if((X|0)>(D|0)){a[ba]=2;ca=W;da=Z;ea=$;fa=_;ga=Y;break}else{ha=+g[p+(X<<2)>>2];ia=+g[b+(X<<2)>>2];a[ba]=1;ca=W-ha*ha;da=Z-ha*ia;ea=$-ia;fa=_-ha;ga=Y+ -1|0;break}}else{ca=W;da=Z;ea=$;fa=_;ga=Y}}while(0);ba=X+1|0;if((ba|0)==(V|0)){ja=fa;ka=ca;la=da;ma=ea;na=ga;break}else{W=ca;Z=da;_=fa;$=ea;X=ba;Y=ga}}}else{ja=T;ka=P;la=R;ma=S;na=U}}else{ja=T;ka=P;la=R;ma=S;na=U+ -1|0}D=D+1|0;if((D|0)==(c|0)){break}else{P=ka;R=la;S=ma;T=ja;E=E+ -1|0;U=na}}if((na|0)>0){T=ja/ka;S=(ma-la*T)/(+(na|0)-ja*T);oa=(la-ja*S)/ka;pa=S}else{oa=s;pa=C}U=B+1|0;if((na|0)>=(q|0)&(na|0)<(A|0)&(U|0)<(j|0)){l=ja;z=ma;u=la;t=ka;s=oa;A=na;B=U;C=pa}else{qa=oa;ra=na;sa=pa;break}}}else{qa=y;ra=c;sa=w}g[d>>2]=sa-qa;sa=f*qa;g[e>>2]=sa;if(!(sa>=0.0)){ta=-sa}else{ta=sa}if(ta<.001){g[e>>2]=f*y}hg(o);hg(p);hg(n);m=ra;i=k;return m|0}function ef(a,b){a=a|0;b=b|0;return(+g[a>>2]<=+g[b>>2]?-1:1)|0}function ff(a,b,c){a=a|0;b=b|0;c=c|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0;e=i;f=a>>>16;g=a&65535;if((c|0)==1){a=(d[b]|0)+g|0;h=a>>>0>65520?a+ -65521|0:a;a=h+f|0;j=(a>>>0>65520?a+15|0:a)<<16|h;i=e;return j|0}if((b|0)==0){j=1;i=e;return j|0}if(c>>>0<16){if((c|0)==0){k=g;l=f}else{h=b;a=c;m=g;n=f;while(1){o=a+ -1|0;p=(d[h]|0)+m|0;q=p+n|0;if((o|0)==0){k=p;l=q;break}else{h=h+1|0;a=o;m=p;n=q}}}j=((l>>>0)%65521|0)<<16|(k>>>0>65520?k+ -65521|0:k);i=e;return j|0}if(c>>>0>5551){k=b;l=c;n=g;m=f;do{l=l+ -5552|0;a=k;h=n;q=347;p=m;while(1){o=(d[a]|0)+h|0;r=o+(d[a+1|0]|0)|0;s=r+(d[a+2|0]|0)|0;t=s+(d[a+3|0]|0)|0;u=t+(d[a+4|0]|0)|0;v=u+(d[a+5|0]|0)|0;w=v+(d[a+6|0]|0)|0;x=w+(d[a+7|0]|0)|0;y=x+(d[a+8|0]|0)|0;z=y+(d[a+9|0]|0)|0;A=z+(d[a+10|0]|0)|0;B=A+(d[a+11|0]|0)|0;C=B+(d[a+12|0]|0)|0;D=C+(d[a+13|0]|0)|0;E=D+(d[a+14|0]|0)|0;h=E+(d[a+15|0]|0)|0;p=o+p+r+s+t+u+v+w+x+y+z+A+B+C+D+E+h|0;q=q+ -1|0;if((q|0)==0){break}else{a=a+16|0}}k=k+5552|0;n=(h>>>0)%65521|0;m=(p>>>0)%65521|0}while(l>>>0>5551);if((l|0)!=0){if(l>>>0>15){F=l;G=k;H=n;I=m;J=15}else{K=l;L=k;M=n;N=m;J=16}}else{O=n;P=m}}else{F=c;G=b;H=g;I=f;J=15}if((J|0)==15){while(1){J=0;F=F+ -16|0;f=(d[G]|0)+H|0;g=f+(d[G+1|0]|0)|0;b=g+(d[G+2|0]|0)|0;c=b+(d[G+3|0]|0)|0;m=c+(d[G+4|0]|0)|0;n=m+(d[G+5|0]|0)|0;k=n+(d[G+6|0]|0)|0;l=k+(d[G+7|0]|0)|0;a=l+(d[G+8|0]|0)|0;q=a+(d[G+9|0]|0)|0;E=q+(d[G+10|0]|0)|0;D=E+(d[G+11|0]|0)|0;C=D+(d[G+12|0]|0)|0;B=C+(d[G+13|0]|0)|0;A=B+(d[G+14|0]|0)|0;H=A+(d[G+15|0]|0)|0;I=f+I+g+b+c+m+n+k+l+a+q+E+D+C+B+A+H|0;G=G+16|0;if(!(F>>>0>15)){break}else{J=15}}if((F|0)==0){Q=H;R=I;J=17}else{K=F;L=G;M=H;N=I;J=16}}if((J|0)==16){while(1){J=0;I=K+ -1|0;H=(d[L]|0)+M|0;G=H+N|0;if((I|0)==0){Q=H;R=G;J=17;break}else{K=I;L=L+1|0;M=H;N=G;J=16}}}if((J|0)==17){O=(Q>>>0)%65521|0;P=(R>>>0)%65521|0}j=P<<16|O;i=e;return j|0}function gf(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;f=i;if((b|0)==0){g=0;i=f;return g|0}h=~a;a:do{if((e|0)!=0){a=b;j=e;k=h;while(1){if((a&3|0)==0){break}l=c[12968+(((d[a]|0)^k&255)<<2)>>2]^k>>>8;m=j+ -1|0;if((m|0)==0){n=l;break a}else{a=a+1|0;j=m;k=l}}if(j>>>0>31){l=j;m=a;o=k;while(1){p=c[m>>2]^o;q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+4>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+8>>2];q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+12>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+16>>2];q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+20>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+24>>2];q=m+32|0;r=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+28>>2];p=c[15016+((r>>>8&255)<<2)>>2]^c[16040+((r&255)<<2)>>2]^c[13992+((r>>>16&255)<<2)>>2]^c[12968+(r>>>24<<2)>>2];r=l+ -32|0;if(r>>>0>31){l=r;m=q;o=p}else{s=r;t=q;u=p;break}}}else{s=j;t=a;u=k}if(s>>>0>3){o=s;m=t;l=u;while(1){p=m+4|0;q=c[m>>2]^l;r=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2];q=o+ -4|0;if(q>>>0>3){o=q;m=p;l=r}else{v=q;w=p;x=r;break}}}else{v=s;w=t;x=u}if((v|0)==0){n=x}else{l=w;m=v;o=x;while(1){k=c[12968+(((d[l]|0)^o&255)<<2)>>2]^o>>>8;a=m+ -1|0;if((a|0)==0){n=k;break}else{l=l+1|0;m=a;o=k}}}}else{n=h}}while(0);g=~n;i=f;return g|0}function hf(b,d,e,f,g,h,j,k){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0;l=i;if((j|0)==0){m=-6;i=l;return m|0}if(!((a[j]|0)==49&(k|0)==56)){m=-6;i=l;return m|0}if((b|0)==0){m=-2;i=l;return m|0}k=b+24|0;c[k>>2]=0;j=b+32|0;n=c[j>>2]|0;if((n|0)==0){c[j>>2]=1;c[b+40>>2]=0;o=1}else{o=n}n=b+36|0;if((c[n>>2]|0)==0){c[n>>2]=1}n=(d|0)==-1?6:d;if((f|0)<0){p=0-f|0;q=0}else{d=(f|0)>15;p=d?f+ -16|0:f;q=d?2:1}if(!((g+ -1|0)>>>0<9&(e|0)==8)){m=-2;i=l;return m|0}if((p+ -8|0)>>>0>7|n>>>0>9|h>>>0>4){m=-2;i=l;return m|0}e=(p|0)==8?9:p;p=b+40|0;d=kb[o&1](c[p>>2]|0,1,5828)|0;if((d|0)==0){m=-4;i=l;return m|0}c[b+28>>2]=d;c[d>>2]=b;c[d+24>>2]=q;c[d+28>>2]=0;c[d+48>>2]=e;q=1<>2]=q;c[d+52>>2]=q+ -1;o=g+7|0;c[d+80>>2]=o;f=1<>2]=f;c[d+84>>2]=f+ -1;c[d+88>>2]=((g+9|0)>>>0)/3|0;f=d+56|0;c[f>>2]=kb[c[j>>2]&1](c[p>>2]|0,q,2)|0;q=kb[c[j>>2]&1](c[p>>2]|0,c[e>>2]|0,2)|0;r=d+64|0;c[r>>2]=q;Eg(q|0,0,c[e>>2]<<1|0)|0;e=d+68|0;c[e>>2]=kb[c[j>>2]&1](c[p>>2]|0,c[o>>2]|0,2)|0;c[d+5824>>2]=0;o=1<>2]=o;q=kb[c[j>>2]&1](c[p>>2]|0,o,4)|0;c[d+8>>2]=q;o=c[g>>2]|0;c[d+12>>2]=o<<2;if(((c[f>>2]|0)!=0?(c[r>>2]|0)!=0:0)?!((c[e>>2]|0)==0|(q|0)==0):0){c[d+5796>>2]=q+(o>>>1<<1);c[d+5784>>2]=q+(o*3|0);c[d+132>>2]=n;c[d+136>>2]=h;a[d+36|0]=8;m=kf(b)|0;i=l;return m|0}c[d+4>>2]=666;c[k>>2]=c[27632>>2];jf(b)|0;m=-4;i=l;return m|0}function jf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;i=b;return d|0}g=c[f+4>>2]|0;switch(g|0){case 42:case 69:case 73:case 91:case 103:case 113:case 666:{break};default:{d=-2;i=b;return d|0}}h=c[f+8>>2]|0;if((h|0)==0){j=f}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);j=c[e>>2]|0}h=c[j+68>>2]|0;if((h|0)==0){k=j}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);k=c[e>>2]|0}h=c[k+64>>2]|0;if((h|0)==0){l=k}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);l=c[e>>2]|0}h=c[l+56>>2]|0;k=a+36|0;if((h|0)==0){m=a+40|0;n=l}else{l=a+40|0;mb[c[k>>2]&1](c[l>>2]|0,h);m=l;n=c[e>>2]|0}mb[c[k>>2]&1](c[m>>2]|0,n);c[e>>2]=0;d=(g|0)==113?-3:0;i=b;return d|0}function kf(a){a=a|0;var d=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;d=i;if((a|0)==0){f=-2;i=d;return f|0}g=c[a+28>>2]|0;if((g|0)==0){f=-2;i=d;return f|0}if((c[a+32>>2]|0)==0){f=-2;i=d;return f|0}if((c[a+36>>2]|0)==0){f=-2;i=d;return f|0}c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+44>>2]=2;c[g+20>>2]=0;c[g+16>>2]=c[g+8>>2];h=g+24|0;j=c[h>>2]|0;if((j|0)<0){k=0-j|0;c[h>>2]=k;l=k}else{l=j}c[g+4>>2]=(l|0)!=0?42:113;if((l|0)==2){m=gf(0,0,0)|0}else{m=ff(0,0,0)|0}c[a+48>>2]=m;c[g+40>>2]=0;Of(g);c[g+60>>2]=c[g+44>>2]<<1;m=c[g+76>>2]|0;a=c[g+68>>2]|0;b[a+(m+ -1<<1)>>1]=0;Eg(a|0,0,(m<<1)+ -2|0)|0;m=c[g+132>>2]|0;c[g+128>>2]=e[21162+(m*12|0)>>1]|0;c[g+140>>2]=e[21160+(m*12|0)>>1]|0;c[g+144>>2]=e[21164+(m*12|0)>>1]|0;c[g+124>>2]=e[21166+(m*12|0)>>1]|0;c[g+108>>2]=0;c[g+92>>2]=0;c[g+116>>2]=0;c[g+120>>2]=2;c[g+96>>2]=2;c[g+112>>2]=0;c[g+104>>2]=0;c[g+72>>2]=0;f=0;i=d;return f|0} + + + +function lf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0;g=i;if((e|0)==0){h=-2;i=g;return h|0}j=e+28|0;k=c[j>>2]|0;if((k|0)==0|f>>>0>5){h=-2;i=g;return h|0}l=e+12|0;do{if((c[l>>2]|0)!=0){if((c[e>>2]|0)==0?(c[e+4>>2]|0)!=0:0){break}m=k+4|0;n=c[m>>2]|0;o=(f|0)==4;if((n|0)!=666|o){p=e+16|0;if((c[p>>2]|0)==0){c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}c[k>>2]=e;q=k+40|0;r=c[q>>2]|0;c[q>>2]=f;do{if((n|0)==42){if((c[k+24>>2]|0)!=2){s=(c[k+48>>2]<<12)+ -30720|0;if((c[k+136>>2]|0)<=1?(t=c[k+132>>2]|0,(t|0)>=2):0){if((t|0)<6){u=64}else{u=(t|0)==6?128:192}}else{u=0}t=u|s;s=k+108|0;v=(c[s>>2]|0)==0?t:t|32;c[m>>2]=113;t=k+20|0;w=c[t>>2]|0;c[t>>2]=w+1;x=k+8|0;a[(c[x>>2]|0)+w|0]=v>>>8;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=(v|((v>>>0)%31|0))^31;v=e+48|0;if((c[s>>2]|0)!=0){s=c[v>>2]|0;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>24;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>16;s=c[v>>2]|0;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>8;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s}c[v>>2]=ff(0,0,0)|0;y=c[m>>2]|0;z=32;break}v=e+48|0;c[v>>2]=gf(0,0,0)|0;s=k+20|0;w=c[s>>2]|0;c[s>>2]=w+1;x=k+8|0;a[(c[x>>2]|0)+w|0]=31;w=c[s>>2]|0;c[s>>2]=w+1;a[(c[x>>2]|0)+w|0]=-117;w=c[s>>2]|0;c[s>>2]=w+1;a[(c[x>>2]|0)+w|0]=8;w=k+28|0;t=c[w>>2]|0;if((t|0)==0){A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[k+132>>2]|0;if((A|0)!=9){if((c[k+136>>2]|0)>1){B=4}else{B=(A|0)<2?4:0}}else{B=2}A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=B;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=3;c[m>>2]=113;break}A=(((c[t+44>>2]|0)!=0?2:0)|(c[t>>2]|0)!=0|((c[t+16>>2]|0)==0?0:4)|((c[t+28>>2]|0)==0?0:8)|((c[t+36>>2]|0)==0?0:16))&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[(c[w>>2]|0)+4>>2]&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>8&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>16&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>24&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[k+132>>2]|0;if((A|0)!=9){if((c[k+136>>2]|0)>1){C=4}else{C=(A|0)<2?4:0}}else{C=2}A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=C;A=c[(c[w>>2]|0)+12>>2]&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[w>>2]|0;if((c[A+16>>2]|0)==0){D=A}else{t=c[A+20>>2]&255;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=t;t=(c[(c[w>>2]|0)+20>>2]|0)>>>8&255;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=t;D=c[w>>2]|0}if((c[D+44>>2]|0)!=0){c[v>>2]=gf(c[v>>2]|0,c[x>>2]|0,c[s>>2]|0)|0}c[k+32>>2]=0;c[m>>2]=69;E=w;z=34}else{y=n;z=32}}while(0);if((z|0)==32){if((y|0)==69){E=k+28|0;z=34}else{F=y;z=55}}do{if((z|0)==34){n=c[E>>2]|0;if((c[n+16>>2]|0)==0){c[m>>2]=73;G=n;z=57;break}w=k+20|0;s=c[w>>2]|0;x=k+32|0;v=c[x>>2]|0;a:do{if(v>>>0<(c[n+20>>2]&65535)>>>0){t=k+12|0;A=e+48|0;H=k+8|0;I=e+20|0;J=v;K=s;L=n;M=s;while(1){if((K|0)==(c[t>>2]|0)){if((c[L+44>>2]|0)!=0&K>>>0>M>>>0){c[A>>2]=gf(c[A>>2]|0,(c[H>>2]|0)+M|0,K-M|0)|0}N=c[j>>2]|0;O=c[N+20>>2]|0;P=c[p>>2]|0;Q=O>>>0>P>>>0?P:O;if((Q|0)!=0?(Kg(c[l>>2]|0,c[N+16>>2]|0,Q|0)|0,c[l>>2]=(c[l>>2]|0)+Q,N=(c[j>>2]|0)+16|0,c[N>>2]=(c[N>>2]|0)+Q,c[I>>2]=(c[I>>2]|0)+Q,c[p>>2]=(c[p>>2]|0)-Q,N=c[j>>2]|0,O=N+20|0,P=c[O>>2]|0,c[O>>2]=P-Q,(P|0)==(Q|0)):0){c[N+16>>2]=c[N+8>>2]}R=c[w>>2]|0;if((R|0)==(c[t>>2]|0)){break}S=c[E>>2]|0;T=c[x>>2]|0;U=R;V=R}else{S=L;T=J;U=K;V=M}N=a[(c[S+16>>2]|0)+T|0]|0;c[w>>2]=U+1;a[(c[H>>2]|0)+U|0]=N;N=(c[x>>2]|0)+1|0;c[x>>2]=N;Q=c[E>>2]|0;if(!(N>>>0<(c[Q+20>>2]&65535)>>>0)){W=Q;X=V;break a}J=N;K=c[w>>2]|0;L=Q;M=V}W=c[E>>2]|0;X=R}else{W=n;X=s}}while(0);if((c[W+44>>2]|0)!=0?(s=c[w>>2]|0,s>>>0>X>>>0):0){n=e+48|0;c[n>>2]=gf(c[n>>2]|0,(c[k+8>>2]|0)+X|0,s-X|0)|0;Y=c[E>>2]|0}else{Y=W}if((c[x>>2]|0)==(c[Y+20>>2]|0)){c[x>>2]=0;c[m>>2]=73;G=Y;z=57;break}else{F=c[m>>2]|0;z=55;break}}}while(0);if((z|0)==55){if((F|0)==73){G=c[k+28>>2]|0;z=57}else{Z=F;z=76}}do{if((z|0)==57){s=k+28|0;if((c[G+28>>2]|0)==0){c[m>>2]=91;_=s;z=78;break}n=k+20|0;v=c[n>>2]|0;M=k+12|0;L=e+48|0;K=k+8|0;J=e+20|0;H=k+32|0;t=v;I=v;while(1){if((t|0)==(c[M>>2]|0)){if((c[(c[s>>2]|0)+44>>2]|0)!=0&t>>>0>I>>>0){c[L>>2]=gf(c[L>>2]|0,(c[K>>2]|0)+I|0,t-I|0)|0}v=c[j>>2]|0;A=c[v+20>>2]|0;Q=c[p>>2]|0;N=A>>>0>Q>>>0?Q:A;if((N|0)!=0?(Kg(c[l>>2]|0,c[v+16>>2]|0,N|0)|0,c[l>>2]=(c[l>>2]|0)+N,v=(c[j>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+N,c[J>>2]=(c[J>>2]|0)+N,c[p>>2]=(c[p>>2]|0)-N,v=c[j>>2]|0,A=v+20|0,Q=c[A>>2]|0,c[A>>2]=Q-N,(Q|0)==(N|0)):0){c[v+16>>2]=c[v+8>>2]}v=c[n>>2]|0;if((v|0)==(c[M>>2]|0)){$=v;aa=1;break}else{ba=v;ca=v}}else{ba=t;ca=I}v=c[H>>2]|0;c[H>>2]=v+1;da=a[(c[(c[s>>2]|0)+28>>2]|0)+v|0]|0;c[n>>2]=ba+1;a[(c[K>>2]|0)+ba|0]=da;if(da<<24>>24==0){z=68;break}t=c[n>>2]|0;I=ca}if((z|0)==68){$=ca;aa=da&255}if((c[(c[s>>2]|0)+44>>2]|0)!=0?(I=c[n>>2]|0,I>>>0>$>>>0):0){c[L>>2]=gf(c[L>>2]|0,(c[K>>2]|0)+$|0,I-$|0)|0}if((aa|0)==0){c[H>>2]=0;c[m>>2]=91;_=s;z=78;break}else{Z=c[m>>2]|0;z=76;break}}}while(0);if((z|0)==76){if((Z|0)==91){_=k+28|0;z=78}else{ea=Z;z=97}}do{if((z|0)==78){if((c[(c[_>>2]|0)+36>>2]|0)==0){c[m>>2]=103;fa=_;z=99;break}I=k+20|0;t=c[I>>2]|0;M=k+12|0;J=e+48|0;x=k+8|0;w=e+20|0;v=k+32|0;N=t;Q=t;while(1){if((N|0)==(c[M>>2]|0)){if((c[(c[_>>2]|0)+44>>2]|0)!=0&N>>>0>Q>>>0){c[J>>2]=gf(c[J>>2]|0,(c[x>>2]|0)+Q|0,N-Q|0)|0}t=c[j>>2]|0;A=c[t+20>>2]|0;P=c[p>>2]|0;O=A>>>0>P>>>0?P:A;if((O|0)!=0?(Kg(c[l>>2]|0,c[t+16>>2]|0,O|0)|0,c[l>>2]=(c[l>>2]|0)+O,t=(c[j>>2]|0)+16|0,c[t>>2]=(c[t>>2]|0)+O,c[w>>2]=(c[w>>2]|0)+O,c[p>>2]=(c[p>>2]|0)-O,t=c[j>>2]|0,A=t+20|0,P=c[A>>2]|0,c[A>>2]=P-O,(P|0)==(O|0)):0){c[t+16>>2]=c[t+8>>2]}t=c[I>>2]|0;if((t|0)==(c[M>>2]|0)){ga=t;ha=1;break}else{ia=t;ja=t}}else{ia=N;ja=Q}t=c[v>>2]|0;c[v>>2]=t+1;ka=a[(c[(c[_>>2]|0)+36>>2]|0)+t|0]|0;c[I>>2]=ia+1;a[(c[x>>2]|0)+ia|0]=ka;if(ka<<24>>24==0){z=89;break}N=c[I>>2]|0;Q=ja}if((z|0)==89){ga=ja;ha=ka&255}if((c[(c[_>>2]|0)+44>>2]|0)!=0?(Q=c[I>>2]|0,Q>>>0>ga>>>0):0){c[J>>2]=gf(c[J>>2]|0,(c[x>>2]|0)+ga|0,Q-ga|0)|0}if((ha|0)==0){c[m>>2]=103;fa=_;z=99;break}else{ea=c[m>>2]|0;z=97;break}}}while(0);if((z|0)==97?(ea|0)==103:0){fa=k+28|0;z=99}do{if((z|0)==99){if((c[(c[fa>>2]|0)+44>>2]|0)==0){c[m>>2]=113;break}Q=k+20|0;N=k+12|0;if((((c[Q>>2]|0)+2|0)>>>0>(c[N>>2]|0)>>>0?(v=c[j>>2]|0,M=c[v+20>>2]|0,w=c[p>>2]|0,s=M>>>0>w>>>0?w:M,(s|0)!=0):0)?(Kg(c[l>>2]|0,c[v+16>>2]|0,s|0)|0,c[l>>2]=(c[l>>2]|0)+s,v=(c[j>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+s,v=e+20|0,c[v>>2]=(c[v>>2]|0)+s,c[p>>2]=(c[p>>2]|0)-s,v=c[j>>2]|0,M=v+20|0,w=c[M>>2]|0,c[M>>2]=w-s,(w|0)==(s|0)):0){c[v+16>>2]=c[v+8>>2]}v=c[Q>>2]|0;if(!((v+2|0)>>>0>(c[N>>2]|0)>>>0)){N=e+48|0;s=c[N>>2]&255;c[Q>>2]=v+1;w=k+8|0;a[(c[w>>2]|0)+v|0]=s;s=(c[N>>2]|0)>>>8&255;v=c[Q>>2]|0;c[Q>>2]=v+1;a[(c[w>>2]|0)+v|0]=s;c[N>>2]=gf(0,0,0)|0;c[m>>2]=113}}}while(0);N=k+20|0;if((c[N>>2]|0)==0){if((c[e+4>>2]|0)==0?(r|0)>=(f|0)&(f|0)!=4:0){c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}}else{s=c[j>>2]|0;v=c[s+20>>2]|0;w=c[p>>2]|0;Q=v>>>0>w>>>0?w:v;if((Q|0)==0){la=w}else{Kg(c[l>>2]|0,c[s+16>>2]|0,Q|0)|0;c[l>>2]=(c[l>>2]|0)+Q;s=(c[j>>2]|0)+16|0;c[s>>2]=(c[s>>2]|0)+Q;s=e+20|0;c[s>>2]=(c[s>>2]|0)+Q;c[p>>2]=(c[p>>2]|0)-Q;s=c[j>>2]|0;w=s+20|0;v=c[w>>2]|0;c[w>>2]=v-Q;if((v|0)==(Q|0)){c[s+16>>2]=c[s+8>>2]}la=c[p>>2]|0}if((la|0)==0){c[q>>2]=-1;h=0;i=g;return h|0}}s=(c[m>>2]|0)==666;Q=(c[e+4>>2]|0)==0;if(s){if(Q){z=121}else{c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}}else{if(Q){z=121}else{z=124}}do{if((z|0)==121){if((c[k+116>>2]|0)==0){if((f|0)!=0){if(s){break}else{z=124;break}}else{h=0;i=g;return h|0}}else{z=124}}}while(0);do{if((z|0)==124){s=c[k+136>>2]|0;b:do{if((s|0)==3){r=k+116|0;Q=(f|0)==0;v=k+96|0;w=k+108|0;M=k+5792|0;H=k+5796|0;K=k+5784|0;L=k+(d[24760]<<2)+2440|0;n=k+5788|0;t=k+56|0;O=k+92|0;while(1){P=c[r>>2]|0;if(P>>>0<258){mf(k);A=c[r>>2]|0;if(A>>>0<258&Q){break b}if((A|0)==0){break}c[v>>2]=0;if(A>>>0>2){ma=A;z=151}else{na=c[w>>2]|0;z=166}}else{c[v>>2]=0;ma=P;z=151}if((z|0)==151){z=0;P=c[w>>2]|0;if((P|0)!=0){A=c[t>>2]|0;oa=a[A+(P+ -1)|0]|0;if((oa<<24>>24==(a[A+P|0]|0)?oa<<24>>24==(a[A+(P+1)|0]|0):0)?(pa=A+(P+2)|0,oa<<24>>24==(a[pa]|0)):0){qa=A+(P+258)|0;A=pa;while(1){pa=A+1|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+2|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+3|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+4|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+5|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+6|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+7|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+8|0;if(oa<<24>>24==(a[pa]|0)&pa>>>0>>0){A=pa}else{ra=pa;break}}A=ra-qa+258|0;oa=A>>>0>ma>>>0?ma:A;c[v>>2]=oa;if(oa>>>0>2){A=oa+253|0;oa=c[M>>2]|0;b[(c[H>>2]|0)+(oa<<1)>>1]=1;c[M>>2]=oa+1;a[(c[K>>2]|0)+oa|0]=A;oa=k+((d[25272+(A&255)|0]|256)+1<<2)+148|0;b[oa>>1]=(b[oa>>1]|0)+1<<16>>16;b[L>>1]=(b[L>>1]|0)+1<<16>>16;oa=(c[M>>2]|0)==((c[n>>2]|0)+ -1|0)|0;A=c[v>>2]|0;c[r>>2]=(c[r>>2]|0)-A;pa=(c[w>>2]|0)+A|0;c[w>>2]=pa;c[v>>2]=0;sa=pa;ta=oa}else{na=P;z=166}}else{na=P;z=166}}else{na=0;z=166}}if((z|0)==166){z=0;oa=a[(c[t>>2]|0)+na|0]|0;pa=c[M>>2]|0;b[(c[H>>2]|0)+(pa<<1)>>1]=0;c[M>>2]=pa+1;a[(c[K>>2]|0)+pa|0]=oa;pa=k+((oa&255)<<2)+148|0;b[pa>>1]=(b[pa>>1]|0)+1<<16>>16;pa=(c[M>>2]|0)==((c[n>>2]|0)+ -1|0)|0;c[r>>2]=(c[r>>2]|0)+ -1;oa=(c[w>>2]|0)+1|0;c[w>>2]=oa;sa=oa;ta=pa}if((ta|0)==0){continue}pa=c[O>>2]|0;if((pa|0)>-1){ua=(c[t>>2]|0)+pa|0}else{ua=0}Sf(k,ua,sa-pa|0,0);c[O>>2]=c[w>>2];pa=c[k>>2]|0;oa=pa+28|0;A=c[oa>>2]|0;va=c[A+20>>2]|0;wa=pa+16|0;xa=c[wa>>2]|0;ya=va>>>0>xa>>>0?xa:va;if((ya|0)!=0?(va=pa+12|0,Kg(c[va>>2]|0,c[A+16>>2]|0,ya|0)|0,c[va>>2]=(c[va>>2]|0)+ya,va=(c[oa>>2]|0)+16|0,c[va>>2]=(c[va>>2]|0)+ya,va=pa+20|0,c[va>>2]=(c[va>>2]|0)+ya,c[wa>>2]=(c[wa>>2]|0)-ya,wa=c[oa>>2]|0,oa=wa+20|0,va=c[oa>>2]|0,c[oa>>2]=va-ya,(va|0)==(ya|0)):0){c[wa+16>>2]=c[wa+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){break b}}r=c[O>>2]|0;if((r|0)>-1){za=(c[t>>2]|0)+r|0}else{za=0}Sf(k,za,(c[w>>2]|0)-r|0,o&1);c[O>>2]=c[w>>2];r=c[k>>2]|0;n=r+28|0;M=c[n>>2]|0;K=c[M+20>>2]|0;H=r+16|0;v=c[H>>2]|0;L=K>>>0>v>>>0?v:K;if((L|0)!=0?(K=r+12|0,Kg(c[K>>2]|0,c[M+16>>2]|0,L|0)|0,c[K>>2]=(c[K>>2]|0)+L,K=(c[n>>2]|0)+16|0,c[K>>2]=(c[K>>2]|0)+L,K=r+20|0,c[K>>2]=(c[K>>2]|0)+L,c[H>>2]=(c[H>>2]|0)-L,H=c[n>>2]|0,n=H+20|0,K=c[n>>2]|0,c[n>>2]=K-L,(K|0)==(L|0)):0){c[H+16>>2]=c[H+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){Aa=o?2:0;z=183;break}else{Aa=o?3:1;z=183;break}}else if((s|0)==2){H=k+116|0;L=k+96|0;K=k+108|0;n=k+56|0;r=k+5792|0;M=k+5796|0;v=k+5784|0;Q=k+5788|0;wa=k+92|0;while(1){if((c[H>>2]|0)==0?(mf(k),(c[H>>2]|0)==0):0){break}c[L>>2]=0;ya=a[(c[n>>2]|0)+(c[K>>2]|0)|0]|0;va=c[r>>2]|0;b[(c[M>>2]|0)+(va<<1)>>1]=0;c[r>>2]=va+1;a[(c[v>>2]|0)+va|0]=ya;va=k+((ya&255)<<2)+148|0;b[va>>1]=(b[va>>1]|0)+1<<16>>16;va=(c[r>>2]|0)==((c[Q>>2]|0)+ -1|0);c[H>>2]=(c[H>>2]|0)+ -1;ya=(c[K>>2]|0)+1|0;c[K>>2]=ya;if(!va){continue}va=c[wa>>2]|0;if((va|0)>-1){Ba=(c[n>>2]|0)+va|0}else{Ba=0}Sf(k,Ba,ya-va|0,0);c[wa>>2]=c[K>>2];va=c[k>>2]|0;ya=va+28|0;oa=c[ya>>2]|0;pa=c[oa+20>>2]|0;A=va+16|0;xa=c[A>>2]|0;Ca=pa>>>0>xa>>>0?xa:pa;if((Ca|0)!=0?(pa=va+12|0,Kg(c[pa>>2]|0,c[oa+16>>2]|0,Ca|0)|0,c[pa>>2]=(c[pa>>2]|0)+Ca,pa=(c[ya>>2]|0)+16|0,c[pa>>2]=(c[pa>>2]|0)+Ca,pa=va+20|0,c[pa>>2]=(c[pa>>2]|0)+Ca,c[A>>2]=(c[A>>2]|0)-Ca,A=c[ya>>2]|0,ya=A+20|0,pa=c[ya>>2]|0,c[ya>>2]=pa-Ca,(pa|0)==(Ca|0)):0){c[A+16>>2]=c[A+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){break b}}if((f|0)!=0){H=c[wa>>2]|0;if((H|0)>-1){Da=(c[n>>2]|0)+H|0}else{Da=0}Sf(k,Da,(c[K>>2]|0)-H|0,o&1);c[wa>>2]=c[K>>2];H=c[k>>2]|0;Q=H+28|0;r=c[Q>>2]|0;v=c[r+20>>2]|0;M=H+16|0;L=c[M>>2]|0;w=v>>>0>L>>>0?L:v;if((w|0)!=0?(v=H+12|0,Kg(c[v>>2]|0,c[r+16>>2]|0,w|0)|0,c[v>>2]=(c[v>>2]|0)+w,v=(c[Q>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+w,v=H+20|0,c[v>>2]=(c[v>>2]|0)+w,c[M>>2]=(c[M>>2]|0)-w,M=c[Q>>2]|0,Q=M+20|0,v=c[Q>>2]|0,c[Q>>2]=v-w,(v|0)==(w|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){Aa=o?2:0;z=183;break}else{Aa=o?3:1;z=183;break}}}else{Aa=nb[c[21168+((c[k+132>>2]|0)*12|0)>>2]&7](k,f)|0;z=183}}while(0);if((z|0)==183){if((Aa&-2|0)==2){c[m>>2]=666}if((Aa&-3|0)!=0){if((Aa|0)!=1){break}if((f|0)==1){Rf(k)}else if(((f|0)!=5?(Qf(k,0,0,0),(f|0)==3):0)?(s=c[k+76>>2]|0,x=c[k+68>>2]|0,b[x+(s+ -1<<1)>>1]=0,Eg(x|0,0,(s<<1)+ -2|0)|0,(c[k+116>>2]|0)==0):0){c[k+108>>2]=0;c[k+92>>2]=0}s=c[j>>2]|0;x=c[s+20>>2]|0;J=c[p>>2]|0;I=x>>>0>J>>>0?J:x;if((I|0)==0){Ea=J}else{Kg(c[l>>2]|0,c[s+16>>2]|0,I|0)|0;c[l>>2]=(c[l>>2]|0)+I;s=(c[j>>2]|0)+16|0;c[s>>2]=(c[s>>2]|0)+I;s=e+20|0;c[s>>2]=(c[s>>2]|0)+I;c[p>>2]=(c[p>>2]|0)-I;s=c[j>>2]|0;J=s+20|0;x=c[J>>2]|0;c[J>>2]=x-I;if((x|0)==(I|0)){c[s+16>>2]=c[s+8>>2]}Ea=c[p>>2]|0}if((Ea|0)!=0){break}c[q>>2]=-1;h=0;i=g;return h|0}}if((c[p>>2]|0)!=0){h=0;i=g;return h|0}c[q>>2]=-1;h=0;i=g;return h|0}}while(0);if(!o){h=0;i=g;return h|0}q=k+24|0;m=c[q>>2]|0;if((m|0)<1){h=1;i=g;return h|0}s=e+48|0;I=c[s>>2]|0;if((m|0)==2){m=c[N>>2]|0;c[N>>2]=m+1;x=k+8|0;a[(c[x>>2]|0)+m|0]=I;m=(c[s>>2]|0)>>>8&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=(c[s>>2]|0)>>>16&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=(c[s>>2]|0)>>>24&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=e+8|0;J=c[m>>2]&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>8&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>16&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>24&255;m=c[N>>2]|0;c[N>>2]=m+1;a[(c[x>>2]|0)+m|0]=J}else{J=c[N>>2]|0;c[N>>2]=J+1;m=k+8|0;a[(c[m>>2]|0)+J|0]=I>>>24;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[m>>2]|0)+J|0]=I>>>16;I=c[s>>2]|0;s=c[N>>2]|0;c[N>>2]=s+1;a[(c[m>>2]|0)+s|0]=I>>>8;s=c[N>>2]|0;c[N>>2]=s+1;a[(c[m>>2]|0)+s|0]=I}I=c[j>>2]|0;s=c[I+20>>2]|0;m=c[p>>2]|0;J=s>>>0>m>>>0?m:s;if((J|0)!=0?(Kg(c[l>>2]|0,c[I+16>>2]|0,J|0)|0,c[l>>2]=(c[l>>2]|0)+J,I=(c[j>>2]|0)+16|0,c[I>>2]=(c[I>>2]|0)+J,I=e+20|0,c[I>>2]=(c[I>>2]|0)+J,c[p>>2]=(c[p>>2]|0)-J,I=c[j>>2]|0,s=I+20|0,m=c[s>>2]|0,c[s>>2]=m-J,(m|0)==(J|0)):0){c[I+16>>2]=c[I+8>>2]}I=c[q>>2]|0;if((I|0)>0){c[q>>2]=0-I}h=(c[N>>2]|0)==0|0;i=g;return h|0}}}while(0);c[e+24>>2]=c[27624>>2];h=-2;i=g;return h|0}function mf(a){a=a|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;f=i;g=a+44|0;h=c[g>>2]|0;j=a+60|0;k=a+116|0;l=a+108|0;m=h+ -262|0;n=a+56|0;o=a+72|0;p=a+88|0;q=a+84|0;r=a+112|0;s=a+92|0;t=a+76|0;u=a+68|0;v=a+64|0;w=c[k>>2]|0;x=h;while(1){y=c[l>>2]|0;z=(c[j>>2]|0)-w-y|0;if(y>>>0<(m+x|0)>>>0){A=y;B=z}else{y=c[n>>2]|0;Kg(y|0,y+h|0,h|0)|0;c[r>>2]=(c[r>>2]|0)-h;y=(c[l>>2]|0)-h|0;c[l>>2]=y;c[s>>2]=(c[s>>2]|0)-h;C=c[t>>2]|0;D=C;E=(c[u>>2]|0)+(C<<1)|0;do{E=E+ -2|0;C=e[E>>1]|0;if(C>>>0>>0){F=0}else{F=C-h&65535}b[E>>1]=F;D=D+ -1|0}while((D|0)!=0);D=h;E=(c[v>>2]|0)+(h<<1)|0;do{E=E+ -2|0;C=e[E>>1]|0;if(C>>>0>>0){G=0}else{G=C-h&65535}b[E>>1]=G;D=D+ -1|0}while((D|0)!=0);A=y;B=z+h|0}D=c[a>>2]|0;E=D+4|0;C=c[E>>2]|0;if((C|0)==0){H=28;break}I=c[k>>2]|0;J=(c[n>>2]|0)+(I+A)|0;K=C>>>0>B>>>0?B:C;if((K|0)==0){L=0;M=I}else{c[E>>2]=C-K;C=c[(c[D+28>>2]|0)+24>>2]|0;if((C|0)==2){E=D+48|0;c[E>>2]=gf(c[E>>2]|0,c[D>>2]|0,K)|0;N=D}else if((C|0)==1){C=D+48|0;c[C>>2]=ff(c[C>>2]|0,c[D>>2]|0,K)|0;N=D}else{N=D}Kg(J|0,c[N>>2]|0,K|0)|0;c[N>>2]=(c[N>>2]|0)+K;J=D+8|0;c[J>>2]=(c[J>>2]|0)+K;L=K;M=c[k>>2]|0}O=M+L|0;c[k>>2]=O;if(O>>>0>2?(K=c[l>>2]|0,J=c[n>>2]|0,D=d[J+K|0]|0,c[o>>2]=D,c[o>>2]=((d[J+(K+1)|0]|0)^D<>2])&c[q>>2],!(O>>>0<262)):0){break}if((c[(c[a>>2]|0)+4>>2]|0)==0){break}w=O;x=c[g>>2]|0}if((H|0)==28){i=f;return}H=a+5824|0;a=c[H>>2]|0;g=c[j>>2]|0;if(!(a>>>0>>0)){i=f;return}j=O+(c[l>>2]|0)|0;if(a>>>0>>0){l=g-j|0;O=l>>>0>258?258:l;Eg((c[n>>2]|0)+j|0,0,O|0)|0;c[H>>2]=O+j;i=f;return}O=j+258|0;if(!(a>>>0>>0)){i=f;return}j=O-a|0;O=g-a|0;g=j>>>0>O>>>0?O:j;Eg((c[n>>2]|0)+a|0,0,g|0)|0;c[H>>2]=(c[H>>2]|0)+g;i=f;return}function nf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;d=i;e=(c[a+12>>2]|0)+ -5|0;f=e>>>0<65535?e:65535;e=a+116|0;g=a+108|0;h=a+92|0;j=a+44|0;k=a+56|0;while(1){l=c[e>>2]|0;if(l>>>0<2){mf(a);m=c[e>>2]|0;if((m|b|0)==0){n=0;o=28;break}if((m|0)==0){o=20;break}else{p=m}}else{p=l}l=(c[g>>2]|0)+p|0;c[g>>2]=l;c[e>>2]=0;m=c[h>>2]|0;q=m+f|0;if((l|0)!=0&l>>>0>>0){r=l;s=m}else{c[e>>2]=l-q;c[g>>2]=q;if((m|0)>-1){t=(c[k>>2]|0)+m|0}else{t=0}Sf(a,t,f,0);c[h>>2]=c[g>>2];m=c[a>>2]|0;q=m+28|0;l=c[q>>2]|0;u=c[l+20>>2]|0;v=m+16|0;w=c[v>>2]|0;x=u>>>0>w>>>0?w:u;if((x|0)!=0?(u=m+12|0,Kg(c[u>>2]|0,c[l+16>>2]|0,x|0)|0,c[u>>2]=(c[u>>2]|0)+x,u=(c[q>>2]|0)+16|0,c[u>>2]=(c[u>>2]|0)+x,u=m+20|0,c[u>>2]=(c[u>>2]|0)+x,c[v>>2]=(c[v>>2]|0)-x,v=c[q>>2]|0,q=v+20|0,u=c[q>>2]|0,c[q>>2]=u-x,(u|0)==(x|0)):0){c[v+16>>2]=c[v+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=0;o=28;break}r=c[g>>2]|0;s=c[h>>2]|0}v=r-s|0;if(v>>>0<((c[j>>2]|0)+ -262|0)>>>0){continue}if((s|0)>-1){y=(c[k>>2]|0)+s|0}else{y=0}Sf(a,y,v,0);c[h>>2]=c[g>>2];v=c[a>>2]|0;x=v+28|0;u=c[x>>2]|0;q=c[u+20>>2]|0;m=v+16|0;l=c[m>>2]|0;w=q>>>0>l>>>0?l:q;if((w|0)!=0?(q=v+12|0,Kg(c[q>>2]|0,c[u+16>>2]|0,w|0)|0,c[q>>2]=(c[q>>2]|0)+w,q=(c[x>>2]|0)+16|0,c[q>>2]=(c[q>>2]|0)+w,q=v+20|0,c[q>>2]=(c[q>>2]|0)+w,c[m>>2]=(c[m>>2]|0)-w,m=c[x>>2]|0,x=m+20|0,q=c[x>>2]|0,c[x>>2]=q-w,(q|0)==(w|0)):0){c[m+16>>2]=c[m+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=0;o=28;break}}if((o|0)==20){y=c[h>>2]|0;if((y|0)>-1){z=(c[k>>2]|0)+y|0}else{z=0}k=(b|0)==4;Sf(a,z,(c[g>>2]|0)-y|0,k&1);c[h>>2]=c[g>>2];g=c[a>>2]|0;h=g+28|0;y=c[h>>2]|0;z=c[y+20>>2]|0;b=g+16|0;s=c[b>>2]|0;j=z>>>0>s>>>0?s:z;if((j|0)!=0?(z=g+12|0,Kg(c[z>>2]|0,c[y+16>>2]|0,j|0)|0,c[z>>2]=(c[z>>2]|0)+j,z=(c[h>>2]|0)+16|0,c[z>>2]=(c[z>>2]|0)+j,z=g+20|0,c[z>>2]=(c[z>>2]|0)+j,c[b>>2]=(c[b>>2]|0)-j,b=c[h>>2]|0,h=b+20|0,z=c[h>>2]|0,c[h>>2]=z-j,(z|0)==(j|0)):0){c[b+16>>2]=c[b+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=k?2:0;i=d;return n|0}else{n=k?3:1;i=d;return n|0}}else if((o|0)==28){i=d;return n|0}return 0}function of(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0;g=i;h=e+116|0;j=(f|0)==0;k=e+72|0;l=e+88|0;m=e+108|0;n=e+56|0;o=e+84|0;p=e+68|0;q=e+52|0;r=e+64|0;s=e+44|0;t=e+96|0;u=e+112|0;v=e+5792|0;w=e+5796|0;x=e+5784|0;y=e+5788|0;z=e+128|0;A=e+92|0;while(1){if((c[h>>2]|0)>>>0<262){mf(e);B=c[h>>2]|0;if(B>>>0<262&j){C=0;D=34;break}if((B|0)==0){D=26;break}if(!(B>>>0>2)){D=9}else{D=6}}else{D=6}if((D|0)==6){D=0;B=c[m>>2]|0;E=((d[(c[n>>2]|0)+(B+2)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=E;F=(c[p>>2]|0)+(E<<1)|0;E=b[F>>1]|0;b[(c[r>>2]|0)+((c[q>>2]&B)<<1)>>1]=E;G=E&65535;b[F>>1]=B;if(!(E<<16>>16==0)?!((B-G|0)>>>0>((c[s>>2]|0)+ -262|0)>>>0):0){B=qf(e,G)|0;c[t>>2]=B;H=B}else{D=9}}if((D|0)==9){D=0;H=c[t>>2]|0}do{if(H>>>0>2){B=H+253|0;G=(c[m>>2]|0)-(c[u>>2]|0)|0;E=c[v>>2]|0;b[(c[w>>2]|0)+(E<<1)>>1]=G;c[v>>2]=E+1;a[(c[x>>2]|0)+E|0]=B;E=e+((d[25272+(B&255)|0]|0|256)+1<<2)+148|0;b[E>>1]=(b[E>>1]|0)+1<<16>>16;E=G+65535&65535;if(E>>>0<256){I=E}else{I=(E>>>7)+256|0}E=e+((d[24760+I|0]|0)<<2)+2440|0;b[E>>1]=(b[E>>1]|0)+1<<16>>16;E=(c[v>>2]|0)==((c[y>>2]|0)+ -1|0)|0;G=c[t>>2]|0;B=(c[h>>2]|0)-G|0;c[h>>2]=B;if(!(G>>>0<=(c[z>>2]|0)>>>0&B>>>0>2)){B=(c[m>>2]|0)+G|0;c[m>>2]=B;c[t>>2]=0;F=c[n>>2]|0;J=d[F+B|0]|0;c[k>>2]=J;c[k>>2]=((d[F+(B+1)|0]|0)^J<>2])&c[o>>2];K=B;L=E;break}B=G+ -1|0;c[t>>2]=B;G=c[l>>2]|0;J=c[n>>2]|0;F=c[o>>2]|0;M=c[p>>2]|0;N=c[q>>2]|0;O=c[r>>2]|0;P=B;B=c[m>>2]|0;Q=c[k>>2]|0;while(1){R=B+1|0;c[m>>2]=R;Q=((d[J+(B+3)|0]|0)^Q<>2]=Q;S=M+(Q<<1)|0;b[O+((N&R)<<1)>>1]=b[S>>1]|0;b[S>>1]=R;P=P+ -1|0;c[t>>2]=P;if((P|0)==0){break}else{B=R}}P=B+2|0;c[m>>2]=P;K=P;L=E}else{P=a[(c[n>>2]|0)+(c[m>>2]|0)|0]|0;N=c[v>>2]|0;b[(c[w>>2]|0)+(N<<1)>>1]=0;c[v>>2]=N+1;a[(c[x>>2]|0)+N|0]=P;N=e+((P&255)<<2)+148|0;b[N>>1]=(b[N>>1]|0)+1<<16>>16;N=(c[v>>2]|0)==((c[y>>2]|0)+ -1|0)|0;c[h>>2]=(c[h>>2]|0)+ -1;P=(c[m>>2]|0)+1|0;c[m>>2]=P;K=P;L=N}}while(0);if((L|0)==0){continue}N=c[A>>2]|0;if((N|0)>-1){T=(c[n>>2]|0)+N|0}else{T=0}Sf(e,T,K-N|0,0);c[A>>2]=c[m>>2];N=c[e>>2]|0;P=N+28|0;O=c[P>>2]|0;Q=c[O+20>>2]|0;M=N+16|0;F=c[M>>2]|0;G=Q>>>0>F>>>0?F:Q;if((G|0)!=0?(Q=N+12|0,Kg(c[Q>>2]|0,c[O+16>>2]|0,G|0)|0,c[Q>>2]=(c[Q>>2]|0)+G,Q=(c[P>>2]|0)+16|0,c[Q>>2]=(c[Q>>2]|0)+G,Q=N+20|0,c[Q>>2]=(c[Q>>2]|0)+G,c[M>>2]=(c[M>>2]|0)-G,M=c[P>>2]|0,P=M+20|0,Q=c[P>>2]|0,c[P>>2]=Q-G,(Q|0)==(G|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){C=0;D=34;break}}if((D|0)==26){K=c[A>>2]|0;if((K|0)>-1){U=(c[n>>2]|0)+K|0}else{U=0}n=(f|0)==4;Sf(e,U,(c[m>>2]|0)-K|0,n&1);c[A>>2]=c[m>>2];m=c[e>>2]|0;A=m+28|0;K=c[A>>2]|0;U=c[K+20>>2]|0;f=m+16|0;T=c[f>>2]|0;L=U>>>0>T>>>0?T:U;if((L|0)!=0?(U=m+12|0,Kg(c[U>>2]|0,c[K+16>>2]|0,L|0)|0,c[U>>2]=(c[U>>2]|0)+L,U=(c[A>>2]|0)+16|0,c[U>>2]=(c[U>>2]|0)+L,U=m+20|0,c[U>>2]=(c[U>>2]|0)+L,c[f>>2]=(c[f>>2]|0)-L,f=c[A>>2]|0,A=f+20|0,U=c[A>>2]|0,c[A>>2]=U-L,(U|0)==(L|0)):0){c[f+16>>2]=c[f+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){C=n?2:0;i=g;return C|0}else{C=n?3:1;i=g;return C|0}}else if((D|0)==34){i=g;return C|0}return 0}function pf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0;g=i;h=e+116|0;j=(f|0)==0;k=e+72|0;l=e+88|0;m=e+108|0;n=e+56|0;o=e+84|0;p=e+68|0;q=e+52|0;r=e+64|0;s=e+96|0;t=e+120|0;u=e+112|0;v=e+100|0;w=e+5792|0;x=e+5796|0;y=e+5784|0;z=e+5788|0;A=e+104|0;B=e+92|0;C=e+128|0;D=e+44|0;E=e+136|0;a:while(1){F=c[h>>2]|0;while(1){if(F>>>0<262){mf(e);G=c[h>>2]|0;if(G>>>0<262&j){H=0;I=50;break a}if((G|0)==0){I=40;break a}if(!(G>>>0>2)){c[t>>2]=c[s>>2];c[v>>2]=c[u>>2];c[s>>2]=2;J=2;I=16}else{I=8}}else{I=8}do{if((I|0)==8){I=0;G=c[m>>2]|0;K=((d[(c[n>>2]|0)+(G+2)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=K;L=(c[p>>2]|0)+(K<<1)|0;K=b[L>>1]|0;b[(c[r>>2]|0)+((c[q>>2]&G)<<1)>>1]=K;M=K&65535;b[L>>1]=G;G=c[s>>2]|0;c[t>>2]=G;c[v>>2]=c[u>>2];c[s>>2]=2;if(!(K<<16>>16==0)){if(G>>>0<(c[C>>2]|0)>>>0){if(!(((c[m>>2]|0)-M|0)>>>0>((c[D>>2]|0)+ -262|0)>>>0)){K=qf(e,M)|0;c[s>>2]=K;if(K>>>0<6){if((c[E>>2]|0)!=1){if((K|0)!=3){J=K;I=16;break}if(!(((c[m>>2]|0)-(c[u>>2]|0)|0)>>>0>4096)){J=3;I=16;break}}c[s>>2]=2;J=2;I=16}else{J=K;I=16}}else{J=2;I=16}}else{N=G;O=2}}else{J=2;I=16}}}while(0);if((I|0)==16){I=0;N=c[t>>2]|0;O=J}if(!(N>>>0<3|O>>>0>N>>>0)){break}if((c[A>>2]|0)==0){c[A>>2]=1;c[m>>2]=(c[m>>2]|0)+1;G=(c[h>>2]|0)+ -1|0;c[h>>2]=G;F=G;continue}G=a[(c[n>>2]|0)+((c[m>>2]|0)+ -1)|0]|0;K=c[w>>2]|0;b[(c[x>>2]|0)+(K<<1)>>1]=0;c[w>>2]=K+1;a[(c[y>>2]|0)+K|0]=G;K=e+((G&255)<<2)+148|0;b[K>>1]=(b[K>>1]|0)+1<<16>>16;if((c[w>>2]|0)==((c[z>>2]|0)+ -1|0)){K=c[B>>2]|0;if((K|0)>-1){P=(c[n>>2]|0)+K|0}else{P=0}Sf(e,P,(c[m>>2]|0)-K|0,0);c[B>>2]=c[m>>2];K=c[e>>2]|0;G=K+28|0;M=c[G>>2]|0;L=c[M+20>>2]|0;Q=K+16|0;R=c[Q>>2]|0;S=L>>>0>R>>>0?R:L;if((S|0)!=0?(L=K+12|0,Kg(c[L>>2]|0,c[M+16>>2]|0,S|0)|0,c[L>>2]=(c[L>>2]|0)+S,L=(c[G>>2]|0)+16|0,c[L>>2]=(c[L>>2]|0)+S,L=K+20|0,c[L>>2]=(c[L>>2]|0)+S,c[Q>>2]=(c[Q>>2]|0)-S,Q=c[G>>2]|0,G=Q+20|0,L=c[G>>2]|0,c[G>>2]=L-S,(L|0)==(S|0)):0){c[Q+16>>2]=c[Q+8>>2]}}c[m>>2]=(c[m>>2]|0)+1;Q=(c[h>>2]|0)+ -1|0;c[h>>2]=Q;if((c[(c[e>>2]|0)+16>>2]|0)==0){H=0;I=50;break a}else{F=Q}}F=c[m>>2]|0;Q=F+ -3+(c[h>>2]|0)|0;S=N+253|0;L=F+65535-(c[v>>2]|0)|0;F=c[w>>2]|0;b[(c[x>>2]|0)+(F<<1)>>1]=L;c[w>>2]=F+1;a[(c[y>>2]|0)+F|0]=S;F=e+((d[25272+(S&255)|0]|0|256)+1<<2)+148|0;b[F>>1]=(b[F>>1]|0)+1<<16>>16;F=L+65535&65535;if(F>>>0<256){T=F}else{T=(F>>>7)+256|0}F=e+((d[24760+T|0]|0)<<2)+2440|0;b[F>>1]=(b[F>>1]|0)+1<<16>>16;F=c[w>>2]|0;L=(c[z>>2]|0)+ -1|0;S=c[t>>2]|0;c[h>>2]=1-S+(c[h>>2]|0);G=S+ -2|0;c[t>>2]=G;S=c[m>>2]|0;K=G;while(1){G=S+1|0;c[m>>2]=G;if(!(G>>>0>Q>>>0)){M=((d[(c[n>>2]|0)+(S+3)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=M;R=(c[p>>2]|0)+(M<<1)|0;b[(c[r>>2]|0)+((c[q>>2]&G)<<1)>>1]=b[R>>1]|0;b[R>>1]=G}K=K+ -1|0;c[t>>2]=K;if((K|0)==0){break}else{S=G}}c[A>>2]=0;c[s>>2]=2;K=S+2|0;c[m>>2]=K;if((F|0)!=(L|0)){continue}Q=c[B>>2]|0;if((Q|0)>-1){U=(c[n>>2]|0)+Q|0}else{U=0}Sf(e,U,K-Q|0,0);c[B>>2]=c[m>>2];Q=c[e>>2]|0;K=Q+28|0;G=c[K>>2]|0;R=c[G+20>>2]|0;M=Q+16|0;V=c[M>>2]|0;W=R>>>0>V>>>0?V:R;if((W|0)!=0?(R=Q+12|0,Kg(c[R>>2]|0,c[G+16>>2]|0,W|0)|0,c[R>>2]=(c[R>>2]|0)+W,R=(c[K>>2]|0)+16|0,c[R>>2]=(c[R>>2]|0)+W,R=Q+20|0,c[R>>2]=(c[R>>2]|0)+W,c[M>>2]=(c[M>>2]|0)-W,M=c[K>>2]|0,K=M+20|0,R=c[K>>2]|0,c[K>>2]=R-W,(R|0)==(W|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){H=0;I=50;break}}if((I|0)==40){if((c[A>>2]|0)!=0){U=a[(c[n>>2]|0)+((c[m>>2]|0)+ -1)|0]|0;s=c[w>>2]|0;b[(c[x>>2]|0)+(s<<1)>>1]=0;c[w>>2]=s+1;a[(c[y>>2]|0)+s|0]=U;s=e+((U&255)<<2)+148|0;b[s>>1]=(b[s>>1]|0)+1<<16>>16;c[A>>2]=0}A=c[B>>2]|0;if((A|0)>-1){X=(c[n>>2]|0)+A|0}else{X=0}n=(f|0)==4;Sf(e,X,(c[m>>2]|0)-A|0,n&1);c[B>>2]=c[m>>2];m=c[e>>2]|0;B=m+28|0;A=c[B>>2]|0;X=c[A+20>>2]|0;f=m+16|0;s=c[f>>2]|0;U=X>>>0>s>>>0?s:X;if((U|0)!=0?(X=m+12|0,Kg(c[X>>2]|0,c[A+16>>2]|0,U|0)|0,c[X>>2]=(c[X>>2]|0)+U,X=(c[B>>2]|0)+16|0,c[X>>2]=(c[X>>2]|0)+U,X=m+20|0,c[X>>2]=(c[X>>2]|0)+U,c[f>>2]=(c[f>>2]|0)-U,f=c[B>>2]|0,B=f+20|0,X=c[B>>2]|0,c[B>>2]=X-U,(X|0)==(U|0)):0){c[f+16>>2]=c[f+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){H=n?2:0;i=g;return H|0}else{H=n?3:1;i=g;return H|0}}else if((I|0)==50){i=g;return H|0}return 0}function qf(b,d){b=b|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;f=i;g=c[b+124>>2]|0;h=c[b+56>>2]|0;j=c[b+108>>2]|0;k=h+j|0;l=c[b+120>>2]|0;m=c[b+144>>2]|0;n=(c[b+44>>2]|0)+ -262|0;o=j>>>0>n>>>0?j-n|0:0;n=c[b+64>>2]|0;p=c[b+52>>2]|0;q=h+(j+258)|0;r=c[b+116>>2]|0;s=m>>>0>r>>>0?r:m;m=b+112|0;t=h+(j+1)|0;u=h+(j+2)|0;v=q;w=j+257|0;x=d;d=l;y=l>>>0<(c[b+140>>2]|0)>>>0?g:g>>>2;g=a[h+(l+j)|0]|0;b=a[h+(j+ -1+l)|0]|0;while(1){l=h+x|0;if((((a[h+(x+d)|0]|0)==g<<24>>24?(a[h+(d+ -1+x)|0]|0)==b<<24>>24:0)?(a[l]|0)==(a[k]|0):0)?(a[h+(x+1)|0]|0)==(a[t]|0):0){l=h+(x+2)|0;z=u;while(1){A=z+1|0;if((a[A]|0)!=(a[l+1|0]|0)){B=A;break}A=z+2|0;if((a[A]|0)!=(a[l+2|0]|0)){B=A;break}A=z+3|0;if((a[A]|0)!=(a[l+3|0]|0)){B=A;break}A=z+4|0;if((a[A]|0)!=(a[l+4|0]|0)){B=A;break}A=z+5|0;if((a[A]|0)!=(a[l+5|0]|0)){B=A;break}A=z+6|0;if((a[A]|0)!=(a[l+6|0]|0)){B=A;break}A=z+7|0;if((a[A]|0)!=(a[l+7|0]|0)){B=A;break}A=z+8|0;C=l+8|0;if((a[A]|0)==(a[C]|0)&A>>>0>>0){l=C;z=A}else{B=A;break}}z=B-v|0;l=z+258|0;if((l|0)>(d|0)){c[m>>2]=x;if((l|0)>=(s|0)){D=l;E=20;break}F=l;G=a[h+(l+j)|0]|0;H=a[h+(w+z)|0]|0}else{F=d;G=g;H=b}}else{F=d;G=g;H=b}z=e[n+((x&p)<<1)>>1]|0;if(!(z>>>0>o>>>0)){D=F;E=20;break}l=y+ -1|0;if((l|0)==0){D=F;E=20;break}else{x=z;d=F;y=l;g=G;b=H}}if((E|0)==20){i=f;return(D>>>0>r>>>0?r:D)|0}return 0}function rf(a){a=a|0;var b=0,d=0;b=i;do{if((a|0)!=0){if((c[a>>2]|0)==7247){d=Af(a)|0;break}else{d=Ff(a)|0;break}}else{d=-2}}while(0);i=b;return d|0}function sf(a,b){a=a|0;b=b|0;var c=0,d=0;c=i;d=tf(a,-1,b)|0;i=c;return d|0}function tf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+16|0;g=f;h=gg(140)|0;if((h|0)==0){j=0;i=f;return j|0}c[h+16>>2]=0;c[h+20>>2]=8192;k=h+80|0;c[k>>2]=0;c[h>>2]=0;l=h+60|0;c[l>>2]=-1;m=h+64|0;c[m>>2]=0;n=a[e]|0;if(!(n<<24>>24==0)){o=e;e=n;n=0;a:while(1){p=e<<24>>24;b:do{if((e+ -48<<24>>24&255)<10){c[l>>2]=p+ -48;q=n}else{switch(p|0){case 70:{c[m>>2]=4;q=n;break b;break};case 43:{r=9;break a;break};case 82:{c[m>>2]=3;q=n;break b;break};case 102:{c[m>>2]=1;q=n;break b;break};case 104:{c[m>>2]=2;q=n;break b;break};case 119:{c[h>>2]=31153;q=31153;break b;break};case 97:{c[h>>2]=1;q=1;break b;break};case 114:{c[h>>2]=7247;q=7247;break b;break};default:{q=n;break b}}}}while(0);o=o+1|0;e=a[o]|0;if(e<<24>>24==0){break}else{n=q}}if((r|0)==9){hg(h);j=0;i=f;return j|0}if((q|0)!=0){q=gg((Dg(b|0)|0)+1|0)|0;r=h+8|0;c[r>>2]=q;if((q|0)==0){hg(h);j=0;i=f;return j|0}Lg(q|0,b|0)|0;if((d|0)==-1){q=c[h>>2]|0;if((q|0)==7247){s=32768}else{s=(q|0)==31153?33345:33857}c[g>>2]=438;q=Aa(b|0,s|0,g|0)|0;c[h+4>>2]=q;if((q|0)==-1){hg(c[r>>2]|0);hg(h);j=0;i=f;return j|0}else{t=q}}else{c[h+4>>2]=d;t=d}d=c[h>>2]|0;if((d|0)==1){c[h>>2]=31153}else if((d|0)==7247?(d=ra(t|0,0,1)|0,c[h+44>>2]=(d|0)==-1?0:d,(c[h>>2]|0)==7247):0){c[h+36>>2]=0;c[h+40>>2]=0;c[h+52>>2]=0;c[h+56>>2]=1}c[h+72>>2]=0;d=c[k>>2]|0;t=h+76|0;if((d|0)!=0){if(!((c[t>>2]|0)==-4)){hg(d)}c[k>>2]=0}c[t>>2]=0;c[h+12>>2]=0;c[h+88>>2]=0;j=h;i=f;return j|0}}hg(h);j=0;i=f;return j|0}function uf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;e=i;if((a|0)==0){f=-1;i=e;return f|0}g=c[a>>2]|0;if(!((g|0)==31153|(g|0)==7247)){f=-1;i=e;return f|0}h=a+76|0;if((c[h>>2]|0)!=0|d>>>0>1){f=-1;i=e;return f|0}if((d|0)!=0){d=a+72|0;if((c[d>>2]|0)==0){j=b;k=d}else{j=(c[a+68>>2]|0)+b|0;k=d}}else{j=b-(c[a+12>>2]|0)|0;k=a+72|0}c[k>>2]=0;b=(g|0)==7247;if((b?(c[a+52>>2]|0)==1:0)?(d=a+12|0,((c[d>>2]|0)+j|0)>=(c[a+48>>2]|0)):0){l=a+36|0;if((ra(c[a+4>>2]|0,j-(c[l>>2]|0)|0,1)|0)==-1){f=-1;i=e;return f|0}c[l>>2]=0;c[a+40>>2]=0;c[k>>2]=0;l=a+80|0;m=c[l>>2]|0;if((m|0)!=0){if(!((c[h>>2]|0)==-4)){hg(m)}c[l>>2]=0}c[h>>2]=0;c[a+88>>2]=0;l=(c[d>>2]|0)+j|0;c[d>>2]=l;f=l;i=e;return f|0}if((j|0)<0){if(!b){f=-1;i=e;return f|0}b=a+12|0;l=(c[b>>2]|0)+j|0;if((l|0)<0){f=-1;i=e;return f|0}if((ra(c[a+4>>2]|0,c[a+44>>2]|0,0)|0)==-1){f=-1;i=e;return f|0}d=c[a>>2]|0;if((d|0)==7247){c[a+36>>2]=0;c[a+40>>2]=0;c[a+52>>2]=0;c[a+56>>2]=1}c[k>>2]=0;m=a+80|0;n=c[m>>2]|0;if((n|0)==0){o=d}else{if((c[h>>2]|0)==-4){p=d}else{hg(n);p=c[a>>2]|0}c[m>>2]=0;o=p}c[h>>2]=0;c[b>>2]=0;c[a+88>>2]=0;q=l;r=o}else{q=j;r=g}if((r|0)==7247){r=a+36|0;g=c[r>>2]|0;j=(g|0)<0|(g|0)>(q|0)?q:g;c[r>>2]=g-j;g=a+32|0;c[g>>2]=(c[g>>2]|0)+j;g=a+12|0;c[g>>2]=j+(c[g>>2]|0);s=q-j|0}else{s=q}if((s|0)!=0){c[k>>2]=1;c[a+68>>2]=s}f=(c[a+12>>2]|0)+s|0;i=e;return f|0}function vf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;g=b+80|0;h=c[g>>2]|0;j=b+76|0;if((h|0)!=0){if(!((c[j>>2]|0)==-4)){hg(h)}c[g>>2]=0}c[j>>2]=d;if((e|0)==0){i=f;return}if((d|0)==-4){c[g>>2]=e;i=f;return}d=c[b+8>>2]|0;b=Dg(d|0)|0;h=gg(b+3+(Dg(e|0)|0)|0)|0;c[g>>2]=h;if((h|0)==0){c[j>>2]=-4;c[g>>2]=21280;i=f;return}else{Lg(h|0,d|0)|0;d=c[g>>2]|0;h=d+(Dg(d|0)|0)|0;a[h+0|0]=a[21296|0]|0;a[h+1|0]=a[21297|0]|0;a[h+2|0]=a[21298|0]|0;Fg(c[g>>2]|0,e|0)|0;i=f;return}}function wf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=uf(a,b,c)|0;i=d;return e|0}function xf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0;e=i;if((a|0)==0){f=-1;i=e;return f|0}if((c[a>>2]|0)!=7247){f=-1;i=e;return f|0}if((c[a+76>>2]|0)!=0){f=-1;i=e;return f|0}if((d|0)<0){vf(a,-5,21304);f=-1;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}g=a+72|0;a:do{if((c[g>>2]|0)!=0){c[g>>2]=0;h=c[a+68>>2]|0;j=a+36|0;k=a+40|0;l=a+88|0;m=a+32|0;n=a+12|0;if((h|0)!=0){o=a+52|0;p=a+28|0;q=a+16|0;r=a+4|0;s=a+100|0;t=a+96|0;u=h;b:while(1){c:while(1){v=c[j>>2]|0;while(1){if((v|0)!=0){break c}if((c[k>>2]|0)!=0?(c[l>>2]|0)==0:0){w=j;x=k;y=m;z=l;A=n;break a}h=c[o>>2]|0;if((h|0)!=0){B=h;break}if((zf(a)|0)==-1){f=-1;C=59;break b}h=c[j>>2]|0;if((h|0)==0){C=21;break}else{v=h}}if((C|0)==21){C=0;B=c[o>>2]|0}if((B|0)==2){c[s>>2]=c[q>>2]<<1;c[t>>2]=c[p>>2];if((yf(a)|0)==-1){f=-1;C=59;break b}else{continue}}else if((B|0)!=1){continue}h=c[p>>2]|0;D=c[q>>2]<<1;c[j>>2]=0;E=0;do{F=Za(c[r>>2]|0,h+E|0,D-E|0)|0;if((F|0)<1){C=26;break}E=(c[j>>2]|0)+F|0;c[j>>2]=E}while(E>>>0>>0);if((C|0)==26){C=0;if((F|0)<0){C=28;break b}c[k>>2]=1}c[m>>2]=c[p>>2]}D=(v|0)<0|(v|0)>(u|0)?u:v;c[j>>2]=v-D;c[m>>2]=(c[m>>2]|0)+D;c[n>>2]=(c[n>>2]|0)+D;if((u|0)==(D|0)){w=j;x=k;y=m;z=l;A=n;break a}else{u=u-D|0}}if((C|0)==28){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==59){i=e;return f|0}}else{w=j;x=k;y=m;z=l;A=n}}else{w=a+36|0;x=a+40|0;y=a+32|0;z=a+88|0;A=a+12|0}}while(0);v=a+52|0;F=a+28|0;B=a+16|0;g=a+4|0;u=a+100|0;p=a+96|0;r=b;b=d;d=0;d:while(1){q=c[w>>2]|0;e:do{if((q|0)==0){if((c[x>>2]|0)!=0?(c[z>>2]|0)==0:0){f=d;C=59;break d}t=c[v>>2]|0;if((t|0)!=0){if(b>>>0>2]<<1>>>0){G=t}else{if((t|0)==1){H=0}else{c[u>>2]=b;c[p>>2]=r;if((yf(a)|0)==-1){f=-1;C=59;break d}t=c[w>>2]|0;c[w>>2]=0;I=t;C=57;break}while(1){J=Za(c[g>>2]|0,r+H|0,b-H|0)|0;if((J|0)<1){break}t=J+H|0;if(t>>>0>>0){H=t}else{I=t;C=57;break e}}if((J|0)<0){C=54;break d}c[x>>2]=1;I=H;C=57;break}}else{if((zf(a)|0)==-1){f=-1;C=59;break d}if((c[w>>2]|0)!=0){K=r;L=b;M=d;break}G=c[v>>2]|0}if((G|0)==2){c[u>>2]=c[B>>2]<<1;c[p>>2]=c[F>>2];if((yf(a)|0)==-1){f=-1;C=59;break d}else{K=r;L=b;M=d;break}}else if((G|0)!=1){K=r;L=b;M=d;break}t=c[F>>2]|0;s=c[B>>2]<<1;c[w>>2]=0;o=0;do{N=Za(c[g>>2]|0,t+o|0,s-o|0)|0;if((N|0)<1){C=44;break}o=(c[w>>2]|0)+N|0;c[w>>2]=o}while(o>>>0>>0);if((C|0)==44){C=0;if((N|0)<0){C=46;break d}c[x>>2]=1}c[y>>2]=c[F>>2];K=r;L=b;M=d}else{s=q>>>0>b>>>0?b:q;Kg(r|0,c[y>>2]|0,s|0)|0;c[y>>2]=(c[y>>2]|0)+s;c[w>>2]=(c[w>>2]|0)-s;I=s;C=57}}while(0);if((C|0)==57){C=0;c[A>>2]=(c[A>>2]|0)+I;K=r+I|0;L=b-I|0;M=I+d|0}if((L|0)==0){f=M;C=59;break}else{r=K;b=L;d=M}}if((C|0)==46){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==54){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==59){i=e;return f|0}return 0}function yf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;b=i;i=i+16|0;d=b+4|0;e=b;f=a+84|0;g=a+100|0;h=c[g>>2]|0;j=a+88|0;k=a+76|0;l=a+40|0;m=a+24|0;n=a+16|0;o=a+4|0;p=a+84|0;while(1){if((c[j>>2]|0)==0){if((c[k>>2]|0)!=0){q=-1;r=27;break}if((c[l>>2]|0)!=0){r=12;break}s=c[m>>2]|0;t=c[n>>2]|0;c[j>>2]=0;u=0;while(1){v=Za(c[o>>2]|0,s+u|0,t-u|0)|0;if((v|0)<1){r=8;break}w=(c[j>>2]|0)+v|0;c[j>>2]=w;if(w>>>0>>0){u=w}else{x=w;break}}if((r|0)==8){r=0;if((v|0)<0){r=10;break}c[l>>2]=1;x=c[j>>2]|0}c[p>>2]=c[m>>2];if((x|0)==0){r=12;break}}u=Kf(f,0)|0;if((u|0)==-4){r=15;break}else if((u|0)==-3){r=16;break}else if((u|0)==2|(u|0)==-2){r=14;break}y=c[g>>2]|0;z=(u|0)==1;if((y|0)==0|z){r=18;break}}if((r|0)==10){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);q=-1;i=b;return q|0}else if((r|0)==12){vf(a,-3,21432);q=-1;i=b;return q|0}else if((r|0)==14){vf(a,-2,21456);q=-1;i=b;return q|0}else if((r|0)==15){vf(a,-4,21344);q=-1;i=b;return q|0}else if((r|0)==16){g=c[a+108>>2]|0;vf(a,-3,(g|0)==0?21496:g);q=-1;i=b;return q|0}else if((r|0)==18){g=h-y|0;c[a+36>>2]=g;y=(c[a+96>>2]|0)+(0-g)|0;c[a+32>>2]=y;h=a+132|0;c[h>>2]=gf(c[h>>2]|0,y,g)|0;if(!z){q=0;i=b;return q|0}if(!((Bf(a,d)|0)==-1)?!((Bf(a,e)|0)==-1):0){if((c[d>>2]|0)!=(c[h>>2]|0)){vf(a,-3,21520);q=-1;i=b;return q|0}if((c[e>>2]|0)==(c[a+104>>2]|0)){c[a+52>>2]=0;q=0;i=b;return q|0}else{vf(a,-3,21544);q=-1;i=b;return q|0}}vf(a,-3,21432);q=-1;i=b;return q|0}else if((r|0)==27){i=b;return q|0}return 0}function zf(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0;e=i;f=b+84|0;g=b+16|0;do{if((c[g>>2]|0)==0){h=c[b+20>>2]|0;j=gg(h)|0;k=b+24|0;c[k>>2]=j;l=gg(h<<1)|0;m=b+28|0;c[m>>2]=l;n=(l|0)==0;if(!((j|0)==0|n)){c[g>>2]=h;c[b+116>>2]=0;c[b+120>>2]=0;c[b+124>>2]=0;h=b+88|0;c[h>>2]=0;c[f>>2]=0;if((Jf(f,-15,21360,56)|0)==0){o=h;break}hg(c[m>>2]|0);hg(c[k>>2]|0);c[g>>2]=0;vf(b,-4,21344);p=-1;i=e;return p|0}if(n){q=j}else{hg(l);q=c[k>>2]|0}if((q|0)!=0){hg(q)}vf(b,-4,21344);p=-1;i=e;return p|0}else{o=b+88|0}}while(0);q=c[o>>2]|0;if((q|0)==0){if((c[b+76>>2]|0)!=0){p=-1;i=e;return p|0}k=b+40|0;if((c[k>>2]|0)!=0){p=0;i=e;return p|0}l=b+24|0;j=c[l>>2]|0;n=c[g>>2]|0;c[o>>2]=0;m=b+4|0;h=0;while(1){r=Za(c[m>>2]|0,j+h|0,n-h|0)|0;if((r|0)<1){s=17;break}t=(c[o>>2]|0)+r|0;c[o>>2]=t;if(t>>>0>>0){h=t}else{u=t;break}}do{if((s|0)==17){if((r|0)>=0){c[k>>2]=1;u=c[o>>2]|0;break}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);p=-1;i=e;return p|0}}while(0);c[b+84>>2]=c[l>>2];if((u|0)==0){p=0;i=e;return p|0}else{v=u}}else{v=q}q=c[f>>2]|0;if((a[q]|0)==31){u=v+ -1|0;c[o>>2]=u;l=q+1|0;c[f>>2]=l;if((u|0)==0){if((c[b+76>>2]|0)!=0){p=-1;i=e;return p|0}q=b+40|0;if((c[q>>2]|0)==0){k=b+24|0;r=c[k>>2]|0;h=c[g>>2]|0;c[o>>2]=0;n=b+4|0;j=0;while(1){w=Za(c[n>>2]|0,r+j|0,h-j|0)|0;if((w|0)<1){s=29;break}m=(c[o>>2]|0)+w|0;c[o>>2]=m;if(m>>>0>>0){j=m}else{x=m;break}}do{if((s|0)==29){if((w|0)>=0){c[q>>2]=1;x=c[o>>2]|0;break}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);p=-1;i=e;return p|0}}while(0);q=c[k>>2]|0;c[b+84>>2]=q;if((x|0)!=0){y=q;z=x;s=33}}}else{y=l;z=u;s=33}if((s|0)==33?(a[y]|0)==-117:0){u=z+ -1|0;c[o>>2]=u;z=y+1|0;c[f>>2]=z;a:do{if((u|0)==0){if((c[b+76>>2]|0)==0?(y=b+40|0,(c[y>>2]|0)==0):0){l=b+24|0;x=c[l>>2]|0;q=c[g>>2]|0;c[o>>2]=0;k=b+4|0;w=0;while(1){A=Za(c[k>>2]|0,x+w|0,q-w|0)|0;if((A|0)<1){s=40;break}j=(c[o>>2]|0)+A|0;c[o>>2]=j;if(j>>>0>>0){w=j}else{B=j;break}}do{if((s|0)==40){if((A|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break a}else{c[y>>2]=1;B=c[o>>2]|0;break}}}while(0);y=c[l>>2]|0;c[b+84>>2]=y;if((B|0)!=0){C=B;D=y;s=44}}}else{C=u;D=z;s=44}}while(0);if((s|0)==44?(z=C+ -1|0,c[o>>2]=z,C=D+1|0,c[f>>2]=C,(a[D]|0)==8):0){b:do{if((z|0)==0){if((c[b+76>>2]|0)==0?(D=b+40|0,(c[D>>2]|0)==0):0){u=b+24|0;B=c[u>>2]|0;A=c[g>>2]|0;c[o>>2]=0;y=b+4|0;w=0;while(1){E=Za(c[y>>2]|0,B+w|0,A-w|0)|0;if((E|0)<1){s=52;break}q=(c[o>>2]|0)+E|0;c[o>>2]=q;if(q>>>0>>0){w=q}else{F=q;break}}do{if((s|0)==52){if((E|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break b}else{c[D>>2]=1;F=c[o>>2]|0;break}}}while(0);D=c[u>>2]|0;c[b+84>>2]=D;if((F|0)!=0){G=F;H=D;s=56}}}else{G=z;H=C;s=56}}while(0);if((s|0)==56?(C=G+ -1|0,c[o>>2]=C,G=H+1|0,c[f>>2]=G,z=d[H]|0,(z&224|0)==0):0){c:do{if((C|0)==0){H=b+76|0;if((c[H>>2]|0)==0){F=b+40|0;if((c[F>>2]|0)==0){E=b+24|0;D=c[E>>2]|0;w=c[g>>2]|0;c[o>>2]=0;A=b+4|0;B=0;while(1){I=Za(c[A>>2]|0,D+B|0,w-B|0)|0;if((I|0)<1){s=64;break}y=(c[o>>2]|0)+I|0;c[o>>2]=y;if(y>>>0>>0){B=y}else{J=y;break}}do{if((s|0)==64){if((I|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);K=c[o>>2]|0;s=69;break c}else{c[F>>2]=1;J=c[o>>2]|0;break}}}while(0);F=c[E>>2]|0;c[b+84>>2]=F;if((J|0)!=0){L=J;M=F;s=68}else{N=H;s=71}}else{N=H;s=71}}else{s=70}}else{L=C;M=G;s=68}}while(0);if((s|0)==68){G=L+ -1|0;c[o>>2]=G;c[f>>2]=M+1;K=G;s=69}if((s|0)==69){if((K|0)==0){s=70}else{O=K;s=80}}if((s|0)==70){N=b+76|0;s=71}d:do{if((s|0)==71){if((c[N>>2]|0)==0){K=b+40|0;if((c[K>>2]|0)==0){G=b+24|0;M=c[G>>2]|0;L=c[g>>2]|0;c[o>>2]=0;C=b+4|0;J=0;while(1){P=Za(c[C>>2]|0,M+J|0,L-J|0)|0;if((P|0)<1){s=76;break}I=(c[o>>2]|0)+P|0;c[o>>2]=I;if(I>>>0>>0){J=I}else{Q=I;break}}do{if((s|0)==76){if((P|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);R=c[o>>2]|0;s=81;break d}else{c[K>>2]=1;Q=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[G>>2];if((Q|0)!=0){O=Q;s=80}else{S=N;s=83}}else{S=N;s=83}}else{s=82}}}while(0);if((s|0)==80){N=O+ -1|0;c[o>>2]=N;c[f>>2]=(c[f>>2]|0)+1;R=N;s=81}if((s|0)==81){if((R|0)==0){s=82}else{T=R;s=92}}if((s|0)==82){S=b+76|0;s=83}e:do{if((s|0)==83){if((c[S>>2]|0)==0){R=b+40|0;if((c[R>>2]|0)==0){N=b+24|0;O=c[N>>2]|0;Q=c[g>>2]|0;c[o>>2]=0;P=b+4|0;K=0;while(1){U=Za(c[P>>2]|0,O+K|0,Q-K|0)|0;if((U|0)<1){s=88;break}J=(c[o>>2]|0)+U|0;c[o>>2]=J;if(J>>>0>>0){K=J}else{V=J;break}}do{if((s|0)==88){if((U|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);W=c[o>>2]|0;s=93;break e}else{c[R>>2]=1;V=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[N>>2];if((V|0)!=0){T=V;s=92}else{X=S;s=95}}else{X=S;s=95}}else{s=94}}}while(0);if((s|0)==92){S=T+ -1|0;c[o>>2]=S;c[f>>2]=(c[f>>2]|0)+1;W=S;s=93}if((s|0)==93){if((W|0)==0){s=94}else{Y=W;s=104}}if((s|0)==94){X=b+76|0;s=95}f:do{if((s|0)==95){if((c[X>>2]|0)==0){W=b+40|0;if((c[W>>2]|0)==0){S=b+24|0;T=c[S>>2]|0;V=c[g>>2]|0;c[o>>2]=0;U=b+4|0;R=0;while(1){Z=Za(c[U>>2]|0,T+R|0,V-R|0)|0;if((Z|0)<1){s=100;break}K=(c[o>>2]|0)+Z|0;c[o>>2]=K;if(K>>>0>>0){R=K}else{_=K;break}}do{if((s|0)==100){if((Z|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);$=c[o>>2]|0;s=105;break f}else{c[W>>2]=1;_=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[S>>2];if((_|0)!=0){Y=_;s=104}else{aa=X;s=107}}else{aa=X;s=107}}else{s=106}}}while(0);if((s|0)==104){X=Y+ -1|0;c[o>>2]=X;c[f>>2]=(c[f>>2]|0)+1;$=X;s=105}if((s|0)==105){if(($|0)==0){s=106}else{ba=$;s=116}}if((s|0)==106){aa=b+76|0;s=107}g:do{if((s|0)==107){if((c[aa>>2]|0)==0){$=b+40|0;if((c[$>>2]|0)==0){X=b+24|0;Y=c[X>>2]|0;_=c[g>>2]|0;c[o>>2]=0;Z=b+4|0;W=0;while(1){ca=Za(c[Z>>2]|0,Y+W|0,_-W|0)|0;if((ca|0)<1){s=112;break}R=(c[o>>2]|0)+ca|0;c[o>>2]=R;if(R>>>0<_>>>0){W=R}else{da=R;break}}do{if((s|0)==112){if((ca|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);ea=c[o>>2]|0;s=117;break g}else{c[$>>2]=1;da=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[X>>2];if((da|0)!=0){ba=da;s=116}else{fa=aa;s=119}}else{fa=aa;s=119}}else{s=118}}}while(0);if((s|0)==116){aa=ba+ -1|0;c[o>>2]=aa;c[f>>2]=(c[f>>2]|0)+1;ea=aa;s=117}if((s|0)==117){if((ea|0)==0){s=118}else{ga=ea;s=128}}if((s|0)==118){fa=b+76|0;s=119}h:do{if(((s|0)==119?(c[fa>>2]|0)==0:0)?(ea=b+40|0,(c[ea>>2]|0)==0):0){aa=b+24|0;ba=c[aa>>2]|0;da=c[g>>2]|0;c[o>>2]=0;ca=b+4|0;$=0;while(1){ha=Za(c[ca>>2]|0,ba+$|0,da-$|0)|0;if((ha|0)<1){s=124;break}W=(c[o>>2]|0)+ha|0;c[o>>2]=W;if(W>>>0>>0){$=W}else{ia=W;break}}do{if((s|0)==124){if((ha|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break h}else{c[ea>>2]=1;ia=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[aa>>2];if((ia|0)!=0){ga=ia;s=128}}}while(0);if((s|0)==128){c[o>>2]=ga+ -1;c[f>>2]=(c[f>>2]|0)+1}i:do{if((z&4|0)!=0){ga=c[o>>2]|0;j:do{if((ga|0)==0){ia=b+76|0;if((c[ia>>2]|0)==0){ha=b+40|0;if((c[ha>>2]|0)==0){fa=b+24|0;ea=c[fa>>2]|0;$=c[g>>2]|0;c[o>>2]=0;da=b+4|0;ba=0;while(1){ja=Za(c[da>>2]|0,ea+ba|0,$-ba|0)|0;if((ja|0)<1){s=136;break}ca=(c[o>>2]|0)+ja|0;c[o>>2]=ca;if(ca>>>0<$>>>0){ba=ca}else{ka=ca;break}}do{if((s|0)==136){if((ja|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);la=-1;ma=c[o>>2]|0;s=141;break j}else{c[ha>>2]=1;ka=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[fa>>2];if((ka|0)!=0){na=ka;s=140}else{oa=ia;pa=-1;s=143}}else{oa=ia;pa=-1;s=143}}else{qa=-1;s=142}}else{na=ga;s=140}}while(0);if((s|0)==140){ga=na+ -1|0;c[o>>2]=ga;aa=c[f>>2]|0;c[f>>2]=aa+1;la=d[aa]|0;ma=ga;s=141}if((s|0)==141){if((ma|0)==0){qa=la;s=142}else{ra=ma;sa=la;s=152}}if((s|0)==142){oa=b+76|0;pa=qa;s=143}k:do{if((s|0)==143){if((c[oa>>2]|0)==0?(ga=b+40|0,(c[ga>>2]|0)==0):0){aa=b+24|0;ha=c[aa>>2]|0;ba=c[g>>2]|0;c[o>>2]=0;$=b+4|0;ea=0;while(1){ta=Za(c[$>>2]|0,ha+ea|0,ba-ea|0)|0;if((ta|0)<1){s=148;break}da=(c[o>>2]|0)+ta|0;c[o>>2]=da;if(da>>>0>>0){ea=da}else{ua=da;break}}do{if((s|0)==148){if((ta|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);va=-256;wa=pa;break k}else{c[ga>>2]=1;ua=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[aa>>2];if((ua|0)!=0){ra=ua;sa=pa;s=152}else{va=-256;wa=pa}}else{va=-256;wa=pa}}}while(0);if((s|0)==152){c[o>>2]=ra+ -1;ga=c[f>>2]|0;c[f>>2]=ga+1;va=d[ga]<<8;wa=sa}ga=va+wa|0;if((ga|0)!=0){ea=b+76|0;ba=b+40|0;ha=b+24|0;$=b+4|0;ia=b+84|0;fa=ga;ga=c[o>>2]|0;while(1){fa=fa+ -1|0;if((ga|0)==0){if((c[ea>>2]|0)!=0){break i}if((c[ba>>2]|0)!=0){break i}da=c[ha>>2]|0;ca=c[g>>2]|0;c[o>>2]=0;X=0;while(1){xa=Za(c[$>>2]|0,da+X|0,ca-X|0)|0;if((xa|0)<1){s=161;break}W=(c[o>>2]|0)+xa|0;c[o>>2]=W;if(W>>>0>>0){X=W}else{ya=W;break}}if((s|0)==161){s=0;if((xa|0)<0){break}c[ba>>2]=1;ya=c[o>>2]|0}c[ia>>2]=c[ha>>2];if((ya|0)==0){break i}else{za=ya}}else{za=ga}ga=za+ -1|0;c[o>>2]=ga;c[f>>2]=(c[f>>2]|0)+1;if((fa|0)==0){break i}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}}while(0);l:do{if((z&8|0)!=0){za=b+76|0;ya=b+40|0;xa=b+24|0;wa=b+4|0;va=b+84|0;sa=c[o>>2]|0;while(1){if((sa|0)==0){if((c[za>>2]|0)!=0){break l}if((c[ya>>2]|0)!=0){break l}ra=c[xa>>2]|0;pa=c[g>>2]|0;c[o>>2]=0;ua=0;while(1){Aa=Za(c[wa>>2]|0,ra+ua|0,pa-ua|0)|0;if((Aa|0)<1){s=174;break}ta=(c[o>>2]|0)+Aa|0;c[o>>2]=ta;if(ta>>>0>>0){ua=ta}else{Ba=ta;break}}if((s|0)==174){s=0;if((Aa|0)<0){break}c[ya>>2]=1;Ba=c[o>>2]|0}c[va>>2]=c[xa>>2];if((Ba|0)==0){break l}else{Ca=Ba}}else{Ca=sa}sa=Ca+ -1|0;c[o>>2]=sa;ua=c[f>>2]|0;c[f>>2]=ua+1;if((a[ua]|0)==0){break l}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}while(0);m:do{if((z&16|0)!=0){Ca=b+76|0;Ba=b+40|0;Aa=b+24|0;sa=b+4|0;xa=b+84|0;va=c[o>>2]|0;while(1){if((va|0)==0){if((c[Ca>>2]|0)!=0){break m}if((c[Ba>>2]|0)!=0){break m}ya=c[Aa>>2]|0;wa=c[g>>2]|0;c[o>>2]=0;za=0;while(1){Da=Za(c[sa>>2]|0,ya+za|0,wa-za|0)|0;if((Da|0)<1){s=187;break}ua=(c[o>>2]|0)+Da|0;c[o>>2]=ua;if(ua>>>0>>0){za=ua}else{Ea=ua;break}}if((s|0)==187){s=0;if((Da|0)<0){break}c[Ba>>2]=1;Ea=c[o>>2]|0}c[xa>>2]=c[Aa>>2];if((Ea|0)==0){break m}else{Fa=Ea}}else{Fa=va}va=Fa+ -1|0;c[o>>2]=va;za=c[f>>2]|0;c[f>>2]=za+1;if((a[za]|0)==0){break m}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}while(0);n:do{if((z&2|0)!=0){Fa=c[o>>2]|0;o:do{if((Fa|0)==0){Ea=b+76|0;if((c[Ea>>2]|0)==0){Da=b+40|0;if((c[Da>>2]|0)==0){va=b+24|0;Aa=c[va>>2]|0;xa=c[g>>2]|0;c[o>>2]=0;Ba=b+4|0;sa=0;while(1){Ga=Za(c[Ba>>2]|0,Aa+sa|0,xa-sa|0)|0;if((Ga|0)<1){s=199;break}Ca=(c[o>>2]|0)+Ga|0;c[o>>2]=Ca;if(Ca>>>0>>0){sa=Ca}else{Ha=Ca;break}}do{if((s|0)==199){if((Ga|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);Ia=c[o>>2]|0;s=204;break o}else{c[Da>>2]=1;Ha=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[va>>2];if((Ha|0)!=0){Ja=Ha;s=203}else{Ka=Ea;s=206}}else{Ka=Ea;s=206}}else{s=205}}else{Ja=Fa;s=203}}while(0);if((s|0)==203){Fa=Ja+ -1|0;c[o>>2]=Fa;c[f>>2]=(c[f>>2]|0)+1;Ia=Fa;s=204}if((s|0)==204){if((Ia|0)==0){s=205}else{La=Ia}}if((s|0)==205){Ka=b+76|0;s=206}if((s|0)==206){if((c[Ka>>2]|0)!=0){break}Fa=b+40|0;if((c[Fa>>2]|0)!=0){break}Da=b+24|0;sa=c[Da>>2]|0;xa=c[g>>2]|0;c[o>>2]=0;Aa=b+4|0;Ba=0;while(1){Ma=Za(c[Aa>>2]|0,sa+Ba|0,xa-Ba|0)|0;if((Ma|0)<1){s=211;break}Ca=(c[o>>2]|0)+Ma|0;c[o>>2]=Ca;if(Ca>>>0>>0){Ba=Ca}else{Na=Ca;break}}do{if((s|0)==211){if((Ma|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break n}else{c[Fa>>2]=1;Na=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[Da>>2];if((Na|0)==0){break}else{La=Na}}c[o>>2]=La+ -1;c[f>>2]=(c[f>>2]|0)+1}}while(0);Hf(f)|0;c[b+132>>2]=gf(0,0,0)|0;c[b+52>>2]=2;c[b+56>>2]=0;p=0;i=e;return p|0}vf(b,-3,21400);p=-1;i=e;return p|0}vf(b,-3,21368);p=-1;i=e;return p|0}La=b+28|0;a[c[La>>2]|0]=31;c[b+36>>2]=1;Oa=La;Pa=c[o>>2]|0}else{Oa=b+28|0;Pa=v}c[b+48>>2]=c[b+12>>2];v=c[Oa>>2]|0;c[b+32>>2]=v;if((Pa|0)!=0){Oa=b+36|0;Kg(v+(c[Oa>>2]|0)|0,c[f>>2]|0,Pa|0)|0;c[Oa>>2]=(c[Oa>>2]|0)+(c[o>>2]|0);c[o>>2]=0}c[b+52>>2]=1;c[b+56>>2]=1;p=0;i=e;return p|0}function Af(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}if((c[a>>2]|0)!=7247){d=-2;i=b;return d|0}if((c[a+16>>2]|0)!=0){Mf(a+84|0)|0;hg(c[a+28>>2]|0);hg(c[a+24>>2]|0)}vf(a,0,0);hg(c[a+8>>2]|0);e=ib(c[a+4>>2]|0)|0;hg(a);d=((e|0)!=0)<<31>>31;i=b;return d|0}function Bf(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0;e=i;f=a+84|0;g=a+88|0;h=c[g>>2]|0;a:do{if((h|0)==0){j=a+76|0;if((c[j>>2]|0)==0){k=a+40|0;if((c[k>>2]|0)==0){l=a+24|0;m=c[l>>2]|0;n=c[a+16>>2]|0;c[g>>2]=0;o=a+4|0;p=0;while(1){q=Za(c[o>>2]|0,m+p|0,n-p|0)|0;if((q|0)<1){r=7;break}s=(c[g>>2]|0)+q|0;c[g>>2]=s;if(s>>>0>>0){p=s}else{t=s;break}}do{if((r|0)==7){if((q|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);u=-1;v=c[g>>2]|0;r=12;break a}else{c[k>>2]=1;t=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[l>>2];if((t|0)!=0){w=t;r=11}else{x=j;y=-1;r=14}}else{x=j;y=-1;r=14}}else{z=-1;r=13}}else{w=h;r=11}}while(0);if((r|0)==11){h=w+ -1|0;c[g>>2]=h;w=c[f>>2]|0;c[f>>2]=w+1;u=d[w]|0;v=h;r=12}if((r|0)==12){if((v|0)==0){z=u;r=13}else{A=u;B=v;r=25}}if((r|0)==13){x=a+76|0;y=z;r=14}b:do{if((r|0)==14){if((c[x>>2]|0)!=0){C=y+ -256|0;r=27;break}z=a+40|0;if((c[z>>2]|0)==0){v=a+24|0;u=c[v>>2]|0;h=c[a+16>>2]|0;c[g>>2]=0;w=a+4|0;t=0;while(1){D=Za(c[w>>2]|0,u+t|0,h-t|0)|0;if((D|0)<1){r=20;break}q=(c[g>>2]|0)+D|0;c[g>>2]=q;if(q>>>0>>0){t=q}else{E=q;break}}do{if((r|0)==20){if((D|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);F=y;G=-256;H=c[g>>2]|0;r=26;break b}else{c[z>>2]=1;E=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[v>>2];if((E|0)!=0){A=y;B=E;r=25;break}}I=x;J=y+ -256|0;r=28}}while(0);if((r|0)==25){y=B+ -1|0;c[g>>2]=y;B=c[f>>2]|0;c[f>>2]=B+1;F=A;G=(d[B]|0)<<8;H=y;r=26}if((r|0)==26){y=G+F|0;if((H|0)==0){C=y;r=27}else{K=H;L=y;r=39}}if((r|0)==27){I=a+76|0;J=C;r=28}c:do{if((r|0)==28){if((c[I>>2]|0)!=0){M=J+ -65536|0;r=41;break}C=a+40|0;if((c[C>>2]|0)==0){y=a+24|0;H=c[y>>2]|0;F=c[a+16>>2]|0;c[g>>2]=0;G=a+4|0;B=0;while(1){N=Za(c[G>>2]|0,H+B|0,F-B|0)|0;if((N|0)<1){r=34;break}A=(c[g>>2]|0)+N|0;c[g>>2]=A;if(A>>>0>>0){B=A}else{O=A;break}}do{if((r|0)==34){if((N|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);P=J;Q=-65536;R=c[g>>2]|0;r=40;break c}else{c[C>>2]=1;O=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[y>>2];if((O|0)!=0){K=O;L=J;r=39;break}}S=I;T=J+ -65536|0;r=42}}while(0);if((r|0)==39){J=K+ -1|0;c[g>>2]=J;K=c[f>>2]|0;c[f>>2]=K+1;P=L;Q=(d[K]|0)<<16;R=J;r=40}if((r|0)==40){J=Q+P|0;if((R|0)==0){M=J;r=41}else{U=R;V=J}}if((r|0)==41){S=a+76|0;T=M;r=42}if((r|0)==42){if((c[S>>2]|0)!=0){W=-1;i=e;return W|0}S=a+40|0;if((c[S>>2]|0)!=0){W=-1;i=e;return W|0}M=a+24|0;J=c[M>>2]|0;R=c[a+16>>2]|0;c[g>>2]=0;P=a+4|0;Q=0;while(1){X=Za(c[P>>2]|0,J+Q|0,R-Q|0)|0;if((X|0)<1){r=47;break}K=(c[g>>2]|0)+X|0;c[g>>2]=K;if(K>>>0>>0){Q=K}else{Y=K;break}}do{if((r|0)==47){if((X|0)>=0){c[S>>2]=1;Y=c[g>>2]|0;break}vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);W=-1;i=e;return W|0}}while(0);c[a+84>>2]=c[M>>2];if((Y|0)==0){W=-1;i=e;return W|0}else{U=Y;V=T}}c[g>>2]=U+ -1;U=c[f>>2]|0;c[f>>2]=U+1;c[b>>2]=((d[U]|0)<<24)+V;W=0;i=e;return W|0}function Cf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=i;if((a|0)==0){f=0;i=e;return f|0}g=a+84|0;if((c[a>>2]|0)!=31153){f=0;i=e;return f|0}if((c[a+76>>2]|0)!=0){f=0;i=e;return f|0}if((d|0)<0){vf(a,-5,21568);f=0;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}h=a+16|0;if((c[h>>2]|0)==0?(Df(a)|0)==-1:0){f=0;i=e;return f|0}j=a+72|0;a:do{if((c[j>>2]|0)!=0){c[j>>2]=0;k=c[a+68>>2]|0;l=a+88|0;if((c[l>>2]|0)!=0?(Ef(a,0)|0)==-1:0){f=0;i=e;return f|0}if((k|0)!=0){m=a+24|0;n=a+12|0;o=k;k=0;while(1){p=c[h>>2]|0;q=(p|0)<0|(p|0)>(o|0)?o:p;if(!k){Eg(c[m>>2]|0,0,q|0)|0}c[l>>2]=q;c[g>>2]=c[m>>2];c[n>>2]=(c[n>>2]|0)+q;if((Ef(a,0)|0)==-1){f=0;break}if((o|0)==(q|0)){break a}o=o-q|0;k=1}i=e;return f|0}}}while(0);j=a+88|0;b:do{if(!((c[h>>2]|0)>>>0>d>>>0)){if((c[j>>2]|0)!=0?(Ef(a,0)|0)==-1:0){f=0;i=e;return f|0}c[j>>2]=d;c[g>>2]=b;k=a+12|0;c[k>>2]=(c[k>>2]|0)+d;if((Ef(a,0)|0)==-1){f=0;i=e;return f|0}}else{k=a+24|0;o=a+12|0;n=b;m=d;while(1){l=c[j>>2]|0;if((l|0)==0){q=c[k>>2]|0;c[g>>2]=q;r=q}else{r=c[g>>2]|0}q=(c[h>>2]|0)-l|0;p=q>>>0>m>>>0?m:q;Kg(r+l|0,n|0,p|0)|0;c[j>>2]=(c[j>>2]|0)+p;c[o>>2]=(c[o>>2]|0)+p;if((m|0)==(p|0)){break b}if((Ef(a,0)|0)==-1){f=0;break}n=n+p|0;m=m-p|0}i=e;return f|0}}while(0);f=d;i=e;return f|0}function Df(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;b=i;d=a+20|0;e=c[d>>2]|0;f=gg(e)|0;g=a+24|0;c[g>>2]=f;h=gg(e)|0;e=a+28|0;c[e>>2]=h;j=(h|0)==0;if(!((f|0)==0|j)){c[a+116>>2]=0;c[a+120>>2]=0;c[a+124>>2]=0;if((hf(a+84|0,c[a+60>>2]|0,8,31,8,c[a+64>>2]|0,21664,56)|0)==0){k=c[d>>2]|0;c[a+16>>2]=k;c[a+100>>2]=k;k=c[e>>2]|0;c[a+96>>2]=k;c[a+32>>2]=k;l=0;i=b;return l|0}else{hg(c[g>>2]|0);vf(a,-4,21648);l=-1;i=b;return l|0}}if(j){m=f}else{hg(h);m=c[g>>2]|0}if((m|0)!=0){hg(m)}vf(a,-4,21648);l=-1;i=b;return l|0}function Ef(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;d=i;e=a+84|0;f=a+16|0;if((c[f>>2]|0)==0?(Df(a)|0)==-1:0){g=-1;i=d;return g|0}h=a+100|0;j=a+96|0;k=a+32|0;l=a+28|0;m=a+4|0;a:do{if((b|0)==4){n=c[h>>2]|0;o=0;while(1){if((n|0)==0|(o|0)==1){p=c[j>>2]|0;q=c[k>>2]|0;r=p-q|0;if((p|0)==(q|0)){s=n}else{p=Qa(c[m>>2]|0,q|0,r|0)|0;if(!((p|0)>-1&(p|0)==(r|0))){t=30;break a}s=c[h>>2]|0}if((s|0)==0){r=c[f>>2]|0;c[h>>2]=r;p=c[l>>2]|0;c[j>>2]=p;u=p;v=r}else{u=c[j>>2]|0;v=s}c[k>>2]=u;w=v}else{w=n}r=lf(e,4)|0;if((r|0)==-2){t=36;break a}p=c[h>>2]|0;if((w|0)==(p|0)){t=38;break}else{n=p;o=r}}}else if((b|0)==0){o=c[h>>2]|0;while(1){if((o|0)==0){n=c[j>>2]|0;r=c[k>>2]|0;p=n-r|0;if((n|0)!=(r|0)){n=Qa(c[m>>2]|0,r|0,p|0)|0;if(!((n|0)>-1&(n|0)==(p|0))){t=30;break a}p=c[h>>2]|0;if((p|0)!=0){x=c[j>>2]|0;y=p}else{t=10}}else{t=10}if((t|0)==10){t=0;p=c[f>>2]|0;c[h>>2]=p;n=c[l>>2]|0;c[j>>2]=n;x=n;y=p}c[k>>2]=x;z=y}else{z=o}if((lf(e,0)|0)==-2){t=36;break a}p=c[h>>2]|0;if((z|0)==(p|0)){t=38;break}else{o=p}}}else{o=c[h>>2]|0;while(1){if((o|0)!=0&(b|0)==0){A=o}else{p=c[j>>2]|0;n=c[k>>2]|0;r=p-n|0;if((p|0)==(n|0)){B=o}else{p=Qa(c[m>>2]|0,n|0,r|0)|0;if(!((p|0)>-1&(p|0)==(r|0))){t=30;break a}B=c[h>>2]|0}if((B|0)==0){r=c[f>>2]|0;c[h>>2]=r;p=c[l>>2]|0;c[j>>2]=p;C=p;D=r}else{C=c[j>>2]|0;D=B}c[k>>2]=C;A=D}if((lf(e,b)|0)==-2){t=36;break a}r=c[h>>2]|0;if((A|0)==(r|0)){t=38;break}else{o=r}}}}while(0);if((t|0)==30){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);g=-1;i=d;return g|0}else if((t|0)==36){vf(a,-2,21608);g=-1;i=d;return g|0}else if((t|0)==38){if((b|0)!=4){g=0;i=d;return g|0}kf(e)|0;g=0;i=d;return g|0}return 0}function Ff(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}if((c[a>>2]|0)!=31153){d=-2;i=b;return d|0}e=a+72|0;a:do{if((c[e>>2]|0)!=0){c[e>>2]=0;f=c[a+68>>2]|0;g=a+88|0;if((c[g>>2]|0)!=0?(Ef(a,0)|0)==-1:0){h=-1;break}if((f|0)!=0){j=a+16|0;k=a+24|0;l=a+84|0;m=a+12|0;n=f;f=0;while(1){o=c[j>>2]|0;p=(o|0)<0|(o|0)>(n|0)?n:o;if(!f){Eg(c[k>>2]|0,0,p|0)|0}c[g>>2]=p;c[l>>2]=c[k>>2];c[m>>2]=(c[m>>2]|0)+p;if((Ef(a,0)|0)==-1){h=-1;break a}if((n|0)==(p|0)){h=0;break}else{n=n-p|0;f=1}}}else{h=0}}else{h=0}}while(0);e=(Ef(a,4)|0)+h|0;jf(a+84|0)|0;hg(c[a+28>>2]|0);hg(c[a+24>>2]|0);vf(a,0,0);hg(c[a+8>>2]|0);h=ib(c[a+4>>2]|0)|0;hg(a);d=((e|0)!=(0-h|0))<<31>>31;i=b;return d|0}function Gf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0;g=i;h=c[e+28>>2]|0;j=c[e>>2]|0;k=e+4|0;l=j+((c[k>>2]|0)+ -6)|0;m=e+12|0;n=c[m>>2]|0;o=e+16|0;p=c[o>>2]|0;q=n+(p+ -258)|0;r=c[h+44>>2]|0;s=c[h+48>>2]|0;t=c[h+52>>2]|0;u=h+56|0;v=h+60|0;w=c[h+76>>2]|0;x=c[h+80>>2]|0;y=(1<>2])+ -1|0;z=(1<>2])+ -1|0;A=n+(p+~f)|0;f=h+7104|0;p=t+ -1|0;B=(s|0)==0;C=(c[h+40>>2]|0)+ -1|0;D=C+s|0;E=s+ -1|0;F=A+ -1|0;G=A-s|0;H=c[v>>2]|0;I=c[u>>2]|0;J=j+ -1|0;j=n+ -1|0;a:while(1){if(H>>>0<15){n=J+2|0;K=H+16|0;L=((d[J+1|0]|0)<>1]|0;P=d[w+(n<<2)+1|0]|0;n=L>>>P;Q=K-P|0;do{if(!(N<<24>>24==0)){R=N&255;S=Q;T=n;P=O;while(1){if((R&16|0)!=0){break}if((R&64|0)!=0){U=55;break a}V=(T&(1<>1]|0;Y=d[w+(V<<2)+1|0]|0;Z=T>>>Y;_=S-Y|0;if(W<<24>>24==0){U=6;break}else{R=W&255;S=_;T=Z;P=X}}if((U|0)==6){U=0;$=Z;aa=_;ba=X&255;U=7;break}W=P&65535;Y=R&15;if((Y|0)==0){ca=S;da=T;ea=M;fa=W}else{if(S>>>0>>0){V=M+1|0;ga=S+8|0;ha=((d[V]|0)<>>Y;ea=ia;fa=(ha&(1<>>0<15){W=ea+2|0;ja=ca+16|0;ka=((d[ea+1|0]|0)<>1]|0;V=d[x+(W<<2)+1|0]|0;ma=ka>>>V;na=ja-V|0;V=d[x+(W<<2)|0]|0;if((V&16|0)==0){W=V;oa=ma;pa=na;qa=Y;while(1){if((W&64|0)!=0){U=52;break a}ra=(oa&(1<>1]|0;ta=d[x+(ra<<2)+1|0]|0;ua=oa>>>ta;va=pa-ta|0;ta=d[x+(ra<<2)|0]|0;if((ta&16|0)==0){W=ta;oa=ua;pa=va;qa=sa}else{wa=ua;xa=va;ya=ta;za=sa;break}}}else{wa=ma;xa=na;ya=V;za=Y}qa=za&65535;W=ya&15;if(xa>>>0>>0){P=la+1|0;sa=((d[P]|0)<>>0>>0){va=la+2|0;Aa=xa+16|0;Ba=((d[va]|0)<>>W;Ea=Aa-W|0;W=j;qa=W-A|0;if(!(P>>>0>qa>>>0)){sa=j+(0-P)|0;ta=fa;va=j;while(1){a[va+1|0]=a[sa+1|0]|0;a[va+2|0]=a[sa+2|0]|0;ua=sa+3|0;Fa=va+3|0;a[Fa]=a[ua]|0;ta=ta+ -3|0;if(!(ta>>>0>2)){break}else{sa=ua;va=Fa}}if((ta|0)==0){Ga=Ea;Ha=Da;Ia=Ca;Ja=Fa;break}Y=va+4|0;a[Y]=a[sa+4|0]|0;if(!(ta>>>0>1)){Ga=Ea;Ha=Da;Ia=Ca;Ja=Y;break}Y=va+5|0;a[Y]=a[sa+5|0]|0;Ga=Ea;Ha=Da;Ia=Ca;Ja=Y;break}Y=P-qa|0;if(Y>>>0>r>>>0?(c[f>>2]|0)!=0:0){U=22;break a}do{if(B){V=t+(C-Y)|0;if(Y>>>0>>0){na=fa-Y|0;ma=P-W|0;ua=V;ra=Y;Ka=j;do{ua=ua+1|0;Ka=Ka+1|0;a[Ka]=a[ua]|0;ra=ra+ -1|0}while((ra|0)!=0);La=j+(F+ma+(1-P))|0;Ma=na;Na=j+(A+ma)|0}else{La=V;Ma=fa;Na=j}}else{if(!(s>>>0>>0)){ra=t+(E-Y)|0;if(!(Y>>>0>>0)){La=ra;Ma=fa;Na=j;break}ua=fa-Y|0;Ka=P-W|0;Oa=ra;ra=Y;Pa=j;do{Oa=Oa+1|0;Pa=Pa+1|0;a[Pa]=a[Oa]|0;ra=ra+ -1|0}while((ra|0)!=0);La=j+(F+Ka+(1-P))|0;Ma=ua;Na=j+(A+Ka)|0;break}ra=t+(D-Y)|0;Oa=Y-s|0;if(Oa>>>0>>0){Pa=fa-Oa|0;V=P-W|0;ma=ra;na=Oa;Oa=j;do{ma=ma+1|0;Oa=Oa+1|0;a[Oa]=a[ma]|0;na=na+ -1|0}while((na|0)!=0);na=j+(G+V)|0;if(s>>>0>>0){ma=Pa-s|0;Oa=p;Ka=s;ua=na;do{Oa=Oa+1|0;ua=ua+1|0;a[ua]=a[Oa]|0;Ka=Ka+ -1|0}while((Ka|0)!=0);La=j+(F+V+(1-P))|0;Ma=ma;Na=j+(A+V)|0}else{La=p;Ma=Pa;Na=na}}else{La=ra;Ma=fa;Na=j}}}while(0);if(Ma>>>0>2){P=La;W=Ma;Y=Na;while(1){a[Y+1|0]=a[P+1|0]|0;a[Y+2|0]=a[P+2|0]|0;qa=P+3|0;sa=Y+3|0;a[sa]=a[qa]|0;va=W+ -3|0;if(va>>>0>2){P=qa;W=va;Y=sa}else{Qa=qa;Ra=va;Sa=sa;break}}}else{Qa=La;Ra=Ma;Sa=Na}if((Ra|0)!=0){Y=Sa+1|0;a[Y]=a[Qa+1|0]|0;if(Ra>>>0>1){W=Sa+2|0;a[W]=a[Qa+2|0]|0;Ga=Ea;Ha=Da;Ia=Ca;Ja=W}else{Ga=Ea;Ha=Da;Ia=Ca;Ja=Y}}else{Ga=Ea;Ha=Da;Ia=Ca;Ja=Sa}}else{$=n;aa=Q;ba=O&255;U=7}}while(0);if((U|0)==7){U=0;O=j+1|0;a[O]=ba;Ga=aa;Ha=$;Ia=M;Ja=O}if(Ia>>>0>>0&Ja>>>0>>0){H=Ga;I=Ha;J=Ia;j=Ja}else{Ta=Ga;Ua=Ha;Va=Ia;Wa=Ja;break}}do{if((U|0)==22){c[e+24>>2]=21672;c[h>>2]=29;Ta=Ea;Ua=Da;Va=Ca;Wa=j}else if((U|0)==52){c[e+24>>2]=21704;c[h>>2]=29;Ta=pa;Ua=oa;Va=la;Wa=j}else if((U|0)==55){if((R&32|0)==0){c[e+24>>2]=21728;c[h>>2]=29;Ta=S;Ua=T;Va=M;Wa=j;break}else{c[h>>2]=11;Ta=S;Ua=T;Va=M;Wa=j;break}}}while(0);j=Ta>>>3;M=Va+(0-j)|0;T=Ta-(j<<3)|0;Ta=(1<>2]=Va+(1-j);c[m>>2]=Wa+1;if(M>>>0>>0){Xa=l-M|0}else{Xa=l-M|0}c[k>>2]=Xa+5;if(Wa>>>0>>0){Ya=q-Wa|0;Za=Ya+257|0;c[o>>2]=Za;c[u>>2]=Ta;c[v>>2]=T;i=g;return}else{Ya=q-Wa|0;Za=Ya+257|0;c[o>>2]=Za;c[u>>2]=Ta;c[v>>2]=T;i=g;return}}function Hf(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=c[a+28>>2]|0;if((e|0)==0){d=-2;i=b;return d|0}c[e+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[e>>2]=0;c[e+4>>2]=0;c[e+12>>2]=0;c[e+20>>2]=32768;c[e+32>>2]=0;c[e+40>>2]=0;c[e+44>>2]=0;c[e+48>>2]=0;c[e+56>>2]=0;c[e+60>>2]=0;a=e+1328|0;c[e+108>>2]=a;c[e+80>>2]=a;c[e+76>>2]=a;c[e+7104>>2]=1;c[e+7108>>2]=-1;d=0;i=b;return d|0}function If(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;if((a|0)==0){e=-2;i=d;return e|0}f=a+28|0;g=c[f>>2]|0;if((g|0)==0){e=-2;i=d;return e|0}if((b|0)<0){h=0-b|0;j=0}else{h=(b|0)<48?b&15:b;j=(b>>4)+1|0}if((h|0)!=0&(h+ -8|0)>>>0>7){e=-2;i=d;return e|0}b=g+52|0;k=c[b>>2]|0;l=g+36|0;if((k|0)!=0?(c[l>>2]|0)!=(h|0):0){mb[c[a+36>>2]&1](c[a+40>>2]|0,k);c[b>>2]=0}c[g+8>>2]=j;c[l>>2]=h;h=c[f>>2]|0;if((h|0)==0){e=-2;i=d;return e|0}c[h+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[h>>2]=0;c[h+4>>2]=0;c[h+12>>2]=0;c[h+20>>2]=32768;c[h+32>>2]=0;c[h+40>>2]=0;c[h+44>>2]=0;c[h+48>>2]=0;c[h+56>>2]=0;c[h+60>>2]=0;a=h+1328|0;c[h+108>>2]=a;c[h+80>>2]=a;c[h+76>>2]=a;c[h+7104>>2]=1;c[h+7108>>2]=-1;e=0;i=d;return e|0}function Jf(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0;g=i;if((e|0)==0){h=-6;i=g;return h|0}if(!((a[e]|0)==49&(f|0)==56)){h=-6;i=g;return h|0}if((b|0)==0){h=-2;i=g;return h|0}c[b+24>>2]=0;f=b+32|0;e=c[f>>2]|0;if((e|0)==0){c[f>>2]=1;c[b+40>>2]=0;j=1}else{j=e}e=b+36|0;if((c[e>>2]|0)==0){c[e>>2]=1}f=b+40|0;k=kb[j&1](c[f>>2]|0,1,7116)|0;if((k|0)==0){h=-4;i=g;return h|0}j=b+28|0;c[j>>2]=k;c[k+52>>2]=0;l=If(b,d)|0;if((l|0)==0){h=0;i=g;return h|0}mb[c[e>>2]&1](c[f>>2]|0,k);c[j>>2]=0;h=l;i=g;return h|0}function Kf(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,fb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0,sc=0,tc=0,uc=0,vc=0,wc=0,xc=0,yc=0,zc=0,Ac=0,Bc=0,Cc=0,Dc=0,Ec=0,Fc=0,Gc=0,Hc=0,Ic=0,Jc=0,Kc=0,Lc=0,Mc=0,Nc=0,Oc=0,Pc=0,Qc=0,Rc=0,Sc=0,Tc=0,Uc=0,Vc=0,Wc=0,Xc=0,Yc=0,Zc=0,_c=0,$c=0,ad=0,bd=0,cd=0,dd=0,ed=0,fd=0,gd=0,hd=0,id=0,jd=0,kd=0,ld=0,md=0,nd=0,od=0,pd=0,qd=0,rd=0,sd=0,td=0,ud=0,vd=0,wd=0,xd=0,yd=0,zd=0,Ad=0,Bd=0,Cd=0,Dd=0,Ed=0,Fd=0,Gd=0,Hd=0,Id=0,Jd=0,Kd=0,Ld=0,Md=0,Nd=0,Od=0,Pd=0,Qd=0,Rd=0,Sd=0,Td=0,Ud=0,Vd=0,Wd=0,Xd=0,Yd=0,Zd=0,_d=0,$d=0,ae=0,be=0,ce=0,de=0,ee=0,fe=0,ge=0,he=0,ie=0,je=0,ke=0,le=0,me=0,ne=0,oe=0,pe=0,qe=0,re=0,se=0,te=0,ue=0,ve=0,we=0,xe=0,ye=0,ze=0,Ae=0,Be=0,Ce=0,De=0,Ee=0,Fe=0,Ge=0,He=0,Ie=0,Je=0,Ke=0,Le=0,Me=0,Ne=0,Oe=0,Pe=0,Qe=0,Re=0,Se=0,Te=0,Ue=0,Ve=0,We=0,Xe=0,Ye=0,Ze=0,_e=0,$e=0,af=0,bf=0,cf=0,df=0,ef=0,hf=0,jf=0,kf=0,lf=0,mf=0,nf=0,of=0,pf=0,qf=0,rf=0,sf=0,tf=0,uf=0,vf=0,wf=0,xf=0,yf=0,zf=0,Af=0,Bf=0,Cf=0,Df=0,Ef=0,Ff=0,Hf=0,If=0,Jf=0,Kf=0,Mf=0,Of=0,Pf=0,Qf=0,Rf=0,Sf=0,Tf=0,Uf=0,Vf=0,Wf=0,Xf=0,Yf=0,Zf=0,_f=0,$f=0,ag=0,bg=0,cg=0,dg=0,eg=0,fg=0,gg=0,hg=0,ig=0,jg=0,kg=0,lg=0,mg=0,ng=0,og=0,pg=0,qg=0,rg=0,sg=0,tg=0,ug=0,vg=0,wg=0,xg=0,yg=0,zg=0,Ag=0,Bg=0,Cg=0,Dg=0,Eg=0,Fg=0,Gg=0,Hg=0,Ig=0,Jg=0;h=i;i=i+16|0;j=h;if((f|0)==0){k=-2;i=h;return k|0}l=c[f+28>>2]|0;if((l|0)==0){k=-2;i=h;return k|0}m=f+12|0;n=c[m>>2]|0;if((n|0)==0){k=-2;i=h;return k|0}o=c[f>>2]|0;if((o|0)==0?(c[f+4>>2]|0)!=0:0){k=-2;i=h;return k|0}p=c[l>>2]|0;if((p|0)==11){c[l>>2]=12;q=12;r=c[f>>2]|0;s=c[m>>2]|0}else{q=p;r=o;s=n}n=f+16|0;o=c[n>>2]|0;p=f+4|0;t=c[p>>2]|0;u=l+56|0;v=l+60|0;w=l+8|0;x=l+24|0;y=j+1|0;z=l+16|0;A=l+32|0;B=f+24|0;C=l+36|0;D=l+20|0;E=f+48|0;F=l+64|0;G=l+12|0;H=(g+ -5|0)>>>0<2;I=l+4|0;J=l+76|0;K=l+84|0;L=l+80|0;M=l+88|0;N=(g|0)==6;O=l+7108|0;P=l+72|0;Q=l+7112|0;R=l+68|0;S=l+44|0;T=l+7104|0;U=l+48|0;V=l+52|0;W=l+40|0;X=f+20|0;Y=l+28|0;Z=l+96|0;_=l+100|0;$=l+92|0;aa=l+104|0;ba=l+1328|0;ca=l+108|0;da=l+112|0;ea=l+752|0;fa=l+624|0;ga=j+2|0;ha=j+3|0;ia=q;q=c[v>>2]|0;ja=t;ka=c[u>>2]|0;la=o;ma=r;r=o;o=s;s=0;a:while(1){b:do{switch(ia|0){case 28:{na=q;oa=ja;pa=ka;qa=la;ra=ma;sa=1;ta=285;break a;break};case 16:{if(q>>>0<14){ua=q;va=ja;wa=ka;xa=ma;while(1){if((va|0)==0){ya=ua;za=0;Aa=wa;Ba=la;Ca=xa;Da=r;Ea=s;break a}Ga=va+ -1|0;Ha=xa+1|0;Ia=(d[xa]<>>0<14){ua=Ja;va=Ga;wa=Ia;xa=Ha}else{Ka=Ja;La=Ga;Ma=Ia;Na=Ha;break}}}else{Ka=q;La=ja;Ma=ka;Na=ma}xa=(Ma&31)+257|0;c[Z>>2]=xa;wa=(Ma>>>5&31)+1|0;c[_>>2]=wa;c[$>>2]=(Ma>>>10&15)+4;va=Ma>>>14;ua=Ka+ -14|0;if(xa>>>0>286|wa>>>0>30){c[B>>2]=21992;c[l>>2]=29;Oa=ua;Pa=La;Qa=va;Ra=la;Sa=Na;Ta=r;Ua=o;Va=s;break b}else{c[aa>>2]=0;c[l>>2]=17;Wa=0;Xa=ua;Ya=La;Za=va;_a=Na;ta=154;break b}break};case 21:{$a=c[P>>2]|0;ab=q;bb=ja;cb=ka;db=ma;eb=s;ta=221;break};case 23:{fb=c[P>>2]|0;gb=q;hb=ja;ib=ka;jb=ma;kb=s;ta=240;break};case 1:{if(q>>>0<16){va=q;ua=ja;wa=ka;xa=ma;while(1){if((ua|0)==0){ya=va;za=0;Aa=wa;Ba=la;Ca=xa;Da=r;Ea=s;break a}Ha=ua+ -1|0;Ia=xa+1|0;Ga=(d[xa]<>>0<16){va=Ja;ua=Ha;wa=Ga;xa=Ia}else{lb=Ja;mb=Ha;nb=Ga;ob=Ia;break}}}else{lb=q;mb=ja;nb=ka;ob=ma}c[z>>2]=nb;if((nb&255|0)!=8){c[B>>2]=21824;c[l>>2]=29;Oa=lb;Pa=mb;Qa=nb;Ra=la;Sa=ob;Ta=r;Ua=o;Va=s;break b}if((nb&57344|0)!=0){c[B>>2]=21880;c[l>>2]=29;Oa=lb;Pa=mb;Qa=nb;Ra=la;Sa=ob;Ta=r;Ua=o;Va=s;break b}xa=c[A>>2]|0;if((xa|0)==0){pb=nb}else{c[xa>>2]=nb>>>8&1;pb=c[z>>2]|0}if((pb&512|0)!=0){a[j]=nb;a[y]=nb>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0}c[l>>2]=2;qb=0;rb=mb;sb=0;tb=ob;ta=47;break};case 22:{ub=q;vb=ja;wb=ka;xb=ma;yb=s;ta=228;break};case 10:{zb=q;Ab=ja;Bb=ka;Cb=ma;ta=121;break};case 7:{Db=q;Eb=ja;Fb=ka;Gb=ma;ta=96;break};case 5:{Hb=q;Ib=ja;Jb=ka;Kb=ma;ta=73;break};case 8:{Lb=q;Mb=ja;Nb=ka;Ob=ma;ta=109;break};case 11:{Pb=q;Qb=ja;Rb=ka;Sb=ma;ta=124;break};case 12:{Tb=q;Ub=ja;Vb=ka;Wb=ma;ta=125;break};case 13:{xa=q&7;wa=ka>>>xa;ua=q-xa|0;if(ua>>>0<32){xa=ua;va=ja;Ia=wa;Ga=ma;while(1){if((va|0)==0){ya=xa;za=0;Aa=Ia;Ba=la;Ca=Ga;Da=r;Ea=s;break a}Ha=va+ -1|0;Ja=Ga+1|0;Xb=(d[Ga]<>>0<32){xa=Yb;va=Ha;Ia=Xb;Ga=Ja}else{Zb=Yb;_b=Ha;$b=Xb;ac=Ja;break}}}else{Zb=ua;_b=ja;$b=wa;ac=ma}Ga=$b&65535;if((Ga|0)==($b>>>16^65535|0)){c[F>>2]=Ga;c[l>>2]=14;if(N){na=0;oa=_b;pa=0;qa=la;ra=ac;sa=s;ta=285;break a}else{bc=0;cc=_b;dc=0;ec=ac;ta=143;break b}}else{c[B>>2]=21960;c[l>>2]=29;Oa=Zb;Pa=_b;Qa=$b;Ra=la;Sa=ac;Ta=r;Ua=o;Va=s;break b}break};case 14:{bc=q;cc=ja;dc=ka;ec=ma;ta=143;break};case 15:{fc=q;gc=ja;hc=ka;ic=ma;ta=144;break};case 17:{Ga=c[aa>>2]|0;if(Ga>>>0<(c[$>>2]|0)>>>0){Wa=Ga;Xa=q;Ya=ja;Za=ka;_a=ma;ta=154}else{jc=Ga;kc=q;lc=ja;mc=ka;nc=ma;ta=158}break};case 0:{Ga=c[w>>2]|0;if((Ga|0)==0){c[l>>2]=12;Oa=q;Pa=ja;Qa=ka;Ra=la;Sa=ma;Ta=r;Ua=o;Va=s;break b}if(q>>>0<16){Ia=q;va=ja;xa=ka;Ja=ma;while(1){if((va|0)==0){ya=Ia;za=0;Aa=xa;Ba=la;Ca=Ja;Da=r;Ea=s;break a}Xb=va+ -1|0;Ha=Ja+1|0;Yb=(d[Ja]<>>0<16){Ia=oc;va=Xb;xa=Yb;Ja=Ha}else{pc=oc;qc=Xb;rc=Yb;sc=Ha;break}}}else{pc=q;qc=ja;rc=ka;sc=ma}if((Ga&2|0)!=0&(rc|0)==35615){c[x>>2]=gf(0,0,0)|0;a[j]=31;a[y]=-117;c[x>>2]=gf(c[x>>2]|0,j,2)|0;c[l>>2]=1;Oa=0;Pa=qc;Qa=0;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}c[z>>2]=0;Ja=c[A>>2]|0;if((Ja|0)==0){tc=Ga}else{c[Ja+48>>2]=-1;tc=c[w>>2]|0}if((tc&1|0)!=0?((((rc<<8&65280)+(rc>>>8)|0)>>>0)%31|0|0)==0:0){if((rc&15|0)!=8){c[B>>2]=21824;c[l>>2]=29;Oa=pc;Pa=qc;Qa=rc;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}Ja=rc>>>4;xa=pc+ -4|0;va=(Ja&15)+8|0;Ia=c[C>>2]|0;if((Ia|0)!=0){if(va>>>0>Ia>>>0){c[B>>2]=21856;c[l>>2]=29;Oa=xa;Pa=qc;Qa=Ja;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}}else{c[C>>2]=va}c[D>>2]=1<>2]=va;c[E>>2]=va;c[l>>2]=rc>>>12&2^11;Oa=0;Pa=qc;Qa=0;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}c[B>>2]=21800;c[l>>2]=29;Oa=pc;Pa=qc;Qa=rc;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break};case 24:{uc=q;vc=ja;wc=ka;xc=ma;yc=s;ta=246;break};case 9:{if(q>>>0<32){va=q;Ja=ja;xa=ka;Ia=ma;while(1){if((Ja|0)==0){ya=va;za=0;Aa=xa;Ba=la;Ca=Ia;Da=r;Ea=s;break a}wa=Ja+ -1|0;ua=Ia+1|0;Ha=(d[Ia]<>>0<32){va=Yb;Ja=wa;xa=Ha;Ia=ua}else{zc=wa;Ac=Ha;Bc=ua;break}}}else{zc=ja;Ac=ka;Bc=ma}Ia=Fa(Ac|0)|0;c[x>>2]=Ia;c[E>>2]=Ia;c[l>>2]=10;zb=0;Ab=zc;Bb=0;Cb=Bc;ta=121;break};case 30:{ta=299;break a;break};case 18:{Cc=c[aa>>2]|0;Dc=q;Ec=ja;Fc=ka;Gc=ma;Hc=s;ta=164;break};case 6:{Ic=q;Jc=ja;Kc=ka;Lc=ma;ta=83;break};case 29:{ya=q;za=ja;Aa=ka;Ba=la;Ca=ma;Da=r;Ea=-3;break a;break};case 19:{Mc=q;Nc=ja;Oc=ka;Pc=ma;Qc=s;ta=201;break};case 20:{Rc=q;Sc=ja;Tc=ka;Uc=ma;Vc=s;ta=202;break};case 25:{if((la|0)==0){na=q;oa=ja;pa=ka;qa=0;ra=ma;sa=s;ta=285;break a}a[o]=c[F>>2];c[l>>2]=20;Oa=q;Pa=ja;Qa=ka;Ra=la+ -1|0;Sa=ma;Ta=r;Ua=o+1|0;Va=s;break};case 26:{if((c[w>>2]|0)!=0){if(q>>>0<32){Ia=q;xa=ja;Ja=ka;va=ma;while(1){if((xa|0)==0){ya=Ia;za=0;Aa=Ja;Ba=la;Ca=va;Da=r;Ea=s;break a}Ga=xa+ -1|0;ua=va+1|0;Ha=(d[va]<>>0<32){Ia=wa;xa=Ga;Ja=Ha;va=ua}else{Wc=wa;Xc=Ga;Yc=Ha;Zc=ua;break}}}else{Wc=q;Xc=ja;Yc=ka;Zc=ma}va=r-la|0;c[X>>2]=(c[X>>2]|0)+va;c[Y>>2]=(c[Y>>2]|0)+va;if((r|0)!=(la|0)){Ja=c[x>>2]|0;xa=o+(0-va)|0;if((c[z>>2]|0)==0){_c=ff(Ja,xa,va)|0}else{_c=gf(Ja,xa,va)|0}c[x>>2]=_c;c[E>>2]=_c}if((c[z>>2]|0)==0){$c=Fa(Yc|0)|0}else{$c=Yc}if(($c|0)==(c[x>>2]|0)){ad=0;bd=Xc;cd=0;dd=Zc;ed=la}else{c[B>>2]=22280;c[l>>2]=29;Oa=Wc;Pa=Xc;Qa=Yc;Ra=la;Sa=Zc;Ta=la;Ua=o;Va=s;break b}}else{ad=q;bd=ja;cd=ka;dd=ma;ed=r}c[l>>2]=27;fd=ad;gd=bd;hd=cd;id=dd;jd=ed;ta=277;break};case 27:{fd=q;gd=ja;hd=ka;id=ma;jd=r;ta=277;break};case 2:{if(q>>>0<32){qb=q;rb=ja;sb=ka;tb=ma;ta=47}else{kd=ja;ld=ka;md=ma;ta=49}break};case 4:{nd=q;od=ja;pd=ka;qd=ma;ta=62;break};case 3:{if(q>>>0<16){rd=q;sd=ja;td=ka;ud=ma;ta=55}else{vd=ja;wd=ka;xd=ma;ta=57}break};default:{k=-2;ta=300;break a}}}while(0);if((ta|0)==47){while(1){ta=0;if((rb|0)==0){ya=qb;za=0;Aa=sb;Ba=la;Ca=tb;Da=r;Ea=s;break a}va=rb+ -1|0;xa=tb+1|0;Ja=(d[tb]<>>0<32){qb=Ia;rb=va;sb=Ja;tb=xa;ta=47}else{kd=va;ld=Ja;md=xa;ta=49;break}}}else if((ta|0)==121){ta=0;if((c[G>>2]|0)==0){ta=122;break}xa=ff(0,0,0)|0;c[x>>2]=xa;c[E>>2]=xa;c[l>>2]=11;Pb=zb;Qb=Ab;Rb=Bb;Sb=Cb;ta=124}else if((ta|0)==143){ta=0;c[l>>2]=15;fc=bc;gc=cc;hc=dc;ic=ec;ta=144}else if((ta|0)==154){while(1){ta=0;if(Xa>>>0<3){xa=Xa;Ja=Ya;va=Za;Ia=_a;while(1){if((Ja|0)==0){ya=xa;za=0;Aa=va;Ba=la;Ca=Ia;Da=r;Ea=s;break a}ua=Ja+ -1|0;Ha=Ia+1|0;Ga=(d[Ia]<>>0<3){xa=wa;Ja=ua;va=Ga;Ia=Ha}else{yd=wa;zd=ua;Ad=Ga;Bd=Ha;break}}}else{yd=Xa;zd=Ya;Ad=Za;Bd=_a}c[aa>>2]=Wa+1;b[l+(e[21760+(Wa<<1)>>1]<<1)+112>>1]=Ad&7;Ia=Ad>>>3;va=yd+ -3|0;Ja=c[aa>>2]|0;if(Ja>>>0<(c[$>>2]|0)>>>0){Wa=Ja;Xa=va;Ya=zd;Za=Ia;_a=Bd;ta=154}else{jc=Ja;kc=va;lc=zd;mc=Ia;nc=Bd;ta=158;break}}}else if((ta|0)==277){ta=0;if((c[w>>2]|0)==0){Cd=fd;Dd=gd;Ed=hd;Fd=id;ta=284;break}if((c[z>>2]|0)==0){Cd=fd;Dd=gd;Ed=hd;Fd=id;ta=284;break}if(fd>>>0<32){Ia=fd;va=gd;Ja=hd;xa=id;while(1){if((va|0)==0){ya=Ia;za=0;Aa=Ja;Ba=la;Ca=xa;Da=jd;Ea=s;break a}Ha=va+ -1|0;Ga=xa+1|0;ua=(d[xa]<>>0<32){Ia=wa;va=Ha;Ja=ua;xa=Ga}else{Gd=wa;Hd=Ha;Id=ua;Jd=Ga;break}}}else{Gd=fd;Hd=gd;Id=hd;Jd=id}if((Id|0)==(c[Y>>2]|0)){Cd=0;Dd=Hd;Ed=0;Fd=Jd;ta=284;break}c[B>>2]=22304;c[l>>2]=29;Oa=Gd;Pa=Hd;Qa=Id;Ra=la;Sa=Jd;Ta=jd;Ua=o;Va=s}do{if((ta|0)==49){ta=0;xa=c[A>>2]|0;if((xa|0)!=0){c[xa+4>>2]=ld}if((c[z>>2]&512|0)!=0){a[j]=ld;a[y]=ld>>>8;a[ga]=ld>>>16;a[ha]=ld>>>24;c[x>>2]=gf(c[x>>2]|0,j,4)|0}c[l>>2]=3;rd=0;sd=kd;td=0;ud=md;ta=55}else if((ta|0)==124){ta=0;if(H){na=Pb;oa=Qb;pa=Rb;qa=la;ra=Sb;sa=s;ta=285;break a}else{Tb=Pb;Ub=Qb;Vb=Rb;Wb=Sb;ta=125}}else if((ta|0)==144){ta=0;xa=c[F>>2]|0;if((xa|0)==0){c[l>>2]=11;Oa=fc;Pa=gc;Qa=hc;Ra=la;Sa=ic;Ta=r;Ua=o;Va=s;break}Ja=xa>>>0>gc>>>0?gc:xa;xa=Ja>>>0>la>>>0?la:Ja;if((xa|0)==0){na=fc;oa=gc;pa=hc;qa=la;ra=ic;sa=s;ta=285;break a}Kg(o|0,ic|0,xa|0)|0;c[F>>2]=(c[F>>2]|0)-xa;Oa=fc;Pa=gc-xa|0;Qa=hc;Ra=la-xa|0;Sa=ic+xa|0;Ta=r;Ua=o+xa|0;Va=s}else if((ta|0)==158){ta=0;if(jc>>>0<19){xa=jc;while(1){Ja=xa+1|0;b[l+(e[21760+(xa<<1)>>1]<<1)+112>>1]=0;if((Ja|0)==19){break}else{xa=Ja}}c[aa>>2]=19}c[ca>>2]=ba;c[J>>2]=ba;c[K>>2]=7;xa=Nf(0,da,19,ca,K,ea)|0;if((xa|0)==0){c[aa>>2]=0;c[l>>2]=18;Cc=0;Dc=kc;Ec=lc;Fc=mc;Gc=nc;Hc=0;ta=164;break}else{c[B>>2]=22032;c[l>>2]=29;Oa=kc;Pa=lc;Qa=mc;Ra=la;Sa=nc;Ta=r;Ua=o;Va=xa;break}}}while(0);c:do{if((ta|0)==55){while(1){ta=0;if((sd|0)==0){ya=rd;za=0;Aa=td;Ba=la;Ca=ud;Da=r;Ea=s;break a}xa=sd+ -1|0;Ja=ud+1|0;va=(d[ud]<>>0<16){rd=Ia;sd=xa;td=va;ud=Ja;ta=55}else{vd=xa;wd=va;xd=Ja;ta=57;break}}}else if((ta|0)==125){ta=0;if((c[I>>2]|0)!=0){Ja=Tb&7;c[l>>2]=26;Oa=Tb-Ja|0;Pa=Ub;Qa=Vb>>>Ja;Ra=la;Sa=Wb;Ta=r;Ua=o;Va=s;break}if(Tb>>>0<3){Ja=Tb;va=Ub;xa=Vb;Ia=Wb;while(1){if((va|0)==0){ya=Ja;za=0;Aa=xa;Ba=la;Ca=Ia;Da=r;Ea=s;break a}Ga=va+ -1|0;ua=Ia+1|0;Ha=(d[Ia]<>>0<3){Ja=wa;va=Ga;xa=Ha;Ia=ua}else{Kd=wa;Ld=Ga;Md=Ha;Nd=ua;break}}}else{Kd=Tb;Ld=Ub;Md=Vb;Nd=Wb}c[I>>2]=Md&1;Ia=Md>>>1&3;if((Ia|0)==0){c[l>>2]=13}else if((Ia|0)==1){c[J>>2]=22328;c[K>>2]=9;c[L>>2]=24376;c[M>>2]=5;c[l>>2]=19;if(N){ta=133;break a}}else if((Ia|0)==2){c[l>>2]=16}else if((Ia|0)==3){c[B>>2]=21936;c[l>>2]=29}Oa=Kd+ -3|0;Pa=Ld;Qa=Md>>>3;Ra=la;Sa=Nd;Ta=r;Ua=o;Va=s}else if((ta|0)==164){ta=0;Ia=c[Z>>2]|0;xa=c[_>>2]|0;do{if(Cc>>>0<(xa+Ia|0)>>>0){va=Cc;Ja=xa;ua=Ia;Ha=Dc;Ga=Ec;wa=Fc;Yb=Gc;d:while(1){Xb=(1<>2])+ -1|0;oc=Xb&wa;Od=c[J>>2]|0;Pd=d[Od+(oc<<2)+1|0]|0;if(Pd>>>0>Ha>>>0){Qd=Ha;Rd=Ga;Sd=wa;Td=Yb;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Td;Da=r;Ea=Hc;break a}Ud=Rd+ -1|0;Vd=Td+1|0;Wd=(d[Td]<>>0>Xd>>>0){Qd=Xd;Rd=Ud;Sd=Wd;Td=Vd}else{_d=Zd;$d=Yd;ae=Xd;be=Ud;ce=Wd;de=Vd;break}}}else{_d=Pd;$d=oc;ae=Ha;be=Ga;ce=wa;de=Yb}Td=b[Od+($d<<2)+2>>1]|0;e:do{if((Td&65535)<16){if(ae>>>0<_d>>>0){Sd=ae;Rd=be;Qd=ce;Xb=de;while(1){if((Rd|0)==0){ya=Sd;za=0;Aa=Qd;Ba=la;Ca=Xb;Da=r;Ea=Hc;break a}Vd=Rd+ -1|0;Wd=Xb+1|0;Ud=(d[Xb]<>>0<_d>>>0){Sd=Xd;Rd=Vd;Qd=Ud;Xb=Wd}else{ee=Xd;fe=Vd;ge=Ud;he=Wd;break}}}else{ee=ae;fe=be;ge=ce;he=de}c[aa>>2]=va+1;b[l+(va<<1)+112>>1]=Td;ie=ee-_d|0;je=fe;ke=ge>>>_d;le=he}else{if(Td<<16>>16==16){Xb=_d+2|0;if(ae>>>0>>0){Qd=ae;Rd=be;Sd=ce;Wd=de;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Wd;Da=r;Ea=Hc;break a}Ud=Rd+ -1|0;Vd=Wd+1|0;Xd=(d[Wd]<>>0>>0){Qd=Yd;Rd=Ud;Sd=Xd;Wd=Vd}else{me=Yd;ne=Ud;oe=Xd;pe=Vd;break}}}else{me=ae;ne=be;oe=ce;pe=de}qe=oe>>>_d;re=me-_d|0;if((va|0)==0){ta=181;break d}se=re+ -2|0;te=(qe&3)+3|0;ue=ne;ve=qe>>>2;we=b[l+(va+ -1<<1)+112>>1]|0;xe=pe}else if(Td<<16>>16==17){Wd=_d+3|0;if(ae>>>0>>0){Sd=ae;Rd=be;Qd=ce;Xb=de;while(1){if((Rd|0)==0){ya=Sd;za=0;Aa=Qd;Ba=la;Ca=Xb;Da=r;Ea=Hc;break a}Vd=Rd+ -1|0;Xd=Xb+1|0;Ud=(d[Xb]<>>0>>0){Sd=Yd;Rd=Vd;Qd=Ud;Xb=Xd}else{ye=Yd;ze=Vd;Ae=Ud;Be=Xd;break}}}else{ye=ae;ze=be;Ae=ce;Be=de}Xb=Ae>>>_d;se=-3-_d+ye|0;te=(Xb&7)+3|0;ue=ze;ve=Xb>>>3;we=0;xe=Be}else{Xb=_d+7|0;if(ae>>>0>>0){Qd=ae;Rd=be;Sd=ce;Wd=de;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Wd;Da=r;Ea=Hc;break a}Xd=Rd+ -1|0;Ud=Wd+1|0;Vd=(d[Wd]<>>0>>0){Qd=Yd;Rd=Xd;Sd=Vd;Wd=Ud}else{Ce=Yd;De=Xd;Ee=Vd;Fe=Ud;break}}}else{Ce=ae;De=be;Ee=ce;Fe=de}Wd=Ee>>>_d;se=-7-_d+Ce|0;te=(Wd&127)+11|0;ue=De;ve=Wd>>>7;we=0;xe=Fe}if((va+te|0)>>>0>(Ja+ua|0)>>>0){ta=190;break d}else{Ge=va;He=te}while(1){Wd=He+ -1|0;c[aa>>2]=Ge+1;b[l+(Ge<<1)+112>>1]=we;if((Wd|0)==0){ie=se;je=ue;ke=ve;le=xe;break e}Ge=c[aa>>2]|0;He=Wd}}}while(0);Td=c[aa>>2]|0;Ie=c[Z>>2]|0;Od=c[_>>2]|0;if(Td>>>0<(Od+Ie|0)>>>0){va=Td;Ja=Od;ua=Ie;Ha=ie;Ga=je;wa=ke;Yb=le}else{ta=193;break}}if((ta|0)==181){ta=0;c[B>>2]=22064;c[l>>2]=29;Oa=re;Pa=ne;Qa=qe;Ra=la;Sa=pe;Ta=r;Ua=o;Va=Hc;break c}else if((ta|0)==190){ta=0;c[B>>2]=22064;c[l>>2]=29;Oa=se;Pa=ue;Qa=ve;Ra=la;Sa=xe;Ta=r;Ua=o;Va=Hc;break c}else if((ta|0)==193){ta=0;if((c[l>>2]|0)==29){Oa=ie;Pa=je;Qa=ke;Ra=la;Sa=le;Ta=r;Ua=o;Va=Hc;break c}else{Je=Ie;Ke=ie;Le=je;Me=ke;Ne=le;break}}}else{Je=Ia;Ke=Dc;Le=Ec;Me=Fc;Ne=Gc}}while(0);if((b[fa>>1]|0)==0){c[B>>2]=22096;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Hc;break}c[ca>>2]=ba;c[J>>2]=ba;c[K>>2]=9;Ia=Nf(1,da,Je,ca,K,ea)|0;if((Ia|0)!=0){c[B>>2]=22136;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Ia;break}c[L>>2]=c[ca>>2];c[M>>2]=6;Ia=Nf(2,l+(c[Z>>2]<<1)+112|0,c[_>>2]|0,ca,M,ea)|0;if((Ia|0)==0){c[l>>2]=19;if(N){na=Ke;oa=Le;pa=Me;qa=la;ra=Ne;sa=0;ta=285;break a}else{Mc=Ke;Nc=Le;Oc=Me;Pc=Ne;Qc=0;ta=201;break}}else{c[B>>2]=22168;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Ia;break}}}while(0);if((ta|0)==57){ta=0;Ia=c[A>>2]|0;if((Ia|0)!=0){c[Ia+8>>2]=wd&255;c[Ia+12>>2]=wd>>>8}if((c[z>>2]&512|0)!=0){a[j]=wd;a[y]=wd>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0}c[l>>2]=4;nd=0;od=vd;pd=0;qd=xd;ta=62}else if((ta|0)==201){ta=0;c[l>>2]=20;Rc=Mc;Sc=Nc;Tc=Oc;Uc=Pc;Vc=Qc;ta=202}do{if((ta|0)==62){ta=0;Ia=c[z>>2]|0;if((Ia&1024|0)==0){xa=c[A>>2]|0;if((xa|0)==0){Oe=nd;Pe=od;Qe=pd;Re=qd}else{c[xa+16>>2]=0;Oe=nd;Pe=od;Qe=pd;Re=qd}}else{if(nd>>>0<16){xa=nd;Yb=od;wa=pd;Ga=qd;while(1){if((Yb|0)==0){ya=xa;za=0;Aa=wa;Ba=la;Ca=Ga;Da=r;Ea=s;break a}Ha=Yb+ -1|0;ua=Ga+1|0;Ja=(d[Ga]<>>0<16){xa=va;Yb=Ha;wa=Ja;Ga=ua}else{Se=Ha;Te=Ja;Ue=ua;break}}}else{Se=od;Te=pd;Ue=qd}c[F>>2]=Te;Ga=c[A>>2]|0;if((Ga|0)==0){Ve=Ia}else{c[Ga+20>>2]=Te;Ve=c[z>>2]|0}if((Ve&512|0)==0){Oe=0;Pe=Se;Qe=0;Re=Ue}else{a[j]=Te;a[y]=Te>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0;Oe=0;Pe=Se;Qe=0;Re=Ue}}c[l>>2]=5;Hb=Oe;Ib=Pe;Jb=Qe;Kb=Re;ta=73}else if((ta|0)==202){ta=0;if(Sc>>>0>5&la>>>0>257){c[m>>2]=o;c[n>>2]=la;c[f>>2]=Uc;c[p>>2]=Sc;c[u>>2]=Tc;c[v>>2]=Rc;Gf(f,r);Ga=c[m>>2]|0;wa=c[n>>2]|0;Yb=c[f>>2]|0;xa=c[p>>2]|0;ua=c[u>>2]|0;Ja=c[v>>2]|0;if((c[l>>2]|0)!=11){Oa=Ja;Pa=xa;Qa=ua;Ra=wa;Sa=Yb;Ta=r;Ua=Ga;Va=Vc;break}c[O>>2]=-1;Oa=Ja;Pa=xa;Qa=ua;Ra=wa;Sa=Yb;Ta=r;Ua=Ga;Va=Vc;break}c[O>>2]=0;Ga=(1<>2])+ -1|0;Yb=Ga&Tc;wa=c[J>>2]|0;ua=a[wa+(Yb<<2)+1|0]|0;xa=ua&255;if(xa>>>0>Rc>>>0){Ja=Rc;Ha=Sc;va=Tc;Od=Uc;while(1){if((Ha|0)==0){ya=Ja;za=0;Aa=va;Ba=la;Ca=Od;Da=r;Ea=Vc;break a}Td=Ha+ -1|0;oc=Od+1|0;Pd=(d[Od]<>>0>Wd>>>0){Ja=Wd;Ha=Td;va=Pd;Od=oc}else{We=Rd;Xe=Qd;Ye=Sd;Ze=Wd;_e=Td;$e=Pd;af=oc;break}}}else{We=ua;Xe=xa;Ye=Yb;Ze=Rc;_e=Sc;$e=Tc;af=Uc}Od=a[wa+(Ye<<2)|0]|0;va=b[wa+(Ye<<2)+2>>1]|0;Ha=Od&255;if(!(Od<<24>>24==0)){if((Ha&240|0)==0){Ja=va&65535;Ga=(1<>>Xe)+Ja|0;Ia=a[wa+(Ha<<2)+1|0]|0;if(((Ia&255)+Xe|0)>>>0>Ze>>>0){oc=Ze;Pd=_e;Td=$e;Wd=af;while(1){if((Pd|0)==0){ya=oc;za=0;Aa=Td;Ba=la;Ca=Wd;Da=r;Ea=Vc;break a}Sd=Pd+ -1|0;Qd=Wd+1|0;Rd=(d[Wd]<>>Xe)+Ja|0;Vd=a[wa+(Ud<<2)+1|0]|0;if(((Vd&255)+Xe|0)>>>0>Xb>>>0){oc=Xb;Pd=Sd;Td=Rd;Wd=Qd}else{bf=Ud;cf=Vd;df=Xb;ef=Sd;hf=Rd;jf=Qd;break}}}else{bf=Ha;cf=Ia;df=Ze;ef=_e;hf=$e;jf=af}Wd=b[wa+(bf<<2)+2>>1]|0;Td=a[wa+(bf<<2)|0]|0;c[O>>2]=Xe;kf=Xe;lf=df-Xe|0;mf=ef;nf=Td;of=cf;pf=Wd;qf=hf>>>Xe;rf=jf}else{kf=0;lf=Ze;mf=_e;nf=Od;of=We;pf=va;qf=$e;rf=af}}else{kf=0;lf=Ze;mf=_e;nf=0;of=We;pf=va;qf=$e;rf=af}Wd=of&255;Td=qf>>>Wd;Pd=lf-Wd|0;c[O>>2]=kf+Wd;c[F>>2]=pf&65535;Wd=nf&255;if(nf<<24>>24==0){c[l>>2]=25;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}if((Wd&32|0)!=0){c[O>>2]=-1;c[l>>2]=11;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}if((Wd&64|0)==0){oc=Wd&15;c[P>>2]=oc;c[l>>2]=21;$a=oc;ab=Pd;bb=mf;cb=Td;db=rf;eb=Vc;ta=221;break}else{c[B>>2]=22192;c[l>>2]=29;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}}}while(0);if((ta|0)==73){ta=0;Td=c[z>>2]|0;if((Td&1024|0)!=0){Pd=c[F>>2]|0;oc=Pd>>>0>Ib>>>0?Ib:Pd;if((oc|0)==0){sf=Pd;tf=Ib;uf=Kb}else{Wd=c[A>>2]|0;if((Wd|0)!=0?(Ja=c[Wd+16>>2]|0,(Ja|0)!=0):0){Ga=(c[Wd+20>>2]|0)-Pd|0;Pd=c[Wd+24>>2]|0;Kg(Ja+Ga|0,Kb|0,((Ga+oc|0)>>>0>Pd>>>0?Pd-Ga|0:oc)|0)|0;vf=c[z>>2]|0}else{vf=Td}if((vf&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Kb,oc)|0}Td=(c[F>>2]|0)-oc|0;c[F>>2]=Td;sf=Td;tf=Ib-oc|0;uf=Kb+oc|0}if((sf|0)==0){wf=tf;xf=uf}else{na=Hb;oa=tf;pa=Jb;qa=la;ra=uf;sa=s;ta=285;break}}else{wf=Ib;xf=Kb}c[F>>2]=0;c[l>>2]=6;Ic=Hb;Jc=wf;Kc=Jb;Lc=xf;ta=83}else if((ta|0)==221){ta=0;if(($a|0)==0){yf=c[F>>2]|0;zf=ab;Af=bb;Bf=cb;Cf=db}else{if(ab>>>0<$a>>>0){oc=ab;Td=bb;Ga=cb;Pd=db;while(1){if((Td|0)==0){ya=oc;za=0;Aa=Ga;Ba=la;Ca=Pd;Da=r;Ea=eb;break a}Ja=Td+ -1|0;Wd=Pd+1|0;Yb=(d[Pd]<>>0<$a>>>0){oc=xa;Td=Ja;Ga=Yb;Pd=Wd}else{Df=xa;Ef=Ja;Ff=Yb;Hf=Wd;break}}}else{Df=ab;Ef=bb;Ff=cb;Hf=db}Pd=(c[F>>2]|0)+((1<<$a)+ -1&Ff)|0;c[F>>2]=Pd;c[O>>2]=(c[O>>2]|0)+$a;yf=Pd;zf=Df-$a|0;Af=Ef;Bf=Ff>>>$a;Cf=Hf}c[Q>>2]=yf;c[l>>2]=22;ub=zf;vb=Af;wb=Bf;xb=Cf;yb=eb;ta=228}do{if((ta|0)==83){ta=0;if((c[z>>2]&2048|0)==0){Pd=c[A>>2]|0;if((Pd|0)==0){If=Jc;Jf=Lc}else{c[Pd+28>>2]=0;If=Jc;Jf=Lc}}else{if((Jc|0)==0){na=Ic;oa=0;pa=Kc;qa=la;ra=Lc;sa=s;ta=285;break a}else{Kf=0}while(1){Mf=Kf+1|0;Pd=a[Lc+Kf|0]|0;Ga=c[A>>2]|0;if(((Ga|0)!=0?(Td=c[Ga+28>>2]|0,(Td|0)!=0):0)?(oc=c[F>>2]|0,oc>>>0<(c[Ga+32>>2]|0)>>>0):0){c[F>>2]=oc+1;a[Td+oc|0]=Pd}Of=Pd<<24>>24!=0;if(Of&Mf>>>0>>0){Kf=Mf}else{break}}if((c[z>>2]&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Lc,Mf)|0}va=Jc-Mf|0;Od=Lc+Mf|0;if(Of){na=Ic;oa=va;pa=Kc;qa=la;ra=Od;sa=s;ta=285;break a}else{If=va;Jf=Od}}c[F>>2]=0;c[l>>2]=7;Db=Ic;Eb=If;Fb=Kc;Gb=Jf;ta=96}else if((ta|0)==228){ta=0;Od=(1<>2])+ -1|0;va=Od&wb;wa=c[L>>2]|0;Ia=a[wa+(va<<2)+1|0]|0;Ha=Ia&255;if(Ha>>>0>ub>>>0){Pd=ub;oc=vb;Td=wb;Ga=xb;while(1){if((oc|0)==0){ya=Pd;za=0;Aa=Td;Ba=la;Ca=Ga;Da=r;Ea=yb;break a}Wd=oc+ -1|0;Yb=Ga+1|0;Ja=(d[Ga]<>>0>xa>>>0){Pd=xa;oc=Wd;Td=Ja;Ga=Yb}else{Pf=Qd;Qf=Rd;Rf=ua;Sf=xa;Tf=Wd;Uf=Ja;Vf=Yb;break}}}else{Pf=Ia;Qf=Ha;Rf=va;Sf=ub;Tf=vb;Uf=wb;Vf=xb}Ga=a[wa+(Rf<<2)|0]|0;Td=b[wa+(Rf<<2)+2>>1]|0;oc=Ga&255;if((oc&240|0)==0){Pd=Td&65535;Od=(1<>>Qf)+Pd|0;Yb=a[wa+(oc<<2)+1|0]|0;if(((Yb&255)+Qf|0)>>>0>Sf>>>0){Ja=Sf;Wd=Tf;xa=Uf;ua=Vf;while(1){if((Wd|0)==0){ya=Ja;za=0;Aa=xa;Ba=la;Ca=ua;Da=r;Ea=yb;break a}Rd=Wd+ -1|0;Qd=ua+1|0;Sd=(d[ua]<>>Qf)+Pd|0;Ud=a[wa+(Vd<<2)+1|0]|0;if(((Ud&255)+Qf|0)>>>0>Xb>>>0){Ja=Xb;Wd=Rd;xa=Sd;ua=Qd}else{Wf=Vd;Xf=Ud;Yf=Xb;Zf=Rd;_f=Sd;$f=Qd;break}}}else{Wf=oc;Xf=Yb;Yf=Sf;Zf=Tf;_f=Uf;$f=Vf}ua=b[wa+(Wf<<2)+2>>1]|0;xa=a[wa+(Wf<<2)|0]|0;Wd=(c[O>>2]|0)+Qf|0;c[O>>2]=Wd;ag=Wd;bg=Yf-Qf|0;cg=Zf;dg=xa;eg=Xf;fg=ua;gg=_f>>>Qf;hg=$f}else{ag=c[O>>2]|0;bg=Sf;cg=Tf;dg=Ga;eg=Pf;fg=Td;gg=Uf;hg=Vf}ua=eg&255;xa=gg>>>ua;Wd=bg-ua|0;c[O>>2]=ag+ua;ua=dg&255;if((ua&64|0)==0){c[R>>2]=fg&65535;Ja=ua&15;c[P>>2]=Ja;c[l>>2]=23;fb=Ja;gb=Wd;hb=cg;ib=xa;jb=hg;kb=yb;ta=240;break}else{c[B>>2]=22224;c[l>>2]=29;Oa=Wd;Pa=cg;Qa=xa;Ra=la;Sa=hg;Ta=r;Ua=o;Va=yb;break}}}while(0);if((ta|0)==96){ta=0;if((c[z>>2]&4096|0)==0){xa=c[A>>2]|0;if((xa|0)==0){ig=Eb;jg=Gb}else{c[xa+36>>2]=0;ig=Eb;jg=Gb}}else{if((Eb|0)==0){na=Db;oa=0;pa=Fb;qa=la;ra=Gb;sa=s;ta=285;break}else{kg=0}while(1){lg=kg+1|0;xa=a[Gb+kg|0]|0;Wd=c[A>>2]|0;if(((Wd|0)!=0?(Ja=c[Wd+36>>2]|0,(Ja|0)!=0):0)?(ua=c[F>>2]|0,ua>>>0<(c[Wd+40>>2]|0)>>>0):0){c[F>>2]=ua+1;a[Ja+ua|0]=xa}mg=xa<<24>>24!=0;if(mg&lg>>>0>>0){kg=lg}else{break}}if((c[z>>2]&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Gb,lg)|0}xa=Eb-lg|0;ua=Gb+lg|0;if(mg){na=Db;oa=xa;pa=Fb;qa=la;ra=ua;sa=s;ta=285;break}else{ig=xa;jg=ua}}c[l>>2]=8;Lb=Db;Mb=ig;Nb=Fb;Ob=jg;ta=109}else if((ta|0)==240){ta=0;if((fb|0)==0){ng=gb;og=hb;pg=ib;qg=jb}else{if(gb>>>0>>0){ua=gb;xa=hb;Ja=ib;Wd=jb;while(1){if((xa|0)==0){ya=ua;za=0;Aa=Ja;Ba=la;Ca=Wd;Da=r;Ea=kb;break a}Pd=xa+ -1|0;Od=Wd+1|0;va=(d[Wd]<>>0>>0){ua=Ha;xa=Pd;Ja=va;Wd=Od}else{rg=Ha;sg=Pd;tg=va;ug=Od;break}}}else{rg=gb;sg=hb;tg=ib;ug=jb}c[R>>2]=(c[R>>2]|0)+((1<>2]=(c[O>>2]|0)+fb;ng=rg-fb|0;og=sg;pg=tg>>>fb;qg=ug}c[l>>2]=24;uc=ng;vc=og;wc=pg;xc=qg;yc=kb;ta=246}do{if((ta|0)==109){ta=0;Wd=c[z>>2]|0;if((Wd&512|0)!=0){if(Lb>>>0<16){Ja=Lb;xa=Mb;ua=Nb;Od=Ob;while(1){if((xa|0)==0){ya=Ja;za=0;Aa=ua;Ba=la;Ca=Od;Da=r;Ea=s;break a}va=xa+ -1|0;Pd=Od+1|0;Ha=(d[Od]<>>0<16){Ja=Ia;xa=va;ua=Ha;Od=Pd}else{vg=Ia;wg=va;xg=Ha;yg=Pd;break}}}else{vg=Lb;wg=Mb;xg=Nb;yg=Ob}if((xg|0)==(c[x>>2]&65535|0)){zg=0;Ag=wg;Bg=0;Cg=yg}else{c[B>>2]=21912;c[l>>2]=29;Oa=vg;Pa=wg;Qa=xg;Ra=la;Sa=yg;Ta=r;Ua=o;Va=s;break}}else{zg=Lb;Ag=Mb;Bg=Nb;Cg=Ob}Od=c[A>>2]|0;if((Od|0)!=0){c[Od+44>>2]=Wd>>>9&1;c[Od+48>>2]=1}Od=gf(0,0,0)|0;c[x>>2]=Od;c[E>>2]=Od;c[l>>2]=11;Oa=zg;Pa=Ag;Qa=Bg;Ra=la;Sa=Cg;Ta=r;Ua=o;Va=s}else if((ta|0)==246){ta=0;if((la|0)==0){na=uc;oa=vc;pa=wc;qa=0;ra=xc;sa=yc;ta=285;break a}Od=r-la|0;ua=c[R>>2]|0;if(ua>>>0>Od>>>0){xa=ua-Od|0;if(xa>>>0>(c[S>>2]|0)>>>0?(c[T>>2]|0)!=0:0){c[B>>2]=22248;c[l>>2]=29;Oa=uc;Pa=vc;Qa=wc;Ra=la;Sa=xc;Ta=r;Ua=o;Va=yc;break}Od=c[U>>2]|0;if(xa>>>0>Od>>>0){Ja=xa-Od|0;Dg=Ja;Eg=(c[V>>2]|0)+((c[W>>2]|0)-Ja)|0}else{Dg=xa;Eg=(c[V>>2]|0)+(Od-xa)|0}xa=c[F>>2]|0;Fg=xa;Gg=Dg>>>0>xa>>>0?xa:Dg;Hg=Eg}else{xa=c[F>>2]|0;Fg=xa;Gg=xa;Hg=o+(0-ua)|0}ua=Gg>>>0>la>>>0?la:Gg;c[F>>2]=Fg-ua;xa=~la;Od=~Gg;Ja=xa>>>0>Od>>>0?xa:Od;Od=ua;xa=Hg;Td=o;while(1){a[Td]=a[xa]|0;Od=Od+ -1|0;if((Od|0)==0){break}else{xa=xa+1|0;Td=Td+1|0}}Td=la-ua|0;xa=o+~Ja|0;if((c[F>>2]|0)==0){c[l>>2]=20;Oa=uc;Pa=vc;Qa=wc;Ra=Td;Sa=xc;Ta=r;Ua=xa;Va=yc}else{Oa=uc;Pa=vc;Qa=wc;Ra=Td;Sa=xc;Ta=r;Ua=xa;Va=yc}}}while(0);ia=c[l>>2]|0;q=Oa;ja=Pa;ka=Qa;la=Ra;ma=Sa;r=Ta;o=Ua;s=Va}if((ta|0)==122){c[m>>2]=o;c[n>>2]=la;c[f>>2]=Cb;c[p>>2]=Ab;c[u>>2]=Bb;c[v>>2]=zb;k=2;i=h;return k|0}else if((ta|0)==133){ya=Kd+ -3|0;za=Ld;Aa=Md>>>3;Ba=la;Ca=Nd;Da=r;Ea=s}else if((ta|0)==284){c[l>>2]=28;ya=Cd;za=Dd;Aa=Ed;Ba=la;Ca=Fd;Da=jd;Ea=1}else if((ta|0)==285){ya=na;za=oa;Aa=pa;Ba=qa;Ca=ra;Da=r;Ea=sa}else if((ta|0)==299){k=-4;i=h;return k|0}else if((ta|0)==300){i=h;return k|0}c[m>>2]=o;c[n>>2]=Ba;c[f>>2]=Ca;c[p>>2]=za;c[u>>2]=Aa;c[v>>2]=ya;if((c[W>>2]|0)==0){if((c[l>>2]|0)>>>0<26?(Da|0)!=(c[n>>2]|0):0){ta=289}}else{ta=289}if((ta|0)==289?(Lf(f,Da)|0)!=0:0){c[l>>2]=30;k=-4;i=h;return k|0}ta=c[p>>2]|0;p=c[n>>2]|0;n=Da-p|0;W=f+8|0;c[W>>2]=t-ta+(c[W>>2]|0);c[X>>2]=(c[X>>2]|0)+n;c[Y>>2]=(c[Y>>2]|0)+n;Y=(Da|0)==(p|0);if(!((c[w>>2]|0)==0|Y)){w=c[x>>2]|0;p=(c[m>>2]|0)+(0-n)|0;if((c[z>>2]|0)==0){Ig=ff(w,p,n)|0}else{Ig=gf(w,p,n)|0}c[x>>2]=Ig;c[E>>2]=Ig}Ig=c[l>>2]|0;if((Ig|0)==19){Jg=256}else{Jg=(Ig|0)==14?256:0}c[f+44>>2]=((c[I>>2]|0)!=0?64:0)+(c[v>>2]|0)+((Ig|0)==11?128:0)+Jg;k=((t|0)==(ta|0)&Y|(g|0)==4)&(Ea|0)==0?-5:Ea;i=h;return k|0}function Lf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;e=c[a+28>>2]|0;f=e+52|0;g=c[f>>2]|0;if((g|0)==0){h=kb[c[a+32>>2]&1](c[a+40>>2]|0,1<>2],1)|0;c[f>>2]=h;if((h|0)==0){j=1;i=d;return j|0}else{k=h}}else{k=g}g=e+40|0;h=c[g>>2]|0;if((h|0)==0){l=1<>2];c[g>>2]=l;c[e+48>>2]=0;c[e+44>>2]=0;m=l}else{m=h}h=b-(c[a+16>>2]|0)|0;if(!(h>>>0>>0)){Kg(k|0,(c[a+12>>2]|0)+(0-m)|0,m|0)|0;c[e+48>>2]=0;c[e+44>>2]=c[g>>2];j=0;i=d;return j|0}b=e+48|0;l=c[b>>2]|0;n=m-l|0;m=n>>>0>h>>>0?h:n;n=a+12|0;Kg(k+l|0,(c[n>>2]|0)+(0-h)|0,m|0)|0;l=h-m|0;if((h|0)!=(m|0)){Kg(c[f>>2]|0,(c[n>>2]|0)+(0-l)|0,l|0)|0;c[b>>2]=l;c[e+44>>2]=c[g>>2];j=0;i=d;return j|0}l=(c[b>>2]|0)+h|0;n=c[g>>2]|0;c[b>>2]=(l|0)==(n|0)?0:l;l=e+44|0;e=c[l>>2]|0;if(!(e>>>0>>0)){j=0;i=d;return j|0}c[l>>2]=e+h;j=0;i=d;return j|0}function Mf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;i=b;return d|0}g=a+36|0;h=c[g>>2]|0;if((h|0)==0){d=-2;i=b;return d|0}j=c[f+52>>2]|0;k=a+40|0;if((j|0)==0){l=h;m=f}else{mb[h&1](c[k>>2]|0,j);l=c[g>>2]|0;m=c[e>>2]|0}mb[l&1](c[k>>2]|0,m);c[e>>2]=0;d=0;i=b;return d|0}function Nf(d,f,g,h,j,k){d=d|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;l=i;i=i+64|0;m=l+32|0;n=l;o=m+0|0;p=o+32|0;do{b[o>>1]=0;o=o+2|0}while((o|0)<(p|0));o=(g|0)==0;if(!o){p=0;do{q=m+(e[f+(p<<1)>>1]<<1)|0;b[q>>1]=(b[q>>1]|0)+1<<16>>16;p=p+1|0}while((p|0)!=(g|0))}p=c[j>>2]|0;q=15;while(1){r=q+ -1|0;if((b[m+(q<<1)>>1]|0)!=0){break}if((r|0)==0){s=7;break}else{q=r}}if((s|0)==7){r=c[h>>2]|0;c[h>>2]=r+4;a[r]=64;a[r+1|0]=1;b[r+2>>1]=0;r=c[h>>2]|0;c[h>>2]=r+4;a[r]=64;a[r+1|0]=1;b[r+2>>1]=0;c[j>>2]=1;t=0;i=l;return t|0}r=p>>>0>q>>>0?q:p;a:do{if(q>>>0>1){p=1;while(1){u=p+1|0;if((b[m+(p<<1)>>1]|0)!=0){v=p;break a}if(u>>>0>>0){p=u}else{v=u;break}}}else{v=1}}while(0);p=r>>>0>>0?v:r;r=1;u=1;do{r=(r<<1)-(e[m+(u<<1)>>1]|0)|0;u=u+1|0;if((r|0)<0){t=-1;s=56;break}}while(u>>>0<16);if((s|0)==56){i=l;return t|0}if((r|0)>0?!((d|0)!=0&(q|0)==1):0){t=-1;i=l;return t|0}b[n+2>>1]=0;r=0;u=1;do{r=(e[m+(u<<1)>>1]|0)+(r&65535)|0;u=u+1|0;b[n+(u<<1)>>1]=r}while((u|0)!=15);if(!o){o=0;do{u=b[f+(o<<1)>>1]|0;if(!(u<<16>>16==0)){r=n+((u&65535)<<1)|0;u=b[r>>1]|0;b[r>>1]=u+1<<16>>16;b[k+((u&65535)<<1)>>1]=o}o=o+1|0}while((o|0)!=(g|0))}if((d|0)==0){w=0;x=1<>>0>851){t=1;i=l;return t|0}else{w=0;x=g;y=1;z=24504+ -514|0;A=256;B=24568+ -514|0}}else{g=1<>>0>591){t=1;i=l;return t|0}else{w=o;x=g;y=0;z=24632;A=-1;B=24696}}g=x+ -1|0;o=p&255;d=p;n=0;u=0;r=v;v=-1;C=c[h>>2]|0;D=0;E=x;b:while(1){x=1<>1]|0;L=K&65535;if((L|0)>=(A|0)){if((L|0)>(A|0)){M=b[B+(L<<1)>>1]&255;N=b[z+(L<<1)>>1]|0}else{M=96;N=0}}else{M=0;N=K}K=1<>>n;L=x;while(1){O=L-K|0;P=O+I|0;a[C+(P<<2)|0]=M;a[C+(P<<2)+1|0]=J;b[C+(P<<2)+2>>1]=N;if((L|0)==(K|0)){break}else{L=O}}L=1<>>1}}if((L|0)==0){Q=0}else{Q=(L+ -1&F)+L|0}R=H+1|0;K=m+(G<<1)|0;I=(b[K>>1]|0)+ -1<<16>>16;b[K>>1]=I;if(I<<16>>16==0){if((G|0)==(q|0)){break b}S=e[f+(e[k+(R<<1)>>1]<<1)>>1]|0}else{S=G}if(!(S>>>0>p>>>0)){F=Q;G=S;H=R;continue}T=Q&g;if((T|0)==(v|0)){F=Q;G=S;H=R}else{break}}H=(n|0)==0?p:n;G=C+(x<<2)|0;F=S-H|0;c:do{if(S>>>0>>0){I=S;K=F;O=1<>1]|0)|0;if((P|0)<1){U=K;break c}V=K+1|0;W=V+H|0;if(W>>>0>>0){I=W;K=V;O=P<<1}else{U=V;break}}}else{U=F}}while(0);F=(1<>>0>851|w&F>>>0>591){t=1;s=56;break}a[(c[h>>2]|0)+(T<<2)|0]=U;a[(c[h>>2]|0)+(T<<2)+1|0]=o;x=c[h>>2]|0;b[x+(T<<2)+2>>1]=(G-x|0)>>>2;d=U;n=H;u=Q;r=S;v=T;C=G;D=R;E=F}if((s|0)==56){i=l;return t|0}d:do{if((Q|0)!=0){s=n;R=J;D=Q;T=q;S=C;while(1){if((s|0)!=0){if((D&g|0)==(v|0)){X=s;Y=R;Z=T;_=S}else{X=0;Y=o;Z=p;_=c[h>>2]|0}}else{X=0;Y=R;Z=T;_=S}r=D>>>X;a[_+(r<<2)|0]=64;a[_+(r<<2)+1|0]=Y;b[_+(r<<2)+2>>1]=0;r=1<>>1}}if((r|0)==0){break d}D=(r+ -1&D)+r|0;if((D|0)==0){break}else{s=X;R=Y;T=Z;S=_}}}}while(0);c[h>>2]=(c[h>>2]|0)+(E<<2);c[j>>2]=p;t=0;i=l;return t|0}function Of(a){a=a|0;var d=0;d=i;c[a+2840>>2]=a+148;c[a+2848>>2]=25528;c[a+2852>>2]=a+2440;c[a+2860>>2]=25552;c[a+2864>>2]=a+2684;c[a+2872>>2]=25576;b[a+5816>>1]=0;c[a+5820>>2]=0;c[a+5812>>2]=8;Pf(a);i=d;return}function Pf(a){a=a|0;var d=0,e=0;d=i;e=0;do{b[a+(e<<2)+148>>1]=0;e=e+1|0}while((e|0)!=286);b[a+2440>>1]=0;b[a+2444>>1]=0;b[a+2448>>1]=0;b[a+2452>>1]=0;b[a+2456>>1]=0;b[a+2460>>1]=0;b[a+2464>>1]=0;b[a+2468>>1]=0;b[a+2472>>1]=0;b[a+2476>>1]=0;b[a+2480>>1]=0;b[a+2484>>1]=0;b[a+2488>>1]=0;b[a+2492>>1]=0;b[a+2496>>1]=0;b[a+2500>>1]=0;b[a+2504>>1]=0;b[a+2508>>1]=0;b[a+2512>>1]=0;b[a+2516>>1]=0;b[a+2520>>1]=0;b[a+2524>>1]=0;b[a+2528>>1]=0;b[a+2532>>1]=0;b[a+2536>>1]=0;b[a+2540>>1]=0;b[a+2544>>1]=0;b[a+2548>>1]=0;b[a+2552>>1]=0;b[a+2556>>1]=0;b[a+2684>>1]=0;b[a+2688>>1]=0;b[a+2692>>1]=0;b[a+2696>>1]=0;b[a+2700>>1]=0;b[a+2704>>1]=0;b[a+2708>>1]=0;b[a+2712>>1]=0;b[a+2716>>1]=0;b[a+2720>>1]=0;b[a+2724>>1]=0;b[a+2728>>1]=0;b[a+2732>>1]=0;b[a+2736>>1]=0;b[a+2740>>1]=0;b[a+2744>>1]=0;b[a+2748>>1]=0;b[a+2752>>1]=0;b[a+2756>>1]=0;b[a+1172>>1]=1;c[a+5804>>2]=0;c[a+5800>>2]=0;c[a+5808>>2]=0;c[a+5792>>2]=0;i=d;return}function Qf(d,f,g,h){d=d|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;j=i;k=d+5820|0;l=c[k>>2]|0;m=h&65535;h=d+5816|0;n=e[h>>1]|0|m<>1]=n;if((l|0)>13){o=d+20|0;p=c[o>>2]|0;c[o>>2]=p+1;q=d+8|0;a[(c[q>>2]|0)+p|0]=n;p=(e[h>>1]|0)>>>8&255;r=c[o>>2]|0;c[o>>2]=r+1;a[(c[q>>2]|0)+r|0]=p;p=c[k>>2]|0;r=m>>>(16-p|0);b[h>>1]=r;s=r;t=p+ -13|0}else{s=n;t=l+3|0}l=s&255;c[k>>2]=t;do{if((t|0)<=8){s=d+20|0;if((t|0)>0){n=c[s>>2]|0;c[s>>2]=n+1;p=d+8|0;a[(c[p>>2]|0)+n|0]=l;u=s;v=p;break}else{u=s;v=d+8|0;break}}else{s=d+20|0;p=c[s>>2]|0;c[s>>2]=p+1;n=d+8|0;a[(c[n>>2]|0)+p|0]=l;p=(e[h>>1]|0)>>>8&255;r=c[s>>2]|0;c[s>>2]=r+1;a[(c[n>>2]|0)+r|0]=p;u=s;v=n}}while(0);b[h>>1]=0;c[k>>2]=0;c[d+5812>>2]=8;d=c[u>>2]|0;c[u>>2]=d+1;a[(c[v>>2]|0)+d|0]=g;d=c[u>>2]|0;c[u>>2]=d+1;a[(c[v>>2]|0)+d|0]=g>>>8;d=g&65535^65535;k=c[u>>2]|0;c[u>>2]=k+1;a[(c[v>>2]|0)+k|0]=d;k=c[u>>2]|0;c[u>>2]=k+1;a[(c[v>>2]|0)+k|0]=d>>>8;if((g|0)==0){i=j;return}else{w=g;x=f}while(1){w=w+ -1|0;f=a[x]|0;g=c[u>>2]|0;c[u>>2]=g+1;a[(c[v>>2]|0)+g|0]=f;if((w|0)==0){break}else{x=x+1|0}}i=j;return}function Rf(d){d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;f=i;g=d+5820|0;h=c[g>>2]|0;j=d+5816|0;k=e[j>>1]|0|2<>1]=l;if((h|0)>13){m=d+20|0;n=c[m>>2]|0;c[m>>2]=n+1;o=d+8|0;a[(c[o>>2]|0)+n|0]=k;k=(e[j>>1]|0)>>>8&255;n=c[m>>2]|0;c[m>>2]=n+1;a[(c[o>>2]|0)+n|0]=k;k=c[g>>2]|0;n=2>>>(16-k|0)&65535;b[j>>1]=n;p=n;q=k+ -13|0}else{p=l;q=h+3|0}c[g>>2]=q;if((q|0)>9){h=d+20|0;l=c[h>>2]|0;c[h>>2]=l+1;k=d+8|0;a[(c[k>>2]|0)+l|0]=p;l=(e[j>>1]|0)>>>8&255;n=c[h>>2]|0;c[h>>2]=n+1;a[(c[k>>2]|0)+n|0]=l;b[j>>1]=0;r=(c[g>>2]|0)+ -9|0;s=0}else{r=q+7|0;s=p}c[g>>2]=r;if((r|0)!=16){if((r|0)>7){p=d+20|0;q=c[p>>2]|0;c[p>>2]=q+1;a[(c[d+8>>2]|0)+q|0]=s;q=(e[j>>1]|0)>>>8;b[j>>1]=q;p=(c[g>>2]|0)+ -8|0;c[g>>2]=p;t=p;u=q}else{t=r;u=s}}else{r=d+20|0;q=c[r>>2]|0;c[r>>2]=q+1;p=d+8|0;a[(c[p>>2]|0)+q|0]=s;s=(e[j>>1]|0)>>>8&255;q=c[r>>2]|0;c[r>>2]=q+1;a[(c[p>>2]|0)+q|0]=s;b[j>>1]=0;c[g>>2]=0;t=0;u=0}s=d+5812|0;if((11-t+(c[s>>2]|0)|0)>=9){c[s>>2]=7;i=f;return}q=u&65535|2<>1]=q;if((t|0)>13){u=d+20|0;p=c[u>>2]|0;c[u>>2]=p+1;r=d+8|0;a[(c[r>>2]|0)+p|0]=q;p=(e[j>>1]|0)>>>8&255;l=c[u>>2]|0;c[u>>2]=l+1;a[(c[r>>2]|0)+l|0]=p;p=c[g>>2]|0;l=2>>>(16-p|0);b[j>>1]=l;v=l;w=p+ -13|0}else{v=q;w=t+3|0}t=v&255;c[g>>2]=w;if((w|0)>9){v=d+20|0;q=c[v>>2]|0;c[v>>2]=q+1;p=d+8|0;a[(c[p>>2]|0)+q|0]=t;q=(e[j>>1]|0)>>>8&255;l=c[v>>2]|0;c[v>>2]=l+1;a[(c[p>>2]|0)+l|0]=q;b[j>>1]=0;x=0;y=(c[g>>2]|0)+ -9|0}else{x=t;y=w+7|0}c[g>>2]=y;if((y|0)==16){w=d+20|0;t=c[w>>2]|0;c[w>>2]=t+1;q=d+8|0;a[(c[q>>2]|0)+t|0]=x;t=(e[j>>1]|0)>>>8&255;l=c[w>>2]|0;c[w>>2]=l+1;a[(c[q>>2]|0)+l|0]=t;b[j>>1]=0;c[g>>2]=0;c[s>>2]=7;i=f;return}if((y|0)<=7){c[s>>2]=7;i=f;return}y=d+20|0;t=c[y>>2]|0;c[y>>2]=t+1;a[(c[d+8>>2]|0)+t|0]=x;b[j>>1]=(e[j>>1]|0)>>>8;c[g>>2]=(c[g>>2]|0)+ -8;c[s>>2]=7;i=f;return}function Sf(f,g,h,j){f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;k=i;if((c[f+132>>2]|0)>0){l=(c[f>>2]|0)+44|0;if((c[l>>2]|0)==2){m=-201342849;n=0;while(1){if((m&1|0)!=0?(b[f+(n<<2)+148>>1]|0)!=0:0){o=0;break}p=n+1|0;if((p|0)<32){m=m>>>1;n=p}else{q=6;break}}a:do{if((q|0)==6){if(((b[f+184>>1]|0)==0?(b[f+188>>1]|0)==0:0)?(b[f+200>>1]|0)==0:0){n=32;while(1){m=n+1|0;if((b[f+(n<<2)+148>>1]|0)!=0){o=1;break a}if((m|0)<256){n=m}else{o=0;break}}}else{o=1}}}while(0);c[l>>2]=o}Tf(f,f+2840|0);Tf(f,f+2852|0);Wf(f,f+148|0,c[f+2844>>2]|0);Wf(f,f+2440|0,c[f+2856>>2]|0);Tf(f,f+2864|0);o=18;while(1){l=o+ -1|0;if((b[f+(d[27352+o|0]<<2)+2686>>1]|0)!=0){r=o;break}if((l|0)>2){o=l}else{r=l;break}}o=f+5800|0;l=(r*3|0)+17+(c[o>>2]|0)|0;c[o>>2]=l;o=(l+10|0)>>>3;l=((c[f+5804>>2]|0)+10|0)>>>3;s=r;t=l>>>0>o>>>0?o:l;u=l}else{l=h+5|0;s=0;t=l;u=l}do{if((h+4|0)>>>0>t>>>0|(g|0)==0){l=f+5820|0;o=c[l>>2]|0;r=(o|0)>13;if((c[f+136>>2]|0)==4|(u|0)==(t|0)){q=j+2&65535;n=f+5816|0;m=e[n>>1]|q<>1]=m;if(r){p=f+20|0;v=c[p>>2]|0;c[p>>2]=v+1;w=f+8|0;a[(c[w>>2]|0)+v|0]=m;m=(e[n>>1]|0)>>>8&255;v=c[p>>2]|0;c[p>>2]=v+1;a[(c[w>>2]|0)+v|0]=m;m=c[l>>2]|0;b[n>>1]=q>>>(16-m|0);x=m+ -13|0}else{x=o+3|0}c[l>>2]=x;Uf(f,25600,26752);break}m=j+4&65535;q=f+5816|0;n=e[q>>1]|m<>1]=n;if(r){r=f+20|0;v=c[r>>2]|0;c[r>>2]=v+1;w=f+8|0;a[(c[w>>2]|0)+v|0]=n;v=(e[q>>1]|0)>>>8&255;p=c[r>>2]|0;c[r>>2]=p+1;a[(c[w>>2]|0)+p|0]=v;v=c[l>>2]|0;p=m>>>(16-v|0);b[q>>1]=p;y=p;z=v+ -13|0}else{y=n;z=o+3|0}c[l>>2]=z;o=c[f+2844>>2]|0;n=c[f+2856>>2]|0;v=o+65280&65535;p=y&65535|v<>1]=p;if((z|0)>11){m=f+20|0;w=c[m>>2]|0;c[m>>2]=w+1;r=f+8|0;a[(c[r>>2]|0)+w|0]=p;w=(e[q>>1]|0)>>>8&255;A=c[m>>2]|0;c[m>>2]=A+1;a[(c[r>>2]|0)+A|0]=w;w=c[l>>2]|0;A=v>>>(16-w|0);b[q>>1]=A;B=w+ -11|0;C=A}else{B=z+5|0;C=p}c[l>>2]=B;p=n&65535;A=p<>1]=A;if((B|0)>11){w=f+20|0;v=c[w>>2]|0;c[w>>2]=v+1;r=f+8|0;a[(c[r>>2]|0)+v|0]=A;v=(e[q>>1]|0)>>>8&255;m=c[w>>2]|0;c[w>>2]=m+1;a[(c[r>>2]|0)+m|0]=v;v=c[l>>2]|0;m=p>>>(16-v|0);b[q>>1]=m;D=v+ -11|0;E=m}else{D=B+5|0;E=A}c[l>>2]=D;A=s+65533&65535;m=A<>1]=m;if((D|0)>12){v=f+20|0;p=c[v>>2]|0;c[v>>2]=p+1;r=f+8|0;a[(c[r>>2]|0)+p|0]=m;p=(e[q>>1]|0)>>>8&255;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[r>>2]|0)+w|0]=p;p=c[l>>2]|0;w=A>>>(16-p|0);b[q>>1]=w;F=w;G=p+ -12|0}else{F=m;G=D+4|0}c[l>>2]=G;if((s|0)>-1){m=f+20|0;p=f+8|0;w=G;A=F;r=0;while(1){v=e[f+(d[27352+r|0]<<2)+2686>>1]|0;H=v<>1]=H;if((w|0)>13){I=c[m>>2]|0;c[m>>2]=I+1;a[(c[p>>2]|0)+I|0]=H;I=(e[q>>1]|0)>>>8&255;J=c[m>>2]|0;c[m>>2]=J+1;a[(c[p>>2]|0)+J|0]=I;I=c[l>>2]|0;J=v>>>(16-I|0);b[q>>1]=J;K=J;L=I+ -13|0}else{K=H;L=w+3|0}c[l>>2]=L;if((r|0)==(s|0)){break}else{w=L;A=K;r=r+1|0}}}r=f+148|0;Vf(f,r,o);A=f+2440|0;Vf(f,A,n);Uf(f,r,A)}else{Qf(f,g,h,j)}}while(0);Pf(f);if((j|0)==0){i=k;return}j=f+5820|0;h=c[j>>2]|0;if((h|0)<=8){g=f+5816|0;if((h|0)>0){h=b[g>>1]&255;K=f+20|0;L=c[K>>2]|0;c[K>>2]=L+1;a[(c[f+8>>2]|0)+L|0]=h;M=g}else{M=g}}else{g=f+5816|0;h=b[g>>1]&255;L=f+20|0;K=c[L>>2]|0;c[L>>2]=K+1;s=f+8|0;a[(c[s>>2]|0)+K|0]=h;h=(e[g>>1]|0)>>>8&255;K=c[L>>2]|0;c[L>>2]=K+1;a[(c[s>>2]|0)+K|0]=h;M=g}b[M>>1]=0;c[j>>2]=0;i=k;return}function Tf(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0;h=i;i=i+32|0;j=h;k=c[g>>2]|0;l=g+8|0;m=c[l>>2]|0;n=c[m>>2]|0;o=c[m+12>>2]|0;m=f+5200|0;c[m>>2]=0;p=f+5204|0;c[p>>2]=573;if((o|0)>0){q=-1;r=0;while(1){if((b[k+(r<<2)>>1]|0)==0){b[k+(r<<2)+2>>1]=0;s=q}else{t=(c[m>>2]|0)+1|0;c[m>>2]=t;c[f+(t<<2)+2908>>2]=r;a[f+r+5208|0]=0;s=r}r=r+1|0;if((r|0)==(o|0)){break}else{q=s}}q=c[m>>2]|0;if((q|0)<2){u=q;v=s;w=3}else{x=s}}else{u=0;v=-1;w=3}if((w|0)==3){w=f+5800|0;s=f+5804|0;if((n|0)==0){q=u;r=v;while(1){t=(r|0)<2;y=r+1|0;z=t?y:r;A=t?y:0;y=q+1|0;c[m>>2]=y;c[f+(y<<2)+2908>>2]=A;b[k+(A<<2)>>1]=1;a[f+A+5208|0]=0;c[w>>2]=(c[w>>2]|0)+ -1;A=c[m>>2]|0;if((A|0)<2){q=A;r=z}else{x=z;break}}}else{r=u;u=v;while(1){v=(u|0)<2;q=u+1|0;z=v?q:u;A=v?q:0;q=r+1|0;c[m>>2]=q;c[f+(q<<2)+2908>>2]=A;b[k+(A<<2)>>1]=1;a[f+A+5208|0]=0;c[w>>2]=(c[w>>2]|0)+ -1;c[s>>2]=(c[s>>2]|0)-(e[n+(A<<2)+2>>1]|0);A=c[m>>2]|0;if((A|0)<2){r=A;u=z}else{x=z;break}}}}u=g+4|0;c[u>>2]=x;r=c[m>>2]|0;if((r|0)>1){n=r;s=(r|0)/2|0;while(1){w=c[f+(s<<2)+2908>>2]|0;z=f+w+5208|0;A=s<<1;a:do{if((A|0)>(n|0)){B=s}else{q=k+(w<<2)|0;v=s;y=n;t=A;while(1){do{if((t|0)<(y|0)){C=t|1;D=c[f+(C<<2)+2908>>2]|0;E=b[k+(D<<2)>>1]|0;F=c[f+(t<<2)+2908>>2]|0;G=b[k+(F<<2)>>1]|0;if(!((E&65535)<(G&65535))){if(!(E<<16>>16==G<<16>>16)){H=t;break}if((d[f+D+5208|0]|0)>(d[f+F+5208|0]|0)){H=t;break}}H=C}else{H=t}}while(0);C=b[q>>1]|0;F=c[f+(H<<2)+2908>>2]|0;D=b[k+(F<<2)>>1]|0;if((C&65535)<(D&65535)){B=v;break a}if(C<<16>>16==D<<16>>16?(d[z]|0)<=(d[f+F+5208|0]|0):0){B=v;break a}c[f+(v<<2)+2908>>2]=F;F=H<<1;D=c[m>>2]|0;if((F|0)>(D|0)){B=H;break}else{v=H;y=D;t=F}}}}while(0);c[f+(B<<2)+2908>>2]=w;z=s+ -1|0;A=c[m>>2]|0;if((z|0)>0){n=A;s=z}else{I=A;break}}}else{I=r}r=f+2912|0;s=I;I=o;while(1){o=c[r>>2]|0;n=s+ -1|0;c[m>>2]=n;B=c[f+(s<<2)+2908>>2]|0;c[r>>2]=B;H=f+B+5208|0;b:do{if((s|0)<3){J=1}else{A=k+(B<<2)|0;z=1;t=n;y=2;while(1){do{if((y|0)<(t|0)){v=y|1;q=c[f+(v<<2)+2908>>2]|0;F=b[k+(q<<2)>>1]|0;D=c[f+(y<<2)+2908>>2]|0;C=b[k+(D<<2)>>1]|0;if(!((F&65535)<(C&65535))){if(!(F<<16>>16==C<<16>>16)){K=y;break}if((d[f+q+5208|0]|0)>(d[f+D+5208|0]|0)){K=y;break}}K=v}else{K=y}}while(0);v=b[A>>1]|0;D=c[f+(K<<2)+2908>>2]|0;q=b[k+(D<<2)>>1]|0;if((v&65535)<(q&65535)){J=z;break b}if(v<<16>>16==q<<16>>16?(d[H]|0)<=(d[f+D+5208|0]|0):0){J=z;break b}c[f+(z<<2)+2908>>2]=D;D=K<<1;q=c[m>>2]|0;if((D|0)>(q|0)){J=K;break}else{z=K;t=q;y=D}}}}while(0);c[f+(J<<2)+2908>>2]=B;H=c[r>>2]|0;n=(c[p>>2]|0)+ -1|0;c[p>>2]=n;c[f+(n<<2)+2908>>2]=o;n=(c[p>>2]|0)+ -1|0;c[p>>2]=n;c[f+(n<<2)+2908>>2]=H;n=k+(I<<2)|0;b[n>>1]=(e[k+(H<<2)>>1]|0)+(e[k+(o<<2)>>1]|0);w=a[f+o+5208|0]|0;y=a[f+H+5208|0]|0;t=f+I+5208|0;a[t]=(((w&255)<(y&255)?y:w)&255)+1;w=I&65535;b[k+(H<<2)+2>>1]=w;b[k+(o<<2)+2>>1]=w;w=I+1|0;c[r>>2]=I;H=c[m>>2]|0;c:do{if((H|0)<2){L=1}else{y=1;z=H;A=2;while(1){do{if((A|0)<(z|0)){D=A|1;q=c[f+(D<<2)+2908>>2]|0;v=b[k+(q<<2)>>1]|0;C=c[f+(A<<2)+2908>>2]|0;F=b[k+(C<<2)>>1]|0;if(!((v&65535)<(F&65535))){if(!(v<<16>>16==F<<16>>16)){M=A;break}if((d[f+q+5208|0]|0)>(d[f+C+5208|0]|0)){M=A;break}}M=D}else{M=A}}while(0);D=b[n>>1]|0;C=c[f+(M<<2)+2908>>2]|0;q=b[k+(C<<2)>>1]|0;if((D&65535)<(q&65535)){L=y;break c}if(D<<16>>16==q<<16>>16?(d[t]|0)<=(d[f+C+5208|0]|0):0){L=y;break c}c[f+(y<<2)+2908>>2]=C;C=M<<1;q=c[m>>2]|0;if((C|0)>(q|0)){L=M;break}else{y=M;z=q;A=C}}}}while(0);c[f+(L<<2)+2908>>2]=I;t=c[m>>2]|0;if((t|0)>1){s=t;I=w}else{break}}I=c[r>>2]|0;r=(c[p>>2]|0)+ -1|0;c[p>>2]=r;c[f+(r<<2)+2908>>2]=I;I=c[g>>2]|0;g=c[u>>2]|0;u=c[l>>2]|0;l=c[u>>2]|0;r=c[u+4>>2]|0;s=c[u+8>>2]|0;m=c[u+16>>2]|0;u=f+2876|0;L=u+32|0;do{b[u>>1]=0;u=u+2|0}while((u|0)<(L|0));u=c[p>>2]|0;b[I+(c[f+(u<<2)+2908>>2]<<2)+2>>1]=0;p=u+1|0;d:do{if((p|0)<573){u=f+5800|0;L=f+5804|0;if((l|0)==0){M=p;J=0;while(1){K=c[f+(M<<2)+2908>>2]|0;t=I+(K<<2)+2|0;n=e[I+(e[t>>1]<<2)+2>>1]|0;H=(n|0)<(m|0);o=H?n+1|0:m;n=(H&1^1)+J|0;b[t>>1]=o;if((K|0)<=(g|0)){t=f+(o<<1)+2876|0;b[t>>1]=(b[t>>1]|0)+1<<16>>16;if((K|0)<(s|0)){N=0}else{N=c[r+(K-s<<2)>>2]|0}t=aa(e[I+(K<<2)>>1]|0,N+o|0)|0;c[u>>2]=t+(c[u>>2]|0)}t=M+1|0;if((t|0)==573){O=n;break}else{M=t;J=n}}}else{J=p;M=0;while(1){w=c[f+(J<<2)+2908>>2]|0;n=I+(w<<2)+2|0;t=e[I+(e[n>>1]<<2)+2>>1]|0;o=(t|0)<(m|0);K=o?t+1|0:m;t=(o&1^1)+M|0;b[n>>1]=K;if((w|0)<=(g|0)){n=f+(K<<1)+2876|0;b[n>>1]=(b[n>>1]|0)+1<<16>>16;if((w|0)<(s|0)){P=0}else{P=c[r+(w-s<<2)>>2]|0}n=e[I+(w<<2)>>1]|0;o=aa(n,P+K|0)|0;c[u>>2]=o+(c[u>>2]|0);o=aa((e[l+(w<<2)+2>>1]|0)+P|0,n)|0;c[L>>2]=o+(c[L>>2]|0)}o=J+1|0;if((o|0)==573){O=t;break}else{J=o;M=t}}}if((O|0)!=0){M=f+(m<<1)+2876|0;J=O;do{L=m;while(1){t=L+ -1|0;Q=f+(t<<1)+2876|0;R=b[Q>>1]|0;if(R<<16>>16==0){L=t}else{break}}b[Q>>1]=R+ -1<<16>>16;t=f+(L<<1)+2876|0;b[t>>1]=(e[t>>1]|0)+2;S=(b[M>>1]|0)+ -1<<16>>16;b[M>>1]=S;J=J+ -2|0}while((J|0)>0);if((m|0)!=0){J=S;M=m;t=573;while(1){o=M&65535;if(J<<16>>16==0){T=t}else{n=t;w=J&65535;while(1){K=n;do{K=K+ -1|0;U=c[f+(K<<2)+2908>>2]|0}while((U|0)>(g|0));H=I+(U<<2)+2|0;B=e[H>>1]|0;if((B|0)!=(M|0)){A=aa(e[I+(U<<2)>>1]|0,M-B|0)|0;c[u>>2]=A+(c[u>>2]|0);b[H>>1]=o}H=w+ -1|0;if((H|0)==0){T=K;break}else{n=K;w=H}}}w=M+ -1|0;if((w|0)==0){break d}J=b[f+(w<<1)+2876>>1]|0;M=w;t=T}}}}}while(0);T=1;U=0;do{U=(e[f+(T+ -1<<1)+2876>>1]|0)+(U&65534)<<1;b[j+(T<<1)>>1]=U;T=T+1|0}while((T|0)!=16);if((x|0)<0){i=h;return}else{V=0}while(1){T=b[k+(V<<2)+2>>1]|0;U=T&65535;if(!(T<<16>>16==0)){T=j+(U<<1)|0;f=b[T>>1]|0;b[T>>1]=f+1<<16>>16;T=U;U=f&65535;f=0;while(1){W=f|U&1;T=T+ -1|0;if((T|0)<=0){break}else{U=U>>>1;f=W<<1}}b[k+(V<<2)>>1]=W}if((V|0)==(x|0)){break}else{V=V+1|0}}i=h;return}function Uf(f,g,h){f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0;j=i;k=f+5792|0;if((c[k>>2]|0)==0){l=c[f+5820>>2]|0;m=b[f+5816>>1]|0}else{n=f+5796|0;o=f+5784|0;p=f+5820|0;q=f+5816|0;r=f+20|0;s=f+8|0;t=0;while(1){u=b[(c[n>>2]|0)+(t<<1)>>1]|0;v=u&65535;w=t+1|0;x=d[(c[o>>2]|0)+t|0]|0;do{if(u<<16>>16==0){y=e[g+(x<<2)+2>>1]|0;z=c[p>>2]|0;A=e[g+(x<<2)>>1]|0;B=e[q>>1]|0|A<>1]=C;if((z|0)>(16-y|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=B;B=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=B;B=c[p>>2]|0;D=A>>>(16-B|0)&65535;b[q>>1]=D;A=y+ -16+B|0;c[p>>2]=A;E=D;F=A;break}else{A=z+y|0;c[p>>2]=A;E=C;F=A;break}}else{A=d[25272+x|0]|0;C=(A|256)+1|0;y=e[g+(C<<2)+2>>1]|0;z=c[p>>2]|0;D=e[g+(C<<2)>>1]|0;C=e[q>>1]|0|D<>1]=B;if((z|0)>(16-y|0)){G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=C;C=(e[q>>1]|0)>>>8&255;G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=C;C=c[p>>2]|0;G=D>>>(16-C|0)&65535;b[q>>1]=G;H=G;I=y+ -16+C|0}else{H=B;I=z+y|0}c[p>>2]=I;y=c[26872+(A<<2)>>2]|0;do{if((A+ -8|0)>>>0<20){z=x-(c[26992+(A<<2)>>2]|0)&65535;B=z<>1]=C;if((I|0)>(16-y|0)){G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=B;B=(e[q>>1]|0)>>>8&255;G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=B;B=c[p>>2]|0;G=z>>>(16-B|0)&65535;b[q>>1]=G;z=y+ -16+B|0;c[p>>2]=z;J=z;K=G;break}else{G=I+y|0;c[p>>2]=G;J=G;K=C;break}}else{J=I;K=H}}while(0);y=v+ -1|0;if(y>>>0<256){L=y}else{L=(y>>>7)+256|0}A=d[24760+L|0]|0;C=e[h+(A<<2)+2>>1]|0;G=e[h+(A<<2)>>1]|0;z=K&65535|G<>1]=B;if((J|0)>(16-C|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=z;z=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=z;z=c[p>>2]|0;D=G>>>(16-z|0)&65535;b[q>>1]=D;M=C+ -16+z|0;N=D}else{M=J+C|0;N=B}c[p>>2]=M;B=c[27112+(A<<2)>>2]|0;if((A+ -4|0)>>>0<26){C=y-(c[27232+(A<<2)>>2]|0)&65535;A=C<>1]=y;if((M|0)>(16-B|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=A;A=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=A;A=c[p>>2]|0;D=C>>>(16-A|0)&65535;b[q>>1]=D;C=B+ -16+A|0;c[p>>2]=C;E=D;F=C;break}else{C=M+B|0;c[p>>2]=C;E=y;F=C;break}}else{E=N;F=M}}}while(0);if(w>>>0<(c[k>>2]|0)>>>0){t=w}else{l=F;m=E;break}}}E=g+1026|0;F=e[E>>1]|0;t=f+5820|0;k=e[g+1024>>1]|0;g=f+5816|0;M=m&65535|k<>1]=M;if((l|0)>(16-F|0)){m=f+20|0;N=c[m>>2]|0;c[m>>2]=N+1;p=f+8|0;a[(c[p>>2]|0)+N|0]=M;M=(e[g>>1]|0)>>>8&255;N=c[m>>2]|0;c[m>>2]=N+1;a[(c[p>>2]|0)+N|0]=M;M=c[t>>2]|0;b[g>>1]=k>>>(16-M|0);O=F+ -16+M|0;c[t>>2]=O;P=b[E>>1]|0;Q=P&65535;R=f+5812|0;c[R>>2]=Q;i=j;return}else{O=l+F|0;c[t>>2]=O;P=b[E>>1]|0;Q=P&65535;R=f+5812|0;c[R>>2]=Q;i=j;return}}function Vf(d,f,g){d=d|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0;h=i;j=b[f+2>>1]|0;k=j<<16>>16==0;l=d+2754|0;m=d+5820|0;n=d+2752|0;o=d+5816|0;p=d+20|0;q=d+8|0;r=d+2758|0;s=d+2756|0;t=d+2750|0;u=d+2748|0;v=k?138:7;w=k?3:4;k=0;x=j&65535;j=-1;a:while(1){y=0;z=k;while(1){if((z|0)>(g|0)){break a}z=z+1|0;A=b[f+(z<<2)+2>>1]|0;B=A&65535;C=y+1|0;D=(x|0)==(B|0);if(!((C|0)<(v|0)&D)){break}else{y=C}}do{if((C|0)>=(w|0)){if((x|0)!=0){if((x|0)==(j|0)){E=b[o>>1]|0;F=c[m>>2]|0;G=C}else{H=e[d+(x<<2)+2686>>1]|0;I=c[m>>2]|0;J=e[d+(x<<2)+2684>>1]|0;K=e[o>>1]|0|J<>1]=L;if((I|0)>(16-H|0)){M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=c[m>>2]|0;M=J>>>(16-K|0)&65535;b[o>>1]=M;N=M;O=H+ -16+K|0}else{N=L;O=I+H|0}c[m>>2]=O;E=N;F=O;G=y}H=e[t>>1]|0;I=e[u>>1]|0;L=E&65535|I<>1]=L;if((F|0)>(16-H|0)){K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=L;K=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=c[m>>2]|0;M=I>>>(16-K|0);b[o>>1]=M;P=H+ -16+K|0;Q=M}else{P=F+H|0;Q=L}c[m>>2]=P;L=G+65533&65535;H=Q&65535|L<>1]=H;if((P|0)>14){M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=H;H=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=H;H=c[m>>2]|0;b[o>>1]=L>>>(16-H|0);c[m>>2]=H+ -14;break}else{c[m>>2]=P+2;break}}if((C|0)<11){H=e[l>>1]|0;L=c[m>>2]|0;M=e[n>>1]|0;K=e[o>>1]|0|M<>1]=K;if((L|0)>(16-H|0)){I=c[p>>2]|0;c[p>>2]=I+1;a[(c[q>>2]|0)+I|0]=K;I=(e[o>>1]|0)>>>8&255;J=c[p>>2]|0;c[p>>2]=J+1;a[(c[q>>2]|0)+J|0]=I;I=c[m>>2]|0;J=M>>>(16-I|0);b[o>>1]=J;R=H+ -16+I|0;S=J}else{R=L+H|0;S=K}c[m>>2]=R;K=y+65534&65535;H=S&65535|K<>1]=H;if((R|0)>13){L=c[p>>2]|0;c[p>>2]=L+1;a[(c[q>>2]|0)+L|0]=H;H=(e[o>>1]|0)>>>8&255;L=c[p>>2]|0;c[p>>2]=L+1;a[(c[q>>2]|0)+L|0]=H;H=c[m>>2]|0;b[o>>1]=K>>>(16-H|0);c[m>>2]=H+ -13;break}else{c[m>>2]=R+3;break}}else{H=e[r>>1]|0;K=c[m>>2]|0;L=e[s>>1]|0;J=e[o>>1]|0|L<>1]=J;if((K|0)>(16-H|0)){I=c[p>>2]|0;c[p>>2]=I+1;a[(c[q>>2]|0)+I|0]=J;I=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=I;I=c[m>>2]|0;M=L>>>(16-I|0);b[o>>1]=M;T=H+ -16+I|0;U=M}else{T=K+H|0;U=J}c[m>>2]=T;J=y+65526&65535;H=U&65535|J<>1]=H;if((T|0)>9){K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=H;H=(e[o>>1]|0)>>>8&255;K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=H;H=c[m>>2]|0;b[o>>1]=J>>>(16-H|0);c[m>>2]=H+ -9;break}else{c[m>>2]=T+7;break}}}else{H=d+(x<<2)+2686|0;J=d+(x<<2)+2684|0;K=c[m>>2]|0;M=b[o>>1]|0;I=C;while(1){L=e[H>>1]|0;V=e[J>>1]|0;W=M&65535|V<>1]=X;if((K|0)>(16-L|0)){Y=c[p>>2]|0;c[p>>2]=Y+1;a[(c[q>>2]|0)+Y|0]=W;W=(e[o>>1]|0)>>>8&255;Y=c[p>>2]|0;c[p>>2]=Y+1;a[(c[q>>2]|0)+Y|0]=W;W=c[m>>2]|0;Y=V>>>(16-W|0)&65535;b[o>>1]=Y;Z=Y;_=L+ -16+W|0}else{Z=X;_=K+L|0}c[m>>2]=_;I=I+ -1|0;if((I|0)==0){break}else{K=_;M=Z}}}}while(0);if(A<<16>>16==0){$=x;v=138;w=3;k=z;x=B;j=$;continue}$=x;v=D?6:7;w=D?3:4;k=z;x=B;j=$}i=h;return}function Wf(a,c,d){a=a|0;c=c|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;f=i;g=b[c+2>>1]|0;h=g<<16>>16==0;b[c+(d+1<<2)+2>>1]=-1;j=a+2752|0;k=a+2756|0;l=a+2748|0;m=h?138:7;n=h?3:4;h=0;o=g&65535;g=-1;a:while(1){p=0;q=h;do{if((q|0)>(d|0)){break a}q=q+1|0;r=b[c+(q<<2)+2>>1]|0;s=r&65535;p=p+1|0;t=(o|0)==(s|0)}while((p|0)<(m|0)&t);do{if((p|0)>=(n|0)){if((o|0)==0){if((p|0)<11){b[j>>1]=(b[j>>1]|0)+1<<16>>16;break}else{b[k>>1]=(b[k>>1]|0)+1<<16>>16;break}}else{if((o|0)!=(g|0)){u=a+(o<<2)+2684|0;b[u>>1]=(b[u>>1]|0)+1<<16>>16}b[l>>1]=(b[l>>1]|0)+1<<16>>16;break}}else{u=a+(o<<2)+2684|0;b[u>>1]=(e[u>>1]|0)+p}}while(0);if(r<<16>>16==0){v=o;m=138;n=3;h=q;o=s;g=v;continue}v=o;m=t?6:7;n=t?3:4;h=q;o=s;g=v}i=f;return}function Xf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;a=i;d=gg(aa(c,b)|0)|0;i=a;return d|0}function Yf(a,b){a=a|0;b=b|0;a=i;hg(b);i=a;return}function Zf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0;f=i;i=i+944|0;g=f+680|0;h=f+424|0;j=f+192|0;k=f;l=aa(d,b)|0;if((l|0)==0){i=f;return}b=l-d|0;c[k+4>>2]=d;c[k>>2]=d;m=d;n=d;o=2;while(1){p=m+d+n|0;c[k+(o<<2)>>2]=p;if(p>>>0>>0){q=n;n=p;o=o+1|0;m=q}else{break}}m=0-d|0;o=a+b|0;if((b|0)>0){b=(d|0)==0;n=d>>>0>256?256:d;l=(n|0)==(d|0);q=o;p=1;r=0;s=a;t=1;while(1){do{if((p&3|0)!=3){u=t+ -1|0;a:do{if((c[k+(u<<2)>>2]|0)>>>0<(q-s|0)>>>0){c[j>>2]=s;if((t|0)>1){v=t;w=s;x=s;y=1;while(1){z=w+m|0;A=v+ -2|0;B=w+(0-((c[k+(A<<2)>>2]|0)+d))|0;if((nb[e&7](x,B)|0)>-1?(nb[e&7](x,z)|0)>-1:0){C=y;break}D=y+1|0;E=j+(y<<2)|0;if((nb[e&7](B,z)|0)>-1){c[E>>2]=B;F=B;G=v+ -1|0}else{c[E>>2]=z;F=z;G=A}if((G|0)<=1){C=D;break}v=G;w=F;x=c[j>>2]|0;y=D}if((C|0)>=2?(y=j+(C<<2)|0,c[y>>2]=g,!b):0){if((C|0)>0){H=d;I=g}else{x=c[j>>2]|0;Kg(g|0,x|0,n|0)|0;if(l){break}else{J=d;K=n}while(1){J=J-K|0;K=J>>>0>256?256:J;Kg(g|0,x|0,K|0)|0;if((J|0)==(K|0)){break a}}}while(1){x=H>>>0>256?256:H;w=c[j>>2]|0;Kg(I|0,w|0,x|0)|0;v=w;w=0;while(1){D=w+1|0;A=c[j+(D<<2)>>2]|0;Kg(v|0,A|0,x|0)|0;c[j+(w<<2)>>2]=v+x;if((D|0)==(C|0)){break}else{v=A;w=D}}if((H|0)==(x|0)){break a}H=H-x|0;I=c[y>>2]|0}}}}else{_f(s,d,e,p,r,t,0,k)}}while(0);if((t|0)==1){L=p<<1;M=p>>>31|r<<1;N=0;break}else{y=u>>>0>31;w=y?0:p;v=y?t+ -33|0:u;L=w<>>(32-v|0)|(y?p:r)<>2]=s;b:do{if((t|0)>1){v=t;y=s;w=s;D=1;while(1){A=y+m|0;z=v+ -2|0;E=y+(0-((c[k+(z<<2)>>2]|0)+d))|0;if((nb[e&7](w,E)|0)>-1?(nb[e&7](w,A)|0)>-1:0){O=D;break}B=D+1|0;P=j+(D<<2)|0;if((nb[e&7](E,A)|0)>-1){c[P>>2]=E;Q=E;R=v+ -1|0}else{c[P>>2]=A;Q=A;R=z}if((R|0)<=1){O=B;break}v=R;y=Q;w=c[j>>2]|0;D=B}if((O|0)>=2?(D=j+(O<<2)|0,c[D>>2]=h,!b):0){if((O|0)>0){S=d;T=h}else{w=c[j>>2]|0;Kg(h|0,w|0,n|0)|0;if(l){break}else{U=d;V=n}while(1){U=U-V|0;V=U>>>0>256?256:U;Kg(h|0,w|0,V|0)|0;if((U|0)==(V|0)){break b}}}while(1){w=S>>>0>256?256:S;y=c[j>>2]|0;Kg(T|0,y|0,w|0)|0;v=y;y=0;while(1){B=y+1|0;z=c[j+(B<<2)>>2]|0;Kg(v|0,z|0,w|0)|0;c[j+(y<<2)>>2]=v+w;if((B|0)==(O|0)){break}else{v=z;y=B}}if((S|0)==(w|0)){break b}S=S-w|0;T=c[D>>2]|0}}}}while(0);L=p>>>2|r<<30;M=r>>>2;N=t+2|0}}while(0);u=L|1;D=s+d|0;if(D>>>0>>0){p=u;r=M;s=D;t=N}else{W=M;X=u;Y=D;Z=N;break}}}else{W=0;X=1;Y=a;Z=1}_f(Y,d,e,X,W,Z,0,k);a=X;X=W;W=Y;Y=Z;while(1){if((Y|0)==1){if((a|0)==1){if((X|0)==0){break}else{_=52}}}else{_=52}if((_|0)==52?(_=0,(Y|0)>=2):0){Z=a>>>30;N=Y+ -2|0;M=(a<<1&2147483646|Z<<31)^3;t=(Z|X<<2)>>>1;_f(W+(0-((c[k+(N<<2)>>2]|0)+d))|0,d,e,M,t,Y+ -1|0,1,k);s=t<<1|Z&1;Z=M<<1|1;M=W+m|0;_f(M,d,e,Z,s,N,1,k);a=Z;X=s;W=M;Y=N;continue}N=a+ -1|0;if((N|0)!=0){if((N&1|0)==0){M=N;N=0;do{N=N+1|0;M=M>>>1}while((M&1|0)==0);if((N|0)!=0){$=N}else{_=57}}else{_=57}if((_|0)==57){_=0;if((X|0)!=0){if((X&1|0)==0){M=X;s=0;while(1){Z=s+1|0;t=M>>>1;if((t&1|0)==0){M=t;s=Z}else{ba=Z;break}}}else{ba=0}}else{ba=32}$=(ba|0)==0?0:ba+32|0}if($>>>0>31){ca=$;_=62}else{da=$;ea=a;fa=X;ga=$}}else{ca=32;_=62}if((_|0)==62){_=0;da=ca+ -32|0;ea=X;fa=0;ga=ca}a=fa<<32-da|ea>>>da;X=fa>>>da;W=W+m|0;Y=ga+Y|0}i=f;return}function _f(a,b,d,e,f,g,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0;k=i;i=i+752|0;l=k+232|0;m=k+488|0;n=k;c[n>>2]=a;o=0-b|0;a:do{if((e|0)==1&(f|0)==0){p=a;q=g;r=h;s=1;t=18}else{u=g;v=a;w=h;x=e;y=f;z=a;A=1;while(1){B=v+(0-(c[j+(u<<2)>>2]|0))|0;if((nb[d&7](B,z)|0)<1){p=v;q=u;r=w;s=A;t=18;break a}if((w|0)==0&(u|0)>1){C=c[j+(u+ -2<<2)>>2]|0;if((nb[d&7](v+o|0,B)|0)>-1){D=v;E=u;F=A;break a}if((nb[d&7](v+(0-(C+b))|0,B)|0)>-1){D=v;E=u;F=A;break a}}C=A+1|0;c[n+(A<<2)>>2]=B;G=x+ -1|0;if((G|0)!=0){if((G&1|0)==0){H=G;G=0;do{G=G+1|0;H=H>>>1}while((H&1|0)==0);if((G|0)!=0){I=G}else{t=10}}else{t=10}if((t|0)==10){t=0;if((y|0)!=0){if((y&1|0)==0){H=y;J=0;while(1){K=J+1|0;L=H>>>1;if((L&1|0)==0){H=L;J=K}else{M=K;break}}}else{M=0}}else{M=32}I=(M|0)==0?0:M+32|0}if(I>>>0>31){N=I;t=15}else{O=I;P=x;Q=y;R=I}}else{N=32;t=15}if((t|0)==15){t=0;O=N+ -32|0;P=y;Q=0;R=N}J=Q<<32-O|P>>>O;H=Q>>>O;G=R+u|0;if((J|0)==1&(H|0)==0){D=B;E=G;F=C;break a}u=G;v=B;w=0;x=J;y=H;z=c[n>>2]|0;A=C}}}while(0);if((t|0)==18){if((r|0)==0){D=p;E=q;F=s}else{i=k;return}}b:do{if((F|0)>=2?(s=n+(F<<2)|0,c[s>>2]=l,(b|0)!=0):0){if((F|0)>0){S=b;T=l}else{q=b>>>0>256?256:b;p=c[n>>2]|0;Kg(l|0,p|0,q|0)|0;if((q|0)==(b|0)){break}else{U=b;V=q}while(1){U=U-V|0;V=U>>>0>256?256:U;Kg(l|0,p|0,V|0)|0;if((U|0)==(V|0)){break b}}}while(1){p=S>>>0>256?256:S;q=c[n>>2]|0;Kg(T|0,q|0,p|0)|0;r=q;q=0;while(1){t=q+1|0;R=c[n+(t<<2)>>2]|0;Kg(r|0,R|0,p|0)|0;c[n+(q<<2)>>2]=r+p;if((t|0)==(F|0)){break}else{r=R;q=t}}if((S|0)==(p|0)){break b}S=S-p|0;T=c[s>>2]|0}}}while(0);c[l>>2]=D;c:do{if((E|0)>1){T=E;S=D;F=D;n=1;while(1){V=S+o|0;U=T+ -2|0;s=S+(0-((c[j+(U<<2)>>2]|0)+b))|0;if((nb[d&7](F,s)|0)>-1?(nb[d&7](F,V)|0)>-1:0){W=n;break}q=n+1|0;r=l+(n<<2)|0;if((nb[d&7](s,V)|0)>-1){c[r>>2]=s;X=s;Y=T+ -1|0}else{c[r>>2]=V;X=V;Y=U}if((Y|0)<=1){W=q;break}T=Y;S=X;F=c[l>>2]|0;n=q}if((W|0)>=2?(n=l+(W<<2)|0,c[n>>2]=m,(b|0)!=0):0){if((W|0)>0){Z=b;_=m}else{F=b>>>0>256?256:b;S=c[l>>2]|0;Kg(m|0,S|0,F|0)|0;if((F|0)==(b|0)){$=m;break}else{aa=b;ba=F}while(1){F=aa-ba|0;T=F>>>0>256?256:F;Kg(m|0,S|0,T|0)|0;if((F|0)==(T|0)){$=m;break c}else{aa=F;ba=T}}}while(1){S=Z>>>0>256?256:Z;T=c[l>>2]|0;Kg(_|0,T|0,S|0)|0;F=T;T=0;while(1){q=T+1|0;U=c[l+(q<<2)>>2]|0;Kg(F|0,U|0,S|0)|0;c[l+(T<<2)>>2]=F+S;if((q|0)==(W|0)){break}else{F=U;T=q}}if((Z|0)==(S|0)){$=m;break c}Z=Z-S|0;_=c[n>>2]|0}}else{$=m}}else{$=m}}while(0);i=k;return}function $f(b,c){b=b|0;c=c|0;var d=0,e=0;d=i;e=ag(b,c)|0;i=d;return((a[e]|0)==(c&255)<<24>>24?e:0)|0}function ag(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;f=d&255;if((f|0)==0){g=b+(Dg(b|0)|0)|0;i=e;return g|0}a:do{if((b&3|0)!=0){h=d&255;j=b;while(1){k=a[j]|0;if(k<<24>>24==0){g=j;l=13;break}m=j+1|0;if(k<<24>>24==h<<24>>24){g=j;l=13;break}if((m&3|0)==0){n=m;break a}else{j=m}}if((l|0)==13){i=e;return g|0}}else{n=b}}while(0);b=aa(f,16843009)|0;f=c[n>>2]|0;b:do{if(((f&-2139062144^-2139062144)&f+ -16843009|0)==0){l=f;j=n;while(1){h=l^b;m=j+4|0;if(((h&-2139062144^-2139062144)&h+ -16843009|0)!=0){o=j;break b}h=c[m>>2]|0;if(((h&-2139062144^-2139062144)&h+ -16843009|0)==0){l=h;j=m}else{o=m;break}}}else{o=n}}while(0);n=d&255;d=o;while(1){o=a[d]|0;if(o<<24>>24==0|o<<24>>24==n<<24>>24){g=d;break}else{d=d+1|0}}i=e;return g|0}function bg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+32|0;f=e;g=a[d]|0;if(!(g<<24>>24==0)?(a[d+1|0]|0)!=0:0){c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[f+24>>2]=0;c[f+28>>2]=0;h=d;d=g;do{j=d&255;k=f+(j>>>5<<2)|0;c[k>>2]=c[k>>2]|1<<(j&31);h=h+1|0;d=a[h]|0}while(!(d<<24>>24==0));d=a[b]|0;a:do{if(d<<24>>24==0){l=b}else{h=b;j=d;while(1){k=j&255;m=h+1|0;if((c[f+(k>>>5<<2)>>2]&1<<(k&31)|0)!=0){l=h;break a}k=a[m]|0;if(k<<24>>24==0){l=m;break}else{h=m;j=k}}}}while(0);n=l-b|0;i=e;return n|0}n=(ag(b,g<<24>>24)|0)-b|0;i=e;return n|0}function cg(a){a=a|0;var b=0,c=0,d=0,e=0;b=i;c=(Dg(a|0)|0)+1|0;d=gg(c)|0;if((d|0)==0){e=0;i=b;return e|0}Kg(d|0,a|0,c|0)|0;e=d;i=b;return e|0}function dg(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;f=b+(Dg(b|0)|0)|0;a:do{if((d|0)==0){g=f}else{h=d;j=c;k=f;while(1){l=a[j]|0;if(l<<24>>24==0){g=k;break a}m=h+ -1|0;n=k+1|0;a[k]=l;if((m|0)==0){g=n;break}else{h=m;j=j+1|0;k=n}}}}while(0);a[g]=0;i=e;return b|0}function eg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e;c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[f+24>>2]=0;c[f+28>>2]=0;g=a[d]|0;if(g<<24>>24==0){h=0;i=e;return h|0}if((a[d+1|0]|0)==0){j=b;while(1){if((a[j]|0)==g<<24>>24){j=j+1|0}else{break}}h=j-b|0;i=e;return h|0}else{k=d;l=g}do{g=l&255;d=f+(g>>>5<<2)|0;c[d>>2]=c[d>>2]|1<<(g&31);k=k+1|0;l=a[k]|0}while(!(l<<24>>24==0));l=a[b]|0;a:do{if(l<<24>>24==0){m=b}else{k=b;g=l;while(1){d=g&255;j=k+1|0;if((c[f+(d>>>5<<2)>>2]&1<<(d&31)|0)==0){m=k;break a}d=a[j]|0;if(d<<24>>24==0){m=j;break}else{k=j;g=d}}}}while(0);h=m-b|0;i=e;return h|0}function fg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;e=i;if((b|0)==0){f=c[6912]|0;if((f|0)==0){g=0;i=e;return g|0}else{h=f}}else{h=b}b=eg(h,d)|0;f=h+b|0;if((a[f]|0)==0){c[6912]=0;g=0;i=e;return g|0}j=(bg(f,d)|0)+b|0;b=h+j|0;c[6912]=b;if((a[b]|0)==0){c[6912]=0;g=f;i=e;return g|0}else{c[6912]=h+(j+1);a[b]=0;g=f;i=e;return g|0}return 0} + + + +function gg(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ja=0,Ka=0,La=0,Ma=0;b=i;do{if(a>>>0<245){if(a>>>0<11){d=16}else{d=a+11&-8}e=d>>>3;f=c[6914]|0;g=f>>>e;if((g&3|0)!=0){h=(g&1^1)+e|0;j=h<<1;k=27696+(j<<2)|0;l=27696+(j+2<<2)|0;j=c[l>>2]|0;m=j+8|0;n=c[m>>2]|0;do{if((k|0)!=(n|0)){if(n>>>0<(c[27672>>2]|0)>>>0){_a()}o=n+12|0;if((c[o>>2]|0)==(j|0)){c[o>>2]=k;c[l>>2]=n;break}else{_a()}}else{c[6914]=f&~(1<>2]=n|3;l=j+(n|4)|0;c[l>>2]=c[l>>2]|1;p=m;i=b;return p|0}if(d>>>0>(c[27664>>2]|0)>>>0){if((g|0)!=0){l=2<>>12&16;k=l>>>n;l=k>>>5&8;o=k>>>l;k=o>>>2&4;q=o>>>k;o=q>>>1&2;r=q>>>o;q=r>>>1&1;s=(l|n|k|o|q)+(r>>>q)|0;q=s<<1;r=27696+(q<<2)|0;o=27696+(q+2<<2)|0;q=c[o>>2]|0;k=q+8|0;n=c[k>>2]|0;do{if((r|0)!=(n|0)){if(n>>>0<(c[27672>>2]|0)>>>0){_a()}l=n+12|0;if((c[l>>2]|0)==(q|0)){c[l>>2]=r;c[o>>2]=n;break}else{_a()}}else{c[6914]=f&~(1<>2]=d|3;o=q+d|0;c[q+(d|4)>>2]=n|1;c[q+f>>2]=n;f=c[27664>>2]|0;if((f|0)!=0){r=c[27676>>2]|0;e=f>>>3;f=e<<1;g=27696+(f<<2)|0;m=c[6914]|0;j=1<>2]|0;if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{t=e;u=h}}else{c[6914]=m|j;t=27696+(f+2<<2)|0;u=g}c[t>>2]=r;c[u+12>>2]=r;c[r+8>>2]=u;c[r+12>>2]=g}c[27664>>2]=n;c[27676>>2]=o;p=k;i=b;return p|0}o=c[27660>>2]|0;if((o|0)!=0){n=(o&0-o)+ -1|0;o=n>>>12&16;g=n>>>o;n=g>>>5&8;r=g>>>n;g=r>>>2&4;f=r>>>g;r=f>>>1&2;j=f>>>r;f=j>>>1&1;m=c[27960+((n|o|g|r|f)+(j>>>f)<<2)>>2]|0;f=(c[m+4>>2]&-8)-d|0;j=m;r=m;while(1){m=c[j+16>>2]|0;if((m|0)==0){g=c[j+20>>2]|0;if((g|0)==0){break}else{v=g}}else{v=m}m=(c[v+4>>2]&-8)-d|0;g=m>>>0>>0;f=g?m:f;j=v;r=g?v:r}j=c[27672>>2]|0;if(r>>>0>>0){_a()}k=r+d|0;if(!(r>>>0>>0)){_a()}q=c[r+24>>2]|0;s=c[r+12>>2]|0;do{if((s|0)==(r|0)){g=r+20|0;m=c[g>>2]|0;if((m|0)==0){o=r+16|0;n=c[o>>2]|0;if((n|0)==0){w=0;break}else{x=n;y=o}}else{x=m;y=g}while(1){g=x+20|0;m=c[g>>2]|0;if((m|0)!=0){x=m;y=g;continue}g=x+16|0;m=c[g>>2]|0;if((m|0)==0){break}else{x=m;y=g}}if(y>>>0>>0){_a()}else{c[y>>2]=0;w=x;break}}else{g=c[r+8>>2]|0;if(g>>>0>>0){_a()}m=g+12|0;if((c[m>>2]|0)!=(r|0)){_a()}o=s+8|0;if((c[o>>2]|0)==(r|0)){c[m>>2]=s;c[o>>2]=g;w=s;break}else{_a()}}}while(0);do{if((q|0)!=0){s=c[r+28>>2]|0;j=27960+(s<<2)|0;if((r|0)==(c[j>>2]|0)){c[j>>2]=w;if((w|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}s=q+16|0;if((c[s>>2]|0)==(r|0)){c[s>>2]=w}else{c[q+20>>2]=w}if((w|0)==0){break}}if(w>>>0<(c[27672>>2]|0)>>>0){_a()}c[w+24>>2]=q;s=c[r+16>>2]|0;do{if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+16>>2]=s;c[s+24>>2]=w;break}}}while(0);s=c[r+20>>2]|0;if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+20>>2]=s;c[s+24>>2]=w;break}}}}while(0);if(f>>>0<16){q=f+d|0;c[r+4>>2]=q|3;s=r+(q+4)|0;c[s>>2]=c[s>>2]|1}else{c[r+4>>2]=d|3;c[r+(d|4)>>2]=f|1;c[r+(f+d)>>2]=f;s=c[27664>>2]|0;if((s|0)!=0){q=c[27676>>2]|0;j=s>>>3;s=j<<1;g=27696+(s<<2)|0;o=c[6914]|0;m=1<>2]|0;if(n>>>0<(c[27672>>2]|0)>>>0){_a()}else{z=j;A=n}}else{c[6914]=o|m;z=27696+(s+2<<2)|0;A=g}c[z>>2]=q;c[A+12>>2]=q;c[q+8>>2]=A;c[q+12>>2]=g}c[27664>>2]=f;c[27676>>2]=k}p=r+8|0;i=b;return p|0}else{B=d}}else{B=d}}else{if(!(a>>>0>4294967231)){g=a+11|0;q=g&-8;s=c[27660>>2]|0;if((s|0)!=0){m=0-q|0;o=g>>>8;if((o|0)!=0){if(q>>>0>16777215){C=31}else{g=(o+1048320|0)>>>16&8;n=o<>>16&4;j=n<>>16&2;h=14-(o|g|n)+(j<>>15)|0;C=q>>>(h+7|0)&1|h<<1}}else{C=0}h=c[27960+(C<<2)>>2]|0;a:do{if((h|0)==0){D=m;E=0;F=0}else{if((C|0)==31){G=0}else{G=25-(C>>>1)|0}n=m;j=0;g=q<>2]&-8;H=l-q|0;if(H>>>0>>0){if((l|0)==(q|0)){D=H;E=o;F=o;break a}else{I=H;J=o}}else{I=n;J=e}H=c[o+20>>2]|0;l=c[o+(g>>>31<<2)+16>>2]|0;K=(H|0)==0|(H|0)==(l|0)?j:H;if((l|0)==0){D=I;E=K;F=J;break}else{n=I;j=K;g=g<<1;o=l;e=J}}}}while(0);if((E|0)==0&(F|0)==0){h=2<>>12&16;r=h>>>m;h=r>>>5&8;k=r>>>h;r=k>>>2&4;f=k>>>r;k=f>>>1&2;e=f>>>k;f=e>>>1&1;L=c[27960+((h|m|r|k|f)+(e>>>f)<<2)>>2]|0}else{L=E}if((L|0)==0){M=D;N=F}else{f=D;e=L;k=F;while(1){r=(c[e+4>>2]&-8)-q|0;m=r>>>0>>0;h=m?r:f;r=m?e:k;m=c[e+16>>2]|0;if((m|0)!=0){f=h;e=m;k=r;continue}m=c[e+20>>2]|0;if((m|0)==0){M=h;N=r;break}else{f=h;e=m;k=r}}}if((N|0)!=0?M>>>0<((c[27664>>2]|0)-q|0)>>>0:0){k=c[27672>>2]|0;if(N>>>0>>0){_a()}e=N+q|0;if(!(N>>>0>>0)){_a()}f=c[N+24>>2]|0;s=c[N+12>>2]|0;do{if((s|0)==(N|0)){r=N+20|0;m=c[r>>2]|0;if((m|0)==0){h=N+16|0;o=c[h>>2]|0;if((o|0)==0){O=0;break}else{P=o;Q=h}}else{P=m;Q=r}while(1){r=P+20|0;m=c[r>>2]|0;if((m|0)!=0){P=m;Q=r;continue}r=P+16|0;m=c[r>>2]|0;if((m|0)==0){break}else{P=m;Q=r}}if(Q>>>0>>0){_a()}else{c[Q>>2]=0;O=P;break}}else{r=c[N+8>>2]|0;if(r>>>0>>0){_a()}m=r+12|0;if((c[m>>2]|0)!=(N|0)){_a()}h=s+8|0;if((c[h>>2]|0)==(N|0)){c[m>>2]=s;c[h>>2]=r;O=s;break}else{_a()}}}while(0);do{if((f|0)!=0){s=c[N+28>>2]|0;k=27960+(s<<2)|0;if((N|0)==(c[k>>2]|0)){c[k>>2]=O;if((O|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}s=f+16|0;if((c[s>>2]|0)==(N|0)){c[s>>2]=O}else{c[f+20>>2]=O}if((O|0)==0){break}}if(O>>>0<(c[27672>>2]|0)>>>0){_a()}c[O+24>>2]=f;s=c[N+16>>2]|0;do{if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[O+16>>2]=s;c[s+24>>2]=O;break}}}while(0);s=c[N+20>>2]|0;if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[O+20>>2]=s;c[s+24>>2]=O;break}}}}while(0);b:do{if(!(M>>>0<16)){c[N+4>>2]=q|3;c[N+(q|4)>>2]=M|1;c[N+(M+q)>>2]=M;f=M>>>3;if(M>>>0<256){s=f<<1;k=27696+(s<<2)|0;r=c[6914]|0;h=1<>2]|0;if(m>>>0<(c[27672>>2]|0)>>>0){_a()}else{R=f;S=m}}else{c[6914]=r|h;R=27696+(s+2<<2)|0;S=k}c[R>>2]=e;c[S+12>>2]=e;c[N+(q+8)>>2]=S;c[N+(q+12)>>2]=k;break}k=M>>>8;if((k|0)!=0){if(M>>>0>16777215){T=31}else{s=(k+1048320|0)>>>16&8;h=k<>>16&4;r=h<>>16&2;m=14-(k|s|h)+(r<>>15)|0;T=M>>>(m+7|0)&1|m<<1}}else{T=0}m=27960+(T<<2)|0;c[N+(q+28)>>2]=T;c[N+(q+20)>>2]=0;c[N+(q+16)>>2]=0;h=c[27660>>2]|0;r=1<>2]=h|r;c[m>>2]=e;c[N+(q+24)>>2]=m;c[N+(q+12)>>2]=e;c[N+(q+8)>>2]=e;break}r=c[m>>2]|0;if((T|0)==31){U=0}else{U=25-(T>>>1)|0}c:do{if((c[r+4>>2]&-8|0)!=(M|0)){m=M<>>31<<2)+16|0;s=c[V>>2]|0;if((s|0)==0){break}if((c[s+4>>2]&-8|0)==(M|0)){W=s;break c}else{m=m<<1;h=s}}if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[V>>2]=e;c[N+(q+24)>>2]=h;c[N+(q+12)>>2]=e;c[N+(q+8)>>2]=e;break b}}else{W=r}}while(0);r=W+8|0;m=c[r>>2]|0;s=c[27672>>2]|0;if(W>>>0>>0){_a()}if(m>>>0>>0){_a()}else{c[m+12>>2]=e;c[r>>2]=e;c[N+(q+8)>>2]=m;c[N+(q+12)>>2]=W;c[N+(q+24)>>2]=0;break}}else{m=M+q|0;c[N+4>>2]=m|3;r=N+(m+4)|0;c[r>>2]=c[r>>2]|1}}while(0);p=N+8|0;i=b;return p|0}else{B=q}}else{B=q}}else{B=-1}}}while(0);N=c[27664>>2]|0;if(!(B>>>0>N>>>0)){M=N-B|0;W=c[27676>>2]|0;if(M>>>0>15){c[27676>>2]=W+B;c[27664>>2]=M;c[W+(B+4)>>2]=M|1;c[W+N>>2]=M;c[W+4>>2]=B|3}else{c[27664>>2]=0;c[27676>>2]=0;c[W+4>>2]=N|3;M=W+(N+4)|0;c[M>>2]=c[M>>2]|1}p=W+8|0;i=b;return p|0}W=c[27668>>2]|0;if(B>>>0>>0){M=W-B|0;c[27668>>2]=M;W=c[27680>>2]|0;c[27680>>2]=W+B;c[W+(B+4)>>2]=M|1;c[W+4>>2]=B|3;p=W+8|0;i=b;return p|0}do{if((c[7032]|0)==0){W=Ia(30)|0;if((W+ -1&W|0)==0){c[28136>>2]=W;c[28132>>2]=W;c[28140>>2]=-1;c[28144>>2]=-1;c[28148>>2]=0;c[28100>>2]=0;c[7032]=(bb(0)|0)&-16^1431655768;break}else{_a()}}}while(0);W=B+48|0;M=c[28136>>2]|0;N=B+47|0;V=M+N|0;U=0-M|0;M=V&U;if(!(M>>>0>B>>>0)){p=0;i=b;return p|0}T=c[28096>>2]|0;if((T|0)!=0?(S=c[28088>>2]|0,R=S+M|0,R>>>0<=S>>>0|R>>>0>T>>>0):0){p=0;i=b;return p|0}d:do{if((c[28100>>2]&4|0)==0){T=c[27680>>2]|0;e:do{if((T|0)!=0){R=28104|0;while(1){S=c[R>>2]|0;if(!(S>>>0>T>>>0)?(X=R+4|0,(S+(c[X>>2]|0)|0)>>>0>T>>>0):0){break}S=c[R+8>>2]|0;if((S|0)==0){Y=182;break e}else{R=S}}if((R|0)!=0){S=V-(c[27668>>2]|0)&U;if(S>>>0<2147483647){O=Ca(S|0)|0;P=(O|0)==((c[R>>2]|0)+(c[X>>2]|0)|0);Z=O;_=S;$=P?O:-1;aa=P?S:0;Y=191}else{ba=0}}else{Y=182}}else{Y=182}}while(0);do{if((Y|0)==182){T=Ca(0)|0;if((T|0)!=(-1|0)){q=T;S=c[28132>>2]|0;P=S+ -1|0;if((P&q|0)==0){ca=M}else{ca=M-q+(P+q&0-S)|0}S=c[28088>>2]|0;q=S+ca|0;if(ca>>>0>B>>>0&ca>>>0<2147483647){P=c[28096>>2]|0;if((P|0)!=0?q>>>0<=S>>>0|q>>>0>P>>>0:0){ba=0;break}P=Ca(ca|0)|0;q=(P|0)==(T|0);Z=P;_=ca;$=q?T:-1;aa=q?ca:0;Y=191}else{ba=0}}else{ba=0}}}while(0);f:do{if((Y|0)==191){q=0-_|0;if(($|0)!=(-1|0)){da=$;ea=aa;Y=202;break d}do{if((Z|0)!=(-1|0)&_>>>0<2147483647&_>>>0>>0?(T=c[28136>>2]|0,P=N-_+T&0-T,P>>>0<2147483647):0){if((Ca(P|0)|0)==(-1|0)){Ca(q|0)|0;ba=aa;break f}else{fa=P+_|0;break}}else{fa=_}}while(0);if((Z|0)==(-1|0)){ba=aa}else{da=Z;ea=fa;Y=202;break d}}}while(0);c[28100>>2]=c[28100>>2]|4;ga=ba;Y=199}else{ga=0;Y=199}}while(0);if((((Y|0)==199?M>>>0<2147483647:0)?(ba=Ca(M|0)|0,M=Ca(0)|0,(M|0)!=(-1|0)&(ba|0)!=(-1|0)&ba>>>0>>0):0)?(fa=M-ba|0,M=fa>>>0>(B+40|0)>>>0,M):0){da=ba;ea=M?fa:ga;Y=202}if((Y|0)==202){ga=(c[28088>>2]|0)+ea|0;c[28088>>2]=ga;if(ga>>>0>(c[28092>>2]|0)>>>0){c[28092>>2]=ga}ga=c[27680>>2]|0;g:do{if((ga|0)!=0){fa=28104|0;while(1){ha=c[fa>>2]|0;ia=fa+4|0;ja=c[ia>>2]|0;if((da|0)==(ha+ja|0)){Y=214;break}M=c[fa+8>>2]|0;if((M|0)==0){break}else{fa=M}}if(((Y|0)==214?(c[fa+12>>2]&8|0)==0:0)?ga>>>0>=ha>>>0&ga>>>0>>0:0){c[ia>>2]=ja+ea;M=(c[27668>>2]|0)+ea|0;ba=ga+8|0;if((ba&7|0)==0){ka=0}else{ka=0-ba&7}ba=M-ka|0;c[27680>>2]=ga+ka;c[27668>>2]=ba;c[ga+(ka+4)>>2]=ba|1;c[ga+(M+4)>>2]=40;c[27684>>2]=c[28144>>2];break}if(da>>>0<(c[27672>>2]|0)>>>0){c[27672>>2]=da}M=da+ea|0;ba=28104|0;while(1){if((c[ba>>2]|0)==(M|0)){Y=224;break}Z=c[ba+8>>2]|0;if((Z|0)==0){break}else{ba=Z}}if((Y|0)==224?(c[ba+12>>2]&8|0)==0:0){c[ba>>2]=da;M=ba+4|0;c[M>>2]=(c[M>>2]|0)+ea;M=da+8|0;if((M&7|0)==0){la=0}else{la=0-M&7}M=da+(ea+8)|0;if((M&7|0)==0){ma=0}else{ma=0-M&7}M=da+(ma+ea)|0;fa=la+B|0;Z=da+fa|0;aa=M-(da+la)-B|0;c[da+(la+4)>>2]=B|3;h:do{if((M|0)!=(c[27680>>2]|0)){if((M|0)==(c[27676>>2]|0)){_=(c[27664>>2]|0)+aa|0;c[27664>>2]=_;c[27676>>2]=Z;c[da+(fa+4)>>2]=_|1;c[da+(_+fa)>>2]=_;break}_=ea+4|0;N=c[da+(_+ma)>>2]|0;if((N&3|0)==1){W=N&-8;$=N>>>3;do{if(!(N>>>0<256)){ca=c[da+((ma|24)+ea)>>2]|0;X=c[da+(ea+12+ma)>>2]|0;do{if((X|0)==(M|0)){U=ma|16;V=da+(_+U)|0;q=c[V>>2]|0;if((q|0)==0){R=da+(U+ea)|0;U=c[R>>2]|0;if((U|0)==0){na=0;break}else{oa=U;pa=R}}else{oa=q;pa=V}while(1){V=oa+20|0;q=c[V>>2]|0;if((q|0)!=0){oa=q;pa=V;continue}V=oa+16|0;q=c[V>>2]|0;if((q|0)==0){break}else{oa=q;pa=V}}if(pa>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[pa>>2]=0;na=oa;break}}else{V=c[da+((ma|8)+ea)>>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}q=V+12|0;if((c[q>>2]|0)!=(M|0)){_a()}R=X+8|0;if((c[R>>2]|0)==(M|0)){c[q>>2]=X;c[R>>2]=V;na=X;break}else{_a()}}}while(0);if((ca|0)!=0){X=c[da+(ea+28+ma)>>2]|0;h=27960+(X<<2)|0;if((M|0)==(c[h>>2]|0)){c[h>>2]=na;if((na|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}X=ca+16|0;if((c[X>>2]|0)==(M|0)){c[X>>2]=na}else{c[ca+20>>2]=na}if((na|0)==0){break}}if(na>>>0<(c[27672>>2]|0)>>>0){_a()}c[na+24>>2]=ca;X=ma|16;h=c[da+(X+ea)>>2]|0;do{if((h|0)!=0){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[na+16>>2]=h;c[h+24>>2]=na;break}}}while(0);h=c[da+(_+X)>>2]|0;if((h|0)!=0){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[na+20>>2]=h;c[h+24>>2]=na;break}}}}else{h=c[da+((ma|8)+ea)>>2]|0;ca=c[da+(ea+12+ma)>>2]|0;V=27696+($<<1<<2)|0;if((h|0)!=(V|0)){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}if((c[h+12>>2]|0)!=(M|0)){_a()}}if((ca|0)==(h|0)){c[6914]=c[6914]&~(1<<$);break}if((ca|0)!=(V|0)){if(ca>>>0<(c[27672>>2]|0)>>>0){_a()}V=ca+8|0;if((c[V>>2]|0)==(M|0)){qa=V}else{_a()}}else{qa=ca+8|0}c[h+12>>2]=ca;c[qa>>2]=h}}while(0);ra=da+((W|ma)+ea)|0;sa=W+aa|0}else{ra=M;sa=aa}$=ra+4|0;c[$>>2]=c[$>>2]&-2;c[da+(fa+4)>>2]=sa|1;c[da+(sa+fa)>>2]=sa;$=sa>>>3;if(sa>>>0<256){_=$<<1;N=27696+(_<<2)|0;h=c[6914]|0;ca=1<<$;if((h&ca|0)!=0){$=27696+(_+2<<2)|0;V=c[$>>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{ta=$;ua=V}}else{c[6914]=h|ca;ta=27696+(_+2<<2)|0;ua=N}c[ta>>2]=Z;c[ua+12>>2]=Z;c[da+(fa+8)>>2]=ua;c[da+(fa+12)>>2]=N;break}N=sa>>>8;if((N|0)!=0){if(sa>>>0>16777215){va=31}else{_=(N+1048320|0)>>>16&8;ca=N<<_;N=(ca+520192|0)>>>16&4;h=ca<>>16&2;V=14-(N|_|ca)+(h<>>15)|0;va=sa>>>(V+7|0)&1|V<<1}}else{va=0}V=27960+(va<<2)|0;c[da+(fa+28)>>2]=va;c[da+(fa+20)>>2]=0;c[da+(fa+16)>>2]=0;ca=c[27660>>2]|0;h=1<>2]=ca|h;c[V>>2]=Z;c[da+(fa+24)>>2]=V;c[da+(fa+12)>>2]=Z;c[da+(fa+8)>>2]=Z;break}h=c[V>>2]|0;if((va|0)==31){wa=0}else{wa=25-(va>>>1)|0}i:do{if((c[h+4>>2]&-8|0)!=(sa|0)){V=sa<>>31<<2)+16|0;_=c[xa>>2]|0;if((_|0)==0){break}if((c[_+4>>2]&-8|0)==(sa|0)){ya=_;break i}else{V=V<<1;ca=_}}if(xa>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[xa>>2]=Z;c[da+(fa+24)>>2]=ca;c[da+(fa+12)>>2]=Z;c[da+(fa+8)>>2]=Z;break h}}else{ya=h}}while(0);h=ya+8|0;W=c[h>>2]|0;V=c[27672>>2]|0;if(ya>>>0>>0){_a()}if(W>>>0>>0){_a()}else{c[W+12>>2]=Z;c[h>>2]=Z;c[da+(fa+8)>>2]=W;c[da+(fa+12)>>2]=ya;c[da+(fa+24)>>2]=0;break}}else{W=(c[27668>>2]|0)+aa|0;c[27668>>2]=W;c[27680>>2]=Z;c[da+(fa+4)>>2]=W|1}}while(0);p=da+(la|8)|0;i=b;return p|0}fa=28104|0;while(1){za=c[fa>>2]|0;if(!(za>>>0>ga>>>0)?(Aa=c[fa+4>>2]|0,Ba=za+Aa|0,Ba>>>0>ga>>>0):0){break}fa=c[fa+8>>2]|0}fa=za+(Aa+ -39)|0;if((fa&7|0)==0){Da=0}else{Da=0-fa&7}fa=za+(Aa+ -47+Da)|0;Z=fa>>>0<(ga+16|0)>>>0?ga:fa;fa=Z+8|0;aa=da+8|0;if((aa&7|0)==0){Ea=0}else{Ea=0-aa&7}aa=ea+ -40-Ea|0;c[27680>>2]=da+Ea;c[27668>>2]=aa;c[da+(Ea+4)>>2]=aa|1;c[da+(ea+ -36)>>2]=40;c[27684>>2]=c[28144>>2];c[Z+4>>2]=27;c[fa+0>>2]=c[28104>>2];c[fa+4>>2]=c[28108>>2];c[fa+8>>2]=c[28112>>2];c[fa+12>>2]=c[28116>>2];c[28104>>2]=da;c[28108>>2]=ea;c[28116>>2]=0;c[28112>>2]=fa;fa=Z+28|0;c[fa>>2]=7;if((Z+32|0)>>>0>>0){aa=fa;while(1){fa=aa+4|0;c[fa>>2]=7;if((aa+8|0)>>>0>>0){aa=fa}else{break}}}if((Z|0)!=(ga|0)){aa=Z-ga|0;fa=ga+(aa+4)|0;c[fa>>2]=c[fa>>2]&-2;c[ga+4>>2]=aa|1;c[ga+aa>>2]=aa;fa=aa>>>3;if(aa>>>0<256){M=fa<<1;ba=27696+(M<<2)|0;W=c[6914]|0;h=1<>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{Fa=fa;Ga=V}}else{c[6914]=W|h;Fa=27696+(M+2<<2)|0;Ga=ba}c[Fa>>2]=ga;c[Ga+12>>2]=ga;c[ga+8>>2]=Ga;c[ga+12>>2]=ba;break}ba=aa>>>8;if((ba|0)!=0){if(aa>>>0>16777215){Ha=31}else{M=(ba+1048320|0)>>>16&8;h=ba<>>16&4;W=h<>>16&2;V=14-(ba|M|h)+(W<>>15)|0;Ha=aa>>>(V+7|0)&1|V<<1}}else{Ha=0}V=27960+(Ha<<2)|0;c[ga+28>>2]=Ha;c[ga+20>>2]=0;c[ga+16>>2]=0;h=c[27660>>2]|0;W=1<>2]=h|W;c[V>>2]=ga;c[ga+24>>2]=V;c[ga+12>>2]=ga;c[ga+8>>2]=ga;break}W=c[V>>2]|0;if((Ha|0)==31){Ja=0}else{Ja=25-(Ha>>>1)|0}j:do{if((c[W+4>>2]&-8|0)!=(aa|0)){V=aa<>>31<<2)+16|0;M=c[Ka>>2]|0;if((M|0)==0){break}if((c[M+4>>2]&-8|0)==(aa|0)){La=M;break j}else{V=V<<1;h=M}}if(Ka>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[Ka>>2]=ga;c[ga+24>>2]=h;c[ga+12>>2]=ga;c[ga+8>>2]=ga;break g}}else{La=W}}while(0);W=La+8|0;aa=c[W>>2]|0;Z=c[27672>>2]|0;if(La>>>0>>0){_a()}if(aa>>>0>>0){_a()}else{c[aa+12>>2]=ga;c[W>>2]=ga;c[ga+8>>2]=aa;c[ga+12>>2]=La;c[ga+24>>2]=0;break}}}else{aa=c[27672>>2]|0;if((aa|0)==0|da>>>0>>0){c[27672>>2]=da}c[28104>>2]=da;c[28108>>2]=ea;c[28116>>2]=0;c[27692>>2]=c[7032];c[27688>>2]=-1;aa=0;do{W=aa<<1;Z=27696+(W<<2)|0;c[27696+(W+3<<2)>>2]=Z;c[27696+(W+2<<2)>>2]=Z;aa=aa+1|0}while((aa|0)!=32);aa=da+8|0;if((aa&7|0)==0){Ma=0}else{Ma=0-aa&7}aa=ea+ -40-Ma|0;c[27680>>2]=da+Ma;c[27668>>2]=aa;c[da+(Ma+4)>>2]=aa|1;c[da+(ea+ -36)>>2]=40;c[27684>>2]=c[28144>>2]}}while(0);ea=c[27668>>2]|0;if(ea>>>0>B>>>0){da=ea-B|0;c[27668>>2]=da;ea=c[27680>>2]|0;c[27680>>2]=ea+B;c[ea+(B+4)>>2]=da|1;c[ea+4>>2]=B|3;p=ea+8|0;i=b;return p|0}}c[(Sa()|0)>>2]=12;p=0;i=b;return p|0}function hg(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0;b=i;if((a|0)==0){i=b;return}d=a+ -8|0;e=c[27672>>2]|0;if(d>>>0>>0){_a()}f=c[a+ -4>>2]|0;g=f&3;if((g|0)==1){_a()}h=f&-8;j=a+(h+ -8)|0;do{if((f&1|0)==0){k=c[d>>2]|0;if((g|0)==0){i=b;return}l=-8-k|0;m=a+l|0;n=k+h|0;if(m>>>0>>0){_a()}if((m|0)==(c[27676>>2]|0)){o=a+(h+ -4)|0;if((c[o>>2]&3|0)!=3){p=m;q=n;break}c[27664>>2]=n;c[o>>2]=c[o>>2]&-2;c[a+(l+4)>>2]=n|1;c[j>>2]=n;i=b;return}o=k>>>3;if(k>>>0<256){k=c[a+(l+8)>>2]|0;r=c[a+(l+12)>>2]|0;s=27696+(o<<1<<2)|0;if((k|0)!=(s|0)){if(k>>>0>>0){_a()}if((c[k+12>>2]|0)!=(m|0)){_a()}}if((r|0)==(k|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}s=r+8|0;if((c[s>>2]|0)==(m|0)){t=s}else{_a()}}else{t=r+8|0}c[k+12>>2]=r;c[t>>2]=k;p=m;q=n;break}k=c[a+(l+24)>>2]|0;r=c[a+(l+12)>>2]|0;do{if((r|0)==(m|0)){s=a+(l+20)|0;o=c[s>>2]|0;if((o|0)==0){u=a+(l+16)|0;v=c[u>>2]|0;if((v|0)==0){w=0;break}else{x=v;y=u}}else{x=o;y=s}while(1){s=x+20|0;o=c[s>>2]|0;if((o|0)!=0){x=o;y=s;continue}s=x+16|0;o=c[s>>2]|0;if((o|0)==0){break}else{x=o;y=s}}if(y>>>0>>0){_a()}else{c[y>>2]=0;w=x;break}}else{s=c[a+(l+8)>>2]|0;if(s>>>0>>0){_a()}o=s+12|0;if((c[o>>2]|0)!=(m|0)){_a()}u=r+8|0;if((c[u>>2]|0)==(m|0)){c[o>>2]=r;c[u>>2]=s;w=r;break}else{_a()}}}while(0);if((k|0)!=0){r=c[a+(l+28)>>2]|0;s=27960+(r<<2)|0;if((m|0)==(c[s>>2]|0)){c[s>>2]=w;if((w|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}r=k+16|0;if((c[r>>2]|0)==(m|0)){c[r>>2]=w}else{c[k+20>>2]=w}if((w|0)==0){p=m;q=n;break}}if(w>>>0<(c[27672>>2]|0)>>>0){_a()}c[w+24>>2]=k;r=c[a+(l+16)>>2]|0;do{if((r|0)!=0){if(r>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+16>>2]=r;c[r+24>>2]=w;break}}}while(0);r=c[a+(l+20)>>2]|0;if((r|0)!=0){if(r>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+20>>2]=r;c[r+24>>2]=w;p=m;q=n;break}}else{p=m;q=n}}else{p=m;q=n}}else{p=d;q=h}}while(0);if(!(p>>>0>>0)){_a()}d=a+(h+ -4)|0;w=c[d>>2]|0;if((w&1|0)==0){_a()}if((w&2|0)==0){if((j|0)==(c[27680>>2]|0)){e=(c[27668>>2]|0)+q|0;c[27668>>2]=e;c[27680>>2]=p;c[p+4>>2]=e|1;if((p|0)!=(c[27676>>2]|0)){i=b;return}c[27676>>2]=0;c[27664>>2]=0;i=b;return}if((j|0)==(c[27676>>2]|0)){e=(c[27664>>2]|0)+q|0;c[27664>>2]=e;c[27676>>2]=p;c[p+4>>2]=e|1;c[p+e>>2]=e;i=b;return}e=(w&-8)+q|0;x=w>>>3;do{if(!(w>>>0<256)){y=c[a+(h+16)>>2]|0;t=c[a+(h|4)>>2]|0;do{if((t|0)==(j|0)){g=a+(h+12)|0;f=c[g>>2]|0;if((f|0)==0){r=a+(h+8)|0;k=c[r>>2]|0;if((k|0)==0){z=0;break}else{A=k;B=r}}else{A=f;B=g}while(1){g=A+20|0;f=c[g>>2]|0;if((f|0)!=0){A=f;B=g;continue}g=A+16|0;f=c[g>>2]|0;if((f|0)==0){break}else{A=f;B=g}}if(B>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[B>>2]=0;z=A;break}}else{g=c[a+h>>2]|0;if(g>>>0<(c[27672>>2]|0)>>>0){_a()}f=g+12|0;if((c[f>>2]|0)!=(j|0)){_a()}r=t+8|0;if((c[r>>2]|0)==(j|0)){c[f>>2]=t;c[r>>2]=g;z=t;break}else{_a()}}}while(0);if((y|0)!=0){t=c[a+(h+20)>>2]|0;n=27960+(t<<2)|0;if((j|0)==(c[n>>2]|0)){c[n>>2]=z;if((z|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}t=y+16|0;if((c[t>>2]|0)==(j|0)){c[t>>2]=z}else{c[y+20>>2]=z}if((z|0)==0){break}}if(z>>>0<(c[27672>>2]|0)>>>0){_a()}c[z+24>>2]=y;t=c[a+(h+8)>>2]|0;do{if((t|0)!=0){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[z+16>>2]=t;c[t+24>>2]=z;break}}}while(0);t=c[a+(h+12)>>2]|0;if((t|0)!=0){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[z+20>>2]=t;c[t+24>>2]=z;break}}}}else{t=c[a+h>>2]|0;y=c[a+(h|4)>>2]|0;n=27696+(x<<1<<2)|0;if((t|0)!=(n|0)){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}if((c[t+12>>2]|0)!=(j|0)){_a()}}if((y|0)==(t|0)){c[6914]=c[6914]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}n=y+8|0;if((c[n>>2]|0)==(j|0)){C=n}else{_a()}}else{C=y+8|0}c[t+12>>2]=y;c[C>>2]=t}}while(0);c[p+4>>2]=e|1;c[p+e>>2]=e;if((p|0)==(c[27676>>2]|0)){c[27664>>2]=e;i=b;return}else{D=e}}else{c[d>>2]=w&-2;c[p+4>>2]=q|1;c[p+q>>2]=q;D=q}q=D>>>3;if(D>>>0<256){w=q<<1;d=27696+(w<<2)|0;e=c[6914]|0;C=1<>2]|0;if(j>>>0<(c[27672>>2]|0)>>>0){_a()}else{E=q;F=j}}else{c[6914]=e|C;E=27696+(w+2<<2)|0;F=d}c[E>>2]=p;c[F+12>>2]=p;c[p+8>>2]=F;c[p+12>>2]=d;i=b;return}d=D>>>8;if((d|0)!=0){if(D>>>0>16777215){G=31}else{F=(d+1048320|0)>>>16&8;E=d<>>16&4;w=E<>>16&2;C=14-(d|F|E)+(w<>>15)|0;G=D>>>(C+7|0)&1|C<<1}}else{G=0}C=27960+(G<<2)|0;c[p+28>>2]=G;c[p+20>>2]=0;c[p+16>>2]=0;E=c[27660>>2]|0;w=1<>2]|0;if((G|0)==31){H=0}else{H=25-(G>>>1)|0}b:do{if((c[F+4>>2]&-8|0)!=(D|0)){d=D<>>31<<2)+16|0;j=c[I>>2]|0;if((j|0)==0){break}if((c[j+4>>2]&-8|0)==(D|0)){J=j;break b}else{d=d<<1;e=j}}if(I>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[I>>2]=p;c[p+24>>2]=e;c[p+12>>2]=p;c[p+8>>2]=p;break a}}else{J=F}}while(0);F=J+8|0;d=c[F>>2]|0;j=c[27672>>2]|0;if(J>>>0>>0){_a()}if(d>>>0>>0){_a()}else{c[d+12>>2]=p;c[F>>2]=p;c[p+8>>2]=d;c[p+12>>2]=J;c[p+24>>2]=0;break}}else{c[27660>>2]=E|w;c[C>>2]=p;c[p+24>>2]=C;c[p+12>>2]=p;c[p+8>>2]=p}}while(0);p=(c[27688>>2]|0)+ -1|0;c[27688>>2]=p;if((p|0)==0){K=28112|0}else{i=b;return}while(1){p=c[K>>2]|0;if((p|0)==0){break}else{K=p+8|0}}c[27688>>2]=-1;i=b;return}function ig(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;if((a|0)!=0){e=aa(b,a)|0;if((b|a)>>>0>65535){f=((e>>>0)/(a>>>0)|0|0)==(b|0)?e:-1}else{f=e}}else{f=0}e=gg(f)|0;if((e|0)==0){i=d;return e|0}if((c[e+ -4>>2]&3|0)==0){i=d;return e|0}Eg(e|0,0,f|0)|0;i=d;return e|0}function jg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;do{if((a|0)!=0){if(b>>>0>4294967231){c[(Sa()|0)>>2]=12;e=0;break}if(b>>>0<11){f=16}else{f=b+11&-8}g=kg(a+ -8|0,f)|0;if((g|0)!=0){e=g+8|0;break}g=gg(b)|0;if((g|0)==0){e=0}else{h=c[a+ -4>>2]|0;j=(h&-8)-((h&3|0)==0?8:4)|0;Kg(g|0,a|0,(j>>>0>>0?j:b)|0)|0;hg(a);e=g}}else{e=gg(b)|0}}while(0);i=d;return e|0}function kg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;d=i;e=a+4|0;f=c[e>>2]|0;g=f&-8;h=a+g|0;j=c[27672>>2]|0;if(a>>>0>>0){_a()}k=f&3;if(!((k|0)!=1&a>>>0>>0)){_a()}l=a+(g|4)|0;m=c[l>>2]|0;if((m&1|0)==0){_a()}if((k|0)==0){if(b>>>0<256){n=0;i=d;return n|0}if(!(g>>>0<(b+4|0)>>>0)?!((g-b|0)>>>0>c[28136>>2]<<1>>>0):0){n=a;i=d;return n|0}n=0;i=d;return n|0}if(!(g>>>0>>0)){k=g-b|0;if(!(k>>>0>15)){n=a;i=d;return n|0}c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=k|3;c[l>>2]=c[l>>2]|1;lg(a+b|0,k);n=a;i=d;return n|0}if((h|0)==(c[27680>>2]|0)){k=(c[27668>>2]|0)+g|0;if(!(k>>>0>b>>>0)){n=0;i=d;return n|0}l=k-b|0;c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=l|1;c[27680>>2]=a+b;c[27668>>2]=l;n=a;i=d;return n|0}if((h|0)==(c[27676>>2]|0)){l=(c[27664>>2]|0)+g|0;if(l>>>0>>0){n=0;i=d;return n|0}k=l-b|0;if(k>>>0>15){c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=k|1;c[a+l>>2]=k;o=a+(l+4)|0;c[o>>2]=c[o>>2]&-2;p=a+b|0;q=k}else{c[e>>2]=f&1|l|2;f=a+(l+4)|0;c[f>>2]=c[f>>2]|1;p=0;q=0}c[27664>>2]=q;c[27676>>2]=p;n=a;i=d;return n|0}if((m&2|0)!=0){n=0;i=d;return n|0}p=(m&-8)+g|0;if(p>>>0>>0){n=0;i=d;return n|0}q=p-b|0;f=m>>>3;do{if(!(m>>>0<256)){l=c[a+(g+24)>>2]|0;k=c[a+(g+12)>>2]|0;do{if((k|0)==(h|0)){o=a+(g+20)|0;r=c[o>>2]|0;if((r|0)==0){s=a+(g+16)|0;t=c[s>>2]|0;if((t|0)==0){u=0;break}else{v=t;w=s}}else{v=r;w=o}while(1){o=v+20|0;r=c[o>>2]|0;if((r|0)!=0){v=r;w=o;continue}o=v+16|0;r=c[o>>2]|0;if((r|0)==0){break}else{v=r;w=o}}if(w>>>0>>0){_a()}else{c[w>>2]=0;u=v;break}}else{o=c[a+(g+8)>>2]|0;if(o>>>0>>0){_a()}r=o+12|0;if((c[r>>2]|0)!=(h|0)){_a()}s=k+8|0;if((c[s>>2]|0)==(h|0)){c[r>>2]=k;c[s>>2]=o;u=k;break}else{_a()}}}while(0);if((l|0)!=0){k=c[a+(g+28)>>2]|0;o=27960+(k<<2)|0;if((h|0)==(c[o>>2]|0)){c[o>>2]=u;if((u|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}k=l+16|0;if((c[k>>2]|0)==(h|0)){c[k>>2]=u}else{c[l+20>>2]=u}if((u|0)==0){break}}if(u>>>0<(c[27672>>2]|0)>>>0){_a()}c[u+24>>2]=l;k=c[a+(g+16)>>2]|0;do{if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+16>>2]=k;c[k+24>>2]=u;break}}}while(0);k=c[a+(g+20)>>2]|0;if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+20>>2]=k;c[k+24>>2]=u;break}}}}else{k=c[a+(g+8)>>2]|0;l=c[a+(g+12)>>2]|0;o=27696+(f<<1<<2)|0;if((k|0)!=(o|0)){if(k>>>0>>0){_a()}if((c[k+12>>2]|0)!=(h|0)){_a()}}if((l|0)==(k|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}o=l+8|0;if((c[o>>2]|0)==(h|0)){x=o}else{_a()}}else{x=l+8|0}c[k+12>>2]=l;c[x>>2]=k}}while(0);if(q>>>0<16){c[e>>2]=p|c[e>>2]&1|2;x=a+(p|4)|0;c[x>>2]=c[x>>2]|1;n=a;i=d;return n|0}else{c[e>>2]=c[e>>2]&1|b|2;c[a+(b+4)>>2]=q|3;e=a+(p|4)|0;c[e>>2]=c[e>>2]|1;lg(a+b|0,q);n=a;i=d;return n|0}return 0}function lg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;d=i;e=a+b|0;f=c[a+4>>2]|0;do{if((f&1|0)==0){g=c[a>>2]|0;if((f&3|0)==0){i=d;return}h=a+(0-g)|0;j=g+b|0;k=c[27672>>2]|0;if(h>>>0>>0){_a()}if((h|0)==(c[27676>>2]|0)){l=a+(b+4)|0;if((c[l>>2]&3|0)!=3){m=h;n=j;break}c[27664>>2]=j;c[l>>2]=c[l>>2]&-2;c[a+(4-g)>>2]=j|1;c[e>>2]=j;i=d;return}l=g>>>3;if(g>>>0<256){o=c[a+(8-g)>>2]|0;p=c[a+(12-g)>>2]|0;q=27696+(l<<1<<2)|0;if((o|0)!=(q|0)){if(o>>>0>>0){_a()}if((c[o+12>>2]|0)!=(h|0)){_a()}}if((p|0)==(o|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}q=p+8|0;if((c[q>>2]|0)==(h|0)){r=q}else{_a()}}else{r=p+8|0}c[o+12>>2]=p;c[r>>2]=o;m=h;n=j;break}o=c[a+(24-g)>>2]|0;p=c[a+(12-g)>>2]|0;do{if((p|0)==(h|0)){q=16-g|0;l=a+(q+4)|0;s=c[l>>2]|0;if((s|0)==0){t=a+q|0;q=c[t>>2]|0;if((q|0)==0){u=0;break}else{v=q;w=t}}else{v=s;w=l}while(1){l=v+20|0;s=c[l>>2]|0;if((s|0)!=0){v=s;w=l;continue}l=v+16|0;s=c[l>>2]|0;if((s|0)==0){break}else{v=s;w=l}}if(w>>>0>>0){_a()}else{c[w>>2]=0;u=v;break}}else{l=c[a+(8-g)>>2]|0;if(l>>>0>>0){_a()}s=l+12|0;if((c[s>>2]|0)!=(h|0)){_a()}t=p+8|0;if((c[t>>2]|0)==(h|0)){c[s>>2]=p;c[t>>2]=l;u=p;break}else{_a()}}}while(0);if((o|0)!=0){p=c[a+(28-g)>>2]|0;k=27960+(p<<2)|0;if((h|0)==(c[k>>2]|0)){c[k>>2]=u;if((u|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}p=o+16|0;if((c[p>>2]|0)==(h|0)){c[p>>2]=u}else{c[o+20>>2]=u}if((u|0)==0){m=h;n=j;break}}if(u>>>0<(c[27672>>2]|0)>>>0){_a()}c[u+24>>2]=o;p=16-g|0;k=c[a+p>>2]|0;do{if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+16>>2]=k;c[k+24>>2]=u;break}}}while(0);k=c[a+(p+4)>>2]|0;if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+20>>2]=k;c[k+24>>2]=u;m=h;n=j;break}}else{m=h;n=j}}else{m=h;n=j}}else{m=a;n=b}}while(0);u=c[27672>>2]|0;if(e>>>0>>0){_a()}v=a+(b+4)|0;w=c[v>>2]|0;if((w&2|0)==0){if((e|0)==(c[27680>>2]|0)){r=(c[27668>>2]|0)+n|0;c[27668>>2]=r;c[27680>>2]=m;c[m+4>>2]=r|1;if((m|0)!=(c[27676>>2]|0)){i=d;return}c[27676>>2]=0;c[27664>>2]=0;i=d;return}if((e|0)==(c[27676>>2]|0)){r=(c[27664>>2]|0)+n|0;c[27664>>2]=r;c[27676>>2]=m;c[m+4>>2]=r|1;c[m+r>>2]=r;i=d;return}r=(w&-8)+n|0;f=w>>>3;do{if(!(w>>>0<256)){k=c[a+(b+24)>>2]|0;g=c[a+(b+12)>>2]|0;do{if((g|0)==(e|0)){o=a+(b+20)|0;l=c[o>>2]|0;if((l|0)==0){t=a+(b+16)|0;s=c[t>>2]|0;if((s|0)==0){x=0;break}else{y=s;z=t}}else{y=l;z=o}while(1){o=y+20|0;l=c[o>>2]|0;if((l|0)!=0){y=l;z=o;continue}o=y+16|0;l=c[o>>2]|0;if((l|0)==0){break}else{y=l;z=o}}if(z>>>0>>0){_a()}else{c[z>>2]=0;x=y;break}}else{o=c[a+(b+8)>>2]|0;if(o>>>0>>0){_a()}l=o+12|0;if((c[l>>2]|0)!=(e|0)){_a()}t=g+8|0;if((c[t>>2]|0)==(e|0)){c[l>>2]=g;c[t>>2]=o;x=g;break}else{_a()}}}while(0);if((k|0)!=0){g=c[a+(b+28)>>2]|0;j=27960+(g<<2)|0;if((e|0)==(c[j>>2]|0)){c[j>>2]=x;if((x|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}g=k+16|0;if((c[g>>2]|0)==(e|0)){c[g>>2]=x}else{c[k+20>>2]=x}if((x|0)==0){break}}if(x>>>0<(c[27672>>2]|0)>>>0){_a()}c[x+24>>2]=k;g=c[a+(b+16)>>2]|0;do{if((g|0)!=0){if(g>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[x+16>>2]=g;c[g+24>>2]=x;break}}}while(0);g=c[a+(b+20)>>2]|0;if((g|0)!=0){if(g>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[x+20>>2]=g;c[g+24>>2]=x;break}}}}else{g=c[a+(b+8)>>2]|0;k=c[a+(b+12)>>2]|0;j=27696+(f<<1<<2)|0;if((g|0)!=(j|0)){if(g>>>0>>0){_a()}if((c[g+12>>2]|0)!=(e|0)){_a()}}if((k|0)==(g|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}j=k+8|0;if((c[j>>2]|0)==(e|0)){A=j}else{_a()}}else{A=k+8|0}c[g+12>>2]=k;c[A>>2]=g}}while(0);c[m+4>>2]=r|1;c[m+r>>2]=r;if((m|0)==(c[27676>>2]|0)){c[27664>>2]=r;i=d;return}else{B=r}}else{c[v>>2]=w&-2;c[m+4>>2]=n|1;c[m+n>>2]=n;B=n}n=B>>>3;if(B>>>0<256){w=n<<1;v=27696+(w<<2)|0;r=c[6914]|0;A=1<>2]|0;if(e>>>0<(c[27672>>2]|0)>>>0){_a()}else{C=n;D=e}}else{c[6914]=r|A;C=27696+(w+2<<2)|0;D=v}c[C>>2]=m;c[D+12>>2]=m;c[m+8>>2]=D;c[m+12>>2]=v;i=d;return}v=B>>>8;if((v|0)!=0){if(B>>>0>16777215){E=31}else{D=(v+1048320|0)>>>16&8;C=v<>>16&4;w=C<>>16&2;A=14-(v|D|C)+(w<>>15)|0;E=B>>>(A+7|0)&1|A<<1}}else{E=0}A=27960+(E<<2)|0;c[m+28>>2]=E;c[m+20>>2]=0;c[m+16>>2]=0;C=c[27660>>2]|0;w=1<>2]=C|w;c[A>>2]=m;c[m+24>>2]=A;c[m+12>>2]=m;c[m+8>>2]=m;i=d;return}w=c[A>>2]|0;if((E|0)==31){F=0}else{F=25-(E>>>1)|0}a:do{if((c[w+4>>2]&-8|0)==(B|0)){G=w}else{E=B<>>31<<2)+16|0;C=c[H>>2]|0;if((C|0)==0){break}if((c[C+4>>2]&-8|0)==(B|0)){G=C;break a}else{E=E<<1;A=C}}if(H>>>0<(c[27672>>2]|0)>>>0){_a()}c[H>>2]=m;c[m+24>>2]=A;c[m+12>>2]=m;c[m+8>>2]=m;i=d;return}}while(0);H=G+8|0;B=c[H>>2]|0;w=c[27672>>2]|0;if(G>>>0>>0){_a()}if(B>>>0>>0){_a()}c[B+12>>2]=m;c[H>>2]=m;c[m+8>>2]=B;c[m+12>>2]=G;c[m+24>>2]=0;i=d;return}function mg(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0.0,Q=0,R=0.0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0.0,ca=0,da=0.0,ea=0,fa=0.0,ga=0,ha=0.0,ia=0,ja=0.0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,ra=0,sa=0.0,ta=0,ua=0.0,va=0,wa=0,xa=0,ya=0,za=0.0,Aa=0,Ba=0.0,Ca=0.0,Da=0,Ea=0.0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Ta=0,Ua=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0.0,sc=0,tc=0,uc=0.0,vc=0.0,wc=0.0,xc=0.0,yc=0.0,zc=0.0,Ac=0,Bc=0,Cc=0.0,Dc=0,Ec=0.0,Fc=0,Gc=0,Hc=0,Ic=0;g=i;i=i+512|0;h=g;if((e|0)==1){j=53;k=-1074}else if((e|0)==0){j=24;k=-149}else if((e|0)==2){j=53;k=-1074}else{l=0.0;i=g;return+l}e=b+4|0;m=b+100|0;do{n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;o=d[n]|0}else{o=pg(b)|0}}while((fb(o|0)|0)!=0);do{if((o|0)==43|(o|0)==45){n=1-(((o|0)==45)<<1)|0;p=c[e>>2]|0;if(p>>>0<(c[m>>2]|0)>>>0){c[e>>2]=p+1;q=d[p]|0;r=n;break}else{q=pg(b)|0;r=n;break}}else{q=o;r=1}}while(0);o=q;q=0;while(1){if((o|32|0)!=(a[28152+q|0]|0)){s=o;v=q;break}do{if(q>>>0<7){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;w=d[n]|0;break}else{w=pg(b)|0;break}}else{w=o}}while(0);n=q+1|0;if(n>>>0<8){o=w;q=n}else{s=w;v=n;break}}do{if((v|0)==3){x=23}else if((v|0)!=8){w=(f|0)==0;if(!(v>>>0<4|w)){if((v|0)==8){break}else{x=23;break}}a:do{if((v|0)==0){q=s;o=0;while(1){if((q|32|0)!=(a[28168+o|0]|0)){y=q;z=o;break a}do{if(o>>>0<2){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;A=d[n]|0;break}else{A=pg(b)|0;break}}else{A=q}}while(0);n=o+1|0;if(n>>>0<3){q=A;o=n}else{y=A;z=n;break}}}else{y=s;z=v}}while(0);if((z|0)==0){do{if((y|0)==48){o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;B=d[o]|0}else{B=pg(b)|0}if((B|32|0)!=120){if((c[m>>2]|0)==0){C=48;break}c[e>>2]=(c[e>>2]|0)+ -1;C=48;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;D=d[o]|0;F=0}else{D=pg(b)|0;F=0}while(1){if((D|0)==46){x=70;break}else if((D|0)!=48){G=0;H=0;I=0;J=0;K=D;L=F;M=0;N=0;O=1.0;Q=0;R=0.0;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;D=d[o]|0;F=1;continue}else{D=pg(b)|0;F=1;continue}}b:do{if((x|0)==70){o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;S=d[o]|0}else{S=pg(b)|0}if((S|0)==48){o=-1;q=-1;while(1){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;T=d[n]|0}else{T=pg(b)|0}if((T|0)!=48){G=0;H=0;I=o;J=q;K=T;L=1;M=1;N=0;O=1.0;Q=0;R=0.0;break b}n=Ig(o|0,q|0,-1,-1)|0;o=n;q=E}}else{G=0;H=0;I=0;J=0;K=S;L=F;M=1;N=0;O=1.0;Q=0;R=0.0}}}while(0);c:while(1){q=K+ -48|0;do{if(!(q>>>0<10)){o=K|32;n=(K|0)==46;if(!((o+ -97|0)>>>0<6|n)){U=K;break c}if(n){if((M|0)==0){V=H;W=G;X=H;Y=G;Z=L;_=1;$=N;ba=O;ca=Q;da=R;break}else{U=46;break c}}else{ea=(K|0)>57?o+ -87|0:q;x=84;break}}else{ea=q;x=84}}while(0);if((x|0)==84){x=0;do{if(!((G|0)<0|(G|0)==0&H>>>0<8)){if((G|0)<0|(G|0)==0&H>>>0<14){fa=O*.0625;ga=N;ha=fa;ia=Q;ja=R+fa*+(ea|0);break}if((ea|0)!=0&(N|0)==0){ga=1;ha=O;ia=Q;ja=R+O*.5}else{ga=N;ha=O;ia=Q;ja=R}}else{ga=N;ha=O;ia=ea+(Q<<4)|0;ja=R}}while(0);q=Ig(H|0,G|0,1,0)|0;V=I;W=J;X=q;Y=E;Z=1;_=M;$=ga;ba=ha;ca=ia;da=ja}q=c[e>>2]|0;if(q>>>0<(c[m>>2]|0)>>>0){c[e>>2]=q+1;G=Y;H=X;I=V;J=W;K=d[q]|0;L=Z;M=_;N=$;O=ba;Q=ca;R=da;continue}else{G=Y;H=X;I=V;J=W;K=pg(b)|0;L=Z;M=_;N=$;O=ba;Q=ca;R=da;continue}}if((L|0)==0){q=(c[m>>2]|0)==0;if(!q){c[e>>2]=(c[e>>2]|0)+ -1}if(!w){if(!q?(q=c[e>>2]|0,c[e>>2]=q+ -1,(M|0)!=0):0){c[e>>2]=q+ -2}}else{og(b,0)}l=+(r|0)*0.0;i=g;return+l}q=(M|0)==0;o=q?H:I;n=q?G:J;if((G|0)<0|(G|0)==0&H>>>0<8){q=H;p=G;ka=Q;while(1){la=ka<<4;ma=Ig(q|0,p|0,1,0)|0;na=E;if((na|0)<0|(na|0)==0&ma>>>0<8){q=ma;p=na;ka=la}else{oa=la;break}}}else{oa=Q}do{if((U|32|0)==112){ka=ng(b,f)|0;p=E;if((ka|0)==0&(p|0)==-2147483648){if(w){og(b,0);l=0.0;i=g;return+l}else{if((c[m>>2]|0)==0){pa=0;ra=0;break}c[e>>2]=(c[e>>2]|0)+ -1;pa=0;ra=0;break}}else{pa=ka;ra=p}}else{if((c[m>>2]|0)==0){pa=0;ra=0}else{c[e>>2]=(c[e>>2]|0)+ -1;pa=0;ra=0}}}while(0);p=Gg(o|0,n|0,2)|0;ka=Ig(p|0,E|0,-32,-1)|0;p=Ig(ka|0,E|0,pa|0,ra|0)|0;ka=E;if((oa|0)==0){l=+(r|0)*0.0;i=g;return+l}if((ka|0)>0|(ka|0)==0&p>>>0>(0-k|0)>>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+l}q=k+ -106|0;la=((q|0)<0)<<31>>31;if((ka|0)<(la|0)|(ka|0)==(la|0)&p>>>0>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+l}if((oa|0)>-1){q=p;la=ka;na=oa;fa=R;while(1){ma=na<<1;if(!(fa>=.5)){sa=fa;ta=ma}else{sa=fa+-1.0;ta=ma|1}ua=fa+sa;ma=Ig(q|0,la|0,-1,-1)|0;va=E;if((ta|0)>-1){q=ma;la=va;na=ta;fa=ua}else{wa=ma;xa=va;ya=ta;za=ua;break}}}else{wa=p;xa=ka;ya=oa;za=R}na=Cg(32,0,k|0,((k|0)<0)<<31>>31|0)|0;la=Ig(wa|0,xa|0,na|0,E|0)|0;na=E;if(0>(na|0)|0==(na|0)&j>>>0>la>>>0){Aa=(la|0)<0?0:la}else{Aa=j}if((Aa|0)<53){fa=+(r|0);ua=+Va(+(+qg(1.0,84-Aa|0)),+fa);if((Aa|0)<32&za!=0.0){la=ya&1;Ba=fa;Ca=ua;Da=(la^1)+ya|0;Ea=(la|0)==0?0.0:za}else{Ba=fa;Ca=ua;Da=ya;Ea=za}}else{Ba=+(r|0);Ca=0.0;Da=ya;Ea=za}ua=Ba*Ea+(Ca+Ba*+(Da>>>0))-Ca;if(!(ua!=0.0)){c[(Sa()|0)>>2]=34}l=+rg(ua,wa);i=g;return+l}else{C=y}}while(0);la=k+j|0;na=0-la|0;q=C;n=0;while(1){if((q|0)==46){x=139;break}else if((q|0)!=48){Fa=q;Ga=0;Ha=0;Ia=n;Ja=0;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;q=d[o]|0;n=1;continue}else{q=pg(b)|0;n=1;continue}}d:do{if((x|0)==139){q=c[e>>2]|0;if(q>>>0<(c[m>>2]|0)>>>0){c[e>>2]=q+1;Ka=d[q]|0}else{Ka=pg(b)|0}if((Ka|0)==48){q=-1;o=-1;while(1){va=c[e>>2]|0;if(va>>>0<(c[m>>2]|0)>>>0){c[e>>2]=va+1;La=d[va]|0}else{La=pg(b)|0}if((La|0)!=48){Fa=La;Ga=q;Ha=o;Ia=1;Ja=1;break d}va=Ig(q|0,o|0,-1,-1)|0;q=va;o=E}}else{Fa=Ka;Ga=0;Ha=0;Ia=n;Ja=1}}}while(0);c[h>>2]=0;n=Fa+ -48|0;o=(Fa|0)==46;e:do{if(n>>>0<10|o){q=h+496|0;ka=Fa;p=0;va=0;ma=o;Ma=n;Na=Ga;Oa=Ha;Pa=Ia;Qa=Ja;Ra=0;Ta=0;Ua=0;while(1){do{if(ma){if((Qa|0)==0){Wa=p;Xa=va;Ya=p;Za=va;_a=Pa;$a=1;ab=Ra;bb=Ta;cb=Ua}else{db=ka;eb=Na;gb=Oa;hb=p;ib=va;jb=Pa;kb=Ra;lb=Ta;mb=Ua;break e}}else{nb=Ig(p|0,va|0,1,0)|0;ob=E;pb=(ka|0)!=48;if((Ta|0)>=125){if(!pb){Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=Pa;$a=Qa;ab=Ra;bb=Ta;cb=Ua;break}c[q>>2]=c[q>>2]|1;Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=Pa;$a=Qa;ab=Ra;bb=Ta;cb=Ua;break}qb=h+(Ta<<2)|0;if((Ra|0)==0){rb=Ma}else{rb=ka+ -48+((c[qb>>2]|0)*10|0)|0}c[qb>>2]=rb;qb=Ra+1|0;sb=(qb|0)==9;Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=1;$a=Qa;ab=sb?0:qb;bb=(sb&1)+Ta|0;cb=pb?nb:Ua}}while(0);nb=c[e>>2]|0;if(nb>>>0<(c[m>>2]|0)>>>0){c[e>>2]=nb+1;tb=d[nb]|0}else{tb=pg(b)|0}nb=tb+ -48|0;pb=(tb|0)==46;if(nb>>>0<10|pb){ka=tb;p=Ya;va=Za;ma=pb;Ma=nb;Na=Wa;Oa=Xa;Pa=_a;Qa=$a;Ra=ab;Ta=bb;Ua=cb}else{ub=tb;vb=Ya;wb=Wa;xb=Za;yb=Xa;zb=_a;Ab=$a;Bb=ab;Cb=bb;Db=cb;x=162;break}}}else{ub=Fa;vb=0;wb=Ga;xb=0;yb=Ha;zb=Ia;Ab=Ja;Bb=0;Cb=0;Db=0;x=162}}while(0);if((x|0)==162){n=(Ab|0)==0;db=ub;eb=n?vb:wb;gb=n?xb:yb;hb=vb;ib=xb;jb=zb;kb=Bb;lb=Cb;mb=Db}n=(jb|0)!=0;if(n?(db|32|0)==101:0){o=ng(b,f)|0;Ua=E;do{if((o|0)==0&(Ua|0)==-2147483648){if(w){og(b,0);l=0.0;i=g;return+l}else{if((c[m>>2]|0)==0){Eb=0;Fb=0;break}c[e>>2]=(c[e>>2]|0)+ -1;Eb=0;Fb=0;break}}else{Eb=o;Fb=Ua}}while(0);Ua=Ig(Eb|0,Fb|0,eb|0,gb|0)|0;Gb=Ua;Hb=E}else{if((db|0)>-1?(c[m>>2]|0)!=0:0){c[e>>2]=(c[e>>2]|0)+ -1;Gb=eb;Hb=gb}else{Gb=eb;Hb=gb}}if(!n){c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}Ua=c[h>>2]|0;if((Ua|0)==0){l=+(r|0)*0.0;i=g;return+l}do{if((Gb|0)==(hb|0)&(Hb|0)==(ib|0)&((ib|0)<0|(ib|0)==0&hb>>>0<10)){if(!(j>>>0>30)?(Ua>>>j|0)!=0:0){break}l=+(r|0)*+(Ua>>>0);i=g;return+l}}while(0);Ua=(k|0)/-2|0;n=((Ua|0)<0)<<31>>31;if((Hb|0)>(n|0)|(Hb|0)==(n|0)&Gb>>>0>Ua>>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+l}Ua=k+ -106|0;n=((Ua|0)<0)<<31>>31;if((Hb|0)<(n|0)|(Hb|0)==(n|0)&Gb>>>0>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+l}if((kb|0)==0){Ib=lb}else{if((kb|0)<9){Ua=h+(lb<<2)|0;n=c[Ua>>2]|0;o=kb;do{n=n*10|0;o=o+1|0}while((o|0)!=9);c[Ua>>2]=n}Ib=lb+1|0}do{if((mb|0)<9?(mb|0)<=(Gb|0)&(Gb|0)<18:0){if((Gb|0)==9){l=+(r|0)*+((c[h>>2]|0)>>>0);i=g;return+l}if((Gb|0)<9){l=+(r|0)*+((c[h>>2]|0)>>>0)/+(c[28184+(8-Gb<<2)>>2]|0);i=g;return+l}o=j+27+(aa(Gb,-3)|0)|0;Ta=c[h>>2]|0;if((o|0)<=30?(Ta>>>o|0)!=0:0){break}l=+(r|0)*+(Ta>>>0)*+(c[28184+(Gb+ -10<<2)>>2]|0);i=g;return+l}}while(0);n=(Gb|0)%9|0;if((n|0)==0){Jb=0;Kb=0;Lb=Gb;Mb=Ib}else{Ua=(Gb|0)>-1?n:n+9|0;n=c[28184+(8-Ua<<2)>>2]|0;if((Ib|0)!=0){Ta=1e9/(n|0)|0;o=0;Ra=0;Qa=0;Pa=Gb;while(1){Oa=h+(Qa<<2)|0;Na=c[Oa>>2]|0;Ma=((Na>>>0)/(n>>>0)|0)+Ra|0;c[Oa>>2]=Ma;Nb=aa((Na>>>0)%(n>>>0)|0,Ta)|0;Na=Qa+1|0;if((Qa|0)==(o|0)&(Ma|0)==0){Ob=Na&127;Pb=Pa+ -9|0}else{Ob=o;Pb=Pa}if((Na|0)==(Ib|0)){break}else{o=Ob;Ra=Nb;Qa=Na;Pa=Pb}}if((Nb|0)==0){Qb=Ob;Rb=Pb;Sb=Ib}else{c[h+(Ib<<2)>>2]=Nb;Qb=Ob;Rb=Pb;Sb=Ib+1|0}}else{Qb=0;Rb=Gb;Sb=0}Jb=Qb;Kb=0;Lb=9-Ua+Rb|0;Mb=Sb}f:while(1){Pa=h+(Jb<<2)|0;if((Lb|0)<18){Qa=Kb;Ra=Mb;while(1){o=0;Ta=Ra+127|0;n=Ra;while(1){Na=Ta&127;Ma=h+(Na<<2)|0;Oa=Gg(c[Ma>>2]|0,0,29)|0;ma=Ig(Oa|0,E|0,o|0,0)|0;Oa=E;if(Oa>>>0>0|(Oa|0)==0&ma>>>0>1e9){va=Ug(ma|0,Oa|0,1e9,0)|0;p=Vg(ma|0,Oa|0,1e9,0)|0;Tb=p;Ub=va}else{Tb=ma;Ub=0}c[Ma>>2]=Tb;Ma=(Na|0)==(Jb|0);if((Na|0)!=(n+127&127|0)|Ma){Vb=n}else{Vb=(Tb|0)==0?Na:n}if(Ma){break}else{o=Ub;Ta=Na+ -1|0;n=Vb}}n=Qa+ -29|0;if((Ub|0)==0){Qa=n;Ra=Vb}else{Wb=n;Xb=Ub;Yb=Vb;break}}}else{if((Lb|0)==18){Zb=Kb;_b=Mb}else{$b=Jb;ac=Kb;bc=Lb;cc=Mb;break}while(1){if(!((c[Pa>>2]|0)>>>0<9007199)){$b=Jb;ac=Zb;bc=18;cc=_b;break f}Ra=0;Qa=_b+127|0;n=_b;while(1){Ta=Qa&127;o=h+(Ta<<2)|0;Na=Gg(c[o>>2]|0,0,29)|0;Ma=Ig(Na|0,E|0,Ra|0,0)|0;Na=E;if(Na>>>0>0|(Na|0)==0&Ma>>>0>1e9){ma=Ug(Ma|0,Na|0,1e9,0)|0;va=Vg(Ma|0,Na|0,1e9,0)|0;dc=va;ec=ma}else{dc=Ma;ec=0}c[o>>2]=dc;o=(Ta|0)==(Jb|0);if((Ta|0)!=(n+127&127|0)|o){fc=n}else{fc=(dc|0)==0?Ta:n}if(o){break}else{Ra=ec;Qa=Ta+ -1|0;n=fc}}n=Zb+ -29|0;if((ec|0)==0){Zb=n;_b=fc}else{Wb=n;Xb=ec;Yb=fc;break}}}Pa=Jb+127&127;if((Pa|0)==(Yb|0)){n=Yb+127&127;Qa=h+((Yb+126&127)<<2)|0;c[Qa>>2]=c[Qa>>2]|c[h+(n<<2)>>2];gc=n}else{gc=Yb}c[h+(Pa<<2)>>2]=Xb;Jb=Pa;Kb=Wb;Lb=Lb+9|0;Mb=gc}g:while(1){hc=cc+1&127;Ua=h+((cc+127&127)<<2)|0;Pa=$b;n=ac;Qa=bc;while(1){Ra=(Qa|0)==18;Ta=(Qa|0)>27?9:1;ic=Pa;jc=n;while(1){o=0;while(1){Ma=o+ic&127;if((Ma|0)==(cc|0)){kc=2;break}ma=c[h+(Ma<<2)>>2]|0;Ma=c[28176+(o<<2)>>2]|0;if(ma>>>0>>0){kc=2;break}va=o+1|0;if(ma>>>0>Ma>>>0){kc=o;break}if((va|0)<2){o=va}else{kc=va;break}}if((kc|0)==2&Ra){break g}lc=Ta+jc|0;if((ic|0)==(cc|0)){ic=cc;jc=lc}else{break}}Ra=(1<>>Ta;mc=ic;nc=0;va=ic;oc=Qa;do{Ma=h+(va<<2)|0;ma=c[Ma>>2]|0;Na=(ma>>>Ta)+nc|0;c[Ma>>2]=Na;nc=aa(ma&Ra,o)|0;ma=(va|0)==(mc|0)&(Na|0)==0;va=va+1&127;oc=ma?oc+ -9|0:oc;mc=ma?va:mc}while((va|0)!=(cc|0));if((nc|0)==0){Pa=mc;n=lc;Qa=oc;continue}if((hc|0)!=(mc|0)){break}c[Ua>>2]=c[Ua>>2]|1;Pa=mc;n=lc;Qa=oc}c[h+(cc<<2)>>2]=nc;$b=mc;ac=lc;bc=oc;cc=hc}Qa=ic&127;if((Qa|0)==(cc|0)){c[h+(hc+ -1<<2)>>2]=0;pc=hc}else{pc=cc}ua=+((c[h+(Qa<<2)>>2]|0)>>>0);Qa=ic+1&127;if((Qa|0)==(pc|0)){n=pc+1&127;c[h+(n+ -1<<2)>>2]=0;qc=n}else{qc=pc}fa=+(r|0);rc=fa*(ua*1.0e9+ +((c[h+(Qa<<2)>>2]|0)>>>0));Qa=jc+53|0;n=Qa-k|0;if((n|0)<(j|0)){sc=(n|0)<0?0:n;tc=1}else{sc=j;tc=0}if((sc|0)<53){ua=+Va(+(+qg(1.0,105-sc|0)),+rc);uc=+qa(+rc,+(+qg(1.0,53-sc|0)));vc=ua;wc=uc;xc=ua+(rc-uc)}else{vc=0.0;wc=0.0;xc=rc}Pa=ic+2&127;if((Pa|0)!=(qc|0)){Ua=c[h+(Pa<<2)>>2]|0;do{if(!(Ua>>>0<5e8)){if(Ua>>>0>5e8){yc=fa*.75+wc;break}if((ic+3&127|0)==(qc|0)){yc=fa*.5+wc;break}else{yc=fa*.75+wc;break}}else{if((Ua|0)==0?(ic+3&127|0)==(qc|0):0){yc=wc;break}yc=fa*.25+wc}}while(0);if((53-sc|0)>1?!(+qa(+yc,1.0)!=0.0):0){zc=yc+1.0}else{zc=yc}}else{zc=wc}fa=xc+zc-vc;do{if((Qa&2147483647|0)>(-2-la|0)){if(!(+P(+fa)>=9007199254740992.0)){Ac=tc;Bc=jc;Cc=fa}else{Ac=(tc|0)!=0&(sc|0)==(n|0)?0:tc;Bc=jc+1|0;Cc=fa*.5}if((Bc+50|0)<=(na|0)?!((Ac|0)!=0&zc!=0.0):0){Dc=Bc;Ec=Cc;break}c[(Sa()|0)>>2]=34;Dc=Bc;Ec=Cc}else{Dc=jc;Ec=fa}}while(0);l=+rg(Ec,Dc);i=g;return+l}else if((z|0)==3){na=c[e>>2]|0;if(na>>>0<(c[m>>2]|0)>>>0){c[e>>2]=na+1;Fc=d[na]|0}else{Fc=pg(b)|0}if((Fc|0)==40){Gc=1}else{if((c[m>>2]|0)==0){l=t;i=g;return+l}c[e>>2]=(c[e>>2]|0)+ -1;l=t;i=g;return+l}while(1){na=c[e>>2]|0;if(na>>>0<(c[m>>2]|0)>>>0){c[e>>2]=na+1;Hc=d[na]|0}else{Hc=pg(b)|0}if(!((Hc+ -48|0)>>>0<10|(Hc+ -65|0)>>>0<26)?!((Hc+ -97|0)>>>0<26|(Hc|0)==95):0){break}Gc=Gc+1|0}if((Hc|0)==41){l=t;i=g;return+l}na=(c[m>>2]|0)==0;if(!na){c[e>>2]=(c[e>>2]|0)+ -1}if(w){c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}if((Gc|0)==0|na){l=t;i=g;return+l}else{Ic=Gc}while(1){na=Ic+ -1|0;c[e>>2]=(c[e>>2]|0)+ -1;if((na|0)==0){l=t;break}else{Ic=na}}i=g;return+l}else{if((c[m>>2]|0)!=0){c[e>>2]=(c[e>>2]|0)+ -1}c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}}}while(0);if((x|0)==23){x=(c[m>>2]|0)==0;if(!x){c[e>>2]=(c[e>>2]|0)+ -1}if(!(v>>>0<4|(f|0)==0|x)){x=v;do{c[e>>2]=(c[e>>2]|0)+ -1;x=x+ -1|0}while(x>>>0>3)}}l=+(r|0)*u;i=g;return+l}function ng(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;e=i;f=a+4|0;g=c[f>>2]|0;h=a+100|0;if(g>>>0<(c[h>>2]|0)>>>0){c[f>>2]=g+1;j=d[g]|0}else{j=pg(a)|0}if((j|0)==43|(j|0)==45){g=(j|0)==45|0;k=c[f>>2]|0;if(k>>>0<(c[h>>2]|0)>>>0){c[f>>2]=k+1;l=d[k]|0}else{l=pg(a)|0}if(!((l+ -48|0)>>>0<10|(b|0)==0)?(c[h>>2]|0)!=0:0){c[f>>2]=(c[f>>2]|0)+ -1;m=l;n=g}else{m=l;n=g}}else{m=j;n=0}if((m+ -48|0)>>>0>9){if((c[h>>2]|0)==0){o=-2147483648;p=0;E=o;i=e;return p|0}c[f>>2]=(c[f>>2]|0)+ -1;o=-2147483648;p=0;E=o;i=e;return p|0}else{q=m;r=0}while(1){s=q+ -48+r|0;m=c[f>>2]|0;if(m>>>0<(c[h>>2]|0)>>>0){c[f>>2]=m+1;t=d[m]|0}else{t=pg(a)|0}if(!((t+ -48|0)>>>0<10&(s|0)<214748364)){break}q=t;r=s*10|0}r=((s|0)<0)<<31>>31;if((t+ -48|0)>>>0<10){q=s;m=r;j=t;while(1){g=Tg(q|0,m|0,10,0)|0;l=E;b=Ig(j|0,((j|0)<0)<<31>>31|0,-48,-1)|0;k=Ig(b|0,E|0,g|0,l|0)|0;l=E;g=c[f>>2]|0;if(g>>>0<(c[h>>2]|0)>>>0){c[f>>2]=g+1;u=d[g]|0}else{u=pg(a)|0}if((u+ -48|0)>>>0<10&((l|0)<21474836|(l|0)==21474836&k>>>0<2061584302)){q=k;m=l;j=u}else{v=k;w=l;x=u;break}}}else{v=s;w=r;x=t}if((x+ -48|0)>>>0<10){do{x=c[f>>2]|0;if(x>>>0<(c[h>>2]|0)>>>0){c[f>>2]=x+1;y=d[x]|0}else{y=pg(a)|0}}while((y+ -48|0)>>>0<10)}if((c[h>>2]|0)!=0){c[f>>2]=(c[f>>2]|0)+ -1}f=(n|0)!=0;n=Cg(0,0,v|0,w|0)|0;o=f?E:w;p=f?n:v;E=o;i=e;return p|0}function og(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;c[a+104>>2]=b;e=c[a+8>>2]|0;f=c[a+4>>2]|0;g=e-f|0;c[a+108>>2]=g;if((b|0)!=0&(g|0)>(b|0)){c[a+100>>2]=f+b;i=d;return}else{c[a+100>>2]=e;i=d;return}}function pg(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;f=b+104|0;g=c[f>>2]|0;if(!((g|0)!=0?(c[b+108>>2]|0)>=(g|0):0)){h=3}if((h|0)==3?(h=tg(b)|0,(h|0)>=0):0){g=c[f>>2]|0;f=c[b+8>>2]|0;if((g|0)!=0?(j=c[b+4>>2]|0,k=g-(c[b+108>>2]|0)+ -1|0,(f-j|0)>(k|0)):0){c[b+100>>2]=j+k}else{c[b+100>>2]=f}k=c[b+4>>2]|0;if((f|0)!=0){j=b+108|0;c[j>>2]=f+1-k+(c[j>>2]|0)}j=k+ -1|0;if((d[j]|0|0)==(h|0)){l=h;i=e;return l|0}a[j]=h;l=h;i=e;return l|0}c[b+100>>2]=0;l=-1;i=e;return l|0}function qg(a,b){a=+a;b=b|0;var d=0,e=0.0,f=0,g=0,j=0,l=0.0;d=i;if((b|0)>1023){e=a*8.98846567431158e+307;f=b+ -1023|0;if((f|0)>1023){g=b+ -2046|0;j=(g|0)>1023?1023:g;l=e*8.98846567431158e+307}else{j=f;l=e}}else{if((b|0)<-1022){e=a*2.2250738585072014e-308;f=b+1022|0;if((f|0)<-1022){g=b+2044|0;j=(g|0)<-1022?-1022:g;l=e*2.2250738585072014e-308}else{j=f;l=e}}else{j=b;l=a}}b=Gg(j+1023|0,0,52)|0;j=E;c[k>>2]=b;c[k+4>>2]=j;a=l*+h[k>>3];i=d;return+a}function rg(a,b){a=+a;b=b|0;var c=0,d=0.0;c=i;d=+qg(a,b);i=c;return+d}function sg(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;e=b+74|0;f=a[e]|0;a[e]=f+255|f;f=b+20|0;e=b+44|0;if((c[f>>2]|0)>>>0>(c[e>>2]|0)>>>0){kb[c[b+36>>2]&1](b,0,0)|0}c[b+16>>2]=0;c[b+28>>2]=0;c[f>>2]=0;f=c[b>>2]|0;if((f&20|0)==0){g=c[e>>2]|0;c[b+8>>2]=g;c[b+4>>2]=g;h=0;i=d;return h|0}if((f&4|0)==0){h=-1;i=d;return h|0}c[b>>2]=f|32;h=-1;i=d;return h|0}function tg(a){a=a|0;var b=0,e=0,f=0;b=i;i=i+16|0;e=b;if((c[a+8>>2]|0)==0?(sg(a)|0)!=0:0){f=-1}else{if((kb[c[a+32>>2]&1](a,e,1)|0)==1){f=d[e]|0}else{f=-1}}i=b;return f|0}function ug(a){a=a|0;var b=0,c=0.0;b=i;c=+wg(a,0);i=b;return+c}function vg(b){b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;c=i;d=b;while(1){e=d+1|0;if((fb(a[d]|0)|0)==0){break}else{d=e}}b=a[d]|0;f=b<<24>>24;if((f|0)==45){g=1;h=5}else if((f|0)==43){g=0;h=5}else{j=d;k=b;l=0}if((h|0)==5){j=e;k=a[e]|0;l=g}if((cb(k<<24>>24|0)|0)==0){m=0;n=(l|0)!=0;o=0-m|0;p=n?m:o;i=c;return p|0}else{q=j;r=0}while(1){j=q+1|0;k=(r*10|0)+48-(a[q]|0)|0;if((cb(a[j]|0)|0)==0){m=k;break}else{q=j;r=k}}n=(l|0)!=0;o=0-m|0;p=n?m:o;i=c;return p|0}function wg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0.0,j=0,k=0;d=i;i=i+112|0;e=d;f=e+0|0;g=f+112|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(g|0));f=e+4|0;c[f>>2]=a;g=e+8|0;c[g>>2]=-1;c[e+44>>2]=a;c[e+76>>2]=-1;og(e,0);h=+mg(e,1,1);j=(c[f>>2]|0)-(c[g>>2]|0)+(c[e+108>>2]|0)|0;if((b|0)==0){i=d;return+h}if((j|0)==0){k=a}else{k=a+j|0}c[b>>2]=k;i=d;return+h}function xg(b,c){b=b|0;c=c|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;f=a[b]|0;a:do{if(f<<24>>24==0){g=0;h=c}else{j=f;k=f&255;l=b;m=c;while(1){n=a[m]|0;if(n<<24>>24==0){g=j;h=m;break a}if(!(j<<24>>24==n<<24>>24)?(n=Jg(k|0)|0,(n|0)!=(Jg(d[m]|0|0)|0)):0){break}n=l+1|0;o=m+1|0;p=a[n]|0;if(p<<24>>24==0){g=0;h=o;break a}else{j=p;k=p&255;l=n;m=o}}g=a[l]|0;h=m}}while(0);c=Jg(g&255|0)|0;g=c-(Jg(d[h]|0|0)|0)|0;i=e;return g|0}function yg(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;e=a[b]|0;f=a[c]|0;if(e<<24>>24!=f<<24>>24|e<<24>>24==0|f<<24>>24==0){g=e;h=f;j=g&255;k=h&255;l=j-k|0;i=d;return l|0}else{m=b;n=c}while(1){c=m+1|0;b=n+1|0;f=a[c]|0;e=a[b]|0;if(f<<24>>24!=e<<24>>24|f<<24>>24==0|e<<24>>24==0){g=f;h=e;break}else{m=c;n=b}}j=g&255;k=h&255;l=j-k|0;i=d;return l|0}function zg(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;if((e|0)==0){g=0;i=f;return g|0}h=a[b]|0;a:do{if(h<<24>>24==0){j=0;k=c}else{l=e;m=h;n=h&255;o=b;p=c;while(1){q=l+ -1|0;r=a[p]|0;if(r<<24>>24==0|(q|0)==0){j=m;k=p;break a}if(!(m<<24>>24==r<<24>>24)?(r=Jg(n|0)|0,(r|0)!=(Jg(d[p]|0|0)|0)):0){break}r=o+1|0;s=p+1|0;t=a[r]|0;if(t<<24>>24==0){j=0;k=s;break a}else{l=q;m=t;n=t&255;o=r;p=s}}j=a[o]|0;k=p}}while(0);c=Jg(j&255|0)|0;g=c-(Jg(d[k]|0|0)|0)|0;i=f;return g|0}function Ag(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;f=i;if((e|0)==0){g=0;i=f;return g|0}h=a[b]|0;a:do{if(h<<24>>24==0){j=0;k=c}else{l=e;m=h;n=b;o=c;while(1){p=l+ -1|0;q=a[o]|0;if(!((p|0)!=0&q<<24>>24!=0&m<<24>>24==q<<24>>24)){j=m;k=o;break a}q=n+1|0;r=o+1|0;s=a[q]|0;if(s<<24>>24==0){j=0;k=r;break}else{l=p;m=s;n=q;o=r}}}}while(0);g=(j&255)-(d[k]|0)|0;i=f;return g|0}function Bg(){}function Cg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=b-d>>>0;e=b-d-(c>>>0>a>>>0|0)>>>0;return(E=e,a-c>>>0|0)|0}function Dg(b){b=b|0;var c=0;c=b;while(a[c]|0){c=c+1|0}return c-b|0}function Eg(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0)>=20){d=d&255;g=b&3;h=d|d<<8|d<<16|d<<24;i=f&~3;if(g){g=b+4-g|0;while((b|0)<(g|0)){a[b]=d;b=b+1|0}}while((b|0)<(i|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b]=d;b=b+1|0}return b-e|0}function Fg(b,c){b=b|0;c=c|0;var d=0,e=0;d=b+(Dg(b)|0)|0;do{a[d+e|0]=a[c+e|0];e=e+1|0}while(a[c+(e-1)|0]|0);return b|0}function Gg(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b<>>32-c;return a<>>0;return(E=b+d+(e>>>0>>0|0)>>>0,e|0)|0}function Jg(a){a=a|0;if((a|0)<65)return a|0;if((a|0)>90)return a|0;return a-65+97|0}function Kg(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return Ga(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if((e|0)==0)return f|0;a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function Lg(b,c){b=b|0;c=c|0;var d=0;do{a[b+d|0]=a[c+d|0];d=d+1|0}while(a[c+(d-1)|0]|0);return b|0}function Mg(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b>>>c;return a>>>c|(b&(1<>>c-32|0}function Ng(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b>>c;return a>>>c|(b&(1<>c-32|0}function Og(b){b=b|0;var c=0;c=a[n+(b>>>24)|0]|0;if((c|0)<8)return c|0;c=a[n+(b>>16&255)|0]|0;if((c|0)<8)return c+8|0;c=a[n+(b>>8&255)|0]|0;if((c|0)<8)return c+16|0;return(a[n+(b&255)|0]|0)+24|0}function Pg(b){b=b|0;var c=0;c=a[m+(b&255)|0]|0;if((c|0)<8)return c|0;c=a[m+(b>>8&255)|0]|0;if((c|0)<8)return c+8|0;c=a[m+(b>>16&255)|0]|0;if((c|0)<8)return c+16|0;return(a[m+(b>>>24)|0]|0)+24|0}function Qg(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=a&65535;d=b&65535;e=aa(d,c)|0;f=a>>>16;a=(e>>>16)+(aa(d,f)|0)|0;d=b>>>16;b=aa(d,c)|0;return(E=(a>>>16)+(aa(d,f)|0)+(((a&65535)+b|0)>>>16)|0,a+b<<16|e&65535|0)|0}function Rg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;e=b>>31|((b|0)<0?-1:0)<<1;f=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;g=d>>31|((d|0)<0?-1:0)<<1;h=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;i=Cg(e^a,f^b,e,f)|0;b=E;a=g^e;e=h^f;f=Cg((Wg(i,b,Cg(g^c,h^d,g,h)|0,E,0)|0)^a,E^e,a,e)|0;return f|0}function Sg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+8|0;g=f|0;h=b>>31|((b|0)<0?-1:0)<<1;j=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;k=e>>31|((e|0)<0?-1:0)<<1;l=((e|0)<0?-1:0)>>31|((e|0)<0?-1:0)<<1;m=Cg(h^a,j^b,h,j)|0;b=E;Wg(m,b,Cg(k^d,l^e,k,l)|0,E,g)|0;l=Cg(c[g>>2]^h,c[g+4>>2]^j,h,j)|0;j=E;i=f;return(E=j,l)|0}function Tg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;a=c;c=Qg(e,a)|0;f=E;return(E=(aa(b,a)|0)+(aa(d,e)|0)+f|f&0,c|0|0)|0}function Ug(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=Wg(a,b,c,d,0)|0;return e|0}function Vg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=i;i=i+8|0;g=f|0;Wg(a,b,d,e,g)|0;i=f;return(E=c[g+4>>2]|0,c[g>>2]|0)|0}function Wg(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;g=a;h=b;i=h;j=d;k=e;l=k;if((i|0)==0){m=(f|0)!=0;if((l|0)==0){if(m){c[f>>2]=(g>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(g>>>0)/(j>>>0)>>>0;return(E=n,o)|0}else{if(!m){n=0;o=0;return(E=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;n=0;o=0;return(E=n,o)|0}}m=(l|0)==0;do{if((j|0)!=0){if(!m){p=(Og(l|0)|0)-(Og(i|0)|0)|0;if(p>>>0<=31){q=p+1|0;r=31-p|0;s=p-31>>31;t=q;u=g>>>(q>>>0)&s|i<>>(q>>>0)&s;w=0;x=g<>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return(E=n,o)|0}r=j-1|0;if((r&j|0)!=0){s=(Og(j|0)|0)+33-(Og(i|0)|0)|0;q=64-s|0;p=32-s|0;y=p>>31;z=s-32|0;A=z>>31;t=s;u=p-1>>31&i>>>(z>>>0)|(i<>>(s>>>0))&A;v=A&i>>>(s>>>0);w=g<>>(z>>>0))&y|g<>31;break}if((f|0)!=0){c[f>>2]=r&g;c[f+4>>2]=0}if((j|0)==1){n=h|b&0;o=a|0|0;return(E=n,o)|0}else{r=Pg(j|0)|0;n=i>>>(r>>>0)|0;o=i<<32-r|g>>>(r>>>0)|0;return(E=n,o)|0}}else{if(m){if((f|0)!=0){c[f>>2]=(i>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(i>>>0)/(j>>>0)>>>0;return(E=n,o)|0}if((g|0)==0){if((f|0)!=0){c[f>>2]=0;c[f+4>>2]=(i>>>0)%(l>>>0)}n=0;o=(i>>>0)/(l>>>0)>>>0;return(E=n,o)|0}r=l-1|0;if((r&l|0)==0){if((f|0)!=0){c[f>>2]=a|0;c[f+4>>2]=r&i|b&0}n=0;o=i>>>((Pg(l|0)|0)>>>0);return(E=n,o)|0}r=(Og(l|0)|0)-(Og(i|0)|0)|0;if(r>>>0<=30){s=r+1|0;p=31-r|0;t=s;u=i<>>(s>>>0);v=i>>>(s>>>0);w=0;x=g<>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return(E=n,o)|0}}while(0);if((t|0)==0){B=x;C=w;D=v;F=u;G=0;H=0}else{b=d|0|0;d=k|e&0;e=Ig(b,d,-1,-1)|0;k=E;h=x;x=w;w=v;v=u;u=t;t=0;while(1){I=x>>>31|h<<1;J=t|x<<1;a=v<<1|h>>>31|0;g=v>>>31|w<<1|0;Cg(e,k,a,g)|0;i=E;l=i>>31|((i|0)<0?-1:0)<<1;K=l&1;L=Cg(a,g,l&b,(((i|0)<0?-1:0)>>31|((i|0)<0?-1:0)<<1)&d)|0;M=E;i=u-1|0;if((i|0)==0){break}else{h=I;x=J;w=M;v=L;u=i;t=K}}B=I;C=J;D=M;F=L;G=0;H=K}K=C;C=0;if((f|0)!=0){c[f>>2]=F;c[f+4>>2]=D}n=(K|0)>>>31|(B|C)<<1|(C<<1|K>>>31)&0|G;o=(K<<1|0>>>31)&-2|H;return(E=n,o)|0}function Xg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return kb[a&1](b|0,c|0,d|0)|0}function Yg(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=d|0;e=e|0;f=f|0;return lb[a&63](+b,+c,d|0,e|0,f|0)|0}function Zg(a,b,c){a=a|0;b=b|0;c=c|0;mb[a&1](b|0,c|0)}function _g(a,b,c){a=a|0;b=b|0;c=c|0;return nb[a&7](b|0,c|0)|0}function $g(a,b,c){a=a|0;b=b|0;c=c|0;ba(0);return 0}function ah(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;ba(1);return 0}function bh(a,b){a=a|0;b=b|0;ba(2)}function ch(a,b){a=a|0;b=b|0;ba(3);return 0} + + + + +// EMSCRIPTEN_END_FUNCS +var kb=[$g,Xf];var lb=[ah,Ud,Vd,Xd,Yd,Zd,_d,$d,ae,de,ee,fe,ge,he,ie,je,ke,le,me,ne,oe,pe,qe,re,se,te,ue,ve,we,He,Ie,Je,Ke,Le,Me,Ne,Oe,Qd,Rd,Sd,Td,be,ce,xe,ye,ze,Ae,Be,Ce,De,Ee,Fe,Ge,ah,ah,ah,ah,ah,ah,ah,ah,ah,ah,ah];var mb=[bh,Yf];var nb=[ch,nf,of,pf,ef,ch,ch,ch];return{_strlen:Dg,_strcat:Fg,_gzread:xf,_wcsunits:Ib,_zscale:Lb,_initwcs:Eb,_wcssys:Hb,_pix2wcsstr:Fb,_calloc:ig,_bitshift64Shl:Gg,_gzwrite:Cf,_saostrtod:Kb,_strncpy:Hg,_memset:Eg,_memcpy:Kg,_gzclose:rf,_i64Subtract:Cg,_realloc:jg,_i64Add:Ig,_wcs2pixstr:Gb,_gzopen:sf,_gzseek:wf,_free:hg,_tolower:Jg,_malloc:gg,_reg2wcsstr:Jb,_strcpy:Lg,runPostSets:Bg,stackAlloc:ob,stackSave:pb,stackRestore:qb,setThrew:rb,setTempRet0:ub,setTempRet1:vb,setTempRet2:wb,setTempRet3:xb,setTempRet4:yb,setTempRet5:zb,setTempRet6:Ab,setTempRet7:Bb,setTempRet8:Cb,setTempRet9:Db,dynCall_iiii:Xg,dynCall_iddiii:Yg,dynCall_vii:Zg,dynCall_iii:_g}}) + + +// EMSCRIPTEN_END_ASM +({ "Math": Math, "Int8Array": Int8Array, "Int16Array": Int16Array, "Int32Array": Int32Array, "Uint8Array": Uint8Array, "Uint16Array": Uint16Array, "Uint32Array": Uint32Array, "Float32Array": Float32Array, "Float64Array": Float64Array }, { "abort": abort, "assert": assert, "asmPrintInt": asmPrintInt, "asmPrintFloat": asmPrintFloat, "min": Math_min, "invoke_iiii": invoke_iiii, "invoke_iddiii": invoke_iddiii, "invoke_vii": invoke_vii, "invoke_iii": invoke_iii, "_fabs": _fabs, "_sin": _sin, "_exp": _exp, "_llvm_pow_f64": _llvm_pow_f64, "_acos": _acos, "_atan2": _atan2, "_fmod": _fmod, "_lseek": _lseek, "__reallyNegative": __reallyNegative, "_asin": _asin, "_atan": _atan, "___buildEnvironment": ___buildEnvironment, "_fflush": _fflush, "_pwrite": _pwrite, "_strerror_r": _strerror_r, "_fprintf": _fprintf, "_open": _open, "_fabsf": _fabsf, "_sbrk": _sbrk, "_send": _send, "_snprintf": _snprintf, "_llvm_bswap_i32": _llvm_bswap_i32, "_emscripten_memcpy_big": _emscripten_memcpy_big, "_fileno": _fileno, "_sysconf": _sysconf, "___setErrNo": ___setErrNo, "_cos": _cos, "_pread": _pread, "_printf": _printf, "_sprintf": _sprintf, "_log": _log, "_toupper": _toupper, "_write": _write, "_isupper": _isupper, "___errno_location": ___errno_location, "_recv": _recv, "_tan": _tan, "_copysign": _copysign, "_getenv": _getenv, "_mkport": _mkport, "__exit": __exit, "_read": _read, "_abort": _abort, "_islower": _islower, "_fwrite": _fwrite, "_time": _time, "_isdigit": _isdigit, "_strerror": _strerror, "__formatString": __formatString, "_isspace": _isspace, "_sqrt": _sqrt, "_exit": _exit, "_close": _close, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "cttz_i8": cttz_i8, "ctlz_i8": ctlz_i8, "NaN": NaN, "Infinity": Infinity, "_stderr": _stderr }, buffer); +var _strlen = Module["_strlen"] = asm["_strlen"]; +var _strcat = Module["_strcat"] = asm["_strcat"]; +var _gzread = Module["_gzread"] = asm["_gzread"]; +var _wcsunits = Module["_wcsunits"] = asm["_wcsunits"]; +var _zscale = Module["_zscale"] = asm["_zscale"]; +var _initwcs = Module["_initwcs"] = asm["_initwcs"]; +var _wcssys = Module["_wcssys"] = asm["_wcssys"]; +var _pix2wcsstr = Module["_pix2wcsstr"] = asm["_pix2wcsstr"]; +var _calloc = Module["_calloc"] = asm["_calloc"]; +var _bitshift64Shl = Module["_bitshift64Shl"] = asm["_bitshift64Shl"]; +var _gzwrite = Module["_gzwrite"] = asm["_gzwrite"]; +var _saostrtod = Module["_saostrtod"] = asm["_saostrtod"]; +var _strncpy = Module["_strncpy"] = asm["_strncpy"]; +var _memset = Module["_memset"] = asm["_memset"]; +var _memcpy = Module["_memcpy"] = asm["_memcpy"]; +var _gzclose = Module["_gzclose"] = asm["_gzclose"]; +var _i64Subtract = Module["_i64Subtract"] = asm["_i64Subtract"]; +var _realloc = Module["_realloc"] = asm["_realloc"]; +var _i64Add = Module["_i64Add"] = asm["_i64Add"]; +var _wcs2pixstr = Module["_wcs2pixstr"] = asm["_wcs2pixstr"]; +var _gzopen = Module["_gzopen"] = asm["_gzopen"]; +var _gzseek = Module["_gzseek"] = asm["_gzseek"]; +var _free = Module["_free"] = asm["_free"]; +var _tolower = Module["_tolower"] = asm["_tolower"]; +var _malloc = Module["_malloc"] = asm["_malloc"]; +var _reg2wcsstr = Module["_reg2wcsstr"] = asm["_reg2wcsstr"]; +var _strcpy = Module["_strcpy"] = asm["_strcpy"]; +var runPostSets = Module["runPostSets"] = asm["runPostSets"]; +var dynCall_iiii = Module["dynCall_iiii"] = asm["dynCall_iiii"]; +var dynCall_iddiii = Module["dynCall_iddiii"] = asm["dynCall_iddiii"]; +var dynCall_vii = Module["dynCall_vii"] = asm["dynCall_vii"]; +var dynCall_iii = Module["dynCall_iii"] = asm["dynCall_iii"]; + +Runtime.stackAlloc = function(size) { return asm['stackAlloc'](size) }; +Runtime.stackSave = function() { return asm['stackSave']() }; +Runtime.stackRestore = function(top) { asm['stackRestore'](top) }; + + +// TODO: strip out parts of this we do not need + +//======= begin closure i64 code ======= + +// Copyright 2009 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Defines a Long class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "long". This + * implementation is derived from LongLib in GWT. + * + */ + +var i64Math = (function() { // Emscripten wrapper + var goog = { math: {} }; + + + /** + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @param {number} low The low (signed) 32 bits of the long. + * @param {number} high The high (signed) 32 bits of the long. + * @constructor + */ + goog.math.Long = function(low, high) { + /** + * @type {number} + * @private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @private + */ + this.high_ = high | 0; // force into 32 signed bits. + }; + + + // NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the + // from* methods on which they depend. + + + /** + * A cache of the Long representations of small integer values. + * @type {!Object} + * @private + */ + goog.math.Long.IntCache_ = {}; + + + /** + * Returns a Long representing the given (32-bit) integer value. + * @param {number} value The 32-bit integer in question. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = goog.math.Long.IntCache_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new goog.math.Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + goog.math.Long.IntCache_[value] = obj; + } + return obj; + }; + + + /** + * Returns a Long representing the given value, provided that it is a finite + * number. Otherwise, zero is returned. + * @param {number} value The number in question. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return goog.math.Long.ZERO; + } else if (value <= -goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MIN_VALUE; + } else if (value + 1 >= goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MAX_VALUE; + } else if (value < 0) { + return goog.math.Long.fromNumber(-value).negate(); + } else { + return new goog.math.Long( + (value % goog.math.Long.TWO_PWR_32_DBL_) | 0, + (value / goog.math.Long.TWO_PWR_32_DBL_) | 0); + } + }; + + + /** + * Returns a Long representing the 64-bit integer that comes by concatenating + * the given high and low bits. Each is assumed to use 32 bits. + * @param {number} lowBits The low 32-bits. + * @param {number} highBits The high 32-bits. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromBits = function(lowBits, highBits) { + return new goog.math.Long(lowBits, highBits); + }; + + + /** + * Returns a Long representation of the given string, written using the given + * radix. + * @param {string} str The textual representation of the Long. + * @param {number=} opt_radix The radix in which the text is written. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return goog.math.Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 8)); + + var result = goog.math.Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = goog.math.Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(goog.math.Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(goog.math.Long.fromNumber(value)); + } + } + return result; + }; + + + // NOTE: the compiler should inline these constant values below and then remove + // these variables, so there should be no runtime penalty for these. + + + /** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_16_DBL_ = 1 << 16; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_24_DBL_ = 1 << 24; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_32_DBL_ = + goog.math.Long.TWO_PWR_16_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_31_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ / 2; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_48_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_64_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_32_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_63_DBL_ = + goog.math.Long.TWO_PWR_64_DBL_ / 2; + + + /** @type {!goog.math.Long} */ + goog.math.Long.ZERO = goog.math.Long.fromInt(0); + + + /** @type {!goog.math.Long} */ + goog.math.Long.ONE = goog.math.Long.fromInt(1); + + + /** @type {!goog.math.Long} */ + goog.math.Long.NEG_ONE = goog.math.Long.fromInt(-1); + + + /** @type {!goog.math.Long} */ + goog.math.Long.MAX_VALUE = + goog.math.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + + + /** @type {!goog.math.Long} */ + goog.math.Long.MIN_VALUE = goog.math.Long.fromBits(0, 0x80000000 | 0); + + + /** + * @type {!goog.math.Long} + * @private + */ + goog.math.Long.TWO_PWR_24_ = goog.math.Long.fromInt(1 << 24); + + + /** @return {number} The value, assuming it is a 32-bit integer. */ + goog.math.Long.prototype.toInt = function() { + return this.low_; + }; + + + /** @return {number} The closest floating-point representation to this value. */ + goog.math.Long.prototype.toNumber = function() { + return this.high_ * goog.math.Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); + }; + + + /** + * @param {number=} opt_radix The radix in which the text should be written. + * @return {string} The textual representation of this value. + */ + goog.math.Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = goog.math.Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } + }; + + + /** @return {number} The high 32-bits as a signed value. */ + goog.math.Long.prototype.getHighBits = function() { + return this.high_; + }; + + + /** @return {number} The low 32-bits as a signed value. */ + goog.math.Long.prototype.getLowBits = function() { + return this.low_; + }; + + + /** @return {number} The low 32-bits as an unsigned value. */ + goog.math.Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : goog.math.Long.TWO_PWR_32_DBL_ + this.low_; + }; + + + /** + * @return {number} Returns the number of bits needed to represent the absolute + * value of this Long. + */ + goog.math.Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } + }; + + + /** @return {boolean} Whether this value is zero. */ + goog.math.Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; + }; + + + /** @return {boolean} Whether this value is negative. */ + goog.math.Long.prototype.isNegative = function() { + return this.high_ < 0; + }; + + + /** @return {boolean} Whether this value is odd. */ + goog.math.Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long equals the other. + */ + goog.math.Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long does not equal the other. + */ + goog.math.Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than the other. + */ + goog.math.Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than or equal to the other. + */ + goog.math.Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than the other. + */ + goog.math.Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than or equal to the other. + */ + goog.math.Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; + }; + + + /** + * Compares this Long with the given one. + * @param {goog.math.Long} other Long to compare against. + * @return {number} 0 if they are the same, 1 if the this is greater, and -1 + * if the given one is greater. + */ + goog.math.Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } + }; + + + /** @return {!goog.math.Long} The negation of this value. */ + goog.math.Long.prototype.negate = function() { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.MIN_VALUE; + } else { + return this.not().add(goog.math.Long.ONE); + } + }; + + + /** + * Returns the sum of this and the given Long. + * @param {goog.math.Long} other Long to add to this one. + * @return {!goog.math.Long} The sum of this and the given Long. + */ + goog.math.Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); + }; + + + /** + * Returns the difference of this and the given Long. + * @param {goog.math.Long} other Long to subtract from this. + * @return {!goog.math.Long} The difference of this and the given Long. + */ + goog.math.Long.prototype.subtract = function(other) { + return this.add(other.negate()); + }; + + + /** + * Returns the product of this and the given long. + * @param {goog.math.Long} other Long to multiply with this. + * @return {!goog.math.Long} The product of this and the other. + */ + goog.math.Long.prototype.multiply = function(other) { + if (this.isZero()) { + return goog.math.Long.ZERO; + } else if (other.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + return other.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return this.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both longs are small, use float multiplication + if (this.lessThan(goog.math.Long.TWO_PWR_24_) && + other.lessThan(goog.math.Long.TWO_PWR_24_)) { + return goog.math.Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); + }; + + + /** + * Returns this Long divided by the given one. + * @param {goog.math.Long} other Long by which to divide. + * @return {!goog.math.Long} This Long divided by the given one. + */ + goog.math.Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + if (other.equals(goog.math.Long.ONE) || + other.equals(goog.math.Long.NEG_ONE)) { + return goog.math.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(goog.math.Long.ZERO)) { + return other.isNegative() ? goog.math.Long.ONE : goog.math.Long.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = goog.math.Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = goog.math.Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = goog.math.Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = goog.math.Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; + }; + + + /** + * Returns this Long modulo the given one. + * @param {goog.math.Long} other Long by which to mod. + * @return {!goog.math.Long} This Long modulo the given one. + */ + goog.math.Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); + }; + + + /** @return {!goog.math.Long} The bitwise-NOT of this value. */ + goog.math.Long.prototype.not = function() { + return goog.math.Long.fromBits(~this.low_, ~this.high_); + }; + + + /** + * Returns the bitwise-AND of this Long and the given one. + * @param {goog.math.Long} other The Long with which to AND. + * @return {!goog.math.Long} The bitwise-AND of this and the other. + */ + goog.math.Long.prototype.and = function(other) { + return goog.math.Long.fromBits(this.low_ & other.low_, + this.high_ & other.high_); + }; + + + /** + * Returns the bitwise-OR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to OR. + * @return {!goog.math.Long} The bitwise-OR of this and the other. + */ + goog.math.Long.prototype.or = function(other) { + return goog.math.Long.fromBits(this.low_ | other.low_, + this.high_ | other.high_); + }; + + + /** + * Returns the bitwise-XOR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to XOR. + * @return {!goog.math.Long} The bitwise-XOR of this and the other. + */ + goog.math.Long.prototype.xor = function(other) { + return goog.math.Long.fromBits(this.low_ ^ other.low_, + this.high_ ^ other.high_); + }; + + + /** + * Returns this Long with bits shifted to the left by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the left by the given amount. + */ + goog.math.Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return goog.math.Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return goog.math.Long.fromBits(0, low << (numBits - 32)); + } + } + }; + + + /** + * Returns this Long with bits shifted to the right by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount. + */ + goog.math.Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return goog.math.Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } + }; + + + /** + * Returns this Long with bits shifted to the right by the given amount, with + * the new top bits matching the current sign bit. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount, with + * zeros placed into the new leading bits. + */ + goog.math.Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return goog.math.Long.fromBits(high, 0); + } else { + return goog.math.Long.fromBits(high >>> (numBits - 32), 0); + } + } + }; + + //======= begin jsbn ======= + + var navigator = { appName: 'Modern Browser' }; // polyfill a little + + // Copyright (c) 2005 Tom Wu + // All Rights Reserved. + // http://www-cs-students.stanford.edu/~tjw/jsbn/ + + /* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ + + // Basic JavaScript BN library - subset useful for RSA encryption. + + // Bits per digit + var dbits; + + // JavaScript engine analysis + var canary = 0xdeadbeefcafe; + var j_lm = ((canary&0xffffff)==0xefcafe); + + // (public) Constructor + function BigInteger(a,b,c) { + if(a != null) + if("number" == typeof a) this.fromNumber(a,b,c); + else if(b == null && "string" != typeof a) this.fromString(a,256); + else this.fromString(a,b); + } + + // return new, unset BigInteger + function nbi() { return new BigInteger(null); } + + // am: Compute w_j += (x*this_i), propagate carries, + // c is initial carry, returns final carry. + // c < 3*dvalue, x < 2*dvalue, this_i < dvalue + // We need to select the fastest one that works in this environment. + + // am1: use a single mult and divide to get the high bits, + // max digit bits should be 26 because + // max internal value = 2*dvalue^2-2*dvalue (< 2^53) + function am1(i,x,w,j,c,n) { + while(--n >= 0) { + var v = x*this[i++]+w[j]+c; + c = Math.floor(v/0x4000000); + w[j++] = v&0x3ffffff; + } + return c; + } + // am2 avoids a big mult-and-extract completely. + // Max digit bits should be <= 30 because we do bitwise ops + // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) + function am2(i,x,w,j,c,n) { + var xl = x&0x7fff, xh = x>>15; + while(--n >= 0) { + var l = this[i]&0x7fff; + var h = this[i++]>>15; + var m = xh*l+h*xl; + l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); + c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); + w[j++] = l&0x3fffffff; + } + return c; + } + // Alternately, set max digit bits to 28 since some + // browsers slow down when dealing with 32-bit numbers. + function am3(i,x,w,j,c,n) { + var xl = x&0x3fff, xh = x>>14; + while(--n >= 0) { + var l = this[i]&0x3fff; + var h = this[i++]>>14; + var m = xh*l+h*xl; + l = xl*l+((m&0x3fff)<<14)+w[j]+c; + c = (l>>28)+(m>>14)+xh*h; + w[j++] = l&0xfffffff; + } + return c; + } + if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { + BigInteger.prototype.am = am2; + dbits = 30; + } + else if(j_lm && (navigator.appName != "Netscape")) { + BigInteger.prototype.am = am1; + dbits = 26; + } + else { // Mozilla/Netscape seems to prefer am3 + BigInteger.prototype.am = am3; + dbits = 28; + } + + BigInteger.prototype.DB = dbits; + BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; + r.t = this.t; + r.s = this.s; + } + + // (protected) set from integer value x, -DV <= x < DV + function bnpFromInt(x) { + this.t = 1; + this.s = (x<0)?-1:0; + if(x > 0) this[0] = x; + else if(x < -1) this[0] = x+DV; + else this.t = 0; + } + + // return bigint initialized to value + function nbv(i) { var r = nbi(); r.fromInt(i); return r; } + + // (protected) set from string and radix + function bnpFromString(s,b) { + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 256) k = 8; // byte array + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else { this.fromRadix(s,b); return; } + this.t = 0; + this.s = 0; + var i = s.length, mi = false, sh = 0; + while(--i >= 0) { + var x = (k==8)?s[i]&0xff:intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if(sh == 0) + this[this.t++] = x; + else if(sh+k > this.DB) { + this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); + } + else + this[this.t-1] |= x<= this.DB) sh -= this.DB; + } + if(k == 8 && (s[0]&0x80) != 0) { + this.s = -1; + if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; + } + + // (public) return string representation in given radix + function bnToString(b) { + if(this.s < 0) return "-"+this.negate().toString(b); + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else return this.toRadix(b); + var km = (1< 0) { + if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } + while(i >= 0) { + if(p < k) { + d = (this[i]&((1<>(p+=this.DB-k); + } + else { + d = (this[i]>>(p-=k))&km; + if(p <= 0) { p += this.DB; --i; } + } + if(d > 0) m = true; + if(m) r += int2char(d); + } + } + return m?r:"0"; + } + + // (public) -this + function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } + + // (public) |this| + function bnAbs() { return (this.s<0)?this.negate():this; } + + // (public) return + if this > a, - if this < a, 0 if equal + function bnCompareTo(a) { + var r = this.s-a.s; + if(r != 0) return r; + var i = this.t; + r = i-a.t; + if(r != 0) return (this.s<0)?-r:r; + while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; + return 0; + } + + // returns bit length of the integer x + function nbits(x) { + var r = 1, t; + if((t=x>>>16) != 0) { x = t; r += 16; } + if((t=x>>8) != 0) { x = t; r += 8; } + if((t=x>>4) != 0) { x = t; r += 4; } + if((t=x>>2) != 0) { x = t; r += 2; } + if((t=x>>1) != 0) { x = t; r += 1; } + return r; + } + + // (public) return the number of bits in "this" + function bnBitLength() { + if(this.t <= 0) return 0; + return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); + } + + // (protected) r = this << n*DB + function bnpDLShiftTo(n,r) { + var i; + for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; + for(i = n-1; i >= 0; --i) r[i] = 0; + r.t = this.t+n; + r.s = this.s; + } + + // (protected) r = this >> n*DB + function bnpDRShiftTo(n,r) { + for(var i = n; i < this.t; ++i) r[i-n] = this[i]; + r.t = Math.max(this.t-n,0); + r.s = this.s; + } + + // (protected) r = this << n + function bnpLShiftTo(n,r) { + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<= 0; --i) { + r[i+ds+1] = (this[i]>>cbs)|c; + c = (this[i]&bm)<= 0; --i) r[i] = 0; + r[ds] = c; + r.t = this.t+ds+1; + r.s = this.s; + r.clamp(); + } + + // (protected) r = this >> n + function bnpRShiftTo(n,r) { + r.s = this.s; + var ds = Math.floor(n/this.DB); + if(ds >= this.t) { r.t = 0; return; } + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<>bs; + for(var i = ds+1; i < this.t; ++i) { + r[i-ds-1] |= (this[i]&bm)<>bs; + } + if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; + } + if(a.t < this.t) { + c -= a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c -= a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c<0)?-1:0; + if(c < -1) r[i++] = this.DV+c; + else if(c > 0) r[i++] = c; + r.t = i; + r.clamp(); + } + + // (protected) r = this * a, r != this,a (HAC 14.12) + // "this" should be the larger one if appropriate. + function bnpMultiplyTo(a,r) { + var x = this.abs(), y = a.abs(); + var i = x.t; + r.t = i+y.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); + r.s = 0; + r.clamp(); + if(this.s != a.s) BigInteger.ZERO.subTo(r,r); + } + + // (protected) r = this^2, r != this (HAC 14.16) + function bnpSquareTo(r) { + var x = this.abs(); + var i = r.t = 2*x.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < x.t-1; ++i) { + var c = x.am(i,x[i],r,2*i,0,1); + if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { + r[i+x.t] -= x.DV; + r[i+x.t+1] = 1; + } + } + if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); + r.s = 0; + r.clamp(); + } + + // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) + // r != q, this != m. q or r may be null. + function bnpDivRemTo(m,q,r) { + var pm = m.abs(); + if(pm.t <= 0) return; + var pt = this.abs(); + if(pt.t < pm.t) { + if(q != null) q.fromInt(0); + if(r != null) this.copyTo(r); + return; + } + if(r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus + if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } + else { pm.copyTo(y); pt.copyTo(r); } + var ys = y.t; + var y0 = y[ys-1]; + if(y0 == 0) return; + var yt = y0*(1<1)?y[ys-2]>>this.F2:0); + var d1 = this.FV/yt, d2 = (1<= 0) { + r[r.t++] = 1; + r.subTo(t,r); + } + BigInteger.ONE.dlShiftTo(ys,t); + t.subTo(y,y); // "negative" y so we can replace sub with am later + while(y.t < ys) y[y.t++] = 0; + while(--j >= 0) { + // Estimate quotient digit + var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); + if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out + y.dlShiftTo(j,t); + r.subTo(t,r); + while(r[i] < --qd) r.subTo(t,r); + } + } + if(q != null) { + r.drShiftTo(ys,q); + if(ts != ms) BigInteger.ZERO.subTo(q,q); + } + r.t = ys; + r.clamp(); + if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder + if(ts < 0) BigInteger.ZERO.subTo(r,r); + } + + // (public) this mod a + function bnMod(a) { + var r = nbi(); + this.abs().divRemTo(a,null,r); + if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); + return r; + } + + // Modular reduction using "classic" algorithm + function Classic(m) { this.m = m; } + function cConvert(x) { + if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; + } + function cRevert(x) { return x; } + function cReduce(x) { x.divRemTo(this.m,null,x); } + function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + Classic.prototype.convert = cConvert; + Classic.prototype.revert = cRevert; + Classic.prototype.reduce = cReduce; + Classic.prototype.mulTo = cMulTo; + Classic.prototype.sqrTo = cSqrTo; + + // (protected) return "-1/this % 2^DB"; useful for Mont. reduction + // justification: + // xy == 1 (mod m) + // xy = 1+km + // xy(2-xy) = (1+km)(1-km) + // x[y(2-xy)] = 1-k^2m^2 + // x[y(2-xy)] == 1 (mod m^2) + // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 + // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. + // JS multiply "overflows" differently from C/C++, so care is needed here. + function bnpInvDigit() { + if(this.t < 1) return 0; + var x = this[0]; + if((x&1) == 0) return 0; + var y = x&3; // y == 1/x mod 2^2 + y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 + y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 + y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y>0)?this.DV-y:-y; + } + + // Montgomery reduction + function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp&0x7fff; + this.mph = this.mp>>15; + this.um = (1<<(m.DB-15))-1; + this.mt2 = 2*m.t; + } + + // xR mod m + function montConvert(x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t,r); + r.divRemTo(this.m,null,r); + if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); + return r; + } + + // x/R mod m + function montRevert(x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + + // x = x/R mod m (HAC 14.32) + function montReduce(x) { + while(x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0; + for(var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i]&0x7fff; + var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; + // use am to combine the multiply-shift-add into one call + j = i+this.m.t; + x[j] += this.m.am(0,u0,x,i,0,this.m.t); + // propagate carry + while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } + } + x.clamp(); + x.drShiftTo(this.m.t,x); + if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); + } + + // r = "x^2/R mod m"; x != r + function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + // r = "xy/R mod m"; x,y != r + function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + + Montgomery.prototype.convert = montConvert; + Montgomery.prototype.revert = montRevert; + Montgomery.prototype.reduce = montReduce; + Montgomery.prototype.mulTo = montMulTo; + Montgomery.prototype.sqrTo = montSqrTo; + + // (protected) true iff this is even + function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } + + // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) + function bnpExp(e,z) { + if(e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; + g.copyTo(r); + while(--i >= 0) { + z.sqrTo(r,r2); + if((e&(1< 0) z.mulTo(r2,g,r); + else { var t = r; r = r2; r2 = t; } + } + return z.revert(r); + } + + // (public) this^e % m, 0 <= e < 2^32 + function bnModPowInt(e,m) { + var z; + if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e,z); + } + + // protected + BigInteger.prototype.copyTo = bnpCopyTo; + BigInteger.prototype.fromInt = bnpFromInt; + BigInteger.prototype.fromString = bnpFromString; + BigInteger.prototype.clamp = bnpClamp; + BigInteger.prototype.dlShiftTo = bnpDLShiftTo; + BigInteger.prototype.drShiftTo = bnpDRShiftTo; + BigInteger.prototype.lShiftTo = bnpLShiftTo; + BigInteger.prototype.rShiftTo = bnpRShiftTo; + BigInteger.prototype.subTo = bnpSubTo; + BigInteger.prototype.multiplyTo = bnpMultiplyTo; + BigInteger.prototype.squareTo = bnpSquareTo; + BigInteger.prototype.divRemTo = bnpDivRemTo; + BigInteger.prototype.invDigit = bnpInvDigit; + BigInteger.prototype.isEven = bnpIsEven; + BigInteger.prototype.exp = bnpExp; + + // public + BigInteger.prototype.toString = bnToString; + BigInteger.prototype.negate = bnNegate; + BigInteger.prototype.abs = bnAbs; + BigInteger.prototype.compareTo = bnCompareTo; + BigInteger.prototype.bitLength = bnBitLength; + BigInteger.prototype.mod = bnMod; + BigInteger.prototype.modPowInt = bnModPowInt; + + // "constants" + BigInteger.ZERO = nbv(0); + BigInteger.ONE = nbv(1); + + // jsbn2 stuff + + // (protected) convert from radix string + function bnpFromRadix(s,b) { + this.fromInt(0); + if(b == null) b = 10; + var cs = this.chunkSize(b); + var d = Math.pow(b,cs), mi = false, j = 0, w = 0; + for(var i = 0; i < s.length; ++i) { + var x = intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-" && this.signum() == 0) mi = true; + continue; + } + w = b*w+x; + if(++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w,0); + j = 0; + w = 0; + } + } + if(j > 0) { + this.dMultiply(Math.pow(b,j)); + this.dAddOffset(w,0); + } + if(mi) BigInteger.ZERO.subTo(this,this); + } + + // (protected) return x s.t. r^x < DV + function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } + + // (public) 0 if this == 0, 1 if this > 0 + function bnSigNum() { + if(this.s < 0) return -1; + else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; + else return 1; + } + + // (protected) this *= n, this >= 0, 1 < n < DV + function bnpDMultiply(n) { + this[this.t] = this.am(0,n-1,this,0,0,this.t); + ++this.t; + this.clamp(); + } + + // (protected) this += n << w words, this >= 0 + function bnpDAddOffset(n,w) { + if(n == 0) return; + while(this.t <= w) this[this.t++] = 0; + this[w] += n; + while(this[w] >= this.DV) { + this[w] -= this.DV; + if(++w >= this.t) this[this.t++] = 0; + ++this[w]; + } + } + + // (protected) convert to radix string + function bnpToRadix(b) { + if(b == null) b = 10; + if(this.signum() == 0 || b < 2 || b > 36) return "0"; + var cs = this.chunkSize(b); + var a = Math.pow(b,cs); + var d = nbv(a), y = nbi(), z = nbi(), r = ""; + this.divRemTo(d,y,z); + while(y.signum() > 0) { + r = (a+z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d,y,z); + } + return z.intValue().toString(b) + r; + } + + // (public) return value as integer + function bnIntValue() { + if(this.s < 0) { + if(this.t == 1) return this[0]-this.DV; + else if(this.t == 0) return -1; + } + else if(this.t == 1) return this[0]; + else if(this.t == 0) return 0; + // assumes 16 < DB < 32 + return ((this[1]&((1<<(32-this.DB))-1))<>= this.DB; + } + if(a.t < this.t) { + c += a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c += a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += a.s; + } + r.s = (c<0)?-1:0; + if(c > 0) r[i++] = c; + else if(c < -1) r[i++] = this.DV+c; + r.t = i; + r.clamp(); + } + + BigInteger.prototype.fromRadix = bnpFromRadix; + BigInteger.prototype.chunkSize = bnpChunkSize; + BigInteger.prototype.signum = bnSigNum; + BigInteger.prototype.dMultiply = bnpDMultiply; + BigInteger.prototype.dAddOffset = bnpDAddOffset; + BigInteger.prototype.toRadix = bnpToRadix; + BigInteger.prototype.intValue = bnIntValue; + BigInteger.prototype.addTo = bnpAddTo; + + //======= end jsbn ======= + + // Emscripten wrapper + var Wrapper = { + abs: function(l, h) { + var x = new goog.math.Long(l, h); + var ret; + if (x.isNegative()) { + ret = x.negate(); + } else { + ret = x; + } + HEAP32[tempDoublePtr>>2] = ret.low_; + HEAP32[tempDoublePtr+4>>2] = ret.high_; + }, + ensureTemps: function() { + if (Wrapper.ensuredTemps) return; + Wrapper.ensuredTemps = true; + Wrapper.two32 = new BigInteger(); + Wrapper.two32.fromString('4294967296', 10); + Wrapper.two64 = new BigInteger(); + Wrapper.two64.fromString('18446744073709551616', 10); + Wrapper.temp1 = new BigInteger(); + Wrapper.temp2 = new BigInteger(); + }, + lh2bignum: function(l, h) { + var a = new BigInteger(); + a.fromString(h.toString(), 10); + var b = new BigInteger(); + a.multiplyTo(Wrapper.two32, b); + var c = new BigInteger(); + c.fromString(l.toString(), 10); + var d = new BigInteger(); + c.addTo(b, d); + return d; + }, + stringify: function(l, h, unsigned) { + var ret = new goog.math.Long(l, h).toString(); + if (unsigned && ret[0] == '-') { + // unsign slowly using jsbn bignums + Wrapper.ensureTemps(); + var bignum = new BigInteger(); + bignum.fromString(ret, 10); + ret = new BigInteger(); + Wrapper.two64.addTo(bignum, ret); + ret = ret.toString(10); + } + return ret; + }, + fromString: function(str, base, min, max, unsigned) { + Wrapper.ensureTemps(); + var bignum = new BigInteger(); + bignum.fromString(str, base); + var bigmin = new BigInteger(); + bigmin.fromString(min, 10); + var bigmax = new BigInteger(); + bigmax.fromString(max, 10); + if (unsigned && bignum.compareTo(BigInteger.ZERO) < 0) { + var temp = new BigInteger(); + bignum.addTo(Wrapper.two64, temp); + bignum = temp; + } + var error = false; + if (bignum.compareTo(bigmin) < 0) { + bignum = bigmin; + error = true; + } else if (bignum.compareTo(bigmax) > 0) { + bignum = bigmax; + error = true; + } + var ret = goog.math.Long.fromString(bignum.toString()); // min-max checks should have clamped this to a range goog.math.Long can handle well + HEAP32[tempDoublePtr>>2] = ret.low_; + HEAP32[tempDoublePtr+4>>2] = ret.high_; + if (error) throw 'range error'; + } + }; + return Wrapper; +})(); + +//======= end closure i64 code ======= + + + +// === Auto-generated postamble setup entry stuff === + +if (memoryInitializer) { + if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) { + var data = Module['readBinary'](memoryInitializer); + HEAPU8.set(data, STATIC_BASE); + } else { + addRunDependency('memory initializer'); + Browser.asyncLoad(memoryInitializer, function(data) { + HEAPU8.set(data, STATIC_BASE); + removeRunDependency('memory initializer'); + }, function(data) { + throw 'could not load memory initializer ' + memoryInitializer; + }); + } +} + +function ExitStatus(status) { + this.name = "ExitStatus"; + this.message = "Program terminated with exit(" + status + ")"; + this.status = status; +}; +ExitStatus.prototype = new Error(); +ExitStatus.prototype.constructor = ExitStatus; + +var initialStackTop; +var preloadStartTime = null; +var calledMain = false; + +dependenciesFulfilled = function runCaller() { + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!Module['calledRun'] && shouldRunNow) run(); + if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled +} + +Module['callMain'] = Module.callMain = function callMain(args) { + assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)'); + assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called'); + + args = args || []; + + ensureInitRuntime(); + + var argc = args.length+1; + function pad() { + for (var i = 0; i < 4-1; i++) { + argv.push(0); + } + } + var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL) ]; + pad(); + for (var i = 0; i < argc-1; i = i + 1) { + argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL)); + pad(); + } + argv.push(0); + argv = allocate(argv, 'i32', ALLOC_NORMAL); + + initialStackTop = STACKTOP; + + try { + + var ret = Module['_main'](argc, argv, 0); + + + // if we're not running an evented main loop, it's time to exit + if (!Module['noExitRuntime']) { + exit(ret); + } + } + catch(e) { + if (e instanceof ExitStatus) { + // exit() throws this once it's done to make sure execution + // has been stopped completely + return; + } else if (e == 'SimulateInfiniteLoop') { + // running an evented main loop, don't immediately exit + Module['noExitRuntime'] = true; + return; + } else { + if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]); + throw e; + } + } finally { + calledMain = true; + } +} + + + + +function run(args) { + args = args || Module['arguments']; + + if (preloadStartTime === null) preloadStartTime = Date.now(); + + if (runDependencies > 0) { + Module.printErr('run() called, but dependencies remain, so not running'); + return; + } + + preRun(); + + if (runDependencies > 0) return; // a preRun added a dependency, run will be called later + if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame + + function doRun() { + if (Module['calledRun']) return; // run may have just been called while the async setStatus time below was happening + Module['calledRun'] = true; + + ensureInitRuntime(); + + preMain(); + + if (ENVIRONMENT_IS_WEB && preloadStartTime !== null) { + Module.printErr('pre-main prep time: ' + (Date.now() - preloadStartTime) + ' ms'); + } + + if (Module['_main'] && shouldRunNow) { + Module['callMain'](args); + } + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + if (!ABORT) doRun(); + }, 1); + } else { + doRun(); + } +} +Module['run'] = Module.run = run; + +function exit(status) { + ABORT = true; + EXITSTATUS = status; + STACKTOP = initialStackTop; + + // exit the runtime + exitRuntime(); + + // TODO We should handle this differently based on environment. + // In the browser, the best we can do is throw an exception + // to halt execution, but in node we could process.exit and + // I'd imagine SM shell would have something equivalent. + // This would let us set a proper exit status (which + // would be great for checking test exit statuses). + // https://github.com/kripken/emscripten/issues/1371 + + // throw an exception to halt the current execution + throw new ExitStatus(status); +} +Module['exit'] = Module.exit = exit; + +function abort(text) { + if (text) { + Module.print(text); + Module.printErr(text); + } + + ABORT = true; + EXITSTATUS = 1; + + var extra = '\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.'; + + throw 'abort() at ' + stackTrace() + extra; +} +Module['abort'] = Module.abort = abort; + +// {{PRE_RUN_ADDITIONS}} + +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} + +// shouldRunNow refers to calling main(), not run(). +var shouldRunNow = true; +if (Module['noInitialRun']) { + shouldRunNow = false; +} + + +run(); + +// {{POST_RUN_ADDITIONS}} + + + + + + +// {{MODULE_ADDITIONS}} + + + + + +Module['arrfile'] = function(filename, arr) { + try{ FS.unlink("/" + filename); } + catch(e){ ; } + FS.createDataFile("/", filename, arr, true, true); + return {path: filename, size: arr.byteLength}; +}; + +Module['gzcompress'] = function(data) { // TODO: Accept strings + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['output.gz', 'wb']); + var buffer = _malloc(data.length); + HEAPU8.set(data, buffer); + ccall('gzwrite', 'number', ['number', 'number', 'number'], [gzFile, buffer, data.length]); + ccall('gzclose', 'number', ['number'], [gzFile]); + _free(buffer); + var ret = new Uint8Array(FS.root.contents['output.gz'].contents); + FS.unlink('output.gz'); + return ret; +}; + +Module['gzdecompress'] = function(data) { + var BUFSIZE = 1024*1024; + FS.createDataFile('/', 'input.gz', data, true, true); + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['input.gz', 'rb']); + var buffer = _malloc(BUFSIZE); + var chunks = []; + var total = 0; + var len; + while( (len = ccall('gzread', 'number', ['number', 'number', 'number'], [gzFile, buffer, BUFSIZE])) > 0) { + chunks.push(new Uint8Array(len)); + chunks[chunks.length-1].set(HEAPU8.subarray(buffer, buffer+len)); + total += len; + } + ccall('gzclose', 'number', ['number'], [gzFile]); + FS.unlink('input.gz'); + _free(buffer); + var ret = new Uint8Array(total); + var curr = 0; + for (var i = 0; i < chunks.length; i++) { + ret.set(chunks[i], curr); + curr += chunks[i].length; + } + return ret; +}; + + + + return { + initwcs: Module.cwrap('initwcs', 'number', ['string', 'number']), + wcssys: Module.cwrap('wcssys', 'string', ['number', 'string']), + wcsunits: Module.cwrap('wcsunits', 'string', ['number', 'string']), + pix2wcs: Module.cwrap('pix2wcsstr', 'string', ['number', 'number', 'number']), + wcs2pix: Module.cwrap('wcs2pixstr', 'string', ['number', 'number', 'number']), + reg2wcs: Module.cwrap('reg2wcsstr', 'string', ['number', 'string']), + saostrtod: Module.cwrap('saostrtod', 'number', ['string']), + zscale: Module.cwrap('zscale', 'string', ['number', 'number', 'number', 'number', 'number', 'number']), + arrfile: Module["arrfile"], + gzopen: Module.cwrap('gzopen', 'number', ['string', 'string']), + gzread: Module.cwrap('gzread', 'number', ['number', 'number', 'number']), + gzwrite: Module.cwrap('gzwrite', 'number', ['number', 'number', 'number']), + gzclose: Module.cwrap('gzclose', 'number', ['number']), + gzseek: Module.cwrap('gzseek', 'number', ['number', 'number', 'number']), + compress: Module['gzcompress'], + decompress: Module['gzdecompress'] + }; +})(); + diff --git a/astroem/astroem.raw.js b/astroem/astroem.raw.js new file mode 100644 index 00000000..33934960 --- /dev/null +++ b/astroem/astroem.raw.js @@ -0,0 +1,7911 @@ + +var Module = { + 'noExitRuntime': true +}; + + +// The Module object: Our interface to the outside world. We import +// and export values on it, and do the work to get that through +// closure compiler if necessary. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to do an eval in order to handle the closure compiler +// case, where this code here is minified but Module was defined +// elsewhere (e.g. case 4 above). We also need to check if Module +// already exists (e.g. case 3 above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module; +if (!Module) Module = (typeof Module !== 'undefined' ? Module : null) || {}; + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. +var moduleOverrides = {}; +for (var key in Module) { + if (Module.hasOwnProperty(key)) { + moduleOverrides[key] = Module[key]; + } +} + +// The environment setup code below is customized to use Module. +// *** Environment setup code *** +var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function'; +var ENVIRONMENT_IS_WEB = typeof window === 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + +if (ENVIRONMENT_IS_NODE) { + // Expose functionality in the same simple way that the shells work + // Note that we pollute the global namespace here, otherwise we break in node + if (!Module['print']) Module['print'] = function print(x) { + process['stdout'].write(x + '\n'); + }; + if (!Module['printErr']) Module['printErr'] = function printErr(x) { + process['stderr'].write(x + '\n'); + }; + + var nodeFS = require('fs'); + var nodePath = require('path'); + + Module['read'] = function read(filename, binary) { + filename = nodePath['normalize'](filename); + var ret = nodeFS['readFileSync'](filename); + // The path is absolute if the normalized version is the same as the resolved. + if (!ret && filename != nodePath['resolve'](filename)) { + filename = path.join(__dirname, '..', 'src', filename); + ret = nodeFS['readFileSync'](filename); + } + if (ret && !binary) ret = ret.toString(); + return ret; + }; + + Module['readBinary'] = function readBinary(filename) { return Module['read'](filename, true) }; + + Module['load'] = function load(f) { + globalEval(read(f)); + }; + + Module['arguments'] = process['argv'].slice(2); + + module['exports'] = Module; +} +else if (ENVIRONMENT_IS_SHELL) { + if (!Module['print']) Module['print'] = print; + if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm + + if (typeof read != 'undefined') { + Module['read'] = read; + } else { + Module['read'] = function read() { throw 'no read() available (jsc?)' }; + } + + Module['readBinary'] = function readBinary(f) { + return read(f, 'binary'); + }; + + if (typeof scriptArgs != 'undefined') { + Module['arguments'] = scriptArgs; + } else if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + + this['Module'] = Module; + + eval("if (typeof gc === 'function' && gc.toString().indexOf('[native code]') > 0) var gc = undefined"); // wipe out the SpiderMonkey shell 'gc' function, which can confuse closure (uses it as a minified name, and it is then initted to a non-falsey value unexpectedly) +} +else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + Module['read'] = function read(url) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + }; + + if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + + if (typeof console !== 'undefined') { + if (!Module['print']) Module['print'] = function print(x) { + console.log(x); + }; + if (!Module['printErr']) Module['printErr'] = function printErr(x) { + console.log(x); + }; + } else { + // Probably a worker, and without console.log. We can do very little here... + var TRY_USE_DUMP = false; + if (!Module['print']) Module['print'] = (TRY_USE_DUMP && (typeof(dump) !== "undefined") ? (function(x) { + dump(x); + }) : (function(x) { + // self.postMessage(x); // enable this if you want stdout to be sent as messages + })); + } + + if (ENVIRONMENT_IS_WEB) { + window['Module'] = Module; + } else { + Module['load'] = importScripts; + } +} +else { + // Unreachable because SHELL is dependant on the others + throw 'Unknown runtime environment. Where are we?'; +} + +function globalEval(x) { + eval.call(null, x); +} +if (!Module['load'] == 'undefined' && Module['read']) { + Module['load'] = function load(f) { + globalEval(Module['read'](f)); + }; +} +if (!Module['print']) { + Module['print'] = function(){}; +} +if (!Module['printErr']) { + Module['printErr'] = Module['print']; +} +if (!Module['arguments']) { + Module['arguments'] = []; +} +// *** Environment setup code *** + +// Closure helpers +Module.print = Module['print']; +Module.printErr = Module['printErr']; + +// Callbacks +Module['preRun'] = []; +Module['postRun'] = []; + +// Merge back in the overrides +for (var key in moduleOverrides) { + if (moduleOverrides.hasOwnProperty(key)) { + Module[key] = moduleOverrides[key]; + } +} + + + +// === Auto-generated preamble library stuff === + +//======================================== +// Runtime code shared with compiler +//======================================== + +var Runtime = { + stackSave: function () { + return STACKTOP; + }, + stackRestore: function (stackTop) { + STACKTOP = stackTop; + }, + forceAlign: function (target, quantum) { + quantum = quantum || 4; + if (quantum == 1) return target; + if (isNumber(target) && isNumber(quantum)) { + return Math.ceil(target/quantum)*quantum; + } else if (isNumber(quantum) && isPowerOfTwo(quantum)) { + return '(((' +target + ')+' + (quantum-1) + ')&' + -quantum + ')'; + } + return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum; + }, + isNumberType: function (type) { + return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES; + }, + isPointerType: function isPointerType(type) { + return type[type.length-1] == '*'; +}, + isStructType: function isStructType(type) { + if (isPointerType(type)) return false; + if (isArrayType(type)) return true; + if (/?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types + // See comment in isStructPointerType() + return type[0] == '%'; +}, + INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0}, + FLOAT_TYPES: {"float":0,"double":0}, + or64: function (x, y) { + var l = (x | 0) | (y | 0); + var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + and64: function (x, y) { + var l = (x | 0) & (y | 0); + var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + xor64: function (x, y) { + var l = (x | 0) ^ (y | 0); + var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + getNativeTypeSize: function (type) { + switch (type) { + case 'i1': case 'i8': return 1; + case 'i16': return 2; + case 'i32': return 4; + case 'i64': return 8; + case 'float': return 4; + case 'double': return 8; + default: { + if (type[type.length-1] === '*') { + return Runtime.QUANTUM_SIZE; // A pointer + } else if (type[0] === 'i') { + var bits = parseInt(type.substr(1)); + assert(bits % 8 === 0); + return bits/8; + } else { + return 0; + } + } + } + }, + getNativeFieldSize: function (type) { + return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE); + }, + dedup: function dedup(items, ident) { + var seen = {}; + if (ident) { + return items.filter(function(item) { + if (seen[item[ident]]) return false; + seen[item[ident]] = true; + return true; + }); + } else { + return items.filter(function(item) { + if (seen[item]) return false; + seen[item] = true; + return true; + }); + } +}, + set: function set() { + var args = typeof arguments[0] === 'object' ? arguments[0] : arguments; + var ret = {}; + for (var i = 0; i < args.length; i++) { + ret[args[i]] = 0; + } + return ret; +}, + STACK_ALIGN: 8, + getAlignSize: function (type, size, vararg) { + // we align i64s and doubles on 64-bit boundaries, unlike x86 + if (!vararg && (type == 'i64' || type == 'double')) return 8; + if (!type) return Math.min(size, 8); // align structures internally to 64 bits + return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE); + }, + calculateStructAlignment: function calculateStructAlignment(type) { + type.flatSize = 0; + type.alignSize = 0; + var diffs = []; + var prev = -1; + var index = 0; + type.flatIndexes = type.fields.map(function(field) { + index++; + var size, alignSize; + if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) { + size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s. + alignSize = Runtime.getAlignSize(field, size); + } else if (Runtime.isStructType(field)) { + if (field[1] === '0') { + // this is [0 x something]. When inside another structure like here, it must be at the end, + // and it adds no size + // XXX this happens in java-nbody for example... assert(index === type.fields.length, 'zero-length in the middle!'); + size = 0; + if (Types.types[field]) { + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } else { + alignSize = type.alignSize || QUANTUM_SIZE; + } + } else { + size = Types.types[field].flatSize; + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } + } else if (field[0] == 'b') { + // bN, large number field, like a [N x i8] + size = field.substr(1)|0; + alignSize = 1; + } else if (field[0] === '<') { + // vector type + size = alignSize = Types.types[field].flatSize; // fully aligned + } else if (field[0] === 'i') { + // illegal integer field, that could not be legalized because it is an internal structure field + // it is ok to have such fields, if we just use them as markers of field size and nothing more complex + size = alignSize = parseInt(field.substr(1))/8; + assert(size % 1 === 0, 'cannot handle non-byte-size field ' + field); + } else { + assert(false, 'invalid type for calculateStructAlignment'); + } + if (type.packed) alignSize = 1; + type.alignSize = Math.max(type.alignSize, alignSize); + var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory + type.flatSize = curr + size; + if (prev >= 0) { + diffs.push(curr-prev); + } + prev = curr; + return curr; + }); + if (type.name_ && type.name_[0] === '[') { + // arrays have 2 elements, so we get the proper difference. then we scale here. that way we avoid + // allocating a potentially huge array for [999999 x i8] etc. + type.flatSize = parseInt(type.name_.substr(1))*type.flatSize/2; + } + type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize); + if (diffs.length == 0) { + type.flatFactor = type.flatSize; + } else if (Runtime.dedup(diffs).length == 1) { + type.flatFactor = diffs[0]; + } + type.needsFlattening = (type.flatFactor != 1); + return type.flatIndexes; + }, + generateStructInfo: function (struct, typeName, offset) { + var type, alignment; + if (typeName) { + offset = offset || 0; + type = (typeof Types === 'undefined' ? Runtime.typeInfo : Types.types)[typeName]; + if (!type) return null; + if (type.fields.length != struct.length) { + printErr('Number of named fields must match the type for ' + typeName + ': possibly duplicate struct names. Cannot return structInfo'); + return null; + } + alignment = type.flatIndexes; + } else { + var type = { fields: struct.map(function(item) { return item[0] }) }; + alignment = Runtime.calculateStructAlignment(type); + } + var ret = { + __size__: type.flatSize + }; + if (typeName) { + struct.forEach(function(item, i) { + if (typeof item === 'string') { + ret[item] = alignment[i] + offset; + } else { + // embedded struct + var key; + for (var k in item) key = k; + ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]); + } + }); + } else { + struct.forEach(function(item, i) { + ret[item[1]] = alignment[i]; + }); + } + return ret; + }, + dynCall: function (sig, ptr, args) { + if (args && args.length) { + if (!args.splice) args = Array.prototype.slice.call(args); + args.splice(0, 0, ptr); + return Module['dynCall_' + sig].apply(null, args); + } else { + return Module['dynCall_' + sig].call(null, ptr); + } + }, + functionPointers: [], + addFunction: function (func) { + for (var i = 0; i < Runtime.functionPointers.length; i++) { + if (!Runtime.functionPointers[i]) { + Runtime.functionPointers[i] = func; + return 2*(1 + i); + } + } + throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; + }, + removeFunction: function (index) { + Runtime.functionPointers[(index-2)/2] = null; + }, + getAsmConst: function (code, numArgs) { + // code is a constant string on the heap, so we can cache these + if (!Runtime.asmConstCache) Runtime.asmConstCache = {}; + var func = Runtime.asmConstCache[code]; + if (func) return func; + var args = []; + for (var i = 0; i < numArgs; i++) { + args.push(String.fromCharCode(36) + i); // $0, $1 etc + } + var source = Pointer_stringify(code); + if (source[0] === '"') { + // tolerate EM_ASM("..code..") even though EM_ASM(..code..) is correct + if (source.indexOf('"', 1) === source.length-1) { + source = source.substr(1, source.length-2); + } else { + // something invalid happened, e.g. EM_ASM("..code($0)..", input) + abort('invalid EM_ASM input |' + source + '|. Please use EM_ASM(..code..) (no quotes) or EM_ASM({ ..code($0).. }, input) (to input values)'); + } + } + try { + var evalled = eval('(function(' + args.join(',') + '){ ' + source + ' })'); // new Function does not allow upvars in node + } catch(e) { + Module.printErr('error in executing inline EM_ASM code: ' + e + ' on: \n\n' + source + '\n\nwith args |' + args + '| (make sure to use the right one out of EM_ASM, EM_ASM_ARGS, etc.)'); + throw e; + } + return Runtime.asmConstCache[code] = evalled; + }, + warnOnce: function (text) { + if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; + if (!Runtime.warnOnce.shown[text]) { + Runtime.warnOnce.shown[text] = 1; + Module.printErr(text); + } + }, + funcWrappers: {}, + getFuncWrapper: function (func, sig) { + assert(sig); + if (!Runtime.funcWrappers[func]) { + Runtime.funcWrappers[func] = function dynCall_wrapper() { + return Runtime.dynCall(sig, func, arguments); + }; + } + return Runtime.funcWrappers[func]; + }, + UTF8Processor: function () { + var buffer = []; + var needed = 0; + this.processCChar = function (code) { + code = code & 0xFF; + + if (buffer.length == 0) { + if ((code & 0x80) == 0x00) { // 0xxxxxxx + return String.fromCharCode(code); + } + buffer.push(code); + if ((code & 0xE0) == 0xC0) { // 110xxxxx + needed = 1; + } else if ((code & 0xF0) == 0xE0) { // 1110xxxx + needed = 2; + } else { // 11110xxx + needed = 3; + } + return ''; + } + + if (needed) { + buffer.push(code); + needed--; + if (needed > 0) return ''; + } + + var c1 = buffer[0]; + var c2 = buffer[1]; + var c3 = buffer[2]; + var c4 = buffer[3]; + var ret; + if (buffer.length == 2) { + ret = String.fromCharCode(((c1 & 0x1F) << 6) | (c2 & 0x3F)); + } else if (buffer.length == 3) { + ret = String.fromCharCode(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); + } else { + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + var codePoint = ((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) | + ((c3 & 0x3F) << 6) | (c4 & 0x3F); + ret = String.fromCharCode( + Math.floor((codePoint - 0x10000) / 0x400) + 0xD800, + (codePoint - 0x10000) % 0x400 + 0xDC00); + } + buffer.length = 0; + return ret; + } + this.processJSString = function processJSString(string) { + /* TODO: use TextEncoder when present, + var encoder = new TextEncoder(); + encoder['encoding'] = "utf-8"; + var utf8Array = encoder['encode'](aMsg.data); + */ + string = unescape(encodeURIComponent(string)); + var ret = []; + for (var i = 0; i < string.length; i++) { + ret.push(string.charCodeAt(i)); + } + return ret; + } + }, + getCompilerSetting: function (name) { + throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work'; + }, + stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = (((STACKTOP)+7)&-8); return ret; }, + staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = (((STATICTOP)+7)&-8); return ret; }, + dynamicAlloc: function (size) { var ret = DYNAMICTOP;DYNAMICTOP = (DYNAMICTOP + size)|0;DYNAMICTOP = (((DYNAMICTOP)+7)&-8); if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();; return ret; }, + alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 8))*(quantum ? quantum : 8); return ret; }, + makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+((low>>>0)))+((+((high>>>0)))*(+4294967296))) : ((+((low>>>0)))+((+((high|0)))*(+4294967296)))); return ret; }, + GLOBAL_BASE: 8, + QUANTUM_SIZE: 4, + __dummy__: 0 +} + + +Module['Runtime'] = Runtime; + + + + + + + + + +//======================================== +// Runtime essentials +//======================================== + +var __THREW__ = 0; // Used in checking for thrown exceptions. + +var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort() +var EXITSTATUS = 0; + +var undef = 0; +// tempInt is used for 32-bit signed values or smaller. tempBigInt is used +// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt +var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD, tempDouble, tempFloat; +var tempI64, tempI64b; +var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9; + +function assert(condition, text) { + if (!condition) { + abort('Assertion failed: ' + text); + } +} + +var globalScope = this; + +// C calling interface. A convenient way to call C functions (in C files, or +// defined with extern "C"). +// +// Note: LLVM optimizations can inline and remove functions, after which you will not be +// able to call them. Closure can also do so. To avoid that, add your function to +// the exports using something like +// +// -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]' +// +// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C") +// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and +// 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit). +// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType, +// except that 'array' is not possible (there is no way for us to know the length of the array) +// @param args An array of the arguments to the function, as native JS values (as in returnType) +// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack). +// @return The return value, as a native JS value (as in returnType) +function ccall(ident, returnType, argTypes, args) { + return ccallFunc(getCFunc(ident), returnType, argTypes, args); +} +Module["ccall"] = ccall; + +// Returns the C function with a specified identifier (for C++, you need to do manual name mangling) +function getCFunc(ident) { + try { + var func = Module['_' + ident]; // closure exported function + if (!func) func = eval('_' + ident); // explicit lookup + } catch(e) { + } + assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)'); + return func; +} + +// Internal function that does a C call using a function, not an identifier +function ccallFunc(func, returnType, argTypes, args) { + var stack = 0; + function toC(value, type) { + if (type == 'string') { + if (value === null || value === undefined || value === 0) return 0; // null string + value = intArrayFromString(value); + type = 'array'; + } + if (type == 'array') { + if (!stack) stack = Runtime.stackSave(); + var ret = Runtime.stackAlloc(value.length); + writeArrayToMemory(value, ret); + return ret; + } + return value; + } + function fromC(value, type) { + if (type == 'string') { + return Pointer_stringify(value); + } + assert(type != 'array'); + return value; + } + var i = 0; + var cArgs = args ? args.map(function(arg) { + return toC(arg, argTypes[i++]); + }) : []; + var ret = fromC(func.apply(null, cArgs), returnType); + if (stack) Runtime.stackRestore(stack); + return ret; +} + +// Returns a native JS wrapper for a C function. This is similar to ccall, but +// returns a function you can call repeatedly in a normal way. For example: +// +// var my_function = cwrap('my_c_function', 'number', ['number', 'number']); +// alert(my_function(5, 22)); +// alert(my_function(99, 12)); +// +function cwrap(ident, returnType, argTypes) { + var func = getCFunc(ident); + return function() { + return ccallFunc(func, returnType, argTypes, Array.prototype.slice.call(arguments)); + } +} +Module["cwrap"] = cwrap; + +// Sets a value in memory in a dynamic way at run-time. Uses the +// type data. This is the same as makeSetValue, except that +// makeSetValue is done at compile-time and generates the needed +// code then, whereas this function picks the right code at +// run-time. +// Note that setValue and getValue only do *aligned* writes and reads! +// Note that ccall uses JS types as for defining types, while setValue and +// getValue need LLVM types ('i8', 'i32') - this is a lower-level operation +function setValue(ptr, value, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': HEAP8[(ptr)]=value; break; + case 'i8': HEAP8[(ptr)]=value; break; + case 'i16': HEAP16[((ptr)>>1)]=value; break; + case 'i32': HEAP32[((ptr)>>2)]=value; break; + case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= (+1) ? (tempDouble > (+0) ? ((Math_min((+(Math_floor((tempDouble)/(+4294967296)))), (+4294967295)))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/(+4294967296))))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break; + case 'float': HEAPF32[((ptr)>>2)]=value; break; + case 'double': HEAPF64[((ptr)>>3)]=value; break; + default: abort('invalid type for setValue: ' + type); + } +} +Module['setValue'] = setValue; + +// Parallel to setValue. +function getValue(ptr, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': return HEAP8[(ptr)]; + case 'i8': return HEAP8[(ptr)]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': return HEAP32[((ptr)>>2)]; + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + default: abort('invalid type for setValue: ' + type); + } + return null; +} +Module['getValue'] = getValue; + +var ALLOC_NORMAL = 0; // Tries to use _malloc() +var ALLOC_STACK = 1; // Lives for the duration of the current function call +var ALLOC_STATIC = 2; // Cannot be freed +var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk +var ALLOC_NONE = 4; // Do not allocate +Module['ALLOC_NORMAL'] = ALLOC_NORMAL; +Module['ALLOC_STACK'] = ALLOC_STACK; +Module['ALLOC_STATIC'] = ALLOC_STATIC; +Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC; +Module['ALLOC_NONE'] = ALLOC_NONE; + +// allocate(): This is for internal use. You can use it yourself as well, but the interface +// is a little tricky (see docs right below). The reason is that it is optimized +// for multiple syntaxes to save space in generated code. So you should +// normally not use allocate(), and instead allocate memory using _malloc(), +// initialize it with setValue(), and so forth. +// @slab: An array of data, or a number. If a number, then the size of the block to allocate, +// in *bytes* (note that this is sometimes confusing: the next parameter does not +// affect this!) +// @types: Either an array of types, one for each byte (or 0 if no type at that position), +// or a single type which is used for the entire block. This only matters if there +// is initial data - if @slab is a number, then this does not matter at all and is +// ignored. +// @allocator: How to allocate memory, see ALLOC_* +function allocate(slab, types, allocator, ptr) { + var zeroinit, size; + if (typeof slab === 'number') { + zeroinit = true; + size = slab; + } else { + zeroinit = false; + size = slab.length; + } + + var singleType = typeof types === 'string' ? types : null; + + var ret; + if (allocator == ALLOC_NONE) { + ret = ptr; + } else { + ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); + } + + if (zeroinit) { + var ptr = ret, stop; + assert((ret & 3) == 0); + stop = ret + (size & ~3); + for (; ptr < stop; ptr += 4) { + HEAP32[((ptr)>>2)]=0; + } + stop = ret + size; + while (ptr < stop) { + HEAP8[((ptr++)|0)]=0; + } + return ret; + } + + if (singleType === 'i8') { + if (slab.subarray || slab.slice) { + HEAPU8.set(slab, ret); + } else { + HEAPU8.set(new Uint8Array(slab), ret); + } + return ret; + } + + var i = 0, type, typeSize, previousType; + while (i < size) { + var curr = slab[i]; + + if (typeof curr === 'function') { + curr = Runtime.getFunctionIndex(curr); + } + + type = singleType || types[i]; + if (type === 0) { + i++; + continue; + } + + if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later + + setValue(ret+i, curr, type); + + // no need to look up size unless type changes, so cache it + if (previousType !== type) { + typeSize = Runtime.getNativeTypeSize(type); + previousType = type; + } + i += typeSize; + } + + return ret; +} +Module['allocate'] = allocate; + +function Pointer_stringify(ptr, /* optional */ length) { + // TODO: use TextDecoder + // Find the length, and check for UTF while doing so + var hasUtf = false; + var t; + var i = 0; + while (1) { + t = HEAPU8[(((ptr)+(i))|0)]; + if (t >= 128) hasUtf = true; + else if (t == 0 && !length) break; + i++; + if (length && i == length) break; + } + if (!length) length = i; + + var ret = ''; + + if (!hasUtf) { + var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack + var curr; + while (length > 0) { + curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); + ret = ret ? ret + curr : curr; + ptr += MAX_CHUNK; + length -= MAX_CHUNK; + } + return ret; + } + + var utf8 = new Runtime.UTF8Processor(); + for (i = 0; i < length; i++) { + t = HEAPU8[(((ptr)+(i))|0)]; + ret += utf8.processCChar(t); + } + return ret; +} +Module['Pointer_stringify'] = Pointer_stringify; + +// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns +// a copy of that string as a Javascript String object. +function UTF16ToString(ptr) { + var i = 0; + + var str = ''; + while (1) { + var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; + if (codeUnit == 0) + return str; + ++i; + // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through. + str += String.fromCharCode(codeUnit); + } +} +Module['UTF16ToString'] = UTF16ToString; + +// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', +// null-terminated and encoded in UTF16LE form. The copy will require at most (str.length*2+1)*2 bytes of space in the HEAP. +function stringToUTF16(str, outPtr) { + for(var i = 0; i < str.length; ++i) { + // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. + var codeUnit = str.charCodeAt(i); // possibly a lead surrogate + HEAP16[(((outPtr)+(i*2))>>1)]=codeUnit; + } + // Null-terminate the pointer to the HEAP. + HEAP16[(((outPtr)+(str.length*2))>>1)]=0; +} +Module['stringToUTF16'] = stringToUTF16; + +// Given a pointer 'ptr' to a null-terminated UTF32LE-encoded string in the emscripten HEAP, returns +// a copy of that string as a Javascript String object. +function UTF32ToString(ptr) { + var i = 0; + + var str = ''; + while (1) { + var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; + if (utf32 == 0) + return str; + ++i; + // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. + if (utf32 >= 0x10000) { + var ch = utf32 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } else { + str += String.fromCharCode(utf32); + } + } +} +Module['UTF32ToString'] = UTF32ToString; + +// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', +// null-terminated and encoded in UTF32LE form. The copy will require at most (str.length+1)*4 bytes of space in the HEAP, +// but can use less, since str.length does not return the number of characters in the string, but the number of UTF-16 code units in the string. +function stringToUTF32(str, outPtr) { + var iChar = 0; + for(var iCodeUnit = 0; iCodeUnit < str.length; ++iCodeUnit) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. + var codeUnit = str.charCodeAt(iCodeUnit); // possibly a lead surrogate + if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { + var trailSurrogate = str.charCodeAt(++iCodeUnit); + codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); + } + HEAP32[(((outPtr)+(iChar*4))>>2)]=codeUnit; + ++iChar; + } + // Null-terminate the pointer to the HEAP. + HEAP32[(((outPtr)+(iChar*4))>>2)]=0; +} +Module['stringToUTF32'] = stringToUTF32; + +function demangle(func) { + var i = 3; + // params, etc. + var basicTypes = { + 'v': 'void', + 'b': 'bool', + 'c': 'char', + 's': 'short', + 'i': 'int', + 'l': 'long', + 'f': 'float', + 'd': 'double', + 'w': 'wchar_t', + 'a': 'signed char', + 'h': 'unsigned char', + 't': 'unsigned short', + 'j': 'unsigned int', + 'm': 'unsigned long', + 'x': 'long long', + 'y': 'unsigned long long', + 'z': '...' + }; + var subs = []; + var first = true; + function dump(x) { + //return; + if (x) Module.print(x); + Module.print(func); + var pre = ''; + for (var a = 0; a < i; a++) pre += ' '; + Module.print (pre + '^'); + } + function parseNested() { + i++; + if (func[i] === 'K') i++; // ignore const + var parts = []; + while (func[i] !== 'E') { + if (func[i] === 'S') { // substitution + i++; + var next = func.indexOf('_', i); + var num = func.substring(i, next) || 0; + parts.push(subs[num] || '?'); + i = next+1; + continue; + } + if (func[i] === 'C') { // constructor + parts.push(parts[parts.length-1]); + i += 2; + continue; + } + var size = parseInt(func.substr(i)); + var pre = size.toString().length; + if (!size || !pre) { i--; break; } // counter i++ below us + var curr = func.substr(i + pre, size); + parts.push(curr); + subs.push(curr); + i += pre + size; + } + i++; // skip E + return parts; + } + function parse(rawList, limit, allowVoid) { // main parser + limit = limit || Infinity; + var ret = '', list = []; + function flushList() { + return '(' + list.join(', ') + ')'; + } + var name; + if (func[i] === 'N') { + // namespaced N-E + name = parseNested().join('::'); + limit--; + if (limit === 0) return rawList ? [name] : name; + } else { + // not namespaced + if (func[i] === 'K' || (first && func[i] === 'L')) i++; // ignore const and first 'L' + var size = parseInt(func.substr(i)); + if (size) { + var pre = size.toString().length; + name = func.substr(i + pre, size); + i += pre + size; + } + } + first = false; + if (func[i] === 'I') { + i++; + var iList = parse(true); + var iRet = parse(true, 1, true); + ret += iRet[0] + ' ' + name + '<' + iList.join(', ') + '>'; + } else { + ret = name; + } + paramLoop: while (i < func.length && limit-- > 0) { + //dump('paramLoop'); + var c = func[i++]; + if (c in basicTypes) { + list.push(basicTypes[c]); + } else { + switch (c) { + case 'P': list.push(parse(true, 1, true)[0] + '*'); break; // pointer + case 'R': list.push(parse(true, 1, true)[0] + '&'); break; // reference + case 'L': { // literal + i++; // skip basic type + var end = func.indexOf('E', i); + var size = end - i; + list.push(func.substr(i, size)); + i += size + 2; // size + 'EE' + break; + } + case 'A': { // array + var size = parseInt(func.substr(i)); + i += size.toString().length; + if (func[i] !== '_') throw '?'; + i++; // skip _ + list.push(parse(true, 1, true)[0] + ' [' + size + ']'); + break; + } + case 'E': break paramLoop; + default: ret += '?' + c; break paramLoop; + } + } + } + if (!allowVoid && list.length === 1 && list[0] === 'void') list = []; // avoid (void) + if (rawList) { + if (ret) { + list.push(ret + '?'); + } + return list; + } else { + return ret + flushList(); + } + } + try { + // Special-case the entry point, since its name differs from other name mangling. + if (func == 'Object._main' || func == '_main') { + return 'main()'; + } + if (typeof func === 'number') func = Pointer_stringify(func); + if (func[0] !== '_') return func; + if (func[1] !== '_') return func; // C function + if (func[2] !== 'Z') return func; + switch (func[3]) { + case 'n': return 'operator new()'; + case 'd': return 'operator delete()'; + } + return parse(); + } catch(e) { + return func; + } +} + +function demangleAll(text) { + return text.replace(/__Z[\w\d_]+/g, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']') }); +} + +function stackTrace() { + var stack = new Error().stack; + return stack ? demangleAll(stack) : '(no stack trace available)'; // Stack trace is not available at least on IE10 and Safari 6. +} + +// Memory management + +var PAGE_SIZE = 4096; +function alignMemoryPage(x) { + return (x+4095)&-4096; +} + +var HEAP; +var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; + +var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area +var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area +var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk + +function enlargeMemory() { + abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.'); +} + +var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; +var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 67108864; +var FAST_MEMORY = Module['FAST_MEMORY'] || 2097152; + +var totalMemory = 4096; +while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) { + if (totalMemory < 16*1024*1024) { + totalMemory *= 2; + } else { + totalMemory += 16*1024*1024 + } +} +if (totalMemory !== TOTAL_MEMORY) { + Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be more reasonable'); + TOTAL_MEMORY = totalMemory; +} + +// Initialize the runtime's memory +// check for full engine support (use string 'subarray' to avoid closure compiler confusion) +assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']), + 'JS engine does not provide full typed array support'); + +var buffer = new ArrayBuffer(TOTAL_MEMORY); +HEAP8 = new Int8Array(buffer); +HEAP16 = new Int16Array(buffer); +HEAP32 = new Int32Array(buffer); +HEAPU8 = new Uint8Array(buffer); +HEAPU16 = new Uint16Array(buffer); +HEAPU32 = new Uint32Array(buffer); +HEAPF32 = new Float32Array(buffer); +HEAPF64 = new Float64Array(buffer); + +// Endianness check (note: assumes compiler arch was little-endian) +HEAP32[0] = 255; +assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system'); + +Module['HEAP'] = HEAP; +Module['HEAP8'] = HEAP8; +Module['HEAP16'] = HEAP16; +Module['HEAP32'] = HEAP32; +Module['HEAPU8'] = HEAPU8; +Module['HEAPU16'] = HEAPU16; +Module['HEAPU32'] = HEAPU32; +Module['HEAPF32'] = HEAPF32; +Module['HEAPF64'] = HEAPF64; + +function callRuntimeCallbacks(callbacks) { + while(callbacks.length > 0) { + var callback = callbacks.shift(); + if (typeof callback == 'function') { + callback(); + continue; + } + var func = callback.func; + if (typeof func === 'number') { + if (callback.arg === undefined) { + Runtime.dynCall('v', func); + } else { + Runtime.dynCall('vi', func, [callback.arg]); + } + } else { + func(callback.arg === undefined ? null : callback.arg); + } + } +} + +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATMAIN__ = []; // functions called when main() is to be run +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the runtime has exited + +var runtimeInitialized = false; + +function preRun() { + // compatibility - merge in anything from Module['preRun'] at this time + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + callRuntimeCallbacks(__ATPRERUN__); +} + +function ensureInitRuntime() { + if (runtimeInitialized) return; + runtimeInitialized = true; + callRuntimeCallbacks(__ATINIT__); +} + +function preMain() { + callRuntimeCallbacks(__ATMAIN__); +} + +function exitRuntime() { + callRuntimeCallbacks(__ATEXIT__); +} + +function postRun() { + // compatibility - merge in anything from Module['postRun'] at this time + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + callRuntimeCallbacks(__ATPOSTRUN__); +} + +function addOnPreRun(cb) { + __ATPRERUN__.unshift(cb); +} +Module['addOnPreRun'] = Module.addOnPreRun = addOnPreRun; + +function addOnInit(cb) { + __ATINIT__.unshift(cb); +} +Module['addOnInit'] = Module.addOnInit = addOnInit; + +function addOnPreMain(cb) { + __ATMAIN__.unshift(cb); +} +Module['addOnPreMain'] = Module.addOnPreMain = addOnPreMain; + +function addOnExit(cb) { + __ATEXIT__.unshift(cb); +} +Module['addOnExit'] = Module.addOnExit = addOnExit; + +function addOnPostRun(cb) { + __ATPOSTRUN__.unshift(cb); +} +Module['addOnPostRun'] = Module.addOnPostRun = addOnPostRun; + +// Tools + +// This processes a JS string into a C-line array of numbers, 0-terminated. +// For LLVM-originating strings, see parser.js:parseLLVMString function +function intArrayFromString(stringy, dontAddNull, length /* optional */) { + var ret = (new Runtime.UTF8Processor()).processJSString(stringy); + if (length) { + ret.length = length; + } + if (!dontAddNull) { + ret.push(0); + } + return ret; +} +Module['intArrayFromString'] = intArrayFromString; + +function intArrayToString(array) { + var ret = []; + for (var i = 0; i < array.length; i++) { + var chr = array[i]; + if (chr > 0xFF) { + chr &= 0xFF; + } + ret.push(String.fromCharCode(chr)); + } + return ret.join(''); +} +Module['intArrayToString'] = intArrayToString; + +// Write a Javascript array to somewhere in the heap +function writeStringToMemory(string, buffer, dontAddNull) { + var array = intArrayFromString(string, dontAddNull); + var i = 0; + while (i < array.length) { + var chr = array[i]; + HEAP8[(((buffer)+(i))|0)]=chr; + i = i + 1; + } +} +Module['writeStringToMemory'] = writeStringToMemory; + +function writeArrayToMemory(array, buffer) { + for (var i = 0; i < array.length; i++) { + HEAP8[(((buffer)+(i))|0)]=array[i]; + } +} +Module['writeArrayToMemory'] = writeArrayToMemory; + +function writeAsciiToMemory(str, buffer, dontAddNull) { + for (var i = 0; i < str.length; i++) { + HEAP8[(((buffer)+(i))|0)]=str.charCodeAt(i); + } + if (!dontAddNull) HEAP8[(((buffer)+(str.length))|0)]=0; +} +Module['writeAsciiToMemory'] = writeAsciiToMemory; + +function unSign(value, bits, ignore) { + if (value >= 0) { + return value; + } + return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts + : Math.pow(2, bits) + value; +} +function reSign(value, bits, ignore) { + if (value <= 0) { + return value; + } + var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 + : Math.pow(2, bits-1); + if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that + // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors + // TODO: In i64 mode 1, resign the two parts separately and safely + value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts + } + return value; +} + +// check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 ) +if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) { + var ah = a >>> 16; + var al = a & 0xffff; + var bh = b >>> 16; + var bl = b & 0xffff; + return (al*bl + ((ah*bl + al*bh) << 16))|0; +}; +Math.imul = Math['imul']; + + +var Math_abs = Math.abs; +var Math_cos = Math.cos; +var Math_sin = Math.sin; +var Math_tan = Math.tan; +var Math_acos = Math.acos; +var Math_asin = Math.asin; +var Math_atan = Math.atan; +var Math_atan2 = Math.atan2; +var Math_exp = Math.exp; +var Math_log = Math.log; +var Math_sqrt = Math.sqrt; +var Math_ceil = Math.ceil; +var Math_floor = Math.floor; +var Math_pow = Math.pow; +var Math_imul = Math.imul; +var Math_fround = Math.fround; +var Math_min = Math.min; + +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// PRE_RUN_ADDITIONS (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled + +function addRunDependency(id) { + runDependencies++; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } +} +Module['addRunDependency'] = addRunDependency; +function removeRunDependency(id) { + runDependencies--; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } +} +Module['removeRunDependency'] = removeRunDependency; + +Module["preloadedImages"] = {}; // maps url to image data +Module["preloadedAudios"] = {}; // maps url to audio data + + +var memoryInitializer = null; + +// === Body === + + + + + +STATIC_BASE = 8; + +STATICTOP = STATIC_BASE + Runtime.alignMemory(28211); +/* global initializers */ __ATINIT__.push(); + + +/* memory initializer */ allocate([37,46,51,102,32,37,46,51,102,0,0,0,0,0,0,0,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,0,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,0,108,105,110,101,97,114,0,0,100,101,103,114,101,101,115,0,115,101,120,97,103,101,115,105,109,97,108,0,0,0,0,0,59,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,115,40,0,0,0,0,0,37,46,54,102,44,32,37,46,54,102,0,0,0,0,0,0,37,115,44,32,37,115,0,0,112,111,108,121,103,111,110,0,44,32,37,46,54,102,44,32,37,46,54,102,0,0,0,0,44,32,37,115,44,32,37,115,0,0,0,0,0,0,0,0,44,32,37,46,50,102,34,0,44,32,37,46,54,102,39,0,44,32,37,46,54,102,100,0,98,111,120,0,0,0,0,0,101,108,108,105,112,115,101,0,44,32,37,46,51,102,0,0,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,102,32,37,102], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE); +/* memory initializer */ allocate([1,0,0,0,0,0,0,0,87,67,83,73,78,73,84,78,58,32,87,67,83,32,110,97,109,101,32,37,115,32,110,111,116,32,109,97,116,99,104,101,100,32,105,110,32,70,73,84,83,32,104,101,97,100,101,114,10,0,0,0,0,0,0,0,87,67,83,78,65,77,69,0,87,67,83,65,88,69,83,0,78,65,88,73,83,0,0,0,87,67,83,68,73,77,0,0,87,67,83,73,78,73,84,58,32,78,111,32,87,67,83,65,88,69,83,44,32,78,65,88,73,83,44,32,111,114,32,87,67,83,68,73,77,32,107,101,121,119,111,114,100,0,0,0,78,65,88,73,83,49,0,0,73,77,65,71,69,87,0,0,87,67,83,73,78,73,84,58,32,78,111,32,78,65,88,73,83,49,32,111,114,32,73,77,65,71,69,87,32,107,101,121,119,111,114,100,0,0,0,0,78,65,88,73,83,50,0,0,73,77,65,71,69,72,0,0,87,67,83,73,78,73,84,58,32,78,111,32,78,65,88,73,83,50,32,111,114,32,73,77,65,71,69,72,32,107,101,121,119,111,114,100,0,0,0,0,37,100,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,77,105,115,115,105,110,103,32,107,101,121,119,111,114,100,32,37,115,32,97,115,115,117,109,101,100,32,49,10,0,0,67,84,89,80,69,0,0,0,45,84,65,66,0,0,0,0,73,78,83,84,82,85,77,69,0,0,0,0,0,0,0,0,68,69,84,69,67,84,79,82,0,0,0,0,0,0,0,0,68,67,45,70,76,65,71,0,87,67,83,68,69,80,0,0,87,67,83,73,78,73,84,58,32,100,101,112,101,110,100,101,100,32,111,110,32,87,67,83,32,99,111,117,108,100,32,110,111,116,32,98,101,32,115,101,116,0,0,0,0,0,0,0,86,83,79,85,82,67,69,0,90,83,79,85,82,67,69,0,86,69,76,79,67,73,84,89,0,0,0,0,0,0,0,0,67,84,89,80,69,49,0,0,67,84,89,80,69,50,0,0,76,65,84,0,0,0,0,0,68,69,67,0,0,0,0,0,67,84,89,80,69,51,0,0,67,84,89,80,69,52,0,0,67,85,78,73,84,49,0,0,87,65,84,49,0,0,0,0,117,110,105,116,115,0,0,0,112,105,120,101,108,0,0,0,67,85,78,73,84,50,0,0,87,65,84,50,0,0,0,0,67,82,80,73,88,49,0,0,67,82,80,73,88,50,0,0,67,82,86,65,76,49,0,0,67,82,86,65,76,50,0,0,76,79,78,80,79,76,69,0,76,65,84,80,79,76,69,0,80,82,79,74,82,48,0,0,80,82,79,74,80,37,100,0,80,86,37,100,95,49,0,0,80,86,37,100,95,50,0,0,80,86,37,100,95,51,0,0,80,86,37,100,95,37,100,0,67,68,49,95,49,0,0,0,67,68,49,95,50,0,0,0,67,68,50,95,49,0,0,0,67,68,50,95,50,0,0,0,67,79,49,95,49,0,0,0,80,76,65,84,69,0,0,0,67,79,49,95,37,100,0,0,67,79,50,95,49,0,0,0,67,79,50,95,37,100,0,0,67,68,69,76,84,49,0,0,67,68,69,76,84,50,0,0,83,69,67,80,73,88,0,0,80,73,88,83,67,65,76,69,0,0,0,0,0,0,0,0,80,73,88,83,67,65,76,49,0,0,0,0,0,0,0,0,88,80,73,88,83,73,90,69,0,0,0,0,0,0,0,0,83,69,67,80,73,88,49,0,83,69,67,80,73,88,50,0,89,80,73,88,83,73,90,69,0,0,0,0,0,0,0,0,80,73,88,83,67,65,76,50,0,0,0,0,0,0,0,0,80,67,48,48,49,48,48,49,0,0,0,0,0,0,0,0,80,67,48,48,37,49,100,48,48,37,49,100,0,0,0,0,80,67,49,95,49,0,0,0,80,67,37,49,100,95,37,49,100,0,0,0,0,0,0,0,67,82,79,84,65,50,0,0,67,82,79,84,65,49,0,0,87,67,83,73,78,73,84,58,32,115,101,116,116,105,110,103,32,67,68,69,76,84,32,116,111,32,49,0,0,0,0,0,76,73,78,69,65,82,0,0,80,73,88,69,76,0,0,0,77,74,68,45,79,66,83,0,68,65,84,69,45,79,66,83,0,0,0,0,0,0,0,0,68,65,84,69,0,0,0,0,69,80,79,67,72,0,0,0,85,84,0,0,0,0,0,0,85,84,77,73,68,0,0,0,87,67,83,73,78,73,84,67,58,32,78,111,32,105,109,97,103,101,32,115,99,97,108,101,32,102,111,114,32,87,67,83,32,37,99,0,0,0,0,0,80,76,84,82,65,72,0,0,80,76,84,82,65,77,0,0,80,76,84,82,65,83,0,0,80,76,84,68,69,67,83,78,0,0,0,0,0,0,0,0,80,76,84,68,69,67,68,0,80,76,84,68,69,67,77,0,80,76,84,68,69,67,83,0,69,81,85,73,78,79,88,0,70,75,52,0,0,0,0,0,70,75,53,0,0,0,0,0,37,50,46,48,102,58,37,50,46,48,102,58,37,53,46,51,102,32,37,99,37,50,46,48,102,58,37,50,46,48,102,58,37,53,46,51,102,32,37,115,0,0,0,0,0,0,0,0,80,76,84,83,67,65,76,69,0,0,0,0,0,0,0,0,88,80,73,88,69,76,83,90,0,0,0,0,0,0,0,0,89,80,73,88,69,76,83,90,0,0,0,0,0,0,0,0,67,78,80,73,88,49,0,0,67,78,80,73,88,50,0,0,80,80,79,49,0,0,0,0,80,80,79,37,100,0,0,0,65,77,68,88,49,0,0,0,65,77,68,88,37,100,0,0,65,77,68,89,49,0,0,0,65,77,68,89,37,100,0,0,82,65,0,0,0,0,0,0,82,65,45,45,45,68,83,83,0,0,0,0,0,0,0,0,68,69,67,45,45,68,83,83,0,0,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,78,111,32,82,65,32,119,105,116,104,32,83,69,67,80,73,88,44,32,110,111,32,87,67,83,0,0,0,0,0,0,87,67,83,73,78,73,84,32,78,111,32,68,69,67,32,119,105,116,104,32,83,69,67,80,73,88,44,32,110,111,32,87,67,83,0,0,0,0,0,0,76,79,78,71,80,79,76,69,0,0,0,0,0,0,0,0,82,65,45,45,45,84,65,78,0,0,0,0,0,0,0,0,68,69,67,45,45,84,65,78,0,0,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,78,111,32,105,109,97,103,101,32,115,99,97,108,101,0,84,65,78,0,0,0,0,0,42,69,114,114,111,114,42,58,32,105,110,99,111,114,114,101,99,116,32,108,105,110,101,97,114,32,99,111,110,118,101,114,115,105,111,110,32,105,110,32,37,115,0,0,0,0,0,0,87,65,82,78,73,78,71,58,32,83,105,103,110,105,102,105,99,97,110,116,32,105,110,97,99,99,117,114,97,99,121,32,108,105,107,101,108,121,32,116,111,32,111,99,99,117,114,32,105,110,32,112,114,111,106,101,99,116,105,111,110,0,0,0,69,81,85,73,78,79,88,37,99,0,0,0,0,0,0,0,82,65,68,69,67,83,89,83,37,99,0,0,0,0,0,0,82,65,68,69,67,83,89,83,0,0,0,0,0,0,0,0,73,67,82,83,0,0,0,0,71,65,76,0,0,0,0,0,69,67,76,0,0,0,0,0,71,65,76,65,67,84,73,67,0,0,0,0,0,0,0,0,69,67,76,73,80,84,73,67,0,0,0,0,0,0,0,0,83,71,65,76,65,67,84,67,0,0,0,0,0,0,0,0,72,69,76,73,79,69,67,76,0,0,0,0,0,0,0,0,65,76,84,65,90,0,0,0,0,0,0,0,0,0,0,0,68,69,67,0,0,0,0,0,76,79,78,71,0,0,0,0,76,73,78,69,65,82,0,0,80,73,88,69,76,0,0,0,68,69,84,0,0,0,0,0,37,45,52,115,37,52,115,0,78,80,79,76,0,0,0,0,76,65,84,0,0,0,0,0,78,80,79,76,69,0,0,0,83,80,65,45,0,0,0,0,73,77,83,89,83,0,0,0,105,109,115,121,115,0,0,0,37,46,52,102,0,0,0,0,66,49,57,53,48,0,0,0,74,50,48,48,48,0,0,0,37,115,9,37,115,0,0,0,37,115,32,37,115,0,0,0,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,42,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,9,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,32,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,9,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,32,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,9,108,111,110,103,45,110,112,97,0,0,0,0,0,0,0,32,108,111,110,103,45,110,112,97,0,0,0,0,0,0,0,9,108,111,110,103,45,115,112,97,0,0,0,0,0,0,0,32,108,111,110,103,45,115,112,97,0,0,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,67,83,95,67,79,77,77,65,78,68,0,0,0,0,0,87,67,83,95,67,79,77,77,65,78,68,37,100,0,0,0,50,48,48,48,0,0,0,0,50,48,48,48,46,48,0,0,73,67,82,83,0,0,0,0,105,99,114,115,0,0,0,0,70,75,53,0,0,0,0,0,102,107,53,0,0,0,0,0,49,57,53,48,0,0,0,0,49,57,53,48,46,48,0,0,70,75,52,0,0,0,0,0,102,107,52,0,0,0,0,0,112,105,120,101,108,0,0,0,44,66,124,35,100,255,239,63,206,4,147,55,81,230,134,63,201,87,119,237,8,231,115,63,8,49,216,60,72,85,196,190,141,82,239,197,175,26,93,190,79,75,150,130,180,74,73,190,206,4,147,55,81,230,134,191,110,20,118,229,124,255,239,63,190,2,89,23,76,127,252,190,141,82,239,197,175,26,93,62,186,92,192,248,87,85,196,190,213,61,80,36,200,25,210,61,192,143,86,244,8,231,115,191,40,252,144,126,141,121,252,190,190,45,6,62,231,255,239,63,79,75,150,130,180,74,73,62,213,61,80,36,200,25,210,61,56,97,156,141,155,85,196,190,37,201,115,125,31,14,66,191,237,156,102,129,118,135,206,63,237,128,235,138,25,225,219,191,138,238,48,88,55,255,239,63,235,42,147,208,76,230,134,63,26,132,28,8,135,230,115,63,12,31,17,83,34,137,206,191,58,234,232,184,26,217,101,191,7,35,246,9,160,24,137,63,235,42,147,208,76,230,134,191,233,248,162,28,80,255,239,63,8,168,211,46,100,125,252,190,137,181,248,20,0,227,219,63,180,173,102,157,241,125,129,191,174,14,128,184,171,87,97,63,26,132,28,8,135,230,115,191,247,97,247,252,180,122,252,190,137,77,92,117,186,255,239,63,125,150,201,34,100,255,239,63,15,157,207,213,158,230,134,191,92,113,244,103,237,229,115,191,26,77,59,180,100,85,196,62,52,175,17,131,3,27,93,190,173,87,210,121,59,74,73,190,20,1,96,210,158,230,134,63,3,186,248,225,124,255,239,63,250,59,9,220,34,127,252,190,52,175,17,131,3,27,93,62,91,229,82,109,116,85,196,62,232,167,8,110,48,27,210,189,73,225,178,117,237,229,115,63,235,19,108,31,83,119,252,190,10,30,195,64,231,255,239,63,173,87,210,121,59,74,73,62,185,158,187,181,171,23,210,189,73,125,255,4,184,85,196,62,37,201,115,125,31,14,66,191,211,48,124,68,76,137,206,191,34,223,165,212,37,227,219,63,45,6,81,239,144,255,239,63,108,197,229,21,219,230,134,191,214,96,142,220,162,229,115,191,180,174,209,114,160,135,206,63,58,234,232,184,26,217,101,191,180,173,102,157,241,125,129,191,108,197,229,21,219,230,134,63,26,73,6,169,169,255,239,63,26,238,175,96,19,128,252,190,134,170,152,74,63,225,219,191,7,35,246,9,160,24,137,63,174,14,128,184,171,87,97,63,214,96,142,220,162,229,115,63,212,213,62,153,86,117,252,190,150,50,62,6,10,0,240,63,0,0,0,0,0,0,0,0,70,75,52,50,71,65,76,58,32,66,49,57,53,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,52,50,71,65,76,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,52,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,52,58,32,66,49,57,53,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,53,50,71,65,76,58,32,74,50,48,48,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,53,50,71,65,76,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,53,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,53,58,32,74,50,48,48,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,32,37,99,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,0,0,0,0,0,0,0,69,78,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,28,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,37,115,95,49,0,0,0,0,37,115,95,37,100,0,0,0,37,115,95,48,49,0,0,0,37,115,95,48,48,49,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,48,0,0,0,0,0,0,37,100,0,0,0,0,0,0,37,37,46,37,100,102,0,0,37,48,50,100,58,37,48,50,100,58,37,48,57,46,54,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,56,46,53,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,55,46,52,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,52,46,49,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,50,100,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,57,46,54,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,56,46,53,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,55,46,52,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,52,46,49,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,50,100,0,0,0,0,0,0,0,0,37,37,37,100,46,37,100,102,0,0,0,0,0,0,0,0,37,37,37,52,100,0,0,0,37,37,37,100,100], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+4352); +/* memory initializer */ allocate([87,65,84,49,0,0,0,0,87,65,84,50,0,0,0,0,108,111,110,103,112,111,108,101,0,0,0,0,0,0,0,0,114,111,0,0,0,0,0,0,108,110,103,99,111,114,0,0,108,97,116,99,111,114,0,0,84,78,88,95,71,83,69,86,65,76,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,10,0,0,0,0,0,0,0,84,78,88,95,71,83,68,69,82,58,32,111,114,100,101,114,32,111,102,32,100,101,114,105,118,97,116,105,118,101,115,32,99,97,110,110,111,116,32,98,101,32,60,32,48,10,0,0,84,78,88,95,71,83,68,69,82,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,32,37,100,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,120,32,111,114,100,101,114,32,37,100,10,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,121,32,111,114,100,101,114,32,37,100,10,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,120,32,114,97,110,103,101,32,37,102,45,37,102,10,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,121,32,114,97,110,103,101,32,37,102,45,37,102,10,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,32,37,100,10,0,0,87,65,84,49,0,0,0,0,87,65,84,49,95,48,48,49,61,32,39,119,116,121,112,101,61,122,112,120,32,97,120,116,121,112,101,61,114,97,32,112,114,111,106,112,48,61,48,46,32,112,114,111,106,112,49,61,49,46,32,112,114,111,106,112,50,61,48,46,32,112,114,111,106,112,51,61,51,51,55,46,55,52,32,112,114,111,106,39,87,65,84,50,95,48,48,49,61,32,39,119,116,121,112,101,61,122,112,120,32,97,120,116,121,112,101,61,100,101,99,32,112,114,111,106,112,48,61,48,46,32,112,114,111,106,112,49,61,49,46,32,112,114,111,106,112,50,61,48,46,32,112,114,111,106,112,51,61,51,51,55,46,55,52,32,112,114,111,39,0,0,0,0,0,0,0,0,87,65,84,50,0,0,0,0,108,111,110,103,112,111,108,101,0,0,0,0,0,0,0,0,114,111,0,0,0,0,0,0,112,114,111,106,112,37,100,0,108,110,103,99,111,114,0,0,108,97,116,99,111,114,0,0,10,62,32,37,115,37,115,10,10,0,0,0,0,0,0,0,78,111,116,32,101,110,111,117,103,104,32,109,101,109,111,114,121,32,102,111,114,32,0,0,112,111,108,121,32,40,49,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,84,104,101,32,100,105,109,101,110,115,105,111,110,97,108,105,116,121,32,111,102,32,116,104,101,32,112,111,108,121,110,111,109,32,40,37,100,41,32,101,120,99,101,101,100,115,32,116,104,101,32,109,97,120,105,109,117,109,10,97,108,108,111,119,101,100,32,111,110,101,32,40,37,100,41,0,0,0,0,0,42,69,114,114,111,114,42,58,32,0,0,0,0,0,0,0,112,111,108,121,45,62,103,114,111,117,112,32,40,112,111,108,121,45,62,110,100,105,109,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,112,111,108,121,45,62,100,101,103,114,101,101,32,40,112,111,108,121,45,62,110,103,114,111,117,112,32,101,108,101,109,101,110,116,115,41,32,33,0,0,42,69,114,114,111,114,42,58,32,112,111,108,121,110,111,109,105,97,108,32,71,82,79,85,80,32,111,117,116,32,111,102,32,114,97,110,103,101,0,0,0,0,0,0,0,0,0,0,84,104,101,32,100,101,103,114,101,101,32,111,102,32,116,104,101,32,112,111,108,121,110,111,109,32,40,37,100,41,32,101,120,99,101,101,100,115,32,116,104,101,32,109,97,120,105,109,117,109,10,97,108,108,111,119,101,100,32,111,110,101,32,40,37,100,41,0,0,0,0,0,112,111,108,121,45,62,98,97,115,105,115,32,40,112,111,108,121,45,62,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,112,111,108,121,45,62,99,111,101,102,102,32,40,112,111,108,121,45,62,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,42,73,110,116,101,114,110,97,108,32,69,114,114,111,114,42,58,32,79,110,101,32,111,102,32,120,32,111,114,32,101,120,116,98,97,115,105,115,32,115,104,111,117,108,100,32,98,101,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,78,85,76,76,10,105,110,32,0,0,0,0,0,0,0,0,112,111,108,121,95,102,117,110,99,40,41,0,0,0,0,0,97,108,112,104,97,32,40,109,97,116,115,105,122,101,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,98,101,116,97,32,40,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,0,0,118,109,97,116,32,40,110,42,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,119,109,97,116,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,112,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,0,0,42,69,114,114,111,114,42,58,32,78,111,116,32,101,110,111,117,103,104,32,114,111,119,115,32,102,111,114,32,115,111,108,118,105,110,103,32,116,104,101,32,115,121,115,116,101,109,32,0,0,0,0,0,0,0,0,105,110,32,115,118,100,102,105,116,40,41,0,0,0,0,0,114,118,49,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,116,109,112,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,42,69,114,114,111,114,42,58,32,78,111,32,99,111,110,118,101,114,103,101,110,99,101,32,105,110,32,49,48,48,32,83,86,68,32,105,116,101,114,97,116,105,111,110,115,32,0,0,67,85,66,69,70,65,67,69,0,0,0,0,0,0,0,0,37,46,51,115,0,0,0,0,82,65,45,45,0,0,0,0,82,65,0,0,0,0,0,0,68,69,67,45,45,37,115,0,68,69,67,45,0,0,0,0,82,65,45,45,45,37,115,0,76,79,78,0,0,0,0,0,37,99,76,79,78,0,0,0,37,99,76,65,84,0,0,0,37,115,45,37,115,0,0,0,76,65,84,0,0,0,0,0,76,78,0,0,0,0,0,0,37,99,37,99,76,78,0,0,37,99,37,99,76,84,0,0,76,84,0,0,0,0,0,0,71,76,83,0,0,0,0,0,78,67,80,0,0,0,0,0,26,0,0,0,0,0,0,0,65,90,80,0,83,90,80,0,84,65,78,0,83,84,71,0,83,73,78,0,65,82,67,0,90,80,78,0,90,69,65,0,65,73,82,0,67,89,80,0,67,69,65,0,67,65,82,0,77,69,82,0,67,79,80,0,67,79,69,0,67,79,68,0,67,79,79,0,83,70,76,0,80,65,82,0,77,79,76,0,65,73,84,0,66,79,78,0,80,67,79,0,84,83,67,0,67,83,67,0,81,83,67,0,65,90,80,0,0,0,0,0,83,90,80,0,0,0,0,0,84,65,78,0,0,0,0,0,83,84,71,0,0,0,0,0,83,73,78,0,0,0,0,0,65,82,67,0,0,0,0,0,90,80,78,0,0,0,0,0,90,69,65,0,0,0,0,0,65,73,82,0,0,0,0,0,67,89,80,0,0,0,0,0,67,69,65,0,0,0,0,0,67,65,82,0,0,0,0,0,77,69,82,0,0,0,0,0,83,70,76,0,0,0,0,0,80,65,82,0,0,0,0,0,77,79,76,0,0,0,0,0,65,73,84,0,0,0,0,0,67,79,80,0,0,0,0,0,67,79,69,0,0,0,0,0,67,79,68,0,0,0,0,0,67,79,79,0,0,0,0,0,66,79,78,0,0,0,0,0,80,67,79,0,0,0,0,0,84,83,67,0,0,0,0,0,67,83,67,0,0,0,0,0,81,83,67,0,0,0,0,0,65,95,79,82,68,69,82,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,65,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,0,65,95,37,100,95,37,100,0,66,95,79,82,68,69,82,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,66,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,0,66,95,37,100,95,37,100,0,65,80,95,79,82,68,69,82,0,0,0,0,0,0,0,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,65,80,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,65,80,95,37,100,95,37,100,0,0,0,0,0,0,0,0,66,80,95,79,82,68,69,82,0,0,0,0,0,0,0,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,66,80,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,66,80,95,37,100,95,37,100,0,0,0,0,0,0,0,0,45,83,73,80,0,0,0,0,0,0,0,0,0,0,0,0,91,99,100,108,95,122,115,99,97,108,101,93,32,37,100,120,37,100,45,37,100,32,32,99,111,110,116,61,37,103,32,111,112,116,115,122,61,37,100,32,108,101,110,61,37,100,10,0,91,99,100,108,95,122,115,99,97,108,101,93,32,122,109,105,110,61,37,103,32,122,109,97,120,61,37,103,32,108,101,102,116,61,37,103,32,109,101,100,105,97,110,61,37,103,10,0,91,99,100,108,95,122,115,99,97,108,101,93,32,109,105,110,112,105,120,61,37,100,32,110,103,114,111,119,61,37,100,32,110,103,111,111,100,112,105,120,61,37,100,10,0,0,0,0,91,99,100,108,95,122,115,99,97,108,101,93,32,122,115,108,111,112,101,61,37,103,32,99,101,110,116,101,114,95,112,105,120,61,37,100,32,122,49,61,37,103,32,122,50,61,37,103,10,0,0,0,0,0,0,0,91,115,97,109,112,108,101,73,109,97,103,101,93,32,111,112,116,95,110,112,105,120,47,108,105,110,101,61,37,100,32,99,111,108,95,115,116,101,112,61,37,100,32,110,47,108,105,110,101,61,37,100,10,0,0,0,91,115,97,109,112,108,101,73,109,97,103,101,93,32,110,108,95,105,110,95,115,97,109,112,61,37,100,47,37,100,32,111,112,116,95,110,108,47,115,97,109,112,61,37,100,32,108,115,116,101,112,61,37,100,10,0,0,0,0,0,150,48,7,119,44,97,14,238,186,81,9,153,25,196,109,7,143,244,106,112,53,165,99,233,163,149,100,158,50,136,219,14,164,184,220,121,30,233,213,224,136,217,210,151,43,76,182,9,189,124,177,126,7,45,184,231,145,29,191,144,100,16,183,29,242,32,176,106,72,113,185,243,222,65,190,132,125,212,218,26,235,228,221,109,81,181,212,244,199,133,211,131,86,152,108,19,192,168,107,100,122,249,98,253,236,201,101,138,79,92,1,20,217,108,6,99,99,61,15,250,245,13,8,141,200,32,110,59,94,16,105,76,228,65,96,213,114,113,103,162,209,228,3,60,71,212,4,75,253,133,13,210,107,181,10,165,250,168,181,53,108,152,178,66,214,201,187,219,64,249,188,172,227,108,216,50,117,92,223,69,207,13,214,220,89,61,209,171,172,48,217,38,58,0,222,81,128,81,215,200,22,97,208,191,181,244,180,33,35,196,179,86,153,149,186,207,15,165,189,184,158,184,2,40,8,136,5,95,178,217,12,198,36,233,11,177,135,124,111,47,17,76,104,88,171,29,97,193,61,45,102,182,144,65,220,118,6,113,219,1,188,32,210,152,42,16,213,239,137,133,177,113,31,181,182,6,165,228,191,159,51,212,184,232,162,201,7,120,52,249,0,15,142,168,9,150,24,152,14,225,187,13,106,127,45,61,109,8,151,108,100,145,1,92,99,230,244,81,107,107,98,97,108,28,216,48,101,133,78,0,98,242,237,149,6,108,123,165,1,27,193,244,8,130,87,196,15,245,198,217,176,101,80,233,183,18,234,184,190,139,124,136,185,252,223,29,221,98,73,45,218,21,243,124,211,140,101,76,212,251,88,97,178,77,206,81,181,58,116,0,188,163,226,48,187,212,65,165,223,74,215,149,216,61,109,196,209,164,251,244,214,211,106,233,105,67,252,217,110,52,70,136,103,173,208,184,96,218,115,45,4,68,229,29,3,51,95,76,10,170,201,124,13,221,60,113,5,80,170,65,2,39,16,16,11,190,134,32,12,201,37,181,104,87,179,133,111,32,9,212,102,185,159,228,97,206,14,249,222,94,152,201,217,41,34,152,208,176,180,168,215,199,23,61,179,89,129,13,180,46,59,92,189,183,173,108,186,192,32,131,184,237,182,179,191,154,12,226,182,3,154,210,177,116,57,71,213,234,175,119,210,157,21,38,219,4,131,22,220,115,18,11,99,227,132,59,100,148,62,106,109,13,168,90,106,122,11,207,14,228,157,255,9,147,39,174,0,10,177,158,7,125,68,147,15,240,210,163,8,135,104,242,1,30,254,194,6,105,93,87,98,247,203,103,101,128,113,54,108,25,231,6,107,110,118,27,212,254,224,43,211,137,90,122,218,16,204,74,221,103,111,223,185,249,249,239,190,142,67,190,183,23,213,142,176,96,232,163,214,214,126,147,209,161,196,194,216,56,82,242,223,79,241,103,187,209,103,87,188,166,221,6,181,63,75,54,178,72,218,43,13,216,76,27,10,175,246,74,3,54,96,122,4,65,195,239,96,223,85,223,103,168,239,142,110,49,121,190,105,70,140,179,97,203,26,131,102,188,160,210,111,37,54,226,104,82,149,119,12,204,3,71,11,187,185,22,2,34,47,38,5,85,190,59,186,197,40,11,189,178,146,90,180,43,4,106,179,92,167,255,215,194,49,207,208,181,139,158,217,44,29,174,222,91,176,194,100,155,38,242,99,236,156,163,106,117,10,147,109,2,169,6,9,156,63,54,14,235,133,103,7,114,19,87,0,5,130,74,191,149,20,122,184,226,174,43,177,123,56,27,182,12,155,142,210,146,13,190,213,229,183,239,220,124,33,223,219,11,212,210,211,134,66,226,212,241,248,179,221,104,110,131,218,31,205,22,190,129,91,38,185,246,225,119,176,111,119,71,183,24,230,90,8,136,112,106,15,255,202,59,6,102,92,11,1,17,255,158,101,143,105,174,98,248,211,255,107,97,69,207,108,22,120,226,10,160,238,210,13,215,84,131,4,78,194,179,3,57,97,38,103,167,247,22,96,208,77,71,105,73,219,119,110,62,74,106,209,174,220,90,214,217,102,11,223,64,240,59,216,55,83,174,188,169,197,158,187,222,127,207,178,71,233,255,181,48,28,242,189,189,138,194,186,202,48,147,179,83,166,163,180,36,5,54,208,186,147,6,215,205,41,87,222,84,191,103,217,35,46,122,102,179,184,74,97,196,2,27,104,93,148,43,111,42,55,190,11,180,161,142,12,195,27,223,5,90,141,239,2,45,0,0,0,0,65,49,27,25,130,98,54,50,195,83,45,43,4,197,108,100,69,244,119,125,134,167,90,86,199,150,65,79,8,138,217,200,73,187,194,209,138,232,239,250,203,217,244,227,12,79,181,172,77,126,174,181,142,45,131,158,207,28,152,135,81,18,194,74,16,35,217,83,211,112,244,120,146,65,239,97,85,215,174,46,20,230,181,55,215,181,152,28,150,132,131,5,89,152,27,130,24,169,0,155,219,250,45,176,154,203,54,169,93,93,119,230,28,108,108,255,223,63,65,212,158,14,90,205,162,36,132,149,227,21,159,140,32,70,178,167,97,119,169,190,166,225,232,241,231,208,243,232,36,131,222,195,101,178,197,218,170,174,93,93,235,159,70,68,40,204,107,111,105,253,112,118,174,107,49,57,239,90,42,32,44,9,7,11,109,56,28,18,243,54,70,223,178,7,93,198,113,84,112,237,48,101,107,244,247,243,42,187,182,194,49,162,117,145,28,137,52,160,7,144,251,188,159,23,186,141,132,14,121,222,169,37,56,239,178,60,255,121,243,115,190,72,232,106,125,27,197,65,60,42,222,88,5,79,121,240,68,126,98,233,135,45,79,194,198,28,84,219,1,138,21,148,64,187,14,141,131,232,35,166,194,217,56,191,13,197,160,56,76,244,187,33,143,167,150,10,206,150,141,19,9,0,204,92,72,49,215,69,139,98,250,110,202,83,225,119,84,93,187,186,21,108,160,163,214,63,141,136,151,14,150,145,80,152,215,222,17,169,204,199,210,250,225,236,147,203,250,245,92,215,98,114,29,230,121,107,222,181,84,64,159,132,79,89,88,18,14,22,25,35,21,15,218,112,56,36,155,65,35,61,167,107,253,101,230,90,230,124,37,9,203,87,100,56,208,78,163,174,145,1,226,159,138,24,33,204,167,51,96,253,188,42,175,225,36,173,238,208,63,180,45,131,18,159,108,178,9,134,171,36,72,201,234,21,83,208,41,70,126,251,104,119,101,226,246,121,63,47,183,72,36,54,116,27,9,29,53,42,18,4,242,188,83,75,179,141,72,82,112,222,101,121,49,239,126,96,254,243,230,231,191,194,253,254,124,145,208,213,61,160,203,204,250,54,138,131,187,7,145,154,120,84,188,177,57,101,167,168,75,152,131,59,10,169,152,34,201,250,181,9,136,203,174,16,79,93,239,95,14,108,244,70,205,63,217,109,140,14,194,116,67,18,90,243,2,35,65,234,193,112,108,193,128,65,119,216,71,215,54,151,6,230,45,142,197,181,0,165,132,132,27,188,26,138,65,113,91,187,90,104,152,232,119,67,217,217,108,90,30,79,45,21,95,126,54,12,156,45,27,39,221,28,0,62,18,0,152,185,83,49,131,160,144,98,174,139,209,83,181,146,22,197,244,221,87,244,239,196,148,167,194,239,213,150,217,246,233,188,7,174,168,141,28,183,107,222,49,156,42,239,42,133,237,121,107,202,172,72,112,211,111,27,93,248,46,42,70,225,225,54,222,102,160,7,197,127,99,84,232,84,34,101,243,77,229,243,178,2,164,194,169,27,103,145,132,48,38,160,159,41,184,174,197,228,249,159,222,253,58,204,243,214,123,253,232,207,188,107,169,128,253,90,178,153,62,9,159,178,127,56,132,171,176,36,28,44,241,21,7,53,50,70,42,30,115,119,49,7,180,225,112,72,245,208,107,81,54,131,70,122,119,178,93,99,78,215,250,203,15,230,225,210,204,181,204,249,141,132,215,224,74,18,150,175,11,35,141,182,200,112,160,157,137,65,187,132,70,93,35,3,7,108,56,26,196,63,21,49,133,14,14,40,66,152,79,103,3,169,84,126,192,250,121,85,129,203,98,76,31,197,56,129,94,244,35,152,157,167,14,179,220,150,21,170,27,0,84,229,90,49,79,252,153,98,98,215,216,83,121,206,23,79,225,73,86,126,250,80,149,45,215,123,212,28,204,98,19,138,141,45,82,187,150,52,145,232,187,31,208,217,160,6,236,243,126,94,173,194,101,71,110,145,72,108,47,160,83,117,232,54,18,58,169,7,9,35,106,84,36,8,43,101,63,17,228,121,167,150,165,72,188,143,102,27,145,164,39,42,138,189,224,188,203,242,161,141,208,235,98,222,253,192,35,239,230,217,189,225,188,20,252,208,167,13,63,131,138,38,126,178,145,63,185,36,208,112,248,21,203,105,59,70,230,66,122,119,253,91,181,107,101,220,244,90,126,197,55,9,83,238,118,56,72,247,177,174,9,184,240,159,18,161,51,204,63,138,114,253,36,147,0,0,0,0,55,106,194,1,110,212,132,3,89,190,70,2,220,168,9,7,235,194,203,6,178,124,141,4,133,22,79,5,184,81,19,14,143,59,209,15,214,133,151,13,225,239,85,12,100,249,26,9,83,147,216,8,10,45,158,10,61,71,92,11,112,163,38,28,71,201,228,29,30,119,162,31,41,29,96,30,172,11,47,27,155,97,237,26,194,223,171,24,245,181,105,25,200,242,53,18,255,152,247,19,166,38,177,17,145,76,115,16,20,90,60,21,35,48,254,20,122,142,184,22,77,228,122,23,224,70,77,56,215,44,143,57,142,146,201,59,185,248,11,58,60,238,68,63,11,132,134,62,82,58,192,60,101,80,2,61,88,23,94,54,111,125,156,55,54,195,218,53,1,169,24,52,132,191,87,49,179,213,149,48,234,107,211,50,221,1,17,51,144,229,107,36,167,143,169,37,254,49,239,39,201,91,45,38,76,77,98,35,123,39,160,34,34,153,230,32,21,243,36,33,40,180,120,42,31,222,186,43,70,96,252,41,113,10,62,40,244,28,113,45,195,118,179,44,154,200,245,46,173,162,55,47,192,141,154,112,247,231,88,113,174,89,30,115,153,51,220,114,28,37,147,119,43,79,81,118,114,241,23,116,69,155,213,117,120,220,137,126,79,182,75,127,22,8,13,125,33,98,207,124,164,116,128,121,147,30,66,120,202,160,4,122,253,202,198,123,176,46,188,108,135,68,126,109,222,250,56,111,233,144,250,110,108,134,181,107,91,236,119,106,2,82,49,104,53,56,243,105,8,127,175,98,63,21,109,99,102,171,43,97,81,193,233,96,212,215,166,101,227,189,100,100,186,3,34,102,141,105,224,103,32,203,215,72,23,161,21,73,78,31,83,75,121,117,145,74,252,99,222,79,203,9,28,78,146,183,90,76,165,221,152,77,152,154,196,70,175,240,6,71,246,78,64,69,193,36,130,68,68,50,205,65,115,88,15,64,42,230,73,66,29,140,139,67,80,104,241,84,103,2,51,85,62,188,117,87,9,214,183,86,140,192,248,83,187,170,58,82,226,20,124,80,213,126,190,81,232,57,226,90,223,83,32,91,134,237,102,89,177,135,164,88,52,145,235,93,3,251,41,92,90,69,111,94,109,47,173,95,128,27,53,225,183,113,247,224,238,207,177,226,217,165,115,227,92,179,60,230,107,217,254,231,50,103,184,229,5,13,122,228,56,74,38,239,15,32,228,238,86,158,162,236,97,244,96,237,228,226,47,232,211,136,237,233,138,54,171,235,189,92,105,234,240,184,19,253,199,210,209,252,158,108,151,254,169,6,85,255,44,16,26,250,27,122,216,251,66,196,158,249,117,174,92,248,72,233,0,243,127,131,194,242,38,61,132,240,17,87,70,241,148,65,9,244,163,43,203,245,250,149,141,247,205,255,79,246,96,93,120,217,87,55,186,216,14,137,252,218,57,227,62,219,188,245,113,222,139,159,179,223,210,33,245,221,229,75,55,220,216,12,107,215,239,102,169,214,182,216,239,212,129,178,45,213,4,164,98,208,51,206,160,209,106,112,230,211,93,26,36,210,16,254,94,197,39,148,156,196,126,42,218,198,73,64,24,199,204,86,87,194,251,60,149,195,162,130,211,193,149,232,17,192,168,175,77,203,159,197,143,202,198,123,201,200,241,17,11,201,116,7,68,204,67,109,134,205,26,211,192,207,45,185,2,206,64,150,175,145,119,252,109,144,46,66,43,146,25,40,233,147,156,62,166,150,171,84,100,151,242,234,34,149,197,128,224,148,248,199,188,159,207,173,126,158,150,19,56,156,161,121,250,157,36,111,181,152,19,5,119,153,74,187,49,155,125,209,243,154,48,53,137,141,7,95,75,140,94,225,13,142,105,139,207,143,236,157,128,138,219,247,66,139,130,73,4,137,181,35,198,136,136,100,154,131,191,14,88,130,230,176,30,128,209,218,220,129,84,204,147,132,99,166,81,133,58,24,23,135,13,114,213,134,160,208,226,169,151,186,32,168,206,4,102,170,249,110,164,171,124,120,235,174,75,18,41,175,18,172,111,173,37,198,173,172,24,129,241,167,47,235,51,166,118,85,117,164,65,63,183,165,196,41,248,160,243,67,58,161,170,253,124,163,157,151,190,162,208,115,196,181,231,25,6,180,190,167,64,182,137,205,130,183,12,219,205,178,59,177,15,179,98,15,73,177,85,101,139,176,104,34,215,187,95,72,21,186,6,246,83,184,49,156,145,185,180,138,222,188,131,224,28,189,218,94,90,191,237,52,152,190,0,0,0,0,101,103,188,184,139,200,9,170,238,175,181,18,87,151,98,143,50,240,222,55,220,95,107,37,185,56,215,157,239,40,180,197,138,79,8,125,100,224,189,111,1,135,1,215,184,191,214,74,221,216,106,242,51,119,223,224,86,16,99,88,159,87,25,80,250,48,165,232,20,159,16,250,113,248,172,66,200,192,123,223,173,167,199,103,67,8,114,117,38,111,206,205,112,127,173,149,21,24,17,45,251,183,164,63,158,208,24,135,39,232,207,26,66,143,115,162,172,32,198,176,201,71,122,8,62,175,50,160,91,200,142,24,181,103,59,10,208,0,135,178,105,56,80,47,12,95,236,151,226,240,89,133,135,151,229,61,209,135,134,101,180,224,58,221,90,79,143,207,63,40,51,119,134,16,228,234,227,119,88,82,13,216,237,64,104,191,81,248,161,248,43,240,196,159,151,72,42,48,34,90,79,87,158,226,246,111,73,127,147,8,245,199,125,167,64,213,24,192,252,109,78,208,159,53,43,183,35,141,197,24,150,159,160,127,42,39,25,71,253,186,124,32,65,2,146,143,244,16,247,232,72,168,61,88,20,155,88,63,168,35,182,144,29,49,211,247,161,137,106,207,118,20,15,168,202,172,225,7,127,190,132,96,195,6,210,112,160,94,183,23,28,230,89,184,169,244,60,223,21,76,133,231,194,209,224,128,126,105,14,47,203,123,107,72,119,195,162,15,13,203,199,104,177,115,41,199,4,97,76,160,184,217,245,152,111,68,144,255,211,252,126,80,102,238,27,55,218,86,77,39,185,14,40,64,5,182,198,239,176,164,163,136,12,28,26,176,219,129,127,215,103,57,145,120,210,43,244,31,110,147,3,247,38,59,102,144,154,131,136,63,47,145,237,88,147,41,84,96,68,180,49,7,248,12,223,168,77,30,186,207,241,166,236,223,146,254,137,184,46,70,103,23,155,84,2,112,39,236,187,72,240,113,222,47,76,201,48,128,249,219,85,231,69,99,156,160,63,107,249,199,131,211,23,104,54,193,114,15,138,121,203,55,93,228,174,80,225,92,64,255,84,78,37,152,232,246,115,136,139,174,22,239,55,22,248,64,130,4,157,39,62,188,36,31,233,33,65,120,85,153,175,215,224,139,202,176,92,51,59,182,89,237,94,209,229,85,176,126,80,71,213,25,236,255,108,33,59,98,9,70,135,218,231,233,50,200,130,142,142,112,212,158,237,40,177,249,81,144,95,86,228,130,58,49,88,58,131,9,143,167,230,110,51,31,8,193,134,13,109,166,58,181,164,225,64,189,193,134,252,5,47,41,73,23,74,78,245,175,243,118,34,50,150,17,158,138,120,190,43,152,29,217,151,32,75,201,244,120,46,174,72,192,192,1,253,210,165,102,65,106,28,94,150,247,121,57,42,79,151,150,159,93,242,241,35,229,5,25,107,77,96,126,215,245,142,209,98,231,235,182,222,95,82,142,9,194,55,233,181,122,217,70,0,104,188,33,188,208,234,49,223,136,143,86,99,48,97,249,214,34,4,158,106,154,189,166,189,7,216,193,1,191,54,110,180,173,83,9,8,21,154,78,114,29,255,41,206,165,17,134,123,183,116,225,199,15,205,217,16,146,168,190,172,42,70,17,25,56,35,118,165,128,117,102,198,216,16,1,122,96,254,174,207,114,155,201,115,202,34,241,164,87,71,150,24,239,169,57,173,253,204,94,17,69,6,238,77,118,99,137,241,206,141,38,68,220,232,65,248,100,81,121,47,249,52,30,147,65,218,177,38,83,191,214,154,235,233,198,249,179,140,161,69,11,98,14,240,25,7,105,76,161,190,81,155,60,219,54,39,132,53,153,146,150,80,254,46,46,153,185,84,38,252,222,232,158,18,113,93,140,119,22,225,52,206,46,54,169,171,73,138,17,69,230,63,3,32,129,131,187,118,145,224,227,19,246,92,91,253,89,233,73,152,62,85,241,33,6,130,108,68,97,62,212,170,206,139,198,207,169,55,126,56,65,127,214,93,38,195,110,179,137,118,124,214,238,202,196,111,214,29,89,10,177,161,225,228,30,20,243,129,121,168,75,215,105,203,19,178,14,119,171,92,161,194,185,57,198,126,1,128,254,169,156,229,153,21,36,11,54,160,54,110,81,28,142,167,22,102,134,194,113,218,62,44,222,111,44,73,185,211,148,240,129,4,9,149,230,184,177,123,73,13,163,30,46,177,27,72,62,210,67,45,89,110,251,195,246,219,233,166,145,103,81,31,169,176,204,122,206,12,116,148,97,185,102,241,6,5,222,0,0,0,0,119,7,48,150,238,14,97,44,153,9,81,186,7,109,196,25,112,106,244,143,233,99,165,53,158,100,149,163,14,219,136,50,121,220,184,164,224,213,233,30,151,210,217,136,9,182,76,43,126,177,124,189,231,184,45,7,144,191,29,145,29,183,16,100,106,176,32,242,243,185,113,72,132,190,65,222,26,218,212,125,109,221,228,235,244,212,181,81,131,211,133,199,19,108,152,86,100,107,168,192,253,98,249,122,138,101,201,236,20,1,92,79,99,6,108,217,250,15,61,99,141,8,13,245,59,110,32,200,76,105,16,94,213,96,65,228,162,103,113,114,60,3,228,209,75,4,212,71,210,13,133,253,165,10,181,107,53,181,168,250,66,178,152,108,219,187,201,214,172,188,249,64,50,216,108,227,69,223,92,117,220,214,13,207,171,209,61,89,38,217,48,172,81,222,0,58,200,215,81,128,191,208,97,22,33,180,244,181,86,179,196,35,207,186,149,153,184,189,165,15,40,2,184,158,95,5,136,8,198,12,217,178,177,11,233,36,47,111,124,135,88,104,76,17,193,97,29,171,182,102,45,61,118,220,65,144,1,219,113,6,152,210,32,188,239,213,16,42,113,177,133,137,6,182,181,31,159,191,228,165,232,184,212,51,120,7,201,162,15,0,249,52,150,9,168,142,225,14,152,24,127,106,13,187,8,109,61,45,145,100,108,151,230,99,92,1,107,107,81,244,28,108,97,98,133,101,48,216,242,98,0,78,108,6,149,237,27,1,165,123,130,8,244,193,245,15,196,87,101,176,217,198,18,183,233,80,139,190,184,234,252,185,136,124,98,221,29,223,21,218,45,73,140,211,124,243,251,212,76,101,77,178,97,88,58,181,81,206,163,188,0,116,212,187,48,226,74,223,165,65,61,216,149,215,164,209,196,109,211,214,244,251,67,105,233,106,52,110,217,252,173,103,136,70,218,96,184,208,68,4,45,115,51,3,29,229,170,10,76,95,221,13,124,201,80,5,113,60,39,2,65,170,190,11,16,16,201,12,32,134,87,104,181,37,32,111,133,179,185,102,212,9,206,97,228,159,94,222,249,14,41,217,201,152,176,208,152,34,199,215,168,180,89,179,61,23,46,180,13,129,183,189,92,59,192,186,108,173,237,184,131,32,154,191,179,182,3,182,226,12,116,177,210,154,234,213,71,57,157,210,119,175,4,219,38,21,115,220,22,131,227,99,11,18,148,100,59,132,13,109,106,62,122,106,90,168,228,14,207,11,147,9,255,157,10,0,174,39,125,7,158,177,240,15,147,68,135,8,163,210,30,1,242,104,105,6,194,254,247,98,87,93,128,101,103,203,25,108,54,113,110,107,6,231,254,212,27,118,137,211,43,224,16,218,122,90,103,221,74,204,249,185,223,111,142,190,239,249,23,183,190,67,96,176,142,213,214,214,163,232,161,209,147,126,56,216,194,196,79,223,242,82,209,187,103,241,166,188,87,103,63,181,6,221,72,178,54,75,216,13,43,218,175,10,27,76,54,3,74,246,65,4,122,96,223,96,239,195,168,103,223,85,49,110,142,239,70,105,190,121,203,97,179,140,188,102,131,26,37,111,210,160,82,104,226,54,204,12,119,149,187,11,71,3,34,2,22,185,85,5,38,47,197,186,59,190,178,189,11,40,43,180,90,146,92,179,106,4,194,215,255,167,181,208,207,49,44,217,158,139,91,222,174,29,155,100,194,176,236,99,242,38,117,106,163,156,2,109,147,10,156,9,6,169,235,14,54,63,114,7,103,133,5,0,87,19,149,191,74,130,226,184,122,20,123,177,43,174,12,182,27,56,146,210,142,155,229,213,190,13,124,220,239,183,11,219,223,33,134,211,210,212,241,212,226,66,104,221,179,248,31,218,131,110,129,190,22,205,246,185,38,91,111,176,119,225,24,183,71,119,136,8,90,230,255,15,106,112,102,6,59,202,17,1,11,92,143,101,158,255,248,98,174,105,97,107,255,211,22,108,207,69,160,10,226,120,215,13,210,238,78,4,131,84,57,3,179,194,167,103,38,97,208,96,22,247,73,105,71,77,62,110,119,219,174,209,106,74,217,214,90,220,64,223,11,102,55,216,59,240,169,188,174,83,222,187,158,197,71,178,207,127,48,181,255,233,189,189,242,28,202,186,194,138,83,179,147,48,36,180,163,166,186,208,54,5,205,215,6,147,84,222,87,41,35,217,103,191,179,102,122,46,196,97,74,184,93,104,27,2,42,111,43,148,180,11,190,55,195,12,142,161,90,5,223,27,45,2,239,141,0,0,0,0,25,27,49,65,50,54,98,130,43,45,83,195,100,108,197,4,125,119,244,69,86,90,167,134,79,65,150,199,200,217,138,8,209,194,187,73,250,239,232,138,227,244,217,203,172,181,79,12,181,174,126,77,158,131,45,142,135,152,28,207,74,194,18,81,83,217,35,16,120,244,112,211,97,239,65,146,46,174,215,85,55,181,230,20,28,152,181,215,5,131,132,150,130,27,152,89,155,0,169,24,176,45,250,219,169,54,203,154,230,119,93,93,255,108,108,28,212,65,63,223,205,90,14,158,149,132,36,162,140,159,21,227,167,178,70,32,190,169,119,97,241,232,225,166,232,243,208,231,195,222,131,36,218,197,178,101,93,93,174,170,68,70,159,235,111,107,204,40,118,112,253,105,57,49,107,174,32,42,90,239,11,7,9,44,18,28,56,109,223,70,54,243,198,93,7,178,237,112,84,113,244,107,101,48,187,42,243,247,162,49,194,182,137,28,145,117,144,7,160,52,23,159,188,251,14,132,141,186,37,169,222,121,60,178,239,56,115,243,121,255,106,232,72,190,65,197,27,125,88,222,42,60,240,121,79,5,233,98,126,68,194,79,45,135,219,84,28,198,148,21,138,1,141,14,187,64,166,35,232,131,191,56,217,194,56,160,197,13,33,187,244,76,10,150,167,143,19,141,150,206,92,204,0,9,69,215,49,72,110,250,98,139,119,225,83,202,186,187,93,84,163,160,108,21,136,141,63,214,145,150,14,151,222,215,152,80,199,204,169,17,236,225,250,210,245,250,203,147,114,98,215,92,107,121,230,29,64,84,181,222,89,79,132,159,22,14,18,88,15,21,35,25,36,56,112,218,61,35,65,155,101,253,107,167,124,230,90,230,87,203,9,37,78,208,56,100,1,145,174,163,24,138,159,226,51,167,204,33,42,188,253,96,173,36,225,175,180,63,208,238,159,18,131,45,134,9,178,108,201,72,36,171,208,83,21,234,251,126,70,41,226,101,119,104,47,63,121,246,54,36,72,183,29,9,27,116,4,18,42,53,75,83,188,242,82,72,141,179,121,101,222,112,96,126,239,49,231,230,243,254,254,253,194,191,213,208,145,124,204,203,160,61,131,138,54,250,154,145,7,187,177,188,84,120,168,167,101,57,59,131,152,75,34,152,169,10,9,181,250,201,16,174,203,136,95,239,93,79,70,244,108,14,109,217,63,205,116,194,14,140,243,90,18,67,234,65,35,2,193,108,112,193,216,119,65,128,151,54,215,71,142,45,230,6,165,0,181,197,188,27,132,132,113,65,138,26,104,90,187,91,67,119,232,152,90,108,217,217,21,45,79,30,12,54,126,95,39,27,45,156,62,0,28,221,185,152,0,18,160,131,49,83,139,174,98,144,146,181,83,209,221,244,197,22,196,239,244,87,239,194,167,148,246,217,150,213,174,7,188,233,183,28,141,168,156,49,222,107,133,42,239,42,202,107,121,237,211,112,72,172,248,93,27,111,225,70,42,46,102,222,54,225,127,197,7,160,84,232,84,99,77,243,101,34,2,178,243,229,27,169,194,164,48,132,145,103,41,159,160,38,228,197,174,184,253,222,159,249,214,243,204,58,207,232,253,123,128,169,107,188,153,178,90,253,178,159,9,62,171,132,56,127,44,28,36,176,53,7,21,241,30,42,70,50,7,49,119,115,72,112,225,180,81,107,208,245,122,70,131,54,99,93,178,119,203,250,215,78,210,225,230,15,249,204,181,204,224,215,132,141,175,150,18,74,182,141,35,11,157,160,112,200,132,187,65,137,3,35,93,70,26,56,108,7,49,21,63,196,40,14,14,133,103,79,152,66,126,84,169,3,85,121,250,192,76,98,203,129,129,56,197,31,152,35,244,94,179,14,167,157,170,21,150,220,229,84,0,27,252,79,49,90,215,98,98,153,206,121,83,216,73,225,79,23,80,250,126,86,123,215,45,149,98,204,28,212,45,141,138,19,52,150,187,82,31,187,232,145,6,160,217,208,94,126,243,236,71,101,194,173,108,72,145,110,117,83,160,47,58,18,54,232,35,9,7,169,8,36,84,106,17,63,101,43,150,167,121,228,143,188,72,165,164,145,27,102,189,138,42,39,242,203,188,224,235,208,141,161,192,253,222,98,217,230,239,35,20,188,225,189,13,167,208,252,38,138,131,63,63,145,178,126,112,208,36,185,105,203,21,248,66,230,70,59,91,253,119,122,220,101,107,181,197,126,90,244,238,83,9,55,247,72,56,118,184,9,174,177,161,18,159,240,138,63,204,51,147,36,253,114,0,0,0,0,1,194,106,55,3,132,212,110,2,70,190,89,7,9,168,220,6,203,194,235,4,141,124,178,5,79,22,133,14,19,81,184,15,209,59,143,13,151,133,214,12,85,239,225,9,26,249,100,8,216,147,83,10,158,45,10,11,92,71,61,28,38,163,112,29,228,201,71,31,162,119,30,30,96,29,41,27,47,11,172,26,237,97,155,24,171,223,194,25,105,181,245,18,53,242,200,19,247,152,255,17,177,38,166,16,115,76,145,21,60,90,20,20,254,48,35,22,184,142,122,23,122,228,77,56,77,70,224,57,143,44,215,59,201,146,142,58,11,248,185,63,68,238,60,62,134,132,11,60,192,58,82,61,2,80,101,54,94,23,88,55,156,125,111,53,218,195,54,52,24,169,1,49,87,191,132,48,149,213,179,50,211,107,234,51,17,1,221,36,107,229,144,37,169,143,167,39,239,49,254,38,45,91,201,35,98,77,76,34,160,39,123,32,230,153,34,33,36,243,21,42,120,180,40,43,186,222,31,41,252,96,70,40,62,10,113,45,113,28,244,44,179,118,195,46,245,200,154,47,55,162,173,112,154,141,192,113,88,231,247,115,30,89,174,114,220,51,153,119,147,37,28,118,81,79,43,116,23,241,114,117,213,155,69,126,137,220,120,127,75,182,79,125,13,8,22,124,207,98,33,121,128,116,164,120,66,30,147,122,4,160,202,123,198,202,253,108,188,46,176,109,126,68,135,111,56,250,222,110,250,144,233,107,181,134,108,106,119,236,91,104,49,82,2,105,243,56,53,98,175,127,8,99,109,21,63,97,43,171,102,96,233,193,81,101,166,215,212,100,100,189,227,102,34,3,186,103,224,105,141,72,215,203,32,73,21,161,23,75,83,31,78,74,145,117,121,79,222,99,252,78,28,9,203,76,90,183,146,77,152,221,165,70,196,154,152,71,6,240,175,69,64,78,246,68,130,36,193,65,205,50,68,64,15,88,115,66,73,230,42,67,139,140,29,84,241,104,80,85,51,2,103,87,117,188,62,86,183,214,9,83,248,192,140,82,58,170,187,80,124,20,226,81,190,126,213,90,226,57,232,91,32,83,223,89,102,237,134,88,164,135,177,93,235,145,52,92,41,251,3,94,111,69,90,95,173,47,109,225,53,27,128,224,247,113,183,226,177,207,238,227,115,165,217,230,60,179,92,231,254,217,107,229,184,103,50,228,122,13,5,239,38,74,56,238,228,32,15,236,162,158,86,237,96,244,97,232,47,226,228,233,237,136,211,235,171,54,138,234,105,92,189,253,19,184,240,252,209,210,199,254,151,108,158,255,85,6,169,250,26,16,44,251,216,122,27,249,158,196,66,248,92,174,117,243,0,233,72,242,194,131,127,240,132,61,38,241,70,87,17,244,9,65,148,245,203,43,163,247,141,149,250,246,79,255,205,217,120,93,96,216,186,55,87,218,252,137,14,219,62,227,57,222,113,245,188,223,179,159,139,221,245,33,210,220,55,75,229,215,107,12,216,214,169,102,239,212,239,216,182,213,45,178,129,208,98,164,4,209,160,206,51,211,230,112,106,210,36,26,93,197,94,254,16,196,156,148,39,198,218,42,126,199,24,64,73,194,87,86,204,195,149,60,251,193,211,130,162,192,17,232,149,203,77,175,168,202,143,197,159,200,201,123,198,201,11,17,241,204,68,7,116,205,134,109,67,207,192,211,26,206,2,185,45,145,175,150,64,144,109,252,119,146,43,66,46,147,233,40,25,150,166,62,156,151,100,84,171,149,34,234,242,148,224,128,197,159,188,199,248,158,126,173,207,156,56,19,150,157,250,121,161,152,181,111,36,153,119,5,19,155,49,187,74,154,243,209,125,141,137,53,48,140,75,95,7,142,13,225,94,143,207,139,105,138,128,157,236,139,66,247,219,137,4,73,130,136,198,35,181,131,154,100,136,130,88,14,191,128,30,176,230,129,220,218,209,132,147,204,84,133,81,166,99,135,23,24,58,134,213,114,13,169,226,208,160,168,32,186,151,170,102,4,206,171,164,110,249,174,235,120,124,175,41,18,75,173,111,172,18,172,173,198,37,167,241,129,24,166,51,235,47,164,117,85,118,165,183,63,65,160,248,41,196,161,58,67,243,163,124,253,170,162,190,151,157,181,196,115,208,180,6,25,231,182,64,167,190,183,130,205,137,178,205,219,12,179,15,177,59,177,73,15,98,176,139,101,85,187,215,34,104,186,21,72,95,184,83,246,6,185,145,156,49,188,222,138,180,189,28,224,131,191,90,94,218,190,152,52,237,0,0,0,0,184,188,103,101,170,9,200,139,18,181,175,238,143,98,151,87,55,222,240,50,37,107,95,220,157,215,56,185,197,180,40,239,125,8,79,138,111,189,224,100,215,1,135,1,74,214,191,184,242,106,216,221,224,223,119,51,88,99,16,86,80,25,87,159,232,165,48,250,250,16,159,20,66,172,248,113,223,123,192,200,103,199,167,173,117,114,8,67,205,206,111,38,149,173,127,112,45,17,24,21,63,164,183,251,135,24,208,158,26,207,232,39,162,115,143,66,176,198,32,172,8,122,71,201,160,50,175,62,24,142,200,91,10,59,103,181,178,135,0,208,47,80,56,105,151,236,95,12,133,89,240,226,61,229,151,135,101,134,135,209,221,58,224,180,207,143,79,90,119,51,40,63,234,228,16,134,82,88,119,227,64,237,216,13,248,81,191,104,240,43,248,161,72,151,159,196,90,34,48,42,226,158,87,79,127,73,111,246,199,245,8,147,213,64,167,125,109,252,192,24,53,159,208,78,141,35,183,43,159,150,24,197,39,42,127,160,186,253,71,25,2,65,32,124,16,244,143,146,168,72,232,247,155,20,88,61,35,168,63,88,49,29,144,182,137,161,247,211,20,118,207,106,172,202,168,15,190,127,7,225,6,195,96,132,94,160,112,210,230,28,23,183,244,169,184,89,76,21,223,60,209,194,231,133,105,126,128,224,123,203,47,14,195,119,72,107,203,13,15,162,115,177,104,199,97,4,199,41,217,184,160,76,68,111,152,245,252,211,255,144,238,102,80,126,86,218,55,27,14,185,39,77,182,5,64,40,164,176,239,198,28,12,136,163,129,219,176,26,57,103,215,127,43,210,120,145,147,110,31,244,59,38,247,3,131,154,144,102,145,47,63,136,41,147,88,237,180,68,96,84,12,248,7,49,30,77,168,223,166,241,207,186,254,146,223,236,70,46,184,137,84,155,23,103,236,39,112,2,113,240,72,187,201,76,47,222,219,249,128,48,99,69,231,85], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+10336); +/* memory initializer */ allocate([107,63,160,156,211,131,199,249,193,54,104,23,121,138,15,114,228,93,55,203,92,225,80,174,78,84,255,64,246,232,152,37,174,139,136,115,22,55,239,22,4,130,64,248,188,62,39,157,33,233,31,36,153,85,120,65,139,224,215,175,51,92,176,202,237,89,182,59,85,229,209,94,71,80,126,176,255,236,25,213,98,59,33,108,218,135,70,9,200,50,233,231,112,142,142,130,40,237,158,212,144,81,249,177,130,228,86,95,58,88,49,58,167,143,9,131,31,51,110,230,13,134,193,8,181,58,166,109,189,64,225,164,5,252,134,193,23,73,41,47,175,245,78,74,50,34,118,243,138,158,17,150,152,43,190,120,32,151,217,29,120,244,201,75,192,72,174,46,210,253,1,192,106,65,102,165,247,150,94,28,79,42,57,121,93,159,150,151,229,35,241,242,77,107,25,5,245,215,126,96,231,98,209,142,95,222,182,235,194,9,142,82,122,181,233,55,104,0,70,217,208,188,33,188,136,223,49,234,48,99,86,143,34,214,249,97,154,106,158,4,7,189,166,189,191,1,193,216,173,180,110,54,21,8,9,83,29,114,78,154,165,206,41,255,183,123,134,17,15,199,225,116,146,16,217,205,42,172,190,168,56,25,17,70,128,165,118,35,216,198,102,117,96,122,1,16,114,207,174,254,202,115,201,155,87,164,241,34,239,24,150,71,253,173,57,169,69,17,94,204,118,77,238,6,206,241,137,99,220,68,38,141,100,248,65,232,249,47,121,81,65,147,30,52,83,38,177,218,235,154,214,191,179,249,198,233,11,69,161,140,25,240,14,98,161,76,105,7,60,155,81,190,132,39,54,219,150,146,153,53,46,46,254,80,38,84,185,153,158,232,222,252,140,93,113,18,52,225,22,119,169,54,46,206,17,138,73,171,3,63,230,69,187,131,129,32,227,224,145,118,91,92,246,19,73,233,89,253,241,85,62,152,108,130,6,33,212,62,97,68,198,139,206,170,126,55,169,207,214,127,65,56,110,195,38,93,124,118,137,179,196,202,238,214,89,29,214,111,225,161,177,10,243,20,30,228,75,168,121,129,19,203,105,215,171,119,14,178,185,194,161,92,1,126,198,57,156,169,254,128,36,21,153,229,54,160,54,11,142,28,81,110,134,102,22,167,62,218,113,194,44,111,222,44,148,211,185,73,9,4,129,240,177,184,230,149,163,13,73,123,27,177,46,30,67,210,62,72,251,110,89,45,233,219,246,195,81,103,145,166,204,176,169,31,116,12,206,122,102,185,97,148,222,5,6,241,0,0,0,0,0,0,0,0,1,0,0,0,4,0,4,0,8,0,4,0,2,0,0,0,4,0,5,0,16,0,8,0,2,0,0,0,4,0,6,0,32,0,32,0,2,0,0,0,4,0,4,0,16,0,16,0,3,0,0,0,8,0,16,0,32,0,32,0,3,0,0,0,8,0,16,0,128,0,128,0,3,0,0,0,8,0,32,0,128,0,0,1,3,0,0,0,32,0,128,0,2,1,0,4,3,0,0,0,32,0,2,1,2,1,0,16,3,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,58,32,0,0,0,0,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,49,46,50,46,53,0,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,117,110,101,120,112,101,99,116,101,100,32,101,110,100,32,111,102,32,102,105,108,101,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,105,110,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,99,111,109,112,114,101,115,115,101,100,32,100,97,116,97,32,101,114,114,111,114,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,100,101,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,49,46,50,46,53,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,16,0,17,0,18,0,0,0,8,0,7,0,9,0,6,0,10,0,5,0,11,0,4,0,12,0,3,0,13,0,2,0,14,0,1,0,15,0,0,0,105,110,99,111,114,114,101,99,116,32,104,101,97,100,101,114,32,99,104,101,99,107,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,105,110,118,97,108,105,100,32,119,105,110,100,111,119,32,115,105,122,101,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,104,101,97,100,101,114,32,99,114,99,32,109,105,115,109,97,116,99,104,0,0,0,0,0,105,110,118,97,108,105,100,32,98,108,111,99,107,32,116,121,112,101,0,0,0,0,0,0,105,110,118,97,108,105,100,32,115,116,111,114,101,100,32,98,108,111,99,107,32,108,101,110,103,116,104,115,0,0,0,0,116,111,111,32,109,97,110,121,32,108,101,110,103,116,104,32,111,114,32,100,105,115,116,97,110,99,101,32,115,121,109,98,111,108,115,0,0,0,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,0,0,0,105,110,118,97,108,105,100,32,98,105,116,32,108,101,110,103,116,104,32,114,101,112,101,97,116,0,0,0,0,0,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,45,45,32,109,105,115,115,105,110,103,32,101,110,100,45,111,102,45,98,108,111,99,107,0,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,115,32,115,101,116,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,192,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,160,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,224,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,144,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,208,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,176,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,240,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,200,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,168,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,232,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,152,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,216,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,184,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,248,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,196,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,164,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,228,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,148,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,212,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,180,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,244,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,204,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,172,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,236,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,156,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,220,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,188,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,252,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,194,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,162,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,226,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,146,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,210,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,178,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,242,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,202,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,170,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,234,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,154,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,218,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,186,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,250,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,198,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,166,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,230,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,150,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,214,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,182,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,246,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,206,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,174,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,238,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,158,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,222,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,190,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,254,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,193,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,161,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,225,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,145,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,209,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,177,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,241,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,201,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,169,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,233,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,153,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,217,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,185,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,249,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,197,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,165,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,229,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,149,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,213,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,181,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,245,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,205,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,173,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,237,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,157,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,221,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,189,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,253,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,195,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,163,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,227,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,147,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,211,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,179,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,243,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,203,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,171,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,235,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,155,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,219,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,187,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,251,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,199,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,167,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,231,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,151,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,215,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,183,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,247,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,207,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,175,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,239,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,159,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,223,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,191,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,255,0,16,5,1,0,23,5,1,1,19,5,17,0,27,5,1,16,17,5,5,0,25,5,1,4,21,5,65,0,29,5,1,64,16,5,3,0,24,5,1,2,20,5,33,0,28,5,1,32,18,5,9,0,26,5,1,8,22,5,129,0,64,5,0,0,16,5,2,0,23,5,129,1,19,5,25,0,27,5,1,24,17,5,7,0,25,5,1,6,21,5,97,0,29,5,1,96,16,5,4,0,24,5,1,3,20,5,49,0,28,5,1,48,18,5,13,0,26,5,1,12,22,5,193,0,64,5,0,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,13,0,15,0,17,0,19,0,23,0,27,0,31,0,35,0,43,0,51,0,59,0,67,0,83,0,99,0,115,0,131,0,163,0,195,0,227,0,2,1,0,0,0,0,0,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,17,0,17,0,17,0,17,0,18,0,18,0,18,0,18,0,19,0,19,0,19,0,19,0,20,0,20,0,20,0,20,0,21,0,21,0,21,0,21,0,16,0,73,0,195,0,0,0,1,0,2,0,3,0,4,0,5,0,7,0,9,0,13,0,17,0,25,0,33,0,49,0,65,0,97,0,129,0,193,0,1,1,129,1,1,2,1,3,1,4,1,6,1,8,1,12,1,16,1,24,1,32,1,48,1,64,1,96,0,0,0,0,16,0,16,0,16,0,16,0,17,0,17,0,18,0,18,0,19,0,19,0,20,0,20,0,21,0,21,0,22,0,22,0,23,0,23,0,24,0,24,0,25,0,25,0,26,0,26,0,27,0,27,0,28,0,28,0,29,0,29,0,64,0,64,0,0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,0,100,0,0,248,104,0,0,1,1,0,0,30,1,0,0,15,0,0,0,0,0,0,0,128,104,0,0,232,105,0,0,0,0,0,0,30,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,240,106,0,0,0,0,0,0,19,0,0,0,7,0,0,0,0,0,0,0,12,0,8,0,140,0,8,0,76,0,8,0,204,0,8,0,44,0,8,0,172,0,8,0,108,0,8,0,236,0,8,0,28,0,8,0,156,0,8,0,92,0,8,0,220,0,8,0,60,0,8,0,188,0,8,0,124,0,8,0,252,0,8,0,2,0,8,0,130,0,8,0,66,0,8,0,194,0,8,0,34,0,8,0,162,0,8,0,98,0,8,0,226,0,8,0,18,0,8,0,146,0,8,0,82,0,8,0,210,0,8,0,50,0,8,0,178,0,8,0,114,0,8,0,242,0,8,0,10,0,8,0,138,0,8,0,74,0,8,0,202,0,8,0,42,0,8,0,170,0,8,0,106,0,8,0,234,0,8,0,26,0,8,0,154,0,8,0,90,0,8,0,218,0,8,0,58,0,8,0,186,0,8,0,122,0,8,0,250,0,8,0,6,0,8,0,134,0,8,0,70,0,8,0,198,0,8,0,38,0,8,0,166,0,8,0,102,0,8,0,230,0,8,0,22,0,8,0,150,0,8,0,86,0,8,0,214,0,8,0,54,0,8,0,182,0,8,0,118,0,8,0,246,0,8,0,14,0,8,0,142,0,8,0,78,0,8,0,206,0,8,0,46,0,8,0,174,0,8,0,110,0,8,0,238,0,8,0,30,0,8,0,158,0,8,0,94,0,8,0,222,0,8,0,62,0,8,0,190,0,8,0,126,0,8,0,254,0,8,0,1,0,8,0,129,0,8,0,65,0,8,0,193,0,8,0,33,0,8,0,161,0,8,0,97,0,8,0,225,0,8,0,17,0,8,0,145,0,8,0,81,0,8,0,209,0,8,0,49,0,8,0,177,0,8,0,113,0,8,0,241,0,8,0,9,0,8,0,137,0,8,0,73,0,8,0,201,0,8,0,41,0,8,0,169,0,8,0,105,0,8,0,233,0,8,0,25,0,8,0,153,0,8,0,89,0,8,0,217,0,8,0,57,0,8,0,185,0,8,0,121,0,8,0,249,0,8,0,5,0,8,0,133,0,8,0,69,0,8,0,197,0,8,0,37,0,8,0,165,0,8,0,101,0,8,0,229,0,8,0,21,0,8,0,149,0,8,0,85,0,8,0,213,0,8,0,53,0,8,0,181,0,8,0,117,0,8,0,245,0,8,0,13,0,8,0,141,0,8,0,77,0,8,0,205,0,8,0,45,0,8,0,173,0,8,0,109,0,8,0,237,0,8,0,29,0,8,0,157,0,8,0,93,0,8,0,221,0,8,0,61,0,8,0,189,0,8,0,125,0,8,0,253,0,8,0,19,0,9,0,19,1,9,0,147,0,9,0,147,1,9,0,83,0,9,0,83,1,9,0,211,0,9,0,211,1,9,0,51,0,9,0,51,1,9,0,179,0,9,0,179,1,9,0,115,0,9,0,115,1,9,0,243,0,9,0,243,1,9,0,11,0,9,0,11,1,9,0,139,0,9,0,139,1,9,0,75,0,9,0,75,1,9,0,203,0,9,0,203,1,9,0,43,0,9,0,43,1,9,0,171,0,9,0,171,1,9,0,107,0,9,0,107,1,9,0,235,0,9,0,235,1,9,0,27,0,9,0,27,1,9,0,155,0,9,0,155,1,9,0,91,0,9,0,91,1,9,0,219,0,9,0,219,1,9,0,59,0,9,0,59,1,9,0,187,0,9,0,187,1,9,0,123,0,9,0,123,1,9,0,251,0,9,0,251,1,9,0,7,0,9,0,7,1,9,0,135,0,9,0,135,1,9,0,71,0,9,0,71,1,9,0,199,0,9,0,199,1,9,0,39,0,9,0,39,1,9,0,167,0,9,0,167,1,9,0,103,0,9,0,103,1,9,0,231,0,9,0,231,1,9,0,23,0,9,0,23,1,9,0,151,0,9,0,151,1,9,0,87,0,9,0,87,1,9,0,215,0,9,0,215,1,9,0,55,0,9,0,55,1,9,0,183,0,9,0,183,1,9,0,119,0,9,0,119,1,9,0,247,0,9,0,247,1,9,0,15,0,9,0,15,1,9,0,143,0,9,0,143,1,9,0,79,0,9,0,79,1,9,0,207,0,9,0,207,1,9,0,47,0,9,0,47,1,9,0,175,0,9,0,175,1,9,0,111,0,9,0,111,1,9,0,239,0,9,0,239,1,9,0,31,0,9,0,31,1,9,0,159,0,9,0,159,1,9,0,95,0,9,0,95,1,9,0,223,0,9,0,223,1,9,0,63,0,9,0,63,1,9,0,191,0,9,0,191,1,9,0,127,0,9,0,127,1,9,0,255,0,9,0,255,1,9,0,0,0,7,0,64,0,7,0,32,0,7,0,96,0,7,0,16,0,7,0,80,0,7,0,48,0,7,0,112,0,7,0,8,0,7,0,72,0,7,0,40,0,7,0,104,0,7,0,24,0,7,0,88,0,7,0,56,0,7,0,120,0,7,0,4,0,7,0,68,0,7,0,36,0,7,0,100,0,7,0,20,0,7,0,84,0,7,0,52,0,7,0,116,0,7,0,3,0,8,0,131,0,8,0,67,0,8,0,195,0,8,0,35,0,8,0,163,0,8,0,99,0,8,0,227,0,8,0,0,0,5,0,16,0,5,0,8,0,5,0,24,0,5,0,4,0,5,0,20,0,5,0,12,0,5,0,28,0,5,0,2,0,5,0,18,0,5,0,10,0,5,0,26,0,5,0,6,0,5,0,22,0,5,0,14,0,5,0,30,0,5,0,1,0,5,0,17,0,5,0,9,0,5,0,25,0,5,0,5,0,5,0,21,0,5,0,13,0,5,0,29,0,5,0,3,0,5,0,19,0,5,0,11,0,5,0,27,0,5,0,7,0,5,0,23,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,8,0,0,0,10,0,0,0,12,0,0,0,14,0,0,0,16,0,0,0,20,0,0,0,24,0,0,0,28,0,0,0,32,0,0,0,40,0,0,0,48,0,0,0,56,0,0,0,64,0,0,0,80,0,0,0,96,0,0,0,112,0,0,0,128,0,0,0,160,0,0,0,192,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,6,0,0,0,6,0,0,0,7,0,0,0,7,0,0,0,8,0,0,0,8,0,0,0,9,0,0,0,9,0,0,0,10,0,0,0,10,0,0,0,11,0,0,0,11,0,0,0,12,0,0,0,12,0,0,0,13,0,0,0,13,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,0,128,0,0,0,192,0,0,0,0,1,0,0,128,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,7,0,0,0,0,0,0,0,110,101,101,100,32,100,105,99,116,105,111,110,97,114,121,0,115,116,114,101,97,109,32,101,110,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,105,108,101,32,101,114,114,111,114,0,0,0,0,0,0,115,116,114,101,97,109,32,101,114,114,111,114,0,0,0,0,100,97,116,97,32,101,114,114,111,114,0,0,0,0,0,0,105,110,115,117,102,102,105,99,105,101,110,116,32,109,101,109,111,114,121,0,0,0,0,0,98,117,102,102,101,114,32,101,114,114,111,114,0,0,0,0,105,110,99,111,109,112,97,116,105,98,108,101,32,118,101,114,115,105,111,110,0,0,0,0,64,107,0,0,80,107,0,0,96,107,0,0,104,107,0,0,120,107,0,0,136,107,0,0,152,107,0,0,176,107,0,0,192,107,0,0,96,107,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,105,110,102,105,110,105,116,121,0,0,0,0,0,0,0,0,110,97,110,0,0,0,0,0,95,112,137,0,255,9,47,15,10,0,0,0,100,0,0,0,232,3,0,0,16,39,0,0,160,134,1,0,64,66,15,0,128,150,152,0,0,225,245,5], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+20576); + + + + +var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8); + +assert(tempDoublePtr % 8 == 0); + +function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much + + HEAP8[tempDoublePtr] = HEAP8[ptr]; + + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + +} + +function copyTempDouble(ptr) { + + HEAP8[tempDoublePtr] = HEAP8[ptr]; + + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + + HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; + + HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; + + HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; + + HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; + +} + + + + + var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86}; + + var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"}; + + + var ___errno_state=0;function ___setErrNo(value) { + // For convenient setting and returning of errno. + HEAP32[((___errno_state)>>2)]=value; + return value; + } + + var PATH={splitPath:function (filename) { + var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + return splitPathRe.exec(filename).slice(1); + },normalizeArray:function (parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + 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 the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + return parts; + },normalize:function (path) { + var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.substr(-1) === '/'; + // Normalize the path + path = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), !isAbsolute).join('/'); + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + return (isAbsolute ? '/' : '') + path; + },dirname:function (path) { + var result = PATH.splitPath(path), + root = result[0], + dir = result[1]; + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + return root + dir; + },basename:function (path) { + // EMSCRIPTEN return '/'' for '/', not an empty string + if (path === '/') return '/'; + var lastSlash = path.lastIndexOf('/'); + if (lastSlash === -1) return path; + return path.substr(lastSlash+1); + },extname:function (path) { + return PATH.splitPath(path)[3]; + },join:function () { + var paths = Array.prototype.slice.call(arguments, 0); + return PATH.normalize(paths.join('/')); + },join2:function (l, r) { + return PATH.normalize(l + '/' + r); + },resolve:function () { + var resolvedPath = '', + resolvedAbsolute = false; + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : FS.cwd(); + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + },relative:function (from, to) { + from = PATH.resolve(from).substr(1); + to = PATH.resolve(to).substr(1); + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + var end = arr.length - 1; + for (; end >= 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 < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + return outputParts.join('/'); + }}; + + var TTY={ttys:[],init:function () { + // https://github.com/kripken/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // currently, FS.init does not distinguish if process.stdin is a file or TTY + // // device, it always assumes it's a TTY device. because of this, we're forcing + // // process.stdin to UTF8 encoding to at least make stdin reading compatible + // // with text files until FS.init can be refactored. + // process['stdin']['setEncoding']('utf8'); + // } + },shutdown:function () { + // https://github.com/kripken/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? + // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation + // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists? + // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle + // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call + // process['stdin']['pause'](); + // } + },register:function (dev, ops) { + TTY.ttys[dev] = { input: [], output: [], ops: ops }; + FS.registerDevice(dev, TTY.stream_ops); + },stream_ops:{open:function (stream) { + var tty = TTY.ttys[stream.node.rdev]; + if (!tty) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + stream.tty = tty; + stream.seekable = false; + },close:function (stream) { + // flush any pending line data + if (stream.tty.output.length) { + stream.tty.ops.put_char(stream.tty, 10); + } + },read:function (stream, buffer, offset, length, pos /* ignored */) { + if (!stream.tty || !stream.tty.ops.get_char) { + throw new FS.ErrnoError(ERRNO_CODES.ENXIO); + } + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = stream.tty.ops.get_char(stream.tty); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + },write:function (stream, buffer, offset, length, pos) { + if (!stream.tty || !stream.tty.ops.put_char) { + throw new FS.ErrnoError(ERRNO_CODES.ENXIO); + } + for (var i = 0; i < length; i++) { + try { + stream.tty.ops.put_char(stream.tty, buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + }},default_tty_ops:{get_char:function (tty) { + if (!tty.input.length) { + var result = null; + if (ENVIRONMENT_IS_NODE) { + result = process['stdin']['read'](); + if (!result) { + if (process['stdin']['_readableState'] && process['stdin']['_readableState']['ended']) { + return null; // EOF + } + return undefined; // no data available + } + } else if (typeof window != 'undefined' && + typeof window.prompt == 'function') { + // Browser. + result = window.prompt('Input: '); // returns null on cancel + if (result !== null) { + result += '\n'; + } + } else if (typeof readline == 'function') { + // Command line. + result = readline(); + if (result !== null) { + result += '\n'; + } + } + if (!result) { + return null; + } + tty.input = intArrayFromString(result, true); + } + return tty.input.shift(); + },put_char:function (tty, val) { + if (val === null || val === 10) { + Module['print'](tty.output.join('')); + tty.output = []; + } else { + tty.output.push(TTY.utf8.processCChar(val)); + } + }},default_tty1_ops:{put_char:function (tty, val) { + if (val === null || val === 10) { + Module['printErr'](tty.output.join('')); + tty.output = []; + } else { + tty.output.push(TTY.utf8.processCChar(val)); + } + }}}; + + var MEMFS={ops_table:null,CONTENT_OWNING:1,CONTENT_FLEXIBLE:2,CONTENT_FIXED:3,mount:function (mount) { + return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + },createNode:function (parent, name, mode, dev) { + if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { + // no supported + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (!MEMFS.ops_table) { + 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, + allocate: MEMFS.stream_ops.allocate, + mmap: MEMFS.stream_ops.mmap + } + }, + 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.contents = []; + node.contentMode = MEMFS.CONTENT_FLEXIBLE; + } 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.timestamp = Date.now(); + // add the new node to the parent + if (parent) { + parent.contents[name] = node; + } + return node; + },ensureFlexible:function (node) { + if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) { + var contents = node.contents; + node.contents = Array.prototype.slice.call(contents); + node.contentMode = MEMFS.CONTENT_FLEXIBLE; + } + },node_ops:{getattr:function (node) { + var attr = {}; + // device numbers reuse inode numbers. + 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.contents.length; + } else if (FS.isLink(node.mode)) { + attr.size = node.link.length; + } else { + attr.size = 0; + } + attr.atime = new Date(node.timestamp); + attr.mtime = new Date(node.timestamp); + attr.ctime = new Date(node.timestamp); + // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), + // but this is not required by the standard. + attr.blksize = 4096; + attr.blocks = Math.ceil(attr.size / attr.blksize); + return attr; + },setattr:function (node, attr) { + if (attr.mode !== undefined) { + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + node.timestamp = attr.timestamp; + } + if (attr.size !== undefined) { + MEMFS.ensureFlexible(node); + var contents = node.contents; + if (attr.size < contents.length) contents.length = attr.size; + else while (attr.size > contents.length) contents.push(0); + } + },lookup:function (parent, name) { + throw FS.genericErrors[ERRNO_CODES.ENOENT]; + },mknod:function (parent, name, mode, dev) { + return MEMFS.createNode(parent, name, mode, dev); + },rename:function (old_node, new_dir, new_name) { + // if we're overwriting a directory at new_name, make sure it's empty. + if (FS.isDir(old_node.mode)) { + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + } + if (new_node) { + for (var i in new_node.contents) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + } + } + // do the internal rewiring + delete old_node.parent.contents[old_node.name]; + old_node.name = new_name; + new_dir.contents[new_name] = old_node; + old_node.parent = new_dir; + },unlink:function (parent, name) { + delete parent.contents[name]; + },rmdir:function (parent, name) { + var node = FS.lookupNode(parent, name); + for (var i in node.contents) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + delete parent.contents[name]; + },readdir:function (node) { + var entries = ['.', '..'] + for (var key in node.contents) { + if (!node.contents.hasOwnProperty(key)) { + continue; + } + entries.push(key); + } + return entries; + },symlink:function (parent, newname, oldpath) { + var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0); + node.link = oldpath; + return node; + },readlink:function (node) { + if (!FS.isLink(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + return node.link; + }},stream_ops:{read:function (stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (size > 8 && contents.subarray) { // non-trivial, and typed array + buffer.set(contents.subarray(position, position + size), offset); + } else + { + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } + return size; + },write:function (stream, buffer, offset, length, position, canOwn) { + var node = stream.node; + node.timestamp = Date.now(); + var contents = node.contents; + if (length && contents.length === 0 && position === 0 && buffer.subarray) { + // just replace it with the new data + if (canOwn && offset === 0) { + node.contents = buffer; // this could be a subarray of Emscripten HEAP, or allocated from some other source. + node.contentMode = (buffer.buffer === HEAP8.buffer) ? MEMFS.CONTENT_OWNING : MEMFS.CONTENT_FIXED; + } else { + node.contents = new Uint8Array(buffer.subarray(offset, offset+length)); + node.contentMode = MEMFS.CONTENT_FIXED; + } + return length; + } + MEMFS.ensureFlexible(node); + var contents = node.contents; + while (contents.length < position) contents.push(0); + for (var i = 0; i < length; i++) { + contents[position + i] = buffer[offset + i]; + } + return length; + },llseek:function (stream, offset, whence) { + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + if (FS.isFile(stream.node.mode)) { + position += stream.node.contents.length; + } + } + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + stream.ungotten = []; + stream.position = position; + return position; + },allocate:function (stream, offset, length) { + MEMFS.ensureFlexible(stream.node); + var contents = stream.node.contents; + var limit = offset + length; + while (limit > contents.length) contents.push(0); + },mmap:function (stream, buffer, offset, length, position, prot, flags) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + var ptr; + var allocated; + var contents = stream.node.contents; + // Only make a new copy when MAP_PRIVATE is specified. + if ( !(flags & 2) && + (contents.buffer === buffer || contents.buffer === buffer.buffer) ) { + // We can't emulate MAP_SHARED when the file is not backed by the buffer + // we're mapping to (e.g. the HEAP buffer). + allocated = false; + ptr = contents.byteOffset; + } else { + // Try to avoid unnecessary slices. + if (position > 0 || position + length < contents.length) { + if (contents.subarray) { + contents = contents.subarray(position, position + length); + } else { + contents = Array.prototype.slice.call(contents, position, position + length); + } + } + allocated = true; + ptr = _malloc(length); + if (!ptr) { + throw new FS.ErrnoError(ERRNO_CODES.ENOMEM); + } + buffer.set(contents, ptr); + } + return { ptr: ptr, allocated: allocated }; + }}}; + + var IDBFS={dbs:{},indexedDB:function () { + return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + },DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:function (mount) { + // reuse all of the core MEMFS functionality + return MEMFS.mount.apply(null, arguments); + },syncfs:function (mount, populate, callback) { + IDBFS.getLocalSet(mount, function(err, local) { + if (err) return callback(err); + + IDBFS.getRemoteSet(mount, function(err, remote) { + if (err) return callback(err); + + var src = populate ? remote : local; + var dst = populate ? local : remote; + + IDBFS.reconcile(src, dst, callback); + }); + }); + },getDB:function (name, callback) { + // check the cache first + var db = IDBFS.dbs[name]; + if (db) { + return callback(null, db); + } + + var req; + try { + req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION); + } catch (e) { + return callback(e); + } + req.onupgradeneeded = function(e) { + var db = e.target.result; + var transaction = e.target.transaction; + + var fileStore; + + if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) { + fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME); + } else { + fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME); + } + + fileStore.createIndex('timestamp', 'timestamp', { unique: false }); + }; + req.onsuccess = function() { + db = req.result; + + // add to the cache + IDBFS.dbs[name] = db; + callback(null, db); + }; + req.onerror = function() { + callback(this.error); + }; + },getLocalSet:function (mount, callback) { + var entries = {}; + + function isRealDir(p) { + return p !== '.' && p !== '..'; + }; + function toAbsolute(root) { + return function(p) { + return PATH.join2(root, p); + } + }; + + var check = FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint)); + + while (check.length) { + var path = check.pop(); + var stat; + + try { + stat = FS.stat(path); + } catch (e) { + return callback(e); + } + + if (FS.isDir(stat.mode)) { + check.push.apply(check, FS.readdir(path).filter(isRealDir).map(toAbsolute(path))); + } + + entries[path] = { timestamp: stat.mtime }; + } + + return callback(null, { type: 'local', entries: entries }); + },getRemoteSet:function (mount, callback) { + var entries = {}; + + IDBFS.getDB(mount.mountpoint, function(err, db) { + if (err) return callback(err); + + var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readonly'); + transaction.onerror = function() { callback(this.error); }; + + var store = transaction.objectStore(IDBFS.DB_STORE_NAME); + var index = store.index('timestamp'); + + index.openKeyCursor().onsuccess = function(event) { + var cursor = event.target.result; + + if (!cursor) { + return callback(null, { type: 'remote', db: db, entries: entries }); + } + + entries[cursor.primaryKey] = { timestamp: cursor.key }; + + cursor.continue(); + }; + }); + },loadLocalEntry:function (path, callback) { + var stat, node; + + try { + var lookup = FS.lookupPath(path); + node = lookup.node; + stat = FS.stat(path); + } catch (e) { + return callback(e); + } + + if (FS.isDir(stat.mode)) { + return callback(null, { timestamp: stat.mtime, mode: stat.mode }); + } else if (FS.isFile(stat.mode)) { + return callback(null, { timestamp: stat.mtime, mode: stat.mode, contents: node.contents }); + } else { + return callback(new Error('node type not supported')); + } + },storeLocalEntry:function (path, entry, callback) { + try { + if (FS.isDir(entry.mode)) { + FS.mkdir(path, entry.mode); + } else if (FS.isFile(entry.mode)) { + FS.writeFile(path, entry.contents, { encoding: 'binary', canOwn: true }); + } else { + return callback(new Error('node type not supported')); + } + + FS.utime(path, entry.timestamp, entry.timestamp); + } catch (e) { + return callback(e); + } + + callback(null); + },removeLocalEntry:function (path, callback) { + try { + var lookup = FS.lookupPath(path); + var stat = FS.stat(path); + + if (FS.isDir(stat.mode)) { + FS.rmdir(path); + } else if (FS.isFile(stat.mode)) { + FS.unlink(path); + } + } catch (e) { + return callback(e); + } + + callback(null); + },loadRemoteEntry:function (store, path, callback) { + var req = store.get(path); + req.onsuccess = function(event) { callback(null, event.target.result); }; + req.onerror = function() { callback(this.error); }; + },storeRemoteEntry:function (store, path, entry, callback) { + var req = store.put(entry, path); + req.onsuccess = function() { callback(null); }; + req.onerror = function() { callback(this.error); }; + },removeRemoteEntry:function (store, path, callback) { + var req = store.delete(path); + req.onsuccess = function() { callback(null); }; + req.onerror = function() { callback(this.error); }; + },reconcile:function (src, dst, callback) { + var total = 0; + + var create = []; + Object.keys(src.entries).forEach(function (key) { + var e = src.entries[key]; + var e2 = dst.entries[key]; + if (!e2 || e.timestamp > e2.timestamp) { + create.push(key); + total++; + } + }); + + var remove = []; + Object.keys(dst.entries).forEach(function (key) { + var e = dst.entries[key]; + var e2 = src.entries[key]; + if (!e2) { + remove.push(key); + total++; + } + }); + + if (!total) { + return callback(null); + } + + var errored = false; + var completed = 0; + var db = src.type === 'remote' ? src.db : dst.db; + var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite'); + var store = transaction.objectStore(IDBFS.DB_STORE_NAME); + + function done(err) { + if (err) { + if (!done.errored) { + done.errored = true; + return callback(err); + } + return; + } + if (++completed >= total) { + return callback(null); + } + }; + + transaction.onerror = function() { done(this.error); }; + + // sort paths in ascending order so directory entries are created + // before the files inside them + create.sort().forEach(function (path) { + if (dst.type === 'local') { + IDBFS.loadRemoteEntry(store, path, function (err, entry) { + if (err) return done(err); + IDBFS.storeLocalEntry(path, entry, done); + }); + } else { + IDBFS.loadLocalEntry(path, function (err, entry) { + if (err) return done(err); + IDBFS.storeRemoteEntry(store, path, entry, done); + }); + } + }); + + // sort paths in descending order so files are deleted before their + // parent directories + remove.sort().reverse().forEach(function(path) { + if (dst.type === 'local') { + IDBFS.removeLocalEntry(path, done); + } else { + IDBFS.removeRemoteEntry(store, path, done); + } + }); + }}; + + var NODEFS={isWindows:false,staticInit:function () { + NODEFS.isWindows = !!process.platform.match(/^win/); + },mount:function (mount) { + assert(ENVIRONMENT_IS_NODE); + return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0); + },createNode:function (parent, name, mode, dev) { + if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node = FS.createNode(parent, name, mode); + node.node_ops = NODEFS.node_ops; + node.stream_ops = NODEFS.stream_ops; + return node; + },getMode:function (path) { + var stat; + try { + stat = fs.lstatSync(path); + if (NODEFS.isWindows) { + // On Windows, directories return permission bits 'rw-rw-rw-', even though they have 'rwxrwxrwx', so + // propagate write bits to execute bits. + stat.mode = stat.mode | ((stat.mode & 146) >> 1); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return stat.mode; + },realPath:function (node) { + var parts = []; + while (node.parent !== node) { + parts.push(node.name); + node = node.parent; + } + parts.push(node.mount.opts.root); + parts.reverse(); + return PATH.join.apply(null, parts); + },flagsToPermissionStringMap:{0:"r",1:"r+",2:"r+",64:"r",65:"r+",66:"r+",129:"rx+",193:"rx+",514:"w+",577:"w",578:"w+",705:"wx",706:"wx+",1024:"a",1025:"a",1026:"a+",1089:"a",1090:"a+",1153:"ax",1154:"ax+",1217:"ax",1218:"ax+",4096:"rs",4098:"rs+"},flagsToPermissionString:function (flags) { + if (flags in NODEFS.flagsToPermissionStringMap) { + return NODEFS.flagsToPermissionStringMap[flags]; + } else { + return flags; + } + },node_ops:{getattr:function (node) { + var path = NODEFS.realPath(node); + var stat; + try { + stat = fs.lstatSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + // node.js v0.10.20 doesn't report blksize and blocks on Windows. Fake them with default blksize of 4096. + // See http://support.microsoft.com/kb/140365 + if (NODEFS.isWindows && !stat.blksize) { + stat.blksize = 4096; + } + if (NODEFS.isWindows && !stat.blocks) { + stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0; + } + return { + dev: stat.dev, + ino: stat.ino, + mode: stat.mode, + nlink: stat.nlink, + uid: stat.uid, + gid: stat.gid, + rdev: stat.rdev, + size: stat.size, + atime: stat.atime, + mtime: stat.mtime, + ctime: stat.ctime, + blksize: stat.blksize, + blocks: stat.blocks + }; + },setattr:function (node, attr) { + var path = NODEFS.realPath(node); + try { + if (attr.mode !== undefined) { + fs.chmodSync(path, attr.mode); + // update the common node structure mode as well + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + var date = new Date(attr.timestamp); + fs.utimesSync(path, date, date); + } + if (attr.size !== undefined) { + fs.truncateSync(path, attr.size); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },lookup:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + var mode = NODEFS.getMode(path); + return NODEFS.createNode(parent, name, mode); + },mknod:function (parent, name, mode, dev) { + var node = NODEFS.createNode(parent, name, mode, dev); + // create the backing node for this in the fs root as well + var path = NODEFS.realPath(node); + try { + if (FS.isDir(node.mode)) { + fs.mkdirSync(path, node.mode); + } else { + fs.writeFileSync(path, '', { mode: node.mode }); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return node; + },rename:function (oldNode, newDir, newName) { + var oldPath = NODEFS.realPath(oldNode); + var newPath = PATH.join2(NODEFS.realPath(newDir), newName); + try { + fs.renameSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },unlink:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.unlinkSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },rmdir:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.rmdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },readdir:function (node) { + var path = NODEFS.realPath(node); + try { + return fs.readdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },symlink:function (parent, newName, oldPath) { + var newPath = PATH.join2(NODEFS.realPath(parent), newName); + try { + fs.symlinkSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },readlink:function (node) { + var path = NODEFS.realPath(node); + try { + return fs.readlinkSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }},stream_ops:{open:function (stream) { + var path = NODEFS.realPath(stream.node); + try { + if (FS.isFile(stream.node.mode)) { + stream.nfd = fs.openSync(path, NODEFS.flagsToPermissionString(stream.flags)); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },close:function (stream) { + try { + if (FS.isFile(stream.node.mode) && stream.nfd) { + fs.closeSync(stream.nfd); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },read:function (stream, buffer, offset, length, position) { + // FIXME this is terrible. + var nbuffer = new Buffer(length); + var res; + try { + res = fs.readSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + if (res > 0) { + for (var i = 0; i < res; i++) { + buffer[offset + i] = nbuffer[i]; + } + } + return res; + },write:function (stream, buffer, offset, length, position) { + // FIXME this is terrible. + var nbuffer = new Buffer(buffer.subarray(offset, offset + length)); + var res; + try { + res = fs.writeSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return res; + },llseek:function (stream, offset, whence) { + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + if (FS.isFile(stream.node.mode)) { + try { + var stat = fs.fstatSync(stream.nfd); + position += stat.size; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + } + } + + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + stream.position = position; + return position; + }}}; + + var _stdin=allocate(1, "i32*", ALLOC_STATIC); + + var _stdout=allocate(1, "i32*", ALLOC_STATIC); + + var _stderr=allocate(1, "i32*", ALLOC_STATIC); + + function _fflush(stream) { + // int fflush(FILE *stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fflush.html + // we don't currently perform any user-space buffering of data + }var FS={root:null,mounts:[],devices:[null],streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},handleFSError:function (e) { + if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace(); + return ___setErrNo(e.errno); + },lookupPath:function (path, opts) { + path = PATH.resolve(FS.cwd(), path); + opts = opts || {}; + + var defaults = { + follow_mount: true, + recurse_count: 0 + }; + for (var key in defaults) { + if (opts[key] === undefined) { + opts[key] = defaults[key]; + } + } + + if (opts.recurse_count > 8) { // max recursive lookup of 8 + throw new FS.ErrnoError(ERRNO_CODES.ELOOP); + } + + // split the path + var parts = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), false); + + // start at the root + var current = FS.root; + var current_path = '/'; + + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + // stop resolving + break; + } + + current = FS.lookupNode(current, parts[i]); + current_path = PATH.join2(current_path, parts[i]); + + // jump to the mount's root node if this is a mountpoint + if (FS.isMountpoint(current)) { + if (!islast || (islast && opts.follow_mount)) { + current = current.mounted.root; + } + } + + // by default, lookupPath will not follow a symlink if it is the final path component. + // setting opts.follow = true will override this behavior. + if (!islast || opts.follow) { + var count = 0; + while (FS.isLink(current.mode)) { + var link = FS.readlink(current_path); + current_path = PATH.resolve(PATH.dirname(current_path), link); + + var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count }); + current = lookup.node; + + if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX). + throw new FS.ErrnoError(ERRNO_CODES.ELOOP); + } + } + } + } + + return { path: current_path, node: current }; + },getPath:function (node) { + var path; + while (true) { + if (FS.isRoot(node)) { + var mount = node.mount.mountpoint; + if (!path) return mount; + return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path; + } + path = path ? node.name + '/' + path : node.name; + node = node.parent; + } + },hashName:function (parentid, name) { + var hash = 0; + + + for (var i = 0; i < name.length; i++) { + hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; + } + return ((parentid + hash) >>> 0) % FS.nameTable.length; + },hashAddNode:function (node) { + var hash = FS.hashName(node.parent.id, node.name); + node.name_next = FS.nameTable[hash]; + FS.nameTable[hash] = node; + },hashRemoveNode:function (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:function (parent, name) { + var err = FS.mayLookup(parent); + if (err) { + throw new FS.ErrnoError(err); + } + 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; + } + } + // if we failed to find it in the cache, call into the VFS + return FS.lookup(parent, name); + },createNode:function (parent, name, mode, rdev) { + if (!FS.FSNode) { + FS.FSNode = function(parent, name, mode, rdev) { + if (!parent) { + parent = this; // root node sets parent to itself + } + this.parent = parent; + this.mount = parent.mount; + this.mounted = null; + this.id = FS.nextInode++; + this.name = name; + this.mode = mode; + this.node_ops = {}; + this.stream_ops = {}; + this.rdev = rdev; + }; + + FS.FSNode.prototype = {}; + + // compatibility + var readMode = 292 | 73; + var writeMode = 146; + + // NOTE we must use Object.defineProperties instead of individual calls to + // Object.defineProperty in order to make closure compiler happy + Object.defineProperties(FS.FSNode.prototype, { + read: { + get: function() { return (this.mode & readMode) === readMode; }, + set: function(val) { val ? this.mode |= readMode : this.mode &= ~readMode; } + }, + write: { + get: function() { return (this.mode & writeMode) === writeMode; }, + set: function(val) { val ? this.mode |= writeMode : this.mode &= ~writeMode; } + }, + isFolder: { + get: function() { return FS.isDir(this.mode); }, + }, + isDevice: { + get: function() { return FS.isChrdev(this.mode); }, + }, + }); + } + + var node = new FS.FSNode(parent, name, mode, rdev); + + FS.hashAddNode(node); + + return node; + },destroyNode:function (node) { + FS.hashRemoveNode(node); + },isRoot:function (node) { + return node === node.parent; + },isMountpoint:function (node) { + return !!node.mounted; + },isFile:function (mode) { + return (mode & 61440) === 32768; + },isDir:function (mode) { + return (mode & 61440) === 16384; + },isLink:function (mode) { + return (mode & 61440) === 40960; + },isChrdev:function (mode) { + return (mode & 61440) === 8192; + },isBlkdev:function (mode) { + return (mode & 61440) === 24576; + },isFIFO:function (mode) { + return (mode & 61440) === 4096; + },isSocket:function (mode) { + return (mode & 49152) === 49152; + },flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function (str) { + var flags = FS.flagModes[str]; + if (typeof flags === 'undefined') { + throw new Error('Unknown file open mode: ' + str); + } + return flags; + },flagsToPermissionString:function (flag) { + var accmode = flag & 2097155; + var perms = ['r', 'w', 'rw'][accmode]; + if ((flag & 512)) { + perms += 'w'; + } + return perms; + },nodePermissions:function (node, perms) { + if (FS.ignorePermissions) { + return 0; + } + // return 0 if any user, group or owner bits are set. + if (perms.indexOf('r') !== -1 && !(node.mode & 292)) { + return ERRNO_CODES.EACCES; + } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) { + return ERRNO_CODES.EACCES; + } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) { + return ERRNO_CODES.EACCES; + } + return 0; + },mayLookup:function (dir) { + return FS.nodePermissions(dir, 'x'); + },mayCreate:function (dir, name) { + try { + var node = FS.lookupNode(dir, name); + return ERRNO_CODES.EEXIST; + } catch (e) { + } + return FS.nodePermissions(dir, 'wx'); + },mayDelete:function (dir, name, isdir) { + var node; + try { + node = FS.lookupNode(dir, name); + } catch (e) { + return e.errno; + } + var err = FS.nodePermissions(dir, 'wx'); + if (err) { + return err; + } + if (isdir) { + if (!FS.isDir(node.mode)) { + return ERRNO_CODES.ENOTDIR; + } + if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { + return ERRNO_CODES.EBUSY; + } + } else { + if (FS.isDir(node.mode)) { + return ERRNO_CODES.EISDIR; + } + } + return 0; + },mayOpen:function (node, flags) { + if (!node) { + return ERRNO_CODES.ENOENT; + } + if (FS.isLink(node.mode)) { + return ERRNO_CODES.ELOOP; + } else if (FS.isDir(node.mode)) { + if ((flags & 2097155) !== 0 || // opening for write + (flags & 512)) { + return ERRNO_CODES.EISDIR; + } + } + return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); + },MAX_OPEN_FDS:4096,nextfd:function (fd_start, fd_end) { + fd_start = fd_start || 0; + fd_end = fd_end || FS.MAX_OPEN_FDS; + for (var fd = fd_start; fd <= fd_end; fd++) { + if (!FS.streams[fd]) { + return fd; + } + } + throw new FS.ErrnoError(ERRNO_CODES.EMFILE); + },getStream:function (fd) { + return FS.streams[fd]; + },createStream:function (stream, fd_start, fd_end) { + if (!FS.FSStream) { + FS.FSStream = function(){}; + FS.FSStream.prototype = {}; + // compatibility + Object.defineProperties(FS.FSStream.prototype, { + object: { + get: function() { return this.node; }, + set: function(val) { this.node = val; } + }, + isRead: { + get: function() { return (this.flags & 2097155) !== 1; } + }, + isWrite: { + get: function() { return (this.flags & 2097155) !== 0; } + }, + isAppend: { + get: function() { return (this.flags & 1024); } + } + }); + } + // clone it, so we can return an instance of FSStream + var newStream = new FS.FSStream(); + for (var p in stream) { + newStream[p] = stream[p]; + } + stream = newStream; + var fd = FS.nextfd(fd_start, fd_end); + stream.fd = fd; + FS.streams[fd] = stream; + return stream; + },closeStream:function (fd) { + FS.streams[fd] = null; + },getStreamFromPtr:function (ptr) { + return FS.streams[ptr - 1]; + },getPtrForStream:function (stream) { + return stream ? stream.fd + 1 : 0; + },chrdev_stream_ops:{open:function (stream) { + var device = FS.getDevice(stream.node.rdev); + // override node's stream ops with the device's + stream.stream_ops = device.stream_ops; + // forward the open call + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + },llseek:function () { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + }},major:function (dev) { + return ((dev) >> 8); + },minor:function (dev) { + return ((dev) & 0xff); + },makedev:function (ma, mi) { + return ((ma) << 8 | (mi)); + },registerDevice:function (dev, ops) { + FS.devices[dev] = { stream_ops: ops }; + },getDevice:function (dev) { + return FS.devices[dev]; + },getMounts:function (mount) { + var mounts = []; + var check = [mount]; + + while (check.length) { + var m = check.pop(); + + mounts.push(m); + + check.push.apply(check, m.mounts); + } + + return mounts; + },syncfs:function (populate, callback) { + if (typeof(populate) === 'function') { + callback = populate; + populate = false; + } + + var mounts = FS.getMounts(FS.root.mount); + var completed = 0; + + function done(err) { + if (err) { + if (!done.errored) { + done.errored = true; + return callback(err); + } + return; + } + if (++completed >= mounts.length) { + callback(null); + } + }; + + // sync all mounts + mounts.forEach(function (mount) { + if (!mount.type.syncfs) { + return done(null); + } + mount.type.syncfs(mount, populate, done); + }); + },mount:function (type, opts, mountpoint) { + var root = mountpoint === '/'; + var pseudo = !mountpoint; + var node; + + if (root && FS.root) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } else if (!root && !pseudo) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + mountpoint = lookup.path; // use the absolute path + node = lookup.node; + + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + + if (!FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + } + + var mount = { + type: type, + opts: opts, + mountpoint: mountpoint, + mounts: [] + }; + + // create a root node for the fs + var mountRoot = type.mount(mount); + mountRoot.mount = mount; + mount.root = mountRoot; + + if (root) { + FS.root = mountRoot; + } else if (node) { + // set as a mountpoint + node.mounted = mount; + + // add the new mount to the current mount's children + if (node.mount) { + node.mount.mounts.push(mount); + } + } + + return mountRoot; + },unmount:function (mountpoint) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + if (!FS.isMountpoint(lookup.node)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + // destroy the nodes for this mount, and all its child mounts + var node = lookup.node; + var mount = node.mounted; + var mounts = FS.getMounts(mount); + + Object.keys(FS.nameTable).forEach(function (hash) { + var current = FS.nameTable[hash]; + + while (current) { + var next = current.name_next; + + if (mounts.indexOf(current.mount) !== -1) { + FS.destroyNode(current); + } + + current = next; + } + }); + + // no longer a mountpoint + node.mounted = null; + + // remove this mount from the child mounts + var idx = node.mount.mounts.indexOf(mount); + assert(idx !== -1); + node.mount.mounts.splice(idx, 1); + },lookup:function (parent, name) { + return parent.node_ops.lookup(parent, name); + },mknod:function (path, mode, dev) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var err = FS.mayCreate(parent, name); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.mknod) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return parent.node_ops.mknod(parent, name, mode, dev); + },create:function (path, mode) { + mode = mode !== undefined ? mode : 438 /* 0666 */; + mode &= 4095; + mode |= 32768; + return FS.mknod(path, mode, 0); + },mkdir:function (path, mode) { + mode = mode !== undefined ? mode : 511 /* 0777 */; + mode &= 511 | 512; + mode |= 16384; + return FS.mknod(path, mode, 0); + },mkdev:function (path, mode, dev) { + if (typeof(dev) === 'undefined') { + dev = mode; + mode = 438 /* 0666 */; + } + mode |= 8192; + return FS.mknod(path, mode, dev); + },symlink:function (oldpath, newpath) { + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + var newname = PATH.basename(newpath); + var err = FS.mayCreate(parent, newname); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.symlink) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return parent.node_ops.symlink(parent, newname, oldpath); + },rename:function (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); + // parents must exist + var lookup, old_dir, new_dir; + try { + lookup = FS.lookupPath(old_path, { parent: true }); + old_dir = lookup.node; + lookup = FS.lookupPath(new_path, { parent: true }); + new_dir = lookup.node; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + // need to be part of the same mount + if (old_dir.mount !== new_dir.mount) { + throw new FS.ErrnoError(ERRNO_CODES.EXDEV); + } + // source must exist + var old_node = FS.lookupNode(old_dir, old_name); + // old path should not be an ancestor of the new path + var relative = PATH.relative(old_path, new_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + // new path should not be an ancestor of the old path + relative = PATH.relative(new_path, old_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + // see if the new path already exists + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + // not fatal + } + // early out if nothing needs to change + if (old_node === new_node) { + return; + } + // we'll need to delete the old entry + var isdir = FS.isDir(old_node.mode); + var err = FS.mayDelete(old_dir, old_name, isdir); + if (err) { + throw new FS.ErrnoError(err); + } + // need delete permissions if we'll be overwriting. + // need create permissions if new doesn't already exist. + err = new_node ? + FS.mayDelete(new_dir, new_name, isdir) : + FS.mayCreate(new_dir, new_name); + if (err) { + throw new FS.ErrnoError(err); + } + if (!old_dir.node_ops.rename) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + // if we are going to change the parent, check write permissions + if (new_dir !== old_dir) { + err = FS.nodePermissions(old_dir, 'w'); + if (err) { + throw new FS.ErrnoError(err); + } + } + // remove the node from the lookup hash + FS.hashRemoveNode(old_node); + // do the underlying fs rename + try { + old_dir.node_ops.rename(old_node, new_dir, new_name); + } catch (e) { + throw e; + } finally { + // add the node back to the hash (in case node_ops.rename + // changed its name) + FS.hashAddNode(old_node); + } + },rmdir:function (path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var err = FS.mayDelete(parent, name, true); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.rmdir) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + parent.node_ops.rmdir(parent, name); + FS.destroyNode(node); + },readdir:function (path) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node.node_ops.readdir) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + return node.node_ops.readdir(node); + },unlink:function (path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var err = FS.mayDelete(parent, name, false); + if (err) { + // POSIX says unlink should set EPERM, not EISDIR + if (err === ERRNO_CODES.EISDIR) err = ERRNO_CODES.EPERM; + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.unlink) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + parent.node_ops.unlink(parent, name); + FS.destroyNode(node); + },readlink:function (path) { + var lookup = FS.lookupPath(path); + var link = lookup.node; + if (!link.node_ops.readlink) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + return link.node_ops.readlink(link); + },stat:function (path, dontFollow) { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var node = lookup.node; + if (!node.node_ops.getattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return node.node_ops.getattr(node); + },lstat:function (path) { + return FS.stat(path, true); + },chmod:function (path, mode, dontFollow) { + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + node.node_ops.setattr(node, { + mode: (mode & 4095) | (node.mode & ~4095), + timestamp: Date.now() + }); + },lchmod:function (path, mode) { + FS.chmod(path, mode, true); + },fchmod:function (fd, mode) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + FS.chmod(stream.node, mode); + },chown:function (path, uid, gid, dontFollow) { + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + node.node_ops.setattr(node, { + timestamp: Date.now() + // we ignore the uid / gid for now + }); + },lchown:function (path, uid, gid) { + FS.chown(path, uid, gid, true); + },fchown:function (fd, uid, gid) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + FS.chown(stream.node, uid, gid); + },truncate:function (path, len) { + if (len < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: true }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!FS.isFile(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var err = FS.nodePermissions(node, 'w'); + if (err) { + throw new FS.ErrnoError(err); + } + node.node_ops.setattr(node, { + size: len, + timestamp: Date.now() + }); + },ftruncate:function (fd, len) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + FS.truncate(stream.node, len); + },utime:function (path, atime, mtime) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + node.node_ops.setattr(node, { + timestamp: Math.max(atime, mtime) + }); + },open:function (path, flags, mode, fd_start, fd_end) { + flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags; + mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode; + if ((flags & 64)) { + mode = (mode & 4095) | 32768; + } else { + mode = 0; + } + var node; + if (typeof path === 'object') { + node = path; + } else { + path = PATH.normalize(path); + try { + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072) + }); + node = lookup.node; + } catch (e) { + // ignore + } + } + // perhaps we need to create the node + if ((flags & 64)) { + if (node) { + // if O_CREAT and O_EXCL are set, error out if the node already exists + if ((flags & 128)) { + throw new FS.ErrnoError(ERRNO_CODES.EEXIST); + } + } else { + // node doesn't exist, try to create it + node = FS.mknod(path, mode, 0); + } + } + if (!node) { + throw new FS.ErrnoError(ERRNO_CODES.ENOENT); + } + // can't truncate a device + if (FS.isChrdev(node.mode)) { + flags &= ~512; + } + // check permissions + var err = FS.mayOpen(node, flags); + if (err) { + throw new FS.ErrnoError(err); + } + // do truncation if necessary + if ((flags & 512)) { + FS.truncate(node, 0); + } + // we've already handled these, don't pass down to the underlying vfs + flags &= ~(128 | 512); + + // register the stream with the filesystem + var stream = FS.createStream({ + node: node, + path: FS.getPath(node), // we want the absolute path to the node + flags: flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + // used by the file family libc calls (fopen, fwrite, ferror, etc.) + ungotten: [], + error: false + }, fd_start, fd_end); + // call the new stream's open function + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + if (Module['logReadFiles'] && !(flags & 1)) { + if (!FS.readFiles) FS.readFiles = {}; + if (!(path in FS.readFiles)) { + FS.readFiles[path] = 1; + Module['printErr']('read file: ' + path); + } + } + return stream; + },close:function (stream) { + try { + if (stream.stream_ops.close) { + stream.stream_ops.close(stream); + } + } catch (e) { + throw e; + } finally { + FS.closeStream(stream.fd); + } + },llseek:function (stream, offset, whence) { + if (!stream.seekable || !stream.stream_ops.llseek) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + return stream.stream_ops.llseek(stream, offset, whence); + },read:function (stream, buffer, offset, length, position) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!stream.stream_ops.read) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var seeking = true; + if (typeof position === 'undefined') { + position = stream.position; + seeking = false; + } else if (!stream.seekable) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); + if (!seeking) stream.position += bytesRead; + return bytesRead; + },write:function (stream, buffer, offset, length, position, canOwn) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!stream.stream_ops.write) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var seeking = true; + if (typeof position === 'undefined') { + position = stream.position; + seeking = false; + } else if (!stream.seekable) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + if (stream.flags & 1024) { + // seek to the end before writing in append mode + FS.llseek(stream, 0, 2); + } + var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); + if (!seeking) stream.position += bytesWritten; + return bytesWritten; + },allocate:function (stream, offset, length) { + if (offset < 0 || length <= 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (!FS.isFile(stream.node.mode) && !FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + if (!stream.stream_ops.allocate) { + throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP); + } + stream.stream_ops.allocate(stream, offset, length); + },mmap:function (stream, buffer, offset, length, position, prot, flags) { + // TODO if PROT is PROT_WRITE, make sure we have write access + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(ERRNO_CODES.EACCES); + } + if (!stream.stream_ops.mmap) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + return stream.stream_ops.mmap(stream, buffer, offset, length, position, prot, flags); + },ioctl:function (stream, cmd, arg) { + if (!stream.stream_ops.ioctl) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTTY); + } + return stream.stream_ops.ioctl(stream, cmd, arg); + },readFile:function (path, opts) { + opts = opts || {}; + opts.flags = opts.flags || 'r'; + opts.encoding = opts.encoding || 'binary'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error('Invalid encoding type "' + opts.encoding + '"'); + } + var ret; + 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') { + ret = ''; + var utf8 = new Runtime.UTF8Processor(); + for (var i = 0; i < length; i++) { + ret += utf8.processCChar(buf[i]); + } + } else if (opts.encoding === 'binary') { + ret = buf; + } + FS.close(stream); + return ret; + },writeFile:function (path, data, opts) { + opts = opts || {}; + opts.flags = opts.flags || 'w'; + opts.encoding = opts.encoding || 'utf8'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error('Invalid encoding type "' + opts.encoding + '"'); + } + var stream = FS.open(path, opts.flags, opts.mode); + if (opts.encoding === 'utf8') { + var utf8 = new Runtime.UTF8Processor(); + var buf = new Uint8Array(utf8.processJSString(data)); + FS.write(stream, buf, 0, buf.length, 0, opts.canOwn); + } else if (opts.encoding === 'binary') { + FS.write(stream, data, 0, data.length, 0, opts.canOwn); + } + FS.close(stream); + },cwd:function () { + return FS.currentPath; + },chdir:function (path) { + var lookup = FS.lookupPath(path, { follow: true }); + if (!FS.isDir(lookup.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + var err = FS.nodePermissions(lookup.node, 'x'); + if (err) { + throw new FS.ErrnoError(err); + } + FS.currentPath = lookup.path; + },createDefaultDirectories:function () { + FS.mkdir('/tmp'); + },createDefaultDevices:function () { + // create /dev + FS.mkdir('/dev'); + // setup /dev/null + FS.registerDevice(FS.makedev(1, 3), { + read: function() { return 0; }, + write: function() { return 0; } + }); + FS.mkdev('/dev/null', FS.makedev(1, 3)); + // setup /dev/tty and /dev/tty1 + // stderr needs to print output using Module['printErr'] + // so we register a second tty just for it. + 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)); + // we're not going to emulate the actual shm device, + // just create the tmp dirs that reside in it commonly + FS.mkdir('/dev/shm'); + FS.mkdir('/dev/shm/tmp'); + },createStandardStreams:function () { + // TODO deprecate the old functionality of a single + // input / output callback and that utilizes FS.createDevice + // and instead require a unique set of stream ops + + // by default, we symlink the standard streams to the + // default tty devices. however, if the standard streams + // have been overwritten we create a unique device for + // them instead. + if (Module['stdin']) { + FS.createDevice('/dev', 'stdin', Module['stdin']); + } else { + FS.symlink('/dev/tty', '/dev/stdin'); + } + if (Module['stdout']) { + FS.createDevice('/dev', 'stdout', null, Module['stdout']); + } else { + FS.symlink('/dev/tty', '/dev/stdout'); + } + if (Module['stderr']) { + FS.createDevice('/dev', 'stderr', null, Module['stderr']); + } else { + FS.symlink('/dev/tty1', '/dev/stderr'); + } + + // open default streams for the stdin, stdout and stderr devices + var stdin = FS.open('/dev/stdin', 'r'); + HEAP32[((_stdin)>>2)]=FS.getPtrForStream(stdin); + assert(stdin.fd === 0, 'invalid handle for stdin (' + stdin.fd + ')'); + + var stdout = FS.open('/dev/stdout', 'w'); + HEAP32[((_stdout)>>2)]=FS.getPtrForStream(stdout); + assert(stdout.fd === 1, 'invalid handle for stdout (' + stdout.fd + ')'); + + var stderr = FS.open('/dev/stderr', 'w'); + HEAP32[((_stderr)>>2)]=FS.getPtrForStream(stderr); + assert(stderr.fd === 2, 'invalid handle for stderr (' + stderr.fd + ')'); + },ensureErrnoError:function () { + if (FS.ErrnoError) return; + FS.ErrnoError = function ErrnoError(errno) { + this.errno = errno; + for (var key in ERRNO_CODES) { + if (ERRNO_CODES[key] === errno) { + this.code = key; + break; + } + } + this.message = ERRNO_MESSAGES[errno]; + }; + FS.ErrnoError.prototype = new Error(); + FS.ErrnoError.prototype.constructor = FS.ErrnoError; + // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info) + [ERRNO_CODES.ENOENT].forEach(function(code) { + FS.genericErrors[code] = new FS.ErrnoError(code); + FS.genericErrors[code].stack = ''; + }); + },staticInit:function () { + FS.ensureErrnoError(); + + FS.nameTable = new Array(4096); + + FS.mount(MEMFS, {}, '/'); + + FS.createDefaultDirectories(); + FS.createDefaultDevices(); + },init:function (input, output, error) { + assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); + FS.init.initialized = true; + + FS.ensureErrnoError(); + + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + Module['stdin'] = input || Module['stdin']; + Module['stdout'] = output || Module['stdout']; + Module['stderr'] = error || Module['stderr']; + + FS.createStandardStreams(); + },quit:function () { + FS.init.initialized = false; + for (var i = 0; i < FS.streams.length; i++) { + var stream = FS.streams[i]; + if (!stream) { + continue; + } + FS.close(stream); + } + },getMode:function (canRead, canWrite) { + var mode = 0; + if (canRead) mode |= 292 | 73; + if (canWrite) mode |= 146; + return mode; + },joinPath:function (parts, forceRelative) { + var path = PATH.join.apply(null, parts); + if (forceRelative && path[0] == '/') path = path.substr(1); + return path; + },absolutePath:function (relative, base) { + return PATH.resolve(base, relative); + },standardizePath:function (path) { + return PATH.normalize(path); + },findObject:function (path, dontResolveLastLink) { + var ret = FS.analyzePath(path, dontResolveLastLink); + if (ret.exists) { + return ret.object; + } else { + ___setErrNo(ret.error); + return null; + } + },analyzePath:function (path, dontResolveLastLink) { + // operate from within the context of the symlink's target + 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; + },createFolder:function (parent, name, canRead, canWrite) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var mode = FS.getMode(canRead, canWrite); + return FS.mkdir(path, mode); + },createPath:function (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) { + // ignore EEXIST + } + parent = current; + } + return current; + },createFile:function (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:function (parent, name, data, canRead, canWrite, canOwn) { + var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(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; i < len; ++i) arr[i] = data.charCodeAt(i); + data = arr; + } + // make sure we can write to the file + FS.chmod(node, mode | 146); + var stream = FS.open(node, 'w'); + FS.write(stream, data, 0, data.length, 0, canOwn); + FS.close(stream); + FS.chmod(node, mode); + } + return node; + },createDevice:function (parent, name, input, output) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var mode = FS.getMode(!!input, !!output); + if (!FS.createDevice.major) FS.createDevice.major = 64; + var dev = FS.makedev(FS.createDevice.major++, 0); + // Create a fake device that a set of stream ops to emulate + // the old behavior. + FS.registerDevice(dev, { + open: function(stream) { + stream.seekable = false; + }, + close: function(stream) { + // flush any pending line data + if (output && output.buffer && output.buffer.length) { + output(10); + } + }, + read: function(stream, buffer, offset, length, pos /* ignored */) { + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = input(); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + }, + write: function(stream, buffer, offset, length, pos) { + for (var i = 0; i < length; i++) { + try { + output(buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + } + }); + return FS.mkdev(path, mode, dev); + },createLink:function (parent, name, target, canRead, canWrite) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + return FS.symlink(target, path); + },forceLoadFile:function (obj) { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + var success = true; + if (typeof XMLHttpRequest !== 'undefined') { + throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else if (Module['read']) { + // Command-line. + try { + // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as + // read() will try to parse UTF8. + obj.contents = intArrayFromString(Module['read'](obj.url), true); + } catch (e) { + success = false; + } + } else { + throw new Error('Cannot load without read() or XMLHttpRequest.'); + } + if (!success) ___setErrNo(ERRNO_CODES.EIO); + return success; + },createLazyFile:function (parent, name, url, canRead, canWrite) { + // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. + function LazyUint8Array() { + this.lengthKnown = false; + this.chunks = []; // Loaded chunks. Index is the chunk number + } + LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = Math.floor(idx / this.chunkSize); + return this.getter(chunkNum)[chunkOffset]; + } + LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) { + this.getter = getter; + } + LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("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 chunkSize = 1024*1024; // Chunk size in bytes + + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (function(from, to) { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + if (typeof Uint8Array != 'undefined') 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)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(xhr.response || []); + } else { + return intArrayFromString(xhr.responseText || '', true); + } + }); + var lazyArray = this; + lazyArray.setDataGetter(function(chunkNum) { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); + return lazyArray.chunks[chunkNum]; + }); + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } + if (typeof XMLHttpRequest !== 'undefined') { + if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; + var lazyArray = new LazyUint8Array(); + Object.defineProperty(lazyArray, "length", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + }); + Object.defineProperty(lazyArray, "chunkSize", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + }); + + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + + var node = FS.createFile(parent, name, properties, canRead, canWrite); + // This is a total hack, but I want to get this lazy file code out of the + // core of MEMFS. If we want to keep this lazy file concept I feel it should + // be its own thin LAZYFS proxying calls to MEMFS. + if (properties.contents) { + node.contents = properties.contents; + } else if (properties.url) { + node.contents = null; + node.url = properties.url; + } + // override each stream op with one that tries to force load the lazy file first + var stream_ops = {}; + var keys = Object.keys(node.stream_ops); + keys.forEach(function(key) { + var fn = node.stream_ops[key]; + stream_ops[key] = function forceLoadLazyFile() { + if (!FS.forceLoadFile(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + return fn.apply(null, arguments); + }; + }); + // use a custom read function + stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) { + if (!FS.forceLoadFile(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (contents.slice) { // normal array + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } else { + for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR + buffer[offset + i] = contents.get(position + i); + } + } + return size; + }; + node.stream_ops = stream_ops; + return node; + },createPreloadedFile:function (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn) { + Browser.init(); + // TODO we should allow people to just pass in a complete filename instead + // of parent and name being that we just join them anyways + var fullname = name ? PATH.resolve(PATH.join2(parent, name)) : parent; + function processData(byteArray) { + function finish(byteArray) { + if (!dontCreateFile) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + } + if (onload) onload(); + removeRunDependency('cp ' + fullname); + } + var handled = false; + Module['preloadPlugins'].forEach(function(plugin) { + if (handled) return; + if (plugin['canHandle'](fullname)) { + plugin['handle'](byteArray, fullname, finish, function() { + if (onerror) onerror(); + removeRunDependency('cp ' + fullname); + }); + handled = true; + } + }); + if (!handled) finish(byteArray); + } + addRunDependency('cp ' + fullname); + if (typeof url == 'string') { + Browser.asyncLoad(url, function(byteArray) { + processData(byteArray); + }, onerror); + } else { + processData(url); + } + },indexedDB:function () { + return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + },DB_NAME:function () { + return 'EM_FS_' + window.location.pathname; + },DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function (paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = function openRequest_onupgradeneeded() { + console.log('creating db'); + var db = openRequest.result; + db.createObjectStore(FS.DB_STORE_NAME); + }; + openRequest.onsuccess = function openRequest_onsuccess() { + var db = openRequest.result; + var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite'); + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var putRequest = files.put(FS.analyzePath(path).object.contents, path); + putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) finish() }; + putRequest.onerror = function putRequest_onerror() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + },loadFilesFromDB:function (paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = onerror; // no database to load from + openRequest.onsuccess = function openRequest_onsuccess() { + var db = openRequest.result; + try { + var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly'); + } catch(e) { + onerror(e); + return; + } + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var getRequest = files.get(path); + getRequest.onsuccess = function getRequest_onsuccess() { + if (FS.analyzePath(path).exists) { + FS.unlink(path); + } + FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true); + ok++; + if (ok + fail == total) finish(); + }; + getRequest.onerror = function getRequest_onerror() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + }};function _lseek(fildes, offset, whence) { + // off_t lseek(int fildes, off_t offset, int whence); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/lseek.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + return FS.llseek(stream, offset, whence); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + + Module["_i64Subtract"] = _i64Subtract; + + var _fabsf=Math_abs; + + + + + Module["_strlen"] = _strlen; + + function __reallyNegative(x) { + return x < 0 || (x === 0 && (1/x) === -Infinity); + }function __formatString(format, varargs) { + var textIndex = format; + var argIndex = 0; + function getNextArg(type) { + // NOTE: Explicitly ignoring type safety. Otherwise this fails: + // int x = 4; printf("%c\n", (char)x); + var ret; + if (type === 'double') { + ret = (HEAP32[((tempDoublePtr)>>2)]=HEAP32[(((varargs)+(argIndex))>>2)],HEAP32[(((tempDoublePtr)+(4))>>2)]=HEAP32[(((varargs)+((argIndex)+(4)))>>2)],(+(HEAPF64[(tempDoublePtr)>>3]))); + } else if (type == 'i64') { + ret = [HEAP32[(((varargs)+(argIndex))>>2)], + HEAP32[(((varargs)+(argIndex+4))>>2)]]; + + } else { + type = 'i32'; // varargs are always i32, i64, or double + ret = HEAP32[(((varargs)+(argIndex))>>2)]; + } + argIndex += Runtime.getNativeFieldSize(type); + return ret; + } + + var ret = []; + var curr, next, currArg; + while(1) { + var startTextIndex = textIndex; + curr = HEAP8[(textIndex)]; + if (curr === 0) break; + next = HEAP8[((textIndex+1)|0)]; + if (curr == 37) { + // Handle flags. + var flagAlwaysSigned = false; + var flagLeftAlign = false; + var flagAlternative = false; + var flagZeroPad = false; + var flagPadSign = false; + flagsLoop: while (1) { + switch (next) { + case 43: + flagAlwaysSigned = true; + break; + case 45: + flagLeftAlign = true; + break; + case 35: + flagAlternative = true; + break; + case 48: + if (flagZeroPad) { + break flagsLoop; + } else { + flagZeroPad = true; + break; + } + case 32: + flagPadSign = true; + break; + default: + break flagsLoop; + } + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } + + // Handle width. + var width = 0; + if (next == 42) { + width = getNextArg('i32'); + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } else { + while (next >= 48 && next <= 57) { + width = width * 10 + (next - 48); + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } + } + + // Handle precision. + var precisionSet = false, precision = -1; + if (next == 46) { + precision = 0; + precisionSet = true; + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + if (next == 42) { + precision = getNextArg('i32'); + textIndex++; + } else { + while(1) { + var precisionChr = HEAP8[((textIndex+1)|0)]; + if (precisionChr < 48 || + precisionChr > 57) break; + precision = precision * 10 + (precisionChr - 48); + textIndex++; + } + } + next = HEAP8[((textIndex+1)|0)]; + } + if (precision < 0) { + precision = 6; // Standard default. + precisionSet = false; + } + + // Handle integer sizes. WARNING: These assume a 32-bit architecture! + var argSize; + switch (String.fromCharCode(next)) { + case 'h': + var nextNext = HEAP8[((textIndex+2)|0)]; + if (nextNext == 104) { + textIndex++; + argSize = 1; // char (actually i32 in varargs) + } else { + argSize = 2; // short (actually i32 in varargs) + } + break; + case 'l': + var nextNext = HEAP8[((textIndex+2)|0)]; + if (nextNext == 108) { + textIndex++; + argSize = 8; // long long + } else { + argSize = 4; // long + } + break; + case 'L': // long long + case 'q': // int64_t + case 'j': // intmax_t + argSize = 8; + break; + case 'z': // size_t + case 't': // ptrdiff_t + case 'I': // signed ptrdiff_t or unsigned size_t + argSize = 4; + break; + default: + argSize = null; + } + if (argSize) textIndex++; + next = HEAP8[((textIndex+1)|0)]; + + // Handle type specifier. + switch (String.fromCharCode(next)) { + case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': case 'p': { + // Integer. + var signed = next == 100 || next == 105; + argSize = argSize || 4; + var currArg = getNextArg('i' + (argSize * 8)); + var origArg = currArg; + var argText; + // Flatten i64-1 [low, high] into a (slightly rounded) double + if (argSize == 8) { + currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == 117); + } + // Truncate to requested size. + if (argSize <= 4) { + var limit = Math.pow(256, argSize) - 1; + currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8); + } + // Format the number. + var currAbsArg = Math.abs(currArg); + var prefix = ''; + if (next == 100 || next == 105) { + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else + argText = reSign(currArg, 8 * argSize, 1).toString(10); + } else if (next == 117) { + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else + argText = unSign(currArg, 8 * argSize, 1).toString(10); + currArg = Math.abs(currArg); + } else if (next == 111) { + argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8); + } else if (next == 120 || next == 88) { + prefix = (flagAlternative && currArg != 0) ? '0x' : ''; + if (argSize == 8 && i64Math) { + if (origArg[1]) { + argText = (origArg[1]>>>0).toString(16); + var lower = (origArg[0]>>>0).toString(16); + while (lower.length < 8) lower = '0' + lower; + argText += lower; + } else { + argText = (origArg[0]>>>0).toString(16); + } + } else + if (currArg < 0) { + // Represent negative numbers in hex as 2's complement. + currArg = -currArg; + argText = (currAbsArg - 1).toString(16); + var buffer = []; + for (var i = 0; i < argText.length; i++) { + buffer.push((0xF - parseInt(argText[i], 16)).toString(16)); + } + argText = buffer.join(''); + while (argText.length < argSize * 2) argText = 'f' + argText; + } else { + argText = currAbsArg.toString(16); + } + if (next == 88) { + prefix = prefix.toUpperCase(); + argText = argText.toUpperCase(); + } + } else if (next == 112) { + if (currAbsArg === 0) { + argText = '(nil)'; + } else { + prefix = '0x'; + argText = currAbsArg.toString(16); + } + } + if (precisionSet) { + while (argText.length < precision) { + argText = '0' + argText; + } + } + + // Add sign if needed + if (currArg >= 0) { + if (flagAlwaysSigned) { + prefix = '+' + prefix; + } else if (flagPadSign) { + prefix = ' ' + prefix; + } + } + + // Move sign to prefix so we zero-pad after the sign + if (argText.charAt(0) == '-') { + prefix = '-' + prefix; + argText = argText.substr(1); + } + + // Add padding. + while (prefix.length + argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad) { + argText = '0' + argText; + } else { + prefix = ' ' + prefix; + } + } + } + + // Insert the result into the buffer. + argText = prefix + argText; + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; + } + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': { + // Float. + var currArg = getNextArg('double'); + var argText; + if (isNaN(currArg)) { + argText = 'nan'; + flagZeroPad = false; + } else if (!isFinite(currArg)) { + argText = (currArg < 0 ? '-' : '') + 'inf'; + flagZeroPad = false; + } else { + var isGeneral = false; + var effectivePrecision = Math.min(precision, 20); + + // Convert g/G to f/F or e/E, as per: + // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html + if (next == 103 || next == 71) { + isGeneral = true; + precision = precision || 1; + var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10); + if (precision > exponent && exponent >= -4) { + next = ((next == 103) ? 'f' : 'F').charCodeAt(0); + precision -= exponent + 1; + } else { + next = ((next == 103) ? 'e' : 'E').charCodeAt(0); + precision--; + } + effectivePrecision = Math.min(precision, 20); + } + + if (next == 101 || next == 69) { + argText = currArg.toExponential(effectivePrecision); + // Make sure the exponent has at least 2 digits. + if (/[eE][-+]\d$/.test(argText)) { + argText = argText.slice(0, -1) + '0' + argText.slice(-1); + } + } else if (next == 102 || next == 70) { + argText = currArg.toFixed(effectivePrecision); + if (currArg === 0 && __reallyNegative(currArg)) { + argText = '-' + argText; + } + } + + var parts = argText.split('e'); + if (isGeneral && !flagAlternative) { + // Discard trailing zeros and periods. + while (parts[0].length > 1 && parts[0].indexOf('.') != -1 && + (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) { + parts[0] = parts[0].slice(0, -1); + } + } else { + // Make sure we have a period in alternative mode. + if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.'; + // Zero pad until required precision. + while (precision > effectivePrecision++) parts[0] += '0'; + } + argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : ''); + + // Capitalize 'E' if needed. + if (next == 69) argText = argText.toUpperCase(); + + // Add sign. + if (currArg >= 0) { + if (flagAlwaysSigned) { + argText = '+' + argText; + } else if (flagPadSign) { + argText = ' ' + argText; + } + } + } + + // Add padding. + while (argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) { + argText = argText[0] + '0' + argText.slice(1); + } else { + argText = (flagZeroPad ? '0' : ' ') + argText; + } + } + } + + // Adjust case. + if (next < 97) argText = argText.toUpperCase(); + + // Insert the result into the buffer. + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; + } + case 's': { + // String. + var arg = getNextArg('i8*'); + var argLength = arg ? _strlen(arg) : '(null)'.length; + if (precisionSet) argLength = Math.min(argLength, precision); + if (!flagLeftAlign) { + while (argLength < width--) { + ret.push(32); + } + } + if (arg) { + for (var i = 0; i < argLength; i++) { + ret.push(HEAPU8[((arg++)|0)]); + } + } else { + ret = ret.concat(intArrayFromString('(null)'.substr(0, argLength), true)); + } + if (flagLeftAlign) { + while (argLength < width--) { + ret.push(32); + } + } + break; + } + case 'c': { + // Character. + if (flagLeftAlign) ret.push(getNextArg('i8')); + while (--width > 0) { + ret.push(32); + } + if (!flagLeftAlign) ret.push(getNextArg('i8')); + break; + } + case 'n': { + // Write the length written so far to the next parameter. + var ptr = getNextArg('i32*'); + HEAP32[((ptr)>>2)]=ret.length; + break; + } + case '%': { + // Literal percent sign. + ret.push(curr); + break; + } + default: { + // Unknown specifiers remain untouched. + for (var i = startTextIndex; i < textIndex + 2; i++) { + ret.push(HEAP8[(i)]); + } + } + } + textIndex += 2; + // TODO: Support a/A (hex float) and m (last error) specifiers. + // TODO: Support %1${specifier} for arg selection. + } else { + ret.push(curr); + textIndex += 1; + } + } + return ret; + } + + function _malloc(bytes) { + /* Over-allocate to make sure it is byte-aligned by 8. + * This will leak memory, but this is only the dummy + * implementation (replaced by dlmalloc normally) so + * not an issue. + */ + var ptr = Runtime.dynamicAlloc(bytes + 8); + return (ptr+8) & 0xFFFFFFF8; + } + Module["_malloc"] = _malloc;function _snprintf(s, n, format, varargs) { + // int snprintf(char *restrict s, size_t n, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var result = __formatString(format, varargs); + var limit = (n === undefined) ? result.length + : Math.min(result.length, Math.max(n - 1, 0)); + if (s < 0) { + s = -s; + var buf = _malloc(limit+1); + HEAP32[((s)>>2)]=buf; + s = buf; + } + for (var i = 0; i < limit; i++) { + HEAP8[(((s)+(i))|0)]=result[i]; + } + if (limit < n || (n === undefined)) HEAP8[(((s)+(i))|0)]=0; + return result.length; + } + + + Module["_memset"] = _memset; + + + Module["_strcat"] = _strcat; + + + function _strerror_r(errnum, strerrbuf, buflen) { + if (errnum in ERRNO_MESSAGES) { + if (ERRNO_MESSAGES[errnum].length > buflen - 1) { + return ___setErrNo(ERRNO_CODES.ERANGE); + } else { + var msg = ERRNO_MESSAGES[errnum]; + writeAsciiToMemory(msg, strerrbuf); + return 0; + } + } else { + return ___setErrNo(ERRNO_CODES.EINVAL); + } + }function _strerror(errnum) { + if (!_strerror.buffer) _strerror.buffer = _malloc(256); + _strerror_r(errnum, _strerror.buffer, 256); + return _strerror.buffer; + } + + + Module["_bitshift64Shl"] = _bitshift64Shl; + + function _abort() { + Module['abort'](); + } + + + + + + + function _mkport() { throw 'TODO' }var SOCKFS={mount:function (mount) { + return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + },createSocket:function (family, type, protocol) { + var streaming = type == 1; + if (protocol) { + assert(streaming == (protocol == 6)); // if SOCK_STREAM, must be tcp + } + + // create our internal socket structure + var sock = { + family: family, + type: type, + protocol: protocol, + server: null, + peers: {}, + pending: [], + recv_queue: [], + sock_ops: SOCKFS.websocket_sock_ops + }; + + // create the filesystem node to store the socket structure + var name = SOCKFS.nextname(); + var node = FS.createNode(SOCKFS.root, name, 49152, 0); + node.sock = sock; + + // and the wrapping stream that enables library functions such + // as read and write to indirectly interact with the socket + var stream = FS.createStream({ + path: name, + node: node, + flags: FS.modeStringToFlags('r+'), + seekable: false, + stream_ops: SOCKFS.stream_ops + }); + + // map the new stream to the socket structure (sockets have a 1:1 + // relationship with a stream) + sock.stream = stream; + + return sock; + },getSocket:function (fd) { + var stream = FS.getStream(fd); + if (!stream || !FS.isSocket(stream.node.mode)) { + return null; + } + return stream.node.sock; + },stream_ops:{poll:function (stream) { + var sock = stream.node.sock; + return sock.sock_ops.poll(sock); + },ioctl:function (stream, request, varargs) { + var sock = stream.node.sock; + return sock.sock_ops.ioctl(sock, request, varargs); + },read:function (stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + var msg = sock.sock_ops.recvmsg(sock, length); + if (!msg) { + // socket is closed + return 0; + } + buffer.set(msg.buffer, offset); + return msg.buffer.length; + },write:function (stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + return sock.sock_ops.sendmsg(sock, buffer, offset, length); + },close:function (stream) { + var sock = stream.node.sock; + sock.sock_ops.close(sock); + }},nextname:function () { + if (!SOCKFS.nextname.current) { + SOCKFS.nextname.current = 0; + } + return 'socket[' + (SOCKFS.nextname.current++) + ']'; + },websocket_sock_ops:{createPeer:function (sock, addr, port) { + var ws; + + if (typeof addr === 'object') { + ws = addr; + addr = null; + port = null; + } + + if (ws) { + // for sockets that've already connected (e.g. we're the server) + // we can inspect the _socket property for the address + if (ws._socket) { + addr = ws._socket.remoteAddress; + port = ws._socket.remotePort; + } + // if we're just now initializing a connection to the remote, + // inspect the url property + else { + var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url); + if (!result) { + throw new Error('WebSocket URL must be in the format ws(s)://address:port'); + } + addr = result[1]; + port = parseInt(result[2], 10); + } + } else { + // create the actual websocket object and connect + try { + // runtimeConfig gets set to true if WebSocket runtime configuration is available. + var runtimeConfig = (Module['websocket'] && ('object' === typeof Module['websocket'])); + + // The default value is 'ws://' the replace is needed because the compiler replaces "//" comments with '#' + // comments without checking context, so we'd end up with ws:#, the replace swaps the "#" for "//" again. + var url = 'ws:#'.replace('#', '//'); + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['url']) { + url = Module['websocket']['url']; // Fetch runtime WebSocket URL config. + } + } + + if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it. + url = url + addr + ':' + port; + } + + // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set. + var subProtocols = 'binary'; // The default value is 'binary' + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['subprotocol']) { + subProtocols = Module['websocket']['subprotocol']; // Fetch runtime WebSocket subprotocol config. + } + } + + // The regex trims the string (removes spaces at the beginning and end, then splits the string by + // , into an Array. Whitespace removal is important for Websockify and ws. + subProtocols = subProtocols.replace(/^ +| +$/g,"").split(/ *, */); + + // The node ws library API for specifying optional subprotocol is slightly different than the browser's. + var opts = ENVIRONMENT_IS_NODE ? {'protocol': subProtocols.toString()} : subProtocols; + + // If node we use the ws library. + var WebSocket = ENVIRONMENT_IS_NODE ? require('ws') : window['WebSocket']; + ws = new WebSocket(url, opts); + ws.binaryType = 'arraybuffer'; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EHOSTUNREACH); + } + } + + + var peer = { + addr: addr, + port: port, + socket: ws, + dgram_send_queue: [] + }; + + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer); + + // if this is a bound dgram socket, send the port number first to allow + // us to override the ephemeral port reported to us by remotePort on the + // remote end. + if (sock.type === 2 && typeof sock.sport !== 'undefined') { + peer.dgram_send_queue.push(new Uint8Array([ + 255, 255, 255, 255, + 'p'.charCodeAt(0), 'o'.charCodeAt(0), 'r'.charCodeAt(0), 't'.charCodeAt(0), + ((sock.sport & 0xff00) >> 8) , (sock.sport & 0xff) + ])); + } + + return peer; + },getPeer:function (sock, addr, port) { + return sock.peers[addr + ':' + port]; + },addPeer:function (sock, peer) { + sock.peers[peer.addr + ':' + peer.port] = peer; + },removePeer:function (sock, peer) { + delete sock.peers[peer.addr + ':' + peer.port]; + },handlePeerEvents:function (sock, peer) { + var first = true; + + var handleOpen = function () { + try { + var queued = peer.dgram_send_queue.shift(); + while (queued) { + peer.socket.send(queued); + queued = peer.dgram_send_queue.shift(); + } + } catch (e) { + // not much we can do here in the way of proper error handling as we've already + // lied and said this data was sent. shut it down. + peer.socket.close(); + } + }; + + function handleMessage(data) { + assert(typeof data !== 'string' && data.byteLength !== undefined); // must receive an ArrayBuffer + data = new Uint8Array(data); // make a typed array view on the array buffer + + + // if this is the port message, override the peer's port with it + var wasfirst = first; + first = false; + if (wasfirst && + data.length === 10 && + data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 && + data[4] === 'p'.charCodeAt(0) && data[5] === 'o'.charCodeAt(0) && data[6] === 'r'.charCodeAt(0) && data[7] === 't'.charCodeAt(0)) { + // update the peer's port and it's key in the peer map + var newport = ((data[8] << 8) | data[9]); + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + peer.port = newport; + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + return; + } + + sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data }); + }; + + if (ENVIRONMENT_IS_NODE) { + peer.socket.on('open', handleOpen); + peer.socket.on('message', function(data, flags) { + if (!flags.binary) { + return; + } + handleMessage((new Uint8Array(data)).buffer); // copy from node Buffer -> ArrayBuffer + }); + peer.socket.on('error', function() { + // don't throw + }); + } else { + peer.socket.onopen = handleOpen; + peer.socket.onmessage = function peer_socket_onmessage(event) { + handleMessage(event.data); + }; + } + },poll:function (sock) { + if (sock.type === 1 && sock.server) { + // listen sockets should only say they're available for reading + // if there are pending clients. + return sock.pending.length ? (64 | 1) : 0; + } + + var mask = 0; + var dest = sock.type === 1 ? // we only care about the socket state for connection-based sockets + SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) : + null; + + if (sock.recv_queue.length || + !dest || // connection-less sockets are always ready to read + (dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { // let recv return 0 once closed + mask |= (64 | 1); + } + + if (!dest || // connection-less sockets are always ready to write + (dest && dest.socket.readyState === dest.socket.OPEN)) { + mask |= 4; + } + + if ((dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { + mask |= 16; + } + + return mask; + },ioctl:function (sock, request, arg) { + switch (request) { + case 21531: + var bytes = 0; + if (sock.recv_queue.length) { + bytes = sock.recv_queue[0].data.length; + } + HEAP32[((arg)>>2)]=bytes; + return 0; + default: + return ERRNO_CODES.EINVAL; + } + },close:function (sock) { + // if we've spawned a listen server, close it + if (sock.server) { + try { + sock.server.close(); + } catch (e) { + } + sock.server = null; + } + // close any peer connections + var peers = Object.keys(sock.peers); + for (var i = 0; i < peers.length; i++) { + var peer = sock.peers[peers[i]]; + try { + peer.socket.close(); + } catch (e) { + } + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + } + return 0; + },bind:function (sock, addr, port) { + if (typeof sock.saddr !== 'undefined' || typeof sock.sport !== 'undefined') { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); // already bound + } + sock.saddr = addr; + sock.sport = port || _mkport(); + // in order to emulate dgram sockets, we need to launch a listen server when + // binding on a connection-less socket + // note: this is only required on the server side + if (sock.type === 2) { + // close the existing server if it exists + if (sock.server) { + sock.server.close(); + sock.server = null; + } + // swallow error operation not supported error that occurs when binding in the + // browser where this isn't supported + try { + sock.sock_ops.listen(sock, 0); + } catch (e) { + if (!(e instanceof FS.ErrnoError)) throw e; + if (e.errno !== ERRNO_CODES.EOPNOTSUPP) throw e; + } + } + },connect:function (sock, addr, port) { + if (sock.server) { + throw new FS.ErrnoError(ERRNO_CODS.EOPNOTSUPP); + } + + // TODO autobind + // if (!sock.addr && sock.type == 2) { + // } + + // early out if we're already connected / in the middle of connecting + if (typeof sock.daddr !== 'undefined' && typeof sock.dport !== 'undefined') { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + if (dest) { + if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(ERRNO_CODES.EALREADY); + } else { + throw new FS.ErrnoError(ERRNO_CODES.EISCONN); + } + } + } + + // add the socket to our peer list and set our + // destination address / port to match + var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + sock.daddr = peer.addr; + sock.dport = peer.port; + + // always "fail" in non-blocking mode + throw new FS.ErrnoError(ERRNO_CODES.EINPROGRESS); + },listen:function (sock, backlog) { + if (!ENVIRONMENT_IS_NODE) { + throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP); + } + if (sock.server) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); // already listening + } + var WebSocketServer = require('ws').Server; + var host = sock.saddr; + sock.server = new WebSocketServer({ + host: host, + port: sock.sport + // TODO support backlog + }); + + sock.server.on('connection', function(ws) { + if (sock.type === 1) { + var newsock = SOCKFS.createSocket(sock.family, sock.type, sock.protocol); + + // create a peer on the new socket + var peer = SOCKFS.websocket_sock_ops.createPeer(newsock, ws); + newsock.daddr = peer.addr; + newsock.dport = peer.port; + + // push to queue for accept to pick up + sock.pending.push(newsock); + } else { + // create a peer on the listen socket so calling sendto + // with the listen socket and an address will resolve + // to the correct client + SOCKFS.websocket_sock_ops.createPeer(sock, ws); + } + }); + sock.server.on('closed', function() { + sock.server = null; + }); + sock.server.on('error', function() { + // don't throw + }); + },accept:function (listensock) { + if (!listensock.server) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var newsock = listensock.pending.shift(); + newsock.stream.flags = listensock.stream.flags; + return newsock; + },getname:function (sock, peer) { + var addr, port; + if (peer) { + if (sock.daddr === undefined || sock.dport === undefined) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + addr = sock.daddr; + port = sock.dport; + } else { + // TODO saddr and sport will be set for bind()'d UDP sockets, but what + // should we be returning for TCP sockets that've been connect()'d? + addr = sock.saddr || 0; + port = sock.sport || 0; + } + return { addr: addr, port: port }; + },sendmsg:function (sock, buffer, offset, length, addr, port) { + if (sock.type === 2) { + // connection-less sockets will honor the message address, + // and otherwise fall back to the bound destination address + if (addr === undefined || port === undefined) { + addr = sock.daddr; + port = sock.dport; + } + // if there was no address to fall back to, error out + if (addr === undefined || port === undefined) { + throw new FS.ErrnoError(ERRNO_CODES.EDESTADDRREQ); + } + } else { + // connection-based sockets will only use the bound + addr = sock.daddr; + port = sock.dport; + } + + // find the peer for the destination address + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port); + + // early out if not connected with a connection-based socket + if (sock.type === 1) { + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } else if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } + + // create a copy of the incoming data to send, as the WebSocket API + // doesn't work entirely with an ArrayBufferView, it'll just send + // the entire underlying buffer + var data; + if (buffer instanceof Array || buffer instanceof ArrayBuffer) { + data = buffer.slice(offset, offset + length); + } else { // ArrayBufferView + data = buffer.buffer.slice(buffer.byteOffset + offset, buffer.byteOffset + offset + length); + } + + // if we're emulating a connection-less dgram socket and don't have + // a cached connection, queue the buffer to send upon connect and + // lie, saying the data was sent now. + if (sock.type === 2) { + if (!dest || dest.socket.readyState !== dest.socket.OPEN) { + // if we're not connected, open a new connection + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + } + dest.dgram_send_queue.push(data); + return length; + } + } + + try { + // send the actual data + dest.socket.send(data); + return length; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + },recvmsg:function (sock, length) { + // http://pubs.opengroup.org/onlinepubs/7908799/xns/recvmsg.html + if (sock.type === 1 && sock.server) { + // tcp servers should not be recv()'ing on the listen socket + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + + var queued = sock.recv_queue.shift(); + if (!queued) { + if (sock.type === 1) { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + + if (!dest) { + // if we have a destination address but are not connected, error out + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + else if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + // return null if the socket has closed + return null; + } + else { + // else, our socket is in a valid state but truly has nothing available + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } else { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } + + // queued.data will be an ArrayBuffer if it's unadulterated, but if it's + // requeued TCP data it'll be an ArrayBufferView + var queuedLength = queued.data.byteLength || queued.data.length; + var queuedOffset = queued.data.byteOffset || 0; + var queuedBuffer = queued.data.buffer || queued.data; + var bytesRead = Math.min(length, queuedLength); + var res = { + buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead), + addr: queued.addr, + port: queued.port + }; + + + // push back any unread data for TCP connections + if (sock.type === 1 && bytesRead < queuedLength) { + var bytesRemaining = queuedLength - bytesRead; + queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining); + sock.recv_queue.unshift(queued); + } + + return res; + }}};function _send(fd, buf, len, flags) { + var sock = SOCKFS.getSocket(fd); + if (!sock) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + // TODO honor flags + return _write(fd, buf, len); + } + + function _pwrite(fildes, buf, nbyte, offset) { + // ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + var slab = HEAP8; + return FS.write(stream, slab, buf, nbyte, offset); + } catch (e) { + FS.handleFSError(e); + return -1; + } + }function _write(fildes, buf, nbyte) { + // ssize_t write(int fildes, const void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + + + try { + var slab = HEAP8; + return FS.write(stream, slab, buf, nbyte); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + function _fileno(stream) { + // int fileno(FILE *stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fileno.html + stream = FS.getStreamFromPtr(stream); + if (!stream) return -1; + return stream.fd; + }function _fwrite(ptr, size, nitems, stream) { + // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fwrite.html + var bytesToWrite = nitems * size; + if (bytesToWrite == 0) return 0; + var fd = _fileno(stream); + var bytesWritten = _write(fd, ptr, bytesToWrite); + if (bytesWritten == -1) { + var streamObj = FS.getStreamFromPtr(stream); + if (streamObj) streamObj.error = true; + return 0; + } else { + return Math.floor(bytesWritten / size); + } + }function _fprintf(stream, format, varargs) { + // int fprintf(FILE *restrict stream, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var result = __formatString(format, varargs); + var stack = Runtime.stackSave(); + var ret = _fwrite(allocate(result, 'i8', ALLOC_STACK), 1, result.length, stream); + Runtime.stackRestore(stack); + return ret; + } + + function _toupper(chr) { + if (chr >= 97 && chr <= 122) { + return chr - 97 + 65; + } else { + return chr; + } + } + + function _printf(format, varargs) { + // int printf(const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var stdout = HEAP32[((_stdout)>>2)]; + return _fprintf(stdout, format, varargs); + } + + function _isdigit(chr) { + return chr >= 48 && chr <= 57; + } + + function _close(fildes) { + // int close(int fildes); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/close.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + FS.close(stream); + return 0; + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + var _tan=Math_tan; + + + + Module["_strncpy"] = _strncpy; + + var _asin=Math_asin; + + + Module["_i64Add"] = _i64Add; + + var _fabs=Math_abs; + + function _open(path, oflag, varargs) { + // int open(const char *path, int oflag, ...); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html + var mode = HEAP32[((varargs)>>2)]; + path = Pointer_stringify(path); + try { + var stream = FS.open(path, oflag, mode); + return stream.fd; + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + + function _copysign(a, b) { + return __reallyNegative(a) === __reallyNegative(b) ? a : -a; + }var _copysignl=_copysign; + + var _sqrt=Math_sqrt; + + + var Browser={mainLoop:{scheduler:null,method:"",shouldPause:false,paused:false,queue:[],pause:function () { + Browser.mainLoop.shouldPause = true; + },resume:function () { + if (Browser.mainLoop.paused) { + Browser.mainLoop.paused = false; + Browser.mainLoop.scheduler(); + } + Browser.mainLoop.shouldPause = false; + },updateStatus:function () { + if (Module['setStatus']) { + var message = Module['statusMessage'] || 'Please wait...'; + var remaining = Browser.mainLoop.remainingBlockers; + var expected = Browser.mainLoop.expectedBlockers; + if (remaining) { + if (remaining < expected) { + Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')'); + } else { + Module['setStatus'](message); + } + } else { + Module['setStatus'](''); + } + } + }},isFullScreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function () { + if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers + + if (Browser.initted || ENVIRONMENT_IS_WORKER) return; + Browser.initted = true; + + try { + new Blob(); + Browser.hasBlobConstructor = true; + } catch(e) { + Browser.hasBlobConstructor = false; + console.log("warning: no blob constructor, cannot create blobs with mimetypes"); + } + Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null)); + Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined; + if (!Module.noImageDecoding && typeof Browser.URLObject === 'undefined') { + console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."); + Module.noImageDecoding = true; + } + + // Support for plugins that can process preloaded files. You can add more of these to + // your app by creating and appending to Module.preloadPlugins. + // + // Each plugin is asked if it can handle a file based on the file's name. If it can, + // it is given the file's raw data. When it is done, it calls a callback with the file's + // (possibly modified) data. For example, a plugin might decompress a file, or it + // might create some side data structure for use later (like an Image element, etc.). + + var imagePlugin = {}; + imagePlugin['canHandle'] = function imagePlugin_canHandle(name) { + return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name); + }; + imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) { + var b = null; + if (Browser.hasBlobConstructor) { + try { + b = new Blob([byteArray], { type: Browser.getMimetype(name) }); + if (b.size !== byteArray.length) { // Safari bug #118630 + // Safari's Blob can only take an ArrayBuffer + b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) }); + } + } catch(e) { + Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder'); + } + } + if (!b) { + var bb = new Browser.BlobBuilder(); + bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range + b = bb.getBlob(); + } + var url = Browser.URLObject.createObjectURL(b); + var img = new Image(); + img.onload = function img_onload() { + assert(img.complete, 'Image ' + name + ' could not be decoded'); + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + Module["preloadedImages"][name] = canvas; + Browser.URLObject.revokeObjectURL(url); + if (onload) onload(byteArray); + }; + img.onerror = function img_onerror(event) { + console.log('Image ' + url + ' could not be decoded'); + if (onerror) onerror(); + }; + img.src = url; + }; + Module['preloadPlugins'].push(imagePlugin); + + var audioPlugin = {}; + audioPlugin['canHandle'] = function audioPlugin_canHandle(name) { + return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; + }; + audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) { + var done = false; + function finish(audio) { + if (done) return; + done = true; + Module["preloadedAudios"][name] = audio; + if (onload) onload(byteArray); + } + function fail() { + if (done) return; + done = true; + Module["preloadedAudios"][name] = new Audio(); // empty shim + if (onerror) onerror(); + } + if (Browser.hasBlobConstructor) { + try { + var b = new Blob([byteArray], { type: Browser.getMimetype(name) }); + } catch(e) { + return fail(); + } + var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! + var audio = new Audio(); + audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926 + audio.onerror = function audio_onerror(event) { + if (done) return; + console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach'); + function encode64(data) { + var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + var PAD = '='; + var ret = ''; + var leftchar = 0; + var leftbits = 0; + for (var i = 0; i < data.length; i++) { + leftchar = (leftchar << 8) | data[i]; + leftbits += 8; + while (leftbits >= 6) { + var curr = (leftchar >> (leftbits-6)) & 0x3f; + leftbits -= 6; + ret += BASE[curr]; + } + } + if (leftbits == 2) { + ret += BASE[(leftchar&3) << 4]; + ret += PAD + PAD; + } else if (leftbits == 4) { + ret += BASE[(leftchar&0xf) << 2]; + ret += PAD; + } + return ret; + } + audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray); + finish(audio); // we don't wait for confirmation this worked - but it's worth trying + }; + audio.src = url; + // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror + Browser.safeSetTimeout(function() { + finish(audio); // try to use it even though it is not necessarily ready to play + }, 10000); + } else { + return fail(); + } + }; + Module['preloadPlugins'].push(audioPlugin); + + // Canvas event setup + + var canvas = Module['canvas']; + + // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module + // Module['forcedAspectRatio'] = 4 / 3; + + canvas.requestPointerLock = canvas['requestPointerLock'] || + canvas['mozRequestPointerLock'] || + canvas['webkitRequestPointerLock'] || + canvas['msRequestPointerLock'] || + function(){}; + canvas.exitPointerLock = document['exitPointerLock'] || + document['mozExitPointerLock'] || + document['webkitExitPointerLock'] || + document['msExitPointerLock'] || + function(){}; // no-op if function does not exist + canvas.exitPointerLock = canvas.exitPointerLock.bind(document); + + function pointerLockChange() { + Browser.pointerLock = document['pointerLockElement'] === canvas || + document['mozPointerLockElement'] === canvas || + document['webkitPointerLockElement'] === canvas || + document['msPointerLockElement'] === canvas; + } + + document.addEventListener('pointerlockchange', pointerLockChange, false); + document.addEventListener('mozpointerlockchange', pointerLockChange, false); + document.addEventListener('webkitpointerlockchange', pointerLockChange, false); + document.addEventListener('mspointerlockchange', pointerLockChange, false); + + if (Module['elementPointerLock']) { + canvas.addEventListener("click", function(ev) { + if (!Browser.pointerLock && canvas.requestPointerLock) { + canvas.requestPointerLock(); + ev.preventDefault(); + } + }, false); + } + },createContext:function (canvas, useWebGL, setInModule, webGLContextAttributes) { + var ctx; + var errorInfo = '?'; + function onContextCreationError(event) { + errorInfo = event.statusMessage || errorInfo; + } + try { + if (useWebGL) { + var contextAttributes = { + antialias: false, + alpha: false + }; + + if (webGLContextAttributes) { + for (var attribute in webGLContextAttributes) { + contextAttributes[attribute] = webGLContextAttributes[attribute]; + } + } + + + canvas.addEventListener('webglcontextcreationerror', onContextCreationError, false); + try { + ['experimental-webgl', 'webgl'].some(function(webglId) { + return ctx = canvas.getContext(webglId, contextAttributes); + }); + } finally { + canvas.removeEventListener('webglcontextcreationerror', onContextCreationError, false); + } + } else { + ctx = canvas.getContext('2d'); + } + if (!ctx) throw ':('; + } catch (e) { + Module.print('Could not create canvas: ' + [errorInfo, e]); + return null; + } + if (useWebGL) { + // Set the background of the WebGL canvas to black + canvas.style.backgroundColor = "black"; + + // Warn on context loss + canvas.addEventListener('webglcontextlost', function(event) { + alert('WebGL context lost. You will need to reload the page.'); + }, false); + } + if (setInModule) { + GLctx = Module.ctx = ctx; + Module.useWebGL = useWebGL; + Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); + Browser.init(); + } + return ctx; + },destroyContext:function (canvas, useWebGL, setInModule) {},fullScreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullScreen:function (lockPointer, resizeCanvas) { + Browser.lockPointer = lockPointer; + Browser.resizeCanvas = resizeCanvas; + if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true; + if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false; + + var canvas = Module['canvas']; + function fullScreenChange() { + Browser.isFullScreen = false; + var canvasContainer = canvas.parentNode; + if ((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement'] || + document['msFullScreenElement'] || document['msFullscreenElement'] || + document['webkitCurrentFullScreenElement']) === canvasContainer) { + canvas.cancelFullScreen = document['cancelFullScreen'] || + document['mozCancelFullScreen'] || + document['webkitCancelFullScreen'] || + document['msExitFullscreen'] || + document['exitFullscreen'] || + function() {}; + canvas.cancelFullScreen = canvas.cancelFullScreen.bind(document); + if (Browser.lockPointer) canvas.requestPointerLock(); + Browser.isFullScreen = true; + if (Browser.resizeCanvas) Browser.setFullScreenCanvasSize(); + } else { + + // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen + canvasContainer.parentNode.insertBefore(canvas, canvasContainer); + canvasContainer.parentNode.removeChild(canvasContainer); + + if (Browser.resizeCanvas) Browser.setWindowedCanvasSize(); + } + if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullScreen); + Browser.updateCanvasDimensions(canvas); + } + + if (!Browser.fullScreenHandlersInstalled) { + Browser.fullScreenHandlersInstalled = true; + document.addEventListener('fullscreenchange', fullScreenChange, false); + document.addEventListener('mozfullscreenchange', fullScreenChange, false); + document.addEventListener('webkitfullscreenchange', fullScreenChange, false); + document.addEventListener('MSFullscreenChange', fullScreenChange, false); + } + + // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root + var canvasContainer = document.createElement("div"); + canvas.parentNode.insertBefore(canvasContainer, canvas); + canvasContainer.appendChild(canvas); + + // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size) + canvasContainer.requestFullScreen = canvasContainer['requestFullScreen'] || + canvasContainer['mozRequestFullScreen'] || + canvasContainer['msRequestFullscreen'] || + (canvasContainer['webkitRequestFullScreen'] ? function() { canvasContainer['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null); + canvasContainer.requestFullScreen(); + },requestAnimationFrame:function requestAnimationFrame(func) { + if (typeof window === 'undefined') { // Provide fallback to setTimeout if window is undefined (e.g. in Node.js) + setTimeout(func, 1000/60); + } else { + if (!window.requestAnimationFrame) { + window.requestAnimationFrame = window['requestAnimationFrame'] || + window['mozRequestAnimationFrame'] || + window['webkitRequestAnimationFrame'] || + window['msRequestAnimationFrame'] || + window['oRequestAnimationFrame'] || + window['setTimeout']; + } + window.requestAnimationFrame(func); + } + },safeCallback:function (func) { + return function() { + if (!ABORT) return func.apply(null, arguments); + }; + },safeRequestAnimationFrame:function (func) { + return Browser.requestAnimationFrame(function() { + if (!ABORT) func(); + }); + },safeSetTimeout:function (func, timeout) { + return setTimeout(function() { + if (!ABORT) func(); + }, timeout); + },safeSetInterval:function (func, timeout) { + return setInterval(function() { + if (!ABORT) func(); + }, timeout); + },getMimetype:function (name) { + return { + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'png': 'image/png', + 'bmp': 'image/bmp', + 'ogg': 'audio/ogg', + 'wav': 'audio/wav', + 'mp3': 'audio/mpeg' + }[name.substr(name.lastIndexOf('.')+1)]; + },getUserMedia:function (func) { + if(!window.getUserMedia) { + window.getUserMedia = navigator['getUserMedia'] || + navigator['mozGetUserMedia']; + } + window.getUserMedia(func); + },getMovementX:function (event) { + return event['movementX'] || + event['mozMovementX'] || + event['webkitMovementX'] || + 0; + },getMovementY:function (event) { + return event['movementY'] || + event['mozMovementY'] || + event['webkitMovementY'] || + 0; + },getMouseWheelDelta:function (event) { + return Math.max(-1, Math.min(1, event.type === 'DOMMouseScroll' ? event.detail : -event.wheelDelta)); + },mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function (event) { // event should be mousemove, mousedown or mouseup + if (Browser.pointerLock) { + // When the pointer is locked, calculate the coordinates + // based on the movement of the mouse. + // Workaround for Firefox bug 764498 + if (event.type != 'mousemove' && + ('mozMovementX' in event)) { + Browser.mouseMovementX = Browser.mouseMovementY = 0; + } else { + Browser.mouseMovementX = Browser.getMovementX(event); + Browser.mouseMovementY = Browser.getMovementY(event); + } + + // check if SDL is available + if (typeof SDL != "undefined") { + Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; + Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; + } else { + // just add the mouse delta to the current absolut mouse position + // FIXME: ideally this should be clamped against the canvas size and zero + Browser.mouseX += Browser.mouseMovementX; + Browser.mouseY += Browser.mouseMovementY; + } + } else { + // Otherwise, calculate the movement based on the changes + // in the coordinates. + var rect = Module["canvas"].getBoundingClientRect(); + var cw = Module["canvas"].width; + var ch = Module["canvas"].height; + + // Neither .scrollX or .pageXOffset are defined in a spec, but + // we prefer .scrollX because it is currently in a spec draft. + // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/) + var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset); + var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset); + + if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') { + var touch = event.touch; + if (touch === undefined) { + return; // the "touch" property is only defined in SDL + + } + var adjustedX = touch.pageX - (scrollX + rect.left); + var adjustedY = touch.pageY - (scrollY + rect.top); + + adjustedX = adjustedX * (cw / rect.width); + adjustedY = adjustedY * (ch / rect.height); + + var coords = { x: adjustedX, y: adjustedY }; + + if (event.type === 'touchstart') { + Browser.lastTouches[touch.identifier] = coords; + Browser.touches[touch.identifier] = coords; + } else if (event.type === 'touchend' || event.type === 'touchmove') { + Browser.lastTouches[touch.identifier] = Browser.touches[touch.identifier]; + Browser.touches[touch.identifier] = { x: adjustedX, y: adjustedY }; + } + return; + } + + var x = event.pageX - (scrollX + rect.left); + var y = event.pageY - (scrollY + rect.top); + + // the canvas might be CSS-scaled compared to its backbuffer; + // SDL-using content will want mouse coordinates in terms + // of backbuffer units. + x = x * (cw / rect.width); + y = y * (ch / rect.height); + + Browser.mouseMovementX = x - Browser.mouseX; + Browser.mouseMovementY = y - Browser.mouseY; + Browser.mouseX = x; + Browser.mouseY = y; + } + },xhrLoad:function (url, onload, onerror) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = function xhr_onload() { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + } else { + onerror(); + } + }; + xhr.onerror = onerror; + xhr.send(null); + },asyncLoad:function (url, onload, onerror, noRunDep) { + Browser.xhrLoad(url, function(arrayBuffer) { + assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).'); + onload(new Uint8Array(arrayBuffer)); + if (!noRunDep) removeRunDependency('al ' + url); + }, function(event) { + if (onerror) { + onerror(); + } else { + throw 'Loading data file "' + url + '" failed.'; + } + }); + if (!noRunDep) addRunDependency('al ' + url); + },resizeListeners:[],updateResizeListeners:function () { + var canvas = Module['canvas']; + Browser.resizeListeners.forEach(function(listener) { + listener(canvas.width, canvas.height); + }); + },setCanvasSize:function (width, height, noUpdates) { + var canvas = Module['canvas']; + Browser.updateCanvasDimensions(canvas, width, height); + if (!noUpdates) Browser.updateResizeListeners(); + },windowedWidth:0,windowedHeight:0,setFullScreenCanvasSize:function () { + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags | 0x00800000; // set SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },setWindowedCanvasSize:function () { + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },updateCanvasDimensions:function (canvas, wNative, hNative) { + if (wNative && hNative) { + canvas.widthNative = wNative; + canvas.heightNative = hNative; + } else { + wNative = canvas.widthNative; + hNative = canvas.heightNative; + } + var w = wNative; + var h = hNative; + if (Module['forcedAspectRatio'] && Module['forcedAspectRatio'] > 0) { + if (w/h < Module['forcedAspectRatio']) { + w = Math.round(h * Module['forcedAspectRatio']); + } else { + h = Math.round(w / Module['forcedAspectRatio']); + } + } + if (((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement'] || + document['msFullScreenElement'] || document['msFullscreenElement'] || + document['webkitCurrentFullScreenElement']) === canvas.parentNode) && (typeof screen != 'undefined')) { + var factor = Math.min(screen.width / w, screen.height / h); + w = Math.round(w * factor); + h = Math.round(h * factor); + } + if (Browser.resizeCanvas) { + if (canvas.width != w) canvas.width = w; + if (canvas.height != h) canvas.height = h; + if (typeof canvas.style != 'undefined') { + canvas.style.removeProperty( "width"); + canvas.style.removeProperty("height"); + } + } else { + if (canvas.width != wNative) canvas.width = wNative; + if (canvas.height != hNative) canvas.height = hNative; + if (typeof canvas.style != 'undefined') { + if (w != wNative || h != hNative) { + canvas.style.setProperty( "width", w + "px", "important"); + canvas.style.setProperty("height", h + "px", "important"); + } else { + canvas.style.removeProperty( "width"); + canvas.style.removeProperty("height"); + } + } + } + }}; + + function _sprintf(s, format, varargs) { + // int sprintf(char *restrict s, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + return _snprintf(s, undefined, format, varargs); + } + + + function __exit(status) { + // void _exit(int status); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html + Module['exit'](status); + }function _exit(status) { + __exit(status); + } + + function _isspace(chr) { + return (chr == 32) || (chr >= 9 && chr <= 13); + } + + + function _fmod(x, y) { + return x % y; + }var _fmodl=_fmod; + + function _sysconf(name) { + // long sysconf(int name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/sysconf.html + switch(name) { + case 30: return PAGE_SIZE; + case 132: + case 133: + case 12: + case 137: + case 138: + case 15: + case 235: + case 16: + case 17: + case 18: + case 19: + case 20: + case 149: + case 13: + case 10: + case 236: + case 153: + case 9: + case 21: + case 22: + case 159: + case 154: + case 14: + case 77: + case 78: + case 139: + case 80: + case 81: + case 79: + case 82: + case 68: + case 67: + case 164: + case 11: + case 29: + case 47: + case 48: + case 95: + case 52: + case 51: + case 46: + return 200809; + case 27: + case 246: + case 127: + case 128: + case 23: + case 24: + case 160: + case 161: + case 181: + case 182: + case 242: + case 183: + case 184: + case 243: + case 244: + case 245: + case 165: + case 178: + case 179: + case 49: + case 50: + case 168: + case 169: + case 175: + case 170: + case 171: + case 172: + case 97: + case 76: + case 32: + case 173: + case 35: + return -1; + case 176: + case 177: + case 7: + case 155: + case 8: + case 157: + case 125: + case 126: + case 92: + case 93: + case 129: + case 130: + case 131: + case 94: + case 91: + return 1; + case 74: + case 60: + case 69: + case 70: + case 4: + return 1024; + case 31: + case 42: + case 72: + return 32; + case 87: + case 26: + case 33: + return 2147483647; + case 34: + case 1: + return 47839; + case 38: + case 36: + return 99; + case 43: + case 37: + return 2048; + case 0: return 2097152; + case 3: return 65536; + case 28: return 32768; + case 44: return 32767; + case 75: return 16384; + case 39: return 1000; + case 89: return 700; + case 71: return 256; + case 40: return 255; + case 2: return 100; + case 180: return 64; + case 25: return 20; + case 5: return 16; + case 6: return 6; + case 73: return 4; + case 84: return 1; + } + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + + + Module["_tolower"] = _tolower; + + var _atan=Math_atan; + + + function _recv(fd, buf, len, flags) { + var sock = SOCKFS.getSocket(fd); + if (!sock) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + // TODO honor flags + return _read(fd, buf, len); + } + + function _pread(fildes, buf, nbyte, offset) { + // ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + var slab = HEAP8; + return FS.read(stream, slab, buf, nbyte, offset); + } catch (e) { + FS.handleFSError(e); + return -1; + } + }function _read(fildes, buf, nbyte) { + // ssize_t read(int fildes, void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + + + try { + var slab = HEAP8; + return FS.read(stream, slab, buf, nbyte); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + function _time(ptr) { + var ret = Math.floor(Date.now()/1000); + if (ptr) { + HEAP32[((ptr)>>2)]=ret; + } + return ret; + } + + + + + + + var _environ=allocate(1, "i32*", ALLOC_STATIC);var ___environ=_environ;function ___buildEnvironment(env) { + // WARNING: Arbitrary limit! + var MAX_ENV_VALUES = 64; + var TOTAL_ENV_SIZE = 1024; + + // Statically allocate memory for the environment. + var poolPtr; + var envPtr; + if (!___buildEnvironment.called) { + ___buildEnvironment.called = true; + // Set default values. Use string keys for Closure Compiler compatibility. + ENV['USER'] = 'root'; + ENV['PATH'] = '/'; + ENV['PWD'] = '/'; + ENV['HOME'] = '/home/emscripten'; + ENV['LANG'] = 'en_US.UTF-8'; + ENV['_'] = './this.program'; + // Allocate memory. + poolPtr = allocate(TOTAL_ENV_SIZE, 'i8', ALLOC_STATIC); + envPtr = allocate(MAX_ENV_VALUES * 4, + 'i8*', ALLOC_STATIC); + HEAP32[((envPtr)>>2)]=poolPtr; + HEAP32[((_environ)>>2)]=envPtr; + } else { + envPtr = HEAP32[((_environ)>>2)]; + poolPtr = HEAP32[((envPtr)>>2)]; + } + + // Collect key=value lines. + var strings = []; + var totalSize = 0; + for (var key in env) { + if (typeof env[key] === 'string') { + var line = key + '=' + env[key]; + strings.push(line); + totalSize += line.length; + } + } + if (totalSize > TOTAL_ENV_SIZE) { + throw new Error('Environment size exceeded TOTAL_ENV_SIZE!'); + } + + // Make new. + var ptrSize = 4; + for (var i = 0; i < strings.length; i++) { + var line = strings[i]; + writeAsciiToMemory(line, poolPtr); + HEAP32[(((envPtr)+(i * ptrSize))>>2)]=poolPtr; + poolPtr += line.length + 1; + } + HEAP32[(((envPtr)+(strings.length * ptrSize))>>2)]=0; + }var ENV={};function _getenv(name) { + // char *getenv(const char *name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html + if (name === 0) return 0; + name = Pointer_stringify(name); + if (!ENV.hasOwnProperty(name)) return 0; + + if (_getenv.ret) _free(_getenv.ret); + _getenv.ret = allocate(intArrayFromString(ENV[name]), 'i8', ALLOC_NORMAL); + return _getenv.ret; + } + + + function _emscripten_memcpy_big(dest, src, num) { + HEAPU8.set(HEAPU8.subarray(src, src+num), dest); + return dest; + } + Module["_memcpy"] = _memcpy; + + var _log=Math_log; + + var _cos=Math_cos; + + var _llvm_pow_f64=Math_pow; + + function _sbrk(bytes) { + // Implement a Linux-like 'memory area' for our 'process'. + // Changes the size of the memory area by |bytes|; returns the + // address of the previous top ('break') of the memory area + // We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP + var self = _sbrk; + if (!self.called) { + DYNAMICTOP = alignMemoryPage(DYNAMICTOP); // make sure we start out aligned + self.called = true; + assert(Runtime.dynamicAlloc); + self.alloc = Runtime.dynamicAlloc; + Runtime.dynamicAlloc = function() { abort('cannot dynamically allocate, sbrk now has control') }; + } + var ret = DYNAMICTOP; + if (bytes != 0) self.alloc(bytes); + return ret; // Previous break location. + } + + function ___errno_location() { + return ___errno_state; + } + + var _BItoD=true; + + var _sin=Math_sin; + + var _atan2=Math_atan2; + + + Module["_strcpy"] = _strcpy; + + function _llvm_bswap_i32(x) { + return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24); + } + + + + function _islower(chr) { + return chr >= 97 && chr <= 122; + } + + var _exp=Math_exp; + + var _acos=Math_acos; + + function _isupper(chr) { + return chr >= 65 && chr <= 90; + } + +FS.staticInit();__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });__ATEXIT__.push({ func: function() { FS.quit() } });Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice; +___errno_state = Runtime.staticAlloc(4); HEAP32[((___errno_state)>>2)]=0; +__ATINIT__.unshift({ func: function() { TTY.init() } });__ATEXIT__.push({ func: function() { TTY.shutdown() } });TTY.utf8 = new Runtime.UTF8Processor(); +if (ENVIRONMENT_IS_NODE) { var fs = require("fs"); NODEFS.staticInit(); } +__ATINIT__.push({ func: function() { SOCKFS.root = FS.mount(SOCKFS, {}, null); } }); +Module["requestFullScreen"] = function Module_requestFullScreen(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) }; + Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) }; + Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) }; + Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() }; + Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() }; + Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() } +___buildEnvironment(ENV); +STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP); + +staticSealed = true; // seal the static portion of memory + +STACK_MAX = STACK_BASE + 5242880; + +DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX); + +assert(DYNAMIC_BASE < TOTAL_MEMORY, "TOTAL_MEMORY not big enough for stack"); + + var ctlz_i8 = allocate([8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], "i8", ALLOC_DYNAMIC); + var cttz_i8 = allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0], "i8", ALLOC_DYNAMIC); + +var Math_min = Math.min; +function invoke_iiii(index,a1,a2,a3) { + try { + return Module["dynCall_iiii"](index,a1,a2,a3); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_iddiii(index,a1,a2,a3,a4,a5) { + try { + return Module["dynCall_iddiii"](index,a1,a2,a3,a4,a5); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_vii(index,a1,a2) { + try { + Module["dynCall_vii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_iii(index,a1,a2) { + try { + return Module["dynCall_iii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function asmPrintInt(x, y) { + Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack); +} +function asmPrintFloat(x, y) { + Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack); +} +// EMSCRIPTEN_START_ASM +var asm=(function(global,env,buffer){"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=env.cttz_i8|0;var n=env.ctlz_i8|0;var o=env._stderr|0;var p=0;var q=0;var r=0;var s=0;var t=+env.NaN,u=+env.Infinity;var v=0,w=0,x=0,y=0,z=0.0,A=0,B=0,C=0,D=0.0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=0;var M=0;var N=0;var O=global.Math.floor;var P=global.Math.abs;var Q=global.Math.sqrt;var R=global.Math.pow;var S=global.Math.cos;var T=global.Math.sin;var U=global.Math.tan;var V=global.Math.acos;var W=global.Math.asin;var X=global.Math.atan;var Y=global.Math.atan2;var Z=global.Math.exp;var _=global.Math.log;var $=global.Math.ceil;var aa=global.Math.imul;var ba=env.abort;var ca=env.assert;var da=env.asmPrintInt;var ea=env.asmPrintFloat;var fa=env.min;var ga=env.invoke_iiii;var ha=env.invoke_iddiii;var ia=env.invoke_vii;var ja=env.invoke_iii;var ka=env._fabs;var la=env._sin;var ma=env._exp;var na=env._llvm_pow_f64;var oa=env._acos;var pa=env._atan2;var qa=env._fmod;var ra=env._lseek;var sa=env.__reallyNegative;var ta=env._asin;var ua=env._atan;var va=env.___buildEnvironment;var wa=env._fflush;var xa=env._pwrite;var ya=env._strerror_r;var za=env._fprintf;var Aa=env._open;var Ba=env._fabsf;var Ca=env._sbrk;var Da=env._send;var Ea=env._snprintf;var Fa=env._llvm_bswap_i32;var Ga=env._emscripten_memcpy_big;var Ha=env._fileno;var Ia=env._sysconf;var Ja=env.___setErrNo;var Ka=env._cos;var La=env._pread;var Ma=env._printf;var Na=env._sprintf;var Oa=env._log;var Pa=env._toupper;var Qa=env._write;var Ra=env._isupper;var Sa=env.___errno_location;var Ta=env._recv;var Ua=env._tan;var Va=env._copysign;var Wa=env._getenv;var Xa=env._mkport;var Ya=env.__exit;var Za=env._read;var _a=env._abort;var $a=env._islower;var ab=env._fwrite;var bb=env._time;var cb=env._isdigit;var db=env._strerror;var eb=env.__formatString;var fb=env._isspace;var gb=env._sqrt;var hb=env._exit;var ib=env._close;var jb=0.0; +// EMSCRIPTEN_START_FUNCS +function ob(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+7&-8;return b|0}function pb(){return i|0}function qb(a){a=a|0;i=a}function rb(a,b){a=a|0;b=b|0;if((p|0)==0){p=a;q=b}}function sb(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0]}function tb(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0];a[k+4|0]=a[b+4|0];a[k+5|0]=a[b+5|0];a[k+6|0]=a[b+6|0];a[k+7|0]=a[b+7|0]}function ub(a){a=a|0;E=a}function vb(a){a=a|0;F=a}function wb(a){a=a|0;G=a}function xb(a){a=a|0;H=a}function yb(a){a=a|0;I=a}function zb(a){a=a|0;J=a}function Ab(a){a=a|0;K=a}function Bb(a){a=a|0;L=a}function Cb(a){a=a|0;M=a}function Db(a){a=a|0;N=a}function Eb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;if((d|0)>0){f=Ob(b,d)|0}else{f=Pb(b)|0}b=(f|0)==0;if(!b){Xb(f,hc(f)|0)}d=c[1086]|0;if((d|0)==0){c[1086]=10;g=gg(41040)|0;c[1088]=g;if((g|0)==0){h=-4;i=e;return h|0}else{j=10}}else{j=d}d=c[1090]|0;a:do{if((d|0)<(j|0)){k=d}else{g=j;l=c[1088]|0;while(1){m=g+10|0;c[1086]=m;n=jg(l,m*4104|0)|0;c[1088]=n;if((n|0)==0){h=-3;break}m=c[1086]|0;o=c[1090]|0;if((o|0)<(m|0)){k=o;break a}else{g=m;l=n}}i=e;return h|0}}while(0);if(b){h=-1;i=e;return h|0}c[(c[1088]|0)+(k*4104|0)>>2]=f;f=c[1088]|0;c[f+(k*4104|0)+4>>2]=0;a[f+((c[1090]|0)*4104|0)+8|0]=0;c[1090]=(c[1090]|0)+1;h=k;i=e;return h|0}function Fb(b,d,e){b=b|0;d=+d;e=+e;var f=0,g=0,h=0,j=0,k=0;f=i;g=c[1088]|0;h=c[g+(b*4104|0)>>2]|0;if((h|0)==0){j=0;i=f;return j|0}k=g+(b*4104|0)+8|0;a[k]=0;dc(h,d+-1.0,e+-1.0,k,4096)|0;j=k;i=f;return j|0}function Gb(b,d,e){b=b|0;d=+d;e=+e;var f=0,g=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+4144|0;g=f+16|0;j=f+40|0;l=f+8|0;m=f;if((b|0)>0&(c[1086]|0)>(b|0)){n=(c[1088]|0)+(b*4104|0)|0}else{n=0}b=c[n>>2]|0;if((b|0)==0){o=0;i=f;return o|0}cc(b,d,e,l,m,f+32|0);e=+h[m>>3]+1.0;h[k>>3]=+h[l>>3]+1.0;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];l=g+8|0;h[k>>3]=e;c[l>>2]=c[k>>2];c[l+4>>2]=c[k+4>>2];Ea(j|0,4095,8,g|0)|0;g=n+8|0;n=a[j]|0;a:do{if(!(n<<24>>24==0)){l=j;m=n;while(1){b=l+1|0;if((fb(m<<24>>24|0)|0)==0){break}m=a[b]|0;if(m<<24>>24==0){break a}else{l=b}}m=a[l]|0;if(!(m<<24>>24==0)){b=g;p=l;q=m;while(1){m=p+1|0;r=b+1|0;a[b]=q;s=a[m]|0;if(s<<24>>24==0){break}else{b=r;p=m;q=s}}a[r]=0;if((r|0)==(g|0)){o=g;i=f;return o|0}q=r;p=r-g|0;while(1){b=q+ -1|0;if((fb(a[b]|0)|0)==0){o=g;t=14;break}a[b]=0;l=p+ -1|0;if((l|0)==0){o=g;t=14;break}else{q=b;p=l}}if((t|0)==14){i=f;return o|0}}}}while(0);a[g]=0;o=g;i=f;return o|0}function Hb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;if((b|0)>0&(c[1086]|0)>(b|0)){f=(c[1088]|0)+(b*4104|0)|0}else{f=0}b=c[f>>2]|0;if((b|0)==0){g=0;i=e;return g|0}h=f+8|0;a[h]=0;do{if((d|0)!=0?(a[d]|0)!=0:0){if(((xg(d,24)|0)!=0?(xg(d,40)|0)!=0:0)?(xg(d,56)|0)!=0:0){if(!(+oc(d)>0.0)){break}j=c[f>>2]|0}else{j=b}Xb(j,d)}}while(0);Hg(h|0,fc(c[f>>2]|0)|0,4096)|0;if((xg(h,24)|0)==0){k=h+0|0;l=24|0;m=k+9|0;do{a[k]=a[l]|0;k=k+1|0;l=l+1|0}while((k|0)<(m|0));g=h;i=e;return g|0}if((xg(h,40)|0)==0){k=h+0|0;l=40|0;m=k+9|0;do{a[k]=a[l]|0;k=k+1|0;l=l+1|0}while((k|0)<(m|0));g=h;i=e;return g|0}l=a[h]|0;if(l<<24>>24==0){g=h;i=e;return g|0}else{n=h;o=l}while(1){if(($a(o<<24>>24|0)|0)!=0){a[n]=Pa(a[n]|0)|0}l=n+1|0;k=a[l]|0;if(k<<24>>24==0){g=h;break}else{n=l;o=k}}i=e;return g|0}function Ib(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;if((b|0)>0&(c[1086]|0)>(b|0)){f=(c[1088]|0)+(b*4104|0)|0}else{f=0}b=c[f>>2]|0;if((b|0)==0){g=0;i=e;return g|0}h=f+8|0;a[h]=0;do{if((d|0)!=0?(a[d]|0)!=0:0){if((xg(d,64)|0)==0){gc(b,1)|0;c[f+4>>2]=1;break}else{gc(b,0)|0;c[f+4>>2]=0;break}}}while(0);b=c[f+4>>2]|0;if((b|0)==1){Hg(h|0,64,4095)|0}else if((b|0)==0){Hg(h|0,72,4095)|0}b=a[h]|0;if(b<<24>>24==0){g=h;i=e;return g|0}else{j=h;k=b}while(1){if((Ra(k<<24>>24|0)|0)!=0){a[j]=Jg(a[j]|0)|0}b=j+1|0;f=a[b]|0;if(f<<24>>24==0){g=h;break}else{j=b;k=f}}i=e;return g|0}function Jb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0.0,C=0.0,D=0,E=0.0,F=0.0,G=0,H=0,I=0.0,J=0.0,K=0.0;e=i;i=i+12352|0;f=e+32|0;g=e+56|0;j=e+4152|0;l=e+8248|0;m=e+48|0;n=e+52|0;o=e+24|0;p=e;q=e+8|0;r=e+16|0;if((b|0)>0&(c[1086]|0)>(b|0)){s=(c[1088]|0)+(b*4104|0)|0}else{s=0}c[m>>2]=0;c[n>>2]=0;if((c[s>>2]|0)==0){t=0;i=e;return t|0}u=Hb(b,0)|0;if(((yg(u,24)|0)!=0?(yg(u,40)|0)!=0:0)?(yg(u,56)|0)!=0:0){v=0}else{v=1}u=s+8|0;a[u]=0;b=cg(d)|0;d=fg(b,88)|0;if((d|0)!=0){w=s+4|0;x=(v|0)==0;v=d;do{d=$f(v,32)|0;if((d|0)==0){c[m>>2]=96;y=96;z=0}else{A=d+1|0;c[m>>2]=A;a[d]=0;y=A;z=v}B=+wg(y,n);if(B!=0.0?(C=+wg(c[n>>2]|0,m),C!=0.0):0){bc(c[s>>2]|0,B,C,o,p);A=(z|0)!=0;if(A){c[f>>2]=z;Ea(g|0,4096,104,f|0)|0;dg(u,g,4095)|0}d=c[w>>2]|0;if((d|0)==0){C=+h[o>>3];if(x){Tc(j,4095,C,3)}else{Uc(j,4095,C,3)}Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,128,f|0)|0;dg(u,g,4095)|0}else if((d|0)==1){C=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];d=f+8|0;h[k>>3]=C;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];Ea(g|0,4096,112,f|0)|0;dg(u,g,4095)|0}else{C=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];d=f+8|0;h[k>>3]=C;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];Ea(g|0,4096,112,f|0)|0;dg(u,g,4095)|0}d=(yg(z,136)|0)==0;C=+wg(c[m>>2]|0,n);D=C!=0.0;a:do{if(d){if(D){if(x){B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);G=c[w>>2]|0;if((G|0)==0){Tc(j,4095,+h[o>>3],3);Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,160,f|0)|0;dg(u,g,4095)|0}else if((G|0)==1){E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}else{E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}E=+wg(c[m>>2]|0,n);if(E!=0.0){B=E}else{F=E;break}}}else{B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);G=c[w>>2]|0;if((G|0)==1){E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];H=f+8|0;h[k>>3]=E;c[H>>2]=c[k>>2];c[H+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}else if((G|0)==0){Uc(j,4095,+h[o>>3],3);Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,160,f|0)|0;dg(u,g,4095)|0}else{E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}E=+wg(c[m>>2]|0,n);if(E!=0.0){B=E}else{F=E;break}}}}else{F=C}}else{if(D){B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}I=+wg(c[m>>2]|0,n);if(!(I!=0.0)){F=B;break a}J=+wg(c[n>>2]|0,m);if(!(J!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);bc(c[s>>2]|0,I,J,q,r);J=+ec(+h[o>>3],+h[p>>3],+h[q>>3],+h[r>>3])*3600.0;do{if(!(J<=60.0)){if(!(J<=3600.0)){h[k>>3]=J/3600.0;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,192,f|0)|0;dg(u,g,4095)|0;break}else{h[k>>3]=J/60.0;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,184,f|0)|0;dg(u,g,4095)|0;break}}else{h[k>>3]=J;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,176,f|0)|0;dg(u,g,4095)|0}}while(0);J=+wg(c[m>>2]|0,n);if(J!=0.0){B=J}else{F=J;break}}}else{F=C}}}while(0);if(!((yg(z,200)|0)!=0?(yg(z,208)|0)!=0:0)){if(F<0.0){C=F;while(1){B=C+6.283185307179586;if(B<0.0){C=B}else{K=B;break}}}else{K=F}h[k>>3]=K*57.29577951308232;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,216,f|0)|0;dg(u,g,4095)|0}if(A){Ea(g|0,4096,224,f|0)|0;dg(u,g,4095)|0}Ea(g|0,4096,88,f|0)|0;dg(u,g,4095)|0}v=fg(0,88)|0}while((v|0)!=0)}if((b|0)==0){t=u;i=e;return t|0}hg(b);t=u;i=e;return t|0}function Kb(a){a=a|0;var b=0,c=0.0;b=i;c=+af(a,0);i=b;return+c}function Lb(b,d,e,f,j,l,m){b=b|0;d=d|0;e=e|0;f=f|0;j=+j;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0;n=i;i=i+4128|0;o=n;p=n+20|0;q=n+16|0;r=n+24|0;bf(b,d,e,f,p,q,j,l,m);j=+g[q>>2];h[k>>3]=+g[p>>2];c[o>>2]=c[k>>2];c[o+4>>2]=c[k+4>>2];p=o+8|0;h[k>>3]=j;c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];Ea(r|0,4095,240,o|0)|0;o=a[r]|0;a:do{if(!(o<<24>>24==0)){p=r;q=o;while(1){m=p+1|0;if((fb(q<<24>>24|0)|0)==0){break}q=a[m]|0;if(q<<24>>24==0){break a}else{p=m}}q=a[p]|0;if(!(q<<24>>24==0)){m=248;l=p;f=q;while(1){q=l+1|0;s=m+1|0;a[m]=f;e=a[q]|0;if(e<<24>>24==0){break}else{m=s;l=q;f=e}}a[s]=0;if((s|0)==248){i=n;return 248}f=s;l=s-248|0;while(1){m=f+ -1|0;if((fb(a[m]|0)|0)==0){t=11;break}a[m]=0;p=l+ -1|0;if((p|0)==0){t=11;break}else{f=m;l=p}}if((t|0)==11){i=n;return 248}}}}while(0);a[248]=0;i=n;return 248}function Mb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0.0,ha=0.0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0.0,sa=0.0,ta=0.0,ua=0,va=0.0,wa=0,xa=0,ya=0.0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0.0,La=0.0,Ma=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0;e=i;i=i+1184|0;f=e+672|0;g=e+1176|0;j=e+1144|0;l=e+1112|0;m=e+1048|0;n=e+1040|0;p=e+1024|0;q=e+1032|0;r=e+1080|0;s=e+848|0;t=e;u=e+752|0;v=e+744|0;w=e+656|0;x=e+760|0;y=e+664|0;z=e+816|0;A=e+856|0;B=e+736|0;C=e+840|0;D=e+824|0;E=e+808|0;F=e+768|0;G=e+8|0;H=e+1088|0;I=e+868|0;J=e+864|0;K=e+872|0;L=e+880|0;M=e+960|0;N=e+1104|0;O=e+832|0;P=e+800|0;Q=e+728|0;R=ig(1,9336)|0;U=a[d]|0;d=U<<24>>24==32?0:U;a[N]=d;a[R+9324|0]=d;if((Oc(b,4424,N,63,M)|0)!=0){d=ig((Dg(M|0)|0)+2|0,1)|0;c[R+9320>>2]=d;Lg(d|0,M|0)|0}d=R+3984|0;c[d>>2]=0;c[R+3956>>2]=0;c[R+3924>>2]=0;c[R+3952>>2]=-1;U=R+3268|0;c[U>>2]=0;V=R+3272|0;c[V>>2]=0;h[D>>3]=0.0;h[E>>3]=0.0;W=F+8|0;X=F+16|0;Y=F+24|0;c[F+0>>2]=0;c[F+4>>2]=0;c[F+8>>2]=0;c[F+12>>2]=0;c[F+16>>2]=0;c[F+20>>2]=0;c[F+24>>2]=0;c[F+28>>2]=0;h[G>>3]=0.0;Z=R+3300|0;c[Z>>2]=0;_=R+48|0;h[_>>3]=0.0;c[K>>2]=0;Dc(b,4432,N,K)|0;$=c[K>>2]|0;if(($|0)==0){Ec(b,4432,K)|0;ba=c[K>>2]|0;if((ba|0)==0){Ec(b,4440,K)|0;ca=c[K>>2]|0;if((ca|0)==0){Ec(b,4448,K)|0;da=c[K>>2]|0}else{da=ca}}else{da=ba}}else{da=$}if((da|0)<1){_b(4456);Tb(R);ea=0;i=e;return ea|0}if((da|0)>2){c[K>>2]=2;fa=2}else{fa=da}da=R+3316|0;c[da>>2]=fa;$=R+3320|0;c[$>>2]=fa;c[R+3960>>2]=fa;fa=R+136|0;h[fa>>3]=0.0;Lc(b,4504,fa)|0;ga=+h[fa>>3];if(ga<1.0){Lc(b,4512,fa)|0;ha=+h[fa>>3]}else{ha=ga}if(ha<1.0){_b(4520);Tb(R);ea=0;i=e;return ea|0}ba=R+144|0;h[ba>>3]=0.0;Lc(b,4560,ba)|0;if(+h[ba>>3]<1.0){Lc(b,4568,ba)|0}ca=c[K>>2]|0;if((ca|0)>1){if(+h[ba>>3]<1.0){_b(4576);Tb(R);ea=0;i=e;return ea|0}else{ia=19}}else{if((ca|0)>0){ia=19}else{ja=0}}if((ia|0)==19){ca=c[o>>2]|0;ka=0;la=0;while(1){a[H+0|0]=a[4440|0]|0;a[H+1|0]=a[4441|0]|0;a[H+2|0]=a[4442|0]|0;a[H+3|0]=a[4443|0]|0;a[H+4|0]=a[4444|0]|0;a[H+5|0]=a[4445|0]|0;ma=ka+1|0;c[f>>2]=ma;Na(L|0,4616,f|0)|0;Fg(H|0,L|0)|0;do{if((Ec(b,H,J)|0)==0){if((ka|0)==0){ha=+h[fa>>3];if(ha>1.0){c[J>>2]=~~ha;break}}else if((ka|0)==1?(ha=+h[ba>>3],ha>1.0):0){c[J>>2]=~~ha;break}c[f>>2]=H;za(ca|0,4624,f|0)|0}}while(0);a[H+0|0]=a[4664|0]|0;a[H+1|0]=a[4665|0]|0;a[H+2|0]=a[4666|0]|0;a[H+3|0]=a[4667|0]|0;a[H+4|0]=a[4668|0]|0;a[H+5|0]=a[4669|0]|0;Fg(H|0,L|0)|0;if((Pc(b,H,16,L)|0)!=0?(Qc(L,4672)|0)!=0:0){c[J>>2]=0}na=((c[J>>2]|0)>1)+la|0;if((ma|0)<(c[K>>2]|0)){ka=ma;la=na}else{ja=na;break}}}c[K>>2]=ja;c[$>>2]=ja;c[da>>2]=ja;Pc(b,4680,16,R+3336|0)|0;Ec(b,4696,R+3332|0)|0;ja=R+3324|0;c[ja>>2]=kc()|0;$=R+9328|0;c[$>>2]=0;Ec(b,4712,$)|0;$=R+832|0;Eg($|0,0,648)|0;Eg(G|0,0,648)|0;la=c[K>>2]|0;ka=(la|0)>0;if(ka){ca=0;do{h[$+((aa(la,ca)|0)+ca<<3)>>3]=1.0;ca=ca+1|0}while((ca|0)<(la|0));if(ka){ca=0;do{h[G+((aa(la,ca)|0)+ca<<3)>>3]=1.0;ca=ca+1|0}while((ca|0)<(la|0));ca=R+760|0;oa=ca+0|0;pa=oa+72|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));if(ka){ka=0;while(1){h[ca+(ka<<3)>>3]=1.0;na=ka+1|0;if((na|0)<(la|0)){ka=na}else{qa=ca;break}}}else{qa=ca}}else{ia=37}}else{ia=37}if((ia|0)==37){ca=R+760|0;oa=ca+0|0;pa=oa+72|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));qa=ca}do{if((Oc(b,4720,N,63,M)|0)==0){c[R+9312>>2]=0}else{ca=Nb(b,M)|0;a[g]=ca;if(!(ca<<24>>24==95)){ca=Mb(b,g)|0;c[R+9312>>2]=ca;if((ca|0)!=0){c[ca+9316>>2]=R;break}}else{ca=c[o>>2]|0;c[f>>2]=M;za(ca|0,4368,f|0)|0;c[R+9312>>2]=0}_b(4728);Tb(R);ea=0;i=e;return ea|0}}while(0);M=R+3224|0;g=R+3232|0;c[M+0>>2]=0;c[M+4>>2]=0;c[M+8>>2]=0;c[M+12>>2]=0;do{if((Kc(b,4776,N,M)|0)==0){if((Kc(b,4784,N,g)|0)!=0){h[M>>3]=+h[g>>3]*299792.5;break}if((Lc(b,4792,M)|0)!=0){h[g>>3]=+h[M>>3]/299792.5}}else{h[g>>3]=+h[M>>3]/299792.5}}while(0);M=R+4096|0;oa=M+0|0;pa=oa+80|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));do{if((Oc(b,4808,N,16,j)|0)==0){g=a[N]|0;if(!(g<<24>>24==32|g<<24>>24==0)){c[f>>2]=g<<24>>24;Na(L|0,5368,f|0)|0;_b(L);Tb(R);ea=0;i=e;return ea|0}if((Cc(b,5408)|0)!=0){c[R+3260>>2]=29;g=Cc(b,5408)|0;Lc(g,5408,s)|0;Lc(g,5416,t)|0;Lc(g,5424,u)|0;h[R+152>>3]=(+h[s>>3]+ +h[t>>3]/60.0+ +h[u>>3]/3600.0)*15.0*3.141592653589793/180.0;a[r]=43;Pc(g,5432,1,r)|0;ha=(a[r]|0)==45?-1.0:1.0;Lc(g,5448,v)|0;Lc(g,5456,w)|0;Lc(g,5464,x)|0;h[R+160>>3]=ha*(+h[v>>3]+ +h[w>>3]/60.0+ +h[x>>3]/3600.0)*3.141592653589793/180.0;g=R+120|0;Lc(b,5472,g)|0;Ec(b,5472,I)|0;ca=R+3764|0;ka=(c[I>>2]|0)==1950?3427142:3492678;a[ca]=ka;a[ca+1|0]=ka>>8;a[ca+2|0]=ka>>16;a[ca+3|0]=ka>>24;ka=R+128|0;h[ka>>3]=+h[g>>3];Lc(b,5344,ka)|0;ha=+h[t>>3];ga=+h[u>>3];ka=a[r]|0;ra=+h[v>>3];sa=+h[w>>3];ta=+h[x>>3];h[k>>3]=+h[s>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];g=f+8|0;h[k>>3]=ha;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];g=f+16|0;h[k>>3]=ga;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];c[f+24>>2]=ka;ka=f+28|0;h[k>>3]=ra;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];ka=f+36|0;h[k>>3]=sa;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];ka=f+44|0;h[k>>3]=ta;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];c[f+52>>2]=ca;Na(R+3892|0,5496,f|0)|0;Lc(b,5544,R+168|0)|0;Lc(b,5560,R+192|0)|0;Lc(b,5576,R+200|0)|0;Lc(b,5592,R+176|0)|0;Lc(b,5600,R+184|0)|0;ca=Cc(b,5608)|0;ka=R+208|0;c[f>>2]=1;Na(H|0,5616,f|0)|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=2;Na(H|0,5616,f|0)|0;ka=R+216|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=3;Na(H|0,5616,f|0)|0;ka=R+224|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=4;Na(H|0,5616,f|0)|0;ka=R+232|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=5;Na(H|0,5616,f|0)|0;ka=R+240|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=6;Na(H|0,5616,f|0)|0;ka=R+248|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;ka=Cc(b,5624)|0;ca=R+256|0;g=0;while(1){la=g+1|0;c[f>>2]=la;Na(H|0,5632,f|0)|0;na=ca+(g<<3)|0;h[na>>3]=0.0;Lc(ka,H,na)|0;if((la|0)==20){break}else{g=la}}g=Cc(b,5640)|0;ka=R+416|0;ca=0;while(1){ma=ca+1|0;c[f>>2]=ma;Na(H|0,5648,f|0)|0;la=ka+(ca<<3)|0;h[la>>3]=0.0;Lc(g,H,la)|0;if((ma|0)==20){break}else{ca=ma}}ca=R+3312|0;c[ca>>2]=1;g=R+3449|0;a[g+0|0]=a[5656|0]|0;a[g+1|0]=a[5657|0]|0;a[g+2|0]=a[5658|0]|0;g=R+3458|0;a[g]=4408644;a[g+1|0]=17221;a[g+2|0]=67;a[g+3|0]=0;g=R+3467|0;a[g]=5460804;a[g+1|0]=21331;a[g+2|0]=83;a[g+3|0]=0;c[R+3292>>2]=0;c[R+3288>>2]=3;oa=R+3368|0;g=5664|0;pa=oa+9|0;do{a[oa]=a[g]|0;oa=oa+1|0;g=g+1|0}while((oa|0)<(pa|0));oa=R+3377|0;g=5680|0;pa=oa+9|0;do{a[oa]=a[g]|0;oa=oa+1|0;g=g+1|0}while((oa|0)<(pa|0));ta=+h[fa>>3]*.5;g=R+616|0;h[g>>3]=ta;sa=+h[ba>>3]*.5;ka=R+624|0;h[ka>>3]=sa;h[R+16>>3]=ta;h[R+24>>3]=sa;nd(ta,sa,R,z,B)|0;sa=+h[z>>3];h[R+688>>3]=sa;ta=+h[B>>3];h[R+696>>3]=ta;h[R>>3]=sa;h[R+8>>3]=ta;nd(+h[g>>3],+h[ka>>3]+1.0,R,A,C)|0;ta=+h[C>>3]- +h[B>>3];h[R+40>>3]=ta;h[R+32>>3]=-ta;Sb(R);c[ca>>2]=1;ac(R);ta=+h[_>>3]*3.141592653589793/180.0;h[P>>3]=ta;sa=+h[g>>3]+ +S(+ta);nd(sa,+h[ka>>3]+ +T(+ta),R,A,C)|0;h[qa>>3]=-+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);ta=+h[P>>3];sa=+h[g>>3]+ +T(+ta);nd(sa,+h[ka>>3]+ +S(+ta),R,A,C)|0;ta=+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[R+768>>3]=ta;Wb(R,+h[qa>>3],ta,+h[_>>3]);ua=qa;break}if(((((Cc(b,5088)|0)==0?(Cc(b,5096)|0)==0:0)?(Cc(b,5112)|0)==0:0)?(Cc(b,5128)|0)==0:0)?(Cc(b,5144)|0)==0:0){_b(5824);Tb(R);ea=0;i=e;return ea|0}h[y>>3]=0.0;Lc(b,5088,y)|0;ta=+h[y>>3];if(ta==0.0){Lc(b,5096,y)|0;va=+h[y>>3]}else{va=ta}do{if(va==0.0){Lc(b,5144,y)|0;ta=+h[y>>3];if(ta!=0.0){h[D>>3]=-ta/3600.0;Lc(b,5152,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}Lc(b,5128,y)|0;ta=+h[y>>3];if(ta!=0.0){h[D>>3]=-ta/3600.0;Lc(b,5160,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}else{Lc(b,5112,y)|0;h[D>>3]=-+h[y>>3]/3600.0;Lc(b,5176,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}}else{ta=va/3600.0;h[E>>3]=ta;h[D>>3]=-ta}}while(0);h[P>>3]=0.0;Lc(b,5256,P)|0;if(+h[_>>3]==0.0){Lc(b,5248,P)|0}Wb(R,+h[D>>3],+h[E>>3],+h[P>>3]);ca=R+616|0;h[ca>>3]=+h[fa>>3]*.5+.5;ka=R+624|0;h[ka>>3]=+h[ba>>3]*.5+.5;if((Cc(b,4904)|0)!=0){Lc(b,4904,ca)|0;Lc(b,4912,ka)|0}h[R+16>>3]=+h[ca>>3];h[R+24>>3]=+h[ka>>3];ka=R+688|0;h[ka>>3]=-999.0;if((Hc(b,5656,ka)|0)==0){_b(5696);Tb(R);ea=0;i=e;return ea|0}ca=R+696|0;h[ca>>3]=-999.0;if((Ic(b,4832,ca)|0)==0){_b(5736);Tb(R);ea=0;i=e;return ea|0}ta=+h[ka>>3];h[R>>3]=ta;sa=+h[ca>>3];h[R+8>>3]=sa;ca=R+3304|0;c[ca>>2]=0;h[R+3992>>3]=ta;h[R+4e3>>3]=sa;ka=R+4008|0;h[ka>>3]=999.0;if((Lc(b,4936,ka)|0)==0){Lc(b,5776,ka)|0}ka=R+4016|0;h[ka>>3]=999.0;Lc(b,4944,ka)|0;do{if((Lc(b,5312,O)|0)==0){ka=R+128|0;if((Mc(b,5320,ka)|0)==0){if((Mc(b,5336,ka)|0)!=0){break}if((Lc(b,5344,ka)|0)!=0){break}h[ka>>3]=+h[R+120>>3];break}Pc(b,5320,32,m)|0;if(($f(m,84)|0)==0){if((Lc(b,5352,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744;break}if((Lc(b,5360,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744}}}else{h[R+128>>3]=(+h[O>>3]+-15019.81352)/365.242198781+1900.0}}while(0);Vb(R,5792,5808)|0;c[ca>>2]=0;a[f]=0;Rb(b,R,f);Sb(R);c[R+3292>>2]=0;c[R+3288>>2]=3;c[R+3312>>2]=1;ua=qa}else{Lg(l|0,j|0)|0;ka=(Oc(b,4816,N,16,l)|0)==0;Lg(R+3368|0,j|0)|0;Lg(R+3377|0,l|0)|0;if((Qc(l,4824)|0)==0){g=(Qc(l,4832)|0)==0;wa=g?1:2}else{wa=2}g=R+3386|0;a[g]=0;Oc(b,4840,N,9,g)|0;g=R+3395|0;a[g]=0;Oc(b,4848,N,9,g)|0;if((Vb(R,j,l)|0)!=0){Tb(R);ea=0;i=e;return ea|0}g=R+3260|0;if((c[g>>2]|0)==0){ma=R+3476|0;if((Oc(b,4856,N,16,ma)|0)==0?(Yc(b,4864,4872,16,ma)|0)==0:0){a[ma]=0}if((yg(ma,4880)|0)==0){c[g>>2]=-1}if(!ka){ka=R+3508|0;if((Oc(b,4888,N,16,ka)|0)==0?(Yc(b,4896,4872,16,ka)|0)==0:0){a[ka]=0}if((yg(ma,4880)|0)==0){c[g>>2]=-1}}}ma=R+616|0;h[ma>>3]=1.0;Kc(b,4904,N,ma)|0;ka=R+624|0;h[ka>>3]=1.0;Kc(b,4912,N,ka)|0;h[R+16>>3]=+h[ma>>3];h[R+24>>3]=+h[ka>>3];la=R+688|0;h[la>>3]=0.0;Kc(b,4920,N,la)|0;na=R+696|0;h[na>>3]=0.0;Kc(b,4928,N,na)|0;xa=c[R+3884>>2]|0;if((xa|0)==7){h[na>>3]=90.0- +h[na>>3];ia=74}else if((xa|0)==8){sa=+h[na>>3]+-90.0;h[na>>3]=sa;ya=sa}else{ia=74}if((ia|0)==74){ya=+h[na>>3]}sa=+h[la>>3];h[R>>3]=sa;h[R+8>>3]=ya;la=R+3992|0;if((c[R+3304>>2]|0)==0){h[la>>3]=sa;h[R+4e3>>3]=ya}else{h[la>>3]=ya;h[R+4e3>>3]=sa}la=R+3176|0;h[la>>3]=999.0;Kc(b,4936,N,la)|0;h[R+4008>>3]=+h[la>>3];la=R+3184|0;h[la>>3]=999.0;Kc(b,4944,N,la)|0;h[R+4016>>3]=+h[la>>3];c[R+3964>>2]=ma;c[R+3972>>2]=qa;c[R+3968>>2]=$;la=R+4088|0;h[la>>3]=0.0;Kc(b,4952,N,la)|0;c[f>>2]=0;Na(H|0,4960,f|0)|0;Kc(b,H,N,M)|0;c[f>>2]=1;Na(H|0,4960,f|0)|0;la=R+4104|0;Kc(b,H,N,la)|0;c[f>>2]=2;Na(H|0,4960,f|0)|0;na=R+4112|0;Kc(b,H,N,na)|0;c[f>>2]=3;Na(H|0,4960,f|0)|0;xa=R+4120|0;Kc(b,H,N,xa)|0;c[f>>2]=4;Na(H|0,4960,f|0)|0;Aa=R+4128|0;Kc(b,H,N,Aa)|0;c[f>>2]=5;Na(H|0,4960,f|0)|0;Ba=R+4136|0;Kc(b,H,N,Ba)|0;c[f>>2]=6;Na(H|0,4960,f|0)|0;Ca=R+4144|0;Kc(b,H,N,Ca)|0;c[f>>2]=7;Na(H|0,4960,f|0)|0;Da=R+4152|0;Kc(b,H,N,Da)|0;c[f>>2]=8;Na(H|0,4960,f|0)|0;Ea=R+4160|0;Kc(b,H,N,Ea)|0;c[f>>2]=9;Na(H|0,4960,f|0)|0;Fa=R+4168|0;Kc(b,H,N,Fa)|0;c[f>>2]=wa;Na(n|0,4968,f|0)|0;c[f>>2]=wa;Na(p|0,4976,f|0)|0;c[f>>2]=wa;Na(q|0,4984,f|0)|0;Ga=c[g>>2]|0;switch(Ga|0){case 7:{c[f>>2]=wa;c[f+4>>2]=0;Na(H|0,4992,f|0)|0;Kc(b,H,N,M)|0;c[f>>2]=wa;c[f+4>>2]=1;Na(H|0,4992,f|0)|0;Kc(b,H,N,la)|0;c[f>>2]=wa;c[f+4>>2]=2;Na(H|0,4992,f|0)|0;Kc(b,H,N,na)|0;c[f>>2]=wa;c[f+4>>2]=3;Na(H|0,4992,f|0)|0;Kc(b,H,N,xa)|0;c[f>>2]=wa;c[f+4>>2]=4;Na(H|0,4992,f|0)|0;Kc(b,H,N,Aa)|0;c[f>>2]=wa;c[f+4>>2]=5;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ba)|0;c[f>>2]=wa;c[f+4>>2]=6;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ca)|0;c[f>>2]=wa;c[f+4>>2]=7;Na(H|0,4992,f|0)|0;Kc(b,H,N,Da)|0;c[f>>2]=wa;c[f+4>>2]=8;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ea)|0;c[f>>2]=wa;c[f+4>>2]=9;Na(H|0,4992,f|0)|0;Kc(b,H,N,Fa)|0;ia=97;break};case 17:case 15:case 16:case 14:case 4:case 1:{Kc(b,n,N,R+4104|0)|0;Kc(b,p,N,R+4112|0)|0;ia=97;break};case 2:{Kc(b,n,N,R+4104|0)|0;Kc(b,p,N,R+4112|0)|0;Fa=R+4120|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=90.0}Kc(b,q,N,Fa)|0;ia=97;break};case 13:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,n,N,Fa)|0;ia=97;break};case 10:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,n,N,Fa)|0;Fa=R+4112|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,p,N,Fa)|0;ia=97;break};case 9:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=90.0}Kc(b,n,N,Fa)|0;ia=97;break};case 18:{Kc(b,n,N,R+4104|0)|0;ia=97;break};default:{Ha=Ga}}if((ia|0)==97){Ha=c[g>>2]|0}do{if((Ha|0)==31){if((dd(b,R)|0)==0){Ia=c[g>>2]|0;ia=102;break}else{a[R+3374|0]=65;a[R+3375|0]=78;a[R+3383|0]=65;a[R+3384|0]=78;c[g>>2]=3;break}}else{Ia=Ha;ia=102}}while(0);a:do{if((ia|0)==102){do{if((Ia|0)==32){if((kd(b,R)|0)==0){Ja=c[g>>2]|0;break}else{a[R+3375|0]=78;a[R+3384|0]=78;c[g>>2]=7;break a}}else{Ja=Ia}}while(0);if((Ja|0)==33){a[R+3374|0]=65;a[R+3375|0]=78;a[R+3383|0]=65;a[R+3384|0]=78;c[g>>2]=3}}}while(0);if((c[ja>>2]|0)>0){Rb(b,R,N)}Sb(R);Ye(R,b);c[U>>2]=0;c[V>>2]=0;ca=Kc(b,5e3,N,F)|0;Ga=Kc(b,5008,N,W)|0;Fa=Kc(b,5016,N,X)|0;Ea=Kc(b,5024,N,Y)|0;if((c[ja>>2]|0)!=2?(Da=Cc(b,5032)|0,(Da|0)!=0):0){c[g>>2]=30;Ca=R+3467|0;a[Ca+0|0]=a[5040|0]|0;a[Ca+1|0]=a[5041|0]|0;a[Ca+2|0]=a[5042|0]|0;a[Ca+3|0]=a[5043|0]|0;a[Ca+4|0]=a[5044|0]|0;a[Ca+5|0]=a[5045|0]|0;Ca=R+256|0;Ba=0;while(1){Aa=Ba+1|0;c[f>>2]=Aa;Na(H|0,5048,f|0)|0;xa=Ca+(Ba<<3)|0;h[xa>>3]=0.0;if((Lc(Da,H,xa)|0)!=0){c[U>>2]=Aa}if((Aa|0)==20){break}else{Ba=Aa}}Ba=Cc(b,5056)|0;Da=R+416|0;Ca=0;while(1){Aa=Ca+1|0;c[f>>2]=Aa;Na(H|0,5064,f|0)|0;xa=Da+(Ca<<3)|0;h[xa>>3]=0.0;if((Lc(Ba,H,xa)|0)!=0){c[V>>2]=Aa}if((Aa|0)==20){break}else{Ca=Aa}}bd(+h[ma>>3],+h[ka>>3],R,z,B)|0;bd(+h[ma>>3],+h[ka>>3]+1.0,R,A,C)|0;sa=+h[C>>3]- +h[B>>3];Ca=R+40|0;h[Ca>>3]=sa;Ba=R+32|0;h[Ba>>3]=-sa;c[R+3312>>2]=1;ac(R);h[P>>3]=+h[_>>3]*3.141592653589793/180.0;bd(+h[ma>>3],+h[ka>>3],R,z,B)|0;sa=+h[P>>3];ta=+h[ma>>3]+ +S(+sa);bd(ta,+h[ka>>3]+ +T(+sa),R,A,C)|0;sa=-+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[qa>>3]=sa;h[Ba>>3]=sa;sa=+h[P>>3];ta=+h[ma>>3]+ +T(+sa);bd(ta,+h[ka>>3]+ +S(+sa),R,A,C)|0;sa=+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[R+768>>3]=sa;h[Ca>>3]=sa;Ca=R+56|0;h[Ca>>3]=+h[F>>3];h[R+64>>3]=+h[W>>3];h[R+72>>3]=+h[X>>3];h[R+80>>3]=+h[Y>>3];Bd(2,Ca,R+88|0)|0}else{ia=121}do{if((ia|0)==121){if((Ga|ca|Fa|Ea|0)!=0){c[Z>>2]=1;Zb(R,F);break}if((Kc(b,5072,N,D)|0)==0){h[R+32>>3]=1.0;h[R+40>>3]=1.0;h[qa>>3]=1.0;h[R+768>>3]=1.0;h[_>>3]=0.0;c[Z>>2]=0;_b(5264);break}Kc(b,5080,N,E)|0;if(!(+h[D>>3]==0.0)){if(+h[ba>>3]>1.0){sa=+h[E>>3];if(sa==0.0){ia=127}else{Ka=sa}}else{ia=154}}else{ia=127}do{if((ia|0)==127){if(((((Cc(b,5088)|0)==0?(Cc(b,5096)|0)==0:0)?(Cc(b,5112)|0)==0:0)?(Cc(b,5128)|0)==0:0)?(Cc(b,5144)|0)==0:0){ia=154;break}h[y>>3]=0.0;Lc(b,5088,y)|0;sa=+h[y>>3];if(sa==0.0){Lc(b,5096,y)|0;La=+h[y>>3]}else{La=sa}if(!(La==0.0)){if(+h[D>>3]==0.0){h[D>>3]=-La/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}sa=La/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5144,y)|0;sa=+h[y>>3];if(sa!=0.0){if(+h[D>>3]==0.0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}Lc(b,5152,y)|0;sa=+h[y>>3]/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5128,y)|0;sa=+h[y>>3];if(sa!=0.0){if(+h[D>>3]==0.0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}Lc(b,5160,y)|0;sa=+h[y>>3]/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5112,y)|0;sa=+h[y>>3];if(sa!=0.0?+h[D>>3]==0.0:0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(sa==0.0){Lc(b,5176,y)|0;ta=+h[y>>3]/3600.0;h[E>>3]=ta;Ka=ta}else{Ka=sa}}}while(0);if((ia|0)==154){Ka=+h[E>>3]}if(Ka==0.0?+h[ba>>3]>1.0:0){h[E>>3]=-+h[D>>3]}h[R+776>>3]=1.0;h[R+784>>3]=1.0;Eg(G|0,0,648)|0;Eg($|0,0,648)|0;Ca=c[K>>2]|0;if((Ca|0)>0){Ba=0;do{h[G+((aa(Ca,Ba)|0)+Ba<<3)>>3]=1.0;Ba=Ba+1|0}while((Ba|0)<(Ca|0))}if((a[N]|0)==0?(Lc(b,5192,G)|0)!=0:0){Ca=c[K>>2]|0;if((Ca|0)>0){Ba=Ca;Ca=0;Da=0;while(1){c[J>>2]=0;Aa=Ca+1|0;if((Ba|0)>0){xa=0;na=Da;while(1){la=G+(na<<3)|0;h[la>>3]=(Ca|0)==(xa|0)?1.0:0.0;c[f>>2]=Aa;c[f+4>>2]=xa+1;Na(H|0,5208,f|0)|0;Ma=na+1|0;Lc(b,H,la)|0;la=(c[J>>2]|0)+1|0;c[J>>2]=la;Oa=c[K>>2]|0;if((la|0)<(Oa|0)){xa=la;na=Ma}else{Pa=Oa;Qa=Ma;break}}}else{Pa=Ba;Qa=Da}if((Aa|0)<(Pa|0)){Ba=Pa;Ca=Aa;Da=Qa}else{break}}}$b(R,+h[D>>3],+h[E>>3],G);break}if((Kc(b,5224,N,G)|0)==0){h[P>>3]=0.0;if((wa|0)==2){Kc(b,5248,N,P)|0}else{Kc(b,5256,N,P)|0}Wb(R,+h[D>>3],+h[E>>3],+h[P>>3]);break}Da=c[K>>2]|0;if((Da|0)>0){Ca=Da;Da=0;Ba=0;while(1){c[J>>2]=0;na=Da+1|0;if((Ca|0)>0){xa=0;Ma=Ba;while(1){Oa=G+(Ma<<3)|0;h[Oa>>3]=(Da|0)==(xa|0)?1.0:0.0;c[f>>2]=na;c[f+4>>2]=xa+1;Na(H|0,5232,f|0)|0;la=Ma+1|0;Kc(b,H,N,Oa)|0;Oa=(c[J>>2]|0)+1|0;c[J>>2]=Oa;Ra=c[K>>2]|0;if((Oa|0)<(Ra|0)){xa=Oa;Ma=la}else{Sa=Ra;Ta=la;break}}}else{Sa=Ca;Ta=Ba}if((na|0)<(Sa|0)){Ca=Sa;Da=na;Ba=Ta}else{break}}}$b(R,+h[D>>3],+h[E>>3],G)}}while(0);if((c[g>>2]|0)==3?(c[da>>2]|0)==2:0){Ea=R+3168|0;Fa=c[Ea>>2]|0;if((Fa|0)!=0){rd(Fa);c[Ea>>2]=0}Ea=R+3172|0;Fa=c[Ea>>2]|0;if((Fa|0)!=0){rd(Fa);c[Ea>>2]=0}c[R+1560>>2]=0;Ea=R+1568|0;Fa=R+4344|0;ca=0;do{h[Ea+(ca<<3)>>3]=0.0;h[Fa+(ca<<3)>>3]=0.0;ca=ca+1|0}while((ca|0)!=200);c[J>>2]=0;ca=0;g=0;while(1){c[f>>2]=1;c[f+4>>2]=g;Na(H|0,4992,f|0)|0;if((Kc(b,H,N,Ea+(c[J>>2]<<3)|0)|0)==0){Ga=c[J>>2]|0;h[Ea+(Ga<<3)>>3]=0.0;Ua=Ga;Va=ca}else{Ua=c[J>>2]|0;Va=ca+1|0}g=Ua+1|0;c[J>>2]=g;if((g|0)>=100){break}else{ca=Va}}c[J>>2]=0;ca=Va;g=0;while(1){c[f>>2]=2;c[f+4>>2]=g;Na(H|0,4992,f|0)|0;if((Kc(b,H,N,Ea+((c[J>>2]|0)+100<<3)|0)|0)==0){Ga=c[J>>2]|0;h[Ea+(Ga+100<<3)>>3]=0.0;Wa=Ga;Xa=ca}else{Wa=c[J>>2]|0;Xa=ca+1|0}g=Wa+1|0;c[J>>2]=g;if((g|0)>=100){break}else{ca=Xa}}if((Xa|0)>0){ca=R+3948|0;g=R+3944|0;Ga=100;ka=0;while(1){sa=+h[Ea+(((c[ca>>2]|0)*100|0)+Ga<<3)>>3];h[Fa+(Ga<<3)>>3]=sa;ta=+h[Ea+(((c[g>>2]|0)*100|0)+Ga<<3)>>3];h[Fa+(Ga+100<<3)>>3]=ta;if((ka|0)==0){Ya=sa!=0.0|ta!=0.0?Ga+1|0:0}else{Ya=ka}if((Ga|0)>0){Ga=Ga+ -1|0;ka=Ya}else{break}}Qb(R);c[d>>2]=0}}ka=R+3467|0;if(!((Ag(ka,5296,6)|0)!=0?(Ag(ka,5304,5)|0)!=0:0)){c[R+3292>>2]=-1;c[R+3288>>2]=5}do{if((Lc(b,5312,O)|0)==0){ka=R+128|0;if((Mc(b,5320,ka)|0)==0){if((Mc(b,5336,ka)|0)!=0){break}if((Lc(b,5344,ka)|0)!=0){break}h[ka>>3]=+h[R+120>>3];break}Pc(b,5320,32,m)|0;if(($f(m,84)|0)==0){if((Lc(b,5352,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744;break}if((Lc(b,5360,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744}}}else{h[R+128>>3]=(+h[O>>3]+-15019.81352)/365.242198781+1900.0}}while(0);c[R+3312>>2]=1;ua=qa}}while(0);c[R+3964>>2]=R+616;c[R+3972>>2]=ua;c[R+3968>>2]=$;c[R+3284>>2]=1;c[R+3296>>2]=0;c[R+3328>>2]=0;Yb(R);ea=R;i=e;return ea|0}function Nb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=i;i=i+96|0;f=e;g=e+16|0;if((d|0)==0){h=0;i=e;return h|0}j=Dg(d|0)|0;k=ig(1,j+1|0)|0;if((j|0)>0){l=0;do{m=a[d+l|0]|0;if((m+ -97<<24>>24&255)<26){a[k+l|0]=(m&255)+224}else{a[k+l|0]=m}l=l+1|0}while((l|0)!=(j|0))}a[k+j|0]=0;if((Dg(k|0)|0)==1){h=a[k]|0;i=e;return h|0}j=f;c[j>>2]=1314079575;c[j+4>>2]=4541761;a[f+8|0]=0;j=f+7|0;l=95;d=0;while(1){if((d|0)>0){n=d+64&255}else{n=0}a[j]=n;if((Pc(b,f,72,g)|0)==0){o=l}else{m=Dg(g|0)|0;p=ig(1,m+1|0)|0;if((m|0)>0){q=0;do{r=a[g+q|0]|0;if((r+ -97<<24>>24&255)<26){a[p+q|0]=(r&255)+224}else{a[p+q|0]=r}q=q+1|0}while((q|0)!=(m|0))}a[p+m|0]=0;q=(yg(p,k)|0)==0;hg(p);o=q?n:l}d=d+1|0;if((d|0)==27){break}else{l=o}}hg(k);h=o;i=e;return h|0}function Ob(b,c){b=b|0;c=c|0;var d=0,e=0;d=i;i=i+16|0;e=d;a[e]=0;Bc(b,c)|0;c=Mb(b,e)|0;i=d;return c|0}function Pb(b){b=b|0;var c=0,d=0,e=0;c=i;i=i+16|0;d=c;a[d]=0;e=Mb(b,d)|0;i=c;return e|0}function Qb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;b=i;i=i+176|0;d=b+88|0;e=b+40|0;f=b+16|0;g=b+56|0;j=b+80|0;k=b+168|0;l=b+32|0;m=b+72|0;n=b+8|0;o=b;p=j;c[p>>2]=1;c[p+4>>2]=1;p=c[a+3944>>2]|0;q=c[a+3948>>2]|0;if((c[a+3316>>2]|0)!=2){i=b;return}r=a+3928|0;if((yg(r,5848)|0)!=0){i=b;return}if(+h[a+((p*100|1)<<3)+1568>>3]==0.0?+h[a+((q*100|1)<<3)+1568>>3]==0.0:0){i=b;return}s=a+9312|0;t=c[s>>2]|0;if((t|0)==0){h[l>>3]=0.0;h[m>>3]=0.0;h[n>>3]=+h[a+136>>3];h[o>>3]=+h[a+144>>3]}else{bc(t,0.0,0.0,l,m);bc(c[s>>2]|0,+h[a+136>>3],+h[a+144>>3],n,o)}if((p|0)==0){u=+h[l>>3];v=+h[m>>3];w=v;x=+h[o>>3]-v;y=u;z=+h[n>>3]-u}else{u=+h[m>>3];v=+h[l>>3];w=v;x=+h[n>>3]-v;y=u;z=+h[o>>3]-u}u=x/11.0;x=z/11.0;o=ig(288,8)|0;n=ig(144,8)|0;l=ig(144,8)|0;z=w+.5;m=g+(q<<3)|0;h[m>>3]=z;s=f+(q<<3)|0;h[s>>3]=z;z=y+.5;t=g+(p<<3)|0;h[t>>3]=z;A=f+(p<<3)|0;h[A>>3]=z;B=a+3956|0;C=e+(p<<3)|0;p=e+(q<<3)|0;q=a+4064|0;y=z;D=11;E=l;F=n;G=o;while(1){h[A>>3]=y;H=E+96|0;I=11;J=E;K=F;L=G;while(1){if((Dd(f,B,e)|0)!=0){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}h[K>>3]=+h[C>>3];h[J>>3]=+h[p>>3];Wd(q,+h[C>>3],+h[p>>3],L,L+8|0)|0;h[A>>3]=x+ +h[A>>3];if((I|0)==0){break}else{I=I+ -1|0;J=J+8|0;K=K+8|0;L=L+16|0}}h[s>>3]=u+ +h[s>>3];if((D|0)==0){break}y=+h[t>>3];D=D+ -1|0;E=H;F=F+96|0;G=G+192|0}Dd(g,B,e)|0;h[C>>3]=+h[C>>3]+.0002777777777777778;Cd(e,B,f)|0;y=+h[A>>3]- +h[t>>3];u=+h[s>>3]- +h[m>>3];x=+Q(+(y*y+u*u))*3600.0;if(!(x!=0.0)){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}u=.04/x;c[k>>2]=1;C=0;G=1;a:while(1){if((G|0)>1){rd(C)}M=qd(j,2,k,1)|0;td(M,o,n,0,144,0);F=143;E=n;D=o;while(1){x=+sd(M,D);if(+P(+(x- +h[E>>3]))>u){break}if((F|0)==0){N=26;break a}else{F=F+ -1|0;E=E+8|0;D=D+16|0}}D=c[k>>2]|0;E=D+1|0;c[k>>2]=E;if((D|0)>8){N=28;break}else{C=M;G=E}}if((N|0)==26){c[k>>2]=(c[k>>2]|0)+1}else if((N|0)==28){_b(5904);c[a+1560>>2]=1}c[a+3168>>2]=M;c[a+5944>>2]=M;Dd(g,B,e)|0;h[p>>3]=+h[p>>3]+.0002777777777777778;Cd(e,B,f)|0;u=+h[A>>3]- +h[t>>3];x=+h[s>>3]- +h[m>>3];y=+Q(+(u*u+x*x))*3600.0;if(!(y!=0.0)){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}x=.04/y;c[k>>2]=1;d=M;M=1;b:while(1){if((M|0)>1){rd(d)}O=qd(j,2,k,1)|0;td(O,o,l,0,144,0);r=143;m=l;s=o;while(1){y=+sd(O,s);if(+P(+(y- +h[m>>3]))>x){break}if((r|0)==0){N=37;break b}else{r=r+ -1|0;m=m+8|0;s=s+16|0}}s=c[k>>2]|0;m=s+1|0;c[k>>2]=m;if((s|0)>8){N=39;break}else{d=O;M=m}}if((N|0)==37){c[k>>2]=(c[k>>2]|0)+1}else if((N|0)==39){_b(5904);c[a+1560>>2]=1}c[a+3172>>2]=O;c[a+5948>>2]=O;hg(o);hg(n);hg(l);i=b;return}function Rb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0,z=0.0,A=0,B=0,C=0;f=i;i=i+144|0;g=f+24|0;j=f+28|0;k=f+32|0;l=f+112|0;m=f+96|0;n=f+8|0;o=f+64|0;p=f;c[j>>2]=0;a[k]=0;a[l]=0;q=a[e]|0;if(q<<24>>24==0){r=n;c[r>>2]=1230328133;c[r+4>>2]=5787470;s=m+0|0;t=6e3|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0))}else{c[g>>2]=q<<24>>24;Na(n|0,5968,g|0)|0;c[g>>2]=a[e]|0;Na(m|0,5984,g|0)|0}if((Pc(b,n,31,l)|0)==0?(Pc(b,5472,31,l)|0)!=0:0){g=n;c[g>>2]=1230328133;c[g+4>>2]=5787470}if((Pc(b,m,31,k)|0)==0?(Pc(b,6e3,31,k)|0)!=0:0){s=m+0|0;t=6e3|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0))}g=a[l]|0;do{if(g<<24>>24==74){e=l+1|0;h[d+120>>3]=+ug(e);c[j>>2]=vg(e)|0;c[k>>2]=3492678;v=0;w=30}else if(!(g<<24>>24==66)){if((Ec(b,n,j)|0)!=0){Lc(b,n,d+120|0)|0;v=1;w=30;break}if((Ec(b,5344,j)|0)!=0){if((c[j>>2]|0)==0){c[j>>2]=1950;h[d+120>>3]=1950.0;v=0;w=30;break}else{Lc(b,5344,d+120|0)|0;v=1;w=30;break}}if((a[k]|0)!=0){if((Ag(k,5480,3)|0)==0){h[d+120>>3]=1950.0;c[j>>2]=1950;x=0;break}if((Ag(k,6016,4)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,5488,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,6024,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,6032,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0}else{v=0;w=30}}else{v=0;w=30}}else{e=l+1|0;h[d+120>>3]=+ug(e);c[j>>2]=~~+ug(e);c[k>>2]=3427142;v=0;w=30}}while(0);do{if((w|0)==30){if((c[j>>2]|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;l=d+3449|0;if((Ag(l,5656,2)|0)!=0?(Ag(l,4832,3)|0)!=0:0){x=v;break}c[k>>2]=3492678;x=v}else{x=v}}}while(0);v=d+128|0;do{if((Mc(b,5320,v)|0)==0){if((Mc(b,5336,v)|0)==0?(Lc(b,5344,v)|0)==0:0){y=+h[d+120>>3];h[v>>3]=y;z=y}else{w=43}}else{Pc(b,5320,32,o)|0;if(($f(o,84)|0)==0){if((Lc(b,5352,p)|0)!=0){y=+h[v>>3]+ +h[p>>3]/8765.812770744;h[v>>3]=y;z=y;break}if((Lc(b,5360,p)|0)!=0){y=+h[v>>3]+ +h[p>>3]/8765.812770744;h[v>>3]=y;z=y}else{w=43}}else{w=43}}}while(0);if((w|0)==43){z=+h[v>>3]}if(z==0.0){h[v>>3]=+h[d+120>>3]}do{if((a[k]|0)==0?(Pc(b,m,31,k)|0,(a[k]|0)==0):0){if((c[d+3884>>2]|0)!=7){v=d+3764|0;if((c[j>>2]|0)>1980){a[v]=3492678;a[v+1|0]=13643;a[v+2|0]=53;a[v+3|0]=0;break}else{a[v]=3427142;a[v+1|0]=13387;a[v+2|0]=52;a[v+3|0]=0;break}}}else{w=48}}while(0);do{if((w|0)==48?(m=d+3764|0,Lg(m|0,k|0)|0,(x|0)==0):0){if((Ag(m,5480,3)|0)==0){h[d+120>>3]=1950.0;break}if((Ag(m,5488,3)|0)==0){h[d+120>>3]=2.0e3;break}if((Ag(m,6016,4)|0)==0){h[d+120>>3]=2.0e3;break}if((Ag(m,6024,3)|0)==0?(c[j>>2]|0)==0:0){h[d+120>>3]=2.0e3}}}while(0);switch(a[d+3449|0]|0){case 71:{j=d+3764|0;s=j+0|0;t=6040|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 72:{j=d+3764|0;s=j+0|0;t=6088|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 65:{j=d+3764|0;a[j+0|0]=a[6104|0]|0;a[j+1|0]=a[6105|0]|0;a[j+2|0]=a[6106|0]|0;a[j+3|0]=a[6107|0]|0;a[j+4|0]=a[6108|0]|0;a[j+5|0]=a[6109|0]|0;A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 76:{j=d+3764|0;a[j+0|0]=a[5296|0]|0;a[j+1|0]=a[5297|0]|0;a[j+2|0]=a[5298|0]|0;a[j+3|0]=a[5299|0]|0;a[j+4|0]=a[5300|0]|0;a[j+5|0]=a[5301|0]|0;a[j+6|0]=a[5302|0]|0;A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 69:{j=d+3764|0;s=j+0|0;t=6056|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 83:{j=d+3764|0;s=j+0|0;t=6072|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};default:{A=d+3764|0;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return}}}function Sb(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0;d=i;e=b+3764|0;f=c[b+3260>>2]|0;if((a[e]|0)!=0){if((f|0)==0){g=0;j=3}else{k=f}}else{g=f;j=3}if((j|0)==3){a[e+0|0]=a[5296|0]|0;a[e+1|0]=a[5297|0]|0;a[e+2|0]=a[5298|0]|0;a[e+3|0]=a[5299|0]|0;a[e+4|0]=a[5300|0]|0;a[e+5|0]=a[5301|0]|0;a[e+6|0]=a[5302|0]|0;k=g}if((k|0)==-1){a[e+0|0]=a[5304|0]|0;a[e+1|0]=a[5305|0]|0;a[e+2|0]=a[5306|0]|0;a[e+3|0]=a[5307|0]|0;a[e+4|0]=a[5308|0]|0;a[e+5|0]=a[5309|0]|0}k=nc(e)|0;c[b+3884>>2]=k;do{if((k|0)!=2){g=b+3796|0;if((k|0)==1){a[g]=3492678;a[g+1|0]=13643;a[g+2|0]=53;a[g+3|0]=0;break}else{Lg(g|0,e|0)|0;break}}else{g=b+3796|0;a[g]=3427142;a[g+1|0]=13387;a[g+2|0]=52;a[g+3|0]=0}}while(0);c[b+3888>>2]=nc(b+3796|0)|0;k=b+120|0;h[b+3872>>3]=+h[k>>3];g=b+3828|0;Lg(g|0,e|0)|0;c[b+3880>>2]=nc(g)|0;h[b+3864>>3]=+h[k>>3];i=d;return}function Tb(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){i=b;return}if((c[a+3312>>2]|0)==0){hg(a);i=b;return}d=a+9312|0;e=c[d>>2]|0;if((e|0)!=0){Tb(e);c[d>>2]=0}Ub(a);d=c[a+9320>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3980>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3976>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3168>>2]|0;if((d|0)!=0){rd(d)}d=c[a+3172>>2]|0;if((d|0)!=0){rd(d)}hg(a);i=b;return}function Ub(a){a=a|0;var b=0,d=0;b=i;d=c[1654]|0;if((d|0)!=0){hg(d);c[1654]=0}d=c[6620>>2]|0;if((d|0)!=0){hg(d);c[6620>>2]=0}d=c[6624>>2]|0;if((d|0)!=0){hg(d);c[6624>>2]=0}d=c[6628>>2]|0;if((d|0)!=0){hg(d);c[6628>>2]=0}d=c[6632>>2]|0;if((d|0)!=0){hg(d);c[6632>>2]=0}d=c[6636>>2]|0;if((d|0)!=0){hg(d);c[6636>>2]=0}d=c[6640>>2]|0;if((d|0)!=0){hg(d);c[6640>>2]=0}d=c[6644>>2]|0;if((d|0)!=0){hg(d);c[6644>>2]=0}d=c[6648>>2]|0;if((d|0)!=0){hg(d);c[6648>>2]=0}d=c[6652>>2]|0;if((d|0)!=0){hg(d);c[6652>>2]=0}if((a|0)==0){i=b;return}if((c[a+3312>>2]|0)==0){i=b;return}d=c[a+9208>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9212>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9216>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9220>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9224>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9228>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9232>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9236>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9240>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9244>>2]|0;if((d|0)==0){i=b;return}hg(d);i=b;return}function Vb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+144|0;g=f;h=f+8|0;c[h>>2]=5130572;c[h+4>>2]=5265985;c[h+8>>2]=5266003;c[h+12>>2]=5128532;c[h+16>>2]=5130579;c[h+20>>2]=4674643;c[h+24>>2]=4411969;c[h+28>>2]=5132378;c[h+32>>2]=4277594;c[h+36>>2]=5392705;c[h+40>>2]=5265731;c[h+44>>2]=5390659;c[h+48>>2]=5391693;c[h+52>>2]=4277571;c[h+56>>2]=5263171;c[h+60>>2]=4476739;c[h+64>>2]=4542275;c[h+68>>2]=5197635;c[h+72>>2]=5132098;c[h+76>>2]=5194576;c[h+80>>2]=4998739;c[h+84>>2]=5390672;c[h+88>>2]=5523777;c[h+92>>2]=5001037;c[h+96>>2]=4412227;c[h+100>>2]=4412241;c[h+104>>2]=4412244;c[h+108>>2]=5260110;c[h+112>>2]=5459015;c[h+116>>2]=5460804;c[h+120>>2]=5524560;c[h+124>>2]=5787220;c[h+128>>2]=5787738;c[h+132>>2]=5656660;if((Ag(d,6128,4)|0)==0){a[d]=1313819736;a[d+1|0]=5132108;a[d+2|0]=20047;a[d+3|0]=78}j=b+3368|0;Lg(j|0,d|0)|0;k=b+3449|0;Lg(k|0,d|0)|0;l=b+3467|0;Lg(l|0,d|0)|0;do{if((Ag(d,6136,6)|0)!=0){if((Ag(d,6144,6)|0)==0){c[b+3260>>2]=-1;break}if((Qc(d,6152)|0)!=0){c[b+3260>>2]=-1;break}m=a[d]|0;if(!(m<<24>>24==65|m<<24>>24==68|m<<24>>24==82)?(a[d+1|0]|0)!=76:0){c[b+3260>>2]=0;i=f;return 0}a[k]=m;a[b+3450|0]=a[d+1|0]|0;m=a[d+2|0]|0;n=b+3451|0;do{if(!(m<<24>>24==45)){a[n]=m;o=a[d+3|0]|0;p=b+3452|0;if(o<<24>>24==45){a[p]=0;q=4;break}else{a[p]=o;a[b+3453|0]=0;q=4;break}}else{a[n]=0;q=3}}while(0);n=((a[d+q|0]|0)==45)+q|0;m=n+((a[d+n|0]|0)==45)|0;n=m+((a[d+m|0]|0)==45)|0;m=n+((a[d+n|0]|0)==45)|0;a[l]=a[d+m|0]|0;a[b+3468|0]=a[d+(m+1)|0]|0;a[b+3469|0]=a[d+(m+2)|0]|0;a[b+3470|0]=0;c[g>>2]=k;c[g+4>>2]=l;Na(j|0,6160,g|0)|0;if((a[j]|0)==32){a[j]=45}m=b+3369|0;if((a[m]|0)==32){a[m]=45}m=b+3370|0;if((a[m]|0)==32){a[m]=45}m=b+3371|0;if((a[m]|0)==32){a[m]=45}m=b+3372|0;if((a[m]|0)==32){a[m]=45}m=b+3373|0;if((a[m]|0)==32){a[m]=45}m=b+3374|0;if((a[m]|0)==32){a[m]=45}n=b+3375|0;if((a[n]|0)==32){a[n]=45}o=b+3260|0;c[o>>2]=0;p=0;r=1;while(1){if((Ag(l,h+(r<<2)|0,3)|0)==0){c[o>>2]=r;s=r}else{s=p}r=r+1|0;if((r|0)==34){break}else{p=s}}p=b+3324|0;r=c[p>>2]|0;if((r|0)==0){c[p>>2]=3;break}else if((r|0)==1){c[p>>2]=2}else if((r|0)!=2){break}if((s|0)==31){a[m]=65;a[n]=78;c[o>>2]=3;break}else if((s|0)==32){a[m]=80;a[n]=78;c[o>>2]=7;break}else{break}}else{c[b+3260>>2]=0}}while(0);do{if((Ag(e,6168,4)|0)!=0){if((Ag(e,6192,4)|0)==0){a[e]=a[d]|0;s=e+1|0;a[s+0|0]=a[6176|0]|0;a[s+1|0]=a[6177|0]|0;a[s+2|0]=a[6178|0]|0;c[b+3264>>2]=-90;s=b+3764|0;a[s]=4280403;a[s+1|0]=16720;a[s+2|0]=65;a[s+3|0]=0;c[b+3884>>2]=8;break}else{c[b+3264>>2]=0;break}}else{a[e]=a[d]|0;s=e+1|0;a[s+0|0]=a[6176|0]|0;a[s+1|0]=a[6177|0]|0;a[s+2|0]=a[6178|0]|0;c[b+3264>>2]=90;s=b+3764|0;a[s+0|0]=a[6184|0]|0;a[s+1|0]=a[6185|0]|0;a[s+2|0]=a[6186|0]|0;a[s+3|0]=a[6187|0]|0;a[s+4|0]=a[6188|0]|0;a[s+5|0]=a[6189|0]|0;c[b+3884>>2]=7}}while(0);s=b+3377|0;Lg(s|0,e|0)|0;h=b+3458|0;Lg(h|0,e|0)|0;do{if((Ag(e,6136,6)|0)!=0){if((Ag(e,6144,6)|0)==0){c[b+3260>>2]=-1;break}j=a[e]|0;if(!(j<<24>>24==65|j<<24>>24==68|j<<24>>24==82)?(a[e+1|0]|0)!=76:0){c[b+3260>>2]=0;break}a[h]=j;j=e+1|0;a[b+3459|0]=a[j]|0;k=a[e+2|0]|0;q=b+3460|0;do{if(!(k<<24>>24==45)){a[q]=k;r=a[e+3|0]|0;p=b+3461|0;if(r<<24>>24==45){a[p]=0;t=4;break}else{a[p]=r;a[b+3462|0]=0;t=4;break}}else{a[q]=0;t=3}}while(0);q=((a[e+t|0]|0)==45)+t|0;k=q+((a[e+q|0]|0)==45)|0;q=k+((a[e+k|0]|0)==45)|0;k=q+((a[e+q|0]|0)==45)|0;a[l]=a[e+k|0]|0;a[b+3468|0]=a[e+(k+1)|0]|0;a[b+3469|0]=a[e+(k+2)|0]|0;a[b+3470|0]=0;if((Ag(d,6120,3)|0)!=0?(Ag(d+1|0,6176,3)|0)!=0:0){c[b+3304>>2]=0}else{c[b+3304>>2]=1}if((a[j]|0)!=76?(a[e]|0)!=65:0){c[b+3292>>2]=0;c[b+3288>>2]=3}else{c[b+3292>>2]=1;c[b+3288>>2]=5}c[g>>2]=h;c[g+4>>2]=l;Na(s|0,6160,g|0)|0;if((a[s]|0)==32){a[s]=45}k=b+3378|0;if((a[k]|0)==32){a[k]=45}k=b+3379|0;if((a[k]|0)==32){a[k]=45}k=b+3380|0;if((a[k]|0)==32){a[k]=45}k=b+3381|0;if((a[k]|0)==32){a[k]=45}k=b+3382|0;if((a[k]|0)==32){a[k]=45}k=b+3383|0;if((a[k]|0)==32){a[k]=45}k=b+3384|0;if((a[k]|0)==32){a[k]=45}}else{c[b+3260>>2]=0}}while(0);$e(b,d);i=f;return 0}function Wb(a,b,d,e){a=a|0;b=+b;d=+d;e=+e;var f=0,g=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0;f=i;g=c[a+3316>>2]|0;j=a+760|0;h[j>>3]=b;k=a+768|0;l=d!=0.0?d:b;h[k>>3]=l;h[a+32>>3]=b;h[a+40>>3]=l;if((g|0)>0){m=(g|0)<2?g:2;g=0;n=a+832|0;while(1){o=0;p=n;while(1){h[p>>3]=(g|0)==(o|0)?1.0:0.0;o=o+1|0;if((o|0)==(m|0)){break}else{p=p+8|0}}g=g+1|0;if((g|0)==(m|0)){break}else{n=n+(m<<3)|0}}}c[a+3300>>2]=0;m=a+48|0;if(e<0.0){q=e+360.0}else{q=e}if(!(q>=360.0)){r=q}else{r=q+-360.0}h[m>>3]=r;q=r*3.141592653589793/180.0;r=+S(+q);if(b*d>0.0){s=-q}else{s=q}q=+T(+s);s=+h[j>>3];n=a+56|0;h[n>>3]=r*s;d=+h[k>>3];b=q*+P(+d);if(s<0.0){h[a+64>>3]=-b}else{h[a+64>>3]=b}b=q*+P(+s);if(d<0.0){h[a+72>>3]=b}else{h[a+72>>3]=-b}h[a+80>>3]=r*d;Bd(2,n,a+88|0)|0;lc(a);d=+h[j>>3];j=d<0.0;if((c[a+3304>>2]|0)!=0){if(j?+h[k>>3]>0.0:0){c[a+3256>>2]=1;r=+h[m>>3];b=r+-90.0;n=a+3200|0;if(b<-180.0){h[n>>3]=b+360.0;h[a+3208>>3]=r;h[a+3216>>3]=b+360.0;i=f;return}else{h[n>>3]=b;h[a+3208>>3]=r;h[a+3216>>3]=b;i=f;return}}do{if(d>0.0){if(!(+h[k>>3]<0.0)){if(!(+h[k>>3]>0.0)){break}c[a+3256>>2]=0;b=+h[m>>3]+90.0;n=a+3200|0;if(b>180.0){r=b+-360.0;h[n>>3]=r;h[a+3208>>3]=r;h[a+3216>>3]=b+-360.0;i=f;return}else{h[n>>3]=b;h[a+3208>>3]=b;h[a+3216>>3]=b;i=f;return}}else{c[a+3256>>2]=1;b=+h[m>>3];r=b+90.0;if(r>180.0){t=r+-360.0}else{t=r}h[a+3200>>3]=t;h[a+3208>>3]=b;r=b+-90.0;n=a+3216|0;h[n>>3]=r;if(!(r<-180.0)){i=f;return}h[n>>3]=r+360.0;i=f;return}}}while(0);if(!j){i=f;return}if(!(+h[k>>3]<0.0)){i=f;return}c[a+3256>>2]=0;t=+h[m>>3];r=t+-90.0;if(r<-180.0){u=r+360.0}else{u=r}h[a+3200>>3]=u;h[a+3208>>3]=u;u=t+90.0;n=a+3216|0;h[n>>3]=u;if(!(u>180.0)){i=f;return}h[n>>3]=u+-360.0;i=f;return}if(j?+h[k>>3]>0.0:0){c[a+3256>>2]=0;u=+h[m>>3];h[a+3200>>3]=u;t=u+90.0;if(t>180.0){v=t+-360.0}else{v=t}h[a+3208>>3]=v;v=u+180.0;n=a+3216|0;h[n>>3]=v;if(!(v>180.0)){i=f;return}h[n>>3]=v+-360.0;i=f;return}do{if(d>0.0){if(!(+h[k>>3]<0.0)){if(!(+h[k>>3]>0.0)){break}c[a+3256>>2]=1;v=+h[m>>3];h[a+3200>>3]=-v;u=90.0-v;if(u>180.0){w=u+-360.0}else{w=u}h[a+3208>>3]=w;h[a+3216>>3]=v;i=f;return}c[a+3256>>2]=0;v=+h[m>>3]+180.0;if(v>180.0){x=v+-360.0}else{x=v}h[a+3200>>3]=x;v=x+90.0;if(v>180.0){y=v+-360.0}else{y=v}h[a+3208>>3]=y;v=x+180.0;n=a+3216|0;h[n>>3]=v;if(!(v>180.0)){i=f;return}h[n>>3]=v+-360.0;i=f;return}}while(0);if(!j){i=f;return}if(!(+h[k>>3]<0.0)){i=f;return}c[a+3256>>2]=1;x=+h[m>>3];y=x+180.0;if(y>180.0){z=y+-360.0}else{z=y}h[a+3200>>3]=z;y=z+90.0;if(y>180.0){A=y+-360.0}else{A=y}h[a+3208>>3]=A;A=x+90.0;m=a+3216|0;h[m>>3]=A;if(!(A>180.0)){i=f;return}h[m>>3]=A+-360.0;i=f;return}function Xb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,o=0.0;e=i;i=i+16|0;f=e;if((b|0)==0){i=e;return}g=b+3312|0;if((c[g>>2]|0)==0){i=e;return}do{if((((d|0)!=0?(a[d]|0)!=0:0)?(yg(d,6200)|0)!=0:0)?(yg(d,6208)|0)!=0:0){j=nc(d)|0;if((j|0)<0){i=e;return}l=c[b+3884>>2]|0;if((j|0)!=(l|0)&(l+ -5|0)>>>0<2){i=e;return}else{Lg(b+3796|0,d|0)|0;h[b+3872>>3]=+oc(d);m=j;break}}else{n=7}}while(0);do{if((n|0)==7){d=c[b+3884>>2]|0;j=b+3796|0;Lg(j|0,b+3764|0)|0;o=+h[b+120>>3];h[b+3872>>3]=o;if((d|0)==1){if(!(o!=2.0e3)){a[j+0|0]=a[6232|0]|0;a[j+1|0]=a[6233|0]|0;a[j+2|0]=a[6234|0]|0;a[j+3|0]=a[6235|0]|0;a[j+4|0]=a[6236|0]|0;a[j+5|0]=a[6237|0]|0;m=1;break}a[j]=74;h[k>>3]=o;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Na(b+3797|0,6216,f|0)|0;l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)!=48){m=1;break}a[l]=0;m=1;break}else if((d|0)==2){if(!(o!=1950.0)){a[j+0|0]=a[6224|0]|0;a[j+1|0]=a[6225|0]|0;a[j+2|0]=a[6226|0]|0;a[j+3|0]=a[6227|0]|0;a[j+4|0]=a[6228|0]|0;a[j+5|0]=a[6229|0]|0;m=2;break}a[j]=66;h[k>>3]=o;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Na(b+3797|0,6216,f|0)|0;l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)!=48){m=2;break}a[l]=0;m=2;break}else{m=d;break}}}while(0);c[b+3888>>2]=m;if((c[g>>2]|0)==0){i=e;return}switch(m|0){case 5:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};case 8:case 7:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};case 9:case 4:case 3:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};default:{c[b+3292>>2]=0;c[b+3288>>2]=3;i=e;return}}}function Yb(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;d=i;i=i+32|0;e=d;f=d+8|0;if((b|0)==0){i=d;return}g=b+3312|0;if((c[g>>2]|0)==0){i=d;return}h=0;a:while(1){if((h|0)==0){j=f+0|0;k=6656|0;l=j+12|0;do{a[j]=a[k]|0;j=j+1|0;k=k+1|0}while((j|0)<(l|0))}else{c[e>>2]=h;Na(f|0,6672,e|0)|0}k=c[6616+(h<<2)>>2]|0;b:do{if((k|0)!=0){if((c[g>>2]|0)!=0?(j=Dg(k|0)|0,(j|0)>0):0){l=b+(h<<2)+9208|0;m=c[l>>2]|0;if((m|0)!=0){hg(m)}m=ig(j+2|0,1)|0;c[l>>2]=m;if((m|0)!=0){n=m;m=0;do{o=a[k+m|0]|0;a[n+m|0]=o<<24>>24==95?32:o;m=m+1|0;n=c[l>>2]|0}while((m|0)!=(j|0));a[n+j|0]=0}}}else{m=Wa(f|0)|0;if((m|0)!=0){if((c[g>>2]|0)==0){break}l=Dg(m|0)|0;if((l|0)<=0){break}o=b+(h<<2)+9208|0;p=c[o>>2]|0;if((p|0)!=0){hg(p)}p=ig(l+2|0,1)|0;c[o>>2]=p;if((p|0)==0){break}else{q=p;r=0}do{p=a[m+r|0]|0;a[q+r|0]=p<<24>>24==95?32:p;r=r+1|0;q=c[o>>2]|0}while((r|0)!=(l|0));a[q+l|0]=0;break}switch(h|0){case 4:{if((c[g>>2]|0)!=0){o=b+9224|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=112;a[m+2|0]=112;a[m+3|0]=109;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};case 2:{if((c[g>>2]|0)!=0){m=b+9216|0;o=c[m>>2]|0;if((o|0)!=0){hg(o)}o=ig(13,1)|0;c[m>>2]=o;if((o|0)==0){break b}a[o]=115;a[o+1|0]=103;a[o+2|0]=115;a[o+3|0]=99;a[o+4|0]=32;a[o+5|0]=45;a[o+6|0]=97;a[o+7|0]=104;a[o+8|0]=32;a[o+9|0]=37;a[o+10|0]=115;a[o+11|0]=0;break b}break};case 3:{if((c[g>>2]|0)!=0){o=b+9220|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=116;a[m+2|0]=121;a[m+3|0]=50;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};case 5:{if((c[g>>2]|0)!=0){m=b+9228|0;o=c[m>>2]|0;if((o|0)!=0){hg(o)}o=ig(13,1)|0;c[m>>2]=o;if((o|0)==0){break b}a[o]=115;a[o+1|0]=115;a[o+2|0]=97;a[o+3|0]=111;a[o+4|0]=32;a[o+5|0]=45;a[o+6|0]=97;a[o+7|0]=104;a[o+8|0]=32;a[o+9|0]=37;a[o+10|0]=115;a[o+11|0]=0;break b}break};case 1:{if((c[g>>2]|0)!=0){o=b+9212|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=117;a[m+2|0]=97;a[m+3|0]=50;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};default:{c[b+(h<<2)+9208>>2]=0;break b}}h=h+1|0;continue a}}while(0);h=h+1|0;if((h|0)==10){break}}i=d;return}function Zb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0.0,l=0.0;d=i;if((b|0)==0){i=d;return}c[a+3300>>2]=1;e=a+56|0;h[e>>3]=+h[b>>3];f=b+8|0;h[a+64>>3]=+h[f>>3];g=b+16|0;h[a+72>>3]=+h[g>>3];j=b+24|0;h[a+80>>3]=+h[j>>3];Bd(2,e,a+88|0)|0;k=+h[b>>3];l=+h[g>>3];b=a+32|0;h[b>>3]=+Q(+(k*k+l*l));l=+h[f>>3];k=+h[j>>3];j=a+40|0;h[j>>3]=+Q(+(l*l+k*k));if((c[a+3304>>2]|0)!=0){k=+h[f>>3];h[f>>3]=-+h[g>>3];h[g>>3]=-k}lc(a);c[a+3312>>2]=1;ac(a);h[a+760>>3]=+h[b>>3];h[a+768>>3]=+h[j>>3];i=d;return}function _b(a){a=a|0;var b=0;b=i;Lg(6536,a|0)|0;i=b;return}function $b(a,b,d,e){a=a|0;b=+b;d=+d;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;f=i;if((e|0)==0){i=f;return}g=a+3316|0;j=c[g>>2]|0;if((j+ -1|0)>>>0>8){k=c[a+3320>>2]|0;c[g>>2]=k;l=k}else{l=j}j=a+760|0;h[j>>3]=b;k=a+768|0;m=d!=0.0?d:b;h[k>>3]=m;h[a+32>>3]=b;h[a+40>>3]=m;if((l|0)>0){g=0;n=e;o=a+832|0;while(1){p=n+(l<<3)|0;q=0;r=n;s=o;while(1){h[s>>3]=+h[r>>3];q=q+1|0;if((q|0)==(l|0)){break}else{r=r+8|0;s=s+8|0}}s=g+1|0;if((s|0)==(l|0)){break}else{g=s;n=p;o=o+(l<<3)|0}}m=+h[j>>3];j=a+56|0;h[j>>3]=+h[e>>3]*m;if((l|0)>1){h[a+64>>3]=+h[e+8>>3]*m;m=+h[k>>3];h[a+72>>3]=+h[e+(l<<3)>>3]*m;h[a+80>>3]=+h[e+(l+1<<3)>>3]*m;t=j}else{u=j;v=11}}else{j=a+56|0;h[j>>3]=+h[e>>3]*b;u=j;v=11}if((v|0)==11){v=a+64|0;j=a+80|0;c[v+0>>2]=0;c[v+4>>2]=0;c[v+8>>2]=0;c[v+12>>2]=0;h[j>>3]=1.0;t=u}Bd(2,t,a+88|0)|0;c[a+3300>>2]=1;Ad(a+3956|0)|0;c[a+3312>>2]=1;ac(a);i=f;return}function ac(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;b=i;i=i+64|0;d=b+48|0;e=b+24|0;f=b+16|0;g=b+40|0;j=b;k=b+32|0;l=b+8|0;if(!(+h[a+136>>3]<1.5)?!(+h[a+144>>3]<1.5):0){if((c[a+3884>>2]|0)==6){i=b;return}m=a+32|0;h[m>>3]=+P(+(+h[m>>3]));n=a+40|0;h[n>>3]=+P(+(+h[n>>3]));o=+h[a+16>>3];p=+h[a+24>>3];bc(a,o,p,e,f);q=a+3304|0;r=+h[e>>3];if((c[q>>2]|0)==0){s=+h[f>>3];e=a+3828|0;ic(a,r+ +h[m>>3],s,e,j,l,d);ic(a,r,s+ +h[n>>3],e,g,k,d)}else{s=+h[f>>3];f=a+3828|0;ic(a,r+ +h[n>>3],s,f,j,l,d);ic(a,r,s+ +h[m>>3],f,g,k,d)}s=+Y(+(+h[k>>3]-p),+(+h[g>>3]-o))*180.0/3.141592653589793;if(s<-90.0){t=s+360.0}else{t=s}h[a+3208>>3]=t;s=+Y(+(+h[l>>3]-p),+(+h[j>>3]-o))*180.0/3.141592653589793;if(s<-90.0){u=s+360.0}else{u=s}h[a+3216>>3]=u;if(t<-90.0){s=t+270.0;h[a+3200>>3]=s;v=s}else{s=t+-90.0;h[a+3200>>3]=s;v=s}j=(c[q>>2]|0)==0;if(!j){s=v+90.0;q=a+48|0;h[q>>3]=s;if(s<0.0){o=s+360.0;h[q>>3]=o;w=o}else{w=s}}else{h[a+48>>3]=v;w=v}q=a+48|0;if(w<0.0){v=w+360.0;h[q>>3]=v;x=v}else{x=w}if(x>=360.0){h[q>>3]=x+-360.0}x=u-t;w=t-u;q=w>80.0&w<100.0?1:x<280.0&x>260.0?1:x<-80.0&x>-100.0&1;c[a+3256>>2]=q;l=(q|0)!=0;if(j){if(l){i=b;return}h[m>>3]=-+h[m>>3];i=b;return}else{if(!l){i=b;return}h[n>>3]=-+h[n>>3];i=b;return}}x=+h[a+48>>3];h[a+3200>>3]=x;h[a+3208>>3]=x+90.0;h[a+3216>>3]=x+180.0;i=b;return}function bc(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0.0,x=0.0,y=0.0;g=i;i=i+144|0;j=g+104|0;k=g+56|0;l=g+8|0;m=g+40|0;n=g+136|0;o=g;p=g+48|0;q=g+96|0;r=g+88|0;if((a|0)==0){i=g;return}if((c[a+3312>>2]|0)==0){i=g;return}h[a+576>>3]=b;h[a+584>>3]=d;h[a+592>>3]=+h[815];s=a+3308|0;c[s>>2]=0;t=c[a+9312>>2]|0;if((t|0)==0){_e(a,b,d,o,p)}else{bc(t,b,d,o,p)}t=a+3260|0;u=c[t>>2]|0;do{if((u|0)==30){if((bd(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==31){if((ed(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==32){if((ld(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==29){if((nd(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else{d=+h[o>>3];b=+h[p>>3];if((c[a+3324>>2]|0)==2|(u|0)<1){if(($c(d,b,a,q,r)|0)==0){v=24;break}c[s>>2]=1;w=0.0;x=0.0;break}h[q>>3]=0.0;h[r>>3]=0.0;h[l>>3]=d;h[l+8>>3]=b;if((u+ -24|0)>>>0<3){h[l+16>>3]=+((c[1632]|0)+1|0)}else{h[l+16>>3]=+h[815]}h[l+24>>3]=1.0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;c[k+16>>2]=0;c[k+20>>2]=0;c[k+24>>2]=0;c[k+28>>2]=0;if((zd(a+3368|0,a+3924|0,l,a+3956|0,k,a+4064|0,m,n,a+688|0,a+3984|0,j)|0)==0){h[q>>3]=+h[j+(c[a+3944>>2]<<3)>>3];h[r>>3]=+h[j+(c[a+3948>>2]<<3)>>3];v=24;break}else{c[s>>2]=1;w=0.0;x=0.0;break}}}while(0);if((v|0)==24){if((c[s>>2]|0)==0){if((c[t>>2]|0)>0){mc(c[a+3884>>2]|0,c[a+3888>>2]|0,+h[a+120>>3],+h[a+3872>>3],q,r,+h[a+128>>3])}t=c[a+3264>>2]|0;if((t|0)==90){b=90.0- +h[r>>3];h[r>>3]=b;y=b}else if((t|0)==-90){b=+h[r>>3]+-90.0;h[r>>3]=b;y=b}else{y=+h[r>>3]}b=+h[q>>3];h[a+600>>3]=b;h[a+608>>3]=y;w=y;x=b}else{w=0.0;x=0.0}}h[e>>3]=x;h[f>>3]=w;f=c[a+3888>>2]|0;if((f|0)<1){i=g;return}if((f|0)==6|(f|0)==10){i=g;return}w=+h[e>>3];if(w<0.0){h[e>>3]=w+360.0;i=g;return}if(!(w>360.0)){i=g;return}h[e>>3]=w+-360.0;i=g;return}function cc(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=d|0;e=e|0;f=f|0;var g=0;g=i;ic(a,b,c,a+3828|0,d,e,f);i=g;return}function dc(b,d,e,f,g){b=b|0;d=+d;e=+e;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+96|0;k=j+16|0;l=j+8|0;m=j;n=j+56|0;o=j+24|0;if((b|0)!=0?(c[b+3312>>2]|0)!=0:0){bc(b,d,e,l,m);if((c[b+3308>>2]|0)!=0){p=f;q=p;a[q]=543581775;a[q+1|0]=2123366;a[q+2|0]=8294;a[q+3|0]=32;q=p+4|0;a[q]=7364973;a[q+1|0]=28769;a[q+2|0]=112;a[q+3|0]=0;r=1;i=j;return r|0}q=c[b+3292>>2]|0;do{if((q|0)==0){p=b+3288|0;s=c[p>>2]|0;t=(s<<1)+18|0;if((t|0)>=(g|0)){if((c[b+3296>>2]|0)==0){Hg(f|0,6336,g|0)|0;u=0;break}else{Hg(f|0,6304,g|0)|0;u=0;break}}e=+h[l>>3];if(((c[b+3888>>2]|0)+ -1|0)>>>0<2){Tc(n,32,e,s);Uc(o,32,+h[m>>3],(c[p>>2]|0)+ -1|0)}else{Uc(n,32,e,s);Uc(o,32,+h[m>>3],c[p>>2]|0)}if((c[b+3296>>2]|0)==0){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0}u=g-t|0}else if((q|0)==1){t=b+3288|0;p=c[t>>2]|0;s=(p<<1)+9|0;if((s|0)>=(g|0)){if((c[b+3296>>2]|0)==0){Hg(f|0,6280,g|0)|0;u=0;break}else{Hg(f|0,6256,g|0)|0;u=0;break}}Vc(n,32,+h[l>>3],p);Vc(o,32,+h[m>>3],c[t>>2]|0);if((c[b+3296>>2]|0)==0){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0}u=g-s|0}else{u=g}}while(0);switch(c[b+3888>>2]|0){case 5:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(q){q=s;t=q;a[t]=1953259808;a[t+1|0]=7629921;a[t+2|0]=29804;a[t+3|0]=116;t=q+4|0;a[t]=8020269;a[t+1|0]=31329;a[t+2|0]=122;a[t+3|0]=0;r=1;i=j;return r|0}else{t=s;s=t;a[s]=1953259785;a[s+1|0]=7629921;a[s+2|0]=29804;a[s+3|0]=116;s=t+4|0;a[s]=8020269;a[s+1|0]=31329;a[s+2|0]=122;a[s+3|0]=0;r=1;i=j;return r|0}break};case 4:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;t=f+(Dg(f|0)|0)|0;if(s){v=t+0|0;w=6416|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=t+0|0;w=6400|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 9:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}t=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(t){t=s;q=t;a[q]=1634496544;a[q+1|0]=6384752;a[q+2|0]=24940;a[q+3|0]=97;q=t+4|0;a[q]=7628142;a[q+1|0]=29797;a[q+2|0]=116;a[q+3|0]=0;r=1;i=j;return r|0}else{q=s;s=q;a[s]=1634496521;a[s+1|0]=6384752;a[s+2|0]=24940;a[s+3|0]=97;s=q+4|0;a[s]=7628142;a[s+1|0]=29797;a[s+2|0]=116;a[s+3|0]=0;r=1;i=j;return r|0}break};case 8:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;q=f+(Dg(f|0)|0)|0;if(s){v=q+0|0;w=6480|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=q+0|0;w=6464|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 7:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(q){v=s+0|0;w=6448|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=s+0|0;w=6432|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 1:case 2:{s=b+3796|0;if((u|0)<=((Dg(s|0)|0)+1|0)){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;t=f+(Dg(f|0)|0)|0;p=q?32:9;a[t]=p;a[t+1|0]=p>>8;Fg(f|0,s|0)|0;r=1;i=j;return r|0};case 3:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;p=f+(Dg(f|0)|0)|0;if(s){v=p+0|0;w=6384|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=p+0|0;w=6368|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};default:{w=b+3288|0;Wc(n,+h[l>>3],0,c[w>>2]|0);Wc(o,+h[m>>3],0,c[w>>2]|0);w=Dg(n|0)|0;m=w+1+(Dg(o|0)|0)|0;l=b+3476|0;v=b+3508|0;x=(Dg(l|0)|0)+2+(Dg(v|0)|0)|0;p=b+3884|0;if(((c[p>>2]|0)==6?(c[b+3328>>2]|0)==1:0)?(s=x+m|0,(u|0)>(s|0)):0){if((a[l]|0)!=0){t=n+w|0;a[t]=32;a[t+1|0]=0;Fg(n|0,l|0)|0}if((a[v]|0)==0){y=s}else{t=o+(Dg(o|0)|0)|0;a[t]=32;a[t+1|0]=0;Fg(o|0,v|0)|0;y=s}}else{y=m}m=(c[b+3296>>2]|0)!=0;do{if((u|0)>(y|0)){if(m){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0;break}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0;break}}else{if(m){Hg(f|0,6496,u|0)|0;break}else{Hg(f|0,6280,u|0)|0;break}}}while(0);if((c[p>>2]|0)!=6){r=1;i=j;return r|0}m=b+3328|0;if((c[m>>2]|0)==1){r=1;i=j;return r|0}if((u|0)>(y+7|0)?(b=f+(Dg(f|0)|0)|0,k=b,a[k]=1852402720,a[k+1|0]=7235948,a[k+2|0]=28265,a[k+3|0]=110,k=b+4|0,a[k]=7496037,a[k+1|0]=29281,a[k+2|0]=114,a[k+3|0]=0,(c[p>>2]|0)!=6):0){r=1;i=j;return r|0}if((c[m>>2]|0)!=2){r=1;i=j;return r|0}if((u|0)<=(x+7+y|0)){r=1;i=j;return r|0}if((a[l]|0)!=0){y=f+(Dg(f|0)|0)|0;a[y]=32;a[y+1|0]=0;Fg(f|0,l|0)|0}if((a[v]|0)==0){r=1;i=j;return r|0}l=f+(Dg(f|0)|0)|0;a[l]=32;a[l+1|0]=0;Fg(f|0,v|0)|0;r=1;i=j;return r|0}}}if((g|0)<=0){r=0;i=j;return r|0}a[f]=0;r=0;i=j;return r|0}function ec(a,b,c,d){a=+a;b=+b;c=+c;d=+d;var e=0,f=0,g=0;e=i;i=i+48|0;f=e+24|0;g=e;Ac(a,b,1.0,f);Ac(c,d,1.0,g);d=+h[f>>3]- +h[g>>3];c=+h[f+8>>3]- +h[g+8>>3];b=+h[f+16>>3]- +h[g+16>>3];a=(d*d+0.0+c*c+b*b)*.25;b=a>1.0?1.0:a;a=+Y(+(+Q(+b)),+(+Q(+(1.0-b))))*2.0*180.0/3.141592653589793;i=e;return+a}function fc(a){a=a|0;var b=0;if((a|0)==0){b=0}else{b=(c[a+3312>>2]|0)!=0}return(b?a+3796|0:0)|0}function gc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;if((a|0)!=0?(c[a+3312>>2]|0)!=0:0){e=a+3292|0;f=c[e>>2]|0;c[e>>2]=b;if((b|0)==1&(f|0)==0?(e=a+3288|0,(c[e>>2]|0)==3):0){c[e>>2]=6}if((b|0)==0&(f|0)==1){b=a+3288|0;if((c[b>>2]|0)==5){c[b>>2]=3;g=1}else{g=1}}else{g=f}}else{g=0}i=d;return g|0}function hc(a){a=a|0;var b=0;if((a|0)==0){b=0}else{b=(c[a+3312>>2]|0)!=0}return(b?a+3764|0:0)|0}function ic(a,b,d,e,f,g,j){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0;k=i;i=i+32|0;l=k+24|0;m=k+16|0;n=k+8|0;o=k;if((a|0)==0){i=k;return}if((c[a+3312>>2]|0)==0){i=k;return}c[j>>2]=0;h[l>>3]=b;h[m>>3]=d;p=c[a+3264>>2]|0;if((p|0)==90){h[m>>3]=90.0-d}else if((p|0)==-90){h[m>>3]=d+-90.0}if((e|0)==0){q=+h[a+120>>3];r=c[a+3884>>2]|0}else{p=nc(e)|0;q=+oc(e);r=p}h[a+592>>3]=1.0;if((r|0)>0?!((r|0)==6|(r|0)==10):0){mc(r,c[a+3884>>2]|0,q,+h[a+120>>3],l,m,+h[a+128>>3])}r=c[a+3260>>2]|0;do{if((r|0)==32){if((md(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==30){if((cd(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==29){if((od(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==31){if((fd(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else{q=+h[l>>3];s=+h[m>>3];if((c[a+3324>>2]|0)==2|(r|0)<1){if((ad(q,s,a,n,o)|0)==0){break}c[j>>2]=1;break}else{if((jc(q,s,a,n,o)|0)==0){break}c[j>>2]=1;break}}}while(0);r=c[a+9312>>2]|0;s=+h[n>>3];q=+h[o>>3];do{if((r|0)==0){Ze(a,s,q,f,g);o=c[j>>2]|0;if((o|0)==0){t=+h[f>>3];if(!(t<.5)?(u=+h[g>>3],!(u<.5)):0){if(!(t>+h[a+136>>3]+.5)?!(u>+h[a+144>>3]+.5):0){v=0;break}c[j>>2]=2;v=2;break}c[j>>2]=2;v=2}else{v=o}}else{ic(r,s,q,0,f,g,j);v=c[j>>2]|0}}while(0);c[a+3308>>2]=v;h[a+600>>3]=b;h[a+608>>3]=d;h[a+576>>3]=+h[f>>3];h[a+584>>3]=+h[g>>3];i=k;return}function jc(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+112|0;j=g+80|0;k=g+48|0;l=g+16|0;m=g+8|0;n=g;h[e>>3]=0.0;h[f>>3]=0.0;o=d+3924|0;if((c[o>>2]|0)!=137){p=d+3368|0;if((xd(c[d+3960>>2]|0,p,o)|0)==0){q=p}else{r=1;i=g;return r|0}}else{q=d+3368|0}p=d+3944|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;c[j+16>>2]=0;c[j+20>>2]=0;c[j+24>>2]=0;c[j+28>>2]=0;h[j+(c[p>>2]<<3)>>3]=a;h[j+(c[d+3948>>2]<<3)>>3]=b;p=l+16|0;c[l+0>>2]=0;c[l+4>>2]=0;c[l+8>>2]=0;c[l+12>>2]=0;h[p>>3]=1.0;h[l+24>>3]=1.0;s=k+16|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;h[s>>3]=1.0;h[k+24>>3]=1.0;s=yd(q,o,j,d+688|0,d+3984|0,m,n,d+4064|0,k,d+3956|0,l)|0;if((s|0)!=0){r=s;i=g;return r|0}h[e>>3]=+h[l>>3];h[f>>3]=+h[l+8>>3];b=+h[p>>3];if(((c[d+3260>>2]|0)+ -24|0)>>>0<3){h[d+592>>3]=b+-1.0;r=0;i=g;return r|0}else{h[d+592>>3]=b;r=0;i=g;return r|0}return 0}function kc(){return c[1528]|0}function lc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0;b=i;d=a+3316|0;e=c[d>>2]|0;f=(e|0)>2?2:e;if((f+ -1|0)>>>0>8){e=c[a+3320>>2]|0;c[d>>2]=e;g=e}else{g=f}f=aa(g<<3,g)|0;e=a+3976|0;d=c[e>>2]|0;if((d|0)==0){j=gg(f)|0;c[e>>2]=j;if((j|0)==0){i=b;return}else{k=j}}else{k=d}d=a+3980|0;if((c[d>>2]|0)==0?(j=gg(f)|0,c[d>>2]=j,(j|0)==0):0){i=b;return}j=a+3956|0;c[j>>2]=137;if((g|0)==3){l=k+0|0;m=l+72|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));f=c[e>>2]|0;h[f>>3]=+h[a+56>>3];h[f+8>>3]=+h[a+64>>3];h[f+24>>3]=+h[a+72>>3];h[f+32>>3]=+h[a+80>>3];h[f+64>>3]=1.0;n=f}else if((g|0)==2){h[k>>3]=+h[a+56>>3];h[k+8>>3]=+h[a+64>>3];h[k+16>>3]=+h[a+72>>3];h[k+24>>3]=+h[a+80>>3];n=k}else if((g|0)==4){l=k+0|0;m=l+128|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));l=c[e>>2]|0;h[l>>3]=+h[a+56>>3];h[l+8>>3]=+h[a+64>>3];h[l+32>>3]=+h[a+72>>3];h[l+40>>3]=+h[a+80>>3];h[l+80>>3]=1.0;h[l+120>>3]=1.0;n=l}else{n=k}Bd(g,n,c[d>>2]|0)|0;c[a+3964>>2]=a+616;c[a+3972>>2]=a+760;c[a+3968>>2]=a+832;c[j>>2]=137;i=b;return}function mc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=+c;d=+d;e=e|0;f=f|0;g=+g;var j=0,k=0,l=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0,s=0,t=0.0;j=i;i=i+32|0;k=j+24|0;l=j+16|0;m=j+8|0;n=j;if(c==0.0){o=(a|0)==2?1950.0:2.0e3}else{o=c}if(d==0.0){p=(b|0)==2?1950.0:2.0e3}else{p=d}q=(b|0)==11;r=(a|0)==1&q&o==2.0e3;d=r?o:(a|0)==11&q?o:p;q=r?b:a;a=(b|0)==1;r=(q|0)==11&a&d==2.0e3;p=r?d:o;s=r?b:q;if((s|0)==(b|0)&p==d){i=j;return}q=p!=d;if(q){if((s|0)==2&p!=1950.0){xc(p,1950.0,e,f)}if((s|0)==1&p!=2.0e3){yc(p,2.0e3,e,f)}}r=(b|0)==2;do{if(r){if((s|0)==3){sc(e,f);break}else if((s|0)==4){if(g>0.0){wc(e,f,g);h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);p=g+-1950.0;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{wc(e,f,1950.0);h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);h[e>>3]=+h[e>>3]+ +h[m>>3]*0.0;h[f>>3]=+h[f>>3]+ +h[n>>3]*0.0;break}}else if((s|0)==1){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);p=g+-1950.0;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);break}}else{break}}else{if((b|0)==4){if((s|0)==1){if(g>0.0){vc(e,f,g);break}else{vc(e,f,2.0e3);break}}else if((s|0)==3){uc(e,f);if(g>0.0){vc(e,f,g);break}else{vc(e,f,2.0e3);break}}else if((s|0)==2){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);p=g+-2.0e3;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];vc(e,f,g);break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);h[e>>3]=+h[e>>3]+ +h[m>>3]*-50.0;h[f>>3]=+h[f>>3]+ +h[n>>3]*-50.0;vc(e,f,1950.0);break}}else{break}}else if((b|0)==3){if((s|0)==4){if(g>0.0){wc(e,f,g)}else{wc(e,f,2.0e3)}tc(e,f);break}else if((s|0)==2){rc(e,f);break}else if((s|0)==1){tc(e,f);break}else{break}}else if((b|0)==1){if((s|0)==3){uc(e,f);break}else if((s|0)==4){if(g>0.0){wc(e,f,g);break}else{wc(e,f,2.0e3);break}}else if((s|0)==2){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);p=g+-2.0e3;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);break}}else{break}}else{break}}}while(0);if(q){if(r&d!=1950.0){xc(1950.0,d,e,f)}if(a&d!=2.0e3){yc(2.0e3,d,e,f)}}d=+h[f>>3];do{if(!(d>90.0)){if(d<-90.0){h[f>>3]=-180.0-d;g=+h[e>>3]+180.0;h[e>>3]=g;t=g;break}else{t=+h[e>>3];break}}else{h[f>>3]=180.0-d;g=+h[e>>3]+180.0;h[e>>3]=g;t=g}}while(0);if(t>360.0){h[e>>3]=t+-360.0;i=j;return}if(!(t<0.0)){i=j;return}h[e>>3]=t+360.0;i=j;return}function nc(b){b=b|0;var c=0,d=0,e=0,f=0.0;c=i;d=a[b]|0;a:do{if((((((!(d<<24>>24==106|d<<24>>24==74)?(yg(b,6688)|0)!=0:0)?(yg(b,6696)|0)!=0:0)?(yg(b,6704)|0)!=0:0)?(yg(b,6712)|0)!=0:0)?(Ag(b,6720,3)|0)!=0:0)?(Ag(b,6728,3)|0)!=0:0){if((((!(d<<24>>24==98|d<<24>>24==66)?(yg(b,6736)|0)!=0:0)?(yg(b,6744)|0)!=0:0)?(Ag(b,6752,3)|0)!=0:0)?(Ag(b,6760,3)|0)!=0:0){switch(d<<24>>24){case 105:case 73:{e=11;break a;break};case 108:case 76:{e=6;break a;break};case 101:case 69:{e=4;break a;break};case 97:case 65:{e=5;break a;break};case 110:case 78:{e=7;break a;break};case 103:case 71:{e=3;break a;break};default:{if((zg(b,6768,5)|0)==0){e=10;break a}if(d<<24>>24==112|d<<24>>24==80){e=9;break a}if((Gc(b)|0)==0){e=-1;break a}f=+ug(b);if(f>1980.0){e=1;break a}e=f>1900.0?2:-1;break a}}}else{e=2}}else{e=1}}while(0);i=c;return e|0}function oc(b){b=b|0;var c=0,d=0,e=0.0;c=i;d=a[b]|0;if(!(d<<24>>24==98|d<<24>>24==66|d<<24>>24==106|d<<24>>24==74)){if((Ag(b,6752,3)|0)!=0?(Ag(b,6760,3)|0)!=0:0){if((((Ag(b,6720,3)|0)!=0?(Ag(b,6728,3)|0)!=0:0)?(Ag(b,6704,4)|0)!=0:0)?(Ag(b,6712,4)|0)!=0:0){if((d+ -49<<24>>24&255)<2){e=+ug(b)}else{e=0.0}}else{e=2.0e3}}else{e=1950.0}}else{e=+ug(b+1|0)}i=c;return+e}function pc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0;g=i;i=i+48|0;j=g;k=+h[a>>3]*3.141592653589793/180.0;l=+h[b>>3]*3.141592653589793/180.0;m=+h[c>>3]*36.0e4;n=+h[d>>3]*36.0e4;o=+T(+k);p=+S(+k);k=+T(+l);q=+S(+l);l=p*q;r=o*q;if(m!=0.0|n!=0.0){s=-(m*r)-n*p*k;t=m*l-n*o*k;u=n*q}else{s=0.0;t=0.0;u=0.0}v=0;do{h[j+(v<<3)>>3]=+h[6776+(v*48|0)>>3]*l+0.0+ +h[6784+(v*48|0)>>3]*r+ +h[6792+(v*48|0)>>3]*k+ +h[6800+(v*48|0)>>3]*s+ +h[6808+(v*48|0)>>3]*t+ +h[6816+(v*48|0)>>3]*u;v=v+1|0}while((v|0)!=6);u=+h[j>>3];t=+h[j+8>>3];s=+h[j+16>>3];k=+Q(+(u*u+t*t+s*s));r=u*-162557.0e-11+t*-3.1919e-7+s*-1.3843e-7;l=u*r;q=u+k*-162557.0e-11-l;o=t*r;p=t+k*-3.1919e-7-o;w=s*r;r=s+k*-1.3843e-7-w;k=+Q(+(r*r+(q*q+p*p)));p=u*.001245+t*-.00158+s*-659.0e-6;q=u+k*-162557.0e-11-l;l=t+k*-3.1919e-7-o;o=s+k*-1.3843e-7-w;w=+h[j+24>>3]+k*.001245-p*q;s=k*-.00158+ +h[j+32>>3]-p*l;t=k*-659.0e-6+ +h[j+40>>3]-p*o;p=q*q+l*l;u=+Q(+p);if(!(q==0.0&l==0.0)){r=+Y(+l,+q);if(r<0.0){x=r+6.283185307179586}else{x=r}}else{x=0.0}r=+Y(+o,+u);if(u>1.0e-30){y=(t*p-o*(q*w+l*s))/(u*(o*o+p));z=(q*s-l*w)/p}else{y=n;z=m}m=+h[e>>3];if(!(m>1.0e-30)){A=x*180.0;B=A/3.141592653589793;h[a>>3]=B;C=r*180.0;D=C/3.141592653589793;h[b>>3]=D;E=z/36.0e4;h[c>>3]=E;F=y/36.0e4;h[d>>3]=F;i=g;return}h[f>>3]=(o*t+(q*w+l*s))/(k*m*21.095);h[e>>3]=+h[e>>3]/k;A=x*180.0;B=A/3.141592653589793;h[a>>3]=B;C=r*180.0;D=C/3.141592653589793;h[b>>3]=D;E=z/36.0e4;h[c>>3]=E;F=y/36.0e4;h[d>>3]=F;i=g;return}function qc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0;g=i;i=i+48|0;j=g;k=+h[a>>3]*3.141592653589793/180.0;l=+h[b>>3]*3.141592653589793/180.0;m=+h[c>>3]*36.0e4;n=+h[d>>3]*36.0e4;o=+T(+k);p=+S(+k);k=+T(+l);q=+S(+l);l=p*q;r=o*q;s=+h[f>>3];t=+h[e>>3];u=s*21.095*t;if(!(m!=0.0|n!=0.0)?!(s!=0.0&t!=0.0):0){v=-.001245;w=.00158;x=659.0e-6}else{v=-(m*r)-n*p*k+u*l+-.001245;w=m*l-n*o*k+u*r+.00158;x=n*q+u*k+659.0e-6}u=l*-162557.0e-11+r*-3.1919e-7+k*-1.3843e-7;q=u*l+(l+162557.0e-11);o=u*r+(r+3.1919e-7);p=u*k+(k+1.3843e-7);u=l*.001245+r*-.00158+k*-659.0e-6;s=v+u*l;l=w+u*r;r=x+u*k;y=0;do{h[j+(y<<3)>>3]=+h[7064+(y*48|0)>>3]*q+0.0+ +h[7072+(y*48|0)>>3]*o+ +h[7080+(y*48|0)>>3]*p+ +h[7088+(y*48|0)>>3]*s+ +h[7096+(y*48|0)>>3]*l+ +h[7104+(y*48|0)>>3]*r;y=y+1|0}while((y|0)!=6);r=+h[j>>3];l=+h[j+8>>3];s=+h[j+16>>3];p=+h[j+24>>3];o=+h[j+32>>3];q=+h[j+40>>3];k=r*r+l*l;u=+Q(+k);x=k+s*s;w=+Q(+x);v=r*p+l*o;z=v+s*q;if(!(r==0.0&l==0.0)){A=+Y(+l,+r);if(A<0.0){B=A+6.283185307179586}else{B=A}}else{B=0.0}A=+Y(+s,+u);if(u>1.0e-30){C=(k*q-s*v)/(x*u);D=(r*o-l*p)/k}else{C=n;D=m}if(!(t>1.0e-30)){E=B*180.0;F=E/3.141592653589793;h[a>>3]=F;G=A*180.0;H=G/3.141592653589793;h[b>>3]=H;I=D/36.0e4;h[c>>3]=I;J=C/36.0e4;h[d>>3]=J;i=g;return}h[f>>3]=z/(w*t*21.095);h[e>>3]=+h[e>>3]/w;E=B*180.0;F=E/3.141592653589793;h[a>>3]=F;G=A*180.0;H=G/3.141592653589793;h[b>>3]=H;I=D/36.0e4;h[c>>3]=I;J=C/36.0e4;h[d>>3]=J;i=g;return}function rc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0,x=0,y=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.066988739415+q*-.872755765852+l*-.483538914632;n=p*.492728466075+q*-.45034695802+l*.744584633283;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.867600811151+q*-.188374601723+l*.460199784784),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}n=g/15.0;d=~~n;g=(n- +(d|0))*60.0;b=~~g;if(j<0.0){u=45;v=-j}else{u=43;v=j}w=~~v;j=(v- +(w|0))*60.0;x=~~j;y=gg(32)|0;c[f>>2]=d;c[f+4>>2]=b;d=f+8|0;h[k>>3]=(g- +(b|0))*60.0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[f+16>>2]=u;c[f+20>>2]=w;c[f+24>>2]=x;w=f+28|0;h[k>>3]=(j- +(x|0))*60.0;c[w>>2]=c[k>>2];c[w+4>>2]=c[k+4>>2];Na(y|0,7648,f|0)|0;w=y+6|0;if((a[w]|0)==32){a[w]=48}w=y+20|0;if((a[w]|0)==32){a[w]=48}w=c[o>>2]|0;c[f>>2]=y;za(w|0,7360,f|0)|0;h[k>>3]=s;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];x=f+8|0;h[k>>3]=t;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];za(w|0,7392,f|0)|0;hg(y);i=e;return}function sc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0.0,x=0,y=0,z=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.066988739415+q*.492728466075+l*-.867600811151;n=p*-.872755765852+q*-.45034695802+l*-.188374601723;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.483538914632+q*.744584633283+l*.460199784784),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}d=c[o>>2]|0;h[k>>3]=g;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];b=f+8|0;h[k>>3]=j;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];za(d|0,7432,f|0)|0;j=s/15.0;b=~~j;s=(j- +(b|0))*60.0;u=~~s;if(t<0.0){v=45;w=-t}else{v=43;w=t}x=~~w;t=(w- +(x|0))*60.0;y=~~t;z=gg(32)|0;c[f>>2]=b;c[f+4>>2]=u;b=f+8|0;h[k>>3]=(s- +(u|0))*60.0;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];c[f+16>>2]=v;c[f+20>>2]=x;c[f+24>>2]=y;x=f+28|0;h[k>>3]=(t- +(y|0))*60.0;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];Na(z|0,7648,f|0)|0;x=z+6|0;if((a[x]|0)==32){a[x]=48}x=z+20|0;if((a[x]|0)==32){a[x]=48}c[f>>2]=z;za(d|0,7472,f|0)|0;hg(z);i=e;return}function tc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0,x=0,y=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.054875539726+q*-.87343710801+l*-.483834985808;n=p*.494109453312+q*-.444829589425+l*.74698225181;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.867666135858+q*-.198076386122+l*.455983795705),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}n=g/15.0;d=~~n;g=(n- +(d|0))*60.0;b=~~g;if(j<0.0){u=45;v=-j}else{u=43;v=j}w=~~v;j=(v- +(w|0))*60.0;x=~~j;y=gg(32)|0;c[f>>2]=d;c[f+4>>2]=b;d=f+8|0;h[k>>3]=(g- +(b|0))*60.0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[f+16>>2]=u;c[f+20>>2]=w;c[f+24>>2]=x;w=f+28|0;h[k>>3]=(j- +(x|0))*60.0;c[w>>2]=c[k>>2];c[w+4>>2]=c[k+4>>2];Na(y|0,7648,f|0)|0;w=y+6|0;if((a[w]|0)==32){a[w]=48}w=y+20|0;if((a[w]|0)==32){a[w]=48}w=c[o>>2]|0;c[f>>2]=y;za(w|0,7504,f|0)|0;h[k>>3]=s;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];x=f+8|0;h[k>>3]=t;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];za(w|0,7536,f|0)|0;hg(y);i=e;return}function uc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0.0,x=0,y=0,z=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.054875539726+q*.494109453312+l*-.867666135858;n=p*-.87343710801+q*-.444829589425+l*-.198076386122;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.483834985808+q*.74698225181+l*.455983795705),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}d=c[o>>2]|0;h[k>>3]=g;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];b=f+8|0;h[k>>3]=j;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];za(d|0,7576,f|0)|0;j=s/15.0;b=~~j;s=(j- +(b|0))*60.0;u=~~s;if(t<0.0){v=45;w=-t}else{v=43;w=t}x=~~w;t=(w- +(x|0))*60.0;y=~~t;z=gg(32)|0;c[f>>2]=b;c[f+4>>2]=u;b=f+8|0;h[k>>3]=(s- +(u|0))*60.0;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];c[f+16>>2]=v;c[f+20>>2]=x;c[f+24>>2]=y;x=f+28|0;h[k>>3]=(t- +(y|0))*60.0;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];Na(z|0,7648,f|0)|0;x=z+6|0;if((a[x]|0)==32){a[x]=48}x=z+20|0;if((a[x]|0)==32){a[x]=48}c[f>>2]=z;za(d|0,7616,f|0)|0;hg(z);i=e;return}function vc(a,b,c){a=a|0;b=b|0;c=+c;var d=0,e=0,f=0.0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0;d=i;i=i+80|0;e=d;if(c!=2.0e3){yc(2.0e3,c,a,b)}f=+h[a>>3]*3.141592653589793/180.0;g=+h[b>>3]*3.141592653589793/180.0;j=+S(+g);k=+S(+f)*j;l=j*+T(+f);f=+T(+g);g=(c+-2.0e3)*.01;zc(1,(g*(g*(g*.001813+-59.0e-5)+-46.815)+84381.448)*48481368110953.0e-19,0.0,0.0,e);g=+h[e>>3]*k+0.0+ +h[e+8>>3]*l+ +h[e+16>>3]*f;c=+h[e+24>>3]*k+0.0+ +h[e+32>>3]*l+ +h[e+40>>3]*f;j=+h[e+48>>3]*k+0.0+ +h[e+56>>3]*l+ +h[e+64>>3]*f;f=+Y(+c,+g);if(f<0.0){m=f+6.283185307179586}else{m=f}if(!(m>6.283185307179586)){n=m;o=g*g;p=c*c;q=o+p;r=+Q(+q);s=+Y(+j,+r);t=n*180.0;u=t/3.141592653589793;h[a>>3]=u;v=s*180.0;w=v/3.141592653589793;h[b>>3]=w;i=d;return}n=m+-6.283185307179586;o=g*g;p=c*c;q=o+p;r=+Q(+q);s=+Y(+j,+r);t=n*180.0;u=t/3.141592653589793;h[a>>3]=u;v=s*180.0;w=v/3.141592653589793;h[b>>3]=w;i=d;return}function wc(a,b,c){a=a|0;b=b|0;c=+c;var d=0,e=0,f=0.0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0;d=i;i=i+80|0;e=d;f=+h[a>>3]*3.141592653589793/180.0;g=+h[b>>3]*3.141592653589793/180.0;j=+S(+g);k=+S(+f)*j;l=j*+T(+f);f=+T(+g);g=(c+-2.0e3)*.01;zc(1,(g*(g*(g*.001813+-59.0e-5)+-46.815)+84381.448)*48481368110953.0e-19,0.0,0.0,e);g=+h[e>>3]*k+0.0+ +h[e+24>>3]*l+ +h[e+48>>3]*f;j=+h[e+8>>3]*k+0.0+ +h[e+32>>3]*l+ +h[e+56>>3]*f;m=+Y(+j,+g);if(m<0.0){n=m+6.283185307179586}else{n=m}if(n>6.283185307179586){o=n+-6.283185307179586}else{o=n}n=+Y(+(+h[e+16>>3]*k+0.0+ +h[e+40>>3]*l+ +h[e+64>>3]*f),+(+Q(+(g*g+j*j))));h[a>>3]=o*180.0/3.141592653589793;h[b>>3]=n*180.0/3.141592653589793;if(!(c!=2.0e3)){i=d;return}yc(c,2.0e3,a,b);i=d;return}function xc(a,b,c,d){a=+a;b=+b;c=c|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;e=i;i=i+80|0;f=e;g=+h[c>>3]*3.141592653589793/180.0;j=+h[d>>3]*3.141592653589793/180.0;k=(a+-1850.0)/100.0;l=(b-a)/100.0;a=l*48481368110953.0e-19;b=k*(k*59.0e-6+1.3972)+2303.5548;m=k*365.0e-6;zc(323,-(a*(b+l*(.30242-k*269.0e-6+l*.017996))),a*(k*(-.85294-m)+2005.1125+l*(-.42647-m-l*.041802)),-(a*(b+l*(k*387.0e-6+1.09478+l*.018324))),f);l=+S(+j);k=+S(+g)*l;b=l*+T(+g);g=+T(+j);j=+h[f>>3]*k+0.0+ +h[f+8>>3]*b+ +h[f+16>>3]*g;l=+h[f+24>>3]*k+0.0+ +h[f+32>>3]*b+ +h[f+40>>3]*g;a=+h[f+48>>3]*k+0.0+ +h[f+56>>3]*b+ +h[f+64>>3]*g;g=+Y(+l,+j);if(g<0.0){n=g+6.283185307179586}else{n=g}if(!(n>6.283185307179586)){o=n;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}o=n+-6.283185307179586;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}function yc(a,b,c,d){a=+a;b=+b;c=c|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;e=i;i=i+80|0;f=e;g=+h[c>>3]*3.141592653589793/180.0;j=+h[d>>3]*3.141592653589793/180.0;k=(a+-2.0e3)/100.0;l=(b-a)/100.0;a=l*48481368110953.0e-19;b=k*(1.39656-k*139.0e-6)+2306.2181;m=k*217.0e-6;zc(323,-(a*(b+l*(.30188-k*344.0e-6+l*.017998))),a*(k*(-.8533-m)+2004.3109+l*(-.42665-m-l*.041833)),-(a*(b+l*(k*66.0e-6+1.09468+l*.018203))),f);l=+S(+j);k=+S(+g)*l;b=l*+T(+g);g=+T(+j);j=k*+h[f>>3]+0.0+b*+h[f+8>>3]+g*+h[f+16>>3];l=k*+h[f+24>>3]+0.0+b*+h[f+32>>3]+g*+h[f+40>>3];a=k*+h[f+48>>3]+0.0+b*+h[f+56>>3]+g*+h[f+64>>3];g=+Y(+l,+j);if(g<0.0){n=g+6.283185307179586}else{n=g}if(!(n>6.283185307179586)){o=n;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}o=n+-6.283185307179586;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}function zc(a,b,d,e,f){a=a|0;b=+b;d=+d;e=+e;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0,B=0.0,C=0.0,D=0,E=0.0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0,L=0.0,M=0,N=0.0;g=i;i=i+192|0;j=g+144|0;k=g+72|0;l=g;m=g+168|0;n=f+8|0;h[f>>3]=1.0;o=f+16|0;h[n>>3]=0.0;h[o>>3]=0.0;p=f+24|0;h[p>>3]=0.0;h[f+32>>3]=1.0;h[f+40>>3]=0.0;h[f+48>>3]=0.0;h[f+56>>3]=0.0;h[f+64>>3]=1.0;q=(a|0)/100|0;c[m>>2]=q;if((a|0)>99){r=(aa(q,-100)|0)+a|0;s=1}else{r=a;s=0}a=(r|0)/10|0;c[m+(s<<2)>>2]=a;if((r|0)>9){t=(aa(a,-10)|0)+r|0;u=s+1|0}else{t=r;u=s}c[m+(u<<2)>>2]=t;s=((t|0)>0)+u|0;h[j>>3]=b;h[j+8>>3]=d;h[j+16>>3]=e;if((s|0)<=0){i=g;return}u=l+32|0;t=l+40|0;r=l+56|0;a=l+64|0;q=l+16|0;v=l+48|0;w=l+8|0;x=l+24|0;y=k+8|0;e=b;b=1.0;d=0.0;z=1.0;A=0;while(1){h[l>>3]=1.0;h[l+8>>3]=0.0;h[l+16>>3]=0.0;h[l+24>>3]=0.0;h[l+32>>3]=1.0;h[l+40>>3]=0.0;h[l+48>>3]=0.0;h[l+56>>3]=0.0;h[l+64>>3]=1.0;B=+T(+e);C=+S(+e);D=c[m+(A<<2)>>2]|0;do{if((D|0)!=1){h[l>>3]=C;if((D|0)==2){h[q>>3]=-B;h[v>>3]=B;h[a>>3]=C;break}else{h[w>>3]=B;h[x>>3]=-B;h[u>>3]=C;break}}else{h[u>>3]=C;h[t>>3]=B;h[r>>3]=-B;h[a>>3]=C}}while(0);C=+h[p>>3];B=+h[n>>3];E=+h[f+32>>3];F=+h[f+56>>3];G=+h[f+16>>3];H=+h[f+40>>3];D=0;do{I=D*3|0;J=+h[l+(I<<3)>>3];K=I+1|0;L=+h[l+(K<<3)>>3];M=I+2|0;N=+h[l+(M<<3)>>3];h[k+(I<<3)>>3]=J*b+0.0+L*C+N*d;h[k+(K<<3)>>3]=J*B+0.0+L*E+N*F;h[k+(M<<3)>>3]=J*G+0.0+L*H+N*z;D=D+1|0}while((D|0)!=3);H=+h[k>>3];h[f>>3]=H;h[n>>3]=+h[y>>3];h[o>>3]=+h[k+16>>3];h[f+24>>3]=+h[k+24>>3];h[f+32>>3]=+h[k+32>>3];h[f+40>>3]=+h[k+40>>3];G=+h[k+48>>3];h[f+48>>3]=G;h[f+56>>3]=+h[k+56>>3];F=+h[k+64>>3];h[f+64>>3]=F;D=A+1|0;if((D|0)==(s|0)){break}e=+h[j+(D<<3)>>3];b=H;d=G;z=F;A=D}i=g;return}function Ac(a,b,c,d){a=+a;b=+b;c=+c;d=d|0;var e=0.0;e=a*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+a);h[d>>3]=+S(+e)*c*b;h[d+8>>3]=b*+T(+e)*c;h[d+16>>3]=+T(+a)*c;return}function Bc(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;if((b|0)>0){e=b}else{c[1922]=0;e=(Cc(a,7696)|0)+80-a|0}c[1922]=e;i=d;return e|0}function Cc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;e=i;f=c[1922]|0;g=(f|0)==0?256e3:f;if((g|0)>0){h=0}else{j=0;i=e;return j|0}while(1){f=h+1|0;if((a[b+h|0]|0)<1){k=h;break}if((f|0)<(g|0)){h=f}else{k=f;break}}h=b+k|0;g=h;if((k|0)<=0){j=0;i=e;return j|0}k=b;f=b;a:while(1){b=Rc(f,d,g-f|0)|0;if((b|0)==0){j=0;l=17;break}m=(b-k|0)%80|0;n=a[b+(Dg(d|0)|0)|0]|0;do{if((m|0)<=7){if(n<<24>>24>32?!(n<<24>>24==61|n<<24>>24==127):0){o=b+1|0;break}p=0-m|0;q=b+p|0;if((p|0)<0){p=b+1|0;r=f;s=q;while(1){t=(a[s]|0)==32?r:p;u=s+1|0;if(u>>>0>>0){r=t;s=u}else{v=t;break}}}else{v=f}if(b>>>0>>0){o=v}else{j=q;l=17;break a}}else{o=b+1|0}}while(0);if(o>>>0>>0){f=o}else{j=0;l=17;break}}if((l|0)==17){i=e;return j|0}return 0}function Dc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;i=i+16|0;g=f;if((a[d]|0)<64){h=Ec(b,c,e)|0;i=f;return h|0}else{Lg(g|0,c|0)|0;j=Dg(c|0)|0;a[g+j|0]=a[d]|0;a[g+(j+1)|0]=0;h=Ec(b,g,e)|0;i=f;return h|0}return 0}function Ec(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0.0,k=0.0;f=i;g=Fc(b,d)|0;if((g|0)==0){h=0;i=f;return h|0}d=(a[g]|0)==35?g+1|0:g;if((Dg(d|0)|0)>81){Hg(7704,d|0,81)|0;a[7785|0]=0}else{Lg(7704,d|0)|0}if((Gc(7704)|0)==2){d=$f(7704,68)|0;if((d|0)!=0){a[d]=101}d=$f(7704,100)|0;if((d|0)!=0){a[d]=101}d=$f(7704,69)|0;if((d|0)!=0){a[d]=101}}j=+ug(7704);k=j+.001;if(k>2147483647.0){c[e>>2]=2147483647;h=1;i=f;return h|0}if(j>=0.0){c[e>>2]=~~k;h=1;i=f;return h|0}k=j+-.001;if(k<-2147483648.0){c[e>>2]=-2147483648;h=1;i=f;return h|0}else{c[e>>2]=~~k;h=1;i=f;return h|0}return 0}function Fc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;e=i;i=i+208|0;f=e+194|0;g=e+8|0;h=e+2|0;j=e+4|0;k=e+196|0;l=e;m=e+6|0;n=e+112|0;o=e+12|0;a[g]=39;a[g+1|0]=0;a[h]=34;a[h+1|0]=0;a[j]=91;a[j+1|0]=0;a[m]=44;a[m+1|0]=0;a[k]=93;a[k+1|0]=0;a[l]=47;a[l+1|0]=0;Hg(n|0,d|0,80)|0;d=Dg(n|0)|0;p=Dg(j|0)|0;a:do{if((p|0)!=0){if((d|0)!=0?(q=p+ -1|0,r=a[j+q|0]|0,s=d+1-p|0,t=n+s|0,(s|0)>0):0){s=(p|0)==1;u=(p|0)<3;v=n;do{b:do{if((a[v]|0)==91){if(s){w=v;x=23;break a}if((a[v+q|0]|0)==r<<24>>24){if(u){w=v;x=23;break a}else{y=1}while(1){z=y+1|0;if((a[v+y|0]|0)!=(a[j+y|0]|0)){break b}if((z|0)<(p|0)){y=z}else{w=v;x=23;break a}}}}}while(0);v=v+1|0}while(v>>>0>>0)}t=Dg(n|0)|0;v=Dg(m|0)|0;if((v|0)!=0){if((t|0)!=0?(u=v+ -1|0,r=a[m+u|0]|0,q=t+1-v|0,t=n+q|0,(q|0)>0):0){q=(v|0)==1;s=(v|0)<3;z=n;while(1){c:do{if((a[z]|0)==44){if(q){w=z;x=23;break a}if((a[z+u|0]|0)==r<<24>>24){if(s){w=z;x=23;break a}else{A=1}while(1){B=A+1|0;if((a[z+A|0]|0)!=(a[m+A|0]|0)){break c}if((B|0)<(v|0)){A=B}else{w=z;x=23;break a}}}}}while(0);B=z+1|0;if(B>>>0>>0){z=B}else{C=0;break}}}else{C=0}}else{w=n;x=23}}else{w=n;x=23}}while(0);if((x|0)==23){a[w]=0;C=w+1|0}w=Cc(b,n)|0;if((w|0)==0){D=0;i=e;return D|0}n=o+0|0;b=n+100|0;do{a[n]=0;n=n+1|0}while((n|0)<(b|0));Hg(o|0,w|0,80)|0;w=Dg(o|0)|0;n=Dg(g|0)|0;d:do{if((n|0)!=0){if((w|0)!=0?(b=a[g]|0,A=n+ -1|0,m=a[g+A|0]|0,y=w+1-n|0,p=o+y|0,(y|0)>0):0){y=(n|0)==1;j=(n|0)<3;d=o;while(1){e:do{if((a[d]|0)==b<<24>>24){if(y){E=d;break d}if((a[d+A|0]|0)==m<<24>>24){if(j){E=d;break d}else{F=1}while(1){z=F+1|0;if((a[d+F|0]|0)!=(a[g+F|0]|0)){break e}if((z|0)<(n|0)){F=z}else{E=d;break d}}}}}while(0);z=d+1|0;if(z>>>0

>>0){d=z}else{E=0;break}}}else{E=0}}else{E=o}}while(0);F=Dg(o|0)|0;n=Dg(l|0)|0;f:do{if((n|0)!=0){if((F|0)!=0?(w=a[l]|0,d=n+ -1|0,p=a[l+d|0]|0,j=F+1-n|0,m=o+j|0,(j|0)>0):0){j=(n|0)==1;A=(n|0)<3;y=o;while(1){g:do{if((a[y]|0)==w<<24>>24){if(j){G=y;break f}if((a[y+d|0]|0)==p<<24>>24){if(A){G=y;break f}else{H=1}while(1){b=H+1|0;if((a[y+H|0]|0)!=(a[l+H|0]|0)){break g}if((b|0)<(n|0)){H=b}else{G=y;break f}}}}}while(0);b=y+1|0;if(b>>>0>>0){y=b}else{G=0;break}}}else{G=0}}else{G=o}}while(0);h:do{if((E|0)==0){H=Dg(o|0)|0;n=Dg(h|0)|0;i:do{if((n|0)==0){I=o}else{if((H|0)==0){x=116;break h}l=a[h]|0;F=n+ -1|0;y=a[h+F|0]|0;m=H+1-n|0;A=o+m|0;if((m|0)<=0){x=116;break h}m=(n|0)==1;p=(n|0)<3;d=o;while(1){j:do{if((a[d]|0)==l<<24>>24){if(m){I=d;break i}if((a[d+F|0]|0)==y<<24>>24){if(p){I=d;break i}else{J=1}while(1){j=J+1|0;if((a[d+J|0]|0)!=(a[h+J|0]|0)){break j}if((j|0)<(n|0)){J=j}else{I=d;break i}}}}}while(0);j=d+1|0;if(j>>>0>>0){d=j}else{x=116;break h}}}}while(0);if((G|0)!=0&I>>>0>>0){n=I+1|0;H=Dg(n|0)|0;d=Dg(h|0)|0;if((d|0)==0){K=I;L=n;x=115;break}if((H|0)!=0?(A=a[h]|0,p=d+ -1|0,y=a[h+p|0]|0,F=H+1-d|0,H=I+(F+1)|0,(F|0)>0):0){F=(d|0)==1;m=(d|0)<3;l=n;while(1){k:do{if((a[l]|0)==A<<24>>24){if(F){K=I;L=l;x=115;break h}if((a[l+p|0]|0)==y<<24>>24){if(m){K=I;L=l;x=115;break h}else{M=1}while(1){n=M+1|0;if((a[l+M|0]|0)!=(a[h+M|0]|0)){break k}if((n|0)<(d|0)){M=n}else{K=I;L=l;x=115;break h}}}}}while(0);n=l+1|0;if(n>>>0>>0){l=n}else{N=G;break}}}else{N=G}while(1){l=N+ -1|0;if((a[l]|0)==32){N=l}else{K=I;L=N;x=115;break h}}}if((G|0)==0){l=I+1|0;H=Dg(l|0)|0;d=Dg(h|0)|0;if((d|0)==0){K=I;L=l;x=115}else{if((H|0)!=0?(m=a[h]|0,y=d+ -1|0,p=a[h+y|0]|0,F=H+1-d|0,H=I+(F+1)|0,(F|0)>0):0){F=(d|0)==1;A=(d|0)<3;n=l;do{l:do{if((a[n]|0)==m<<24>>24){if(F){K=I;L=n;x=115;break h}if((a[n+y|0]|0)==p<<24>>24){if(A){K=I;L=n;x=115;break h}else{O=1}while(1){l=O+1|0;if((a[n+O|0]|0)!=(a[h+O|0]|0)){break l}if((l|0)<(d|0)){O=l}else{K=I;L=n;x=115;break h}}}}}while(0);n=n+1|0}while(n>>>0>>0)}H=o+79|0;while(1){if((a[H]|0)==32){H=H+ -1|0}else{break}}K=I;L=H+1|0;x=115}}else{x=116}}else{if((G|0)!=0&E>>>0>>0){n=E+1|0;d=Dg(n|0)|0;A=Dg(g|0)|0;if((A|0)==0){K=E;L=n;x=115;break}if((d|0)!=0?(p=a[g]|0,y=A+ -1|0,F=a[g+y|0]|0,m=d+1-A|0,d=E+(m+1)|0,(m|0)>0):0){m=(A|0)==1;l=(A|0)<3;j=n;while(1){m:do{if((a[j]|0)==p<<24>>24){if(m){K=E;L=j;x=115;break h}if((a[j+y|0]|0)==F<<24>>24){if(l){K=E;L=j;x=115;break h}else{P=1}while(1){n=P+1|0;if((a[j+P|0]|0)!=(a[g+P|0]|0)){break m}if((n|0)<(A|0)){P=n}else{K=E;L=j;x=115;break h}}}}}while(0);n=j+1|0;if(n>>>0>>0){j=n}else{Q=G;break}}}else{Q=G}while(1){j=Q+ -1|0;if((a[j]|0)==32){Q=j}else{K=E;L=Q;x=115;break h}}}if((G|0)==0){j=E+1|0;d=Dg(j|0)|0;A=Dg(g|0)|0;if((A|0)==0){K=E;L=j;x=115}else{if((d|0)!=0?(l=a[g]|0,F=A+ -1|0,y=a[g+F|0]|0,m=d+1-A|0,d=E+(m+1)|0,(m|0)>0):0){m=(A|0)==1;p=(A|0)<3;H=j;do{n:do{if((a[H]|0)==l<<24>>24){if(m){K=E;L=H;x=115;break h}if((a[H+F|0]|0)==y<<24>>24){if(p){K=E;L=H;x=115;break h}else{R=1}while(1){j=R+1|0;if((a[H+R|0]|0)!=(a[g+R|0]|0)){break n}if((j|0)<(A|0)){R=j}else{K=E;L=H;x=115;break h}}}}}while(0);H=H+1|0}while(H>>>0>>0)}d=o+79|0;while(1){if((a[d]|0)==32){d=d+ -1|0}else{break}}K=E;L=d+1|0;x=115}}else{x=116}}}while(0);if((x|0)==115){S=K+1|0;T=L}else if((x|0)==116){L=Dg(o|0)|0;o:do{if((L|0)!=0?(K=o+L|0,(L|0)>0):0){E=o;while(1){if((a[E]|0)==61){U=E;break o}R=E+1|0;if(R>>>0>>0){E=R}else{U=0;break}}}else{U=0}}while(0);L=(U|0)==0?o+9|0:U+1|0;U=Dg(o|0)|0;p:do{if((U|0)!=0?(E=o+U|0,(U|0)>0):0){K=o;while(1){if((a[K]|0)==47){V=K;break p}d=K+1|0;if(d>>>0>>0){K=d}else{V=0;break}}}else{V=0}}while(0);S=L;T=(V|0)==0?o+79|0:V}if((c[1968]|0)==0){V=S;while(1){if((a[V]|0)==32&V>>>0>>0){V=V+1|0}else{W=V;break}}}else{W=S}a[T]=0;q:do{if((c[1968]|0)==0){S=T;while(1){V=S+ -1|0;o=a[V]|0;if(!(o<<24>>24==13|o<<24>>24==32)){break q}if(!(V>>>0>W>>>0)){break q}a[V]=0;S=V}}}while(0);T=(yg(W,7960)|0)==0;S=T?W+1|0:W;Lg(7880,S|0)|0;if((C|0)==0){D=7880;i=e;return D|0}W=Dg(C|0)|0;T=Dg(k|0)|0;r:do{if((T|0)!=0){if((W|0)!=0?(V=a[k]|0,o=T+ -1|0,L=a[k+o|0]|0,U=W+1-T|0,K=C+U|0,(U|0)>0):0){U=(T|0)==1;E=(T|0)<3;d=C;s:while(1){t:do{if((a[d]|0)==V<<24>>24){if(U){break s}if((a[d+o|0]|0)==L<<24>>24){if(E){break s}else{X=1}while(1){R=X+1|0;if((a[d+X|0]|0)!=(a[k+X|0]|0)){break t}if((R|0)<(T|0)){X=R}else{break s}}}}}while(0);R=d+1|0;if(R>>>0>>0){d=R}else{break r}}if((d|0)!=0){Y=d;x=144}}}else{Y=C;x=144}}while(0);if((x|0)==144){a[Y]=0}if((Gc(C)|0)==0){Y=Dg(C|0)|0;if((Y|0)>0){x=0;do{X=C+x|0;T=a[X]|0;if((T+ -65<<24>>24&255)<26){a[X]=(T&255)+32}x=x+1|0}while((x|0)!=(Y|0))}Y=_c(7880,C)|0;if((Y|0)==0){D=0;i=e;return D|0}Lg(7880,Y|0)|0;D=7880;i=e;return D|0}Y=vg(C)|0;a[f]=32;a[f+1|0]=0;if((Y|0)>0){C=1;x=S;while(1){Z=fg(x,f)|0;if((C|0)==(Y|0)){break}else{C=C+1|0;x=0}}if((Z|0)==0){D=0;i=e;return D|0}Lg(7880,Z|0)|0;D=7880;i=e;return D|0}if((Y|0)>=0){D=7880;i=e;return D|0}Z=0-Y|0;u:do{if((Z|0)<=1){if((S|0)==0){D=0;i=e;return D|0}else{_=S}}else{Y=1;x=S;while(1){C=$f(x,32)|0;if((C|0)==0){D=0;break}f=C+1|0;C=Y+1|0;if((C|0)<(Z|0)){Y=C;x=f}else{_=f;break u}}i=e;return D|0}}while(0);Lg(7880,_|0)|0;D=7880;i=e;return D|0}function Gc(b){b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;c=i;a:do{if((b|0)!=0?(d=a[b]|0,!(d<<24>>24==101|d<<24>>24==69|d<<24>>24==100|d<<24>>24==68)):0){e=Dg(b|0)|0;while(1){f=e+ -1|0;if((a[b+f|0]|0)==32){e=f}else{break}}if((e|0)>0){f=d;g=0;h=1;j=0;k=0;while(1){if(f<<24>>24==32){if((k|0)==0){l=g;m=h;n=0}else{o=0;break a}}else if(!(f<<24>>24==10)){b:do{if(!((f+ -48<<24>>24&255)<10)){switch(f<<24>>24){case 45:case 43:{break};case 101:case 100:case 69:case 68:case 58:case 46:{p=13;break b;break};default:{o=0;break a}}q=a[b+(j+1)|0]|0;if(q<<24>>24==43|q<<24>>24==45){o=0;break a}if((j|0)>0){switch(a[b+(j+ -1)|0]|0){case 32:case 58:case 101:case 69:case 100:case 68:{r=g;s=k;break};default:{o=0;break a}}}else{r=g;s=k}}else{p=13}}while(0);do{if((p|0)==13){p=0;if((f+ -47<<24>>24&255)<11){r=g;s=k+1|0;break}else{r=(f<<24>>24==58)+g|0;s=k;break}}}while(0);if(f<<24>>24==101|f<<24>>24==100|f<<24>>24==46){l=r;m=2;n=s}else{l=r;m=h;n=s}}else{t=g;u=h;v=k;break}q=j+1|0;if((q|0)>=(e|0)){t=l;u=m;v=n;break}f=a[b+q|0]|0;g=l;h=m;j=q;k=n}if((v|0)>0){o=(t|0)==0?u:3}else{o=0}}else{o=0}}else{o=0}}while(0);i=c;return o|0}function Hc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,j=0.0,k=0,l=0,m=0.0;e=i;f=Fc(b,c)|0;if((f|0)==0){g=0;i=e;return g|0}j=+Jc(f);c=Dg(f|0)|0;a:do{if((c|0)!=0?(b=f+c|0,(c|0)>0):0){k=f;while(1){if((a[k]|0)==58){break}l=k+1|0;if(l>>>0>>0){k=l}else{m=j;break a}}if((k|0)!=0){m=j*15.0}else{m=j}}else{m=j}}while(0);h[d>>3]=m;g=1;i=e;return g|0}function Ic(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;d=i;e=Fc(a,b)|0;if((e|0)==0){f=0}else{h[c>>3]=+Jc(e);f=1}i=d;return f|0}function Jc(b){b=b|0;var c=0,d=0.0,e=0,f=0,g=0,h=0,j=0.0,k=0,l=0.0,m=0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0,w=0.0,x=0.0;c=i;if((b|0)==0){d=0.0;i=c;return+d}e=a[b]|0;if(e<<24>>24==0){d=0.0;i=c;return+d}else{f=e;g=b}while(1){if(f<<24>>24==43){h=5;break}else if(f<<24>>24==45){j=-1.0;h=6;break}else if(!(f<<24>>24==32)){h=7;break}b=g+1|0;f=a[b]|0;g=b}if((h|0)==5){j=1.0;h=6}else if((h|0)==7){f=Dg(g|0)|0;if((g|0)==0){k=1;l=1.0;m=0}else{n=f;o=1.0;p=g;h=8}}if((h|0)==6){f=g+1|0;n=Dg(f|0)|0;o=j;p=f;h=8}a:do{if((h|0)==8){if((n|0)!=0?(f=p+n|0,(n|0)>0):0){g=p;while(1){if((a[g]|0)==44){break}b=g+1|0;if(b>>>0>>0){g=b}else{k=0;l=o;m=p;break a}}if((g|0)!=0){a[g]=32;k=0;l=o;m=p}else{k=0;l=o;m=p}}else{k=0;l=o;m=p}}}while(0);p=Dg(m|0)|0;while(1){n=p+ -1|0;if((a[m+n|0]|0)==32){p=n}else{break}}n=Dg(m|0)|0;b:do{if(!k){c:do{if((n|0)!=0?(f=m+n|0,(n|0)>0):0){b=m;while(1){if((a[b]|0)==58){break}e=b+1|0;if(e>>>0>>0){b=e}else{h=22;break c}}if((b|0)!=0){q=b}else{h=22}}else{h=22}}while(0);if((h|0)==22){if((p|0)==0){break}g=m+p|0;if((p|0)>0){r=m}else{break}while(1){if((a[r]|0)==32){break}f=r+1|0;if(f>>>0>>0){r=f}else{break b}}if((r|0)==0){break}else{q=r}}a[q]=0;o=+(vg(m)|0);a[q]=58;g=q+1|0;f=Dg(g|0)|0;d:do{if((f|0)!=0?(e=q+(f+1)|0,(f|0)>0):0){s=g;while(1){if((a[s]|0)==58){t=s;h=35;break d}u=s+1|0;if(u>>>0>>0){s=u}else{h=31;break}}}else{h=31}}while(0);e:do{if((h|0)==31){f=Dg(g|0)|0;if((f|0)!=0?(s=q+(f+1)|0,(f|0)>0):0){f=g;do{if((a[f]|0)==32){t=f;h=35;break e}f=f+1|0}while(f>>>0>>0)}s=Dg(g|0)|0;f:do{if((s|0)!=0?(f=q+(s+1)|0,(s|0)>0):0){e=g;while(1){if((a[e]|0)==46){break}b=e+1|0;if(b>>>0>>0){e=b}else{v=0.0;break f}}v=+ug(g)}else{v=0.0}}while(0);if((a[g]|0)==0){w=v;x=0.0}else{w=+(vg(g)|0);x=0.0}}}while(0);if((h|0)==35){a[t]=0;j=+(vg(g)|0);a[t]=58;w=j;x=+ug(t+1|0)}d=l*(o+w/60.0+x/3600.0);i=c;return+d}}while(0);if((Gc(m)|0)!=2){d=l*+(vg(m)|0);i=c;return+d}t=$f(m,68)|0;if((t|0)!=0){a[t]=101}t=$f(m,100)|0;if((t|0)!=0){a[t]=101}t=$f(m,69)|0;if((t|0)!=0){a[t]=101}d=l*+ug(m);i=c;return+d}function Kc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;i=i+16|0;g=f;if((a[d]|0)<64){h=Lc(b,c,e)|0;i=f;return h|0}else{Lg(g|0,c|0)|0;j=Dg(c|0)|0;a[g+j|0]=a[d]|0;a[g+(j+1)|0]=0;h=Lc(b,g,e)|0;i=f;return h|0}return 0}function Lc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;e=i;f=Fc(b,c)|0;if((f|0)==0){g=0;i=e;return g|0}c=(a[f]|0)==35?f+1|0:f;if((Dg(c|0)|0)>81){Hg(7704,c|0,81)|0;a[7785|0]=0}else{Lg(7704,c|0)|0}if((Gc(7704)|0)==2){c=$f(7704,68)|0;if((c|0)!=0){a[c]=101}c=$f(7704,100)|0;if((c|0)!=0){a[c]=101}c=$f(7704,69)|0;if((c|0)!=0){a[c]=101}}h[d>>3]=+ug(7704);g=1;i=e;return g|0}function Mc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0;f=i;g=Fc(b,d)|0;if((g|0)==0){j=0;i=f;return j|0}d=$f(g,47)|0;b=$f(g,45)|0;if(d>>>0>g>>>0){a[d]=0;k=~~+ug(g);a[d]=47;l=d+1|0;d=$f(l,47)|0;if((d|0)==0){m=$f(l,45)|0}else{m=d}if(!(m>>>0>g>>>0)){j=0;i=f;return j|0}a[m]=0;d=~~+ug(l);a[m]=47;l=~~+ug(m+1|0);m=(k|0)>31;n=m?k:l;o=m?l:k;if(n>>>0<50){p=n+2e3|0}else{p=(n|0)<100?n+1900|0:n}n=((p|0)%100|0|0)!=0|((p|0)%400|0|0)==0?(p&3|0)==0?29:28:28;c[7796>>2]=n;k=d+ -1|0;d=c[7792+(k<<2)>>2]|0;if((o|0)>(d|0)){q=d}else{q=(o|0)<1?1:o}r=(n|0)==28?365.0:366.0;n=q+ -1|0;if((k|0)>0){q=0;o=n;while(1){d=(c[7792+(q<<2)>>2]|0)+o|0;l=q+1|0;if((l|0)==(k|0)){s=d;break}else{q=l;o=d}}}else{s=n}h[e>>3]=+(p|0)+ +(s|0)/r;j=1;i=f;return j|0}if(!(b>>>0>g>>>0)){j=0;i=f;return j|0}a[b]=0;s=~~+ug(g);a[b]=45;p=b+1|0;b=$f(p,45)|0;do{if(b>>>0>g>>>0){a[b]=0;n=~~+ug(p);a[b]=45;o=b+1|0;q=$f(o,84)|0;if(q>>>0>g>>>0){a[q]=0;k=~~+ug(o);a[q]=84;t=k;u=n;v=q;break}else{t=~~+ug(o);u=n;v=q;break}}else{t=1;u=1;v=0}}while(0);b=(s|0)<32;p=b?t+1900|0:s;q=b?s:t;t=((p|0)%100|0|0)!=0|((p|0)%400|0|0)==0?(p&3|0)==0?29:28:28;c[7796>>2]=t;s=u+ -1|0;u=c[7792+(s<<2)>>2]|0;if((q|0)>(u|0)){w=u}else{w=(q|0)<1?1:q}r=(t|0)==28?365.0:366.0;t=w+ -1|0;if((s|0)>0){w=0;q=t;while(1){u=(c[7792+(w<<2)>>2]|0)+q|0;b=w+1|0;if((b|0)==(s|0)){x=u;break}else{w=b;q=u}}}else{x=t}h[e>>3]=+(p|0)+ +(x|0)/r;if(!(v>>>0>g>>>0)){j=1;i=f;return j|0}x=v+1|0;v=$f(x,58)|0;do{if(v>>>0>g>>>0){a[v]=0;p=~~+ug(x);a[v]=58;t=v+1|0;q=$f(t,58)|0;if(q>>>0>g>>>0){a[q]=0;w=~~+ug(t);a[q]=58;y=p;z=w;A=+ug(q+1|0);break}else{y=p;z=~~+ug(t);A=0.0;break}}else{y=0;z=0;A=0.0}}while(0);h[e>>3]=+h[e>>3]+(A+(+(y|0)*3600.0+ +(z|0)*60.0))/86400.0/r;j=1;i=f;return j|0}function Nc(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+32|0;h=g+8|0;j=g+16|0;k=g;c[h>>2]=d;Na(j|0,7840,h|0)|0;do{if((Cc(b,j)|0)==0){c[h>>2]=d;Na(j|0,7856,h|0)|0;if((Cc(b,j)|0)!=0){l=k;c[l>>2]=627012389;c[l+4>>2]=6566448;break}c[h>>2]=d;Na(j|0,7864,h|0)|0;if((Cc(b,j)|0)!=0){l=k;c[l>>2]=627012389;c[l+4>>2]=6566704;break}if((Cc(b,j)|0)==0){m=0;i=g;return m|0}else{l=k;c[l>>2]=627012389;c[l+4>>2]=6566704;break}}else{a[k+0|0]=a[7848|0]|0;a[k+1|0]=a[7849|0]|0;a[k+2|0]=a[7850|0]|0;a[k+3|0]=a[7851|0]|0;a[k+4|0]=a[7852|0]|0;a[k+5|0]=a[7853|0]|0}}while(0);c[1968]=1;l=1;n=e;e=f;while(1){c[h>>2]=d;c[h+4>>2]=l;Na(j|0,k|0,h|0)|0;o=Fc(b,j)|0;if((o|0)==0){p=l;break}q=Dg(o|0)|0;if((q|0)>=(n|0)){r=13;break}Lg(e|0,o|0)|0;s=l+1|0;if((s|0)<500){l=s;n=n-q|0;e=e+q|0}else{p=s;break}}do{if((r|0)==13){if((n|0)>1){Hg(e|0,o|0,n+ -1|0)|0;a[e+n|0]=0;p=l;break}else{a[f]=a[o]|0;p=l;break}}}while(0);c[1968]=0;m=(p|0)>1|0;i=g;return m|0}function Oc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;g=i;i=i+16|0;h=g;do{if((a[d]|0)<64){j=Fc(b,c)|0;if((j|0)!=0){if((Dg(j|0)|0)<(e|0)){Lg(f|0,j|0)|0;k=1;break}if((e|0)>1){Hg(f|0,j|0,e+ -1|0)|0;k=1;break}else{a[f]=a[j]|0;k=1;break}}else{k=0}}else{Lg(h|0,c|0)|0;j=Dg(c|0)|0;a[h+j|0]=a[d]|0;a[h+(j+1)|0]=0;j=Fc(b,h)|0;if((j|0)!=0){if((Dg(j|0)|0)<(e|0)){Lg(f|0,j|0)|0;k=1;break}if((e|0)>1){Hg(f|0,j|0,e+ -1|0)|0;k=1;break}else{a[f]=a[j]|0;k=1;break}}else{k=0}}}while(0);i=g;return k|0}function Pc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=i;g=Fc(b,c)|0;do{if((g|0)!=0){if((Dg(g|0)|0)<(d|0)){Lg(e|0,g|0)|0;h=1;break}if((d|0)>1){Hg(e|0,g|0,d+ -1|0)|0;h=1;break}else{a[e]=a[g]|0;h=1;break}}else{h=0}}while(0);i=f;return h|0}function Qc(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;d=i;e=Dg(b|0)|0;a:do{if(!((b|0)==0|(c|0)==0)){f=Dg(c|0)|0;if((f|0)!=0){if((e|0)!=0?(g=a[c]|0,h=f+ -1|0,j=a[c+h|0]|0,k=e+1-f|0,l=b+k|0,(k|0)>0):0){k=(f|0)==1;m=(f|0)<3;n=b;while(1){b:do{if((a[n]|0)==g<<24>>24){if(k){o=n;break a}if((a[n+h|0]|0)==j<<24>>24){if(m){o=n;break a}else{p=1}while(1){q=p+1|0;if((a[n+p|0]|0)!=(a[c+p|0]|0)){break b}if((q|0)<(f|0)){p=q}else{o=n;break a}}}}}while(0);q=n+1|0;if(q>>>0>>0){n=q}else{o=0;break}}}else{o=0}}else{o=b}}else{o=0}}while(0);i=d;return o|0}function Rc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;e=i;if((b|0)==0|(c|0)==0){f=0;i=e;return f|0}g=Dg(c|0)|0;if((g|0)==0){f=b;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}do{if((g|0)<3){h=a[c]|0;j=h<<24>>24;if(!((h+ -97<<24>>24&255)<26)){if((h+ -65<<24>>24&255)<26){k=j+32&255}else{k=h}}else{k=j+224&255}if((g|0)>1){j=a[c+1|0]|0;l=j<<24>>24;if((j+ -97<<24>>24&255)<26){m=h;n=j;o=k;p=l+224&255;q=0;break}if((j+ -65<<24>>24&255)<26){m=h;n=j;o=k;p=l+32&255;q=0}else{m=h;n=j;o=k;p=j;q=0}}else{m=h;n=32;o=k;p=32;q=0}}else{h=ig(g,1)|0;j=0;do{l=a[c+j|0]|0;r=l&255;do{if(!((l+ -97<<24>>24&255)<26)){if((l+ -65<<24>>24&255)<26){a[h+j|0]=r+32;break}else{a[h+j|0]=l;break}}else{a[h+j|0]=r+224}}while(0);j=j+1|0}while((j|0)!=(g|0));j=g+ -1|0;m=a[c]|0;n=a[c+j|0]|0;o=a[h]|0;p=a[h+j|0]|0;q=h}}while(0);k=d+1-g|0;d=b+k|0;a:do{if((k|0)>0){j=g+ -1|0;r=(g|0)>1;if((g|0)==2){l=b;while(1){s=a[l]|0;if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24?(s=a[l+j|0]|0,s<<24>>24==n<<24>>24|s<<24>>24==p<<24>>24):0){break}s=l+1|0;if(s>>>0>>0){l=s}else{break a}}if((q|0)==0){f=l;i=e;return f|0}hg(q);f=l;i=e;return f|0}else if((g|0)==1){h=b;while(1){s=a[h]|0;if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24){break}s=h+1|0;if(s>>>0>>0){h=s}else{break a}}if((q|0)==0){f=h;i=e;return f|0}hg(q);f=h;i=e;return f|0}else{l=b;b:while(1){s=a[l]|0;c:do{if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24?(t=a[l+j|0]|0,t<<24>>24==n<<24>>24|t<<24>>24==p<<24>>24):0){if(r){u=1}else{break b}while(1){t=a[l+u|0]|0;if(!(t<<24>>24==(a[c+u|0]|0))?!(t<<24>>24==(a[q+u|0]|0)):0){break c}u=u+1|0;if((u|0)>=(g|0)){break b}}}}while(0);s=l+1|0;if(s>>>0>>0){l=s}else{break a}}if((q|0)==0){f=l;i=e;return f|0}hg(q);f=l;i=e;return f|0}}}while(0);if((q|0)==0){f=0;i=e;return f|0}hg(q);f=0;i=e;return f|0}function Sc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;a:do{if(!((b|0)==0|(c|0)==0)){f=Dg(c|0)|0;if((f|0)!=0){if((d|0)!=0?(g=a[c]|0,h=f+ -1|0,j=a[c+h|0]|0,k=d+1-f|0,l=b+k|0,(k|0)>0):0){k=(f|0)==1;m=b;while(1){b:do{if((a[m]|0)==g<<24>>24){if(k){n=m;break a}if((a[m+h|0]|0)==j<<24>>24){if((f|0)<3){n=m;break a}else{o=1}while(1){p=o+1|0;if((a[m+o|0]|0)!=(a[c+o|0]|0)){break b}if((p|0)<(f|0)){o=p}else{n=m;break a}}}}}while(0);p=m+1|0;if(p>>>0>>0){m=p}else{n=0;break}}}else{n=0}}else{n=b}}else{n=0}}while(0);i=e;return n|0}function Tc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0;g=i;i=i+80|0;j=g;l=g+16|0;if(e<0.0){m=-e;n=-1.0}else{m=e;n=1.0}e=n*+qa(+m,360.0);if(e<0.0){o=e+360.0}else{o=e}e=o/15.0;p=~~e;o=(e- +(p|0))*60.0;q=~~o;e=(o- +(q|0))*60.0;do{if((f|0)<=5){if((f|0)>4){r=e>59.99999;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8008,j|0)|0;break}if((f|0)>3){s=e>59.9999;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,8032,j|0)|0;break}if((f|0)>2){r=e>59.999;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8056,j|0)|0;break}if((f|0)>1){s=e>59.99;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,8080,j|0)|0;break}if((f|0)>0){r=e>59.9;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8104,j|0)|0;break}else{s=~~(e+.5);r=(s|0)>59;t=(r&1)+q|0;u=(t|0)>59;c[j>>2]=((u&1)+p|0)%24|0;c[j+4>>2]=u?0:t;c[j+8>>2]=r?0:s;Na(l|0,8128,j|0)|0;break}}else{s=e>59.999999;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,7984,j|0)|0}}while(0);j=d+ -1|0;if((Dg(l|0)|0)<(j|0)){Lg(b|0,l|0)|0;i=g;return}else{Hg(b|0,l|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Uc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;g=i;i=i+96|0;j=g;l=g+24|0;if(e<0.0){m=-e;n=-1.0}else{m=e;n=1.0}e=n*+qa(+m,360.0);if(!(e<=-180.0)){o=e}else{o=e+360.0}if(o<0.0){p=-o;q=45}else{p=o;q=43}r=~~p;o=(p- +(r|0))*60.0;s=~~o;p=(o- +(s|0))*60.0;do{if((f|0)<=5){if((f|0)>4){t=p>59.99999;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8168,j|0)|0;break}if((f|0)>3){u=p>59.9999;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8192,j|0)|0;break}if((f|0)>2){t=p>59.999;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8216,j|0)|0;break}if((f|0)>1){u=p>59.99;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8240,j|0)|0;break}if((f|0)>0){t=p>59.9;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8264,j|0)|0;break}else{u=~~(p+.5);t=(u|0)>59;v=(t&1)+s|0;w=(v|0)>59;c[j>>2]=q&255;c[j+4>>2]=(w&1)+r;c[j+8>>2]=w?0:v;c[j+12>>2]=t?0:u;Na(l|0,8288,j|0)|0;break}}else{u=p>59.999999;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8144,j|0)|0}}while(0);j=d+ -1|0;if((Dg(l|0)|0)<(j|0)){Lg(b|0,l|0)|0;i=g;return}else{Hg(b|0,l|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Vc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0;g=i;i=i+80|0;j=g;l=g+72|0;m=g+8|0;if(e<0.0){n=-e;o=-1.0}else{n=e;o=1.0}e=o*+qa(+n,360.0);if(!(e<=-180.0)){p=e}else{p=e+360.0}q=f+4|0;if((f|0)>0){c[j>>2]=q;c[j+4>>2]=f;Na(l|0,8312,j|0)|0;h[k>>3]=p;c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];Na(m|0,l|0,j|0)|0}else{c[j>>2]=q;Na(l|0,8328,j|0)|0;c[j>>2]=~~p;Na(m|0,l|0,j|0)|0}j=d+ -1|0;if((Dg(m|0)|0)<(j|0)){Lg(b|0,m|0)|0;i=g;return}else{Hg(b|0,m|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Wc(a,b,d,e){a=a|0;b=+b;d=d|0;e=e|0;var f=0,g=0,j=0,l=0;f=i;i=i+16|0;g=f;j=f+8|0;l=(e|0)>0;if((d|0)>0){if(l){c[g>>2]=d;c[g+4>>2]=e;Na(j|0,8312,g|0)|0;h[k>>3]=b;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];Na(a|0,j|0,g|0)|0;i=f;return}else{c[g>>2]=d;Na(j|0,8336,g|0)|0;c[g>>2]=~~b;Na(a|0,j|0,g|0)|0;i=f;return}}else{if(l){c[g>>2]=e;Na(j|0,7976,g|0)|0;h[k>>3]=b;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];Na(a|0,j|0,g|0)|0;i=f;return}else{c[g>>2]=~~b;Na(a|0,7968,g|0)|0;i=f;return}}}function Xc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=i;i=i+32|0;e=d;f=_c(a,b)|0;if((f|0)==0){g=0;i=d;return g|0}Lg(e|0,f|0)|0;h[c>>3]=+ug(e);g=1;i=d;return g|0}function Yc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;g=i;h=gg(2e3)|0;if((Nc(b,c,2e3,h)|0)==0){hg(h);j=0;i=g;return j|0}c=_c(h,d)|0;do{if((c|0)!=0){if((Dg(c|0)|0)<(e|0)){Lg(f|0,c|0)|0;k=1;break}if((e|0)>1){Hg(f|0,c|0,e+ -1|0)|0;k=1;break}else{a[f]=a[c]|0;k=1;break}}else{k=0}}while(0);hg(h);j=k;i=g;return j|0}function Zc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=i;g=_c(b,c)|0;do{if((g|0)!=0){if((Dg(g|0)|0)<(d|0)){Lg(e|0,g|0)|0;h=1;break}if((d|0)>1){Hg(e|0,g|0,d+ -1|0)|0;h=1;break}else{a[e]=a[g]|0;h=1;break}}else{h=0}}while(0);i=f;return h|0}function _c(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=i;i=i+2032|0;e=d+2024|0;f=d+2018|0;g=d+2016|0;h=d+2e3|0;j=d;a[f]=91;a[f+1|0]=0;a[g]=93;a[g+1|0]=0;Lg(h|0,c|0)|0;c=Qc(h,f)|0;f=(c|0)!=0;if(f){a[c]=0;k=0}else{k=0}while(1){l=k+1|0;if((a[b+k|0]|0)==0){m=6;break}if((l|0)<57600){k=l}else{m=4;break}}if((m|0)==4){n=l;o=Dg(h|0)|0}else if((m|0)==6){l=Dg(h|0)|0;if((k|0)>0){n=k;o=l}else{p=0;i=d;return p|0}}l=b+n|0;n=l;k=b;while(1){q=Sc(k,h,n-k|0)|0;if((q|0)==0){p=0;m=34;break}r=a[q+o|0]|0;s=a[q+ -1|0]|0;if(!(r<<24>>24>32?!(r<<24>>24==61|r<<24>>24==127):0)){if((q|0)==(b|0)){t=b;m=14;break}if(s<<24>>24==9|s<<24>>24==32){t=q;m=14;break}}s=q+1|0;if(s>>>0>>0){k=s}else{p=0;m=34;break}}if((m|0)==14){if((t|0)==0){p=0;i=d;return p|0}k=t+o|0;while(1){o=a[k]|0;if(!(o<<24>>24==61|o<<24>>24==32)){break}k=k+1|0}if((k|0)==0){p=0;i=d;return p|0}Eg(j|0,0,2e3)|0;o=a[k]|0;a:do{if(o<<24>>24==34){t=k;l=0;while(1){b=t+1|0;n=a[b]|0;if(n<<24>>24==34|n<<24>>24==0){break a}if((l|0)>=2e3){break a}a[j+l|0]=n;t=b;l=l+1|0}}else{l=o;t=0;b=k;while(1){if(l<<24>>24==9|l<<24>>24==32){break a}if(!(l<<24>>24>0&(t|0)<2e3)){break a}n=b+1|0;a[j+t|0]=l;l=a[n]|0;t=t+1|0;b=n}}}while(0);if(!f){Lg(8344,j|0)|0;p=8344;i=d;return p|0}f=c+1|0;c=Qc(f,g)|0;if((c|0)==0){p=8344;i=d;return p|0}a[c]=0;c=vg(f)|0;if((c|0)<=0){p=8344;i=d;return p|0}a[e]=32;a[e+1|0]=44;a[e+2|0]=0;f=fg(j,e)|0;if((c|0)>1){j=1;while(1){g=fg(0,e)|0;k=j+1|0;if((k|0)==(c|0)){u=g;break}else{j=k}}}else{u=f}if((u|0)==0){p=8344;i=d;return p|0}Lg(8344,u|0)|0;p=8344;i=d;return p|0}else if((m|0)==34){i=d;return p|0}return 0}function $c(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0;g=i;j=c[d+3260>>2]|0;k=+h[d>>3];l=+h[d+8>>3];m=+h[d+32>>3];n=+h[d+40>>3];o=+h[d+48>>3]*3.141592653589793/180.0;p=+S(+o);q=+T(+o);r=a- +h[d+16>>3];a=b- +h[d+24>>3];do{if((c[d+3300>>2]|0)==0){if(m==0.0|n==0.0){h[e>>3]=0.0;h[f>>3]=0.0;s=2;i=g;return s|0}else{b=r*m;t=a*n;if(!(o!=0.0)){u=b;v=t;break}u=b*p-t*q;v=t*p+b*q;break}}else{u=r*+h[d+56>>3]+a*+h[d+64>>3];v=r*+h[d+72>>3]+a*+h[d+80>>3]}}while(0);w=(c[d+3304>>2]|0)==0;a=w?v:u;r=w?u:v;h[e>>3]=k+r;h[f>>3]=l+a;if((j|0)<1){s=0;i=g;return s|0}v=k*3.141592653589793/180.0;k=l*3.141592653589793/180.0;u=w?k:v;o=w?v:k;v=r*3.141592653589793/180.0;r=a*3.141592653589793/180.0;a=v*v;b=a+r*r;t=+S(+u);x=+T(+u);a:do{switch(j|0){case 11:{y=u+r;z=o+v;break};case 32:case 33:case 31:case 3:{if(b>1.0){s=1;i=g;return s|0}A=t-r*x;if(A==0.0){s=1;i=g;return s|0}else{B=o+ +Y(+v,+A);y=+X(+((r*t+x)*+S(+(B-o))/A));z=B;break a}break};case 6:{if(b>=9.869604401089369){s=1;i=g;return s|0}B=+Q(+b);A=+S(+B);if(B!=0.0){C=+T(+B)/B}else{C=1.0}B=x*A+r*t*C;if(B>1.0|B<-1.0){s=1;i=g;return s|0}D=A-x*B;A=t*v*C;if(D==0.0&A==0.0){s=1;i=g;return s|0}else{y=+W(+B);z=o+ +Y(+A,+D);break a}break};case 22:{D=n*p+m*q;A=(D==0.0?3.141592653589793:D*3.141592653589793)/180.0;D=k+A;B=+T(+k);E=+S(+k);F=+Q(+((E+1.0)*.5));G=+T(+D)/+Q(+((+S(+D)+1.0)*.5))-B/F;D=A/(G==0.0?1.0:G);G=m*p-n*q;A=(G==0.0?3.141592653589793:G*3.141592653589793)/180.0;G=A*.5;H=E*2.0*+T(+G);I=A*+Q(+((E*+S(+G)+1.0)*.5))/(H==0.0?1.0:H);if(!(v==0.0&r==0.0)){H=r+B*D/F;F=H/D;B=4.0-a/(I*I*4.0)-F*F;if(B>4.0|B<2.0){s=1;i=g;return s|0}F=+Q(+B)*.5;B=H*F/D;if(+P(+B)>1.0){s=1;i=g;return s|0}D=+W(+B);B=+S(+D);if(+P(+B)<1.0e-5){s=1;i=g;return s|0}H=v*F/(I*2.0*B);if(+P(+H)>1.0){s=1;i=g;return s|0}else{y=D;z=o+ +W(+H)*2.0;break a}}else{y=u;z=o}break};case 5:{H=(4.0-b)/(b+4.0);if(+P(+H)>1.0){s=1;i=g;return s|0}D=H+1.0;B=x*H+r*t*D*.5;if(+P(+B)>1.0){s=1;i=g;return s|0}H=+W(+B);B=+S(+H);if(+P(+B)<1.0e-5){s=1;i=g;return s|0}I=v*D/(B*2.0);if(+P(+I)>1.0){s=1;i=g;return s|0}D=+W(+I);I=+T(+H);F=+S(+D);G=x*I+1.0+t*B*F;if(+P(+G)<1.0e-5){s=1;i=g;return s|0}if(+P(+((t*I-x*B*F)*2.0/G-r))>1.0e-5){J=3.141592653589795-D}else{J=D}y=H;z=o+J;break};case 20:case 28:{H=u+r;if(+P(+H)>1.5707963267948974){s=1;i=g;return s|0}D=+S(+H);if(+P(+v)>D*6.28318530717959*.5){s=1;i=g;return s|0}if(D>1.0e-5){y=H;z=o+v/D}else{y=H;z=o}break};case 27:{H=t-r*x;if(H==0.0){s=1;i=g;return s|0}D=o+ +Y(+v,+H);G=+S(+(D-o));if(G==0.0){s=1;i=g;return s|0}F=H/G;if(F>1.0|F<-1.0){s=1;i=g;return s|0}G=+V(+F);if(u<0.0){y=-G;z=D}else{y=G;z=D}break};case 12:{D=n*p+m*q;G=D==0.0?1.0:D;D=(l*.5+45.0)*3.141592653589793/180.0;F=+_(+(+U(+D)));H=G*3.141592653589793/180.0/(+_(+(+U(+(G*.5*.01745329252+D))))-F);D=+S(+k);G=o+v/(!(D<=0.0)?D:1.0);if(+P(+(G-o))>6.28318530717959){s=1;i=g;return s|0}if(H!=0.0){K=(r+F*H)/H}else{K=0.0}y=+X(+(+Z(+K)))*2.0+-1.5707963267948974;z=G;break};case 4:{if(b>1.0){s=1;i=g;return s|0}G=+Q(+(1.0-b));H=r*t+x*G;if(H>1.0|H<-1.0){s=1;i=g;return s|0}F=t*G-r*x;if(F==0.0&v==0.0){s=1;i=g;return s|0}else{y=+W(+H);z=o+ +Y(+v,+F);break a}break};case 16:{F=1.0/+U(+u)-r;if(u<0.0){L=-F}else{L=F}y=+W(+((x*x*(1.0-(a+F*F))+1.0)*(1.0/(x*2.0))));z=o- +Y(+v,+L)/x;break};default:{y=0.0;z=0.0}}}while(0);if(z-o>3.141592653589795){M=z+-6.28318530717959}else{M=z}if(M-o<-3.141592653589795){N=M+6.28318530717959}else{N=M}if(N<0.0){O=N+6.28318530717959}else{O=N}h[e>>3]=O*180.0/3.141592653589793;h[f>>3]=y*180.0/3.141592653589793;s=0;i=g;return s|0}function ad(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0,N=0.0,O=0.0,R=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0;g=i;j=+h[d>>3];k=+h[d+8>>3];l=+h[d+16>>3];m=+h[d+24>>3];n=+h[d+32>>3];o=+h[d+40>>3];p=+h[d+48>>3]*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=c[d+3260>>2]|0;t=(s|0)>0;if(t){u=(c[d+3304>>2]|0)==0;v=j*3.141592653589793/180.0;w=k*3.141592653589793/180.0;x=u?w:v;y=u?v:w;w=a-(u?j:k);v=l*n;if(v>180.0|v<-180.0){if(w>360.0){z=a+-360.0}else{z=a}if(w<0.0){A=z+360.0}else{A=z}}else{if(w>180.0){B=a+-360.0}else{B=a}if(w<-180.0){A=B+360.0}else{A=B}}B=A*3.141592653589793/180.0;w=b*3.141592653589793/180.0;z=+S(+w);v=+T(+w);C=B-y;D=A;E=z;F=w;G=x;H=z*+T(+C);I=B;J=y;K=v;L=v*+T(+x)+z*+S(+x)*+S(+C)}else{D=a;E=0.0;F=0.0;G=0.0;H=0.0;I=0.0;J=0.0;K=0.0;L=0.0}a:do{switch(s|0){case 22:{a=(I-J)*.5;if(+P(+a)>1.5707963267948974){M=1;i=g;return M|0}C=o*q+n*r;x=(C==0.0?3.141592653589793:C*3.141592653589793)/180.0;C=k*3.141592653589793/180.0;z=x+C;v=+T(+C);y=+S(+C);C=+Q(+((y+1.0)*.5));B=+T(+z)/+Q(+((+S(+z)+1.0)*.5))-v/C;z=x/(B==0.0?1.0:B);B=n*q-o*r;x=(B==0.0?3.141592653589793:B*3.141592653589793)/180.0;B=x*.5;w=y*2.0*+T(+B);A=+S(+F);N=+Q(+((A*+S(+a)+1.0)*.5));if(+P(+N)<1.0e-5){M=3;i=g;return M|0}else{O=+T(+a)*A*x*+Q(+((y*+S(+B)+1.0)*.5))/(w==0.0?1.0:w)*2.0/N;R=z*+T(+F)/N-v*z/C;break a}break};case 3:case 32:case 33:case 31:{if(!(L<=0.0)){C=+T(+G);z=+S(+G);v=+S(+(I-J));N=K*C+E*z*v;O=H/N;R=(K*z-E*C*v)/N;break a}else{M=1;i=g;return M|0}break};case 16:{N=+U(+G);v=1.0/N;C=N*-2.0;z=N*N;w=N/3.0;N=C*C;B=(J-I)*+T(+G);y=F-G;x=v*(y*(C*.5+y*(z*.5+N*-.125+y*(w*.5+(z*C*-.25+C*N*.0625)+y*(z*.1875*N+(z*z*-.125-C*.25*w)-N*N*.0390625))))+1.0);N=B*B;if((c[d+3300>>2]|0)==0){W=n/+P(+n)}else{w=+h[d+56>>3];W=w/+P(+w)}O=(1.0-N/6.0)*B*x*W;R=v-(1.0-N*.5)*x;break};case 27:{if(G==0.0){M=1;i=g;return M|0}else{O=H;R=(+S(+G)-E*+S(+(I-J)))/+T(+G);break a}break};case 12:{x=o*q+n*r;N=x==0.0?1.0:x;x=(k*.5+45.0)*3.141592653589793/180.0;v=+_(+(+U(+x)));B=N*3.141592653589793/180.0/(+_(+(+U(+(N*.5*.01745329252+x))))-v);x=+S(+(k*3.141592653589793/180.0));N=+U(+(F*.5+.7853981633974487));if(N<1.0e-5){M=2;i=g;return M|0}else{O=(I-J)*(!(x<=0.0)?x:1.0);R=B*+_(+N)-v*B;break a}break};case 6:{B=+T(+G);v=+S(+G);N=+S(+(I-J));x=K*B+E*v*N;w=x<-1.0?-1.0:x;x=+V(+(w>1.0?1.0:w));if(x!=0.0){X=x/+T(+x)}else{X=1.0}O=H*X;R=(K*v-E*B*N)*X;break};case 20:case 28:{if(+P(+F)>1.5707963267948974){M=1;i=g;return M|0}if(+P(+G)>1.5707963267948974){M=1;i=g;return M|0}else{O=E*(I-J);R=F-G;break a}break};case 11:{O=I-J;R=F-G;break};case 4:{if(L<0.0){M=1;i=g;return M|0}else{O=H;R=K*+S(+G)-E*+T(+G)*+S(+(I-J));break a}break};case 5:{if(+P(+F)>1.5707963267948974){M=1;i=g;return M|0}N=+T(+G);B=+S(+G);v=+S(+(I-J));x=K*N+1.0+E*B*v;if(+P(+x)<1.0e-5){M=1;i=g;return M|0}else{w=2.0/x;O=H*w;R=(K*B-E*N*v)*w;break a}break};default:{O=H;R=0.0}}}while(0);if(t){Y=O*180.0/3.141592653589793;Z=R*180.0/3.141592653589793}else{Y=D-j;Z=b-k}t=(c[d+3304>>2]|0)==0;k=t?Z:Y;b=t?Y:Z;if((c[d+3300>>2]|0)==0){if(p!=0.0){$=q*b+r*k;aa=q*k-r*b}else{$=b;aa=k}if(n!=0.0){ba=$/n}else{ba=$}if(o!=0.0){ca=ba;da=aa/o}else{ca=ba;da=aa}}else{ca=b*+h[d+88>>3]+k*+h[d+96>>3];da=b*+h[d+104>>3]+k*+h[d+112>>3]}k=l+ca;h[e>>3]=k;do{if((s|0)==11){ca=+h[d+136>>3];if(k>ca){l=k-360.0/n;if(!(l>0.0)){break}h[e>>3]=l;break}if(k<0.0?(l=k+360.0/n,l<=ca):0){h[e>>3]=l}}}while(0);h[f>>3]=m+da;M=0;i=g;return M|0}function bd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0;g=i;j=c[d+3268>>2]|0;k=c[d+3272>>2]|0;l=a- +h[d+616>>3];a=b- +h[d+624>>3];b=l*l;m=a*a;n=l*b;o=a*m;p=b+m;q=+h[d+256>>3]+l*+h[d+264>>3]+a*+h[d+272>>3]+b*+h[d+280>>3]+m*+h[d+288>>3]+a*l*+h[d+296>>3];if((j|0)>6){r=q+n*+h[d+304>>3]+o*+h[d+312>>3];if((j|0)>8){s=p*+h[d+336>>3]+(r+a*b*+h[d+320>>3]+m*l*+h[d+328>>3])+p*l*+h[d+344>>3]+p*a*+h[d+352>>3]}else{s=r}}else{s=q}q=+h[d+416>>3]+l*+h[d+424>>3]+a*+h[d+432>>3]+b*+h[d+440>>3]+m*+h[d+448>>3]+a*l*+h[d+456>>3];if((k|0)>6){r=q+n*+h[d+464>>3]+o*+h[d+472>>3];if((k|0)>8){t=p*+h[d+496>>3]+(r+a*b*+h[d+480>>3]+l*m*+h[d+488>>3])+p*l*+h[d+504>>3]+p*a*+h[d+512>>3]}else{t=r}}else{t=q}q=t*3.141592653589793/180.0;t=+h[d+696>>3]*3.141592653589793/180.0;r=+U(+t);a=1.0-q*r;p=+Y(+(s*3.141592653589793/180.0/+S(+t)),+a);t=+h[d+688>>3]*3.141592653589793/180.0+p;if(!(t<0.0)){u=t;v=u*180.0;w=v/3.141592653589793;h[e>>3]=w;x=+S(+p);y=q+r;z=a/y;A=x/z;B=+X(+A);C=B*180.0;D=C/3.141592653589793;h[f>>3]=D;i=g;return 0}u=t+6.28318530717959;v=u*180.0;w=v/3.141592653589793;h[e>>3]=w;x=+S(+p);y=q+r;z=a/y;A=x/z;B=+X(+A);C=B*180.0;D=C/3.141592653589793;h[f>>3]=D;i=g;return 0}function cd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0,M=0,N=0,O=0,Q=0,R=0,T=0,V=0,W=0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0,va=0.0,wa=0.0,xa=0,ya=0.0,za=0.0,Aa=0.0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0;g=i;j=c[d+3268>>2]|0;k=c[d+3272>>2]|0;l=+U(+(b*3.141592653589793/180.0));b=+h[d+696>>3]*3.141592653589793/180.0;m=+U(+b);n=a*3.141592653589793/180.0- +h[d+688>>3]*3.141592653589793/180.0;a=+S(+n);o=(1.0-m*a/l)/(m+a/l);l=+S(+b)*+U(+n)*(1.0-m*o)*180.0/3.141592653589793;m=o*180.0/3.141592653589793;o=l*+h[d+88>>3]+m*+h[d+96>>3];n=l*+h[d+104>>3]+m*+h[d+112>>3];b=+h[d+256>>3];a=+h[d+264>>3];p=+h[d+272>>3];q=+h[d+280>>3];r=+h[d+288>>3];s=+h[d+296>>3];t=q*2.0;u=r*2.0;v=d+304|0;w=d+312|0;x=(j|0)>8;y=d+320|0;z=d+328|0;A=d+336|0;B=d+344|0;C=d+352|0;D=+h[d+416>>3];E=+h[d+424>>3];F=+h[d+432>>3];G=+h[d+440>>3];H=+h[d+448>>3];I=+h[d+456>>3];J=G*2.0;K=H*2.0;L=(k|0)>6;M=d+464|0;N=d+472|0;O=(k|0)>8;k=d+480|0;Q=d+488|0;R=d+496|0;T=d+504|0;V=d+512|0;a:do{if((j|0)>6){W=0;X=o;Y=n;while(1){Z=Y*X;_=X*X;$=Y*Y;aa=X*_;ba=Y*$;ca=Y*_;da=$*X;ea=$+_;fa=+h[v>>3];ga=+h[w>>3];ha=b+X*a+Y*p+_*q+$*r+Z*s+aa*fa+ba*ga;ia=a+X*t+Y*s+_*fa*3.0;fa=X*s+(p+Y*u)+$*ga*3.0;if(x){ga=+h[y>>3];ja=+h[z>>3];ka=+h[A>>3];la=+h[B>>3];ma=+h[C>>3];na=ka*2.0;oa=ha+ca*ga+da*ja+ea*ka+ea*X*la+ea*Y*ma;pa=($+_*3.0)*la+($*ja+(ia+Z*ga*2.0)+X*na)+Z*ma*2.0;qa=($*3.0+_)*ma+(fa+_*ga+Z*ja*2.0+Y*na+Z*la*2.0)}else{oa=ha;pa=ia;qa=fa}fa=D+X*E+Y*F+_*G+$*H+Z*I;ia=E+X*J+Y*I;ha=X*I+(F+Y*K);if(L){la=+h[M>>3];na=+h[N>>3];ja=fa+aa*la+ba*na;ba=ia+_*la*3.0;la=ha+$*na*3.0;if(O){na=+h[k>>3];aa=+h[Q>>3];ga=+h[R>>3];ma=+h[T>>3];ka=+h[V>>3];ra=ga*2.0;sa=ja+ca*na+da*aa+ea*ga+ea*X*ma+ea*Y*ka;ta=($+_*3.0)*ma+($*aa+(ba+Z*na*2.0)+X*ra)+Z*ka*2.0;ua=($*3.0+_)*ka+(la+_*na+Z*aa*2.0+Y*ra+Z*ma*2.0)}else{sa=ja;ta=ba;ua=la}}else{sa=fa;ta=ia;ua=ha}ha=oa-l;ia=sa-m;fa=pa*ua-qa*ta;la=(qa*ia-ha*ua)/fa;ba=(ha*ta-pa*ia)/fa;fa=X+la;ia=Y+ba;if(+P(+la)<5.0e-7?+P(+ba)<5.0e-7:0){va=fa;wa=ia;break a}xa=W+1|0;if((xa|0)<50){W=xa;X=fa;Y=ia}else{va=fa;wa=ia;break}}}else{W=0;Y=o;X=n;while(1){ia=X*Y;fa=Y*Y;ba=X*X;la=X*fa;ha=ba*Y;ja=ba+fa;ma=b+Y*a+X*p+fa*q+ba*r+ia*s;Z=a+Y*t+X*s;ra=Y*s+(p+X*u);aa=D+Y*E+X*F+fa*G+ba*H+ia*I;na=E+Y*J+X*I;_=Y*I+(F+X*K);if(L){ka=+h[M>>3];$=+h[N>>3];ea=aa+Y*fa*ka+X*ba*$;ga=na+fa*ka*3.0;ka=_+ba*$*3.0;if(O){$=+h[k>>3];da=+h[Q>>3];ca=+h[R>>3];ya=+h[T>>3];za=+h[V>>3];Aa=ca*2.0;Ba=ea+la*$+ha*da+ja*ca+ja*Y*ya+ja*X*za;Ca=(ba+fa*3.0)*ya+(ba*da+(ga+ia*$*2.0)+Y*Aa)+ia*za*2.0;Da=(ba*3.0+fa)*za+(ka+fa*$+ia*da*2.0+X*Aa+ia*ya*2.0)}else{Ba=ea;Ca=ga;Da=ka}}else{Ba=aa;Ca=na;Da=_}_=ma-l;ma=Ba-m;na=Z*Da-ra*Ca;aa=(ra*ma-_*Da)/na;ra=(_*Ca-Z*ma)/na;na=Y+aa;ma=X+ra;if(+P(+aa)<5.0e-7?+P(+ra)<5.0e-7:0){va=na;wa=ma;break a}xa=W+1|0;if((xa|0)<50){W=xa;Y=na;X=ma}else{va=na;wa=ma;break}}}}while(0);h[e>>3]=va+ +h[d+616>>3];va=wa+ +h[d+624>>3];h[f>>3]=va;wa=+h[e>>3];if(wa<.5){Ea=-1;i=g;return Ea|0}if(wa>+h[d+136>>3]+.5|va<.5){Ea=-1;i=g;return Ea|0}if(va>+h[d+144>>3]+.5){Ea=-1;i=g;return Ea|0}Ea=0;i=g;return Ea|0}function dd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0;d=i;e=gg(2e3)|0;f=gg(2e3)|0;Nc(a,10344,2e3,e)|0;Nc(a,10352,2e3,f)|0;a=gg(2e3)|0;g=gg(2e3)|0;j=b+3176|0;if((+h[j>>3]>360.0?(Xc(e,10360,j)|0)==0:0)?(Xc(f,10360,j)|0)==0:0){h[j>>3]=180.0}j=b+3192|0;if((Xc(e,10376,j)|0)==0?(Xc(f,10376,j)|0)==0:0){h[j>>3]=57.29577951308232}do{if((Zc(e,10384,2e3,a)|0)==0){if((Zc(f,10384,2e3,a)|0)==0){c[b+5960>>2]=0;break}else{c[b+5960>>2]=gd(a)|0;break}}else{c[b+5960>>2]=gd(a)|0}}while(0);do{if((Zc(f,10392,2e3,g)|0)==0){if((Zc(e,10392,2e3,g)|0)==0){c[b+5964>>2]=0;break}else{c[b+5964>>2]=gd(g)|0;break}}else{c[b+5964>>2]=gd(g)|0}}while(0);ac(b);hg(e);hg(f);hg(a);hg(g);if((c[b+5964>>2]|0)==0?(c[b+5960>>2]|0)==0:0){k=1;i=d;return k|0}k=0;i=d;return k|0}function ed(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0;g=i;j=a- +h[d+616>>3];a=b- +h[d+624>>3];if((c[d+3300>>2]|0)==0){b=+h[d+760>>3];if(b==0.0){k=2;l=0.0;m=0.0;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}n=+h[d+768>>3];if(n==0.0){k=2;l=0.0;m=0.0;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}o=j*b;b=a*n;n=+h[d+48>>3];if(n!=0.0){p=n*3.141592653589793/180.0;n=+S(+p);q=+T(+p);r=o*n-b*q;s=b*n+o*q}else{r=o;s=b}}else{r=j*+h[d+56>>3]+a*+h[d+64>>3];s=j*+h[d+72>>3]+a*+h[d+80>>3]}t=(c[d+3304>>2]|0)==0|0;a=(90.0- +h[d+(t<<3)+688>>3])*3.141592653589793/180.0;j=+S(+a);b=+T(+a);o=+h[d+3176>>3]*3.141592653589793/180.0;u=c[d+5960>>2]|0;if((u|0)==0){v=r}else{v=r+ +hd(u,r,s)}u=c[d+5964>>2]|0;if((u|0)==0){w=s}else{w=s+ +hd(u,r,s)}s=+Q(+(v*v+w*w));if(s==0.0){x=0.0}else{x=+Y(+v,+-w)}w=+Y(+(+h[d+3192>>3]),+s);s=+S(+w);v=+T(+w);r=x-o;o=+S(+r);x=+T(+r);q=j*s;n=b*v-q*o;if(+P(+n)<1.0e-5){y=q*(1.0-o)- +S(+(a+w))}else{y=n}n=s*x;if(y!=0.0|n!=-0.0){z=+Y(+-n,+y)}else{z=r+3.141592653589793}x=+h[d+((t^1)<<3)+688>>3];q=x+z*180.0/3.141592653589793;if(!(x>=0.0)){if(q>0.0){A=q+-360.0}else{A=q}}else{if(q<0.0){A=q+360.0}else{A=q}}if(!(A>360.0)){if(A<-360.0){B=A+360.0}else{B=A}}else{B=A+-360.0}if(+qa(+r,3.141592653589793)==0.0){r=(w+a*o)*180.0/3.141592653589793;if(r>90.0){C=180.0-r}else{C=r}if(!(C<-90.0)){k=0;l=C;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}k=0;l=-180.0-C;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}C=j*v+b*s*o;if(!(+P(+C)>.99)){k=0;l=+W(+C)*180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}o=+V(+(+Q(+(n*n+y*y))));if(!(C>=0.0)){k=0;l=o*-180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}else{k=0;l=o*180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}return 0}function fd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0,D=0,E=0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0,U=0.0,X=0.0,Z=0.0,_=0,$=0.0,aa=0.0,ba=0.0;g=i;j=d+3304|0;k=(c[j>>2]|0)==0|0;l=(a- +h[d+((k^1)<<3)+688>>3])*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+l);m=+T(+l);n=+S(+a);o=+T(+a);p=(90.0- +h[d+(k<<3)+688>>3])*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=+h[d+3176>>3];if(s==999.0){t=3.141592653589793}else{t=s*3.141592653589793/180.0}s=n*q;u=o*r-b*s;if(+P(+u)<1.0e-5){v=(1.0-b)*s- +S(+(a+p))}else{v=u}u=m*n;if(v!=0.0|u!=-0.0){w=+Y(+-u,+v)}else{w=l+-3.141592653589793}m=t+w;if(!(m>3.141592653589793)){if(m<-3.141592653589793){x=m+6.283185307179586}else{x=m}}else{x=m+-6.283185307179586}do{if(+qa(+l,3.141592653589793)==0.0){m=a+b*p;if(m>1.5707963267948966){y=3.141592653589793-m}else{y=m}if(y<-1.5707963267948966){z=-3.141592653589793-y}else{z=y}}else{m=o*q+b*n*r;if(!(+P(+m)>.99)){z=+W(+m);break}w=+V(+(+Q(+(u*u+v*v))));if(!(m>=0.0)){z=-w}else{z=w}}}while(0);v=+T(+z);do{if(v==0.0){A=0.0;B=0.0}else{u=+h[d+3192>>3]*+S(+z)/v;k=d+5960|0;C=c[k>>2]|0;D=d+5964|0;if((C|0)==0?(c[D>>2]|0)==0:0){E=(c[j>>2]|0)==0;r=u*+T(+x);n=-(u*+S(+x));A=E?r:n;B=E?n:r;break}r=u*+T(+x);n=u*+S(+x);E=C;C=1;u=r;b=-n;while(1){if((E|0)==0){F=u;G=1.0;H=0.0}else{q=u+ +hd(E,u,b);o=+id(c[k>>2]|0,u,b,1,0)+1.0;F=q;G=o;H=+id(c[k>>2]|0,u,b,0,1)}o=F-r;I=c[D>>2]|0;if((I|0)==0){J=b;K=0.0;L=1.0}else{q=b+ +hd(I,u,b);y=+id(c[D>>2]|0,u,b,1,0);J=q;K=y;L=+id(c[D>>2]|0,u,b,0,1)+1.0}y=n+J;q=G*L-H*K;if(q==0.0){M=u;N=b;break}p=(H*y-o*L)/q;a=(o*K-G*y)/q;q=u+p;l=b+a;I=+P(+p)>+P(+a);w=I?p:a;a=+P(+w);I=+P(+o)>+P(+y);p=I?o:y;I=a>+P(+p);if(!(!(+P(+(I?w:p))<2.8e-8)&(C|0)<500)){M=q;N=l;break}E=c[k>>2]|0;C=C+1|0;u=q;b=l}C=(c[j>>2]|0)==0;A=C?M:N;B=C?N:M}}while(0);if((c[d+3300>>2]|0)!=0){h[e>>3]=A*+h[d+88>>3]+B*+h[d+96>>3];h[f>>3]=A*+h[d+104>>3]+B*+h[d+112>>3];O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}M=+h[d+48>>3];if(M!=0.0){N=M*3.141592653589793/180.0;M=+S(+N);G=+T(+N);h[e>>3]=A*M+B*G;ba=B*M-A*G}else{h[e>>3]=A;ba=B}h[f>>3]=ba;ba=+h[d+32>>3];if(ba!=0.0){h[e>>3]=+h[e>>3]/ba}ba=+h[d+40>>3];if(!(ba!=0.0)){O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}h[f>>3]=+h[f>>3]/ba;O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}function gd(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=i;i=i+16|0;e=d;if((a[b+1|0]|0)==0){f=0;i=d;return f|0}g=gg(160)|0;c[e>>2]=b;j=b;k=b;b=g;g=0;l=20;a:while(1){if((a[k]|0)==0){break}m=+wg(j,e);n=c[e>>2]|0;o=a[n]|0;if(o<<24>>24==46){p=n+1|0;c[e>>2]=p;q=a[p]|0;r=p}else{q=o;r=n}if(q<<24>>24==0){break}n=g+1|0;if((n|0)<(l|0)){s=r;t=b;u=l}else{o=l+20|0;p=jg(b,o<<3)|0;s=c[e>>2]|0;t=p;u=o}h[t+(g<<3)>>3]=m;o=s;while(1){if((a[o]|0)==32){o=o+1|0}else{j=o;k=s;b=t;g=n;l=u;continue a}}}u=jd(b)|0;hg(b);f=(g|0)==0?0:u;i=d;return f|0}function hd(a,b,d){a=a|0;b=+b;d=+d;var e=0,f=0,g=0,j=0.0,k=0.0,l=0,m=0.0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0,F=0,G=0,H=0,I=0,J=0.0,K=0,L=0.0,M=0,N=0.0,O=0;e=i;f=c[a+32>>2]|0;if((f|0)==1){g=c[a+36>>2]|0;j=+h[a+8>>3];k=+h[a>>3];l=c[a+56>>2]|0;h[l>>3]=1.0;if(((g|0)!=1?(m=(j+b)*k,h[l+8>>3]=m,(g|0)>2):0)?(k=m*2.0,j=k*m+-1.0,h[l+16>>3]=j,(g|0)!=3):0){m=j;n=3;p=2;while(1){m=k*m- +h[l+(p+ -1<<3)>>3];h[l+(n<<3)>>3]=m;q=n+1|0;if((q|0)==(g|0)){break}else{r=n;n=q;p=r}}}p=c[a+40>>2]|0;m=+h[a+24>>3];k=+h[a+16>>3];n=c[a+60>>2]|0;h[n>>3]=1.0;if((p|0)!=1){j=(m+d)*k;h[n+8>>3]=j;if((p|0)>2){k=j*2.0;m=k*j+-1.0;h[n+16>>3]=m;if((p|0)==3){s=l;t=n;u=3;v=g;w=25}else{j=m;r=3;q=2;while(1){m=k*j- +h[n+(q+ -1<<3)>>3];h[n+(r<<3)>>3]=m;x=r+1|0;if((x|0)==(p|0)){y=g;z=p;A=l;B=n;w=26;break}else{C=r;j=m;r=x;q=C}}}}else{y=g;z=p;A=l;B=n;w=26}}else{s=l;t=n;u=1;v=g;w=25}}else if((f|0)==3){g=c[a+36>>2]|0;n=c[a+56>>2]|0;h[n>>3]=1.0;if((g|0)!=1?(h[n+8>>3]=b,(g|0)>2):0){j=b;l=2;do{j=j*b;h[n+(l<<3)>>3]=j;l=l+1|0}while((l|0)!=(g|0))}l=c[a+40>>2]|0;p=c[a+60>>2]|0;h[p>>3]=1.0;if((l|0)!=1){h[p+8>>3]=d;if((l|0)>2){j=d;q=2;while(1){k=j*d;h[p+(q<<3)>>3]=k;r=q+1|0;if((r|0)==(l|0)){y=g;z=l;A=n;B=p;w=26;break}else{j=k;q=r}}}else{y=g;z=l;A=n;B=p;w=26}}else{s=n;t=p;u=1;v=g;w=25}}else if((f|0)==2){f=c[a+36>>2]|0;j=+h[a+8>>3];k=+h[a>>3];g=c[a+56>>2]|0;h[g>>3]=1.0;if(((f|0)!=1?(m=(j+b)*k,h[g+8>>3]=m,(f|0)>2):0)?(k=(m*m*3.0+-1.0)*.5,h[g+16>>3]=k,(f|0)!=3):0){p=3;b=k;n=2;while(1){k=+(p|0);b=(b*m*(k*2.0+-1.0)- +h[g+(n+ -1<<3)>>3]*(k+-1.0))/k;h[g+(p<<3)>>3]=b;l=p+1|0;if((l|0)==(f|0)){break}else{q=p;p=l;n=q}}}n=c[a+40>>2]|0;b=+h[a+24>>3];m=+h[a+16>>3];p=c[a+60>>2]|0;h[p>>3]=1.0;if((n|0)!=1){k=(b+d)*m;h[p+8>>3]=k;if((n|0)>2){m=(k*k*3.0+-1.0)*.5;h[p+16>>3]=m;if((n|0)==3){s=g;t=p;u=3;v=f;w=25}else{q=3;d=m;l=2;while(1){m=+(q|0);b=(d*k*(m*2.0+-1.0)- +h[p+(l+ -1<<3)>>3]*(m+-1.0))/m;h[p+(q<<3)>>3]=b;r=q+1|0;if((r|0)==(n|0)){y=f;z=n;A=g;B=p;w=26;break}else{C=q;q=r;d=b;l=C}}}}else{y=f;z=n;A=g;B=p;w=26}}else{s=g;t=p;u=1;v=f;w=25}}else{ab(10400,33,1,c[o>>2]|0)|0;D=0.0;i=e;return+D}if((w|0)==25){E=(v|0)>(u|0)?v:u;F=t;G=u;H=s;I=v}else if((w|0)==26){if((z|0)>0){E=(y|0)>(z|0)?y:z;F=B;G=z;H=A;I=y}else{D=0.0;i=e;return+D}}y=c[a+44>>2]|0;A=a+52|0;if((y|0)==2){a=0;z=0;d=0.0;B=I;while(1){if((B|0)>0){w=c[A>>2]|0;k=0.0;v=z;s=0;while(1){k=k+ +h[w+(v<<3)>>3]*+h[H+(s<<3)>>3];s=s+1|0;if((s|0)==(B|0)){break}else{v=v+1|0}}J=k;K=B+z|0}else{J=0.0;K=z}b=d+J*+h[F+(a<<3)>>3];v=(((a+1+I|0)>(E|0))<<31>>31)+B|0;s=a+1|0;if((s|0)<(G|0)){a=s;z=K;d=b;B=v}else{D=b;break}}i=e;return+D}else if((y|0)==0){y=0;B=0;d=0.0;K=I;while(1){if((K|0)>0){z=c[A>>2]|0;J=0.0;a=B;E=0;while(1){J=J+ +h[z+(a<<3)>>3]*+h[H+(E<<3)>>3];E=E+1|0;if((E|0)==(K|0)){break}else{a=a+1|0}}L=J;M=K+B|0}else{L=0.0;M=B}k=d+L*+h[F+(y<<3)>>3];a=y+1|0;if((a|0)<(G|0)){y=a;B=M;d=k;K=1}else{D=k;break}}i=e;return+D}else{K=0;M=0;d=0.0;while(1){if((I|0)>0){B=c[A>>2]|0;L=0.0;y=M;a=0;while(1){L=L+ +h[B+(y<<3)>>3]*+h[H+(a<<3)>>3];a=a+1|0;if((a|0)==(I|0)){break}else{y=y+1|0}}N=L;O=I+M|0}else{N=0.0;O=M}J=d+N*+h[F+(K<<3)>>3];y=K+1|0;if((y|0)<(G|0)){K=y;M=O;d=J}else{D=J;break}}i=e;return+D}return 0.0}function id(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0.0,O=0,P=0,Q=0,S=0,T=0.0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0.0,$=0.0,ba=0.0,ca=0.0,da=0,ea=0.0,fa=0.0;g=i;i=i+16|0;j=g;if((a|0)==0){k=0.0;i=g;return+k}l=f|e;if((l|0)<0){ab(10440,46,1,c[o>>2]|0)|0;k=0.0;i=g;return+k}if((l|0)==0){k=+hd(a,b,d);i=g;return+k}l=gg(64)|0;m=a+36|0;n=c[m>>2]|0;p=n+ -1|0;q=(p|0)>(e|0)?e:p;p=a+40|0;e=c[p>>2]|0;r=e+ -1|0;s=(r|0)>(f|0)?f:r;r=c[a+32>>2]|0;t=l+32|0;c[t>>2]=r;if(!((r+ -1|0)>>>0<3)){u=c[o>>2]|0;c[j>>2]=r;za(u|0,10488,j|0)|0;k=0.0;i=g;return+k}j=c[a+44>>2]|0;u=l+44|0;c[u>>2]=j;do{if((j|0)==2){r=((n|0)>(e|0)?n:e)-s-q|0;v=n-q|0;w=(r|0)<(v|0)?r:v;v=(w|0)<1?1:w;w=l+36|0;c[w>>2]=v;x=e-s|0;y=(r|0)<(x|0)?r:x;x=(y|0)<1?1:y;y=l+40|0;c[y>>2]=x;r=(v|0)<(x|0)?v:x;z=(aa(x,v)|0)-((aa(r+ -1|0,r)|0)/2|0)|0;r=l+48|0;c[r>>2]=z;A=r;B=w;C=y;D=z;E=v;F=x}else if((j|0)==0){x=(q|0)>0;v=(s|0)>0;if(x&v){z=l+36|0;c[z>>2]=1;y=l+40|0;c[y>>2]=1;w=l+48|0;c[w>>2]=1;A=w;B=z;C=y;D=1;E=1;F=1;break}if(x){x=n-q|0;y=(x|0)<1?1:x;x=l+36|0;c[x>>2]=y;z=l+40|0;c[z>>2]=1;w=l+48|0;c[w>>2]=y;A=w;B=x;C=z;D=y;E=y;F=1;break}if(v){v=l+36|0;c[v>>2]=1;y=e-s|0;z=(y|0)<1?1:y;y=l+40|0;c[y>>2]=z;x=l+48|0;c[x>>2]=z;A=x;B=v;C=y;D=z;E=1;F=z;break}else{A=l+48|0;B=l+36|0;C=l+40|0;D=0;E=0;F=0;break}}else{z=n-q|0;y=(z|0)<1?1:z;z=l+36|0;c[z>>2]=y;v=e-s|0;x=(v|0)<1?1:v;v=l+40|0;c[v>>2]=x;w=aa(x,y)|0;r=l+48|0;c[r>>2]=w;A=r;B=z;C=v;D=w;E=y;F=x}}while(0);h[l>>3]=+h[a>>3];h[l+8>>3]=+h[a+8>>3];n=l+16|0;h[n>>3]=+h[a+16>>3];h[l+24>>3]=+h[a+24>>3];j=l+52|0;c[j>>2]=gg(D<<3)|0;D=l+56|0;c[D>>2]=gg(E<<3)|0;E=l+60|0;c[E>>2]=gg(F<<3)|0;F=a+48|0;x=c[F>>2]|0;y=x<<3;w=c[2632]|0;if((y|0)>(w|0)){if((w|0)>0){G=jg(c[2634]|0,y)|0}else{G=gg(y)|0}c[2634]=G;c[2632]=y;H=G;I=c[F>>2]|0}else{H=c[2634]|0;I=x}if((I|0)>0){x=c[a+52>>2]|0;a=0;do{h[H+(a<<3)>>3]=+h[x+(a<<3)>>3];a=a+1|0}while((a|0)!=(I|0))}a=c[u>>2]|0;a:do{if((a|0)==1){u=c[p>>2]|0;x=u+ -1|0;if((u|0)>(s|0)){u=c[m>>2]|0;F=c[B>>2]|0;G=aa(x,u)|0;y=aa((c[C>>2]|0)+ -1|0,F)|0;w=1-s|0;v=q+1|0;z=(u|0)<(v|0);r=(F|0)>0;J=0-u|0;K=1-q|0;L=x;x=H+(G<<3)|0;G=(c[j>>2]|0)+(y<<3)|0;while(1){y=w+L|0;if((L|0)>=(y|0)){M=L;while(1){if(r){N=+(M|0);O=0;do{P=x+(O+q<<3)|0;h[P>>3]=N*+h[P>>3];O=O+1|0}while((O|0)<(F|0))}if((M|0)>(y|0)){M=M+ -1|0}else{break}}}if(!z){M=u;while(1){y=K+M|0;O=M+ -1|0;if((M|0)>=(y|0)){P=x+(O<<3)|0;N=+h[P>>3];Q=M;while(1){S=Q+ -1|0;T=+(S|0)*N;if((Q|0)>(y|0)){N=T;Q=S}else{break}}h[P>>3]=T}if((M|0)>(v|0)){M=O}else{break}}}if(r){M=0;do{h[G+(M<<3)>>3]=+h[x+(M+q<<3)>>3];M=M+1|0}while((M|0)<(F|0))}if((L|0)>(s|0)){L=L+ -1|0;x=x+(J<<3)|0;G=G+(0-F<<3)|0}else{break}}}}else if((a|0)==2){F=c[m>>2]|0;G=c[p>>2]|0;J=((F|0)>(G|0)?F:G)+1|0;x=c[B>>2]|0;L=c[C>>2]|0;r=s+1|0;if((G|0)>=(r|0)){v=r+((x|0)>(L|0)?x:L)|0;L=1-s|0;K=q+1|0;u=1-q|0;z=G;G=H+(I<<3)|0;w=(c[j>>2]|0)+(c[A>>2]<<3)|0;while(1){M=J-z|0;Q=(M|0)<(F|0)?M:F;M=(Q|0)<0?0:Q;Q=v-z|0;y=(Q|0)<(x|0)?Q:x;Q=(y|0)<0?0:y;y=G+(0-M<<3)|0;S=w+(0-Q<<3)|0;U=L+z|0;if((z|0)>(U|0)){V=(Q|0)>0;W=q-M|0;X=z;do{X=X+ -1|0;if(V){N=+(X|0);Y=0;do{Z=G+(W+Y<<3)|0;h[Z>>3]=N*+h[Z>>3];Y=Y+1|0}while((Y|0)<(Q|0))}}while((X|0)>(U|0))}if((M|0)>=(K|0)){U=M;while(1){X=u+U|0;W=U+ -1|0;if((U|0)>=(X|0)){V=G+(W-M<<3)|0;N=+h[V>>3];Y=U;while(1){O=Y+ -1|0;_=+(O|0)*N;if((Y|0)>(X|0)){N=_;Y=O}else{break}}h[V>>3]=_}if((U|0)>(K|0)){U=W}else{break}}}if((Q|0)>0){U=q-M|0;Y=0;do{h[w+(Y-Q<<3)>>3]=+h[G+(U+Y<<3)>>3];Y=Y+1|0}while((Y|0)<(Q|0))}if((z|0)>(r|0)){z=z+ -1|0;G=y;w=S}else{break}}}}else{w=(q|0)>0;G=(s|0)>0;if(w&G){h[c[j>>2]>>3]=0.0;break}if(w){w=c[m>>2]|0;z=q+1|0;if((w|0)<(z|0)){break}r=1-q|0;K=w;w=(c[j>>2]|0)+((c[A>>2]|0)+ -1<<3)|0;while(1){u=r+K|0;L=K+ -1|0;x=H+(L<<3)|0;N=+h[x>>3];if((K|0)<(u|0)){$=N}else{ba=N;v=K;while(1){F=v+ -1|0;ca=ba*+(F|0);if((v|0)>(u|0)){ba=ca;v=F}else{break}}h[x>>3]=ca;$=ca}h[w>>3]=$;if((K|0)>(z|0)){K=L;w=w+ -8|0}else{break a}}}if(G){w=H+(I+ -1<<3)|0;K=c[j>>2]|0;z=c[p>>2]|0;r=s+1|0;if((z|0)<(r|0)){da=w}else{v=1-s|0;u=0-e|0;S=~f;y=((u|0)>(S|0)?u:S)+ -1|0;S=~z;u=I+ -3-(z+((y|0)>(S|0)?y:S))|0;S=z;z=w;while(1){w=v+S|0;if((S|0)>=(w|0)){ba=+h[z>>3];y=S;while(1){F=y+ -1|0;ea=+(F|0)*ba;if((y|0)>(w|0)){ba=ea;y=F}else{break}}h[z>>3]=ea}if((S|0)>(r|0)){S=S+ -1|0;z=z+ -8|0}else{break}}da=H+(u<<3)|0}z=c[A>>2]|0;if((z|0)>0){S=0;while(1){r=S+1|0;h[K+(S<<3)>>3]=+h[da+(r<<3)>>3];if((r|0)<(z|0)){S=r}else{break}}}}}}while(0);ea=+hd(l,b,d);if((c[t>>2]|0)==3){if((l|0)==0){k=ea;i=g;return+k}else{fa=ea}}else{d=+R(+(+h[l>>3]),+(+(q|0)));fa=ea*d*+R(+(+h[n>>3]),+(+(s|0)))}s=c[D>>2]|0;if((s|0)!=0){hg(s)}s=c[E>>2]|0;if((s|0)!=0){hg(s)}s=c[j>>2]|0;if((s|0)!=0){hg(s)}hg(l);k=fa;i=g;return+k}function jd(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,l=0.0,m=0.0,n=0,p=0.0,q=0.0,r=0,s=0,t=0;b=i;i=i+16|0;d=b;e=~~(+h[a+8>>3]+.5);if((e|0)<1){f=c[o>>2]|0;c[d>>2]=e;za(f|0,10544,d|0)|0;g=0;i=b;return g|0}f=~~(+h[a+16>>3]+.5);if((f|0)<1){j=c[o>>2]|0;c[d>>2]=f;za(j|0,10584,d|0)|0;g=0;i=b;return g|0}l=+h[a+32>>3];m=+h[a+40>>3];if(m<=l){j=c[o>>2]|0;h[k>>3]=l;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];n=d+8|0;h[k>>3]=m;c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];za(j|0,10624,d|0)|0;g=0;i=b;return g|0}p=+h[a+48>>3];q=+h[a+56>>3];if(q<=p){j=c[o>>2]|0;h[k>>3]=p;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];n=d+8|0;h[k>>3]=q;c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];za(j|0,10664,d|0)|0;g=0;i=b;return g|0}j=~~(+h[a>>3]+.5);if(!((j+ -1|0)>>>0<3)){n=c[o>>2]|0;c[d>>2]=j;za(n|0,10704,d|0)|0;g=0;i=b;return g|0}d=gg(64)|0;c[d+36>>2]=e;h[d>>3]=2.0/(m-l);h[d+8>>3]=(l+m)*-.5;c[d+40>>2]=f;h[d+16>>3]=2.0/(q-p);h[d+24>>3]=(p+q)*-.5;n=~~+h[a+24>>3];c[d+44>>2]=n;if((n|0)==1){r=aa(f,e)|0;c[d+48>>2]=r;s=r}else if((n|0)==2){r=(e|0)<(f|0)?e:f;t=(aa(f,e)|0)-((aa(r+ -1|0,r)|0)/2|0)|0;c[d+48>>2]=t;s=t}else if((n|0)==0){n=e+ -1+f|0;c[d+48>>2]=n;s=n}else{s=0}c[d+32>>2]=j;j=gg(s<<3)|0;c[d+52>>2]=j;if((s|0)>0){n=0;do{h[j+(n<<3)>>3]=+h[a+(n+8<<3)>>3];n=n+1|0}while((n|0)<(s|0))}c[d+56>>2]=gg(e<<3)|0;c[d+60>>2]=gg(f<<3)|0;g=d;i=b;return g|0}function kd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0;d=i;i=i+16|0;e=d;f=d+8|0;g=gg(2e3)|0;j=gg(2e3)|0;if((Nc(a,10744,2e3,g)|0)==0){k=gg((Dg(a|0)|0)+200|0)|0;Kg(k|0,10752,161)|0;Fg(k|0,a|0)|0;Nc(k,10744,2e3,g)|0;Nc(k,10920,2e3,j)|0;hg(k)}Nc(a,10920,2e3,j)|0;a=gg(2e3)|0;k=gg(2e3)|0;l=b+3176|0;if((+h[l>>3]>360.0?(Xc(g,10928,l)|0)==0:0)?(Xc(j,10928,l)|0)==0:0){h[l>>3]=180.0}l=b+3192|0;if((Xc(g,10944,l)|0)==0?(Xc(j,10944,l)|0)==0:0){h[l>>3]=57.29577951308232}l=0;do{c[e>>2]=l;Na(f|0,10952,e|0)|0;m=b+(l<<3)+4096|0;if((Xc(g,f,m)|0)==0){h[m>>3]=0.0}l=l+1|0}while((l|0)!=10);do{if((Zc(g,10960,2e3,a)|0)==0){if((Zc(j,10960,2e3,a)|0)==0){c[b+5960>>2]=0;break}else{c[b+5960>>2]=gd(a)|0;break}}else{c[b+5960>>2]=gd(a)|0}}while(0);do{if((Zc(j,10968,2e3,k)|0)==0){if((Zc(g,10968,2e3,k)|0)==0){c[b+5964>>2]=0;n=9;break}else{c[b+5964>>2]=gd(k)|0;n=9;break}}else{c[b+5964>>2]=gd(k)|0;n=9}}while(0);while(1){o=n+ -1|0;if(!(+h[b+(n<<3)+4096>>3]==0.0)){p=27;break}if((n|0)>0){n=o}else{p=25;break}}if((p|0)==25){c[b+3276>>2]=o}else if((p|0)==27?(c[b+3276>>2]=n,(n|0)>2):0){q=+h[b+4104>>3];p=1;r=0.0;while(1){s=+(p|0)*3.141592653589793/180.0;t=0.0;o=n;do{t=s*t+ +(o|0)*+h[b+(o<<3)+4096>>3];o=o+ -1|0}while((o|0)>0);o=p+1|0;if(t<=0.0){u=q;v=r;break}if((o|0)<181){q=t;p=o;r=s}else{u=t;v=s;break}}a:do{if(!(t<=0.0)){w=3.141592653589793}else{r=u;q=t;p=1;x=v;y=s;while(1){z=x-r*(y-x)/(q-r);A=0.0;o=n;do{A=z*A+ +(o|0)*+h[b+(o<<3)+4096>>3];o=o+ -1|0}while((o|0)>0);if(+P(+A)<1.0e-13){w=z;break a}o=A<0.0;l=p+1|0;if((l|0)<11){r=o?r:A;q=o?A:q;p=l;x=o?x:z;y=o?z:y}else{w=z;break}}}}while(0);if((n|0)>-1){p=n;s=0.0;while(1){v=w*s+ +h[b+(p<<3)+4096>>3];if((p|0)>0){p=p+ -1|0;s=v}else{B=v;break}}}else{B=0.0}h[b+3240>>3]=w;h[b+3248>>3]=B}ac(b);hg(g);hg(j);hg(a);hg(k);if((c[b+5964>>2]|0)==0?(c[b+5960>>2]|0)==0:0){C=1;i=d;return C|0}C=0;i=d;return C|0} + + + +function ld(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,U=0.0,X=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0;g=i;j=a- +h[d+616>>3];a=b- +h[d+624>>3];do{if((c[d+3300>>2]|0)==0){b=+h[d+760>>3];if(!(b==0.0)?(k=+h[d+768>>3],!(k==0.0)):0){l=j*b;b=a*k;k=+h[d+48>>3];if(!(k!=0.0)){m=l;n=b;break}o=k*3.141592653589793/180.0;k=+S(+o);p=+T(+o);m=l*k-b*p;n=b*k+l*p;break}h[e>>3]=0.0;h[f>>3]=0.0;q=2;i=g;return q|0}else{m=j*+h[d+56>>3]+a*+h[d+64>>3];n=j*+h[d+72>>3]+a*+h[d+80>>3]}}while(0);r=(c[d+3304>>2]|0)==0|0;s=r^1;a=(90.0- +h[d+(r<<3)+688>>3])*3.141592653589793/180.0;j=+S(+a);p=+T(+a);l=+h[d+3176>>3]*3.141592653589793/180.0;r=c[d+3276>>2]|0;t=c[d+5960>>2]|0;if((t|0)==0){u=m}else{u=m+ +hd(t,m,n)}t=c[d+5964>>2]|0;if((t|0)==0){v=n}else{v=n+ +hd(t,m,n)}n=+Q(+(u*u+v*v));m=n/+h[d+3192>>3];if((r|0)<1){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}a:do{if((r|0)==2){n=+h[d+4112>>3];k=+h[d+4104>>3];b=k*k-n*4.0*(+h[d+4096>>3]-m);if(b<0.0){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}o=+Q(+b);b=n*2.0;n=(o-k)/b;w=(-k-o)/b;b=nw?n:w}else{x=b}if(x<0.0){if(!(x<-1.0e-13)){y=0.0;break}h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if(x>3.141592653589793){if(x>3.141592653589893){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}else{y=3.141592653589793}}else{y=x}}else if((r|0)==1){y=(m- +h[d+4096>>3])/+h[d+4104>>3]}else{b=+h[d+4096>>3];w=+h[d+3240>>3];n=+h[d+3248>>3];if(m>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if(m>n){if(!(m>n+1.0e-13)){y=w;break}h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if((r|0)>-1){z=0;A=b;B=n;C=0.0;D=w}else{o=0.0-m;t=0;k=b;b=n;n=0.0;E=w;while(1){w=(b-m)/(b-k);if(!(w<.1)){if(w>.9){F=.9}else{F=w}}else{F=.1}w=E-(E-n)*F;if(m>0.0){if(m<1.0e-13){y=w;break a}else{G=0.0;H=b;I=w;J=E}}else{if(o<1.0e-13){y=w;break a}else{G=k;H=0.0;I=n;J=w}}K=t+1|0;if(!(+P(+(J-I))<1.0e-13)&(K|0)<100){t=K;k=G;b=H;n=I;E=J}else{y=w;break a}}}while(1){E=(B-m)/(B-A);if(!(E<.1)){if(E>.9){L=.9}else{L=E}}else{L=.1}E=D-(D-C)*L;t=r;n=0.0;while(1){n=E*n+ +h[d+(t<<3)+4096>>3];if((t|0)<=0){break}else{t=t+ -1|0}}if(n>3];R=U+Z*180.0/3.141592653589793;if(!(U>=0.0)){if(R>0.0){_=R+-360.0}else{_=R}}else{if(R<0.0){_=R+360.0}else{_=R}}if(!(_>360.0)){if(_<-360.0){$=_+360.0}else{$=_}}else{$=_+-360.0}do{if(+qa(+m,3.141592653589793)==0.0){_=(v+a*l)*180.0/3.141592653589793;if(_>90.0){aa=180.0-_}else{aa=_}if(aa<-90.0){ba=-180.0-aa}else{ba=aa}}else{_=j*u+p*y*l;if(!(+P(+_)>.99)){ba=+W(+_)*180.0/3.141592653589793;break}R=+V(+(+Q(+(D*D+X*X))));if(!(_>=0.0)){ba=R*-180.0/3.141592653589793;break}else{ba=R*180.0/3.141592653589793;break}}}while(0);h[e>>3]=$;h[f>>3]=ba;q=0;i=g;return q|0}function md(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0,U=0.0,X=0.0,Z=0.0,_=0,$=0.0,aa=0.0,ba=0.0;g=i;j=d+3304|0;k=(c[j>>2]|0)==0|0;l=(a- +h[d+((k^1)<<3)+688>>3])*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+l);m=+T(+l);n=+S(+a);o=+T(+a);p=(90.0- +h[d+(k<<3)+688>>3])*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=+h[d+3176>>3];if(s==999.0){t=3.141592653589793}else{t=s*3.141592653589793/180.0}s=n*q;u=o*r-b*s;if(+P(+u)<1.0e-5){v=(1.0-b)*s- +S(+(a+p))}else{v=u}u=m*n;if(v!=0.0|u!=-0.0){w=+Y(+-u,+v)}else{w=l+-3.141592653589793}m=t+w;if(!(m>3.141592653589793)){if(m<-3.141592653589793){x=m+6.283185307179586}else{x=m}}else{x=m+-6.283185307179586}do{if(+qa(+l,3.141592653589793)==0.0){m=a+b*p;if(m>1.5707963267948966){y=3.141592653589793-m}else{y=m}if(y<-1.5707963267948966){z=-3.141592653589793-y}else{z=y}}else{m=o*q+b*n*r;if(!(+P(+m)>.99)){z=+W(+m);break}w=+V(+(+Q(+(u*u+v*v))));if(!(m>=0.0)){z=-w}else{z=w}}}while(0);v=1.5707963267948966-z;z=(v*(v*(v*(v*(v*(v*(v*(v*(v*(v*0.0+ +h[d+4168>>3])+ +h[d+4160>>3])+ +h[d+4152>>3])+ +h[d+4144>>3])+ +h[d+4136>>3])+ +h[d+4128>>3])+ +h[d+4120>>3])+ +h[d+4112>>3])+ +h[d+4104>>3])+ +h[d+4096>>3])*+h[d+3192>>3];k=d+5960|0;A=c[k>>2]|0;B=d+5964|0;if((A|0)==0?(c[B>>2]|0)==0:0){C=(c[j>>2]|0)==0;v=z*+T(+x);u=-(z*+S(+x));D=C?v:u;E=C?u:v}else{v=z*+T(+x);u=z*+S(+x);C=A;A=1;x=v;z=-u;while(1){if((C|0)==0){F=x;G=1.0;H=0.0}else{r=x+ +hd(C,x,z);n=+id(c[k>>2]|0,x,z,1,0)+1.0;F=r;G=n;H=+id(c[k>>2]|0,x,z,0,1)}n=F-v;I=c[B>>2]|0;if((I|0)==0){J=z;K=0.0;L=1.0}else{r=z+ +hd(I,x,z);b=+id(c[B>>2]|0,x,z,1,0);J=r;K=b;L=+id(c[B>>2]|0,x,z,0,1)+1.0}b=u+J;r=G*L-H*K;if(r==0.0){M=x;N=z;break}q=(H*b-n*L)/r;o=(n*K-G*b)/r;r=x+q;y=z+o;I=+P(+q)>+P(+o);p=I?q:o;o=+P(+p);I=+P(+n)>+P(+b);q=I?n:b;I=o>+P(+q);if(!(!(+P(+(I?p:q))<2.8e-8)&(A|0)<500)){M=r;N=y;break}C=c[k>>2]|0;A=A+1|0;x=r;z=y}A=(c[j>>2]|0)==0;D=A?M:N;E=A?N:M}if((c[d+3300>>2]|0)!=0){h[e>>3]=D*+h[d+88>>3]+E*+h[d+96>>3];h[f>>3]=D*+h[d+104>>3]+E*+h[d+112>>3];O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}M=+h[d+48>>3];if(M!=0.0){N=M*3.141592653589793/180.0;M=+S(+N);z=+T(+N);h[e>>3]=D*M+E*z;ba=E*M-D*z}else{h[e>>3]=D;ba=E}h[f>>3]=ba;ba=+h[d+32>>3];if(ba!=0.0){h[e>>3]=+h[e>>3]/ba}ba=+h[d+40>>3];if(!(ba!=0.0)){O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}h[f>>3]=+h[f>>3]/ba;O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}function nd(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0;f=i;g=(+h[c+224>>3]-(+h[c+176>>3]+a+-1.0+.5)*+h[c+192>>3])/1.0e3;a=((+h[c+184>>3]+b+-1.0+.5)*+h[c+200>>3]- +h[c+248>>3])/1.0e3;b=g*g;j=a*a;k=g*b;l=a*j;m=b+j;n=(k*+h[c+496>>3]+(l*+h[c+472>>3]+(m*+h[c+464>>3]+(b*+h[c+456>>3]+(+h[c+432>>3]+(a*+h[c+416>>3]+g*+h[c+424>>3])+j*+h[c+440>>3]+a*g*+h[c+448>>3])))+g*j*+h[c+480>>3]+b*a*+h[c+488>>3])+m*a*+h[c+504>>3]+m*m*a*+h[c+512>>3])/206264.8062470964;o=+h[c+160>>3];p=+U(+o);q=1.0-n*p;r=+Y(+((l*+h[c+336>>3]+(k*+h[c+312>>3]+(m*+h[c+304>>3]+(j*+h[c+296>>3]+(+h[c+272>>3]+(g*+h[c+256>>3]+a*+h[c+264>>3])+b*+h[c+280>>3]+a*g*+h[c+288>>3])))+a*b*+h[c+320>>3]+j*g*+h[c+328>>3])+m*g*+h[c+344>>3]+m*m*g*+h[c+352>>3])/206264.8062470964/+S(+o)),+q);o=r+ +h[c+152>>3];if(!(o<0.0)){s=o;t=s/.01745329252;h[d>>3]=t;u=+S(+r);v=n+p;w=v/q;x=u*w;y=+X(+x);z=y/.01745329252;h[e>>3]=z;i=f;return 0}s=o+6.28318530717959;t=s/.01745329252;h[d>>3]=t;u=+S(+r);v=n+p;w=v/q;x=u*w;y=+X(+x);z=y/.01745329252;h[e>>3]=z;i=f;return 0}function od(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,Q=0.0,R=0.0,U=0.0,V=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0;f=i;h[d>>3]=0.0;h[e>>3]=0.0;g=b*3.141592653589793/180.0;b=+T(+g);j=+S(+g);k=c+160|0;g=+h[k>>3];if(g==0.0){l=+h[c+8>>3]*3.141592653589793/180.0;h[k>>3]=l;m=l}else{m=g}g=+T(+m);l=+S(+m);k=c+152|0;m=+h[k>>3];if(m==0.0){n=+h[c+8>>3]*3.141592653589793/180.0;h[k>>3]=n;o=n}else{o=m}m=a*3.141592653589793/180.0-o;o=+S(+m);a=b*g+j*l*o;if(a==0.0){p=1;i=f;return p|0}n=j*+T(+m)*206264.8062470964/a;m=(b*l-j*g*o)*206264.8062470964/a;a=+h[c+168>>3];if(a==0.0){p=1;i=f;return p|0}o=+h[c+256>>3];g=+h[c+264>>3];j=+h[c+272>>3];l=+h[c+280>>3];b=+h[c+288>>3];q=+h[c+296>>3];r=+h[c+304>>3];s=+h[c+312>>3];t=+h[c+320>>3];u=+h[c+328>>3];v=+h[c+336>>3];w=+h[c+344>>3];x=+h[c+352>>3];y=l*2.0;z=r*2.0;A=s*3.0;B=t*2.0;C=q*2.0;D=u*2.0;E=v*3.0;F=w*2.0;G=x*4.0;H=+h[c+416>>3];I=+h[c+424>>3];J=+h[c+432>>3];K=+h[c+440>>3];L=+h[c+448>>3];M=+h[c+456>>3];N=+h[c+464>>3];O=+h[c+472>>3];Q=+h[c+480>>3];R=+h[c+488>>3];U=+h[c+496>>3];V=+h[c+504>>3];W=+h[c+512>>3];X=M*2.0;Y=N*2.0;Z=R*2.0;_=U*3.0;$=V*2.0;aa=W*4.0;ba=K*2.0;ca=O*3.0;da=Q*2.0;k=0;ea=n/a;fa=m/a;do{a=fa*ea;ga=ea*ea;ha=fa*fa;ia=fa*ga;ja=ha*ea;ka=ha+ga;la=ka*ka;ma=ea*ga;na=fa*ha;oa=ga*ga;pa=ha*ha;qa=ha*ga*6.0;ra=ha*u+(fa*b+(o+ea*y)+ea*z+ga*A+a*B)+(ha+ga*3.0)*w+(pa+(oa*5.0+qa))*x;sa=g+ea*b+fa*C+fa*z+ga*t+a*D+ha*E+a*F+ka*a*G;ta=I+fa*L+ea*X+ea*Y+ha*Q+a*Z+ga*_+a*$+ka*a*aa;ua=ga*R+(ea*L+(H+fa*ba)+fa*Y+ha*ca+a*da)+(ha*3.0+ga)*V+(oa+(pa*5.0+qa))*W;qa=j+(ea*o+fa*g)+ga*l+a*b+ha*q+ka*r+ma*s+ia*t+ja*u+na*v+ka*ea*w+la*ea*x-n;pa=J+(fa*H+ea*I)+ha*K+a*L+ga*M+ka*N+na*O+ja*Q+ia*R+ma*U+ka*fa*V+la*fa*W-m;la=ra*ua-sa*ta;ka=(sa*pa-qa*ua)/la;ua=(qa*ta-ra*pa)/la;ea=ea+ka;fa=fa+ua;if(+P(+ka)<5.0e-7?+P(+ua)<5.0e-7:0){break}k=k+1|0}while((k|0)<50);m=+h[c+192>>3];if(m==0.0){p=1;i=f;return p|0}W=+h[c+200>>3];if(W==0.0){p=1;i=f;return p|0}V=(fa*1.0e3+ +h[c+248>>3])/W;h[d>>3]=(+h[c+224>>3]-ea*1.0e3)/m- +h[c+176>>3]+1.0+-.5;m=V- +h[c+184>>3]+1.0+-.5;h[e>>3]=m;V=+h[d>>3];if(V<.5){p=-1;i=f;return p|0}if(V>+h[c+136>>3]+.5|m<.5){p=-1;i=f;return p|0}if(m>+h[c+144>>3]+.5){p=-1;i=f;return p|0}p=0;i=f;return p|0}function pd(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;i=i+16|0;e=d;d=c[o>>2]|0;c[e>>2]=a;c[e+4>>2]=b;za(d|0,10976,e|0)|0;hb(-1)}function qd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;f=i;i=i+544|0;g=f;h=f+24|0;j=f+8|0;k=ig(1,28)|0;if((k|0)==0){pd(10992,11016)}c[k+16>>2]=b;if((b|0)>4){c[g>>2]=b;c[g+4>>2]=4;Na(h|0,11040,g|0)|0;pd(11120,h)}if((b|0)==0){l=k+12|0}else{m=gg(b<<2)|0;n=k+12|0;c[n>>2]=m;if((m|0)==0){pd(10992,11136)}m=a;a=b;o=c[n>>2]|0;while(1){p=a+ -1|0;c[o>>2]=(c[m>>2]|0)+ -1;if((p|0)==0){l=n;break}else{m=m+4|0;a=p;o=o+4|0}}}c[k+24>>2]=e;a:do{if((e|0)!=0){o=c[l>>2]|0;a=e<<2;m=gg(a)|0;c[k+20>>2]=m;if((m|0)==0){pd(10992,11176)}Eg(j|0,0,a|0)|0;b:do{if((b|0)>0){a=0;while(1){m=c[o+(a<<2)>>2]|0;if((m|0)>=(e|0)){break}n=j+(m<<2)|0;c[n>>2]=(c[n>>2]|0)+1;a=a+1|0;if((a|0)>=(b|0)){break b}}pd(11216,11256)}}while(0);o=k+8|0;c[o>>2]=1;if((e|0)>0){a=c[k+20>>2]|0;n=d;m=1;p=0;while(1){q=n+4|0;r=c[n>>2]|0;c[a+(p<<2)>>2]=r;if((r|0)>10){break}s=c[j+(p<<2)>>2]|0;if((r|0)==0){t=1;u=1}else{v=r;w=1;x=1;while(1){y=aa(x,v+s|0)|0;z=v+ -1|0;A=aa(w,v)|0;if((z|0)==0){t=A;u=y;break}else{v=z;w=A;x=y}}}x=aa(m,(u|0)/(t|0)|0)|0;c[o>>2]=x;w=p+1|0;if((w|0)<(e|0)){n=q;m=x;p=w}else{B=x;break a}}c[g>>2]=r;c[g+4>>2]=10;Na(h|0,11264,g|0)|0;pd(11120,h)}else{B=1}}else{c[k+8>>2]=1;B=1}}while(0);h=gg(B<<3)|0;c[k>>2]=h;if((h|0)==0){pd(10992,11336)}h=ig(B,8)|0;c[k+4>>2]=h;if((h|0)==0){pd(10992,11376)}else{i=f;return k|0}return 0}function rd(a){a=a|0;var b=0;b=i;if((a|0)==0){i=b;return}hg(c[a+4>>2]|0);hg(c[a>>2]|0);hg(c[a+20>>2]|0);hg(c[a+12>>2]|0);hg(a);i=b;return}function sd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0.0,z=0.0,A=0,B=0,C=0,D=0;d=i;i=i+80|0;e=d;f=d+60|0;g=d+40|0;j=c[a+16>>2]|0;k=c[a>>2]|0;l=c[a+4>>2]|0;m=c[a+12>>2]|0;n=c[a+20>>2]|0;if((j|0)!=0){o=j+ -1|0;if((o|0)!=0){p=o;o=f;q=e;do{q=q+8|0;h[q>>3]=1.0;o=o+4|0;c[o>>2]=0;p=p+ -1|0}while((p|0)!=0)}p=c[a+24>>2]|0;if((p|0)!=0){o=n;n=p;p=g;while(1){n=n+ -1|0;c[p>>2]=c[o>>2];if((n|0)==0){break}else{o=o+4|0;p=p+4|0}}}p=g+(c[m>>2]<<2)|0;o=c[p>>2]|0;if((o|0)!=0){c[p>>2]=o+ -1}}o=l+8|0;r=+h[l>>3];l=k+8|0;h[k>>3]=1.0;c[f>>2]=1;s=+h[b>>3];h[e>>3]=s;k=(c[a+8>>2]|0)+ -1|0;if((k|0)==0){t=r;i=d;return+t}if((j|0)>0){u=s;v=k;w=l;x=o;y=r}else{z=s;a=k;k=l;l=o;s=r;while(1){h[k>>3]=z;r=s+z*+h[l>>3];o=a+ -1|0;if((o|0)==0){t=r;break}z=+h[e>>3];a=o;k=k+8|0;l=l+8|0;s=r}i=d;return+t}while(1){l=w+8|0;h[w>>3]=u;k=x+8|0;s=y+u*+h[x>>3];a=0;o=f;p=m;n=b;q=e;while(1){A=g+(c[p>>2]<<2)|0;B=c[A>>2]|0;c[A>>2]=B+ -1;C=c[o>>2]|0;if((B|0)!=0){D=13;break}c[g+(c[p>>2]<<2)>>2]=C;c[o>>2]=0;h[q>>3]=1.0;B=a+1|0;if((B|0)>=(j|0)){break}a=B;o=o+4|0;p=p+4|0;n=n+8|0;q=q+8|0}if((D|0)==13?(D=0,c[o>>2]=C+1,z=+h[n>>3]*+h[q>>3],h[q>>3]=z,(a|0)!=0):0){p=a;B=q;do{B=B+ -8|0;p=p+ -1|0;h[B>>3]=z}while((p|0)!=0)}p=v+ -1|0;if((p|0)==0){t=s;break}u=+h[e>>3];v=p;w=l;x=k;y=s}i=d;return+t}function td(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0.0,D=0.0,E=0,F=0,G=0,H=0,I=0.0,J=0,K=0,L=0,M=0;j=i;i=i+32|0;k=j;l=(b|0)!=0;m=(g|0)==0;if(m&(l^1)){pd(11416,11496)}n=c[a+8>>2]|0;o=c[a+16>>2]|0;p=aa(n,n)|0;q=c[a>>2]|0;r=ig(p,8)|0;if((r|0)==0){pd(10992,11512)}p=ig(n,8)|0;if((p|0)==0){pd(10992,11544)}if((f|0)!=0){s=(n|0)==0;t=(o|0)>0;u=e;e=d;d=f;f=g;g=b;while(1){b=d+ -1|0;if(l){if(t){v=0;w=g;while(1){h[k+(v<<3)>>3]=+h[w>>3];v=v+1|0;if((v|0)==(o|0)){break}else{w=w+8|0}}x=g+(o<<3)|0}else{x=g}+sd(a,k);if(m|s){y=f;z=x}else{w=q;v=f;A=n;while(1){A=A+ -1|0;h[v>>3]=+h[w>>3];if((A|0)==0){break}else{w=w+8|0;v=v+8|0}}y=f+(n<<3)|0;z=x}}else{if(s){y=f;z=g}else{v=q;w=f;A=n;while(1){A=A+ -1|0;h[v>>3]=+h[w>>3];if((A|0)==0){break}else{v=v+8|0;w=w+8|0}}y=f+(n<<3)|0;z=g}}if((u|0)==0){B=0;C=1.0}else{B=u+8|0;C=+h[u>>3]}w=e+8|0;D=+h[e>>3];if(!s){v=n;A=r;E=q;F=p;while(1){G=v+ -1|0;H=E+8|0;I=C*+h[E>>3];J=F+8|0;h[F>>3]=+h[F>>3]+D*I;K=A;L=q;M=n;while(1){M=M+ -1|0;h[K>>3]=+h[K>>3]+I*+h[L>>3];if((M|0)==0){break}else{K=K+8|0;L=L+8|0}}if((G|0)==0){break}else{v=G;A=A+(n<<3)|0;E=H;F=J}}}if((b|0)==0){break}else{u=B;e=w;d=b;f=y;g=z}}}ud(r,p,n);hg(r);if((n|0)==0){hg(p);i=j;return}r=p;z=c[a+4>>2]|0;a=n;while(1){a=a+ -1|0;h[z>>3]=+h[r>>3];if((a|0)==0){break}else{r=r+8|0;z=z+8|0}}hg(p);i=j;return}function ud(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=i;if((vd(a,b,c)|0)==0){i=d;return}e=c<<3;f=gg(aa(e,c)|0)|0;if((f|0)==0){pd(10992,11576)}g=gg(e)|0;if((g|0)==0){pd(10992,11600)}wd(a,b,c,c,f,g);hg(f);hg(g);i=d;return}function vd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0;d=i;e=gg(c<<3)|0;if((e|0)==0){pd(10992,11624)}f=(c|0)>0;if(f){g=0;a:do{j=aa(g,c)|0;k=e+(g<<3)|0;if((g|0)>0){l=g;do{m=aa(l,c)|0;n=g;o=+h[a+(l+j<<3)>>3];do{n=n+ -1|0;o=o- +h[a+(n+j<<3)>>3]*+h[a+(n+m<<3)>>3]}while((n|0)>0);if((g|0)==(l|0)){if(o<=0.0){p=15;break a}h[k>>3]=+Q(+o)}else{h[a+((aa(l,c)|0)+g<<3)>>3]=o/+h[k>>3]}l=l+1|0}while((l|0)<(c|0))}else{l=g;do{q=+h[a+(l+j<<3)>>3];if((g|0)==(l|0)){if(q<=0.0){p=15;break a}h[k>>3]=+Q(+q)}else{h[a+((aa(l,c)|0)+g<<3)>>3]=q/+h[k>>3]}l=l+1|0}while((l|0)<(c|0))}g=g+1|0}while((g|0)<(c|0));if((p|0)==15){hg(e);r=-1;i=d;return r|0}if(f){p=0;do{g=b+(p<<3)|0;q=+h[g>>3];if((p|0)>0){l=aa(p,c)|0;k=p;s=q;while(1){j=k+ -1|0;t=s- +h[a+(j+l<<3)>>3]*+h[b+(j<<3)>>3];if((j|0)>0){k=j;s=t}else{u=t;break}}}else{u=q}h[g>>3]=u/+h[e+(p<<3)>>3];p=p+1|0}while((p|0)!=(c|0));if(f){f=c;while(1){p=f+ -1|0;k=b+(p<<3)|0;u=+h[k>>3];if((f|0)<(c|0)){l=f;s=u;while(1){t=+h[a+((aa(l,c)|0)+p<<3)>>3];v=s-t*+h[b+(l<<3)>>3];j=l+1|0;if((j|0)==(c|0)){w=v;break}else{l=j;s=v}}}else{w=u}h[k>>3]=w/+h[e+(p<<3)>>3];if((p|0)>0){f=p}else{break}}}}}hg(e);r=0;i=d;return r|0}function wd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0.0,B=0.0,C=0,D=0.0,E=0.0,F=0.0,G=0,H=0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,S=0.0,T=0,U=0,V=0,W=0,X=0.0,Y=0,Z=0,_=0,$=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0.0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0.0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0.0,Fa=0.0,Ga=0.0,Ha=0.0,Ia=0.0,Ja=0.0,Ka=0.0,La=0.0,Ma=0.0,Na=0.0,Oa=0.0,Pa=0,Qa=0,Ra=0.0,Sa=0,Ta=0.0,Ua=0,Va=0,Wa=0.0;g=i;if((c|0)<(d|0)){pd(11648,11704)}j=d<<3;k=gg(j)|0;if((k|0)==0){pd(10992,11720)}l=gg(j)|0;if((l|0)==0){pd(10992,11744)}j=(d|0)>0;a:do{if(j){m=c+1|0;n=0.0;o=0.0;p=0;q=0.0;while(1){r=p+1|0;s=d-r|0;t=k+(p<<3)|0;h[t>>3]=o*q;u=c-p|0;b:do{if((u|0)>0?(v=a+((aa(p,m)|0)<<3)|0,w=(p|0)==(c|0),!w):0){x=v;y=u;z=0.0;while(1){y=y+ -1|0;z=z+ +P(+(+h[x>>3]));if((y|0)==0){break}else{x=x+8|0}}if(z!=0.0){if(w){A=0.0}else{x=v;y=u;B=0.0;while(1){C=y+ -1|0;D=+h[x>>3]/z;h[x>>3]=D;E=B+D*D;if((C|0)==0){A=E;break}else{x=x+8|0;y=C;B=E}}}B=+h[v>>3];E=+P(+(+Q(+A)));if(!(B>=0.0)){F=-E}else{F=E}E=-F;D=B*E-A;h[v>>3]=B+F;if((r|0)!=(d|0)){y=s;x=a+((aa(r,c)|0)+p<<3)|0;while(1){y=y+ -1|0;c:do{if(!w){C=v;G=x;H=u;B=0.0;while(1){I=H+ -1|0;J=B+ +h[G>>3]*+h[C>>3];if((I|0)==0){break}C=C+8|0;G=G+8|0;H=I;B=J}B=J/D;if(!w){H=v;G=x;C=u;while(1){I=C+ -1|0;h[G>>3]=+h[G>>3]+B*+h[H>>3];if((I|0)==0){break c}H=H+8|0;G=G+8|0;C=I}}}}while(0);if((y|0)==0){break}else{x=x+(c<<3)|0}}}if(w){K=E;L=z}else{x=v;y=u;while(1){C=y+ -1|0;h[x>>3]=z*+h[x>>3];if((C|0)==0){K=E;L=z;break b}x=x+8|0;y=C}}}else{K=0.0;L=z}}else{K=0.0;L=0.0}}while(0);E=K*L;u=f+(p<<3)|0;h[u>>3]=E;if(!((p|0)>=(c|0)|(r|0)==(d|0))){y=aa(r,c)|0;x=a+(y+p<<3)|0;v=x;w=s;D=0.0;while(1){w=w+ -1|0;D=D+ +P(+(+h[v>>3]));if((w|0)==0){break}else{v=v+(c<<3)|0}}if(D!=0.0){v=x;w=s;B=0.0;while(1){w=w+ -1|0;M=+h[v>>3]/D;h[v>>3]=M;B=B+M*M;if((w|0)==0){break}else{v=v+(c<<3)|0}}M=+h[x>>3];N=+P(+(+Q(+B)));if(!(M>=0.0)){O=-N}else{O=N}N=-O;R=M*N-B;S=M+O;h[x>>3]=S;v=k+(r<<3)|0;M=S;w=x;C=s;G=v;while(1){H=C+ -1|0;h[G>>3]=M/R;I=w+(c<<3)|0;if((H|0)==0){break}M=+h[I>>3];w=I;C=H;G=G+8|0}if((r|0)==(c|0)){T=x;U=s}else{G=c-r|0;C=a+(y+r<<3)|0;while(1){w=G+ -1|0;H=x;I=C;V=s;M=0.0;while(1){W=V+ -1|0;X=M+ +h[I>>3]*+h[H>>3];if((W|0)==0){Y=C;Z=s;_=v;break}H=H+(c<<3)|0;I=I+(c<<3)|0;V=W;M=X}while(1){Z=Z+ -1|0;h[Y>>3]=+h[Y>>3]+X*+h[_>>3];if((Z|0)==0){break}else{Y=Y+(c<<3)|0;_=_+8|0}}if((w|0)==0){T=x;U=s;break}else{G=w;C=C+8|0}}}while(1){C=U+ -1|0;h[T>>3]=D*+h[T>>3];if((C|0)==0){break}T=T+(c<<3)|0;U=C}$=+h[u>>3];ba=N;ca=D}else{$=E;ba=0.0;ca=D}}else{$=E;ba=0.0;ca=0.0}M=+P(+$);z=M+ +P(+(+h[t>>3]));da=n>z?n:z;if((r|0)==(d|0)){break}else{n=da;o=ba;p=r;q=ca}}p=d+ -1|0;if(j){q=ba;m=p;C=0;G=d;s=0;while(1){do{if((m|0)<(p|0)){if(q!=0.0){x=a+(m+(aa(G,c)|0)<<3)|0;v=e+((aa(m,d)|0)+G<<3)|0;y=e+((aa(G,d)|0)+G<<3)|0;o=+h[x>>3];n=q*o;V=(s|0)==0;if(V){break}else{ea=o;fa=x;ga=s;ha=v}while(1){I=ga+ -1|0;h[ha>>3]=ea/n;H=fa+(c<<3)|0;if((I|0)==0){break}ea=+h[H>>3];fa=H;ga=I;ha=ha+8|0}if(V){break}else{ia=s;ja=y}while(1){ia=ia+ -1|0;w=x;I=s;n=0.0;H=ja;while(1){W=I+ -1|0;ka=n+ +h[w>>3]*+h[H>>3];if((W|0)==0){la=s;ma=v;na=ja;break}w=w+(c<<3)|0;I=W;n=ka;H=H+8|0}while(1){la=la+ -1|0;h[na>>3]=+h[na>>3]+ka*+h[ma>>3];if((la|0)==0){break}else{ma=ma+8|0;na=na+8|0}}if((ia|0)==0){break}else{ja=ja+(d<<3)|0}}}if((s|0)!=0){v=s;x=e+(m+(aa(G,d)|0)<<3)|0;y=e+((aa(m,d)|0)+G<<3)|0;while(1){v=v+ -1|0;h[y>>3]=0.0;h[x>>3]=0.0;if((v|0)==0){break}else{x=x+(d<<3)|0;y=y+8|0}}}}}while(0);h[e+((aa(m,d)|0)+m<<3)>>3]=1.0;s=d-m|0;C=C+1|0;if((C|0)==(d|0)){break}else{r=m;q=+h[k+(m<<3)>>3];m=m+ -1|0;G=r}}if(j){G=~d;m=~c;C=(G|0)>(m|0)?G:m;m=a+((aa(-2-C|0,c)|0)+ -2-C<<3)|0;G=-8-(c<<3)|0;s=(C+c<<3)+16|0;p=~C;C=d;r=0;while(1){t=m+(aa(G,r)|0)|0;u=s+(r<<3)|0;y=C+ -1|0;x=d-C|0;v=c-y|0;q=+h[f+(y<<3)>>3];V=(aa(y,c)|0)+y|0;H=a+(V<<3)|0;I=a+(V+c<<3)|0;V=(C|0)==(d|0);if(!V){w=I;W=x;while(1){W=W+ -1|0;h[w>>3]=0.0;if((W|0)==0){break}else{w=w+(c<<3)|0}}}d:do{if(q!=0.0){E=1.0/q;if(!V){w=v+ -1|0;W=(w|0)==0;oa=(y|0)==(c|0);pa=x;qa=I;while(1){pa=pa+ -1|0;if(W){ra=0.0}else{sa=w;ta=H;ua=qa;D=0.0;while(1){va=ta+8|0;wa=ua+8|0;N=D+ +h[va>>3]*+h[wa>>3];xa=sa+ -1|0;if((xa|0)==0){ra=N;break}else{sa=xa;ta=va;ua=wa;D=N}}}D=+h[H>>3];N=E*(ra/D);e:do{if(!oa){n=D;ua=H;ta=qa;sa=v;while(1){wa=sa+ -1|0;va=ua+8|0;h[ta>>3]=+h[ta>>3]+N*n;if((wa|0)==0){break e}n=+h[va>>3];ua=va;ta=ta+8|0;sa=wa}}}while(0);if((pa|0)==0){break}else{qa=qa+(c<<3)|0}}}if((y|0)!=(c|0)){qa=H;pa=v;while(1){oa=pa+ -1|0;h[qa>>3]=E*+h[qa>>3];if((oa|0)==0){break d}qa=qa+8|0;pa=oa}}}else{if((y|0)!=(c|0)){Eg(t|0,0,u|0)|0}}}while(0);h[H>>3]=+h[H>>3]+1.0;u=r+1|0;if((u|0)==(p|0)){break}else{C=y;r=u}}if(j){r=(c|0)==0;C=d;p=0;f:while(1){s=C+ -1|0;G=f+(s<<3)|0;m=C+ -2|0;u=f+(m<<3)|0;t=k+(m<<3)|0;v=k+(s<<3)|0;I=0;x=p;while(1){V=s;pa=x;while(1){if(!((V|0)>-1)){ya=pa;za=93;break}qa=V+ -1|0;if(da+ +P(+(+h[k+(V<<3)>>3]))==da){Aa=qa;break}if(da+ +P(+(+h[f+(qa<<3)>>3]))==da){ya=qa;za=93;break}else{V=qa;pa=qa}}g:do{if((za|0)==93){za=0;pa=a+((aa(ya,c)|0)<<3)|0;if((V|0)>(s|0)){Aa=ya}else{qa=a+((aa(V,c)|0)<<3)|0;oa=V;q=1.0;while(1){E=q*+h[k+(oa<<3)>>3];N=+P(+E);if(da+N==da){Aa=ya;break g}w=f+(oa<<3)|0;D=+h[w>>3];n=+P(+D);if(!(N>n)){if(D!=0.0){o=N/n;Ba=n*+Q(+(o*o+1.0))}else{Ba=0.0}}else{o=n/N;Ba=N*+Q(+(o*o+1.0))}h[w>>3]=Ba;o=1.0/Ba;N=D*o;D=-(E*o);if(!r){w=pa;W=qa;sa=c;while(1){sa=sa+ -1|0;o=+h[W>>3];E=+h[w>>3];h[w>>3]=o*D+N*E;h[W>>3]=N*o-E*D;if((sa|0)==0){break}else{w=w+8|0;W=W+8|0}}}if((oa|0)>=(s|0)){Aa=ya;break g}qa=qa+(c<<3)|0;oa=oa+1|0;q=D}}}}while(0);Ca=+h[G>>3];if((V|0)==(s|0)){za=105;break}if((I|0)==99){break f}q=+h[f+(V<<3)>>3];N=+h[u>>3];E=+h[t>>3];o=+h[v>>3];n=((N-Ca)*(Ca+N)+(E-o)*(E+o))/(N*o*2.0);E=+P(+n);if(E>1.0){z=1.0/E;Da=E*+Q(+(z*z+1.0))}else{Da=+Q(+(E*E+1.0))}E=+P(+Da);if(!(n>=0.0)){Ea=-E}else{Ea=E}E=((q-Ca)*(Ca+q)+o*(N/(n+Ea)-o))/q;if((V|0)>(m|0)){Fa=E;Ga=q}else{oa=a+((aa(V,c)|0)<<3)|0;o=1.0;n=E;qa=V;E=1.0;pa=e+((aa(V,d)|0)<<3)|0;N=q;while(1){W=qa+1|0;q=+h[k+(W<<3)>>3];z=+h[f+(W<<3)>>3];M=E*q;R=o*q;q=+P(+n);B=+P(+M);if(!(q>B)){if(M!=0.0){S=q/B;Ha=B*+Q(+(S*S+1.0))}else{Ha=0.0}}else{S=B/q;Ha=q*+Q(+(S*S+1.0))}h[k+(qa<<3)>>3]=Ha;S=n/Ha;q=M/Ha;M=N*S+R*q;B=R*S-N*q;R=z*q;Ia=z*S;w=pa+(d<<3)|0;sa=d;ta=w;ua=pa;while(1){sa=sa+ -1|0;z=+h[ta>>3];Ja=+h[ua>>3];h[ua>>3]=q*z+S*Ja;h[ta>>3]=S*z-q*Ja;if((sa|0)==0){break}else{ta=ta+8|0;ua=ua+8|0}}Ja=+P(+M);z=+P(+R);do{if(!(Ja>z)){if(R!=0.0){Ka=Ja/z;La=z*+Q(+(Ka*Ka+1.0));za=130;break}else{h[f+(qa<<3)>>3]=0.0;Ma=S;Na=q;break}}else{Ka=z/Ja;La=Ja*+Q(+(Ka*Ka+1.0));za=130}}while(0);if((za|0)==130){za=0;h[f+(qa<<3)>>3]=La;if(La!=0.0){Ja=1.0/La;Ma=M*Ja;Na=R*Ja}else{Ma=S;Na=q}}Ja=B*Ma+Ia*Na;z=Ia*Ma-B*Na;ua=oa+(c<<3)|0;if(!r){ta=ua;sa=oa;wa=c;while(1){wa=wa+ -1|0;Ka=+h[ta>>3];Oa=+h[sa>>3];h[sa>>3]=Na*Ka+Ma*Oa;h[ta>>3]=Ma*Ka-Na*Oa;if((wa|0)==0){break}else{ta=ta+8|0;sa=sa+8|0}}}if((qa|0)<(m|0)){oa=ua;o=Ma;n=Ja;qa=W;E=Na;pa=w;N=z}else{Fa=Ja;Ga=z;break}}}h[k+(V<<3)>>3]=0.0;h[v>>3]=Fa;h[G>>3]=Ga;pa=I+1|0;if((pa|0)<100){I=pa;x=m}else{Pa=m;break}}if((za|0)==105){za=0;if(Ca<0.0){h[G>>3]=-Ca;m=d;x=e+((aa(s,d)|0)<<3)|0;while(1){I=m+ -1|0;h[x>>3]=-+h[x>>3];if((I|0)==0){Pa=Aa;break}else{m=I;x=x+8|0}}}else{Pa=Aa}}if((s|0)>0){C=s;p=Pa}else{break a}}pd(11768,11704)}}}}}while(0);Pa=(d|0)==0;if(!Pa){Aa=d;za=f;Ca=0.0;while(1){Aa=Aa+ -1|0;Ga=+h[za>>3];Ca=Ga>Ca?Ga:Ca;if((Aa|0)==0){break}else{za=za+8|0}}Ga=Ca*1.0e-11;if(!Pa){za=d;Aa=f;while(1){za=za+ -1|0;if(+h[Aa>>3]>3]=0.0}if((za|0)==0){break}else{Aa=Aa+8|0}}if(!Pa){Pa=(c|0)==0;Aa=d;za=a;a=l;ya=f;while(1){Aa=Aa+ -1|0;Ga=+h[ya>>3];if(Ga!=0.0){if(Pa){Qa=za;Ra=0.0}else{f=za;ja=b;ia=c;Ca=0.0;while(1){ia=ia+ -1|0;Ca=Ca+ +h[f>>3]*+h[ja>>3];if((ia|0)==0){break}else{f=f+8|0;ja=ja+8|0}}Qa=za+(c<<3)|0;Ra=Ca}Sa=Qa;Ta=Ra/Ga}else{Sa=za+(c<<3)|0;Ta=0.0}h[a>>3]=Ta;if((Aa|0)==0){break}else{za=Sa;a=a+8|0;ya=ya+8|0}}}}}if(j){Ua=0;Va=e}else{hg(l);hg(k);i=g;return}while(1){e=d;Ta=0.0;j=l;ya=Va;while(1){a=e+ -1|0;Wa=Ta+ +h[ya>>3]*+h[j>>3];if((a|0)==0){break}e=a;Ta=Wa;j=j+8|0;ya=ya+(d<<3)|0}h[b+(Ua<<3)>>3]=Wa;Ua=Ua+1|0;if((Ua|0)==(d|0)){break}else{Va=Va+8|0}}hg(l);hg(k);i=g;return}function xd(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0;f=i;i=i+32|0;g=f+8|0;h=f;j=f+16|0;k=h;c[k>>2]=5260110;c[k+4>>2]=5459015;k=e+4|0;a[k]=0;a[j]=0;l=e+20|0;c[l>>2]=-1;m=e+24|0;c[m>>2]=-1;n=e+28|0;c[n>>2]=-1;do{if((b|0)>0){o=e+8|0;p=e+13|0;q=0;r=0;a:while(1){s=d+(q*9|0)|0;do{if((a[d+(q*9|0)+4|0]|0)!=45){if((yg(s,11816)|0)==0){if(!((c[n>>2]|0)==-1)){t=1;u=35;break a}c[n>>2]=q;v=r}else{v=r}}else{w=d+(q*9|0)+5|0;x=c[2992]|0;b:do{if((x|0)>0){y=0;while(1){z=y+1|0;if((Ag(w,11976+(y<<2)|0,3)|0)==0){A=y;break b}if((z|0)<(x|0)){y=z}else{A=z;break}}}else{A=0}}while(0);if((A|0)==(x|0)){y=0;while(1){z=y+1|0;if((Ag(w,h+(y<<2)|0,3)|0)==0){B=y;break}if((z|0)<2){y=z}else{B=z;break}}if((B|0)==2){v=r;break}}if((a[k]|0)!=0){if((Ag(s,j,8)|0)!=0|(r|0)==0){t=1;u=35;break a}c[r>>2]=q;a[j]=0;v=r;break}c[g>>2]=w;Na(k|0,11832,g|0)|0;if((Ag(s,11840,4)|0)==0){c[l>>2]=q;a[o+0|0]=a[11848|0]|0;a[o+1|0]=a[11849|0]|0;a[o+2|0]=a[11850|0]|0;a[p]=4408644;a[p+1|0]=17221;a[p+2|0]=67;a[p+3|0]=0;c[g>>2]=k;Na(j|0,11856,g|0)|0;v=m;break}if((Ag(s,11864,4)|0)==0){c[m>>2]=q;a[o+0|0]=a[11848|0]|0;a[o+1|0]=a[11849|0]|0;a[o+2|0]=a[11850|0]|0;a[p]=4408644;a[p+1|0]=17221;a[p+2|0]=67;a[p+3|0]=0;c[g>>2]=k;Na(j|0,11872,g|0)|0;v=l;break}y=d+(q*9|0)+1|0;if((Ag(y,11880,3)|0)==0){c[l>>2]=q;c[g>>2]=a[s]|0;Na(o|0,11888,g|0)|0;c[g>>2]=a[s]|0;Na(p|0,11896,g|0)|0;c[g>>2]=p;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=m;break}if((Ag(y,11912,3)|0)==0){c[m>>2]=q;c[g>>2]=a[s]|0;Na(o|0,11888,g|0)|0;c[g>>2]=a[s]|0;Na(p|0,11896,g|0)|0;c[g>>2]=o;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=l;break}x=d+(q*9|0)+2|0;if((Ag(x,11920,2)|0)==0){c[l>>2]=q;z=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=z;Na(o|0,11928,g|0)|0;z=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=z;Na(p|0,11936,g|0)|0;c[g>>2]=p;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=m;break}if((Ag(x,11944,2)|0)!=0){t=1;u=35;break a}c[m>>2]=q;x=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=x;Na(o|0,11928,g|0)|0;x=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=x;Na(p|0,11936,g|0)|0;c[g>>2]=o;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=l}}while(0);s=q+1|0;if((s|0)<(b|0)){q=s;r=v}else{u=30;break}}if((u|0)==30){if((a[j]|0)==0){break}else{t=1}i=f;return t|0}else if((u|0)==35){i=f;return t|0}}}while(0);if((Ag(k,11952,3)|0)==0){a[k]=4998739;a[k+1|0]=19526;a[k+2|0]=76;a[k+3|0]=0;C=137}else{C=(a[k]|0)==0?999:137}c[e>>2]=C;t=0;i=f;return t|0}function yd(b,d,e,f,g,j,k,l,m,n,o){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0,t=0,u=0.0,v=0,w=0.0,x=0.0;p=i;q=n+4|0;if((c[d>>2]|0)!=137?(xd(c[q>>2]|0,b,d)|0)!=0:0){r=1;i=p;return r|0}b=c[q>>2]|0;if((b|0)>0){q=c[d+20>>2]|0;s=d+24|0;t=0;do{if((t|0)!=(q|0)?(t|0)!=(c[s>>2]|0):0){h[m+(t<<3)>>3]=+h[e+(t<<3)>>3]- +h[f+(t<<3)>>3]}t=t+1|0}while((t|0)<(b|0))}do{if((c[d>>2]|0)!=999){b=d+4|0;do{if((yg(b,11960)|0)==0){t=g+16|0;if(+h[t>>3]==0.0){r=2;i=p;return r|0}else{a[b]=5130579;a[b+1|0]=20041;a[b+2|0]=78;a[b+3|0]=0;h[l+40>>3]=0.0;u=+Re(+h[t>>3]);h[l+48>>3]=u/+Se(+h[t>>3]);t=l+4|0;c[t>>2]=c[t>>2]>>31;break}}}while(0);t=d+20|0;f=c[t>>2]|0;s=d+24|0;q=c[s>>2]|0;v=Fd(b,+h[e+(f<<3)>>3],+h[e+(q<<3)>>3],g,j,k,l,m+(f<<3)|0,m+(q<<3)|0)|0;if((v|0)!=0){r=v;i=p;return r|0}v=c[d+28>>2]|0;if(!((v|0)==-1)){u=+h[l+24>>3];if(u==0.0){w=90.0}else{w=u*3.141592653589793*.5}q=m+(c[s>>2]<<3)|0;u=+h[q>>3];if(u>3]=w+u;h[m+(v<<3)>>3]=5.0;break}x=w*.5;if(u>x){h[q>>3]=u-w;h[m+(v<<3)>>3]=0.0;break}q=m+(c[t>>2]<<3)|0;u=+h[q>>3];if(u>w*2.5){h[q>>3]=u-w*3.0;h[m+(v<<3)>>3]=4.0;break}if(u>w*1.5){h[q>>3]=u-w*2.0;h[m+(v<<3)>>3]=3.0;break}if(u>x){h[q>>3]=u-w;h[m+(v<<3)>>3]=2.0;break}else{h[m+(v<<3)>>3]=1.0;break}}}}while(0);l=(Cd(m,n,o)|0)==0;r=l?0:4;i=p;return r|0}function zd(b,d,e,f,g,j,k,l,m,n,o){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0.0,t=0.0;p=i;if((c[d>>2]|0)!=137?(xd(c[f+4>>2]|0,b,d)|0)!=0:0){q=1;i=p;return q|0}if((Dd(e,f,g)|0)!=0){q=4;i=p;return q|0}e=c[f+4>>2]|0;if((e|0)>0){f=c[d+20>>2]|0;b=d+24|0;r=0;do{if((r|0)!=(f|0)?(r|0)!=(c[b>>2]|0):0){h[o+(r<<3)>>3]=+h[g+(r<<3)>>3]+ +h[m+(r<<3)>>3]}r=r+1|0}while((r|0)<(e|0))}if((c[d>>2]|0)!=999){e=c[d+28>>2]|0;a:do{if(!((e|0)==-1)){s=+h[g+(e<<3)>>3];r=~~(s+.5);if(+P(+(s- +(r|0)))>1.0e-10){q=3;i=p;return q|0}s=+h[j+24>>3];if(s==0.0){t=90.0}else{t=s*3.141592653589793*.5}switch(r|0){case 2:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t+ +h[r>>3];break a;break};case 4:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t*3.0+ +h[r>>3];break a;break};case 3:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t*2.0+ +h[r>>3];break a;break};case 0:{r=g+(c[d+24>>2]<<3)|0;h[r>>3]=t+ +h[r>>3];break a;break};case 5:{r=g+(c[d+24>>2]<<3)|0;h[r>>3]=+h[r>>3]-t;break a;break};case 1:{break a;break};default:{q=3;i=p;return q|0}}}}while(0);e=d+4|0;do{if((yg(e,11960)|0)==0){r=n+16|0;if(+h[r>>3]==0.0){q=2;i=p;return q|0}else{a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;h[j+40>>3]=0.0;t=+Re(+h[r>>3]);h[j+48>>3]=t/+Se(+h[r>>3]);r=j+4|0;c[r>>2]=c[r>>2]>>31;break}}}while(0);r=c[d+20>>2]|0;m=c[d+24>>2]|0;d=Gd(e,+h[g+(r<<3)>>3],+h[g+(m<<3)>>3],j,k,l,n,o+(r<<3)|0,o+(m<<3)|0)|0;if((d|0)!=0){q=d;i=p;return q|0}}q=0;i=p;return q|0}function Ad(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;b=i;d=c[a+4>>2]|0;e=aa(d<<3,d)|0;f=gg(e)|0;c[a+20>>2]=f;if((f|0)==0){g=1;i=b;return g|0}j=gg(e)|0;c[a+24>>2]=j;if((j|0)==0){hg(f);g=1;i=b;return g|0}if((d|0)>0){e=a+16|0;k=a+12|0;l=0;m=0;while(1){n=(c[e>>2]|0)+(l<<3)|0;o=c[k>>2]|0;p=m;q=0;while(1){h[f+(p<<3)>>3]=+h[n>>3]*+h[o+(p<<3)>>3];q=q+1|0;if((q|0)==(d|0)){break}else{p=p+1|0}}l=l+1|0;if((l|0)==(d|0)){break}else{m=d+m|0}}}if((Bd(d,f,j)|0)!=0){g=2;i=b;return g|0}c[a>>2]=137;g=0;i=b;return g|0}function Bd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0,x=0,y=0,z=0,A=0,B=0;e=i;f=a<<2;g=gg(f)|0;if((g|0)==0){j=1;i=e;return j|0}k=gg(f)|0;if((k|0)==0){hg(g);j=1;i=e;return j|0}f=a<<3;l=gg(f)|0;if((l|0)==0){hg(g);hg(k);j=1;i=e;return j|0}m=gg(aa(f,a)|0)|0;if((m|0)==0){hg(g);hg(k);hg(l);j=1;i=e;return j|0}f=(a|0)>0;if(f){n=a<<3;o=0;p=0;while(1){c[g+(o<<2)>>2]=o;q=l+(o<<3)|0;h[q>>3]=0.0;Kg(m+(p<<3)|0,b+(p<<3)|0,n|0)|0;r=0.0;s=p;t=0;while(1){u=+P(+(+h[b+(s<<3)>>3]));if(u>r){h[q>>3]=u;v=u}else{v=r}t=t+1|0;if((t|0)==(a|0)){break}else{r=v;s=s+1|0}}o=o+1|0;if(v==0.0){w=17;break}if((o|0)>=(a|0)){break}else{p=p+a|0}}if((w|0)==17){hg(g);hg(k);hg(l);hg(m);j=2;i=e;return j|0}if(f){w=0;while(1){p=aa(w,a)|0;o=m+(p+w<<3)|0;b=l+(w<<3)|0;n=w+1|0;s=(n|0)<(a|0);if(s){v=+P(+(+h[o>>3]))/+h[b>>3];t=n;q=w;while(1){r=+P(+(+h[m+((aa(t,a)|0)+w<<3)>>3]));u=r/+h[l+(t<<3)>>3];x=u>v;q=x?t:q;t=t+1|0;if((t|0)==(a|0)){break}else{v=x?u:v}}if((q|0)>(w|0)){t=0;x=p;y=aa(q,a)|0;while(1){z=m+(y<<3)|0;v=+h[z>>3];A=m+(x<<3)|0;h[z>>3]=+h[A>>3];h[A>>3]=v;t=t+1|0;if((t|0)==(a|0)){break}else{x=x+1|0;y=y+1|0}}y=l+(q<<3)|0;v=+h[y>>3];h[y>>3]=+h[b>>3];h[b>>3]=v;y=g+(q<<2)|0;x=c[y>>2]|0;t=g+(w<<2)|0;c[y>>2]=c[t>>2];c[t>>2]=x}if(s){x=n;do{t=aa(x,a)|0;y=m+(t+w<<3)|0;v=+h[y>>3];a:do{if(v!=0.0){u=v/+h[o>>3];h[y>>3]=u;r=u;A=n;while(1){z=m+(A+t<<3)|0;h[z>>3]=+h[z>>3]-r*+h[m+(A+p<<3)>>3];z=A+1|0;if((z|0)==(a|0)){break a}r=+h[y>>3];A=z}}}while(0);x=x+1|0}while((x|0)!=(a|0))}}if((n|0)==(a|0)){break}else{w=n}}if(f){w=0;do{c[k+(c[g+(w<<2)>>2]<<2)>>2]=w;w=w+1|0}while((w|0)!=(a|0));if(f){w=a<<3;x=0;p=0;while(1){Eg(d+(p<<3)|0,0,w|0)|0;x=x+1|0;if((x|0)==(a|0)){break}else{p=p+a|0}}if(f){f=0;do{p=c[k+(f<<2)>>2]|0;h[d+((aa(p,a)|0)+f<<3)>>3]=1.0;x=p+1|0;if((x|0)<(a|0)){w=x;while(1){if((p|0)<(w|0)){x=aa(w,a)|0;o=d+(x+f<<3)|0;v=+h[o>>3];s=p;do{v=v- +h[m+(s+x<<3)>>3]*+h[d+((aa(s,a)|0)+f<<3)>>3];h[o>>3]=v;s=s+1|0}while((s|0)!=(w|0))}s=w+1|0;if((s|0)==(a|0)){B=a;break}else{w=s}}}else{B=a}while(1){w=B+ -1|0;p=aa(w,a)|0;n=d+(p+f<<3)|0;if((B|0)<(a|0)){v=+h[n>>3];s=B;do{v=v- +h[m+(s+p<<3)>>3]*+h[d+((aa(s,a)|0)+f<<3)>>3];h[n>>3]=v;s=s+1|0}while((s|0)!=(a|0))}h[n>>3]=+h[n>>3]/+h[m+(p+w<<3)>>3];if((w|0)>0){B=w}else{break}}f=f+1|0}while((f|0)!=(a|0))}}}}}hg(g);hg(k);hg(l);hg(m);j=0;i=e;return j|0}function Cd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0,r=0;e=i;f=c[b+4>>2]|0;if((c[b>>2]|0)!=137?(Ad(b)|0)!=0:0){g=1;i=e;return g|0}j=(f|0)>0;if(!j){g=0;i=e;return g|0}k=b+24|0;l=0;m=0;while(1){n=d+(l<<3)|0;h[n>>3]=0.0;o=c[k>>2]|0;p=0.0;q=m;r=0;while(1){p=p+ +h[o+(q<<3)>>3]*+h[a+(r<<3)>>3];h[n>>3]=p;r=r+1|0;if((r|0)==(f|0)){break}else{q=q+1|0}}l=l+1|0;if((l|0)==(f|0)){break}else{m=f+m|0}}if(!j){g=0;i=e;return g|0}j=c[b+8>>2]|0;b=0;while(1){m=d+(b<<3)|0;h[m>>3]=+h[j+(b<<3)>>3]+ +h[m>>3];m=b+1|0;if((m|0)==(f|0)){g=0;break}else{b=m}}i=e;return g|0}function Dd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0;e=i;f=c[b+4>>2]|0;if((c[b>>2]|0)!=137?(Ad(b)|0)!=0:0){g=1;i=e;return g|0}if((f|0)<=0){g=0;i=e;return g|0}Eg(d|0,0,f<<3|0)|0;j=c[b+8>>2]|0;k=b+20|0;b=0;while(1){l=+h[a+(b<<3)>>3]- +h[j+(b<<3)>>3];m=c[k>>2]|0;n=0;o=b;while(1){p=d+(n<<3)|0;h[p>>3]=+h[p>>3]+l*+h[m+(o<<3)>>3];n=n+1|0;if((n|0)==(f|0)){break}else{o=o+f|0}}o=b+1|0;if((o|0)==(f|0)){g=0;break}else{b=o}}i=e;return g|0}function Ed(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0,C=0.0,D=0.0;e=i;if((Hd(a,d)|0)!=0){f=1;i=e;return f|0}a=b+8|0;g=b+24|0;j=+h[g>>3]==999.0;k=d+16|0;l=+h[k>>3];do{if(!(l==90.0)){m=+h[b+16>>3];if(j){h[g>>3]=m>3]);o=+Re(+h[g>>3]);p=+Se(+h[g>>3]);q=+Re(+h[k>>3]);r=+Se(+h[k>>3]);s=o*q;o=+Q(+(s*s+r*r));do{if(o==0.0){if(m!=0.0){f=1;i=e;return f|0}else{t=+h[b+32>>3];break}}else{u=m/o;if(+P(+u)>1.0){f=1;i=e;return f|0}v=+Xe(r,s);w=+Ue(u);u=v+w;if(!(u>180.0)){if(u<-180.0){x=u+360.0}else{x=u}}else{x=u+-360.0}u=v-w;if(!(u>180.0)){if(u<-180.0){y=u+360.0}else{y=u}}else{y=u+-360.0}d=b+32|0;u=+h[d>>3];if(+P(+(u-x))<+P(+(u-y))){z=+P(+x)<90.0000000001;A=z?x:y}else{z=+P(+y)<90.0000000001;A=z?y:x}h[d>>3]=A;t=A}}while(0);d=b+40|0;z=b+48|0;h[z>>3]=90.0-t;s=n*+Re(t);do{if(+P(+s)<1.0e-10){if(+P(+n)<1.0e-10){o=+h[a>>3];h[d>>3]=o;h[z>>3]=90.0- +h[k>>3];B=a;C=o;break}if(t>0.0){o=+h[a>>3]+ +h[g>>3]+-180.0;h[d>>3]=o;h[z>>3]=0.0;B=a;C=o;break}if(t<0.0){o=+h[a>>3]- +h[g>>3];h[d>>3]=o;h[z>>3]=180.0;B=a;C=o;break}else{B=a;C=+h[d>>3];break}}else{o=(r-m*+Se(t))/s;u=p*q/n;if(o==0.0&u==0.0){f=1;i=e;return f|0}else{w=+h[a>>3];v=w- +Xe(u,o);h[d>>3]=v;B=a;C=v;break}}}while(0);if(!(+h[B>>3]>=0.0)){if(!(C>0.0)){D=t;break}h[d>>3]=C+-360.0;D=t;break}else{if(!(C<0.0)){D=t;break}h[d>>3]=C+360.0;D=t;break}}else{if(j){h[g>>3]=180.0}n=+h[b+16>>3];h[b+32>>3]=n;h[b+40>>3]=+h[a>>3];h[b+48>>3]=90.0-n;D=n}}while(0);h[b+56>>3]=+h[g>>3];g=b+48|0;h[b+64>>3]=+Re(+h[g>>3]);h[b+72>>3]=+Se(+h[g>>3]);c[b>>2]=137;b=+P(+D)>90.0000000001;f=b?2:0;i=e;return f|0}function Fd(a,b,d,e,f,g,j,k,l){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;m=i;if((c[e>>2]|0)!=137?(Ed(a,e,j)|0)!=0:0){n=1;i=m;return n|0}Pe(b,d,e+40|0,f,g)|0;e=lb[c[j+1888>>2]&63](+h[f>>3],+h[g>>3],j,k,l)|0;if((e|0)==0){n=0;i=m;return n|0}n=(e|0)==1?2:3;i=m;return n|0}function Gd(a,b,d,e,f,g,j,k,l){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;m=i;if((c[j>>2]|0)!=137?(Ed(a,j,e)|0)!=0:0){n=1;i=m;return n|0}a=lb[c[e+1892>>2]&63](b,d,e,f,g)|0;if((a|0)==0){Qe(+h[f>>3],+h[g>>3],j+40|0,k,l)|0;n=0;i=m;return n|0}else{n=(a|0)==1?2:3;i=m;return n|0}return 0}function Hd(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;e=i;if((yg(b,12080)|0)==0){Id(d)|0;f=0;i=e;return f|0}if((yg(b,12088)|0)==0){Jd(d)|0;f=0;i=e;return f|0}if((yg(b,12096)|0)==0){a[d]=5128532;a[d+1|0]=20033;a[d+2|0]=78;a[d+3|0]=0;g=d+4|0;c[g>>2]=(c[g>>2]>>31&-206)+103;h[d+8>>3]=0.0;h[d+16>>3]=90.0;g=d+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}c[d+1888>>2]=1;c[d+1892>>2]=2;g=99;while(1){if(!(+h[d+(g<<3)+280>>3]==0.0)){j=g;break}k=g+ -1|0;if(!(+h[d+(g+100<<3)+280>>3]==0.0)){j=g;break}if((g|0)>0){g=k}else{j=k;break}}c[d+276>>2]=(j|0)<0?0:j;f=0;i=e;return f|0}if((yg(b,12104)|0)==0){a[d]=4674643;a[d+1|0]=18260;a[d+2|0]=71;a[d+3|0]=0;c[d+4>>2]=104;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=114.59155902616465;h[d+120>>3]=.008726646259971648}else{m=l*2.0;h[d+112>>3]=m;h[d+120>>3]=1.0/m}c[d+1888>>2]=3;c[d+1892>>2]=4;f=0;i=e;return f|0}if((yg(b,12112)|0)==0){a[d]=5130579;a[d+1|0]=20041;a[d+2|0]=78;a[d+3|0]=0;j=d+4|0;c[j>>2]=(c[j>>2]>>31&-210)+105;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;m=+h[j>>3];if(m==0.0){h[j>>3]=57.29577951308232;n=57.29577951308232}else{n=m}h[d+112>>3]=1.0/n;n=+h[d+40>>3];m=+h[d+48>>3];l=n*n+m*m;h[d+120>>3]=l;h[d+128>>3]=l+1.0;h[d+136>>3]=l+-1.0;c[d+1888>>2]=5;c[d+1892>>2]=6;f=0;i=e;return f|0}if((yg(b,12120)|0)==0){a[d]=4411969;a[d+1|0]=17234;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=106;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{m=l*3.141592653589793/180.0;h[d+112>>3]=m;h[d+120>>3]=1.0/m}c[d+1888>>2]=7;c[d+1892>>2]=8;f=0;i=e;return f|0}if((yg(b,12128)|0)==0){Kd(d)|0;f=0;i=e;return f|0}if((yg(b,12136)|0)==0){a[d]=4277594;a[d+1|0]=16709;a[d+2|0]=65;a[d+3|0]=0;c[d+4>>2]=108;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;m=+h[j>>3];if(m==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=114.59155902616465;h[d+120>>3]=.008726646259971648}else{l=m*2.0;h[d+112>>3]=l;h[d+120>>3]=1.0/l}c[d+1888>>2]=9;c[d+1892>>2]=10;f=0;i=e;return f|0}if((yg(b,12144)|0)==0){a[d]=5392705;a[d+1|0]=21065;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=109;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;o=57.29577951308232}else{o=l}l=o*2.0;j=d+112|0;h[j>>3]=l;o=+h[d+40>>3];do{if(!(o==90.0)){if(o>-90.0){m=+Re((90.0-o)*.5);n=m*m;p=+_(+m)*n/(1.0-n);h[d+120>>3]=p;n=.5-p;h[d+128>>3]=n;q=n;r=+h[j>>3];break}else{f=0;i=e;return f|0}}else{h[d+120>>3]=-.5;h[d+128>>3]=1.0;q=1.0;r=l}}while(0);h[d+136>>3]=q*r;h[d+144>>3]=1.0e-4;h[d+152>>3]=q*1.0e-4;h[d+160>>3]=57.29577951308232/q;c[d+1888>>2]=11;c[d+1892>>2]=12;f=0;i=e;return f|0}if((yg(b,12152)|0)==0){a[d]=5265731;a[d+1|0]=20569;a[d+2|0]=80;a[d+3|0]=0;c[d+4>>2]=201;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];do{if(q==0.0){h[g>>3]=57.29577951308232;r=+h[d+48>>3];h[d+112>>3]=r;if(r==0.0){f=0;i=e;return f|0}h[d+120>>3]=1.0/r;l=(r+ +h[d+40>>3])*57.29577951308232;h[d+128>>3]=l;if(l==0.0){f=0;i=e;return f|0}else{h[d+136>>3]=1.0/l;break}}else{l=+h[d+48>>3];r=q*l*3.141592653589793/180.0;h[d+112>>3]=r;if(r==0.0){f=0;i=e;return f|0}h[d+120>>3]=1.0/r;r=q*(l+ +h[d+40>>3]);h[d+128>>3]=r;if(r==0.0){f=0;i=e;return f|0}else{h[d+136>>3]=1.0/r;break}}}while(0);c[d+1888>>2]=13;c[d+1892>>2]=14;f=0;i=e;return f|0}if((yg(b,12160)|0)==0){a[d]=4277571;a[d+1|0]=16709;a[d+2|0]=65;a[d+3|0]=0;c[d+4>>2]=202;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;q=+h[j>>3];do{if(q==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;r=+h[d+40>>3];if(r<=0.0|r>1.0){f=0;i=e;return f|0}else{h[d+128>>3]=57.29577951308232/r;h[d+136>>3]=r/57.29577951308232;break}}else{h[d+112>>3]=q*3.141592653589793/180.0;h[d+120>>3]=57.29577951308232/q;r=+h[d+40>>3];if(r<=0.0|r>1.0){f=0;i=e;return f|0}else{h[d+128>>3]=q/r;h[d+136>>3]=r/q;break}}}while(0);c[d+1888>>2]=15;c[d+1892>>2]=16;f=0;i=e;return f|0}if((yg(b,12168)|0)==0){a[d]=5390659;a[d+1|0]=21057;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=203;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{r=q*3.141592653589793/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r}c[d+1888>>2]=17;c[d+1892>>2]=18;f=0;i=e;return f|0}if((yg(b,12176)|0)==0){a[d]=5391693;a[d+1|0]=21061;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=204;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;r=+h[j>>3];if(r==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{q=r*3.141592653589793/180.0;h[d+112>>3]=q;h[d+120>>3]=1.0/q}c[d+1888>>2]=19;c[d+1892>>2]=20;f=0;i=e;return f|0}if((yg(b,12184)|0)==0){a[d]=4998739;a[d+1|0]=19526;a[d+2|0]=76;a[d+3|0]=0;c[d+4>>2]=301;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{r=q*3.141592653589793/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r}c[d+1888>>2]=21;c[d+1892>>2]=22;f=0;i=e;return f|0}if((yg(b,12192)|0)==0){a[d]=5390672;a[d+1|0]=21057;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=302;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;r=+h[j>>3];if(r==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;h[d+128>>3]=180.0;h[d+136>>3]=.005555555555555556}else{q=r*3.141592653589793;r=q/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r;h[d+128>>3]=q;h[d+136>>3]=1.0/q}c[d+1888>>2]=23;c[d+1892>>2]=24;f=0;i=e;return f|0}if((yg(b,12200)|0)==0){a[d]=5001037;a[d+1|0]=19535;a[d+2|0]=76;a[d+3|0]=0;c[d+4>>2]=303;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;s=57.29577951308232}else{s=q}q=s*1.4142135623730951;h[d+112>>3]=q;h[d+120>>3]=q/90.0;h[d+128>>3]=1.0/q;h[d+136>>3]=90.0/s;h[d+144>>3]=.6366197723675814;c[d+1888>>2]=25;c[d+1892>>2]=26;f=0;i=e;return f|0}if((yg(b,12208)|0)==0){a[d]=5523777;a[d+1|0]=21577;a[d+2|0]=84;a[d+3|0]=0;c[d+4>>2]=401;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;s=+h[j>>3];if(s==0.0){h[j>>3]=57.29577951308232;t=57.29577951308232}else{t=s}s=t*2.0;q=t*s;h[d+112>>3]=q;t=1.0/(q*2.0);h[d+120>>3]=t;h[d+128>>3]=t*.25;h[d+136>>3]=1.0/s;c[d+1888>>2]=27;c[d+1892>>2]=28;f=0;i=e;return f|0}if((yg(b,12216)|0)==0){Ld(d)|0;f=0;i=e;return f|0}if((yg(b,12224)|0)==0){Md(d)|0;f=0;i=e;return f|0}if((yg(b,12232)|0)==0){Nd(d)|0;f=0;i=e;return f|0}if((yg(b,12240)|0)==0){Od(d)|0;f=0;i=e;return f|0}if((yg(b,12248)|0)==0){Pd(d)|0;f=0;i=e;return f|0}if((yg(b,12256)|0)==0){a[d]=5194576;a[d+1|0]=20291;a[d+2|0]=79;a[d+3|0]=0;c[d+4>>2]=602;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;s=+h[g>>3];if(s==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;h[d+128>>3]=114.59155902616465}else{t=s*3.141592653589793/180.0;h[d+112>>3]=t;h[d+120>>3]=1.0/t;h[d+128>>3]=s*2.0}c[d+1888>>2]=29;c[d+1892>>2]=30;f=0;i=e;return f|0}if((yg(b,12264)|0)==0){a[d]=4412244;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=701;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;s=+h[j>>3];if(s==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{t=s*3.141592653589793*.25;h[d+112>>3]=t;h[d+120>>3]=1.0/t}c[d+1888>>2]=31;c[d+1892>>2]=32;f=0;i=e;return f|0}if((yg(b,12272)|0)==0){a[d]=4412227;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=702;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;t=+h[g>>3];if(t==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{s=t*3.141592653589793*.25;h[d+112>>3]=s;h[d+120>>3]=1.0/s}c[d+1888>>2]=33;c[d+1892>>2]=34;f=0;i=e;return f|0}if((yg(b,12280)|0)!=0){f=1;i=e;return f|0}a[d]=4412241;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=703;b=d+8|0;g=d+24|0;c[b+0>>2]=0;c[b+4>>2]=0;c[b+8>>2]=0;c[b+12>>2]=0;s=+h[g>>3];if(s==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{t=s*3.141592653589793*.25;h[d+112>>3]=t;h[d+120>>3]=1.0/t}c[d+1888>>2]=35;c[d+1892>>2]=36;f=0;i=e;return f|0}function Id(b){b=b|0;var d=0,e=0,f=0.0,g=0.0,j=0,k=0,l=0,m=0.0,n=0.0;d=i;a[b]=5265985;a[b+1|0]=20570;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-202)+101;h[b+8>>3]=0.0;h[b+16>>3]=90.0;e=b+24|0;f=+h[e>>3];if(f==0.0){h[e>>3]=57.29577951308232;g=57.29577951308232}else{g=f}e=b+40|0;f=g*(+h[e>>3]+1.0);h[b+112>>3]=f;if(f==0.0){j=1;i=d;return j|0}k=b+48|0;f=+Re(+h[k>>3]);l=b+136|0;h[l>>3]=f;if(f==0.0){j=1;i=d;return j|0}h[b+128>>3]=1.0/f;f=+Se(+h[k>>3]);h[b+144>>3]=f;g=+h[l>>3];h[b+120>>3]=f/g;f=+h[e>>3];if(+P(+f)>1.0){h[b+152>>3]=+Ve(-1.0/f);m=+h[e>>3];n=+h[l>>3]}else{h[b+152>>3]=-90.0;m=f;n=g}g=m*n;h[b+160>>3]=g;l=+P(+g)<1.0;h[b+168>>3]=l?1.0:0.0;c[b+1888>>2]=37;c[b+1892>>2]=38;j=0;i=d;return j|0}function Jd(b){b=b|0;var d=0,e=0,f=0.0,g=0.0,j=0,k=0,l=0,m=0,n=0,o=0;d=i;a[b]=5266003;a[b+1|0]=20570;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-204)+102;h[b+8>>3]=0.0;h[b+16>>3]=90.0;e=b+24|0;f=+h[e>>3];if(f==0.0){h[e>>3]=57.29577951308232;g=57.29577951308232}else{g=f}h[b+112>>3]=1.0/g;j=b+40|0;g=+h[j>>3];k=b+56|0;f=g*+Se(+h[k>>3])+1.0;l=b+136|0;h[l>>3]=f;if(f==0.0){m=1;i=d;return m|0}f=+h[j>>3];g=f*+Re(+h[k>>3]);n=b+48|0;o=b+120|0;h[o>>3]=-(g*+Se(+h[n>>3]));g=+h[j>>3];f=g*+Re(+h[k>>3]);g=f*+Re(+h[n>>3]);h[b+128>>3]=g;f=+h[e>>3];h[b+144>>3]=f*+h[o>>3];h[b+152>>3]=f*g;g=+h[l>>3];h[b+160>>3]=f*g;f=g+-1.0;h[b+168>>3]=g*f+-1.0;if(+P(+f)<1.0){h[b+176>>3]=+Ve(1.0-g)}else{h[b+176>>3]=-90.0}c[b+1888>>2]=39;c[b+1892>>2]=40;m=0;i=d;return m|0}function Kd(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0.0,l=0.0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0.0,C=0.0,D=0.0;d=i;a[b]=5132378;a[b+1|0]=20048;a[b+2|0]=78;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-214)+107;f=b+8|0;h[f>>3]=0.0;g=b+16|0;h[g>>3]=90.0;j=b+24|0;k=+h[j>>3];if(k==0.0){h[j>>3]=57.29577951308232;l=57.29577951308232}else{l=k}m=9;while(1){if(!(+h[b+(m<<3)+32>>3]==0.0)){break}if((m|0)>0){m=m+ -1|0}else{n=6;break}}if((n|0)==6){a[b]=4411969;a[b+1|0]=17234;a[b+2|0]=67;a[b+3|0]=0;c[e>>2]=106;h[f>>3]=0.0;h[g>>3]=90.0;if(l==0.0){h[j>>3]=57.29577951308232;h[b+112>>3]=1.0;h[b+120>>3]=1.0}else{k=l*3.141592653589793/180.0;h[b+112>>3]=k;h[b+120>>3]=1.0/k}c[b+1888>>2]=7;c[b+1892>>2]=8;o=0;i=d;return o|0}c[b+272>>2]=m;c[b+1888>>2]=41;c[b+1892>>2]=42;if((m|0)<=2){o=0;i=d;return o|0}k=+h[b+40>>3];if(k<=0.0){o=1;i=d;return o|0}j=(m|0)>0;a:do{if(j){l=k;g=0;p=0.0;while(1){q=+(g|0)*3.141592653589793/180.0;r=0.0;f=m;do{r=q*r+ +(f|0)*+h[b+(f<<3)+32>>3];f=f+ -1|0}while((f|0)>0);f=g+1|0;if(r<=0.0){s=l;t=r;u=g;v=p;w=q;break a}if((f|0)<180){l=r;g=f;p=q}else{s=r;t=r;u=f;v=q;w=q;break}}}else{s=k;t=0.0;u=0;v=0.0;w=0.0}}while(0);b:do{if((u|0)==180){x=3.141592653589793}else{if(j){y=s;z=t;A=1;B=v;C=w}else{x=v-s*(w-v)/(t-s);break}while(1){k=B-y*(C-B)/(z-y);p=0.0;g=m;do{p=k*p+ +(g|0)*+h[b+(g<<3)+32>>3];g=g+ -1|0}while((g|0)>0);if(+P(+p)<1.0e-13){x=k;break b}g=p<0.0;f=A+1|0;if((f|0)<11){y=g?y:p;z=g?p:z;A=f;B=g?B:k;C=g?k:C}else{x=k;break}}}}while(0);if((m|0)>-1){A=m;C=0.0;while(1){B=x*C+ +h[b+(A<<3)+32>>3];if((A|0)>0){A=A+ -1|0;C=B}else{D=B;break}}}else{D=0.0}h[b+112>>3]=x;h[b+120>>3]=D;o=0;i=d;return o|0}function Ld(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0;d=i;a[b]=5263171;a[b+1|0]=20559;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-1002)+501;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+Se(f);h[b+112>>3]=j;if(j==0.0){k=1;i=d;return k|0}h[b+120>>3]=1.0/j;j=+h[g>>3];f=j*+Re(+h[b+48>>3]);g=b+136|0;h[g>>3]=f;if(f==0.0){k=1;i=d;return k|0}h[b+144>>3]=1.0/f;f=1.0/+Te(+h[e>>3]);h[b+152>>3]=f;h[b+128>>3]=f*+h[g>>3];c[b+1888>>2]=43;c[b+1892>>2]=44;k=0;i=d;return k|0}function Md(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0;d=i;a[b]=4542275;a[b+1|0]=17743;a[b+2|0]=69;a[b+3|0]=0;c[b+4>>2]=502;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+h[b+48>>3];k=f-j;l=f+j;j=+Se(k);f=(j+ +Se(l))*.5;m=b+112|0;h[m>>3]=f;if(f==0.0){n=1;i=d;return n|0}h[b+120>>3]=1.0/f;o=b+136|0;h[o>>3]=+h[g>>3]/f;f=+Se(k);k=f*+Se(l)+1.0;h[b+144>>3]=k;l=+h[m>>3]*2.0;h[b+152>>3]=l;f=+h[o>>3];h[b+160>>3]=f*f*k;h[b+168>>3]=1.0/(+h[g>>3]*2.0*f);h[b+176>>3]=f*+Q(+(k+l));h[b+128>>3]=f*+Q(+(k-l*+Se(+h[e>>3])));c[b+1888>>2]=45;c[b+1892>>2]=46;n=0;i=d;return n|0}function Nd(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0,m=0,n=0.0,o=0;d=i;a[b]=4476739;a[b+1|0]=17487;a[b+2|0]=68;a[b+3|0]=0;c[b+4>>2]=503;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;j=+h[g>>3];if(j==0.0){h[g>>3]=57.29577951308232;k=57.29577951308232}else{k=j}l=b+48|0;m=+h[l>>3]==0.0;j=k*+Se(f);if(m){f=j*3.141592653589793/180.0;h[b+112>>3]=f;n=f}else{f=j*+Se(+h[l>>3]);j=f/+h[l>>3];h[b+112>>3]=j;n=j}if(n==0.0){o=1;i=d;return o|0}h[b+120>>3]=1.0/n;n=+h[g>>3];j=n*+Re(+h[l>>3]);n=j*+Re(+h[e>>3]);j=n/+h[b+112>>3];h[b+128>>3]=j;h[b+136>>3]=j+ +h[e>>3];c[b+1888>>2]=47;c[b+1892>>2]=48;o=0;i=d;return o|0}function Od(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0;d=i;a[b]=5197635;a[b+1|0]=20303;a[b+2|0]=79;a[b+3|0]=0;c[b+4>>2]=504;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+h[b+48>>3];k=f-j;l=f+j;j=+Te((90.0-k)*.5);f=+Re(k);if(k==l){m=+Se(k);h[b+112>>3]=m;n=m}else{m=+Te((90.0-l)*.5);k=+_(+(+Re(l)/f))/+_(+(m/j));h[b+112>>3]=k;n=k}if(n==0.0){o=1;i=d;return o|0}h[b+120>>3]=1.0/n;k=+h[g>>3]*(f/n)/+R(+j,+n);g=b+136|0;h[g>>3]=k;if(k==0.0){o=1;i=d;return o|0}n=+Te((90.0- +h[e>>3])*.5);h[b+128>>3]=k*+R(+n,+(+h[b+112>>3]));h[b+144>>3]=1.0/+h[g>>3];c[b+1888>>2]=49;c[b+1892>>2]=50;o=0;i=d;return o|0}function Pd(b){b=b|0;var d=0,e=0,f=0,g=0.0,j=0.0,k=0.0,l=0,m=0;d=i;a[b]=5132098;a[b+1|0]=20047;a[b+2|0]=78;a[b+3|0]=0;c[b+4>>2]=601;e=b+8|0;f=b+24|0;c[e+0>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;g=+h[f>>3];if(g==0.0){h[f>>3]=57.29577951308232;h[b+120>>3]=1.0;f=b+40|0;j=+Re(+h[f>>3])*57.29577951308232;k=j/+Se(+h[f>>3]);h[b+128>>3]=k+ +h[f>>3];l=b+1888|0;c[l>>2]=51;m=b+1892|0;c[m>>2]=52;i=d;return 0}else{h[b+120>>3]=g*3.141592653589793/180.0;f=b+40|0;k=+Re(+h[f>>3]);j=k/+Se(+h[f>>3]);h[b+128>>3]=g*(j+ +h[f>>3]*3.141592653589793/180.0);l=b+1888|0;c[l>>2]=51;m=b+1892|0;c[m>>2]=52;i=d;return 0}return 0}function Qd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=101?(Id(d)|0)!=0:0){l=1;i=g;return l|0}m=+Re(a);n=+Re(b);o=m*+h[d+120>>3];k=d+40|0;p=+h[k>>3];q=n*o+(p+ +Se(b));if(q==0.0){l=2;i=g;return l|0}p=n*+h[d+112>>3]/q;h[e>>3]=p*+Se(a);h[f>>3]=-(m*p*+h[d+128>>3]);if((c[j>>2]|0)>0){if(+h[d+152>>3]>b){l=2;i=g;return l|0}if(+h[d+168>>3]>0.0?(p=+h[k>>3]/+Q(+(o*o+1.0)),+P(+p)<=1.0):0){m=+We(-o);o=+Ve(p);p=m-o;a=m+o+180.0;if(p>90.0){r=p+-360.0}else{r=p}if(a>90.0){s=a+-360.0}else{s=a}if((r>s?r:s)>b){l=2;i=g;return l|0}}}l=0;i=g;return l|0}function Rd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=101?(Id(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+136>>3]*b;m=+Q(+(a*a+l*l));if(m==0.0){h[e>>3]=0.0;n=90.0}else{h[e>>3]=+Xe(a,-l);l=m/(+h[d+112>>3]+ +h[d+144>>3]*b);b=l*+h[d+40>>3]/+Q(+(l*l+1.0));m=+Xe(1.0,l);if(+P(+b)>1.0){l=b<0.0?-90.0:90.0;if(+P(+l)>1.0000000000001){k=2;i=g;return k|0}else{o=l}}else{o=+Ve(b)}b=m-o;l=m+o+180.0;if(b>90.0){p=b+-360.0}else{p=b}if(l>90.0){q=l+-360.0}else{q=l}n=p>q?p:q}h[f>>3]=n;k=0;i=g;return k|0}function Sd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=102?(Jd(d)|0)!=0:0){l=1;i=g;return l|0}m=+Re(a);n=+Se(a);a=+Re(b);o=1.0- +Se(b);k=d+136|0;p=+h[k>>3]-o;if(p==0.0){l=2;i=g;return l|0}q=d+160|0;h[e>>3]=(n*a*+h[q>>3]-o*+h[d+144>>3])/p;h[f>>3]=-(m*a*+h[q>>3]+o*+h[d+152>>3])/p;if((c[j>>2]|0)>0){if(+h[d+176>>3]>b){l=2;i=g;return l|0}if(+P(+(+h[d+40>>3]))>1.0?(p=n*+h[d+120>>3]-m*+h[d+128>>3],m=1.0/+Q(+(+h[d+168>>3]+p*p)),+P(+m)<=1.0):0){n=+Xe(p,+h[k>>3]+-1.0);p=+Ve(m);m=n-p;o=n+p+180.0;if(m>90.0){r=m+-360.0}else{r=m}if(o>90.0){s=o+-360.0}else{s=o}if((r>s?r:s)>b){l=2;i=g;return l|0}}}l=0;i=g;return l|0}function Td(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=102?(Jd(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+112>>3];m=l*a;a=l*b;b=m*m+a*a;l=+h[d+136>>3];n=(m- +h[d+120>>3])/l;o=(a- +h[d+128>>3])/l;l=m*n+a*o;do{if(!(b<1.0e-10)){p=n*n+o*o;q=p+1.0;r=l-p;s=r*r-q*(p+(b-l-l)+-1.0);if(s<0.0){k=2;i=g;return k|0}p=+Q(+s);s=(p-r)/q;t=(-r-p)/q;q=s>t?s:t;if(q>1.0){if(q+-1.0<1.0e-13){u=1.0}else{u=s-1.0e-13?-1.0:u;if(q>1.0|q<-1.0){k=2;i=g;return k|0}else{h[f>>3]=+Ve(q);v=1.0-q;break}}else{h[f>>3]=90.0- +Q(+(b/(l+1.0)))*57.29577951308232;v=b*.5}}while(0);h[e>>3]=+Xe(m-n*v,-(a-o*v));k=0;i=g;return k|0}function Ud(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+16|0;k=j;l=e+4|0;m=c[l>>2]|0;if((((m|0)>-1?m:0-m|0)|0)!=103){a[e]=5128532;a[e+1|0]=20033;a[e+2|0]=78;a[e+3|0]=0;c[l>>2]=(m>>31&-206)+103;h[e+8>>3]=0.0;h[e+16>>3]=90.0;m=e+24|0;if(+h[m>>3]==0.0){h[m>>3]=57.29577951308232}c[e+1888>>2]=1;c[e+1892>>2]=2;m=99;while(1){if(!(+h[e+(m<<3)+280>>3]==0.0)){n=m;break}o=m+ -1|0;if(!(+h[e+(m+100<<3)+280>>3]==0.0)){n=m;break}if((m|0)>0){m=o}else{n=o;break}}c[e+276>>2]=(n|0)<0?0:n}p=+Se(d);if(p<=0.0){i=j;return 2}q=+h[e+24>>3];r=q*+Re(d)/p;h[k>>3]=r*+Se(b);n=k+8|0;h[n>>3]=-(r*+Re(b));m=c[e+1880>>2]|0;if((m|0)==0){s=+h[k>>3]}else{s=+sd(m,k)}h[f>>3]=s;f=c[e+1884>>2]|0;if((f|0)==0){t=+h[n>>3];h[g>>3]=t;u=c[l>>2]|0;v=(u|0)>0;w=p<0.0;x=v&w;y=x?2:0;i=j;return y|0}else{t=+sd(f,k);h[g>>3]=t;u=c[l>>2]|0;v=(u|0)>0;w=p<0.0;x=v&w;y=x?2:0;i=j;return y|0}return 0}function Vd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0;j=i;i=i+16|0;k=j+8|0;l=j;m=e+4|0;n=c[m>>2]|0;if((((n|0)>-1?n:0-n|0)|0)==103){o=c[e+276>>2]|0}else{a[e]=5128532;a[e+1|0]=20033;a[e+2|0]=78;a[e+3|0]=0;c[m>>2]=(n>>31&-206)+103;h[e+8>>3]=0.0;h[e+16>>3]=90.0;n=e+24|0;if(+h[n>>3]==0.0){h[n>>3]=57.29577951308232}c[e+1888>>2]=1;c[e+1892>>2]=2;n=99;while(1){if(!(+h[e+(n<<3)+280>>3]==0.0)){p=n;break}m=n+ -1|0;if(!(+h[e+(n+100<<3)+280>>3]==0.0)){p=n;break}if((n|0)>0){n=m}else{p=m;break}}n=(p|0)<0?0:p;c[e+276>>2]=n;o=n}if((o|0)==0){h[k>>3]=b;h[l>>3]=d;q=b;r=d}else{Wd(e,b,d,k,l)|0;q=+h[k>>3];r=+h[l>>3]}d=+Q(+(q*q+r*r));if(d==0.0){s=0.0;h[f>>3]=s;t=e+24|0;u=+h[t>>3];v=+Xe(u,d);h[g>>3]=v;i=j;return 0}s=+Xe(q,-r);h[f>>3]=s;t=e+24|0;u=+h[t>>3];v=+Xe(u,d);h[g>>3]=v;i=j;return 0}function Wd(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,P=0.0,R=0.0,S=0.0,T=0.0,U=0.0,V=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0,va=0.0,wa=0.0,xa=0.0,ya=0.0,za=0.0,Aa=0.0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0.0,Fa=0.0,Ga=0.0,Ha=0.0,Ia=0.0,Ja=0.0,Ka=0.0,La=0.0,Ma=0.0,Na=0.0,Oa=0.0,Pa=0.0;g=i;j=c[a+276>>2]|0;k=+h[a+1080>>3]+ +h[a+1088>>3]*b;l=+h[a+280>>3]+ +h[a+288>>3]*d;if((j|0)!=1){m=k+ +h[a+1096>>3]*d;n=l+ +h[a+296>>3]*b;if((j|0)!=2){o=b*b;p=d*d;q=+Q(+(o+p));r=m+q*+h[a+1104>>3];s=n+q*+h[a+304>>3];if((j|0)!=3){t=r+o*+h[a+1112>>3];u=s+p*+h[a+312>>3];if((j|0)!=4){v=b*d;w=t+v*+h[a+1120>>3];x=u+v*+h[a+320>>3];if((j|0)!=5){v=w+p*+h[a+1128>>3];y=x+o*+h[a+328>>3];if((j|0)!=6){z=o*b;A=v+z*+h[a+1136>>3];B=p*d;C=y+B*+h[a+336>>3];if((j|0)!=7){D=A+o*+h[a+1144>>3]*d;E=C+p*+h[a+344>>3]*b;if((j|0)!=8){F=D+p*+h[a+1152>>3]*b;G=E+o*+h[a+352>>3]*d;if((j|0)!=9){H=F+B*+h[a+1160>>3];I=G+z*+h[a+360>>3];if((j|0)!=10){J=q*q*q;K=H+J*+h[a+1168>>3];L=I+J*+h[a+368>>3];if((j|0)!=11){M=o*o;N=K+M*+h[a+1176>>3];O=p*p;P=L+O*+h[a+376>>3];if((j|0)!=12){R=N+z*+h[a+1184>>3]*d;S=P+B*+h[a+384>>3]*b;if((j|0)!=13){T=R+p*o*+h[a+1192>>3];U=S+p*o*+h[a+392>>3];if((j|0)!=14){V=T+B*+h[a+1200>>3]*b;W=U+z*+h[a+400>>3]*d;if((j|0)!=15){X=V+O*+h[a+1208>>3];Y=W+M*+h[a+408>>3];if((j|0)!=16){Z=M*b;_=X+Z*+h[a+1216>>3];$=O*d;aa=Y+$*+h[a+416>>3];if((j|0)!=17){ba=_+M*+h[a+1224>>3]*d;ca=aa+O*+h[a+424>>3]*b;if((j|0)!=18){da=ba+p*z*+h[a+1232>>3];ea=ca+o*B*+h[a+432>>3];if((j|0)!=19){fa=da+B*o*+h[a+1240>>3];ga=ea+z*p*+h[a+440>>3];if((j|0)!=20){ha=fa+O*+h[a+1248>>3]*b;ia=ga+M*+h[a+448>>3]*d;if((j|0)!=21){ja=ha+$*+h[a+1256>>3];ka=ia+Z*+h[a+456>>3];if((j|0)!=22){la=q*q*J;J=ja+la*+h[a+1264>>3];ma=ka+la*+h[a+464>>3];if((j|0)!=23){na=Z*b;oa=J+na*+h[a+1272>>3];pa=$*d;qa=ma+pa*+h[a+472>>3];if((j|0)!=24){ra=oa+Z*+h[a+1280>>3]*d;sa=qa+$*+h[a+480>>3]*b;if((j|0)!=25){ta=ra+p*M*+h[a+1288>>3];ua=sa+o*O*+h[a+488>>3];if((j|0)!=26){va=ta+B*z*+h[a+1296>>3];wa=ua+z*B*+h[a+496>>3];if((j|0)!=27){xa=va+O*o*+h[a+1304>>3];ya=wa+M*p*+h[a+504>>3];if((j|0)!=28){za=xa+$*+h[a+1312>>3]*b;Aa=ya+Z*+h[a+512>>3]*d;if((j|0)!=29){Ba=za+pa*+h[a+1320>>3];Ca=Aa+na*+h[a+520>>3];if((j|0)!=30){Da=na*b;Ea=Ba+Da*+h[a+1328>>3];Fa=pa*d;Ga=Ca+Fa*+h[a+528>>3];if((j|0)!=31){Ha=Ea+na*+h[a+1336>>3]*d;Ia=Ga+pa*+h[a+536>>3]*b;if((j|0)!=32){Ja=Ha+p*Z*+h[a+1344>>3];Ka=Ia+o*$*+h[a+544>>3];if((j|0)!=33){La=Ja+B*M*+h[a+1352>>3];Ma=Ka+z*O*+h[a+552>>3];if((j|0)!=34){Na=La+O*z*+h[a+1360>>3];z=Ma+M*B*+h[a+560>>3];if((j|0)!=35){B=Na+$*o*+h[a+1368>>3];o=z+Z*p*+h[a+568>>3];if((j|0)!=36){p=B+pa*+h[a+1376>>3]*b;b=o+na*+h[a+576>>3]*d;if((j|0)!=37){d=p+Fa*+h[a+1384>>3];Fa=b+Da*+h[a+584>>3];if((j|0)==38){Oa=d;Pa=Fa}else{Da=q*q*la;Oa=d+Da*+h[a+1392>>3];Pa=Fa+Da*+h[a+592>>3]}}else{Oa=p;Pa=b}}else{Oa=B;Pa=o}}else{Oa=Na;Pa=z}}else{Oa=La;Pa=Ma}}else{Oa=Ja;Pa=Ka}}else{Oa=Ha;Pa=Ia}}else{Oa=Ea;Pa=Ga}}else{Oa=Ba;Pa=Ca}}else{Oa=za;Pa=Aa}}else{Oa=xa;Pa=ya}}else{Oa=va;Pa=wa}}else{Oa=ta;Pa=ua}}else{Oa=ra;Pa=sa}}else{Oa=oa;Pa=qa}}else{Oa=J;Pa=ma}}else{Oa=ja;Pa=ka}}else{Oa=ha;Pa=ia}}else{Oa=fa;Pa=ga}}else{Oa=da;Pa=ea}}else{Oa=ba;Pa=ca}}else{Oa=_;Pa=aa}}else{Oa=X;Pa=Y}}else{Oa=V;Pa=W}}else{Oa=T;Pa=U}}else{Oa=R;Pa=S}}else{Oa=N;Pa=P}}else{Oa=K;Pa=L}}else{Oa=H;Pa=I}}else{Oa=F;Pa=G}}else{Oa=D;Pa=E}}else{Oa=A;Pa=C}}else{Oa=v;Pa=y}}else{Oa=w;Pa=x}}else{Oa=t;Pa=u}}else{Oa=r;Pa=s}}else{Oa=m;Pa=n}}else{Oa=k;Pa=l}h[e>>3]=Oa;h[f>>3]=Pa;i=g;return 0}function Xd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0,o=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=104){a[e]=4674643;a[e+1|0]=18260;a[e+2|0]=71;a[e+3|0]=0;c[k>>2]=104;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=3;c[e+1892>>2]=4}m=+Se(d)+1.0;if(m==0.0){n=2;i=j;return n|0}l=+h[e+112>>3];o=l*+Re(d)/m;h[f>>3]=o*+Se(b);h[g>>3]=-(o*+Re(b));n=0;i=j;return n|0}function Yd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=104){a[e]=4674643;a[e+1|0]=18260;a[e+2|0]=71;a[e+3|0]=0;c[k>>2]=104;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=3;c[e+1892>>2]=4}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0;h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=+We(q);s=r*2.0;t=90.0-s;h[g>>3]=t;i=j;return 0}n=+Xe(b,-d);h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=+We(q);s=r*2.0;t=90.0-s;h[g>>3]=t;i=j;return 0}function Zd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0;j=i;k=e+4|0;l=c[k>>2]|0;if((((l|0)>-1?l:0-l|0)|0)!=105){a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;c[k>>2]=(l>>31&-210)+105;h[e+8>>3]=0.0;h[e+16>>3]=90.0;l=e+24|0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;n=57.29577951308232}else{n=m}h[e+112>>3]=1.0/n;n=+h[e+40>>3];m=+h[e+48>>3];o=n*n+m*m;h[e+120>>3]=o;h[e+128>>3]=o+1.0;h[e+136>>3]=o+-1.0;c[e+1888>>2]=5;c[e+1892>>2]=6}o=(90.0- +P(+d))*3.141592653589793/180.0;if(o<1.0e-5){m=o*o*.5;if(d>0.0){p=o;q=m}else{p=o;q=2.0-m}}else{m=1.0- +Se(d);p=+Re(d);q=m}m=+Re(b);o=+Se(b);l=e+24|0;r=e+40|0;h[f>>3]=+h[l>>3]*(p*o+q*+h[r>>3]);f=e+48|0;h[g>>3]=-(+h[l>>3]*(p*m-q*+h[f>>3]));do{if((c[k>>2]|0)>0){if(+h[e+120>>3]==0.0){if(d<0.0){s=2}else{break}i=j;return s|0}else{if(d<-+We(o*+h[r>>3]-m*+h[f>>3])){s=2}else{break}i=j;return s|0}}}while(0);s=0;i=j;return s|0}function _d(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0;j=i;k=e+4|0;l=c[k>>2]|0;if((((l|0)>-1?l:0-l|0)|0)==105){m=+h[e+112>>3];n=+h[e+120>>3]}else{a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;c[k>>2]=(l>>31&-210)+105;h[e+8>>3]=0.0;h[e+16>>3]=90.0;l=e+24|0;o=+h[l>>3];if(o==0.0){h[l>>3]=57.29577951308232;p=57.29577951308232}else{p=o}o=1.0/p;h[e+112>>3]=o;p=+h[e+40>>3];q=+h[e+48>>3];r=p*p+q*q;h[e+120>>3]=r;h[e+128>>3]=r+1.0;h[e+136>>3]=r+-1.0;c[e+1888>>2]=5;c[e+1892>>2]=6;m=o;n=r}r=m*b;b=m*d;d=r*r+b*b;if(n==0.0){if(d!=0.0){s=+Xe(r,-b)}else{s=0.0}h[f>>3]=s;if(d<.5){h[g>>3]=+Ue(+Q(+d));t=0;i=j;return t|0}if(!(d<=1.0)){t=2;i=j;return t|0}h[g>>3]=+Ve(+Q(+(1.0-d)));t=0;i=j;return t|0}l=e+40|0;k=e+48|0;s=r*+h[l>>3]+b*+h[k>>3];do{if(!(d<1.0e-10)){m=+h[e+128>>3];o=s-n;q=o*o-m*(d-s-s+ +h[e+136>>3]);if(q<0.0){t=2;i=j;return t|0}p=+Q(+q);q=(p-o)/m;u=(-o-p)/m;m=q>u?q:u;if(m>1.0){if(m+-1.0<1.0e-13){v=1.0}else{v=q-1.0e-13?-1.0:v;if(m>1.0|m<-1.0){t=2;i=j;return t|0}else{h[g>>3]=+Ve(m);w=1.0-m;break}}else{h[g>>3]=90.0- +Q(+(d/(s+1.0)))*57.29577951308232;w=d*.5}}while(0);d=w*+h[k>>3]-b;b=r-w*+h[l>>3];if(d==0.0&b==0.0){h[f>>3]=0.0;t=0;i=j;return t|0}else{h[f>>3]=+Xe(b,d);t=0;i=j;return t|0}return 0}function $d(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==106){l=+h[e+112>>3];m=90.0-d;n=m*l;o=+Se(b);p=n*o;h[f>>3]=p;q=+Re(b);r=n*q;s=-r;h[g>>3]=s;i=j;return 0}a[e]=4411969;a[e+1|0]=17234;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=106;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;t=+h[k>>3];if(t==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;u=1.0}else{v=t*3.141592653589793/180.0;h[e+112>>3]=v;h[e+120>>3]=1.0/v;u=v}c[e+1888>>2]=7;c[e+1892>>2]=8;l=u;m=90.0-d;n=m*l;o=+Se(b);p=n*o;h[f>>3]=p;q=+Re(b);r=n*q;s=-r;h[g>>3]=s;i=j;return 0}function ae(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0,p=0.0,q=0.0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=106){a[e]=4411969;a[e+1|0]=17234;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=106;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0}else{m=l*3.141592653589793/180.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=7;c[e+1892>>2]=8}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0;h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=90.0-q;h[g>>3]=r;i=j;return 0}n=+Xe(b,-d);h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=90.0-q;h[g>>3]=r;i=j;return 0}function be(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=107?(Kd(d)|0)!=0:0){l=1;i=g;return l|0}m=(90.0-b)*3.141592653589793/180.0;b=(m*(m*(m*(m*(m*(m*(m*(m*(m*(m*0.0+ +h[d+104>>3])+ +h[d+96>>3])+ +h[d+88>>3])+ +h[d+80>>3])+ +h[d+72>>3])+ +h[d+64>>3])+ +h[d+56>>3])+ +h[d+48>>3])+ +h[d+40>>3])+ +h[d+32>>3])*+h[d+24>>3];h[e>>3]=b*+Se(a);h[f>>3]=-(b*+Re(a));if((c[j>>2]|0)>0?m>+h[d+112>>3]:0){l=2;i=g;return l|0}l=0;i=g;return l|0}function ce(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=107?(Kd(d)|0)!=0:0){k=1;i=g;return k|0}j=c[d+272>>2]|0;l=+Q(+(a*a+b*b));m=l/+h[d+24>>3];if((j|0)<1){k=1;i=g;return k|0}a:do{if((j|0)==2){l=+h[d+48>>3];n=+h[d+40>>3];o=n*n-l*4.0*(+h[d+32>>3]-m);if(o<0.0){k=2;i=g;return k|0}p=+Q(+o);o=l*2.0;l=(p-n)/o;q=(-n-p)/o;o=lq?l:q}else{r=o}if(r<0.0){if(r<-1.0e-13){k=2}else{s=0.0;break}i=g;return k|0}if(r>3.141592653589793){if(r>3.141592653589893){k=2;i=g;return k|0}else{s=3.141592653589793}}else{s=r}}else if((j|0)==1){s=(m- +h[d+32>>3])/+h[d+40>>3]}else{o=+h[d+32>>3];q=+h[d+112>>3];l=+h[d+120>>3];if(ml){if(m>l+1.0e-13){k=2}else{s=q;break}i=g;return k|0}if((j|0)>-1){t=0;u=o;v=l;w=0.0;x=q}else{p=0.0-m;y=0;n=o;o=l;l=0.0;z=q;while(1){q=(o-m)/(o-n);if(!(q<.1)){if(q>.9){A=.9}else{A=q}}else{A=.1}q=z-(z-l)*A;if(m>0.0){if(m<1.0e-13){s=q;break a}else{B=0.0;C=o;D=q;E=z}}else{if(p<1.0e-13){s=q;break a}else{B=n;C=0.0;D=l;E=q}}F=y+1|0;if(!(+P(+(E-D))<1.0e-13)&(F|0)<100){y=F;n=B;o=C;l=D;z=E}else{s=q;break a}}}while(1){z=(v-m)/(v-u);if(!(z<.1)){if(z>.9){G=.9}else{G=z}}else{G=.1}z=x-(x-w)*G;y=j;l=0.0;while(1){l=z*l+ +h[d+(y<<3)+32>>3];if((y|0)<=0){break}else{y=y+ -1|0}}if(l>3]=L;h[f>>3]=90.0-s*180.0/3.141592653589793;k=0;i=g;return k|0}function de(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==108){l=+h[e+112>>3]}else{a[e]=4277594;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=108;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;m=+h[k>>3];if(m==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648;n=114.59155902616465}else{o=m*2.0;h[e+112>>3]=o;h[e+120>>3]=1.0/o;n=o}c[e+1888>>2]=9;c[e+1892>>2]=10;l=n}n=l*+Se((90.0-d)*.5);h[f>>3]=n*+Se(b);h[g>>3]=-(n*+Re(b));i=j;return 0}function ee(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0;j=i;k=e+4|0;if((c[k>>2]|0)!=108){a[e]=4277594;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=108;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=9;c[e+1892>>2]=10}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0}else{n=+Xe(b,-d)}h[f>>3]=n;n=m*+h[e+120>>3];if(+P(+n)>1.0){if(+P(+(m- +h[e+112>>3]))<1.0e-12){o=-90.0}else{p=2;i=j;return p|0}}else{o=90.0- +Ve(n)*2.0}h[g>>3]=o;p=0;i=j;return p|0}function fe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=109){a[e]=5392705;a[e+1|0]=21065;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=109;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;m=57.29577951308232}else{m=l}l=m*2.0;k=e+112|0;h[k>>3]=l;m=+h[e+40>>3];do{if(!(m==90.0)){if(m>-90.0){n=+Re((90.0-m)*.5);o=n*n;p=+_(+n)*o/(1.0-o);h[e+120>>3]=p;o=.5-p;h[e+128>>3]=o;q=o;r=+h[k>>3];break}else{s=1;i=j;return s|0}}else{h[e+120>>3]=-.5;h[e+128>>3]=1.0;q=1.0;r=l}}while(0);h[e+136>>3]=q*r;h[e+144>>3]=1.0e-4;h[e+152>>3]=q*1.0e-4;h[e+160>>3]=57.29577951308232/q;c[e+1888>>2]=11;c[e+1892>>2]=12}do{if(!(d==90.0)){if(!(d>-90.0)){s=2;i=j;return s|0}q=90.0-d;r=q*.017453292519943295*.5;if(r<+h[e+144>>3]){t=r*+h[e+136>>3];break}else{r=+Re(q*.5);q=+Q(+(1.0-r*r))/r;l=+_(+r)/q;t=-(+h[e+112>>3]*(l+q*+h[e+120>>3]));break}}else{t=0.0}}while(0);h[f>>3]=t*+Se(b);h[g>>3]=-(t*+Re(b));s=0;i=j;return s|0}function ge(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0,A=0.0,B=0.0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==109){l=+h[e+112>>3]}else{a[e]=5392705;a[e+1|0]=21065;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=109;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;m=+h[k>>3];if(m==0.0){h[k>>3]=57.29577951308232;n=57.29577951308232}else{n=m}m=n*2.0;k=e+112|0;h[k>>3]=m;n=+h[e+40>>3];do{if(!(n==90.0)){if(n>-90.0){o=+Re((90.0-n)*.5);p=o*o;q=+_(+o)*p/(1.0-p);h[e+120>>3]=q;p=.5-q;h[e+128>>3]=p;r=p;s=+h[k>>3];break}else{t=1;i=j;return t|0}}else{h[e+120>>3]=-.5;h[e+128>>3]=1.0;r=1.0;s=m}}while(0);h[e+136>>3]=r*s;h[e+144>>3]=1.0e-4;h[e+152>>3]=r*1.0e-4;h[e+160>>3]=57.29577951308232/r;c[e+1888>>2]=11;c[e+1892>>2]=12;l=s}s=+Q(+(b*b+d*d))/l;if(s==0.0){u=0.0;v=0.0}else{do{if(!(s<+h[e+152>>3])){l=+h[e+120>>3];k=0;r=0.0;m=1.0;while(1){w=m*.5;n=+Q(+(1.0-w*w))/w;x=-(+_(+w)/n+n*l);y=k+1|0;if(s<=x){z=k;A=r;B=m;break}if((y|0)<30){k=y;r=x;m=w}else{z=y;A=x;B=w;break}}if((z|0)==30){t=2;i=j;return t|0}else{C=0;D=A;E=x;F=B;G=w}while(1){m=(E-s)/(E-D);if(!(m<.1)){if(m>.9){H=.9}else{H=m}}else{H=.1}I=G-(G-F)*H;m=+Q(+(1.0-I*I))/I;r=+_(+I)/m+m*l;m=-r;if(s>m){if(s+r<1.0e-12){J=C;break}else{K=m;L=E;M=I;N=G}}else{if(m-s<1.0e-12){J=C;break}else{K=D;L=m;M=F;N=I}}k=C+1|0;if((k|0)<100){C=k;D=K;E=L;F=M;G=N}else{J=k;break}}if((J|0)==100){t=2;i=j;return t|0}else{O=+Ue(I);break}}else{O=s*+h[e+160>>3]}}while(0);u=+Xe(b,-d);v=O}h[f>>3]=u;h[g>>3]=90.0-v*2.0;t=0;i=j;return t|0}function he(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==201){l=+h[e+40>>3]}else{a[e]=5265731;a[e+1|0]=20569;a[e+2|0]=80;a[e+3|0]=0;c[k>>2]=201;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;o=+h[e+48>>3];h[e+112>>3]=o;if(o==0.0){p=1;i=j;return p|0}h[e+120>>3]=1.0/o;q=+h[e+40>>3];r=(o+q)*57.29577951308232;h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=q;break}}else{q=+h[e+48>>3];r=n*q*3.141592653589793/180.0;h[e+112>>3]=r;if(r==0.0){p=1;i=j;return p|0}h[e+120>>3]=1.0/r;r=+h[e+40>>3];o=n*(q+r);h[e+128>>3]=o;if(o==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/o;s=r;break}}}while(0);c[e+1888>>2]=13;c[e+1892>>2]=14;l=s}s=l+ +Re(d);if(s==0.0){p=2;i=j;return p|0}h[f>>3]=+h[e+112>>3]*b;b=+h[e+128>>3];h[g>>3]=b*+Se(d)/s;p=0;i=j;return p|0}function ie(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==201){l=+h[e+120>>3]}else{a[e]=5265731;a[e+1|0]=20569;a[e+2|0]=80;a[e+3|0]=0;c[k>>2]=201;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;o=+h[e+48>>3];h[e+112>>3]=o;if(o==0.0){p=1;i=j;return p|0}q=1.0/o;h[e+120>>3]=q;r=(o+ +h[e+40>>3])*57.29577951308232;h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=q;break}}else{q=+h[e+48>>3];r=n*q*3.141592653589793/180.0;h[e+112>>3]=r;if(r==0.0){p=1;i=j;return p|0}o=1.0/r;h[e+120>>3]=o;r=n*(q+ +h[e+40>>3]);h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=o;break}}}while(0);c[e+1888>>2]=13;c[e+1892>>2]=14;l=s}h[f>>3]=l*b;b=+h[e+136>>3]*d;d=+Xe(b,1.0);h[g>>3]=d+ +Ve(b*+h[e+40>>3]/+Q(+(b*b+1.0)));p=0;i=j;return p|0}function je(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==202){l=+h[e+112>>3]}else{a[e]=4277571;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=202;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=+h[e+40>>3];if(o<=0.0|o>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=57.29577951308232/o;h[e+136>>3]=o/57.29577951308232;q=1.0;break}}else{o=n*3.141592653589793/180.0;h[e+112>>3]=o;h[e+120>>3]=57.29577951308232/n;r=+h[e+40>>3];if(r<=0.0|r>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=n/r;h[e+136>>3]=r/n;q=o;break}}}while(0);c[e+1888>>2]=15;c[e+1892>>2]=16;l=q}h[f>>3]=l*b;b=+h[e+128>>3];h[g>>3]=b*+Se(d);p=0;i=j;return p|0}function ke(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==202){l=+h[e+136>>3]}else{a[e]=4277571;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=202;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=+h[e+40>>3];if(o<=0.0|o>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=57.29577951308232/o;q=o/57.29577951308232;h[e+136>>3]=q;r=q;break}}else{h[e+112>>3]=n*3.141592653589793/180.0;h[e+120>>3]=57.29577951308232/n;q=+h[e+40>>3];if(q<=0.0|q>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=n/q;o=q/n;h[e+136>>3]=o;r=o;break}}}while(0);c[e+1888>>2]=15;c[e+1892>>2]=16;l=r}r=l*d;d=+P(+r);do{if(d>1.0){if(d>1.0000000000001){p=2;i=j;return p|0}else{s=r<0.0?-1.0:1.0;break}}else{s=r}}while(0);h[f>>3]=+h[e+120>>3]*b;h[g>>3]=+Ve(s);p=0;i=j;return p|0}function le(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==203){l=e+112|0;m=l;n=+h[l>>3];o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}a[e]=5390659;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=203;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;r=+h[l>>3];if(r==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;s=1.0}else{t=r*3.141592653589793/180.0;h[e+112>>3]=t;h[e+120>>3]=1.0/t;s=t}c[e+1888>>2]=17;c[e+1892>>2]=18;m=e+112|0;n=s;o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}function me(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==203){l=e+120|0;m=l;n=+h[l>>3];o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}a[e]=5390659;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=203;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;r=+h[l>>3];if(r==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;s=1.0}else{t=r*3.141592653589793/180.0;h[e+112>>3]=t;r=1.0/t;h[e+120>>3]=r;s=r}c[e+1888>>2]=17;c[e+1892>>2]=18;m=e+120|0;n=s;o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}function ne(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0;j=i;k=e+4|0;if((c[k>>2]|0)!=204){a[e]=5391693;a[e+1|0]=21061;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=204;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0}else{n=m*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=19;c[e+1892>>2]=20}if(d<=-90.0|d>=90.0){o=2;i=j;return o|0}h[f>>3]=+h[e+112>>3]*b;b=+h[e+24>>3];h[g>>3]=b*+_(+(+Te((d+90.0)*.5)));o=0;i=j;return o|0}function oe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0,o=0.0,p=0.0,q=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==204){l=e+24|0;m=+h[e+120>>3]}else{a[e]=5391693;a[e+1|0]=21061;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=204;k=e+8|0;n=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;o=+h[n>>3];if(o==0.0){h[n>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;p=1.0}else{q=o*3.141592653589793/180.0;h[e+112>>3]=q;o=1.0/q;h[e+120>>3]=o;p=o}c[e+1888>>2]=19;c[e+1892>>2]=20;l=n;m=p}h[f>>3]=m*b;h[g>>3]=+We(+Z(+(d/+h[l>>3])))*2.0+-90.0;i=j;return 0}function pe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==301){l=e+112|0;m=l;n=+h[l>>3];o=n*b;p=+Re(d);q=o*p;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;t=+h[l>>3];if(t==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;u=1.0}else{v=t*3.141592653589793/180.0;h[e+112>>3]=v;h[e+120>>3]=1.0/v;u=v}c[e+1888>>2]=21;c[e+1892>>2]=22;m=e+112|0;n=u;o=n*b;p=+Re(d);q=o*p;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}function qe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==301){l=+h[e+24>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=57.29577951308232}else{p=n*3.141592653589793/180.0;h[e+112>>3]=p;h[e+120>>3]=1.0/p;o=n}c[e+1888>>2]=21;c[e+1892>>2]=22;l=o}o=+S(+(d/l));m=e+120|0;if(o==0.0){q=0.0;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}q=+h[m>>3]*b/o;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}function re(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=302){a[e]=5390672;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=302;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=180.0;h[e+136>>3]=.005555555555555556}else{n=m*3.141592653589793;m=n/180.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m;h[e+128>>3]=n;h[e+136>>3]=1.0/n}c[e+1888>>2]=23;c[e+1892>>2]=24}n=+Se(d/3.0);h[f>>3]=+h[e+112>>3]*b*(1.0-n*n*4.0);h[g>>3]=n*+h[e+128>>3];i=j;return 0}function se(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==302){l=+h[e+136>>3]}else{a[e]=5390672;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=302;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=180.0;h[e+136>>3]=.005555555555555556;o=.005555555555555556}else{p=n*3.141592653589793;n=p/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;h[e+128>>3]=p;n=1.0/p;h[e+136>>3]=n;o=n}c[e+1888>>2]=23;c[e+1892>>2]=24;l=o}o=l*d;if(o>1.0|o<-1.0){q=2;i=j;return q|0}d=1.0-o*o*4.0;if(d==0.0){if(b==0.0){r=0.0}else{q=2;i=j;return q|0}}else{r=+h[e+120>>3]*b/d}h[f>>3]=r;h[g>>3]=+Ve(o)*3.0;q=0;i=j;return q|0}function te(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=303){a[e]=5001037;a[e+1|0]=19535;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=303;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;n=57.29577951308232}else{n=m}m=n*1.4142135623730951;h[e+112>>3]=m;h[e+120>>3]=m/90.0;h[e+128>>3]=1.0/m;h[e+136>>3]=90.0/n;h[e+144>>3]=.6366197723675814;c[e+1888>>2]=25;c[e+1892>>2]=26}if(+P(+d)==90.0){h[f>>3]=0.0;n=+P(+(+h[e+112>>3]));if(d<0.0){o=-n}else{o=n}h[g>>3]=o;i=j;return 0}if(d==0.0){h[f>>3]=+h[e+120>>3]*b;h[g>>3]=0.0;i=j;return 0}o=+Se(d)*3.141592653589793;l=0;d=o;n=-3.141592653589793;m=3.141592653589793;while(1){p=d-o+ +T(+d);if(p<0.0){if(p>-1.0e-13){q=d;break}else{r=d;s=m}}else{if(p<1.0e-13){q=d;break}else{r=n;s=d}}p=(r+s)*.5;k=l+1|0;if((k|0)<100){l=k;d=p;n=r;m=s}else{q=p;break}}s=q*.5;h[f>>3]=+h[e+120>>3]*b*+S(+s);h[g>>3]=+h[e+112>>3]*+T(+s);i=j;return 0}function ue(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==303){l=+h[e+24>>3]}else{a[e]=5001037;a[e+1|0]=19535;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=303;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;o=57.29577951308232}else{o=n}n=o*1.4142135623730951;h[e+112>>3]=n;h[e+120>>3]=n/90.0;h[e+128>>3]=1.0/n;h[e+136>>3]=90.0/o;h[e+144>>3]=.6366197723675814;c[e+1888>>2]=25;c[e+1892>>2]=26;l=o}o=d/l;l=2.0-o*o;if(l<=1.0e-12){if(l<-1.0e-12){p=2;i=j;return p|0}if(+P(+b)>1.0e-12){p=2;i=j;return p|0}else{q=0.0;r=0.0}}else{n=+Q(+l);q=n;r=+h[e+136>>3]*b/n}h[f>>3]=r;r=+h[e+128>>3]*d;d=+P(+r);do{if(d>1.0){if(d>1.000000000001){p=2;i=j;return p|0}else{s=(r<0.0?-1.0:1.0)+o*q/3.141592653589793;break}}else{n=+W(+r);s=n*+h[e+144>>3]+o*q/3.141592653589793}}while(0);q=+P(+s);do{if(q>1.0){if(q>1.000000000001){p=2;i=j;return p|0}else{t=s<0.0?-1.0:1.0;break}}else{t=s}}while(0);h[g>>3]=+Ve(t);p=0;i=j;return p|0}function ve(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==401){l=e+112|0}else{a[e]=5523777;a[e+1|0]=21577;a[e+2|0]=84;a[e+3|0]=0;c[k>>2]=401;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;o=57.29577951308232}else{o=n}n=o*2.0;p=o*n;m=e+112|0;h[m>>3]=p;o=1.0/(p*2.0);h[e+120>>3]=o;h[e+128>>3]=o*.25;h[e+136>>3]=1.0/n;c[e+1888>>2]=27;c[e+1892>>2]=28;l=m}n=+Re(d);o=+h[l>>3];p=b*.5;b=+Q(+(o/(n*+Re(p)+1.0)));h[f>>3]=+Se(p)*n*b*2.0;h[g>>3]=b*+Se(d);i=j;return 0}function we(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==401){l=+h[e+128>>3];m=+h[e+120>>3]}else{a[e]=5523777;a[e+1|0]=21577;a[e+2|0]=84;a[e+3|0]=0;c[k>>2]=401;k=e+8|0;n=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;o=+h[n>>3];if(o==0.0){h[n>>3]=57.29577951308232;p=57.29577951308232}else{p=o}o=p*2.0;q=p*o;h[e+112>>3]=q;p=1.0/(q*2.0);h[e+120>>3]=p;q=p*.25;h[e+128>>3]=q;h[e+136>>3]=1.0/o;c[e+1888>>2]=27;c[e+1892>>2]=28;l=q;m=p}p=1.0-b*b*l-d*d*m;if(p<0.0){if(p<-1.0e-13){r=2;i=j;return r|0}else{s=0.0}}else{s=p}p=+Q(+s);s=p*d/+h[e+24>>3];d=+P(+s);do{if(d>1.0){if(d>1.0000000000001){r=2;i=j;return r|0}else{t=s<0.0?-1.0:1.0;break}}else{t=s}}while(0);s=p*p*2.0+-1.0;d=p*b*+h[e+136>>3];if(s==0.0&d==0.0){u=0.0}else{u=+Xe(d,s)*2.0}h[f>>3]=u;h[g>>3]=+Ve(t);r=0;i=j;return r|0}function xe(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0,p=0.0,q=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=501?(Ld(d)|0)!=0:0){l=1;i=g;return l|0}m=b- +h[d+40>>3];b=+Re(m);if(b==0.0){l=2;i=g;return l|0}k=d+112|0;n=+h[k>>3]*a;o=d+128|0;a=+h[o>>3];p=+h[d+136>>3];q=a-p*+Se(m)/b;h[e>>3]=q*+Se(n);b=+h[o>>3];h[f>>3]=b-q*+Re(n);if((c[j>>2]|0)>0?q*+h[k>>3]<0.0:0){l=2;i=g;return l|0}l=0;i=g;return l|0}function ye(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=501?(Ld(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+128>>3]-b;b=+Q(+(a*a+l*l));j=d+40|0;if(+h[j>>3]<0.0){m=-b}else{m=b}if(m==0.0){n=0.0}else{n=+Xe(a/m,l/m)}h[e>>3]=n*+h[d+120>>3];n=+h[j>>3];h[f>>3]=n+ +We(+h[d+152>>3]-m*+h[d+144>>3]);k=0;i=g;return k|0}function ze(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0;g=i;if((c[d+4>>2]|0)!=502?(Md(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+112>>3]*a;if(b==-90.0){l=+h[d+176>>3]}else{a=+h[d+136>>3];m=+h[d+144>>3];n=+h[d+152>>3];l=a*+Q(+(m-n*+Se(b)))}h[e>>3]=l*+Se(k);b=+h[d+128>>3];h[f>>3]=b-l*+Re(k);j=0;i=g;return j|0}function Ae(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0;g=i;if((c[d+4>>2]|0)!=502?(Md(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){m=0.0}else{m=+Xe(a/l,k/l)}h[e>>3]=m*+h[d+120>>3];if(+P(+(l- +h[d+176>>3]))<1.0e-12){h[f>>3]=-90.0;j=0;i=g;return j|0}m=(+h[d+160>>3]-l*l)*+h[d+168>>3];if(!(+P(+m)>1.0)){h[f>>3]=+Ve(m);j=0;i=g;return j|0}if(+P(+(m+-1.0))<1.0e-12){h[f>>3]=90.0;j=0;i=g;return j|0}if(!(+P(+(m+1.0))<1.0e-12)){j=2;i=g;return j|0}h[f>>3]=-90.0;j=0;i=g;return j|0}function Be(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0;g=i;if((c[d+4>>2]|0)!=503?(Nd(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+112>>3]*a;a=+h[d+136>>3]-b;h[e>>3]=a*+Se(k);b=+h[d+128>>3];h[f>>3]=b-a*+Re(k);j=0;i=g;return j|0}function Ce(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0;g=i;if((c[d+4>>2]|0)!=503?(Nd(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){m=0.0}else{m=+Xe(a/l,k/l)}h[e>>3]=m*+h[d+120>>3];h[f>>3]=+h[d+136>>3]-l;j=0;i=g;return j|0}function De(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0;g=i;if((c[d+4>>2]|0)!=504?(Od(d)|0)!=0:0){j=1;i=g;return j|0}k=d+112|0;l=+h[k>>3];m=l*a;if(b==-90.0){if(l<0.0){n=0.0}else{j=2;i=g;return j|0}}else{l=+h[d+136>>3];a=+Te((90.0-b)*.5);n=l*+R(+a,+(+h[k>>3]))}h[e>>3]=n*+Se(m);a=+h[d+128>>3];h[f>>3]=a-n*+Re(m);j=0;i=g;return j|0}function Ee(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0;g=i;if((c[d+4>>2]|0)!=504?(Od(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){h[e>>3]=+h[d+120>>3]*0.0;if(+h[d+112>>3]<0.0){m=-90.0}else{j=2;i=g;return j|0}}else{b=+Xe(a/l,k/l);n=d+120|0;h[e>>3]=b*+h[n>>3];m=90.0- +We(+R(+(l*+h[d+144>>3]),+(+h[n>>3])))*2.0}h[f>>3]=m;j=0;i=g;return j|0}function Fe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0;j=i;k=e+4|0;l=c[k>>2]|0;if(!(+h[e+40>>3]==0.0)){if((l|0)!=601){Pd(e)|0}m=e+128|0;n=+h[m>>3]- +h[e+120>>3]*d;o=+h[e+24>>3]*b;p=o*+Re(d)/n;h[f>>3]=n*+Se(p);o=+h[m>>3];q=o-n*+Re(p);h[g>>3]=q;i=j;return 0}if((l|0)==301){l=e+112|0;r=l;s=+h[l>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;p=+h[l>>3];if(p==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;t=1.0}else{n=p*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;t=n}c[e+1888>>2]=21;c[e+1892>>2]=22;r=e+112|0;s=t}h[f>>3]=s*b*+Re(d);q=+h[r>>3]*d;h[g>>3]=q;i=j;return 0}function Ge(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0;j=i;k=e+40|0;l=+h[k>>3];m=e+4|0;n=c[m>>2]|0;if(l==0.0){if((n|0)==301){o=+h[e+24>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[m>>2]=301;m=e+8|0;p=e+24|0;c[m+0>>2]=0;c[m+4>>2]=0;c[m+8>>2]=0;c[m+12>>2]=0;q=+h[p>>3];if(q==0.0){h[p>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;r=57.29577951308232}else{s=q*3.141592653589793/180.0;h[e+112>>3]=s;h[e+120>>3]=1.0/s;r=q}c[e+1888>>2]=21;c[e+1892>>2]=22;o=r}r=+S(+(d/o));p=e+120|0;if(r==0.0){t=0.0}else{t=+h[p>>3]*b/r}h[f>>3]=t;h[g>>3]=+h[p>>3]*d;i=j;return 0}else{if((n|0)==601){u=l}else{Pd(e)|0;u=+h[k>>3]}k=e+128|0;l=+h[k>>3];t=l-d;d=+Q(+(b*b+t*t));if(u<0.0){v=-d}else{v=d}if(v==0.0){w=l;x=0.0}else{l=+Xe(b/v,t/v);w=+h[k>>3];x=l}l=(w-v)/+h[e+120>>3];h[g>>3]=l;w=+Re(l);if(w==0.0){y=0.0}else{y=x*(v/+h[e+24>>3])/w}h[f>>3]=y;i=j;return 0}return 0}function He(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=602){a[e]=5194576;a[e+1|0]=20291;a[e+2|0]=79;a[e+3|0]=0;c[k>>2]=602;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=114.59155902616465}else{n=m*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;h[e+128>>3]=m*2.0}c[e+1888>>2]=29;c[e+1892>>2]=30}m=+Re(d);n=+Se(d);o=n*b;if(n==0.0){h[f>>3]=+h[e+112>>3]*b;p=0.0;h[g>>3]=p;i=j;return 0}else{b=m/n;l=e+24|0;n=b*+h[l>>3];h[f>>3]=n*+Se(o);n=+h[l>>3];p=n*(d*3.141592653589793/180.0+b*(1.0- +Re(o)));h[g>>3]=p;i=j;return 0}return 0}function Ie(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0,y=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==602){l=+h[e+120>>3]}else{a[e]=5194576;a[e+1|0]=20291;a[e+2|0]=79;a[e+3|0]=0;c[k>>2]=602;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=114.59155902616465;o=1.0}else{p=n*3.141592653589793/180.0;h[e+112>>3]=p;q=1.0/p;h[e+120>>3]=q;h[e+128>>3]=n*2.0;o=q}c[e+1888>>2]=29;c[e+1892>>2]=30;l=o}o=+P(+(l*d));if(o<1.0e-12){h[f>>3]=l*b;h[g>>3]=0.0;i=j;return 0}if(+P(+(o+-90.0))<1.0e-12){h[f>>3]=0.0;h[g>>3]=d<0.0?-90.0:90.0;i=j;return 0}o=d>0.0?90.0:-90.0;l=b*b;m=e+112|0;q=d-o*+h[m>>3];k=e+128|0;n=-999.0;p=l+q*q;r=0;q=0.0;s=o;while(1){if(n<-100.0){t=(q+s)*.5}else{o=p/(p-n);if(!(o<.1)){if(o>.9){u=.9}else{u=o}}else{u=.1}t=s-(s-q)*u}h[g>>3]=t;v=d-t*+h[m>>3];w=+Te(t);o=l+v*(v- +h[k>>3]/w);if(+P(+o)<1.0e-12){break}if(+P(+(s-q))<1.0e-12){break}x=o>0.0;y=+h[g>>3];r=r+1|0;if((r|0)>=64){break}else{n=x?n:o;p=x?o:p;q=x?q:y;s=x?y:s}}s=+h[e+24>>3]-w*v;v=w*b;if(s==0.0&v==0.0){h[f>>3]=0.0;i=j;return 0}else{b=+Xe(v,s);h[f>>3]=b/+Se(+h[g>>3]);i=j;return 0}return 0}function Je(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=701){a[e]=4412244;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=701;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=31;c[e+1892>>2]=32}n=+Re(d);m=n*+Re(b);o=n*+Se(b);b=+Se(d);l=m>b;d=l?m:b;k=o>d;n=k?o:d;d=-m;p=n1.0){if(u>1.000000000001){z=2;i=j;return z|0}else{A=w<0.0?-1.0:1.0;break}}else{A=w}}while(0);w=+P(+y);do{if(w>1.0){if(w>1.000000000001){z=2;i=j;return z|0}else{B=y<0.0?-1.0:1.0;break}}else{B=y}}while(0);l=e+112|0;h[f>>3]=(v+A)*+h[l>>3];h[g>>3]=(x+B)*+h[l>>3];z=0;i=j;return z|0}function Ke(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==701){l=+h[e+120>>3]}else{a[e]=4412244;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=701;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=31;c[e+1892>>2]=32;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){o=r+-4.0;d=-1.0/+Q(+(b*b+(o*o+1.0)));s=d;t=o*d;u=-(b*d);break}if(r>1.0){d=r+-2.0;o=1.0/+Q(+(b*b+(d*d+1.0)));s=-(d*o);t=o;u=b*o;break}if(b>1.0){o=b+-2.0;d=1.0/+Q(+(o*o+(r*r+1.0)));s=-(o*d);t=r*d;u=d;break}if(b<-1.0){d=b+2.0;o=-1.0/+Q(+(d*d+(r*r+1.0)));l=-o;s=d*l;t=r*l;u=o;break}else{o=1.0/+Q(+(b*b+(r*r+1.0)));s=o;t=r*o;u=b*o;break}}else{o=r+-6.0;l=-1.0/+Q(+(b*b+(o*o+1.0)));d=-l;s=o*d;t=l;u=b*d}}while(0);if(s==0.0&t==0.0){v=0.0}else{v=+Xe(t,s)}h[f>>3]=v;h[g>>3]=+Ve(u);q=0;i=j;return q|0}function Le(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0,E=0.0,F=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=702){a[e]=4412227;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=702;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=33;c[e+1892>>2]=34}n=+Re(d);m=n*+Re(b);o=n*+Se(b);b=+Se(d);l=m>b;d=l?m:b;k=o>d;n=k?o:d;d=-m;p=n1.0e-16){A=u*u}else{A=0.0}if(w>1.0e-16){B=w*w}else{B=0.0}if(b>1.0e-16){C=u*w*.15384112298488617}else{C=0.0}b=o*(u+m*(u*(-.15959623456001282-m*(u*-.021776249632239342+.07591962069272995))+(w*(u*.004869491793215275+m*-.1316167116165161+n*(B*.10695946961641312+(A*-.1782512068748474+(u*.08097013086080551+.14118963479995728+w*-.2815285325050354+C))))+1.374848484992981)));o=y*(w+n*(w*(-.15959623456001282-n*(w*-.021776249632239342+.07591962069272995))+(u*(w*.004869491793215275+n*-.1316167116165161+m*(A*.10695946961641312+(B*-.1782512068748474+(u*-.2815285325050354+(w*.08097013086080551+.14118963479995728)+C))))+1.374848484992981)));C=+P(+b);do{if(C>1.0){if(C>1.0000001000000012){D=2;i=j;return D|0}else{E=b<0.0?-1.0:1.0;break}}else{E=b}}while(0);b=+P(+o);do{if(b>1.0){if(b>1.0000001000000012){D=2;i=j;return D|0}else{F=o<0.0?-1.0:1.0;break}}else{F=o}}while(0);l=e+112|0;h[f>>3]=(x+E)*+h[l>>3];h[g>>3]=+h[l>>3]*(z+F);D=0;i=j;return D|0}function Me(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==702){l=+h[e+120>>3]}else{a[e]=4412227;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=702;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=33;c[e+1892>>2]=34;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){s=3;t=r+-4.0;u=b;break}if(r>1.0){s=2;t=r+-2.0;u=b;break}if(b>1.0){s=0;t=r;u=b+-2.0;break}if(b<-1.0){s=5;t=r;u=b+2.0}else{s=1;t=r;u=b}}else{s=4;t=r+-6.0;u=b}}while(0);b=t*t;r=u*u;o=t;t=o+o*(1.0-b)*(b*(b*(b*(b*(b*(b*.025843750685453415+.25795793533325195)+-.6293006539344788)+.5485238432884216)+-.22797055542469025)+-.07629968971014023)+-.2729269564151764+r*(b*(b*(b*(b*(b*-.5302233695983887+1.715475082397461)+-1.7411445379257202)+.48051509261131287)+-.014715650118887424)+-.028194520622491837+r*(b*(b*(b*(b*-.8318046927452087+.9893810153007507)+.30803316831588745)+-.5680093765258789)+.27058160305023193+r*(b*(b*(b*.08693841099739075+-.9367857575416565)+1.5088008642196655)+-.6044155955314636+r*(b*(b*.3388744592666626+-1.4160192012786865)+.934120774269104+r*(r*.14381584525108337+(b*.5203223824501038+-.6391530632972717)))))));o=u;u=o+o*(1.0-r)*(r*(r*(r*(r*(r*(r*.025843750685453415+.25795793533325195)+-.6293006539344788)+.5485238432884216)+-.22797055542469025)+-.07629968971014023)+-.2729269564151764+b*(r*(r*(r*(r*(r*-.5302233695983887+1.715475082397461)+-1.7411445379257202)+.48051509261131287)+-.014715650118887424)+-.028194520622491837+b*(r*(r*(r*(r*-.8318046927452087+.9893810153007507)+.30803316831588745)+-.5680093765258789)+.27058160305023193+b*(r*(r*(r*.08693841099739075+-.9367857575416565)+1.5088008642196655)+-.6044155955314636+b*(r*(r*.3388744592666626+-1.4160192012786865)+.934120774269104+b*(r*.5203223824501038+-.6391530632972717+b*.14381584525108337))))));switch(s|0){case 1:{b=1.0/+Q(+(u*u+t*t+1.0));v=b;w=t*b;x=u*b;break};case 4:{b=-1.0/+Q(+(u*u+t*t+1.0));v=-t*b;w=b;x=-u*b;break};case 0:{b=1.0/+Q(+(u*u+t*t+1.0));v=-u*b;w=t*b;x=b;break};case 5:{b=-1.0/+Q(+(u*u+t*t+1.0));v=-u*b;w=-t*b;x=b;break};case 3:{b=-1.0/+Q(+(u*u+t*t+1.0));v=b;w=t*b;x=-u*b;break};case 2:{b=1.0/+Q(+(u*u+t*t+1.0));v=-t*b;w=b;x=u*b;break};default:{v=0.0;w=0.0;x=0.0}}if(v==0.0&w==0.0){y=0.0}else{y=+Xe(w,v)}h[f>>3]=y;h[g>>3]=+Ve(x);q=0;i=j;return q|0}function Ne(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0,t=0.0,u=0,v=0.0,w=0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=703){a[e]=4412241;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=703;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=35;c[e+1892>>2]=36}if(+P(+d)==90.0){h[f>>3]=0.0;n=+P(+(+h[e+112>>3]*2.0));if(d<0.0){o=-n}else{o=n}h[g>>3]=o;p=0;i=j;return p|0}o=+Re(d);n=o*+Re(b);m=o*+Se(b);o=+Se(d);l=n>o;q=l?n:o;k=m>q;r=k?m:q;q=-n;s=r180.0){z=y+-360.0}else{z=y}y=z*.017453292519943295;A=o;B=(v*v+y*y)*.5;C=0.0;D=m;E=0.0}else{A=o;B=x;C=0.0;D=m;E=0.0}break};case 3:{if(x<1.0e-8){y=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v<0.0){F=v+360.0}else{F=v}v=(180.0-F)*3.141592653589793/180.0;A=o;B=(y*y+v*v)*.5;C=4.0;D=r;E=0.0}else{A=o;B=x;C=4.0;D=r;E=0.0}break};case 0:{if(x<1.0e-8){r=(90.0-d)*3.141592653589793/180.0;A=q;B=r*r*.5;C=0.0;D=m;E=2.0}else{A=q;B=x;C=0.0;D=m;E=2.0}break};case 2:{if(x<1.0e-8){r=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v<-180.0){G=v+360.0}else{G=v}v=(90.0-G)*3.141592653589793/180.0;A=o;B=(r*r+v*v)*.5;C=2.0;D=q;E=0.0}else{A=o;B=x;C=2.0;D=q;E=0.0}break};case 4:{if(x<1.0e-8){q=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v>180.0){H=v+-360.0}else{H=v}v=H*((H+90.0)*3.141592653589793/180.0);A=o;B=(q*q+v*v)*.5;C=6.0;D=n;E=0.0}else{A=o;B=x;C=6.0;D=n;E=0.0}break};case 5:{if(x<1.0e-8){o=(d+90.0)*3.141592653589793/180.0;A=n;B=o*o*.5;C=0.0;D=m;E=-2.0}else{A=n;B=x;C=0.0;D=m;E=-2.0}break};default:{A=0.0;B=x;C=0.0;D=0.0;E=0.0}}do{if(!(D==0.0&A==0.0)){x=+P(+A);if(x<=-D){m=A/D;n=m*m+1.0;o=-+Q(+(B/(1.0-1.0/+Q(+(n+1.0)))));d=+We(m);I=o;J=o/15.0*(d- +Ve(m/+Q(+(n+n))));break}if(D>=x){x=A/D;n=x*x+1.0;m=+Q(+(B/(1.0-1.0/+Q(+(n+1.0)))));d=+We(x);I=m;J=m/15.0*(d- +Ve(x/+Q(+(n+n))));break}n=+P(+D);if(n<-A){x=D/A;d=x*x+1.0;m=-+Q(+(B/(1.0-1.0/+Q(+(d+1.0)))));o=+We(x);I=m/15.0*(o- +Ve(x/+Q(+(d+d))));J=m;break}if(A>n){n=D/A;m=n*n+1.0;d=+Q(+(B/(1.0-1.0/+Q(+(m+1.0)))));x=+We(n);I=d/15.0*(x- +Ve(n/+Q(+(m+m))));J=d}else{I=0.0;J=0.0}}else{I=0.0;J=0.0}}while(0);B=+P(+I);do{if(B>1.0){if(B>1.000000000001){p=2;i=j;return p|0}else{K=I<0.0?-1.0:1.0;break}}else{K=I}}while(0);I=+P(+J);do{if(I>1.0){if(I>1.000000000001){p=2;i=j;return p|0}else{L=J<0.0?-1.0:1.0;break}}else{L=J}}while(0);l=e+112|0;h[f>>3]=(C+K)*+h[l>>3];h[g>>3]=(E+L)*+h[l>>3];p=0;i=j;return p|0}function Oe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,S=0.0,T=0.0,U=0.0,V=0.0,W=0.0,X=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==703){l=+h[e+120>>3]}else{a[e]=4412241;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=703;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=35;c[e+1892>>2]=36;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){s=3;t=r+-4.0;u=b;break}if(r>1.0){s=2;t=r+-2.0;u=b;break}if(b>1.0){s=0;t=r;u=b+-2.0;break}if(b<-1.0){s=5;t=r;u=b+2.0}else{s=1;t=r;u=b}}else{s=4;t=r+-6.0;u=b}}while(0);e=+P(+t)>+P(+u);if(e){if(t==0.0){v=0.0;w=1.0;x=0.0;y=1.0;z=30}else{b=u*15.0/t;r=+Se(b);o=r/(+Re(b)+-.7071067811865475);b=o*o+1.0;A=t*t*(1.0-1.0/+Q(+(b+1.0)));B=o;C=b;z=28}}else{if(u==0.0){v=0.0;w=1.0;x=0.0;y=1.0;z=30}else{b=t*15.0/u;o=+Se(b);r=o/(+Re(b)+-.7071067811865475);b=r*r+1.0;A=u*u*(1.0-1.0/+Q(+(b+1.0)));B=r;C=b;z=28}}if((z|0)==28){b=1.0-A;if(b<-1.0){if(b<-1.000000000001){q=2;i=j;return q|0}else{D=B;E=-1.0;F=0.0}}else{v=B;w=b;x=A;y=C;z=30}}if((z|0)==30){D=v;E=w;F=+Q(+(x*(2.0-x)/y))}a:do{switch(s|0){case 2:{if(e){if(t>0.0){G=-F}else{G=F}H=G;I=E;J=-(D*G);break a}else{if(u<0.0){K=-F}else{K=F}H=-(D*K);I=E;J=K;break a}break};case 3:{y=-E;if(e){if(t>0.0){L=-F}else{L=F}H=y;I=L;J=-(D*L);break a}else{if(u<0.0){M=-F}else{M=F}H=y;I=-(D*M);J=M;break a}break};case 1:{if(e){if(t<0.0){N=-F}else{N=F}H=E;I=N;J=D*N;break a}else{if(u<0.0){O=-F}else{O=F}H=E;I=D*O;J=O;break a}break};case 5:{y=-E;if(e){if(t<0.0){R=-F}else{R=F}H=D*R;I=R;J=y;break a}else{if(u<0.0){S=-F}else{S=F}H=S;I=D*S;J=y;break a}break};case 4:{y=-E;if(e){if(t<0.0){T=-F}else{T=F}H=T;I=y;J=D*T;break a}else{if(u<0.0){U=-F}else{U=F}H=D*U;I=y;J=U;break a}break};case 0:{if(e){if(t<0.0){V=-F}else{V=F}H=-(D*V);I=V;J=E;break a}else{if(u>0.0){W=-F}else{W=F}H=W;I=-(D*W);J=E;break a}break};default:{H=0.0;I=0.0;J=0.0}}}while(0);if(H==0.0&I==0.0){X=0.0}else{X=+Xe(I,H)}h[f>>3]=X;h[g>>3]=+Ve(J);q=0;i=j;return q|0}function Pe(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;f=i;g=+Re(b);j=+Se(b);k=a- +h[c>>3];a=+Re(k);l=+Se(k);m=c+32|0;n=c+24|0;o=j*+h[m>>3]-a*g*+h[n>>3];if(+P(+o)<1.0e-5){p=+Re(+h[c+8>>3]+b);q=(1.0-a)*g*+h[n>>3]-p}else{q=o}o=g*l;if(q!=0.0|o!=-0.0){r=+Xe(-o,q)}else{r=k+-180.0}l=r+ +h[c+16>>3];h[d>>3]=l;if(!(l>180.0)){if(l<-180.0){h[d>>3]=l+360.0}}else{h[d>>3]=l+-360.0}if(+qa(+k,180.0)==0.0){k=a*+h[c+8>>3]+b;if(k>90.0){s=180.0-k}else{s=k}h[e>>3]=s;if(!(s<-90.0)){i=f;return 0}h[e>>3]=-180.0-s;i=f;return 0}s=j*+h[n>>3]+a*g*+h[m>>3];if(!(+P(+s)>.99)){h[e>>3]=+Ve(s);i=f;return 0}g=+Ue(+Q(+(o*o+q*q)));if(s<0.0){h[e>>3]=-g;i=f;return 0}else{h[e>>3]=g;i=f;return 0}return 0}function Qe(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;f=i;g=+Re(b);j=+Se(b);k=a- +h[c+16>>3];a=+Re(k);l=+Se(k);m=c+32|0;n=c+24|0;o=j*+h[m>>3]-a*g*+h[n>>3];if(+P(+o)<1.0e-5){p=+Re(+h[c+8>>3]+b);q=(1.0-a)*g*+h[n>>3]-p}else{q=o}o=g*l;if(q!=0.0|o!=-0.0){r=+Xe(-o,q)}else{r=k+180.0}l=r+ +h[c>>3];h[d>>3]=l;if(!(+h[c>>3]>=0.0)){if(l>0.0){r=l+-360.0;h[d>>3]=r;s=r}else{s=l}}else{if(l<0.0){r=l+360.0;h[d>>3]=r;s=r}else{s=l}}if(!(s>360.0)){if(s<-360.0){h[d>>3]=s+360.0}}else{h[d>>3]=s+-360.0}if(+qa(+k,180.0)==0.0){k=a*+h[c+8>>3]+b;if(k>90.0){t=180.0-k}else{t=k}h[e>>3]=t;if(!(t<-90.0)){i=f;return 0}h[e>>3]=-180.0-t;i=f;return 0}t=j*+h[n>>3]+a*g*+h[m>>3];if(!(+P(+t)>.99)){h[e>>3]=+Ve(t);i=f;return 0}g=+Ue(+Q(+(o*o+q*q)));if(t<0.0){h[e>>3]=-g;i=f;return 0}else{h[e>>3]=g;i=f;return 0}return 0}function Re(a){a=+a;var b=0,c=0.0,d=0.0,e=0.0;b=i;c=+qa(+a,360.0);d=+P(+c);if(!(c==0.0)){if(!(d==90.0)){if(!(d==180.0)){if(d==270.0){e=0.0}else{e=+S(+(a*.017453292519943295))}}else{e=-1.0}}else{e=0.0}}else{e=1.0}i=b;return+e}function Se(a){a=+a;var b=0,c=0.0,d=0.0;b=i;c=+qa(+(a+-90.0),360.0);if(!(c==0.0)){if(!(c==90.0)){if(!(c==180.0)){if(c==270.0){d=0.0}else{d=+T(+(a*.017453292519943295))}}else{d=-1.0}}else{d=0.0}}else{d=1.0}i=b;return+d}function Te(a){a=+a;var b=0,c=0.0,d=0.0;b=i;c=+qa(+a,360.0);if(!(c==0.0)?!(+P(+c)==180.0):0){if(!(c==45.0|c==225.0)){if(c==-135.0|c==-315.0){d=-1.0}else{d=+U(+(a*.017453292519943295))}}else{d=1.0}}else{d=0.0}i=b;return+d}function Ue(a){a=+a;var b=0,c=0.0,d=0;b=i;if(!(a>=1.0)){if(!(a==0.0)){if(a<=-1.0&a+1.0>-1.0e-10){c=180.0}else{d=5}}else{c=90.0}}else{if(a+-1.0<1.0e-10){c=0.0}else{d=5}}if((d|0)==5){c=+V(+a)*57.29577951308232}i=b;return+c}function Ve(a){a=+a;var b=0,c=0.0,d=0;b=i;if(!(a<=-1.0)){if(!(a==0.0)){if(a>=1.0&a+-1.0<1.0e-10){c=90.0}else{d=5}}else{c=0.0}}else{if(a+1.0>-1.0e-10){c=-90.0}else{d=5}}if((d|0)==5){c=+W(+a)*57.29577951308232}i=b;return+c}function We(a){a=+a;var b=0,c=0.0;b=i;if(!(a==-1.0)){if(!(a==0.0)){if(a==1.0){c=45.0}else{c=+X(+a)*57.29577951308232}}else{c=0.0}}else{c=-45.0}i=b;return+c}function Xe(a,b){a=+a;b=+b;var c=0,d=0.0,e=0;c=i;if(a==0.0){if(!(b>=0.0)){if(b<0.0){d=180.0}else{e=7}}else{d=0.0}}else{if(b==0.0){if(!(a>0.0)){if(a<0.0){d=-90.0}else{e=7}}else{d=90.0}}else{e=7}}if((e|0)==7){d=+Y(+a,+b)*57.29577951308232}i=c;return+d}function Ye(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;i=i+32|0;e=d;f=d+8|0;if((c[a+5968>>2]|0)!=1){i=d;return}g=a+3324|0;if((c[g>>2]|0)==2){c[g>>2]=3;c[a+5976>>2]=0;c[a+6784>>2]=0;c[a+7592>>2]=0;c[a+8400>>2]=0;i=d;return}g=a+5976|0;if((Ec(b,12288,g)|0)!=0){h=c[g>>2]|0;g=(h|0)<0;if(!g){j=(h<<3)+8|0;k=0;while(1){Eg(a+(k*80|0)+5984|0,0,j|0)|0;if((k|0)==(h|0)){break}else{k=k+1|0}}if(!g){g=h+1|0;k=0;j=g;while(1){if((h-k|0)>=0){l=0;do{c[e>>2]=k;c[e+4>>2]=l;Na(f|0,12360,e|0)|0;Lc(b,f,a+(k*80|0)+(l<<3)+5984|0)|0;l=l+1|0}while((l|0)!=(j|0))}k=k+1|0;if((k|0)==(g|0)){break}else{j=j+ -1|0}}}}}else{_b(12296)}j=a+6784|0;if((Ec(b,12368,j)|0)!=0){g=c[j>>2]|0;j=(g|0)<0;if(!j){k=(g<<3)+8|0;h=0;while(1){Eg(a+(h*80|0)+6792|0,0,k|0)|0;if((h|0)==(g|0)){break}else{h=h+1|0}}if(!j){j=g+1|0;h=0;k=j;while(1){if((g-h|0)>=0){l=0;do{c[e>>2]=h;c[e+4>>2]=l;Na(f|0,12440,e|0)|0;Lc(b,f,a+(h*80|0)+(l<<3)+6792|0)|0;l=l+1|0}while((l|0)!=(k|0))}h=h+1|0;if((h|0)==(j|0)){break}else{k=k+ -1|0}}}}}else{_b(12376)}k=a+7592|0;if((Ec(b,12448,k)|0)!=0){j=c[k>>2]|0;k=(j|0)<0;if(!k){h=(j<<3)+8|0;g=0;while(1){Eg(a+(g*80|0)+7600|0,0,h|0)|0;if((g|0)==(j|0)){break}else{g=g+1|0}}if(!k){k=j+1|0;g=0;h=k;while(1){if((j-g|0)>=0){l=0;do{c[e>>2]=g;c[e+4>>2]=l;Na(f|0,12528,e|0)|0;Lc(b,f,a+(g*80|0)+(l<<3)+7600|0)|0;l=l+1|0}while((l|0)!=(h|0))}g=g+1|0;if((g|0)==(k|0)){break}else{h=h+ -1|0}}}}}else{_b(12464)}h=a+8400|0;if((Ec(b,12544,h)|0)==0){_b(12560);i=d;return}k=c[h>>2]|0;h=(k|0)<0;if(h){i=d;return}g=(k<<3)+8|0;j=0;while(1){Eg(a+(j*80|0)+8408|0,0,g|0)|0;if((j|0)==(k|0)){break}else{j=j+1|0}}if(h){i=d;return}h=k+1|0;j=0;g=h;while(1){if((k-j|0)>=0){l=0;do{c[e>>2]=j;c[e+4>>2]=l;Na(f|0,12624,e|0)|0;Lc(b,f,a+(j*80|0)+(l<<3)+8408|0)|0;l=l+1|0}while((l|0)!=(g|0))}j=j+1|0;if((j|0)==(h|0)){break}else{g=g+ -1|0}}i=d;return}function Ze(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0,y=0.0,z=0.0;g=i;i=i+80|0;j=g;if((c[a+5968>>2]|0)!=1){h[e>>3]=b;k=d;h[f>>3]=k;i=g;return}l=c[a+7592>>2]|0;m=c[a+8400>>2]|0;n=b- +h[a+16>>3];o=d- +h[a+24>>3];if((l|0)>=0){p=0;while(1){q=l-p|0;r=+h[a+(q*80|0)+(p<<3)+7600>>3];s=j+(p<<3)|0;h[s>>3]=r;if((p|0)>0){t=p;u=r;do{t=t+ -1|0;u=o*u+ +h[a+(q*80|0)+(t<<3)+7600>>3]}while((t|0)>0);h[s>>3]=u}if((p|0)==(l|0)){break}else{p=p+1|0}}r=+h[j>>3];if((l|0)>0){p=l+1|0;t=l;v=r;while(1){w=n*v+ +h[j+(p-t<<3)>>3];l=t+ -1|0;if((l|0)>0){t=l;v=w}else{x=j;y=w;break}}}else{x=j;y=r}}else{x=j;y=0.0}h[e>>3]=y;if((m|0)>=0){t=0;while(1){p=m-t|0;y=+h[a+(p*80|0)+(t<<3)+8408>>3];l=j+(t<<3)|0;h[l>>3]=y;if((t|0)>0){q=t;r=y;do{q=q+ -1|0;r=o*r+ +h[a+(p*80|0)+(q<<3)+8408>>3]}while((q|0)>0);h[l>>3]=r}if((t|0)==(m|0)){break}else{t=t+1|0}}o=+h[x>>3];if((m|0)>0){t=m+1|0;a=m;u=o;while(1){y=n*u+ +h[j+(t-a<<3)>>3];m=a+ -1|0;if((m|0)>0){a=m;u=y}else{z=y;break}}}else{z=o}}else{z=+h[x>>3]}h[f>>3]=z;h[e>>3]=+h[e>>3]+b;k=+h[f>>3]+d;h[f>>3]=k;i=g;return}function _e(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0,y=0.0,z=0.0;g=i;i=i+80|0;j=g;if((c[a+5968>>2]|0)!=1){h[e>>3]=b;k=d;h[f>>3]=k;i=g;return}l=c[a+5976>>2]|0;m=c[a+6784>>2]|0;n=b- +h[a+16>>3];o=d- +h[a+24>>3];if((l|0)>=0){p=0;while(1){q=l-p|0;r=+h[a+(q*80|0)+(p<<3)+5984>>3];s=j+(p<<3)|0;h[s>>3]=r;if((p|0)>0){t=p;u=r;do{t=t+ -1|0;u=o*u+ +h[a+(q*80|0)+(t<<3)+5984>>3]}while((t|0)>0);h[s>>3]=u}if((p|0)==(l|0)){break}else{p=p+1|0}}r=+h[j>>3];if((l|0)>0){p=l+1|0;t=l;v=r;while(1){w=n*v+ +h[j+(p-t<<3)>>3];l=t+ -1|0;if((l|0)>0){t=l;v=w}else{x=j;y=w;break}}}else{x=j;y=r}}else{x=j;y=0.0}h[e>>3]=y;if((m|0)>=0){t=0;while(1){p=m-t|0;y=+h[a+(p*80|0)+(t<<3)+6792>>3];l=j+(t<<3)|0;h[l>>3]=y;if((t|0)>0){q=t;r=y;do{q=q+ -1|0;r=o*r+ +h[a+(p*80|0)+(q<<3)+6792>>3]}while((q|0)>0);h[l>>3]=r}if((t|0)==(m|0)){break}else{t=t+1|0}}o=+h[x>>3];if((m|0)>0){t=m+1|0;a=m;u=o;while(1){y=n*u+ +h[j+(t-a<<3)>>3];m=a+ -1|0;if((m|0)>0){a=m;u=y}else{z=y;break}}}else{z=o}}else{z=+h[x>>3]}h[f>>3]=z;h[e>>3]=+h[e>>3]+b;k=+h[f>>3]+d;h[f>>3]=k;i=g;return}function $e(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;if((Dg(b|0)|0)<9){c[a+5968>>2]=0;i=d;return}e=a+5968|0;if((Ag(b+8|0,12640,4)|0)==0){c[e>>2]=1;i=d;return}else{c[e>>2]=0;i=d;return}}function af(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0.0,k=0.0,l=0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;e=i;i=i+16|0;f=e;c[3162]=0;g=(d|0)==0;h=b;while(1){if((a[h]|0)==32){h=h+1|0}else{break}}b=g?f:d;j=+wg(h,b);d=c[b>>2]|0;if(($f(h,46)|0)!=0){c[3162]=46}f=a[d]|0;g=f<<24>>24;switch(f<<24>>24){case 32:case 58:case 100:case 104:case 109:{break};default:{k=j;i=e;return+k}}l=d;if((l-h|0)>=5){k=j;i=e;return+k}m=d+1|0;n=a[m]|0;if(!(((n<<24>>24)+ -48|0)>>>0<10)){if(!(n<<24>>24==32)){k=j;i=e;return+k}if(!(((a[d+2|0]|0)+ -48|0)>>>0<10)){k=j;i=e;return+k}}c[3162]=g;c[b>>2]=m;if((a[h]|0)==45){o=-j;p=-1.0}else{o=j;p=1.0}j=+wg(m,b);do{if(!(f<<24>>24==109)){m=c[b>>2]|0;h=a[m]|0;if(h<<24>>24==32|h<<24>>24==58|h<<24>>24==109?(m-l|0)<4:0){h=m+1|0;g=a[h]|0;if(!(((g<<24>>24)+ -48|0)>>>0<10)){if(!(g<<24>>24==32)){q=o;r=j;s=0.0;break}if(!(((a[m+2|0]|0)+ -48|0)>>>0<10)){q=o;r=j;s=0.0;break}}c[b>>2]=h;q=o;r=j;s=+wg(h,b)}else{q=o;r=j;s=0.0}}else{q=0.0;r=o;s=j}}while(0);k=p*(q+r/60.0+s/3600.0);i=e;return+k}function bf(a,b,d,e,f,j,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;j=j|0;l=+l;m=m|0;n=n|0;var o=0,p=0,q=0,r=0,s=0.0,t=0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0;o=i;i=i+48|0;p=o;q=o+36|0;r=o+32|0;s=l;c[r>>2]=0;if((c[58]|0)!=0){c[p>>2]=b;c[p+4>>2]=d;c[p+8>>2]=e;t=p+12|0;h[k>>3]=s;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];c[p+20>>2]=m;c[p+24>>2]=n;Ma(12656,p|0)|0}t=cf(a,e,r,b,d,m,n)|0;n=c[r>>2]|0;Zf(n,t,4,4);l=+g[n>>2];u=+g[n+(t+ -1<<2)>>2];r=t+1|0;if((r|0)<2){v=1}else{v=(r|0)/2|0}r=v+ -1|0;m=n+(r<<2)|0;w=+g[m>>2];if(((t|0)%2|0|0)!=1&(v|0)<(t|0)){x=(w+ +g[n+(v<<2)>>2])*.5}else{x=w}w=+(t|0);d=~~(w*.5);b=(d|0)<5?5:d;d=~~(w*.01+.5);e=(d|0)<1?1:d;d=df(n,t,o+40|0,q,2.5,e,5)|0;if((d|0)<(b|0)){g[f>>2]=l;y=u}else{w=+g[q>>2];if(s>0.0){z=w/s;g[q>>2]=z;A=z}else{A=w}w=x- +(r|0)*A;g[f>>2]=l>w?l:w;w=x+ +(t-v|0)*A;y=u>2]=y;if((c[58]|0)==0){hg(n);i=o;return}y=+g[m>>2];h[k>>3]=l;c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];m=p+8|0;h[k>>3]=u;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];m=p+16|0;h[k>>3]=y;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];m=p+24|0;h[k>>3]=x;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];Ma(12704,p|0)|0;c[p>>2]=b;c[p+4>>2]=e;c[p+8>>2]=d;Ma(12752,p|0)|0;x=+g[f>>2];y=+g[j>>2];h[k>>3]=+g[q>>2];c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];c[p+8>>2]=v;v=p+12|0;h[k>>3]=x;c[v>>2]=c[k>>2];c[v+4>>2]=c[k+4>>2];v=p+20|0;h[k>>3]=y;c[v>>2]=c[k>>2];c[v+4>>2]=c[k+4>>2];Ma(12800,p|0)|0;hg(n);i=o;return}function cf(d,e,f,j,k,l,m){d=d|0;e=e|0;f=f|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;n=i;i=i+16|0;o=n;p=(j|0)<(m|0)?j:m;q=(p|0)<1?1:p;p=j+ -1|0;r=(p+q|0)/(q|0)|0;s=(r|0)<2?2:r;r=(p+s|0)/(s|0)|0;p=(r|0)<1?1:r;if((c[58]|0)==0){t=1}else{c[o>>2]=q;c[o+4>>2]=s;c[o+8>>2]=p;Ma(12856,o|0)|0;t=(c[58]|0)==0}q=(l|0)/(m|0)|0;m=(q|0)<1?1:q;q=(l+ -1+p|0)/(p|0)|0;l=(q|0)>(k|0)?k:q;q=(m|0)>(l|0)?m:l;l=(k|0)/(q|0)|0;r=(l|0)<2?2:l;u=(k+ -1+r|0)/(r|0)|0;if(!t){c[o>>2]=m;c[o+4>>2]=q;c[o+8>>2]=r;c[o+12>>2]=u;Ma(12912,o|0)|0}o=aa(u,p)|0;u=gg(o<<2)|0;c[f>>2]=u;f=j<<2;q=gg(f)|0;m=(r+1|0)/2|0;if((m|0)>=(k|0)){v=0;hg(q);i=n;return v|0}t=(p|0)>0;w=(j|0)>0;x=j<<1;y=j<<3;if((e|0)==8){z=m;A=0;B=u;while(1){C=aa(z+ -1|0,j)|0;if(w){D=0;do{g[q+(D<<2)>>2]=+(a[d+(D+C)|0]|0);D=D+1|0}while((D|0)!=(j|0))}a:do{if(t){D=0;C=0;while(1){g[B+(D<<2)>>2]=+g[q+(C<<2)>>2];E=D+1|0;if((E|0)==(p|0)){break a}D=E;C=C+s|0}}}while(0);C=A+p|0;if((C|0)>(o|0)){v=C;F=29;break}D=z+r|0;if((D|0)<(k|0)){z=D;A=C;B=B+(p<<2)|0}else{v=C;F=29;break}}if((F|0)==29){hg(q);i=n;return v|0}}B=(aa(m+ -1|0,j)|0)<<2;A=(aa((l|0)>2?l:2,j)|0)<<2;l=j<<2;z=0;C=m;m=0;D=u;while(1){u=d+(B+(aa(A,z)|0))|0;if((e|0)==32){E=d+(aa(f,C+ -1|0)|0)|0;if(w){G=0;do{g[q+(G<<2)>>2]=+(c[E+(G<<2)>>2]|0);G=G+1|0}while((G|0)!=(j|0))}}else if((e|0)==-32){if(w){Kg(q|0,u|0,l|0)|0}}else if((e|0)==-64){G=d+(aa(y,C+ -1|0)|0)|0;if(w){E=0;do{g[q+(E<<2)>>2]=+h[G+(E<<3)>>3];E=E+1|0}while((E|0)!=(j|0))}}else if((e|0)==16?(E=d+(aa(x,C+ -1|0)|0)|0,w):0){G=0;do{g[q+(G<<2)>>2]=+(b[E+(G<<1)>>1]|0);G=G+1|0}while((G|0)!=(j|0))}b:do{if(t){G=0;E=0;while(1){g[D+(G<<2)>>2]=+g[q+(E<<2)>>2];u=G+1|0;if((u|0)==(p|0)){break b}G=u;E=E+s|0}}}while(0);E=m+p|0;if((E|0)>(o|0)){v=E;F=29;break}G=C+r|0;if((G|0)<(k|0)){z=z+1|0;C=G;m=E;D=D+(p<<2)|0}else{v=E;F=29;break}}if((F|0)==29){hg(q);i=n;return v|0}return 0}function df(b,c,d,e,f,h,j){b=b|0;c=c|0;d=d|0;e=e|0;f=+f;h=h|0;j=j|0;var k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0.0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0.0,D=0,E=0,F=0,G=0,H=0.0,I=0.0,J=0.0,K=0,L=0.0,M=0.0,N=0.0,O=0.0,P=0.0,R=0.0,S=0.0,T=0.0,U=0,V=0,W=0.0,X=0,Y=0,Z=0.0,_=0.0,$=0.0,ba=0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0,oa=0.0,pa=0.0,qa=0.0,ra=0,sa=0.0,ta=0.0;k=i;l=f;if((c|0)<1){m=0;i=k;return m|0}if((c|0)==1){g[d>>2]=+g[b+4>>2];g[e>>2]=0.0;m=1;i=k;return m|0}f=2.0/+(c+ -1|0);n=c<<2;o=gg(n)|0;p=gg(n)|0;n=ig(c,1)|0;q=0;while(1){g[p+(q<<2)>>2]=f*+(q|0)+-1.0;r=q+1|0;if((r|0)==(c|0)){s=0.0;t=0.0;u=0.0;v=0;break}else{q=r}}do{w=+g[p+(v<<2)>>2];x=+g[b+(v<<2)>>2];s=s+w*w;t=t+w*x;u=u+x;v=v+1|0}while((v|0)!=(c|0));x=+(c|0);w=u/x;y=t/s;v=~~(x*.5);q=(v|0)<5?5:v;if((j|0)>0){x=l;v=~h;r=~c;l=0.0;z=u;u=t;t=s;s=y;A=c;B=0;C=w;while(1){D=0;while(1){g[o+(D<<2)>>2]=+g[b+(D<<2)>>2]-(C+s*+g[p+(D<<2)>>2]);E=D+1|0;if((E|0)==(c|0)){F=0;G=0;H=0.0;I=0.0;break}else{D=E}}while(1){if((a[n+F|0]|0)==0){J=+g[o+(F<<2)>>2];K=G+1|0;L=H+J;M=I+J*J}else{K=G;L=H;M=I}F=F+1|0;if((F|0)==(c|0)){break}else{G=K;H=L;I=M}}if(!(K>>>0<2)){D=K+ -1|0;J=M/+(D|0)-L*L/+(aa(D,K)|0);if(J<0.0){N=0.0}else{N=+Q(+J)}}else{N=-999.0}J=x*N;O=-J;P=t;R=u;S=z;T=l;D=0;E=v;U=c;while(1){V=~((E|0)>(r|0)?E:r);if((a[n+D|0]|0)!=1){W=+g[o+(D<<2)>>2];if(WJ?(X=D-h|0,Y=(X|0)<0?0:X,X=D+h|0,(Y|0)<(((X|0)>(c|0)?c:X)|0)):0){W=P;Z=R;_=T;$=S;X=Y;Y=U;while(1){ba=n+X|0;do{if((a[ba]|0)!=1){if((X|0)>(D|0)){a[ba]=2;ca=W;da=Z;ea=$;fa=_;ga=Y;break}else{ha=+g[p+(X<<2)>>2];ia=+g[b+(X<<2)>>2];a[ba]=1;ca=W-ha*ha;da=Z-ha*ia;ea=$-ia;fa=_-ha;ga=Y+ -1|0;break}}else{ca=W;da=Z;ea=$;fa=_;ga=Y}}while(0);ba=X+1|0;if((ba|0)==(V|0)){ja=fa;ka=ca;la=da;ma=ea;na=ga;break}else{W=ca;Z=da;_=fa;$=ea;X=ba;Y=ga}}}else{ja=T;ka=P;la=R;ma=S;na=U}}else{ja=T;ka=P;la=R;ma=S;na=U+ -1|0}D=D+1|0;if((D|0)==(c|0)){break}else{P=ka;R=la;S=ma;T=ja;E=E+ -1|0;U=na}}if((na|0)>0){T=ja/ka;S=(ma-la*T)/(+(na|0)-ja*T);oa=(la-ja*S)/ka;pa=S}else{oa=s;pa=C}U=B+1|0;if((na|0)>=(q|0)&(na|0)<(A|0)&(U|0)<(j|0)){l=ja;z=ma;u=la;t=ka;s=oa;A=na;B=U;C=pa}else{qa=oa;ra=na;sa=pa;break}}}else{qa=y;ra=c;sa=w}g[d>>2]=sa-qa;sa=f*qa;g[e>>2]=sa;if(!(sa>=0.0)){ta=-sa}else{ta=sa}if(ta<.001){g[e>>2]=f*y}hg(o);hg(p);hg(n);m=ra;i=k;return m|0}function ef(a,b){a=a|0;b=b|0;return(+g[a>>2]<=+g[b>>2]?-1:1)|0}function ff(a,b,c){a=a|0;b=b|0;c=c|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0;e=i;f=a>>>16;g=a&65535;if((c|0)==1){a=(d[b]|0)+g|0;h=a>>>0>65520?a+ -65521|0:a;a=h+f|0;j=(a>>>0>65520?a+15|0:a)<<16|h;i=e;return j|0}if((b|0)==0){j=1;i=e;return j|0}if(c>>>0<16){if((c|0)==0){k=g;l=f}else{h=b;a=c;m=g;n=f;while(1){o=a+ -1|0;p=(d[h]|0)+m|0;q=p+n|0;if((o|0)==0){k=p;l=q;break}else{h=h+1|0;a=o;m=p;n=q}}}j=((l>>>0)%65521|0)<<16|(k>>>0>65520?k+ -65521|0:k);i=e;return j|0}if(c>>>0>5551){k=b;l=c;n=g;m=f;do{l=l+ -5552|0;a=k;h=n;q=347;p=m;while(1){o=(d[a]|0)+h|0;r=o+(d[a+1|0]|0)|0;s=r+(d[a+2|0]|0)|0;t=s+(d[a+3|0]|0)|0;u=t+(d[a+4|0]|0)|0;v=u+(d[a+5|0]|0)|0;w=v+(d[a+6|0]|0)|0;x=w+(d[a+7|0]|0)|0;y=x+(d[a+8|0]|0)|0;z=y+(d[a+9|0]|0)|0;A=z+(d[a+10|0]|0)|0;B=A+(d[a+11|0]|0)|0;C=B+(d[a+12|0]|0)|0;D=C+(d[a+13|0]|0)|0;E=D+(d[a+14|0]|0)|0;h=E+(d[a+15|0]|0)|0;p=o+p+r+s+t+u+v+w+x+y+z+A+B+C+D+E+h|0;q=q+ -1|0;if((q|0)==0){break}else{a=a+16|0}}k=k+5552|0;n=(h>>>0)%65521|0;m=(p>>>0)%65521|0}while(l>>>0>5551);if((l|0)!=0){if(l>>>0>15){F=l;G=k;H=n;I=m;J=15}else{K=l;L=k;M=n;N=m;J=16}}else{O=n;P=m}}else{F=c;G=b;H=g;I=f;J=15}if((J|0)==15){while(1){J=0;F=F+ -16|0;f=(d[G]|0)+H|0;g=f+(d[G+1|0]|0)|0;b=g+(d[G+2|0]|0)|0;c=b+(d[G+3|0]|0)|0;m=c+(d[G+4|0]|0)|0;n=m+(d[G+5|0]|0)|0;k=n+(d[G+6|0]|0)|0;l=k+(d[G+7|0]|0)|0;a=l+(d[G+8|0]|0)|0;q=a+(d[G+9|0]|0)|0;E=q+(d[G+10|0]|0)|0;D=E+(d[G+11|0]|0)|0;C=D+(d[G+12|0]|0)|0;B=C+(d[G+13|0]|0)|0;A=B+(d[G+14|0]|0)|0;H=A+(d[G+15|0]|0)|0;I=f+I+g+b+c+m+n+k+l+a+q+E+D+C+B+A+H|0;G=G+16|0;if(!(F>>>0>15)){break}else{J=15}}if((F|0)==0){Q=H;R=I;J=17}else{K=F;L=G;M=H;N=I;J=16}}if((J|0)==16){while(1){J=0;I=K+ -1|0;H=(d[L]|0)+M|0;G=H+N|0;if((I|0)==0){Q=H;R=G;J=17;break}else{K=I;L=L+1|0;M=H;N=G;J=16}}}if((J|0)==17){O=(Q>>>0)%65521|0;P=(R>>>0)%65521|0}j=P<<16|O;i=e;return j|0}function gf(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;f=i;if((b|0)==0){g=0;i=f;return g|0}h=~a;a:do{if((e|0)!=0){a=b;j=e;k=h;while(1){if((a&3|0)==0){break}l=c[12968+(((d[a]|0)^k&255)<<2)>>2]^k>>>8;m=j+ -1|0;if((m|0)==0){n=l;break a}else{a=a+1|0;j=m;k=l}}if(j>>>0>31){l=j;m=a;o=k;while(1){p=c[m>>2]^o;q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+4>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+8>>2];q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+12>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+16>>2];q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+20>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+24>>2];q=m+32|0;r=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+28>>2];p=c[15016+((r>>>8&255)<<2)>>2]^c[16040+((r&255)<<2)>>2]^c[13992+((r>>>16&255)<<2)>>2]^c[12968+(r>>>24<<2)>>2];r=l+ -32|0;if(r>>>0>31){l=r;m=q;o=p}else{s=r;t=q;u=p;break}}}else{s=j;t=a;u=k}if(s>>>0>3){o=s;m=t;l=u;while(1){p=m+4|0;q=c[m>>2]^l;r=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2];q=o+ -4|0;if(q>>>0>3){o=q;m=p;l=r}else{v=q;w=p;x=r;break}}}else{v=s;w=t;x=u}if((v|0)==0){n=x}else{l=w;m=v;o=x;while(1){k=c[12968+(((d[l]|0)^o&255)<<2)>>2]^o>>>8;a=m+ -1|0;if((a|0)==0){n=k;break}else{l=l+1|0;m=a;o=k}}}}else{n=h}}while(0);g=~n;i=f;return g|0}function hf(b,d,e,f,g,h,j,k){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0;l=i;if((j|0)==0){m=-6;i=l;return m|0}if(!((a[j]|0)==49&(k|0)==56)){m=-6;i=l;return m|0}if((b|0)==0){m=-2;i=l;return m|0}k=b+24|0;c[k>>2]=0;j=b+32|0;n=c[j>>2]|0;if((n|0)==0){c[j>>2]=1;c[b+40>>2]=0;o=1}else{o=n}n=b+36|0;if((c[n>>2]|0)==0){c[n>>2]=1}n=(d|0)==-1?6:d;if((f|0)<0){p=0-f|0;q=0}else{d=(f|0)>15;p=d?f+ -16|0:f;q=d?2:1}if(!((g+ -1|0)>>>0<9&(e|0)==8)){m=-2;i=l;return m|0}if((p+ -8|0)>>>0>7|n>>>0>9|h>>>0>4){m=-2;i=l;return m|0}e=(p|0)==8?9:p;p=b+40|0;d=kb[o&1](c[p>>2]|0,1,5828)|0;if((d|0)==0){m=-4;i=l;return m|0}c[b+28>>2]=d;c[d>>2]=b;c[d+24>>2]=q;c[d+28>>2]=0;c[d+48>>2]=e;q=1<>2]=q;c[d+52>>2]=q+ -1;o=g+7|0;c[d+80>>2]=o;f=1<>2]=f;c[d+84>>2]=f+ -1;c[d+88>>2]=((g+9|0)>>>0)/3|0;f=d+56|0;c[f>>2]=kb[c[j>>2]&1](c[p>>2]|0,q,2)|0;q=kb[c[j>>2]&1](c[p>>2]|0,c[e>>2]|0,2)|0;r=d+64|0;c[r>>2]=q;Eg(q|0,0,c[e>>2]<<1|0)|0;e=d+68|0;c[e>>2]=kb[c[j>>2]&1](c[p>>2]|0,c[o>>2]|0,2)|0;c[d+5824>>2]=0;o=1<>2]=o;q=kb[c[j>>2]&1](c[p>>2]|0,o,4)|0;c[d+8>>2]=q;o=c[g>>2]|0;c[d+12>>2]=o<<2;if(((c[f>>2]|0)!=0?(c[r>>2]|0)!=0:0)?!((c[e>>2]|0)==0|(q|0)==0):0){c[d+5796>>2]=q+(o>>>1<<1);c[d+5784>>2]=q+(o*3|0);c[d+132>>2]=n;c[d+136>>2]=h;a[d+36|0]=8;m=kf(b)|0;i=l;return m|0}c[d+4>>2]=666;c[k>>2]=c[27632>>2];jf(b)|0;m=-4;i=l;return m|0}function jf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;i=b;return d|0}g=c[f+4>>2]|0;switch(g|0){case 42:case 69:case 73:case 91:case 103:case 113:case 666:{break};default:{d=-2;i=b;return d|0}}h=c[f+8>>2]|0;if((h|0)==0){j=f}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);j=c[e>>2]|0}h=c[j+68>>2]|0;if((h|0)==0){k=j}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);k=c[e>>2]|0}h=c[k+64>>2]|0;if((h|0)==0){l=k}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);l=c[e>>2]|0}h=c[l+56>>2]|0;k=a+36|0;if((h|0)==0){m=a+40|0;n=l}else{l=a+40|0;mb[c[k>>2]&1](c[l>>2]|0,h);m=l;n=c[e>>2]|0}mb[c[k>>2]&1](c[m>>2]|0,n);c[e>>2]=0;d=(g|0)==113?-3:0;i=b;return d|0}function kf(a){a=a|0;var d=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;d=i;if((a|0)==0){f=-2;i=d;return f|0}g=c[a+28>>2]|0;if((g|0)==0){f=-2;i=d;return f|0}if((c[a+32>>2]|0)==0){f=-2;i=d;return f|0}if((c[a+36>>2]|0)==0){f=-2;i=d;return f|0}c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+44>>2]=2;c[g+20>>2]=0;c[g+16>>2]=c[g+8>>2];h=g+24|0;j=c[h>>2]|0;if((j|0)<0){k=0-j|0;c[h>>2]=k;l=k}else{l=j}c[g+4>>2]=(l|0)!=0?42:113;if((l|0)==2){m=gf(0,0,0)|0}else{m=ff(0,0,0)|0}c[a+48>>2]=m;c[g+40>>2]=0;Of(g);c[g+60>>2]=c[g+44>>2]<<1;m=c[g+76>>2]|0;a=c[g+68>>2]|0;b[a+(m+ -1<<1)>>1]=0;Eg(a|0,0,(m<<1)+ -2|0)|0;m=c[g+132>>2]|0;c[g+128>>2]=e[21162+(m*12|0)>>1]|0;c[g+140>>2]=e[21160+(m*12|0)>>1]|0;c[g+144>>2]=e[21164+(m*12|0)>>1]|0;c[g+124>>2]=e[21166+(m*12|0)>>1]|0;c[g+108>>2]=0;c[g+92>>2]=0;c[g+116>>2]=0;c[g+120>>2]=2;c[g+96>>2]=2;c[g+112>>2]=0;c[g+104>>2]=0;c[g+72>>2]=0;f=0;i=d;return f|0} + + + +function lf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0;g=i;if((e|0)==0){h=-2;i=g;return h|0}j=e+28|0;k=c[j>>2]|0;if((k|0)==0|f>>>0>5){h=-2;i=g;return h|0}l=e+12|0;do{if((c[l>>2]|0)!=0){if((c[e>>2]|0)==0?(c[e+4>>2]|0)!=0:0){break}m=k+4|0;n=c[m>>2]|0;o=(f|0)==4;if((n|0)!=666|o){p=e+16|0;if((c[p>>2]|0)==0){c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}c[k>>2]=e;q=k+40|0;r=c[q>>2]|0;c[q>>2]=f;do{if((n|0)==42){if((c[k+24>>2]|0)!=2){s=(c[k+48>>2]<<12)+ -30720|0;if((c[k+136>>2]|0)<=1?(t=c[k+132>>2]|0,(t|0)>=2):0){if((t|0)<6){u=64}else{u=(t|0)==6?128:192}}else{u=0}t=u|s;s=k+108|0;v=(c[s>>2]|0)==0?t:t|32;c[m>>2]=113;t=k+20|0;w=c[t>>2]|0;c[t>>2]=w+1;x=k+8|0;a[(c[x>>2]|0)+w|0]=v>>>8;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=(v|((v>>>0)%31|0))^31;v=e+48|0;if((c[s>>2]|0)!=0){s=c[v>>2]|0;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>24;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>16;s=c[v>>2]|0;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>8;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s}c[v>>2]=ff(0,0,0)|0;y=c[m>>2]|0;z=32;break}v=e+48|0;c[v>>2]=gf(0,0,0)|0;s=k+20|0;w=c[s>>2]|0;c[s>>2]=w+1;x=k+8|0;a[(c[x>>2]|0)+w|0]=31;w=c[s>>2]|0;c[s>>2]=w+1;a[(c[x>>2]|0)+w|0]=-117;w=c[s>>2]|0;c[s>>2]=w+1;a[(c[x>>2]|0)+w|0]=8;w=k+28|0;t=c[w>>2]|0;if((t|0)==0){A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[k+132>>2]|0;if((A|0)!=9){if((c[k+136>>2]|0)>1){B=4}else{B=(A|0)<2?4:0}}else{B=2}A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=B;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=3;c[m>>2]=113;break}A=(((c[t+44>>2]|0)!=0?2:0)|(c[t>>2]|0)!=0|((c[t+16>>2]|0)==0?0:4)|((c[t+28>>2]|0)==0?0:8)|((c[t+36>>2]|0)==0?0:16))&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[(c[w>>2]|0)+4>>2]&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>8&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>16&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>24&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[k+132>>2]|0;if((A|0)!=9){if((c[k+136>>2]|0)>1){C=4}else{C=(A|0)<2?4:0}}else{C=2}A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=C;A=c[(c[w>>2]|0)+12>>2]&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[w>>2]|0;if((c[A+16>>2]|0)==0){D=A}else{t=c[A+20>>2]&255;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=t;t=(c[(c[w>>2]|0)+20>>2]|0)>>>8&255;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=t;D=c[w>>2]|0}if((c[D+44>>2]|0)!=0){c[v>>2]=gf(c[v>>2]|0,c[x>>2]|0,c[s>>2]|0)|0}c[k+32>>2]=0;c[m>>2]=69;E=w;z=34}else{y=n;z=32}}while(0);if((z|0)==32){if((y|0)==69){E=k+28|0;z=34}else{F=y;z=55}}do{if((z|0)==34){n=c[E>>2]|0;if((c[n+16>>2]|0)==0){c[m>>2]=73;G=n;z=57;break}w=k+20|0;s=c[w>>2]|0;x=k+32|0;v=c[x>>2]|0;a:do{if(v>>>0<(c[n+20>>2]&65535)>>>0){t=k+12|0;A=e+48|0;H=k+8|0;I=e+20|0;J=v;K=s;L=n;M=s;while(1){if((K|0)==(c[t>>2]|0)){if((c[L+44>>2]|0)!=0&K>>>0>M>>>0){c[A>>2]=gf(c[A>>2]|0,(c[H>>2]|0)+M|0,K-M|0)|0}N=c[j>>2]|0;O=c[N+20>>2]|0;P=c[p>>2]|0;Q=O>>>0>P>>>0?P:O;if((Q|0)!=0?(Kg(c[l>>2]|0,c[N+16>>2]|0,Q|0)|0,c[l>>2]=(c[l>>2]|0)+Q,N=(c[j>>2]|0)+16|0,c[N>>2]=(c[N>>2]|0)+Q,c[I>>2]=(c[I>>2]|0)+Q,c[p>>2]=(c[p>>2]|0)-Q,N=c[j>>2]|0,O=N+20|0,P=c[O>>2]|0,c[O>>2]=P-Q,(P|0)==(Q|0)):0){c[N+16>>2]=c[N+8>>2]}R=c[w>>2]|0;if((R|0)==(c[t>>2]|0)){break}S=c[E>>2]|0;T=c[x>>2]|0;U=R;V=R}else{S=L;T=J;U=K;V=M}N=a[(c[S+16>>2]|0)+T|0]|0;c[w>>2]=U+1;a[(c[H>>2]|0)+U|0]=N;N=(c[x>>2]|0)+1|0;c[x>>2]=N;Q=c[E>>2]|0;if(!(N>>>0<(c[Q+20>>2]&65535)>>>0)){W=Q;X=V;break a}J=N;K=c[w>>2]|0;L=Q;M=V}W=c[E>>2]|0;X=R}else{W=n;X=s}}while(0);if((c[W+44>>2]|0)!=0?(s=c[w>>2]|0,s>>>0>X>>>0):0){n=e+48|0;c[n>>2]=gf(c[n>>2]|0,(c[k+8>>2]|0)+X|0,s-X|0)|0;Y=c[E>>2]|0}else{Y=W}if((c[x>>2]|0)==(c[Y+20>>2]|0)){c[x>>2]=0;c[m>>2]=73;G=Y;z=57;break}else{F=c[m>>2]|0;z=55;break}}}while(0);if((z|0)==55){if((F|0)==73){G=c[k+28>>2]|0;z=57}else{Z=F;z=76}}do{if((z|0)==57){s=k+28|0;if((c[G+28>>2]|0)==0){c[m>>2]=91;_=s;z=78;break}n=k+20|0;v=c[n>>2]|0;M=k+12|0;L=e+48|0;K=k+8|0;J=e+20|0;H=k+32|0;t=v;I=v;while(1){if((t|0)==(c[M>>2]|0)){if((c[(c[s>>2]|0)+44>>2]|0)!=0&t>>>0>I>>>0){c[L>>2]=gf(c[L>>2]|0,(c[K>>2]|0)+I|0,t-I|0)|0}v=c[j>>2]|0;A=c[v+20>>2]|0;Q=c[p>>2]|0;N=A>>>0>Q>>>0?Q:A;if((N|0)!=0?(Kg(c[l>>2]|0,c[v+16>>2]|0,N|0)|0,c[l>>2]=(c[l>>2]|0)+N,v=(c[j>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+N,c[J>>2]=(c[J>>2]|0)+N,c[p>>2]=(c[p>>2]|0)-N,v=c[j>>2]|0,A=v+20|0,Q=c[A>>2]|0,c[A>>2]=Q-N,(Q|0)==(N|0)):0){c[v+16>>2]=c[v+8>>2]}v=c[n>>2]|0;if((v|0)==(c[M>>2]|0)){$=v;aa=1;break}else{ba=v;ca=v}}else{ba=t;ca=I}v=c[H>>2]|0;c[H>>2]=v+1;da=a[(c[(c[s>>2]|0)+28>>2]|0)+v|0]|0;c[n>>2]=ba+1;a[(c[K>>2]|0)+ba|0]=da;if(da<<24>>24==0){z=68;break}t=c[n>>2]|0;I=ca}if((z|0)==68){$=ca;aa=da&255}if((c[(c[s>>2]|0)+44>>2]|0)!=0?(I=c[n>>2]|0,I>>>0>$>>>0):0){c[L>>2]=gf(c[L>>2]|0,(c[K>>2]|0)+$|0,I-$|0)|0}if((aa|0)==0){c[H>>2]=0;c[m>>2]=91;_=s;z=78;break}else{Z=c[m>>2]|0;z=76;break}}}while(0);if((z|0)==76){if((Z|0)==91){_=k+28|0;z=78}else{ea=Z;z=97}}do{if((z|0)==78){if((c[(c[_>>2]|0)+36>>2]|0)==0){c[m>>2]=103;fa=_;z=99;break}I=k+20|0;t=c[I>>2]|0;M=k+12|0;J=e+48|0;x=k+8|0;w=e+20|0;v=k+32|0;N=t;Q=t;while(1){if((N|0)==(c[M>>2]|0)){if((c[(c[_>>2]|0)+44>>2]|0)!=0&N>>>0>Q>>>0){c[J>>2]=gf(c[J>>2]|0,(c[x>>2]|0)+Q|0,N-Q|0)|0}t=c[j>>2]|0;A=c[t+20>>2]|0;P=c[p>>2]|0;O=A>>>0>P>>>0?P:A;if((O|0)!=0?(Kg(c[l>>2]|0,c[t+16>>2]|0,O|0)|0,c[l>>2]=(c[l>>2]|0)+O,t=(c[j>>2]|0)+16|0,c[t>>2]=(c[t>>2]|0)+O,c[w>>2]=(c[w>>2]|0)+O,c[p>>2]=(c[p>>2]|0)-O,t=c[j>>2]|0,A=t+20|0,P=c[A>>2]|0,c[A>>2]=P-O,(P|0)==(O|0)):0){c[t+16>>2]=c[t+8>>2]}t=c[I>>2]|0;if((t|0)==(c[M>>2]|0)){ga=t;ha=1;break}else{ia=t;ja=t}}else{ia=N;ja=Q}t=c[v>>2]|0;c[v>>2]=t+1;ka=a[(c[(c[_>>2]|0)+36>>2]|0)+t|0]|0;c[I>>2]=ia+1;a[(c[x>>2]|0)+ia|0]=ka;if(ka<<24>>24==0){z=89;break}N=c[I>>2]|0;Q=ja}if((z|0)==89){ga=ja;ha=ka&255}if((c[(c[_>>2]|0)+44>>2]|0)!=0?(Q=c[I>>2]|0,Q>>>0>ga>>>0):0){c[J>>2]=gf(c[J>>2]|0,(c[x>>2]|0)+ga|0,Q-ga|0)|0}if((ha|0)==0){c[m>>2]=103;fa=_;z=99;break}else{ea=c[m>>2]|0;z=97;break}}}while(0);if((z|0)==97?(ea|0)==103:0){fa=k+28|0;z=99}do{if((z|0)==99){if((c[(c[fa>>2]|0)+44>>2]|0)==0){c[m>>2]=113;break}Q=k+20|0;N=k+12|0;if((((c[Q>>2]|0)+2|0)>>>0>(c[N>>2]|0)>>>0?(v=c[j>>2]|0,M=c[v+20>>2]|0,w=c[p>>2]|0,s=M>>>0>w>>>0?w:M,(s|0)!=0):0)?(Kg(c[l>>2]|0,c[v+16>>2]|0,s|0)|0,c[l>>2]=(c[l>>2]|0)+s,v=(c[j>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+s,v=e+20|0,c[v>>2]=(c[v>>2]|0)+s,c[p>>2]=(c[p>>2]|0)-s,v=c[j>>2]|0,M=v+20|0,w=c[M>>2]|0,c[M>>2]=w-s,(w|0)==(s|0)):0){c[v+16>>2]=c[v+8>>2]}v=c[Q>>2]|0;if(!((v+2|0)>>>0>(c[N>>2]|0)>>>0)){N=e+48|0;s=c[N>>2]&255;c[Q>>2]=v+1;w=k+8|0;a[(c[w>>2]|0)+v|0]=s;s=(c[N>>2]|0)>>>8&255;v=c[Q>>2]|0;c[Q>>2]=v+1;a[(c[w>>2]|0)+v|0]=s;c[N>>2]=gf(0,0,0)|0;c[m>>2]=113}}}while(0);N=k+20|0;if((c[N>>2]|0)==0){if((c[e+4>>2]|0)==0?(r|0)>=(f|0)&(f|0)!=4:0){c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}}else{s=c[j>>2]|0;v=c[s+20>>2]|0;w=c[p>>2]|0;Q=v>>>0>w>>>0?w:v;if((Q|0)==0){la=w}else{Kg(c[l>>2]|0,c[s+16>>2]|0,Q|0)|0;c[l>>2]=(c[l>>2]|0)+Q;s=(c[j>>2]|0)+16|0;c[s>>2]=(c[s>>2]|0)+Q;s=e+20|0;c[s>>2]=(c[s>>2]|0)+Q;c[p>>2]=(c[p>>2]|0)-Q;s=c[j>>2]|0;w=s+20|0;v=c[w>>2]|0;c[w>>2]=v-Q;if((v|0)==(Q|0)){c[s+16>>2]=c[s+8>>2]}la=c[p>>2]|0}if((la|0)==0){c[q>>2]=-1;h=0;i=g;return h|0}}s=(c[m>>2]|0)==666;Q=(c[e+4>>2]|0)==0;if(s){if(Q){z=121}else{c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}}else{if(Q){z=121}else{z=124}}do{if((z|0)==121){if((c[k+116>>2]|0)==0){if((f|0)!=0){if(s){break}else{z=124;break}}else{h=0;i=g;return h|0}}else{z=124}}}while(0);do{if((z|0)==124){s=c[k+136>>2]|0;b:do{if((s|0)==3){r=k+116|0;Q=(f|0)==0;v=k+96|0;w=k+108|0;M=k+5792|0;H=k+5796|0;K=k+5784|0;L=k+(d[24760]<<2)+2440|0;n=k+5788|0;t=k+56|0;O=k+92|0;while(1){P=c[r>>2]|0;if(P>>>0<258){mf(k);A=c[r>>2]|0;if(A>>>0<258&Q){break b}if((A|0)==0){break}c[v>>2]=0;if(A>>>0>2){ma=A;z=151}else{na=c[w>>2]|0;z=166}}else{c[v>>2]=0;ma=P;z=151}if((z|0)==151){z=0;P=c[w>>2]|0;if((P|0)!=0){A=c[t>>2]|0;oa=a[A+(P+ -1)|0]|0;if((oa<<24>>24==(a[A+P|0]|0)?oa<<24>>24==(a[A+(P+1)|0]|0):0)?(pa=A+(P+2)|0,oa<<24>>24==(a[pa]|0)):0){qa=A+(P+258)|0;A=pa;while(1){pa=A+1|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+2|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+3|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+4|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+5|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+6|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+7|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+8|0;if(oa<<24>>24==(a[pa]|0)&pa>>>0>>0){A=pa}else{ra=pa;break}}A=ra-qa+258|0;oa=A>>>0>ma>>>0?ma:A;c[v>>2]=oa;if(oa>>>0>2){A=oa+253|0;oa=c[M>>2]|0;b[(c[H>>2]|0)+(oa<<1)>>1]=1;c[M>>2]=oa+1;a[(c[K>>2]|0)+oa|0]=A;oa=k+((d[25272+(A&255)|0]|256)+1<<2)+148|0;b[oa>>1]=(b[oa>>1]|0)+1<<16>>16;b[L>>1]=(b[L>>1]|0)+1<<16>>16;oa=(c[M>>2]|0)==((c[n>>2]|0)+ -1|0)|0;A=c[v>>2]|0;c[r>>2]=(c[r>>2]|0)-A;pa=(c[w>>2]|0)+A|0;c[w>>2]=pa;c[v>>2]=0;sa=pa;ta=oa}else{na=P;z=166}}else{na=P;z=166}}else{na=0;z=166}}if((z|0)==166){z=0;oa=a[(c[t>>2]|0)+na|0]|0;pa=c[M>>2]|0;b[(c[H>>2]|0)+(pa<<1)>>1]=0;c[M>>2]=pa+1;a[(c[K>>2]|0)+pa|0]=oa;pa=k+((oa&255)<<2)+148|0;b[pa>>1]=(b[pa>>1]|0)+1<<16>>16;pa=(c[M>>2]|0)==((c[n>>2]|0)+ -1|0)|0;c[r>>2]=(c[r>>2]|0)+ -1;oa=(c[w>>2]|0)+1|0;c[w>>2]=oa;sa=oa;ta=pa}if((ta|0)==0){continue}pa=c[O>>2]|0;if((pa|0)>-1){ua=(c[t>>2]|0)+pa|0}else{ua=0}Sf(k,ua,sa-pa|0,0);c[O>>2]=c[w>>2];pa=c[k>>2]|0;oa=pa+28|0;A=c[oa>>2]|0;va=c[A+20>>2]|0;wa=pa+16|0;xa=c[wa>>2]|0;ya=va>>>0>xa>>>0?xa:va;if((ya|0)!=0?(va=pa+12|0,Kg(c[va>>2]|0,c[A+16>>2]|0,ya|0)|0,c[va>>2]=(c[va>>2]|0)+ya,va=(c[oa>>2]|0)+16|0,c[va>>2]=(c[va>>2]|0)+ya,va=pa+20|0,c[va>>2]=(c[va>>2]|0)+ya,c[wa>>2]=(c[wa>>2]|0)-ya,wa=c[oa>>2]|0,oa=wa+20|0,va=c[oa>>2]|0,c[oa>>2]=va-ya,(va|0)==(ya|0)):0){c[wa+16>>2]=c[wa+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){break b}}r=c[O>>2]|0;if((r|0)>-1){za=(c[t>>2]|0)+r|0}else{za=0}Sf(k,za,(c[w>>2]|0)-r|0,o&1);c[O>>2]=c[w>>2];r=c[k>>2]|0;n=r+28|0;M=c[n>>2]|0;K=c[M+20>>2]|0;H=r+16|0;v=c[H>>2]|0;L=K>>>0>v>>>0?v:K;if((L|0)!=0?(K=r+12|0,Kg(c[K>>2]|0,c[M+16>>2]|0,L|0)|0,c[K>>2]=(c[K>>2]|0)+L,K=(c[n>>2]|0)+16|0,c[K>>2]=(c[K>>2]|0)+L,K=r+20|0,c[K>>2]=(c[K>>2]|0)+L,c[H>>2]=(c[H>>2]|0)-L,H=c[n>>2]|0,n=H+20|0,K=c[n>>2]|0,c[n>>2]=K-L,(K|0)==(L|0)):0){c[H+16>>2]=c[H+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){Aa=o?2:0;z=183;break}else{Aa=o?3:1;z=183;break}}else if((s|0)==2){H=k+116|0;L=k+96|0;K=k+108|0;n=k+56|0;r=k+5792|0;M=k+5796|0;v=k+5784|0;Q=k+5788|0;wa=k+92|0;while(1){if((c[H>>2]|0)==0?(mf(k),(c[H>>2]|0)==0):0){break}c[L>>2]=0;ya=a[(c[n>>2]|0)+(c[K>>2]|0)|0]|0;va=c[r>>2]|0;b[(c[M>>2]|0)+(va<<1)>>1]=0;c[r>>2]=va+1;a[(c[v>>2]|0)+va|0]=ya;va=k+((ya&255)<<2)+148|0;b[va>>1]=(b[va>>1]|0)+1<<16>>16;va=(c[r>>2]|0)==((c[Q>>2]|0)+ -1|0);c[H>>2]=(c[H>>2]|0)+ -1;ya=(c[K>>2]|0)+1|0;c[K>>2]=ya;if(!va){continue}va=c[wa>>2]|0;if((va|0)>-1){Ba=(c[n>>2]|0)+va|0}else{Ba=0}Sf(k,Ba,ya-va|0,0);c[wa>>2]=c[K>>2];va=c[k>>2]|0;ya=va+28|0;oa=c[ya>>2]|0;pa=c[oa+20>>2]|0;A=va+16|0;xa=c[A>>2]|0;Ca=pa>>>0>xa>>>0?xa:pa;if((Ca|0)!=0?(pa=va+12|0,Kg(c[pa>>2]|0,c[oa+16>>2]|0,Ca|0)|0,c[pa>>2]=(c[pa>>2]|0)+Ca,pa=(c[ya>>2]|0)+16|0,c[pa>>2]=(c[pa>>2]|0)+Ca,pa=va+20|0,c[pa>>2]=(c[pa>>2]|0)+Ca,c[A>>2]=(c[A>>2]|0)-Ca,A=c[ya>>2]|0,ya=A+20|0,pa=c[ya>>2]|0,c[ya>>2]=pa-Ca,(pa|0)==(Ca|0)):0){c[A+16>>2]=c[A+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){break b}}if((f|0)!=0){H=c[wa>>2]|0;if((H|0)>-1){Da=(c[n>>2]|0)+H|0}else{Da=0}Sf(k,Da,(c[K>>2]|0)-H|0,o&1);c[wa>>2]=c[K>>2];H=c[k>>2]|0;Q=H+28|0;r=c[Q>>2]|0;v=c[r+20>>2]|0;M=H+16|0;L=c[M>>2]|0;w=v>>>0>L>>>0?L:v;if((w|0)!=0?(v=H+12|0,Kg(c[v>>2]|0,c[r+16>>2]|0,w|0)|0,c[v>>2]=(c[v>>2]|0)+w,v=(c[Q>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+w,v=H+20|0,c[v>>2]=(c[v>>2]|0)+w,c[M>>2]=(c[M>>2]|0)-w,M=c[Q>>2]|0,Q=M+20|0,v=c[Q>>2]|0,c[Q>>2]=v-w,(v|0)==(w|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){Aa=o?2:0;z=183;break}else{Aa=o?3:1;z=183;break}}}else{Aa=nb[c[21168+((c[k+132>>2]|0)*12|0)>>2]&7](k,f)|0;z=183}}while(0);if((z|0)==183){if((Aa&-2|0)==2){c[m>>2]=666}if((Aa&-3|0)!=0){if((Aa|0)!=1){break}if((f|0)==1){Rf(k)}else if(((f|0)!=5?(Qf(k,0,0,0),(f|0)==3):0)?(s=c[k+76>>2]|0,x=c[k+68>>2]|0,b[x+(s+ -1<<1)>>1]=0,Eg(x|0,0,(s<<1)+ -2|0)|0,(c[k+116>>2]|0)==0):0){c[k+108>>2]=0;c[k+92>>2]=0}s=c[j>>2]|0;x=c[s+20>>2]|0;J=c[p>>2]|0;I=x>>>0>J>>>0?J:x;if((I|0)==0){Ea=J}else{Kg(c[l>>2]|0,c[s+16>>2]|0,I|0)|0;c[l>>2]=(c[l>>2]|0)+I;s=(c[j>>2]|0)+16|0;c[s>>2]=(c[s>>2]|0)+I;s=e+20|0;c[s>>2]=(c[s>>2]|0)+I;c[p>>2]=(c[p>>2]|0)-I;s=c[j>>2]|0;J=s+20|0;x=c[J>>2]|0;c[J>>2]=x-I;if((x|0)==(I|0)){c[s+16>>2]=c[s+8>>2]}Ea=c[p>>2]|0}if((Ea|0)!=0){break}c[q>>2]=-1;h=0;i=g;return h|0}}if((c[p>>2]|0)!=0){h=0;i=g;return h|0}c[q>>2]=-1;h=0;i=g;return h|0}}while(0);if(!o){h=0;i=g;return h|0}q=k+24|0;m=c[q>>2]|0;if((m|0)<1){h=1;i=g;return h|0}s=e+48|0;I=c[s>>2]|0;if((m|0)==2){m=c[N>>2]|0;c[N>>2]=m+1;x=k+8|0;a[(c[x>>2]|0)+m|0]=I;m=(c[s>>2]|0)>>>8&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=(c[s>>2]|0)>>>16&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=(c[s>>2]|0)>>>24&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=e+8|0;J=c[m>>2]&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>8&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>16&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>24&255;m=c[N>>2]|0;c[N>>2]=m+1;a[(c[x>>2]|0)+m|0]=J}else{J=c[N>>2]|0;c[N>>2]=J+1;m=k+8|0;a[(c[m>>2]|0)+J|0]=I>>>24;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[m>>2]|0)+J|0]=I>>>16;I=c[s>>2]|0;s=c[N>>2]|0;c[N>>2]=s+1;a[(c[m>>2]|0)+s|0]=I>>>8;s=c[N>>2]|0;c[N>>2]=s+1;a[(c[m>>2]|0)+s|0]=I}I=c[j>>2]|0;s=c[I+20>>2]|0;m=c[p>>2]|0;J=s>>>0>m>>>0?m:s;if((J|0)!=0?(Kg(c[l>>2]|0,c[I+16>>2]|0,J|0)|0,c[l>>2]=(c[l>>2]|0)+J,I=(c[j>>2]|0)+16|0,c[I>>2]=(c[I>>2]|0)+J,I=e+20|0,c[I>>2]=(c[I>>2]|0)+J,c[p>>2]=(c[p>>2]|0)-J,I=c[j>>2]|0,s=I+20|0,m=c[s>>2]|0,c[s>>2]=m-J,(m|0)==(J|0)):0){c[I+16>>2]=c[I+8>>2]}I=c[q>>2]|0;if((I|0)>0){c[q>>2]=0-I}h=(c[N>>2]|0)==0|0;i=g;return h|0}}}while(0);c[e+24>>2]=c[27624>>2];h=-2;i=g;return h|0}function mf(a){a=a|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;f=i;g=a+44|0;h=c[g>>2]|0;j=a+60|0;k=a+116|0;l=a+108|0;m=h+ -262|0;n=a+56|0;o=a+72|0;p=a+88|0;q=a+84|0;r=a+112|0;s=a+92|0;t=a+76|0;u=a+68|0;v=a+64|0;w=c[k>>2]|0;x=h;while(1){y=c[l>>2]|0;z=(c[j>>2]|0)-w-y|0;if(y>>>0<(m+x|0)>>>0){A=y;B=z}else{y=c[n>>2]|0;Kg(y|0,y+h|0,h|0)|0;c[r>>2]=(c[r>>2]|0)-h;y=(c[l>>2]|0)-h|0;c[l>>2]=y;c[s>>2]=(c[s>>2]|0)-h;C=c[t>>2]|0;D=C;E=(c[u>>2]|0)+(C<<1)|0;do{E=E+ -2|0;C=e[E>>1]|0;if(C>>>0>>0){F=0}else{F=C-h&65535}b[E>>1]=F;D=D+ -1|0}while((D|0)!=0);D=h;E=(c[v>>2]|0)+(h<<1)|0;do{E=E+ -2|0;C=e[E>>1]|0;if(C>>>0>>0){G=0}else{G=C-h&65535}b[E>>1]=G;D=D+ -1|0}while((D|0)!=0);A=y;B=z+h|0}D=c[a>>2]|0;E=D+4|0;C=c[E>>2]|0;if((C|0)==0){H=28;break}I=c[k>>2]|0;J=(c[n>>2]|0)+(I+A)|0;K=C>>>0>B>>>0?B:C;if((K|0)==0){L=0;M=I}else{c[E>>2]=C-K;C=c[(c[D+28>>2]|0)+24>>2]|0;if((C|0)==2){E=D+48|0;c[E>>2]=gf(c[E>>2]|0,c[D>>2]|0,K)|0;N=D}else if((C|0)==1){C=D+48|0;c[C>>2]=ff(c[C>>2]|0,c[D>>2]|0,K)|0;N=D}else{N=D}Kg(J|0,c[N>>2]|0,K|0)|0;c[N>>2]=(c[N>>2]|0)+K;J=D+8|0;c[J>>2]=(c[J>>2]|0)+K;L=K;M=c[k>>2]|0}O=M+L|0;c[k>>2]=O;if(O>>>0>2?(K=c[l>>2]|0,J=c[n>>2]|0,D=d[J+K|0]|0,c[o>>2]=D,c[o>>2]=((d[J+(K+1)|0]|0)^D<>2])&c[q>>2],!(O>>>0<262)):0){break}if((c[(c[a>>2]|0)+4>>2]|0)==0){break}w=O;x=c[g>>2]|0}if((H|0)==28){i=f;return}H=a+5824|0;a=c[H>>2]|0;g=c[j>>2]|0;if(!(a>>>0>>0)){i=f;return}j=O+(c[l>>2]|0)|0;if(a>>>0>>0){l=g-j|0;O=l>>>0>258?258:l;Eg((c[n>>2]|0)+j|0,0,O|0)|0;c[H>>2]=O+j;i=f;return}O=j+258|0;if(!(a>>>0>>0)){i=f;return}j=O-a|0;O=g-a|0;g=j>>>0>O>>>0?O:j;Eg((c[n>>2]|0)+a|0,0,g|0)|0;c[H>>2]=(c[H>>2]|0)+g;i=f;return}function nf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;d=i;e=(c[a+12>>2]|0)+ -5|0;f=e>>>0<65535?e:65535;e=a+116|0;g=a+108|0;h=a+92|0;j=a+44|0;k=a+56|0;while(1){l=c[e>>2]|0;if(l>>>0<2){mf(a);m=c[e>>2]|0;if((m|b|0)==0){n=0;o=28;break}if((m|0)==0){o=20;break}else{p=m}}else{p=l}l=(c[g>>2]|0)+p|0;c[g>>2]=l;c[e>>2]=0;m=c[h>>2]|0;q=m+f|0;if((l|0)!=0&l>>>0>>0){r=l;s=m}else{c[e>>2]=l-q;c[g>>2]=q;if((m|0)>-1){t=(c[k>>2]|0)+m|0}else{t=0}Sf(a,t,f,0);c[h>>2]=c[g>>2];m=c[a>>2]|0;q=m+28|0;l=c[q>>2]|0;u=c[l+20>>2]|0;v=m+16|0;w=c[v>>2]|0;x=u>>>0>w>>>0?w:u;if((x|0)!=0?(u=m+12|0,Kg(c[u>>2]|0,c[l+16>>2]|0,x|0)|0,c[u>>2]=(c[u>>2]|0)+x,u=(c[q>>2]|0)+16|0,c[u>>2]=(c[u>>2]|0)+x,u=m+20|0,c[u>>2]=(c[u>>2]|0)+x,c[v>>2]=(c[v>>2]|0)-x,v=c[q>>2]|0,q=v+20|0,u=c[q>>2]|0,c[q>>2]=u-x,(u|0)==(x|0)):0){c[v+16>>2]=c[v+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=0;o=28;break}r=c[g>>2]|0;s=c[h>>2]|0}v=r-s|0;if(v>>>0<((c[j>>2]|0)+ -262|0)>>>0){continue}if((s|0)>-1){y=(c[k>>2]|0)+s|0}else{y=0}Sf(a,y,v,0);c[h>>2]=c[g>>2];v=c[a>>2]|0;x=v+28|0;u=c[x>>2]|0;q=c[u+20>>2]|0;m=v+16|0;l=c[m>>2]|0;w=q>>>0>l>>>0?l:q;if((w|0)!=0?(q=v+12|0,Kg(c[q>>2]|0,c[u+16>>2]|0,w|0)|0,c[q>>2]=(c[q>>2]|0)+w,q=(c[x>>2]|0)+16|0,c[q>>2]=(c[q>>2]|0)+w,q=v+20|0,c[q>>2]=(c[q>>2]|0)+w,c[m>>2]=(c[m>>2]|0)-w,m=c[x>>2]|0,x=m+20|0,q=c[x>>2]|0,c[x>>2]=q-w,(q|0)==(w|0)):0){c[m+16>>2]=c[m+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=0;o=28;break}}if((o|0)==20){y=c[h>>2]|0;if((y|0)>-1){z=(c[k>>2]|0)+y|0}else{z=0}k=(b|0)==4;Sf(a,z,(c[g>>2]|0)-y|0,k&1);c[h>>2]=c[g>>2];g=c[a>>2]|0;h=g+28|0;y=c[h>>2]|0;z=c[y+20>>2]|0;b=g+16|0;s=c[b>>2]|0;j=z>>>0>s>>>0?s:z;if((j|0)!=0?(z=g+12|0,Kg(c[z>>2]|0,c[y+16>>2]|0,j|0)|0,c[z>>2]=(c[z>>2]|0)+j,z=(c[h>>2]|0)+16|0,c[z>>2]=(c[z>>2]|0)+j,z=g+20|0,c[z>>2]=(c[z>>2]|0)+j,c[b>>2]=(c[b>>2]|0)-j,b=c[h>>2]|0,h=b+20|0,z=c[h>>2]|0,c[h>>2]=z-j,(z|0)==(j|0)):0){c[b+16>>2]=c[b+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=k?2:0;i=d;return n|0}else{n=k?3:1;i=d;return n|0}}else if((o|0)==28){i=d;return n|0}return 0}function of(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0;g=i;h=e+116|0;j=(f|0)==0;k=e+72|0;l=e+88|0;m=e+108|0;n=e+56|0;o=e+84|0;p=e+68|0;q=e+52|0;r=e+64|0;s=e+44|0;t=e+96|0;u=e+112|0;v=e+5792|0;w=e+5796|0;x=e+5784|0;y=e+5788|0;z=e+128|0;A=e+92|0;while(1){if((c[h>>2]|0)>>>0<262){mf(e);B=c[h>>2]|0;if(B>>>0<262&j){C=0;D=34;break}if((B|0)==0){D=26;break}if(!(B>>>0>2)){D=9}else{D=6}}else{D=6}if((D|0)==6){D=0;B=c[m>>2]|0;E=((d[(c[n>>2]|0)+(B+2)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=E;F=(c[p>>2]|0)+(E<<1)|0;E=b[F>>1]|0;b[(c[r>>2]|0)+((c[q>>2]&B)<<1)>>1]=E;G=E&65535;b[F>>1]=B;if(!(E<<16>>16==0)?!((B-G|0)>>>0>((c[s>>2]|0)+ -262|0)>>>0):0){B=qf(e,G)|0;c[t>>2]=B;H=B}else{D=9}}if((D|0)==9){D=0;H=c[t>>2]|0}do{if(H>>>0>2){B=H+253|0;G=(c[m>>2]|0)-(c[u>>2]|0)|0;E=c[v>>2]|0;b[(c[w>>2]|0)+(E<<1)>>1]=G;c[v>>2]=E+1;a[(c[x>>2]|0)+E|0]=B;E=e+((d[25272+(B&255)|0]|0|256)+1<<2)+148|0;b[E>>1]=(b[E>>1]|0)+1<<16>>16;E=G+65535&65535;if(E>>>0<256){I=E}else{I=(E>>>7)+256|0}E=e+((d[24760+I|0]|0)<<2)+2440|0;b[E>>1]=(b[E>>1]|0)+1<<16>>16;E=(c[v>>2]|0)==((c[y>>2]|0)+ -1|0)|0;G=c[t>>2]|0;B=(c[h>>2]|0)-G|0;c[h>>2]=B;if(!(G>>>0<=(c[z>>2]|0)>>>0&B>>>0>2)){B=(c[m>>2]|0)+G|0;c[m>>2]=B;c[t>>2]=0;F=c[n>>2]|0;J=d[F+B|0]|0;c[k>>2]=J;c[k>>2]=((d[F+(B+1)|0]|0)^J<>2])&c[o>>2];K=B;L=E;break}B=G+ -1|0;c[t>>2]=B;G=c[l>>2]|0;J=c[n>>2]|0;F=c[o>>2]|0;M=c[p>>2]|0;N=c[q>>2]|0;O=c[r>>2]|0;P=B;B=c[m>>2]|0;Q=c[k>>2]|0;while(1){R=B+1|0;c[m>>2]=R;Q=((d[J+(B+3)|0]|0)^Q<>2]=Q;S=M+(Q<<1)|0;b[O+((N&R)<<1)>>1]=b[S>>1]|0;b[S>>1]=R;P=P+ -1|0;c[t>>2]=P;if((P|0)==0){break}else{B=R}}P=B+2|0;c[m>>2]=P;K=P;L=E}else{P=a[(c[n>>2]|0)+(c[m>>2]|0)|0]|0;N=c[v>>2]|0;b[(c[w>>2]|0)+(N<<1)>>1]=0;c[v>>2]=N+1;a[(c[x>>2]|0)+N|0]=P;N=e+((P&255)<<2)+148|0;b[N>>1]=(b[N>>1]|0)+1<<16>>16;N=(c[v>>2]|0)==((c[y>>2]|0)+ -1|0)|0;c[h>>2]=(c[h>>2]|0)+ -1;P=(c[m>>2]|0)+1|0;c[m>>2]=P;K=P;L=N}}while(0);if((L|0)==0){continue}N=c[A>>2]|0;if((N|0)>-1){T=(c[n>>2]|0)+N|0}else{T=0}Sf(e,T,K-N|0,0);c[A>>2]=c[m>>2];N=c[e>>2]|0;P=N+28|0;O=c[P>>2]|0;Q=c[O+20>>2]|0;M=N+16|0;F=c[M>>2]|0;G=Q>>>0>F>>>0?F:Q;if((G|0)!=0?(Q=N+12|0,Kg(c[Q>>2]|0,c[O+16>>2]|0,G|0)|0,c[Q>>2]=(c[Q>>2]|0)+G,Q=(c[P>>2]|0)+16|0,c[Q>>2]=(c[Q>>2]|0)+G,Q=N+20|0,c[Q>>2]=(c[Q>>2]|0)+G,c[M>>2]=(c[M>>2]|0)-G,M=c[P>>2]|0,P=M+20|0,Q=c[P>>2]|0,c[P>>2]=Q-G,(Q|0)==(G|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){C=0;D=34;break}}if((D|0)==26){K=c[A>>2]|0;if((K|0)>-1){U=(c[n>>2]|0)+K|0}else{U=0}n=(f|0)==4;Sf(e,U,(c[m>>2]|0)-K|0,n&1);c[A>>2]=c[m>>2];m=c[e>>2]|0;A=m+28|0;K=c[A>>2]|0;U=c[K+20>>2]|0;f=m+16|0;T=c[f>>2]|0;L=U>>>0>T>>>0?T:U;if((L|0)!=0?(U=m+12|0,Kg(c[U>>2]|0,c[K+16>>2]|0,L|0)|0,c[U>>2]=(c[U>>2]|0)+L,U=(c[A>>2]|0)+16|0,c[U>>2]=(c[U>>2]|0)+L,U=m+20|0,c[U>>2]=(c[U>>2]|0)+L,c[f>>2]=(c[f>>2]|0)-L,f=c[A>>2]|0,A=f+20|0,U=c[A>>2]|0,c[A>>2]=U-L,(U|0)==(L|0)):0){c[f+16>>2]=c[f+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){C=n?2:0;i=g;return C|0}else{C=n?3:1;i=g;return C|0}}else if((D|0)==34){i=g;return C|0}return 0}function pf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0;g=i;h=e+116|0;j=(f|0)==0;k=e+72|0;l=e+88|0;m=e+108|0;n=e+56|0;o=e+84|0;p=e+68|0;q=e+52|0;r=e+64|0;s=e+96|0;t=e+120|0;u=e+112|0;v=e+100|0;w=e+5792|0;x=e+5796|0;y=e+5784|0;z=e+5788|0;A=e+104|0;B=e+92|0;C=e+128|0;D=e+44|0;E=e+136|0;a:while(1){F=c[h>>2]|0;while(1){if(F>>>0<262){mf(e);G=c[h>>2]|0;if(G>>>0<262&j){H=0;I=50;break a}if((G|0)==0){I=40;break a}if(!(G>>>0>2)){c[t>>2]=c[s>>2];c[v>>2]=c[u>>2];c[s>>2]=2;J=2;I=16}else{I=8}}else{I=8}do{if((I|0)==8){I=0;G=c[m>>2]|0;K=((d[(c[n>>2]|0)+(G+2)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=K;L=(c[p>>2]|0)+(K<<1)|0;K=b[L>>1]|0;b[(c[r>>2]|0)+((c[q>>2]&G)<<1)>>1]=K;M=K&65535;b[L>>1]=G;G=c[s>>2]|0;c[t>>2]=G;c[v>>2]=c[u>>2];c[s>>2]=2;if(!(K<<16>>16==0)){if(G>>>0<(c[C>>2]|0)>>>0){if(!(((c[m>>2]|0)-M|0)>>>0>((c[D>>2]|0)+ -262|0)>>>0)){K=qf(e,M)|0;c[s>>2]=K;if(K>>>0<6){if((c[E>>2]|0)!=1){if((K|0)!=3){J=K;I=16;break}if(!(((c[m>>2]|0)-(c[u>>2]|0)|0)>>>0>4096)){J=3;I=16;break}}c[s>>2]=2;J=2;I=16}else{J=K;I=16}}else{J=2;I=16}}else{N=G;O=2}}else{J=2;I=16}}}while(0);if((I|0)==16){I=0;N=c[t>>2]|0;O=J}if(!(N>>>0<3|O>>>0>N>>>0)){break}if((c[A>>2]|0)==0){c[A>>2]=1;c[m>>2]=(c[m>>2]|0)+1;G=(c[h>>2]|0)+ -1|0;c[h>>2]=G;F=G;continue}G=a[(c[n>>2]|0)+((c[m>>2]|0)+ -1)|0]|0;K=c[w>>2]|0;b[(c[x>>2]|0)+(K<<1)>>1]=0;c[w>>2]=K+1;a[(c[y>>2]|0)+K|0]=G;K=e+((G&255)<<2)+148|0;b[K>>1]=(b[K>>1]|0)+1<<16>>16;if((c[w>>2]|0)==((c[z>>2]|0)+ -1|0)){K=c[B>>2]|0;if((K|0)>-1){P=(c[n>>2]|0)+K|0}else{P=0}Sf(e,P,(c[m>>2]|0)-K|0,0);c[B>>2]=c[m>>2];K=c[e>>2]|0;G=K+28|0;M=c[G>>2]|0;L=c[M+20>>2]|0;Q=K+16|0;R=c[Q>>2]|0;S=L>>>0>R>>>0?R:L;if((S|0)!=0?(L=K+12|0,Kg(c[L>>2]|0,c[M+16>>2]|0,S|0)|0,c[L>>2]=(c[L>>2]|0)+S,L=(c[G>>2]|0)+16|0,c[L>>2]=(c[L>>2]|0)+S,L=K+20|0,c[L>>2]=(c[L>>2]|0)+S,c[Q>>2]=(c[Q>>2]|0)-S,Q=c[G>>2]|0,G=Q+20|0,L=c[G>>2]|0,c[G>>2]=L-S,(L|0)==(S|0)):0){c[Q+16>>2]=c[Q+8>>2]}}c[m>>2]=(c[m>>2]|0)+1;Q=(c[h>>2]|0)+ -1|0;c[h>>2]=Q;if((c[(c[e>>2]|0)+16>>2]|0)==0){H=0;I=50;break a}else{F=Q}}F=c[m>>2]|0;Q=F+ -3+(c[h>>2]|0)|0;S=N+253|0;L=F+65535-(c[v>>2]|0)|0;F=c[w>>2]|0;b[(c[x>>2]|0)+(F<<1)>>1]=L;c[w>>2]=F+1;a[(c[y>>2]|0)+F|0]=S;F=e+((d[25272+(S&255)|0]|0|256)+1<<2)+148|0;b[F>>1]=(b[F>>1]|0)+1<<16>>16;F=L+65535&65535;if(F>>>0<256){T=F}else{T=(F>>>7)+256|0}F=e+((d[24760+T|0]|0)<<2)+2440|0;b[F>>1]=(b[F>>1]|0)+1<<16>>16;F=c[w>>2]|0;L=(c[z>>2]|0)+ -1|0;S=c[t>>2]|0;c[h>>2]=1-S+(c[h>>2]|0);G=S+ -2|0;c[t>>2]=G;S=c[m>>2]|0;K=G;while(1){G=S+1|0;c[m>>2]=G;if(!(G>>>0>Q>>>0)){M=((d[(c[n>>2]|0)+(S+3)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=M;R=(c[p>>2]|0)+(M<<1)|0;b[(c[r>>2]|0)+((c[q>>2]&G)<<1)>>1]=b[R>>1]|0;b[R>>1]=G}K=K+ -1|0;c[t>>2]=K;if((K|0)==0){break}else{S=G}}c[A>>2]=0;c[s>>2]=2;K=S+2|0;c[m>>2]=K;if((F|0)!=(L|0)){continue}Q=c[B>>2]|0;if((Q|0)>-1){U=(c[n>>2]|0)+Q|0}else{U=0}Sf(e,U,K-Q|0,0);c[B>>2]=c[m>>2];Q=c[e>>2]|0;K=Q+28|0;G=c[K>>2]|0;R=c[G+20>>2]|0;M=Q+16|0;V=c[M>>2]|0;W=R>>>0>V>>>0?V:R;if((W|0)!=0?(R=Q+12|0,Kg(c[R>>2]|0,c[G+16>>2]|0,W|0)|0,c[R>>2]=(c[R>>2]|0)+W,R=(c[K>>2]|0)+16|0,c[R>>2]=(c[R>>2]|0)+W,R=Q+20|0,c[R>>2]=(c[R>>2]|0)+W,c[M>>2]=(c[M>>2]|0)-W,M=c[K>>2]|0,K=M+20|0,R=c[K>>2]|0,c[K>>2]=R-W,(R|0)==(W|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){H=0;I=50;break}}if((I|0)==40){if((c[A>>2]|0)!=0){U=a[(c[n>>2]|0)+((c[m>>2]|0)+ -1)|0]|0;s=c[w>>2]|0;b[(c[x>>2]|0)+(s<<1)>>1]=0;c[w>>2]=s+1;a[(c[y>>2]|0)+s|0]=U;s=e+((U&255)<<2)+148|0;b[s>>1]=(b[s>>1]|0)+1<<16>>16;c[A>>2]=0}A=c[B>>2]|0;if((A|0)>-1){X=(c[n>>2]|0)+A|0}else{X=0}n=(f|0)==4;Sf(e,X,(c[m>>2]|0)-A|0,n&1);c[B>>2]=c[m>>2];m=c[e>>2]|0;B=m+28|0;A=c[B>>2]|0;X=c[A+20>>2]|0;f=m+16|0;s=c[f>>2]|0;U=X>>>0>s>>>0?s:X;if((U|0)!=0?(X=m+12|0,Kg(c[X>>2]|0,c[A+16>>2]|0,U|0)|0,c[X>>2]=(c[X>>2]|0)+U,X=(c[B>>2]|0)+16|0,c[X>>2]=(c[X>>2]|0)+U,X=m+20|0,c[X>>2]=(c[X>>2]|0)+U,c[f>>2]=(c[f>>2]|0)-U,f=c[B>>2]|0,B=f+20|0,X=c[B>>2]|0,c[B>>2]=X-U,(X|0)==(U|0)):0){c[f+16>>2]=c[f+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){H=n?2:0;i=g;return H|0}else{H=n?3:1;i=g;return H|0}}else if((I|0)==50){i=g;return H|0}return 0}function qf(b,d){b=b|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;f=i;g=c[b+124>>2]|0;h=c[b+56>>2]|0;j=c[b+108>>2]|0;k=h+j|0;l=c[b+120>>2]|0;m=c[b+144>>2]|0;n=(c[b+44>>2]|0)+ -262|0;o=j>>>0>n>>>0?j-n|0:0;n=c[b+64>>2]|0;p=c[b+52>>2]|0;q=h+(j+258)|0;r=c[b+116>>2]|0;s=m>>>0>r>>>0?r:m;m=b+112|0;t=h+(j+1)|0;u=h+(j+2)|0;v=q;w=j+257|0;x=d;d=l;y=l>>>0<(c[b+140>>2]|0)>>>0?g:g>>>2;g=a[h+(l+j)|0]|0;b=a[h+(j+ -1+l)|0]|0;while(1){l=h+x|0;if((((a[h+(x+d)|0]|0)==g<<24>>24?(a[h+(d+ -1+x)|0]|0)==b<<24>>24:0)?(a[l]|0)==(a[k]|0):0)?(a[h+(x+1)|0]|0)==(a[t]|0):0){l=h+(x+2)|0;z=u;while(1){A=z+1|0;if((a[A]|0)!=(a[l+1|0]|0)){B=A;break}A=z+2|0;if((a[A]|0)!=(a[l+2|0]|0)){B=A;break}A=z+3|0;if((a[A]|0)!=(a[l+3|0]|0)){B=A;break}A=z+4|0;if((a[A]|0)!=(a[l+4|0]|0)){B=A;break}A=z+5|0;if((a[A]|0)!=(a[l+5|0]|0)){B=A;break}A=z+6|0;if((a[A]|0)!=(a[l+6|0]|0)){B=A;break}A=z+7|0;if((a[A]|0)!=(a[l+7|0]|0)){B=A;break}A=z+8|0;C=l+8|0;if((a[A]|0)==(a[C]|0)&A>>>0>>0){l=C;z=A}else{B=A;break}}z=B-v|0;l=z+258|0;if((l|0)>(d|0)){c[m>>2]=x;if((l|0)>=(s|0)){D=l;E=20;break}F=l;G=a[h+(l+j)|0]|0;H=a[h+(w+z)|0]|0}else{F=d;G=g;H=b}}else{F=d;G=g;H=b}z=e[n+((x&p)<<1)>>1]|0;if(!(z>>>0>o>>>0)){D=F;E=20;break}l=y+ -1|0;if((l|0)==0){D=F;E=20;break}else{x=z;d=F;y=l;g=G;b=H}}if((E|0)==20){i=f;return(D>>>0>r>>>0?r:D)|0}return 0}function rf(a){a=a|0;var b=0,d=0;b=i;do{if((a|0)!=0){if((c[a>>2]|0)==7247){d=Af(a)|0;break}else{d=Ff(a)|0;break}}else{d=-2}}while(0);i=b;return d|0}function sf(a,b){a=a|0;b=b|0;var c=0,d=0;c=i;d=tf(a,-1,b)|0;i=c;return d|0}function tf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+16|0;g=f;h=gg(140)|0;if((h|0)==0){j=0;i=f;return j|0}c[h+16>>2]=0;c[h+20>>2]=8192;k=h+80|0;c[k>>2]=0;c[h>>2]=0;l=h+60|0;c[l>>2]=-1;m=h+64|0;c[m>>2]=0;n=a[e]|0;if(!(n<<24>>24==0)){o=e;e=n;n=0;a:while(1){p=e<<24>>24;b:do{if((e+ -48<<24>>24&255)<10){c[l>>2]=p+ -48;q=n}else{switch(p|0){case 70:{c[m>>2]=4;q=n;break b;break};case 43:{r=9;break a;break};case 82:{c[m>>2]=3;q=n;break b;break};case 102:{c[m>>2]=1;q=n;break b;break};case 104:{c[m>>2]=2;q=n;break b;break};case 119:{c[h>>2]=31153;q=31153;break b;break};case 97:{c[h>>2]=1;q=1;break b;break};case 114:{c[h>>2]=7247;q=7247;break b;break};default:{q=n;break b}}}}while(0);o=o+1|0;e=a[o]|0;if(e<<24>>24==0){break}else{n=q}}if((r|0)==9){hg(h);j=0;i=f;return j|0}if((q|0)!=0){q=gg((Dg(b|0)|0)+1|0)|0;r=h+8|0;c[r>>2]=q;if((q|0)==0){hg(h);j=0;i=f;return j|0}Lg(q|0,b|0)|0;if((d|0)==-1){q=c[h>>2]|0;if((q|0)==7247){s=32768}else{s=(q|0)==31153?33345:33857}c[g>>2]=438;q=Aa(b|0,s|0,g|0)|0;c[h+4>>2]=q;if((q|0)==-1){hg(c[r>>2]|0);hg(h);j=0;i=f;return j|0}else{t=q}}else{c[h+4>>2]=d;t=d}d=c[h>>2]|0;if((d|0)==1){c[h>>2]=31153}else if((d|0)==7247?(d=ra(t|0,0,1)|0,c[h+44>>2]=(d|0)==-1?0:d,(c[h>>2]|0)==7247):0){c[h+36>>2]=0;c[h+40>>2]=0;c[h+52>>2]=0;c[h+56>>2]=1}c[h+72>>2]=0;d=c[k>>2]|0;t=h+76|0;if((d|0)!=0){if(!((c[t>>2]|0)==-4)){hg(d)}c[k>>2]=0}c[t>>2]=0;c[h+12>>2]=0;c[h+88>>2]=0;j=h;i=f;return j|0}}hg(h);j=0;i=f;return j|0}function uf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;e=i;if((a|0)==0){f=-1;i=e;return f|0}g=c[a>>2]|0;if(!((g|0)==31153|(g|0)==7247)){f=-1;i=e;return f|0}h=a+76|0;if((c[h>>2]|0)!=0|d>>>0>1){f=-1;i=e;return f|0}if((d|0)!=0){d=a+72|0;if((c[d>>2]|0)==0){j=b;k=d}else{j=(c[a+68>>2]|0)+b|0;k=d}}else{j=b-(c[a+12>>2]|0)|0;k=a+72|0}c[k>>2]=0;b=(g|0)==7247;if((b?(c[a+52>>2]|0)==1:0)?(d=a+12|0,((c[d>>2]|0)+j|0)>=(c[a+48>>2]|0)):0){l=a+36|0;if((ra(c[a+4>>2]|0,j-(c[l>>2]|0)|0,1)|0)==-1){f=-1;i=e;return f|0}c[l>>2]=0;c[a+40>>2]=0;c[k>>2]=0;l=a+80|0;m=c[l>>2]|0;if((m|0)!=0){if(!((c[h>>2]|0)==-4)){hg(m)}c[l>>2]=0}c[h>>2]=0;c[a+88>>2]=0;l=(c[d>>2]|0)+j|0;c[d>>2]=l;f=l;i=e;return f|0}if((j|0)<0){if(!b){f=-1;i=e;return f|0}b=a+12|0;l=(c[b>>2]|0)+j|0;if((l|0)<0){f=-1;i=e;return f|0}if((ra(c[a+4>>2]|0,c[a+44>>2]|0,0)|0)==-1){f=-1;i=e;return f|0}d=c[a>>2]|0;if((d|0)==7247){c[a+36>>2]=0;c[a+40>>2]=0;c[a+52>>2]=0;c[a+56>>2]=1}c[k>>2]=0;m=a+80|0;n=c[m>>2]|0;if((n|0)==0){o=d}else{if((c[h>>2]|0)==-4){p=d}else{hg(n);p=c[a>>2]|0}c[m>>2]=0;o=p}c[h>>2]=0;c[b>>2]=0;c[a+88>>2]=0;q=l;r=o}else{q=j;r=g}if((r|0)==7247){r=a+36|0;g=c[r>>2]|0;j=(g|0)<0|(g|0)>(q|0)?q:g;c[r>>2]=g-j;g=a+32|0;c[g>>2]=(c[g>>2]|0)+j;g=a+12|0;c[g>>2]=j+(c[g>>2]|0);s=q-j|0}else{s=q}if((s|0)!=0){c[k>>2]=1;c[a+68>>2]=s}f=(c[a+12>>2]|0)+s|0;i=e;return f|0}function vf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;g=b+80|0;h=c[g>>2]|0;j=b+76|0;if((h|0)!=0){if(!((c[j>>2]|0)==-4)){hg(h)}c[g>>2]=0}c[j>>2]=d;if((e|0)==0){i=f;return}if((d|0)==-4){c[g>>2]=e;i=f;return}d=c[b+8>>2]|0;b=Dg(d|0)|0;h=gg(b+3+(Dg(e|0)|0)|0)|0;c[g>>2]=h;if((h|0)==0){c[j>>2]=-4;c[g>>2]=21280;i=f;return}else{Lg(h|0,d|0)|0;d=c[g>>2]|0;h=d+(Dg(d|0)|0)|0;a[h+0|0]=a[21296|0]|0;a[h+1|0]=a[21297|0]|0;a[h+2|0]=a[21298|0]|0;Fg(c[g>>2]|0,e|0)|0;i=f;return}}function wf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=uf(a,b,c)|0;i=d;return e|0}function xf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0;e=i;if((a|0)==0){f=-1;i=e;return f|0}if((c[a>>2]|0)!=7247){f=-1;i=e;return f|0}if((c[a+76>>2]|0)!=0){f=-1;i=e;return f|0}if((d|0)<0){vf(a,-5,21304);f=-1;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}g=a+72|0;a:do{if((c[g>>2]|0)!=0){c[g>>2]=0;h=c[a+68>>2]|0;j=a+36|0;k=a+40|0;l=a+88|0;m=a+32|0;n=a+12|0;if((h|0)!=0){o=a+52|0;p=a+28|0;q=a+16|0;r=a+4|0;s=a+100|0;t=a+96|0;u=h;b:while(1){c:while(1){v=c[j>>2]|0;while(1){if((v|0)!=0){break c}if((c[k>>2]|0)!=0?(c[l>>2]|0)==0:0){w=j;x=k;y=m;z=l;A=n;break a}h=c[o>>2]|0;if((h|0)!=0){B=h;break}if((zf(a)|0)==-1){f=-1;C=59;break b}h=c[j>>2]|0;if((h|0)==0){C=21;break}else{v=h}}if((C|0)==21){C=0;B=c[o>>2]|0}if((B|0)==2){c[s>>2]=c[q>>2]<<1;c[t>>2]=c[p>>2];if((yf(a)|0)==-1){f=-1;C=59;break b}else{continue}}else if((B|0)!=1){continue}h=c[p>>2]|0;D=c[q>>2]<<1;c[j>>2]=0;E=0;do{F=Za(c[r>>2]|0,h+E|0,D-E|0)|0;if((F|0)<1){C=26;break}E=(c[j>>2]|0)+F|0;c[j>>2]=E}while(E>>>0>>0);if((C|0)==26){C=0;if((F|0)<0){C=28;break b}c[k>>2]=1}c[m>>2]=c[p>>2]}D=(v|0)<0|(v|0)>(u|0)?u:v;c[j>>2]=v-D;c[m>>2]=(c[m>>2]|0)+D;c[n>>2]=(c[n>>2]|0)+D;if((u|0)==(D|0)){w=j;x=k;y=m;z=l;A=n;break a}else{u=u-D|0}}if((C|0)==28){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==59){i=e;return f|0}}else{w=j;x=k;y=m;z=l;A=n}}else{w=a+36|0;x=a+40|0;y=a+32|0;z=a+88|0;A=a+12|0}}while(0);v=a+52|0;F=a+28|0;B=a+16|0;g=a+4|0;u=a+100|0;p=a+96|0;r=b;b=d;d=0;d:while(1){q=c[w>>2]|0;e:do{if((q|0)==0){if((c[x>>2]|0)!=0?(c[z>>2]|0)==0:0){f=d;C=59;break d}t=c[v>>2]|0;if((t|0)!=0){if(b>>>0>2]<<1>>>0){G=t}else{if((t|0)==1){H=0}else{c[u>>2]=b;c[p>>2]=r;if((yf(a)|0)==-1){f=-1;C=59;break d}t=c[w>>2]|0;c[w>>2]=0;I=t;C=57;break}while(1){J=Za(c[g>>2]|0,r+H|0,b-H|0)|0;if((J|0)<1){break}t=J+H|0;if(t>>>0>>0){H=t}else{I=t;C=57;break e}}if((J|0)<0){C=54;break d}c[x>>2]=1;I=H;C=57;break}}else{if((zf(a)|0)==-1){f=-1;C=59;break d}if((c[w>>2]|0)!=0){K=r;L=b;M=d;break}G=c[v>>2]|0}if((G|0)==2){c[u>>2]=c[B>>2]<<1;c[p>>2]=c[F>>2];if((yf(a)|0)==-1){f=-1;C=59;break d}else{K=r;L=b;M=d;break}}else if((G|0)!=1){K=r;L=b;M=d;break}t=c[F>>2]|0;s=c[B>>2]<<1;c[w>>2]=0;o=0;do{N=Za(c[g>>2]|0,t+o|0,s-o|0)|0;if((N|0)<1){C=44;break}o=(c[w>>2]|0)+N|0;c[w>>2]=o}while(o>>>0>>0);if((C|0)==44){C=0;if((N|0)<0){C=46;break d}c[x>>2]=1}c[y>>2]=c[F>>2];K=r;L=b;M=d}else{s=q>>>0>b>>>0?b:q;Kg(r|0,c[y>>2]|0,s|0)|0;c[y>>2]=(c[y>>2]|0)+s;c[w>>2]=(c[w>>2]|0)-s;I=s;C=57}}while(0);if((C|0)==57){C=0;c[A>>2]=(c[A>>2]|0)+I;K=r+I|0;L=b-I|0;M=I+d|0}if((L|0)==0){f=M;C=59;break}else{r=K;b=L;d=M}}if((C|0)==46){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==54){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==59){i=e;return f|0}return 0}function yf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;b=i;i=i+16|0;d=b+4|0;e=b;f=a+84|0;g=a+100|0;h=c[g>>2]|0;j=a+88|0;k=a+76|0;l=a+40|0;m=a+24|0;n=a+16|0;o=a+4|0;p=a+84|0;while(1){if((c[j>>2]|0)==0){if((c[k>>2]|0)!=0){q=-1;r=27;break}if((c[l>>2]|0)!=0){r=12;break}s=c[m>>2]|0;t=c[n>>2]|0;c[j>>2]=0;u=0;while(1){v=Za(c[o>>2]|0,s+u|0,t-u|0)|0;if((v|0)<1){r=8;break}w=(c[j>>2]|0)+v|0;c[j>>2]=w;if(w>>>0>>0){u=w}else{x=w;break}}if((r|0)==8){r=0;if((v|0)<0){r=10;break}c[l>>2]=1;x=c[j>>2]|0}c[p>>2]=c[m>>2];if((x|0)==0){r=12;break}}u=Kf(f,0)|0;if((u|0)==-4){r=15;break}else if((u|0)==-3){r=16;break}else if((u|0)==2|(u|0)==-2){r=14;break}y=c[g>>2]|0;z=(u|0)==1;if((y|0)==0|z){r=18;break}}if((r|0)==10){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);q=-1;i=b;return q|0}else if((r|0)==12){vf(a,-3,21432);q=-1;i=b;return q|0}else if((r|0)==14){vf(a,-2,21456);q=-1;i=b;return q|0}else if((r|0)==15){vf(a,-4,21344);q=-1;i=b;return q|0}else if((r|0)==16){g=c[a+108>>2]|0;vf(a,-3,(g|0)==0?21496:g);q=-1;i=b;return q|0}else if((r|0)==18){g=h-y|0;c[a+36>>2]=g;y=(c[a+96>>2]|0)+(0-g)|0;c[a+32>>2]=y;h=a+132|0;c[h>>2]=gf(c[h>>2]|0,y,g)|0;if(!z){q=0;i=b;return q|0}if(!((Bf(a,d)|0)==-1)?!((Bf(a,e)|0)==-1):0){if((c[d>>2]|0)!=(c[h>>2]|0)){vf(a,-3,21520);q=-1;i=b;return q|0}if((c[e>>2]|0)==(c[a+104>>2]|0)){c[a+52>>2]=0;q=0;i=b;return q|0}else{vf(a,-3,21544);q=-1;i=b;return q|0}}vf(a,-3,21432);q=-1;i=b;return q|0}else if((r|0)==27){i=b;return q|0}return 0}function zf(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0;e=i;f=b+84|0;g=b+16|0;do{if((c[g>>2]|0)==0){h=c[b+20>>2]|0;j=gg(h)|0;k=b+24|0;c[k>>2]=j;l=gg(h<<1)|0;m=b+28|0;c[m>>2]=l;n=(l|0)==0;if(!((j|0)==0|n)){c[g>>2]=h;c[b+116>>2]=0;c[b+120>>2]=0;c[b+124>>2]=0;h=b+88|0;c[h>>2]=0;c[f>>2]=0;if((Jf(f,-15,21360,56)|0)==0){o=h;break}hg(c[m>>2]|0);hg(c[k>>2]|0);c[g>>2]=0;vf(b,-4,21344);p=-1;i=e;return p|0}if(n){q=j}else{hg(l);q=c[k>>2]|0}if((q|0)!=0){hg(q)}vf(b,-4,21344);p=-1;i=e;return p|0}else{o=b+88|0}}while(0);q=c[o>>2]|0;if((q|0)==0){if((c[b+76>>2]|0)!=0){p=-1;i=e;return p|0}k=b+40|0;if((c[k>>2]|0)!=0){p=0;i=e;return p|0}l=b+24|0;j=c[l>>2]|0;n=c[g>>2]|0;c[o>>2]=0;m=b+4|0;h=0;while(1){r=Za(c[m>>2]|0,j+h|0,n-h|0)|0;if((r|0)<1){s=17;break}t=(c[o>>2]|0)+r|0;c[o>>2]=t;if(t>>>0>>0){h=t}else{u=t;break}}do{if((s|0)==17){if((r|0)>=0){c[k>>2]=1;u=c[o>>2]|0;break}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);p=-1;i=e;return p|0}}while(0);c[b+84>>2]=c[l>>2];if((u|0)==0){p=0;i=e;return p|0}else{v=u}}else{v=q}q=c[f>>2]|0;if((a[q]|0)==31){u=v+ -1|0;c[o>>2]=u;l=q+1|0;c[f>>2]=l;if((u|0)==0){if((c[b+76>>2]|0)!=0){p=-1;i=e;return p|0}q=b+40|0;if((c[q>>2]|0)==0){k=b+24|0;r=c[k>>2]|0;h=c[g>>2]|0;c[o>>2]=0;n=b+4|0;j=0;while(1){w=Za(c[n>>2]|0,r+j|0,h-j|0)|0;if((w|0)<1){s=29;break}m=(c[o>>2]|0)+w|0;c[o>>2]=m;if(m>>>0>>0){j=m}else{x=m;break}}do{if((s|0)==29){if((w|0)>=0){c[q>>2]=1;x=c[o>>2]|0;break}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);p=-1;i=e;return p|0}}while(0);q=c[k>>2]|0;c[b+84>>2]=q;if((x|0)!=0){y=q;z=x;s=33}}}else{y=l;z=u;s=33}if((s|0)==33?(a[y]|0)==-117:0){u=z+ -1|0;c[o>>2]=u;z=y+1|0;c[f>>2]=z;a:do{if((u|0)==0){if((c[b+76>>2]|0)==0?(y=b+40|0,(c[y>>2]|0)==0):0){l=b+24|0;x=c[l>>2]|0;q=c[g>>2]|0;c[o>>2]=0;k=b+4|0;w=0;while(1){A=Za(c[k>>2]|0,x+w|0,q-w|0)|0;if((A|0)<1){s=40;break}j=(c[o>>2]|0)+A|0;c[o>>2]=j;if(j>>>0>>0){w=j}else{B=j;break}}do{if((s|0)==40){if((A|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break a}else{c[y>>2]=1;B=c[o>>2]|0;break}}}while(0);y=c[l>>2]|0;c[b+84>>2]=y;if((B|0)!=0){C=B;D=y;s=44}}}else{C=u;D=z;s=44}}while(0);if((s|0)==44?(z=C+ -1|0,c[o>>2]=z,C=D+1|0,c[f>>2]=C,(a[D]|0)==8):0){b:do{if((z|0)==0){if((c[b+76>>2]|0)==0?(D=b+40|0,(c[D>>2]|0)==0):0){u=b+24|0;B=c[u>>2]|0;A=c[g>>2]|0;c[o>>2]=0;y=b+4|0;w=0;while(1){E=Za(c[y>>2]|0,B+w|0,A-w|0)|0;if((E|0)<1){s=52;break}q=(c[o>>2]|0)+E|0;c[o>>2]=q;if(q>>>0>>0){w=q}else{F=q;break}}do{if((s|0)==52){if((E|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break b}else{c[D>>2]=1;F=c[o>>2]|0;break}}}while(0);D=c[u>>2]|0;c[b+84>>2]=D;if((F|0)!=0){G=F;H=D;s=56}}}else{G=z;H=C;s=56}}while(0);if((s|0)==56?(C=G+ -1|0,c[o>>2]=C,G=H+1|0,c[f>>2]=G,z=d[H]|0,(z&224|0)==0):0){c:do{if((C|0)==0){H=b+76|0;if((c[H>>2]|0)==0){F=b+40|0;if((c[F>>2]|0)==0){E=b+24|0;D=c[E>>2]|0;w=c[g>>2]|0;c[o>>2]=0;A=b+4|0;B=0;while(1){I=Za(c[A>>2]|0,D+B|0,w-B|0)|0;if((I|0)<1){s=64;break}y=(c[o>>2]|0)+I|0;c[o>>2]=y;if(y>>>0>>0){B=y}else{J=y;break}}do{if((s|0)==64){if((I|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);K=c[o>>2]|0;s=69;break c}else{c[F>>2]=1;J=c[o>>2]|0;break}}}while(0);F=c[E>>2]|0;c[b+84>>2]=F;if((J|0)!=0){L=J;M=F;s=68}else{N=H;s=71}}else{N=H;s=71}}else{s=70}}else{L=C;M=G;s=68}}while(0);if((s|0)==68){G=L+ -1|0;c[o>>2]=G;c[f>>2]=M+1;K=G;s=69}if((s|0)==69){if((K|0)==0){s=70}else{O=K;s=80}}if((s|0)==70){N=b+76|0;s=71}d:do{if((s|0)==71){if((c[N>>2]|0)==0){K=b+40|0;if((c[K>>2]|0)==0){G=b+24|0;M=c[G>>2]|0;L=c[g>>2]|0;c[o>>2]=0;C=b+4|0;J=0;while(1){P=Za(c[C>>2]|0,M+J|0,L-J|0)|0;if((P|0)<1){s=76;break}I=(c[o>>2]|0)+P|0;c[o>>2]=I;if(I>>>0>>0){J=I}else{Q=I;break}}do{if((s|0)==76){if((P|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);R=c[o>>2]|0;s=81;break d}else{c[K>>2]=1;Q=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[G>>2];if((Q|0)!=0){O=Q;s=80}else{S=N;s=83}}else{S=N;s=83}}else{s=82}}}while(0);if((s|0)==80){N=O+ -1|0;c[o>>2]=N;c[f>>2]=(c[f>>2]|0)+1;R=N;s=81}if((s|0)==81){if((R|0)==0){s=82}else{T=R;s=92}}if((s|0)==82){S=b+76|0;s=83}e:do{if((s|0)==83){if((c[S>>2]|0)==0){R=b+40|0;if((c[R>>2]|0)==0){N=b+24|0;O=c[N>>2]|0;Q=c[g>>2]|0;c[o>>2]=0;P=b+4|0;K=0;while(1){U=Za(c[P>>2]|0,O+K|0,Q-K|0)|0;if((U|0)<1){s=88;break}J=(c[o>>2]|0)+U|0;c[o>>2]=J;if(J>>>0>>0){K=J}else{V=J;break}}do{if((s|0)==88){if((U|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);W=c[o>>2]|0;s=93;break e}else{c[R>>2]=1;V=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[N>>2];if((V|0)!=0){T=V;s=92}else{X=S;s=95}}else{X=S;s=95}}else{s=94}}}while(0);if((s|0)==92){S=T+ -1|0;c[o>>2]=S;c[f>>2]=(c[f>>2]|0)+1;W=S;s=93}if((s|0)==93){if((W|0)==0){s=94}else{Y=W;s=104}}if((s|0)==94){X=b+76|0;s=95}f:do{if((s|0)==95){if((c[X>>2]|0)==0){W=b+40|0;if((c[W>>2]|0)==0){S=b+24|0;T=c[S>>2]|0;V=c[g>>2]|0;c[o>>2]=0;U=b+4|0;R=0;while(1){Z=Za(c[U>>2]|0,T+R|0,V-R|0)|0;if((Z|0)<1){s=100;break}K=(c[o>>2]|0)+Z|0;c[o>>2]=K;if(K>>>0>>0){R=K}else{_=K;break}}do{if((s|0)==100){if((Z|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);$=c[o>>2]|0;s=105;break f}else{c[W>>2]=1;_=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[S>>2];if((_|0)!=0){Y=_;s=104}else{aa=X;s=107}}else{aa=X;s=107}}else{s=106}}}while(0);if((s|0)==104){X=Y+ -1|0;c[o>>2]=X;c[f>>2]=(c[f>>2]|0)+1;$=X;s=105}if((s|0)==105){if(($|0)==0){s=106}else{ba=$;s=116}}if((s|0)==106){aa=b+76|0;s=107}g:do{if((s|0)==107){if((c[aa>>2]|0)==0){$=b+40|0;if((c[$>>2]|0)==0){X=b+24|0;Y=c[X>>2]|0;_=c[g>>2]|0;c[o>>2]=0;Z=b+4|0;W=0;while(1){ca=Za(c[Z>>2]|0,Y+W|0,_-W|0)|0;if((ca|0)<1){s=112;break}R=(c[o>>2]|0)+ca|0;c[o>>2]=R;if(R>>>0<_>>>0){W=R}else{da=R;break}}do{if((s|0)==112){if((ca|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);ea=c[o>>2]|0;s=117;break g}else{c[$>>2]=1;da=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[X>>2];if((da|0)!=0){ba=da;s=116}else{fa=aa;s=119}}else{fa=aa;s=119}}else{s=118}}}while(0);if((s|0)==116){aa=ba+ -1|0;c[o>>2]=aa;c[f>>2]=(c[f>>2]|0)+1;ea=aa;s=117}if((s|0)==117){if((ea|0)==0){s=118}else{ga=ea;s=128}}if((s|0)==118){fa=b+76|0;s=119}h:do{if(((s|0)==119?(c[fa>>2]|0)==0:0)?(ea=b+40|0,(c[ea>>2]|0)==0):0){aa=b+24|0;ba=c[aa>>2]|0;da=c[g>>2]|0;c[o>>2]=0;ca=b+4|0;$=0;while(1){ha=Za(c[ca>>2]|0,ba+$|0,da-$|0)|0;if((ha|0)<1){s=124;break}W=(c[o>>2]|0)+ha|0;c[o>>2]=W;if(W>>>0>>0){$=W}else{ia=W;break}}do{if((s|0)==124){if((ha|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break h}else{c[ea>>2]=1;ia=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[aa>>2];if((ia|0)!=0){ga=ia;s=128}}}while(0);if((s|0)==128){c[o>>2]=ga+ -1;c[f>>2]=(c[f>>2]|0)+1}i:do{if((z&4|0)!=0){ga=c[o>>2]|0;j:do{if((ga|0)==0){ia=b+76|0;if((c[ia>>2]|0)==0){ha=b+40|0;if((c[ha>>2]|0)==0){fa=b+24|0;ea=c[fa>>2]|0;$=c[g>>2]|0;c[o>>2]=0;da=b+4|0;ba=0;while(1){ja=Za(c[da>>2]|0,ea+ba|0,$-ba|0)|0;if((ja|0)<1){s=136;break}ca=(c[o>>2]|0)+ja|0;c[o>>2]=ca;if(ca>>>0<$>>>0){ba=ca}else{ka=ca;break}}do{if((s|0)==136){if((ja|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);la=-1;ma=c[o>>2]|0;s=141;break j}else{c[ha>>2]=1;ka=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[fa>>2];if((ka|0)!=0){na=ka;s=140}else{oa=ia;pa=-1;s=143}}else{oa=ia;pa=-1;s=143}}else{qa=-1;s=142}}else{na=ga;s=140}}while(0);if((s|0)==140){ga=na+ -1|0;c[o>>2]=ga;aa=c[f>>2]|0;c[f>>2]=aa+1;la=d[aa]|0;ma=ga;s=141}if((s|0)==141){if((ma|0)==0){qa=la;s=142}else{ra=ma;sa=la;s=152}}if((s|0)==142){oa=b+76|0;pa=qa;s=143}k:do{if((s|0)==143){if((c[oa>>2]|0)==0?(ga=b+40|0,(c[ga>>2]|0)==0):0){aa=b+24|0;ha=c[aa>>2]|0;ba=c[g>>2]|0;c[o>>2]=0;$=b+4|0;ea=0;while(1){ta=Za(c[$>>2]|0,ha+ea|0,ba-ea|0)|0;if((ta|0)<1){s=148;break}da=(c[o>>2]|0)+ta|0;c[o>>2]=da;if(da>>>0>>0){ea=da}else{ua=da;break}}do{if((s|0)==148){if((ta|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);va=-256;wa=pa;break k}else{c[ga>>2]=1;ua=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[aa>>2];if((ua|0)!=0){ra=ua;sa=pa;s=152}else{va=-256;wa=pa}}else{va=-256;wa=pa}}}while(0);if((s|0)==152){c[o>>2]=ra+ -1;ga=c[f>>2]|0;c[f>>2]=ga+1;va=d[ga]<<8;wa=sa}ga=va+wa|0;if((ga|0)!=0){ea=b+76|0;ba=b+40|0;ha=b+24|0;$=b+4|0;ia=b+84|0;fa=ga;ga=c[o>>2]|0;while(1){fa=fa+ -1|0;if((ga|0)==0){if((c[ea>>2]|0)!=0){break i}if((c[ba>>2]|0)!=0){break i}da=c[ha>>2]|0;ca=c[g>>2]|0;c[o>>2]=0;X=0;while(1){xa=Za(c[$>>2]|0,da+X|0,ca-X|0)|0;if((xa|0)<1){s=161;break}W=(c[o>>2]|0)+xa|0;c[o>>2]=W;if(W>>>0>>0){X=W}else{ya=W;break}}if((s|0)==161){s=0;if((xa|0)<0){break}c[ba>>2]=1;ya=c[o>>2]|0}c[ia>>2]=c[ha>>2];if((ya|0)==0){break i}else{za=ya}}else{za=ga}ga=za+ -1|0;c[o>>2]=ga;c[f>>2]=(c[f>>2]|0)+1;if((fa|0)==0){break i}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}}while(0);l:do{if((z&8|0)!=0){za=b+76|0;ya=b+40|0;xa=b+24|0;wa=b+4|0;va=b+84|0;sa=c[o>>2]|0;while(1){if((sa|0)==0){if((c[za>>2]|0)!=0){break l}if((c[ya>>2]|0)!=0){break l}ra=c[xa>>2]|0;pa=c[g>>2]|0;c[o>>2]=0;ua=0;while(1){Aa=Za(c[wa>>2]|0,ra+ua|0,pa-ua|0)|0;if((Aa|0)<1){s=174;break}ta=(c[o>>2]|0)+Aa|0;c[o>>2]=ta;if(ta>>>0>>0){ua=ta}else{Ba=ta;break}}if((s|0)==174){s=0;if((Aa|0)<0){break}c[ya>>2]=1;Ba=c[o>>2]|0}c[va>>2]=c[xa>>2];if((Ba|0)==0){break l}else{Ca=Ba}}else{Ca=sa}sa=Ca+ -1|0;c[o>>2]=sa;ua=c[f>>2]|0;c[f>>2]=ua+1;if((a[ua]|0)==0){break l}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}while(0);m:do{if((z&16|0)!=0){Ca=b+76|0;Ba=b+40|0;Aa=b+24|0;sa=b+4|0;xa=b+84|0;va=c[o>>2]|0;while(1){if((va|0)==0){if((c[Ca>>2]|0)!=0){break m}if((c[Ba>>2]|0)!=0){break m}ya=c[Aa>>2]|0;wa=c[g>>2]|0;c[o>>2]=0;za=0;while(1){Da=Za(c[sa>>2]|0,ya+za|0,wa-za|0)|0;if((Da|0)<1){s=187;break}ua=(c[o>>2]|0)+Da|0;c[o>>2]=ua;if(ua>>>0>>0){za=ua}else{Ea=ua;break}}if((s|0)==187){s=0;if((Da|0)<0){break}c[Ba>>2]=1;Ea=c[o>>2]|0}c[xa>>2]=c[Aa>>2];if((Ea|0)==0){break m}else{Fa=Ea}}else{Fa=va}va=Fa+ -1|0;c[o>>2]=va;za=c[f>>2]|0;c[f>>2]=za+1;if((a[za]|0)==0){break m}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}while(0);n:do{if((z&2|0)!=0){Fa=c[o>>2]|0;o:do{if((Fa|0)==0){Ea=b+76|0;if((c[Ea>>2]|0)==0){Da=b+40|0;if((c[Da>>2]|0)==0){va=b+24|0;Aa=c[va>>2]|0;xa=c[g>>2]|0;c[o>>2]=0;Ba=b+4|0;sa=0;while(1){Ga=Za(c[Ba>>2]|0,Aa+sa|0,xa-sa|0)|0;if((Ga|0)<1){s=199;break}Ca=(c[o>>2]|0)+Ga|0;c[o>>2]=Ca;if(Ca>>>0>>0){sa=Ca}else{Ha=Ca;break}}do{if((s|0)==199){if((Ga|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);Ia=c[o>>2]|0;s=204;break o}else{c[Da>>2]=1;Ha=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[va>>2];if((Ha|0)!=0){Ja=Ha;s=203}else{Ka=Ea;s=206}}else{Ka=Ea;s=206}}else{s=205}}else{Ja=Fa;s=203}}while(0);if((s|0)==203){Fa=Ja+ -1|0;c[o>>2]=Fa;c[f>>2]=(c[f>>2]|0)+1;Ia=Fa;s=204}if((s|0)==204){if((Ia|0)==0){s=205}else{La=Ia}}if((s|0)==205){Ka=b+76|0;s=206}if((s|0)==206){if((c[Ka>>2]|0)!=0){break}Fa=b+40|0;if((c[Fa>>2]|0)!=0){break}Da=b+24|0;sa=c[Da>>2]|0;xa=c[g>>2]|0;c[o>>2]=0;Aa=b+4|0;Ba=0;while(1){Ma=Za(c[Aa>>2]|0,sa+Ba|0,xa-Ba|0)|0;if((Ma|0)<1){s=211;break}Ca=(c[o>>2]|0)+Ma|0;c[o>>2]=Ca;if(Ca>>>0>>0){Ba=Ca}else{Na=Ca;break}}do{if((s|0)==211){if((Ma|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break n}else{c[Fa>>2]=1;Na=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[Da>>2];if((Na|0)==0){break}else{La=Na}}c[o>>2]=La+ -1;c[f>>2]=(c[f>>2]|0)+1}}while(0);Hf(f)|0;c[b+132>>2]=gf(0,0,0)|0;c[b+52>>2]=2;c[b+56>>2]=0;p=0;i=e;return p|0}vf(b,-3,21400);p=-1;i=e;return p|0}vf(b,-3,21368);p=-1;i=e;return p|0}La=b+28|0;a[c[La>>2]|0]=31;c[b+36>>2]=1;Oa=La;Pa=c[o>>2]|0}else{Oa=b+28|0;Pa=v}c[b+48>>2]=c[b+12>>2];v=c[Oa>>2]|0;c[b+32>>2]=v;if((Pa|0)!=0){Oa=b+36|0;Kg(v+(c[Oa>>2]|0)|0,c[f>>2]|0,Pa|0)|0;c[Oa>>2]=(c[Oa>>2]|0)+(c[o>>2]|0);c[o>>2]=0}c[b+52>>2]=1;c[b+56>>2]=1;p=0;i=e;return p|0}function Af(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}if((c[a>>2]|0)!=7247){d=-2;i=b;return d|0}if((c[a+16>>2]|0)!=0){Mf(a+84|0)|0;hg(c[a+28>>2]|0);hg(c[a+24>>2]|0)}vf(a,0,0);hg(c[a+8>>2]|0);e=ib(c[a+4>>2]|0)|0;hg(a);d=((e|0)!=0)<<31>>31;i=b;return d|0}function Bf(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0;e=i;f=a+84|0;g=a+88|0;h=c[g>>2]|0;a:do{if((h|0)==0){j=a+76|0;if((c[j>>2]|0)==0){k=a+40|0;if((c[k>>2]|0)==0){l=a+24|0;m=c[l>>2]|0;n=c[a+16>>2]|0;c[g>>2]=0;o=a+4|0;p=0;while(1){q=Za(c[o>>2]|0,m+p|0,n-p|0)|0;if((q|0)<1){r=7;break}s=(c[g>>2]|0)+q|0;c[g>>2]=s;if(s>>>0>>0){p=s}else{t=s;break}}do{if((r|0)==7){if((q|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);u=-1;v=c[g>>2]|0;r=12;break a}else{c[k>>2]=1;t=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[l>>2];if((t|0)!=0){w=t;r=11}else{x=j;y=-1;r=14}}else{x=j;y=-1;r=14}}else{z=-1;r=13}}else{w=h;r=11}}while(0);if((r|0)==11){h=w+ -1|0;c[g>>2]=h;w=c[f>>2]|0;c[f>>2]=w+1;u=d[w]|0;v=h;r=12}if((r|0)==12){if((v|0)==0){z=u;r=13}else{A=u;B=v;r=25}}if((r|0)==13){x=a+76|0;y=z;r=14}b:do{if((r|0)==14){if((c[x>>2]|0)!=0){C=y+ -256|0;r=27;break}z=a+40|0;if((c[z>>2]|0)==0){v=a+24|0;u=c[v>>2]|0;h=c[a+16>>2]|0;c[g>>2]=0;w=a+4|0;t=0;while(1){D=Za(c[w>>2]|0,u+t|0,h-t|0)|0;if((D|0)<1){r=20;break}q=(c[g>>2]|0)+D|0;c[g>>2]=q;if(q>>>0>>0){t=q}else{E=q;break}}do{if((r|0)==20){if((D|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);F=y;G=-256;H=c[g>>2]|0;r=26;break b}else{c[z>>2]=1;E=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[v>>2];if((E|0)!=0){A=y;B=E;r=25;break}}I=x;J=y+ -256|0;r=28}}while(0);if((r|0)==25){y=B+ -1|0;c[g>>2]=y;B=c[f>>2]|0;c[f>>2]=B+1;F=A;G=(d[B]|0)<<8;H=y;r=26}if((r|0)==26){y=G+F|0;if((H|0)==0){C=y;r=27}else{K=H;L=y;r=39}}if((r|0)==27){I=a+76|0;J=C;r=28}c:do{if((r|0)==28){if((c[I>>2]|0)!=0){M=J+ -65536|0;r=41;break}C=a+40|0;if((c[C>>2]|0)==0){y=a+24|0;H=c[y>>2]|0;F=c[a+16>>2]|0;c[g>>2]=0;G=a+4|0;B=0;while(1){N=Za(c[G>>2]|0,H+B|0,F-B|0)|0;if((N|0)<1){r=34;break}A=(c[g>>2]|0)+N|0;c[g>>2]=A;if(A>>>0>>0){B=A}else{O=A;break}}do{if((r|0)==34){if((N|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);P=J;Q=-65536;R=c[g>>2]|0;r=40;break c}else{c[C>>2]=1;O=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[y>>2];if((O|0)!=0){K=O;L=J;r=39;break}}S=I;T=J+ -65536|0;r=42}}while(0);if((r|0)==39){J=K+ -1|0;c[g>>2]=J;K=c[f>>2]|0;c[f>>2]=K+1;P=L;Q=(d[K]|0)<<16;R=J;r=40}if((r|0)==40){J=Q+P|0;if((R|0)==0){M=J;r=41}else{U=R;V=J}}if((r|0)==41){S=a+76|0;T=M;r=42}if((r|0)==42){if((c[S>>2]|0)!=0){W=-1;i=e;return W|0}S=a+40|0;if((c[S>>2]|0)!=0){W=-1;i=e;return W|0}M=a+24|0;J=c[M>>2]|0;R=c[a+16>>2]|0;c[g>>2]=0;P=a+4|0;Q=0;while(1){X=Za(c[P>>2]|0,J+Q|0,R-Q|0)|0;if((X|0)<1){r=47;break}K=(c[g>>2]|0)+X|0;c[g>>2]=K;if(K>>>0>>0){Q=K}else{Y=K;break}}do{if((r|0)==47){if((X|0)>=0){c[S>>2]=1;Y=c[g>>2]|0;break}vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);W=-1;i=e;return W|0}}while(0);c[a+84>>2]=c[M>>2];if((Y|0)==0){W=-1;i=e;return W|0}else{U=Y;V=T}}c[g>>2]=U+ -1;U=c[f>>2]|0;c[f>>2]=U+1;c[b>>2]=((d[U]|0)<<24)+V;W=0;i=e;return W|0}function Cf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=i;if((a|0)==0){f=0;i=e;return f|0}g=a+84|0;if((c[a>>2]|0)!=31153){f=0;i=e;return f|0}if((c[a+76>>2]|0)!=0){f=0;i=e;return f|0}if((d|0)<0){vf(a,-5,21568);f=0;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}h=a+16|0;if((c[h>>2]|0)==0?(Df(a)|0)==-1:0){f=0;i=e;return f|0}j=a+72|0;a:do{if((c[j>>2]|0)!=0){c[j>>2]=0;k=c[a+68>>2]|0;l=a+88|0;if((c[l>>2]|0)!=0?(Ef(a,0)|0)==-1:0){f=0;i=e;return f|0}if((k|0)!=0){m=a+24|0;n=a+12|0;o=k;k=0;while(1){p=c[h>>2]|0;q=(p|0)<0|(p|0)>(o|0)?o:p;if(!k){Eg(c[m>>2]|0,0,q|0)|0}c[l>>2]=q;c[g>>2]=c[m>>2];c[n>>2]=(c[n>>2]|0)+q;if((Ef(a,0)|0)==-1){f=0;break}if((o|0)==(q|0)){break a}o=o-q|0;k=1}i=e;return f|0}}}while(0);j=a+88|0;b:do{if(!((c[h>>2]|0)>>>0>d>>>0)){if((c[j>>2]|0)!=0?(Ef(a,0)|0)==-1:0){f=0;i=e;return f|0}c[j>>2]=d;c[g>>2]=b;k=a+12|0;c[k>>2]=(c[k>>2]|0)+d;if((Ef(a,0)|0)==-1){f=0;i=e;return f|0}}else{k=a+24|0;o=a+12|0;n=b;m=d;while(1){l=c[j>>2]|0;if((l|0)==0){q=c[k>>2]|0;c[g>>2]=q;r=q}else{r=c[g>>2]|0}q=(c[h>>2]|0)-l|0;p=q>>>0>m>>>0?m:q;Kg(r+l|0,n|0,p|0)|0;c[j>>2]=(c[j>>2]|0)+p;c[o>>2]=(c[o>>2]|0)+p;if((m|0)==(p|0)){break b}if((Ef(a,0)|0)==-1){f=0;break}n=n+p|0;m=m-p|0}i=e;return f|0}}while(0);f=d;i=e;return f|0}function Df(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;b=i;d=a+20|0;e=c[d>>2]|0;f=gg(e)|0;g=a+24|0;c[g>>2]=f;h=gg(e)|0;e=a+28|0;c[e>>2]=h;j=(h|0)==0;if(!((f|0)==0|j)){c[a+116>>2]=0;c[a+120>>2]=0;c[a+124>>2]=0;if((hf(a+84|0,c[a+60>>2]|0,8,31,8,c[a+64>>2]|0,21664,56)|0)==0){k=c[d>>2]|0;c[a+16>>2]=k;c[a+100>>2]=k;k=c[e>>2]|0;c[a+96>>2]=k;c[a+32>>2]=k;l=0;i=b;return l|0}else{hg(c[g>>2]|0);vf(a,-4,21648);l=-1;i=b;return l|0}}if(j){m=f}else{hg(h);m=c[g>>2]|0}if((m|0)!=0){hg(m)}vf(a,-4,21648);l=-1;i=b;return l|0}function Ef(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;d=i;e=a+84|0;f=a+16|0;if((c[f>>2]|0)==0?(Df(a)|0)==-1:0){g=-1;i=d;return g|0}h=a+100|0;j=a+96|0;k=a+32|0;l=a+28|0;m=a+4|0;a:do{if((b|0)==4){n=c[h>>2]|0;o=0;while(1){if((n|0)==0|(o|0)==1){p=c[j>>2]|0;q=c[k>>2]|0;r=p-q|0;if((p|0)==(q|0)){s=n}else{p=Qa(c[m>>2]|0,q|0,r|0)|0;if(!((p|0)>-1&(p|0)==(r|0))){t=30;break a}s=c[h>>2]|0}if((s|0)==0){r=c[f>>2]|0;c[h>>2]=r;p=c[l>>2]|0;c[j>>2]=p;u=p;v=r}else{u=c[j>>2]|0;v=s}c[k>>2]=u;w=v}else{w=n}r=lf(e,4)|0;if((r|0)==-2){t=36;break a}p=c[h>>2]|0;if((w|0)==(p|0)){t=38;break}else{n=p;o=r}}}else if((b|0)==0){o=c[h>>2]|0;while(1){if((o|0)==0){n=c[j>>2]|0;r=c[k>>2]|0;p=n-r|0;if((n|0)!=(r|0)){n=Qa(c[m>>2]|0,r|0,p|0)|0;if(!((n|0)>-1&(n|0)==(p|0))){t=30;break a}p=c[h>>2]|0;if((p|0)!=0){x=c[j>>2]|0;y=p}else{t=10}}else{t=10}if((t|0)==10){t=0;p=c[f>>2]|0;c[h>>2]=p;n=c[l>>2]|0;c[j>>2]=n;x=n;y=p}c[k>>2]=x;z=y}else{z=o}if((lf(e,0)|0)==-2){t=36;break a}p=c[h>>2]|0;if((z|0)==(p|0)){t=38;break}else{o=p}}}else{o=c[h>>2]|0;while(1){if((o|0)!=0&(b|0)==0){A=o}else{p=c[j>>2]|0;n=c[k>>2]|0;r=p-n|0;if((p|0)==(n|0)){B=o}else{p=Qa(c[m>>2]|0,n|0,r|0)|0;if(!((p|0)>-1&(p|0)==(r|0))){t=30;break a}B=c[h>>2]|0}if((B|0)==0){r=c[f>>2]|0;c[h>>2]=r;p=c[l>>2]|0;c[j>>2]=p;C=p;D=r}else{C=c[j>>2]|0;D=B}c[k>>2]=C;A=D}if((lf(e,b)|0)==-2){t=36;break a}r=c[h>>2]|0;if((A|0)==(r|0)){t=38;break}else{o=r}}}}while(0);if((t|0)==30){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);g=-1;i=d;return g|0}else if((t|0)==36){vf(a,-2,21608);g=-1;i=d;return g|0}else if((t|0)==38){if((b|0)!=4){g=0;i=d;return g|0}kf(e)|0;g=0;i=d;return g|0}return 0}function Ff(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}if((c[a>>2]|0)!=31153){d=-2;i=b;return d|0}e=a+72|0;a:do{if((c[e>>2]|0)!=0){c[e>>2]=0;f=c[a+68>>2]|0;g=a+88|0;if((c[g>>2]|0)!=0?(Ef(a,0)|0)==-1:0){h=-1;break}if((f|0)!=0){j=a+16|0;k=a+24|0;l=a+84|0;m=a+12|0;n=f;f=0;while(1){o=c[j>>2]|0;p=(o|0)<0|(o|0)>(n|0)?n:o;if(!f){Eg(c[k>>2]|0,0,p|0)|0}c[g>>2]=p;c[l>>2]=c[k>>2];c[m>>2]=(c[m>>2]|0)+p;if((Ef(a,0)|0)==-1){h=-1;break a}if((n|0)==(p|0)){h=0;break}else{n=n-p|0;f=1}}}else{h=0}}else{h=0}}while(0);e=(Ef(a,4)|0)+h|0;jf(a+84|0)|0;hg(c[a+28>>2]|0);hg(c[a+24>>2]|0);vf(a,0,0);hg(c[a+8>>2]|0);h=ib(c[a+4>>2]|0)|0;hg(a);d=((e|0)!=(0-h|0))<<31>>31;i=b;return d|0}function Gf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0;g=i;h=c[e+28>>2]|0;j=c[e>>2]|0;k=e+4|0;l=j+((c[k>>2]|0)+ -6)|0;m=e+12|0;n=c[m>>2]|0;o=e+16|0;p=c[o>>2]|0;q=n+(p+ -258)|0;r=c[h+44>>2]|0;s=c[h+48>>2]|0;t=c[h+52>>2]|0;u=h+56|0;v=h+60|0;w=c[h+76>>2]|0;x=c[h+80>>2]|0;y=(1<>2])+ -1|0;z=(1<>2])+ -1|0;A=n+(p+~f)|0;f=h+7104|0;p=t+ -1|0;B=(s|0)==0;C=(c[h+40>>2]|0)+ -1|0;D=C+s|0;E=s+ -1|0;F=A+ -1|0;G=A-s|0;H=c[v>>2]|0;I=c[u>>2]|0;J=j+ -1|0;j=n+ -1|0;a:while(1){if(H>>>0<15){n=J+2|0;K=H+16|0;L=((d[J+1|0]|0)<>1]|0;P=d[w+(n<<2)+1|0]|0;n=L>>>P;Q=K-P|0;do{if(!(N<<24>>24==0)){R=N&255;S=Q;T=n;P=O;while(1){if((R&16|0)!=0){break}if((R&64|0)!=0){U=55;break a}V=(T&(1<>1]|0;Y=d[w+(V<<2)+1|0]|0;Z=T>>>Y;_=S-Y|0;if(W<<24>>24==0){U=6;break}else{R=W&255;S=_;T=Z;P=X}}if((U|0)==6){U=0;$=Z;aa=_;ba=X&255;U=7;break}W=P&65535;Y=R&15;if((Y|0)==0){ca=S;da=T;ea=M;fa=W}else{if(S>>>0>>0){V=M+1|0;ga=S+8|0;ha=((d[V]|0)<>>Y;ea=ia;fa=(ha&(1<>>0<15){W=ea+2|0;ja=ca+16|0;ka=((d[ea+1|0]|0)<>1]|0;V=d[x+(W<<2)+1|0]|0;ma=ka>>>V;na=ja-V|0;V=d[x+(W<<2)|0]|0;if((V&16|0)==0){W=V;oa=ma;pa=na;qa=Y;while(1){if((W&64|0)!=0){U=52;break a}ra=(oa&(1<>1]|0;ta=d[x+(ra<<2)+1|0]|0;ua=oa>>>ta;va=pa-ta|0;ta=d[x+(ra<<2)|0]|0;if((ta&16|0)==0){W=ta;oa=ua;pa=va;qa=sa}else{wa=ua;xa=va;ya=ta;za=sa;break}}}else{wa=ma;xa=na;ya=V;za=Y}qa=za&65535;W=ya&15;if(xa>>>0>>0){P=la+1|0;sa=((d[P]|0)<>>0>>0){va=la+2|0;Aa=xa+16|0;Ba=((d[va]|0)<>>W;Ea=Aa-W|0;W=j;qa=W-A|0;if(!(P>>>0>qa>>>0)){sa=j+(0-P)|0;ta=fa;va=j;while(1){a[va+1|0]=a[sa+1|0]|0;a[va+2|0]=a[sa+2|0]|0;ua=sa+3|0;Fa=va+3|0;a[Fa]=a[ua]|0;ta=ta+ -3|0;if(!(ta>>>0>2)){break}else{sa=ua;va=Fa}}if((ta|0)==0){Ga=Ea;Ha=Da;Ia=Ca;Ja=Fa;break}Y=va+4|0;a[Y]=a[sa+4|0]|0;if(!(ta>>>0>1)){Ga=Ea;Ha=Da;Ia=Ca;Ja=Y;break}Y=va+5|0;a[Y]=a[sa+5|0]|0;Ga=Ea;Ha=Da;Ia=Ca;Ja=Y;break}Y=P-qa|0;if(Y>>>0>r>>>0?(c[f>>2]|0)!=0:0){U=22;break a}do{if(B){V=t+(C-Y)|0;if(Y>>>0>>0){na=fa-Y|0;ma=P-W|0;ua=V;ra=Y;Ka=j;do{ua=ua+1|0;Ka=Ka+1|0;a[Ka]=a[ua]|0;ra=ra+ -1|0}while((ra|0)!=0);La=j+(F+ma+(1-P))|0;Ma=na;Na=j+(A+ma)|0}else{La=V;Ma=fa;Na=j}}else{if(!(s>>>0>>0)){ra=t+(E-Y)|0;if(!(Y>>>0>>0)){La=ra;Ma=fa;Na=j;break}ua=fa-Y|0;Ka=P-W|0;Oa=ra;ra=Y;Pa=j;do{Oa=Oa+1|0;Pa=Pa+1|0;a[Pa]=a[Oa]|0;ra=ra+ -1|0}while((ra|0)!=0);La=j+(F+Ka+(1-P))|0;Ma=ua;Na=j+(A+Ka)|0;break}ra=t+(D-Y)|0;Oa=Y-s|0;if(Oa>>>0>>0){Pa=fa-Oa|0;V=P-W|0;ma=ra;na=Oa;Oa=j;do{ma=ma+1|0;Oa=Oa+1|0;a[Oa]=a[ma]|0;na=na+ -1|0}while((na|0)!=0);na=j+(G+V)|0;if(s>>>0>>0){ma=Pa-s|0;Oa=p;Ka=s;ua=na;do{Oa=Oa+1|0;ua=ua+1|0;a[ua]=a[Oa]|0;Ka=Ka+ -1|0}while((Ka|0)!=0);La=j+(F+V+(1-P))|0;Ma=ma;Na=j+(A+V)|0}else{La=p;Ma=Pa;Na=na}}else{La=ra;Ma=fa;Na=j}}}while(0);if(Ma>>>0>2){P=La;W=Ma;Y=Na;while(1){a[Y+1|0]=a[P+1|0]|0;a[Y+2|0]=a[P+2|0]|0;qa=P+3|0;sa=Y+3|0;a[sa]=a[qa]|0;va=W+ -3|0;if(va>>>0>2){P=qa;W=va;Y=sa}else{Qa=qa;Ra=va;Sa=sa;break}}}else{Qa=La;Ra=Ma;Sa=Na}if((Ra|0)!=0){Y=Sa+1|0;a[Y]=a[Qa+1|0]|0;if(Ra>>>0>1){W=Sa+2|0;a[W]=a[Qa+2|0]|0;Ga=Ea;Ha=Da;Ia=Ca;Ja=W}else{Ga=Ea;Ha=Da;Ia=Ca;Ja=Y}}else{Ga=Ea;Ha=Da;Ia=Ca;Ja=Sa}}else{$=n;aa=Q;ba=O&255;U=7}}while(0);if((U|0)==7){U=0;O=j+1|0;a[O]=ba;Ga=aa;Ha=$;Ia=M;Ja=O}if(Ia>>>0>>0&Ja>>>0>>0){H=Ga;I=Ha;J=Ia;j=Ja}else{Ta=Ga;Ua=Ha;Va=Ia;Wa=Ja;break}}do{if((U|0)==22){c[e+24>>2]=21672;c[h>>2]=29;Ta=Ea;Ua=Da;Va=Ca;Wa=j}else if((U|0)==52){c[e+24>>2]=21704;c[h>>2]=29;Ta=pa;Ua=oa;Va=la;Wa=j}else if((U|0)==55){if((R&32|0)==0){c[e+24>>2]=21728;c[h>>2]=29;Ta=S;Ua=T;Va=M;Wa=j;break}else{c[h>>2]=11;Ta=S;Ua=T;Va=M;Wa=j;break}}}while(0);j=Ta>>>3;M=Va+(0-j)|0;T=Ta-(j<<3)|0;Ta=(1<>2]=Va+(1-j);c[m>>2]=Wa+1;if(M>>>0>>0){Xa=l-M|0}else{Xa=l-M|0}c[k>>2]=Xa+5;if(Wa>>>0>>0){Ya=q-Wa|0;Za=Ya+257|0;c[o>>2]=Za;c[u>>2]=Ta;c[v>>2]=T;i=g;return}else{Ya=q-Wa|0;Za=Ya+257|0;c[o>>2]=Za;c[u>>2]=Ta;c[v>>2]=T;i=g;return}}function Hf(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=c[a+28>>2]|0;if((e|0)==0){d=-2;i=b;return d|0}c[e+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[e>>2]=0;c[e+4>>2]=0;c[e+12>>2]=0;c[e+20>>2]=32768;c[e+32>>2]=0;c[e+40>>2]=0;c[e+44>>2]=0;c[e+48>>2]=0;c[e+56>>2]=0;c[e+60>>2]=0;a=e+1328|0;c[e+108>>2]=a;c[e+80>>2]=a;c[e+76>>2]=a;c[e+7104>>2]=1;c[e+7108>>2]=-1;d=0;i=b;return d|0}function If(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;if((a|0)==0){e=-2;i=d;return e|0}f=a+28|0;g=c[f>>2]|0;if((g|0)==0){e=-2;i=d;return e|0}if((b|0)<0){h=0-b|0;j=0}else{h=(b|0)<48?b&15:b;j=(b>>4)+1|0}if((h|0)!=0&(h+ -8|0)>>>0>7){e=-2;i=d;return e|0}b=g+52|0;k=c[b>>2]|0;l=g+36|0;if((k|0)!=0?(c[l>>2]|0)!=(h|0):0){mb[c[a+36>>2]&1](c[a+40>>2]|0,k);c[b>>2]=0}c[g+8>>2]=j;c[l>>2]=h;h=c[f>>2]|0;if((h|0)==0){e=-2;i=d;return e|0}c[h+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[h>>2]=0;c[h+4>>2]=0;c[h+12>>2]=0;c[h+20>>2]=32768;c[h+32>>2]=0;c[h+40>>2]=0;c[h+44>>2]=0;c[h+48>>2]=0;c[h+56>>2]=0;c[h+60>>2]=0;a=h+1328|0;c[h+108>>2]=a;c[h+80>>2]=a;c[h+76>>2]=a;c[h+7104>>2]=1;c[h+7108>>2]=-1;e=0;i=d;return e|0}function Jf(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0;g=i;if((e|0)==0){h=-6;i=g;return h|0}if(!((a[e]|0)==49&(f|0)==56)){h=-6;i=g;return h|0}if((b|0)==0){h=-2;i=g;return h|0}c[b+24>>2]=0;f=b+32|0;e=c[f>>2]|0;if((e|0)==0){c[f>>2]=1;c[b+40>>2]=0;j=1}else{j=e}e=b+36|0;if((c[e>>2]|0)==0){c[e>>2]=1}f=b+40|0;k=kb[j&1](c[f>>2]|0,1,7116)|0;if((k|0)==0){h=-4;i=g;return h|0}j=b+28|0;c[j>>2]=k;c[k+52>>2]=0;l=If(b,d)|0;if((l|0)==0){h=0;i=g;return h|0}mb[c[e>>2]&1](c[f>>2]|0,k);c[j>>2]=0;h=l;i=g;return h|0}function Kf(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,fb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0,sc=0,tc=0,uc=0,vc=0,wc=0,xc=0,yc=0,zc=0,Ac=0,Bc=0,Cc=0,Dc=0,Ec=0,Fc=0,Gc=0,Hc=0,Ic=0,Jc=0,Kc=0,Lc=0,Mc=0,Nc=0,Oc=0,Pc=0,Qc=0,Rc=0,Sc=0,Tc=0,Uc=0,Vc=0,Wc=0,Xc=0,Yc=0,Zc=0,_c=0,$c=0,ad=0,bd=0,cd=0,dd=0,ed=0,fd=0,gd=0,hd=0,id=0,jd=0,kd=0,ld=0,md=0,nd=0,od=0,pd=0,qd=0,rd=0,sd=0,td=0,ud=0,vd=0,wd=0,xd=0,yd=0,zd=0,Ad=0,Bd=0,Cd=0,Dd=0,Ed=0,Fd=0,Gd=0,Hd=0,Id=0,Jd=0,Kd=0,Ld=0,Md=0,Nd=0,Od=0,Pd=0,Qd=0,Rd=0,Sd=0,Td=0,Ud=0,Vd=0,Wd=0,Xd=0,Yd=0,Zd=0,_d=0,$d=0,ae=0,be=0,ce=0,de=0,ee=0,fe=0,ge=0,he=0,ie=0,je=0,ke=0,le=0,me=0,ne=0,oe=0,pe=0,qe=0,re=0,se=0,te=0,ue=0,ve=0,we=0,xe=0,ye=0,ze=0,Ae=0,Be=0,Ce=0,De=0,Ee=0,Fe=0,Ge=0,He=0,Ie=0,Je=0,Ke=0,Le=0,Me=0,Ne=0,Oe=0,Pe=0,Qe=0,Re=0,Se=0,Te=0,Ue=0,Ve=0,We=0,Xe=0,Ye=0,Ze=0,_e=0,$e=0,af=0,bf=0,cf=0,df=0,ef=0,hf=0,jf=0,kf=0,lf=0,mf=0,nf=0,of=0,pf=0,qf=0,rf=0,sf=0,tf=0,uf=0,vf=0,wf=0,xf=0,yf=0,zf=0,Af=0,Bf=0,Cf=0,Df=0,Ef=0,Ff=0,Hf=0,If=0,Jf=0,Kf=0,Mf=0,Of=0,Pf=0,Qf=0,Rf=0,Sf=0,Tf=0,Uf=0,Vf=0,Wf=0,Xf=0,Yf=0,Zf=0,_f=0,$f=0,ag=0,bg=0,cg=0,dg=0,eg=0,fg=0,gg=0,hg=0,ig=0,jg=0,kg=0,lg=0,mg=0,ng=0,og=0,pg=0,qg=0,rg=0,sg=0,tg=0,ug=0,vg=0,wg=0,xg=0,yg=0,zg=0,Ag=0,Bg=0,Cg=0,Dg=0,Eg=0,Fg=0,Gg=0,Hg=0,Ig=0,Jg=0;h=i;i=i+16|0;j=h;if((f|0)==0){k=-2;i=h;return k|0}l=c[f+28>>2]|0;if((l|0)==0){k=-2;i=h;return k|0}m=f+12|0;n=c[m>>2]|0;if((n|0)==0){k=-2;i=h;return k|0}o=c[f>>2]|0;if((o|0)==0?(c[f+4>>2]|0)!=0:0){k=-2;i=h;return k|0}p=c[l>>2]|0;if((p|0)==11){c[l>>2]=12;q=12;r=c[f>>2]|0;s=c[m>>2]|0}else{q=p;r=o;s=n}n=f+16|0;o=c[n>>2]|0;p=f+4|0;t=c[p>>2]|0;u=l+56|0;v=l+60|0;w=l+8|0;x=l+24|0;y=j+1|0;z=l+16|0;A=l+32|0;B=f+24|0;C=l+36|0;D=l+20|0;E=f+48|0;F=l+64|0;G=l+12|0;H=(g+ -5|0)>>>0<2;I=l+4|0;J=l+76|0;K=l+84|0;L=l+80|0;M=l+88|0;N=(g|0)==6;O=l+7108|0;P=l+72|0;Q=l+7112|0;R=l+68|0;S=l+44|0;T=l+7104|0;U=l+48|0;V=l+52|0;W=l+40|0;X=f+20|0;Y=l+28|0;Z=l+96|0;_=l+100|0;$=l+92|0;aa=l+104|0;ba=l+1328|0;ca=l+108|0;da=l+112|0;ea=l+752|0;fa=l+624|0;ga=j+2|0;ha=j+3|0;ia=q;q=c[v>>2]|0;ja=t;ka=c[u>>2]|0;la=o;ma=r;r=o;o=s;s=0;a:while(1){b:do{switch(ia|0){case 28:{na=q;oa=ja;pa=ka;qa=la;ra=ma;sa=1;ta=285;break a;break};case 16:{if(q>>>0<14){ua=q;va=ja;wa=ka;xa=ma;while(1){if((va|0)==0){ya=ua;za=0;Aa=wa;Ba=la;Ca=xa;Da=r;Ea=s;break a}Ga=va+ -1|0;Ha=xa+1|0;Ia=(d[xa]<>>0<14){ua=Ja;va=Ga;wa=Ia;xa=Ha}else{Ka=Ja;La=Ga;Ma=Ia;Na=Ha;break}}}else{Ka=q;La=ja;Ma=ka;Na=ma}xa=(Ma&31)+257|0;c[Z>>2]=xa;wa=(Ma>>>5&31)+1|0;c[_>>2]=wa;c[$>>2]=(Ma>>>10&15)+4;va=Ma>>>14;ua=Ka+ -14|0;if(xa>>>0>286|wa>>>0>30){c[B>>2]=21992;c[l>>2]=29;Oa=ua;Pa=La;Qa=va;Ra=la;Sa=Na;Ta=r;Ua=o;Va=s;break b}else{c[aa>>2]=0;c[l>>2]=17;Wa=0;Xa=ua;Ya=La;Za=va;_a=Na;ta=154;break b}break};case 21:{$a=c[P>>2]|0;ab=q;bb=ja;cb=ka;db=ma;eb=s;ta=221;break};case 23:{fb=c[P>>2]|0;gb=q;hb=ja;ib=ka;jb=ma;kb=s;ta=240;break};case 1:{if(q>>>0<16){va=q;ua=ja;wa=ka;xa=ma;while(1){if((ua|0)==0){ya=va;za=0;Aa=wa;Ba=la;Ca=xa;Da=r;Ea=s;break a}Ha=ua+ -1|0;Ia=xa+1|0;Ga=(d[xa]<>>0<16){va=Ja;ua=Ha;wa=Ga;xa=Ia}else{lb=Ja;mb=Ha;nb=Ga;ob=Ia;break}}}else{lb=q;mb=ja;nb=ka;ob=ma}c[z>>2]=nb;if((nb&255|0)!=8){c[B>>2]=21824;c[l>>2]=29;Oa=lb;Pa=mb;Qa=nb;Ra=la;Sa=ob;Ta=r;Ua=o;Va=s;break b}if((nb&57344|0)!=0){c[B>>2]=21880;c[l>>2]=29;Oa=lb;Pa=mb;Qa=nb;Ra=la;Sa=ob;Ta=r;Ua=o;Va=s;break b}xa=c[A>>2]|0;if((xa|0)==0){pb=nb}else{c[xa>>2]=nb>>>8&1;pb=c[z>>2]|0}if((pb&512|0)!=0){a[j]=nb;a[y]=nb>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0}c[l>>2]=2;qb=0;rb=mb;sb=0;tb=ob;ta=47;break};case 22:{ub=q;vb=ja;wb=ka;xb=ma;yb=s;ta=228;break};case 10:{zb=q;Ab=ja;Bb=ka;Cb=ma;ta=121;break};case 7:{Db=q;Eb=ja;Fb=ka;Gb=ma;ta=96;break};case 5:{Hb=q;Ib=ja;Jb=ka;Kb=ma;ta=73;break};case 8:{Lb=q;Mb=ja;Nb=ka;Ob=ma;ta=109;break};case 11:{Pb=q;Qb=ja;Rb=ka;Sb=ma;ta=124;break};case 12:{Tb=q;Ub=ja;Vb=ka;Wb=ma;ta=125;break};case 13:{xa=q&7;wa=ka>>>xa;ua=q-xa|0;if(ua>>>0<32){xa=ua;va=ja;Ia=wa;Ga=ma;while(1){if((va|0)==0){ya=xa;za=0;Aa=Ia;Ba=la;Ca=Ga;Da=r;Ea=s;break a}Ha=va+ -1|0;Ja=Ga+1|0;Xb=(d[Ga]<>>0<32){xa=Yb;va=Ha;Ia=Xb;Ga=Ja}else{Zb=Yb;_b=Ha;$b=Xb;ac=Ja;break}}}else{Zb=ua;_b=ja;$b=wa;ac=ma}Ga=$b&65535;if((Ga|0)==($b>>>16^65535|0)){c[F>>2]=Ga;c[l>>2]=14;if(N){na=0;oa=_b;pa=0;qa=la;ra=ac;sa=s;ta=285;break a}else{bc=0;cc=_b;dc=0;ec=ac;ta=143;break b}}else{c[B>>2]=21960;c[l>>2]=29;Oa=Zb;Pa=_b;Qa=$b;Ra=la;Sa=ac;Ta=r;Ua=o;Va=s;break b}break};case 14:{bc=q;cc=ja;dc=ka;ec=ma;ta=143;break};case 15:{fc=q;gc=ja;hc=ka;ic=ma;ta=144;break};case 17:{Ga=c[aa>>2]|0;if(Ga>>>0<(c[$>>2]|0)>>>0){Wa=Ga;Xa=q;Ya=ja;Za=ka;_a=ma;ta=154}else{jc=Ga;kc=q;lc=ja;mc=ka;nc=ma;ta=158}break};case 0:{Ga=c[w>>2]|0;if((Ga|0)==0){c[l>>2]=12;Oa=q;Pa=ja;Qa=ka;Ra=la;Sa=ma;Ta=r;Ua=o;Va=s;break b}if(q>>>0<16){Ia=q;va=ja;xa=ka;Ja=ma;while(1){if((va|0)==0){ya=Ia;za=0;Aa=xa;Ba=la;Ca=Ja;Da=r;Ea=s;break a}Xb=va+ -1|0;Ha=Ja+1|0;Yb=(d[Ja]<>>0<16){Ia=oc;va=Xb;xa=Yb;Ja=Ha}else{pc=oc;qc=Xb;rc=Yb;sc=Ha;break}}}else{pc=q;qc=ja;rc=ka;sc=ma}if((Ga&2|0)!=0&(rc|0)==35615){c[x>>2]=gf(0,0,0)|0;a[j]=31;a[y]=-117;c[x>>2]=gf(c[x>>2]|0,j,2)|0;c[l>>2]=1;Oa=0;Pa=qc;Qa=0;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}c[z>>2]=0;Ja=c[A>>2]|0;if((Ja|0)==0){tc=Ga}else{c[Ja+48>>2]=-1;tc=c[w>>2]|0}if((tc&1|0)!=0?((((rc<<8&65280)+(rc>>>8)|0)>>>0)%31|0|0)==0:0){if((rc&15|0)!=8){c[B>>2]=21824;c[l>>2]=29;Oa=pc;Pa=qc;Qa=rc;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}Ja=rc>>>4;xa=pc+ -4|0;va=(Ja&15)+8|0;Ia=c[C>>2]|0;if((Ia|0)!=0){if(va>>>0>Ia>>>0){c[B>>2]=21856;c[l>>2]=29;Oa=xa;Pa=qc;Qa=Ja;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}}else{c[C>>2]=va}c[D>>2]=1<>2]=va;c[E>>2]=va;c[l>>2]=rc>>>12&2^11;Oa=0;Pa=qc;Qa=0;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}c[B>>2]=21800;c[l>>2]=29;Oa=pc;Pa=qc;Qa=rc;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break};case 24:{uc=q;vc=ja;wc=ka;xc=ma;yc=s;ta=246;break};case 9:{if(q>>>0<32){va=q;Ja=ja;xa=ka;Ia=ma;while(1){if((Ja|0)==0){ya=va;za=0;Aa=xa;Ba=la;Ca=Ia;Da=r;Ea=s;break a}wa=Ja+ -1|0;ua=Ia+1|0;Ha=(d[Ia]<>>0<32){va=Yb;Ja=wa;xa=Ha;Ia=ua}else{zc=wa;Ac=Ha;Bc=ua;break}}}else{zc=ja;Ac=ka;Bc=ma}Ia=Fa(Ac|0)|0;c[x>>2]=Ia;c[E>>2]=Ia;c[l>>2]=10;zb=0;Ab=zc;Bb=0;Cb=Bc;ta=121;break};case 30:{ta=299;break a;break};case 18:{Cc=c[aa>>2]|0;Dc=q;Ec=ja;Fc=ka;Gc=ma;Hc=s;ta=164;break};case 6:{Ic=q;Jc=ja;Kc=ka;Lc=ma;ta=83;break};case 29:{ya=q;za=ja;Aa=ka;Ba=la;Ca=ma;Da=r;Ea=-3;break a;break};case 19:{Mc=q;Nc=ja;Oc=ka;Pc=ma;Qc=s;ta=201;break};case 20:{Rc=q;Sc=ja;Tc=ka;Uc=ma;Vc=s;ta=202;break};case 25:{if((la|0)==0){na=q;oa=ja;pa=ka;qa=0;ra=ma;sa=s;ta=285;break a}a[o]=c[F>>2];c[l>>2]=20;Oa=q;Pa=ja;Qa=ka;Ra=la+ -1|0;Sa=ma;Ta=r;Ua=o+1|0;Va=s;break};case 26:{if((c[w>>2]|0)!=0){if(q>>>0<32){Ia=q;xa=ja;Ja=ka;va=ma;while(1){if((xa|0)==0){ya=Ia;za=0;Aa=Ja;Ba=la;Ca=va;Da=r;Ea=s;break a}Ga=xa+ -1|0;ua=va+1|0;Ha=(d[va]<>>0<32){Ia=wa;xa=Ga;Ja=Ha;va=ua}else{Wc=wa;Xc=Ga;Yc=Ha;Zc=ua;break}}}else{Wc=q;Xc=ja;Yc=ka;Zc=ma}va=r-la|0;c[X>>2]=(c[X>>2]|0)+va;c[Y>>2]=(c[Y>>2]|0)+va;if((r|0)!=(la|0)){Ja=c[x>>2]|0;xa=o+(0-va)|0;if((c[z>>2]|0)==0){_c=ff(Ja,xa,va)|0}else{_c=gf(Ja,xa,va)|0}c[x>>2]=_c;c[E>>2]=_c}if((c[z>>2]|0)==0){$c=Fa(Yc|0)|0}else{$c=Yc}if(($c|0)==(c[x>>2]|0)){ad=0;bd=Xc;cd=0;dd=Zc;ed=la}else{c[B>>2]=22280;c[l>>2]=29;Oa=Wc;Pa=Xc;Qa=Yc;Ra=la;Sa=Zc;Ta=la;Ua=o;Va=s;break b}}else{ad=q;bd=ja;cd=ka;dd=ma;ed=r}c[l>>2]=27;fd=ad;gd=bd;hd=cd;id=dd;jd=ed;ta=277;break};case 27:{fd=q;gd=ja;hd=ka;id=ma;jd=r;ta=277;break};case 2:{if(q>>>0<32){qb=q;rb=ja;sb=ka;tb=ma;ta=47}else{kd=ja;ld=ka;md=ma;ta=49}break};case 4:{nd=q;od=ja;pd=ka;qd=ma;ta=62;break};case 3:{if(q>>>0<16){rd=q;sd=ja;td=ka;ud=ma;ta=55}else{vd=ja;wd=ka;xd=ma;ta=57}break};default:{k=-2;ta=300;break a}}}while(0);if((ta|0)==47){while(1){ta=0;if((rb|0)==0){ya=qb;za=0;Aa=sb;Ba=la;Ca=tb;Da=r;Ea=s;break a}va=rb+ -1|0;xa=tb+1|0;Ja=(d[tb]<>>0<32){qb=Ia;rb=va;sb=Ja;tb=xa;ta=47}else{kd=va;ld=Ja;md=xa;ta=49;break}}}else if((ta|0)==121){ta=0;if((c[G>>2]|0)==0){ta=122;break}xa=ff(0,0,0)|0;c[x>>2]=xa;c[E>>2]=xa;c[l>>2]=11;Pb=zb;Qb=Ab;Rb=Bb;Sb=Cb;ta=124}else if((ta|0)==143){ta=0;c[l>>2]=15;fc=bc;gc=cc;hc=dc;ic=ec;ta=144}else if((ta|0)==154){while(1){ta=0;if(Xa>>>0<3){xa=Xa;Ja=Ya;va=Za;Ia=_a;while(1){if((Ja|0)==0){ya=xa;za=0;Aa=va;Ba=la;Ca=Ia;Da=r;Ea=s;break a}ua=Ja+ -1|0;Ha=Ia+1|0;Ga=(d[Ia]<>>0<3){xa=wa;Ja=ua;va=Ga;Ia=Ha}else{yd=wa;zd=ua;Ad=Ga;Bd=Ha;break}}}else{yd=Xa;zd=Ya;Ad=Za;Bd=_a}c[aa>>2]=Wa+1;b[l+(e[21760+(Wa<<1)>>1]<<1)+112>>1]=Ad&7;Ia=Ad>>>3;va=yd+ -3|0;Ja=c[aa>>2]|0;if(Ja>>>0<(c[$>>2]|0)>>>0){Wa=Ja;Xa=va;Ya=zd;Za=Ia;_a=Bd;ta=154}else{jc=Ja;kc=va;lc=zd;mc=Ia;nc=Bd;ta=158;break}}}else if((ta|0)==277){ta=0;if((c[w>>2]|0)==0){Cd=fd;Dd=gd;Ed=hd;Fd=id;ta=284;break}if((c[z>>2]|0)==0){Cd=fd;Dd=gd;Ed=hd;Fd=id;ta=284;break}if(fd>>>0<32){Ia=fd;va=gd;Ja=hd;xa=id;while(1){if((va|0)==0){ya=Ia;za=0;Aa=Ja;Ba=la;Ca=xa;Da=jd;Ea=s;break a}Ha=va+ -1|0;Ga=xa+1|0;ua=(d[xa]<>>0<32){Ia=wa;va=Ha;Ja=ua;xa=Ga}else{Gd=wa;Hd=Ha;Id=ua;Jd=Ga;break}}}else{Gd=fd;Hd=gd;Id=hd;Jd=id}if((Id|0)==(c[Y>>2]|0)){Cd=0;Dd=Hd;Ed=0;Fd=Jd;ta=284;break}c[B>>2]=22304;c[l>>2]=29;Oa=Gd;Pa=Hd;Qa=Id;Ra=la;Sa=Jd;Ta=jd;Ua=o;Va=s}do{if((ta|0)==49){ta=0;xa=c[A>>2]|0;if((xa|0)!=0){c[xa+4>>2]=ld}if((c[z>>2]&512|0)!=0){a[j]=ld;a[y]=ld>>>8;a[ga]=ld>>>16;a[ha]=ld>>>24;c[x>>2]=gf(c[x>>2]|0,j,4)|0}c[l>>2]=3;rd=0;sd=kd;td=0;ud=md;ta=55}else if((ta|0)==124){ta=0;if(H){na=Pb;oa=Qb;pa=Rb;qa=la;ra=Sb;sa=s;ta=285;break a}else{Tb=Pb;Ub=Qb;Vb=Rb;Wb=Sb;ta=125}}else if((ta|0)==144){ta=0;xa=c[F>>2]|0;if((xa|0)==0){c[l>>2]=11;Oa=fc;Pa=gc;Qa=hc;Ra=la;Sa=ic;Ta=r;Ua=o;Va=s;break}Ja=xa>>>0>gc>>>0?gc:xa;xa=Ja>>>0>la>>>0?la:Ja;if((xa|0)==0){na=fc;oa=gc;pa=hc;qa=la;ra=ic;sa=s;ta=285;break a}Kg(o|0,ic|0,xa|0)|0;c[F>>2]=(c[F>>2]|0)-xa;Oa=fc;Pa=gc-xa|0;Qa=hc;Ra=la-xa|0;Sa=ic+xa|0;Ta=r;Ua=o+xa|0;Va=s}else if((ta|0)==158){ta=0;if(jc>>>0<19){xa=jc;while(1){Ja=xa+1|0;b[l+(e[21760+(xa<<1)>>1]<<1)+112>>1]=0;if((Ja|0)==19){break}else{xa=Ja}}c[aa>>2]=19}c[ca>>2]=ba;c[J>>2]=ba;c[K>>2]=7;xa=Nf(0,da,19,ca,K,ea)|0;if((xa|0)==0){c[aa>>2]=0;c[l>>2]=18;Cc=0;Dc=kc;Ec=lc;Fc=mc;Gc=nc;Hc=0;ta=164;break}else{c[B>>2]=22032;c[l>>2]=29;Oa=kc;Pa=lc;Qa=mc;Ra=la;Sa=nc;Ta=r;Ua=o;Va=xa;break}}}while(0);c:do{if((ta|0)==55){while(1){ta=0;if((sd|0)==0){ya=rd;za=0;Aa=td;Ba=la;Ca=ud;Da=r;Ea=s;break a}xa=sd+ -1|0;Ja=ud+1|0;va=(d[ud]<>>0<16){rd=Ia;sd=xa;td=va;ud=Ja;ta=55}else{vd=xa;wd=va;xd=Ja;ta=57;break}}}else if((ta|0)==125){ta=0;if((c[I>>2]|0)!=0){Ja=Tb&7;c[l>>2]=26;Oa=Tb-Ja|0;Pa=Ub;Qa=Vb>>>Ja;Ra=la;Sa=Wb;Ta=r;Ua=o;Va=s;break}if(Tb>>>0<3){Ja=Tb;va=Ub;xa=Vb;Ia=Wb;while(1){if((va|0)==0){ya=Ja;za=0;Aa=xa;Ba=la;Ca=Ia;Da=r;Ea=s;break a}Ga=va+ -1|0;ua=Ia+1|0;Ha=(d[Ia]<>>0<3){Ja=wa;va=Ga;xa=Ha;Ia=ua}else{Kd=wa;Ld=Ga;Md=Ha;Nd=ua;break}}}else{Kd=Tb;Ld=Ub;Md=Vb;Nd=Wb}c[I>>2]=Md&1;Ia=Md>>>1&3;if((Ia|0)==0){c[l>>2]=13}else if((Ia|0)==1){c[J>>2]=22328;c[K>>2]=9;c[L>>2]=24376;c[M>>2]=5;c[l>>2]=19;if(N){ta=133;break a}}else if((Ia|0)==2){c[l>>2]=16}else if((Ia|0)==3){c[B>>2]=21936;c[l>>2]=29}Oa=Kd+ -3|0;Pa=Ld;Qa=Md>>>3;Ra=la;Sa=Nd;Ta=r;Ua=o;Va=s}else if((ta|0)==164){ta=0;Ia=c[Z>>2]|0;xa=c[_>>2]|0;do{if(Cc>>>0<(xa+Ia|0)>>>0){va=Cc;Ja=xa;ua=Ia;Ha=Dc;Ga=Ec;wa=Fc;Yb=Gc;d:while(1){Xb=(1<>2])+ -1|0;oc=Xb&wa;Od=c[J>>2]|0;Pd=d[Od+(oc<<2)+1|0]|0;if(Pd>>>0>Ha>>>0){Qd=Ha;Rd=Ga;Sd=wa;Td=Yb;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Td;Da=r;Ea=Hc;break a}Ud=Rd+ -1|0;Vd=Td+1|0;Wd=(d[Td]<>>0>Xd>>>0){Qd=Xd;Rd=Ud;Sd=Wd;Td=Vd}else{_d=Zd;$d=Yd;ae=Xd;be=Ud;ce=Wd;de=Vd;break}}}else{_d=Pd;$d=oc;ae=Ha;be=Ga;ce=wa;de=Yb}Td=b[Od+($d<<2)+2>>1]|0;e:do{if((Td&65535)<16){if(ae>>>0<_d>>>0){Sd=ae;Rd=be;Qd=ce;Xb=de;while(1){if((Rd|0)==0){ya=Sd;za=0;Aa=Qd;Ba=la;Ca=Xb;Da=r;Ea=Hc;break a}Vd=Rd+ -1|0;Wd=Xb+1|0;Ud=(d[Xb]<>>0<_d>>>0){Sd=Xd;Rd=Vd;Qd=Ud;Xb=Wd}else{ee=Xd;fe=Vd;ge=Ud;he=Wd;break}}}else{ee=ae;fe=be;ge=ce;he=de}c[aa>>2]=va+1;b[l+(va<<1)+112>>1]=Td;ie=ee-_d|0;je=fe;ke=ge>>>_d;le=he}else{if(Td<<16>>16==16){Xb=_d+2|0;if(ae>>>0>>0){Qd=ae;Rd=be;Sd=ce;Wd=de;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Wd;Da=r;Ea=Hc;break a}Ud=Rd+ -1|0;Vd=Wd+1|0;Xd=(d[Wd]<>>0>>0){Qd=Yd;Rd=Ud;Sd=Xd;Wd=Vd}else{me=Yd;ne=Ud;oe=Xd;pe=Vd;break}}}else{me=ae;ne=be;oe=ce;pe=de}qe=oe>>>_d;re=me-_d|0;if((va|0)==0){ta=181;break d}se=re+ -2|0;te=(qe&3)+3|0;ue=ne;ve=qe>>>2;we=b[l+(va+ -1<<1)+112>>1]|0;xe=pe}else if(Td<<16>>16==17){Wd=_d+3|0;if(ae>>>0>>0){Sd=ae;Rd=be;Qd=ce;Xb=de;while(1){if((Rd|0)==0){ya=Sd;za=0;Aa=Qd;Ba=la;Ca=Xb;Da=r;Ea=Hc;break a}Vd=Rd+ -1|0;Xd=Xb+1|0;Ud=(d[Xb]<>>0>>0){Sd=Yd;Rd=Vd;Qd=Ud;Xb=Xd}else{ye=Yd;ze=Vd;Ae=Ud;Be=Xd;break}}}else{ye=ae;ze=be;Ae=ce;Be=de}Xb=Ae>>>_d;se=-3-_d+ye|0;te=(Xb&7)+3|0;ue=ze;ve=Xb>>>3;we=0;xe=Be}else{Xb=_d+7|0;if(ae>>>0>>0){Qd=ae;Rd=be;Sd=ce;Wd=de;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Wd;Da=r;Ea=Hc;break a}Xd=Rd+ -1|0;Ud=Wd+1|0;Vd=(d[Wd]<>>0>>0){Qd=Yd;Rd=Xd;Sd=Vd;Wd=Ud}else{Ce=Yd;De=Xd;Ee=Vd;Fe=Ud;break}}}else{Ce=ae;De=be;Ee=ce;Fe=de}Wd=Ee>>>_d;se=-7-_d+Ce|0;te=(Wd&127)+11|0;ue=De;ve=Wd>>>7;we=0;xe=Fe}if((va+te|0)>>>0>(Ja+ua|0)>>>0){ta=190;break d}else{Ge=va;He=te}while(1){Wd=He+ -1|0;c[aa>>2]=Ge+1;b[l+(Ge<<1)+112>>1]=we;if((Wd|0)==0){ie=se;je=ue;ke=ve;le=xe;break e}Ge=c[aa>>2]|0;He=Wd}}}while(0);Td=c[aa>>2]|0;Ie=c[Z>>2]|0;Od=c[_>>2]|0;if(Td>>>0<(Od+Ie|0)>>>0){va=Td;Ja=Od;ua=Ie;Ha=ie;Ga=je;wa=ke;Yb=le}else{ta=193;break}}if((ta|0)==181){ta=0;c[B>>2]=22064;c[l>>2]=29;Oa=re;Pa=ne;Qa=qe;Ra=la;Sa=pe;Ta=r;Ua=o;Va=Hc;break c}else if((ta|0)==190){ta=0;c[B>>2]=22064;c[l>>2]=29;Oa=se;Pa=ue;Qa=ve;Ra=la;Sa=xe;Ta=r;Ua=o;Va=Hc;break c}else if((ta|0)==193){ta=0;if((c[l>>2]|0)==29){Oa=ie;Pa=je;Qa=ke;Ra=la;Sa=le;Ta=r;Ua=o;Va=Hc;break c}else{Je=Ie;Ke=ie;Le=je;Me=ke;Ne=le;break}}}else{Je=Ia;Ke=Dc;Le=Ec;Me=Fc;Ne=Gc}}while(0);if((b[fa>>1]|0)==0){c[B>>2]=22096;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Hc;break}c[ca>>2]=ba;c[J>>2]=ba;c[K>>2]=9;Ia=Nf(1,da,Je,ca,K,ea)|0;if((Ia|0)!=0){c[B>>2]=22136;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Ia;break}c[L>>2]=c[ca>>2];c[M>>2]=6;Ia=Nf(2,l+(c[Z>>2]<<1)+112|0,c[_>>2]|0,ca,M,ea)|0;if((Ia|0)==0){c[l>>2]=19;if(N){na=Ke;oa=Le;pa=Me;qa=la;ra=Ne;sa=0;ta=285;break a}else{Mc=Ke;Nc=Le;Oc=Me;Pc=Ne;Qc=0;ta=201;break}}else{c[B>>2]=22168;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Ia;break}}}while(0);if((ta|0)==57){ta=0;Ia=c[A>>2]|0;if((Ia|0)!=0){c[Ia+8>>2]=wd&255;c[Ia+12>>2]=wd>>>8}if((c[z>>2]&512|0)!=0){a[j]=wd;a[y]=wd>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0}c[l>>2]=4;nd=0;od=vd;pd=0;qd=xd;ta=62}else if((ta|0)==201){ta=0;c[l>>2]=20;Rc=Mc;Sc=Nc;Tc=Oc;Uc=Pc;Vc=Qc;ta=202}do{if((ta|0)==62){ta=0;Ia=c[z>>2]|0;if((Ia&1024|0)==0){xa=c[A>>2]|0;if((xa|0)==0){Oe=nd;Pe=od;Qe=pd;Re=qd}else{c[xa+16>>2]=0;Oe=nd;Pe=od;Qe=pd;Re=qd}}else{if(nd>>>0<16){xa=nd;Yb=od;wa=pd;Ga=qd;while(1){if((Yb|0)==0){ya=xa;za=0;Aa=wa;Ba=la;Ca=Ga;Da=r;Ea=s;break a}Ha=Yb+ -1|0;ua=Ga+1|0;Ja=(d[Ga]<>>0<16){xa=va;Yb=Ha;wa=Ja;Ga=ua}else{Se=Ha;Te=Ja;Ue=ua;break}}}else{Se=od;Te=pd;Ue=qd}c[F>>2]=Te;Ga=c[A>>2]|0;if((Ga|0)==0){Ve=Ia}else{c[Ga+20>>2]=Te;Ve=c[z>>2]|0}if((Ve&512|0)==0){Oe=0;Pe=Se;Qe=0;Re=Ue}else{a[j]=Te;a[y]=Te>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0;Oe=0;Pe=Se;Qe=0;Re=Ue}}c[l>>2]=5;Hb=Oe;Ib=Pe;Jb=Qe;Kb=Re;ta=73}else if((ta|0)==202){ta=0;if(Sc>>>0>5&la>>>0>257){c[m>>2]=o;c[n>>2]=la;c[f>>2]=Uc;c[p>>2]=Sc;c[u>>2]=Tc;c[v>>2]=Rc;Gf(f,r);Ga=c[m>>2]|0;wa=c[n>>2]|0;Yb=c[f>>2]|0;xa=c[p>>2]|0;ua=c[u>>2]|0;Ja=c[v>>2]|0;if((c[l>>2]|0)!=11){Oa=Ja;Pa=xa;Qa=ua;Ra=wa;Sa=Yb;Ta=r;Ua=Ga;Va=Vc;break}c[O>>2]=-1;Oa=Ja;Pa=xa;Qa=ua;Ra=wa;Sa=Yb;Ta=r;Ua=Ga;Va=Vc;break}c[O>>2]=0;Ga=(1<>2])+ -1|0;Yb=Ga&Tc;wa=c[J>>2]|0;ua=a[wa+(Yb<<2)+1|0]|0;xa=ua&255;if(xa>>>0>Rc>>>0){Ja=Rc;Ha=Sc;va=Tc;Od=Uc;while(1){if((Ha|0)==0){ya=Ja;za=0;Aa=va;Ba=la;Ca=Od;Da=r;Ea=Vc;break a}Td=Ha+ -1|0;oc=Od+1|0;Pd=(d[Od]<>>0>Wd>>>0){Ja=Wd;Ha=Td;va=Pd;Od=oc}else{We=Rd;Xe=Qd;Ye=Sd;Ze=Wd;_e=Td;$e=Pd;af=oc;break}}}else{We=ua;Xe=xa;Ye=Yb;Ze=Rc;_e=Sc;$e=Tc;af=Uc}Od=a[wa+(Ye<<2)|0]|0;va=b[wa+(Ye<<2)+2>>1]|0;Ha=Od&255;if(!(Od<<24>>24==0)){if((Ha&240|0)==0){Ja=va&65535;Ga=(1<>>Xe)+Ja|0;Ia=a[wa+(Ha<<2)+1|0]|0;if(((Ia&255)+Xe|0)>>>0>Ze>>>0){oc=Ze;Pd=_e;Td=$e;Wd=af;while(1){if((Pd|0)==0){ya=oc;za=0;Aa=Td;Ba=la;Ca=Wd;Da=r;Ea=Vc;break a}Sd=Pd+ -1|0;Qd=Wd+1|0;Rd=(d[Wd]<>>Xe)+Ja|0;Vd=a[wa+(Ud<<2)+1|0]|0;if(((Vd&255)+Xe|0)>>>0>Xb>>>0){oc=Xb;Pd=Sd;Td=Rd;Wd=Qd}else{bf=Ud;cf=Vd;df=Xb;ef=Sd;hf=Rd;jf=Qd;break}}}else{bf=Ha;cf=Ia;df=Ze;ef=_e;hf=$e;jf=af}Wd=b[wa+(bf<<2)+2>>1]|0;Td=a[wa+(bf<<2)|0]|0;c[O>>2]=Xe;kf=Xe;lf=df-Xe|0;mf=ef;nf=Td;of=cf;pf=Wd;qf=hf>>>Xe;rf=jf}else{kf=0;lf=Ze;mf=_e;nf=Od;of=We;pf=va;qf=$e;rf=af}}else{kf=0;lf=Ze;mf=_e;nf=0;of=We;pf=va;qf=$e;rf=af}Wd=of&255;Td=qf>>>Wd;Pd=lf-Wd|0;c[O>>2]=kf+Wd;c[F>>2]=pf&65535;Wd=nf&255;if(nf<<24>>24==0){c[l>>2]=25;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}if((Wd&32|0)!=0){c[O>>2]=-1;c[l>>2]=11;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}if((Wd&64|0)==0){oc=Wd&15;c[P>>2]=oc;c[l>>2]=21;$a=oc;ab=Pd;bb=mf;cb=Td;db=rf;eb=Vc;ta=221;break}else{c[B>>2]=22192;c[l>>2]=29;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}}}while(0);if((ta|0)==73){ta=0;Td=c[z>>2]|0;if((Td&1024|0)!=0){Pd=c[F>>2]|0;oc=Pd>>>0>Ib>>>0?Ib:Pd;if((oc|0)==0){sf=Pd;tf=Ib;uf=Kb}else{Wd=c[A>>2]|0;if((Wd|0)!=0?(Ja=c[Wd+16>>2]|0,(Ja|0)!=0):0){Ga=(c[Wd+20>>2]|0)-Pd|0;Pd=c[Wd+24>>2]|0;Kg(Ja+Ga|0,Kb|0,((Ga+oc|0)>>>0>Pd>>>0?Pd-Ga|0:oc)|0)|0;vf=c[z>>2]|0}else{vf=Td}if((vf&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Kb,oc)|0}Td=(c[F>>2]|0)-oc|0;c[F>>2]=Td;sf=Td;tf=Ib-oc|0;uf=Kb+oc|0}if((sf|0)==0){wf=tf;xf=uf}else{na=Hb;oa=tf;pa=Jb;qa=la;ra=uf;sa=s;ta=285;break}}else{wf=Ib;xf=Kb}c[F>>2]=0;c[l>>2]=6;Ic=Hb;Jc=wf;Kc=Jb;Lc=xf;ta=83}else if((ta|0)==221){ta=0;if(($a|0)==0){yf=c[F>>2]|0;zf=ab;Af=bb;Bf=cb;Cf=db}else{if(ab>>>0<$a>>>0){oc=ab;Td=bb;Ga=cb;Pd=db;while(1){if((Td|0)==0){ya=oc;za=0;Aa=Ga;Ba=la;Ca=Pd;Da=r;Ea=eb;break a}Ja=Td+ -1|0;Wd=Pd+1|0;Yb=(d[Pd]<>>0<$a>>>0){oc=xa;Td=Ja;Ga=Yb;Pd=Wd}else{Df=xa;Ef=Ja;Ff=Yb;Hf=Wd;break}}}else{Df=ab;Ef=bb;Ff=cb;Hf=db}Pd=(c[F>>2]|0)+((1<<$a)+ -1&Ff)|0;c[F>>2]=Pd;c[O>>2]=(c[O>>2]|0)+$a;yf=Pd;zf=Df-$a|0;Af=Ef;Bf=Ff>>>$a;Cf=Hf}c[Q>>2]=yf;c[l>>2]=22;ub=zf;vb=Af;wb=Bf;xb=Cf;yb=eb;ta=228}do{if((ta|0)==83){ta=0;if((c[z>>2]&2048|0)==0){Pd=c[A>>2]|0;if((Pd|0)==0){If=Jc;Jf=Lc}else{c[Pd+28>>2]=0;If=Jc;Jf=Lc}}else{if((Jc|0)==0){na=Ic;oa=0;pa=Kc;qa=la;ra=Lc;sa=s;ta=285;break a}else{Kf=0}while(1){Mf=Kf+1|0;Pd=a[Lc+Kf|0]|0;Ga=c[A>>2]|0;if(((Ga|0)!=0?(Td=c[Ga+28>>2]|0,(Td|0)!=0):0)?(oc=c[F>>2]|0,oc>>>0<(c[Ga+32>>2]|0)>>>0):0){c[F>>2]=oc+1;a[Td+oc|0]=Pd}Of=Pd<<24>>24!=0;if(Of&Mf>>>0>>0){Kf=Mf}else{break}}if((c[z>>2]&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Lc,Mf)|0}va=Jc-Mf|0;Od=Lc+Mf|0;if(Of){na=Ic;oa=va;pa=Kc;qa=la;ra=Od;sa=s;ta=285;break a}else{If=va;Jf=Od}}c[F>>2]=0;c[l>>2]=7;Db=Ic;Eb=If;Fb=Kc;Gb=Jf;ta=96}else if((ta|0)==228){ta=0;Od=(1<>2])+ -1|0;va=Od&wb;wa=c[L>>2]|0;Ia=a[wa+(va<<2)+1|0]|0;Ha=Ia&255;if(Ha>>>0>ub>>>0){Pd=ub;oc=vb;Td=wb;Ga=xb;while(1){if((oc|0)==0){ya=Pd;za=0;Aa=Td;Ba=la;Ca=Ga;Da=r;Ea=yb;break a}Wd=oc+ -1|0;Yb=Ga+1|0;Ja=(d[Ga]<>>0>xa>>>0){Pd=xa;oc=Wd;Td=Ja;Ga=Yb}else{Pf=Qd;Qf=Rd;Rf=ua;Sf=xa;Tf=Wd;Uf=Ja;Vf=Yb;break}}}else{Pf=Ia;Qf=Ha;Rf=va;Sf=ub;Tf=vb;Uf=wb;Vf=xb}Ga=a[wa+(Rf<<2)|0]|0;Td=b[wa+(Rf<<2)+2>>1]|0;oc=Ga&255;if((oc&240|0)==0){Pd=Td&65535;Od=(1<>>Qf)+Pd|0;Yb=a[wa+(oc<<2)+1|0]|0;if(((Yb&255)+Qf|0)>>>0>Sf>>>0){Ja=Sf;Wd=Tf;xa=Uf;ua=Vf;while(1){if((Wd|0)==0){ya=Ja;za=0;Aa=xa;Ba=la;Ca=ua;Da=r;Ea=yb;break a}Rd=Wd+ -1|0;Qd=ua+1|0;Sd=(d[ua]<>>Qf)+Pd|0;Ud=a[wa+(Vd<<2)+1|0]|0;if(((Ud&255)+Qf|0)>>>0>Xb>>>0){Ja=Xb;Wd=Rd;xa=Sd;ua=Qd}else{Wf=Vd;Xf=Ud;Yf=Xb;Zf=Rd;_f=Sd;$f=Qd;break}}}else{Wf=oc;Xf=Yb;Yf=Sf;Zf=Tf;_f=Uf;$f=Vf}ua=b[wa+(Wf<<2)+2>>1]|0;xa=a[wa+(Wf<<2)|0]|0;Wd=(c[O>>2]|0)+Qf|0;c[O>>2]=Wd;ag=Wd;bg=Yf-Qf|0;cg=Zf;dg=xa;eg=Xf;fg=ua;gg=_f>>>Qf;hg=$f}else{ag=c[O>>2]|0;bg=Sf;cg=Tf;dg=Ga;eg=Pf;fg=Td;gg=Uf;hg=Vf}ua=eg&255;xa=gg>>>ua;Wd=bg-ua|0;c[O>>2]=ag+ua;ua=dg&255;if((ua&64|0)==0){c[R>>2]=fg&65535;Ja=ua&15;c[P>>2]=Ja;c[l>>2]=23;fb=Ja;gb=Wd;hb=cg;ib=xa;jb=hg;kb=yb;ta=240;break}else{c[B>>2]=22224;c[l>>2]=29;Oa=Wd;Pa=cg;Qa=xa;Ra=la;Sa=hg;Ta=r;Ua=o;Va=yb;break}}}while(0);if((ta|0)==96){ta=0;if((c[z>>2]&4096|0)==0){xa=c[A>>2]|0;if((xa|0)==0){ig=Eb;jg=Gb}else{c[xa+36>>2]=0;ig=Eb;jg=Gb}}else{if((Eb|0)==0){na=Db;oa=0;pa=Fb;qa=la;ra=Gb;sa=s;ta=285;break}else{kg=0}while(1){lg=kg+1|0;xa=a[Gb+kg|0]|0;Wd=c[A>>2]|0;if(((Wd|0)!=0?(Ja=c[Wd+36>>2]|0,(Ja|0)!=0):0)?(ua=c[F>>2]|0,ua>>>0<(c[Wd+40>>2]|0)>>>0):0){c[F>>2]=ua+1;a[Ja+ua|0]=xa}mg=xa<<24>>24!=0;if(mg&lg>>>0>>0){kg=lg}else{break}}if((c[z>>2]&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Gb,lg)|0}xa=Eb-lg|0;ua=Gb+lg|0;if(mg){na=Db;oa=xa;pa=Fb;qa=la;ra=ua;sa=s;ta=285;break}else{ig=xa;jg=ua}}c[l>>2]=8;Lb=Db;Mb=ig;Nb=Fb;Ob=jg;ta=109}else if((ta|0)==240){ta=0;if((fb|0)==0){ng=gb;og=hb;pg=ib;qg=jb}else{if(gb>>>0>>0){ua=gb;xa=hb;Ja=ib;Wd=jb;while(1){if((xa|0)==0){ya=ua;za=0;Aa=Ja;Ba=la;Ca=Wd;Da=r;Ea=kb;break a}Pd=xa+ -1|0;Od=Wd+1|0;va=(d[Wd]<>>0>>0){ua=Ha;xa=Pd;Ja=va;Wd=Od}else{rg=Ha;sg=Pd;tg=va;ug=Od;break}}}else{rg=gb;sg=hb;tg=ib;ug=jb}c[R>>2]=(c[R>>2]|0)+((1<>2]=(c[O>>2]|0)+fb;ng=rg-fb|0;og=sg;pg=tg>>>fb;qg=ug}c[l>>2]=24;uc=ng;vc=og;wc=pg;xc=qg;yc=kb;ta=246}do{if((ta|0)==109){ta=0;Wd=c[z>>2]|0;if((Wd&512|0)!=0){if(Lb>>>0<16){Ja=Lb;xa=Mb;ua=Nb;Od=Ob;while(1){if((xa|0)==0){ya=Ja;za=0;Aa=ua;Ba=la;Ca=Od;Da=r;Ea=s;break a}va=xa+ -1|0;Pd=Od+1|0;Ha=(d[Od]<>>0<16){Ja=Ia;xa=va;ua=Ha;Od=Pd}else{vg=Ia;wg=va;xg=Ha;yg=Pd;break}}}else{vg=Lb;wg=Mb;xg=Nb;yg=Ob}if((xg|0)==(c[x>>2]&65535|0)){zg=0;Ag=wg;Bg=0;Cg=yg}else{c[B>>2]=21912;c[l>>2]=29;Oa=vg;Pa=wg;Qa=xg;Ra=la;Sa=yg;Ta=r;Ua=o;Va=s;break}}else{zg=Lb;Ag=Mb;Bg=Nb;Cg=Ob}Od=c[A>>2]|0;if((Od|0)!=0){c[Od+44>>2]=Wd>>>9&1;c[Od+48>>2]=1}Od=gf(0,0,0)|0;c[x>>2]=Od;c[E>>2]=Od;c[l>>2]=11;Oa=zg;Pa=Ag;Qa=Bg;Ra=la;Sa=Cg;Ta=r;Ua=o;Va=s}else if((ta|0)==246){ta=0;if((la|0)==0){na=uc;oa=vc;pa=wc;qa=0;ra=xc;sa=yc;ta=285;break a}Od=r-la|0;ua=c[R>>2]|0;if(ua>>>0>Od>>>0){xa=ua-Od|0;if(xa>>>0>(c[S>>2]|0)>>>0?(c[T>>2]|0)!=0:0){c[B>>2]=22248;c[l>>2]=29;Oa=uc;Pa=vc;Qa=wc;Ra=la;Sa=xc;Ta=r;Ua=o;Va=yc;break}Od=c[U>>2]|0;if(xa>>>0>Od>>>0){Ja=xa-Od|0;Dg=Ja;Eg=(c[V>>2]|0)+((c[W>>2]|0)-Ja)|0}else{Dg=xa;Eg=(c[V>>2]|0)+(Od-xa)|0}xa=c[F>>2]|0;Fg=xa;Gg=Dg>>>0>xa>>>0?xa:Dg;Hg=Eg}else{xa=c[F>>2]|0;Fg=xa;Gg=xa;Hg=o+(0-ua)|0}ua=Gg>>>0>la>>>0?la:Gg;c[F>>2]=Fg-ua;xa=~la;Od=~Gg;Ja=xa>>>0>Od>>>0?xa:Od;Od=ua;xa=Hg;Td=o;while(1){a[Td]=a[xa]|0;Od=Od+ -1|0;if((Od|0)==0){break}else{xa=xa+1|0;Td=Td+1|0}}Td=la-ua|0;xa=o+~Ja|0;if((c[F>>2]|0)==0){c[l>>2]=20;Oa=uc;Pa=vc;Qa=wc;Ra=Td;Sa=xc;Ta=r;Ua=xa;Va=yc}else{Oa=uc;Pa=vc;Qa=wc;Ra=Td;Sa=xc;Ta=r;Ua=xa;Va=yc}}}while(0);ia=c[l>>2]|0;q=Oa;ja=Pa;ka=Qa;la=Ra;ma=Sa;r=Ta;o=Ua;s=Va}if((ta|0)==122){c[m>>2]=o;c[n>>2]=la;c[f>>2]=Cb;c[p>>2]=Ab;c[u>>2]=Bb;c[v>>2]=zb;k=2;i=h;return k|0}else if((ta|0)==133){ya=Kd+ -3|0;za=Ld;Aa=Md>>>3;Ba=la;Ca=Nd;Da=r;Ea=s}else if((ta|0)==284){c[l>>2]=28;ya=Cd;za=Dd;Aa=Ed;Ba=la;Ca=Fd;Da=jd;Ea=1}else if((ta|0)==285){ya=na;za=oa;Aa=pa;Ba=qa;Ca=ra;Da=r;Ea=sa}else if((ta|0)==299){k=-4;i=h;return k|0}else if((ta|0)==300){i=h;return k|0}c[m>>2]=o;c[n>>2]=Ba;c[f>>2]=Ca;c[p>>2]=za;c[u>>2]=Aa;c[v>>2]=ya;if((c[W>>2]|0)==0){if((c[l>>2]|0)>>>0<26?(Da|0)!=(c[n>>2]|0):0){ta=289}}else{ta=289}if((ta|0)==289?(Lf(f,Da)|0)!=0:0){c[l>>2]=30;k=-4;i=h;return k|0}ta=c[p>>2]|0;p=c[n>>2]|0;n=Da-p|0;W=f+8|0;c[W>>2]=t-ta+(c[W>>2]|0);c[X>>2]=(c[X>>2]|0)+n;c[Y>>2]=(c[Y>>2]|0)+n;Y=(Da|0)==(p|0);if(!((c[w>>2]|0)==0|Y)){w=c[x>>2]|0;p=(c[m>>2]|0)+(0-n)|0;if((c[z>>2]|0)==0){Ig=ff(w,p,n)|0}else{Ig=gf(w,p,n)|0}c[x>>2]=Ig;c[E>>2]=Ig}Ig=c[l>>2]|0;if((Ig|0)==19){Jg=256}else{Jg=(Ig|0)==14?256:0}c[f+44>>2]=((c[I>>2]|0)!=0?64:0)+(c[v>>2]|0)+((Ig|0)==11?128:0)+Jg;k=((t|0)==(ta|0)&Y|(g|0)==4)&(Ea|0)==0?-5:Ea;i=h;return k|0}function Lf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;e=c[a+28>>2]|0;f=e+52|0;g=c[f>>2]|0;if((g|0)==0){h=kb[c[a+32>>2]&1](c[a+40>>2]|0,1<>2],1)|0;c[f>>2]=h;if((h|0)==0){j=1;i=d;return j|0}else{k=h}}else{k=g}g=e+40|0;h=c[g>>2]|0;if((h|0)==0){l=1<>2];c[g>>2]=l;c[e+48>>2]=0;c[e+44>>2]=0;m=l}else{m=h}h=b-(c[a+16>>2]|0)|0;if(!(h>>>0>>0)){Kg(k|0,(c[a+12>>2]|0)+(0-m)|0,m|0)|0;c[e+48>>2]=0;c[e+44>>2]=c[g>>2];j=0;i=d;return j|0}b=e+48|0;l=c[b>>2]|0;n=m-l|0;m=n>>>0>h>>>0?h:n;n=a+12|0;Kg(k+l|0,(c[n>>2]|0)+(0-h)|0,m|0)|0;l=h-m|0;if((h|0)!=(m|0)){Kg(c[f>>2]|0,(c[n>>2]|0)+(0-l)|0,l|0)|0;c[b>>2]=l;c[e+44>>2]=c[g>>2];j=0;i=d;return j|0}l=(c[b>>2]|0)+h|0;n=c[g>>2]|0;c[b>>2]=(l|0)==(n|0)?0:l;l=e+44|0;e=c[l>>2]|0;if(!(e>>>0>>0)){j=0;i=d;return j|0}c[l>>2]=e+h;j=0;i=d;return j|0}function Mf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;i=b;return d|0}g=a+36|0;h=c[g>>2]|0;if((h|0)==0){d=-2;i=b;return d|0}j=c[f+52>>2]|0;k=a+40|0;if((j|0)==0){l=h;m=f}else{mb[h&1](c[k>>2]|0,j);l=c[g>>2]|0;m=c[e>>2]|0}mb[l&1](c[k>>2]|0,m);c[e>>2]=0;d=0;i=b;return d|0}function Nf(d,f,g,h,j,k){d=d|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;l=i;i=i+64|0;m=l+32|0;n=l;o=m+0|0;p=o+32|0;do{b[o>>1]=0;o=o+2|0}while((o|0)<(p|0));o=(g|0)==0;if(!o){p=0;do{q=m+(e[f+(p<<1)>>1]<<1)|0;b[q>>1]=(b[q>>1]|0)+1<<16>>16;p=p+1|0}while((p|0)!=(g|0))}p=c[j>>2]|0;q=15;while(1){r=q+ -1|0;if((b[m+(q<<1)>>1]|0)!=0){break}if((r|0)==0){s=7;break}else{q=r}}if((s|0)==7){r=c[h>>2]|0;c[h>>2]=r+4;a[r]=64;a[r+1|0]=1;b[r+2>>1]=0;r=c[h>>2]|0;c[h>>2]=r+4;a[r]=64;a[r+1|0]=1;b[r+2>>1]=0;c[j>>2]=1;t=0;i=l;return t|0}r=p>>>0>q>>>0?q:p;a:do{if(q>>>0>1){p=1;while(1){u=p+1|0;if((b[m+(p<<1)>>1]|0)!=0){v=p;break a}if(u>>>0>>0){p=u}else{v=u;break}}}else{v=1}}while(0);p=r>>>0>>0?v:r;r=1;u=1;do{r=(r<<1)-(e[m+(u<<1)>>1]|0)|0;u=u+1|0;if((r|0)<0){t=-1;s=56;break}}while(u>>>0<16);if((s|0)==56){i=l;return t|0}if((r|0)>0?!((d|0)!=0&(q|0)==1):0){t=-1;i=l;return t|0}b[n+2>>1]=0;r=0;u=1;do{r=(e[m+(u<<1)>>1]|0)+(r&65535)|0;u=u+1|0;b[n+(u<<1)>>1]=r}while((u|0)!=15);if(!o){o=0;do{u=b[f+(o<<1)>>1]|0;if(!(u<<16>>16==0)){r=n+((u&65535)<<1)|0;u=b[r>>1]|0;b[r>>1]=u+1<<16>>16;b[k+((u&65535)<<1)>>1]=o}o=o+1|0}while((o|0)!=(g|0))}if((d|0)==0){w=0;x=1<>>0>851){t=1;i=l;return t|0}else{w=0;x=g;y=1;z=24504+ -514|0;A=256;B=24568+ -514|0}}else{g=1<>>0>591){t=1;i=l;return t|0}else{w=o;x=g;y=0;z=24632;A=-1;B=24696}}g=x+ -1|0;o=p&255;d=p;n=0;u=0;r=v;v=-1;C=c[h>>2]|0;D=0;E=x;b:while(1){x=1<>1]|0;L=K&65535;if((L|0)>=(A|0)){if((L|0)>(A|0)){M=b[B+(L<<1)>>1]&255;N=b[z+(L<<1)>>1]|0}else{M=96;N=0}}else{M=0;N=K}K=1<>>n;L=x;while(1){O=L-K|0;P=O+I|0;a[C+(P<<2)|0]=M;a[C+(P<<2)+1|0]=J;b[C+(P<<2)+2>>1]=N;if((L|0)==(K|0)){break}else{L=O}}L=1<>>1}}if((L|0)==0){Q=0}else{Q=(L+ -1&F)+L|0}R=H+1|0;K=m+(G<<1)|0;I=(b[K>>1]|0)+ -1<<16>>16;b[K>>1]=I;if(I<<16>>16==0){if((G|0)==(q|0)){break b}S=e[f+(e[k+(R<<1)>>1]<<1)>>1]|0}else{S=G}if(!(S>>>0>p>>>0)){F=Q;G=S;H=R;continue}T=Q&g;if((T|0)==(v|0)){F=Q;G=S;H=R}else{break}}H=(n|0)==0?p:n;G=C+(x<<2)|0;F=S-H|0;c:do{if(S>>>0>>0){I=S;K=F;O=1<>1]|0)|0;if((P|0)<1){U=K;break c}V=K+1|0;W=V+H|0;if(W>>>0>>0){I=W;K=V;O=P<<1}else{U=V;break}}}else{U=F}}while(0);F=(1<>>0>851|w&F>>>0>591){t=1;s=56;break}a[(c[h>>2]|0)+(T<<2)|0]=U;a[(c[h>>2]|0)+(T<<2)+1|0]=o;x=c[h>>2]|0;b[x+(T<<2)+2>>1]=(G-x|0)>>>2;d=U;n=H;u=Q;r=S;v=T;C=G;D=R;E=F}if((s|0)==56){i=l;return t|0}d:do{if((Q|0)!=0){s=n;R=J;D=Q;T=q;S=C;while(1){if((s|0)!=0){if((D&g|0)==(v|0)){X=s;Y=R;Z=T;_=S}else{X=0;Y=o;Z=p;_=c[h>>2]|0}}else{X=0;Y=R;Z=T;_=S}r=D>>>X;a[_+(r<<2)|0]=64;a[_+(r<<2)+1|0]=Y;b[_+(r<<2)+2>>1]=0;r=1<>>1}}if((r|0)==0){break d}D=(r+ -1&D)+r|0;if((D|0)==0){break}else{s=X;R=Y;T=Z;S=_}}}}while(0);c[h>>2]=(c[h>>2]|0)+(E<<2);c[j>>2]=p;t=0;i=l;return t|0}function Of(a){a=a|0;var d=0;d=i;c[a+2840>>2]=a+148;c[a+2848>>2]=25528;c[a+2852>>2]=a+2440;c[a+2860>>2]=25552;c[a+2864>>2]=a+2684;c[a+2872>>2]=25576;b[a+5816>>1]=0;c[a+5820>>2]=0;c[a+5812>>2]=8;Pf(a);i=d;return}function Pf(a){a=a|0;var d=0,e=0;d=i;e=0;do{b[a+(e<<2)+148>>1]=0;e=e+1|0}while((e|0)!=286);b[a+2440>>1]=0;b[a+2444>>1]=0;b[a+2448>>1]=0;b[a+2452>>1]=0;b[a+2456>>1]=0;b[a+2460>>1]=0;b[a+2464>>1]=0;b[a+2468>>1]=0;b[a+2472>>1]=0;b[a+2476>>1]=0;b[a+2480>>1]=0;b[a+2484>>1]=0;b[a+2488>>1]=0;b[a+2492>>1]=0;b[a+2496>>1]=0;b[a+2500>>1]=0;b[a+2504>>1]=0;b[a+2508>>1]=0;b[a+2512>>1]=0;b[a+2516>>1]=0;b[a+2520>>1]=0;b[a+2524>>1]=0;b[a+2528>>1]=0;b[a+2532>>1]=0;b[a+2536>>1]=0;b[a+2540>>1]=0;b[a+2544>>1]=0;b[a+2548>>1]=0;b[a+2552>>1]=0;b[a+2556>>1]=0;b[a+2684>>1]=0;b[a+2688>>1]=0;b[a+2692>>1]=0;b[a+2696>>1]=0;b[a+2700>>1]=0;b[a+2704>>1]=0;b[a+2708>>1]=0;b[a+2712>>1]=0;b[a+2716>>1]=0;b[a+2720>>1]=0;b[a+2724>>1]=0;b[a+2728>>1]=0;b[a+2732>>1]=0;b[a+2736>>1]=0;b[a+2740>>1]=0;b[a+2744>>1]=0;b[a+2748>>1]=0;b[a+2752>>1]=0;b[a+2756>>1]=0;b[a+1172>>1]=1;c[a+5804>>2]=0;c[a+5800>>2]=0;c[a+5808>>2]=0;c[a+5792>>2]=0;i=d;return}function Qf(d,f,g,h){d=d|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;j=i;k=d+5820|0;l=c[k>>2]|0;m=h&65535;h=d+5816|0;n=e[h>>1]|0|m<>1]=n;if((l|0)>13){o=d+20|0;p=c[o>>2]|0;c[o>>2]=p+1;q=d+8|0;a[(c[q>>2]|0)+p|0]=n;p=(e[h>>1]|0)>>>8&255;r=c[o>>2]|0;c[o>>2]=r+1;a[(c[q>>2]|0)+r|0]=p;p=c[k>>2]|0;r=m>>>(16-p|0);b[h>>1]=r;s=r;t=p+ -13|0}else{s=n;t=l+3|0}l=s&255;c[k>>2]=t;do{if((t|0)<=8){s=d+20|0;if((t|0)>0){n=c[s>>2]|0;c[s>>2]=n+1;p=d+8|0;a[(c[p>>2]|0)+n|0]=l;u=s;v=p;break}else{u=s;v=d+8|0;break}}else{s=d+20|0;p=c[s>>2]|0;c[s>>2]=p+1;n=d+8|0;a[(c[n>>2]|0)+p|0]=l;p=(e[h>>1]|0)>>>8&255;r=c[s>>2]|0;c[s>>2]=r+1;a[(c[n>>2]|0)+r|0]=p;u=s;v=n}}while(0);b[h>>1]=0;c[k>>2]=0;c[d+5812>>2]=8;d=c[u>>2]|0;c[u>>2]=d+1;a[(c[v>>2]|0)+d|0]=g;d=c[u>>2]|0;c[u>>2]=d+1;a[(c[v>>2]|0)+d|0]=g>>>8;d=g&65535^65535;k=c[u>>2]|0;c[u>>2]=k+1;a[(c[v>>2]|0)+k|0]=d;k=c[u>>2]|0;c[u>>2]=k+1;a[(c[v>>2]|0)+k|0]=d>>>8;if((g|0)==0){i=j;return}else{w=g;x=f}while(1){w=w+ -1|0;f=a[x]|0;g=c[u>>2]|0;c[u>>2]=g+1;a[(c[v>>2]|0)+g|0]=f;if((w|0)==0){break}else{x=x+1|0}}i=j;return}function Rf(d){d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;f=i;g=d+5820|0;h=c[g>>2]|0;j=d+5816|0;k=e[j>>1]|0|2<>1]=l;if((h|0)>13){m=d+20|0;n=c[m>>2]|0;c[m>>2]=n+1;o=d+8|0;a[(c[o>>2]|0)+n|0]=k;k=(e[j>>1]|0)>>>8&255;n=c[m>>2]|0;c[m>>2]=n+1;a[(c[o>>2]|0)+n|0]=k;k=c[g>>2]|0;n=2>>>(16-k|0)&65535;b[j>>1]=n;p=n;q=k+ -13|0}else{p=l;q=h+3|0}c[g>>2]=q;if((q|0)>9){h=d+20|0;l=c[h>>2]|0;c[h>>2]=l+1;k=d+8|0;a[(c[k>>2]|0)+l|0]=p;l=(e[j>>1]|0)>>>8&255;n=c[h>>2]|0;c[h>>2]=n+1;a[(c[k>>2]|0)+n|0]=l;b[j>>1]=0;r=(c[g>>2]|0)+ -9|0;s=0}else{r=q+7|0;s=p}c[g>>2]=r;if((r|0)!=16){if((r|0)>7){p=d+20|0;q=c[p>>2]|0;c[p>>2]=q+1;a[(c[d+8>>2]|0)+q|0]=s;q=(e[j>>1]|0)>>>8;b[j>>1]=q;p=(c[g>>2]|0)+ -8|0;c[g>>2]=p;t=p;u=q}else{t=r;u=s}}else{r=d+20|0;q=c[r>>2]|0;c[r>>2]=q+1;p=d+8|0;a[(c[p>>2]|0)+q|0]=s;s=(e[j>>1]|0)>>>8&255;q=c[r>>2]|0;c[r>>2]=q+1;a[(c[p>>2]|0)+q|0]=s;b[j>>1]=0;c[g>>2]=0;t=0;u=0}s=d+5812|0;if((11-t+(c[s>>2]|0)|0)>=9){c[s>>2]=7;i=f;return}q=u&65535|2<>1]=q;if((t|0)>13){u=d+20|0;p=c[u>>2]|0;c[u>>2]=p+1;r=d+8|0;a[(c[r>>2]|0)+p|0]=q;p=(e[j>>1]|0)>>>8&255;l=c[u>>2]|0;c[u>>2]=l+1;a[(c[r>>2]|0)+l|0]=p;p=c[g>>2]|0;l=2>>>(16-p|0);b[j>>1]=l;v=l;w=p+ -13|0}else{v=q;w=t+3|0}t=v&255;c[g>>2]=w;if((w|0)>9){v=d+20|0;q=c[v>>2]|0;c[v>>2]=q+1;p=d+8|0;a[(c[p>>2]|0)+q|0]=t;q=(e[j>>1]|0)>>>8&255;l=c[v>>2]|0;c[v>>2]=l+1;a[(c[p>>2]|0)+l|0]=q;b[j>>1]=0;x=0;y=(c[g>>2]|0)+ -9|0}else{x=t;y=w+7|0}c[g>>2]=y;if((y|0)==16){w=d+20|0;t=c[w>>2]|0;c[w>>2]=t+1;q=d+8|0;a[(c[q>>2]|0)+t|0]=x;t=(e[j>>1]|0)>>>8&255;l=c[w>>2]|0;c[w>>2]=l+1;a[(c[q>>2]|0)+l|0]=t;b[j>>1]=0;c[g>>2]=0;c[s>>2]=7;i=f;return}if((y|0)<=7){c[s>>2]=7;i=f;return}y=d+20|0;t=c[y>>2]|0;c[y>>2]=t+1;a[(c[d+8>>2]|0)+t|0]=x;b[j>>1]=(e[j>>1]|0)>>>8;c[g>>2]=(c[g>>2]|0)+ -8;c[s>>2]=7;i=f;return}function Sf(f,g,h,j){f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;k=i;if((c[f+132>>2]|0)>0){l=(c[f>>2]|0)+44|0;if((c[l>>2]|0)==2){m=-201342849;n=0;while(1){if((m&1|0)!=0?(b[f+(n<<2)+148>>1]|0)!=0:0){o=0;break}p=n+1|0;if((p|0)<32){m=m>>>1;n=p}else{q=6;break}}a:do{if((q|0)==6){if(((b[f+184>>1]|0)==0?(b[f+188>>1]|0)==0:0)?(b[f+200>>1]|0)==0:0){n=32;while(1){m=n+1|0;if((b[f+(n<<2)+148>>1]|0)!=0){o=1;break a}if((m|0)<256){n=m}else{o=0;break}}}else{o=1}}}while(0);c[l>>2]=o}Tf(f,f+2840|0);Tf(f,f+2852|0);Wf(f,f+148|0,c[f+2844>>2]|0);Wf(f,f+2440|0,c[f+2856>>2]|0);Tf(f,f+2864|0);o=18;while(1){l=o+ -1|0;if((b[f+(d[27352+o|0]<<2)+2686>>1]|0)!=0){r=o;break}if((l|0)>2){o=l}else{r=l;break}}o=f+5800|0;l=(r*3|0)+17+(c[o>>2]|0)|0;c[o>>2]=l;o=(l+10|0)>>>3;l=((c[f+5804>>2]|0)+10|0)>>>3;s=r;t=l>>>0>o>>>0?o:l;u=l}else{l=h+5|0;s=0;t=l;u=l}do{if((h+4|0)>>>0>t>>>0|(g|0)==0){l=f+5820|0;o=c[l>>2]|0;r=(o|0)>13;if((c[f+136>>2]|0)==4|(u|0)==(t|0)){q=j+2&65535;n=f+5816|0;m=e[n>>1]|q<>1]=m;if(r){p=f+20|0;v=c[p>>2]|0;c[p>>2]=v+1;w=f+8|0;a[(c[w>>2]|0)+v|0]=m;m=(e[n>>1]|0)>>>8&255;v=c[p>>2]|0;c[p>>2]=v+1;a[(c[w>>2]|0)+v|0]=m;m=c[l>>2]|0;b[n>>1]=q>>>(16-m|0);x=m+ -13|0}else{x=o+3|0}c[l>>2]=x;Uf(f,25600,26752);break}m=j+4&65535;q=f+5816|0;n=e[q>>1]|m<>1]=n;if(r){r=f+20|0;v=c[r>>2]|0;c[r>>2]=v+1;w=f+8|0;a[(c[w>>2]|0)+v|0]=n;v=(e[q>>1]|0)>>>8&255;p=c[r>>2]|0;c[r>>2]=p+1;a[(c[w>>2]|0)+p|0]=v;v=c[l>>2]|0;p=m>>>(16-v|0);b[q>>1]=p;y=p;z=v+ -13|0}else{y=n;z=o+3|0}c[l>>2]=z;o=c[f+2844>>2]|0;n=c[f+2856>>2]|0;v=o+65280&65535;p=y&65535|v<>1]=p;if((z|0)>11){m=f+20|0;w=c[m>>2]|0;c[m>>2]=w+1;r=f+8|0;a[(c[r>>2]|0)+w|0]=p;w=(e[q>>1]|0)>>>8&255;A=c[m>>2]|0;c[m>>2]=A+1;a[(c[r>>2]|0)+A|0]=w;w=c[l>>2]|0;A=v>>>(16-w|0);b[q>>1]=A;B=w+ -11|0;C=A}else{B=z+5|0;C=p}c[l>>2]=B;p=n&65535;A=p<>1]=A;if((B|0)>11){w=f+20|0;v=c[w>>2]|0;c[w>>2]=v+1;r=f+8|0;a[(c[r>>2]|0)+v|0]=A;v=(e[q>>1]|0)>>>8&255;m=c[w>>2]|0;c[w>>2]=m+1;a[(c[r>>2]|0)+m|0]=v;v=c[l>>2]|0;m=p>>>(16-v|0);b[q>>1]=m;D=v+ -11|0;E=m}else{D=B+5|0;E=A}c[l>>2]=D;A=s+65533&65535;m=A<>1]=m;if((D|0)>12){v=f+20|0;p=c[v>>2]|0;c[v>>2]=p+1;r=f+8|0;a[(c[r>>2]|0)+p|0]=m;p=(e[q>>1]|0)>>>8&255;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[r>>2]|0)+w|0]=p;p=c[l>>2]|0;w=A>>>(16-p|0);b[q>>1]=w;F=w;G=p+ -12|0}else{F=m;G=D+4|0}c[l>>2]=G;if((s|0)>-1){m=f+20|0;p=f+8|0;w=G;A=F;r=0;while(1){v=e[f+(d[27352+r|0]<<2)+2686>>1]|0;H=v<>1]=H;if((w|0)>13){I=c[m>>2]|0;c[m>>2]=I+1;a[(c[p>>2]|0)+I|0]=H;I=(e[q>>1]|0)>>>8&255;J=c[m>>2]|0;c[m>>2]=J+1;a[(c[p>>2]|0)+J|0]=I;I=c[l>>2]|0;J=v>>>(16-I|0);b[q>>1]=J;K=J;L=I+ -13|0}else{K=H;L=w+3|0}c[l>>2]=L;if((r|0)==(s|0)){break}else{w=L;A=K;r=r+1|0}}}r=f+148|0;Vf(f,r,o);A=f+2440|0;Vf(f,A,n);Uf(f,r,A)}else{Qf(f,g,h,j)}}while(0);Pf(f);if((j|0)==0){i=k;return}j=f+5820|0;h=c[j>>2]|0;if((h|0)<=8){g=f+5816|0;if((h|0)>0){h=b[g>>1]&255;K=f+20|0;L=c[K>>2]|0;c[K>>2]=L+1;a[(c[f+8>>2]|0)+L|0]=h;M=g}else{M=g}}else{g=f+5816|0;h=b[g>>1]&255;L=f+20|0;K=c[L>>2]|0;c[L>>2]=K+1;s=f+8|0;a[(c[s>>2]|0)+K|0]=h;h=(e[g>>1]|0)>>>8&255;K=c[L>>2]|0;c[L>>2]=K+1;a[(c[s>>2]|0)+K|0]=h;M=g}b[M>>1]=0;c[j>>2]=0;i=k;return}function Tf(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0;h=i;i=i+32|0;j=h;k=c[g>>2]|0;l=g+8|0;m=c[l>>2]|0;n=c[m>>2]|0;o=c[m+12>>2]|0;m=f+5200|0;c[m>>2]=0;p=f+5204|0;c[p>>2]=573;if((o|0)>0){q=-1;r=0;while(1){if((b[k+(r<<2)>>1]|0)==0){b[k+(r<<2)+2>>1]=0;s=q}else{t=(c[m>>2]|0)+1|0;c[m>>2]=t;c[f+(t<<2)+2908>>2]=r;a[f+r+5208|0]=0;s=r}r=r+1|0;if((r|0)==(o|0)){break}else{q=s}}q=c[m>>2]|0;if((q|0)<2){u=q;v=s;w=3}else{x=s}}else{u=0;v=-1;w=3}if((w|0)==3){w=f+5800|0;s=f+5804|0;if((n|0)==0){q=u;r=v;while(1){t=(r|0)<2;y=r+1|0;z=t?y:r;A=t?y:0;y=q+1|0;c[m>>2]=y;c[f+(y<<2)+2908>>2]=A;b[k+(A<<2)>>1]=1;a[f+A+5208|0]=0;c[w>>2]=(c[w>>2]|0)+ -1;A=c[m>>2]|0;if((A|0)<2){q=A;r=z}else{x=z;break}}}else{r=u;u=v;while(1){v=(u|0)<2;q=u+1|0;z=v?q:u;A=v?q:0;q=r+1|0;c[m>>2]=q;c[f+(q<<2)+2908>>2]=A;b[k+(A<<2)>>1]=1;a[f+A+5208|0]=0;c[w>>2]=(c[w>>2]|0)+ -1;c[s>>2]=(c[s>>2]|0)-(e[n+(A<<2)+2>>1]|0);A=c[m>>2]|0;if((A|0)<2){r=A;u=z}else{x=z;break}}}}u=g+4|0;c[u>>2]=x;r=c[m>>2]|0;if((r|0)>1){n=r;s=(r|0)/2|0;while(1){w=c[f+(s<<2)+2908>>2]|0;z=f+w+5208|0;A=s<<1;a:do{if((A|0)>(n|0)){B=s}else{q=k+(w<<2)|0;v=s;y=n;t=A;while(1){do{if((t|0)<(y|0)){C=t|1;D=c[f+(C<<2)+2908>>2]|0;E=b[k+(D<<2)>>1]|0;F=c[f+(t<<2)+2908>>2]|0;G=b[k+(F<<2)>>1]|0;if(!((E&65535)<(G&65535))){if(!(E<<16>>16==G<<16>>16)){H=t;break}if((d[f+D+5208|0]|0)>(d[f+F+5208|0]|0)){H=t;break}}H=C}else{H=t}}while(0);C=b[q>>1]|0;F=c[f+(H<<2)+2908>>2]|0;D=b[k+(F<<2)>>1]|0;if((C&65535)<(D&65535)){B=v;break a}if(C<<16>>16==D<<16>>16?(d[z]|0)<=(d[f+F+5208|0]|0):0){B=v;break a}c[f+(v<<2)+2908>>2]=F;F=H<<1;D=c[m>>2]|0;if((F|0)>(D|0)){B=H;break}else{v=H;y=D;t=F}}}}while(0);c[f+(B<<2)+2908>>2]=w;z=s+ -1|0;A=c[m>>2]|0;if((z|0)>0){n=A;s=z}else{I=A;break}}}else{I=r}r=f+2912|0;s=I;I=o;while(1){o=c[r>>2]|0;n=s+ -1|0;c[m>>2]=n;B=c[f+(s<<2)+2908>>2]|0;c[r>>2]=B;H=f+B+5208|0;b:do{if((s|0)<3){J=1}else{A=k+(B<<2)|0;z=1;t=n;y=2;while(1){do{if((y|0)<(t|0)){v=y|1;q=c[f+(v<<2)+2908>>2]|0;F=b[k+(q<<2)>>1]|0;D=c[f+(y<<2)+2908>>2]|0;C=b[k+(D<<2)>>1]|0;if(!((F&65535)<(C&65535))){if(!(F<<16>>16==C<<16>>16)){K=y;break}if((d[f+q+5208|0]|0)>(d[f+D+5208|0]|0)){K=y;break}}K=v}else{K=y}}while(0);v=b[A>>1]|0;D=c[f+(K<<2)+2908>>2]|0;q=b[k+(D<<2)>>1]|0;if((v&65535)<(q&65535)){J=z;break b}if(v<<16>>16==q<<16>>16?(d[H]|0)<=(d[f+D+5208|0]|0):0){J=z;break b}c[f+(z<<2)+2908>>2]=D;D=K<<1;q=c[m>>2]|0;if((D|0)>(q|0)){J=K;break}else{z=K;t=q;y=D}}}}while(0);c[f+(J<<2)+2908>>2]=B;H=c[r>>2]|0;n=(c[p>>2]|0)+ -1|0;c[p>>2]=n;c[f+(n<<2)+2908>>2]=o;n=(c[p>>2]|0)+ -1|0;c[p>>2]=n;c[f+(n<<2)+2908>>2]=H;n=k+(I<<2)|0;b[n>>1]=(e[k+(H<<2)>>1]|0)+(e[k+(o<<2)>>1]|0);w=a[f+o+5208|0]|0;y=a[f+H+5208|0]|0;t=f+I+5208|0;a[t]=(((w&255)<(y&255)?y:w)&255)+1;w=I&65535;b[k+(H<<2)+2>>1]=w;b[k+(o<<2)+2>>1]=w;w=I+1|0;c[r>>2]=I;H=c[m>>2]|0;c:do{if((H|0)<2){L=1}else{y=1;z=H;A=2;while(1){do{if((A|0)<(z|0)){D=A|1;q=c[f+(D<<2)+2908>>2]|0;v=b[k+(q<<2)>>1]|0;C=c[f+(A<<2)+2908>>2]|0;F=b[k+(C<<2)>>1]|0;if(!((v&65535)<(F&65535))){if(!(v<<16>>16==F<<16>>16)){M=A;break}if((d[f+q+5208|0]|0)>(d[f+C+5208|0]|0)){M=A;break}}M=D}else{M=A}}while(0);D=b[n>>1]|0;C=c[f+(M<<2)+2908>>2]|0;q=b[k+(C<<2)>>1]|0;if((D&65535)<(q&65535)){L=y;break c}if(D<<16>>16==q<<16>>16?(d[t]|0)<=(d[f+C+5208|0]|0):0){L=y;break c}c[f+(y<<2)+2908>>2]=C;C=M<<1;q=c[m>>2]|0;if((C|0)>(q|0)){L=M;break}else{y=M;z=q;A=C}}}}while(0);c[f+(L<<2)+2908>>2]=I;t=c[m>>2]|0;if((t|0)>1){s=t;I=w}else{break}}I=c[r>>2]|0;r=(c[p>>2]|0)+ -1|0;c[p>>2]=r;c[f+(r<<2)+2908>>2]=I;I=c[g>>2]|0;g=c[u>>2]|0;u=c[l>>2]|0;l=c[u>>2]|0;r=c[u+4>>2]|0;s=c[u+8>>2]|0;m=c[u+16>>2]|0;u=f+2876|0;L=u+32|0;do{b[u>>1]=0;u=u+2|0}while((u|0)<(L|0));u=c[p>>2]|0;b[I+(c[f+(u<<2)+2908>>2]<<2)+2>>1]=0;p=u+1|0;d:do{if((p|0)<573){u=f+5800|0;L=f+5804|0;if((l|0)==0){M=p;J=0;while(1){K=c[f+(M<<2)+2908>>2]|0;t=I+(K<<2)+2|0;n=e[I+(e[t>>1]<<2)+2>>1]|0;H=(n|0)<(m|0);o=H?n+1|0:m;n=(H&1^1)+J|0;b[t>>1]=o;if((K|0)<=(g|0)){t=f+(o<<1)+2876|0;b[t>>1]=(b[t>>1]|0)+1<<16>>16;if((K|0)<(s|0)){N=0}else{N=c[r+(K-s<<2)>>2]|0}t=aa(e[I+(K<<2)>>1]|0,N+o|0)|0;c[u>>2]=t+(c[u>>2]|0)}t=M+1|0;if((t|0)==573){O=n;break}else{M=t;J=n}}}else{J=p;M=0;while(1){w=c[f+(J<<2)+2908>>2]|0;n=I+(w<<2)+2|0;t=e[I+(e[n>>1]<<2)+2>>1]|0;o=(t|0)<(m|0);K=o?t+1|0:m;t=(o&1^1)+M|0;b[n>>1]=K;if((w|0)<=(g|0)){n=f+(K<<1)+2876|0;b[n>>1]=(b[n>>1]|0)+1<<16>>16;if((w|0)<(s|0)){P=0}else{P=c[r+(w-s<<2)>>2]|0}n=e[I+(w<<2)>>1]|0;o=aa(n,P+K|0)|0;c[u>>2]=o+(c[u>>2]|0);o=aa((e[l+(w<<2)+2>>1]|0)+P|0,n)|0;c[L>>2]=o+(c[L>>2]|0)}o=J+1|0;if((o|0)==573){O=t;break}else{J=o;M=t}}}if((O|0)!=0){M=f+(m<<1)+2876|0;J=O;do{L=m;while(1){t=L+ -1|0;Q=f+(t<<1)+2876|0;R=b[Q>>1]|0;if(R<<16>>16==0){L=t}else{break}}b[Q>>1]=R+ -1<<16>>16;t=f+(L<<1)+2876|0;b[t>>1]=(e[t>>1]|0)+2;S=(b[M>>1]|0)+ -1<<16>>16;b[M>>1]=S;J=J+ -2|0}while((J|0)>0);if((m|0)!=0){J=S;M=m;t=573;while(1){o=M&65535;if(J<<16>>16==0){T=t}else{n=t;w=J&65535;while(1){K=n;do{K=K+ -1|0;U=c[f+(K<<2)+2908>>2]|0}while((U|0)>(g|0));H=I+(U<<2)+2|0;B=e[H>>1]|0;if((B|0)!=(M|0)){A=aa(e[I+(U<<2)>>1]|0,M-B|0)|0;c[u>>2]=A+(c[u>>2]|0);b[H>>1]=o}H=w+ -1|0;if((H|0)==0){T=K;break}else{n=K;w=H}}}w=M+ -1|0;if((w|0)==0){break d}J=b[f+(w<<1)+2876>>1]|0;M=w;t=T}}}}}while(0);T=1;U=0;do{U=(e[f+(T+ -1<<1)+2876>>1]|0)+(U&65534)<<1;b[j+(T<<1)>>1]=U;T=T+1|0}while((T|0)!=16);if((x|0)<0){i=h;return}else{V=0}while(1){T=b[k+(V<<2)+2>>1]|0;U=T&65535;if(!(T<<16>>16==0)){T=j+(U<<1)|0;f=b[T>>1]|0;b[T>>1]=f+1<<16>>16;T=U;U=f&65535;f=0;while(1){W=f|U&1;T=T+ -1|0;if((T|0)<=0){break}else{U=U>>>1;f=W<<1}}b[k+(V<<2)>>1]=W}if((V|0)==(x|0)){break}else{V=V+1|0}}i=h;return}function Uf(f,g,h){f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0;j=i;k=f+5792|0;if((c[k>>2]|0)==0){l=c[f+5820>>2]|0;m=b[f+5816>>1]|0}else{n=f+5796|0;o=f+5784|0;p=f+5820|0;q=f+5816|0;r=f+20|0;s=f+8|0;t=0;while(1){u=b[(c[n>>2]|0)+(t<<1)>>1]|0;v=u&65535;w=t+1|0;x=d[(c[o>>2]|0)+t|0]|0;do{if(u<<16>>16==0){y=e[g+(x<<2)+2>>1]|0;z=c[p>>2]|0;A=e[g+(x<<2)>>1]|0;B=e[q>>1]|0|A<>1]=C;if((z|0)>(16-y|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=B;B=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=B;B=c[p>>2]|0;D=A>>>(16-B|0)&65535;b[q>>1]=D;A=y+ -16+B|0;c[p>>2]=A;E=D;F=A;break}else{A=z+y|0;c[p>>2]=A;E=C;F=A;break}}else{A=d[25272+x|0]|0;C=(A|256)+1|0;y=e[g+(C<<2)+2>>1]|0;z=c[p>>2]|0;D=e[g+(C<<2)>>1]|0;C=e[q>>1]|0|D<>1]=B;if((z|0)>(16-y|0)){G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=C;C=(e[q>>1]|0)>>>8&255;G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=C;C=c[p>>2]|0;G=D>>>(16-C|0)&65535;b[q>>1]=G;H=G;I=y+ -16+C|0}else{H=B;I=z+y|0}c[p>>2]=I;y=c[26872+(A<<2)>>2]|0;do{if((A+ -8|0)>>>0<20){z=x-(c[26992+(A<<2)>>2]|0)&65535;B=z<>1]=C;if((I|0)>(16-y|0)){G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=B;B=(e[q>>1]|0)>>>8&255;G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=B;B=c[p>>2]|0;G=z>>>(16-B|0)&65535;b[q>>1]=G;z=y+ -16+B|0;c[p>>2]=z;J=z;K=G;break}else{G=I+y|0;c[p>>2]=G;J=G;K=C;break}}else{J=I;K=H}}while(0);y=v+ -1|0;if(y>>>0<256){L=y}else{L=(y>>>7)+256|0}A=d[24760+L|0]|0;C=e[h+(A<<2)+2>>1]|0;G=e[h+(A<<2)>>1]|0;z=K&65535|G<>1]=B;if((J|0)>(16-C|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=z;z=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=z;z=c[p>>2]|0;D=G>>>(16-z|0)&65535;b[q>>1]=D;M=C+ -16+z|0;N=D}else{M=J+C|0;N=B}c[p>>2]=M;B=c[27112+(A<<2)>>2]|0;if((A+ -4|0)>>>0<26){C=y-(c[27232+(A<<2)>>2]|0)&65535;A=C<>1]=y;if((M|0)>(16-B|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=A;A=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=A;A=c[p>>2]|0;D=C>>>(16-A|0)&65535;b[q>>1]=D;C=B+ -16+A|0;c[p>>2]=C;E=D;F=C;break}else{C=M+B|0;c[p>>2]=C;E=y;F=C;break}}else{E=N;F=M}}}while(0);if(w>>>0<(c[k>>2]|0)>>>0){t=w}else{l=F;m=E;break}}}E=g+1026|0;F=e[E>>1]|0;t=f+5820|0;k=e[g+1024>>1]|0;g=f+5816|0;M=m&65535|k<>1]=M;if((l|0)>(16-F|0)){m=f+20|0;N=c[m>>2]|0;c[m>>2]=N+1;p=f+8|0;a[(c[p>>2]|0)+N|0]=M;M=(e[g>>1]|0)>>>8&255;N=c[m>>2]|0;c[m>>2]=N+1;a[(c[p>>2]|0)+N|0]=M;M=c[t>>2]|0;b[g>>1]=k>>>(16-M|0);O=F+ -16+M|0;c[t>>2]=O;P=b[E>>1]|0;Q=P&65535;R=f+5812|0;c[R>>2]=Q;i=j;return}else{O=l+F|0;c[t>>2]=O;P=b[E>>1]|0;Q=P&65535;R=f+5812|0;c[R>>2]=Q;i=j;return}}function Vf(d,f,g){d=d|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0;h=i;j=b[f+2>>1]|0;k=j<<16>>16==0;l=d+2754|0;m=d+5820|0;n=d+2752|0;o=d+5816|0;p=d+20|0;q=d+8|0;r=d+2758|0;s=d+2756|0;t=d+2750|0;u=d+2748|0;v=k?138:7;w=k?3:4;k=0;x=j&65535;j=-1;a:while(1){y=0;z=k;while(1){if((z|0)>(g|0)){break a}z=z+1|0;A=b[f+(z<<2)+2>>1]|0;B=A&65535;C=y+1|0;D=(x|0)==(B|0);if(!((C|0)<(v|0)&D)){break}else{y=C}}do{if((C|0)>=(w|0)){if((x|0)!=0){if((x|0)==(j|0)){E=b[o>>1]|0;F=c[m>>2]|0;G=C}else{H=e[d+(x<<2)+2686>>1]|0;I=c[m>>2]|0;J=e[d+(x<<2)+2684>>1]|0;K=e[o>>1]|0|J<>1]=L;if((I|0)>(16-H|0)){M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=c[m>>2]|0;M=J>>>(16-K|0)&65535;b[o>>1]=M;N=M;O=H+ -16+K|0}else{N=L;O=I+H|0}c[m>>2]=O;E=N;F=O;G=y}H=e[t>>1]|0;I=e[u>>1]|0;L=E&65535|I<>1]=L;if((F|0)>(16-H|0)){K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=L;K=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=c[m>>2]|0;M=I>>>(16-K|0);b[o>>1]=M;P=H+ -16+K|0;Q=M}else{P=F+H|0;Q=L}c[m>>2]=P;L=G+65533&65535;H=Q&65535|L<>1]=H;if((P|0)>14){M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=H;H=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=H;H=c[m>>2]|0;b[o>>1]=L>>>(16-H|0);c[m>>2]=H+ -14;break}else{c[m>>2]=P+2;break}}if((C|0)<11){H=e[l>>1]|0;L=c[m>>2]|0;M=e[n>>1]|0;K=e[o>>1]|0|M<>1]=K;if((L|0)>(16-H|0)){I=c[p>>2]|0;c[p>>2]=I+1;a[(c[q>>2]|0)+I|0]=K;I=(e[o>>1]|0)>>>8&255;J=c[p>>2]|0;c[p>>2]=J+1;a[(c[q>>2]|0)+J|0]=I;I=c[m>>2]|0;J=M>>>(16-I|0);b[o>>1]=J;R=H+ -16+I|0;S=J}else{R=L+H|0;S=K}c[m>>2]=R;K=y+65534&65535;H=S&65535|K<>1]=H;if((R|0)>13){L=c[p>>2]|0;c[p>>2]=L+1;a[(c[q>>2]|0)+L|0]=H;H=(e[o>>1]|0)>>>8&255;L=c[p>>2]|0;c[p>>2]=L+1;a[(c[q>>2]|0)+L|0]=H;H=c[m>>2]|0;b[o>>1]=K>>>(16-H|0);c[m>>2]=H+ -13;break}else{c[m>>2]=R+3;break}}else{H=e[r>>1]|0;K=c[m>>2]|0;L=e[s>>1]|0;J=e[o>>1]|0|L<>1]=J;if((K|0)>(16-H|0)){I=c[p>>2]|0;c[p>>2]=I+1;a[(c[q>>2]|0)+I|0]=J;I=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=I;I=c[m>>2]|0;M=L>>>(16-I|0);b[o>>1]=M;T=H+ -16+I|0;U=M}else{T=K+H|0;U=J}c[m>>2]=T;J=y+65526&65535;H=U&65535|J<>1]=H;if((T|0)>9){K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=H;H=(e[o>>1]|0)>>>8&255;K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=H;H=c[m>>2]|0;b[o>>1]=J>>>(16-H|0);c[m>>2]=H+ -9;break}else{c[m>>2]=T+7;break}}}else{H=d+(x<<2)+2686|0;J=d+(x<<2)+2684|0;K=c[m>>2]|0;M=b[o>>1]|0;I=C;while(1){L=e[H>>1]|0;V=e[J>>1]|0;W=M&65535|V<>1]=X;if((K|0)>(16-L|0)){Y=c[p>>2]|0;c[p>>2]=Y+1;a[(c[q>>2]|0)+Y|0]=W;W=(e[o>>1]|0)>>>8&255;Y=c[p>>2]|0;c[p>>2]=Y+1;a[(c[q>>2]|0)+Y|0]=W;W=c[m>>2]|0;Y=V>>>(16-W|0)&65535;b[o>>1]=Y;Z=Y;_=L+ -16+W|0}else{Z=X;_=K+L|0}c[m>>2]=_;I=I+ -1|0;if((I|0)==0){break}else{K=_;M=Z}}}}while(0);if(A<<16>>16==0){$=x;v=138;w=3;k=z;x=B;j=$;continue}$=x;v=D?6:7;w=D?3:4;k=z;x=B;j=$}i=h;return}function Wf(a,c,d){a=a|0;c=c|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;f=i;g=b[c+2>>1]|0;h=g<<16>>16==0;b[c+(d+1<<2)+2>>1]=-1;j=a+2752|0;k=a+2756|0;l=a+2748|0;m=h?138:7;n=h?3:4;h=0;o=g&65535;g=-1;a:while(1){p=0;q=h;do{if((q|0)>(d|0)){break a}q=q+1|0;r=b[c+(q<<2)+2>>1]|0;s=r&65535;p=p+1|0;t=(o|0)==(s|0)}while((p|0)<(m|0)&t);do{if((p|0)>=(n|0)){if((o|0)==0){if((p|0)<11){b[j>>1]=(b[j>>1]|0)+1<<16>>16;break}else{b[k>>1]=(b[k>>1]|0)+1<<16>>16;break}}else{if((o|0)!=(g|0)){u=a+(o<<2)+2684|0;b[u>>1]=(b[u>>1]|0)+1<<16>>16}b[l>>1]=(b[l>>1]|0)+1<<16>>16;break}}else{u=a+(o<<2)+2684|0;b[u>>1]=(e[u>>1]|0)+p}}while(0);if(r<<16>>16==0){v=o;m=138;n=3;h=q;o=s;g=v;continue}v=o;m=t?6:7;n=t?3:4;h=q;o=s;g=v}i=f;return}function Xf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;a=i;d=gg(aa(c,b)|0)|0;i=a;return d|0}function Yf(a,b){a=a|0;b=b|0;a=i;hg(b);i=a;return}function Zf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0;f=i;i=i+944|0;g=f+680|0;h=f+424|0;j=f+192|0;k=f;l=aa(d,b)|0;if((l|0)==0){i=f;return}b=l-d|0;c[k+4>>2]=d;c[k>>2]=d;m=d;n=d;o=2;while(1){p=m+d+n|0;c[k+(o<<2)>>2]=p;if(p>>>0>>0){q=n;n=p;o=o+1|0;m=q}else{break}}m=0-d|0;o=a+b|0;if((b|0)>0){b=(d|0)==0;n=d>>>0>256?256:d;l=(n|0)==(d|0);q=o;p=1;r=0;s=a;t=1;while(1){do{if((p&3|0)!=3){u=t+ -1|0;a:do{if((c[k+(u<<2)>>2]|0)>>>0<(q-s|0)>>>0){c[j>>2]=s;if((t|0)>1){v=t;w=s;x=s;y=1;while(1){z=w+m|0;A=v+ -2|0;B=w+(0-((c[k+(A<<2)>>2]|0)+d))|0;if((nb[e&7](x,B)|0)>-1?(nb[e&7](x,z)|0)>-1:0){C=y;break}D=y+1|0;E=j+(y<<2)|0;if((nb[e&7](B,z)|0)>-1){c[E>>2]=B;F=B;G=v+ -1|0}else{c[E>>2]=z;F=z;G=A}if((G|0)<=1){C=D;break}v=G;w=F;x=c[j>>2]|0;y=D}if((C|0)>=2?(y=j+(C<<2)|0,c[y>>2]=g,!b):0){if((C|0)>0){H=d;I=g}else{x=c[j>>2]|0;Kg(g|0,x|0,n|0)|0;if(l){break}else{J=d;K=n}while(1){J=J-K|0;K=J>>>0>256?256:J;Kg(g|0,x|0,K|0)|0;if((J|0)==(K|0)){break a}}}while(1){x=H>>>0>256?256:H;w=c[j>>2]|0;Kg(I|0,w|0,x|0)|0;v=w;w=0;while(1){D=w+1|0;A=c[j+(D<<2)>>2]|0;Kg(v|0,A|0,x|0)|0;c[j+(w<<2)>>2]=v+x;if((D|0)==(C|0)){break}else{v=A;w=D}}if((H|0)==(x|0)){break a}H=H-x|0;I=c[y>>2]|0}}}}else{_f(s,d,e,p,r,t,0,k)}}while(0);if((t|0)==1){L=p<<1;M=p>>>31|r<<1;N=0;break}else{y=u>>>0>31;w=y?0:p;v=y?t+ -33|0:u;L=w<>>(32-v|0)|(y?p:r)<>2]=s;b:do{if((t|0)>1){v=t;y=s;w=s;D=1;while(1){A=y+m|0;z=v+ -2|0;E=y+(0-((c[k+(z<<2)>>2]|0)+d))|0;if((nb[e&7](w,E)|0)>-1?(nb[e&7](w,A)|0)>-1:0){O=D;break}B=D+1|0;P=j+(D<<2)|0;if((nb[e&7](E,A)|0)>-1){c[P>>2]=E;Q=E;R=v+ -1|0}else{c[P>>2]=A;Q=A;R=z}if((R|0)<=1){O=B;break}v=R;y=Q;w=c[j>>2]|0;D=B}if((O|0)>=2?(D=j+(O<<2)|0,c[D>>2]=h,!b):0){if((O|0)>0){S=d;T=h}else{w=c[j>>2]|0;Kg(h|0,w|0,n|0)|0;if(l){break}else{U=d;V=n}while(1){U=U-V|0;V=U>>>0>256?256:U;Kg(h|0,w|0,V|0)|0;if((U|0)==(V|0)){break b}}}while(1){w=S>>>0>256?256:S;y=c[j>>2]|0;Kg(T|0,y|0,w|0)|0;v=y;y=0;while(1){B=y+1|0;z=c[j+(B<<2)>>2]|0;Kg(v|0,z|0,w|0)|0;c[j+(y<<2)>>2]=v+w;if((B|0)==(O|0)){break}else{v=z;y=B}}if((S|0)==(w|0)){break b}S=S-w|0;T=c[D>>2]|0}}}}while(0);L=p>>>2|r<<30;M=r>>>2;N=t+2|0}}while(0);u=L|1;D=s+d|0;if(D>>>0>>0){p=u;r=M;s=D;t=N}else{W=M;X=u;Y=D;Z=N;break}}}else{W=0;X=1;Y=a;Z=1}_f(Y,d,e,X,W,Z,0,k);a=X;X=W;W=Y;Y=Z;while(1){if((Y|0)==1){if((a|0)==1){if((X|0)==0){break}else{_=52}}}else{_=52}if((_|0)==52?(_=0,(Y|0)>=2):0){Z=a>>>30;N=Y+ -2|0;M=(a<<1&2147483646|Z<<31)^3;t=(Z|X<<2)>>>1;_f(W+(0-((c[k+(N<<2)>>2]|0)+d))|0,d,e,M,t,Y+ -1|0,1,k);s=t<<1|Z&1;Z=M<<1|1;M=W+m|0;_f(M,d,e,Z,s,N,1,k);a=Z;X=s;W=M;Y=N;continue}N=a+ -1|0;if((N|0)!=0){if((N&1|0)==0){M=N;N=0;do{N=N+1|0;M=M>>>1}while((M&1|0)==0);if((N|0)!=0){$=N}else{_=57}}else{_=57}if((_|0)==57){_=0;if((X|0)!=0){if((X&1|0)==0){M=X;s=0;while(1){Z=s+1|0;t=M>>>1;if((t&1|0)==0){M=t;s=Z}else{ba=Z;break}}}else{ba=0}}else{ba=32}$=(ba|0)==0?0:ba+32|0}if($>>>0>31){ca=$;_=62}else{da=$;ea=a;fa=X;ga=$}}else{ca=32;_=62}if((_|0)==62){_=0;da=ca+ -32|0;ea=X;fa=0;ga=ca}a=fa<<32-da|ea>>>da;X=fa>>>da;W=W+m|0;Y=ga+Y|0}i=f;return}function _f(a,b,d,e,f,g,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0;k=i;i=i+752|0;l=k+232|0;m=k+488|0;n=k;c[n>>2]=a;o=0-b|0;a:do{if((e|0)==1&(f|0)==0){p=a;q=g;r=h;s=1;t=18}else{u=g;v=a;w=h;x=e;y=f;z=a;A=1;while(1){B=v+(0-(c[j+(u<<2)>>2]|0))|0;if((nb[d&7](B,z)|0)<1){p=v;q=u;r=w;s=A;t=18;break a}if((w|0)==0&(u|0)>1){C=c[j+(u+ -2<<2)>>2]|0;if((nb[d&7](v+o|0,B)|0)>-1){D=v;E=u;F=A;break a}if((nb[d&7](v+(0-(C+b))|0,B)|0)>-1){D=v;E=u;F=A;break a}}C=A+1|0;c[n+(A<<2)>>2]=B;G=x+ -1|0;if((G|0)!=0){if((G&1|0)==0){H=G;G=0;do{G=G+1|0;H=H>>>1}while((H&1|0)==0);if((G|0)!=0){I=G}else{t=10}}else{t=10}if((t|0)==10){t=0;if((y|0)!=0){if((y&1|0)==0){H=y;J=0;while(1){K=J+1|0;L=H>>>1;if((L&1|0)==0){H=L;J=K}else{M=K;break}}}else{M=0}}else{M=32}I=(M|0)==0?0:M+32|0}if(I>>>0>31){N=I;t=15}else{O=I;P=x;Q=y;R=I}}else{N=32;t=15}if((t|0)==15){t=0;O=N+ -32|0;P=y;Q=0;R=N}J=Q<<32-O|P>>>O;H=Q>>>O;G=R+u|0;if((J|0)==1&(H|0)==0){D=B;E=G;F=C;break a}u=G;v=B;w=0;x=J;y=H;z=c[n>>2]|0;A=C}}}while(0);if((t|0)==18){if((r|0)==0){D=p;E=q;F=s}else{i=k;return}}b:do{if((F|0)>=2?(s=n+(F<<2)|0,c[s>>2]=l,(b|0)!=0):0){if((F|0)>0){S=b;T=l}else{q=b>>>0>256?256:b;p=c[n>>2]|0;Kg(l|0,p|0,q|0)|0;if((q|0)==(b|0)){break}else{U=b;V=q}while(1){U=U-V|0;V=U>>>0>256?256:U;Kg(l|0,p|0,V|0)|0;if((U|0)==(V|0)){break b}}}while(1){p=S>>>0>256?256:S;q=c[n>>2]|0;Kg(T|0,q|0,p|0)|0;r=q;q=0;while(1){t=q+1|0;R=c[n+(t<<2)>>2]|0;Kg(r|0,R|0,p|0)|0;c[n+(q<<2)>>2]=r+p;if((t|0)==(F|0)){break}else{r=R;q=t}}if((S|0)==(p|0)){break b}S=S-p|0;T=c[s>>2]|0}}}while(0);c[l>>2]=D;c:do{if((E|0)>1){T=E;S=D;F=D;n=1;while(1){V=S+o|0;U=T+ -2|0;s=S+(0-((c[j+(U<<2)>>2]|0)+b))|0;if((nb[d&7](F,s)|0)>-1?(nb[d&7](F,V)|0)>-1:0){W=n;break}q=n+1|0;r=l+(n<<2)|0;if((nb[d&7](s,V)|0)>-1){c[r>>2]=s;X=s;Y=T+ -1|0}else{c[r>>2]=V;X=V;Y=U}if((Y|0)<=1){W=q;break}T=Y;S=X;F=c[l>>2]|0;n=q}if((W|0)>=2?(n=l+(W<<2)|0,c[n>>2]=m,(b|0)!=0):0){if((W|0)>0){Z=b;_=m}else{F=b>>>0>256?256:b;S=c[l>>2]|0;Kg(m|0,S|0,F|0)|0;if((F|0)==(b|0)){$=m;break}else{aa=b;ba=F}while(1){F=aa-ba|0;T=F>>>0>256?256:F;Kg(m|0,S|0,T|0)|0;if((F|0)==(T|0)){$=m;break c}else{aa=F;ba=T}}}while(1){S=Z>>>0>256?256:Z;T=c[l>>2]|0;Kg(_|0,T|0,S|0)|0;F=T;T=0;while(1){q=T+1|0;U=c[l+(q<<2)>>2]|0;Kg(F|0,U|0,S|0)|0;c[l+(T<<2)>>2]=F+S;if((q|0)==(W|0)){break}else{F=U;T=q}}if((Z|0)==(S|0)){$=m;break c}Z=Z-S|0;_=c[n>>2]|0}}else{$=m}}else{$=m}}while(0);i=k;return}function $f(b,c){b=b|0;c=c|0;var d=0,e=0;d=i;e=ag(b,c)|0;i=d;return((a[e]|0)==(c&255)<<24>>24?e:0)|0}function ag(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;f=d&255;if((f|0)==0){g=b+(Dg(b|0)|0)|0;i=e;return g|0}a:do{if((b&3|0)!=0){h=d&255;j=b;while(1){k=a[j]|0;if(k<<24>>24==0){g=j;l=13;break}m=j+1|0;if(k<<24>>24==h<<24>>24){g=j;l=13;break}if((m&3|0)==0){n=m;break a}else{j=m}}if((l|0)==13){i=e;return g|0}}else{n=b}}while(0);b=aa(f,16843009)|0;f=c[n>>2]|0;b:do{if(((f&-2139062144^-2139062144)&f+ -16843009|0)==0){l=f;j=n;while(1){h=l^b;m=j+4|0;if(((h&-2139062144^-2139062144)&h+ -16843009|0)!=0){o=j;break b}h=c[m>>2]|0;if(((h&-2139062144^-2139062144)&h+ -16843009|0)==0){l=h;j=m}else{o=m;break}}}else{o=n}}while(0);n=d&255;d=o;while(1){o=a[d]|0;if(o<<24>>24==0|o<<24>>24==n<<24>>24){g=d;break}else{d=d+1|0}}i=e;return g|0}function bg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+32|0;f=e;g=a[d]|0;if(!(g<<24>>24==0)?(a[d+1|0]|0)!=0:0){c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[f+24>>2]=0;c[f+28>>2]=0;h=d;d=g;do{j=d&255;k=f+(j>>>5<<2)|0;c[k>>2]=c[k>>2]|1<<(j&31);h=h+1|0;d=a[h]|0}while(!(d<<24>>24==0));d=a[b]|0;a:do{if(d<<24>>24==0){l=b}else{h=b;j=d;while(1){k=j&255;m=h+1|0;if((c[f+(k>>>5<<2)>>2]&1<<(k&31)|0)!=0){l=h;break a}k=a[m]|0;if(k<<24>>24==0){l=m;break}else{h=m;j=k}}}}while(0);n=l-b|0;i=e;return n|0}n=(ag(b,g<<24>>24)|0)-b|0;i=e;return n|0}function cg(a){a=a|0;var b=0,c=0,d=0,e=0;b=i;c=(Dg(a|0)|0)+1|0;d=gg(c)|0;if((d|0)==0){e=0;i=b;return e|0}Kg(d|0,a|0,c|0)|0;e=d;i=b;return e|0}function dg(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;f=b+(Dg(b|0)|0)|0;a:do{if((d|0)==0){g=f}else{h=d;j=c;k=f;while(1){l=a[j]|0;if(l<<24>>24==0){g=k;break a}m=h+ -1|0;n=k+1|0;a[k]=l;if((m|0)==0){g=n;break}else{h=m;j=j+1|0;k=n}}}}while(0);a[g]=0;i=e;return b|0}function eg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e;c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[f+24>>2]=0;c[f+28>>2]=0;g=a[d]|0;if(g<<24>>24==0){h=0;i=e;return h|0}if((a[d+1|0]|0)==0){j=b;while(1){if((a[j]|0)==g<<24>>24){j=j+1|0}else{break}}h=j-b|0;i=e;return h|0}else{k=d;l=g}do{g=l&255;d=f+(g>>>5<<2)|0;c[d>>2]=c[d>>2]|1<<(g&31);k=k+1|0;l=a[k]|0}while(!(l<<24>>24==0));l=a[b]|0;a:do{if(l<<24>>24==0){m=b}else{k=b;g=l;while(1){d=g&255;j=k+1|0;if((c[f+(d>>>5<<2)>>2]&1<<(d&31)|0)==0){m=k;break a}d=a[j]|0;if(d<<24>>24==0){m=j;break}else{k=j;g=d}}}}while(0);h=m-b|0;i=e;return h|0}function fg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;e=i;if((b|0)==0){f=c[6912]|0;if((f|0)==0){g=0;i=e;return g|0}else{h=f}}else{h=b}b=eg(h,d)|0;f=h+b|0;if((a[f]|0)==0){c[6912]=0;g=0;i=e;return g|0}j=(bg(f,d)|0)+b|0;b=h+j|0;c[6912]=b;if((a[b]|0)==0){c[6912]=0;g=f;i=e;return g|0}else{c[6912]=h+(j+1);a[b]=0;g=f;i=e;return g|0}return 0} + + + +function gg(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ja=0,Ka=0,La=0,Ma=0;b=i;do{if(a>>>0<245){if(a>>>0<11){d=16}else{d=a+11&-8}e=d>>>3;f=c[6914]|0;g=f>>>e;if((g&3|0)!=0){h=(g&1^1)+e|0;j=h<<1;k=27696+(j<<2)|0;l=27696+(j+2<<2)|0;j=c[l>>2]|0;m=j+8|0;n=c[m>>2]|0;do{if((k|0)!=(n|0)){if(n>>>0<(c[27672>>2]|0)>>>0){_a()}o=n+12|0;if((c[o>>2]|0)==(j|0)){c[o>>2]=k;c[l>>2]=n;break}else{_a()}}else{c[6914]=f&~(1<>2]=n|3;l=j+(n|4)|0;c[l>>2]=c[l>>2]|1;p=m;i=b;return p|0}if(d>>>0>(c[27664>>2]|0)>>>0){if((g|0)!=0){l=2<>>12&16;k=l>>>n;l=k>>>5&8;o=k>>>l;k=o>>>2&4;q=o>>>k;o=q>>>1&2;r=q>>>o;q=r>>>1&1;s=(l|n|k|o|q)+(r>>>q)|0;q=s<<1;r=27696+(q<<2)|0;o=27696+(q+2<<2)|0;q=c[o>>2]|0;k=q+8|0;n=c[k>>2]|0;do{if((r|0)!=(n|0)){if(n>>>0<(c[27672>>2]|0)>>>0){_a()}l=n+12|0;if((c[l>>2]|0)==(q|0)){c[l>>2]=r;c[o>>2]=n;break}else{_a()}}else{c[6914]=f&~(1<>2]=d|3;o=q+d|0;c[q+(d|4)>>2]=n|1;c[q+f>>2]=n;f=c[27664>>2]|0;if((f|0)!=0){r=c[27676>>2]|0;e=f>>>3;f=e<<1;g=27696+(f<<2)|0;m=c[6914]|0;j=1<>2]|0;if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{t=e;u=h}}else{c[6914]=m|j;t=27696+(f+2<<2)|0;u=g}c[t>>2]=r;c[u+12>>2]=r;c[r+8>>2]=u;c[r+12>>2]=g}c[27664>>2]=n;c[27676>>2]=o;p=k;i=b;return p|0}o=c[27660>>2]|0;if((o|0)!=0){n=(o&0-o)+ -1|0;o=n>>>12&16;g=n>>>o;n=g>>>5&8;r=g>>>n;g=r>>>2&4;f=r>>>g;r=f>>>1&2;j=f>>>r;f=j>>>1&1;m=c[27960+((n|o|g|r|f)+(j>>>f)<<2)>>2]|0;f=(c[m+4>>2]&-8)-d|0;j=m;r=m;while(1){m=c[j+16>>2]|0;if((m|0)==0){g=c[j+20>>2]|0;if((g|0)==0){break}else{v=g}}else{v=m}m=(c[v+4>>2]&-8)-d|0;g=m>>>0>>0;f=g?m:f;j=v;r=g?v:r}j=c[27672>>2]|0;if(r>>>0>>0){_a()}k=r+d|0;if(!(r>>>0>>0)){_a()}q=c[r+24>>2]|0;s=c[r+12>>2]|0;do{if((s|0)==(r|0)){g=r+20|0;m=c[g>>2]|0;if((m|0)==0){o=r+16|0;n=c[o>>2]|0;if((n|0)==0){w=0;break}else{x=n;y=o}}else{x=m;y=g}while(1){g=x+20|0;m=c[g>>2]|0;if((m|0)!=0){x=m;y=g;continue}g=x+16|0;m=c[g>>2]|0;if((m|0)==0){break}else{x=m;y=g}}if(y>>>0>>0){_a()}else{c[y>>2]=0;w=x;break}}else{g=c[r+8>>2]|0;if(g>>>0>>0){_a()}m=g+12|0;if((c[m>>2]|0)!=(r|0)){_a()}o=s+8|0;if((c[o>>2]|0)==(r|0)){c[m>>2]=s;c[o>>2]=g;w=s;break}else{_a()}}}while(0);do{if((q|0)!=0){s=c[r+28>>2]|0;j=27960+(s<<2)|0;if((r|0)==(c[j>>2]|0)){c[j>>2]=w;if((w|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}s=q+16|0;if((c[s>>2]|0)==(r|0)){c[s>>2]=w}else{c[q+20>>2]=w}if((w|0)==0){break}}if(w>>>0<(c[27672>>2]|0)>>>0){_a()}c[w+24>>2]=q;s=c[r+16>>2]|0;do{if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+16>>2]=s;c[s+24>>2]=w;break}}}while(0);s=c[r+20>>2]|0;if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+20>>2]=s;c[s+24>>2]=w;break}}}}while(0);if(f>>>0<16){q=f+d|0;c[r+4>>2]=q|3;s=r+(q+4)|0;c[s>>2]=c[s>>2]|1}else{c[r+4>>2]=d|3;c[r+(d|4)>>2]=f|1;c[r+(f+d)>>2]=f;s=c[27664>>2]|0;if((s|0)!=0){q=c[27676>>2]|0;j=s>>>3;s=j<<1;g=27696+(s<<2)|0;o=c[6914]|0;m=1<>2]|0;if(n>>>0<(c[27672>>2]|0)>>>0){_a()}else{z=j;A=n}}else{c[6914]=o|m;z=27696+(s+2<<2)|0;A=g}c[z>>2]=q;c[A+12>>2]=q;c[q+8>>2]=A;c[q+12>>2]=g}c[27664>>2]=f;c[27676>>2]=k}p=r+8|0;i=b;return p|0}else{B=d}}else{B=d}}else{if(!(a>>>0>4294967231)){g=a+11|0;q=g&-8;s=c[27660>>2]|0;if((s|0)!=0){m=0-q|0;o=g>>>8;if((o|0)!=0){if(q>>>0>16777215){C=31}else{g=(o+1048320|0)>>>16&8;n=o<>>16&4;j=n<>>16&2;h=14-(o|g|n)+(j<>>15)|0;C=q>>>(h+7|0)&1|h<<1}}else{C=0}h=c[27960+(C<<2)>>2]|0;a:do{if((h|0)==0){D=m;E=0;F=0}else{if((C|0)==31){G=0}else{G=25-(C>>>1)|0}n=m;j=0;g=q<>2]&-8;H=l-q|0;if(H>>>0>>0){if((l|0)==(q|0)){D=H;E=o;F=o;break a}else{I=H;J=o}}else{I=n;J=e}H=c[o+20>>2]|0;l=c[o+(g>>>31<<2)+16>>2]|0;K=(H|0)==0|(H|0)==(l|0)?j:H;if((l|0)==0){D=I;E=K;F=J;break}else{n=I;j=K;g=g<<1;o=l;e=J}}}}while(0);if((E|0)==0&(F|0)==0){h=2<>>12&16;r=h>>>m;h=r>>>5&8;k=r>>>h;r=k>>>2&4;f=k>>>r;k=f>>>1&2;e=f>>>k;f=e>>>1&1;L=c[27960+((h|m|r|k|f)+(e>>>f)<<2)>>2]|0}else{L=E}if((L|0)==0){M=D;N=F}else{f=D;e=L;k=F;while(1){r=(c[e+4>>2]&-8)-q|0;m=r>>>0>>0;h=m?r:f;r=m?e:k;m=c[e+16>>2]|0;if((m|0)!=0){f=h;e=m;k=r;continue}m=c[e+20>>2]|0;if((m|0)==0){M=h;N=r;break}else{f=h;e=m;k=r}}}if((N|0)!=0?M>>>0<((c[27664>>2]|0)-q|0)>>>0:0){k=c[27672>>2]|0;if(N>>>0>>0){_a()}e=N+q|0;if(!(N>>>0>>0)){_a()}f=c[N+24>>2]|0;s=c[N+12>>2]|0;do{if((s|0)==(N|0)){r=N+20|0;m=c[r>>2]|0;if((m|0)==0){h=N+16|0;o=c[h>>2]|0;if((o|0)==0){O=0;break}else{P=o;Q=h}}else{P=m;Q=r}while(1){r=P+20|0;m=c[r>>2]|0;if((m|0)!=0){P=m;Q=r;continue}r=P+16|0;m=c[r>>2]|0;if((m|0)==0){break}else{P=m;Q=r}}if(Q>>>0>>0){_a()}else{c[Q>>2]=0;O=P;break}}else{r=c[N+8>>2]|0;if(r>>>0>>0){_a()}m=r+12|0;if((c[m>>2]|0)!=(N|0)){_a()}h=s+8|0;if((c[h>>2]|0)==(N|0)){c[m>>2]=s;c[h>>2]=r;O=s;break}else{_a()}}}while(0);do{if((f|0)!=0){s=c[N+28>>2]|0;k=27960+(s<<2)|0;if((N|0)==(c[k>>2]|0)){c[k>>2]=O;if((O|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}s=f+16|0;if((c[s>>2]|0)==(N|0)){c[s>>2]=O}else{c[f+20>>2]=O}if((O|0)==0){break}}if(O>>>0<(c[27672>>2]|0)>>>0){_a()}c[O+24>>2]=f;s=c[N+16>>2]|0;do{if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[O+16>>2]=s;c[s+24>>2]=O;break}}}while(0);s=c[N+20>>2]|0;if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[O+20>>2]=s;c[s+24>>2]=O;break}}}}while(0);b:do{if(!(M>>>0<16)){c[N+4>>2]=q|3;c[N+(q|4)>>2]=M|1;c[N+(M+q)>>2]=M;f=M>>>3;if(M>>>0<256){s=f<<1;k=27696+(s<<2)|0;r=c[6914]|0;h=1<>2]|0;if(m>>>0<(c[27672>>2]|0)>>>0){_a()}else{R=f;S=m}}else{c[6914]=r|h;R=27696+(s+2<<2)|0;S=k}c[R>>2]=e;c[S+12>>2]=e;c[N+(q+8)>>2]=S;c[N+(q+12)>>2]=k;break}k=M>>>8;if((k|0)!=0){if(M>>>0>16777215){T=31}else{s=(k+1048320|0)>>>16&8;h=k<>>16&4;r=h<>>16&2;m=14-(k|s|h)+(r<>>15)|0;T=M>>>(m+7|0)&1|m<<1}}else{T=0}m=27960+(T<<2)|0;c[N+(q+28)>>2]=T;c[N+(q+20)>>2]=0;c[N+(q+16)>>2]=0;h=c[27660>>2]|0;r=1<>2]=h|r;c[m>>2]=e;c[N+(q+24)>>2]=m;c[N+(q+12)>>2]=e;c[N+(q+8)>>2]=e;break}r=c[m>>2]|0;if((T|0)==31){U=0}else{U=25-(T>>>1)|0}c:do{if((c[r+4>>2]&-8|0)!=(M|0)){m=M<>>31<<2)+16|0;s=c[V>>2]|0;if((s|0)==0){break}if((c[s+4>>2]&-8|0)==(M|0)){W=s;break c}else{m=m<<1;h=s}}if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[V>>2]=e;c[N+(q+24)>>2]=h;c[N+(q+12)>>2]=e;c[N+(q+8)>>2]=e;break b}}else{W=r}}while(0);r=W+8|0;m=c[r>>2]|0;s=c[27672>>2]|0;if(W>>>0>>0){_a()}if(m>>>0>>0){_a()}else{c[m+12>>2]=e;c[r>>2]=e;c[N+(q+8)>>2]=m;c[N+(q+12)>>2]=W;c[N+(q+24)>>2]=0;break}}else{m=M+q|0;c[N+4>>2]=m|3;r=N+(m+4)|0;c[r>>2]=c[r>>2]|1}}while(0);p=N+8|0;i=b;return p|0}else{B=q}}else{B=q}}else{B=-1}}}while(0);N=c[27664>>2]|0;if(!(B>>>0>N>>>0)){M=N-B|0;W=c[27676>>2]|0;if(M>>>0>15){c[27676>>2]=W+B;c[27664>>2]=M;c[W+(B+4)>>2]=M|1;c[W+N>>2]=M;c[W+4>>2]=B|3}else{c[27664>>2]=0;c[27676>>2]=0;c[W+4>>2]=N|3;M=W+(N+4)|0;c[M>>2]=c[M>>2]|1}p=W+8|0;i=b;return p|0}W=c[27668>>2]|0;if(B>>>0>>0){M=W-B|0;c[27668>>2]=M;W=c[27680>>2]|0;c[27680>>2]=W+B;c[W+(B+4)>>2]=M|1;c[W+4>>2]=B|3;p=W+8|0;i=b;return p|0}do{if((c[7032]|0)==0){W=Ia(30)|0;if((W+ -1&W|0)==0){c[28136>>2]=W;c[28132>>2]=W;c[28140>>2]=-1;c[28144>>2]=-1;c[28148>>2]=0;c[28100>>2]=0;c[7032]=(bb(0)|0)&-16^1431655768;break}else{_a()}}}while(0);W=B+48|0;M=c[28136>>2]|0;N=B+47|0;V=M+N|0;U=0-M|0;M=V&U;if(!(M>>>0>B>>>0)){p=0;i=b;return p|0}T=c[28096>>2]|0;if((T|0)!=0?(S=c[28088>>2]|0,R=S+M|0,R>>>0<=S>>>0|R>>>0>T>>>0):0){p=0;i=b;return p|0}d:do{if((c[28100>>2]&4|0)==0){T=c[27680>>2]|0;e:do{if((T|0)!=0){R=28104|0;while(1){S=c[R>>2]|0;if(!(S>>>0>T>>>0)?(X=R+4|0,(S+(c[X>>2]|0)|0)>>>0>T>>>0):0){break}S=c[R+8>>2]|0;if((S|0)==0){Y=182;break e}else{R=S}}if((R|0)!=0){S=V-(c[27668>>2]|0)&U;if(S>>>0<2147483647){O=Ca(S|0)|0;P=(O|0)==((c[R>>2]|0)+(c[X>>2]|0)|0);Z=O;_=S;$=P?O:-1;aa=P?S:0;Y=191}else{ba=0}}else{Y=182}}else{Y=182}}while(0);do{if((Y|0)==182){T=Ca(0)|0;if((T|0)!=(-1|0)){q=T;S=c[28132>>2]|0;P=S+ -1|0;if((P&q|0)==0){ca=M}else{ca=M-q+(P+q&0-S)|0}S=c[28088>>2]|0;q=S+ca|0;if(ca>>>0>B>>>0&ca>>>0<2147483647){P=c[28096>>2]|0;if((P|0)!=0?q>>>0<=S>>>0|q>>>0>P>>>0:0){ba=0;break}P=Ca(ca|0)|0;q=(P|0)==(T|0);Z=P;_=ca;$=q?T:-1;aa=q?ca:0;Y=191}else{ba=0}}else{ba=0}}}while(0);f:do{if((Y|0)==191){q=0-_|0;if(($|0)!=(-1|0)){da=$;ea=aa;Y=202;break d}do{if((Z|0)!=(-1|0)&_>>>0<2147483647&_>>>0>>0?(T=c[28136>>2]|0,P=N-_+T&0-T,P>>>0<2147483647):0){if((Ca(P|0)|0)==(-1|0)){Ca(q|0)|0;ba=aa;break f}else{fa=P+_|0;break}}else{fa=_}}while(0);if((Z|0)==(-1|0)){ba=aa}else{da=Z;ea=fa;Y=202;break d}}}while(0);c[28100>>2]=c[28100>>2]|4;ga=ba;Y=199}else{ga=0;Y=199}}while(0);if((((Y|0)==199?M>>>0<2147483647:0)?(ba=Ca(M|0)|0,M=Ca(0)|0,(M|0)!=(-1|0)&(ba|0)!=(-1|0)&ba>>>0>>0):0)?(fa=M-ba|0,M=fa>>>0>(B+40|0)>>>0,M):0){da=ba;ea=M?fa:ga;Y=202}if((Y|0)==202){ga=(c[28088>>2]|0)+ea|0;c[28088>>2]=ga;if(ga>>>0>(c[28092>>2]|0)>>>0){c[28092>>2]=ga}ga=c[27680>>2]|0;g:do{if((ga|0)!=0){fa=28104|0;while(1){ha=c[fa>>2]|0;ia=fa+4|0;ja=c[ia>>2]|0;if((da|0)==(ha+ja|0)){Y=214;break}M=c[fa+8>>2]|0;if((M|0)==0){break}else{fa=M}}if(((Y|0)==214?(c[fa+12>>2]&8|0)==0:0)?ga>>>0>=ha>>>0&ga>>>0>>0:0){c[ia>>2]=ja+ea;M=(c[27668>>2]|0)+ea|0;ba=ga+8|0;if((ba&7|0)==0){ka=0}else{ka=0-ba&7}ba=M-ka|0;c[27680>>2]=ga+ka;c[27668>>2]=ba;c[ga+(ka+4)>>2]=ba|1;c[ga+(M+4)>>2]=40;c[27684>>2]=c[28144>>2];break}if(da>>>0<(c[27672>>2]|0)>>>0){c[27672>>2]=da}M=da+ea|0;ba=28104|0;while(1){if((c[ba>>2]|0)==(M|0)){Y=224;break}Z=c[ba+8>>2]|0;if((Z|0)==0){break}else{ba=Z}}if((Y|0)==224?(c[ba+12>>2]&8|0)==0:0){c[ba>>2]=da;M=ba+4|0;c[M>>2]=(c[M>>2]|0)+ea;M=da+8|0;if((M&7|0)==0){la=0}else{la=0-M&7}M=da+(ea+8)|0;if((M&7|0)==0){ma=0}else{ma=0-M&7}M=da+(ma+ea)|0;fa=la+B|0;Z=da+fa|0;aa=M-(da+la)-B|0;c[da+(la+4)>>2]=B|3;h:do{if((M|0)!=(c[27680>>2]|0)){if((M|0)==(c[27676>>2]|0)){_=(c[27664>>2]|0)+aa|0;c[27664>>2]=_;c[27676>>2]=Z;c[da+(fa+4)>>2]=_|1;c[da+(_+fa)>>2]=_;break}_=ea+4|0;N=c[da+(_+ma)>>2]|0;if((N&3|0)==1){W=N&-8;$=N>>>3;do{if(!(N>>>0<256)){ca=c[da+((ma|24)+ea)>>2]|0;X=c[da+(ea+12+ma)>>2]|0;do{if((X|0)==(M|0)){U=ma|16;V=da+(_+U)|0;q=c[V>>2]|0;if((q|0)==0){R=da+(U+ea)|0;U=c[R>>2]|0;if((U|0)==0){na=0;break}else{oa=U;pa=R}}else{oa=q;pa=V}while(1){V=oa+20|0;q=c[V>>2]|0;if((q|0)!=0){oa=q;pa=V;continue}V=oa+16|0;q=c[V>>2]|0;if((q|0)==0){break}else{oa=q;pa=V}}if(pa>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[pa>>2]=0;na=oa;break}}else{V=c[da+((ma|8)+ea)>>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}q=V+12|0;if((c[q>>2]|0)!=(M|0)){_a()}R=X+8|0;if((c[R>>2]|0)==(M|0)){c[q>>2]=X;c[R>>2]=V;na=X;break}else{_a()}}}while(0);if((ca|0)!=0){X=c[da+(ea+28+ma)>>2]|0;h=27960+(X<<2)|0;if((M|0)==(c[h>>2]|0)){c[h>>2]=na;if((na|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}X=ca+16|0;if((c[X>>2]|0)==(M|0)){c[X>>2]=na}else{c[ca+20>>2]=na}if((na|0)==0){break}}if(na>>>0<(c[27672>>2]|0)>>>0){_a()}c[na+24>>2]=ca;X=ma|16;h=c[da+(X+ea)>>2]|0;do{if((h|0)!=0){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[na+16>>2]=h;c[h+24>>2]=na;break}}}while(0);h=c[da+(_+X)>>2]|0;if((h|0)!=0){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[na+20>>2]=h;c[h+24>>2]=na;break}}}}else{h=c[da+((ma|8)+ea)>>2]|0;ca=c[da+(ea+12+ma)>>2]|0;V=27696+($<<1<<2)|0;if((h|0)!=(V|0)){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}if((c[h+12>>2]|0)!=(M|0)){_a()}}if((ca|0)==(h|0)){c[6914]=c[6914]&~(1<<$);break}if((ca|0)!=(V|0)){if(ca>>>0<(c[27672>>2]|0)>>>0){_a()}V=ca+8|0;if((c[V>>2]|0)==(M|0)){qa=V}else{_a()}}else{qa=ca+8|0}c[h+12>>2]=ca;c[qa>>2]=h}}while(0);ra=da+((W|ma)+ea)|0;sa=W+aa|0}else{ra=M;sa=aa}$=ra+4|0;c[$>>2]=c[$>>2]&-2;c[da+(fa+4)>>2]=sa|1;c[da+(sa+fa)>>2]=sa;$=sa>>>3;if(sa>>>0<256){_=$<<1;N=27696+(_<<2)|0;h=c[6914]|0;ca=1<<$;if((h&ca|0)!=0){$=27696+(_+2<<2)|0;V=c[$>>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{ta=$;ua=V}}else{c[6914]=h|ca;ta=27696+(_+2<<2)|0;ua=N}c[ta>>2]=Z;c[ua+12>>2]=Z;c[da+(fa+8)>>2]=ua;c[da+(fa+12)>>2]=N;break}N=sa>>>8;if((N|0)!=0){if(sa>>>0>16777215){va=31}else{_=(N+1048320|0)>>>16&8;ca=N<<_;N=(ca+520192|0)>>>16&4;h=ca<>>16&2;V=14-(N|_|ca)+(h<>>15)|0;va=sa>>>(V+7|0)&1|V<<1}}else{va=0}V=27960+(va<<2)|0;c[da+(fa+28)>>2]=va;c[da+(fa+20)>>2]=0;c[da+(fa+16)>>2]=0;ca=c[27660>>2]|0;h=1<>2]=ca|h;c[V>>2]=Z;c[da+(fa+24)>>2]=V;c[da+(fa+12)>>2]=Z;c[da+(fa+8)>>2]=Z;break}h=c[V>>2]|0;if((va|0)==31){wa=0}else{wa=25-(va>>>1)|0}i:do{if((c[h+4>>2]&-8|0)!=(sa|0)){V=sa<>>31<<2)+16|0;_=c[xa>>2]|0;if((_|0)==0){break}if((c[_+4>>2]&-8|0)==(sa|0)){ya=_;break i}else{V=V<<1;ca=_}}if(xa>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[xa>>2]=Z;c[da+(fa+24)>>2]=ca;c[da+(fa+12)>>2]=Z;c[da+(fa+8)>>2]=Z;break h}}else{ya=h}}while(0);h=ya+8|0;W=c[h>>2]|0;V=c[27672>>2]|0;if(ya>>>0>>0){_a()}if(W>>>0>>0){_a()}else{c[W+12>>2]=Z;c[h>>2]=Z;c[da+(fa+8)>>2]=W;c[da+(fa+12)>>2]=ya;c[da+(fa+24)>>2]=0;break}}else{W=(c[27668>>2]|0)+aa|0;c[27668>>2]=W;c[27680>>2]=Z;c[da+(fa+4)>>2]=W|1}}while(0);p=da+(la|8)|0;i=b;return p|0}fa=28104|0;while(1){za=c[fa>>2]|0;if(!(za>>>0>ga>>>0)?(Aa=c[fa+4>>2]|0,Ba=za+Aa|0,Ba>>>0>ga>>>0):0){break}fa=c[fa+8>>2]|0}fa=za+(Aa+ -39)|0;if((fa&7|0)==0){Da=0}else{Da=0-fa&7}fa=za+(Aa+ -47+Da)|0;Z=fa>>>0<(ga+16|0)>>>0?ga:fa;fa=Z+8|0;aa=da+8|0;if((aa&7|0)==0){Ea=0}else{Ea=0-aa&7}aa=ea+ -40-Ea|0;c[27680>>2]=da+Ea;c[27668>>2]=aa;c[da+(Ea+4)>>2]=aa|1;c[da+(ea+ -36)>>2]=40;c[27684>>2]=c[28144>>2];c[Z+4>>2]=27;c[fa+0>>2]=c[28104>>2];c[fa+4>>2]=c[28108>>2];c[fa+8>>2]=c[28112>>2];c[fa+12>>2]=c[28116>>2];c[28104>>2]=da;c[28108>>2]=ea;c[28116>>2]=0;c[28112>>2]=fa;fa=Z+28|0;c[fa>>2]=7;if((Z+32|0)>>>0>>0){aa=fa;while(1){fa=aa+4|0;c[fa>>2]=7;if((aa+8|0)>>>0>>0){aa=fa}else{break}}}if((Z|0)!=(ga|0)){aa=Z-ga|0;fa=ga+(aa+4)|0;c[fa>>2]=c[fa>>2]&-2;c[ga+4>>2]=aa|1;c[ga+aa>>2]=aa;fa=aa>>>3;if(aa>>>0<256){M=fa<<1;ba=27696+(M<<2)|0;W=c[6914]|0;h=1<>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{Fa=fa;Ga=V}}else{c[6914]=W|h;Fa=27696+(M+2<<2)|0;Ga=ba}c[Fa>>2]=ga;c[Ga+12>>2]=ga;c[ga+8>>2]=Ga;c[ga+12>>2]=ba;break}ba=aa>>>8;if((ba|0)!=0){if(aa>>>0>16777215){Ha=31}else{M=(ba+1048320|0)>>>16&8;h=ba<>>16&4;W=h<>>16&2;V=14-(ba|M|h)+(W<>>15)|0;Ha=aa>>>(V+7|0)&1|V<<1}}else{Ha=0}V=27960+(Ha<<2)|0;c[ga+28>>2]=Ha;c[ga+20>>2]=0;c[ga+16>>2]=0;h=c[27660>>2]|0;W=1<>2]=h|W;c[V>>2]=ga;c[ga+24>>2]=V;c[ga+12>>2]=ga;c[ga+8>>2]=ga;break}W=c[V>>2]|0;if((Ha|0)==31){Ja=0}else{Ja=25-(Ha>>>1)|0}j:do{if((c[W+4>>2]&-8|0)!=(aa|0)){V=aa<>>31<<2)+16|0;M=c[Ka>>2]|0;if((M|0)==0){break}if((c[M+4>>2]&-8|0)==(aa|0)){La=M;break j}else{V=V<<1;h=M}}if(Ka>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[Ka>>2]=ga;c[ga+24>>2]=h;c[ga+12>>2]=ga;c[ga+8>>2]=ga;break g}}else{La=W}}while(0);W=La+8|0;aa=c[W>>2]|0;Z=c[27672>>2]|0;if(La>>>0>>0){_a()}if(aa>>>0>>0){_a()}else{c[aa+12>>2]=ga;c[W>>2]=ga;c[ga+8>>2]=aa;c[ga+12>>2]=La;c[ga+24>>2]=0;break}}}else{aa=c[27672>>2]|0;if((aa|0)==0|da>>>0>>0){c[27672>>2]=da}c[28104>>2]=da;c[28108>>2]=ea;c[28116>>2]=0;c[27692>>2]=c[7032];c[27688>>2]=-1;aa=0;do{W=aa<<1;Z=27696+(W<<2)|0;c[27696+(W+3<<2)>>2]=Z;c[27696+(W+2<<2)>>2]=Z;aa=aa+1|0}while((aa|0)!=32);aa=da+8|0;if((aa&7|0)==0){Ma=0}else{Ma=0-aa&7}aa=ea+ -40-Ma|0;c[27680>>2]=da+Ma;c[27668>>2]=aa;c[da+(Ma+4)>>2]=aa|1;c[da+(ea+ -36)>>2]=40;c[27684>>2]=c[28144>>2]}}while(0);ea=c[27668>>2]|0;if(ea>>>0>B>>>0){da=ea-B|0;c[27668>>2]=da;ea=c[27680>>2]|0;c[27680>>2]=ea+B;c[ea+(B+4)>>2]=da|1;c[ea+4>>2]=B|3;p=ea+8|0;i=b;return p|0}}c[(Sa()|0)>>2]=12;p=0;i=b;return p|0}function hg(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0;b=i;if((a|0)==0){i=b;return}d=a+ -8|0;e=c[27672>>2]|0;if(d>>>0>>0){_a()}f=c[a+ -4>>2]|0;g=f&3;if((g|0)==1){_a()}h=f&-8;j=a+(h+ -8)|0;do{if((f&1|0)==0){k=c[d>>2]|0;if((g|0)==0){i=b;return}l=-8-k|0;m=a+l|0;n=k+h|0;if(m>>>0>>0){_a()}if((m|0)==(c[27676>>2]|0)){o=a+(h+ -4)|0;if((c[o>>2]&3|0)!=3){p=m;q=n;break}c[27664>>2]=n;c[o>>2]=c[o>>2]&-2;c[a+(l+4)>>2]=n|1;c[j>>2]=n;i=b;return}o=k>>>3;if(k>>>0<256){k=c[a+(l+8)>>2]|0;r=c[a+(l+12)>>2]|0;s=27696+(o<<1<<2)|0;if((k|0)!=(s|0)){if(k>>>0>>0){_a()}if((c[k+12>>2]|0)!=(m|0)){_a()}}if((r|0)==(k|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}s=r+8|0;if((c[s>>2]|0)==(m|0)){t=s}else{_a()}}else{t=r+8|0}c[k+12>>2]=r;c[t>>2]=k;p=m;q=n;break}k=c[a+(l+24)>>2]|0;r=c[a+(l+12)>>2]|0;do{if((r|0)==(m|0)){s=a+(l+20)|0;o=c[s>>2]|0;if((o|0)==0){u=a+(l+16)|0;v=c[u>>2]|0;if((v|0)==0){w=0;break}else{x=v;y=u}}else{x=o;y=s}while(1){s=x+20|0;o=c[s>>2]|0;if((o|0)!=0){x=o;y=s;continue}s=x+16|0;o=c[s>>2]|0;if((o|0)==0){break}else{x=o;y=s}}if(y>>>0>>0){_a()}else{c[y>>2]=0;w=x;break}}else{s=c[a+(l+8)>>2]|0;if(s>>>0>>0){_a()}o=s+12|0;if((c[o>>2]|0)!=(m|0)){_a()}u=r+8|0;if((c[u>>2]|0)==(m|0)){c[o>>2]=r;c[u>>2]=s;w=r;break}else{_a()}}}while(0);if((k|0)!=0){r=c[a+(l+28)>>2]|0;s=27960+(r<<2)|0;if((m|0)==(c[s>>2]|0)){c[s>>2]=w;if((w|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}r=k+16|0;if((c[r>>2]|0)==(m|0)){c[r>>2]=w}else{c[k+20>>2]=w}if((w|0)==0){p=m;q=n;break}}if(w>>>0<(c[27672>>2]|0)>>>0){_a()}c[w+24>>2]=k;r=c[a+(l+16)>>2]|0;do{if((r|0)!=0){if(r>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+16>>2]=r;c[r+24>>2]=w;break}}}while(0);r=c[a+(l+20)>>2]|0;if((r|0)!=0){if(r>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+20>>2]=r;c[r+24>>2]=w;p=m;q=n;break}}else{p=m;q=n}}else{p=m;q=n}}else{p=d;q=h}}while(0);if(!(p>>>0>>0)){_a()}d=a+(h+ -4)|0;w=c[d>>2]|0;if((w&1|0)==0){_a()}if((w&2|0)==0){if((j|0)==(c[27680>>2]|0)){e=(c[27668>>2]|0)+q|0;c[27668>>2]=e;c[27680>>2]=p;c[p+4>>2]=e|1;if((p|0)!=(c[27676>>2]|0)){i=b;return}c[27676>>2]=0;c[27664>>2]=0;i=b;return}if((j|0)==(c[27676>>2]|0)){e=(c[27664>>2]|0)+q|0;c[27664>>2]=e;c[27676>>2]=p;c[p+4>>2]=e|1;c[p+e>>2]=e;i=b;return}e=(w&-8)+q|0;x=w>>>3;do{if(!(w>>>0<256)){y=c[a+(h+16)>>2]|0;t=c[a+(h|4)>>2]|0;do{if((t|0)==(j|0)){g=a+(h+12)|0;f=c[g>>2]|0;if((f|0)==0){r=a+(h+8)|0;k=c[r>>2]|0;if((k|0)==0){z=0;break}else{A=k;B=r}}else{A=f;B=g}while(1){g=A+20|0;f=c[g>>2]|0;if((f|0)!=0){A=f;B=g;continue}g=A+16|0;f=c[g>>2]|0;if((f|0)==0){break}else{A=f;B=g}}if(B>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[B>>2]=0;z=A;break}}else{g=c[a+h>>2]|0;if(g>>>0<(c[27672>>2]|0)>>>0){_a()}f=g+12|0;if((c[f>>2]|0)!=(j|0)){_a()}r=t+8|0;if((c[r>>2]|0)==(j|0)){c[f>>2]=t;c[r>>2]=g;z=t;break}else{_a()}}}while(0);if((y|0)!=0){t=c[a+(h+20)>>2]|0;n=27960+(t<<2)|0;if((j|0)==(c[n>>2]|0)){c[n>>2]=z;if((z|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}t=y+16|0;if((c[t>>2]|0)==(j|0)){c[t>>2]=z}else{c[y+20>>2]=z}if((z|0)==0){break}}if(z>>>0<(c[27672>>2]|0)>>>0){_a()}c[z+24>>2]=y;t=c[a+(h+8)>>2]|0;do{if((t|0)!=0){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[z+16>>2]=t;c[t+24>>2]=z;break}}}while(0);t=c[a+(h+12)>>2]|0;if((t|0)!=0){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[z+20>>2]=t;c[t+24>>2]=z;break}}}}else{t=c[a+h>>2]|0;y=c[a+(h|4)>>2]|0;n=27696+(x<<1<<2)|0;if((t|0)!=(n|0)){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}if((c[t+12>>2]|0)!=(j|0)){_a()}}if((y|0)==(t|0)){c[6914]=c[6914]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}n=y+8|0;if((c[n>>2]|0)==(j|0)){C=n}else{_a()}}else{C=y+8|0}c[t+12>>2]=y;c[C>>2]=t}}while(0);c[p+4>>2]=e|1;c[p+e>>2]=e;if((p|0)==(c[27676>>2]|0)){c[27664>>2]=e;i=b;return}else{D=e}}else{c[d>>2]=w&-2;c[p+4>>2]=q|1;c[p+q>>2]=q;D=q}q=D>>>3;if(D>>>0<256){w=q<<1;d=27696+(w<<2)|0;e=c[6914]|0;C=1<>2]|0;if(j>>>0<(c[27672>>2]|0)>>>0){_a()}else{E=q;F=j}}else{c[6914]=e|C;E=27696+(w+2<<2)|0;F=d}c[E>>2]=p;c[F+12>>2]=p;c[p+8>>2]=F;c[p+12>>2]=d;i=b;return}d=D>>>8;if((d|0)!=0){if(D>>>0>16777215){G=31}else{F=(d+1048320|0)>>>16&8;E=d<>>16&4;w=E<>>16&2;C=14-(d|F|E)+(w<>>15)|0;G=D>>>(C+7|0)&1|C<<1}}else{G=0}C=27960+(G<<2)|0;c[p+28>>2]=G;c[p+20>>2]=0;c[p+16>>2]=0;E=c[27660>>2]|0;w=1<>2]|0;if((G|0)==31){H=0}else{H=25-(G>>>1)|0}b:do{if((c[F+4>>2]&-8|0)!=(D|0)){d=D<>>31<<2)+16|0;j=c[I>>2]|0;if((j|0)==0){break}if((c[j+4>>2]&-8|0)==(D|0)){J=j;break b}else{d=d<<1;e=j}}if(I>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[I>>2]=p;c[p+24>>2]=e;c[p+12>>2]=p;c[p+8>>2]=p;break a}}else{J=F}}while(0);F=J+8|0;d=c[F>>2]|0;j=c[27672>>2]|0;if(J>>>0>>0){_a()}if(d>>>0>>0){_a()}else{c[d+12>>2]=p;c[F>>2]=p;c[p+8>>2]=d;c[p+12>>2]=J;c[p+24>>2]=0;break}}else{c[27660>>2]=E|w;c[C>>2]=p;c[p+24>>2]=C;c[p+12>>2]=p;c[p+8>>2]=p}}while(0);p=(c[27688>>2]|0)+ -1|0;c[27688>>2]=p;if((p|0)==0){K=28112|0}else{i=b;return}while(1){p=c[K>>2]|0;if((p|0)==0){break}else{K=p+8|0}}c[27688>>2]=-1;i=b;return}function ig(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;if((a|0)!=0){e=aa(b,a)|0;if((b|a)>>>0>65535){f=((e>>>0)/(a>>>0)|0|0)==(b|0)?e:-1}else{f=e}}else{f=0}e=gg(f)|0;if((e|0)==0){i=d;return e|0}if((c[e+ -4>>2]&3|0)==0){i=d;return e|0}Eg(e|0,0,f|0)|0;i=d;return e|0}function jg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;do{if((a|0)!=0){if(b>>>0>4294967231){c[(Sa()|0)>>2]=12;e=0;break}if(b>>>0<11){f=16}else{f=b+11&-8}g=kg(a+ -8|0,f)|0;if((g|0)!=0){e=g+8|0;break}g=gg(b)|0;if((g|0)==0){e=0}else{h=c[a+ -4>>2]|0;j=(h&-8)-((h&3|0)==0?8:4)|0;Kg(g|0,a|0,(j>>>0>>0?j:b)|0)|0;hg(a);e=g}}else{e=gg(b)|0}}while(0);i=d;return e|0}function kg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;d=i;e=a+4|0;f=c[e>>2]|0;g=f&-8;h=a+g|0;j=c[27672>>2]|0;if(a>>>0>>0){_a()}k=f&3;if(!((k|0)!=1&a>>>0>>0)){_a()}l=a+(g|4)|0;m=c[l>>2]|0;if((m&1|0)==0){_a()}if((k|0)==0){if(b>>>0<256){n=0;i=d;return n|0}if(!(g>>>0<(b+4|0)>>>0)?!((g-b|0)>>>0>c[28136>>2]<<1>>>0):0){n=a;i=d;return n|0}n=0;i=d;return n|0}if(!(g>>>0>>0)){k=g-b|0;if(!(k>>>0>15)){n=a;i=d;return n|0}c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=k|3;c[l>>2]=c[l>>2]|1;lg(a+b|0,k);n=a;i=d;return n|0}if((h|0)==(c[27680>>2]|0)){k=(c[27668>>2]|0)+g|0;if(!(k>>>0>b>>>0)){n=0;i=d;return n|0}l=k-b|0;c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=l|1;c[27680>>2]=a+b;c[27668>>2]=l;n=a;i=d;return n|0}if((h|0)==(c[27676>>2]|0)){l=(c[27664>>2]|0)+g|0;if(l>>>0>>0){n=0;i=d;return n|0}k=l-b|0;if(k>>>0>15){c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=k|1;c[a+l>>2]=k;o=a+(l+4)|0;c[o>>2]=c[o>>2]&-2;p=a+b|0;q=k}else{c[e>>2]=f&1|l|2;f=a+(l+4)|0;c[f>>2]=c[f>>2]|1;p=0;q=0}c[27664>>2]=q;c[27676>>2]=p;n=a;i=d;return n|0}if((m&2|0)!=0){n=0;i=d;return n|0}p=(m&-8)+g|0;if(p>>>0>>0){n=0;i=d;return n|0}q=p-b|0;f=m>>>3;do{if(!(m>>>0<256)){l=c[a+(g+24)>>2]|0;k=c[a+(g+12)>>2]|0;do{if((k|0)==(h|0)){o=a+(g+20)|0;r=c[o>>2]|0;if((r|0)==0){s=a+(g+16)|0;t=c[s>>2]|0;if((t|0)==0){u=0;break}else{v=t;w=s}}else{v=r;w=o}while(1){o=v+20|0;r=c[o>>2]|0;if((r|0)!=0){v=r;w=o;continue}o=v+16|0;r=c[o>>2]|0;if((r|0)==0){break}else{v=r;w=o}}if(w>>>0>>0){_a()}else{c[w>>2]=0;u=v;break}}else{o=c[a+(g+8)>>2]|0;if(o>>>0>>0){_a()}r=o+12|0;if((c[r>>2]|0)!=(h|0)){_a()}s=k+8|0;if((c[s>>2]|0)==(h|0)){c[r>>2]=k;c[s>>2]=o;u=k;break}else{_a()}}}while(0);if((l|0)!=0){k=c[a+(g+28)>>2]|0;o=27960+(k<<2)|0;if((h|0)==(c[o>>2]|0)){c[o>>2]=u;if((u|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}k=l+16|0;if((c[k>>2]|0)==(h|0)){c[k>>2]=u}else{c[l+20>>2]=u}if((u|0)==0){break}}if(u>>>0<(c[27672>>2]|0)>>>0){_a()}c[u+24>>2]=l;k=c[a+(g+16)>>2]|0;do{if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+16>>2]=k;c[k+24>>2]=u;break}}}while(0);k=c[a+(g+20)>>2]|0;if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+20>>2]=k;c[k+24>>2]=u;break}}}}else{k=c[a+(g+8)>>2]|0;l=c[a+(g+12)>>2]|0;o=27696+(f<<1<<2)|0;if((k|0)!=(o|0)){if(k>>>0>>0){_a()}if((c[k+12>>2]|0)!=(h|0)){_a()}}if((l|0)==(k|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}o=l+8|0;if((c[o>>2]|0)==(h|0)){x=o}else{_a()}}else{x=l+8|0}c[k+12>>2]=l;c[x>>2]=k}}while(0);if(q>>>0<16){c[e>>2]=p|c[e>>2]&1|2;x=a+(p|4)|0;c[x>>2]=c[x>>2]|1;n=a;i=d;return n|0}else{c[e>>2]=c[e>>2]&1|b|2;c[a+(b+4)>>2]=q|3;e=a+(p|4)|0;c[e>>2]=c[e>>2]|1;lg(a+b|0,q);n=a;i=d;return n|0}return 0}function lg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;d=i;e=a+b|0;f=c[a+4>>2]|0;do{if((f&1|0)==0){g=c[a>>2]|0;if((f&3|0)==0){i=d;return}h=a+(0-g)|0;j=g+b|0;k=c[27672>>2]|0;if(h>>>0>>0){_a()}if((h|0)==(c[27676>>2]|0)){l=a+(b+4)|0;if((c[l>>2]&3|0)!=3){m=h;n=j;break}c[27664>>2]=j;c[l>>2]=c[l>>2]&-2;c[a+(4-g)>>2]=j|1;c[e>>2]=j;i=d;return}l=g>>>3;if(g>>>0<256){o=c[a+(8-g)>>2]|0;p=c[a+(12-g)>>2]|0;q=27696+(l<<1<<2)|0;if((o|0)!=(q|0)){if(o>>>0>>0){_a()}if((c[o+12>>2]|0)!=(h|0)){_a()}}if((p|0)==(o|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}q=p+8|0;if((c[q>>2]|0)==(h|0)){r=q}else{_a()}}else{r=p+8|0}c[o+12>>2]=p;c[r>>2]=o;m=h;n=j;break}o=c[a+(24-g)>>2]|0;p=c[a+(12-g)>>2]|0;do{if((p|0)==(h|0)){q=16-g|0;l=a+(q+4)|0;s=c[l>>2]|0;if((s|0)==0){t=a+q|0;q=c[t>>2]|0;if((q|0)==0){u=0;break}else{v=q;w=t}}else{v=s;w=l}while(1){l=v+20|0;s=c[l>>2]|0;if((s|0)!=0){v=s;w=l;continue}l=v+16|0;s=c[l>>2]|0;if((s|0)==0){break}else{v=s;w=l}}if(w>>>0>>0){_a()}else{c[w>>2]=0;u=v;break}}else{l=c[a+(8-g)>>2]|0;if(l>>>0>>0){_a()}s=l+12|0;if((c[s>>2]|0)!=(h|0)){_a()}t=p+8|0;if((c[t>>2]|0)==(h|0)){c[s>>2]=p;c[t>>2]=l;u=p;break}else{_a()}}}while(0);if((o|0)!=0){p=c[a+(28-g)>>2]|0;k=27960+(p<<2)|0;if((h|0)==(c[k>>2]|0)){c[k>>2]=u;if((u|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}p=o+16|0;if((c[p>>2]|0)==(h|0)){c[p>>2]=u}else{c[o+20>>2]=u}if((u|0)==0){m=h;n=j;break}}if(u>>>0<(c[27672>>2]|0)>>>0){_a()}c[u+24>>2]=o;p=16-g|0;k=c[a+p>>2]|0;do{if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+16>>2]=k;c[k+24>>2]=u;break}}}while(0);k=c[a+(p+4)>>2]|0;if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+20>>2]=k;c[k+24>>2]=u;m=h;n=j;break}}else{m=h;n=j}}else{m=h;n=j}}else{m=a;n=b}}while(0);u=c[27672>>2]|0;if(e>>>0>>0){_a()}v=a+(b+4)|0;w=c[v>>2]|0;if((w&2|0)==0){if((e|0)==(c[27680>>2]|0)){r=(c[27668>>2]|0)+n|0;c[27668>>2]=r;c[27680>>2]=m;c[m+4>>2]=r|1;if((m|0)!=(c[27676>>2]|0)){i=d;return}c[27676>>2]=0;c[27664>>2]=0;i=d;return}if((e|0)==(c[27676>>2]|0)){r=(c[27664>>2]|0)+n|0;c[27664>>2]=r;c[27676>>2]=m;c[m+4>>2]=r|1;c[m+r>>2]=r;i=d;return}r=(w&-8)+n|0;f=w>>>3;do{if(!(w>>>0<256)){k=c[a+(b+24)>>2]|0;g=c[a+(b+12)>>2]|0;do{if((g|0)==(e|0)){o=a+(b+20)|0;l=c[o>>2]|0;if((l|0)==0){t=a+(b+16)|0;s=c[t>>2]|0;if((s|0)==0){x=0;break}else{y=s;z=t}}else{y=l;z=o}while(1){o=y+20|0;l=c[o>>2]|0;if((l|0)!=0){y=l;z=o;continue}o=y+16|0;l=c[o>>2]|0;if((l|0)==0){break}else{y=l;z=o}}if(z>>>0>>0){_a()}else{c[z>>2]=0;x=y;break}}else{o=c[a+(b+8)>>2]|0;if(o>>>0>>0){_a()}l=o+12|0;if((c[l>>2]|0)!=(e|0)){_a()}t=g+8|0;if((c[t>>2]|0)==(e|0)){c[l>>2]=g;c[t>>2]=o;x=g;break}else{_a()}}}while(0);if((k|0)!=0){g=c[a+(b+28)>>2]|0;j=27960+(g<<2)|0;if((e|0)==(c[j>>2]|0)){c[j>>2]=x;if((x|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}g=k+16|0;if((c[g>>2]|0)==(e|0)){c[g>>2]=x}else{c[k+20>>2]=x}if((x|0)==0){break}}if(x>>>0<(c[27672>>2]|0)>>>0){_a()}c[x+24>>2]=k;g=c[a+(b+16)>>2]|0;do{if((g|0)!=0){if(g>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[x+16>>2]=g;c[g+24>>2]=x;break}}}while(0);g=c[a+(b+20)>>2]|0;if((g|0)!=0){if(g>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[x+20>>2]=g;c[g+24>>2]=x;break}}}}else{g=c[a+(b+8)>>2]|0;k=c[a+(b+12)>>2]|0;j=27696+(f<<1<<2)|0;if((g|0)!=(j|0)){if(g>>>0>>0){_a()}if((c[g+12>>2]|0)!=(e|0)){_a()}}if((k|0)==(g|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}j=k+8|0;if((c[j>>2]|0)==(e|0)){A=j}else{_a()}}else{A=k+8|0}c[g+12>>2]=k;c[A>>2]=g}}while(0);c[m+4>>2]=r|1;c[m+r>>2]=r;if((m|0)==(c[27676>>2]|0)){c[27664>>2]=r;i=d;return}else{B=r}}else{c[v>>2]=w&-2;c[m+4>>2]=n|1;c[m+n>>2]=n;B=n}n=B>>>3;if(B>>>0<256){w=n<<1;v=27696+(w<<2)|0;r=c[6914]|0;A=1<>2]|0;if(e>>>0<(c[27672>>2]|0)>>>0){_a()}else{C=n;D=e}}else{c[6914]=r|A;C=27696+(w+2<<2)|0;D=v}c[C>>2]=m;c[D+12>>2]=m;c[m+8>>2]=D;c[m+12>>2]=v;i=d;return}v=B>>>8;if((v|0)!=0){if(B>>>0>16777215){E=31}else{D=(v+1048320|0)>>>16&8;C=v<>>16&4;w=C<>>16&2;A=14-(v|D|C)+(w<>>15)|0;E=B>>>(A+7|0)&1|A<<1}}else{E=0}A=27960+(E<<2)|0;c[m+28>>2]=E;c[m+20>>2]=0;c[m+16>>2]=0;C=c[27660>>2]|0;w=1<>2]=C|w;c[A>>2]=m;c[m+24>>2]=A;c[m+12>>2]=m;c[m+8>>2]=m;i=d;return}w=c[A>>2]|0;if((E|0)==31){F=0}else{F=25-(E>>>1)|0}a:do{if((c[w+4>>2]&-8|0)==(B|0)){G=w}else{E=B<>>31<<2)+16|0;C=c[H>>2]|0;if((C|0)==0){break}if((c[C+4>>2]&-8|0)==(B|0)){G=C;break a}else{E=E<<1;A=C}}if(H>>>0<(c[27672>>2]|0)>>>0){_a()}c[H>>2]=m;c[m+24>>2]=A;c[m+12>>2]=m;c[m+8>>2]=m;i=d;return}}while(0);H=G+8|0;B=c[H>>2]|0;w=c[27672>>2]|0;if(G>>>0>>0){_a()}if(B>>>0>>0){_a()}c[B+12>>2]=m;c[H>>2]=m;c[m+8>>2]=B;c[m+12>>2]=G;c[m+24>>2]=0;i=d;return}function mg(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0.0,Q=0,R=0.0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0.0,ca=0,da=0.0,ea=0,fa=0.0,ga=0,ha=0.0,ia=0,ja=0.0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,ra=0,sa=0.0,ta=0,ua=0.0,va=0,wa=0,xa=0,ya=0,za=0.0,Aa=0,Ba=0.0,Ca=0.0,Da=0,Ea=0.0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Ta=0,Ua=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0.0,sc=0,tc=0,uc=0.0,vc=0.0,wc=0.0,xc=0.0,yc=0.0,zc=0.0,Ac=0,Bc=0,Cc=0.0,Dc=0,Ec=0.0,Fc=0,Gc=0,Hc=0,Ic=0;g=i;i=i+512|0;h=g;if((e|0)==1){j=53;k=-1074}else if((e|0)==0){j=24;k=-149}else if((e|0)==2){j=53;k=-1074}else{l=0.0;i=g;return+l}e=b+4|0;m=b+100|0;do{n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;o=d[n]|0}else{o=pg(b)|0}}while((fb(o|0)|0)!=0);do{if((o|0)==43|(o|0)==45){n=1-(((o|0)==45)<<1)|0;p=c[e>>2]|0;if(p>>>0<(c[m>>2]|0)>>>0){c[e>>2]=p+1;q=d[p]|0;r=n;break}else{q=pg(b)|0;r=n;break}}else{q=o;r=1}}while(0);o=q;q=0;while(1){if((o|32|0)!=(a[28152+q|0]|0)){s=o;v=q;break}do{if(q>>>0<7){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;w=d[n]|0;break}else{w=pg(b)|0;break}}else{w=o}}while(0);n=q+1|0;if(n>>>0<8){o=w;q=n}else{s=w;v=n;break}}do{if((v|0)==3){x=23}else if((v|0)!=8){w=(f|0)==0;if(!(v>>>0<4|w)){if((v|0)==8){break}else{x=23;break}}a:do{if((v|0)==0){q=s;o=0;while(1){if((q|32|0)!=(a[28168+o|0]|0)){y=q;z=o;break a}do{if(o>>>0<2){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;A=d[n]|0;break}else{A=pg(b)|0;break}}else{A=q}}while(0);n=o+1|0;if(n>>>0<3){q=A;o=n}else{y=A;z=n;break}}}else{y=s;z=v}}while(0);if((z|0)==0){do{if((y|0)==48){o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;B=d[o]|0}else{B=pg(b)|0}if((B|32|0)!=120){if((c[m>>2]|0)==0){C=48;break}c[e>>2]=(c[e>>2]|0)+ -1;C=48;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;D=d[o]|0;F=0}else{D=pg(b)|0;F=0}while(1){if((D|0)==46){x=70;break}else if((D|0)!=48){G=0;H=0;I=0;J=0;K=D;L=F;M=0;N=0;O=1.0;Q=0;R=0.0;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;D=d[o]|0;F=1;continue}else{D=pg(b)|0;F=1;continue}}b:do{if((x|0)==70){o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;S=d[o]|0}else{S=pg(b)|0}if((S|0)==48){o=-1;q=-1;while(1){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;T=d[n]|0}else{T=pg(b)|0}if((T|0)!=48){G=0;H=0;I=o;J=q;K=T;L=1;M=1;N=0;O=1.0;Q=0;R=0.0;break b}n=Ig(o|0,q|0,-1,-1)|0;o=n;q=E}}else{G=0;H=0;I=0;J=0;K=S;L=F;M=1;N=0;O=1.0;Q=0;R=0.0}}}while(0);c:while(1){q=K+ -48|0;do{if(!(q>>>0<10)){o=K|32;n=(K|0)==46;if(!((o+ -97|0)>>>0<6|n)){U=K;break c}if(n){if((M|0)==0){V=H;W=G;X=H;Y=G;Z=L;_=1;$=N;ba=O;ca=Q;da=R;break}else{U=46;break c}}else{ea=(K|0)>57?o+ -87|0:q;x=84;break}}else{ea=q;x=84}}while(0);if((x|0)==84){x=0;do{if(!((G|0)<0|(G|0)==0&H>>>0<8)){if((G|0)<0|(G|0)==0&H>>>0<14){fa=O*.0625;ga=N;ha=fa;ia=Q;ja=R+fa*+(ea|0);break}if((ea|0)!=0&(N|0)==0){ga=1;ha=O;ia=Q;ja=R+O*.5}else{ga=N;ha=O;ia=Q;ja=R}}else{ga=N;ha=O;ia=ea+(Q<<4)|0;ja=R}}while(0);q=Ig(H|0,G|0,1,0)|0;V=I;W=J;X=q;Y=E;Z=1;_=M;$=ga;ba=ha;ca=ia;da=ja}q=c[e>>2]|0;if(q>>>0<(c[m>>2]|0)>>>0){c[e>>2]=q+1;G=Y;H=X;I=V;J=W;K=d[q]|0;L=Z;M=_;N=$;O=ba;Q=ca;R=da;continue}else{G=Y;H=X;I=V;J=W;K=pg(b)|0;L=Z;M=_;N=$;O=ba;Q=ca;R=da;continue}}if((L|0)==0){q=(c[m>>2]|0)==0;if(!q){c[e>>2]=(c[e>>2]|0)+ -1}if(!w){if(!q?(q=c[e>>2]|0,c[e>>2]=q+ -1,(M|0)!=0):0){c[e>>2]=q+ -2}}else{og(b,0)}l=+(r|0)*0.0;i=g;return+l}q=(M|0)==0;o=q?H:I;n=q?G:J;if((G|0)<0|(G|0)==0&H>>>0<8){q=H;p=G;ka=Q;while(1){la=ka<<4;ma=Ig(q|0,p|0,1,0)|0;na=E;if((na|0)<0|(na|0)==0&ma>>>0<8){q=ma;p=na;ka=la}else{oa=la;break}}}else{oa=Q}do{if((U|32|0)==112){ka=ng(b,f)|0;p=E;if((ka|0)==0&(p|0)==-2147483648){if(w){og(b,0);l=0.0;i=g;return+l}else{if((c[m>>2]|0)==0){pa=0;ra=0;break}c[e>>2]=(c[e>>2]|0)+ -1;pa=0;ra=0;break}}else{pa=ka;ra=p}}else{if((c[m>>2]|0)==0){pa=0;ra=0}else{c[e>>2]=(c[e>>2]|0)+ -1;pa=0;ra=0}}}while(0);p=Gg(o|0,n|0,2)|0;ka=Ig(p|0,E|0,-32,-1)|0;p=Ig(ka|0,E|0,pa|0,ra|0)|0;ka=E;if((oa|0)==0){l=+(r|0)*0.0;i=g;return+l}if((ka|0)>0|(ka|0)==0&p>>>0>(0-k|0)>>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+l}q=k+ -106|0;la=((q|0)<0)<<31>>31;if((ka|0)<(la|0)|(ka|0)==(la|0)&p>>>0>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+l}if((oa|0)>-1){q=p;la=ka;na=oa;fa=R;while(1){ma=na<<1;if(!(fa>=.5)){sa=fa;ta=ma}else{sa=fa+-1.0;ta=ma|1}ua=fa+sa;ma=Ig(q|0,la|0,-1,-1)|0;va=E;if((ta|0)>-1){q=ma;la=va;na=ta;fa=ua}else{wa=ma;xa=va;ya=ta;za=ua;break}}}else{wa=p;xa=ka;ya=oa;za=R}na=Cg(32,0,k|0,((k|0)<0)<<31>>31|0)|0;la=Ig(wa|0,xa|0,na|0,E|0)|0;na=E;if(0>(na|0)|0==(na|0)&j>>>0>la>>>0){Aa=(la|0)<0?0:la}else{Aa=j}if((Aa|0)<53){fa=+(r|0);ua=+Va(+(+qg(1.0,84-Aa|0)),+fa);if((Aa|0)<32&za!=0.0){la=ya&1;Ba=fa;Ca=ua;Da=(la^1)+ya|0;Ea=(la|0)==0?0.0:za}else{Ba=fa;Ca=ua;Da=ya;Ea=za}}else{Ba=+(r|0);Ca=0.0;Da=ya;Ea=za}ua=Ba*Ea+(Ca+Ba*+(Da>>>0))-Ca;if(!(ua!=0.0)){c[(Sa()|0)>>2]=34}l=+rg(ua,wa);i=g;return+l}else{C=y}}while(0);la=k+j|0;na=0-la|0;q=C;n=0;while(1){if((q|0)==46){x=139;break}else if((q|0)!=48){Fa=q;Ga=0;Ha=0;Ia=n;Ja=0;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;q=d[o]|0;n=1;continue}else{q=pg(b)|0;n=1;continue}}d:do{if((x|0)==139){q=c[e>>2]|0;if(q>>>0<(c[m>>2]|0)>>>0){c[e>>2]=q+1;Ka=d[q]|0}else{Ka=pg(b)|0}if((Ka|0)==48){q=-1;o=-1;while(1){va=c[e>>2]|0;if(va>>>0<(c[m>>2]|0)>>>0){c[e>>2]=va+1;La=d[va]|0}else{La=pg(b)|0}if((La|0)!=48){Fa=La;Ga=q;Ha=o;Ia=1;Ja=1;break d}va=Ig(q|0,o|0,-1,-1)|0;q=va;o=E}}else{Fa=Ka;Ga=0;Ha=0;Ia=n;Ja=1}}}while(0);c[h>>2]=0;n=Fa+ -48|0;o=(Fa|0)==46;e:do{if(n>>>0<10|o){q=h+496|0;ka=Fa;p=0;va=0;ma=o;Ma=n;Na=Ga;Oa=Ha;Pa=Ia;Qa=Ja;Ra=0;Ta=0;Ua=0;while(1){do{if(ma){if((Qa|0)==0){Wa=p;Xa=va;Ya=p;Za=va;_a=Pa;$a=1;ab=Ra;bb=Ta;cb=Ua}else{db=ka;eb=Na;gb=Oa;hb=p;ib=va;jb=Pa;kb=Ra;lb=Ta;mb=Ua;break e}}else{nb=Ig(p|0,va|0,1,0)|0;ob=E;pb=(ka|0)!=48;if((Ta|0)>=125){if(!pb){Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=Pa;$a=Qa;ab=Ra;bb=Ta;cb=Ua;break}c[q>>2]=c[q>>2]|1;Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=Pa;$a=Qa;ab=Ra;bb=Ta;cb=Ua;break}qb=h+(Ta<<2)|0;if((Ra|0)==0){rb=Ma}else{rb=ka+ -48+((c[qb>>2]|0)*10|0)|0}c[qb>>2]=rb;qb=Ra+1|0;sb=(qb|0)==9;Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=1;$a=Qa;ab=sb?0:qb;bb=(sb&1)+Ta|0;cb=pb?nb:Ua}}while(0);nb=c[e>>2]|0;if(nb>>>0<(c[m>>2]|0)>>>0){c[e>>2]=nb+1;tb=d[nb]|0}else{tb=pg(b)|0}nb=tb+ -48|0;pb=(tb|0)==46;if(nb>>>0<10|pb){ka=tb;p=Ya;va=Za;ma=pb;Ma=nb;Na=Wa;Oa=Xa;Pa=_a;Qa=$a;Ra=ab;Ta=bb;Ua=cb}else{ub=tb;vb=Ya;wb=Wa;xb=Za;yb=Xa;zb=_a;Ab=$a;Bb=ab;Cb=bb;Db=cb;x=162;break}}}else{ub=Fa;vb=0;wb=Ga;xb=0;yb=Ha;zb=Ia;Ab=Ja;Bb=0;Cb=0;Db=0;x=162}}while(0);if((x|0)==162){n=(Ab|0)==0;db=ub;eb=n?vb:wb;gb=n?xb:yb;hb=vb;ib=xb;jb=zb;kb=Bb;lb=Cb;mb=Db}n=(jb|0)!=0;if(n?(db|32|0)==101:0){o=ng(b,f)|0;Ua=E;do{if((o|0)==0&(Ua|0)==-2147483648){if(w){og(b,0);l=0.0;i=g;return+l}else{if((c[m>>2]|0)==0){Eb=0;Fb=0;break}c[e>>2]=(c[e>>2]|0)+ -1;Eb=0;Fb=0;break}}else{Eb=o;Fb=Ua}}while(0);Ua=Ig(Eb|0,Fb|0,eb|0,gb|0)|0;Gb=Ua;Hb=E}else{if((db|0)>-1?(c[m>>2]|0)!=0:0){c[e>>2]=(c[e>>2]|0)+ -1;Gb=eb;Hb=gb}else{Gb=eb;Hb=gb}}if(!n){c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}Ua=c[h>>2]|0;if((Ua|0)==0){l=+(r|0)*0.0;i=g;return+l}do{if((Gb|0)==(hb|0)&(Hb|0)==(ib|0)&((ib|0)<0|(ib|0)==0&hb>>>0<10)){if(!(j>>>0>30)?(Ua>>>j|0)!=0:0){break}l=+(r|0)*+(Ua>>>0);i=g;return+l}}while(0);Ua=(k|0)/-2|0;n=((Ua|0)<0)<<31>>31;if((Hb|0)>(n|0)|(Hb|0)==(n|0)&Gb>>>0>Ua>>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+l}Ua=k+ -106|0;n=((Ua|0)<0)<<31>>31;if((Hb|0)<(n|0)|(Hb|0)==(n|0)&Gb>>>0>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+l}if((kb|0)==0){Ib=lb}else{if((kb|0)<9){Ua=h+(lb<<2)|0;n=c[Ua>>2]|0;o=kb;do{n=n*10|0;o=o+1|0}while((o|0)!=9);c[Ua>>2]=n}Ib=lb+1|0}do{if((mb|0)<9?(mb|0)<=(Gb|0)&(Gb|0)<18:0){if((Gb|0)==9){l=+(r|0)*+((c[h>>2]|0)>>>0);i=g;return+l}if((Gb|0)<9){l=+(r|0)*+((c[h>>2]|0)>>>0)/+(c[28184+(8-Gb<<2)>>2]|0);i=g;return+l}o=j+27+(aa(Gb,-3)|0)|0;Ta=c[h>>2]|0;if((o|0)<=30?(Ta>>>o|0)!=0:0){break}l=+(r|0)*+(Ta>>>0)*+(c[28184+(Gb+ -10<<2)>>2]|0);i=g;return+l}}while(0);n=(Gb|0)%9|0;if((n|0)==0){Jb=0;Kb=0;Lb=Gb;Mb=Ib}else{Ua=(Gb|0)>-1?n:n+9|0;n=c[28184+(8-Ua<<2)>>2]|0;if((Ib|0)!=0){Ta=1e9/(n|0)|0;o=0;Ra=0;Qa=0;Pa=Gb;while(1){Oa=h+(Qa<<2)|0;Na=c[Oa>>2]|0;Ma=((Na>>>0)/(n>>>0)|0)+Ra|0;c[Oa>>2]=Ma;Nb=aa((Na>>>0)%(n>>>0)|0,Ta)|0;Na=Qa+1|0;if((Qa|0)==(o|0)&(Ma|0)==0){Ob=Na&127;Pb=Pa+ -9|0}else{Ob=o;Pb=Pa}if((Na|0)==(Ib|0)){break}else{o=Ob;Ra=Nb;Qa=Na;Pa=Pb}}if((Nb|0)==0){Qb=Ob;Rb=Pb;Sb=Ib}else{c[h+(Ib<<2)>>2]=Nb;Qb=Ob;Rb=Pb;Sb=Ib+1|0}}else{Qb=0;Rb=Gb;Sb=0}Jb=Qb;Kb=0;Lb=9-Ua+Rb|0;Mb=Sb}f:while(1){Pa=h+(Jb<<2)|0;if((Lb|0)<18){Qa=Kb;Ra=Mb;while(1){o=0;Ta=Ra+127|0;n=Ra;while(1){Na=Ta&127;Ma=h+(Na<<2)|0;Oa=Gg(c[Ma>>2]|0,0,29)|0;ma=Ig(Oa|0,E|0,o|0,0)|0;Oa=E;if(Oa>>>0>0|(Oa|0)==0&ma>>>0>1e9){va=Ug(ma|0,Oa|0,1e9,0)|0;p=Vg(ma|0,Oa|0,1e9,0)|0;Tb=p;Ub=va}else{Tb=ma;Ub=0}c[Ma>>2]=Tb;Ma=(Na|0)==(Jb|0);if((Na|0)!=(n+127&127|0)|Ma){Vb=n}else{Vb=(Tb|0)==0?Na:n}if(Ma){break}else{o=Ub;Ta=Na+ -1|0;n=Vb}}n=Qa+ -29|0;if((Ub|0)==0){Qa=n;Ra=Vb}else{Wb=n;Xb=Ub;Yb=Vb;break}}}else{if((Lb|0)==18){Zb=Kb;_b=Mb}else{$b=Jb;ac=Kb;bc=Lb;cc=Mb;break}while(1){if(!((c[Pa>>2]|0)>>>0<9007199)){$b=Jb;ac=Zb;bc=18;cc=_b;break f}Ra=0;Qa=_b+127|0;n=_b;while(1){Ta=Qa&127;o=h+(Ta<<2)|0;Na=Gg(c[o>>2]|0,0,29)|0;Ma=Ig(Na|0,E|0,Ra|0,0)|0;Na=E;if(Na>>>0>0|(Na|0)==0&Ma>>>0>1e9){ma=Ug(Ma|0,Na|0,1e9,0)|0;va=Vg(Ma|0,Na|0,1e9,0)|0;dc=va;ec=ma}else{dc=Ma;ec=0}c[o>>2]=dc;o=(Ta|0)==(Jb|0);if((Ta|0)!=(n+127&127|0)|o){fc=n}else{fc=(dc|0)==0?Ta:n}if(o){break}else{Ra=ec;Qa=Ta+ -1|0;n=fc}}n=Zb+ -29|0;if((ec|0)==0){Zb=n;_b=fc}else{Wb=n;Xb=ec;Yb=fc;break}}}Pa=Jb+127&127;if((Pa|0)==(Yb|0)){n=Yb+127&127;Qa=h+((Yb+126&127)<<2)|0;c[Qa>>2]=c[Qa>>2]|c[h+(n<<2)>>2];gc=n}else{gc=Yb}c[h+(Pa<<2)>>2]=Xb;Jb=Pa;Kb=Wb;Lb=Lb+9|0;Mb=gc}g:while(1){hc=cc+1&127;Ua=h+((cc+127&127)<<2)|0;Pa=$b;n=ac;Qa=bc;while(1){Ra=(Qa|0)==18;Ta=(Qa|0)>27?9:1;ic=Pa;jc=n;while(1){o=0;while(1){Ma=o+ic&127;if((Ma|0)==(cc|0)){kc=2;break}ma=c[h+(Ma<<2)>>2]|0;Ma=c[28176+(o<<2)>>2]|0;if(ma>>>0>>0){kc=2;break}va=o+1|0;if(ma>>>0>Ma>>>0){kc=o;break}if((va|0)<2){o=va}else{kc=va;break}}if((kc|0)==2&Ra){break g}lc=Ta+jc|0;if((ic|0)==(cc|0)){ic=cc;jc=lc}else{break}}Ra=(1<>>Ta;mc=ic;nc=0;va=ic;oc=Qa;do{Ma=h+(va<<2)|0;ma=c[Ma>>2]|0;Na=(ma>>>Ta)+nc|0;c[Ma>>2]=Na;nc=aa(ma&Ra,o)|0;ma=(va|0)==(mc|0)&(Na|0)==0;va=va+1&127;oc=ma?oc+ -9|0:oc;mc=ma?va:mc}while((va|0)!=(cc|0));if((nc|0)==0){Pa=mc;n=lc;Qa=oc;continue}if((hc|0)!=(mc|0)){break}c[Ua>>2]=c[Ua>>2]|1;Pa=mc;n=lc;Qa=oc}c[h+(cc<<2)>>2]=nc;$b=mc;ac=lc;bc=oc;cc=hc}Qa=ic&127;if((Qa|0)==(cc|0)){c[h+(hc+ -1<<2)>>2]=0;pc=hc}else{pc=cc}ua=+((c[h+(Qa<<2)>>2]|0)>>>0);Qa=ic+1&127;if((Qa|0)==(pc|0)){n=pc+1&127;c[h+(n+ -1<<2)>>2]=0;qc=n}else{qc=pc}fa=+(r|0);rc=fa*(ua*1.0e9+ +((c[h+(Qa<<2)>>2]|0)>>>0));Qa=jc+53|0;n=Qa-k|0;if((n|0)<(j|0)){sc=(n|0)<0?0:n;tc=1}else{sc=j;tc=0}if((sc|0)<53){ua=+Va(+(+qg(1.0,105-sc|0)),+rc);uc=+qa(+rc,+(+qg(1.0,53-sc|0)));vc=ua;wc=uc;xc=ua+(rc-uc)}else{vc=0.0;wc=0.0;xc=rc}Pa=ic+2&127;if((Pa|0)!=(qc|0)){Ua=c[h+(Pa<<2)>>2]|0;do{if(!(Ua>>>0<5e8)){if(Ua>>>0>5e8){yc=fa*.75+wc;break}if((ic+3&127|0)==(qc|0)){yc=fa*.5+wc;break}else{yc=fa*.75+wc;break}}else{if((Ua|0)==0?(ic+3&127|0)==(qc|0):0){yc=wc;break}yc=fa*.25+wc}}while(0);if((53-sc|0)>1?!(+qa(+yc,1.0)!=0.0):0){zc=yc+1.0}else{zc=yc}}else{zc=wc}fa=xc+zc-vc;do{if((Qa&2147483647|0)>(-2-la|0)){if(!(+P(+fa)>=9007199254740992.0)){Ac=tc;Bc=jc;Cc=fa}else{Ac=(tc|0)!=0&(sc|0)==(n|0)?0:tc;Bc=jc+1|0;Cc=fa*.5}if((Bc+50|0)<=(na|0)?!((Ac|0)!=0&zc!=0.0):0){Dc=Bc;Ec=Cc;break}c[(Sa()|0)>>2]=34;Dc=Bc;Ec=Cc}else{Dc=jc;Ec=fa}}while(0);l=+rg(Ec,Dc);i=g;return+l}else if((z|0)==3){na=c[e>>2]|0;if(na>>>0<(c[m>>2]|0)>>>0){c[e>>2]=na+1;Fc=d[na]|0}else{Fc=pg(b)|0}if((Fc|0)==40){Gc=1}else{if((c[m>>2]|0)==0){l=t;i=g;return+l}c[e>>2]=(c[e>>2]|0)+ -1;l=t;i=g;return+l}while(1){na=c[e>>2]|0;if(na>>>0<(c[m>>2]|0)>>>0){c[e>>2]=na+1;Hc=d[na]|0}else{Hc=pg(b)|0}if(!((Hc+ -48|0)>>>0<10|(Hc+ -65|0)>>>0<26)?!((Hc+ -97|0)>>>0<26|(Hc|0)==95):0){break}Gc=Gc+1|0}if((Hc|0)==41){l=t;i=g;return+l}na=(c[m>>2]|0)==0;if(!na){c[e>>2]=(c[e>>2]|0)+ -1}if(w){c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}if((Gc|0)==0|na){l=t;i=g;return+l}else{Ic=Gc}while(1){na=Ic+ -1|0;c[e>>2]=(c[e>>2]|0)+ -1;if((na|0)==0){l=t;break}else{Ic=na}}i=g;return+l}else{if((c[m>>2]|0)!=0){c[e>>2]=(c[e>>2]|0)+ -1}c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}}}while(0);if((x|0)==23){x=(c[m>>2]|0)==0;if(!x){c[e>>2]=(c[e>>2]|0)+ -1}if(!(v>>>0<4|(f|0)==0|x)){x=v;do{c[e>>2]=(c[e>>2]|0)+ -1;x=x+ -1|0}while(x>>>0>3)}}l=+(r|0)*u;i=g;return+l}function ng(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;e=i;f=a+4|0;g=c[f>>2]|0;h=a+100|0;if(g>>>0<(c[h>>2]|0)>>>0){c[f>>2]=g+1;j=d[g]|0}else{j=pg(a)|0}if((j|0)==43|(j|0)==45){g=(j|0)==45|0;k=c[f>>2]|0;if(k>>>0<(c[h>>2]|0)>>>0){c[f>>2]=k+1;l=d[k]|0}else{l=pg(a)|0}if(!((l+ -48|0)>>>0<10|(b|0)==0)?(c[h>>2]|0)!=0:0){c[f>>2]=(c[f>>2]|0)+ -1;m=l;n=g}else{m=l;n=g}}else{m=j;n=0}if((m+ -48|0)>>>0>9){if((c[h>>2]|0)==0){o=-2147483648;p=0;E=o;i=e;return p|0}c[f>>2]=(c[f>>2]|0)+ -1;o=-2147483648;p=0;E=o;i=e;return p|0}else{q=m;r=0}while(1){s=q+ -48+r|0;m=c[f>>2]|0;if(m>>>0<(c[h>>2]|0)>>>0){c[f>>2]=m+1;t=d[m]|0}else{t=pg(a)|0}if(!((t+ -48|0)>>>0<10&(s|0)<214748364)){break}q=t;r=s*10|0}r=((s|0)<0)<<31>>31;if((t+ -48|0)>>>0<10){q=s;m=r;j=t;while(1){g=Tg(q|0,m|0,10,0)|0;l=E;b=Ig(j|0,((j|0)<0)<<31>>31|0,-48,-1)|0;k=Ig(b|0,E|0,g|0,l|0)|0;l=E;g=c[f>>2]|0;if(g>>>0<(c[h>>2]|0)>>>0){c[f>>2]=g+1;u=d[g]|0}else{u=pg(a)|0}if((u+ -48|0)>>>0<10&((l|0)<21474836|(l|0)==21474836&k>>>0<2061584302)){q=k;m=l;j=u}else{v=k;w=l;x=u;break}}}else{v=s;w=r;x=t}if((x+ -48|0)>>>0<10){do{x=c[f>>2]|0;if(x>>>0<(c[h>>2]|0)>>>0){c[f>>2]=x+1;y=d[x]|0}else{y=pg(a)|0}}while((y+ -48|0)>>>0<10)}if((c[h>>2]|0)!=0){c[f>>2]=(c[f>>2]|0)+ -1}f=(n|0)!=0;n=Cg(0,0,v|0,w|0)|0;o=f?E:w;p=f?n:v;E=o;i=e;return p|0}function og(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;c[a+104>>2]=b;e=c[a+8>>2]|0;f=c[a+4>>2]|0;g=e-f|0;c[a+108>>2]=g;if((b|0)!=0&(g|0)>(b|0)){c[a+100>>2]=f+b;i=d;return}else{c[a+100>>2]=e;i=d;return}}function pg(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;f=b+104|0;g=c[f>>2]|0;if(!((g|0)!=0?(c[b+108>>2]|0)>=(g|0):0)){h=3}if((h|0)==3?(h=tg(b)|0,(h|0)>=0):0){g=c[f>>2]|0;f=c[b+8>>2]|0;if((g|0)!=0?(j=c[b+4>>2]|0,k=g-(c[b+108>>2]|0)+ -1|0,(f-j|0)>(k|0)):0){c[b+100>>2]=j+k}else{c[b+100>>2]=f}k=c[b+4>>2]|0;if((f|0)!=0){j=b+108|0;c[j>>2]=f+1-k+(c[j>>2]|0)}j=k+ -1|0;if((d[j]|0|0)==(h|0)){l=h;i=e;return l|0}a[j]=h;l=h;i=e;return l|0}c[b+100>>2]=0;l=-1;i=e;return l|0}function qg(a,b){a=+a;b=b|0;var d=0,e=0.0,f=0,g=0,j=0,l=0.0;d=i;if((b|0)>1023){e=a*8.98846567431158e+307;f=b+ -1023|0;if((f|0)>1023){g=b+ -2046|0;j=(g|0)>1023?1023:g;l=e*8.98846567431158e+307}else{j=f;l=e}}else{if((b|0)<-1022){e=a*2.2250738585072014e-308;f=b+1022|0;if((f|0)<-1022){g=b+2044|0;j=(g|0)<-1022?-1022:g;l=e*2.2250738585072014e-308}else{j=f;l=e}}else{j=b;l=a}}b=Gg(j+1023|0,0,52)|0;j=E;c[k>>2]=b;c[k+4>>2]=j;a=l*+h[k>>3];i=d;return+a}function rg(a,b){a=+a;b=b|0;var c=0,d=0.0;c=i;d=+qg(a,b);i=c;return+d}function sg(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;e=b+74|0;f=a[e]|0;a[e]=f+255|f;f=b+20|0;e=b+44|0;if((c[f>>2]|0)>>>0>(c[e>>2]|0)>>>0){kb[c[b+36>>2]&1](b,0,0)|0}c[b+16>>2]=0;c[b+28>>2]=0;c[f>>2]=0;f=c[b>>2]|0;if((f&20|0)==0){g=c[e>>2]|0;c[b+8>>2]=g;c[b+4>>2]=g;h=0;i=d;return h|0}if((f&4|0)==0){h=-1;i=d;return h|0}c[b>>2]=f|32;h=-1;i=d;return h|0}function tg(a){a=a|0;var b=0,e=0,f=0;b=i;i=i+16|0;e=b;if((c[a+8>>2]|0)==0?(sg(a)|0)!=0:0){f=-1}else{if((kb[c[a+32>>2]&1](a,e,1)|0)==1){f=d[e]|0}else{f=-1}}i=b;return f|0}function ug(a){a=a|0;var b=0,c=0.0;b=i;c=+wg(a,0);i=b;return+c}function vg(b){b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;c=i;d=b;while(1){e=d+1|0;if((fb(a[d]|0)|0)==0){break}else{d=e}}b=a[d]|0;f=b<<24>>24;if((f|0)==45){g=1;h=5}else if((f|0)==43){g=0;h=5}else{j=d;k=b;l=0}if((h|0)==5){j=e;k=a[e]|0;l=g}if((cb(k<<24>>24|0)|0)==0){m=0;n=(l|0)!=0;o=0-m|0;p=n?m:o;i=c;return p|0}else{q=j;r=0}while(1){j=q+1|0;k=(r*10|0)+48-(a[q]|0)|0;if((cb(a[j]|0)|0)==0){m=k;break}else{q=j;r=k}}n=(l|0)!=0;o=0-m|0;p=n?m:o;i=c;return p|0}function wg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0.0,j=0,k=0;d=i;i=i+112|0;e=d;f=e+0|0;g=f+112|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(g|0));f=e+4|0;c[f>>2]=a;g=e+8|0;c[g>>2]=-1;c[e+44>>2]=a;c[e+76>>2]=-1;og(e,0);h=+mg(e,1,1);j=(c[f>>2]|0)-(c[g>>2]|0)+(c[e+108>>2]|0)|0;if((b|0)==0){i=d;return+h}if((j|0)==0){k=a}else{k=a+j|0}c[b>>2]=k;i=d;return+h}function xg(b,c){b=b|0;c=c|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;f=a[b]|0;a:do{if(f<<24>>24==0){g=0;h=c}else{j=f;k=f&255;l=b;m=c;while(1){n=a[m]|0;if(n<<24>>24==0){g=j;h=m;break a}if(!(j<<24>>24==n<<24>>24)?(n=Jg(k|0)|0,(n|0)!=(Jg(d[m]|0|0)|0)):0){break}n=l+1|0;o=m+1|0;p=a[n]|0;if(p<<24>>24==0){g=0;h=o;break a}else{j=p;k=p&255;l=n;m=o}}g=a[l]|0;h=m}}while(0);c=Jg(g&255|0)|0;g=c-(Jg(d[h]|0|0)|0)|0;i=e;return g|0}function yg(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;e=a[b]|0;f=a[c]|0;if(e<<24>>24!=f<<24>>24|e<<24>>24==0|f<<24>>24==0){g=e;h=f;j=g&255;k=h&255;l=j-k|0;i=d;return l|0}else{m=b;n=c}while(1){c=m+1|0;b=n+1|0;f=a[c]|0;e=a[b]|0;if(f<<24>>24!=e<<24>>24|f<<24>>24==0|e<<24>>24==0){g=f;h=e;break}else{m=c;n=b}}j=g&255;k=h&255;l=j-k|0;i=d;return l|0}function zg(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;if((e|0)==0){g=0;i=f;return g|0}h=a[b]|0;a:do{if(h<<24>>24==0){j=0;k=c}else{l=e;m=h;n=h&255;o=b;p=c;while(1){q=l+ -1|0;r=a[p]|0;if(r<<24>>24==0|(q|0)==0){j=m;k=p;break a}if(!(m<<24>>24==r<<24>>24)?(r=Jg(n|0)|0,(r|0)!=(Jg(d[p]|0|0)|0)):0){break}r=o+1|0;s=p+1|0;t=a[r]|0;if(t<<24>>24==0){j=0;k=s;break a}else{l=q;m=t;n=t&255;o=r;p=s}}j=a[o]|0;k=p}}while(0);c=Jg(j&255|0)|0;g=c-(Jg(d[k]|0|0)|0)|0;i=f;return g|0}function Ag(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;f=i;if((e|0)==0){g=0;i=f;return g|0}h=a[b]|0;a:do{if(h<<24>>24==0){j=0;k=c}else{l=e;m=h;n=b;o=c;while(1){p=l+ -1|0;q=a[o]|0;if(!((p|0)!=0&q<<24>>24!=0&m<<24>>24==q<<24>>24)){j=m;k=o;break a}q=n+1|0;r=o+1|0;s=a[q]|0;if(s<<24>>24==0){j=0;k=r;break}else{l=p;m=s;n=q;o=r}}}}while(0);g=(j&255)-(d[k]|0)|0;i=f;return g|0}function Bg(){}function Cg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=b-d>>>0;e=b-d-(c>>>0>a>>>0|0)>>>0;return(E=e,a-c>>>0|0)|0}function Dg(b){b=b|0;var c=0;c=b;while(a[c]|0){c=c+1|0}return c-b|0}function Eg(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0)>=20){d=d&255;g=b&3;h=d|d<<8|d<<16|d<<24;i=f&~3;if(g){g=b+4-g|0;while((b|0)<(g|0)){a[b]=d;b=b+1|0}}while((b|0)<(i|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b]=d;b=b+1|0}return b-e|0}function Fg(b,c){b=b|0;c=c|0;var d=0,e=0;d=b+(Dg(b)|0)|0;do{a[d+e|0]=a[c+e|0];e=e+1|0}while(a[c+(e-1)|0]|0);return b|0}function Gg(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b<>>32-c;return a<>>0;return(E=b+d+(e>>>0>>0|0)>>>0,e|0)|0}function Jg(a){a=a|0;if((a|0)<65)return a|0;if((a|0)>90)return a|0;return a-65+97|0}function Kg(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return Ga(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if((e|0)==0)return f|0;a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function Lg(b,c){b=b|0;c=c|0;var d=0;do{a[b+d|0]=a[c+d|0];d=d+1|0}while(a[c+(d-1)|0]|0);return b|0}function Mg(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b>>>c;return a>>>c|(b&(1<>>c-32|0}function Ng(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b>>c;return a>>>c|(b&(1<>c-32|0}function Og(b){b=b|0;var c=0;c=a[n+(b>>>24)|0]|0;if((c|0)<8)return c|0;c=a[n+(b>>16&255)|0]|0;if((c|0)<8)return c+8|0;c=a[n+(b>>8&255)|0]|0;if((c|0)<8)return c+16|0;return(a[n+(b&255)|0]|0)+24|0}function Pg(b){b=b|0;var c=0;c=a[m+(b&255)|0]|0;if((c|0)<8)return c|0;c=a[m+(b>>8&255)|0]|0;if((c|0)<8)return c+8|0;c=a[m+(b>>16&255)|0]|0;if((c|0)<8)return c+16|0;return(a[m+(b>>>24)|0]|0)+24|0}function Qg(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=a&65535;d=b&65535;e=aa(d,c)|0;f=a>>>16;a=(e>>>16)+(aa(d,f)|0)|0;d=b>>>16;b=aa(d,c)|0;return(E=(a>>>16)+(aa(d,f)|0)+(((a&65535)+b|0)>>>16)|0,a+b<<16|e&65535|0)|0}function Rg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;e=b>>31|((b|0)<0?-1:0)<<1;f=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;g=d>>31|((d|0)<0?-1:0)<<1;h=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;i=Cg(e^a,f^b,e,f)|0;b=E;a=g^e;e=h^f;f=Cg((Wg(i,b,Cg(g^c,h^d,g,h)|0,E,0)|0)^a,E^e,a,e)|0;return f|0}function Sg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+8|0;g=f|0;h=b>>31|((b|0)<0?-1:0)<<1;j=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;k=e>>31|((e|0)<0?-1:0)<<1;l=((e|0)<0?-1:0)>>31|((e|0)<0?-1:0)<<1;m=Cg(h^a,j^b,h,j)|0;b=E;Wg(m,b,Cg(k^d,l^e,k,l)|0,E,g)|0;l=Cg(c[g>>2]^h,c[g+4>>2]^j,h,j)|0;j=E;i=f;return(E=j,l)|0}function Tg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;a=c;c=Qg(e,a)|0;f=E;return(E=(aa(b,a)|0)+(aa(d,e)|0)+f|f&0,c|0|0)|0}function Ug(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=Wg(a,b,c,d,0)|0;return e|0}function Vg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=i;i=i+8|0;g=f|0;Wg(a,b,d,e,g)|0;i=f;return(E=c[g+4>>2]|0,c[g>>2]|0)|0}function Wg(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;g=a;h=b;i=h;j=d;k=e;l=k;if((i|0)==0){m=(f|0)!=0;if((l|0)==0){if(m){c[f>>2]=(g>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(g>>>0)/(j>>>0)>>>0;return(E=n,o)|0}else{if(!m){n=0;o=0;return(E=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;n=0;o=0;return(E=n,o)|0}}m=(l|0)==0;do{if((j|0)!=0){if(!m){p=(Og(l|0)|0)-(Og(i|0)|0)|0;if(p>>>0<=31){q=p+1|0;r=31-p|0;s=p-31>>31;t=q;u=g>>>(q>>>0)&s|i<>>(q>>>0)&s;w=0;x=g<>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return(E=n,o)|0}r=j-1|0;if((r&j|0)!=0){s=(Og(j|0)|0)+33-(Og(i|0)|0)|0;q=64-s|0;p=32-s|0;y=p>>31;z=s-32|0;A=z>>31;t=s;u=p-1>>31&i>>>(z>>>0)|(i<>>(s>>>0))&A;v=A&i>>>(s>>>0);w=g<>>(z>>>0))&y|g<>31;break}if((f|0)!=0){c[f>>2]=r&g;c[f+4>>2]=0}if((j|0)==1){n=h|b&0;o=a|0|0;return(E=n,o)|0}else{r=Pg(j|0)|0;n=i>>>(r>>>0)|0;o=i<<32-r|g>>>(r>>>0)|0;return(E=n,o)|0}}else{if(m){if((f|0)!=0){c[f>>2]=(i>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(i>>>0)/(j>>>0)>>>0;return(E=n,o)|0}if((g|0)==0){if((f|0)!=0){c[f>>2]=0;c[f+4>>2]=(i>>>0)%(l>>>0)}n=0;o=(i>>>0)/(l>>>0)>>>0;return(E=n,o)|0}r=l-1|0;if((r&l|0)==0){if((f|0)!=0){c[f>>2]=a|0;c[f+4>>2]=r&i|b&0}n=0;o=i>>>((Pg(l|0)|0)>>>0);return(E=n,o)|0}r=(Og(l|0)|0)-(Og(i|0)|0)|0;if(r>>>0<=30){s=r+1|0;p=31-r|0;t=s;u=i<>>(s>>>0);v=i>>>(s>>>0);w=0;x=g<>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return(E=n,o)|0}}while(0);if((t|0)==0){B=x;C=w;D=v;F=u;G=0;H=0}else{b=d|0|0;d=k|e&0;e=Ig(b,d,-1,-1)|0;k=E;h=x;x=w;w=v;v=u;u=t;t=0;while(1){I=x>>>31|h<<1;J=t|x<<1;a=v<<1|h>>>31|0;g=v>>>31|w<<1|0;Cg(e,k,a,g)|0;i=E;l=i>>31|((i|0)<0?-1:0)<<1;K=l&1;L=Cg(a,g,l&b,(((i|0)<0?-1:0)>>31|((i|0)<0?-1:0)<<1)&d)|0;M=E;i=u-1|0;if((i|0)==0){break}else{h=I;x=J;w=M;v=L;u=i;t=K}}B=I;C=J;D=M;F=L;G=0;H=K}K=C;C=0;if((f|0)!=0){c[f>>2]=F;c[f+4>>2]=D}n=(K|0)>>>31|(B|C)<<1|(C<<1|K>>>31)&0|G;o=(K<<1|0>>>31)&-2|H;return(E=n,o)|0}function Xg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return kb[a&1](b|0,c|0,d|0)|0}function Yg(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=d|0;e=e|0;f=f|0;return lb[a&63](+b,+c,d|0,e|0,f|0)|0}function Zg(a,b,c){a=a|0;b=b|0;c=c|0;mb[a&1](b|0,c|0)}function _g(a,b,c){a=a|0;b=b|0;c=c|0;return nb[a&7](b|0,c|0)|0}function $g(a,b,c){a=a|0;b=b|0;c=c|0;ba(0);return 0}function ah(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;ba(1);return 0}function bh(a,b){a=a|0;b=b|0;ba(2)}function ch(a,b){a=a|0;b=b|0;ba(3);return 0} + + + + +// EMSCRIPTEN_END_FUNCS +var kb=[$g,Xf];var lb=[ah,Ud,Vd,Xd,Yd,Zd,_d,$d,ae,de,ee,fe,ge,he,ie,je,ke,le,me,ne,oe,pe,qe,re,se,te,ue,ve,we,He,Ie,Je,Ke,Le,Me,Ne,Oe,Qd,Rd,Sd,Td,be,ce,xe,ye,ze,Ae,Be,Ce,De,Ee,Fe,Ge,ah,ah,ah,ah,ah,ah,ah,ah,ah,ah,ah];var mb=[bh,Yf];var nb=[ch,nf,of,pf,ef,ch,ch,ch];return{_strlen:Dg,_strcat:Fg,_gzread:xf,_wcsunits:Ib,_zscale:Lb,_initwcs:Eb,_wcssys:Hb,_pix2wcsstr:Fb,_calloc:ig,_bitshift64Shl:Gg,_gzwrite:Cf,_saostrtod:Kb,_strncpy:Hg,_memset:Eg,_memcpy:Kg,_gzclose:rf,_i64Subtract:Cg,_realloc:jg,_i64Add:Ig,_wcs2pixstr:Gb,_gzopen:sf,_gzseek:wf,_free:hg,_tolower:Jg,_malloc:gg,_reg2wcsstr:Jb,_strcpy:Lg,runPostSets:Bg,stackAlloc:ob,stackSave:pb,stackRestore:qb,setThrew:rb,setTempRet0:ub,setTempRet1:vb,setTempRet2:wb,setTempRet3:xb,setTempRet4:yb,setTempRet5:zb,setTempRet6:Ab,setTempRet7:Bb,setTempRet8:Cb,setTempRet9:Db,dynCall_iiii:Xg,dynCall_iddiii:Yg,dynCall_vii:Zg,dynCall_iii:_g}}) + + +// EMSCRIPTEN_END_ASM +({ "Math": Math, "Int8Array": Int8Array, "Int16Array": Int16Array, "Int32Array": Int32Array, "Uint8Array": Uint8Array, "Uint16Array": Uint16Array, "Uint32Array": Uint32Array, "Float32Array": Float32Array, "Float64Array": Float64Array }, { "abort": abort, "assert": assert, "asmPrintInt": asmPrintInt, "asmPrintFloat": asmPrintFloat, "min": Math_min, "invoke_iiii": invoke_iiii, "invoke_iddiii": invoke_iddiii, "invoke_vii": invoke_vii, "invoke_iii": invoke_iii, "_fabs": _fabs, "_sin": _sin, "_exp": _exp, "_llvm_pow_f64": _llvm_pow_f64, "_acos": _acos, "_atan2": _atan2, "_fmod": _fmod, "_lseek": _lseek, "__reallyNegative": __reallyNegative, "_asin": _asin, "_atan": _atan, "___buildEnvironment": ___buildEnvironment, "_fflush": _fflush, "_pwrite": _pwrite, "_strerror_r": _strerror_r, "_fprintf": _fprintf, "_open": _open, "_fabsf": _fabsf, "_sbrk": _sbrk, "_send": _send, "_snprintf": _snprintf, "_llvm_bswap_i32": _llvm_bswap_i32, "_emscripten_memcpy_big": _emscripten_memcpy_big, "_fileno": _fileno, "_sysconf": _sysconf, "___setErrNo": ___setErrNo, "_cos": _cos, "_pread": _pread, "_printf": _printf, "_sprintf": _sprintf, "_log": _log, "_toupper": _toupper, "_write": _write, "_isupper": _isupper, "___errno_location": ___errno_location, "_recv": _recv, "_tan": _tan, "_copysign": _copysign, "_getenv": _getenv, "_mkport": _mkport, "__exit": __exit, "_read": _read, "_abort": _abort, "_islower": _islower, "_fwrite": _fwrite, "_time": _time, "_isdigit": _isdigit, "_strerror": _strerror, "__formatString": __formatString, "_isspace": _isspace, "_sqrt": _sqrt, "_exit": _exit, "_close": _close, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "cttz_i8": cttz_i8, "ctlz_i8": ctlz_i8, "NaN": NaN, "Infinity": Infinity, "_stderr": _stderr }, buffer); +var _strlen = Module["_strlen"] = asm["_strlen"]; +var _strcat = Module["_strcat"] = asm["_strcat"]; +var _gzread = Module["_gzread"] = asm["_gzread"]; +var _wcsunits = Module["_wcsunits"] = asm["_wcsunits"]; +var _zscale = Module["_zscale"] = asm["_zscale"]; +var _initwcs = Module["_initwcs"] = asm["_initwcs"]; +var _wcssys = Module["_wcssys"] = asm["_wcssys"]; +var _pix2wcsstr = Module["_pix2wcsstr"] = asm["_pix2wcsstr"]; +var _calloc = Module["_calloc"] = asm["_calloc"]; +var _bitshift64Shl = Module["_bitshift64Shl"] = asm["_bitshift64Shl"]; +var _gzwrite = Module["_gzwrite"] = asm["_gzwrite"]; +var _saostrtod = Module["_saostrtod"] = asm["_saostrtod"]; +var _strncpy = Module["_strncpy"] = asm["_strncpy"]; +var _memset = Module["_memset"] = asm["_memset"]; +var _memcpy = Module["_memcpy"] = asm["_memcpy"]; +var _gzclose = Module["_gzclose"] = asm["_gzclose"]; +var _i64Subtract = Module["_i64Subtract"] = asm["_i64Subtract"]; +var _realloc = Module["_realloc"] = asm["_realloc"]; +var _i64Add = Module["_i64Add"] = asm["_i64Add"]; +var _wcs2pixstr = Module["_wcs2pixstr"] = asm["_wcs2pixstr"]; +var _gzopen = Module["_gzopen"] = asm["_gzopen"]; +var _gzseek = Module["_gzseek"] = asm["_gzseek"]; +var _free = Module["_free"] = asm["_free"]; +var _tolower = Module["_tolower"] = asm["_tolower"]; +var _malloc = Module["_malloc"] = asm["_malloc"]; +var _reg2wcsstr = Module["_reg2wcsstr"] = asm["_reg2wcsstr"]; +var _strcpy = Module["_strcpy"] = asm["_strcpy"]; +var runPostSets = Module["runPostSets"] = asm["runPostSets"]; +var dynCall_iiii = Module["dynCall_iiii"] = asm["dynCall_iiii"]; +var dynCall_iddiii = Module["dynCall_iddiii"] = asm["dynCall_iddiii"]; +var dynCall_vii = Module["dynCall_vii"] = asm["dynCall_vii"]; +var dynCall_iii = Module["dynCall_iii"] = asm["dynCall_iii"]; + +Runtime.stackAlloc = function(size) { return asm['stackAlloc'](size) }; +Runtime.stackSave = function() { return asm['stackSave']() }; +Runtime.stackRestore = function(top) { asm['stackRestore'](top) }; + + +// TODO: strip out parts of this we do not need + +//======= begin closure i64 code ======= + +// Copyright 2009 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Defines a Long class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "long". This + * implementation is derived from LongLib in GWT. + * + */ + +var i64Math = (function() { // Emscripten wrapper + var goog = { math: {} }; + + + /** + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @param {number} low The low (signed) 32 bits of the long. + * @param {number} high The high (signed) 32 bits of the long. + * @constructor + */ + goog.math.Long = function(low, high) { + /** + * @type {number} + * @private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @private + */ + this.high_ = high | 0; // force into 32 signed bits. + }; + + + // NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the + // from* methods on which they depend. + + + /** + * A cache of the Long representations of small integer values. + * @type {!Object} + * @private + */ + goog.math.Long.IntCache_ = {}; + + + /** + * Returns a Long representing the given (32-bit) integer value. + * @param {number} value The 32-bit integer in question. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = goog.math.Long.IntCache_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new goog.math.Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + goog.math.Long.IntCache_[value] = obj; + } + return obj; + }; + + + /** + * Returns a Long representing the given value, provided that it is a finite + * number. Otherwise, zero is returned. + * @param {number} value The number in question. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return goog.math.Long.ZERO; + } else if (value <= -goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MIN_VALUE; + } else if (value + 1 >= goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MAX_VALUE; + } else if (value < 0) { + return goog.math.Long.fromNumber(-value).negate(); + } else { + return new goog.math.Long( + (value % goog.math.Long.TWO_PWR_32_DBL_) | 0, + (value / goog.math.Long.TWO_PWR_32_DBL_) | 0); + } + }; + + + /** + * Returns a Long representing the 64-bit integer that comes by concatenating + * the given high and low bits. Each is assumed to use 32 bits. + * @param {number} lowBits The low 32-bits. + * @param {number} highBits The high 32-bits. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromBits = function(lowBits, highBits) { + return new goog.math.Long(lowBits, highBits); + }; + + + /** + * Returns a Long representation of the given string, written using the given + * radix. + * @param {string} str The textual representation of the Long. + * @param {number=} opt_radix The radix in which the text is written. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return goog.math.Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 8)); + + var result = goog.math.Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = goog.math.Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(goog.math.Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(goog.math.Long.fromNumber(value)); + } + } + return result; + }; + + + // NOTE: the compiler should inline these constant values below and then remove + // these variables, so there should be no runtime penalty for these. + + + /** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_16_DBL_ = 1 << 16; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_24_DBL_ = 1 << 24; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_32_DBL_ = + goog.math.Long.TWO_PWR_16_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_31_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ / 2; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_48_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_64_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_32_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_63_DBL_ = + goog.math.Long.TWO_PWR_64_DBL_ / 2; + + + /** @type {!goog.math.Long} */ + goog.math.Long.ZERO = goog.math.Long.fromInt(0); + + + /** @type {!goog.math.Long} */ + goog.math.Long.ONE = goog.math.Long.fromInt(1); + + + /** @type {!goog.math.Long} */ + goog.math.Long.NEG_ONE = goog.math.Long.fromInt(-1); + + + /** @type {!goog.math.Long} */ + goog.math.Long.MAX_VALUE = + goog.math.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + + + /** @type {!goog.math.Long} */ + goog.math.Long.MIN_VALUE = goog.math.Long.fromBits(0, 0x80000000 | 0); + + + /** + * @type {!goog.math.Long} + * @private + */ + goog.math.Long.TWO_PWR_24_ = goog.math.Long.fromInt(1 << 24); + + + /** @return {number} The value, assuming it is a 32-bit integer. */ + goog.math.Long.prototype.toInt = function() { + return this.low_; + }; + + + /** @return {number} The closest floating-point representation to this value. */ + goog.math.Long.prototype.toNumber = function() { + return this.high_ * goog.math.Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); + }; + + + /** + * @param {number=} opt_radix The radix in which the text should be written. + * @return {string} The textual representation of this value. + */ + goog.math.Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = goog.math.Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } + }; + + + /** @return {number} The high 32-bits as a signed value. */ + goog.math.Long.prototype.getHighBits = function() { + return this.high_; + }; + + + /** @return {number} The low 32-bits as a signed value. */ + goog.math.Long.prototype.getLowBits = function() { + return this.low_; + }; + + + /** @return {number} The low 32-bits as an unsigned value. */ + goog.math.Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : goog.math.Long.TWO_PWR_32_DBL_ + this.low_; + }; + + + /** + * @return {number} Returns the number of bits needed to represent the absolute + * value of this Long. + */ + goog.math.Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } + }; + + + /** @return {boolean} Whether this value is zero. */ + goog.math.Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; + }; + + + /** @return {boolean} Whether this value is negative. */ + goog.math.Long.prototype.isNegative = function() { + return this.high_ < 0; + }; + + + /** @return {boolean} Whether this value is odd. */ + goog.math.Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long equals the other. + */ + goog.math.Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long does not equal the other. + */ + goog.math.Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than the other. + */ + goog.math.Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than or equal to the other. + */ + goog.math.Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than the other. + */ + goog.math.Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than or equal to the other. + */ + goog.math.Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; + }; + + + /** + * Compares this Long with the given one. + * @param {goog.math.Long} other Long to compare against. + * @return {number} 0 if they are the same, 1 if the this is greater, and -1 + * if the given one is greater. + */ + goog.math.Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } + }; + + + /** @return {!goog.math.Long} The negation of this value. */ + goog.math.Long.prototype.negate = function() { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.MIN_VALUE; + } else { + return this.not().add(goog.math.Long.ONE); + } + }; + + + /** + * Returns the sum of this and the given Long. + * @param {goog.math.Long} other Long to add to this one. + * @return {!goog.math.Long} The sum of this and the given Long. + */ + goog.math.Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); + }; + + + /** + * Returns the difference of this and the given Long. + * @param {goog.math.Long} other Long to subtract from this. + * @return {!goog.math.Long} The difference of this and the given Long. + */ + goog.math.Long.prototype.subtract = function(other) { + return this.add(other.negate()); + }; + + + /** + * Returns the product of this and the given long. + * @param {goog.math.Long} other Long to multiply with this. + * @return {!goog.math.Long} The product of this and the other. + */ + goog.math.Long.prototype.multiply = function(other) { + if (this.isZero()) { + return goog.math.Long.ZERO; + } else if (other.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + return other.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return this.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both longs are small, use float multiplication + if (this.lessThan(goog.math.Long.TWO_PWR_24_) && + other.lessThan(goog.math.Long.TWO_PWR_24_)) { + return goog.math.Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); + }; + + + /** + * Returns this Long divided by the given one. + * @param {goog.math.Long} other Long by which to divide. + * @return {!goog.math.Long} This Long divided by the given one. + */ + goog.math.Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + if (other.equals(goog.math.Long.ONE) || + other.equals(goog.math.Long.NEG_ONE)) { + return goog.math.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(goog.math.Long.ZERO)) { + return other.isNegative() ? goog.math.Long.ONE : goog.math.Long.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = goog.math.Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = goog.math.Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = goog.math.Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = goog.math.Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; + }; + + + /** + * Returns this Long modulo the given one. + * @param {goog.math.Long} other Long by which to mod. + * @return {!goog.math.Long} This Long modulo the given one. + */ + goog.math.Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); + }; + + + /** @return {!goog.math.Long} The bitwise-NOT of this value. */ + goog.math.Long.prototype.not = function() { + return goog.math.Long.fromBits(~this.low_, ~this.high_); + }; + + + /** + * Returns the bitwise-AND of this Long and the given one. + * @param {goog.math.Long} other The Long with which to AND. + * @return {!goog.math.Long} The bitwise-AND of this and the other. + */ + goog.math.Long.prototype.and = function(other) { + return goog.math.Long.fromBits(this.low_ & other.low_, + this.high_ & other.high_); + }; + + + /** + * Returns the bitwise-OR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to OR. + * @return {!goog.math.Long} The bitwise-OR of this and the other. + */ + goog.math.Long.prototype.or = function(other) { + return goog.math.Long.fromBits(this.low_ | other.low_, + this.high_ | other.high_); + }; + + + /** + * Returns the bitwise-XOR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to XOR. + * @return {!goog.math.Long} The bitwise-XOR of this and the other. + */ + goog.math.Long.prototype.xor = function(other) { + return goog.math.Long.fromBits(this.low_ ^ other.low_, + this.high_ ^ other.high_); + }; + + + /** + * Returns this Long with bits shifted to the left by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the left by the given amount. + */ + goog.math.Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return goog.math.Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return goog.math.Long.fromBits(0, low << (numBits - 32)); + } + } + }; + + + /** + * Returns this Long with bits shifted to the right by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount. + */ + goog.math.Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return goog.math.Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } + }; + + + /** + * Returns this Long with bits shifted to the right by the given amount, with + * the new top bits matching the current sign bit. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount, with + * zeros placed into the new leading bits. + */ + goog.math.Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return goog.math.Long.fromBits(high, 0); + } else { + return goog.math.Long.fromBits(high >>> (numBits - 32), 0); + } + } + }; + + //======= begin jsbn ======= + + var navigator = { appName: 'Modern Browser' }; // polyfill a little + + // Copyright (c) 2005 Tom Wu + // All Rights Reserved. + // http://www-cs-students.stanford.edu/~tjw/jsbn/ + + /* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ + + // Basic JavaScript BN library - subset useful for RSA encryption. + + // Bits per digit + var dbits; + + // JavaScript engine analysis + var canary = 0xdeadbeefcafe; + var j_lm = ((canary&0xffffff)==0xefcafe); + + // (public) Constructor + function BigInteger(a,b,c) { + if(a != null) + if("number" == typeof a) this.fromNumber(a,b,c); + else if(b == null && "string" != typeof a) this.fromString(a,256); + else this.fromString(a,b); + } + + // return new, unset BigInteger + function nbi() { return new BigInteger(null); } + + // am: Compute w_j += (x*this_i), propagate carries, + // c is initial carry, returns final carry. + // c < 3*dvalue, x < 2*dvalue, this_i < dvalue + // We need to select the fastest one that works in this environment. + + // am1: use a single mult and divide to get the high bits, + // max digit bits should be 26 because + // max internal value = 2*dvalue^2-2*dvalue (< 2^53) + function am1(i,x,w,j,c,n) { + while(--n >= 0) { + var v = x*this[i++]+w[j]+c; + c = Math.floor(v/0x4000000); + w[j++] = v&0x3ffffff; + } + return c; + } + // am2 avoids a big mult-and-extract completely. + // Max digit bits should be <= 30 because we do bitwise ops + // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) + function am2(i,x,w,j,c,n) { + var xl = x&0x7fff, xh = x>>15; + while(--n >= 0) { + var l = this[i]&0x7fff; + var h = this[i++]>>15; + var m = xh*l+h*xl; + l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); + c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); + w[j++] = l&0x3fffffff; + } + return c; + } + // Alternately, set max digit bits to 28 since some + // browsers slow down when dealing with 32-bit numbers. + function am3(i,x,w,j,c,n) { + var xl = x&0x3fff, xh = x>>14; + while(--n >= 0) { + var l = this[i]&0x3fff; + var h = this[i++]>>14; + var m = xh*l+h*xl; + l = xl*l+((m&0x3fff)<<14)+w[j]+c; + c = (l>>28)+(m>>14)+xh*h; + w[j++] = l&0xfffffff; + } + return c; + } + if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { + BigInteger.prototype.am = am2; + dbits = 30; + } + else if(j_lm && (navigator.appName != "Netscape")) { + BigInteger.prototype.am = am1; + dbits = 26; + } + else { // Mozilla/Netscape seems to prefer am3 + BigInteger.prototype.am = am3; + dbits = 28; + } + + BigInteger.prototype.DB = dbits; + BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; + r.t = this.t; + r.s = this.s; + } + + // (protected) set from integer value x, -DV <= x < DV + function bnpFromInt(x) { + this.t = 1; + this.s = (x<0)?-1:0; + if(x > 0) this[0] = x; + else if(x < -1) this[0] = x+DV; + else this.t = 0; + } + + // return bigint initialized to value + function nbv(i) { var r = nbi(); r.fromInt(i); return r; } + + // (protected) set from string and radix + function bnpFromString(s,b) { + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 256) k = 8; // byte array + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else { this.fromRadix(s,b); return; } + this.t = 0; + this.s = 0; + var i = s.length, mi = false, sh = 0; + while(--i >= 0) { + var x = (k==8)?s[i]&0xff:intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if(sh == 0) + this[this.t++] = x; + else if(sh+k > this.DB) { + this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); + } + else + this[this.t-1] |= x<= this.DB) sh -= this.DB; + } + if(k == 8 && (s[0]&0x80) != 0) { + this.s = -1; + if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; + } + + // (public) return string representation in given radix + function bnToString(b) { + if(this.s < 0) return "-"+this.negate().toString(b); + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else return this.toRadix(b); + var km = (1< 0) { + if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } + while(i >= 0) { + if(p < k) { + d = (this[i]&((1<>(p+=this.DB-k); + } + else { + d = (this[i]>>(p-=k))&km; + if(p <= 0) { p += this.DB; --i; } + } + if(d > 0) m = true; + if(m) r += int2char(d); + } + } + return m?r:"0"; + } + + // (public) -this + function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } + + // (public) |this| + function bnAbs() { return (this.s<0)?this.negate():this; } + + // (public) return + if this > a, - if this < a, 0 if equal + function bnCompareTo(a) { + var r = this.s-a.s; + if(r != 0) return r; + var i = this.t; + r = i-a.t; + if(r != 0) return (this.s<0)?-r:r; + while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; + return 0; + } + + // returns bit length of the integer x + function nbits(x) { + var r = 1, t; + if((t=x>>>16) != 0) { x = t; r += 16; } + if((t=x>>8) != 0) { x = t; r += 8; } + if((t=x>>4) != 0) { x = t; r += 4; } + if((t=x>>2) != 0) { x = t; r += 2; } + if((t=x>>1) != 0) { x = t; r += 1; } + return r; + } + + // (public) return the number of bits in "this" + function bnBitLength() { + if(this.t <= 0) return 0; + return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); + } + + // (protected) r = this << n*DB + function bnpDLShiftTo(n,r) { + var i; + for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; + for(i = n-1; i >= 0; --i) r[i] = 0; + r.t = this.t+n; + r.s = this.s; + } + + // (protected) r = this >> n*DB + function bnpDRShiftTo(n,r) { + for(var i = n; i < this.t; ++i) r[i-n] = this[i]; + r.t = Math.max(this.t-n,0); + r.s = this.s; + } + + // (protected) r = this << n + function bnpLShiftTo(n,r) { + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<= 0; --i) { + r[i+ds+1] = (this[i]>>cbs)|c; + c = (this[i]&bm)<= 0; --i) r[i] = 0; + r[ds] = c; + r.t = this.t+ds+1; + r.s = this.s; + r.clamp(); + } + + // (protected) r = this >> n + function bnpRShiftTo(n,r) { + r.s = this.s; + var ds = Math.floor(n/this.DB); + if(ds >= this.t) { r.t = 0; return; } + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<>bs; + for(var i = ds+1; i < this.t; ++i) { + r[i-ds-1] |= (this[i]&bm)<>bs; + } + if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; + } + if(a.t < this.t) { + c -= a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c -= a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c<0)?-1:0; + if(c < -1) r[i++] = this.DV+c; + else if(c > 0) r[i++] = c; + r.t = i; + r.clamp(); + } + + // (protected) r = this * a, r != this,a (HAC 14.12) + // "this" should be the larger one if appropriate. + function bnpMultiplyTo(a,r) { + var x = this.abs(), y = a.abs(); + var i = x.t; + r.t = i+y.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); + r.s = 0; + r.clamp(); + if(this.s != a.s) BigInteger.ZERO.subTo(r,r); + } + + // (protected) r = this^2, r != this (HAC 14.16) + function bnpSquareTo(r) { + var x = this.abs(); + var i = r.t = 2*x.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < x.t-1; ++i) { + var c = x.am(i,x[i],r,2*i,0,1); + if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { + r[i+x.t] -= x.DV; + r[i+x.t+1] = 1; + } + } + if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); + r.s = 0; + r.clamp(); + } + + // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) + // r != q, this != m. q or r may be null. + function bnpDivRemTo(m,q,r) { + var pm = m.abs(); + if(pm.t <= 0) return; + var pt = this.abs(); + if(pt.t < pm.t) { + if(q != null) q.fromInt(0); + if(r != null) this.copyTo(r); + return; + } + if(r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus + if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } + else { pm.copyTo(y); pt.copyTo(r); } + var ys = y.t; + var y0 = y[ys-1]; + if(y0 == 0) return; + var yt = y0*(1<1)?y[ys-2]>>this.F2:0); + var d1 = this.FV/yt, d2 = (1<= 0) { + r[r.t++] = 1; + r.subTo(t,r); + } + BigInteger.ONE.dlShiftTo(ys,t); + t.subTo(y,y); // "negative" y so we can replace sub with am later + while(y.t < ys) y[y.t++] = 0; + while(--j >= 0) { + // Estimate quotient digit + var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); + if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out + y.dlShiftTo(j,t); + r.subTo(t,r); + while(r[i] < --qd) r.subTo(t,r); + } + } + if(q != null) { + r.drShiftTo(ys,q); + if(ts != ms) BigInteger.ZERO.subTo(q,q); + } + r.t = ys; + r.clamp(); + if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder + if(ts < 0) BigInteger.ZERO.subTo(r,r); + } + + // (public) this mod a + function bnMod(a) { + var r = nbi(); + this.abs().divRemTo(a,null,r); + if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); + return r; + } + + // Modular reduction using "classic" algorithm + function Classic(m) { this.m = m; } + function cConvert(x) { + if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; + } + function cRevert(x) { return x; } + function cReduce(x) { x.divRemTo(this.m,null,x); } + function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + Classic.prototype.convert = cConvert; + Classic.prototype.revert = cRevert; + Classic.prototype.reduce = cReduce; + Classic.prototype.mulTo = cMulTo; + Classic.prototype.sqrTo = cSqrTo; + + // (protected) return "-1/this % 2^DB"; useful for Mont. reduction + // justification: + // xy == 1 (mod m) + // xy = 1+km + // xy(2-xy) = (1+km)(1-km) + // x[y(2-xy)] = 1-k^2m^2 + // x[y(2-xy)] == 1 (mod m^2) + // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 + // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. + // JS multiply "overflows" differently from C/C++, so care is needed here. + function bnpInvDigit() { + if(this.t < 1) return 0; + var x = this[0]; + if((x&1) == 0) return 0; + var y = x&3; // y == 1/x mod 2^2 + y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 + y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 + y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y>0)?this.DV-y:-y; + } + + // Montgomery reduction + function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp&0x7fff; + this.mph = this.mp>>15; + this.um = (1<<(m.DB-15))-1; + this.mt2 = 2*m.t; + } + + // xR mod m + function montConvert(x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t,r); + r.divRemTo(this.m,null,r); + if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); + return r; + } + + // x/R mod m + function montRevert(x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + + // x = x/R mod m (HAC 14.32) + function montReduce(x) { + while(x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0; + for(var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i]&0x7fff; + var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; + // use am to combine the multiply-shift-add into one call + j = i+this.m.t; + x[j] += this.m.am(0,u0,x,i,0,this.m.t); + // propagate carry + while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } + } + x.clamp(); + x.drShiftTo(this.m.t,x); + if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); + } + + // r = "x^2/R mod m"; x != r + function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + // r = "xy/R mod m"; x,y != r + function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + + Montgomery.prototype.convert = montConvert; + Montgomery.prototype.revert = montRevert; + Montgomery.prototype.reduce = montReduce; + Montgomery.prototype.mulTo = montMulTo; + Montgomery.prototype.sqrTo = montSqrTo; + + // (protected) true iff this is even + function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } + + // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) + function bnpExp(e,z) { + if(e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; + g.copyTo(r); + while(--i >= 0) { + z.sqrTo(r,r2); + if((e&(1< 0) z.mulTo(r2,g,r); + else { var t = r; r = r2; r2 = t; } + } + return z.revert(r); + } + + // (public) this^e % m, 0 <= e < 2^32 + function bnModPowInt(e,m) { + var z; + if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e,z); + } + + // protected + BigInteger.prototype.copyTo = bnpCopyTo; + BigInteger.prototype.fromInt = bnpFromInt; + BigInteger.prototype.fromString = bnpFromString; + BigInteger.prototype.clamp = bnpClamp; + BigInteger.prototype.dlShiftTo = bnpDLShiftTo; + BigInteger.prototype.drShiftTo = bnpDRShiftTo; + BigInteger.prototype.lShiftTo = bnpLShiftTo; + BigInteger.prototype.rShiftTo = bnpRShiftTo; + BigInteger.prototype.subTo = bnpSubTo; + BigInteger.prototype.multiplyTo = bnpMultiplyTo; + BigInteger.prototype.squareTo = bnpSquareTo; + BigInteger.prototype.divRemTo = bnpDivRemTo; + BigInteger.prototype.invDigit = bnpInvDigit; + BigInteger.prototype.isEven = bnpIsEven; + BigInteger.prototype.exp = bnpExp; + + // public + BigInteger.prototype.toString = bnToString; + BigInteger.prototype.negate = bnNegate; + BigInteger.prototype.abs = bnAbs; + BigInteger.prototype.compareTo = bnCompareTo; + BigInteger.prototype.bitLength = bnBitLength; + BigInteger.prototype.mod = bnMod; + BigInteger.prototype.modPowInt = bnModPowInt; + + // "constants" + BigInteger.ZERO = nbv(0); + BigInteger.ONE = nbv(1); + + // jsbn2 stuff + + // (protected) convert from radix string + function bnpFromRadix(s,b) { + this.fromInt(0); + if(b == null) b = 10; + var cs = this.chunkSize(b); + var d = Math.pow(b,cs), mi = false, j = 0, w = 0; + for(var i = 0; i < s.length; ++i) { + var x = intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-" && this.signum() == 0) mi = true; + continue; + } + w = b*w+x; + if(++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w,0); + j = 0; + w = 0; + } + } + if(j > 0) { + this.dMultiply(Math.pow(b,j)); + this.dAddOffset(w,0); + } + if(mi) BigInteger.ZERO.subTo(this,this); + } + + // (protected) return x s.t. r^x < DV + function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } + + // (public) 0 if this == 0, 1 if this > 0 + function bnSigNum() { + if(this.s < 0) return -1; + else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; + else return 1; + } + + // (protected) this *= n, this >= 0, 1 < n < DV + function bnpDMultiply(n) { + this[this.t] = this.am(0,n-1,this,0,0,this.t); + ++this.t; + this.clamp(); + } + + // (protected) this += n << w words, this >= 0 + function bnpDAddOffset(n,w) { + if(n == 0) return; + while(this.t <= w) this[this.t++] = 0; + this[w] += n; + while(this[w] >= this.DV) { + this[w] -= this.DV; + if(++w >= this.t) this[this.t++] = 0; + ++this[w]; + } + } + + // (protected) convert to radix string + function bnpToRadix(b) { + if(b == null) b = 10; + if(this.signum() == 0 || b < 2 || b > 36) return "0"; + var cs = this.chunkSize(b); + var a = Math.pow(b,cs); + var d = nbv(a), y = nbi(), z = nbi(), r = ""; + this.divRemTo(d,y,z); + while(y.signum() > 0) { + r = (a+z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d,y,z); + } + return z.intValue().toString(b) + r; + } + + // (public) return value as integer + function bnIntValue() { + if(this.s < 0) { + if(this.t == 1) return this[0]-this.DV; + else if(this.t == 0) return -1; + } + else if(this.t == 1) return this[0]; + else if(this.t == 0) return 0; + // assumes 16 < DB < 32 + return ((this[1]&((1<<(32-this.DB))-1))<>= this.DB; + } + if(a.t < this.t) { + c += a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c += a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += a.s; + } + r.s = (c<0)?-1:0; + if(c > 0) r[i++] = c; + else if(c < -1) r[i++] = this.DV+c; + r.t = i; + r.clamp(); + } + + BigInteger.prototype.fromRadix = bnpFromRadix; + BigInteger.prototype.chunkSize = bnpChunkSize; + BigInteger.prototype.signum = bnSigNum; + BigInteger.prototype.dMultiply = bnpDMultiply; + BigInteger.prototype.dAddOffset = bnpDAddOffset; + BigInteger.prototype.toRadix = bnpToRadix; + BigInteger.prototype.intValue = bnIntValue; + BigInteger.prototype.addTo = bnpAddTo; + + //======= end jsbn ======= + + // Emscripten wrapper + var Wrapper = { + abs: function(l, h) { + var x = new goog.math.Long(l, h); + var ret; + if (x.isNegative()) { + ret = x.negate(); + } else { + ret = x; + } + HEAP32[tempDoublePtr>>2] = ret.low_; + HEAP32[tempDoublePtr+4>>2] = ret.high_; + }, + ensureTemps: function() { + if (Wrapper.ensuredTemps) return; + Wrapper.ensuredTemps = true; + Wrapper.two32 = new BigInteger(); + Wrapper.two32.fromString('4294967296', 10); + Wrapper.two64 = new BigInteger(); + Wrapper.two64.fromString('18446744073709551616', 10); + Wrapper.temp1 = new BigInteger(); + Wrapper.temp2 = new BigInteger(); + }, + lh2bignum: function(l, h) { + var a = new BigInteger(); + a.fromString(h.toString(), 10); + var b = new BigInteger(); + a.multiplyTo(Wrapper.two32, b); + var c = new BigInteger(); + c.fromString(l.toString(), 10); + var d = new BigInteger(); + c.addTo(b, d); + return d; + }, + stringify: function(l, h, unsigned) { + var ret = new goog.math.Long(l, h).toString(); + if (unsigned && ret[0] == '-') { + // unsign slowly using jsbn bignums + Wrapper.ensureTemps(); + var bignum = new BigInteger(); + bignum.fromString(ret, 10); + ret = new BigInteger(); + Wrapper.two64.addTo(bignum, ret); + ret = ret.toString(10); + } + return ret; + }, + fromString: function(str, base, min, max, unsigned) { + Wrapper.ensureTemps(); + var bignum = new BigInteger(); + bignum.fromString(str, base); + var bigmin = new BigInteger(); + bigmin.fromString(min, 10); + var bigmax = new BigInteger(); + bigmax.fromString(max, 10); + if (unsigned && bignum.compareTo(BigInteger.ZERO) < 0) { + var temp = new BigInteger(); + bignum.addTo(Wrapper.two64, temp); + bignum = temp; + } + var error = false; + if (bignum.compareTo(bigmin) < 0) { + bignum = bigmin; + error = true; + } else if (bignum.compareTo(bigmax) > 0) { + bignum = bigmax; + error = true; + } + var ret = goog.math.Long.fromString(bignum.toString()); // min-max checks should have clamped this to a range goog.math.Long can handle well + HEAP32[tempDoublePtr>>2] = ret.low_; + HEAP32[tempDoublePtr+4>>2] = ret.high_; + if (error) throw 'range error'; + } + }; + return Wrapper; +})(); + +//======= end closure i64 code ======= + + + +// === Auto-generated postamble setup entry stuff === + +if (memoryInitializer) { + if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) { + var data = Module['readBinary'](memoryInitializer); + HEAPU8.set(data, STATIC_BASE); + } else { + addRunDependency('memory initializer'); + Browser.asyncLoad(memoryInitializer, function(data) { + HEAPU8.set(data, STATIC_BASE); + removeRunDependency('memory initializer'); + }, function(data) { + throw 'could not load memory initializer ' + memoryInitializer; + }); + } +} + +function ExitStatus(status) { + this.name = "ExitStatus"; + this.message = "Program terminated with exit(" + status + ")"; + this.status = status; +}; +ExitStatus.prototype = new Error(); +ExitStatus.prototype.constructor = ExitStatus; + +var initialStackTop; +var preloadStartTime = null; +var calledMain = false; + +dependenciesFulfilled = function runCaller() { + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!Module['calledRun'] && shouldRunNow) run(); + if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled +} + +Module['callMain'] = Module.callMain = function callMain(args) { + assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)'); + assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called'); + + args = args || []; + + ensureInitRuntime(); + + var argc = args.length+1; + function pad() { + for (var i = 0; i < 4-1; i++) { + argv.push(0); + } + } + var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL) ]; + pad(); + for (var i = 0; i < argc-1; i = i + 1) { + argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL)); + pad(); + } + argv.push(0); + argv = allocate(argv, 'i32', ALLOC_NORMAL); + + initialStackTop = STACKTOP; + + try { + + var ret = Module['_main'](argc, argv, 0); + + + // if we're not running an evented main loop, it's time to exit + if (!Module['noExitRuntime']) { + exit(ret); + } + } + catch(e) { + if (e instanceof ExitStatus) { + // exit() throws this once it's done to make sure execution + // has been stopped completely + return; + } else if (e == 'SimulateInfiniteLoop') { + // running an evented main loop, don't immediately exit + Module['noExitRuntime'] = true; + return; + } else { + if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]); + throw e; + } + } finally { + calledMain = true; + } +} + + + + +function run(args) { + args = args || Module['arguments']; + + if (preloadStartTime === null) preloadStartTime = Date.now(); + + if (runDependencies > 0) { + Module.printErr('run() called, but dependencies remain, so not running'); + return; + } + + preRun(); + + if (runDependencies > 0) return; // a preRun added a dependency, run will be called later + if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame + + function doRun() { + if (Module['calledRun']) return; // run may have just been called while the async setStatus time below was happening + Module['calledRun'] = true; + + ensureInitRuntime(); + + preMain(); + + if (ENVIRONMENT_IS_WEB && preloadStartTime !== null) { + Module.printErr('pre-main prep time: ' + (Date.now() - preloadStartTime) + ' ms'); + } + + if (Module['_main'] && shouldRunNow) { + Module['callMain'](args); + } + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + if (!ABORT) doRun(); + }, 1); + } else { + doRun(); + } +} +Module['run'] = Module.run = run; + +function exit(status) { + ABORT = true; + EXITSTATUS = status; + STACKTOP = initialStackTop; + + // exit the runtime + exitRuntime(); + + // TODO We should handle this differently based on environment. + // In the browser, the best we can do is throw an exception + // to halt execution, but in node we could process.exit and + // I'd imagine SM shell would have something equivalent. + // This would let us set a proper exit status (which + // would be great for checking test exit statuses). + // https://github.com/kripken/emscripten/issues/1371 + + // throw an exception to halt the current execution + throw new ExitStatus(status); +} +Module['exit'] = Module.exit = exit; + +function abort(text) { + if (text) { + Module.print(text); + Module.printErr(text); + } + + ABORT = true; + EXITSTATUS = 1; + + var extra = '\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.'; + + throw 'abort() at ' + stackTrace() + extra; +} +Module['abort'] = Module.abort = abort; + +// {{PRE_RUN_ADDITIONS}} + +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} + +// shouldRunNow refers to calling main(), not run(). +var shouldRunNow = true; +if (Module['noInitialRun']) { + shouldRunNow = false; +} + + +run(); + +// {{POST_RUN_ADDITIONS}} + + + + + + +// {{MODULE_ADDITIONS}} + + + + + +Module['arrfile'] = function(filename, arr) { + try{ FS.unlink("/" + filename); } + catch(e){ ; } + FS.createDataFile("/", filename, arr, true, true); + return {path: filename, size: arr.byteLength}; +}; + +Module['gzcompress'] = function(data) { // TODO: Accept strings + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['output.gz', 'wb']); + var buffer = _malloc(data.length); + HEAPU8.set(data, buffer); + ccall('gzwrite', 'number', ['number', 'number', 'number'], [gzFile, buffer, data.length]); + ccall('gzclose', 'number', ['number'], [gzFile]); + _free(buffer); + var ret = new Uint8Array(FS.root.contents['output.gz'].contents); + FS.unlink('output.gz'); + return ret; +}; + +Module['gzdecompress'] = function(data) { + var BUFSIZE = 1024*1024; + FS.createDataFile('/', 'input.gz', data, true, true); + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['input.gz', 'rb']); + var buffer = _malloc(BUFSIZE); + var chunks = []; + var total = 0; + var len; + while( (len = ccall('gzread', 'number', ['number', 'number', 'number'], [gzFile, buffer, BUFSIZE])) > 0) { + chunks.push(new Uint8Array(len)); + chunks[chunks.length-1].set(HEAPU8.subarray(buffer, buffer+len)); + total += len; + } + ccall('gzclose', 'number', ['number'], [gzFile]); + FS.unlink('input.gz'); + _free(buffer); + var ret = new Uint8Array(total); + var curr = 0; + for (var i = 0; i < chunks.length; i++) { + ret.set(chunks[i], curr); + curr += chunks[i].length; + } + return ret; +}; + + diff --git a/astroem/casa.head b/astroem/casa.head new file mode 100644 index 00000000..2b860b19 --- /dev/null +++ b/astroem/casa.head @@ -0,0 +1 @@ +char * header = "SIMPLE = T / Standard FITS BITPIX = 32 / bits/pixel NAXIS = 2 / number of axes NAXIS1 = 1025 / x axis dimension NAXIS2 = 1025 / y axis dimension HDUNAME = 'EVENTS ' / ASCDM block name COMMENT This FITS file may contain long string keyword values that are COMMENT continued over multiple keywords. The HEASARC convention uses the & COMMENT character at the end of each substring which is then continued COMMENT on the next keyword which has the name CONTINUE. REVISION= 1 LONGSTRN= 'OGIP 1.0' / The HEASARC Long String Convention may be used.COMMENT This FITS file may contain long string keyword values that are COMMENT continued over multiple keywords. The HEASARC convention uses the & COMMENT character at the end of each substring which is then continued COMMENT on the next keyword which has the name CONTINUE. CONTENT = 'EVT2 ' HDUCLASS= ' ' HDUCLAS1= ' ' HDUCLAS2= ' ' ORIGIN = 'ASC ' / Source of FITS file CREATOR = 'asc - Version 1.2' / tool that created this output ASCDSVER= 'R4CU3UPD2 Thursday, July 29, 1999' / ASCDS version number DATE = '1999-09-04T03:08:28' / Date and time of file creation DATE-OBS= '1999-08-20T00:07:44' / Date and time of observation start DATE-END= '1999-08-20T02:26:38' / Date and time of observation stop TIMESYS = 'TT ' / Time system MJDREF = 5.0814000000000E+04 / MJD zero point for times TIMEZERO= 0.0000000000000E+00 / Clock correction TIMEUNIT= 's ' / Time unit BTIMNULL= 5.1525063963414E+07 / Basic Time offset (s) BTIMRATE= 2.5625000921100E-01 / Basic Time clock rate (s / VCDUcount) BTIMDRFT= -7.8489580000000E-18 / Basic Time clock drift (s / VCDUcount^2) BTIMCORR= 0.0000000000000E+00 / Correction applied to Basic Time rate (s) TIMEREF = 'LOCAL ' / Time reference (barycenter/local) TASSIGN = 'SATELLITE' / Time assigned by clock CLOCKAPP= T / default TIERRELA= 1.0000000000000E-09 / default TIERABSO= 1.0000000000000E-03 / default TIMVERSN= 'ASC-FITS-2' / Timing system definition TSTART = 5.1494864899828E+07 / Observation start time TSTOP = 5.1503198662628E+07 / Observation end time TIMEPIXR= 5.0000000000000E-01 / default TIMEDEL = 3.2410400000000E+00 / Time resolution of data (in seconds) MISSION = 'AXAF ' / Mission TELESCOP= 'CHANDRA ' / Telescope INSTRUME= 'ACIS ' / Instrument DETNAM = 'ACIS-456789' / Detector GRATING = 'NONE ' / Grating OBJECT = 'CAS A, CHIP S3,' / Source name TITLE = 'ACIS CHIP RESPONSE TO CAS A, JAN. 99' / Proposal title OBSERVER= 'DR. AXAF CALIBRATION' / Principal investigator OBS_ID = '214 ' / Observation id OBI_NUM = 0 / Obi number SEQ_NUM = '590082 ' / Sequence number SIM_X = -7.3623565999634E-01 / SIM focus pos (mm) SIM_Y = 0.0000000000000E+00 / SIM orthogonal axis pos (mm) SIM_Z = -1.9011995152746E+02 / SIM translation stage pos (mm) FOC_LEN = 1.0061620000000E+04 / HRMA focal length (mm) OBS_MODE= 'POINTING' / Observation mode DATAMODE= 'FAINT ' / Data mode RA_NOM = 3.5084373348796E+02 / Nominal RA DEC_NOM = 5.8834901856618E+01 / Nominal Dec ROLL_NOM= 1.5752717461018E+02 / Nominal Roll EQUINOX = 2.0000000000000E+03 / default RADECSYS= 'ICRS ' / default DATACLAS= 'OBSERVED' / default HISTNUM = 25 HISTORY TOOL :ade ASC00001HISTORY PARM :infile=/dsops/current/ap/sdp/opus/prs_run/tmp//TP_ADE__ASC00002HISTORY CONT :__052704811n573/input/acisf051495329_SR0.strip ASC00003HISTORY PARM :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_ASC00004HISTORY CONT :strip_file_info.dat@@/main/2 ASC00005HISTORY PARM :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_ASC00006HISTORY CONT :file_info.dat@@/main/12 ASC00007HISTORY PARM :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_ASC00008HISTORY CONT :config_file.dat@@/main/2 ASC00009HISTORY PARM :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_ASC00010HISTORY CONT :group_info.dat@@/main/12 ASC00011STARTMJF= 2638 / Major frame ctr value at start of data STARTMNF= 64 / Start minor frame ctr at start of data STOPMJF = 2841 / Major frame ctr value at stop of data STOPMNF = 79 / Stop minor frame ctr at end of data HISTORY TOOL :ade ASC00001HISTORY PARM :infile=/dsops/current/ap/sdp/opus/prs_run/tmp//TP_ADE__ASC00002HISTORY CONT :__052704811n573/input/acisf051495329_SR0.strip ASC00003HISTORY PARM :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_ASC00004HISTORY CONT :strip_file_info.dat@@/main/2 ASC00005HISTORY PARM :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_ASC00006HISTORY CONT :file_info.dat@@/main/12 ASC00007HISTORY PARM :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_ASC00008HISTORY CONT :config_file.dat@@/main/2 ASC00009HISTORY PARM :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_ASC00010HISTORY CONT :group_info.dat@@/main/12 ASC00011READMODE= 'TIMED ' / Read mode (for ACIS only) ACSYS1 = 'CHIP:AXAF-ACIS-1.0' / reference for chip coord system ACSYS2 = 'TDET:AXAF-ACIS-2.2' / reference for tiled detector coord system ACSYS3 = 'DET:ASC-FP-1.1' / reference for focal plane coord system ACSYS4 = 'SKY:ASC-FP-1.1' / reference for sky coord system MIR_AL_X= 0.0000000000000E+00 / mirror X misalignment (arcmins) MIR_AL_Y= 0.0000000000000E+00 / mirror Y misalignment (arcmins) MIR_AL_Z= 0.0000000000000E+00 / mirror Z misalignment (arcmins) STG_AL_X= 0.0000000000000E+00 / stage X misalignment (arcmins) STG_AL_Y= 0.0000000000000E+00 / stage Y misalignment (arcmins) STG_AL_Z= 0.0000000000000E+00 / stage Z misalignment (arcmins) GAINFILE= '/home/ascds/DS.ap/data/acisD1999-07-22gainN0001.fits' GRD_FILE= '/home/ascds/DS.ap/data/asca_grades.fits' BIASFIL4= '/dsops/current/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_052713473n939/inp&'CONTINUE= ' ' / 'ut/acisf051495447N001_1_bias0.fits' BIASFIL5= '/dsops/current/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_052713473n939/inp&'BIASFIL6= '/dsops/current/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_052713473n939/inp&'BIASFIL7= '/dsops/current/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_052713473n939/inp' BIASFIL8= '/dsops/current/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_052713473n939/inp&'BIASFIL9= '/dsops/current/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_052713473n939/inp&'CYCLE = 'P ' / events from which exps? Prim/Second/Both HISTORY TOOL :acis_process_events 1999-09-04T02:53:01 ASC00012HISTORY PARM :infile=/dsops/current/ap/sdp/opus/prs_run/tmp//ACIS_F_L1ASC00013HISTORY CONT :_052713473n939/output/acisf00214_000N001_tim1.fits ASC00014HISTORY PARM :outfile=/dsops/current/ap/sdp/opus/prs_run/tmp//ACIS_F_LASC00015HISTORY CONT :1_052713473n939/output/acisf00214_000N001_evt1.fits ASC00016CORNERS = 2 / num adjacent side pix > threshold to include coGRADESYS= 'ASCA ' / grade system: ASCA, ACIS, or USER FIRSTROW= 1 / Index of first row of CCD (sub)array readout NROWS = 1023 / Number of rows in (sub)array readout EXPTIME = 3.2000000000000E+00 / [s] commanded exposure time (s) ONTIME4 = 8.3337628000006E+03 / [s] LIVTIME4= 8.3337628000006E+03 / [s] ONTIME5 = 8.3337628000006E+03 / [s] LIVTIME5= 8.3337628000006E+03 / [s] ONTIME6 = 8.3337628000006E+03 / [s] LIVTIME6= 8.3337628000006E+03 / [s] ONTIME7 = 6.1071683208048E+03 / [s] LIVTIME7= 6.1071683208048E+03 / [s] ONTIME8 = 8.3337628000006E+03 / [s] LIVTIME8= 8.3337628000006E+03 / [s] ONTIME9 = 8.3337628000006E+03 / [s] LIVTIME9= 8.3337628000006E+03 / [s] ONTIME = 6.1071683208048E+03 / [s] [s] LIVETIME= 6.1071683208048E+03 / [s] [s] DTCOR = 1.0000000000000E+00 HISTORY TOOL :acis_build_chip_gti 1999-09-04T02:57:53 ASC00017HISTORY PARM :infile=/dsops/current/ap/sdp/opus/prs_run/tmp//ACIS_F_L1ASC00018HISTORY CONT :_052713473n939/output/acisf00214_000N001_stat1.fits ASC00019HISTORY PARM :outfile=/dsops/current/ap/sdp/opus/prs_run/tmp//ACIS_F_LASC00020HISTORY CONT :1_052713473n939/output/acisf00214_000N001_evt1.fits ASC00021DSREF1 = ':GTI4 ' 2DSREF1 = ':GTI5 ' 3DSREF1 = ':GTI6 ' 4DSREF1 = ':GTI7 ' 5DSREF1 = ':GTI8 ' 6DSREF1 = ':GTI9 ' HISTORY TOOL :dmmerge 1999-09-04T03:08:27 ASC00022HISTORY PARM :infile= File # 1 : /dsops/current/ap/sdp/opus/prs_run/tmASC00023HISTORY CONT :p//ACIS_L2___052715018n957/input/acisf00214_000N001_evt1ASC00024HISTORY CONT :.fits[status=0] ASC00025DTYPE1 = 'REVISION' / DM Keyword: Descriptor name. DFORM1 = 'I ' / DM Keyword: Descriptor datatype. DSTYP1 = 'time ' / DM Keyword: Descriptor name. DSTYP2 = 'ccd_id ' / DM Keyword: Descriptor name. DSTYP3 = 'FEP_ID ' / DM Keyword: Descriptor name. DSVAL1 = 'TABLE ' / DM Keyword: Descriptor value. DSVAL2 = '4:4 ' / DM Keyword: Descriptor value. DSVAL3 = '2:2 ' / DM Keyword: Descriptor value. DSFORM1 = 'D ' / DM Keyword: Descriptor datatype. 2DSVAL1 = 'TABLE ' 3DSVAL1 = 'TABLE ' 4DSVAL1 = 'TABLE ' 5DSVAL1 = 'TABLE ' 6DSVAL1 = 'TABLE ' DSFORM2 = 'I ' / DM Keyword: Descriptor datatype. 2DSVAL2 = '5:5 ' 3DSVAL2 = '6:6 ' 4DSVAL2 = '7:7 ' 5DSVAL2 = '8:8 ' 6DSVAL2 = '9:9 ' DSFORM3 = 'I ' / DM Keyword: Descriptor datatype. 2DSVAL3 = '1:1 ' 3DSVAL3 = '5:5 ' 4DSVAL3 = '0:0 ' 5DSVAL3 = '3:3 ' 6DSVAL3 = '4:4 ' MTYPE1 = 'chip ' / DM Keyword: Descriptor name. MTYPE2 = 'tdet ' / DM Keyword: Descriptor name. MTYPE3 = 'det ' / DM Keyword: Descriptor name. MTYPE4 = 'sky ' / DM Keyword: Descriptor name. MTYPE5 = 'CPC ' / DM Keyword: Descriptor name. MTYPE6 = 'MSC ' / DM Keyword: Descriptor name. MTYPE7 = 'EQPOS ' / DM Keyword: Descriptor name. MFORM1 = 'chipx,chipy' / DM Keyword: Descriptor value. MFORM2 = 'tdetx,tdety' / DM Keyword: Descriptor value. MFORM3 = 'detx,dety' / DM Keyword: Descriptor value. MFORM4 = 'x,y ' / DM Keyword: Descriptor value. MFORM5 = 'CPCX,CPCY' / DM Keyword: Descriptor value. MFORM6 = 'THETA,PHI' / DM Keyword: Descriptor value. MFORM7 = 'RA,DEC ' / DM Keyword: Descriptor value. TCNAM9 = 'THETA ' TCNAM10 = 'PHI ' CTYPE1 = 'RA---TAN' CRVAL1 = 3.5084373348796E+02 CDELT1 = -1.3663889E-04 / degrees/pixel CDELT2 = 1.3663889E-04 / degrees/pixel CRPIX1 = 582.0000000 / reference point CRPIX2 = 665.0000000 / reference point CTYPE2 = 'DEC--TAN' CRVAL2 = 5.8834901856618E+01 LTV1 = -3514.0000000 / IRAF ref. point LTV2 = -3431.0000000 / IRAF ref. point LTM1_1 = 1.0000000 / IRAF matrix value LTM1_2 = 0.0000000E+00 / IRAF matrix value LTM2_1 = 0.0000000E+00 / IRAF matrix value LTM2_2 = 1.0000000 / IRAF matrix value END"; diff --git a/astroem/cdl.h b/astroem/cdl.h new file mode 100644 index 00000000..e3d47635 --- /dev/null +++ b/astroem/cdl.h @@ -0,0 +1,335 @@ +/* + * CDL.H -- Global definitions for the Client Display Library. + */ + +#include +#include +#include + + +#ifndef _CDL_Defined +#define _CDL_Defined + +#define CDL_VERSION "Client Display Library V1.8 07/28/01" + +/* Declare prototypes if using ANSI C */ +#ifdef CDL_ANSIC +#define ANSI_FUNC +#endif + +#define MAX_FBCONFIG 128 /* max size of FB config table */ +#define MAX_FRAMES 16 /* max frames support by server */ +#define MAX_MAPPINGS 32 /* max image mappings per frame */ +#define DEF_CONTRAST 0.25 /* default zscale contrast */ +#define DEF_NSAMPLE 600 /* default number of samples */ +#define DEF_NSAMPLINES -1 /* default no. of sample lines */ +#define INDEF -999 /* INDEF value flag */ + + +/* Include private definitions when compiling library sources. */ +#ifdef CDL_LIBRARY_SOURCE +#include "eps.h" +#include "cdlP.h" +#endif + +/* Frame buffer selection code. */ +#define FB_AUTO -1 /* autoconfig the frame buffer */ + +/* Types of greyscale transformations. */ +#define CDL_UNITARY 0 /* values map without change */ +#define CDL_LINEAR 1 /* linear mapping */ +#define CDL_LOG 2 /* logarithmic mapping */ + +/* Overlay colors. */ +#define C_BLACK 202 /* Static overlay color defs */ +#define C_WHITE 203 +#define C_RED 204 +#define C_GREEN 205 +#define C_BLUE 206 +#define C_YELLOW 207 +#define C_CYAN 208 +#define C_MAGENTA 209 +#define C_CORAL 210 +#define C_MAROON 211 +#define C_ORANGE 212 +#define C_KHAKI 213 +#define C_ORCHID 214 +#define C_TURQUOISE 215 +#define C_VIOLET 216 +#define C_WHEAT 217 + +#define M_FILL 1 /* Overlay point mark types. */ +#define M_POINT 2 +#define M_BOX 4 +#define M_PLUS 8 +#define M_CROSS 16 +#define M_DIAMOND 32 +#define M_CIRCLE 64 +#define M_STAR 128 +#define M_HLINE 256 +#define M_VLINE 512 +#define M_HBLINE 1024 +#define M_VBLINE 2048 + +#define F_ROMAN 0 /* Font types. */ +#define F_GREEK 1 +#define F_FUTURA 2 +#define F_TIMES 3 +#define F_BOLD 4 + +#define L_SOLID 0 /* Polyline attribute values. */ +#define L_DASHED 1 +#define L_DOTTED 2 +#define L_DOTDASH 3 +#define L_HOLLOW 4 +#define L_SHADOW 5 + + +/* Local type definitions. */ +typedef struct CDL *CDLPtr; +typedef struct Marker *MarkerPtr; + + +#ifndef AIXV3 +#ifndef OSF1 +typedef unsigned char uchar; +#endif +#endif + + + +/* The main CDL package structure. + */ +struct CDL { +#ifdef CDL_LIBRARY_SOURCE + IMDPtr imd; /* IMD package pointer */ + int memModel; /* Memory model to use */ +#endif + + int frame; /* display frame number */ + int fbconfig; /* fb config number */ + int fbwidth; /* current FB width */ + int fbheight; /* current FB height */ + int fbnf; /* current FB nframes */ + + float contrast; /* zscale contrast value*/ + int nsample; /* opt. sample points */ + int nsamplines; /* opt. sample lines */ + + int im_nx; /* current image width */ + int im_ny; /* current image height */ + + /* Overlay graphics attributes. */ + int font; /* overlay text font */ + int textwidth; /* text width */ + int linewidth; /* line width */ + int linestyle; /* line style */ + + /* WCS descriptor stuff. */ + char *imname; /* image name */ + char *imtitle; /* image title */ + float a, b, c, d; /* WCS values */ + float tx, ty; /* translation values */ + float z1, z2; /* zscale values */ + int ztrans; /* Z trans type */ + + /* Coordinate mappings on the frame buffer. */ + char *ref; /* img reference */ + char *region; /* region name */ + float sx, sy; /* source rect */ + int snx, sny; + int dx, dy; /* destination rect */ + int dnx, dny; + int iis_version; /* server IIS version */ + int iis_valid; /* valid mapping flag */ +}; + + +/* A element of the display list describing the marker. We throw in the + * kitchen sinke here to cover all possible marker types, in reality only + * a few of these are used for any given marker type. + */ +struct Marker { + short type; /* marker type */ + int x, y; /* center coords */ + int number; /* label a point */ + int pt_type; /* point type */ + int size; /* point marker size */ + int fill; /* fill marker */ + int color; /* marker color */ + int *xp, *yp; /* coords */ + int npts; /* npts in array */ + int radius; /* circle radius */ + int nannuli; /* num of annuli */ + int sep; /* annulus separation */ + int xrad, yrad; /* ellipse axes */ + float ang; /* ellipse rotation */ + float txsize; /* text marker size */ + char *str; /* text marker string */ + int font; /* text font type */ + int textwidth; /* text width */ + int linewidth; /* line width */ + int linestyle; /* line style */ + + int nx, ny; /* marker region size */ + int lx, ly; /* marker LL corner */ + + unsigned char *refpix; /* orig image pixels */ + unsigned char *markpix; /* marked image pixels */ + + MarkerPtr back; /* linked list pointers */ + MarkerPtr next; + int markerID; /* assigned id number */ +}; + + +/* Marker types used internally. */ +#define MK_POINT 0 +#define MK_LINE 1 +#define MK_BOX 2 +#define MK_POLYLINE 3 +#define MK_POLYGON 4 +#define MK_CIRCLE 5 +#define MK_CIRCANN 6 +#define MK_ELLIPSE 7 +#define MK_ELLIPANN 8 +#define MK_TEXT 9 + + +/* Function definitions. */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ANSI_FUNC + +CDLPtr cdl_open(); + +char cdl_readCursor(); + +int cdl_displayPix(), cdl_displayIRAF(), cdl_displayFITS(); +int cdl_readIRAF(), cdl_readFITS(), cdl_clearFrame(); +int cdl_readImage(), cdl_readFrameBuffer(), cdl_readSubRaster(); +int cdl_writeSubRaster(), cdl_setCursor(); +int cdl_printPix(), cdl_printPixToFile(); +int cdl_setWCS(), cdl_getWCS(); +int cdl_getMapping(), cdl_setMapping(), cdl_queryMap(); + +void cdl_selectFB(), cdl_close(), cdl_computeZscale(), cdl_zscaleImage(); +void cdl_setFrame(), cdl_setFBConfig(), cdl_setZTrans(), cdl_setZoom(); +void cdl_setSample(), cdl_setContrast(), cdl_setName(), cdl_setTitle(); +void cdl_getFrame(), cdl_getFBConfig(), cdl_getZTrans(), cdl_getZoom(); +void cdl_getSample(), cdl_getContrast(), cdl_getName(), cdl_getTitle(); +void cdl_getSampleLines(), cdl_setSampleLines(), cdl_zscale(); +void cdl_setZScale(), cdl_getZScale(), cdl_lookupFBSize(); +void cdl_setDebug(); + +/* Marker function definitions. */ +int cdl_markPoint(), cdl_markLine(), cdl_markBox(), cdl_markPolyline(); +int cdl_markPolygon(), cdl_markCircle(), cdl_markCircAnnuli(); +int cdl_markEllipse(), cdl_markEllipAnnuli(), cdl_markText(); +int cdl_deleteMark(), cdl_clearOverlay(), cdl_redrawOverlay(); +int cdl_markCoordsFile(), cdl_mapFrame(); + +void cdl_setFont(), cdl_setTextWidth(); +void cdl_setLineWidth(), cdl_setLineStyle(); + +#endif + + +/* Include function prototypes for all public CDL functions when using ANSI C */ + +#ifdef ANSI_FUNC + +CDLPtr cdl_open(char *imtdev); +int cdl_displayPix(CDLPtr cdl, uchar *pix, int nx, int ny, int bitpix, int frame, int fbconfig, int zscale); +char cdl_readCursor(CDLPtr cdl, int sample, float *x, float *y, int *wcs, char *key); +int cdl_setCursor(CDLPtr cdl, int x, int y, int wcs); +int cdl_setWCS(CDLPtr cdl, char *imname, char *imtitle, float a, float b, float c, float d, float tx, float ty, float z1, float z2, int zt); +int cdl_getWCS(CDLPtr cdl, char *name, char *title, float *a, float *b, float *c, float *d, float *tx, float *ty, float *z1, float *z2, int *zt); +int cdl_getMapping(CDLPtr cdl, char *region, float *sx, float *sy, int *snx, int *sny, int *dx, int *dy, int *dnx, int *dny, char *ref); +int cdl_setMapping(CDLPtr cdl, char *region, float sx, float sy, int snx, int sny, int dx, int dy, int dnx, int dny, char *ref); +int cdl_queryMap(CDLPtr cdl, int wcs, char *region, float *sx, float *sy, int *snx, int *sny, int *dx, int *dy, int *dnx, int *dny, char *objref); +int cdl_clearFrame(CDLPtr cdl); +void cdl_selectFB(CDLPtr cdl, int nx, int ny, int *fb, int *w, int *h, int *nf, int reset); +void cdl_close(CDLPtr cdl); +int cdl_readImage(CDLPtr cdl, uchar **pix, int *nx, int *ny); +int cdl_readFrameBuffer(CDLPtr cdl, uchar **pix, int *nx, int *ny); +void cdl_computeZscale(CDLPtr cdl, uchar *pix, int nx, int ny, int bitpix, float *z1, float *z2); +void cdl_zscaleImage(CDLPtr cdl, uchar **pix, int nx, int ny, int bitpix, float z1, float z2); +int cdl_printPix(CDLPtr cdl, char *cmd, uchar *pix, int nx, int ny, int annotate); +int cdl_printPixToFile(CDLPtr cdl, char *fname, uchar *pix, int nx, int ny, int annotate); +int cdl_readSubRaster(CDLPtr cdl, int lx, int ly, int nx, int ny, uchar **pix); +int cdl_writeSubRaster(CDLPtr cdl, int lx, int ly, int nx, int ny, uchar *pix); +void cdl_setFBConfig(CDLPtr cdl, int configno); +void cdl_getFBConfig(CDLPtr cdl, int *configno, int *w, int *h, int *nframes); +void cdl_lookupFBSize(CDLPtr cdl, int configno, int *w, int *h, int *nf); +void cdl_setFrame(CDLPtr cdl, int frame); +void cdl_setZTrans(CDLPtr cdl, int ztrans); +void cdl_setZScale(CDLPtr cdl, float z1, float z2); +void cdl_setSample(CDLPtr cdl, int nsample); +void cdl_setSampleLines(CDLPtr cdl, int nlines); +void cdl_setContrast(CDLPtr cdl, float contrast); +void cdl_setName(CDLPtr cdl, char *imname); +void cdl_setTitle(CDLPtr cdl, char *imtitle); +void cdl_getFrame(CDLPtr cdl, int *frame); +void cdl_getZTrans(CDLPtr cdl, int *ztrans); +void cdl_getZScale(CDLPtr cdl, float *z1, float *z2); +void cdl_getSample(CDLPtr cdl, int *nsample); +void cdl_getSampleLines(CDLPtr cdl, int *nlines); +void cdl_getContrast(CDLPtr cdl, float *contrast); +void cdl_getName(CDLPtr cdl, char *imname); +void cdl_getTitle(CDLPtr cdl, char *imtitle); +void cdl_setDebug(int state); + + +int cdl_mapFrame(CDLPtr cdl, int frame); +int cdl_markCoordsFile(CDLPtr cdl, char *fname, int type, int size, int color, int label); +int cdl_markPoint(CDLPtr cdl, int x, int y, int number, int size, int type, int color); +int cdl_markPointLabel(CDLPtr cdl, int x, int y, char *label, int size, int type, int color); +int cdl_markLine(CDLPtr cdl, int xs, int ys, int xe, int ye, int color); +int cdl_markBox(CDLPtr cdl, int lx, int ly, int ux, int uy, int fill, int color); +int cdl_markPolygon(CDLPtr cdl, int xarray[], int yarray[], int npts, int fill, int color); +int cdl_markPolyline(CDLPtr cdl, int *xarray, int *yarray, int npts, int color); +int cdl_markCircle(CDLPtr cdl, int x, int y, int radius, int fill, int color); +int cdl_markCircAnnuli(CDLPtr cdl, int x, int y, int radius, int nannuli, int sep, int color); +int cdl_markEllipse(CDLPtr cdl, int x, int y, int xrad, int yrad, float rotang, int fill, int color); +int cdl_markEllipAnnuli(CDLPtr cdl, int x, int y, int xrad, int yrad, float ang, int nannuli, int sep, int color); +int cdl_markText(CDLPtr cdl, int x, int y, char *str, float size, float angle, int color); +void cdl_setFont(CDLPtr cdl, int font); +void cdl_setTextWidth(CDLPtr cdl, int width); +void cdl_setLineWidth(CDLPtr cdl, int width); +void cdl_setLineStyle(CDLPtr cdl, int style); +int cdl_deleteMark(CDLPtr cdl, int x, int y); +int cdl_clearOverlay(CDLPtr cdl); +int cdl_redrawOverlay(CDLPtr cdl); +void cdl_beginDList(int frame); +void cdl_drawDList(int frame); +void cdl_clearDList(int frame); +void cdl_endDList(int frame, int flush); +int cdl_doTextMarker(int x, int y, char *string, float size, float angle, int color, int width, int font, uchar *pix, int lx, int ly, int nx, int ny); +int cdl_freeDisplayList(CDLPtr cdl, MarkerPtr head); + +int cdl_displayFITS(CDLPtr cdl, char *fname, int frame, int fbconfig, int zscale); +int cdl_isFITS(char *fname); +int cdl_readFITS(char *fname, uchar **pix, int *nx, int *ny, int *bitpix, +char *title); + +int cdl_displayIRAF(CDLPtr cdl, char *fname, int band, int frame, int +fbconfig, int zscale); +int cdl_isIRAF(char *fname); +int cdl_readIRAF(char *fname, int band, uchar **pix, int *nx, int *ny, int *bitpix, char *title); + +#endif + +#ifdef __cplusplus +} +#endif + + +#ifdef CDL_LIBRARY_SOURCE +#include "cdlProto.h" +#endif + +/* _CDL_Defined */ +#endif diff --git a/astroem/cdlP.h b/astroem/cdlP.h new file mode 100644 index 00000000..37358e26 --- /dev/null +++ b/astroem/cdlP.h @@ -0,0 +1,176 @@ +/* + * CDLP.H -- Private definitions for the Client Display Library. + */ + +/* Default values, size limiting values. + */ +#define SZ_FNAME 256 /* size of an image name */ +#define SZ_NAME 256 /* size of an image name */ +#define SZ_LINE 256 /* size of temp buffer */ +#define SZ_IMTDEV 128 /* size of an IMTDEV string */ +#define SZ_IMCURVAL 160 /* cursor value str length */ +#define SZ_OLD_WCSBUF 320 /* old wcs buffer length */ +#define SZ_WCSBUF 1024 /* wcs buffer length */ + +#define OK 0 /* success */ +#define ERR 1 /* failure */ +#define EOS '\0' /* end of statement */ + + + +/* Utility macros. + */ +#undef max +#define max(a,b) (a > b ? a : b) +#undef min +#define min(a,b) (a < b ? a : b) + +/* Handy values. + */ +#undef True +#define True 1 +#undef False +#define False 0 + + +/* Define the structures needed by the IMD interface. This is a kludge + * to avoid having applications include the IMD header. + */ + +typedef struct { + int config; /* configuration number */ + int nframes; /* number of frames */ + int width, height; /* frame buffer dimensions */ +} FBTab; + +struct IMD { + int datain, dataout; /* connection file descriptors */ + int domain; /* connection type */ + + short frame; /* display frame number */ + short fbconfig; /* frame buffer config number */ + FBTab *fbtab[MAX_FBCONFIG]; /* fb configuration table */ + + short xs, xe; /* X start/end values */ + short ys, ye; /* Y start/end values */ + char *name; /* image name */ + char *title; /* image title */ + float a, b, c, d; /* WCS values */ + float tx, ty; /* translation values */ + float z1, z2; /* zscale values */ + short ztrans; /* Z trans type */ + + /* Coordinate mappings on the frame buffer. */ + int iis_version; /* server IIS version */ + int iis_valid; /* valid mapping flag */ + char *ref; /* img reference */ + char *region; /* region name */ + float sx, sy; /* source rect */ + int snx, sny; + int dx, dy; /* destination rect */ + int dnx, dny; +}; +typedef struct IMD *IMDPtr; + + + +#ifdef CDL_NEED_COLORMAPS + +/* Define a grayscale+static colormap used by the print routines. */ +static unsigned char cmap_r[] = { + 0, 1, 3, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, 17, 18, 19, + 20, 22, 23, 24, 26, 27, 28, 29, 31, 32, 33, 35, 36, 37, 38, 40, + 41, 42, 44, 45, 46, 47, 49, 50, 51, 52, 54, 55, 56, 58, 59, 60, + 61, 63, 64, 65, 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 81, + 82, 83, 84, 86, 87, 88, 90, 91, 92, 93, 95, 96, 97, 99, 100, 101, +102, 104, 105, 106, 108, 109, 110, 111, 113, 114, 115, 116, 118, 119, 120, 122, +123, 124, 125, 127, 128, 129, 131, 132, 133, 134, 136, 137, 138, 140, 141, 142, +143, 145, 146, 147, 148, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 163, +164, 165, 166, 168, 169, 170, 172, 173, 174, 175, 177, 178, 179, 180, 182, 183, +184, 186, 187, 188, 189, 191, 192, 193, 195, 196, 197, 198, 200, 201, 202, 204, +205, 206, 207, 209, 210, 211, 212, 214, 215, 216, 218, 219, 220, 221, 223, 224, +225, 227, 228, 229, 230, 232, 233, 234, 236, 237, 238, 239, 241, 242, 243, 244, +246, 247, 248, 250, 251, 252, 253, 255, 255, 255, 0, 255, 255, 0, 0, 255, + 0, 255, 255, 177, 255, 255, 219, 0, 239, 255, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char cmap_g[] = { + 0, 1, 3, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, 17, 18, 19, + 20, 22, 23, 24, 26, 27, 28, 29, 31, 32, 33, 35, 36, 37, 38, 40, + 41, 42, 44, 45, 46, 47, 49, 50, 51, 52, 54, 55, 56, 58, 59, 60, + 61, 63, 64, 65, 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 81, + 82, 83, 84, 86, 87, 88, 90, 91, 92, 93, 95, 96, 97, 99, 100, 101, +102, 104, 105, 106, 108, 109, 110, 111, 113, 114, 115, 116, 118, 119, 120, 122, +123, 124, 125, 127, 128, 129, 131, 132, 133, 134, 136, 137, 138, 140, 141, 142, +143, 145, 146, 147, 148, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 163, +164, 165, 166, 168, 169, 170, 172, 173, 174, 175, 177, 178, 179, 180, 182, 183, +184, 186, 187, 188, 189, 191, 192, 193, 195, 196, 197, 198, 200, 201, 202, 204, +205, 206, 207, 209, 210, 211, 212, 214, 215, 216, 218, 219, 220, 221, 223, 224, +225, 227, 228, 229, 230, 232, 233, 234, 236, 237, 238, 239, 241, 242, 243, 244, +246, 247, 248, 250, 251, 252, 253, 255, 255, 255, 0, 255, 0, 255, 0, 255, +255, 0, 127, 48, 166, 247, 112, 246, 131, 232, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char cmap_b[] = { + 0, 1, 3, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, 17, 18, 19, + 20, 22, 23, 24, 26, 27, 28, 29, 31, 32, 33, 35, 36, 37, 38, 40, + 41, 42, 44, 45, 46, 47, 49, 50, 51, 52, 54, 55, 56, 58, 59, 60, + 61, 63, 64, 65, 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 81, + 82, 83, 84, 86, 87, 88, 90, 91, 92, 93, 95, 96, 97, 99, 100, 101, +102, 104, 105, 106, 108, 109, 110, 111, 113, 114, 115, 116, 118, 119, 120, 122, +123, 124, 125, 127, 128, 129, 131, 132, 133, 134, 136, 137, 138, 140, 141, 142, +143, 145, 146, 147, 148, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 163, +164, 165, 166, 168, 169, 170, 172, 173, 174, 175, 177, 178, 179, 180, 182, 183, +184, 186, 187, 188, 189, 191, 192, 193, 195, 196, 197, 198, 200, 201, 202, 204, +205, 206, 207, 209, 210, 211, 212, 214, 215, 216, 218, 219, 220, 221, 223, 224, +225, 227, 228, 229, 230, 232, 233, 234, 236, 237, 238, 239, 241, 242, 243, 244, +246, 247, 248, 250, 251, 252, 253, 255, 255, 255, 0, 255, 0, 0, 255, 0, +255, 255, 80, 96, 0, 144, 215, 255, 239, 187, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#endif + + +#ifdef CDL_NEED_LINESTYLES + +/* Define the linestyle arrays needed in the marker code. */ + +#define HOLLOW_LINE_WIDTH 5 +#define SHADOW_LINE_WIDTH 4 + +static char dash_pattern[] = {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }; +static char dot_pattern[] = {1, 1, 0, 0, 0, 0 }; +static char dotdash_pattern[] = {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0 }; + +static int dash = 0, sv_dash = 0, p_dash = 0, + dot = 0, sv_dot = 0, p_dot = 0, + dotdash = 0, sv_dotdash = 0, p_dotdash = 0; + +#define LEN_DASH 12 +#define LEN_DOT 6 +#define LEN_DOTDASH 19 + +#define DASH_PIXEL (dash_pattern[(dash++)%LEN_DASH]) +#define DOT_PIXEL (dot_pattern[(dot++)%LEN_DOT]) +#define DOTDASH_PIXEL (dotdash_pattern[(dotdash++)%LEN_DOTDASH]) + +#define SAVE_DASH_COUNT sv_dash=dash; +#define CLEAR_DASH_COUNT dash=0; +#define RESTORE_DASH_COUNT dash=sv_dash; + +#define SAVE_DOT_COUNT sv_dot=dot; +#define CLEAR_DOT_COUNT dot=0; +#define RESTORE_DOT_COUNT dot=sv_dot; + +#define SAVE_DOTDASH_COUNT sv_dotdash=dotdash; +#define CLEAR_DOTDASH_COUNT dotdash=0; +#define RESTORE_DOTDASH_COUNT dotdash=sv_dotdash; + +#endif diff --git a/astroem/cdlProto.h b/astroem/cdlProto.h new file mode 100644 index 00000000..fa867263 --- /dev/null +++ b/astroem/cdlProto.h @@ -0,0 +1,103 @@ +/* + * CDLPROTO.H -- CDL Library internal function prototype definitions. + */ + + +/* IMD Interface Function definitions. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef ANSI_FUNC + +IMDPtr imd_open(char *imtdev); +int imd_displayImage(IMDPtr imd, uchar *pix, int nx, int ny, int frame, int fbconfig, int comp_wcs); +int imd_readCursor(IMDPtr imd, int sample, float *x, float *y, int *wcs, char *key); +int imd_setWCS(IMDPtr imd, char *name, char *title, float a, float b, float c, float d, float tx, float ty, float z1, float z2, int zt); +int imd_getWCS(IMDPtr imd, int wcs, char *name, char *title, float *a, float *b, float *c, float *d, float *tx, float *ty, float *z1, float *z2, int *zt); +int imd_close(IMDPtr imd); +int imd_writeImage(IMDPtr imd, uchar *pix, int nx, int ny, int llx, int lly); +int imd_readImage(IMDPtr imd, uchar *pix, int *nx, int *ny); +int imd_readFrameBuffer(IMDPtr imd, uchar *pix, int *nx, int *ny); +int imd_setFrame(IMDPtr imd, int frame); +int imd_setFBConfig(IMDPtr imd, int configno); +int imd_getFBConfig(IMDPtr imd, int *configno, int *width, int *height, int *nframes); +int imd_setName(IMDPtr imd, char *name); +int imd_setTitle(IMDPtr imd, char *title); +int imd_setCursor(IMDPtr imd, int x, int y, int wcs); +int imd_clearFrame(IMDPtr imd); +int imd_readSubRaster(IMDPtr imd, int llx, int lly, int nx, int ny, uchar *pix); +int imd_writeSubRaster(IMDPtr imd, int llx, int lly, int nx, int ny, uchar *pix); +int imd_setDebug(int state); + +#else + +IMDPtr imd_open(); +int imd_setFBConfig(), imd_writeDisplay(), imd_readDisplay(); +int imd_setFrame(), imd_setCursor(), imd_readCursor(); +int imd_close(), imd_readSubRaster(), imd_writeSubRaster(); +int imd_clearFrame(), imd_setWCS(), imd_getWCS(); + +#endif + +#ifdef __cplusplus +} +#endif + + + +/* COMM Interface Function definitions. */ + +#ifdef ANSI_FUNC + +int com_writeData(int fd, short x, short y, uchar *pix, int nbytes); +int com_readData(int fdin, int fdout, short x, short y, uchar *pix, int *npix); +int com_readCursor(int fdin, int fdout, int sample, float *x, float *y, int *wcs, char *key); +int com_setCursor(int fd, int x, int y, int wcs); +int com_setFBConfig(int fd, int configno); +int com_setFrame(int fd, int frame_num); +int com_writeWCS(int fd, char *buffer, int nbytes, int version); +int com_readWCS(int fdin, int fdout, char *buffer, int *nbytes, int wcs,int version); +int com_eraseFrame(int fd); +int com_wcsVersion(int fdin, int fdout); + +int com_setDebug(int state); + +#else + +int com_writeData(), com_readData(), com_setFBConfig(); +int com_readCursor(), com_setCursor(), com_setFrame(); +int com_writeWCS(), com_readWCS(), com_eraseFrame(); +int com_setDebug(), com_wcsVersion(); + +#endif + + + +/* EPS Interface Function definitions. */ + +#ifdef ANSI_FUNC + +PSImage *eps_init(void); +void eps_print(PSImage *psim, FILE *fp, uchar *data, int xdim, int ydim, int depth, int pad); +void eps_close(PSImage *psim); +void eps_setPage(PSImage *psim, int orientation, int paper_size, int scale, int flags); +void eps_setCmap(PSImage *psim, uchar *r, uchar *g, uchar *b, int ncolors); +void eps_setCompress(PSImage *psim, int compress); +void eps_setColorType(PSImage *psim, int color_class); +void eps_setLabel(register PSImage *psim, char *label); +void eps_setTransform(PSImage *psim, float z1, float z2, int ztype, float offset, float scale, char *cmap_name); +void eps_setCorners(PSImage *psim, int llx, int lly, int urx, int ury); +void eps_getImageSize(PSImagePtr psim, int xdim, int ydim, float *width, float *height); +void eps_getImagePos(PSImagePtr psim, int xdim, int ydim, int *llx, int *lly); + +#else + +PSImage *eps_init(); +void eps_print(), eps_close(), eps_setPage(), eps_setCmap(); +void eps_setCompress(), eps_setColorType(), eps_setLabel(); +void eps_setTransform(), eps_setCorners(), eps_getImageSize(); +void eps_getImagePos(); + +#endif diff --git a/astroem/cdlzscale.c b/astroem/cdlzscale.c new file mode 100644 index 00000000..18d1b9d3 --- /dev/null +++ b/astroem/cdlzscale.c @@ -0,0 +1,687 @@ +#include +#include +#define CDL_LIBRARY_SOURCE +#include "cdl.h" + + +/* + * ZSCALE -- Compute the optimal Z1, Z2 (range of greyscale values to be + * displayed) of an image. For efficiency a statistical subsample of an image + * is used. The pixel sample evenly subsamples the image in x and y. The + * entire image is used if the number of pixels in the image is smaller than + * the desired sample. + * + * The sample is accumulated in a buffer and sorted by greyscale value. + * The median value is the central value of the sorted array. The slope of a + * straight line fitted to the sorted sample is a measure of the standard + * deviation of the sample about the median value. Our algorithm is to sort + * the sample and perform an iterative fit of a straight line to the sample, + * using pixel rejection to omit gross deviants near the endpoints. The fitted + * straight line is the transfer function used to map image Z into display Z. + * If more than half the pixels are rejected the full range is used. The slope + * of the fitted line is divided by the user-supplied contrast factor and the + * final Z1 and Z2 are computed, taking the origin of the fitted line at the + * median value. + */ + +#define MIN_NPIXELS 5 /* smallest permissible sample */ +#define MAX_REJECT 0.5 /* max frac. of pixels to be rejected */ +#define GOOD_PIXEL 0 /* use pixel in fit */ +#define BAD_PIXEL 1 /* ignore pixel in all computations */ +#define REJECT_PIXEL 2 /* reject pixel after a bit */ +#define KREJ 2.5 /* k-sigma pixel rejection factor */ +#define MAX_ITERATIONS 5 /* maximum number of fitline iterations */ + +#undef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#undef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#undef mod +#define mod(a,b) ((a) % (b)) +#undef nint +#define nint(a) ((int)(a + 0.5)) +#undef abs +#define abs(a) ((a) >= 0 ? (a) : -(a)) + + +extern int cdl_debug; + +#ifdef ANSI_FUNC + +void cdl_zscale(unsigned char *im, int nx, int ny, int bitpix, float *z1, float *z2, float contrast, int opt_size, int len_stdline); +int sampleImage(unsigned char *im, int bitpix, float **sample, int nx, int ny, int optimal_size, int len_stdline); + +static void subSample(float *a, float *b, int npix, int step); +int fitLine(float *data, int npix, float *zstart, float *zslope, float krej, int ngrow, int maxiter); +static void flattenData(float *data, float *flat, float *x, int npix, double +z0, double dz); +int computeSigma(float *a, char *badpix, int npix, double *mean, double *sigma); +int rejectPixels(float *data, float *flat, float *normx, char *badpix, int npix, double *sumxsqr, double *sumxz, double *sumx, double *sumz, double threshold, int ngrow); +int floatCompare(float *i, float *j); + +#else + +int rejectPixels(), computeSigma(); +int sampleImage(), fitLine(), floatCompare(); + +static void flattenData(); +static void subSample(); + +#endif + +/* Compatibility hacks. */ +#ifdef AUX + +#ifdef ANSI_FUNC +void * memmove (void *a, const void *b, size_t n) +#else +void *memmove(a,b,n) void *a; const void *b; size_t n; +#endif + + { bcopy(b,a,n); } + +#else + +#if defined(sun) && !defined(SYSV) + +#ifdef ANSI_FUNC +void * memmove (void *a, void *b, int n) +#else +void *memmove(a,b,n) void *a, *b; int n; +#endif + + { bcopy(b,a,n); } +#endif +#endif + + + +/* CDL_ZSCALE -- Sample the image and compute optimal Z1 and Z2 values. + */ + +#ifdef ANSI_FUNC + +void +cdl_zscale ( + unsigned char *im, /* image data to be sampled */ + int nx, + int ny, /* image dimensions */ + int bitpix, /* bits per pixel */ + float *z1, + float *z2, /* output min and max greyscale values */ + float contrast, /* adj. to slope of transfer function */ + int opt_size, /* desired number of pixels in sample */ + int len_stdline /* optimal number of pixels per line */ +) +#else + +void +cdl_zscale (im, nx, ny, bitpix, z1, z2, contrast, opt_size, len_stdline) + +unsigned char *im; /* image data to be sampled */ +int nx, ny; /* image dimensions */ +int bitpix; /* bits per pixel */ +float *z1, *z2; /* output min and max greyscale values */ +float contrast; /* adj. to slope of transfer function */ +int opt_size; /* desired number of pixels in sample */ +int len_stdline; /* optimal number of pixels per line */ +#endif +{ + register int npix, minpix, ngoodpix, center_pixel, ngrow; + float zmin, zmax, median; + float zstart, zslope; + float *sample = NULL, *left = NULL; + + + if (cdl_debug) + printf ("[cdl_zscale] %dx%d-%d cont=%g optsz=%d len=%d\n", + nx, ny, bitpix, contrast, opt_size, len_stdline); + + /* Subsample the image. */ + npix = sampleImage((unsigned char *)im, bitpix, &sample, nx, ny, + opt_size, len_stdline); + + /* Sort the sample, compute the minimum, maximum, and median pixel + * values. + */ + qsort (sample, npix, sizeof (float), floatCompare); + zmin = *sample; + zmax = *(sample+npix-1); + + /* The median value is the average of the two central values if there + * are an even number of pixels in the sample. + */ + center_pixel = max (1, (npix + 1) / 2); + left = &(sample[center_pixel - 1]); + if (mod (npix, 2) == 1 || center_pixel >= npix) + median = *left; + else + median = (*left + *(left+1)) / 2; + + /* Fit a line to the sorted sample vector. If more than half of the + * pixels in the sample are rejected give up and return the full range. + * If the user-supplied contrast factor is not 1.0 adjust the scale + * accordingly and compute Z1 and Z2, the y intercepts at indices 1 and + * npix. + */ + minpix = max (MIN_NPIXELS, (int) (npix * MAX_REJECT)); + ngrow = max (1, nint (npix * .01)); + ngoodpix = fitLine (sample, npix, &zstart, &zslope, + KREJ, ngrow, MAX_ITERATIONS); + + if (ngoodpix < minpix) { + *z1 = zmin; + *z2 = zmax; + } else { + if (contrast > 0) + zslope = zslope / contrast; + *z1 = max (zmin, median - (center_pixel - 1) * zslope); + *z2 = min (zmax, median + (npix - center_pixel) * zslope); + } + + if (cdl_debug) { + printf("[cdl_zscale] zmin=%g zmax=%g left=%g median=%g\n", + zmin, zmax, *left, median); + printf("[cdl_zscale] minpix=%d ngrow=%d ngoodpix=%d\n", + minpix, ngrow, ngoodpix); + printf("[cdl_zscale] zslope=%g center_pix=%d z1=%g z2=%g\n", + zslope, center_pixel, *z1, *z2); + } + + /* Clean up. */ + free ((float *)sample); +} + + +/* sampleImage -- Extract an evenly gridded subsample of the pixels from + * a two-dimensional image into a one-dimensional vector. + */ + +#ifdef ANSI_FUNC + +int +sampleImage ( + unsigned char *im, /* image to be sampled */ + int bitpix, /* bits per pixel in image */ + float **sample, /* output vector containing the sample */ + int nx, + int ny, /* image dimensions */ + int optimal_size, /* desired number of pixels in sample */ + int len_stdline /* optimal number of pixels per line */ +) +#else + +int +sampleImage (im, bitpix, sample, nx, ny, optimal_size, len_stdline) + +unsigned char *im; /* image to be sampled */ +int bitpix; /* bits per pixel in image */ +float **sample; /* output vector containing the sample */ +int nx, ny; /* image dimensions */ +int optimal_size; /* desired number of pixels in sample */ +int len_stdline; /* optimal number of pixels per line */ +#endif +{ + register int i; + int ncols, nlines, col_step, line_step, maxpix, line; + int opt_npix_per_line, npix_per_line, npix = 0; + int opt_nlines_in_sample, min_nlines_in_sample, max_nlines_in_sample; + float *op = NULL, *row = NULL; + int *ipix = NULL; + float *fpix = NULL; + double *dpix = NULL; + short *spix = NULL; + char *bpix = NULL; + + + ncols = nx; + nlines = ny; + + /* Compute the number of pixels each line will contribute to the sample, + * and the subsampling step size for a line. The sampling grid must + * span the whole line on a uniform grid. + */ + opt_npix_per_line = max (1, min (ncols, len_stdline)); + col_step = max (2, (ncols + opt_npix_per_line-1) / opt_npix_per_line); + npix_per_line = max (1, (ncols + col_step-1) / col_step); + if (cdl_debug) + printf ("[sampleImage] opt_npix/line=%d col_step=%d n/line=%d\n", + opt_npix_per_line, col_step, npix_per_line); + + /* Compute the number of lines to sample and the spacing between lines. + * We must ensure that the image is adequately sampled despite its + * size, hence there is a lower limit on the number of lines in the + * sample. We also want to minimize the number of lines accessed when + * accessing a large image, because each disk seek and read is ex- + * pensive. The number of lines extracted will be roughly the sample + * size divided by len_stdline, possibly more if the lines are very + * short. + */ + min_nlines_in_sample = max (1, optimal_size / len_stdline); + opt_nlines_in_sample = max(min_nlines_in_sample, min(nlines, + (optimal_size + npix_per_line-1) / npix_per_line)); + line_step = max (2, nlines / (opt_nlines_in_sample)); + max_nlines_in_sample = (nlines + line_step-1) / line_step; + if (cdl_debug) + printf ("[sampleImage] nl_in_samp=%d/%d opt_nl/samp=%d lstep=%d\n", + min_nlines_in_sample, opt_nlines_in_sample, line_step, + max_nlines_in_sample); + + /* Allocate space for the output vector. Buffer must be freed by our + * caller. + */ + maxpix = npix_per_line * max_nlines_in_sample; + *sample = (float *) malloc (maxpix * sizeof (float)); + row = (float *) malloc (nx * sizeof (float)); + + /* Extract the vector. */ + op = *sample; + for (line = (line_step + 1)/2; line < nlines; line+=line_step) { + /* Load a row of float values from the image */ + switch (bitpix) { + case 8: + bpix = (char *) &im[(line-1) * nx * sizeof(char)]; + for (i=0; i < nx; i++) + row[i] = (float) bpix[i]; + break; + case 16: + spix = (short *) &im[(line-1) * nx * sizeof(short)]; + for (i=0; i < nx; i++) + row[i] = (float) spix[i]; + break; + case 32: + ipix = (int *) &im[(line-1) * nx * sizeof(int)]; + for (i=0; i < nx; i++) + row[i] = (float) ipix[i]; + break; + case -32: + fpix = (float *) &im[(line-1) * nx * sizeof(float)]; + for (i=0; i < nx; i++) + row[i] = (float) fpix[i]; + break; + case -64: + dpix = (double *) &im[(line-1) * nx * sizeof(double)]; + for (i=0; i < nx; i++) + row[i] = (float) dpix[i]; + break; + } + + subSample (row, op, npix_per_line, col_step); + op += npix_per_line; + npix += npix_per_line; + if (npix > maxpix) + break; + } + + free ((float *)row); + return (npix); +} + + +/* subSample -- Subsample an image line. Extract the first pixel and + * every "step"th pixel thereafter for a total of npix pixels. + */ + +#ifdef ANSI_FUNC + +static void +subSample (float *a, float *b, int npix, int step) +#else + +static void +subSample (a, b, npix, step) +float *a; +float *b; +int npix, step; +#endif +{ + register int ip, i; + + if (step <= 1) + memmove (b, a, npix); + else { + ip = 0; + for (i=0; i < npix; i++) { + b[i] = a[ip]; + ip += step; + } + } +} + + +/* fitLine -- Fit a straight line to a data array of type real. This is + * an iterative fitting algorithm, wherein points further than ksigma from the + * current fit are excluded from the next fit. Convergence occurs when the + * next iteration does not decrease the number of pixels in the fit, or when + * there are no pixels left. The number of pixels left after pixel rejection + * is returned as the function value. + */ + +#ifdef ANSI_FUNC + +int +fitLine ( + float *data, /* data to be fitted */ + int npix, /* number of pixels before rejection */ + float *zstart, /* Z-value of pixel data[1] (output) */ + float *zslope, /* dz/pixel (output) */ + float krej, /* k-sigma pixel rejection factor */ + int ngrow, /* number of pixels of growing */ + int maxiter /* max iterations */ +) +#else + +int +fitLine (data, npix, zstart, zslope, krej, ngrow, maxiter) + +float *data; /* data to be fitted */ +int npix; /* number of pixels before rejection */ +float *zstart; /* Z-value of pixel data[1] (output) */ +float *zslope; /* dz/pixel (output) */ +float krej; /* k-sigma pixel rejection factor */ +int ngrow; /* number of pixels of growing */ +int maxiter; /* max iterations */ +#endif +{ + int i, ngoodpix, last_ngoodpix, minpix, niter; + double xscale, z0, dz, o_dz, x, z, mean, sigma, threshold; + double sumxsqr, sumxz, sumz, sumx, rowrat; + float *flat, *normx; + char *badpix; + + if (npix <= 0) + return (0); + else if (npix == 1) { + *zstart = data[1]; + *zslope = 0.0; + return (1); + } else + xscale = 2.0 / (npix - 1); + + /* Allocate a buffer for data minus fitted curve, another for the + * normalized X values, and another to flag rejected pixels. + */ + flat = (float *) malloc (npix * sizeof (float)); + normx = (float *) malloc (npix * sizeof (float)); + badpix = (char *) calloc (npix, sizeof(char)); + + /* Compute normalized X vector. The data X values [1:npix] are + * normalized to the range [-1:1]. This diagonalizes the lsq matrix + * and reduces its condition number. + */ + for (i=0; i 0) { + rowrat = sumx / sumxsqr; + z0 = (sumz - rowrat * sumxz) / (ngoodpix - rowrat * sumx); + dz = (sumxz - z0 * sumx) / sumxsqr; + } + + if (ngoodpix >= last_ngoodpix || ngoodpix < minpix) + break; + } + + /* Transform the line coefficients back to the X range [1:npix]. */ + *zstart = z0 - dz; + *zslope = dz * xscale; + if (abs(*zslope) < 0.001) + *zslope = o_dz * xscale; + + free ((float *)flat); + free ((float *)normx); + free ((char *)badpix); + return (ngoodpix); +} + + +/* flattenData -- Compute and subtract the fitted line from the data array, + * returned the flattened data in FLAT. + */ + +#ifdef ANSI_FUNC + +static void +flattenData ( + float *data, /* raw data array */ + float *flat, /* flattened data (output) */ + float *x, /* x value of each pixel */ + int npix, /* number of pixels */ + double z0, + double dz /* z-intercept, dz/dx of fitted line */ +) +#else + +static void +flattenData (data, flat, x, npix, z0, dz) +float *data; /* raw data array */ +float *flat; /* flattened data (output) */ +float *x; /* x value of each pixel */ +int npix; /* number of pixels */ +double z0, dz; /* z-intercept, dz/dx of fitted line */ +#endif +{ + register int i; + + for (i=0; i < npix; i++) + flat[i] = data[i] - (x[i] * dz + z0); +} + + +/* computeSigma -- Compute the root mean square deviation from the + * mean of a flattened array. Ignore rejected pixels. + */ + +#ifdef ANSI_FUNC + +int +computeSigma ( + float *a, /* flattened data array */ + char *badpix, /* bad pixel flags (!= 0 if bad pixel) */ + int npix, + double *mean, + double *sigma /* (output) */ +) +#else + +int +computeSigma (a, badpix, npix, mean, sigma) + +float *a; /* flattened data array */ +char *badpix; /* bad pixel flags (!= 0 if bad pixel) */ +int npix; +double *mean, *sigma; /* (output) */ +#endif +{ + float pixval; + int i, ngoodpix = 0; + double sum = 0.0, sumsq = 0.0, temp; + + /* Accumulate sum and sum of squares. */ + for (i=0; i < npix; i++) + if (badpix[i] == GOOD_PIXEL) { + pixval = a[i]; + ngoodpix = ngoodpix + 1; + sum = sum + pixval; + sumsq = sumsq + pixval * pixval; + } + + /* Compute mean and sigma. */ + switch (ngoodpix) { + case 0: + *mean = INDEF; + *sigma = INDEF; + break; + case 1: + *mean = sum; + *sigma = INDEF; + break; + default: + *mean = sum / (double) ngoodpix; + temp = sumsq / (double) (ngoodpix-1) - + (sum*sum) / (double) (ngoodpix*(ngoodpix - 1)); + if (temp < 0) /* possible with roundoff error */ + *sigma = 0.0; + else + *sigma = sqrt (temp); + } + + return (ngoodpix); +} + + +/* rejectPixels -- Detect and reject pixels more than "threshold" greyscale + * units from the fitted line. The residuals about the fitted line are given + * by the "flat" array, while the raw data is in "data". Each time a pixel + * is rejected subtract its contributions from the matrix sums and flag the + * pixel as rejected. When a pixel is rejected reject its neighbors out to + * a specified radius as well. This speeds up convergence considerably and + * produces a more stringent rejection criteria which takes advantage of the + * fact that bad pixels tend to be clumped. The number of pixels left in the + * fit is returned as the function value. + */ + +#ifdef ANSI_FUNC + +int +rejectPixels ( + float *data, /* raw data array */ + float *flat, /* flattened data array */ + float *normx, /* normalized x values of pixels */ + char *badpix, /* bad pixel flags (!= 0 if bad pixel) */ + int npix, + double *sumxsqr, + double *sumxz, + double *sumx, + double *sumz,/* matrix sums */ + double threshold, /* threshold for pixel rejection */ + int ngrow /* number of pixels of growing */ +) +#else + +int +rejectPixels (data, flat, normx, badpix, npix, + sumxsqr, sumxz, sumx, sumz, threshold, ngrow) + +float *data; /* raw data array */ +float *flat; /* flattened data array */ +float *normx; /* normalized x values of pixels */ +char *badpix; /* bad pixel flags (!= 0 if bad) */ +int npix; +double *sumxsqr,*sumxz,*sumx,*sumz; /* matrix sums */ +double threshold; /* threshold for pixel rejection */ +int ngrow; /* number of pixels of growing */ +#endif +{ + int ngoodpix, i, j; + float residual, lcut, hcut; + double x, z; + + ngoodpix = npix; + lcut = -threshold; + hcut = threshold; + + for (i=0; i < npix; i++) { + if (badpix[i] == BAD_PIXEL) + ngoodpix = ngoodpix - 1; + else { + residual = flat[i]; + if (residual < lcut || residual > hcut) { + /* Reject the pixel and its neighbors out to the growing + * radius. We must be careful how we do this to avoid + * directional effects. Do not turn off thresholding on + * pixels in the forward direction; mark them for rejection + * but do not reject until they have been thresholded. + * If this is not done growing will not be symmetric. + */ + for (j=max(0,i-ngrow); j < min(npix,i+ngrow); j++) { + if (badpix[j] != BAD_PIXEL) { + if (j <= i) { + x = (double) normx[j]; + z = (double) data[j]; + *sumxsqr = *sumxsqr - (x * x); + *sumxz = *sumxz - z * x; + *sumx = *sumx - x; + *sumz = *sumz - z; + badpix[j] = BAD_PIXEL; + ngoodpix = ngoodpix - 1; + } else + badpix[j] = REJECT_PIXEL; + } + } + } + } + } + + return (ngoodpix); +} + + +#ifdef ANSI_FUNC + +int +floatCompare (float *i, float *j) +#else + +int floatCompare (i,j) +float *i, *j; +#endif +{ + return ((*i <= *j) ? -1 : 1); +} diff --git a/astroem/cel.c b/astroem/cel.c new file mode 100644 index 00000000..91092843 --- /dev/null +++ b/astroem/cel.c @@ -0,0 +1,474 @@ +/*============================================================================= +* +* WCSLIB - an implementation of the FITS WCS proposal. +* Copyright (C) 1995-2002, Mark Calabretta +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +* Correspondence concerning WCSLIB may be directed to: +* Internet email: mcalabre@atnf.csiro.au +* Postal address: Dr. Mark Calabretta, +* Australia Telescope National Facility, +* P.O. Box 76, +* Epping, NSW, 2121, +* AUSTRALIA +* +*============================================================================= +* +* C routines which implement the FITS World Coordinate System (WCS) +* convention. +* +* Summary of routines +* ------------------- +* These routines are provided as drivers for the lower level spherical +* coordinate transformation and projection routines. There are separate +* driver routines for the forward, celfwd(), and reverse, celrev(), +* transformations. +* +* An initialization routine, celset(), computes intermediate values from +* the transformation parameters but need not be called explicitly - see the +* explanation of cel.flag below. +* +* +* Initialization routine; celset() +* -------------------------------- +* Initializes members of a celprm data structure which hold intermediate +* values. Note that this routine need not be called directly; it will be +* invoked by celfwd() and celrev() if the "flag" structure member is +* anything other than a predefined magic value. +* +* Given: +* pcode[4] const char +* WCS projection code (see below). +* +* Given and returned: +* cel celprm* Spherical coordinate transformation parameters +* (see below). +* prj prjprm* Projection parameters (usage is described in the +* prologue to "proj.c"). +* +* Function return value: +* int Error status +* 0: Success. +* 1: Invalid coordinate transformation parameters. +* 2: Ill-conditioned coordinate transformation +* parameters. +* +* Forward transformation; celfwd() +* -------------------------------- +* Compute (x,y) coordinates in the plane of projection from celestial +* coordinates (lng,lat). +* +* Given: +* pcode[4] const char +* WCS projection code (see below). +* lng,lat const double +* Celestial longitude and latitude of the projected +* point, in degrees. +* +* Given and returned: +* cel celprm* Spherical coordinate transformation parameters +* (see below). +* +* Returned: +* phi, double* Longitude and latitude in the native coordinate +* theta system of the projection, in degrees. +* +* Given and returned: +* prj prjprm* Projection parameters (usage is described in the +* prologue to "proj.c"). +* +* Returned: +* x,y double* Projected coordinates, "degrees". +* +* Function return value: +* int Error status +* 0: Success. +* 1: Invalid coordinate transformation parameters. +* 2: Invalid projection parameters. +* 3: Invalid value of (lng,lat). +* +* Reverse transformation; celrev() +* -------------------------------- +* Compute the celestial coordinates (lng,lat) of the point with projected +* coordinates (x,y). +* +* Given: +* pcode[4] const char +* WCS projection code (see below). +* x,y const double +* Projected coordinates, "degrees". +* +* Given and returned: +* prj prjprm* Projection parameters (usage is described in the +* prologue to "proj.c"). +* +* Returned: +* phi, double* Longitude and latitude in the native coordinate +* theta system of the projection, in degrees. +* +* Given and returned: +* cel celprm* Spherical coordinate transformation parameters +* (see below). +* +* Returned: +* lng,lat double* Celestial longitude and latitude of the projected +* point, in degrees. +* +* Function return value: +* int Error status +* 0: Success. +* 1: Invalid coordinate transformation parameters. +* 2: Invalid projection parameters. +* 3: Invalid value of (x,y). +* +* Coordinate transformation parameters +* ------------------------------------ +* The celprm struct consists of the following: +* +* int flag +* The celprm struct contains pointers to the forward and reverse +* projection routines as well as intermediaries computed from the +* reference coordinates (see below). Whenever the projection code +* (pcode) or any of ref[4] are set or changed then this flag must be +* set to zero to signal the initialization routine, celset(), to +* redetermine the function pointers and recompute intermediaries. +* Once this has been done pcode itself is ignored. +* +* double ref[4] +* The first pair of values should be set to the celestial longitude +* and latitude (usually right ascension and declination) of the +* reference point of the projection. These are given by the CRVALn +* keywords in FITS. +* +* The second pair of values are the native longitude of the celestial +* pole and the celestial latitude of the native pole and correspond to +* FITS keywords LONPOLE and LATPOLE. +* +* LONPOLE defaults to 0 degrees if the celestial latitude of the +* reference point of the projection is greater than the native +* latitude, otherwise 180 degrees. (This is the condition for the +* celestial latitude to increase in the same direction as the native +* latitude at the reference point.) ref[2] may be set to 999.0 to +* indicate that the correct default should be substituted. +* +* In some circumstances the celestial latitude of the native pole may +* be determined by the first three values only to within a sign and +* LATPOLE is used to choose between the two solutions. LATPOLE is +* set in ref[3] and the solution closest to this value is used to +* reset ref[3]. It is therefore legitimate, for example, to set +* ref[3] to 999.0 to choose the more northerly solution - the default +* if the LATPOLE card is omitted from the FITS header. For the +* special case where the reference point of the projection is at +* native latitude zero, its celestial latitude is zero, and +* LONPOLE = +/- 90 then the celestial latitude of the pole is not +* determined by the first three reference values and LATPOLE +* specifies it completely. +* +* The remaining members of the celprm struct are maintained by the +* initialization routines and should not be modified. This is done for the +* sake of efficiency and to allow an arbitrary number of contexts to be +* maintained simultaneously. +* +* double euler[5] +* Euler angles and associated intermediaries derived from the +* coordinate reference values. +* +* +* WCS projection codes +* -------------------- +* Zenithals/azimuthals: +* AZP: zenithal/azimuthal perspective +* TAN: gnomonic +* STG: stereographic +* SIN: synthesis (generalized orthographic) +* ARC: zenithal/azimuthal equidistant +* ZPN: zenithal/azimuthal polynomial +* ZEA: zenithal/azimuthal equal area +* AIR: Airy +* +* Cylindricals: +* CYP: cylindrical perspective +* CEA: cylindrical equal area +* CAR: Cartesian +* MER: Mercator +* +* Pseudo-cylindricals: +* SFL: Sanson-Flamsteed +* PAR: parabolic +* MOL: Mollweide +* +* Conventional: +* AIT: Hammer-Aitoff +* +* Conics: +* COP: conic perspective +* COD: conic equidistant +* COE: conic equal area +* COO: conic orthomorphic +* +* Polyconics: +* BON: Bonne +* PCO: polyconic +* +* Quad-cubes: +* TSC: tangential spherical cube +* CSC: COBE quadrilateralized spherical cube +* QSC: quadrilateralized spherical cube +* +* Author: Mark Calabretta, Australia Telescope National Facility +* $Id: cel.c,v 2.14 2002/04/03 01:25:29 mcalabre Exp $ +*===========================================================================*/ + +#include +#include +#include "wcslib.h" + +/* Map error number to error message for each function. */ +const char *celset_errmsg[] = { + 0, + "Invalid coordinate transformation parameters", + "Ill-conditioned coordinate transformation parameters"}; + +const char *celfwd_errmsg[] = { + 0, + "Invalid coordinate transformation parameters", + "Invalid projection parameters", + "Invalid value of (lng,lat)"}; + +const char *celrev_errmsg[] = { + 0, + "Invalid coordinate transformation parameters", + "Invalid projection parameters", + "Invalid value of (x,y)"}; + + +int +celset(pcode, cel, prj) + +const char pcode[4]; +struct celprm *cel; +struct prjprm *prj; + +{ + int dophip; + const double tol = 1.0e-10; + double clat0, cphip, cthe0, slat0, sphip, sthe0; + double latp, latp1, latp2; + double u, v, x, y, z; + + /* Initialize the projection driver routines. */ + if (prjset(pcode, prj)) { + return 1; + } + + /* Set default for native longitude of the celestial pole? */ + dophip = (cel->ref[2] == 999.0); + + /* Compute celestial coordinates of the native pole. */ + if (prj->theta0 == 90.0) { + /* Reference point is at the native pole. */ + + if (dophip) { + /* Set default for longitude of the celestial pole. */ + cel->ref[2] = 180.0; + } + + latp = cel->ref[1]; + cel->ref[3] = latp; + + cel->euler[0] = cel->ref[0]; + cel->euler[1] = 90.0 - latp; + } else { + /* Reference point away from the native pole. */ + + /* Set default for longitude of the celestial pole. */ + if (dophip) { + cel->ref[2] = (cel->ref[1] < prj->theta0) ? 180.0 : 0.0; + } + + clat0 = cosdeg (cel->ref[1]); + slat0 = sindeg (cel->ref[1]); + cphip = cosdeg (cel->ref[2]); + sphip = sindeg (cel->ref[2]); + cthe0 = cosdeg (prj->theta0); + sthe0 = sindeg (prj->theta0); + + x = cthe0*cphip; + y = sthe0; + z = sqrt(x*x + y*y); + if (z == 0.0) { + if (slat0 != 0.0) { + return 1; + } + + /* latp determined by LATPOLE in this case. */ + latp = cel->ref[3]; + } else { + if (fabs(slat0/z) > 1.0) { + return 1; + } + + u = atan2deg (y,x); + v = acosdeg (slat0/z); + + latp1 = u + v; + if (latp1 > 180.0) { + latp1 -= 360.0; + } else if (latp1 < -180.0) { + latp1 += 360.0; + } + + latp2 = u - v; + if (latp2 > 180.0) { + latp2 -= 360.0; + } else if (latp2 < -180.0) { + latp2 += 360.0; + } + + if (fabs(cel->ref[3]-latp1) < fabs(cel->ref[3]-latp2)) { + if (fabs(latp1) < 90.0+tol) { + latp = latp1; + } else { + latp = latp2; + } + } else { + if (fabs(latp2) < 90.0+tol) { + latp = latp2; + } else { + latp = latp1; + } + } + + cel->ref[3] = latp; + } + + cel->euler[1] = 90.0 - latp; + + z = cosdeg (latp)*clat0; + if (fabs(z) < tol) { + if (fabs(clat0) < tol) { + /* Celestial pole at the reference point. */ + cel->euler[0] = cel->ref[0]; + cel->euler[1] = 90.0 - prj->theta0; + } else if (latp > 0.0) { + /* Celestial pole at the native north pole.*/ + cel->euler[0] = cel->ref[0] + cel->ref[2] - 180.0; + cel->euler[1] = 0.0; + } else if (latp < 0.0) { + /* Celestial pole at the native south pole. */ + cel->euler[0] = cel->ref[0] - cel->ref[2]; + cel->euler[1] = 180.0; + } + } else { + x = (sthe0 - sindeg (latp)*slat0)/z; + y = sphip*cthe0/clat0; + if (x == 0.0 && y == 0.0) { + return 1; + } + cel->euler[0] = cel->ref[0] - atan2deg (y,x); + } + + /* Make euler[0] the same sign as ref[0]. */ + if (cel->ref[0] >= 0.0) { + if (cel->euler[0] < 0.0) cel->euler[0] += 360.0; + } else { + if (cel->euler[0] > 0.0) cel->euler[0] -= 360.0; + } + } + + cel->euler[2] = cel->ref[2]; + cel->euler[3] = cosdeg (cel->euler[1]); + cel->euler[4] = sindeg (cel->euler[1]); + cel->flag = CELSET; + + /* Check for ill-conditioned parameters. */ + if (fabs(latp) > 90.0+tol) { + return 2; + } + + return 0; +} + +/*--------------------------------------------------------------------------*/ + +int +celfwd(pcode, lng, lat, cel, phi, theta, prj, x, y) + +const char pcode[4]; +const double lng, lat; +struct celprm *cel; +double *phi, *theta; +struct prjprm *prj; +double *x, *y; + +{ + int err; + + if (cel->flag != CELSET) { + if (celset(pcode, cel, prj)) return 1; + } + + /* Compute native coordinates. */ + sphfwd(lng, lat, cel->euler, phi, theta); + + /* Apply forward projection. */ + if ((err = prj->prjfwd(*phi, *theta, prj, x, y))) { + return err == 1 ? 2 : 3; + } + + return 0; +} + +/*--------------------------------------------------------------------------*/ + +int +celrev(pcode, x, y, prj, phi, theta, cel, lng, lat) + +const char pcode[4]; +const double x, y; +struct prjprm *prj; +double *phi, *theta; +struct celprm *cel; +double *lng, *lat; + +{ + int err; + + if (cel->flag != CELSET) { + if(celset(pcode, cel, prj)) return 1; + } + + /* Apply reverse projection. */ + if ((err = prj->prjrev(x, y, prj, phi, theta))) { + return err == 1 ? 2 : 3; + } + + /* Compute native coordinates. */ + sphrev(*phi, *theta, cel->euler, lng, lat); + + return 0; +} + +/* Dec 20 1999 Doug Mink - Change cosd() and sind() to cosdeg() and sindeg() + * Dec 20 1999 Doug Mink - Include wcslib.h, which includes wcsmath.h and cel.h + * + * Dec 18 2000 Doug Mink - Include string.h for strcmp() + * + * Mar 20 2001 Doug Mink - Add () around err assignments in if statements + * Sep 19 2001 Doug Mink - Add above changes to WCSLIB-2.7 cel.c + * + * Mar 12 2002 Doug Mink - Add changes to WCSLIB-2.8.2 cel.c + */ diff --git a/astroem/dateutil.c b/astroem/dateutil.c new file mode 100644 index 00000000..ada0c95a --- /dev/null +++ b/astroem/dateutil.c @@ -0,0 +1,4554 @@ +/*** File libwcs/dateutil.c + *** October 19, 2012 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1999-2012 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + */ + +/* Date and time conversion routines using the following conventions: + ang = Angle in fractional degrees + deg = Angle in degrees as dd:mm:ss.ss + doy = 2 floating point numbers: year and day, including fraction, of year + *** First day of year is 1, not zero. + dt = 2 floating point numbers: yyyy.mmdd, hh.mmssssss + ep = fractional year, often epoch of a position including proper motion + epb = Besselian epoch = 365.242198781-day years based on 1900.0 + epj = Julian epoch = 365.25-day years based on 2000.0 + fd = FITS date string which may be any of the following: + yyyy.ffff (fractional year) + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) + hr = Sexigesimal hours as hh:mm:dd.ss + jd = Julian Date + lt = Local time + mjd = modified Julian Date = JD - 2400000.5 + ofd = FITS date string (dd/mm/yy before 2000, else no return) + time = use fd2* with no date to convert time as hh:mm:ss.ss to sec, day, year + ts = UT seconds since 1950-01-01T00:00 (used for ephemeris computations) + tsi = local seconds since 1980-01-01T00:00 (used by IRAF as a time tag) + tsu = UT seconds since 1970-01-01T00:00 (used as Unix system time) + tsd = UT seconds of current day + ut = Universal Time (UTC) + et = Ephemeris Time (or TDB or TT) = TAI + 32.184 seconds + tai = International Atomic Time (Temps Atomique International) = ET - 32.184 seconds + gps = GPS time = TAI - 19 seconds + mst = Mean Greenwich Sidereal Time + gst = Greenwich Sidereal Time (includes nutation) + lst = Local Sidereal Time (includes nutation) (longitude must be set) + hjd = Heliocentric Julian Date + mhjd = modified Heliocentric Julian Date = HJD - 2400000.5 + + * ang2hr (angle) + * Convert angle in decimal floating point degrees to hours as hh:mm:ss.ss + * ang2deg (angle) + * Convert angle in decimal floating point degrees to degrees as dd:mm:ss.ss + * deg2ang (angle as dd:mm:ss.ss) + * Convert angle in degrees as dd:mm:ss.ss to decimal floating point degrees + * ang2hr (angle) + * Convert angle in hours as hh:mm:ss.ss to decimal floating point degrees + * + * doy2dt (year, doy, date, time) + * Convert year and day of year to date as yyyy.ddmm and time as hh.mmsss + * doy2ep, doy2epb, doy2epj (date, time) + * Convert year and day of year to fractional year + * doy2fd (year, doy) + * Convert year and day of year to FITS date string + * doy2mjd (year, doy) + * Convert year and day of year to modified Julian date + * + * dt2doy (date, time, year, doy) + * Convert date as yyyy.ddmm and time as hh.mmsss to year and day of year + * dt2ep, dt2epb, dt2epj (date, time) + * Convert date as yyyy.ddmm and time as hh.mmsss to fractional year + * dt2fd (date, time) + * Convert date as yyyy.ddmm and time as hh.mmsss to FITS date string + * dt2i (date,time,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert yyyy.mmdd hh.mmssss to year month day hours minutes seconds + * dt2jd (date,time) + * Convert date as yyyy.ddmm and time as hh.mmsss to Julian date + * dt2mjd (date,time) + * Convert date as yyyy.ddmm and time as hh.mmsss to modified Julian date + * dt2ts (date,time) + * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1950-01-01 + * dt2tsi (date,time) + * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1980-01-01 + * dt2tsu (date,time) + * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1970-01-01 + * + * ep2dt, epb2dt, epj2dt (epoch,date, time) + * Convert fractional year to date as yyyy.ddmm and time as hh.mmsss + * ep2fd, epb2fd, epj2fd (epoch) + * Convert epoch to FITS ISO date string + * ep2i, epb2i, epj2i (epoch,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert fractional year to year month day hours minutes seconds + * ep2jd, epb2jd, epj2jd (epoch) + * Convert fractional year as used in epoch to Julian date + * ep2mjd, epb2mjd, epj2mjd (epoch) + * Convert fractional year as used in epoch to modified Julian date + * ep2ts, epb2ts, epj2ts (epoch) + * Convert fractional year to seconds since 1950.0 + * + * et2fd (string) + * Convert from ET (or TDT or TT) in FITS format to UT in FITS format + * fd2et (string) + * Convert from UT in FITS format to ET (or TDT or TT) in FITS format + * jd2jed (dj) + * Convert from Julian Date to Julian Ephemeris Date + * jed2jd (dj) + * Convert from Julian Ephemeris Date to Julian Date + * dt2et (date, time) + * Convert date (yyyy.ddmm) and time (hh.mmsss) to ephemeris time + * edt2dt (date, time) + * Convert ephemeris date (yyyy.ddmm) and time (hh.mmsss) to UT + * dt2tai (date, time) + * Convert date (yyyy.ddmm) and time (hh.mmsss) to TAI date and time + * tai2dt (date, time) + * Convert TAI date (yyyy.ddmm) and time (hh.mmsss) to UT + * ts2ets (tsec) + * Convert from UT in seconds since 1950-01-01 to ET in same format + * ets2ts (tsec) + * Convert from ET in seconds since 1950-01-01 to UT in same format + * + * fd2ep, fd2epb, fd2epj (string) + * Convert FITS date string to fractional year + * Convert time alone to fraction of Besselian year + * fd2doy (string, year, doy) + * Convert FITS standard date string to year and day of year + * fd2dt (string, date, time) + * Convert FITS date string to date as yyyy.ddmm and time as hh.mmsss + * Convert time alone to hh.mmssss with date set to 0.0 + * fd2i (string,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert FITS standard date string to year month day hours min sec + * Convert time alone to hours min sec, year month day are zero + * fd2jd (string) + * Convert FITS standard date string to Julian date + * Convert time alone to fraction of day + * fd2mjd (string) + * Convert FITS standard date string to modified Julian date + * fd2ts (string) + * Convert FITS standard date string to seconds since 1950.0 + * Convert time alone to seconds of day + * fd2fd (string) + * Convert FITS standard date string to ISO FITS date string + * fd2of (string) + * Convert FITS standard date string to old-format FITS date and time + * fd2ofd (string) + * Convert FITS standard date string to old-format FITS date string + * fd2oft (string) + * Convert time part of FITS standard date string to FITS date string + * + * jd2doy (dj, year, doy) + * Convert Julian date to year and day of year + * jd2dt (dj,date,time) + * Convert Julian date to date as yyyy.mmdd and time as hh.mmssss + * jd2ep, jd2epb, jd2epj (dj) + * Convert Julian date to fractional year as used in epoch + * jd2fd (dj) + * Convert Julian date to FITS ISO date string + * jd2i (dj,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert Julian date to year month day hours min sec + * jd2mjd (dj) + * Convert Julian date to modified Julian date + * jd2ts (dj) + * Convert Julian day to seconds since 1950.0 + * + * lt2dt() + * Return local time as yyyy.mmdd and time as hh.mmssss + * lt2fd() + * Return local time as FITS ISO date string + * lt2tsi() + * Return local time as IRAF seconds since 1980-01-01 00:00 + * lt2tsu() + * Return local time as Unix seconds since 1970-01-01 00:00 + * lt2ts() + * Return local time as Unix seconds since 1950-01-01 00:00 + * + * mjd2doy (dj,year,doy) + * Convert modified Julian date to date as year and day of year + * mjd2dt (dj,date,time) + * Convert modified Julian date to date as yyyy.mmdd and time as hh.mmssss + * mjd2ep, mjd2epb, mjd2epj (dj) + * Convert modified Julian date to fractional year as used in epoch + * mjd2fd (dj) + * Convert modified Julian date to FITS ISO date string + * mjd2i (dj,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert modified Julian date to year month day hours min sec + * mjd2jd (dj) + * Convert modified Julian date to Julian date + * mjd2ts (dj) + * Convert modified Julian day to seconds since 1950.0 + * + * ts2dt (tsec,date,time) + * Convert seconds since 1950.0 to date as yyyy.ddmm and time as hh.mmsss + * ts2ep, ts2epb, ts2epj (tsec) + * Convert seconds since 1950.0 to fractional year + * ts2fd (tsec) + * Convert seconds since 1950.0 to FITS standard date string + * ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert sec since 1950.0 to year month day hours minutes seconds + * ts2jd (tsec) + * Convert seconds since 1950.0 to Julian date + * ts2mjd (tsec) + * Convert seconds since 1950.0 to modified Julian date + * tsi2fd (tsec) + * Convert seconds since 1980-01-01 to FITS standard date string + * tsi2dt (tsec,date,time) + * Convert seconds since 1980-01-01 to date as yyyy.ddmm, time as hh.mmsss + * tsu2fd (tsec) + * Convert seconds since 1970-01-01 to FITS standard date string + * tsu2tsi (tsec) + * Convert UT seconds since 1970-01-01 to local seconds since 1980-01-01 + * tsu2dt (tsec,date,time) + * Convert seconds since 1970-01-01 to date as yyyy.ddmm, time as hh.mmsss + * + * tsd2fd (tsec) + * Convert seconds since start of day to FITS time, hh:mm:ss.ss + * tsd2dt (tsec) + * Convert seconds since start of day to hh.mmssss + * + * fd2gst (string) + * convert from FITS date Greenwich Sidereal Time + * dt2gst (date, time) + * convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time + * ts2gst (tsec) + * Calculate Greenwich Sidereal Time given Universal Time + * in seconds since 1951-01-01T0:00:00 + * fd2mst (string) + * convert from FITS UT date to Mean Sidereal Time + * dt2gmt (date, time) + * convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time + * ts2mst (tsec) + * Calculate Mean Sidereal Time given Universal Time + * in seconds since 1951-01-01T0:00:00 + * jd2mst (string) + * convert from Julian Date to Mean Sidereal Time + * mst2fd (string) + * convert to current UT in FITS format given Greenwich Mean Sidereal Time + * mst2jd (dj) + * convert to current UT as Julian Date given Greenwich Mean Sidereal Time + * jd2lst (dj) + * Calculate Local Sidereal Time from Julian Date + * ts2lst (tsec) + * Calculate Local Sidereal Time given UT in seconds since 1951-01-01T0:00 + * fd2lst (string) + * Calculate Local Sidereal Time given Universal Time as FITS ISO date + * lst2jd (dj, lst) + * Calculate Julian Date given current Julian date and Local Sidereal Time + * lst2fd (string, lst) + * Calculate Julian Date given current UT date and Local Sidereal Time + * gst2fd (string) + * Calculate current UT given UT date and Greenwich Sidereal Time + * gst2jd (dj) + * Calculate current UT given UT date and Greenwich Sidereal Time as JD + * + * compnut (dj, dpsi, deps, eps0) + * Compute the longitude and obliquity components of nutation and + * mean obliquity from the IAU 1980 theory + * + * utdt (dj) + * Compute difference between UT and dynamical time (ET-UT) + * ut2dt (year, doy) + * Current Universal Time to year and day of year + * ut2dt (date, time) + * Current Universal Time to date (yyyy.mmdd) and time (hh.mmsss) + * ut2ep(), ut2epb(), ut2epj() + * Current Universal Time to fractional year, Besselian, Julian epoch + * ut2fd() + * Current Universal Time to FITS ISO date string + * ut2jd() + * Current Universal Time to Julian Date + * ut2mjd() + * Current Universal Time to Modified Julian Date + * ut2tsi() + * Current Universal Time to IRAF seconds since 1980-01-01T00:00 + * ut2tsu() + * Current Universal Time to Unix seconds since 1970-01-01T00:00 + * ut2ts() + * Current Universal Time to seconds since 1950-01-01T00:00 + * isdate (string) + * Return 1 if string is a FITS date (old or ISO) + * + * Internally-used subroutines + * + * fixdate (iyr, imon, iday, ihr, imn, sec, ndsec) + * Round seconds and make sure date and time numbers are within limits + * caldays (year, month) + * Calculate days in month 1-12 given year (Gregorian calendar only + * dint (dnum) + * Return integer part of floating point number + * dmod (dnum) + * Return Mod of floating point number + */ + +#include +#include +#include +#include +#include +#include +#include "wcs.h" +#include "fitsfile.h" + +static double suntl(); +static void fixdate(); +static int caldays(); +static double dint(); +static double dmod(); + +static double longitude = 0.0; /* longitude of observatory in degrees (+=west) */ +void +setlongitude (longitude0) +double longitude0; +{ longitude = longitude0; return; } + +static int ndec = 3; +void +setdatedec (nd) +int nd; +{ ndec = nd; return; } + +/* ANG2HR -- Convert angle in fraction degrees to hours as hh:mm:ss.ss */ + +void +ang2hr (angle, lstr, string) + +double angle; /* Angle in fractional degrees */ +int lstr; /* Maximum number of characters in string */ +char *string; /* Character string (hh:mm:ss.ss returned) */ + +{ + angle = angle / 15.0; + dec2str (string, lstr, angle, ndec); + return; +} + + +/* ANG2DEG -- Convert angle in fraction degrees to degrees as dd:mm:ss.ss */ + +void +ang2deg (angle, lstr, string) + +double angle; /* Angle in fractional degrees */ +int lstr; /* Maximum number of characters in string */ +char *string; /* Character string (dd:mm:ss.ss returned) */ +{ + dec2str (string, lstr, angle, ndec); + return; +} + + +/* DEG2ANG -- Convert angle in degrees as dd:mm:ss.ss to fractional degrees */ + +double +deg2ang (angle) + +char *angle; /* Angle as dd:mm:ss.ss */ +{ + double deg; + + deg = str2dec (angle); + return (deg); +} + +/* HR2ANG -- Convert angle in hours as hh:mm:ss.ss to fractional degrees */ + +double +hr2ang (angle) + +char *angle; /* Angle in sexigesimal hours (hh:mm:ss.sss) */ + +{ + double deg; + + deg = str2dec (angle); + deg = deg * 15.0; + return (deg); +} + + +/* DT2FD-- convert vigesimal date and time to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +dt2fd (date, time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + int nf; + char *string; + char tstring[32], dstring[32]; + char outform[64]; + + dt2i (date, time, &iyr,&imon,&iday,&ihr,&imn,&sec, ndec); + + /* Convert to ISO date format */ + string = (char *) calloc (32, sizeof (char)); + + /* Make time string */ + if (time != 0.0 || ndec > 0) { + if (ndec == 0) + nf = 2; + else + nf = 3 + ndec; + if (ndec > 0) { + sprintf (outform, "%%02d:%%02d:%%0%d.%df", nf, ndec); + sprintf (tstring, outform, ihr, imn, sec); + } + else { + sprintf (outform, "%%02d:%%02d:%%0%dd", nf); + sprintf (tstring, outform, ihr, imn, (int)(sec+0.5)); + } + } + + /* Make date string */ + if (date != 0.0) + sprintf (dstring, "%4d-%02d-%02d", iyr, imon, iday); + + /* Make FITS (ISO) date string */ + if (date == 0.0) + strcpy (string, tstring); + else if (time == 0.0 && ndec < 1) + strcpy (string, dstring); + else + sprintf (string, "%sT%s", dstring, tstring); + + return (string); +} + + +/* DT2JD-- convert from date as yyyy.mmdd and time as hh.mmsss to Julian Date + * Return fractional days if date is zero */ + +double +dt2jd (date,time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Julian date (returned) */ + double tsec; /* seconds since 1950.0 */ + + tsec = dt2ts (date, time); + if (date == 0.0) + dj = tsec / 86400.0; + else + dj = ts2jd (tsec); + + return (dj); +} + + +/* DT2MJD-- convert from date yyyy.mmdd time hh.mmsss to modified Julian Date + * Return fractional days if date is zero */ + +double +dt2mjd (date,time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Modified Julian date (returned) */ + double tsec; /* seconds since 1950.0 */ + + tsec = dt2ts (date, time); + if (date == 0.0) + dj = tsec / 86400.0; + else + dj = ts2jd (tsec); + + return (dj - 2400000.5); +} + + +/* HJD2JD-- convert Heliocentric Julian Date to (geocentric) Julian date */ + +double +hjd2jd (dj, ra, dec, sys) + +double dj; /* Heliocentric Julian date */ +double ra; /* Right ascension (degrees) */ +double dec; /* Declination (degrees) */ +int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ +{ + double lt; /* Light travel difference to the Sun (days) */ + + lt = suntl (dj, ra, dec, sys); + + /* Return Heliocentric Julian Date */ + return (dj - lt); +} + + +/* JD2HJD-- convert (geocentric) Julian date to Heliocentric Julian Date */ + +double +jd2hjd (dj, ra, dec, sys) + +double dj; /* Julian date (geocentric) */ +double ra; /* Right ascension (degrees) */ +double dec; /* Declination (degrees) */ +int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ +{ + double lt; /* Light travel difference to the Sun (days) */ + + lt = suntl (dj, ra, dec, sys); + + /* Return Heliocentric Julian Date */ + return (dj + lt); +} + + +/* MHJD2MJD-- convert modified Heliocentric Julian Date to + modified geocentric Julian date */ + +double +mhjd2mjd (mhjd, ra, dec, sys) + +double mhjd; /* Modified Heliocentric Julian date */ +double ra; /* Right ascension (degrees) */ +double dec; /* Declination (degrees) */ +int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ +{ + double lt; /* Light travel difference to the Sun (days) */ + double hjd; /* Heliocentric Julian date */ + + hjd = mjd2jd (mhjd); + + lt = suntl (hjd, ra, dec, sys); + + /* Return Heliocentric Julian Date */ + return (jd2mjd (hjd - lt)); +} + + +/* MJD2MHJD-- convert modified geocentric Julian date tp + modified Heliocentric Julian Date */ + +double +mjd2mhjd (mjd, ra, dec, sys) + +double mjd; /* Julian date (geocentric) */ +double ra; /* Right ascension (degrees) */ +double dec; /* Declination (degrees) */ +int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ +{ + double lt; /* Light travel difference to the Sun (days) */ + double dj; /* Julian date (geocentric) */ + + dj = mjd2jd (mjd); + + lt = suntl (dj, ra, dec, sys); + + /* Return Heliocentric Julian Date */ + return (jd2mjd (dj + lt)); +} + + +/* SUNTL-- compute light travel time to heliocentric correction in days */ +/* Translated into C from IRAF SPP noao.astutils.asttools.asthjd.x */ + +static double +suntl (dj, ra, dec, sys) + +double dj; /* Julian date (geocentric) */ +double ra; /* Right ascension (degrees) */ +double dec; /* Declination (degrees) */ +int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ +{ + double t; /* Number of Julian centuries since J1900 */ + double manom; /* Mean anomaly of the Earth's orbit (degrees) */ + double lperi; /* Mean longitude of perihelion (degrees) */ + double oblq; /* Mean obliquity of the ecliptic (degrees) */ + double eccen; /* Eccentricity of the Earth's orbit (dimensionless) */ + double eccen2, eccen3; + double tanom; /* True anomaly (approximate formula) (radians) */ + double slong; /* True longitude of the Sun from the Earth (radians) */ + double rs; /* Distance to the sun (AU) */ + double lt; /* Light travel difference to the Sun (days) */ + double l; /* Longitude of star in orbital plane of Earth (radians) */ + double b; /* Latitude of star in orbital plane of Earth (radians) */ + double epoch; /* Epoch of obervation */ + double rs1,rs2; + + t = (dj - 2415020.0) / 36525.0; + + /* Compute earth orbital parameters */ + manom = 358.47583 + (t * (35999.04975 - t * (0.000150 + t * 0.000003))); + lperi = 101.22083 + (t * (1.7191733 + t * (0.000453 + t * 0.000003))); + oblq = 23.452294 - (t * (0.0130125 + t * (0.00000164 - t * 0.000000503))); + eccen = 0.01675104 - (t * (0.00004180 + t * 0.000000126)); + eccen2 = eccen * eccen; + eccen3 = eccen * eccen2; + + /* Convert to principle angles */ + manom = manom - (360.0 * (dint) (manom / 360.0)); + lperi = lperi - (360.0 * (dint) (lperi / 360.0)); + + /* Convert to radians */ + manom = degrad (manom); + lperi = degrad (lperi); + oblq = degrad (oblq); + + /* True anomaly */ + tanom = manom + (2 * eccen - 0.25 * eccen3) * sin (manom) + + 1.25 * eccen2 * sin (2 * manom) + + 13./12. * eccen3 * sin (3 * manom); + + /* Distance to the Sun */ + rs1 = 1.0 - eccen2; + rs2 = 1.0 + (eccen * cos (tanom)); + rs = rs1 / rs2; + + /* True longitude of the Sun seen from the Earth */ + slong = lperi + tanom + PI; + + /* Longitude and latitude of star in orbital plane of the Earth */ + epoch = jd2ep (dj); + wcscon (sys, WCS_ECLIPTIC, 0.0, 0.0, &ra, &dec, epoch); + l = degrad (ra); + b = degrad (dec); + + /* Light travel difference to the Sun */ + lt = -0.005770 * rs * cos (b) * cos (l - slong); + + /* Return light travel difference */ + return (lt); +} + + +/* JD2DT-- convert Julian date to date as yyyy.mmdd and time as hh.mmssss */ + +void +jd2dt (dj,date,time) + +double dj; /* Julian date */ +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + /* Convert Julian Date to date and time */ + jd2i (dj, &iyr, &imon, &iday, &ihr, &imn, &sec, 4); + + /* Convert date to yyyy.mmdd */ + if (iyr < 0) { + *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; + *date = -(*date); + } + else + *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; + + /* Convert time to hh.mmssssss */ + *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; + + return; +} + + +/* JD2I-- convert Julian date to date as year, month, and day, and time hours, + minutes, and seconds */ +/* after Fliegel and Van Flander, CACM 11, 657 (1968) */ + + +void +jd2i (dj, iyr, imon, iday, ihr, imn, sec, ndsec) + +double dj; /* Julian date */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ + +{ + double tsec; + double frac, dts, ts, sday; + int jd, l, n, i, j; + + tsec = jd2ts (dj); + /* ts2i (tsec, iyr, imon, iday, ihr, imn, sec, ndsec); */ + + /* Round seconds to 0 - 4 decimal places */ + if (tsec < 0.0) + dts = -0.5; + else + dts = 0.5; + if (ndsec < 1) + ts = dint (tsec + dts); + else if (ndsec < 2) + ts = dint (tsec * 10.0 + dts) / 10.0; + else if (ndsec < 3) + ts = dint (tsec * 100.0 + dts) / 100.0; + else if (ndsec < 4) + ts = dint (tsec * 1000.0 + dts) / 1000.0; + else + ts = dint (tsec * 10000.0 + dts) / 10000.0; + + /* Convert back to Julian Date */ + dj = ts2jd (ts); + + /* Compute time from fraction of a day */ + frac = dmod (dj, 1.0); + if (frac < 0.5) { + jd = (int) (dj - frac); + sday = (frac + 0.5) * 86400.0; + } + else { + jd = (int) (dj - frac) + 1; + sday = (frac - 0.5) * 86400.0; + } + + *ihr = (int) (sday / 3600.0); + sday = sday - (double) (*ihr * 3600); + *imn = (int) (sday / 60.0); + *sec = sday - (double) (*imn * 60); + + /* Compute day, month, year */ + l = jd + 68569; + n = (4 * l) / 146097; + l = l - (146097 * n + 3) / 4; + i = (4000 * (l + 1)) / 1461001; + l = l - (1461 * i) / 4 + 31; + j = (80 * l) / 2447; + *iday = l - (2447 * j) / 80; + l = j / 11; + *imon = j + 2 - (12 * l); + *iyr = 100 * (n - 49) + i + l; + + return; +} + + +/* JD2MJD-- convert Julian Date to Modified Julian Date */ + +double +jd2mjd (dj) + +double dj; /* Julian Date */ + +{ + return (dj - 2400000.5); +} + + +/* JD2EP-- convert Julian date to fractional year as used in epoch */ + +double +jd2ep (dj) + +double dj; /* Julian date */ + +{ + double date, time; + jd2dt (dj, &date, &time); + return (dt2ep (date, time)); +} + + +/* JD2EPB-- convert Julian date to Besselian epoch */ + +double +jd2epb (dj) + +double dj; /* Julian date */ + +{ + return (1900.0 + (dj - 2415020.31352) / 365.242198781); +} + + +/* JD2EPJ-- convert Julian date to Julian epoch */ + +double +jd2epj (dj) + +double dj; /* Julian date */ + +{ + return (2000.0 + (dj - 2451545.0) / 365.25); +} + + +/* LT2DT-- Return local time as yyyy.mmdd and time as hh.mmssss */ + +void +lt2dt(date, time) + +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ + +{ + time_t tsec; + struct timeval tp; + struct timezone tzp; + struct tm *ts; + + gettimeofday (&tp,&tzp); + + tsec = tp.tv_sec; + ts = localtime (&tsec); + + if (ts->tm_year < 1000) + *date = (double) (ts->tm_year + 1900); + else + *date = (double) ts->tm_year; + *date = *date + (0.01 * (double) (ts->tm_mon + 1)); + *date = *date + (0.0001 * (double) ts->tm_mday); + *time = (double) ts->tm_hour; + *time = *time + (0.01 * (double) ts->tm_min); + *time = *time + (0.0001 * (double) ts->tm_sec); + + return; +} + + +/* LT2FD-- Return current local time as FITS ISO date string */ + +char * +lt2fd() +{ + time_t tsec; + struct tm *ts; + struct timeval tp; + struct timezone tzp; + int month, day, year, hour, minute, second; + char *isotime; + + gettimeofday (&tp,&tzp); + tsec = tp.tv_sec; + + ts = localtime (&tsec); + + year = ts->tm_year; + if (year < 1000) + year = year + 1900; + month = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + minute = ts->tm_min; + second = ts->tm_sec; + + isotime = (char *) calloc (32, sizeof (char)); + sprintf (isotime, "%04d-%02d-%02dT%02d:%02d:%02d", + year, month, day, hour, minute, second); + return (isotime); +} + + +/* LT2TSI-- Return local time as IRAF seconds since 1980-01-01 00:00 */ + +int +lt2tsi() +{ + return ((int)(lt2ts() - 946684800.0)); +} + + +/* LT2TSU-- Return local time as Unix seconds since 1970-01-01 00:00 */ + +time_t +lt2tsu() +{ + return ((time_t)(lt2ts() - 631152000.0)); +} + +/* LT2TS-- Return local time as Unix seconds since 1950-01-01 00:00 */ + +double +lt2ts() +{ + double tsec; + char *datestring; + datestring = lt2fd(); + tsec = fd2ts (datestring); + free (datestring); + return (tsec); +} + + +/* MJD2DT-- convert Modified Julian Date to date (yyyy.mmdd) time (hh.mmssss) */ + +void +mjd2dt (dj,date,time) + +double dj; /* Modified Julian Date */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double tsec; + + tsec = jd2ts (dj + 2400000.5); + ts2dt (tsec, date, time); + + return; +} + + +/* MJD2I-- convert Modified Julian Date to date as year, month, day and + time as hours, minutes, seconds */ + +void +mjd2i (dj, iyr, imon, iday, ihr, imn, sec, ndsec) + +double dj; /* Modified Julian Date */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ + +{ + double tsec; + + tsec = jd2ts (dj + 2400000.5); + ts2i (tsec, iyr, imon, iday, ihr, imn, sec, ndsec); + return; +} + + +/* MJD2DOY-- convert Modified Julian Date to Year,Day-of-Year */ + +void +mjd2doy (dj, year, doy) + +double dj; /* Modified Julian Date */ +int *year; /* Year (returned) */ +double *doy; /* Day of year with fraction (returned) */ + +{ + jd2doy (dj + 2400000.5, year, doy); + return; +} + + +/* MJD2JD-- convert Modified Julian Date to Julian Date */ + +double +mjd2jd (dj) + +double dj; /* Modified Julian Date */ + +{ + return (dj + 2400000.5); +} + + +/* MJD2EP-- convert Modified Julian Date to fractional year */ + +double +mjd2ep (dj) + +double dj; /* Modified Julian Date */ + +{ + double date, time; + jd2dt (dj + 2400000.5, &date, &time); + return (dt2ep (date, time)); +} + + +/* MJD2EPB-- convert Modified Julian Date to Besselian epoch */ + +double +mjd2epb (dj) + +double dj; /* Modified Julian Date */ + +{ + return (1900.0 + (dj - 15019.81352) / 365.242198781); +} + + +/* MJD2EPJ-- convert Modified Julian Date to Julian epoch */ + +double +mjd2epj (dj) + +double dj; /* Modified Julian Date */ + +{ + return (2000.0 + (dj - 51544.5) / 365.25); +} + + +/* MJD2FD-- convert modified Julian date to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +mjd2fd (dj) + +double dj; /* Modified Julian date */ +{ + return (jd2fd (dj + 2400000.5)); +} + + +/* MJD2TS-- convert modified Julian date to seconds since 1950.0 */ + +double +mjd2ts (dj) + +double dj; /* Modified Julian date */ +{ + return ((dj - 33282.0) * 86400.0); +} + + +/* EP2FD-- convert fractional year to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +ep2fd (epoch) + +double epoch; /* Date as fractional year */ +{ + double tsec; /* seconds since 1950.0 (returned) */ + tsec = ep2ts (epoch); + return (ts2fd (tsec)); +} + + +/* EPB2FD-- convert Besselian epoch to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +epb2fd (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +{ + double dj; /* Julian Date */ + dj = epb2jd (epoch); + return (jd2fd (dj)); +} + + +/* EPJ2FD-- convert Julian epoch to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +epj2fd (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +{ + double dj; /* Julian Date */ + dj = epj2jd (epoch); + return (jd2fd (dj)); +} + + +/* EP2TS-- convert fractional year to seconds since 1950.0 */ + +double +ep2ts (epoch) + +double epoch; /* Date as fractional year */ +{ + double dj; + dj = ep2jd (epoch); + return ((dj - 2433282.5) * 86400.0); +} + + +/* EPB2TS-- convert Besselian epoch to seconds since 1950.0 */ + +double +epb2ts (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +{ + double dj; + dj = epb2jd (epoch); + return ((dj - 2433282.5) * 86400.0); +} + + +/* EPJ2TS-- convert Julian epoch to seconds since 1950.0 */ + +double +epj2ts (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +{ + double dj; + dj = epj2jd (epoch); + return ((dj - 2433282.5) * 86400.0); +} + + +/* EPB2EP-- convert Besselian epoch to fractional years */ + +double +epb2ep (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +{ + double dj; + dj = epb2jd (epoch); + return (jd2ep (dj)); +} + + +/* EP2EPB-- convert fractional year to Besselian epoch */ + +double +ep2epb (epoch) + +double epoch; /* Fractional year */ +{ + double dj; + dj = ep2jd (epoch); + return (jd2epb (dj)); +} + + +/* EPJ2EP-- convert Julian epoch to fractional year */ + +double +epj2ep (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +{ + double dj; + dj = epj2jd (epoch); + return (jd2ep (dj)); +} + + +/* EP2EPJ-- convert fractional year to Julian epoch */ + +double +ep2epj (epoch) + +double epoch; /* Fractional year */ +{ + double dj; + dj = ep2jd (epoch); + return (jd2epj (dj)); +} + + +/* EP2I-- convert fractional year to year month day hours min sec */ + +void +ep2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) + +double epoch; /* Date as fractional year */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ +{ + double date, time; + + ep2dt (epoch, &date, &time); + dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); + return; +} + + +/* EPB2I-- convert Besselian epoch to year month day hours min sec */ + +void +epb2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ +{ + double date, time; + + epb2dt (epoch, &date, &time); + dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); + return; +} + + +/* EPJ2I-- convert Julian epoch to year month day hours min sec */ + +void +epj2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ +{ + double date, time; + + epj2dt (epoch, &date, &time); + dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); + return; +} + + +/* EP2JD-- convert fractional year as used in epoch to Julian date */ + +double +ep2jd (epoch) + +double epoch; /* Date as fractional year */ + +{ + double dj; /* Julian date (returned)*/ + double date, time; + + ep2dt (epoch, &date, &time); + dj = dt2jd (date, time); + return (dj); +} + + +/* EPB2JD-- convert Besselian epoch to Julian Date */ + +double +epb2jd (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ + +{ + return (2415020.31352 + ((epoch - 1900.0) * 365.242198781)); +} + + +/* EPJ2JD-- convert Julian epoch to Julian Date */ + +double +epj2jd (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ + +{ + return (2451545.0 + ((epoch - 2000.0) * 365.25)); +} + + +/* EP2MJD-- convert fractional year as used in epoch to modified Julian date */ + +double +ep2mjd (epoch) + +double epoch; /* Date as fractional year */ + +{ + double dj; /* Julian date (returned)*/ + double date, time; + + ep2dt (epoch, &date, &time); + dj = dt2jd (date, time); + return (dj - 2400000.5); +} + + +/* EPB2MJD-- convert Besselian epoch to modified Julian Date */ + +double +epb2mjd (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ + +{ + return (15019.81352 + ((epoch - 1900.0) * 365.242198781)); +} + + +/* EPJ2MJD-- convert Julian epoch to modified Julian Date */ + +double +epj2mjd (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ + +{ + return (51544.5 + ((epoch - 2000.0) * 365.25)); +} + + + +/* EPB2EPJ-- convert Besselian epoch to Julian epoch */ + +double +epb2epj (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +{ + double dj; /* Julian date */ + dj = epb2jd (epoch); + return (jd2epj (dj)); +} + + +/* EPJ2EPB-- convert Julian epoch to Besselian epoch */ + +double +epj2epb (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +{ + double dj; /* Julian date */ + dj = epj2jd (epoch); + return (jd2epb (dj)); +} + + +/* JD2FD-- convert Julian date to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +jd2fd (dj) + +double dj; /* Julian date */ +{ + double tsec; /* seconds since 1950.0 (returned) */ + tsec = (dj - 2433282.5) * 86400.0; + return (ts2fd (tsec)); +} + + +/* JD2TS-- convert Julian date to seconds since 1950.0 */ + +double +jd2ts (dj) + +double dj; /* Julian date */ +{ + return ((dj - 2433282.5) * 86400.0); +} + + +/* JD2TSI-- convert Julian date to IRAF seconds since 1980-01-01T0:00 */ + +int +jd2tsi (dj) + +double dj; /* Julian date */ +{ + double ts; + ts = (dj - 2444239.5) * 86400.0; + return ((int) ts); +} + + +/* JD2TSU-- convert Julian date to Unix seconds since 1970-01-01T0:00 */ + +time_t +jd2tsu (dj) + +double dj; /* Julian date */ +{ + return ((time_t)((dj - 2440587.5) * 86400.0)); +} + + +/* DT2DOY-- convert yyyy.mmdd hh.mmss to year and day of year */ + +void +dt2doy (date, time, year, doy) + +double date; /* Date as yyyy.mmdd */ +double time; /* Time as hh.mmssxxxx */ +int *year; /* Year (returned) */ +double *doy; /* Day of year with fraction (returned) */ +{ + double dj; /* Julian date */ + double dj0; /* Julian date on January 1 0:00 */ + double date0; /* January first of date's year */ + double dyear; + + dyear = floor (date); + date0 = dyear + 0.0101; + dj0 = dt2jd (date0, 0.0); + dj = dt2jd (date, time); + *year = (int) (dyear + 0.00000001); + *doy = dj - dj0 + 1.0; + return; +} + + +/* DOY2DT-- convert year and day of year to yyyy.mmdd hh.mmss */ + +void +doy2dt (year, doy, date, time) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ +{ + double dj; /* Julian date */ + double dj0; /* Julian date on January 1 0:00 */ + double date0; /* January first of date's year */ + + date0 = year + 0.0101; + dj0 = dt2jd (date0, 0.0); + dj = dj0 + doy - 1.0; + jd2dt (dj, date, time); + return; +} + + +/* DOY2EP-- convert year and day of year to fractional year as used in epoch */ + +double +doy2ep (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double date, time; + doy2dt (year, doy, &date, &time); + return (dt2ep (date, time)); +} + + + +/* DOY2EPB-- convert year and day of year to Besellian epoch */ + +double +doy2epb (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; + dj = doy2jd (year, doy); + return (jd2epb (dj)); +} + + +/* DOY2EPJ-- convert year and day of year to Julian epoch */ + +double +doy2epj (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; + dj = doy2jd (year, doy); + return (jd2epj (dj)); +} + + +/* DOY2FD-- convert year and day of year to FITS date */ + +char * +doy2fd (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; /* Julian date */ + + dj = doy2jd (year, doy); + return (jd2fd (dj)); +} + + +/* DOY2JD-- convert year and day of year to Julian date */ + +double +doy2jd (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj0; /* Julian date */ + double date; /* Date as yyyy.mmdd (returned) */ + double time; /* Time as hh.mmssxxxx (returned) */ + + date = (double) year + 0.0101; + time = 0.0; + dj0 = dt2jd (date, time); + return (dj0 + doy - 1.0); +} + + +/* DOY2MJD-- convert year and day of year to Julian date */ + +double +doy2mjd (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj0; /* Julian date */ + double date; /* Date as yyyy.mmdd (returned) */ + double time; /* Time as hh.mmssxxxx (returned) */ + + date = (double) year + 0.0101; + time = 0.0; + dj0 = dt2jd (date, time); + return (dj0 + doy - 1.0 - 2400000.5); +} + + +/* DOY2TSU-- convert from FITS date to Unix seconds since 1970-01-01T0:00 */ + +time_t +doy2tsu (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; + dj = doy2jd (year, doy); + return ((time_t)jd2ts (dj)); +} + + +/* DOY2TSI-- convert from FITS date to IRAF seconds since 1980-01-01T0:00 */ + +int +doy2tsi (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; + dj = doy2jd (year, doy); + return ((int)jd2tsi (dj)); +} + + +/* DOY2TS-- convert year, day of year to seconds since 1950 */ + +double +doy2ts (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; + dj = doy2jd (year, doy); + return (jd2ts (dj)); +} + + +/* FD2DOY-- convert FITS date to year and day of year */ + +void +fd2doy (string, year, doy) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +int *year; /* Year (returned) */ +double *doy; /* Day of year with fraction (returned) */ +{ + double dj; /* Julian date */ + + dj = fd2jd (string); + jd2doy (dj, year, doy); + return; +} + + +/* JD2DOY-- convert Julian date to year and day of year */ + +void +jd2doy (dj, year, doy) + +double dj; /* Julian date */ +int *year; /* Year (returned) */ +double *doy; /* Day of year with fraction (returned) */ +{ + double date; /* Date as yyyy.mmdd (returned) */ + double time; /* Time as hh.mmssxxxx (returned) */ + double dj0; /* Julian date at 0:00 on 1/1 */ + double dyear; + + jd2dt (dj, &date, &time); + *year = (int) date; + dyear = (double) *year; + dj0 = dt2jd (dyear+0.0101, 0.0); + *doy = dj - dj0 + 1.0; + return; +} + + +/* TS2JD-- convert seconds since 1950.0 to Julian date */ + +double +ts2jd (tsec) + +double tsec; /* seconds since 1950.0 */ +{ + return (2433282.5 + (tsec / 86400.0)); +} + + +/* TS2MJD-- convert seconds since 1950.0 to modified Julian date */ + +double +ts2mjd (tsec) + +double tsec; /* seconds since 1950.0 */ +{ + return (33282.0 + (tsec / 86400.0)); +} + + +/* TS2EP-- convert seconds since 1950.0 to fractional year as used in epoch */ + +double +ts2ep (tsec) + +double tsec; /* Seconds since 1950.0 */ + +{ + double date, time; + ts2dt (tsec, &date, &time); + return (dt2ep (date, time)); +} + + +/* TS2EPB-- convert seconds since 1950.0 to Besselian epoch */ + +double +ts2epb (tsec) + +double tsec; /* Seconds since 1950.0 */ + +{ + double dj; /* Julian Date */ + dj = ts2jd (tsec); + return (jd2epb (dj)); +} + + +/* TS2EPB-- convert seconds since 1950.0 to Julian epoch */ + +double +ts2epj (tsec) + +double tsec; /* Seconds since 1950.0 */ + +{ + double dj; /* Julian Date */ + dj = ts2jd (tsec); + return (jd2epj (dj)); +} + + +/* DT2EP-- convert from date, time as yyyy.mmdd hh.mmsss to fractional year */ + +double +dt2ep (date, time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double epoch; /* Date as fractional year (returned) */ + double dj, dj0, dj1, date0, time0, date1; + + dj = dt2jd (date, time); + if (date == 0.0) + epoch = dj / 365.2422; + else { + time0 = 0.0; + date0 = dint (date) + 0.0101; + date1 = dint (date) + 1.0101; + dj0 = dt2jd (date0, time0); + dj1 = dt2jd (date1, time0); + epoch = dint (date) + ((dj - dj0) / (dj1 - dj0)); + } + return (epoch); +} + + +/* DT2EPB-- convert from date, time as yyyy.mmdd hh.mmsss to Besselian epoch */ + +double +dt2epb (date, time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Julian date */ + double epoch; /* Date as fractional year (returned) */ + dj = dt2jd (date, time); + if (date == 0.0) + epoch = dj / 365.242198781; + else + epoch = jd2epb (dj); + return (epoch); +} + + +/* DT2EPJ-- convert from date, time as yyyy.mmdd hh.mmsss to Julian epoch */ + +double +dt2epj (date, time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Julian date */ + double epoch; /* Date as fractional year (returned) */ + dj = dt2jd (date, time); + if (date == 0.0) + epoch = dj / 365.25; + else + epoch = jd2epj (dj); + return (epoch); +} + + +/* EP2DT-- convert from fractional year to date, time as yyyy.mmdd hh.mmsss */ + +void +ep2dt (epoch, date, time) + +double epoch; /* Date as fractional year */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj, dj0, dj1, date0, time0, date1, epochi, epochf; + + time0 = 0.0; + epochi = dint (epoch); + epochf = epoch - epochi; + date0 = epochi + 0.0101; + date1 = epochi + 1.0101; + dj0 = dt2jd (date0, time0); + dj1 = dt2jd (date1, time0); + dj = dj0 + epochf * (dj1 - dj0); + jd2dt (dj, date, time); + return; +} + + +/* EPB2DT-- convert from Besselian epoch to date, time as yyyy.mmdd hh.mmsss */ + +void +epb2dt (epoch, date, time) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Julian date */ + dj = epb2jd (epoch); + jd2dt (dj, date, time); +} + + +/* EPJ2DT-- convert from Julian epoch to date, time as yyyy.mmdd hh.mmsss */ + +void +epj2dt (epoch, date, time) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Julian date */ + dj = epj2jd (epoch); + jd2dt (dj, date, time); +} + + +/* FD2JD-- convert FITS standard date to Julian date */ + +double +fd2jd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double date, time; + + fd2dt (string, &date, &time); + return (dt2jd (date, time)); +} + + +/* FD2MJD-- convert FITS standard date to modified Julian date */ + +double +fd2mjd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + return (fd2jd (string) - 2400000.5); +} + + +/* FD2TSU-- convert from FITS date to Unix seconds since 1970-01-01T0:00 */ + +time_t +fd2tsu (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double date, time; + fd2dt (string, &date, &time); + return (dt2tsu (date, time)); +} + + +/* FD2TSI-- convert from FITS date to IRAF seconds since 1980-01-01T0:00 */ + +int +fd2tsi (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double date, time; + fd2dt (string, &date, &time); + return (dt2tsi (date, time)); +} + + +/* FD2TS-- convert FITS standard date to seconds since 1950 */ + +double +fd2ts (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double date, time; + fd2dt (string, &date, &time); + return (dt2ts (date, time)); +} + + +/* FD2FD-- convert any FITS standard date to ISO FITS standard date */ + +char * +fd2fd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double date, time; + fd2dt (string, &date, &time); + return (dt2fd (date, time)); +} + + +/* FD2OF-- convert any FITS standard date to old FITS standard date time */ + +char * +fd2of (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); + + /* Convert to old FITS date format */ + string = (char *) calloc (32, sizeof (char)); + if (iyr < 1900) + sprintf (string, "*** date out of range ***"); + else if (iyr < 2000) + sprintf (string, "%02d/%02d/%02d %02d:%02d:%06.3f", + iday, imon, iyr-1900, ihr, imn, sec); + else if (iyr < 2900.0) + sprintf (string, "%02d/%02d/%3d %02d:%02d:%6.3f", + iday, imon, iyr-1900, ihr, imn, sec); + else + sprintf (string, "*** date out of range ***"); + return (string); +} + + +/* TAI-UTC from the U.S. Naval Observatory */ +/* ftp://maia.usno.navy.mil/ser7/tai-utc.dat */ +static double taijd[26]={2441317.5, 2441499.5, 2441683.5, 2442048.5, 2442413.5, + 2442778.5, 2443144.5, 2443509.5, 2443874.5, 2444239.5, 2444786.5, + 2445151.5, 2445516.5, 2446247.5, 2447161.5, 2447892.5, 2448257.5, + 2448804.5, 2449169.5, 2449534.5, 2450083.5, 2450630.5, 2451179.5, + 2453736.5, 2454832.5, 2456293.5}; +static double taidt[26]={10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0, + 20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0,32.0, + 33.0,34.0,35.0}; +static double dttab[173]={13.7,13.4,13.1,12.9,12.7,12.6,12.5,12.5,12.5,12.5, + 12.5,12.5,12.5,12.5,12.5,12.5,12.5,12.4,12.3,12.2,12.0,11.7,11.4, + 11.1,10.6,10.2, 9.6, 9.1, 8.6, 8.0, 7.5, 7.0, 6.6, 6.3, 6.0, 5.8, + 5.7, 5.6, 5.6, 5.6, 5.7, 5.8, 5.9, 6.1, 6.2, 6.3, 6.5, 6.6, 6.8, + 6.9, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.7, 7.8, 7.8,7.88,7.82, + 7.54, 6.97, 6.40, 6.02, 5.41, 4.10, 2.92, 1.82, 1.61, 0.10,-1.02, + -1.28,-2.69,-3.24,-3.64,-4.54,-4.71,-5.11,-5.40,-5.42,-5.20,-5.46, + -5.46,-5.79,-5.63,-5.64,-5.80,-5.66,-5.87,-6.01,-6.19,-6.64,-6.44, + -6.47,-6.09,-5.76,-4.66,-3.74,-2.72,-1.54,-0.02, 1.24, 2.64, 3.86, + 5.37, 6.14, 7.75, 9.13,10.46,11.53,13.36,14.65,16.01,17.20,18.24, + 19.06,20.25,20.95,21.16,22.25,22.41,23.03,23.49,23.62,23.86,24.49, + 24.34,24.08,24.02,24.00,23.87,23.95,23.86,23.93,23.73,23.92,23.96, + 24.02,24.33,24.83,25.30,25.70,26.24,26.77,27.28,27.78,28.25,28.71, + 29.15,29.57,29.97,30.36,30.72,31.07,31.35,31.68,32.18,32.68,33.15, + 33.59,34.00,34.47,35.03,35.73,36.54,37.43,38.29,39.20,40.18,41.17, + 42.23}; + + +/* TAI2FD-- convert from TAI in FITS format to UT in FITS format */ + +char * +tai2fd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double dj0, dj, tsec, dt; + + dj0 = fd2jd (string); + dt = utdt (dj0); + dj = dj0 - (dt / 86400.0); + dt = utdt (dj); + tsec = fd2ts (string); + tsec = tsec - dt + 32.184; + return (ts2fd (tsec)); +} + + +/* FD2TAI-- convert from UT in FITS format to TAI in FITS format */ + +char * +fd2tai (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double dj, tsec, dt; + + dj = fd2jd (string); + dt = utdt (dj); + tsec = fd2ts (string); + tsec = tsec + dt - 32.184; + return (ts2fd (tsec)); +} + + +/* DT2TAI-- convert from UT as yyyy.mmdd hh.mmssss to TAI in same format */ + +void +dt2tai (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, dt, tsec; + + dj = dt2jd (*date, *time); + dt = utdt (dj); + tsec = dt2ts (*date, *time); + tsec = tsec + dt - 32.184; + ts2dt (tsec, date, time); + return; +} + + +/* TAI2DT-- convert from TAI as yyyy.mmdd hh.mmssss to UT in same format */ + +void +tai2dt (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, dt, tsec, tsec0; + + dj = dt2jd (*date, *time); + dt = utdt (dj); + tsec0 = dt2ts (*date, *time); + tsec = tsec0 + dt; + dj = ts2jd (tsec); + dt = utdt (dj); + tsec = tsec0 + dt + 32.184; + ts2dt (tsec, date, time); + return; +} + + +/* ET2FD-- convert from ET (or TDT or TT) in FITS format to UT in FITS format */ + +char * +et2fd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double dj0, dj, tsec, dt; + + dj0 = fd2jd (string); + dt = utdt (dj0); + dj = dj0 - (dt / 86400.0); + dt = utdt (dj); + tsec = fd2ts (string); + tsec = tsec - dt; + return (ts2fd (tsec)); +} + + +/* FD2ET-- convert from UT in FITS format to ET (or TDT or TT) in FITS format */ + +char * +fd2et (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double dj, tsec, dt; + + dj = fd2jd (string); + dt = utdt (dj); + tsec = fd2ts (string); + tsec = tsec + dt; + return (ts2fd (tsec)); +} + + +/* DT2ET-- convert from UT as yyyy.mmdd hh.mmssss to ET in same format */ + +void +dt2et (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, dt, tsec; + + dj = dt2jd (*date, *time); + dt = utdt (dj); + tsec = dt2ts (*date, *time); + tsec = tsec + dt; + ts2dt (tsec, date, time); + return; +} + + +/* EDT2DT-- convert from ET as yyyy.mmdd hh.mmssss to UT in same format */ + +void +edt2dt (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, dt, tsec, tsec0; + + dj = dt2jd (*date, *time); + dt = utdt (dj); + tsec0 = dt2ts (*date, *time); + tsec = tsec0 + dt; + dj = ts2jd (tsec); + dt = utdt (dj); + tsec = tsec0 + dt; + ts2dt (tsec, date, time); + return; +} + + +/* JD2JED-- convert from Julian Date to Julian Ephemeris Date */ + +double +jd2jed (dj) + +double dj; /* Julian Date */ +{ + double dt; + + dt = utdt (dj); + return (dj + (dt / 86400.0)); +} + + +/* JED2JD-- convert from Julian Ephemeris Date to Julian Date */ + +double +jed2jd (dj) + +double dj; /* Julian Ephemeris Date */ +{ + double dj0, dt; + + dj0 = dj; + dt = utdt (dj); + dj = dj0 - (dt / 86400.0); + dt = utdt (dj); + return (dj - (dt / 86400.0)); +} + + +/* TS2ETS-- convert from UT in seconds since 1950-01-01 to ET in same format */ + +double +ts2ets (tsec) + +double tsec; +{ + double dj, dt; + + dj = ts2jd (tsec); + dt = utdt (dj); + return (tsec + dt); +} + + +/* ETS2TS-- convert from ET in seconds since 1950-01-01 to UT in same format */ + +double +ets2ts (tsec) + +double tsec; +{ + double dj, dj0, dt; + + dj0 = ts2jd (tsec); + dt = utdt (dj0); + dj = dj0 - (dt / 86400.0); + dt = utdt (dj); + return (tsec - dt); +} + + +/* UTDT-- Compute difference between UT and dynamical time (ET-UT) */ + +double +utdt (dj) + +double dj; /* Julian Date (UT) */ +{ + double dt, date, time, ts, ts1, ts0, date0, yfrac, diff, cj; + int i, iyr, iyear; + + /* If after 1972-01-01, use tabulated TAI-UT */ + if (dj >= 2441317.5) { + dt = 0.0; + for (i = 22; i > 0; i--) { + if (dj >= taijd[i]) + dt = taidt[i]; + } + dt = dt + 32.184; + } + + /* For 1800-01-01 to 1972-01-01, use table of ET-UT from AE */ + else if (dj >= 2378496.5) { + jd2dt (dj, &date, &time); + ts = jd2ts (dj); + iyear = (int) date; + iyr = iyear - 1800; + date0 = (double) iyear + 0.0101; + ts0 = dt2ts (date0, 0.0); + date0 = (double) (iyear + 1) + 0.0101; + ts1 = dt2ts (date0, 0.0); + yfrac = (ts - ts0) / (ts1 - ts0); + diff = dttab[iyr+1] - dttab[iyr]; + dt = dttab[iyr] + (diff * yfrac); + } + + /* Compute back to 1600 using formula from McCarthy and Babcock (1986) */ + else if (dj >= 2305447.5) { + cj = (dj - 2378496.5) / 36525.0; + dt = 5.156 + 13.3066 * (cj - 0.19) * (cj - 0.19); + } + + /* Compute back to 948 using formula from Stephenson and Morrison (1984) */ + else if (dj >= 2067309.5) { + cj = (dj - 2378496.5) / 36525.0; + dt = 25.5 * cj * cj; + } + + /*Compute back to 390 BC using formula from Stephenson and Morrison (1984)*/ + else if (dj >= 0.0) { + cj = (dj = 2378496.5) / 36525.0; + dt = 1360.0 + (320.0 * cj) + (44.3 * cj * cj); + } + + else + dt = 0.0; + return (dt); +} + + +/* FD2OFD-- convert any FITS standard date to old FITS standard date */ + +char * +fd2ofd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); + + /* Convert to old FITS date format */ + string = (char *) calloc (32, sizeof (char)); + if (iyr < 1900) + sprintf (string, "*** date out of range ***"); + else if (iyr < 2000) + sprintf (string, "%02d/%02d/%02d", iday, imon, iyr-1900); + else if (iyr < 2900.0) + sprintf (string, "%02d/%02d/%3d", iday, imon, iyr-1900); + else + sprintf (string, "*** date out of range ***"); + return (string); +} + + +/* FD2OFT-- convert any FITS standard date to old FITS standard time */ + +char * +fd2oft (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); + + /* Convert to old FITS date format */ + string = (char *) calloc (32, sizeof (char)); + sprintf (string, "%02d:%02d:%06.3f", ihr, imn, sec); + return (string); +} + + +/* FD2DT-- convert FITS standard date to date, time as yyyy.mmdd hh.mmsss */ + +void +fd2dt (string, date, time) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 4); + + /* Convert date to yyyy.mmdd */ + if (iyr < 0) { + *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; + *date = -(*date); + } + else + *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; + + /* Convert time to hh.mmssssss */ + *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; + + return; +} + + +/* FD2EP-- convert from FITS standard date to fractional year */ + +double +fd2ep (string) + +char *string; /* FITS date string, which may be: + yyyy.ffff (fractional year) + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ + +{ + double dj; /* Julian date */ + dj = fd2jd (string); + if (dj < 1.0) + return (dj / 365.2422); + else + return (jd2ep (dj)); +} + + +/* FD2EPB-- convert from FITS standard date to Besselian epoch */ + +double +fd2epb (string) + +char *string; /* FITS date string, which may be: + yyyy.ffff (fractional year) + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ + +{ + double dj; /* Julian date */ + dj = fd2jd (string); + if (dj < 1.0) + return (dj / 365.242198781); + else + return (jd2epb (dj)); +} + + +/* FD2EPJ-- convert from FITS standard date to Julian epoch */ + +double +fd2epj (string) + +char *string; /* FITS date string, which may be: + yyyy.ffff (fractional year) + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ + +{ + double dj; /* Julian date */ + dj = fd2jd (string); + if (dj < 1.0) + return (dj / 365.25); + else + return (jd2epj (dj)); +} + + +/* DT2TSU-- convert from date and time to Unix seconds since 1970-01-01T0:00 */ + +time_t +dt2tsu (date,time) + +double date; /* Date as yyyy.mmdd */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + return ((time_t)(dt2ts (date, time) - 631152000.0)); +} + + +/* DT2TSI-- convert from date and time to IRAF seconds since 1980-01-01T0:00 */ + +int +dt2tsi (date,time) + +double date; /* Date as yyyy.mmdd */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + return ((int)(dt2ts (date, time) - 946684800.0)); +} + + + +/* DT2TS-- convert from date, time as yyyy.mmdd hh.mmsss to sec since 1950.0 */ + +double +dt2ts (date,time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double tsec; /* Seconds past 1950.0 (returned) */ + + double dh,dm,dd; + int iy,im,id; + +/* Calculate the number of full years, months, and days already + * elapsed since 0h, March 1, -1 (up to most recent midnight). */ + + /* convert time of day to elapsed seconds */ + + /* If time is < 0, it is assumed to be a fractional day */ + if (time < 0.0) + tsec = time * -86400.0; + else { + dh = (int) (time + 0.0000000001); + dm = (int) (((time - dh) * 100.0) + 0.0000000001); + tsec = (time * 10000.0) - (dh * 10000.0) - (dm * 100.0); + tsec = (int) (tsec * 100000.0 + 0.0001) / 100000.0; + tsec = tsec + (dm * 60.0) + (dh * 3600.0); + } + + + /* Calculate the number of full months elapsed since + * the current or most recent March */ + if (date >= 0.0301) { + iy = (int) (date + 0.0000000001); + im = (int) (((date - (double) (iy)) * 10000.0) + 0.00000001); + id = im % 100; + im = (im / 100) + 9; + if (im < 12) iy = iy - 1; + im = im % 12; + id = id - 1; + + /* starting with March as month 0 and ending with the following + * February as month 11, the calculation of the number of days + * per month reduces to a simple formula. the following statement + * determines the number of whole days elapsed since 3/1/-1 and then + * subtracts the 712163 days between then and 1/1/1950. it converts + * the result to seconds and adds the accumulated seconds above. */ + id = id + ((im+1+im/6+im/11)/2 * 31) + ((im-im/6-im/11)/2 * 30) + + (iy / 4) - (iy / 100) + (iy / 400); + dd = (double) id + (365.0 * (double) iy) - 712163.0; + tsec = tsec + (dd * 86400.0); + } + + return (tsec); +} + + +/* TS2DT-- convert seconds since 1950.0 to date, time as yyyy.mmdd hh.mmssss */ + +void +ts2dt (tsec,date,time) + +double tsec; /* Seconds past 1950.0 */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + ts2i (tsec,&iyr,&imon,&iday,&ihr,&imn,&sec, 4); + + /* Convert date to yyyy.mmdd */ + if (iyr < 0) { + *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; + *date = -(*date); + } + else + *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; + + /* Convert time to hh.mmssssss */ + *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; + + return; +} + + +/* TSI2DT-- Convert seconds since 1980-01-01 to date yyyy.ddmm, time hh.mmsss */ + +void +tsi2dt (isec,date,time) + +int isec; /* Seconds past 1980-01-01 */ +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ +{ + ts2dt (tsi2ts (isec), date, time); +} + + +/* TSI2FD-- Convert seconds since 1980-01-01 to FITS standard date string */ + +char * +tsi2fd (isec) + +int isec; /* Seconds past 1980-01-01 */ +{ + return (ts2fd (tsi2ts (isec))); +} + + +/* TSI2TS-- Convert seconds since 1980-01-01 to seconds since 1950-01-01 */ + +double +tsi2ts (isec) +int isec; /* Seconds past 1980-01-01 */ +{ + return ((double) isec + 946684800.0); +} + + +/* TSU2FD-- Convert seconds since 1970-01-01 to FITS standard date string */ + +char * +tsu2fd (isec) +time_t isec; /* Seconds past 1970-01-01 */ +{ + return (ts2fd (tsu2ts (isec))); +} + + +/* TSU2DT-- Convert seconds since 1970-01-01 to date yyyy.ddmm, time hh.mmsss */ + +void +tsu2dt (isec,date,time) +time_t isec; /* Seconds past 1970-01-01 */ +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ +{ + ts2dt (tsu2ts (isec), date, time); +} + + +/* TSU2TS-- Convert seconds since 1970-01-01 to seconds since 1950-01-01 */ + +double +tsu2ts (isec) +time_t isec; /* Seconds past 1970-01-01 */ +{ + return ((double) isec + 631152000.0); +} + +/* TSU2TSI-- UT seconds since 1970-01-01 to local seconds since 1980-01-01 */ + +int +tsu2tsi (isec) +time_t isec; /* Seconds past 1970-01-01 */ +{ + double date, time; + struct tm *ts; + + /* Get local time from UT seconds */ + ts = localtime (&isec); + if (ts->tm_year < 1000) + date = (double) (ts->tm_year + 1900); + else + date = (double) ts->tm_year; + date = date + (0.01 * (double) (ts->tm_mon + 1)); + date = date + (0.0001 * (double) ts->tm_mday); + time = (double) ts->tm_hour; + time = time + (0.01 * (double) ts->tm_min); + time = time + (0.0001 * (double) ts->tm_sec); + return ((int)(dt2ts (date, time) - 631152000.0)); +} + + +/* TS2FD-- convert seconds since 1950.0 to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +ts2fd (tsec) + +double tsec; /* Seconds past 1950.0 */ +{ + double date, time; + + ts2dt (tsec, &date, &time); + return (dt2fd (date, time)); +} + + +/* TSD2FD-- convert seconds since start of day to FITS time, hh:mm:ss.ss */ + +char * +tsd2fd (tsec) + +double tsec; /* Seconds since start of day */ +{ + double date, time; + char *thms, *fdate; + int lfd, nbc; + + ts2dt (tsec, &date, &time); + fdate = dt2fd (date, time); + thms = (char *) calloc (16, 1); + lfd = strlen (fdate); + nbc = lfd - 11; + strncpy (thms, fdate+11, nbc); + return (thms); +} + + +/* TSD2DT-- convert seconds since start of day to hh.mmssss */ + +double +tsd2dt (tsec) + +double tsec; /* Seconds since start of day */ +{ + double date, time; + + ts2dt (tsec, &date, &time); + return (time); +} + + + +/* DT2I-- convert vigesimal date and time to year month day hours min sec */ + +void +dt2i (date, time, iyr, imon, iday, ihr, imn, sec, ndsec) + +double date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ + +{ + double t,d; + + t = time; + if (date < 0.0) + d = -date; + else + d = date; + + /* Extract components of time */ + *ihr = dint (t + 0.000000001); + t = 100.0 * (t - (double) *ihr); + *imn = dint (t + 0.0000001); + *sec = 100.0 * (t - (double) *imn); + + /* Extract components of date */ + *iyr = dint (d + 0.00001); + d = 100.0 * (d - (double) *iyr); + if (date < 0.0) + *iyr = - *iyr; + *imon = dint (d + 0.001); + d = 100.0 * (d - (double) *imon); + *iday = dint (d + 0.1); + + /* Make sure date and time are legal */ + fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); + + return; +} + + +/* FD2I-- convert from FITS standard date to year, mon, day, hours, min, sec */ + +void +fd2i (string, iyr, imon, iday, ihr, imn, sec, ndsec) + +char *string; /* FITS date string, which may be: + yyyy.ffff (fractional year) + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ + +{ + double tsec, fday, hr, mn; + int i; + char *sstr, *dstr, *tstr, *cstr, *nval, *fstr; + + /* Initialize all returned data to zero */ + *iyr = 0; + *imon = 0; + *iday = 0; + *ihr = 0; + *imn = 0; + *sec = 0.0; + + /* Return if no input string */ + if (string == NULL) + return; + + /* Check for various non-numeric characters */ + sstr = strchr (string,'/'); + dstr = strchr (string,'-'); + if (dstr == string) + dstr = strchr (string+1, '-'); + fstr = strchr (string, '.'); + tstr = strchr (string,'T'); + if (tstr == NULL) + tstr = strchr (string, 'Z'); + if (tstr == NULL) + tstr = strchr (string, 'S'); + if (fstr != NULL && tstr != NULL && fstr > tstr) + fstr = NULL; + cstr = strchr (string,':'); + + /* Original FITS date format: dd/mm/yy */ + if (sstr > string) { + *sstr = '\0'; + *iday = (int) atof (string); + if (*iday > 31) { + *iyr = *iday; + if (*iyr >= 0 && *iyr <= 49) + *iyr = *iyr + 2000; + else if (*iyr < 1000) + *iyr = *iyr + 1900; + *sstr = '/'; + nval = sstr + 1; + sstr = strchr (nval,'/'); + if (sstr > string) { + *sstr = '\0'; + *imon = (int) atof (nval); + *sstr = '/'; + nval = sstr + 1; + *iday = (int) atof (nval); + } + } + else { + *sstr = '/'; + nval = sstr + 1; + sstr = strchr (nval,'/'); + if (sstr == NULL) + sstr = strchr (nval,'-'); + if (sstr > string) { + *sstr = '\0'; + *imon = (int) atof (nval); + *sstr = '/'; + nval = sstr + 1; + *iyr = (int) atof (nval); + if (*iyr >= 0 && *iyr <= 49) + *iyr = *iyr + 2000; + else if (*iyr < 1000) + *iyr = *iyr + 1900; + } + } + tstr = strchr (string,'_'); + if (tstr == NULL) + return; + } + + /* New FITS date format: yyyy-mm-ddThh:mm:ss[.sss] */ + else if (dstr > string) { + *dstr = '\0'; + *iyr = (int) atof (string); + *dstr = '-'; + nval = dstr + 1; + dstr = strchr (nval,'-'); + *imon = 1; + *iday = 1; + + /* Decode year, month, and day */ + if (dstr > string) { + *dstr = '\0'; + *imon = (int) atof (nval); + *dstr = '-'; + nval = dstr + 1; + if (tstr > string) + *tstr = '\0'; + *iday = (int) atof (nval); + + /* If fraction of a day is present, turn it into a time */ + if (fstr != NULL) { + fday = atof (fstr); + hr = fday * 24.0; + *ihr = (int) hr; + mn = 60.0 * (hr - (double) *ihr); + *imn = (int) mn; + *sec = 60.0 * (mn - (double) *imn); + } + + if (tstr > string) + *tstr = 'T'; + } + + /* If date is > 31, it is really year in old format */ + if (*iday > 31) { + i = *iyr; + if (*iday < 100) + *iyr = *iday + 1900; + else + *iyr = *iday; + *iday = i; + } + } + + /* In rare cases, a FITS time is entered as an epoch */ + else if (tstr == NULL && cstr == NULL && isnum (string)) { + tsec = ep2ts (atof (string)); + ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec); + return; + } + + /* Extract time, if it is present */ + if (tstr > string || cstr > string) { + if (tstr > string) + nval = tstr + 1; + else + nval = string; + cstr = strchr (nval,':'); + if (cstr > string) { + *cstr = '\0'; + *ihr = (int) atof (nval); + *cstr = ':'; + nval = cstr + 1; + cstr = strchr (nval,':'); + if (cstr > string) { + *cstr = '\0'; + *imn = (int) atof (nval); + *cstr = ':'; + nval = cstr + 1; + *sec = atof (nval); + } + else + *imn = (int) atof (nval); + } + else + *ihr = (int) atof (nval); + } + else + ndsec = -1; + + /* Make sure date and time are legal */ + fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); + + return; +} + + +/* TS2I-- convert sec since 1950.0 to year month day hours minutes seconds */ + +void +ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec) + +double tsec; /* seconds since 1/1/1950 0:00 */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ + +{ + double t,days, ts, dts; + int nc,nc4,nly,ny,m,im; + + /* Round seconds to 0 - 4 decimal places */ + ts = tsec + 61530883200.0; + if (ts < 0.0) + dts = -0.5; + else + dts = 0.5; + if (ndsec < 1) + t = dint (ts + dts) * 10000.0; + else if (ndsec < 2) + t = dint (ts * 10.0 + dts) * 1000.0; + else if (ndsec < 3) + t = dint (ts * 100.0 + dts) * 100.0; + else if (ndsec < 4) + t = dint (ts * 1000.0 + dts) * 10.0; + else + t = dint (ts * 10000.0 + dts); + ts = t / 10000.0; + + /* Time of day (hours, minutes, seconds */ + *ihr = (int) (dmod (ts/3600.0, 24.0)); + *imn = (int) (dmod (ts/60.0, 60.0)); + *sec = dmod (ts, 60.0); + + /* Number of days since 0 hr 0/0/0000 */ + days = dint ((t / 864000000.0) + 0.000001); + + /* Number of leap centuries (400 years) */ + nc4 = (int) ((days / 146097.0) + 0.00001); + + /* Number of centuries since last /400 */ + days = days - (146097.0 * (double) (nc4)); + nc = (int) ((days / 36524.0) + 0.000001); + if (nc > 3) nc = 3; + + /* Number of leap years since last century */ + days = days - (36524.0 * nc); + nly = (int) ((days / 1461.0) + 0.0000000001); + + /* Number of years since last leap year */ + days = days - (1461.0 * (double) nly); + ny = (int) ((days / 365.0) + 0.00000001); + if (ny > 3) ny = 3; + + /* Day of month */ + days = days - (365.0 * (double) ny); + if (days < 0) { + m = 0; + *iday = 29; + } + else { + *iday = (int) (days + 0.00000001) + 1; + for (m = 1; m <= 12; m++) { + im = (m + ((m - 1) / 5)) % 2; + /* fprintf (stderr,"%d %d %d %d\n", m, im, *iday, nc); */ + if (*iday-1 < im+30) break; + *iday = *iday - im - 30; + } + } + + /* Month */ + *imon = ((m+1) % 12) + 1; + + /* Year */ + *iyr = nc4*400 + nc*100 + nly*4 + ny + m/11; + + /* Make sure date and time are legal */ + fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); + + return; +} + + +/* UT2DOY-- Current Universal Time as year, day of year */ + +void +ut2doy (year, doy) + +int *year; /* Year (returned) */ +double *doy; /* Day of year (returned) */ +{ + double date, time; + ut2dt (&date, &time); + dt2doy (date, time, year, doy); + return; +} + + +/* UT2DT-- Current Universal Time as date (yyyy.mmdd) and time (hh.mmsss) */ + +void +ut2dt(date, time) + +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ +{ + time_t tsec; + struct timeval tp; + struct timezone tzp; + struct tm *ts; + + gettimeofday (&tp,&tzp); + + tsec = tp.tv_sec; + ts = gmtime (&tsec); + + if (ts->tm_year < 1000) + *date = (double) (ts->tm_year + 1900); + else + *date = (double) ts->tm_year; + *date = *date + (0.01 * (double) (ts->tm_mon + 1)); + *date = *date + (0.0001 * (double) ts->tm_mday); + *time = (double) ts->tm_hour; + *time = *time + (0.01 * (double) ts->tm_min); + *time = *time + (0.0001 * (double) ts->tm_sec); + + return; +} + + +/* UT2EP-- Return current Universal Time as fractional year */ + +double +ut2ep() +{ + return (jd2ep (ut2jd())); +} + + +/* UT2EPB-- Return current Universal Time as Besselian epoch */ + +double +ut2epb() +{ + return (jd2epb (ut2jd())); +} + + +/* UT2EPJ-- Return current Universal Time as Julian epoch */ + +double +ut2epj() +{ + return (jd2epj (ut2jd())); +} + + +/* UT2FD-- Return current Universal Time as FITS ISO date string */ + +char * +ut2fd() +{ + int year, month, day, hour, minute, second; + time_t tsec; + struct timeval tp; + struct timezone tzp; + struct tm *ts; + char *isotime; + + gettimeofday (&tp,&tzp); + tsec = tp.tv_sec; + ts = gmtime (&tsec); + + year = ts->tm_year; + if (year < 1000) + year = year + 1900; + month = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + minute = ts->tm_min; + second = ts->tm_sec; + + isotime = (char *) calloc (32, sizeof (char)); + sprintf (isotime, "%04d-%02d-%02dT%02d:%02d:%02d", + year, month, day, hour, minute, second); + return (isotime); +} + + +/* UT2JD-- Return current Universal Time as Julian Date */ + +double +ut2jd() +{ + return (fd2jd (ut2fd())); +} + + +/* UT2MJD-- convert current UT to Modified Julian Date */ + +double +ut2mjd () + +{ + return (ut2jd() - 2400000.5); +} + +/* UT2TS-- current Universal Time as IRAF seconds since 1950-01-01T00:00 */ + +double +ut2ts() +{ + double tsec; + char *datestring; + datestring = ut2fd(); + tsec = fd2ts (datestring); + free (datestring); + return (tsec); +} + + +/* UT2TSI-- current Universal Time as IRAF seconds since 1980-01-01T00:00 */ + +int +ut2tsi() +{ + return ((int)(ut2ts() - 946684800.0)); +} + + +/* UT2TSU-- current Universal Time as IRAF seconds since 1970-01-01T00:00 */ + +time_t +ut2tsu() +{ + return ((time_t)(ut2ts () - 631152000.0)); +} + + +/* FD2GST-- convert from FITS date to Greenwich Sidereal Time */ + +char * +fd2gst (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double dj, gsec, date, time; + + dj = fd2jd (string); + gsec = jd2gst (dj); + ts2dt (gsec, &date, &time); + date = 0.0; + return (dt2fd (date, time)); +} + + +/* DT2GST-- convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time*/ + +void +dt2gst (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, gsec; + + dj = dt2ts (*date, *time); + gsec = jd2gst (dj); + ts2dt (gsec, date, time); + *date = 0.0; + return; +} + + +/* JD2LST - Local Sidereal Time in seconds from Julian Date */ + +double +jd2lst (dj) + +double dj; /* Julian Date */ +{ + double gst, lst; + + /* Compute Greenwich Sidereal Time at this epoch */ + gst = jd2gst (dj); + + /* Subtract longitude (degrees to seconds of time) */ + lst = gst - (240.0 * longitude); + if (lst < 0.0) + lst = lst + 86400.0; + else if (lst > 86400.0) + lst = lst - 86400.0; + return (lst); +} + + +/* FD2LST - Local Sidereal Time as hh:mm:ss.ss + from Universal Time as FITS ISO date */ + +char * +fd2lst (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) */ +{ + double dj, date, time, lst; + + dj = fd2jd (string); + lst = jd2lst (dj); + ts2dt (lst, &date, &time); + date = 0.0; + return (dt2fd (date, time)); +} + + +/* DT2LST - Local Sidereal Time as hh.mmssss + from Universal Time as yyyy.mmdd hh.mmssss */ + +void +dt2lst (date, time) + +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, lst, date0; + + dj = dt2jd (*date, *time); + lst = jd2lst (dj); + date0 = 0.0; + ts2dt (lst, &date0, time); + return; +} + + +/* TS2LST - Local Sidereal Time in seconds of day + * from Universal Time in seconds since 1951-01-01T0:00:00 + */ + +double +ts2lst (tsec) + +double tsec; /* time since 1950.0 in UT seconds */ +{ + double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ + double lst; /* Local Sidereal Time in seconds since 0:00 */ + double gsec, date; + + /* Greenwich Sidereal Time */ + gsec = ts2gst (tsec); + date = 0.0; + ts2dt (gsec, &date, &gst); + + lst = gst - (longitude / 15.0); + if (lst < 0.0) + lst = lst + 86400.0; + else if (lst > 86400.0) + lst = lst - 86400.0; + return (lst); +} + + +/* LST2FD - calculate current UT given Local Sidereal Time + * plus date in FITS ISO format (yyyy-mm-dd) + * Return UT date and time in FITS ISO format + */ + +char * +lst2fd (string) + +char *string; /* UT Date, LST as yyyy-mm-ddShh:mm:ss.ss */ +{ + double sdj, dj; + + sdj = fd2jd (string); + + dj = lst2jd (sdj); + + return (jd2fd (dj)); +} + + +/* LST2JD - calculate current Julian Date given Local Sidereal Time + * plus current Julian Date (0.5 at 0:00 UT) + * Return UT date and time as Julian Date + */ + +double +lst2jd (sdj) + +double sdj; /* Julian Date of desired day at 0:00 UT + sidereal time */ +{ + double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ + double lsd; /* Local Sidereal Time in seconds since 0:00 */ + double gst0, tsd, dj1, dj0, eqnx; + int idj; + + /* Julian date at 0:00 UT */ + idj = (int) sdj; + dj0 = (double) idj + 0.5; + if (dj0 > sdj) dj0 = dj0 - 1.0; + + /* Greenwich Sidereal Time at 0:00 UT in seconds */ + gst0 = jd2gst (dj0); + + /* Sidereal seconds since 0:00 */ + lsd = (sdj - dj0) * 86400.0; + + /* Remove longitude for current Greenwich Sidereal Time in seconds */ + /* (convert longitude from degrees to seconds of time) */ + gst = lsd + (longitude * 240.0); + + /* Time since 0:00 UT */ + tsd = (gst - gst0) / 1.0027379093; + + /* Julian Date (UT) */ + dj1 = dj0 + (tsd / 86400.0); + + /* Equation of the equinoxes converted to UT seconds */ + eqnx = eqeqnx (dj1) / 1.002739093; + + /* Remove equation of equinoxes */ + dj1 = dj1 - (eqnx / 86400.0); + if (dj1 < dj0) + dj1 = dj1 + 1.0; + + return (dj1); +} + + +/* MST2FD - calculate current UT given Greenwich Mean Sidereal Time + * plus date in FITS ISO format (yyyy-mm-ddShh:mm:ss.ss) + * Return UT date and time in FITS ISO format + */ + +char * +mst2fd (string) + +char *string; /* UT Date, MST as yyyy-mm-ddShh:mm:ss.ss */ +{ + double sdj, dj; + + sdj = fd2jd (string); + + dj = mst2jd (sdj); + + return (jd2fd (dj)); +} + + +/* MST2JD - calculate current UT given Greenwich Mean Sidereal Time + * plus date in Julian Date (0:00 UT + Mean Sidereal Time) + * Return UT date and time as Julian Date + */ + +double +mst2jd (sdj) + +double sdj; /* UT Date, MST as Julian Date */ +{ + double tsd, djd, st0, dj0, dj; + + dj0 = (double) ((int) sdj) + 0.5; + + /* Greenwich Mean Sidereal Time at 0:00 UT in seconds */ + st0 = jd2mst (dj0); + + /* Mean Sidereal Time in seconds */ + tsd = (sdj - dj0) * 86400.0; + if (tsd < 0.0) + tsd = tsd + 86400.0; + + /* Convert to fraction of a day since 0:00 UT */ + djd = ((tsd - st0) / 1.0027379093) / 86400.0; + + /* Julian Date */ + dj = dj0 + djd; + if (dj < dj0) + dj = dj + (1.0 / 1.0027379093); + + return (dj); +} + + + +/* GST2FD - calculate current UT given Greenwich Sidereal Time + * plus date in FITS ISO format (yyyy-mm-ddShh:mm:ss.ss) + * Return UT date and time in FITS ISO format + */ + +char * +gst2fd (string) + +char *string; /* UT Date, GST as yyyy-mm-ddShh:mm:ss.ss */ +{ + double sdj, dj; + + sdj = fd2jd (string); + + dj = gst2jd (sdj); + + return (jd2fd (dj)); +} + + +/* GST2JD - calculate current UT given Greenwich Sidereal Time + * plus date as Julian Date (JD at 0:00 UT + sidereal time) + * Return UT date and time as Julian Date + */ + +double +gst2jd (sdj) + +double sdj; /* UT Date, GST as Julian Date */ +{ + double dj, tsd, djd, st0, dj0, eqnx; + + dj0 = (double) ((int) sdj) + 0.5; + + /* Greenwich Mean Sidereal Time at 0:00 UT in seconds */ + st0 = jd2mst (dj0); + + /* Mean Sidereal Time in seconds */ + tsd = (sdj - dj0) * 86400.0; + if (tsd < 0.0) + tsd = tsd + 86400.0; + + /* Convert to fraction of a day since 0:00 UT */ + djd = ((tsd - st0) / 1.0027379093) / 86400.0; + + /* Julian Date */ + dj = dj0 + djd; + + /* Equation of the equinoxes (converted to UT seconds) */ + eqnx = eqeqnx (dj) / 1.002737909; + + dj = dj - eqnx / 86400.0; + if (dj < dj0) + dj = dj + 1.0; + + return (dj); +} + + +/* LST2DT - calculate current UT given Local Sidereal Time as hh.mmsss + * plus date as yyyy.mmdd + * Return UT time as hh.mmssss + */ + +double +lst2dt (date0, time0) + +double date0; /* UT date as yyyy.mmdd */ +double time0; /* LST as hh.mmssss */ +{ + double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ + double lst; /* Local Sidereal Time in seconds since 0:00 */ + double date1; /* UT date as yyyy.mmdd */ + double time1; /* UT as hh.mmssss */ + double tsec0, gst0, tsd, tsec; + + /* Greenwich Sidereal Time at 0:00 UT */ + tsec0 = dt2ts (date0, 0.0); + gst0 = ts2gst (tsec0); + + /* Current Greenwich Sidereal Time in seconds */ + /* (convert longitude from degrees to seconds of time) */ + lst = dt2ts (0.0, time0); + gst = lst + (longitude * 240.0); + + /* Time since 0:00 UT */ + tsd = (gst - gst0) / 1.0027379093; + + /* UT date and time */ + tsec = tsec0 + tsd; + ts2dt (tsec, &date1, &time1); + + return (time1); +} + + +/* TS2GST - calculate Greenwich Sidereal Time given Universal Time + * in seconds since 1951-01-01T0:00:00 + * Return sidereal time of day in seconds + */ + +double +ts2gst (tsec) + +double tsec; /* time since 1950.0 in UT seconds */ +{ + double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ + double tsd, eqnx, dj; + int its; + + /* Elapsed time as of 0:00 UT */ + if (tsec >= 0.0) { + its = (int) (tsec + 0.5); + tsd = (double) (its % 86400); + } + else { + its = (int) (-tsec + 0.5); + tsd = (double) (86400 - (its % 86400)); + } + + /* Mean sidereal time */ + gst = ts2mst (tsec); + + /* Equation of the equinoxes */ + dj = ts2jd (tsec); + eqnx = eqeqnx (dj); + + /* Apparent sidereal time at 0:00 ut */ + gst = gst + eqnx; + + /* Current sidereal time */ + gst = gst + (tsd * 1.0027379093); + gst = dmod (gst,86400.0); + + return (gst); +} + + +/* FD2MST-- convert from FITS date Mean Sidereal Time */ + +char * +fd2mst (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double gsec, date, time, dj; + + dj = fd2jd (string); + gsec = jd2mst (dj); + ts2dt (gsec, &date, &time); + date = 0.0; + return (dt2fd (date, time)); +} + + +/* DT2MST-- convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time + in the same format */ + +void +dt2mst (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double date0, gsec, dj; + date0 = *date; + dj = dt2jd (*date, *time); + gsec = jd2mst (dj); + ts2dt (gsec, date, time); + *date = date0; + return; +} + + +/* TS2MST - calculate Greenwich Mean Sidereal Time given Universal Time + * in seconds since 1951-01-01T0:00:00 + */ + +double +ts2mst (tsec) + +double tsec; /* time since 1950.0 in UT seconds */ +{ + double dj; + + dj = ts2jd (tsec); + return (jd2mst (dj)); +} + + +/* JD2MST - Julian Date to Greenwich Mean Sidereal Time using IAU 2000 + * Return sideral time in seconds of time + * (from USNO NOVAS package + * http://aa.usno.navy.mil/software/novas/novas_info.html + */ + +double +jd2mst2 (dj) + +double dj; /* Julian Date */ +{ + double dt, t, t2, t3, mst, st; + + dt = dj - 2451545.0; + t = dt / 36525.0; + t2 = t * t; + t3 = t2 * t; + + /* Compute Greenwich Mean Sidereal Time in seconds */ + st = (8640184.812866 * t) + (3155760000.0 * t) - (0.0000062 * t3) + + (0.093104 * t2) + 67310.54841; + + mst = dmod (st, 86400.0); + if (mst < 0.0) + mst = mst + 86400.0; + return (mst); +} + + +/* MJD2MST - Modified Julian Date to Greenwich Mean Sidereal Time using IAU 2000 + * Return sideral time in seconds of time + * (from USNO NOVAS package + * http://aa.usno.navy.mil/software/novas/novas_info.html + */ + +double +mjd2mst (dj) + +double dj; /* Modified Julian Date */ +{ + double dt, t, t2, t3, mst, st; + + dt = dj - 51544.5; + t = dt / 36525.0; + t2 = t * t; + t3 = t2 * t; + + /* Compute Greenwich Mean Sidereal Time in seconds */ + st = (8640184.812866 * t) + (3155760000.0 * t) - (0.0000062 * t3) + + (0.093104 * t2) + 67310.54841; + + mst = dmod (st, 86400.0); + if (mst < 0.0) + mst = mst + 86400.0; + return (mst); +} + + +/* JD2GST - Julian Date to Greenwich Sideral Time + * Return sideral time in seconds of time + * (Jean Meeus, Astronomical Algorithms, Willmann-Bell, 1991, pp 83-84) + */ + +double +jd2gst (dj) + +double dj; /* Julian Date */ +{ + double dj0, gmt, gst, tsd, eqnx, ssd, l0; + double ts2ss = 1.00273790935; + int ijd; + + /* Julian date at 0:00 UT */ + ijd = (int) dj; + dj0 = (double) ijd + 0.5; + if (dj0 > dj) dj0 = dj0 - 1.0; + + /* Greenwich mean sidereal time at 0:00 UT in seconds */ + l0 = longitude; + longitude = 0.0; + gmt = jd2mst (dj0); + longitude = l0; + + /* Equation of the equinoxes */ + eqnx = eqeqnx (dj); + + /* Apparent sidereal time at 0:00 ut */ + gst = gmt + eqnx; + + /* UT seconds since 0:00 */ + tsd = (dj - dj0) * 86400.0; + ssd = tsd * ts2ss; + + /* Current sidereal time */ + gst = gst + ssd; + gst = dmod (gst, 86400.0); + + return (gst); +} + + +/* EQEQNX - Compute equation of the equinoxes for apparent sidereal time */ + +double +eqeqnx (dj) + +double dj; /* Julian Date */ + +{ + double dt, edj, dpsi, deps, obl, eqnx; + double rad2tsec = 13750.98708; + + /* Convert UT to Ephemeris Time (TDB or TT)*/ + dt = utdt (dj); + edj = dj + dt / 86400.0; + + /* Nutation and obliquity */ + compnut (edj, &dpsi, &deps, &obl); + + /* Correct obliquity for nutation */ + obl = obl + deps; + + /* Equation of the equinoxes in seconds */ + eqnx = (dpsi * cos (obl)) * rad2tsec; + + return (eqnx); +} + + + +/* JD2MST - Julian Date to Mean Sideral Time + * Return sideral time in seconds of time + * (Jean Meeus, Astronomical Algorithms, Willmann-Bell, 1991, pp 83-84) + */ + +double +jd2mst (dj) + +double dj; /* Julian Date */ +{ + double dt, t, mst; + + dt = dj - 2451545.0; + t = dt / 36525.0; + + /* Compute Greenwich mean sidereal time in degrees (Meeus, page 84) */ + mst = 280.46061837 + (360.98564736629 * dt) + (0.000387933 * t * t) - + (t * t * t / 38710000.0); + + /* Keep degrees between 0 and 360 */ + while (mst > 360.0) + mst = mst - 360.0; + while (mst < 0.0) + mst = mst + 360.0; + + /* Convert to time in seconds (3600 / 15) */ + mst = mst * 240.0; + + /* Subtract longitude (degrees to seconds of time) */ + mst = mst - (240.0 * longitude); + if (mst < 0.0) + mst = mst + 86400.0; + else if (mst > 86400.0) + mst = mst - 86400.0; + + return (mst); +} + + +/* COMPNUT - Compute nutation using the IAU 2000b model */ +/* Translated from Pat Wallace's Fortran subroutine iau_nut00b (June 26 2007) + into C by Jessica Mink on September 5, 2008 */ + +#define NLS 77 /* number of terms in the luni-solar nutation model */ + +void +compnut (dj, dpsi, deps, eps0) + +double dj; /* Julian Date */ +double *dpsi; /* Nutation in longitude in radians (returned) */ +double *deps; /* Nutation in obliquity in radians (returned) */ +double *eps0; /* Mean obliquity in radians (returned) */ + +/* This routine is translated from the International Astronomical Union's + * Fortran SOFA (Standards Of Fundamental Astronomy) software collection. + * + * notes: + * + * 1) the nutation components in longitude and obliquity are in radians + * and with respect to the equinox and ecliptic of date. the + * obliquity at j2000 is assumed to be the lieske et al. (1977) value + * of 84381.448 arcsec. (the errors that result from using this + * routine with the iau 2006 value of 84381.406 arcsec can be + * neglected.) + * + * the nutation model consists only of luni-solar terms, but includes + * also a fixed offset which compensates for certain long-period + * planetary terms (note 7). + * + * 2) this routine is an implementation of the iau 2000b abridged + * nutation model formally adopted by the iau general assembly in + * 2000. the routine computes the mhb_2000_short luni-solar nutation + * series (luzum 2001), but without the associated corrections for + * the precession rate adjustments and the offset between the gcrs + * and j2000 mean poles. + * + * 3) the full IAU 2000a (mhb2000) nutation model contains nearly 1400 + * terms. the IAU 2000b model (mccarthy & luzum 2003) contains only + * 77 terms, plus additional simplifications, yet still delivers + * results of 1 mas accuracy at present epochs. this combination of + * accuracy and size makes the IAU 2000b abridged nutation model + * suitable for most practical applications. + * + * the routine delivers a pole accurate to 1 mas from 1900 to 2100 + * (usually better than 1 mas, very occasionally just outside 1 mas). + * the full IAU 2000a model, which is implemented in the routine + * iau_nut00a (q.v.), delivers considerably greater accuracy at + * current epochs; however, to realize this improved accuracy, + * corrections for the essentially unpredictable free-core-nutation + * (fcn) must also be included. + * + * 4) the present routine provides classical nutation. the + * mhb_2000_short algorithm, from which it is adapted, deals also + * with (i) the offsets between the gcrs and mean poles and (ii) the + * adjustments in longitude and obliquity due to the changed + * precession rates. these additional functions, namely frame bias + * and precession adjustments, are supported by the sofa routines + * iau_bi00 and iau_pr00. + * + * 6) the mhb_2000_short algorithm also provides "total" nutations, + * comprising the arithmetic sum of the frame bias, precession + * adjustments, and nutation (luni-solar + planetary). these total + * nutations can be used in combination with an existing IAU 1976 + * precession implementation, such as iau_pmat76, to deliver gcrs-to- + * true predictions of mas accuracy at current epochs. however, for + * symmetry with the iau_nut00a routine (q.v. for the reasons), the + * sofa routines do not generate the "total nutations" directly. + * should they be required, they could of course easily be generated + * by calling iau_bi00, iau_pr00 and the present routine and adding + * the results. + * + * 7) the IAU 2000b model includes "planetary bias" terms that are fixed + * in size but compensate for long-period nutations. the amplitudes + * quoted in mccarthy & luzum (2003), namely dpsi = -1.5835 mas and + * depsilon = +1.6339 mas, are optimized for the "total nutations" + * method described in note 6. the luzum (2001) values used in this + * sofa implementation, namely -0.135 mas and +0.388 mas, are + * optimized for the "rigorous" method, where frame bias, precession + * and nutation are applied separately and in that order. during the + * interval 1995-2050, the sofa implementation delivers a maximum + * error of 1.001 mas (not including fcn). + * + * References from original Fortran subroutines: + * + * Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351 + * + * Lieske, J.H., Lederle, T., Fricke, W., Morando, B., "Expressions + * for the precession quantities based upon the IAU 1976 system of + * astronomical constants", Astron.Astrophys. 58, 1-2, 1-16. (1977) + * + * Luzum, B., private communication, 2001 (Fortran code + * mhb_2000_short) + * + * McCarthy, D.D. & Luzum, B.J., "An abridged model of the + * precession-nutation of the celestial pole", Cel.Mech.Dyn.Astron. + * 85, 37-49 (2003) + * + * Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M., + * Francou, G., Laskar, J., Astron.Astrophys. 282, 663-683 (1994) + * + */ + +{ + double as2r = 0.000004848136811095359935899141; /* arcseconds to radians */ + + double dmas2r = as2r / 1000.0; /* milliarcseconds to radians */ + + double as2pi = 1296000.0; /* arc seconds in a full circle */ + + double d2pi = 6.283185307179586476925287; /* 2pi */ + + double u2r = as2r / 10000000.0; /* units of 0.1 microarcsecond to radians */ + + double dj0 = 2451545.0; /* reference epoch (j2000), jd */ + + double djc = 36525.0; /* Days per julian century */ + + /* Miscellaneous */ + double t, el, elp, f, d, om, arg, dp, de, sarg, carg; + double dpsils, depsls, dpsipl, depspl; + int i, j; + + int nls = NLS; /* number of terms in the luni-solar nutation model */ + + /* Fixed offset in lieu of planetary terms (radians) */ + double dpplan = - 0.135 * dmas2r; + double deplan = + 0.388 * dmas2r; + +/* Tables of argument and term coefficients */ + + /* Coefficients for fundamental arguments */ + /* Luni-solar argument multipliers: */ + /* l l' f d om */ +static int nals[5*NLS]= + {0, 0, 0, 0, 1, + 0, 0, 2, -2, 2, + 0, 0, 2, 0, 2, + 0, 0, 0, 0, 2, + 0, 1, 0, 0, 0, + 0, 1, 2, -2, 2, + 1, 0, 0, 0, 0, + 0, 0, 2, 0, 1, + 1, 0, 2, 0, 2, + 0, -1, 2, -2, 2, + 0, 0, 2, -2, 1, + -1, 0, 2, 0, 2, + -1, 0, 0, 2, 0, + 1, 0, 0, 0, 1, + -1, 0, 0, 0, 1, + -1, 0, 2, 2, 2, + 1, 0, 2, 0, 1, + -2, 0, 2, 0, 1, + 0, 0, 0, 2, 0, + 0, 0, 2, 2, 2, + 0, -2, 2, -2, 2, + -2, 0, 0, 2, 0, + 2, 0, 2, 0, 2, + 1, 0, 2, -2, 2, + -1, 0, 2, 0, 1, + 2, 0, 0, 0, 0, + 0, 0, 2, 0, 0, + 0, 1, 0, 0, 1, + -1, 0, 0, 2, 1, + 0, 2, 2, -2, 2, + 0, 0, -2, 2, 0, + 1, 0, 0, -2, 1, + 0, -1, 0, 0, 1, + -1, 0, 2, 2, 1, + 0, 2, 0, 0, 0, + 1, 0, 2, 2, 2, + -2, 0, 2, 0, 0, + 0, 1, 2, 0, 2, + 0, 0, 2, 2, 1, + 0, -1, 2, 0, 2, + 0, 0, 0, 2, 1, + 1, 0, 2, -2, 1, + 2, 0, 2, -2, 2, + -2, 0, 0, 2, 1, + 2, 0, 2, 0, 1, + 0, -1, 2, -2, 1, + 0, 0, 0, -2, 1, + -1, -1, 0, 2, 0, + 2, 0, 0, -2, 1, + 1, 0, 0, 2, 0, + 0, 1, 2, -2, 1, + 1, -1, 0, 0, 0, + -2, 0, 2, 0, 2, + 3, 0, 2, 0, 2, + 0, -1, 0, 2, 0, + 1, -1, 2, 0, 2, + 0, 0, 0, 1, 0, + -1, -1, 2, 2, 2, + -1, 0, 2, 0, 0, + 0, -1, 2, 2, 2, + -2, 0, 0, 0, 1, + 1, 1, 2, 0, 2, + 2, 0, 0, 0, 1, + -1, 1, 0, 1, 0, + 1, 1, 0, 0, 0, + 1, 0, 2, 0, 0, + -1, 0, 2, -2, 1, + 1, 0, 0, 0, 2, + -1, 0, 0, 1, 0, + 0, 0, 2, 1, 2, + -1, 0, 2, 4, 2, + -1, 1, 0, 1, 1, + 0, -2, 2, -2, 1, + 1, 0, 2, 2, 1, + -2, 0, 2, 2, 2, + -1, 0, 0, 0, 2, + 1, 1, 2, -2, 2}; + + /* Luni-solar nutation coefficients, in 1e-7 arcsec */ + /* longitude (sin, t*sin, cos), obliquity (cos, t*cos, sin) */ +static double cls[6*NLS]= + {-172064161.0, -174666.0, 33386.0, 92052331.0, 9086.0, 15377.0, + -13170906.0, -1675.0, -13696.0, 5730336.0, -3015.0, -4587.0, + -2276413.0, -234.0, 2796.0, 978459.0, -485.0, 1374.0, + 2074554.0, 207.0, -698.0, -897492.0, 470.0, -291.0, + 1475877.0, -3633.0, 11817.0, 73871.0, -184.0, -1924.0, + -516821.0, 1226.0, -524.0, 224386.0, -677.0, -174.0, + 711159.0, 73.0, -872.0, -6750.0, 0.0, 358.0, + -387298.0, -367.0, 380.0, 200728.0, 18.0, 318.0, + -301461.0, -36.0, 816.0, 129025.0, -63.0, 367.0, + 215829.0, -494.0, 111.0, -95929.0, 299.0, 132.0, + 128227.0, 137.0, 181.0, -68982.0, -9.0, 39.0, + 123457.0, 11.0, 19.0, -53311.0, 32.0, -4.0, + 156994.0, 10.0, -168.0, -1235.0, 0.0, 82.0, + 63110.0, 63.0, 27.0, -33228.0, 0.0, -9.0, + -57976.0, -63.0, -189.0, 31429.0, 0.0, -75.0, + -59641.0, -11.0, 149.0, 25543.0, -11.0, 66.0, + -51613.0, -42.0, 129.0, 26366.0, 0.0, 78.0, + 45893.0, 50.0, 31.0, -24236.0, -10.0, 20.0, + 63384.0, 11.0, -150.0, -1220.0, 0.0, 29.0, + -38571.0, -1.0, 158.0, 16452.0, -11.0, 68.0, + 32481.0, 0.0, 0.0, -13870.0, 0.0, 0.0, + -47722.0, 0.0, -18.0, 477.0, 0.0, -25.0, + -31046.0, -1.0, 131.0, 13238.0, -11.0, 59.0, + 28593.0, 0.0, -1.0, -12338.0, 10.0, -3.0, + 20441.0, 21.0, 10.0, -10758.0, 0.0, -3.0, + 29243.0, 0.0, -74.0, -609.0, 0.0, 13.0, + 25887.0, 0.0, -66.0, -550.0, 0.0, 11.0, + -14053.0, -25.0, 79.0, 8551.0, -2.0, -45.0, + 15164.0, 10.0, 11.0, -8001.0, 0.0, -1.0, + -15794.0, 72.0, -16.0, 6850.0, -42.0, -5.0, + 21783.0, 0.0, 13.0, -167.0, 0.0, 13.0, + -12873.0, -10.0, -37.0, 6953.0, 0.0, -14.0, + -12654.0, 11.0, 63.0, 6415.0, 0.0, 26.0, + -10204.0, 0.0, 25.0, 5222.0, 0.0, 15.0, + 16707.0, -85.0, -10.0, 168.0, -1.0, 10.0, + -7691.0, 0.0, 44.0, 3268.0, 0.0, 19.0, + -11024.0, 0.0, -14.0, 104.0, 0.0, 2.0, + 7566.0, -21.0, -11.0, -3250.0, 0.0, -5.0, + -6637.0, -11.0, 25.0, 3353.0, 0.0, 14.0, + -7141.0, 21.0, 8.0, 3070.0, 0.0, 4.0, + -6302.0, -11.0, 2.0, 3272.0, 0.0, 4.0, + 5800.0, 10.0, 2.0, -3045.0, 0.0, -1.0, + 6443.0, 0.0, -7.0, -2768.0, 0.0, -4.0, + -5774.0, -11.0, -15.0, 3041.0, 0.0, -5.0, + -5350.0, 0.0, 21.0, 2695.0, 0.0, 12.0, + -4752.0, -11.0, -3.0, 2719.0, 0.0, -3.0, + -4940.0, -11.0, -21.0, 2720.0, 0.0, -9.0, + 7350.0, 0.0, -8.0, -51.0, 0.0, 4.0, + 4065.0, 0.0, 6.0, -2206.0, 0.0, 1.0, + 6579.0, 0.0, -24.0, -199.0, 0.0, 2.0, + 3579.0, 0.0, 5.0, -1900.0, 0.0, 1.0, + 4725.0, 0.0, -6.0, -41.0, 0.0, 3.0, + -3075.0, 0.0, -2.0, 1313.0, 0.0, -1.0, + -2904.0, 0.0, 15.0, 1233.0, 0.0, 7.0, + 4348.0, 0.0, -10.0, -81.0, 0.0, 2.0, + -2878.0, 0.0, 8.0, 1232.0, 0.0, 4.0, + -4230.0, 0.0, 5.0, -20.0, 0.0, -2.0, + -2819.0, 0.0, 7.0, 1207.0, 0.0, 3.0, + -4056.0, 0.0, 5.0, 40.0, 0.0, -2.0, + -2647.0, 0.0, 11.0, 1129.0, 0.0, 5.0, + -2294.0, 0.0, -10.0, 1266.0, 0.0, -4.0, + 2481.0, 0.0, -7.0, -1062.0, 0.0, -3.0, + 2179.0, 0.0, -2.0, -1129.0, 0.0, -2.0, + 3276.0, 0.0, 1.0, -9.0, 0.0, 0.0, + -3389.0, 0.0, 5.0, 35.0, 0.0, -2.0, + 3339.0, 0.0, -13.0, -107.0, 0.0, 1.0, + -1987.0, 0.0, -6.0, 1073.0, 0.0, -2.0, + -1981.0, 0.0, 0.0, 854.0, 0.0, 0.0, + 4026.0, 0.0, -353.0, -553.0, 0.0, -139.0, + 1660.0, 0.0, -5.0, -710.0, 0.0, -2.0, + -1521.0, 0.0, 9.0, 647.0, 0.0, 4.0, + 1314.0, 0.0, 0.0, -700.0, 0.0, 0.0, + -1283.0, 0.0, 0.0, 672.0, 0.0, 0.0, + -1331.0, 0.0, 8.0, 663.0, 0.0, 4.0, + 1383.0, 0.0, -2.0, -594.0, 0.0, -2.0, + 1405.0, 0.0, 4.0, -610.0, 0.0, 2.0, + 1290.0, 0.0, 0.0, -556.0, 0.0, 0.0}; + + /* Interval between fundamental epoch J2000.0 and given date (JC) */ + t = (dj - dj0) / djc; + +/* Luni-solar nutation */ + +/* Fundamental (delaunay) arguments from Simon et al. (1994) */ + + /* Mean anomaly of the moon */ + el = fmod (485868.249036 + (1717915923.2178 * t), as2pi) * as2r; + + /* Mean anomaly of the sun */ + elp = fmod (1287104.79305 + (129596581.0481 * t), as2pi) * as2r; + + /* Mean argument of the latitude of the moon */ + f = fmod (335779.526232 + (1739527262.8478 * t), as2pi) * as2r; + + /* Mean elongation of the moon from the sun */ + d = fmod (1072260.70369 + (1602961601.2090 * t), as2pi ) * as2r; + + /* Mean longitude of the ascending node of the moon */ + om = fmod (450160.398036 - (6962890.5431 * t), as2pi ) * as2r; + + /* Initialize the nutation values */ + dp = 0.0; + de = 0.0; + + /* Summation of luni-solar nutation series (in reverse order) */ + for (i = nls; i > 0; i=i-1) { + j = i - 1; + + /* Argument and functions */ + arg = fmod ( (double) (nals[5*j]) * el + + (double) (nals[1+5*j]) * elp + + (double) (nals[2+5*j]) * f + + (double) (nals[3+5*j]) * d + + (double) (nals[4+5*j]) * om, d2pi); + sarg = sin (arg); + carg = cos (arg); + + /* Terms */ + dp = dp + (cls[6*j] + cls[1+6*j] * t) * sarg + cls[2+6*j] * carg; + de = de + (cls[3+6*j] + cls[4+6*j] * t) * carg + cls[5+6*j] * sarg; + } + + /* Convert from 0.1 microarcsec units to radians */ + dpsils = dp * u2r; + depsls = de * u2r; + +/* In lieu of planetary nutation */ + + /* Fixed offset to correct for missing terms in truncated series */ + dpsipl = dpplan; + depspl = deplan; + +/* Results */ + + /* Add luni-solar and planetary components */ + *dpsi = dpsils + dpsipl; + *deps = depsls + depspl; + + /* Mean Obliquity in radians (IAU 2006, Hilton, et al.) */ + *eps0 = ( 84381.406 + + ( -46.836769 + + ( -0.0001831 + + ( 0.00200340 + + ( -0.000000576 + + ( -0.0000000434 ) * t ) * t ) * t ) * t ) * t ) * as2r; +} + + +/* ISDATE - Return 1 if string is an old or ISO FITS standard date */ + +int +isdate (string) + +char *string; /* Possible FITS date string, which may be: + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ + +{ + int iyr = 0; /* year (returned) */ + int imon = 0; /* month (returned) */ + int iday = 0; /* day (returned) */ + int i; + char *sstr, *dstr, *tstr, *nval; + + /* Translate string from ASCII to binary */ + if (string == NULL) + return (0); + + sstr = strchr (string,'/'); + dstr = strchr (string,'-'); + if (dstr == string) + dstr = strchr (string+1,'-'); + tstr = strchr (string,'T'); + + /* Original FITS date format: dd/mm/yy */ + if (sstr > string) { + *sstr = '\0'; + iday = (int) atof (string); + *sstr = '/'; + nval = sstr + 1; + sstr = strchr (nval,'/'); + if (sstr == NULL) + sstr = strchr (nval,'-'); + if (sstr > string) { + *sstr = '\0'; + imon = (int) atof (nval); + *sstr = '/'; + nval = sstr + 1; + iyr = (int) atof (nval); + if (iyr < 1000) + iyr = iyr + 1900; + } + if (imon > 0 && iday > 0) + return (1); + else + return (0); + } + + /* New FITS date format: yyyy-mm-ddThh:mm:ss[.sss] */ + else if (dstr > string) { + *dstr = '\0'; + iyr = (int) atof (string); + nval = dstr + 1; + *dstr = '-'; + dstr = strchr (nval,'-'); + imon = 0; + iday = 0; + + /* Decode year, month, and day */ + if (dstr > string) { + *dstr = '\0'; + imon = (int) atof (nval); + *dstr = '-'; + nval = dstr + 1; + if (tstr > string) + *tstr = '\0'; + iday = (int) atof (nval); + if (tstr > string) + *tstr = 'T'; + } + + /* If day is > 31, it is really year in old format */ + if (iday > 31) { + i = iyr; + if (iday < 100) + iyr = iday + 1900; + else + iyr = iday; + iday = i; + } + if (imon > 0 && iday > 0) + return (1); + else + return (0); + } + + /* If FITS date is entered as an epoch, return 0 anyway */ + else + return (0); +} + + +/* Round seconds and make sure date and time numbers are within limits */ + +static void +fixdate (iyr, imon, iday, ihr, imn, sec, ndsec) + +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ +{ + double days; + + /* Round seconds to 0 - 4 decimal places (no rounding if <0, >4) */ + if (ndsec == 0) + *sec = dint (*sec + 0.5); + else if (ndsec < 2) + *sec = dint (*sec * 10.0 + 0.5) / 10.0; + else if (ndsec < 3) + *sec = dint (*sec * 100.0 + 0.5) / 100.0; + else if (ndsec < 4) + *sec = dint (*sec * 1000.0 + 0.5) / 1000.0; + else if (ndsec < 5) + *sec = dint (*sec * 10000.0 + 0.5) / 10000.0; + + /* Adjust minutes and hours */ + if (*sec > 60.0) { + *sec = *sec - 60.0; + *imn = *imn + 1; + } + if (*imn > 60) { + *imn = *imn - 60; + *ihr = *ihr + 1; + } + + /* Return if no date */ + if (*iyr == 0 && *imon == 0 && *iday == 0) + return; + + /* Adjust date */ + if (*ihr > 23) { + *ihr = *ihr - 24; + *iday = *iday + 1; + } + days = caldays (*iyr, *imon); + if (*iday > days) { + *iday = *iday - days; + *imon = *imon + 1; + } + if (*iday < 1) { + *imon = *imon - 1; + if (*imon < 1) { + *imon = *imon + 12; + *iyr = *iyr - 1; + } + days = caldays (*iyr, *imon); + *iday = *iday + days; + } + if (*imon < 1) { + *imon = *imon + 12; + *iyr = *iyr - 1; + days = caldays (*iyr, *imon); + if (*iday > days) { + *iday = *iday - days; + *imon = *imon + 1; + } + } + if (*imon > 12) { + *imon = *imon - 12; + *iyr = *iyr + 1; + } + return; +} + + +/* Calculate days in month 1-12 given year (Gregorian calendar only) */ + +static int +caldays (year, month) + +int year; /* 4-digit year */ +int month; /* Month (1=January, 2=February, etc.) */ +{ + if (month < 1) { + month = month + 12; + year = year + 1; + } + if (month > 12) { + month = month - 12; + year = year + 1; + } + switch (month) { + case 1: + return (31); + case 2: + if (year%400 == 0) + return (29); + else if (year%100 == 0) + return (28); + else if (year%4 == 0) + return (29); + else + return (28); + case 3: + return (31); + case 4: + return (30); + case 5: + return (31); + case 6: + return (30); + case 7: + return (31); + case 8: + return (31); + case 9: + return (30); + case 10: + return (31); + case 11: + return (30); + case 12: + return (31); + default: + return (0); + } +} + + +static double +dint (dnum) + +double dnum; +{ + double dn; + + if (dnum < 0.0) + dn = -floor (-dnum); + else + dn = floor (dnum); + return (dn); +} + + +static double +dmod (dnum, dm) + +double dnum, dm; +{ + double dnumx, dnumi, dnumf; + if (dnum < 0.0) + dnumx = -dnum; + else + dnumx = dnum; + dnumi = dint (dnumx / dm); + if (dnum < 0.0) + dnumf = dnum + (dnumi * dm); + else if (dnum > 0.0) + dnumf = dnum - (dnumi * dm); + else + dnumf = 0.0; + return (dnumf); +} + +/* Jul 1 1999 New file, based on iolib/jcon.f and iolib/vcon.f and hgetdate() + * Oct 21 1999 Fix declarations after lint + * Oct 27 1999 Fix bug to return epoch if fractional year input + * Dec 9 1999 Fix bug in ts2jd() found by Pete Ratzlaff (SAO) + * Dec 17 1999 Add all unimplemented conversions + * Dec 20 1999 Add isdate(); leave date, time strings unchanged in fd2i() + * Dec 20 1999 Make all fd2*() subroutines deal with time alone + * + * Jan 3 2000 In old FITS format, year 100 is assumed to be 2000 + * Jan 11 2000 Fix epoch to date conversion so .0 is 0:00, not 12:00 + * Jan 21 2000 Add separate Besselian and Julian epoch computations + * Jan 28 2000 Add Modified Julian Date conversions + * Mar 2 2000 Implement decimal places for FITS date string + * Mar 14 2000 Fix bug in dealing with 2000-02-29 in ts2i() + * Mar 22 2000 Add lt2* and ut2* to get current time as local and UT + * Mar 24 2000 Fix calloc() calls + * Mar 24 2000 Add tsi2* and tsu2* to convert IRAF and Unix seconds + * May 1 2000 In old FITS format, all years < 1000 get 1900 added to them + * Aug 1 2000 Make ep2jd and jd2ep consistently starting at 1/1 0:00 + * + * Jan 11 2001 Print all messages to stderr + * May 21 2001 Add day of year conversions + * May 25 2001 Allow fraction of day in FITS date instead of time + * + * Apr 8 2002 Change all long declaration to time_t + * May 13 2002 Fix bugs found by lint + * Jul 5 2002 Fix bug in fixdate() so fractional seconds come out + * Jul 8 2002 Fix rounding bug in t2i() + * Jul 8 2002 Try Fliegel and Van Flandern's algorithm for JD to UT date + * Jul 8 2002 If first character of string is -, check for other -'s in isdate + * Sep 10 2002 Add ET/TDT/TT conversion from UT subroutines + * Sep 10 2002 Add sidereal time conversions + * + * Jan 30 2003 Fix typo in ts2gst() + * Mar 7 2003 Add conversions for heliocentric julian dates + * May 20 2003 Declare nd in setdatedec() + * Jul 18 2003 Add code to parse Las Campanas dates + * + * Mar 24 2004 If ndec > 0, add UT to FITS date even if it is 0:00:00 + * + * Oct 14 2005 Add tsd2fd() and tsd2dt() + * + * May 3 2006 Drop declaration of unused variables + * Jun 20 2006 Initialized uninitialized variables + * Aug 2 2006 Add local sidereal time + * Sep 13 2006 Add more local sidereal time subroutines + * Oct 2 2006 Add UT to old FITS date conversions + * Oct 6 2006 Add eqeqnx() to compute equation of the equinoxes + * + * Jan 8 2007 Remove unused variables + * + * Sep 5 2008 Replace nutation with IAU 2006 model translated from SOFA + * Sep 9 2008 Add ang2hr(), ang2deg(), hr2ang(), deg2ang() + * Sep 10 2008 Add longitude to mean standard time (default = Greenwich) + * Oct 8 2008 Clean up sidereal time computations + * + * Sep 24 2009 Add end to comment "Coefficients for fundamental arguments" + * + * Jan 11 2012 Add TAI, TT, GPS time + * Oct 19 2012 Unused l0 dropped from jd2lst(); ts2ss from jd2mst() + */ diff --git a/astroem/distort.c b/astroem/distort.c new file mode 100644 index 00000000..d903dfe4 --- /dev/null +++ b/astroem/distort.c @@ -0,0 +1,407 @@ +/*** File libwcs/distort.c + *** January 4, 2007 + *** By Jessica Mink, jmink@cfa.harvard.edu, + *** Based on code written by Jing Li, IPAC + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 2004-2007 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + + * Module: distort.c (World Coordinate Systems) + * Purpose: Convert focal plane coordinates to pixels and vice versa: + * Subroutine: distortinit (wcs, hstring) set distortion coefficients from FITS header + * Subroutine: DelDistort (header, verbose) delete distortion coefficients in FITS header + * Subroutine: pix2foc (wcs, x, y, u, v) pixel coordinates -> focal plane coordinates + * Subroutine: foc2pix (wcs, u, v, x, y) focal plane coordinates -> pixel coordinates + * Subroutine: setdistcode (wcs,ctype) sets distortion code from CTYPEi + * Subroutine: getdistcode (wcs) returns distortion code string for CTYPEi + */ + +#include +#include +#include +#include +#include "wcs.h" + +void +distortinit (wcs, hstring) +struct WorldCoor *wcs; /* World coordinate system structure */ +const char *hstring; /* character string containing FITS header information + in the format = [/ ] */ +{ + int i, j, m; + char keyword[12]; + + /* Read distortion coefficients, if present */ + if (wcs->distcode == DISTORT_SIRTF) { + if (wcs->wcsproj == WCS_OLD) { + wcs->wcsproj = WCS_NEW; + wcs->distort.a_order = 0; + wcs->distort.b_order = 0; + wcs->distort.ap_order = 0; + wcs->distort.bp_order = 0; + } + else { + if (!hgeti4 (hstring, "A_ORDER", &wcs->distort.a_order)) { + setwcserr ("DISTINIT: Missing A_ORDER keyword for Spitzer distortion"); + } + else { + m = wcs->distort.a_order; + for (i = 0; i <= m; i++) { + for (j = 0; j <= m; j++) { + wcs->distort.a[i][j] = 0.0; + } + } + for (i = 0; i <= m; i++) { + for (j = 0; j <= m-i; j++) { + sprintf (keyword, "A_%d_%d", i, j); + hgetr8 (hstring, keyword, &wcs->distort.a[i][j]); + } + } + } + if (!hgeti4 (hstring, "B_ORDER", &wcs->distort.b_order)) { + setwcserr ("DISTINIT: Missing B_ORDER keyword for Spitzer distortion"); + } + else { + m = wcs->distort.b_order; + for (i = 0; i <= m; i++) { + for (j = 0; j <= m; j++) { + wcs->distort.b[i][j] = 0.0; + } + } + for (i = 0; i <= m; i++) { + for (j = 0; j <= m-i; j++) { + sprintf (keyword, "B_%d_%d", i, j); + hgetr8 (hstring, keyword, &wcs->distort.b[i][j]); + } + } + } + if (!hgeti4 (hstring, "AP_ORDER", &wcs->distort.ap_order)) { + setwcserr ("DISTINIT: Missing AP_ORDER keyword for Spitzer distortion"); + } + else { + m = wcs->distort.ap_order; + for (i = 0; i <= m; i++) { + for (j = 0; j <= m; j++) { + wcs->distort.ap[i][j] = 0.0; + } + } + for (i = 0; i <= m; i++) { + for (j = 0; j <= m-i; j++) { + sprintf (keyword, "AP_%d_%d", i, j); + hgetr8 (hstring, keyword, &wcs->distort.ap[i][j]); + } + } + } + if (!hgeti4 (hstring, "BP_ORDER", &wcs->distort.bp_order)) { + setwcserr ("DISTINIT: Missing BP_ORDER keyword for Spitzer distortion"); + } + else { + m = wcs->distort.bp_order; + for (i = 0; i <= m; i++) { + for (j = 0; j <= m; j++) { + wcs->distort.bp[i][j] = 0.0; + } + } + for (i = 0; i <= m; i++) { + for (j = 0; j <= m-i; j++) { + sprintf (keyword, "BP_%d_%d", i, j); + hgetr8 (hstring, keyword, &wcs->distort.bp[i][j]); + } + } + } + } + } + return; +} + + +/* Delete all distortion-related fields. + * return 0 if at least one such field is found, else -1. */ + +int +DelDistort (header, verbose) + +char *header; +int verbose; + +{ + char keyword[16]; + char str[32]; + int i, j, m; + int lctype; + int n; + + n = 0; + + if (hgeti4 (header, "A_ORDER", &m)) { + for (i = 0; i <= m; i++) { + for (j = 0; j <= m-i; j++) { + sprintf (keyword, "A_%d_%d", i, j); + hdel (header, keyword); + n++; + } + } + hdel (header, "A_ORDER"); + n++; + } + + if (hgeti4 (header, "AP_ORDER", &m)) { + for (i = 0; i <= m; i++) { + for (j = 0; j <= m-i; j++) { + sprintf (keyword, "AP_%d_%d", i, j); + hdel (header, keyword); + n++; + } + } + hdel (header, "AP_ORDER"); + n++; + } + + if (hgeti4 (header, "B_ORDER", &m)) { + for (i = 0; i <= m; i++) { + for (j = 0; j <= m-i; j++) { + sprintf (keyword, "B_%d_%d", i, j); + hdel (header, keyword); + n++; + } + } + hdel (header, "B_ORDER"); + n++; + } + + if (hgeti4 (header, "BP_ORDER", &m)) { + for (i = 0; i <= m; i++) { + for (j = 0; j <= m-i; j++) { + sprintf (keyword, "BP_%d_%d", i, j); + hdel (header, keyword); + n++; + } + } + hdel (header, "BP_ORDER"); + n++; + } + + if (n > 0 && verbose) + fprintf (stderr,"%d keywords deleted\n", n); + + /* Remove WCS distortion code from CTYPEi in FITS header */ + if (hgets (header, "CTYPE1", 31, str)) { + lctype = strlen (str); + if (lctype > 8) { + str[8] = (char) 0; + hputs (header, "CTYPE1", str); + } + } + if (hgets (header, "CTYPE2", 31, str)) { + lctype = strlen (str); + if (lctype > 8) { + str[8] = (char) 0; + hputs (header, "CTYPE2", str); + } + } + + return (n); +} + +void +foc2pix (wcs, x, y, u, v) + +struct WorldCoor *wcs; /* World coordinate system structure */ +double x, y; /* Focal plane coordinates */ +double *u, *v; /* Image pixel coordinates (returned) */ +{ + int m, n, i, j, k; + double s[DISTMAX], sum; + double temp_x, temp_y; + + /* Spitzer distortion */ + if (wcs->distcode == DISTORT_SIRTF) { + m = wcs->distort.ap_order; + n = wcs->distort.bp_order; + + temp_x = x - wcs->xrefpix; + temp_y = y - wcs->yrefpix; + + /* compute u */ + for (j = 0; j <= m; j++) { + s[j] = wcs->distort.ap[m-j][j]; + for (k = j-1; k >= 0; k--) { + s[j] = (temp_y * s[j]) + wcs->distort.ap[m-j][k]; + } + } + + sum = s[0]; + for (i=m; i>=1; i--){ + sum = (temp_x * sum) + s[m-i+1]; + } + *u = sum; + + /* compute v*/ + for (j = 0; j <= n; j++) { + s[j] = wcs->distort.bp[n-j][j]; + for (k = j-1; k >= 0; k--) { + s[j] = temp_y*s[j] + wcs->distort.bp[n-j][k]; + } + } + + sum = s[0]; + for (i = n; i >= 1; i--) + sum = temp_x * sum + s[n-i+1]; + + *v = sum; + + *u = x + *u; + *v = y + *v; + } + + /* If no distortion, return pixel positions unchanged */ + else { + *u = x; + *v = y; + } + + return; +} + + +void +pix2foc (wcs, u, v, x, y) + +struct WorldCoor *wcs; /* World coordinate system structure */ +double u, v; /* Image pixel coordinates */ +double *x, *y; /* Focal plane coordinates (returned) */ +{ + int m, n, i, j, k; + double s[DISTMAX], sum; + double temp_u, temp_v; + + /* Spitzer distortion */ + if (wcs->distcode == DISTORT_SIRTF) { + m = wcs->distort.a_order; + n = wcs->distort.b_order; + + temp_u = u - wcs->xrefpix; + temp_v = v - wcs->yrefpix; + + /* compute u */ + for (j = 0; j <= m; j++) { + s[j] = wcs->distort.a[m-j][j]; + for (k = j-1; k >= 0; k--) { + s[j] = (temp_v * s[j]) + wcs->distort.a[m-j][k]; + } + } + + sum = s[0]; + for (i=m; i>=1; i--){ + sum = temp_u*sum + s[m-i+1]; + } + *x = sum; + + /* compute v*/ + for (j=0; j<=n; j++) { + s[j] = wcs->distort.b[n-j][j]; + for (k=j-1; k>=0; k--) { + s[j] =temp_v*s[j] + wcs->distort.b[n-j][k]; + } + } + + sum = s[0]; + for (i=n; i>=1; i--) + sum = temp_u*sum + s[n-i+1]; + + *y = sum; + + *x = u + *x; + *y = v + *y; + +/* *x = u + *x + coeff.crpix1; */ +/* *y = v + *y + coeff.crpix2; */ + } + + /* If no distortion, return pixel positions unchanged */ + else { + *x = u; + *y = v; + } + + return; +} + + +/* SETDISTCODE -- Set WCS distortion code from CTYPEi in FITS header */ + +void +setdistcode (wcs, ctype) + +struct WorldCoor *wcs; /* World coordinate system structure */ +char *ctype; /* Value of CTYPEi from FITS header */ + +{ + char *extension; + int lctype; + + lctype = strlen (ctype); + if (lctype < 9) + wcs->distcode = DISTORT_NONE; + else { + extension = ctype + 8; + if (!strncmp (extension, "-SIP", 4)) + wcs->distcode = DISTORT_SIRTF; + else + wcs->distcode = DISTORT_NONE; + } + return; +} + + +/* GETDISTCODE -- Return NULL if no distortion or code from wcs.h */ + +char * +getdistcode (wcs) + +struct WorldCoor *wcs; /* World coordinate system structure */ + +{ + char *dcode; /* Distortion string for CTYPEi */ + + if (wcs->distcode == DISTORT_SIRTF) { + dcode = (char *) calloc (8, sizeof (char)); + strcpy (dcode, "-SIP"); + } + else + dcode = NULL; + return (dcode); +} + +/* Apr 2 2003 New subroutines + * Nov 3 2003 Add getdistcode to return distortion code string + * Nov 10 2003 Include unistd.h to get definition of NULL + * Nov 18 2003 Include string.h to get strlen() + * + * Jan 9 2004 Add DelDistort() to delete distortion keywords + * + * Jan 4 2007 Declare header const char* + * + * Feb 25 2011 Change SIRTF to Spitzer (long overdue!) + */ diff --git a/astroem/dsspos.c b/astroem/dsspos.c new file mode 100644 index 00000000..3bbd5a0b --- /dev/null +++ b/astroem/dsspos.c @@ -0,0 +1,318 @@ +/*** File saoimage/wcslib/dsspos.c + *** October 21, 1999 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1995-2002 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + + * Module: dsspos.c (Plate solution WCS conversion) + * Purpose: Compute WCS from Digital Sky Survey plate fit + * Subroutine: dsspos() converts from pixel location to RA,Dec + * Subroutine: dsspix() converts from RA,Dec to pixel location + + These functions are based on the astrmcal.c portion of GETIMAGE by + J. Doggett and the documentation distributed with the Digital Sky Survey. + +*/ + +#include +#include +#include +#include "wcs.h" + +int +dsspos (xpix, ypix, wcs, xpos, ypos) + +/* Routine to determine accurate position for pixel coordinates */ +/* returns 0 if successful otherwise 1 = angle too large for projection; */ +/* based on amdpos() from getimage */ + +/* Input: */ +double xpix; /* x pixel number (RA or long without rotation) */ +double ypix; /* y pixel number (dec or lat without rotation) */ +struct WorldCoor *wcs; /* WCS parameter structure */ + +/* Output: */ +double *xpos; /* Right ascension or longitude in degrees */ +double *ypos; /* Declination or latitude in degrees */ + +{ + double x, y, xmm, ymm, xmm2, ymm2, xmm3, ymm3, x2y2; + double xi, xir, eta, etar, raoff, ra, dec; + double cond2r = 1.745329252e-2; + double cons2r = 206264.8062470964; + double twopi = 6.28318530717959; + double ctan, ccos; + +/* Ignore magnitude and color terms + double mag = 0.0; + double color = 0.0; */ + +/* Convert from image pixels to plate pixels */ + x = xpix + wcs->x_pixel_offset - 1.0 + 0.5; + y = ypix + wcs->y_pixel_offset - 1.0 + 0.5; + +/* Convert from pixels to millimeters */ + xmm = (wcs->ppo_coeff[2] - x * wcs->x_pixel_size) / 1000.0; + ymm = (y * wcs->y_pixel_size - wcs->ppo_coeff[5]) / 1000.0; + xmm2 = xmm * xmm; + ymm2 = ymm * ymm; + xmm3 = xmm * xmm2; + ymm3 = ymm * ymm2; + x2y2 = xmm2 + ymm2; + +/* Compute coordinates from x,y and plate model */ + + xi = wcs->x_coeff[ 0]*xmm + wcs->x_coeff[ 1]*ymm + + wcs->x_coeff[ 2] + wcs->x_coeff[ 3]*xmm2 + + wcs->x_coeff[ 4]*xmm*ymm + wcs->x_coeff[ 5]*ymm2 + + wcs->x_coeff[ 6]*(x2y2) + wcs->x_coeff[ 7]*xmm3 + + wcs->x_coeff[ 8]*xmm2*ymm + wcs->x_coeff[ 9]*xmm*ymm2 + + wcs->x_coeff[10]*ymm3 + wcs->x_coeff[11]*xmm*(x2y2) + + wcs->x_coeff[12]*xmm*x2y2*x2y2; + +/* Ignore magnitude and color terms + + wcs->x_coeff[13]*mag + wcs->x_coeff[14]*mag*mag + + wcs->x_coeff[15]*mag*mag*mag + wcs->x_coeff[16]*mag*xmm + + wcs->x_coeff[17]*mag*x2y2 + wcs->x_coeff[18]*mag*xmm*x2y2 + + wcs->x_coeff[19]*color; */ + + eta = wcs->y_coeff[ 0]*ymm + wcs->y_coeff[ 1]*xmm + + wcs->y_coeff[ 2] + wcs->y_coeff[ 3]*ymm2 + + wcs->y_coeff[ 4]*xmm*ymm + wcs->y_coeff[ 5]*xmm2 + + wcs->y_coeff[ 6]*(x2y2) + wcs->y_coeff[ 7]*ymm3 + + wcs->y_coeff[ 8]*ymm2*xmm + wcs->y_coeff[ 9]*ymm*xmm2 + + wcs->y_coeff[10]*xmm3 + wcs->y_coeff[11]*ymm*(x2y2) + + wcs->y_coeff[12]*ymm*x2y2*x2y2; + +/* Ignore magnitude and color terms + + wcs->y_coeff[13]*mag + wcs->y_coeff[14]*mag*mag + + wcs->y_coeff[15]*mag*mag*mag + wcs->y_coeff[16]*mag*ymm + + wcs->y_coeff[17]*mag*x2y2) + wcs->y_coeff[18]*mag*ymm*x2y2 + + wcs->y_coeff[19]*color; */ + +/* Convert to radians */ + + xir = xi / cons2r; + etar = eta / cons2r; + +/* Convert to RA and Dec */ + + ctan = tan (wcs->plate_dec); + ccos = cos (wcs->plate_dec); + raoff = atan2 (xir / ccos, 1.0 - etar * ctan); + ra = raoff + wcs->plate_ra; + if (ra < 0.0) ra = ra + twopi; + *xpos = ra / cond2r; + + dec = atan (cos (raoff) * ((etar + ctan) / (1.0 - (etar * ctan)))); + *ypos = dec / cond2r; + return 0; +} + + +int +dsspix (xpos, ypos, wcs, xpix, ypix) + +/* Routine to determine pixel coordinates for sky position */ +/* returns 0 if successful otherwise 1 = angle too large for projection; */ +/* based on amdinv() from getimage */ + +/* Input: */ +double xpos; /* Right ascension or longitude in degrees */ +double ypos; /* Declination or latitude in degrees */ +struct WorldCoor *wcs; /* WCS parameter structure */ + +/* Output: */ +double *xpix; /* x pixel number (RA or long without rotation) */ +double *ypix; /* y pixel number (dec or lat without rotation) */ + +{ + double div,xi,eta,x,y,xy,x2,y2,x2y,y2x,x3,y3,x4,y4,x2y2,cjunk,dx,dy; + double sypos,cypos,syplate,cyplate,sxdiff,cxdiff; + double f,fx,fy,g,gx,gy, xmm, ymm; + double conr2s = 206264.8062470964; + double tolerance = 0.0000005; + int max_iterations = 50; + int i; + double xr, yr; /* position in radians */ + + *xpix = 0.0; + *ypix = 0.0; + +/* Convert RA and Dec in radians to standard coordinates on a plate */ + xr = degrad (xpos); + yr = degrad (ypos); + sypos = sin (yr); + cypos = cos (yr); + if (wcs->plate_dec == 0.0) + wcs->plate_dec = degrad (wcs->yref); + syplate = sin (wcs->plate_dec); + cyplate = cos (wcs->plate_dec); + if (wcs->plate_ra == 0.0) + wcs->plate_ra = degrad (wcs->yref); + sxdiff = sin (xr - wcs->plate_ra); + cxdiff = cos (xr - wcs->plate_ra); + div = (sypos * syplate) + (cypos * cyplate * cxdiff); + if (div == 0.0) + return (1); + xi = cypos * sxdiff * conr2s / div; + eta = ((sypos * cyplate) - (cypos * syplate * cxdiff)) * conr2s / div; + +/* Set initial value for x,y */ + if (wcs->plate_scale == 0.0) + return (1); + xmm = xi / wcs->plate_scale; + ymm = eta / wcs->plate_scale; + +/* Iterate by Newton's method */ + for (i = 0; i < max_iterations; i++) { + + /* X plate model */ + xy = xmm * ymm; + x2 = xmm * xmm; + y2 = ymm * ymm; + x2y = x2 * ymm; + y2x = y2 * xmm; + x2y2 = x2 + y2; + cjunk = x2y2 * x2y2; + x3 = x2 * xmm; + y3 = y2 * ymm; + x4 = x2 * x2; + y4 = y2 * y2; + f = wcs->x_coeff[0]*xmm + wcs->x_coeff[1]*ymm + + wcs->x_coeff[2] + wcs->x_coeff[3]*x2 + + wcs->x_coeff[4]*xy + wcs->x_coeff[5]*y2 + + wcs->x_coeff[6]*x2y2 + wcs->x_coeff[7]*x3 + + wcs->x_coeff[8]*x2y + wcs->x_coeff[9]*y2x + + wcs->x_coeff[10]*y3 + wcs->x_coeff[11]*xmm*x2y2 + + wcs->x_coeff[12]*xmm*cjunk; + /* magnitude and color terms ignored + + wcs->x_coeff[13]*mag + + wcs->x_coeff[14]*mag*mag + wcs->x_coeff[15]*mag*mag*mag + + wcs->x_coeff[16]*mag*xmm + wcs->x_coeff[17]*mag*(x2+y2) + + wcs->x_coeff[18]*mag*xmm*(x2+y2) + wcs->x_coeff[19]*color; + */ + + /* Derivative of X model wrt x */ + fx = wcs->x_coeff[0] + wcs->x_coeff[3]*2.0*xmm + + wcs->x_coeff[4]*ymm + wcs->x_coeff[6]*2.0*xmm + + wcs->x_coeff[7]*3.0*x2 + wcs->x_coeff[8]*2.0*xy + + wcs->x_coeff[9]*y2 + wcs->x_coeff[11]*(3.0*x2+y2) + + wcs->x_coeff[12]*(5.0*x4 +6.0*x2*y2+y4); + /* magnitude and color terms ignored + wcs->x_coeff[16]*mag + wcs->x_coeff[17]*mag*2.0*xmm + + wcs->x_coeff[18]*mag*(3.0*x2+y2); + */ + + /* Derivative of X model wrt y */ + fy = wcs->x_coeff[1] + wcs->x_coeff[4]*xmm + + wcs->x_coeff[5]*2.0*ymm + wcs->x_coeff[6]*2.0*ymm + + wcs->x_coeff[8]*x2 + wcs->x_coeff[9]*2.0*xy + + wcs->x_coeff[10]*3.0*y2 + wcs->x_coeff[11]*2.0*xy + + wcs->x_coeff[12]*4.0*xy*x2y2; + /* magnitude and color terms ignored + wcs->x_coeff[17]*mag*2.0*ymm + + wcs->x_coeff[18]*mag*2.0*xy; + */ + + /* Y plate model */ + g = wcs->y_coeff[0]*ymm + wcs->y_coeff[1]*xmm + + wcs->y_coeff[2] + wcs->y_coeff[3]*y2 + + wcs->y_coeff[4]*xy + wcs->y_coeff[5]*x2 + + wcs->y_coeff[6]*x2y2 + wcs->y_coeff[7]*y3 + + wcs->y_coeff[8]*y2x + wcs->y_coeff[9]*x2y + + wcs->y_coeff[10]*x3 + wcs->y_coeff[11]*ymm*x2y2 + + wcs->y_coeff[12]*ymm*cjunk; + /* magnitude and color terms ignored + wcs->y_coeff[13]*mag + wcs->y_coeff[14]*mag*mag + + wcs->y_coeff[15]*mag*mag*mag + wcs->y_coeff[16]*mag*ymm + + wcs->y_coeff[17]*mag*x2y2 + + wcs->y_coeff[18]*mag*ymm*x2y2 + wcs->y_coeff[19]*color; + */ + + /* Derivative of Y model wrt x */ + gx = wcs->y_coeff[1] + wcs->y_coeff[4]*ymm + + wcs->y_coeff[5]*2.0*xmm + wcs->y_coeff[6]*2.0*xmm + + wcs->y_coeff[8]*y2 + wcs->y_coeff[9]*2.0*xy + + wcs->y_coeff[10]*3.0*x2 + wcs->y_coeff[11]*2.0*xy + + wcs->y_coeff[12]*4.0*xy*x2y2; + /* magnitude and color terms ignored + wcs->y_coeff[17]*mag*2.0*xmm + + wcs->y_coeff[18]*mag*ymm*2.0*xmm; + */ + + /* Derivative of Y model wrt y */ + gy = wcs->y_coeff[0] + wcs->y_coeff[3]*2.0*ymm + + wcs->y_coeff[4]*xmm + wcs->y_coeff[6]*2.0*ymm + + wcs->y_coeff[7]*3.0*y2 + wcs->y_coeff[8]*2.0*xy + + wcs->y_coeff[9]*x2 + wcs->y_coeff[11]*(x2+3.0*y2) + + wcs->y_coeff[12]*(5.0*y4 + 6.0*x2*y2 + x4); + /* magnitude and color terms ignored + wcs->y_coeff[16]*mag + wcs->y_coeff[17]*mag*2.0*ymm + + wcs->y_coeff[18]*mag*(x2+3.0*y2); + */ + + f = f - xi; + g = g - eta; + dx = ((-f * gy) + (g * fy)) / ((fx * gy) - (fy * gx)); + dy = ((-g * fx) + (f * gx)) / ((fx * gy) - (fy * gx)); + xmm = xmm + dx; + ymm = ymm + dy; + if ((fabs(dx) < tolerance) && (fabs(dy) < tolerance)) break; + } + +/* Convert mm from plate center to plate pixels */ + if (wcs->x_pixel_size == 0.0 || wcs->y_pixel_size == 0.0) + return (1); + x = (wcs->ppo_coeff[2] - xmm*1000.0) / wcs->x_pixel_size; + y = (wcs->ppo_coeff[5] + ymm*1000.0) / wcs->y_pixel_size; + +/* Convert from plate pixels to image pixels */ + *xpix = x - wcs->x_pixel_offset + 1.0 - 0.5; + *ypix = y - wcs->y_pixel_offset + 1.0 - 0.5; + +/* If position is off of the image, return offscale code */ + if (*xpix < 0.5 || *xpix > wcs->nxpix+0.5) + return -1; + if (*ypix < 0.5 || *ypix > wcs->nypix+0.5) + return -1; + + return 0; +} +/* Mar 6 1995 Original version of this code + * May 4 1995 Fix eta cross terms which were all in y + * Jun 21 1995 Add inverse routine + * Oct 17 1995 Fix inverse routine (degrees -> radians) + * Nov 7 1995 Add half pixel to image coordinates to get astrometric + * plate coordinates + * Feb 26 1996 Fix plate to image pixel conversion error + * + * Mar 23 1998 Change names from plate*() to dss*() + * Apr 7 1998 Change amd_i_coeff to i_coeff + * Sep 4 1998 Fix possible divide by zero in dsspos() from Allen Harris, SAO + * Sep 10 1998 Fix possible divide by zero in dsspix() from Allen Harris, SAO + * + * Oct 21 1999 Drop declaration of cond2r in dsspix() + */ diff --git a/astroem/empty_main.c b/astroem/empty_main.c new file mode 100644 index 00000000..b54a2202 --- /dev/null +++ b/astroem/empty_main.c @@ -0,0 +1,2 @@ +int main() { return 0; } + diff --git a/astroem/eps.h b/astroem/eps.h new file mode 100644 index 00000000..c65ed4b4 --- /dev/null +++ b/astroem/eps.h @@ -0,0 +1,109 @@ +/* + * EPS.H -- Include definitions for EPS hardcopy routines. + */ + + +/* Handy macro definitions */ + +#define MONO(rd,gn,bl) ((int)(rd*11 + gn*16 + bl*5) >> 5) /*.33R+ .5G+ .17B*/ +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +#define Orientation(ps) ( ps->page.orientation ) +#define Scale(ps) ( ps->page.scale ) +#define MaxScale(ps) ( ps->page.maxscale ) +#define PageType(ps) ( ps->page.page_type ) +#define DoAutoScale(ps) ( ps->page.flags & EPS_AUTOSCALE ) +#define DoAutoRotate(ps) ( ps->page.flags & EPS_AUTOROTATE ) +#define DoMaxAspect(ps) ( ps->page.flags & EPS_MAXASPECT ) + +#define PIX_PER_LINE 72 + +/* Compression options. */ +#define NoCompression 0 /* Don't compress image */ +#define RLECompression 1 /* RLE compression */ +#define LZWCompression 2 /* LZW compression (not implemted) */ +#define JPEGCompression 3 /* JPEG compression (not implemted) */ + +/* Output color classes. */ +#define EPS_GRAYSCALE 0 /* Write a grayscale image */ +#define EPS_PSEUDOCOLOR 1 /* Write a pseudocolor image */ +#define EPS_TRUECOLOR 2 /* Write a RGB image */ + +/* Page option flags. */ +#define EPS_PORTRAIT 0 /* Page orientations */ +#define EPS_LANDSCAPE 1 +#define EPS_AUTOSCALE 0x01 /* Auto scale to fit on page */ +#define EPS_AUTOROTATE 0x02 /* Auto rotate to fit on page */ +#define EPS_MAXASPECT 0x04 /* Increase scale to max aspect */ + +/* Transformation parameters. */ +#define EPS_UNITARY 0 +#define EPS_LINEAR 1 +#define EPS_LOG 2 + +/* Page layout structure. */ +typedef struct { + int orientation; /* page orioentation */ + float scale; /* image scale factor */ + float maxscale; /* maxaspect image scale factor */ + int dpi; /* dpi resolution */ + int page_type; /* type of paper being used */ + int flags; /* option flags */ +} PSPage, *PSPagePtr; + +/* Colormap structure. */ +typedef struct { + int IsDefault; /* Are we using the default colormap? */ + int ncolors; /* number of colormap colors */ + int min, max; /* image min/max */ + unsigned char r[256]; /* red colormap */ + unsigned char g[256]; /* green colormap */ + unsigned char b[256]; /* blue colormap */ + char *cmap_name; /* colormap name */ +} PSCmap, *PSCmapPtr; + +/* Main EPS structure. */ +typedef struct { + int cols; /* num output columns */ + int rows; /* num output rows */ + int colorClass; /* output color class */ + int compression; /* output compression type */ + int annotate; /* annotate the output image? */ + int llx, lly, urx, ury; /* image coordinate corners */ + float z1, z2; /* zscale transform values */ + int ztype; /* type of transformation */ + float offset, scale; /* brightness/contrast values */ + char *label; /* label string */ + + PSPage page; /* Page layout structure */ + PSCmap cmap; /* Colormap struct */ +} PSImage, *PSImagePtr; + + +/* Page sizes and resolution information. */ +#define EPS_LETTER 0 +#define EPS_LEGAL 1 +#define EPS_A4 2 +#define EPS_B5 3 +#define EPS_BSIZE 4 +#define EPS_4BY5 5 +#define EPS_35MM 6 + +/* Page layout definitions. */ +#define X_ANNOT_MARGIN 30 /* margin in pixels for annotation */ +#define Y_ANNOT_MARGIN 60 /* margin in pixels for annotation */ +#define TITLE_OFFSET 20 /* Offset for title string */ +#define AXIS_OOFFSET 7 /* Outer offset for axis */ +#define AXIS_IOFFSET 2 /* Inner offset for axis */ +#define AXIS_OWIDTH 1.5 /* Outer axis width */ +#define AXIS_IWIDTH 1.0 /* Inner axis width */ +#define MAJOR_TICK_SIZE 5 /* Size of major tic mark */ +#define MAJOR_TICK_WIDTH 1.5 /* Width of major tic mark */ +#define MINOR_TICK_SIZE 3 /* Size of major tic mark */ +#define MINOR_TICK_WIDTH 0.5 /* Width of major tic mark */ +#define NTICMARKS 5 /* Number of major tick marks */ + diff --git a/astroem/fileutil.c b/astroem/fileutil.c new file mode 100644 index 00000000..a4189a15 --- /dev/null +++ b/astroem/fileutil.c @@ -0,0 +1,818 @@ +/*** File libwcs/fileutil.c + *** January 11, 2007 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1999-2007 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + + * Module: fileutil.c (ASCII file utilities) + * Purpose: Find out things about ASCII files + * Subroutine: getfilelines (filename) + * Return number of lines in an ASCII file + * Subroutine: getfilebuff (filename) + * Return entire file contents in a character string + * Subroutine: getfilesize (filename) + * Return size of a binary or ASCII file + * Subroutine: isimlist (filename) + * Return 1 if file is list of FITS or IRAF image files, else 0 + * Subroutine: isimlistd (filename, rootdir) + * Return 1 if file is list of FITS or IRAF image files, else 0 + * Subroutine: isfilelist (filename, rootdir) + * Return 1 if file is list of readable files, else 0 + * Subroutine: isfile (filename) + * Return 1 if file is a readable file, else 0 + * Subroutine: first_token (diskfile, ncmax, token) + * Return first token from the next line of an ASCII file + * Subroutine: stc2s (spchar, string) + * Replace character in string with space + * Subroutine: sts2c (spchar, string) + * Replace spaces in string with character + * Subroutine: istiff (filename) + * Return 1 if file is a readable TIFF graphics file, else 0 + * Subroutine: isjpeg (filename) + * Return 1 if file is a readable JPEG graphics file, else 0 + * int setoken (tokens, string, cwhite) + * Tokenize a string for easy decoding + * int nextoken (tokens, token, maxchars) + * Get next token from tokenized string + * int getoken (tokens, itok, token, maxchars) + * Get specified token from tokenized string + */ + +#include +#ifndef VMS +#include +#endif +#include +#include +#include +#include +#include +#include "fitsfile.h" +#include +#include + + +/* GETFILELINES -- return number of lines in one file */ + +int +getfilelines (filename) + +char *filename; /* Name of file for which to find number of lines */ +{ + + char *buffer, *bufline; + int nlines = 0; + char newline = 10; + + /* Read file */ + buffer = getfilebuff (filename); + + /* Count lines in file */ + if (buffer != NULL) { + bufline = buffer; + nlines = 0; + while ((bufline = strchr (bufline, newline)) != NULL) { + bufline = bufline + 1; + nlines++; + } + free (buffer); + return (nlines); + } + else { + return (0); + } +} + + +/* GETFILEBUFF -- return entire file contents in one character string */ + +char * +getfilebuff (filename) + +char *filename; /* Name of file for which to find number of lines */ +{ + + FILE *diskfile; + int lfile, nr, lbuff, ipt, ibuff; + char *buffer, *newbuff, *nextbuff; + + /* Treat stdin differently */ + if (!strcmp (filename, "stdin")) { + lbuff = 5000; + lfile = lbuff; + buffer = NULL; + ipt = 0; + for (ibuff = 0; ibuff < 10; ibuff++) { + if ((newbuff = realloc (buffer, lfile+1)) != NULL) { + buffer = newbuff; + nextbuff = buffer + ipt; + nr = fread (nextbuff, 1, lbuff, stdin); + if (nr == lbuff) + break; + else { + ipt = ipt + lbuff; + lfile = lfile + lbuff; + } + } + else { + fprintf (stderr,"GETFILEBUFF: No room for %d-byte buffer\n", + lfile); + break; + } + } + return (buffer); + } + + /* Open file */ + if ((diskfile = fopen (filename, "rb")) == NULL) + return (NULL); + + /* Find length of file */ + if (fseek (diskfile, 0, 2) == 0) + lfile = ftell (diskfile); + else + lfile = 0; + if (lfile < 1) { + fprintf (stderr,"GETFILEBUFF: File %s is empty\n", filename); + fclose (diskfile); + return (NULL); + } + + /* Allocate buffer to hold entire file and read it */ + if ((buffer = calloc (1, lfile+1)) != NULL) { + fseek (diskfile, 0, 0); + nr = fread (buffer, 1, lfile, diskfile); + if (nr < lfile) { + fprintf (stderr,"GETFILEBUFF: File %s: read %d / %d bytes\n", + filename, nr, lfile); + free (buffer); + fclose (diskfile); + return (NULL); + } + buffer[lfile] = (char) 0; + fclose (diskfile); + return (buffer); + } + else { + fprintf (stderr,"GETFILEBUFF: File %s: no room for %d-byte buffer\n", + filename, lfile); + fclose (diskfile); + return (NULL); + } +} + + +/* GETFILESIZE -- return size of one file in bytes */ + +int +getfilesize (filename) + +char *filename; /* Name of file for which to find size */ +{ + struct stat statbuff; + + if (stat (filename, &statbuff)) + return (0); + else + return ((int) statbuff.st_size); +} + +int +getfilesize0 (filename) + +char *filename; /* Name of file for which to find size */ +{ + FILE *diskfile; + long filesize; + + /* Open file */ + if ((diskfile = fopen (filename, "rb")) == NULL) + return (-1); + + /* Move to end of the file */ + if (fseek (diskfile, 0, 2) == 0) + + /* Position is the size of the file */ + filesize = ftell (diskfile); + + else + filesize = -1; + + fclose (diskfile); + + return ((int) filesize); +} + + +/* ISIMLIST -- Return 1 if list of FITS or IRAF files, else 0 */ +int +isimlist (filename) + +char *filename; /* Name of possible list file */ +{ + FILE *diskfile; + char token[256]; + int ncmax = 254; + + if ((diskfile = fopen (filename, "r")) == NULL) + return (0); + else { + first_token (diskfile, ncmax, token); + fclose (diskfile); + if (isfits (token) | isiraf (token)) + return (1); + else + return (0); + } +} + + +/* ISIMLISTD -- Return 1 if list of FITS or IRAF files, else 0 */ +int +isimlistd (filename, rootdir) + +char *filename; /* Name of possible list file */ +char *rootdir; /* Name of root directory for files in list */ +{ + FILE *diskfile; + char token[256]; + char filepath[256]; + int ncmax = 254; + + if ((diskfile = fopen (filename, "r")) == NULL) + return (0); + else { + first_token (diskfile, ncmax, token); + fclose (diskfile); + if (rootdir != NULL) { + strcpy (filepath, rootdir); + strcat (filepath, "/"); + strcat (filepath, token); + } + else + strcpy (filepath, token); + if (isfits (filepath) | isiraf (filepath)) + return (1); + else + return (0); + } +} + + +/* ISFILELIST -- Return 1 if list of readable files, else 0 */ +int +isfilelist (filename, rootdir) + +char *filename; /* Name of possible list file */ +char *rootdir; /* Name of root directory for files in list */ +{ + FILE *diskfile; + char token[256]; + char filepath[256]; + int ncmax = 254; + + if ((diskfile = fopen (filename, "r")) == NULL) + return (0); + else { + first_token (diskfile, ncmax, token); + fclose (diskfile); + if (rootdir != NULL) { + strcpy (filepath, rootdir); + strcat (filepath, "/"); + strcat (filepath, token); + } + else + strcpy (filepath, token); + if (isfile (filepath)) + return (1); + else + return (0); + } +} + + +/* ISFILE -- Return 1 if file is a readable file, else 0 */ + +int +isfile (filename) + +char *filename; /* Name of file to check */ +{ + if (!strcasecmp (filename, "stdin")) + return (1); + else if (access (filename, R_OK)) + return (0); + else + return (1); +} + + +/* FIRST_TOKEN -- Return first token from the next line of an ASCII file */ + +int +first_token (diskfile, ncmax, token) + +FILE *diskfile; /* File descriptor for ASCII file */ +int ncmax; /* Maximum number of characters returned */ +char *token; /* First token on next line (returned) */ +{ + char *lastchar, *lspace; + + /* If line can be read, add null at the end of the first token */ + if (fgets (token, ncmax, diskfile) != NULL) { + if (token[0] == '#') { + (void) fgets (token, ncmax, diskfile); + } + + /* If only character is a control character, return a NULL */ + if ((strlen(token)==1) && (token[0]<32)){ + token[0]=0; + return (1); + } + lastchar = token + strlen (token) - 1; + + /* Remove trailing spaces or control characters */ + while (*lastchar <= 32) + *lastchar-- = 0; + + if ((lspace = strchr (token, ' ')) != NULL) { + *lspace = (char) 0; + } + return (1); + } + else + return (0); +} + + +/* Replace character in string with space */ + +int +stc2s (spchar, string) + +char *spchar; /* Character to replace with spaces */ +char *string; +{ + int i, lstr, n; + lstr = strlen (string); + n = 0; + for (i = 0; i < lstr; i++) { + if (string[i] == spchar[0]) { + n++; + string[i] = ' '; + } + } + return (n); +} + + +/* Replace spaces in string with character */ + +int +sts2c (spchar, string) + +char *spchar; /* Character with which to replace spaces */ +char *string; +{ + int i, lstr, n; + lstr = strlen (string); + n = 0; + for (i = 0; i < lstr; i++) { + if (string[i] == ' ') { + n++; + string[i] = spchar[0]; + } + } + return (n); +} + + +/* ISTIFF -- Return 1 if TIFF file, else 0 */ +int +istiff (filename) + +char *filename; /* Name of file to check */ +{ + int diskfile; + char keyword[16]; + int nbr; + + /* First check to see if this is an assignment */ + if (strchr (filename, '=')) + return (0); + + /* Check file extension */ + if (strsrch (filename, ".tif") || + strsrch (filename, ".tiff") || + strsrch (filename, ".TIFF") || + strsrch (filename, ".TIF")) + return (1); + + /* If no TIFF file suffix, try opening the file */ + else { + if ((diskfile = open (filename, O_RDONLY)) < 0) + return (0); + else { + nbr = read (diskfile, keyword, 4); + close (diskfile); + if (nbr < 4) + return (0); + else if (!strncmp (keyword, "II", 2)) + return (1); + else if (!strncmp (keyword, "MM", 2)) + return (1); + else + return (0); + } + } +} + + +/* ISJPEG -- Return 1 if JPEG file, else 0 */ +int +isjpeg (filename) + +char *filename; /* Name of file to check */ +{ + int diskfile; + char keyword[16]; + int nbr; + + /* First check to see if this is an assignment */ + if (strchr (filename, '=')) + return (0); + + /* Check file extension */ + if (strsrch (filename, ".jpg") || + strsrch (filename, ".jpeg") || + strsrch (filename, ".JPEG") || + strsrch (filename, ".jfif") || + strsrch (filename, ".jfi") || + strsrch (filename, ".JFIF") || + strsrch (filename, ".JFI") || + strsrch (filename, ".JPG")) + return (1); + + /* If no JPEG file suffix, try opening the file */ + else { + if ((diskfile = open (filename, O_RDONLY)) < 0) + return (0); + else { + nbr = read (diskfile, keyword, 2); + close (diskfile); + if (nbr < 4) + return (0); + else if (keyword[0] == (char) 0xFF && + keyword[1] == (char) 0xD8) + return (1); + else + return (0); + } + } +} + + +/* ISGIF -- Return 1 if GIF file, else 0 */ +int +isgif (filename) + +char *filename; /* Name of file to check */ +{ + int diskfile; + char keyword[16]; + int nbr; + + /* First check to see if this is an assignment */ + if (strchr (filename, '=')) + return (0); + + /* Check file extension */ + if (strsrch (filename, ".gif") || + strsrch (filename, ".GIF")) + return (1); + + /* If no GIF file suffix, try opening the file */ + else { + if ((diskfile = open (filename, O_RDONLY)) < 0) + return (0); + else { + nbr = read (diskfile, keyword, 6); + close (diskfile); + if (nbr < 4) + return (0); + else if (!strncmp (keyword, "GIF", 3)) + return (1); + else + return (0); + } + } +} + + +static int maxtokens = MAXTOKENS; /* Set maximum number of tokens from wcscat.h*/ + +/* -- SETOKEN -- tokenize a string for easy decoding */ + +int +setoken (tokens, string, cwhite) + +struct Tokens *tokens; /* Token structure returned */ +char *string; /* character string to tokenize */ +char *cwhite; /* additional whitespace characters + * if = tab, disallow spaces and commas */ +{ + char squote, dquote, jch, newline; + char *iq, *stri, *wtype, *str0, *inew; + int i,j,naddw, ltok; + + newline = (char) 10; + squote = (char) 39; + dquote = (char) 34; + if (string == NULL) + return (0); + + /* Line is terminated by newline or NULL */ + inew = strchr (string, newline); + if (inew != NULL) + tokens->lline = inew - string - 1; + else + tokens->lline = strlen (string); + + /* Save current line in structure */ + tokens->line = string; + + /* Add extra whitespace characters */ + if (cwhite == NULL) + naddw = 0; + else + naddw = strlen (cwhite); + + /* if character is tab, allow only tabs and nulls as separators */ + if (naddw > 0 && !strncmp (cwhite, "tab", 3)) { + tokens->white[0] = (char) 9; /* Tab */ + tokens->white[1] = (char) 0; /* NULL (end of string) */ + tokens->nwhite = 2; + } + + /* if character is bar, allow only bars and nulls as separators */ + else if (naddw > 0 && !strncmp (cwhite, "bar", 3)) { + tokens->white[0] = '|'; /* Bar */ + tokens->white[1] = (char) 0; /* NULL (end of string) */ + tokens->nwhite = 2; + } + + /* otherwise, allow spaces, tabs, commas, nulls, and cwhite */ + else { + tokens->nwhite = 4 + naddw;; + tokens->white[0] = ' '; /* Space */ + tokens->white[1] = (char) 9; /* Tab */ + tokens->white[2] = ','; /* Comma */ + tokens->white[3] = (char) 124; /* Vertical bar */ + tokens->white[4] = (char) 0; /* Null (end of string) */ + if (tokens->nwhite > 20) + tokens->nwhite = 20; + if (naddw > 0) { + i = 0; + for (j = 4; j < tokens->nwhite; j++) { + tokens->white[j] = cwhite[i]; + i++; + } + } + } + tokens->white[tokens->nwhite] = (char) 0; + + tokens->ntok = 0; + tokens->itok = 0; + iq = string - 1; + for (i = 0; i < maxtokens; i++) { + tokens->tok1[i] = NULL; + tokens->ltok[i] = 0; + } + + /* Process string one character at a time */ + stri = string; + str0 = string; + while (stri < string+tokens->lline) { + + /* Keep stuff between quotes in one token */ + if (stri <= iq) + continue; + jch = *stri; + + /* Handle quoted strings */ + if (jch == squote) + iq = strchr (stri+1, squote); + else if (jch == dquote) + iq = strchr (stri+1, dquote); + else + iq = stri; + if (iq > stri) { + tokens->ntok = tokens->ntok + 1; + if (tokens->ntok > maxtokens) return (maxtokens); + tokens->tok1[tokens->ntok] = stri + 1; + tokens->ltok[tokens->ntok] = (iq - stri) - 1; + stri = iq + 1; + str0 = iq + 1; + continue; + } + + /* Search for unquoted tokens */ + wtype = strchr (tokens->white, jch); + + /* If this is one of the additional whitespace characters, + * pass as a separate token */ + if (wtype > tokens->white + 3) { + + /* Terminate token before whitespace */ + if (stri > str0) { + tokens->ntok = tokens->ntok + 1; + if (tokens->ntok > maxtokens) return (maxtokens); + tokens->tok1[tokens->ntok] = str0; + tokens->ltok[tokens->ntok] = stri - str0; + } + + /* Make whitespace character next token; start new one */ + tokens->ntok = tokens->ntok + 1; + if (tokens->ntok > maxtokens) return (maxtokens); + tokens->tok1[tokens->ntok] = stri; + tokens->ltok[tokens->ntok] = 1; + stri++; + str0 = stri; + } + + /* Pass previous token if regular whitespace or NULL */ + else if (wtype != NULL || jch == (char) 0) { + + /* Ignore leading whitespace */ + if (stri == str0) { + stri++; + str0 = stri; + } + + /* terminate token before whitespace; start new one */ + else { + tokens->ntok = tokens->ntok + 1; + if (tokens->ntok > maxtokens) return (maxtokens); + tokens->tok1[tokens->ntok] = str0; + tokens->ltok[tokens->ntok] = stri - str0; + stri++; + str0 = stri; + } + } + + /* Keep going if not whitespace */ + else + stri++; + } + + /* Add token terminated by end of line */ + if (str0 < stri) { + tokens->ntok = tokens->ntok + 1; + if (tokens->ntok > maxtokens) + return (maxtokens); + tokens->tok1[tokens->ntok] = str0; + ltok = stri - str0 + 1; + tokens->ltok[tokens->ntok] = ltok; + + /* Deal with white space just before end of line */ + jch = str0[ltok-1]; + if (strchr (tokens->white, jch)) { + ltok = ltok - 1; + tokens->ltok[tokens->ntok] = ltok; + tokens->ntok = tokens->ntok + 1; + tokens->tok1[tokens->ntok] = str0 + ltok; + tokens->ltok[tokens->ntok] = 0; + } + } + + tokens->itok = 0; + + return (tokens->ntok); +} + + +/* NEXTOKEN -- get next token from tokenized string */ + +int +nextoken (tokens, token, maxchars) + +struct Tokens *tokens; /* Token structure returned */ +char *token; /* token (returned) */ +int maxchars; /* Maximum length of token */ +{ + int ltok; /* length of token string (returned) */ + int it, i; + int maxc = maxchars - 1; + + tokens->itok = tokens->itok + 1; + it = tokens->itok; + if (it > tokens->ntok) + it = tokens->ntok; + else if (it < 1) + it = 1; + ltok = tokens->ltok[it]; + if (ltok > maxc) + ltok = maxc; + strncpy (token, tokens->tok1[it], ltok); + for (i = ltok; i < maxc; i++) + token[i] = (char) 0; + return (ltok); +} + + +/* GETOKEN -- get specified token from tokenized string */ + +int +getoken (tokens, itok, token, maxchars) + +struct Tokens *tokens; /* Token structure returned */ +int itok; /* token sequence number of token + * if <0, get whole string after token -itok + * if =0, get whole string */ +char *token; /* token (returned) */ +int maxchars; /* Maximum length of token */ +{ + int ltok; /* length of token string (returned) */ + int it, i; + int maxc = maxchars - 1; + + it = itok; + if (it > 0 ) { + if (it > tokens->ntok) + it = tokens->ntok; + ltok = tokens->ltok[it]; + if (ltok > maxc) + ltok = maxc; + strncpy (token, tokens->tok1[it], ltok); + } + else if (it < 0) { + if (it < -tokens->ntok) + it = -tokens->ntok; + ltok = tokens->line + tokens->lline - tokens->tok1[-it]; + if (ltok > maxc) + ltok = maxc; + strncpy (token, tokens->tok1[-it], ltok); + } + else { + ltok = tokens->lline; + if (ltok > maxc) + ltok = maxc; + strncpy (token, tokens->tok1[1], ltok); + } + for (i = ltok; i < maxc; i++) + token[i] = (char) 0; + + return (ltok); +} + +/* + * Jul 14 1999 New subroutines + * Jul 15 1999 Add getfilebuff() + * Oct 15 1999 Fix format eror in error message + * Oct 21 1999 Fix declarations after lint + * Dec 9 1999 Add next_token(); set pointer to next token in first_token + * + * Sep 25 2001 Add isfilelist(); move isfile() from catutil.c + * + * Jan 4 2002 Allow getfilebuffer() to read from stdin + * Jan 8 2002 Add sts2c() and stc2s() for space-replaced strings + * Mar 22 2002 Clean up isfilelist() + * Aug 1 2002 Return 1 if file is stdin in isfile() + * + * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern) + * Mar 5 2003 Add isimlistd() to check image lists with root directory + * May 27 2003 Use file stat call in getfilesize() instead of opening file + * Jul 17 2003 Add root directory argument to isfilelist() + * + * Sep 29 2004 Drop next_token() to avoid conflict with subroutine in catutil.c + * + * Sep 26 2005 In first_token, return NULL if token is only control character + * + * Feb 23 2006 Add istiff(), isjpeg(), isgif() to check TIFF, JPEG, GIF files + * Jun 20 2006 Cast call to fgets() void + * + * Jan 5 2007 Change stc2s() and sts2c() to pass single character as pointer + * Jan 11 2007 Move token access subroutines from catutil.c + */ diff --git a/astroem/fitsfile.c b/astroem/fitsfile.c new file mode 100644 index 00000000..0ff9479e --- /dev/null +++ b/astroem/fitsfile.c @@ -0,0 +1,2308 @@ +/*** File libwcs/fitsfile.c + *** September 15, 2011 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1996-2011 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + + * Module: fitsfile.c (FITS file reading and writing) + * Purpose: Read and write FITS image and table files + * fitsropen (inpath) + * Open a FITS file for reading, returning a FILE pointer + * fitsrhead (filename, lhead, nbhead) + * Read FITS header and return it + * fitsrtail (filename, lhead, nbhead) + * Read appended FITS header and return it + * fitsrsect (filename, nbhead, header, fd, x0, y0, nx, ny) + * Read section of a FITS image, having already read the header + * fitsrimage (filename, nbhead, header) + * Read FITS image, having already ready the header + * fitsrfull (filename, nbhead, header) + * Read a FITS image of any dimension + * fitsrtopen (inpath, nk, kw, nrows, nchar, nbhead) + * Open a FITS table file for reading; return header information + * fitsrthead (header, nk, kw, nrows, nchar, nbhead) + * Extract FITS table information from a FITS header + * fitsrtline (fd, nbhead, lbuff, tbuff, irow, nbline, line) + * Read next line of FITS table file + * ftgetr8 (entry, kw) + * Extract column from FITS table line as double + * ftgetr4 (entry, kw) + * Extract column from FITS table line as float + * ftgeti4 (entry, kw) + * Extract column from FITS table line as int + * ftgeti2 (entry, kw) + * Extract column from FITS table line as short + * ftgetc (entry, kw, string, maxchar) + * Extract column from FITS table line as a character string + * fitswimage (filename, header, image) + * Write FITS header and image + * fitswext (filename, header, image) + * Write FITS header and image as extension to existing FITS file + * fitswhdu (fd, filename, header, image) + * Write FITS header and image as extension to file descriptor + * fitscimage (filename, header, filename0) + * Write FITS header and copy FITS image + * fitswhead (filename, header) + * Write FITS header and keep file open for further writing + * fitswexhead (filename, header) + * Write FITS header only to FITS extension without writing data + * isfits (filename) + * Return 1 if file is a FITS file, else 0 + * fitsheadsize (header) + * Return size of FITS header in bytes + */ + +#include +#ifndef VMS +#include +#endif +#include +#include +#include +#include +#include +#include "fitsfile.h" + +static int verbose=0; /* Print diagnostics */ +static char fitserrmsg[80]; +static int fitsinherit = 1; /* Append primary header to extension header */ +void +setfitsinherit (inh) +int inh; +{fitsinherit = inh; return;} + +static off_t ibhead = 0; /* Number of bytes read before header starts */ + +off_t +getfitsskip() +{return (ibhead);} + +/* FITSRHEAD -- Read a FITS header */ + +char * +fitsrhead (filename, lhead, nbhead) + +char *filename; /* Name of FITS image file */ +int *lhead; /* Allocated length of FITS header in bytes (returned) */ +int *nbhead; /* Number of bytes before start of data (returned) */ + /* This includes all skipped image extensions */ + +{ + int fd; + char *header; /* FITS image header (filled) */ + int extend; + int nbytes,naxis, i; + int ntry,nbr,irec,nrec, nbh, ipos, npos, nbprim, lprim, lext; + int nax1, nax2, nax3, nax4, nbpix, ibpix, nblock, nbskip; + char fitsbuf[2884]; + char *headend; /* Pointer to last line of header */ + char *headnext; /* Pointer to next line of header to be added */ + int hdu; /* header/data unit counter */ + int extnum; /* desired header data number + (0=primary -1=first with data -2=use EXTNAME) */ + char extname[32]; /* FITS extension name */ + char extnam[32]; /* Desired FITS extension name */ + char *ext; /* FITS extension name or number in header, if any */ + char *pheader; /* Primary header (naxis is 0) */ + char cext = 0; + char *rbrac; /* Pointer to right bracket if present in file name */ + char *mwcs; /* Pointer to WCS name separated by % */ + char *newhead; /* New larger header */ + int nbh0; /* Length of old too small header */ + char *pheadend; + int inherit = 1; /* Value of INHERIT keyword in FITS extension header */ + int extfound = 0; /* Set to one if desired FITS extension is found */ + int npcount; + + pheader = NULL; + lprim = 0; + header = NULL; + + /* Check for FITS WCS specification and ignore for file opening */ + mwcs = strchr (filename, '%'); + if (mwcs != NULL) + *mwcs = (char) 0; + + /* Check for FITS extension and ignore for file opening */ + rbrac = NULL; + ext = strchr (filename, ','); + if (ext == NULL) { + ext = strchr (filename, '['); + if (ext != NULL) { + rbrac = strchr (filename, ']'); + if (rbrac != NULL) + *rbrac = (char) 0; + } + } + if (ext != NULL) { + cext = *ext; + *ext = (char) 0; + } + + /* Open the image file and read the header */ + if (strncasecmp (filename,"stdin",5)) { + fd = -1; + fd = fitsropen (filename); + } +#ifndef VMS + else { + fd = STDIN_FILENO; + extnum = -1; + } +#endif + + if (ext != NULL) { + if (isnum (ext+1)) + extnum = atoi (ext+1); + else { + extnum = -2; + strcpy (extnam, ext+1); + } + } + else + extnum = -1; + + /* Repair the damage done to the file-name string during parsing */ + if (ext != NULL) + *ext = cext; + if (rbrac != NULL) + *rbrac = ']'; + if (mwcs != NULL) + *mwcs = '%'; + + if (fd < 0) { + fprintf (stderr,"FITSRHEAD: cannot read file %s\n", filename); + return (NULL); + } + + nbytes = FITSBLOCK; + *nbhead = 0; + headend = NULL; + nbh = FITSBLOCK * 20 + 4; + header = (char *) calloc ((unsigned int) nbh, 1); + (void) hlength (header, nbh); + headnext = header; + nrec = 1; + hdu = 0; + ibhead = 0; + + /* Read FITS header from input file one FITS block at a time */ + irec = 0; + ibhead = 0; + while (irec < 200) { + nbytes = FITSBLOCK; + for (ntry = 0; ntry < 10; ntry++) { + for (i = 0; i < 2884; i++) fitsbuf[i] = 0; + nbr = read (fd, fitsbuf, nbytes); + + /* Short records allowed only if they have the last header line */ + if (nbr < nbytes) { + headend = ksearch (fitsbuf,"END"); + if (headend == NULL) { + if (ntry < 9) { + if (verbose) + fprintf (stderr,"FITSRHEAD: %d / %d bytes read %d\n", + nbr,nbytes,ntry); + } + else { + snprintf(fitserrmsg,79,"FITSRHEAD: '%d / %d bytes of header read from %s\n" + ,nbr,nbytes,filename); +#ifndef VMS + if (fd != STDIN_FILENO) +#endif + (void)close (fd); + free (header); + /* if (pheader != NULL) + return (pheader); */ + if (extnum != -1 && !extfound) { + *ext = (char) 0; + if (extnum < 0) { + snprintf (fitserrmsg,79, + "FITSRHEAD: Extension %s not found in file %s", + extnam, filename); + } + else { + snprintf (fitserrmsg,79, + "FITSRHEAD: Extension %d not found in file %s", + extnum, filename); + } + *ext = cext; + } + else if (hdu > 0) { + snprintf (fitserrmsg,79, + "FITSRHEAD: No extensions found in file %s", filename); + hdu = 0; + if (pheader != NULL) { + *lhead = nbprim; + *nbhead = nbprim; + return (pheader); + } + break; + } + else { + snprintf (fitserrmsg,79, + "FITSRHEAD: No header found in file %s", filename); + } + return (NULL); + } + } + else + break; + } + else + break; + } + + /* Move current FITS record into header string */ + for (i = 0; i < 2880; i++) + if (fitsbuf[i] < 32 || i > nbr) fitsbuf[i] = 32; + if (nbr < 2880) + nbr = 2880; + strncpy (headnext, fitsbuf, nbr); + *nbhead = *nbhead + nbr; + nrec = nrec + 1; + *(headnext+nbr) = 0; + ibhead = ibhead + 2880; + + /* Check to see if this is the final record in this header */ + headend = ksearch (fitsbuf,"END"); + if (headend == NULL) { + + /* Increase size of header buffer by 4 blocks if too small */ + if (nrec * FITSBLOCK > nbh) { + nbh0 = nbh; + nbh = (nrec + 4) * FITSBLOCK + 4; + newhead = (char *) calloc (1,(unsigned int) nbh); + for (i = 0; i < nbh0; i++) + newhead[i] = header[i]; + free (header); + header = newhead; + (void) hlength (header, nbh); + headnext = header + *nbhead - FITSBLOCK; + } + headnext = headnext + FITSBLOCK; + } + + else { + naxis = 0; + hgeti4 (header,"NAXIS",&naxis); + + /* If header has no data, save it for appending to desired header */ + if (naxis < 1) { + nbprim = nrec * FITSBLOCK; + headend = ksearch (header,"END"); + lprim = headend + 80 - header; + pheader = (char *) calloc ((unsigned int) nbprim, 1); + for (i = 0; i < lprim; i++) + pheader[i] = header[i]; + strncpy (pheader, header, lprim); + } + + /* If header has no data, start with the next record */ + if (naxis < 1 && extnum == -1) { + extend = 0; + hgetl (header,"EXTEND",&extend); + if (naxis == 0 && extend) { + headnext = header; + *headend = ' '; + headend = NULL; + nrec = 1; + hdu = hdu + 1; + } + else { + break; + } + } + + /* If this is the desired header data unit, keep it */ + else if (extnum != -1) { + if (extnum > -1 && hdu == extnum) { + extfound = 1; + break; + } + else if (extnum < 0) { + extname[0] = 0; + hgets (header, "EXTNAME", 32, extname); + if (!strcmp (extnam,extname)) { + extfound = 1; + break; + } + } + + /* If this is not desired header data unit, skip over data */ + hdu = hdu + 1; + nblock = 0; + ibhead = 0; + if (naxis > 0) { + ibpix = 0; + hgeti4 (header,"BITPIX",&ibpix); + if (ibpix < 0) { + nbpix = -ibpix / 8; + } + else { + nbpix = ibpix / 8; + } + nax1 = 1; + hgeti4 (header,"NAXIS1",&nax1); + nax2 = 1; + if (naxis > 1) { + hgeti4 (header,"NAXIS2",&nax2); + } + nax3 = 1; + if (naxis > 2) { + hgeti4 (header,"NAXIS3",&nax3); + } + nax4 = 1; + if (naxis > 3) { + hgeti4 (header,"NAXIS4",&nax4); + } + nbskip = nax1 * nax2 * nax3 * nax4 * nbpix; + nblock = nbskip / 2880; + if (nblock*2880 < nbskip) { + nblock = nblock + 1; + } + npcount = 0; + hgeti4 (header,"PCOUNT", &npcount); + if (npcount > 0) { + nbskip = nbskip + npcount; + nblock = nbskip / 2880; + if (nblock*2880 < nbskip) + nblock = nblock + 1; + } + } + else { + nblock = 0; + } + *nbhead = *nbhead + (nblock * 2880); + + /* Set file pointer to beginning of next header/data unit */ + if (nblock > 0) { +#ifndef VMS + if (fd != STDIN_FILENO) { + ipos = lseek (fd, *nbhead, SEEK_SET); + npos = *nbhead; + } + else { +#else + { +#endif + ipos = 0; + for (i = 0; i < nblock; i++) { + nbytes = FITSBLOCK; + nbr = read (fd, fitsbuf, nbytes); + if (nbr < nbytes) { + ipos = ipos + nbr; + break; + } + else { + ipos = ipos + nbytes; + } + } + npos = nblock * 2880; + } + if (ipos < npos) { + snprintf (fitserrmsg,79,"FITSRHEAD: %d / %d bytes skipped\n", + ipos,npos); + extfound = 0; + break; + } + } + headnext = header; + headend = NULL; + nrec = 1; + } + else { + break; + } + } + } + +#ifndef VMS + if (fd != STDIN_FILENO) + (void)close (fd); +#endif + +/* Print error message and return null if extension not found */ + if (extnum != -1 && !extfound) { + if (extnum < 0) + fprintf (stderr, "FITSRHEAD: Extension %s not found in file %s\n",extnam, filename); + else + fprintf (stderr, "FITSRHEAD: Extension %d not found in file %s\n",extnum, filename); + if (pheader != NULL) { + free (pheader); + pheader = NULL; + } + return (NULL); + } + + /* Allocate an extra block for good measure */ + *lhead = (nrec + 1) * FITSBLOCK; + if (*lhead > nbh) { + newhead = (char *) calloc (1,(unsigned int) *lhead); + for (i = 0; i < nbh; i++) + newhead[i] = header[i]; + free (header); + header = newhead; + (void) hlength (header, *lhead); + } + else + *lhead = nbh; + + /* If INHERIT keyword is FALSE, never append primary header */ + if (hgetl (header, "INHERIT", &inherit)) { + if (!inherit && fitsinherit) + fitsinherit = 0; + } + + /* Append primary data header to extension header */ + if (pheader != NULL && extnum != 0 && fitsinherit && hdu > 0) { + extname[0] = 0; + hgets (header, "XTENSION", 32, extname); + if (!strcmp (extname,"IMAGE")) { + strncpy (header, "SIMPLE ", 8); + hputl (header, "SIMPLE", 1); + } + headend = blsearch (header,"END"); + if (headend == NULL) + headend = ksearch (header, "END"); + lext = headend - header; + + /* Update primary header for inclusion at end of extension header */ + hchange (pheader, "SIMPLE", "ROOTHEAD"); + hchange (pheader, "NEXTEND", "NUMEXT"); + hdel (pheader, "BITPIX"); + hdel (pheader, "NAXIS"); + hdel (pheader, "EXTEND"); + hputl (pheader, "ROOTEND",1); + pheadend = ksearch (pheader,"END"); + lprim = pheadend + 320 - pheader; + if (lext + lprim > nbh) { + nrec = (lext + lprim) / FITSBLOCK; + if (FITSBLOCK*nrec < lext+lprim) + nrec = nrec + 1; + *lhead = (nrec+1) * FITSBLOCK; + newhead = (char *) calloc (1,(unsigned int) *lhead); + for (i = 0; i < nbh; i++) + newhead[i] = header[i]; + free (header); + header = newhead; + headend = header + lext; + (void) hlength (header, *lhead); + } + hputs (header,"COMMENT","-------------------------------------------"); + hputs (header,"COMMENT","Information from Primary Header"); + hputs (header,"COMMENT","-------------------------------------------"); + headend = blsearch (header,"END"); + if (headend == NULL) + headend = ksearch (header, "END"); + pheader[lprim] = 0; + strncpy (headend, pheader, lprim); + if (pheader != NULL) { + free (pheader); + pheader = NULL; + } + } + + ibhead = *nbhead - ibhead; + + return (header); +} + + +/* FITSRTAIL -- Read FITS header appended to graphics file */ + +char * +fitsrtail (filename, lhead, nbhead) + +char *filename; /* Name of image file */ +int *lhead; /* Allocated length of FITS header in bytes (returned) */ +int *nbhead; /* Number of bytes before start of data (returned) */ + /* This includes all skipped image extensions */ + +{ + int fd; + char *header; /* FITS image header (filled) */ + int nbytes, i, ndiff; + int nbr, irec; + off_t offset; + char *mwcs; /* Pointer to WCS name separated by % */ + char *headstart; + char *newhead; + + header = NULL; + + /* Check for FITS WCS specification and ignore for file opening */ + mwcs = strchr (filename, '%'); + if (mwcs != NULL) + *mwcs = (char) 0; + + /* Open the image file and read the header */ + if (strncasecmp (filename,"stdin",5)) { + fd = -1; + fd = fitsropen (filename); + } +#ifndef VMS + else { + fd = STDIN_FILENO; + } +#endif + + /* Repair the damage done to the file-name string during parsing */ + if (mwcs != NULL) + *mwcs = '%'; + + if (fd < 0) { + fprintf (stderr,"FITSRTAIL: cannot read file %s\n", filename); + return (NULL); + } + + nbytes = FITSBLOCK; + *nbhead = 0; + *lhead = 0; + + /* Read FITS header from end of input file one FITS block at a time */ + irec = 0; + while (irec < 100) { + nbytes = FITSBLOCK * (irec + 2); + header = (char *) calloc ((unsigned int) nbytes, 1); + offset = lseek (fd, -nbytes, SEEK_END); + if (offset < 0) { + free (header); + header = NULL; + nbytes = 0; + break; + } + for (i = 0; i < nbytes; i++) header[i] = 0; + nbr = read (fd, header, nbytes); + + /* Check for SIMPLE at start of header */ + for (i = 0; i < nbr; i++) + if (header[i] < 32) header[i] = 32; + if ((headstart = ksearch (header,"SIMPLE"))) { + if (headstart != header) { + ndiff = headstart - header; + newhead = (char *) calloc ((unsigned int) nbytes, 1); + for (i = 0; i < nbytes-ndiff; i++) + newhead[i] = headstart[i]; + free (header); + header = newhead; + } + *lhead = nbytes; + *nbhead = nbytes; + break; + } + free (header); + } + (void) hlength (header, nbytes); + +#ifndef VMS + if (fd != STDIN_FILENO) + (void)close (fd); +#endif + + return (header); +} + + +/* FITSRSECT -- Read a piece of a FITS image, having already read the header */ + +char * +fitsrsect (filename, header, nbhead, x0, y0, nx, ny, nlog) + +char *filename; /* Name of FITS image file */ +char *header; /* FITS header for image (previously read) */ +int nbhead; /* Actual length of image header(s) in bytes */ +int x0, y0; /* FITS image coordinate of first pixel */ +int nx; /* Number of columns to read (less than NAXIS1) */ +int ny; /* Number of rows to read (less than NAXIS2) */ +int nlog; /* Note progress mod this rows */ +{ + int fd; /* File descriptor */ + int nbimage, naxis1, naxis2, bytepix, nbread; + int bitpix, naxis, nblocks, nbytes, nbr; + int x1, y1, nbline, nyleft; + off_t impos, nblin; + char *image, *imline, *imlast; + int ilog = 0; + int row; + + /* Open the image file and read the header */ + if (strncasecmp (filename,"stdin", 5)) { + fd = -1; + + fd = fitsropen (filename); + if (fd < 0) { + snprintf (fitserrmsg,79, "FITSRSECT: cannot read file %s\n", filename); + return (NULL); + } + + /* Skip over FITS header and whatever else needs to be skipped */ + if (lseek (fd, nbhead, SEEK_SET) < 0) { + (void)close (fd); + snprintf (fitserrmsg,79, "FITSRSECT: cannot skip header of file %s\n", + filename); + return (NULL); + } + } +#ifndef VMS + else + fd = STDIN_FILENO; +#endif + + /* Compute size of image in bytes using relevant header parameters */ + naxis = 1; + hgeti4 (header,"NAXIS",&naxis); + naxis1 = 1; + hgeti4 (header,"NAXIS1",&naxis1); + naxis2 = 1; + hgeti4 (header,"NAXIS2",&naxis2); + bitpix = 0; + hgeti4 (header,"BITPIX",&bitpix); + if (bitpix == 0) { + /* snprintf (fitserrmsg,79, "FITSRSECT: BITPIX is 0; image not read\n"); */ + (void)close (fd); + return (NULL); + } + bytepix = bitpix / 8; + if (bytepix < 0) bytepix = -bytepix; + + /* Keep X coordinates within image limits */ + if (x0 < 1) + x0 = 1; + else if (x0 > naxis1) + x0 = naxis1; + x1 = x0 + nx - 1; + if (x1 < 1) + x1 = 1; + else if (x1 > naxis1) + x1 = naxis1; + nx = x1 - x0 + 1; + + /* Keep Y coordinates within image limits */ + if (y0 < 1) + y0 = 1; + else if (y0 > naxis2) + y0 = naxis2; + y1 = y0 + ny - 1; + if (y1 < 1) + y1 = 1; + else if (y1 > naxis2) + y1 = naxis2; + ny = y1 - y0 + 1; + + /* Number of bytes in output image */ + nbline = nx * bytepix; + nbimage = nbline * ny; + + /* Set number of bytes to integral number of 2880-byte blocks */ + nblocks = nbimage / FITSBLOCK; + if (nblocks * FITSBLOCK < nbimage) + nblocks = nblocks + 1; + nbytes = nblocks * FITSBLOCK; + + /* Allocate image section to be read */ + image = (char *) malloc (nbytes); + nyleft = ny; + imline = image; + nbr = 0; + + /* Computer pointer to first byte of input image to read */ + nblin = naxis1 * bytepix; + impos = ((y0 - 1) * nblin) + ((x0 - 1) * bytepix); + row = y0 - 1; + + /* Read image section one line at a time */ + while (nyleft-- > 0) { + if (lseek (fd, impos, SEEK_CUR) >= 0) { + nbread = read (fd, imline, nbline); + nbr = nbr + nbread; + impos = nblin - nbread; + imline = imline + nbline; + row++; + if (++ilog == nlog) { + ilog = 0; + fprintf (stderr, "Row %5d extracted ", row); + (void) putc (13,stderr); + } + } + } + if (nlog) + fprintf (stderr, "\n"); + + /* Fill rest of image with zeroes */ + imline = image + nbimage; + imlast = image + nbytes; + while (imline++ < imlast) + *imline = (char) 0; + + /* Byte-reverse image, if necessary */ + if (imswapped ()) + imswap (bitpix, image, nbytes); + + return (image); +} + + +/* FITSRIMAGE -- Read a FITS image */ + +char * +fitsrimage (filename, nbhead, header) + +char *filename; /* Name of FITS image file */ +int nbhead; /* Actual length of image header(s) in bytes */ +char *header; /* FITS header for image (previously read) */ +{ + int fd; + int nbimage, naxis1, naxis2, bytepix, nbread; + int bitpix, naxis, nblocks, nbytes, nbleft, nbr; + int simple; + char *image, *imleft; + + /* Open the image file and read the header */ + if (strncasecmp (filename,"stdin", 5)) { + fd = -1; + + fd = fitsropen (filename); + if (fd < 0) { + snprintf (fitserrmsg,79, "FITSRIMAGE: cannot read file %s\n", filename); + return (NULL); + } + + /* Skip over FITS header and whatever else needs to be skipped */ + if (lseek (fd, nbhead, SEEK_SET) < 0) { + (void)close (fd); + snprintf (fitserrmsg,79, "FITSRIMAGE: cannot skip header of file %s\n", + filename); + return (NULL); + } + } +#ifndef VMS + else + fd = STDIN_FILENO; +#endif + + /* If SIMPLE=F in header, simply put post-header part of file in buffer */ + hgetl (header, "SIMPLE", &simple); + if (!simple) { + nbytes = getfilesize (filename) - nbhead; + if ((image = (char *) malloc (nbytes + 1)) == NULL) { + /* snprintf (fitserrmsg,79, "FITSRIMAGE: %d-byte image buffer cannot be allocated\n"); */ + (void)close (fd); + return (NULL); + } + hputi4 (header, "NBDATA", nbytes); + nbread = read (fd, image, nbytes); + return (image); + } + + /* Compute size of image in bytes using relevant header parameters */ + naxis = 1; + hgeti4 (header,"NAXIS",&naxis); + naxis1 = 1; + hgeti4 (header,"NAXIS1",&naxis1); + naxis2 = 1; + hgeti4 (header,"NAXIS2",&naxis2); + bitpix = 0; + hgeti4 (header,"BITPIX",&bitpix); + if (bitpix == 0) { + /* snprintf (fitserrmsg,79, "FITSRIMAGE: BITPIX is 0; image not read\n"); */ + (void)close (fd); + return (NULL); + } + bytepix = bitpix / 8; + if (bytepix < 0) bytepix = -bytepix; + + /* If either dimension is one and image is 3-D, read all three dimensions */ + if (naxis == 3 && (naxis1 ==1 || naxis2 == 1)) { + int naxis3; + hgeti4 (header,"NAXIS3",&naxis3); + nbimage = naxis1 * naxis2 * naxis3 * bytepix; + } + else + nbimage = naxis1 * naxis2 * bytepix; + + /* Set number of bytes to integral number of 2880-byte blocks */ + nblocks = nbimage / FITSBLOCK; + if (nblocks * FITSBLOCK < nbimage) + nblocks = nblocks + 1; + nbytes = nblocks * FITSBLOCK; + + /* Allocate and read image */ + image = (char *) malloc (nbytes); + nbleft = nbytes; + imleft = image; + nbr = 0; + while (nbleft > 0) { + nbread = read (fd, imleft, nbleft); + nbr = nbr + nbread; +#ifndef VMS + if (fd == STDIN_FILENO && nbread < nbleft && nbread > 0) { + nbleft = nbleft - nbread; + imleft = imleft + nbread; + } + else +#endif + nbleft = 0; + } +#ifndef VMS + if (fd != STDIN_FILENO) + (void)close (fd); +#endif + if (nbr < nbimage) { + snprintf (fitserrmsg,79, "FITSRIMAGE: %d of %d bytes read from file %s\n", + nbr, nbimage, filename); + return (NULL); + } + + /* Byte-reverse image, if necessary */ + if (imswapped ()) + imswap (bitpix, image, nbytes); + + return (image); +} + + +/* FITSRFULL -- Read a FITS image of any dimension */ + +char * +fitsrfull (filename, nbhead, header) + +char *filename; /* Name of FITS image file */ +int nbhead; /* Actual length of image header(s) in bytes */ +char *header; /* FITS header for image (previously read) */ +{ + int fd; + int nbimage, naxisi, iaxis, bytepix, nbread; + int bitpix, naxis, nblocks, nbytes, nbleft, nbr, simple; + char keyword[16]; + char *image, *imleft; + + /* Open the image file and read the header */ + if (strncasecmp (filename,"stdin", 5)) { + fd = -1; + + fd = fitsropen (filename); + if (fd < 0) { + snprintf (fitserrmsg,79, "FITSRFULL: cannot read file %s\n", filename); + return (NULL); + } + + /* Skip over FITS header and whatever else needs to be skipped */ + if (lseek (fd, nbhead, SEEK_SET) < 0) { + (void)close (fd); + snprintf (fitserrmsg,79, "FITSRFULL: cannot skip header of file %s\n", + filename); + return (NULL); + } + } +#ifndef VMS + else + fd = STDIN_FILENO; +#endif + + /* If SIMPLE=F in header, simply put post-header part of file in buffer */ + hgetl (header, "SIMPLE", &simple); + if (!simple) { + nbytes = getfilesize (filename) - nbhead; + if ((image = (char *) malloc (nbytes + 1)) == NULL) { + snprintf (fitserrmsg,79, "FITSRFULL: %d-byte image buffer cannot be allocated\n",nbytes+1); + (void)close (fd); + return (NULL); + } + hputi4 (header, "NBDATA", nbytes); + nbread = read (fd, image, nbytes); + return (image); + } + + /* Find number of bytes per pixel */ + bitpix = 0; + hgeti4 (header,"BITPIX",&bitpix); + if (bitpix == 0) { + snprintf (fitserrmsg,79, "FITSRFULL: BITPIX is 0; image not read\n"); + (void)close (fd); + return (NULL); + } + bytepix = bitpix / 8; + if (bytepix < 0) bytepix = -bytepix; + nbimage = bytepix; + + /* Compute size of image in bytes using relevant header parameters */ + naxis = 1; + hgeti4 (header,"NAXIS",&naxis); + for (iaxis = 1; iaxis <= naxis; iaxis++) { + sprintf (keyword, "NAXIS%d", iaxis); + naxisi = 1; + hgeti4 (header,keyword,&naxisi); + nbimage = nbimage * naxisi; + } + + /* Set number of bytes to integral number of 2880-byte blocks */ + nblocks = nbimage / FITSBLOCK; + if (nblocks * FITSBLOCK < nbimage) + nblocks = nblocks + 1; + nbytes = nblocks * FITSBLOCK; + + /* Allocate and read image */ + image = (char *) malloc (nbytes); + nbleft = nbytes; + imleft = image; + nbr = 0; + while (nbleft > 0) { + nbread = read (fd, imleft, nbleft); + nbr = nbr + nbread; +#ifndef VMS + if (fd == STDIN_FILENO && nbread < nbleft && nbread > 0) { + nbleft = nbleft - nbread; + imleft = imleft + nbread; + } + else +#endif + nbleft = 0; + } +#ifndef VMS + if (fd != STDIN_FILENO) + (void)close (fd); +#endif + if (nbr < nbimage) { + snprintf (fitserrmsg,79, "FITSRFULL: %d of %d image bytes read from file %s\n", + nbr, nbimage, filename); + return (NULL); + } + + /* Byte-reverse image, if necessary */ + if (imswapped ()) + imswap (bitpix, image, nbytes); + + return (image); +} + + +/* FITSROPEN -- Open a FITS file, returning the file descriptor */ + +int +fitsropen (inpath) + +char *inpath; /* Pathname for FITS tables file to read */ + +{ + int ntry; + int fd; /* file descriptor for FITS tables file (returned) */ + char *ext; /* extension name or number */ + char cext = 0; + char *rbrac; + char *mwcs; /* Pointer to WCS name separated by % */ + +/* Check for FITS WCS specification and ignore for file opening */ + mwcs = strchr (inpath, '%'); + +/* Check for FITS extension and ignore for file opening */ + ext = strchr (inpath, ','); + rbrac = NULL; + if (ext == NULL) { + ext = strchr (inpath, '['); + if (ext != NULL) { + rbrac = strchr (inpath, ']'); + } + } + +/* Open input file */ + for (ntry = 0; ntry < 3; ntry++) { + if (ext != NULL) { + cext = *ext; + *ext = 0; + } + if (rbrac != NULL) + *rbrac = (char) 0; + if (mwcs != NULL) + *mwcs = (char) 0; + fd = open (inpath, O_RDONLY); + if (ext != NULL) + *ext = cext; + if (rbrac != NULL) + *rbrac = ']'; + if (mwcs != NULL) + *mwcs = '%'; + if (fd >= 0) + break; + else if (ntry == 2) { + snprintf (fitserrmsg,79, "FITSROPEN: cannot read file %s\n", inpath); + return (-1); + } + } + + if (verbose) + fprintf (stderr,"FITSROPEN: input file %s opened\n",inpath); + + return (fd); +} + + +static int offset1=0; +static int offset2=0; + +/* FITSRTOPEN -- Open FITS table file and fill structure with + * pointers to selected keywords + * Return file descriptor (-1 if unsuccessful) + */ + +int +fitsrtopen (inpath, nk, kw, nrows, nchar, nbhead) + +char *inpath; /* Pathname for FITS tables file to read */ +int *nk; /* Number of keywords to use */ +struct Keyword **kw; /* Structure for desired entries */ +int *nrows; /* Number of rows in table (returned) */ +int *nchar; /* Number of characters in one table row (returned) */ +int *nbhead; /* Number of characters before table starts */ + +{ + char temp[16]; + int fd; + int lhead; /* Maximum length in bytes of FITS header */ + char *header; /* Header for FITS tables file to read */ + +/* Read FITS header from input file */ + header = fitsrhead (inpath, &lhead, nbhead); + if (!header) { + snprintf (fitserrmsg,79,"FITSRTOPEN: %s is not a FITS file\n",inpath); + return (0); + } + +/* Make sure this file is really a FITS table file */ + temp[0] = 0; + (void) hgets (header,"XTENSION",16,temp); + if (strlen (temp) == 0) { + snprintf (fitserrmsg,79, + "FITSRTOPEN: %s is not a FITS table file\n",inpath); + free ((void *) header); + return (0); + } + +/* If it is a FITS file, get table information from the header */ + else if (!strcmp (temp, "TABLE") || !strcmp (temp, "BINTABLE")) { + if (fitsrthead (header, nk, kw, nrows, nchar)) { + snprintf (fitserrmsg,79, + "FITSRTOPEN: Cannot read FITS table from %s\n",inpath); + free ((void *) header); + return (-1); + } + else { + fd = fitsropen (inpath); + offset1 = 0; + offset2 = 0; + free ((void *) header); + return (fd); + } + } + +/* If it is another FITS extension note it and return */ + else { + snprintf (fitserrmsg,79, + "FITSRTOPEN: %s is a %s extension, not table\n", + inpath, temp); + free ((void *) header); + return (0); + } +} + +static struct Keyword *pw; /* Structure for all entries */ +static int *lpnam; /* length of name for each field */ +static int bfields = 0; + +/* FITSRTHEAD -- From FITS table header, read pointers to selected keywords */ + +int +fitsrthead (header, nk, kw, nrows, nchar) + +char *header; /* Header for FITS tables file to read */ +int *nk; /* Number of keywords to use */ +struct Keyword **kw; /* Structure for desired entries */ +int *nrows; /* Number of rows in table (returned) */ +int *nchar; /* Number of characters in one table row (returned) */ + +{ + struct Keyword *rw; /* Structure for desired entries */ + int nfields; + int ifield, ik, i, ikf, ltform, kl; + char *h0, *h1, *tf1, *tf2; + char tname[12]; + char temp[16]; + char tform[16]; + int tverb; + int bintable = 0; + + h0 = header; + +/* Make sure this is really a FITS table file header */ + temp[0] = 0; + hgets (header,"XTENSION",16,temp); + if (strlen (temp) == 0) { + snprintf (fitserrmsg,79, "FITSRTHEAD: Not a FITS table header\n"); + return (-1); + } + else if (!strcmp (temp, "BINTABLE")) { + bintable = 1; + } + else if (strcmp (temp, "TABLE")) { + snprintf (fitserrmsg,79, "FITSRTHEAD: %s extension, not TABLE\n",temp); + return (-1); + } + +/* Get table size from FITS header */ + *nchar = 0; + hgeti4 (header,"NAXIS1",nchar); + *nrows = 0; + hgeti4 (header,"NAXIS2", nrows); + if (*nrows <= 0 || *nchar <= 0) { + snprintf (fitserrmsg,79, "FITSRTHEAD: cannot read %d x %d table\n", + *nrows,*nchar); + return (-1); + } + +/* Set up table for access to individual fields */ + nfields = 0; + hgeti4 (header,"TFIELDS",&nfields); + if (verbose) + fprintf (stderr, "FITSRTHEAD: %d fields per table entry\n", nfields); + if (nfields > bfields) { + if (bfields > 0) + free ((void *)pw); + pw = (struct Keyword *) calloc (nfields, sizeof(struct Keyword)); + if (pw == NULL) { + snprintf (fitserrmsg,79,"FITSRTHEAD: cannot allocate table structure\n"); + return (-1); + } + if (bfields > 0) + free ((void *)lpnam); + lpnam = (int *) calloc (nfields, sizeof(int)); + if (lpnam == NULL) { + snprintf (fitserrmsg,79,"FITSRTHEAD: cannot allocate length structure\n"); + return (-1); + } + bfields = nfields; + } + + tverb = verbose; + verbose = 0; + ikf = 0; + + for (ifield = 0; ifield < nfields; ifield++) { + + /* Name of field */ + for (i = 0; i < 12; i++) tname[i] = 0; + sprintf (tname, "TTYPE%d", ifield+1);; + temp[0] = 0; + h1 = ksearch (h0,tname); + h0 = h1; + hgets (h0,tname,16,temp); + strcpy (pw[ifield].kname,temp); + pw[ifield].lname = strlen (pw[ifield].kname); + + /* Sequence of field on line */ + pw[ifield].kn = ifield + 1; + + /* First column of field */ + if (bintable) + pw[ifield].kf = ikf; + else { + for (i = 0; i < 12; i++) tname[i] = 0; + sprintf (tname, "TBCOL%d", ifield+1); + pw[ifield].kf = 0; + hgeti4 (h0,tname, &pw[ifield].kf); + } + + /* Length of field */ + for (i = 0; i < 12; i++) tname[i] = 0; + sprintf (tname, "TFORM%d", ifield+1);; + tform[0] = 0; + hgets (h0,tname,16,tform); + strcpy (pw[ifield].kform, tform); + ltform = strlen (tform); + if (tform[ltform-1] == 'A') { + pw[ifield].kform[0] = 'A'; + for (i = 0; i < ltform-1; i++) + pw[ifield].kform[i+1] = tform[i]; + pw[ifield].kform[ltform] = (char) 0; + tf1 = pw[ifield].kform + 1; + kl = atof (tf1); + } + else if (!strcmp (tform,"I")) + kl = 2; + else if (!strcmp (tform, "J")) + kl = 4; + else if (!strcmp (tform, "E")) + kl = 4; + else if (!strcmp (tform, "D")) + kl = 8; + else { + tf1 = tform + 1; + tf2 = strchr (tform,'.'); + if (tf2 != NULL) + *tf2 = ' '; + kl = atoi (tf1); + } + pw[ifield].kl = kl; + ikf = ikf + kl; + } + +/* Set up table for access to desired fields */ + verbose = tverb; + if (verbose) + fprintf (stderr, "FITSRTHEAD: %d keywords read\n", *nk); + +/* If nk = 0, allocate and return structures for all table fields */ + if (*nk <= 0) { + *kw = pw; + *nk = nfields; + return (0); + } + else + rw = *kw; + +/* Find each desired keyword in the header */ + for (ik = 0; ik < *nk; ik++) { + if (rw[ik].kn <= 0) { + for (ifield = 0; ifield < nfields; ifield++) { + if (rw[ik].lname != pw[ifield].lname) + continue; + if (strcmp (pw[ifield].kname, rw[ik].kname) == 0) { + break; + } + } + } + else + ifield = rw[ik].kn - 1; + +/* Set pointer, lentth, and name in returned array of structures */ + rw[ik].kn = ifield + 1; + rw[ik].kf = pw[ifield].kf - 1; + rw[ik].kl = pw[ifield].kl; + strcpy (rw[ik].kform, pw[ifield].kform); + strcpy (rw[ik].kname, pw[ifield].kname); + } + + return (0); +} + + +int +fitsrtline (fd, nbhead, lbuff, tbuff, irow, nbline, line) + +int fd; /* File descriptor for FITS file */ +int nbhead; /* Number of bytes in FITS header */ +int lbuff; /* Number of bytes in table buffer */ +char *tbuff; /* FITS table buffer */ +int irow; /* Number of table row to read */ +int nbline; /* Number of bytes to read for this line */ +char *line; /* One line of FITS table (returned) */ + +{ + int nbuff, nlbuff; + int nbr = 0; + int offset, offend, ntry, ioff; + char *tbuff1; + + offset = nbhead + (nbline * irow); + offend = offset + nbline - 1; + +/* Read a new buffer of the FITS table into memory if needed */ + if (offset < offset1 || offend > offset2) { + nlbuff = lbuff / nbline; + nbuff = nlbuff * nbline; + for (ntry = 0; ntry < 3; ntry++) { + ioff = lseek (fd, offset, SEEK_SET); + if (ioff < offset) { + if (ntry == 2) + return (0); + else + continue; + } + nbr = read (fd, tbuff, nbuff); + if (nbr < nbline) { + if (verbose) + fprintf (stderr, "FITSRTLINE: %d / %d bytes read %d\n", + nbr,nbuff,ntry); + if (ntry == 2) + return (nbr); + } + else + break; + } + offset1 = offset; + offset2 = offset + nbr - 1; + strncpy (line, tbuff, nbline); + return (nbline); + } + else { + tbuff1 = tbuff + (offset - offset1); + strncpy (line, tbuff1, nbline); + return (nbline); + } +} + + +void +fitsrtlset () +{ + offset1 = 0; + offset2 = 0; + return; +} + + +/* FTGETI2 -- Extract n'th column from FITS table line as short */ + +short +ftgeti2 (entry, kw) + +char *entry; /* Row or entry from table */ +struct Keyword *kw; /* Table column information from FITS header */ +{ + char temp[30]; + short i; + int j; + float r; + double d; + + if (ftgetc (entry, kw, temp, 30)) { + if (!strcmp (kw->kform, "I")) + moveb (temp, (char *) &i, 2, 0, 0); + else if (!strcmp (kw->kform, "J")) { + moveb (temp, (char *) &j, 4, 0, 0); + i = (short) j; + } + else if (!strcmp (kw->kform, "E")) { + moveb (temp, (char *) &r, 4, 0, 0); + i = (short) r; + } + else if (!strcmp (kw->kform, "D")) { + moveb (temp, (char *) &d, 8, 0, 0); + i = (short) d; + } + else + i = (short) atof (temp); + return (i); + } + else + return ((short) 0); +} + + +/* FTGETI4 -- Extract n'th column from FITS table line as int */ + +int +ftgeti4 (entry, kw) + +char *entry; /* Row or entry from table */ +struct Keyword *kw; /* Table column information from FITS header */ +{ + char temp[30]; + short i; + int j; + float r; + double d; + + if (ftgetc (entry, kw, temp, 30)) { + if (!strcmp (kw->kform, "I")) { + moveb (temp, (char *) &i, 2, 0, 0); + j = (int) i; + } + else if (!strcmp (kw->kform, "J")) + moveb (temp, (char *) &j, 4, 0, 0); + else if (!strcmp (kw->kform, "E")) { + moveb (temp, (char *) &r, 4, 0, 0); + j = (int) r; + } + else if (!strcmp (kw->kform, "D")) { + moveb (temp, (char *) &d, 8, 0, 0); + j = (int) d; + } + else + j = (int) atof (temp); + return (j); + } + else + return (0); +} + + +/* FTGETR4 -- Extract n'th column from FITS table line as float */ + +float +ftgetr4 (entry, kw) + +char *entry; /* Row or entry from table */ +struct Keyword *kw; /* Table column information from FITS header */ +{ + char temp[30]; + short i; + int j; + float r; + double d; + + if (ftgetc (entry, kw, temp, 30)) { + if (!strcmp (kw->kform, "I")) { + moveb (temp, (char *) &i, 2, 0, 0); + r = (float) i; + } + else if (!strcmp (kw->kform, "J")) { + moveb (temp, (char *) &j, 4, 0, 0); + r = (float) j; + } + else if (!strcmp (kw->kform, "E")) + moveb (temp, (char *) &r, 4, 0, 0); + else if (!strcmp (kw->kform, "D")) { + moveb (temp, (char *) &d, 8, 0, 0); + r = (float) d; + } + else + r = (float) atof (temp); + return (r); + } + else + return ((float) 0.0); +} + + +/* FTGETR8 -- Extract n'th column from FITS table line as double */ + +double +ftgetr8 (entry, kw) + +char *entry; /* Row or entry from table */ +struct Keyword *kw; /* Table column information from FITS header */ +{ + char temp[30]; + short i; + int j; + float r; + double d; + + if (ftgetc (entry, kw, temp, 30)) { + if (!strcmp (kw->kform, "I")) { + moveb (temp, (char *) &i, 2, 0, 0); + d = (double) i; + } + else if (!strcmp (kw->kform, "J")) { + moveb (temp, (char *) &j, 4, 0, 0); + d = (double) j; + } + else if (!strcmp (kw->kform, "E")) { + moveb (temp, (char *) &r, 4, 0, 0); + d = (double) r; + } + else if (!strcmp (kw->kform, "D")) + moveb (temp, (char *) &d, 8, 0, 0); + else + d = atof (temp); + return (d); + } + else + return ((double) 0.0); +} + + +/* FTGETC -- Extract n'th column from FITS table line as character string */ + +int +ftgetc (entry, kw, string, maxchar) + +char *entry; /* Row or entry from table */ +struct Keyword *kw; /* Table column information from FITS header */ +char *string; /* Returned string */ +int maxchar; /* Maximum number of characters in returned string */ +{ + int length = maxchar; + + if (kw->kl < length) + length = kw->kl; + if (length > 0) { + strncpy (string, entry+kw->kf, length); + string[length] = 0; + return ( 1 ); + } + else + return ( 0 ); +} + +extern int errno; + + +/*FITSWIMAGE -- Write FITS header and image */ + +int +fitswimage (filename, header, image) + +char *filename; /* Name of FITS image file */ +char *header; /* FITS image header */ +char *image; /* FITS image pixels */ + +{ + int fd; + + /* Open the output file */ + if (strcasecmp (filename,"stdout") ) { + + if (!access (filename, 0)) { + fd = open (filename, O_WRONLY); + if (fd < 3) { + snprintf (fitserrmsg,79, "FITSWIMAGE: file %s not writeable\n", filename); + return (0); + } + } + else { + fd = open (filename, O_RDWR+O_CREAT, 0666); + if (fd < 3) { + snprintf (fitserrmsg,79, "FITSWIMAGE: cannot create file %s\n", filename); + return (0); + } + } + } +#ifndef VMS + else + fd = STDOUT_FILENO; +#endif + + return (fitswhdu (fd, filename, header, image)); +} + + +/*FITSWEXT -- Write FITS header and image as extension to a file */ + +int +fitswext (filename, header, image) + +char *filename; /* Name of IFTS image file */ +char *header; /* FITS image header */ +char *image; /* FITS image pixels */ + +{ + int fd; + + /* Open the output file */ + if (strcasecmp (filename,"stdout") ) { + + if (!access (filename, 0)) { + fd = open (filename, O_WRONLY); + if (fd < 3) { + snprintf (fitserrmsg,79, "FITSWEXT: file %s not writeable\n", + filename); + return (0); + } + } + else { + fd = open (filename, O_APPEND, 0666); + if (fd < 3) { + snprintf (fitserrmsg,79, "FITSWEXT: cannot append to file %s\n", + filename); + return (0); + } + } + } +#ifndef VMS + else + fd = STDOUT_FILENO; +#endif + + return (fitswhdu (fd, filename, header, image)); +} + + +/* FITSWHDU -- Write FITS head and image as extension */ + +int +fitswhdu (fd, filename, header, image) + +int fd; /* File descriptor */ +char *filename; /* Name of IFTS image file */ +char *header; /* FITS image header */ +char *image; /* FITS image pixels */ +{ + int nbhead, nbimage, nblocks, bytepix, i, nbhw; + int bitpix, naxis, iaxis, naxisi, nbytes, nbw, nbpad, nbwp, simple; + char *endhead, *padding; + double bzero, bscale; + char keyword[32]; + + /* Change BITPIX=-16 files to BITPIX=16 with BZERO and BSCALE */ + bitpix = 0; + hgeti4 (header,"BITPIX",&bitpix); + if (bitpix == -16) { + if (!hgetr8 (header, "BZERO", &bzero) && + !hgetr8 (header, "BSCALE", &bscale)) { + bitpix = 16; + hputi4 (header, "BITPIX", bitpix); + hputr8 (header, "BZERO", 32768.0); + hputr8 (header, "BSCALE", 1.0); + } + } + + /* Write header to file */ + endhead = ksearch (header,"END") + 80; + nbhead = endhead - header; + nbhw = write (fd, header, nbhead); + if (nbhw < nbhead) { + snprintf (fitserrmsg,79, "FITSWHDU: wrote %d / %d bytes of header to file %s\n", + nbhw, nbhead, filename); + (void)close (fd); + return (0); + } + + /* Write extra spaces to make an integral number of 2880-byte blocks */ + nblocks = nbhead / FITSBLOCK; + if (nblocks * FITSBLOCK < nbhead) + nblocks = nblocks + 1; + nbytes = nblocks * FITSBLOCK; + nbpad = nbytes - nbhead; + padding = (char *)calloc (1, nbpad); + for (i = 0; i < nbpad; i++) + padding[i] = ' '; + nbwp = write (fd, padding, nbpad); + if (nbwp < nbpad) { + snprintf (fitserrmsg,79, "FITSWHDU: wrote %d / %d bytes of header padding to file %s\n", + nbwp, nbpad, filename); + (void)close (fd); + return (0); + } + nbhw = nbhw + nbwp; + free (padding); + + /* Return if file has no data */ + if (bitpix == 0 || image == NULL) { + /* snprintf (fitserrmsg,79, "FITSWHDU: BITPIX is 0; image not written\n"); */ + (void)close (fd); + return (0); + } + + /* If SIMPLE=F in header, just write whatever is in the buffer */ + hgetl (header, "SIMPLE", &simple); + if (!simple) { + hgeti4 (header, "NBDATA", &nbytes); + nbimage = nbytes; + } + + else { + + /* Compute size of pixel in bytes */ + bytepix = bitpix / 8; + if (bytepix < 0) bytepix = -bytepix; + nbimage = bytepix; + + /* Compute size of image in bytes using relevant header parameters */ + naxis = 1; + hgeti4 (header,"NAXIS",&naxis); + for (iaxis = 1; iaxis <= naxis; iaxis++) { + sprintf (keyword, "NAXIS%d", iaxis); + naxisi = 1; + hgeti4 (header,keyword,&naxisi); + nbimage = nbimage * naxisi; + } + + /* Number of bytes to write is an integral number of FITS blocks */ + nblocks = nbimage / FITSBLOCK; + if (nblocks * FITSBLOCK < nbimage) + nblocks = nblocks + 1; + nbytes = nblocks * FITSBLOCK; + + /* Byte-reverse image before writing, if necessary */ + if (imswapped ()) + imswap (bitpix, image, nbimage); + } + + /* Write image to file */ + nbw = write (fd, image, nbimage); + if (nbw < nbimage) { + snprintf (fitserrmsg,79, "FITSWHDU: wrote %d / %d bytes of image to file %s\n", + nbw, nbimage, filename); + return (0); + } + + /* Write extra zeroes to make an integral number of 2880-byte blocks */ + nbpad = nbytes - nbimage; + if (nbpad > 0) { + padding = (char *)calloc (1, nbpad); + nbwp = write (fd, padding, nbpad); + if (nbwp < nbpad) { + snprintf (fitserrmsg,79, "FITSWHDU: wrote %d / %d bytes of image padding to file %s\n", + nbwp, nbpad, filename); + (void)close (fd); + return (0); + } + free (padding); + } + else + nbwp = 0; + + (void)close (fd); + + /* Byte-reverse image after writing, if necessary */ + if (imswapped ()) + imswap (bitpix, image, nbimage); + + nbw = nbw + nbwp + nbhw; + return (nbw); +} + + +/*FITSCIMAGE -- Write FITS header and copy FITS image + Return number of bytes in output image, 0 if failure */ + +int +fitscimage (filename, header, filename0) + +char *filename; /* Name of output FITS image file */ +char *header; /* FITS image header */ +char *filename0; /* Name of input FITS image file */ + +{ + int fdout, fdin; + int nbhead, nbimage, nblocks, bytepix; + int bitpix, naxis, naxis1, naxis2, nbytes, nbw, nbpad, nbwp; + char *endhead, *lasthead, *padding; + char *image; /* FITS image pixels */ + char *oldhead; /* Input file image header */ + int nbhead0; /* Length of input file image header */ + int lhead0; + int nbbuff, nbuff, ibuff, nbr, nbdata; + + /* Compute size of image in bytes using relevant header parameters */ + naxis = 1; + hgeti4 (header, "NAXIS", &naxis); + naxis1 = 1; + hgeti4 (header, "NAXIS1", &naxis1); + naxis2 = 1; + hgeti4 (header, "NAXIS2", &naxis2); + hgeti4 (header, "BITPIX", &bitpix); + bytepix = bitpix / 8; + if (bytepix < 0) bytepix = -bytepix; + + /* If either dimension is one and image is 3-D, read all three dimensions */ + if (naxis == 3 && (naxis1 ==1 || naxis2 == 1)) { + int naxis3; + hgeti4 (header,"NAXIS3",&naxis3); + nbimage = naxis1 * naxis2 * naxis3 * bytepix; + } + else + nbimage = naxis1 * naxis2 * bytepix; + + nblocks = nbimage / FITSBLOCK; + if (nblocks * FITSBLOCK < nbimage) + nblocks = nblocks + 1; + nbytes = nblocks * FITSBLOCK; + + /* Allocate image buffer */ + nbbuff = FITSBLOCK * 100; + if (nbytes < nbbuff) + nbbuff = nbytes; + image = (char *) calloc (1, nbbuff); + nbuff = nbytes / nbbuff; + if (nbytes > nbuff * nbbuff) + nbuff = nbuff + 1; + + /* Read input file header */ + if ((oldhead = fitsrhead (filename0, &lhead0, &nbhead0)) == NULL) { + snprintf (fitserrmsg, 79,"FITSCIMAGE: header of input file %s cannot be read\n", + filename0); + return (0); + } + + /* Find size of output header */ + nbhead = fitsheadsize (header); + + /* If overwriting, be more careful if new header is longer than old */ + if (!strcmp (filename, filename0) && nbhead > nbhead0) { + if ((image = fitsrimage (filename0, nbhead0, oldhead)) == NULL) { + snprintf (fitserrmsg,79, "FITSCIMAGE: cannot read image from file %s\n", + filename0); + free (oldhead); + return (0); + } + return (fitswimage (filename, header, image)); + } + free (oldhead); + + /* Open the input file and skip over the header */ + if (strcasecmp (filename0,"stdin")) { + fdin = -1; + fdin = fitsropen (filename0); + if (fdin < 0) { + snprintf (fitserrmsg, 79,"FITSCIMAGE: cannot read file %s\n", filename0); + return (0); + } + + /* Skip over FITS header */ + if (lseek (fdin, nbhead0, SEEK_SET) < 0) { + (void)close (fdin); + snprintf (fitserrmsg,79, "FITSCIMAGE: cannot skip header of file %s\n", + filename0); + return (0); + } + } +#ifndef VMS + else + fdin = STDIN_FILENO; +#endif + + /* Open the output file */ + if (!access (filename, 0)) { + fdout = open (filename, O_WRONLY); + if (fdout < 3) { + snprintf (fitserrmsg,79, "FITSCIMAGE: file %s not writeable\n", filename); + return (0); + } + } + else { + fdout = open (filename, O_RDWR+O_CREAT, 0666); + if (fdout < 3) { + snprintf (fitserrmsg,79, "FITSCHEAD: cannot create file %s\n", filename); + return (0); + } + } + + /* Pad header with spaces */ + endhead = ksearch (header,"END") + 80; + lasthead = header + nbhead; + while (endhead < lasthead) + *(endhead++) = ' '; + + /* Write header to file */ + nbw = write (fdout, header, nbhead); + if (nbw < nbhead) { + snprintf (fitserrmsg, 79,"FITSCIMAGE: wrote %d / %d bytes of header to file %s\n", + nbw, nbytes, filename); + (void)close (fdout); + (void)close (fdin); + return (0); + } + + /* Return if no data */ + if (bitpix == 0) { + (void)close (fdout); + (void)close (fdin); + return (nbhead); + } + + nbdata = 0; + for (ibuff = 0; ibuff < nbuff; ibuff++) { + nbr = read (fdin, image, nbbuff); + if (nbr > 0) { + nbw = write (fdout, image, nbr); + nbdata = nbdata + nbw; + } + } + + /* Write extra to make integral number of 2880-byte blocks */ + nblocks = nbdata / FITSBLOCK; + if (nblocks * FITSBLOCK < nbdata) + nblocks = nblocks + 1; + nbytes = nblocks * FITSBLOCK; + nbpad = nbytes - nbdata; + padding = (char *)calloc (1,nbpad); + nbwp = write (fdout, padding, nbpad); + nbw = nbdata + nbwp; + free (padding); + + (void)close (fdout); + (void)close (fdin); + + if (nbw < nbimage) { + snprintf (fitserrmsg, 79, "FITSWIMAGE: wrote %d / %d bytes of image to file %s\n", + nbw, nbimage, filename); + return (0); + } + else + return (nbw); +} + + +/* FITSWHEAD -- Write FITS header and keep file open for further writing */ + +int +fitswhead (filename, header) + +char *filename; /* Name of IFTS image file */ +char *header; /* FITS image header */ + +{ + int fd; + int nbhead, nblocks; + int nbytes, nbw; + char *endhead, *lasthead; + + /* Open the output file */ + if (!access (filename, 0)) { + fd = open (filename, O_WRONLY); + if (fd < 3) { + snprintf (fitserrmsg, 79, "FITSWHEAD: file %s not writeable\n", filename); + return (0); + } + } + else { + fd = open (filename, O_RDWR+O_CREAT, 0666); + if (fd < 3) { + snprintf (fitserrmsg, 79, "FITSWHEAD: cannot create file %s\n", filename); + return (0); + } + } + + /* Write header to file */ + endhead = ksearch (header,"END") + 80; + nbhead = endhead - header; + nblocks = nbhead / FITSBLOCK; + if (nblocks * FITSBLOCK < nbhead) + nblocks = nblocks + 1; + nbytes = nblocks * FITSBLOCK; + + /* Pad header with spaces */ + lasthead = header + nbytes; + while (endhead < lasthead) + *(endhead++) = ' '; + + nbw = write (fd, header, nbytes); + if (nbw < nbytes) { + fprintf (stderr, "FITSWHEAD: wrote %d / %d bytes of header to file %s\n", + nbw, nbytes, filename); + (void)close (fd); + return (0); + } + return (fd); +} + + +/* FITSWEXHEAD -- Write FITS header in place */ + +int +fitswexhead (filename, header) + +char *filename; /* Name of FITS image file with ,extension */ +char *header; /* FITS image header */ + +{ + int fd; + int nbhead, lhead; + int nbw, nbnew, nbold; + char *endhead, *lasthead, *oldheader; + char *ext, cext; + + /* Compare size of existing header to size of new header */ + fitsinherit = 0; + oldheader = fitsrhead (filename, &lhead, &nbhead); + if (oldheader == NULL) { + snprintf (fitserrmsg, 79, "FITSWEXHEAD: file %s cannot be read\n", filename); + return (-1); + } + nbold = fitsheadsize (oldheader); + nbnew = fitsheadsize (header); + + /* Return if the new header is bigger than the old header */ + if (nbnew > nbold) { + snprintf (fitserrmsg, 79, "FITSWEXHEAD: old header %d bytes, new header %d bytes\n", nbold,nbnew); + free (oldheader); + oldheader = NULL; + return (-1); + } + + /* Add blank lines if new header is smaller than the old header */ + else if (nbnew < nbold) { + strcpy (oldheader, header); + endhead = ksearch (oldheader,"END"); + lasthead = oldheader + nbold; + while (endhead < lasthead) + *(endhead++) = ' '; + strncpy (lasthead-80, "END", 3); + } + + /* Pad header with spaces */ + else { + endhead = ksearch (header,"END") + 80; + lasthead = header + nbnew; + while (endhead < lasthead) + *(endhead++) = ' '; + strncpy (oldheader, header, nbnew); + } + + /* Check for FITS extension and ignore for file opening */ + ext = strchr (filename, ','); + if (ext == NULL) + ext = strchr (filename, '['); + if (ext != NULL) { + cext = *ext; + *ext = (char) 0; + } + + /* Open the output file */ + fd = open (filename, O_WRONLY); + if (ext != NULL) + *ext = cext; + if (fd < 3) { + snprintf (fitserrmsg, 79, "FITSWEXHEAD: file %s not writeable\n", filename); + return (-1); + } + + /* Skip to appropriate place in file */ + (void) lseek (fd, ibhead, SEEK_SET); + + /* Write header to file */ + nbw = write (fd, oldheader, nbold); + (void)close (fd); + free (oldheader); + oldheader = NULL; + if (nbw < nbold) { + fprintf (stderr, "FITSWHEAD: wrote %d / %d bytes of header to file %s\n", + nbw, nbold, filename); + return (-1); + } + return (0); +} + + +/* ISFITS -- Return 1 if FITS file, else 0 */ +int +isfits (filename) + +char *filename; /* Name of file for which to find size */ +{ + int diskfile; + char keyword[16]; + char *comma; + int nbr; + + /* First check to see if this is an assignment */ + if (strchr (filename, '=')) + return (0); + + /* Check for stdin (input from pipe) */ + else if (!strcasecmp (filename,"stdin")) + return (1); + + /* Then check file extension + else if (strsrch (filename, ".fit") || + strsrch (filename, ".fits") || + strsrch (filename, ".fts")) + return (1); */ + + /* If no FITS file extension, try opening the file */ + else { + if ((comma = strchr (filename,','))) + *comma = (char) 0; + if ((diskfile = open (filename, O_RDONLY)) < 0) { + if (comma) + *comma = ','; + return (0); + } + else { + nbr = read (diskfile, keyword, 8); + if (comma) + *comma = ','; + close (diskfile); + if (nbr < 8) + return (0); + else if (!strncmp (keyword, "SIMPLE", 6)) + return (1); + else + return (0); + } + } +} + + +/* FITSHEADSIZE -- Find size of FITS header */ + +int +fitsheadsize (header) + +char *header; /* FITS header */ +{ + char *endhead; + int nbhead, nblocks; + + endhead = ksearch (header,"END") + 80; + nbhead = endhead - header; + nblocks = nbhead / FITSBLOCK; + if (nblocks * FITSBLOCK < nbhead) + nblocks = nblocks + 1; + return (nblocks * FITSBLOCK); +} + + +/* Print error message */ +void +fitserr () +{ fprintf (stderr, "%s\n",fitserrmsg); + return; } + + +/* MOVEB -- Copy nbytes bytes from source+offs to dest+offd (any data type) */ + +void +moveb (source, dest, nbytes, offs, offd) + +char *source; /* Pointer to source */ +char *dest; /* Pointer to destination */ +int nbytes; /* Number of bytes to move */ +int offs; /* Offset in bytes in source from which to start copying */ +int offd; /* Offset in bytes in destination to which to start copying */ +{ +char *from, *last, *to; + from = source + offs; + to = dest + offd; + last = from + nbytes; + while (from < last) *(to++) = *(from++); + return; +} + +/* + * Feb 8 1996 New subroutines + * Apr 10 1996 Add subroutine list at start of file + * Apr 17 1996 Print error message to stderr + * May 2 1996 Write using stream IO + * May 14 1996 If FITSRTOPEN NK is zero, return all keywords in header + * May 17 1996 Make header internal to FITSRTOPEN + * Jun 3 1996 Use stream I/O for input as well as output + * Jun 10 1996 Remove unused variables after running lint + * Jun 12 1996 Deal with byte-swapped images + * Jul 11 1996 Rewrite code to separate header and data reading + * Aug 6 1996 Fixed small defects after lint + * Aug 6 1996 Drop unused NBHEAD argument from FITSRTHEAD + * Aug 13 1996 If filename is stdin, read from standard input instead of file + * Aug 30 1996 Use write for output, not fwrite + * Sep 4 1996 Fix mode when file is created + * Oct 15 1996 Drop column argument from FGET* subroutines + * Oct 15 1996 Drop unused variable + * Dec 17 1996 Add option to skip bytes in file before reading the header + * Dec 27 1996 Turn nonprinting header characters into spaces + * + * Oct 9 1997 Add FITS extension support as filename,extension + * Dec 15 1997 Fix minor bugs after lint + * + * Feb 23 1998 Do not append primary header if getting header for ext. 0 + * Feb 23 1998 Accept either bracketed or comma extension + * Feb 24 1998 Add SIMPLE keyword to start of extracted extension + * Apr 30 1998 Fix error return if not table file after Allan Brighton + * May 4 1998 Fix error in argument sequence in HGETS call + * May 27 1998 Include fitsio.h and imio.h + * Jun 1 1998 Add VMS fixes from Harry Payne at STScI + * Jun 3 1998 Fix bug reading EXTNAME + * Jun 11 1998 Initialize all header parameters before reading them + * Jul 13 1998 Clarify argument definitions + * Aug 6 1998 Rename fitsio.c to fitsfile.c to avoid conflict with CFITSIO + * Aug 13 1998 Add FITSWHEAD to write only header + * Sep 25 1998 Allow STDIN or stdin for standard input reading + * Oct 5 1998 Add isfits() to decide whether a file is FITS + * Oct 9 1998 Assume stdin and STDIN to be FITS files in isfits() + * Nov 30 1998 Fix bug found by Andreas Wicenec when reading large headers + * Dec 8 1998 Fix bug introduced by previous bug fix + * + * Jan 4 1999 Do not print error message if BITPIX is 0 + * Jan 27 1999 Read and write all of 3D images if one dimension is 1 + * Jan 27 1999 Pad out data to integral number of 2880-byte blocks + * Apr 29 1999 Write BITPIX=-16 files as BITPIX=16 with BSCALE and BZERO + * Apr 30 1999 Add % as alternative to , to denote sub-images + * May 25 1999 Set buffer offsets to 0 when FITS table file is opened + * Jul 14 1999 Do not try to write image data if BITPIX is 0 + * Sep 27 1999 Add STDOUT as output filename option in fitswimage() + * Oct 6 1999 Set header length global variable hget.lhead0 in fitsrhead() + * Oct 14 1999 Update header length as it is changed in fitsrhead() + * Oct 20 1999 Change | in if statements to || + * Oct 25 1999 Change most malloc() calls to calloc() + * Nov 24 1999 Add fitscimage() + * + * Feb 23 2000 Fix problem with some error returns in fitscimage() + * Mar 17 2000 Drop unused variables after lint + * Jul 20 2000 Drop BITPIX and NAXIS from primary header if extension printerd + * Jul 20 2000 Start primary part of header with ROOTHEAD keyword + * Jul 28 2000 Add loop to deal with buffered stdin + * + * Jan 11 2001 Print all messages to stderr + * Jan 12 2001 Add extension back onto filename after fitsropen() (Guy Rixon) + * Jan 18 2001 Drop EXTEND keyword when extracting an extension + * Jan 18 2001 Add fitswext() to append HDU and fitswhdu() to do actual writing + * Jan 22 2001 Ignore WCS name or letter following a : in file name in fitsrhead() + * Jan 30 2001 Fix FITSCIMAGE so it doesn't overwrite data when overwriting a file + * Feb 20 2001 Ignore WCS name or letter following a : in file name in fitsropen() + * Feb 23 2001 Initialize rbrac in fitsropen() + * Mar 8 2001 Use % instead of : for WCS specification in file name + * Mar 9 2001 Fix bug so primary header is always appended to secondary header + * Mar 9 2001 Change NEXTEND to NUMEXT in appended primary header + * Mar 20 2001 Declare fitsheadsize() in fitschead() + * Apr 24 2001 When matching column names, use longest length + * Jun 27 2001 In fitsrthead(), allocate pw and lpnam only if more space needed + * Aug 24 2001 In isfits(), return 0 if argument contains an equal sign + * + * Jan 28 2002 In fitsrhead(), allow stdin to include extension and/or WCS selection + * Jun 18 2002 Save error messages as fitserrmsg and use fitserr() to print them + * Oct 21 2002 Add fitsrsect() to read a section of an image + * + * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern) + * Apr 2 2003 Drop unused variable in fitsrsect() + * Jul 11 2003 Use strcasecmp() to check for stdout and stdin + * Aug 1 2003 If no other header, return root header from fitsrhead() + * Aug 20 2003 Add fitsrfull() to read n-dimensional FITS images + * Aug 21 2003 Modify fitswimage() to always write n-dimensional FITS images + * Nov 18 2003 Fix minor bug in fitswhdu() + * Dec 3 2003 Remove unused variable lasthead in fitswhdu() + * + * May 3 2004 Do not always append primary header to extension header + * May 3 2004 Add ibhead as position of header read in file + * May 19 2004 Do not reset ext if NULL in fitswexhead() + * Jul 1 2004 Initialize INHERIT to 1 + * Aug 30 2004 Move fitsheadsize() declaration to fitsfile.h + * Aug 31 2004 If SIMPLE=F, put whatever is in file after header in image + * + * Mar 17 2005 Use unbuffered I/O in isfits() for robustness + * Jun 27 2005 Drop unused variable nblocks in fitswexhead() + * Aug 8 2005 Fix space-padding bug in fitswexhead() found by Armin Rest + * Sep 30 2005 Fix fitsrsect() to position relatively, not absolutely + * Oct 28 2005 Add error message if desired FITS extension is not found + * Oct 28 2005 Fix initialization problem found by Sergey Koposov + * + * Feb 23 2006 Add fitsrtail() to read appended FITS headers + * Feb 27 2006 Add file name to header-reading error messages + * May 3 2006 Remove declarations of unused variables + * Jun 20 2006 Initialize uninitialized variables + * Nov 2 2006 Change all realloc() calls to calloc() + * + * Jan 5 2007 In fitsrtail(), change control characters in header to spaces + * Apr 30 2007 Improve error reporting in FITSRFULL + * Nov 28 2007 Add support to BINTABLE in ftget*() and fitsrthead() + * Dec 20 2007 Add data heap numerated by PCOUNT when skipping HDU in fitsrhead() + * Dec 20 2007 Return NULL pointer if fitsrhead() cannot find requested HDU + * + * Apr 7 2008 Drop comma from name when reading file in isfits() + * Jun 27 2008 Do not append primary data header if it is the only header + * Nov 21 2008 In fitswhead(), print message if too few bytes written + * + * Sep 18 2009 In fitswexhead() write to error string instead of stderr + * Sep 22 2009 In fitsrthead(), fix lengths for ASCII numeric table entries + * Sep 25 2009 Add subroutine moveb() and fix calls to it + * Sep 25 2009 Fix several small errors found by Jessicalas Burke + * + * Mar 29 2010 In fitswhead(), always pad blocks to 2880 bytes with spaces + * Mar 31 2010 In fitsrhead(), fix bug reading long primary headers + * + * Sep 15 2011 In fitsrsect() declare impos and nblin off_t + * Sep 15 2011 In fitsrtail() declare offset off_t + * Sep 15 2011 Declare global variable ibhead off_t + */ diff --git a/astroem/fitsfile.h b/astroem/fitsfile.h new file mode 100644 index 00000000..c000d18c --- /dev/null +++ b/astroem/fitsfile.h @@ -0,0 +1,1286 @@ +/*** File fitsfile.h FITS and IRAF file access subroutines + *** September 25, 2009 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1996-2009 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + */ + +#ifndef fitsfile_h_ +#define fitsfile_h_ +#include "fitshead.h" + +/* Declarations for subroutines in fitsfile.c, imhfile.c, imio.c, + * fileutil.c, and dateutil.c */ + +#define FITSBLOCK 2880 + +/* FITS table keyword structure */ +struct Keyword { + char kname[10]; /* Keyword for table entry */ + int lname; /* Length of keyword name */ + int kn; /* Index of entry on line */ + int kf; /* Index in line of first character of entry */ + int kl; /* Length of entry value */ + char kform[8]; /* Format for this value */ +}; + +/* Structure for access to tokens within a string */ +#define MAXTOKENS 1000 /* Maximum number of tokens to parse */ +#define MAXWHITE 20 /* Maximum number of different whitespace characters */ +struct Tokens { + char *line; /* Line which has been parsed */ + int lline; /* Number of characters in line */ + int ntok; /* Number of tokens on line */ + int nwhite; /* Number of whitespace characters */ + char white[MAXWHITE]; /* Whitespace (separator) characters */ + char *tok1[MAXTOKENS]; /* Pointers to start of tokens */ + int ltok[MAXTOKENS]; /* Lengths of tokens */ + int itok; /* Current token number */ +}; + +#ifdef __cplusplus /* C++ prototypes */ +extern "C" { +#endif + + +#ifdef __STDC__ /* Full ANSI prototypes */ + +/* Declarations for subroutines in fitsfile.c, imhfile.c, imio.c, + * fileutil.c, and dateutil.c */ + +/* FITS file access subroutines in fitsfile.c */ + int fitsropen( /* Open a FITS file for reading, returning a FILE pointer */ + char *inpath); /* Pathname for FITS tables file to read */ + char *fitsrhead( /* Read a FITS header */ + char *filename, /* Name of FITS image file */ + int *lhead, /* Allocated length of FITS header in bytes (returned) */ + int *nbhead); /* Number of bytes before start of data (returned) */ + char *fitsrtail( /* Read FITS header appended to graphics file */ + char *filename, /* Name of FITS image file */ + int *lhead, /* Allocated length of FITS header in bytes (returned) */ + int *nbhead); /* Number of bytes before start of data (returned) */ + char *fitsrimage( /* Read a FITS image */ + char *filename, /* Name of FITS image file */ + int nbhead, /* Actual length of image header(s) in bytes */ + char *header); /* FITS header for image (previously read) */ + char *fitsrfull( /* Read a FITS image of any dimension */ + char *filename, /* Name of FITS image file */ + int nbhead, /* Actual length of image header(s) in bytes */ + char *header); /* FITS header for image (previously read) */ + char *fitsrsect( /* Read a piece of a FITS image, header */ + char *filename, /* Name of FITS image file */ + char *header, /* FITS header for image (previously read) */ + int nbhead, /* Actual length of image header(s) in bytes */ + int x0, /* FITS image X coordinate of first pixel */ + int y0, /* FITS image Y coordinate of first pixel */ + int nx, /* Number of columns to read (less than NAXIS1) */ + int ny, /* Number of rows to read (less than NAXIS2) */ + int nlog); /* Note progress mod this rows */ + int fitswhead( /* Write FITS header; keep file open for further writing */ + char *filename, /* Name of FITS image file */ + char *header); /* FITS header for image (previously read) */ + int fitswexhead( /* Write FITS header in place */ + char *filename, /* Name of FITS image file */ + char *header); /* FITS header for image */ + int fitswext( /* Write FITS header and image as extension to a file */ + char *filename, /* Name of FITS image file */ + char *header, /* FITS image header */ + char *image); /* FITS image pixels */ + int fitswhdu( /* Write FITS head and image as extension */ + int fd, /* File descriptor */ + char *filename, /* Name of FITS image file */ + char *header, /* FITS image header */ + char *image); /* FITS image pixels */ + int fitswimage( /* Write FITS header and image */ + char *filename, /* Name of FITS image file */ + char *header, /* FITS image header */ + char *image); /* FITS image pixels */ + int fitscimage( /* Write FITS header and copy FITS image */ + char *filename, /* Name of output FITS image file */ + char *header, /* FITS image header */ + char *filename0); /* Name of input FITS image file */ + int isfits( /* Return 1 if file is a FITS file */ + char *filename); /* Name of file to check */ + void fitserr(); /* Print FITS error message to stderr */ + void setfitsinherit( /* Set flag to append primary data header */ + int inh); /* 1 to inherit primary data header, else 0 */ + int fitsheadsize( /* Return size of fitsheader in bytes */ + char *header); /* FITS image header */ + +/* FITS table file access subroutines in fitsfile.c */ + + int fitsrtopen( /* Open FITS table file and fill structure with + * pointers to selected keywords + * Return file descriptor (-1 if unsuccessful) */ + char *inpath, /* Pathname for FITS tables file to read */ + int *nk, /* Number of keywords to use */ + struct Keyword **kw, /* Structure for desired entries */ + int *nrows, /* Number of rows in table (returned) */ + int *nchar, /* Number of characters in one table row (returned) */ + int *nbhead); /* Number of characters before table starts */ + int fitsrthead( /* Read pointers to selected keywords + * from FITS table header */ + char *header, /* Header for FITS tables file */ + int *nk, /* Number of keywords to use */ + struct Keyword **kw, /* Structure for desired entries */ + int *nrows, /* Number of rows in table (returned) */ + int *nchar); /* Number of characters in one table row (returned) */ + void fitsrtlset(void); /* Reset FITS Table buffer limits from start of data */ + int fitsrtline( /* Return specified line of FITS table */ + int fd, /* File descriptor for FITS file */ + int nbhead, /* Number of bytes in FITS header */ + int lbuff, /* Number of bytes in table buffer */ + char *tbuff, /* FITS table buffer */ + int irow, /* Number of table row to read */ + int nbline, /* Number of bytes to read for this line */ + char *line); /* One line of FITS table (returned) */ +short ftgeti2( /* Extract column for keyword from FITS table line + * as short */ + char *entry, /* Row or entry from table */ + struct Keyword *kw); /* Table column information from FITS header */ + int ftgeti4( /* Extract column for keyword from FITS table line + * as int */ + char *entry, /* Row or entry from table */ + struct Keyword *kw); /* Table column information from FITS header */ +float ftgetr4( /* Extract column for keyword from FITS table line + * as float */ + char *entry, /* Row or entry from table */ + struct Keyword *kw); /* Table column information from FITS header */ + double ftgetr8( /* Extract column for keyword from FITS table line + * as double */ + char *entry, /* Row or entry from table */ + struct Keyword *kw); /* Table column information from FITS header */ + int ftgetc( /* Extract column for keyword from FITS table line + * as char string */ + char *entry, /* Row or entry from table */ + struct Keyword *kw, /* Table column information from FITS header */ + char *string, /* Returned string */ + int maxchar); /* Maximum number of characters in returned string */ + + void moveb ( /* Copy nbytes bytes from source+offs to dest+offd */ + char *source, /* Pointer to source */ + char *dest, /* Pointer to destination */ + int nbytes, /* Number of bytes to move */ + int offs, /* Offset in bytes in source from which to start copying */ + int offd); /* Offset in bytes in destination to which to start copying */ + + +/* IRAF file access subroutines in imhfile.c */ + + char *irafrhead( /* Read IRAF .imh header file and translate to FITS header */ + char *filename, /* Name of IRAF header file */ + int *lihead); /* Length of IRAF image header in bytes (returned) */ + char *irafrimage( /* Read IRAF image pixels (call after irafrhead) */ + char *fitsheader); /* FITS image header (filled) */ + int irafwhead( /* Write IRAF .imh header file */ + char *hdrname, /* Name of IRAF header file */ + int lhead, /* Length of IRAF header */ + char *irafheader, /* IRAF header */ + char *fitsheader); /* FITS image header */ + int irafwimage( /* Write IRAF .imh header file and .pix image file */ + char *hdrname, /* Name of IRAF header file */ + int lhead, /* Length of IRAF header */ + char *irafheader, /* IRAF header */ + char *fitsheader, /* FITS image header */ + char *image); /* IRAF image */ + int isiraf( /* return 1 if IRAF imh file, else 0 */ + char *filename); /* Name of file to check */ + char *iraf2fits( /* Convert IRAF image header to FITS image header, + * returning FITS header */ + char *hdrname, /* IRAF header file name (may be path) */ + char *irafheader, /* IRAF image header */ + int nbiraf, /* Number of bytes in IRAF header */ + int *nbfits); /* Number of bytes in FITS header (returned) */ + + char *fits2iraf( /* Convert FITS image header to IRAF image header, + * returning IRAF header */ + char *fitsheader, /* FITS image header */ + char *irafheader, /* IRAF image header (returned updated) */ + int nbhead, /* Length of IRAF header */ + int *nbiraf); /* Length of returned IRAF header */ + +/* Image pixel access subroutines in imio.c */ + + double getpix( /* Read one pixel from any data type 2-D array (0,0)*/ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel + * 16 = short, -16 = unsigned short, 32 = int + * -32 = float, -64 = double */ + int w, /* Image width in pixels */ + int h, /* Image height in pixels */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int x, /* Zero-based horizontal pixel number */ + int y); /* Zero-based vertical pixel number */ + double getpix1( /* Read one pixel from any data type 2-D array (1,1)*/ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel */ + int w, /* Image width in pixels */ + int h, /* Image height in pixels */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int x, /* One-based horizontal pixel number */ + int y); /* One-based vertical pixel number */ + double maxvec( /* Get maximum value in vector from a image */ + char *image, /* Image array from which to extract vector */ + int bitpix, /* Number of bits per pixel in image */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int pix1, /* Offset of first pixel to extract */ + int npix); /* Number of pixels to extract */ + double minvec( /* Get minimum value in vector from a image */ + char *image, /* Image array from which to extract vector */ + int bitpix, /* Number of bits per pixel in image */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int pix1, /* Offset of first pixel to extract */ + int npix); /* Number of pixels to extract */ + void putpix( /* Write one pixel to any data type 2-D array (0,0)*/ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel */ + int w, /* Image width in pixels */ + int h, /* Image height in pixels */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int x, /* Zero-based horizontal pixel number */ + int y, /* Zero-based vertical pixel number */ + double dpix); /* Value to put into image pixel */ + void putpix1( /* Write one pixel to any data type 2-D array (1,1) */ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel */ + int w, /* Image width in pixels */ + int h, /* Image height in pixels */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int x, /* One-based horizontal pixel number */ + int y, /* One-based vertical pixel number */ + double dpix); /* Value to put into image pixel */ + void addpix( /* Add to one pixel in any data type 2-D array (0,0)*/ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel */ + int w, /* Image width in pixels */ + int h, /* Image height in pixels */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int x, /* Zero-based horizontal pixel number */ + int y, /* Zero-based vertical pixel number */ + double dpix); /* Value to add to image pixel */ + void addpix1( /* Add to one pixel in any data type 2-D array (1,1)*/ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel */ + int w, /* Image width in pixels */ + int h, /* Image height in pixels */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int x, /* One-based horizontal pixel number */ + int y, /* One-based vertical pixel number */ + double dpix); /* Value to add to image pixel */ + void movepix( /* Move one pixel value between two 2-D arrays (0,0) */ + char *image1, /* Pointer to first pixel in input image */ + int bitpix1, /* Bits per input pixel (FITS codes) */ + int w1, /* Number of horizontal pixels in input image */ + int x1, /* Zero-based row for input pixel */ + int y1, /* Zero-based column for input pixel */ + char *image2, /* Pointer to first pixel in output image */ + int bitpix2, /* Bits per output pixel (FITS codes) */ + int w2, /* Number of horizontal pixels in output image */ + int x2, /* Zero-based row for output pixel */ + int y2); /* Zero-based column for output pixel */ + void movepix1( /* Move one pixel value between two 2-D arrays (1,1) */ + char *image1, /* Pointer to first pixel in input image */ + int bitpix1, /* Bits per input pixel (FITS codes) */ + int w1, /* Number of horizontal pixels in input image */ + int x1, /* One-based row for input pixel */ + int y1, /* One-based column for input pixel */ + char *image2, /* Pointer to first pixel in output image */ + int bitpix2, /* Bits per output pixel (FITS codes) */ + int w2, /* Number of horizontal pixels in output image */ + int x2, /* One-based row for output pixel */ + int y2); /* One-based column for output pixel */ + +/* Image vector processing subroutines in imio.c */ + + void addvec( /* Add constant to vector from 2-D array */ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int pix1, /* Offset of first pixel to which to add */ + int npix, /* Number of pixels to which to add */ + double dpix); /* Value to add to pixels */ + void multvec( /* Multiply vector from 2-D array by a constant */ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int pix1, /* Offset of first pixel to multiply */ + int npix, /* Number of pixels to multiply */ + double dpix); /* Value to add to pixels */ + void getvec( /* Read vector from 2-D array */ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int pix1, /* Offset of first pixel to extract */ + int npix, /* Number of pixels to extract */ + double *dvec0); /* Vector of pixels (returned) */ + void putvec( /* Write vector into 2-D array */ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int pix1, /* Offset of first pixel to insert */ + int npix, /* Number of pixels to insert */ + double *dvec0); /* Vector of pixels to insert */ + void fillvec( /* Write constant into a vector */ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int pix1, /* Zero-based offset of first pixel to multiply */ + int npix, /* Number of pixels to multiply */ + double dpix); /* Value to which to set pixels */ + void fillvec1( /* Write constant into a vector */ + char *image, /* Image array as 1-D vector */ + int bitpix, /* FITS bits per pixel */ + double bzero, /* Zero point for pixel scaling */ + double bscale, /* Scale factor for pixel scaling */ + int pix1, /* One-based offset of first pixel to multiply */ + int npix, /* Number of pixels to multiply */ + double dpix); /* Value to which to set pixels */ + +/* Image pixel byte-swapping subroutines in imio.c */ + + void imswap( /* Swap alternating bytes in a vector */ + int bitpix, /* Number of bits per pixel */ + char *string, /* Address of starting point of bytes to swap */ + int nbytes); /* Number of bytes to swap */ + void imswap2( /* Swap bytes in a vector of 2-byte (short) integers */ + char *string, /* Address of starting point of bytes to swap */ + int nbytes); /* Number of bytes to swap */ + void imswap4( /* Reverse bytes in a vector of 4-byte numbers */ + char *string, /* Address of starting point of bytes to swap */ + int nbytes); /* Number of bytes to swap */ + void imswap8( /* Reverse bytes in a vector of 8-byte numbers */ + char *string, /* Address of starting point of bytes to swap */ + int nbytes); /* Number of bytes to swap */ + int imswapped(void); /* Return 1 if machine byte order is not FITS order */ + +/* File utilities from fileutil.c */ + + int getfilelines( /* Return number of lines in an ASCII file */ + char *filename); /* Name of file to check */ + char *getfilebuff( /* Return entire file contents in a character string */ + char *filename); /* Name of file to read */ + int getfilesize( /* Return size of a binary or ASCII file */ + char *filename); /* Name of file to check */ + int isimlist( /* Return 1 if file is list of FITS or IRAF image files, else 0 */ + char *filename); /* Name of file to check */ + int isimlistd( /* Return 1 if file is list of FITS or IRAF image files, else 0 */ + char *filename, /* Name of file to check */ + char *rootdir); /* Name of root directory for files in list */ + int isfilelist( /* Return 1 if list of readable files, else 0 */ + char *filename, /* Name of file to check */ + char *rootdir); /* Name of root directory for files in list */ + int isfile( /* Return 1 if file is a readable file, else 0 */ + char *filename); /* Name of file to check */ + int istiff( /* Return 1 if TIFF image file, else 0 */ + char *filename); /* Name of file to check */ + int isjpeg( /* Return 1 if JPEG image file, else 0 */ + char *filename); /* Name of file to check */ + int isgif( /* Return 1 if GIF image file, else 0 */ + char *filename); /* Name of file to check */ + int first_token( /* Return first token from the next line of an ASCII file */ + FILE *diskfile, /* File descriptor for ASCII file */ + int ncmax, /* Maximum number of characters returned */ + char *token); /* First token on next line (returned) */ + int stc2s ( /* Replace character in string with space */ + char *spchar, /* Character to replace with spaces */ + char *string); /* Character string to process */ + int sts2c ( /* Replace spaces in string with character */ + char *spchar, /* Character with which to replace spaces */ + char *string); /* Character string to process */ + +/* Subroutines for access to tokens within a string from fileutil.c */ + int setoken( /* Tokenize a string for easy decoding */ + struct Tokens *tokens, /* Token structure returned */ + char *string, /* character string to tokenize */ + char *cwhite); /* additional whitespace characters + * if = tab, disallow spaces and commas */ + int nextoken( /* Get next token from tokenized string */ + struct Tokens *tokens, /* Token structure returned */ + char *token, /* token (returned) */ + int maxchars); /* Maximum length of token */ + int getoken( /* Get specified token from tokenized string */ + struct Tokens *tokens, /* Token structure returned */ + int itok, /* token sequence number of token + * if <0, get whole string after token -itok + * if =0, get whole string */ + char *token, /* token (returned) */ + int maxchars); /* Maximum length of token */ + +/* Subroutines for translating dates and times in dateutil.c */ + + /* Subroutines to convert between floating point and vigesimal angles */ + + void ang2hr ( /* Fractional degrees to hours as hh:mm:ss.ss */ + double angle, /* Angle in fractional degrees */ + int lstr, /* Maximum number of characters in string */ + char *string); /* Character string (hh:mm:ss.ss returned) */ + void ang2deg ( /* Fractional degrees to degrees as dd:mm:ss.ss */ + double angle, /* Angle in fractional degrees */ + int lstr, /* Maximum number of characters in string */ + char *string); /* Character string (dd:mm:ss.ss returned) */ + double deg2ang ( /* Degrees as dd:mm:ss.ss to fractional degrees */ + char *angle); /* Angle as dd:mm:ss.ss */ + double hr2ang ( /* Hours as hh:mm:ss.ss to fractional degrees */ + char *angle); /* Angle in sexigesimal hours (hh:mm:ss.sss) */ + + /* Subroutines to convert from year and day of year */ + + void doy2dt( /* Year and day of year to yyyy.mmdd hh.mmss */ + int year, /* Year */ + double doy, /* Day of year with fraction */ + double *date, /* Date as yyyy.mmdd (returned) */ + double *time); /* Time as hh.mmssxxxx (returned) */ + double doy2ep( /* Year and day of year to fractional year (epoch) */ + int year, /* Year */ + double doy); /* Day of year with fraction */ + double doy2epb( /* year and day of year to Besselian epoch */ + int year, /* Year */ + double doy); /* Day of year with fraction */ + double doy2epj( /* year and day of year to Julian epoch */ + int year, /* Year */ + double doy); /* Day of year with fraction */ + char *doy2fd( /* year and day of year to FITS date */ + int year, /* Year */ + double doy); /* Day of year with fraction */ + double doy2jd( /* year and day of year to Julian Day */ + int year, /* Year */ + double doy); /* Day of year with fraction */ + double doy2mjd( /* year and day of year to Modified Julian Day */ + int year, /* Year */ + double doy); /* Day of year with fraction */ + double doy2ts( /* year and day of year to seconds since 1950.0 */ + int year, /* Year */ + double doy); /* Day of year with fraction */ + int doy2tsi( /* year and day of year to IRAF seconds since 1980-01-01 */ + int year, /* Year */ + double doy); /* Day of year with fraction */ + time_t doy2tsu( /* year and day of year to Unix seconds since 1970-01-01 */ + int year, /* Year */ + double doy); /* Day of year with fraction */ + + /* Subroutines to convert from date and time */ + + void dt2doy( /* yyyy.mmdd hh.mmss to year and day of year */ + double date, /* Date as yyyy.mmdd + * yyyy = calendar year (e.g. 1973) + * mm = calendar month (e.g. 04 = april) + * dd = calendar day (e.g. 15) */ + double time, /* Time as hh.mmssxxxx + * if time<0, it is time as -(fraction of a day) + * hh = hour of day (0 .le. hh .le. 23) + * nn = minutes (0 .le. nn .le. 59) + * ss = seconds (0 .le. ss .le. 59) + * xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ + int *year, /* Year (returned) */ + double *doy); /* Day of year with fraction (returned) */ + double dt2ep( /* yyyy.ddmm and hh.mmsss to fractional year (epoch) */ + double date, /* Date as yyyy.mmdd */ + double time); /* Time as hh.mmssxxxx */ + double dt2epb( /* yyyy.ddmm and hh.mmsss to Besselian epoch */ + double date, /* Date as yyyy.mmdd */ + double time); /* Time as hh.mmssxxxx */ + double dt2epj( /* yyyy.ddmm and hh.mmsss to Julian epoch */ + double date, /* Date as yyyy.mmdd */ + double time); /* Time as hh.mmssxxxx */ + char *dt2fd( /* yyyy.ddmm and hh.mmsss to FITS date string */ + double date, /* Date as yyyy.mmdd */ + double time); /* Time as hh.mmssxxxx */ + void dt2i( /* yyyy.ddmm and hh.mmsss to year, month, day, hrs, min, sec */ + double date, /* Date as yyyy.mmdd */ + double time, /* Time as hh.mmssxxxx */ + int *iyr, /* year (returned) */ + int *imon, /* month (returned) */ + int *iday, /* day (returned) */ + int *ihr, /* hours (returned) */ + int *imn, /* minutes (returned) */ + double *sec, /* seconds (returned) */ + int ndsec); /* Number of decimal places in seconds (0=int) */ + double dt2jd( /* yyyy.ddmm and hh.mmsss to Julian Day */ + double date, /* Date as yyyy.mmdd */ + double time); /* Time as hh.mmssxxxx */ + double dt2mjd( /* yyyy.ddmm and hh.mmsss to Modified Julian Day */ + double date, /* Date as yyyy.mmdd */ + double time); /* Time as hh.mmssxxxx */ + double dt2ts( /* yyyy.ddmm and hh.mmsss to seconds since 1950.0 */ + double date, /* Date as yyyy.mmdd */ + double time); /* Time as hh.mmssxxxx */ + int dt2tsi( /* yyyy.ddmm and hh.mmsss to IRAF seconds since 1980-01-01 */ + double date, /* Date as yyyy.mmdd */ + double time); /* Time as hh.mmssxxxx */ + time_t dt2tsu( /* yyyy.ddmm and hh.mmsss to Unix seconds since 1970-01-01 */ + double date, /* Date as yyyy.mmdd */ + double time); /* Time as hh.mmssxxxx */ + + /* Subroutines to convert from epoch (various types of fractional year) */ + + void ep2dt( /* Fractional year to yyyy.mmdd hh.mmssss */ + double epoch, /* Date as fractional year */ + double *date, /* Date as yyyy.mmdd (returned) */ + double *time); /* Time as hh.mmssxxxx (returned) */ + void epb2dt( /* Besselian epoch to yyyy.mmdd hh.mmssss */ + double epoch, /* Besselian epoch (fractional 365.242198781-day years) */ + double *date, /* Date as yyyy.mmdd (returned) */ + double *time); /* Time as hh.mmssxxxx (returned) */ + void epj2dt( /* Julian epoch to yyyy.mmdd hh.mmssss */ + double epoch, /* Julian epoch (fractional 365.25-day years) */ + double *date, /* Date as yyyy.mmdd (returned)*/ + double *time); /* Time as hh.mmssxxxx (returned) */ + char *ep2fd( /* Fractional year to FITS date string yyyy-mm-ddThh:mm:ss.ss */ + double epoch); /* Date as fractional year */ + char *epb2fd( /* Besselian epoch to FITS date string yyyy-mm-ddThh:mm:ss.ss */ + double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ + char *epj2fd( /* Julian epoch to FITS date string yyyy-mm-ddThh:mm:ss.ss */ + double epoch); /* Julian epoch (fractional 365.25-day years) */ + void ep2i( /* Fractional year to year, month, day, hours, min., sec. */ + double epoch, /* Date as fractional year */ + int *iyr, /* year (returned) */ + int *imon, /* month (returned) */ + int *iday, /* day (returned) */ + int *ihr, /* hours (returned) */ + int *imn, /* minutes (returned) */ + double *sec, /* seconds (returned) */ + int ndsec); /* Number of decimal places in seconds (0=int) */ + void epb2i( /* Besselian epoch to year, month, day, hours, min., sec. */ + double epoch, /* Besselian epoch (fractional 365.242198781-day years) */ + int *iyr, /* year (returned) */ + int *imon, /* month (returned) */ + int *iday, /* day (returned) */ + int *ihr, /* hours (returned) */ + int *imn, /* minutes (returned) */ + double *sec, /* seconds (returned) */ + int ndsec); /* Number of decimal places in seconds (0=int) */ + void epj2i( /* Julian epoch to year, month, day, hours, min., sec. */ + double epoch, /* Julian epoch (fractional 365.25-day years) */ + int *iyr, /* year (returned) */ + int *imon, /* month (returned) */ + int *iday, /* day (returned) */ + int *ihr, /* hours (returned) */ + int *imn, /* minutes (returned) */ + double *sec, /* seconds (returned) */ + int ndsec); /* Number of decimal places in seconds (0=int) */ + double ep2jd( /* Fractional year to Julian Date */ + double epoch); /* Date as fractional year */ + double epb2jd( /* Besselian epoch to Julian Date */ + double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ + double epj2jd( /* Julian epoch to Julian Date */ + double epoch); /* Julian epoch (fractional 365.25-day years) */ + double ep2mjd( /* Fractional year to Modified Julian Date */ + double epoch); /* Date as fractional year */ + double epb2mjd( /* Besselian epoch to Modified Julian Date */ + double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ + double epj2mjd( /* Julian epoch to Modified Julian Date */ + double epoch); /* Julian epoch (fractional 365.25-day years) */ + double ep2epb( /* Fractional year to Besselian epoch */ + double epoch); /* Date as fractional year */ + double ep2epj( /* Fractional year to Julian epoch */ + double epoch); /* Date as fractional year */ + double epb2epj( /* Besselian epoch to Julian epoch */ + double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ + double epj2epb( /* Julian epoch to Besselian epoch */ + double epoch); /* Julian epoch (fractional 365.25-day years) */ + double epb2ep( /* Besselian epoch to fractional year */ + double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ + double epj2ep( /* Julian epoch to fractional year */ + double epoch); /* Julian epoch (fractional 365.25-day years) */ + double ep2ts( /* Fractional year to seconds since 1950.0 */ + double epoch); /* Date as fractional year */ + double epb2ts( /* Besselian epoch to seconds since 1950.0 */ + double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ + double epj2ts( /* Julian epoch to seconds since 1950.0 */ + double epoch); /* Julian epoch (fractional 365.25-day years) */ + + /* Convert from FITS standard date string */ + + void fd2dt( /* FITS standard date string to date and time */ + char *string, /* FITS date string, which may be: + * fractional year + * dd/mm/yy (FITS standard before 2000) + * dd-mm-yy (nonstandard use before 2000) + * yyyy-mm-dd (FITS standard after 1999) + * yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ + double *date, /* Date as yyyy.mmdd (returned)*/ + double *time); /* Time as hh.mmssxxxx (returned) */ + void fd2doy( /* FITS standard date string to year, day of year */ + char *string, /* FITS date string */ + int *year, /* Year (returned) */ + double *doy); /* Day of year with fraction (returned) */ + double fd2ep( /* FITS standard date string to fractional year (epoch) */ + char *string); /* FITS date string */ + double fd2epb( /* FITS standard date string to Besselian epoch */ + char *string); /* FITS date string */ + double fd2epj( /* FITS standard date string to Julian epoch */ + char *string); /* FITS date string */ + char *fd2fd( /* Any FITS standard date string to ISO FITS date string */ + char *string); /* FITS date string */ + char *fd2of( /* Any FITS standard date string to old FITS date and time */ + char *string); /* FITS date string */ + char *fd2ofd( /* Any FITS standard date string to old FITS date string */ + char *string); /* FITS date string */ + char *fd2oft( /* Any FITS standard date string to old FITS time string */ + char *string); /* FITS date string */ + void fd2i( /* FITS standard date string to year, mon, day, hrs, min, sec */ + char *string, /* FITS date string */ + int *iyr, /* year (returned) */ + int *imon, /* month (returned) */ + int *iday, /* day (returned) */ + int *ihr, /* hours (returned) */ + int *imn, /* minutes (returned) */ + double *sec, /* seconds (returned) */ + int ndsec); /* Number of decimal places in seconds (0=int) */ + double fd2jd( /* FITS standard date string to Julian Day */ + char *string); /* FITS date string */ + double fd2mjd( /* FITS standard date string to Modified Julian Day */ + char *string); /* FITS date string */ + double fd2ts( /* FITS standard date to seconds since 1950-01-01 */ + char *string); /* FITS date string */ + int fd2tsi( /* FITS standard date to IRAF seconds since 1980-01-01 */ + char *string); /* FITS date string */ + time_t fd2tsu( /* FITS standard date to Unix seconds since 1970-01-01 */ + char *string); /* FITS date string */ + + /* Convert from Julian Day */ + + void jd2doy( /* Julian Day to year and day of year */ + double dj, /* Julian Day */ + int *year, /* Year (returned) */ + double *doy); /* Day of year with fraction (returned) */ + void jd2dt( /* Julian Day to yyyy.mmdd hh.mmssss */ + double dj, /* Julian Day */ + double *date, /* Date as yyyy.mmdd (returned)*/ + double *time); /* Time as hh.mmssxxxx (returned) */ + double jd2ep( /* Julian Day to fractional year */ + double dj); /* Julian Day */ + double jd2epb( /* Julian Day to Besselian epoch */ + double dj); /* Julian Day */ + double jd2epj( /* Julian Day to Julian epoch */ + double dj); /* Julian Day */ + char *jd2fd( /* Julian Day to FITS date string yyyy-mm-ddThh:mm:ss.ss */ + double dj); /* Julian Day */ + void jd2i( /* Julian Day to year, month, day, hours, min., sec. */ + double dj, /* Julian Day */ + int *iyr, /* year (returned) */ + int *imon, /* month (returned) */ + int *iday, /* day (returned) */ + int *ihr, /* hours (returned) */ + int *imn, /* minutes (returned) */ + double *sec, /* seconds (returned) */ + int ndsec); /* Number of decimal places in seconds (0=int) */ + double jd2mjd( /* Julian Day to Modified Julian day */ + double dj); /* Julian Day */ + double jd2ts( /* Julian Day to seconds since 1950.0 */ + double dj); /* Julian Day */ + time_t jd2tsu( /* Julian Day to Unix seconds since 1970-01-01T00:00 */ + double dj); /* Julian Day */ + int jd2tsi( /* Julian Day to IRAF seconds since 1980-01-01T00:00 */ + double dj); /* Julian Day */ + + /* Convert current local time to various formats */ + + void lt2dt( /* Current local time to date (yyyy.mmdd), time (hh.mmsss) */ + double *date, /* Date as yyyy.mmdd (returned) */ + double *time); /* Time as hh.mmssxxxx (returned) */ + char *lt2fd(void); /* Current local time to FITS ISO date string */ + int lt2tsi(void); /* Current local time to IRAF seconds since 1980-01-01T00:00 */ + time_t lt2tsu(void); /* Current local time to Unix seconds since 1970-01-01T00:00 */ + double lt2ts(void); /* Current local time to IRAF seconds since 1950-01-01T00:00 */ + + /* Convert from Modified Julian Day (JD - 2400000.5) */ + + void mjd2doy( /* Modified Julian Day to year and day of year */ + double dj, /* Modified Julian Day */ + int *year, /* Year (returned) */ + double *doy); /* Day of year with fraction (returned) */ + void mjd2dt( /* Modified Julian Day to yyyy.mmdd hh.mmssss */ + double dj, /* Modified Julian Date */ + double *date, /* Date as yyyy.mmdd (returned)*/ + double *time); /* Time as hh.mmssxxxx (returned) */ + double mjd2ep( /* Modified Julian Day to fractional year */ + double dj); /* Modified Julian Date */ + double mjd2epb( /* Modified Julian Day to Besselian epoch */ + double dj); /* Modified Julian Date */ + double mjd2epj( /* Modified Julian Day to Julian epoch */ + double dj); /* Modified Julian Date */ + char *mjd2fd( /* Modified Julian Day to FITS date yyyy-mm-ddThh:mm:ss.ss */ + double dj); /* Modified Julian Date */ + void mjd2i( /* Modified Julian Day to year, month, day, hours, min, sec */ + double dj, /* Modified Julian Date */ + int *iyr, /* year (returned) */ + int *imon, /* month (returned) */ + int *iday, /* day (returned) */ + int *ihr, /* hours (returned) */ + int *imn, /* minutes (returned) */ + double *sec, /* seconds (returned) */ + int ndsec); /* Number of decimal places in seconds (0=int) */ + double mjd2jd( /* Modified Julian Day to Julian day */ + double dj); /* Modified Julian Date */ + double mjd2ts( /* Modified Julian Day to seconds since 1950.0 */ + double dj); /* Modified Julian Date */ + + /* Convert from seconds since 1950-01-01 0:00 (JPL Ephemeris time) */ + + void ts2dt( /* Seconds since 1950.0 to yyyy.mmdd hh.mmssss */ + double tsec, /* seconds since 1950.0 */ + double *date, /* Date as yyyy.mmdd (returned)*/ + double *time); /* Time as hh.mmssxxxx (returned) */ + double ts2ep( /* Seconds since 1950.0 to fractional year */ + double tsec); /* seconds since 1950.0 */ + double ts2epb( /* Seconds since 1950.0 to Besselian epoch */ + double tsec); /* seconds since 1950.0 */ + double ts2epj( /* Seconds since 1950.0 to Julian epoch */ + double tsec); /* seconds since 1950.0 */ + char *ts2fd( /* Seconds since 1950.0 to FITS date, yyyy-mm-ddT00:00:00.000 */ + double tsec); /* seconds since 1950.0 */ + void ts2i( /* Seconds since 1950.0 to year, month, day, hours, min, sec */ + double tsec, /* seconds since 1950.0 */ + int *iyr, /* year (returned) */ + int *imon, /* month (returned) */ + int *iday, /* day (returned) */ + int *ihr, /* hours (returned) */ + int *imn, /* minutes (returned) */ + double *sec, /* seconds (returned) */ + int ndsec); /* Number of decimal places in seconds (0=int) */ + double ts2jd( /* Seconds since 1950.0 to Julian Day */ + double tsec); /* seconds since 1950.0 */ + double ts2mjd( /* Seconds since 1950.0 to Modified Julian Day */ + double tsec); /* seconds since 1950.0 */ + + /* Convert from IRAF time (seconds since 1980-01-01 0:00 UT) */ + + char *tsi2fd( /* Seconds since 1980-01-01 to FITS standard date string */ + int isec); /* Seconds past 1980-01-01 */ + double tsi2ts( /* Seconds since 1980-01-01 to seconds since 1950-01-01 */ + int isec); /* Seconds past 1980-01-01 */ + void tsi2dt( /* Seconds since 1980-01-01 to date yyyy.mmdd, time hh.mmssss */ + int isec, /* Seconds past 1980-01-01 */ + double *date, /* Date as yyyy.mmdd (returned) */ + double *time); /* Time as hh.mmssxxxx (returned) */ + + /* Convert from Unix time (seconds since 1970-01-01 0:00 UT) */ + + void tsu2dt( /* Seconds since 1970-01-01 to date yyyy.ddmm, time hh.mmsss */ + time_t isec, /* Seconds past 1970-01-01 */ + double *date, /* Date as yyyy.mmdd (returned) */ + double *time); /* Time as hh.mmssxxxx (returned) */ + char *tsu2fd( /* Seconds since 1970-01-01 to FITS standard date string */ + time_t isec); /* Seconds past 1970-01-01 */ + double tsu2ts( /* Seconds since 1970-01-01 to seconds since 1950-01-01 */ + time_t isec); /* Seconds past 1970-01-01 */ + int tsu2tsi( /* Seconds since 1970-01-01 to local seconds since 1980-01-01 */ + time_t isec); /* Seconds past 1970-01-01 */ + + /* Convert times within a day */ + + char *tsd2fd( /* Seconds since start of day to FITS standard time string */ + double tsec); /* Seconds since start of day */ + double tsd2dt( /* Seconds since start of day to hh.mmsssss */ + double tsec); /* Seconds since start of day */ + + /* Convert from current Universal Time */ + + void ut2dt( /* Current Universal Time to date (yyyy.mmdd), time (hh.mmsss) */ + double *date, /* Date as yyyy.mmdd (returned) */ + double *time); /* Time as hh.mmssxxxx (returned) */ + void ut2doy( /* Current Universal Time to year, day of year */ + int *year, /* Year (returned) */ + double *doy); /* Day of year (returned) */ + double ut2ep(void); /* Current Universal Time to fractional year */ + double ut2epb(void); /* Current Universal Time to Besselian Epoch */ + double ut2epj(void); /* Current Universal Time to Julian Epoch */ + char *ut2fd(void); /* Current Universal Time to FITS ISO date string */ + double ut2jd(void); /* Current Universal Time to Julian Date */ + double ut2mjd(void); /* Current Universal Time to Modified Julian Date */ + int ut2tsi(void); /* Current UT to IRAF seconds since 1980-01-01T00:00 */ + time_t ut2tsu(void); /* Current UT to Unix seconds since 1970-01-01T00:00 */ + double ut2ts(void); /* Current UT to seconds since 1950-01-01T00:00 */ + + int isdate( /* Return 1 if string is FITS old or ISO date */ + char *string); /* Possible FITS date string, which may be: + * dd/mm/yy (FITS standard before 2000) + * dd-mm-yy (nonstandard FITS use before 2000) + * yyyy-mm-dd (FITS standard after 1999) + * yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ + + /* Ephemeris time conversions (ET, TT, and TDT) */ + + char *et2fd( /* ET (or TDT or TT) in FITS format to UT in FITS format */ + char *string); /* Ephemeris Time as FITS date string (E not T) */ + char *fd2et( /* UT in FITS format to ET (or TDT or TT) in FITS format */ + char *string); /* FITS date string */ + void dt2et( /* yyyy.ddmm and hh.mmsss to Ephemeris Time */ + double *date, /* Date as yyyy.mmdd */ + double *time); /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ + double jd2jed( /* Convert from Julian Date to Julian Ephemeris Date */ + double dj); /* Julian Date */ + double jed2jd( /* Convert from Julian Ephemeris Date to Julian Date */ + double dj); /* Julian Ephemeris Date */ + double ets2ts( /* ET in seconds since 1950-01-01 to UT in same format */ + double tsec); /* ET in seconds since 1950-01-01 */ + double ts2ets( /* UT in seconds since 1950-01-01 to ET in same format */ + double tsec); /* UT in seconds since 1950-01-01 */ + void edt2dt( /* yyyy.ddmm and hh.mmsss Ephemeris Time to UT */ + double *date, /* Date as yyyy.mmdd */ + double *time); /* Time as hh.mmssxxxx + * If time<0, it is time as -(fraction of a day) */ + double utdt( /* Compute difference between UT and dynamical time (ET-UT) */ + double dj); /* Julian Date (UT) */ + + /* Sidereal Time conversions */ + + char *fd2gst( /* Convert from FITS UT date to Greenwich Sidereal Time */ + char *string); /* FITS date string */ + void dt2gst( /* Convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time */ + double *date, /* Date as yyyy.mmdd */ + double *time); /* Time as hh.mmssxxxx + * If time<0, it is time as -(fraction of a day) */ + double jd2gst( /* Calculate Greenwich Sidereal Time given Julian Date */ + double dj); /* Julian Date (UT) */ + double ts2gst( /* Calculate Greenwich Sidereal Time given Universal Time */ + double tsec); /* Time since 1950.0 in UT seconds */ + char *fd2lst( /* Convert from FITS UT date to Local Sidereal Time */ + char *string); /* FITS date string */ + void dt2lst( /* Convert from UT as yyyy.mmdd hh.mmssss to Local Sidereal Time */ + double *date, /* Date as yyyy.mmdd */ + double *time); /* Time as hh.mmssxxxx + * If time<0, it is time as -(fraction of a day) */ + double ts2lst( /* Calculate Local Sidereal Time given Universal Time */ + double tsec); /* Time since 1950.0 in UT seconds */ + double jd2lst( /* Calculate Local Sidereal Time given Julian Date */ + double dj); /* Julian Date (UT) */ + double eqeqnx( /* Compute equation of eqinoxes from Julian Date */ + double dj); /* Julian Date (UT) */ + char *fd2mst( /* Convert from FITS UT date to Mean Sidereal Time */ + char *string); /* FITS date string */ + double jd2mst( /* Convert from Julian Date to Mean Sidereal Time */ + double dj); /* Julian Date (UT) */ + double jd2mst2( /* Convert from Julian Date to Mean Sidereal Time */ + double dj); /* Julian Date (UT) */ + void dt2mst( /* Convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time */ + double *date, /* Date as yyyy.mmdd */ + double *time); /* Time as hh.mmssxxxx + * If time<0, it is time as -(fraction of a day) */ + double lst2dt( /* Calculate UT as hh.mmsss given UT date and + * Local Sidereal Time */ + double date0, /* UT date as yyyy.mmdd */ + double time0); /* LST as hh.mmssss */ + double lst2jd( /* Calculate UT as Julian Date given UT date and + * Local Sidereal Time */ + double sdj); /* Julian Date of desired day at 0:00 UT + sidereal time */ + char *lst2fd( /* Calculate FITS UT date and time given UT date and + * Local Sidereal Time */ + char *string); /* UT Date, LST as yyyy-mm-ddShh:mm:ss.ss */ + char *gst2fd( /* Calculate FITS UT date and time given Greenwich Sidereal Time */ + char *string); /* UT Date, GST as yyyy-mm-ddShh:mm:ss.ss */ + double gst2jd( /* Calculate FITS UT Julian Date given Greenwich Sidereal Time */ + double sdj); /* UT Date, GST as Julian Date */ + char *mst2fd( /* Calculate FITS UT date and time given Mean Sidereal Time */ + char *string); /* UT Date, MST as yyyy-mm-ddShh:mm:ss.ss */ + double mst2jd( /* Calculate FITS UT Julian Date given Mean Sidereal Time */ + double sdj); /* UT Date, MST as Julian Date */ + double ts2mst( /* Calculate Mean Sidereal Time given Universal Time */ + double tsec); /* time since 1950.0 in UT seconds */ + void setlongitude( /* Longitude for sidereal time in or out */ + double longitude); /* longitude of observatory in degrees (+=west) */ + void compnut( /* Compute nutation in longitude and obliquity and mean obliquity*/ + double dj, /* TDB (loosely ET or TT) as Julian Date */ + double *dpsi, /* Nutation in longitude in radians (returned) */ + double *deps, /* Nutation in obliquity in radians (returned) */ + double *eps0); /* Mean obliquity in radians (returned) */ + + /* Heliocentric Julian Date conversions */ + + double mjd2mhjd( /* Convert from Modified Julian Date to Heliocentric MJD */ + double mjd, /* Julian date (geocentric) */ + double ra, /* Right ascension (degrees) */ + double dec, /* Declination (degrees) */ + int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ + double mjd2hjd( /* Convert from Modified Julian Date to Heliocentric JD */ + double mjd, /* Julian date (geocentric) */ + double ra, /* Right ascension (degrees) */ + double dec, /* Declination (degrees) */ + int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ + double mhjd2mjd( /* Convert from Heliocentric Modified Julian Date to MJD */ + double mhjd, /* Modified Heliocentric Julian date */ + double ra, /* Right ascension (degrees) */ + double dec, /* Declination (degrees) */ + int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ + double jd2hjd( /* Convert from Julian Date to Heliocentric Julian Date */ + double dj, /* Julian date (geocentric) */ + double ra, /* Right ascension (degrees) */ + double dec, /* Declination (degrees) */ + int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ + double hjd2jd( /* Convert from Heliocentric Julian Date to Julian Date */ + double dj, /* Heliocentric Julian date */ + double ra, /* Right ascension (degrees) */ + double dec, /* Declination (degrees) */ + int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ + + void setdatedec( /* Set number of decimal places in FITS dates */ + int nd); /* Number of decimal places in FITS dates */ + +#else /* K&R prototypes */ + +/* FITS file access subroutines in fitsfile.c */ +extern int fitsropen(); +extern char *fitsrhead(); +extern char *fitsrtail(); +extern char *fitsrimage(); +extern char *fitsrfull(); +extern char *fitsrsect(); +extern int fitswhead(); +extern int fitswexhead(); +extern int fitswext(); +extern int fitswhdu(); +extern int fitswimage(); +extern int fitscimage(); +extern int isfits(); /* Return 1 if file is a FITS file */ +extern void fitserr(); /* Print FITS error message to stderr */ +extern void setfitsinherit(); /* Set flag to append primary data header */ +extern int fitsheadsize(); /* Return size of fitsheader in bytes */ + +/* FITS table file access subroutines in fitsfile.c */ +extern int fitsrtopen(); +extern int fitsrthead(); +extern void fitsrtlset(); +extern int fitsrtline(); +extern short ftgeti2(); +extern int ftgeti4(); +extern float ftgetr4(); +extern double ftgetr8(); +extern int ftgetc(); +extern void moveb(); /* Copy nbytes bytes from source+offs to dest+offd */ + +/* IRAF file access subroutines in imhfile.c */ +extern char *irafrhead(); +extern char *irafrimage(); +extern int irafwhead(); +extern int irafwimage(); +extern int isiraf(); +extern char *iraf2fits(); +extern char *fits2iraf(); + +/* Image pixel access subroutines in imio.c */ +extern double getpix(); /* Read one pixel from any data type 2-D array (0,0)*/ +extern double getpix1(); /* Read one pixel from any data type 2-D array (1,1)*/ +extern double maxvec(); /* Get maximum value in vector from a image */ +extern double minvec(); /* Get minimum value in vector from a image */ +extern void putpix(); /* Write one pixel to any data type 2-D array (0,0)*/ +extern void putpix1(); /* Write one pixel to any data type 2-D array (1,1) */ +extern void addpix(); /* Add to one pixel in any data type 2-D array (0,0)*/ +extern void addpix1(); /* Add to one pixel in any data type 2-D array (1,1)*/ +extern void movepix(); /* Move one pixel value between two 2-D arrays (0,0) */ +extern void movepix1(); /* Move one pixel value between two 2-D arrays (1,1) */ +extern void addvec(); /* Add constant to vector from 2-D array */ +extern void multvec(); /* Multiply vector from 2-D array by a constant */ +extern void getvec(); /* Read vector from 2-D array */ +extern void putvec(); /* Write vector into 2-D array */ +extern void fillvec(); /* Write constant into a vector */ +extern void fillvec1(); /* Write constant into a vector */ +extern void imswap(); /* Swap alternating bytes in a vector */ +extern void imswap2(); /* Swap bytes in a vector of 2-byte (short) integers */ +extern void imswap4(); /* Reverse bytes in a vector of 4-byte numbers */ +extern void imswap8(); /* Reverse bytes in a vector of 8-byte numbers */ +extern int imswapped(); /* Return 1 if machine byte order is not FITS order */ + +/* File utilities from fileutil.c */ +extern int getfilelines(); +extern char *getfilebuff(); +extern int getfilesize(); +extern int isimlist(); +extern int isimlistd(); +extern int isfilelist(); +extern int isfile(); +extern int istiff(); +extern int isjpeg(); +extern int isgif(); +extern int first_token(); + +/* Subroutines for access to tokens within a string from fileutil.c */ +int setoken(); /* Tokenize a string for easy decoding */ +int nextoken(); /* Get next token from tokenized string */ +int getoken(); /* Get specified token from tokenized string */ + +/* Subroutines for translating dates and times in dateutil.c */ + +void ang2hr(); /* Fractional degrees to hours as hh:mm:ss.ss */ +void ang2deg(); /* Fractional degrees to degrees as dd:mm:ss.ss */ +double deg2ang(); /* Degrees as dd:mm:ss.ss to fractional degrees */ +double hr2ang(); /* Hours as hh:mm:ss.ss to fractional degrees */ + +void doy2dt(); /* year and day of year to yyyy.mmdd hh.mmss */ +double doy2ep(); /* year and day of year to fractional year (epoch) */ +double doy2epb(); /* year and day of year to Besselian epoch */ +double doy2epj(); /* year and day of year to Julian epoch */ +char *doy2fd(); /* year and day of year to FITS date */ +double doy2jd(); /* year and day of year to Julian date */ +double doy2mjd(); /* year and day of year to modified Julian date */ +double doy2ts(); /* year and day of year to seconds since 1950.0 */ +int doy2tsi(); /* year and day of year to IRAF seconds since 1980-01-01 */ + +time_t doy2tsu(); /* year and day of year to Unix seconds since 1970-01-01 */ +void dt2doy(); /* yyyy.mmdd hh.mmss to year and day of year */ +double dt2ep(); /* yyyy.ddmm and hh.mmsss to fractional year (epoch) */ +double dt2epb(); /* yyyy.ddmm and hh.mmsss to Besselian epoch */ +double dt2epj(); /* yyyy.ddmm and hh.mmsss to Julian epoch */ +char *dt2fd(); /* yyyy.ddmm and hh.mmsss to FITS date string */ +void dt2i(); /* yyyy.ddmm and hh.mmsss to year, month, day, hrs, min, sec */ +double dt2jd(); /* yyyy.ddmm and hh.mmsss to Julian date */ +double dt2mjd(); /* yyyy.ddmm and hh.mmsss to modified Julian date */ +double dt2ts(); /* yyyy.ddmm and hh.mmsss to seconds since 1950.0 */ +int dt2tsi(); /* yyyy.ddmm and hh.mmsss to IRAF seconds since 1980-01-01 */ +time_t dt2tsu(); /* yyyy.ddmm and hh.mmsss to Unix seconds since 1970-01-01 */ + +void ep2dt(); /* Fractional year to yyyy.mmdd hh.mmssss */ +void epb2dt(); /* Besselian epoch to yyyy.mmdd hh.mmssss */ +void epj2dt(); /* Julian epoch to yyyy.mmdd hh.mmssss */ +char *ep2fd(); /* Fractional year to FITS date string yyyy-mm-ddThh:mm:ss.ss */ +char *epb2fd(); /* Besselian epoch to FITS date string yyyy-mm-ddThh:mm:ss.ss */ +char *epj2fd(); /* Julian epoch to FITS date string yyyy-mm-ddThh:mm:ss.ss */ +void ep2i(); /* Fractional year to year, month, day, hours, min., sec. */ +void epb2i(); /* Besselian epoch to year, month, day, hours, min., sec. */ +void epj2i(); /* Julian epoch to year, month, day, hours, min., sec. */ +double ep2jd(); /* Fractional year to Julian Date */ +double epb2jd(); /* Besselian epoch to Julian Date */ +double epj2jd(); /* Julian epoch to Julian Date */ +double ep2mjd(); /* Fractional year to modified Julian Date */ +double epb2mjd(); /* Besselian epoch to modified Julian Date */ +double epj2mjd(); /* Julian epoch to modified Julian Date */ +double ep2epb(); /* Fractional year to Besselian epoch */ +double ep2epj(); /* Fractional year to Julian epoch */ +double epb2epj(); /* Besselian epoch to Julian epoch */ +double epj2epb(); /* Julian epoch to Besselian epoch */ +double epb2ep(); /* Besselian epoch to fractional year */ +double epj2ep(); /* Julian epoch to fractional year */ +double ep2ts(); /* Fractional year to seconds since 1950.0 */ +double epb2ts(); /* Besselian epoch to seconds since 1950.0 */ +double epj2ts(); /* Julian epoch to seconds since 1950.0 */ + +void fd2dt(); /* FITS standard date string to Julian date */ +void fd2doy(); /* FITS standard date string to year, day of year */ +double fd2ep(); /* FITS standard date string to fractional year (epoch) */ +double fd2epb(); /* FITS standard date string to Besselian epoch */ +double fd2epj(); /* FITS standard date string to Julian epoch */ +char *fd2fd(); /* Any FITS standard date string to ISO FITS date string */ +char *fd2of(); /* Any FITS standard date string to old FITS date and time */ +char *fd2ofd(); /* Any FITS standard date string to old FITS date string */ +char *fd2oft(); /* Any FITS standard date string to old FITS time string */ +void fd2i(); /* FITS standard date string to year, mon, day, hrs, min, sec */ +double fd2jd(); /* FITS standard date string to Julian date */ +double fd2mjd(); /* FITS standard date string to modified Julian date */ +double fd2ts(); /* FITS standard date to seconds since 1950-01-01 */ +int fd2tsi(); /* FITS standard date to IRAF seconds since 1980-01-01 */ +time_t fd2tsu(); /* FITS standard date to Unix seconds since 1970-01-01 */ +void jd2doy(); /* Julian date to year and day of year */ +void jd2dt(); /* Julian date to yyyy.mmdd hh.mmssss */ +double jd2ep(); /* Julian date to fractional year */ +double jd2epb(); /* Julian date to Besselian epoch */ +double jd2epj(); /* Julian date to Julian epoch */ +char *jd2fd(); /* Julian date to FITS date string yyyy-mm-ddThh:mm:ss.ss */ +void jd2i(); /* Julian date to year, month, day, hours, min., sec. */ +double jd2mjd(); /* Julian date to modified Julian date */ +double jd2ts(); /* Julian date to seconds since 1950.0 */ +time_t jd2tsu(); /* Julian date to Unix seconds since 1970-01-01T00:00 */ +int jd2tsi(); /* Julian date to IRAF seconds since 1980-01-01T00:00 */ + +void lt2dt(); /* Current local time to date (yyyy.mmdd), time (hh.mmsss) */ +char *lt2fd(); /* Current local time to FITS ISO date string */ +int lt2tsi(); /* Current local time to IRAF seconds since 1980-01-01T00:00 */ +time_t lt2tsu(); /* Current local time to Unix seconds since 1970-01-01T00:00 */ +double lt2ts(); /* Current local time to IRAF seconds since 1950-01-01T00:00 */ + +void mjd2doy(); /* Convert from Modified Julian Date to Day of Year */ +void mjd2dt(); /* Modified Julian date to yyyy.mmdd hh.mmssss */ +double mjd2ep(); /* Modified Julian date to fractional year */ +double mjd2epb(); /* Modified Julian date to Besselian epoch */ +double mjd2epj(); /* Modified Julian date to Julian epoch */ +char *mjd2fd(); /* Modified Julian date to FITS date yyyy-mm-ddThh:mm:ss.ss */ +void mjd2i(); /* Modified Julian date to year, month, day, hours, min, sec */ +double mjd2jd(); /* Modified Julian date to Julian date */ +double mjd2ts(); /* Modified Julian date to seconds since 1950.0 */ + +void ts2dt(); /* Seconds since 1950.0 to yyyy.mmdd hh.mmssss */ +double ts2ep(); /* Seconds since 1950.0 to fractional year */ +double ts2epb(); /* Seconds since 1950.0 to Besselian epoch */ +double ts2epj(); /* Seconds since 1950.0 to Julian epoch */ +char *ts2fd(); /* Seconds since 1950.0 to FITS date, yyyy-mm-ddT00:00:00.000 */ +void ts2i(); /* Seconds since 1950.0 to year, month, day, hours, min, sec */ +double ts2jd(); /* Seconds since 1950.0 to Julian date */ +double ts2mjd(); /* Seconds since 1950.0 to modified Julian date */ +char *tsi2fd(); /* Seconds since 1980-01-01 to FITS standard date string */ +double tsi2ts(); /* Seconds since 1980-01-01 to seconds since 1950-01-01 */ +double tsi2ts(); /* Seconds since 1980-01-01 to seconds since 1950-01-01 */ +void tsi2dt(); /* Seconds since 1980-01-01 to date yyyy.mmdd, time hh.mmssss */ +void tsu2dt(); /* Seconds since 1970-01-01 to date yyyy.ddmm, time hh.mmsss */ +char *tsu2fd(); /* Seconds since 1970-01-01 to FITS standard date string */ +char *tsd2fd(); /* Seconds since start of day to FITS standard time string */ +double tsd2dt(); /* Seconds since start of day to hh.mmsssss */ +double tsu2ts(); /* Seconds since 1970-01-01 to seconds since 1950-01-01 */ +int tsu2tsi(); /* Seconds since 1970-01-01 to local seconds since 1980-01-01 */ +int isdate(); /* Return 1 if string is FITS old or ISO date */ +void ut2dt(); /* Current Universal Time to date (yyyy.mmdd), time (hh.mmsss) */ +void ut2doy(); /* Current Universal Time to year, day of year */ +double ut2ep(); /* Current Universal Time to fractional year */ +double ut2epb(); /* Current Universal Time to Besselian Epoch */ +double ut2epj(); /* Current Universal Time to Julian Epoch */ +char *ut2fd(); /* Current Universal Time to FITS ISO date string */ +double ut2jd(); /* Current Universal Time to Julian Date */ +double ut2mjd(); /* Current Universal Time to Modified Julian Date */ +int ut2tsi(); /* Current UT to IRAF seconds since 1980-01-01T00:00 */ +time_t ut2tsu(); /* Current UT to Unix seconds since 1970-01-01T00:00 */ +double ut2ts(); /* Current UT to IRAF seconds since 1950-01-01T00:00 */ +int sts2c(); /* Replaces spaces in a string with a specified character */ +int stc2s(); /* Replaces a specified character in a string with spaces */ +char *et2fd(); /* ET (or TDT or TT) in FITS format to UT in FITS format */ +char *fd2et(); /* UT in FITS format to ET (or TDT or TT) in FITS format */ +double jd2jed(); /* Convert from Julian Date to Julian Ephemeris Date */ +double jed2jd(); /* Convert from Julian Ephemeris Date to Julian Date */ +double ets2ts(); /* ET in seconds since 1950-01-01 to UT in same format */ +double ts2ets(); /* UT in seconds since 1950-01-01 to ET in same format */ +void dt2et(); /* yyyy.ddmm and hh.mmsss to Ephemeris Time */ +void edt2dt(); /* yyyy.ddmm and hh.mmsss Ephemeris Time to UT */ +double utdt(); /* Compute difference between UT and dynamical time (ET-UT) */ +char *fd2gst(); /* Convert from FITS UT date to Greenwich Sidereal Time */ +void dt2gst(); /* Convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time */ +double jd2gst(); /* Calculate Greenwich Sidereal Time given Julian Date */ +double ts2gst(); /* Calculate Greenwich Sidereal Time given Universal Time */ +char *fd2lst(); /* Convert from FITS UT date to Local Sidereal Time */ +void dt2lst(); /* Convert from UT as yyyy.mmdd hh.mmssss to Local Sidereal Time */ +double ts2lst(); /* Calculate Local Sidereal Time given Universal Time */ +double jd2lst(); /* Calculate Local Sidereal Time given Julian Date */ +double eqeqnx(); /* Compute equation of eqinoxes from Julian Date */ +char *fd2mst(); /* Convert from FITS UT date to Mean Sidereal Time */ +double jd2mst(); /* Convert from Julian Date to Mean Sidereal Time */ +double jd2mst2(); /* Convert from Julian Date to Mean Sidereal Time */ +void dt2mst(); /* Convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time */ +double lst2ts(); /* Calculate Universal Time given Local Sidereal Time */ +double lst2dt(); /* Calculate UT as yyyy.mmdd hh.mmsss given UT date and Local Sidereal Time */ +double lst2jd(); /* Calculate UT as Julian Date given UT date and Local Sidereal Time */ +char *lst2fd(); /* Calculate FITS UT date and time given UT date and Local Sidereal Time */ +char *gst2fd(); /* Calculate FITS UT date and time given Greenwich Sidereal Time */ +double gst2jd(); /* Calculate FITS UT Julian Date given Greenwich Sidereal Time */ +char *mst2fd(); /* Calculate FITS UT date and time given Mean Sidereal Time */ +double mst2jd(); /* Calculate FITS UT Julian Date given Mean Sidereal Time */ +char *fd2mst(); /* Convert from FITS UT date to Mean Sidereal Time */ +void dt2mst(); /* Convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time */ +double ts2mst(); /* Calculate Mean Sidereal Time given Universal Time */ +double mjd2mhjd(); /* Convert from Modified Julian Date to Heliocentric MJD */ +double mjd2hjd(); /* Convert from Modified Julian Date to Heliocentric JD */ +double mhjd2mjd(); /* Convert from Heliocentric Modified Julian Date to MJD */ +double jd2hjd(); /* Convert from Julian Date to Heliocentric Julian Date */ +double jd2mhjd(); /* Convert from Julian Date to Modified Heliocentric JD */ +double hjd2jd(); /* Convert from Heliocentric Julian Date to Julian Date */ +double hjd2mjd(); /* Convert from Heliocentric Julian Date to Modified JD */ +double hjd2mhjd(); /* Convert from Heliocentric Julian Date to Modified HJD */ +void setdatedec(); /* Set number of decimal places in FITS dates */ +void setlongitude(); /* Longitude for sidereal time in or out */ + +void compnut(); /* Compute nutation in longitude and obliquity and mean obliquity*/ + +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* fitsfile_h_ */ + +/* May 31 1996 Use stream I/O for reading as well as writing + * Jun 12 1996 Add byte-swapping subroutines + * Jul 10 1996 FITS header now allocated in subroutines + * Jul 17 1996 Add FITS table column extraction subroutines + * Aug 6 1996 Add MOVEPIX, HDEL and HCHANGE declarations + * + * Oct 10 1997 FITS file opening subroutines now return int instead of FILE * + * + * May 27 1998 Split off fitsio and imhio subroutines to fitsio.h + * Jun 4 1998 Change fits2iraf from int to int * + * Jul 24 1998 Make IRAF header char instead of int + * Aug 18 1998 Change name to fitsfile.h from fitsio.h + * Oct 5 1998 Add isiraf() and isfits() + * Oct 7 1998 Note separation of imhfile.c into two files + * + * Jul 15 1999 Add fileutil.c subroutines + * Sep 28 1999 Add (1,1)-based image access subroutines + * Oct 21 1999 Add fitswhead() + * Nov 2 1999 Add date utilities from wcscat.h + * Nov 23 1999 Add fitscimage() + * Dec 15 1999 Fix misdeclaration of *2fd() subroutines, add fd2i(), dt2i() + * Dec 20 1999 Add isdate() + * + * Jan 20 2000 Add conversions to and from Besselian and Julian epochs + * Jan 21 2000 Add conversions to old FITS date and time + * Jan 26 2000 Add conversion to modified Julian date (JD - 2400000.5 + * Mar 22 2000 Add lt2* and ut2* to get current time as local and UT + * Mar 24 2000 Add tsi2* and tsu2* to convert IRAF and Unix seconds + * Sep 8 2000 Improve comments + * + * Apr 24 2001 Add length of column name to column data structure + * May 22 2001 Add day of year date conversion subroutines + * Sep 25 2001 Add isfilelist() and isfile() + * + * Jan 8 2002 Add sts2c() and stc2s() + * Apr 8 2002 Change all long declarations to time_t for compatibility + * Jun 18 2002 Add fitserr() to print error messages + * Aug 30 2002 Add Ephemeris Time date conversions + * Sep 10 2002 Add Sidereal Time conversions + * Oct 21 2002 Add fitsrsect() to read sections of FITS images + * + * Mar 5 2003 Add isimlistd() to check image lists with root directory + * Aug 20 2003 Add fitsrfull() to read n-dimensional simple FITS images + * + * Feb 27 2004 Add fillvec() and fillvec1() + * May 3 2004 Add setfitsinherit() + * May 6 2004 Add fitswexhead() + * Aug 27 2004 Add fitsheadsize() + * + * Oct 14 2005 Add tsd2fd(), tsd2dt(), epj2ep(), epb2ep(), tsi2dt() + * + * Feb 23 2006 Add fitsrtail() to read appended FITS header + * Feb 23 2006 Add istiff(), isjpeg(), isgif() to check TIFF, JPEG, GIF files + * Sep 6 2006 Add heliocentric time conversions + * Oct 5 2006 Add local sidereal time conversions + * + * Jan 9 2007 Add ANSI prototypes + * Jan 11 2007 Add token subroutines from catutil.c/wcscat.h to fileutil.c + * Jun 11 2007 Add minvec() subroutine in imio.c + * Nov 28 2007 Add kform format to FITS table keyword data structure + * + * Sep 8 2008 Add ag2hr(), ang2deg(), deg2ang(), and hr2ang() + * + * Sep 25 2009 Add moveb() + */ diff --git a/astroem/fitshead.h b/astroem/fitshead.h new file mode 100644 index 00000000..1212709c --- /dev/null +++ b/astroem/fitshead.h @@ -0,0 +1,438 @@ +/*** File fitshead.h FITS header access subroutines + *** January 9, 2007 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1996-2007 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + */ + +/* Declarations for subroutines in hget.c, hput.c, and iget.c */ + +#ifndef _fitshead_h_ +#define _fitshead_h_ + +#include + +#ifdef __cplusplus /* C++ prototypes */ +extern "C" { +#endif + + +#ifdef __STDC__ /* Full ANSI prototypes */ + +/* Subroutines in hget.c */ + int hgeti2( /* Extract short value from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + short* val); /* short integer value (returned) */ + int hgeti4c( /* Extract int value from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + const char* wchar, /* WCS to use (A-Z or null) */ + int* val); /* integer value (returned) */ + int hgeti4( /* Extract int value from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + int* val); /* integer value (returned) */ + int hgetr4( /* Extract float value from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + float* val); /* float value (returned) */ + int hgetr8c( /* Extract double value from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + const char* wchar, /* WCS to use (A-Z or null) */ + double* val); /* double value (returned) */ + int hgetr8( /* Extract double value from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + double* val); /* double value (returned) */ + int hgetra( /* Extract right ascension from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + double* ra); /* RA in degrees (returned) */ + int hgetdec( /* Extract declination from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + double* dec); /* Dec in degrees (returned) */ + int hgetdate( /* Extract date from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + double* date); /* Date in fractional years (returned) */ + int hgetl( /* Extract boolean value from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + int* lval); /* 1 if T, 0 if F (returned) */ + int hgetsc( /* Extract string value from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + const char* wchar, /* WCS to use (A-Z or null) */ + const int lstr, /* maximum length of returned string */ + char* string); /* null-terminated string value (returned) */ + int hgets( /* Extract string value from FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + const int lstr, /* maximum length of returned string */ + char* string); /* null-terminated string value (returned) */ + int hgetm ( /* Extract string from multiple keywords */ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + const int lstr, /* maximum length of returned string */ + char* string); /* null-terminated string value (returned) */ + int hgetndec( /* Find number of decimal places in FITS value*/ + const char* hstring, /* FITS header string */ + const char* keyword, /* FITS keyword */ + int* ndec); /* number of decimal places (returned) */ + + char* hgetc( /* Return pointer to value for FITS keyword */ + const char* hstring, /* FITS header string */ + const char* keyword); /* FITS keyword */ + + char* ksearch( /* Return pointer to keyword in FITS header */ + const char* hstring, /* FITS header string */ + const char* keyword); /* FITS keyword */ + char *blsearch ( + const char* hstring, /* FITS header string */ + const char* keyword); /* FITS keyword */ + + char *strsrch ( /* Find string s2 within string s1 */ + const char* s1, /* String to search */ + const char* s2); /* String to look for */ + char *strnsrch ( /* Find string s2 within string s1 */ + const char* s1, /* String to search */ + const char* s2, /* String to look for */ + const int ls1); /* Length of string being searched */ + + char *strcsrch ( /* Find string s2 within string s1 (no case) */ + const char* s1, /* String to search */ + const char* s2); /* String to look for */ + char *strncsrch ( /* Find string s2 within string s1 (no case) */ + const char* s1, /* String to search */ + const char* s2, /* String to look for */ + const int ls1); /* Length of string being searched */ + + int hlength( /* Set length of unterminated FITS header */ + const char *header, /* FITS header */ + const int lhead); /* Allocated length of FITS header */ + int gethlength( /* Get length of current FITS header */ + char* header); /* FITS header */ + + double str2ra( /* Return RA in degrees from string */ + const char* in); /* Character string (hh:mm:ss.sss or dd.dddd) */ + double str2dec( /* Return Dec in degrees from string */ + const char* in); /* Character string (dd:mm:ss.sss or dd.dddd) */ + + int isnum( /* Return 1 if number, else 0 */ + const char* string); /* Character string which may be a number */ + int notnum( /* Return 0 if number, else 1 */ + const char* string); /* Character string which may be a number */ + int numdec( /* Return number of decimal places in number */ + const char* string); /* Character string which may be a number */ + void strfix( /* Clean up extraneous characters in string */ + char* string, /* Character string which may be a number */ + int fillblank, /* If 1, blanks are replaced by underscores */ + int dropzero); /* If 1, drop trailing zeroes from string */ + + char *getltime(void); /* Return current local time in ISO format */ + char *getutime(void); /* Return current UT as an ISO-format string */ + +/* Subroutines in iget.c */ + int mgetstr( /* Extract string from multiline FITS keyword */ + const char* hstring, /* FITS header string */ + const char* mkey, /* FITS keyword root _n added for extra lines */ + const char* keyword, /* IRAF keyword */ + const int lstr, /* maximum length of returned string */ + char* string); /* null-terminated string value (returned) */ + int mgeti4( /* Extract int from multiline FITS keyword */ + const char* hstring, /* FITS header string */ + const char* mkey, /* FITS keyword root _n added for extra lines */ + const char* keyword, /* IRAF keyword */ + int* ival); /* int keyword value (returned) */ + int mgetr8( /* Extract double from multiline FITS keyword */ + const char* hstring, /* FITS header string */ + const char* mkey, /* FITS keyword root _n added for extra lines */ + const char* keyword, /* IRAF keyword */ + double* dval); /* double keyword value (returned) */ + int igeti4( /* Extract int from IRAF keyword string */ + const char* hstring, /* Multiline IRAF keyword string value */ + const char* keyword, /* IRAF keyword */ + int* val); /* int value (returned) */ + int igetr4( /* Extract float from IRAF keyword string */ + const char* hstring, /* Multiline IRAF keyword string value */ + const char* keyword, /* IRAF keyword */ + float* val); /* float value (returned) */ + int igetr8( /* Extract double from IRAF keyword string */ + const char* hstring, /* Multiline IRAF keyword string value */ + const char* keyword, /* IRAF keyword */ + double* val); /* double value (returned) */ + int igets( /* Extract string from IRAF keyword string */ + const char* hstring, /* Multiline IRAF keyword string value */ + const char* keyword, /* IRAF keyword */ + const int lstr, /* maximum length of returned string */ + char* string); /* null-terminated string value (returned) */ + char *igetc( /* Extract string from IRAF keyword string */ + const char* hstring, /* Multiline IRAF keyword string value */ + const char* keyword); /* IRAF keyword */ + +/* Subroutines in hput.c */ +/* All hput* routines return 0 if successful, else -1 */ + int hputi2( /* Implant short value into FITS header */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + short ival); /* short value */ + int hputi4( /* Implant int value into FITS header */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + const int ival); /* int value */ + int hputr4( /* Implant float value into FITS header */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + const float* rval); /* float (4 byte) value */ + int hputr8( /* Implant short into FITS header */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + const double dval); /* double value */ + int hputnr8( /* double with specified number of decimal places */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + const int ndec, /* Number of decimal places in keyword value */ + const double dval); /* double value */ + int hputs( /* Quoted character string into FITS header */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + const char* cval); /* Character string value */ + int hputm( /* Quoted character string, mutiple keywords */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + const char* cval); /* Character string value */ + int hputcom( /* Add comment to keyword line in FITS header */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + const char* comment); /* Comment string */ + int hputra( /* Right ascension in degrees into hh:mm:ss.sss */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + const double ra); /* Right ascension in degrees */ + int hputdec( /* Declination in degrees into dd:mm:ss.ss */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + const double dec); /* Declination in degrees */ + int hputl( /* Implant boolean value into FITS header */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + const int lval); /* 0->F, else ->T */ + int hputc( /* Implant character string without quotes */ + char* hstring, /* FITS header string (modified) */ + const char* keyword, /* FITS keyword */ + const char* cval); /* Character string value */ + + int hdel( /* Delete a keyword line from a FITS header */ + char* hstring, /* FITS header string (modified) */ + const char* keyword); /* FITS keyword to delete */ + int hadd( /* Add a keyword line from a FITS header */ + char* hplace, /* Location in FITS header string (modified) */ + const char* keyword); /* FITS keyword to add */ + int hchange( /* Change a keyword name in a FITS header */ + char* hstring, /* FITS header string (modified) */ + const char* keyword1, /* Current FITS keyword name */ + const char* keyword2); /* New FITS keyword name */ + + void ra2str( /* Convert degrees to hh:mm:ss.ss */ + char *string, /* Character string (returned) */ + int lstr, /* Length of string */ + const double ra, /* Right ascension in degrees */ + const int ndec); /* Number of decimal places in seconds */ + void dec2str( /* Convert degrees to dd:mm:ss.ss */ + char *string, /* Character string (returned) */ + int lstr, /* Length of string */ + const double dec, /* Declination in degrees */ + const int ndec); /* Number of decimal places in arcseconds */ + void deg2str( /* Format angle into decimal degrees string */ + char *string, /* Character string (returned) */ + int lstr, /* Length of string */ + const double deg, /* Angle in degrees */ + const int ndec); /* Number of decimal places in degrees */ + void num2str( /* Format number into string */ + char *string, /* Character string (returned) */ + const double num, /* Number */ + const int field, /* Total field size in characters */ + const int ndec); /* Number of decimal places */ + void setheadshrink( /* 0 to keep blank line when keyword deleted */ + const int hsh); /* 1 to shrink header by one line */ + void setleaveblank( /* 1 to keep blank line where keyword deleted */ + const int hsh); /* 0 to shrink header by one line */ + +#else /* K&R prototypes */ + +/* Subroutines in hget.c */ + +/* Extract a value from a FITS header for given keyword */ +extern int hgeti4(); /* int (Multiple WCS) */ +extern int hgeti4c(); /* int */ +extern int hgeti2(); /* short */ +extern int hgetr4(); /* float */ +extern int hgetr8(); /* double */ +extern int hgetr8c(); /* double (Multiple WCS) */ +extern int hgetra(); /* Right ascension in degrees from string */ +extern int hgetdec(); /* Declination in degrees from string */ +extern int hgetdate(); /* Date in years from FITS date string */ +extern int hgetl(); /* T->1, F->0 from FITS logical entry */ +extern int hgets(); /* Previously allocated string */ +extern int hgetsc(); /* Previously allocated string (Multiple WCS) */ +extern int hgetm(); /* Previously allocated string from multiple keywords */ +extern char *hgetc(); /* Return pointer to string */ +extern int hgetndec(); /* Number of decimal places in keyword value */ + +/* Subroutines to convert strings to RA and Dec in degrees */ +extern double str2ra(); +extern double str2dec(); + +/* Check to see whether a string is a number or not */ +extern int isnum(); +extern int notnum(); +extern int decnum(); + +/* Find given keyword entry in FITS header */ +extern char *ksearch(); + +/* Find beginning of fillable blank line before FITS header keyword */ +extern char *blsearch(); + +/* Search for substring s2 within string s1 */ +extern char *strsrch (); /* s1 null-terminated */ +extern char *strnsrch (); /* s1 ls1 characters long */ +extern char *strcsrch (); /* s1 null-terminated (case-insensitive) */ +extern char *strncsrch (); /* s1 ls1 characters long (case-insensitive) */ +extern void strfix(); /* Drop or change extraneous characters in string */ + +/* Set length of header which is not null-terminated */ +extern int hlength(); + +/* Get length of current FITS header */ +extern int gethlength(); + +/* Subroutines in iget.c */ +extern int mgetstr(); /* Previously allocated string from multiline keyword */ +extern int mgetr8(); /* double from multiline keyword */ +extern int mgeti4(); /* int from multiline keyword */ +extern int igeti4(); /* long integer from IRAF compound keyword value */ +extern int igetr4(); /* real from IRAF compound keyword value */ +extern int igetr8(); /* double from IRAF compound keyword value */ +extern int igets(); /* character string from IRAF compound keyword value */ +extern char *igetc(); /* Extract string from IRAF keyword string */ + +/* Subroutines in hput.c */ + +/* Implant a value into a FITS header for given keyword */ +extern int hputi4(); /* int */ +extern int hputi2(); /* short */ +extern int hputr4(); /* float */ +extern int hputr8(); /* double */ +extern int hputnr8(); /* double with specified number of decimal places */ +extern int hputra(); /* Right ascension in degrees into hh:mm:ss.sss */ +extern int hputdec(); /* Declination in degrees into dd:mm:ss.ss */ +extern int hputl(); /* 0 -> F, else T FITS logical entry */ +extern int hputs(); /* Quoted character string */ +extern int hputm(); /* Quoted character string into mutiple keywords */ +extern int hputc(); /* Character string without quotes (returns 0 if OK) */ +extern int hputcom(); /* Comment after keyword=value (returns 0 if OK) */ + +extern int hdel(); /* Delete a keyword line from a FITS header */ +extern int hadd(); /* Add a keyword line to a FITS header */ +extern int hchange(); /* Change a keyword name in a FITS header */ +extern void setheadshrink(); /* Set flag for deleted keyword space disposition*/ +extern void setleaveblank(); /* Set flag for deleted keyword space disposition*/ + +/* Subroutines to convert RA and Dec in degrees to strings */ +extern void ra2str(); +extern void dec2str(); + +extern void deg2str(); +extern void num2str(); +extern int numdec(); /* Return number of decimal places in number */ + +extern char *getltime(); /* Return current local time in ISO format */ +extern char *getutime(); /* Return current UT as an ISO-format string */ + +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* fitshead_h_ */ + +/* Apr 26 1996 Add HGETDATE to get year from date string + * May 22 1996 Return double from STR2RA and STR2DEC + * May 31 1996 Use stream I/O for reading as well as writing + * Jun 12 1996 Add byte-swapping subroutines + * Jul 10 1996 FITS header now allocated in subroutines + * Jul 17 1996 Add FITS table column extraction subroutines + * Jul 19 1996 Add declarations for header implanting subroutines + * Aug 5 1996 Add HLENGTH for FITS headers which are not null-terminated + * Aug 5 1996 Add STRNSRCH for FITS headers which are not null-terminated + * Aug 6 1996 Add HPUTNR8 to save a specified number of decimal places + * Aug 6 1996 Add MOVEPIX, HDEL and HCHANGE declarations + * Nov 1 1996 Add DEG2STR + * Dec 12 1996 Add ISNUM + * + * Oct 10 1997 FITS file opening subroutines now return int instead of FILE * + * + * Mar 12 1998 Add NOTNUM + * Apr 30 1998 Clean up declarations and add more comments + * May 12 1998 Add MGETS, MGETR8, MGETI4 for IRAF multi-line keywords + * May 26 1998 Add HGETNDEC for number of decimal places in keyword value + * May 27 1998 Add BLSEARCH to find usable blank lines in header + * May 27 1998 Split off fitsio and imhio subroutines to fitsio.h + * May 27 1998 Add all subroutines in hget.c, hput.c, and iget.c to C++ dec. + * Jun 24 1998 Add string lengths to ra2str(), dec2str, and deg2str() calls + * Jun 25 1998 Fix other C++ declarations with added string lengths + * Aug 31 1998 Add current date subroutines getltime() and getutime() + * Oct 28 1998 Add missing hgetc() to non c++ declarations + * + * Oct 6 1999 Add gethlength() to return current size of header + * Oct 14 1999 All HPUT subroutines now return an error code, 0 if OK, else -1 + * Oct 15 1999 Add hputcom() declaration + * Oct 21 1999 Add hgetm() declaration + * + * Mar 22 2000 Add int to iget*() declarations + * Mar 27 2000 Add hputm() declaration + * + * Apr 3 2002 Add hgeti4c(), hgetr8c(), and hgetsc() + * Apr 8 2002 Include sys/types.h + * Aug 30 2002 Add strcsrch() and strncsrch() + * + * Sep 23 2003 Change mgets() to mgetstr() to avoid name collision at UCO Lick + * Oct 20 2003 Add numdec() to return the number of decimal places in a string + * + * Feb 26 2004 Add igetc(), formerly internal to iget.c + * Jul 1 2004 Add setheadshrink() for hdel() + * Aug 30 2004 Add numdec() to non-C++ declarations + * + * May 22 2006 Add setleaveblank() to leave blank line where keyword is deleted + * Jun 28 2006 Add strfix() to clean up characters in strings + * Nov 29 2006 Drop semicolon at end of C++ ifdef + * + * Jan 9 2007 Fix declarations so ANSI prototypes are not just for C++ + */ diff --git a/astroem/hget.c b/astroem/hget.c new file mode 100644 index 00000000..653e8ebf --- /dev/null +++ b/astroem/hget.c @@ -0,0 +1,1913 @@ +/*** File libwcs/hget.c + *** May 19, 2011 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1994-2011 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + + * Module: hget.c (Get FITS Header parameter values) + * Purpose: Extract values for variables from FITS header string + * Subroutine: hgeti2 (hstring,keyword,ival) returns short integer + * Subroutine: hgeti4c (hstring,keyword,wchar,ival) returns long integer + * Subroutine: hgeti4 (hstring,keyword,ival) returns long integer + * Subroutine: hgetr4 (hstring,keyword,rval) returns real + * Subroutine: hgetra (hstring,keyword,ra) returns double RA in degrees + * Subroutine: hgetdec (hstring,keyword,dec) returns double Dec in degrees + * Subroutine: hgetr8c (hstring,keyword,wchar,dval) returns double + * Subroutine: hgetr8 (hstring,keyword,dval) returns double + * Subroutine: hgetl (hstring,keyword,lval) returns logical int (0=F, 1=T) + * Subroutine: hgetsc (hstring,keyword,wchar,lstr,str) returns character string + * Subroutine: hgets (hstring,keyword, lstr, str) returns character string + * Subroutine: hgetm (hstring,keyword, lstr, str) returns multi-keyword string + * Subroutine: hgetdate (hstring,keyword,date) returns date as fractional year + * Subroutine: hgetndec (hstring, keyword, ndec) returns number of dec. places + * Subroutine: hgetc (hstring,keyword) returns character string + * Subroutine: blsearch (hstring,keyword) returns pointer to blank lines + before keyword + * Subroutine: ksearch (hstring,keyword) returns pointer to header string entry + * Subroutine: str2ra (in) converts string to right ascension in degrees + * Subroutine: str2dec (in) converts string to declination in degrees + * Subroutine: strsrch (s1, s2) finds string s2 in null-terminated string s1 + * Subroutine: strnsrch (s1, s2, ls1) finds string s2 in ls1-byte string s1 + * Subroutine: hlength (header,lhead) sets length of FITS header for searching + * Subroutine: isnum (string) returns 1 if integer, 2 if fp number, else 0 + * Subroutine: notnum (string) returns 0 if number, else 1 + * Subroutine: numdec (string) returns number of decimal places in numeric string + * Subroutine: strfix (string,blankfill,zerodrop) removes extraneous characters + */ + +#include /* NULL, strlen, strstr, strcpy */ +#include +#include "fitshead.h" /* FITS header extraction subroutines */ +#include +#ifndef VMS +#include +#else +#define INT_MAX 2147483647 /* Biggest number that can fit in long */ +#define SHRT_MAX 32767 +#endif +#define VLENGTH 81 + +#ifdef USE_SAOLIB +static int use_saolib=0; +#endif + +char *hgetc (); + +static char val[VLENGTH+1]; +static int multiline = 0; + +static int lhead0 = 0; /* Length of header string */ + +/* Set the length of the header string, if not terminated by NULL */ +int +hlength (header, lhead) +const char *header; /* FITS header */ +int lhead; /* Maximum length of FITS header */ +{ + char *hend; + if (lhead > 0) + lhead0 = lhead; + else { + lhead0 = 0; + hend = ksearch (header,"END"); + lhead0 = hend + 80 - header; + } + return (lhead0); +} + +/* Return the length of the header string, computing it if lhead0 not set */ +int +gethlength (header) +char *header; /* FITS header */ +{ + if (lhead0 > 0) + return (lhead0); + else + return (hlength (header, 0)); +} + + +/* Extract Integer*4 value for variable from FITS header string */ + +int +hgeti4c (hstring,keyword,wchar,ival) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for + a line beginning with this string. if "[n]" is + present, the n'th token in the value is returned. + (the first 8 characters must be unique) */ +const char *wchar; /* Character of multiple WCS header; =0 if unused */ +int *ival; /* Keyword value returned */ +{ + char keyword1[16]; + int lkey; + + if (wchar[0] < (char) 64) + return (hgeti4 (hstring, keyword, ival)); + else { + strcpy (keyword1, keyword); + lkey = strlen (keyword); + keyword1[lkey] = wchar[0]; + keyword1[lkey+1] = (char) 0; + return (hgeti4 (hstring, keyword1, ival)); + } +} + + +/* Extract long value for variable from FITS header string */ + +int +hgeti4 (hstring,keyword,ival) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +int *ival; +{ + char *value; + double dval; + int minint; + int lval; + char *dchar; + + /* Get value and comment from header string */ + value = hgetc (hstring,keyword); + + /* Translate value from ASCII to binary */ + if (value != NULL) { + if (value[0] == '#') value++; + minint = -INT_MAX - 1; + lval = strlen (value); + if (lval > VLENGTH) { + strncpy (val, value, VLENGTH); + val[VLENGTH] = (char) 0; + } + else + strcpy (val, value); + if (isnum (val) == 2) { + if ((dchar = strchr (val, 'D'))) + *dchar = 'e'; + if ((dchar = strchr (val, 'd'))) + *dchar = 'e'; + if ((dchar = strchr (val, 'E'))) + *dchar = 'e'; + } + dval = atof (val); + if (dval+0.001 > INT_MAX) + *ival = INT_MAX; + else if (dval >= 0) + *ival = (int) (dval + 0.001); + else if (dval-0.001 < minint) + *ival = minint; + else + *ival = (int) (dval - 0.001); + return (1); + } + else { + return (0); + } +} + + +/* Extract integer*2 value for variable from fits header string */ + +int +hgeti2 (hstring,keyword,ival) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +short *ival; +{ + char *value; + double dval; + int minshort; + int lval; + char *dchar; + + /* Get value and comment from header string */ + value = hgetc (hstring,keyword); + + /* Translate value from ASCII to binary */ + if (value != NULL) { + if (value[0] == '#') value++; + lval = strlen (value); + if (lval > VLENGTH) { + strncpy (val, value, VLENGTH); + val[VLENGTH] = (char) 0; + } + else + strcpy (val, value); + if (isnum (val) == 2) { + if ((dchar = strchr (val, 'D'))) + *dchar = 'e'; + if ((dchar = strchr (val, 'd'))) + *dchar = 'e'; + if ((dchar = strchr (val, 'E'))) + *dchar = 'e'; + } + dval = atof (val); + minshort = -SHRT_MAX - 1; + if (dval+0.001 > SHRT_MAX) + *ival = SHRT_MAX; + else if (dval >= 0) + *ival = (short) (dval + 0.001); + else if (dval-0.001 < minshort) + *ival = minshort; + else + *ival = (short) (dval - 0.001); + return (1); + } + else { + return (0); + } +} + +/* Extract real value for variable from FITS header string */ + +int +hgetr4 (hstring,keyword,rval) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +float *rval; +{ + char *value; + int lval; + char *dchar; + + /* Get value and comment from header string */ + value = hgetc (hstring,keyword); + + /* translate value from ASCII to binary */ + if (value != NULL) { + if (value[0] == '#') value++; + lval = strlen (value); + if (lval > VLENGTH) { + strncpy (val, value, VLENGTH); + val[VLENGTH] = (char) 0; + } + else + strcpy (val, value); + if (isnum (val) == 2) { + if ((dchar = strchr (val, 'D'))) + *dchar = 'e'; + if ((dchar = strchr (val, 'd'))) + *dchar = 'e'; + if ((dchar = strchr (val, 'E'))) + *dchar = 'e'; + } + *rval = (float) atof (val); + return (1); + } + else { + return (0); + } +} + + +/* Extract real*8 right ascension in degrees from FITS header string */ + +int +hgetra (hstring,keyword,dval) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +double *dval; /* Right ascension in degrees (returned) */ +{ + char *value; + + /* Get value from header string */ + value = hgetc (hstring,keyword); + + /* Translate value from ASCII colon-delimited string to binary */ + if (value != NULL) { + *dval = str2ra (value); + return (1); + } + else + return (0); +} + + +/* Extract real*8 declination in degrees from FITS header string */ + +int +hgetdec (hstring,keyword,dval) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +double *dval; /* Right ascension in degrees (returned) */ +{ + char *value; + + /* Get value from header string */ + value = hgetc (hstring,keyword); + + /* Translate value from ASCII colon-delimited string to binary */ + if (value != NULL) { + *dval = str2dec (value); + return (1); + } + else + return (0); +} + + +/* Extract real*8 value for variable from FITS header string */ + +int +hgetr8c (hstring,keyword,wchar,dval) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for + a line beginning with this string. if "[n]" is + present, the n'th token in the value is returned. + (the first 8 characters must be unique) */ +const char *wchar; /* Character of multiple WCS header; =0 if unused */ +double *dval; /* Keyword value returned */ +{ + char keyword1[16]; + int lkey; + + if (wchar[0] < (char) 64) + return (hgetr8 (hstring, keyword, dval)); + else { + strcpy (keyword1, keyword); + lkey = strlen (keyword); + keyword1[lkey] = wchar[0]; + keyword1[lkey+1] = (char) 0; + return (hgetr8 (hstring, keyword1, dval)); + } +} + + + +/* Extract real*8 value for variable from FITS header string */ + +int +hgetr8 (hstring,keyword,dval) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +double *dval; +{ + char *value; + int lval; + char *dchar; + + /* Get value and comment from header string */ + value = hgetc (hstring,keyword); + + /* Translate value from ASCII to binary */ + if (value != NULL) { + if (value[0] == '#') value++; + lval = strlen (value); + if (lval > VLENGTH) { + strncpy (val, value, VLENGTH); + val[VLENGTH] = (char) 0; + } + else + strcpy (val, value); + if (isnum (val) == 2) { + if ((dchar = strchr (val, 'D'))) + *dchar = 'e'; + if ((dchar = strchr (val, 'd'))) + *dchar = 'e'; + if ((dchar = strchr (val, 'E'))) + *dchar = 'e'; + } + *dval = atof (val); + return (1); + } + else { + return (0); + } +} + + +/* Extract logical value for variable from FITS header string */ + +int +hgetl (hstring,keyword,ival) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +int *ival; +{ + char *value; + char newval; + int lval; + + /* Get value and comment from header string */ + value = hgetc (hstring,keyword); + + /* Translate value from ASCII to binary */ + if (value != NULL) { + lval = strlen (value); + if (lval > VLENGTH) { + strncpy (val, value, VLENGTH); + val[VLENGTH] = (char) 0; + } + else + strcpy (val, value); + newval = val[0]; + if (newval == 't' || newval == 'T') + *ival = 1; + else + *ival = 0; + return (1); + } + else { + return (0); + } +} + + +/* Extract real*8 date from FITS header string (dd/mm/yy or dd-mm-yy) */ + +int +hgetdate (hstring,keyword,dval) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +double *dval; +{ + double yeardays, seconds, fday; + char *value,*sstr, *dstr, *tstr, *cstr, *nval; + int year, month, day, yday, i, hours, minutes; + static int mday[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + + /* Get value and comment from header string */ + value = hgetc (hstring,keyword); + + /* Translate value from ASCII to binary */ + if (value != NULL) { + sstr = strchr (value,'/'); + dstr = strchr (value,'-'); + + /* Original FITS date format: dd/mm/yy */ + if (sstr > value) { + *sstr = '\0'; + day = (int) atof (value); + *sstr = '/'; + nval = sstr + 1; + sstr = strchr (nval,'/'); + if (sstr == NULL) + sstr = strchr (nval,'-'); + if (sstr > value) { + *sstr = '\0'; + month = (int) atof (nval); + *sstr = '/'; + nval = sstr + 1; + year = (int) atof (nval); + if (day > 31) { + yday = year; + year = day; + day = yday; + } + if (year >= 0 && year <= 49) + year = year + 2000; + else if (year < 100) + year = year + 1900; + if ((year % 4) == 0) + mday[1] = 29; + else + mday[1] = 28; + if ((year % 100) == 0 && (year % 400) != 0) + mday[1] = 28; + if (day > mday[month-1]) + day = mday[month-1]; + else if (day < 1) + day = 1; + if (mday[1] == 28) + yeardays = 365.0; + else + yeardays = 366.0; + yday = day - 1; + for (i = 0; i < month-1; i++) + yday = yday + mday[i]; + *dval = (double) year + ((double)yday / yeardays); + return (1); + } + else + return (0); + } + + /* New FITS date format: yyyy-mm-ddThh:mm:ss[.sss] */ + else if (dstr > value) { + *dstr = '\0'; + year = (int) atof (value); + *dstr = '-'; + nval = dstr + 1; + dstr = strchr (nval,'-'); + month = 1; + day = 1; + tstr = NULL; + if (dstr > value) { + *dstr = '\0'; + month = (int) atof (nval); + *dstr = '-'; + nval = dstr + 1; + tstr = strchr (nval,'T'); + if (tstr > value) + *tstr = '\0'; + day = (int) atof (nval); + if (tstr > value) + *tstr = 'T'; + } + + /* If year is < 32, it is really day of month in old format */ + if (year < 32) { + i = year; + year = day + 1900; + day = i; + } + + if ((year % 4) == 0) + mday[1] = 29; + else + mday[1] = 28; + if ((year % 100) == 0 && (year % 400) != 0) + mday[1] = 28; + if (day > mday[month-1]) + day = mday[month-1]; + else if (day < 1) + day = 1; + if (mday[1] == 28) + yeardays = 365.0; + else + yeardays = 366.0; + yday = day - 1; + for (i = 0; i < month-1; i++) + yday = yday + mday[i]; + *dval = (double) year + ((double)yday / yeardays); + + /* Extract time, if it is present */ + if (tstr > value) { + nval = tstr + 1; + hours = 0.0; + minutes = 0.0; + seconds = 0.0; + cstr = strchr (nval,':'); + if (cstr > value) { + *cstr = '\0'; + hours = (int) atof (nval); + *cstr = ':'; + nval = cstr + 1; + cstr = strchr (nval,':'); + if (cstr > value) { + *cstr = '\0'; + minutes = (int) atof (nval); + *cstr = ':'; + nval = cstr + 1; + seconds = atof (nval); + } + else { + minutes = (int) atof (nval); + seconds = 0.0; + } + } + fday = ((3.6e3 * (double)hours) + (6.e1 * (double)minutes) + + seconds) / 8.64e4; + *dval = *dval + (fday / yeardays); + } + return (1); + } + else + return (0); + } + else + return (0); +} + + +/* Extract IRAF multiple-keyword string value from FITS header string */ + +int +hgetm (hstring, keyword, lstr, str) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the root name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +const int lstr; /* Size of str in characters */ +char *str; /* String (returned) */ +{ + char *value; + char *stri; + char keywordi[16]; + int lval, lstri, ikey; + char keyform[8]; + + stri = str; + lstri = lstr; + + sprintf (keywordi, "%s_1", keyword); + if (ksearch (hstring, keywordi)) + strcpy (keyform, "%s_%d"); + else { + sprintf (keywordi, "%s_01", keyword); + if (ksearch (hstring, keywordi)) + strcpy (keyform, "%s_%02d"); + else { + sprintf (keywordi, "%s_001", keyword); + if (ksearch (hstring, keywordi)) + strcpy (keyform, "%s_%03d"); + else if (ksearch (hstring, keywordi)) + strcpy (keyform, "%s_%03d"); + else + return (0); + } + } + + /* Loop through sequentially-named keywords */ + multiline = 1; + for (ikey = 1; ikey < 500; ikey++) { + sprintf (keywordi, keyform, keyword, ikey); + + /* Get value for this keyword */ + value = hgetc (hstring, keywordi); + if (value != NULL) { + lval = strlen (value); + if (lval < lstri) + strcpy (stri, value); + else if (lstri > 1) { + strncpy (stri, value, lstri-1); + stri[lstri] = (char) 0; + break; + } + else { + str[0] = value[0]; + break; + } + } + else + break; + stri = stri + lval; + lstri = lstri - lval; + } + multiline = 0; + + /* Return 1 if any keyword found, else 0 */ + if (ikey > 1) + return (1); + else + return (0); +} + + +/* Extract string value for variable from FITS header string */ + +int +hgetsc (hstring,keyword,wchar,lstr,str) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for + a line beginning with this string. if "[n]" is + present, the n'th token in the value is returned. + (the first 8 characters must be unique) */ +const char *wchar; /* Character of multiple WCS header; =0 if unused */ +const int lstr; /* Size of str in characters */ +char *str; /* String (returned) */ +{ + char keyword1[16]; + int lkey; + + if (wchar[0] < (char) 64) + return (hgets (hstring, keyword, lstr, str)); + else { + strcpy (keyword1, keyword); + lkey = strlen (keyword); + keyword1[lkey] = wchar[0]; + keyword1[lkey+1] = (char) 0; + return (hgets (hstring, keyword1, lstr, str)); + } +} + + +/* Extract string value for variable from FITS header string */ + +int +hgets (hstring, keyword, lstr, str) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +const int lstr; /* Size of str in characters */ +char *str; /* String (returned) */ +{ + char *value; + int lval; + + /* Get value and comment from header string */ + value = hgetc (hstring,keyword); + + if (value != NULL) { + lval = strlen (value); + if (lval < lstr) + strcpy (str, value); + else if (lstr > 1) + strncpy (str, value, lstr-1); + else + str[0] = value[0]; + return (1); + } + else + return (0); +} + + +/* Extract number of decimal places for value in FITS header string */ + +int +hgetndec (hstring, keyword, ndec) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +int *ndec; /* Number of decimal places in keyword value */ +{ + char *value; + int i, nchar; + + /* Get value and comment from header string */ + value = hgetc (hstring,keyword); + + /* Find end of string and count backward to decimal point */ + *ndec = 0; + if (value != NULL) { + nchar = strlen (value); + for (i = nchar-1; i >= 0; i--) { + if (value[i] == '.') + return (1); + *ndec = *ndec + 1; + } + return (1); + } + else + return (0); +} + + +/* Extract character value for variable from FITS header string */ + +char * +hgetc (hstring,keyword0) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword0; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +{ + static char cval[80]; + char *value; + char cwhite[2]; + char squot[2], dquot[2], lbracket[2], rbracket[2], slash[2], comma[2]; + char space; + char keyword[81]; /* large for ESO hierarchical keywords */ + char line[100]; + char *vpos, *cpar; + char *q1, *q2, *v1, *v2, *c1, *brack1, *brack2; + int ipar, i, lkey; + +#ifdef USE_SAOLIB + int iel=1, ip=1, nel, np, ier; + char *get_fits_head_str(); + + if( !use_saolib ){ +#endif + + squot[0] = (char) 39; + squot[1] = (char) 0; + dquot[0] = (char) 34; + dquot[1] = (char) 0; + lbracket[0] = (char) 91; + lbracket[1] = (char) 0; + comma[0] = (char) 44; + comma[1] = (char) 0; + rbracket[0] = (char) 93; + rbracket[1] = (char) 0; + slash[0] = (char) 47; + slash[1] = (char) 0; + space = (char) 32; + + /* Find length of variable name */ + strncpy (keyword,keyword0, sizeof(keyword)-1); + brack1 = strsrch (keyword,lbracket); + if (brack1 == NULL) + brack1 = strsrch (keyword,comma); + if (brack1 != NULL) { + *brack1 = '\0'; + brack1++; + } + + /* Search header string for variable name */ + vpos = ksearch (hstring,keyword); + + /* Exit if not found */ + if (vpos == NULL) + return (NULL); + + /* Initialize line to nulls */ + for (i = 0; i < 100; i++) + line[i] = 0; + +/* In standard FITS, data lasts until 80th character */ + + /* Extract entry for this variable from the header */ + strncpy (line,vpos,80); + + /* Check for quoted value */ + q1 = strsrch (line,squot); + c1 = strsrch (line,slash); + if (q1 != NULL) { + if (c1 != NULL && q1 < c1) { + q2 = strsrch (q1+1,squot); + if (q2 == NULL) { + q2 = c1 - 1; + while (*q2 == space) + q2--; + q2++; + } + else if (c1 < q2) + c1 = strsrch (q2,slash); + } + else if (c1 == NULL) { + q2 = strsrch (q1+1,squot); + if (q2 == NULL) { + q2 = line + 79; + while (*q2 == space) + q2--; + q2++; + } + } + else + q1 = NULL; + } + else { + q1 = strsrch (line,dquot); + if (q1 != NULL) { + if (c1 != NULL && q1 < c1) { + q2 = strsrch (q1+1,dquot); + if (q2 == NULL) { + q2 = c1 - 1; + while (*q2 == space) + q2--; + q2++; + } + else if (c1 < q2) + c1 = strsrch (q2,slash); + } + else if (c1 == NULL) { + q2 = strsrch (q1+1,dquot); + if (q2 == NULL) { + q2 = line + 79; + while (*q2 == space) + q2--; + q2++; + } + } + else + q1 = NULL; + } + else { + q1 = NULL; + q2 = line + 10; + } + } + + /* Extract value and remove excess spaces */ + if (q1 != NULL) { + v1 = q1 + 1; + v2 = q2; + } + else { + v1 = strsrch (line,"="); + if (v1 == NULL) + v1 = line + 9; + else + v1 = v1 + 1; + c1 = strsrch (line,"/"); + if (c1 != NULL) + v2 = c1; + else + v2 = line + 79; + } + + /* Ignore leading spaces if not multiline */ + if (!multiline) { + while (*v1 == ' ' && v1 < v2) { + v1++; + } + } + + /* Drop trailing spaces */ + *v2 = '\0'; + if (!multiline) { + v2--; + while ((*v2 == ' ' || *v2 == (char) 13) && v2 > v1) { + *v2 = '\0'; + v2--; + } + } + + /* Convert -zero to just plain 0 */ + if (!strcmp (v1, "-0")) + v1++; + strcpy (cval,v1); + value = cval; + + /* If keyword has brackets, extract appropriate token from value */ + if (brack1 != NULL) { + brack2 = strsrch (brack1,rbracket); + if (brack2 != NULL) + *brack2 = '\0'; + if (isnum (brack1)) { + ipar = atoi (brack1); + cwhite[0] = ' '; + cwhite[1] = '\0'; + if (ipar > 0) { + for (i = 1; i <= ipar; i++) { + cpar = strtok (v1,cwhite); + v1 = NULL; + } + if (cpar != NULL) { + strcpy (cval,cpar); + value = cval; + } + else + value = NULL; + } + + /* If token counter is negative, include rest of value */ + else if (ipar < 0) { + for (i = 1; i < -ipar; i++) { + v1 = strchr (v1, ' '); + if (v1 == NULL) + break; + else + v1 = v1 + 1; + } + if (v1 != NULL) { + strcpy (cval, v1); + value = cval; + } + else + value = NULL; + } + } + else { + lkey = strlen (brack1); + for (i = 0; i < lkey; i++) { + if (brack1[i] > 64 && brack1[i] < 91) + brack1[i] = brack1[i] + 32; + } + v1 = igetc (cval, brack1); + if (v1) { + strcpy (cval,v1); + value = cval; + } + else + value = NULL; + } + } + + return (value); +#ifdef USE_SAOLIB + } else { + return(get_fits_head_str(keyword0, iel, ip, &nel, &np, &ier, hstring)); + } +#endif +} + + +/* Find beginning of fillable blank line before FITS header keyword line */ + +char * +blsearch (hstring,keyword) + +/* Find entry for keyword keyword in FITS header string hstring. + (the keyword may have a maximum of eight letters) + NULL is returned if the keyword is not found */ + +const char *hstring; /* character string containing fits-style header + information in the format = {/ } + the default is that each entry is 80 characters long; + however, lines may be of arbitrary length terminated by + nulls, carriage returns or linefeeds, if packed is true. */ +const char *keyword; /* character string containing the name of the variable + to be returned. ksearch searches for a line beginning + with this string. The string may be a character + literal or a character variable terminated by a null + or '$'. it is truncated to 8 characters. */ +{ + const char *headlast; + char *loc, *headnext, *pval, *lc, *line; + char *bval; + int icol, nextchar, lkey, nleft, lhstr; + + pval = 0; + + /* Search header string for variable name */ + if (lhead0) + lhstr = lhead0; + else { + lhstr = 0; + while (lhstr < 256000 && hstring[lhstr] != 0) + lhstr++; + } + headlast = hstring + lhstr; + headnext = (char *) hstring; + pval = NULL; + while (headnext < headlast) { + nleft = headlast - headnext; + loc = strncsrch (headnext, keyword, nleft); + + /* Exit if keyword is not found */ + if (loc == NULL) { + break; + } + + icol = (loc - hstring) % 80; + lkey = strlen (keyword); + nextchar = (int) *(loc + lkey); + + /* If this is not in the first 8 characters of a line, keep searching */ + if (icol > 7) + headnext = loc + 1; + + /* If parameter name in header is longer, keep searching */ + else if (nextchar != 61 && nextchar > 32 && nextchar < 127) + headnext = loc + 1; + + /* If preceeding characters in line are not blanks, keep searching */ + else { + line = loc - icol; + for (lc = line; lc < loc; lc++) { + if (*lc != ' ') + headnext = loc + 1; + } + + /* Return pointer to start of line if match */ + if (loc >= headnext) { + pval = line; + break; + } + } + } + + /* Return NULL to calling program if keyword is not found */ + if (pval == NULL) + return (pval); + + /* Return NULL if keyword is found at start of FITS header string */ + if (pval == hstring) + return (NULL); + + /* Find last nonblank in FITS header string line before requested keyword */ + bval = pval - 80; + while (!strncmp (bval," ",8) && bval >= hstring) + bval = bval - 80; + bval = bval + 80; + + /* Return pointer to calling program if blank lines found */ + if (bval < pval && bval >= hstring) + return (bval); + else + return (NULL); +} + + +/* Find FITS header line containing specified keyword */ + +char * +ksearch (hstring,keyword) + +/* Find entry for keyword keyword in FITS header string hstring. + (the keyword may have a maximum of eight letters) + NULL is returned if the keyword is not found */ + +const char *hstring; /* character string containing fits-style header + information in the format = {/ } + the default is that each entry is 80 characters long; + however, lines may be of arbitrary length terminated by + nulls, carriage returns or linefeeds, if packed is true. */ +const char *keyword; /* character string containing the name of the variable + to be returned. ksearch searches for a line beginning + with this string. The string may be a character + literal or a character variable terminated by a null + or '$'. it is truncated to 8 characters. */ +{ + const char *headlast; + char *loc, *headnext, *pval, *lc, *line; + int icol, nextchar, lkey, nleft, lhead, lmax; + +#ifdef USE_SAOLIB + int iel=1, ip=1, nel, np, ier; + char *get_fits_head_str(); + + if( !use_saolib ){ +#endif + + pval = 0; + +/* Find current length of header string */ + if (lhead0) + lmax = lhead0; + else + lmax = 256000; + for (lhead = 0; lhead < lmax; lhead++) { + if (hstring[lhead] <= (char) 0) + break; + } + +/* Search header string for variable name */ + headlast = hstring + lhead; + headnext = (char *) hstring; + pval = NULL; + while (headnext < headlast) { + nleft = headlast - headnext; + loc = strncsrch (headnext, keyword, nleft); + + /* Exit if keyword is not found */ + if (loc == NULL) { + break; + } + + icol = (loc - hstring) % 80; + lkey = strlen (keyword); + nextchar = (int) *(loc + lkey); + + /* If this is not in the first 8 characters of a line, keep searching */ + if (icol > 7) + headnext = loc + 1; + + /* If parameter name in header is longer, keep searching */ + else if (nextchar != 61 && nextchar > 32 && nextchar < 127) + headnext = loc + 1; + + /* If preceeding characters in line are not blanks, keep searching */ + else { + line = loc - icol; + for (lc = line; lc < loc; lc++) { + if (*lc != ' ') + headnext = loc + 1; + } + + /* Return pointer to start of line if match */ + if (loc >= headnext) { + pval = line; + break; + } + } + } + +/* Return pointer to calling program */ + return (pval); + +#ifdef USE_SAOLIB + } + else { + if (get_fits_head_str(keyword,iel,ip,&nel,&np,&ier,hstring) != NULL) + return(hstring); + else + return(NULL); + } +#endif +} + + +/* Return the right ascension in degrees from sexagesimal hours or decimal degrees */ + +double +str2ra (in) + +const char *in; /* Character string of sexigesimal hours or decimal degrees */ + +{ + double ra; /* Right ascension in degrees (returned) */ + + ra = str2dec (in); + if (strsrch (in,":")) + ra = ra * 15.0; + + return (ra); +} + + +/* Return the declination in degrees from sexagesimal or decimal degrees */ + +double +str2dec (in) + +const char *in; /* Character string of sexigesimal or decimal degrees */ + +{ + double dec; /* Declination in degrees (returned) */ + double deg, min, sec, sign; + char *value, *c1, *c2; + int lval; + char *dchar; + + dec = 0.0; + + /* Return 0.0 if string is null */ + if (in == NULL) + return (dec); + + /* Translate value from ASCII colon-delimited string to binary */ + if (in[0]) { + value = (char *) in; + + /* Remove leading spaces */ + while (*value == ' ') + value++; + + /* Save sign */ + if (*value == '-') { + sign = -1.0; + value++; + } + else if (*value == '+') { + sign = 1.0; + value++; + } + else + sign = 1.0; + + /* Turn comma into space */ + if ((c1 = strsrch (value,",")) != NULL) + *c1 = ' '; + + /* Remove trailing spaces */ + lval = strlen (value); + while (value[lval-1] == ' ') + lval--; + + if ((c1 = strsrch (value,":")) == NULL) + c1 = strnsrch (value," ",lval); + if (c1 != NULL) { + *c1 = 0; + deg = (double) atoi (value); + *c1 = ':'; + value = c1 + 1; + if ((c2 = strsrch (value,":")) == NULL) + c2 = strsrch (value," "); + if (c2 != NULL) { + *c2 = 0; + min = (double) atoi (value); + *c2 = ':'; + value = c2 + 1; + sec = atof (value); + } + else { + sec = 0.0; + if ((c1 = strsrch (value,".")) != NULL) + min = atof (value); + if (strlen (value) > 0) + min = (double) atoi (value); + } + dec = sign * (deg + (min / 60.0) + (sec / 3600.0)); + } + else if (isnum (value) == 2) { + if ((dchar = strchr (value, 'D'))) + *dchar = 'e'; + if ((dchar = strchr (value, 'd'))) + *dchar = 'e'; + if ((dchar = strchr (value, 'E'))) + *dchar = 'e'; + dec = sign * atof (value); + } + else + dec = sign * (double) atoi (value); + } + return (dec); +} + + +/* Find string s2 within null-terminated string s1 */ + +char * +strsrch (s1, s2) + +const char *s1; /* String to search */ +const char *s2; /* String to look for */ + +{ + int ls1; + ls1 = strlen (s1); + return (strnsrch (s1, s2, ls1)); +} + + +/* Find string s2 within string s1 */ + +char * +strnsrch (s1, s2, ls1) + +const char *s1; /* String to search */ +const char *s2; /* String to look for */ +const int ls1; /* Length of string being searched */ + +{ + char *s,*s1e; + char cfirst,clast; + int i,ls2; + + /* Return null string if either pointer is NULL */ + if (s1 == NULL || s2 == NULL) + return (NULL); + + /* A zero-length pattern is found in any string */ + ls2 = strlen (s2); + if (ls2 ==0) + return ((char *) s1); + + /* Only a zero-length string can be found in a zero-length string */ + if (ls1 ==0) + return (NULL); + + cfirst = (char) s2[0]; + clast = (char) s2[ls2-1]; + s1e = (char *) s1 + (int) ls1 - ls2 + 1; + s = (char *) s1; + while (s < s1e) { + + /* Search for first character in pattern string */ + if (*s == cfirst) { + + /* If single character search, return */ + if (ls2 == 1) + return (s); + + /* Search for last character in pattern string if first found */ + if (s[ls2-1] == clast) { + + /* If two-character search, return */ + if (ls2 == 2) + return (s); + + /* If 3 or more characters, check for rest of search string */ + i = 1; + while (i < ls2 && s[i] == s2[i]) + i++; + + /* If entire string matches, return */ + if (i >= ls2) + return (s); + } + } + s++; + } + return (NULL); +} + + +/* Find string s2 within null-terminated string s1 (case-free search) */ + +char * +strcsrch (s1, s2) + +const char *s1; /* String to search */ +const char *s2; /* String to look for */ + +{ + int ls1; + ls1 = strlen ((char *) s1); + return (strncsrch (s1, s2, ls1)); +} + + +/* Find string s2 within string s1 (case-free search) */ + +char * +strncsrch (s1, s2, ls1) + +const char *s1; /* String to search */ +const char *s2; /* String to look for */ +const int ls1; /* Length of string being searched */ + +{ + char *s,*s1e, sl, *os2; + char cfirst,ocfirst; + char clast = ' '; + char oclast = ' '; + int i,ls2; + + /* Return null string if either pointer is NULL */ + if (s1 == NULL || s2 == NULL) + return (NULL); + + /* A zero-length pattern is found in any string */ + ls2 = strlen (s2); + if (ls2 ==0) + return ((char *) s1); + + /* Only a zero-length string can be found in a zero-length string */ + os2 = NULL; + if (ls1 ==0) + return (NULL); + + /* For one or two characters, set opposite case first and last letters */ + if (ls2 < 3) { + cfirst = (char) s2[0]; + if (cfirst > 96 && cfirst < 123) + ocfirst = cfirst - 32; + else if (cfirst > 64 && cfirst < 91) + ocfirst = cfirst + 32; + else + ocfirst = cfirst; + if (ls2 > 1) { + clast = s2[1]; + if (clast > 96 && clast < 123) + oclast = clast - 32; + else if (clast > 64 && clast < 91) + oclast = clast + 32; + else + oclast = clast; + } + } + + /* Else duplicate string with opposite case letters for comparison */ + else { + os2 = (char *) calloc (ls2, 1); + for (i = 0; i < ls2; i++) { + if (s2[i] > 96 && s2[i] < 123) + os2[i] = s2[i] - 32; + else if (s2[i] > 64 && s2[i] < 91) + os2[i] = s2[i] + 32; + else + os2[i] = s2[i]; + } + cfirst = s2[0]; + ocfirst = os2[0]; + clast = s2[ls2-1]; + oclast = os2[ls2-1]; + } + + /* Loop through input string, character by character */ + s = (char *) s1; + s1e = s + (int) ls1 - ls2 + 1; + while (s < s1e) { + + /* Search for first character in pattern string */ + if (*s == cfirst || *s == ocfirst) { + + /* If single character search, return */ + if (ls2 == 1) { + if (os2 != NULL) + free (os2); + return (s); + } + + /* Search for last character in pattern string if first found */ + sl = s[ls2-1]; + if (sl == clast || sl == oclast) { + + /* If two-character search, return */ + if (ls2 == 2) { + if (os2 != NULL) + free (os2); + return (s); + } + + /* If 3 or more characters, check for rest of search string */ + i = 1; + while (i < ls2 && (s[i] == (char) s2[i] || s[i] == os2[i])) + i++; + + /* If entire string matches, return */ + if (i >= ls2) { + if (os2 != NULL) + free (os2); + return (s); + } + } + } + s++; + } + if (os2 != NULL) + free (os2); + return (NULL); +} + + +int +notnum (string) + +const char *string; /* Character string */ +{ + if (isnum (string)) + return (0); + else + return (1); +} + + +/* ISNUM-- Return 1 if string is an integer number, + 2 if floating point, + 3 if sexigesimal, with or without decimal point + else 0 + */ + +int +isnum (string) + +const char *string; /* Character string */ +{ + int lstr, i, nd, cl; + char cstr, cstr1; + int fpcode; + + /* Return 0 if string is NULL */ + if (string == NULL) + return (0); + + lstr = strlen (string); + nd = 0; + cl = 0; + fpcode = 1; + + /* Return 0 if string starts with a D or E */ + cstr = string[0]; + if (cstr == 'D' || cstr == 'd' || + cstr == 'E' || cstr == 'e') { + return (0); + } + + /* Remove trailing spaces */ + while (string[lstr-1] == ' ') + lstr--; + + /* Numeric strings contain 0123456789-+ and d or e for exponents */ + for (i = 0; i < lstr; i++) { + cstr = string[i]; + if (cstr == '\n') + break; + + /* Ignore leading spaces */ + if (cstr == ' ' && nd == 0) + continue; + + if ((cstr < 48 || cstr > 57) && + cstr != '+' && cstr != '-' && + cstr != 'D' && cstr != 'd' && + cstr != 'E' && cstr != 'e' && + cstr != ':' && cstr != '.') + return (0); + else if (cstr == '+' || cstr == '-') { + if (string[i+1] == '-' || string[i+1] == '+') + return (0); + else if (i > 0) { + cstr1 = string[i-1]; + if (cstr1 != 'D' && cstr1 != 'd' && + cstr1 != 'E' && cstr1 != 'e' && + cstr1 != ':' && cstr1 != ' ') + return (0); + } + } + else if (cstr >= 47 && cstr <= 57) + nd++; + + /* Check for colon */ + else if (cstr == 58) + cl++; + if (cstr=='.' || cstr=='d' || cstr=='e' || cstr=='d' || cstr=='e') + fpcode = 2; + } + if (nd > 0) { + if (cl) + fpcode = 3; + return (fpcode); + } + else + return (0); +} + + +/* NUMDEC -- Return number of decimal places in numeric string (-1 if not number) */ + +int +numdec (string) + +const char *string; /* Numeric string */ +{ + char *cdot; + int lstr; + + if (notnum (string) && !strchr (string, ':')) + return (-1); + else { + lstr = strlen (string); + if ((cdot = strchr (string, '.')) == NULL) + return (0); + else + return (lstr - (cdot - string) - 1); + } +} + + +#ifdef USE_SAOLIB +int set_saolib(hstring) + void *hstring; +{ + if( *((int *)hstring) == 142857 ) + use_saolib = 1; + else + use_saolib = 0; +} + +#endif + + +/* Remove exponent, leading #, surrounding parentheses, + and/or trailing zeroes, if reasonable */ +void +strfix (string, fillblank, dropzero) + +char *string; /* String to modify */ +int fillblank; /* If nonzero, fill blanks with underscores */ +int dropzero; /* If nonzero, drop trailing zeroes */ +{ + char *sdot, *s, *strend, *str, ctemp, *slast; + int ndek, lstr, i; + + /* If number, ignore leading # and remove trailing non-numeric character */ + if (string[0] == '#') { + strend = string + strlen (string); + str = string + 1; + strend = str + strlen (str) - 1; + ctemp = *strend; + if (!isnum (strend)) + *strend = (char) 0; + if (isnum (str)) { + strend = string + strlen (string); + for (str = string; str < strend; str++) + *str = *(str + 1); + } + else + *strend = ctemp; + } + + /* Remove parentheses if they enclose the string */ + if (string[0] == '(') { + lstr = strlen (string); + if (string[lstr-1] == ')') { + string[lstr-1] = (char) 0; + strend = string + lstr - 1; + for (str = string; str < strend; str++) + *str = *(str+1); + string[lstr-2] = (char) 0; + } + } + + /* Remove positive exponent if there are enough digits given */ + if (isnum (string) > 1 && strsrch (string, "E+") != NULL) { + lstr = strlen (string); + ndek = (int) (string[lstr-1] - 48); + ndek = ndek + (10 * ((int) (string[lstr-2] - 48))); + if (ndek < lstr - 7) { + lstr = lstr - 4; + string[lstr] = (char) 0; + string[lstr+1] = (char) 0; + string[lstr+2] = (char) 0; + string[lstr+3] = (char) 0; + sdot = strchr (string, '.'); + if (ndek > 0 && sdot != NULL) { + for (i = 1; i <= ndek; i++) { + *sdot = *(sdot+1); + sdot++; + *sdot = '.'; + } + } + } + } + + /* Remove trailing zeroes if they are not significant */ + if (dropzero) { + if (isnum (string) > 1 && strchr (string, '.') != NULL && + strsrch (string, "E-") == NULL && + strsrch (string, "E+") == NULL && + strsrch (string, "e-") == NULL && + strsrch (string, "e+") == NULL) { + lstr = strlen (string); + s = string + lstr - 1; + while (*s == '0' && lstr > 1) { + if (*(s - 1) != '.') { + *s = (char) 0; + lstr --; + } + s--; + } + } + } + + /* Remove trailing decimal point */ + lstr = strlen (string); + s = string + lstr - 1; + if (*s == '.') + *s = (char) 0; + + /* Replace embedded blanks with underscores, if requested to */ + if (fillblank) { + lstr = strlen (string); + slast = string + lstr; + for (s = string; s < slast; s++) { + if (*s == ' ') *s = '_'; + } + } + + return; + +} + +/* Oct 28 1994 New program + * + * Mar 1 1995 Search for / after second quote, not first one + * May 2 1995 Initialize line in HGETC; deal with logicals in HGETL better + * May 4 1995 Declare STRSRCH in KSEARCH + * Aug 7 1995 Fix line initialization in HGETC + * Dec 22 1995 Add HGETRA and HGETDEC to get degrees from xx:xx:xx.xxx string + * + * Jan 26 1996 Fix HGETL to not crash when parameter is not present + * Feb 1 1996 Fix HGETC to deal with quotes correctly + * Feb 1 1996 Fix HGETDEG to deal with sign correctly + * Feb 6 1996 Add HGETS to update character strings + * Feb 8 1996 Fix STRSRCH to find final characters in string + * Feb 23 1996 Add string to degree conversions + * Apr 26 1996 Add HGETDATE to get fractional year from date string + * May 22 1996 Fix documentation; return double from STR2RA and STR2DEC + * May 28 1996 Fix string translation of RA and Dec when no seconds + * Jun 10 1996 Remove unused variables after running lint + * Jun 17 1996 Fix bug which failed to return single character strings + * Jul 1 1996 Skip sign when reading declination after testing for it + * Jul 19 1996 Do not divide by 15 if RA header value is already in degrees + * Aug 5 1996 Add STRNSRCH to search strings which are not null-terminated + * Aug 6 1996 Make minor changes after lint + * Aug 8 1996 Fix ksearch bug which finds wrong keywords + * Aug 13 1996 Fix sign bug in STR2DEC for degrees + * Aug 26 1996 Drop unused variables ICOL0, NLINE, PREVCHAR from KSEARCH + * Sep 10 1996 Fix header length setting code + * Oct 15 1996 Clean up loops and fix ICOL assignment + * Nov 13 1996 Handle integer degrees correctly in STR2DEC + * Nov 21 1996 Make changes for Linux thanks to Sidik Isani + * Dec 12 1996 Add ISNUM to check to see whether strings are numbers + * + * Jan 22 1997 Add ifdefs for Eric Mandel (SAOtng) + * Jan 27 1997 Convert to integer through ATOF so exponents are recognized + * Jul 25 1997 Implement FITS version of ISO date format + * + * Feb 24 1998 Implement code to return IRAF multiple-keyword strings + * Mar 12 1998 Add subroutine NOTNUM + * Mar 27 1998 Add changes to match SKYCAT version + * Apr 30 1998 Add BLSEARCH() to find blank lines before END + * May 27 1998 Add HGETNDEC() to get number of decimal places in entry + * Jun 1 1998 Add VMS patch from Harry Payne at StSci + * Jun 18 1998 Fix code which extracts tokens from string values + * Jul 21 1998 Drop minus sign for values of -0 + * Sep 29 1998 Treat hyphen-separated date as old format if 2-digit year + * Oct 7 1998 Clean up search for last blank line + * + * Apr 5 1999 Check lengths of strings before copying them + * May 5 1999 values.h -> POSIX limits.h: MAXINT->INT_MAX, MAXSHORT->SHRT_MAX + * Jul 15 1999 Add hgetm() options of 1- or 2-digit keyword extensions + * Oct 6 1999 Add gethlength() to return header length + * Oct 14 1999 In ksearch(), search only to null not to end of buffer + * Oct 15 1999 Return 1 from hgetndec() if successful + * Oct 20 1999 Drop unused variable after lint (val in hgetndec) + * Dec 3 1999 Fix isnum() to reject strings starting with a d or e + * Dec 20 1999 Update hgetdate() to get minutes and seconds right + * + * Feb 10 2000 Parse RA and Dec with spaces as well as colons as separators + * Feb 11 2000 Add null at end of multi-line keyword value character string + * Feb 25 2000 Change max search string length from 57600 to 256000 + * Mar 15 2000 Deal with missing second quotes in string values + * Mar 17 2000 Return 2 from isnum() if number is floating point (.de) + * Mar 17 2000 Ignore leading # for numeric values in header + * Mar 21 2000 Implement -n to get string value starting with nth token + * Apr 5 2000 Reject +- in isnum() + * Jun 9 2000 Read keyword values even if no equal sign is present + * Sep 20 2000 Ignore linefeed at end of number in isnum() + * Oct 23 2000 Fix handling of embedded + or - in isnum() + * + * Jan 19 2000 Return 0 from isnum(), str2ra(), and str2dec() if string is null + * Mar 30 2001 Fix header length finding algorithm in ksearch() + * Jul 13 2001 Make val[] static int instead of int; drop unused variables + * Sep 12 2001 Read yyyy/mm/dd dates as well as dd/mm/yyyy + * Sep 20 2001 Ignore leading spaces in str2dec() + * Sep 20 2001 Ignore trailing spaces in isnum() + * + * Apr 3 2002 Add hgetr8c(), hgeti4c(), and hgetsc() for multiple WCS handling + * Apr 26 2002 Fix bug in hgetsc(), hgeti4c(), and hgetr8c() found by Bill Joye + * Jun 26 2002 Do not drop leading or trailing spaces in multi-line values + * Aug 6 2002 Add strcsrch() and strncsrch() for case-insensitive searches + * Aug 30 2002 Fix bug so strcsrch() really is case-insensitive + * Oct 20 2003 Add numdec() to return number of decimal places in a string + * Dec 9 2003 Fix numdec() to return 0 if no digits after decimal point + * + * Feb 26 2004 Extract value from keyword=value strings within a keyword value + * Apr 9 2004 Use strncsrch() in ksearch() to find differently-cased keywords + * Apr 28 2004 Free os2 in strncsrch() only if it is allocated + * Jul 13 2004 Accept D, d, E, or e as exponent delimiter in floating points + * Aug 30 2004 Change numdec() to accept sexigesimal numbers (:'s) + * + * Jun 27 2005 Drop unused variables + * Aug 30 2005 Adjust code in hlength() + * + * Jun 20 2006 Initialize uninitialized variables in strnsrch() + * Jun 29 2006 Add new subroutine strfix() to clean strings for other uses + * Jul 13 2006 Increase maximum number of multiline keywords from 20 to 500 + * + * Jan 4 2007 Declare header, keyword to be const + * Jan 4 2007 Change WCS letter from char to char* + * Feb 28 2007 If header length is not set in hlength, set it to 0 + * May 31 2007 Add return value of 3 to isnum() if string has colon(s) + * Aug 22 2007 If closing quote not found, make one up + * + * Nov 12 2009 In strfix(), if drop enclosing parantheses + * + * Apr 19 2011 In str2dec(), change comma to space + * May 19 2011 In strncsrch() always free allocated memory before returning + */ diff --git a/astroem/hput.c b/astroem/hput.c new file mode 100644 index 00000000..7ec81abd --- /dev/null +++ b/astroem/hput.c @@ -0,0 +1,1316 @@ +/*** File libwcs/hput.c + *** September 9, 2011 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1995-2011 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + + * Module: hput.c (Put FITS Header parameter values) + * Purpose: Implant values for parameters into FITS header string + * Subroutine: hputi4 (hstring,keyword,ival) sets int ival + * Subroutine: hputr4 (hstring,keyword,rval) sets real*4 rval + * Subroutine: hputr8 (hstring,keyword,dval) sets real*8 dval + * Subroutine: hputnr8 (hstring,keyword,ndec,dval) sets real*8 dval + * Subroutine: hputra (hstring,keyword,lval) sets right ascension as string + * Subroutine: hputdec (hstring,keyword,lval) sets declination as string + * Subroutine: hputl (hstring,keyword,lval) sets logical lval + * Subroutine: hputs (hstring,keyword,cval) sets character string adding '' + * Subroutine: hputm (hstring,keyword,cval) sets multi-line character string + * Subroutine: hputc (hstring,keyword,cval) sets character string cval + * Subroutine: hdel (hstring,keyword) deletes entry for keyword keyword + * Subroutine: hadd (hplace,keyword) adds entry for keyword at hplace + * Subroutine: hchange (hstring,keyword1,keyword2) changes keyword for entry + * Subroutine: hputcom (hstring,keyword,comment) sets comment for parameter keyword + * Subroutine: ra2str (out, lstr, ra, ndec) converts RA from degrees to string + * Subroutine: dec2str (out, lstr, dec, ndec) converts Dec from degrees to string + * Subroutine: deg2str (out, lstr, deg, ndec) converts degrees to string + * Subroutine: num2str (out, num, field, ndec) converts number to string + * Subroutine: getltime () returns current local time as ISO-style string + * Subroutine: getutime () returns current UT as ISO-style string + */ +#include +#include /* NULL, strlen, strstr, strcpy */ +#include +#include +#include +#include "fitshead.h" + +static int verbose=0; /* Set to 1 to print error messages and other info */ + +static void fixnegzero(); + + +/* HPUTI4 - Set int keyword = ival in FITS header string */ + +int +hputi4 (hstring,keyword,ival) + +char *hstring; /* FITS-style header information in the format + = {/ } + each entry is padded with spaces to 80 characters */ + +const char *keyword; /* Name of the variable in header to be returned. + If no line begins with this string, one is created. + The first 8 characters of keyword must be unique. */ +int ival; /* int number */ +{ + char value[30]; + + /* Translate value from binary to ASCII */ + sprintf (value,"%d",ival); + + /* Put value into header string */ + return (hputc (hstring,keyword,value)); +} + + +/* HPUTR4 - Set float keyword = rval in FITS header string */ + +int +hputr4 (hstring, keyword, rval) + +char *hstring; /* FITS header string */ +const char *keyword; /* Keyword name */ +const float *rval; /* float number */ + +{ + char value[30]; + + /* Translate value from binary to ASCII */ + sprintf (value, "%f", *rval); + + /* Remove sign if string is -0 or extension thereof */ + fixnegzero (value); + + /* Put value into header string */ + return (hputc (hstring, keyword, value)); +} + + +/* HPUTR8 - Set double keyword = dval in FITS header string */ + +int +hputr8 (hstring, keyword, dval) + +char *hstring; /* FITS header string */ +const char *keyword; /* Keyword name */ +const double dval; /* double number */ +{ + char value[30]; + + /* Translate value from binary to ASCII */ + sprintf (value, "%g", dval); + + /* Remove sign if string is -0 or extension thereof */ + fixnegzero (value); + + /* Put value into header string */ + return (hputc (hstring, keyword, value)); +} + + +/* HPUTNR8 - Set double keyword = dval in FITS header string */ + +int +hputnr8 (hstring, keyword, ndec, dval) + +char *hstring; /* FITS header string */ +const char *keyword; /* Keyword name */ +const int ndec; /* Number of decimal places to print */ +const double dval; /* double number */ +{ + char value[30]; + char format[8]; + int i, lval; + + /* Translate value from binary to ASCII */ + if (ndec < 0) { + sprintf (format, "%%.%dg", -ndec); + sprintf (value, format, dval); + lval = (int) strlen (value); + for (i = 0; i < lval; i++) + if (value[i] == 'e') value[i] = 'E'; + } + else { + sprintf (format, "%%.%df", ndec); + sprintf (value, format, dval); + } + + /* Remove sign if string is -0 or extension thereof */ + fixnegzero (value); + + /* Put value into header string */ + return (hputc (hstring, keyword, value)); +} + + +/* HPUTRA - Set double keyword = hh:mm:ss.sss in FITS header string */ + +int +hputra (hstring, keyword, ra) + +char *hstring; /* FITS header string */ +const char *keyword; /* Keyword name */ +const double ra; /* Right ascension in degrees */ +{ + char value[30]; + + /* Translate value from binary to ASCII */ + ra2str (value, 30, ra, 3); + + /* Remove sign if string is -0 or extension thereof */ + fixnegzero (value); + + /* Put value into header string */ + return (hputs (hstring, keyword, value)); +} + + +/* HPUTDEC - Set double keyword = dd:mm:ss.sss in FITS header string */ + +int +hputdec (hstring, keyword, dec) + +char *hstring; /* FITS header string */ +const char *keyword; /* Keyword name */ +const double dec; /* Declination in degrees */ +{ + char value[30]; + + /* Translate value from binary to ASCII */ + dec2str (value, 30, dec, 2); + + /* Remove sign if string is -0 or extension thereof */ + fixnegzero (value); + + /* Put value into header string */ + return (hputs (hstring, keyword, value)); +} + + +/* FIXNEGZERO -- Drop - sign from beginning of any string which is all zeros */ + +static void +fixnegzero (string) + +char *string; +{ + int i, lstr; + + if (string[0] != '-') + return; + + /* Drop out if any non-zero digits in this string */ + lstr = (int) strlen (string); + for (i = 1; i < lstr; i++) { + if (string[i] > '0' && string[i] <= '9') + return; + if (string[i] == 'd' || string[i] == 'e' || string[i] == ' ') + break; + } + + /* Drop - from start of string; overwrite string in place */ + for (i = 1; i < lstr; i++) + string[i-1] = string[i]; + string[lstr-1] = (char) 0; + + return; +} + + + +/* HPUTL - Set keyword = F if lval=0, else T, in FITS header string */ + +int +hputl (hstring, keyword,lval) + +char *hstring; /* FITS header */ +const char *keyword; /* Keyword name */ +const int lval; /* logical variable (0=false, else true) */ +{ + char value[8]; + + /* Translate value from binary to ASCII */ + if (lval) + strcpy (value, "T"); + else + strcpy (value, "F"); + + /* Put value into header string */ + return (hputc (hstring,keyword,value)); +} + + +/* HPUTM - Set multi-line character string in FITS header string */ +/* return number of keywords written */ + +int +hputm (hstring,keyword,cval) + +char *hstring; /* FITS header */ +const char *keyword; /* Keyword name root (6 characters or less) */ +const char *cval; /* character string containing the value for variable + keyword. trailing and leading blanks are removed. */ +{ + int lroot, lcv, i, ii, nkw, lkw, lval; + int comment = 0; + const char *v; + char keyroot[8], newkey[12], value[80]; + char squot = 39; + + /* If COMMENT or HISTORY, use the same keyword on every line */ + lkw = (int) strlen (keyword); + if (lkw == 7 && (strncmp (keyword,"COMMENT",7) == 0 || + strncmp (keyword,"HISTORY",7) == 0)) { + comment = 1; + lroot = 0; + } + + /* Set up keyword root, shortening it to 6 characters, if necessary */ + else { + comment = 0; + strcpy (keyroot, keyword); + lroot = (int) strlen (keyroot); + if (lroot > 6) { + keyroot[6] = (char) 0; + lroot = 6; + } + } + + /* Write keyword value one line of up to 67 characters at a time */ + ii = '1'; + nkw = 0; + lcv = (int) strlen (cval); + if (!comment) { + strcpy (newkey, keyroot); + strcat (newkey, "_"); + newkey[lroot+2] = (char) 0; + } + v = cval; + while (lcv > 0) { + if (lcv > 67) + lval = 67; + else + lval = lcv; + value[0] = squot; + for (i = 1; i <= lval; i++) + value[i] = *v++; + + /* Pad short strings to 8 characters */ + if (lval < 8) { + for (i = lval+1; i < 9; i++) + value[i] = ' '; + lval = 8; + } + value[lval+1] = squot; + value[lval+2] = (char) 0; + + /* Add this line to the header */ + if (comment) + i = hputc (hstring, keyroot, value); + else { + newkey[lroot+1] = ii; + ii++; + i = hputc (hstring, newkey, value); + } + if (i != 0) return (i); + nkw++; + if (lcv > 67) + lcv = lcv - 67; + else + break; + } + return (nkw); +} + + +/* HPUTS - Set character string keyword = 'cval' in FITS header string */ + +int +hputs (hstring,keyword,cval) + +char *hstring; /* FITS header */ +const char *keyword; /* Keyword name */ +const char *cval; /* character string containing the value for variable + keyword. trailing and leading blanks are removed. */ +{ + char squot = 39; + char value[80]; + int lcval, i, lkeyword; + + /* If COMMENT or HISTORY, just add it as is */ + lkeyword = (int) strlen (keyword); + if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 || + strncmp (keyword,"HISTORY",7) == 0)) + return (hputc (hstring,keyword,cval)); + + /* find length of variable string */ + lcval = (int) strlen (cval); + if (lcval > 67) + lcval = 67; + + /* Put single quote at start of string */ + value[0] = squot; + strncpy (&value[1],cval,lcval); + + /* If string is less than eight characters, pad it with spaces */ + if (lcval < 8) { + for (i = lcval; i < 8; i++) { + value[i+1] = ' '; + } + lcval = 8; + } + + /* Add single quote and null to end of string */ + value[lcval+1] = squot; + value[lcval+2] = (char) 0; + + /* Put value into header string */ + return (hputc (hstring,keyword,value)); +} + + +/* HPUTC - Set character string keyword = value in FITS header string */ +/* Return -1 if error, 0 if OK */ + +int +hputc (hstring,keyword,value) + +char *hstring; +const char *keyword; +const char *value; /* character string containing the value for variable + keyword. trailing and leading blanks are removed. */ +{ + char squot = 39; + char line[100]; + char newcom[50]; + char *vp, *v1, *v2, *q1, *q2, *c1, *ve; + int lkeyword, lcom, lval, lc, lv1, lhead, lblank, ln, nc, i; + + /* Find length of keyword, value, and header */ + lkeyword = (int) strlen (keyword); + lval = (int) strlen (value); + lhead = gethlength (hstring); + + /* If COMMENT or HISTORY, always add it just before the END */ + if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 || + strncmp (keyword,"HISTORY",7) == 0)) { + + /* First look for blank lines before END */ + v1 = blsearch (hstring, "END"); + + /* Otherwise, create a space for it at the end of the header */ + if (v1 == NULL) { + + /* Find end of header */ + v1 = ksearch (hstring,"END"); + + /* Align pointer at start of 80-character line */ + lc = v1 - hstring; + ln = lc / 80; + nc = ln * 80; + v1 = hstring + nc; + v2 = v1 + 80; + + /* If header length is exceeded, return error code */ + if (v2 - hstring > lhead) { + return (-1); + } + + /* Move END down 80 characters */ + strncpy (v2, v1, 80); + } + else + v2 = v1 + 80; + + /* Insert keyword */ + strncpy (v1,keyword,7); + + /* Pad with spaces */ + for (vp = v1+lkeyword; vp < v2; vp++) + *vp = ' '; + + if (lval > 71) + lv1 = 71; + else + lv1 = lval; + + /* Insert comment */ + strncpy (v1+9,value,lv1); + return (0); + } + + /* Otherwise search for keyword */ + else + v1 = ksearch (hstring,keyword); + + /* If parameter is not found, find a place to put it */ + if (v1 == NULL) { + + /* First look for blank lines before END */ + v1 = blsearch (hstring, "END"); + + /* Otherwise, create a space for it at the end of the header */ + if (v1 == NULL) { + ve = ksearch (hstring,"END"); + v1 = ve; + + /* Align pointer at start of 80-character line */ + lc = v1 - hstring; + ln = lc / 80; + nc = ln * 80; + v1 = hstring + nc; + v2 = v1 + 80; + + /* If header length is exceeded, return error code */ + if (v2 - hstring > lhead) { + return (-1); + } + + strncpy (v2, ve, 80); + } + else + v2 = v1 + 80; + lcom = 0; + newcom[0] = 0; + } + + /* Otherwise, extract the entry for this keyword from the header */ + else { + + /* Align pointer at start of 80-character line */ + lc = v1 - hstring; + ln = lc / 80; + nc = ln * 80; + v1 = hstring + nc; + v2 = v1 + 80; + + strncpy (line, v1, 80); + line[80] = 0; + v2 = v1 + 80; + + /* check for quoted value */ + q1 = strchr (line, squot); + if (q1 != NULL) { + q2 = strchr (q1+1,squot); + if (q2 != NULL) + c1 = strchr (q2,'/'); + else + c1 = strrchr (line+79,'/'); + } + else + c1 = strchr (line,'/'); + + /* extract comment and discount trailing spaces */ + if (c1 != NULL) { + lcom = 80 - (c1 + 2 - line); + strncpy (newcom, c1+2, lcom); + vp = newcom + lcom - 1; + while (vp-- > newcom && *vp == ' ') + lcom--; + } + else { + newcom[0] = 0; + lcom = 0; + } + } + + /* Fill new entry with spaces */ + for (vp = v1; vp < v2; vp++) + *vp = ' '; + + /* Copy keyword to new entry */ + strncpy (v1, keyword, lkeyword); + + /* Add parameter value in the appropriate place */ + vp = v1 + 8; + *vp = '='; + vp = v1 + 9; + *vp = ' '; + vp = vp + 1; + if (*value == squot) { + strncpy (vp, value, lval); + if (lval+12 > 31) + lc = lval + 12; + else + lc = 30; + } + else { + vp = v1 + 30 - lval; + strncpy (vp, value, lval); + lc = 30; + } + + /* Add comment in the appropriate place */ + if (lcom > 0) { + if (lc+2+lcom > 80) + lcom = 77 - lc; + vp = v1 + lc; /* Jul 16 1997: was vp = v1 + lc * 2 */ + *vp++ = ' '; + *vp++ = '/'; + *vp++ = ' '; + lblank = v2 - vp; + for (i = 0; i < lblank; i++) + vp[i] = ' '; + if (lcom > lblank) + lcom = lblank; + strncpy (vp, newcom, lcom); + } + + if (verbose) { + if (lcom > 0) + fprintf (stderr,"HPUT: %s = %s / %s\n",keyword, value, newcom); + else + fprintf (stderr,"HPUT: %s = %s\n",keyword, value); + } + + return (0); +} + + +/* HPUTCOM - Set comment for keyword or on line in FITS header string */ + +int +hputcom (hstring,keyword,comment) + + char *hstring; + const char *keyword; + const char *comment; +{ + char squot, slash, space; + char line[100]; + int lkeyword, lcom, lhead, i, lblank, ln, nc, lc; + char *vp, *v1, *v2, *c0, *c1, *q1, *q2; + + squot = (char) 39; + slash = (char) 47; + space = (char) 32; + + /* Find length of variable name */ + lkeyword = (int) strlen (keyword); + lhead = gethlength (hstring); + lcom = (int) strlen (comment); + + /* If COMMENT or HISTORY, always add it just before the END */ + if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 || + strncmp (keyword,"HISTORY",7) == 0)) { + + /* Find end of header */ + v1 = ksearch (hstring,"END"); + + /* Align pointer at start of 80-character line */ + lc = v1 - hstring; + ln = lc / 80; + nc = ln * 80; + v1 = hstring + nc; + v2 = v1 + 80; + + /* If header length is exceeded, return error code */ + if (v2 - hstring > lhead) { + return (-1); + } + + /* Move END down 80 characters */ + strncpy (v2, v1, 80); + + /* blank out new line and insert keyword */ + for (vp = v1; vp < v2; vp++) + *vp = ' '; + strncpy (v1, keyword, lkeyword); + c0 = v1 + lkeyword; + } + + /* Search header string for variable name */ + else { + v1 = ksearch (hstring,keyword); + + /* If parameter is not found, return without doing anything */ + if (v1 == NULL) { + if (verbose) + fprintf (stderr,"HPUTCOM: %s not found\n",keyword); + return (-1); + } + + /* Align pointer at start of 80-character line */ + lc = v1 - hstring; + ln = lc / 80; + nc = ln * 80; + v1 = hstring + nc; + v2 = v1 + 80; + + /* Extract entry for this variable from the header */ + strncpy (line, v1, 80); + line[80] = '\0'; /* Null-terminate line before strchr call */ + + /* check for quoted value */ + q1 = strchr (line,squot); + c1 = strchr (line,slash); + if (q1 != NULL) { + if (c1 != NULL && q1 < c1) { + q2 = strchr (q1+1, squot); + if (q2 == NULL) { + q2 = c1 - 1; + while (*q2 == space) + q2--; + q2++; + } + else if (c1 < q2) + c1 = strchr (q2, slash); + } + else if (c1 == NULL) { + q2 = strchr (q1+1, squot); + if (q2 == NULL) { + q2 = line + 79; + while (*q2 == space) + q2--; + q2++; + } + } + else + q1 = NULL; + q2 = NULL; + } + + else + q2 = NULL; + + if (c1 != NULL) + c0 = v1 + (c1 - line) - 1; + else if (q2 == NULL || q2-line < 30) + c0 = v1 + 30; + else + c0 = v1 + (q2 - line) + 1; /* allan: 1997-09-30, was c0=q2+2 */ + + /* If comment will not fit at all, return */ + if (c0 - v1 > 77) + return (-1); + strncpy (c0, " / ",3); + } + + /* Create new entry */ + if (lcom > 0) { + c1 = c0 + 3; + lblank = v1 + 79 - c1; + if (lcom > lblank) + lcom = lblank; + for (i = 0; i < lblank; i++) + c1[i] = ' '; + strncpy (c1, comment, lcom); + } + + if (verbose) { + fprintf (stderr,"HPUTCOM: %s / %s\n",keyword,comment); + } + return (0); +} + + +static int leaveblank = 0; /* If 1, leave blank line when deleting */ +void +setleaveblank (lb) +int lb; { leaveblank = lb; return; } + +static int headshrink=1; /* Set to 1 to drop line after deleting keyword */ +void +setheadshrink (hsh) +int hsh; +{headshrink = hsh; return;} + +/* HDEL - Set character string keyword = value in FITS header string + * returns 1 if entry deleted, else 0 + */ + +int +hdel (hstring,keyword) + +char *hstring; /* FITS header */ +const char *keyword; /* Keyword of entry to be deleted */ +{ + char *v, *v1, *v2, *ve; + + /* Search for keyword */ + v1 = ksearch (hstring,keyword); + + /* If keyword is not found, return header unchanged */ + if (v1 == NULL) { + return (0); + } + + /* Find end of header */ + ve = ksearch (hstring,"END"); + + /* If headshrink is 0, leave END where it is */ + if (!leaveblank && !headshrink) + ve = ve - 80; + + /* Cover deleted keyword line with spaces */ + if (leaveblank) { + v2 = v1 + 80; + for (v = ve; v < v2; v++) + *v = ' '; + } + + /* Shift rest of header up one line */ + else { + for (v = v1; v < ve; v = v + 80) { + v2 = v + 80; + strncpy (v, v2, 80); + } + + /* Cover former last line with spaces */ + v2 = ve + 80; + for (v = ve; v < v2; v++) + *v = ' '; + } + + return (1); +} + + +/* HADD - Add character string keyword = value to FITS header string + * returns 1 if entry added, else 0 + * Call hputx() to put value into entry + */ + +int +hadd (hplace, keyword) + +char *hplace; /* FITS header position for new keyword */ +const char *keyword; /* Keyword of entry to be deleted */ +{ + char *v, *v1, *v2, *ve; + int i, lkey; + + /* Find end of header */ + ve = ksearch (hplace,"END"); + + /* If END is not found, return header unchanged */ + if (ve == NULL) { + return (0); + } + + v1 = hplace; + + /* Shift rest of header down one line */ + /* limit bug found by Paolo Montegriffo fixed 2000-04-19 */ + for (v = ve; v >= v1; v = v - 80) { + v2 = v + 80; + strncpy (v2, v, 80); + } + + /* Cover former first line with new keyword */ + lkey = (int) strlen (keyword); + strncpy (hplace, keyword, lkey); + if (lkey < 8) { + for (i = lkey; i < 8; i++) + hplace[i] = ' '; + hplace[8] = '='; + } + for (i = 9; i < 80; i++) + hplace[i] = ' '; + + return (1); +} + + +/* HCHANGE - Changes keyword for entry from keyword1 to keyword2 in FITS + header string + * returns 1 if entry changed, else 0 + */ + +int +hchange (hstring, keyword1, keyword2) + +char *hstring; /* FITS header */ +const char *keyword1; /* Keyword to be changed */ +const char *keyword2; /* New keyword name */ +{ + char *v, *v1; + const char *v2; + int lv2, i; + + /* Search for keyword */ + v1 = ksearch (hstring,keyword1); + + /* If keyword is not found, return header unchanged */ + if (!v1) + return (0); + + else { + lv2 = (int) strlen (keyword2); + v = v1; + v2 = keyword2; + for (i = 0; i < 8; i++) { + if (i < lv2) + v[i] = v2[i]; + else + v[i] = ' '; + } + } + + return (1); +} + + +/* Write the right ascension ra in sexagesimal format into string*/ + +void +ra2str (string, lstr, ra, ndec) + +char *string; /* Character string (returned) */ +int lstr; /* Maximum number of characters in string */ +double ra; /* Right ascension in degrees */ +int ndec; /* Number of decimal places in seconds */ + +{ + double a,b; + double seconds; + char tstring[64]; + int hours; + int minutes; + int isec, ltstr; + double dsgn; + + /* Keep RA between 0 and 360 */ + if (ra < 0.0 ) { + ra = -ra; + dsgn = -1.0; + } + else + dsgn = 1.0; + ra = fmod(ra, 360.0); + ra *= dsgn; + if (ra < 0.0) + ra = ra + 360.0; + + a = ra / 15.0; + + /* Convert to hours */ + hours = (int) a; + + /* Compute minutes */ + b = (a - (double)hours) * 60.0; + minutes = (int) b; + + /* Compute seconds */ + seconds = (b - (double)minutes) * 60.0; + + if (ndec > 5) { + if (seconds > 59.999999) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + hours = hours + 1; + } + hours = hours % 24; + (void) sprintf (tstring,"%02d:%02d:%09.6f",hours,minutes,seconds); + } + else if (ndec > 4) { + if (seconds > 59.99999) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + hours = hours + 1; + } + hours = hours % 24; + (void) sprintf (tstring,"%02d:%02d:%08.5f",hours,minutes,seconds); + } + else if (ndec > 3) { + if (seconds > 59.9999) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + hours = hours + 1; + } + hours = hours % 24; + (void) sprintf (tstring,"%02d:%02d:%07.4f",hours,minutes,seconds); + } + else if (ndec > 2) { + if (seconds > 59.999) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + hours = hours + 1; + } + hours = hours % 24; + (void) sprintf (tstring,"%02d:%02d:%06.3f",hours,minutes,seconds); + } + else if (ndec > 1) { + if (seconds > 59.99) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + hours = hours + 1; + } + hours = hours % 24; + (void) sprintf (tstring,"%02d:%02d:%05.2f",hours,minutes,seconds); + } + else if (ndec > 0) { + if (seconds > 59.9) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + hours = hours + 1; + } + hours = hours % 24; + (void) sprintf (tstring,"%02d:%02d:%04.1f",hours,minutes,seconds); + } + else { + isec = (int)(seconds + 0.5); + if (isec > 59) { + isec = 0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + hours = hours + 1; + } + hours = hours % 24; + (void) sprintf (tstring,"%02d:%02d:%02d",hours,minutes,isec); + } + + /* Move formatted string to returned string */ + ltstr = (int) strlen (tstring); + if (ltstr < lstr-1) + strcpy (string, tstring); + else { + strncpy (string, tstring, lstr-1); + string[lstr-1] = 0; + } + return; +} + + +/* Write the variable a in sexagesimal format into string */ + +void +dec2str (string, lstr, dec, ndec) + +char *string; /* Character string (returned) */ +int lstr; /* Maximum number of characters in string */ +double dec; /* Declination in degrees */ +int ndec; /* Number of decimal places in arcseconds */ + +{ + double a, b, dsgn, deg1; + double seconds; + char sign; + int degrees; + int minutes; + int isec, ltstr; + char tstring[64]; + + /* Keep angle between -180 and 360 degrees */ + deg1 = dec; + if (deg1 < 0.0 ) { + deg1 = -deg1; + dsgn = -1.0; + } + else + dsgn = 1.0; + deg1 = fmod(deg1, 360.0); + deg1 *= dsgn; + if (deg1 <= -180.0) + deg1 = deg1 + 360.0; + + a = deg1; + + /* Set sign and do all the rest with a positive */ + if (a < 0) { + sign = '-'; + a = -a; + } + else + sign = '+'; + + /* Convert to degrees */ + degrees = (int) a; + + /* Compute minutes */ + b = (a - (double)degrees) * 60.0; + minutes = (int) b; + + /* Compute seconds */ + seconds = (b - (double)minutes) * 60.0; + + if (ndec > 5) { + if (seconds > 59.999999) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + degrees = degrees + 1; + } + (void) sprintf (tstring,"%c%02d:%02d:%09.6f",sign,degrees,minutes,seconds); + } + else if (ndec > 4) { + if (seconds > 59.99999) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + degrees = degrees + 1; + } + (void) sprintf (tstring,"%c%02d:%02d:%08.5f",sign,degrees,minutes,seconds); + } + else if (ndec > 3) { + if (seconds > 59.9999) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + degrees = degrees + 1; + } + (void) sprintf (tstring,"%c%02d:%02d:%07.4f",sign,degrees,minutes,seconds); + } + else if (ndec > 2) { + if (seconds > 59.999) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + degrees = degrees + 1; + } + (void) sprintf (tstring,"%c%02d:%02d:%06.3f",sign,degrees,minutes,seconds); + } + else if (ndec > 1) { + if (seconds > 59.99) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + degrees = degrees + 1; + } + (void) sprintf (tstring,"%c%02d:%02d:%05.2f",sign,degrees,minutes,seconds); + } + else if (ndec > 0) { + if (seconds > 59.9) { + seconds = 0.0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + degrees = degrees + 1; + } + (void) sprintf (tstring,"%c%02d:%02d:%04.1f",sign,degrees,minutes,seconds); + } + else { + isec = (int)(seconds + 0.5); + if (isec > 59) { + isec = 0; + minutes = minutes + 1; + } + if (minutes > 59) { + minutes = 0; + degrees = degrees + 1; + } + (void) sprintf (tstring,"%c%02d:%02d:%02d",sign,degrees,minutes,isec); + } + + /* Move formatted string to returned string */ + ltstr = (int) strlen (tstring); + if (ltstr < lstr-1) + strcpy (string, tstring); + else { + strncpy (string, tstring, lstr-1); + string[lstr-1] = 0; + } + return; +} + + +/* Write the angle a in decimal format into string */ + +void +deg2str (string, lstr, deg, ndec) + +char *string; /* Character string (returned) */ +int lstr; /* Maximum number of characters in string */ +double deg; /* Angle in degrees */ +int ndec; /* Number of decimal places in degree string */ + +{ + char degform[8]; + int field, ltstr; + char tstring[64]; + double deg1; + double dsgn; + + /* Keep angle between -180 and 360 degrees */ + deg1 = deg; + if (deg1 < 0.0 ) { + deg1 = -deg1; + dsgn = -1.0; + } + else + dsgn = 1.0; + deg1 = fmod(deg1, 360.0); + deg1 *= dsgn; + if (deg1 <= -180.0) + deg1 = deg1 + 360.0; + + /* Write angle to string, adding 4 digits to number of decimal places */ + field = ndec + 4; + if (ndec > 0) { + sprintf (degform, "%%%d.%df", field, ndec); + sprintf (tstring, degform, deg1); + } + else { + sprintf (degform, "%%%4d", field); + sprintf (tstring, degform, (int)deg1); + } + + /* Move formatted string to returned string */ + ltstr = (int) strlen (tstring); + if (ltstr < lstr-1) + strcpy (string, tstring); + else { + strncpy (string, tstring, lstr-1); + string[lstr-1] = 0; + } + return; +} + + +/* Write the variable a in decimal format into field-character string */ + +void +num2str (string, num, field, ndec) + +char *string; /* Character string (returned) */ +double num; /* Number */ +int field; /* Number of characters in output field (0=any) */ +int ndec; /* Number of decimal places in degree string */ + +{ + char numform[8]; + + if (field > 0) { + if (ndec > 0) { + sprintf (numform, "%%%d.%df", field, ndec); + sprintf (string, numform, num); + } + else { + sprintf (numform, "%%%dd", field); + sprintf (string, numform, (int)num); + } + } + else { + if (ndec > 0) { + sprintf (numform, "%%.%df", ndec); + sprintf (string, numform, num); + } + else { + sprintf (string, "%d", (int)num); + } + } + return; +} + +/* Dec 14 1995 Original subroutines + + * Feb 5 1996 Added HDEL to delete keyword entry from FITS header + * Feb 7 1996 Add EOS to LINE in HPUTC + * Feb 21 1996 Add RA2STR and DEC2STR string routines + * Jul 19 1996 Add HPUTRA and HPUTDEC + * Jul 22 1996 Add HCHANGE to change keywords + * Aug 5 1996 Add HPUTNR8 to save specific number of decimal places + * Oct 15 1996 Fix spelling + * Nov 1 1996 Add DEG2STR to set specific number of decimal places + * Nov 1 1996 Allow DEC2STR to handle upt to 6 decimal places + * + * Mar 20 1997 Fix format error in DEG2STR + * Jul 7 1997 Fix 2 errors in HPUTCOM found by Allan Brighton + * Jul 16 1997 Fix error in HPUTC found by Allan Brighton + * Jul 17 1997 Fix error in HPUTC found by Allan Brighton + * Sep 30 1997 Fix error in HPUTCOM found by Allan Brighton + * Dec 15 1997 Fix minor bugs after lint + * Dec 31 1997 Always put two hour digits in RA2STR + * + * Feb 25 1998 Add HADD to insert keywords at specific locations + * Mar 27 1998 If n is negative, write g format in HPUTNR8() + * Apr 24 1998 Add NUM2STR() for easy output formatting + * Apr 30 1998 Use BLSEARCH() to overwrite blank lines before END + * May 27 1998 Keep Dec between -90 and +90 in DEC2STR() + * May 28 1998 Keep RA between 0 and 360 in RA2STR() + * Jun 2 1998 Fix bug when filling in blank lines before END + * Jun 24 1998 Add string length to ra2str(), dec2str(), and deg2str() + * Jun 25 1998 Make string converstion subroutines more robust + * Aug 31 1998 Add getltime() and getutime() + * Sep 28 1998 Null-terminate comment in HPUTCOM (Allan Brighton) + * Oct 1 1998 Change clock declaration in getltime() from int (Allan Brighton) + * + * Jan 28 1999 Fix bug to avoid writing HISTORY or COMMENT past 80 characters + * Jul 14 1999 Pad string in hputs() to minimum of 8 characters + * Aug 16 1999 Keep angle between -180 and +360 in dec2str() + * Oct 6 1999 Reallocate header buffer if it is too small in hputc() + * Oct 14 1999 Do not reallocate header; return error if not successful + * + * Mar 2 2000 Do not add quotes if adding HISTORY or COMMENT with hputs() + * Mar 22 2000 Move getutime() and getltime() to dateutil.c + * Mar 27 2000 Add hputm() for muti-line keywords + * Mar 27 2000 Fix bug testing for space to fit comment in hputcom() + * Apr 19 2000 Fix bug in hadd() which overwrote line + * Jun 2 2000 Dropped unused variable lv in hputm() after lint + * Jul 20 2000 Drop unused variables blank and i in hputc() + * + * Jan 11 2001 Print all messages to stderr + * Jan 18 2001 Drop declaration of blsearch(); it is in fitshead.h + * + * Jan 4 2002 Fix placement of comments + * + * Jul 1 2004 Add headshrink to optionally keep blank lines in header + * Sep 3 2004 Fix bug so comments are not pushed onto next line if long value + * Sep 16 2004 Add fixnegzero() to avoid putting signed zero values in header + * + * May 22 2006 Add option to leave blank line when deleting a keyword + * Jun 15 2006 Fix comment alignment in hputc() and hputcom() + * Jun 20 2006 Initialized uninitialized variables in hputm() and hputcom() + * + * Jan 4 2007 Declare keyword to be const + * Jan 4 2007 Drop unused subroutine hputi2() + * Jan 5 2007 Drop ksearch() declarations; it is now in fitshead.h + * Jan 16 2007 Fix bugs in ra2str() and dec2str() so ndec=0 works + * Aug 20 2007 Fix bug so comments after quoted keywords work + * Aug 22 2007 If closing quote not found, make one up + * + * Sep 9 2011 Always initialize q2 and lroot + */ diff --git a/astroem/iget.c b/astroem/iget.c new file mode 100644 index 00000000..58e54f7b --- /dev/null +++ b/astroem/iget.c @@ -0,0 +1,531 @@ +/*** File libwcs/iget.c + *** January 4, 2007 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1998-2007 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + + * Module: iget.c (Get IRAF FITS Header parameter values) + * Purpose: Extract values for variables from IRAF keyword value string + * Subroutine: mgeti4 (hstring,mkey,keyword,ival) returns long integer + * Subroutine: mgetr8 (hstring,mkey,keyword,dval) returns double + * Subroutine: mgetstr (hstring,mkey,keyword,lstr,str) returns character string + * Subroutine: igeti4 (hstring,keyword,ival) returns long integer + * Subroutine: igetr4 (hstring,keyword,rval) returns real + * Subroutine: igetr8 (hstring,keyword,dval) returns double + * Subroutine: igets (hstring,keyword,lstr,str) returns character string + * Subroutine: igetc (hstring,keyword) returns character string + * Subroutine: isearch (hstring,keyword) returns pointer to header string entry + */ + +#include /* NULL, strlen, strstr, strcpy */ +#include +#include "fitshead.h" /* FITS header extraction subroutines */ +#include +#ifndef VMS +#include +#else +#define INT_MAX 2147483647 /* Biggest number that can fit in long */ +#define SHRT_MAX 32767 +#endif + +#define MAX_LVAL 2000 + +static char *isearch(); +static char val[30]; + +/* Extract long value for variable from IRAF multiline keyword value */ + +int +mgeti4 (hstring, mkey, keyword, ival) + +const char *hstring; /* Character string containing FITS or IRAF header information + in the format = ... */ +const char *mkey; /* Character string containing the name of the multi-line + keyword, the string value of which contains the desired + keyword, the value of which is returned. */ +const char *keyword; /* Character string containing the name of the keyword + within the multiline IRAF keyword */ +int *ival; /* Integer value returned */ +{ + char *mstring; + + mstring = malloc (MAX_LVAL); + + if (hgetm (hstring, mkey, MAX_LVAL, mstring)) { + if (igeti4 (mstring, keyword, ival)) { + free (mstring); + return (1); + } + else { + free (mstring); + return (0); + } + } + else { + free (mstring); + return (0); + } +} + +/* Extract double value for variable from IRAF multiline keyword value */ + +int +mgetr8 (hstring, mkey, keyword, dval) + +const char *hstring; /* Character string containing FITS or IRAF header information + in the format = ... */ +const char *mkey; /* Character string containing the name of the multi-line + keyword, the string value of which contains the desired + keyword, the value of which is returned. */ +const char *keyword; /* Character string containing the name of the keyword + within the multiline IRAF keyword */ +double *dval; /* Integer value returned */ +{ + char *mstring; + mstring = malloc (MAX_LVAL); + + if (hgetm (hstring, mkey, MAX_LVAL, mstring)) { + if (igetr8 (mstring, keyword, dval)) { + free (mstring); + return (1); + } + else { + free (mstring); + return (0); + } + } + else { + free (mstring); + return (0); + } +} + + +/* Extract string value for variable from IRAF keyword value string */ + +int +mgetstr (hstring, mkey, keyword, lstr, str) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *mkey; /* Character string containing the name of the multi-line + keyword, the string value of which contains the desired + keyword, the value of which is returned. */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +const int lstr; /* Size of str in characters */ +char *str; /* String (returned) */ +{ + char *mstring; + mstring = malloc (MAX_LVAL); + + if (hgetm (hstring, mkey, MAX_LVAL, mstring)) { + if (igets (mstring, keyword, lstr, str)) { + free (mstring); + return (1); + } + else { + free (mstring); + return (0); + } + } + else { + free (mstring); + return (0); + } +} + + +/* Extract long value for variable from IRAF keyword value string */ + +int +igeti4 (hstring, keyword, ival) + +const char *hstring; /* character string containing IRAF header information + in the format = ... */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +int *ival; /* Integer value returned */ +{ +char *value; +double dval; +int minint; + +/* Get value from header string */ + value = igetc (hstring,keyword); + +/* Translate value from ASCII to binary */ + if (value != NULL) { + minint = -INT_MAX - 1; + strcpy (val, value); + dval = atof (val); + if (dval+0.001 > INT_MAX) + *ival = INT_MAX; + else if (dval >= 0) + *ival = (int) (dval + 0.001); + else if (dval-0.001 < minint) + *ival = minint; + else + *ival = (int) (dval - 0.001); + return (1); + } + else { + return (0); + } +} + + +/* Extract integer*2 value for variable from IRAF keyword value string */ + +int +igeti2 (hstring,keyword,ival) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +short *ival; +{ +char *value; +double dval; +int minshort; + +/* Get value from header string */ + value = igetc (hstring,keyword); + +/* Translate value from ASCII to binary */ + if (value != NULL) { + strcpy (val, value); + dval = atof (val); + minshort = -SHRT_MAX - 1; + if (dval+0.001 > SHRT_MAX) + *ival = SHRT_MAX; + else if (dval >= 0) + *ival = (short) (dval + 0.001); + else if (dval-0.001 < minshort) + *ival = minshort; + else + *ival = (short) (dval - 0.001); + return (1); + } + else { + return (0); + } +} + +/* Extract real value for variable from IRAF keyword value string */ + +int +igetr4 (hstring,keyword,rval) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +float *rval; +{ + char *value; + +/* Get value from header string */ + value = igetc (hstring,keyword); + +/* Translate value from ASCII to binary */ + if (value != NULL) { + strcpy (val, value); + *rval = (float) atof (val); + return (1); + } + else { + return (0); + } +} + + +/* Extract real*8 value for variable from IRAF keyword value string */ + +int +igetr8 (hstring,keyword,dval) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +double *dval; +{ + char *value,val[30]; + +/* Get value from header string */ + value = igetc (hstring,keyword); + +/* Translate value from ASCII to binary */ + if (value != NULL) { + strcpy (val, value); + *dval = atof (val); + return (1); + } + else { + return (0); + } +} + + +/* Extract string value for variable from IRAF keyword value string */ + +int +igets (hstring, keyword, lstr, str) + +const char *hstring; /* character string containing FITS header information + in the format = {/ } */ +const char *keyword; /* character string containing the name of the keyword + the value of which is returned. hget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +const int lstr; /* Size of str in characters */ +char *str; /* String (returned) */ +{ + char *value; + int lval; + +/* Get value from header string */ + value = igetc (hstring,keyword); + + if (value != NULL) { + lval = strlen (value); + if (lval < lstr) + strcpy (str, value); + else if (lstr > 1) + strncpy (str, value, lstr-1); + else + str[0] = value[0]; + return (1); + } + else + return (0); +} + + +/* Extract character value for variable from IRAF keyword value string */ + +char * +igetc (hstring,keyword0) + +const char *hstring; /* character string containing IRAF keyword value string + in the format = {/ } */ +const char *keyword0; /* character string containing the name of the keyword + the value of which is returned. iget searches for a + line beginning with this string. if "[n]" is present, + the n'th token in the value is returned. + (the first 8 characters must be unique) */ +{ + static char cval[MAX_LVAL]; + char *value; + char cwhite[8]; + char lbracket[2],rbracket[2]; + char keyword[16]; + char line[MAX_LVAL]; + char *vpos,*cpar; + char *c1, *brack1, *brack2; + int ipar, i; + + lbracket[0] = 91; + lbracket[1] = 0; + rbracket[0] = 93; + rbracket[1] = 0; + +/* Find length of variable name */ + strcpy (keyword,keyword0); + brack1 = strsrch (keyword,lbracket); + if (brack1 != NULL) *brack1 = '\0'; + +/* Search header string for variable name */ + vpos = isearch (hstring,keyword); + +/* Exit if not found */ + if (vpos == NULL) { + return (NULL); + } + +/* Initialize returned value to nulls */ + for (i = 0; i < MAX_LVAL; i++) + line[i] = 0; + +/* If quoted value, copy until second quote is reached */ + i = 0; + if (*vpos == '"') { + vpos++; + while (*vpos && *vpos != '"' && i < MAX_LVAL) + line[i++] = *vpos++; + } + +/* Otherwise copy until next space or tab */ + else { + while (*vpos != ' ' && *vpos != (char)9 && + *vpos > 0 && i < MAX_LVAL) + line[i++] = *vpos++; + } + +/* If keyword has brackets, extract appropriate token from value */ + if (brack1 != NULL) { + c1 = (char *) (brack1 + 1); + brack2 = strsrch (c1, rbracket); + if (brack2 != NULL) { + *brack2 = '\0'; + ipar = atoi (c1); + if (ipar > 0) { + cwhite[0] = ' '; + cwhite[1] = ','; + cwhite[2] = '\0'; + cpar = strtok (line, cwhite); + for (i = 1; i < ipar; i++) { + cpar = strtok (NULL, cwhite); + } + if (cpar != NULL) { + strcpy (cval,cpar); + } + else + value = NULL; + } + } + } + else + strcpy (cval, line); + + value = cval; + + return (value); +} + + +/* Find value for specified IRAF keyword */ + +static char * +isearch (hstring,keyword) + +/* Find entry for keyword keyword in IRAF keyword value string hstring. + NULL is returned if the keyword is not found */ + +const char *hstring; /* character string containing fits-style header + information in the format = {/ } + the default is that each entry is 80 characters long; + however, lines may be of arbitrary length terminated by + nulls, carriage returns or linefeeds, if packed is true. */ +const char *keyword; /* character string containing the name of the variable + to be returned. isearch searches for a line beginning + with this string. The string may be a character + literal or a character variable terminated by a null + or '$'. it is truncated to 8 characters. */ +{ + char *loc, *headnext, *headlast, *pval; + int lastchar, nextchar, lkey, nleft, lhstr; + +/* Search header string for variable name */ + lhstr = 0; + while (lhstr < 57600 && hstring[lhstr] != 0) + lhstr++; + headlast = (char *) hstring + lhstr; + headnext = (char *) hstring; + pval = NULL; + lkey = strlen (keyword); + while (headnext < headlast) { + nleft = headlast - headnext; + loc = strnsrch (headnext, keyword, nleft); + + /* Exit if keyword is not found */ + if (loc == NULL) { + break; + } + + nextchar = (int) *(loc + lkey); + lastchar = (int) *(loc - 1); + + /* If parameter name in header is longer, keep searching */ + if (nextchar != 61 && nextchar > 32 && nextchar < 127) + headnext = loc + 1; + + /* If start of string, keep it */ + else if (loc == hstring) { + pval = loc; + break; + } + + /* If preceeded by a blank or tab, keep it */ + else if (lastchar == 32 || lastchar == 9) { + pval = loc; + break; + } + + else + headnext = loc + 1; + } + + /* Find start of value string for this keyword */ + if (pval != NULL) { + pval = pval + lkey; + while (*pval == ' ' || *pval == '=') + pval++; + } + + /* Return pointer to calling program */ + return (pval); + +} + +/* Mar 12 1998 New subroutines + * Apr 15 1998 Set IGET() and ISEARCH() static when defined + * Apr 24 1998 Add MGETI4(), MGETR8(), and MGETS() for single step IRAF ext. + * Jun 1 1998 Add VMS patch from Harry Payne at STScI + * Jul 9 1998 Fix bracket token extraction after Paul Sydney + + * May 5 1999 values.h -> POSIX limits.h: MAXINT->INT_MAX, MAXSHORT->SHRT_MAX + * Oct 21 1999 Fix declarations after lint + * + * Feb 11 2000 Stop search for end of quoted keyword if more than 500 chars + * Jul 20 2000 Drop unused variables squot, dquot, and slash in igetc() + * + * Jun 26 2002 Change maximum string length from 600 to 2000; use MAX_LVAL + * Jun 26 2002 Stop search for end of quoted keyword if > MAX_LVAL chars + * + * Sep 23 2003 Change mgets() to mgetstr() to avoid name collision at UCO Lick + * + * Feb 26 2004 Make igetc() accessible from outside this file + * + * Jan 4 2007 Declare header, keyword to be const + */ diff --git a/astroem/imhfile.c b/astroem/imhfile.c new file mode 100644 index 00000000..b618686e --- /dev/null +++ b/astroem/imhfile.c @@ -0,0 +1,1941 @@ +/*** File imhfile.c + *** March 27, 2012 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1996-2012 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + + * Module: imhfile.c (IRAF .imh image file reading and writing) + * Purpose: Read and write IRAF image files (and translate headers) + * Subroutine: check_immagic (irafheader, teststring ) + * Verify that file is valid IRAF imhdr or impix + * Subroutine: irafrhead (filename, lfhead, fitsheader, lihead) + * Read IRAF image header + * Subroutine: irafrimage (fitsheader) + * Read IRAF image pixels (call after irafrhead) + * Subroutine: same_path (pixname, hdrname) + * Put filename and header path together + * Subroutine: iraf2fits (hdrname, irafheader, nbiraf, nbfits) + * Convert IRAF image header to FITS image header + * Subroutine: irafwhead (hdrname, irafheader, fitsheader) + * Write IRAF header file + * Subroutine: irafwimage (hdrname, irafheader, fitsheader, image ) + * Write IRAF image and header files + * Subroutine: fits2iraf (fitsheader, irafheader) + * Convert FITS image header to IRAF image header + * Subroutine: irafgeti4 (irafheader, offset) + * Get 4-byte integer from arbitrary part of IRAF header + * Subroutine: irafgetc2 (irafheader, offset) + * Get character string from arbitrary part of IRAF v.1 header + * Subroutine: irafgetc (irafheader, offset) + * Get character string from arbitrary part of IRAF header + * Subroutine: iraf2str (irafstring, nchar) + * Convert 2-byte/char IRAF string to 1-byte/char string + * Subroutine: str2iraf (string, irafstring, nchar) + * Convert 1-byte/char string to IRAF 2-byte/char string + * Subroutine: irafswap (bitpix,string,nbytes) + * Swap bytes in string in place, with FITS bits/pixel code + * Subroutine: irafswap2 (string,nbytes) + * Swap bytes in string in place + * Subroutine irafswap4 (string,nbytes) + * Reverse bytes of Integer*4 or Real*4 vector in place + * Subroutine irafswap8 (string,nbytes) + * Reverse bytes of Real*8 vector in place + * Subroutine irafsize (filename) + * Return length of file in bytes + * Subroutine isiraf (filename) + * Return 1 if IRAF .imh file, else 0 + + + * Copyright: 2000 Smithsonian Astrophysical Observatory + * You may do anything you like with this file except remove + * this copyright. The Smithsonian Astrophysical Observatory + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include /* define stderr, FD, and NULL */ +#include +#include +#include +#include +#include +#include +#include "fitsfile.h" + +/* Parameters from iraf/lib/imhdr.h for IRAF version 1 images */ +#define SZ_IMPIXFILE 79 /* name of pixel storage file */ +#define SZ_IMHDRFILE 79 /* length of header storage file */ +#define SZ_IMTITLE 79 /* image title string */ +#define LEN_IMHDR 2052 /* length of std header */ + +/* Parameters from iraf/lib/imhdr.h for IRAF version 2 images */ +#define SZ_IM2PIXFILE 255 /* name of pixel storage file */ +#define SZ_IM2HDRFILE 255 /* name of header storage file */ +#define SZ_IM2TITLE 383 /* image title string */ +#define LEN_IM2HDR 2046 /* length of std header */ + +/* Offsets into header in bytes for parameters in IRAF version 1 images */ +#define IM_HDRLEN 12 /* Length of header in 4-byte ints */ +#define IM_PIXTYPE 16 /* Datatype of the pixels */ +#define IM_NDIM 20 /* Number of dimensions */ +#define IM_LEN 24 /* Length (as stored) */ +#define IM_PHYSLEN 52 /* Physical length (as stored) */ +#define IM_PIXOFF 88 /* Offset of the pixels */ +#define IM_CTIME 108 /* Time of image creation */ +#define IM_MTIME 112 /* Time of last modification */ +#define IM_LIMTIME 116 /* Time of min,max computation */ +#define IM_MAX 120 /* Maximum pixel value */ +#define IM_MIN 124 /* Maximum pixel value */ +#define IM_PIXFILE 412 /* Name of pixel storage file */ +#define IM_HDRFILE 572 /* Name of header storage file */ +#define IM_TITLE 732 /* Image name string */ + +/* Offsets into header in bytes for parameters in IRAF version 2 images */ +#define IM2_HDRLEN 6 /* Length of header in 4-byte ints */ +#define IM2_PIXTYPE 10 /* Datatype of the pixels */ +#define IM2_SWAPPED 14 /* Pixels are byte swapped */ +#define IM2_NDIM 18 /* Number of dimensions */ +#define IM2_LEN 22 /* Length (as stored) */ +#define IM2_PHYSLEN 50 /* Physical length (as stored) */ +#define IM2_PIXOFF 86 /* Offset of the pixels */ +#define IM2_CTIME 106 /* Time of image creation */ +#define IM2_MTIME 110 /* Time of last modification */ +#define IM2_LIMTIME 114 /* Time of min,max computation */ +#define IM2_MAX 118 /* Maximum pixel value */ +#define IM2_MIN 122 /* Maximum pixel value */ +#define IM2_PIXFILE 126 /* Name of pixel storage file */ +#define IM2_HDRFILE 382 /* Name of header storage file */ +#define IM2_TITLE 638 /* Image name string */ + +/* Codes from iraf/unix/hlib/iraf.h */ +#define TY_CHAR 2 +#define TY_SHORT 3 +#define TY_INT 4 +#define TY_LONG 5 +#define TY_REAL 6 +#define TY_DOUBLE 7 +#define TY_COMPLEX 8 +#define TY_POINTER 9 +#define TY_STRUCT 10 +#define TY_USHORT 11 +#define TY_UBYTE 12 + +#define LEN_IRAFHDR 25000 +#define LEN_PIXHDR 1024 +#define LEN_FITSHDR 11520 + +int check_immagic(); +int irafgeti4(); +float irafgetr4(); +char *irafgetc2(); +char *irafgetc(); +char *iraf2str(); +static char *same_path(); +static void irafputr4(); +static void irafputi4(); +static void irafputc2(); +static void irafputc(); +static void str2iraf(); +static int headswap=-1; /* =1 to swap data bytes of foreign IRAF file */ +static void irafswap(); +static void irafswap2(); +static void irafswap4(); +static void irafswap8(); +int head_version (); +int pix_version (); +int irafncmp (); +static int machswap(); +static int irafsize(); + +#define SECONDS_1970_TO_1980 315532800L + +/* Subroutine: irafrhead + * Purpose: Open and read the iraf .imh file, translating it to FITS, too. + * Returns: NULL if failure, else pointer to IRAF .imh image header + * Notes: The imhdr format is defined in iraf/lib/imhdr.h, some of + * which defines or mimicked, above. + */ + +char * +irafrhead (filename, lihead) + +char *filename; /* Name of IRAF header file */ +int *lihead; /* Length of IRAF image header in bytes (returned) */ +{ + FILE *fd; + int nbr; + char *irafheader; + int nbhead, nbytes; + int imhver; + + headswap = -1; + *lihead = 0; + + /* open the image header file */ + fd = fopen (filename, "rb"); + if (fd == NULL) { + fprintf (stderr, "IRAFRHEAD: cannot open file %s to read\n", filename); + return (NULL); + } + + /* Find size of image header file */ + if ((nbhead = irafsize (fd)) <= 0) { + fprintf (stderr, "IRAFRHEAD: cannot read file %s, size = %d\n", + filename, nbhead); + return (NULL); + } + + /* allocate initial sized buffer */ + nbytes = nbhead + 5000; + irafheader = (char *) calloc (nbytes/4, 4); + if (irafheader == NULL) { + (void)fprintf(stderr, "IRAFRHEAD Cannot allocate %d-byte header\n", + nbytes); + return (NULL); + } + *lihead = nbytes; + + /* Read IRAF header */ + nbr = fread (irafheader, 1, nbhead, fd); + fclose (fd); + + /* Reject if header less than minimum length */ + if (nbr < LEN_PIXHDR) { + (void)fprintf(stderr, "IRAFRHEAD header file %s: %d / %d bytes read.\n", + filename,nbr,LEN_PIXHDR); + free (irafheader); + return (NULL); + } + + /* Check header magic word */ + imhver = head_version (irafheader); + if (imhver < 1) { + free (irafheader); + (void)fprintf(stderr, "IRAFRHEAD: %s is not a valid IRAF image header\n", + filename); + return(NULL); + } + + /* check number of image dimensions + if (imhver == 2) + ndim = irafgeti4 (irafheader, IM2_NDIM]) + else + ndim = irafgeti4 (irafheader, IM_NDIM]) + if (ndim < 2) { + free (irafheader); + (void)fprintf(stderr, "File %s does not contain 2d image\n", filename); + return (NULL); + } */ + + return (irafheader); +} + + +char * +irafrimage (fitsheader) + +char *fitsheader; /* FITS image header (filled) */ +{ + FILE *fd; + char *bang; + int naxis, naxis1, naxis2, naxis3, npaxis1, npaxis2,bitpix, bytepix, pixswap, i; + char *image; + int nbr, nbimage, nbaxis, nbl, nbdiff, lpname; + char *pixheader; + char *linebuff, *pixchar; + int imhver, lpixhead, len; + char pixname[SZ_IM2PIXFILE+1]; + char newpixname[SZ_IM2HDRFILE+1]; + + /* Convert pixel file name to character string */ + hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixname); + + /* Drop trailing spaces */ + lpname = strlen (pixname); + pixchar = pixname + lpname - 1; + while (*pixchar == ' ') + *pixchar = (char) 0; + + hgeti4 (fitsheader, "PIXOFF", &lpixhead); + + /* Open pixel file, ignoring machine name if present */ + if ((bang = strchr (pixname, '!')) != NULL ) + fd = fopen (bang + 1, "rb"); + else + fd = fopen (pixname, "rb"); + + /* If not at pathname in header, try same directory as header file */ + if (!fd) { + hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, newpixname); + len = strlen (newpixname); + newpixname[len-3] = 'p'; + newpixname[len-2] = 'i'; + newpixname[len-1] = 'x'; + fd = fopen (newpixname, "rb"); + } + + /* Print error message and exit if pixel file is not found */ + if (!fd) { + (void)fprintf(stderr, + "IRAFRIMAGE: Cannot open IRAF pixel file %s\n", pixname); + return (NULL); + } + + /* Read pixel header */ + pixheader = (char *) calloc (lpixhead/4, 4); + if (pixheader == NULL) { + (void)fprintf(stderr, "IRAFRIMAGE Cannot allocate %d-byte pixel header\n", + lpixhead); + return (NULL); + } + nbr = fread (pixheader, 1, lpixhead, fd); + + /* Check size of pixel header */ + if (nbr < lpixhead) { + (void)fprintf(stderr, "IRAF pixel file %s: %d / %d bytes read.\n", + pixname,nbr,LEN_PIXHDR); + free (pixheader); + fclose (fd); + return (NULL); + } + + /* check pixel header magic word */ + imhver = pix_version (pixheader); + if (imhver < 1) { + (void)fprintf(stderr, "File %s not valid IRAF pixel file.\n", pixname); + free (pixheader); + fclose (fd); + return(NULL); + } + free (pixheader); + + /* Find number of bytes to read */ + hgeti4 (fitsheader,"NAXIS",&naxis); + hgeti4 (fitsheader,"NAXIS1",&naxis1); + hgeti4 (fitsheader,"NAXIS2",&naxis2); + hgeti4 (fitsheader,"NPAXIS1",&npaxis1); + hgeti4 (fitsheader,"NPAXIS2",&npaxis2); + hgeti4 (fitsheader,"BITPIX",&bitpix); + if (bitpix < 0) + bytepix = -bitpix / 8; + else + bytepix = bitpix / 8; + + /* If either dimension is one and image is 3-D, read all three dimensions */ + if (naxis == 3 && ((naxis1 == 1) | (naxis2 == 1))) { + hgeti4 (fitsheader,"NAXIS3",&naxis3); + nbimage = naxis1 * naxis2 * naxis3 * bytepix; + } + else { + nbimage = naxis1 * naxis2 * bytepix; + naxis3 = 1; + } + + if (bytepix > 4) + image = (char *) calloc (nbimage/8, 8); + else if (bytepix > 2) + image = (char *) calloc (nbimage/4, 4); + else if (bytepix > 1) + image = (char *) calloc (nbimage/2, 2); + else + image = (char *) calloc (nbimage, 1); + if (image == NULL) { + (void)fprintf(stderr, "IRAFRIMAGE Cannot allocate %d-byte image buffer\n", + nbimage); + return (NULL); + } + + /* Read IRAF image all at once if physical and image dimensions are the same */ + if (npaxis1 == naxis1) + nbr = fread (image, 1, nbimage, fd); + + /* Read IRAF image one line at a time if physical and image dimensions differ */ + else { + nbdiff = (npaxis1 - naxis1) * bytepix; + nbaxis = naxis1 * bytepix; + linebuff = image; + nbr = 0; + if (naxis2 == 1 && naxis3 > 1) + naxis2 = naxis3; + for (i = 0; i < naxis2; i++) { + nbl = fread (linebuff, 1, nbaxis, fd); + nbr = nbr + nbl; + (void) fseek (fd, nbdiff, SEEK_CUR); + linebuff = linebuff + nbaxis; + } + } + fclose (fd); + + /* Check size of image */ + if (nbr < nbimage) { + (void)fprintf(stderr, "IRAF pixel file %s: %d / %d bytes read.\n", + pixname,nbr,nbimage); + free (image); + return (NULL); + } + + /* Byte-reverse image, if necessary */ + pixswap = 0; + hgetl (fitsheader, "PIXSWAP", &pixswap); + if (pixswap) + irafswap (bitpix, image, nbimage); + + return (image); +} + + +/* Return IRAF image format version number from magic word in IRAF header*/ + +int +head_version (irafheader) + +char *irafheader; /* IRAF image header from file */ + +{ + + /* Check header file magic word */ + if (irafncmp (irafheader, "imhdr", 5) != 0 ) { + if (strncmp (irafheader, "imhv2", 5) != 0) + return (0); + else + return (2); + } + else + return (1); +} + + +/* Return IRAF image format version number from magic word in IRAF pixel file */ + +int +pix_version (irafheader) + +char *irafheader; /* IRAF image header from file */ + +{ + + /* Check pixel file header magic word */ + if (irafncmp (irafheader, "impix", 5) != 0) { + if (strncmp (irafheader, "impv2", 5) != 0) + return (0); + else + return (2); + } + else + return (1); +} + + +/* Verify that file is valid IRAF imhdr or impix by checking first 5 chars + * Returns: 0 on success, 1 on failure */ + +int +irafncmp (irafheader, teststring, nc) + +char *irafheader; /* IRAF image header from file */ +char *teststring; /* C character string to compare */ +int nc; /* Number of characters to compate */ + +{ + char *line; + + headswap = -1; + if ((line = iraf2str (irafheader, nc)) == NULL) + return (1); + if (strncmp (line, teststring, nc) == 0) { + free (line); + return (0); + } + else { + free (line); + return (1); + } +} + +/* Convert IRAF image header to FITS image header, returning FITS header */ + +char * +iraf2fits (hdrname, irafheader, nbiraf, nbfits) + +char *hdrname; /* IRAF header file name (may be path) */ +char *irafheader; /* IRAF image header */ +int nbiraf; /* Number of bytes in IRAF header */ +int *nbfits; /* Number of bytes in FITS header (returned) */ + +{ + char *objname; /* object name from FITS file */ + int lstr, i, j, k, ib, nax, nbits, nl; + int lname = 0; + char *pixname, *newpixname, *bang, *chead; + char *fitsheader; + int nblock, nlines; + char *fhead, *fhead1, *fp, endline[81]; + char irafchar; + char fitsline[81]; + char *dstring; + int pixtype; + int imhver, n, imu, pixoff, impixoff, immax, immin, imtime; + int imndim, imlen, imphyslen, impixtype, pixswap, hpixswap, mtime; + float rmax, rmin; + + headswap = -1; + + /* Set up last line of FITS header */ + (void)strncpy (endline,"END", 3); + for (i = 3; i < 80; i++) + endline[i] = ' '; + endline[80] = 0; + + /* Check header magic word */ + imhver = head_version (irafheader); + if (imhver < 1) { + (void)fprintf(stderr, "File %s not valid IRAF image header\n", + hdrname); + return(NULL); + } + if (imhver == 2) { + nlines = 24 + ((nbiraf - LEN_IM2HDR) / 81); + imndim = IM2_NDIM; + imlen = IM2_LEN; + imphyslen = IM2_PHYSLEN; + impixtype = IM2_PIXTYPE; + impixoff = IM2_PIXOFF; + imtime = IM2_MTIME; + immax = IM2_MAX; + immin = IM2_MIN; + } + else { + nlines = 24 + ((nbiraf - LEN_IMHDR) / 162); + imndim = IM_NDIM; + imlen = IM_LEN; + imphyslen = IM_PHYSLEN; + impixtype = IM_PIXTYPE; + impixoff = IM_PIXOFF; + imtime = IM_MTIME; + immax = IM_MAX; + immin = IM_MIN; + } + + /* Initialize FITS header */ + nblock = (nlines * 80) / 2880; + *nbfits = (nblock + 5) * 2880 + 4; + fitsheader = (char *) calloc (*nbfits, 1); + if (fitsheader == NULL) { + (void)fprintf(stderr, "IRAF2FITS Cannot allocate %d-byte FITS header\n", + *nbfits); + return (NULL); + } + hlength (fitsheader, *nbfits); + fhead = fitsheader; + (void)strncpy (fitsheader, endline, 80); + hputl (fitsheader, "SIMPLE", 1); + fhead = fhead + 80; + + /* Set pixel size in FITS header */ + pixtype = irafgeti4 (irafheader, impixtype); + switch (pixtype) { + case TY_CHAR: + nbits = 8; + break; + case TY_UBYTE: + nbits = 8; + break; + case TY_SHORT: + nbits = 16; + break; + case TY_USHORT: + nbits = -16; + break; + case TY_INT: + case TY_LONG: + nbits = 32; + break; + case TY_REAL: + nbits = -32; + break; + case TY_DOUBLE: + nbits = -64; + break; + default: + (void)fprintf(stderr,"Unsupported data type: %d\n", pixtype); + return (NULL); + } + hputi4 (fitsheader,"BITPIX",nbits); + hputcom (fitsheader,"BITPIX", "IRAF .imh pixel type"); + fhead = fhead + 80; + + /* Set image dimensions in FITS header */ + nax = irafgeti4 (irafheader, imndim); + hputi4 (fitsheader,"NAXIS",nax); + hputcom (fitsheader,"NAXIS", "IRAF .imh naxis"); + fhead = fhead + 80; + + n = irafgeti4 (irafheader, imlen); + hputi4 (fitsheader, "NAXIS1", n); + hputcom (fitsheader,"NAXIS1", "IRAF .imh image naxis[1]"); + fhead = fhead + 80; + + if (nax > 1) { + n = irafgeti4 (irafheader, imlen+4); + hputi4 (fitsheader, "NAXIS2", n); + hputcom (fitsheader,"NAXIS2", "IRAF .imh image naxis[2]"); + } + else + hputi4 (fitsheader, "NAXIS2", 1); + hputcom (fitsheader,"NAXIS2", "IRAF .imh naxis[2]"); + fhead = fhead + 80; + + if (nax > 2) { + n = irafgeti4 (irafheader, imlen+8); + hputi4 (fitsheader, "NAXIS3", n); + hputcom (fitsheader,"NAXIS3", "IRAF .imh image naxis[3]"); + fhead = fhead + 80; + } + if (nax > 3) { + n = irafgeti4 (irafheader, imlen+12); + hputi4 (fitsheader, "NAXIS4", n); + hputcom (fitsheader,"NAXIS4", "IRAF .imh image naxis[4]"); + fhead = fhead + 80; + } + + /* Set object name in FITS header */ + if (imhver == 2) + objname = irafgetc (irafheader, IM2_TITLE, SZ_IM2TITLE); + else + objname = irafgetc2 (irafheader, IM_TITLE, SZ_IMTITLE); + if ((lstr = strlen (objname)) < 8) { + for (i = lstr; i < 8; i++) + objname[i] = ' '; + objname[8] = 0; + } + hputs (fitsheader,"OBJECT",objname); + hputcom (fitsheader,"OBJECT", "IRAF .imh title"); + free (objname); + fhead = fhead + 80; + + /* Save physical axis lengths so image file can be read */ + n = irafgeti4 (irafheader, imphyslen); + hputi4 (fitsheader, "NPAXIS1", n); + hputcom (fitsheader,"NPAXIS1", "IRAF .imh physical naxis[1]"); + fhead = fhead + 80; + if (nax > 1) { + n = irafgeti4 (irafheader, imphyslen+4); + hputi4 (fitsheader, "NPAXIS2", n); + hputcom (fitsheader,"NPAXIS2", "IRAF .imh physical naxis[2]"); + fhead = fhead + 80; + } + if (nax > 2) { + n = irafgeti4 (irafheader, imphyslen+8); + hputi4 (fitsheader, "NPAXIS3", n); + hputcom (fitsheader,"NPAXIS3", "IRAF .imh physical naxis[3]"); + fhead = fhead + 80; + } + if (nax > 3) { + n = irafgeti4 (irafheader, imphyslen+12); + hputi4 (fitsheader, "NPAXIS4", n); + hputcom (fitsheader,"NPAXIS4", "IRAF .imh physical naxis[4]"); + fhead = fhead + 80; + } + + /* Save image minimum and maximum in header */ + rmax = irafgetr4 (irafheader, immax); + rmin = irafgetr4 (irafheader, immin); + if (rmin != rmax) { + hputr4 (fitsheader, "IRAFMIN", &rmin); + fhead = fhead + 80; + hputcom (fitsheader,"IRAFMIN", "IRAF .imh minimum"); + hputr4 (fitsheader, "IRAFMAX", &rmax); + hputcom (fitsheader,"IRAFMAX", "IRAF .imh maximum"); + fhead = fhead + 80; + } + + /* Save image header filename in header */ + nl = hputm (fitsheader,"IMHFIL",hdrname); + if (nl > 0) { + lname = strlen (hdrname); + strcpy (fitsline, "IRAF header file name"); + if (lname < 43) + hputcom (fitsheader,"IMHFIL_1", fitsline); + else if (lname > 67 && lname < 110) + hputcom (fitsheader,"IMHFIL_2", fitsline); + else if (lname > 134 && lname < 177) + hputcom (fitsheader,"IMHFIL_3", fitsline); + } + if (nl > 0) fhead = fhead + (nl * 80); + + /* Save image pixel file pathname in header */ + if (imhver == 2) + pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); + else + pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE); + if (strncmp(pixname, "HDR", 3) == 0 ) { + newpixname = same_path (pixname, hdrname); + free (pixname); + pixname = newpixname; + } + if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { + newpixname = same_path (pixname, hdrname); + free (pixname); + pixname = newpixname; + } + + if ((bang = strchr (pixname, '!')) != NULL ) + nl = hputm (fitsheader,"PIXFIL",bang+1); + else + nl = hputm (fitsheader,"PIXFIL",pixname); + free (pixname); + if (nl > 0) { + strcpy (fitsline, "IRAF .pix pixel file"); + if (lname < 43) + hputcom (fitsheader,"PIXFIL_1", fitsline); + else if (lname > 67 && lname < 110) + hputcom (fitsheader,"PIXFIL_2", fitsline); + else if (lname > 134 && lname < 177) + hputcom (fitsheader,"PIXFIL_3", fitsline); + } + if (nl > 0) fhead = fhead + (nl * 80); + + /* Save image offset from star of pixel file */ + pixoff = irafgeti4 (irafheader, impixoff); + pixoff = (pixoff - 1) * 2; + hputi4 (fitsheader, "PIXOFF", pixoff); + hputcom (fitsheader,"PIXOFF", "IRAF .pix pixel offset (Do not change!)"); + fhead = fhead + 80; + + /* Save IRAF file format version in header */ + hputi4 (fitsheader,"IMHVER",imhver); + hputcom (fitsheader,"IMHVER", "IRAF .imh format version (1 or 2)"); + fhead = fhead + 80; + + /* Set flag if header numbers are byte-reversed on this machine */ + if (machswap() != headswap) + hputl (fitsheader, "HEADSWAP", 1); + else + hputl (fitsheader, "HEADSWAP", 0); + hputcom (fitsheader,"HEADSWAP", "IRAF header, FITS byte orders differ if T"); + fhead = fhead + 80; + + /* Set flag if image pixels are byte-reversed on this machine */ + if (imhver == 2) { + hpixswap = irafgeti4 (irafheader, IM2_SWAPPED); + if (headswap && !hpixswap) + pixswap = 1; + else if (!headswap && hpixswap) + pixswap = 1; + else + pixswap = 0; + } + else + pixswap = headswap; + if (machswap() != pixswap) + hputl (fitsheader, "PIXSWAP", 1); + else + hputl (fitsheader, "PIXSWAP", 0); + hputcom (fitsheader,"PIXSWAP", "IRAF pixels, FITS byte orders differ if T"); + fhead = fhead + 80; + + /* Read modification time */ + mtime = irafgeti4 (irafheader, imtime); + if (mtime == 0) + dstring = lt2fd (); + else + dstring = tsi2fd (mtime); + hputs (fitsheader, "DATE-MOD", dstring); + hputcom (fitsheader,"DATE-MOD", "Date of latest file modification"); + free (dstring); + fhead = fhead + 80; + + /* Add user portion of IRAF header to FITS header */ + fitsline[80] = 0; + if (imhver == 2) { + imu = LEN_IM2HDR; + chead = irafheader; + j = 0; + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + for (i = imu; i < nbiraf; i++) { + irafchar = chead[i]; + if (irafchar == 0) + break; + else if (irafchar == 10) { + (void)strncpy (fhead, fitsline, 80); + /* fprintf (stderr,"%80s\n",fitsline); */ + if (strncmp (fitsline, "OBJECT ", 7) != 0) { + fhead = fhead + 80; + } + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + j = 0; + } + else { + if (j > 80) { + if (strncmp (fitsline, "OBJECT ", 7) != 0) { + (void)strncpy (fhead, fitsline, 80); + /* fprintf (stderr,"%80s\n",fitsline); */ + j = 9; + fhead = fhead + 80; + } + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + } + if (irafchar > 32 && irafchar < 127) + fitsline[j] = irafchar; + j++; + } + } + } + else { + imu = LEN_IMHDR; + chead = irafheader; + if (headswap == 1) + ib = 0; + else + ib = 1; + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + j = 0; + for (i = imu; i < nbiraf; i=i+2) { + irafchar = chead[i+ib]; + if (irafchar == 0) + break; + else if (irafchar == 10) { + if (strncmp (fitsline, "OBJECT ", 7) != 0) { + (void)strncpy (fhead, fitsline, 80); + fhead = fhead + 80; + } + /* fprintf (stderr,"%80s\n",fitsline); */ + j = 0; + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + } + else { + if (j > 80) { + if (strncmp (fitsline, "OBJECT ", 7) != 0) { + (void)strncpy (fhead, fitsline, 80); + j = 9; + fhead = fhead + 80; + } + /* fprintf (stderr,"%80s\n",fitsline); */ + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + } + if (irafchar > 32 && irafchar < 127) + fitsline[j] = irafchar; + j++; + } + } + } + + /* Add END to last line */ + (void)strncpy (fhead, endline, 80); + + /* Find end of last 2880-byte block of header */ + fhead = ksearch (fitsheader, "END") + 80; + nblock = *nbfits / 2880; + fhead1 = fitsheader + (nblock * 2880); + + /* Pad rest of header with spaces */ + strncpy (endline," ",3); + for (fp = fhead; fp < fhead1; fp = fp + 80) { + (void)strncpy (fp, endline,80); + } + + return (fitsheader); +} + + +int +irafwhead (hdrname, lhead, irafheader, fitsheader) + +char *hdrname; /* Name of IRAF header file */ +int lhead; /* Length of IRAF header */ +char *irafheader; /* IRAF header */ +char *fitsheader; /* FITS image header */ + +{ + int fd; + int nbw, nbhead, lphead, pixswap; + + /* Get rid of redundant header information */ + hgeti4 (fitsheader, "PIXOFF", &lphead); + hgeti4 (fitsheader, "PIXSWAP", &pixswap); + + /* Write IRAF header file */ + + /* Convert FITS header to IRAF header */ + irafheader = fits2iraf (fitsheader, irafheader, lhead, &nbhead); + if (irafheader == NULL) { + fprintf (stderr, "IRAFWIMAGE: file %s header error\n", hdrname); + return (-1); + } + + /* Open the output file */ + if (!access (hdrname, 0)) { + fd = open (hdrname, O_WRONLY); + if (fd < 3) { + fprintf (stderr, "IRAFWIMAGE: file %s not writeable\n", hdrname); + return (0); + } + } + else { + fd = open (hdrname, O_RDWR+O_CREAT, 0666); + if (fd < 3) { + fprintf (stderr, "IRAFWIMAGE: cannot create file %s\n", hdrname); + return (0); + } + } + + /* Write IRAF header to disk file */ + nbw = write (fd, irafheader, nbhead); + (void) ftruncate (fd, nbhead); + close (fd); + if (nbw < nbhead) { + (void)fprintf(stderr, "IRAF header file %s: %d / %d bytes written.\n", + hdrname, nbw, nbhead); + return (-1); + } + + return (nbw); +} + +/* IRAFWIMAGE -- write IRAF .imh header file and .pix image file + * No matter what the input, this always writes in the local byte order */ + +int +irafwimage (hdrname, lhead, irafheader, fitsheader, image ) + +char *hdrname; /* Name of IRAF header file */ +int lhead; /* Length of IRAF header */ +char *irafheader; /* IRAF header */ +char *fitsheader; /* FITS image header */ +char *image; /* IRAF image */ + +{ + int fd; + char *bang; + int nbw, bytepix, bitpix, naxis, naxis1, naxis2, nbimage, lphead; + char *pixn, *newpixname; + char pixname[SZ_IM2PIXFILE+1]; + int imhver, pixswap; + + hgeti4 (fitsheader, "IMHVER", &imhver); + + if (!hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixname)) { + if (imhver == 2) + pixn = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); + else + pixn = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE); + if (strncmp(pixn, "HDR", 3) == 0 ) { + newpixname = same_path (pixn, hdrname); + strcpy (pixname, newpixname); + free (newpixname); + } + else { + if ((bang = strchr (pixn, '!')) != NULL ) + strcpy (pixname, bang+1); + else + strcpy (pixname, pixn); + } + free (pixn); + } + + /* Find number of bytes to write */ + hgeti4 (fitsheader,"NAXIS",&naxis); + hgeti4 (fitsheader,"NAXIS1",&naxis1); + hgeti4 (fitsheader,"NAXIS2",&naxis2); + hgeti4 (fitsheader,"BITPIX",&bitpix); + if (bitpix < 0) + bytepix = -bitpix / 8; + else + bytepix = bitpix / 8; + + /* If either dimension is one and image is 3-D, read all three dimensions */ + if (naxis == 3 && ((naxis1 == 1) | (naxis2 == 1))) { + int naxis3; + hgeti4 (fitsheader,"NAXIS3",&naxis3); + nbimage = naxis1 * naxis2 * naxis3 * bytepix; + } + else + nbimage = naxis1 * naxis2 * bytepix; + + /* Read information about pixel file from header */ + hgeti4 (fitsheader, "PIXOFF", &lphead); + hgeti4 (fitsheader, "PIXSWAP", &pixswap); + + /* Write IRAF header file */ + if (irafwhead (hdrname, lhead, irafheader, fitsheader)) + return (0); + + /* Open the output file */ + if (!access (pixname, 0)) { + fd = open (pixname, O_WRONLY); + if (fd < 3) { + fprintf (stderr, "IRAFWIMAGE: file %s not writeable\n", pixname); + return (0); + } + } + else { + fd = open (pixname, O_RDWR+O_CREAT, 0666); + if (fd < 3) { + fprintf (stderr, "IRAFWIMAGE: cannot create file %s\n", pixname); + return (0); + } + } + + /* Write header to IRAF pixel file */ + if (imhver == 2) + irafputc ("impv2", irafheader, 0, 5); + else + irafputc2 ("impix", irafheader, 0, 5); + nbw = write (fd, irafheader, lphead); + + /* Byte-reverse image, if necessary */ + if (pixswap) + irafswap (bitpix, image, nbimage); + + /* Write data to IRAF pixel file */ + nbw = write (fd, image, nbimage); + close (fd); + + return (nbw); +} + + +/* Put filename and header path together */ + +static char * +same_path (pixname, hdrname) + +char *pixname; /* IRAF pixel file pathname */ +char *hdrname; /* IRAF image header file pathname */ + +{ + int len, plen; + char *newpixname; + + newpixname = (char *) calloc (SZ_IM2PIXFILE, 1); + + /* Pixel file is in same directory as header */ + if (strncmp(pixname, "HDR$", 4) == 0 ) { + (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); + + /* find the end of the pathname */ + len = strlen (newpixname); +#ifndef VMS + while( (len > 0) && (newpixname[len-1] != '/') ) +#else + while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') ) +#endif + len--; + + /* add name */ + newpixname[len] = '\0'; + plen = strlen (pixname) - 4; + if (len + plen > SZ_IM2PIXFILE) + (void)strncat (newpixname, &pixname[4], SZ_IM2PIXFILE - len); + else + (void)strncat (newpixname, &pixname[4], plen); + } + + /* Bare pixel file with no path is assumed to be same as HDR$filename */ + else if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { + (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); + + /* find the end of the pathname */ + len = strlen (newpixname); +#ifndef VMS + while( (len > 0) && (newpixname[len-1] != '/') ) +#else + while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') ) +#endif + len--; + + /* add name */ + newpixname[len] = '\0'; + (void)strncat (newpixname, pixname, SZ_IM2PIXFILE); + } + + /* Pixel file has same name as header file, but with .pix extension */ + else if (strncmp (pixname, "HDR", 3) == 0) { + + /* load entire header name string into name buffer */ + (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); + len = strlen (newpixname); + newpixname[len-3] = 'p'; + newpixname[len-2] = 'i'; + newpixname[len-1] = 'x'; + } + + return (newpixname); +} + +/* Convert FITS image header to IRAF image header, returning IRAF header */ +/* No matter what the input, this always writes in the local byte order */ + +char * +fits2iraf (fitsheader, irafheader, nbhead, nbiraf) + +char *fitsheader; /* FITS image header */ +char *irafheader; /* IRAF image header (returned updated) */ +int nbhead; /* Length of IRAF header */ +int *nbiraf; /* Length of returned IRAF header */ + +{ + int i, n, pixoff, lhdrdir; + short *irafp, *irafs, *irafu; + char *iraf2u, *iraf2p, *filename, *hdrdir; + char *fitsend, *fitsp, pixfile[SZ_IM2PIXFILE], hdrfile[SZ_IM2HDRFILE]; + char title[SZ_IM2TITLE], temp[80]; + int nax, nlfits, imhver, nbits, pixtype, hdrlength, mtime; + int imndim, imlen, imphyslen, impixtype, imhlen, imtime, immax, immin; + float rmax, rmin; + + hgeti4 (fitsheader, "IMHVER", &imhver); + hdel (fitsheader, "IMHVER"); + hdel (fitsheader, "IMHVER"); + hgetl (fitsheader, "HEADSWAP", &headswap); + hdel (fitsheader, "HEADSWAP"); + hdel (fitsheader, "HEADSWAP"); + if (imhver == 2) { + imhlen = IM2_HDRLEN; + imndim = IM2_NDIM; + imlen = IM2_LEN; + imtime = IM2_MTIME; + imphyslen = IM2_PHYSLEN; + impixtype = IM2_PIXTYPE; + immax = IM2_MAX; + immin = IM2_MIN; + } + else { + imhlen = IM_HDRLEN; + imndim = IM_NDIM; + imlen = IM_LEN; + imtime = IM_MTIME; + imphyslen = IM_PHYSLEN; + impixtype = IM_PIXTYPE; + immax = IM_MAX; + immin = IM_MIN; + } + + /* Delete FITS header keyword not needed by IRAF */ + hdel (fitsheader,"SIMPLE"); + + /* Set IRAF image data type */ + hgeti4 (fitsheader,"BITPIX", &nbits); + switch (nbits) { + case 8: + pixtype = TY_CHAR; + break; + case -8: + pixtype = TY_UBYTE; + break; + case 16: + pixtype = TY_SHORT; + break; + case -16: + pixtype = TY_USHORT; + break; + case 32: + pixtype = TY_INT; + break; + case -32: + pixtype = TY_REAL; + break; + case -64: + pixtype = TY_DOUBLE; + break; + default: + (void)fprintf(stderr,"Unsupported data type: %d\n", nbits); + return (NULL); + } + irafputi4 (irafheader, impixtype, pixtype); + hdel (fitsheader,"BITPIX"); + + /* Set IRAF image dimensions */ + hgeti4 (fitsheader,"NAXIS",&nax); + irafputi4 (irafheader, imndim, nax); + hdel (fitsheader,"NAXIS"); + + hgeti4 (fitsheader, "NAXIS1", &n); + irafputi4 (irafheader, imlen, n); + irafputi4 (irafheader, imphyslen, n); + hdel (fitsheader,"NAXIS1"); + + hgeti4 (fitsheader,"NAXIS2",&n); + irafputi4 (irafheader, imlen+4, n); + irafputi4 (irafheader, imphyslen+4, n); + hdel (fitsheader,"NAXIS2"); + + if (nax > 2) { + hgeti4 (fitsheader,"NAXIS3",&n); + irafputi4 (irafheader, imlen+8, n); + irafputi4 (irafheader, imphyslen+8, n); + hdel (fitsheader,"NAXIS3"); + } + + if (nax > 3) { + hgeti4 (fitsheader,"NAXIS4",&n); + irafputi4 (irafheader, imlen+12, n); + irafputi4 (irafheader, imphyslen+12, n); + hdel (fitsheader,"NAXIS4"); + } + + /* Set image pixel value limits */ + rmin = 0.0; + hgetr4 (fitsheader, "IRAFMIN", &rmin); + rmax = 0.0; + hgetr4 (fitsheader, "IRAFMAX", &rmax); + if (rmin != rmax) { + irafputr4 (irafheader, immax, rmax); + irafputr4 (irafheader, immin, rmin); + } + hdel (fitsheader, "IRAFMIN"); + hdel (fitsheader, "IRAFMAX"); + + /* Replace pixel file name, if it is in the FITS header */ + if (hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixfile)) { + if (strchr (pixfile, '/')) { + if (hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, hdrfile)) { + hdrdir = strrchr (hdrfile, '/'); + if (hdrdir != NULL) { + lhdrdir = hdrdir - hdrfile + 1; + if (!strncmp (pixfile, hdrfile, lhdrdir)) { + filename = pixfile + lhdrdir; + strcpy (temp, "HDR$"); + strcat (temp,filename); + strcpy (pixfile, temp); + } + } + if (pixfile[0] != '/' && pixfile[0] != 'H') { + strcpy (temp, "HDR$"); + strcat (temp,pixfile); + strcpy (pixfile, temp); + } + } + } + + if (imhver == 2) + irafputc (pixfile, irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); + else + irafputc2 (pixfile, irafheader, IM_PIXFILE, SZ_IMPIXFILE); + hdel (fitsheader,"PIXFIL_1"); + hdel (fitsheader,"PIXFIL_2"); + hdel (fitsheader,"PIXFIL_3"); + hdel (fitsheader,"PIXFIL_4"); + } + + /* Replace header file name, if it is in the FITS header */ + if (hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, pixfile)) { + if (!strchr (pixfile,'/') && !strchr (pixfile,'$')) { + strcpy (temp, "HDR$"); + strcat (temp,pixfile); + strcpy (pixfile, temp); + } + if (imhver == 2) + irafputc (pixfile, irafheader, IM2_HDRFILE, SZ_IM2HDRFILE); + else + irafputc2 (pixfile, irafheader, IM_HDRFILE, SZ_IMHDRFILE); + hdel (fitsheader, "IMHFIL_1"); + hdel (fitsheader, "IMHFIL_2"); + hdel (fitsheader, "IMHFIL_3"); + hdel (fitsheader, "IMHFIL_4"); + } + + /* Replace image title, if it is in the FITS header */ + if (hgets (fitsheader, "OBJECT", SZ_IM2TITLE, title)) { + if (imhver == 2) + irafputc (title, irafheader, IM2_TITLE, SZ_IM2TITLE); + else + irafputc2 (title, irafheader, IM_TITLE, SZ_IMTITLE); + hdel (fitsheader, "OBJECT"); + } + hgeti4 (fitsheader, "PIXOFF", &pixoff); + hdel (fitsheader, "PIXOFF"); + hdel (fitsheader, "PIXOFF"); + hdel (fitsheader, "PIXSWAP"); + hdel (fitsheader, "PIXSWAP"); + hdel (fitsheader, "DATE-MOD"); + hdel (fitsheader, "DATE-MOD"); + fitsend = ksearch (fitsheader,"END"); + + /* Find length of FITS header */ + fitsend = ksearch (fitsheader,"END"); + nlfits = ((fitsend - fitsheader) / 80); + + /* Find new length of IRAF header */ + if (imhver == 2) + *nbiraf = LEN_IM2HDR + (81 * nlfits); + else + *nbiraf = LEN_IMHDR + (162 * nlfits); + if (*nbiraf > nbhead) + irafheader = realloc (irafheader, *nbiraf); + + /* Reset modification time */ + mtime = lt2tsi (); + irafputi4 (irafheader, imtime, mtime); + + /* Replace user portion of IRAF header with remaining FITS header */ + if (imhver == 2) { + iraf2u = irafheader + LEN_IM2HDR; + iraf2p = iraf2u; + for (fitsp = fitsheader; fitsp < fitsend; fitsp = fitsp + 80) { + for (i = 0; i < 80; i++) + *iraf2p++ = fitsp[i]; + *iraf2p++ = 10; + } + *iraf2p++ = 0; + *nbiraf = iraf2p - irafheader; + hdrlength = 1 + *nbiraf / 2; + } + else { + irafs = (short *)irafheader; + irafu = irafs + (LEN_IMHDR / 2); + irafp = irafu; + for (fitsp = fitsheader; fitsp < fitsend; fitsp = fitsp + 80) { + for (i = 0; i < 80; i++) + *irafp++ = (short) fitsp[i]; + *irafp++ = 10; + } + *irafp++ = 0; + *irafp++ = 32; + *nbiraf = 2 * (irafp - irafs); + hdrlength = *nbiraf / 4; + } + + /* Length of header file */ + irafputi4 (irafheader, imhlen, hdrlength); + + /* Offset in .pix file to first pixel data + hputi4 (fitsheader, "PIXOFF", pixoff); */ + + /* Return number of bytes in new IRAF header */ + return (irafheader); +} + + +int +irafgeti4 (irafheader, offset) + +char *irafheader; /* IRAF image header */ +int offset; /* Number of bytes to skip before number */ + +{ + char *ctemp, *cheader; + int temp; + + cheader = irafheader; + ctemp = (char *) &temp; + + /* If header swap flag not set, set it now */ + if (headswap < 0) { + if (cheader[offset] > 0) + headswap = 1; + else + headswap = 0; + } + + if (machswap() != headswap) { + ctemp[3] = cheader[offset]; + ctemp[2] = cheader[offset+1]; + ctemp[1] = cheader[offset+2]; + ctemp[0] = cheader[offset+3]; + } + else { + ctemp[0] = cheader[offset]; + ctemp[1] = cheader[offset+1]; + ctemp[2] = cheader[offset+2]; + ctemp[3] = cheader[offset+3]; + } + return (temp); +} + + +float +irafgetr4 (irafheader, offset) + +char *irafheader; /* IRAF image header */ +int offset; /* Number of bytes to skip before number */ + +{ + char *ctemp, *cheader; + float temp; + + cheader = irafheader; + ctemp = (char *) &temp; + + /* If header swap flag not set, set it now */ + if (headswap < 0) { + if (cheader[offset] > 0) + headswap = 1; + else + headswap = 0; + } + + if (machswap() != headswap) { + ctemp[3] = cheader[offset]; + ctemp[2] = cheader[offset+1]; + ctemp[1] = cheader[offset+2]; + ctemp[0] = cheader[offset+3]; + } + else { + ctemp[0] = cheader[offset]; + ctemp[1] = cheader[offset+1]; + ctemp[2] = cheader[offset+2]; + ctemp[3] = cheader[offset+3]; + } + return (temp); +} + + +/* IRAFGETC2 -- Get character string from arbitrary part of v.1 IRAF header */ + +char * +irafgetc2 (irafheader, offset, nc) + +char *irafheader; /* IRAF image header */ +int offset; /* Number of bytes to skip before string */ +int nc; /* Maximum number of characters in string */ + +{ + char *irafstring, *string; + + irafstring = irafgetc (irafheader, offset, 2*(nc+1)); + string = iraf2str (irafstring, nc); + free (irafstring); + + return (string); +} + + +/* IRAFGETC -- Get character string from arbitrary part of IRAF header */ + +char * +irafgetc (irafheader, offset, nc) + +char *irafheader; /* IRAF image header */ +int offset; /* Number of bytes to skip before string */ +int nc; /* Maximum number of characters in string */ + +{ + char *ctemp, *cheader; + int i; + + cheader = irafheader; + ctemp = (char *) calloc (nc+1, 1); + if (ctemp == NULL) { + (void)fprintf(stderr, "IRAFGETC Cannot allocate %d-byte variable\n", + nc+1); + return (NULL); + } + for (i = 0; i < nc; i++) { + ctemp[i] = cheader[offset+i]; + if (ctemp[i] > 0 && ctemp[i] < 32) + ctemp[i] = ' '; + } + + return (ctemp); +} + + +/* Convert IRAF 2-byte/char string to 1-byte/char string */ + +char * +iraf2str (irafstring, nchar) + +char *irafstring; /* IRAF 2-byte/character string */ +int nchar; /* Number of characters in string */ +{ + char *string; + int i, j; + + /* Set swap flag according to position of nulls in 2-byte characters */ + if (headswap < 0) { + if (irafstring[0] != 0 && irafstring[1] == 0) + headswap = 1; + else if (irafstring[0] == 0 && irafstring[1] != 0) + headswap = 0; + else + return (NULL); + } + + string = (char *) calloc (nchar+1, 1); + if (string == NULL) { + (void)fprintf(stderr, "IRAF2STR Cannot allocate %d-byte variable\n", + nchar+1); + return (NULL); + } + + /* Swap bytes, if requested */ + if (headswap) + j = 0; + else + j = 1; + + /* Convert appropriate byte of input to output character */ + for (i = 0; i < nchar; i++) { + string[i] = irafstring[j]; + j = j + 2; + } + + return (string); +} + + +/* IRAFPUTI4 -- Insert 4-byte integer into arbitrary part of IRAF header */ + +static void +irafputi4 (irafheader, offset, inum) + +char *irafheader; /* IRAF image header */ +int offset; /* Number of bytes to skip before number */ +int inum; /* Number to put into header */ + +{ + char *cn, *chead; + + chead = irafheader; + cn = (char *) &inum; + if (headswap < 0) + headswap = 0; + if (headswap != machswap()) { + chead[offset+3] = cn[0]; + chead[offset+2] = cn[1]; + chead[offset+1] = cn[2]; + chead[offset] = cn[3]; + } + else { + chead[offset] = cn[0]; + chead[offset+1] = cn[1]; + chead[offset+2] = cn[2]; + chead[offset+3] = cn[3]; + } + return; +} + + +/* IRAFPUTR4 -- Insert 4-byte real number into arbitrary part of IRAF header */ + +static void +irafputr4 (irafheader, offset, rnum) + +char *irafheader; /* IRAF image header */ +int offset; /* Number of bytes to skip before number */ +float rnum; /* Number to put into header */ + +{ + char *cn, *chead; + + chead = irafheader; + cn = (char *) &rnum; + if (headswap < 0) + headswap = 0; + if (headswap != machswap()) { + chead[offset+3] = cn[0]; + chead[offset+2] = cn[1]; + chead[offset+1] = cn[2]; + chead[offset] = cn[3]; + } + else { + chead[offset] = cn[0]; + chead[offset+1] = cn[1]; + chead[offset+2] = cn[2]; + chead[offset+3] = cn[3]; + } + return; +} + + +/* IRAFPUTC2 -- Insert character string into arbitrary part of v.1 IRAF header */ + +static void +irafputc2 (string, irafheader, offset, nc) + +char *string; /* String to insert into header */ +char *irafheader; /* IRAF image header */ +int offset; /* Number of bytes to skip before string */ +int nc; /* Maximum number of characters in string */ + +{ + char *irafstring; + + irafstring = (char *) calloc (2 * nc, 1); + if (irafstring == NULL) { + (void)fprintf(stderr, "IRAFPUTC2 Cannot allocate %d-byte variable\n", + 2 * nc); + } + str2iraf (string, irafstring, nc); + irafputc (irafstring, irafheader, offset, 2*nc); + + return; +} + + +/* IRAFPUTC -- Insert character string into arbitrary part of IRAF header */ + +static void +irafputc (string, irafheader, offset, nc) + +char *string; /* String to insert into header */ +char *irafheader; /* IRAF image header */ +int offset; /* Number of bytes to skip before string */ +int nc; /* Maximum number of characters in string */ + +{ + char *chead; + int i; + + chead = irafheader; + for (i = 0; i < nc; i++) + chead[offset+i] = string[i]; + + return; +} + + +/* STR2IRAF -- Convert 1-byte/char string to IRAF 2-byte/char string */ + +static void +str2iraf (string, irafstring, nchar) + +char *string; /* 1-byte/character string */ +char *irafstring; /* IRAF 2-byte/character string */ +int nchar; /* Maximum number of characters in IRAF string */ +{ + int i, j, nc, nbytes; + + nc = strlen (string); + + /* Fill output string with zeroes */ + nbytes = nchar * 2; + for (i = 0; i < nbytes; i++) + irafstring[i] = 0; + + /* If swapped, start with first byte of 2-byte characters */ + if (headswap) + j = 0; + else + j = 1; + + /* Move input characters to appropriate bytes of output */ + for (i = 0; i < nchar; i++) { + if (i > nc) + irafstring[j] = 0; + else + irafstring[j] = string[i]; + j = j + 2; + } + + return; +} + + +/* IRAFSWAP -- Reverse bytes of any type of vector in place */ + +static void +irafswap (bitpix, string, nbytes) + +int bitpix; /* Number of bits per pixel */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +char *string; /* Address of starting point of bytes to swap */ +int nbytes; /* Number of bytes to swap */ + +{ + switch (bitpix) { + + case 16: + if (nbytes < 2) return; + irafswap2 (string,nbytes); + break; + + case 32: + if (nbytes < 4) return; + irafswap4 (string,nbytes); + break; + + case -16: + if (nbytes < 2) return; + irafswap2 (string,nbytes); + break; + + case -32: + if (nbytes < 4) return; + irafswap4 (string,nbytes); + break; + + case -64: + if (nbytes < 8) return; + irafswap8 (string,nbytes); + break; + + } + return; +} + + +/* IRAFSWAP2 -- Swap bytes in string in place */ + +static void +irafswap2 (string,nbytes) + + +char *string; /* Address of starting point of bytes to swap */ +int nbytes; /* Number of bytes to swap */ + +{ + char *sbyte, temp, *slast; + + slast = string + nbytes; + sbyte = string; + while (sbyte < slast) { + temp = sbyte[0]; + sbyte[0] = sbyte[1]; + sbyte[1] = temp; + sbyte= sbyte + 2; + } + return; +} + + +/* IRAFSWAP4 -- Reverse bytes of Integer*4 or Real*4 vector in place */ + +static void +irafswap4 (string,nbytes) + +char *string; /* Address of Integer*4 or Real*4 vector */ +int nbytes; /* Number of bytes to reverse */ + +{ + char *sbyte, *slast; + char temp0, temp1, temp2, temp3; + + slast = string + nbytes; + sbyte = string; + while (sbyte < slast) { + temp3 = sbyte[0]; + temp2 = sbyte[1]; + temp1 = sbyte[2]; + temp0 = sbyte[3]; + sbyte[0] = temp0; + sbyte[1] = temp1; + sbyte[2] = temp2; + sbyte[3] = temp3; + sbyte = sbyte + 4; + } + + return; +} + + +/* IRAFSWAP8 -- Reverse bytes of Real*8 vector in place */ + +static void +irafswap8 (string,nbytes) + +char *string; /* Address of Real*8 vector */ +int nbytes; /* Number of bytes to reverse */ + +{ + char *sbyte, *slast; + char temp[8]; + + slast = string + nbytes; + sbyte = string; + while (sbyte < slast) { + temp[7] = sbyte[0]; + temp[6] = sbyte[1]; + temp[5] = sbyte[2]; + temp[4] = sbyte[3]; + temp[3] = sbyte[4]; + temp[2] = sbyte[5]; + temp[1] = sbyte[6]; + temp[0] = sbyte[7]; + sbyte[0] = temp[0]; + sbyte[1] = temp[1]; + sbyte[2] = temp[2]; + sbyte[3] = temp[3]; + sbyte[4] = temp[4]; + sbyte[5] = temp[5]; + sbyte[6] = temp[6]; + sbyte[7] = temp[7]; + sbyte = sbyte + 8; + } + return; +} + + +/* Set flag if machine on which program is executing is not FITS byte order + * ( i.e., if it is an Alpha or PC instead of a Sun ) */ + +static int +machswap () + +{ + char *ctest; + int itest; + + itest = 1; + ctest = (char *)&itest; + if (*ctest) + return (1); + else + return (0); +} + + +/* ISIRAF -- return 1 if IRAF imh file, else 0 */ + +int +isiraf (filename) + +char *filename; /* Name of file for which to find size */ +{ + if (strchr (filename, '=')) + return (0); + else if (strsrch (filename, ".imh")) + return (1); + else + return (0); +} + + +/* IRAFSIZE -- return size of file in bytes */ + +static int +irafsize (diskfile) + +FILE *diskfile; /* Descriptor of file for which to find size */ +{ + long filesize; + long offset; + + offset = (long) 0; + + /* Move to end of the file */ + if (fseek (diskfile, offset, SEEK_END) == 0) { + + /* Position is the size of the file */ + filesize = ftell (diskfile); + + /* Move file pointer back tot he start of the file */ + fseek (diskfile, offset, SEEK_SET); + } + + else + filesize = -1; + + return (filesize); +} + +/* Feb 15 1996 New file + * Apr 10 1996 Add more documentation + * Apr 17 1996 Print error message on open failure + * Jun 5 1996 Add byte swapping (reversal); use streams + * Jun 10 1996 Make fixes after running lint + * Jun 12 1996 Use IMSWAP subroutines instead of local ones + * Jul 3 1996 Go back to using local IRAFSWAP subroutines + * Jul 3 1996 Write to pixel file from FITS header + * Jul 10 1996 Allocate all headers + * Aug 13 1996 Add unistd.h to include list + * Aug 26 1996 Allow 1-d images; fix comments; fix arguments after lint + * Aug 26 1996 Add IRAF header lingth argument to IRAFWIMAGE and IRAFWHEAD + * Aug 28 1996 Clean up code in IRAF2FITS + * Aug 30 1996 Use write instead of fwrite + * Sep 4 1996 Fix write mode bug + * Oct 15 1996 Drop unused variables + * Oct 17 1996 Minor fix after lint; cast arguments to STR2IRAF + * + * May 15 1997 Fix returned header length in IRAF2FITS + * Dec 19 1997 Add IRAF version 2 .imh files + * + * Jan 2 1998 Allow uneven length of user parameter lines in IRAF headers + * Jan 6 1998 Fix output of imh2 headers; allow newlines in imh1 headers + * Jan 14 1998 Handle byte reversing correctly + * Apr 17 1998 Add new IRAF data types unsigned char and unsigned short + * Apr 30 1998 Fix error return if illegal data type after Allan Brighton + * May 15 1998 Delete header keywords used for IRAF binary values + * May 15 1998 Fix bug so FITS OBJECT is put into IRAF title + * May 26 1998 Fix bug in fits2iraf keeping track of end of header + * May 27 1998 Include fitsio.h instead of fitshead.h + * Jun 4 1998 Write comments into header for converted IRAF binary values + * Jun 4 1998 Pad FITS strings to 8 character minimum + * Jul 24 1998 Write header file length to IRAF header file + * Jul 27 1998 Print error messages to stderr for all failed malloc's + * Jul 27 1998 Fix bug padding FITS header with spaces in iraf2fits + * Jul 27 1998 Write modification time to IRAF header file + * Aug 6 1998 Change fitsio.h to fitsfile.h; imhio.c to imhfile.c + * Oct 1 1998 Set irafswap flag only once per file + * Oct 5 1998 Add subroutines irafsize() and isiraf() + * Nov 16 1998 Fix byte-swap checking + * + * Jan 27 1999 Read and write all of 3D image if one dimension is =1 + * Jul 13 1999 Improve error messages; change irafsize() argument to fd + * Sep 22 1999 Don't copy OBJECT keyword from .imh file; use binary title + * Oct 14 1999 Set FITS header length + * Oct 20 1999 Allocate 5000 extra bytes for IRAF header + * Nov 2 1999 Fix getclocktime() to use only time.h subroutines + * Nov 2 1999 Add modification date and time to FITS header in iraf2fits() + * Nov 24 1999 Delete HEADSWAP, IMHVER, DATE-MOD from header before writing + * Nov 29 1999 Delete PIXSWAP, IRAF-MIN, IRAF-MAX from header before writing + * + * Jan 13 2000 Fix bug which dropped characters in iraf2fits() + * Feb 3 2000 Declare timezone long, not time_t; drop unused variable + * Mar 7 2000 Add more code to keep pixel file path short + * Mar 10 2000 Fix bugs when writing .imh file headers + * Mar 21 2000 Change computation of IRAF time tags to use only data structure + * Mar 22 2000 Move IRAF time tag computation to lt2tsi() in dateutil.c + * Mar 24 2000 Use Unix file update time if none in header + * Mar 27 2000 Use hputm() to save file paths up to 256 characters + * Mar 27 2000 Write filename comments after 1st keyword with short value + * Mar 27 2000 Allocate pixel file name in same_path to imh2 length + * Mar 29 2000 Add space after last linefeed of header in fits2iraf() + * Apr 28 2000 Dimension pixname in irafwimage() + * May 1 2000 Fix code for updating pixel file name with HDR$ in fits2iraf() + * Jun 2 2000 Drop unused variables in fits2iraf() after lint + * Jun 12 2000 If pixel filename has no / or $, use same path as header file + * Sep 6 2000 Use header directory if pixel file not found at its pathname + * + * Jan 11 2001 Print all messages to stderr + * Aug 24 2001 In isiraf(), return 0 if argument contains an equal sign + * + * Apr 8 2002 Fix bug in error message for unidentified nbits in fits2iraf() + * + * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern) + * Oct 31 2003 Read image only in irafrimage() if physical dimension > image dim. + * Nov 3 2003 Set NAXISi to image, not physical dimensions in iraf2fits() + * + * Jun 13 2005 Drop trailing spaces on pixel file name + * + * Jun 20 2006 Initialize uninitialized variables + * + * Jan 4 2007 Change hputr4() calls to send pointer to value + * Jan 8 2007 Drop unused variable nbx in irafrimage() + * Jan 8 2007 Align header and image buffers properly by 4 and by BITPIX + * + * May 20 2011 Free newpixname, not pixname in irafwimage() + * + * Mar 27 2012 Fix pixname's appending to newpixname to avoid overflow + */ diff --git a/astroem/imio.c b/astroem/imio.c new file mode 100644 index 00000000..9bbf5a4b --- /dev/null +++ b/astroem/imio.c @@ -0,0 +1,1543 @@ +/*** File wcslib/imio.c + *** October 30, 2012 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1996-2012 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + + * Module: imio.c (image pixel manipulation) + * Purpose: Read and write pixels from arbitrary data type 2D arrays + * Subroutine: getpix (image, bitpix, w, h, bz, bs, x, y) + * Read pixel from 2D image of any numeric type (0,0 lower left) + * Subroutine: getpix1 (image, bitpix, w, h, bz, bs, x, y) + * Read pixel from 2D image of any numeric type (1,1 lower left) + * Subroutine: putpix (image, bitpix, w, h, bz, bs, x, y, dpix) + * Write pixel into 2D image of any numeric type (0,0 lower left) + * Subroutine: putpix1 (image, bitpix, w, h, bz, bs, x, y, dpix) + * Write pixel into 2D image of any numeric type (1,1 lower left) + * Subroutine: addpix (image, bitpix, w, h, bz, bs, x, y, dpix) + * Copy pixel into 2D image of any numeric type (0,0 lower left) + * Subroutine: addpix1 (image, bitpix, w, h, bz, bs, x, y, dpix) + * Add pixel into 2D image of any numeric type (1,1 lower left) + * Subroutine: maxvec (image, bitpix, bz, bs, pix1, npix) + * Get maximum of vector from 2D image of any numeric type + * Subroutine: minvec (image, bitpix, bz, bs, pix1, npix) + * Get minimum of vector from 2D image of any numeric type + * Subroutine: getvec (image, bitpix, bz, bs, pix1, npix, dvec) + * Get vector from 2D image of any numeric type + * Subroutine: putvec (image, bitpix, bz, bs, pix1, npix, dvec) + * Copy pixel vector into a vector of any numeric type + * Subroutine: addvec (image, bitpix, bz, bs, pix1, npix, dpix) + * Add constant to pixel values in a vector + * Subroutine: multvec (image, bitpix, bz, bs, pix1, npix, dpix) + * Multiply pixel values in a vector by a constant + * Subroutine: fillvec (image, bitpix, bz, bs, pix1, npix, dpix) + * Copy pixel value in a vector of any numeric type + * Subroutine: fillvec1 (image, bitpix, bz, bs, pix1, npix, dpix) + * Copy pixel value int a vector of any numeric type + * Subroutine: movepix (image1, bitpix, w1, x1, y1, image2, w2, x2, y2) + * Copy pixel from one image location to another + * Subroutine: imswap (bitpix,string,nbytes) + * Swap bytes in string in place, with FITS bits/pixel code + * Subroutine: imswap2 (string,nbytes) + * Swap bytes in string in place + * Subroutine imswap4 (string,nbytes) + * Reverse bytes of Integer*4 or Real*4 vector in place + * Subroutine imswap8 (string,nbytes) + * Reverse bytes of Real*8 vector in place + * Subroutine imswapped () + * Return 1 if PC/DEC byte order, else 0 + */ + +#include +#include +#include "fitsfile.h" + +static int scale = 1; /* If 0, skip scaling step */ +void +setscale (scale0) +int scale0; +{scale = scale0; return;} + +/* GETPIX1 -- Get pixel from 2D FITS image of any numeric type */ + +double +getpix1 (image, bitpix, w, h, bzero, bscale, x, y) + +char *image; /* Image array as 1-D vector */ +int bitpix; /* FITS bits per pixel */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +int w; /* Image width in pixels */ +int h; /* Image height in pixels */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int x; /* One-based horizontal pixel number */ +int y; /* One-based vertical pixel number */ + +{ + return (getpix (image, bitpix, w, h, bzero, bscale, x-1, y-1)); +} + + +/* GETPIX -- Get pixel from 2D image of any numeric type */ + +double +getpix (image, bitpix, w, h, bzero, bscale, x, y) + +char *image; /* Image array as 1-D vector */ +int bitpix; /* FITS bits per pixel */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +int w; /* Image width in pixels */ +int h; /* Image height in pixels */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int x; /* Zero-based horizontal pixel number */ +int y; /* Zero-based vertical pixel number */ + +{ + short *im2; + int *im4; + unsigned char *im1; + unsigned short *imu; + float *imr; + double *imd; + double dpix; + +/* Return 0 if coordinates are not inside image */ + if (x < 0 || x >= w) + return (0.0); + if (y < 0 || y >= h) + return (0.0); + +/* Extract pixel from appropriate type of array */ + switch (bitpix) { + + case 8: + im1 = (unsigned char *)image; + dpix = (double) im1[(y*w) + x]; + break; + + case 16: + im2 = (short *)image; + dpix = (double) im2[(y*w) + x]; + break; + + case 32: + im4 = (int *)image; + dpix = (double) im4[(y*w) + x]; + break; + + case -16: + imu = (unsigned short *)image; + dpix = (double) imu[(y*w) + x]; + break; + + case -32: + imr = (float *)image; + dpix = (double) imr[(y*w) + x]; + break; + + case -64: + imd = (double *)image; + dpix = imd[(y*w) + x]; + break; + + default: + dpix = 0.0; + } + if (scale) + return (bzero + (bscale * dpix)); + else + return (dpix); +} + + +/* PUTPIX1 -- Copy pixel into 2D FITS image of any numeric type */ + +void +putpix1 (image, bitpix, w, h, bzero, bscale, x, y, dpix) + +char *image; +int bitpix; /* Number of bits per pixel */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +int w; /* Image width in pixels */ +int h; /* Image height in pixels */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int x; /* One-based horizontal pixel number */ +int y; /* One-based vertical pixel number */ +double dpix; + +{ + putpix (image, bitpix, w, h, bzero, bscale, x-1, y-1, dpix); + return; +} + + +/* PUTPIX -- Copy pixel into 2D image of any numeric type */ + +void +putpix (image, bitpix, w, h, bzero, bscale, x, y, dpix) + +char *image; +int bitpix; /* Number of bits per pixel */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +int w; /* Image width in pixels */ +int h; /* Image height in pixels */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int x; +int y; +double dpix; + +{ + double *imd; + float *imr; + int *im4; + short *im2; + unsigned short *imu; + unsigned char *im1; + +/* Return if coordinates are not inside image */ + if (x < 0 || x >= w) + return; + if (y < 0 || y >= h) + return; + + if (scale) + dpix = (dpix - bzero) / bscale; + + switch (bitpix) { + + case 8: + im1 = (unsigned char *)image; + if (dpix < 0) + im1[(y*w) + x] = (unsigned char) (dpix - 0.5); + else + im1[(y*w) + x] = (unsigned char) (dpix + 0.5); + break; + + case 16: + im2 = (short *)image; + if (dpix < 0) + im2[(y*w) + x] = (short) (dpix - 0.5); + else + im2[(y*w) + x] = (short) (dpix + 0.5); + break; + + case 32: + im4 = (int *)image; + if (dpix < 0) + im4[(y*w) + x] = (int) (dpix - 0.5); + else + im4[(y*w) + x] = (int) (dpix + 0.5); + break; + + case -16: + imu = (unsigned short *)image; + if (dpix < 0) + imu[(y*w) + x] = (unsigned short) 0; + else + imu[(y*w) + x] = (unsigned short) (dpix + 0.5); + break; + + case -32: + imr = (float *)image; + imr[(y*w) + x] = (float) dpix; + break; + + case -64: + imd = (double *)image; + imd[(y*w) + x] = dpix; + break; + + } + return; +} + + +/* ADDPIX1 -- Add pixel value into 2D FITS image of any numeric type */ + +void +addpix1 (image, bitpix, w, h, bzero, bscale, x, y, dpix) + +char *image; +int bitpix; /* Number of bits per pixel */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +int w; /* Image width in pixels */ +int h; /* Image height in pixels */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int x; /* One-based horizontal pixel number */ +int y; /* One-based vertical pixel number */ +double dpix; /* Value to add to pixel */ + +{ + addpix (image, bitpix, w, h, bzero, bscale, x-1, y-1, dpix); + return; +} + + +/* ADDPIX -- Add constant to pixel values in 2D image of any numeric type */ + +void +addpix (image, bitpix, w, h, bzero, bscale, x, y, dpix) + +char *image; +int bitpix; /* Number of bits per pixel */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +int w; /* Image width in pixels */ +int h; /* Image height in pixels */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int x; /* Zero-based horizontal pixel number */ +int y; /* Zero-based vertical pixel number */ +double dpix; /* Value to add to pixel */ + +{ + double *imd; + float *imr; + int *im4; + short *im2; + unsigned short *imu; + unsigned char *im1; + int ipix; + +/* Return if coordinates are not inside image */ + if (x < 0 || x >= w) + return; + if (y < 0 || y >= h) + return; + + if (scale) + dpix = (dpix - bzero) / bscale; + ipix = (y * w) + x; + + switch (bitpix) { + + case 8: + im1 = (unsigned char *)image; + if (dpix < 0) + image[ipix] = im1[ipix] + (unsigned char) (dpix - 0.5); + else + image[ipix] = im1[ipix] + (unsigned char) (dpix + 0.5); + break; + + case 16: + im2 = (short *)image; + if (dpix < 0) + im2[ipix] = im2[ipix] + (short) (dpix - 0.5); + else + im2[ipix] = im2[ipix] + (short) (dpix + 0.5); + break; + + case 32: + im4 = (int *)image; + if (dpix < 0) + im4[ipix] = im4[ipix] + (int) (dpix - 0.5); + else + im4[ipix] = im4[ipix] + (int) (dpix + 0.5); + break; + + case -16: + imu = (unsigned short *)image; + if (dpix > 0) + imu[ipix] = imu[ipix] + (unsigned short) (dpix + 0.5); + break; + + case -32: + imr = (float *)image; + imr[ipix] = imr[ipix] + (float) dpix; + break; + + case -64: + imd = (double *)image; + imd[ipix] = imd[ipix] + dpix; + break; + + } + return; +} + + +/* MOVEPIX -- Copy pixel between images */ + +void +movepix (image1, bitpix1, w1, x1, y1, image2, bitpix2, w2, x2, y2) + +char *image1; /* Pointer to first pixel in input image */ +int bitpix1; /* Bits per input pixel (FITS codes) */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +int w1; /* Number of horizontal pixels in input image */ +int x1, y1; /* Row and column for input pixel */ + +char *image2; /* Pointer to first pixel in output image */ +int bitpix2; /* Bits per output pixel (FITS codes) */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +int w2; /* Number of horizontal pixels in output image */ +int x2, y2; /* Row and column for output pixel */ + +{ + double dpix, *imd1, *imd2; + float rpix, *imr1, *imr2; + int *imi1, *imi2; + short *ims1, *ims2; + unsigned short *imu1, *imu2; + unsigned char *imc1, *imc2; + + if (x1 < 0 || x2 < 0 || x1 >= w1 || x2 >= w2) + return; + if (y1 < 0 || y2 < 0) + return; + + switch (bitpix1) { + + case 8: + imc1 = (unsigned char *)image1; + switch (bitpix2) { + case 8: + imc2 = (unsigned char *)image2; + imc2[(y2*w2) + x2] = imc1[(y1*w1) + x1]; + break; + case 16: + ims2 = (short *)image2; + ims2[(y2*w2) + x2] = (short) imc1[(y1*w1) + x1]; + break; + case 32: + imi2 = (int *)image2; + imi2[(y2*w2) + x2] = (int) imc1[(y1*w1) + x1]; + break; + case -16: + imu2 = (unsigned short *)image2; + imu2[(y2*w2) + x2] = (unsigned short) imc1[(y1*w1) + x1]; + break; + case -32: + imr2 = (float *)image2; + imr2[(y2*w2) + x2] = (float) imc1[(y1*w1) + x1]; + break; + case -64: + imd2 = (double *)image2; + imd2[(y2*w2) + x2] = (double) imc1[(y1*w1) + x1]; + break; + } + break; + + case 16: + ims1 = (short *)image1; + switch (bitpix2) { + case 8: + imc2 = (unsigned char *)image1; + imc2[(y2*w2) + x2] = (unsigned char) ims1[(y1*w1) + x1]; + break; + case 16: + ims2 = (short *)image2; + ims2[(y2*w2) + x2] = ims1[(y1*w1) + x1]; + break; + case 32: + imi2 = (int *)image2; + imi2[(y2*w2) + x2] = (int) ims1[(y1*w1) + x1]; + break; + case -16: + imu2 = (unsigned short *)image2; + imu2[(y2*w2) + x2] = (unsigned short) ims1[(y1*w1) + x1]; + break; + case -32: + imr2 = (float *)image2; + imr2[(y2*w2) + x2] = (float) ims1[(y1*w1) + x1]; + break; + case -64: + imd2 = (double *)image2; + imd2[(y2*w2) + x2] = (double) ims1[(y1*w1) + x1]; + break; + } + break; + + case 32: + imi1 = (int *)image1; + switch (bitpix2) { + case 8: + imc2 = (unsigned char *)image2; + imc2[(y2*w2) + x2] = (unsigned char) imi1[(y1*w1) + x1]; + break; + case 16: + ims2 = (short *)image2; + ims2[(y2*w2) + x2] = (short) imi1[(y1*w1) + x1]; + break; + case 32: + imi2 = (int *)image2; + imi2[(y2*w2) + x2] = imi1[(y1*w1) + x1]; + break; + case -16: + imu2 = (unsigned short *)image2; + imu2[(y2*w2) + x2] = (unsigned short) imi1[(y1*w1) + x1]; + break; + case -32: + imr2 = (float *)image2; + imr2[(y2*w2) + x2] = (float) imi1[(y1*w1) + x1]; + break; + case -64: + imd2 = (double *)image2; + imd2[(y2*w2) + x2] = (double) imi1[(y1*w1) + x1]; + break; + } + break; + + case -16: + imu1 = (unsigned short *)image1; + switch (bitpix2) { + case 8: + imc2 = (unsigned char *)image2; + imc2[(y2*w2) + x2] = (unsigned char) imu1[(y1*w1) + x1]; + break; + case 16: + ims2 = (short *)image2; + ims2[(y2*w2) + x2] = (short) imu1[(y1*w1) + x1]; + break; + case 32: + imi2 = (int *)image2; + imi2[(y2*w2) + x2] = (int) imu1[(y1*w1) + x1]; + break; + case -16: + imu2 = (unsigned short *)image2; + imu2[(y2*w2) + x2] = imu1[(y1*w1) + x1]; + break; + case -32: + imr2 = (float *)image2; + imr2[(y2*w2) + x2] = (float) imu1[(y1*w1) + x1]; + break; + case -64: + imd2 = (double *)image2; + imd2[(y2*w2) + x2] = (double) imu1[(y1*w1) + x1]; + break; + } + break; + + case -32: + imr1 = (float *)image1; + rpix = imr1[(y1*w1) + x1]; + switch (bitpix2) { + case 8: + imc2 = (unsigned char *)image2; + if (rpix < 0.0) + imc2[(y2*w2) + x2] = (unsigned char) 0; + else + imc2[(y2*w2) + x2] = (unsigned char) (rpix + 0.5); + break; + case 16: + ims2 = (short *)image2; + if (rpix < 0.0) + ims2[(y2*w2) + x2] = (short) (rpix - 0.5); + else + ims2[(y2*w2) + x2] = (short) (rpix + 0.5); + break; + case 32: + imi2 = (int *)image2; + if (rpix < 0.0) + imi2[(y2*w2) + x2] = (int) (rpix - 0.5); + else + imi2[(y2*w2) + x2] = (int) (rpix + 0.5); + break; + case -16: + imu2 = (unsigned short *)image2; + if (rpix < 0.0) + imu2[(y2*w2) + x2] = (unsigned short) 0; + else + imu2[(y2*w2) + x2] = (unsigned short) (rpix + 0.5); + break; + case -32: + imr2 = (float *)image2; + imr2[(y2*w2) + x2] = rpix; + break; + case -64: + imd2 = (double *)image2; + imd2[(y2*w2) + x2] = (double) rpix; + break; + } + break; + + case -64: + imd1 = (double *)image1; + dpix = imd1[(y1*w1) + x1]; + switch (bitpix2) { + case 8: + imc2 = (unsigned char *)image2; + if (dpix < 0.0) + imc2[(y2*w2) + x2] = (unsigned char) 0; + else + imc2[(y2*w2) + x2] = (unsigned char) (dpix + 0.5); + break; + case 16: + ims2 = (short *)image2; + if (dpix < 0.0) + ims2[(y2*w2) + x2] = (short) (dpix - 0.5); + else + ims2[(y2*w2) + x2] = (short) (dpix + 0.5); + break; + case 32: + imi2 = (int *)image2; + if (dpix < 0.0) + imi2[(y2*w2) + x2] = (int) (dpix - 0.5); + else + imi2[(y2*w2) + x2] = (int) (dpix + 0.5); + break; + case -16: + imu2 = (unsigned short *)image2; + if (dpix < 0.0) + imu2[(y2*w2) + x2] = (unsigned short) 0; + else + imu2[(y2*w2) + x2] = (unsigned short) (dpix + 0.5); + break; + case -32: + imr2 = (float *)image2; + imr2[(y2*w2) + x2] = (float) dpix; + break; + case -64: + imd2 = (double *)image2; + imd2[(y2*w2) + x2] = dpix; + break; + } + break; + } + return; +} + + +/* MAXVEC -- Get maximum value in vector from 2D image of any numeric type */ + +double +maxvec (image, bitpix, bzero, bscale, pix1, npix) + +char *image; /* Image array from which to read vector */ +int bitpix; /* Number of bits per pixel in image */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int pix1; /* Offset of first pixel to check */ +int npix; /* Number of pixels to check */ + +{ + short *im2, imax2, ip2; + int *im4, imax4, ip4; + unsigned short *imu, imaxu, ipu; + float *imr, imaxr, ipr; + double *imd; + double dmax = 0.0; + double ipd; + int ipix, pix2; + unsigned char *imc, imaxc, ipc; + + pix2 = pix1 + npix; + + switch (bitpix) { + + case 8: + imc = (unsigned char *)(image); + imaxc = *(imc + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + ipc = *(imc + ipix); + if (ipc > imaxc) + imaxc = ipc; + } + dmax = (double) imaxc; + break; + + case 16: + im2 = (short *)image; + imax2 = *(im2 + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + ip2 = *(im2 + ipix); + if (ip2 > imax2) + imax2 = ip2; + } + dmax = (double) imax2; + break; + + case 32: + im4 = (int *)image; + imax4 = *(im4 + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + ip4 = *(im4 + ipix); + if (ip4 > imax4) + imax4 = ip4; + } + dmax = (double) imax4; + break; + + case -16: + imu = (unsigned short *)image; + imaxu = *(imu + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + ipu = *(imu + ipix); + if (ipu > imaxu) + imaxu = ipu; + } + dmax = (double) imaxu; + break; + + case -32: + imr = (float *)image; + imaxr = *(imr + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + ipr = *(imr + ipix); + if (ipr > imaxr) + imax2 = ipr; + } + dmax = (double) imaxr; + break; + + case -64: + imd = (double *)image; + dmax = *(imd + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + ipd = *(imd + ipix); + if (ipd > dmax) + dmax = ipd; + } + break; + + } + + /* Scale data if either BZERO or BSCALE keyword has been set */ + if (scale && (bzero != 0.0 || bscale != 1.0)) + dmax = (dmax * bscale) + bzero; + + return (dmax); +} + + +/* MINVEC -- Get minimum value in vector from 2D image of any numeric type */ + +double +minvec (image, bitpix, bzero, bscale, pix1, npix) + +char *image; /* Image array from which to read vector */ +int bitpix; /* Number of bits per pixel in image */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int pix1; /* Offset of first pixel to check */ +int npix; /* Number of pixels to check */ + +{ + short *im2, imin2, ip2; + int *im4, imin4, ip4; + unsigned short *imu, iminu, ipu; + float *imr, iminr, ipr; + double *imd, ipd; + double dmin = 0.0; + int ipix, pix2; + unsigned char *imc, cmin, cp; + + pix2 = pix1 + npix; + + switch (bitpix) { + + case 8: + imc = (unsigned char *)image; + cmin = *(imc + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + cp = *(imc + ipix); + if (cp < cmin) + cmin = cp; + } + dmin = (double) cmin; + break; + + case 16: + im2 = (short *)image + pix1; + imin2 = *im2; + for (ipix = pix1; ipix < pix2; ipix++) { + ip2 = *(im2 + ipix); + if (ip2 < imin2) + imin2 = ip2; + } + dmin = (double) imin2; + break; + + case 32: + im4 = (int *)image; + imin4 = *(im4 + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + ip4 = *(im4 + ipix); + if (ip4 < imin4) + imin4 = ip4; + } + dmin = (double) imin4; + break; + + case -16: + imu = (unsigned short *)image; + iminu = *(imu + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + ipu = *(imu + ipix); + if (ipu < iminu) + iminu = ipu; + } + dmin = (double) iminu; + break; + + case -32: + imr = (float *)image; + iminr = *(imr + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + ipr = *(imr + ipix); + if (ipr < iminr) + iminr = ipr; + } + dmin = (double) iminr; + break; + + case -64: + imd = (double *)image; + dmin = *(imd + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + ipd = *(imd + ipix); + if (ipd < dmin) + dmin = ipd; + } + break; + + } + + /* Scale data if either BZERO or BSCALE keyword has been set */ + if (scale && (bzero != 0.0 || bscale != 1.0)) + dmin = (dmin * bscale) + bzero; + + return (dmin); +} + + +/* ADDVEC -- Add constant to pixel values in 2D image of any numeric type */ + +void +addvec (image, bitpix, bzero, bscale, pix1, npix, dpix) + +char *image; /* Image array from which to extract vector */ +int bitpix; /* Number of bits per pixel in image */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int pix1; /* Offset of first pixel to extract */ +int npix; /* Number of pixels to extract */ +double dpix; /* Value to add to pixels */ + +{ + unsigned char *imc, ccon; + short *im2, jcon; + int *im4, icon; + unsigned short *imu, ucon; + float *imr, rcon; + double *imd; + int ipix, pix2; + + pix2 = pix1 + npix; + + if (scale) + dpix = (dpix - bzero) / bscale; + + switch (bitpix) { + + case 8: + imc = (unsigned char *) (image + pix1); + if (dpix < 0) + ccon = (unsigned char) (dpix - 0.5); + else + ccon = (unsigned char) (dpix + 0.5); + for (ipix = pix1; ipix < pix2; ipix++) + *imc++ += ccon; + break; + + case 16: + im2 = (short *) (image + pix1); + if (dpix < 0) + jcon = (short) (dpix - 0.5); + else + jcon = (short) (dpix + 0.5); + for (ipix = pix1; ipix < pix2; ipix++) + *im2++ += jcon; + break; + + case 32: + im4 = (int *) (image + pix1); + if (dpix < 0) + icon = (int) (dpix - 0.5); + else + icon = (int) (dpix + 0.5); + for (ipix = pix1; ipix < pix2; ipix++) + *im4++ += icon; + break; + + case -16: + imu = (unsigned short *) (image + pix1); + if (dpix > 0) { + ucon = (unsigned short) (dpix + 0.5); + imu = (unsigned short *) (image + pix1); + for (ipix = pix1; ipix < pix2; ipix++) + *imu++ += ucon; + } + else { + icon = (int) (dpix - 0.5); + imu = (unsigned short *) (image + pix1); + for (ipix = pix1; ipix < pix2; ipix++) { + unsigned short tmp = (icon + (int) *imu); + *imu++ += tmp; + } + } + break; + + case -32: + rcon = (float) dpix; + imr = (float *) (image + pix1); + for (ipix = pix1; ipix < pix2; ipix++) + *imr++ += rcon; + break; + + case -64: + imd = (double *) (image + pix1); + for (ipix = pix1; ipix < pix2; ipix++) + *imd++ += dpix; + break; + } + return; +} + + +/* MULTVEC -- Multiply pixel values in place in 2D image of any numeric type */ + +void +multvec (image, bitpix, bzero, bscale, pix1, npix, dpix) + +char *image; /* Image array from which to extract vector */ +int bitpix; /* Number of bits per pixel in image */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int pix1; /* Offset of first pixel to extract */ +int npix; /* Number of pixels to extract */ +double dpix; /* Value by which to multiply pixels */ + +{ + char *imc, ccon; + short *im2, jcon; + int *im4, icon, isint; + unsigned short *imu, ucon; + float *imr, rcon; + double *imd, dcon, dval; + int ipix, pix2; + + pix2 = pix1 + npix; + + if (scale) + dpix = (dpix - bzero) / bscale; + ipix = (int) dpix; + dcon = (double) ipix; + if (dcon == dpix) + isint = 1; + else + isint = 0; + + switch (bitpix) { + + case 8: + imc = image + pix1; + if (isint) { + if (dpix < 0) + ccon = (char) (dpix - 0.5); + else + ccon = (char) (dpix + 0.5); + for (ipix = pix1; ipix < pix2; ipix++) + *imc++ *= ccon; + } + else { + for (ipix = pix1; ipix < pix2; ipix++) { + dval = ((double) *imc) * dpix; + if (dval < 256.0) + *imc++ = (char) dval; + else + *imc++ = (char) 255; + } + } + break; + + case 16: + im2 = (short *) (image + pix1); + if (isint) { + im2 = (short *)image; + if (dpix < 0) + jcon = (short) (dpix - 0.5); + else + jcon = (short) (dpix + 0.5); + for (ipix = pix1; ipix < pix2; ipix++) + *im2++ *= jcon; + } + else { + for (ipix = pix1; ipix < pix2; ipix++) { + dval = ((double) *im2) * dpix; + if (dval < 32768.0) + *im2++ = (short) dval; + else + *im2++ = (short) 32767; + } + } + break; + + case 32: + im4 = (int *) (image + pix1); + if (isint) { + if (dpix < 0) + icon = (int) (dpix - 0.5); + else + icon = (int) (dpix + 0.5); + for (ipix = pix1; ipix < pix2; ipix++) + *im4++ *= icon; + } + else { + for (ipix = pix1; ipix < pix2; ipix++) { + dval = ((double) *im4) * dpix; + if (dval < 32768.0) + *im4++ = (int) dval; + else + *im4++ = (int) 32767; + } + } + break; + + case -16: + imu = (unsigned short *) (image + pix1); + if (dpix > 0) { + ucon = (unsigned short) (dpix + 0.5); + imu = (unsigned short *) (image + pix1); + for (ipix = pix1; ipix < pix2; ipix++) + *imu++ *= ucon; + } + break; + + case -32: + rcon = (float) dpix; + imr = (float *) (image + pix1); + for (ipix = pix1; ipix < pix2; ipix++) + *imr++ *= rcon; + break; + + case -64: + imd = (double *) (image + pix1); + for (ipix = pix1; ipix < pix2; ipix++) + *imd++ *= dpix; + break; + + } + return; +} + + +/* GETVEC -- Get vector from 2D image of any numeric type */ + +void +getvec (image, bitpix, bzero, bscale, pix1, npix, dvec0) + +char *image; /* Image array from which to extract vector */ +int bitpix; /* Number of bits per pixel in image */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int pix1; /* Offset of first pixel to extract */ +int npix; /* Number of pixels to extract */ +double *dvec0; /* Vector of pixels (returned) */ + +{ + short *im2; + int *im4; + unsigned short *imu; + float *imr; + double *imd; + double *dvec; + int ipix, pix2; + + pix2 = pix1 + npix; + dvec = dvec0; + + switch (bitpix) { + + case 8: + for (ipix = pix1; ipix < pix2; ipix++) + *dvec++ = (double) *(image + ipix); + break; + + case 16: + im2 = (short *)image; + for (ipix = pix1; ipix < pix2; ipix++) + *dvec++ = (double) *(im2 + ipix); + break; + + case 32: + im4 = (int *)image; + for (ipix = pix1; ipix < pix2; ipix++) + *dvec++ = (double) *(im4 + ipix); + break; + + case -16: + imu = (unsigned short *)image; + for (ipix = pix1; ipix < pix2; ipix++) + *dvec++ = (double) *(imu + ipix); + break; + + case -32: + imr = (float *)image; + for (ipix = pix1; ipix < pix2; ipix++) + *dvec++ = (double) *(imr + ipix); + break; + + case -64: + imd = (double *)image; + for (ipix = pix1; ipix < pix2; ipix++) + *dvec++ = (double) *(imd + ipix); + break; + + } + + /* Scale data if either BZERO or BSCALE keyword has been set */ + if (scale && (bzero != 0.0 || bscale != 1.0)) { + dvec = dvec0; + for (ipix = pix1; ipix < pix2; ipix++) { + *dvec = (*dvec * bscale) + bzero; + dvec++; + } + } + + return; +} + + +/* PUTVEC -- Copy pixel vector into 2D image of any numeric type */ + +void +putvec (image, bitpix, bzero, bscale, pix1, npix, dvec) + +char *image; /* Image into which to copy vector */ +int bitpix; /* Number of bits per pixel im image */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int pix1; /* Offset of first pixel of vector in image */ +int npix; /* Number of pixels to copy */ +double *dvec; /* Vector of pixels to copy */ + +{ + short *im2; + int *im4; + unsigned short *imu; + float *imr; + double *imd; + int ipix, pix2; + double *dp = dvec; + + pix2 = pix1 + npix; + + /* Scale data if either BZERO or BSCALE keyword has been set */ + if (scale && (bzero != 0.0 || bscale != 1.0)) { + for (ipix = pix1; ipix < pix2; ipix++) { + *dp = (*dp - bzero) / bscale; + dp++; + } + dp = dvec; + } + + switch (bitpix) { + + case 8: + for (ipix = pix1; ipix < pix2; ipix++) + *(image+ipix) = (char) *dp++; + break; + + case 16: + im2 = (short *)image; + for (ipix = pix1; ipix < pix2; ipix++) { + if (*dp < 0.0) + *(im2+ipix) = (short) (*dp++ - 0.5); + else + *(im2+ipix) = (short) (*dp++ + 0.5); + } + break; + + case 32: + im4 = (int *)image; + for (ipix = pix1; ipix < pix2; ipix++) { + if (*dp < 0.0) + *(im4+ipix) = (int) (*dp++ - 0.5); + else + *(im4+ipix) = (int) (*dp++ + 0.5); + } + break; + + case -16: + imu = (unsigned short *)image; + for (ipix = pix1; ipix < pix2; ipix++) { + if (*dp < 0.0) + *(imu+ipix) = (unsigned short) 0; + else + *(imu+ipix) = (unsigned short) (*dp++ + 0.5); + } + break; + + case -32: + imr = (float *)image; + for (ipix = pix1; ipix < pix2; ipix++) + *(imr+ipix) = (float) *dp++; + break; + + case -64: + imd = (double *)image; + for (ipix = pix1; ipix < pix2; ipix++) + *(imd+ipix) = (double) *dp++; + break; + } + return; +} + + +/* FILLVEC1 -- Copy single value into a vector of any numeric type */ + +void +fillvec1 (image, bitpix, bzero, bscale, pix1, npix, dpix) + +char *image; /* Vector to fill */ +int bitpix; /* Number of bits per pixel im image */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int pix1; /* First pixel to fill */ +int npix; /* Number of pixels to fill */ +double dpix; /* Value with which to fill pixels */ +{ + fillvec (image, bitpix, bzero, bscale, pix1-1, npix, dpix); + return; +} + + +/* FILLVEC -- Copy single value into a vector of any numeric type */ + +void +fillvec (image, bitpix, bzero, bscale, pix1, npix, dpix) + +char *image; /* Vector to fill */ +int bitpix; /* Number of bits per pixel im image */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +double bzero; /* Zero point for pixel scaling */ +double bscale; /* Scale factor for pixel scaling */ +int pix1; /* First pixel to fill */ +int npix; /* Number of pixels to fill */ +double dpix; /* Value with which to fill pixels */ +{ + char ipc; + short *im2, ip2; + int *im4, ip4; + unsigned short *imu, ipu; + float *imr, ipr; + double *imd; + int ipix, pix2; + double dp; + + pix2 = pix1 + npix; + + /* Scale data if either BZERO or BSCALE keyword has been set */ + dp = dpix; + if (scale && (bzero != 0.0 || bscale != 1.0)) + dp = (dp - bzero) / bscale; + + switch (bitpix) { + + case 8: + if (dp < 0.0) + ipc = (char) (dp - 0.5); + else + ipc = (char) (dp + 0.5); + for (ipix = pix1; ipix < pix2; ipix++) + image[ipix] = ipc; + break; + + case 16: + im2 = (short *)image; + if (dp < 0.0) + ip2 = (short) (dp - 0.5); + else + ip2 = (short) (dp + 0.5); + for (ipix = pix1; ipix < pix2; ipix++) + im2[ipix] = ip2; + break; + + case 32: + im4 = (int *)image; + if (dp < 0.0) + ip4 = (int) (dp - 0.5); + else + ip4 = (int) (dp + 0.5); + for (ipix = pix1; ipix < pix2; ipix++) + im4[ipix] = ip4; + break; + + case -16: + imu = (unsigned short *)image; + if (dp < 0.0) + ipu = (unsigned short) (dp - 0.5); + else + ipu = (unsigned short) (dp + 0.5); + for (ipix = pix1; ipix < pix2; ipix++) + imu[ipix] = ipu; + break; + + case -32: + imr = (float *)image; + ipr = (float) dp; + for (ipix = pix1; ipix < pix2; ipix++) + imr[ipix] = ipr; + break; + + case -64: + imd = (double *)image; + for (ipix = pix1; ipix < pix2; ipix++) + imd[ipix] = dp; + break; + } + return; +} + + +/* IMSWAP -- Reverse bytes of any type of vector in place */ + +void +imswap (bitpix, string, nbytes) + +int bitpix; /* Number of bits per pixel */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +char *string; /* Address of starting point of bytes to swap */ +int nbytes; /* Number of bytes to swap */ + +{ + switch (bitpix) { + + case 8: + break; + + case 16: + if (nbytes < 2) return; + imswap2 (string,nbytes); + break; + + case 32: + if (nbytes < 4) return; + imswap4 (string,nbytes); + break; + + case -16: + if (nbytes < 2) return; + imswap2 (string,nbytes); + break; + + case -32: + if (nbytes < 4) return; + imswap4 (string,nbytes); + break; + + case -64: + if (nbytes < 8) return; + imswap8 (string,nbytes); + break; + + } + return; +} + + +/* IMSWAP2 -- Swap bytes in string in place */ + +void +imswap2 (string,nbytes) + + +char *string; /* Address of starting point of bytes to swap */ +int nbytes; /* Number of bytes to swap */ + +{ + char *sbyte, temp, *slast; + + slast = string + nbytes; + sbyte = string; + while (sbyte < slast) { + temp = sbyte[0]; + sbyte[0] = sbyte[1]; + sbyte[1] = temp; + sbyte= sbyte + 2; + } + return; +} + + +/* IMSWAP4 -- Reverse bytes of Integer*4 or Real*4 vector in place */ + +void +imswap4 (string,nbytes) + +char *string; /* Address of Integer*4 or Real*4 vector */ +int nbytes; /* Number of bytes to reverse */ + +{ + char *sbyte, *slast; + char temp0, temp1, temp2, temp3; + + slast = string + nbytes; + sbyte = string; + while (sbyte < slast) { + temp3 = sbyte[0]; + temp2 = sbyte[1]; + temp1 = sbyte[2]; + temp0 = sbyte[3]; + sbyte[0] = temp0; + sbyte[1] = temp1; + sbyte[2] = temp2; + sbyte[3] = temp3; + sbyte = sbyte + 4; + } + + return; +} + + +/* IMSWAP8 -- Reverse bytes of Real*8 vector in place */ + +void +imswap8 (string,nbytes) + +char *string; /* Address of Real*8 vector */ +int nbytes; /* Number of bytes to reverse */ + +{ + char *sbyte, *slast; + char temp[8]; + + slast = string + nbytes; + sbyte = string; + while (sbyte < slast) { + temp[7] = sbyte[0]; + temp[6] = sbyte[1]; + temp[5] = sbyte[2]; + temp[4] = sbyte[3]; + temp[3] = sbyte[4]; + temp[2] = sbyte[5]; + temp[1] = sbyte[6]; + temp[0] = sbyte[7]; + sbyte[0] = temp[0]; + sbyte[1] = temp[1]; + sbyte[2] = temp[2]; + sbyte[3] = temp[3]; + sbyte[4] = temp[4]; + sbyte[5] = temp[5]; + sbyte[6] = temp[6]; + sbyte[7] = temp[7]; + sbyte = sbyte + 8; + } + return; +} + +/* IMSWAPPED -- Returns 0 if big-endian (Sun,Mac), + 1 if little-endian(PC,Alpha) */ + +int +imswapped () + +{ + char *ctest; + int itest; + + itest = 1; + ctest = (char *)&itest; + if (*ctest) + return (1); + else + return (0); +} + +/* Apr 17 1996 New file + * May 22 1996 Add H so that PUTPIX and GETPIX can check coordinates + * Jun 11 1996 Simplify NEWIMAGE subroutine + * Jun 12 1996 Add byte-swapping subroutines + * + * Jul 24 1997 Add 8-bit option to subroutines + * + * May 27 1998 Include imio.h instead of fitshead.h + * Jun 17 1998 Fix bug, changing all unsigned int's to unsigned short's + * + * Apr 29 1999 Add scaling to getpix, putpix, getvec, and putvec + * Apr 29 1999 Fix bug in getvec in dealing with 1-byte data + * Sep 14 1999 Change dp incrementing so it works on Alpha compiler + * Sep 27 1999 Add interface for 1-based (FITS) image access + * Sep 27 1999 Add addpix() and addpix1() + * Dec 14 1999 In putpix(), addpix(), putvec(), round when output is integer + * + * Sep 20 2000 In getvec(), scale only if necessary + * + * Nov 27 2001 In movepix(), add char to char move + * + * Jan 23 2002 Add global scale switch to turn off scaling + * Jun 4 2002 In getvec() and putvec(), change dpix to dvec + * Jun 4 2002 Add addvec() to add to a vector + * Jul 19 2002 Fix getvec() bug rescaling scaled numbers + * + * May 20 2003 Declare scale0 in setscale() + * + * Jan 28 2004 Add image limit check to movepix() + * Feb 27 2004 Add fillvec() and fillvec1() to set vector to a constant + * + * Jun 27 2005 Fix major bug in fillvec(); pass value dpix in fillvec1(), too + * Aug 18 2005 Add maxvec(), addvec(), and multvec() + * + * Mar 1 2006 Fix bug of occasional double application of bscale in getvec() + * Apr 3 2006 Fix bad cast in unisigned int section of addvec() + * May 3 2006 Code fixes in addpix and multpix suggested by Robert Lupton + * Jun 8 2006 Drop erroneous second im2 assignment without offset in addvec() + * Jun 20 2006 Fix typos masquerading as unitialized variables + * + * Jan 8 2007 Include fitsfile.h instead of imio.h + * Jun 11 2007 Add minvec() and speed up maxvec() + * + * Apr 12 2012 Fix 8-bit variables to be unsigned char + * Oct 19 2012 Fix errors with character images in minvec() and maxvec() + * Oct 30 2012 Fix errors with short images in minvec() and maxvec() + */ diff --git a/astroem/imio.h b/astroem/imio.h new file mode 100644 index 00000000..a12d8e88 --- /dev/null +++ b/astroem/imio.h @@ -0,0 +1,64 @@ +/*** imio.h memory access subroutines + *** September 27, 1999 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1996-2002 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + */ + +#ifndef imio_h_ +#define imio_h_ + +/* Image pixel access subroutines in imio.c */ +extern double getpix(); /* Read one pixel from any data type 2-D array (0,0)*/ +extern double getpix1(); /* Read one pixel from any data type 2-D array (1,1)*/ +extern void putpix(); /* Write one pixel to any data type 2-D array (0,0)*/ +extern void putpix1(); /* Write one pixel to any data type 2-D array (1,1) */ +extern void addpix(); /* Add to one pixel in any data type 2-D array (0,0)*/ +extern void addpix1(); /* Add to one pixel in any data type 2-D array (1,1)*/ +extern void movepix(); /* Move one pixel value between two 2-D arrays (0,0) */ +extern void movepix1(); /* Move one pixel value between two 2-D arrays (1,1) */ +extern void getvec(); /* Read vector from a 2-D array */ +extern void putvec(); /* Write vector into a 2-D array */ +extern void fillvec(); /* Write constant into a vector */ +extern void fillvec1(); /* Write constant into a vector */ +extern void imswap(); /* Swap alternating bytes in a vector */ +extern void imswap2(); /* Swap bytes in a vector of 2-byte (short) integers */ +extern void imswap4(); /* Reverse bytes in a vector of 4-byte numbers */ +extern void imswap8(); /* Reverse bytes in a vector of 8-byte numbers */ +extern int imswapped(); /* Return 1 if machine byte order is not FITS order */ + +#endif /* imio_h_ */ + +/* May 31 1996 Use stream I/O for reading as well as writing + * Jun 12 1996 Add byte-swapping subroutines + * Aug 6 1996 Add MOVEPIX, HDEL and HCHANGE declarations + * + * May 27 1998 Split off imio subroutines to imio.h + + * Sep 27 1999 Add Fortran-indexed (1,1), not (0,0) image access *1() + * Sep 28 1999 Add addpix() + * + * Feb 27 2004 Add fillvec() + */ diff --git a/astroem/lin.c b/astroem/lin.c new file mode 100644 index 00000000..999a9d00 --- /dev/null +++ b/astroem/lin.c @@ -0,0 +1,448 @@ +/*============================================================================= +* +* WCSLIB - an implementation of the FITS WCS proposal. +* Copyright (C) 1995-2002, Mark Calabretta +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +* Correspondence concerning WCSLIB may be directed to: +* Internet email: mcalabre@atnf.csiro.au +* Postal address: Dr. Mark Calabretta, +* Australia Telescope National Facility, +* P.O. Box 76, +* Epping, NSW, 2121, +* AUSTRALIA +* +*============================================================================= +* +* C routines which implement the FITS World Coordinate System (WCS) +* convention. +* +* Summary of routines +* ------------------- +* These utility routines apply the linear transformation defined by the WCS +* FITS header cards. There are separate routines for the image-to-pixel, +* linfwd(), and pixel-to-image, linrev(), transformations. +* +* An initialization routine, linset(), computes intermediate values from +* the transformation parameters but need not be called explicitly - see the +* explanation of lin.flag below. +* +* An auxiliary matrix inversion routine, matinv(), is included. It uses +* LU-triangular factorization with scaled partial pivoting. +* +* +* Initialization routine; linset() +* -------------------------------- +* Initializes members of a linprm data structure which hold intermediate +* values. Note that this routine need not be called directly; it will be +* invoked by linfwd() and linrev() if the "flag" structure member is +* anything other than a predefined magic value. +* +* Given and/or returned: +* lin linprm* Linear transformation parameters (see below). +* +* Function return value: +* int Error status +* 0: Success. +* 1: Memory allocation error. +* 2: PC matrix is singular. +* +* Forward transformation; linfwd() +* -------------------------------- +* Compute pixel coordinates from image coordinates. Note that where +* celestial coordinate systems are concerned the image coordinates +* correspond to (x,y) in the plane of projection, not celestial (lng,lat). +* +* Given: +* imgcrd const double[] +* Image (world) coordinate. +* +* Given and returned: +* lin linprm* Linear transformation parameters (see below). +* +* Returned: +* pixcrd d[] Pixel coordinate. +* +* Function return value: +* int Error status +* 0: Success. +* 1: The transformation is not invertible. +* +* Reverse transformation; linrev() +* -------------------------------- +* Compute image coordinates from pixel coordinates. Note that where +* celestial coordinate systems are concerned the image coordinates +* correspond to (x,y) in the plane of projection, not celestial (lng,lat). +* +* Given: +* pixcrd const double[] +* Pixel coordinate. +* +* Given and/or returned: +* lin linprm* Linear transformation parameters (see below). +* +* Returned: +* imgcrd d[] Image (world) coordinate. +* +* Function return value: +* int Error status +* 0: Success. +* 1: Error. +* +* Linear transformation parameters +* -------------------------------- +* The linprm struct consists of the following: +* +* int flag +* This flag must be set to zero whenever any of the following members +* are set or modified. This signals the initialization routine, +* linset(), to recompute intermediaries. +* int naxis +* Number of image axes. +* double *crpix +* Pointer to the first element of an array of double containing the +* coordinate reference pixel, CRPIXn. +* double *pc +* Pointer to the first element of the PC (pixel coordinate) +* transformation matrix. The expected order is +* +* lin.pc = {PC1_1, PC1_2, PC2_1, PC2_2}; +* +* This may be conveniently constructed from a two-dimensional array +* via +* +* double m[2][2] = {{PC1_1, PC1_2}, +* {PC2_1, PC2_2}}; +* +* which is equivalent to, +* +* double m[2][2]; +* m[0][0] = PC1_1; +* m[0][1] = PC1_2; +* m[1][0] = PC2_1; +* m[1][1] = PC2_2; +* +* for which the storage order is +* +* PC1_1, PC1_2, PC2_1, PC2_2 +* +* so it would be legitimate to set lin.pc = *m. +* double *cdelt +* Pointer to the first element of an array of double containing the +* coordinate increments, CDELTn. +* +* The remaining members of the linprm struct are maintained by the +* initialization routine and should not be modified. +* +* double *piximg +* Pointer to the first element of the matrix containing the product +* of the CDELTn diagonal matrix and the PC matrix. +* double *imgpix +* Pointer to the first element of the inverse of the piximg matrix. +* +* linset allocates storage for the above arrays using malloc(). Note, +* however, that these routines do not free this storage so if a linprm +* variable has itself been malloc'd then these structure members must be +* explicitly freed before the linprm variable is free'd otherwise a memory +* leak will result. +* +* Author: Mark Calabretta, Australia Telescope National Facility +* $Id: lin.c,v 2.8 2002/01/30 06:04:03 mcalabre Exp $ +*===========================================================================*/ + +#include +#include +#include "wcslib.h" + +/* Map error number to error message for each function. */ +const char *linset_errmsg[] = { + 0, + "Memory allocation error", + "PC matrix is singular"}; + +const char *linfwd_errmsg[] = { + 0, + "Memory allocation error", + "PC matrix is singular"}; + +const char *linrev_errmsg[] = { + 0, + "Memory allocation error", + "PC matrix is singular"}; + +int linset(lin) + +struct linprm *lin; + +{ + int i, ij, j, mem, n; + + n = lin->naxis; + + /* Allocate memory for internal arrays. */ + mem = n * n * sizeof(double); + lin->piximg = (double*)malloc(mem); + if (lin->piximg == (double*)0) return 1; + + lin->imgpix = (double*)malloc(mem); + if (lin->imgpix == (double*)0) { + free(lin->piximg); + return 1; + } + + /* Compute the pixel-to-image transformation matrix. */ + for (i = 0, ij = 0; i < n; i++) { + for (j = 0; j < n; j++, ij++) { + lin->piximg[ij] = lin->cdelt[i] * lin->pc[ij]; + } + } + + /* Compute the image-to-pixel transformation matrix. */ + if (matinv(n, lin->piximg, lin->imgpix)) return 2; + + lin->flag = LINSET; + + return 0; +} + +/*--------------------------------------------------------------------------*/ + +int linfwd(imgcrd, lin, pixcrd) + +const double imgcrd[]; +struct linprm *lin; +double pixcrd[]; + +{ + int i, ij, j, n; + + n = lin->naxis; + + if (lin->flag != LINSET) { + if (linset(lin)) return 1; + } + + for (i = 0, ij = 0; i < n; i++) { + pixcrd[i] = 0.0; + for (j = 0; j < n; j++, ij++) { + pixcrd[i] += lin->imgpix[ij] * imgcrd[j]; + } + } + + for (j = 0; j < n; j++) { + pixcrd[j] += lin->crpix[j]; + } + + return 0; +} + +/*--------------------------------------------------------------------------*/ + +int linrev(pixcrd, lin, imgcrd) + +const double pixcrd[]; +struct linprm *lin; +double imgcrd[]; + +{ + int i, ij, j, n; + double temp; + + n = lin->naxis; + + if (lin->flag != LINSET) { + if (linset(lin)) return 1; + } + + for (i = 0; i < n; i++) { + imgcrd[i] = 0.0; + } + + for (j = 0; j < n; j++) { + temp = pixcrd[j] - lin->crpix[j]; + for (i = 0, ij = j; i < n; i++, ij+=n) { + imgcrd[i] += lin->piximg[ij] * temp; + } + } + + return 0; +} + +/*--------------------------------------------------------------------------*/ + +int matinv(n, mat, inv) + +const int n; +const double mat[]; +double inv[]; + +{ + register int i, ij, ik, j, k, kj, pj; + int itemp, mem, *mxl, *lxm, pivot; + double colmax, *lu, *rowmax, dtemp; + + + /* Allocate memory for internal arrays. */ + mem = n * sizeof(int); + if ((mxl = (int*)malloc(mem)) == (int*)0) return 1; + if ((lxm = (int*)malloc(mem)) == (int*)0) { + free(mxl); + return 1; + } + + mem = n * sizeof(double); + if ((rowmax = (double*)malloc(mem)) == (double*)0) { + free(mxl); + free(lxm); + return 1; + } + + mem *= n; + if ((lu = (double*)malloc(mem)) == (double*)0) { + free(mxl); + free(lxm); + free(rowmax); + return 1; + } + + + /* Initialize arrays. */ + for (i = 0, ij = 0; i < n; i++) { + /* Vector which records row interchanges. */ + mxl[i] = i; + + rowmax[i] = 0.0; + + for (j = 0; j < n; j++, ij++) { + dtemp = fabs(mat[ij]); + if (dtemp > rowmax[i]) rowmax[i] = dtemp; + + lu[ij] = mat[ij]; + } + + /* A row of zeroes indicates a singular matrix. */ + if (rowmax[i] == 0.0) { + free(mxl); + free(lxm); + free(rowmax); + free(lu); + return 2; + } + } + + + /* Form the LU triangular factorization using scaled partial pivoting. */ + for (k = 0; k < n; k++) { + /* Decide whether to pivot. */ + colmax = fabs(lu[k*n+k]) / rowmax[k]; + pivot = k; + + for (i = k+1; i < n; i++) { + ik = i*n + k; + dtemp = fabs(lu[ik]) / rowmax[i]; + if (dtemp > colmax) { + colmax = dtemp; + pivot = i; + } + } + + if (pivot > k) { + /* We must pivot, interchange the rows of the design matrix. */ + for (j = 0, pj = pivot*n, kj = k*n; j < n; j++, pj++, kj++) { + dtemp = lu[pj]; + lu[pj] = lu[kj]; + lu[kj] = dtemp; + } + + /* Amend the vector of row maxima. */ + dtemp = rowmax[pivot]; + rowmax[pivot] = rowmax[k]; + rowmax[k] = dtemp; + + /* Record the interchange for later use. */ + itemp = mxl[pivot]; + mxl[pivot] = mxl[k]; + mxl[k] = itemp; + } + + /* Gaussian elimination. */ + for (i = k+1; i < n; i++) { + ik = i*n + k; + + /* Nothing to do if lu[ik] is zero. */ + if (lu[ik] != 0.0) { + /* Save the scaling factor. */ + lu[ik] /= lu[k*n+k]; + + /* Subtract rows. */ + for (j = k+1; j < n; j++) { + lu[i*n+j] -= lu[ik]*lu[k*n+j]; + } + } + } + } + + + /* mxl[i] records which row of mat corresponds to row i of lu. */ + /* lxm[i] records which row of lu corresponds to row i of mat. */ + for (i = 0; i < n; i++) { + lxm[mxl[i]] = i; + } + + + /* Determine the inverse matrix. */ + for (i = 0, ij = 0; i < n; i++) { + for (j = 0; j < n; j++, ij++) { + inv[ij] = 0.0; + } + } + + for (k = 0; k < n; k++) { + inv[lxm[k]*n+k] = 1.0; + + /* Forward substitution. */ + for (i = lxm[k]+1; i < n; i++) { + for (j = lxm[k]; j < i; j++) { + inv[i*n+k] -= lu[i*n+j]*inv[j*n+k]; + } + } + + /* Backward substitution. */ + for (i = n-1; i >= 0; i--) { + for (j = i+1; j < n; j++) { + inv[i*n+k] -= lu[i*n+j]*inv[j*n+k]; + } + inv[i*n+k] /= lu[i*n+i]; + } + } + + free(mxl); + free(lxm); + free(rowmax); + free(lu); + + return 0; +} +/* Dec 20 1999 Doug Mink - Include wcslib.h, which includes lin.h + * + * Feb 15 2001 Doug Mink - Add comments for WCSLIB 2.6; no code changes + * Sep 19 2001 Doug Mink - Add above change to WCSLIB 2.7 code + * Nov 20 2001 Doug Mink - Always include stdlib.h + * + * Jan 15 2002 Bill Joye - Add ifdef so this compiles on MacOS/X + * + * Nov 18 2003 Doug Mink - Include stdlib.h instead of malloc.h + */ diff --git a/astroem/platepos.c b/astroem/platepos.c new file mode 100644 index 00000000..84793507 --- /dev/null +++ b/astroem/platepos.c @@ -0,0 +1,391 @@ +/*** File saoimage/wcslib/platepos.c + *** February 29, 2000 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1998-2002 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + + * Module: platepos.c (Plate solution WCS conversion + * Purpose: Compute WCS from plate fit + * Subroutine: platepos() converts from pixel location to RA,Dec + * Subroutine: platepix() converts from RA,Dec to pixel location + + These functions are based on the astrmcal.c portion of GETIMAGE by + J. Doggett and the documentation distributed with the Digital Sky Survey. + +*/ + +#include +#include +#include +#include "wcs.h" + +int +platepos (xpix, ypix, wcs, xpos, ypos) + +/* Routine to determine accurate position for pixel coordinates */ +/* returns 0 if successful otherwise 1 = angle too large for projection; */ +/* based on amdpos() from getimage */ + +/* Input: */ +double xpix; /* x pixel number (RA or long without rotation) */ +double ypix; /* y pixel number (dec or lat without rotation) */ +struct WorldCoor *wcs; /* WCS parameter structure */ + +/* Output: */ +double *xpos; /* Right ascension or longitude in degrees */ +double *ypos; /* Declination or latitude in degrees */ + +{ + double x, y, x2, y2, x3, y3, r2; + double xi, xir, eta, etar, raoff, ra, dec, ra0, dec0; + double twopi = 6.28318530717959; + double ctan, ccos; + int ncoeff1 = wcs->ncoeff1; + int ncoeff2 = wcs->ncoeff2; + + /* Ignore magnitude and color terms + double mag = 0.0; + double color = 0.0; */ + + /* Convert from pixels to millimeters */ + x = xpix - wcs->crpix[0]; + y = ypix - wcs->crpix[1]; + x2 = x * x; + y2 = y * y; + x3 = x * x2; + y3 = y * y2; + r2 = x2 + y2; + + /* Compute xi,eta coordinates in degrees from x,y and plate model */ + xi = wcs->x_coeff[ 0] + wcs->x_coeff[ 1]*x + + wcs->x_coeff[ 2]*y + wcs->x_coeff[ 3]*x2 + + wcs->x_coeff[ 4]*y2 + wcs->x_coeff[ 5]*x*y; + + if (ncoeff1 > 6) + xi = xi + wcs->x_coeff[ 6]*x3 + wcs->x_coeff[ 7]*y3; + + if (ncoeff1 > 8) { + xi = xi + wcs->x_coeff[ 8]*x2*y + wcs->x_coeff[ 9]*x*y2 + + wcs->x_coeff[10]*(r2) + wcs->x_coeff[11]*x*r2 + + wcs->x_coeff[12]*y*r2; + } + + eta = wcs->y_coeff[ 0] + wcs->y_coeff[ 1]*x + + wcs->y_coeff[ 2]*y + wcs->y_coeff[ 3]*x2 + + wcs->y_coeff[ 4]*y2 + wcs->y_coeff[ 5]*x*y; + + if (ncoeff2 > 6) + eta = eta + wcs->y_coeff[ 6]*x3 + wcs->y_coeff[ 7]*y3; + + if (ncoeff2 > 8) { + eta = eta + wcs->y_coeff[ 8]*x2*y + wcs->y_coeff[ 9]*y2*x + + wcs->y_coeff[10]*r2 + wcs->y_coeff[11]*x*r2 + + wcs->y_coeff[12]*y*r2; + } + + /* Convert to radians */ + xir = degrad (xi); + etar = degrad (eta); + + /* Convert to RA and Dec */ + ra0 = degrad (wcs->crval[0]); + dec0 = degrad (wcs->crval[1]); + ctan = tan (dec0); + ccos = cos (dec0); + raoff = atan2 (xir / ccos, 1.0 - etar * ctan); + ra = raoff + ra0; + if (ra < 0.0) ra = ra + twopi; + *xpos = raddeg (ra); + + dec = atan (cos (raoff) / ((1.0 - (etar * ctan)) / (etar + ctan))); + *ypos = raddeg (dec); + return 0; +} + + +int +platepix (xpos, ypos, wcs, xpix, ypix) + +/* Routine to determine pixel coordinates for sky position */ +/* returns 0 if successful otherwise 1 = angle too large for projection; */ +/* based on amdinv() from getimage */ + +/* Input: */ +double xpos; /* Right ascension or longitude in degrees */ +double ypos; /* Declination or latitude in degrees */ +struct WorldCoor *wcs; /* WCS parameter structure */ + +/* Output: */ +double *xpix; /* x pixel number (RA or long without rotation) */ +double *ypix; /* y pixel number (dec or lat without rotation) */ + +{ + double xi,eta,x,y,xy,x2,y2,x2y,y2x,x3,y3,r2,dx,dy; + double tdec,ctan,ccos,traoff, craoff, etar, xir; + double f,fx,fy,g,gx,gy; + double ra0, dec0, ra, dec; + double tolerance = 0.0000005; + int max_iterations = 50; + int i; + int ncoeff1 = wcs->ncoeff1; + int ncoeff2 = wcs->ncoeff2; + + /* Convert RA and Dec in radians to standard coordinates on a plate */ + ra = degrad (xpos); + dec = degrad (ypos); + tdec = tan (dec); + ra0 = degrad (wcs->crval[0]); + dec0 = degrad (wcs->crval[1]); + ctan = tan (dec0); + ccos = cos (dec0); + traoff = tan (ra - ra0); + craoff = cos (ra - ra0); + etar = (1.0 - ctan * craoff / tdec) / (ctan + (craoff / tdec)); + xir = traoff * ccos * (1.0 - (etar * ctan)); + xi = raddeg (xir); + eta = raddeg (etar); + + /* Set initial value for x,y */ + x = xi * wcs->dc[0] + eta * wcs->dc[1]; + y = xi * wcs->dc[2] + eta * wcs->dc[3]; + + /* if (wcs->x_coeff[1] == 0.0) + x = xi - wcs->x_coeff[0]; + else + x = (xi - wcs->x_coeff[0]) / wcs->x_coeff[1]; + if (wcs->y_coeff[2] == 0.0) + y = eta - wcs->y_coeff[0]; + else + y = (eta - wcs->y_coeff[0]) / wcs->y_coeff[2]; */ + + /* Iterate by Newton's method */ + for (i = 0; i < max_iterations; i++) { + + /* X plate model */ + xy = x * y; + x2 = x * x; + y2 = y * y; + x3 = x2 * x; + y3 = y2 * y; + x2y = x2 * y; + y2x = y2 * x; + r2 = x2 + y2; + + f = wcs->x_coeff[0] + wcs->x_coeff[1]*x + + wcs->x_coeff[2]*y + wcs->x_coeff[3]*x2 + + wcs->x_coeff[4]*y2 + wcs->x_coeff[5]*xy; + + /* Derivative of X model wrt x */ + fx = wcs->x_coeff[1] + wcs->x_coeff[3]*2.0*x + + wcs->x_coeff[5]*y; + + /* Derivative of X model wrt y */ + fy = wcs->x_coeff[2] + wcs->x_coeff[4]*2.0*y + + wcs->x_coeff[5]*x; + + if (ncoeff1 > 6) { + f = f + wcs->x_coeff[6]*x3 + wcs->x_coeff[7]*y3; + fx = fx + wcs->x_coeff[6]*3.0*x2; + fy = fy + wcs->x_coeff[7]*3.0*y2; + } + + if (ncoeff1 > 8) { + f = f + + wcs->x_coeff[8]*x2y + wcs->x_coeff[9]*y2x + + wcs->x_coeff[10]*r2 + wcs->x_coeff[11]*x*r2 + + wcs->x_coeff[12]*y*r2; + + fx = fx + wcs->x_coeff[8]*2.0*xy + + wcs->x_coeff[9]*y2 + + wcs->x_coeff[10]*2.0*x + + wcs->x_coeff[11]*(3.0*x2+y2) + + wcs->x_coeff[12]*2.0*xy; + + fy = fy + wcs->x_coeff[8]*x2 + + wcs->x_coeff[9]*2.0*xy + + wcs->x_coeff[10]*2.0*y + + wcs->x_coeff[11]*2.0*xy + + wcs->x_coeff[12]*(3.0*y2+x2); + } + + /* Y plate model */ + g = wcs->y_coeff[0] + wcs->y_coeff[1]*x + + wcs->y_coeff[2]*y + wcs->y_coeff[3]*x2 + + wcs->y_coeff[4]*y2 + wcs->y_coeff[5]*xy; + + /* Derivative of Y model wrt x */ + gx = wcs->y_coeff[1] + wcs->y_coeff[3]*2.0*x + + wcs->y_coeff[5]*y; + + /* Derivative of Y model wrt y */ + gy = wcs->y_coeff[2] + wcs->y_coeff[4]*2.0*y + + wcs->y_coeff[5]*x; + + if (ncoeff2 > 6) { + g = g + wcs->y_coeff[6]*x3 + wcs->y_coeff[7]*y3; + gx = gx + wcs->y_coeff[6]*3.0*x2; + gy = gy + wcs->y_coeff[7]*3.0*y2; + } + + if (ncoeff2 > 8) { + g = g + + wcs->y_coeff[8]*x2y + wcs->y_coeff[9]*y2x + + wcs->y_coeff[10]*r2 + wcs->y_coeff[11]*x*r2 + + wcs->y_coeff[12]*y*r2; + + gx = gx + wcs->y_coeff[8]*2.0*xy + + wcs->y_coeff[9]*y2 + + wcs->y_coeff[10]*2.0*x + + wcs->y_coeff[11]*(3.0*x2+y2) + + wcs->y_coeff[12]*2.0*xy; + + gy = gy + wcs->y_coeff[8]*x2 + + wcs->y_coeff[9]*2.0*xy + + wcs->y_coeff[10]*2.0*y + + wcs->y_coeff[11]*2.0*xy + + wcs->y_coeff[12]*(3.0*y2+x2); + } + + f = f - xi; + g = g - eta; + dx = ((-f * gy) + (g * fy)) / ((fx * gy) - (fy * gx)); + dy = ((-g * fx) + (f * gx)) / ((fx * gy) - (fy * gx)); + x = x + dx; + y = y + dy; + if ((fabs(dx) < tolerance) && (fabs(dy) < tolerance)) break; + } + + /* Convert from plate pixels to image pixels */ + *xpix = x + wcs->crpix[0]; + *ypix = y + wcs->crpix[1]; + + /* If position is off of the image, return offscale code */ + if (*xpix < 0.5 || *xpix > wcs->nxpix+0.5) + return -1; + if (*ypix < 0.5 || *ypix > wcs->nypix+0.5) + return -1; + + return 0; +} + + +/* Set plate fit coefficients in structure from arguments */ +int +SetPlate (wcs, ncoeff1, ncoeff2, coeff) + +struct WorldCoor *wcs; /* World coordinate system structure */ +int ncoeff1; /* Number of coefficients for x */ +int ncoeff2; /* Number of coefficients for y */ +double *coeff; /* Plate fit coefficients */ + +{ + int i; + + if (nowcs (wcs) || (ncoeff1 < 1 && ncoeff2 < 1)) + return 1; + + wcs->ncoeff1 = ncoeff1; + wcs->ncoeff2 = ncoeff2; + wcs->prjcode = WCS_PLT; + + for (i = 0; i < 20; i++) { + if (i < ncoeff1) + wcs->x_coeff[i] = coeff[i]; + else + wcs->x_coeff[i] = 0.0; + } + + for (i = 0; i < 20; i++) { + if (i < ncoeff2) + wcs->y_coeff[i] = coeff[ncoeff1+i]; + else + wcs->y_coeff[i] = 0.0; + } + return 0; +} + + +/* Return plate fit coefficients from structure in arguments */ +int +GetPlate (wcs, ncoeff1, ncoeff2, coeff) + +struct WorldCoor *wcs; /* World coordinate system structure */ +int *ncoeff1; /* Number of coefficients for x */ +int *ncoeff2; /* Number of coefficients for y) */ +double *coeff; /* Plate fit coefficients */ + +{ + int i; + + if (nowcs (wcs)) + return 1; + + *ncoeff1 = wcs->ncoeff1; + *ncoeff2 = wcs->ncoeff2; + + for (i = 0; i < *ncoeff1; i++) + coeff[i] = wcs->x_coeff[i]; + + for (i = 0; i < *ncoeff2; i++) + coeff[*ncoeff1+i] = wcs->y_coeff[i]; + + return 0; +} + + +/* Set FITS header plate fit coefficients from structure */ +void +SetFITSPlate (header, wcs) + +char *header; /* Image FITS header */ +struct WorldCoor *wcs; /* WCS structure */ + +{ + char keyword[16]; + int i; + + for (i = 0; i < wcs->ncoeff1; i++) { + sprintf (keyword,"CO1_%d",i+1); + hputnr8 (header, keyword, -15, wcs->x_coeff[i]); + } + for (i = 0; i < wcs->ncoeff2; i++) { + sprintf (keyword,"CO2_%d",i+1); + hputnr8 (header, keyword, -15, wcs->y_coeff[i]); + } + return; +} + +/* Mar 27 1998 New subroutines for direct image pixel <-> sky polynomials + * Apr 10 1998 Make terms identical for both x and y polynomials + * Apr 10 1998 Allow different numbers of coefficients for x and y + * Apr 16 1998 Drom NCOEFF header parameter + * Apr 28 1998 Change projection flags to WCS_* + * Sep 10 1998 Check for xc1 and yc2 divide by zero after Allen Harris, SAO + * + * Oct 21 1999 Drop unused variables after lint + * + * Feb 29 2000 Use inverse CD matrix to get initial X,Y in platepix() + * as suggested by Paolo Montegriffo from Bologna Ast. Obs. + */ diff --git a/astroem/poly.c b/astroem/poly.c new file mode 100644 index 00000000..7e88d95d --- /dev/null +++ b/astroem/poly.c @@ -0,0 +1,914 @@ + /* + poly.c + +*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +* +* Part of: A program using Polynomials +* +* Author: E.BERTIN (IAP) +* +* Contents: Polynomial fitting +* +* Last modify: 08/03/2005 +* +*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +*/ + +#if HAVE_CONFIG_H +#include "conf.h" +#endif + +#include +#include +#include +#include + +#include "wcslib.h" + + +#define QCALLOC(ptr, typ, nel) \ + {if (!(ptr = (typ *)calloc((size_t)(nel),sizeof(typ)))) \ + qerror("Not enough memory for ", \ + #ptr " (" #nel " elements) !");;} + +#define QMALLOC(ptr, typ, nel) \ + {if (!(ptr = (typ *)malloc((size_t)(nel)*sizeof(typ)))) \ + qerror("Not enough memory for ", \ + #ptr " (" #nel " elements) !");;} + +/********************************* qerror ************************************/ +/* +I hope it will never be used! +*/ +void qerror(char *msg1, char *msg2) + { + fprintf(stderr, "\n> %s%s\n\n",msg1,msg2); + exit(-1); + } + + +/****** poly_init ************************************************************ +PROTO polystruct *poly_init(int *group, int ndim, int *degree, int ngroup) +PURPOSE Allocate and initialize a polynom structure. +INPUT 1D array containing the group for each parameter, + number of dimensions (parameters), + 1D array with the polynomial degree for each group, + number of groups. +OUTPUT polystruct pointer. +NOTES -. +AUTHOR E. Bertin (IAP) +VERSION 08/03/2003 + ***/ +polystruct *poly_init(int *group, int ndim, int *degree, int ngroup) + { + void qerror(char *msg1, char *msg2); + polystruct *poly; + char str[512]; + int nd[POLY_MAXDIM]; + int *groupt, + d,g,n,num,den; + + QCALLOC(poly, polystruct, 1); + if ((poly->ndim=ndim) > POLY_MAXDIM) + { + sprintf(str, "The dimensionality of the polynom (%d) exceeds the maximum\n" + "allowed one (%d)", ndim, POLY_MAXDIM); + qerror("*Error*: ", str); + } + + if (ndim) + QMALLOC(poly->group, int, poly->ndim); + for (groupt=poly->group, d=ndim; d--;) + *(groupt++) = *(group++)-1; + + poly->ngroup = ngroup; + if (ngroup) + { + group = poly->group; /* Forget the original *group */ + + QMALLOC(poly->degree, int, poly->ngroup); + +/*-- Compute the number of context parameters for each group */ + memset(nd, 0, ngroup*sizeof(int)); + for (d=0; d=ngroup) + qerror("*Error*: polynomial GROUP out of range", ""); + nd[g]++; + } + } + +/* Compute the total number of coefficients */ + poly->ncoeff = 1; + for (g=0; gdegree[g]=*(degree++))>POLY_MAXDEGREE) + { + sprintf(str, "The degree of the polynom (%d) exceeds the maximum\n" + "allowed one (%d)", poly->degree[g], POLY_MAXDEGREE); + qerror("*Error*: ", str); + } + +/*-- There are (n+d)!/(n!d!) coeffs per group, that is Prod_(i<=d) (n+i)/i */ + for (num=den=1, n=nd[g]; d; num*=(n+d), den*=d--); + poly->ncoeff *= num/den; + } + + QMALLOC(poly->basis, double, poly->ncoeff); + QCALLOC(poly->coeff, double, poly->ncoeff); + + return poly; + } + + +/****** poly_end ************************************************************* +PROTO void poly_end(polystruct *poly) +PURPOSE Free a polynom structure and everything it contains. +INPUT polystruct pointer. +OUTPUT -. +NOTES -. +AUTHOR E. Bertin (IAP, Leiden observatory & ESO) +VERSION 09/04/2000 + ***/ +void poly_end(polystruct *poly) + { + if (poly) + { + free(poly->coeff); + free(poly->basis); + free(poly->degree); + free(poly->group); + free(poly); + } + } + + +/****** poly_func ************************************************************ +PROTO double poly_func(polystruct *poly, double *pos) +PURPOSE Evaluate a multidimensional polynom. +INPUT polystruct pointer, + pointer to the 1D array of input vector data. +OUTPUT Polynom value. +NOTES Values of the basis functions are updated in poly->basis. +AUTHOR E. Bertin (IAP) +VERSION 03/03/2004 + ***/ +double poly_func(polystruct *poly, double *pos) + { + double xpol[POLY_MAXDIM+1]; + double *post, *xpolt, *basis, *coeff, xval; + long double val; + int expo[POLY_MAXDIM+1], gexpo[POLY_MAXDIM+1]; + int *expot, *degree,*degreet, *group,*groupt, *gexpot, + d,g,t, ndim; + +/* Prepare the vectors and counters */ + ndim = poly->ndim; + basis = poly->basis; + coeff = poly->coeff; + group = poly->group; + degree = poly->degree; + if (ndim) + { + for (xpolt=xpol, expot=expo, post=pos, d=ndim; --d;) + { + *(++xpolt) = 1.0; + *(++expot) = 0; + } + for (gexpot=gexpo, degreet=degree, g=poly->ngroup; g--;) + *(gexpot++) = *(degreet++); + if (gexpo[*group]) + gexpo[*group]--; + } + +/* The constant term is handled separately */ + val = *(coeff++); + *(basis++) = 1.0; + *expo = 1; + *xpol = *pos; + +/* Compute the rest of the polynom */ + for (t=poly->ncoeff; --t; ) + { +/*-- xpol[0] contains the current product of the x^n's */ + val += (*(basis++)=*xpol)**(coeff++); +/*-- A complex recursion between terms of the polynom speeds up computations */ +/*-- Not too good for roundoff errors (prefer Horner's), but much easier for */ +/*-- multivariate polynomials: this is why we use a long double accumulator */ + post = pos; + groupt = group; + expot = expo; + xpolt = xpol; + for (d=0; dncoeff; + ndim = poly->ndim; + matsize = ncoeff*ncoeff; + basis = poly->basis; + extbasist = extbasis; + QCALLOC(alpha, double, matsize); + QCALLOC(beta, double, ncoeff); + +/* Subtract an average offset to maintain precision (droped for now ) */ +/* + if (x) + { + for (d=0; dcoeff; + for (j=ncoeff; j--;) + *(coeff++) = *(betat++); +/* + poly_addcste(poly, offset); +*/ + free(beta); + + return; + } + + +/****** poly_addcste ********************************************************* +PROTO void poly_addcste(polystruct *poly, double *cste) +PURPOSE Modify matrix coefficients to mimick the effect of adding a cst to + the input of a polynomial. +INPUT Pointer to the polynomial structure, + Pointer to the vector of cst. +OUTPUT -. +NOTES Requires quadruple-precision. **For the time beeing, this function + returns completely wrong results!!** +AUTHOR E. Bertin (IAP) +VERSION 03/03/2004 + ***/ +void poly_addcste(polystruct *poly, double *cste) + { + long double *acoeff; + double *coeff,*mcoeff,*mcoefft, + val; + int *mpowers,*powers,*powerst,*powerst2, + i,j,n,p, denum, flag, maxdegree, ncoeff, ndim; + + ncoeff = poly->ncoeff; + ndim = poly->ndim; + maxdegree = 0; + for (j=0; jngroup; j++) + if (maxdegree < poly->degree[j]) + maxdegree = poly->degree[j]; + maxdegree++; /* Actually we need maxdegree+1 terms */ + QCALLOC(acoeff, long double, ncoeff); + QCALLOC(mcoeff, double, ndim*maxdegree); + QCALLOC(mpowers, int, ndim); + mcoefft = mcoeff; /* To avoid gcc -Wall warnings */ + powerst = powers = poly_powers(poly); + coeff = poly->coeff; + for (i=0; i

>>0;r=u;d=k?u:d;p=k?g:p}r=d;i=c[2158]|0;if(r>>>0>>0){an();return 0}e=r+b|0;m=e;if(r>>>0>=e>>>0){an();return 0}e=c[d+24>>2]|0;f=c[d+12>>2]|0;do{if((f|0)==(d|0)){q=d+20|0;g=c[q>>2]|0;if((g|0)==0){k=d+16|0;l=c[k>>2]|0;if((l|0)==0){v=0;break}else{w=l;x=k}}else{w=g;x=q}while(1){q=w+20|0;g=c[q>>2]|0;if((g|0)!=0){w=g;x=q;continue}q=w+16|0;g=c[q>>2]|0;if((g|0)==0){break}else{w=g;x=q}}if(x>>>0>>0){an();return 0}else{c[x>>2]=0;v=w;break}}else{q=c[d+8>>2]|0;if(q>>>0>>0){an();return 0}g=q+12|0;if((c[g>>2]|0)!=(d|0)){an();return 0}k=f+8|0;if((c[k>>2]|0)==(d|0)){c[g>>2]=f;c[k>>2]=q;v=f;break}else{an();return 0}}}while(0);L1467:do{if((e|0)!=0){f=d+28|0;i=8920+(c[f>>2]<<2)|0;do{if((d|0)==(c[i>>2]|0)){c[i>>2]=v;if((v|0)!=0){break}c[2155]=c[2155]&~(1<>2]);break L1467}else{if(e>>>0<(c[2158]|0)>>>0){an();return 0}q=e+16|0;if((c[q>>2]|0)==(d|0)){c[q>>2]=v}else{c[e+20>>2]=v}if((v|0)==0){break L1467}}}while(0);if(v>>>0<(c[2158]|0)>>>0){an();return 0}c[v+24>>2]=e;f=c[d+16>>2]|0;do{if((f|0)!=0){if(f>>>0<(c[2158]|0)>>>0){an();return 0}else{c[v+16>>2]=f;c[f+24>>2]=v;break}}}while(0);f=c[d+20>>2]|0;if((f|0)==0){break}if(f>>>0<(c[2158]|0)>>>0){an();return 0}else{c[v+20>>2]=f;c[f+24>>2]=v;break}}}while(0);if(p>>>0<16){e=p+b|0;c[d+4>>2]=e|3;f=r+(e+4)|0;c[f>>2]=c[f>>2]|1}else{c[d+4>>2]=b|3;c[r+(b|4)>>2]=p|1;c[r+(p+b)>>2]=p;f=c[2156]|0;if((f|0)!=0){e=c[2159]|0;i=f>>>3;f=i<<1;q=8656+(f<<2)|0;k=c[2154]|0;g=1<>2]|0;if(l>>>0>=(c[2158]|0)>>>0){y=l;z=i;break}an();return 0}}while(0);c[z>>2]=e;c[y+12>>2]=e;c[e+8>>2]=y;c[e+12>>2]=q}c[2156]=p;c[2159]=m}f=d+8|0;if((f|0)==0){o=b;break}else{n=f}return n|0}else{if(a>>>0>4294967231){o=-1;break}f=a+11|0;g=f&-8;k=c[2155]|0;if((k|0)==0){o=g;break}r=-g|0;i=f>>>8;do{if((i|0)==0){A=0}else{if(g>>>0>16777215){A=31;break}f=(i+1048320|0)>>>16&8;l=i<>>16&4;j=l<>>16&2;B=14-(h|f|l)+(j<>>15)|0;A=g>>>((B+7|0)>>>0)&1|B<<1}}while(0);i=c[8920+(A<<2)>>2]|0;L1515:do{if((i|0)==0){C=0;D=r;E=0}else{if((A|0)==31){F=0}else{F=25-(A>>>1)|0}d=0;m=r;p=i;q=g<>2]&-8;l=B-g|0;if(l>>>0>>0){if((B|0)==(g|0)){C=p;D=l;E=p;break L1515}else{G=p;H=l}}else{G=d;H=m}l=c[p+20>>2]|0;B=c[p+16+(q>>>31<<2)>>2]|0;j=(l|0)==0|(l|0)==(B|0)?e:l;if((B|0)==0){C=G;D=H;E=j;break}else{d=G;m=H;p=B;q=q<<1;e=j}}}}while(0);if((E|0)==0&(C|0)==0){i=2<>>12&16;e=i>>>(r>>>0);i=e>>>5&8;q=e>>>(i>>>0);e=q>>>2&4;p=q>>>(e>>>0);q=p>>>1&2;m=p>>>(q>>>0);p=m>>>1&1;I=c[8920+((i|r|e|q|p)+(m>>>(p>>>0))<<2)>>2]|0}else{I=E}if((I|0)==0){J=D;K=C}else{p=I;m=D;q=C;while(1){e=(c[p+4>>2]&-8)-g|0;r=e>>>0>>0;i=r?e:m;e=r?p:q;r=c[p+16>>2]|0;if((r|0)!=0){p=r;m=i;q=e;continue}r=c[p+20>>2]|0;if((r|0)==0){J=i;K=e;break}else{p=r;m=i;q=e}}}if((K|0)==0){o=g;break}if(J>>>0>=((c[2156]|0)-g|0)>>>0){o=g;break}q=K;m=c[2158]|0;if(q>>>0>>0){an();return 0}p=q+g|0;k=p;if(q>>>0>=p>>>0){an();return 0}e=c[K+24>>2]|0;i=c[K+12>>2]|0;do{if((i|0)==(K|0)){r=K+20|0;d=c[r>>2]|0;if((d|0)==0){j=K+16|0;B=c[j>>2]|0;if((B|0)==0){L=0;break}else{M=B;N=j}}else{M=d;N=r}while(1){r=M+20|0;d=c[r>>2]|0;if((d|0)!=0){M=d;N=r;continue}r=M+16|0;d=c[r>>2]|0;if((d|0)==0){break}else{M=d;N=r}}if(N>>>0>>0){an();return 0}else{c[N>>2]=0;L=M;break}}else{r=c[K+8>>2]|0;if(r>>>0>>0){an();return 0}d=r+12|0;if((c[d>>2]|0)!=(K|0)){an();return 0}j=i+8|0;if((c[j>>2]|0)==(K|0)){c[d>>2]=i;c[j>>2]=r;L=i;break}else{an();return 0}}}while(0);L1565:do{if((e|0)!=0){i=K+28|0;m=8920+(c[i>>2]<<2)|0;do{if((K|0)==(c[m>>2]|0)){c[m>>2]=L;if((L|0)!=0){break}c[2155]=c[2155]&~(1<>2]);break L1565}else{if(e>>>0<(c[2158]|0)>>>0){an();return 0}r=e+16|0;if((c[r>>2]|0)==(K|0)){c[r>>2]=L}else{c[e+20>>2]=L}if((L|0)==0){break L1565}}}while(0);if(L>>>0<(c[2158]|0)>>>0){an();return 0}c[L+24>>2]=e;i=c[K+16>>2]|0;do{if((i|0)!=0){if(i>>>0<(c[2158]|0)>>>0){an();return 0}else{c[L+16>>2]=i;c[i+24>>2]=L;break}}}while(0);i=c[K+20>>2]|0;if((i|0)==0){break}if(i>>>0<(c[2158]|0)>>>0){an();return 0}else{c[L+20>>2]=i;c[i+24>>2]=L;break}}}while(0);do{if(J>>>0<16){e=J+g|0;c[K+4>>2]=e|3;i=q+(e+4)|0;c[i>>2]=c[i>>2]|1}else{c[K+4>>2]=g|3;c[q+(g|4)>>2]=J|1;c[q+(J+g)>>2]=J;i=J>>>3;if(J>>>0<256){e=i<<1;m=8656+(e<<2)|0;r=c[2154]|0;j=1<>2]|0;if(d>>>0>=(c[2158]|0)>>>0){O=d;P=i;break}an();return 0}}while(0);c[P>>2]=k;c[O+12>>2]=k;c[q+(g+8)>>2]=O;c[q+(g+12)>>2]=m;break}e=p;j=J>>>8;do{if((j|0)==0){Q=0}else{if(J>>>0>16777215){Q=31;break}r=(j+1048320|0)>>>16&8;i=j<>>16&4;B=i<>>16&2;l=14-(d|r|i)+(B<>>15)|0;Q=J>>>((l+7|0)>>>0)&1|l<<1}}while(0);j=8920+(Q<<2)|0;c[q+(g+28)>>2]=Q;c[q+(g+20)>>2]=0;c[q+(g+16)>>2]=0;m=c[2155]|0;l=1<>2]=e;c[q+(g+24)>>2]=j;c[q+(g+12)>>2]=e;c[q+(g+8)>>2]=e;break}if((Q|0)==31){R=0}else{R=25-(Q>>>1)|0}l=J<>2]|0;while(1){if((c[m+4>>2]&-8|0)==(J|0)){break}S=m+16+(l>>>31<<2)|0;j=c[S>>2]|0;if((j|0)==0){T=1240;break}else{l=l<<1;m=j}}if((T|0)==1240){if(S>>>0<(c[2158]|0)>>>0){an();return 0}else{c[S>>2]=e;c[q+(g+24)>>2]=m;c[q+(g+12)>>2]=e;c[q+(g+8)>>2]=e;break}}l=m+8|0;j=c[l>>2]|0;i=c[2158]|0;if(m>>>0>>0){an();return 0}if(j>>>0>>0){an();return 0}else{c[j+12>>2]=e;c[l>>2]=e;c[q+(g+8)>>2]=j;c[q+(g+12)>>2]=m;c[q+(g+24)>>2]=0;break}}}while(0);q=K+8|0;if((q|0)==0){o=g;break}else{n=q}return n|0}}while(0);K=c[2156]|0;if(o>>>0<=K>>>0){S=K-o|0;J=c[2159]|0;if(S>>>0>15){R=J;c[2159]=R+o;c[2156]=S;c[R+(o+4)>>2]=S|1;c[R+K>>2]=S;c[J+4>>2]=o|3}else{c[2156]=0;c[2159]=0;c[J+4>>2]=K|3;S=J+(K+4)|0;c[S>>2]=c[S>>2]|1}n=J+8|0;return n|0}J=c[2157]|0;if(o>>>0>>0){S=J-o|0;c[2157]=S;J=c[2160]|0;K=J;c[2160]=K+o;c[K+(o+4)>>2]=S|1;c[J+4>>2]=o|3;n=J+8|0;return n|0}do{if((c[1612]|0)==0){J=a$(8)|0;if((J-1&J|0)==0){c[1614]=J;c[1613]=J;c[1615]=-1;c[1616]=-1;c[1617]=0;c[2265]=0;c[1612]=(aO(0)|0)&-16^1431655768;break}else{an();return 0}}}while(0);J=o+48|0;S=c[1614]|0;K=o+47|0;R=S+K|0;Q=-S|0;S=R&Q;if(S>>>0<=o>>>0){n=0;return n|0}O=c[2264]|0;do{if((O|0)!=0){P=c[2262]|0;L=P+S|0;if(L>>>0<=P>>>0|L>>>0>O>>>0){n=0}else{break}return n|0}}while(0);L1657:do{if((c[2265]&4|0)==0){O=c[2160]|0;L1659:do{if((O|0)==0){T=1270}else{L=O;P=9064;while(1){U=P|0;M=c[U>>2]|0;if(M>>>0<=L>>>0){V=P+4|0;if((M+(c[V>>2]|0)|0)>>>0>L>>>0){break}}M=c[P+8>>2]|0;if((M|0)==0){T=1270;break L1659}else{P=M}}if((P|0)==0){T=1270;break}L=R-(c[2157]|0)&Q;if(L>>>0>=2147483647){W=0;break}m=aV(L|0)|0;e=(m|0)==((c[U>>2]|0)+(c[V>>2]|0)|0);X=e?m:-1;Y=e?L:0;Z=m;_=L;T=1279}}while(0);do{if((T|0)==1270){O=aV(0)|0;if((O|0)==-1){W=0;break}g=O;L=c[1613]|0;m=L-1|0;if((m&g|0)==0){$=S}else{$=S-g+(m+g&-L)|0}L=c[2262]|0;g=L+$|0;if(!($>>>0>o>>>0&$>>>0<2147483647)){W=0;break}m=c[2264]|0;if((m|0)!=0){if(g>>>0<=L>>>0|g>>>0>m>>>0){W=0;break}}m=aV($|0)|0;g=(m|0)==(O|0);X=g?O:-1;Y=g?$:0;Z=m;_=$;T=1279}}while(0);L1679:do{if((T|0)==1279){m=-_|0;if((X|0)!=-1){aa=Y;ab=X;T=1290;break L1657}do{if((Z|0)!=-1&_>>>0<2147483647&_>>>0>>0){g=c[1614]|0;O=K-_+g&-g;if(O>>>0>=2147483647){ac=_;break}if((aV(O|0)|0)==-1){aV(m|0)|0;W=Y;break L1679}else{ac=O+_|0;break}}else{ac=_}}while(0);if((Z|0)==-1){W=Y}else{aa=ac;ab=Z;T=1290;break L1657}}}while(0);c[2265]=c[2265]|4;ad=W;T=1287}else{ad=0;T=1287}}while(0);do{if((T|0)==1287){if(S>>>0>=2147483647){break}W=aV(S|0)|0;Z=aV(0)|0;if(!((Z|0)!=-1&(W|0)!=-1&W>>>0>>0)){break}ac=Z-W|0;Z=ac>>>0>(o+40|0)>>>0;Y=Z?W:-1;if((Y|0)!=-1){aa=Z?ac:ad;ab=Y;T=1290}}}while(0);do{if((T|0)==1290){ad=(c[2262]|0)+aa|0;c[2262]=ad;if(ad>>>0>(c[2263]|0)>>>0){c[2263]=ad}ad=c[2160]|0;L1699:do{if((ad|0)==0){S=c[2158]|0;if((S|0)==0|ab>>>0>>0){c[2158]=ab}c[2266]=ab;c[2267]=aa;c[2269]=0;c[2163]=c[1612];c[2162]=-1;S=0;do{Y=S<<1;ac=8656+(Y<<2)|0;c[8656+(Y+3<<2)>>2]=ac;c[8656+(Y+2<<2)>>2]=ac;S=S+1|0;}while(S>>>0<32);S=ab+8|0;if((S&7|0)==0){ae=0}else{ae=-S&7}S=aa-40-ae|0;c[2160]=ab+ae;c[2157]=S;c[ab+(ae+4)>>2]=S|1;c[ab+(aa-36)>>2]=40;c[2161]=c[1616]}else{S=9064;while(1){af=c[S>>2]|0;ag=S+4|0;ah=c[ag>>2]|0;if((ab|0)==(af+ah|0)){T=1302;break}ac=c[S+8>>2]|0;if((ac|0)==0){break}else{S=ac}}do{if((T|0)==1302){if((c[S+12>>2]&8|0)!=0){break}ac=ad;if(!(ac>>>0>=af>>>0&ac>>>0>>0)){break}c[ag>>2]=ah+aa;ac=c[2160]|0;Y=(c[2157]|0)+aa|0;Z=ac;W=ac+8|0;if((W&7|0)==0){ai=0}else{ai=-W&7}W=Y-ai|0;c[2160]=Z+ai;c[2157]=W;c[Z+(ai+4)>>2]=W|1;c[Z+(Y+4)>>2]=40;c[2161]=c[1616];break L1699}}while(0);if(ab>>>0<(c[2158]|0)>>>0){c[2158]=ab}S=ab+aa|0;Y=9064;while(1){aj=Y|0;if((c[aj>>2]|0)==(S|0)){T=1312;break}Z=c[Y+8>>2]|0;if((Z|0)==0){break}else{Y=Z}}do{if((T|0)==1312){if((c[Y+12>>2]&8|0)!=0){break}c[aj>>2]=ab;S=Y+4|0;c[S>>2]=(c[S>>2]|0)+aa;S=ab+8|0;if((S&7|0)==0){ak=0}else{ak=-S&7}S=ab+(aa+8)|0;if((S&7|0)==0){al=0}else{al=-S&7}S=ab+(al+aa)|0;Z=S;W=ak+o|0;ac=ab+W|0;_=ac;K=S-(ab+ak)-o|0;c[ab+(ak+4)>>2]=o|3;do{if((Z|0)==(c[2160]|0)){J=(c[2157]|0)+K|0;c[2157]=J;c[2160]=_;c[ab+(W+4)>>2]=J|1}else{if((Z|0)==(c[2159]|0)){J=(c[2156]|0)+K|0;c[2156]=J;c[2159]=_;c[ab+(W+4)>>2]=J|1;c[ab+(J+W)>>2]=J;break}J=aa+4|0;X=c[ab+(J+al)>>2]|0;if((X&3|0)==1){$=X&-8;V=X>>>3;L1744:do{if(X>>>0<256){U=c[ab+((al|8)+aa)>>2]|0;Q=c[ab+(aa+12+al)>>2]|0;R=8656+(V<<1<<2)|0;do{if((U|0)!=(R|0)){if(U>>>0<(c[2158]|0)>>>0){an();return 0}if((c[U+12>>2]|0)==(Z|0)){break}an();return 0}}while(0);if((Q|0)==(U|0)){c[2154]=c[2154]&~(1<>>0<(c[2158]|0)>>>0){an();return 0}m=Q+8|0;if((c[m>>2]|0)==(Z|0)){am=m;break}an();return 0}}while(0);c[U+12>>2]=Q;c[am>>2]=U}else{R=S;m=c[ab+((al|24)+aa)>>2]|0;P=c[ab+(aa+12+al)>>2]|0;do{if((P|0)==(R|0)){O=al|16;g=ab+(J+O)|0;L=c[g>>2]|0;if((L|0)==0){e=ab+(O+aa)|0;O=c[e>>2]|0;if((O|0)==0){ao=0;break}else{ap=O;aq=e}}else{ap=L;aq=g}while(1){g=ap+20|0;L=c[g>>2]|0;if((L|0)!=0){ap=L;aq=g;continue}g=ap+16|0;L=c[g>>2]|0;if((L|0)==0){break}else{ap=L;aq=g}}if(aq>>>0<(c[2158]|0)>>>0){an();return 0}else{c[aq>>2]=0;ao=ap;break}}else{g=c[ab+((al|8)+aa)>>2]|0;if(g>>>0<(c[2158]|0)>>>0){an();return 0}L=g+12|0;if((c[L>>2]|0)!=(R|0)){an();return 0}e=P+8|0;if((c[e>>2]|0)==(R|0)){c[L>>2]=P;c[e>>2]=g;ao=P;break}else{an();return 0}}}while(0);if((m|0)==0){break}P=ab+(aa+28+al)|0;U=8920+(c[P>>2]<<2)|0;do{if((R|0)==(c[U>>2]|0)){c[U>>2]=ao;if((ao|0)!=0){break}c[2155]=c[2155]&~(1<>2]);break L1744}else{if(m>>>0<(c[2158]|0)>>>0){an();return 0}Q=m+16|0;if((c[Q>>2]|0)==(R|0)){c[Q>>2]=ao}else{c[m+20>>2]=ao}if((ao|0)==0){break L1744}}}while(0);if(ao>>>0<(c[2158]|0)>>>0){an();return 0}c[ao+24>>2]=m;R=al|16;P=c[ab+(R+aa)>>2]|0;do{if((P|0)!=0){if(P>>>0<(c[2158]|0)>>>0){an();return 0}else{c[ao+16>>2]=P;c[P+24>>2]=ao;break}}}while(0);P=c[ab+(J+R)>>2]|0;if((P|0)==0){break}if(P>>>0<(c[2158]|0)>>>0){an();return 0}else{c[ao+20>>2]=P;c[P+24>>2]=ao;break}}}while(0);ar=ab+(($|al)+aa)|0;as=$+K|0}else{ar=Z;as=K}J=ar+4|0;c[J>>2]=c[J>>2]&-2;c[ab+(W+4)>>2]=as|1;c[ab+(as+W)>>2]=as;J=as>>>3;if(as>>>0<256){V=J<<1;X=8656+(V<<2)|0;P=c[2154]|0;m=1<>2]|0;if(U>>>0>=(c[2158]|0)>>>0){at=U;au=J;break}an();return 0}}while(0);c[au>>2]=_;c[at+12>>2]=_;c[ab+(W+8)>>2]=at;c[ab+(W+12)>>2]=X;break}V=ac;m=as>>>8;do{if((m|0)==0){av=0}else{if(as>>>0>16777215){av=31;break}P=(m+1048320|0)>>>16&8;$=m<>>16&4;U=$<>>16&2;Q=14-(J|P|$)+(U<<$>>>15)|0;av=as>>>((Q+7|0)>>>0)&1|Q<<1}}while(0);m=8920+(av<<2)|0;c[ab+(W+28)>>2]=av;c[ab+(W+20)>>2]=0;c[ab+(W+16)>>2]=0;X=c[2155]|0;Q=1<>2]=V;c[ab+(W+24)>>2]=m;c[ab+(W+12)>>2]=V;c[ab+(W+8)>>2]=V;break}if((av|0)==31){aw=0}else{aw=25-(av>>>1)|0}Q=as<>2]|0;while(1){if((c[X+4>>2]&-8|0)==(as|0)){break}ax=X+16+(Q>>>31<<2)|0;m=c[ax>>2]|0;if((m|0)==0){T=1385;break}else{Q=Q<<1;X=m}}if((T|0)==1385){if(ax>>>0<(c[2158]|0)>>>0){an();return 0}else{c[ax>>2]=V;c[ab+(W+24)>>2]=X;c[ab+(W+12)>>2]=V;c[ab+(W+8)>>2]=V;break}}Q=X+8|0;m=c[Q>>2]|0;$=c[2158]|0;if(X>>>0<$>>>0){an();return 0}if(m>>>0<$>>>0){an();return 0}else{c[m+12>>2]=V;c[Q>>2]=V;c[ab+(W+8)>>2]=m;c[ab+(W+12)>>2]=X;c[ab+(W+24)>>2]=0;break}}}while(0);n=ab+(ak|8)|0;return n|0}}while(0);Y=ad;W=9064;while(1){ay=c[W>>2]|0;if(ay>>>0<=Y>>>0){az=c[W+4>>2]|0;aA=ay+az|0;if(aA>>>0>Y>>>0){break}}W=c[W+8>>2]|0}W=ay+(az-39)|0;if((W&7|0)==0){aB=0}else{aB=-W&7}W=ay+(az-47+aB)|0;ac=W>>>0<(ad+16|0)>>>0?Y:W;W=ac+8|0;_=ab+8|0;if((_&7|0)==0){aC=0}else{aC=-_&7}_=aa-40-aC|0;c[2160]=ab+aC;c[2157]=_;c[ab+(aC+4)>>2]=_|1;c[ab+(aa-36)>>2]=40;c[2161]=c[1616];c[ac+4>>2]=27;c[W>>2]=c[2266];c[W+4>>2]=c[9068>>2];c[W+8>>2]=c[9072>>2];c[W+12>>2]=c[9076>>2];c[2266]=ab;c[2267]=aa;c[2269]=0;c[2268]=W;W=ac+28|0;c[W>>2]=7;if((ac+32|0)>>>0>>0){_=W;while(1){W=_+4|0;c[W>>2]=7;if((_+8|0)>>>0>>0){_=W}else{break}}}if((ac|0)==(Y|0)){break}_=ac-ad|0;W=Y+(_+4)|0;c[W>>2]=c[W>>2]&-2;c[ad+4>>2]=_|1;c[Y+_>>2]=_;W=_>>>3;if(_>>>0<256){K=W<<1;Z=8656+(K<<2)|0;S=c[2154]|0;m=1<>2]|0;if(Q>>>0>=(c[2158]|0)>>>0){aD=Q;aE=W;break}an();return 0}}while(0);c[aE>>2]=ad;c[aD+12>>2]=ad;c[ad+8>>2]=aD;c[ad+12>>2]=Z;break}K=ad;m=_>>>8;do{if((m|0)==0){aF=0}else{if(_>>>0>16777215){aF=31;break}S=(m+1048320|0)>>>16&8;Y=m<>>16&4;W=Y<>>16&2;Q=14-(ac|S|Y)+(W<>>15)|0;aF=_>>>((Q+7|0)>>>0)&1|Q<<1}}while(0);m=8920+(aF<<2)|0;c[ad+28>>2]=aF;c[ad+20>>2]=0;c[ad+16>>2]=0;Z=c[2155]|0;Q=1<>2]=K;c[ad+24>>2]=m;c[ad+12>>2]=ad;c[ad+8>>2]=ad;break}if((aF|0)==31){aG=0}else{aG=25-(aF>>>1)|0}Q=_<>2]|0;while(1){if((c[Z+4>>2]&-8|0)==(_|0)){break}aH=Z+16+(Q>>>31<<2)|0;m=c[aH>>2]|0;if((m|0)==0){T=1420;break}else{Q=Q<<1;Z=m}}if((T|0)==1420){if(aH>>>0<(c[2158]|0)>>>0){an();return 0}else{c[aH>>2]=K;c[ad+24>>2]=Z;c[ad+12>>2]=ad;c[ad+8>>2]=ad;break}}Q=Z+8|0;_=c[Q>>2]|0;m=c[2158]|0;if(Z>>>0>>0){an();return 0}if(_>>>0>>0){an();return 0}else{c[_+12>>2]=K;c[Q>>2]=K;c[ad+8>>2]=_;c[ad+12>>2]=Z;c[ad+24>>2]=0;break}}}while(0);ad=c[2157]|0;if(ad>>>0<=o>>>0){break}_=ad-o|0;c[2157]=_;ad=c[2160]|0;Q=ad;c[2160]=Q+o;c[Q+(o+4)>>2]=_|1;c[ad+4>>2]=o|3;n=ad+8|0;return n|0}}while(0);c[(aW()|0)>>2]=12;n=0;return n|0}function ej(a,b){a=a|0;b=b|0;var d=0,e=0;do{if((a|0)==0){d=0}else{e=_(b,a)|0;if((b|a)>>>0<=65535){d=e;break}d=((e>>>0)/(a>>>0)|0|0)==(b|0)?e:-1}}while(0);b=ei(d)|0;if((b|0)==0){return b|0}if((c[b-4>>2]&3|0)==0){return b|0}ey(b|0,0,d|0);return b|0}function ek(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;if((a|0)==0){return}b=a-8|0;d=b;e=c[2158]|0;if(b>>>0>>0){an()}f=c[a-4>>2]|0;g=f&3;if((g|0)==1){an()}h=f&-8;i=a+(h-8)|0;j=i;L1928:do{if((f&1|0)==0){k=c[b>>2]|0;if((g|0)==0){return}l=-8-k|0;m=a+l|0;n=m;o=k+h|0;if(m>>>0>>0){an()}if((n|0)==(c[2159]|0)){p=a+(h-4)|0;if((c[p>>2]&3|0)!=3){q=n;r=o;break}c[2156]=o;c[p>>2]=c[p>>2]&-2;c[a+(l+4)>>2]=o|1;c[i>>2]=o;return}p=k>>>3;if(k>>>0<256){k=c[a+(l+8)>>2]|0;s=c[a+(l+12)>>2]|0;t=8656+(p<<1<<2)|0;do{if((k|0)!=(t|0)){if(k>>>0>>0){an()}if((c[k+12>>2]|0)==(n|0)){break}an()}}while(0);if((s|0)==(k|0)){c[2154]=c[2154]&~(1<>>0>>0){an()}v=s+8|0;if((c[v>>2]|0)==(n|0)){u=v;break}an()}}while(0);c[k+12>>2]=s;c[u>>2]=k;q=n;r=o;break}t=m;p=c[a+(l+24)>>2]|0;v=c[a+(l+12)>>2]|0;do{if((v|0)==(t|0)){w=a+(l+20)|0;x=c[w>>2]|0;if((x|0)==0){y=a+(l+16)|0;z=c[y>>2]|0;if((z|0)==0){A=0;break}else{B=z;C=y}}else{B=x;C=w}while(1){w=B+20|0;x=c[w>>2]|0;if((x|0)!=0){B=x;C=w;continue}w=B+16|0;x=c[w>>2]|0;if((x|0)==0){break}else{B=x;C=w}}if(C>>>0>>0){an()}else{c[C>>2]=0;A=B;break}}else{w=c[a+(l+8)>>2]|0;if(w>>>0>>0){an()}x=w+12|0;if((c[x>>2]|0)!=(t|0)){an()}y=v+8|0;if((c[y>>2]|0)==(t|0)){c[x>>2]=v;c[y>>2]=w;A=v;break}else{an()}}}while(0);if((p|0)==0){q=n;r=o;break}v=a+(l+28)|0;m=8920+(c[v>>2]<<2)|0;do{if((t|0)==(c[m>>2]|0)){c[m>>2]=A;if((A|0)!=0){break}c[2155]=c[2155]&~(1<>2]);q=n;r=o;break L1928}else{if(p>>>0<(c[2158]|0)>>>0){an()}k=p+16|0;if((c[k>>2]|0)==(t|0)){c[k>>2]=A}else{c[p+20>>2]=A}if((A|0)==0){q=n;r=o;break L1928}}}while(0);if(A>>>0<(c[2158]|0)>>>0){an()}c[A+24>>2]=p;t=c[a+(l+16)>>2]|0;do{if((t|0)!=0){if(t>>>0<(c[2158]|0)>>>0){an()}else{c[A+16>>2]=t;c[t+24>>2]=A;break}}}while(0);t=c[a+(l+20)>>2]|0;if((t|0)==0){q=n;r=o;break}if(t>>>0<(c[2158]|0)>>>0){an()}else{c[A+20>>2]=t;c[t+24>>2]=A;q=n;r=o;break}}else{q=d;r=h}}while(0);d=q;if(d>>>0>=i>>>0){an()}A=a+(h-4)|0;e=c[A>>2]|0;if((e&1|0)==0){an()}do{if((e&2|0)==0){if((j|0)==(c[2160]|0)){B=(c[2157]|0)+r|0;c[2157]=B;c[2160]=q;c[q+4>>2]=B|1;if((q|0)!=(c[2159]|0)){return}c[2159]=0;c[2156]=0;return}if((j|0)==(c[2159]|0)){B=(c[2156]|0)+r|0;c[2156]=B;c[2159]=q;c[q+4>>2]=B|1;c[d+B>>2]=B;return}B=(e&-8)+r|0;C=e>>>3;L2031:do{if(e>>>0<256){u=c[a+h>>2]|0;g=c[a+(h|4)>>2]|0;b=8656+(C<<1<<2)|0;do{if((u|0)!=(b|0)){if(u>>>0<(c[2158]|0)>>>0){an()}if((c[u+12>>2]|0)==(j|0)){break}an()}}while(0);if((g|0)==(u|0)){c[2154]=c[2154]&~(1<>>0<(c[2158]|0)>>>0){an()}f=g+8|0;if((c[f>>2]|0)==(j|0)){D=f;break}an()}}while(0);c[u+12>>2]=g;c[D>>2]=u}else{b=i;f=c[a+(h+16)>>2]|0;t=c[a+(h|4)>>2]|0;do{if((t|0)==(b|0)){p=a+(h+12)|0;v=c[p>>2]|0;if((v|0)==0){m=a+(h+8)|0;k=c[m>>2]|0;if((k|0)==0){E=0;break}else{F=k;G=m}}else{F=v;G=p}while(1){p=F+20|0;v=c[p>>2]|0;if((v|0)!=0){F=v;G=p;continue}p=F+16|0;v=c[p>>2]|0;if((v|0)==0){break}else{F=v;G=p}}if(G>>>0<(c[2158]|0)>>>0){an()}else{c[G>>2]=0;E=F;break}}else{p=c[a+h>>2]|0;if(p>>>0<(c[2158]|0)>>>0){an()}v=p+12|0;if((c[v>>2]|0)!=(b|0)){an()}m=t+8|0;if((c[m>>2]|0)==(b|0)){c[v>>2]=t;c[m>>2]=p;E=t;break}else{an()}}}while(0);if((f|0)==0){break}t=a+(h+20)|0;u=8920+(c[t>>2]<<2)|0;do{if((b|0)==(c[u>>2]|0)){c[u>>2]=E;if((E|0)!=0){break}c[2155]=c[2155]&~(1<>2]);break L2031}else{if(f>>>0<(c[2158]|0)>>>0){an()}g=f+16|0;if((c[g>>2]|0)==(b|0)){c[g>>2]=E}else{c[f+20>>2]=E}if((E|0)==0){break L2031}}}while(0);if(E>>>0<(c[2158]|0)>>>0){an()}c[E+24>>2]=f;b=c[a+(h+8)>>2]|0;do{if((b|0)!=0){if(b>>>0<(c[2158]|0)>>>0){an()}else{c[E+16>>2]=b;c[b+24>>2]=E;break}}}while(0);b=c[a+(h+12)>>2]|0;if((b|0)==0){break}if(b>>>0<(c[2158]|0)>>>0){an()}else{c[E+20>>2]=b;c[b+24>>2]=E;break}}}while(0);c[q+4>>2]=B|1;c[d+B>>2]=B;if((q|0)!=(c[2159]|0)){H=B;break}c[2156]=B;return}else{c[A>>2]=e&-2;c[q+4>>2]=r|1;c[d+r>>2]=r;H=r}}while(0);r=H>>>3;if(H>>>0<256){d=r<<1;e=8656+(d<<2)|0;A=c[2154]|0;E=1<>2]|0;if(h>>>0>=(c[2158]|0)>>>0){I=h;J=r;break}an()}}while(0);c[J>>2]=q;c[I+12>>2]=q;c[q+8>>2]=I;c[q+12>>2]=e;return}e=q;I=H>>>8;do{if((I|0)==0){K=0}else{if(H>>>0>16777215){K=31;break}J=(I+1048320|0)>>>16&8;d=I<>>16&4;A=d<>>16&2;r=14-(E|J|d)+(A<>>15)|0;K=H>>>((r+7|0)>>>0)&1|r<<1}}while(0);I=8920+(K<<2)|0;c[q+28>>2]=K;c[q+20>>2]=0;c[q+16>>2]=0;r=c[2155]|0;d=1<>2]=e;c[q+24>>2]=I;c[q+12>>2]=q;c[q+8>>2]=q}else{if((K|0)==31){L=0}else{L=25-(K>>>1)|0}A=H<>2]|0;while(1){if((c[J+4>>2]&-8|0)==(H|0)){break}M=J+16+(A>>>31<<2)|0;E=c[M>>2]|0;if((E|0)==0){N=1607;break}else{A=A<<1;J=E}}if((N|0)==1607){if(M>>>0<(c[2158]|0)>>>0){an()}else{c[M>>2]=e;c[q+24>>2]=J;c[q+12>>2]=q;c[q+8>>2]=q;break}}A=J+8|0;B=c[A>>2]|0;E=c[2158]|0;if(J>>>0>>0){an()}if(B>>>0>>0){an()}else{c[B+12>>2]=e;c[A>>2]=e;c[q+8>>2]=B;c[q+12>>2]=J;c[q+24>>2]=0;break}}}while(0);q=(c[2162]|0)-1|0;c[2162]=q;if((q|0)==0){O=9072}else{return}while(1){q=c[O>>2]|0;if((q|0)==0){break}else{O=q+8|0}}c[2162]=-1;return}function el(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;if((a|0)==0){d=ei(b)|0;return d|0}if(b>>>0>4294967231){c[(aW()|0)>>2]=12;d=0;return d|0}if(b>>>0<11){e=16}else{e=b+11&-8}f=em(a-8|0,e)|0;if((f|0)!=0){d=f+8|0;return d|0}f=ei(b)|0;if((f|0)==0){d=0;return d|0}e=c[a-4>>2]|0;g=(e&-8)-((e&3|0)==0?8:4)|0;e=g>>>0>>0?g:b;ev(f|0,a|0,e)|0;ek(a);d=f;return d|0}function em(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;d=a+4|0;e=c[d>>2]|0;f=e&-8;g=a;h=g+f|0;i=h;j=c[2158]|0;if(g>>>0>>0){an();return 0}k=e&3;if(!((k|0)!=1&g>>>0>>0)){an();return 0}l=g+(f|4)|0;m=c[l>>2]|0;if((m&1|0)==0){an();return 0}if((k|0)==0){if(b>>>0<256){n=0;return n|0}do{if(f>>>0>=(b+4|0)>>>0){if((f-b|0)>>>0>c[1614]<<1>>>0){break}else{n=a}return n|0}}while(0);n=0;return n|0}if(f>>>0>=b>>>0){k=f-b|0;if(k>>>0<=15){n=a;return n|0}c[d>>2]=e&1|b|2;c[g+(b+4)>>2]=k|3;c[l>>2]=c[l>>2]|1;en(g+b|0,k);n=a;return n|0}if((i|0)==(c[2160]|0)){k=(c[2157]|0)+f|0;if(k>>>0<=b>>>0){n=0;return n|0}l=k-b|0;c[d>>2]=e&1|b|2;c[g+(b+4)>>2]=l|1;c[2160]=g+b;c[2157]=l;n=a;return n|0}if((i|0)==(c[2159]|0)){l=(c[2156]|0)+f|0;if(l>>>0>>0){n=0;return n|0}k=l-b|0;if(k>>>0>15){c[d>>2]=e&1|b|2;c[g+(b+4)>>2]=k|1;c[g+l>>2]=k;o=g+(l+4)|0;c[o>>2]=c[o>>2]&-2;p=g+b|0;q=k}else{c[d>>2]=e&1|l|2;e=g+(l+4)|0;c[e>>2]=c[e>>2]|1;p=0;q=0}c[2156]=q;c[2159]=p;n=a;return n|0}if((m&2|0)!=0){n=0;return n|0}p=(m&-8)+f|0;if(p>>>0>>0){n=0;return n|0}q=p-b|0;e=m>>>3;L2217:do{if(m>>>0<256){l=c[g+(f+8)>>2]|0;k=c[g+(f+12)>>2]|0;o=8656+(e<<1<<2)|0;do{if((l|0)!=(o|0)){if(l>>>0>>0){an();return 0}if((c[l+12>>2]|0)==(i|0)){break}an();return 0}}while(0);if((k|0)==(l|0)){c[2154]=c[2154]&~(1<>>0>>0){an();return 0}s=k+8|0;if((c[s>>2]|0)==(i|0)){r=s;break}an();return 0}}while(0);c[l+12>>2]=k;c[r>>2]=l}else{o=h;s=c[g+(f+24)>>2]|0;t=c[g+(f+12)>>2]|0;do{if((t|0)==(o|0)){u=g+(f+20)|0;v=c[u>>2]|0;if((v|0)==0){w=g+(f+16)|0;x=c[w>>2]|0;if((x|0)==0){y=0;break}else{z=x;A=w}}else{z=v;A=u}while(1){u=z+20|0;v=c[u>>2]|0;if((v|0)!=0){z=v;A=u;continue}u=z+16|0;v=c[u>>2]|0;if((v|0)==0){break}else{z=v;A=u}}if(A>>>0>>0){an();return 0}else{c[A>>2]=0;y=z;break}}else{u=c[g+(f+8)>>2]|0;if(u>>>0>>0){an();return 0}v=u+12|0;if((c[v>>2]|0)!=(o|0)){an();return 0}w=t+8|0;if((c[w>>2]|0)==(o|0)){c[v>>2]=t;c[w>>2]=u;y=t;break}else{an();return 0}}}while(0);if((s|0)==0){break}t=g+(f+28)|0;l=8920+(c[t>>2]<<2)|0;do{if((o|0)==(c[l>>2]|0)){c[l>>2]=y;if((y|0)!=0){break}c[2155]=c[2155]&~(1<>2]);break L2217}else{if(s>>>0<(c[2158]|0)>>>0){an();return 0}k=s+16|0;if((c[k>>2]|0)==(o|0)){c[k>>2]=y}else{c[s+20>>2]=y}if((y|0)==0){break L2217}}}while(0);if(y>>>0<(c[2158]|0)>>>0){an();return 0}c[y+24>>2]=s;o=c[g+(f+16)>>2]|0;do{if((o|0)!=0){if(o>>>0<(c[2158]|0)>>>0){an();return 0}else{c[y+16>>2]=o;c[o+24>>2]=y;break}}}while(0);o=c[g+(f+20)>>2]|0;if((o|0)==0){break}if(o>>>0<(c[2158]|0)>>>0){an();return 0}else{c[y+20>>2]=o;c[o+24>>2]=y;break}}}while(0);if(q>>>0<16){c[d>>2]=p|c[d>>2]&1|2;y=g+(p|4)|0;c[y>>2]=c[y>>2]|1;n=a;return n|0}else{c[d>>2]=c[d>>2]&1|b|2;c[g+(b+4)>>2]=q|3;d=g+(p|4)|0;c[d>>2]=c[d>>2]|1;en(g+b|0,q);n=a;return n|0}return 0}function en(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0;d=a;e=d+b|0;f=e;g=c[a+4>>2]|0;L2293:do{if((g&1|0)==0){h=c[a>>2]|0;if((g&3|0)==0){return}i=d+(-h|0)|0;j=i;k=h+b|0;l=c[2158]|0;if(i>>>0>>0){an()}if((j|0)==(c[2159]|0)){m=d+(b+4)|0;if((c[m>>2]&3|0)!=3){n=j;o=k;break}c[2156]=k;c[m>>2]=c[m>>2]&-2;c[d+(4-h)>>2]=k|1;c[e>>2]=k;return}m=h>>>3;if(h>>>0<256){p=c[d+(8-h)>>2]|0;q=c[d+(12-h)>>2]|0;r=8656+(m<<1<<2)|0;do{if((p|0)!=(r|0)){if(p>>>0>>0){an()}if((c[p+12>>2]|0)==(j|0)){break}an()}}while(0);if((q|0)==(p|0)){c[2154]=c[2154]&~(1<>>0>>0){an()}t=q+8|0;if((c[t>>2]|0)==(j|0)){s=t;break}an()}}while(0);c[p+12>>2]=q;c[s>>2]=p;n=j;o=k;break}r=i;m=c[d+(24-h)>>2]|0;t=c[d+(12-h)>>2]|0;do{if((t|0)==(r|0)){u=16-h|0;v=d+(u+4)|0;w=c[v>>2]|0;if((w|0)==0){x=d+u|0;u=c[x>>2]|0;if((u|0)==0){y=0;break}else{z=u;A=x}}else{z=w;A=v}while(1){v=z+20|0;w=c[v>>2]|0;if((w|0)!=0){z=w;A=v;continue}v=z+16|0;w=c[v>>2]|0;if((w|0)==0){break}else{z=w;A=v}}if(A>>>0>>0){an()}else{c[A>>2]=0;y=z;break}}else{v=c[d+(8-h)>>2]|0;if(v>>>0>>0){an()}w=v+12|0;if((c[w>>2]|0)!=(r|0)){an()}x=t+8|0;if((c[x>>2]|0)==(r|0)){c[w>>2]=t;c[x>>2]=v;y=t;break}else{an()}}}while(0);if((m|0)==0){n=j;o=k;break}t=d+(28-h)|0;l=8920+(c[t>>2]<<2)|0;do{if((r|0)==(c[l>>2]|0)){c[l>>2]=y;if((y|0)!=0){break}c[2155]=c[2155]&~(1<>2]);n=j;o=k;break L2293}else{if(m>>>0<(c[2158]|0)>>>0){an()}i=m+16|0;if((c[i>>2]|0)==(r|0)){c[i>>2]=y}else{c[m+20>>2]=y}if((y|0)==0){n=j;o=k;break L2293}}}while(0);if(y>>>0<(c[2158]|0)>>>0){an()}c[y+24>>2]=m;r=16-h|0;t=c[d+r>>2]|0;do{if((t|0)!=0){if(t>>>0<(c[2158]|0)>>>0){an()}else{c[y+16>>2]=t;c[t+24>>2]=y;break}}}while(0);t=c[d+(r+4)>>2]|0;if((t|0)==0){n=j;o=k;break}if(t>>>0<(c[2158]|0)>>>0){an()}else{c[y+20>>2]=t;c[t+24>>2]=y;n=j;o=k;break}}else{n=a;o=b}}while(0);a=c[2158]|0;if(e>>>0>>0){an()}y=d+(b+4)|0;z=c[y>>2]|0;do{if((z&2|0)==0){if((f|0)==(c[2160]|0)){A=(c[2157]|0)+o|0;c[2157]=A;c[2160]=n;c[n+4>>2]=A|1;if((n|0)!=(c[2159]|0)){return}c[2159]=0;c[2156]=0;return}if((f|0)==(c[2159]|0)){A=(c[2156]|0)+o|0;c[2156]=A;c[2159]=n;c[n+4>>2]=A|1;c[n+A>>2]=A;return}A=(z&-8)+o|0;s=z>>>3;L2392:do{if(z>>>0<256){g=c[d+(b+8)>>2]|0;t=c[d+(b+12)>>2]|0;h=8656+(s<<1<<2)|0;do{if((g|0)!=(h|0)){if(g>>>0>>0){an()}if((c[g+12>>2]|0)==(f|0)){break}an()}}while(0);if((t|0)==(g|0)){c[2154]=c[2154]&~(1<>>0>>0){an()}m=t+8|0;if((c[m>>2]|0)==(f|0)){B=m;break}an()}}while(0);c[g+12>>2]=t;c[B>>2]=g}else{h=e;m=c[d+(b+24)>>2]|0;l=c[d+(b+12)>>2]|0;do{if((l|0)==(h|0)){i=d+(b+20)|0;p=c[i>>2]|0;if((p|0)==0){q=d+(b+16)|0;v=c[q>>2]|0;if((v|0)==0){C=0;break}else{D=v;E=q}}else{D=p;E=i}while(1){i=D+20|0;p=c[i>>2]|0;if((p|0)!=0){D=p;E=i;continue}i=D+16|0;p=c[i>>2]|0;if((p|0)==0){break}else{D=p;E=i}}if(E>>>0>>0){an()}else{c[E>>2]=0;C=D;break}}else{i=c[d+(b+8)>>2]|0;if(i>>>0>>0){an()}p=i+12|0;if((c[p>>2]|0)!=(h|0)){an()}q=l+8|0;if((c[q>>2]|0)==(h|0)){c[p>>2]=l;c[q>>2]=i;C=l;break}else{an()}}}while(0);if((m|0)==0){break}l=d+(b+28)|0;g=8920+(c[l>>2]<<2)|0;do{if((h|0)==(c[g>>2]|0)){c[g>>2]=C;if((C|0)!=0){break}c[2155]=c[2155]&~(1<>2]);break L2392}else{if(m>>>0<(c[2158]|0)>>>0){an()}t=m+16|0;if((c[t>>2]|0)==(h|0)){c[t>>2]=C}else{c[m+20>>2]=C}if((C|0)==0){break L2392}}}while(0);if(C>>>0<(c[2158]|0)>>>0){an()}c[C+24>>2]=m;h=c[d+(b+16)>>2]|0;do{if((h|0)!=0){if(h>>>0<(c[2158]|0)>>>0){an()}else{c[C+16>>2]=h;c[h+24>>2]=C;break}}}while(0);h=c[d+(b+20)>>2]|0;if((h|0)==0){break}if(h>>>0<(c[2158]|0)>>>0){an()}else{c[C+20>>2]=h;c[h+24>>2]=C;break}}}while(0);c[n+4>>2]=A|1;c[n+A>>2]=A;if((n|0)!=(c[2159]|0)){F=A;break}c[2156]=A;return}else{c[y>>2]=z&-2;c[n+4>>2]=o|1;c[n+o>>2]=o;F=o}}while(0);o=F>>>3;if(F>>>0<256){z=o<<1;y=8656+(z<<2)|0;C=c[2154]|0;b=1<>2]|0;if(d>>>0>=(c[2158]|0)>>>0){G=d;H=o;break}an()}}while(0);c[H>>2]=n;c[G+12>>2]=n;c[n+8>>2]=G;c[n+12>>2]=y;return}y=n;G=F>>>8;do{if((G|0)==0){I=0}else{if(F>>>0>16777215){I=31;break}H=(G+1048320|0)>>>16&8;z=G<>>16&4;C=z<>>16&2;o=14-(b|H|z)+(C<>>15)|0;I=F>>>((o+7|0)>>>0)&1|o<<1}}while(0);G=8920+(I<<2)|0;c[n+28>>2]=I;c[n+20>>2]=0;c[n+16>>2]=0;o=c[2155]|0;z=1<>2]=y;c[n+24>>2]=G;c[n+12>>2]=n;c[n+8>>2]=n;return}if((I|0)==31){J=0}else{J=25-(I>>>1)|0}I=F<>2]|0;while(1){if((c[J+4>>2]&-8|0)==(F|0)){break}K=J+16+(I>>>31<<2)|0;G=c[K>>2]|0;if((G|0)==0){L=1887;break}else{I=I<<1;J=G}}if((L|0)==1887){if(K>>>0<(c[2158]|0)>>>0){an()}c[K>>2]=y;c[n+24>>2]=J;c[n+12>>2]=n;c[n+8>>2]=n;return}K=J+8|0;L=c[K>>2]|0;I=c[2158]|0;if(J>>>0>>0){an()}if(L>>>0>>0){an()}c[L+12>>2]=y;c[K>>2]=y;c[n+8>>2]=L;c[n+12>>2]=J;c[n+24>>2]=0;return}function eo(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0,t=0,u=0,v=0.0,w=0,x=0,y=0,z=0.0,A=0.0,B=0,C=0,D=0,E=0.0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0.0,O=0,P=0,Q=0.0,R=0.0,S=0.0;e=b;while(1){f=e+1|0;if((aY(a[e]|0)|0)==0){break}else{e=f}}switch(a[e]|0){case 43:{g=f;i=0;break};case 45:{g=f;i=1;break};default:{g=e;i=0}}e=-1;f=0;j=g;while(1){k=a[j]|0;if(((k<<24>>24)-48|0)>>>0<10){l=e}else{if(k<<24>>24!=46|(e|0)>-1){break}else{l=f}}e=l;f=f+1|0;j=j+1|0}l=j+(-f|0)|0;g=(e|0)<0;m=((g^1)<<31>>31)+f|0;n=(m|0)>18;o=(n?-18:-m|0)+(g?f:e)|0;e=n?18:m;do{if((e|0)==0){p=b;q=0.0}else{if((e|0)>9){m=l;n=e;f=0;while(1){g=a[m]|0;r=m+1|0;if(g<<24>>24==46){s=a[r]|0;t=m+2|0}else{s=g;t=r}u=(f*10|0)-48+(s<<24>>24)|0;r=n-1|0;if((r|0)>9){m=t;n=r;f=u}else{break}}v=+(u|0)*1.0e9;w=9;x=t;y=1935}else{if((e|0)>0){v=0.0;w=e;x=l;y=1935}else{z=0.0;A=0.0}}if((y|0)==1935){f=x;n=w;m=0;while(1){r=a[f]|0;g=f+1|0;if(r<<24>>24==46){B=a[g]|0;C=f+2|0}else{B=r;C=g}D=(m*10|0)-48+(B<<24>>24)|0;g=n-1|0;if((g|0)>0){f=C;n=g;m=D}else{break}}z=+(D|0);A=v}E=A+z;L2536:do{switch(k<<24>>24){case 69:case 101:{m=j+1|0;switch(a[m]|0){case 43:{F=j+2|0;G=0;break};case 45:{F=j+2|0;G=1;break};default:{F=m;G=0}}m=a[F]|0;if(((m<<24>>24)-48|0)>>>0<10){H=F;I=0;J=m}else{K=0;L=F;M=G;break L2536}while(1){m=(I*10|0)-48+(J<<24>>24)|0;n=H+1|0;f=a[n]|0;if(((f<<24>>24)-48|0)>>>0<10){H=n;I=m;J=f}else{K=m;L=n;M=G;break}}break};default:{K=0;L=j;M=0}}}while(0);n=o+((M|0)==0?K:-K|0)|0;m=(n|0)<0?-n|0:n;if((m|0)>511){c[(aW()|0)>>2]=34;N=1.0;O=16;P=511;y=1952}else{if((m|0)==0){Q=1.0}else{N=1.0;O=16;P=m;y=1952}}if((y|0)==1952){while(1){y=0;if((P&1|0)==0){R=N}else{R=N*+h[O>>3]}m=P>>1;if((m|0)==0){Q=R;break}else{N=R;O=O+8|0;P=m;y=1952}}}if((n|0)>-1){p=L;q=E*Q;break}else{p=L;q=E/Q;break}}}while(0);if((d|0)!=0){c[d>>2]=p}if((i|0)==0){S=q;return+S}S=-0.0-q;return+S}function ep(a){a=a|0;return+(+eo(a,0))}function eq(a){a=a|0;if((a|0)<65)return a|0;if((a|0)>90)return a|0;return a-65+97|0}function er(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;while(e>>>0>>0){f=eq(a[b+e|0]|0)|0;g=eq(a[c+e|0]|0)|0;if((f|0)==(g|0)&(f|0)==0)return 0;if((f|0)==0)return-1;if((g|0)==0)return 1;if((f|0)==(g|0)){e=e+1|0;continue}else{return(f>>>0>g>>>0?1:-1)|0}}return 0}function es(a,b){a=a|0;b=b|0;return er(a,b,-1)|0}function et(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0;while((e|0)<(d|0)){a[b+e|0]=f?0:a[c+e|0]|0;f=f?1:(a[c+e|0]|0)==0;e=e+1|0}return b|0}function eu(b){b=b|0;var c=0;c=b;while(a[c]|0){c=c+1|0}return c-b|0}function ev(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;f=b|0;if((b&3)==(d&3)){while(b&3){if((e|0)==0)return f|0;a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function ew(b,c){b=b|0;c=c|0;var d=0;do{a[b+d|0]=a[c+d|0];d=d+1|0}while(a[c+(d-1)|0]|0);return b|0}function ex(b,c){b=b|0;c=c|0;var d=0,e=0;d=b+(eu(b)|0)|0;do{a[d+e|0]=a[c+e|0];e=e+1|0}while(a[c+(e-1)|0]|0);return b|0}function ey(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=b+e|0;if((e|0)>=20){d=d&255;e=b&3;g=d|d<<8|d<<16|d<<24;h=f&~3;if(e){e=b+4-e|0;while((b|0)<(e|0)){a[b]=d;b=b+1|0}}while((b|0)<(h|0)){c[b>>2]=g;b=b+4|0}}while((b|0)<(f|0)){a[b]=d;b=b+1|0}}function ez(a,b){a=a|0;b=b|0;a5[a&1](b|0)}function eA(a,b){a=a|0;b=b|0;return a6[a&1](b|0)|0}function eB(a){a=a|0;a7[a&1]()}function eC(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=d|0;e=e|0;f=f|0;return a8[a&127](+b,+c,d|0,e|0,f|0)|0}function eD(a,b,c){a=a|0;b=b|0;c=c|0;return a9[a&1](b|0,c|0)|0}function eE(a){a=a|0;$(0)}function eF(a){a=a|0;$(1);return 0}function eG(){$(2)}function eH(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;$(3);return 0}function eI(a,b){a=a|0;b=b|0;$(4);return 0} +// EMSCRIPTEN_END_FUNCS +var a5=[eE,eE];var a6=[eF,eF];var a7=[eG,eG];var a8=[eH,eH,dq,eH,dS,eH,dw,eH,dk,eH,dh,eH,df,eH,dN,eH,dY,eH,dz,eH,dC,eH,dU,eH,dW,eH,dr,eH,dG,eH,dB,eH,ds,eH,dH,eH,dx,eH,dK,eH,d2,eH,du,eH,d1,eH,d$,eH,dL,eH,dV,eH,d4,eH,dI,eH,dg,eH,dM,eH,di,eH,dt,eH,dj,eH,d_,eH,dR,eH,dZ,eH,dO,eH,dT,eH,dQ,eH,dm,eH,dF,eH,dP,eH,d3,eH,dv,eH,dy,eH,dp,eH,dE,eH,dJ,eH,dD,eH,dn,eH,d0,eH,dX,eH,dA,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH,eH];var a9=[eI,eI];return{_strncasecmp:er,_strcat:ex,_free:ek,_memcpy:ev,_realloc:el,_strncpy:et,_tolower:eq,_strlen:eu,_initwcs:br,_memset:ey,_malloc:ei,_wcsunits:bu,_reg2wcsstr:bv,_strcasecmp:es,_wcssys:bt,_pix2wcsstr:bs,_strcpy:ew,_calloc:ej,runPostSets:bq,stackAlloc:ba,stackSave:bb,stackRestore:bc,setThrew:bd,setTempRet0:bg,setTempRet1:bh,setTempRet2:bi,setTempRet3:bj,setTempRet4:bk,setTempRet5:bl,setTempRet6:bm,setTempRet7:bn,setTempRet8:bo,setTempRet9:bp,dynCall_vi:ez,dynCall_ii:eA,dynCall_v:eB,dynCall_iffiii:eC,dynCall_iii:eD}}) +// EMSCRIPTEN_END_ASM +({ "Math": Math, "Int8Array": Int8Array, "Int16Array": Int16Array, "Int32Array": Int32Array, "Uint8Array": Uint8Array, "Uint16Array": Uint16Array, "Uint32Array": Uint32Array, "Float32Array": Float32Array, "Float64Array": Float64Array }, { "abort": abort, "assert": assert, "asmPrintInt": asmPrintInt, "asmPrintFloat": asmPrintFloat, "min": Math_min, "invoke_vi": invoke_vi, "invoke_ii": invoke_ii, "invoke_v": invoke_v, "invoke_iffiii": invoke_iffiii, "invoke_iii": invoke_iii, "_strncmp": _strncmp, "_fabsf": _fabsf, "_snprintf": _snprintf, "_strtok_r": _strtok_r, "_abort": _abort, "_fprintf": _fprintf, "_sqrt": _sqrt, "_toupper": _toupper, "_fflush": _fflush, "___buildEnvironment": ___buildEnvironment, "__reallyNegative": __reallyNegative, "_tan": _tan, "_strchr": _strchr, "_asin": _asin, "_strtol": _strtol, "_log": _log, "_fabs": _fabs, "_strtok": _strtok, "___setErrNo": ___setErrNo, "_fwrite": _fwrite, "_send": _send, "_write": _write, "_exit": _exit, "_sprintf": _sprintf, "_llvm_lifetime_end": _llvm_lifetime_end, "_strdup": _strdup, "_sin": _sin, "_strncat": _strncat, "_atan2": _atan2, "_atan": _atan, "__exit": __exit, "_time": _time, "__formatString": __formatString, "_getenv": _getenv, "_atoi": _atoi, "_cos": _cos, "_pwrite": _pwrite, "_llvm_pow_f64": _llvm_pow_f64, "_sbrk": _sbrk, "___errno_location": ___errno_location, "_fmod": _fmod, "_isspace": _isspace, "_llvm_lifetime_start": _llvm_lifetime_start, "__parseInt": __parseInt, "_sysconf": _sysconf, "_islower": _islower, "_exp": _exp, "_acos": _acos, "_isupper": _isupper, "_strcmp": _strcmp, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "NaN": NaN, "Infinity": Infinity, "_stderr": _stderr }, buffer); +var _strncasecmp = Module["_strncasecmp"] = asm["_strncasecmp"]; +var _strcat = Module["_strcat"] = asm["_strcat"]; +var _free = Module["_free"] = asm["_free"]; +var _memcpy = Module["_memcpy"] = asm["_memcpy"]; +var _realloc = Module["_realloc"] = asm["_realloc"]; +var _strncpy = Module["_strncpy"] = asm["_strncpy"]; +var _tolower = Module["_tolower"] = asm["_tolower"]; +var _strlen = Module["_strlen"] = asm["_strlen"]; +var _initwcs = Module["_initwcs"] = asm["_initwcs"]; +var _memset = Module["_memset"] = asm["_memset"]; +var _malloc = Module["_malloc"] = asm["_malloc"]; +var _wcsunits = Module["_wcsunits"] = asm["_wcsunits"]; +var _reg2wcsstr = Module["_reg2wcsstr"] = asm["_reg2wcsstr"]; +var _strcasecmp = Module["_strcasecmp"] = asm["_strcasecmp"]; +var _wcssys = Module["_wcssys"] = asm["_wcssys"]; +var _pix2wcsstr = Module["_pix2wcsstr"] = asm["_pix2wcsstr"]; +var _strcpy = Module["_strcpy"] = asm["_strcpy"]; +var _calloc = Module["_calloc"] = asm["_calloc"]; +var runPostSets = Module["runPostSets"] = asm["runPostSets"]; +var dynCall_vi = Module["dynCall_vi"] = asm["dynCall_vi"]; +var dynCall_ii = Module["dynCall_ii"] = asm["dynCall_ii"]; +var dynCall_v = Module["dynCall_v"] = asm["dynCall_v"]; +var dynCall_iffiii = Module["dynCall_iffiii"] = asm["dynCall_iffiii"]; +var dynCall_iii = Module["dynCall_iii"] = asm["dynCall_iii"]; +Runtime.stackAlloc = function(size) { return asm['stackAlloc'](size) }; +Runtime.stackSave = function() { return asm['stackSave']() }; +Runtime.stackRestore = function(top) { asm['stackRestore'](top) }; +// Warning: printing of i64 values may be slightly rounded! No deep i64 math used, so precise i64 code not included +var i64Math = null; +// === Auto-generated postamble setup entry stuff === +function ExitStatus(status) { + this.name = "ExitStatus"; + this.message = "Program terminated with exit(" + status + ")"; + this.status = status; +}; +ExitStatus.prototype = new Error(); +ExitStatus.prototype.constructor = ExitStatus; +var initialStackTop; +var preloadStartTime = null; +Module['callMain'] = Module.callMain = function callMain(args) { + assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)'); + assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called'); + args = args || []; + if (ENVIRONMENT_IS_WEB && preloadStartTime !== null) { + Module.printErr('preload time: ' + (Date.now() - preloadStartTime) + ' ms'); + } + ensureInitRuntime(); + var argc = args.length+1; + function pad() { + for (var i = 0; i < 4-1; i++) { + argv.push(0); + } + } + var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL) ]; + pad(); + for (var i = 0; i < argc-1; i = i + 1) { + argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL)); + pad(); + } + argv.push(0); + argv = allocate(argv, 'i32', ALLOC_NORMAL); + initialStackTop = STACKTOP; + try { + var ret = Module['_main'](argc, argv, 0); + // if we're not running an evented main loop, it's time to exit + if (!Module['noExitRuntime']) { + exit(ret); + } + } + catch(e) { + if (e instanceof ExitStatus) { + // exit() throws this once it's done to make sure execution + // has been stopped completely + return; + } else if (e == 'SimulateInfiniteLoop') { + // running an evented main loop, don't immediately exit + Module['noExitRuntime'] = true; + return; + } else { + throw e; + } + } +} +function run(args) { + args = args || Module['arguments']; + if (preloadStartTime === null) preloadStartTime = Date.now(); + if (runDependencies > 0) { + Module.printErr('run() called, but dependencies remain, so not running'); + return; + } + preRun(); + if (runDependencies > 0) { + // a preRun added a dependency, run will be called later + return; + } + function doRun() { + ensureInitRuntime(); + preMain(); + calledRun = true; + if (Module['_main'] && shouldRunNow) { + Module['callMain'](args); + } + postRun(); + } + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + if (!ABORT) doRun(); + }, 1); + } else { + doRun(); + } +} +Module['run'] = Module.run = run; +function exit(status) { + ABORT = true; + EXITSTATUS = status; + STACKTOP = initialStackTop; + // exit the runtime + exitRuntime(); + // throw an exception to halt the current execution + throw new ExitStatus(status); +} +Module['exit'] = Module.exit = exit; +function abort(text) { + if (text) { + Module.print(text); + Module.printErr(text); + } + ABORT = true; + EXITSTATUS = 1; + throw 'abort() at ' + (new Error().stack); +} +Module['abort'] = Module.abort = abort; +// {{PRE_RUN_ADDITIONS}} +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} +// shouldRunNow refers to calling main(), not run(). +var shouldRunNow = true; +if (Module['noInitialRun']) { + shouldRunNow = false; +} +run(); +// {{POST_RUN_ADDITIONS}} +// {{MODULE_ADDITIONS}} diff --git a/astroem/wcstrig.c b/astroem/wcstrig.c new file mode 100644 index 00000000..6a30d033 --- /dev/null +++ b/astroem/wcstrig.c @@ -0,0 +1,189 @@ +/*============================================================================ +* +* WCSLIB - an implementation of the FITS WCS proposal. +* Copyright (C) 1995-2002, Mark Calabretta +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +* Correspondence concerning WCSLIB may be directed to: +* Internet email: mcalabre@atnf.csiro.au +* Postal address: Dr. Mark Calabretta, +* Australia Telescope National Facility, +* P.O. Box 76, +* Epping, NSW, 2121, +* AUSTRALIA +* +*============================================================================= +* +* The functions defined herein are trigonometric or inverse trigonometric +* functions which take or return angular arguments in decimal degrees. +* +* $Id: wcstrig.c,v 2.8 2002/04/03 01:25:29 mcalabre Exp $ +*---------------------------------------------------------------------------*/ + +#include +#include "wcslib.h" +const double d2r = PI / 180.0; +const double r2d = 180.0 / PI; + + +double cosdeg (angle) + +const double angle; + +{ + double resid; + + resid = fabs(fmod(angle,360.0)); + if (resid == 0.0) { + return 1.0; + } else if (resid == 90.0) { + return 0.0; + } else if (resid == 180.0) { + return -1.0; + } else if (resid == 270.0) { + return 0.0; + } + + return cos(angle*d2r); +} + +/*--------------------------------------------------------------------------*/ + +double sindeg (angle) + +const double angle; + +{ + double resid; + + resid = fmod(angle-90.0,360.0); + if (resid == 0.0) { + return 1.0; + } else if (resid == 90.0) { + return 0.0; + } else if (resid == 180.0) { + return -1.0; + } else if (resid == 270.0) { + return 0.0; + } + + return sin(angle*d2r); +} + +/*--------------------------------------------------------------------------*/ + +double tandeg (angle) + +const double angle; + +{ + double resid; + + resid = fmod(angle,360.0); + if (resid == 0.0 || fabs(resid) == 180.0) { + return 0.0; + } else if (resid == 45.0 || resid == 225.0) { + return 1.0; + } else if (resid == -135.0 || resid == -315.0) { + return -1.0; + } + + return tan(angle*d2r); +} + +/*--------------------------------------------------------------------------*/ + +double acosdeg(v) + +const double v; + +{ + if (v >= 1.0) { + if (v-1.0 < WCSTRIG_TOL) return 0.0; + } else if (v == 0.0) { + return 90.0; + } else if (v <= -1.0) { + if (v+1.0 > -WCSTRIG_TOL) return 180.0; + } + + return acos(v)*r2d; +} + +/*--------------------------------------------------------------------------*/ + +double asindeg (v) + +const double v; + +{ + if (v <= -1.0) { + if (v+1.0 > -WCSTRIG_TOL) return -90.0; + } else if (v == 0.0) { + return 0.0; + } else if (v >= 1.0) { + if (v-1.0 < WCSTRIG_TOL) return 90.0; + } + + return asin(v)*r2d; +} + +/*--------------------------------------------------------------------------*/ + +double atandeg (v) + +const double v; + +{ + if (v == -1.0) { + return -45.0; + } else if (v == 0.0) { + return 0.0; + } else if (v == 1.0) { + return 45.0; + } + + return atan(v)*r2d; +} + +/*--------------------------------------------------------------------------*/ + +double atan2deg (y, x) + +const double x, y; + +{ + if (y == 0.0) { + if (x >= 0.0) { + return 0.0; + } else if (x < 0.0) { + return 180.0; + } + } else if (x == 0.0) { + if (y > 0.0) { + return 90.0; + } else if (y < 0.0) { + return -90.0; + } + } + + return atan2(y,x)*r2d; +} +/* Dec 20 1999 Doug Mink - Change cosd() and sind() to cosdeg() and sindeg() + * Dec 20 1999 Doug Mink - Include wcslib.h, which includes wcstrig.h + * Dec 20 1999 Doug Mink - Use PI from wcslib.h, not locally defined + * + * Sep 19 2001 Doug Mink - No change for WCSLIB 2.7 + */ diff --git a/astroem/worldpos.c b/astroem/worldpos.c new file mode 100644 index 00000000..86937892 --- /dev/null +++ b/astroem/worldpos.c @@ -0,0 +1,693 @@ +/* worldpos.c -- WCS Algorithms from Classic AIPS. + * September 1, 2011 + * Copyright (C) 1994-2011 + * Associated Universities, Inc. Washington DC, USA. + * With code added by Jessica Mink, Smithsonian Astrophysical Observatory + * and Allan Brighton and Andreas Wicenec, ESO + * and Frank Valdes, NOAO + + * Module: worldpos.c + * Purpose: Perform forward and reverse WCS computations for 8 projections + * Subroutine: worldpos() converts from pixel location to RA,Dec + * Subroutine: worldpix() converts from RA,Dec to pixel location + + -=-=-=-=-=-=- + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning AIPS should be addressed as follows: + Internet email: aipsmail@nrao.edu + Postal address: AIPS Group + National Radio Astronomy Observatory + 520 Edgemont Road + Charlottesville, VA 22903-2475 USA + + -=-=-=-=-=-=- + + These two ANSI C functions, worldpos() and worldpix(), perform + forward and reverse WCS computations for 8 types of projective + geometries ("-SIN", "-TAN", "-ARC", "-NCP", "-GLS" or "-SFL", "-MER", + "-AIT", "-STG", "CAR", and "COE"): + + worldpos() converts from pixel location to RA,Dec + worldpix() converts from RA,Dec to pixel location + + where "(RA,Dec)" are more generically (long,lat). These functions + are based on the WCS implementation of Classic AIPS, an + implementation which has been in production use for more than ten + years. See the two memos by Eric Greisen + + ftp://fits.cv.nrao.edu/fits/documents/wcs/aips27.ps.Z + ftp://fits.cv.nrao.edu/fits/documents/wcs/aips46.ps.Z + + for descriptions of the 8 projective geometries and the + algorithms. Footnotes in these two documents describe the + differences between these algorithms and the 1993-94 WCS draft + proposal (see URL below). In particular, these algorithms support + ordinary field rotation, but not skew geometries (CD or PC matrix + cases). Also, the MER and AIT algorithms work correctly only for + CRVALi=(0,0). Users should note that GLS projections with yref!=0 + will behave differently in this code than in the draft WCS + proposal. The NCP projection is now obsolete (it is a special + case of SIN). WCS syntax and semantics for various advanced + features is discussed in the draft WCS proposal by Greisen and + Calabretta at: + + ftp://fits.cv.nrao.edu/fits/documents/wcs/wcs.all.ps.Z + + -=-=-=- + + The original version of this code was Emailed to D.Wells on + Friday, 23 September by Bill Cotton , + who described it as a "..more or less.. exact translation from the + AIPSish..". Changes were made by Don Wells + during the period October 11-13, 1994: + 1) added GNU license and header comments + 2) added testpos.c program to perform extensive circularity tests + 3) changed float-->double to get more than 7 significant figures + 4) testpos.c circularity test failed on MER and AIT. B.Cotton + found that "..there were a couple of lines of code [in] the wrong + place as a result of merging several Fortran routines." + 5) testpos.c found 0h wraparound in worldpix() and worldpos(). + 6) E.Greisen recommended removal of various redundant if-statements, + and addition of a 360d difference test to MER case of worldpos(). + 7) D.Mink changed input to data structure and implemented rotation matrix. +*/ +#include +#include +#include +#include "wcs.h" + +int +worldpos (xpix, ypix, wcs, xpos, ypos) + +/* Routine to determine accurate position for pixel coordinates */ +/* returns 0 if successful otherwise 1 = angle too large for projection; */ +/* does: -SIN, -TAN, -ARC, -NCP, -GLS or -SFL, -MER, -AIT projections */ +/* anything else is linear */ + +/* Input: */ +double xpix; /* x pixel number (RA or long without rotation) */ +double ypix; /* y pixel number (Dec or lat without rotation) */ +struct WorldCoor *wcs; /* WCS parameter structure */ + +/* Output: */ +double *xpos; /* x (RA) coordinate (deg) */ +double *ypos; /* y (dec) coordinate (deg) */ + +{ + double cosr, sinr, dx, dy, dz, tx; + double sins, coss, dt, l, m, mg, da, dd, cos0, sin0; + double rat = 0.0; + double dect = 0.0; + double mt, a, y0, td, r2; /* allan: for COE */ + double dec0, ra0, decout, raout; + double geo1, geo2, geo3; + double cond2r=1.745329252e-2; + double twopi = 6.28318530717959; + double deps = 1.0e-5; + + /* Structure elements */ + double xref; /* X reference coordinate value (deg) */ + double yref; /* Y reference coordinate value (deg) */ + double xrefpix; /* X reference pixel */ + double yrefpix; /* Y reference pixel */ + double xinc; /* X coordinate increment (deg) */ + double yinc; /* Y coordinate increment (deg) */ + double rot; /* Optical axis rotation (deg) (N through E) */ + int itype = wcs->prjcode; + + /* Set local projection parameters */ + xref = wcs->xref; + yref = wcs->yref; + xrefpix = wcs->xrefpix; + yrefpix = wcs->yrefpix; + xinc = wcs->xinc; + yinc = wcs->yinc; + rot = degrad (wcs->rot); + cosr = cos (rot); + sinr = sin (rot); + + /* Offset from ref pixel */ + dx = xpix - xrefpix; + dy = ypix - yrefpix; + + /* Scale and rotate using CD matrix */ + if (wcs->rotmat) { + tx = dx * wcs->cd[0] + dy * wcs->cd[1]; + dy = dx * wcs->cd[2] + dy * wcs->cd[3]; + dx = tx; + } + + /* Scale and rotate using CDELTn and CROTA2 */ + else { + + /* Check axis increments - bail out if either 0 */ + if ((xinc==0.0) || (yinc==0.0)) { + *xpos=0.0; + *ypos=0.0; + return 2; + } + + /* Scale using CDELT */ + dx = dx * xinc; + dy = dy * yinc; + + /* Take out rotation from CROTA */ + if (rot != 0.0) { + tx = dx * cosr - dy * sinr; + dy = dx * sinr + dy * cosr; + dx = tx; + } + } + + /* Flip coordinates if necessary */ + if (wcs->coorflip) { + tx = dx; + dx = dy; + dy = tx; + } + + /* Default, linear result for error or pixel return */ + *xpos = xref + dx; + *ypos = yref + dy; + if (itype <= 0) + return 0; + + /* Convert to radians */ + if (wcs->coorflip) { + dec0 = degrad (xref); + ra0 = degrad (yref); + } + else { + ra0 = degrad (xref); + dec0 = degrad (yref); + } + l = degrad (dx); + m = degrad (dy); + sins = l*l + m*m; + decout = 0.0; + raout = 0.0; + cos0 = cos (dec0); + sin0 = sin (dec0); + + /* Process by case */ + switch (itype) { + + case WCS_CAR: /* -CAR Cartesian (was WCS_PIX pixel and WCS_LIN linear) */ + rat = ra0 + l; + dect = dec0 + m; + break; + + case WCS_SIN: /* -SIN sin*/ + if (sins>1.0) return 1; + coss = sqrt (1.0 - sins); + dt = sin0 * coss + cos0 * m; + if ((dt>1.0) || (dt<-1.0)) return 1; + dect = asin (dt); + rat = cos0 * coss - sin0 * m; + if ((rat==0.0) && (l==0.0)) return 1; + rat = atan2 (l, rat) + ra0; + break; + + case WCS_TAN: /* -TAN tan */ + case WCS_TNX: /* -TNX tan with polynomial correction */ + case WCS_TPV: /* -TPV tan with polynomial correction */ + case WCS_ZPX: /* -ZPX zpn with polynomial correction */ + if (sins>1.0) return 1; + dect = cos0 - m * sin0; + if (dect==0.0) return 1; + rat = ra0 + atan2 (l, dect); + dect = atan (cos(rat-ra0) * (m * cos0 + sin0) / dect); + break; + + case WCS_ARC: /* -ARC Arc*/ + if (sins>=twopi*twopi/4.0) return 1; + sins = sqrt(sins); + coss = cos (sins); + if (sins!=0.0) sins = sin (sins) / sins; + else + sins = 1.0; + dt = m * cos0 * sins + sin0 * coss; + if ((dt>1.0) || (dt<-1.0)) return 1; + dect = asin (dt); + da = coss - dt * sin0; + dt = l * sins * cos0; + if ((da==0.0) && (dt==0.0)) return 1; + rat = ra0 + atan2 (dt, da); + break; + + case WCS_NCP: /* -NCP North celestial pole*/ + dect = cos0 - m * sin0; + if (dect==0.0) return 1; + rat = ra0 + atan2 (l, dect); + dt = cos (rat-ra0); + if (dt==0.0) return 1; + dect = dect / dt; + if ((dect>1.0) || (dect<-1.0)) return 1; + dect = acos (dect); + if (dec0<0.0) dect = -dect; + break; + + case WCS_GLS: /* -GLS global sinusoid */ + case WCS_SFL: /* -SFL Samson-Flamsteed */ + dect = dec0 + m; + if (fabs(dect)>twopi/4.0) return 1; + coss = cos (dect); + if (fabs(l)>twopi*coss/2.0) return 1; + rat = ra0; + if (coss>deps) rat = rat + l / coss; + break; + + case WCS_MER: /* -MER mercator*/ + dt = yinc * cosr + xinc * sinr; + if (dt==0.0) dt = 1.0; + dy = degrad (yref/2.0 + 45.0); + dx = dy + dt / 2.0 * cond2r; + dy = log (tan (dy)); + dx = log (tan (dx)); + geo2 = degrad (dt) / (dx - dy); + geo3 = geo2 * dy; + geo1 = cos (degrad (yref)); + if (geo1<=0.0) geo1 = 1.0; + rat = l / geo1 + ra0; + if (fabs(rat - ra0) > twopi) return 1; /* added 10/13/94 DCW/EWG */ + dt = 0.0; + if (geo2!=0.0) dt = (m + geo3) / geo2; + dt = exp (dt); + dect = 2.0 * atan (dt) - twopi / 4.0; + break; + + case WCS_AIT: /* -AIT Aitoff*/ + dt = yinc*cosr + xinc*sinr; + if (dt==0.0) dt = 1.0; + dt = degrad (dt); + dy = degrad (yref); + dx = sin(dy+dt)/sqrt((1.0+cos(dy+dt))/2.0) - + sin(dy)/sqrt((1.0+cos(dy))/2.0); + if (dx==0.0) dx = 1.0; + geo2 = dt / dx; + dt = xinc*cosr - yinc* sinr; + if (dt==0.0) dt = 1.0; + dt = degrad (dt); + dx = 2.0 * cos(dy) * sin(dt/2.0); + if (dx==0.0) dx = 1.0; + geo1 = dt * sqrt((1.0+cos(dy)*cos(dt/2.0))/2.0) / dx; + geo3 = geo2 * sin(dy) / sqrt((1.0+cos(dy))/2.0); + rat = ra0; + dect = dec0; + if ((l==0.0) && (m==0.0)) break; + dz = 4.0 - l*l/(4.0*geo1*geo1) - ((m+geo3)/geo2)*((m+geo3)/geo2) ; + if ((dz>4.0) || (dz<2.0)) return 1;; + dz = 0.5 * sqrt (dz); + dd = (m+geo3) * dz / geo2; + if (fabs(dd)>1.0) return 1;; + dd = asin (dd); + if (fabs(cos(dd))1.0) return 1;; + da = asin (da); + rat = ra0 + 2.0 * da; + dect = dd; + break; + + case WCS_STG: /* -STG Sterographic*/ + dz = (4.0 - sins) / (4.0 + sins); + if (fabs(dz)>1.0) return 1; + dect = dz * sin0 + m * cos0 * (1.0+dz) / 2.0; + if (fabs(dect)>1.0) return 1; + dect = asin (dect); + rat = cos(dect); + if (fabs(rat)1.0) return 1; + rat = asin (rat); + mg = 1.0 + sin(dect) * sin0 + cos(dect) * cos0 * cos(rat); + if (fabs(mg)deps) rat = twopi/2.0 - rat; + rat = ra0 + rat; + break; + + case WCS_COE: /* COE projection code from Andreas Wicenic, ESO */ + td = tan (dec0); + y0 = 1.0 / td; + mt = y0 - m; + if (dec0 < 0.) + a = atan2 (l,-mt); + else + a = atan2 (l, mt); + rat = ra0 - (a / sin0); + r2 = (l * l) + (mt * mt); + dect = asin (1.0 / (sin0 * 2.0) * (1.0 + sin0*sin0 * (1.0 - r2))); + break; + } + + /* Return RA in range */ + raout = rat; + decout = dect; + if (raout-ra0>twopi/2.0) raout = raout - twopi; + if (raout-ra0<-twopi/2.0) raout = raout + twopi; + if (raout < 0.0) raout += twopi; /* added by DCW 10/12/94 */ + + /* Convert units back to degrees */ + *xpos = raddeg (raout); + *ypos = raddeg (decout); + + return 0; +} /* End of worldpos */ + + +int +worldpix (xpos, ypos, wcs, xpix, ypix) + +/*-----------------------------------------------------------------------*/ +/* routine to determine accurate pixel coordinates for an RA and Dec */ +/* returns 0 if successful otherwise: */ +/* 1 = angle too large for projection; */ +/* 2 = bad values */ +/* does: SIN, TAN, ARC, NCP, GLS or SFL, MER, AIT, STG, CAR, COE projections */ +/* anything else is linear */ + +/* Input: */ +double xpos; /* x (RA) coordinate (deg) */ +double ypos; /* y (dec) coordinate (deg) */ +struct WorldCoor *wcs; /* WCS parameter structure */ + +/* Output: */ +double *xpix; /* x pixel number (RA or long without rotation) */ +double *ypix; /* y pixel number (dec or lat without rotation) */ +{ + double dx, dy, ra0, dec0, ra, dec, coss, sins, dt, da, dd, sint; + double l, m, geo1, geo2, geo3, sinr, cosr, tx, x, a2, a3, a4; + double rthea,gamby2,a,b,c,phi,an,rap,v,tthea,co1,co2,co3,co4,ansq; /* COE */ + double cond2r=1.745329252e-2, deps=1.0e-5, twopi=6.28318530717959; + +/* Structure elements */ + double xref; /* x reference coordinate value (deg) */ + double yref; /* y reference coordinate value (deg) */ + double xrefpix; /* x reference pixel */ + double yrefpix; /* y reference pixel */ + double xinc; /* x coordinate increment (deg) */ + double yinc; /* y coordinate increment (deg) */ + double rot; /* Optical axis rotation (deg) (from N through E) */ + int itype; + + /* Set local projection parameters */ + xref = wcs->xref; + yref = wcs->yref; + xrefpix = wcs->xrefpix; + yrefpix = wcs->yrefpix; + xinc = wcs->xinc; + yinc = wcs->yinc; + rot = degrad (wcs->rot); + cosr = cos (rot); + sinr = sin (rot); + + /* Projection type */ + itype = wcs->prjcode; + + /* Nonlinear position */ + if (itype > 0) { + if (wcs->coorflip) { + dec0 = degrad (xref); + ra0 = degrad (yref); + dt = xpos - yref; + } + else { + ra0 = degrad (xref); + dec0 = degrad (yref); + dt = xpos - xref; + } + + /* 0h wrap-around tests added by D.Wells 10/12/1994: */ + /* Modified to exclude weird reference pixels by D.Mink 2/3/2004 */ + if (xrefpix*xinc > 180.0 || xrefpix*xinc < -180.0) { + if (dt > 360.0) xpos -= 360.0; + if (dt < 0.0) xpos += 360.0; + } + else { + if (dt > 180.0) xpos -= 360.0; + if (dt < -180.0) xpos += 360.0; + } + /* NOTE: changing input argument xpos is OK (call-by-value in C!) */ + + ra = degrad (xpos); + dec = degrad (ypos); + + /* Compute direction cosine */ + coss = cos (dec); + sins = sin (dec); + l = sin(ra-ra0) * coss; + sint = sins * sin(dec0) + coss * cos(dec0) * cos(ra-ra0); + } + else { + l = 0.0; + sint = 0.0; + sins = 0.0; + coss = 0.0; + ra = 0.0; + dec = 0.0; + ra0 = 0.0; + dec0 = 0.0; + m = 0.0; + } + + /* Process by case */ + switch (itype) { + + case WCS_CAR: /* -CAR Cartesian */ + l = ra - ra0; + m = dec - dec0; + break; + + case WCS_SIN: /* -SIN sin*/ + if (sint<0.0) return 1; + m = sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0); + break; + + case WCS_TNX: /* -TNX tan with polynomial correction */ + case WCS_TPV: /* -TPV tan with polynomial correction */ + case WCS_ZPX: /* -ZPX zpn with polynomial correction */ + case WCS_TAN: /* -TAN tan */ + if (sint<=0.0) return 1; + m = sins * sin(dec0) + coss * cos(dec0) * cos(ra-ra0); + l = l / m; + m = (sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0)) / m; + break; + + case WCS_ARC: /* -ARC Arc*/ + m = sins * sin(dec0) + coss * cos(dec0) * cos(ra-ra0); + if (m<-1.0) m = -1.0; + if (m>1.0) m = 1.0; + m = acos (m); + if (m!=0) + m = m / sin(m); + else + m = 1.0; + l = l * m; + m = (sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0)) * m; + break; + + case WCS_NCP: /* -NCP North celestial pole*/ + if (dec0==0.0) + return 1; /* can't stand the equator */ + else + m = (cos(dec0) - coss * cos(ra-ra0)) / sin(dec0); + break; + + case WCS_GLS: /* -GLS global sinusoid */ + case WCS_SFL: /* -SFL Samson-Flamsteed */ + dt = ra - ra0; + if (fabs(dec)>twopi/4.0) return 1; + if (fabs(dec0)>twopi/4.0) return 1; + m = dec - dec0; + l = dt * coss; + break; + + case WCS_MER: /* -MER mercator*/ + dt = yinc * cosr + xinc * sinr; + if (dt==0.0) dt = 1.0; + dy = degrad (yref/2.0 + 45.0); + dx = dy + dt / 2.0 * cond2r; + dy = log (tan (dy)); + dx = log (tan (dx)); + geo2 = degrad (dt) / (dx - dy); + geo3 = geo2 * dy; + geo1 = cos (degrad (yref)); + if (geo1<=0.0) geo1 = 1.0; + dt = ra - ra0; + l = geo1 * dt; + dt = dec / 2.0 + twopi / 8.0; + dt = tan (dt); + if (dttwopi/4.0) return 1; + dt = yinc*cosr + xinc*sinr; + if (dt==0.0) dt = 1.0; + dt = degrad (dt); + dy = degrad (yref); + dx = sin(dy+dt)/sqrt((1.0+cos(dy+dt))/2.0) - + sin(dy)/sqrt((1.0+cos(dy))/2.0); + if (dx==0.0) dx = 1.0; + geo2 = dt / dx; + dt = xinc*cosr - yinc* sinr; + if (dt==0.0) dt = 1.0; + dt = degrad (dt); + dx = 2.0 * cos(dy) * sin(dt/2.0); + if (dx==0.0) dx = 1.0; + geo1 = dt * sqrt((1.0+cos(dy)*cos(dt/2.0))/2.0) / dx; + geo3 = geo2 * sin(dy) / sqrt((1.0+cos(dy))/2.0); + dt = sqrt ((1.0 + cos(dec) * cos(da))/2.0); + if (fabs(dt)twopi/4.0) return 1; + dd = 1.0 + sins * sin(dec0) + coss * cos(dec0) * cos(da); + if (fabs(dd)rotmat) + l = rap * an * (1.0 - ansq/6.0) * (wcs->cd[0] / fabs(wcs->cd[0])); + else + l = rap * an * (1.0 - ansq/6.0) * (xinc / fabs(xinc)); + m = rthea - (rap * (1.0 - ansq/2.0)); + break; + + } /* end of itype switch */ + + /* Convert back to degrees */ + if (itype > 0) { + dx = raddeg (l); + dy = raddeg (m); + } + + /* For linear or pixel projection */ + else { + dx = xpos - xref; + dy = ypos - yref; + } + + if (wcs->coorflip) { + tx = dx; + dx = dy; + dy = tx; + } + + /* Scale and rotate using CD matrix */ + if (wcs->rotmat) { + tx = dx * wcs->dc[0] + dy * wcs->dc[1]; + dy = dx * wcs->dc[2] + dy * wcs->dc[3]; + dx = tx; + } + + /* Scale and rotate using CDELTn and CROTA2 */ + else { + + /* Correct for rotation */ + if (rot!=0.0) { + tx = dx*cosr + dy*sinr; + dy = dy*cosr - dx*sinr; + dx = tx; + } + + /* Scale using CDELT */ + if (xinc != 0.) + dx = dx / xinc; + if (yinc != 0.) + dy = dy / yinc; + } + + /* Convert to pixels */ + *xpix = dx + xrefpix; + if (itype == WCS_CAR) { + if (*xpix > wcs->nxpix) { + x = *xpix - (360.0 / xinc); + if (x > 0.0) *xpix = x; + } + else if (*xpix < 0) { + x = *xpix + (360.0 / xinc); + if (x <= wcs->nxpix) *xpix = x; + } + } + *ypix = dy + yrefpix; + + return 0; +} /* end worldpix */ + + +/* Oct 26 1995 Fix bug which interchanged RA and Dec twice when coorflip + * + * Oct 31 1996 Fix CD matrix use in WORLDPIX + * Nov 4 1996 Eliminate extra code for linear projection in WORLDPIX + * Nov 5 1996 Add coordinate flip in WORLDPIX + * + * May 22 1997 Avoid angle wraparound when CTYPE is pixel + * Jun 4 1997 Return without angle conversion from worldpos if type is PIXEL + * + * Oct 20 1997 Add chip rotation; compute rotation angle trig functions + * Jan 23 1998 Change PCODE to PRJCODE + * Jan 26 1998 Remove chip rotation code + * Feb 5 1998 Make cd[] and dc[] vectors; use xinc, yinc, rot from init + * Feb 23 1998 Add NOAO TNX projection as TAN + * Apr 28 1998 Change projection flags to WCS_* + * May 27 1998 Skip limit checking for linear projection + * Jun 25 1998 Fix inverse for CAR projection + * Aug 5 1998 Allan Brighton: Added COE projection (code from A. Wicenec, ESO) + * Sep 30 1998 Fix bug in COE inverse code to get sign correct + * + * Oct 21 1999 Drop unused y from worldpix() + * + * Apr 3 2002 Use GLS and SFL interchangeably + * + * Feb 3 2004 Let ra be >180 in worldpix() if ref pixel is >180 deg away + * + * Jun 20 2006 Initialize uninitialized variables + * + * Mar 11 2011 Initialize ZPX + * Sep 1 2011 Add TPV projection as TAN + */ diff --git a/astroem/wrappers.c b/astroem/wrappers.c new file mode 100644 index 00000000..7b0f0cf1 --- /dev/null +++ b/astroem/wrappers.c @@ -0,0 +1,397 @@ +/* + * wcswrapper.c -- enscripten wrapper functions + * + * Eric Mandel 10/11/2013 (during the Great Government Shutdown) + * + * The main reasons for writing this module are: + * 1. I couldn't figure out how to call subroutines and fill in indirect args + * 2. I didn't seem to be able to return the wcs struct to javascript + * 3. I didn't see much help in the scant documentation + * 4. I got tired of banging my head against the wall regarding #1, #2, #3 + * + */ + +#include +#include +#include +#include +#include +#include "wcs.h" +#include "strtod.h" +#include "cdl.h" + +#define PI 3.141592653589793238462643 +#define DEG2RAD(a) ((PI/180.0)*a) +#define RAD2DEG(a) ((180.0/PI)*a) + +#define WCS_SEXAGESIMAL 0 +#define WCS_DEGREES 1 + +#define NDEC 3 + +#define SZ_LINE 4096 + +/* static return buffer */ +char rstr[SZ_LINE]; + +/* hold information about wcs for individual images */ +typedef struct infostruct { + struct WorldCoor *wcs; + int wcsunits; + char str[SZ_LINE]; +} *Info, InfoRec; + +/* management of info records */ +static Info infos=NULL; +static int ninfo = 1; +static int maxinfo = 0; +static int maxinc = 10; + +/* + * + * private routines + * + */ + +/* upper to lower case */ +static void culc(char *s) +{ + while(*s){ + if( isupper((int)*s) ) + *s = tolower(*s); + s++; + } +} + +/* lower to upper case */ +static void cluc(char *s) +{ + while(*s){ + if( islower((int)*s) ) + *s = toupper(*s); + s++; + } +} + +int nowhite (char *c, char *cr) +{ + char *cr0; /* initial value of cr */ + int n; /* the number of characters */ + + /* skip leading white space */ + while(*c && isspace((int)*c)) + c++; + /* copy up to the null */ + cr0 = cr; + while(*c) + *cr++ = *c++; + n = cr - cr0; /* the number of characters */ + *cr-- = '\0'; /* Null and point to the last character */ + /* remove trailing white space */ + while( n && isspace((int)*cr) ){ + *cr-- = '\0'; + n--; + } + return(n); +} + +/* add a new Info record with a valid wcs struct */ +static int newinfo(struct WorldCoor *wcs){ + int n; + if( maxinfo == 0 ){ + maxinfo = maxinc; + infos = malloc(maxinfo * sizeof(InfoRec)); + if( !infos ){ + return -4; + } + } + while( ninfo >= maxinfo ){ + maxinfo += maxinc; + infos = realloc(infos, maxinfo * sizeof(InfoRec)); + if( !infos ){ + return -3; + } + } + if( wcs ){ + n = ninfo; + infos[ninfo].wcs = wcs; + infos[ninfo].wcsunits = WCS_SEXAGESIMAL; + *infos[ninfo].str = '\0'; + ninfo++; + } else { + n = -1; + } + return n; +} + +/* return Info record for this id */ +static Info getinfo(int n){ + if( (n < 1) || (n >= maxinfo) ){ + return NULL; + } else { + return &infos[n]; + } +} + +/* + * + * public routines: these are exported to javascript + * + */ + +/* init the wcs struct and create a new info record */ +int initwcs(char *s, int n){ + struct WorldCoor *wcs; + if( n > 0 ){ + wcs = wcsninit(s, n); + } else { + wcs = wcsinit(s); + } + if( wcs ){ + wcsoutinit(wcs, getradecsys(wcs)); + } + return newinfo(wcs); +} + +/* convert pixels to wcs and return string */ +char *pix2wcsstr(int n, double xpix, double ypix){ + Info info = getinfo(n); + char *str = NULL; + if( info->wcs ){ + str = info->str; + *str = '\0'; + // convert from 1-indexed image coords + pix2wcst(info->wcs, xpix-1, ypix-1, str, SZ_LINE); + } + return str; +} + +/* convert pixels to wcs and return string */ +char *wcs2pixstr(int n, double ra, double dec){ + Info info = getinfo(n); + char str[SZ_LINE]; + double xpix, ypix; + int offscale; + if( info->wcs ){ + wcs2pix(info->wcs, ra, dec, &xpix, &ypix, &offscale); + // convert to 1-indexed image coords + snprintf(str, SZ_LINE-1, "%.3f %.3f", xpix+1, ypix+1); + nowhite(str, info->str); + return info->str; + } else { + return NULL; + } +} + +/* set or get wcssys (FK4, FK5, etc) */ +char *wcssys(int n, char *s){ + Info info = getinfo(n); + char *str = NULL; + if( info->wcs ){ + str = info->str; + *str = '\0'; + if( s && *s && + (!strcasecmp(s, "galactic") || !strcasecmp(s, "ecliptic") || + !strcasecmp(s, "linear") || (wcsceq(s) > 0.0)) ){ + /* try to set the wcs output system */ + wcsoutinit(info->wcs, s); + } + /* always return current */ + strncpy(str, getwcsout(info->wcs), SZ_LINE); + if( !strcasecmp(str, "galactic") ){ + strcpy(str, "galactic"); + } else if( !strcasecmp(str, "ecliptic") ){ + strcpy(str, "ecliptic"); + } else { + cluc(str); + } + } + return str; +} + +/* set or get wcs units (degrees or sexigesimal) */ +char *wcsunits(int n, char *s){ + Info info = getinfo(n); + char *str = NULL; + if( info->wcs ){ + str = info->str; + *str = '\0'; + if( s && *s ){ + if( !strcasecmp(s, "degrees") ){ + setwcsdeg(info->wcs, WCS_DEGREES); + info->wcsunits = WCS_DEGREES; + } else { + setwcsdeg(info->wcs, WCS_SEXAGESIMAL); + info->wcsunits = WCS_SEXAGESIMAL; + } + } + switch(info->wcsunits){ + case WCS_DEGREES: + strncpy(str, "degrees", SZ_LINE-1); + break; + case WCS_SEXAGESIMAL: + strncpy(str, "sexagesimal", SZ_LINE-1); + break; + } + culc(str); + } + return str; +} + +/* convert image values to wcs values in a region (see fitshelper.c) */ +char *reg2wcsstr(int n, char *regstr){ + Info info = getinfo(n); + char tbuf[SZ_LINE]; + char rbuf1[SZ_LINE]; + char rbuf2[SZ_LINE]; + char *str = NULL; + char *s=NULL, *t=NULL;; + char *s1=NULL, *s2=NULL; + char *targs=NULL, *targ=NULL; + char *mywcssys=NULL; + int alwaysdeg = 0; + double dval1, dval2, dval3, dval4; + double rval1, rval2, rval3, rval4; + double sep; + + if( info->wcs ){ + mywcssys = wcssys(n, NULL); + if( !strcmp(mywcssys, "galactic") || + !strcmp(mywcssys, "ecliptic") || + !strcmp(mywcssys, "linear") ){ + alwaysdeg = 1; + } + str = info->str; + *str = '\0'; + /* start with original input string */ + targs = (char *)strdup(regstr); + for(targ=(char *)strtok(targs, ";"); targ != NULL; + targ=(char *)strtok(NULL,";")){ + s = targ; + /* look for region type */ + t = strchr(s, ' '); + if( t ){ + s1 = t + 1; + *t = '\0'; + } else { + s = NULL; + s1 = ""; + } + /* these are the coords of the region */ + if( (dval1=strtod(s1, &s2)) && (dval2=strtod(s2, &s1)) ){ + /* convert image x,y to ra,dec */ + pix2wcs(info->wcs, dval1, dval2, &rval1, &rval2); + if( s ){ + snprintf(tbuf, SZ_LINE, "%s(", s); + strncat(str, tbuf, SZ_LINE-1); + } + /* convert to proper units */ + switch(info->wcsunits){ + case WCS_DEGREES: + snprintf(tbuf, SZ_LINE, "%.6f, %.6f", rval1, rval2); + strncat(str, tbuf, SZ_LINE-1); + break; + case WCS_SEXAGESIMAL: + if( alwaysdeg ){ + dec2str(rbuf1, SZ_LINE-1, rval1, NDEC); + } else { + ra2str(rbuf1, SZ_LINE-1, rval1, NDEC); + } + dec2str(rbuf2, SZ_LINE-1, rval2, NDEC); + snprintf(tbuf, SZ_LINE, "%s, %s", rbuf1, rbuf2); + strncat(str, tbuf, SZ_LINE-1); + break; + default: + snprintf(tbuf, SZ_LINE, "%.6f, %.6f", rval1, rval2); + strncat(str, tbuf, SZ_LINE-1); + break; + } + /* convert more positions */ + if( !strcmp(s, "polygon") ){ + /* convert successive image values to RA, Dec */ + while( (dval1=strtod(s1, &s2)) && (dval2=strtod(s2, &s1)) ){ + /* convert image x,y to ra,dec */ + pix2wcs(info->wcs, dval1, dval2, &rval1, &rval2); + /* convert to proper units */ + switch(info->wcsunits){ + case WCS_DEGREES: + snprintf(tbuf, SZ_LINE, ", %.6f, %.6f", rval1, rval2); + strncat(str, tbuf, SZ_LINE-1); + break; + case WCS_SEXAGESIMAL: + if( alwaysdeg ){ + dec2str(rbuf1, SZ_LINE-1, rval1, NDEC); + } else { + ra2str(rbuf1, SZ_LINE-1, rval1, NDEC); + } + dec2str(rbuf2, SZ_LINE-1, rval2, NDEC); + snprintf(tbuf, SZ_LINE, ", %s, %s", rbuf1, rbuf2); + strncat(str, tbuf, SZ_LINE-1); + break; + default: + snprintf(tbuf, SZ_LINE, ", %.6f, %.6f", rval1, rval2); + strncat(str, tbuf, SZ_LINE-1); + break; + } + } + } else { + /* use successive x1,y1,x2,y2 to calculate separation (arcsecs) */ + while( (dval1=strtod(s1, &s2)) && (dval2=strtod(s2, &s1)) && + (dval3=strtod(s1, &s2)) && (dval4=strtod(s2, &s1)) ){ + /* convert image x,y to ra,dec */ + pix2wcs(info->wcs, dval1, dval2, &rval1, &rval2); + /* convert image x,y to ra,dec */ + pix2wcs(info->wcs, dval3, dval4, &rval3, &rval4); + /* calculate and output separation between the two points */ + sep = wcsdist(rval1, rval2, rval3, rval4)*3600.0; + if( sep <= 60 ){ + snprintf(tbuf, SZ_LINE, ", %.2f\"", sep); + strncat(str, tbuf, SZ_LINE-1); + } else if( sep <= 3600 ){ + snprintf(tbuf, SZ_LINE, ", %.6f'", sep/60.0); + strncat(str, tbuf, SZ_LINE-1); + } else { + snprintf(tbuf, SZ_LINE, ", %.6fd", sep/3600.0); + strncat(str, tbuf, SZ_LINE-1); + } + } + } + /* output angle, as needed */ + if( !strcmp(s, "box") || !strcmp(s, "ellipse") ){ + while( dval1 < 0 ) dval1 += (2.0 * PI); + snprintf(tbuf, SZ_LINE, ", %.3f", RAD2DEG(dval1)); + strncat(str, tbuf, SZ_LINE-1); + } + /* close region */ + if( s ){ + snprintf(tbuf, SZ_LINE, ")"); + strncat(str, tbuf, SZ_LINE-1); + } + snprintf(tbuf, SZ_LINE, ";"); + strncat(str, tbuf, SZ_LINE-1); + } + } + } + if( targs ) free(targs); + return str; +} + +/* convert string to float (includes sexagesimal strings) */ +double saostrtod(char *s){ + return SAOstrtod(s, NULL); +} + +/* required by cdlzscale.c */ +int cdl_debug=0; + +/* calculate zscale parameters */ +char *zscale(unsigned char *im, int nx, int ny, int bitpix, + float contrast, int numsamples, int perline){ + float z1, z2; + char tbuf[SZ_LINE]; + cdl_zscale(im, nx, ny, bitpix, &z1, &z2, contrast, numsamples, perline); + /* encode in a string for easy return */ + snprintf(tbuf, SZ_LINE-1, "%f %f", z1, z2); + nowhite(tbuf, rstr);; + return rstr; +} diff --git a/astroem/zee.js/Makefile.in b/astroem/zee.js/Makefile.in new file mode 100644 index 00000000..5b15bd00 --- /dev/null +++ b/astroem/zee.js/Makefile.in @@ -0,0 +1,257 @@ +# Makefile for zlib +# Copyright (C) 1995-2010 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile and test, type: +# ./configure; make test +# Normally configure builds both a static and a shared library. +# If you want to build just a static library, use: ./configure --static + +# To use the asm code, type: +# cp contrib/asm?86/match.S ./match.S +# make LOC=-DASMV OBJA=match.o + +# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: +# make install +# To install in $HOME instead of /usr/local, use: +# make install prefix=$HOME + +CC=cc + +CFLAGS=-O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DDEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +SFLAGS=-O +LDFLAGS= +TEST_LDFLAGS=-L. libz.a +LDSHARED=$(CC) +CPP=$(CC) -E + +STATICLIB=libz.a +SHAREDLIB=libz.so +SHAREDLIBV=libz.so.1.2.5 +SHAREDLIBM=libz.so.1 +LIBS=$(STATICLIB) $(SHAREDLIBV) + +AR=ar rc +RANLIB=ranlib +LDCONFIG=ldconfig +LDSHAREDLIBC=-lc +TAR=tar +SHELL=/bin/sh +EXE= + +prefix = /usr/local +exec_prefix = ${prefix} +libdir = ${exec_prefix}/lib +sharedlibdir = ${libdir} +includedir = ${prefix}/include +mandir = ${prefix}/share/man +man3dir = ${mandir}/man3 +pkgconfigdir = ${libdir}/pkgconfig + +OBJC = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \ + gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o + +PIC_OBJC = adler32.lo compress.lo crc32.lo deflate.lo gzclose.lo gzlib.lo gzread.lo \ + gzwrite.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo uncompr.lo zutil.lo + +# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo +OBJA = +PIC_OBJA = + +OBJS = $(OBJC) $(OBJA) + +PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA) + +all: static shared + +static: example$(EXE) minigzip$(EXE) + +shared: examplesh$(EXE) minigzipsh$(EXE) + +all64: example64$(EXE) minigzip64$(EXE) + +check: test + +test: all teststatic testshared + +teststatic: static + @if echo hello world | ./minigzip | ./minigzip -d && ./example; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; false; \ + fi + -@rm -f foo.gz + +testshared: shared + @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ + DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ + SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ + if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh; then \ + echo ' *** zlib shared test OK ***'; \ + else \ + echo ' *** zlib shared test FAILED ***'; false; \ + fi + -@rm -f foo.gz + +test64: all64 + @if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64; then \ + echo ' *** zlib 64-bit test OK ***'; \ + else \ + echo ' *** zlib 64-bit test FAILED ***'; false; \ + fi + -@rm -f foo.gz + +libz.a: $(OBJS) + $(AR) $@ $(OBJS) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +match.o: match.S + $(CPP) match.S > _match.s + $(CC) -c _match.s + mv _match.o match.o + rm -f _match.s + +match.lo: match.S + $(CPP) match.S > _match.s + $(CC) -c -fPIC _match.s + mv _match.o match.lo + rm -f _match.s + +example64.o: example.c zlib.h zconf.h + $(CC) $(CFLAGS) -D_FILE_OFFSET_BITS=64 -c -o $@ example.c + +minigzip64.o: minigzip.c zlib.h zconf.h + $(CC) $(CFLAGS) -D_FILE_OFFSET_BITS=64 -c -o $@ minigzip.c + +.SUFFIXES: .lo + +.c.lo: + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) -DPIC -c -o objs/$*.o $< + -@mv objs/$*.o $@ + +$(SHAREDLIBV): $(PIC_OBJS) + $(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS) + rm -f $(SHAREDLIB) $(SHAREDLIBM) + ln -s $@ $(SHAREDLIB) + ln -s $@ $(SHAREDLIBM) + -@rmdir objs + +example$(EXE): example.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS) + +minigzip$(EXE): minigzip.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS) + +examplesh$(EXE): example.o $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV) + +minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV) + +example64$(EXE): example64.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS) + +minigzip64$(EXE): minigzip64.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS) + +install-libs: $(LIBS) + -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi + -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi + -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi + -@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi + -@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi + cp $(STATICLIB) $(DESTDIR)$(libdir) + cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir) + cd $(DESTDIR)$(libdir); chmod u=rw,go=r $(STATICLIB) + -@(cd $(DESTDIR)$(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1 + -@cd $(DESTDIR)$(sharedlibdir); if test "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \ + chmod 755 $(SHAREDLIBV); \ + rm -f $(SHAREDLIB) $(SHAREDLIBM); \ + ln -s $(SHAREDLIBV) $(SHAREDLIB); \ + ln -s $(SHAREDLIBV) $(SHAREDLIBM); \ + ($(LDCONFIG) || true) >/dev/null 2>&1; \ + fi + cp zlib.3 $(DESTDIR)$(man3dir) + chmod 644 $(DESTDIR)$(man3dir)/zlib.3 + cp zlib.pc $(DESTDIR)$(pkgconfigdir) + chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc +# The ranlib in install is needed on NeXTSTEP which checks file times +# ldconfig is for Linux + +install: install-libs + -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi + cp zlib.h zconf.h $(DESTDIR)$(includedir) + chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h + +uninstall: + cd $(DESTDIR)$(includedir); rm -f zlib.h zconf.h + cd $(DESTDIR)$(libdir); rm -f libz.a; \ + if test "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \ + rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \ + fi + cd $(DESTDIR)$(man3dir); rm -f zlib.3 + cd $(DESTDIR)$(pkgconfigdir); rm -f zlib.pc + +docs: zlib.3.pdf + +zlib.3.pdf: zlib.3 + groff -mandoc -f H -T ps zlib.3 | ps2pdf - zlib.3.pdf + +zconf.h.in: zconf.h.cmakein + sed "/^#cmakedefine/D" < zconf.h.cmakein > zconf.h.in + touch -r zconf.h.cmakein zconf.h.in + +zconf: zconf.h.in + cp -p zconf.h.in zconf.h + +mostlyclean: clean +clean: + rm -f *.o *.lo *~ \ + example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ + example64$(EXE) minigzip64$(EXE) \ + libz.* foo.gz so_locations \ + _match.s maketree contrib/infback9/*.o + rm -rf objs + +maintainer-clean: distclean +distclean: clean zconf docs + rm -f Makefile zlib.pc + -@rm -f .DS_Store + -@printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile + -@printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile + -@touch -r Makefile.in Makefile + +tags: + etags *.[ch] + +depend: + makedepend -- $(CFLAGS) -- *.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o zutil.o: zutil.h zlib.h zconf.h +gzclose.o gzlib.o gzread.o gzwrite.o: zlib.h zconf.h gzguts.h +compress.o example.o minigzip.o uncompr.o: zlib.h zconf.h +crc32.o: zutil.h zlib.h zconf.h crc32.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +infback.o inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inffixed.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h + +adler32.lo zutil.lo: zutil.h zlib.h zconf.h +gzclose.lo gzlib.lo gzread.lo gzwrite.lo: zlib.h zconf.h gzguts.h +compress.lo example.lo minigzip.lo uncompr.lo: zlib.h zconf.h +crc32.lo: zutil.h zlib.h zconf.h crc32.h +deflate.lo: deflate.h zutil.h zlib.h zconf.h +infback.lo inflate.lo: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inffixed.h +inffast.lo: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +inftrees.lo: zutil.h zlib.h zconf.h inftrees.h +trees.lo: deflate.h zutil.h zlib.h zconf.h trees.h diff --git a/astroem/zee.js/README.markdown b/astroem/zee.js/README.markdown new file mode 100644 index 00000000..7c51ac19 --- /dev/null +++ b/astroem/zee.js/README.markdown @@ -0,0 +1,18 @@ + +zee.js +====== + +zee.js is a port of zlib, a very useful compression library (used in gzip) +to JavaScript, by compiling the zlib C code with Emscripten. + +zee.js is zlib licensed, just like zlib. + + +Usage +----- + +Zee.compress and Zee.decompress are the relevant functions. See test.js +for an example. + +There is also a worker version, zee-worker.js. See zee-client.js for +usage. diff --git a/astroem/zee.js/README.zlib b/astroem/zee.js/README.zlib new file mode 100644 index 00000000..d4219bf8 --- /dev/null +++ b/astroem/zee.js/README.zlib @@ -0,0 +1,115 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.5 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile.in. In short "./configure; make test", and if that goes +well, "make install" should work for most flavors of Unix. For Windows, use one +of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use +make_vms.com. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://zlib.net/ . Before reporting a problem, please check this site to +verify that you have the latest version of zlib; otherwise get the latest +version and check whether the problem still exists or not. + +PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available at +http://marknelson.us/1997/01/01/zlib-engine/ . + +The changes made in version 1.2.5 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory contrib/ . + +zlib is available in Java using the java.util.zip package, documented at +http://java.sun.com/developer/technicalArticles/Programming/compression/ . + +A Perl interface to zlib written by Paul Marquess is available +at CPAN (Comprehensive Perl Archive Network) sites, including +http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html . + +zlib is built into tcl: http://wiki.tcl.tk/4610 . + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS or BEOS. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate and + zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; they + are too numerous to cite here. + +Copyright notice: + + (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. diff --git a/astroem/zee.js/adler32.c b/astroem/zee.js/adler32.c new file mode 100644 index 00000000..65ad6a5a --- /dev/null +++ b/astroem/zee.js/adler32.c @@ -0,0 +1,169 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2007 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#define local static + +local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/astroem/zee.js/compress.c b/astroem/zee.js/compress.c new file mode 100644 index 00000000..26cf3ddc --- /dev/null +++ b/astroem/zee.js/compress.c @@ -0,0 +1,80 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + XXX remove attributes */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; +} diff --git a/astroem/zee.js/configure b/astroem/zee.js/configure new file mode 100755 index 00000000..bd9edd26 --- /dev/null +++ b/astroem/zee.js/configure @@ -0,0 +1,596 @@ +#!/bin/sh +# configure script for zlib. +# +# Normally configure builds both a static and a shared library. +# If you want to build just a static library, use: ./configure --static +# +# To impose specific compiler or flags or install directory, use for example: +# prefix=$HOME CC=cc CFLAGS="-O4" ./configure +# or for csh/tcsh users: +# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) + +# Incorrect settings of CC or CFLAGS may prevent creating a shared library. +# If you have problems, try without defining CC and CFLAGS before reporting +# an error. + +if [ -n "${CHOST}" ]; then + uname="$(echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/')" + CROSS_PREFIX="${CHOST}-" +fi + +STATICLIB=libz.a +LDFLAGS="${LDFLAGS} -L. ${STATICLIB}" +VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h` +VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < zlib.h` +VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h` +VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < zlib.h` +if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then + AR=${AR-"${CROSS_PREFIX}ar"} + test -n "${CROSS_PREFIX}" && echo Using ${AR} +else + AR=${AR-"ar"} + test -n "${CROSS_PREFIX}" && echo Using ${AR} +fi +AR_RC="${AR} rc" +if "${CROSS_PREFIX}ranlib" --version >/dev/null 2>/dev/null || test $? -lt 126; then + RANLIB=${RANLIB-"${CROSS_PREFIX}ranlib"} + test -n "${CROSS_PREFIX}" && echo Using ${RANLIB} +else + RANLIB=${RANLIB-"ranlib"} +fi +if "${CROSS_PREFIX}nm" --version >/dev/null 2>/dev/null || test $? -lt 126; then + NM=${NM-"${CROSS_PREFIX}nm"} + test -n "${CROSS_PREFIX}" && echo Using ${NM} +else + NM=${NM-"nm"} +fi +LDCONFIG=${LDCONFIG-"ldconfig"} +LDSHAREDLIBC="${LDSHAREDLIBC--lc}" +prefix=${prefix-/usr/local} +exec_prefix=${exec_prefix-'${prefix}'} +libdir=${libdir-'${exec_prefix}/lib'} +sharedlibdir=${sharedlibdir-'${libdir}'} +includedir=${includedir-'${prefix}/include'} +mandir=${mandir-'${prefix}/share/man'} +shared_ext='.so' +shared=1 +zprefix=0 +build64=0 +gcc=0 +old_cc="$CC" +old_cflags="$CFLAGS" + +while test $# -ge 1 +do +case "$1" in + -h* | --help) + echo 'usage:' + echo ' configure [--zprefix] [--prefix=PREFIX] [--eprefix=EXPREFIX]' + echo ' [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' + echo ' [--includedir=INCLUDEDIR]' + exit 0 ;; + -p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;; + -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;; + -l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;; + --sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;; + -i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;; + -u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;; + -p* | --prefix) prefix="$2"; shift; shift ;; + -e* | --eprefix) exec_prefix="$2"; shift; shift ;; + -l* | --libdir) libdir="$2"; shift; shift ;; + -i* | --includedir) includedir="$2"; shift; shift ;; + -s* | --shared | --enable-shared) shared=1; shift ;; + -t | --static) shared=0; shift ;; + -z* | --zprefix) zprefix=1; shift ;; + -6* | --64) build64=1; shift ;; + --sysconfdir=*) echo "ignored option: --sysconfdir"; shift ;; + --localstatedir=*) echo "ignored option: --localstatedir"; shift ;; + *) echo "unknown option: $1"; echo "$0 --help for help"; exit 1 ;; + esac +done + +test=ztest$$ +cat > $test.c </dev/null; then + CC="$cc" + SFLAGS="${CFLAGS--O3} -fPIC" + CFLAGS="${CFLAGS--O3}" + if test $build64 -eq 1; then + CFLAGS="${CFLAGS} -m64" + SFLAGS="${SFLAGS} -m64" + fi + if test "${ZLIBGCCWARN}" = "YES"; then + CFLAGS="${CFLAGS} -Wall -Wextra -pedantic" + fi + if test -z "$uname"; then + uname=`(uname -s || echo unknown) 2>/dev/null` + fi + case "$uname" in + Linux* | linux* | GNU | GNU/* | *BSD | DragonFly) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map"} ;; + CYGWIN* | Cygwin* | cygwin* | OS/2*) + EXE='.exe' ;; + MINGW*|mingw*) +# temporary bypass + rm -f $test.[co] $test $test$shared_ext + echo "Please use win32/Makefile.gcc instead." + exit 1 + LDSHARED=${LDSHARED-"$cc -shared"} + LDSHAREDLIBC="" + EXE='.exe' ;; + QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 + # (alain.bonnefoy@icbt.com) + LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;; + HP-UX*) + LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} + case `(uname -m || echo unknown) 2>/dev/null` in + ia64) + shared_ext='.so' + SHAREDLIB='libz.so' ;; + *) + shared_ext='.sl' + SHAREDLIB='libz.sl' ;; + esac ;; + Darwin*) shared_ext='.dylib' + SHAREDLIB=libz$shared_ext + SHAREDLIBV=libz.$VER$shared_ext + SHAREDLIBM=libz.$VER1$shared_ext + LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} ;; + *) LDSHARED=${LDSHARED-"$cc -shared"} ;; + esac +else + # find system name and corresponding cc options + CC=${CC-cc} + gcc=0 + if test -z "$uname"; then + uname=`(uname -sr || echo unknown) 2>/dev/null` + fi + case "$uname" in + HP-UX*) SFLAGS=${CFLAGS-"-O +z"} + CFLAGS=${CFLAGS-"-O"} +# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"} + LDSHARED=${LDSHARED-"ld -b"} + case `(uname -m || echo unknown) 2>/dev/null` in + ia64) + shared_ext='.so' + SHAREDLIB='libz.so' ;; + *) + shared_ext='.sl' + SHAREDLIB='libz.sl' ;; + esac ;; + IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} + CFLAGS=${CFLAGS-"-ansi -O2"} + LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; + OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"} + CFLAGS=${CFLAGS-"-O -std1"} + LDFLAGS="${LDFLAGS} -Wl,-rpath,." + LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"} ;; + OSF1*) SFLAGS=${CFLAGS-"-O -std1"} + CFLAGS=${CFLAGS-"-O -std1"} + LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; + QNX*) SFLAGS=${CFLAGS-"-4 -O"} + CFLAGS=${CFLAGS-"-4 -O"} + LDSHARED=${LDSHARED-"cc"} + RANLIB=${RANLIB-"true"} + AR_RC="cc -A" ;; + SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "} + CFLAGS=${CFLAGS-"-O3"} + LDSHARED=${LDSHARED-"cc -dy -KPIC -G"} ;; + SunOS\ 5*) LDSHARED=${LDSHARED-"cc -G"} + case `(uname -m || echo unknown) 2>/dev/null` in + i86*) + SFLAGS=${CFLAGS-"-xpentium -fast -KPIC -R."} + CFLAGS=${CFLAGS-"-xpentium -fast"} ;; + *) + SFLAGS=${CFLAGS-"-fast -xcg92 -KPIC -R."} + CFLAGS=${CFLAGS-"-fast -xcg92"} ;; + esac ;; + SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} + CFLAGS=${CFLAGS-"-O2"} + LDSHARED=${LDSHARED-"ld"} ;; + SunStudio\ 9*) SFLAGS=${CFLAGS-"-fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"} + CFLAGS=${CFLAGS-"-fast -xtarget=ultra3 -xarch=v9b"} + LDSHARED=${LDSHARED-"cc -xarch=v9b"} ;; + UNIX_System_V\ 4.2.0) + SFLAGS=${CFLAGS-"-KPIC -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"} ;; + UNIX_SV\ 4.2MP) + SFLAGS=${CFLAGS-"-Kconform_pic -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"} ;; + OpenUNIX\ 5) + SFLAGS=${CFLAGS-"-KPIC -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"} ;; + AIX*) # Courtesy of dbakker@arrayasolutions.com + SFLAGS=${CFLAGS-"-O -qmaxmem=8192"} + CFLAGS=${CFLAGS-"-O -qmaxmem=8192"} + LDSHARED=${LDSHARED-"xlc -G"} ;; + # send working options for other systems to zlib@gzip.org + *) SFLAGS=${CFLAGS-"-O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -shared"} ;; + esac +fi + +SHAREDLIB=${SHAREDLIB-"libz$shared_ext"} +SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"} +SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"} + +if test $shared -eq 1; then + echo Checking for shared library support... + # we must test in two steps (cc then ld), required at least on SunOS 4.x + if test "`($CC -w -c $SFLAGS $test.c) 2>&1`" = "" && + test "`($LDSHARED $SFLAGS -o $test$shared_ext $test.o) 2>&1`" = ""; then + echo Building shared library $SHAREDLIBV with $CC. + elif test -z "$old_cc" -a -z "$old_cflags"; then + echo No shared library support. + shared=0; + else + echo Tested $CC -w -c $SFLAGS $test.c + $CC -w -c $SFLAGS $test.c + echo Tested $LDSHARED $SFLAGS -o $test$shared_ext $test.o + $LDSHARED $SFLAGS -o $test$shared_ext $test.o + echo 'No shared library support; try without defining CC and CFLAGS' + shared=0; + fi +fi +if test $shared -eq 0; then + LDSHARED="$CC" + ALL="static" + TEST="all teststatic" + SHAREDLIB="" + SHAREDLIBV="" + SHAREDLIBM="" + echo Building static library $STATICLIB version $VER with $CC. +else + ALL="static shared" + TEST="all teststatic testshared" +fi + +cat > $test.c < +off64_t dummy = 0; +EOF +if test "`($CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c) 2>&1`" = ""; then + CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1" + SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1" + ALL="${ALL} all64" + TEST="${TEST} test64" + echo "Checking for off64_t... Yes." + echo "Checking for fseeko... Yes." +else + echo "Checking for off64_t... No." + cat > $test.c < +int main(void) { + fseeko(NULL, 0, 0); + return 0; +} +EOF + if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then + echo "Checking for fseeko... Yes." + else + CFLAGS="${CFLAGS} -DNO_FSEEKO" + SFLAGS="${SFLAGS} -DNO_FSEEKO" + echo "Checking for fseeko... No." + fi +fi + +cp -p zconf.h.in zconf.h + +cat > $test.c < +int main() { return 0; } +EOF +if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + sed < zconf.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be/ 1\1 was/" > zconf.temp.h + mv zconf.temp.h zconf.h + echo "Checking for unistd.h... Yes." +else + echo "Checking for unistd.h... No." +fi + +if test $zprefix -eq 1; then + sed < zconf.h "/#ifdef Z_PREFIX.* may be/s/def Z_PREFIX\(.*\) may be/ 1\1 was/" > zconf.temp.h + mv zconf.temp.h zconf.h + echo "Using z_ prefix on all symbols." +fi + +cat > $test.c < +#include +#include "zconf.h" + +int main() +{ +#ifndef STDC + choke me +#endif + + return 0; +} +EOF + +if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()." + + cat > $test.c < +#include + +int mytest(const char *fmt, ...) +{ + char buf[20]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + return 0; +} + +int main() +{ + return (mytest("Hello%d\n", 1)); +} +EOF + + if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then + echo "Checking for vsnprintf() in stdio.h... Yes." + + cat >$test.c < +#include + +int mytest(const char *fmt, ...) +{ + int n; + char buf[20]; + va_list ap; + + va_start(ap, fmt); + n = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + return n; +} + +int main() +{ + return (mytest("Hello%d\n", 1)); +} +EOF + + if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + echo "Checking for return value of vsnprintf()... Yes." + else + CFLAGS="$CFLAGS -DHAS_vsnprintf_void" + SFLAGS="$SFLAGS -DHAS_vsnprintf_void" + echo "Checking for return value of vsnprintf()... No." + echo " WARNING: apparently vsnprintf() does not return a value. zlib" + echo " can build but will be open to possible string-format security" + echo " vulnerabilities." + fi + else + CFLAGS="$CFLAGS -DNO_vsnprintf" + SFLAGS="$SFLAGS -DNO_vsnprintf" + echo "Checking for vsnprintf() in stdio.h... No." + echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" + echo " can build but will be open to possible buffer-overflow security" + echo " vulnerabilities." + + cat >$test.c < +#include + +int mytest(const char *fmt, ...) +{ + int n; + char buf[20]; + va_list ap; + + va_start(ap, fmt); + n = vsprintf(buf, fmt, ap); + va_end(ap); + return n; +} + +int main() +{ + return (mytest("Hello%d\n", 1)); +} +EOF + + if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + echo "Checking for return value of vsprintf()... Yes." + else + CFLAGS="$CFLAGS -DHAS_vsprintf_void" + SFLAGS="$SFLAGS -DHAS_vsprintf_void" + echo "Checking for return value of vsprintf()... No." + echo " WARNING: apparently vsprintf() does not return a value. zlib" + echo " can build but will be open to possible string-format security" + echo " vulnerabilities." + fi + fi +else + echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()." + + cat >$test.c < + +int mytest() +{ + char buf[20]; + + snprintf(buf, sizeof(buf), "%s", "foo"); + return 0; +} + +int main() +{ + return (mytest()); +} +EOF + + if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then + echo "Checking for snprintf() in stdio.h... Yes." + + cat >$test.c < + +int mytest() +{ + char buf[20]; + + return snprintf(buf, sizeof(buf), "%s", "foo"); +} + +int main() +{ + return (mytest()); +} +EOF + + if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + echo "Checking for return value of snprintf()... Yes." + else + CFLAGS="$CFLAGS -DHAS_snprintf_void" + SFLAGS="$SFLAGS -DHAS_snprintf_void" + echo "Checking for return value of snprintf()... No." + echo " WARNING: apparently snprintf() does not return a value. zlib" + echo " can build but will be open to possible string-format security" + echo " vulnerabilities." + fi + else + CFLAGS="$CFLAGS -DNO_snprintf" + SFLAGS="$SFLAGS -DNO_snprintf" + echo "Checking for snprintf() in stdio.h... No." + echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" + echo " can build but will be open to possible buffer-overflow security" + echo " vulnerabilities." + + cat >$test.c < + +int mytest() +{ + char buf[20]; + + return sprintf(buf, "%s", "foo"); +} + +int main() +{ + return (mytest()); +} +EOF + + if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + echo "Checking for return value of sprintf()... Yes." + else + CFLAGS="$CFLAGS -DHAS_sprintf_void" + SFLAGS="$SFLAGS -DHAS_sprintf_void" + echo "Checking for return value of sprintf()... No." + echo " WARNING: apparently sprintf() does not return a value. zlib" + echo " can build but will be open to possible string-format security" + echo " vulnerabilities." + fi + fi +fi + +if test "$gcc" -eq 1; then + cat > $test.c <= 33) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif +int ZLIB_INTERNAL foo; +int main() +{ + return 0; +} +EOF + if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + echo "Checking for attribute(visibility) support... Yes." + else + CFLAGS="$CFLAGS -DNO_VIZ" + SFLAGS="$SFLAGS -DNO_VIZ" + echo "Checking for attribute(visibility) support... No." + fi +fi + +CPP=${CPP-"$CC -E"} +case $CFLAGS in + *ASMV*) + if test "`$NM $test.o | grep _hello`" = ""; then + CPP="$CPP -DNO_UNDERLINE" + echo Checking for underline in external names... No. + else + echo Checking for underline in external names... Yes. + fi ;; +esac + +rm -f $test.[co] $test $test$shared_ext + +# udpate Makefile +sed < Makefile.in " +/^CC *=/s#=.*#=$CC# +/^CFLAGS *=/s#=.*#=$CFLAGS# +/^SFLAGS *=/s#=.*#=$SFLAGS# +/^LDFLAGS *=/s#=.*#=$LDFLAGS# +/^LDSHARED *=/s#=.*#=$LDSHARED# +/^CPP *=/s#=.*#=$CPP# +/^STATICLIB *=/s#=.*#=$STATICLIB# +/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# +/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# +/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# +/^AR *=/s#=.*#=$AR_RC# +/^RANLIB *=/s#=.*#=$RANLIB# +/^LDCONFIG *=/s#=.*#=$LDCONFIG# +/^LDSHAREDLIBC *=/s#=.*#=$LDSHAREDLIBC# +/^EXE *=/s#=.*#=$EXE# +/^prefix *=/s#=.*#=$prefix# +/^exec_prefix *=/s#=.*#=$exec_prefix# +/^libdir *=/s#=.*#=$libdir# +/^sharedlibdir *=/s#=.*#=$sharedlibdir# +/^includedir *=/s#=.*#=$includedir# +/^mandir *=/s#=.*#=$mandir# +/^all: */s#:.*#: $ALL# +/^test: */s#:.*#: $TEST# +" > Makefile + +sed < zlib.pc.in " +/^CC *=/s#=.*#=$CC# +/^CFLAGS *=/s#=.*#=$CFLAGS# +/^CPP *=/s#=.*#=$CPP# +/^LDSHARED *=/s#=.*#=$LDSHARED# +/^STATICLIB *=/s#=.*#=$STATICLIB# +/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# +/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# +/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# +/^AR *=/s#=.*#=$AR_RC# +/^RANLIB *=/s#=.*#=$RANLIB# +/^EXE *=/s#=.*#=$EXE# +/^prefix *=/s#=.*#=$prefix# +/^exec_prefix *=/s#=.*#=$exec_prefix# +/^libdir *=/s#=.*#=$libdir# +/^sharedlibdir *=/s#=.*#=$sharedlibdir# +/^includedir *=/s#=.*#=$includedir# +/^mandir *=/s#=.*#=$mandir# +/^LDFLAGS *=/s#=.*#=$LDFLAGS# +" | sed -e " +s/\@VERSION\@/$VER/g; +" > zlib.pc diff --git a/astroem/zee.js/crc32.c b/astroem/zee.js/crc32.c new file mode 100644 index 00000000..91be372d --- /dev/null +++ b/astroem/zee.js/crc32.c @@ -0,0 +1,442 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/astroem/zee.js/crc32.h b/astroem/zee.js/crc32.h new file mode 100644 index 00000000..8053b611 --- /dev/null +++ b/astroem/zee.js/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/astroem/zee.js/deflate.c b/astroem/zee.js/deflate.c new file mode 100644 index 00000000..68c065fb --- /dev/null +++ b/astroem/zee.js/deflate.c @@ -0,0 +1,1837 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local block_state deflate_rle OF((deflate_state *s, int flush)); +local block_state deflate_huff OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + memset(s->prev, 0, s->w_size*sizeof(Pos)); /* XXX Zero out for emscripten, to avoid SAFE_HEAP warnings */ + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > s->w_size) { + length = s->w_size; + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if ((strategy != s->strategy || func != configuration_table[level].func) && + strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_BLOCK); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds for + * every combination of windowBits and memLevel. But even the conservative + * upper bound of about 14% expansion does not seem onerous for output buffer + * allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong complen, wraplen; + Bytef *str; + + /* conservative upper bound for compressed data */ + complen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + + /* if can't get parameters, return conservative bound plus zlib wrapper */ + if (strm == Z_NULL || strm->state == Z_NULL) + return complen + 6; + + /* compute wrapper length */ + s = strm->state; + switch (s->wrap) { + case 0: /* raw deflate */ + wraplen = 0; + break; + case 1: /* zlib wrapper */ + wraplen = 6 + (s->strstart ? 4 : 0); + break; + case 2: /* gzip wrapper */ + wraplen = 18; + if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + if (s->gzhead->extra != Z_NULL) + wraplen += 2 + s->gzhead->extra_len; + str = s->gzhead->name; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + str = s->gzhead->comment; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + if (s->gzhead->hcrc) + wraplen += 2; + } + break; + default: /* for compiler happiness */ + wraplen = 6; + } + + /* if not default parameters, return conservative bound */ + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return complen + wraplen; + + /* default settings: return tight bound for that case */ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13 - 6 + wraplen; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_BLOCK || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + (s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush)); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + if (s->lookahead == 0) { + s->strstart = 0; + s->block_start = 0L; + } + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + memset(ds->prev, 0, ds->w_size*sizeof(Pos)); /* XXX Zero out for emscripten, to avoid SAFE_HEAP warnings */ + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_start = 0; /* XXX Emscripten: initialize to 0, to prevent a SAFE_HEAP notification */ + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ + +#else /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for FASTEST only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#endif /* FASTEST */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, last) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (last)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, last) { \ + FLUSH_BLOCK_ONLY(s, last); \ + if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt prev; /* byte at distance one to match */ + Bytef *scan, *strend; /* scan goes up to strend for length of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s->match_length = 0; + if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + prev = *scan; + if (prev == *++scan && prev == *++scan && prev == *++scan) { + strend = s->window + s->strstart + MAX_MATCH; + do { + } while (prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + scan < strend); + s->match_length = MAX_MATCH - (int)(strend - scan); + if (s->match_length > s->lookahead) + s->match_length = s->lookahead; + } + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, s->match_length); + + _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + s->strstart += s->match_length; + s->match_length = 0; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +local block_state deflate_huff(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + fill_window(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s->match_length = 0; + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/astroem/zee.js/deflate.h b/astroem/zee.js/deflate.h new file mode 100644 index 00000000..cbf0d1ea --- /dev/null +++ b/astroem/zee.js/deflate.h @@ -0,0 +1,342 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/astroem/zee.js/empty_main.c b/astroem/zee.js/empty_main.c new file mode 100644 index 00000000..b54a2202 --- /dev/null +++ b/astroem/zee.js/empty_main.c @@ -0,0 +1,2 @@ +int main() { return 0; } + diff --git a/astroem/zee.js/example.c b/astroem/zee.js/example.c new file mode 100644 index 00000000..6367a55d --- /dev/null +++ b/astroem/zee.js/example.c @@ -0,0 +1,567 @@ +/* example.c -- usage example of the zlib compression library + * Copyright (C) 1995-2006 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" +#include + +#ifdef STDC +# include +# include +#endif + +#if defined(VMS) || defined(RISCOS) +# define TESTFILE "foo-gz" +#else +# define TESTFILE "foo.gz" +#endif + +#define CHECK_ERR(err, msg) { \ + if (err != Z_OK) { \ + fprintf(stderr, "%s error: %d\n", msg, err); \ + exit(1); \ + } \ +} + +const char hello[] = "hello, hello!"; +/* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + */ + +const char dictionary[] = "hello"; +uLong dictId; /* Adler32 value of the dictionary */ + +void test_compress OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_gzio OF((const char *fname, + Byte *uncompr, uLong uncomprLen)); +void test_deflate OF((Byte *compr, uLong comprLen)); +void test_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_deflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_flush OF((Byte *compr, uLong *comprLen)); +void test_sync OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_dict_deflate OF((Byte *compr, uLong comprLen)); +void test_dict_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Test compress() and uncompress() + */ +void test_compress(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + uLong len = (uLong)strlen(hello)+1; + + err = compress(compr, &comprLen, (const Bytef*)hello, len); + CHECK_ERR(err, "compress"); + + strcpy((char*)uncompr, "garbage"); + + err = uncompress(uncompr, &uncomprLen, compr, comprLen); + CHECK_ERR(err, "uncompress"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad uncompress\n"); + exit(1); + } else { + printf("uncompress(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test read/write of .gz files + */ +void test_gzio(fname, uncompr, uncomprLen) + const char *fname; /* compressed file name */ + Byte *uncompr; + uLong uncomprLen; +{ +#ifdef NO_GZCOMPRESS + fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); +#else + int err; + int len = (int)strlen(hello)+1; + gzFile file; + z_off_t pos; + + file = gzopen(fname, "wb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + gzputc(file, 'h'); + if (gzputs(file, "ello") != 4) { + fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); + exit(1); + } + if (gzprintf(file, ", %s!", "hello") != 8) { + fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); + exit(1); + } + gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ + gzclose(file); + + file = gzopen(fname, "rb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + strcpy((char*)uncompr, "garbage"); + + if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { + fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); + exit(1); + } else { + printf("gzread(): %s\n", (char*)uncompr); + } + + pos = gzseek(file, -8L, SEEK_CUR); + if (pos != 6 || gztell(file) != pos) { + fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", + (long)pos, (long)gztell(file)); + exit(1); + } + + if (gzgetc(file) != ' ') { + fprintf(stderr, "gzgetc error\n"); + exit(1); + } + + if (gzungetc(' ', file) != ' ') { + fprintf(stderr, "gzungetc error\n"); + exit(1); + } + + gzgets(file, (char*)uncompr, (int)uncomprLen); + if (strlen((char*)uncompr) != 7) { /* " hello!" */ + fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello + 6)) { + fprintf(stderr, "bad gzgets after gzseek\n"); + exit(1); + } else { + printf("gzgets() after gzseek: %s\n", (char*)uncompr); + } + + gzclose(file); +#endif +} + +/* =========================================================================== + * Test deflate() with small buffers + */ +void test_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uLong len = (uLong)strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != len && c_stream.total_out < comprLen) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + } + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = deflate(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "deflate"); + } + + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with small buffers + */ +void test_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 0; + d_stream.next_out = uncompr; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { + d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate\n"); + exit(1); + } else { + printf("inflate(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test deflate() with large buffers and dynamic change of compression level + */ +void test_large_deflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_SPEED); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + /* At this point, uncompr is still mostly zeroes, so it should compress + * very well: + */ + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + if (c_stream.avail_in != 0) { + fprintf(stderr, "deflate not greedy\n"); + exit(1); + } + + /* Feed in already compressed data and switch to no compression: */ + deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); + c_stream.next_in = compr; + c_stream.avail_in = (uInt)comprLen/2; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + /* Switch back to compressing mode: */ + deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with large buffers + */ +void test_large_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + for (;;) { + d_stream.next_out = uncompr; /* discard the output */ + d_stream.avail_out = (uInt)uncomprLen; + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "large inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (d_stream.total_out != 2*uncomprLen + comprLen/2) { + fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); + exit(1); + } else { + printf("large_inflate(): OK\n"); + } +} + +/* =========================================================================== + * Test deflate() with full flush + */ +void test_flush(compr, comprLen) + Byte *compr; + uLong *comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uInt len = (uInt)strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + c_stream.avail_in = 3; + c_stream.avail_out = (uInt)*comprLen; + err = deflate(&c_stream, Z_FULL_FLUSH); + CHECK_ERR(err, "deflate"); + + compr[3]++; /* force an error in first compressed block */ + c_stream.avail_in = len - 3; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + CHECK_ERR(err, "deflate"); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); + + *comprLen = c_stream.total_out; +} + +/* =========================================================================== + * Test inflateSync() + */ +void test_sync(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 2; /* just read the zlib header */ + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + inflate(&d_stream, Z_NO_FLUSH); + CHECK_ERR(err, "inflate"); + + d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ + err = inflateSync(&d_stream); /* but skip the damaged part */ + CHECK_ERR(err, "inflateSync"); + + err = inflate(&d_stream, Z_FINISH); + if (err != Z_DATA_ERROR) { + fprintf(stderr, "inflate should report DATA_ERROR\n"); + /* Because of incorrect adler32 */ + exit(1); + } + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + printf("after inflateSync(): hel%s\n", (char *)uncompr); +} + +/* =========================================================================== + * Test deflate() with preset dictionary + */ +void test_dict_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + err = deflateSetDictionary(&c_stream, + (const Bytef*)dictionary, sizeof(dictionary)); + CHECK_ERR(err, "deflateSetDictionary"); + + dictId = c_stream.adler; + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + c_stream.next_in = (Bytef*)hello; + c_stream.avail_in = (uInt)strlen(hello)+1; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with a preset dictionary + */ +void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + for (;;) { + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + if (err == Z_NEED_DICT) { + if (d_stream.adler != dictId) { + fprintf(stderr, "unexpected dictionary"); + exit(1); + } + err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, + sizeof(dictionary)); + } + CHECK_ERR(err, "inflate with dict"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate with dict\n"); + exit(1); + } else { + printf("inflate with dictionary: %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Usage: example [output.gz [input.gz]] + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + Byte *compr, *uncompr; + uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ + uLong uncomprLen = comprLen; + static const char* myVersion = ZLIB_VERSION; + + if (zlibVersion()[0] != myVersion[0]) { + fprintf(stderr, "incompatible zlib version\n"); + exit(1); + + } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { + fprintf(stderr, "warning: different zlib version\n"); + } + + printf("zlib version %s = %d, compile flags = %d\n", + ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); + + compr = (Byte*)calloc((uInt)comprLen, 1); + uncompr = (Byte*)calloc((uInt)uncomprLen, 1); + /* compr and uncompr are cleared to avoid reading uninitialized + * data and to ensure that uncompr compresses well. + */ + if (compr == Z_NULL || uncompr == Z_NULL) { + printf("out of memory\n"); + exit(1); + } + test_compress(compr, comprLen, uncompr, uncomprLen); + + /* XXX Emscripten commenting out + test_gzio((argc > 1 ? argv[1] : TESTFILE), + uncompr, uncomprLen); + */ + + test_deflate(compr, comprLen); + test_inflate(compr, comprLen, uncompr, uncomprLen); + + test_large_deflate(compr, comprLen, uncompr, uncomprLen); + test_large_inflate(compr, comprLen, uncompr, uncomprLen); + + test_flush(compr, &comprLen); + test_sync(compr, comprLen, uncompr, uncomprLen); + comprLen = uncomprLen; + + test_dict_deflate(compr, comprLen); + test_dict_inflate(compr, comprLen, uncompr, uncomprLen); + + free(compr); + free(uncompr); + + return 0; +} diff --git a/astroem/zee.js/gzclose.c b/astroem/zee.js/gzclose.c new file mode 100644 index 00000000..3adcc5fa --- /dev/null +++ b/astroem/zee.js/gzclose.c @@ -0,0 +1,25 @@ +/* gzclose.c -- zlib gzclose() function + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* gzclose() is in a separate file so that it is linked in only if it is used. + That way the other gzclose functions can be used instead to avoid linking in + unneeded compression or decompression routines. */ +int ZEXPORT __attribute__((used)) gzclose(file) + gzFile file; +{ +#ifndef NO_GZCOMPRESS + gz_statep state; + + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); +#else + return gzclose_r(file); +#endif +} diff --git a/astroem/zee.js/gzguts.h b/astroem/zee.js/gzguts.h new file mode 100644 index 00000000..0f8fb79f --- /dev/null +++ b/astroem/zee.js/gzguts.h @@ -0,0 +1,132 @@ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +# endif +#endif + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include +#include "zlib.h" +#ifdef STDC +# include +# include +# include +#endif +#include + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifdef _MSC_VER +# include +# define vsnprintf _vsnprintf +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +/* gz* functions always use library allocation functions */ +#ifndef STDC + extern voidp malloc OF((uInt size)); + extern void free OF((voidpf ptr)); +#endif + +/* get errno and strerror definition */ +#if defined UNDER_CE +# include +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifdef STDC +# include +# define zstrerror() strerror(errno) +# else +# define zstrerror() "stdio error (consult errno)" +# endif +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); +#endif + +/* default i/o buffer size -- double this for output when reading */ +#define GZBUFSIZE 8192 + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + z_off64_t pos; /* current position in uncompressed data */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer */ + unsigned char *out; /* output buffer (double-sized when reading) */ + unsigned char *next; /* next output data to deliver or write */ + /* just for reading */ + unsigned have; /* amount of output data unused at next */ + int eof; /* true if end of input file reached */ + z_off64_t start; /* where the gzip data started, for rewinding */ + z_off64_t raw; /* where the raw data started, for seeking */ + int how; /* 0: get header, 1: copy, 2: decompress */ + int direct; /* true if last read direct, false if gzip */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state FAR *gz_statep; + +/* shared functions */ +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +#endif + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#ifdef INT_MAX +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) +#else +unsigned ZLIB_INTERNAL gz_intmax OF((void)); +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) +#endif diff --git a/astroem/zee.js/gzlib.c b/astroem/zee.js/gzlib.c new file mode 100644 index 00000000..2d147825 --- /dev/null +++ b/astroem/zee.js/gzlib.c @@ -0,0 +1,537 @@ +/* gzlib.c -- zlib functions common to reading and writing gzip files + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define LSEEK lseek64 +#else +# define LSEEK lseek +#endif + +/* Local functions */ +local void gz_reset OF((gz_statep)); +local gzFile gz_open OF((const char *, int, const char *)); + +#if defined UNDER_CE + +/* Map the Windows error number in ERROR to a locale-dependent error message + string and return a pointer to it. Typically, the values for ERROR come + from GetLastError. + + The string pointed to shall not be modified by the application, but may be + overwritten by a subsequent call to gz_strwinerror + + The gz_strwinerror function does not change the current setting of + GetLastError. */ +char ZLIB_INTERNAL *gz_strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +#endif /* UNDER_CE */ + +/* Reset gzip file state */ +local void gz_reset(state) + gz_statep state; +{ + if (state->mode == GZ_READ) { /* for reading ... */ + state->have = 0; /* no output data available */ + state->eof = 0; /* not at end of file */ + state->how = LOOK; /* look for gzip header */ + state->direct = 1; /* default for empty file */ + } + state->seek = 0; /* no seek request pending */ + gz_error(state, Z_OK, NULL); /* clear error */ + state->pos = 0; /* no uncompressed data yet */ + state->strm.avail_in = 0; /* no input data yet */ +} + +/* Open a gzip file either by name or file descriptor. */ +local gzFile gz_open(path, fd, mode) + const char *path; + int fd; + const char *mode; +{ + gz_statep state; + + /* allocate gzFile structure to return */ + state = malloc(sizeof(gz_state)); + if (state == NULL) + return NULL; + state->size = 0; /* no buffers allocated yet */ + state->want = GZBUFSIZE; /* requested buffer size */ + state->msg = NULL; /* no error message yet */ + + /* interpret mode */ + state->mode = GZ_NONE; + state->level = Z_DEFAULT_COMPRESSION; + state->strategy = Z_DEFAULT_STRATEGY; + while (*mode) { + if (*mode >= '0' && *mode <= '9') + state->level = *mode - '0'; + else + switch (*mode) { + case 'r': + state->mode = GZ_READ; + break; +#ifndef NO_GZCOMPRESS + case 'w': + state->mode = GZ_WRITE; + break; + case 'a': + state->mode = GZ_APPEND; + break; +#endif + case '+': /* can't read and write at the same time */ + free(state); + return NULL; + case 'b': /* ignore -- will request binary anyway */ + break; + case 'f': + state->strategy = Z_FILTERED; + break; + case 'h': + state->strategy = Z_HUFFMAN_ONLY; + break; + case 'R': + state->strategy = Z_RLE; + break; + case 'F': + state->strategy = Z_FIXED; + default: /* could consider as an error, but just ignore */ + ; + } + mode++; + } + + /* must provide an "r", "w", or "a" */ + if (state->mode == GZ_NONE) { + free(state); + return NULL; + } + + /* save the path name for error messages */ + state->path = malloc(strlen(path) + 1); + if (state->path == NULL) { + free(state); + return NULL; + } + strcpy(state->path, path); + + /* open the file with the appropriate mode (or just use fd) */ + state->fd = fd != -1 ? fd : + open(path, +#ifdef O_LARGEFILE + O_LARGEFILE | +#endif +#ifdef O_BINARY + O_BINARY | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | ( + state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))), + 0666); + if (state->fd == -1) { + free(state->path); + free(state); + return NULL; + } + if (state->mode == GZ_APPEND) + state->mode = GZ_WRITE; /* simplify later checks */ + + /* save the current position for rewinding (only if reading) */ + if (state->mode == GZ_READ) { + state->start = LSEEK(state->fd, 0, SEEK_CUR); + if (state->start == -1) state->start = 0; + } + + /* initialize stream */ + gz_reset(state); + + /* return stream */ + return (gzFile)state; +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT __attribute__((used)) gzopen(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen64(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzdopen(fd, mode) + int fd; + const char *mode; +{ + char *path; /* identifier for error messages */ + gzFile gz; + + if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) + return NULL; + sprintf(path, "", fd); /* for debugging */ + gz = gz_open(path, fd, mode); + free(path); + return gz; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzbuffer(file, size) + gzFile file; + unsigned size; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* make sure we haven't already allocated memory */ + if (state->size != 0) + return -1; + + /* check and set requested size */ + if (size == 0) + return -1; + state->want = size; + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzrewind(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* back up and start over */ + if (LSEEK(state->fd, state->start, SEEK_SET) == -1) + return -1; + gz_reset(state); + return 0; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzseek64(file, offset, whence) + gzFile file; + z_off64_t offset; + int whence; +{ + unsigned n; + z_off64_t ret; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* check that there's no error */ + if (state->err != Z_OK) + return -1; + + /* can only seek from start or relative to current position */ + if (whence != SEEK_SET && whence != SEEK_CUR) + return -1; + + /* normalize offset to a SEEK_CUR specification */ + if (whence == SEEK_SET) + offset -= state->pos; + else if (state->seek) + offset += state->skip; + state->seek = 0; + + /* if within raw area while reading, just go there */ + if (state->mode == GZ_READ && state->how == COPY && + state->pos + offset >= state->raw) { + ret = LSEEK(state->fd, offset - state->have, SEEK_CUR); + if (ret == -1) + return -1; + state->have = 0; + state->eof = 0; + state->seek = 0; + gz_error(state, Z_OK, NULL); + state->strm.avail_in = 0; + state->pos += offset; + return state->pos; + } + + /* calculate skip amount, rewinding if needed for back seek when reading */ + if (offset < 0) { + if (state->mode != GZ_READ) /* writing -- can't go backwards */ + return -1; + offset += state->pos; + if (offset < 0) /* before start of file! */ + return -1; + if (gzrewind(file) == -1) /* rewind, then skip to offset */ + return -1; + } + + /* if reading, skip what's in output buffer (one less gzgetc() check) */ + if (state->mode == GZ_READ) { + n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? + (unsigned)offset : state->have; + state->have -= n; + state->next += n; + state->pos += n; + offset -= n; + } + + /* request skip (if not zero) */ + if (offset) { + state->seek = 1; + state->skip = offset; + } + return state->pos + offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzseek(file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + z_off64_t ret; + + ret = gzseek64(file, (z_off64_t)offset, whence); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gztell64(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* return position */ + return state->pos + (state->seek ? state->skip : 0); +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gztell(file) + gzFile file; +{ + z_off64_t ret; + + ret = gztell64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzoffset64(file) + gzFile file; +{ + z_off64_t offset; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* compute and return effective offset in file */ + offset = LSEEK(state->fd, 0, SEEK_CUR); + if (offset == -1) + return -1; + if (state->mode == GZ_READ) /* reading */ + offset -= state->strm.avail_in; /* don't count buffered input */ + return offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzoffset(file) + gzFile file; +{ + z_off64_t ret; + + ret = gzoffset64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzeof(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return 0; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return 0; + + /* return end-of-file state */ + return state->mode == GZ_READ ? + (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0; +} + +/* -- see zlib.h -- */ +const char * ZEXPORT gzerror(file, errnum) + gzFile file; + int *errnum; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return NULL; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return NULL; + + /* return error information */ + if (errnum != NULL) + *errnum = state->err; + return state->msg == NULL ? "" : state->msg; +} + +/* -- see zlib.h -- */ +void ZEXPORT gzclearerr(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return; + + /* clear error and end-of-file */ + if (state->mode == GZ_READ) + state->eof = 0; + gz_error(state, Z_OK, NULL); +} + +/* Create an error message in allocated memory and set state->err and + state->msg accordingly. Free any previous error message already there. Do + not try to free or allocate space if the error is Z_MEM_ERROR (out of + memory). Simply save the error message as a static string. If there is an + allocation failure constructing the error message, then convert the error to + out of memory. */ +void ZLIB_INTERNAL gz_error(state, err, msg) + gz_statep state; + int err; + const char *msg; +{ + /* free previously allocated message and clear */ + if (state->msg != NULL) { + if (state->err != Z_MEM_ERROR) + free(state->msg); + state->msg = NULL; + } + + /* set error code, and if no message, then done */ + state->err = err; + if (msg == NULL) + return; + + /* for an out of memory error, save as static string */ + if (err == Z_MEM_ERROR) { + state->msg = (char *)msg; + return; + } + + /* construct error message with path */ + if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + state->err = Z_MEM_ERROR; + state->msg = (char *)"out of memory"; + return; + } + strcpy(state->msg, state->path); + strcat(state->msg, ": "); + strcat(state->msg, msg); + return; +} + +#ifndef INT_MAX +/* portably return maximum value for an int (when limits.h presumed not + available) -- we need to do this to cover cases where 2's complement not + used, since C standard permits 1's complement and sign-bit representations, + otherwise we could just use ((unsigned)-1) >> 1 */ +unsigned ZLIB_INTERNAL gz_intmax() +{ + unsigned p, q; + + p = 1; + do { + q = p; + p <<= 1; + p++; + } while (p > q); + return q >> 1; +} +#endif diff --git a/astroem/zee.js/gzread.c b/astroem/zee.js/gzread.c new file mode 100644 index 00000000..374aaad2 --- /dev/null +++ b/astroem/zee.js/gzread.c @@ -0,0 +1,653 @@ +/* gzread.c -- zlib functions for reading gzip files + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); +local int gz_avail OF((gz_statep)); +local int gz_next4 OF((gz_statep, unsigned long *)); +local int gz_head OF((gz_statep)); +local int gz_decomp OF((gz_statep)); +local int gz_make OF((gz_statep)); +local int gz_skip OF((gz_statep, z_off64_t)); + +/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from + state->fd, and update state->eof, state->err, and state->msg as appropriate. + This function needs to loop on read(), since read() is not guaranteed to + read the number of bytes requested, depending on the type of descriptor. */ +local int gz_load(state, buf, len, have) + gz_statep state; + unsigned char *buf; + unsigned len; + unsigned *have; +{ + int ret; + + *have = 0; + do { + ret = read(state->fd, buf + *have, len - *have); + if (ret <= 0) + break; + *have += ret; + } while (*have < len); + if (ret < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (ret == 0) + state->eof = 1; + return 0; +} + +/* Load up input buffer and set eof flag if last data loaded -- return -1 on + error, 0 otherwise. Note that the eof flag is set when the end of the input + file is reached, even though there may be unused data in the buffer. Once + that data has been used, no more attempts will be made to read the file. + gz_avail() assumes that strm->avail_in == 0. */ +local int gz_avail(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + if (state->err != Z_OK) + return -1; + if (state->eof == 0) { + if (gz_load(state, state->in, state->size, + (unsigned *)&(strm->avail_in)) == -1) + return -1; + strm->next_in = state->in; + } + return 0; +} + +/* Get next byte from input, or -1 if end or error. */ +#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \ + (strm->avail_in == 0 ? -1 : \ + (strm->avail_in--, *(strm->next_in)++))) + +/* Get a four-byte little-endian integer and return 0 on success and the value + in *ret. Otherwise -1 is returned and *ret is not modified. */ +local int gz_next4(state, ret) + gz_statep state; + unsigned long *ret; +{ + int ch; + unsigned long val; + z_streamp strm = &(state->strm); + + val = NEXT(); + val += (unsigned)NEXT() << 8; + val += (unsigned long)NEXT() << 16; + ch = NEXT(); + if (ch == -1) + return -1; + val += (unsigned long)ch << 24; + *ret = val; + return 0; +} + +/* Look for gzip header, set up for inflate or copy. state->have must be zero. + If this is the first time in, allocate required memory. state->how will be + left unchanged if there is no more input data available, will be set to COPY + if there is no gzip header and direct copying will be performed, or it will + be set to GZIP for decompression, and the gzip header will be skipped so + that the next available input data is the raw deflate stream. If direct + copying, then leftover input data from the input buffer will be copied to + the output buffer. In that case, all further file reads will be directly to + either the output buffer or a user buffer. If decompressing, the inflate + state and the check value will be initialized. gz_head() will return 0 on + success or -1 on failure. Failures may include read errors or gzip header + errors. */ +local int gz_head(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + int flags; + unsigned len; + + /* allocate read buffers and inflate memory */ + if (state->size == 0) { + /* allocate buffers */ + state->in = malloc(state->want); + state->out = malloc(state->want << 1); + if (state->in == NULL || state->out == NULL) { + if (state->out != NULL) + free(state->out); + if (state->in != NULL) + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + state->size = state->want; + + /* allocate inflate memory */ + state->strm.zalloc = Z_NULL; + state->strm.zfree = Z_NULL; + state->strm.opaque = Z_NULL; + state->strm.avail_in = 0; + state->strm.next_in = Z_NULL; + if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */ + free(state->out); + free(state->in); + state->size = 0; + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + } + + /* get some data in the input buffer */ + if (strm->avail_in == 0) { + if (gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) + return 0; + } + + /* look for the gzip magic header bytes 31 and 139 */ + if (strm->next_in[0] == 31) { + strm->avail_in--; + strm->next_in++; + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in && strm->next_in[0] == 139) { + /* we have a gzip header, woo hoo! */ + strm->avail_in--; + strm->next_in++; + + /* skip rest of header */ + if (NEXT() != 8) { /* compression method */ + gz_error(state, Z_DATA_ERROR, "unknown compression method"); + return -1; + } + flags = NEXT(); + if (flags & 0xe0) { /* reserved flag bits */ + gz_error(state, Z_DATA_ERROR, "unknown header flags set"); + return -1; + } + NEXT(); /* modification time */ + NEXT(); + NEXT(); + NEXT(); + NEXT(); /* extra flags */ + NEXT(); /* operating system */ + if (flags & 4) { /* extra field */ + len = (unsigned)NEXT(); + len += (unsigned)NEXT() << 8; + while (len--) + if (NEXT() < 0) + break; + } + if (flags & 8) /* file name */ + while (NEXT() > 0) + ; + if (flags & 16) /* comment */ + while (NEXT() > 0) + ; + if (flags & 2) { /* header crc */ + NEXT(); + NEXT(); + } + /* an unexpected end of file is not checked for here -- it will be + noticed on the first request for uncompressed data */ + + /* set up for decompression */ + inflateReset(strm); + strm->adler = crc32(0L, Z_NULL, 0); + state->how = GZIP; + state->direct = 0; + return 0; + } + else { + /* not a gzip file -- save first byte (31) and fall to raw i/o */ + state->out[0] = 31; + state->have = 1; + } + } + + /* doing raw i/o, save start of raw data for seeking, copy any leftover + input to output -- this assumes that the output buffer is larger than + the input buffer, which also assures space for gzungetc() */ + state->raw = state->pos; + state->next = state->out; + if (strm->avail_in) { + memcpy(state->next + state->have, strm->next_in, strm->avail_in); + state->have += strm->avail_in; + strm->avail_in = 0; + } + state->how = COPY; + state->direct = 1; + return 0; +} + +/* Decompress from input to the provided next_out and avail_out in the state. + If the end of the compressed data is reached, then verify the gzip trailer + check value and length (modulo 2^32). state->have and state->next are set + to point to the just decompressed data, and the crc is updated. If the + trailer is verified, state->how is reset to LOOK to look for the next gzip + stream or raw data, once state->have is depleted. Returns 0 on success, -1 + on failure. Failures may include invalid compressed data or a failed gzip + trailer verification. */ +local int gz_decomp(state) + gz_statep state; +{ + int ret; + unsigned had; + unsigned long crc, len; + z_streamp strm = &(state->strm); + + /* fill output buffer up to end of deflate stream */ + had = strm->avail_out; + do { + /* get more input for inflate() */ + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) { + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); + return -1; + } + + /* decompress and handle errors */ + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { + gz_error(state, Z_STREAM_ERROR, + "internal error: inflate stream corrupt"); + return -1; + } + if (ret == Z_MEM_ERROR) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ + gz_error(state, Z_DATA_ERROR, + strm->msg == NULL ? "compressed data error" : strm->msg); + return -1; + } + } while (strm->avail_out && ret != Z_STREAM_END); + + /* update available output and crc check value */ + state->have = had - strm->avail_out; + state->next = strm->next_out - state->have; + strm->adler = crc32(strm->adler, state->next, state->have); + + /* check gzip trailer if at end of deflate stream */ + if (ret == Z_STREAM_END) { + if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); + return -1; + } + if (crc != strm->adler) { + gz_error(state, Z_DATA_ERROR, "incorrect data check"); + return -1; + } + if (len != (strm->total_out & 0xffffffffL)) { + gz_error(state, Z_DATA_ERROR, "incorrect length check"); + return -1; + } + state->how = LOOK; /* ready for next stream, once have is 0 (leave + state->direct unchanged to remember how) */ + } + + /* good decompression */ + return 0; +} + +/* Make data and put in the output buffer. Assumes that state->have == 0. + Data is either copied from the input file or decompressed from the input + file depending on state->how. If state->how is LOOK, then a gzip header is + looked for (and skipped if found) to determine wither to copy or decompress. + Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY + or GZIP unless the end of the input file has been reached and all data has + been processed. */ +local int gz_make(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + if (state->how == LOOK) { /* look for gzip header */ + if (gz_head(state) == -1) + return -1; + if (state->have) /* got some data from gz_head() */ + return 0; + } + if (state->how == COPY) { /* straight copy */ + if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1) + return -1; + state->next = state->out; + } + else if (state->how == GZIP) { /* decompress */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + } + return 0; +} + +/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ +local int gz_skip(state, len) + gz_statep state; + z_off64_t len; +{ + unsigned n; + + /* skip over len bytes or reach end-of-file, whichever comes first */ + while (len) + /* skip over whatever is in output buffer */ + if (state->have) { + n = GT_OFF(state->have) || (z_off64_t)state->have > len ? + (unsigned)len : state->have; + state->have -= n; + state->next += n; + state->pos += n; + len -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && state->strm.avail_in == 0) + break; + + /* need more data to skip -- load up output buffer */ + else { + /* get more output, looking for header if required */ + if (gz_make(state) == -1) + return -1; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT __attribute__((used)) gzread(file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + unsigned got, n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + return -1; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* get len bytes to buf, or less than len if at the end */ + got = 0; + do { + /* first just try copying data from the output buffer */ + if (state->have) { + n = state->have > len ? len : state->have; + memcpy(buf, state->next, n); + state->next += n; + state->have -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && strm->avail_in == 0) + break; + + /* need output data -- for small len or new stream load up our output + buffer */ + else if (state->how == LOOK || len < (state->size << 1)) { + /* get more output, looking for header if required */ + if (gz_make(state) == -1) + return -1; + continue; /* no progress yet -- go back to memcpy() above */ + /* the copy above assures that we will leave with space in the + output buffer, allowing at least one gzungetc() to succeed */ + } + + /* large len -- read directly into user buffer */ + else if (state->how == COPY) { /* read directly */ + if (gz_load(state, buf, len, &n) == -1) + return -1; + } + + /* large len -- decompress directly into user buffer */ + else { /* state->how == GZIP */ + strm->avail_out = len; + strm->next_out = buf; + if (gz_decomp(state) == -1) + return -1; + n = state->have; + state->have = 0; + } + + /* update progress */ + len -= n; + buf = (char *)buf + n; + got += n; + state->pos += n; + } while (len); + + /* return number of bytes read into user buffer (will fit in int) */ + return (int)got; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzgetc(file) + gzFile file; +{ + int ret; + unsigned char buf[1]; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* try output buffer (no need to check for skip request) */ + if (state->have) { + state->have--; + state->pos++; + return *(state->next)++; + } + + /* nothing there -- try gzread() */ + ret = gzread(file, buf, 1); + return ret < 1 ? -1 : buf[0]; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* can't push EOF */ + if (c < 0) + return -1; + + /* if output buffer empty, put byte at end (allows more pushing) */ + if (state->have == 0) { + state->have = 1; + state->next = state->out + (state->size << 1) - 1; + state->next[0] = c; + state->pos--; + return c; + } + + /* if no room, give up (must have already done a gzungetc()) */ + if (state->have == (state->size << 1)) { + gz_error(state, Z_BUF_ERROR, "out of room to push characters"); + return -1; + } + + /* slide output data if needed and insert byte before existing data */ + if (state->next == state->out) { + unsigned char *src = state->out + state->have; + unsigned char *dest = state->out + (state->size << 1); + while (src > state->out) + *--dest = *--src; + state->next = dest; + } + state->have++; + state->next--; + state->next[0] = c; + state->pos--; + return c; +} + +/* -- see zlib.h -- */ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + unsigned left, n; + char *str; + unsigned char *eol; + gz_statep state; + + /* check parameters and get internal structure */ + if (file == NULL || buf == NULL || len < 1) + return NULL; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return NULL; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return NULL; + } + + /* copy output bytes up to new line or len - 1, whichever comes first -- + append a terminating zero to the string (we don't check for a zero in + the contents, let the user worry about that) */ + str = buf; + left = (unsigned)len - 1; + if (left) do { + /* assure that something is in the output buffer */ + if (state->have == 0) { + if (gz_make(state) == -1) + return NULL; /* error */ + if (state->have == 0) { /* end of file */ + if (buf == str) /* got bupkus */ + return NULL; + break; /* got something -- return it */ + } + } + + /* look for end-of-line in current output buffer */ + n = state->have > left ? left : state->have; + eol = memchr(state->next, '\n', n); + if (eol != NULL) + n = (unsigned)(eol - state->next) + 1; + + /* copy through end-of-line, or remainder if not found */ + memcpy(buf, state->next, n); + state->have -= n; + state->next += n; + state->pos += n; + left -= n; + buf += n; + } while (left && eol == NULL); + + /* found end-of-line or out of space -- terminate string and return it */ + buf[0] = 0; + return str; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzdirect(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return 0; + + /* if the state is not known, but we can find out, then do so (this is + mainly for right after a gzopen() or gzdopen()) */ + if (state->how == LOOK && state->have == 0) + (void)gz_head(state); + + /* return 1 if reading direct, 0 if decompressing a gzip stream */ + return state->direct; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_r(file) + gzFile file; +{ + int ret; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return Z_STREAM_ERROR; + + /* free memory and close file */ + if (state->size) { + inflateEnd(&(state->strm)); + free(state->out); + free(state->in); + } + gz_error(state, Z_OK, NULL); + free(state->path); + ret = close(state->fd); + free(state); + return ret ? Z_ERRNO : Z_OK; +} diff --git a/astroem/zee.js/gzwrite.c b/astroem/zee.js/gzwrite.c new file mode 100644 index 00000000..f9780d56 --- /dev/null +++ b/astroem/zee.js/gzwrite.c @@ -0,0 +1,531 @@ +/* gzwrite.c -- zlib functions for writing gzip files + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_init OF((gz_statep)); +local int gz_comp OF((gz_statep, int)); +local int gz_zero OF((gz_statep, z_off64_t)); + +/* Initialize state for writing a gzip file. Mark initialization by setting + state->size to non-zero. Return -1 on failure or 0 on success. */ +local int gz_init(state) + gz_statep state; +{ + int ret; + z_streamp strm = &(state->strm); + + /* allocate input and output buffers */ + state->in = malloc(state->want); + state->out = malloc(state->want); + if (state->in == NULL || state->out == NULL) { + if (state->out != NULL) + free(state->out); + if (state->in != NULL) + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = deflateInit2(strm, state->level, Z_DEFLATED, + 15 + 16, 8, state->strategy); + if (ret != Z_OK) { + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* mark state as initialized */ + state->size = state->want; + + /* initialize write buffer */ + strm->avail_out = state->size; + strm->next_out = state->out; + state->next = strm->next_out; + return 0; +} + +/* Compress whatever is at avail_in and next_in and write to the output file. + Return -1 if there is an error writing to the output file, otherwise 0. + flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, + then the deflate() state is reset to start a new gzip stream. */ +local int gz_comp(state, flush) + gz_statep state; + int flush; +{ + int ret, got; + unsigned have; + z_streamp strm = &(state->strm); + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return -1; + + /* run deflate() on provided input until it produces no more output */ + ret = Z_OK; + do { + /* write out current buffer contents if full, or if flushing, but if + doing Z_FINISH then don't write until we get to Z_STREAM_END */ + if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && + (flush != Z_FINISH || ret == Z_STREAM_END))) { + have = (unsigned)(strm->next_out - state->next); + if (have && ((got = write(state->fd, state->next, have)) < 0 || + (unsigned)got != have)) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (strm->avail_out == 0) { + strm->avail_out = state->size; + strm->next_out = state->out; + } + state->next = strm->next_out; + } + + /* compress */ + have = strm->avail_out; + ret = deflate(strm, flush); + if (ret == Z_STREAM_ERROR) { + gz_error(state, Z_STREAM_ERROR, + "internal error: deflate stream corrupt"); + return -1; + } + have -= strm->avail_out; + } while (have); + + /* if that completed a deflate stream, allow another to start */ + if (flush == Z_FINISH) + deflateReset(strm); + + /* all done, no errors */ + return 0; +} + +/* Compress len zeros to output. Return -1 on error, 0 on success. */ +local int gz_zero(state, len) + gz_statep state; + z_off64_t len; +{ + int first; + unsigned n; + z_streamp strm = &(state->strm); + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + + /* compress len zeros (len guaranteed > 0) */ + first = 1; + while (len) { + n = GT_OFF(state->size) || (z_off64_t)state->size > len ? + (unsigned)len : state->size; + if (first) { + memset(state->in, 0, n); + first = 0; + } + strm->avail_in = n; + strm->next_in = state->in; + state->pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + len -= n; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT __attribute__((used)) gzwrite(file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + unsigned put = len; + unsigned n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + return 0; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* for small len, copy to input buffer, otherwise compress directly */ + if (len < state->size) { + /* copy to input buffer, compress when full */ + do { + if (strm->avail_in == 0) + strm->next_in = state->in; + n = state->size - strm->avail_in; + if (n > len) + n = len; + memcpy(strm->next_in + strm->avail_in, buf, n); + strm->avail_in += n; + state->pos += n; + buf = (char *)buf + n; + len -= n; + if (len && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } while (len); + } + else { + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* directly compress user buffer to file */ + strm->avail_in = len; + strm->next_in = (voidp)buf; + state->pos += len; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } + + /* input was all buffered or compressed (put will fit in int) */ + return (int)put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char buf[1]; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* try writing to input buffer for speed (state->size == 0 if buffer not + initialized) */ + if (strm->avail_in < state->size) { + if (strm->avail_in == 0) + strm->next_in = state->in; + strm->next_in[strm->avail_in++] = c; + state->pos++; + return c; + } + + /* no room in buffer or not initialized, use gz_write() */ + buf[0] = c; + if (gzwrite(file, buf, 1) != 1) + return -1; + return c; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputs(file, str) + gzFile file; + const char *str; +{ + int ret; + unsigned len; + + /* write string */ + len = (unsigned)strlen(str); + ret = gzwrite(file, str, len); + return ret == 0 && len != 0 ? -1 : ret; +} + +#ifdef STDC +#include + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) +{ + int size, len; + gz_statep state; + z_streamp strm; + va_list va; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(state->in, format, va); + va_end(va); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = vsprintf(state->in, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(state->in, size, format, va); + va_end(va); + len = strlen(state->in); +# else + len = vsnprintf((char *)(state->in), size, format, va); + va_end(va); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->pos += len; + return len; +} + +#else /* !STDC */ + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + int size, len; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(state->in); +# else + len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->pos += len; + return len; +} + +#endif + +/* -- see zlib.h -- */ +int ZEXPORT gzflush(file, flush) + gzFile file; + int flush; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* check flush parameter */ + if (flush < 0 || flush > Z_FINISH) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* compress remaining data with requested flush */ + gz_comp(state, flush); + return state->err; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzsetparams(file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* if no change is requested, then do nothing */ + if (level == state->level && strategy == state->strategy) + return Z_OK; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* change compression parameters for subsequent input */ + if (state->size) { + /* flush previous input with previous parameters before changing */ + if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) + return state->err; + deflateParams(strm, level, strategy); + } + state->level = level; + state->strategy = strategy; + return Z_OK; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_w(file) + gzFile file; +{ + int ret = 0; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're writing */ + if (state->mode != GZ_WRITE) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + ret += gz_zero(state, state->skip); + } + + /* flush, free memory, and close file */ + ret += gz_comp(state, Z_FINISH); + (void)deflateEnd(&(state->strm)); + free(state->out); + free(state->in); + gz_error(state, Z_OK, NULL); + free(state->path); + ret += close(state->fd); + free(state); + return ret ? Z_ERRNO : Z_OK; +} diff --git a/astroem/zee.js/infback.c b/astroem/zee.js/infback.c new file mode 100644 index 00000000..af3a8c96 --- /dev/null +++ b/astroem/zee.js/infback.c @@ -0,0 +1,632 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->wnext = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + state->length = (unsigned)here.val; + + /* process literal */ + if (here.op == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/astroem/zee.js/inffast.c b/astroem/zee.js/inffast.c new file mode 100644 index 00000000..2f1d60b4 --- /dev/null +++ b/astroem/zee.js/inffast.c @@ -0,0 +1,340 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2008, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + PUP(out) = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + PUP(out) = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + PUP(out) = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + PUP(out) = PUP(from); + } while (--len); + continue; + } +#endif + } + from = window - OFF; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/astroem/zee.js/inffast.h b/astroem/zee.js/inffast.h new file mode 100644 index 00000000..e5c1aa4c --- /dev/null +++ b/astroem/zee.js/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/astroem/zee.js/inffixed.h b/astroem/zee.js/inffixed.h new file mode 100644 index 00000000..75ed4b59 --- /dev/null +++ b/astroem/zee.js/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/astroem/zee.js/inflate.c b/astroem/zee.js/inflate.c new file mode 100644 index 00000000..a8431abe --- /dev/null +++ b/astroem/zee.js/inflate.c @@ -0,0 +1,1480 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->window = Z_NULL; + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + else if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->sane = !subvert; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + return Z_OK; +#else + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + state = (struct inflate_state FAR *)strm->state; + return ((long)(state->back) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} diff --git a/astroem/zee.js/inflate.h b/astroem/zee.js/inflate.h new file mode 100644 index 00000000..95f4986d --- /dev/null +++ b/astroem/zee.js/inflate.h @@ -0,0 +1,122 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 10K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/astroem/zee.js/inftrees.c b/astroem/zee.js/inftrees.c new file mode 100644 index 00000000..11e9c52a --- /dev/null +++ b/astroem/zee.js/inftrees.c @@ -0,0 +1,330 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + here.op = (unsigned char)(extra[work[sym]]); + here.val = base[work[sym]]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + here.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = here; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/astroem/zee.js/inftrees.h b/astroem/zee.js/inftrees.h new file mode 100644 index 00000000..baa53a0b --- /dev/null +++ b/astroem/zee.js/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/astroem/zee.js/minigzip.c b/astroem/zee.js/minigzip.c new file mode 100644 index 00000000..9825ccc3 --- /dev/null +++ b/astroem/zee.js/minigzip.c @@ -0,0 +1,440 @@ +/* minigzip.c -- simulate gzip using the zlib compression library + * Copyright (C) 1995-2006, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * minigzip is a minimal implementation of the gzip utility. This is + * only an example of using zlib and isn't meant to replace the + * full-featured gzip. No attempt is made to deal with file systems + * limiting names to 14 or 8+3 characters, etc... Error checking is + * very limited. So use minigzip only for testing; use gzip for the + * real thing. On MSDOS, use only on file names without extension + * or in pipe mode. + */ + +/* @(#) $Id$ */ + +#include "zlib.h" +#include + +#ifdef STDC +# include +# include +#endif + +#ifdef USE_MMAP +# include +# include +# include +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +# include +# include +# ifdef UNDER_CE +# include +# endif +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#ifdef VMS +# define unlink delete +# define GZ_SUFFIX "-gz" +#endif +#ifdef RISCOS +# define unlink remove +# define GZ_SUFFIX "-gz" +# define fileno(file) file->__file +#endif +#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fileno */ +#endif + +#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) +#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ + extern int unlink OF((const char *)); +#endif +#endif + +#if defined(UNDER_CE) +# include +# define perror(s) pwinerror(s) + +/* Map the Windows error number in ERROR to a locale-dependent error + message string and return a pointer to it. Typically, the values + for ERROR come from GetLastError. + + The string pointed to shall not be modified by the application, + but may be overwritten by a subsequent call to strwinerror + + The strwinerror function does not change the current setting + of GetLastError. */ + +static char *strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +static void pwinerror (s) + const char *s; +{ + if (s && *s) + fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); + else + fprintf(stderr, "%s\n", strwinerror(GetLastError ())); +} + +#endif /* UNDER_CE */ + +#ifndef GZ_SUFFIX +# define GZ_SUFFIX ".gz" +#endif +#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) + +#define BUFLEN 16384 +#define MAX_NAME_LEN 1024 + +#ifdef MAXSEG_64K +# define local static + /* Needed for systems with limitation on stack size. */ +#else +# define local +#endif + +char *prog; + +void error OF((const char *msg)); +void gz_compress OF((FILE *in, gzFile out)); +#ifdef USE_MMAP +int gz_compress_mmap OF((FILE *in, gzFile out)); +#endif +void gz_uncompress OF((gzFile in, FILE *out)); +void file_compress OF((char *file, char *mode)); +void file_uncompress OF((char *file)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Display error message and exit + */ +void error(msg) + const char *msg; +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + +/* =========================================================================== + * Compress input to output then close both files. + */ + +void gz_compress(in, out) + FILE *in; + gzFile out; +{ + local char buf[BUFLEN]; + int len; + int err; + +#ifdef USE_MMAP + /* Try first compressing with mmap. If mmap fails (minigzip used in a + * pipe), use the normal fread loop. + */ + if (gz_compress_mmap(in, out) == Z_OK) return; +#endif + for (;;) { + len = (int)fread(buf, 1, sizeof(buf), in); + if (ferror(in)) { + perror("fread"); + exit(1); + } + if (len == 0) break; + + if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); + } + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); +} + +#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ + +/* Try compressing the input file at once using mmap. Return Z_OK if + * if success, Z_ERRNO otherwise. + */ +int gz_compress_mmap(in, out) + FILE *in; + gzFile out; +{ + int len; + int err; + int ifd = fileno(in); + caddr_t buf; /* mmap'ed buffer for the entire input file */ + off_t buf_len; /* length of the input file */ + struct stat sb; + + /* Determine the size of the file, needed for mmap: */ + if (fstat(ifd, &sb) < 0) return Z_ERRNO; + buf_len = sb.st_size; + if (buf_len <= 0) return Z_ERRNO; + + /* Now do the actual mmap: */ + buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); + if (buf == (caddr_t)(-1)) return Z_ERRNO; + + /* Compress the whole file at once: */ + len = gzwrite(out, (char *)buf, (unsigned)buf_len); + + if (len != (int)buf_len) error(gzerror(out, &err)); + + munmap(buf, buf_len); + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); + return Z_OK; +} +#endif /* USE_MMAP */ + +/* =========================================================================== + * Uncompress input to output then close both files. + */ +void gz_uncompress(in, out) + gzFile in; + FILE *out; +{ + local char buf[BUFLEN]; + int len; + int err; + + for (;;) { + len = gzread(in, buf, sizeof(buf)); + if (len < 0) error (gzerror(in, &err)); + if (len == 0) break; + + if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { + error("failed fwrite"); + } + } + if (fclose(out)) error("failed fclose"); + + if (gzclose(in) != Z_OK) error("failed gzclose"); +} + + +/* =========================================================================== + * Compress the given file: create a corresponding .gz file and remove the + * original. + */ +void file_compress(file, mode) + char *file; + char *mode; +{ + local char outfile[MAX_NAME_LEN]; + FILE *in; + gzFile out; + + if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + + strcpy(outfile, file); + strcat(outfile, GZ_SUFFIX); + + in = fopen(file, "rb"); + if (in == NULL) { + perror(file); + exit(1); + } + out = gzopen(outfile, mode); + if (out == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); + exit(1); + } + gz_compress(in, out); + + unlink(file); +} + + +/* =========================================================================== + * Uncompress the given file and remove the original. + */ +void file_uncompress(file) + char *file; +{ + local char buf[MAX_NAME_LEN]; + char *infile, *outfile; + FILE *out; + gzFile in; + size_t len = strlen(file); + + if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + + strcpy(buf, file); + + if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { + infile = file; + outfile = buf; + outfile[len-3] = '\0'; + } else { + outfile = file; + infile = buf; + strcat(infile, GZ_SUFFIX); + } + in = gzopen(infile, "rb"); + if (in == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); + exit(1); + } + out = fopen(outfile, "wb"); + if (out == NULL) { + perror(file); + exit(1); + } + + gz_uncompress(in, out); + + unlink(infile); +} + + +/* =========================================================================== + * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] + * -c : write to standard output + * -d : decompress + * -f : compress with Z_FILTERED + * -h : compress with Z_HUFFMAN_ONLY + * -r : compress with Z_RLE + * -1 to -9 : compression level + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + int copyout = 0; + int uncompr = 0; + gzFile file; + char *bname, outmode[20]; + + strcpy(outmode, "wb6 "); + + prog = argv[0]; + bname = strrchr(argv[0], '/'); + if (bname) + bname++; + else + bname = argv[0]; + argc--, argv++; + + if (!strcmp(bname, "gunzip")) + uncompr = 1; + else if (!strcmp(bname, "zcat")) + copyout = uncompr = 1; + + while (argc > 0) { + if (strcmp(*argv, "-c") == 0) + copyout = 1; + else if (strcmp(*argv, "-d") == 0) + uncompr = 1; + else if (strcmp(*argv, "-f") == 0) + outmode[3] = 'f'; + else if (strcmp(*argv, "-h") == 0) + outmode[3] = 'h'; + else if (strcmp(*argv, "-r") == 0) + outmode[3] = 'R'; + else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && + (*argv)[2] == 0) + outmode[2] = (*argv)[1]; + else + break; + argc--, argv++; + } + if (outmode[3] == ' ') + outmode[3] = 0; + if (argc == 0) { + SET_BINARY_MODE(stdin); + SET_BINARY_MODE(stdout); + if (uncompr) { + file = gzdopen(fileno(stdin), "rb"); + if (file == NULL) error("can't gzdopen stdin"); + gz_uncompress(file, stdout); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + gz_compress(stdin, file); + } + } else { + if (copyout) { + SET_BINARY_MODE(stdout); + } + do { + if (uncompr) { + if (copyout) { + file = gzopen(*argv, "rb"); + if (file == NULL) + fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); + else + gz_uncompress(file, stdout); + } else { + file_uncompress(*argv); + } + } else { + if (copyout) { + FILE * in = fopen(*argv, "rb"); + + if (in == NULL) { + perror(*argv); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + + gz_compress(in, file); + } + + } else { + file_compress(*argv, outmode); + } + } + } while (argv++, --argc); + } + return 0; +} diff --git a/astroem/zee.js/post.js b/astroem/zee.js/post.js new file mode 100644 index 00000000..21a40e30 --- /dev/null +++ b/astroem/zee.js/post.js @@ -0,0 +1,38 @@ + +Module['gzcompress'] = function(data) { // TODO: Accept strings + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['output.gz', 'wb']); + var buffer = _malloc(data.length); + HEAPU8.set(data, buffer); + ccall('gzwrite', 'number', ['number', 'number', 'number'], [gzFile, buffer, data.length]); + ccall('gzclose', 'number', ['number'], [gzFile]); + _free(buffer); + var ret = new Uint8Array(FS.root.contents['output.gz'].contents); + FS.deleteFile('output.gz'); + return ret; +}; + +Module['gzdecompress'] = function(data) { + var BUFSIZE = 1024*1024; + FS.createDataFile('/', 'input.gz', data, true, true); + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['input.gz', 'rb']); + var buffer = _malloc(BUFSIZE); + var chunks = []; + var total = 0; + var len; + while( (len = ccall('gzread', 'number', ['number', 'number', 'number'], [gzFile, buffer, BUFSIZE])) > 0) { + chunks.push(new Uint8Array(len)); + chunks[chunks.length-1].set(HEAPU8.subarray(buffer, buffer+len)); + total += len; + } + ccall('gzclose', 'number', ['number'], [gzFile]); + FS.deleteFile('input.gz'); + _free(buffer); + var ret = new Uint8Array(total); + var curr = 0; + for (var i = 0; i < chunks.length; i++) { + ret.set(chunks[i], curr); + curr += chunks[i].length; + } + return ret; +}; + diff --git a/astroem/zee.js/pre.js b/astroem/zee.js/pre.js new file mode 100644 index 00000000..26b35ed8 --- /dev/null +++ b/astroem/zee.js/pre.js @@ -0,0 +1,5 @@ + +var Module = { + 'noExitRuntime': true +}; + diff --git a/astroem/zee.js/readme.txt b/astroem/zee.js/readme.txt new file mode 100644 index 00000000..9a628e4a --- /dev/null +++ b/astroem/zee.js/readme.txt @@ -0,0 +1,10 @@ +This is zlib 1.2.5. See README for licensing info. + +Changes for emscripten: + + deflate.c: Initialize match_start to 0, to prevent a SAFE_HEAP notification + Initialize s->prev's buffer (in 2 places) to 0, same reasons + + example.c: Use %d instead of %x in version number printout + Comment out gzio test + diff --git a/astroem/zee.js/shell-post.js b/astroem/zee.js/shell-post.js new file mode 100644 index 00000000..10b82bfb --- /dev/null +++ b/astroem/zee.js/shell-post.js @@ -0,0 +1,7 @@ + + return { + compress: Module['gzcompress'], + decompress: Module['gzdecompress'] + }; +})(); + diff --git a/astroem/zee.js/shell-pre.js b/astroem/zee.js/shell-pre.js new file mode 100644 index 00000000..28c75f6b --- /dev/null +++ b/astroem/zee.js/shell-pre.js @@ -0,0 +1,5 @@ + +// zee.js: zlib compiled to js + +var Zee = (function() { + diff --git a/astroem/zee.js/test.js b/astroem/zee.js/test.js new file mode 100644 index 00000000..0db4a30b --- /dev/null +++ b/astroem/zee.js/test.js @@ -0,0 +1,91 @@ +// js -m -n -e "load('zee.fast.js')" test.js + +load('zee.js'); + +/* +var data = [100, 200, 200, 200, 200, 200, 200, 100, 100, 200, 200, 200, 200, 0, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1]; +print('original: ' + data + ' : ' + data.length); + +var compressed = Zee.compress(data); +print('compressed: ' + compressed.length); + +var uncompressed = Zee.uncompress(compressed); +print('decompressed: ' + uncompressed.length); +*/ + +function assertEq(a, b) { + if (a !== b) { + throw 'Should have been equal: ' + a + ' : ' + b; + } + return false; +} + +function assertNeq(a, b) { + try { + assertEq(a, b); + } catch(e) { + return; + } + throw 'Should have not been equal: ' + a + ' : ' + b; +} + +function byteCompare(a, b) { + assertEq(a.length, b.length); + for (var i = 0; i < a.length; i++) { + assertEq(a[i]&255, b[i]&255); + } +} + +function testSimple() { + print('testing simple..'); + var data = [100, 200, 200, 200, 200, 200, 200, 100, 100, 200, 200, 200, 200, 0, 1]; + var compressed = Zee.compress(data); + var decompressed = Zee.decompress(compressed); + + byteCompare(data, decompressed); + assertNeq(data.length, compressed.length); +} + +function testBig() { + print('testing big..'); + var seed1 = 100; + var seed2 = 200; + var last = 255; + function fakeRandom() { + // numbers from http://triptico.com/docs/sp_random.html + seed1 = ((seed1 * 58321) + 11113) | 0; + var ret = (seed1 >> 16) & 255; + seed2 = ((seed2 * 58321) + 11113) | 0; + if (seed2 % 5) { + return last; + } + last = ret; + return last; + } + print(' ..generating data..'); + var size = 1*1024*1024; + var data = new Array(size); + for (var i = 0; i < size; i++) { + data[i] = fakeRandom(); + } + + print(' ..compressing ' + data.length + ' bytes..'); + var t = Date.now(); + var compressed = Zee.compress(data); + print(' ..took ' + ((Date.now() - t)/1000).toFixed(2) + ' secs'); + print(' ..decompressing ' + compressed.length + ' bytes..'); + t = Date.now(); + var decompressed = Zee.decompress(compressed); + print(' ..took ' + ((Date.now() - t)/1000).toFixed(2) + ' secs'); + print(' ..got ' + decompressed.length + ' bytes..'); + + byteCompare(data, decompressed); + assertNeq(data.length, compressed.length); + print(' ..decompressed == original'); +} + +testSimple(); +testBig(); + +print('ok.'); + diff --git a/astroem/zee.js/trees.c b/astroem/zee.js/trees.c new file mode 100644 index 00000000..56e9bb1c --- /dev/null +++ b/astroem/zee.js/trees.c @@ -0,0 +1,1244 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2010 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local int detect_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void ZLIB_INTERNAL _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void ZLIB_INTERNAL _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+last, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+last, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ZLIB_INTERNAL _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(s) + deflate_state *s; +{ + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/astroem/zee.js/trees.h b/astroem/zee.js/trees.h new file mode 100644 index 00000000..d35639d8 --- /dev/null +++ b/astroem/zee.js/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/astroem/zee.js/uncompr.c b/astroem/zee.js/uncompr.c new file mode 100644 index 00000000..ad98be3a --- /dev/null +++ b/astroem/zee.js/uncompr.c @@ -0,0 +1,59 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/astroem/zee.js/worker.js b/astroem/zee.js/worker.js new file mode 100644 index 00000000..94c2a8ee --- /dev/null +++ b/astroem/zee.js/worker.js @@ -0,0 +1,12 @@ + +onmessage = function(msg) { + var start = Date.now(); + var data = Zee.decompress(new Uint8Array(msg.data.data)); + postMessage({ + filename: msg.data.filename, + data: data, + callbackID: msg.data.callbackID, + time: Date.now() - start + }); +}; + diff --git a/astroem/zee.js/zconf.h b/astroem/zee.js/zconf.h new file mode 100644 index 00000000..b2343874 --- /dev/null +++ b/astroem/zee.js/zconf.h @@ -0,0 +1,428 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define uncompress z_uncompress +# define zError z_zError +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 1 /* was set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef STDC +# include /* for off_t */ +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define z_off64_t off64_t +#else +# define z_off64_t z_off_t +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/astroem/zee.js/zconf.h.in b/astroem/zee.js/zconf.h.in new file mode 100644 index 00000000..02ce56c4 --- /dev/null +++ b/astroem/zee.js/zconf.h.in @@ -0,0 +1,428 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define uncompress z_uncompress +# define zError z_zError +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef STDC +# include /* for off_t */ +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define z_off64_t off64_t +#else +# define z_off64_t z_off_t +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/astroem/zee.js/zee-client.js b/astroem/zee.js/zee-client.js new file mode 100644 index 00000000..27186f00 --- /dev/null +++ b/astroem/zee.js/zee-client.js @@ -0,0 +1,20 @@ + +var zeeWorker = new Worker('zee-worker.js'); + +var zeeCallbacks = []; + +zeeWorker.onmessage = function(msg) { + zeeCallbacks[msg.data.callbackID](msg.data.data); + console.log("zee'd " + msg.data.filename + ' in ' + msg.data.time + ' ms, ' + msg.data.data.length + ' bytes'); + zeeCallbacks[msg.data.callbackID] = null; +}; + +function requestZee(filename, data, callback) { + zeeWorker.postMessage({ + filename: filename, + data: new Uint8Array(data), // do not send over the underlying ArrayBuffer + callbackID: zeeCallbacks.length + }); + zeeCallbacks.push(callback); +} + diff --git a/astroem/zee.js/zee-worker.js b/astroem/zee.js/zee-worker.js new file mode 100644 index 00000000..cabd4d6b --- /dev/null +++ b/astroem/zee.js/zee-worker.js @@ -0,0 +1,2560 @@ + +// zee.js: zlib compiled to js + +var Zee = (function() { + + +var Module = { + 'noExitRuntime': true +}; +// Note: For maximum-speed code, see "Optimizing Code" on the Emscripten wiki, https://github.com/kripken/emscripten/wiki/Optimizing-Code +// Note: Some Emscripten settings may limit the speed of the generated code. +try { + this['Module'] = Module; + Module.test; +} catch(e) { + this['Module'] = Module = {}; +} +// The environment setup code below is customized to use Module. +// *** Environment setup code *** +var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function'; +var ENVIRONMENT_IS_WEB = typeof window === 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; +if (ENVIRONMENT_IS_NODE) { + // Expose functionality in the same simple way that the shells work + // Note that we pollute the global namespace here, otherwise we break in node + Module['print'] = function(x) { + process['stdout'].write(x + '\n'); + }; + Module['printErr'] = function(x) { + process['stderr'].write(x + '\n'); + }; + var nodeFS = require('fs'); + var nodePath = require('path'); + Module['read'] = function(filename, binary) { + filename = nodePath['normalize'](filename); + var ret = nodeFS['readFileSync'](filename); + // The path is absolute if the normalized version is the same as the resolved. + if (!ret && filename != nodePath['resolve'](filename)) { + filename = path.join(__dirname, '..', 'src', filename); + ret = nodeFS['readFileSync'](filename); + } + if (ret && !binary) ret = ret.toString(); + return ret; + }; + Module['readBinary'] = function(filename) { return Module['read'](filename, true) }; + Module['load'] = function(f) { + globalEval(read(f)); + }; + if (!Module['arguments']) { + Module['arguments'] = process['argv'].slice(2); + } + module.exports = Module; +} +if (ENVIRONMENT_IS_SHELL) { + Module['print'] = print; + if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm + Module['read'] = read; + Module['readBinary'] = function(f) { + return read(f, 'binary'); + }; + if (!Module['arguments']) { + if (typeof scriptArgs != 'undefined') { + Module['arguments'] = scriptArgs; + } else if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + } + this['Module'] = Module; +} +if (ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER) { + if (!Module['print']) { + Module['print'] = function(x) { + console.log(x); + }; + } + if (!Module['printErr']) { + Module['printErr'] = function(x) { + console.log(x); + }; + } + this['Module'] = Module; +} +if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + Module['read'] = function(url) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + }; + if (!Module['arguments']) { + if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + } +} +if (ENVIRONMENT_IS_WORKER) { + // We can do very little here... + var TRY_USE_DUMP = false; + if (!Module['print']) { + Module['print'] = (TRY_USE_DUMP && (typeof(dump) !== "undefined") ? (function(x) { + dump(x); + }) : (function(x) { + // self.postMessage(x); // enable this if you want stdout to be sent as messages + })); + } + Module['load'] = importScripts; +} +if (!ENVIRONMENT_IS_WORKER && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_SHELL) { + // Unreachable because SHELL is dependant on the others + throw 'Unknown runtime environment. Where are we?'; +} +function globalEval(x) { + eval.call(null, x); +} +if (!Module['load'] == 'undefined' && Module['read']) { + Module['load'] = function(f) { + globalEval(Module['read'](f)); + }; +} +if (!Module['print']) { + Module['print'] = function(){}; +} +if (!Module['printErr']) { + Module['printErr'] = Module['print']; +} +if (!Module['arguments']) { + Module['arguments'] = []; +} +// *** Environment setup code *** +// Closure helpers +Module.print = Module['print']; +Module.printErr = Module['printErr']; +// Callbacks +if (!Module['preRun']) Module['preRun'] = []; +if (!Module['postRun']) Module['postRun'] = []; +// === Auto-generated preamble library stuff === +//======================================== +// Runtime code shared with compiler +//======================================== +var Runtime = { + stackSave: function () { + return STACKTOP; + }, + stackRestore: function (stackTop) { + STACKTOP = stackTop; + }, + forceAlign: function (target, quantum) { + quantum = quantum || 4; + if (quantum == 1) return target; + if (isNumber(target) && isNumber(quantum)) { + return Math.ceil(target/quantum)*quantum; + } else if (isNumber(quantum) && isPowerOfTwo(quantum)) { + var logg = log2(quantum); + return '((((' +target + ')+' + (quantum-1) + ')>>' + logg + ')<<' + logg + ')'; + } + return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum; + }, + isNumberType: function (type) { + return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES; + }, + isPointerType: function isPointerType(type) { + return type[type.length-1] == '*'; +}, + isStructType: function isStructType(type) { + if (isPointerType(type)) return false; + if (isArrayType(type)) return true; + if (/?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types + // See comment in isStructPointerType() + return type[0] == '%'; +}, + INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0}, + FLOAT_TYPES: {"float":0,"double":0}, + or64: function (x, y) { + var l = (x | 0) | (y | 0); + var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + and64: function (x, y) { + var l = (x | 0) & (y | 0); + var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + xor64: function (x, y) { + var l = (x | 0) ^ (y | 0); + var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + getNativeTypeSize: function (type, quantumSize) { + if (Runtime.QUANTUM_SIZE == 1) return 1; + var size = { + '%i1': 1, + '%i8': 1, + '%i16': 2, + '%i32': 4, + '%i64': 8, + "%float": 4, + "%double": 8 + }['%'+type]; // add '%' since float and double confuse Closure compiler as keys, and also spidermonkey as a compiler will remove 's from '_i8' etc + if (!size) { + if (type.charAt(type.length-1) == '*') { + size = Runtime.QUANTUM_SIZE; // A pointer + } else if (type[0] == 'i') { + var bits = parseInt(type.substr(1)); + assert(bits % 8 == 0); + size = bits/8; + } + } + return size; + }, + getNativeFieldSize: function (type) { + return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE); + }, + dedup: function dedup(items, ident) { + var seen = {}; + if (ident) { + return items.filter(function(item) { + if (seen[item[ident]]) return false; + seen[item[ident]] = true; + return true; + }); + } else { + return items.filter(function(item) { + if (seen[item]) return false; + seen[item] = true; + return true; + }); + } +}, + set: function set() { + var args = typeof arguments[0] === 'object' ? arguments[0] : arguments; + var ret = {}; + for (var i = 0; i < args.length; i++) { + ret[args[i]] = 0; + } + return ret; +}, + STACK_ALIGN: 8, + getAlignSize: function (type, size, vararg) { + // we align i64s and doubles on 64-bit boundaries, unlike x86 + if (type == 'i64' || type == 'double' || vararg) return 8; + if (!type) return Math.min(size, 8); // align structures internally to 64 bits + return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE); + }, + calculateStructAlignment: function calculateStructAlignment(type) { + type.flatSize = 0; + type.alignSize = 0; + var diffs = []; + var prev = -1; + type.flatIndexes = type.fields.map(function(field) { + var size, alignSize; + if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) { + size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s. + alignSize = Runtime.getAlignSize(field, size); + } else if (Runtime.isStructType(field)) { + size = Types.types[field].flatSize; + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } else if (field[0] == 'b') { + // bN, large number field, like a [N x i8] + size = field.substr(1)|0; + alignSize = 1; + } else { + throw 'Unclear type in struct: ' + field + ', in ' + type.name_ + ' :: ' + dump(Types.types[type.name_]); + } + if (type.packed) alignSize = 1; + type.alignSize = Math.max(type.alignSize, alignSize); + var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory + type.flatSize = curr + size; + if (prev >= 0) { + diffs.push(curr-prev); + } + prev = curr; + return curr; + }); + type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize); + if (diffs.length == 0) { + type.flatFactor = type.flatSize; + } else if (Runtime.dedup(diffs).length == 1) { + type.flatFactor = diffs[0]; + } + type.needsFlattening = (type.flatFactor != 1); + return type.flatIndexes; + }, + generateStructInfo: function (struct, typeName, offset) { + var type, alignment; + if (typeName) { + offset = offset || 0; + type = (typeof Types === 'undefined' ? Runtime.typeInfo : Types.types)[typeName]; + if (!type) return null; + if (type.fields.length != struct.length) { + printErr('Number of named fields must match the type for ' + typeName + ': possibly duplicate struct names. Cannot return structInfo'); + return null; + } + alignment = type.flatIndexes; + } else { + var type = { fields: struct.map(function(item) { return item[0] }) }; + alignment = Runtime.calculateStructAlignment(type); + } + var ret = { + __size__: type.flatSize + }; + if (typeName) { + struct.forEach(function(item, i) { + if (typeof item === 'string') { + ret[item] = alignment[i] + offset; + } else { + // embedded struct + var key; + for (var k in item) key = k; + ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]); + } + }); + } else { + struct.forEach(function(item, i) { + ret[item[1]] = alignment[i]; + }); + } + return ret; + }, + dynCall: function (sig, ptr, args) { + if (args && args.length) { + if (!args.splice) args = Array.prototype.slice.call(args); + args.splice(0, 0, ptr); + return Module['dynCall_' + sig].apply(null, args); + } else { + return Module['dynCall_' + sig].call(null, ptr); + } + }, + functionPointers: [], + addFunction: function (func) { + for (var i = 0; i < Runtime.functionPointers.length; i++) { + if (!Runtime.functionPointers[i]) { + Runtime.functionPointers[i] = func; + return 2 + 2*i; + } + } + throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; + }, + removeFunction: function (index) { + Runtime.functionPointers[(index-2)/2] = null; + }, + warnOnce: function (text) { + if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; + if (!Runtime.warnOnce.shown[text]) { + Runtime.warnOnce.shown[text] = 1; + Module.printErr(text); + } + }, + funcWrappers: {}, + getFuncWrapper: function (func, sig) { + assert(sig); + if (!Runtime.funcWrappers[func]) { + Runtime.funcWrappers[func] = function() { + return Runtime.dynCall(sig, func, arguments); + }; + } + return Runtime.funcWrappers[func]; + }, + UTF8Processor: function () { + var buffer = []; + var needed = 0; + this.processCChar = function (code) { + code = code & 0xff; + if (needed) { + buffer.push(code); + needed--; + } + if (buffer.length == 0) { + if (code < 128) return String.fromCharCode(code); + buffer.push(code); + if (code > 191 && code < 224) { + needed = 1; + } else { + needed = 2; + } + return ''; + } + if (needed > 0) return ''; + var c1 = buffer[0]; + var c2 = buffer[1]; + var c3 = buffer[2]; + var ret; + if (c1 > 191 && c1 < 224) { + ret = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)); + } else { + ret = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + } + buffer.length = 0; + return ret; + } + this.processJSString = function(string) { + string = unescape(encodeURIComponent(string)); + var ret = []; + for (var i = 0; i < string.length; i++) { + ret.push(string.charCodeAt(i)); + } + return ret; + } + }, + stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = ((((STACKTOP)+7)>>3)<<3); return ret; }, + staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = ((((STATICTOP)+7)>>3)<<3); return ret; }, + dynamicAlloc: function (size) { var ret = DYNAMICTOP;DYNAMICTOP = (DYNAMICTOP + size)|0;DYNAMICTOP = ((((DYNAMICTOP)+7)>>3)<<3); if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();; return ret; }, + alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 8))*(quantum ? quantum : 8); return ret; }, + makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+(((low)>>>(0))))+((+(((high)>>>(0))))*(+(4294967296)))) : ((+(((low)>>>(0))))+((+(((high)|(0))))*(+(4294967296))))); return ret; }, + GLOBAL_BASE: 8, + QUANTUM_SIZE: 4, + __dummy__: 0 +} +//======================================== +// Runtime essentials +//======================================== +var __THREW__ = 0; // Used in checking for thrown exceptions. +var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort() +var undef = 0; +// tempInt is used for 32-bit signed values or smaller. tempBigInt is used +// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt +var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD; +var tempI64, tempI64b; +var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9; +function abort(text) { + Module.print(text + ':\n' + (new Error).stack); + ABORT = true; + throw "Assertion: " + text; +} +function assert(condition, text) { + if (!condition) { + abort('Assertion failed: ' + text); + } +} +var globalScope = this; +// C calling interface. A convenient way to call C functions (in C files, or +// defined with extern "C"). +// +// Note: LLVM optimizations can inline and remove functions, after which you will not be +// able to call them. Closure can also do so. To avoid that, add your function to +// the exports using something like +// +// -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]' +// +// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C") +// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and +// 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit). +// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType, +// except that 'array' is not possible (there is no way for us to know the length of the array) +// @param args An array of the arguments to the function, as native JS values (as in returnType) +// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack). +// @return The return value, as a native JS value (as in returnType) +function ccall(ident, returnType, argTypes, args) { + return ccallFunc(getCFunc(ident), returnType, argTypes, args); +} +Module["ccall"] = ccall; +// Returns the C function with a specified identifier (for C++, you need to do manual name mangling) +function getCFunc(ident) { + try { + var func = globalScope['Module']['_' + ident]; // closure exported function + if (!func) func = eval('_' + ident); // explicit lookup + } catch(e) { + } + assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)'); + return func; +} +// Internal function that does a C call using a function, not an identifier +function ccallFunc(func, returnType, argTypes, args) { + var stack = 0; + function toC(value, type) { + if (type == 'string') { + if (value === null || value === undefined || value === 0) return 0; // null string + if (!stack) stack = Runtime.stackSave(); + var ret = Runtime.stackAlloc(value.length+1); + writeStringToMemory(value, ret); + return ret; + } else if (type == 'array') { + if (!stack) stack = Runtime.stackSave(); + var ret = Runtime.stackAlloc(value.length); + writeArrayToMemory(value, ret); + return ret; + } + return value; + } + function fromC(value, type) { + if (type == 'string') { + return Pointer_stringify(value); + } + assert(type != 'array'); + return value; + } + var i = 0; + var cArgs = args ? args.map(function(arg) { + return toC(arg, argTypes[i++]); + }) : []; + var ret = fromC(func.apply(null, cArgs), returnType); + if (stack) Runtime.stackRestore(stack); + return ret; +} +// Returns a native JS wrapper for a C function. This is similar to ccall, but +// returns a function you can call repeatedly in a normal way. For example: +// +// var my_function = cwrap('my_c_function', 'number', ['number', 'number']); +// alert(my_function(5, 22)); +// alert(my_function(99, 12)); +// +function cwrap(ident, returnType, argTypes) { + var func = getCFunc(ident); + return function() { + return ccallFunc(func, returnType, argTypes, Array.prototype.slice.call(arguments)); + } +} +Module["cwrap"] = cwrap; +// Sets a value in memory in a dynamic way at run-time. Uses the +// type data. This is the same as makeSetValue, except that +// makeSetValue is done at compile-time and generates the needed +// code then, whereas this function picks the right code at +// run-time. +// Note that setValue and getValue only do *aligned* writes and reads! +// Note that ccall uses JS types as for defining types, while setValue and +// getValue need LLVM types ('i8', 'i32') - this is a lower-level operation +function setValue(ptr, value, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': HEAP8[(ptr)]=value; break; + case 'i8': HEAP8[(ptr)]=value; break; + case 'i16': HEAP16[((ptr)>>1)]=value; break; + case 'i32': HEAP32[((ptr)>>2)]=value; break; + case 'i64': (tempI64 = [value>>>0,((Math.min((+(Math.floor((value)/(+(4294967296))))), (+(4294967295))))|0)>>>0],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break; + case 'float': HEAPF32[((ptr)>>2)]=value; break; + case 'double': HEAPF64[((ptr)>>3)]=value; break; + default: abort('invalid type for setValue: ' + type); + } +} +Module['setValue'] = setValue; +// Parallel to setValue. +function getValue(ptr, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': return HEAP8[(ptr)]; + case 'i8': return HEAP8[(ptr)]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': return HEAP32[((ptr)>>2)]; + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + default: abort('invalid type for setValue: ' + type); + } + return null; +} +Module['getValue'] = getValue; +var ALLOC_NORMAL = 0; // Tries to use _malloc() +var ALLOC_STACK = 1; // Lives for the duration of the current function call +var ALLOC_STATIC = 2; // Cannot be freed +var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk +var ALLOC_NONE = 4; // Do not allocate +Module['ALLOC_NORMAL'] = ALLOC_NORMAL; +Module['ALLOC_STACK'] = ALLOC_STACK; +Module['ALLOC_STATIC'] = ALLOC_STATIC; +Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC; +Module['ALLOC_NONE'] = ALLOC_NONE; +// allocate(): This is for internal use. You can use it yourself as well, but the interface +// is a little tricky (see docs right below). The reason is that it is optimized +// for multiple syntaxes to save space in generated code. So you should +// normally not use allocate(), and instead allocate memory using _malloc(), +// initialize it with setValue(), and so forth. +// @slab: An array of data, or a number. If a number, then the size of the block to allocate, +// in *bytes* (note that this is sometimes confusing: the next parameter does not +// affect this!) +// @types: Either an array of types, one for each byte (or 0 if no type at that position), +// or a single type which is used for the entire block. This only matters if there +// is initial data - if @slab is a number, then this does not matter at all and is +// ignored. +// @allocator: How to allocate memory, see ALLOC_* +function allocate(slab, types, allocator, ptr) { + var zeroinit, size; + if (typeof slab === 'number') { + zeroinit = true; + size = slab; + } else { + zeroinit = false; + size = slab.length; + } + var singleType = typeof types === 'string' ? types : null; + var ret; + if (allocator == ALLOC_NONE) { + ret = ptr; + } else { + ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); + } + if (zeroinit) { + var ptr = ret, stop; + assert((ret & 3) == 0); + stop = ret + (size & ~3); + for (; ptr < stop; ptr += 4) { + HEAP32[((ptr)>>2)]=0; + } + stop = ret + size; + while (ptr < stop) { + HEAP8[((ptr++)|0)]=0; + } + return ret; + } + if (singleType === 'i8') { + if (slab.subarray || slab.slice) { + HEAPU8.set(slab, ret); + } else { + HEAPU8.set(new Uint8Array(slab), ret); + } + return ret; + } + var i = 0, type, typeSize, previousType; + while (i < size) { + var curr = slab[i]; + if (typeof curr === 'function') { + curr = Runtime.getFunctionIndex(curr); + } + type = singleType || types[i]; + if (type === 0) { + i++; + continue; + } + if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later + setValue(ret+i, curr, type); + // no need to look up size unless type changes, so cache it + if (previousType !== type) { + typeSize = Runtime.getNativeTypeSize(type); + previousType = type; + } + i += typeSize; + } + return ret; +} +Module['allocate'] = allocate; +function Pointer_stringify(ptr, /* optional */ length) { + // Find the length, and check for UTF while doing so + var hasUtf = false; + var t; + var i = 0; + while (1) { + t = HEAPU8[(((ptr)+(i))|0)]; + if (t >= 128) hasUtf = true; + else if (t == 0 && !length) break; + i++; + if (length && i == length) break; + } + if (!length) length = i; + var ret = ''; + if (!hasUtf) { + var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack + var curr; + while (length > 0) { + curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); + ret = ret ? ret + curr : curr; + ptr += MAX_CHUNK; + length -= MAX_CHUNK; + } + return ret; + } + var utf8 = new Runtime.UTF8Processor(); + for (i = 0; i < length; i++) { + t = HEAPU8[(((ptr)+(i))|0)]; + ret += utf8.processCChar(t); + } + return ret; +} +Module['Pointer_stringify'] = Pointer_stringify; +// Memory management +var PAGE_SIZE = 4096; +function alignMemoryPage(x) { + return ((x+4095)>>12)<<12; +} +var HEAP; +var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; +var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area +var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area +var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk +function enlargeMemory() { + abort('Cannot enlarge memory arrays in asm.js. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, or (2) set Module.TOTAL_MEMORY before the program runs.'); +} +var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; +var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216; +var FAST_MEMORY = Module['FAST_MEMORY'] || 2097152; +// Initialize the runtime's memory +// check for full engine support (use string 'subarray' to avoid closure compiler confusion) +assert(!!Int32Array && !!Float64Array && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']), + 'Cannot fallback to non-typed array case: Code is too specialized'); +var buffer = new ArrayBuffer(TOTAL_MEMORY); +HEAP8 = new Int8Array(buffer); +HEAP16 = new Int16Array(buffer); +HEAP32 = new Int32Array(buffer); +HEAPU8 = new Uint8Array(buffer); +HEAPU16 = new Uint16Array(buffer); +HEAPU32 = new Uint32Array(buffer); +HEAPF32 = new Float32Array(buffer); +HEAPF64 = new Float64Array(buffer); +// Endianness check (note: assumes compiler arch was little-endian) +HEAP32[0] = 255; +assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system'); +Module['HEAP'] = HEAP; +Module['HEAP8'] = HEAP8; +Module['HEAP16'] = HEAP16; +Module['HEAP32'] = HEAP32; +Module['HEAPU8'] = HEAPU8; +Module['HEAPU16'] = HEAPU16; +Module['HEAPU32'] = HEAPU32; +Module['HEAPF32'] = HEAPF32; +Module['HEAPF64'] = HEAPF64; +function callRuntimeCallbacks(callbacks) { + while(callbacks.length > 0) { + var callback = callbacks.shift(); + if (typeof callback == 'function') { + callback(); + continue; + } + var func = callback.func; + if (typeof func === 'number') { + if (callback.arg === undefined) { + Runtime.dynCall('v', func); + } else { + Runtime.dynCall('vi', func, [callback.arg]); + } + } else { + func(callback.arg === undefined ? null : callback.arg); + } + } +} +var __ATINIT__ = []; // functions called during startup +var __ATMAIN__ = []; // functions called when main() is to be run +var __ATEXIT__ = []; // functions called during shutdown +var runtimeInitialized = false; +function ensureInitRuntime() { + if (runtimeInitialized) return; + runtimeInitialized = true; + callRuntimeCallbacks(__ATINIT__); +} +function preMain() { + callRuntimeCallbacks(__ATMAIN__); +} +function exitRuntime() { + callRuntimeCallbacks(__ATEXIT__); +} +// Tools +// This processes a JS string into a C-line array of numbers, 0-terminated. +// For LLVM-originating strings, see parser.js:parseLLVMString function +function intArrayFromString(stringy, dontAddNull, length /* optional */) { + var ret = (new Runtime.UTF8Processor()).processJSString(stringy); + if (length) { + ret.length = length; + } + if (!dontAddNull) { + ret.push(0); + } + return ret; +} +Module['intArrayFromString'] = intArrayFromString; +function intArrayToString(array) { + var ret = []; + for (var i = 0; i < array.length; i++) { + var chr = array[i]; + if (chr > 0xFF) { + chr &= 0xFF; + } + ret.push(String.fromCharCode(chr)); + } + return ret.join(''); +} +Module['intArrayToString'] = intArrayToString; +// Write a Javascript array to somewhere in the heap +function writeStringToMemory(string, buffer, dontAddNull) { + var array = intArrayFromString(string, dontAddNull); + var i = 0; + while (i < array.length) { + var chr = array[i]; + HEAP8[(((buffer)+(i))|0)]=chr + i = i + 1; + } +} +Module['writeStringToMemory'] = writeStringToMemory; +function writeArrayToMemory(array, buffer) { + for (var i = 0; i < array.length; i++) { + HEAP8[(((buffer)+(i))|0)]=array[i]; + } +} +Module['writeArrayToMemory'] = writeArrayToMemory; +function unSign(value, bits, ignore, sig) { + if (value >= 0) { + return value; + } + return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts + : Math.pow(2, bits) + value; +} +function reSign(value, bits, ignore, sig) { + if (value <= 0) { + return value; + } + var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 + : Math.pow(2, bits-1); + if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that + // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors + // TODO: In i64 mode 1, resign the two parts separately and safely + value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts + } + return value; +} +if (!Math['imul']) Math['imul'] = function(a, b) { + var ah = a >>> 16; + var al = a & 0xffff; + var bh = b >>> 16; + var bl = b & 0xffff; + return (al*bl + ((ah*bl + al*bh) << 16))|0; +}; +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// PRE_RUN_ADDITIONS (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyTracking = {}; +var calledInit = false, calledRun = false; +var runDependencyWatcher = null; +function addRunDependency(id) { + runDependencies++; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + if (id) { + assert(!runDependencyTracking[id]); + runDependencyTracking[id] = 1; + } else { + Module.printErr('warning: run dependency added without ID'); + } +} +Module['addRunDependency'] = addRunDependency; +function removeRunDependency(id) { + runDependencies--; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + if (id) { + assert(runDependencyTracking[id]); + delete runDependencyTracking[id]; + } else { + Module.printErr('warning: run dependency removed without ID'); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!calledRun && shouldRunNow) run(); + } +} +Module['removeRunDependency'] = removeRunDependency; +Module["preloadedImages"] = {}; // maps url to image data +Module["preloadedAudios"] = {}; // maps url to audio data +function addPreRun(func) { + if (!Module['preRun']) Module['preRun'] = []; + else if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + Module['preRun'].push(func); +} +function loadMemoryInitializer(filename) { + function applyData(data) { + HEAPU8.set(data, STATIC_BASE); + } + // always do this asynchronously, to keep shell and web as similar as possible + addPreRun(function() { + if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) { + applyData(Module['readBinary'](filename)); + } else { + Browser.asyncLoad(filename, function(data) { + applyData(data); + }, function(data) { + throw 'could not load memory initializer ' + filename; + }); + } + }); +} +// === Body === +STATIC_BASE = 8; +STATICTOP = STATIC_BASE + 15192; +/* global initializers */ __ATINIT__.push({ func: function() { runPostSets() } }); +/* memory initializer */ allocate([176,50,0,0,248,52,0,0,128,57,0,0,232,51,0,0,152,51,0,0,80,51,0,0,8,51,0,0,160,50,0,0,72,50,0,0,128,57,0,0,12,0,8,0,140,0,8,0,76,0,8,0,204,0,8,0,44,0,8,0,172,0,8,0,108,0,8,0,236,0,8,0,28,0,8,0,156,0,8,0,92,0,8,0,220,0,8,0,60,0,8,0,188,0,8,0,124,0,8,0,252,0,8,0,2,0,8,0,130,0,8,0,66,0,8,0,194,0,8,0,34,0,8,0,162,0,8,0,98,0,8,0,226,0,8,0,18,0,8,0,146,0,8,0,82,0,8,0,210,0,8,0,50,0,8,0,178,0,8,0,114,0,8,0,242,0,8,0,10,0,8,0,138,0,8,0,74,0,8,0,202,0,8,0,42,0,8,0,170,0,8,0,106,0,8,0,234,0,8,0,26,0,8,0,154,0,8,0,90,0,8,0,218,0,8,0,58,0,8,0,186,0,8,0,122,0,8,0,250,0,8,0,6,0,8,0,134,0,8,0,70,0,8,0,198,0,8,0,38,0,8,0,166,0,8,0,102,0,8,0,230,0,8,0,22,0,8,0,150,0,8,0,86,0,8,0,214,0,8,0,54,0,8,0,182,0,8,0,118,0,8,0,246,0,8,0,14,0,8,0,142,0,8,0,78,0,8,0,206,0,8,0,46,0,8,0,174,0,8,0,110,0,8,0,238,0,8,0,30,0,8,0,158,0,8,0,94,0,8,0,222,0,8,0,62,0,8,0,190,0,8,0,126,0,8,0,254,0,8,0,1,0,8,0,129,0,8,0,65,0,8,0,193,0,8,0,33,0,8,0,161,0,8,0,97,0,8,0,225,0,8,0,17,0,8,0,145,0,8,0,81,0,8,0,209,0,8,0,49,0,8,0,177,0,8,0,113,0,8,0,241,0,8,0,9,0,8,0,137,0,8,0,73,0,8,0,201,0,8,0,41,0,8,0,169,0,8,0,105,0,8,0,233,0,8,0,25,0,8,0,153,0,8,0,89,0,8,0,217,0,8,0,57,0,8,0,185,0,8,0,121,0,8,0,249,0,8,0,5,0,8,0,133,0,8,0,69,0,8,0,197,0,8,0,37,0,8,0,165,0,8,0,101,0,8,0,229,0,8,0,21,0,8,0,149,0,8,0,85,0,8,0,213,0,8,0,53,0,8,0,181,0,8,0,117,0,8,0,245,0,8,0,13,0,8,0,141,0,8,0,77,0,8,0,205,0,8,0,45,0,8,0,173,0,8,0,109,0,8,0,237,0,8,0,29,0,8,0,157,0,8,0,93,0,8,0,221,0,8,0,61,0,8,0,189,0,8,0,125,0,8,0,253,0,8,0,19,0,9,0,19,1,9,0,147,0,9,0,147,1,9,0,83,0,9,0,83,1,9,0,211,0,9,0,211,1,9,0,51,0,9,0,51,1,9,0,179,0,9,0,179,1,9,0,115,0,9,0,115,1,9,0,243,0,9,0,243,1,9,0,11,0,9,0,11,1,9,0,139,0,9,0,139,1,9,0,75,0,9,0,75,1,9,0,203,0,9,0,203,1,9,0,43,0,9,0,43,1,9,0,171,0,9,0,171,1,9,0,107,0,9,0,107,1,9,0,235,0,9,0,235,1,9,0,27,0,9,0,27,1,9,0,155,0,9,0,155,1,9,0,91,0,9,0,91,1,9,0,219,0,9,0,219,1,9,0,59,0,9,0,59,1,9,0,187,0,9,0,187,1,9,0,123,0,9,0,123,1,9,0,251,0,9,0,251,1,9,0,7,0,9,0,7,1,9,0,135,0,9,0,135,1,9,0,71,0,9,0,71,1,9,0,199,0,9,0,199,1,9,0,39,0,9,0,39,1,9,0,167,0,9,0,167,1,9,0,103,0,9,0,103,1,9,0,231,0,9,0,231,1,9,0,23,0,9,0,23,1,9,0,151,0,9,0,151,1,9,0,87,0,9,0,87,1,9,0,215,0,9,0,215,1,9,0,55,0,9,0,55,1,9,0,183,0,9,0,183,1,9,0,119,0,9,0,119,1,9,0,247,0,9,0,247,1,9,0,15,0,9,0,15,1,9,0,143,0,9,0,143,1,9,0,79,0,9,0,79,1,9,0,207,0,9,0,207,1,9,0,47,0,9,0,47,1,9,0,175,0,9,0,175,1,9,0,111,0,9,0,111,1,9,0,239,0,9,0,239,1,9,0,31,0,9,0,31,1,9,0,159,0,9,0,159,1,9,0,95,0,9,0,95,1,9,0,223,0,9,0,223,1,9,0,63,0,9,0,63,1,9,0,191,0,9,0,191,1,9,0,127,0,9,0,127,1,9,0,255,0,9,0,255,1,9,0,0,0,7,0,64,0,7,0,32,0,7,0,96,0,7,0,16,0,7,0,80,0,7,0,48,0,7,0,112,0,7,0,8,0,7,0,72,0,7,0,40,0,7,0,104,0,7,0,24,0,7,0,88,0,7,0,56,0,7,0,120,0,7,0,4,0,7,0,68,0,7,0,36,0,7,0,100,0,7,0,20,0,7,0,84,0,7,0,52,0,7,0,116,0,7,0,3,0,8,0,131,0,8,0,67,0,8,0,195,0,8,0,35,0,8,0,163,0,8,0,99,0,8,0,227,0,8,0,48,0,0,0,40,15,0,0,1,1,0,0,30,1,0,0,15,0,0,0,0,0,0,0,0,0,5,0,16,0,5,0,8,0,5,0,24,0,5,0,4,0,5,0,20,0,5,0,12,0,5,0,28,0,5,0,2,0,5,0,18,0,5,0,10,0,5,0,26,0,5,0,6,0,5,0,22,0,5,0,14,0,5,0,30,0,5,0,1,0,5,0,17,0,5,0,9,0,5,0,25,0,5,0,5,0,5,0,21,0,5,0,13,0,5,0,29,0,5,0,3,0,5,0,19,0,5,0,11,0,5,0,27,0,5,0,7,0,5,0,23,0,5,0,200,4,0,0,160,15,0,0,0,0,0,0,30,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,24,16,0,0,0,0,0,0,19,0,0,0,7,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,4,0,0,0,2,0,0,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,17,0,17,0,17,0,17,0,18,0,18,0,18,0,18,0,19,0,19,0,19,0,19,0,20,0,20,0,20,0,20,0,21,0,21,0,21,0,21,0,16,0,73,0,195,0,0,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,13,0,15,0,17,0,19,0,23,0,27,0,31,0,35,0,43,0,51,0,59,0,67,0,83,0,99,0,115,0,131,0,163,0,195,0,227,0,2,1,0,0,0,0,0,0,16,0,16,0,16,0,16,0,17,0,17,0,18,0,18,0,19,0,19,0,20,0,20,0,21,0,21,0,22,0,22,0,23,0,23,0,24,0,24,0,25,0,25,0,26,0,26,0,27,0,27,0,28,0,28,0,29,0,29,0,64,0,64,0,1,0,2,0,3,0,4,0,5,0,7,0,9,0,13,0,17,0,25,0,33,0,49,0,65,0,97,0,129,0,193,0,1,1,129,1,1,2,1,3,1,4,1,6,1,8,1,12,1,16,1,24,1,32,1,48,1,64,1,96,0,0,0,0,16,0,17,0,18,0,0,0,8,0,7,0,9,0,6,0,10,0,5,0,11,0,4,0,12,0,3,0,13,0,2,0,14,0,1,0,15,0,0,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,192,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,160,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,224,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,144,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,208,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,176,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,240,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,200,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,168,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,232,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,152,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,216,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,184,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,248,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,196,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,164,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,228,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,148,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,212,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,180,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,244,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,204,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,172,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,236,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,156,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,220,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,188,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,252,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,194,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,162,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,226,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,146,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,210,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,178,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,242,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,202,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,170,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,234,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,154,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,218,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,186,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,250,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,198,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,166,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,230,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,150,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,214,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,182,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,246,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,206,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,174,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,238,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,158,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,222,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,190,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,254,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,193,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,161,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,225,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,145,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,209,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,177,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,241,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,201,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,169,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,233,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,153,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,217,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,185,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,249,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,197,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,165,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,229,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,149,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,213,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,181,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,245,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,205,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,173,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,237,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,157,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,221,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,189,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,253,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,195,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,163,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,227,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,147,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,211,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,179,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,243,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,203,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,171,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,235,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,155,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,219,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,187,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,251,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,199,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,167,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,231,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,151,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,215,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,183,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,247,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,207,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,175,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,239,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,159,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,223,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,191,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,255,0,16,5,1,0,23,5,1,1,19,5,17,0,27,5,1,16,17,5,5,0,25,5,1,4,21,5,65,0,29,5,1,64,16,5,3,0,24,5,1,2,20,5,33,0,28,5,1,32,18,5,9,0,26,5,1,8,22,5,129,0,64,5,0,0,16,5,2,0,23,5,129,1,19,5,25,0,27,5,1,24,17,5,7,0,25,5,1,6,21,5,97,0,29,5,1,96,16,5,4,0,24,5,1,3,20,5,49,0,28,5,1,48,18,5,13,0,26,5,1,12,22,5,193,0,64,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,6,0,0,0,6,0,0,0,7,0,0,0,7,0,0,0,8,0,0,0,8,0,0,0,9,0,0,0,9,0,0,0,10,0,0,0,10,0,0,0,11,0,0,0,11,0,0,0,12,0,0,0,12,0,0,0,13,0,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,150,48,7,119,44,97,14,238,186,81,9,153,25,196,109,7,143,244,106,112,53,165,99,233,163,149,100,158,50,136,219,14,164,184,220,121,30,233,213,224,136,217,210,151,43,76,182,9,189,124,177,126,7,45,184,231,145,29,191,144,100,16,183,29,242,32,176,106,72,113,185,243,222,65,190,132,125,212,218,26,235,228,221,109,81,181,212,244,199,133,211,131,86,152,108,19,192,168,107,100,122,249,98,253,236,201,101,138,79,92,1,20,217,108,6,99,99,61,15,250,245,13,8,141,200,32,110,59,94,16,105,76,228,65,96,213,114,113,103,162,209,228,3,60,71,212,4,75,253,133,13,210,107,181,10,165,250,168,181,53,108,152,178,66,214,201,187,219,64,249,188,172,227,108,216,50,117,92,223,69,207,13,214,220,89,61,209,171,172,48,217,38,58,0,222,81,128,81,215,200,22,97,208,191,181,244,180,33,35,196,179,86,153,149,186,207,15,165,189,184,158,184,2,40,8,136,5,95,178,217,12,198,36,233,11,177,135,124,111,47,17,76,104,88,171,29,97,193,61,45,102,182,144,65,220,118,6,113,219,1,188,32,210,152,42,16,213,239,137,133,177,113,31,181,182,6,165,228,191,159,51,212,184,232,162,201,7,120,52,249,0,15,142,168,9,150,24,152,14,225,187,13,106,127,45,61,109,8,151,108,100,145,1,92,99,230,244,81,107,107,98,97,108,28,216,48,101,133,78,0,98,242,237,149,6,108,123,165,1,27,193,244,8,130,87,196,15,245,198,217,176,101,80,233,183,18,234,184,190,139,124,136,185,252,223,29,221,98,73,45,218,21,243,124,211,140,101,76,212,251,88,97,178,77,206,81,181,58,116,0,188,163,226,48,187,212,65,165,223,74,215,149,216,61,109,196,209,164,251,244,214,211,106,233,105,67,252,217,110,52,70,136,103,173,208,184,96,218,115,45,4,68,229,29,3,51,95,76,10,170,201,124,13,221,60,113,5,80,170,65,2,39,16,16,11,190,134,32,12,201,37,181,104,87,179,133,111,32,9,212,102,185,159,228,97,206,14,249,222,94,152,201,217,41,34,152,208,176,180,168,215,199,23,61,179,89,129,13,180,46,59,92,189,183,173,108,186,192,32,131,184,237,182,179,191,154,12,226,182,3,154,210,177,116,57,71,213,234,175,119,210,157,21,38,219,4,131,22,220,115,18,11,99,227,132,59,100,148,62,106,109,13,168,90,106,122,11,207,14,228,157,255,9,147,39,174,0,10,177,158,7,125,68,147,15,240,210,163,8,135,104,242,1,30,254,194,6,105,93,87,98,247,203,103,101,128,113,54,108,25,231,6,107,110,118,27,212,254,224,43,211,137,90,122,218,16,204,74,221,103,111,223,185,249,249,239,190,142,67,190,183,23,213,142,176,96,232,163,214,214,126,147,209,161,196,194,216,56,82,242,223,79,241,103,187,209,103,87,188,166,221,6,181,63,75,54,178,72,218,43,13,216,76,27,10,175,246,74,3,54,96,122,4,65,195,239,96,223,85,223,103,168,239,142,110,49,121,190,105,70,140,179,97,203,26,131,102,188,160,210,111,37,54,226,104,82,149,119,12,204,3,71,11,187,185,22,2,34,47,38,5,85,190,59,186,197,40,11,189,178,146,90,180,43,4,106,179,92,167,255,215,194,49,207,208,181,139,158,217,44,29,174,222,91,176,194,100,155,38,242,99,236,156,163,106,117,10,147,109,2,169,6,9,156,63,54,14,235,133,103,7,114,19,87,0,5,130,74,191,149,20,122,184,226,174,43,177,123,56,27,182,12,155,142,210,146,13,190,213,229,183,239,220,124,33,223,219,11,212,210,211,134,66,226,212,241,248,179,221,104,110,131,218,31,205,22,190,129,91,38,185,246,225,119,176,111,119,71,183,24,230,90,8,136,112,106,15,255,202,59,6,102,92,11,1,17,255,158,101,143,105,174,98,248,211,255,107,97,69,207,108,22,120,226,10,160,238,210,13,215,84,131,4,78,194,179,3,57,97,38,103,167,247,22,96,208,77,71,105,73,219,119,110,62,74,106,209,174,220,90,214,217,102,11,223,64,240,59,216,55,83,174,188,169,197,158,187,222,127,207,178,71,233,255,181,48,28,242,189,189,138,194,186,202,48,147,179,83,166,163,180,36,5,54,208,186,147,6,215,205,41,87,222,84,191,103,217,35,46,122,102,179,184,74,97,196,2,27,104,93,148,43,111,42,55,190,11,180,161,142,12,195,27,223,5,90,141,239,2,45,0,0,0,0,65,49,27,25,130,98,54,50,195,83,45,43,4,197,108,100,69,244,119,125,134,167,90,86,199,150,65,79,8,138,217,200,73,187,194,209,138,232,239,250,203,217,244,227,12,79,181,172,77,126,174,181,142,45,131,158,207,28,152,135,81,18,194,74,16,35,217,83,211,112,244,120,146,65,239,97,85,215,174,46,20,230,181,55,215,181,152,28,150,132,131,5,89,152,27,130,24,169,0,155,219,250,45,176,154,203,54,169,93,93,119,230,28,108,108,255,223,63,65,212,158,14,90,205,162,36,132,149,227,21,159,140,32,70,178,167,97,119,169,190,166,225,232,241,231,208,243,232,36,131,222,195,101,178,197,218,170,174,93,93,235,159,70,68,40,204,107,111,105,253,112,118,174,107,49,57,239,90,42,32,44,9,7,11,109,56,28,18,243,54,70,223,178,7,93,198,113,84,112,237,48,101,107,244,247,243,42,187,182,194,49,162,117,145,28,137,52,160,7,144,251,188,159,23,186,141,132,14,121,222,169,37,56,239,178,60,255,121,243,115,190,72,232,106,125,27,197,65,60,42,222,88,5,79,121,240,68,126,98,233,135,45,79,194,198,28,84,219,1,138,21,148,64,187,14,141,131,232,35,166,194,217,56,191,13,197,160,56,76,244,187,33,143,167,150,10,206,150,141,19,9,0,204,92,72,49,215,69,139,98,250,110,202,83,225,119,84,93,187,186,21,108,160,163,214,63,141,136,151,14,150,145,80,152,215,222,17,169,204,199,210,250,225,236,147,203,250,245,92,215,98,114,29,230,121,107,222,181,84,64,159,132,79,89,88,18,14,22,25,35,21,15,218,112,56,36,155,65,35,61,167,107,253,101,230,90,230,124,37,9,203,87,100,56,208,78,163,174,145,1,226,159,138,24,33,204,167,51,96,253,188,42,175,225,36,173,238,208,63,180,45,131,18,159,108,178,9,134,171,36,72,201,234,21,83,208,41,70,126,251,104,119,101,226,246,121,63,47,183,72,36,54,116,27,9,29,53,42,18,4,242,188,83,75,179,141,72,82,112,222,101,121,49,239,126,96,254,243,230,231,191,194,253,254,124,145,208,213,61,160,203,204,250,54,138,131,187,7,145,154,120,84,188,177,57,101,167,168,75,152,131,59,10,169,152,34,201,250,181,9,136,203,174,16,79,93,239,95,14,108,244,70,205,63,217,109,140,14,194,116,67,18,90,243,2,35,65,234,193,112,108,193,128,65,119,216,71,215,54,151,6,230,45,142,197,181,0,165,132,132,27,188,26,138,65,113,91,187,90,104,152,232,119,67,217,217,108,90,30,79,45,21,95,126,54,12,156,45,27,39,221,28,0,62,18,0,152,185,83,49,131,160,144,98,174,139,209,83,181,146,22,197,244,221,87,244,239,196,148,167,194,239,213,150,217,246,233,188,7,174,168,141,28,183,107,222,49,156,42,239,42,133,237,121,107,202,172,72,112,211,111,27,93,248,46,42,70,225,225,54,222,102,160,7,197,127,99,84,232,84,34,101,243,77,229,243,178,2,164,194,169,27,103,145,132,48,38,160,159,41,184,174,197,228,249,159,222,253,58,204,243,214,123,253,232,207,188,107,169,128,253,90,178,153,62,9,159,178,127,56,132,171,176,36,28,44,241,21,7,53,50,70,42,30,115,119,49,7,180,225,112,72,245,208,107,81,54,131,70,122,119,178,93,99,78,215,250,203,15,230,225,210,204,181,204,249,141,132,215,224,74,18,150,175,11,35,141,182,200,112,160,157,137,65,187,132,70,93,35,3,7,108,56,26,196,63,21,49,133,14,14,40,66,152,79,103,3,169,84,126,192,250,121,85,129,203,98,76,31,197,56,129,94,244,35,152,157,167,14,179,220,150,21,170,27,0,84,229,90,49,79,252,153,98,98,215,216,83,121,206,23,79,225,73,86,126,250,80,149,45,215,123,212,28,204,98,19,138,141,45,82,187,150,52,145,232,187,31,208,217,160,6,236,243,126,94,173,194,101,71,110,145,72,108,47,160,83,117,232,54,18,58,169,7,9,35,106,84,36,8,43,101,63,17,228,121,167,150,165,72,188,143,102,27,145,164,39,42,138,189,224,188,203,242,161,141,208,235,98,222,253,192,35,239,230,217,189,225,188,20,252,208,167,13,63,131,138,38,126,178,145,63,185,36,208,112,248,21,203,105,59,70,230,66,122,119,253,91,181,107,101,220,244,90,126,197,55,9,83,238,118,56,72,247,177,174,9,184,240,159,18,161,51,204,63,138,114,253,36,147,0,0,0,0,55,106,194,1,110,212,132,3,89,190,70,2,220,168,9,7,235,194,203,6,178,124,141,4,133,22,79,5,184,81,19,14,143,59,209,15,214,133,151,13,225,239,85,12,100,249,26,9,83,147,216,8,10,45,158,10,61,71,92,11,112,163,38,28,71,201,228,29,30,119,162,31,41,29,96,30,172,11,47,27,155,97,237,26,194,223,171,24,245,181,105,25,200,242,53,18,255,152,247,19,166,38,177,17,145,76,115,16,20,90,60,21,35,48,254,20,122,142,184,22,77,228,122,23,224,70,77,56,215,44,143,57,142,146,201,59,185,248,11,58,60,238,68,63,11,132,134,62,82,58,192,60,101,80,2,61,88,23,94,54,111,125,156,55,54,195,218,53,1,169,24,52,132,191,87,49,179,213,149,48,234,107,211,50,221,1,17,51,144,229,107,36,167,143,169,37,254,49,239,39,201,91,45,38,76,77,98,35,123,39,160,34,34,153,230,32,21,243,36,33,40,180,120,42,31,222,186,43,70,96,252,41,113,10,62,40,244,28,113,45,195,118,179,44,154,200,245,46,173,162,55,47,192,141,154,112,247,231,88,113,174,89,30,115,153,51,220,114,28,37,147,119,43,79,81,118,114,241,23,116,69,155,213,117,120,220,137,126,79,182,75,127,22,8,13,125,33,98,207,124,164,116,128,121,147,30,66,120,202,160,4,122,253,202,198,123,176,46,188,108,135,68,126,109,222,250,56,111,233,144,250,110,108,134,181,107,91,236,119,106,2,82,49,104,53,56,243,105,8,127,175,98,63,21,109,99,102,171,43,97,81,193,233,96,212,215,166,101,227,189,100,100,186,3,34,102,141,105,224,103,32,203,215,72,23,161,21,73,78,31,83,75,121,117,145,74,252,99,222,79,203,9,28,78,146,183,90,76,165,221,152,77,152,154,196,70,175,240,6,71,246,78,64,69,193,36,130,68,68,50,205,65,115,88,15,64,42,230,73,66,29,140,139,67,80,104,241,84,103,2,51,85,62,188,117,87,9,214,183,86,140,192,248,83,187,170,58,82,226,20,124,80,213,126,190,81,232,57,226,90,223,83,32,91,134,237,102,89,177,135,164,88,52,145,235,93,3,251,41,92,90,69,111,94,109,47,173,95,128,27,53,225,183,113,247,224,238,207,177,226,217,165,115,227,92,179,60,230,107,217,254,231,50,103,184,229,5,13,122,228,56,74,38,239,15,32,228,238,86,158,162,236,97,244,96,237,228,226,47,232,211,136,237,233,138,54,171,235,189,92,105,234,240,184,19,253,199,210,209,252,158,108,151,254,169,6,85,255,44,16,26,250,27,122,216,251,66,196,158,249,117,174,92,248,72,233,0,243,127,131,194,242,38,61,132,240,17,87,70,241,148,65,9,244,163,43,203,245,250,149,141,247,205,255,79,246,96,93,120,217,87,55,186,216,14,137,252,218,57,227,62,219,188,245,113,222,139,159,179,223,210,33,245,221,229,75,55,220,216,12,107,215,239,102,169,214,182,216,239,212,129,178,45,213,4,164,98,208,51,206,160,209,106,112,230,211,93,26,36,210,16,254,94,197,39,148,156,196,126,42,218,198,73,64,24,199,204,86,87,194,251,60,149,195,162,130,211,193,149,232,17,192,168,175,77,203,159,197,143,202,198,123,201,200,241,17,11,201,116,7,68,204,67,109,134,205,26,211,192,207,45,185,2,206,64,150,175,145,119,252,109,144,46,66,43,146,25,40,233,147,156,62,166,150,171,84,100,151,242,234,34,149,197,128,224,148,248,199,188,159,207,173,126,158,150,19,56,156,161,121,250,157,36,111,181,152,19,5,119,153,74,187,49,155,125,209,243,154,48,53,137,141,7,95,75,140,94,225,13,142,105,139,207,143,236,157,128,138,219,247,66,139,130,73,4,137,181,35,198,136,136,100,154,131,191,14,88,130,230,176,30,128,209,218,220,129,84,204,147,132,99,166,81,133,58,24,23,135,13,114,213,134,160,208,226,169,151,186,32,168,206,4,102,170,249,110,164,171,124,120,235,174,75,18,41,175,18,172,111,173,37,198,173,172,24,129,241,167,47,235,51,166,118,85,117,164,65,63,183,165,196,41,248,160,243,67,58,161,170,253,124,163,157,151,190,162,208,115,196,181,231,25,6,180,190,167,64,182,137,205,130,183,12,219,205,178,59,177,15,179,98,15,73,177,85,101,139,176,104,34,215,187,95,72,21,186,6,246,83,184,49,156,145,185,180,138,222,188,131,224,28,189,218,94,90,191,237,52,152,190,0,0,0,0,101,103,188,184,139,200,9,170,238,175,181,18,87,151,98,143,50,240,222,55,220,95,107,37,185,56,215,157,239,40,180,197,138,79,8,125,100,224,189,111,1,135,1,215,184,191,214,74,221,216,106,242,51,119,223,224,86,16,99,88,159,87,25,80,250,48,165,232,20,159,16,250,113,248,172,66,200,192,123,223,173,167,199,103,67,8,114,117,38,111,206,205,112,127,173,149,21,24,17,45,251,183,164,63,158,208,24,135,39,232,207,26,66,143,115,162,172,32,198,176,201,71,122,8,62,175,50,160,91,200,142,24,181,103,59,10,208,0,135,178,105,56,80,47,12,95,236,151,226,240,89,133,135,151,229,61,209,135,134,101,180,224,58,221,90,79,143,207,63,40,51,119,134,16,228,234,227,119,88,82,13,216,237,64,104,191,81,248,161,248,43,240,196,159,151,72,42,48,34,90,79,87,158,226,246,111,73,127,147,8,245,199,125,167,64,213,24,192,252,109,78,208,159,53,43,183,35,141,197,24,150,159,160,127,42,39,25,71,253,186,124,32,65,2,146,143,244,16,247,232,72,168,61,88,20,155,88,63,168,35,182,144,29,49,211,247,161,137,106,207,118,20,15,168,202,172,225,7,127,190,132,96,195,6,210,112,160,94,183,23,28,230,89,184,169,244,60,223,21,76,133,231,194,209,224,128,126,105,14,47,203,123,107,72,119,195,162,15,13,203,199,104,177,115,41,199,4,97,76,160,184,217,245,152,111,68,144,255,211,252,126,80,102,238,27,55,218,86,77,39,185,14,40,64,5,182,198,239,176,164,163,136,12,28,26,176,219,129,127,215,103,57,145,120,210,43,244,31,110,147,3,247,38,59,102,144,154,131,136,63,47,145,237,88,147,41,84,96,68,180,49,7,248,12,223,168,77,30,186,207,241,166,236,223,146,254,137,184,46,70,103,23,155,84,2,112,39,236,187,72,240,113,222,47,76,201,48,128,249,219,85,231,69,99,156,160,63,107,249,199,131,211,23,104,54,193,114,15,138,121,203,55,93,228,174,80,225,92,64,255,84,78,37,152,232,246,115,136,139,174,22,239,55,22,248,64,130,4,157,39,62,188,36,31,233,33,65,120,85,153,175,215,224,139,202,176,92,51,59,182,89,237,94,209,229,85,176,126,80,71,213,25,236,255,108,33,59,98,9,70,135,218,231,233,50,200,130,142,142,112,212,158,237,40,177,249,81,144,95,86,228,130,58,49,88,58,131,9,143,167,230,110,51,31,8,193,134,13,109,166,58,181,164,225,64,189,193,134,252,5,47,41,73,23,74,78,245,175,243,118,34,50,150,17,158,138,120,190,43,152,29,217,151,32,75,201,244,120,46,174,72,192,192,1,253,210,165,102,65,106,28,94,150,247,121,57,42,79,151,150,159,93,242,241,35,229,5,25,107,77,96,126,215,245,142,209,98,231,235,182,222,95,82,142,9,194,55,233,181,122,217,70,0,104,188,33,188,208,234,49,223,136,143,86,99,48,97,249,214,34,4,158,106,154,189,166,189,7,216,193,1,191,54,110,180,173,83,9,8,21,154,78,114,29,255,41,206,165,17,134,123,183,116,225,199,15,205,217,16,146,168,190,172,42,70,17,25,56,35,118,165,128,117,102,198,216,16,1,122,96,254,174,207,114,155,201,115,202,34,241,164,87,71,150,24,239,169,57,173,253,204,94,17,69,6,238,77,118,99,137,241,206,141,38,68,220,232,65,248,100,81,121,47,249,52,30,147,65,218,177,38,83,191,214,154,235,233,198,249,179,140,161,69,11,98,14,240,25,7,105,76,161,190,81,155,60,219,54,39,132,53,153,146,150,80,254,46,46,153,185,84,38,252,222,232,158,18,113,93,140,119,22,225,52,206,46,54,169,171,73,138,17,69,230,63,3,32,129,131,187,118,145,224,227,19,246,92,91,253,89,233,73,152,62,85,241,33,6,130,108,68,97,62,212,170,206,139,198,207,169,55,126,56,65,127,214,93,38,195,110,179,137,118,124,214,238,202,196,111,214,29,89,10,177,161,225,228,30,20,243,129,121,168,75,215,105,203,19,178,14,119,171,92,161,194,185,57,198,126,1,128,254,169,156,229,153,21,36,11,54,160,54,110,81,28,142,167,22,102,134,194,113,218,62,44,222,111,44,73,185,211,148,240,129,4,9,149,230,184,177,123,73,13,163,30,46,177,27,72,62,210,67,45,89,110,251,195,246,219,233,166,145,103,81,31,169,176,204,122,206,12,116,148,97,185,102,241,6,5,222,0,0,0,0,119,7,48,150,238,14,97,44,153,9,81,186,7,109,196,25,112,106,244,143,233,99,165,53,158,100,149,163,14,219,136,50,121,220,184,164,224,213,233,30,151,210,217,136,9,182,76,43,126,177,124,189,231,184,45,7,144,191,29,145,29,183,16,100,106,176,32,242,243,185,113,72,132,190,65,222,26,218,212,125,109,221,228,235,244,212,181,81,131,211,133,199,19,108,152,86,100,107,168,192,253,98,249,122,138,101,201,236,20,1,92,79,99,6,108,217,250,15,61,99,141,8,13,245,59,110,32,200,76,105,16,94,213,96,65,228,162,103,113,114,60,3,228,209,75,4,212,71,210,13,133,253,165,10,181,107,53,181,168,250,66,178,152,108,219,187,201,214,172,188,249,64,50,216,108,227,69,223,92,117,220,214,13,207,171,209,61,89,38,217,48,172,81,222,0,58,200,215,81,128,191,208,97,22,33,180,244,181,86,179,196,35,207,186,149,153,184,189,165,15,40,2,184,158,95,5,136,8,198,12,217,178,177,11,233,36,47,111,124,135,88,104,76,17,193,97,29,171,182,102,45,61,118,220,65,144,1,219,113,6,152,210,32,188,239,213,16,42,113,177,133,137,6,182,181,31,159,191,228,165,232,184,212,51,120,7,201,162,15,0,249,52,150,9,168,142,225,14,152,24,127,106,13,187,8,109,61,45,145,100,108,151,230,99,92,1,107,107,81,244,28,108,97,98,133,101,48,216,242,98,0,78,108,6,149,237,27,1,165,123,130,8,244,193,245,15,196,87,101,176,217,198,18,183,233,80,139,190,184,234,252,185,136,124,98,221,29,223,21,218,45,73,140,211,124,243,251,212,76,101,77,178,97,88,58,181,81,206,163,188,0,116,212,187,48,226,74,223,165,65,61,216,149,215,164,209,196,109,211,214,244,251,67,105,233,106,52,110,217,252,173,103,136,70,218,96,184,208,68,4,45,115,51,3,29,229,170,10,76,95,221,13,124,201,80,5,113,60,39,2,65,170,190,11,16,16,201,12,32,134,87,104,181,37,32,111,133,179,185,102,212,9,206,97,228,159,94,222,249,14,41,217,201,152,176,208,152,34,199,215,168,180,89,179,61,23,46,180,13,129,183,189,92,59,192,186,108,173,237,184,131,32,154,191,179,182,3,182,226,12,116,177,210,154,234,213,71,57,157,210,119,175,4,219,38,21,115,220,22,131,227,99,11,18,148,100,59,132,13,109,106,62,122,106,90,168,228,14,207,11,147,9,255,157,10,0,174,39,125,7,158,177,240,15,147,68,135,8,163,210,30,1,242,104,105,6,194,254,247,98,87,93,128,101,103,203,25,108,54,113,110,107,6,231,254,212,27,118,137,211,43,224,16,218,122,90,103,221,74,204,249,185,223,111,142,190,239,249,23,183,190,67,96,176,142,213,214,214,163,232,161,209,147,126,56,216,194,196,79,223,242,82,209,187,103,241,166,188,87,103,63,181,6,221,72,178,54,75,216,13,43,218,175,10,27,76,54,3,74,246,65,4,122,96,223,96,239,195,168,103,223,85,49,110,142,239,70,105,190,121,203,97,179,140,188,102,131,26,37,111,210,160,82,104,226,54,204,12,119,149,187,11,71,3,34,2,22,185,85,5,38,47,197,186,59,190,178,189,11,40,43,180,90,146,92,179,106,4,194,215,255,167,181,208,207,49,44,217,158,139,91,222,174,29,155,100,194,176,236,99,242,38,117,106,163,156,2,109,147,10,156,9,6,169,235,14,54,63,114,7,103,133,5,0,87,19,149,191,74,130,226,184,122,20,123,177,43,174,12,182,27,56,146,210,142,155,229,213,190,13,124,220,239,183,11,219,223,33,134,211,210,212,241,212,226,66,104,221,179,248,31,218,131,110,129,190,22,205,246,185,38,91,111,176,119,225,24,183,71,119,136,8,90,230,255,15,106,112,102,6,59,202,17,1,11,92,143,101,158,255,248,98,174,105,97,107,255,211,22,108,207,69,160,10,226,120,215,13,210,238,78,4,131,84,57,3,179,194,167,103,38,97,208,96,22,247,73,105,71,77,62,110,119,219,174,209,106,74,217,214,90,220,64,223,11,102,55,216,59,240,169,188,174,83,222,187,158,197,71,178,207,127,48,181,255,233,189,189,242,28,202,186,194,138,83,179,147,48,36,180,163,166,186,208,54,5,205,215,6,147,84,222,87,41,35,217,103,191,179,102,122,46,196,97,74,184,93,104,27,2,42,111,43,148,180,11,190,55,195,12,142,161,90,5,223,27,45,2,239,141,0,0,0,0,25,27,49,65,50,54,98,130,43,45,83,195,100,108,197,4,125,119,244,69,86,90,167,134,79,65,150,199,200,217,138,8,209,194,187,73,250,239,232,138,227,244,217,203,172,181,79,12,181,174,126,77,158,131,45,142,135,152,28,207,74,194,18,81,83,217,35,16,120,244,112,211,97,239,65,146,46,174,215,85,55,181,230,20,28,152,181,215,5,131,132,150,130,27,152,89,155,0,169,24,176,45,250,219,169,54,203,154,230,119,93,93,255,108,108,28,212,65,63,223,205,90,14,158,149,132,36,162,140,159,21,227,167,178,70,32,190,169,119,97,241,232,225,166,232,243,208,231,195,222,131,36,218,197,178,101,93,93,174,170,68,70,159,235,111,107,204,40,118,112,253,105,57,49,107,174,32,42,90,239,11,7,9,44,18,28,56,109,223,70,54,243,198,93,7,178,237,112,84,113,244,107,101,48,187,42,243,247,162,49,194,182,137,28,145,117,144,7,160,52,23,159,188,251,14,132,141,186,37,169,222,121,60,178,239,56,115,243,121,255,106,232,72,190,65,197,27,125,88,222,42,60,240,121,79,5,233,98,126,68,194,79,45,135,219,84,28,198,148,21,138,1,141,14,187,64,166,35,232,131,191,56,217,194,56,160,197,13,33,187,244,76,10,150,167,143,19,141,150,206,92,204,0,9,69,215,49,72,110,250,98,139,119,225,83,202,186,187,93,84,163,160,108,21,136,141,63,214,145,150,14,151,222,215,152,80,199,204,169,17,236,225,250,210,245,250,203,147,114,98,215,92,107,121,230,29,64,84,181,222,89,79,132,159,22,14,18,88,15,21,35,25,36,56,112,218,61,35,65,155,101,253,107,167,124,230,90,230,87,203,9,37,78,208,56,100,1,145,174,163,24,138,159,226,51,167,204,33,42,188,253,96,173,36,225,175,180,63,208,238,159,18,131,45,134,9,178,108,201,72,36,171,208,83,21,234,251,126,70,41,226,101,119,104,47,63,121,246,54,36,72,183,29,9,27,116,4,18,42,53,75,83,188,242,82,72,141,179,121,101,222,112,96,126,239,49,231,230,243,254,254,253,194,191,213,208,145,124,204,203,160,61,131,138,54,250,154,145,7,187,177,188,84,120,168,167,101,57,59,131,152,75,34,152,169,10,9,181,250,201,16,174,203,136,95,239,93,79,70,244,108,14,109,217,63,205,116,194,14,140,243,90,18,67,234,65,35,2,193,108,112,193,216,119,65,128,151,54,215,71,142,45,230,6,165,0,181,197,188,27,132,132,113,65,138,26,104,90,187,91,67,119,232,152,90,108,217,217,21,45,79,30,12,54,126,95,39,27,45,156,62,0,28,221,185,152,0,18,160,131,49,83,139,174,98,144,146,181,83,209,221,244,197,22,196,239,244,87,239,194,167,148,246,217,150,213,174,7,188,233,183,28,141,168,156,49,222,107,133,42,239,42,202,107,121,237,211,112,72,172,248,93,27,111,225,70,42,46,102,222,54,225,127,197,7,160,84,232,84,99,77,243,101,34,2,178,243,229,27,169,194,164,48,132,145,103,41,159,160,38,228,197,174,184,253,222,159,249,214,243,204,58,207,232,253,123,128,169,107,188,153,178,90,253,178,159,9,62,171,132,56,127,44,28,36,176,53,7,21,241,30,42,70,50,7,49,119,115,72,112,225,180,81,107,208,245,122,70,131,54,99,93,178,119,203,250,215,78,210,225,230,15,249,204,181,204,224,215,132,141,175,150,18,74,182,141,35,11,157,160,112,200,132,187,65,137,3,35,93,70,26,56,108,7,49,21,63,196,40,14,14,133,103,79,152,66,126,84,169,3,85,121,250,192,76,98,203,129,129,56,197,31,152,35,244,94,179,14,167,157,170,21,150,220,229,84,0,27,252,79,49,90,215,98,98,153,206,121,83,216,73,225,79,23,80,250,126,86,123,215,45,149,98,204,28,212,45,141,138,19,52,150,187,82,31,187,232,145,6,160,217,208,94,126,243,236,71,101,194,173,108,72,145,110,117,83,160,47,58,18,54,232,35,9,7,169,8,36,84,106,17,63,101,43].concat([150,167,121,228,143,188,72,165,164,145,27,102,189,138,42,39,242,203,188,224,235,208,141,161,192,253,222,98,217,230,239,35,20,188,225,189,13,167,208,252,38,138,131,63,63,145,178,126,112,208,36,185,105,203,21,248,66,230,70,59,91,253,119,122,220,101,107,181,197,126,90,244,238,83,9,55,247,72,56,118,184,9,174,177,161,18,159,240,138,63,204,51,147,36,253,114,0,0,0,0,1,194,106,55,3,132,212,110,2,70,190,89,7,9,168,220,6,203,194,235,4,141,124,178,5,79,22,133,14,19,81,184,15,209,59,143,13,151,133,214,12,85,239,225,9,26,249,100,8,216,147,83,10,158,45,10,11,92,71,61,28,38,163,112,29,228,201,71,31,162,119,30,30,96,29,41,27,47,11,172,26,237,97,155,24,171,223,194,25,105,181,245,18,53,242,200,19,247,152,255,17,177,38,166,16,115,76,145,21,60,90,20,20,254,48,35,22,184,142,122,23,122,228,77,56,77,70,224,57,143,44,215,59,201,146,142,58,11,248,185,63,68,238,60,62,134,132,11,60,192,58,82,61,2,80,101,54,94,23,88,55,156,125,111,53,218,195,54,52,24,169,1,49,87,191,132,48,149,213,179,50,211,107,234,51,17,1,221,36,107,229,144,37,169,143,167,39,239,49,254,38,45,91,201,35,98,77,76,34,160,39,123,32,230,153,34,33,36,243,21,42,120,180,40,43,186,222,31,41,252,96,70,40,62,10,113,45,113,28,244,44,179,118,195,46,245,200,154,47,55,162,173,112,154,141,192,113,88,231,247,115,30,89,174,114,220,51,153,119,147,37,28,118,81,79,43,116,23,241,114,117,213,155,69,126,137,220,120,127,75,182,79,125,13,8,22,124,207,98,33,121,128,116,164,120,66,30,147,122,4,160,202,123,198,202,253,108,188,46,176,109,126,68,135,111,56,250,222,110,250,144,233,107,181,134,108,106,119,236,91,104,49,82,2,105,243,56,53,98,175,127,8,99,109,21,63,97,43,171,102,96,233,193,81,101,166,215,212,100,100,189,227,102,34,3,186,103,224,105,141,72,215,203,32,73,21,161,23,75,83,31,78,74,145,117,121,79,222,99,252,78,28,9,203,76,90,183,146,77,152,221,165,70,196,154,152,71,6,240,175,69,64,78,246,68,130,36,193,65,205,50,68,64,15,88,115,66,73,230,42,67,139,140,29,84,241,104,80,85,51,2,103,87,117,188,62,86,183,214,9,83,248,192,140,82,58,170,187,80,124,20,226,81,190,126,213,90,226,57,232,91,32,83,223,89,102,237,134,88,164,135,177,93,235,145,52,92,41,251,3,94,111,69,90,95,173,47,109,225,53,27,128,224,247,113,183,226,177,207,238,227,115,165,217,230,60,179,92,231,254,217,107,229,184,103,50,228,122,13,5,239,38,74,56,238,228,32,15,236,162,158,86,237,96,244,97,232,47,226,228,233,237,136,211,235,171,54,138,234,105,92,189,253,19,184,240,252,209,210,199,254,151,108,158,255,85,6,169,250,26,16,44,251,216,122,27,249,158,196,66,248,92,174,117,243,0,233,72,242,194,131,127,240,132,61,38,241,70,87,17,244,9,65,148,245,203,43,163,247,141,149,250,246,79,255,205,217,120,93,96,216,186,55,87,218,252,137,14,219,62,227,57,222,113,245,188,223,179,159,139,221,245,33,210,220,55,75,229,215,107,12,216,214,169,102,239,212,239,216,182,213,45,178,129,208,98,164,4,209,160,206,51,211,230,112,106,210,36,26,93,197,94,254,16,196,156,148,39,198,218,42,126,199,24,64,73,194,87,86,204,195,149,60,251,193,211,130,162,192,17,232,149,203,77,175,168,202,143,197,159,200,201,123,198,201,11,17,241,204,68,7,116,205,134,109,67,207,192,211,26,206,2,185,45,145,175,150,64,144,109,252,119,146,43,66,46,147,233,40,25,150,166,62,156,151,100,84,171,149,34,234,242,148,224,128,197,159,188,199,248,158,126,173,207,156,56,19,150,157,250,121,161,152,181,111,36,153,119,5,19,155,49,187,74,154,243,209,125,141,137,53,48,140,75,95,7,142,13,225,94,143,207,139,105,138,128,157,236,139,66,247,219,137,4,73,130,136,198,35,181,131,154,100,136,130,88,14,191,128,30,176,230,129,220,218,209,132,147,204,84,133,81,166,99,135,23,24,58,134,213,114,13,169,226,208,160,168,32,186,151,170,102,4,206,171,164,110,249,174,235,120,124,175,41,18,75,173,111,172,18,172,173,198,37,167,241,129,24,166,51,235,47,164,117,85,118,165,183,63,65,160,248,41,196,161,58,67,243,163,124,253,170,162,190,151,157,181,196,115,208,180,6,25,231,182,64,167,190,183,130,205,137,178,205,219,12,179,15,177,59,177,73,15,98,176,139,101,85,187,215,34,104,186,21,72,95,184,83,246,6,185,145,156,49,188,222,138,180,189,28,224,131,191,90,94,218,190,152,52,237,0,0,0,0,184,188,103,101,170,9,200,139,18,181,175,238,143,98,151,87,55,222,240,50,37,107,95,220,157,215,56,185,197,180,40,239,125,8,79,138,111,189,224,100,215,1,135,1,74,214,191,184,242,106,216,221,224,223,119,51,88,99,16,86,80,25,87,159,232,165,48,250,250,16,159,20,66,172,248,113,223,123,192,200,103,199,167,173,117,114,8,67,205,206,111,38,149,173,127,112,45,17,24,21,63,164,183,251,135,24,208,158,26,207,232,39,162,115,143,66,176,198,32,172,8,122,71,201,160,50,175,62,24,142,200,91,10,59,103,181,178,135,0,208,47,80,56,105,151,236,95,12,133,89,240,226,61,229,151,135,101,134,135,209,221,58,224,180,207,143,79,90,119,51,40,63,234,228,16,134,82,88,119,227,64,237,216,13,248,81,191,104,240,43,248,161,72,151,159,196,90,34,48,42,226,158,87,79,127,73,111,246,199,245,8,147,213,64,167,125,109,252,192,24,53,159,208,78,141,35,183,43,159,150,24,197,39,42,127,160,186,253,71,25,2,65,32,124,16,244,143,146,168,72,232,247,155,20,88,61,35,168,63,88,49,29,144,182,137,161,247,211,20,118,207,106,172,202,168,15,190,127,7,225,6,195,96,132,94,160,112,210,230,28,23,183,244,169,184,89,76,21,223,60,209,194,231,133,105,126,128,224,123,203,47,14,195,119,72,107,203,13,15,162,115,177,104,199,97,4,199,41,217,184,160,76,68,111,152,245,252,211,255,144,238,102,80,126,86,218,55,27,14,185,39,77,182,5,64,40,164,176,239,198,28,12,136,163,129,219,176,26,57,103,215,127,43,210,120,145,147,110,31,244,59,38,247,3,131,154,144,102,145,47,63,136,41,147,88,237,180,68,96,84,12,248,7,49,30,77,168,223,166,241,207,186,254,146,223,236,70,46,184,137,84,155,23,103,236,39,112,2,113,240,72,187,201,76,47,222,219,249,128,48,99,69,231,85,107,63,160,156,211,131,199,249,193,54,104,23,121,138,15,114,228,93,55,203,92,225,80,174,78,84,255,64,246,232,152,37,174,139,136,115,22,55,239,22,4,130,64,248,188,62,39,157,33,233,31,36,153,85,120,65,139,224,215,175,51,92,176,202,237,89,182,59,85,229,209,94,71,80,126,176,255,236,25,213,98,59,33,108,218,135,70,9,200,50,233,231,112,142,142,130,40,237,158,212,144,81,249,177,130,228,86,95,58,88,49,58,167,143,9,131,31,51,110,230,13,134,193,8,181,58,166,109,189,64,225,164,5,252,134,193,23,73,41,47,175,245,78,74,50,34,118,243,138,158,17,150,152,43,190,120,32,151,217,29,120,244,201,75,192,72,174,46,210,253,1,192,106,65,102,165,247,150,94,28,79,42,57,121,93,159,150,151,229,35,241,242,77,107,25,5,245,215,126,96,231,98,209,142,95,222,182,235,194,9,142,82,122,181,233,55,104,0,70,217,208,188,33,188,136,223,49,234,48,99,86,143,34,214,249,97,154,106,158,4,7,189,166,189,191,1,193,216,173,180,110,54,21,8,9,83,29,114,78,154,165,206,41,255,183,123,134,17,15,199,225,116,146,16,217,205,42,172,190,168,56,25,17,70,128,165,118,35,216,198,102,117,96,122,1,16,114,207,174,254,202,115,201,155,87,164,241,34,239,24,150,71,253,173,57,169,69,17,94,204,118,77,238,6,206,241,137,99,220,68,38,141,100,248,65,232,249,47,121,81,65,147,30,52,83,38,177,218,235,154,214,191,179,249,198,233,11,69,161,140,25,240,14,98,161,76,105,7,60,155,81,190,132,39,54,219,150,146,153,53,46,46,254,80,38,84,185,153,158,232,222,252,140,93,113,18,52,225,22,119,169,54,46,206,17,138,73,171,3,63,230,69,187,131,129,32,227,224,145,118,91,92,246,19,73,233,89,253,241,85,62,152,108,130,6,33,212,62,97,68,198,139,206,170,126,55,169,207,214,127,65,56,110,195,38,93,124,118,137,179,196,202,238,214,89,29,214,111,225,161,177,10,243,20,30,228,75,168,121,129,19,203,105,215,171,119,14,178,185,194,161,92,1,126,198,57,156,169,254,128,36,21,153,229,54,160,54,11,142,28,81,110,134,102,22,167,62,218,113,194,44,111,222,44,148,211,185,73,9,4,129,240,177,184,230,149,163,13,73,123,27,177,46,30,67,210,62,72,251,110,89,45,233,219,246,195,81,103,145,166,204,176,169,31,116,12,206,122,102,185,97,148,222,5,6,241,0,0,0,0,0,0,0,0,2,0,0,0,4,0,4,0,8,0,4,0,8,0,0,0,4,0,5,0,16,0,8,0,8,0,0,0,4,0,6,0,32,0,32,0,8,0,0,0,4,0,4,0,16,0,16,0,6,0,0,0,8,0,16,0,32,0,32,0,6,0,0,0,8,0,16,0,128,0,128,0,6,0,0,0,8,0,32,0,128,0,0,1,6,0,0,0,32,0,128,0,2,1,0,4,6,0,0,0,32,0,2,1,2,1,0,16,6,0,0,0,16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,8,0,0,0,10,0,0,0,12,0,0,0,14,0,0,0,16,0,0,0,20,0,0,0,24,0,0,0,28,0,0,0,32,0,0,0,40,0,0,0,48,0,0,0,56,0,0,0,64,0,0,0,80,0,0,0,96,0,0,0,112,0,0,0,128,0,0,0,160,0,0,0,192,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,0,128,0,0,0,192,0,0,0,0,1,0,0,128,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,105,110,99,111,109,112,97,116,105,98,108,101,32,118,101,114,115,105,111,110,0,0,0,0,116,111,111,32,109,97,110,121,32,108,101,110,103,116,104,32,111,114,32,100,105,115,116,97,110,99,101,32,115,121,109,98,111,108,115,0,0,0,0,0,99,111,109,112,114,101,115,115,101,100,32,100,97,116,97,32,101,114,114,111,114,0,0,0,98,117,102,102,101,114,32,101,114,114,111,114,0,0,0,0,110,101,101,100,32,100,105,99,116,105,111,110,97,114,121,0,105,110,118,97,108,105,100,32,115,116,111,114,101,100,32,98,108,111,99,107,32,108,101,110,103,116,104,115,0,0,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,105,110,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,105,110,115,117,102,102,105,99,105,101,110,116,32,109,101,109,111,114,121,0,0,0,0,0,105,110,118,97,108,105,100,32,98,108,111,99,107,32,116,121,112,101,0,0,0,0,0,0,117,110,101,120,112,101,99,116,101,100,32,101,110,100,32,111,102,32,102,105,108,101,0,0,100,97,116,97,32,101,114,114,111,114,0,0,0,0,0,0,104,101,97,100,101,114,32,99,114,99,32,109,105,115,109,97,116,99,104,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,115,116,114,101,97,109,32,101,114,114,111,114,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,102,105,108,101,32,101,114,114,111,114,0,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,118,97,108,105,100,32,119,105,110,100,111,119,32,115,105,122,101,0,0,0,0,0,49,46,50,46,53,0,0,0,49,46,50,46,53,0,0,0,58,32,0,0,0,0,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,115,116,114,101,97,109,32,101,110,100,0,0,0,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,99,111,114,114,101,99,116,32,104,101,97,100,101,114,32,99,104,101,99,107,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,115,32,115,101,116,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,100,101,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,45,45,32,109,105,115,115,105,110,103,32,101,110,100,45,111,102,45,98,108,111,99,107,0,0,0,0,105,110,118,97,108,105,100,32,98,105,116,32,108,101,110,103,116,104,32,114,101,112,101,97,116,0,0,0,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29]) +, "i8", ALLOC_NONE, Runtime.GLOBAL_BASE) +var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8); +assert(tempDoublePtr % 8 == 0); +function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much + HEAP8[tempDoublePtr] = HEAP8[ptr]; + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; +} +function copyTempDouble(ptr) { + HEAP8[tempDoublePtr] = HEAP8[ptr]; + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; + HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; + HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; + HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; +} + function _llvm_lifetime_start() {} + function _llvm_lifetime_end() {} + Module["_memset"] = _memset;var _llvm_memset_p0i8_i32=_memset; + Module["_memcpy"] = _memcpy;var _llvm_memcpy_p0i8_p0i8_i32=_memcpy; + var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:35,EIDRM:36,ECHRNG:37,EL2NSYNC:38,EL3HLT:39,EL3RST:40,ELNRNG:41,EUNATCH:42,ENOCSI:43,EL2HLT:44,EDEADLK:45,ENOLCK:46,EBADE:50,EBADR:51,EXFULL:52,ENOANO:53,EBADRQC:54,EBADSLT:55,EDEADLOCK:56,EBFONT:57,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:74,ELBIN:75,EDOTDOT:76,EBADMSG:77,EFTYPE:79,ENOTUNIQ:80,EBADFD:81,EREMCHG:82,ELIBACC:83,ELIBBAD:84,ELIBSCN:85,ELIBMAX:86,ELIBEXEC:87,ENOSYS:88,ENMFILE:89,ENOTEMPTY:90,ENAMETOOLONG:91,ELOOP:92,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:106,EPROTOTYPE:107,ENOTSOCK:108,ENOPROTOOPT:109,ESHUTDOWN:110,ECONNREFUSED:111,EADDRINUSE:112,ECONNABORTED:113,ENETUNREACH:114,ENETDOWN:115,ETIMEDOUT:116,EHOSTDOWN:117,EHOSTUNREACH:118,EINPROGRESS:119,EALREADY:120,EDESTADDRREQ:121,EMSGSIZE:122,EPROTONOSUPPORT:123,ESOCKTNOSUPPORT:124,EADDRNOTAVAIL:125,ENETRESET:126,EISCONN:127,ENOTCONN:128,ETOOMANYREFS:129,EPROCLIM:130,EUSERS:131,EDQUOT:132,ESTALE:133,ENOTSUP:134,ENOMEDIUM:135,ENOSHARE:136,ECASECLASH:137,EILSEQ:138,EOVERFLOW:139,ECANCELED:140,ENOTRECOVERABLE:141,EOWNERDEAD:142,ESTRPIPE:143}; + var ___errno_state=0;function ___setErrNo(value) { + // For convenient setting and returning of errno. + HEAP32[((___errno_state)>>2)]=value + return value; + } + var _stdin=allocate(1, "i32*", ALLOC_STATIC); + var _stdout=allocate(1, "i32*", ALLOC_STATIC); + var _stderr=allocate(1, "i32*", ALLOC_STATIC); + var __impure_ptr=allocate(1, "i32*", ALLOC_STATIC);var FS={currentPath:"/",nextInode:2,streams:[null],ignorePermissions:true,createFileHandle:function (stream, fd) { + if (typeof stream === 'undefined') { + stream = null; + } + if (!fd) { + if (stream && stream.socket) { + for (var i = 1; i < 64; i++) { + if (!FS.streams[i]) { + fd = i; + break; + } + } + assert(fd, 'ran out of low fds for sockets'); + } else { + fd = Math.max(FS.streams.length, 64); + for (var i = FS.streams.length; i < fd; i++) { + FS.streams[i] = null; // Keep dense + } + } + } + // Close WebSocket first if we are about to replace the fd (i.e. dup2) + if (FS.streams[fd] && FS.streams[fd].socket && FS.streams[fd].socket.close) { + FS.streams[fd].socket.close(); + } + FS.streams[fd] = stream; + return fd; + },removeFileHandle:function (fd) { + FS.streams[fd] = null; + },joinPath:function (parts, forceRelative) { + var ret = parts[0]; + for (var i = 1; i < parts.length; i++) { + if (ret[ret.length-1] != '/') ret += '/'; + ret += parts[i]; + } + if (forceRelative && ret[0] == '/') ret = ret.substr(1); + return ret; + },absolutePath:function (relative, base) { + if (typeof relative !== 'string') return null; + if (base === undefined) base = FS.currentPath; + if (relative && relative[0] == '/') base = ''; + var full = base + '/' + relative; + var parts = full.split('/').reverse(); + var absolute = ['']; + while (parts.length) { + var part = parts.pop(); + if (part == '' || part == '.') { + // Nothing. + } else if (part == '..') { + if (absolute.length > 1) absolute.pop(); + } else { + absolute.push(part); + } + } + return absolute.length == 1 ? '/' : absolute.join('/'); + },analyzePath:function (path, dontResolveLastLink, linksVisited) { + var ret = { + isRoot: false, + exists: false, + error: 0, + name: null, + path: null, + object: null, + parentExists: false, + parentPath: null, + parentObject: null + }; + path = FS.absolutePath(path); + if (path == '/') { + ret.isRoot = true; + ret.exists = ret.parentExists = true; + ret.name = '/'; + ret.path = ret.parentPath = '/'; + ret.object = ret.parentObject = FS.root; + } else if (path !== null) { + linksVisited = linksVisited || 0; + path = path.slice(1).split('/'); + var current = FS.root; + var traversed = ['']; + while (path.length) { + if (path.length == 1 && current.isFolder) { + ret.parentExists = true; + ret.parentPath = traversed.length == 1 ? '/' : traversed.join('/'); + ret.parentObject = current; + ret.name = path[0]; + } + var target = path.shift(); + if (!current.isFolder) { + ret.error = ERRNO_CODES.ENOTDIR; + break; + } else if (!current.read) { + ret.error = ERRNO_CODES.EACCES; + break; + } else if (!current.contents.hasOwnProperty(target)) { + ret.error = ERRNO_CODES.ENOENT; + break; + } + current = current.contents[target]; + if (current.link && !(dontResolveLastLink && path.length == 0)) { + if (linksVisited > 40) { // Usual Linux SYMLOOP_MAX. + ret.error = ERRNO_CODES.ELOOP; + break; + } + var link = FS.absolutePath(current.link, traversed.join('/')); + ret = FS.analyzePath([link].concat(path).join('/'), + dontResolveLastLink, linksVisited + 1); + return ret; + } + traversed.push(target); + if (path.length == 0) { + ret.exists = true; + ret.path = traversed.join('/'); + ret.object = current; + } + } + } + return ret; + },findObject:function (path, dontResolveLastLink) { + FS.ensureRoot(); + var ret = FS.analyzePath(path, dontResolveLastLink); + if (ret.exists) { + return ret.object; + } else { + ___setErrNo(ret.error); + return null; + } + },createObject:function (parent, name, properties, canRead, canWrite) { + if (!parent) parent = '/'; + if (typeof parent === 'string') parent = FS.findObject(parent); + if (!parent) { + ___setErrNo(ERRNO_CODES.EACCES); + throw new Error('Parent path must exist.'); + } + if (!parent.isFolder) { + ___setErrNo(ERRNO_CODES.ENOTDIR); + throw new Error('Parent must be a folder.'); + } + if (!parent.write && !FS.ignorePermissions) { + ___setErrNo(ERRNO_CODES.EACCES); + throw new Error('Parent folder must be writeable.'); + } + if (!name || name == '.' || name == '..') { + ___setErrNo(ERRNO_CODES.ENOENT); + throw new Error('Name must not be empty.'); + } + if (parent.contents.hasOwnProperty(name)) { + ___setErrNo(ERRNO_CODES.EEXIST); + throw new Error("Can't overwrite object."); + } + parent.contents[name] = { + read: canRead === undefined ? true : canRead, + write: canWrite === undefined ? false : canWrite, + timestamp: Date.now(), + inodeNumber: FS.nextInode++ + }; + for (var key in properties) { + if (properties.hasOwnProperty(key)) { + parent.contents[name][key] = properties[key]; + } + } + return parent.contents[name]; + },createFolder:function (parent, name, canRead, canWrite) { + var properties = {isFolder: true, isDevice: false, contents: {}}; + return FS.createObject(parent, name, properties, canRead, canWrite); + },createPath:function (parent, path, canRead, canWrite) { + var current = FS.findObject(parent); + if (current === null) throw new Error('Invalid parent.'); + path = path.split('/').reverse(); + while (path.length) { + var part = path.pop(); + if (!part) continue; + if (!current.contents.hasOwnProperty(part)) { + FS.createFolder(current, part, canRead, canWrite); + } + current = current.contents[part]; + } + return current; + },createFile:function (parent, name, properties, canRead, canWrite) { + properties.isFolder = false; + return FS.createObject(parent, name, properties, canRead, canWrite); + },createDataFile:function (parent, name, data, canRead, canWrite) { + if (typeof data === 'string') { + var dataArray = new Array(data.length); + for (var i = 0, len = data.length; i < len; ++i) dataArray[i] = data.charCodeAt(i); + data = dataArray; + } + var properties = { + isDevice: false, + contents: data.subarray ? data.subarray(0) : data // as an optimization, create a new array wrapper (not buffer) here, to help JS engines understand this object + }; + return FS.createFile(parent, name, properties, canRead, canWrite); + },createLazyFile:function (parent, name, url, canRead, canWrite) { + if (typeof XMLHttpRequest !== 'undefined') { + if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; + // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. + var LazyUint8Array = function() { + this.lengthKnown = false; + this.chunks = []; // Loaded chunks. Index is the chunk number + } + LazyUint8Array.prototype.get = function(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = Math.floor(idx / this.chunkSize); + return this.getter(chunkNum)[chunkOffset]; + } + LazyUint8Array.prototype.setDataGetter = function(getter) { + this.getter = getter; + } + LazyUint8Array.prototype.cacheLength = function() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("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 chunkSize = 1024*1024; // Chunk size in bytes + if (!hasByteServing) chunkSize = datalength; + // Function to get a range from the remote URL. + var doXHR = (function(from, to) { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + // Some hints to the browser that we want binary data. + if (typeof Uint8Array != 'undefined') 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)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(xhr.response || []); + } else { + return intArrayFromString(xhr.responseText || '', true); + } + }); + var lazyArray = this; + lazyArray.setDataGetter(function(chunkNum) { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); + return lazyArray.chunks[chunkNum]; + }); + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } + var lazyArray = new LazyUint8Array(); + Object.defineProperty(lazyArray, "length", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + }); + Object.defineProperty(lazyArray, "chunkSize", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + }); + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + return FS.createFile(parent, name, properties, canRead, canWrite); + },createPreloadedFile:function (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile) { + Browser.init(); + var fullname = FS.joinPath([parent, name], true); + function processData(byteArray) { + function finish(byteArray) { + if (!dontCreateFile) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite); + } + if (onload) onload(); + removeRunDependency('cp ' + fullname); + } + var handled = false; + Module['preloadPlugins'].forEach(function(plugin) { + if (handled) return; + if (plugin['canHandle'](fullname)) { + plugin['handle'](byteArray, fullname, finish, function() { + if (onerror) onerror(); + removeRunDependency('cp ' + fullname); + }); + handled = true; + } + }); + if (!handled) finish(byteArray); + } + addRunDependency('cp ' + fullname); + if (typeof url == 'string') { + Browser.asyncLoad(url, function(byteArray) { + processData(byteArray); + }, onerror); + } else { + processData(url); + } + },createLink:function (parent, name, target, canRead, canWrite) { + var properties = {isDevice: false, link: target}; + return FS.createFile(parent, name, properties, canRead, canWrite); + },createDevice:function (parent, name, input, output) { + if (!(input || output)) { + throw new Error('A device must have at least one callback defined.'); + } + var ops = {isDevice: true, input: input, output: output}; + return FS.createFile(parent, name, ops, Boolean(input), Boolean(output)); + },forceLoadFile:function (obj) { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + var success = true; + if (typeof XMLHttpRequest !== 'undefined') { + throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else if (Module['read']) { + // Command-line. + try { + // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as + // read() will try to parse UTF8. + obj.contents = intArrayFromString(Module['read'](obj.url), true); + } catch (e) { + success = false; + } + } else { + throw new Error('Cannot load without read() or XMLHttpRequest.'); + } + if (!success) ___setErrNo(ERRNO_CODES.EIO); + return success; + },ensureRoot:function () { + if (FS.root) return; + // The main file system tree. All the contents are inside this. + FS.root = { + read: true, + write: true, + isFolder: true, + isDevice: false, + timestamp: Date.now(), + inodeNumber: 1, + contents: {} + }; + },init:function (input, output, error) { + // Make sure we initialize only once. + assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); + FS.init.initialized = true; + FS.ensureRoot(); + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + input = input || Module['stdin']; + output = output || Module['stdout']; + error = error || Module['stderr']; + // Default handlers. + var stdinOverridden = true, stdoutOverridden = true, stderrOverridden = true; + if (!input) { + stdinOverridden = false; + input = function() { + if (!input.cache || !input.cache.length) { + var result; + if (typeof window != 'undefined' && + typeof window.prompt == 'function') { + // Browser. + result = window.prompt('Input: '); + if (result === null) result = String.fromCharCode(0); // cancel ==> EOF + } else if (typeof readline == 'function') { + // Command line. + result = readline(); + } + if (!result) result = ''; + input.cache = intArrayFromString(result + '\n', true); + } + return input.cache.shift(); + }; + } + var utf8 = new Runtime.UTF8Processor(); + function simpleOutput(val) { + if (val === null || val === 10) { + output.printer(output.buffer.join('')); + output.buffer = []; + } else { + output.buffer.push(utf8.processCChar(val)); + } + } + if (!output) { + stdoutOverridden = false; + output = simpleOutput; + } + if (!output.printer) output.printer = Module['print']; + if (!output.buffer) output.buffer = []; + if (!error) { + stderrOverridden = false; + error = simpleOutput; + } + if (!error.printer) error.printer = Module['print']; + if (!error.buffer) error.buffer = []; + // Create the temporary folder, if not already created + try { + FS.createFolder('/', 'tmp', true, true); + } catch(e) {} + // Create the I/O devices. + var devFolder = FS.createFolder('/', 'dev', true, true); + var stdin = FS.createDevice(devFolder, 'stdin', input); + var stdout = FS.createDevice(devFolder, 'stdout', null, output); + var stderr = FS.createDevice(devFolder, 'stderr', null, error); + FS.createDevice(devFolder, 'tty', input, output); + FS.createDevice(devFolder, 'null', function(){}, function(){}); + // Create default streams. + FS.streams[1] = { + path: '/dev/stdin', + object: stdin, + position: 0, + isRead: true, + isWrite: false, + isAppend: false, + isTerminal: !stdinOverridden, + error: false, + eof: false, + ungotten: [] + }; + FS.streams[2] = { + path: '/dev/stdout', + object: stdout, + position: 0, + isRead: false, + isWrite: true, + isAppend: false, + isTerminal: !stdoutOverridden, + error: false, + eof: false, + ungotten: [] + }; + FS.streams[3] = { + path: '/dev/stderr', + object: stderr, + position: 0, + isRead: false, + isWrite: true, + isAppend: false, + isTerminal: !stderrOverridden, + error: false, + eof: false, + ungotten: [] + }; + // TODO: put these low in memory like we used to assert on: assert(Math.max(_stdin, _stdout, _stderr) < 15000); // make sure these are low, we flatten arrays with these + HEAP32[((_stdin)>>2)]=1; + HEAP32[((_stdout)>>2)]=2; + HEAP32[((_stderr)>>2)]=3; + // Other system paths + FS.createPath('/', 'dev/shm/tmp', true, true); // temp files + // Newlib initialization + for (var i = FS.streams.length; i < Math.max(_stdin, _stdout, _stderr) + 4; i++) { + FS.streams[i] = null; // Make sure to keep FS.streams dense + } + FS.streams[_stdin] = FS.streams[1]; + FS.streams[_stdout] = FS.streams[2]; + FS.streams[_stderr] = FS.streams[3]; + allocate([ allocate( + [0, 0, 0, 0, _stdin, 0, 0, 0, _stdout, 0, 0, 0, _stderr, 0, 0, 0], + 'void*', ALLOC_NORMAL) ], 'void*', ALLOC_NONE, __impure_ptr); + },quit:function () { + if (!FS.init.initialized) return; + // Flush any partially-printed lines in stdout and stderr. Careful, they may have been closed + if (FS.streams[2] && FS.streams[2].object.output.buffer.length > 0) FS.streams[2].object.output(10); + if (FS.streams[3] && FS.streams[3].object.output.buffer.length > 0) FS.streams[3].object.output(10); + },standardizePath:function (path) { + if (path.substr(0, 2) == './') path = path.substr(2); + return path; + },deleteFile:function (path) { + path = FS.analyzePath(path); + if (!path.parentExists || !path.exists) { + throw 'Invalid path ' + path; + } + delete path.parentObject.contents[path.name]; + }};function _lseek(fildes, offset, whence) { + // off_t lseek(int fildes, off_t offset, int whence); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/lseek.html + if (FS.streams[fildes] && !FS.streams[fildes].object.isDevice) { + var stream = FS.streams[fildes]; + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + position += stream.object.contents.length; + } + if (position < 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } else { + stream.ungotten = []; + stream.position = position; + return position; + } + } else { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + } + Module["_strlen"] = _strlen; + Module["_strcpy"] = _strcpy; + Module["_strcat"] = _strcat; + var ___dirent_struct_layout={__size__:1040,d_ino:0,d_name:4,d_off:1028,d_reclen:1032,d_type:1036};function _open(path, oflag, varargs) { + // int open(const char *path, int oflag, ...); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html + // NOTE: This implementation tries to mimic glibc rather than strictly + // following the POSIX standard. + var mode = HEAP32[((varargs)>>2)]; + // Simplify flags. + var accessMode = oflag & 3; + var isWrite = accessMode != 0; + var isRead = accessMode != 1; + var isCreate = Boolean(oflag & 512); + var isExistCheck = Boolean(oflag & 2048); + var isTruncate = Boolean(oflag & 1024); + var isAppend = Boolean(oflag & 8); + // Verify path. + var origPath = path; + path = FS.analyzePath(Pointer_stringify(path)); + if (!path.parentExists) { + ___setErrNo(path.error); + return -1; + } + var target = path.object || null; + var finalPath; + // Verify the file exists, create if needed and allowed. + if (target) { + if (isCreate && isExistCheck) { + ___setErrNo(ERRNO_CODES.EEXIST); + return -1; + } + if ((isWrite || isCreate || isTruncate) && target.isFolder) { + ___setErrNo(ERRNO_CODES.EISDIR); + return -1; + } + if (isRead && !target.read || isWrite && !target.write) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } + if (isTruncate && !target.isDevice) { + target.contents = []; + } else { + if (!FS.forceLoadFile(target)) { + ___setErrNo(ERRNO_CODES.EIO); + return -1; + } + } + finalPath = path.path; + } else { + if (!isCreate) { + ___setErrNo(ERRNO_CODES.ENOENT); + return -1; + } + if (!path.parentObject.write) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } + target = FS.createDataFile(path.parentObject, path.name, [], + mode & 0x100, mode & 0x80); // S_IRUSR, S_IWUSR. + finalPath = path.parentPath + '/' + path.name; + } + // Actually create an open stream. + var id; + if (target.isFolder) { + var entryBuffer = 0; + if (___dirent_struct_layout) { + entryBuffer = _malloc(___dirent_struct_layout.__size__); + } + var contents = []; + for (var key in target.contents) contents.push(key); + id = FS.createFileHandle({ + path: finalPath, + object: target, + // An index into contents. Special values: -2 is ".", -1 is "..". + position: -2, + isRead: true, + isWrite: false, + isAppend: false, + error: false, + eof: false, + ungotten: [], + // Folder-specific properties: + // Remember the contents at the time of opening in an array, so we can + // seek between them relying on a single order. + contents: contents, + // Each stream has its own area for readdir() returns. + currentEntry: entryBuffer + }); + } else { + id = FS.createFileHandle({ + path: finalPath, + object: target, + position: 0, + isRead: isRead, + isWrite: isWrite, + isAppend: isAppend, + error: false, + eof: false, + ungotten: [] + }); + } + return id; + } + function _close(fildes) { + // int close(int fildes); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/close.html + if (FS.streams[fildes]) { + if (FS.streams[fildes].currentEntry) { + _free(FS.streams[fildes].currentEntry); + } + FS.streams[fildes] = null; + return 0; + } else { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + } + function _recv(fd, buf, len, flags) { + var info = FS.streams[fd]; + if (!info) return -1; + if (!info.hasData()) { + ___setErrNo(ERRNO_CODES.EAGAIN); // no data, and all sockets are nonblocking, so this is the right behavior + return -1; + } + var buffer = info.inQueue.shift(); + if (len < buffer.length) { + if (info.stream) { + // This is tcp (reliable), so if not all was read, keep it + info.inQueue.unshift(buffer.subarray(len)); + } + buffer = buffer.subarray(0, len); + } + HEAPU8.set(buffer, buf); + return buffer.length; + } + function _pread(fildes, buf, nbyte, offset) { + // ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.streams[fildes]; + if (!stream || stream.object.isDevice) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } else if (!stream.isRead) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } else if (stream.object.isFolder) { + ___setErrNo(ERRNO_CODES.EISDIR); + return -1; + } else if (nbyte < 0 || offset < 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } else { + var bytesRead = 0; + while (stream.ungotten.length && nbyte > 0) { + HEAP8[((buf++)|0)]=stream.ungotten.pop() + nbyte--; + bytesRead++; + } + var contents = stream.object.contents; + var size = Math.min(contents.length - offset, nbyte); + if (contents.subarray) { // typed array + HEAPU8.set(contents.subarray(offset, offset+size), buf); + } else + if (contents.slice) { // normal array + for (var i = 0; i < size; i++) { + HEAP8[(((buf)+(i))|0)]=contents[offset + i] + } + } else { + for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR + HEAP8[(((buf)+(i))|0)]=contents.get(offset + i) + } + } + bytesRead += size; + return bytesRead; + } + }function _read(fildes, buf, nbyte) { + // ssize_t read(int fildes, void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.streams[fildes]; + if (stream && ('socket' in stream)) { + return _recv(fildes, buf, nbyte, 0); + } else if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } else if (!stream.isRead) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } else if (nbyte < 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } else { + var bytesRead; + if (stream.object.isDevice) { + if (stream.object.input) { + bytesRead = 0; + while (stream.ungotten.length && nbyte > 0) { + HEAP8[((buf++)|0)]=stream.ungotten.pop() + nbyte--; + bytesRead++; + } + for (var i = 0; i < nbyte; i++) { + try { + var result = stream.object.input(); + } catch (e) { + ___setErrNo(ERRNO_CODES.EIO); + return -1; + } + if (result === undefined && bytesRead === 0) { + ___setErrNo(ERRNO_CODES.EAGAIN); + return -1; + } + if (result === null || result === undefined) break; + bytesRead++; + HEAP8[(((buf)+(i))|0)]=result + } + return bytesRead; + } else { + ___setErrNo(ERRNO_CODES.ENXIO); + return -1; + } + } else { + var ungotSize = stream.ungotten.length; + bytesRead = _pread(fildes, buf, nbyte, stream.position); + if (bytesRead != -1) { + stream.position += (stream.ungotten.length - ungotSize) + bytesRead; + } + return bytesRead; + } + } + } + var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"No message of desired type",36:"Identifier removed",37:"Channel number out of range",38:"Level 2 not synchronized",39:"Level 3 halted",40:"Level 3 reset",41:"Link number out of range",42:"Protocol driver not attached",43:"No CSI structure available",44:"Level 2 halted",45:"Deadlock condition",46:"No record locks available",50:"Invalid exchange",51:"Invalid request descriptor",52:"Exchange full",53:"No anode",54:"Invalid request code",55:"Invalid slot",56:"File locking deadlock error",57:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",74:"Multihop attempted",75:"Inode is remote (not really error)",76:"Cross mount point (not really error)",77:"Trying to read unreadable message",79:"Inappropriate file type or format",80:"Given log. name not unique",81:"f.d. invalid for this operation",82:"Remote address changed",83:"Can\t access a needed shared lib",84:"Accessing a corrupted shared lib",85:".lib section in a.out corrupted",86:"Attempting to link in too many libs",87:"Attempting to exec a shared library",88:"Function not implemented",89:"No more files",90:"Directory not empty",91:"File or path name too long",92:"Too many symbolic links",95:"Operation not supported on transport endpoint",96:"Protocol family not supported",104:"Connection reset by peer",105:"No buffer space available",106:"Address family not supported by protocol family",107:"Protocol wrong type for socket",108:"Socket operation on non-socket",109:"Protocol not available",110:"Can't send after socket shutdown",111:"Connection refused",112:"Address already in use",113:"Connection aborted",114:"Network is unreachable",115:"Network interface is not configured",116:"Connection timed out",117:"Host is down",118:"Host is unreachable",119:"Connection already in progress",120:"Socket already connected",121:"Destination address required",122:"Message too long",123:"Unknown protocol",124:"Socket type not supported",125:"Address not available",126:"ENETRESET",127:"Socket is already connected",128:"Socket is not connected",129:"TOOMANYREFS",130:"EPROCLIM",131:"EUSERS",132:"EDQUOT",133:"ESTALE",134:"Not supported",135:"No medium (in tape drive)",136:"No such host or network path",137:"Filename exists with different case",138:"EILSEQ",139:"Value too large for defined data type",140:"Operation canceled",141:"State not recoverable",142:"Previous owner died",143:"Streams pipe error"};function _strerror_r(errnum, strerrbuf, buflen) { + if (errnum in ERRNO_MESSAGES) { + if (ERRNO_MESSAGES[errnum].length > buflen - 1) { + return ___setErrNo(ERRNO_CODES.ERANGE); + } else { + var msg = ERRNO_MESSAGES[errnum]; + for (var i = 0; i < msg.length; i++) { + HEAP8[(((strerrbuf)+(i))|0)]=msg.charCodeAt(i) + } + HEAP8[(((strerrbuf)+(i))|0)]=0 + return 0; + } + } else { + return ___setErrNo(ERRNO_CODES.EINVAL); + } + }function _strerror(errnum) { + if (!_strerror.buffer) _strerror.buffer = _malloc(256); + _strerror_r(errnum, _strerror.buffer, 256); + return _strerror.buffer; + } + function ___errno_location() { + return ___errno_state; + }var ___errno=___errno_location; + function _send(fd, buf, len, flags) { + var info = FS.streams[fd]; + if (!info) return -1; + info.sender(HEAPU8.subarray(buf, buf+len)); + return len; + } + function _pwrite(fildes, buf, nbyte, offset) { + // ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.streams[fildes]; + if (!stream || stream.object.isDevice) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } else if (!stream.isWrite) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } else if (stream.object.isFolder) { + ___setErrNo(ERRNO_CODES.EISDIR); + return -1; + } else if (nbyte < 0 || offset < 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } else { + var contents = stream.object.contents; + while (contents.length < offset) contents.push(0); + for (var i = 0; i < nbyte; i++) { + contents[offset + i] = HEAPU8[(((buf)+(i))|0)]; + } + stream.object.timestamp = Date.now(); + return i; + } + }function _write(fildes, buf, nbyte) { + // ssize_t write(int fildes, const void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.streams[fildes]; + if (stream && ('socket' in stream)) { + return _send(fildes, buf, nbyte, 0); + } else if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } else if (!stream.isWrite) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } else if (nbyte < 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } else { + if (stream.object.isDevice) { + if (stream.object.output) { + for (var i = 0; i < nbyte; i++) { + try { + stream.object.output(HEAP8[(((buf)+(i))|0)]); + } catch (e) { + ___setErrNo(ERRNO_CODES.EIO); + return -1; + } + } + stream.object.timestamp = Date.now(); + return i; + } else { + ___setErrNo(ERRNO_CODES.ENXIO); + return -1; + } + } else { + var bytesWritten = _pwrite(fildes, buf, nbyte, stream.position); + if (bytesWritten != -1) stream.position += bytesWritten; + return bytesWritten; + } + } + } + function _llvm_bswap_i32(x) { + return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24); + } + function _abort() { + ABORT = true; + throw 'abort() at ' + (new Error().stack); + } + function _sysconf(name) { + // long sysconf(int name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/sysconf.html + switch(name) { + case 8: return PAGE_SIZE; + case 54: + case 56: + case 21: + case 61: + case 63: + case 22: + case 67: + case 23: + case 24: + case 25: + case 26: + case 27: + case 69: + case 28: + case 101: + case 70: + case 71: + case 29: + case 30: + case 199: + case 75: + case 76: + case 32: + case 43: + case 44: + case 80: + case 46: + case 47: + case 45: + case 48: + case 49: + case 42: + case 82: + case 33: + case 7: + case 108: + case 109: + case 107: + case 112: + case 119: + case 121: + return 200809; + case 13: + case 104: + case 94: + case 95: + case 34: + case 35: + case 77: + case 81: + case 83: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 90: + case 91: + case 94: + case 95: + case 110: + case 111: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + case 120: + case 40: + case 16: + case 79: + case 19: + return -1; + case 92: + case 93: + case 5: + case 72: + case 6: + case 74: + case 92: + case 93: + case 96: + case 97: + case 98: + case 99: + case 102: + case 103: + case 105: + return 1; + case 38: + case 66: + case 50: + case 51: + case 4: + return 1024; + case 15: + case 64: + case 41: + return 32; + case 55: + case 37: + case 17: + return 2147483647; + case 18: + case 1: + return 47839; + case 59: + case 57: + return 99; + case 68: + case 58: + return 2048; + case 0: return 2097152; + case 3: return 65536; + case 14: return 32768; + case 73: return 32767; + case 39: return 16384; + case 60: return 1000; + case 106: return 700; + case 52: return 256; + case 62: return 255; + case 2: return 100; + case 65: return 64; + case 36: return 20; + case 100: return 16; + case 20: return 6; + case 53: return 4; + case 10: return 1; + } + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + function _time(ptr) { + var ret = Math.floor(Date.now()/1000); + if (ptr) { + HEAP32[((ptr)>>2)]=ret + } + return ret; + } + function _sbrk(bytes) { + // Implement a Linux-like 'memory area' for our 'process'. + // Changes the size of the memory area by |bytes|; returns the + // address of the previous top ('break') of the memory area + // We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP + var self = _sbrk; + if (!self.called) { + DYNAMICTOP = alignMemoryPage(DYNAMICTOP); // make sure we start out aligned + self.called = true; + assert(Runtime.dynamicAlloc); + self.alloc = Runtime.dynamicAlloc; + Runtime.dynamicAlloc = function() { abort('cannot dynamically allocate, sbrk now has control') }; + } + var ret = DYNAMICTOP; + if (bytes != 0) self.alloc(bytes); + return ret; // Previous break location. + } + var Browser={mainLoop:{scheduler:null,shouldPause:false,paused:false,queue:[],pause:function () { + Browser.mainLoop.shouldPause = true; + },resume:function () { + if (Browser.mainLoop.paused) { + Browser.mainLoop.paused = false; + Browser.mainLoop.scheduler(); + } + Browser.mainLoop.shouldPause = false; + },updateStatus:function () { + if (Module['setStatus']) { + var message = Module['statusMessage'] || 'Please wait...'; + var remaining = Browser.mainLoop.remainingBlockers; + var expected = Browser.mainLoop.expectedBlockers; + if (remaining) { + if (remaining < expected) { + Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')'); + } else { + Module['setStatus'](message); + } + } else { + Module['setStatus'](''); + } + } + }},isFullScreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function () { + if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers + if (Browser.initted || ENVIRONMENT_IS_WORKER) return; + Browser.initted = true; + try { + new Blob(); + Browser.hasBlobConstructor = true; + } catch(e) { + Browser.hasBlobConstructor = false; + console.log("warning: no blob constructor, cannot create blobs with mimetypes"); + } + Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null)); + Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : console.log("warning: cannot create object URLs"); + // Support for plugins that can process preloaded files. You can add more of these to + // your app by creating and appending to Module.preloadPlugins. + // + // Each plugin is asked if it can handle a file based on the file's name. If it can, + // it is given the file's raw data. When it is done, it calls a callback with the file's + // (possibly modified) data. For example, a plugin might decompress a file, or it + // might create some side data structure for use later (like an Image element, etc.). + function getMimetype(name) { + return { + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'png': 'image/png', + 'bmp': 'image/bmp', + 'ogg': 'audio/ogg', + 'wav': 'audio/wav', + 'mp3': 'audio/mpeg' + }[name.substr(name.lastIndexOf('.')+1)]; + } + var imagePlugin = {}; + imagePlugin['canHandle'] = function(name) { + return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name); + }; + imagePlugin['handle'] = function(byteArray, name, onload, onerror) { + var b = null; + if (Browser.hasBlobConstructor) { + try { + b = new Blob([byteArray], { type: getMimetype(name) }); + } catch(e) { + Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder'); + } + } + if (!b) { + var bb = new Browser.BlobBuilder(); + bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range + b = bb.getBlob(); + } + var url = Browser.URLObject.createObjectURL(b); + var img = new Image(); + img.onload = function() { + assert(img.complete, 'Image ' + name + ' could not be decoded'); + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + Module["preloadedImages"][name] = canvas; + Browser.URLObject.revokeObjectURL(url); + if (onload) onload(byteArray); + }; + img.onerror = function(event) { + console.log('Image ' + url + ' could not be decoded'); + if (onerror) onerror(); + }; + img.src = url; + }; + Module['preloadPlugins'].push(imagePlugin); + var audioPlugin = {}; + audioPlugin['canHandle'] = function(name) { + return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; + }; + audioPlugin['handle'] = function(byteArray, name, onload, onerror) { + var done = false; + function finish(audio) { + if (done) return; + done = true; + Module["preloadedAudios"][name] = audio; + if (onload) onload(byteArray); + } + function fail() { + if (done) return; + done = true; + Module["preloadedAudios"][name] = new Audio(); // empty shim + if (onerror) onerror(); + } + if (Browser.hasBlobConstructor) { + try { + var b = new Blob([byteArray], { type: getMimetype(name) }); + } catch(e) { + return fail(); + } + var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! + var audio = new Audio(); + audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926 + audio.onerror = function(event) { + if (done) return; + console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach'); + function encode64(data) { + var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + var PAD = '='; + var ret = ''; + var leftchar = 0; + var leftbits = 0; + for (var i = 0; i < data.length; i++) { + leftchar = (leftchar << 8) | data[i]; + leftbits += 8; + while (leftbits >= 6) { + var curr = (leftchar >> (leftbits-6)) & 0x3f; + leftbits -= 6; + ret += BASE[curr]; + } + } + if (leftbits == 2) { + ret += BASE[(leftchar&3) << 4]; + ret += PAD + PAD; + } else if (leftbits == 4) { + ret += BASE[(leftchar&0xf) << 2]; + ret += PAD; + } + return ret; + } + audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray); + finish(audio); // we don't wait for confirmation this worked - but it's worth trying + }; + audio.src = url; + // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror + Browser.safeSetTimeout(function() { + finish(audio); // try to use it even though it is not necessarily ready to play + }, 10000); + } else { + return fail(); + } + }; + Module['preloadPlugins'].push(audioPlugin); + // Canvas event setup + var canvas = Module['canvas']; + canvas.requestPointerLock = canvas['requestPointerLock'] || + canvas['mozRequestPointerLock'] || + canvas['webkitRequestPointerLock']; + canvas.exitPointerLock = document['exitPointerLock'] || + document['mozExitPointerLock'] || + document['webkitExitPointerLock'] || + function(){}; // no-op if function does not exist + canvas.exitPointerLock = canvas.exitPointerLock.bind(document); + function pointerLockChange() { + Browser.pointerLock = document['pointerLockElement'] === canvas || + document['mozPointerLockElement'] === canvas || + document['webkitPointerLockElement'] === canvas; + } + document.addEventListener('pointerlockchange', pointerLockChange, false); + document.addEventListener('mozpointerlockchange', pointerLockChange, false); + document.addEventListener('webkitpointerlockchange', pointerLockChange, false); + if (Module['elementPointerLock']) { + canvas.addEventListener("click", function(ev) { + if (!Browser.pointerLock && canvas.requestPointerLock) { + canvas.requestPointerLock(); + ev.preventDefault(); + } + }, false); + } + },createContext:function (canvas, useWebGL, setInModule) { + var ctx; + try { + if (useWebGL) { + ctx = canvas.getContext('experimental-webgl', { + alpha: false + }); + } else { + ctx = canvas.getContext('2d'); + } + if (!ctx) throw ':('; + } catch (e) { + Module.print('Could not create canvas - ' + e); + return null; + } + if (useWebGL) { + // Set the background of the WebGL canvas to black + canvas.style.backgroundColor = "black"; + // Warn on context loss + canvas.addEventListener('webglcontextlost', function(event) { + alert('WebGL context lost. You will need to reload the page.'); + }, false); + } + if (setInModule) { + Module.ctx = ctx; + Module.useWebGL = useWebGL; + Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); + Browser.init(); + } + return ctx; + },destroyContext:function (canvas, useWebGL, setInModule) {},fullScreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullScreen:function (lockPointer, resizeCanvas) { + Browser.lockPointer = lockPointer; + Browser.resizeCanvas = resizeCanvas; + if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true; + if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false; + var canvas = Module['canvas']; + function fullScreenChange() { + Browser.isFullScreen = false; + if ((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement']) === canvas) { + canvas.cancelFullScreen = document['cancelFullScreen'] || + document['mozCancelFullScreen'] || + document['webkitCancelFullScreen']; + canvas.cancelFullScreen = canvas.cancelFullScreen.bind(document); + if (Browser.lockPointer) canvas.requestPointerLock(); + Browser.isFullScreen = true; + if (Browser.resizeCanvas) Browser.setFullScreenCanvasSize(); + } else if (Browser.resizeCanvas){ + Browser.setWindowedCanvasSize(); + } + if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullScreen); + } + if (!Browser.fullScreenHandlersInstalled) { + Browser.fullScreenHandlersInstalled = true; + document.addEventListener('fullscreenchange', fullScreenChange, false); + document.addEventListener('mozfullscreenchange', fullScreenChange, false); + document.addEventListener('webkitfullscreenchange', fullScreenChange, false); + } + canvas.requestFullScreen = canvas['requestFullScreen'] || + canvas['mozRequestFullScreen'] || + (canvas['webkitRequestFullScreen'] ? function() { canvas['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null); + canvas.requestFullScreen(); + },requestAnimationFrame:function (func) { + if (!window.requestAnimationFrame) { + window.requestAnimationFrame = window['requestAnimationFrame'] || + window['mozRequestAnimationFrame'] || + window['webkitRequestAnimationFrame'] || + window['msRequestAnimationFrame'] || + window['oRequestAnimationFrame'] || + window['setTimeout']; + } + window.requestAnimationFrame(func); + },safeCallback:function (func) { + return function() { + if (!ABORT) return func.apply(null, arguments); + }; + },safeRequestAnimationFrame:function (func) { + return Browser.requestAnimationFrame(function() { + if (!ABORT) func(); + }); + },safeSetTimeout:function (func, timeout) { + return setTimeout(function() { + if (!ABORT) func(); + }, timeout); + },safeSetInterval:function (func, timeout) { + return setInterval(function() { + if (!ABORT) func(); + }, timeout); + },getUserMedia:function (func) { + if(!window.getUserMedia) { + window.getUserMedia = navigator['getUserMedia'] || + navigator['mozGetUserMedia']; + } + window.getUserMedia(func); + },getMovementX:function (event) { + return event['movementX'] || + event['mozMovementX'] || + event['webkitMovementX'] || + 0; + },getMovementY:function (event) { + return event['movementY'] || + event['mozMovementY'] || + event['webkitMovementY'] || + 0; + },mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,calculateMouseEvent:function (event) { // event should be mousemove, mousedown or mouseup + if (Browser.pointerLock) { + // When the pointer is locked, calculate the coordinates + // based on the movement of the mouse. + // Workaround for Firefox bug 764498 + if (event.type != 'mousemove' && + ('mozMovementX' in event)) { + Browser.mouseMovementX = Browser.mouseMovementY = 0; + } else { + Browser.mouseMovementX = Browser.getMovementX(event); + Browser.mouseMovementY = Browser.getMovementY(event); + } + // check if SDL is available + if (typeof SDL != "undefined") { + Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; + Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; + } else { + // just add the mouse delta to the current absolut mouse position + // FIXME: ideally this should be clamped against the canvas size and zero + Browser.mouseX += Browser.mouseMovementX; + Browser.mouseY += Browser.mouseMovementY; + } + } else { + // Otherwise, calculate the movement based on the changes + // in the coordinates. + var rect = Module["canvas"].getBoundingClientRect(); + var x = event.pageX - (window.scrollX + rect.left); + var y = event.pageY - (window.scrollY + rect.top); + // the canvas might be CSS-scaled compared to its backbuffer; + // SDL-using content will want mouse coordinates in terms + // of backbuffer units. + var cw = Module["canvas"].width; + var ch = Module["canvas"].height; + x = x * (cw / rect.width); + y = y * (ch / rect.height); + Browser.mouseMovementX = x - Browser.mouseX; + Browser.mouseMovementY = y - Browser.mouseY; + Browser.mouseX = x; + Browser.mouseY = y; + } + },xhrLoad:function (url, onload, onerror) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = function() { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + } else { + onerror(); + } + }; + xhr.onerror = onerror; + xhr.send(null); + },asyncLoad:function (url, onload, onerror, noRunDep) { + Browser.xhrLoad(url, function(arrayBuffer) { + assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).'); + onload(new Uint8Array(arrayBuffer)); + if (!noRunDep) removeRunDependency('al ' + url); + }, function(event) { + if (onerror) { + onerror(); + } else { + throw 'Loading data file "' + url + '" failed.'; + } + }); + if (!noRunDep) addRunDependency('al ' + url); + },resizeListeners:[],updateResizeListeners:function () { + var canvas = Module['canvas']; + Browser.resizeListeners.forEach(function(listener) { + listener(canvas.width, canvas.height); + }); + },setCanvasSize:function (width, height, noUpdates) { + var canvas = Module['canvas']; + canvas.width = width; + canvas.height = height; + if (!noUpdates) Browser.updateResizeListeners(); + },windowedWidth:0,windowedHeight:0,setFullScreenCanvasSize:function () { + var canvas = Module['canvas']; + this.windowedWidth = canvas.width; + this.windowedHeight = canvas.height; + canvas.width = screen.width; + canvas.height = screen.height; + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags | 0x00800000; // set SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },setWindowedCanvasSize:function () { + var canvas = Module['canvas']; + canvas.width = this.windowedWidth; + canvas.height = this.windowedHeight; + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + }}; +__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });__ATEXIT__.push({ func: function() { FS.quit() } });Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice; +___errno_state = Runtime.staticAlloc(4); HEAP32[((___errno_state)>>2)]=0; +Module["requestFullScreen"] = function(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) }; + Module["requestAnimationFrame"] = function(func) { Browser.requestAnimationFrame(func) }; + Module["pauseMainLoop"] = function() { Browser.mainLoop.pause() }; + Module["resumeMainLoop"] = function() { Browser.mainLoop.resume() }; + Module["getUserMedia"] = function() { Browser.getUserMedia() } +STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP); +staticSealed = true; // seal the static portion of memory +STACK_MAX = STACK_BASE + 5242880; +DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX); +assert(DYNAMIC_BASE < TOTAL_MEMORY); // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY +var Math_min = Math.min; +function invoke_ii(index,a1) { + try { + return Module["dynCall_ii"](index,a1); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function invoke_vi(index,a1) { + try { + Module["dynCall_vi"](index,a1); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function invoke_vii(index,a1,a2) { + try { + Module["dynCall_vii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function invoke_iiii(index,a1,a2,a3) { + try { + return Module["dynCall_iiii"](index,a1,a2,a3); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function invoke_v(index) { + try { + Module["dynCall_v"](index); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function invoke_iii(index,a1,a2) { + try { + return Module["dynCall_iii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function asmPrintInt(x, y) { + Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack); +} +function asmPrintFloat(x, y) { + Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack); +} +// EMSCRIPTEN_START_ASM +var asm=(function(global,env,buffer){"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=+env.NaN;var n=+env.Infinity;var o=0;var p=0;var q=0;var r=0;var s=0,t=0,u=0,v=0,w=0.0,x=0,y=0,z=0,A=0.0;var B=0;var C=0;var D=0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=global.Math.floor;var M=global.Math.abs;var N=global.Math.sqrt;var O=global.Math.pow;var P=global.Math.cos;var Q=global.Math.sin;var R=global.Math.tan;var S=global.Math.acos;var T=global.Math.asin;var U=global.Math.atan;var V=global.Math.atan2;var W=global.Math.exp;var X=global.Math.log;var Y=global.Math.ceil;var Z=global.Math.imul;var _=env.abort;var $=env.assert;var aa=env.asmPrintInt;var ab=env.asmPrintFloat;var ac=env.min;var ad=env.invoke_ii;var ae=env.invoke_vi;var af=env.invoke_vii;var ag=env.invoke_iiii;var ah=env.invoke_v;var ai=env.invoke_iii;var aj=env._llvm_lifetime_end;var ak=env._lseek;var al=env._sysconf;var am=env._abort;var an=env._close;var ao=env._pread;var ap=env._open;var aq=env.___setErrNo;var ar=env._send;var as=env._write;var at=env._read;var au=env._recv;var av=env._pwrite;var aw=env._sbrk;var ax=env._strerror_r;var ay=env.___errno_location;var az=env._strerror;var aA=env._llvm_lifetime_start;var aB=env._llvm_bswap_i32;var aC=env._time; +// EMSCRIPTEN_START_FUNCS +function aJ(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+7>>3<<3;return b|0}function aK(){return i|0}function aL(a){a=a|0;i=a}function aM(a,b){a=a|0;b=b|0;if((o|0)==0){o=a;p=b}}function aN(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0]}function aO(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0];a[k+4|0]=a[b+4|0];a[k+5|0]=a[b+5|0];a[k+6|0]=a[b+6|0];a[k+7|0]=a[b+7|0]}function aP(a){a=a|0;B=a}function aQ(a){a=a|0;C=a}function aR(a){a=a|0;D=a}function aS(a){a=a|0;E=a}function aT(a){a=a|0;F=a}function aU(a){a=a|0;G=a}function aV(a){a=a|0;H=a}function aW(a){a=a|0;I=a}function aX(a){a=a|0;J=a}function aY(a){a=a|0;K=a}function aZ(){}function a_(a,b,c){a=a|0;b=b|0;c=c|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0;e=a>>>16;f=a&65535;if((c|0)==1){a=(d[b]|0)+f|0;g=a>>>0>65520?a-65521|0:a;a=g+e|0;h=(a>>>0>65520?a+15|0:a)<<16|g;return h|0}if((b|0)==0){h=1;return h|0}if(c>>>0<16){if((c|0)==0){i=f;j=e}else{g=f;a=b;k=c;l=e;while(1){m=k-1|0;n=(d[a]|0)+g|0;o=n+l|0;if((m|0)==0){i=n;j=o;break}else{g=n;a=a+1|0;k=m;l=o}}}h=((j>>>0)%65521|0)<<16|(i>>>0>65520?i-65521|0:i);return h|0}do{if(c>>>0>5551){i=f;j=b;l=c;k=e;do{l=l-5552|0;a=347;g=k;o=j;m=i;while(1){n=(d[o]|0)+m|0;p=n+(d[o+1|0]|0)|0;q=p+(d[o+2|0]|0)|0;r=q+(d[o+3|0]|0)|0;s=r+(d[o+4|0]|0)|0;t=s+(d[o+5|0]|0)|0;u=t+(d[o+6|0]|0)|0;v=u+(d[o+7|0]|0)|0;w=v+(d[o+8|0]|0)|0;x=w+(d[o+9|0]|0)|0;y=x+(d[o+10|0]|0)|0;z=y+(d[o+11|0]|0)|0;A=z+(d[o+12|0]|0)|0;B=A+(d[o+13|0]|0)|0;C=B+(d[o+14|0]|0)|0;D=C+(d[o+15|0]|0)|0;E=n+g+p+q+r+s+t+u+v+w+x+y+z+A+B+C+D|0;C=a-1|0;if((C|0)==0){break}else{a=C;g=E;o=o+16|0;m=D}}j=j+5552|0;i=(D>>>0)%65521|0;k=(E>>>0)%65521|0;}while(l>>>0>5551);if((l|0)==0){F=k;G=i;break}if(l>>>0>15){H=i;I=j;J=l;K=k;L=15}else{M=i;N=j;O=l;P=k;L=16}}else{H=f;I=b;J=c;K=e;L=15}}while(0);if((L|0)==15){while(1){L=0;Q=J-16|0;e=(d[I]|0)+H|0;c=e+(d[I+1|0]|0)|0;b=c+(d[I+2|0]|0)|0;f=b+(d[I+3|0]|0)|0;E=f+(d[I+4|0]|0)|0;D=E+(d[I+5|0]|0)|0;m=D+(d[I+6|0]|0)|0;o=m+(d[I+7|0]|0)|0;g=o+(d[I+8|0]|0)|0;a=g+(d[I+9|0]|0)|0;C=a+(d[I+10|0]|0)|0;B=C+(d[I+11|0]|0)|0;A=B+(d[I+12|0]|0)|0;z=A+(d[I+13|0]|0)|0;y=z+(d[I+14|0]|0)|0;R=y+(d[I+15|0]|0)|0;S=e+K+c+b+f+E+D+m+o+g+a+C+B+A+z+y+R|0;T=I+16|0;if(Q>>>0>15){H=R;I=T;J=Q;K=S;L=15}else{break}}if((Q|0)==0){U=R;V=S;L=17}else{M=R;N=T;O=Q;P=S;L=16}}if((L|0)==16){while(1){L=0;S=O-1|0;Q=(d[N]|0)+M|0;T=Q+P|0;if((S|0)==0){U=Q;V=T;L=17;break}else{M=Q;N=N+1|0;O=S;P=T;L=16}}}if((L|0)==17){F=(V>>>0)%65521|0;G=(U>>>0)%65521|0}h=F<<16|G;return h|0}function a$(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;if((b|0)==0){f=0;return f|0}g=~a;L39:do{if((e|0)==0){h=g}else{a=b;i=e;j=g;while(1){if((a&3|0)==0){break}k=c[4200+(((d[a]|0)^j&255)<<2)>>2]^j>>>8;l=i-1|0;if((l|0)==0){h=k;break L39}else{a=a+1|0;i=l;j=k}}k=a;if(i>>>0>31){l=i;m=j;n=k;while(1){o=c[n>>2]^m;p=c[6248+((o>>>8&255)<<2)>>2]^c[7272+((o&255)<<2)>>2]^c[5224+((o>>>16&255)<<2)>>2]^c[4200+(o>>>24<<2)>>2]^c[n+4>>2];o=c[6248+((p>>>8&255)<<2)>>2]^c[7272+((p&255)<<2)>>2]^c[5224+((p>>>16&255)<<2)>>2]^c[4200+(p>>>24<<2)>>2]^c[n+8>>2];p=c[6248+((o>>>8&255)<<2)>>2]^c[7272+((o&255)<<2)>>2]^c[5224+((o>>>16&255)<<2)>>2]^c[4200+(o>>>24<<2)>>2]^c[n+12>>2];o=c[6248+((p>>>8&255)<<2)>>2]^c[7272+((p&255)<<2)>>2]^c[5224+((p>>>16&255)<<2)>>2]^c[4200+(p>>>24<<2)>>2]^c[n+16>>2];p=c[6248+((o>>>8&255)<<2)>>2]^c[7272+((o&255)<<2)>>2]^c[5224+((o>>>16&255)<<2)>>2]^c[4200+(o>>>24<<2)>>2]^c[n+20>>2];o=c[6248+((p>>>8&255)<<2)>>2]^c[7272+((p&255)<<2)>>2]^c[5224+((p>>>16&255)<<2)>>2]^c[4200+(p>>>24<<2)>>2]^c[n+24>>2];p=n+32|0;q=c[6248+((o>>>8&255)<<2)>>2]^c[7272+((o&255)<<2)>>2]^c[5224+((o>>>16&255)<<2)>>2]^c[4200+(o>>>24<<2)>>2]^c[n+28>>2];o=c[6248+((q>>>8&255)<<2)>>2]^c[7272+((q&255)<<2)>>2]^c[5224+((q>>>16&255)<<2)>>2]^c[4200+(q>>>24<<2)>>2];q=l-32|0;if(q>>>0>31){l=q;m=o;n=p}else{r=q;s=o;t=p;break}}}else{r=i;s=j;t=k}if(r>>>0>3){n=r;m=s;l=t;while(1){a=l+4|0;p=c[l>>2]^m;o=c[6248+((p>>>8&255)<<2)>>2]^c[7272+((p&255)<<2)>>2]^c[5224+((p>>>16&255)<<2)>>2]^c[4200+(p>>>24<<2)>>2];p=n-4|0;if(p>>>0>3){n=p;m=o;l=a}else{u=p;v=o;w=a;break}}}else{u=r;v=s;w=t}if((u|0)==0){h=v;break}l=v;m=u;n=w;while(1){k=c[4200+(((d[n]|0)^l&255)<<2)>>2]^l>>>8;j=m-1|0;if((j|0)==0){h=k;break}else{l=k;m=j;n=n+1|0}}}}while(0);f=~h;return f|0}function a0(b,d,e,f,g,h,i,j){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0;if((i|0)==0){k=-6;return k|0}if(!((a[i]|0)==49&(j|0)==56)){k=-6;return k|0}if((b|0)==0){k=-2;return k|0}j=b+24|0;c[j>>2]=0;i=b+32|0;l=c[i>>2]|0;if((l|0)==0){c[i>>2]=6;c[b+40>>2]=0;m=6}else{m=l}l=b+36|0;if((c[l>>2]|0)==0){c[l>>2]=2}l=(d|0)==-1?6:d;if((f|0)<0){n=0;o=-f|0}else{d=(f|0)>15;n=d?2:1;o=d?f-16|0:f}if(!((g-1|0)>>>0<9&(e|0)==8)){k=-2;return k|0}if((o-8|0)>>>0>7|l>>>0>9|h>>>0>4){k=-2;return k|0}e=(o|0)==8?9:o;o=b+40|0;f=aG[m&7](c[o>>2]|0,1,5828)|0;if((f|0)==0){k=-4;return k|0}c[b+28>>2]=f;c[f>>2]=b;c[f+24>>2]=n;c[f+28>>2]=0;c[f+48>>2]=e;n=1<>2]=n;c[f+52>>2]=n-1;m=g+7|0;c[f+80>>2]=m;d=1<>2]=d;c[f+84>>2]=d-1;c[f+88>>2]=((g+9|0)>>>0)/3|0;d=f+56|0;c[d>>2]=aG[c[i>>2]&7](c[o>>2]|0,n,2)|0;n=aG[c[i>>2]&7](c[o>>2]|0,c[e>>2]|0,2)|0;p=f+64|0;c[p>>2]=n;bI(n|0,0,c[e>>2]<<1|0);e=f+68|0;c[e>>2]=aG[c[i>>2]&7](c[o>>2]|0,c[m>>2]|0,2)|0;c[f+5824>>2]=0;m=1<>2]=m;n=aG[c[i>>2]&7](c[o>>2]|0,m,4)|0;m=n;c[f+8>>2]=n;o=c[g>>2]|0;c[f+12>>2]=o<<2;do{if((c[d>>2]|0)!=0){if((c[p>>2]|0)==0){break}if((c[e>>2]|0)==0|(n|0)==0){break}c[f+5796>>2]=m+(o>>>1<<1);c[f+5784>>2]=n+(o*3|0);c[f+132>>2]=l;c[f+136>>2]=h;a[f+36|0]=8;k=a2(b)|0;return k|0}}while(0);c[f+4>>2]=666;c[j>>2]=c[8];a1(b)|0;k=-4;return k|0}function a1(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;if((a|0)==0){b=-2;return b|0}d=a+28|0;e=c[d>>2]|0;if((e|0)==0){b=-2;return b|0}f=c[e+4>>2]|0;if(!((f|0)==666|(f|0)==113|(f|0)==103|(f|0)==91|(f|0)==73|(f|0)==69|(f|0)==42)){b=-2;return b|0}g=c[e+8>>2]|0;if((g|0)==0){h=e}else{aF[c[a+36>>2]&3](c[a+40>>2]|0,g);h=c[d>>2]|0}g=c[h+68>>2]|0;if((g|0)==0){i=h}else{aF[c[a+36>>2]&3](c[a+40>>2]|0,g);i=c[d>>2]|0}g=c[i+64>>2]|0;if((g|0)==0){j=i}else{aF[c[a+36>>2]&3](c[a+40>>2]|0,g);j=c[d>>2]|0}g=c[j+56>>2]|0;i=a+36|0;if((g|0)==0){k=j;l=a+40|0}else{j=a+40|0;aF[c[i>>2]&3](c[j>>2]|0,g);k=c[d>>2]|0;l=j}aF[c[i>>2]&3](c[l>>2]|0,k);c[d>>2]=0;b=(f|0)==113?-3:0;return b|0}function a2(a){a=a|0;var d=0,f=0,g=0,h=0,i=0,j=0,k=0;if((a|0)==0){d=-2;return d|0}f=c[a+28>>2]|0;if((f|0)==0){d=-2;return d|0}if((c[a+32>>2]|0)==0){d=-2;return d|0}if((c[a+36>>2]|0)==0){d=-2;return d|0}c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+44>>2]=2;c[f+20>>2]=0;c[f+16>>2]=c[f+8>>2];g=f+24|0;h=c[g>>2]|0;if((h|0)<0){i=-h|0;c[g>>2]=i;j=i}else{j=h}c[f+4>>2]=(j|0)!=0?42:113;if((j|0)==2){k=a$(0,0,0)|0}else{k=a_(0,0,0)|0}c[a+48>>2]=k;c[f+40>>2]=0;bw(f);c[f+60>>2]=c[f+44>>2]<<1;k=f+76|0;a=f+68|0;b[(c[a>>2]|0)+((c[k>>2]|0)-1<<1)>>1]=0;bI(c[a>>2]|0,0,(c[k>>2]<<1)-2|0);k=c[f+132>>2]|0;c[f+128>>2]=e[12394+(k*12|0)>>1]|0;c[f+140>>2]=e[12392+(k*12|0)>>1]|0;c[f+144>>2]=e[12396+(k*12|0)>>1]|0;c[f+124>>2]=e[12398+(k*12|0)>>1]|0;c[f+108>>2]=0;c[f+92>>2]=0;c[f+116>>2]=0;c[f+120>>2]=2;c[f+96>>2]=2;c[f+112>>2]=0;c[f+104>>2]=0;c[f+72>>2]=0;d=0;return d|0}function a3(e,f){e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ab=0,ac=0,ad=0,ae=0,af=0,ag=0,ah=0,ai=0,aj=0,ak=0,al=0,am=0,an=0,ao=0,ap=0,aq=0,ar=0,as=0,at=0,au=0,av=0,aw=0,ax=0,ay=0,az=0,aA=0,aB=0;if((e|0)==0){g=-2;return g|0}h=e+28|0;i=c[h>>2]|0;if((i|0)==0|f>>>0>5){g=-2;return g|0}j=e+12|0;do{if((c[j>>2]|0)!=0){if((c[e>>2]|0)==0){if((c[e+4>>2]|0)!=0){break}}k=i+4|0;l=c[k>>2]|0;m=(f|0)==4;if(!((l|0)!=666|m)){break}n=e+16|0;if((c[n>>2]|0)==0){c[e+24>>2]=c[9];g=-5;return g|0}o=i|0;c[o>>2]=e;p=i+40|0;q=c[p>>2]|0;c[p>>2]=f;do{if((l|0)==42){if((c[i+24>>2]|0)!=2){r=(c[i+48>>2]<<12)-30720|0;do{if((c[i+136>>2]|0)>1){s=0}else{t=c[i+132>>2]|0;if((t|0)<2){s=0;break}if((t|0)<6){s=64;break}s=(t|0)==6?128:192}}while(0);t=s|r;u=i+108|0;v=(c[u>>2]|0)==0?t:t|32;t=(v|((v>>>0)%31|0))^31;c[k>>2]=113;v=i+20|0;w=c[v>>2]|0;c[v>>2]=w+1;x=i+8|0;a[(c[x>>2]|0)+w|0]=t>>>8&255;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[x>>2]|0)+w|0]=t&255;t=e+48|0;if((c[u>>2]|0)!=0){u=c[t>>2]|0;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[x>>2]|0)+w|0]=u>>>24&255;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[x>>2]|0)+w|0]=u>>>16&255;u=c[t>>2]|0;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[x>>2]|0)+w|0]=u>>>8&255;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[x>>2]|0)+w|0]=u&255}c[t>>2]=a_(0,0,0)|0;y=c[k>>2]|0;z=131;break}t=e+48|0;c[t>>2]=a$(0,0,0)|0;u=i+20|0;w=c[u>>2]|0;c[u>>2]=w+1;x=i+8|0;a[(c[x>>2]|0)+w|0]=31;w=c[u>>2]|0;c[u>>2]=w+1;a[(c[x>>2]|0)+w|0]=-117;w=c[u>>2]|0;c[u>>2]=w+1;a[(c[x>>2]|0)+w|0]=8;w=i+28|0;v=c[w>>2]|0;if((v|0)==0){A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[i+132>>2]|0;do{if((A|0)==9){B=2}else{if((c[i+136>>2]|0)>1){B=4;break}B=(A|0)<2?4:0}}while(0);A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=B;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=3;c[k>>2]=113;break}A=((c[v+44>>2]|0)!=0?2:0)|(c[v>>2]|0)!=0|((c[v+16>>2]|0)==0?0:4)|((c[v+28>>2]|0)==0?0:8)|((c[v+36>>2]|0)==0?0:16);r=c[u>>2]|0;c[u>>2]=r+1;a[(c[x>>2]|0)+r|0]=A;A=c[(c[w>>2]|0)+4>>2]&255;r=c[u>>2]|0;c[u>>2]=r+1;a[(c[x>>2]|0)+r|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>8&255;r=c[u>>2]|0;c[u>>2]=r+1;a[(c[x>>2]|0)+r|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>16&255;r=c[u>>2]|0;c[u>>2]=r+1;a[(c[x>>2]|0)+r|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>24&255;r=c[u>>2]|0;c[u>>2]=r+1;a[(c[x>>2]|0)+r|0]=A;A=c[i+132>>2]|0;do{if((A|0)==9){C=2}else{if((c[i+136>>2]|0)>1){C=4;break}C=(A|0)<2?4:0}}while(0);A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=C;A=c[(c[w>>2]|0)+12>>2]&255;v=c[u>>2]|0;c[u>>2]=v+1;a[(c[x>>2]|0)+v|0]=A;A=c[w>>2]|0;if((c[A+16>>2]|0)==0){D=A}else{v=c[A+20>>2]&255;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=v;v=(c[(c[w>>2]|0)+20>>2]|0)>>>8&255;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=v;D=c[w>>2]|0}if((c[D+44>>2]|0)!=0){c[t>>2]=a$(c[t>>2]|0,c[x>>2]|0,c[u>>2]|0)|0}c[i+32>>2]=0;c[k>>2]=69;E=w;z=133}else{y=l;z=131}}while(0);do{if((z|0)==131){if((y|0)!=69){F=y;z=154;break}E=i+28|0;z=133}}while(0);do{if((z|0)==133){l=c[E>>2]|0;if((c[l+16>>2]|0)==0){c[k>>2]=73;G=l;z=156;break}v=i+20|0;A=c[v>>2]|0;r=i+32|0;H=c[r>>2]|0;L193:do{if(H>>>0<(c[l+20>>2]&65535)>>>0){I=i+12|0;J=e+48|0;K=i+8|0;L=e+20|0;M=A;N=l;O=A;P=H;while(1){if((O|0)==(c[I>>2]|0)){if((c[N+44>>2]|0)!=0&O>>>0>M>>>0){c[J>>2]=a$(c[J>>2]|0,(c[K>>2]|0)+M|0,O-M|0)|0}Q=c[h>>2]|0;R=c[Q+20>>2]|0;S=c[n>>2]|0;T=R>>>0>S>>>0?S:R;do{if((T|0)!=0){R=c[j>>2]|0;S=c[Q+16>>2]|0;bJ(R|0,S|0,T)|0;c[j>>2]=(c[j>>2]|0)+T;S=(c[h>>2]|0)+16|0;c[S>>2]=(c[S>>2]|0)+T;c[L>>2]=(c[L>>2]|0)+T;c[n>>2]=(c[n>>2]|0)-T;S=(c[h>>2]|0)+20|0;c[S>>2]=(c[S>>2]|0)-T;S=c[h>>2]|0;if((c[S+20>>2]|0)!=0){break}c[S+16>>2]=c[S+8>>2]}}while(0);U=c[v>>2]|0;if((U|0)==(c[I>>2]|0)){break}V=U;W=U;X=c[r>>2]|0;Y=c[E>>2]|0}else{V=M;W=O;X=P;Y=N}T=a[(c[Y+16>>2]|0)+X|0]|0;c[v>>2]=W+1;a[(c[K>>2]|0)+W|0]=T;T=(c[r>>2]|0)+1|0;c[r>>2]=T;Q=c[E>>2]|0;if(T>>>0>=(c[Q+20>>2]&65535)>>>0){Z=V;_=Q;break L193}M=V;N=Q;O=c[v>>2]|0;P=T}Z=U;_=c[E>>2]|0}else{Z=A;_=l}}while(0);do{if((c[_+44>>2]|0)==0){$=_}else{l=c[v>>2]|0;if(l>>>0<=Z>>>0){$=_;break}A=e+48|0;c[A>>2]=a$(c[A>>2]|0,(c[i+8>>2]|0)+Z|0,l-Z|0)|0;$=c[E>>2]|0}}while(0);if((c[r>>2]|0)==(c[$+20>>2]|0)){c[r>>2]=0;c[k>>2]=73;G=$;z=156;break}else{F=c[k>>2]|0;z=154;break}}}while(0);do{if((z|0)==154){if((F|0)!=73){aa=F;z=175;break}G=c[i+28>>2]|0;z=156}}while(0);do{if((z|0)==156){v=i+28|0;if((c[G+28>>2]|0)==0){c[k>>2]=91;ab=v;z=177;break}l=i+20|0;A=c[l>>2]|0;H=i+12|0;w=e+48|0;u=i+8|0;x=e+20|0;t=i+32|0;P=A;O=A;while(1){if((O|0)==(c[H>>2]|0)){if((c[(c[v>>2]|0)+44>>2]|0)!=0&O>>>0>P>>>0){c[w>>2]=a$(c[w>>2]|0,(c[u>>2]|0)+P|0,O-P|0)|0}A=c[h>>2]|0;N=c[A+20>>2]|0;M=c[n>>2]|0;K=N>>>0>M>>>0?M:N;do{if((K|0)!=0){N=c[j>>2]|0;M=c[A+16>>2]|0;bJ(N|0,M|0,K)|0;c[j>>2]=(c[j>>2]|0)+K;M=(c[h>>2]|0)+16|0;c[M>>2]=(c[M>>2]|0)+K;c[x>>2]=(c[x>>2]|0)+K;c[n>>2]=(c[n>>2]|0)-K;M=(c[h>>2]|0)+20|0;c[M>>2]=(c[M>>2]|0)-K;M=c[h>>2]|0;if((c[M+20>>2]|0)!=0){break}c[M+16>>2]=c[M+8>>2]}}while(0);K=c[l>>2]|0;if((K|0)==(c[H>>2]|0)){ac=1;ad=K;break}else{ae=K;af=K}}else{ae=P;af=O}K=c[t>>2]|0;c[t>>2]=K+1;ag=a[(c[(c[v>>2]|0)+28>>2]|0)+K|0]|0;c[l>>2]=af+1;a[(c[u>>2]|0)+af|0]=ag;if(ag<<24>>24==0){z=167;break}P=ae;O=c[l>>2]|0}if((z|0)==167){ac=ag&255;ad=ae}do{if((c[(c[v>>2]|0)+44>>2]|0)!=0){O=c[l>>2]|0;if(O>>>0<=ad>>>0){break}c[w>>2]=a$(c[w>>2]|0,(c[u>>2]|0)+ad|0,O-ad|0)|0}}while(0);if((ac|0)==0){c[t>>2]=0;c[k>>2]=91;ab=v;z=177;break}else{aa=c[k>>2]|0;z=175;break}}}while(0);do{if((z|0)==175){if((aa|0)!=91){ah=aa;z=196;break}ab=i+28|0;z=177}}while(0);do{if((z|0)==177){if((c[(c[ab>>2]|0)+36>>2]|0)==0){c[k>>2]=103;ai=ab;z=198;break}u=i+20|0;w=c[u>>2]|0;l=i+12|0;O=e+48|0;P=i+8|0;H=e+20|0;x=i+32|0;r=w;K=w;while(1){if((K|0)==(c[l>>2]|0)){if((c[(c[ab>>2]|0)+44>>2]|0)!=0&K>>>0>r>>>0){c[O>>2]=a$(c[O>>2]|0,(c[P>>2]|0)+r|0,K-r|0)|0}w=c[h>>2]|0;A=c[w+20>>2]|0;M=c[n>>2]|0;N=A>>>0>M>>>0?M:A;do{if((N|0)!=0){A=c[j>>2]|0;M=c[w+16>>2]|0;bJ(A|0,M|0,N)|0;c[j>>2]=(c[j>>2]|0)+N;M=(c[h>>2]|0)+16|0;c[M>>2]=(c[M>>2]|0)+N;c[H>>2]=(c[H>>2]|0)+N;c[n>>2]=(c[n>>2]|0)-N;M=(c[h>>2]|0)+20|0;c[M>>2]=(c[M>>2]|0)-N;M=c[h>>2]|0;if((c[M+20>>2]|0)!=0){break}c[M+16>>2]=c[M+8>>2]}}while(0);N=c[u>>2]|0;if((N|0)==(c[l>>2]|0)){aj=1;ak=N;break}else{al=N;am=N}}else{al=r;am=K}N=c[x>>2]|0;c[x>>2]=N+1;an=a[(c[(c[ab>>2]|0)+36>>2]|0)+N|0]|0;c[u>>2]=am+1;a[(c[P>>2]|0)+am|0]=an;if(an<<24>>24==0){z=188;break}r=al;K=c[u>>2]|0}if((z|0)==188){aj=an&255;ak=al}do{if((c[(c[ab>>2]|0)+44>>2]|0)!=0){K=c[u>>2]|0;if(K>>>0<=ak>>>0){break}c[O>>2]=a$(c[O>>2]|0,(c[P>>2]|0)+ak|0,K-ak|0)|0}}while(0);if((aj|0)==0){c[k>>2]=103;ai=ab;z=198;break}else{ah=c[k>>2]|0;z=196;break}}}while(0);do{if((z|0)==196){if((ah|0)!=103){break}ai=i+28|0;z=198}}while(0);do{if((z|0)==198){if((c[(c[ai>>2]|0)+44>>2]|0)==0){c[k>>2]=113;break}P=i+20|0;O=i+12|0;do{if(((c[P>>2]|0)+2|0)>>>0>(c[O>>2]|0)>>>0){u=c[h>>2]|0;K=c[u+20>>2]|0;r=c[n>>2]|0;x=K>>>0>r>>>0?r:K;if((x|0)==0){break}K=c[j>>2]|0;r=c[u+16>>2]|0;bJ(K|0,r|0,x)|0;c[j>>2]=(c[j>>2]|0)+x;r=(c[h>>2]|0)+16|0;c[r>>2]=(c[r>>2]|0)+x;r=e+20|0;c[r>>2]=(c[r>>2]|0)+x;c[n>>2]=(c[n>>2]|0)-x;r=(c[h>>2]|0)+20|0;c[r>>2]=(c[r>>2]|0)-x;x=c[h>>2]|0;if((c[x+20>>2]|0)!=0){break}c[x+16>>2]=c[x+8>>2]}}while(0);x=c[P>>2]|0;if((x+2|0)>>>0>(c[O>>2]|0)>>>0){break}r=e+48|0;K=c[r>>2]&255;c[P>>2]=x+1;u=i+8|0;a[(c[u>>2]|0)+x|0]=K;K=(c[r>>2]|0)>>>8&255;x=c[P>>2]|0;c[P>>2]=x+1;a[(c[u>>2]|0)+x|0]=K;c[r>>2]=a$(0,0,0)|0;c[k>>2]=113}}while(0);r=i+20|0;do{if((c[r>>2]|0)==0){if((c[e+4>>2]|0)!=0){break}if(!((q|0)>=(f|0)&(f|0)!=4)){break}c[e+24>>2]=c[9];g=-5;return g|0}else{K=c[h>>2]|0;x=c[K+20>>2]|0;u=c[n>>2]|0;l=x>>>0>u>>>0?u:x;if((l|0)==0){ao=u}else{u=c[j>>2]|0;x=c[K+16>>2]|0;bJ(u|0,x|0,l)|0;c[j>>2]=(c[j>>2]|0)+l;x=(c[h>>2]|0)+16|0;c[x>>2]=(c[x>>2]|0)+l;x=e+20|0;c[x>>2]=(c[x>>2]|0)+l;c[n>>2]=(c[n>>2]|0)-l;x=(c[h>>2]|0)+20|0;c[x>>2]=(c[x>>2]|0)-l;l=c[h>>2]|0;if((c[l+20>>2]|0)==0){c[l+16>>2]=c[l+8>>2]}ao=c[n>>2]|0}if((ao|0)!=0){break}c[p>>2]=-1;g=0;return g|0}}while(0);q=(c[k>>2]|0)==666;l=(c[e+4>>2]|0)==0;do{if(q){if(l){z=220;break}c[e+24>>2]=c[9];g=-5;return g|0}else{if(l){z=220}else{z=223}}}while(0);do{if((z|0)==220){if((c[i+116>>2]|0)!=0){z=223;break}if((f|0)==0){g=0;return g|0}else{if(q){break}else{z=223;break}}}}while(0);L321:do{if((z|0)==223){q=c[i+136>>2]|0;L323:do{if((q|0)==2){l=i+116|0;x=i+96|0;u=i+108|0;K=i+56|0;H=i+5792|0;v=i+5796|0;t=i+5784|0;N=i+5788|0;w=i+92|0;while(1){if((c[l>>2]|0)==0){a4(i);if((c[l>>2]|0)==0){break}}c[x>>2]=0;M=a[(c[K>>2]|0)+(c[u>>2]|0)|0]|0;b[(c[v>>2]|0)+(c[H>>2]<<1)>>1]=0;A=c[H>>2]|0;c[H>>2]=A+1;a[(c[t>>2]|0)+A|0]=M;A=i+148+((M&255)<<2)|0;b[A>>1]=(b[A>>1]|0)+1&65535;A=(c[H>>2]|0)==((c[N>>2]|0)-1|0);c[l>>2]=(c[l>>2]|0)-1;M=(c[u>>2]|0)+1|0;c[u>>2]=M;if(!A){continue}A=c[w>>2]|0;if((A|0)>-1){ap=(c[K>>2]|0)+A|0}else{ap=0}by(i,ap,M-A|0,0);c[w>>2]=c[u>>2];A=c[o>>2]|0;M=A+28|0;I=c[M>>2]|0;L=c[I+20>>2]|0;J=A+16|0;T=c[J>>2]|0;Q=L>>>0>T>>>0?T:L;do{if((Q|0)!=0){L=A+12|0;T=c[L>>2]|0;S=c[I+16>>2]|0;bJ(T|0,S|0,Q)|0;c[L>>2]=(c[L>>2]|0)+Q;L=(c[M>>2]|0)+16|0;c[L>>2]=(c[L>>2]|0)+Q;L=A+20|0;c[L>>2]=(c[L>>2]|0)+Q;c[J>>2]=(c[J>>2]|0)-Q;L=(c[M>>2]|0)+20|0;c[L>>2]=(c[L>>2]|0)-Q;L=c[M>>2]|0;if((c[L+20>>2]|0)!=0){break}c[L+16>>2]=c[L+8>>2]}}while(0);if((c[(c[o>>2]|0)+16>>2]|0)==0){break L323}}if((f|0)==0){break}l=c[w>>2]|0;if((l|0)>-1){aq=(c[K>>2]|0)+l|0}else{aq=0}by(i,aq,(c[u>>2]|0)-l|0,m&1);c[w>>2]=c[u>>2];l=c[o>>2]|0;N=l+28|0;H=c[N>>2]|0;t=c[H+20>>2]|0;v=l+16|0;x=c[v>>2]|0;M=t>>>0>x>>>0?x:t;do{if((M|0)!=0){t=l+12|0;x=c[t>>2]|0;Q=c[H+16>>2]|0;bJ(x|0,Q|0,M)|0;c[t>>2]=(c[t>>2]|0)+M;t=(c[N>>2]|0)+16|0;c[t>>2]=(c[t>>2]|0)+M;t=l+20|0;c[t>>2]=(c[t>>2]|0)+M;c[v>>2]=(c[v>>2]|0)-M;t=(c[N>>2]|0)+20|0;c[t>>2]=(c[t>>2]|0)-M;t=c[N>>2]|0;if((c[t+20>>2]|0)!=0){break}c[t+16>>2]=c[t+8>>2]}}while(0);if((c[(c[o>>2]|0)+16>>2]|0)==0){ar=m?2:0;z=281;break}else{ar=m?3:1;z=281;break}}else if((q|0)==3){N=i+116|0;M=(f|0)==0;v=i+96|0;l=i+108|0;H=i+5792|0;u=i+5796|0;w=i+5784|0;K=i+2440+(d[14184]<<2)|0;t=i+5788|0;Q=i+56|0;x=i+92|0;L351:while(1){J=c[N>>2]|0;do{if(J>>>0<258){a4(i);A=c[N>>2]|0;if(A>>>0<258&M){break L323}if((A|0)==0){break L351}c[v>>2]=0;if(A>>>0>2){as=A;z=250;break}at=c[l>>2]|0;z=265}else{c[v>>2]=0;as=J;z=250}}while(0);do{if((z|0)==250){z=0;J=c[l>>2]|0;if((J|0)==0){at=0;z=265;break}A=c[Q>>2]|0;I=a[A+(J-1)|0]|0;if(I<<24>>24!=(a[A+J|0]|0)){at=J;z=265;break}if(I<<24>>24!=(a[A+(J+1)|0]|0)){at=J;z=265;break}L=A+(J+2)|0;if(I<<24>>24!=(a[L]|0)){at=J;z=265;break}S=A+(J+258)|0;A=L;while(1){L=A+1|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+2|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+3|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+4|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+5|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+6|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+7|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+8|0;if(I<<24>>24==(a[L]|0)&L>>>0>>0){A=L}else{au=L;break}}A=au-S+258|0;I=A>>>0>as>>>0?as:A;c[v>>2]=I;if(I>>>0<=2){at=J;z=265;break}A=I+253|0;b[(c[u>>2]|0)+(c[H>>2]<<1)>>1]=1;I=c[H>>2]|0;c[H>>2]=I+1;a[(c[w>>2]|0)+I|0]=A&255;I=i+148+((d[13928+(A&255)|0]|256)+1<<2)|0;b[I>>1]=(b[I>>1]|0)+1&65535;b[K>>1]=(b[K>>1]|0)+1&65535;I=(c[H>>2]|0)==((c[t>>2]|0)-1|0);A=c[v>>2]|0;c[N>>2]=(c[N>>2]|0)-A;L=(c[l>>2]|0)+A|0;c[l>>2]=L;c[v>>2]=0;if(I){av=L}else{continue L351}}}while(0);if((z|0)==265){z=0;L=a[(c[Q>>2]|0)+at|0]|0;b[(c[u>>2]|0)+(c[H>>2]<<1)>>1]=0;I=c[H>>2]|0;c[H>>2]=I+1;a[(c[w>>2]|0)+I|0]=L;I=i+148+((L&255)<<2)|0;b[I>>1]=(b[I>>1]|0)+1&65535;I=(c[H>>2]|0)==((c[t>>2]|0)-1|0);c[N>>2]=(c[N>>2]|0)-1;L=(c[l>>2]|0)+1|0;c[l>>2]=L;if(I){av=L}else{continue}}L=c[x>>2]|0;if((L|0)>-1){aw=(c[Q>>2]|0)+L|0}else{aw=0}by(i,aw,av-L|0,0);c[x>>2]=c[l>>2];L=c[o>>2]|0;I=L+28|0;A=c[I>>2]|0;T=c[A+20>>2]|0;R=L+16|0;ax=c[R>>2]|0;ay=T>>>0>ax>>>0?ax:T;do{if((ay|0)!=0){T=L+12|0;ax=c[T>>2]|0;az=c[A+16>>2]|0;bJ(ax|0,az|0,ay)|0;c[T>>2]=(c[T>>2]|0)+ay;T=(c[I>>2]|0)+16|0;c[T>>2]=(c[T>>2]|0)+ay;T=L+20|0;c[T>>2]=(c[T>>2]|0)+ay;c[R>>2]=(c[R>>2]|0)-ay;T=(c[I>>2]|0)+20|0;c[T>>2]=(c[T>>2]|0)-ay;T=c[I>>2]|0;if((c[T+20>>2]|0)!=0){break}c[T+16>>2]=c[T+8>>2]}}while(0);if((c[(c[o>>2]|0)+16>>2]|0)==0){break L323}}N=c[x>>2]|0;if((N|0)>-1){aA=(c[Q>>2]|0)+N|0}else{aA=0}by(i,aA,(c[l>>2]|0)-N|0,m&1);c[x>>2]=c[l>>2];N=c[o>>2]|0;t=N+28|0;H=c[t>>2]|0;w=c[H+20>>2]|0;u=N+16|0;v=c[u>>2]|0;K=w>>>0>v>>>0?v:w;do{if((K|0)!=0){w=N+12|0;v=c[w>>2]|0;M=c[H+16>>2]|0;bJ(v|0,M|0,K)|0;c[w>>2]=(c[w>>2]|0)+K;w=(c[t>>2]|0)+16|0;c[w>>2]=(c[w>>2]|0)+K;w=N+20|0;c[w>>2]=(c[w>>2]|0)+K;c[u>>2]=(c[u>>2]|0)-K;w=(c[t>>2]|0)+20|0;c[w>>2]=(c[w>>2]|0)-K;w=c[t>>2]|0;if((c[w+20>>2]|0)!=0){break}c[w+16>>2]=c[w+8>>2]}}while(0);if((c[(c[o>>2]|0)+16>>2]|0)==0){ar=m?2:0;z=281;break}else{ar=m?3:1;z=281;break}}else{ar=aI[c[12400+((c[i+132>>2]|0)*12|0)>>2]&15](i,f)|0;z=281}}while(0);do{if((z|0)==281){if((ar-2|0)>>>0<2){c[k>>2]=666}if((ar|0)==2|(ar|0)==0){break}else if((ar|0)!=1){break L321}do{if((f|0)==1){bx(i)}else if((f|0)!=5){bs(i,0,0,0);if((f|0)!=3){break}q=i+76|0;P=i+68|0;b[(c[P>>2]|0)+((c[q>>2]|0)-1<<1)>>1]=0;bI(c[P>>2]|0,0,(c[q>>2]<<1)-2|0);if((c[i+116>>2]|0)!=0){break}c[i+108>>2]=0;c[i+92>>2]=0}}while(0);q=c[h>>2]|0;P=c[q+20>>2]|0;O=c[n>>2]|0;t=P>>>0>O>>>0?O:P;if((t|0)==0){aB=O}else{O=c[j>>2]|0;P=c[q+16>>2]|0;bJ(O|0,P|0,t)|0;c[j>>2]=(c[j>>2]|0)+t;P=(c[h>>2]|0)+16|0;c[P>>2]=(c[P>>2]|0)+t;P=e+20|0;c[P>>2]=(c[P>>2]|0)+t;c[n>>2]=(c[n>>2]|0)-t;P=(c[h>>2]|0)+20|0;c[P>>2]=(c[P>>2]|0)-t;t=c[h>>2]|0;if((c[t+20>>2]|0)==0){c[t+16>>2]=c[t+8>>2]}aB=c[n>>2]|0}if((aB|0)!=0){break L321}c[p>>2]=-1;g=0;return g|0}}while(0);if((c[n>>2]|0)!=0){g=0;return g|0}c[p>>2]=-1;g=0;return g|0}}while(0);if(!m){g=0;return g|0}p=i+24|0;k=c[p>>2]|0;if((k|0)<1){g=1;return g|0}o=e+48|0;t=c[o>>2]|0;if((k|0)==2){k=c[r>>2]|0;c[r>>2]=k+1;P=i+8|0;a[(c[P>>2]|0)+k|0]=t&255;k=(c[o>>2]|0)>>>8&255;O=c[r>>2]|0;c[r>>2]=O+1;a[(c[P>>2]|0)+O|0]=k;k=(c[o>>2]|0)>>>16&255;O=c[r>>2]|0;c[r>>2]=O+1;a[(c[P>>2]|0)+O|0]=k;k=(c[o>>2]|0)>>>24&255;O=c[r>>2]|0;c[r>>2]=O+1;a[(c[P>>2]|0)+O|0]=k;k=e+8|0;O=c[k>>2]&255;q=c[r>>2]|0;c[r>>2]=q+1;a[(c[P>>2]|0)+q|0]=O;O=(c[k>>2]|0)>>>8&255;q=c[r>>2]|0;c[r>>2]=q+1;a[(c[P>>2]|0)+q|0]=O;O=(c[k>>2]|0)>>>16&255;q=c[r>>2]|0;c[r>>2]=q+1;a[(c[P>>2]|0)+q|0]=O;O=(c[k>>2]|0)>>>24&255;k=c[r>>2]|0;c[r>>2]=k+1;a[(c[P>>2]|0)+k|0]=O}else{O=c[r>>2]|0;c[r>>2]=O+1;k=i+8|0;a[(c[k>>2]|0)+O|0]=t>>>24&255;O=c[r>>2]|0;c[r>>2]=O+1;a[(c[k>>2]|0)+O|0]=t>>>16&255;t=c[o>>2]|0;o=c[r>>2]|0;c[r>>2]=o+1;a[(c[k>>2]|0)+o|0]=t>>>8&255;o=c[r>>2]|0;c[r>>2]=o+1;a[(c[k>>2]|0)+o|0]=t&255}t=c[h>>2]|0;o=c[t+20>>2]|0;k=c[n>>2]|0;O=o>>>0>k>>>0?k:o;do{if((O|0)!=0){o=c[j>>2]|0;k=c[t+16>>2]|0;bJ(o|0,k|0,O)|0;c[j>>2]=(c[j>>2]|0)+O;k=(c[h>>2]|0)+16|0;c[k>>2]=(c[k>>2]|0)+O;k=e+20|0;c[k>>2]=(c[k>>2]|0)+O;c[n>>2]=(c[n>>2]|0)-O;k=(c[h>>2]|0)+20|0;c[k>>2]=(c[k>>2]|0)-O;k=c[h>>2]|0;if((c[k+20>>2]|0)!=0){break}c[k+16>>2]=c[k+8>>2]}}while(0);O=c[p>>2]|0;if((O|0)>0){c[p>>2]=-O}g=(c[r>>2]|0)==0|0;return g|0}}while(0);c[e+24>>2]=c[6];g=-2;return g|0}function a4(a){a=a|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0;f=a+44|0;g=c[f>>2]|0;h=a+60|0;i=a+116|0;j=a+108|0;k=g-262|0;l=a|0;m=a+56|0;n=a+72|0;o=a+88|0;p=a+84|0;q=a+112|0;r=a+92|0;s=a+76|0;t=a+68|0;u=a+64|0;v=c[i>>2]|0;w=g;while(1){x=c[j>>2]|0;y=(c[h>>2]|0)-v-x|0;if(x>>>0<(k+w|0)>>>0){z=y}else{x=c[m>>2]|0;A=x+g|0;bJ(x|0,A|0,g)|0;c[q>>2]=(c[q>>2]|0)-g;c[j>>2]=(c[j>>2]|0)-g;c[r>>2]=(c[r>>2]|0)-g;A=c[s>>2]|0;x=A;B=(c[t>>2]|0)+(A<<1)|0;do{B=B-2|0;A=e[B>>1]|0;if(A>>>0>>0){C=0}else{C=A-g&65535}b[B>>1]=C;x=x-1|0;}while((x|0)!=0);x=g;B=(c[u>>2]|0)+(g<<1)|0;do{B=B-2|0;A=e[B>>1]|0;if(A>>>0>>0){D=0}else{D=A-g&65535}b[B>>1]=D;x=x-1|0;}while((x|0)!=0);z=y+g|0}x=c[l>>2]|0;B=x+4|0;A=c[B>>2]|0;if((A|0)==0){E=355;break}F=c[i>>2]|0;G=(c[m>>2]|0)+(F+(c[j>>2]|0))|0;H=A>>>0>z>>>0?z:A;if((H|0)==0){I=0;J=F}else{c[B>>2]=A-H;A=c[(c[x+28>>2]|0)+24>>2]|0;if((A|0)==1){B=x+48|0;F=x|0;c[B>>2]=a_(c[B>>2]|0,c[F>>2]|0,H)|0;K=F}else if((A|0)==2){A=x+48|0;F=x|0;c[A>>2]=a$(c[A>>2]|0,c[F>>2]|0,H)|0;K=F}else{K=x|0}F=c[K>>2]|0;bJ(G|0,F|0,H)|0;c[K>>2]=(c[K>>2]|0)+H;F=x+8|0;c[F>>2]=(c[F>>2]|0)+H;I=H;J=c[i>>2]|0}L=J+I|0;c[i>>2]=L;if(L>>>0>2){H=c[j>>2]|0;F=c[m>>2]|0;x=d[F+H|0]|0;c[n>>2]=x;c[n>>2]=((d[F+(H+1)|0]|0)^x<>2])&c[p>>2];if(L>>>0>=262){break}}if((c[(c[l>>2]|0)+4>>2]|0)==0){break}v=L;w=c[f>>2]|0}if((E|0)==355){return}E=a+5824|0;a=c[E>>2]|0;f=c[h>>2]|0;if(a>>>0>=f>>>0){return}h=L+(c[j>>2]|0)|0;if(a>>>0>>0){j=f-h|0;L=j>>>0>258?258:j;bI((c[m>>2]|0)+h|0,0,L|0);c[E>>2]=L+h;return}L=h+258|0;if(a>>>0>=L>>>0){return}h=L-a|0;L=f-a|0;f=h>>>0>L>>>0?L:h;bI((c[m>>2]|0)+a|0,0,f|0);c[E>>2]=(c[E>>2]|0)+f;return}function a5(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;d=(c[a+12>>2]|0)-5|0;e=d>>>0<65535?d:65535;d=a+116|0;f=a+108|0;g=a+92|0;h=a+44|0;i=a+56|0;j=a|0;while(1){k=c[d>>2]|0;if(k>>>0<2){a4(a);l=c[d>>2]|0;if((l|b|0)==0){m=0;n=384;break}if((l|0)==0){n=375;break}else{o=l}}else{o=k}k=(c[f>>2]|0)+o|0;c[f>>2]=k;c[d>>2]=0;l=c[g>>2]|0;p=l+e|0;if((k|0)!=0&k>>>0

>>0){q=k;r=l}else{c[d>>2]=k-p;c[f>>2]=p;if((l|0)>-1){s=(c[i>>2]|0)+l|0}else{s=0}by(a,s,e,0);c[g>>2]=c[f>>2];l=c[j>>2]|0;p=l+28|0;k=c[p>>2]|0;t=c[k+20>>2]|0;u=l+16|0;v=c[u>>2]|0;w=t>>>0>v>>>0?v:t;do{if((w|0)!=0){t=l+12|0;v=c[t>>2]|0;x=c[k+16>>2]|0;bJ(v|0,x|0,w)|0;c[t>>2]=(c[t>>2]|0)+w;t=(c[p>>2]|0)+16|0;c[t>>2]=(c[t>>2]|0)+w;t=l+20|0;c[t>>2]=(c[t>>2]|0)+w;c[u>>2]=(c[u>>2]|0)-w;t=(c[p>>2]|0)+20|0;c[t>>2]=(c[t>>2]|0)-w;t=c[p>>2]|0;if((c[t+20>>2]|0)!=0){break}c[t+16>>2]=c[t+8>>2]}}while(0);if((c[(c[j>>2]|0)+16>>2]|0)==0){m=0;n=385;break}q=c[f>>2]|0;r=c[g>>2]|0}p=q-r|0;if(p>>>0<((c[h>>2]|0)-262|0)>>>0){continue}if((r|0)>-1){y=(c[i>>2]|0)+r|0}else{y=0}by(a,y,p,0);c[g>>2]=c[f>>2];p=c[j>>2]|0;w=p+28|0;u=c[w>>2]|0;l=c[u+20>>2]|0;k=p+16|0;t=c[k>>2]|0;x=l>>>0>t>>>0?t:l;do{if((x|0)!=0){l=p+12|0;t=c[l>>2]|0;v=c[u+16>>2]|0;bJ(t|0,v|0,x)|0;c[l>>2]=(c[l>>2]|0)+x;l=(c[w>>2]|0)+16|0;c[l>>2]=(c[l>>2]|0)+x;l=p+20|0;c[l>>2]=(c[l>>2]|0)+x;c[k>>2]=(c[k>>2]|0)-x;l=(c[w>>2]|0)+20|0;c[l>>2]=(c[l>>2]|0)-x;l=c[w>>2]|0;if((c[l+20>>2]|0)!=0){break}c[l+16>>2]=c[l+8>>2]}}while(0);if((c[(c[j>>2]|0)+16>>2]|0)==0){m=0;n=386;break}}if((n|0)==384){return m|0}else if((n|0)==386){return m|0}else if((n|0)==385){return m|0}else if((n|0)==375){n=c[g>>2]|0;if((n|0)>-1){z=(c[i>>2]|0)+n|0}else{z=0}i=(b|0)==4;by(a,z,(c[f>>2]|0)-n|0,i&1);c[g>>2]=c[f>>2];f=c[j>>2]|0;g=f+28|0;n=c[g>>2]|0;z=c[n+20>>2]|0;a=f+16|0;b=c[a>>2]|0;y=z>>>0>b>>>0?b:z;do{if((y|0)!=0){z=f+12|0;b=c[z>>2]|0;r=c[n+16>>2]|0;bJ(b|0,r|0,y)|0;c[z>>2]=(c[z>>2]|0)+y;z=(c[g>>2]|0)+16|0;c[z>>2]=(c[z>>2]|0)+y;z=f+20|0;c[z>>2]=(c[z>>2]|0)+y;c[a>>2]=(c[a>>2]|0)-y;z=(c[g>>2]|0)+20|0;c[z>>2]=(c[z>>2]|0)-y;z=c[g>>2]|0;if((c[z+20>>2]|0)!=0){break}c[z+16>>2]=c[z+8>>2]}}while(0);if((c[(c[j>>2]|0)+16>>2]|0)==0){m=i?2:0;return m|0}else{m=i?3:1;return m|0}}return 0}function a6(e,f){e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0;g=e+116|0;h=(f|0)==0;i=e+72|0;j=e+88|0;k=e+108|0;l=e+56|0;m=e+84|0;n=e+68|0;o=e+52|0;p=e+64|0;q=e+44|0;r=e+96|0;s=e+112|0;t=e+5792|0;u=e+5796|0;v=e+5784|0;w=e+5788|0;x=e+128|0;y=e+92|0;z=e|0;while(1){if((c[g>>2]|0)>>>0<262){a4(e);A=c[g>>2]|0;if(A>>>0<262&h){B=0;C=426;break}if((A|0)==0){C=414;break}if(A>>>0>2){C=394}else{C=397}}else{C=394}do{if((C|0)==394){C=0;A=c[k>>2]|0;D=((d[(c[l>>2]|0)+(A+2)|0]|0)^c[i>>2]<>2])&c[m>>2];c[i>>2]=D;E=b[(c[n>>2]|0)+(D<<1)>>1]|0;b[(c[p>>2]|0)+((c[o>>2]&A)<<1)>>1]=E;A=E&65535;b[(c[n>>2]|0)+(c[i>>2]<<1)>>1]=c[k>>2]&65535;if(E<<16>>16==0){C=397;break}if(((c[k>>2]|0)-A|0)>>>0>((c[q>>2]|0)-262|0)>>>0){C=397;break}E=a7(e,A)|0;c[r>>2]=E;F=E}}while(0);if((C|0)==397){C=0;F=c[r>>2]|0}do{if(F>>>0>2){E=F+253|0;A=(c[k>>2]|0)-(c[s>>2]|0)&65535;b[(c[u>>2]|0)+(c[t>>2]<<1)>>1]=A;D=c[t>>2]|0;c[t>>2]=D+1;a[(c[v>>2]|0)+D|0]=E&255;D=A-1&65535;A=e+148+((d[13928+(E&255)|0]|0|256)+1<<2)|0;b[A>>1]=(b[A>>1]|0)+1&65535;A=D&65535;if((D&65535)<256){G=A}else{G=(A>>>7)+256|0}A=e+2440+((d[14184+G|0]|0)<<2)|0;b[A>>1]=(b[A>>1]|0)+1&65535;A=(c[t>>2]|0)==((c[w>>2]|0)-1|0)|0;D=c[r>>2]|0;E=(c[g>>2]|0)-D|0;c[g>>2]=E;if(!(D>>>0<=(c[x>>2]|0)>>>0&E>>>0>2)){E=(c[k>>2]|0)+D|0;c[k>>2]=E;c[r>>2]=0;H=c[l>>2]|0;I=d[H+E|0]|0;c[i>>2]=I;c[i>>2]=((d[H+(E+1)|0]|0)^I<>2])&c[m>>2];J=A;K=E;break}c[r>>2]=D-1;do{D=c[k>>2]|0;E=D+1|0;c[k>>2]=E;I=((d[(c[l>>2]|0)+(D+3)|0]|0)^c[i>>2]<>2])&c[m>>2];c[i>>2]=I;b[(c[p>>2]|0)+((c[o>>2]&E)<<1)>>1]=b[(c[n>>2]|0)+(I<<1)>>1]|0;b[(c[n>>2]|0)+(c[i>>2]<<1)>>1]=c[k>>2]&65535;I=(c[r>>2]|0)-1|0;c[r>>2]=I;}while((I|0)!=0);I=(c[k>>2]|0)+1|0;c[k>>2]=I;J=A;K=I}else{I=a[(c[l>>2]|0)+(c[k>>2]|0)|0]|0;b[(c[u>>2]|0)+(c[t>>2]<<1)>>1]=0;E=c[t>>2]|0;c[t>>2]=E+1;a[(c[v>>2]|0)+E|0]=I;E=e+148+((I&255)<<2)|0;b[E>>1]=(b[E>>1]|0)+1&65535;E=(c[t>>2]|0)==((c[w>>2]|0)-1|0)|0;c[g>>2]=(c[g>>2]|0)-1;I=(c[k>>2]|0)+1|0;c[k>>2]=I;J=E;K=I}}while(0);if((J|0)==0){continue}I=c[y>>2]|0;if((I|0)>-1){L=(c[l>>2]|0)+I|0}else{L=0}by(e,L,K-I|0,0);c[y>>2]=c[k>>2];I=c[z>>2]|0;E=I+28|0;D=c[E>>2]|0;H=c[D+20>>2]|0;M=I+16|0;N=c[M>>2]|0;O=H>>>0>N>>>0?N:H;do{if((O|0)!=0){H=I+12|0;N=c[H>>2]|0;P=c[D+16>>2]|0;bJ(N|0,P|0,O)|0;c[H>>2]=(c[H>>2]|0)+O;H=(c[E>>2]|0)+16|0;c[H>>2]=(c[H>>2]|0)+O;H=I+20|0;c[H>>2]=(c[H>>2]|0)+O;c[M>>2]=(c[M>>2]|0)-O;H=(c[E>>2]|0)+20|0;c[H>>2]=(c[H>>2]|0)-O;H=c[E>>2]|0;if((c[H+20>>2]|0)!=0){break}c[H+16>>2]=c[H+8>>2]}}while(0);if((c[(c[z>>2]|0)+16>>2]|0)==0){B=0;C=425;break}}if((C|0)==414){K=c[y>>2]|0;if((K|0)>-1){Q=(c[l>>2]|0)+K|0}else{Q=0}l=(f|0)==4;by(e,Q,(c[k>>2]|0)-K|0,l&1);c[y>>2]=c[k>>2];k=c[z>>2]|0;y=k+28|0;K=c[y>>2]|0;Q=c[K+20>>2]|0;e=k+16|0;f=c[e>>2]|0;L=Q>>>0>f>>>0?f:Q;do{if((L|0)!=0){Q=k+12|0;f=c[Q>>2]|0;J=c[K+16>>2]|0;bJ(f|0,J|0,L)|0;c[Q>>2]=(c[Q>>2]|0)+L;Q=(c[y>>2]|0)+16|0;c[Q>>2]=(c[Q>>2]|0)+L;Q=k+20|0;c[Q>>2]=(c[Q>>2]|0)+L;c[e>>2]=(c[e>>2]|0)-L;Q=(c[y>>2]|0)+20|0;c[Q>>2]=(c[Q>>2]|0)-L;Q=c[y>>2]|0;if((c[Q+20>>2]|0)!=0){break}c[Q+16>>2]=c[Q+8>>2]}}while(0);if((c[(c[z>>2]|0)+16>>2]|0)==0){B=l?2:0;return B|0}else{B=l?3:1;return B|0}}else if((C|0)==425){return B|0}else if((C|0)==426){return B|0}return 0}function a7(b,d){b=b|0;d=d|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0;f=c[b+124>>2]|0;g=c[b+56>>2]|0;h=c[b+108>>2]|0;i=g+h|0;j=c[b+120>>2]|0;k=c[b+144>>2]|0;l=(c[b+44>>2]|0)-262|0;m=h>>>0>l>>>0?h-l|0:0;l=c[b+64>>2]|0;n=c[b+52>>2]|0;o=g+(h+258)|0;p=c[b+116>>2]|0;q=k>>>0>p>>>0?p:k;k=b+112|0;r=g+(h+1)|0;s=g+(h+2)|0;t=o;u=h+257|0;v=a[g+(j+h)|0]|0;w=a[g+(h-1+j)|0]|0;x=d;d=j>>>0<(c[b+140>>2]|0)>>>0?f:f>>>2;f=j;L584:while(1){j=g+x|0;do{if((a[g+(x+f)|0]|0)==v<<24>>24){if((a[g+(f-1+x)|0]|0)!=w<<24>>24){y=v;z=w;A=f;break}if((a[j]|0)!=(a[i]|0)){y=v;z=w;A=f;break}if((a[g+(x+1)|0]|0)!=(a[r]|0)){y=v;z=w;A=f;break}b=s;B=g+(x+2)|0;while(1){C=b+1|0;if((a[C]|0)!=(a[B+1|0]|0)){D=C;break}C=b+2|0;if((a[C]|0)!=(a[B+2|0]|0)){D=C;break}C=b+3|0;if((a[C]|0)!=(a[B+3|0]|0)){D=C;break}C=b+4|0;if((a[C]|0)!=(a[B+4|0]|0)){D=C;break}C=b+5|0;if((a[C]|0)!=(a[B+5|0]|0)){D=C;break}C=b+6|0;if((a[C]|0)!=(a[B+6|0]|0)){D=C;break}C=b+7|0;if((a[C]|0)!=(a[B+7|0]|0)){D=C;break}C=b+8|0;E=B+8|0;if((a[C]|0)==(a[E]|0)&C>>>0>>0){b=C;B=E}else{D=C;break}}B=D-t|0;b=B+258|0;if((b|0)<=(f|0)){y=v;z=w;A=f;break}c[k>>2]=x;if((b|0)>=(q|0)){F=b;G=447;break L584}y=a[g+(b+h)|0]|0;z=a[g+(u+B)|0]|0;A=b}else{y=v;z=w;A=f}}while(0);j=e[l+((x&n)<<1)>>1]|0;if(j>>>0<=m>>>0){F=A;G=448;break}b=d-1|0;if((b|0)==0){F=A;G=449;break}else{v=y;w=z;x=j;d=b;f=A}}if((G|0)==447){H=F>>>0>p>>>0;I=H?p:F;return I|0}else if((G|0)==448){H=F>>>0>p>>>0;I=H?p:F;return I|0}else if((G|0)==449){H=F>>>0>p>>>0;I=H?p:F;return I|0}return 0}function a8(e,f){e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0;g=e+116|0;h=(f|0)==0;i=e+72|0;j=e+88|0;k=e+108|0;l=e+56|0;m=e+84|0;n=e+68|0;o=e+52|0;p=e+64|0;q=e+96|0;r=e+120|0;s=e+112|0;t=e+100|0;u=e+5792|0;v=e+5796|0;w=e+5784|0;x=e+5788|0;y=e+104|0;z=e+92|0;A=e|0;B=e+128|0;C=e+44|0;D=e+136|0;L610:while(1){E=c[g>>2]|0;while(1){do{if(E>>>0<262){a4(e);F=c[g>>2]|0;if(F>>>0<262&h){G=0;H=500;break L610}if((F|0)==0){H=489;break L610}if(F>>>0>2){H=457;break}c[r>>2]=c[q>>2];c[t>>2]=c[s>>2];c[q>>2]=2;I=2;H=465}else{H=457}}while(0);do{if((H|0)==457){H=0;F=c[k>>2]|0;J=((d[(c[l>>2]|0)+(F+2)|0]|0)^c[i>>2]<>2])&c[m>>2];c[i>>2]=J;K=b[(c[n>>2]|0)+(J<<1)>>1]|0;b[(c[p>>2]|0)+((c[o>>2]&F)<<1)>>1]=K;F=K&65535;b[(c[n>>2]|0)+(c[i>>2]<<1)>>1]=c[k>>2]&65535;J=c[q>>2]|0;c[r>>2]=J;c[t>>2]=c[s>>2];c[q>>2]=2;if(K<<16>>16==0){I=2;H=465;break}if(J>>>0>=(c[B>>2]|0)>>>0){L=J;M=2;break}if(((c[k>>2]|0)-F|0)>>>0>((c[C>>2]|0)-262|0)>>>0){I=2;H=465;break}J=a7(e,F)|0;c[q>>2]=J;if(J>>>0>=6){I=J;H=465;break}if((c[D>>2]|0)!=1){if((J|0)!=3){I=J;H=465;break}if(((c[k>>2]|0)-(c[s>>2]|0)|0)>>>0<=4096){I=3;H=465;break}}c[q>>2]=2;I=2;H=465}}while(0);if((H|0)==465){H=0;L=c[r>>2]|0;M=I}if(!(L>>>0<3|M>>>0>L>>>0)){break}if((c[y>>2]|0)==0){c[y>>2]=1;c[k>>2]=(c[k>>2]|0)+1;J=(c[g>>2]|0)-1|0;c[g>>2]=J;E=J;continue}J=a[(c[l>>2]|0)+((c[k>>2]|0)-1)|0]|0;b[(c[v>>2]|0)+(c[u>>2]<<1)>>1]=0;F=c[u>>2]|0;c[u>>2]=F+1;a[(c[w>>2]|0)+F|0]=J;F=e+148+((J&255)<<2)|0;b[F>>1]=(b[F>>1]|0)+1&65535;do{if((c[u>>2]|0)==((c[x>>2]|0)-1|0)){F=c[z>>2]|0;if((F|0)>-1){N=(c[l>>2]|0)+F|0}else{N=0}by(e,N,(c[k>>2]|0)-F|0,0);c[z>>2]=c[k>>2];F=c[A>>2]|0;J=F+28|0;K=c[J>>2]|0;O=c[K+20>>2]|0;P=F+16|0;Q=c[P>>2]|0;R=O>>>0>Q>>>0?Q:O;if((R|0)==0){break}O=F+12|0;Q=c[O>>2]|0;S=c[K+16>>2]|0;bJ(Q|0,S|0,R)|0;c[O>>2]=(c[O>>2]|0)+R;O=(c[J>>2]|0)+16|0;c[O>>2]=(c[O>>2]|0)+R;O=F+20|0;c[O>>2]=(c[O>>2]|0)+R;c[P>>2]=(c[P>>2]|0)-R;P=(c[J>>2]|0)+20|0;c[P>>2]=(c[P>>2]|0)-R;R=c[J>>2]|0;if((c[R+20>>2]|0)!=0){break}c[R+16>>2]=c[R+8>>2]}}while(0);c[k>>2]=(c[k>>2]|0)+1;R=(c[g>>2]|0)-1|0;c[g>>2]=R;if((c[(c[A>>2]|0)+16>>2]|0)==0){G=0;H=502;break L610}else{E=R}}E=c[k>>2]|0;R=E-3+(c[g>>2]|0)|0;J=L+253|0;P=E+65535-(c[t>>2]|0)&65535;b[(c[v>>2]|0)+(c[u>>2]<<1)>>1]=P;E=c[u>>2]|0;c[u>>2]=E+1;a[(c[w>>2]|0)+E|0]=J&255;E=P-1&65535;P=e+148+((d[13928+(J&255)|0]|0|256)+1<<2)|0;b[P>>1]=(b[P>>1]|0)+1&65535;P=E&65535;if((E&65535)<256){T=P}else{T=(P>>>7)+256|0}P=e+2440+((d[14184+T|0]|0)<<2)|0;b[P>>1]=(b[P>>1]|0)+1&65535;P=c[u>>2]|0;E=(c[x>>2]|0)-1|0;J=c[r>>2]|0;c[g>>2]=1-J+(c[g>>2]|0);O=J-2|0;c[r>>2]=O;J=O;do{O=c[k>>2]|0;F=O+1|0;c[k>>2]=F;if(F>>>0>R>>>0){U=J}else{S=((d[(c[l>>2]|0)+(O+3)|0]|0)^c[i>>2]<>2])&c[m>>2];c[i>>2]=S;b[(c[p>>2]|0)+((c[o>>2]&F)<<1)>>1]=b[(c[n>>2]|0)+(S<<1)>>1]|0;b[(c[n>>2]|0)+(c[i>>2]<<1)>>1]=c[k>>2]&65535;U=c[r>>2]|0}J=U-1|0;c[r>>2]=J;}while((J|0)!=0);c[y>>2]=0;c[q>>2]=2;J=(c[k>>2]|0)+1|0;c[k>>2]=J;if((P|0)!=(E|0)){continue}R=c[z>>2]|0;if((R|0)>-1){V=(c[l>>2]|0)+R|0}else{V=0}by(e,V,J-R|0,0);c[z>>2]=c[k>>2];R=c[A>>2]|0;J=R+28|0;S=c[J>>2]|0;F=c[S+20>>2]|0;O=R+16|0;Q=c[O>>2]|0;K=F>>>0>Q>>>0?Q:F;do{if((K|0)!=0){F=R+12|0;Q=c[F>>2]|0;W=c[S+16>>2]|0;bJ(Q|0,W|0,K)|0;c[F>>2]=(c[F>>2]|0)+K;F=(c[J>>2]|0)+16|0;c[F>>2]=(c[F>>2]|0)+K;F=R+20|0;c[F>>2]=(c[F>>2]|0)+K;c[O>>2]=(c[O>>2]|0)-K;F=(c[J>>2]|0)+20|0;c[F>>2]=(c[F>>2]|0)-K;F=c[J>>2]|0;if((c[F+20>>2]|0)!=0){break}c[F+16>>2]=c[F+8>>2]}}while(0);if((c[(c[A>>2]|0)+16>>2]|0)==0){G=0;H=501;break}}if((H|0)==489){if((c[y>>2]|0)!=0){V=a[(c[l>>2]|0)+((c[k>>2]|0)-1)|0]|0;b[(c[v>>2]|0)+(c[u>>2]<<1)>>1]=0;v=c[u>>2]|0;c[u>>2]=v+1;a[(c[w>>2]|0)+v|0]=V;v=e+148+((V&255)<<2)|0;b[v>>1]=(b[v>>1]|0)+1&65535;c[y>>2]=0}y=c[z>>2]|0;if((y|0)>-1){X=(c[l>>2]|0)+y|0}else{X=0}l=(f|0)==4;by(e,X,(c[k>>2]|0)-y|0,l&1);c[z>>2]=c[k>>2];k=c[A>>2]|0;z=k+28|0;y=c[z>>2]|0;X=c[y+20>>2]|0;e=k+16|0;f=c[e>>2]|0;v=X>>>0>f>>>0?f:X;do{if((v|0)!=0){X=k+12|0;f=c[X>>2]|0;V=c[y+16>>2]|0;bJ(f|0,V|0,v)|0;c[X>>2]=(c[X>>2]|0)+v;X=(c[z>>2]|0)+16|0;c[X>>2]=(c[X>>2]|0)+v;X=k+20|0;c[X>>2]=(c[X>>2]|0)+v;c[e>>2]=(c[e>>2]|0)-v;X=(c[z>>2]|0)+20|0;c[X>>2]=(c[X>>2]|0)-v;X=c[z>>2]|0;if((c[X+20>>2]|0)!=0){break}c[X+16>>2]=c[X+8>>2]}}while(0);if((c[(c[A>>2]|0)+16>>2]|0)==0){G=l?2:0;return G|0}else{G=l?3:1;return G|0}}else if((H|0)==500){return G|0}else if((H|0)==501){return G|0}else if((H|0)==502){return G|0}return 0}function a9(a){a=a|0;var b=0;do{if((a|0)==0){b=-2}else{if((c[a>>2]|0)==7247){b=bg(a)|0;break}else{b=bn(a)|0;break}}}while(0);return b|0}function ba(a,b){a=a|0;b=b|0;return bb(a,-1,b)|0}function bb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,t=0,u=0,v=0,w=0,x=0,y=0;f=i;g=bF(140)|0;if((g|0)==0){h=0;i=f;return h|0}c[g+16>>2]=0;c[g+20>>2]=8192;j=g+80|0;c[j>>2]=0;k=g;c[k>>2]=0;l=g+60|0;c[l>>2]=-1;m=g+64|0;c[m>>2]=0;n=a[e]|0;do{if(n<<24>>24!=0){o=e;p=n;q=0;L695:while(1){r=p<<24>>24;do{if((p-48&255)<10){c[l>>2]=r-48;t=q}else{if((r|0)==114){c[k>>2]=7247;t=7247;break}else if((r|0)==119){c[k>>2]=31153;t=31153;break}else if((r|0)==97){c[k>>2]=1;t=1;break}else if((r|0)==43){u=519;break L695}else if((r|0)==102){c[m>>2]=1;t=q;break}else if((r|0)==104){c[m>>2]=2;t=q;break}else if((r|0)==82){c[m>>2]=3;t=q;break}else if((r|0)==70){c[m>>2]=4;t=q;break}else{t=q;break}}}while(0);r=o+1|0;v=a[r]|0;if(v<<24>>24==0){break}else{o=r;p=v;q=t}}if((u|0)==519){bG(g);h=0;i=f;return h|0}if((t|0)==0){break}q=bF((bK(b|0)|0)+1|0)|0;p=g+8|0;c[p>>2]=q;if((q|0)==0){bG(g);h=0;i=f;return h|0}bL(q|0,b|0)|0;do{if((d|0)==-1){q=c[k>>2]|0;if((q|0)==7247){w=0}else{w=(q|0)==31153?1537:521}q=ap(b|0,w|0,(s=i,i=i+8|0,c[s>>2]=438,s)|0)|0;c[g+4>>2]=q;if((q|0)!=-1){x=q;break}bG(c[p>>2]|0);bG(g);h=0;i=f;return h|0}else{c[g+4>>2]=d;x=d}}while(0);p=c[k>>2]|0;do{if((p|0)==1){c[k>>2]=31153}else if((p|0)==7247){q=ak(x|0,0,1)|0;if((q|0)==-1){y=0}else{y=q}c[g+44>>2]=y;if((c[k>>2]|0)!=7247){break}c[g+36>>2]=0;c[g+40>>2]=0;c[g+52>>2]=0;c[g+56>>2]=1}}while(0);c[g+72>>2]=0;p=c[j>>2]|0;q=g+76|0;if((p|0)!=0){if((c[q>>2]|0)!=-4){bG(p)}c[j>>2]=0}c[q>>2]=0;c[g+12>>2]=0;c[g+88>>2]=0;h=g;i=f;return h|0}}while(0);bG(g);h=0;i=f;return h|0}function bc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=b+80|0;g=c[f>>2]|0;h=b+76|0;if((g|0)!=0){if((c[h>>2]|0)!=-4){bG(g)}c[f>>2]=0}c[h>>2]=d;if((e|0)==0){return}if((d|0)==-4){c[f>>2]=e;return}d=c[b+8>>2]|0;b=bK(d|0)|0;g=bF(b+3+(bK(e|0)|0)|0)|0;c[f>>2]=g;if((g|0)==0){c[h>>2]=-4;c[f>>2]=13480;return}else{bL(g|0,d|0)|0;d=c[f>>2]|0;g=d+(bK(d|0)|0)|0;a[g]=a[13376]|0;a[g+1|0]=a[13377|0]|0;a[g+2|0]=a[13378|0]|0;g=c[f>>2]|0;bM(g|0,e|0)|0;return}}function bd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;if((a|0)==0){e=-1;return e|0}f=a;if((c[a>>2]|0)!=7247){e=-1;return e|0}if((c[a+76>>2]|0)!=0){e=-1;return e|0}if((d|0)<0){bc(f,-5,12832);e=-1;return e|0}if((d|0)==0){e=0;return e|0}g=a+72|0;L780:do{if((c[g>>2]|0)==0){h=a+36|0;i=a+40|0;j=a+32|0;k=a+88|0;l=a+12|0}else{c[g>>2]=0;m=c[a+68>>2]|0;n=a+36|0;o=a+40|0;p=a+88|0;q=a+32|0;r=a+12|0;if((m|0)==0){h=n;i=o;j=q;k=p;l=r;break}s=a+52|0;t=a+28|0;u=a+16|0;v=a+4|0;w=a+100|0;x=a+96|0;y=m;L784:while(1){L786:while(1){z=c[n>>2]|0;while(1){if((z|0)!=0){break L786}if((c[o>>2]|0)!=0){if((c[p>>2]|0)==0){h=n;i=o;j=q;k=p;l=r;break L780}}m=c[s>>2]|0;if((m|0)!=0){A=m;break}if((bf(f)|0)==-1){e=-1;B=631;break L784}m=c[n>>2]|0;if((m|0)==0){B=588;break}else{z=m}}if((B|0)==588){B=0;A=c[s>>2]|0}if((A|0)==2){c[w>>2]=c[u>>2]<<1;c[x>>2]=c[t>>2];if((be(f)|0)==-1){e=-1;B=633;break L784}else{continue}}else if((A|0)!=1){continue}m=c[t>>2]|0;C=c[u>>2]<<1;c[n>>2]=0;D=0;do{E=at(c[v>>2]|0,m+D|0,C-D|0)|0;if((E|0)<1){B=593;break}D=(c[n>>2]|0)+E|0;c[n>>2]=D;}while(D>>>0>>0);if((B|0)==593){B=0;if((E|0)<0){B=595;break L784}c[o>>2]=1}c[q>>2]=c[t>>2]}C=(z|0)<0|(z|0)>(y|0)?y:z;c[n>>2]=z-C;c[q>>2]=(c[q>>2]|0)+C;c[r>>2]=(c[r>>2]|0)+C;if((y|0)==(C|0)){h=n;i=o;j=q;k=p;l=r;break L780}else{y=y-C|0}}if((B|0)==595){bc(f,-1,az(c[(ay()|0)>>2]|0)|0);e=-1;return e|0}else if((B|0)==631){return e|0}else if((B|0)==633){return e|0}}}while(0);z=a+52|0;E=a+28|0;A=a+16|0;g=a+4|0;y=a+100|0;r=a+96|0;a=b;b=0;p=d;L816:while(1){d=c[h>>2]|0;L818:do{if((d|0)==0){if((c[i>>2]|0)!=0){if((c[k>>2]|0)==0){e=b;B=634;break L816}}q=c[z>>2]|0;do{if((q|0)==0){if((bf(f)|0)==-1){e=-1;B=635;break L816}if((c[h>>2]|0)!=0){F=a;G=b;H=p;break L818}I=c[z>>2]|0}else{if(p>>>0>2]<<1>>>0){I=q;break}if((q|0)==1){J=0}else{c[y>>2]=p;c[r>>2]=a;if((be(f)|0)==-1){e=-1;B=639;break L816}o=c[h>>2]|0;c[h>>2]=0;K=o;B=624;break L818}while(1){L=at(c[g>>2]|0,a+J|0,p-J|0)|0;if((L|0)<1){break}o=L+J|0;if(o>>>0

>>0){J=o}else{K=o;B=624;break L818}}if((L|0)<0){B=621;break L816}c[i>>2]=1;K=J;B=624;break L818}}while(0);if((I|0)==2){c[y>>2]=c[A>>2]<<1;c[r>>2]=c[E>>2];if((be(f)|0)==-1){e=-1;B=637;break L816}else{F=a;G=b;H=p;break}}else if((I|0)!=1){F=a;G=b;H=p;break}q=c[E>>2]|0;o=c[A>>2]<<1;c[h>>2]=0;n=0;do{M=at(c[g>>2]|0,q+n|0,o-n|0)|0;if((M|0)<1){B=611;break}n=(c[h>>2]|0)+M|0;c[h>>2]=n;}while(n>>>0>>0);if((B|0)==611){B=0;if((M|0)<0){B=613;break L816}c[i>>2]=1}c[j>>2]=c[E>>2];F=a;G=b;H=p}else{o=d>>>0>p>>>0?p:d;n=c[j>>2]|0;bJ(a|0,n|0,o)|0;c[j>>2]=(c[j>>2]|0)+o;c[h>>2]=(c[h>>2]|0)-o;K=o;B=624}}while(0);if((B|0)==624){B=0;c[l>>2]=(c[l>>2]|0)+K;F=a+K|0;G=K+b|0;H=p-K|0}if((H|0)==0){e=G;B=640;break}else{a=F;b=G;p=H}}if((B|0)==613){bc(f,-1,az(c[(ay()|0)>>2]|0)|0);e=-1;return e|0}else if((B|0)==621){bc(f,-1,az(c[(ay()|0)>>2]|0)|0);e=-1;return e|0}else if((B|0)==634){return e|0}else if((B|0)==635){return e|0}else if((B|0)==637){return e|0}else if((B|0)==639){return e|0}else if((B|0)==640){return e|0}return 0}function be(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;b=i;i=i+16|0;d=b|0;e=b+8|0;f=a+84|0;g=a+100|0;h=c[g>>2]|0;j=a+88|0;k=a+76|0;l=a+40|0;m=a+24|0;n=a+16|0;o=a+4|0;p=a+84|0;while(1){if((c[j>>2]|0)==0){if((c[k>>2]|0)!=0){q=-1;r=669;break}if((c[l>>2]|0)!=0){r=653;break}s=c[m>>2]|0;t=c[n>>2]|0;c[j>>2]=0;u=0;while(1){v=at(c[o>>2]|0,s+u|0,t-u|0)|0;if((v|0)<1){r=649;break}w=(c[j>>2]|0)+v|0;c[j>>2]=w;if(w>>>0>>0){u=w}else{x=w;break}}if((r|0)==649){r=0;if((v|0)<0){r=651;break}c[l>>2]=1;x=c[j>>2]|0}c[p>>2]=c[m>>2];if((x|0)==0){r=653;break}}u=bq(f,0)|0;if((u|0)==(-2|0)|(u|0)==2){r=655;break}else if((u|0)==(-4|0)){r=656;break}else if((u|0)==(-3|0)){r=657;break}y=c[g>>2]|0;z=(u|0)==1;if((y|0)==0|z){r=659;break}}if((r|0)==651){bc(a,-1,az(c[(ay()|0)>>2]|0)|0);q=-1;i=b;return q|0}else if((r|0)==653){bc(a,-3,13112);q=-1;i=b;return q|0}else if((r|0)==655){bc(a,-2,13024);q=-1;i=b;return q|0}else if((r|0)==656){bc(a,-4,13464);q=-1;i=b;return q|0}else if((r|0)==657){g=c[a+108>>2]|0;bc(a,-3,(g|0)==0?12936:g);q=-1;i=b;return q|0}else if((r|0)==659){g=h-y|0;c[a+36>>2]=g;y=(c[a+96>>2]|0)+(-g|0)|0;c[a+32>>2]=y;h=a+132|0;c[h>>2]=a$(c[h>>2]|0,y,g)|0;if(!z){q=0;i=b;return q|0}do{if((bh(a,d)|0)!=-1){if((bh(a,e)|0)==-1){break}if((c[d>>2]|0)!=(c[h>>2]|0)){bc(a,-3,12808);q=-1;i=b;return q|0}if((c[e>>2]|0)==(c[a+104>>2]|0)){c[a+52>>2]=0;q=0;i=b;return q|0}else{bc(a,-3,13904);q=-1;i=b;return q|0}}}while(0);bc(a,-3,13112);q=-1;i=b;return q|0}else if((r|0)==669){i=b;return q|0}return 0}function bf(b){b=b|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ab=0,ac=0,ad=0,ae=0,af=0,ag=0,ah=0,ai=0,aj=0,ak=0,al=0,am=0,an=0,ao=0,ap=0,aq=0,ar=0,as=0,au=0,av=0,aw=0,ax=0,aA=0,aB=0,aC=0,aD=0,aE=0,aF=0,aG=0,aH=0,aI=0,aJ=0,aK=0,aL=0,aM=0,aN=0,aO=0,aP=0,aQ=0,aR=0,aS=0;e=b+84|0;f=b+16|0;do{if((c[f>>2]|0)==0){g=c[b+20>>2]|0;h=bF(g)|0;i=b+24|0;c[i>>2]=h;j=bF(g<<1)|0;k=b+28|0;c[k>>2]=j;l=(j|0)==0;if(!((h|0)==0|l)){c[f>>2]=g;c[b+116>>2]=0;c[b+120>>2]=0;c[b+124>>2]=0;g=b+88|0;c[g>>2]=0;c[e>>2]=0;if((bp(e,-15,13368,56)|0)==0){m=g;break}bG(c[k>>2]|0);bG(c[i>>2]|0);c[f>>2]=0;bc(b,-4,13464);n=-1;return n|0}if(l){o=h}else{bG(j);o=c[i>>2]|0}if((o|0)!=0){bG(o)}bc(b,-4,13464);n=-1;return n|0}else{m=b+88|0}}while(0);o=c[m>>2]|0;do{if((o|0)==0){if((c[b+76>>2]|0)!=0){n=-1;return n|0}i=b+40|0;if((c[i>>2]|0)!=0){n=0;return n|0}j=b+24|0;h=c[j>>2]|0;l=c[f>>2]|0;c[m>>2]=0;k=b+4|0;g=0;while(1){p=at(c[k>>2]|0,h+g|0,l-g|0)|0;if((p|0)<1){q=696;break}r=(c[m>>2]|0)+p|0;c[m>>2]=r;if(r>>>0>>0){g=r}else{s=r;break}}do{if((q|0)==696){if((p|0)>=0){c[i>>2]=1;s=c[m>>2]|0;break}bc(b,-1,az(c[(ay()|0)>>2]|0)|0);n=-1;return n|0}}while(0);c[b+84>>2]=c[j>>2];if((s|0)==0){n=0}else{t=s;break}return n|0}else{t=o}}while(0);o=e|0;s=c[o>>2]|0;if((a[s]|0)==31){p=t-1|0;c[m>>2]=p;i=s+1|0;c[o>>2]=i;do{if((p|0)==0){if((c[b+76>>2]|0)!=0){n=-1;return n|0}s=b+40|0;if((c[s>>2]|0)!=0){break}g=b+24|0;l=c[g>>2]|0;h=c[f>>2]|0;c[m>>2]=0;k=b+4|0;r=0;while(1){u=at(c[k>>2]|0,l+r|0,h-r|0)|0;if((u|0)<1){q=708;break}v=(c[m>>2]|0)+u|0;c[m>>2]=v;if(v>>>0>>0){r=v}else{w=v;break}}do{if((q|0)==708){if((u|0)>=0){c[s>>2]=1;w=c[m>>2]|0;break}bc(b,-1,az(c[(ay()|0)>>2]|0)|0);n=-1;return n|0}}while(0);s=c[g>>2]|0;c[b+84>>2]=s;if((w|0)!=0){x=w;y=s;q=712}}else{x=p;y=i;q=712}}while(0);do{if((q|0)==712){if((a[y]|0)!=-117){break}i=x-1|0;c[m>>2]=i;p=y+1|0;c[o>>2]=p;L967:do{if((i|0)==0){if((c[b+76>>2]|0)!=0){break}w=b+40|0;if((c[w>>2]|0)!=0){break}u=b+24|0;s=c[u>>2]|0;r=c[f>>2]|0;c[m>>2]=0;h=b+4|0;l=0;while(1){z=at(c[h>>2]|0,s+l|0,r-l|0)|0;if((z|0)<1){q=719;break}k=(c[m>>2]|0)+z|0;c[m>>2]=k;if(k>>>0>>0){l=k}else{A=k;break}}do{if((q|0)==719){if((z|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);break L967}else{c[w>>2]=1;A=c[m>>2]|0;break}}}while(0);w=c[u>>2]|0;c[b+84>>2]=w;if((A|0)!=0){B=A;C=w;q=723}}else{B=i;C=p;q=723}}while(0);do{if((q|0)==723){p=B-1|0;c[m>>2]=p;i=C+1|0;c[o>>2]=i;if((a[C]|0)!=8){break}L983:do{if((p|0)==0){if((c[b+76>>2]|0)!=0){break}g=b+40|0;if((c[g>>2]|0)!=0){break}w=b+24|0;l=c[w>>2]|0;r=c[f>>2]|0;c[m>>2]=0;s=b+4|0;h=0;while(1){D=at(c[s>>2]|0,l+h|0,r-h|0)|0;if((D|0)<1){q=731;break}k=(c[m>>2]|0)+D|0;c[m>>2]=k;if(k>>>0>>0){h=k}else{E=k;break}}do{if((q|0)==731){if((D|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);break L983}else{c[g>>2]=1;E=c[m>>2]|0;break}}}while(0);g=c[w>>2]|0;c[b+84>>2]=g;if((E|0)!=0){F=E;G=g;q=735}}else{F=p;G=i;q=735}}while(0);do{if((q|0)==735){i=F-1|0;c[m>>2]=i;p=G+1|0;c[o>>2]=p;u=d[G]|0;if((u&224|0)!=0){break}L999:do{if((i|0)==0){g=b+76|0;if((c[g>>2]|0)!=0){q=749;break}h=b+40|0;if((c[h>>2]|0)!=0){H=g;q=750;break}r=b+24|0;l=c[r>>2]|0;s=c[f>>2]|0;c[m>>2]=0;k=b+4|0;j=0;while(1){I=at(c[k>>2]|0,l+j|0,s-j|0)|0;if((I|0)<1){q=743;break}v=(c[m>>2]|0)+I|0;c[m>>2]=v;if(v>>>0>>0){j=v}else{J=v;break}}do{if((q|0)==743){if((I|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);K=c[m>>2]|0;q=748;break L999}else{c[h>>2]=1;J=c[m>>2]|0;break}}}while(0);h=c[r>>2]|0;c[b+84>>2]=h;if((J|0)==0){H=g;q=750}else{L=J;M=h;q=747}}else{L=i;M=p;q=747}}while(0);if((q|0)==747){p=L-1|0;c[m>>2]=p;c[o>>2]=M+1;K=p;q=748}if((q|0)==748){if((K|0)==0){q=749}else{N=K;q=759}}if((q|0)==749){H=b+76|0;q=750}L1018:do{if((q|0)==750){if((c[H>>2]|0)!=0){q=761;break}p=b+40|0;if((c[p>>2]|0)!=0){O=H;q=762;break}i=b+24|0;w=c[i>>2]|0;h=c[f>>2]|0;c[m>>2]=0;j=b+4|0;s=0;while(1){P=at(c[j>>2]|0,w+s|0,h-s|0)|0;if((P|0)<1){q=755;break}l=(c[m>>2]|0)+P|0;c[m>>2]=l;if(l>>>0>>0){s=l}else{Q=l;break}}do{if((q|0)==755){if((P|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);R=c[m>>2]|0;q=760;break L1018}else{c[p>>2]=1;Q=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[i>>2];if((Q|0)==0){O=H;q=762}else{N=Q;q=759}}}while(0);if((q|0)==759){p=N-1|0;c[m>>2]=p;c[o>>2]=(c[o>>2]|0)+1;R=p;q=760}if((q|0)==760){if((R|0)==0){q=761}else{S=R;q=771}}if((q|0)==761){O=b+76|0;q=762}L1037:do{if((q|0)==762){if((c[O>>2]|0)!=0){q=773;break}p=b+40|0;if((c[p>>2]|0)!=0){T=O;q=774;break}s=b+24|0;h=c[s>>2]|0;w=c[f>>2]|0;c[m>>2]=0;j=b+4|0;g=0;while(1){U=at(c[j>>2]|0,h+g|0,w-g|0)|0;if((U|0)<1){q=767;break}r=(c[m>>2]|0)+U|0;c[m>>2]=r;if(r>>>0>>0){g=r}else{V=r;break}}do{if((q|0)==767){if((U|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);W=c[m>>2]|0;q=772;break L1037}else{c[p>>2]=1;V=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[s>>2];if((V|0)==0){T=O;q=774}else{S=V;q=771}}}while(0);if((q|0)==771){p=S-1|0;c[m>>2]=p;c[o>>2]=(c[o>>2]|0)+1;W=p;q=772}if((q|0)==772){if((W|0)==0){q=773}else{X=W;q=783}}if((q|0)==773){T=b+76|0;q=774}L1056:do{if((q|0)==774){if((c[T>>2]|0)!=0){q=785;break}p=b+40|0;if((c[p>>2]|0)!=0){Y=T;q=786;break}g=b+24|0;w=c[g>>2]|0;h=c[f>>2]|0;c[m>>2]=0;j=b+4|0;i=0;while(1){Z=at(c[j>>2]|0,w+i|0,h-i|0)|0;if((Z|0)<1){q=779;break}r=(c[m>>2]|0)+Z|0;c[m>>2]=r;if(r>>>0>>0){i=r}else{_=r;break}}do{if((q|0)==779){if((Z|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);$=c[m>>2]|0;q=784;break L1056}else{c[p>>2]=1;_=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[g>>2];if((_|0)==0){Y=T;q=786}else{X=_;q=783}}}while(0);if((q|0)==783){p=X-1|0;c[m>>2]=p;c[o>>2]=(c[o>>2]|0)+1;$=p;q=784}if((q|0)==784){if(($|0)==0){q=785}else{aa=$;q=795}}if((q|0)==785){Y=b+76|0;q=786}L1075:do{if((q|0)==786){if((c[Y>>2]|0)!=0){q=797;break}p=b+40|0;if((c[p>>2]|0)!=0){ab=Y;q=798;break}i=b+24|0;h=c[i>>2]|0;w=c[f>>2]|0;c[m>>2]=0;j=b+4|0;s=0;while(1){ac=at(c[j>>2]|0,h+s|0,w-s|0)|0;if((ac|0)<1){q=791;break}r=(c[m>>2]|0)+ac|0;c[m>>2]=r;if(r>>>0>>0){s=r}else{ad=r;break}}do{if((q|0)==791){if((ac|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);ae=c[m>>2]|0;q=796;break L1075}else{c[p>>2]=1;ad=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[i>>2];if((ad|0)==0){ab=Y;q=798}else{aa=ad;q=795}}}while(0);if((q|0)==795){p=aa-1|0;c[m>>2]=p;c[o>>2]=(c[o>>2]|0)+1;ae=p;q=796}if((q|0)==796){if((ae|0)==0){q=797}else{af=ae;q=807}}if((q|0)==797){ab=b+76|0;q=798}L1094:do{if((q|0)==798){if((c[ab>>2]|0)!=0){break}p=b+40|0;if((c[p>>2]|0)!=0){break}s=b+24|0;w=c[s>>2]|0;h=c[f>>2]|0;c[m>>2]=0;j=b+4|0;g=0;while(1){ag=at(c[j>>2]|0,w+g|0,h-g|0)|0;if((ag|0)<1){q=803;break}r=(c[m>>2]|0)+ag|0;c[m>>2]=r;if(r>>>0>>0){g=r}else{ah=r;break}}do{if((q|0)==803){if((ag|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);break L1094}else{c[p>>2]=1;ah=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[s>>2];if((ah|0)!=0){af=ah;q=807}}}while(0);if((q|0)==807){c[m>>2]=af-1;c[o>>2]=(c[o>>2]|0)+1}L1110:do{if((u&4|0)!=0){p=c[m>>2]|0;L1112:do{if((p|0)==0){g=b+76|0;if((c[g>>2]|0)!=0){ai=-1;q=821;break}h=b+40|0;if((c[h>>2]|0)!=0){aj=-1;ak=g;q=822;break}w=b+24|0;j=c[w>>2]|0;i=c[f>>2]|0;c[m>>2]=0;r=b+4|0;l=0;while(1){al=at(c[r>>2]|0,j+l|0,i-l|0)|0;if((al|0)<1){q=815;break}k=(c[m>>2]|0)+al|0;c[m>>2]=k;if(k>>>0>>0){l=k}else{am=k;break}}do{if((q|0)==815){if((al|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);an=-1;ao=c[m>>2]|0;q=820;break L1112}else{c[h>>2]=1;am=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[w>>2];if((am|0)==0){aj=-1;ak=g;q=822}else{ap=am;q=819}}else{ap=p;q=819}}while(0);if((q|0)==819){p=ap-1|0;c[m>>2]=p;s=c[o>>2]|0;c[o>>2]=s+1;an=d[s]|0;ao=p;q=820}if((q|0)==820){if((ao|0)==0){ai=an;q=821}else{aq=ao;ar=an;q=831}}if((q|0)==821){aj=ai;ak=b+76|0;q=822}L1131:do{if((q|0)==822){if((c[ak>>2]|0)!=0){as=-256;au=aj;break}p=b+40|0;if((c[p>>2]|0)!=0){as=-256;au=aj;break}s=b+24|0;h=c[s>>2]|0;l=c[f>>2]|0;c[m>>2]=0;i=b+4|0;j=0;while(1){av=at(c[i>>2]|0,h+j|0,l-j|0)|0;if((av|0)<1){q=827;break}r=(c[m>>2]|0)+av|0;c[m>>2]=r;if(r>>>0>>0){j=r}else{aw=r;break}}do{if((q|0)==827){if((av|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);as=-256;au=aj;break L1131}else{c[p>>2]=1;aw=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[s>>2];if((aw|0)==0){as=-256;au=aj}else{aq=aw;ar=aj;q=831}}}while(0);if((q|0)==831){c[m>>2]=aq-1;p=c[o>>2]|0;c[o>>2]=p+1;as=d[p]<<8;au=ar}p=as+au|0;if((p|0)==0){break}j=b+76|0;l=b+40|0;h=b+24|0;i=b+4|0;g=b+84|0;w=p;p=c[m>>2]|0;while(1){w=w-1|0;if((p|0)==0){if((c[j>>2]|0)!=0){break L1110}if((c[l>>2]|0)!=0){break L1110}r=c[h>>2]|0;k=c[f>>2]|0;c[m>>2]=0;v=0;while(1){ax=at(c[i>>2]|0,r+v|0,k-v|0)|0;if((ax|0)<1){q=840;break}aA=(c[m>>2]|0)+ax|0;c[m>>2]=aA;if(aA>>>0>>0){v=aA}else{aB=aA;break}}if((q|0)==840){q=0;if((ax|0)<0){break}c[l>>2]=1;aB=c[m>>2]|0}c[g>>2]=c[h>>2];if((aB|0)==0){break L1110}else{aC=aB}}else{aC=p}p=aC-1|0;c[m>>2]=p;c[o>>2]=(c[o>>2]|0)+1;if((w|0)==0){break L1110}}bc(b,-1,az(c[(ay()|0)>>2]|0)|0)}}while(0);L1164:do{if((u&8|0)!=0){w=b+76|0;p=b+40|0;h=b+24|0;g=b+4|0;l=b+84|0;i=c[m>>2]|0;while(1){if((i|0)==0){if((c[w>>2]|0)!=0){break L1164}if((c[p>>2]|0)!=0){break L1164}j=c[h>>2]|0;v=c[f>>2]|0;c[m>>2]=0;k=0;while(1){aD=at(c[g>>2]|0,j+k|0,v-k|0)|0;if((aD|0)<1){q=853;break}r=(c[m>>2]|0)+aD|0;c[m>>2]=r;if(r>>>0>>0){k=r}else{aE=r;break}}if((q|0)==853){q=0;if((aD|0)<0){break}c[p>>2]=1;aE=c[m>>2]|0}c[l>>2]=c[h>>2];if((aE|0)==0){break L1164}else{aF=aE}}else{aF=i}i=aF-1|0;c[m>>2]=i;k=c[o>>2]|0;c[o>>2]=k+1;if((a[k]|0)==0){break L1164}}bc(b,-1,az(c[(ay()|0)>>2]|0)|0)}}while(0);L1182:do{if((u&16|0)!=0){i=b+76|0;h=b+40|0;l=b+24|0;p=b+4|0;g=b+84|0;w=c[m>>2]|0;while(1){if((w|0)==0){if((c[i>>2]|0)!=0){break L1182}if((c[h>>2]|0)!=0){break L1182}k=c[l>>2]|0;v=c[f>>2]|0;c[m>>2]=0;j=0;while(1){aG=at(c[p>>2]|0,k+j|0,v-j|0)|0;if((aG|0)<1){q=866;break}r=(c[m>>2]|0)+aG|0;c[m>>2]=r;if(r>>>0>>0){j=r}else{aH=r;break}}if((q|0)==866){q=0;if((aG|0)<0){break}c[h>>2]=1;aH=c[m>>2]|0}c[g>>2]=c[l>>2];if((aH|0)==0){break L1182}else{aI=aH}}else{aI=w}w=aI-1|0;c[m>>2]=w;j=c[o>>2]|0;c[o>>2]=j+1;if((a[j]|0)==0){break L1182}}bc(b,-1,az(c[(ay()|0)>>2]|0)|0)}}while(0);L1200:do{if((u&2|0)!=0){w=c[m>>2]|0;L1202:do{if((w|0)==0){l=b+76|0;if((c[l>>2]|0)!=0){q=884;break}g=b+40|0;if((c[g>>2]|0)!=0){aJ=l;q=885;break}h=b+24|0;p=c[h>>2]|0;i=c[f>>2]|0;c[m>>2]=0;j=b+4|0;v=0;while(1){aK=at(c[j>>2]|0,p+v|0,i-v|0)|0;if((aK|0)<1){q=878;break}k=(c[m>>2]|0)+aK|0;c[m>>2]=k;if(k>>>0>>0){v=k}else{aL=k;break}}do{if((q|0)==878){if((aK|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);aM=c[m>>2]|0;q=883;break L1202}else{c[g>>2]=1;aL=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[h>>2];if((aL|0)==0){aJ=l;q=885}else{aN=aL;q=882}}else{aN=w;q=882}}while(0);if((q|0)==882){w=aN-1|0;c[m>>2]=w;c[o>>2]=(c[o>>2]|0)+1;aM=w;q=883}if((q|0)==883){if((aM|0)==0){q=884}else{aO=aM}}if((q|0)==884){aJ=b+76|0;q=885}if((q|0)==885){if((c[aJ>>2]|0)!=0){break}w=b+40|0;if((c[w>>2]|0)!=0){break}g=b+24|0;v=c[g>>2]|0;i=c[f>>2]|0;c[m>>2]=0;p=b+4|0;j=0;while(1){aP=at(c[p>>2]|0,v+j|0,i-j|0)|0;if((aP|0)<1){q=890;break}k=(c[m>>2]|0)+aP|0;c[m>>2]=k;if(k>>>0>>0){j=k}else{aQ=k;break}}do{if((q|0)==890){if((aP|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);break L1200}else{c[w>>2]=1;aQ=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[g>>2];if((aQ|0)==0){break}else{aO=aQ}}c[m>>2]=aO-1;c[o>>2]=(c[o>>2]|0)+1}}while(0);bm(e)|0;c[b+132>>2]=a$(0,0,0)|0;c[b+52>>2]=2;c[b+56>>2]=0;n=0;return n|0}}while(0);bc(b,-3,13176);n=-1;return n|0}}while(0);bc(b,-3,13256);n=-1;return n|0}}while(0);e=b+28|0;a[c[e>>2]|0]=31;c[b+36>>2]=1;aR=c[m>>2]|0;aS=e}else{aR=t;aS=b+28|0}c[b+48>>2]=c[b+12>>2];t=c[aS>>2]|0;c[b+32>>2]=t;if((aR|0)!=0){aS=b+36|0;e=t+(c[aS>>2]|0)|0;t=c[o>>2]|0;bJ(e|0,t|0,aR)|0;c[aS>>2]=(c[aS>>2]|0)+(c[m>>2]|0);c[m>>2]=0}c[b+52>>2]=1;c[b+56>>2]=1;n=0;return n|0}function bg(a){a=a|0;var b=0,d=0;if((a|0)==0){b=-2;return b|0}if((c[a>>2]|0)!=7247){b=-2;return b|0}if((c[a+16>>2]|0)!=0){d=a+84|0;bu(d)|0;bG(c[a+28>>2]|0);bG(c[a+24>>2]|0)}bc(a,0,0);bG(c[a+8>>2]|0);d=an(c[a+4>>2]|0)|0;bG(a);b=((d|0)!=0)<<31>>31;return b|0}function bh(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0;e=a+84|0;f=a+88|0;g=c[f>>2]|0;L1259:do{if((g|0)==0){h=a+76|0;if((c[h>>2]|0)!=0){i=-1;j=934;break}k=a+40|0;if((c[k>>2]|0)!=0){l=-1;m=h;j=935;break}n=a+24|0;o=c[n>>2]|0;p=c[a+16>>2]|0;c[f>>2]=0;q=a+4|0;r=0;while(1){s=at(c[q>>2]|0,o+r|0,p-r|0)|0;if((s|0)<1){j=928;break}t=(c[f>>2]|0)+s|0;c[f>>2]=t;if(t>>>0

>>0){r=t}else{u=t;break}}do{if((j|0)==928){if((s|0)<0){bc(a,-1,az(c[(ay()|0)>>2]|0)|0);v=-1;w=c[f>>2]|0;j=933;break L1259}else{c[k>>2]=1;u=c[f>>2]|0;break}}}while(0);c[a+84>>2]=c[n>>2];if((u|0)==0){l=-1;m=h;j=935}else{x=u;j=932}}else{x=g;j=932}}while(0);if((j|0)==932){g=x-1|0;c[f>>2]=g;x=e|0;u=c[x>>2]|0;c[x>>2]=u+1;v=d[u]|0;w=g;j=933}if((j|0)==933){if((w|0)==0){i=v;j=934}else{y=w;z=v;j=946}}if((j|0)==934){l=i;m=a+76|0;j=935}L1278:do{if((j|0)==935){if((c[m>>2]|0)!=0){A=l-256|0;j=948;break}i=a+40|0;if((c[i>>2]|0)==0){v=a+24|0;w=c[v>>2]|0;g=c[a+16>>2]|0;c[f>>2]=0;u=a+4|0;x=0;while(1){B=at(c[u>>2]|0,w+x|0,g-x|0)|0;if((B|0)<1){j=941;break}s=(c[f>>2]|0)+B|0;c[f>>2]=s;if(s>>>0>>0){x=s}else{C=s;break}}do{if((j|0)==941){if((B|0)<0){bc(a,-1,az(c[(ay()|0)>>2]|0)|0);D=-256;E=l;F=c[f>>2]|0;j=947;break L1278}else{c[i>>2]=1;C=c[f>>2]|0;break}}}while(0);c[a+84>>2]=c[v>>2];if((C|0)!=0){y=C;z=l;j=946;break}}G=l-256|0;H=m;j=949}}while(0);if((j|0)==946){m=y-1|0;c[f>>2]=m;y=e|0;l=c[y>>2]|0;c[y>>2]=l+1;D=(d[l]|0)<<8;E=z;F=m;j=947}if((j|0)==947){m=D+E|0;if((F|0)==0){A=m;j=948}else{I=F;J=m;j=960}}if((j|0)==948){G=A;H=a+76|0;j=949}L1301:do{if((j|0)==949){if((c[H>>2]|0)!=0){K=G-65536|0;j=962;break}A=a+40|0;if((c[A>>2]|0)==0){m=a+24|0;F=c[m>>2]|0;E=c[a+16>>2]|0;c[f>>2]=0;D=a+4|0;z=0;while(1){L=at(c[D>>2]|0,F+z|0,E-z|0)|0;if((L|0)<1){j=955;break}l=(c[f>>2]|0)+L|0;c[f>>2]=l;if(l>>>0>>0){z=l}else{M=l;break}}do{if((j|0)==955){if((L|0)<0){bc(a,-1,az(c[(ay()|0)>>2]|0)|0);N=-65536;O=G;P=c[f>>2]|0;j=961;break L1301}else{c[A>>2]=1;M=c[f>>2]|0;break}}}while(0);c[a+84>>2]=c[m>>2];if((M|0)!=0){I=M;J=G;j=960;break}}Q=G-65536|0;R=H;j=963}}while(0);if((j|0)==960){H=I-1|0;c[f>>2]=H;I=e|0;G=c[I>>2]|0;c[I>>2]=G+1;N=(d[G]|0)<<16;O=J;P=H;j=961}if((j|0)==961){H=N+O|0;if((P|0)==0){K=H;j=962}else{S=P;T=H}}if((j|0)==962){Q=K;R=a+76|0;j=963}do{if((j|0)==963){if((c[R>>2]|0)!=0){U=-1;return U|0}K=a+40|0;if((c[K>>2]|0)!=0){U=-1;return U|0}H=a+24|0;P=c[H>>2]|0;O=c[a+16>>2]|0;c[f>>2]=0;N=a+4|0;J=0;while(1){V=at(c[N>>2]|0,P+J|0,O-J|0)|0;if((V|0)<1){j=968;break}G=(c[f>>2]|0)+V|0;c[f>>2]=G;if(G>>>0>>0){J=G}else{W=G;break}}do{if((j|0)==968){if((V|0)>=0){c[K>>2]=1;W=c[f>>2]|0;break}bc(a,-1,az(c[(ay()|0)>>2]|0)|0);U=-1;return U|0}}while(0);c[a+84>>2]=c[H>>2];if((W|0)==0){U=-1}else{S=W;T=Q;break}return U|0}}while(0);c[f>>2]=S-1;S=e|0;e=c[S>>2]|0;c[S>>2]=e+1;c[b>>2]=((d[e]|0)<<24)+T;U=0;return U|0}function bi(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;if((a|0)==0){e=0;return e|0}f=a;g=a+84|0;if((c[a>>2]|0)!=31153){e=0;return e|0}if((c[a+76>>2]|0)!=0){e=0;return e|0}if((d|0)<0){bc(f,-5,13520);e=0;return e|0}if((d|0)==0){e=0;return e|0}h=a+16|0;do{if((c[h>>2]|0)==0){if((bj(f)|0)==-1){e=0}else{break}return e|0}}while(0);i=a+72|0;L1366:do{if((c[i>>2]|0)!=0){c[i>>2]=0;j=c[a+68>>2]|0;k=a+88|0;do{if((c[k>>2]|0)!=0){if((bk(f,0)|0)==-1){e=0}else{break}return e|0}}while(0);l=a+24|0;m=g;n=a+12|0;o=j;p=1;while(1){if((o|0)==0){break L1366}q=c[h>>2]|0;r=(q|0)<0|(q|0)>(o|0)?o:q;if((p|0)!=0){bI(c[l>>2]|0,0,r|0)}c[k>>2]=r;c[m>>2]=c[l>>2];c[n>>2]=(c[n>>2]|0)+r;if((bk(f,0)|0)==-1){e=0;break}else{o=o-r|0;p=0}}return e|0}}while(0);i=a+88|0;L1380:do{if((c[h>>2]|0)>>>0>d>>>0){p=a+24|0;o=g;n=a+12|0;l=b;m=d;while(1){k=c[i>>2]|0;if((k|0)==0){j=c[p>>2]|0;c[o>>2]=j;s=j}else{s=c[o>>2]|0}j=(c[h>>2]|0)-k|0;r=j>>>0>m>>>0?m:j;j=s+k|0;bJ(j|0,l|0,r)|0;c[i>>2]=(c[i>>2]|0)+r;c[n>>2]=(c[n>>2]|0)+r;if((m|0)==(r|0)){break L1380}if((bk(f,0)|0)==-1){e=0;break}l=l+r|0;m=m-r|0}return e|0}else{do{if((c[i>>2]|0)!=0){if((bk(f,0)|0)==-1){e=0}else{break}return e|0}}while(0);c[i>>2]=d;c[g>>2]=b;m=a+12|0;c[m>>2]=(c[m>>2]|0)+d;if((bk(f,0)|0)==-1){e=0}else{break}return e|0}}while(0);e=d;return e|0}function bj(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;b=a+20|0;d=c[b>>2]|0;e=bF(d)|0;f=a+24|0;c[f>>2]=e;g=bF(d)|0;d=a+28|0;c[d>>2]=g;h=(g|0)==0;if(!((e|0)==0|h)){c[a+116>>2]=0;c[a+120>>2]=0;c[a+124>>2]=0;if((a0(a+84|0,c[a+60>>2]|0,8,31,8,c[a+64>>2]|0,13360,56)|0)==0){i=c[b>>2]|0;c[a+16>>2]=i;c[a+100>>2]=i;i=c[d>>2]|0;c[a+96>>2]=i;c[a+32>>2]=i;j=0;return j|0}else{bG(c[f>>2]|0);bc(a,-4,13448);j=-1;return j|0}}if(h){k=e}else{bG(g);k=c[f>>2]|0}if((k|0)!=0){bG(k)}bc(a,-4,13448);j=-1;return j|0}function bk(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;d=a+84|0;e=a+16|0;do{if((c[e>>2]|0)==0){if((bj(a)|0)==-1){f=-1}else{break}return f|0}}while(0);g=a+100|0;h=a+96|0;i=a+32|0;j=a+28|0;k=a+4|0;L1420:do{if((b|0)==4){l=0;m=c[g>>2]|0;while(1){if((m|0)==0|(l|0)==1){n=c[h>>2]|0;o=c[i>>2]|0;p=n-o|0;if((n|0)==(o|0)){q=m}else{n=as(c[k>>2]|0,o|0,p|0)|0;if(!((n|0)>-1&(n|0)==(p|0))){r=1062;break L1420}q=c[g>>2]|0}if((q|0)==0){p=c[e>>2]|0;c[g>>2]=p;n=c[j>>2]|0;c[h>>2]=n;s=p;t=n}else{s=q;t=c[h>>2]|0}c[i>>2]=t;u=s}else{u=m}n=a3(d,4)|0;if((n|0)==-2){r=1068;break L1420}p=c[g>>2]|0;if((u|0)==(p|0)){r=1070;break}else{l=n;m=p}}}else if((b|0)==0){m=c[g>>2]|0;while(1){if((m|0)==0){l=c[h>>2]|0;p=c[i>>2]|0;n=l-p|0;do{if((l|0)==(p|0)){r=1042}else{o=as(c[k>>2]|0,p|0,n|0)|0;if(!((o|0)>-1&(o|0)==(n|0))){r=1062;break L1420}o=c[g>>2]|0;if((o|0)==0){r=1042;break}v=o;w=c[h>>2]|0}}while(0);if((r|0)==1042){r=0;n=c[e>>2]|0;c[g>>2]=n;p=c[j>>2]|0;c[h>>2]=p;v=n;w=p}c[i>>2]=w;x=v}else{x=m}if((a3(d,0)|0)==-2){r=1068;break L1420}p=c[g>>2]|0;if((x|0)==(p|0)){r=1070;break}else{m=p}}}else{m=c[g>>2]|0;while(1){if((m|0)!=0&(b|0)==0){y=m}else{p=c[h>>2]|0;n=c[i>>2]|0;l=p-n|0;if((p|0)==(n|0)){z=m}else{p=as(c[k>>2]|0,n|0,l|0)|0;if(!((p|0)>-1&(p|0)==(l|0))){r=1062;break L1420}z=c[g>>2]|0}if((z|0)==0){l=c[e>>2]|0;c[g>>2]=l;p=c[j>>2]|0;c[h>>2]=p;A=l;B=p}else{A=z;B=c[h>>2]|0}c[i>>2]=B;y=A}if((a3(d,b)|0)==-2){r=1068;break L1420}p=c[g>>2]|0;if((y|0)==(p|0)){r=1070;break}else{m=p}}}}while(0);if((r|0)==1062){bc(a,-1,az(c[(ay()|0)>>2]|0)|0);f=-1;return f|0}else if((r|0)==1070){if((b|0)!=4){f=0;return f|0}a2(d)|0;f=0;return f|0}else if((r|0)==1068){bc(a,-2,13792);f=-1;return f|0}return 0}function bl(e,f){e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ab=0,ac=0,ad=0,ae=0,af=0,ag=0,ah=0,ai=0,aj=0,ak=0,al=0,am=0,an=0,ao=0,ap=0,aq=0,ar=0,as=0,at=0,au=0,av=0,aw=0,ax=0,ay=0,az=0,aA=0,aB=0,aC=0,aD=0,aE=0,aF=0,aG=0,aH=0,aI=0,aJ=0,aK=0,aL=0,aM=0,aN=0,aO=0,aP=0,aQ=0,aR=0,aS=0,aT=0,aU=0,aV=0,aW=0,aX=0;g=c[e+28>>2]|0;h=g;i=e|0;j=c[i>>2]|0;k=e+4|0;l=j+((c[k>>2]|0)-6)|0;m=e+12|0;n=c[m>>2]|0;o=e+16|0;p=c[o>>2]|0;q=n+(p-258)|0;r=c[h+44>>2]|0;s=c[h+48>>2]|0;t=c[h+52>>2]|0;u=h+56|0;v=h+60|0;w=c[h+76>>2]|0;x=c[h+80>>2]|0;y=(1<>2])-1|0;z=(1<>2])-1|0;A=n+(p+~f)|0;f=h+7104|0;p=t-1|0;B=(s|0)==0;C=(c[h+40>>2]|0)-1|0;h=C+s|0;D=s-1|0;E=A-1|0;F=A-s|0;G=j-1|0;j=n-1|0;n=c[u>>2]|0;H=c[v>>2]|0;L1476:while(1){if(H>>>0<15){I=G+2|0;J=I;K=((d[G+1|0]|0)<>1]|0;O=d[w+(I<<2)+1|0]|0;I=K>>>(O>>>0);P=L-O|0;do{if(M<<24>>24==0){Q=N&255;R=I;S=P;T=1083}else{O=N;U=I;V=P;W=M;while(1){X=W&255;if((X&16|0)!=0){break}if((X&64|0)!=0){T=1131;break L1476}Y=(U&(1<>1]|0;$=d[w+(Y<<2)+1|0]|0;aa=U>>>($>>>0);ab=V-$|0;if(Z<<24>>24==0){T=1082;break}else{O=_;U=aa;V=ab;W=Z}}if((T|0)==1082){T=0;Q=_&255;R=aa;S=ab;T=1083;break}W=O&65535;Z=X&15;if((Z|0)==0){ac=W;ad=J;ae=U;af=V}else{if(V>>>0>>0){$=J+1|0;ag=$;ah=((d[$]|0)<>>(Z>>>0);af=ai-Z|0}if(af>>>0<15){Z=ad+2|0;aj=Z;ak=((d[ad+1|0]|0)<>1]|0;$=d[x+(Z<<2)+1|0]|0;Y=ak>>>($>>>0);am=al-$|0;$=d[x+(Z<<2)|0]|0;if(($&16|0)==0){Z=W;an=Y;ao=am;ap=$;while(1){if((ap&64|0)!=0){T=1128;break L1476}aq=(an&(1<>1]|0;as=d[x+(aq<<2)+1|0]|0;at=an>>>(as>>>0);au=ao-as|0;as=d[x+(aq<<2)|0]|0;if((as&16|0)==0){Z=ar;an=at;ao=au;ap=as}else{av=ar;aw=at;ax=au;ay=as;break}}}else{av=W;aw=Y;ax=am;ay=$}ap=av&65535;Z=ay&15;do{if(ax>>>0>>0){O=aj+1|0;as=((d[O]|0)<>>0>=Z>>>0){az=O;aA=as;aB=au;break}O=aj+2|0;az=O;aA=((d[O]|0)<>>(Z>>>0);aD=aB-Z|0;am=j;Y=am-A|0;if($>>>0<=Y>>>0){W=j+(-$|0)|0;as=ac;au=j;while(1){a[au+1|0]=a[W+1|0]|0;a[au+2|0]=a[W+2|0]|0;O=W+3|0;aE=au+3|0;a[aE]=a[O]|0;aF=as-3|0;if(aF>>>0>2){W=O;as=aF;au=aE}else{break}}if((aF|0)==0){aG=az;aH=aE;aI=aC;aJ=aD;break}as=au+4|0;a[as]=a[W+4|0]|0;if(aF>>>0<=1){aG=az;aH=as;aI=aC;aJ=aD;break}as=au+5|0;a[as]=a[W+5|0]|0;aG=az;aH=as;aI=aC;aJ=aD;break}as=$-Y|0;if(as>>>0>r>>>0){if((c[f>>2]|0)!=0){T=1098;break L1476}}do{if(B){Z=t+(C-as)|0;if(as>>>0>=ac>>>0){aK=Z;aL=ac;aM=j;break}ap=ac-as|0;O=$-am|0;at=Z;Z=as;ar=j;do{at=at+1|0;ar=ar+1|0;a[ar]=a[at]|0;Z=Z-1|0;}while((Z|0)!=0);aK=j+(E+O+(1-$))|0;aL=ap;aM=j+(A+O)|0}else{if(s>>>0>=as>>>0){Z=t+(D-as)|0;if(as>>>0>=ac>>>0){aK=Z;aL=ac;aM=j;break}at=ac-as|0;ar=$-am|0;aq=Z;Z=as;aN=j;do{aq=aq+1|0;aN=aN+1|0;a[aN]=a[aq]|0;Z=Z-1|0;}while((Z|0)!=0);aK=j+(E+ar+(1-$))|0;aL=at;aM=j+(A+ar)|0;break}Z=t+(h-as)|0;aq=as-s|0;if(aq>>>0>=ac>>>0){aK=Z;aL=ac;aM=j;break}aN=ac-aq|0;O=$-am|0;ap=Z;Z=aq;aq=j;do{ap=ap+1|0;aq=aq+1|0;a[aq]=a[ap]|0;Z=Z-1|0;}while((Z|0)!=0);Z=j+(F+O)|0;if(s>>>0>=aN>>>0){aK=p;aL=aN;aM=Z;break}ap=aN-s|0;aq=p;ar=s;at=Z;do{aq=aq+1|0;at=at+1|0;a[at]=a[aq]|0;ar=ar-1|0;}while((ar|0)!=0);aK=j+(E+O+(1-$))|0;aL=ap;aM=j+(A+O)|0}}while(0);if(aL>>>0>2){$=aM;am=aL;as=aK;while(1){a[$+1|0]=a[as+1|0]|0;a[$+2|0]=a[as+2|0]|0;Y=as+3|0;W=$+3|0;a[W]=a[Y]|0;au=am-3|0;if(au>>>0>2){$=W;am=au;as=Y}else{aO=W;aP=au;aQ=Y;break}}}else{aO=aM;aP=aL;aQ=aK}if((aP|0)==0){aG=az;aH=aO;aI=aC;aJ=aD;break}as=aO+1|0;a[as]=a[aQ+1|0]|0;if(aP>>>0<=1){aG=az;aH=as;aI=aC;aJ=aD;break}as=aO+2|0;a[as]=a[aQ+2|0]|0;aG=az;aH=as;aI=aC;aJ=aD}}while(0);if((T|0)==1083){T=0;M=j+1|0;a[M]=Q;aG=J;aH=M;aI=R;aJ=S}if(aG>>>0>>0&aH>>>0>>0){G=aG;j=aH;n=aI;H=aJ}else{aR=aG;aS=aH;aT=aI;aU=aJ;break}}do{if((T|0)==1128){c[e+24>>2]=13712;c[g>>2]=29;aR=aj;aS=j;aT=an;aU=ao}else if((T|0)==1131){if((X&32|0)==0){c[e+24>>2]=13416;c[g>>2]=29;aR=J;aS=j;aT=U;aU=V;break}else{c[g>>2]=11;aR=J;aS=j;aT=U;aU=V;break}}else if((T|0)==1098){c[e+24>>2]=13304;c[g>>2]=29;aR=az;aS=j;aT=aC;aU=aD}}while(0);aD=aU>>>3;aC=aR+(-aD|0)|0;j=aU-(aD<<3)|0;aU=(1<>2]=aR+(1-aD);c[m>>2]=aS+1;if(aC>>>0>>0){aV=l-aC|0}else{aV=l-aC|0}c[k>>2]=aV+5;if(aS>>>0>>0){aW=q-aS|0;aX=aW+257|0;c[o>>2]=aX;c[u>>2]=aU;c[v>>2]=j;return}else{aW=q-aS|0;aX=aW+257|0;c[o>>2]=aX;c[u>>2]=aU;c[v>>2]=j;return}}function bm(a){a=a|0;var b=0,d=0,e=0;if((a|0)==0){b=-2;return b|0}d=c[a+28>>2]|0;if((d|0)==0){b=-2;return b|0}e=d;c[e+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[d>>2]=0;c[e+4>>2]=0;c[e+12>>2]=0;c[e+20>>2]=32768;c[e+32>>2]=0;c[e+40>>2]=0;c[e+44>>2]=0;c[e+48>>2]=0;c[e+56>>2]=0;c[e+60>>2]=0;d=e+1328|0;c[e+108>>2]=d;c[e+80>>2]=d;c[e+76>>2]=d;c[e+7104>>2]=1;c[e+7108>>2]=-1;b=0;return b|0}function bn(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;if((a|0)==0){b=-2;return b|0}d=a;if((c[a>>2]|0)!=31153){b=-2;return b|0}e=a+72|0;L1582:do{if((c[e>>2]|0)==0){f=0}else{c[e>>2]=0;g=c[a+68>>2]|0;h=a+88|0;if((c[h>>2]|0)!=0){if((bk(d,0)|0)==-1){f=-1;break}}i=a+16|0;j=a+24|0;k=a+84|0;l=a+12|0;m=g;g=1;while(1){if((m|0)==0){f=0;break L1582}n=c[i>>2]|0;o=(n|0)<0|(n|0)>(m|0)?m:n;if((g|0)!=0){bI(c[j>>2]|0,0,o|0)}c[h>>2]=o;c[k>>2]=c[j>>2];c[l>>2]=(c[l>>2]|0)+o;if((bk(d,0)|0)==-1){f=-1;break}else{m=m-o|0;g=0}}}}while(0);e=(bk(d,4)|0)+f|0;a1(a+84|0)|0;bG(c[a+28>>2]|0);bG(c[a+24>>2]|0);bc(d,0,0);bG(c[a+8>>2]|0);d=an(c[a+4>>2]|0)|0;bG(a);b=((e|0)!=(-d|0))<<31>>31;return b|0}function bo(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;if((a|0)==0){d=-2;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;return d|0}g=f;if((b|0)<0){h=0;i=-b|0}else{h=(b>>4)+1|0;i=(b|0)<48?b&15:b}if((i|0)!=0&(i-8|0)>>>0>7){d=-2;return d|0}b=g+52|0;f=c[b>>2]|0;j=g+36|0;do{if((f|0)!=0){if((c[j>>2]|0)==(i|0)){break}aF[c[a+36>>2]&3](c[a+40>>2]|0,f);c[b>>2]=0}}while(0);c[g+8>>2]=h;c[j>>2]=i;i=c[e>>2]|0;if((i|0)==0){d=-2;return d|0}e=i;c[e+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[i>>2]=0;c[e+4>>2]=0;c[e+12>>2]=0;c[e+20>>2]=32768;c[e+32>>2]=0;c[e+40>>2]=0;c[e+44>>2]=0;c[e+48>>2]=0;c[e+56>>2]=0;c[e+60>>2]=0;i=e+1328|0;c[e+108>>2]=i;c[e+80>>2]=i;c[e+76>>2]=i;c[e+7104>>2]=1;c[e+7108>>2]=-1;d=0;return d|0}function bp(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;if((e|0)==0){g=-6;return g|0}if(!((a[e]|0)==49&(f|0)==56)){g=-6;return g|0}if((b|0)==0){g=-2;return g|0}c[b+24>>2]=0;f=b+32|0;e=c[f>>2]|0;if((e|0)==0){c[f>>2]=6;c[b+40>>2]=0;h=6}else{h=e}e=b+36|0;if((c[e>>2]|0)==0){c[e>>2]=2}f=b+40|0;i=aG[h&7](c[f>>2]|0,1,7116)|0;if((i|0)==0){g=-4;return g|0}h=b+28|0;c[h>>2]=i;c[i+52>>2]=0;j=bo(b,d)|0;if((j|0)==0){g=0;return g|0}aF[c[e>>2]&3](c[f>>2]|0,i);c[h>>2]=0;g=j;return g|0}function bq(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ab=0,ac=0,ad=0,ae=0,af=0,ag=0,ah=0,ai=0,aj=0,ak=0,al=0,am=0,an=0,ao=0,ap=0,aq=0,ar=0,as=0,at=0,au=0,av=0,aw=0,ax=0,ay=0,az=0,aA=0,aC=0,aD=0,aE=0,aF=0,aG=0,aH=0,aI=0,aJ=0,aK=0,aL=0,aM=0,aN=0,aO=0,aP=0,aQ=0,aR=0,aS=0,aT=0,aU=0,aV=0,aW=0,aX=0,aY=0,aZ=0,a0=0,a1=0,a2=0,a3=0,a4=0,a5=0,a6=0,a7=0,a8=0,a9=0,ba=0,bb=0,bc=0,bd=0,be=0,bf=0,bg=0,bh=0,bi=0,bj=0,bk=0,bm=0,bn=0,bo=0,bp=0,bq=0,br=0,bs=0,bu=0,bw=0,bx=0,by=0,bz=0,bA=0,bB=0,bC=0,bD=0,bE=0,bF=0,bG=0,bH=0,bI=0,bK=0,bL=0,bM=0,bN=0,bO=0,bP=0,bQ=0,bR=0,bS=0,bT=0,bU=0,bV=0,bW=0,bX=0,bY=0,bZ=0,b_=0,b$=0,b0=0,b1=0,b2=0,b3=0,b4=0,b5=0,b6=0,b7=0,b8=0,b9=0,ca=0,cb=0,cc=0,cd=0,ce=0,cf=0,cg=0,ch=0,ci=0,cj=0,ck=0,cl=0,cm=0,cn=0,co=0,cp=0,cq=0,cr=0,cs=0,ct=0,cu=0,cv=0,cw=0,cx=0,cy=0,cz=0,cA=0,cB=0,cC=0,cD=0,cE=0,cF=0,cG=0,cH=0,cI=0,cJ=0,cK=0,cL=0,cM=0,cN=0,cO=0,cP=0,cQ=0,cR=0,cS=0,cT=0,cU=0,cV=0,cW=0,cX=0,cY=0,cZ=0,c_=0,c$=0,c0=0,c1=0,c2=0,c3=0,c4=0,c5=0,c6=0,c7=0,c8=0,c9=0,da=0,db=0,dc=0,dd=0,de=0,df=0,dg=0,dh=0,di=0,dj=0,dk=0,dl=0,dm=0,dn=0,dp=0,dq=0,dr=0,ds=0,dt=0,du=0,dv=0,dw=0,dx=0,dy=0,dz=0,dA=0,dB=0,dC=0,dD=0,dE=0,dF=0,dG=0,dH=0,dI=0,dJ=0,dK=0,dL=0,dM=0,dN=0,dO=0,dP=0,dQ=0,dR=0,dS=0,dT=0,dU=0,dV=0,dW=0,dX=0,dY=0,dZ=0,d_=0,d$=0,d0=0,d1=0,d2=0,d3=0,d4=0,d5=0,d6=0,d7=0,d8=0,d9=0,ea=0,eb=0,ec=0,ed=0,ee=0,ef=0,eg=0,eh=0,ei=0,ej=0,ek=0,el=0,em=0,en=0,eo=0,ep=0,eq=0,er=0,es=0,et=0,eu=0,ev=0,ew=0,ex=0,ey=0,ez=0,eA=0,eB=0,eC=0,eD=0,eE=0,eF=0,eG=0,eH=0,eI=0,eJ=0,eK=0,eL=0,eM=0,eN=0,eO=0,eP=0,eQ=0,eR=0,eS=0,eT=0,eU=0,eV=0,eW=0,eX=0,eY=0,eZ=0,e_=0,e$=0,e0=0,e1=0,e2=0,e3=0,e4=0,e5=0,e6=0,e7=0,e8=0,e9=0,fa=0,fb=0,fc=0,fd=0,fe=0,ff=0,fg=0,fh=0,fi=0,fj=0,fk=0,fl=0,fm=0,fn=0,fo=0,fp=0,fq=0,fr=0,fs=0,ft=0,fu=0,fv=0,fw=0,fx=0,fy=0,fz=0,fA=0,fB=0,fC=0,fD=0,fE=0,fF=0,fG=0,fH=0,fI=0,fJ=0,fK=0,fL=0,fM=0,fN=0,fO=0,fP=0,fQ=0,fR=0;h=i;i=i+8|0;j=h|0;if((f|0)==0){k=-2;i=h;return k|0}l=c[f+28>>2]|0;if((l|0)==0){k=-2;i=h;return k|0}m=f+12|0;n=c[m>>2]|0;if((n|0)==0){k=-2;i=h;return k|0}o=f|0;p=c[o>>2]|0;do{if((p|0)==0){if((c[f+4>>2]|0)==0){break}else{k=-2}i=h;return k|0}}while(0);q=l;r=l;l=c[r>>2]|0;if((l|0)==11){c[r>>2]=12;s=c[m>>2]|0;t=c[o>>2]|0;u=12}else{s=n;t=p;u=l}l=f+16|0;p=c[l>>2]|0;n=f+4|0;v=c[n>>2]|0;w=q+56|0;x=q+60|0;y=q+8|0;z=q+24|0;A=j|0;B=j+1|0;C=q+16|0;D=q+32|0;E=f+24|0;F=q+36|0;G=q+20|0;H=f+48|0;I=q+64|0;J=q+12|0;K=(g-5|0)>>>0<2;L=q+4|0;M=q+76|0;N=q+84|0;O=q+80|0;P=q+88|0;Q=(g|0)==6;R=q+7108|0;S=q+72|0;T=q+7112|0;U=q+68|0;V=q+44|0;W=q+7104|0;X=q+48|0;Y=q+52|0;Z=q+40|0;_=f+20|0;$=q+28|0;aa=q+96|0;ab=q+100|0;ac=q+92|0;ad=q+104|0;ae=q+1328|0;af=q+108|0;ag=q+112|0;ah=q+752|0;ai=q+624|0;aj=j+2|0;ak=j+3|0;j=0;al=p;am=c[x>>2]|0;an=c[w>>2]|0;ao=p;p=v;ap=s;s=t;t=u;L1657:while(1){L1659:do{if((t|0)==2){if(am>>>0<32){aq=s;ar=p;as=an;at=am;au=1246}else{av=s;aw=p;ax=an;au=1248}}else if((t|0)==7){ay=am;az=an;aA=p;aC=s;au=1295}else if((t|0)==9){if(am>>>0<32){u=s;aD=p;aE=an;aF=am;while(1){if((aD|0)==0){aG=j;aH=al;aI=aF;aJ=aE;aK=0;aL=u;aM=ao;break L1657}aN=aD-1|0;aO=u+1|0;aP=(d[u]<>>0<32){u=aO;aD=aN;aE=aP;aF=aQ}else{aR=aO;aS=aN;aT=aP;break}}}else{aR=s;aS=p;aT=an}aF=aB(aT|0)|0;c[z>>2]=aF;c[H>>2]=aF;c[r>>2]=10;aU=0;aV=0;aW=aS;aX=aR;au=1320}else if((t|0)==1){if(am>>>0<16){aF=s;aE=p;aD=an;u=am;while(1){if((aE|0)==0){aG=j;aH=al;aI=u;aJ=aD;aK=0;aL=aF;aM=ao;break L1657}aP=aE-1|0;aN=aF+1|0;aO=(d[aF]<>>0<16){aF=aN;aE=aP;aD=aO;u=aQ}else{aY=aN;aZ=aP;a0=aO;a1=aQ;break}}}else{aY=s;aZ=p;a0=an;a1=am}c[C>>2]=a0;if((a0&255|0)!=8){c[E>>2]=13384;c[r>>2]=29;a2=j;a3=al;a4=a1;a5=a0;a6=ao;a7=aZ;a8=ap;a9=aY;break}if((a0&57344|0)!=0){c[E>>2]=13224;c[r>>2]=29;a2=j;a3=al;a4=a1;a5=a0;a6=ao;a7=aZ;a8=ap;a9=aY;break}u=c[D>>2]|0;if((u|0)==0){ba=a0}else{c[u>>2]=a0>>>8&1;ba=c[C>>2]|0}if((ba&512|0)!=0){a[A]=a0&255;a[B]=a0>>>8&255;c[z>>2]=a$(c[z>>2]|0,A,2)|0}c[r>>2]=2;aq=aY;ar=aZ;as=0;at=0;au=1246}else if((t|0)==5){bb=am;bc=an;bd=p;be=s;au=1272}else if((t|0)==21){bf=j;bg=am;bh=an;bi=p;bj=s;bk=c[S>>2]|0;au=1419}else if((t|0)==17){u=c[ad>>2]|0;if(u>>>0<(c[ac>>2]|0)>>>0){bm=s;bn=p;bo=an;bp=am;bq=u;au=1353}else{br=s;bs=p;bu=an;bw=am;bx=u;au=1357}}else if((t|0)==18){by=j;bz=am;bA=an;bB=p;bC=s;bD=c[ad>>2]|0;au=1362}else if((t|0)==12){bE=am;bF=an;bG=p;bH=s;au=1324}else if((t|0)==25){if((ao|0)==0){bI=j;bK=am;bL=an;bM=p;bN=s;bO=0;au=1483;break L1657}a[ap]=c[I>>2]&255;c[r>>2]=20;a2=j;a3=al;a4=am;a5=an;a6=ao-1|0;a7=p;a8=ap+1|0;a9=s}else if((t|0)==26){do{if((c[y>>2]|0)==0){bP=al;bQ=am;bR=an;bS=p;bT=s}else{if(am>>>0<32){u=s;aD=p;aE=an;aF=am;while(1){if((aD|0)==0){aG=j;aH=al;aI=aF;aJ=aE;aK=0;aL=u;aM=ao;break L1657}aQ=aD-1|0;aO=u+1|0;aP=(d[u]<>>0<32){u=aO;aD=aQ;aE=aP;aF=aN}else{bU=aO;bV=aQ;bW=aP;bX=aN;break}}}else{bU=s;bV=p;bW=an;bX=am}aF=al-ao|0;c[_>>2]=(c[_>>2]|0)+aF;c[$>>2]=(c[$>>2]|0)+aF;if((al|0)!=(ao|0)){aE=c[z>>2]|0;aD=ap+(-aF|0)|0;if((c[C>>2]|0)==0){bY=a_(aE,aD,aF)|0}else{bY=a$(aE,aD,aF)|0}c[z>>2]=bY;c[H>>2]=bY}if((c[C>>2]|0)==0){bZ=aB(bW|0)|0}else{bZ=bW}if((bZ|0)==(c[z>>2]|0)){bP=ao;bQ=0;bR=0;bS=bV;bT=bU;break}c[E>>2]=13576;c[r>>2]=29;a2=j;a3=ao;a4=bX;a5=bW;a6=ao;a7=bV;a8=ap;a9=bU;break L1659}}while(0);c[r>>2]=27;b_=bP;b$=bQ;b0=bR;b1=bS;b2=bT;au=1475}else if((t|0)==27){b_=al;b$=am;b0=an;b1=p;b2=s;au=1475}else if((t|0)==28){bI=1;bK=am;bL=an;bM=p;bN=s;bO=ao;au=1483;break L1657}else if((t|0)==29){aG=-3;aH=al;aI=am;aJ=an;aK=p;aL=s;aM=ao;break L1657}else if((t|0)==0){aF=c[y>>2]|0;if((aF|0)==0){c[r>>2]=12;a2=j;a3=al;a4=am;a5=an;a6=ao;a7=p;a8=ap;a9=s;break}if(am>>>0<16){aD=s;aE=p;u=an;aN=am;while(1){if((aE|0)==0){aG=j;aH=al;aI=aN;aJ=u;aK=0;aL=aD;aM=ao;break L1657}aP=aE-1|0;aQ=aD+1|0;aO=(d[aD]<>>0<16){aD=aQ;aE=aP;u=aO;aN=b3}else{b4=aQ;b5=aP;b6=aO;b7=b3;break}}}else{b4=s;b5=p;b6=an;b7=am}if((aF&2|0)!=0&(b6|0)==35615){c[z>>2]=a$(0,0,0)|0;a[A]=31;a[B]=-117;c[z>>2]=a$(c[z>>2]|0,A,2)|0;c[r>>2]=1;a2=j;a3=al;a4=0;a5=0;a6=ao;a7=b5;a8=ap;a9=b4;break}c[C>>2]=0;aN=c[D>>2]|0;if((aN|0)==0){b8=aF}else{c[aN+48>>2]=-1;b8=c[y>>2]|0}do{if((b8&1|0)!=0){if(((((b6<<8&65280)+(b6>>>8)|0)>>>0)%31|0|0)!=0){break}if((b6&15|0)!=8){c[E>>2]=13384;c[r>>2]=29;a2=j;a3=al;a4=b7;a5=b6;a6=ao;a7=b5;a8=ap;a9=b4;break L1659}aN=b6>>>4;u=b7-4|0;aE=(aN&15)+8|0;aD=c[F>>2]|0;do{if((aD|0)==0){c[F>>2]=aE}else{if(aE>>>0<=aD>>>0){break}c[E>>2]=13336;c[r>>2]=29;a2=j;a3=al;a4=u;a5=aN;a6=ao;a7=b5;a8=ap;a9=b4;break L1659}}while(0);c[G>>2]=1<>2]=aN;c[H>>2]=aN;c[r>>2]=b6>>>12&2^11;a2=j;a3=al;a4=0;a5=0;a6=ao;a7=b5;a8=ap;a9=b4;break L1659}}while(0);c[E>>2]=13656;c[r>>2]=29;a2=j;a3=al;a4=b7;a5=b6;a6=ao;a7=b5;a8=ap;a9=b4}else if((t|0)==16){if(am>>>0<14){aF=s;aN=p;u=an;aD=am;while(1){if((aN|0)==0){aG=j;aH=al;aI=aD;aJ=u;aK=0;aL=aF;aM=ao;break L1657}b3=aN-1|0;aO=aF+1|0;aP=(d[aF]<>>0<14){aF=aO;aN=b3;u=aP;aD=aQ}else{b9=aO;ca=b3;cb=aP;cc=aQ;break}}}else{b9=s;ca=p;cb=an;cc=am}aD=(cb&31)+257|0;c[aa>>2]=aD;u=(cb>>>5&31)+1|0;c[ab>>2]=u;c[ac>>2]=(cb>>>10&15)+4;aN=cb>>>14;aF=cc-14|0;if(aD>>>0>286|u>>>0>30){c[E>>2]=12896;c[r>>2]=29;a2=j;a3=al;a4=aF;a5=aN;a6=ao;a7=ca;a8=ap;a9=b9;break}else{c[ad>>2]=0;c[r>>2]=17;bm=b9;bn=ca;bo=aN;bp=aF;bq=0;au=1353;break}}else if((t|0)==3){if(am>>>0<16){cd=s;ce=p;cf=an;cg=am;au=1254}else{ch=s;ci=p;cj=an;au=1256}}else if((t|0)==8){ck=am;cl=an;cm=p;cn=s;au=1308}else if((t|0)==23){co=j;cp=am;cq=an;cr=p;cs=s;ct=c[S>>2]|0;au=1438}else if((t|0)==4){cu=am;cv=an;cw=p;cx=s;au=1261}else if((t|0)==30){au=1497;break L1657}else if((t|0)==22){cy=j;cz=am;cA=an;cB=p;cC=s;au=1426}else if((t|0)==24){cD=j;cE=am;cF=an;cG=p;cH=s;au=1444}else if((t|0)==14){cI=am;cJ=an;cK=p;cL=s;au=1342}else if((t|0)==15){cM=am;cN=an;cO=p;cP=s;au=1343}else if((t|0)==19){cQ=j;cR=am;cS=an;cT=p;cU=s;au=1399}else if((t|0)==20){cV=j;cW=am;cX=an;cY=p;cZ=s;au=1400}else if((t|0)==13){aF=am&7;aN=an>>>(aF>>>0);u=am-aF|0;if(u>>>0<32){aF=s;aD=p;aQ=aN;aP=u;while(1){if((aD|0)==0){aG=j;aH=al;aI=aP;aJ=aQ;aK=0;aL=aF;aM=ao;break L1657}b3=aD-1|0;aO=aF+1|0;c_=(d[aF]<>>0<32){aF=aO;aD=b3;aQ=c_;aP=c$}else{c0=aO;c1=b3;c2=c_;c3=c$;break}}}else{c0=s;c1=p;c2=aN;c3=u}aP=c2&65535;if((aP|0)==(c2>>>16^65535|0)){c[I>>2]=aP;c[r>>2]=14;if(Q){bI=j;bK=0;bL=0;bM=c1;bN=c0;bO=ao;au=1483;break L1657}else{cI=0;cJ=0;cK=c1;cL=c0;au=1342;break}}else{c[E>>2]=12992;c[r>>2]=29;a2=j;a3=al;a4=c3;a5=c2;a6=ao;a7=c1;a8=ap;a9=c0;break}}else if((t|0)==10){aU=am;aV=an;aW=p;aX=s;au=1320}else if((t|0)==11){c4=am;c5=an;c6=p;c7=s;au=1323}else if((t|0)==6){c8=am;c9=an;da=p;db=s;au=1282}else{k=-2;au=1500;break L1657}}while(0);if((au|0)==1246){while(1){au=0;if((ar|0)==0){aG=j;aH=al;aI=at;aJ=as;aK=0;aL=aq;aM=ao;break L1657}aP=ar-1|0;aQ=aq+1|0;aD=(d[aq]<>>0<32){aq=aQ;ar=aP;as=aD;at=aF;au=1246}else{av=aQ;aw=aP;ax=aD;au=1248;break}}}else if((au|0)==1353){while(1){au=0;if(bp>>>0<3){aD=bm;aP=bn;aQ=bo;aF=bp;while(1){if((aP|0)==0){aG=j;aH=al;aI=aF;aJ=aQ;aK=0;aL=aD;aM=ao;break L1657}c$=aP-1|0;c_=aD+1|0;b3=(d[aD]<>>0<3){aD=c_;aP=c$;aQ=b3;aF=aO}else{dc=c_;dd=c$;de=b3;df=aO;break}}}else{dc=bm;dd=bn;de=bo;df=bp}c[ad>>2]=bq+1;b[q+112+(e[1664+(bq<<1)>>1]<<1)>>1]=de&7;aF=de>>>3;aQ=df-3|0;aP=c[ad>>2]|0;if(aP>>>0<(c[ac>>2]|0)>>>0){bm=dc;bn=dd;bo=aF;bp=aQ;bq=aP;au=1353}else{br=dc;bs=dd;bu=aF;bw=aQ;bx=aP;au=1357;break}}}else if((au|0)==1475){au=0;if((c[y>>2]|0)==0){dg=b$;dh=b0;di=b1;dj=b2;au=1482;break}if((c[C>>2]|0)==0){dg=b$;dh=b0;di=b1;dj=b2;au=1482;break}if(b$>>>0<32){aP=b2;aQ=b1;aF=b0;aD=b$;while(1){if((aQ|0)==0){aG=j;aH=b_;aI=aD;aJ=aF;aK=0;aL=aP;aM=ao;break L1657}u=aQ-1|0;aN=aP+1|0;aO=(d[aP]<>>0<32){aP=aN;aQ=u;aF=aO;aD=b3}else{dk=aN;dl=u;dm=aO;dn=b3;break}}}else{dk=b2;dl=b1;dm=b0;dn=b$}if((dm|0)==(c[$>>2]|0)){dg=0;dh=0;di=dl;dj=dk;au=1482;break}c[E>>2]=13496;c[r>>2]=29;a2=j;a3=b_;a4=dn;a5=dm;a6=ao;a7=dl;a8=ap;a9=dk}else if((au|0)==1342){au=0;c[r>>2]=15;cM=cI;cN=cJ;cO=cK;cP=cL;au=1343}else if((au|0)==1320){au=0;if((c[J>>2]|0)==0){au=1321;break}aD=a_(0,0,0)|0;c[z>>2]=aD;c[H>>2]=aD;c[r>>2]=11;c4=aU;c5=aV;c6=aW;c7=aX;au=1323}do{if((au|0)==1357){au=0;if(bx>>>0<19){aD=bx;do{c[ad>>2]=aD+1;b[q+112+(e[1664+(aD<<1)>>1]<<1)>>1]=0;aD=c[ad>>2]|0;}while(aD>>>0<19)}c[af>>2]=ae;c[M>>2]=ae;c[N>>2]=7;aD=bv(0,ag,19,af,N,ah)|0;if((aD|0)==0){c[ad>>2]=0;c[r>>2]=18;by=0;bz=bw;bA=bu;bB=bs;bC=br;bD=0;au=1362;break}else{c[E>>2]=12776;c[r>>2]=29;a2=aD;a3=al;a4=bw;a5=bu;a6=ao;a7=bs;a8=ap;a9=br;break}}else if((au|0)==1343){au=0;aD=c[I>>2]|0;if((aD|0)==0){c[r>>2]=11;a2=j;a3=al;a4=cM;a5=cN;a6=ao;a7=cO;a8=ap;a9=cP;break}aF=aD>>>0>cO>>>0?cO:aD;aD=aF>>>0>ao>>>0?ao:aF;if((aD|0)==0){bI=j;bK=cM;bL=cN;bM=cO;bN=cP;bO=ao;au=1483;break L1657}bJ(ap|0,cP|0,aD)|0;c[I>>2]=(c[I>>2]|0)-aD;a2=j;a3=al;a4=cM;a5=cN;a6=ao-aD|0;a7=cO-aD|0;a8=ap+aD|0;a9=cP+aD|0}else if((au|0)==1323){au=0;if(K){bI=j;bK=c4;bL=c5;bM=c6;bN=c7;bO=ao;au=1483;break L1657}else{bE=c4;bF=c5;bG=c6;bH=c7;au=1324}}else if((au|0)==1248){au=0;aD=c[D>>2]|0;if((aD|0)!=0){c[aD+4>>2]=ax}if((c[C>>2]&512|0)!=0){a[A]=ax&255;a[B]=ax>>>8&255;a[aj]=ax>>>16&255;a[ak]=ax>>>24&255;c[z>>2]=a$(c[z>>2]|0,A,4)|0}c[r>>2]=3;cd=av;ce=aw;cf=0;cg=0;au=1254}}while(0);L1802:do{if((au|0)==1324){au=0;if((c[L>>2]|0)!=0){aD=bE&7;c[r>>2]=26;a2=j;a3=al;a4=bE-aD|0;a5=bF>>>(aD>>>0);a6=ao;a7=bG;a8=ap;a9=bH;break}if(bE>>>0<3){aD=bH;aF=bG;aQ=bF;aP=bE;while(1){if((aF|0)==0){aG=j;aH=al;aI=aP;aJ=aQ;aK=0;aL=aD;aM=ao;break L1657}b3=aF-1|0;aO=aD+1|0;u=(d[aD]<>>0<3){aD=aO;aF=b3;aQ=u;aP=aN}else{dp=aO;dq=b3;dr=u;ds=aN;break}}}else{dp=bH;dq=bG;dr=bF;ds=bE}c[L>>2]=dr&1;aP=dr>>>1&3;if((aP|0)==0){c[r>>2]=13}else if((aP|0)==1){c[M>>2]=1704;c[N>>2]=9;c[O>>2]=3752;c[P>>2]=5;c[r>>2]=19;if(Q){au=1332;break L1657}}else if((aP|0)==2){c[r>>2]=16}else if((aP|0)==3){c[E>>2]=13088;c[r>>2]=29}a2=j;a3=al;a4=ds-3|0;a5=dr>>>3;a6=ao;a7=dq;a8=ap;a9=dp}else if((au|0)==1362){au=0;aP=c[aa>>2]|0;aQ=c[ab>>2]|0;do{if(bD>>>0<(aQ+aP|0)>>>0){aF=bC;aD=bB;aN=bA;u=bz;b3=bD;aO=aP;c$=aQ;L1820:while(1){c_=(1<>2])-1|0;dt=c_&aN;du=c[M>>2]|0;dv=d[du+(dt<<2)+1|0]|0;if(dv>>>0>u>>>0){dw=aF;dx=aD;dy=aN;dz=u;while(1){if((dx|0)==0){aG=by;aH=al;aI=dz;aJ=dy;aK=0;aL=dw;aM=ao;break L1657}dA=dx-1|0;dB=dw+1|0;dC=(d[dw]<>>0>dD>>>0){dw=dB;dx=dA;dy=dC;dz=dD}else{dG=dB;dH=dA;dI=dC;dJ=dD;dK=dE;dL=dF;break}}}else{dG=aF;dH=aD;dI=aN;dJ=u;dK=dt;dL=dv}dz=b[du+(dK<<2)+2>>1]|0;L1827:do{if((dz&65535)<16){if(dJ>>>0

>>0){dy=dG;dx=dH;dw=dI;c_=dJ;while(1){if((dx|0)==0){aG=by;aH=al;aI=c_;aJ=dw;aK=0;aL=dy;aM=ao;break L1657}dF=dx-1|0;dE=dy+1|0;dD=(d[dy]<>>0
>>0){dy=dE;dx=dF;dw=dD;c_=dC}else{dM=dE;dN=dF;dO=dD;dP=dC;break}}}else{dM=dG;dN=dH;dO=dI;dP=dJ}c[ad>>2]=b3+1;b[q+112+(b3<<1)>>1]=dz;dQ=dP-dL|0;dR=dO>>>(dL>>>0);dS=dN;dT=dM}else{if((dz<<16>>16|0)==16){c_=dL+2|0;if(dJ>>>0>>0){dw=dG;dx=dH;dy=dI;dC=dJ;while(1){if((dx|0)==0){aG=by;aH=al;aI=dC;aJ=dy;aK=0;aL=dw;aM=ao;break L1657}dD=dx-1|0;dF=dw+1|0;dE=(d[dw]<>>0>>0){dw=dF;dx=dD;dy=dE;dC=dA}else{dU=dF;dV=dD;dW=dE;dX=dA;break}}}else{dU=dG;dV=dH;dW=dI;dX=dJ}dY=dW>>>(dL>>>0);dZ=dX-dL|0;if((b3|0)==0){au=1379;break L1820}d_=b[q+112+(b3-1<<1)>>1]|0;d$=(dY&3)+3|0;d0=dZ-2|0;d1=dY>>>2;d2=dV;d3=dU}else if((dz<<16>>16|0)==17){dC=dL+3|0;if(dJ>>>0>>0){dy=dG;dx=dH;dw=dI;c_=dJ;while(1){if((dx|0)==0){aG=by;aH=al;aI=c_;aJ=dw;aK=0;aL=dy;aM=ao;break L1657}dA=dx-1|0;dE=dy+1|0;dD=(d[dy]<>>0>>0){dy=dE;dx=dA;dw=dD;c_=dF}else{d4=dE;d5=dA;d6=dD;d7=dF;break}}}else{d4=dG;d5=dH;d6=dI;d7=dJ}c_=d6>>>(dL>>>0);d_=0;d$=(c_&7)+3|0;d0=-3-dL+d7|0;d1=c_>>>3;d2=d5;d3=d4}else{c_=dL+7|0;if(dJ>>>0>>0){dw=dG;dx=dH;dy=dI;dC=dJ;while(1){if((dx|0)==0){aG=by;aH=al;aI=dC;aJ=dy;aK=0;aL=dw;aM=ao;break L1657}dF=dx-1|0;dD=dw+1|0;dA=(d[dw]<>>0>>0){dw=dD;dx=dF;dy=dA;dC=dE}else{d8=dD;d9=dF;ea=dA;eb=dE;break}}}else{d8=dG;d9=dH;ea=dI;eb=dJ}dC=ea>>>(dL>>>0);d_=0;d$=(dC&127)+11|0;d0=-7-dL+eb|0;d1=dC>>>7;d2=d9;d3=d8}if((b3+d$|0)>>>0>(c$+aO|0)>>>0){au=1388;break L1820}else{ec=d$;ed=b3}while(1){dC=ec-1|0;c[ad>>2]=ed+1;b[q+112+(ed<<1)>>1]=d_;if((dC|0)==0){dQ=d0;dR=d1;dS=d2;dT=d3;break L1827}ec=dC;ed=c[ad>>2]|0}}}while(0);dz=c[ad>>2]|0;ee=c[aa>>2]|0;du=c[ab>>2]|0;if(dz>>>0<(du+ee|0)>>>0){aF=dT;aD=dS;aN=dR;u=dQ;b3=dz;aO=ee;c$=du}else{au=1391;break}}if((au|0)==1379){au=0;c[E>>2]=13872;c[r>>2]=29;a2=by;a3=al;a4=dZ;a5=dY;a6=ao;a7=dV;a8=ap;a9=dU;break L1802}else if((au|0)==1388){au=0;c[E>>2]=13872;c[r>>2]=29;a2=by;a3=al;a4=d0;a5=d1;a6=ao;a7=d2;a8=ap;a9=d3;break L1802}else if((au|0)==1391){au=0;if((c[r>>2]|0)==29){a2=by;a3=al;a4=dQ;a5=dR;a6=ao;a7=dS;a8=ap;a9=dT;break L1802}else{ef=ee;eg=dQ;eh=dR;ei=dS;ej=dT;break}}}else{ef=aP;eg=bz;eh=bA;ei=bB;ej=bC}}while(0);if((b[ai>>1]|0)==0){c[E>>2]=13832;c[r>>2]=29;a2=by;a3=al;a4=eg;a5=eh;a6=ao;a7=ei;a8=ap;a9=ej;break}c[af>>2]=ae;c[M>>2]=ae;c[N>>2]=9;aP=bv(1,ag,ef,af,N,ah)|0;if((aP|0)!=0){c[E>>2]=13760;c[r>>2]=29;a2=aP;a3=al;a4=eg;a5=eh;a6=ao;a7=ei;a8=ap;a9=ej;break}c[O>>2]=c[af>>2];c[P>>2]=6;aP=bv(2,q+112+(c[aa>>2]<<1)|0,c[ab>>2]|0,af,P,ah)|0;if((aP|0)==0){c[r>>2]=19;if(Q){bI=0;bK=eg;bL=eh;bM=ei;bN=ej;bO=ao;au=1483;break L1657}else{cQ=0;cR=eg;cS=eh;cT=ei;cU=ej;au=1399;break}}else{c[E>>2]=13736;c[r>>2]=29;a2=aP;a3=al;a4=eg;a5=eh;a6=ao;a7=ei;a8=ap;a9=ej;break}}else if((au|0)==1254){while(1){au=0;if((ce|0)==0){aG=j;aH=al;aI=cg;aJ=cf;aK=0;aL=cd;aM=ao;break L1657}aP=ce-1|0;aQ=cd+1|0;c$=(d[cd]<>>0<16){cd=aQ;ce=aP;cf=c$;cg=aO;au=1254}else{ch=aQ;ci=aP;cj=c$;au=1256;break}}}}while(0);if((au|0)==1256){au=0;c$=c[D>>2]|0;if((c$|0)!=0){c[c$+8>>2]=cj&255;c[(c[D>>2]|0)+12>>2]=cj>>>8}if((c[C>>2]&512|0)!=0){a[A]=cj&255;a[B]=cj>>>8&255;c[z>>2]=a$(c[z>>2]|0,A,2)|0}c[r>>2]=4;cu=0;cv=0;cw=ci;cx=ch;au=1261}else if((au|0)==1399){au=0;c[r>>2]=20;cV=cQ;cW=cR;cX=cS;cY=cT;cZ=cU;au=1400}do{if((au|0)==1261){au=0;c$=c[C>>2]|0;do{if((c$&1024|0)==0){aP=c[D>>2]|0;if((aP|0)==0){ek=cu;el=cv;em=cw;en=cx;break}c[aP+16>>2]=0;ek=cu;el=cv;em=cw;en=cx}else{if(cu>>>0<16){aP=cx;aQ=cw;aO=cv;b3=cu;while(1){if((aQ|0)==0){aG=j;aH=al;aI=b3;aJ=aO;aK=0;aL=aP;aM=ao;break L1657}u=aQ-1|0;aN=aP+1|0;aD=(d[aP]<>>0<16){aP=aN;aQ=u;aO=aD;b3=aF}else{eo=aN;ep=u;eq=aD;break}}}else{eo=cx;ep=cw;eq=cv}c[I>>2]=eq;b3=c[D>>2]|0;if((b3|0)==0){er=c$}else{c[b3+20>>2]=eq;er=c[C>>2]|0}if((er&512|0)==0){ek=0;el=0;em=ep;en=eo;break}a[A]=eq&255;a[B]=eq>>>8&255;c[z>>2]=a$(c[z>>2]|0,A,2)|0;ek=0;el=0;em=ep;en=eo}}while(0);c[r>>2]=5;bb=ek;bc=el;bd=em;be=en;au=1272}else if((au|0)==1400){au=0;if(cY>>>0>5&ao>>>0>257){c[m>>2]=ap;c[l>>2]=ao;c[o>>2]=cZ;c[n>>2]=cY;c[w>>2]=cX;c[x>>2]=cW;bl(f,al);c$=c[m>>2]|0;b3=c[l>>2]|0;aO=c[o>>2]|0;aQ=c[n>>2]|0;aP=c[w>>2]|0;aD=c[x>>2]|0;if((c[r>>2]|0)!=11){a2=cV;a3=al;a4=aD;a5=aP;a6=b3;a7=aQ;a8=c$;a9=aO;break}c[R>>2]=-1;a2=cV;a3=al;a4=aD;a5=aP;a6=b3;a7=aQ;a8=c$;a9=aO;break}c[R>>2]=0;aO=(1<>2])-1|0;c$=aO&cX;aQ=c[M>>2]|0;b3=a[aQ+(c$<<2)+1|0]|0;aP=b3&255;if(aP>>>0>cW>>>0){aD=cZ;u=cY;aN=cX;aF=cW;while(1){if((u|0)==0){aG=cV;aH=al;aI=aF;aJ=aN;aK=0;aL=aD;aM=ao;break L1657}aE=u-1|0;du=aD+1|0;dz=(d[aD]<>>0>dv>>>0){aD=du;u=aE;aN=dz;aF=dv}else{es=du;et=aE;eu=dz;ev=dv;ew=dC;ex=dt;ey=dy;break}}}else{es=cZ;et=cY;eu=cX;ev=cW;ew=b3;ex=c$;ey=aP}aF=a[aQ+(ex<<2)|0]|0;aN=b[aQ+(ex<<2)+2>>1]|0;u=aF&255;do{if(aF<<24>>24==0){ez=0;eA=ew;eB=aN;eC=ev;eD=eu;eE=et;eF=es;eG=0}else{if((u&240|0)!=0){ez=aF;eA=ew;eB=aN;eC=ev;eD=eu;eE=et;eF=es;eG=0;break}aD=aN&65535;aO=(1<>>(ey>>>0))+aD|0;dt=a[aQ+(dy<<2)+1|0]|0;if(((dt&255)+ey|0)>>>0>ev>>>0){dC=es;dv=et;dz=eu;aE=ev;while(1){if((dv|0)==0){aG=cV;aH=al;aI=aE;aJ=dz;aK=0;aL=dC;aM=ao;break L1657}du=dv-1|0;dx=dC+1|0;dw=(d[dC]<>>(ey>>>0))+aD|0;dA=a[aQ+(dE<<2)+1|0]|0;if(((dA&255)+ey|0)>>>0>c_>>>0){dC=dx;dv=du;dz=dw;aE=c_}else{eH=dx;eI=du;eJ=dw;eK=c_;eL=dE;eM=dA;break}}}else{eH=es;eI=et;eJ=eu;eK=ev;eL=dy;eM=dt}aE=b[aQ+(eL<<2)+2>>1]|0;dz=a[aQ+(eL<<2)|0]|0;c[R>>2]=ey;ez=dz;eA=eM;eB=aE;eC=eK-ey|0;eD=eJ>>>(ey>>>0);eE=eI;eF=eH;eG=ey}}while(0);aQ=eA&255;u=eD>>>(aQ>>>0);aN=eC-aQ|0;c[R>>2]=eG+aQ;c[I>>2]=eB&65535;aQ=ez&255;if(ez<<24>>24==0){c[r>>2]=25;a2=cV;a3=al;a4=aN;a5=u;a6=ao;a7=eE;a8=ap;a9=eF;break}if((aQ&32|0)!=0){c[R>>2]=-1;c[r>>2]=11;a2=cV;a3=al;a4=aN;a5=u;a6=ao;a7=eE;a8=ap;a9=eF;break}if((aQ&64|0)==0){aF=aQ&15;c[S>>2]=aF;c[r>>2]=21;bf=cV;bg=aN;bh=u;bi=eE;bj=eF;bk=aF;au=1419;break}else{c[E>>2]=13680;c[r>>2]=29;a2=cV;a3=al;a4=aN;a5=u;a6=ao;a7=eE;a8=ap;a9=eF;break}}}while(0);if((au|0)==1272){au=0;u=c[C>>2]|0;if((u&1024|0)==0){eN=bd;eO=be}else{aN=c[I>>2]|0;aF=aN>>>0>bd>>>0?bd:aN;if((aF|0)==0){eP=bd;eQ=be;eR=aN}else{aQ=c[D>>2]|0;do{if((aQ|0)==0){eS=u}else{aP=c[aQ+16>>2]|0;if((aP|0)==0){eS=u;break}c$=(c[aQ+20>>2]|0)-aN|0;b3=aP+c$|0;aP=c[aQ+24>>2]|0;aE=(c$+aF|0)>>>0>aP>>>0?aP-c$|0:aF;bJ(b3|0,be|0,aE)|0;eS=c[C>>2]|0}}while(0);if((eS&512|0)!=0){c[z>>2]=a$(c[z>>2]|0,be,aF)|0}aQ=(c[I>>2]|0)-aF|0;c[I>>2]=aQ;eP=bd-aF|0;eQ=be+aF|0;eR=aQ}if((eR|0)==0){eN=eP;eO=eQ}else{bI=j;bK=bb;bL=bc;bM=eP;bN=eQ;bO=ao;au=1483;break}}c[I>>2]=0;c[r>>2]=6;c8=bb;c9=bc;da=eN;db=eO;au=1282}else if((au|0)==1419){au=0;if((bk|0)==0){eT=bg;eU=bh;eV=bi;eW=bj;eX=c[I>>2]|0}else{if(bg>>>0>>0){aQ=bj;aN=bi;u=bh;aE=bg;while(1){if((aN|0)==0){aG=bf;aH=al;aI=aE;aJ=u;aK=0;aL=aQ;aM=ao;break L1657}b3=aN-1|0;c$=aQ+1|0;aP=(d[aQ]<>>0>>0){aQ=c$;aN=b3;u=aP;aE=dz}else{eY=c$;eZ=b3;e_=aP;e$=dz;break}}}else{eY=bj;eZ=bi;e_=bh;e$=bg}aE=(c[I>>2]|0)+((1<>2]=aE;c[R>>2]=(c[R>>2]|0)+bk;eT=e$-bk|0;eU=e_>>>(bk>>>0);eV=eZ;eW=eY;eX=aE}c[T>>2]=eX;c[r>>2]=22;cy=bf;cz=eT;cA=eU;cB=eV;cC=eW;au=1426}do{if((au|0)==1426){au=0;aE=(1<>2])-1|0;u=aE&cA;aN=c[O>>2]|0;aQ=a[aN+(u<<2)+1|0]|0;aF=aQ&255;if(aF>>>0>cz>>>0){dz=cC;aP=cB;b3=cA;c$=cz;while(1){if((aP|0)==0){aG=cy;aH=al;aI=c$;aJ=b3;aK=0;aL=dz;aM=ao;break L1657}dv=aP-1|0;dC=dz+1|0;aD=(d[dz]<>>0>aO>>>0){dz=dC;aP=dv;b3=aD;c$=aO}else{e0=dC;e1=dv;e2=aD;e3=aO;e4=dE;e5=dA;e6=c_;break}}}else{e0=cC;e1=cB;e2=cA;e3=cz;e4=aQ;e5=u;e6=aF}c$=a[aN+(e5<<2)|0]|0;b3=b[aN+(e5<<2)+2>>1]|0;aP=c$&255;if((aP&240|0)==0){dz=b3&65535;aE=(1<>>(e6>>>0))+dz|0;c_=a[aN+(aP<<2)+1|0]|0;if(((c_&255)+e6|0)>>>0>e3>>>0){dA=e0;dE=e1;aO=e2;aD=e3;while(1){if((dE|0)==0){aG=cy;aH=al;aI=aD;aJ=aO;aK=0;aL=dA;aM=ao;break L1657}dv=dE-1|0;dC=dA+1|0;dw=(d[dA]<>>(e6>>>0))+dz|0;dF=a[aN+(dx<<2)+1|0]|0;if(((dF&255)+e6|0)>>>0>du>>>0){dA=dC;dE=dv;aO=dw;aD=du}else{e7=dC;e8=dv;e9=dw;fa=du;fb=dx;fc=dF;break}}}else{e7=e0;e8=e1;e9=e2;fa=e3;fb=aP;fc=c_}aD=b[aN+(fb<<2)+2>>1]|0;aO=a[aN+(fb<<2)|0]|0;dE=(c[R>>2]|0)+e6|0;c[R>>2]=dE;fd=aO;fe=fc;ff=aD;fg=fa-e6|0;fh=e9>>>(e6>>>0);fi=e8;fj=e7;fk=dE}else{fd=c$;fe=e4;ff=b3;fg=e3;fh=e2;fi=e1;fj=e0;fk=c[R>>2]|0}dE=fe&255;aD=fh>>>(dE>>>0);aO=fg-dE|0;c[R>>2]=fk+dE;dE=fd&255;if((dE&64|0)==0){c[U>>2]=ff&65535;dA=dE&15;c[S>>2]=dA;c[r>>2]=23;co=cy;cp=aO;cq=aD;cr=fi;cs=fj;ct=dA;au=1438;break}else{c[E>>2]=13632;c[r>>2]=29;a2=cy;a3=al;a4=aO;a5=aD;a6=ao;a7=fi;a8=ap;a9=fj;break}}else if((au|0)==1282){au=0;do{if((c[C>>2]&2048|0)==0){aD=c[D>>2]|0;if((aD|0)==0){fl=da;fm=db;break}c[aD+28>>2]=0;fl=da;fm=db}else{if((da|0)==0){bI=j;bK=c8;bL=c9;bM=0;bN=db;bO=ao;au=1483;break L1657}else{fn=0}while(1){fo=fn+1|0;aD=a[db+fn|0]|0;aO=c[D>>2]|0;do{if((aO|0)!=0){dA=aO+28|0;if((c[dA>>2]|0)==0){break}dE=c[I>>2]|0;if(dE>>>0>=(c[aO+32>>2]|0)>>>0){break}c[I>>2]=dE+1;a[(c[dA>>2]|0)+dE|0]=aD}}while(0);fp=aD<<24>>24!=0;if(fp&fo>>>0>>0){fn=fo}else{break}}if((c[C>>2]&512|0)!=0){c[z>>2]=a$(c[z>>2]|0,db,fo)|0}dt=da-fo|0;dy=db+fo|0;if(fp){bI=j;bK=c8;bL=c9;bM=dt;bN=dy;bO=ao;au=1483;break L1657}else{fl=dt;fm=dy}}}while(0);c[I>>2]=0;c[r>>2]=7;ay=c8;az=c9;aA=fl;aC=fm;au=1295}}while(0);if((au|0)==1295){au=0;do{if((c[C>>2]&4096|0)==0){b3=c[D>>2]|0;if((b3|0)==0){fq=aA;fr=aC;break}c[b3+36>>2]=0;fq=aA;fr=aC}else{if((aA|0)==0){bI=j;bK=ay;bL=az;bM=0;bN=aC;bO=ao;au=1483;break L1657}else{fs=0}while(1){ft=fs+1|0;b3=a[aC+fs|0]|0;c$=c[D>>2]|0;do{if((c$|0)!=0){aN=c$+36|0;if((c[aN>>2]|0)==0){break}c_=c[I>>2]|0;if(c_>>>0>=(c[c$+40>>2]|0)>>>0){break}c[I>>2]=c_+1;a[(c[aN>>2]|0)+c_|0]=b3}}while(0);fu=b3<<24>>24!=0;if(fu&ft>>>0>>0){fs=ft}else{break}}if((c[C>>2]&512|0)!=0){c[z>>2]=a$(c[z>>2]|0,aC,ft)|0}c$=aA-ft|0;c_=aC+ft|0;if(fu){bI=j;bK=ay;bL=az;bM=c$;bN=c_;bO=ao;au=1483;break L1657}else{fq=c$;fr=c_}}}while(0);c[r>>2]=8;ck=ay;cl=az;cm=fq;cn=fr;au=1308}else if((au|0)==1438){au=0;if((ct|0)==0){fv=cp;fw=cq;fx=cr;fy=cs}else{if(cp>>>0>>0){c_=cs;c$=cr;aN=cq;aP=cp;while(1){if((c$|0)==0){aG=co;aH=al;aI=aP;aJ=aN;aK=0;aL=c_;aM=ao;break L1657}dy=c$-1|0;dt=c_+1|0;aO=(d[c_]<>>0>>0){c_=dt;c$=dy;aN=aO;aP=dE}else{fz=dt;fA=dy;fB=aO;fC=dE;break}}}else{fz=cs;fA=cr;fB=cq;fC=cp}c[U>>2]=(c[U>>2]|0)+((1<>2]=(c[R>>2]|0)+ct;fv=fC-ct|0;fw=fB>>>(ct>>>0);fx=fA;fy=fz}c[r>>2]=24;cD=co;cE=fv;cF=fw;cG=fx;cH=fy;au=1444}L2018:do{if((au|0)==1308){au=0;aP=c[C>>2]|0;do{if((aP&512|0)==0){fD=ck;fE=cl;fF=cm;fG=cn}else{if(ck>>>0<16){aN=cn;c$=cm;c_=cl;dE=ck;while(1){if((c$|0)==0){aG=j;aH=al;aI=dE;aJ=c_;aK=0;aL=aN;aM=ao;break L1657}aO=c$-1|0;dy=aN+1|0;dt=(d[aN]<>>0<16){aN=dy;c$=aO;c_=dt;dE=dA}else{fH=dy;fI=aO;fJ=dt;fK=dA;break}}}else{fH=cn;fI=cm;fJ=cl;fK=ck}if((fJ|0)==(c[z>>2]&65535|0)){fD=0;fE=0;fF=fI;fG=fH;break}c[E>>2]=13152;c[r>>2]=29;a2=j;a3=al;a4=fK;a5=fJ;a6=ao;a7=fI;a8=ap;a9=fH;break L2018}}while(0);dE=c[D>>2]|0;if((dE|0)!=0){c[dE+44>>2]=aP>>>9&1;c[(c[D>>2]|0)+48>>2]=1}dE=a$(0,0,0)|0;c[z>>2]=dE;c[H>>2]=dE;c[r>>2]=11;a2=j;a3=al;a4=fD;a5=fE;a6=ao;a7=fF;a8=ap;a9=fG}else if((au|0)==1444){au=0;if((ao|0)==0){bI=cD;bK=cE;bL=cF;bM=cG;bN=cH;bO=0;au=1483;break L1657}dE=al-ao|0;c_=c[U>>2]|0;if(c_>>>0>dE>>>0){c$=c_-dE|0;do{if(c$>>>0>(c[V>>2]|0)>>>0){if((c[W>>2]|0)==0){break}c[E>>2]=13600;c[r>>2]=29;a2=cD;a3=al;a4=cE;a5=cF;a6=ao;a7=cG;a8=ap;a9=cH;break L2018}}while(0);aP=c[X>>2]|0;if(c$>>>0>aP>>>0){dE=c$-aP|0;fL=(c[Y>>2]|0)+((c[Z>>2]|0)-dE)|0;fM=dE}else{fL=(c[Y>>2]|0)+(aP-c$)|0;fM=c$}aP=c[I>>2]|0;fN=fL;fO=fM>>>0>aP>>>0?aP:fM;fP=aP}else{aP=c[I>>2]|0;fN=ap+(-c_|0)|0;fO=aP;fP=aP}aP=fO>>>0>ao>>>0?ao:fO;c[I>>2]=fP-aP;dE=~ao;aN=~fO;b3=dE>>>0>aN>>>0?dE:aN;aN=fN;dE=aP;dA=ap;while(1){a[dA]=a[aN]|0;dt=dE-1|0;if((dt|0)==0){break}else{aN=aN+1|0;dE=dt;dA=dA+1|0}}dA=ao-aP|0;dE=ap+~b3|0;if((c[I>>2]|0)!=0){a2=cD;a3=al;a4=cE;a5=cF;a6=dA;a7=cG;a8=dE;a9=cH;break}c[r>>2]=20;a2=cD;a3=al;a4=cE;a5=cF;a6=dA;a7=cG;a8=dE;a9=cH}}while(0);j=a2;al=a3;am=a4;an=a5;ao=a6;p=a7;ap=a8;s=a9;t=c[r>>2]|0}if((au|0)==1482){c[r>>2]=28;aG=1;aH=b_;aI=dg;aJ=dh;aK=di;aL=dj;aM=ao}else if((au|0)==1483){aG=bI;aH=al;aI=bK;aJ=bL;aK=bM;aL=bN;aM=bO}else if((au|0)==1497){k=-4;i=h;return k|0}else if((au|0)==1332){aG=j;aH=al;aI=ds-3|0;aJ=dr>>>3;aK=dq;aL=dp;aM=ao}else if((au|0)==1321){c[m>>2]=ap;c[l>>2]=ao;c[o>>2]=aX;c[n>>2]=aW;c[w>>2]=aV;c[x>>2]=aU;k=2;i=h;return k|0}else if((au|0)==1500){i=h;return k|0}c[m>>2]=ap;c[l>>2]=aM;c[o>>2]=aL;c[n>>2]=aK;c[w>>2]=aJ;c[x>>2]=aI;do{if((c[Z>>2]|0)==0){if((c[r>>2]|0)>>>0>=26){break}if((aH|0)!=(c[l>>2]|0)){au=1487}}else{au=1487}}while(0);do{if((au|0)==1487){if((bt(f,aH)|0)==0){break}c[r>>2]=30;k=-4;i=h;return k|0}}while(0);au=c[n>>2]|0;n=c[l>>2]|0;l=aH-n|0;Z=f+8|0;c[Z>>2]=v-au+(c[Z>>2]|0);c[_>>2]=(c[_>>2]|0)+l;c[$>>2]=(c[$>>2]|0)+l;$=(aH|0)==(n|0);if(!((c[y>>2]|0)==0|$)){y=c[z>>2]|0;n=(c[m>>2]|0)+(-l|0)|0;if((c[C>>2]|0)==0){fQ=a_(y,n,l)|0}else{fQ=a$(y,n,l)|0}c[z>>2]=fQ;c[H>>2]=fQ}fQ=c[r>>2]|0;if((fQ|0)==19){fR=256}else{fR=(fQ|0)==14?256:0}c[f+44>>2]=((c[L>>2]|0)!=0?64:0)+(c[x>>2]|0)+((fQ|0)==11?128:0)+fR;k=((v|0)==(au|0)&$|(g|0)==4)&(aG|0)==0?-5:aG;i=h;return k|0}function br(a){a=a|0;var d=0;d=0;do{b[a+148+(d<<2)>>1]=0;d=d+1|0;}while((d|0)<286);b[a+2440>>1]=0;b[a+2444>>1]=0;b[a+2448>>1]=0;b[a+2452>>1]=0;b[a+2456>>1]=0;b[a+2460>>1]=0;b[a+2464>>1]=0;b[a+2468>>1]=0;b[a+2472>>1]=0;b[a+2476>>1]=0;b[a+2480>>1]=0;b[a+2484>>1]=0;b[a+2488>>1]=0;b[a+2492>>1]=0;b[a+2496>>1]=0;b[a+2500>>1]=0;b[a+2504>>1]=0;b[a+2508>>1]=0;b[a+2512>>1]=0;b[a+2516>>1]=0;b[a+2520>>1]=0;b[a+2524>>1]=0;b[a+2528>>1]=0;b[a+2532>>1]=0;b[a+2536>>1]=0;b[a+2540>>1]=0;b[a+2544>>1]=0;b[a+2548>>1]=0;b[a+2552>>1]=0;b[a+2556>>1]=0;b[a+2684>>1]=0;b[a+2688>>1]=0;b[a+2692>>1]=0;b[a+2696>>1]=0;b[a+2700>>1]=0;b[a+2704>>1]=0;b[a+2708>>1]=0;b[a+2712>>1]=0;b[a+2716>>1]=0;b[a+2720>>1]=0;b[a+2724>>1]=0;b[a+2728>>1]=0;b[a+2732>>1]=0;b[a+2736>>1]=0;b[a+2740>>1]=0;b[a+2744>>1]=0;b[a+2748>>1]=0;b[a+2752>>1]=0;b[a+2756>>1]=0;b[a+1172>>1]=1;c[a+5804>>2]=0;c[a+5800>>2]=0;c[a+5808>>2]=0;c[a+5792>>2]=0;return}function bs(d,f,g,h){d=d|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;i=d+5820|0;j=c[i>>2]|0;k=h&65535;h=d+5816|0;l=e[h>>1]|0|k<>1]=l&65535;if((j|0)>13){m=d+20|0;n=c[m>>2]|0;c[m>>2]=n+1;o=d+8|0;a[(c[o>>2]|0)+n|0]=l&255;n=(e[h>>1]|0)>>>8&255;p=c[m>>2]|0;c[m>>2]=p+1;a[(c[o>>2]|0)+p|0]=n;n=c[i>>2]|0;p=k>>>((16-n|0)>>>0);b[h>>1]=p&65535;q=n-13|0;r=p&255}else{q=j+3|0;r=l&255}c[i>>2]=q;do{if((q|0)>8){l=d+20|0;j=c[l>>2]|0;c[l>>2]=j+1;p=d+8|0;a[(c[p>>2]|0)+j|0]=r;j=(e[h>>1]|0)>>>8&255;n=c[l>>2]|0;c[l>>2]=n+1;a[(c[p>>2]|0)+n|0]=j;s=l;t=p}else{p=d+20|0;if((q|0)>0){l=c[p>>2]|0;c[p>>2]=l+1;j=d+8|0;a[(c[j>>2]|0)+l|0]=r;s=p;t=j;break}else{s=p;t=d+8|0;break}}}while(0);b[h>>1]=0;c[i>>2]=0;c[d+5812>>2]=8;d=c[s>>2]|0;c[s>>2]=d+1;a[(c[t>>2]|0)+d|0]=g&255;d=c[s>>2]|0;c[s>>2]=d+1;a[(c[t>>2]|0)+d|0]=g>>>8&255;d=g&65535^65535;i=c[s>>2]|0;c[s>>2]=i+1;a[(c[t>>2]|0)+i|0]=d&255;i=c[s>>2]|0;c[s>>2]=i+1;a[(c[t>>2]|0)+i|0]=d>>>8&255;if((g|0)==0){return}else{u=g;v=f}while(1){f=u-1|0;g=a[v]|0;d=c[s>>2]|0;c[s>>2]=d+1;a[(c[t>>2]|0)+d|0]=g;if((f|0)==0){break}else{u=f;v=v+1|0}}return}function bt(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;d=c[a+28>>2]|0;e=d+52|0;f=c[e>>2]|0;do{if((f|0)==0){g=aG[c[a+32>>2]&7](c[a+40>>2]|0,1<>2],1)|0;c[e>>2]=g;if((g|0)==0){h=1}else{i=g;break}return h|0}else{i=f}}while(0);f=d+40|0;g=c[f>>2]|0;if((g|0)==0){j=1<>2];c[f>>2]=j;c[d+48>>2]=0;c[d+44>>2]=0;k=j}else{k=g}g=b-(c[a+16>>2]|0)|0;if(g>>>0>=k>>>0){b=(c[a+12>>2]|0)+(-k|0)|0;bJ(i|0,b|0,k)|0;c[d+48>>2]=0;c[d+44>>2]=c[f>>2];h=0;return h|0}b=d+48|0;j=c[b>>2]|0;l=k-j|0;k=l>>>0>g>>>0?g:l;l=i+j|0;j=a+12|0;a=(c[j>>2]|0)+(-g|0)|0;bJ(l|0,a|0,k)|0;a=g-k|0;if((g|0)!=(k|0)){k=c[e>>2]|0;e=(c[j>>2]|0)+(-a|0)|0;bJ(k|0,e|0,a)|0;c[b>>2]=a;c[d+44>>2]=c[f>>2];h=0;return h|0}a=(c[b>>2]|0)+g|0;c[b>>2]=a;e=c[f>>2]|0;if((a|0)==(e|0)){c[b>>2]=0}b=d+44|0;d=c[b>>2]|0;if(d>>>0>=e>>>0){h=0;return h|0}c[b>>2]=d+g;h=0;return h|0}function bu(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;if((a|0)==0){b=-2;return b|0}d=a+28|0;e=c[d>>2]|0;if((e|0)==0){b=-2;return b|0}f=a+36|0;g=c[f>>2]|0;if((g|0)==0){b=-2;return b|0}h=c[e+52>>2]|0;i=a+40|0;if((h|0)==0){j=g;k=e}else{aF[g&3](c[i>>2]|0,h);j=c[f>>2]|0;k=c[d>>2]|0}aF[j&3](c[i>>2]|0,k);c[d>>2]=0;b=0;return b|0}function bv(d,f,g,h,j,k){d=d|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;l=i;i=i+32|0;m=l|0;n=i;i=i+32|0;bI(m|0,0,32);o=(g|0)==0;if(!o){p=0;do{q=m+(e[f+(p<<1)>>1]<<1)|0;b[q>>1]=(b[q>>1]|0)+1&65535;p=p+1|0;}while(p>>>0>>0)}p=c[j>>2]|0;q=15;while(1){if((q|0)==0){r=1559;break}if((b[m+(q<<1)>>1]|0)==0){q=q-1|0}else{break}}if((r|0)==1559){s=c[h>>2]|0;c[h>>2]=s+4;a[s|0]=64;a[s+1|0]=1;b[s+2>>1]=0;s=c[h>>2]|0;c[h>>2]=s+4;a[s|0]=64;a[s+1|0]=1;b[s+2>>1]=0;c[j>>2]=1;t=0;i=l;return t|0}s=p>>>0>q>>>0?q:p;p=1;while(1){if(p>>>0>=q>>>0){break}if((b[m+(p<<1)>>1]|0)==0){p=p+1|0}else{break}}u=s>>>0

>>0?p:s;s=1;v=1;while(1){if(v>>>0>=16){break}w=(s<<1)-(e[m+(v<<1)>>1]|0)|0;if((w|0)<0){t=-1;r=1612;break}else{s=w;v=v+1|0}}if((r|0)==1612){i=l;return t|0}do{if((s|0)>0){if((d|0)!=0&(q|0)==1){break}else{t=-1}i=l;return t|0}}while(0);b[n+2>>1]=0;s=b[m+2>>1]|0;b[n+4>>1]=s;v=(b[m+4>>1]|0)+s&65535;b[n+6>>1]=v;s=(b[m+6>>1]|0)+v&65535;b[n+8>>1]=s;v=(b[m+8>>1]|0)+s&65535;b[n+10>>1]=v;s=(b[m+10>>1]|0)+v&65535;b[n+12>>1]=s;v=(b[m+12>>1]|0)+s&65535;b[n+14>>1]=v;s=(b[m+14>>1]|0)+v&65535;b[n+16>>1]=s;v=(b[m+16>>1]|0)+s&65535;b[n+18>>1]=v;s=(b[m+18>>1]|0)+v&65535;b[n+20>>1]=s;v=(b[m+20>>1]|0)+s&65535;b[n+22>>1]=v;s=(b[m+22>>1]|0)+v&65535;b[n+24>>1]=s;v=(b[m+24>>1]|0)+s&65535;b[n+26>>1]=v;s=(b[m+26>>1]|0)+v&65535;b[n+28>>1]=s;b[n+30>>1]=(b[m+28>>1]|0)+s&65535;if(!o){o=0;do{s=b[f+(o<<1)>>1]|0;if(s<<16>>16!=0){v=n+((s&65535)<<1)|0;s=b[v>>1]|0;b[v>>1]=s+1&65535;b[k+((s&65535)<<1)>>1]=o&65535}o=o+1|0;}while(o>>>0>>0)}do{if((d|0)==0){x=0;y=1<>>0>851){t=1}else{x=1;y=g;z=256;A=894;B=958;C=0;break}i=l;return t|0}else{g=1<>>0>591){t=1}else{x=0;y=g;z=-1;A=1536;B=1600;C=o;break}i=l;return t|0}}while(0);d=y-1|0;o=u&255;g=c[h>>2]|0;n=-1;s=0;v=y;y=0;w=u;D=0;E=p;L2178:while(1){p=1<>1]|0;L=K&65535;do{if((L|0)<(z|0)){M=0;N=K}else{if((L|0)<=(z|0)){M=96;N=0;break}M=b[A+(L<<1)>>1]&255;N=b[B+(L<<1)>>1]|0}}while(0);L=1<>>(y>>>0);O=p;while(1){P=O-L|0;Q=P+K|0;a[g+(Q<<2)|0]=M;a[g+(Q<<2)+1|0]=J;b[g+(Q<<2)+2>>1]=N;if((O|0)==(L|0)){break}else{O=P}}O=1<>>1}}if((O|0)==0){R=0}else{R=(O-1&F)+O|0}S=G+1|0;L=m+(H<<1)|0;K=(b[L>>1]|0)-1&65535;b[L>>1]=K;if(K<<16>>16==0){if((H|0)==(q|0)){break L2178}T=e[f+(e[k+(S<<1)>>1]<<1)>>1]|0}else{T=H}if(T>>>0<=u>>>0){F=R;G=S;H=T;continue}U=R&d;if((U|0)==(n|0)){F=R;G=S;H=T}else{break}}H=(y|0)==0?u:y;G=g+(p<<2)|0;F=T-H|0;L2201:do{if(T>>>0>>0){K=F;L=1<>1]|0)|0;if((P|0)<1){V=K;break L2201}Q=K+1|0;W=Q+H|0;if(W>>>0>>0){K=Q;L=P<<1;I=W}else{V=Q;break}}}else{V=F}}while(0);F=(1<>>0>851|C&F>>>0>591){t=1;r=1613;break}a[(c[h>>2]|0)+(U<<2)|0]=V&255;a[(c[h>>2]|0)+(U<<2)+1|0]=o;p=c[h>>2]|0;b[p+(U<<2)+2>>1]=(G-p|0)>>>2&65535;g=G;n=U;s=R;v=F;y=H;w=V;D=S;E=T}if((r|0)==1613){i=l;return t|0}L2211:do{if((R|0)!=0){r=q;T=y;E=R;S=J;D=g;while(1){do{if((T|0)==0){X=D;Y=S;Z=0;_=r}else{if((E&d|0)==(n|0)){X=D;Y=S;Z=T;_=r;break}X=c[h>>2]|0;Y=o;Z=0;_=u}}while(0);V=E>>>(Z>>>0);a[X+(V<<2)|0]=64;a[X+(V<<2)+1|0]=Y;b[X+(V<<2)+2>>1]=0;V=1<<_-1;while(1){if((V&E|0)==0){break}else{V=V>>>1}}if((V|0)==0){break L2211}w=(V-1&E)+V|0;if((w|0)==0){break}else{r=_;T=Z;E=w;S=Y;D=X}}}}while(0);c[h>>2]=(c[h>>2]|0)+(v<<2);c[j>>2]=u;t=0;i=l;return t|0}function bw(a){a=a|0;c[a+2840>>2]=a+148;c[a+2848>>2]=1200;c[a+2852>>2]=a+2440;c[a+2860>>2]=1344;c[a+2864>>2]=a+2684;c[a+2872>>2]=1368;b[a+5816>>1]=0;c[a+5820>>2]=0;c[a+5812>>2]=8;br(a);return}function bx(d){d=d|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;f=d+5820|0;g=c[f>>2]|0;h=d+5816|0;i=e[h>>1]|0|2<>1]=j;if((g|0)>13){k=d+20|0;l=c[k>>2]|0;c[k>>2]=l+1;m=d+8|0;a[(c[m>>2]|0)+l|0]=i&255;i=(e[h>>1]|0)>>>8&255;l=c[k>>2]|0;c[k>>2]=l+1;a[(c[m>>2]|0)+l|0]=i;i=c[f>>2]|0;l=2>>>((16-i|0)>>>0)&65535;b[h>>1]=l;n=i-13|0;o=l}else{n=g+3|0;o=j}c[f>>2]=n;if((n|0)>9){j=d+20|0;g=c[j>>2]|0;c[j>>2]=g+1;l=d+8|0;a[(c[l>>2]|0)+g|0]=o&255;g=(e[h>>1]|0)>>>8&255;i=c[j>>2]|0;c[j>>2]=i+1;a[(c[l>>2]|0)+i|0]=g;b[h>>1]=0;p=(c[f>>2]|0)-9|0;q=0}else{p=n+7|0;q=o}c[f>>2]=p;do{if((p|0)==16){o=d+20|0;n=c[o>>2]|0;c[o>>2]=n+1;g=d+8|0;a[(c[g>>2]|0)+n|0]=q&255;n=(e[h>>1]|0)>>>8&255;i=c[o>>2]|0;c[o>>2]=i+1;a[(c[g>>2]|0)+i|0]=n;b[h>>1]=0;c[f>>2]=0;r=0;s=0}else{if((p|0)<=7){r=p;s=q;break}n=d+20|0;i=c[n>>2]|0;c[n>>2]=i+1;a[(c[d+8>>2]|0)+i|0]=q&255;i=(e[h>>1]|0)>>>8;b[h>>1]=i;n=(c[f>>2]|0)-8|0;c[f>>2]=n;r=n;s=i}}while(0);q=d+5812|0;if((11-r+(c[q>>2]|0)|0)>=9){c[q>>2]=7;return}p=s&65535|2<>1]=p&65535;if((r|0)>13){s=d+20|0;i=c[s>>2]|0;c[s>>2]=i+1;n=d+8|0;a[(c[n>>2]|0)+i|0]=p&255;i=(e[h>>1]|0)>>>8&255;g=c[s>>2]|0;c[s>>2]=g+1;a[(c[n>>2]|0)+g|0]=i;i=c[f>>2]|0;g=2>>>((16-i|0)>>>0);b[h>>1]=g&65535;t=i-13|0;u=g&255}else{t=r+3|0;u=p&255}c[f>>2]=t;if((t|0)>9){p=d+20|0;r=c[p>>2]|0;c[p>>2]=r+1;g=d+8|0;a[(c[g>>2]|0)+r|0]=u;r=(e[h>>1]|0)>>>8&255;i=c[p>>2]|0;c[p>>2]=i+1;a[(c[g>>2]|0)+i|0]=r;b[h>>1]=0;v=(c[f>>2]|0)-9|0;w=0}else{v=t+7|0;w=u}c[f>>2]=v;if((v|0)==16){u=d+20|0;t=c[u>>2]|0;c[u>>2]=t+1;r=d+8|0;a[(c[r>>2]|0)+t|0]=w;t=(e[h>>1]|0)>>>8&255;i=c[u>>2]|0;c[u>>2]=i+1;a[(c[r>>2]|0)+i|0]=t;b[h>>1]=0;c[f>>2]=0;c[q>>2]=7;return}if((v|0)<=7){c[q>>2]=7;return}v=d+20|0;t=c[v>>2]|0;c[v>>2]=t+1;a[(c[d+8>>2]|0)+t|0]=w;b[h>>1]=(e[h>>1]|0)>>>8;c[f>>2]=(c[f>>2]|0)-8;c[q>>2]=7;return}function by(f,g,h,i){f=f|0;g=g|0;h=h|0;i=i|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0;if((c[f+132>>2]|0)>0){j=(c[f>>2]|0)+44|0;if((c[j>>2]|0)==2){k=-201342849;l=0;while(1){if((k&1|0)!=0){if((b[f+148+(l<<2)>>1]|0)!=0){m=0;break}}n=l+1|0;if((n|0)<32){k=k>>>1;l=n}else{o=1646;break}}L2268:do{if((o|0)==1646){if((b[f+184>>1]|0)!=0){m=1;break}if((b[f+188>>1]|0)!=0){m=1;break}if((b[f+200>>1]|0)==0){p=32}else{m=1;break}while(1){if((p|0)>=256){m=0;break L2268}if((b[f+148+(p<<2)>>1]|0)==0){p=p+1|0}else{m=1;break}}}}while(0);c[j>>2]=m}bz(f,f+2840|0);bz(f,f+2852|0);bC(f,f+148|0,c[f+2844>>2]|0);bC(f,f+2440|0,c[f+2856>>2]|0);bz(f,f+2864|0);m=18;while(1){if((m|0)<=2){break}if((b[f+2684+(d[12512+m|0]<<2)+2>>1]|0)==0){m=m-1|0}else{break}}j=f+5800|0;p=(m*3|0)+17+(c[j>>2]|0)|0;c[j>>2]=p;j=(p+10|0)>>>3;p=((c[f+5804>>2]|0)+10|0)>>>3;q=p>>>0>j>>>0?j:p;r=p;s=m}else{m=h+5|0;q=m;r=m;s=0}do{if((h+4|0)>>>0>q>>>0|(g|0)==0){m=f+5820|0;p=c[m>>2]|0;j=(p|0)>13;if((c[f+136>>2]|0)==4|(r|0)==(q|0)){o=i+2&65535;l=f+5816|0;k=e[l>>1]|o<>1]=k&65535;if(j){n=f+20|0;t=c[n>>2]|0;c[n>>2]=t+1;u=f+8|0;a[(c[u>>2]|0)+t|0]=k&255;k=(e[l>>1]|0)>>>8&255;t=c[n>>2]|0;c[n>>2]=t+1;a[(c[u>>2]|0)+t|0]=k;k=c[m>>2]|0;b[l>>1]=o>>>((16-k|0)>>>0)&65535;v=k-13|0}else{v=p+3|0}c[m>>2]=v;bA(f,48,1224);break}k=i+4&65535;o=f+5816|0;l=e[o>>1]|k<>1]=t;if(j){j=f+20|0;u=c[j>>2]|0;c[j>>2]=u+1;n=f+8|0;a[(c[n>>2]|0)+u|0]=l&255;l=(e[o>>1]|0)>>>8&255;u=c[j>>2]|0;c[j>>2]=u+1;a[(c[n>>2]|0)+u|0]=l;l=c[m>>2]|0;u=k>>>((16-l|0)>>>0)&65535;b[o>>1]=u;w=l-13|0;x=u}else{w=p+3|0;x=t}c[m>>2]=w;t=c[f+2844>>2]|0;p=c[f+2856>>2]|0;u=s+1|0;l=t+65280&65535;k=x&65535|l<>1]=n;if((w|0)>11){j=f+20|0;y=c[j>>2]|0;c[j>>2]=y+1;z=f+8|0;a[(c[z>>2]|0)+y|0]=k&255;k=(e[o>>1]|0)>>>8&255;y=c[j>>2]|0;c[j>>2]=y+1;a[(c[z>>2]|0)+y|0]=k;k=c[m>>2]|0;y=l>>>((16-k|0)>>>0)&65535;b[o>>1]=y;A=k-11|0;B=y}else{A=w+5|0;B=n}c[m>>2]=A;n=p&65535;y=n<>1]=k;if((A|0)>11){l=f+20|0;z=c[l>>2]|0;c[l>>2]=z+1;j=f+8|0;a[(c[j>>2]|0)+z|0]=y&255;y=(e[o>>1]|0)>>>8&255;z=c[l>>2]|0;c[l>>2]=z+1;a[(c[j>>2]|0)+z|0]=y;y=c[m>>2]|0;z=n>>>((16-y|0)>>>0)&65535;b[o>>1]=z;C=y-11|0;D=z}else{C=A+5|0;D=k}c[m>>2]=C;k=s+65533&65535;z=k<>1]=y;if((C|0)>12){n=f+20|0;j=c[n>>2]|0;c[n>>2]=j+1;l=f+8|0;a[(c[l>>2]|0)+j|0]=z&255;z=(e[o>>1]|0)>>>8&255;j=c[n>>2]|0;c[n>>2]=j+1;a[(c[l>>2]|0)+j|0]=z;z=c[m>>2]|0;j=k>>>((16-z|0)>>>0)&65535;b[o>>1]=j;E=z-12|0;F=j}else{E=C+4|0;F=y}c[m>>2]=E;if((u|0)>0){y=f+20|0;j=f+8|0;z=0;k=E;l=F;while(1){n=e[f+2684+(d[12512+z|0]<<2)+2>>1]|0;G=n<>1]=H;if((k|0)>13){I=c[y>>2]|0;c[y>>2]=I+1;a[(c[j>>2]|0)+I|0]=G&255;G=(e[o>>1]|0)>>>8&255;I=c[y>>2]|0;c[y>>2]=I+1;a[(c[j>>2]|0)+I|0]=G;G=c[m>>2]|0;I=n>>>((16-G|0)>>>0)&65535;b[o>>1]=I;J=G-13|0;K=I}else{J=k+3|0;K=H}c[m>>2]=J;H=z+1|0;if((H|0)<(u|0)){z=H;k=J;l=K}else{break}}}l=f+148|0;bB(f,l,t);k=f+2440|0;bB(f,k,p);bA(f,l,k)}else{bs(f,g,h,i)}}while(0);br(f);if((i|0)==0){return}i=f+5820|0;h=c[i>>2]|0;do{if((h|0)>8){g=f+5816|0;K=b[g>>1]&255;J=f+20|0;F=c[J>>2]|0;c[J>>2]=F+1;E=f+8|0;a[(c[E>>2]|0)+F|0]=K;K=(e[g>>1]|0)>>>8&255;F=c[J>>2]|0;c[J>>2]=F+1;a[(c[E>>2]|0)+F|0]=K;L=g}else{g=f+5816|0;if((h|0)<=0){L=g;break}K=b[g>>1]&255;F=f+20|0;E=c[F>>2]|0;c[F>>2]=E+1;a[(c[f+8>>2]|0)+E|0]=K;L=g}}while(0);b[L>>1]=0;c[i>>2]=0;return}function bz(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,_=0;h=i;i=i+32|0;j=h|0;k=g|0;l=c[k>>2]|0;m=g+8|0;n=c[m>>2]|0;o=c[n>>2]|0;p=c[n+12>>2]|0;n=f+5200|0;c[n>>2]=0;q=f+5204|0;c[q>>2]=573;if((p|0)>0){r=0;s=-1;while(1){if((b[l+(r<<2)>>1]|0)==0){b[l+(r<<2)+2>>1]=0;t=s}else{u=(c[n>>2]|0)+1|0;c[n>>2]=u;c[f+2908+(u<<2)>>2]=r;a[f+5208+r|0]=0;t=r}u=r+1|0;if((u|0)<(p|0)){r=u;s=t}else{break}}s=c[n>>2]|0;if((s|0)<2){v=s;w=t;x=1694}else{y=t}}else{v=0;w=-1;x=1694}if((x|0)==1694){x=f+5800|0;t=f+5804|0;if((o|0)==0){s=w;r=v;while(1){u=(s|0)<2;z=s+1|0;A=u?z:s;B=u?z:0;z=r+1|0;c[n>>2]=z;c[f+2908+(z<<2)>>2]=B;b[l+(B<<2)>>1]=1;a[f+5208+B|0]=0;c[x>>2]=(c[x>>2]|0)-1;B=c[n>>2]|0;if((B|0)<2){s=A;r=B}else{y=A;break}}}else{r=w;w=v;while(1){v=(r|0)<2;s=r+1|0;A=v?s:r;B=v?s:0;s=w+1|0;c[n>>2]=s;c[f+2908+(s<<2)>>2]=B;b[l+(B<<2)>>1]=1;a[f+5208+B|0]=0;c[x>>2]=(c[x>>2]|0)-1;c[t>>2]=(c[t>>2]|0)-(e[o+(B<<2)+2>>1]|0);B=c[n>>2]|0;if((B|0)<2){r=A;w=B}else{y=A;break}}}}w=g+4|0;c[w>>2]=y;g=c[n>>2]|0;if((g|0)>1){r=(g|0)/2|0;o=g;while(1){t=c[f+2908+(r<<2)>>2]|0;x=f+5208+t|0;A=r<<1;L2348:do{if((A|0)>(o|0)){C=r}else{B=l+(t<<2)|0;s=r;v=A;z=o;while(1){do{if((v|0)<(z|0)){u=v|1;D=c[f+2908+(u<<2)>>2]|0;E=b[l+(D<<2)>>1]|0;F=c[f+2908+(v<<2)>>2]|0;G=b[l+(F<<2)>>1]|0;if((E&65535)>=(G&65535)){if(E<<16>>16!=G<<16>>16){H=v;break}if((d[f+5208+D|0]|0)>(d[f+5208+F|0]|0)){H=v;break}}H=u}else{H=v}}while(0);u=b[B>>1]|0;F=c[f+2908+(H<<2)>>2]|0;D=b[l+(F<<2)>>1]|0;if((u&65535)<(D&65535)){C=s;break L2348}if(u<<16>>16==D<<16>>16){if((d[x]|0)<=(d[f+5208+F|0]|0)){C=s;break L2348}}c[f+2908+(s<<2)>>2]=F;F=H<<1;D=c[n>>2]|0;if((F|0)>(D|0)){C=H;break}else{s=H;v=F;z=D}}}}while(0);c[f+2908+(C<<2)>>2]=t;x=r-1|0;A=c[n>>2]|0;if((x|0)>0){r=x;o=A}else{I=A;break}}}else{I=g}g=f+2912|0;o=p;p=I;while(1){I=c[g>>2]|0;r=p-1|0;c[n>>2]=r;C=c[f+2908+(p<<2)>>2]|0;c[g>>2]=C;H=f+5208+C|0;L2367:do{if((r|0)<2){J=1}else{A=l+(C<<2)|0;x=1;z=2;v=r;while(1){do{if((z|0)<(v|0)){s=z|1;B=c[f+2908+(s<<2)>>2]|0;D=b[l+(B<<2)>>1]|0;F=c[f+2908+(z<<2)>>2]|0;u=b[l+(F<<2)>>1]|0;if((D&65535)>=(u&65535)){if(D<<16>>16!=u<<16>>16){K=z;break}if((d[f+5208+B|0]|0)>(d[f+5208+F|0]|0)){K=z;break}}K=s}else{K=z}}while(0);s=b[A>>1]|0;F=c[f+2908+(K<<2)>>2]|0;B=b[l+(F<<2)>>1]|0;if((s&65535)<(B&65535)){J=x;break L2367}if(s<<16>>16==B<<16>>16){if((d[H]|0)<=(d[f+5208+F|0]|0)){J=x;break L2367}}c[f+2908+(x<<2)>>2]=F;F=K<<1;B=c[n>>2]|0;if((F|0)>(B|0)){J=K;break}else{x=K;z=F;v=B}}}}while(0);c[f+2908+(J<<2)>>2]=C;H=c[g>>2]|0;r=(c[q>>2]|0)-1|0;c[q>>2]=r;c[f+2908+(r<<2)>>2]=I;r=(c[q>>2]|0)-1|0;c[q>>2]=r;c[f+2908+(r<<2)>>2]=H;r=l+(o<<2)|0;b[r>>1]=(b[l+(H<<2)>>1]|0)+(b[l+(I<<2)>>1]|0)&65535;t=a[f+5208+I|0]|0;v=a[f+5208+H|0]|0;z=f+5208+o|0;a[z]=((t&255)<(v&255)?v:t)+1&255;t=o&65535;b[l+(H<<2)+2>>1]=t;b[l+(I<<2)+2>>1]=t;t=o+1|0;c[g>>2]=o;H=c[n>>2]|0;L2383:do{if((H|0)<2){L=1}else{v=1;x=2;A=H;while(1){do{if((x|0)<(A|0)){B=x|1;F=c[f+2908+(B<<2)>>2]|0;s=b[l+(F<<2)>>1]|0;u=c[f+2908+(x<<2)>>2]|0;D=b[l+(u<<2)>>1]|0;if((s&65535)>=(D&65535)){if(s<<16>>16!=D<<16>>16){M=x;break}if((d[f+5208+F|0]|0)>(d[f+5208+u|0]|0)){M=x;break}}M=B}else{M=x}}while(0);B=b[r>>1]|0;u=c[f+2908+(M<<2)>>2]|0;F=b[l+(u<<2)>>1]|0;if((B&65535)<(F&65535)){L=v;break L2383}if(B<<16>>16==F<<16>>16){if((d[z]|0)<=(d[f+5208+u|0]|0)){L=v;break L2383}}c[f+2908+(v<<2)>>2]=u;u=M<<1;F=c[n>>2]|0;if((u|0)>(F|0)){L=M;break}else{v=M;x=u;A=F}}}}while(0);c[f+2908+(L<<2)>>2]=o;z=c[n>>2]|0;if((z|0)>1){o=t;p=z}else{break}}p=c[g>>2]|0;g=(c[q>>2]|0)-1|0;c[q>>2]=g;c[f+2908+(g<<2)>>2]=p;p=c[k>>2]|0;k=c[w>>2]|0;w=c[m>>2]|0;m=c[w>>2]|0;g=c[w+4>>2]|0;o=c[w+8>>2]|0;n=c[w+16>>2]|0;w=f+2876|0;bI(w|0,0,32);b[p+(c[f+2908+(c[q>>2]<<2)>>2]<<2)+2>>1]=0;L=(c[q>>2]|0)+1|0;L2399:do{if((L|0)<573){q=f+5800|0;M=f+5804|0;if((m|0)==0){J=0;K=L;while(1){z=c[f+2908+(K<<2)>>2]|0;r=p+(z<<2)+2|0;H=(e[p+(e[r>>1]<<2)+2>>1]|0)+1|0;I=(H|0)>(n|0);C=I?n:H;H=(I&1)+J|0;b[r>>1]=C&65535;if((z|0)<=(k|0)){r=f+2876+(C<<1)|0;b[r>>1]=(b[r>>1]|0)+1&65535;if((z|0)<(o|0)){N=0}else{N=c[g+(z-o<<2)>>2]|0}r=Z(e[p+(z<<2)>>1]|0,N+C|0)|0;c[q>>2]=r+(c[q>>2]|0)}r=K+1|0;if((r|0)<573){J=H;K=r}else{O=H;break}}}else{K=0;J=L;while(1){t=c[f+2908+(J<<2)>>2]|0;H=p+(t<<2)+2|0;r=(e[p+(e[H>>1]<<2)+2>>1]|0)+1|0;C=(r|0)>(n|0);z=C?n:r;r=(C&1)+K|0;b[H>>1]=z&65535;if((t|0)<=(k|0)){H=f+2876+(z<<1)|0;b[H>>1]=(b[H>>1]|0)+1&65535;if((t|0)<(o|0)){P=0}else{P=c[g+(t-o<<2)>>2]|0}H=e[p+(t<<2)>>1]|0;C=Z(H,P+z|0)|0;c[q>>2]=C+(c[q>>2]|0);C=Z((e[m+(t<<2)+2>>1]|0)+P|0,H)|0;c[M>>2]=C+(c[M>>2]|0)}C=J+1|0;if((C|0)<573){K=r;J=C}else{O=r;break}}}if((O|0)==0){break}J=f+2876+(n<<1)|0;K=O;do{M=n;while(1){r=M-1|0;Q=f+2876+(r<<1)|0;R=b[Q>>1]|0;if(R<<16>>16==0){M=r}else{break}}b[Q>>1]=R-1&65535;r=f+2876+(M<<1)|0;b[r>>1]=(b[r>>1]|0)+2&65535;S=(b[J>>1]|0)-1&65535;b[J>>1]=S;K=K-2|0;}while((K|0)>0);if((n|0)==0){break}else{T=n;U=573;V=S}while(1){K=T&65535;if(V<<16>>16==0){W=U}else{J=V&65535;r=U;while(1){C=r;do{C=C-1|0;X=c[f+2908+(C<<2)>>2]|0;}while((X|0)>(k|0));H=p+(X<<2)+2|0;t=e[H>>1]|0;if((t|0)!=(T|0)){z=Z(e[p+(X<<2)>>1]|0,T-t|0)|0;c[q>>2]=z+(c[q>>2]|0);b[H>>1]=K}H=J-1|0;if((H|0)==0){W=C;break}else{J=H;r=C}}}r=T-1|0;if((r|0)==0){break L2399}T=r;U=W;V=b[f+2876+(r<<1)>>1]|0}}}while(0);V=b[w>>1]<<1;b[j+2>>1]=V;w=((b[f+2878>>1]|0)+V&65535)<<1;b[j+4>>1]=w;V=(w+(b[f+2880>>1]|0)&65535)<<1;b[j+6>>1]=V;w=(V+(b[f+2882>>1]|0)&65535)<<1;b[j+8>>1]=w;V=(w+(b[f+2884>>1]|0)&65535)<<1;b[j+10>>1]=V;w=(V+(b[f+2886>>1]|0)&65535)<<1;b[j+12>>1]=w;V=(w+(b[f+2888>>1]|0)&65535)<<1;b[j+14>>1]=V;w=(V+(b[f+2890>>1]|0)&65535)<<1;b[j+16>>1]=w;V=(w+(b[f+2892>>1]|0)&65535)<<1;b[j+18>>1]=V;w=(V+(b[f+2894>>1]|0)&65535)<<1;b[j+20>>1]=w;V=(w+(b[f+2896>>1]|0)&65535)<<1;b[j+22>>1]=V;w=(V+(b[f+2898>>1]|0)&65535)<<1;b[j+24>>1]=w;V=(w+(b[f+2900>>1]|0)&65535)<<1;b[j+26>>1]=V;w=(V+(b[f+2902>>1]|0)&65535)<<1;b[j+28>>1]=w;b[j+30>>1]=(w+(b[f+2904>>1]|0)&65535)<<1;if((y|0)<0){i=h;return}else{Y=0}do{f=b[l+(Y<<2)+2>>1]|0;w=f&65535;if(f<<16>>16!=0){f=j+(w<<1)|0;V=b[f>>1]|0;b[f>>1]=V+1&65535;f=0;W=w;w=V&65535;while(1){_=f|w&1;V=W-1|0;if((V|0)>0){f=_<<1;W=V;w=w>>>1}else{break}}b[l+(Y<<2)>>1]=_&65535}Y=Y+1|0;}while((Y|0)<=(y|0));i=h;return}function bA(f,g,h){f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0;i=f+5792|0;if((c[i>>2]|0)==0){j=c[f+5820>>2]|0;k=b[f+5816>>1]|0}else{l=f+5796|0;m=f+5784|0;n=f+5820|0;o=f+5816|0;p=f+20|0;q=f+8|0;r=0;while(1){s=b[(c[l>>2]|0)+(r<<1)>>1]|0;t=s&65535;u=r+1|0;v=d[(c[m>>2]|0)+r|0]|0;do{if(s<<16>>16==0){w=e[g+(v<<2)+2>>1]|0;x=c[n>>2]|0;y=e[g+(v<<2)>>1]|0;z=e[o>>1]|0|y<>1]=A;if((x|0)>(16-w|0)){B=c[p>>2]|0;c[p>>2]=B+1;a[(c[q>>2]|0)+B|0]=z&255;z=(e[o>>1]|0)>>>8&255;B=c[p>>2]|0;c[p>>2]=B+1;a[(c[q>>2]|0)+B|0]=z;z=c[n>>2]|0;B=y>>>((16-z|0)>>>0)&65535;b[o>>1]=B;y=w-16+z|0;c[n>>2]=y;C=y;D=B;break}else{B=x+w|0;c[n>>2]=B;C=B;D=A;break}}else{A=d[13928+v|0]|0;B=(A|256)+1|0;w=e[g+(B<<2)+2>>1]|0;x=c[n>>2]|0;y=e[g+(B<<2)>>1]|0;B=e[o>>1]|0|y<>1]=z;if((x|0)>(16-w|0)){E=c[p>>2]|0;c[p>>2]=E+1;a[(c[q>>2]|0)+E|0]=B&255;B=(e[o>>1]|0)>>>8&255;E=c[p>>2]|0;c[p>>2]=E+1;a[(c[q>>2]|0)+E|0]=B;B=c[n>>2]|0;E=y>>>((16-B|0)>>>0)&65535;b[o>>1]=E;F=w-16+B|0;G=E}else{F=x+w|0;G=z}c[n>>2]=F;z=c[3880+(A<<2)>>2]|0;do{if((A-8|0)>>>0<20){w=v-(c[12536+(A<<2)>>2]|0)&65535;x=w<>1]=E;if((F|0)>(16-z|0)){B=c[p>>2]|0;c[p>>2]=B+1;a[(c[q>>2]|0)+B|0]=x&255;x=(e[o>>1]|0)>>>8&255;B=c[p>>2]|0;c[p>>2]=B+1;a[(c[q>>2]|0)+B|0]=x;x=c[n>>2]|0;B=w>>>((16-x|0)>>>0)&65535;b[o>>1]=B;w=z-16+x|0;c[n>>2]=w;H=w;I=B;break}else{B=F+z|0;c[n>>2]=B;H=B;I=E;break}}else{H=F;I=G}}while(0);z=t-1|0;if(z>>>0<256){J=z}else{J=(z>>>7)+256|0}A=d[14184+J|0]|0;E=e[h+(A<<2)+2>>1]|0;B=e[h+(A<<2)>>1]|0;w=I&65535|B<>1]=x;if((H|0)>(16-E|0)){y=c[p>>2]|0;c[p>>2]=y+1;a[(c[q>>2]|0)+y|0]=w&255;w=(e[o>>1]|0)>>>8&255;y=c[p>>2]|0;c[p>>2]=y+1;a[(c[q>>2]|0)+y|0]=w;w=c[n>>2]|0;y=B>>>((16-w|0)>>>0)&65535;b[o>>1]=y;K=E-16+w|0;L=y}else{K=H+E|0;L=x}c[n>>2]=K;x=c[4e3+(A<<2)>>2]|0;if((A-4|0)>>>0>=26){C=K;D=L;break}E=z-(c[12656+(A<<2)>>2]|0)&65535;A=E<>1]=z;if((K|0)>(16-x|0)){y=c[p>>2]|0;c[p>>2]=y+1;a[(c[q>>2]|0)+y|0]=A&255;A=(e[o>>1]|0)>>>8&255;y=c[p>>2]|0;c[p>>2]=y+1;a[(c[q>>2]|0)+y|0]=A;A=c[n>>2]|0;y=E>>>((16-A|0)>>>0)&65535;b[o>>1]=y;E=x-16+A|0;c[n>>2]=E;C=E;D=y;break}else{y=K+x|0;c[n>>2]=y;C=y;D=z;break}}}while(0);if(u>>>0<(c[i>>2]|0)>>>0){r=u}else{j=C;k=D;break}}}D=g+1026|0;C=e[D>>1]|0;r=f+5820|0;i=e[g+1024>>1]|0;g=f+5816|0;n=k&65535|i<>1]=n&65535;if((j|0)>(16-C|0)){k=f+20|0;K=c[k>>2]|0;c[k>>2]=K+1;o=f+8|0;a[(c[o>>2]|0)+K|0]=n&255;n=(e[g>>1]|0)>>>8&255;K=c[k>>2]|0;c[k>>2]=K+1;a[(c[o>>2]|0)+K|0]=n;n=c[r>>2]|0;b[g>>1]=i>>>((16-n|0)>>>0)&65535;M=C-16+n|0;c[r>>2]=M;N=b[D>>1]|0;O=N&65535;P=f+5812|0;c[P>>2]=O;return}else{M=j+C|0;c[r>>2]=M;N=b[D>>1]|0;O=N&65535;P=f+5812|0;c[P>>2]=O;return}}function bB(d,f,g){d=d|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0;h=b[f+2>>1]|0;i=h<<16>>16==0;j=d+2754|0;k=d+5820|0;l=d+2752|0;m=d+5816|0;n=d+20|0;o=d+8|0;p=d+2758|0;q=d+2756|0;r=d+2750|0;s=d+2748|0;t=0;u=-1;v=h&65535;h=i?138:7;w=i?3:4;L2493:while(1){i=t;x=0;while(1){if((i|0)>(g|0)){break L2493}y=i+1|0;z=b[f+(y<<2)+2>>1]|0;A=z&65535;B=x+1|0;C=(v|0)==(A|0);if((B|0)<(h|0)&C){i=y;x=B}else{break}}do{if((B|0)<(w|0)){i=d+2684+(v<<2)+2|0;D=d+2684+(v<<2)|0;E=B;F=c[k>>2]|0;G=b[m>>1]|0;while(1){H=e[i>>1]|0;I=e[D>>1]|0;J=G&65535|I<>1]=K;if((F|0)>(16-H|0)){L=c[n>>2]|0;c[n>>2]=L+1;a[(c[o>>2]|0)+L|0]=J&255;J=(e[m>>1]|0)>>>8&255;L=c[n>>2]|0;c[n>>2]=L+1;a[(c[o>>2]|0)+L|0]=J;J=c[k>>2]|0;L=I>>>((16-J|0)>>>0)&65535;b[m>>1]=L;M=H-16+J|0;N=L}else{M=F+H|0;N=K}c[k>>2]=M;K=E-1|0;if((K|0)==0){break}else{E=K;F=M;G=N}}}else{if((v|0)!=0){if((v|0)==(u|0)){O=B;P=c[k>>2]|0;Q=b[m>>1]|0}else{G=e[d+2684+(v<<2)+2>>1]|0;F=c[k>>2]|0;E=e[d+2684+(v<<2)>>1]|0;D=e[m>>1]|0|E<>1]=i;if((F|0)>(16-G|0)){K=c[n>>2]|0;c[n>>2]=K+1;a[(c[o>>2]|0)+K|0]=D&255;D=(e[m>>1]|0)>>>8&255;K=c[n>>2]|0;c[n>>2]=K+1;a[(c[o>>2]|0)+K|0]=D;D=c[k>>2]|0;K=E>>>((16-D|0)>>>0)&65535;b[m>>1]=K;R=G-16+D|0;S=K}else{R=F+G|0;S=i}c[k>>2]=R;O=x;P=R;Q=S}i=e[r>>1]|0;G=e[s>>1]|0;F=Q&65535|G<>1]=K;if((P|0)>(16-i|0)){D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=F&255;F=(e[m>>1]|0)>>>8&255;D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=F;F=c[k>>2]|0;D=G>>>((16-F|0)>>>0)&65535;b[m>>1]=D;T=i-16+F|0;U=D}else{T=P+i|0;U=K}c[k>>2]=T;K=O+65533&65535;i=U&65535|K<>1]=i&65535;if((T|0)>14){D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=i&255;i=(e[m>>1]|0)>>>8&255;D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=i;i=c[k>>2]|0;b[m>>1]=K>>>((16-i|0)>>>0)&65535;c[k>>2]=i-14;break}else{c[k>>2]=T+2;break}}if((B|0)<11){i=e[j>>1]|0;K=c[k>>2]|0;D=e[l>>1]|0;F=e[m>>1]|0|D<>1]=G;if((K|0)>(16-i|0)){E=c[n>>2]|0;c[n>>2]=E+1;a[(c[o>>2]|0)+E|0]=F&255;F=(e[m>>1]|0)>>>8&255;E=c[n>>2]|0;c[n>>2]=E+1;a[(c[o>>2]|0)+E|0]=F;F=c[k>>2]|0;E=D>>>((16-F|0)>>>0)&65535;b[m>>1]=E;V=i-16+F|0;W=E}else{V=K+i|0;W=G}c[k>>2]=V;G=x+65534&65535;i=W&65535|G<>1]=i&65535;if((V|0)>13){K=c[n>>2]|0;c[n>>2]=K+1;a[(c[o>>2]|0)+K|0]=i&255;i=(e[m>>1]|0)>>>8&255;K=c[n>>2]|0;c[n>>2]=K+1;a[(c[o>>2]|0)+K|0]=i;i=c[k>>2]|0;b[m>>1]=G>>>((16-i|0)>>>0)&65535;c[k>>2]=i-13;break}else{c[k>>2]=V+3;break}}else{i=e[p>>1]|0;G=c[k>>2]|0;K=e[q>>1]|0;E=e[m>>1]|0|K<>1]=F;if((G|0)>(16-i|0)){D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=E&255;E=(e[m>>1]|0)>>>8&255;D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=E;E=c[k>>2]|0;D=K>>>((16-E|0)>>>0)&65535;b[m>>1]=D;X=i-16+E|0;Y=D}else{X=G+i|0;Y=F}c[k>>2]=X;F=x+65526&65535;i=Y&65535|F<>1]=i&65535;if((X|0)>9){G=c[n>>2]|0;c[n>>2]=G+1;a[(c[o>>2]|0)+G|0]=i&255;i=(e[m>>1]|0)>>>8&255;G=c[n>>2]|0;c[n>>2]=G+1;a[(c[o>>2]|0)+G|0]=i;i=c[k>>2]|0;b[m>>1]=F>>>((16-i|0)>>>0)&65535;c[k>>2]=i-9;break}else{c[k>>2]=X+7;break}}}}while(0);if(z<<16>>16==0){t=y;u=v;v=A;h=138;w=3;continue}t=y;u=v;v=A;h=C?6:7;w=C?3:4}return}function bC(a,c,d){a=a|0;c=c|0;d=d|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;f=b[c+2>>1]|0;g=f<<16>>16==0;b[c+(d+1<<2)+2>>1]=-1;h=a+2752|0;i=a+2756|0;j=a+2748|0;k=g?3:4;l=g?138:7;g=f&65535;f=0;m=-1;L2547:while(1){n=0;o=f;do{if((o|0)>(d|0)){break L2547}o=o+1|0;p=b[c+(o<<2)+2>>1]|0;q=p&65535;n=n+1|0;r=(g|0)==(q|0);}while((n|0)<(l|0)&r);do{if((n|0)<(k|0)){s=a+2684+(g<<2)|0;b[s>>1]=(e[s>>1]|0)+n&65535}else{if((g|0)==0){if((n|0)<11){b[h>>1]=(b[h>>1]|0)+1&65535;break}else{b[i>>1]=(b[i>>1]|0)+1&65535;break}}else{if((g|0)!=(m|0)){s=a+2684+(g<<2)|0;b[s>>1]=(b[s>>1]|0)+1&65535}b[j>>1]=(b[j>>1]|0)+1&65535;break}}}while(0);if(p<<16>>16==0){k=3;l=138;m=g;g=q;f=o;continue}k=r?3:4;l=r?6:7;m=g;g=q;f=o}return}function bD(a,b,c){a=a|0;b=b|0;c=c|0;return bF(Z(c,b)|0)|0}function bE(a,b){a=a|0;b=b|0;bG(b);return}function bF(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ab=0,ac=0,ad=0,ae=0,af=0,ag=0,ah=0,ai=0,aj=0,ak=0,an=0,ao=0,ap=0,aq=0,ar=0,as=0,at=0,au=0,av=0,ax=0,az=0,aA=0,aB=0,aD=0,aE=0,aF=0,aG=0,aH=0,aI=0,aJ=0,aK=0,aL=0;do{if(a>>>0<245){if(a>>>0<11){b=16}else{b=a+11&-8}d=b>>>3;e=c[3682]|0;f=e>>>(d>>>0);if((f&3|0)!=0){g=(f&1^1)+d|0;h=g<<1;i=14768+(h<<2)|0;j=14768+(h+2<<2)|0;h=c[j>>2]|0;k=h+8|0;l=c[k>>2]|0;do{if((i|0)==(l|0)){c[3682]=e&~(1<>>0<(c[3686]|0)>>>0){am();return 0}m=l+12|0;if((c[m>>2]|0)==(h|0)){c[m>>2]=i;c[j>>2]=l;break}else{am();return 0}}}while(0);l=g<<3;c[h+4>>2]=l|3;j=h+(l|4)|0;c[j>>2]=c[j>>2]|1;n=k;return n|0}if(b>>>0<=(c[3684]|0)>>>0){o=b;break}if((f|0)!=0){j=2<>>12&16;i=j>>>(l>>>0);j=i>>>5&8;m=i>>>(j>>>0);i=m>>>2&4;p=m>>>(i>>>0);m=p>>>1&2;q=p>>>(m>>>0);p=q>>>1&1;r=(j|l|i|m|p)+(q>>>(p>>>0))|0;p=r<<1;q=14768+(p<<2)|0;m=14768+(p+2<<2)|0;p=c[m>>2]|0;i=p+8|0;l=c[i>>2]|0;do{if((q|0)==(l|0)){c[3682]=e&~(1<>>0<(c[3686]|0)>>>0){am();return 0}j=l+12|0;if((c[j>>2]|0)==(p|0)){c[j>>2]=q;c[m>>2]=l;break}else{am();return 0}}}while(0);l=r<<3;m=l-b|0;c[p+4>>2]=b|3;q=p;e=q+b|0;c[q+(b|4)>>2]=m|1;c[q+l>>2]=m;l=c[3684]|0;if((l|0)!=0){q=c[3687]|0;d=l>>>3;l=d<<1;f=14768+(l<<2)|0;k=c[3682]|0;h=1<>2]|0;if(g>>>0>=(c[3686]|0)>>>0){s=g;t=d;break}am();return 0}}while(0);c[t>>2]=q;c[s+12>>2]=q;c[q+8>>2]=s;c[q+12>>2]=f}c[3684]=m;c[3687]=e;n=i;return n|0}l=c[3683]|0;if((l|0)==0){o=b;break}h=(l&-l)-1|0;l=h>>>12&16;k=h>>>(l>>>0);h=k>>>5&8;p=k>>>(h>>>0);k=p>>>2&4;r=p>>>(k>>>0);p=r>>>1&2;d=r>>>(p>>>0);r=d>>>1&1;g=c[15032+((h|l|k|p|r)+(d>>>(r>>>0))<<2)>>2]|0;r=g;d=g;p=(c[g+4>>2]&-8)-b|0;while(1){g=c[r+16>>2]|0;if((g|0)==0){k=c[r+20>>2]|0;if((k|0)==0){break}else{u=k}}else{u=g}g=(c[u+4>>2]&-8)-b|0;k=g>>>0

>>0;r=u;d=k?u:d;p=k?g:p}r=d;i=c[3686]|0;if(r>>>0>>0){am();return 0}e=r+b|0;m=e;if(r>>>0>=e>>>0){am();return 0}e=c[d+24>>2]|0;f=c[d+12>>2]|0;do{if((f|0)==(d|0)){q=d+20|0;g=c[q>>2]|0;if((g|0)==0){k=d+16|0;l=c[k>>2]|0;if((l|0)==0){v=0;break}else{w=l;x=k}}else{w=g;x=q}while(1){q=w+20|0;g=c[q>>2]|0;if((g|0)!=0){w=g;x=q;continue}q=w+16|0;g=c[q>>2]|0;if((g|0)==0){break}else{w=g;x=q}}if(x>>>0>>0){am();return 0}else{c[x>>2]=0;v=w;break}}else{q=c[d+8>>2]|0;if(q>>>0>>0){am();return 0}g=q+12|0;if((c[g>>2]|0)!=(d|0)){am();return 0}k=f+8|0;if((c[k>>2]|0)==(d|0)){c[g>>2]=f;c[k>>2]=q;v=f;break}else{am();return 0}}}while(0);L2648:do{if((e|0)!=0){f=d+28|0;i=15032+(c[f>>2]<<2)|0;do{if((d|0)==(c[i>>2]|0)){c[i>>2]=v;if((v|0)!=0){break}c[3683]=c[3683]&~(1<>2]);break L2648}else{if(e>>>0<(c[3686]|0)>>>0){am();return 0}q=e+16|0;if((c[q>>2]|0)==(d|0)){c[q>>2]=v}else{c[e+20>>2]=v}if((v|0)==0){break L2648}}}while(0);if(v>>>0<(c[3686]|0)>>>0){am();return 0}c[v+24>>2]=e;f=c[d+16>>2]|0;do{if((f|0)!=0){if(f>>>0<(c[3686]|0)>>>0){am();return 0}else{c[v+16>>2]=f;c[f+24>>2]=v;break}}}while(0);f=c[d+20>>2]|0;if((f|0)==0){break}if(f>>>0<(c[3686]|0)>>>0){am();return 0}else{c[v+20>>2]=f;c[f+24>>2]=v;break}}}while(0);if(p>>>0<16){e=p+b|0;c[d+4>>2]=e|3;f=r+(e+4)|0;c[f>>2]=c[f>>2]|1}else{c[d+4>>2]=b|3;c[r+(b|4)>>2]=p|1;c[r+(p+b)>>2]=p;f=c[3684]|0;if((f|0)!=0){e=c[3687]|0;i=f>>>3;f=i<<1;q=14768+(f<<2)|0;k=c[3682]|0;g=1<>2]|0;if(l>>>0>=(c[3686]|0)>>>0){y=l;z=i;break}am();return 0}}while(0);c[z>>2]=e;c[y+12>>2]=e;c[e+8>>2]=y;c[e+12>>2]=q}c[3684]=p;c[3687]=m}f=d+8|0;if((f|0)==0){o=b;break}else{n=f}return n|0}else{if(a>>>0>4294967231){o=-1;break}f=a+11|0;g=f&-8;k=c[3683]|0;if((k|0)==0){o=g;break}r=-g|0;i=f>>>8;do{if((i|0)==0){A=0}else{if(g>>>0>16777215){A=31;break}f=(i+1048320|0)>>>16&8;l=i<>>16&4;j=l<>>16&2;B=14-(h|f|l)+(j<>>15)|0;A=g>>>((B+7|0)>>>0)&1|B<<1}}while(0);i=c[15032+(A<<2)>>2]|0;L2696:do{if((i|0)==0){C=0;D=r;E=0}else{if((A|0)==31){F=0}else{F=25-(A>>>1)|0}d=0;m=r;p=i;q=g<>2]&-8;l=B-g|0;if(l>>>0>>0){if((B|0)==(g|0)){C=p;D=l;E=p;break L2696}else{G=p;H=l}}else{G=d;H=m}l=c[p+20>>2]|0;B=c[p+16+(q>>>31<<2)>>2]|0;j=(l|0)==0|(l|0)==(B|0)?e:l;if((B|0)==0){C=G;D=H;E=j;break}else{d=G;m=H;p=B;q=q<<1;e=j}}}}while(0);if((E|0)==0&(C|0)==0){i=2<>>12&16;e=i>>>(r>>>0);i=e>>>5&8;q=e>>>(i>>>0);e=q>>>2&4;p=q>>>(e>>>0);q=p>>>1&2;m=p>>>(q>>>0);p=m>>>1&1;I=c[15032+((i|r|e|q|p)+(m>>>(p>>>0))<<2)>>2]|0}else{I=E}if((I|0)==0){J=D;K=C}else{p=I;m=D;q=C;while(1){e=(c[p+4>>2]&-8)-g|0;r=e>>>0>>0;i=r?e:m;e=r?p:q;r=c[p+16>>2]|0;if((r|0)!=0){p=r;m=i;q=e;continue}r=c[p+20>>2]|0;if((r|0)==0){J=i;K=e;break}else{p=r;m=i;q=e}}}if((K|0)==0){o=g;break}if(J>>>0>=((c[3684]|0)-g|0)>>>0){o=g;break}q=K;m=c[3686]|0;if(q>>>0>>0){am();return 0}p=q+g|0;k=p;if(q>>>0>=p>>>0){am();return 0}e=c[K+24>>2]|0;i=c[K+12>>2]|0;do{if((i|0)==(K|0)){r=K+20|0;d=c[r>>2]|0;if((d|0)==0){j=K+16|0;B=c[j>>2]|0;if((B|0)==0){L=0;break}else{M=B;N=j}}else{M=d;N=r}while(1){r=M+20|0;d=c[r>>2]|0;if((d|0)!=0){M=d;N=r;continue}r=M+16|0;d=c[r>>2]|0;if((d|0)==0){break}else{M=d;N=r}}if(N>>>0>>0){am();return 0}else{c[N>>2]=0;L=M;break}}else{r=c[K+8>>2]|0;if(r>>>0>>0){am();return 0}d=r+12|0;if((c[d>>2]|0)!=(K|0)){am();return 0}j=i+8|0;if((c[j>>2]|0)==(K|0)){c[d>>2]=i;c[j>>2]=r;L=i;break}else{am();return 0}}}while(0);L2746:do{if((e|0)!=0){i=K+28|0;m=15032+(c[i>>2]<<2)|0;do{if((K|0)==(c[m>>2]|0)){c[m>>2]=L;if((L|0)!=0){break}c[3683]=c[3683]&~(1<>2]);break L2746}else{if(e>>>0<(c[3686]|0)>>>0){am();return 0}r=e+16|0;if((c[r>>2]|0)==(K|0)){c[r>>2]=L}else{c[e+20>>2]=L}if((L|0)==0){break L2746}}}while(0);if(L>>>0<(c[3686]|0)>>>0){am();return 0}c[L+24>>2]=e;i=c[K+16>>2]|0;do{if((i|0)!=0){if(i>>>0<(c[3686]|0)>>>0){am();return 0}else{c[L+16>>2]=i;c[i+24>>2]=L;break}}}while(0);i=c[K+20>>2]|0;if((i|0)==0){break}if(i>>>0<(c[3686]|0)>>>0){am();return 0}else{c[L+20>>2]=i;c[i+24>>2]=L;break}}}while(0);do{if(J>>>0<16){e=J+g|0;c[K+4>>2]=e|3;i=q+(e+4)|0;c[i>>2]=c[i>>2]|1}else{c[K+4>>2]=g|3;c[q+(g|4)>>2]=J|1;c[q+(J+g)>>2]=J;i=J>>>3;if(J>>>0<256){e=i<<1;m=14768+(e<<2)|0;r=c[3682]|0;j=1<>2]|0;if(d>>>0>=(c[3686]|0)>>>0){O=d;P=i;break}am();return 0}}while(0);c[P>>2]=k;c[O+12>>2]=k;c[q+(g+8)>>2]=O;c[q+(g+12)>>2]=m;break}e=p;j=J>>>8;do{if((j|0)==0){Q=0}else{if(J>>>0>16777215){Q=31;break}r=(j+1048320|0)>>>16&8;i=j<>>16&4;B=i<>>16&2;l=14-(d|r|i)+(B<>>15)|0;Q=J>>>((l+7|0)>>>0)&1|l<<1}}while(0);j=15032+(Q<<2)|0;c[q+(g+28)>>2]=Q;c[q+(g+20)>>2]=0;c[q+(g+16)>>2]=0;m=c[3683]|0;l=1<>2]=e;c[q+(g+24)>>2]=j;c[q+(g+12)>>2]=e;c[q+(g+8)>>2]=e;break}if((Q|0)==31){R=0}else{R=25-(Q>>>1)|0}l=J<>2]|0;while(1){if((c[m+4>>2]&-8|0)==(J|0)){break}S=m+16+(l>>>31<<2)|0;j=c[S>>2]|0;if((j|0)==0){T=2011;break}else{l=l<<1;m=j}}if((T|0)==2011){if(S>>>0<(c[3686]|0)>>>0){am();return 0}else{c[S>>2]=e;c[q+(g+24)>>2]=m;c[q+(g+12)>>2]=e;c[q+(g+8)>>2]=e;break}}l=m+8|0;j=c[l>>2]|0;i=c[3686]|0;if(m>>>0>>0){am();return 0}if(j>>>0>>0){am();return 0}else{c[j+12>>2]=e;c[l>>2]=e;c[q+(g+8)>>2]=j;c[q+(g+12)>>2]=m;c[q+(g+24)>>2]=0;break}}}while(0);q=K+8|0;if((q|0)==0){o=g;break}else{n=q}return n|0}}while(0);K=c[3684]|0;if(o>>>0<=K>>>0){S=K-o|0;J=c[3687]|0;if(S>>>0>15){R=J;c[3687]=R+o;c[3684]=S;c[R+(o+4)>>2]=S|1;c[R+K>>2]=S;c[J+4>>2]=o|3}else{c[3684]=0;c[3687]=0;c[J+4>>2]=K|3;S=J+(K+4)|0;c[S>>2]=c[S>>2]|1}n=J+8|0;return n|0}J=c[3685]|0;if(o>>>0>>0){S=J-o|0;c[3685]=S;J=c[3688]|0;K=J;c[3688]=K+o;c[K+(o+4)>>2]=S|1;c[J+4>>2]=o|3;n=J+8|0;return n|0}do{if((c[3674]|0)==0){J=al(8)|0;if((J-1&J|0)==0){c[3676]=J;c[3675]=J;c[3677]=-1;c[3678]=2097152;c[3679]=0;c[3793]=0;c[3674]=(aC(0)|0)&-16^1431655768;break}else{am();return 0}}}while(0);J=o+48|0;S=c[3676]|0;K=o+47|0;R=S+K|0;Q=-S|0;S=R&Q;if(S>>>0<=o>>>0){n=0;return n|0}O=c[3792]|0;do{if((O|0)!=0){P=c[3790]|0;L=P+S|0;if(L>>>0<=P>>>0|L>>>0>O>>>0){n=0}else{break}return n|0}}while(0);L2838:do{if((c[3793]&4|0)==0){O=c[3688]|0;L2840:do{if((O|0)==0){T=2041}else{L=O;P=15176;while(1){U=P|0;M=c[U>>2]|0;if(M>>>0<=L>>>0){V=P+4|0;if((M+(c[V>>2]|0)|0)>>>0>L>>>0){break}}M=c[P+8>>2]|0;if((M|0)==0){T=2041;break L2840}else{P=M}}if((P|0)==0){T=2041;break}L=R-(c[3685]|0)&Q;if(L>>>0>=2147483647){W=0;break}m=aw(L|0)|0;e=(m|0)==((c[U>>2]|0)+(c[V>>2]|0)|0);X=e?m:-1;Y=e?L:0;Z=m;_=L;T=2050}}while(0);do{if((T|0)==2041){O=aw(0)|0;if((O|0)==-1){W=0;break}g=O;L=c[3675]|0;m=L-1|0;if((m&g|0)==0){$=S}else{$=S-g+(m+g&-L)|0}L=c[3790]|0;g=L+$|0;if(!($>>>0>o>>>0&$>>>0<2147483647)){W=0;break}m=c[3792]|0;if((m|0)!=0){if(g>>>0<=L>>>0|g>>>0>m>>>0){W=0;break}}m=aw($|0)|0;g=(m|0)==(O|0);X=g?O:-1;Y=g?$:0;Z=m;_=$;T=2050}}while(0);L2860:do{if((T|0)==2050){m=-_|0;if((X|0)!=-1){aa=Y;ab=X;T=2061;break L2838}do{if((Z|0)!=-1&_>>>0<2147483647&_>>>0>>0){g=c[3676]|0;O=K-_+g&-g;if(O>>>0>=2147483647){ac=_;break}if((aw(O|0)|0)==-1){aw(m|0)|0;W=Y;break L2860}else{ac=O+_|0;break}}else{ac=_}}while(0);if((Z|0)==-1){W=Y}else{aa=ac;ab=Z;T=2061;break L2838}}}while(0);c[3793]=c[3793]|4;ad=W;T=2058}else{ad=0;T=2058}}while(0);do{if((T|0)==2058){if(S>>>0>=2147483647){break}W=aw(S|0)|0;Z=aw(0)|0;if(!((Z|0)!=-1&(W|0)!=-1&W>>>0>>0)){break}ac=Z-W|0;Z=ac>>>0>(o+40|0)>>>0;Y=Z?W:-1;if((Y|0)!=-1){aa=Z?ac:ad;ab=Y;T=2061}}}while(0);do{if((T|0)==2061){ad=(c[3790]|0)+aa|0;c[3790]=ad;if(ad>>>0>(c[3791]|0)>>>0){c[3791]=ad}ad=c[3688]|0;L2880:do{if((ad|0)==0){S=c[3686]|0;if((S|0)==0|ab>>>0>>0){c[3686]=ab}c[3794]=ab;c[3795]=aa;c[3797]=0;c[3691]=c[3674];c[3690]=-1;S=0;do{Y=S<<1;ac=14768+(Y<<2)|0;c[14768+(Y+3<<2)>>2]=ac;c[14768+(Y+2<<2)>>2]=ac;S=S+1|0;}while(S>>>0<32);S=ab+8|0;if((S&7|0)==0){ae=0}else{ae=-S&7}S=aa-40-ae|0;c[3688]=ab+ae;c[3685]=S;c[ab+(ae+4)>>2]=S|1;c[ab+(aa-36)>>2]=40;c[3689]=c[3678]}else{S=15176;while(1){af=c[S>>2]|0;ag=S+4|0;ah=c[ag>>2]|0;if((ab|0)==(af+ah|0)){T=2073;break}ac=c[S+8>>2]|0;if((ac|0)==0){break}else{S=ac}}do{if((T|0)==2073){if((c[S+12>>2]&8|0)!=0){break}ac=ad;if(!(ac>>>0>=af>>>0&ac>>>0>>0)){break}c[ag>>2]=ah+aa;ac=c[3688]|0;Y=(c[3685]|0)+aa|0;Z=ac;W=ac+8|0;if((W&7|0)==0){ai=0}else{ai=-W&7}W=Y-ai|0;c[3688]=Z+ai;c[3685]=W;c[Z+(ai+4)>>2]=W|1;c[Z+(Y+4)>>2]=40;c[3689]=c[3678];break L2880}}while(0);if(ab>>>0<(c[3686]|0)>>>0){c[3686]=ab}S=ab+aa|0;Y=15176;while(1){aj=Y|0;if((c[aj>>2]|0)==(S|0)){T=2083;break}Z=c[Y+8>>2]|0;if((Z|0)==0){break}else{Y=Z}}do{if((T|0)==2083){if((c[Y+12>>2]&8|0)!=0){break}c[aj>>2]=ab;S=Y+4|0;c[S>>2]=(c[S>>2]|0)+aa;S=ab+8|0;if((S&7|0)==0){ak=0}else{ak=-S&7}S=ab+(aa+8)|0;if((S&7|0)==0){an=0}else{an=-S&7}S=ab+(an+aa)|0;Z=S;W=ak+o|0;ac=ab+W|0;_=ac;K=S-(ab+ak)-o|0;c[ab+(ak+4)>>2]=o|3;do{if((Z|0)==(c[3688]|0)){J=(c[3685]|0)+K|0;c[3685]=J;c[3688]=_;c[ab+(W+4)>>2]=J|1}else{if((Z|0)==(c[3687]|0)){J=(c[3684]|0)+K|0;c[3684]=J;c[3687]=_;c[ab+(W+4)>>2]=J|1;c[ab+(J+W)>>2]=J;break}J=aa+4|0;X=c[ab+(J+an)>>2]|0;if((X&3|0)==1){$=X&-8;V=X>>>3;L2915:do{if(X>>>0<256){U=c[ab+((an|8)+aa)>>2]|0;Q=c[ab+(aa+12+an)>>2]|0;R=14768+(V<<1<<2)|0;do{if((U|0)!=(R|0)){if(U>>>0<(c[3686]|0)>>>0){am();return 0}if((c[U+12>>2]|0)==(Z|0)){break}am();return 0}}while(0);if((Q|0)==(U|0)){c[3682]=c[3682]&~(1<>>0<(c[3686]|0)>>>0){am();return 0}m=Q+8|0;if((c[m>>2]|0)==(Z|0)){ao=m;break}am();return 0}}while(0);c[U+12>>2]=Q;c[ao>>2]=U}else{R=S;m=c[ab+((an|24)+aa)>>2]|0;P=c[ab+(aa+12+an)>>2]|0;do{if((P|0)==(R|0)){O=an|16;g=ab+(J+O)|0;L=c[g>>2]|0;if((L|0)==0){e=ab+(O+aa)|0;O=c[e>>2]|0;if((O|0)==0){ap=0;break}else{aq=O;ar=e}}else{aq=L;ar=g}while(1){g=aq+20|0;L=c[g>>2]|0;if((L|0)!=0){aq=L;ar=g;continue}g=aq+16|0;L=c[g>>2]|0;if((L|0)==0){break}else{aq=L;ar=g}}if(ar>>>0<(c[3686]|0)>>>0){am();return 0}else{c[ar>>2]=0;ap=aq;break}}else{g=c[ab+((an|8)+aa)>>2]|0;if(g>>>0<(c[3686]|0)>>>0){am();return 0}L=g+12|0;if((c[L>>2]|0)!=(R|0)){am();return 0}e=P+8|0;if((c[e>>2]|0)==(R|0)){c[L>>2]=P;c[e>>2]=g;ap=P;break}else{am();return 0}}}while(0);if((m|0)==0){break}P=ab+(aa+28+an)|0;U=15032+(c[P>>2]<<2)|0;do{if((R|0)==(c[U>>2]|0)){c[U>>2]=ap;if((ap|0)!=0){break}c[3683]=c[3683]&~(1<>2]);break L2915}else{if(m>>>0<(c[3686]|0)>>>0){am();return 0}Q=m+16|0;if((c[Q>>2]|0)==(R|0)){c[Q>>2]=ap}else{c[m+20>>2]=ap}if((ap|0)==0){break L2915}}}while(0);if(ap>>>0<(c[3686]|0)>>>0){am();return 0}c[ap+24>>2]=m;R=an|16;P=c[ab+(R+aa)>>2]|0;do{if((P|0)!=0){if(P>>>0<(c[3686]|0)>>>0){am();return 0}else{c[ap+16>>2]=P;c[P+24>>2]=ap;break}}}while(0);P=c[ab+(J+R)>>2]|0;if((P|0)==0){break}if(P>>>0<(c[3686]|0)>>>0){am();return 0}else{c[ap+20>>2]=P;c[P+24>>2]=ap;break}}}while(0);as=ab+(($|an)+aa)|0;at=$+K|0}else{as=Z;at=K}J=as+4|0;c[J>>2]=c[J>>2]&-2;c[ab+(W+4)>>2]=at|1;c[ab+(at+W)>>2]=at;J=at>>>3;if(at>>>0<256){V=J<<1;X=14768+(V<<2)|0;P=c[3682]|0;m=1<>2]|0;if(U>>>0>=(c[3686]|0)>>>0){au=U;av=J;break}am();return 0}}while(0);c[av>>2]=_;c[au+12>>2]=_;c[ab+(W+8)>>2]=au;c[ab+(W+12)>>2]=X;break}V=ac;m=at>>>8;do{if((m|0)==0){ax=0}else{if(at>>>0>16777215){ax=31;break}P=(m+1048320|0)>>>16&8;$=m<>>16&4;U=$<>>16&2;Q=14-(J|P|$)+(U<<$>>>15)|0;ax=at>>>((Q+7|0)>>>0)&1|Q<<1}}while(0);m=15032+(ax<<2)|0;c[ab+(W+28)>>2]=ax;c[ab+(W+20)>>2]=0;c[ab+(W+16)>>2]=0;X=c[3683]|0;Q=1<>2]=V;c[ab+(W+24)>>2]=m;c[ab+(W+12)>>2]=V;c[ab+(W+8)>>2]=V;break}if((ax|0)==31){az=0}else{az=25-(ax>>>1)|0}Q=at<>2]|0;while(1){if((c[X+4>>2]&-8|0)==(at|0)){break}aA=X+16+(Q>>>31<<2)|0;m=c[aA>>2]|0;if((m|0)==0){T=2156;break}else{Q=Q<<1;X=m}}if((T|0)==2156){if(aA>>>0<(c[3686]|0)>>>0){am();return 0}else{c[aA>>2]=V;c[ab+(W+24)>>2]=X;c[ab+(W+12)>>2]=V;c[ab+(W+8)>>2]=V;break}}Q=X+8|0;m=c[Q>>2]|0;$=c[3686]|0;if(X>>>0<$>>>0){am();return 0}if(m>>>0<$>>>0){am();return 0}else{c[m+12>>2]=V;c[Q>>2]=V;c[ab+(W+8)>>2]=m;c[ab+(W+12)>>2]=X;c[ab+(W+24)>>2]=0;break}}}while(0);n=ab+(ak|8)|0;return n|0}}while(0);Y=ad;W=15176;while(1){aB=c[W>>2]|0;if(aB>>>0<=Y>>>0){aD=c[W+4>>2]|0;aE=aB+aD|0;if(aE>>>0>Y>>>0){break}}W=c[W+8>>2]|0}W=aB+(aD-39)|0;if((W&7|0)==0){aF=0}else{aF=-W&7}W=aB+(aD-47+aF)|0;ac=W>>>0<(ad+16|0)>>>0?Y:W;W=ac+8|0;_=ab+8|0;if((_&7|0)==0){aG=0}else{aG=-_&7}_=aa-40-aG|0;c[3688]=ab+aG;c[3685]=_;c[ab+(aG+4)>>2]=_|1;c[ab+(aa-36)>>2]=40;c[3689]=c[3678];c[ac+4>>2]=27;c[W>>2]=c[3794];c[W+4>>2]=c[15180>>2];c[W+8>>2]=c[15184>>2];c[W+12>>2]=c[15188>>2];c[3794]=ab;c[3795]=aa;c[3797]=0;c[3796]=W;W=ac+28|0;c[W>>2]=7;if((ac+32|0)>>>0>>0){_=W;while(1){W=_+4|0;c[W>>2]=7;if((_+8|0)>>>0>>0){_=W}else{break}}}if((ac|0)==(Y|0)){break}_=ac-ad|0;W=Y+(_+4)|0;c[W>>2]=c[W>>2]&-2;c[ad+4>>2]=_|1;c[Y+_>>2]=_;W=_>>>3;if(_>>>0<256){K=W<<1;Z=14768+(K<<2)|0;S=c[3682]|0;m=1<>2]|0;if(Q>>>0>=(c[3686]|0)>>>0){aH=Q;aI=W;break}am();return 0}}while(0);c[aI>>2]=ad;c[aH+12>>2]=ad;c[ad+8>>2]=aH;c[ad+12>>2]=Z;break}K=ad;m=_>>>8;do{if((m|0)==0){aJ=0}else{if(_>>>0>16777215){aJ=31;break}S=(m+1048320|0)>>>16&8;Y=m<>>16&4;W=Y<>>16&2;Q=14-(ac|S|Y)+(W<>>15)|0;aJ=_>>>((Q+7|0)>>>0)&1|Q<<1}}while(0);m=15032+(aJ<<2)|0;c[ad+28>>2]=aJ;c[ad+20>>2]=0;c[ad+16>>2]=0;Z=c[3683]|0;Q=1<>2]=K;c[ad+24>>2]=m;c[ad+12>>2]=ad;c[ad+8>>2]=ad;break}if((aJ|0)==31){aK=0}else{aK=25-(aJ>>>1)|0}Q=_<>2]|0;while(1){if((c[Z+4>>2]&-8|0)==(_|0)){break}aL=Z+16+(Q>>>31<<2)|0;m=c[aL>>2]|0;if((m|0)==0){T=2191;break}else{Q=Q<<1;Z=m}}if((T|0)==2191){if(aL>>>0<(c[3686]|0)>>>0){am();return 0}else{c[aL>>2]=K;c[ad+24>>2]=Z;c[ad+12>>2]=ad;c[ad+8>>2]=ad;break}}Q=Z+8|0;_=c[Q>>2]|0;m=c[3686]|0;if(Z>>>0>>0){am();return 0}if(_>>>0>>0){am();return 0}else{c[_+12>>2]=K;c[Q>>2]=K;c[ad+8>>2]=_;c[ad+12>>2]=Z;c[ad+24>>2]=0;break}}}while(0);ad=c[3685]|0;if(ad>>>0<=o>>>0){break}_=ad-o|0;c[3685]=_;ad=c[3688]|0;Q=ad;c[3688]=Q+o;c[Q+(o+4)>>2]=_|1;c[ad+4>>2]=o|3;n=ad+8|0;return n|0}}while(0);c[(ay()|0)>>2]=12;n=0;return n|0}function bG(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;if((a|0)==0){return}b=a-8|0;d=b;e=c[3686]|0;if(b>>>0>>0){am()}f=c[a-4>>2]|0;g=f&3;if((g|0)==1){am()}h=f&-8;i=a+(h-8)|0;j=i;L3097:do{if((f&1|0)==0){k=c[b>>2]|0;if((g|0)==0){return}l=-8-k|0;m=a+l|0;n=m;o=k+h|0;if(m>>>0>>0){am()}if((n|0)==(c[3687]|0)){p=a+(h-4)|0;if((c[p>>2]&3|0)!=3){q=n;r=o;break}c[3684]=o;c[p>>2]=c[p>>2]&-2;c[a+(l+4)>>2]=o|1;c[i>>2]=o;return}p=k>>>3;if(k>>>0<256){k=c[a+(l+8)>>2]|0;s=c[a+(l+12)>>2]|0;t=14768+(p<<1<<2)|0;do{if((k|0)!=(t|0)){if(k>>>0>>0){am()}if((c[k+12>>2]|0)==(n|0)){break}am()}}while(0);if((s|0)==(k|0)){c[3682]=c[3682]&~(1<>>0>>0){am()}v=s+8|0;if((c[v>>2]|0)==(n|0)){u=v;break}am()}}while(0);c[k+12>>2]=s;c[u>>2]=k;q=n;r=o;break}t=m;p=c[a+(l+24)>>2]|0;v=c[a+(l+12)>>2]|0;do{if((v|0)==(t|0)){w=a+(l+20)|0;x=c[w>>2]|0;if((x|0)==0){y=a+(l+16)|0;z=c[y>>2]|0;if((z|0)==0){A=0;break}else{B=z;C=y}}else{B=x;C=w}while(1){w=B+20|0;x=c[w>>2]|0;if((x|0)!=0){B=x;C=w;continue}w=B+16|0;x=c[w>>2]|0;if((x|0)==0){break}else{B=x;C=w}}if(C>>>0>>0){am()}else{c[C>>2]=0;A=B;break}}else{w=c[a+(l+8)>>2]|0;if(w>>>0>>0){am()}x=w+12|0;if((c[x>>2]|0)!=(t|0)){am()}y=v+8|0;if((c[y>>2]|0)==(t|0)){c[x>>2]=v;c[y>>2]=w;A=v;break}else{am()}}}while(0);if((p|0)==0){q=n;r=o;break}v=a+(l+28)|0;m=15032+(c[v>>2]<<2)|0;do{if((t|0)==(c[m>>2]|0)){c[m>>2]=A;if((A|0)!=0){break}c[3683]=c[3683]&~(1<>2]);q=n;r=o;break L3097}else{if(p>>>0<(c[3686]|0)>>>0){am()}k=p+16|0;if((c[k>>2]|0)==(t|0)){c[k>>2]=A}else{c[p+20>>2]=A}if((A|0)==0){q=n;r=o;break L3097}}}while(0);if(A>>>0<(c[3686]|0)>>>0){am()}c[A+24>>2]=p;t=c[a+(l+16)>>2]|0;do{if((t|0)!=0){if(t>>>0<(c[3686]|0)>>>0){am()}else{c[A+16>>2]=t;c[t+24>>2]=A;break}}}while(0);t=c[a+(l+20)>>2]|0;if((t|0)==0){q=n;r=o;break}if(t>>>0<(c[3686]|0)>>>0){am()}else{c[A+20>>2]=t;c[t+24>>2]=A;q=n;r=o;break}}else{q=d;r=h}}while(0);d=q;if(d>>>0>=i>>>0){am()}A=a+(h-4)|0;e=c[A>>2]|0;if((e&1|0)==0){am()}do{if((e&2|0)==0){if((j|0)==(c[3688]|0)){B=(c[3685]|0)+r|0;c[3685]=B;c[3688]=q;c[q+4>>2]=B|1;if((q|0)==(c[3687]|0)){c[3687]=0;c[3684]=0}if(B>>>0<=(c[3689]|0)>>>0){return}bH(0)|0;return}if((j|0)==(c[3687]|0)){B=(c[3684]|0)+r|0;c[3684]=B;c[3687]=q;c[q+4>>2]=B|1;c[d+B>>2]=B;return}B=(e&-8)+r|0;C=e>>>3;L3203:do{if(e>>>0<256){u=c[a+h>>2]|0;g=c[a+(h|4)>>2]|0;b=14768+(C<<1<<2)|0;do{if((u|0)!=(b|0)){if(u>>>0<(c[3686]|0)>>>0){am()}if((c[u+12>>2]|0)==(j|0)){break}am()}}while(0);if((g|0)==(u|0)){c[3682]=c[3682]&~(1<>>0<(c[3686]|0)>>>0){am()}f=g+8|0;if((c[f>>2]|0)==(j|0)){D=f;break}am()}}while(0);c[u+12>>2]=g;c[D>>2]=u}else{b=i;f=c[a+(h+16)>>2]|0;t=c[a+(h|4)>>2]|0;do{if((t|0)==(b|0)){p=a+(h+12)|0;v=c[p>>2]|0;if((v|0)==0){m=a+(h+8)|0;k=c[m>>2]|0;if((k|0)==0){E=0;break}else{F=k;G=m}}else{F=v;G=p}while(1){p=F+20|0;v=c[p>>2]|0;if((v|0)!=0){F=v;G=p;continue}p=F+16|0;v=c[p>>2]|0;if((v|0)==0){break}else{F=v;G=p}}if(G>>>0<(c[3686]|0)>>>0){am()}else{c[G>>2]=0;E=F;break}}else{p=c[a+h>>2]|0;if(p>>>0<(c[3686]|0)>>>0){am()}v=p+12|0;if((c[v>>2]|0)!=(b|0)){am()}m=t+8|0;if((c[m>>2]|0)==(b|0)){c[v>>2]=t;c[m>>2]=p;E=t;break}else{am()}}}while(0);if((f|0)==0){break}t=a+(h+20)|0;u=15032+(c[t>>2]<<2)|0;do{if((b|0)==(c[u>>2]|0)){c[u>>2]=E;if((E|0)!=0){break}c[3683]=c[3683]&~(1<>2]);break L3203}else{if(f>>>0<(c[3686]|0)>>>0){am()}g=f+16|0;if((c[g>>2]|0)==(b|0)){c[g>>2]=E}else{c[f+20>>2]=E}if((E|0)==0){break L3203}}}while(0);if(E>>>0<(c[3686]|0)>>>0){am()}c[E+24>>2]=f;b=c[a+(h+8)>>2]|0;do{if((b|0)!=0){if(b>>>0<(c[3686]|0)>>>0){am()}else{c[E+16>>2]=b;c[b+24>>2]=E;break}}}while(0);b=c[a+(h+12)>>2]|0;if((b|0)==0){break}if(b>>>0<(c[3686]|0)>>>0){am()}else{c[E+20>>2]=b;c[b+24>>2]=E;break}}}while(0);c[q+4>>2]=B|1;c[d+B>>2]=B;if((q|0)!=(c[3687]|0)){H=B;break}c[3684]=B;return}else{c[A>>2]=e&-2;c[q+4>>2]=r|1;c[d+r>>2]=r;H=r}}while(0);r=H>>>3;if(H>>>0<256){d=r<<1;e=14768+(d<<2)|0;A=c[3682]|0;E=1<>2]|0;if(h>>>0>=(c[3686]|0)>>>0){I=h;J=r;break}am()}}while(0);c[J>>2]=q;c[I+12>>2]=q;c[q+8>>2]=I;c[q+12>>2]=e;return}e=q;I=H>>>8;do{if((I|0)==0){K=0}else{if(H>>>0>16777215){K=31;break}J=(I+1048320|0)>>>16&8;d=I<>>16&4;A=d<>>16&2;r=14-(E|J|d)+(A<>>15)|0;K=H>>>((r+7|0)>>>0)&1|r<<1}}while(0);I=15032+(K<<2)|0;c[q+28>>2]=K;c[q+20>>2]=0;c[q+16>>2]=0;r=c[3683]|0;d=1<>2]=e;c[q+24>>2]=I;c[q+12>>2]=q;c[q+8>>2]=q}else{if((K|0)==31){L=0}else{L=25-(K>>>1)|0}A=H<>2]|0;while(1){if((c[J+4>>2]&-8|0)==(H|0)){break}M=J+16+(A>>>31<<2)|0;E=c[M>>2]|0;if((E|0)==0){N=2370;break}else{A=A<<1;J=E}}if((N|0)==2370){if(M>>>0<(c[3686]|0)>>>0){am()}else{c[M>>2]=e;c[q+24>>2]=J;c[q+12>>2]=q;c[q+8>>2]=q;break}}A=J+8|0;B=c[A>>2]|0;E=c[3686]|0;if(J>>>0>>0){am()}if(B>>>0>>0){am()}else{c[B+12>>2]=e;c[A>>2]=e;c[q+8>>2]=B;c[q+12>>2]=J;c[q+24>>2]=0;break}}}while(0);q=(c[3690]|0)-1|0;c[3690]=q;if((q|0)==0){O=15184}else{return}while(1){q=c[O>>2]|0;if((q|0)==0){break}else{O=q+8|0}}c[3690]=-1;return}function bH(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;do{if((c[3674]|0)==0){b=al(8)|0;if((b-1&b|0)==0){c[3676]=b;c[3675]=b;c[3677]=-1;c[3678]=2097152;c[3679]=0;c[3793]=0;c[3674]=(aC(0)|0)&-16^1431655768;break}else{am();return 0}}}while(0);if(a>>>0>=4294967232){d=0;return d|0}b=c[3688]|0;if((b|0)==0){d=0;return d|0}e=c[3685]|0;do{if(e>>>0>(a+40|0)>>>0){f=c[3676]|0;g=Z((((-40-a-1+e+f|0)>>>0)/(f>>>0)|0)-1|0,f)|0;h=b;i=15176;while(1){j=c[i>>2]|0;if(j>>>0<=h>>>0){if((j+(c[i+4>>2]|0)|0)>>>0>h>>>0){k=i;break}}j=c[i+8>>2]|0;if((j|0)==0){k=0;break}else{i=j}}if((c[k+12>>2]&8|0)!=0){break}i=aw(0)|0;h=k+4|0;if((i|0)!=((c[k>>2]|0)+(c[h>>2]|0)|0)){break}j=aw(-(g>>>0>2147483646?-2147483648-f|0:g)|0)|0;l=aw(0)|0;if(!((j|0)!=-1&l>>>0>>0)){break}j=i-l|0;if((i|0)==(l|0)){break}c[h>>2]=(c[h>>2]|0)-j;c[3790]=(c[3790]|0)-j;h=c[3688]|0;m=(c[3685]|0)-j|0;j=h;n=h+8|0;if((n&7|0)==0){o=0}else{o=-n&7}n=m-o|0;c[3688]=j+o;c[3685]=n;c[j+(o+4)>>2]=n|1;c[j+(m+4)>>2]=40;c[3689]=c[3678];d=(i|0)!=(l|0)|0;return d|0}}while(0);if((c[3685]|0)>>>0<=(c[3689]|0)>>>0){d=0;return d|0}c[3689]=-1;d=0;return d|0}function bI(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=b+e|0;if((e|0)>=20){d=d&255;e=b&3;g=d|d<<8|d<<16|d<<24;h=f&~3;if(e){e=b+4-e|0;while((b|0)<(e|0)){a[b]=d;b=b+1|0}}while((b|0)<(h|0)){c[b>>2]=g;b=b+4|0}}while((b|0)<(f|0)){a[b]=d;b=b+1|0}}function bJ(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;f=b|0;if((b&3)==(d&3)){while(b&3){if((e|0)==0)return f|0;a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function bK(b){b=b|0;var c=0;c=b;while(a[c]|0){c=c+1|0}return c-b|0}function bL(b,c){b=b|0;c=c|0;var d=0;do{a[b+d|0]=a[c+d|0];d=d+1|0}while(a[c+(d-1)|0]|0);return b|0}function bM(b,c){b=b|0;c=c|0;var d=0,e=0;d=b+(bK(b)|0)|0;do{a[d+e|0]=a[c+e|0];e=e+1|0}while(a[c+(e-1)|0]|0);return b|0}function bN(a,b){a=a|0;b=b|0;return aD[a&3](b|0)|0}function bO(a,b){a=a|0;b=b|0;aE[a&1](b|0)}function bP(a,b,c){a=a|0;b=b|0;c=c|0;aF[a&3](b|0,c|0)}function bQ(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return aG[a&7](b|0,c|0,d|0)|0}function bR(a){a=a|0;aH[a&1]()}function bS(a,b,c){a=a|0;b=b|0;c=c|0;return aI[a&15](b|0,c|0)|0}function bT(a){a=a|0;_(0);return 0}function bU(a){a=a|0;_(1)}function bV(a,b){a=a|0;b=b|0;_(2)}function bW(a,b,c){a=a|0;b=b|0;c=c|0;_(3);return 0}function bX(){_(4)}function bY(a,b){a=a|0;b=b|0;_(5);return 0} +// EMSCRIPTEN_END_FUNCS +var aD=[bT,bT,a9,bT];var aE=[bU,bU];var aF=[bV,bV,bE,bV];var aG=[bW,bW,bi,bW,bd,bW,bD,bW];var aH=[bX,bX];var aI=[bY,bY,a5,bY,ba,bY,a8,bY,a6,bY,bY,bY,bY,bY,bY,bY];return{_gzwrite:bi,_strlen:bK,_strcat:bM,_free:bG,_gzread:bd,_gzopen:ba,_memset:bI,_malloc:bF,_memcpy:bJ,_gzclose:a9,_strcpy:bL,runPostSets:aZ,stackAlloc:aJ,stackSave:aK,stackRestore:aL,setThrew:aM,setTempRet0:aP,setTempRet1:aQ,setTempRet2:aR,setTempRet3:aS,setTempRet4:aT,setTempRet5:aU,setTempRet6:aV,setTempRet7:aW,setTempRet8:aX,setTempRet9:aY,dynCall_ii:bN,dynCall_vi:bO,dynCall_vii:bP,dynCall_iiii:bQ,dynCall_v:bR,dynCall_iii:bS}}) +// EMSCRIPTEN_END_ASM +({ "Math": Math, "Int8Array": Int8Array, "Int16Array": Int16Array, "Int32Array": Int32Array, "Uint8Array": Uint8Array, "Uint16Array": Uint16Array, "Uint32Array": Uint32Array, "Float32Array": Float32Array, "Float64Array": Float64Array }, { "abort": abort, "assert": assert, "asmPrintInt": asmPrintInt, "asmPrintFloat": asmPrintFloat, "min": Math_min, "invoke_ii": invoke_ii, "invoke_vi": invoke_vi, "invoke_vii": invoke_vii, "invoke_iiii": invoke_iiii, "invoke_v": invoke_v, "invoke_iii": invoke_iii, "_llvm_lifetime_end": _llvm_lifetime_end, "_lseek": _lseek, "_sysconf": _sysconf, "_abort": _abort, "_close": _close, "_pread": _pread, "_open": _open, "___setErrNo": ___setErrNo, "_send": _send, "_write": _write, "_read": _read, "_recv": _recv, "_pwrite": _pwrite, "_sbrk": _sbrk, "_strerror_r": _strerror_r, "___errno_location": ___errno_location, "_strerror": _strerror, "_llvm_lifetime_start": _llvm_lifetime_start, "_llvm_bswap_i32": _llvm_bswap_i32, "_time": _time, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "NaN": NaN, "Infinity": Infinity }, buffer); +var _gzwrite = Module["_gzwrite"] = asm["_gzwrite"]; +var _strlen = Module["_strlen"] = asm["_strlen"]; +var _strcat = Module["_strcat"] = asm["_strcat"]; +var _free = Module["_free"] = asm["_free"]; +var _gzread = Module["_gzread"] = asm["_gzread"]; +var _gzopen = Module["_gzopen"] = asm["_gzopen"]; +var _memset = Module["_memset"] = asm["_memset"]; +var _malloc = Module["_malloc"] = asm["_malloc"]; +var _memcpy = Module["_memcpy"] = asm["_memcpy"]; +var _gzclose = Module["_gzclose"] = asm["_gzclose"]; +var _strcpy = Module["_strcpy"] = asm["_strcpy"]; +var runPostSets = Module["runPostSets"] = asm["runPostSets"]; +var dynCall_ii = Module["dynCall_ii"] = asm["dynCall_ii"]; +var dynCall_vi = Module["dynCall_vi"] = asm["dynCall_vi"]; +var dynCall_vii = Module["dynCall_vii"] = asm["dynCall_vii"]; +var dynCall_iiii = Module["dynCall_iiii"] = asm["dynCall_iiii"]; +var dynCall_v = Module["dynCall_v"] = asm["dynCall_v"]; +var dynCall_iii = Module["dynCall_iii"] = asm["dynCall_iii"]; +Runtime.stackAlloc = function(size) { return asm['stackAlloc'](size) }; +Runtime.stackSave = function() { return asm['stackSave']() }; +Runtime.stackRestore = function(top) { asm['stackRestore'](top) }; +// Warning: printing of i64 values may be slightly rounded! No deep i64 math used, so precise i64 code not included +var i64Math = null; +// === Auto-generated postamble setup entry stuff === +Module['callMain'] = function callMain(args) { + assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)'); + assert(!Module['preRun'] || Module['preRun'].length == 0, 'cannot call main when preRun functions remain to be called'); + args = args || []; + ensureInitRuntime(); + var argc = args.length+1; + function pad() { + for (var i = 0; i < 4-1; i++) { + argv.push(0); + } + } + var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL) ]; + pad(); + for (var i = 0; i < argc-1; i = i + 1) { + argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL)); + pad(); + } + argv.push(0); + argv = allocate(argv, 'i32', ALLOC_NORMAL); + var ret; + var initialStackTop = STACKTOP; + try { + ret = Module['_main'](argc, argv, 0); + } + catch(e) { + if (e.name == 'ExitStatus') { + return e.status; + } else if (e == 'SimulateInfiniteLoop') { + Module['noExitRuntime'] = true; + } else { + throw e; + } + } finally { + STACKTOP = initialStackTop; + } + return ret; +} +function run(args) { + args = args || Module['arguments']; + if (runDependencies > 0) { + Module.printErr('run() called, but dependencies remain, so not running'); + return 0; + } + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + var toRun = Module['preRun']; + Module['preRun'] = []; + for (var i = toRun.length-1; i >= 0; i--) { + toRun[i](); + } + if (runDependencies > 0) { + // a preRun added a dependency, run will be called later + return 0; + } + } + function doRun() { + ensureInitRuntime(); + preMain(); + var ret = 0; + calledRun = true; + if (Module['_main'] && shouldRunNow) { + ret = Module['callMain'](args); + if (!Module['noExitRuntime']) { + exitRuntime(); + } + } + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length > 0) { + Module['postRun'].pop()(); + } + } + return ret; + } + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + if (!ABORT) doRun(); + }, 1); + return 0; + } else { + return doRun(); + } +} +Module['run'] = Module.run = run; +// {{PRE_RUN_ADDITIONS}} +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} +// shouldRunNow refers to calling main(), not run(). +var shouldRunNow = true; +if (Module['noInitialRun']) { + shouldRunNow = false; +} +run(); +// {{POST_RUN_ADDITIONS}} + // {{MODULE_ADDITIONS}} +Module['gzcompress'] = function(data) { // TODO: Accept strings + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['output.gz', 'wb']); + var buffer = _malloc(data.length); + HEAPU8.set(data, buffer); + ccall('gzwrite', 'number', ['number', 'number', 'number'], [gzFile, buffer, data.length]); + ccall('gzclose', 'number', ['number'], [gzFile]); + _free(buffer); + var ret = new Uint8Array(FS.root.contents['output.gz'].contents); + FS.deleteFile('output.gz'); + return ret; +}; +Module['gzdecompress'] = function(data) { + var BUFSIZE = 1024*1024; + FS.createDataFile('/', 'input.gz', data, true, true); + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['input.gz', 'rb']); + var buffer = _malloc(BUFSIZE); + var chunks = []; + var total = 0; + var len; + while( (len = ccall('gzread', 'number', ['number', 'number', 'number'], [gzFile, buffer, BUFSIZE])) > 0) { + chunks.push(new Uint8Array(len)); + chunks[chunks.length-1].set(HEAPU8.subarray(buffer, buffer+len)); + total += len; + } + ccall('gzclose', 'number', ['number'], [gzFile]); + FS.deleteFile('input.gz'); + _free(buffer); + var ret = new Uint8Array(total); + var curr = 0; + for (var i = 0; i < chunks.length; i++) { + ret.set(chunks[i], curr); + curr += chunks[i].length; + } + return ret; +}; + + return { + compress: Module['gzcompress'], + decompress: Module['gzdecompress'] + }; +})(); + + +onmessage = function(msg) { + var start = Date.now(); + var data = Zee.decompress(new Uint8Array(msg.data.data)); + postMessage({ + filename: msg.data.filename, + data: data, + callbackID: msg.data.callbackID, + time: Date.now() - start + }); +}; + diff --git a/astroem/zee.js/zee.js b/astroem/zee.js/zee.js new file mode 100644 index 00000000..d467e28d --- /dev/null +++ b/astroem/zee.js/zee.js @@ -0,0 +1,2548 @@ + +// zee.js: zlib compiled to js + +var Zee = (function() { + + +var Module = { + 'noExitRuntime': true +}; +// Note: For maximum-speed code, see "Optimizing Code" on the Emscripten wiki, https://github.com/kripken/emscripten/wiki/Optimizing-Code +// Note: Some Emscripten settings may limit the speed of the generated code. +try { + this['Module'] = Module; + Module.test; +} catch(e) { + this['Module'] = Module = {}; +} +// The environment setup code below is customized to use Module. +// *** Environment setup code *** +var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function'; +var ENVIRONMENT_IS_WEB = typeof window === 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; +if (ENVIRONMENT_IS_NODE) { + // Expose functionality in the same simple way that the shells work + // Note that we pollute the global namespace here, otherwise we break in node + Module['print'] = function(x) { + process['stdout'].write(x + '\n'); + }; + Module['printErr'] = function(x) { + process['stderr'].write(x + '\n'); + }; + var nodeFS = require('fs'); + var nodePath = require('path'); + Module['read'] = function(filename, binary) { + filename = nodePath['normalize'](filename); + var ret = nodeFS['readFileSync'](filename); + // The path is absolute if the normalized version is the same as the resolved. + if (!ret && filename != nodePath['resolve'](filename)) { + filename = path.join(__dirname, '..', 'src', filename); + ret = nodeFS['readFileSync'](filename); + } + if (ret && !binary) ret = ret.toString(); + return ret; + }; + Module['readBinary'] = function(filename) { return Module['read'](filename, true) }; + Module['load'] = function(f) { + globalEval(read(f)); + }; + if (!Module['arguments']) { + Module['arguments'] = process['argv'].slice(2); + } + module.exports = Module; +} +if (ENVIRONMENT_IS_SHELL) { + Module['print'] = print; + if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm + Module['read'] = read; + Module['readBinary'] = function(f) { + return read(f, 'binary'); + }; + if (!Module['arguments']) { + if (typeof scriptArgs != 'undefined') { + Module['arguments'] = scriptArgs; + } else if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + } + this['Module'] = Module; +} +if (ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER) { + if (!Module['print']) { + Module['print'] = function(x) { + console.log(x); + }; + } + if (!Module['printErr']) { + Module['printErr'] = function(x) { + console.log(x); + }; + } + this['Module'] = Module; +} +if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + Module['read'] = function(url) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + }; + if (!Module['arguments']) { + if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + } +} +if (ENVIRONMENT_IS_WORKER) { + // We can do very little here... + var TRY_USE_DUMP = false; + if (!Module['print']) { + Module['print'] = (TRY_USE_DUMP && (typeof(dump) !== "undefined") ? (function(x) { + dump(x); + }) : (function(x) { + // self.postMessage(x); // enable this if you want stdout to be sent as messages + })); + } + Module['load'] = importScripts; +} +if (!ENVIRONMENT_IS_WORKER && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_SHELL) { + // Unreachable because SHELL is dependant on the others + throw 'Unknown runtime environment. Where are we?'; +} +function globalEval(x) { + eval.call(null, x); +} +if (!Module['load'] == 'undefined' && Module['read']) { + Module['load'] = function(f) { + globalEval(Module['read'](f)); + }; +} +if (!Module['print']) { + Module['print'] = function(){}; +} +if (!Module['printErr']) { + Module['printErr'] = Module['print']; +} +if (!Module['arguments']) { + Module['arguments'] = []; +} +// *** Environment setup code *** +// Closure helpers +Module.print = Module['print']; +Module.printErr = Module['printErr']; +// Callbacks +if (!Module['preRun']) Module['preRun'] = []; +if (!Module['postRun']) Module['postRun'] = []; +// === Auto-generated preamble library stuff === +//======================================== +// Runtime code shared with compiler +//======================================== +var Runtime = { + stackSave: function () { + return STACKTOP; + }, + stackRestore: function (stackTop) { + STACKTOP = stackTop; + }, + forceAlign: function (target, quantum) { + quantum = quantum || 4; + if (quantum == 1) return target; + if (isNumber(target) && isNumber(quantum)) { + return Math.ceil(target/quantum)*quantum; + } else if (isNumber(quantum) && isPowerOfTwo(quantum)) { + var logg = log2(quantum); + return '((((' +target + ')+' + (quantum-1) + ')>>' + logg + ')<<' + logg + ')'; + } + return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum; + }, + isNumberType: function (type) { + return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES; + }, + isPointerType: function isPointerType(type) { + return type[type.length-1] == '*'; +}, + isStructType: function isStructType(type) { + if (isPointerType(type)) return false; + if (isArrayType(type)) return true; + if (/?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types + // See comment in isStructPointerType() + return type[0] == '%'; +}, + INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0}, + FLOAT_TYPES: {"float":0,"double":0}, + or64: function (x, y) { + var l = (x | 0) | (y | 0); + var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + and64: function (x, y) { + var l = (x | 0) & (y | 0); + var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + xor64: function (x, y) { + var l = (x | 0) ^ (y | 0); + var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + getNativeTypeSize: function (type, quantumSize) { + if (Runtime.QUANTUM_SIZE == 1) return 1; + var size = { + '%i1': 1, + '%i8': 1, + '%i16': 2, + '%i32': 4, + '%i64': 8, + "%float": 4, + "%double": 8 + }['%'+type]; // add '%' since float and double confuse Closure compiler as keys, and also spidermonkey as a compiler will remove 's from '_i8' etc + if (!size) { + if (type.charAt(type.length-1) == '*') { + size = Runtime.QUANTUM_SIZE; // A pointer + } else if (type[0] == 'i') { + var bits = parseInt(type.substr(1)); + assert(bits % 8 == 0); + size = bits/8; + } + } + return size; + }, + getNativeFieldSize: function (type) { + return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE); + }, + dedup: function dedup(items, ident) { + var seen = {}; + if (ident) { + return items.filter(function(item) { + if (seen[item[ident]]) return false; + seen[item[ident]] = true; + return true; + }); + } else { + return items.filter(function(item) { + if (seen[item]) return false; + seen[item] = true; + return true; + }); + } +}, + set: function set() { + var args = typeof arguments[0] === 'object' ? arguments[0] : arguments; + var ret = {}; + for (var i = 0; i < args.length; i++) { + ret[args[i]] = 0; + } + return ret; +}, + STACK_ALIGN: 8, + getAlignSize: function (type, size, vararg) { + // we align i64s and doubles on 64-bit boundaries, unlike x86 + if (type == 'i64' || type == 'double' || vararg) return 8; + if (!type) return Math.min(size, 8); // align structures internally to 64 bits + return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE); + }, + calculateStructAlignment: function calculateStructAlignment(type) { + type.flatSize = 0; + type.alignSize = 0; + var diffs = []; + var prev = -1; + type.flatIndexes = type.fields.map(function(field) { + var size, alignSize; + if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) { + size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s. + alignSize = Runtime.getAlignSize(field, size); + } else if (Runtime.isStructType(field)) { + size = Types.types[field].flatSize; + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } else if (field[0] == 'b') { + // bN, large number field, like a [N x i8] + size = field.substr(1)|0; + alignSize = 1; + } else { + throw 'Unclear type in struct: ' + field + ', in ' + type.name_ + ' :: ' + dump(Types.types[type.name_]); + } + if (type.packed) alignSize = 1; + type.alignSize = Math.max(type.alignSize, alignSize); + var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory + type.flatSize = curr + size; + if (prev >= 0) { + diffs.push(curr-prev); + } + prev = curr; + return curr; + }); + type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize); + if (diffs.length == 0) { + type.flatFactor = type.flatSize; + } else if (Runtime.dedup(diffs).length == 1) { + type.flatFactor = diffs[0]; + } + type.needsFlattening = (type.flatFactor != 1); + return type.flatIndexes; + }, + generateStructInfo: function (struct, typeName, offset) { + var type, alignment; + if (typeName) { + offset = offset || 0; + type = (typeof Types === 'undefined' ? Runtime.typeInfo : Types.types)[typeName]; + if (!type) return null; + if (type.fields.length != struct.length) { + printErr('Number of named fields must match the type for ' + typeName + ': possibly duplicate struct names. Cannot return structInfo'); + return null; + } + alignment = type.flatIndexes; + } else { + var type = { fields: struct.map(function(item) { return item[0] }) }; + alignment = Runtime.calculateStructAlignment(type); + } + var ret = { + __size__: type.flatSize + }; + if (typeName) { + struct.forEach(function(item, i) { + if (typeof item === 'string') { + ret[item] = alignment[i] + offset; + } else { + // embedded struct + var key; + for (var k in item) key = k; + ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]); + } + }); + } else { + struct.forEach(function(item, i) { + ret[item[1]] = alignment[i]; + }); + } + return ret; + }, + dynCall: function (sig, ptr, args) { + if (args && args.length) { + if (!args.splice) args = Array.prototype.slice.call(args); + args.splice(0, 0, ptr); + return Module['dynCall_' + sig].apply(null, args); + } else { + return Module['dynCall_' + sig].call(null, ptr); + } + }, + functionPointers: [], + addFunction: function (func) { + for (var i = 0; i < Runtime.functionPointers.length; i++) { + if (!Runtime.functionPointers[i]) { + Runtime.functionPointers[i] = func; + return 2 + 2*i; + } + } + throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; + }, + removeFunction: function (index) { + Runtime.functionPointers[(index-2)/2] = null; + }, + warnOnce: function (text) { + if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; + if (!Runtime.warnOnce.shown[text]) { + Runtime.warnOnce.shown[text] = 1; + Module.printErr(text); + } + }, + funcWrappers: {}, + getFuncWrapper: function (func, sig) { + assert(sig); + if (!Runtime.funcWrappers[func]) { + Runtime.funcWrappers[func] = function() { + return Runtime.dynCall(sig, func, arguments); + }; + } + return Runtime.funcWrappers[func]; + }, + UTF8Processor: function () { + var buffer = []; + var needed = 0; + this.processCChar = function (code) { + code = code & 0xff; + if (needed) { + buffer.push(code); + needed--; + } + if (buffer.length == 0) { + if (code < 128) return String.fromCharCode(code); + buffer.push(code); + if (code > 191 && code < 224) { + needed = 1; + } else { + needed = 2; + } + return ''; + } + if (needed > 0) return ''; + var c1 = buffer[0]; + var c2 = buffer[1]; + var c3 = buffer[2]; + var ret; + if (c1 > 191 && c1 < 224) { + ret = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)); + } else { + ret = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + } + buffer.length = 0; + return ret; + } + this.processJSString = function(string) { + string = unescape(encodeURIComponent(string)); + var ret = []; + for (var i = 0; i < string.length; i++) { + ret.push(string.charCodeAt(i)); + } + return ret; + } + }, + stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = ((((STACKTOP)+7)>>3)<<3); return ret; }, + staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = ((((STATICTOP)+7)>>3)<<3); return ret; }, + dynamicAlloc: function (size) { var ret = DYNAMICTOP;DYNAMICTOP = (DYNAMICTOP + size)|0;DYNAMICTOP = ((((DYNAMICTOP)+7)>>3)<<3); if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();; return ret; }, + alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 8))*(quantum ? quantum : 8); return ret; }, + makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+(((low)>>>(0))))+((+(((high)>>>(0))))*(+(4294967296)))) : ((+(((low)>>>(0))))+((+(((high)|(0))))*(+(4294967296))))); return ret; }, + GLOBAL_BASE: 8, + QUANTUM_SIZE: 4, + __dummy__: 0 +} +//======================================== +// Runtime essentials +//======================================== +var __THREW__ = 0; // Used in checking for thrown exceptions. +var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort() +var undef = 0; +// tempInt is used for 32-bit signed values or smaller. tempBigInt is used +// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt +var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD; +var tempI64, tempI64b; +var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9; +function abort(text) { + Module.print(text + ':\n' + (new Error).stack); + ABORT = true; + throw "Assertion: " + text; +} +function assert(condition, text) { + if (!condition) { + abort('Assertion failed: ' + text); + } +} +var globalScope = this; +// C calling interface. A convenient way to call C functions (in C files, or +// defined with extern "C"). +// +// Note: LLVM optimizations can inline and remove functions, after which you will not be +// able to call them. Closure can also do so. To avoid that, add your function to +// the exports using something like +// +// -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]' +// +// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C") +// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and +// 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit). +// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType, +// except that 'array' is not possible (there is no way for us to know the length of the array) +// @param args An array of the arguments to the function, as native JS values (as in returnType) +// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack). +// @return The return value, as a native JS value (as in returnType) +function ccall(ident, returnType, argTypes, args) { + return ccallFunc(getCFunc(ident), returnType, argTypes, args); +} +Module["ccall"] = ccall; +// Returns the C function with a specified identifier (for C++, you need to do manual name mangling) +function getCFunc(ident) { + try { + var func = globalScope['Module']['_' + ident]; // closure exported function + if (!func) func = eval('_' + ident); // explicit lookup + } catch(e) { + } + assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)'); + return func; +} +// Internal function that does a C call using a function, not an identifier +function ccallFunc(func, returnType, argTypes, args) { + var stack = 0; + function toC(value, type) { + if (type == 'string') { + if (value === null || value === undefined || value === 0) return 0; // null string + if (!stack) stack = Runtime.stackSave(); + var ret = Runtime.stackAlloc(value.length+1); + writeStringToMemory(value, ret); + return ret; + } else if (type == 'array') { + if (!stack) stack = Runtime.stackSave(); + var ret = Runtime.stackAlloc(value.length); + writeArrayToMemory(value, ret); + return ret; + } + return value; + } + function fromC(value, type) { + if (type == 'string') { + return Pointer_stringify(value); + } + assert(type != 'array'); + return value; + } + var i = 0; + var cArgs = args ? args.map(function(arg) { + return toC(arg, argTypes[i++]); + }) : []; + var ret = fromC(func.apply(null, cArgs), returnType); + if (stack) Runtime.stackRestore(stack); + return ret; +} +// Returns a native JS wrapper for a C function. This is similar to ccall, but +// returns a function you can call repeatedly in a normal way. For example: +// +// var my_function = cwrap('my_c_function', 'number', ['number', 'number']); +// alert(my_function(5, 22)); +// alert(my_function(99, 12)); +// +function cwrap(ident, returnType, argTypes) { + var func = getCFunc(ident); + return function() { + return ccallFunc(func, returnType, argTypes, Array.prototype.slice.call(arguments)); + } +} +Module["cwrap"] = cwrap; +// Sets a value in memory in a dynamic way at run-time. Uses the +// type data. This is the same as makeSetValue, except that +// makeSetValue is done at compile-time and generates the needed +// code then, whereas this function picks the right code at +// run-time. +// Note that setValue and getValue only do *aligned* writes and reads! +// Note that ccall uses JS types as for defining types, while setValue and +// getValue need LLVM types ('i8', 'i32') - this is a lower-level operation +function setValue(ptr, value, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': HEAP8[(ptr)]=value; break; + case 'i8': HEAP8[(ptr)]=value; break; + case 'i16': HEAP16[((ptr)>>1)]=value; break; + case 'i32': HEAP32[((ptr)>>2)]=value; break; + case 'i64': (tempI64 = [value>>>0,((Math.min((+(Math.floor((value)/(+(4294967296))))), (+(4294967295))))|0)>>>0],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break; + case 'float': HEAPF32[((ptr)>>2)]=value; break; + case 'double': HEAPF64[((ptr)>>3)]=value; break; + default: abort('invalid type for setValue: ' + type); + } +} +Module['setValue'] = setValue; +// Parallel to setValue. +function getValue(ptr, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': return HEAP8[(ptr)]; + case 'i8': return HEAP8[(ptr)]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': return HEAP32[((ptr)>>2)]; + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + default: abort('invalid type for setValue: ' + type); + } + return null; +} +Module['getValue'] = getValue; +var ALLOC_NORMAL = 0; // Tries to use _malloc() +var ALLOC_STACK = 1; // Lives for the duration of the current function call +var ALLOC_STATIC = 2; // Cannot be freed +var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk +var ALLOC_NONE = 4; // Do not allocate +Module['ALLOC_NORMAL'] = ALLOC_NORMAL; +Module['ALLOC_STACK'] = ALLOC_STACK; +Module['ALLOC_STATIC'] = ALLOC_STATIC; +Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC; +Module['ALLOC_NONE'] = ALLOC_NONE; +// allocate(): This is for internal use. You can use it yourself as well, but the interface +// is a little tricky (see docs right below). The reason is that it is optimized +// for multiple syntaxes to save space in generated code. So you should +// normally not use allocate(), and instead allocate memory using _malloc(), +// initialize it with setValue(), and so forth. +// @slab: An array of data, or a number. If a number, then the size of the block to allocate, +// in *bytes* (note that this is sometimes confusing: the next parameter does not +// affect this!) +// @types: Either an array of types, one for each byte (or 0 if no type at that position), +// or a single type which is used for the entire block. This only matters if there +// is initial data - if @slab is a number, then this does not matter at all and is +// ignored. +// @allocator: How to allocate memory, see ALLOC_* +function allocate(slab, types, allocator, ptr) { + var zeroinit, size; + if (typeof slab === 'number') { + zeroinit = true; + size = slab; + } else { + zeroinit = false; + size = slab.length; + } + var singleType = typeof types === 'string' ? types : null; + var ret; + if (allocator == ALLOC_NONE) { + ret = ptr; + } else { + ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); + } + if (zeroinit) { + var ptr = ret, stop; + assert((ret & 3) == 0); + stop = ret + (size & ~3); + for (; ptr < stop; ptr += 4) { + HEAP32[((ptr)>>2)]=0; + } + stop = ret + size; + while (ptr < stop) { + HEAP8[((ptr++)|0)]=0; + } + return ret; + } + if (singleType === 'i8') { + if (slab.subarray || slab.slice) { + HEAPU8.set(slab, ret); + } else { + HEAPU8.set(new Uint8Array(slab), ret); + } + return ret; + } + var i = 0, type, typeSize, previousType; + while (i < size) { + var curr = slab[i]; + if (typeof curr === 'function') { + curr = Runtime.getFunctionIndex(curr); + } + type = singleType || types[i]; + if (type === 0) { + i++; + continue; + } + if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later + setValue(ret+i, curr, type); + // no need to look up size unless type changes, so cache it + if (previousType !== type) { + typeSize = Runtime.getNativeTypeSize(type); + previousType = type; + } + i += typeSize; + } + return ret; +} +Module['allocate'] = allocate; +function Pointer_stringify(ptr, /* optional */ length) { + // Find the length, and check for UTF while doing so + var hasUtf = false; + var t; + var i = 0; + while (1) { + t = HEAPU8[(((ptr)+(i))|0)]; + if (t >= 128) hasUtf = true; + else if (t == 0 && !length) break; + i++; + if (length && i == length) break; + } + if (!length) length = i; + var ret = ''; + if (!hasUtf) { + var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack + var curr; + while (length > 0) { + curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); + ret = ret ? ret + curr : curr; + ptr += MAX_CHUNK; + length -= MAX_CHUNK; + } + return ret; + } + var utf8 = new Runtime.UTF8Processor(); + for (i = 0; i < length; i++) { + t = HEAPU8[(((ptr)+(i))|0)]; + ret += utf8.processCChar(t); + } + return ret; +} +Module['Pointer_stringify'] = Pointer_stringify; +// Memory management +var PAGE_SIZE = 4096; +function alignMemoryPage(x) { + return ((x+4095)>>12)<<12; +} +var HEAP; +var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; +var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area +var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area +var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk +function enlargeMemory() { + abort('Cannot enlarge memory arrays in asm.js. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, or (2) set Module.TOTAL_MEMORY before the program runs.'); +} +var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; +var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216; +var FAST_MEMORY = Module['FAST_MEMORY'] || 2097152; +// Initialize the runtime's memory +// check for full engine support (use string 'subarray' to avoid closure compiler confusion) +assert(!!Int32Array && !!Float64Array && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']), + 'Cannot fallback to non-typed array case: Code is too specialized'); +var buffer = new ArrayBuffer(TOTAL_MEMORY); +HEAP8 = new Int8Array(buffer); +HEAP16 = new Int16Array(buffer); +HEAP32 = new Int32Array(buffer); +HEAPU8 = new Uint8Array(buffer); +HEAPU16 = new Uint16Array(buffer); +HEAPU32 = new Uint32Array(buffer); +HEAPF32 = new Float32Array(buffer); +HEAPF64 = new Float64Array(buffer); +// Endianness check (note: assumes compiler arch was little-endian) +HEAP32[0] = 255; +assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system'); +Module['HEAP'] = HEAP; +Module['HEAP8'] = HEAP8; +Module['HEAP16'] = HEAP16; +Module['HEAP32'] = HEAP32; +Module['HEAPU8'] = HEAPU8; +Module['HEAPU16'] = HEAPU16; +Module['HEAPU32'] = HEAPU32; +Module['HEAPF32'] = HEAPF32; +Module['HEAPF64'] = HEAPF64; +function callRuntimeCallbacks(callbacks) { + while(callbacks.length > 0) { + var callback = callbacks.shift(); + if (typeof callback == 'function') { + callback(); + continue; + } + var func = callback.func; + if (typeof func === 'number') { + if (callback.arg === undefined) { + Runtime.dynCall('v', func); + } else { + Runtime.dynCall('vi', func, [callback.arg]); + } + } else { + func(callback.arg === undefined ? null : callback.arg); + } + } +} +var __ATINIT__ = []; // functions called during startup +var __ATMAIN__ = []; // functions called when main() is to be run +var __ATEXIT__ = []; // functions called during shutdown +var runtimeInitialized = false; +function ensureInitRuntime() { + if (runtimeInitialized) return; + runtimeInitialized = true; + callRuntimeCallbacks(__ATINIT__); +} +function preMain() { + callRuntimeCallbacks(__ATMAIN__); +} +function exitRuntime() { + callRuntimeCallbacks(__ATEXIT__); +} +// Tools +// This processes a JS string into a C-line array of numbers, 0-terminated. +// For LLVM-originating strings, see parser.js:parseLLVMString function +function intArrayFromString(stringy, dontAddNull, length /* optional */) { + var ret = (new Runtime.UTF8Processor()).processJSString(stringy); + if (length) { + ret.length = length; + } + if (!dontAddNull) { + ret.push(0); + } + return ret; +} +Module['intArrayFromString'] = intArrayFromString; +function intArrayToString(array) { + var ret = []; + for (var i = 0; i < array.length; i++) { + var chr = array[i]; + if (chr > 0xFF) { + chr &= 0xFF; + } + ret.push(String.fromCharCode(chr)); + } + return ret.join(''); +} +Module['intArrayToString'] = intArrayToString; +// Write a Javascript array to somewhere in the heap +function writeStringToMemory(string, buffer, dontAddNull) { + var array = intArrayFromString(string, dontAddNull); + var i = 0; + while (i < array.length) { + var chr = array[i]; + HEAP8[(((buffer)+(i))|0)]=chr + i = i + 1; + } +} +Module['writeStringToMemory'] = writeStringToMemory; +function writeArrayToMemory(array, buffer) { + for (var i = 0; i < array.length; i++) { + HEAP8[(((buffer)+(i))|0)]=array[i]; + } +} +Module['writeArrayToMemory'] = writeArrayToMemory; +function unSign(value, bits, ignore, sig) { + if (value >= 0) { + return value; + } + return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts + : Math.pow(2, bits) + value; +} +function reSign(value, bits, ignore, sig) { + if (value <= 0) { + return value; + } + var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 + : Math.pow(2, bits-1); + if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that + // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors + // TODO: In i64 mode 1, resign the two parts separately and safely + value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts + } + return value; +} +if (!Math['imul']) Math['imul'] = function(a, b) { + var ah = a >>> 16; + var al = a & 0xffff; + var bh = b >>> 16; + var bl = b & 0xffff; + return (al*bl + ((ah*bl + al*bh) << 16))|0; +}; +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// PRE_RUN_ADDITIONS (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyTracking = {}; +var calledInit = false, calledRun = false; +var runDependencyWatcher = null; +function addRunDependency(id) { + runDependencies++; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + if (id) { + assert(!runDependencyTracking[id]); + runDependencyTracking[id] = 1; + } else { + Module.printErr('warning: run dependency added without ID'); + } +} +Module['addRunDependency'] = addRunDependency; +function removeRunDependency(id) { + runDependencies--; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + if (id) { + assert(runDependencyTracking[id]); + delete runDependencyTracking[id]; + } else { + Module.printErr('warning: run dependency removed without ID'); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!calledRun && shouldRunNow) run(); + } +} +Module['removeRunDependency'] = removeRunDependency; +Module["preloadedImages"] = {}; // maps url to image data +Module["preloadedAudios"] = {}; // maps url to audio data +function addPreRun(func) { + if (!Module['preRun']) Module['preRun'] = []; + else if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + Module['preRun'].push(func); +} +function loadMemoryInitializer(filename) { + function applyData(data) { + HEAPU8.set(data, STATIC_BASE); + } + // always do this asynchronously, to keep shell and web as similar as possible + addPreRun(function() { + if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) { + applyData(Module['readBinary'](filename)); + } else { + Browser.asyncLoad(filename, function(data) { + applyData(data); + }, function(data) { + throw 'could not load memory initializer ' + filename; + }); + } + }); +} +// === Body === +STATIC_BASE = 8; +STATICTOP = STATIC_BASE + 15192; +/* global initializers */ __ATINIT__.push({ func: function() { runPostSets() } }); +/* memory initializer */ allocate([176,50,0,0,248,52,0,0,128,57,0,0,232,51,0,0,152,51,0,0,80,51,0,0,8,51,0,0,160,50,0,0,72,50,0,0,128,57,0,0,12,0,8,0,140,0,8,0,76,0,8,0,204,0,8,0,44,0,8,0,172,0,8,0,108,0,8,0,236,0,8,0,28,0,8,0,156,0,8,0,92,0,8,0,220,0,8,0,60,0,8,0,188,0,8,0,124,0,8,0,252,0,8,0,2,0,8,0,130,0,8,0,66,0,8,0,194,0,8,0,34,0,8,0,162,0,8,0,98,0,8,0,226,0,8,0,18,0,8,0,146,0,8,0,82,0,8,0,210,0,8,0,50,0,8,0,178,0,8,0,114,0,8,0,242,0,8,0,10,0,8,0,138,0,8,0,74,0,8,0,202,0,8,0,42,0,8,0,170,0,8,0,106,0,8,0,234,0,8,0,26,0,8,0,154,0,8,0,90,0,8,0,218,0,8,0,58,0,8,0,186,0,8,0,122,0,8,0,250,0,8,0,6,0,8,0,134,0,8,0,70,0,8,0,198,0,8,0,38,0,8,0,166,0,8,0,102,0,8,0,230,0,8,0,22,0,8,0,150,0,8,0,86,0,8,0,214,0,8,0,54,0,8,0,182,0,8,0,118,0,8,0,246,0,8,0,14,0,8,0,142,0,8,0,78,0,8,0,206,0,8,0,46,0,8,0,174,0,8,0,110,0,8,0,238,0,8,0,30,0,8,0,158,0,8,0,94,0,8,0,222,0,8,0,62,0,8,0,190,0,8,0,126,0,8,0,254,0,8,0,1,0,8,0,129,0,8,0,65,0,8,0,193,0,8,0,33,0,8,0,161,0,8,0,97,0,8,0,225,0,8,0,17,0,8,0,145,0,8,0,81,0,8,0,209,0,8,0,49,0,8,0,177,0,8,0,113,0,8,0,241,0,8,0,9,0,8,0,137,0,8,0,73,0,8,0,201,0,8,0,41,0,8,0,169,0,8,0,105,0,8,0,233,0,8,0,25,0,8,0,153,0,8,0,89,0,8,0,217,0,8,0,57,0,8,0,185,0,8,0,121,0,8,0,249,0,8,0,5,0,8,0,133,0,8,0,69,0,8,0,197,0,8,0,37,0,8,0,165,0,8,0,101,0,8,0,229,0,8,0,21,0,8,0,149,0,8,0,85,0,8,0,213,0,8,0,53,0,8,0,181,0,8,0,117,0,8,0,245,0,8,0,13,0,8,0,141,0,8,0,77,0,8,0,205,0,8,0,45,0,8,0,173,0,8,0,109,0,8,0,237,0,8,0,29,0,8,0,157,0,8,0,93,0,8,0,221,0,8,0,61,0,8,0,189,0,8,0,125,0,8,0,253,0,8,0,19,0,9,0,19,1,9,0,147,0,9,0,147,1,9,0,83,0,9,0,83,1,9,0,211,0,9,0,211,1,9,0,51,0,9,0,51,1,9,0,179,0,9,0,179,1,9,0,115,0,9,0,115,1,9,0,243,0,9,0,243,1,9,0,11,0,9,0,11,1,9,0,139,0,9,0,139,1,9,0,75,0,9,0,75,1,9,0,203,0,9,0,203,1,9,0,43,0,9,0,43,1,9,0,171,0,9,0,171,1,9,0,107,0,9,0,107,1,9,0,235,0,9,0,235,1,9,0,27,0,9,0,27,1,9,0,155,0,9,0,155,1,9,0,91,0,9,0,91,1,9,0,219,0,9,0,219,1,9,0,59,0,9,0,59,1,9,0,187,0,9,0,187,1,9,0,123,0,9,0,123,1,9,0,251,0,9,0,251,1,9,0,7,0,9,0,7,1,9,0,135,0,9,0,135,1,9,0,71,0,9,0,71,1,9,0,199,0,9,0,199,1,9,0,39,0,9,0,39,1,9,0,167,0,9,0,167,1,9,0,103,0,9,0,103,1,9,0,231,0,9,0,231,1,9,0,23,0,9,0,23,1,9,0,151,0,9,0,151,1,9,0,87,0,9,0,87,1,9,0,215,0,9,0,215,1,9,0,55,0,9,0,55,1,9,0,183,0,9,0,183,1,9,0,119,0,9,0,119,1,9,0,247,0,9,0,247,1,9,0,15,0,9,0,15,1,9,0,143,0,9,0,143,1,9,0,79,0,9,0,79,1,9,0,207,0,9,0,207,1,9,0,47,0,9,0,47,1,9,0,175,0,9,0,175,1,9,0,111,0,9,0,111,1,9,0,239,0,9,0,239,1,9,0,31,0,9,0,31,1,9,0,159,0,9,0,159,1,9,0,95,0,9,0,95,1,9,0,223,0,9,0,223,1,9,0,63,0,9,0,63,1,9,0,191,0,9,0,191,1,9,0,127,0,9,0,127,1,9,0,255,0,9,0,255,1,9,0,0,0,7,0,64,0,7,0,32,0,7,0,96,0,7,0,16,0,7,0,80,0,7,0,48,0,7,0,112,0,7,0,8,0,7,0,72,0,7,0,40,0,7,0,104,0,7,0,24,0,7,0,88,0,7,0,56,0,7,0,120,0,7,0,4,0,7,0,68,0,7,0,36,0,7,0,100,0,7,0,20,0,7,0,84,0,7,0,52,0,7,0,116,0,7,0,3,0,8,0,131,0,8,0,67,0,8,0,195,0,8,0,35,0,8,0,163,0,8,0,99,0,8,0,227,0,8,0,48,0,0,0,40,15,0,0,1,1,0,0,30,1,0,0,15,0,0,0,0,0,0,0,0,0,5,0,16,0,5,0,8,0,5,0,24,0,5,0,4,0,5,0,20,0,5,0,12,0,5,0,28,0,5,0,2,0,5,0,18,0,5,0,10,0,5,0,26,0,5,0,6,0,5,0,22,0,5,0,14,0,5,0,30,0,5,0,1,0,5,0,17,0,5,0,9,0,5,0,25,0,5,0,5,0,5,0,21,0,5,0,13,0,5,0,29,0,5,0,3,0,5,0,19,0,5,0,11,0,5,0,27,0,5,0,7,0,5,0,23,0,5,0,200,4,0,0,160,15,0,0,0,0,0,0,30,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,24,16,0,0,0,0,0,0,19,0,0,0,7,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,4,0,0,0,2,0,0,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,17,0,17,0,17,0,17,0,18,0,18,0,18,0,18,0,19,0,19,0,19,0,19,0,20,0,20,0,20,0,20,0,21,0,21,0,21,0,21,0,16,0,73,0,195,0,0,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,13,0,15,0,17,0,19,0,23,0,27,0,31,0,35,0,43,0,51,0,59,0,67,0,83,0,99,0,115,0,131,0,163,0,195,0,227,0,2,1,0,0,0,0,0,0,16,0,16,0,16,0,16,0,17,0,17,0,18,0,18,0,19,0,19,0,20,0,20,0,21,0,21,0,22,0,22,0,23,0,23,0,24,0,24,0,25,0,25,0,26,0,26,0,27,0,27,0,28,0,28,0,29,0,29,0,64,0,64,0,1,0,2,0,3,0,4,0,5,0,7,0,9,0,13,0,17,0,25,0,33,0,49,0,65,0,97,0,129,0,193,0,1,1,129,1,1,2,1,3,1,4,1,6,1,8,1,12,1,16,1,24,1,32,1,48,1,64,1,96,0,0,0,0,16,0,17,0,18,0,0,0,8,0,7,0,9,0,6,0,10,0,5,0,11,0,4,0,12,0,3,0,13,0,2,0,14,0,1,0,15,0,0,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,192,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,160,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,224,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,144,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,208,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,176,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,240,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,200,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,168,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,232,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,152,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,216,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,184,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,248,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,196,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,164,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,228,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,148,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,212,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,180,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,244,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,204,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,172,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,236,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,156,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,220,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,188,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,252,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,194,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,162,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,226,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,146,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,210,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,178,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,242,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,202,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,170,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,234,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,154,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,218,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,186,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,250,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,198,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,166,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,230,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,150,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,214,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,182,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,246,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,206,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,174,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,238,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,158,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,222,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,190,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,254,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,193,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,161,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,225,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,145,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,209,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,177,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,241,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,201,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,169,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,233,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,153,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,217,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,185,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,249,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,197,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,165,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,229,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,149,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,213,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,181,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,245,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,205,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,173,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,237,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,157,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,221,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,189,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,253,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,195,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,163,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,227,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,147,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,211,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,179,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,243,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,203,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,171,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,235,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,155,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,219,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,187,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,251,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,199,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,167,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,231,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,151,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,215,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,183,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,247,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,207,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,175,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,239,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,159,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,223,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,191,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,255,0,16,5,1,0,23,5,1,1,19,5,17,0,27,5,1,16,17,5,5,0,25,5,1,4,21,5,65,0,29,5,1,64,16,5,3,0,24,5,1,2,20,5,33,0,28,5,1,32,18,5,9,0,26,5,1,8,22,5,129,0,64,5,0,0,16,5,2,0,23,5,129,1,19,5,25,0,27,5,1,24,17,5,7,0,25,5,1,6,21,5,97,0,29,5,1,96,16,5,4,0,24,5,1,3,20,5,49,0,28,5,1,48,18,5,13,0,26,5,1,12,22,5,193,0,64,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,6,0,0,0,6,0,0,0,7,0,0,0,7,0,0,0,8,0,0,0,8,0,0,0,9,0,0,0,9,0,0,0,10,0,0,0,10,0,0,0,11,0,0,0,11,0,0,0,12,0,0,0,12,0,0,0,13,0,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,150,48,7,119,44,97,14,238,186,81,9,153,25,196,109,7,143,244,106,112,53,165,99,233,163,149,100,158,50,136,219,14,164,184,220,121,30,233,213,224,136,217,210,151,43,76,182,9,189,124,177,126,7,45,184,231,145,29,191,144,100,16,183,29,242,32,176,106,72,113,185,243,222,65,190,132,125,212,218,26,235,228,221,109,81,181,212,244,199,133,211,131,86,152,108,19,192,168,107,100,122,249,98,253,236,201,101,138,79,92,1,20,217,108,6,99,99,61,15,250,245,13,8,141,200,32,110,59,94,16,105,76,228,65,96,213,114,113,103,162,209,228,3,60,71,212,4,75,253,133,13,210,107,181,10,165,250,168,181,53,108,152,178,66,214,201,187,219,64,249,188,172,227,108,216,50,117,92,223,69,207,13,214,220,89,61,209,171,172,48,217,38,58,0,222,81,128,81,215,200,22,97,208,191,181,244,180,33,35,196,179,86,153,149,186,207,15,165,189,184,158,184,2,40,8,136,5,95,178,217,12,198,36,233,11,177,135,124,111,47,17,76,104,88,171,29,97,193,61,45,102,182,144,65,220,118,6,113,219,1,188,32,210,152,42,16,213,239,137,133,177,113,31,181,182,6,165,228,191,159,51,212,184,232,162,201,7,120,52,249,0,15,142,168,9,150,24,152,14,225,187,13,106,127,45,61,109,8,151,108,100,145,1,92,99,230,244,81,107,107,98,97,108,28,216,48,101,133,78,0,98,242,237,149,6,108,123,165,1,27,193,244,8,130,87,196,15,245,198,217,176,101,80,233,183,18,234,184,190,139,124,136,185,252,223,29,221,98,73,45,218,21,243,124,211,140,101,76,212,251,88,97,178,77,206,81,181,58,116,0,188,163,226,48,187,212,65,165,223,74,215,149,216,61,109,196,209,164,251,244,214,211,106,233,105,67,252,217,110,52,70,136,103,173,208,184,96,218,115,45,4,68,229,29,3,51,95,76,10,170,201,124,13,221,60,113,5,80,170,65,2,39,16,16,11,190,134,32,12,201,37,181,104,87,179,133,111,32,9,212,102,185,159,228,97,206,14,249,222,94,152,201,217,41,34,152,208,176,180,168,215,199,23,61,179,89,129,13,180,46,59,92,189,183,173,108,186,192,32,131,184,237,182,179,191,154,12,226,182,3,154,210,177,116,57,71,213,234,175,119,210,157,21,38,219,4,131,22,220,115,18,11,99,227,132,59,100,148,62,106,109,13,168,90,106,122,11,207,14,228,157,255,9,147,39,174,0,10,177,158,7,125,68,147,15,240,210,163,8,135,104,242,1,30,254,194,6,105,93,87,98,247,203,103,101,128,113,54,108,25,231,6,107,110,118,27,212,254,224,43,211,137,90,122,218,16,204,74,221,103,111,223,185,249,249,239,190,142,67,190,183,23,213,142,176,96,232,163,214,214,126,147,209,161,196,194,216,56,82,242,223,79,241,103,187,209,103,87,188,166,221,6,181,63,75,54,178,72,218,43,13,216,76,27,10,175,246,74,3,54,96,122,4,65,195,239,96,223,85,223,103,168,239,142,110,49,121,190,105,70,140,179,97,203,26,131,102,188,160,210,111,37,54,226,104,82,149,119,12,204,3,71,11,187,185,22,2,34,47,38,5,85,190,59,186,197,40,11,189,178,146,90,180,43,4,106,179,92,167,255,215,194,49,207,208,181,139,158,217,44,29,174,222,91,176,194,100,155,38,242,99,236,156,163,106,117,10,147,109,2,169,6,9,156,63,54,14,235,133,103,7,114,19,87,0,5,130,74,191,149,20,122,184,226,174,43,177,123,56,27,182,12,155,142,210,146,13,190,213,229,183,239,220,124,33,223,219,11,212,210,211,134,66,226,212,241,248,179,221,104,110,131,218,31,205,22,190,129,91,38,185,246,225,119,176,111,119,71,183,24,230,90,8,136,112,106,15,255,202,59,6,102,92,11,1,17,255,158,101,143,105,174,98,248,211,255,107,97,69,207,108,22,120,226,10,160,238,210,13,215,84,131,4,78,194,179,3,57,97,38,103,167,247,22,96,208,77,71,105,73,219,119,110,62,74,106,209,174,220,90,214,217,102,11,223,64,240,59,216,55,83,174,188,169,197,158,187,222,127,207,178,71,233,255,181,48,28,242,189,189,138,194,186,202,48,147,179,83,166,163,180,36,5,54,208,186,147,6,215,205,41,87,222,84,191,103,217,35,46,122,102,179,184,74,97,196,2,27,104,93,148,43,111,42,55,190,11,180,161,142,12,195,27,223,5,90,141,239,2,45,0,0,0,0,65,49,27,25,130,98,54,50,195,83,45,43,4,197,108,100,69,244,119,125,134,167,90,86,199,150,65,79,8,138,217,200,73,187,194,209,138,232,239,250,203,217,244,227,12,79,181,172,77,126,174,181,142,45,131,158,207,28,152,135,81,18,194,74,16,35,217,83,211,112,244,120,146,65,239,97,85,215,174,46,20,230,181,55,215,181,152,28,150,132,131,5,89,152,27,130,24,169,0,155,219,250,45,176,154,203,54,169,93,93,119,230,28,108,108,255,223,63,65,212,158,14,90,205,162,36,132,149,227,21,159,140,32,70,178,167,97,119,169,190,166,225,232,241,231,208,243,232,36,131,222,195,101,178,197,218,170,174,93,93,235,159,70,68,40,204,107,111,105,253,112,118,174,107,49,57,239,90,42,32,44,9,7,11,109,56,28,18,243,54,70,223,178,7,93,198,113,84,112,237,48,101,107,244,247,243,42,187,182,194,49,162,117,145,28,137,52,160,7,144,251,188,159,23,186,141,132,14,121,222,169,37,56,239,178,60,255,121,243,115,190,72,232,106,125,27,197,65,60,42,222,88,5,79,121,240,68,126,98,233,135,45,79,194,198,28,84,219,1,138,21,148,64,187,14,141,131,232,35,166,194,217,56,191,13,197,160,56,76,244,187,33,143,167,150,10,206,150,141,19,9,0,204,92,72,49,215,69,139,98,250,110,202,83,225,119,84,93,187,186,21,108,160,163,214,63,141,136,151,14,150,145,80,152,215,222,17,169,204,199,210,250,225,236,147,203,250,245,92,215,98,114,29,230,121,107,222,181,84,64,159,132,79,89,88,18,14,22,25,35,21,15,218,112,56,36,155,65,35,61,167,107,253,101,230,90,230,124,37,9,203,87,100,56,208,78,163,174,145,1,226,159,138,24,33,204,167,51,96,253,188,42,175,225,36,173,238,208,63,180,45,131,18,159,108,178,9,134,171,36,72,201,234,21,83,208,41,70,126,251,104,119,101,226,246,121,63,47,183,72,36,54,116,27,9,29,53,42,18,4,242,188,83,75,179,141,72,82,112,222,101,121,49,239,126,96,254,243,230,231,191,194,253,254,124,145,208,213,61,160,203,204,250,54,138,131,187,7,145,154,120,84,188,177,57,101,167,168,75,152,131,59,10,169,152,34,201,250,181,9,136,203,174,16,79,93,239,95,14,108,244,70,205,63,217,109,140,14,194,116,67,18,90,243,2,35,65,234,193,112,108,193,128,65,119,216,71,215,54,151,6,230,45,142,197,181,0,165,132,132,27,188,26,138,65,113,91,187,90,104,152,232,119,67,217,217,108,90,30,79,45,21,95,126,54,12,156,45,27,39,221,28,0,62,18,0,152,185,83,49,131,160,144,98,174,139,209,83,181,146,22,197,244,221,87,244,239,196,148,167,194,239,213,150,217,246,233,188,7,174,168,141,28,183,107,222,49,156,42,239,42,133,237,121,107,202,172,72,112,211,111,27,93,248,46,42,70,225,225,54,222,102,160,7,197,127,99,84,232,84,34,101,243,77,229,243,178,2,164,194,169,27,103,145,132,48,38,160,159,41,184,174,197,228,249,159,222,253,58,204,243,214,123,253,232,207,188,107,169,128,253,90,178,153,62,9,159,178,127,56,132,171,176,36,28,44,241,21,7,53,50,70,42,30,115,119,49,7,180,225,112,72,245,208,107,81,54,131,70,122,119,178,93,99,78,215,250,203,15,230,225,210,204,181,204,249,141,132,215,224,74,18,150,175,11,35,141,182,200,112,160,157,137,65,187,132,70,93,35,3,7,108,56,26,196,63,21,49,133,14,14,40,66,152,79,103,3,169,84,126,192,250,121,85,129,203,98,76,31,197,56,129,94,244,35,152,157,167,14,179,220,150,21,170,27,0,84,229,90,49,79,252,153,98,98,215,216,83,121,206,23,79,225,73,86,126,250,80,149,45,215,123,212,28,204,98,19,138,141,45,82,187,150,52,145,232,187,31,208,217,160,6,236,243,126,94,173,194,101,71,110,145,72,108,47,160,83,117,232,54,18,58,169,7,9,35,106,84,36,8,43,101,63,17,228,121,167,150,165,72,188,143,102,27,145,164,39,42,138,189,224,188,203,242,161,141,208,235,98,222,253,192,35,239,230,217,189,225,188,20,252,208,167,13,63,131,138,38,126,178,145,63,185,36,208,112,248,21,203,105,59,70,230,66,122,119,253,91,181,107,101,220,244,90,126,197,55,9,83,238,118,56,72,247,177,174,9,184,240,159,18,161,51,204,63,138,114,253,36,147,0,0,0,0,55,106,194,1,110,212,132,3,89,190,70,2,220,168,9,7,235,194,203,6,178,124,141,4,133,22,79,5,184,81,19,14,143,59,209,15,214,133,151,13,225,239,85,12,100,249,26,9,83,147,216,8,10,45,158,10,61,71,92,11,112,163,38,28,71,201,228,29,30,119,162,31,41,29,96,30,172,11,47,27,155,97,237,26,194,223,171,24,245,181,105,25,200,242,53,18,255,152,247,19,166,38,177,17,145,76,115,16,20,90,60,21,35,48,254,20,122,142,184,22,77,228,122,23,224,70,77,56,215,44,143,57,142,146,201,59,185,248,11,58,60,238,68,63,11,132,134,62,82,58,192,60,101,80,2,61,88,23,94,54,111,125,156,55,54,195,218,53,1,169,24,52,132,191,87,49,179,213,149,48,234,107,211,50,221,1,17,51,144,229,107,36,167,143,169,37,254,49,239,39,201,91,45,38,76,77,98,35,123,39,160,34,34,153,230,32,21,243,36,33,40,180,120,42,31,222,186,43,70,96,252,41,113,10,62,40,244,28,113,45,195,118,179,44,154,200,245,46,173,162,55,47,192,141,154,112,247,231,88,113,174,89,30,115,153,51,220,114,28,37,147,119,43,79,81,118,114,241,23,116,69,155,213,117,120,220,137,126,79,182,75,127,22,8,13,125,33,98,207,124,164,116,128,121,147,30,66,120,202,160,4,122,253,202,198,123,176,46,188,108,135,68,126,109,222,250,56,111,233,144,250,110,108,134,181,107,91,236,119,106,2,82,49,104,53,56,243,105,8,127,175,98,63,21,109,99,102,171,43,97,81,193,233,96,212,215,166,101,227,189,100,100,186,3,34,102,141,105,224,103,32,203,215,72,23,161,21,73,78,31,83,75,121,117,145,74,252,99,222,79,203,9,28,78,146,183,90,76,165,221,152,77,152,154,196,70,175,240,6,71,246,78,64,69,193,36,130,68,68,50,205,65,115,88,15,64,42,230,73,66,29,140,139,67,80,104,241,84,103,2,51,85,62,188,117,87,9,214,183,86,140,192,248,83,187,170,58,82,226,20,124,80,213,126,190,81,232,57,226,90,223,83,32,91,134,237,102,89,177,135,164,88,52,145,235,93,3,251,41,92,90,69,111,94,109,47,173,95,128,27,53,225,183,113,247,224,238,207,177,226,217,165,115,227,92,179,60,230,107,217,254,231,50,103,184,229,5,13,122,228,56,74,38,239,15,32,228,238,86,158,162,236,97,244,96,237,228,226,47,232,211,136,237,233,138,54,171,235,189,92,105,234,240,184,19,253,199,210,209,252,158,108,151,254,169,6,85,255,44,16,26,250,27,122,216,251,66,196,158,249,117,174,92,248,72,233,0,243,127,131,194,242,38,61,132,240,17,87,70,241,148,65,9,244,163,43,203,245,250,149,141,247,205,255,79,246,96,93,120,217,87,55,186,216,14,137,252,218,57,227,62,219,188,245,113,222,139,159,179,223,210,33,245,221,229,75,55,220,216,12,107,215,239,102,169,214,182,216,239,212,129,178,45,213,4,164,98,208,51,206,160,209,106,112,230,211,93,26,36,210,16,254,94,197,39,148,156,196,126,42,218,198,73,64,24,199,204,86,87,194,251,60,149,195,162,130,211,193,149,232,17,192,168,175,77,203,159,197,143,202,198,123,201,200,241,17,11,201,116,7,68,204,67,109,134,205,26,211,192,207,45,185,2,206,64,150,175,145,119,252,109,144,46,66,43,146,25,40,233,147,156,62,166,150,171,84,100,151,242,234,34,149,197,128,224,148,248,199,188,159,207,173,126,158,150,19,56,156,161,121,250,157,36,111,181,152,19,5,119,153,74,187,49,155,125,209,243,154,48,53,137,141,7,95,75,140,94,225,13,142,105,139,207,143,236,157,128,138,219,247,66,139,130,73,4,137,181,35,198,136,136,100,154,131,191,14,88,130,230,176,30,128,209,218,220,129,84,204,147,132,99,166,81,133,58,24,23,135,13,114,213,134,160,208,226,169,151,186,32,168,206,4,102,170,249,110,164,171,124,120,235,174,75,18,41,175,18,172,111,173,37,198,173,172,24,129,241,167,47,235,51,166,118,85,117,164,65,63,183,165,196,41,248,160,243,67,58,161,170,253,124,163,157,151,190,162,208,115,196,181,231,25,6,180,190,167,64,182,137,205,130,183,12,219,205,178,59,177,15,179,98,15,73,177,85,101,139,176,104,34,215,187,95,72,21,186,6,246,83,184,49,156,145,185,180,138,222,188,131,224,28,189,218,94,90,191,237,52,152,190,0,0,0,0,101,103,188,184,139,200,9,170,238,175,181,18,87,151,98,143,50,240,222,55,220,95,107,37,185,56,215,157,239,40,180,197,138,79,8,125,100,224,189,111,1,135,1,215,184,191,214,74,221,216,106,242,51,119,223,224,86,16,99,88,159,87,25,80,250,48,165,232,20,159,16,250,113,248,172,66,200,192,123,223,173,167,199,103,67,8,114,117,38,111,206,205,112,127,173,149,21,24,17,45,251,183,164,63,158,208,24,135,39,232,207,26,66,143,115,162,172,32,198,176,201,71,122,8,62,175,50,160,91,200,142,24,181,103,59,10,208,0,135,178,105,56,80,47,12,95,236,151,226,240,89,133,135,151,229,61,209,135,134,101,180,224,58,221,90,79,143,207,63,40,51,119,134,16,228,234,227,119,88,82,13,216,237,64,104,191,81,248,161,248,43,240,196,159,151,72,42,48,34,90,79,87,158,226,246,111,73,127,147,8,245,199,125,167,64,213,24,192,252,109,78,208,159,53,43,183,35,141,197,24,150,159,160,127,42,39,25,71,253,186,124,32,65,2,146,143,244,16,247,232,72,168,61,88,20,155,88,63,168,35,182,144,29,49,211,247,161,137,106,207,118,20,15,168,202,172,225,7,127,190,132,96,195,6,210,112,160,94,183,23,28,230,89,184,169,244,60,223,21,76,133,231,194,209,224,128,126,105,14,47,203,123,107,72,119,195,162,15,13,203,199,104,177,115,41,199,4,97,76,160,184,217,245,152,111,68,144,255,211,252,126,80,102,238,27,55,218,86,77,39,185,14,40,64,5,182,198,239,176,164,163,136,12,28,26,176,219,129,127,215,103,57,145,120,210,43,244,31,110,147,3,247,38,59,102,144,154,131,136,63,47,145,237,88,147,41,84,96,68,180,49,7,248,12,223,168,77,30,186,207,241,166,236,223,146,254,137,184,46,70,103,23,155,84,2,112,39,236,187,72,240,113,222,47,76,201,48,128,249,219,85,231,69,99,156,160,63,107,249,199,131,211,23,104,54,193,114,15,138,121,203,55,93,228,174,80,225,92,64,255,84,78,37,152,232,246,115,136,139,174,22,239,55,22,248,64,130,4,157,39,62,188,36,31,233,33,65,120,85,153,175,215,224,139,202,176,92,51,59,182,89,237,94,209,229,85,176,126,80,71,213,25,236,255,108,33,59,98,9,70,135,218,231,233,50,200,130,142,142,112,212,158,237,40,177,249,81,144,95,86,228,130,58,49,88,58,131,9,143,167,230,110,51,31,8,193,134,13,109,166,58,181,164,225,64,189,193,134,252,5,47,41,73,23,74,78,245,175,243,118,34,50,150,17,158,138,120,190,43,152,29,217,151,32,75,201,244,120,46,174,72,192,192,1,253,210,165,102,65,106,28,94,150,247,121,57,42,79,151,150,159,93,242,241,35,229,5,25,107,77,96,126,215,245,142,209,98,231,235,182,222,95,82,142,9,194,55,233,181,122,217,70,0,104,188,33,188,208,234,49,223,136,143,86,99,48,97,249,214,34,4,158,106,154,189,166,189,7,216,193,1,191,54,110,180,173,83,9,8,21,154,78,114,29,255,41,206,165,17,134,123,183,116,225,199,15,205,217,16,146,168,190,172,42,70,17,25,56,35,118,165,128,117,102,198,216,16,1,122,96,254,174,207,114,155,201,115,202,34,241,164,87,71,150,24,239,169,57,173,253,204,94,17,69,6,238,77,118,99,137,241,206,141,38,68,220,232,65,248,100,81,121,47,249,52,30,147,65,218,177,38,83,191,214,154,235,233,198,249,179,140,161,69,11,98,14,240,25,7,105,76,161,190,81,155,60,219,54,39,132,53,153,146,150,80,254,46,46,153,185,84,38,252,222,232,158,18,113,93,140,119,22,225,52,206,46,54,169,171,73,138,17,69,230,63,3,32,129,131,187,118,145,224,227,19,246,92,91,253,89,233,73,152,62,85,241,33,6,130,108,68,97,62,212,170,206,139,198,207,169,55,126,56,65,127,214,93,38,195,110,179,137,118,124,214,238,202,196,111,214,29,89,10,177,161,225,228,30,20,243,129,121,168,75,215,105,203,19,178,14,119,171,92,161,194,185,57,198,126,1,128,254,169,156,229,153,21,36,11,54,160,54,110,81,28,142,167,22,102,134,194,113,218,62,44,222,111,44,73,185,211,148,240,129,4,9,149,230,184,177,123,73,13,163,30,46,177,27,72,62,210,67,45,89,110,251,195,246,219,233,166,145,103,81,31,169,176,204,122,206,12,116,148,97,185,102,241,6,5,222,0,0,0,0,119,7,48,150,238,14,97,44,153,9,81,186,7,109,196,25,112,106,244,143,233,99,165,53,158,100,149,163,14,219,136,50,121,220,184,164,224,213,233,30,151,210,217,136,9,182,76,43,126,177,124,189,231,184,45,7,144,191,29,145,29,183,16,100,106,176,32,242,243,185,113,72,132,190,65,222,26,218,212,125,109,221,228,235,244,212,181,81,131,211,133,199,19,108,152,86,100,107,168,192,253,98,249,122,138,101,201,236,20,1,92,79,99,6,108,217,250,15,61,99,141,8,13,245,59,110,32,200,76,105,16,94,213,96,65,228,162,103,113,114,60,3,228,209,75,4,212,71,210,13,133,253,165,10,181,107,53,181,168,250,66,178,152,108,219,187,201,214,172,188,249,64,50,216,108,227,69,223,92,117,220,214,13,207,171,209,61,89,38,217,48,172,81,222,0,58,200,215,81,128,191,208,97,22,33,180,244,181,86,179,196,35,207,186,149,153,184,189,165,15,40,2,184,158,95,5,136,8,198,12,217,178,177,11,233,36,47,111,124,135,88,104,76,17,193,97,29,171,182,102,45,61,118,220,65,144,1,219,113,6,152,210,32,188,239,213,16,42,113,177,133,137,6,182,181,31,159,191,228,165,232,184,212,51,120,7,201,162,15,0,249,52,150,9,168,142,225,14,152,24,127,106,13,187,8,109,61,45,145,100,108,151,230,99,92,1,107,107,81,244,28,108,97,98,133,101,48,216,242,98,0,78,108,6,149,237,27,1,165,123,130,8,244,193,245,15,196,87,101,176,217,198,18,183,233,80,139,190,184,234,252,185,136,124,98,221,29,223,21,218,45,73,140,211,124,243,251,212,76,101,77,178,97,88,58,181,81,206,163,188,0,116,212,187,48,226,74,223,165,65,61,216,149,215,164,209,196,109,211,214,244,251,67,105,233,106,52,110,217,252,173,103,136,70,218,96,184,208,68,4,45,115,51,3,29,229,170,10,76,95,221,13,124,201,80,5,113,60,39,2,65,170,190,11,16,16,201,12,32,134,87,104,181,37,32,111,133,179,185,102,212,9,206,97,228,159,94,222,249,14,41,217,201,152,176,208,152,34,199,215,168,180,89,179,61,23,46,180,13,129,183,189,92,59,192,186,108,173,237,184,131,32,154,191,179,182,3,182,226,12,116,177,210,154,234,213,71,57,157,210,119,175,4,219,38,21,115,220,22,131,227,99,11,18,148,100,59,132,13,109,106,62,122,106,90,168,228,14,207,11,147,9,255,157,10,0,174,39,125,7,158,177,240,15,147,68,135,8,163,210,30,1,242,104,105,6,194,254,247,98,87,93,128,101,103,203,25,108,54,113,110,107,6,231,254,212,27,118,137,211,43,224,16,218,122,90,103,221,74,204,249,185,223,111,142,190,239,249,23,183,190,67,96,176,142,213,214,214,163,232,161,209,147,126,56,216,194,196,79,223,242,82,209,187,103,241,166,188,87,103,63,181,6,221,72,178,54,75,216,13,43,218,175,10,27,76,54,3,74,246,65,4,122,96,223,96,239,195,168,103,223,85,49,110,142,239,70,105,190,121,203,97,179,140,188,102,131,26,37,111,210,160,82,104,226,54,204,12,119,149,187,11,71,3,34,2,22,185,85,5,38,47,197,186,59,190,178,189,11,40,43,180,90,146,92,179,106,4,194,215,255,167,181,208,207,49,44,217,158,139,91,222,174,29,155,100,194,176,236,99,242,38,117,106,163,156,2,109,147,10,156,9,6,169,235,14,54,63,114,7,103,133,5,0,87,19,149,191,74,130,226,184,122,20,123,177,43,174,12,182,27,56,146,210,142,155,229,213,190,13,124,220,239,183,11,219,223,33,134,211,210,212,241,212,226,66,104,221,179,248,31,218,131,110,129,190,22,205,246,185,38,91,111,176,119,225,24,183,71,119,136,8,90,230,255,15,106,112,102,6,59,202,17,1,11,92,143,101,158,255,248,98,174,105,97,107,255,211,22,108,207,69,160,10,226,120,215,13,210,238,78,4,131,84,57,3,179,194,167,103,38,97,208,96,22,247,73,105,71,77,62,110,119,219,174,209,106,74,217,214,90,220,64,223,11,102,55,216,59,240,169,188,174,83,222,187,158,197,71,178,207,127,48,181,255,233,189,189,242,28,202,186,194,138,83,179,147,48,36,180,163,166,186,208,54,5,205,215,6,147,84,222,87,41,35,217,103,191,179,102,122,46,196,97,74,184,93,104,27,2,42,111,43,148,180,11,190,55,195,12,142,161,90,5,223,27,45,2,239,141,0,0,0,0,25,27,49,65,50,54,98,130,43,45,83,195,100,108,197,4,125,119,244,69,86,90,167,134,79,65,150,199,200,217,138,8,209,194,187,73,250,239,232,138,227,244,217,203,172,181,79,12,181,174,126,77,158,131,45,142,135,152,28,207,74,194,18,81,83,217,35,16,120,244,112,211,97,239,65,146,46,174,215,85,55,181,230,20,28,152,181,215,5,131,132,150,130,27,152,89,155,0,169,24,176,45,250,219,169,54,203,154,230,119,93,93,255,108,108,28,212,65,63,223,205,90,14,158,149,132,36,162,140,159,21,227,167,178,70,32,190,169,119,97,241,232,225,166,232,243,208,231,195,222,131,36,218,197,178,101,93,93,174,170,68,70,159,235,111,107,204,40,118,112,253,105,57,49,107,174,32,42,90,239,11,7,9,44,18,28,56,109,223,70,54,243,198,93,7,178,237,112,84,113,244,107,101,48,187,42,243,247,162,49,194,182,137,28,145,117,144,7,160,52,23,159,188,251,14,132,141,186,37,169,222,121,60,178,239,56,115,243,121,255,106,232,72,190,65,197,27,125,88,222,42,60,240,121,79,5,233,98,126,68,194,79,45,135,219,84,28,198,148,21,138,1,141,14,187,64,166,35,232,131,191,56,217,194,56,160,197,13,33,187,244,76,10,150,167,143,19,141,150,206,92,204,0,9,69,215,49,72,110,250,98,139,119,225,83,202,186,187,93,84,163,160,108,21,136,141,63,214,145,150,14,151,222,215,152,80,199,204,169,17,236,225,250,210,245,250,203,147,114,98,215,92,107,121,230,29,64,84,181,222,89,79,132,159,22,14,18,88,15,21,35,25,36,56,112,218,61,35,65,155,101,253,107,167,124,230,90,230,87,203,9,37,78,208,56,100,1,145,174,163,24,138,159,226,51,167,204,33,42,188,253,96,173,36,225,175,180,63,208,238,159,18,131,45,134,9,178,108,201,72,36,171,208,83,21,234,251,126,70,41,226,101,119,104,47,63,121,246,54,36,72,183,29,9,27,116,4,18,42,53,75,83,188,242,82,72,141,179,121,101,222,112,96,126,239,49,231,230,243,254,254,253,194,191,213,208,145,124,204,203,160,61,131,138,54,250,154,145,7,187,177,188,84,120,168,167,101,57,59,131,152,75,34,152,169,10,9,181,250,201,16,174,203,136,95,239,93,79,70,244,108,14,109,217,63,205,116,194,14,140,243,90,18,67,234,65,35,2,193,108,112,193,216,119,65,128,151,54,215,71,142,45,230,6,165,0,181,197,188,27,132,132,113,65,138,26,104,90,187,91,67,119,232,152,90,108,217,217,21,45,79,30,12,54,126,95,39,27,45,156,62,0,28,221,185,152,0,18,160,131,49,83,139,174,98,144,146,181,83,209,221,244,197,22,196,239,244,87,239,194,167,148,246,217,150,213,174,7,188,233,183,28,141,168,156,49,222,107,133,42,239,42,202,107,121,237,211,112,72,172,248,93,27,111,225,70,42,46,102,222,54,225,127,197,7,160,84,232,84,99,77,243,101,34,2,178,243,229,27,169,194,164,48,132,145,103,41,159,160,38,228,197,174,184,253,222,159,249,214,243,204,58,207,232,253,123,128,169,107,188,153,178,90,253,178,159,9,62,171,132,56,127,44,28,36,176,53,7,21,241,30,42,70,50,7,49,119,115,72,112,225,180,81,107,208,245,122,70,131,54,99,93,178,119,203,250,215,78,210,225,230,15,249,204,181,204,224,215,132,141,175,150,18,74,182,141,35,11,157,160,112,200,132,187,65,137,3,35,93,70,26,56,108,7,49,21,63,196,40,14,14,133,103,79,152,66,126,84,169,3,85,121,250,192,76,98,203,129,129,56,197,31,152,35,244,94,179,14,167,157,170,21,150,220,229,84,0,27,252,79,49,90,215,98,98,153,206,121,83,216,73,225,79,23,80,250,126,86,123,215,45,149,98,204,28,212,45,141,138,19,52,150,187,82,31,187,232,145,6,160,217,208,94,126,243,236,71,101,194,173,108,72,145,110,117,83,160,47,58,18,54,232,35,9,7,169,8,36,84,106,17,63,101,43].concat([150,167,121,228,143,188,72,165,164,145,27,102,189,138,42,39,242,203,188,224,235,208,141,161,192,253,222,98,217,230,239,35,20,188,225,189,13,167,208,252,38,138,131,63,63,145,178,126,112,208,36,185,105,203,21,248,66,230,70,59,91,253,119,122,220,101,107,181,197,126,90,244,238,83,9,55,247,72,56,118,184,9,174,177,161,18,159,240,138,63,204,51,147,36,253,114,0,0,0,0,1,194,106,55,3,132,212,110,2,70,190,89,7,9,168,220,6,203,194,235,4,141,124,178,5,79,22,133,14,19,81,184,15,209,59,143,13,151,133,214,12,85,239,225,9,26,249,100,8,216,147,83,10,158,45,10,11,92,71,61,28,38,163,112,29,228,201,71,31,162,119,30,30,96,29,41,27,47,11,172,26,237,97,155,24,171,223,194,25,105,181,245,18,53,242,200,19,247,152,255,17,177,38,166,16,115,76,145,21,60,90,20,20,254,48,35,22,184,142,122,23,122,228,77,56,77,70,224,57,143,44,215,59,201,146,142,58,11,248,185,63,68,238,60,62,134,132,11,60,192,58,82,61,2,80,101,54,94,23,88,55,156,125,111,53,218,195,54,52,24,169,1,49,87,191,132,48,149,213,179,50,211,107,234,51,17,1,221,36,107,229,144,37,169,143,167,39,239,49,254,38,45,91,201,35,98,77,76,34,160,39,123,32,230,153,34,33,36,243,21,42,120,180,40,43,186,222,31,41,252,96,70,40,62,10,113,45,113,28,244,44,179,118,195,46,245,200,154,47,55,162,173,112,154,141,192,113,88,231,247,115,30,89,174,114,220,51,153,119,147,37,28,118,81,79,43,116,23,241,114,117,213,155,69,126,137,220,120,127,75,182,79,125,13,8,22,124,207,98,33,121,128,116,164,120,66,30,147,122,4,160,202,123,198,202,253,108,188,46,176,109,126,68,135,111,56,250,222,110,250,144,233,107,181,134,108,106,119,236,91,104,49,82,2,105,243,56,53,98,175,127,8,99,109,21,63,97,43,171,102,96,233,193,81,101,166,215,212,100,100,189,227,102,34,3,186,103,224,105,141,72,215,203,32,73,21,161,23,75,83,31,78,74,145,117,121,79,222,99,252,78,28,9,203,76,90,183,146,77,152,221,165,70,196,154,152,71,6,240,175,69,64,78,246,68,130,36,193,65,205,50,68,64,15,88,115,66,73,230,42,67,139,140,29,84,241,104,80,85,51,2,103,87,117,188,62,86,183,214,9,83,248,192,140,82,58,170,187,80,124,20,226,81,190,126,213,90,226,57,232,91,32,83,223,89,102,237,134,88,164,135,177,93,235,145,52,92,41,251,3,94,111,69,90,95,173,47,109,225,53,27,128,224,247,113,183,226,177,207,238,227,115,165,217,230,60,179,92,231,254,217,107,229,184,103,50,228,122,13,5,239,38,74,56,238,228,32,15,236,162,158,86,237,96,244,97,232,47,226,228,233,237,136,211,235,171,54,138,234,105,92,189,253,19,184,240,252,209,210,199,254,151,108,158,255,85,6,169,250,26,16,44,251,216,122,27,249,158,196,66,248,92,174,117,243,0,233,72,242,194,131,127,240,132,61,38,241,70,87,17,244,9,65,148,245,203,43,163,247,141,149,250,246,79,255,205,217,120,93,96,216,186,55,87,218,252,137,14,219,62,227,57,222,113,245,188,223,179,159,139,221,245,33,210,220,55,75,229,215,107,12,216,214,169,102,239,212,239,216,182,213,45,178,129,208,98,164,4,209,160,206,51,211,230,112,106,210,36,26,93,197,94,254,16,196,156,148,39,198,218,42,126,199,24,64,73,194,87,86,204,195,149,60,251,193,211,130,162,192,17,232,149,203,77,175,168,202,143,197,159,200,201,123,198,201,11,17,241,204,68,7,116,205,134,109,67,207,192,211,26,206,2,185,45,145,175,150,64,144,109,252,119,146,43,66,46,147,233,40,25,150,166,62,156,151,100,84,171,149,34,234,242,148,224,128,197,159,188,199,248,158,126,173,207,156,56,19,150,157,250,121,161,152,181,111,36,153,119,5,19,155,49,187,74,154,243,209,125,141,137,53,48,140,75,95,7,142,13,225,94,143,207,139,105,138,128,157,236,139,66,247,219,137,4,73,130,136,198,35,181,131,154,100,136,130,88,14,191,128,30,176,230,129,220,218,209,132,147,204,84,133,81,166,99,135,23,24,58,134,213,114,13,169,226,208,160,168,32,186,151,170,102,4,206,171,164,110,249,174,235,120,124,175,41,18,75,173,111,172,18,172,173,198,37,167,241,129,24,166,51,235,47,164,117,85,118,165,183,63,65,160,248,41,196,161,58,67,243,163,124,253,170,162,190,151,157,181,196,115,208,180,6,25,231,182,64,167,190,183,130,205,137,178,205,219,12,179,15,177,59,177,73,15,98,176,139,101,85,187,215,34,104,186,21,72,95,184,83,246,6,185,145,156,49,188,222,138,180,189,28,224,131,191,90,94,218,190,152,52,237,0,0,0,0,184,188,103,101,170,9,200,139,18,181,175,238,143,98,151,87,55,222,240,50,37,107,95,220,157,215,56,185,197,180,40,239,125,8,79,138,111,189,224,100,215,1,135,1,74,214,191,184,242,106,216,221,224,223,119,51,88,99,16,86,80,25,87,159,232,165,48,250,250,16,159,20,66,172,248,113,223,123,192,200,103,199,167,173,117,114,8,67,205,206,111,38,149,173,127,112,45,17,24,21,63,164,183,251,135,24,208,158,26,207,232,39,162,115,143,66,176,198,32,172,8,122,71,201,160,50,175,62,24,142,200,91,10,59,103,181,178,135,0,208,47,80,56,105,151,236,95,12,133,89,240,226,61,229,151,135,101,134,135,209,221,58,224,180,207,143,79,90,119,51,40,63,234,228,16,134,82,88,119,227,64,237,216,13,248,81,191,104,240,43,248,161,72,151,159,196,90,34,48,42,226,158,87,79,127,73,111,246,199,245,8,147,213,64,167,125,109,252,192,24,53,159,208,78,141,35,183,43,159,150,24,197,39,42,127,160,186,253,71,25,2,65,32,124,16,244,143,146,168,72,232,247,155,20,88,61,35,168,63,88,49,29,144,182,137,161,247,211,20,118,207,106,172,202,168,15,190,127,7,225,6,195,96,132,94,160,112,210,230,28,23,183,244,169,184,89,76,21,223,60,209,194,231,133,105,126,128,224,123,203,47,14,195,119,72,107,203,13,15,162,115,177,104,199,97,4,199,41,217,184,160,76,68,111,152,245,252,211,255,144,238,102,80,126,86,218,55,27,14,185,39,77,182,5,64,40,164,176,239,198,28,12,136,163,129,219,176,26,57,103,215,127,43,210,120,145,147,110,31,244,59,38,247,3,131,154,144,102,145,47,63,136,41,147,88,237,180,68,96,84,12,248,7,49,30,77,168,223,166,241,207,186,254,146,223,236,70,46,184,137,84,155,23,103,236,39,112,2,113,240,72,187,201,76,47,222,219,249,128,48,99,69,231,85,107,63,160,156,211,131,199,249,193,54,104,23,121,138,15,114,228,93,55,203,92,225,80,174,78,84,255,64,246,232,152,37,174,139,136,115,22,55,239,22,4,130,64,248,188,62,39,157,33,233,31,36,153,85,120,65,139,224,215,175,51,92,176,202,237,89,182,59,85,229,209,94,71,80,126,176,255,236,25,213,98,59,33,108,218,135,70,9,200,50,233,231,112,142,142,130,40,237,158,212,144,81,249,177,130,228,86,95,58,88,49,58,167,143,9,131,31,51,110,230,13,134,193,8,181,58,166,109,189,64,225,164,5,252,134,193,23,73,41,47,175,245,78,74,50,34,118,243,138,158,17,150,152,43,190,120,32,151,217,29,120,244,201,75,192,72,174,46,210,253,1,192,106,65,102,165,247,150,94,28,79,42,57,121,93,159,150,151,229,35,241,242,77,107,25,5,245,215,126,96,231,98,209,142,95,222,182,235,194,9,142,82,122,181,233,55,104,0,70,217,208,188,33,188,136,223,49,234,48,99,86,143,34,214,249,97,154,106,158,4,7,189,166,189,191,1,193,216,173,180,110,54,21,8,9,83,29,114,78,154,165,206,41,255,183,123,134,17,15,199,225,116,146,16,217,205,42,172,190,168,56,25,17,70,128,165,118,35,216,198,102,117,96,122,1,16,114,207,174,254,202,115,201,155,87,164,241,34,239,24,150,71,253,173,57,169,69,17,94,204,118,77,238,6,206,241,137,99,220,68,38,141,100,248,65,232,249,47,121,81,65,147,30,52,83,38,177,218,235,154,214,191,179,249,198,233,11,69,161,140,25,240,14,98,161,76,105,7,60,155,81,190,132,39,54,219,150,146,153,53,46,46,254,80,38,84,185,153,158,232,222,252,140,93,113,18,52,225,22,119,169,54,46,206,17,138,73,171,3,63,230,69,187,131,129,32,227,224,145,118,91,92,246,19,73,233,89,253,241,85,62,152,108,130,6,33,212,62,97,68,198,139,206,170,126,55,169,207,214,127,65,56,110,195,38,93,124,118,137,179,196,202,238,214,89,29,214,111,225,161,177,10,243,20,30,228,75,168,121,129,19,203,105,215,171,119,14,178,185,194,161,92,1,126,198,57,156,169,254,128,36,21,153,229,54,160,54,11,142,28,81,110,134,102,22,167,62,218,113,194,44,111,222,44,148,211,185,73,9,4,129,240,177,184,230,149,163,13,73,123,27,177,46,30,67,210,62,72,251,110,89,45,233,219,246,195,81,103,145,166,204,176,169,31,116,12,206,122,102,185,97,148,222,5,6,241,0,0,0,0,0,0,0,0,2,0,0,0,4,0,4,0,8,0,4,0,8,0,0,0,4,0,5,0,16,0,8,0,8,0,0,0,4,0,6,0,32,0,32,0,8,0,0,0,4,0,4,0,16,0,16,0,6,0,0,0,8,0,16,0,32,0,32,0,6,0,0,0,8,0,16,0,128,0,128,0,6,0,0,0,8,0,32,0,128,0,0,1,6,0,0,0,32,0,128,0,2,1,0,4,6,0,0,0,32,0,2,1,2,1,0,16,6,0,0,0,16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,8,0,0,0,10,0,0,0,12,0,0,0,14,0,0,0,16,0,0,0,20,0,0,0,24,0,0,0,28,0,0,0,32,0,0,0,40,0,0,0,48,0,0,0,56,0,0,0,64,0,0,0,80,0,0,0,96,0,0,0,112,0,0,0,128,0,0,0,160,0,0,0,192,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,0,128,0,0,0,192,0,0,0,0,1,0,0,128,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,105,110,99,111,109,112,97,116,105,98,108,101,32,118,101,114,115,105,111,110,0,0,0,0,116,111,111,32,109,97,110,121,32,108,101,110,103,116,104,32,111,114,32,100,105,115,116,97,110,99,101,32,115,121,109,98,111,108,115,0,0,0,0,0,99,111,109,112,114,101,115,115,101,100,32,100,97,116,97,32,101,114,114,111,114,0,0,0,98,117,102,102,101,114,32,101,114,114,111,114,0,0,0,0,110,101,101,100,32,100,105,99,116,105,111,110,97,114,121,0,105,110,118,97,108,105,100,32,115,116,111,114,101,100,32,98,108,111,99,107,32,108,101,110,103,116,104,115,0,0,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,105,110,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,105,110,115,117,102,102,105,99,105,101,110,116,32,109,101,109,111,114,121,0,0,0,0,0,105,110,118,97,108,105,100,32,98,108,111,99,107,32,116,121,112,101,0,0,0,0,0,0,117,110,101,120,112,101,99,116,101,100,32,101,110,100,32,111,102,32,102,105,108,101,0,0,100,97,116,97,32,101,114,114,111,114,0,0,0,0,0,0,104,101,97,100,101,114,32,99,114,99,32,109,105,115,109,97,116,99,104,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,115,116,114,101,97,109,32,101,114,114,111,114,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,102,105,108,101,32,101,114,114,111,114,0,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,118,97,108,105,100,32,119,105,110,100,111,119,32,115,105,122,101,0,0,0,0,0,49,46,50,46,53,0,0,0,49,46,50,46,53,0,0,0,58,32,0,0,0,0,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,115,116,114,101,97,109,32,101,110,100,0,0,0,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,99,111,114,114,101,99,116,32,104,101,97,100,101,114,32,99,104,101,99,107,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,115,32,115,101,116,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,100,101,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,45,45,32,109,105,115,115,105,110,103,32,101,110,100,45,111,102,45,98,108,111,99,107,0,0,0,0,105,110,118,97,108,105,100,32,98,105,116,32,108,101,110,103,116,104,32,114,101,112,101,97,116,0,0,0,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29]) +, "i8", ALLOC_NONE, Runtime.GLOBAL_BASE) +var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8); +assert(tempDoublePtr % 8 == 0); +function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much + HEAP8[tempDoublePtr] = HEAP8[ptr]; + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; +} +function copyTempDouble(ptr) { + HEAP8[tempDoublePtr] = HEAP8[ptr]; + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; + HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; + HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; + HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; +} + function _llvm_lifetime_start() {} + function _llvm_lifetime_end() {} + Module["_memset"] = _memset;var _llvm_memset_p0i8_i32=_memset; + Module["_memcpy"] = _memcpy;var _llvm_memcpy_p0i8_p0i8_i32=_memcpy; + var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:35,EIDRM:36,ECHRNG:37,EL2NSYNC:38,EL3HLT:39,EL3RST:40,ELNRNG:41,EUNATCH:42,ENOCSI:43,EL2HLT:44,EDEADLK:45,ENOLCK:46,EBADE:50,EBADR:51,EXFULL:52,ENOANO:53,EBADRQC:54,EBADSLT:55,EDEADLOCK:56,EBFONT:57,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:74,ELBIN:75,EDOTDOT:76,EBADMSG:77,EFTYPE:79,ENOTUNIQ:80,EBADFD:81,EREMCHG:82,ELIBACC:83,ELIBBAD:84,ELIBSCN:85,ELIBMAX:86,ELIBEXEC:87,ENOSYS:88,ENMFILE:89,ENOTEMPTY:90,ENAMETOOLONG:91,ELOOP:92,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:106,EPROTOTYPE:107,ENOTSOCK:108,ENOPROTOOPT:109,ESHUTDOWN:110,ECONNREFUSED:111,EADDRINUSE:112,ECONNABORTED:113,ENETUNREACH:114,ENETDOWN:115,ETIMEDOUT:116,EHOSTDOWN:117,EHOSTUNREACH:118,EINPROGRESS:119,EALREADY:120,EDESTADDRREQ:121,EMSGSIZE:122,EPROTONOSUPPORT:123,ESOCKTNOSUPPORT:124,EADDRNOTAVAIL:125,ENETRESET:126,EISCONN:127,ENOTCONN:128,ETOOMANYREFS:129,EPROCLIM:130,EUSERS:131,EDQUOT:132,ESTALE:133,ENOTSUP:134,ENOMEDIUM:135,ENOSHARE:136,ECASECLASH:137,EILSEQ:138,EOVERFLOW:139,ECANCELED:140,ENOTRECOVERABLE:141,EOWNERDEAD:142,ESTRPIPE:143}; + var ___errno_state=0;function ___setErrNo(value) { + // For convenient setting and returning of errno. + HEAP32[((___errno_state)>>2)]=value + return value; + } + var _stdin=allocate(1, "i32*", ALLOC_STATIC); + var _stdout=allocate(1, "i32*", ALLOC_STATIC); + var _stderr=allocate(1, "i32*", ALLOC_STATIC); + var __impure_ptr=allocate(1, "i32*", ALLOC_STATIC);var FS={currentPath:"/",nextInode:2,streams:[null],ignorePermissions:true,createFileHandle:function (stream, fd) { + if (typeof stream === 'undefined') { + stream = null; + } + if (!fd) { + if (stream && stream.socket) { + for (var i = 1; i < 64; i++) { + if (!FS.streams[i]) { + fd = i; + break; + } + } + assert(fd, 'ran out of low fds for sockets'); + } else { + fd = Math.max(FS.streams.length, 64); + for (var i = FS.streams.length; i < fd; i++) { + FS.streams[i] = null; // Keep dense + } + } + } + // Close WebSocket first if we are about to replace the fd (i.e. dup2) + if (FS.streams[fd] && FS.streams[fd].socket && FS.streams[fd].socket.close) { + FS.streams[fd].socket.close(); + } + FS.streams[fd] = stream; + return fd; + },removeFileHandle:function (fd) { + FS.streams[fd] = null; + },joinPath:function (parts, forceRelative) { + var ret = parts[0]; + for (var i = 1; i < parts.length; i++) { + if (ret[ret.length-1] != '/') ret += '/'; + ret += parts[i]; + } + if (forceRelative && ret[0] == '/') ret = ret.substr(1); + return ret; + },absolutePath:function (relative, base) { + if (typeof relative !== 'string') return null; + if (base === undefined) base = FS.currentPath; + if (relative && relative[0] == '/') base = ''; + var full = base + '/' + relative; + var parts = full.split('/').reverse(); + var absolute = ['']; + while (parts.length) { + var part = parts.pop(); + if (part == '' || part == '.') { + // Nothing. + } else if (part == '..') { + if (absolute.length > 1) absolute.pop(); + } else { + absolute.push(part); + } + } + return absolute.length == 1 ? '/' : absolute.join('/'); + },analyzePath:function (path, dontResolveLastLink, linksVisited) { + var ret = { + isRoot: false, + exists: false, + error: 0, + name: null, + path: null, + object: null, + parentExists: false, + parentPath: null, + parentObject: null + }; + path = FS.absolutePath(path); + if (path == '/') { + ret.isRoot = true; + ret.exists = ret.parentExists = true; + ret.name = '/'; + ret.path = ret.parentPath = '/'; + ret.object = ret.parentObject = FS.root; + } else if (path !== null) { + linksVisited = linksVisited || 0; + path = path.slice(1).split('/'); + var current = FS.root; + var traversed = ['']; + while (path.length) { + if (path.length == 1 && current.isFolder) { + ret.parentExists = true; + ret.parentPath = traversed.length == 1 ? '/' : traversed.join('/'); + ret.parentObject = current; + ret.name = path[0]; + } + var target = path.shift(); + if (!current.isFolder) { + ret.error = ERRNO_CODES.ENOTDIR; + break; + } else if (!current.read) { + ret.error = ERRNO_CODES.EACCES; + break; + } else if (!current.contents.hasOwnProperty(target)) { + ret.error = ERRNO_CODES.ENOENT; + break; + } + current = current.contents[target]; + if (current.link && !(dontResolveLastLink && path.length == 0)) { + if (linksVisited > 40) { // Usual Linux SYMLOOP_MAX. + ret.error = ERRNO_CODES.ELOOP; + break; + } + var link = FS.absolutePath(current.link, traversed.join('/')); + ret = FS.analyzePath([link].concat(path).join('/'), + dontResolveLastLink, linksVisited + 1); + return ret; + } + traversed.push(target); + if (path.length == 0) { + ret.exists = true; + ret.path = traversed.join('/'); + ret.object = current; + } + } + } + return ret; + },findObject:function (path, dontResolveLastLink) { + FS.ensureRoot(); + var ret = FS.analyzePath(path, dontResolveLastLink); + if (ret.exists) { + return ret.object; + } else { + ___setErrNo(ret.error); + return null; + } + },createObject:function (parent, name, properties, canRead, canWrite) { + if (!parent) parent = '/'; + if (typeof parent === 'string') parent = FS.findObject(parent); + if (!parent) { + ___setErrNo(ERRNO_CODES.EACCES); + throw new Error('Parent path must exist.'); + } + if (!parent.isFolder) { + ___setErrNo(ERRNO_CODES.ENOTDIR); + throw new Error('Parent must be a folder.'); + } + if (!parent.write && !FS.ignorePermissions) { + ___setErrNo(ERRNO_CODES.EACCES); + throw new Error('Parent folder must be writeable.'); + } + if (!name || name == '.' || name == '..') { + ___setErrNo(ERRNO_CODES.ENOENT); + throw new Error('Name must not be empty.'); + } + if (parent.contents.hasOwnProperty(name)) { + ___setErrNo(ERRNO_CODES.EEXIST); + throw new Error("Can't overwrite object."); + } + parent.contents[name] = { + read: canRead === undefined ? true : canRead, + write: canWrite === undefined ? false : canWrite, + timestamp: Date.now(), + inodeNumber: FS.nextInode++ + }; + for (var key in properties) { + if (properties.hasOwnProperty(key)) { + parent.contents[name][key] = properties[key]; + } + } + return parent.contents[name]; + },createFolder:function (parent, name, canRead, canWrite) { + var properties = {isFolder: true, isDevice: false, contents: {}}; + return FS.createObject(parent, name, properties, canRead, canWrite); + },createPath:function (parent, path, canRead, canWrite) { + var current = FS.findObject(parent); + if (current === null) throw new Error('Invalid parent.'); + path = path.split('/').reverse(); + while (path.length) { + var part = path.pop(); + if (!part) continue; + if (!current.contents.hasOwnProperty(part)) { + FS.createFolder(current, part, canRead, canWrite); + } + current = current.contents[part]; + } + return current; + },createFile:function (parent, name, properties, canRead, canWrite) { + properties.isFolder = false; + return FS.createObject(parent, name, properties, canRead, canWrite); + },createDataFile:function (parent, name, data, canRead, canWrite) { + if (typeof data === 'string') { + var dataArray = new Array(data.length); + for (var i = 0, len = data.length; i < len; ++i) dataArray[i] = data.charCodeAt(i); + data = dataArray; + } + var properties = { + isDevice: false, + contents: data.subarray ? data.subarray(0) : data // as an optimization, create a new array wrapper (not buffer) here, to help JS engines understand this object + }; + return FS.createFile(parent, name, properties, canRead, canWrite); + },createLazyFile:function (parent, name, url, canRead, canWrite) { + if (typeof XMLHttpRequest !== 'undefined') { + if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; + // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. + var LazyUint8Array = function() { + this.lengthKnown = false; + this.chunks = []; // Loaded chunks. Index is the chunk number + } + LazyUint8Array.prototype.get = function(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = Math.floor(idx / this.chunkSize); + return this.getter(chunkNum)[chunkOffset]; + } + LazyUint8Array.prototype.setDataGetter = function(getter) { + this.getter = getter; + } + LazyUint8Array.prototype.cacheLength = function() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("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 chunkSize = 1024*1024; // Chunk size in bytes + if (!hasByteServing) chunkSize = datalength; + // Function to get a range from the remote URL. + var doXHR = (function(from, to) { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + // Some hints to the browser that we want binary data. + if (typeof Uint8Array != 'undefined') 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)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(xhr.response || []); + } else { + return intArrayFromString(xhr.responseText || '', true); + } + }); + var lazyArray = this; + lazyArray.setDataGetter(function(chunkNum) { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); + return lazyArray.chunks[chunkNum]; + }); + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } + var lazyArray = new LazyUint8Array(); + Object.defineProperty(lazyArray, "length", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + }); + Object.defineProperty(lazyArray, "chunkSize", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + }); + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + return FS.createFile(parent, name, properties, canRead, canWrite); + },createPreloadedFile:function (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile) { + Browser.init(); + var fullname = FS.joinPath([parent, name], true); + function processData(byteArray) { + function finish(byteArray) { + if (!dontCreateFile) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite); + } + if (onload) onload(); + removeRunDependency('cp ' + fullname); + } + var handled = false; + Module['preloadPlugins'].forEach(function(plugin) { + if (handled) return; + if (plugin['canHandle'](fullname)) { + plugin['handle'](byteArray, fullname, finish, function() { + if (onerror) onerror(); + removeRunDependency('cp ' + fullname); + }); + handled = true; + } + }); + if (!handled) finish(byteArray); + } + addRunDependency('cp ' + fullname); + if (typeof url == 'string') { + Browser.asyncLoad(url, function(byteArray) { + processData(byteArray); + }, onerror); + } else { + processData(url); + } + },createLink:function (parent, name, target, canRead, canWrite) { + var properties = {isDevice: false, link: target}; + return FS.createFile(parent, name, properties, canRead, canWrite); + },createDevice:function (parent, name, input, output) { + if (!(input || output)) { + throw new Error('A device must have at least one callback defined.'); + } + var ops = {isDevice: true, input: input, output: output}; + return FS.createFile(parent, name, ops, Boolean(input), Boolean(output)); + },forceLoadFile:function (obj) { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + var success = true; + if (typeof XMLHttpRequest !== 'undefined') { + throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else if (Module['read']) { + // Command-line. + try { + // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as + // read() will try to parse UTF8. + obj.contents = intArrayFromString(Module['read'](obj.url), true); + } catch (e) { + success = false; + } + } else { + throw new Error('Cannot load without read() or XMLHttpRequest.'); + } + if (!success) ___setErrNo(ERRNO_CODES.EIO); + return success; + },ensureRoot:function () { + if (FS.root) return; + // The main file system tree. All the contents are inside this. + FS.root = { + read: true, + write: true, + isFolder: true, + isDevice: false, + timestamp: Date.now(), + inodeNumber: 1, + contents: {} + }; + },init:function (input, output, error) { + // Make sure we initialize only once. + assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); + FS.init.initialized = true; + FS.ensureRoot(); + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + input = input || Module['stdin']; + output = output || Module['stdout']; + error = error || Module['stderr']; + // Default handlers. + var stdinOverridden = true, stdoutOverridden = true, stderrOverridden = true; + if (!input) { + stdinOverridden = false; + input = function() { + if (!input.cache || !input.cache.length) { + var result; + if (typeof window != 'undefined' && + typeof window.prompt == 'function') { + // Browser. + result = window.prompt('Input: '); + if (result === null) result = String.fromCharCode(0); // cancel ==> EOF + } else if (typeof readline == 'function') { + // Command line. + result = readline(); + } + if (!result) result = ''; + input.cache = intArrayFromString(result + '\n', true); + } + return input.cache.shift(); + }; + } + var utf8 = new Runtime.UTF8Processor(); + function simpleOutput(val) { + if (val === null || val === 10) { + output.printer(output.buffer.join('')); + output.buffer = []; + } else { + output.buffer.push(utf8.processCChar(val)); + } + } + if (!output) { + stdoutOverridden = false; + output = simpleOutput; + } + if (!output.printer) output.printer = Module['print']; + if (!output.buffer) output.buffer = []; + if (!error) { + stderrOverridden = false; + error = simpleOutput; + } + if (!error.printer) error.printer = Module['print']; + if (!error.buffer) error.buffer = []; + // Create the temporary folder, if not already created + try { + FS.createFolder('/', 'tmp', true, true); + } catch(e) {} + // Create the I/O devices. + var devFolder = FS.createFolder('/', 'dev', true, true); + var stdin = FS.createDevice(devFolder, 'stdin', input); + var stdout = FS.createDevice(devFolder, 'stdout', null, output); + var stderr = FS.createDevice(devFolder, 'stderr', null, error); + FS.createDevice(devFolder, 'tty', input, output); + FS.createDevice(devFolder, 'null', function(){}, function(){}); + // Create default streams. + FS.streams[1] = { + path: '/dev/stdin', + object: stdin, + position: 0, + isRead: true, + isWrite: false, + isAppend: false, + isTerminal: !stdinOverridden, + error: false, + eof: false, + ungotten: [] + }; + FS.streams[2] = { + path: '/dev/stdout', + object: stdout, + position: 0, + isRead: false, + isWrite: true, + isAppend: false, + isTerminal: !stdoutOverridden, + error: false, + eof: false, + ungotten: [] + }; + FS.streams[3] = { + path: '/dev/stderr', + object: stderr, + position: 0, + isRead: false, + isWrite: true, + isAppend: false, + isTerminal: !stderrOverridden, + error: false, + eof: false, + ungotten: [] + }; + // TODO: put these low in memory like we used to assert on: assert(Math.max(_stdin, _stdout, _stderr) < 15000); // make sure these are low, we flatten arrays with these + HEAP32[((_stdin)>>2)]=1; + HEAP32[((_stdout)>>2)]=2; + HEAP32[((_stderr)>>2)]=3; + // Other system paths + FS.createPath('/', 'dev/shm/tmp', true, true); // temp files + // Newlib initialization + for (var i = FS.streams.length; i < Math.max(_stdin, _stdout, _stderr) + 4; i++) { + FS.streams[i] = null; // Make sure to keep FS.streams dense + } + FS.streams[_stdin] = FS.streams[1]; + FS.streams[_stdout] = FS.streams[2]; + FS.streams[_stderr] = FS.streams[3]; + allocate([ allocate( + [0, 0, 0, 0, _stdin, 0, 0, 0, _stdout, 0, 0, 0, _stderr, 0, 0, 0], + 'void*', ALLOC_NORMAL) ], 'void*', ALLOC_NONE, __impure_ptr); + },quit:function () { + if (!FS.init.initialized) return; + // Flush any partially-printed lines in stdout and stderr. Careful, they may have been closed + if (FS.streams[2] && FS.streams[2].object.output.buffer.length > 0) FS.streams[2].object.output(10); + if (FS.streams[3] && FS.streams[3].object.output.buffer.length > 0) FS.streams[3].object.output(10); + },standardizePath:function (path) { + if (path.substr(0, 2) == './') path = path.substr(2); + return path; + },deleteFile:function (path) { + path = FS.analyzePath(path); + if (!path.parentExists || !path.exists) { + throw 'Invalid path ' + path; + } + delete path.parentObject.contents[path.name]; + }};function _lseek(fildes, offset, whence) { + // off_t lseek(int fildes, off_t offset, int whence); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/lseek.html + if (FS.streams[fildes] && !FS.streams[fildes].object.isDevice) { + var stream = FS.streams[fildes]; + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + position += stream.object.contents.length; + } + if (position < 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } else { + stream.ungotten = []; + stream.position = position; + return position; + } + } else { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + } + Module["_strlen"] = _strlen; + Module["_strcpy"] = _strcpy; + Module["_strcat"] = _strcat; + var ___dirent_struct_layout={__size__:1040,d_ino:0,d_name:4,d_off:1028,d_reclen:1032,d_type:1036};function _open(path, oflag, varargs) { + // int open(const char *path, int oflag, ...); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html + // NOTE: This implementation tries to mimic glibc rather than strictly + // following the POSIX standard. + var mode = HEAP32[((varargs)>>2)]; + // Simplify flags. + var accessMode = oflag & 3; + var isWrite = accessMode != 0; + var isRead = accessMode != 1; + var isCreate = Boolean(oflag & 512); + var isExistCheck = Boolean(oflag & 2048); + var isTruncate = Boolean(oflag & 1024); + var isAppend = Boolean(oflag & 8); + // Verify path. + var origPath = path; + path = FS.analyzePath(Pointer_stringify(path)); + if (!path.parentExists) { + ___setErrNo(path.error); + return -1; + } + var target = path.object || null; + var finalPath; + // Verify the file exists, create if needed and allowed. + if (target) { + if (isCreate && isExistCheck) { + ___setErrNo(ERRNO_CODES.EEXIST); + return -1; + } + if ((isWrite || isCreate || isTruncate) && target.isFolder) { + ___setErrNo(ERRNO_CODES.EISDIR); + return -1; + } + if (isRead && !target.read || isWrite && !target.write) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } + if (isTruncate && !target.isDevice) { + target.contents = []; + } else { + if (!FS.forceLoadFile(target)) { + ___setErrNo(ERRNO_CODES.EIO); + return -1; + } + } + finalPath = path.path; + } else { + if (!isCreate) { + ___setErrNo(ERRNO_CODES.ENOENT); + return -1; + } + if (!path.parentObject.write) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } + target = FS.createDataFile(path.parentObject, path.name, [], + mode & 0x100, mode & 0x80); // S_IRUSR, S_IWUSR. + finalPath = path.parentPath + '/' + path.name; + } + // Actually create an open stream. + var id; + if (target.isFolder) { + var entryBuffer = 0; + if (___dirent_struct_layout) { + entryBuffer = _malloc(___dirent_struct_layout.__size__); + } + var contents = []; + for (var key in target.contents) contents.push(key); + id = FS.createFileHandle({ + path: finalPath, + object: target, + // An index into contents. Special values: -2 is ".", -1 is "..". + position: -2, + isRead: true, + isWrite: false, + isAppend: false, + error: false, + eof: false, + ungotten: [], + // Folder-specific properties: + // Remember the contents at the time of opening in an array, so we can + // seek between them relying on a single order. + contents: contents, + // Each stream has its own area for readdir() returns. + currentEntry: entryBuffer + }); + } else { + id = FS.createFileHandle({ + path: finalPath, + object: target, + position: 0, + isRead: isRead, + isWrite: isWrite, + isAppend: isAppend, + error: false, + eof: false, + ungotten: [] + }); + } + return id; + } + function _close(fildes) { + // int close(int fildes); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/close.html + if (FS.streams[fildes]) { + if (FS.streams[fildes].currentEntry) { + _free(FS.streams[fildes].currentEntry); + } + FS.streams[fildes] = null; + return 0; + } else { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + } + function _recv(fd, buf, len, flags) { + var info = FS.streams[fd]; + if (!info) return -1; + if (!info.hasData()) { + ___setErrNo(ERRNO_CODES.EAGAIN); // no data, and all sockets are nonblocking, so this is the right behavior + return -1; + } + var buffer = info.inQueue.shift(); + if (len < buffer.length) { + if (info.stream) { + // This is tcp (reliable), so if not all was read, keep it + info.inQueue.unshift(buffer.subarray(len)); + } + buffer = buffer.subarray(0, len); + } + HEAPU8.set(buffer, buf); + return buffer.length; + } + function _pread(fildes, buf, nbyte, offset) { + // ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.streams[fildes]; + if (!stream || stream.object.isDevice) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } else if (!stream.isRead) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } else if (stream.object.isFolder) { + ___setErrNo(ERRNO_CODES.EISDIR); + return -1; + } else if (nbyte < 0 || offset < 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } else { + var bytesRead = 0; + while (stream.ungotten.length && nbyte > 0) { + HEAP8[((buf++)|0)]=stream.ungotten.pop() + nbyte--; + bytesRead++; + } + var contents = stream.object.contents; + var size = Math.min(contents.length - offset, nbyte); + if (contents.subarray) { // typed array + HEAPU8.set(contents.subarray(offset, offset+size), buf); + } else + if (contents.slice) { // normal array + for (var i = 0; i < size; i++) { + HEAP8[(((buf)+(i))|0)]=contents[offset + i] + } + } else { + for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR + HEAP8[(((buf)+(i))|0)]=contents.get(offset + i) + } + } + bytesRead += size; + return bytesRead; + } + }function _read(fildes, buf, nbyte) { + // ssize_t read(int fildes, void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.streams[fildes]; + if (stream && ('socket' in stream)) { + return _recv(fildes, buf, nbyte, 0); + } else if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } else if (!stream.isRead) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } else if (nbyte < 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } else { + var bytesRead; + if (stream.object.isDevice) { + if (stream.object.input) { + bytesRead = 0; + while (stream.ungotten.length && nbyte > 0) { + HEAP8[((buf++)|0)]=stream.ungotten.pop() + nbyte--; + bytesRead++; + } + for (var i = 0; i < nbyte; i++) { + try { + var result = stream.object.input(); + } catch (e) { + ___setErrNo(ERRNO_CODES.EIO); + return -1; + } + if (result === undefined && bytesRead === 0) { + ___setErrNo(ERRNO_CODES.EAGAIN); + return -1; + } + if (result === null || result === undefined) break; + bytesRead++; + HEAP8[(((buf)+(i))|0)]=result + } + return bytesRead; + } else { + ___setErrNo(ERRNO_CODES.ENXIO); + return -1; + } + } else { + var ungotSize = stream.ungotten.length; + bytesRead = _pread(fildes, buf, nbyte, stream.position); + if (bytesRead != -1) { + stream.position += (stream.ungotten.length - ungotSize) + bytesRead; + } + return bytesRead; + } + } + } + var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"No message of desired type",36:"Identifier removed",37:"Channel number out of range",38:"Level 2 not synchronized",39:"Level 3 halted",40:"Level 3 reset",41:"Link number out of range",42:"Protocol driver not attached",43:"No CSI structure available",44:"Level 2 halted",45:"Deadlock condition",46:"No record locks available",50:"Invalid exchange",51:"Invalid request descriptor",52:"Exchange full",53:"No anode",54:"Invalid request code",55:"Invalid slot",56:"File locking deadlock error",57:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",74:"Multihop attempted",75:"Inode is remote (not really error)",76:"Cross mount point (not really error)",77:"Trying to read unreadable message",79:"Inappropriate file type or format",80:"Given log. name not unique",81:"f.d. invalid for this operation",82:"Remote address changed",83:"Can\t access a needed shared lib",84:"Accessing a corrupted shared lib",85:".lib section in a.out corrupted",86:"Attempting to link in too many libs",87:"Attempting to exec a shared library",88:"Function not implemented",89:"No more files",90:"Directory not empty",91:"File or path name too long",92:"Too many symbolic links",95:"Operation not supported on transport endpoint",96:"Protocol family not supported",104:"Connection reset by peer",105:"No buffer space available",106:"Address family not supported by protocol family",107:"Protocol wrong type for socket",108:"Socket operation on non-socket",109:"Protocol not available",110:"Can't send after socket shutdown",111:"Connection refused",112:"Address already in use",113:"Connection aborted",114:"Network is unreachable",115:"Network interface is not configured",116:"Connection timed out",117:"Host is down",118:"Host is unreachable",119:"Connection already in progress",120:"Socket already connected",121:"Destination address required",122:"Message too long",123:"Unknown protocol",124:"Socket type not supported",125:"Address not available",126:"ENETRESET",127:"Socket is already connected",128:"Socket is not connected",129:"TOOMANYREFS",130:"EPROCLIM",131:"EUSERS",132:"EDQUOT",133:"ESTALE",134:"Not supported",135:"No medium (in tape drive)",136:"No such host or network path",137:"Filename exists with different case",138:"EILSEQ",139:"Value too large for defined data type",140:"Operation canceled",141:"State not recoverable",142:"Previous owner died",143:"Streams pipe error"};function _strerror_r(errnum, strerrbuf, buflen) { + if (errnum in ERRNO_MESSAGES) { + if (ERRNO_MESSAGES[errnum].length > buflen - 1) { + return ___setErrNo(ERRNO_CODES.ERANGE); + } else { + var msg = ERRNO_MESSAGES[errnum]; + for (var i = 0; i < msg.length; i++) { + HEAP8[(((strerrbuf)+(i))|0)]=msg.charCodeAt(i) + } + HEAP8[(((strerrbuf)+(i))|0)]=0 + return 0; + } + } else { + return ___setErrNo(ERRNO_CODES.EINVAL); + } + }function _strerror(errnum) { + if (!_strerror.buffer) _strerror.buffer = _malloc(256); + _strerror_r(errnum, _strerror.buffer, 256); + return _strerror.buffer; + } + function ___errno_location() { + return ___errno_state; + }var ___errno=___errno_location; + function _send(fd, buf, len, flags) { + var info = FS.streams[fd]; + if (!info) return -1; + info.sender(HEAPU8.subarray(buf, buf+len)); + return len; + } + function _pwrite(fildes, buf, nbyte, offset) { + // ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.streams[fildes]; + if (!stream || stream.object.isDevice) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } else if (!stream.isWrite) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } else if (stream.object.isFolder) { + ___setErrNo(ERRNO_CODES.EISDIR); + return -1; + } else if (nbyte < 0 || offset < 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } else { + var contents = stream.object.contents; + while (contents.length < offset) contents.push(0); + for (var i = 0; i < nbyte; i++) { + contents[offset + i] = HEAPU8[(((buf)+(i))|0)]; + } + stream.object.timestamp = Date.now(); + return i; + } + }function _write(fildes, buf, nbyte) { + // ssize_t write(int fildes, const void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.streams[fildes]; + if (stream && ('socket' in stream)) { + return _send(fildes, buf, nbyte, 0); + } else if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } else if (!stream.isWrite) { + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + } else if (nbyte < 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } else { + if (stream.object.isDevice) { + if (stream.object.output) { + for (var i = 0; i < nbyte; i++) { + try { + stream.object.output(HEAP8[(((buf)+(i))|0)]); + } catch (e) { + ___setErrNo(ERRNO_CODES.EIO); + return -1; + } + } + stream.object.timestamp = Date.now(); + return i; + } else { + ___setErrNo(ERRNO_CODES.ENXIO); + return -1; + } + } else { + var bytesWritten = _pwrite(fildes, buf, nbyte, stream.position); + if (bytesWritten != -1) stream.position += bytesWritten; + return bytesWritten; + } + } + } + function _llvm_bswap_i32(x) { + return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24); + } + function _abort() { + ABORT = true; + throw 'abort() at ' + (new Error().stack); + } + function _sysconf(name) { + // long sysconf(int name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/sysconf.html + switch(name) { + case 8: return PAGE_SIZE; + case 54: + case 56: + case 21: + case 61: + case 63: + case 22: + case 67: + case 23: + case 24: + case 25: + case 26: + case 27: + case 69: + case 28: + case 101: + case 70: + case 71: + case 29: + case 30: + case 199: + case 75: + case 76: + case 32: + case 43: + case 44: + case 80: + case 46: + case 47: + case 45: + case 48: + case 49: + case 42: + case 82: + case 33: + case 7: + case 108: + case 109: + case 107: + case 112: + case 119: + case 121: + return 200809; + case 13: + case 104: + case 94: + case 95: + case 34: + case 35: + case 77: + case 81: + case 83: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 90: + case 91: + case 94: + case 95: + case 110: + case 111: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + case 120: + case 40: + case 16: + case 79: + case 19: + return -1; + case 92: + case 93: + case 5: + case 72: + case 6: + case 74: + case 92: + case 93: + case 96: + case 97: + case 98: + case 99: + case 102: + case 103: + case 105: + return 1; + case 38: + case 66: + case 50: + case 51: + case 4: + return 1024; + case 15: + case 64: + case 41: + return 32; + case 55: + case 37: + case 17: + return 2147483647; + case 18: + case 1: + return 47839; + case 59: + case 57: + return 99; + case 68: + case 58: + return 2048; + case 0: return 2097152; + case 3: return 65536; + case 14: return 32768; + case 73: return 32767; + case 39: return 16384; + case 60: return 1000; + case 106: return 700; + case 52: return 256; + case 62: return 255; + case 2: return 100; + case 65: return 64; + case 36: return 20; + case 100: return 16; + case 20: return 6; + case 53: return 4; + case 10: return 1; + } + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + function _time(ptr) { + var ret = Math.floor(Date.now()/1000); + if (ptr) { + HEAP32[((ptr)>>2)]=ret + } + return ret; + } + function _sbrk(bytes) { + // Implement a Linux-like 'memory area' for our 'process'. + // Changes the size of the memory area by |bytes|; returns the + // address of the previous top ('break') of the memory area + // We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP + var self = _sbrk; + if (!self.called) { + DYNAMICTOP = alignMemoryPage(DYNAMICTOP); // make sure we start out aligned + self.called = true; + assert(Runtime.dynamicAlloc); + self.alloc = Runtime.dynamicAlloc; + Runtime.dynamicAlloc = function() { abort('cannot dynamically allocate, sbrk now has control') }; + } + var ret = DYNAMICTOP; + if (bytes != 0) self.alloc(bytes); + return ret; // Previous break location. + } + var Browser={mainLoop:{scheduler:null,shouldPause:false,paused:false,queue:[],pause:function () { + Browser.mainLoop.shouldPause = true; + },resume:function () { + if (Browser.mainLoop.paused) { + Browser.mainLoop.paused = false; + Browser.mainLoop.scheduler(); + } + Browser.mainLoop.shouldPause = false; + },updateStatus:function () { + if (Module['setStatus']) { + var message = Module['statusMessage'] || 'Please wait...'; + var remaining = Browser.mainLoop.remainingBlockers; + var expected = Browser.mainLoop.expectedBlockers; + if (remaining) { + if (remaining < expected) { + Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')'); + } else { + Module['setStatus'](message); + } + } else { + Module['setStatus'](''); + } + } + }},isFullScreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function () { + if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers + if (Browser.initted || ENVIRONMENT_IS_WORKER) return; + Browser.initted = true; + try { + new Blob(); + Browser.hasBlobConstructor = true; + } catch(e) { + Browser.hasBlobConstructor = false; + console.log("warning: no blob constructor, cannot create blobs with mimetypes"); + } + Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null)); + Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : console.log("warning: cannot create object URLs"); + // Support for plugins that can process preloaded files. You can add more of these to + // your app by creating and appending to Module.preloadPlugins. + // + // Each plugin is asked if it can handle a file based on the file's name. If it can, + // it is given the file's raw data. When it is done, it calls a callback with the file's + // (possibly modified) data. For example, a plugin might decompress a file, or it + // might create some side data structure for use later (like an Image element, etc.). + function getMimetype(name) { + return { + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'png': 'image/png', + 'bmp': 'image/bmp', + 'ogg': 'audio/ogg', + 'wav': 'audio/wav', + 'mp3': 'audio/mpeg' + }[name.substr(name.lastIndexOf('.')+1)]; + } + var imagePlugin = {}; + imagePlugin['canHandle'] = function(name) { + return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name); + }; + imagePlugin['handle'] = function(byteArray, name, onload, onerror) { + var b = null; + if (Browser.hasBlobConstructor) { + try { + b = new Blob([byteArray], { type: getMimetype(name) }); + } catch(e) { + Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder'); + } + } + if (!b) { + var bb = new Browser.BlobBuilder(); + bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range + b = bb.getBlob(); + } + var url = Browser.URLObject.createObjectURL(b); + var img = new Image(); + img.onload = function() { + assert(img.complete, 'Image ' + name + ' could not be decoded'); + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + Module["preloadedImages"][name] = canvas; + Browser.URLObject.revokeObjectURL(url); + if (onload) onload(byteArray); + }; + img.onerror = function(event) { + console.log('Image ' + url + ' could not be decoded'); + if (onerror) onerror(); + }; + img.src = url; + }; + Module['preloadPlugins'].push(imagePlugin); + var audioPlugin = {}; + audioPlugin['canHandle'] = function(name) { + return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; + }; + audioPlugin['handle'] = function(byteArray, name, onload, onerror) { + var done = false; + function finish(audio) { + if (done) return; + done = true; + Module["preloadedAudios"][name] = audio; + if (onload) onload(byteArray); + } + function fail() { + if (done) return; + done = true; + Module["preloadedAudios"][name] = new Audio(); // empty shim + if (onerror) onerror(); + } + if (Browser.hasBlobConstructor) { + try { + var b = new Blob([byteArray], { type: getMimetype(name) }); + } catch(e) { + return fail(); + } + var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! + var audio = new Audio(); + audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926 + audio.onerror = function(event) { + if (done) return; + console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach'); + function encode64(data) { + var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + var PAD = '='; + var ret = ''; + var leftchar = 0; + var leftbits = 0; + for (var i = 0; i < data.length; i++) { + leftchar = (leftchar << 8) | data[i]; + leftbits += 8; + while (leftbits >= 6) { + var curr = (leftchar >> (leftbits-6)) & 0x3f; + leftbits -= 6; + ret += BASE[curr]; + } + } + if (leftbits == 2) { + ret += BASE[(leftchar&3) << 4]; + ret += PAD + PAD; + } else if (leftbits == 4) { + ret += BASE[(leftchar&0xf) << 2]; + ret += PAD; + } + return ret; + } + audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray); + finish(audio); // we don't wait for confirmation this worked - but it's worth trying + }; + audio.src = url; + // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror + Browser.safeSetTimeout(function() { + finish(audio); // try to use it even though it is not necessarily ready to play + }, 10000); + } else { + return fail(); + } + }; + Module['preloadPlugins'].push(audioPlugin); + // Canvas event setup + var canvas = Module['canvas']; + canvas.requestPointerLock = canvas['requestPointerLock'] || + canvas['mozRequestPointerLock'] || + canvas['webkitRequestPointerLock']; + canvas.exitPointerLock = document['exitPointerLock'] || + document['mozExitPointerLock'] || + document['webkitExitPointerLock'] || + function(){}; // no-op if function does not exist + canvas.exitPointerLock = canvas.exitPointerLock.bind(document); + function pointerLockChange() { + Browser.pointerLock = document['pointerLockElement'] === canvas || + document['mozPointerLockElement'] === canvas || + document['webkitPointerLockElement'] === canvas; + } + document.addEventListener('pointerlockchange', pointerLockChange, false); + document.addEventListener('mozpointerlockchange', pointerLockChange, false); + document.addEventListener('webkitpointerlockchange', pointerLockChange, false); + if (Module['elementPointerLock']) { + canvas.addEventListener("click", function(ev) { + if (!Browser.pointerLock && canvas.requestPointerLock) { + canvas.requestPointerLock(); + ev.preventDefault(); + } + }, false); + } + },createContext:function (canvas, useWebGL, setInModule) { + var ctx; + try { + if (useWebGL) { + ctx = canvas.getContext('experimental-webgl', { + alpha: false + }); + } else { + ctx = canvas.getContext('2d'); + } + if (!ctx) throw ':('; + } catch (e) { + Module.print('Could not create canvas - ' + e); + return null; + } + if (useWebGL) { + // Set the background of the WebGL canvas to black + canvas.style.backgroundColor = "black"; + // Warn on context loss + canvas.addEventListener('webglcontextlost', function(event) { + alert('WebGL context lost. You will need to reload the page.'); + }, false); + } + if (setInModule) { + Module.ctx = ctx; + Module.useWebGL = useWebGL; + Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); + Browser.init(); + } + return ctx; + },destroyContext:function (canvas, useWebGL, setInModule) {},fullScreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullScreen:function (lockPointer, resizeCanvas) { + Browser.lockPointer = lockPointer; + Browser.resizeCanvas = resizeCanvas; + if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true; + if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false; + var canvas = Module['canvas']; + function fullScreenChange() { + Browser.isFullScreen = false; + if ((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement']) === canvas) { + canvas.cancelFullScreen = document['cancelFullScreen'] || + document['mozCancelFullScreen'] || + document['webkitCancelFullScreen']; + canvas.cancelFullScreen = canvas.cancelFullScreen.bind(document); + if (Browser.lockPointer) canvas.requestPointerLock(); + Browser.isFullScreen = true; + if (Browser.resizeCanvas) Browser.setFullScreenCanvasSize(); + } else if (Browser.resizeCanvas){ + Browser.setWindowedCanvasSize(); + } + if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullScreen); + } + if (!Browser.fullScreenHandlersInstalled) { + Browser.fullScreenHandlersInstalled = true; + document.addEventListener('fullscreenchange', fullScreenChange, false); + document.addEventListener('mozfullscreenchange', fullScreenChange, false); + document.addEventListener('webkitfullscreenchange', fullScreenChange, false); + } + canvas.requestFullScreen = canvas['requestFullScreen'] || + canvas['mozRequestFullScreen'] || + (canvas['webkitRequestFullScreen'] ? function() { canvas['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null); + canvas.requestFullScreen(); + },requestAnimationFrame:function (func) { + if (!window.requestAnimationFrame) { + window.requestAnimationFrame = window['requestAnimationFrame'] || + window['mozRequestAnimationFrame'] || + window['webkitRequestAnimationFrame'] || + window['msRequestAnimationFrame'] || + window['oRequestAnimationFrame'] || + window['setTimeout']; + } + window.requestAnimationFrame(func); + },safeCallback:function (func) { + return function() { + if (!ABORT) return func.apply(null, arguments); + }; + },safeRequestAnimationFrame:function (func) { + return Browser.requestAnimationFrame(function() { + if (!ABORT) func(); + }); + },safeSetTimeout:function (func, timeout) { + return setTimeout(function() { + if (!ABORT) func(); + }, timeout); + },safeSetInterval:function (func, timeout) { + return setInterval(function() { + if (!ABORT) func(); + }, timeout); + },getUserMedia:function (func) { + if(!window.getUserMedia) { + window.getUserMedia = navigator['getUserMedia'] || + navigator['mozGetUserMedia']; + } + window.getUserMedia(func); + },getMovementX:function (event) { + return event['movementX'] || + event['mozMovementX'] || + event['webkitMovementX'] || + 0; + },getMovementY:function (event) { + return event['movementY'] || + event['mozMovementY'] || + event['webkitMovementY'] || + 0; + },mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,calculateMouseEvent:function (event) { // event should be mousemove, mousedown or mouseup + if (Browser.pointerLock) { + // When the pointer is locked, calculate the coordinates + // based on the movement of the mouse. + // Workaround for Firefox bug 764498 + if (event.type != 'mousemove' && + ('mozMovementX' in event)) { + Browser.mouseMovementX = Browser.mouseMovementY = 0; + } else { + Browser.mouseMovementX = Browser.getMovementX(event); + Browser.mouseMovementY = Browser.getMovementY(event); + } + // check if SDL is available + if (typeof SDL != "undefined") { + Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; + Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; + } else { + // just add the mouse delta to the current absolut mouse position + // FIXME: ideally this should be clamped against the canvas size and zero + Browser.mouseX += Browser.mouseMovementX; + Browser.mouseY += Browser.mouseMovementY; + } + } else { + // Otherwise, calculate the movement based on the changes + // in the coordinates. + var rect = Module["canvas"].getBoundingClientRect(); + var x = event.pageX - (window.scrollX + rect.left); + var y = event.pageY - (window.scrollY + rect.top); + // the canvas might be CSS-scaled compared to its backbuffer; + // SDL-using content will want mouse coordinates in terms + // of backbuffer units. + var cw = Module["canvas"].width; + var ch = Module["canvas"].height; + x = x * (cw / rect.width); + y = y * (ch / rect.height); + Browser.mouseMovementX = x - Browser.mouseX; + Browser.mouseMovementY = y - Browser.mouseY; + Browser.mouseX = x; + Browser.mouseY = y; + } + },xhrLoad:function (url, onload, onerror) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = function() { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + } else { + onerror(); + } + }; + xhr.onerror = onerror; + xhr.send(null); + },asyncLoad:function (url, onload, onerror, noRunDep) { + Browser.xhrLoad(url, function(arrayBuffer) { + assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).'); + onload(new Uint8Array(arrayBuffer)); + if (!noRunDep) removeRunDependency('al ' + url); + }, function(event) { + if (onerror) { + onerror(); + } else { + throw 'Loading data file "' + url + '" failed.'; + } + }); + if (!noRunDep) addRunDependency('al ' + url); + },resizeListeners:[],updateResizeListeners:function () { + var canvas = Module['canvas']; + Browser.resizeListeners.forEach(function(listener) { + listener(canvas.width, canvas.height); + }); + },setCanvasSize:function (width, height, noUpdates) { + var canvas = Module['canvas']; + canvas.width = width; + canvas.height = height; + if (!noUpdates) Browser.updateResizeListeners(); + },windowedWidth:0,windowedHeight:0,setFullScreenCanvasSize:function () { + var canvas = Module['canvas']; + this.windowedWidth = canvas.width; + this.windowedHeight = canvas.height; + canvas.width = screen.width; + canvas.height = screen.height; + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags | 0x00800000; // set SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },setWindowedCanvasSize:function () { + var canvas = Module['canvas']; + canvas.width = this.windowedWidth; + canvas.height = this.windowedHeight; + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + }}; +__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });__ATEXIT__.push({ func: function() { FS.quit() } });Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice; +___errno_state = Runtime.staticAlloc(4); HEAP32[((___errno_state)>>2)]=0; +Module["requestFullScreen"] = function(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) }; + Module["requestAnimationFrame"] = function(func) { Browser.requestAnimationFrame(func) }; + Module["pauseMainLoop"] = function() { Browser.mainLoop.pause() }; + Module["resumeMainLoop"] = function() { Browser.mainLoop.resume() }; + Module["getUserMedia"] = function() { Browser.getUserMedia() } +STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP); +staticSealed = true; // seal the static portion of memory +STACK_MAX = STACK_BASE + 5242880; +DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX); +assert(DYNAMIC_BASE < TOTAL_MEMORY); // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY +var Math_min = Math.min; +function invoke_ii(index,a1) { + try { + return Module["dynCall_ii"](index,a1); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function invoke_vi(index,a1) { + try { + Module["dynCall_vi"](index,a1); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function invoke_vii(index,a1,a2) { + try { + Module["dynCall_vii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function invoke_iiii(index,a1,a2,a3) { + try { + return Module["dynCall_iiii"](index,a1,a2,a3); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function invoke_v(index) { + try { + Module["dynCall_v"](index); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function invoke_iii(index,a1,a2) { + try { + return Module["dynCall_iii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} +function asmPrintInt(x, y) { + Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack); +} +function asmPrintFloat(x, y) { + Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack); +} +// EMSCRIPTEN_START_ASM +var asm=(function(global,env,buffer){"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=+env.NaN;var n=+env.Infinity;var o=0;var p=0;var q=0;var r=0;var s=0,t=0,u=0,v=0,w=0.0,x=0,y=0,z=0,A=0.0;var B=0;var C=0;var D=0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=global.Math.floor;var M=global.Math.abs;var N=global.Math.sqrt;var O=global.Math.pow;var P=global.Math.cos;var Q=global.Math.sin;var R=global.Math.tan;var S=global.Math.acos;var T=global.Math.asin;var U=global.Math.atan;var V=global.Math.atan2;var W=global.Math.exp;var X=global.Math.log;var Y=global.Math.ceil;var Z=global.Math.imul;var _=env.abort;var $=env.assert;var aa=env.asmPrintInt;var ab=env.asmPrintFloat;var ac=env.min;var ad=env.invoke_ii;var ae=env.invoke_vi;var af=env.invoke_vii;var ag=env.invoke_iiii;var ah=env.invoke_v;var ai=env.invoke_iii;var aj=env._llvm_lifetime_end;var ak=env._lseek;var al=env._sysconf;var am=env._abort;var an=env._close;var ao=env._pread;var ap=env._open;var aq=env.___setErrNo;var ar=env._send;var as=env._write;var at=env._read;var au=env._recv;var av=env._pwrite;var aw=env._sbrk;var ax=env._strerror_r;var ay=env.___errno_location;var az=env._strerror;var aA=env._llvm_lifetime_start;var aB=env._llvm_bswap_i32;var aC=env._time; +// EMSCRIPTEN_START_FUNCS +function aJ(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+7>>3<<3;return b|0}function aK(){return i|0}function aL(a){a=a|0;i=a}function aM(a,b){a=a|0;b=b|0;if((o|0)==0){o=a;p=b}}function aN(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0]}function aO(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0];a[k+4|0]=a[b+4|0];a[k+5|0]=a[b+5|0];a[k+6|0]=a[b+6|0];a[k+7|0]=a[b+7|0]}function aP(a){a=a|0;B=a}function aQ(a){a=a|0;C=a}function aR(a){a=a|0;D=a}function aS(a){a=a|0;E=a}function aT(a){a=a|0;F=a}function aU(a){a=a|0;G=a}function aV(a){a=a|0;H=a}function aW(a){a=a|0;I=a}function aX(a){a=a|0;J=a}function aY(a){a=a|0;K=a}function aZ(){}function a_(a,b,c){a=a|0;b=b|0;c=c|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0;e=a>>>16;f=a&65535;if((c|0)==1){a=(d[b]|0)+f|0;g=a>>>0>65520?a-65521|0:a;a=g+e|0;h=(a>>>0>65520?a+15|0:a)<<16|g;return h|0}if((b|0)==0){h=1;return h|0}if(c>>>0<16){if((c|0)==0){i=f;j=e}else{g=f;a=b;k=c;l=e;while(1){m=k-1|0;n=(d[a]|0)+g|0;o=n+l|0;if((m|0)==0){i=n;j=o;break}else{g=n;a=a+1|0;k=m;l=o}}}h=((j>>>0)%65521|0)<<16|(i>>>0>65520?i-65521|0:i);return h|0}do{if(c>>>0>5551){i=f;j=b;l=c;k=e;do{l=l-5552|0;a=347;g=k;o=j;m=i;while(1){n=(d[o]|0)+m|0;p=n+(d[o+1|0]|0)|0;q=p+(d[o+2|0]|0)|0;r=q+(d[o+3|0]|0)|0;s=r+(d[o+4|0]|0)|0;t=s+(d[o+5|0]|0)|0;u=t+(d[o+6|0]|0)|0;v=u+(d[o+7|0]|0)|0;w=v+(d[o+8|0]|0)|0;x=w+(d[o+9|0]|0)|0;y=x+(d[o+10|0]|0)|0;z=y+(d[o+11|0]|0)|0;A=z+(d[o+12|0]|0)|0;B=A+(d[o+13|0]|0)|0;C=B+(d[o+14|0]|0)|0;D=C+(d[o+15|0]|0)|0;E=n+g+p+q+r+s+t+u+v+w+x+y+z+A+B+C+D|0;C=a-1|0;if((C|0)==0){break}else{a=C;g=E;o=o+16|0;m=D}}j=j+5552|0;i=(D>>>0)%65521|0;k=(E>>>0)%65521|0;}while(l>>>0>5551);if((l|0)==0){F=k;G=i;break}if(l>>>0>15){H=i;I=j;J=l;K=k;L=15}else{M=i;N=j;O=l;P=k;L=16}}else{H=f;I=b;J=c;K=e;L=15}}while(0);if((L|0)==15){while(1){L=0;Q=J-16|0;e=(d[I]|0)+H|0;c=e+(d[I+1|0]|0)|0;b=c+(d[I+2|0]|0)|0;f=b+(d[I+3|0]|0)|0;E=f+(d[I+4|0]|0)|0;D=E+(d[I+5|0]|0)|0;m=D+(d[I+6|0]|0)|0;o=m+(d[I+7|0]|0)|0;g=o+(d[I+8|0]|0)|0;a=g+(d[I+9|0]|0)|0;C=a+(d[I+10|0]|0)|0;B=C+(d[I+11|0]|0)|0;A=B+(d[I+12|0]|0)|0;z=A+(d[I+13|0]|0)|0;y=z+(d[I+14|0]|0)|0;R=y+(d[I+15|0]|0)|0;S=e+K+c+b+f+E+D+m+o+g+a+C+B+A+z+y+R|0;T=I+16|0;if(Q>>>0>15){H=R;I=T;J=Q;K=S;L=15}else{break}}if((Q|0)==0){U=R;V=S;L=17}else{M=R;N=T;O=Q;P=S;L=16}}if((L|0)==16){while(1){L=0;S=O-1|0;Q=(d[N]|0)+M|0;T=Q+P|0;if((S|0)==0){U=Q;V=T;L=17;break}else{M=Q;N=N+1|0;O=S;P=T;L=16}}}if((L|0)==17){F=(V>>>0)%65521|0;G=(U>>>0)%65521|0}h=F<<16|G;return h|0}function a$(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;if((b|0)==0){f=0;return f|0}g=~a;L39:do{if((e|0)==0){h=g}else{a=b;i=e;j=g;while(1){if((a&3|0)==0){break}k=c[4200+(((d[a]|0)^j&255)<<2)>>2]^j>>>8;l=i-1|0;if((l|0)==0){h=k;break L39}else{a=a+1|0;i=l;j=k}}k=a;if(i>>>0>31){l=i;m=j;n=k;while(1){o=c[n>>2]^m;p=c[6248+((o>>>8&255)<<2)>>2]^c[7272+((o&255)<<2)>>2]^c[5224+((o>>>16&255)<<2)>>2]^c[4200+(o>>>24<<2)>>2]^c[n+4>>2];o=c[6248+((p>>>8&255)<<2)>>2]^c[7272+((p&255)<<2)>>2]^c[5224+((p>>>16&255)<<2)>>2]^c[4200+(p>>>24<<2)>>2]^c[n+8>>2];p=c[6248+((o>>>8&255)<<2)>>2]^c[7272+((o&255)<<2)>>2]^c[5224+((o>>>16&255)<<2)>>2]^c[4200+(o>>>24<<2)>>2]^c[n+12>>2];o=c[6248+((p>>>8&255)<<2)>>2]^c[7272+((p&255)<<2)>>2]^c[5224+((p>>>16&255)<<2)>>2]^c[4200+(p>>>24<<2)>>2]^c[n+16>>2];p=c[6248+((o>>>8&255)<<2)>>2]^c[7272+((o&255)<<2)>>2]^c[5224+((o>>>16&255)<<2)>>2]^c[4200+(o>>>24<<2)>>2]^c[n+20>>2];o=c[6248+((p>>>8&255)<<2)>>2]^c[7272+((p&255)<<2)>>2]^c[5224+((p>>>16&255)<<2)>>2]^c[4200+(p>>>24<<2)>>2]^c[n+24>>2];p=n+32|0;q=c[6248+((o>>>8&255)<<2)>>2]^c[7272+((o&255)<<2)>>2]^c[5224+((o>>>16&255)<<2)>>2]^c[4200+(o>>>24<<2)>>2]^c[n+28>>2];o=c[6248+((q>>>8&255)<<2)>>2]^c[7272+((q&255)<<2)>>2]^c[5224+((q>>>16&255)<<2)>>2]^c[4200+(q>>>24<<2)>>2];q=l-32|0;if(q>>>0>31){l=q;m=o;n=p}else{r=q;s=o;t=p;break}}}else{r=i;s=j;t=k}if(r>>>0>3){n=r;m=s;l=t;while(1){a=l+4|0;p=c[l>>2]^m;o=c[6248+((p>>>8&255)<<2)>>2]^c[7272+((p&255)<<2)>>2]^c[5224+((p>>>16&255)<<2)>>2]^c[4200+(p>>>24<<2)>>2];p=n-4|0;if(p>>>0>3){n=p;m=o;l=a}else{u=p;v=o;w=a;break}}}else{u=r;v=s;w=t}if((u|0)==0){h=v;break}l=v;m=u;n=w;while(1){k=c[4200+(((d[n]|0)^l&255)<<2)>>2]^l>>>8;j=m-1|0;if((j|0)==0){h=k;break}else{l=k;m=j;n=n+1|0}}}}while(0);f=~h;return f|0}function a0(b,d,e,f,g,h,i,j){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0;if((i|0)==0){k=-6;return k|0}if(!((a[i]|0)==49&(j|0)==56)){k=-6;return k|0}if((b|0)==0){k=-2;return k|0}j=b+24|0;c[j>>2]=0;i=b+32|0;l=c[i>>2]|0;if((l|0)==0){c[i>>2]=6;c[b+40>>2]=0;m=6}else{m=l}l=b+36|0;if((c[l>>2]|0)==0){c[l>>2]=2}l=(d|0)==-1?6:d;if((f|0)<0){n=0;o=-f|0}else{d=(f|0)>15;n=d?2:1;o=d?f-16|0:f}if(!((g-1|0)>>>0<9&(e|0)==8)){k=-2;return k|0}if((o-8|0)>>>0>7|l>>>0>9|h>>>0>4){k=-2;return k|0}e=(o|0)==8?9:o;o=b+40|0;f=aG[m&7](c[o>>2]|0,1,5828)|0;if((f|0)==0){k=-4;return k|0}c[b+28>>2]=f;c[f>>2]=b;c[f+24>>2]=n;c[f+28>>2]=0;c[f+48>>2]=e;n=1<>2]=n;c[f+52>>2]=n-1;m=g+7|0;c[f+80>>2]=m;d=1<>2]=d;c[f+84>>2]=d-1;c[f+88>>2]=((g+9|0)>>>0)/3|0;d=f+56|0;c[d>>2]=aG[c[i>>2]&7](c[o>>2]|0,n,2)|0;n=aG[c[i>>2]&7](c[o>>2]|0,c[e>>2]|0,2)|0;p=f+64|0;c[p>>2]=n;bI(n|0,0,c[e>>2]<<1|0);e=f+68|0;c[e>>2]=aG[c[i>>2]&7](c[o>>2]|0,c[m>>2]|0,2)|0;c[f+5824>>2]=0;m=1<>2]=m;n=aG[c[i>>2]&7](c[o>>2]|0,m,4)|0;m=n;c[f+8>>2]=n;o=c[g>>2]|0;c[f+12>>2]=o<<2;do{if((c[d>>2]|0)!=0){if((c[p>>2]|0)==0){break}if((c[e>>2]|0)==0|(n|0)==0){break}c[f+5796>>2]=m+(o>>>1<<1);c[f+5784>>2]=n+(o*3|0);c[f+132>>2]=l;c[f+136>>2]=h;a[f+36|0]=8;k=a2(b)|0;return k|0}}while(0);c[f+4>>2]=666;c[j>>2]=c[8];a1(b)|0;k=-4;return k|0}function a1(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;if((a|0)==0){b=-2;return b|0}d=a+28|0;e=c[d>>2]|0;if((e|0)==0){b=-2;return b|0}f=c[e+4>>2]|0;if(!((f|0)==666|(f|0)==113|(f|0)==103|(f|0)==91|(f|0)==73|(f|0)==69|(f|0)==42)){b=-2;return b|0}g=c[e+8>>2]|0;if((g|0)==0){h=e}else{aF[c[a+36>>2]&3](c[a+40>>2]|0,g);h=c[d>>2]|0}g=c[h+68>>2]|0;if((g|0)==0){i=h}else{aF[c[a+36>>2]&3](c[a+40>>2]|0,g);i=c[d>>2]|0}g=c[i+64>>2]|0;if((g|0)==0){j=i}else{aF[c[a+36>>2]&3](c[a+40>>2]|0,g);j=c[d>>2]|0}g=c[j+56>>2]|0;i=a+36|0;if((g|0)==0){k=j;l=a+40|0}else{j=a+40|0;aF[c[i>>2]&3](c[j>>2]|0,g);k=c[d>>2]|0;l=j}aF[c[i>>2]&3](c[l>>2]|0,k);c[d>>2]=0;b=(f|0)==113?-3:0;return b|0}function a2(a){a=a|0;var d=0,f=0,g=0,h=0,i=0,j=0,k=0;if((a|0)==0){d=-2;return d|0}f=c[a+28>>2]|0;if((f|0)==0){d=-2;return d|0}if((c[a+32>>2]|0)==0){d=-2;return d|0}if((c[a+36>>2]|0)==0){d=-2;return d|0}c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+44>>2]=2;c[f+20>>2]=0;c[f+16>>2]=c[f+8>>2];g=f+24|0;h=c[g>>2]|0;if((h|0)<0){i=-h|0;c[g>>2]=i;j=i}else{j=h}c[f+4>>2]=(j|0)!=0?42:113;if((j|0)==2){k=a$(0,0,0)|0}else{k=a_(0,0,0)|0}c[a+48>>2]=k;c[f+40>>2]=0;bw(f);c[f+60>>2]=c[f+44>>2]<<1;k=f+76|0;a=f+68|0;b[(c[a>>2]|0)+((c[k>>2]|0)-1<<1)>>1]=0;bI(c[a>>2]|0,0,(c[k>>2]<<1)-2|0);k=c[f+132>>2]|0;c[f+128>>2]=e[12394+(k*12|0)>>1]|0;c[f+140>>2]=e[12392+(k*12|0)>>1]|0;c[f+144>>2]=e[12396+(k*12|0)>>1]|0;c[f+124>>2]=e[12398+(k*12|0)>>1]|0;c[f+108>>2]=0;c[f+92>>2]=0;c[f+116>>2]=0;c[f+120>>2]=2;c[f+96>>2]=2;c[f+112>>2]=0;c[f+104>>2]=0;c[f+72>>2]=0;d=0;return d|0}function a3(e,f){e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ab=0,ac=0,ad=0,ae=0,af=0,ag=0,ah=0,ai=0,aj=0,ak=0,al=0,am=0,an=0,ao=0,ap=0,aq=0,ar=0,as=0,at=0,au=0,av=0,aw=0,ax=0,ay=0,az=0,aA=0,aB=0;if((e|0)==0){g=-2;return g|0}h=e+28|0;i=c[h>>2]|0;if((i|0)==0|f>>>0>5){g=-2;return g|0}j=e+12|0;do{if((c[j>>2]|0)!=0){if((c[e>>2]|0)==0){if((c[e+4>>2]|0)!=0){break}}k=i+4|0;l=c[k>>2]|0;m=(f|0)==4;if(!((l|0)!=666|m)){break}n=e+16|0;if((c[n>>2]|0)==0){c[e+24>>2]=c[9];g=-5;return g|0}o=i|0;c[o>>2]=e;p=i+40|0;q=c[p>>2]|0;c[p>>2]=f;do{if((l|0)==42){if((c[i+24>>2]|0)!=2){r=(c[i+48>>2]<<12)-30720|0;do{if((c[i+136>>2]|0)>1){s=0}else{t=c[i+132>>2]|0;if((t|0)<2){s=0;break}if((t|0)<6){s=64;break}s=(t|0)==6?128:192}}while(0);t=s|r;u=i+108|0;v=(c[u>>2]|0)==0?t:t|32;t=(v|((v>>>0)%31|0))^31;c[k>>2]=113;v=i+20|0;w=c[v>>2]|0;c[v>>2]=w+1;x=i+8|0;a[(c[x>>2]|0)+w|0]=t>>>8&255;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[x>>2]|0)+w|0]=t&255;t=e+48|0;if((c[u>>2]|0)!=0){u=c[t>>2]|0;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[x>>2]|0)+w|0]=u>>>24&255;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[x>>2]|0)+w|0]=u>>>16&255;u=c[t>>2]|0;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[x>>2]|0)+w|0]=u>>>8&255;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[x>>2]|0)+w|0]=u&255}c[t>>2]=a_(0,0,0)|0;y=c[k>>2]|0;z=131;break}t=e+48|0;c[t>>2]=a$(0,0,0)|0;u=i+20|0;w=c[u>>2]|0;c[u>>2]=w+1;x=i+8|0;a[(c[x>>2]|0)+w|0]=31;w=c[u>>2]|0;c[u>>2]=w+1;a[(c[x>>2]|0)+w|0]=-117;w=c[u>>2]|0;c[u>>2]=w+1;a[(c[x>>2]|0)+w|0]=8;w=i+28|0;v=c[w>>2]|0;if((v|0)==0){A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[i+132>>2]|0;do{if((A|0)==9){B=2}else{if((c[i+136>>2]|0)>1){B=4;break}B=(A|0)<2?4:0}}while(0);A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=B;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=3;c[k>>2]=113;break}A=((c[v+44>>2]|0)!=0?2:0)|(c[v>>2]|0)!=0|((c[v+16>>2]|0)==0?0:4)|((c[v+28>>2]|0)==0?0:8)|((c[v+36>>2]|0)==0?0:16);r=c[u>>2]|0;c[u>>2]=r+1;a[(c[x>>2]|0)+r|0]=A;A=c[(c[w>>2]|0)+4>>2]&255;r=c[u>>2]|0;c[u>>2]=r+1;a[(c[x>>2]|0)+r|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>8&255;r=c[u>>2]|0;c[u>>2]=r+1;a[(c[x>>2]|0)+r|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>16&255;r=c[u>>2]|0;c[u>>2]=r+1;a[(c[x>>2]|0)+r|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>24&255;r=c[u>>2]|0;c[u>>2]=r+1;a[(c[x>>2]|0)+r|0]=A;A=c[i+132>>2]|0;do{if((A|0)==9){C=2}else{if((c[i+136>>2]|0)>1){C=4;break}C=(A|0)<2?4:0}}while(0);A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=C;A=c[(c[w>>2]|0)+12>>2]&255;v=c[u>>2]|0;c[u>>2]=v+1;a[(c[x>>2]|0)+v|0]=A;A=c[w>>2]|0;if((c[A+16>>2]|0)==0){D=A}else{v=c[A+20>>2]&255;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=v;v=(c[(c[w>>2]|0)+20>>2]|0)>>>8&255;A=c[u>>2]|0;c[u>>2]=A+1;a[(c[x>>2]|0)+A|0]=v;D=c[w>>2]|0}if((c[D+44>>2]|0)!=0){c[t>>2]=a$(c[t>>2]|0,c[x>>2]|0,c[u>>2]|0)|0}c[i+32>>2]=0;c[k>>2]=69;E=w;z=133}else{y=l;z=131}}while(0);do{if((z|0)==131){if((y|0)!=69){F=y;z=154;break}E=i+28|0;z=133}}while(0);do{if((z|0)==133){l=c[E>>2]|0;if((c[l+16>>2]|0)==0){c[k>>2]=73;G=l;z=156;break}v=i+20|0;A=c[v>>2]|0;r=i+32|0;H=c[r>>2]|0;L193:do{if(H>>>0<(c[l+20>>2]&65535)>>>0){I=i+12|0;J=e+48|0;K=i+8|0;L=e+20|0;M=A;N=l;O=A;P=H;while(1){if((O|0)==(c[I>>2]|0)){if((c[N+44>>2]|0)!=0&O>>>0>M>>>0){c[J>>2]=a$(c[J>>2]|0,(c[K>>2]|0)+M|0,O-M|0)|0}Q=c[h>>2]|0;R=c[Q+20>>2]|0;S=c[n>>2]|0;T=R>>>0>S>>>0?S:R;do{if((T|0)!=0){R=c[j>>2]|0;S=c[Q+16>>2]|0;bJ(R|0,S|0,T)|0;c[j>>2]=(c[j>>2]|0)+T;S=(c[h>>2]|0)+16|0;c[S>>2]=(c[S>>2]|0)+T;c[L>>2]=(c[L>>2]|0)+T;c[n>>2]=(c[n>>2]|0)-T;S=(c[h>>2]|0)+20|0;c[S>>2]=(c[S>>2]|0)-T;S=c[h>>2]|0;if((c[S+20>>2]|0)!=0){break}c[S+16>>2]=c[S+8>>2]}}while(0);U=c[v>>2]|0;if((U|0)==(c[I>>2]|0)){break}V=U;W=U;X=c[r>>2]|0;Y=c[E>>2]|0}else{V=M;W=O;X=P;Y=N}T=a[(c[Y+16>>2]|0)+X|0]|0;c[v>>2]=W+1;a[(c[K>>2]|0)+W|0]=T;T=(c[r>>2]|0)+1|0;c[r>>2]=T;Q=c[E>>2]|0;if(T>>>0>=(c[Q+20>>2]&65535)>>>0){Z=V;_=Q;break L193}M=V;N=Q;O=c[v>>2]|0;P=T}Z=U;_=c[E>>2]|0}else{Z=A;_=l}}while(0);do{if((c[_+44>>2]|0)==0){$=_}else{l=c[v>>2]|0;if(l>>>0<=Z>>>0){$=_;break}A=e+48|0;c[A>>2]=a$(c[A>>2]|0,(c[i+8>>2]|0)+Z|0,l-Z|0)|0;$=c[E>>2]|0}}while(0);if((c[r>>2]|0)==(c[$+20>>2]|0)){c[r>>2]=0;c[k>>2]=73;G=$;z=156;break}else{F=c[k>>2]|0;z=154;break}}}while(0);do{if((z|0)==154){if((F|0)!=73){aa=F;z=175;break}G=c[i+28>>2]|0;z=156}}while(0);do{if((z|0)==156){v=i+28|0;if((c[G+28>>2]|0)==0){c[k>>2]=91;ab=v;z=177;break}l=i+20|0;A=c[l>>2]|0;H=i+12|0;w=e+48|0;u=i+8|0;x=e+20|0;t=i+32|0;P=A;O=A;while(1){if((O|0)==(c[H>>2]|0)){if((c[(c[v>>2]|0)+44>>2]|0)!=0&O>>>0>P>>>0){c[w>>2]=a$(c[w>>2]|0,(c[u>>2]|0)+P|0,O-P|0)|0}A=c[h>>2]|0;N=c[A+20>>2]|0;M=c[n>>2]|0;K=N>>>0>M>>>0?M:N;do{if((K|0)!=0){N=c[j>>2]|0;M=c[A+16>>2]|0;bJ(N|0,M|0,K)|0;c[j>>2]=(c[j>>2]|0)+K;M=(c[h>>2]|0)+16|0;c[M>>2]=(c[M>>2]|0)+K;c[x>>2]=(c[x>>2]|0)+K;c[n>>2]=(c[n>>2]|0)-K;M=(c[h>>2]|0)+20|0;c[M>>2]=(c[M>>2]|0)-K;M=c[h>>2]|0;if((c[M+20>>2]|0)!=0){break}c[M+16>>2]=c[M+8>>2]}}while(0);K=c[l>>2]|0;if((K|0)==(c[H>>2]|0)){ac=1;ad=K;break}else{ae=K;af=K}}else{ae=P;af=O}K=c[t>>2]|0;c[t>>2]=K+1;ag=a[(c[(c[v>>2]|0)+28>>2]|0)+K|0]|0;c[l>>2]=af+1;a[(c[u>>2]|0)+af|0]=ag;if(ag<<24>>24==0){z=167;break}P=ae;O=c[l>>2]|0}if((z|0)==167){ac=ag&255;ad=ae}do{if((c[(c[v>>2]|0)+44>>2]|0)!=0){O=c[l>>2]|0;if(O>>>0<=ad>>>0){break}c[w>>2]=a$(c[w>>2]|0,(c[u>>2]|0)+ad|0,O-ad|0)|0}}while(0);if((ac|0)==0){c[t>>2]=0;c[k>>2]=91;ab=v;z=177;break}else{aa=c[k>>2]|0;z=175;break}}}while(0);do{if((z|0)==175){if((aa|0)!=91){ah=aa;z=196;break}ab=i+28|0;z=177}}while(0);do{if((z|0)==177){if((c[(c[ab>>2]|0)+36>>2]|0)==0){c[k>>2]=103;ai=ab;z=198;break}u=i+20|0;w=c[u>>2]|0;l=i+12|0;O=e+48|0;P=i+8|0;H=e+20|0;x=i+32|0;r=w;K=w;while(1){if((K|0)==(c[l>>2]|0)){if((c[(c[ab>>2]|0)+44>>2]|0)!=0&K>>>0>r>>>0){c[O>>2]=a$(c[O>>2]|0,(c[P>>2]|0)+r|0,K-r|0)|0}w=c[h>>2]|0;A=c[w+20>>2]|0;M=c[n>>2]|0;N=A>>>0>M>>>0?M:A;do{if((N|0)!=0){A=c[j>>2]|0;M=c[w+16>>2]|0;bJ(A|0,M|0,N)|0;c[j>>2]=(c[j>>2]|0)+N;M=(c[h>>2]|0)+16|0;c[M>>2]=(c[M>>2]|0)+N;c[H>>2]=(c[H>>2]|0)+N;c[n>>2]=(c[n>>2]|0)-N;M=(c[h>>2]|0)+20|0;c[M>>2]=(c[M>>2]|0)-N;M=c[h>>2]|0;if((c[M+20>>2]|0)!=0){break}c[M+16>>2]=c[M+8>>2]}}while(0);N=c[u>>2]|0;if((N|0)==(c[l>>2]|0)){aj=1;ak=N;break}else{al=N;am=N}}else{al=r;am=K}N=c[x>>2]|0;c[x>>2]=N+1;an=a[(c[(c[ab>>2]|0)+36>>2]|0)+N|0]|0;c[u>>2]=am+1;a[(c[P>>2]|0)+am|0]=an;if(an<<24>>24==0){z=188;break}r=al;K=c[u>>2]|0}if((z|0)==188){aj=an&255;ak=al}do{if((c[(c[ab>>2]|0)+44>>2]|0)!=0){K=c[u>>2]|0;if(K>>>0<=ak>>>0){break}c[O>>2]=a$(c[O>>2]|0,(c[P>>2]|0)+ak|0,K-ak|0)|0}}while(0);if((aj|0)==0){c[k>>2]=103;ai=ab;z=198;break}else{ah=c[k>>2]|0;z=196;break}}}while(0);do{if((z|0)==196){if((ah|0)!=103){break}ai=i+28|0;z=198}}while(0);do{if((z|0)==198){if((c[(c[ai>>2]|0)+44>>2]|0)==0){c[k>>2]=113;break}P=i+20|0;O=i+12|0;do{if(((c[P>>2]|0)+2|0)>>>0>(c[O>>2]|0)>>>0){u=c[h>>2]|0;K=c[u+20>>2]|0;r=c[n>>2]|0;x=K>>>0>r>>>0?r:K;if((x|0)==0){break}K=c[j>>2]|0;r=c[u+16>>2]|0;bJ(K|0,r|0,x)|0;c[j>>2]=(c[j>>2]|0)+x;r=(c[h>>2]|0)+16|0;c[r>>2]=(c[r>>2]|0)+x;r=e+20|0;c[r>>2]=(c[r>>2]|0)+x;c[n>>2]=(c[n>>2]|0)-x;r=(c[h>>2]|0)+20|0;c[r>>2]=(c[r>>2]|0)-x;x=c[h>>2]|0;if((c[x+20>>2]|0)!=0){break}c[x+16>>2]=c[x+8>>2]}}while(0);x=c[P>>2]|0;if((x+2|0)>>>0>(c[O>>2]|0)>>>0){break}r=e+48|0;K=c[r>>2]&255;c[P>>2]=x+1;u=i+8|0;a[(c[u>>2]|0)+x|0]=K;K=(c[r>>2]|0)>>>8&255;x=c[P>>2]|0;c[P>>2]=x+1;a[(c[u>>2]|0)+x|0]=K;c[r>>2]=a$(0,0,0)|0;c[k>>2]=113}}while(0);r=i+20|0;do{if((c[r>>2]|0)==0){if((c[e+4>>2]|0)!=0){break}if(!((q|0)>=(f|0)&(f|0)!=4)){break}c[e+24>>2]=c[9];g=-5;return g|0}else{K=c[h>>2]|0;x=c[K+20>>2]|0;u=c[n>>2]|0;l=x>>>0>u>>>0?u:x;if((l|0)==0){ao=u}else{u=c[j>>2]|0;x=c[K+16>>2]|0;bJ(u|0,x|0,l)|0;c[j>>2]=(c[j>>2]|0)+l;x=(c[h>>2]|0)+16|0;c[x>>2]=(c[x>>2]|0)+l;x=e+20|0;c[x>>2]=(c[x>>2]|0)+l;c[n>>2]=(c[n>>2]|0)-l;x=(c[h>>2]|0)+20|0;c[x>>2]=(c[x>>2]|0)-l;l=c[h>>2]|0;if((c[l+20>>2]|0)==0){c[l+16>>2]=c[l+8>>2]}ao=c[n>>2]|0}if((ao|0)!=0){break}c[p>>2]=-1;g=0;return g|0}}while(0);q=(c[k>>2]|0)==666;l=(c[e+4>>2]|0)==0;do{if(q){if(l){z=220;break}c[e+24>>2]=c[9];g=-5;return g|0}else{if(l){z=220}else{z=223}}}while(0);do{if((z|0)==220){if((c[i+116>>2]|0)!=0){z=223;break}if((f|0)==0){g=0;return g|0}else{if(q){break}else{z=223;break}}}}while(0);L321:do{if((z|0)==223){q=c[i+136>>2]|0;L323:do{if((q|0)==2){l=i+116|0;x=i+96|0;u=i+108|0;K=i+56|0;H=i+5792|0;v=i+5796|0;t=i+5784|0;N=i+5788|0;w=i+92|0;while(1){if((c[l>>2]|0)==0){a4(i);if((c[l>>2]|0)==0){break}}c[x>>2]=0;M=a[(c[K>>2]|0)+(c[u>>2]|0)|0]|0;b[(c[v>>2]|0)+(c[H>>2]<<1)>>1]=0;A=c[H>>2]|0;c[H>>2]=A+1;a[(c[t>>2]|0)+A|0]=M;A=i+148+((M&255)<<2)|0;b[A>>1]=(b[A>>1]|0)+1&65535;A=(c[H>>2]|0)==((c[N>>2]|0)-1|0);c[l>>2]=(c[l>>2]|0)-1;M=(c[u>>2]|0)+1|0;c[u>>2]=M;if(!A){continue}A=c[w>>2]|0;if((A|0)>-1){ap=(c[K>>2]|0)+A|0}else{ap=0}by(i,ap,M-A|0,0);c[w>>2]=c[u>>2];A=c[o>>2]|0;M=A+28|0;I=c[M>>2]|0;L=c[I+20>>2]|0;J=A+16|0;T=c[J>>2]|0;Q=L>>>0>T>>>0?T:L;do{if((Q|0)!=0){L=A+12|0;T=c[L>>2]|0;S=c[I+16>>2]|0;bJ(T|0,S|0,Q)|0;c[L>>2]=(c[L>>2]|0)+Q;L=(c[M>>2]|0)+16|0;c[L>>2]=(c[L>>2]|0)+Q;L=A+20|0;c[L>>2]=(c[L>>2]|0)+Q;c[J>>2]=(c[J>>2]|0)-Q;L=(c[M>>2]|0)+20|0;c[L>>2]=(c[L>>2]|0)-Q;L=c[M>>2]|0;if((c[L+20>>2]|0)!=0){break}c[L+16>>2]=c[L+8>>2]}}while(0);if((c[(c[o>>2]|0)+16>>2]|0)==0){break L323}}if((f|0)==0){break}l=c[w>>2]|0;if((l|0)>-1){aq=(c[K>>2]|0)+l|0}else{aq=0}by(i,aq,(c[u>>2]|0)-l|0,m&1);c[w>>2]=c[u>>2];l=c[o>>2]|0;N=l+28|0;H=c[N>>2]|0;t=c[H+20>>2]|0;v=l+16|0;x=c[v>>2]|0;M=t>>>0>x>>>0?x:t;do{if((M|0)!=0){t=l+12|0;x=c[t>>2]|0;Q=c[H+16>>2]|0;bJ(x|0,Q|0,M)|0;c[t>>2]=(c[t>>2]|0)+M;t=(c[N>>2]|0)+16|0;c[t>>2]=(c[t>>2]|0)+M;t=l+20|0;c[t>>2]=(c[t>>2]|0)+M;c[v>>2]=(c[v>>2]|0)-M;t=(c[N>>2]|0)+20|0;c[t>>2]=(c[t>>2]|0)-M;t=c[N>>2]|0;if((c[t+20>>2]|0)!=0){break}c[t+16>>2]=c[t+8>>2]}}while(0);if((c[(c[o>>2]|0)+16>>2]|0)==0){ar=m?2:0;z=281;break}else{ar=m?3:1;z=281;break}}else if((q|0)==3){N=i+116|0;M=(f|0)==0;v=i+96|0;l=i+108|0;H=i+5792|0;u=i+5796|0;w=i+5784|0;K=i+2440+(d[14184]<<2)|0;t=i+5788|0;Q=i+56|0;x=i+92|0;L351:while(1){J=c[N>>2]|0;do{if(J>>>0<258){a4(i);A=c[N>>2]|0;if(A>>>0<258&M){break L323}if((A|0)==0){break L351}c[v>>2]=0;if(A>>>0>2){as=A;z=250;break}at=c[l>>2]|0;z=265}else{c[v>>2]=0;as=J;z=250}}while(0);do{if((z|0)==250){z=0;J=c[l>>2]|0;if((J|0)==0){at=0;z=265;break}A=c[Q>>2]|0;I=a[A+(J-1)|0]|0;if(I<<24>>24!=(a[A+J|0]|0)){at=J;z=265;break}if(I<<24>>24!=(a[A+(J+1)|0]|0)){at=J;z=265;break}L=A+(J+2)|0;if(I<<24>>24!=(a[L]|0)){at=J;z=265;break}S=A+(J+258)|0;A=L;while(1){L=A+1|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+2|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+3|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+4|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+5|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+6|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+7|0;if(I<<24>>24!=(a[L]|0)){au=L;break}L=A+8|0;if(I<<24>>24==(a[L]|0)&L>>>0>>0){A=L}else{au=L;break}}A=au-S+258|0;I=A>>>0>as>>>0?as:A;c[v>>2]=I;if(I>>>0<=2){at=J;z=265;break}A=I+253|0;b[(c[u>>2]|0)+(c[H>>2]<<1)>>1]=1;I=c[H>>2]|0;c[H>>2]=I+1;a[(c[w>>2]|0)+I|0]=A&255;I=i+148+((d[13928+(A&255)|0]|256)+1<<2)|0;b[I>>1]=(b[I>>1]|0)+1&65535;b[K>>1]=(b[K>>1]|0)+1&65535;I=(c[H>>2]|0)==((c[t>>2]|0)-1|0);A=c[v>>2]|0;c[N>>2]=(c[N>>2]|0)-A;L=(c[l>>2]|0)+A|0;c[l>>2]=L;c[v>>2]=0;if(I){av=L}else{continue L351}}}while(0);if((z|0)==265){z=0;L=a[(c[Q>>2]|0)+at|0]|0;b[(c[u>>2]|0)+(c[H>>2]<<1)>>1]=0;I=c[H>>2]|0;c[H>>2]=I+1;a[(c[w>>2]|0)+I|0]=L;I=i+148+((L&255)<<2)|0;b[I>>1]=(b[I>>1]|0)+1&65535;I=(c[H>>2]|0)==((c[t>>2]|0)-1|0);c[N>>2]=(c[N>>2]|0)-1;L=(c[l>>2]|0)+1|0;c[l>>2]=L;if(I){av=L}else{continue}}L=c[x>>2]|0;if((L|0)>-1){aw=(c[Q>>2]|0)+L|0}else{aw=0}by(i,aw,av-L|0,0);c[x>>2]=c[l>>2];L=c[o>>2]|0;I=L+28|0;A=c[I>>2]|0;T=c[A+20>>2]|0;R=L+16|0;ax=c[R>>2]|0;ay=T>>>0>ax>>>0?ax:T;do{if((ay|0)!=0){T=L+12|0;ax=c[T>>2]|0;az=c[A+16>>2]|0;bJ(ax|0,az|0,ay)|0;c[T>>2]=(c[T>>2]|0)+ay;T=(c[I>>2]|0)+16|0;c[T>>2]=(c[T>>2]|0)+ay;T=L+20|0;c[T>>2]=(c[T>>2]|0)+ay;c[R>>2]=(c[R>>2]|0)-ay;T=(c[I>>2]|0)+20|0;c[T>>2]=(c[T>>2]|0)-ay;T=c[I>>2]|0;if((c[T+20>>2]|0)!=0){break}c[T+16>>2]=c[T+8>>2]}}while(0);if((c[(c[o>>2]|0)+16>>2]|0)==0){break L323}}N=c[x>>2]|0;if((N|0)>-1){aA=(c[Q>>2]|0)+N|0}else{aA=0}by(i,aA,(c[l>>2]|0)-N|0,m&1);c[x>>2]=c[l>>2];N=c[o>>2]|0;t=N+28|0;H=c[t>>2]|0;w=c[H+20>>2]|0;u=N+16|0;v=c[u>>2]|0;K=w>>>0>v>>>0?v:w;do{if((K|0)!=0){w=N+12|0;v=c[w>>2]|0;M=c[H+16>>2]|0;bJ(v|0,M|0,K)|0;c[w>>2]=(c[w>>2]|0)+K;w=(c[t>>2]|0)+16|0;c[w>>2]=(c[w>>2]|0)+K;w=N+20|0;c[w>>2]=(c[w>>2]|0)+K;c[u>>2]=(c[u>>2]|0)-K;w=(c[t>>2]|0)+20|0;c[w>>2]=(c[w>>2]|0)-K;w=c[t>>2]|0;if((c[w+20>>2]|0)!=0){break}c[w+16>>2]=c[w+8>>2]}}while(0);if((c[(c[o>>2]|0)+16>>2]|0)==0){ar=m?2:0;z=281;break}else{ar=m?3:1;z=281;break}}else{ar=aI[c[12400+((c[i+132>>2]|0)*12|0)>>2]&15](i,f)|0;z=281}}while(0);do{if((z|0)==281){if((ar-2|0)>>>0<2){c[k>>2]=666}if((ar|0)==2|(ar|0)==0){break}else if((ar|0)!=1){break L321}do{if((f|0)==1){bx(i)}else if((f|0)!=5){bs(i,0,0,0);if((f|0)!=3){break}q=i+76|0;P=i+68|0;b[(c[P>>2]|0)+((c[q>>2]|0)-1<<1)>>1]=0;bI(c[P>>2]|0,0,(c[q>>2]<<1)-2|0);if((c[i+116>>2]|0)!=0){break}c[i+108>>2]=0;c[i+92>>2]=0}}while(0);q=c[h>>2]|0;P=c[q+20>>2]|0;O=c[n>>2]|0;t=P>>>0>O>>>0?O:P;if((t|0)==0){aB=O}else{O=c[j>>2]|0;P=c[q+16>>2]|0;bJ(O|0,P|0,t)|0;c[j>>2]=(c[j>>2]|0)+t;P=(c[h>>2]|0)+16|0;c[P>>2]=(c[P>>2]|0)+t;P=e+20|0;c[P>>2]=(c[P>>2]|0)+t;c[n>>2]=(c[n>>2]|0)-t;P=(c[h>>2]|0)+20|0;c[P>>2]=(c[P>>2]|0)-t;t=c[h>>2]|0;if((c[t+20>>2]|0)==0){c[t+16>>2]=c[t+8>>2]}aB=c[n>>2]|0}if((aB|0)!=0){break L321}c[p>>2]=-1;g=0;return g|0}}while(0);if((c[n>>2]|0)!=0){g=0;return g|0}c[p>>2]=-1;g=0;return g|0}}while(0);if(!m){g=0;return g|0}p=i+24|0;k=c[p>>2]|0;if((k|0)<1){g=1;return g|0}o=e+48|0;t=c[o>>2]|0;if((k|0)==2){k=c[r>>2]|0;c[r>>2]=k+1;P=i+8|0;a[(c[P>>2]|0)+k|0]=t&255;k=(c[o>>2]|0)>>>8&255;O=c[r>>2]|0;c[r>>2]=O+1;a[(c[P>>2]|0)+O|0]=k;k=(c[o>>2]|0)>>>16&255;O=c[r>>2]|0;c[r>>2]=O+1;a[(c[P>>2]|0)+O|0]=k;k=(c[o>>2]|0)>>>24&255;O=c[r>>2]|0;c[r>>2]=O+1;a[(c[P>>2]|0)+O|0]=k;k=e+8|0;O=c[k>>2]&255;q=c[r>>2]|0;c[r>>2]=q+1;a[(c[P>>2]|0)+q|0]=O;O=(c[k>>2]|0)>>>8&255;q=c[r>>2]|0;c[r>>2]=q+1;a[(c[P>>2]|0)+q|0]=O;O=(c[k>>2]|0)>>>16&255;q=c[r>>2]|0;c[r>>2]=q+1;a[(c[P>>2]|0)+q|0]=O;O=(c[k>>2]|0)>>>24&255;k=c[r>>2]|0;c[r>>2]=k+1;a[(c[P>>2]|0)+k|0]=O}else{O=c[r>>2]|0;c[r>>2]=O+1;k=i+8|0;a[(c[k>>2]|0)+O|0]=t>>>24&255;O=c[r>>2]|0;c[r>>2]=O+1;a[(c[k>>2]|0)+O|0]=t>>>16&255;t=c[o>>2]|0;o=c[r>>2]|0;c[r>>2]=o+1;a[(c[k>>2]|0)+o|0]=t>>>8&255;o=c[r>>2]|0;c[r>>2]=o+1;a[(c[k>>2]|0)+o|0]=t&255}t=c[h>>2]|0;o=c[t+20>>2]|0;k=c[n>>2]|0;O=o>>>0>k>>>0?k:o;do{if((O|0)!=0){o=c[j>>2]|0;k=c[t+16>>2]|0;bJ(o|0,k|0,O)|0;c[j>>2]=(c[j>>2]|0)+O;k=(c[h>>2]|0)+16|0;c[k>>2]=(c[k>>2]|0)+O;k=e+20|0;c[k>>2]=(c[k>>2]|0)+O;c[n>>2]=(c[n>>2]|0)-O;k=(c[h>>2]|0)+20|0;c[k>>2]=(c[k>>2]|0)-O;k=c[h>>2]|0;if((c[k+20>>2]|0)!=0){break}c[k+16>>2]=c[k+8>>2]}}while(0);O=c[p>>2]|0;if((O|0)>0){c[p>>2]=-O}g=(c[r>>2]|0)==0|0;return g|0}}while(0);c[e+24>>2]=c[6];g=-2;return g|0}function a4(a){a=a|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0;f=a+44|0;g=c[f>>2]|0;h=a+60|0;i=a+116|0;j=a+108|0;k=g-262|0;l=a|0;m=a+56|0;n=a+72|0;o=a+88|0;p=a+84|0;q=a+112|0;r=a+92|0;s=a+76|0;t=a+68|0;u=a+64|0;v=c[i>>2]|0;w=g;while(1){x=c[j>>2]|0;y=(c[h>>2]|0)-v-x|0;if(x>>>0<(k+w|0)>>>0){z=y}else{x=c[m>>2]|0;A=x+g|0;bJ(x|0,A|0,g)|0;c[q>>2]=(c[q>>2]|0)-g;c[j>>2]=(c[j>>2]|0)-g;c[r>>2]=(c[r>>2]|0)-g;A=c[s>>2]|0;x=A;B=(c[t>>2]|0)+(A<<1)|0;do{B=B-2|0;A=e[B>>1]|0;if(A>>>0>>0){C=0}else{C=A-g&65535}b[B>>1]=C;x=x-1|0;}while((x|0)!=0);x=g;B=(c[u>>2]|0)+(g<<1)|0;do{B=B-2|0;A=e[B>>1]|0;if(A>>>0>>0){D=0}else{D=A-g&65535}b[B>>1]=D;x=x-1|0;}while((x|0)!=0);z=y+g|0}x=c[l>>2]|0;B=x+4|0;A=c[B>>2]|0;if((A|0)==0){E=355;break}F=c[i>>2]|0;G=(c[m>>2]|0)+(F+(c[j>>2]|0))|0;H=A>>>0>z>>>0?z:A;if((H|0)==0){I=0;J=F}else{c[B>>2]=A-H;A=c[(c[x+28>>2]|0)+24>>2]|0;if((A|0)==1){B=x+48|0;F=x|0;c[B>>2]=a_(c[B>>2]|0,c[F>>2]|0,H)|0;K=F}else if((A|0)==2){A=x+48|0;F=x|0;c[A>>2]=a$(c[A>>2]|0,c[F>>2]|0,H)|0;K=F}else{K=x|0}F=c[K>>2]|0;bJ(G|0,F|0,H)|0;c[K>>2]=(c[K>>2]|0)+H;F=x+8|0;c[F>>2]=(c[F>>2]|0)+H;I=H;J=c[i>>2]|0}L=J+I|0;c[i>>2]=L;if(L>>>0>2){H=c[j>>2]|0;F=c[m>>2]|0;x=d[F+H|0]|0;c[n>>2]=x;c[n>>2]=((d[F+(H+1)|0]|0)^x<>2])&c[p>>2];if(L>>>0>=262){break}}if((c[(c[l>>2]|0)+4>>2]|0)==0){break}v=L;w=c[f>>2]|0}if((E|0)==355){return}E=a+5824|0;a=c[E>>2]|0;f=c[h>>2]|0;if(a>>>0>=f>>>0){return}h=L+(c[j>>2]|0)|0;if(a>>>0>>0){j=f-h|0;L=j>>>0>258?258:j;bI((c[m>>2]|0)+h|0,0,L|0);c[E>>2]=L+h;return}L=h+258|0;if(a>>>0>=L>>>0){return}h=L-a|0;L=f-a|0;f=h>>>0>L>>>0?L:h;bI((c[m>>2]|0)+a|0,0,f|0);c[E>>2]=(c[E>>2]|0)+f;return}function a5(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;d=(c[a+12>>2]|0)-5|0;e=d>>>0<65535?d:65535;d=a+116|0;f=a+108|0;g=a+92|0;h=a+44|0;i=a+56|0;j=a|0;while(1){k=c[d>>2]|0;if(k>>>0<2){a4(a);l=c[d>>2]|0;if((l|b|0)==0){m=0;n=384;break}if((l|0)==0){n=375;break}else{o=l}}else{o=k}k=(c[f>>2]|0)+o|0;c[f>>2]=k;c[d>>2]=0;l=c[g>>2]|0;p=l+e|0;if((k|0)!=0&k>>>0

>>0){q=k;r=l}else{c[d>>2]=k-p;c[f>>2]=p;if((l|0)>-1){s=(c[i>>2]|0)+l|0}else{s=0}by(a,s,e,0);c[g>>2]=c[f>>2];l=c[j>>2]|0;p=l+28|0;k=c[p>>2]|0;t=c[k+20>>2]|0;u=l+16|0;v=c[u>>2]|0;w=t>>>0>v>>>0?v:t;do{if((w|0)!=0){t=l+12|0;v=c[t>>2]|0;x=c[k+16>>2]|0;bJ(v|0,x|0,w)|0;c[t>>2]=(c[t>>2]|0)+w;t=(c[p>>2]|0)+16|0;c[t>>2]=(c[t>>2]|0)+w;t=l+20|0;c[t>>2]=(c[t>>2]|0)+w;c[u>>2]=(c[u>>2]|0)-w;t=(c[p>>2]|0)+20|0;c[t>>2]=(c[t>>2]|0)-w;t=c[p>>2]|0;if((c[t+20>>2]|0)!=0){break}c[t+16>>2]=c[t+8>>2]}}while(0);if((c[(c[j>>2]|0)+16>>2]|0)==0){m=0;n=385;break}q=c[f>>2]|0;r=c[g>>2]|0}p=q-r|0;if(p>>>0<((c[h>>2]|0)-262|0)>>>0){continue}if((r|0)>-1){y=(c[i>>2]|0)+r|0}else{y=0}by(a,y,p,0);c[g>>2]=c[f>>2];p=c[j>>2]|0;w=p+28|0;u=c[w>>2]|0;l=c[u+20>>2]|0;k=p+16|0;t=c[k>>2]|0;x=l>>>0>t>>>0?t:l;do{if((x|0)!=0){l=p+12|0;t=c[l>>2]|0;v=c[u+16>>2]|0;bJ(t|0,v|0,x)|0;c[l>>2]=(c[l>>2]|0)+x;l=(c[w>>2]|0)+16|0;c[l>>2]=(c[l>>2]|0)+x;l=p+20|0;c[l>>2]=(c[l>>2]|0)+x;c[k>>2]=(c[k>>2]|0)-x;l=(c[w>>2]|0)+20|0;c[l>>2]=(c[l>>2]|0)-x;l=c[w>>2]|0;if((c[l+20>>2]|0)!=0){break}c[l+16>>2]=c[l+8>>2]}}while(0);if((c[(c[j>>2]|0)+16>>2]|0)==0){m=0;n=386;break}}if((n|0)==384){return m|0}else if((n|0)==386){return m|0}else if((n|0)==385){return m|0}else if((n|0)==375){n=c[g>>2]|0;if((n|0)>-1){z=(c[i>>2]|0)+n|0}else{z=0}i=(b|0)==4;by(a,z,(c[f>>2]|0)-n|0,i&1);c[g>>2]=c[f>>2];f=c[j>>2]|0;g=f+28|0;n=c[g>>2]|0;z=c[n+20>>2]|0;a=f+16|0;b=c[a>>2]|0;y=z>>>0>b>>>0?b:z;do{if((y|0)!=0){z=f+12|0;b=c[z>>2]|0;r=c[n+16>>2]|0;bJ(b|0,r|0,y)|0;c[z>>2]=(c[z>>2]|0)+y;z=(c[g>>2]|0)+16|0;c[z>>2]=(c[z>>2]|0)+y;z=f+20|0;c[z>>2]=(c[z>>2]|0)+y;c[a>>2]=(c[a>>2]|0)-y;z=(c[g>>2]|0)+20|0;c[z>>2]=(c[z>>2]|0)-y;z=c[g>>2]|0;if((c[z+20>>2]|0)!=0){break}c[z+16>>2]=c[z+8>>2]}}while(0);if((c[(c[j>>2]|0)+16>>2]|0)==0){m=i?2:0;return m|0}else{m=i?3:1;return m|0}}return 0}function a6(e,f){e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0;g=e+116|0;h=(f|0)==0;i=e+72|0;j=e+88|0;k=e+108|0;l=e+56|0;m=e+84|0;n=e+68|0;o=e+52|0;p=e+64|0;q=e+44|0;r=e+96|0;s=e+112|0;t=e+5792|0;u=e+5796|0;v=e+5784|0;w=e+5788|0;x=e+128|0;y=e+92|0;z=e|0;while(1){if((c[g>>2]|0)>>>0<262){a4(e);A=c[g>>2]|0;if(A>>>0<262&h){B=0;C=426;break}if((A|0)==0){C=414;break}if(A>>>0>2){C=394}else{C=397}}else{C=394}do{if((C|0)==394){C=0;A=c[k>>2]|0;D=((d[(c[l>>2]|0)+(A+2)|0]|0)^c[i>>2]<>2])&c[m>>2];c[i>>2]=D;E=b[(c[n>>2]|0)+(D<<1)>>1]|0;b[(c[p>>2]|0)+((c[o>>2]&A)<<1)>>1]=E;A=E&65535;b[(c[n>>2]|0)+(c[i>>2]<<1)>>1]=c[k>>2]&65535;if(E<<16>>16==0){C=397;break}if(((c[k>>2]|0)-A|0)>>>0>((c[q>>2]|0)-262|0)>>>0){C=397;break}E=a7(e,A)|0;c[r>>2]=E;F=E}}while(0);if((C|0)==397){C=0;F=c[r>>2]|0}do{if(F>>>0>2){E=F+253|0;A=(c[k>>2]|0)-(c[s>>2]|0)&65535;b[(c[u>>2]|0)+(c[t>>2]<<1)>>1]=A;D=c[t>>2]|0;c[t>>2]=D+1;a[(c[v>>2]|0)+D|0]=E&255;D=A-1&65535;A=e+148+((d[13928+(E&255)|0]|0|256)+1<<2)|0;b[A>>1]=(b[A>>1]|0)+1&65535;A=D&65535;if((D&65535)<256){G=A}else{G=(A>>>7)+256|0}A=e+2440+((d[14184+G|0]|0)<<2)|0;b[A>>1]=(b[A>>1]|0)+1&65535;A=(c[t>>2]|0)==((c[w>>2]|0)-1|0)|0;D=c[r>>2]|0;E=(c[g>>2]|0)-D|0;c[g>>2]=E;if(!(D>>>0<=(c[x>>2]|0)>>>0&E>>>0>2)){E=(c[k>>2]|0)+D|0;c[k>>2]=E;c[r>>2]=0;H=c[l>>2]|0;I=d[H+E|0]|0;c[i>>2]=I;c[i>>2]=((d[H+(E+1)|0]|0)^I<>2])&c[m>>2];J=A;K=E;break}c[r>>2]=D-1;do{D=c[k>>2]|0;E=D+1|0;c[k>>2]=E;I=((d[(c[l>>2]|0)+(D+3)|0]|0)^c[i>>2]<>2])&c[m>>2];c[i>>2]=I;b[(c[p>>2]|0)+((c[o>>2]&E)<<1)>>1]=b[(c[n>>2]|0)+(I<<1)>>1]|0;b[(c[n>>2]|0)+(c[i>>2]<<1)>>1]=c[k>>2]&65535;I=(c[r>>2]|0)-1|0;c[r>>2]=I;}while((I|0)!=0);I=(c[k>>2]|0)+1|0;c[k>>2]=I;J=A;K=I}else{I=a[(c[l>>2]|0)+(c[k>>2]|0)|0]|0;b[(c[u>>2]|0)+(c[t>>2]<<1)>>1]=0;E=c[t>>2]|0;c[t>>2]=E+1;a[(c[v>>2]|0)+E|0]=I;E=e+148+((I&255)<<2)|0;b[E>>1]=(b[E>>1]|0)+1&65535;E=(c[t>>2]|0)==((c[w>>2]|0)-1|0)|0;c[g>>2]=(c[g>>2]|0)-1;I=(c[k>>2]|0)+1|0;c[k>>2]=I;J=E;K=I}}while(0);if((J|0)==0){continue}I=c[y>>2]|0;if((I|0)>-1){L=(c[l>>2]|0)+I|0}else{L=0}by(e,L,K-I|0,0);c[y>>2]=c[k>>2];I=c[z>>2]|0;E=I+28|0;D=c[E>>2]|0;H=c[D+20>>2]|0;M=I+16|0;N=c[M>>2]|0;O=H>>>0>N>>>0?N:H;do{if((O|0)!=0){H=I+12|0;N=c[H>>2]|0;P=c[D+16>>2]|0;bJ(N|0,P|0,O)|0;c[H>>2]=(c[H>>2]|0)+O;H=(c[E>>2]|0)+16|0;c[H>>2]=(c[H>>2]|0)+O;H=I+20|0;c[H>>2]=(c[H>>2]|0)+O;c[M>>2]=(c[M>>2]|0)-O;H=(c[E>>2]|0)+20|0;c[H>>2]=(c[H>>2]|0)-O;H=c[E>>2]|0;if((c[H+20>>2]|0)!=0){break}c[H+16>>2]=c[H+8>>2]}}while(0);if((c[(c[z>>2]|0)+16>>2]|0)==0){B=0;C=425;break}}if((C|0)==414){K=c[y>>2]|0;if((K|0)>-1){Q=(c[l>>2]|0)+K|0}else{Q=0}l=(f|0)==4;by(e,Q,(c[k>>2]|0)-K|0,l&1);c[y>>2]=c[k>>2];k=c[z>>2]|0;y=k+28|0;K=c[y>>2]|0;Q=c[K+20>>2]|0;e=k+16|0;f=c[e>>2]|0;L=Q>>>0>f>>>0?f:Q;do{if((L|0)!=0){Q=k+12|0;f=c[Q>>2]|0;J=c[K+16>>2]|0;bJ(f|0,J|0,L)|0;c[Q>>2]=(c[Q>>2]|0)+L;Q=(c[y>>2]|0)+16|0;c[Q>>2]=(c[Q>>2]|0)+L;Q=k+20|0;c[Q>>2]=(c[Q>>2]|0)+L;c[e>>2]=(c[e>>2]|0)-L;Q=(c[y>>2]|0)+20|0;c[Q>>2]=(c[Q>>2]|0)-L;Q=c[y>>2]|0;if((c[Q+20>>2]|0)!=0){break}c[Q+16>>2]=c[Q+8>>2]}}while(0);if((c[(c[z>>2]|0)+16>>2]|0)==0){B=l?2:0;return B|0}else{B=l?3:1;return B|0}}else if((C|0)==425){return B|0}else if((C|0)==426){return B|0}return 0}function a7(b,d){b=b|0;d=d|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0;f=c[b+124>>2]|0;g=c[b+56>>2]|0;h=c[b+108>>2]|0;i=g+h|0;j=c[b+120>>2]|0;k=c[b+144>>2]|0;l=(c[b+44>>2]|0)-262|0;m=h>>>0>l>>>0?h-l|0:0;l=c[b+64>>2]|0;n=c[b+52>>2]|0;o=g+(h+258)|0;p=c[b+116>>2]|0;q=k>>>0>p>>>0?p:k;k=b+112|0;r=g+(h+1)|0;s=g+(h+2)|0;t=o;u=h+257|0;v=a[g+(j+h)|0]|0;w=a[g+(h-1+j)|0]|0;x=d;d=j>>>0<(c[b+140>>2]|0)>>>0?f:f>>>2;f=j;L584:while(1){j=g+x|0;do{if((a[g+(x+f)|0]|0)==v<<24>>24){if((a[g+(f-1+x)|0]|0)!=w<<24>>24){y=v;z=w;A=f;break}if((a[j]|0)!=(a[i]|0)){y=v;z=w;A=f;break}if((a[g+(x+1)|0]|0)!=(a[r]|0)){y=v;z=w;A=f;break}b=s;B=g+(x+2)|0;while(1){C=b+1|0;if((a[C]|0)!=(a[B+1|0]|0)){D=C;break}C=b+2|0;if((a[C]|0)!=(a[B+2|0]|0)){D=C;break}C=b+3|0;if((a[C]|0)!=(a[B+3|0]|0)){D=C;break}C=b+4|0;if((a[C]|0)!=(a[B+4|0]|0)){D=C;break}C=b+5|0;if((a[C]|0)!=(a[B+5|0]|0)){D=C;break}C=b+6|0;if((a[C]|0)!=(a[B+6|0]|0)){D=C;break}C=b+7|0;if((a[C]|0)!=(a[B+7|0]|0)){D=C;break}C=b+8|0;E=B+8|0;if((a[C]|0)==(a[E]|0)&C>>>0>>0){b=C;B=E}else{D=C;break}}B=D-t|0;b=B+258|0;if((b|0)<=(f|0)){y=v;z=w;A=f;break}c[k>>2]=x;if((b|0)>=(q|0)){F=b;G=447;break L584}y=a[g+(b+h)|0]|0;z=a[g+(u+B)|0]|0;A=b}else{y=v;z=w;A=f}}while(0);j=e[l+((x&n)<<1)>>1]|0;if(j>>>0<=m>>>0){F=A;G=448;break}b=d-1|0;if((b|0)==0){F=A;G=449;break}else{v=y;w=z;x=j;d=b;f=A}}if((G|0)==447){H=F>>>0>p>>>0;I=H?p:F;return I|0}else if((G|0)==448){H=F>>>0>p>>>0;I=H?p:F;return I|0}else if((G|0)==449){H=F>>>0>p>>>0;I=H?p:F;return I|0}return 0}function a8(e,f){e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0;g=e+116|0;h=(f|0)==0;i=e+72|0;j=e+88|0;k=e+108|0;l=e+56|0;m=e+84|0;n=e+68|0;o=e+52|0;p=e+64|0;q=e+96|0;r=e+120|0;s=e+112|0;t=e+100|0;u=e+5792|0;v=e+5796|0;w=e+5784|0;x=e+5788|0;y=e+104|0;z=e+92|0;A=e|0;B=e+128|0;C=e+44|0;D=e+136|0;L610:while(1){E=c[g>>2]|0;while(1){do{if(E>>>0<262){a4(e);F=c[g>>2]|0;if(F>>>0<262&h){G=0;H=500;break L610}if((F|0)==0){H=489;break L610}if(F>>>0>2){H=457;break}c[r>>2]=c[q>>2];c[t>>2]=c[s>>2];c[q>>2]=2;I=2;H=465}else{H=457}}while(0);do{if((H|0)==457){H=0;F=c[k>>2]|0;J=((d[(c[l>>2]|0)+(F+2)|0]|0)^c[i>>2]<>2])&c[m>>2];c[i>>2]=J;K=b[(c[n>>2]|0)+(J<<1)>>1]|0;b[(c[p>>2]|0)+((c[o>>2]&F)<<1)>>1]=K;F=K&65535;b[(c[n>>2]|0)+(c[i>>2]<<1)>>1]=c[k>>2]&65535;J=c[q>>2]|0;c[r>>2]=J;c[t>>2]=c[s>>2];c[q>>2]=2;if(K<<16>>16==0){I=2;H=465;break}if(J>>>0>=(c[B>>2]|0)>>>0){L=J;M=2;break}if(((c[k>>2]|0)-F|0)>>>0>((c[C>>2]|0)-262|0)>>>0){I=2;H=465;break}J=a7(e,F)|0;c[q>>2]=J;if(J>>>0>=6){I=J;H=465;break}if((c[D>>2]|0)!=1){if((J|0)!=3){I=J;H=465;break}if(((c[k>>2]|0)-(c[s>>2]|0)|0)>>>0<=4096){I=3;H=465;break}}c[q>>2]=2;I=2;H=465}}while(0);if((H|0)==465){H=0;L=c[r>>2]|0;M=I}if(!(L>>>0<3|M>>>0>L>>>0)){break}if((c[y>>2]|0)==0){c[y>>2]=1;c[k>>2]=(c[k>>2]|0)+1;J=(c[g>>2]|0)-1|0;c[g>>2]=J;E=J;continue}J=a[(c[l>>2]|0)+((c[k>>2]|0)-1)|0]|0;b[(c[v>>2]|0)+(c[u>>2]<<1)>>1]=0;F=c[u>>2]|0;c[u>>2]=F+1;a[(c[w>>2]|0)+F|0]=J;F=e+148+((J&255)<<2)|0;b[F>>1]=(b[F>>1]|0)+1&65535;do{if((c[u>>2]|0)==((c[x>>2]|0)-1|0)){F=c[z>>2]|0;if((F|0)>-1){N=(c[l>>2]|0)+F|0}else{N=0}by(e,N,(c[k>>2]|0)-F|0,0);c[z>>2]=c[k>>2];F=c[A>>2]|0;J=F+28|0;K=c[J>>2]|0;O=c[K+20>>2]|0;P=F+16|0;Q=c[P>>2]|0;R=O>>>0>Q>>>0?Q:O;if((R|0)==0){break}O=F+12|0;Q=c[O>>2]|0;S=c[K+16>>2]|0;bJ(Q|0,S|0,R)|0;c[O>>2]=(c[O>>2]|0)+R;O=(c[J>>2]|0)+16|0;c[O>>2]=(c[O>>2]|0)+R;O=F+20|0;c[O>>2]=(c[O>>2]|0)+R;c[P>>2]=(c[P>>2]|0)-R;P=(c[J>>2]|0)+20|0;c[P>>2]=(c[P>>2]|0)-R;R=c[J>>2]|0;if((c[R+20>>2]|0)!=0){break}c[R+16>>2]=c[R+8>>2]}}while(0);c[k>>2]=(c[k>>2]|0)+1;R=(c[g>>2]|0)-1|0;c[g>>2]=R;if((c[(c[A>>2]|0)+16>>2]|0)==0){G=0;H=502;break L610}else{E=R}}E=c[k>>2]|0;R=E-3+(c[g>>2]|0)|0;J=L+253|0;P=E+65535-(c[t>>2]|0)&65535;b[(c[v>>2]|0)+(c[u>>2]<<1)>>1]=P;E=c[u>>2]|0;c[u>>2]=E+1;a[(c[w>>2]|0)+E|0]=J&255;E=P-1&65535;P=e+148+((d[13928+(J&255)|0]|0|256)+1<<2)|0;b[P>>1]=(b[P>>1]|0)+1&65535;P=E&65535;if((E&65535)<256){T=P}else{T=(P>>>7)+256|0}P=e+2440+((d[14184+T|0]|0)<<2)|0;b[P>>1]=(b[P>>1]|0)+1&65535;P=c[u>>2]|0;E=(c[x>>2]|0)-1|0;J=c[r>>2]|0;c[g>>2]=1-J+(c[g>>2]|0);O=J-2|0;c[r>>2]=O;J=O;do{O=c[k>>2]|0;F=O+1|0;c[k>>2]=F;if(F>>>0>R>>>0){U=J}else{S=((d[(c[l>>2]|0)+(O+3)|0]|0)^c[i>>2]<>2])&c[m>>2];c[i>>2]=S;b[(c[p>>2]|0)+((c[o>>2]&F)<<1)>>1]=b[(c[n>>2]|0)+(S<<1)>>1]|0;b[(c[n>>2]|0)+(c[i>>2]<<1)>>1]=c[k>>2]&65535;U=c[r>>2]|0}J=U-1|0;c[r>>2]=J;}while((J|0)!=0);c[y>>2]=0;c[q>>2]=2;J=(c[k>>2]|0)+1|0;c[k>>2]=J;if((P|0)!=(E|0)){continue}R=c[z>>2]|0;if((R|0)>-1){V=(c[l>>2]|0)+R|0}else{V=0}by(e,V,J-R|0,0);c[z>>2]=c[k>>2];R=c[A>>2]|0;J=R+28|0;S=c[J>>2]|0;F=c[S+20>>2]|0;O=R+16|0;Q=c[O>>2]|0;K=F>>>0>Q>>>0?Q:F;do{if((K|0)!=0){F=R+12|0;Q=c[F>>2]|0;W=c[S+16>>2]|0;bJ(Q|0,W|0,K)|0;c[F>>2]=(c[F>>2]|0)+K;F=(c[J>>2]|0)+16|0;c[F>>2]=(c[F>>2]|0)+K;F=R+20|0;c[F>>2]=(c[F>>2]|0)+K;c[O>>2]=(c[O>>2]|0)-K;F=(c[J>>2]|0)+20|0;c[F>>2]=(c[F>>2]|0)-K;F=c[J>>2]|0;if((c[F+20>>2]|0)!=0){break}c[F+16>>2]=c[F+8>>2]}}while(0);if((c[(c[A>>2]|0)+16>>2]|0)==0){G=0;H=501;break}}if((H|0)==489){if((c[y>>2]|0)!=0){V=a[(c[l>>2]|0)+((c[k>>2]|0)-1)|0]|0;b[(c[v>>2]|0)+(c[u>>2]<<1)>>1]=0;v=c[u>>2]|0;c[u>>2]=v+1;a[(c[w>>2]|0)+v|0]=V;v=e+148+((V&255)<<2)|0;b[v>>1]=(b[v>>1]|0)+1&65535;c[y>>2]=0}y=c[z>>2]|0;if((y|0)>-1){X=(c[l>>2]|0)+y|0}else{X=0}l=(f|0)==4;by(e,X,(c[k>>2]|0)-y|0,l&1);c[z>>2]=c[k>>2];k=c[A>>2]|0;z=k+28|0;y=c[z>>2]|0;X=c[y+20>>2]|0;e=k+16|0;f=c[e>>2]|0;v=X>>>0>f>>>0?f:X;do{if((v|0)!=0){X=k+12|0;f=c[X>>2]|0;V=c[y+16>>2]|0;bJ(f|0,V|0,v)|0;c[X>>2]=(c[X>>2]|0)+v;X=(c[z>>2]|0)+16|0;c[X>>2]=(c[X>>2]|0)+v;X=k+20|0;c[X>>2]=(c[X>>2]|0)+v;c[e>>2]=(c[e>>2]|0)-v;X=(c[z>>2]|0)+20|0;c[X>>2]=(c[X>>2]|0)-v;X=c[z>>2]|0;if((c[X+20>>2]|0)!=0){break}c[X+16>>2]=c[X+8>>2]}}while(0);if((c[(c[A>>2]|0)+16>>2]|0)==0){G=l?2:0;return G|0}else{G=l?3:1;return G|0}}else if((H|0)==500){return G|0}else if((H|0)==501){return G|0}else if((H|0)==502){return G|0}return 0}function a9(a){a=a|0;var b=0;do{if((a|0)==0){b=-2}else{if((c[a>>2]|0)==7247){b=bg(a)|0;break}else{b=bn(a)|0;break}}}while(0);return b|0}function ba(a,b){a=a|0;b=b|0;return bb(a,-1,b)|0}function bb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,t=0,u=0,v=0,w=0,x=0,y=0;f=i;g=bF(140)|0;if((g|0)==0){h=0;i=f;return h|0}c[g+16>>2]=0;c[g+20>>2]=8192;j=g+80|0;c[j>>2]=0;k=g;c[k>>2]=0;l=g+60|0;c[l>>2]=-1;m=g+64|0;c[m>>2]=0;n=a[e]|0;do{if(n<<24>>24!=0){o=e;p=n;q=0;L695:while(1){r=p<<24>>24;do{if((p-48&255)<10){c[l>>2]=r-48;t=q}else{if((r|0)==114){c[k>>2]=7247;t=7247;break}else if((r|0)==119){c[k>>2]=31153;t=31153;break}else if((r|0)==97){c[k>>2]=1;t=1;break}else if((r|0)==43){u=519;break L695}else if((r|0)==102){c[m>>2]=1;t=q;break}else if((r|0)==104){c[m>>2]=2;t=q;break}else if((r|0)==82){c[m>>2]=3;t=q;break}else if((r|0)==70){c[m>>2]=4;t=q;break}else{t=q;break}}}while(0);r=o+1|0;v=a[r]|0;if(v<<24>>24==0){break}else{o=r;p=v;q=t}}if((u|0)==519){bG(g);h=0;i=f;return h|0}if((t|0)==0){break}q=bF((bK(b|0)|0)+1|0)|0;p=g+8|0;c[p>>2]=q;if((q|0)==0){bG(g);h=0;i=f;return h|0}bL(q|0,b|0)|0;do{if((d|0)==-1){q=c[k>>2]|0;if((q|0)==7247){w=0}else{w=(q|0)==31153?1537:521}q=ap(b|0,w|0,(s=i,i=i+8|0,c[s>>2]=438,s)|0)|0;c[g+4>>2]=q;if((q|0)!=-1){x=q;break}bG(c[p>>2]|0);bG(g);h=0;i=f;return h|0}else{c[g+4>>2]=d;x=d}}while(0);p=c[k>>2]|0;do{if((p|0)==1){c[k>>2]=31153}else if((p|0)==7247){q=ak(x|0,0,1)|0;if((q|0)==-1){y=0}else{y=q}c[g+44>>2]=y;if((c[k>>2]|0)!=7247){break}c[g+36>>2]=0;c[g+40>>2]=0;c[g+52>>2]=0;c[g+56>>2]=1}}while(0);c[g+72>>2]=0;p=c[j>>2]|0;q=g+76|0;if((p|0)!=0){if((c[q>>2]|0)!=-4){bG(p)}c[j>>2]=0}c[q>>2]=0;c[g+12>>2]=0;c[g+88>>2]=0;h=g;i=f;return h|0}}while(0);bG(g);h=0;i=f;return h|0}function bc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=b+80|0;g=c[f>>2]|0;h=b+76|0;if((g|0)!=0){if((c[h>>2]|0)!=-4){bG(g)}c[f>>2]=0}c[h>>2]=d;if((e|0)==0){return}if((d|0)==-4){c[f>>2]=e;return}d=c[b+8>>2]|0;b=bK(d|0)|0;g=bF(b+3+(bK(e|0)|0)|0)|0;c[f>>2]=g;if((g|0)==0){c[h>>2]=-4;c[f>>2]=13480;return}else{bL(g|0,d|0)|0;d=c[f>>2]|0;g=d+(bK(d|0)|0)|0;a[g]=a[13376]|0;a[g+1|0]=a[13377|0]|0;a[g+2|0]=a[13378|0]|0;g=c[f>>2]|0;bM(g|0,e|0)|0;return}}function bd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;if((a|0)==0){e=-1;return e|0}f=a;if((c[a>>2]|0)!=7247){e=-1;return e|0}if((c[a+76>>2]|0)!=0){e=-1;return e|0}if((d|0)<0){bc(f,-5,12832);e=-1;return e|0}if((d|0)==0){e=0;return e|0}g=a+72|0;L780:do{if((c[g>>2]|0)==0){h=a+36|0;i=a+40|0;j=a+32|0;k=a+88|0;l=a+12|0}else{c[g>>2]=0;m=c[a+68>>2]|0;n=a+36|0;o=a+40|0;p=a+88|0;q=a+32|0;r=a+12|0;if((m|0)==0){h=n;i=o;j=q;k=p;l=r;break}s=a+52|0;t=a+28|0;u=a+16|0;v=a+4|0;w=a+100|0;x=a+96|0;y=m;L784:while(1){L786:while(1){z=c[n>>2]|0;while(1){if((z|0)!=0){break L786}if((c[o>>2]|0)!=0){if((c[p>>2]|0)==0){h=n;i=o;j=q;k=p;l=r;break L780}}m=c[s>>2]|0;if((m|0)!=0){A=m;break}if((bf(f)|0)==-1){e=-1;B=631;break L784}m=c[n>>2]|0;if((m|0)==0){B=588;break}else{z=m}}if((B|0)==588){B=0;A=c[s>>2]|0}if((A|0)==2){c[w>>2]=c[u>>2]<<1;c[x>>2]=c[t>>2];if((be(f)|0)==-1){e=-1;B=633;break L784}else{continue}}else if((A|0)!=1){continue}m=c[t>>2]|0;C=c[u>>2]<<1;c[n>>2]=0;D=0;do{E=at(c[v>>2]|0,m+D|0,C-D|0)|0;if((E|0)<1){B=593;break}D=(c[n>>2]|0)+E|0;c[n>>2]=D;}while(D>>>0>>0);if((B|0)==593){B=0;if((E|0)<0){B=595;break L784}c[o>>2]=1}c[q>>2]=c[t>>2]}C=(z|0)<0|(z|0)>(y|0)?y:z;c[n>>2]=z-C;c[q>>2]=(c[q>>2]|0)+C;c[r>>2]=(c[r>>2]|0)+C;if((y|0)==(C|0)){h=n;i=o;j=q;k=p;l=r;break L780}else{y=y-C|0}}if((B|0)==595){bc(f,-1,az(c[(ay()|0)>>2]|0)|0);e=-1;return e|0}else if((B|0)==631){return e|0}else if((B|0)==633){return e|0}}}while(0);z=a+52|0;E=a+28|0;A=a+16|0;g=a+4|0;y=a+100|0;r=a+96|0;a=b;b=0;p=d;L816:while(1){d=c[h>>2]|0;L818:do{if((d|0)==0){if((c[i>>2]|0)!=0){if((c[k>>2]|0)==0){e=b;B=634;break L816}}q=c[z>>2]|0;do{if((q|0)==0){if((bf(f)|0)==-1){e=-1;B=635;break L816}if((c[h>>2]|0)!=0){F=a;G=b;H=p;break L818}I=c[z>>2]|0}else{if(p>>>0>2]<<1>>>0){I=q;break}if((q|0)==1){J=0}else{c[y>>2]=p;c[r>>2]=a;if((be(f)|0)==-1){e=-1;B=639;break L816}o=c[h>>2]|0;c[h>>2]=0;K=o;B=624;break L818}while(1){L=at(c[g>>2]|0,a+J|0,p-J|0)|0;if((L|0)<1){break}o=L+J|0;if(o>>>0

>>0){J=o}else{K=o;B=624;break L818}}if((L|0)<0){B=621;break L816}c[i>>2]=1;K=J;B=624;break L818}}while(0);if((I|0)==2){c[y>>2]=c[A>>2]<<1;c[r>>2]=c[E>>2];if((be(f)|0)==-1){e=-1;B=637;break L816}else{F=a;G=b;H=p;break}}else if((I|0)!=1){F=a;G=b;H=p;break}q=c[E>>2]|0;o=c[A>>2]<<1;c[h>>2]=0;n=0;do{M=at(c[g>>2]|0,q+n|0,o-n|0)|0;if((M|0)<1){B=611;break}n=(c[h>>2]|0)+M|0;c[h>>2]=n;}while(n>>>0>>0);if((B|0)==611){B=0;if((M|0)<0){B=613;break L816}c[i>>2]=1}c[j>>2]=c[E>>2];F=a;G=b;H=p}else{o=d>>>0>p>>>0?p:d;n=c[j>>2]|0;bJ(a|0,n|0,o)|0;c[j>>2]=(c[j>>2]|0)+o;c[h>>2]=(c[h>>2]|0)-o;K=o;B=624}}while(0);if((B|0)==624){B=0;c[l>>2]=(c[l>>2]|0)+K;F=a+K|0;G=K+b|0;H=p-K|0}if((H|0)==0){e=G;B=640;break}else{a=F;b=G;p=H}}if((B|0)==613){bc(f,-1,az(c[(ay()|0)>>2]|0)|0);e=-1;return e|0}else if((B|0)==621){bc(f,-1,az(c[(ay()|0)>>2]|0)|0);e=-1;return e|0}else if((B|0)==634){return e|0}else if((B|0)==635){return e|0}else if((B|0)==637){return e|0}else if((B|0)==639){return e|0}else if((B|0)==640){return e|0}return 0}function be(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;b=i;i=i+16|0;d=b|0;e=b+8|0;f=a+84|0;g=a+100|0;h=c[g>>2]|0;j=a+88|0;k=a+76|0;l=a+40|0;m=a+24|0;n=a+16|0;o=a+4|0;p=a+84|0;while(1){if((c[j>>2]|0)==0){if((c[k>>2]|0)!=0){q=-1;r=669;break}if((c[l>>2]|0)!=0){r=653;break}s=c[m>>2]|0;t=c[n>>2]|0;c[j>>2]=0;u=0;while(1){v=at(c[o>>2]|0,s+u|0,t-u|0)|0;if((v|0)<1){r=649;break}w=(c[j>>2]|0)+v|0;c[j>>2]=w;if(w>>>0>>0){u=w}else{x=w;break}}if((r|0)==649){r=0;if((v|0)<0){r=651;break}c[l>>2]=1;x=c[j>>2]|0}c[p>>2]=c[m>>2];if((x|0)==0){r=653;break}}u=bq(f,0)|0;if((u|0)==(-2|0)|(u|0)==2){r=655;break}else if((u|0)==(-4|0)){r=656;break}else if((u|0)==(-3|0)){r=657;break}y=c[g>>2]|0;z=(u|0)==1;if((y|0)==0|z){r=659;break}}if((r|0)==651){bc(a,-1,az(c[(ay()|0)>>2]|0)|0);q=-1;i=b;return q|0}else if((r|0)==653){bc(a,-3,13112);q=-1;i=b;return q|0}else if((r|0)==655){bc(a,-2,13024);q=-1;i=b;return q|0}else if((r|0)==656){bc(a,-4,13464);q=-1;i=b;return q|0}else if((r|0)==657){g=c[a+108>>2]|0;bc(a,-3,(g|0)==0?12936:g);q=-1;i=b;return q|0}else if((r|0)==659){g=h-y|0;c[a+36>>2]=g;y=(c[a+96>>2]|0)+(-g|0)|0;c[a+32>>2]=y;h=a+132|0;c[h>>2]=a$(c[h>>2]|0,y,g)|0;if(!z){q=0;i=b;return q|0}do{if((bh(a,d)|0)!=-1){if((bh(a,e)|0)==-1){break}if((c[d>>2]|0)!=(c[h>>2]|0)){bc(a,-3,12808);q=-1;i=b;return q|0}if((c[e>>2]|0)==(c[a+104>>2]|0)){c[a+52>>2]=0;q=0;i=b;return q|0}else{bc(a,-3,13904);q=-1;i=b;return q|0}}}while(0);bc(a,-3,13112);q=-1;i=b;return q|0}else if((r|0)==669){i=b;return q|0}return 0}function bf(b){b=b|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ab=0,ac=0,ad=0,ae=0,af=0,ag=0,ah=0,ai=0,aj=0,ak=0,al=0,am=0,an=0,ao=0,ap=0,aq=0,ar=0,as=0,au=0,av=0,aw=0,ax=0,aA=0,aB=0,aC=0,aD=0,aE=0,aF=0,aG=0,aH=0,aI=0,aJ=0,aK=0,aL=0,aM=0,aN=0,aO=0,aP=0,aQ=0,aR=0,aS=0;e=b+84|0;f=b+16|0;do{if((c[f>>2]|0)==0){g=c[b+20>>2]|0;h=bF(g)|0;i=b+24|0;c[i>>2]=h;j=bF(g<<1)|0;k=b+28|0;c[k>>2]=j;l=(j|0)==0;if(!((h|0)==0|l)){c[f>>2]=g;c[b+116>>2]=0;c[b+120>>2]=0;c[b+124>>2]=0;g=b+88|0;c[g>>2]=0;c[e>>2]=0;if((bp(e,-15,13368,56)|0)==0){m=g;break}bG(c[k>>2]|0);bG(c[i>>2]|0);c[f>>2]=0;bc(b,-4,13464);n=-1;return n|0}if(l){o=h}else{bG(j);o=c[i>>2]|0}if((o|0)!=0){bG(o)}bc(b,-4,13464);n=-1;return n|0}else{m=b+88|0}}while(0);o=c[m>>2]|0;do{if((o|0)==0){if((c[b+76>>2]|0)!=0){n=-1;return n|0}i=b+40|0;if((c[i>>2]|0)!=0){n=0;return n|0}j=b+24|0;h=c[j>>2]|0;l=c[f>>2]|0;c[m>>2]=0;k=b+4|0;g=0;while(1){p=at(c[k>>2]|0,h+g|0,l-g|0)|0;if((p|0)<1){q=696;break}r=(c[m>>2]|0)+p|0;c[m>>2]=r;if(r>>>0>>0){g=r}else{s=r;break}}do{if((q|0)==696){if((p|0)>=0){c[i>>2]=1;s=c[m>>2]|0;break}bc(b,-1,az(c[(ay()|0)>>2]|0)|0);n=-1;return n|0}}while(0);c[b+84>>2]=c[j>>2];if((s|0)==0){n=0}else{t=s;break}return n|0}else{t=o}}while(0);o=e|0;s=c[o>>2]|0;if((a[s]|0)==31){p=t-1|0;c[m>>2]=p;i=s+1|0;c[o>>2]=i;do{if((p|0)==0){if((c[b+76>>2]|0)!=0){n=-1;return n|0}s=b+40|0;if((c[s>>2]|0)!=0){break}g=b+24|0;l=c[g>>2]|0;h=c[f>>2]|0;c[m>>2]=0;k=b+4|0;r=0;while(1){u=at(c[k>>2]|0,l+r|0,h-r|0)|0;if((u|0)<1){q=708;break}v=(c[m>>2]|0)+u|0;c[m>>2]=v;if(v>>>0>>0){r=v}else{w=v;break}}do{if((q|0)==708){if((u|0)>=0){c[s>>2]=1;w=c[m>>2]|0;break}bc(b,-1,az(c[(ay()|0)>>2]|0)|0);n=-1;return n|0}}while(0);s=c[g>>2]|0;c[b+84>>2]=s;if((w|0)!=0){x=w;y=s;q=712}}else{x=p;y=i;q=712}}while(0);do{if((q|0)==712){if((a[y]|0)!=-117){break}i=x-1|0;c[m>>2]=i;p=y+1|0;c[o>>2]=p;L967:do{if((i|0)==0){if((c[b+76>>2]|0)!=0){break}w=b+40|0;if((c[w>>2]|0)!=0){break}u=b+24|0;s=c[u>>2]|0;r=c[f>>2]|0;c[m>>2]=0;h=b+4|0;l=0;while(1){z=at(c[h>>2]|0,s+l|0,r-l|0)|0;if((z|0)<1){q=719;break}k=(c[m>>2]|0)+z|0;c[m>>2]=k;if(k>>>0>>0){l=k}else{A=k;break}}do{if((q|0)==719){if((z|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);break L967}else{c[w>>2]=1;A=c[m>>2]|0;break}}}while(0);w=c[u>>2]|0;c[b+84>>2]=w;if((A|0)!=0){B=A;C=w;q=723}}else{B=i;C=p;q=723}}while(0);do{if((q|0)==723){p=B-1|0;c[m>>2]=p;i=C+1|0;c[o>>2]=i;if((a[C]|0)!=8){break}L983:do{if((p|0)==0){if((c[b+76>>2]|0)!=0){break}g=b+40|0;if((c[g>>2]|0)!=0){break}w=b+24|0;l=c[w>>2]|0;r=c[f>>2]|0;c[m>>2]=0;s=b+4|0;h=0;while(1){D=at(c[s>>2]|0,l+h|0,r-h|0)|0;if((D|0)<1){q=731;break}k=(c[m>>2]|0)+D|0;c[m>>2]=k;if(k>>>0>>0){h=k}else{E=k;break}}do{if((q|0)==731){if((D|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);break L983}else{c[g>>2]=1;E=c[m>>2]|0;break}}}while(0);g=c[w>>2]|0;c[b+84>>2]=g;if((E|0)!=0){F=E;G=g;q=735}}else{F=p;G=i;q=735}}while(0);do{if((q|0)==735){i=F-1|0;c[m>>2]=i;p=G+1|0;c[o>>2]=p;u=d[G]|0;if((u&224|0)!=0){break}L999:do{if((i|0)==0){g=b+76|0;if((c[g>>2]|0)!=0){q=749;break}h=b+40|0;if((c[h>>2]|0)!=0){H=g;q=750;break}r=b+24|0;l=c[r>>2]|0;s=c[f>>2]|0;c[m>>2]=0;k=b+4|0;j=0;while(1){I=at(c[k>>2]|0,l+j|0,s-j|0)|0;if((I|0)<1){q=743;break}v=(c[m>>2]|0)+I|0;c[m>>2]=v;if(v>>>0>>0){j=v}else{J=v;break}}do{if((q|0)==743){if((I|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);K=c[m>>2]|0;q=748;break L999}else{c[h>>2]=1;J=c[m>>2]|0;break}}}while(0);h=c[r>>2]|0;c[b+84>>2]=h;if((J|0)==0){H=g;q=750}else{L=J;M=h;q=747}}else{L=i;M=p;q=747}}while(0);if((q|0)==747){p=L-1|0;c[m>>2]=p;c[o>>2]=M+1;K=p;q=748}if((q|0)==748){if((K|0)==0){q=749}else{N=K;q=759}}if((q|0)==749){H=b+76|0;q=750}L1018:do{if((q|0)==750){if((c[H>>2]|0)!=0){q=761;break}p=b+40|0;if((c[p>>2]|0)!=0){O=H;q=762;break}i=b+24|0;w=c[i>>2]|0;h=c[f>>2]|0;c[m>>2]=0;j=b+4|0;s=0;while(1){P=at(c[j>>2]|0,w+s|0,h-s|0)|0;if((P|0)<1){q=755;break}l=(c[m>>2]|0)+P|0;c[m>>2]=l;if(l>>>0>>0){s=l}else{Q=l;break}}do{if((q|0)==755){if((P|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);R=c[m>>2]|0;q=760;break L1018}else{c[p>>2]=1;Q=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[i>>2];if((Q|0)==0){O=H;q=762}else{N=Q;q=759}}}while(0);if((q|0)==759){p=N-1|0;c[m>>2]=p;c[o>>2]=(c[o>>2]|0)+1;R=p;q=760}if((q|0)==760){if((R|0)==0){q=761}else{S=R;q=771}}if((q|0)==761){O=b+76|0;q=762}L1037:do{if((q|0)==762){if((c[O>>2]|0)!=0){q=773;break}p=b+40|0;if((c[p>>2]|0)!=0){T=O;q=774;break}s=b+24|0;h=c[s>>2]|0;w=c[f>>2]|0;c[m>>2]=0;j=b+4|0;g=0;while(1){U=at(c[j>>2]|0,h+g|0,w-g|0)|0;if((U|0)<1){q=767;break}r=(c[m>>2]|0)+U|0;c[m>>2]=r;if(r>>>0>>0){g=r}else{V=r;break}}do{if((q|0)==767){if((U|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);W=c[m>>2]|0;q=772;break L1037}else{c[p>>2]=1;V=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[s>>2];if((V|0)==0){T=O;q=774}else{S=V;q=771}}}while(0);if((q|0)==771){p=S-1|0;c[m>>2]=p;c[o>>2]=(c[o>>2]|0)+1;W=p;q=772}if((q|0)==772){if((W|0)==0){q=773}else{X=W;q=783}}if((q|0)==773){T=b+76|0;q=774}L1056:do{if((q|0)==774){if((c[T>>2]|0)!=0){q=785;break}p=b+40|0;if((c[p>>2]|0)!=0){Y=T;q=786;break}g=b+24|0;w=c[g>>2]|0;h=c[f>>2]|0;c[m>>2]=0;j=b+4|0;i=0;while(1){Z=at(c[j>>2]|0,w+i|0,h-i|0)|0;if((Z|0)<1){q=779;break}r=(c[m>>2]|0)+Z|0;c[m>>2]=r;if(r>>>0>>0){i=r}else{_=r;break}}do{if((q|0)==779){if((Z|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);$=c[m>>2]|0;q=784;break L1056}else{c[p>>2]=1;_=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[g>>2];if((_|0)==0){Y=T;q=786}else{X=_;q=783}}}while(0);if((q|0)==783){p=X-1|0;c[m>>2]=p;c[o>>2]=(c[o>>2]|0)+1;$=p;q=784}if((q|0)==784){if(($|0)==0){q=785}else{aa=$;q=795}}if((q|0)==785){Y=b+76|0;q=786}L1075:do{if((q|0)==786){if((c[Y>>2]|0)!=0){q=797;break}p=b+40|0;if((c[p>>2]|0)!=0){ab=Y;q=798;break}i=b+24|0;h=c[i>>2]|0;w=c[f>>2]|0;c[m>>2]=0;j=b+4|0;s=0;while(1){ac=at(c[j>>2]|0,h+s|0,w-s|0)|0;if((ac|0)<1){q=791;break}r=(c[m>>2]|0)+ac|0;c[m>>2]=r;if(r>>>0>>0){s=r}else{ad=r;break}}do{if((q|0)==791){if((ac|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);ae=c[m>>2]|0;q=796;break L1075}else{c[p>>2]=1;ad=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[i>>2];if((ad|0)==0){ab=Y;q=798}else{aa=ad;q=795}}}while(0);if((q|0)==795){p=aa-1|0;c[m>>2]=p;c[o>>2]=(c[o>>2]|0)+1;ae=p;q=796}if((q|0)==796){if((ae|0)==0){q=797}else{af=ae;q=807}}if((q|0)==797){ab=b+76|0;q=798}L1094:do{if((q|0)==798){if((c[ab>>2]|0)!=0){break}p=b+40|0;if((c[p>>2]|0)!=0){break}s=b+24|0;w=c[s>>2]|0;h=c[f>>2]|0;c[m>>2]=0;j=b+4|0;g=0;while(1){ag=at(c[j>>2]|0,w+g|0,h-g|0)|0;if((ag|0)<1){q=803;break}r=(c[m>>2]|0)+ag|0;c[m>>2]=r;if(r>>>0>>0){g=r}else{ah=r;break}}do{if((q|0)==803){if((ag|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);break L1094}else{c[p>>2]=1;ah=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[s>>2];if((ah|0)!=0){af=ah;q=807}}}while(0);if((q|0)==807){c[m>>2]=af-1;c[o>>2]=(c[o>>2]|0)+1}L1110:do{if((u&4|0)!=0){p=c[m>>2]|0;L1112:do{if((p|0)==0){g=b+76|0;if((c[g>>2]|0)!=0){ai=-1;q=821;break}h=b+40|0;if((c[h>>2]|0)!=0){aj=-1;ak=g;q=822;break}w=b+24|0;j=c[w>>2]|0;i=c[f>>2]|0;c[m>>2]=0;r=b+4|0;l=0;while(1){al=at(c[r>>2]|0,j+l|0,i-l|0)|0;if((al|0)<1){q=815;break}k=(c[m>>2]|0)+al|0;c[m>>2]=k;if(k>>>0>>0){l=k}else{am=k;break}}do{if((q|0)==815){if((al|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);an=-1;ao=c[m>>2]|0;q=820;break L1112}else{c[h>>2]=1;am=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[w>>2];if((am|0)==0){aj=-1;ak=g;q=822}else{ap=am;q=819}}else{ap=p;q=819}}while(0);if((q|0)==819){p=ap-1|0;c[m>>2]=p;s=c[o>>2]|0;c[o>>2]=s+1;an=d[s]|0;ao=p;q=820}if((q|0)==820){if((ao|0)==0){ai=an;q=821}else{aq=ao;ar=an;q=831}}if((q|0)==821){aj=ai;ak=b+76|0;q=822}L1131:do{if((q|0)==822){if((c[ak>>2]|0)!=0){as=-256;au=aj;break}p=b+40|0;if((c[p>>2]|0)!=0){as=-256;au=aj;break}s=b+24|0;h=c[s>>2]|0;l=c[f>>2]|0;c[m>>2]=0;i=b+4|0;j=0;while(1){av=at(c[i>>2]|0,h+j|0,l-j|0)|0;if((av|0)<1){q=827;break}r=(c[m>>2]|0)+av|0;c[m>>2]=r;if(r>>>0>>0){j=r}else{aw=r;break}}do{if((q|0)==827){if((av|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);as=-256;au=aj;break L1131}else{c[p>>2]=1;aw=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[s>>2];if((aw|0)==0){as=-256;au=aj}else{aq=aw;ar=aj;q=831}}}while(0);if((q|0)==831){c[m>>2]=aq-1;p=c[o>>2]|0;c[o>>2]=p+1;as=d[p]<<8;au=ar}p=as+au|0;if((p|0)==0){break}j=b+76|0;l=b+40|0;h=b+24|0;i=b+4|0;g=b+84|0;w=p;p=c[m>>2]|0;while(1){w=w-1|0;if((p|0)==0){if((c[j>>2]|0)!=0){break L1110}if((c[l>>2]|0)!=0){break L1110}r=c[h>>2]|0;k=c[f>>2]|0;c[m>>2]=0;v=0;while(1){ax=at(c[i>>2]|0,r+v|0,k-v|0)|0;if((ax|0)<1){q=840;break}aA=(c[m>>2]|0)+ax|0;c[m>>2]=aA;if(aA>>>0>>0){v=aA}else{aB=aA;break}}if((q|0)==840){q=0;if((ax|0)<0){break}c[l>>2]=1;aB=c[m>>2]|0}c[g>>2]=c[h>>2];if((aB|0)==0){break L1110}else{aC=aB}}else{aC=p}p=aC-1|0;c[m>>2]=p;c[o>>2]=(c[o>>2]|0)+1;if((w|0)==0){break L1110}}bc(b,-1,az(c[(ay()|0)>>2]|0)|0)}}while(0);L1164:do{if((u&8|0)!=0){w=b+76|0;p=b+40|0;h=b+24|0;g=b+4|0;l=b+84|0;i=c[m>>2]|0;while(1){if((i|0)==0){if((c[w>>2]|0)!=0){break L1164}if((c[p>>2]|0)!=0){break L1164}j=c[h>>2]|0;v=c[f>>2]|0;c[m>>2]=0;k=0;while(1){aD=at(c[g>>2]|0,j+k|0,v-k|0)|0;if((aD|0)<1){q=853;break}r=(c[m>>2]|0)+aD|0;c[m>>2]=r;if(r>>>0>>0){k=r}else{aE=r;break}}if((q|0)==853){q=0;if((aD|0)<0){break}c[p>>2]=1;aE=c[m>>2]|0}c[l>>2]=c[h>>2];if((aE|0)==0){break L1164}else{aF=aE}}else{aF=i}i=aF-1|0;c[m>>2]=i;k=c[o>>2]|0;c[o>>2]=k+1;if((a[k]|0)==0){break L1164}}bc(b,-1,az(c[(ay()|0)>>2]|0)|0)}}while(0);L1182:do{if((u&16|0)!=0){i=b+76|0;h=b+40|0;l=b+24|0;p=b+4|0;g=b+84|0;w=c[m>>2]|0;while(1){if((w|0)==0){if((c[i>>2]|0)!=0){break L1182}if((c[h>>2]|0)!=0){break L1182}k=c[l>>2]|0;v=c[f>>2]|0;c[m>>2]=0;j=0;while(1){aG=at(c[p>>2]|0,k+j|0,v-j|0)|0;if((aG|0)<1){q=866;break}r=(c[m>>2]|0)+aG|0;c[m>>2]=r;if(r>>>0>>0){j=r}else{aH=r;break}}if((q|0)==866){q=0;if((aG|0)<0){break}c[h>>2]=1;aH=c[m>>2]|0}c[g>>2]=c[l>>2];if((aH|0)==0){break L1182}else{aI=aH}}else{aI=w}w=aI-1|0;c[m>>2]=w;j=c[o>>2]|0;c[o>>2]=j+1;if((a[j]|0)==0){break L1182}}bc(b,-1,az(c[(ay()|0)>>2]|0)|0)}}while(0);L1200:do{if((u&2|0)!=0){w=c[m>>2]|0;L1202:do{if((w|0)==0){l=b+76|0;if((c[l>>2]|0)!=0){q=884;break}g=b+40|0;if((c[g>>2]|0)!=0){aJ=l;q=885;break}h=b+24|0;p=c[h>>2]|0;i=c[f>>2]|0;c[m>>2]=0;j=b+4|0;v=0;while(1){aK=at(c[j>>2]|0,p+v|0,i-v|0)|0;if((aK|0)<1){q=878;break}k=(c[m>>2]|0)+aK|0;c[m>>2]=k;if(k>>>0>>0){v=k}else{aL=k;break}}do{if((q|0)==878){if((aK|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);aM=c[m>>2]|0;q=883;break L1202}else{c[g>>2]=1;aL=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[h>>2];if((aL|0)==0){aJ=l;q=885}else{aN=aL;q=882}}else{aN=w;q=882}}while(0);if((q|0)==882){w=aN-1|0;c[m>>2]=w;c[o>>2]=(c[o>>2]|0)+1;aM=w;q=883}if((q|0)==883){if((aM|0)==0){q=884}else{aO=aM}}if((q|0)==884){aJ=b+76|0;q=885}if((q|0)==885){if((c[aJ>>2]|0)!=0){break}w=b+40|0;if((c[w>>2]|0)!=0){break}g=b+24|0;v=c[g>>2]|0;i=c[f>>2]|0;c[m>>2]=0;p=b+4|0;j=0;while(1){aP=at(c[p>>2]|0,v+j|0,i-j|0)|0;if((aP|0)<1){q=890;break}k=(c[m>>2]|0)+aP|0;c[m>>2]=k;if(k>>>0>>0){j=k}else{aQ=k;break}}do{if((q|0)==890){if((aP|0)<0){bc(b,-1,az(c[(ay()|0)>>2]|0)|0);break L1200}else{c[w>>2]=1;aQ=c[m>>2]|0;break}}}while(0);c[b+84>>2]=c[g>>2];if((aQ|0)==0){break}else{aO=aQ}}c[m>>2]=aO-1;c[o>>2]=(c[o>>2]|0)+1}}while(0);bm(e)|0;c[b+132>>2]=a$(0,0,0)|0;c[b+52>>2]=2;c[b+56>>2]=0;n=0;return n|0}}while(0);bc(b,-3,13176);n=-1;return n|0}}while(0);bc(b,-3,13256);n=-1;return n|0}}while(0);e=b+28|0;a[c[e>>2]|0]=31;c[b+36>>2]=1;aR=c[m>>2]|0;aS=e}else{aR=t;aS=b+28|0}c[b+48>>2]=c[b+12>>2];t=c[aS>>2]|0;c[b+32>>2]=t;if((aR|0)!=0){aS=b+36|0;e=t+(c[aS>>2]|0)|0;t=c[o>>2]|0;bJ(e|0,t|0,aR)|0;c[aS>>2]=(c[aS>>2]|0)+(c[m>>2]|0);c[m>>2]=0}c[b+52>>2]=1;c[b+56>>2]=1;n=0;return n|0}function bg(a){a=a|0;var b=0,d=0;if((a|0)==0){b=-2;return b|0}if((c[a>>2]|0)!=7247){b=-2;return b|0}if((c[a+16>>2]|0)!=0){d=a+84|0;bu(d)|0;bG(c[a+28>>2]|0);bG(c[a+24>>2]|0)}bc(a,0,0);bG(c[a+8>>2]|0);d=an(c[a+4>>2]|0)|0;bG(a);b=((d|0)!=0)<<31>>31;return b|0}function bh(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0;e=a+84|0;f=a+88|0;g=c[f>>2]|0;L1259:do{if((g|0)==0){h=a+76|0;if((c[h>>2]|0)!=0){i=-1;j=934;break}k=a+40|0;if((c[k>>2]|0)!=0){l=-1;m=h;j=935;break}n=a+24|0;o=c[n>>2]|0;p=c[a+16>>2]|0;c[f>>2]=0;q=a+4|0;r=0;while(1){s=at(c[q>>2]|0,o+r|0,p-r|0)|0;if((s|0)<1){j=928;break}t=(c[f>>2]|0)+s|0;c[f>>2]=t;if(t>>>0

>>0){r=t}else{u=t;break}}do{if((j|0)==928){if((s|0)<0){bc(a,-1,az(c[(ay()|0)>>2]|0)|0);v=-1;w=c[f>>2]|0;j=933;break L1259}else{c[k>>2]=1;u=c[f>>2]|0;break}}}while(0);c[a+84>>2]=c[n>>2];if((u|0)==0){l=-1;m=h;j=935}else{x=u;j=932}}else{x=g;j=932}}while(0);if((j|0)==932){g=x-1|0;c[f>>2]=g;x=e|0;u=c[x>>2]|0;c[x>>2]=u+1;v=d[u]|0;w=g;j=933}if((j|0)==933){if((w|0)==0){i=v;j=934}else{y=w;z=v;j=946}}if((j|0)==934){l=i;m=a+76|0;j=935}L1278:do{if((j|0)==935){if((c[m>>2]|0)!=0){A=l-256|0;j=948;break}i=a+40|0;if((c[i>>2]|0)==0){v=a+24|0;w=c[v>>2]|0;g=c[a+16>>2]|0;c[f>>2]=0;u=a+4|0;x=0;while(1){B=at(c[u>>2]|0,w+x|0,g-x|0)|0;if((B|0)<1){j=941;break}s=(c[f>>2]|0)+B|0;c[f>>2]=s;if(s>>>0>>0){x=s}else{C=s;break}}do{if((j|0)==941){if((B|0)<0){bc(a,-1,az(c[(ay()|0)>>2]|0)|0);D=-256;E=l;F=c[f>>2]|0;j=947;break L1278}else{c[i>>2]=1;C=c[f>>2]|0;break}}}while(0);c[a+84>>2]=c[v>>2];if((C|0)!=0){y=C;z=l;j=946;break}}G=l-256|0;H=m;j=949}}while(0);if((j|0)==946){m=y-1|0;c[f>>2]=m;y=e|0;l=c[y>>2]|0;c[y>>2]=l+1;D=(d[l]|0)<<8;E=z;F=m;j=947}if((j|0)==947){m=D+E|0;if((F|0)==0){A=m;j=948}else{I=F;J=m;j=960}}if((j|0)==948){G=A;H=a+76|0;j=949}L1301:do{if((j|0)==949){if((c[H>>2]|0)!=0){K=G-65536|0;j=962;break}A=a+40|0;if((c[A>>2]|0)==0){m=a+24|0;F=c[m>>2]|0;E=c[a+16>>2]|0;c[f>>2]=0;D=a+4|0;z=0;while(1){L=at(c[D>>2]|0,F+z|0,E-z|0)|0;if((L|0)<1){j=955;break}l=(c[f>>2]|0)+L|0;c[f>>2]=l;if(l>>>0>>0){z=l}else{M=l;break}}do{if((j|0)==955){if((L|0)<0){bc(a,-1,az(c[(ay()|0)>>2]|0)|0);N=-65536;O=G;P=c[f>>2]|0;j=961;break L1301}else{c[A>>2]=1;M=c[f>>2]|0;break}}}while(0);c[a+84>>2]=c[m>>2];if((M|0)!=0){I=M;J=G;j=960;break}}Q=G-65536|0;R=H;j=963}}while(0);if((j|0)==960){H=I-1|0;c[f>>2]=H;I=e|0;G=c[I>>2]|0;c[I>>2]=G+1;N=(d[G]|0)<<16;O=J;P=H;j=961}if((j|0)==961){H=N+O|0;if((P|0)==0){K=H;j=962}else{S=P;T=H}}if((j|0)==962){Q=K;R=a+76|0;j=963}do{if((j|0)==963){if((c[R>>2]|0)!=0){U=-1;return U|0}K=a+40|0;if((c[K>>2]|0)!=0){U=-1;return U|0}H=a+24|0;P=c[H>>2]|0;O=c[a+16>>2]|0;c[f>>2]=0;N=a+4|0;J=0;while(1){V=at(c[N>>2]|0,P+J|0,O-J|0)|0;if((V|0)<1){j=968;break}G=(c[f>>2]|0)+V|0;c[f>>2]=G;if(G>>>0>>0){J=G}else{W=G;break}}do{if((j|0)==968){if((V|0)>=0){c[K>>2]=1;W=c[f>>2]|0;break}bc(a,-1,az(c[(ay()|0)>>2]|0)|0);U=-1;return U|0}}while(0);c[a+84>>2]=c[H>>2];if((W|0)==0){U=-1}else{S=W;T=Q;break}return U|0}}while(0);c[f>>2]=S-1;S=e|0;e=c[S>>2]|0;c[S>>2]=e+1;c[b>>2]=((d[e]|0)<<24)+T;U=0;return U|0}function bi(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;if((a|0)==0){e=0;return e|0}f=a;g=a+84|0;if((c[a>>2]|0)!=31153){e=0;return e|0}if((c[a+76>>2]|0)!=0){e=0;return e|0}if((d|0)<0){bc(f,-5,13520);e=0;return e|0}if((d|0)==0){e=0;return e|0}h=a+16|0;do{if((c[h>>2]|0)==0){if((bj(f)|0)==-1){e=0}else{break}return e|0}}while(0);i=a+72|0;L1366:do{if((c[i>>2]|0)!=0){c[i>>2]=0;j=c[a+68>>2]|0;k=a+88|0;do{if((c[k>>2]|0)!=0){if((bk(f,0)|0)==-1){e=0}else{break}return e|0}}while(0);l=a+24|0;m=g;n=a+12|0;o=j;p=1;while(1){if((o|0)==0){break L1366}q=c[h>>2]|0;r=(q|0)<0|(q|0)>(o|0)?o:q;if((p|0)!=0){bI(c[l>>2]|0,0,r|0)}c[k>>2]=r;c[m>>2]=c[l>>2];c[n>>2]=(c[n>>2]|0)+r;if((bk(f,0)|0)==-1){e=0;break}else{o=o-r|0;p=0}}return e|0}}while(0);i=a+88|0;L1380:do{if((c[h>>2]|0)>>>0>d>>>0){p=a+24|0;o=g;n=a+12|0;l=b;m=d;while(1){k=c[i>>2]|0;if((k|0)==0){j=c[p>>2]|0;c[o>>2]=j;s=j}else{s=c[o>>2]|0}j=(c[h>>2]|0)-k|0;r=j>>>0>m>>>0?m:j;j=s+k|0;bJ(j|0,l|0,r)|0;c[i>>2]=(c[i>>2]|0)+r;c[n>>2]=(c[n>>2]|0)+r;if((m|0)==(r|0)){break L1380}if((bk(f,0)|0)==-1){e=0;break}l=l+r|0;m=m-r|0}return e|0}else{do{if((c[i>>2]|0)!=0){if((bk(f,0)|0)==-1){e=0}else{break}return e|0}}while(0);c[i>>2]=d;c[g>>2]=b;m=a+12|0;c[m>>2]=(c[m>>2]|0)+d;if((bk(f,0)|0)==-1){e=0}else{break}return e|0}}while(0);e=d;return e|0}function bj(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;b=a+20|0;d=c[b>>2]|0;e=bF(d)|0;f=a+24|0;c[f>>2]=e;g=bF(d)|0;d=a+28|0;c[d>>2]=g;h=(g|0)==0;if(!((e|0)==0|h)){c[a+116>>2]=0;c[a+120>>2]=0;c[a+124>>2]=0;if((a0(a+84|0,c[a+60>>2]|0,8,31,8,c[a+64>>2]|0,13360,56)|0)==0){i=c[b>>2]|0;c[a+16>>2]=i;c[a+100>>2]=i;i=c[d>>2]|0;c[a+96>>2]=i;c[a+32>>2]=i;j=0;return j|0}else{bG(c[f>>2]|0);bc(a,-4,13448);j=-1;return j|0}}if(h){k=e}else{bG(g);k=c[f>>2]|0}if((k|0)!=0){bG(k)}bc(a,-4,13448);j=-1;return j|0}function bk(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;d=a+84|0;e=a+16|0;do{if((c[e>>2]|0)==0){if((bj(a)|0)==-1){f=-1}else{break}return f|0}}while(0);g=a+100|0;h=a+96|0;i=a+32|0;j=a+28|0;k=a+4|0;L1420:do{if((b|0)==4){l=0;m=c[g>>2]|0;while(1){if((m|0)==0|(l|0)==1){n=c[h>>2]|0;o=c[i>>2]|0;p=n-o|0;if((n|0)==(o|0)){q=m}else{n=as(c[k>>2]|0,o|0,p|0)|0;if(!((n|0)>-1&(n|0)==(p|0))){r=1062;break L1420}q=c[g>>2]|0}if((q|0)==0){p=c[e>>2]|0;c[g>>2]=p;n=c[j>>2]|0;c[h>>2]=n;s=p;t=n}else{s=q;t=c[h>>2]|0}c[i>>2]=t;u=s}else{u=m}n=a3(d,4)|0;if((n|0)==-2){r=1068;break L1420}p=c[g>>2]|0;if((u|0)==(p|0)){r=1070;break}else{l=n;m=p}}}else if((b|0)==0){m=c[g>>2]|0;while(1){if((m|0)==0){l=c[h>>2]|0;p=c[i>>2]|0;n=l-p|0;do{if((l|0)==(p|0)){r=1042}else{o=as(c[k>>2]|0,p|0,n|0)|0;if(!((o|0)>-1&(o|0)==(n|0))){r=1062;break L1420}o=c[g>>2]|0;if((o|0)==0){r=1042;break}v=o;w=c[h>>2]|0}}while(0);if((r|0)==1042){r=0;n=c[e>>2]|0;c[g>>2]=n;p=c[j>>2]|0;c[h>>2]=p;v=n;w=p}c[i>>2]=w;x=v}else{x=m}if((a3(d,0)|0)==-2){r=1068;break L1420}p=c[g>>2]|0;if((x|0)==(p|0)){r=1070;break}else{m=p}}}else{m=c[g>>2]|0;while(1){if((m|0)!=0&(b|0)==0){y=m}else{p=c[h>>2]|0;n=c[i>>2]|0;l=p-n|0;if((p|0)==(n|0)){z=m}else{p=as(c[k>>2]|0,n|0,l|0)|0;if(!((p|0)>-1&(p|0)==(l|0))){r=1062;break L1420}z=c[g>>2]|0}if((z|0)==0){l=c[e>>2]|0;c[g>>2]=l;p=c[j>>2]|0;c[h>>2]=p;A=l;B=p}else{A=z;B=c[h>>2]|0}c[i>>2]=B;y=A}if((a3(d,b)|0)==-2){r=1068;break L1420}p=c[g>>2]|0;if((y|0)==(p|0)){r=1070;break}else{m=p}}}}while(0);if((r|0)==1062){bc(a,-1,az(c[(ay()|0)>>2]|0)|0);f=-1;return f|0}else if((r|0)==1070){if((b|0)!=4){f=0;return f|0}a2(d)|0;f=0;return f|0}else if((r|0)==1068){bc(a,-2,13792);f=-1;return f|0}return 0}function bl(e,f){e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ab=0,ac=0,ad=0,ae=0,af=0,ag=0,ah=0,ai=0,aj=0,ak=0,al=0,am=0,an=0,ao=0,ap=0,aq=0,ar=0,as=0,at=0,au=0,av=0,aw=0,ax=0,ay=0,az=0,aA=0,aB=0,aC=0,aD=0,aE=0,aF=0,aG=0,aH=0,aI=0,aJ=0,aK=0,aL=0,aM=0,aN=0,aO=0,aP=0,aQ=0,aR=0,aS=0,aT=0,aU=0,aV=0,aW=0,aX=0;g=c[e+28>>2]|0;h=g;i=e|0;j=c[i>>2]|0;k=e+4|0;l=j+((c[k>>2]|0)-6)|0;m=e+12|0;n=c[m>>2]|0;o=e+16|0;p=c[o>>2]|0;q=n+(p-258)|0;r=c[h+44>>2]|0;s=c[h+48>>2]|0;t=c[h+52>>2]|0;u=h+56|0;v=h+60|0;w=c[h+76>>2]|0;x=c[h+80>>2]|0;y=(1<>2])-1|0;z=(1<>2])-1|0;A=n+(p+~f)|0;f=h+7104|0;p=t-1|0;B=(s|0)==0;C=(c[h+40>>2]|0)-1|0;h=C+s|0;D=s-1|0;E=A-1|0;F=A-s|0;G=j-1|0;j=n-1|0;n=c[u>>2]|0;H=c[v>>2]|0;L1476:while(1){if(H>>>0<15){I=G+2|0;J=I;K=((d[G+1|0]|0)<>1]|0;O=d[w+(I<<2)+1|0]|0;I=K>>>(O>>>0);P=L-O|0;do{if(M<<24>>24==0){Q=N&255;R=I;S=P;T=1083}else{O=N;U=I;V=P;W=M;while(1){X=W&255;if((X&16|0)!=0){break}if((X&64|0)!=0){T=1131;break L1476}Y=(U&(1<>1]|0;$=d[w+(Y<<2)+1|0]|0;aa=U>>>($>>>0);ab=V-$|0;if(Z<<24>>24==0){T=1082;break}else{O=_;U=aa;V=ab;W=Z}}if((T|0)==1082){T=0;Q=_&255;R=aa;S=ab;T=1083;break}W=O&65535;Z=X&15;if((Z|0)==0){ac=W;ad=J;ae=U;af=V}else{if(V>>>0>>0){$=J+1|0;ag=$;ah=((d[$]|0)<>>(Z>>>0);af=ai-Z|0}if(af>>>0<15){Z=ad+2|0;aj=Z;ak=((d[ad+1|0]|0)<>1]|0;$=d[x+(Z<<2)+1|0]|0;Y=ak>>>($>>>0);am=al-$|0;$=d[x+(Z<<2)|0]|0;if(($&16|0)==0){Z=W;an=Y;ao=am;ap=$;while(1){if((ap&64|0)!=0){T=1128;break L1476}aq=(an&(1<>1]|0;as=d[x+(aq<<2)+1|0]|0;at=an>>>(as>>>0);au=ao-as|0;as=d[x+(aq<<2)|0]|0;if((as&16|0)==0){Z=ar;an=at;ao=au;ap=as}else{av=ar;aw=at;ax=au;ay=as;break}}}else{av=W;aw=Y;ax=am;ay=$}ap=av&65535;Z=ay&15;do{if(ax>>>0>>0){O=aj+1|0;as=((d[O]|0)<>>0>=Z>>>0){az=O;aA=as;aB=au;break}O=aj+2|0;az=O;aA=((d[O]|0)<>>(Z>>>0);aD=aB-Z|0;am=j;Y=am-A|0;if($>>>0<=Y>>>0){W=j+(-$|0)|0;as=ac;au=j;while(1){a[au+1|0]=a[W+1|0]|0;a[au+2|0]=a[W+2|0]|0;O=W+3|0;aE=au+3|0;a[aE]=a[O]|0;aF=as-3|0;if(aF>>>0>2){W=O;as=aF;au=aE}else{break}}if((aF|0)==0){aG=az;aH=aE;aI=aC;aJ=aD;break}as=au+4|0;a[as]=a[W+4|0]|0;if(aF>>>0<=1){aG=az;aH=as;aI=aC;aJ=aD;break}as=au+5|0;a[as]=a[W+5|0]|0;aG=az;aH=as;aI=aC;aJ=aD;break}as=$-Y|0;if(as>>>0>r>>>0){if((c[f>>2]|0)!=0){T=1098;break L1476}}do{if(B){Z=t+(C-as)|0;if(as>>>0>=ac>>>0){aK=Z;aL=ac;aM=j;break}ap=ac-as|0;O=$-am|0;at=Z;Z=as;ar=j;do{at=at+1|0;ar=ar+1|0;a[ar]=a[at]|0;Z=Z-1|0;}while((Z|0)!=0);aK=j+(E+O+(1-$))|0;aL=ap;aM=j+(A+O)|0}else{if(s>>>0>=as>>>0){Z=t+(D-as)|0;if(as>>>0>=ac>>>0){aK=Z;aL=ac;aM=j;break}at=ac-as|0;ar=$-am|0;aq=Z;Z=as;aN=j;do{aq=aq+1|0;aN=aN+1|0;a[aN]=a[aq]|0;Z=Z-1|0;}while((Z|0)!=0);aK=j+(E+ar+(1-$))|0;aL=at;aM=j+(A+ar)|0;break}Z=t+(h-as)|0;aq=as-s|0;if(aq>>>0>=ac>>>0){aK=Z;aL=ac;aM=j;break}aN=ac-aq|0;O=$-am|0;ap=Z;Z=aq;aq=j;do{ap=ap+1|0;aq=aq+1|0;a[aq]=a[ap]|0;Z=Z-1|0;}while((Z|0)!=0);Z=j+(F+O)|0;if(s>>>0>=aN>>>0){aK=p;aL=aN;aM=Z;break}ap=aN-s|0;aq=p;ar=s;at=Z;do{aq=aq+1|0;at=at+1|0;a[at]=a[aq]|0;ar=ar-1|0;}while((ar|0)!=0);aK=j+(E+O+(1-$))|0;aL=ap;aM=j+(A+O)|0}}while(0);if(aL>>>0>2){$=aM;am=aL;as=aK;while(1){a[$+1|0]=a[as+1|0]|0;a[$+2|0]=a[as+2|0]|0;Y=as+3|0;W=$+3|0;a[W]=a[Y]|0;au=am-3|0;if(au>>>0>2){$=W;am=au;as=Y}else{aO=W;aP=au;aQ=Y;break}}}else{aO=aM;aP=aL;aQ=aK}if((aP|0)==0){aG=az;aH=aO;aI=aC;aJ=aD;break}as=aO+1|0;a[as]=a[aQ+1|0]|0;if(aP>>>0<=1){aG=az;aH=as;aI=aC;aJ=aD;break}as=aO+2|0;a[as]=a[aQ+2|0]|0;aG=az;aH=as;aI=aC;aJ=aD}}while(0);if((T|0)==1083){T=0;M=j+1|0;a[M]=Q;aG=J;aH=M;aI=R;aJ=S}if(aG>>>0>>0&aH>>>0>>0){G=aG;j=aH;n=aI;H=aJ}else{aR=aG;aS=aH;aT=aI;aU=aJ;break}}do{if((T|0)==1128){c[e+24>>2]=13712;c[g>>2]=29;aR=aj;aS=j;aT=an;aU=ao}else if((T|0)==1131){if((X&32|0)==0){c[e+24>>2]=13416;c[g>>2]=29;aR=J;aS=j;aT=U;aU=V;break}else{c[g>>2]=11;aR=J;aS=j;aT=U;aU=V;break}}else if((T|0)==1098){c[e+24>>2]=13304;c[g>>2]=29;aR=az;aS=j;aT=aC;aU=aD}}while(0);aD=aU>>>3;aC=aR+(-aD|0)|0;j=aU-(aD<<3)|0;aU=(1<>2]=aR+(1-aD);c[m>>2]=aS+1;if(aC>>>0>>0){aV=l-aC|0}else{aV=l-aC|0}c[k>>2]=aV+5;if(aS>>>0>>0){aW=q-aS|0;aX=aW+257|0;c[o>>2]=aX;c[u>>2]=aU;c[v>>2]=j;return}else{aW=q-aS|0;aX=aW+257|0;c[o>>2]=aX;c[u>>2]=aU;c[v>>2]=j;return}}function bm(a){a=a|0;var b=0,d=0,e=0;if((a|0)==0){b=-2;return b|0}d=c[a+28>>2]|0;if((d|0)==0){b=-2;return b|0}e=d;c[e+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[d>>2]=0;c[e+4>>2]=0;c[e+12>>2]=0;c[e+20>>2]=32768;c[e+32>>2]=0;c[e+40>>2]=0;c[e+44>>2]=0;c[e+48>>2]=0;c[e+56>>2]=0;c[e+60>>2]=0;d=e+1328|0;c[e+108>>2]=d;c[e+80>>2]=d;c[e+76>>2]=d;c[e+7104>>2]=1;c[e+7108>>2]=-1;b=0;return b|0}function bn(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;if((a|0)==0){b=-2;return b|0}d=a;if((c[a>>2]|0)!=31153){b=-2;return b|0}e=a+72|0;L1582:do{if((c[e>>2]|0)==0){f=0}else{c[e>>2]=0;g=c[a+68>>2]|0;h=a+88|0;if((c[h>>2]|0)!=0){if((bk(d,0)|0)==-1){f=-1;break}}i=a+16|0;j=a+24|0;k=a+84|0;l=a+12|0;m=g;g=1;while(1){if((m|0)==0){f=0;break L1582}n=c[i>>2]|0;o=(n|0)<0|(n|0)>(m|0)?m:n;if((g|0)!=0){bI(c[j>>2]|0,0,o|0)}c[h>>2]=o;c[k>>2]=c[j>>2];c[l>>2]=(c[l>>2]|0)+o;if((bk(d,0)|0)==-1){f=-1;break}else{m=m-o|0;g=0}}}}while(0);e=(bk(d,4)|0)+f|0;a1(a+84|0)|0;bG(c[a+28>>2]|0);bG(c[a+24>>2]|0);bc(d,0,0);bG(c[a+8>>2]|0);d=an(c[a+4>>2]|0)|0;bG(a);b=((e|0)!=(-d|0))<<31>>31;return b|0}function bo(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;if((a|0)==0){d=-2;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;return d|0}g=f;if((b|0)<0){h=0;i=-b|0}else{h=(b>>4)+1|0;i=(b|0)<48?b&15:b}if((i|0)!=0&(i-8|0)>>>0>7){d=-2;return d|0}b=g+52|0;f=c[b>>2]|0;j=g+36|0;do{if((f|0)!=0){if((c[j>>2]|0)==(i|0)){break}aF[c[a+36>>2]&3](c[a+40>>2]|0,f);c[b>>2]=0}}while(0);c[g+8>>2]=h;c[j>>2]=i;i=c[e>>2]|0;if((i|0)==0){d=-2;return d|0}e=i;c[e+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[i>>2]=0;c[e+4>>2]=0;c[e+12>>2]=0;c[e+20>>2]=32768;c[e+32>>2]=0;c[e+40>>2]=0;c[e+44>>2]=0;c[e+48>>2]=0;c[e+56>>2]=0;c[e+60>>2]=0;i=e+1328|0;c[e+108>>2]=i;c[e+80>>2]=i;c[e+76>>2]=i;c[e+7104>>2]=1;c[e+7108>>2]=-1;d=0;return d|0}function bp(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;if((e|0)==0){g=-6;return g|0}if(!((a[e]|0)==49&(f|0)==56)){g=-6;return g|0}if((b|0)==0){g=-2;return g|0}c[b+24>>2]=0;f=b+32|0;e=c[f>>2]|0;if((e|0)==0){c[f>>2]=6;c[b+40>>2]=0;h=6}else{h=e}e=b+36|0;if((c[e>>2]|0)==0){c[e>>2]=2}f=b+40|0;i=aG[h&7](c[f>>2]|0,1,7116)|0;if((i|0)==0){g=-4;return g|0}h=b+28|0;c[h>>2]=i;c[i+52>>2]=0;j=bo(b,d)|0;if((j|0)==0){g=0;return g|0}aF[c[e>>2]&3](c[f>>2]|0,i);c[h>>2]=0;g=j;return g|0}function bq(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ab=0,ac=0,ad=0,ae=0,af=0,ag=0,ah=0,ai=0,aj=0,ak=0,al=0,am=0,an=0,ao=0,ap=0,aq=0,ar=0,as=0,at=0,au=0,av=0,aw=0,ax=0,ay=0,az=0,aA=0,aC=0,aD=0,aE=0,aF=0,aG=0,aH=0,aI=0,aJ=0,aK=0,aL=0,aM=0,aN=0,aO=0,aP=0,aQ=0,aR=0,aS=0,aT=0,aU=0,aV=0,aW=0,aX=0,aY=0,aZ=0,a0=0,a1=0,a2=0,a3=0,a4=0,a5=0,a6=0,a7=0,a8=0,a9=0,ba=0,bb=0,bc=0,bd=0,be=0,bf=0,bg=0,bh=0,bi=0,bj=0,bk=0,bm=0,bn=0,bo=0,bp=0,bq=0,br=0,bs=0,bu=0,bw=0,bx=0,by=0,bz=0,bA=0,bB=0,bC=0,bD=0,bE=0,bF=0,bG=0,bH=0,bI=0,bK=0,bL=0,bM=0,bN=0,bO=0,bP=0,bQ=0,bR=0,bS=0,bT=0,bU=0,bV=0,bW=0,bX=0,bY=0,bZ=0,b_=0,b$=0,b0=0,b1=0,b2=0,b3=0,b4=0,b5=0,b6=0,b7=0,b8=0,b9=0,ca=0,cb=0,cc=0,cd=0,ce=0,cf=0,cg=0,ch=0,ci=0,cj=0,ck=0,cl=0,cm=0,cn=0,co=0,cp=0,cq=0,cr=0,cs=0,ct=0,cu=0,cv=0,cw=0,cx=0,cy=0,cz=0,cA=0,cB=0,cC=0,cD=0,cE=0,cF=0,cG=0,cH=0,cI=0,cJ=0,cK=0,cL=0,cM=0,cN=0,cO=0,cP=0,cQ=0,cR=0,cS=0,cT=0,cU=0,cV=0,cW=0,cX=0,cY=0,cZ=0,c_=0,c$=0,c0=0,c1=0,c2=0,c3=0,c4=0,c5=0,c6=0,c7=0,c8=0,c9=0,da=0,db=0,dc=0,dd=0,de=0,df=0,dg=0,dh=0,di=0,dj=0,dk=0,dl=0,dm=0,dn=0,dp=0,dq=0,dr=0,ds=0,dt=0,du=0,dv=0,dw=0,dx=0,dy=0,dz=0,dA=0,dB=0,dC=0,dD=0,dE=0,dF=0,dG=0,dH=0,dI=0,dJ=0,dK=0,dL=0,dM=0,dN=0,dO=0,dP=0,dQ=0,dR=0,dS=0,dT=0,dU=0,dV=0,dW=0,dX=0,dY=0,dZ=0,d_=0,d$=0,d0=0,d1=0,d2=0,d3=0,d4=0,d5=0,d6=0,d7=0,d8=0,d9=0,ea=0,eb=0,ec=0,ed=0,ee=0,ef=0,eg=0,eh=0,ei=0,ej=0,ek=0,el=0,em=0,en=0,eo=0,ep=0,eq=0,er=0,es=0,et=0,eu=0,ev=0,ew=0,ex=0,ey=0,ez=0,eA=0,eB=0,eC=0,eD=0,eE=0,eF=0,eG=0,eH=0,eI=0,eJ=0,eK=0,eL=0,eM=0,eN=0,eO=0,eP=0,eQ=0,eR=0,eS=0,eT=0,eU=0,eV=0,eW=0,eX=0,eY=0,eZ=0,e_=0,e$=0,e0=0,e1=0,e2=0,e3=0,e4=0,e5=0,e6=0,e7=0,e8=0,e9=0,fa=0,fb=0,fc=0,fd=0,fe=0,ff=0,fg=0,fh=0,fi=0,fj=0,fk=0,fl=0,fm=0,fn=0,fo=0,fp=0,fq=0,fr=0,fs=0,ft=0,fu=0,fv=0,fw=0,fx=0,fy=0,fz=0,fA=0,fB=0,fC=0,fD=0,fE=0,fF=0,fG=0,fH=0,fI=0,fJ=0,fK=0,fL=0,fM=0,fN=0,fO=0,fP=0,fQ=0,fR=0;h=i;i=i+8|0;j=h|0;if((f|0)==0){k=-2;i=h;return k|0}l=c[f+28>>2]|0;if((l|0)==0){k=-2;i=h;return k|0}m=f+12|0;n=c[m>>2]|0;if((n|0)==0){k=-2;i=h;return k|0}o=f|0;p=c[o>>2]|0;do{if((p|0)==0){if((c[f+4>>2]|0)==0){break}else{k=-2}i=h;return k|0}}while(0);q=l;r=l;l=c[r>>2]|0;if((l|0)==11){c[r>>2]=12;s=c[m>>2]|0;t=c[o>>2]|0;u=12}else{s=n;t=p;u=l}l=f+16|0;p=c[l>>2]|0;n=f+4|0;v=c[n>>2]|0;w=q+56|0;x=q+60|0;y=q+8|0;z=q+24|0;A=j|0;B=j+1|0;C=q+16|0;D=q+32|0;E=f+24|0;F=q+36|0;G=q+20|0;H=f+48|0;I=q+64|0;J=q+12|0;K=(g-5|0)>>>0<2;L=q+4|0;M=q+76|0;N=q+84|0;O=q+80|0;P=q+88|0;Q=(g|0)==6;R=q+7108|0;S=q+72|0;T=q+7112|0;U=q+68|0;V=q+44|0;W=q+7104|0;X=q+48|0;Y=q+52|0;Z=q+40|0;_=f+20|0;$=q+28|0;aa=q+96|0;ab=q+100|0;ac=q+92|0;ad=q+104|0;ae=q+1328|0;af=q+108|0;ag=q+112|0;ah=q+752|0;ai=q+624|0;aj=j+2|0;ak=j+3|0;j=0;al=p;am=c[x>>2]|0;an=c[w>>2]|0;ao=p;p=v;ap=s;s=t;t=u;L1657:while(1){L1659:do{if((t|0)==2){if(am>>>0<32){aq=s;ar=p;as=an;at=am;au=1246}else{av=s;aw=p;ax=an;au=1248}}else if((t|0)==7){ay=am;az=an;aA=p;aC=s;au=1295}else if((t|0)==9){if(am>>>0<32){u=s;aD=p;aE=an;aF=am;while(1){if((aD|0)==0){aG=j;aH=al;aI=aF;aJ=aE;aK=0;aL=u;aM=ao;break L1657}aN=aD-1|0;aO=u+1|0;aP=(d[u]<>>0<32){u=aO;aD=aN;aE=aP;aF=aQ}else{aR=aO;aS=aN;aT=aP;break}}}else{aR=s;aS=p;aT=an}aF=aB(aT|0)|0;c[z>>2]=aF;c[H>>2]=aF;c[r>>2]=10;aU=0;aV=0;aW=aS;aX=aR;au=1320}else if((t|0)==1){if(am>>>0<16){aF=s;aE=p;aD=an;u=am;while(1){if((aE|0)==0){aG=j;aH=al;aI=u;aJ=aD;aK=0;aL=aF;aM=ao;break L1657}aP=aE-1|0;aN=aF+1|0;aO=(d[aF]<>>0<16){aF=aN;aE=aP;aD=aO;u=aQ}else{aY=aN;aZ=aP;a0=aO;a1=aQ;break}}}else{aY=s;aZ=p;a0=an;a1=am}c[C>>2]=a0;if((a0&255|0)!=8){c[E>>2]=13384;c[r>>2]=29;a2=j;a3=al;a4=a1;a5=a0;a6=ao;a7=aZ;a8=ap;a9=aY;break}if((a0&57344|0)!=0){c[E>>2]=13224;c[r>>2]=29;a2=j;a3=al;a4=a1;a5=a0;a6=ao;a7=aZ;a8=ap;a9=aY;break}u=c[D>>2]|0;if((u|0)==0){ba=a0}else{c[u>>2]=a0>>>8&1;ba=c[C>>2]|0}if((ba&512|0)!=0){a[A]=a0&255;a[B]=a0>>>8&255;c[z>>2]=a$(c[z>>2]|0,A,2)|0}c[r>>2]=2;aq=aY;ar=aZ;as=0;at=0;au=1246}else if((t|0)==5){bb=am;bc=an;bd=p;be=s;au=1272}else if((t|0)==21){bf=j;bg=am;bh=an;bi=p;bj=s;bk=c[S>>2]|0;au=1419}else if((t|0)==17){u=c[ad>>2]|0;if(u>>>0<(c[ac>>2]|0)>>>0){bm=s;bn=p;bo=an;bp=am;bq=u;au=1353}else{br=s;bs=p;bu=an;bw=am;bx=u;au=1357}}else if((t|0)==18){by=j;bz=am;bA=an;bB=p;bC=s;bD=c[ad>>2]|0;au=1362}else if((t|0)==12){bE=am;bF=an;bG=p;bH=s;au=1324}else if((t|0)==25){if((ao|0)==0){bI=j;bK=am;bL=an;bM=p;bN=s;bO=0;au=1483;break L1657}a[ap]=c[I>>2]&255;c[r>>2]=20;a2=j;a3=al;a4=am;a5=an;a6=ao-1|0;a7=p;a8=ap+1|0;a9=s}else if((t|0)==26){do{if((c[y>>2]|0)==0){bP=al;bQ=am;bR=an;bS=p;bT=s}else{if(am>>>0<32){u=s;aD=p;aE=an;aF=am;while(1){if((aD|0)==0){aG=j;aH=al;aI=aF;aJ=aE;aK=0;aL=u;aM=ao;break L1657}aQ=aD-1|0;aO=u+1|0;aP=(d[u]<>>0<32){u=aO;aD=aQ;aE=aP;aF=aN}else{bU=aO;bV=aQ;bW=aP;bX=aN;break}}}else{bU=s;bV=p;bW=an;bX=am}aF=al-ao|0;c[_>>2]=(c[_>>2]|0)+aF;c[$>>2]=(c[$>>2]|0)+aF;if((al|0)!=(ao|0)){aE=c[z>>2]|0;aD=ap+(-aF|0)|0;if((c[C>>2]|0)==0){bY=a_(aE,aD,aF)|0}else{bY=a$(aE,aD,aF)|0}c[z>>2]=bY;c[H>>2]=bY}if((c[C>>2]|0)==0){bZ=aB(bW|0)|0}else{bZ=bW}if((bZ|0)==(c[z>>2]|0)){bP=ao;bQ=0;bR=0;bS=bV;bT=bU;break}c[E>>2]=13576;c[r>>2]=29;a2=j;a3=ao;a4=bX;a5=bW;a6=ao;a7=bV;a8=ap;a9=bU;break L1659}}while(0);c[r>>2]=27;b_=bP;b$=bQ;b0=bR;b1=bS;b2=bT;au=1475}else if((t|0)==27){b_=al;b$=am;b0=an;b1=p;b2=s;au=1475}else if((t|0)==28){bI=1;bK=am;bL=an;bM=p;bN=s;bO=ao;au=1483;break L1657}else if((t|0)==29){aG=-3;aH=al;aI=am;aJ=an;aK=p;aL=s;aM=ao;break L1657}else if((t|0)==0){aF=c[y>>2]|0;if((aF|0)==0){c[r>>2]=12;a2=j;a3=al;a4=am;a5=an;a6=ao;a7=p;a8=ap;a9=s;break}if(am>>>0<16){aD=s;aE=p;u=an;aN=am;while(1){if((aE|0)==0){aG=j;aH=al;aI=aN;aJ=u;aK=0;aL=aD;aM=ao;break L1657}aP=aE-1|0;aQ=aD+1|0;aO=(d[aD]<>>0<16){aD=aQ;aE=aP;u=aO;aN=b3}else{b4=aQ;b5=aP;b6=aO;b7=b3;break}}}else{b4=s;b5=p;b6=an;b7=am}if((aF&2|0)!=0&(b6|0)==35615){c[z>>2]=a$(0,0,0)|0;a[A]=31;a[B]=-117;c[z>>2]=a$(c[z>>2]|0,A,2)|0;c[r>>2]=1;a2=j;a3=al;a4=0;a5=0;a6=ao;a7=b5;a8=ap;a9=b4;break}c[C>>2]=0;aN=c[D>>2]|0;if((aN|0)==0){b8=aF}else{c[aN+48>>2]=-1;b8=c[y>>2]|0}do{if((b8&1|0)!=0){if(((((b6<<8&65280)+(b6>>>8)|0)>>>0)%31|0|0)!=0){break}if((b6&15|0)!=8){c[E>>2]=13384;c[r>>2]=29;a2=j;a3=al;a4=b7;a5=b6;a6=ao;a7=b5;a8=ap;a9=b4;break L1659}aN=b6>>>4;u=b7-4|0;aE=(aN&15)+8|0;aD=c[F>>2]|0;do{if((aD|0)==0){c[F>>2]=aE}else{if(aE>>>0<=aD>>>0){break}c[E>>2]=13336;c[r>>2]=29;a2=j;a3=al;a4=u;a5=aN;a6=ao;a7=b5;a8=ap;a9=b4;break L1659}}while(0);c[G>>2]=1<>2]=aN;c[H>>2]=aN;c[r>>2]=b6>>>12&2^11;a2=j;a3=al;a4=0;a5=0;a6=ao;a7=b5;a8=ap;a9=b4;break L1659}}while(0);c[E>>2]=13656;c[r>>2]=29;a2=j;a3=al;a4=b7;a5=b6;a6=ao;a7=b5;a8=ap;a9=b4}else if((t|0)==16){if(am>>>0<14){aF=s;aN=p;u=an;aD=am;while(1){if((aN|0)==0){aG=j;aH=al;aI=aD;aJ=u;aK=0;aL=aF;aM=ao;break L1657}b3=aN-1|0;aO=aF+1|0;aP=(d[aF]<>>0<14){aF=aO;aN=b3;u=aP;aD=aQ}else{b9=aO;ca=b3;cb=aP;cc=aQ;break}}}else{b9=s;ca=p;cb=an;cc=am}aD=(cb&31)+257|0;c[aa>>2]=aD;u=(cb>>>5&31)+1|0;c[ab>>2]=u;c[ac>>2]=(cb>>>10&15)+4;aN=cb>>>14;aF=cc-14|0;if(aD>>>0>286|u>>>0>30){c[E>>2]=12896;c[r>>2]=29;a2=j;a3=al;a4=aF;a5=aN;a6=ao;a7=ca;a8=ap;a9=b9;break}else{c[ad>>2]=0;c[r>>2]=17;bm=b9;bn=ca;bo=aN;bp=aF;bq=0;au=1353;break}}else if((t|0)==3){if(am>>>0<16){cd=s;ce=p;cf=an;cg=am;au=1254}else{ch=s;ci=p;cj=an;au=1256}}else if((t|0)==8){ck=am;cl=an;cm=p;cn=s;au=1308}else if((t|0)==23){co=j;cp=am;cq=an;cr=p;cs=s;ct=c[S>>2]|0;au=1438}else if((t|0)==4){cu=am;cv=an;cw=p;cx=s;au=1261}else if((t|0)==30){au=1497;break L1657}else if((t|0)==22){cy=j;cz=am;cA=an;cB=p;cC=s;au=1426}else if((t|0)==24){cD=j;cE=am;cF=an;cG=p;cH=s;au=1444}else if((t|0)==14){cI=am;cJ=an;cK=p;cL=s;au=1342}else if((t|0)==15){cM=am;cN=an;cO=p;cP=s;au=1343}else if((t|0)==19){cQ=j;cR=am;cS=an;cT=p;cU=s;au=1399}else if((t|0)==20){cV=j;cW=am;cX=an;cY=p;cZ=s;au=1400}else if((t|0)==13){aF=am&7;aN=an>>>(aF>>>0);u=am-aF|0;if(u>>>0<32){aF=s;aD=p;aQ=aN;aP=u;while(1){if((aD|0)==0){aG=j;aH=al;aI=aP;aJ=aQ;aK=0;aL=aF;aM=ao;break L1657}b3=aD-1|0;aO=aF+1|0;c_=(d[aF]<>>0<32){aF=aO;aD=b3;aQ=c_;aP=c$}else{c0=aO;c1=b3;c2=c_;c3=c$;break}}}else{c0=s;c1=p;c2=aN;c3=u}aP=c2&65535;if((aP|0)==(c2>>>16^65535|0)){c[I>>2]=aP;c[r>>2]=14;if(Q){bI=j;bK=0;bL=0;bM=c1;bN=c0;bO=ao;au=1483;break L1657}else{cI=0;cJ=0;cK=c1;cL=c0;au=1342;break}}else{c[E>>2]=12992;c[r>>2]=29;a2=j;a3=al;a4=c3;a5=c2;a6=ao;a7=c1;a8=ap;a9=c0;break}}else if((t|0)==10){aU=am;aV=an;aW=p;aX=s;au=1320}else if((t|0)==11){c4=am;c5=an;c6=p;c7=s;au=1323}else if((t|0)==6){c8=am;c9=an;da=p;db=s;au=1282}else{k=-2;au=1500;break L1657}}while(0);if((au|0)==1246){while(1){au=0;if((ar|0)==0){aG=j;aH=al;aI=at;aJ=as;aK=0;aL=aq;aM=ao;break L1657}aP=ar-1|0;aQ=aq+1|0;aD=(d[aq]<>>0<32){aq=aQ;ar=aP;as=aD;at=aF;au=1246}else{av=aQ;aw=aP;ax=aD;au=1248;break}}}else if((au|0)==1353){while(1){au=0;if(bp>>>0<3){aD=bm;aP=bn;aQ=bo;aF=bp;while(1){if((aP|0)==0){aG=j;aH=al;aI=aF;aJ=aQ;aK=0;aL=aD;aM=ao;break L1657}c$=aP-1|0;c_=aD+1|0;b3=(d[aD]<>>0<3){aD=c_;aP=c$;aQ=b3;aF=aO}else{dc=c_;dd=c$;de=b3;df=aO;break}}}else{dc=bm;dd=bn;de=bo;df=bp}c[ad>>2]=bq+1;b[q+112+(e[1664+(bq<<1)>>1]<<1)>>1]=de&7;aF=de>>>3;aQ=df-3|0;aP=c[ad>>2]|0;if(aP>>>0<(c[ac>>2]|0)>>>0){bm=dc;bn=dd;bo=aF;bp=aQ;bq=aP;au=1353}else{br=dc;bs=dd;bu=aF;bw=aQ;bx=aP;au=1357;break}}}else if((au|0)==1475){au=0;if((c[y>>2]|0)==0){dg=b$;dh=b0;di=b1;dj=b2;au=1482;break}if((c[C>>2]|0)==0){dg=b$;dh=b0;di=b1;dj=b2;au=1482;break}if(b$>>>0<32){aP=b2;aQ=b1;aF=b0;aD=b$;while(1){if((aQ|0)==0){aG=j;aH=b_;aI=aD;aJ=aF;aK=0;aL=aP;aM=ao;break L1657}u=aQ-1|0;aN=aP+1|0;aO=(d[aP]<>>0<32){aP=aN;aQ=u;aF=aO;aD=b3}else{dk=aN;dl=u;dm=aO;dn=b3;break}}}else{dk=b2;dl=b1;dm=b0;dn=b$}if((dm|0)==(c[$>>2]|0)){dg=0;dh=0;di=dl;dj=dk;au=1482;break}c[E>>2]=13496;c[r>>2]=29;a2=j;a3=b_;a4=dn;a5=dm;a6=ao;a7=dl;a8=ap;a9=dk}else if((au|0)==1342){au=0;c[r>>2]=15;cM=cI;cN=cJ;cO=cK;cP=cL;au=1343}else if((au|0)==1320){au=0;if((c[J>>2]|0)==0){au=1321;break}aD=a_(0,0,0)|0;c[z>>2]=aD;c[H>>2]=aD;c[r>>2]=11;c4=aU;c5=aV;c6=aW;c7=aX;au=1323}do{if((au|0)==1357){au=0;if(bx>>>0<19){aD=bx;do{c[ad>>2]=aD+1;b[q+112+(e[1664+(aD<<1)>>1]<<1)>>1]=0;aD=c[ad>>2]|0;}while(aD>>>0<19)}c[af>>2]=ae;c[M>>2]=ae;c[N>>2]=7;aD=bv(0,ag,19,af,N,ah)|0;if((aD|0)==0){c[ad>>2]=0;c[r>>2]=18;by=0;bz=bw;bA=bu;bB=bs;bC=br;bD=0;au=1362;break}else{c[E>>2]=12776;c[r>>2]=29;a2=aD;a3=al;a4=bw;a5=bu;a6=ao;a7=bs;a8=ap;a9=br;break}}else if((au|0)==1343){au=0;aD=c[I>>2]|0;if((aD|0)==0){c[r>>2]=11;a2=j;a3=al;a4=cM;a5=cN;a6=ao;a7=cO;a8=ap;a9=cP;break}aF=aD>>>0>cO>>>0?cO:aD;aD=aF>>>0>ao>>>0?ao:aF;if((aD|0)==0){bI=j;bK=cM;bL=cN;bM=cO;bN=cP;bO=ao;au=1483;break L1657}bJ(ap|0,cP|0,aD)|0;c[I>>2]=(c[I>>2]|0)-aD;a2=j;a3=al;a4=cM;a5=cN;a6=ao-aD|0;a7=cO-aD|0;a8=ap+aD|0;a9=cP+aD|0}else if((au|0)==1323){au=0;if(K){bI=j;bK=c4;bL=c5;bM=c6;bN=c7;bO=ao;au=1483;break L1657}else{bE=c4;bF=c5;bG=c6;bH=c7;au=1324}}else if((au|0)==1248){au=0;aD=c[D>>2]|0;if((aD|0)!=0){c[aD+4>>2]=ax}if((c[C>>2]&512|0)!=0){a[A]=ax&255;a[B]=ax>>>8&255;a[aj]=ax>>>16&255;a[ak]=ax>>>24&255;c[z>>2]=a$(c[z>>2]|0,A,4)|0}c[r>>2]=3;cd=av;ce=aw;cf=0;cg=0;au=1254}}while(0);L1802:do{if((au|0)==1324){au=0;if((c[L>>2]|0)!=0){aD=bE&7;c[r>>2]=26;a2=j;a3=al;a4=bE-aD|0;a5=bF>>>(aD>>>0);a6=ao;a7=bG;a8=ap;a9=bH;break}if(bE>>>0<3){aD=bH;aF=bG;aQ=bF;aP=bE;while(1){if((aF|0)==0){aG=j;aH=al;aI=aP;aJ=aQ;aK=0;aL=aD;aM=ao;break L1657}b3=aF-1|0;aO=aD+1|0;u=(d[aD]<>>0<3){aD=aO;aF=b3;aQ=u;aP=aN}else{dp=aO;dq=b3;dr=u;ds=aN;break}}}else{dp=bH;dq=bG;dr=bF;ds=bE}c[L>>2]=dr&1;aP=dr>>>1&3;if((aP|0)==0){c[r>>2]=13}else if((aP|0)==1){c[M>>2]=1704;c[N>>2]=9;c[O>>2]=3752;c[P>>2]=5;c[r>>2]=19;if(Q){au=1332;break L1657}}else if((aP|0)==2){c[r>>2]=16}else if((aP|0)==3){c[E>>2]=13088;c[r>>2]=29}a2=j;a3=al;a4=ds-3|0;a5=dr>>>3;a6=ao;a7=dq;a8=ap;a9=dp}else if((au|0)==1362){au=0;aP=c[aa>>2]|0;aQ=c[ab>>2]|0;do{if(bD>>>0<(aQ+aP|0)>>>0){aF=bC;aD=bB;aN=bA;u=bz;b3=bD;aO=aP;c$=aQ;L1820:while(1){c_=(1<>2])-1|0;dt=c_&aN;du=c[M>>2]|0;dv=d[du+(dt<<2)+1|0]|0;if(dv>>>0>u>>>0){dw=aF;dx=aD;dy=aN;dz=u;while(1){if((dx|0)==0){aG=by;aH=al;aI=dz;aJ=dy;aK=0;aL=dw;aM=ao;break L1657}dA=dx-1|0;dB=dw+1|0;dC=(d[dw]<>>0>dD>>>0){dw=dB;dx=dA;dy=dC;dz=dD}else{dG=dB;dH=dA;dI=dC;dJ=dD;dK=dE;dL=dF;break}}}else{dG=aF;dH=aD;dI=aN;dJ=u;dK=dt;dL=dv}dz=b[du+(dK<<2)+2>>1]|0;L1827:do{if((dz&65535)<16){if(dJ>>>0

>>0){dy=dG;dx=dH;dw=dI;c_=dJ;while(1){if((dx|0)==0){aG=by;aH=al;aI=c_;aJ=dw;aK=0;aL=dy;aM=ao;break L1657}dF=dx-1|0;dE=dy+1|0;dD=(d[dy]<>>0
>>0){dy=dE;dx=dF;dw=dD;c_=dC}else{dM=dE;dN=dF;dO=dD;dP=dC;break}}}else{dM=dG;dN=dH;dO=dI;dP=dJ}c[ad>>2]=b3+1;b[q+112+(b3<<1)>>1]=dz;dQ=dP-dL|0;dR=dO>>>(dL>>>0);dS=dN;dT=dM}else{if((dz<<16>>16|0)==16){c_=dL+2|0;if(dJ>>>0>>0){dw=dG;dx=dH;dy=dI;dC=dJ;while(1){if((dx|0)==0){aG=by;aH=al;aI=dC;aJ=dy;aK=0;aL=dw;aM=ao;break L1657}dD=dx-1|0;dF=dw+1|0;dE=(d[dw]<>>0>>0){dw=dF;dx=dD;dy=dE;dC=dA}else{dU=dF;dV=dD;dW=dE;dX=dA;break}}}else{dU=dG;dV=dH;dW=dI;dX=dJ}dY=dW>>>(dL>>>0);dZ=dX-dL|0;if((b3|0)==0){au=1379;break L1820}d_=b[q+112+(b3-1<<1)>>1]|0;d$=(dY&3)+3|0;d0=dZ-2|0;d1=dY>>>2;d2=dV;d3=dU}else if((dz<<16>>16|0)==17){dC=dL+3|0;if(dJ>>>0>>0){dy=dG;dx=dH;dw=dI;c_=dJ;while(1){if((dx|0)==0){aG=by;aH=al;aI=c_;aJ=dw;aK=0;aL=dy;aM=ao;break L1657}dA=dx-1|0;dE=dy+1|0;dD=(d[dy]<>>0>>0){dy=dE;dx=dA;dw=dD;c_=dF}else{d4=dE;d5=dA;d6=dD;d7=dF;break}}}else{d4=dG;d5=dH;d6=dI;d7=dJ}c_=d6>>>(dL>>>0);d_=0;d$=(c_&7)+3|0;d0=-3-dL+d7|0;d1=c_>>>3;d2=d5;d3=d4}else{c_=dL+7|0;if(dJ>>>0>>0){dw=dG;dx=dH;dy=dI;dC=dJ;while(1){if((dx|0)==0){aG=by;aH=al;aI=dC;aJ=dy;aK=0;aL=dw;aM=ao;break L1657}dF=dx-1|0;dD=dw+1|0;dA=(d[dw]<>>0>>0){dw=dD;dx=dF;dy=dA;dC=dE}else{d8=dD;d9=dF;ea=dA;eb=dE;break}}}else{d8=dG;d9=dH;ea=dI;eb=dJ}dC=ea>>>(dL>>>0);d_=0;d$=(dC&127)+11|0;d0=-7-dL+eb|0;d1=dC>>>7;d2=d9;d3=d8}if((b3+d$|0)>>>0>(c$+aO|0)>>>0){au=1388;break L1820}else{ec=d$;ed=b3}while(1){dC=ec-1|0;c[ad>>2]=ed+1;b[q+112+(ed<<1)>>1]=d_;if((dC|0)==0){dQ=d0;dR=d1;dS=d2;dT=d3;break L1827}ec=dC;ed=c[ad>>2]|0}}}while(0);dz=c[ad>>2]|0;ee=c[aa>>2]|0;du=c[ab>>2]|0;if(dz>>>0<(du+ee|0)>>>0){aF=dT;aD=dS;aN=dR;u=dQ;b3=dz;aO=ee;c$=du}else{au=1391;break}}if((au|0)==1379){au=0;c[E>>2]=13872;c[r>>2]=29;a2=by;a3=al;a4=dZ;a5=dY;a6=ao;a7=dV;a8=ap;a9=dU;break L1802}else if((au|0)==1388){au=0;c[E>>2]=13872;c[r>>2]=29;a2=by;a3=al;a4=d0;a5=d1;a6=ao;a7=d2;a8=ap;a9=d3;break L1802}else if((au|0)==1391){au=0;if((c[r>>2]|0)==29){a2=by;a3=al;a4=dQ;a5=dR;a6=ao;a7=dS;a8=ap;a9=dT;break L1802}else{ef=ee;eg=dQ;eh=dR;ei=dS;ej=dT;break}}}else{ef=aP;eg=bz;eh=bA;ei=bB;ej=bC}}while(0);if((b[ai>>1]|0)==0){c[E>>2]=13832;c[r>>2]=29;a2=by;a3=al;a4=eg;a5=eh;a6=ao;a7=ei;a8=ap;a9=ej;break}c[af>>2]=ae;c[M>>2]=ae;c[N>>2]=9;aP=bv(1,ag,ef,af,N,ah)|0;if((aP|0)!=0){c[E>>2]=13760;c[r>>2]=29;a2=aP;a3=al;a4=eg;a5=eh;a6=ao;a7=ei;a8=ap;a9=ej;break}c[O>>2]=c[af>>2];c[P>>2]=6;aP=bv(2,q+112+(c[aa>>2]<<1)|0,c[ab>>2]|0,af,P,ah)|0;if((aP|0)==0){c[r>>2]=19;if(Q){bI=0;bK=eg;bL=eh;bM=ei;bN=ej;bO=ao;au=1483;break L1657}else{cQ=0;cR=eg;cS=eh;cT=ei;cU=ej;au=1399;break}}else{c[E>>2]=13736;c[r>>2]=29;a2=aP;a3=al;a4=eg;a5=eh;a6=ao;a7=ei;a8=ap;a9=ej;break}}else if((au|0)==1254){while(1){au=0;if((ce|0)==0){aG=j;aH=al;aI=cg;aJ=cf;aK=0;aL=cd;aM=ao;break L1657}aP=ce-1|0;aQ=cd+1|0;c$=(d[cd]<>>0<16){cd=aQ;ce=aP;cf=c$;cg=aO;au=1254}else{ch=aQ;ci=aP;cj=c$;au=1256;break}}}}while(0);if((au|0)==1256){au=0;c$=c[D>>2]|0;if((c$|0)!=0){c[c$+8>>2]=cj&255;c[(c[D>>2]|0)+12>>2]=cj>>>8}if((c[C>>2]&512|0)!=0){a[A]=cj&255;a[B]=cj>>>8&255;c[z>>2]=a$(c[z>>2]|0,A,2)|0}c[r>>2]=4;cu=0;cv=0;cw=ci;cx=ch;au=1261}else if((au|0)==1399){au=0;c[r>>2]=20;cV=cQ;cW=cR;cX=cS;cY=cT;cZ=cU;au=1400}do{if((au|0)==1261){au=0;c$=c[C>>2]|0;do{if((c$&1024|0)==0){aP=c[D>>2]|0;if((aP|0)==0){ek=cu;el=cv;em=cw;en=cx;break}c[aP+16>>2]=0;ek=cu;el=cv;em=cw;en=cx}else{if(cu>>>0<16){aP=cx;aQ=cw;aO=cv;b3=cu;while(1){if((aQ|0)==0){aG=j;aH=al;aI=b3;aJ=aO;aK=0;aL=aP;aM=ao;break L1657}u=aQ-1|0;aN=aP+1|0;aD=(d[aP]<>>0<16){aP=aN;aQ=u;aO=aD;b3=aF}else{eo=aN;ep=u;eq=aD;break}}}else{eo=cx;ep=cw;eq=cv}c[I>>2]=eq;b3=c[D>>2]|0;if((b3|0)==0){er=c$}else{c[b3+20>>2]=eq;er=c[C>>2]|0}if((er&512|0)==0){ek=0;el=0;em=ep;en=eo;break}a[A]=eq&255;a[B]=eq>>>8&255;c[z>>2]=a$(c[z>>2]|0,A,2)|0;ek=0;el=0;em=ep;en=eo}}while(0);c[r>>2]=5;bb=ek;bc=el;bd=em;be=en;au=1272}else if((au|0)==1400){au=0;if(cY>>>0>5&ao>>>0>257){c[m>>2]=ap;c[l>>2]=ao;c[o>>2]=cZ;c[n>>2]=cY;c[w>>2]=cX;c[x>>2]=cW;bl(f,al);c$=c[m>>2]|0;b3=c[l>>2]|0;aO=c[o>>2]|0;aQ=c[n>>2]|0;aP=c[w>>2]|0;aD=c[x>>2]|0;if((c[r>>2]|0)!=11){a2=cV;a3=al;a4=aD;a5=aP;a6=b3;a7=aQ;a8=c$;a9=aO;break}c[R>>2]=-1;a2=cV;a3=al;a4=aD;a5=aP;a6=b3;a7=aQ;a8=c$;a9=aO;break}c[R>>2]=0;aO=(1<>2])-1|0;c$=aO&cX;aQ=c[M>>2]|0;b3=a[aQ+(c$<<2)+1|0]|0;aP=b3&255;if(aP>>>0>cW>>>0){aD=cZ;u=cY;aN=cX;aF=cW;while(1){if((u|0)==0){aG=cV;aH=al;aI=aF;aJ=aN;aK=0;aL=aD;aM=ao;break L1657}aE=u-1|0;du=aD+1|0;dz=(d[aD]<>>0>dv>>>0){aD=du;u=aE;aN=dz;aF=dv}else{es=du;et=aE;eu=dz;ev=dv;ew=dC;ex=dt;ey=dy;break}}}else{es=cZ;et=cY;eu=cX;ev=cW;ew=b3;ex=c$;ey=aP}aF=a[aQ+(ex<<2)|0]|0;aN=b[aQ+(ex<<2)+2>>1]|0;u=aF&255;do{if(aF<<24>>24==0){ez=0;eA=ew;eB=aN;eC=ev;eD=eu;eE=et;eF=es;eG=0}else{if((u&240|0)!=0){ez=aF;eA=ew;eB=aN;eC=ev;eD=eu;eE=et;eF=es;eG=0;break}aD=aN&65535;aO=(1<>>(ey>>>0))+aD|0;dt=a[aQ+(dy<<2)+1|0]|0;if(((dt&255)+ey|0)>>>0>ev>>>0){dC=es;dv=et;dz=eu;aE=ev;while(1){if((dv|0)==0){aG=cV;aH=al;aI=aE;aJ=dz;aK=0;aL=dC;aM=ao;break L1657}du=dv-1|0;dx=dC+1|0;dw=(d[dC]<>>(ey>>>0))+aD|0;dA=a[aQ+(dE<<2)+1|0]|0;if(((dA&255)+ey|0)>>>0>c_>>>0){dC=dx;dv=du;dz=dw;aE=c_}else{eH=dx;eI=du;eJ=dw;eK=c_;eL=dE;eM=dA;break}}}else{eH=es;eI=et;eJ=eu;eK=ev;eL=dy;eM=dt}aE=b[aQ+(eL<<2)+2>>1]|0;dz=a[aQ+(eL<<2)|0]|0;c[R>>2]=ey;ez=dz;eA=eM;eB=aE;eC=eK-ey|0;eD=eJ>>>(ey>>>0);eE=eI;eF=eH;eG=ey}}while(0);aQ=eA&255;u=eD>>>(aQ>>>0);aN=eC-aQ|0;c[R>>2]=eG+aQ;c[I>>2]=eB&65535;aQ=ez&255;if(ez<<24>>24==0){c[r>>2]=25;a2=cV;a3=al;a4=aN;a5=u;a6=ao;a7=eE;a8=ap;a9=eF;break}if((aQ&32|0)!=0){c[R>>2]=-1;c[r>>2]=11;a2=cV;a3=al;a4=aN;a5=u;a6=ao;a7=eE;a8=ap;a9=eF;break}if((aQ&64|0)==0){aF=aQ&15;c[S>>2]=aF;c[r>>2]=21;bf=cV;bg=aN;bh=u;bi=eE;bj=eF;bk=aF;au=1419;break}else{c[E>>2]=13680;c[r>>2]=29;a2=cV;a3=al;a4=aN;a5=u;a6=ao;a7=eE;a8=ap;a9=eF;break}}}while(0);if((au|0)==1272){au=0;u=c[C>>2]|0;if((u&1024|0)==0){eN=bd;eO=be}else{aN=c[I>>2]|0;aF=aN>>>0>bd>>>0?bd:aN;if((aF|0)==0){eP=bd;eQ=be;eR=aN}else{aQ=c[D>>2]|0;do{if((aQ|0)==0){eS=u}else{aP=c[aQ+16>>2]|0;if((aP|0)==0){eS=u;break}c$=(c[aQ+20>>2]|0)-aN|0;b3=aP+c$|0;aP=c[aQ+24>>2]|0;aE=(c$+aF|0)>>>0>aP>>>0?aP-c$|0:aF;bJ(b3|0,be|0,aE)|0;eS=c[C>>2]|0}}while(0);if((eS&512|0)!=0){c[z>>2]=a$(c[z>>2]|0,be,aF)|0}aQ=(c[I>>2]|0)-aF|0;c[I>>2]=aQ;eP=bd-aF|0;eQ=be+aF|0;eR=aQ}if((eR|0)==0){eN=eP;eO=eQ}else{bI=j;bK=bb;bL=bc;bM=eP;bN=eQ;bO=ao;au=1483;break}}c[I>>2]=0;c[r>>2]=6;c8=bb;c9=bc;da=eN;db=eO;au=1282}else if((au|0)==1419){au=0;if((bk|0)==0){eT=bg;eU=bh;eV=bi;eW=bj;eX=c[I>>2]|0}else{if(bg>>>0>>0){aQ=bj;aN=bi;u=bh;aE=bg;while(1){if((aN|0)==0){aG=bf;aH=al;aI=aE;aJ=u;aK=0;aL=aQ;aM=ao;break L1657}b3=aN-1|0;c$=aQ+1|0;aP=(d[aQ]<>>0>>0){aQ=c$;aN=b3;u=aP;aE=dz}else{eY=c$;eZ=b3;e_=aP;e$=dz;break}}}else{eY=bj;eZ=bi;e_=bh;e$=bg}aE=(c[I>>2]|0)+((1<>2]=aE;c[R>>2]=(c[R>>2]|0)+bk;eT=e$-bk|0;eU=e_>>>(bk>>>0);eV=eZ;eW=eY;eX=aE}c[T>>2]=eX;c[r>>2]=22;cy=bf;cz=eT;cA=eU;cB=eV;cC=eW;au=1426}do{if((au|0)==1426){au=0;aE=(1<>2])-1|0;u=aE&cA;aN=c[O>>2]|0;aQ=a[aN+(u<<2)+1|0]|0;aF=aQ&255;if(aF>>>0>cz>>>0){dz=cC;aP=cB;b3=cA;c$=cz;while(1){if((aP|0)==0){aG=cy;aH=al;aI=c$;aJ=b3;aK=0;aL=dz;aM=ao;break L1657}dv=aP-1|0;dC=dz+1|0;aD=(d[dz]<>>0>aO>>>0){dz=dC;aP=dv;b3=aD;c$=aO}else{e0=dC;e1=dv;e2=aD;e3=aO;e4=dE;e5=dA;e6=c_;break}}}else{e0=cC;e1=cB;e2=cA;e3=cz;e4=aQ;e5=u;e6=aF}c$=a[aN+(e5<<2)|0]|0;b3=b[aN+(e5<<2)+2>>1]|0;aP=c$&255;if((aP&240|0)==0){dz=b3&65535;aE=(1<>>(e6>>>0))+dz|0;c_=a[aN+(aP<<2)+1|0]|0;if(((c_&255)+e6|0)>>>0>e3>>>0){dA=e0;dE=e1;aO=e2;aD=e3;while(1){if((dE|0)==0){aG=cy;aH=al;aI=aD;aJ=aO;aK=0;aL=dA;aM=ao;break L1657}dv=dE-1|0;dC=dA+1|0;dw=(d[dA]<>>(e6>>>0))+dz|0;dF=a[aN+(dx<<2)+1|0]|0;if(((dF&255)+e6|0)>>>0>du>>>0){dA=dC;dE=dv;aO=dw;aD=du}else{e7=dC;e8=dv;e9=dw;fa=du;fb=dx;fc=dF;break}}}else{e7=e0;e8=e1;e9=e2;fa=e3;fb=aP;fc=c_}aD=b[aN+(fb<<2)+2>>1]|0;aO=a[aN+(fb<<2)|0]|0;dE=(c[R>>2]|0)+e6|0;c[R>>2]=dE;fd=aO;fe=fc;ff=aD;fg=fa-e6|0;fh=e9>>>(e6>>>0);fi=e8;fj=e7;fk=dE}else{fd=c$;fe=e4;ff=b3;fg=e3;fh=e2;fi=e1;fj=e0;fk=c[R>>2]|0}dE=fe&255;aD=fh>>>(dE>>>0);aO=fg-dE|0;c[R>>2]=fk+dE;dE=fd&255;if((dE&64|0)==0){c[U>>2]=ff&65535;dA=dE&15;c[S>>2]=dA;c[r>>2]=23;co=cy;cp=aO;cq=aD;cr=fi;cs=fj;ct=dA;au=1438;break}else{c[E>>2]=13632;c[r>>2]=29;a2=cy;a3=al;a4=aO;a5=aD;a6=ao;a7=fi;a8=ap;a9=fj;break}}else if((au|0)==1282){au=0;do{if((c[C>>2]&2048|0)==0){aD=c[D>>2]|0;if((aD|0)==0){fl=da;fm=db;break}c[aD+28>>2]=0;fl=da;fm=db}else{if((da|0)==0){bI=j;bK=c8;bL=c9;bM=0;bN=db;bO=ao;au=1483;break L1657}else{fn=0}while(1){fo=fn+1|0;aD=a[db+fn|0]|0;aO=c[D>>2]|0;do{if((aO|0)!=0){dA=aO+28|0;if((c[dA>>2]|0)==0){break}dE=c[I>>2]|0;if(dE>>>0>=(c[aO+32>>2]|0)>>>0){break}c[I>>2]=dE+1;a[(c[dA>>2]|0)+dE|0]=aD}}while(0);fp=aD<<24>>24!=0;if(fp&fo>>>0>>0){fn=fo}else{break}}if((c[C>>2]&512|0)!=0){c[z>>2]=a$(c[z>>2]|0,db,fo)|0}dt=da-fo|0;dy=db+fo|0;if(fp){bI=j;bK=c8;bL=c9;bM=dt;bN=dy;bO=ao;au=1483;break L1657}else{fl=dt;fm=dy}}}while(0);c[I>>2]=0;c[r>>2]=7;ay=c8;az=c9;aA=fl;aC=fm;au=1295}}while(0);if((au|0)==1295){au=0;do{if((c[C>>2]&4096|0)==0){b3=c[D>>2]|0;if((b3|0)==0){fq=aA;fr=aC;break}c[b3+36>>2]=0;fq=aA;fr=aC}else{if((aA|0)==0){bI=j;bK=ay;bL=az;bM=0;bN=aC;bO=ao;au=1483;break L1657}else{fs=0}while(1){ft=fs+1|0;b3=a[aC+fs|0]|0;c$=c[D>>2]|0;do{if((c$|0)!=0){aN=c$+36|0;if((c[aN>>2]|0)==0){break}c_=c[I>>2]|0;if(c_>>>0>=(c[c$+40>>2]|0)>>>0){break}c[I>>2]=c_+1;a[(c[aN>>2]|0)+c_|0]=b3}}while(0);fu=b3<<24>>24!=0;if(fu&ft>>>0>>0){fs=ft}else{break}}if((c[C>>2]&512|0)!=0){c[z>>2]=a$(c[z>>2]|0,aC,ft)|0}c$=aA-ft|0;c_=aC+ft|0;if(fu){bI=j;bK=ay;bL=az;bM=c$;bN=c_;bO=ao;au=1483;break L1657}else{fq=c$;fr=c_}}}while(0);c[r>>2]=8;ck=ay;cl=az;cm=fq;cn=fr;au=1308}else if((au|0)==1438){au=0;if((ct|0)==0){fv=cp;fw=cq;fx=cr;fy=cs}else{if(cp>>>0>>0){c_=cs;c$=cr;aN=cq;aP=cp;while(1){if((c$|0)==0){aG=co;aH=al;aI=aP;aJ=aN;aK=0;aL=c_;aM=ao;break L1657}dy=c$-1|0;dt=c_+1|0;aO=(d[c_]<>>0>>0){c_=dt;c$=dy;aN=aO;aP=dE}else{fz=dt;fA=dy;fB=aO;fC=dE;break}}}else{fz=cs;fA=cr;fB=cq;fC=cp}c[U>>2]=(c[U>>2]|0)+((1<>2]=(c[R>>2]|0)+ct;fv=fC-ct|0;fw=fB>>>(ct>>>0);fx=fA;fy=fz}c[r>>2]=24;cD=co;cE=fv;cF=fw;cG=fx;cH=fy;au=1444}L2018:do{if((au|0)==1308){au=0;aP=c[C>>2]|0;do{if((aP&512|0)==0){fD=ck;fE=cl;fF=cm;fG=cn}else{if(ck>>>0<16){aN=cn;c$=cm;c_=cl;dE=ck;while(1){if((c$|0)==0){aG=j;aH=al;aI=dE;aJ=c_;aK=0;aL=aN;aM=ao;break L1657}aO=c$-1|0;dy=aN+1|0;dt=(d[aN]<>>0<16){aN=dy;c$=aO;c_=dt;dE=dA}else{fH=dy;fI=aO;fJ=dt;fK=dA;break}}}else{fH=cn;fI=cm;fJ=cl;fK=ck}if((fJ|0)==(c[z>>2]&65535|0)){fD=0;fE=0;fF=fI;fG=fH;break}c[E>>2]=13152;c[r>>2]=29;a2=j;a3=al;a4=fK;a5=fJ;a6=ao;a7=fI;a8=ap;a9=fH;break L2018}}while(0);dE=c[D>>2]|0;if((dE|0)!=0){c[dE+44>>2]=aP>>>9&1;c[(c[D>>2]|0)+48>>2]=1}dE=a$(0,0,0)|0;c[z>>2]=dE;c[H>>2]=dE;c[r>>2]=11;a2=j;a3=al;a4=fD;a5=fE;a6=ao;a7=fF;a8=ap;a9=fG}else if((au|0)==1444){au=0;if((ao|0)==0){bI=cD;bK=cE;bL=cF;bM=cG;bN=cH;bO=0;au=1483;break L1657}dE=al-ao|0;c_=c[U>>2]|0;if(c_>>>0>dE>>>0){c$=c_-dE|0;do{if(c$>>>0>(c[V>>2]|0)>>>0){if((c[W>>2]|0)==0){break}c[E>>2]=13600;c[r>>2]=29;a2=cD;a3=al;a4=cE;a5=cF;a6=ao;a7=cG;a8=ap;a9=cH;break L2018}}while(0);aP=c[X>>2]|0;if(c$>>>0>aP>>>0){dE=c$-aP|0;fL=(c[Y>>2]|0)+((c[Z>>2]|0)-dE)|0;fM=dE}else{fL=(c[Y>>2]|0)+(aP-c$)|0;fM=c$}aP=c[I>>2]|0;fN=fL;fO=fM>>>0>aP>>>0?aP:fM;fP=aP}else{aP=c[I>>2]|0;fN=ap+(-c_|0)|0;fO=aP;fP=aP}aP=fO>>>0>ao>>>0?ao:fO;c[I>>2]=fP-aP;dE=~ao;aN=~fO;b3=dE>>>0>aN>>>0?dE:aN;aN=fN;dE=aP;dA=ap;while(1){a[dA]=a[aN]|0;dt=dE-1|0;if((dt|0)==0){break}else{aN=aN+1|0;dE=dt;dA=dA+1|0}}dA=ao-aP|0;dE=ap+~b3|0;if((c[I>>2]|0)!=0){a2=cD;a3=al;a4=cE;a5=cF;a6=dA;a7=cG;a8=dE;a9=cH;break}c[r>>2]=20;a2=cD;a3=al;a4=cE;a5=cF;a6=dA;a7=cG;a8=dE;a9=cH}}while(0);j=a2;al=a3;am=a4;an=a5;ao=a6;p=a7;ap=a8;s=a9;t=c[r>>2]|0}if((au|0)==1482){c[r>>2]=28;aG=1;aH=b_;aI=dg;aJ=dh;aK=di;aL=dj;aM=ao}else if((au|0)==1483){aG=bI;aH=al;aI=bK;aJ=bL;aK=bM;aL=bN;aM=bO}else if((au|0)==1497){k=-4;i=h;return k|0}else if((au|0)==1332){aG=j;aH=al;aI=ds-3|0;aJ=dr>>>3;aK=dq;aL=dp;aM=ao}else if((au|0)==1321){c[m>>2]=ap;c[l>>2]=ao;c[o>>2]=aX;c[n>>2]=aW;c[w>>2]=aV;c[x>>2]=aU;k=2;i=h;return k|0}else if((au|0)==1500){i=h;return k|0}c[m>>2]=ap;c[l>>2]=aM;c[o>>2]=aL;c[n>>2]=aK;c[w>>2]=aJ;c[x>>2]=aI;do{if((c[Z>>2]|0)==0){if((c[r>>2]|0)>>>0>=26){break}if((aH|0)!=(c[l>>2]|0)){au=1487}}else{au=1487}}while(0);do{if((au|0)==1487){if((bt(f,aH)|0)==0){break}c[r>>2]=30;k=-4;i=h;return k|0}}while(0);au=c[n>>2]|0;n=c[l>>2]|0;l=aH-n|0;Z=f+8|0;c[Z>>2]=v-au+(c[Z>>2]|0);c[_>>2]=(c[_>>2]|0)+l;c[$>>2]=(c[$>>2]|0)+l;$=(aH|0)==(n|0);if(!((c[y>>2]|0)==0|$)){y=c[z>>2]|0;n=(c[m>>2]|0)+(-l|0)|0;if((c[C>>2]|0)==0){fQ=a_(y,n,l)|0}else{fQ=a$(y,n,l)|0}c[z>>2]=fQ;c[H>>2]=fQ}fQ=c[r>>2]|0;if((fQ|0)==19){fR=256}else{fR=(fQ|0)==14?256:0}c[f+44>>2]=((c[L>>2]|0)!=0?64:0)+(c[x>>2]|0)+((fQ|0)==11?128:0)+fR;k=((v|0)==(au|0)&$|(g|0)==4)&(aG|0)==0?-5:aG;i=h;return k|0}function br(a){a=a|0;var d=0;d=0;do{b[a+148+(d<<2)>>1]=0;d=d+1|0;}while((d|0)<286);b[a+2440>>1]=0;b[a+2444>>1]=0;b[a+2448>>1]=0;b[a+2452>>1]=0;b[a+2456>>1]=0;b[a+2460>>1]=0;b[a+2464>>1]=0;b[a+2468>>1]=0;b[a+2472>>1]=0;b[a+2476>>1]=0;b[a+2480>>1]=0;b[a+2484>>1]=0;b[a+2488>>1]=0;b[a+2492>>1]=0;b[a+2496>>1]=0;b[a+2500>>1]=0;b[a+2504>>1]=0;b[a+2508>>1]=0;b[a+2512>>1]=0;b[a+2516>>1]=0;b[a+2520>>1]=0;b[a+2524>>1]=0;b[a+2528>>1]=0;b[a+2532>>1]=0;b[a+2536>>1]=0;b[a+2540>>1]=0;b[a+2544>>1]=0;b[a+2548>>1]=0;b[a+2552>>1]=0;b[a+2556>>1]=0;b[a+2684>>1]=0;b[a+2688>>1]=0;b[a+2692>>1]=0;b[a+2696>>1]=0;b[a+2700>>1]=0;b[a+2704>>1]=0;b[a+2708>>1]=0;b[a+2712>>1]=0;b[a+2716>>1]=0;b[a+2720>>1]=0;b[a+2724>>1]=0;b[a+2728>>1]=0;b[a+2732>>1]=0;b[a+2736>>1]=0;b[a+2740>>1]=0;b[a+2744>>1]=0;b[a+2748>>1]=0;b[a+2752>>1]=0;b[a+2756>>1]=0;b[a+1172>>1]=1;c[a+5804>>2]=0;c[a+5800>>2]=0;c[a+5808>>2]=0;c[a+5792>>2]=0;return}function bs(d,f,g,h){d=d|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;i=d+5820|0;j=c[i>>2]|0;k=h&65535;h=d+5816|0;l=e[h>>1]|0|k<>1]=l&65535;if((j|0)>13){m=d+20|0;n=c[m>>2]|0;c[m>>2]=n+1;o=d+8|0;a[(c[o>>2]|0)+n|0]=l&255;n=(e[h>>1]|0)>>>8&255;p=c[m>>2]|0;c[m>>2]=p+1;a[(c[o>>2]|0)+p|0]=n;n=c[i>>2]|0;p=k>>>((16-n|0)>>>0);b[h>>1]=p&65535;q=n-13|0;r=p&255}else{q=j+3|0;r=l&255}c[i>>2]=q;do{if((q|0)>8){l=d+20|0;j=c[l>>2]|0;c[l>>2]=j+1;p=d+8|0;a[(c[p>>2]|0)+j|0]=r;j=(e[h>>1]|0)>>>8&255;n=c[l>>2]|0;c[l>>2]=n+1;a[(c[p>>2]|0)+n|0]=j;s=l;t=p}else{p=d+20|0;if((q|0)>0){l=c[p>>2]|0;c[p>>2]=l+1;j=d+8|0;a[(c[j>>2]|0)+l|0]=r;s=p;t=j;break}else{s=p;t=d+8|0;break}}}while(0);b[h>>1]=0;c[i>>2]=0;c[d+5812>>2]=8;d=c[s>>2]|0;c[s>>2]=d+1;a[(c[t>>2]|0)+d|0]=g&255;d=c[s>>2]|0;c[s>>2]=d+1;a[(c[t>>2]|0)+d|0]=g>>>8&255;d=g&65535^65535;i=c[s>>2]|0;c[s>>2]=i+1;a[(c[t>>2]|0)+i|0]=d&255;i=c[s>>2]|0;c[s>>2]=i+1;a[(c[t>>2]|0)+i|0]=d>>>8&255;if((g|0)==0){return}else{u=g;v=f}while(1){f=u-1|0;g=a[v]|0;d=c[s>>2]|0;c[s>>2]=d+1;a[(c[t>>2]|0)+d|0]=g;if((f|0)==0){break}else{u=f;v=v+1|0}}return}function bt(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;d=c[a+28>>2]|0;e=d+52|0;f=c[e>>2]|0;do{if((f|0)==0){g=aG[c[a+32>>2]&7](c[a+40>>2]|0,1<>2],1)|0;c[e>>2]=g;if((g|0)==0){h=1}else{i=g;break}return h|0}else{i=f}}while(0);f=d+40|0;g=c[f>>2]|0;if((g|0)==0){j=1<>2];c[f>>2]=j;c[d+48>>2]=0;c[d+44>>2]=0;k=j}else{k=g}g=b-(c[a+16>>2]|0)|0;if(g>>>0>=k>>>0){b=(c[a+12>>2]|0)+(-k|0)|0;bJ(i|0,b|0,k)|0;c[d+48>>2]=0;c[d+44>>2]=c[f>>2];h=0;return h|0}b=d+48|0;j=c[b>>2]|0;l=k-j|0;k=l>>>0>g>>>0?g:l;l=i+j|0;j=a+12|0;a=(c[j>>2]|0)+(-g|0)|0;bJ(l|0,a|0,k)|0;a=g-k|0;if((g|0)!=(k|0)){k=c[e>>2]|0;e=(c[j>>2]|0)+(-a|0)|0;bJ(k|0,e|0,a)|0;c[b>>2]=a;c[d+44>>2]=c[f>>2];h=0;return h|0}a=(c[b>>2]|0)+g|0;c[b>>2]=a;e=c[f>>2]|0;if((a|0)==(e|0)){c[b>>2]=0}b=d+44|0;d=c[b>>2]|0;if(d>>>0>=e>>>0){h=0;return h|0}c[b>>2]=d+g;h=0;return h|0}function bu(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;if((a|0)==0){b=-2;return b|0}d=a+28|0;e=c[d>>2]|0;if((e|0)==0){b=-2;return b|0}f=a+36|0;g=c[f>>2]|0;if((g|0)==0){b=-2;return b|0}h=c[e+52>>2]|0;i=a+40|0;if((h|0)==0){j=g;k=e}else{aF[g&3](c[i>>2]|0,h);j=c[f>>2]|0;k=c[d>>2]|0}aF[j&3](c[i>>2]|0,k);c[d>>2]=0;b=0;return b|0}function bv(d,f,g,h,j,k){d=d|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;l=i;i=i+32|0;m=l|0;n=i;i=i+32|0;bI(m|0,0,32);o=(g|0)==0;if(!o){p=0;do{q=m+(e[f+(p<<1)>>1]<<1)|0;b[q>>1]=(b[q>>1]|0)+1&65535;p=p+1|0;}while(p>>>0>>0)}p=c[j>>2]|0;q=15;while(1){if((q|0)==0){r=1559;break}if((b[m+(q<<1)>>1]|0)==0){q=q-1|0}else{break}}if((r|0)==1559){s=c[h>>2]|0;c[h>>2]=s+4;a[s|0]=64;a[s+1|0]=1;b[s+2>>1]=0;s=c[h>>2]|0;c[h>>2]=s+4;a[s|0]=64;a[s+1|0]=1;b[s+2>>1]=0;c[j>>2]=1;t=0;i=l;return t|0}s=p>>>0>q>>>0?q:p;p=1;while(1){if(p>>>0>=q>>>0){break}if((b[m+(p<<1)>>1]|0)==0){p=p+1|0}else{break}}u=s>>>0

>>0?p:s;s=1;v=1;while(1){if(v>>>0>=16){break}w=(s<<1)-(e[m+(v<<1)>>1]|0)|0;if((w|0)<0){t=-1;r=1612;break}else{s=w;v=v+1|0}}if((r|0)==1612){i=l;return t|0}do{if((s|0)>0){if((d|0)!=0&(q|0)==1){break}else{t=-1}i=l;return t|0}}while(0);b[n+2>>1]=0;s=b[m+2>>1]|0;b[n+4>>1]=s;v=(b[m+4>>1]|0)+s&65535;b[n+6>>1]=v;s=(b[m+6>>1]|0)+v&65535;b[n+8>>1]=s;v=(b[m+8>>1]|0)+s&65535;b[n+10>>1]=v;s=(b[m+10>>1]|0)+v&65535;b[n+12>>1]=s;v=(b[m+12>>1]|0)+s&65535;b[n+14>>1]=v;s=(b[m+14>>1]|0)+v&65535;b[n+16>>1]=s;v=(b[m+16>>1]|0)+s&65535;b[n+18>>1]=v;s=(b[m+18>>1]|0)+v&65535;b[n+20>>1]=s;v=(b[m+20>>1]|0)+s&65535;b[n+22>>1]=v;s=(b[m+22>>1]|0)+v&65535;b[n+24>>1]=s;v=(b[m+24>>1]|0)+s&65535;b[n+26>>1]=v;s=(b[m+26>>1]|0)+v&65535;b[n+28>>1]=s;b[n+30>>1]=(b[m+28>>1]|0)+s&65535;if(!o){o=0;do{s=b[f+(o<<1)>>1]|0;if(s<<16>>16!=0){v=n+((s&65535)<<1)|0;s=b[v>>1]|0;b[v>>1]=s+1&65535;b[k+((s&65535)<<1)>>1]=o&65535}o=o+1|0;}while(o>>>0>>0)}do{if((d|0)==0){x=0;y=1<>>0>851){t=1}else{x=1;y=g;z=256;A=894;B=958;C=0;break}i=l;return t|0}else{g=1<>>0>591){t=1}else{x=0;y=g;z=-1;A=1536;B=1600;C=o;break}i=l;return t|0}}while(0);d=y-1|0;o=u&255;g=c[h>>2]|0;n=-1;s=0;v=y;y=0;w=u;D=0;E=p;L2178:while(1){p=1<>1]|0;L=K&65535;do{if((L|0)<(z|0)){M=0;N=K}else{if((L|0)<=(z|0)){M=96;N=0;break}M=b[A+(L<<1)>>1]&255;N=b[B+(L<<1)>>1]|0}}while(0);L=1<>>(y>>>0);O=p;while(1){P=O-L|0;Q=P+K|0;a[g+(Q<<2)|0]=M;a[g+(Q<<2)+1|0]=J;b[g+(Q<<2)+2>>1]=N;if((O|0)==(L|0)){break}else{O=P}}O=1<>>1}}if((O|0)==0){R=0}else{R=(O-1&F)+O|0}S=G+1|0;L=m+(H<<1)|0;K=(b[L>>1]|0)-1&65535;b[L>>1]=K;if(K<<16>>16==0){if((H|0)==(q|0)){break L2178}T=e[f+(e[k+(S<<1)>>1]<<1)>>1]|0}else{T=H}if(T>>>0<=u>>>0){F=R;G=S;H=T;continue}U=R&d;if((U|0)==(n|0)){F=R;G=S;H=T}else{break}}H=(y|0)==0?u:y;G=g+(p<<2)|0;F=T-H|0;L2201:do{if(T>>>0>>0){K=F;L=1<>1]|0)|0;if((P|0)<1){V=K;break L2201}Q=K+1|0;W=Q+H|0;if(W>>>0>>0){K=Q;L=P<<1;I=W}else{V=Q;break}}}else{V=F}}while(0);F=(1<>>0>851|C&F>>>0>591){t=1;r=1613;break}a[(c[h>>2]|0)+(U<<2)|0]=V&255;a[(c[h>>2]|0)+(U<<2)+1|0]=o;p=c[h>>2]|0;b[p+(U<<2)+2>>1]=(G-p|0)>>>2&65535;g=G;n=U;s=R;v=F;y=H;w=V;D=S;E=T}if((r|0)==1613){i=l;return t|0}L2211:do{if((R|0)!=0){r=q;T=y;E=R;S=J;D=g;while(1){do{if((T|0)==0){X=D;Y=S;Z=0;_=r}else{if((E&d|0)==(n|0)){X=D;Y=S;Z=T;_=r;break}X=c[h>>2]|0;Y=o;Z=0;_=u}}while(0);V=E>>>(Z>>>0);a[X+(V<<2)|0]=64;a[X+(V<<2)+1|0]=Y;b[X+(V<<2)+2>>1]=0;V=1<<_-1;while(1){if((V&E|0)==0){break}else{V=V>>>1}}if((V|0)==0){break L2211}w=(V-1&E)+V|0;if((w|0)==0){break}else{r=_;T=Z;E=w;S=Y;D=X}}}}while(0);c[h>>2]=(c[h>>2]|0)+(v<<2);c[j>>2]=u;t=0;i=l;return t|0}function bw(a){a=a|0;c[a+2840>>2]=a+148;c[a+2848>>2]=1200;c[a+2852>>2]=a+2440;c[a+2860>>2]=1344;c[a+2864>>2]=a+2684;c[a+2872>>2]=1368;b[a+5816>>1]=0;c[a+5820>>2]=0;c[a+5812>>2]=8;br(a);return}function bx(d){d=d|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;f=d+5820|0;g=c[f>>2]|0;h=d+5816|0;i=e[h>>1]|0|2<>1]=j;if((g|0)>13){k=d+20|0;l=c[k>>2]|0;c[k>>2]=l+1;m=d+8|0;a[(c[m>>2]|0)+l|0]=i&255;i=(e[h>>1]|0)>>>8&255;l=c[k>>2]|0;c[k>>2]=l+1;a[(c[m>>2]|0)+l|0]=i;i=c[f>>2]|0;l=2>>>((16-i|0)>>>0)&65535;b[h>>1]=l;n=i-13|0;o=l}else{n=g+3|0;o=j}c[f>>2]=n;if((n|0)>9){j=d+20|0;g=c[j>>2]|0;c[j>>2]=g+1;l=d+8|0;a[(c[l>>2]|0)+g|0]=o&255;g=(e[h>>1]|0)>>>8&255;i=c[j>>2]|0;c[j>>2]=i+1;a[(c[l>>2]|0)+i|0]=g;b[h>>1]=0;p=(c[f>>2]|0)-9|0;q=0}else{p=n+7|0;q=o}c[f>>2]=p;do{if((p|0)==16){o=d+20|0;n=c[o>>2]|0;c[o>>2]=n+1;g=d+8|0;a[(c[g>>2]|0)+n|0]=q&255;n=(e[h>>1]|0)>>>8&255;i=c[o>>2]|0;c[o>>2]=i+1;a[(c[g>>2]|0)+i|0]=n;b[h>>1]=0;c[f>>2]=0;r=0;s=0}else{if((p|0)<=7){r=p;s=q;break}n=d+20|0;i=c[n>>2]|0;c[n>>2]=i+1;a[(c[d+8>>2]|0)+i|0]=q&255;i=(e[h>>1]|0)>>>8;b[h>>1]=i;n=(c[f>>2]|0)-8|0;c[f>>2]=n;r=n;s=i}}while(0);q=d+5812|0;if((11-r+(c[q>>2]|0)|0)>=9){c[q>>2]=7;return}p=s&65535|2<>1]=p&65535;if((r|0)>13){s=d+20|0;i=c[s>>2]|0;c[s>>2]=i+1;n=d+8|0;a[(c[n>>2]|0)+i|0]=p&255;i=(e[h>>1]|0)>>>8&255;g=c[s>>2]|0;c[s>>2]=g+1;a[(c[n>>2]|0)+g|0]=i;i=c[f>>2]|0;g=2>>>((16-i|0)>>>0);b[h>>1]=g&65535;t=i-13|0;u=g&255}else{t=r+3|0;u=p&255}c[f>>2]=t;if((t|0)>9){p=d+20|0;r=c[p>>2]|0;c[p>>2]=r+1;g=d+8|0;a[(c[g>>2]|0)+r|0]=u;r=(e[h>>1]|0)>>>8&255;i=c[p>>2]|0;c[p>>2]=i+1;a[(c[g>>2]|0)+i|0]=r;b[h>>1]=0;v=(c[f>>2]|0)-9|0;w=0}else{v=t+7|0;w=u}c[f>>2]=v;if((v|0)==16){u=d+20|0;t=c[u>>2]|0;c[u>>2]=t+1;r=d+8|0;a[(c[r>>2]|0)+t|0]=w;t=(e[h>>1]|0)>>>8&255;i=c[u>>2]|0;c[u>>2]=i+1;a[(c[r>>2]|0)+i|0]=t;b[h>>1]=0;c[f>>2]=0;c[q>>2]=7;return}if((v|0)<=7){c[q>>2]=7;return}v=d+20|0;t=c[v>>2]|0;c[v>>2]=t+1;a[(c[d+8>>2]|0)+t|0]=w;b[h>>1]=(e[h>>1]|0)>>>8;c[f>>2]=(c[f>>2]|0)-8;c[q>>2]=7;return}function by(f,g,h,i){f=f|0;g=g|0;h=h|0;i=i|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0;if((c[f+132>>2]|0)>0){j=(c[f>>2]|0)+44|0;if((c[j>>2]|0)==2){k=-201342849;l=0;while(1){if((k&1|0)!=0){if((b[f+148+(l<<2)>>1]|0)!=0){m=0;break}}n=l+1|0;if((n|0)<32){k=k>>>1;l=n}else{o=1646;break}}L2268:do{if((o|0)==1646){if((b[f+184>>1]|0)!=0){m=1;break}if((b[f+188>>1]|0)!=0){m=1;break}if((b[f+200>>1]|0)==0){p=32}else{m=1;break}while(1){if((p|0)>=256){m=0;break L2268}if((b[f+148+(p<<2)>>1]|0)==0){p=p+1|0}else{m=1;break}}}}while(0);c[j>>2]=m}bz(f,f+2840|0);bz(f,f+2852|0);bC(f,f+148|0,c[f+2844>>2]|0);bC(f,f+2440|0,c[f+2856>>2]|0);bz(f,f+2864|0);m=18;while(1){if((m|0)<=2){break}if((b[f+2684+(d[12512+m|0]<<2)+2>>1]|0)==0){m=m-1|0}else{break}}j=f+5800|0;p=(m*3|0)+17+(c[j>>2]|0)|0;c[j>>2]=p;j=(p+10|0)>>>3;p=((c[f+5804>>2]|0)+10|0)>>>3;q=p>>>0>j>>>0?j:p;r=p;s=m}else{m=h+5|0;q=m;r=m;s=0}do{if((h+4|0)>>>0>q>>>0|(g|0)==0){m=f+5820|0;p=c[m>>2]|0;j=(p|0)>13;if((c[f+136>>2]|0)==4|(r|0)==(q|0)){o=i+2&65535;l=f+5816|0;k=e[l>>1]|o<>1]=k&65535;if(j){n=f+20|0;t=c[n>>2]|0;c[n>>2]=t+1;u=f+8|0;a[(c[u>>2]|0)+t|0]=k&255;k=(e[l>>1]|0)>>>8&255;t=c[n>>2]|0;c[n>>2]=t+1;a[(c[u>>2]|0)+t|0]=k;k=c[m>>2]|0;b[l>>1]=o>>>((16-k|0)>>>0)&65535;v=k-13|0}else{v=p+3|0}c[m>>2]=v;bA(f,48,1224);break}k=i+4&65535;o=f+5816|0;l=e[o>>1]|k<>1]=t;if(j){j=f+20|0;u=c[j>>2]|0;c[j>>2]=u+1;n=f+8|0;a[(c[n>>2]|0)+u|0]=l&255;l=(e[o>>1]|0)>>>8&255;u=c[j>>2]|0;c[j>>2]=u+1;a[(c[n>>2]|0)+u|0]=l;l=c[m>>2]|0;u=k>>>((16-l|0)>>>0)&65535;b[o>>1]=u;w=l-13|0;x=u}else{w=p+3|0;x=t}c[m>>2]=w;t=c[f+2844>>2]|0;p=c[f+2856>>2]|0;u=s+1|0;l=t+65280&65535;k=x&65535|l<>1]=n;if((w|0)>11){j=f+20|0;y=c[j>>2]|0;c[j>>2]=y+1;z=f+8|0;a[(c[z>>2]|0)+y|0]=k&255;k=(e[o>>1]|0)>>>8&255;y=c[j>>2]|0;c[j>>2]=y+1;a[(c[z>>2]|0)+y|0]=k;k=c[m>>2]|0;y=l>>>((16-k|0)>>>0)&65535;b[o>>1]=y;A=k-11|0;B=y}else{A=w+5|0;B=n}c[m>>2]=A;n=p&65535;y=n<>1]=k;if((A|0)>11){l=f+20|0;z=c[l>>2]|0;c[l>>2]=z+1;j=f+8|0;a[(c[j>>2]|0)+z|0]=y&255;y=(e[o>>1]|0)>>>8&255;z=c[l>>2]|0;c[l>>2]=z+1;a[(c[j>>2]|0)+z|0]=y;y=c[m>>2]|0;z=n>>>((16-y|0)>>>0)&65535;b[o>>1]=z;C=y-11|0;D=z}else{C=A+5|0;D=k}c[m>>2]=C;k=s+65533&65535;z=k<>1]=y;if((C|0)>12){n=f+20|0;j=c[n>>2]|0;c[n>>2]=j+1;l=f+8|0;a[(c[l>>2]|0)+j|0]=z&255;z=(e[o>>1]|0)>>>8&255;j=c[n>>2]|0;c[n>>2]=j+1;a[(c[l>>2]|0)+j|0]=z;z=c[m>>2]|0;j=k>>>((16-z|0)>>>0)&65535;b[o>>1]=j;E=z-12|0;F=j}else{E=C+4|0;F=y}c[m>>2]=E;if((u|0)>0){y=f+20|0;j=f+8|0;z=0;k=E;l=F;while(1){n=e[f+2684+(d[12512+z|0]<<2)+2>>1]|0;G=n<>1]=H;if((k|0)>13){I=c[y>>2]|0;c[y>>2]=I+1;a[(c[j>>2]|0)+I|0]=G&255;G=(e[o>>1]|0)>>>8&255;I=c[y>>2]|0;c[y>>2]=I+1;a[(c[j>>2]|0)+I|0]=G;G=c[m>>2]|0;I=n>>>((16-G|0)>>>0)&65535;b[o>>1]=I;J=G-13|0;K=I}else{J=k+3|0;K=H}c[m>>2]=J;H=z+1|0;if((H|0)<(u|0)){z=H;k=J;l=K}else{break}}}l=f+148|0;bB(f,l,t);k=f+2440|0;bB(f,k,p);bA(f,l,k)}else{bs(f,g,h,i)}}while(0);br(f);if((i|0)==0){return}i=f+5820|0;h=c[i>>2]|0;do{if((h|0)>8){g=f+5816|0;K=b[g>>1]&255;J=f+20|0;F=c[J>>2]|0;c[J>>2]=F+1;E=f+8|0;a[(c[E>>2]|0)+F|0]=K;K=(e[g>>1]|0)>>>8&255;F=c[J>>2]|0;c[J>>2]=F+1;a[(c[E>>2]|0)+F|0]=K;L=g}else{g=f+5816|0;if((h|0)<=0){L=g;break}K=b[g>>1]&255;F=f+20|0;E=c[F>>2]|0;c[F>>2]=E+1;a[(c[f+8>>2]|0)+E|0]=K;L=g}}while(0);b[L>>1]=0;c[i>>2]=0;return}function bz(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,_=0;h=i;i=i+32|0;j=h|0;k=g|0;l=c[k>>2]|0;m=g+8|0;n=c[m>>2]|0;o=c[n>>2]|0;p=c[n+12>>2]|0;n=f+5200|0;c[n>>2]=0;q=f+5204|0;c[q>>2]=573;if((p|0)>0){r=0;s=-1;while(1){if((b[l+(r<<2)>>1]|0)==0){b[l+(r<<2)+2>>1]=0;t=s}else{u=(c[n>>2]|0)+1|0;c[n>>2]=u;c[f+2908+(u<<2)>>2]=r;a[f+5208+r|0]=0;t=r}u=r+1|0;if((u|0)<(p|0)){r=u;s=t}else{break}}s=c[n>>2]|0;if((s|0)<2){v=s;w=t;x=1694}else{y=t}}else{v=0;w=-1;x=1694}if((x|0)==1694){x=f+5800|0;t=f+5804|0;if((o|0)==0){s=w;r=v;while(1){u=(s|0)<2;z=s+1|0;A=u?z:s;B=u?z:0;z=r+1|0;c[n>>2]=z;c[f+2908+(z<<2)>>2]=B;b[l+(B<<2)>>1]=1;a[f+5208+B|0]=0;c[x>>2]=(c[x>>2]|0)-1;B=c[n>>2]|0;if((B|0)<2){s=A;r=B}else{y=A;break}}}else{r=w;w=v;while(1){v=(r|0)<2;s=r+1|0;A=v?s:r;B=v?s:0;s=w+1|0;c[n>>2]=s;c[f+2908+(s<<2)>>2]=B;b[l+(B<<2)>>1]=1;a[f+5208+B|0]=0;c[x>>2]=(c[x>>2]|0)-1;c[t>>2]=(c[t>>2]|0)-(e[o+(B<<2)+2>>1]|0);B=c[n>>2]|0;if((B|0)<2){r=A;w=B}else{y=A;break}}}}w=g+4|0;c[w>>2]=y;g=c[n>>2]|0;if((g|0)>1){r=(g|0)/2|0;o=g;while(1){t=c[f+2908+(r<<2)>>2]|0;x=f+5208+t|0;A=r<<1;L2348:do{if((A|0)>(o|0)){C=r}else{B=l+(t<<2)|0;s=r;v=A;z=o;while(1){do{if((v|0)<(z|0)){u=v|1;D=c[f+2908+(u<<2)>>2]|0;E=b[l+(D<<2)>>1]|0;F=c[f+2908+(v<<2)>>2]|0;G=b[l+(F<<2)>>1]|0;if((E&65535)>=(G&65535)){if(E<<16>>16!=G<<16>>16){H=v;break}if((d[f+5208+D|0]|0)>(d[f+5208+F|0]|0)){H=v;break}}H=u}else{H=v}}while(0);u=b[B>>1]|0;F=c[f+2908+(H<<2)>>2]|0;D=b[l+(F<<2)>>1]|0;if((u&65535)<(D&65535)){C=s;break L2348}if(u<<16>>16==D<<16>>16){if((d[x]|0)<=(d[f+5208+F|0]|0)){C=s;break L2348}}c[f+2908+(s<<2)>>2]=F;F=H<<1;D=c[n>>2]|0;if((F|0)>(D|0)){C=H;break}else{s=H;v=F;z=D}}}}while(0);c[f+2908+(C<<2)>>2]=t;x=r-1|0;A=c[n>>2]|0;if((x|0)>0){r=x;o=A}else{I=A;break}}}else{I=g}g=f+2912|0;o=p;p=I;while(1){I=c[g>>2]|0;r=p-1|0;c[n>>2]=r;C=c[f+2908+(p<<2)>>2]|0;c[g>>2]=C;H=f+5208+C|0;L2367:do{if((r|0)<2){J=1}else{A=l+(C<<2)|0;x=1;z=2;v=r;while(1){do{if((z|0)<(v|0)){s=z|1;B=c[f+2908+(s<<2)>>2]|0;D=b[l+(B<<2)>>1]|0;F=c[f+2908+(z<<2)>>2]|0;u=b[l+(F<<2)>>1]|0;if((D&65535)>=(u&65535)){if(D<<16>>16!=u<<16>>16){K=z;break}if((d[f+5208+B|0]|0)>(d[f+5208+F|0]|0)){K=z;break}}K=s}else{K=z}}while(0);s=b[A>>1]|0;F=c[f+2908+(K<<2)>>2]|0;B=b[l+(F<<2)>>1]|0;if((s&65535)<(B&65535)){J=x;break L2367}if(s<<16>>16==B<<16>>16){if((d[H]|0)<=(d[f+5208+F|0]|0)){J=x;break L2367}}c[f+2908+(x<<2)>>2]=F;F=K<<1;B=c[n>>2]|0;if((F|0)>(B|0)){J=K;break}else{x=K;z=F;v=B}}}}while(0);c[f+2908+(J<<2)>>2]=C;H=c[g>>2]|0;r=(c[q>>2]|0)-1|0;c[q>>2]=r;c[f+2908+(r<<2)>>2]=I;r=(c[q>>2]|0)-1|0;c[q>>2]=r;c[f+2908+(r<<2)>>2]=H;r=l+(o<<2)|0;b[r>>1]=(b[l+(H<<2)>>1]|0)+(b[l+(I<<2)>>1]|0)&65535;t=a[f+5208+I|0]|0;v=a[f+5208+H|0]|0;z=f+5208+o|0;a[z]=((t&255)<(v&255)?v:t)+1&255;t=o&65535;b[l+(H<<2)+2>>1]=t;b[l+(I<<2)+2>>1]=t;t=o+1|0;c[g>>2]=o;H=c[n>>2]|0;L2383:do{if((H|0)<2){L=1}else{v=1;x=2;A=H;while(1){do{if((x|0)<(A|0)){B=x|1;F=c[f+2908+(B<<2)>>2]|0;s=b[l+(F<<2)>>1]|0;u=c[f+2908+(x<<2)>>2]|0;D=b[l+(u<<2)>>1]|0;if((s&65535)>=(D&65535)){if(s<<16>>16!=D<<16>>16){M=x;break}if((d[f+5208+F|0]|0)>(d[f+5208+u|0]|0)){M=x;break}}M=B}else{M=x}}while(0);B=b[r>>1]|0;u=c[f+2908+(M<<2)>>2]|0;F=b[l+(u<<2)>>1]|0;if((B&65535)<(F&65535)){L=v;break L2383}if(B<<16>>16==F<<16>>16){if((d[z]|0)<=(d[f+5208+u|0]|0)){L=v;break L2383}}c[f+2908+(v<<2)>>2]=u;u=M<<1;F=c[n>>2]|0;if((u|0)>(F|0)){L=M;break}else{v=M;x=u;A=F}}}}while(0);c[f+2908+(L<<2)>>2]=o;z=c[n>>2]|0;if((z|0)>1){o=t;p=z}else{break}}p=c[g>>2]|0;g=(c[q>>2]|0)-1|0;c[q>>2]=g;c[f+2908+(g<<2)>>2]=p;p=c[k>>2]|0;k=c[w>>2]|0;w=c[m>>2]|0;m=c[w>>2]|0;g=c[w+4>>2]|0;o=c[w+8>>2]|0;n=c[w+16>>2]|0;w=f+2876|0;bI(w|0,0,32);b[p+(c[f+2908+(c[q>>2]<<2)>>2]<<2)+2>>1]=0;L=(c[q>>2]|0)+1|0;L2399:do{if((L|0)<573){q=f+5800|0;M=f+5804|0;if((m|0)==0){J=0;K=L;while(1){z=c[f+2908+(K<<2)>>2]|0;r=p+(z<<2)+2|0;H=(e[p+(e[r>>1]<<2)+2>>1]|0)+1|0;I=(H|0)>(n|0);C=I?n:H;H=(I&1)+J|0;b[r>>1]=C&65535;if((z|0)<=(k|0)){r=f+2876+(C<<1)|0;b[r>>1]=(b[r>>1]|0)+1&65535;if((z|0)<(o|0)){N=0}else{N=c[g+(z-o<<2)>>2]|0}r=Z(e[p+(z<<2)>>1]|0,N+C|0)|0;c[q>>2]=r+(c[q>>2]|0)}r=K+1|0;if((r|0)<573){J=H;K=r}else{O=H;break}}}else{K=0;J=L;while(1){t=c[f+2908+(J<<2)>>2]|0;H=p+(t<<2)+2|0;r=(e[p+(e[H>>1]<<2)+2>>1]|0)+1|0;C=(r|0)>(n|0);z=C?n:r;r=(C&1)+K|0;b[H>>1]=z&65535;if((t|0)<=(k|0)){H=f+2876+(z<<1)|0;b[H>>1]=(b[H>>1]|0)+1&65535;if((t|0)<(o|0)){P=0}else{P=c[g+(t-o<<2)>>2]|0}H=e[p+(t<<2)>>1]|0;C=Z(H,P+z|0)|0;c[q>>2]=C+(c[q>>2]|0);C=Z((e[m+(t<<2)+2>>1]|0)+P|0,H)|0;c[M>>2]=C+(c[M>>2]|0)}C=J+1|0;if((C|0)<573){K=r;J=C}else{O=r;break}}}if((O|0)==0){break}J=f+2876+(n<<1)|0;K=O;do{M=n;while(1){r=M-1|0;Q=f+2876+(r<<1)|0;R=b[Q>>1]|0;if(R<<16>>16==0){M=r}else{break}}b[Q>>1]=R-1&65535;r=f+2876+(M<<1)|0;b[r>>1]=(b[r>>1]|0)+2&65535;S=(b[J>>1]|0)-1&65535;b[J>>1]=S;K=K-2|0;}while((K|0)>0);if((n|0)==0){break}else{T=n;U=573;V=S}while(1){K=T&65535;if(V<<16>>16==0){W=U}else{J=V&65535;r=U;while(1){C=r;do{C=C-1|0;X=c[f+2908+(C<<2)>>2]|0;}while((X|0)>(k|0));H=p+(X<<2)+2|0;t=e[H>>1]|0;if((t|0)!=(T|0)){z=Z(e[p+(X<<2)>>1]|0,T-t|0)|0;c[q>>2]=z+(c[q>>2]|0);b[H>>1]=K}H=J-1|0;if((H|0)==0){W=C;break}else{J=H;r=C}}}r=T-1|0;if((r|0)==0){break L2399}T=r;U=W;V=b[f+2876+(r<<1)>>1]|0}}}while(0);V=b[w>>1]<<1;b[j+2>>1]=V;w=((b[f+2878>>1]|0)+V&65535)<<1;b[j+4>>1]=w;V=(w+(b[f+2880>>1]|0)&65535)<<1;b[j+6>>1]=V;w=(V+(b[f+2882>>1]|0)&65535)<<1;b[j+8>>1]=w;V=(w+(b[f+2884>>1]|0)&65535)<<1;b[j+10>>1]=V;w=(V+(b[f+2886>>1]|0)&65535)<<1;b[j+12>>1]=w;V=(w+(b[f+2888>>1]|0)&65535)<<1;b[j+14>>1]=V;w=(V+(b[f+2890>>1]|0)&65535)<<1;b[j+16>>1]=w;V=(w+(b[f+2892>>1]|0)&65535)<<1;b[j+18>>1]=V;w=(V+(b[f+2894>>1]|0)&65535)<<1;b[j+20>>1]=w;V=(w+(b[f+2896>>1]|0)&65535)<<1;b[j+22>>1]=V;w=(V+(b[f+2898>>1]|0)&65535)<<1;b[j+24>>1]=w;V=(w+(b[f+2900>>1]|0)&65535)<<1;b[j+26>>1]=V;w=(V+(b[f+2902>>1]|0)&65535)<<1;b[j+28>>1]=w;b[j+30>>1]=(w+(b[f+2904>>1]|0)&65535)<<1;if((y|0)<0){i=h;return}else{Y=0}do{f=b[l+(Y<<2)+2>>1]|0;w=f&65535;if(f<<16>>16!=0){f=j+(w<<1)|0;V=b[f>>1]|0;b[f>>1]=V+1&65535;f=0;W=w;w=V&65535;while(1){_=f|w&1;V=W-1|0;if((V|0)>0){f=_<<1;W=V;w=w>>>1}else{break}}b[l+(Y<<2)>>1]=_&65535}Y=Y+1|0;}while((Y|0)<=(y|0));i=h;return}function bA(f,g,h){f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0;i=f+5792|0;if((c[i>>2]|0)==0){j=c[f+5820>>2]|0;k=b[f+5816>>1]|0}else{l=f+5796|0;m=f+5784|0;n=f+5820|0;o=f+5816|0;p=f+20|0;q=f+8|0;r=0;while(1){s=b[(c[l>>2]|0)+(r<<1)>>1]|0;t=s&65535;u=r+1|0;v=d[(c[m>>2]|0)+r|0]|0;do{if(s<<16>>16==0){w=e[g+(v<<2)+2>>1]|0;x=c[n>>2]|0;y=e[g+(v<<2)>>1]|0;z=e[o>>1]|0|y<>1]=A;if((x|0)>(16-w|0)){B=c[p>>2]|0;c[p>>2]=B+1;a[(c[q>>2]|0)+B|0]=z&255;z=(e[o>>1]|0)>>>8&255;B=c[p>>2]|0;c[p>>2]=B+1;a[(c[q>>2]|0)+B|0]=z;z=c[n>>2]|0;B=y>>>((16-z|0)>>>0)&65535;b[o>>1]=B;y=w-16+z|0;c[n>>2]=y;C=y;D=B;break}else{B=x+w|0;c[n>>2]=B;C=B;D=A;break}}else{A=d[13928+v|0]|0;B=(A|256)+1|0;w=e[g+(B<<2)+2>>1]|0;x=c[n>>2]|0;y=e[g+(B<<2)>>1]|0;B=e[o>>1]|0|y<>1]=z;if((x|0)>(16-w|0)){E=c[p>>2]|0;c[p>>2]=E+1;a[(c[q>>2]|0)+E|0]=B&255;B=(e[o>>1]|0)>>>8&255;E=c[p>>2]|0;c[p>>2]=E+1;a[(c[q>>2]|0)+E|0]=B;B=c[n>>2]|0;E=y>>>((16-B|0)>>>0)&65535;b[o>>1]=E;F=w-16+B|0;G=E}else{F=x+w|0;G=z}c[n>>2]=F;z=c[3880+(A<<2)>>2]|0;do{if((A-8|0)>>>0<20){w=v-(c[12536+(A<<2)>>2]|0)&65535;x=w<>1]=E;if((F|0)>(16-z|0)){B=c[p>>2]|0;c[p>>2]=B+1;a[(c[q>>2]|0)+B|0]=x&255;x=(e[o>>1]|0)>>>8&255;B=c[p>>2]|0;c[p>>2]=B+1;a[(c[q>>2]|0)+B|0]=x;x=c[n>>2]|0;B=w>>>((16-x|0)>>>0)&65535;b[o>>1]=B;w=z-16+x|0;c[n>>2]=w;H=w;I=B;break}else{B=F+z|0;c[n>>2]=B;H=B;I=E;break}}else{H=F;I=G}}while(0);z=t-1|0;if(z>>>0<256){J=z}else{J=(z>>>7)+256|0}A=d[14184+J|0]|0;E=e[h+(A<<2)+2>>1]|0;B=e[h+(A<<2)>>1]|0;w=I&65535|B<>1]=x;if((H|0)>(16-E|0)){y=c[p>>2]|0;c[p>>2]=y+1;a[(c[q>>2]|0)+y|0]=w&255;w=(e[o>>1]|0)>>>8&255;y=c[p>>2]|0;c[p>>2]=y+1;a[(c[q>>2]|0)+y|0]=w;w=c[n>>2]|0;y=B>>>((16-w|0)>>>0)&65535;b[o>>1]=y;K=E-16+w|0;L=y}else{K=H+E|0;L=x}c[n>>2]=K;x=c[4e3+(A<<2)>>2]|0;if((A-4|0)>>>0>=26){C=K;D=L;break}E=z-(c[12656+(A<<2)>>2]|0)&65535;A=E<>1]=z;if((K|0)>(16-x|0)){y=c[p>>2]|0;c[p>>2]=y+1;a[(c[q>>2]|0)+y|0]=A&255;A=(e[o>>1]|0)>>>8&255;y=c[p>>2]|0;c[p>>2]=y+1;a[(c[q>>2]|0)+y|0]=A;A=c[n>>2]|0;y=E>>>((16-A|0)>>>0)&65535;b[o>>1]=y;E=x-16+A|0;c[n>>2]=E;C=E;D=y;break}else{y=K+x|0;c[n>>2]=y;C=y;D=z;break}}}while(0);if(u>>>0<(c[i>>2]|0)>>>0){r=u}else{j=C;k=D;break}}}D=g+1026|0;C=e[D>>1]|0;r=f+5820|0;i=e[g+1024>>1]|0;g=f+5816|0;n=k&65535|i<>1]=n&65535;if((j|0)>(16-C|0)){k=f+20|0;K=c[k>>2]|0;c[k>>2]=K+1;o=f+8|0;a[(c[o>>2]|0)+K|0]=n&255;n=(e[g>>1]|0)>>>8&255;K=c[k>>2]|0;c[k>>2]=K+1;a[(c[o>>2]|0)+K|0]=n;n=c[r>>2]|0;b[g>>1]=i>>>((16-n|0)>>>0)&65535;M=C-16+n|0;c[r>>2]=M;N=b[D>>1]|0;O=N&65535;P=f+5812|0;c[P>>2]=O;return}else{M=j+C|0;c[r>>2]=M;N=b[D>>1]|0;O=N&65535;P=f+5812|0;c[P>>2]=O;return}}function bB(d,f,g){d=d|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0;h=b[f+2>>1]|0;i=h<<16>>16==0;j=d+2754|0;k=d+5820|0;l=d+2752|0;m=d+5816|0;n=d+20|0;o=d+8|0;p=d+2758|0;q=d+2756|0;r=d+2750|0;s=d+2748|0;t=0;u=-1;v=h&65535;h=i?138:7;w=i?3:4;L2493:while(1){i=t;x=0;while(1){if((i|0)>(g|0)){break L2493}y=i+1|0;z=b[f+(y<<2)+2>>1]|0;A=z&65535;B=x+1|0;C=(v|0)==(A|0);if((B|0)<(h|0)&C){i=y;x=B}else{break}}do{if((B|0)<(w|0)){i=d+2684+(v<<2)+2|0;D=d+2684+(v<<2)|0;E=B;F=c[k>>2]|0;G=b[m>>1]|0;while(1){H=e[i>>1]|0;I=e[D>>1]|0;J=G&65535|I<>1]=K;if((F|0)>(16-H|0)){L=c[n>>2]|0;c[n>>2]=L+1;a[(c[o>>2]|0)+L|0]=J&255;J=(e[m>>1]|0)>>>8&255;L=c[n>>2]|0;c[n>>2]=L+1;a[(c[o>>2]|0)+L|0]=J;J=c[k>>2]|0;L=I>>>((16-J|0)>>>0)&65535;b[m>>1]=L;M=H-16+J|0;N=L}else{M=F+H|0;N=K}c[k>>2]=M;K=E-1|0;if((K|0)==0){break}else{E=K;F=M;G=N}}}else{if((v|0)!=0){if((v|0)==(u|0)){O=B;P=c[k>>2]|0;Q=b[m>>1]|0}else{G=e[d+2684+(v<<2)+2>>1]|0;F=c[k>>2]|0;E=e[d+2684+(v<<2)>>1]|0;D=e[m>>1]|0|E<>1]=i;if((F|0)>(16-G|0)){K=c[n>>2]|0;c[n>>2]=K+1;a[(c[o>>2]|0)+K|0]=D&255;D=(e[m>>1]|0)>>>8&255;K=c[n>>2]|0;c[n>>2]=K+1;a[(c[o>>2]|0)+K|0]=D;D=c[k>>2]|0;K=E>>>((16-D|0)>>>0)&65535;b[m>>1]=K;R=G-16+D|0;S=K}else{R=F+G|0;S=i}c[k>>2]=R;O=x;P=R;Q=S}i=e[r>>1]|0;G=e[s>>1]|0;F=Q&65535|G<>1]=K;if((P|0)>(16-i|0)){D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=F&255;F=(e[m>>1]|0)>>>8&255;D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=F;F=c[k>>2]|0;D=G>>>((16-F|0)>>>0)&65535;b[m>>1]=D;T=i-16+F|0;U=D}else{T=P+i|0;U=K}c[k>>2]=T;K=O+65533&65535;i=U&65535|K<>1]=i&65535;if((T|0)>14){D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=i&255;i=(e[m>>1]|0)>>>8&255;D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=i;i=c[k>>2]|0;b[m>>1]=K>>>((16-i|0)>>>0)&65535;c[k>>2]=i-14;break}else{c[k>>2]=T+2;break}}if((B|0)<11){i=e[j>>1]|0;K=c[k>>2]|0;D=e[l>>1]|0;F=e[m>>1]|0|D<>1]=G;if((K|0)>(16-i|0)){E=c[n>>2]|0;c[n>>2]=E+1;a[(c[o>>2]|0)+E|0]=F&255;F=(e[m>>1]|0)>>>8&255;E=c[n>>2]|0;c[n>>2]=E+1;a[(c[o>>2]|0)+E|0]=F;F=c[k>>2]|0;E=D>>>((16-F|0)>>>0)&65535;b[m>>1]=E;V=i-16+F|0;W=E}else{V=K+i|0;W=G}c[k>>2]=V;G=x+65534&65535;i=W&65535|G<>1]=i&65535;if((V|0)>13){K=c[n>>2]|0;c[n>>2]=K+1;a[(c[o>>2]|0)+K|0]=i&255;i=(e[m>>1]|0)>>>8&255;K=c[n>>2]|0;c[n>>2]=K+1;a[(c[o>>2]|0)+K|0]=i;i=c[k>>2]|0;b[m>>1]=G>>>((16-i|0)>>>0)&65535;c[k>>2]=i-13;break}else{c[k>>2]=V+3;break}}else{i=e[p>>1]|0;G=c[k>>2]|0;K=e[q>>1]|0;E=e[m>>1]|0|K<>1]=F;if((G|0)>(16-i|0)){D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=E&255;E=(e[m>>1]|0)>>>8&255;D=c[n>>2]|0;c[n>>2]=D+1;a[(c[o>>2]|0)+D|0]=E;E=c[k>>2]|0;D=K>>>((16-E|0)>>>0)&65535;b[m>>1]=D;X=i-16+E|0;Y=D}else{X=G+i|0;Y=F}c[k>>2]=X;F=x+65526&65535;i=Y&65535|F<>1]=i&65535;if((X|0)>9){G=c[n>>2]|0;c[n>>2]=G+1;a[(c[o>>2]|0)+G|0]=i&255;i=(e[m>>1]|0)>>>8&255;G=c[n>>2]|0;c[n>>2]=G+1;a[(c[o>>2]|0)+G|0]=i;i=c[k>>2]|0;b[m>>1]=F>>>((16-i|0)>>>0)&65535;c[k>>2]=i-9;break}else{c[k>>2]=X+7;break}}}}while(0);if(z<<16>>16==0){t=y;u=v;v=A;h=138;w=3;continue}t=y;u=v;v=A;h=C?6:7;w=C?3:4}return}function bC(a,c,d){a=a|0;c=c|0;d=d|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;f=b[c+2>>1]|0;g=f<<16>>16==0;b[c+(d+1<<2)+2>>1]=-1;h=a+2752|0;i=a+2756|0;j=a+2748|0;k=g?3:4;l=g?138:7;g=f&65535;f=0;m=-1;L2547:while(1){n=0;o=f;do{if((o|0)>(d|0)){break L2547}o=o+1|0;p=b[c+(o<<2)+2>>1]|0;q=p&65535;n=n+1|0;r=(g|0)==(q|0);}while((n|0)<(l|0)&r);do{if((n|0)<(k|0)){s=a+2684+(g<<2)|0;b[s>>1]=(e[s>>1]|0)+n&65535}else{if((g|0)==0){if((n|0)<11){b[h>>1]=(b[h>>1]|0)+1&65535;break}else{b[i>>1]=(b[i>>1]|0)+1&65535;break}}else{if((g|0)!=(m|0)){s=a+2684+(g<<2)|0;b[s>>1]=(b[s>>1]|0)+1&65535}b[j>>1]=(b[j>>1]|0)+1&65535;break}}}while(0);if(p<<16>>16==0){k=3;l=138;m=g;g=q;f=o;continue}k=r?3:4;l=r?6:7;m=g;g=q;f=o}return}function bD(a,b,c){a=a|0;b=b|0;c=c|0;return bF(Z(c,b)|0)|0}function bE(a,b){a=a|0;b=b|0;bG(b);return}function bF(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ab=0,ac=0,ad=0,ae=0,af=0,ag=0,ah=0,ai=0,aj=0,ak=0,an=0,ao=0,ap=0,aq=0,ar=0,as=0,at=0,au=0,av=0,ax=0,az=0,aA=0,aB=0,aD=0,aE=0,aF=0,aG=0,aH=0,aI=0,aJ=0,aK=0,aL=0;do{if(a>>>0<245){if(a>>>0<11){b=16}else{b=a+11&-8}d=b>>>3;e=c[3682]|0;f=e>>>(d>>>0);if((f&3|0)!=0){g=(f&1^1)+d|0;h=g<<1;i=14768+(h<<2)|0;j=14768+(h+2<<2)|0;h=c[j>>2]|0;k=h+8|0;l=c[k>>2]|0;do{if((i|0)==(l|0)){c[3682]=e&~(1<>>0<(c[3686]|0)>>>0){am();return 0}m=l+12|0;if((c[m>>2]|0)==(h|0)){c[m>>2]=i;c[j>>2]=l;break}else{am();return 0}}}while(0);l=g<<3;c[h+4>>2]=l|3;j=h+(l|4)|0;c[j>>2]=c[j>>2]|1;n=k;return n|0}if(b>>>0<=(c[3684]|0)>>>0){o=b;break}if((f|0)!=0){j=2<>>12&16;i=j>>>(l>>>0);j=i>>>5&8;m=i>>>(j>>>0);i=m>>>2&4;p=m>>>(i>>>0);m=p>>>1&2;q=p>>>(m>>>0);p=q>>>1&1;r=(j|l|i|m|p)+(q>>>(p>>>0))|0;p=r<<1;q=14768+(p<<2)|0;m=14768+(p+2<<2)|0;p=c[m>>2]|0;i=p+8|0;l=c[i>>2]|0;do{if((q|0)==(l|0)){c[3682]=e&~(1<>>0<(c[3686]|0)>>>0){am();return 0}j=l+12|0;if((c[j>>2]|0)==(p|0)){c[j>>2]=q;c[m>>2]=l;break}else{am();return 0}}}while(0);l=r<<3;m=l-b|0;c[p+4>>2]=b|3;q=p;e=q+b|0;c[q+(b|4)>>2]=m|1;c[q+l>>2]=m;l=c[3684]|0;if((l|0)!=0){q=c[3687]|0;d=l>>>3;l=d<<1;f=14768+(l<<2)|0;k=c[3682]|0;h=1<>2]|0;if(g>>>0>=(c[3686]|0)>>>0){s=g;t=d;break}am();return 0}}while(0);c[t>>2]=q;c[s+12>>2]=q;c[q+8>>2]=s;c[q+12>>2]=f}c[3684]=m;c[3687]=e;n=i;return n|0}l=c[3683]|0;if((l|0)==0){o=b;break}h=(l&-l)-1|0;l=h>>>12&16;k=h>>>(l>>>0);h=k>>>5&8;p=k>>>(h>>>0);k=p>>>2&4;r=p>>>(k>>>0);p=r>>>1&2;d=r>>>(p>>>0);r=d>>>1&1;g=c[15032+((h|l|k|p|r)+(d>>>(r>>>0))<<2)>>2]|0;r=g;d=g;p=(c[g+4>>2]&-8)-b|0;while(1){g=c[r+16>>2]|0;if((g|0)==0){k=c[r+20>>2]|0;if((k|0)==0){break}else{u=k}}else{u=g}g=(c[u+4>>2]&-8)-b|0;k=g>>>0

>>0;r=u;d=k?u:d;p=k?g:p}r=d;i=c[3686]|0;if(r>>>0>>0){am();return 0}e=r+b|0;m=e;if(r>>>0>=e>>>0){am();return 0}e=c[d+24>>2]|0;f=c[d+12>>2]|0;do{if((f|0)==(d|0)){q=d+20|0;g=c[q>>2]|0;if((g|0)==0){k=d+16|0;l=c[k>>2]|0;if((l|0)==0){v=0;break}else{w=l;x=k}}else{w=g;x=q}while(1){q=w+20|0;g=c[q>>2]|0;if((g|0)!=0){w=g;x=q;continue}q=w+16|0;g=c[q>>2]|0;if((g|0)==0){break}else{w=g;x=q}}if(x>>>0>>0){am();return 0}else{c[x>>2]=0;v=w;break}}else{q=c[d+8>>2]|0;if(q>>>0>>0){am();return 0}g=q+12|0;if((c[g>>2]|0)!=(d|0)){am();return 0}k=f+8|0;if((c[k>>2]|0)==(d|0)){c[g>>2]=f;c[k>>2]=q;v=f;break}else{am();return 0}}}while(0);L2648:do{if((e|0)!=0){f=d+28|0;i=15032+(c[f>>2]<<2)|0;do{if((d|0)==(c[i>>2]|0)){c[i>>2]=v;if((v|0)!=0){break}c[3683]=c[3683]&~(1<>2]);break L2648}else{if(e>>>0<(c[3686]|0)>>>0){am();return 0}q=e+16|0;if((c[q>>2]|0)==(d|0)){c[q>>2]=v}else{c[e+20>>2]=v}if((v|0)==0){break L2648}}}while(0);if(v>>>0<(c[3686]|0)>>>0){am();return 0}c[v+24>>2]=e;f=c[d+16>>2]|0;do{if((f|0)!=0){if(f>>>0<(c[3686]|0)>>>0){am();return 0}else{c[v+16>>2]=f;c[f+24>>2]=v;break}}}while(0);f=c[d+20>>2]|0;if((f|0)==0){break}if(f>>>0<(c[3686]|0)>>>0){am();return 0}else{c[v+20>>2]=f;c[f+24>>2]=v;break}}}while(0);if(p>>>0<16){e=p+b|0;c[d+4>>2]=e|3;f=r+(e+4)|0;c[f>>2]=c[f>>2]|1}else{c[d+4>>2]=b|3;c[r+(b|4)>>2]=p|1;c[r+(p+b)>>2]=p;f=c[3684]|0;if((f|0)!=0){e=c[3687]|0;i=f>>>3;f=i<<1;q=14768+(f<<2)|0;k=c[3682]|0;g=1<>2]|0;if(l>>>0>=(c[3686]|0)>>>0){y=l;z=i;break}am();return 0}}while(0);c[z>>2]=e;c[y+12>>2]=e;c[e+8>>2]=y;c[e+12>>2]=q}c[3684]=p;c[3687]=m}f=d+8|0;if((f|0)==0){o=b;break}else{n=f}return n|0}else{if(a>>>0>4294967231){o=-1;break}f=a+11|0;g=f&-8;k=c[3683]|0;if((k|0)==0){o=g;break}r=-g|0;i=f>>>8;do{if((i|0)==0){A=0}else{if(g>>>0>16777215){A=31;break}f=(i+1048320|0)>>>16&8;l=i<>>16&4;j=l<>>16&2;B=14-(h|f|l)+(j<>>15)|0;A=g>>>((B+7|0)>>>0)&1|B<<1}}while(0);i=c[15032+(A<<2)>>2]|0;L2696:do{if((i|0)==0){C=0;D=r;E=0}else{if((A|0)==31){F=0}else{F=25-(A>>>1)|0}d=0;m=r;p=i;q=g<>2]&-8;l=B-g|0;if(l>>>0>>0){if((B|0)==(g|0)){C=p;D=l;E=p;break L2696}else{G=p;H=l}}else{G=d;H=m}l=c[p+20>>2]|0;B=c[p+16+(q>>>31<<2)>>2]|0;j=(l|0)==0|(l|0)==(B|0)?e:l;if((B|0)==0){C=G;D=H;E=j;break}else{d=G;m=H;p=B;q=q<<1;e=j}}}}while(0);if((E|0)==0&(C|0)==0){i=2<>>12&16;e=i>>>(r>>>0);i=e>>>5&8;q=e>>>(i>>>0);e=q>>>2&4;p=q>>>(e>>>0);q=p>>>1&2;m=p>>>(q>>>0);p=m>>>1&1;I=c[15032+((i|r|e|q|p)+(m>>>(p>>>0))<<2)>>2]|0}else{I=E}if((I|0)==0){J=D;K=C}else{p=I;m=D;q=C;while(1){e=(c[p+4>>2]&-8)-g|0;r=e>>>0>>0;i=r?e:m;e=r?p:q;r=c[p+16>>2]|0;if((r|0)!=0){p=r;m=i;q=e;continue}r=c[p+20>>2]|0;if((r|0)==0){J=i;K=e;break}else{p=r;m=i;q=e}}}if((K|0)==0){o=g;break}if(J>>>0>=((c[3684]|0)-g|0)>>>0){o=g;break}q=K;m=c[3686]|0;if(q>>>0>>0){am();return 0}p=q+g|0;k=p;if(q>>>0>=p>>>0){am();return 0}e=c[K+24>>2]|0;i=c[K+12>>2]|0;do{if((i|0)==(K|0)){r=K+20|0;d=c[r>>2]|0;if((d|0)==0){j=K+16|0;B=c[j>>2]|0;if((B|0)==0){L=0;break}else{M=B;N=j}}else{M=d;N=r}while(1){r=M+20|0;d=c[r>>2]|0;if((d|0)!=0){M=d;N=r;continue}r=M+16|0;d=c[r>>2]|0;if((d|0)==0){break}else{M=d;N=r}}if(N>>>0>>0){am();return 0}else{c[N>>2]=0;L=M;break}}else{r=c[K+8>>2]|0;if(r>>>0>>0){am();return 0}d=r+12|0;if((c[d>>2]|0)!=(K|0)){am();return 0}j=i+8|0;if((c[j>>2]|0)==(K|0)){c[d>>2]=i;c[j>>2]=r;L=i;break}else{am();return 0}}}while(0);L2746:do{if((e|0)!=0){i=K+28|0;m=15032+(c[i>>2]<<2)|0;do{if((K|0)==(c[m>>2]|0)){c[m>>2]=L;if((L|0)!=0){break}c[3683]=c[3683]&~(1<>2]);break L2746}else{if(e>>>0<(c[3686]|0)>>>0){am();return 0}r=e+16|0;if((c[r>>2]|0)==(K|0)){c[r>>2]=L}else{c[e+20>>2]=L}if((L|0)==0){break L2746}}}while(0);if(L>>>0<(c[3686]|0)>>>0){am();return 0}c[L+24>>2]=e;i=c[K+16>>2]|0;do{if((i|0)!=0){if(i>>>0<(c[3686]|0)>>>0){am();return 0}else{c[L+16>>2]=i;c[i+24>>2]=L;break}}}while(0);i=c[K+20>>2]|0;if((i|0)==0){break}if(i>>>0<(c[3686]|0)>>>0){am();return 0}else{c[L+20>>2]=i;c[i+24>>2]=L;break}}}while(0);do{if(J>>>0<16){e=J+g|0;c[K+4>>2]=e|3;i=q+(e+4)|0;c[i>>2]=c[i>>2]|1}else{c[K+4>>2]=g|3;c[q+(g|4)>>2]=J|1;c[q+(J+g)>>2]=J;i=J>>>3;if(J>>>0<256){e=i<<1;m=14768+(e<<2)|0;r=c[3682]|0;j=1<>2]|0;if(d>>>0>=(c[3686]|0)>>>0){O=d;P=i;break}am();return 0}}while(0);c[P>>2]=k;c[O+12>>2]=k;c[q+(g+8)>>2]=O;c[q+(g+12)>>2]=m;break}e=p;j=J>>>8;do{if((j|0)==0){Q=0}else{if(J>>>0>16777215){Q=31;break}r=(j+1048320|0)>>>16&8;i=j<>>16&4;B=i<>>16&2;l=14-(d|r|i)+(B<>>15)|0;Q=J>>>((l+7|0)>>>0)&1|l<<1}}while(0);j=15032+(Q<<2)|0;c[q+(g+28)>>2]=Q;c[q+(g+20)>>2]=0;c[q+(g+16)>>2]=0;m=c[3683]|0;l=1<>2]=e;c[q+(g+24)>>2]=j;c[q+(g+12)>>2]=e;c[q+(g+8)>>2]=e;break}if((Q|0)==31){R=0}else{R=25-(Q>>>1)|0}l=J<>2]|0;while(1){if((c[m+4>>2]&-8|0)==(J|0)){break}S=m+16+(l>>>31<<2)|0;j=c[S>>2]|0;if((j|0)==0){T=2011;break}else{l=l<<1;m=j}}if((T|0)==2011){if(S>>>0<(c[3686]|0)>>>0){am();return 0}else{c[S>>2]=e;c[q+(g+24)>>2]=m;c[q+(g+12)>>2]=e;c[q+(g+8)>>2]=e;break}}l=m+8|0;j=c[l>>2]|0;i=c[3686]|0;if(m>>>0>>0){am();return 0}if(j>>>0>>0){am();return 0}else{c[j+12>>2]=e;c[l>>2]=e;c[q+(g+8)>>2]=j;c[q+(g+12)>>2]=m;c[q+(g+24)>>2]=0;break}}}while(0);q=K+8|0;if((q|0)==0){o=g;break}else{n=q}return n|0}}while(0);K=c[3684]|0;if(o>>>0<=K>>>0){S=K-o|0;J=c[3687]|0;if(S>>>0>15){R=J;c[3687]=R+o;c[3684]=S;c[R+(o+4)>>2]=S|1;c[R+K>>2]=S;c[J+4>>2]=o|3}else{c[3684]=0;c[3687]=0;c[J+4>>2]=K|3;S=J+(K+4)|0;c[S>>2]=c[S>>2]|1}n=J+8|0;return n|0}J=c[3685]|0;if(o>>>0>>0){S=J-o|0;c[3685]=S;J=c[3688]|0;K=J;c[3688]=K+o;c[K+(o+4)>>2]=S|1;c[J+4>>2]=o|3;n=J+8|0;return n|0}do{if((c[3674]|0)==0){J=al(8)|0;if((J-1&J|0)==0){c[3676]=J;c[3675]=J;c[3677]=-1;c[3678]=2097152;c[3679]=0;c[3793]=0;c[3674]=(aC(0)|0)&-16^1431655768;break}else{am();return 0}}}while(0);J=o+48|0;S=c[3676]|0;K=o+47|0;R=S+K|0;Q=-S|0;S=R&Q;if(S>>>0<=o>>>0){n=0;return n|0}O=c[3792]|0;do{if((O|0)!=0){P=c[3790]|0;L=P+S|0;if(L>>>0<=P>>>0|L>>>0>O>>>0){n=0}else{break}return n|0}}while(0);L2838:do{if((c[3793]&4|0)==0){O=c[3688]|0;L2840:do{if((O|0)==0){T=2041}else{L=O;P=15176;while(1){U=P|0;M=c[U>>2]|0;if(M>>>0<=L>>>0){V=P+4|0;if((M+(c[V>>2]|0)|0)>>>0>L>>>0){break}}M=c[P+8>>2]|0;if((M|0)==0){T=2041;break L2840}else{P=M}}if((P|0)==0){T=2041;break}L=R-(c[3685]|0)&Q;if(L>>>0>=2147483647){W=0;break}m=aw(L|0)|0;e=(m|0)==((c[U>>2]|0)+(c[V>>2]|0)|0);X=e?m:-1;Y=e?L:0;Z=m;_=L;T=2050}}while(0);do{if((T|0)==2041){O=aw(0)|0;if((O|0)==-1){W=0;break}g=O;L=c[3675]|0;m=L-1|0;if((m&g|0)==0){$=S}else{$=S-g+(m+g&-L)|0}L=c[3790]|0;g=L+$|0;if(!($>>>0>o>>>0&$>>>0<2147483647)){W=0;break}m=c[3792]|0;if((m|0)!=0){if(g>>>0<=L>>>0|g>>>0>m>>>0){W=0;break}}m=aw($|0)|0;g=(m|0)==(O|0);X=g?O:-1;Y=g?$:0;Z=m;_=$;T=2050}}while(0);L2860:do{if((T|0)==2050){m=-_|0;if((X|0)!=-1){aa=Y;ab=X;T=2061;break L2838}do{if((Z|0)!=-1&_>>>0<2147483647&_>>>0>>0){g=c[3676]|0;O=K-_+g&-g;if(O>>>0>=2147483647){ac=_;break}if((aw(O|0)|0)==-1){aw(m|0)|0;W=Y;break L2860}else{ac=O+_|0;break}}else{ac=_}}while(0);if((Z|0)==-1){W=Y}else{aa=ac;ab=Z;T=2061;break L2838}}}while(0);c[3793]=c[3793]|4;ad=W;T=2058}else{ad=0;T=2058}}while(0);do{if((T|0)==2058){if(S>>>0>=2147483647){break}W=aw(S|0)|0;Z=aw(0)|0;if(!((Z|0)!=-1&(W|0)!=-1&W>>>0>>0)){break}ac=Z-W|0;Z=ac>>>0>(o+40|0)>>>0;Y=Z?W:-1;if((Y|0)!=-1){aa=Z?ac:ad;ab=Y;T=2061}}}while(0);do{if((T|0)==2061){ad=(c[3790]|0)+aa|0;c[3790]=ad;if(ad>>>0>(c[3791]|0)>>>0){c[3791]=ad}ad=c[3688]|0;L2880:do{if((ad|0)==0){S=c[3686]|0;if((S|0)==0|ab>>>0>>0){c[3686]=ab}c[3794]=ab;c[3795]=aa;c[3797]=0;c[3691]=c[3674];c[3690]=-1;S=0;do{Y=S<<1;ac=14768+(Y<<2)|0;c[14768+(Y+3<<2)>>2]=ac;c[14768+(Y+2<<2)>>2]=ac;S=S+1|0;}while(S>>>0<32);S=ab+8|0;if((S&7|0)==0){ae=0}else{ae=-S&7}S=aa-40-ae|0;c[3688]=ab+ae;c[3685]=S;c[ab+(ae+4)>>2]=S|1;c[ab+(aa-36)>>2]=40;c[3689]=c[3678]}else{S=15176;while(1){af=c[S>>2]|0;ag=S+4|0;ah=c[ag>>2]|0;if((ab|0)==(af+ah|0)){T=2073;break}ac=c[S+8>>2]|0;if((ac|0)==0){break}else{S=ac}}do{if((T|0)==2073){if((c[S+12>>2]&8|0)!=0){break}ac=ad;if(!(ac>>>0>=af>>>0&ac>>>0>>0)){break}c[ag>>2]=ah+aa;ac=c[3688]|0;Y=(c[3685]|0)+aa|0;Z=ac;W=ac+8|0;if((W&7|0)==0){ai=0}else{ai=-W&7}W=Y-ai|0;c[3688]=Z+ai;c[3685]=W;c[Z+(ai+4)>>2]=W|1;c[Z+(Y+4)>>2]=40;c[3689]=c[3678];break L2880}}while(0);if(ab>>>0<(c[3686]|0)>>>0){c[3686]=ab}S=ab+aa|0;Y=15176;while(1){aj=Y|0;if((c[aj>>2]|0)==(S|0)){T=2083;break}Z=c[Y+8>>2]|0;if((Z|0)==0){break}else{Y=Z}}do{if((T|0)==2083){if((c[Y+12>>2]&8|0)!=0){break}c[aj>>2]=ab;S=Y+4|0;c[S>>2]=(c[S>>2]|0)+aa;S=ab+8|0;if((S&7|0)==0){ak=0}else{ak=-S&7}S=ab+(aa+8)|0;if((S&7|0)==0){an=0}else{an=-S&7}S=ab+(an+aa)|0;Z=S;W=ak+o|0;ac=ab+W|0;_=ac;K=S-(ab+ak)-o|0;c[ab+(ak+4)>>2]=o|3;do{if((Z|0)==(c[3688]|0)){J=(c[3685]|0)+K|0;c[3685]=J;c[3688]=_;c[ab+(W+4)>>2]=J|1}else{if((Z|0)==(c[3687]|0)){J=(c[3684]|0)+K|0;c[3684]=J;c[3687]=_;c[ab+(W+4)>>2]=J|1;c[ab+(J+W)>>2]=J;break}J=aa+4|0;X=c[ab+(J+an)>>2]|0;if((X&3|0)==1){$=X&-8;V=X>>>3;L2915:do{if(X>>>0<256){U=c[ab+((an|8)+aa)>>2]|0;Q=c[ab+(aa+12+an)>>2]|0;R=14768+(V<<1<<2)|0;do{if((U|0)!=(R|0)){if(U>>>0<(c[3686]|0)>>>0){am();return 0}if((c[U+12>>2]|0)==(Z|0)){break}am();return 0}}while(0);if((Q|0)==(U|0)){c[3682]=c[3682]&~(1<>>0<(c[3686]|0)>>>0){am();return 0}m=Q+8|0;if((c[m>>2]|0)==(Z|0)){ao=m;break}am();return 0}}while(0);c[U+12>>2]=Q;c[ao>>2]=U}else{R=S;m=c[ab+((an|24)+aa)>>2]|0;P=c[ab+(aa+12+an)>>2]|0;do{if((P|0)==(R|0)){O=an|16;g=ab+(J+O)|0;L=c[g>>2]|0;if((L|0)==0){e=ab+(O+aa)|0;O=c[e>>2]|0;if((O|0)==0){ap=0;break}else{aq=O;ar=e}}else{aq=L;ar=g}while(1){g=aq+20|0;L=c[g>>2]|0;if((L|0)!=0){aq=L;ar=g;continue}g=aq+16|0;L=c[g>>2]|0;if((L|0)==0){break}else{aq=L;ar=g}}if(ar>>>0<(c[3686]|0)>>>0){am();return 0}else{c[ar>>2]=0;ap=aq;break}}else{g=c[ab+((an|8)+aa)>>2]|0;if(g>>>0<(c[3686]|0)>>>0){am();return 0}L=g+12|0;if((c[L>>2]|0)!=(R|0)){am();return 0}e=P+8|0;if((c[e>>2]|0)==(R|0)){c[L>>2]=P;c[e>>2]=g;ap=P;break}else{am();return 0}}}while(0);if((m|0)==0){break}P=ab+(aa+28+an)|0;U=15032+(c[P>>2]<<2)|0;do{if((R|0)==(c[U>>2]|0)){c[U>>2]=ap;if((ap|0)!=0){break}c[3683]=c[3683]&~(1<>2]);break L2915}else{if(m>>>0<(c[3686]|0)>>>0){am();return 0}Q=m+16|0;if((c[Q>>2]|0)==(R|0)){c[Q>>2]=ap}else{c[m+20>>2]=ap}if((ap|0)==0){break L2915}}}while(0);if(ap>>>0<(c[3686]|0)>>>0){am();return 0}c[ap+24>>2]=m;R=an|16;P=c[ab+(R+aa)>>2]|0;do{if((P|0)!=0){if(P>>>0<(c[3686]|0)>>>0){am();return 0}else{c[ap+16>>2]=P;c[P+24>>2]=ap;break}}}while(0);P=c[ab+(J+R)>>2]|0;if((P|0)==0){break}if(P>>>0<(c[3686]|0)>>>0){am();return 0}else{c[ap+20>>2]=P;c[P+24>>2]=ap;break}}}while(0);as=ab+(($|an)+aa)|0;at=$+K|0}else{as=Z;at=K}J=as+4|0;c[J>>2]=c[J>>2]&-2;c[ab+(W+4)>>2]=at|1;c[ab+(at+W)>>2]=at;J=at>>>3;if(at>>>0<256){V=J<<1;X=14768+(V<<2)|0;P=c[3682]|0;m=1<>2]|0;if(U>>>0>=(c[3686]|0)>>>0){au=U;av=J;break}am();return 0}}while(0);c[av>>2]=_;c[au+12>>2]=_;c[ab+(W+8)>>2]=au;c[ab+(W+12)>>2]=X;break}V=ac;m=at>>>8;do{if((m|0)==0){ax=0}else{if(at>>>0>16777215){ax=31;break}P=(m+1048320|0)>>>16&8;$=m<>>16&4;U=$<>>16&2;Q=14-(J|P|$)+(U<<$>>>15)|0;ax=at>>>((Q+7|0)>>>0)&1|Q<<1}}while(0);m=15032+(ax<<2)|0;c[ab+(W+28)>>2]=ax;c[ab+(W+20)>>2]=0;c[ab+(W+16)>>2]=0;X=c[3683]|0;Q=1<>2]=V;c[ab+(W+24)>>2]=m;c[ab+(W+12)>>2]=V;c[ab+(W+8)>>2]=V;break}if((ax|0)==31){az=0}else{az=25-(ax>>>1)|0}Q=at<>2]|0;while(1){if((c[X+4>>2]&-8|0)==(at|0)){break}aA=X+16+(Q>>>31<<2)|0;m=c[aA>>2]|0;if((m|0)==0){T=2156;break}else{Q=Q<<1;X=m}}if((T|0)==2156){if(aA>>>0<(c[3686]|0)>>>0){am();return 0}else{c[aA>>2]=V;c[ab+(W+24)>>2]=X;c[ab+(W+12)>>2]=V;c[ab+(W+8)>>2]=V;break}}Q=X+8|0;m=c[Q>>2]|0;$=c[3686]|0;if(X>>>0<$>>>0){am();return 0}if(m>>>0<$>>>0){am();return 0}else{c[m+12>>2]=V;c[Q>>2]=V;c[ab+(W+8)>>2]=m;c[ab+(W+12)>>2]=X;c[ab+(W+24)>>2]=0;break}}}while(0);n=ab+(ak|8)|0;return n|0}}while(0);Y=ad;W=15176;while(1){aB=c[W>>2]|0;if(aB>>>0<=Y>>>0){aD=c[W+4>>2]|0;aE=aB+aD|0;if(aE>>>0>Y>>>0){break}}W=c[W+8>>2]|0}W=aB+(aD-39)|0;if((W&7|0)==0){aF=0}else{aF=-W&7}W=aB+(aD-47+aF)|0;ac=W>>>0<(ad+16|0)>>>0?Y:W;W=ac+8|0;_=ab+8|0;if((_&7|0)==0){aG=0}else{aG=-_&7}_=aa-40-aG|0;c[3688]=ab+aG;c[3685]=_;c[ab+(aG+4)>>2]=_|1;c[ab+(aa-36)>>2]=40;c[3689]=c[3678];c[ac+4>>2]=27;c[W>>2]=c[3794];c[W+4>>2]=c[15180>>2];c[W+8>>2]=c[15184>>2];c[W+12>>2]=c[15188>>2];c[3794]=ab;c[3795]=aa;c[3797]=0;c[3796]=W;W=ac+28|0;c[W>>2]=7;if((ac+32|0)>>>0>>0){_=W;while(1){W=_+4|0;c[W>>2]=7;if((_+8|0)>>>0>>0){_=W}else{break}}}if((ac|0)==(Y|0)){break}_=ac-ad|0;W=Y+(_+4)|0;c[W>>2]=c[W>>2]&-2;c[ad+4>>2]=_|1;c[Y+_>>2]=_;W=_>>>3;if(_>>>0<256){K=W<<1;Z=14768+(K<<2)|0;S=c[3682]|0;m=1<>2]|0;if(Q>>>0>=(c[3686]|0)>>>0){aH=Q;aI=W;break}am();return 0}}while(0);c[aI>>2]=ad;c[aH+12>>2]=ad;c[ad+8>>2]=aH;c[ad+12>>2]=Z;break}K=ad;m=_>>>8;do{if((m|0)==0){aJ=0}else{if(_>>>0>16777215){aJ=31;break}S=(m+1048320|0)>>>16&8;Y=m<>>16&4;W=Y<>>16&2;Q=14-(ac|S|Y)+(W<>>15)|0;aJ=_>>>((Q+7|0)>>>0)&1|Q<<1}}while(0);m=15032+(aJ<<2)|0;c[ad+28>>2]=aJ;c[ad+20>>2]=0;c[ad+16>>2]=0;Z=c[3683]|0;Q=1<>2]=K;c[ad+24>>2]=m;c[ad+12>>2]=ad;c[ad+8>>2]=ad;break}if((aJ|0)==31){aK=0}else{aK=25-(aJ>>>1)|0}Q=_<>2]|0;while(1){if((c[Z+4>>2]&-8|0)==(_|0)){break}aL=Z+16+(Q>>>31<<2)|0;m=c[aL>>2]|0;if((m|0)==0){T=2191;break}else{Q=Q<<1;Z=m}}if((T|0)==2191){if(aL>>>0<(c[3686]|0)>>>0){am();return 0}else{c[aL>>2]=K;c[ad+24>>2]=Z;c[ad+12>>2]=ad;c[ad+8>>2]=ad;break}}Q=Z+8|0;_=c[Q>>2]|0;m=c[3686]|0;if(Z>>>0>>0){am();return 0}if(_>>>0>>0){am();return 0}else{c[_+12>>2]=K;c[Q>>2]=K;c[ad+8>>2]=_;c[ad+12>>2]=Z;c[ad+24>>2]=0;break}}}while(0);ad=c[3685]|0;if(ad>>>0<=o>>>0){break}_=ad-o|0;c[3685]=_;ad=c[3688]|0;Q=ad;c[3688]=Q+o;c[Q+(o+4)>>2]=_|1;c[ad+4>>2]=o|3;n=ad+8|0;return n|0}}while(0);c[(ay()|0)>>2]=12;n=0;return n|0}function bG(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;if((a|0)==0){return}b=a-8|0;d=b;e=c[3686]|0;if(b>>>0>>0){am()}f=c[a-4>>2]|0;g=f&3;if((g|0)==1){am()}h=f&-8;i=a+(h-8)|0;j=i;L3097:do{if((f&1|0)==0){k=c[b>>2]|0;if((g|0)==0){return}l=-8-k|0;m=a+l|0;n=m;o=k+h|0;if(m>>>0>>0){am()}if((n|0)==(c[3687]|0)){p=a+(h-4)|0;if((c[p>>2]&3|0)!=3){q=n;r=o;break}c[3684]=o;c[p>>2]=c[p>>2]&-2;c[a+(l+4)>>2]=o|1;c[i>>2]=o;return}p=k>>>3;if(k>>>0<256){k=c[a+(l+8)>>2]|0;s=c[a+(l+12)>>2]|0;t=14768+(p<<1<<2)|0;do{if((k|0)!=(t|0)){if(k>>>0>>0){am()}if((c[k+12>>2]|0)==(n|0)){break}am()}}while(0);if((s|0)==(k|0)){c[3682]=c[3682]&~(1<>>0>>0){am()}v=s+8|0;if((c[v>>2]|0)==(n|0)){u=v;break}am()}}while(0);c[k+12>>2]=s;c[u>>2]=k;q=n;r=o;break}t=m;p=c[a+(l+24)>>2]|0;v=c[a+(l+12)>>2]|0;do{if((v|0)==(t|0)){w=a+(l+20)|0;x=c[w>>2]|0;if((x|0)==0){y=a+(l+16)|0;z=c[y>>2]|0;if((z|0)==0){A=0;break}else{B=z;C=y}}else{B=x;C=w}while(1){w=B+20|0;x=c[w>>2]|0;if((x|0)!=0){B=x;C=w;continue}w=B+16|0;x=c[w>>2]|0;if((x|0)==0){break}else{B=x;C=w}}if(C>>>0>>0){am()}else{c[C>>2]=0;A=B;break}}else{w=c[a+(l+8)>>2]|0;if(w>>>0>>0){am()}x=w+12|0;if((c[x>>2]|0)!=(t|0)){am()}y=v+8|0;if((c[y>>2]|0)==(t|0)){c[x>>2]=v;c[y>>2]=w;A=v;break}else{am()}}}while(0);if((p|0)==0){q=n;r=o;break}v=a+(l+28)|0;m=15032+(c[v>>2]<<2)|0;do{if((t|0)==(c[m>>2]|0)){c[m>>2]=A;if((A|0)!=0){break}c[3683]=c[3683]&~(1<>2]);q=n;r=o;break L3097}else{if(p>>>0<(c[3686]|0)>>>0){am()}k=p+16|0;if((c[k>>2]|0)==(t|0)){c[k>>2]=A}else{c[p+20>>2]=A}if((A|0)==0){q=n;r=o;break L3097}}}while(0);if(A>>>0<(c[3686]|0)>>>0){am()}c[A+24>>2]=p;t=c[a+(l+16)>>2]|0;do{if((t|0)!=0){if(t>>>0<(c[3686]|0)>>>0){am()}else{c[A+16>>2]=t;c[t+24>>2]=A;break}}}while(0);t=c[a+(l+20)>>2]|0;if((t|0)==0){q=n;r=o;break}if(t>>>0<(c[3686]|0)>>>0){am()}else{c[A+20>>2]=t;c[t+24>>2]=A;q=n;r=o;break}}else{q=d;r=h}}while(0);d=q;if(d>>>0>=i>>>0){am()}A=a+(h-4)|0;e=c[A>>2]|0;if((e&1|0)==0){am()}do{if((e&2|0)==0){if((j|0)==(c[3688]|0)){B=(c[3685]|0)+r|0;c[3685]=B;c[3688]=q;c[q+4>>2]=B|1;if((q|0)==(c[3687]|0)){c[3687]=0;c[3684]=0}if(B>>>0<=(c[3689]|0)>>>0){return}bH(0)|0;return}if((j|0)==(c[3687]|0)){B=(c[3684]|0)+r|0;c[3684]=B;c[3687]=q;c[q+4>>2]=B|1;c[d+B>>2]=B;return}B=(e&-8)+r|0;C=e>>>3;L3203:do{if(e>>>0<256){u=c[a+h>>2]|0;g=c[a+(h|4)>>2]|0;b=14768+(C<<1<<2)|0;do{if((u|0)!=(b|0)){if(u>>>0<(c[3686]|0)>>>0){am()}if((c[u+12>>2]|0)==(j|0)){break}am()}}while(0);if((g|0)==(u|0)){c[3682]=c[3682]&~(1<>>0<(c[3686]|0)>>>0){am()}f=g+8|0;if((c[f>>2]|0)==(j|0)){D=f;break}am()}}while(0);c[u+12>>2]=g;c[D>>2]=u}else{b=i;f=c[a+(h+16)>>2]|0;t=c[a+(h|4)>>2]|0;do{if((t|0)==(b|0)){p=a+(h+12)|0;v=c[p>>2]|0;if((v|0)==0){m=a+(h+8)|0;k=c[m>>2]|0;if((k|0)==0){E=0;break}else{F=k;G=m}}else{F=v;G=p}while(1){p=F+20|0;v=c[p>>2]|0;if((v|0)!=0){F=v;G=p;continue}p=F+16|0;v=c[p>>2]|0;if((v|0)==0){break}else{F=v;G=p}}if(G>>>0<(c[3686]|0)>>>0){am()}else{c[G>>2]=0;E=F;break}}else{p=c[a+h>>2]|0;if(p>>>0<(c[3686]|0)>>>0){am()}v=p+12|0;if((c[v>>2]|0)!=(b|0)){am()}m=t+8|0;if((c[m>>2]|0)==(b|0)){c[v>>2]=t;c[m>>2]=p;E=t;break}else{am()}}}while(0);if((f|0)==0){break}t=a+(h+20)|0;u=15032+(c[t>>2]<<2)|0;do{if((b|0)==(c[u>>2]|0)){c[u>>2]=E;if((E|0)!=0){break}c[3683]=c[3683]&~(1<>2]);break L3203}else{if(f>>>0<(c[3686]|0)>>>0){am()}g=f+16|0;if((c[g>>2]|0)==(b|0)){c[g>>2]=E}else{c[f+20>>2]=E}if((E|0)==0){break L3203}}}while(0);if(E>>>0<(c[3686]|0)>>>0){am()}c[E+24>>2]=f;b=c[a+(h+8)>>2]|0;do{if((b|0)!=0){if(b>>>0<(c[3686]|0)>>>0){am()}else{c[E+16>>2]=b;c[b+24>>2]=E;break}}}while(0);b=c[a+(h+12)>>2]|0;if((b|0)==0){break}if(b>>>0<(c[3686]|0)>>>0){am()}else{c[E+20>>2]=b;c[b+24>>2]=E;break}}}while(0);c[q+4>>2]=B|1;c[d+B>>2]=B;if((q|0)!=(c[3687]|0)){H=B;break}c[3684]=B;return}else{c[A>>2]=e&-2;c[q+4>>2]=r|1;c[d+r>>2]=r;H=r}}while(0);r=H>>>3;if(H>>>0<256){d=r<<1;e=14768+(d<<2)|0;A=c[3682]|0;E=1<>2]|0;if(h>>>0>=(c[3686]|0)>>>0){I=h;J=r;break}am()}}while(0);c[J>>2]=q;c[I+12>>2]=q;c[q+8>>2]=I;c[q+12>>2]=e;return}e=q;I=H>>>8;do{if((I|0)==0){K=0}else{if(H>>>0>16777215){K=31;break}J=(I+1048320|0)>>>16&8;d=I<>>16&4;A=d<>>16&2;r=14-(E|J|d)+(A<>>15)|0;K=H>>>((r+7|0)>>>0)&1|r<<1}}while(0);I=15032+(K<<2)|0;c[q+28>>2]=K;c[q+20>>2]=0;c[q+16>>2]=0;r=c[3683]|0;d=1<>2]=e;c[q+24>>2]=I;c[q+12>>2]=q;c[q+8>>2]=q}else{if((K|0)==31){L=0}else{L=25-(K>>>1)|0}A=H<>2]|0;while(1){if((c[J+4>>2]&-8|0)==(H|0)){break}M=J+16+(A>>>31<<2)|0;E=c[M>>2]|0;if((E|0)==0){N=2370;break}else{A=A<<1;J=E}}if((N|0)==2370){if(M>>>0<(c[3686]|0)>>>0){am()}else{c[M>>2]=e;c[q+24>>2]=J;c[q+12>>2]=q;c[q+8>>2]=q;break}}A=J+8|0;B=c[A>>2]|0;E=c[3686]|0;if(J>>>0>>0){am()}if(B>>>0>>0){am()}else{c[B+12>>2]=e;c[A>>2]=e;c[q+8>>2]=B;c[q+12>>2]=J;c[q+24>>2]=0;break}}}while(0);q=(c[3690]|0)-1|0;c[3690]=q;if((q|0)==0){O=15184}else{return}while(1){q=c[O>>2]|0;if((q|0)==0){break}else{O=q+8|0}}c[3690]=-1;return}function bH(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;do{if((c[3674]|0)==0){b=al(8)|0;if((b-1&b|0)==0){c[3676]=b;c[3675]=b;c[3677]=-1;c[3678]=2097152;c[3679]=0;c[3793]=0;c[3674]=(aC(0)|0)&-16^1431655768;break}else{am();return 0}}}while(0);if(a>>>0>=4294967232){d=0;return d|0}b=c[3688]|0;if((b|0)==0){d=0;return d|0}e=c[3685]|0;do{if(e>>>0>(a+40|0)>>>0){f=c[3676]|0;g=Z((((-40-a-1+e+f|0)>>>0)/(f>>>0)|0)-1|0,f)|0;h=b;i=15176;while(1){j=c[i>>2]|0;if(j>>>0<=h>>>0){if((j+(c[i+4>>2]|0)|0)>>>0>h>>>0){k=i;break}}j=c[i+8>>2]|0;if((j|0)==0){k=0;break}else{i=j}}if((c[k+12>>2]&8|0)!=0){break}i=aw(0)|0;h=k+4|0;if((i|0)!=((c[k>>2]|0)+(c[h>>2]|0)|0)){break}j=aw(-(g>>>0>2147483646?-2147483648-f|0:g)|0)|0;l=aw(0)|0;if(!((j|0)!=-1&l>>>0>>0)){break}j=i-l|0;if((i|0)==(l|0)){break}c[h>>2]=(c[h>>2]|0)-j;c[3790]=(c[3790]|0)-j;h=c[3688]|0;m=(c[3685]|0)-j|0;j=h;n=h+8|0;if((n&7|0)==0){o=0}else{o=-n&7}n=m-o|0;c[3688]=j+o;c[3685]=n;c[j+(o+4)>>2]=n|1;c[j+(m+4)>>2]=40;c[3689]=c[3678];d=(i|0)!=(l|0)|0;return d|0}}while(0);if((c[3685]|0)>>>0<=(c[3689]|0)>>>0){d=0;return d|0}c[3689]=-1;d=0;return d|0}function bI(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=b+e|0;if((e|0)>=20){d=d&255;e=b&3;g=d|d<<8|d<<16|d<<24;h=f&~3;if(e){e=b+4-e|0;while((b|0)<(e|0)){a[b]=d;b=b+1|0}}while((b|0)<(h|0)){c[b>>2]=g;b=b+4|0}}while((b|0)<(f|0)){a[b]=d;b=b+1|0}}function bJ(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;f=b|0;if((b&3)==(d&3)){while(b&3){if((e|0)==0)return f|0;a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function bK(b){b=b|0;var c=0;c=b;while(a[c]|0){c=c+1|0}return c-b|0}function bL(b,c){b=b|0;c=c|0;var d=0;do{a[b+d|0]=a[c+d|0];d=d+1|0}while(a[c+(d-1)|0]|0);return b|0}function bM(b,c){b=b|0;c=c|0;var d=0,e=0;d=b+(bK(b)|0)|0;do{a[d+e|0]=a[c+e|0];e=e+1|0}while(a[c+(e-1)|0]|0);return b|0}function bN(a,b){a=a|0;b=b|0;return aD[a&3](b|0)|0}function bO(a,b){a=a|0;b=b|0;aE[a&1](b|0)}function bP(a,b,c){a=a|0;b=b|0;c=c|0;aF[a&3](b|0,c|0)}function bQ(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return aG[a&7](b|0,c|0,d|0)|0}function bR(a){a=a|0;aH[a&1]()}function bS(a,b,c){a=a|0;b=b|0;c=c|0;return aI[a&15](b|0,c|0)|0}function bT(a){a=a|0;_(0);return 0}function bU(a){a=a|0;_(1)}function bV(a,b){a=a|0;b=b|0;_(2)}function bW(a,b,c){a=a|0;b=b|0;c=c|0;_(3);return 0}function bX(){_(4)}function bY(a,b){a=a|0;b=b|0;_(5);return 0} +// EMSCRIPTEN_END_FUNCS +var aD=[bT,bT,a9,bT];var aE=[bU,bU];var aF=[bV,bV,bE,bV];var aG=[bW,bW,bi,bW,bd,bW,bD,bW];var aH=[bX,bX];var aI=[bY,bY,a5,bY,ba,bY,a8,bY,a6,bY,bY,bY,bY,bY,bY,bY];return{_gzwrite:bi,_strlen:bK,_strcat:bM,_free:bG,_gzread:bd,_gzopen:ba,_memset:bI,_malloc:bF,_memcpy:bJ,_gzclose:a9,_strcpy:bL,runPostSets:aZ,stackAlloc:aJ,stackSave:aK,stackRestore:aL,setThrew:aM,setTempRet0:aP,setTempRet1:aQ,setTempRet2:aR,setTempRet3:aS,setTempRet4:aT,setTempRet5:aU,setTempRet6:aV,setTempRet7:aW,setTempRet8:aX,setTempRet9:aY,dynCall_ii:bN,dynCall_vi:bO,dynCall_vii:bP,dynCall_iiii:bQ,dynCall_v:bR,dynCall_iii:bS}}) +// EMSCRIPTEN_END_ASM +({ "Math": Math, "Int8Array": Int8Array, "Int16Array": Int16Array, "Int32Array": Int32Array, "Uint8Array": Uint8Array, "Uint16Array": Uint16Array, "Uint32Array": Uint32Array, "Float32Array": Float32Array, "Float64Array": Float64Array }, { "abort": abort, "assert": assert, "asmPrintInt": asmPrintInt, "asmPrintFloat": asmPrintFloat, "min": Math_min, "invoke_ii": invoke_ii, "invoke_vi": invoke_vi, "invoke_vii": invoke_vii, "invoke_iiii": invoke_iiii, "invoke_v": invoke_v, "invoke_iii": invoke_iii, "_llvm_lifetime_end": _llvm_lifetime_end, "_lseek": _lseek, "_sysconf": _sysconf, "_abort": _abort, "_close": _close, "_pread": _pread, "_open": _open, "___setErrNo": ___setErrNo, "_send": _send, "_write": _write, "_read": _read, "_recv": _recv, "_pwrite": _pwrite, "_sbrk": _sbrk, "_strerror_r": _strerror_r, "___errno_location": ___errno_location, "_strerror": _strerror, "_llvm_lifetime_start": _llvm_lifetime_start, "_llvm_bswap_i32": _llvm_bswap_i32, "_time": _time, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "NaN": NaN, "Infinity": Infinity }, buffer); +var _gzwrite = Module["_gzwrite"] = asm["_gzwrite"]; +var _strlen = Module["_strlen"] = asm["_strlen"]; +var _strcat = Module["_strcat"] = asm["_strcat"]; +var _free = Module["_free"] = asm["_free"]; +var _gzread = Module["_gzread"] = asm["_gzread"]; +var _gzopen = Module["_gzopen"] = asm["_gzopen"]; +var _memset = Module["_memset"] = asm["_memset"]; +var _malloc = Module["_malloc"] = asm["_malloc"]; +var _memcpy = Module["_memcpy"] = asm["_memcpy"]; +var _gzclose = Module["_gzclose"] = asm["_gzclose"]; +var _strcpy = Module["_strcpy"] = asm["_strcpy"]; +var runPostSets = Module["runPostSets"] = asm["runPostSets"]; +var dynCall_ii = Module["dynCall_ii"] = asm["dynCall_ii"]; +var dynCall_vi = Module["dynCall_vi"] = asm["dynCall_vi"]; +var dynCall_vii = Module["dynCall_vii"] = asm["dynCall_vii"]; +var dynCall_iiii = Module["dynCall_iiii"] = asm["dynCall_iiii"]; +var dynCall_v = Module["dynCall_v"] = asm["dynCall_v"]; +var dynCall_iii = Module["dynCall_iii"] = asm["dynCall_iii"]; +Runtime.stackAlloc = function(size) { return asm['stackAlloc'](size) }; +Runtime.stackSave = function() { return asm['stackSave']() }; +Runtime.stackRestore = function(top) { asm['stackRestore'](top) }; +// Warning: printing of i64 values may be slightly rounded! No deep i64 math used, so precise i64 code not included +var i64Math = null; +// === Auto-generated postamble setup entry stuff === +Module['callMain'] = function callMain(args) { + assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)'); + assert(!Module['preRun'] || Module['preRun'].length == 0, 'cannot call main when preRun functions remain to be called'); + args = args || []; + ensureInitRuntime(); + var argc = args.length+1; + function pad() { + for (var i = 0; i < 4-1; i++) { + argv.push(0); + } + } + var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL) ]; + pad(); + for (var i = 0; i < argc-1; i = i + 1) { + argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL)); + pad(); + } + argv.push(0); + argv = allocate(argv, 'i32', ALLOC_NORMAL); + var ret; + var initialStackTop = STACKTOP; + try { + ret = Module['_main'](argc, argv, 0); + } + catch(e) { + if (e.name == 'ExitStatus') { + return e.status; + } else if (e == 'SimulateInfiniteLoop') { + Module['noExitRuntime'] = true; + } else { + throw e; + } + } finally { + STACKTOP = initialStackTop; + } + return ret; +} +function run(args) { + args = args || Module['arguments']; + if (runDependencies > 0) { + Module.printErr('run() called, but dependencies remain, so not running'); + return 0; + } + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + var toRun = Module['preRun']; + Module['preRun'] = []; + for (var i = toRun.length-1; i >= 0; i--) { + toRun[i](); + } + if (runDependencies > 0) { + // a preRun added a dependency, run will be called later + return 0; + } + } + function doRun() { + ensureInitRuntime(); + preMain(); + var ret = 0; + calledRun = true; + if (Module['_main'] && shouldRunNow) { + ret = Module['callMain'](args); + if (!Module['noExitRuntime']) { + exitRuntime(); + } + } + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length > 0) { + Module['postRun'].pop()(); + } + } + return ret; + } + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + if (!ABORT) doRun(); + }, 1); + return 0; + } else { + return doRun(); + } +} +Module['run'] = Module.run = run; +// {{PRE_RUN_ADDITIONS}} +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} +// shouldRunNow refers to calling main(), not run(). +var shouldRunNow = true; +if (Module['noInitialRun']) { + shouldRunNow = false; +} +run(); +// {{POST_RUN_ADDITIONS}} + // {{MODULE_ADDITIONS}} +Module['gzcompress'] = function(data) { // TODO: Accept strings + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['output.gz', 'wb']); + var buffer = _malloc(data.length); + HEAPU8.set(data, buffer); + ccall('gzwrite', 'number', ['number', 'number', 'number'], [gzFile, buffer, data.length]); + ccall('gzclose', 'number', ['number'], [gzFile]); + _free(buffer); + var ret = new Uint8Array(FS.root.contents['output.gz'].contents); + FS.deleteFile('output.gz'); + return ret; +}; +Module['gzdecompress'] = function(data) { + var BUFSIZE = 1024*1024; + FS.createDataFile('/', 'input.gz', data, true, true); + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['input.gz', 'rb']); + var buffer = _malloc(BUFSIZE); + var chunks = []; + var total = 0; + var len; + while( (len = ccall('gzread', 'number', ['number', 'number', 'number'], [gzFile, buffer, BUFSIZE])) > 0) { + chunks.push(new Uint8Array(len)); + chunks[chunks.length-1].set(HEAPU8.subarray(buffer, buffer+len)); + total += len; + } + ccall('gzclose', 'number', ['number'], [gzFile]); + FS.deleteFile('input.gz'); + _free(buffer); + var ret = new Uint8Array(total); + var curr = 0; + for (var i = 0; i < chunks.length; i++) { + ret.set(chunks[i], curr); + curr += chunks[i].length; + } + return ret; +}; + + return { + compress: Module['gzcompress'], + decompress: Module['gzdecompress'] + }; +})(); + diff --git a/astroem/zee.js/zlib.3 b/astroem/zee.js/zlib.3 new file mode 100644 index 00000000..27adc4cd --- /dev/null +++ b/astroem/zee.js/zlib.3 @@ -0,0 +1,151 @@ +.TH ZLIB 3 "19 Apr 2010" +.SH NAME +zlib \- compression/decompression library +.SH SYNOPSIS +[see +.I zlib.h +for full description] +.SH DESCRIPTION +The +.I zlib +library is a general purpose data compression library. +The code is thread safe, assuming that the standard library functions +used are thread safe, such as memory allocation routines. +It provides in-memory compression and decompression functions, +including integrity checks of the uncompressed data. +This version of the library supports only one compression method (deflation) +but other algorithms may be added later +with the same stream interface. +.LP +Compression can be done in a single step if the buffers are large enough +or can be done by repeated calls of the compression function. +In the latter case, +the application must provide more input and/or consume the output +(providing more output space) before each call. +.LP +The library also supports reading and writing files in +.IR gzip (1) +(.gz) format +with an interface similar to that of stdio. +.LP +The library does not install any signal handler. +The decoder checks the consistency of the compressed data, +so the library should never crash even in the case of corrupted input. +.LP +All functions of the compression library are documented in the file +.IR zlib.h . +The distribution source includes examples of use of the library +in the files +.I example.c +and +.IR minigzip.c, +as well as other examples in the +.IR examples/ +directory. +.LP +Changes to this version are documented in the file +.I ChangeLog +that accompanies the source. +.LP +.I zlib +is available in Java using the java.util.zip package: +.IP +http://java.sun.com/developer/technicalArticles/Programming/compression/ +.LP +A Perl interface to +.IR zlib , +written by Paul Marquess (pmqs@cpan.org), +is available at CPAN (Comprehensive Perl Archive Network) sites, +including: +.IP +http://search.cpan.org/~pmqs/IO-Compress-Zlib/ +.LP +A Python interface to +.IR zlib , +written by A.M. Kuchling (amk@magnet.com), +is available in Python 1.5 and later versions: +.IP +http://www.python.org/doc/lib/module-zlib.html +.LP +.I zlib +is built into +.IR tcl: +.IP +http://wiki.tcl.tk/4610 +.LP +An experimental package to read and write files in .zip format, +written on top of +.I zlib +by Gilles Vollant (info@winimage.com), +is available at: +.IP +http://www.winimage.com/zLibDll/minizip.html +and also in the +.I contrib/minizip +directory of the main +.I zlib +source distribution. +.SH "SEE ALSO" +The +.I zlib +web site can be found at: +.IP +http://zlib.net/ +.LP +The data format used by the zlib library is described by RFC +(Request for Comments) 1950 to 1952 in the files: +.IP +http://www.ietf.org/rfc/rfc1950.txt (for the zlib header and trailer format) +.br +http://www.ietf.org/rfc/rfc1951.txt (for the deflate compressed data format) +.br +http://www.ietf.org/rfc/rfc1952.txt (for the gzip header and trailer format) +.LP +Mark Nelson wrote an article about +.I zlib +for the Jan. 1997 issue of Dr. Dobb's Journal; +a copy of the article is available at: +.IP +http://marknelson.us/1997/01/01/zlib-engine/ +.SH "REPORTING PROBLEMS" +Before reporting a problem, +please check the +.I zlib +web site to verify that you have the latest version of +.IR zlib ; +otherwise, +obtain the latest version and see if the problem still exists. +Please read the +.I zlib +FAQ at: +.IP +http://zlib.net/zlib_faq.html +.LP +before asking for help. +Send questions and/or comments to zlib@gzip.org, +or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). +.SH AUTHORS +Version 1.2.5 +Copyright (C) 1995-2010 Jean-loup Gailly (jloup@gzip.org) +and Mark Adler (madler@alumni.caltech.edu). +.LP +This software is provided "as-is," +without any express or implied warranty. +In no event will the authors be held liable for any damages +arising from the use of this software. +See the distribution directory with respect to requirements +governing redistribution. +The deflate format used by +.I zlib +was defined by Phil Katz. +The deflate and +.I zlib +specifications were written by L. Peter Deutsch. +Thanks to all the people who reported problems and suggested various +improvements in +.IR zlib ; +who are too numerous to cite here. +.LP +UNIX manual page by R. P. C. Rodgers, +U.S. National Library of Medicine (rodgers@nlm.nih.gov). +.\" end of man page diff --git a/astroem/zee.js/zlib.h b/astroem/zee.js/zlib.h new file mode 100644 index 00000000..bfbba83e --- /dev/null +++ b/astroem/zee.js/zlib.h @@ -0,0 +1,1613 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.5" +#define ZLIB_VERNUM 0x1250 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is never required, but can be + used to inform inflate that a faster approach may be used for the single + inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK or Z_TREES is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been + found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the + success case, the application may save the current current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef voidp gzFile; /* opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) Also "a" + can be used instead of "w" to request that the gzip stream that will be + written be appended to the file. "+" will result in an error, since reading + and writing to the same gzip file is not supported. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file was not in gzip format, gzread copies the given number of + bytes into the buffer. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream, or failing that, reading the rest + of the input file directly without decompression. The entire input file + will be read if gzread is called until it returns less than the requested + len. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. This state can change from + false to true while reading the input file if the end of a gzip stream is + reached, but is followed by data that is not another gzip stream. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# ifdef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/astroem/zee.js/zlib.map b/astroem/zee.js/zlib.map new file mode 100644 index 00000000..f282d362 --- /dev/null +++ b/astroem/zee.js/zlib.map @@ -0,0 +1,68 @@ +ZLIB_1.2.0 { + global: + compressBound; + deflateBound; + inflateBack; + inflateBackEnd; + inflateBackInit_; + inflateCopy; + local: + deflate_copyright; + inflate_copyright; + inflate_fast; + inflate_table; + zcalloc; + zcfree; + z_errmsg; + gz_error; + gz_intmax; + _*; +}; + +ZLIB_1.2.0.2 { + gzclearerr; + gzungetc; + zlibCompileFlags; +} ZLIB_1.2.0; + +ZLIB_1.2.0.8 { + deflatePrime; +} ZLIB_1.2.0.2; + +ZLIB_1.2.2 { + adler32_combine; + crc32_combine; + deflateSetHeader; + inflateGetHeader; +} ZLIB_1.2.0.8; + +ZLIB_1.2.2.3 { + deflateTune; + gzdirect; +} ZLIB_1.2.2; + +ZLIB_1.2.2.4 { + inflatePrime; +} ZLIB_1.2.2.3; + +ZLIB_1.2.3.3 { + adler32_combine64; + crc32_combine64; + gzopen64; + gzseek64; + gztell64; + inflateUndermine; +} ZLIB_1.2.2.4; + +ZLIB_1.2.3.4 { + inflateReset2; + inflateMark; +} ZLIB_1.2.3.3; + +ZLIB_1.2.3.5 { + gzbuffer; + gzoffset; + gzoffset64; + gzclose_r; + gzclose_w; +} ZLIB_1.2.3.4; diff --git a/astroem/zee.js/zlib.pc b/astroem/zee.js/zlib.pc new file mode 100644 index 00000000..e89d853d --- /dev/null +++ b/astroem/zee.js/zlib.pc @@ -0,0 +1,13 @@ +prefix=/usr/local +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +sharedlibdir=${libdir} +includedir=${prefix}/include + +Name: zlib +Description: zlib compression library +Version: 1.2.5 + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: -I${includedir} diff --git a/astroem/zee.js/zlib.pc.in b/astroem/zee.js/zlib.pc.in new file mode 100644 index 00000000..7e5acf9c --- /dev/null +++ b/astroem/zee.js/zlib.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +sharedlibdir=@sharedlibdir@ +includedir=@includedir@ + +Name: zlib +Description: zlib compression library +Version: @VERSION@ + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: -I${includedir} diff --git a/astroem/zee.js/zutil.c b/astroem/zee.js/zutil.c new file mode 100644 index 00000000..898ed345 --- /dev/null +++ b/astroem/zee.js/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/astroem/zee.js/zutil.h b/astroem/zee.js/zutil.h new file mode 100644 index 00000000..258fa887 --- /dev/null +++ b/astroem/zee.js/zutil.h @@ -0,0 +1,274 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#ifdef STDC +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); +void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/astroem/zpxpos.c b/astroem/zpxpos.c new file mode 100644 index 00000000..a6f7168c --- /dev/null +++ b/astroem/zpxpos.c @@ -0,0 +1,735 @@ +/*** File wcslib/zpxpos.c + *** October 31, 2012 + *** By Frank Valdes, valdes@noao.edu + *** Modified from tnxpos.c by Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** After IRAF mwcs/wfzpx.x + *** Copyright (C) 1998-2012 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + */ + +#include +#include +#include +#include +#include "wcs.h" + +#define TOL 1e-13 +#define SPHTOL 0.00001 +#define BADCVAL 0.0 +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + +/* wfzpx -- wcs function driver for the zenithal / azimuthal polynomial. + * zpxinit (header, wcs) + * zpxclose (wcs) + * zpxfwd (xpix, ypix, wcs, xpos, ypos) Pixels to WCS + * zpxrev (xpos, ypos, wcs, xpix, ypix) WCS to pixels + */ + +#define max_niter 500 +#define SZ_ATSTRING 2000 +static void wf_gsclose(); + +/* zpxinit -- initialize the zenithal/azimuthal polynomial forward or + * inverse transform. initialization for this transformation consists of, + * determining which axis is ra / lon and which is dec / lat, computing the + * celestial longitude and colatitude of the native pole, reading in the the + * native longitude of the pole of the celestial coordinate system longpole + * from the attribute list, precomputing the euler angles and various + * intermediary functions of the reference coordinates, reading in the + * projection parameter ro from the attribute list, reading in up to ten + * polynomial coefficients, and, for polynomial orders greater than 2 computing + * the colatitude and radius of the first point of inflection. if longpole is + * undefined then a value of 180.0 degrees is assumed. if ro is undefined a + * value of 180.0 / pi is assumed. if the polynomial coefficients are all zero + * then an error condition is posted. if the order of the polynomial is 2 or + * greater and there is no point of inflection an error condition is posted. + * the zpx projection with an order of 1 and 0th and 1st coefficients of 0.0 + * and 1.0 respectively is equivalent to the arc projtection. in order to + * determine the axis order, the parameter "axtype={ra|dec} {xlon|xlat}" must + * have been set in the attribute list for the function. the longpole and ro + * parameters may be set in either or both of the axes attribute lists, but the + * value in the ra axis attribute list takes precedence. + */ + +int +zpxinit (header, wcs) + +const char *header; /* FITS header */ +struct WorldCoor *wcs; /* pointer to WCS structure */ +{ + int i, j; + struct IRAFsurface *wf_gsopen(); + char key[8], *str1, *str2, *lngstr, *latstr, *header1; + double zd1, d1, zd2,d2, zd, d, r; + extern void wcsrotset(); + + /* allocate space for the attribute strings */ + str1 = malloc (SZ_ATSTRING); + str2 = malloc (SZ_ATSTRING); + if (!hgetm (header, "WAT1", SZ_ATSTRING, str1)) { + /* this is a kludge to handle NOAO archived data where the first + * WAT cards are in the primary header and this code does not + * implement the inheritance convention. since zpx is largely an + * NOAO system and it doesn't make sense for WAT1 to be missing if + * ctype is ZPX, this block is only triggered with this kludge. + * there had to be a few changes to defeat the caching of the + * index of the header string so that the added cards are also + * found. + */ + + header1 = malloc (strlen(header)+200); + strcpy (header1, "WAT1_001= 'wtype=zpx axtype=ra projp0=0. projp1=1. projp2=0. projp3=337.74 proj'WAT2_001= 'wtype=zpx axtype=dec projp0=0. projp1=1. projp2=0. projp3=337.74 pro'"); + strcat (header1, header); + hgetm (header1, "WAT1", SZ_ATSTRING, str1); + hgetm (header1, "WAT2", SZ_ATSTRING, str2); + free (header1); + } + hgetm (header, "WAT2", SZ_ATSTRING, str2); + + lngstr = malloc (SZ_ATSTRING); + latstr = malloc (SZ_ATSTRING); + + /* determine the native longitude of the pole of the celestial + coordinate system corresponding to the FITS keyword longpole. + this number has no default and should normally be set to 180 + degrees. search both axes for this quantity. */ + + if (wcs->longpole > 360.0) { + if (!igetr8 (str1, "longpole", &wcs->longpole)) { + if (!igetr8 (str2, "longpole", &wcs->longpole)) + wcs->longpole = 180.0; + } + } + + /* Fetch the ro projection parameter which is the radius of the + generating sphere for the projection. if ro is absent which + is the usual case set it to 180 / pi. search both axes for + this quantity. */ + + if (!igetr8 (str1, "ro", &wcs->rodeg)) { + if (!igetr8 (str2, "ro", &wcs->rodeg)) + wcs->rodeg = 180.0 / PI; + } + + /* Fetch the zenithal polynomial coefficients. */ + for (i = 0; i < 10; i++) { + sprintf (key,"projp%d",i); + if (!igetr8 (str1, key, &wcs->prj.p[i])) + wcs->prj.p[i] = 0.0; + } + + /* Fetch the longitude correction surface. note that the attribute + string may be of any length so the length of atvalue may have + to be adjusted. */ + + if (!igets (str1, "lngcor", SZ_ATSTRING, lngstr)) { + if (!igets (str2, "lngcor", SZ_ATSTRING, lngstr)) + wcs->lngcor = NULL; + else + wcs->lngcor = wf_gsopen (lngstr); + } + else + wcs->lngcor = wf_gsopen (lngstr); + + /* Fetch the latitude correction surface. note that the attribute + string may be of any length so the length of atvalue may have + to be adjusted. */ + + if (!igets (str2, "latcor", SZ_ATSTRING, latstr)) { + if (!igets (str1, "latcor", SZ_ATSTRING, latstr)) + wcs->latcor = NULL; + else + wcs->latcor = wf_gsopen (latstr); + } + else + wcs->latcor = wf_gsopen (latstr); + + /* Determine the number of ZP coefficients */ + for (i = 9; i >= 0 && wcs->prj.p[i] == 0.; i--); + wcs->zpnp = i; + + if (i >= 3) { + /* Find the point of inflection closest to the pole. */ + zd1 = 0.; + d1 = wcs->prj.p[1]; + + /* Find the point where the derivative first goes negative. */ + for (i = 1; i<= 180; i++) { + zd2 = PI * i / 180.0; + d2 = 0.; + for (j = wcs->zpnp; j >= 1; j--) { + d2 = d2 * zd2 + j * wcs->prj.p[j]; + } + if (d2 <= 0.) + break; + zd1 = zd2; + d1 = d2; + } + + /* Find where the derivative is 0. */ + if (d2 <= 0.0) { + for (i = 1; i <= 10; i++) { + zd = zd1 - d1 * (zd2 - zd1) / (d2 - d1); + d = 0.; + for (j = wcs->zpnp; j >= 1; j--) { + d = d * zd + j * wcs->prj.p[j]; + } + if (fabs(d) < TOL) + break; + if (d < 0.) { + zd2 = zd; + d2 = d; + } + else { + zd1 = zd; + d1 = d; + } + } + } + + /* No negative derivative. */ + else + zd = PI; + + r = 0.; + for (j = wcs->zpnp; j >= 0; j--) + r = r * zd + wcs->prj.p[j]; + wcs->zpzd = zd; + wcs->zpr = r; + } + + /* Compute image rotation */ + wcsrotset (wcs); + + /* free working space. */ + free (str1); + free (str2); + free (lngstr); + free (latstr); + + /* Return 1 if there are no correction coefficients */ + if (wcs->latcor == NULL && wcs->lngcor == NULL) + return (1); + else + return (0); +} + + +/* zpxpos -- forward transform (physical to world) gnomonic projection. */ + +int +zpxpos (xpix, ypix, wcs, xpos, ypos) + +double xpix, ypix; /*i physical coordinates (x, y) */ +struct WorldCoor *wcs; /*i pointer to WCS descriptor */ +double *xpos, *ypos; /*o world coordinates (ra, dec) */ +{ + int i, j, k, ira, idec; + double x, y, r, phi, theta, costhe, sinthe, dphi, cosphi, sinphi, dlng, z; + double colatp, coslatp, sinlatp, longp; + double xs, ys, ra, dec, xp, yp; + double a, b, c, d, zd, zd1, zd2, r1, r2, rt, lambda; + double wf_gseval(); + + /* Convert from pixels to image coordinates */ + xpix = xpix - wcs->crpix[0]; + ypix = ypix - wcs->crpix[1]; + + /* Scale and rotate using CD matrix */ + if (wcs->rotmat) { + x = xpix * wcs->cd[0] + ypix * wcs->cd[1]; + y = xpix * wcs->cd[2] + ypix * wcs->cd[3]; + } + + else { + + /* Check axis increments - bail out if either 0 */ + if (wcs->cdelt[0] == 0.0 || wcs->cdelt[1] == 0.0) { + *xpos = 0.0; + *ypos = 0.0; + return 2; + } + + /* Scale using CDELT */ + xs = xpix * wcs->cdelt[0]; + ys = ypix * wcs->cdelt[1]; + + /* Take out rotation from CROTA */ + if (wcs->rot != 0.0) { + double cosr = cos (degrad (wcs->rot)); + double sinr = sin (degrad (wcs->rot)); + x = xs * cosr - ys * sinr; + y = xs * sinr + ys * cosr; + } + else { + x = xs; + y = ys; + } + } + + /* Get the axis numbers */ + if (wcs->coorflip) { + ira = 1; + idec = 0; + } + else { + ira = 0; + idec = 1; + } + colatp = degrad (90.0 - wcs->crval[idec]); + coslatp = cos(colatp); + sinlatp = sin(colatp); + longp = degrad(wcs->longpole); + + /* Compute native spherical coordinates phi and theta in degrees from the + projected coordinates. this is the projection part of the computation */ + k = wcs->zpnp; + if (wcs->lngcor != NULL) + xp = x + wf_gseval (wcs->lngcor, x, y); + else + xp = x; + if (wcs->latcor != NULL) + yp = y + wf_gseval (wcs->latcor, x, y); + else + yp = y; + x = xp; + y = yp; + r = sqrt (x * x + y * y) / wcs->rodeg; + + /* Solve */ + + /* Constant no solution */ + if (k < 1) { + *xpos = BADCVAL; + *ypos = BADCVAL; + return (1); + } + + /* Linear */ + else if (k == 1) { + zd = (r - wcs->prj.p[0]) / wcs->prj.p[1]; + } + + /* Quadratic */ + else if (k == 2) { + + a = wcs->prj.p[2]; + b = wcs->prj.p[1]; + c = wcs->prj.p[0] - r; + d = b * b - 4. * a * c; + if (d < 0.) { + *xpos = BADCVAL; + *ypos = BADCVAL; + return (1); + } + d = sqrt (d); + + /* Choose solution closest to the pole */ + zd1 = (-b + d) / (2. * a); + zd2 = (-b - d) / (2. * a); + if (zd1 < zd2) + zd = zd1; + else + zd = zd2; + if (zd < -TOL) { + if (zd1 > zd2) + zd = zd1; + else + zd = zd2; + } + if (zd < 0.) { + if (zd < -TOL) { + *xpos = BADCVAL; + *ypos = BADCVAL; + return (1); + } + zd = 0.; + } + else if (zd > PI) { + if (zd > (PI + TOL)) { + *xpos = BADCVAL; + *ypos = BADCVAL; + return (1); + } + zd = PI; + } + } + + /* Higher order solve iteratively */ + else { + + zd1 = 0.; + r1 = wcs->prj.p[0]; + zd2 = wcs->zpzd; + r2 = wcs->zpr; + + if (r < r1) { + if (r < (r1 - TOL)) { + *xpos = BADCVAL; + *ypos = BADCVAL; + return (1); + } + zd = zd1; + } + else if (r > r2) { + if (r > (r2 + TOL)) { + *xpos = BADCVAL; + *ypos = BADCVAL; + return (1); + } + zd = zd2; + } + else { + for (j=0; j<100; j++) { + lambda = (r2 - r) / (r2 - r1); + if (lambda < 0.1) + lambda = 0.1; + else if (lambda > 0.9) + lambda = 0.9; + zd = zd2 - lambda * (zd2 - zd1); + rt = 0.; + for (i=k; i>=0; i--) + rt = (rt * zd) + wcs->prj.p[i]; + if (rt < r) { + if ((r - rt) < TOL) + break; + r1 = rt; + zd1 = zd; + } + else { + if ((rt - r) < TOL) + break; + r2 = rt; + zd2 = zd; + } + lambda = zd2 - zd1; + lambda = fabs (zd2 - zd1); + if (fabs (zd2 - zd1) < TOL) + break; + } + } + } + + /* Compute phi */ + if (r == 0.0) + phi = 0.0; + else + phi = atan2 (x, -y); + + /* Compute theta */ + theta = PI / 2 - zd; + + /* Compute the celestial coordinates ra and dec from the native + coordinates phi and theta. this is the spherical geometry part + of the computation */ + + costhe = cos (theta); + sinthe = sin (theta); + dphi = phi - longp; + cosphi = cos (dphi); + sinphi = sin (dphi); + + /* Compute the ra */ + x = sinthe * sinlatp - costhe * coslatp * cosphi; + if (fabs (x) < SPHTOL) + x = -cos (theta + colatp) + costhe * coslatp * (1.0 - cosphi); + y = -costhe * sinphi; + if (x != 0.0 || y != 0.0) + dlng = atan2 (y, x); + else + dlng = dphi + PI ; + ra = wcs->crval[ira] + raddeg(dlng); + + /* normalize ra */ + if (wcs->crval[ira] >= 0.0) { + if (ra < 0.0) + ra = ra + 360.0; + } + else { + if (ra > 0.0) + ra = ra - 360.0; + } + if (ra > 360.0) + ra = ra - 360.0; + else if (ra < -360.0) + ra = ra + 360.0; + + /* compute the dec */ + if (fmod (dphi, PI) == 0.0) { + dec = raddeg(theta + cosphi * colatp); + if (dec > 90.0) + dec = 180.0 - dec; + if (dec < -90.0) + dec = -180.0 - dec; + } + else { + z = sinthe * coslatp + costhe * sinlatp * cosphi; + if (fabs(z) > 0.99) { + if (z >= 0.0) + dec = raddeg(acos (sqrt(x * x + y * y))); + else + dec = raddeg(-acos (sqrt(x * x + y * y))); + } + else + dec = raddeg(asin (z)); + } + + /* store the results */ + *xpos = ra; + *ypos = dec; + return (0); +} + + +/* zpxpix -- inverse transform (world to physical) for the zenithal + * azimuthal polynomial projection. + */ + +int +zpxpix (xpos, ypos, wcs, xpix, ypix) + +double xpos, ypos; /*i world coordinates (ra, dec) */ +struct WorldCoor *wcs; /*i pointer to WCS descriptor */ +double *xpix, *ypix; /*o physical coordinates (x, y) */ +{ + int i, ira, idec, niter; + double ra, dec, cosdec, sindec, cosra, sinra, x, y, phi, theta; + double s, r, dphi, z, dpi, dhalfpi, twopi, tx; + double xm, ym, f, fx, fy, g, gx, gy, denom, dx, dy; + double colatp, coslatp, sinlatp, longp, sphtol; + double wf_gseval(), wf_gsder(); + + /* get the axis numbers */ + if (wcs->coorflip) { + ira = 1; + idec = 0; + } + else { + ira = 0; + idec = 1; + } + + /* Compute the transformation from celestial coordinates ra and + dec to native coordinates phi and theta. this is the spherical + geometry part of the transformation */ + + ra = degrad (xpos - wcs->crval[ira]); + dec = degrad (ypos); + cosra = cos (ra); + sinra = sin (ra); + cosdec = cos (dec); + sindec = sin (dec); + colatp = degrad (90.0 - wcs->crval[idec]); + coslatp = cos (colatp); + sinlatp = sin (colatp); + if (wcs->longpole == 999.0) + longp = degrad (180.0); + else + longp = degrad(wcs->longpole); + dpi = PI; + dhalfpi = dpi * 0.5; + twopi = PI + PI; + sphtol = SPHTOL; + + /* Compute phi */ + x = sindec * sinlatp - cosdec * coslatp * cosra; + if (fabs(x) < sphtol) + x = -cos (dec + colatp) + cosdec * coslatp * (1.0 - cosra); + y = -cosdec * sinra; + if (x != 0.0 || y != 0.0) + dphi = atan2 (y, x); + else + dphi = ra - dpi; + phi = longp + dphi; + if (phi > dpi) + phi = phi - twopi; + else if (phi < -dpi) + phi = phi + twopi; + + /* Compute theta */ + if (fmod (ra, dpi) == 0.0) { + theta = dec + cosra * colatp; + if (theta > dhalfpi) + theta = dpi - theta; + if (theta < -dhalfpi) + theta = -dpi - theta; + } + else { + z = sindec * coslatp + cosdec * sinlatp * cosra; + if (fabs (z) > 0.99) { + if (z >= 0.0) + theta = acos (sqrt(x * x + y * y)); + else + theta = -acos (sqrt(x * x + y * y)); + } + else + theta = asin (z); + } + + /* Compute the transformation from native coordinates phi and theta + to projected coordinates x and y */ + + s = dhalfpi - theta; + r = 0.; + for (i=9; i>=0; i--) + r = r * s + wcs->prj.p[i]; + r = wcs->rodeg * r; + + if (wcs->lngcor == NULL && wcs->latcor == NULL) { + if (wcs->coorflip) { + y = r * sin (phi); + x = -r * cos (phi); + } else { + x = r * sin (phi); + y = -r * cos (phi); + } + } else { + xm = r * sin (phi); + ym = -r * cos (phi); + x = xm; + y = ym; + niter = 0; + while (niter < max_niter) { + if (wcs->lngcor != NULL) { + f = x + wf_gseval (wcs->lngcor, x, y) - xm; + fx = wf_gsder (wcs->lngcor, x, y, 1, 0); + fx = 1.0 + fx; + fy = wf_gsder (wcs->lngcor, x, y, 0, 1); + } + else { + f = x - xm; + fx = 1.0 ; + fy = 0.0; + } + if (wcs->latcor != NULL) { + g = y + wf_gseval (wcs->latcor, x, y) - ym; + gx = wf_gsder (wcs->latcor, x, y, 1, 0); + gy = wf_gsder (wcs->latcor, x, y, 0, 1); + gy = 1.0 + gy; + } + else { + g = y - ym; + gx = 0.0 ; + gy = 1.0; + } + + denom = fx * gy - fy * gx; + if (denom == 0.0) + break; + dx = (-f * gy + g * fy) / denom; + dy = (-g * fx + f * gx) / denom; + x = x + dx; + y = y + dy; + if (MAX(MAX(fabs(dx),fabs(dy)),MAX(fabs(f),fabs(g))) < 2.80e-8) + break; + + niter = niter + 1; + } + + /* Reverse x and y if axes flipped */ + if (wcs->coorflip) { + tx = x; + x = y; + y = tx; + } + } + + /* Scale and rotate using CD matrix */ + if (wcs->rotmat) { + *xpix = x * wcs->dc[0] + y * wcs->dc[1]; + *ypix = x * wcs->dc[2] + y * wcs->dc[3]; + } + + else { + + /* Correct for rotation */ + if (wcs->rot!=0.0) { + double cosr = cos (degrad (wcs->rot)); + double sinr = sin (degrad (wcs->rot)); + *xpix = x * cosr + y * sinr; + *ypix = y * cosr - x * sinr; + } + else { + *xpix = x; + *ypix = y; + } + + /* Scale using CDELT */ + if (wcs->xinc != 0.) + *xpix = *xpix / wcs->xinc; + if (wcs->yinc != 0.) + *ypix = *ypix / wcs->yinc; + } + + /* Convert to pixels */ + *xpix = *xpix + wcs->xrefpix; + *ypix = *ypix + wcs->yrefpix; + + return (0); +} + + +/* ZPXCLOSE -- free up the distortion surface pointers */ + +void +zpxclose (wcs) + +struct WorldCoor *wcs; /* pointer to the WCS descriptor */ + +{ + if (wcs->lngcor != NULL) + wf_gsclose (wcs->lngcor); + if (wcs->latcor != NULL) + wf_gsclose (wcs->latcor); + return; +} + + +/* wf_gsclose -- procedure to free the surface descriptor */ + +static void +wf_gsclose (sf) + +struct IRAFsurface *sf; /* the surface descriptor */ + +{ + if (sf != NULL) { + if (sf->xbasis != NULL) + free (sf->xbasis); + if (sf->ybasis != NULL) + free (sf->ybasis); + if (sf->coeff != NULL) + free (sf->coeff); + free (sf); + } + return; +} + +/* + * Mar 8 2011 Created from tnxpos.c and wfzpx.x + * + * Oct 31 2012 End comment on line 346 after pole; fix code thereafter + */ diff --git a/compiler/COPYING b/compiler/COPYING new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/compiler/COPYING @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/compiler/README b/compiler/README new file mode 100644 index 00000000..270cfc27 --- /dev/null +++ b/compiler/README @@ -0,0 +1,292 @@ +/* + * Copyright 2009 The Closure Compiler Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// Contents +// + +The Closure Compiler performs checking, instrumentation, and +optimizations on JavaScript code. The purpose of this README is to +explain how to build and run the Closure Compiler. + +The Closure Compiler requires Java 6 or higher. +http://www.java.com/ + + +// +// Building The Closure Compiler +// + +There are three ways to get a Closure Compiler executable. + +1) Use one we built for you. + +Pre-built Closure binaries can be found at +http://code.google.com/p/closure-compiler/downloads/list + + +2) Check out the source and build it with Apache Ant. + +First, check out the full source tree of the Closure Compiler. There +are instructions on how to do this at the project site. +http://code.google.com/p/closure-compiler/source/checkout + +Apache Ant is a cross-platform build tool. +http://ant.apache.org/ + +At the root of the source tree, there is an Ant file named +build.xml. To use it, navigate to the same directory and type the +command + +ant jar + +This will produce a jar file called "build/compiler.jar". + + +3) Check out the source and build it with Eclipse. + +Eclipse is a cross-platform IDE. +http://www.eclipse.org/ + +Under Eclipse's File menu, click "New > Project ..." and create a +"Java Project." You will see an options screen. Give the project a +name, select "Create project from existing source," and choose the +root of the checked-out source tree as the existing directory. Verify +that you are using JRE version 6 or higher. + +Eclipse can use the build.xml file to discover rules. When you +navigate to the build.xml file, you will see all the build rules in +the "Outline" pane. Run the "jar" rule to build the compiler in +build/compiler.jar. + + +// +// Running The Closure Compiler +// + +Once you have the jar binary, running the Closure Compiler is straightforward. + +On the command line, type + +java -jar compiler.jar + +This starts the compiler in interactive mode. Type + +var x = 17 + 25; + +then hit "Enter", then hit "Ctrl-Z" (on Windows) or "Ctrl-D" (on Mac or Linux) +and "Enter" again. The Compiler will respond: + +var x=42; + +The Closure Compiler has many options for reading input from a file, +writing output to a file, checking your code, and running +optimizations. To learn more, type + +java -jar compiler.jar --help + +You can read more detailed documentation about the many flags at +http://code.google.com/closure/compiler/docs/gettingstarted_app.html + + +// +// Compiling Multiple Scripts +// + +If you have multiple scripts, you should compile them all together with +one compile command. + +java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js + +The Closure Compiler will concatenate the files in the order they're +passed at the command line. + +If you need to compile many, many scripts together, you may start to +run into problems with managing dependencies between scripts. You +should check out the Closure Library. It contains functions for +enforcing dependencies between scripts, and a tool called calcdeps.py +that knows how to give scripts to the Closure Compiler in the right +order. + +http://code.google.com/p/closure-library/ + +// +// Licensing +// + +Unless otherwise stated, all source files are licensed under +the Apache License, Version 2.0. + + +----- +Code under: +src/com/google/javascript/rhino +test/com/google/javascript/rhino + +URL: http://www.mozilla.org/rhino +Version: 1.5R3, with heavy modifications +License: Netscape Public License and MPL / GPL dual license + +Description: A partial copy of Mozilla Rhino. Mozilla Rhino is an +implementation of JavaScript for the JVM. The JavaScript parser and +the parse tree data structures were extracted and modified +significantly for use by Google's JavaScript compiler. + +Local Modifications: The packages have been renamespaced. All code not +relevant to parsing has been removed. A JsDoc parser and static typing +system have been added. + + +----- +Code in: +lib/rhino + +Rhino +URL: http://www.mozilla.org/rhino +Version: Trunk +License: Netscape Public License and MPL / GPL dual license + +Description: Mozilla Rhino is an implementation of JavaScript for the JVM. + +Local Modifications: Minor changes to parsing JSDoc that usually get pushed +up-stream to Rhino trunk. + + +----- +Code in: +lib/args4j.jar + +Args4j +URL: https://args4j.dev.java.net/ +Version: 2.0.16 +License: MIT + +Description: +args4j is a small Java class library that makes it easy to parse command line +options/arguments in your CUI application. + +Local Modifications: None. + + +----- +Code in: +lib/guava.jar + +Guava Libraries +URL: http://code.google.com/p/guava-libraries/ +Version: 13.0.1 +License: Apache License 2.0 + +Description: Google's core Java libraries. + +Local Modifications: None. + + +----- +Code in: +lib/jsr305.jar + +Annotations for software defect detection +URL: http://code.google.com/p/jsr-305/ +Version: svn revision 47 +License: BSD License + +Description: Annotations for software defect detection. + +Local Modifications: None. + + +----- +Code in: +lib/jarjar.jar + +Jar Jar Links +URL: http://jarjar.googlecode.com/ +Version: 1.1 +License: Apache License 2.0 + +Description: +A utility for repackaging Java libraries. + +Local Modifications: None. + + +---- +Code in: +lib/junit.jar + +JUnit +URL: http://sourceforge.net/projects/junit/ +Version: 4.10 +License: Common Public License 1.0 + +Description: A framework for writing and running automated tests in Java. + +Local Modifications: None. + + +--- +Code in: +lib/protobuf-java.jar + +Protocol Buffers +URL: http://code.google.com/p/protobuf/ +Version: 2.4.1 +License: New BSD License + +Description: Supporting libraries for protocol buffers, +an encoding of structured data. + +Local Modifications: None + + +--- +Code in: +lib/ant.jar +lib/ant-launcher.jar + +URL: http://ant.apache.org/bindownload.cgi +Version: 1.8.1 +License: Apache License 2.0 +Description: + Ant is a Java based build tool. In theory it is kind of like "make" + without make's wrinkles and with the full portability of pure java code. + +Local Modifications: None + + +--- +Code in: +lib/json.jar +URL: http://json.org/java/index.html +Version: JSON version 20090211 +License: MIT license +Description: +JSON is a set of java files for use in transmitting data in JSON format. + +Local Modifications: None + +--- +Code in: +tools/maven-ant-tasks-2.1.3.jar +URL: http://maven.apache.org +Version 2.1.3 +License: Apache License 2.0 +Description: + Maven Ant tasks are used to manage dependencies and to install/deploy to + maven repositories. + +Local Modifications: None diff --git a/compiler/compiler.jar b/compiler/compiler.jar new file mode 100644 index 00000000..53037b0e Binary files /dev/null and b/compiler/compiler.jar differ diff --git a/conf.h.in b/conf.h.in new file mode 100644 index 00000000..8bc87030 --- /dev/null +++ b/conf.h.in @@ -0,0 +1,63 @@ +/* Define as 1 if this compiler supports long long. */ +#undef HAVE_LONG_LONG + +/* Define as 1 if you have string.h */ +#undef HAVE_STRING_H + +/* Define as 1 if you have stdlib.h */ +#undef HAVE_STDLIB_H + +/* Define as 1 if you have malloc.h */ +#undef HAVE_MALLOC_H + +/* Define as 1 if you have limits.h */ +#undef HAVE_LIMITS_H + +/* Define as 1 if you have unistd.h */ +#undef HAVE_UNISTD_H + +/* Define as 1 if you have getopt.h */ +#undef HAVE_GETOPT_H + +/* Define as 1 if you have values.h */ +#undef HAVE_VALUES_H + +/* Define as 1 if you have dlfcn.h */ +#undef HAVE_DLFCN_H + +/* Define as 1 if you have sys/un.h */ +#undef HAVE_SYS_UN_H + +/* Define as 1 if you have sys/shm.h */ +#undef HAVE_SYS_SHM_H + +/* Define as 1 if you have sys/mman.h */ +#undef HAVE_SYS_MMAN_H + +/* Define as 1 if you have sys/ipc.h */ +#undef HAVE_SYS_IPC_H + +/* Define as 1 if you have socklen_t */ +#undef HAVE_SOCKLEN_T + +/* Define as 1 if you have strchr */ +#undef HAVE_STRCHR + +/* Define as 1 if you have memcpy */ +#undef HAVE_MEMCPY + +/* Define as 1 if you have snprintf */ +#undef HAVE_SNPRINTF + +/* Define as 1 if you have Tcl */ +#undef HAVE_TCL + +/* Define as 1 if you have Xt */ +#undef HAVE_XT + +/* Define as 1 if you are running Cygwin. */ +#undef HAVE_CYGWIN + +/* Define as 1 if you are running MinGW. */ +#undef HAVE_MINGW32 + diff --git a/config.guess b/config.guess new file mode 100644 index 00000000..b02565c7 --- /dev/null +++ b/config.guess @@ -0,0 +1,1517 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. + +timestamp='2011-06-03' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.sub b/config.sub new file mode 100644 index 00000000..59bb593f --- /dev/null +++ b/config.sub @@ -0,0 +1,1779 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-04-18' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 00000000..df715a58 --- /dev/null +++ b/configure @@ -0,0 +1,6291 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59 for js9 1.0. +# +# Report bugs to . +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='js9' +PACKAGE_TARNAME='js9' +PACKAGE_VERSION='1.0' +PACKAGE_STRING='js9 1.0' +PACKAGE_BUGREPORT='saord@cfa.harvard.edu' + +ac_unique_file="./tpos.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS WEBDIR HELPER USEHELPER build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT RANLIB ac_ct_RANLIB CPP EGREP CGIDIR CGIURL CGIXPATH FUNINC FUNLIB PNGLIB PNGINC EXTRA_LIBS SAODIR LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures js9 1.0 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of js9 1.0:";; + esac + cat <<\_ACEOF + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-webdir= web install directory e.g. /var/www/public_html/js9 + --with-helper= i.e. none, nodejs, get, or post + --with-cgidir= cgi install directory e.g. /var/www/public_html/cgi-bin + --with-cgiurl= cgi relative url e.g. ./cgi-bin + --with-cgixpath= directories to add to cgi path + --with-funtools= funtools directory e.g. /soft/funtools + --with-png= directory containing lib/libpng e.g. /usr/local + --with-saodir= top install directory e.g. /var/www/public_html + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +js9 configure 1.0 +generated by GNU Autoconf 2.59 + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by js9 $as_me 1.0, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + + +echo "$as_me:$LINENO: checking for web install directory" >&5 +echo $ECHO_N "checking for web install directory... $ECHO_C" >&6 + +# Check whether --with-webdir or --without-webdir was given. +if test "${with_webdir+set}" = set; then + withval="$with_webdir" + haveweb=1 +else + haveweb=0 +fi; +if test x"$haveweb" = x1 ; then + WEBDIR=$withval + echo "$as_me:$LINENO: result: yes ($WEBDIR)" >&5 +echo "${ECHO_T}yes ($WEBDIR)" >&6 +else + { { echo "$as_me:$LINENO: error: --with-webdir= is required to specify the Web install directory" >&5 +echo "$as_me: error: --with-webdir= is required to specify the Web install directory" >&2;} + { (exit 1); exit 1; }; } +fi + + +echo "$as_me:$LINENO: checking for server-side helper type" >&5 +echo $ECHO_N "checking for server-side helper type... $ECHO_C" >&6 + +# Check whether --with-helper or --without-helper was given. +if test "${with_helper+set}" = set; then + withval="$with_helper" + havebe=1 +else + havebe=0 +fi; +if test x"$havebe" = x1 ; then + HELPER=$withval + USEHELPER=yes + echo "$as_me:$LINENO: result: yes ($HELPER)" >&5 +echo "${ECHO_T}yes ($HELPER)" >&6 +else + HELPER=none + USEHELPER=no + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + + +# if no back-end, we don't need a compiler, etc. +if test x"$USEHELPER" = xyes ; then + + ac_config_headers="$ac_config_headers conf.h" + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Make sure we can run config.sub. +$ac_config_sub sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 +echo "$as_me: error: cannot run $ac_config_sub" >&2;} + { (exit 1); exit 1; }; } + +echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6 +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_build_alias=$build_alias +test -z "$ac_cv_build_alias" && + ac_cv_build_alias=`$ac_config_guess` +test -z "$ac_cv_build_alias" && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6 +build=$ac_cv_build +build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6 +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_host_alias=$host_alias +test -z "$ac_cv_host_alias" && + ac_cv_host_alias=$ac_cv_build_alias +ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6 +host=$ac_cv_host +host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +echo "$as_me:$LINENO: checking C compiler flags" >&5 +echo $ECHO_N "checking C compiler flags... $ECHO_C" >&6 +case $CC in + *icc* ) + CFLAGS="-axW $CFLAGS" + ;; +esac +echo "$as_me:$LINENO: result: OK" >&5 +echo "${ECHO_T}OK" >&6 + +# check for rflag +case $host_os in + *solaris*|*Solaris* ) + RFLAG="-R" + ;; + *linux*|*Linux* ) + RFLAG="-Wl,-R" + ;; + * ) + RFLAG="" + ;; +esac + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +echo "$as_me:$LINENO: checking for void *" >&5 +echo $ECHO_N "checking for void *... $ECHO_C" >&6 +if test "${ac_cv_type_void_p+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((void * *) 0) + return 0; +if (sizeof (void *)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_void_p=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_void_p=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_void_p" >&5 +echo "${ECHO_T}$ac_cv_type_void_p" >&6 + +echo "$as_me:$LINENO: checking size of void *" >&5 +echo $ECHO_N "checking size of void *... $ECHO_C" >&6 +if test "${ac_cv_sizeof_void_p+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_void_p" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (void *))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_void_p=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (void *), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (void *)); } +unsigned long ulongval () { return (long) (sizeof (void *)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (void *))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (void *)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (void *)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_void_p=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (void *), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_void_p=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p" >&5 +echo "${ECHO_T}$ac_cv_sizeof_void_p" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_VOID_P $ac_cv_sizeof_void_p +_ACEOF + + +case $ac_cv_sizeof_void_p in + 8) LSUFFIX="64";; +esac + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + + +for ac_header in malloc.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to saord@cfa.harvard.edu ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in getopt.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to saord@cfa.harvard.edu ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in pwd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to saord@cfa.harvard.edu ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to saord@cfa.harvard.edu ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in setjmp.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to saord@cfa.harvard.edu ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in values.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to saord@cfa.harvard.edu ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +echo "$as_me:$LINENO: checking for cgi install directory" >&5 +echo $ECHO_N "checking for cgi install directory... $ECHO_C" >&6 + +# Check whether --with-cgidir or --without-cgidir was given. +if test "${with_cgidir+set}" = set; then + withval="$with_cgidir" + havecgi=1 +else + havecgi=0 +fi; +if test x"$havecgi" = x1 ; then + CGIDIR=$withval + # make sure this directory is present + if test -d $CGIDIR; then + echo "$as_me:$LINENO: result: yes ($CGIDIR)" >&5 +echo "${ECHO_T}yes ($CGIDIR)" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + { { echo "$as_me:$LINENO: error: can't find cgi install dir: $CGIDIR" >&5 +echo "$as_me: error: can't find cgi install dir: $CGIDIR" >&2;} + { (exit 1); exit 1; }; } + fi +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + +echo "$as_me:$LINENO: checking for cgi url" >&5 +echo $ECHO_N "checking for cgi url... $ECHO_C" >&6 + +# Check whether --with-cgiurl or --without-cgiurl was given. +if test "${with_cgiurl+set}" = set; then + withval="$with_cgiurl" + havecgi=1 +else + havecgi=0 +fi; +if test x"$havecgi" = x1 ; then + CGIURL=$withval + echo "$as_me:$LINENO: result: yes ($CGIURL)" >&5 +echo "${ECHO_T}yes ($CGIURL)" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + +echo "$as_me:$LINENO: checking for extra directories for cgi path" >&5 +echo $ECHO_N "checking for extra directories for cgi path... $ECHO_C" >&6 + +# Check whether --with-cgixpath or --without-cgixpath was given. +if test "${with_cgixpath+set}" = set; then + withval="$with_cgixpath" + havecgi=1 +else + havecgi=0 +fi; +if test x"$havecgi" = x1 ; then + CGIXPATH=$withval + echo "$as_me:$LINENO: result: yes ($CGIXPATH)" >&5 +echo "${ECHO_T}yes ($CGIXPATH)" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + +# check for external funtools libraries +echo "$as_me:$LINENO: checking for funtools" >&5 +echo $ECHO_N "checking for funtools... $ECHO_C" >&6 + +# Check whether --with-funtools or --without-funtools was given. +if test "${with_funtools+set}" = set; then + withval="$with_funtools" + havelib=1 +else + havelib=0 +fi; +if test x"$havelib" = x1 ; then + FUNTOOLSBASE=$withval + # make sure essential libraries are present + if test -r $FUNTOOLSBASE/lib$LSUFFIX/libfuntools.a -o \ + -r $FUNTOOLSBASE/lib$LSUFFIX/libfuntools.so -o \ + -r $FUNTOOLSBASE/lib$LSUFFIX/libfuntools.dylib; then + FUNTOOLSLIB=$FUNTOOLSBASE/lib$LSUFFIX + FUNTOOLSINC=$FUNTOOLSBASE/include + echo "$as_me:$LINENO: result: yes ($FUNTOOLSBASE)" >&5 +echo "${ECHO_T}yes ($FUNTOOLSBASE)" >&6 + elif test -r $FUNTOOLSBASE/lib/libfuntools.a -o \ + -r $FUNTOOLSBASE/lib/libfuntools.so -o \ + -r $FUNTOOLSBASE/lib/libfuntools.dylib; then + FUNTOOLSLIB=$FUNTOOLSBASE/lib + FUNTOOLSINC=$FUNTOOLSBASE/include + echo "$as_me:$LINENO: result: yes ($FUNTOOLSBASE)" >&5 +echo "${ECHO_T}yes ($FUNTOOLSBASE)" >&6 + else + echo "$as_me:$LINENO: result: no: back-end programs will not be built" >&5 +echo "${ECHO_T}no: back-end programs will not be built" >&6 + USEHELPER="no" + fi +else + echo "$as_me:$LINENO: result: no: back-end programs will not be built" >&5 +echo "${ECHO_T}no: back-end programs will not be built" >&6 + USEHELPER="no" +fi +# make up the final switches +if test x$FUNTOOLSINC != x; then + FUNINC="-I$FUNTOOLSINC" +fi +if test x$FUNTOOLSLIB != x; then + FUNLIB="-L $FUNTOOLSLIB -lfuntools" +fi +# results from funtools search + + + +# check for external png libraries +echo "$as_me:$LINENO: checking for png" >&5 +echo $ECHO_N "checking for png... $ECHO_C" >&6 + +# Check whether --with-png or --without-png was given. +if test "${with_png+set}" = set; then + withval="$with_png" + havelib=1 +else + havelib=0 +fi; +if test x"$havelib" = x1 ; then + PNGBASE=$withval + # make sure essential libraries are present + if test -r $PNGBASE/lib$LSUFFIX/libpng.a -o \ + -r $PNGBASE/lib$LSUFFIX/libpng.so -o \ + -r $PNGBASE/lib$LSUFFIX/libpng.dylib; then + PNGLIB="-L $PNGBASE/lib$LSUFFIX -lpng" + if test x"$RFLAG" != x; then + PNGLIB="$RFLAG $PNGBASE/lib$LSUFFIX $PNGLIB" + fi + PNGINC="-I$PNGBASE/include" + echo "$as_me:$LINENO: result: yes ($PNGBASE)" >&5 +echo "${ECHO_T}yes ($PNGBASE)" >&6 + elif test -r $PNGBASE/lib/libpng.a -o \ + -r $PNGBASE/lib/libpng.so -o \ + -r $PNGBASE/lib/libpng.dylib; then + PNGLIB="-L $PNGBASE/lib -lpng" + if test x"$RFLAG" != x; then + PNGLIB="$RFLAG $PNGBASE/lib $PNGLIB" + fi + PNGINC="-I$PNGBASE/include" + echo "$as_me:$LINENO: result: yes ($PNGBASE)" >&5 +echo "${ECHO_T}yes ($PNGBASE)" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + { { echo "$as_me:$LINENO: error: can't find png library" >&5 +echo "$as_me: error: can't find png library" >&2;} + { (exit 1); exit 1; }; } + fi +else + echo "$as_me:$LINENO: checking for png_create_write_struct in -lpng" >&5 +echo $ECHO_N "checking for png_create_write_struct in -lpng... $ECHO_C" >&6 +if test "${ac_cv_lib_png_png_create_write_struct+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpng $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char png_create_write_struct (); +int +main () +{ +png_create_write_struct (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_png_png_create_write_struct=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_png_png_create_write_struct=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_create_write_struct" >&5 +echo "${ECHO_T}$ac_cv_lib_png_png_create_write_struct" >&6 +if test $ac_cv_lib_png_png_create_write_struct = yes; then + have_png=yes +else + have_png=no +fi + + if test "$have_png" = yes; then + PNGLIB="-lpng" + PNGINC="" + else + { { echo "$as_me:$LINENO: error: png library is required (visit: http://www.libpng.org)" >&5 +echo "$as_me: error: png library is required (visit: http://www.libpng.org)" >&2;} + { (exit 1); exit 1; }; } + fi +fi +# results from png search + + + +echo "$as_me:$LINENO: checking for connect" >&5 +echo $ECHO_N "checking for connect... $ECHO_C" >&6 +if test "${ac_cv_func_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define connect to an innocuous variant, in case declares connect. + For example, HP-UX 11i declares gettimeofday. */ +#define connect innocuous_connect + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char connect (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef connect + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_connect) || defined (__stub___connect) +choke me +#else +char (*f) () = connect; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != connect; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 +echo "${ECHO_T}$ac_cv_func_connect" >&6 + +if test $ac_cv_func_connect = no; then + echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 +echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6 +if test "${ac_cv_lib_socket_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +int +main () +{ +connect (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_socket_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_socket_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6 +if test $ac_cv_lib_socket_connect = yes; then + EXTRA_LIBS="$EXTRA_LIBS -lsocket" +fi + +fi +echo "$as_me:$LINENO: checking for gethostbyname" >&5 +echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6 +if test "${ac_cv_func_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostbyname to an innocuous variant, in case declares gethostbyname. + For example, HP-UX 11i declares gettimeofday. */ +#define gethostbyname innocuous_gethostbyname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef gethostbyname + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +char (*f) () = gethostbyname; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != gethostbyname; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6 + +if test $ac_cv_func_gethostbyname = no; then + echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 +echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6 +if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_nsl_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_nsl_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6 +if test $ac_cv_lib_nsl_gethostbyname = yes; then + EXTRA_LIBS="$EXTRA_LIBS -lnsl" +fi + +fi +echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + EXTRA_LIBS="$EXTRA_LIBS -ldl" +fi + + +echo "$as_me:$LINENO: checking $host_os configuration" >&5 +echo $ECHO_N "checking $host_os configuration... $ECHO_C" >&6 +case $host_os in + *cygwin*|*Cygwin* ) + cat >>confdefs.h <<\_ACEOF +#define HAVE_CYGWIN 1 +_ACEOF + + echo "$as_me:$LINENO: result: flagging Cygwin" >&5 +echo "${ECHO_T}flagging Cygwin" >&6 + ;; + *mingw32*|*Mingw32*) + CFLAGS="$CFLAGS -mconsole" + EXTRA_LIBS="$EXTRA_LIBS -lwsock32" + cat >>confdefs.h <<\_ACEOF +#define HAVE_MINGW32 1 +_ACEOF + + echo "$as_me:$LINENO: result: flagging MinGW" >&5 +echo "${ECHO_T}flagging MinGW" >&6 + ;; + * ) + if test x"$fpic" = x"yes" ; then + if test "$CC" = "gcc" -o `$CC -v 2>&1 | grep -c gcc` != "0" ; then + CFLAGS="$CFLAGS -fPIC" + echo "$as_me:$LINENO: result: adding -fPIC to gcc" >&5 +echo "${ECHO_T}adding -fPIC to gcc" >&6 + else + echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6 + fi + else + echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6 + fi + ;; +esac + + + +fi + +echo "$as_me:$LINENO: checking for sao top-level install directory" >&5 +echo $ECHO_N "checking for sao top-level install directory... $ECHO_C" >&6 + +# Check whether --with-saodir or --without-saodir was given. +if test "${with_saodir+set}" = set; then + withval="$with_saodir" + havetop=1 +else + havetop=0 +fi; +if test x"$havetop" = x1 ; then + SAODIR=$withval + echo "$as_me:$LINENO: result: yes ($SAODIR)" >&5 +echo "${ECHO_T}yes ($SAODIR)" >&6 +else + SAODIR="" + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + + ac_config_files="$ac_config_files Makefile" + + +# generate pkg-config meta-data file + ac_config_files="$ac_config_files js9helper.pc" + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by js9 $as_me 1.0, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +js9 config.status 1.0 +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "js9helper.pc" ) CONFIG_FILES="$CONFIG_FILES js9helper.pc" ;; + "conf.h" ) CONFIG_HEADERS="$CONFIG_HEADERS conf.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@WEBDIR@,$WEBDIR,;t t +s,@HELPER@,$HELPER,;t t +s,@USEHELPER@,$USEHELPER,;t t +s,@build@,$build,;t t +s,@build_cpu@,$build_cpu,;t t +s,@build_vendor@,$build_vendor,;t t +s,@build_os@,$build_os,;t t +s,@host@,$host,;t t +s,@host_cpu@,$host_cpu,;t t +s,@host_vendor@,$host_vendor,;t t +s,@host_os@,$host_os,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@CPP@,$CPP,;t t +s,@EGREP@,$EGREP,;t t +s,@CGIDIR@,$CGIDIR,;t t +s,@CGIURL@,$CGIURL,;t t +s,@CGIXPATH@,$CGIXPATH,;t t +s,@FUNINC@,$FUNINC,;t t +s,@FUNLIB@,$FUNLIB,;t t +s,@PNGLIB@,$PNGLIB,;t t +s,@PNGINC@,$PNGINC,;t t +s,@EXTRA_LIBS@,$EXTRA_LIBS,;t t +s,@SAODIR@,$SAODIR,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..15f3da04 --- /dev/null +++ b/configure.ac @@ -0,0 +1,252 @@ +# This file is an input file used by the GNU "autoconf" program to +# generate the file "configure", which is run during XPA installation +# to configure the system for the local environment. +AC_INIT(js9, 1.0, saord@cfa.harvard.edu, js9) + +AC_MSG_CHECKING(for web install directory) +AC_ARG_WITH(webdir, + [ --with-webdir= web install directory e.g. /var/www/public_html/js9], haveweb=1, haveweb=0) +if test x"$haveweb" = x1 ; then + WEBDIR=$withval + AC_MSG_RESULT(yes ($WEBDIR)) +else + AC_MSG_ERROR([--with-webdir= is required to specify the Web install directory]) +fi +AC_SUBST(WEBDIR) + +AC_MSG_CHECKING(for server-side helper type) +AC_ARG_WITH(helper, + [ --with-helper= i.e. none, nodejs, get, or post], havebe=1, havebe=0) +if test x"$havebe" = x1 ; then + HELPER=$withval + USEHELPER=yes + AC_MSG_RESULT(yes ($HELPER)) +else + HELPER=none + USEHELPER=no + AC_MSG_RESULT(no) +fi +AC_SUBST(HELPER) +AC_SUBST(USEHELPER) + +# if no back-end, we don't need a compiler, etc. +if [ test x"$USEHELPER" = xyes ]; then + +AC_CONFIG_HEADERS([conf.h]) +AC_CONFIG_SRCDIR(./tpos.c) +AC_CANONICAL_HOST + +AC_PROG_CC +AC_MSG_CHECKING([C compiler flags]) +case $CC in + *icc* ) + CFLAGS="-axW $CFLAGS" + ;; +esac +AC_MSG_RESULT(OK) + +# check for rflag +case $host_os in + *solaris*|*Solaris* ) + RFLAG="-R" + ;; + *linux*|*Linux* ) + RFLAG="-Wl,-R" + ;; + * ) + RFLAG="" + ;; +esac + +AC_PROG_RANLIB + +AC_CHECK_SIZEOF([void *]) +case $ac_cv_sizeof_void_p in + 8) LSUFFIX="64";; +esac + +AC_HEADER_STDC +AC_CHECK_HEADERS(malloc.h) +AC_CHECK_HEADERS(getopt.h) +AC_CHECK_HEADERS(pwd.h) +AC_CHECK_HEADERS(dlfcn.h) +AC_CHECK_HEADERS(setjmp.h) +AC_CHECK_HEADERS(values.h) + +AC_MSG_CHECKING(for cgi install directory) +AC_ARG_WITH(cgidir, + [ --with-cgidir= cgi install directory e.g. /var/www/public_html/cgi-bin], havecgi=1, havecgi=0) +if test x"$havecgi" = x1 ; then + CGIDIR=$withval + # make sure this directory is present + if test -d $CGIDIR; then + AC_MSG_RESULT(yes ($CGIDIR)) + else + AC_MSG_RESULT(no) + AC_MSG_ERROR([can't find cgi install dir: $CGIDIR]) + fi +else + AC_MSG_RESULT(no) +fi +AC_SUBST(CGIDIR) + +AC_MSG_CHECKING(for cgi url) +AC_ARG_WITH(cgiurl, + [ --with-cgiurl= cgi relative url e.g. ./cgi-bin], havecgi=1, havecgi=0) +if test x"$havecgi" = x1 ; then + CGIURL=$withval + AC_MSG_RESULT(yes ($CGIURL)) +else + AC_MSG_RESULT(no) +fi +AC_SUBST(CGIURL) + +AC_MSG_CHECKING(for extra directories for cgi path) +AC_ARG_WITH(cgixpath, + [ --with-cgixpath= directories to add to cgi path], havecgi=1, havecgi=0) +if test x"$havecgi" = x1 ; then + CGIXPATH=$withval + AC_MSG_RESULT(yes ($CGIXPATH)) +else + AC_MSG_RESULT(no) +fi +AC_SUBST(CGIXPATH) + +# check for external funtools libraries +AC_MSG_CHECKING(for funtools) +AC_ARG_WITH(funtools, + [ --with-funtools= funtools directory e.g. /soft/funtools], havelib=1, havelib=0) +if test x"$havelib" = x1 ; then + FUNTOOLSBASE=$withval + # make sure essential libraries are present + if test -r $FUNTOOLSBASE/lib$LSUFFIX/libfuntools.a -o \ + -r $FUNTOOLSBASE/lib$LSUFFIX/libfuntools.so -o \ + -r $FUNTOOLSBASE/lib$LSUFFIX/libfuntools.dylib; then + FUNTOOLSLIB=$FUNTOOLSBASE/lib$LSUFFIX + FUNTOOLSINC=$FUNTOOLSBASE/include + AC_MSG_RESULT(yes ($FUNTOOLSBASE)) + elif test -r $FUNTOOLSBASE/lib/libfuntools.a -o \ + -r $FUNTOOLSBASE/lib/libfuntools.so -o \ + -r $FUNTOOLSBASE/lib/libfuntools.dylib; then + FUNTOOLSLIB=$FUNTOOLSBASE/lib + FUNTOOLSINC=$FUNTOOLSBASE/include + AC_MSG_RESULT(yes ($FUNTOOLSBASE)) + else + AC_MSG_RESULT(no: back-end programs will not be built) + USEHELPER="no" + fi +else + AC_MSG_RESULT(no: back-end programs will not be built) + USEHELPER="no" +fi +# make up the final switches +if test x$FUNTOOLSINC != x; then + FUNINC="-I$FUNTOOLSINC" +fi +if test x$FUNTOOLSLIB != x; then + FUNLIB="-L $FUNTOOLSLIB -lfuntools" +fi +# results from funtools search +AC_SUBST(FUNINC) +AC_SUBST(FUNLIB) + +# check for external png libraries +AC_MSG_CHECKING(for png) +AC_ARG_WITH(png, + [ --with-png= directory containing lib/libpng e.g. /usr/local], havelib=1, havelib=0) +if test x"$havelib" = x1 ; then + PNGBASE=$withval + # make sure essential libraries are present + if test -r $PNGBASE/lib$LSUFFIX/libpng.a -o \ + -r $PNGBASE/lib$LSUFFIX/libpng.so -o \ + -r $PNGBASE/lib$LSUFFIX/libpng.dylib; then + PNGLIB="-L $PNGBASE/lib$LSUFFIX -lpng" + if test x"$RFLAG" != x; then + PNGLIB="$RFLAG $PNGBASE/lib$LSUFFIX $PNGLIB" + fi + PNGINC="-I$PNGBASE/include" + AC_MSG_RESULT(yes ($PNGBASE)) + elif test -r $PNGBASE/lib/libpng.a -o \ + -r $PNGBASE/lib/libpng.so -o \ + -r $PNGBASE/lib/libpng.dylib; then + PNGLIB="-L $PNGBASE/lib -lpng" + if test x"$RFLAG" != x; then + PNGLIB="$RFLAG $PNGBASE/lib $PNGLIB" + fi + PNGINC="-I$PNGBASE/include" + AC_MSG_RESULT(yes ($PNGBASE)) + else + AC_MSG_RESULT(no) + AC_MSG_ERROR([can't find png library]) + fi +else + AC_CHECK_LIB(png, png_create_write_struct, have_png=yes, have_png=no) + if test "$have_png" = yes; then + PNGLIB="-lpng" + PNGINC="" + else + AC_MSG_ERROR([png library is required (visit: http://www.libpng.org)]) + fi +fi +# results from png search +AC_SUBST(PNGLIB) +AC_SUBST(PNGINC) + +AC_CHECK_FUNC(connect) +if test $ac_cv_func_connect = no; then + AC_CHECK_LIB(socket, connect, EXTRA_LIBS="$EXTRA_LIBS -lsocket") +fi +AC_CHECK_FUNC(gethostbyname) +if test $ac_cv_func_gethostbyname = no; then + AC_CHECK_LIB(nsl, gethostbyname, EXTRA_LIBS="$EXTRA_LIBS -lnsl") +fi +AC_CHECK_LIB(dl, dlopen, EXTRA_LIBS="$EXTRA_LIBS -ldl") + +AC_MSG_CHECKING([$host_os configuration]) +case $host_os in + *cygwin*|*Cygwin* ) + AC_DEFINE(HAVE_CYGWIN) + AC_MSG_RESULT(flagging Cygwin) + ;; + *mingw32*|*Mingw32*) + CFLAGS="$CFLAGS -mconsole" + EXTRA_LIBS="$EXTRA_LIBS -lwsock32" + AC_DEFINE(HAVE_MINGW32) + AC_MSG_RESULT(flagging MinGW) + ;; + * ) + if test x"$fpic" = x"yes" ; then + if test "$CC" = "gcc" -o `$CC -v 2>&1 | grep -c gcc` != "0" ; then + CFLAGS="$CFLAGS -fPIC" + AC_MSG_RESULT(adding -fPIC to gcc) + else + AC_MSG_RESULT(none) + fi + else + AC_MSG_RESULT(none) + fi + ;; +esac + +AC_SUBST(EXTRA_LIBS) + +fi + +AC_MSG_CHECKING(for sao top-level install directory) +AC_ARG_WITH(saodir, + [ --with-saodir= top install directory e.g. /var/www/public_html], havetop=1, havetop=0) +if test x"$havetop" = x1 ; then + SAODIR=$withval + AC_MSG_RESULT(yes ($SAODIR)) +else + SAODIR="" + AC_MSG_RESULT(no) +fi +AC_SUBST(SAODIR) + +AC_CONFIG_FILES(Makefile) + +# generate pkg-config meta-data file +AC_CONFIG_FILES(js9helper.pc) + +AC_OUTPUT diff --git a/css/dhtmlwindow.css b/css/dhtmlwindow.css new file mode 100644 index 00000000..36ec3af7 --- /dev/null +++ b/css/dhtmlwindow.css @@ -0,0 +1,57 @@ +.dhtmlwindow{ +position: absolute; +border: 2px solid black; +visibility: hidden; +background-color: white; +} + +.drag-handle{ /*CSS for Drag Handle*/ +padding: 1px; +text-indent: 3px; +font: bold 14px Arial; +background-color: #CA0000; +color: white; +cursor: move; +overflow: hidden; +width: auto; +filter:progid:DXImageTransform.Microsoft.alpha(opacity=100); +-moz-opacity: 1; +opacity: 1; +} + +.drag-handle .drag-controls{ /*CSS for controls (min, close etc) within Drag Handle*/ +position: absolute; +right: 1px; +top: 2px; +cursor: hand; +cursor: pointer; +} + +* html .drag-handle{ /*IE6 and below CSS hack. Width must be set to 100% in order for opaque title bar to render*/ +width: 100%; +} + + +.drag-contentarea{ /*CSS for Content Display Area div*/ +border-top: 1px solid brown; +background-color: white; +color: black; +height: 150px; +padding: 2px; +overflow: auto; +} + +.drag-statusarea{ /*CSS for Status Bar div (includes resizearea)*/ +border-top: 1px solid gray; +background-color: #F8F8F8; +height: 13px; /*height of resize image*/ +} + + +.drag-resizearea{ /*CSS for Resize Area itself*/ +float: right; +width: 13px; /*width of resize image*/ +height: 13px; /*height of resize image*/ +cursor: nw-resize; +font-size: 0; +} \ No newline at end of file diff --git a/css/jquery.contextMenu-1.5.24.css b/css/jquery.contextMenu-1.5.24.css new file mode 100755 index 00000000..71d537da --- /dev/null +++ b/css/jquery.contextMenu-1.5.24.css @@ -0,0 +1,142 @@ +/*! + * jQuery contextMenu - Plugin for simple contextMenu handling + * + * Version: 1.5.24 + * + * Authors: Rodney Rehm, Addy Osmani (patches for FF) + * Web: http://medialize.github.com/jQuery-contextMenu/ + * + * Licensed under + * MIT License http://www.opensource.org/licenses/mit-license + * GPL v3 http://opensource.org/licenses/GPL-3.0 + * + */ + +.context-menu-list { + margin:0; + padding:5px; + + min-width: 120px; + max-width: 250px; + display: inline-block; + position: absolute; + list-style-type: none; + + border: 1px solid #DDD; + background: #EEE; + + -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); + -ms-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); + -o-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); + + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +.context-menu-item { + padding: 2px 2px 2px 24px; + background-color: #EEE; + position: relative; + -webkit-user-select: none; + -moz-user-select: -moz-none; + -ms-user-select: none; + user-select: none; +} + +.context-menu-separator { + padding-bottom:0; + border-bottom: 1px solid #DDD; +} + +.context-menu-item > label > input, +.context-menu-item > label > textarea { + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.context-menu-item.hover { + cursor: pointer; + background-color: #39F; +} + +.context-menu-item.disabled { + color: #666; +} + +.context-menu-input.hover, +.context-menu-item.disabled.hover { + cursor: default; + background-color: #EEE; +} + +.context-menu-submenu:after { + content: ">"; + color: #666; + position: absolute; + top: 0; + right: 3px; + z-index: 1; +} + +/* icons + #protip: + In case you want to use sprites for icons (which I would suggest you do) have a look at + http://css-tricks.com/13224-pseudo-spriting/ to get an idea of how to implement + .context-menu-item.icon:before {} + */ +.context-menu-item.icon { min-height: 18px; background-repeat: no-repeat; background-position: 4px 2px; } +.context-menu-item.icon-edit { background-image: url(images/page_white_edit.png); } +.context-menu-item.icon-cut { background-image: url(images/cut.png); } +.context-menu-item.icon-copy { background-image: url(images/page_white_copy.png); } +.context-menu-item.icon-paste { background-image: url(images/page_white_paste.png); } +.context-menu-item.icon-delete { background-image: url(images/page_white_delete.png); } +.context-menu-item.icon-add { background-image: url(images/page_white_add.png); } +.context-menu-item.icon-quit { background-image: url(images/door.png); } + +/* vertically align inside labels */ +.context-menu-input > label > * { vertical-align: top; } + +/* position checkboxes and radios as icons */ +.context-menu-input > label > input[type="checkbox"], +.context-menu-input > label > input[type="radio"] { + margin-left: -17px; +} +.context-menu-input > label > span { + margin-left: 5px; +} + +.context-menu-input > label, +.context-menu-input > label > input[type="text"], +.context-menu-input > label > textarea, +.context-menu-input > label > select { + display: block; + width: 100%; + + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + -o-box-sizing: border-box; + box-sizing: border-box; +} + +.context-menu-input > label > textarea { + height: 100px; +} +.context-menu-item > .context-menu-list { + display: none; + /* re-positioned by js */ + right: -5px; + top: 5px; +} + +.context-menu-item.hover > .context-menu-list { + display: block; +} + +.context-menu-accesskey { + text-decoration: underline; +} diff --git a/css/jquery.contextMenu.css b/css/jquery.contextMenu.css new file mode 100755 index 00000000..ee58116f --- /dev/null +++ b/css/jquery.contextMenu.css @@ -0,0 +1,142 @@ +/*! + * jQuery contextMenu - Plugin for simple contextMenu handling + * + * Version: git-master + * + * Authors: Rodney Rehm, Addy Osmani (patches for FF) + * Web: http://medialize.github.com/jQuery-contextMenu/ + * + * Licensed under + * MIT License http://www.opensource.org/licenses/mit-license + * GPL v3 http://opensource.org/licenses/GPL-3.0 + * + */ + +.context-menu-list { + margin:0; + padding:0; + + min-width: 120px; + max-width: 250px; + display: inline-block; + position: absolute; + list-style-type: none; + + border: 1px solid #DDD; + background: #EEE; + + -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); + -ms-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); + -o-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); + + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +.context-menu-item { + padding: 2px 2px 2px 24px; + background-color: #EEE; + position: relative; + -webkit-user-select: none; + -moz-user-select: -moz-none; + -ms-user-select: none; + user-select: none; +} + +.context-menu-separator { + padding-bottom:0; + border-bottom: 1px solid #DDD; +} + +.context-menu-item > label > input, +.context-menu-item > label > textarea { + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.context-menu-item.hover { + cursor: pointer; + background-color: #39F; +} + +.context-menu-item.disabled { + color: #666; +} + +.context-menu-input.hover, +.context-menu-item.disabled.hover { + cursor: default; + background-color: #EEE; +} + +.context-menu-submenu:after { + content: ">"; + color: #666; + position: absolute; + top: 0; + right: 3px; + z-index: 1; +} + +/* icons + #protip: + In case you want to use sprites for icons (which I would suggest you do) have a look at + http://css-tricks.com/13224-pseudo-spriting/ to get an idea of how to implement + .context-menu-item.icon:before {} + */ +.context-menu-item.icon { min-height: 18px; background-repeat: no-repeat; background-position: 4px 2px; } +.context-menu-item.icon-edit { background-image: url(images/page_white_edit.png); } +.context-menu-item.icon-cut { background-image: url(images/cut.png); } +.context-menu-item.icon-copy { background-image: url(images/page_white_copy.png); } +.context-menu-item.icon-paste { background-image: url(images/page_white_paste.png); } +.context-menu-item.icon-delete { background-image: url(images/page_white_delete.png); } +.context-menu-item.icon-add { background-image: url(images/page_white_add.png); } +.context-menu-item.icon-quit { background-image: url(images/door.png); } + +/* vertically align inside labels */ +.context-menu-input > label > * { vertical-align: top; } + +/* position checkboxes and radios as icons */ +.context-menu-input > label > input[type="checkbox"], +.context-menu-input > label > input[type="radio"] { + margin-left: -17px; +} +.context-menu-input > label > span { + margin-left: 5px; +} + +.context-menu-input > label, +.context-menu-input > label > input[type="text"], +.context-menu-input > label > textarea, +.context-menu-input > label > select { + display: block; + width: 100%; + + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + -o-box-sizing: border-box; + box-sizing: border-box; +} + +.context-menu-input > label > textarea { + height: 100px; +} +.context-menu-item > .context-menu-list { + display: none; + /* re-positioned by js */ + right: -5px; + top: 5px; +} + +.context-menu-item.hover > .context-menu-list { + display: block; +} + +.context-menu-accesskey { + text-decoration: underline; +} diff --git a/css/tabcontent.css b/css/tabcontent.css new file mode 100644 index 00000000..cbf482c8 --- /dev/null +++ b/css/tabcontent.css @@ -0,0 +1,176 @@ +/* ######### CSS for Shade Tabs. Remove if not using ######### */ + +.shadetabs{ +padding: 3px 0; +margin-left: 0; +margin-top: 1px; +margin-bottom: 0; +font: bold 12px Verdana; +list-style-type: none; +text-align: left; /*set to left, center, or right to align the menu as desired*/ +} + +.shadetabs li{ +display: inline; +margin: 0; +} + +.shadetabs li a{ +text-decoration: none; +position: relative; +z-index: 1; +padding: 3px 7px; +margin-right: 3px; +border: 1px solid #778; +color: #2d2b2b; +background: white url(shade.gif) top left repeat-x; +} + +.shadetabs li a:visited{ +color: #2d2b2b; +} + +.shadetabs li a:hover{ +text-decoration: underline; +color: #2d2b2b; +} + +.shadetabs li a.selected{ /*selected main tab style */ +position: relative; +top: 1px; +} + +.shadetabs li a.selected{ /*selected main tab style */ +background-image: url(shadeactive.gif); +border-bottom-color: white; +} + +.shadetabs li a.selected:hover{ /*selected main tab style */ +text-decoration: none; +} + +.tabcontent{ +display:none; +} + +@media print { +.tabcontent { +display:block !important; +} +} + +/* ######### CSS for Inverted Modern Bricks II Tabs. Remove if not using ######### */ + +.modernbricksmenu2{ +padding: 0; +width: 362px; +border-top: 5px solid #D25A0B; /*Brown color theme*/ +background: transparent; +voice-family: "\"}\""; +voice-family: inherit; +} + +.modernbricksmenu2 ul{ +margin:0; +margin-left: 10px; /*margin between first menu item and left browser edge*/ +padding: 0; +list-style: none; +} + +.modernbricksmenu2 li{ +display: inline; +margin: 0 2px 0 0; +padding: 0; +text-transform:uppercase; +} + +.modernbricksmenu2 a{ +float: left; +display: block; +font: bold 11px Arial; +color: white; +text-decoration: none; +margin: 0 1px 0 0; /*Margin between each menu item*/ +padding: 5px 10px; +background-color: black; /*Brown color theme*/ +border-top: 1px solid white; +} + +.modernbricksmenu2 a:hover{ +background-color: #D25A0B; /*Brown color theme*/ +color: white; +} + +.modernbricksmenu2 a.selected{ /*currently selected tab*/ +background-color: #D25A0B; /*Brown color theme*/ +color: white; +border-color: #D25A0B; /*Brown color theme*/ +} + +.tabcontent{ +display:none; +} + +@media print { +.tabcontent { +display:block !important; +} +} + +/* ######### CSS for Indented CSS Tabs. Remove if not using ######### */ + + +.indentmenu{ +font: bold 13px Arial; +width: 100%; /*leave this value as is in most cases*/ +} + +.indentmenu ul{ +margin: 0; +padding: 0; +float: left; +/* width: 80%; width of menu*/ +border-top: 1px solid navy; /*navy border*/ +background: black url(indentbg.gif) center center repeat-x; +} + +.indentmenu ul li{ +display: inline; +} + +.indentmenu ul li a{ +float: left; +color: white; /*text color*/ +padding: 5px 11px; +text-decoration: none; +border-right: 1px solid navy; /*navy divider between menu items*/ +} + +.indentmenu ul li a:visited{ +color: white; +} + +.indentmenu ul li a.selected{ +color: white !important; +padding-top: 6px; /*shift text down 1px*/ +padding-bottom: 4px; +background: black url(indentbg2.gif) center center repeat-x; +} + + +.tabcontentstyle{ /*style of tab content oontainer*/ +border: 1px solid gray; +width: 450px; +margin-bottom: 1em; +padding: 10px; +} + +.tabcontent{ +display:none; +} + +@media print { +.tabcontent { +display:block !important; +} +} \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 00000000..8636d9b2 Binary files /dev/null and b/favicon.ico differ diff --git a/fits2png b/fits2png new file mode 100755 index 00000000..6f7d9325 --- /dev/null +++ b/fits2png @@ -0,0 +1,167 @@ +#!/bin/bash +# set -x + +# error routine +error () { + echo "ERROR: $*" >&2 + exit 1 +} + +ODIR="" +SWITCHES="" +REPLACE=true +# switch processing +while [ x"$1" != x ]; do + case $1 in + -abs) shift + ABSPATH=$1 + shift + continue;; + + -dim) shift + XDIM=$1 + YDIM=$2 + shift + shift + continue;; + + -js9) shift + XDIM=1024 + YDIM=1024 + VERBOSE=ofile + ODIR="@IDIR@" + REPLACE=false + continue;; + + -odir) shift + ODIR=$1 + shift + continue;; + + -repl) shift + REPLACE=$1 + shift + continue;; + + -id) shift + ID="/""$1" + shift + continue;; + + -gz) shift + FTYPE="gzip:" + continue;; + + -ftype) shift + FTYPE="$1" + shift + continue;; + + -v) shift + VERBOSE=$1 + shift + continue;; + + *) break;; + esac +done + +# required first arg: input FITS file +if [ x"$1" != x ]; then + F=$1 +else + echo "usage: $0 ifits [opng]" >&2 + exit 1 +fi + +# get input file without extension +IFILE=`echo $F | sed 's#\[.*##'` +# make sure input file exits +if [ ! -r $IFILE ]; then + error "can't locate file: $IFILE" +fi +# get extension +IEXT=`echo $F | sed 's#^[^[]*##'` + +# get absolute path +if [ x$ABSPATH = xtrue ]; then + ADIR=$PWD + MYDIR=`dirname $IFILE` + MYFILE=`basename $IFILE` + cd $MYDIR 2>/dev/null || error "can't cd to $MYDIR (for absolute directory)" + IFILE=$PWD/$MYFILE + cd $ADIR || exit +fi + +# optional second arg: output PNG file +if [ x"$2" != x ]; then + OFILE=$2 +else + OFILE=`basename $IFILE .fits` + OFILE=${OFILE}.png +fi + +# where to put the png file ... +# put png is same directory as fits? +if [ x"$ODIR" = 'x@IDIR@' ]; then + ODIR=`dirname $F` +fi + +# look for %X string in odir, which will be replaced by a cookie value +KEY=`echo $ODIR | sed -n 's#.*%\([A-Za-z0-9_][A-Za-z0-9_]*\).*#\1#p'` +if [ x"$KEY" != x ]; then + VAL="" + OFS="$IFS" + if [ "$HTTP_COOKIE" != "" ] ; then + IFS=";"; set $HTTP_COOKIE; IFS="$OFS"; COOKIES=$* + for COOK in $COOKIES ; do + IFS="="; set $COOK; IFS="$OFS" + # check for a key of the same name, set value if present + case $1 in + $KEY) VAL="$2";; + esac + done + fi + # make replacement + if [ x"$VAL" != x ]; then + ODIR=`echo $ODIR | sed 's#%'$KEY'#'$VAL'#'` + else + error "no cookie found with key: $KEY" + fi +fi + +# make sure output directory exists +if [ x$ODIR != x ]; then + mkdir -p $ODIR + # final form for output file + OFILE=${ODIR}/${OFILE} +fi + +# if output file already exists, do we replace it? +if [ x$REPLACE = xtrue -o ! -r $OFILE ]; then + +# for js9 processing, determine block factor +if [ x$XDIM != x -a x$YDIM != x ]; then + BL=8 + DIMS=`funimage ${FTYPE}$IFILE'[*,*,'$BL']' stdout bitpix=8 2>/dev/null | dd bs=80 count=10 2>/dev/null | sed -e 's/.\{80\}/&@/g' | tr '@' '\012' | egrep NAXIS'[1,2]' | sed 's# /.*##g;s# ##g'` + eval $DIMS + if [ $NAXIS1 -gt $NAXIS2 ]; then + BLOCK=`echo "($NAXIS1 * $BL + ($XDIM - 1)) / $XDIM" | bc` + else + BLOCK=`echo "($NAXIS2 * $BL + ($XDIM - 1)) / $XDIM" | bc` + fi + IEXT="[*,*,$BLOCK]"$IEXT +fi + +# create png file (filter out the annoying warning about dimensions!) +{ tpos $SWITCHES "${FTYPE}$IFILE""$IEXT" "$OFILE" 2>&1 1>&3 | egrep -v WARNING 1>&2; } 3>&1 + +fi + +# verbose output +case $VERBOSE in + ofile) echo "$OFILE";; + cmd) echo tpos "${FTYPE}$IFILE""$IEXT" "$OFILE";; + * ) ;; +esac + diff --git a/fitsy.js b/fitsy.js new file mode 120000 index 00000000..ee66aacc --- /dev/null +++ b/fitsy.js @@ -0,0 +1 @@ +./plugins/fitsy/fitsy.js \ No newline at end of file diff --git a/fitsy.min.js b/fitsy.min.js new file mode 100644 index 00000000..97d2a1c6 --- /dev/null +++ b/fitsy.min.js @@ -0,0 +1,43 @@ +var Fitsy;if(Fitsy&&("object"!==typeof Fitsy||Fitsy.NAME))throw Error("Namespace 'Fitsy' already exists"); +Fitsy={NAME:"Fitsy",VERSION:"1.0",clone:function(b){var a,d,e;if(null===b||"object"!==typeof b)return b;if(b instanceof Date)return a=new Date,a.setTime(b.getTime()),a;if(b instanceof Array){a=[];d=0;for(e=b.length;da)return"";for(var d="";1>=1,b+=b;return d+ +b}};ArrayBuffer.prototype.slice||(ArrayBuffer.prototype.slice=function(b,a){var d,e,c,f=new Uint8Array(this);void 0===a&&(a=f.length);e=new ArrayBuffer(a-b);c=new Uint8Array(e);for(d=0;d= $2 && $1 <= $3)");d=d.replace(/([a-zA-Z][a-zA-Z0-9_]*) *= *([\-]?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+\-]?[0-9]+)?) *:/g,"$1 >= $2");d=d.replace(/([a-zA-Z][a-zA-Z0-9_]*) *= *:([\-]?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+\-]?[0-9]+)?)/g,"$1 <= $2");return d.replace(/([ (&|+\-\/*%<>=]|^)?([a-zA-Z][a-zA-Z0-9_]*)([ )&|+\-\/*%<>=]|$)/g, +function(a,d,f,g){a=f;var j=f.toUpperCase();d=d||"";g=g||"";void 0!==b.table[a]?a=d+"view.get"+b.table[a].type+"(vstart + i * {{table.width}} + "+b.table[a].offs+")"+g:void 0!==b.table[j]?a=d+"view.get"+b.table[j].type+"(vstart + i * {{table.width}} + "+b.table[j].offs+")"+g:Fitsy.error("the requested column '"+f+"' is missing from this FITS table");return a})};Fitsy.getFileSlice=function(b,a,d){var e;b.slice?e=b.slice(a,d):b.mozSlice?e=b.mozSlice(a,d):b.webkitSlice&&(e=b.webkitSlice(a,d));return e}; +Fitsy.isNumber=function(b){return!isNaN(parseFloat(b))&&isFinite(b)};Fitsy.xtypeof=function(b){return Object.prototype.toString.call(b).slice(8,-1)};Fitsy.cardpars=function(b){var a;if("="===b[8])return a=b.slice(0,8).trim(),b=b.slice(10).replace(/\'/g," ").replace(/\/.*/,"").trim(),"T"===b?b=!0:"F"===b?b=!1:Fitsy.isNumber(b)&&(b=parseFloat(b)),[a,b]}; +Fitsy.readImageHDUDataConverter=function(b,a,d,e){var c,f,g,j,k,l,h;g=0;var m;a.dmin=Number.MAX_VALUE;a.dmax=Number.MIN_VALUE;a.filename=b.name;switch(b.ftype){case "array":b.rlo&&(g=b.rlo)}switch(a.bitpix){case 8:c=DataView.prototype.getUint8;f=DataView.prototype.setUint8;try{a.filedata=new Uint8Array(b.result,g)}catch(q){l=!0}break;case -16:c=DataView.prototype.getUint16;f=DataView.prototype.setUint16;try{a.filedata=new Uint16Array(b.result,g)}catch(p){l=!0}break;case 16:if(a.bzero&&32768===a.bzero){c= +DataView.prototype.getInt16;f=DataView.prototype.setUint16;try{a.filedata=new Uint16Array(b.result,g)}catch(n){l=!0}a.bitpix=-16}else{c=DataView.prototype.getInt16;f=DataView.prototype.setInt16;try{a.filedata=new Int16Array(b.result,g)}catch(r){l=!0}}break;case 32:c=DataView.prototype.getInt32;f=DataView.prototype.setInt32;try{a.filedata=new Int32Array(b.result,g)}catch(s){l=!0}break;case -32:c=DataView.prototype.getFloat32;f=DataView.prototype.setFloat32;try{a.filedata=new Float32Array(b.result, +g)}catch(t){l=!0}break;case -64:c=DataView.prototype.getFloat64;f=DataView.prototype.setFloat64;try{a.filedata=new Float64Array(b.result,g)}catch(u){l=!0}break;default:Fitsy.error("unsupported FITS BITPIX value: "+a.bitpix)}l&&Fitsy.error("can't allocate enough memory for this FITS image");a.image=a.filedata;h=a.bzero||0;l=a.bscale||1;b=new DataView(b.result);m=a.converted?Fitsy.hostEndian:!1;j=0;for(k=g;jFitsy.options.gzfilesize?(b.ftype="gzarray",b.gz={},b.gz.arrfile=Astroem.arrfile(b.name,a),b.gz.fd=Astroem.gzopen(b.gz.arrfile.path,"rb"),b.gz.here=0,b.size=-1,b.eof=!1):(a=Astroem.decompress(a),b.ftype="array",b.file=a.buffer,b.size=b.file.byteLength):window.hasOwnProperty("Zee")?(a=Zee.decompress(a),b.ftype="array",b.file=a.buffer,b.size=b.file.byteLength):window.hasOwnProperty("pako")?(a=pako.inflate(a),b.ftype="array", +b.file=a.buffer,b.size=b.file.byteLength):Fitsy.error("gzip support not available")):Fitsy.error("not a recognized FITS file (compressed or otherwise): "+b.name);Fitsy.getDataSlice(b,"asString",0,2880,Fitsy.readHeaderBlock,Fitsy.readError,b)}; +Fitsy.readHeaderBlock=function(b){var a,d,e=0;b.eof&&(Fitsy.waiting(!1),b.handler(b));b.hdu[b.nhdu]||(b.hdu[b.nhdu]={});var c=b.hdu[b.nhdu];if(!c.card&&(c.headseek=b.here,c.card=[],c.head={},c.ncard=0,c.fits=b,c.nth=b.nhdu,0===b.here&&"SIMPLE"!==b.result.slice(0,6))){Fitsy.waiting(!0);setTimeout(function(){Fitsy.getDataSlice(b,"asArray",null,null,Fitsy.readForDeCompress,Fitsy.readError,b)},Fitsy.options.wtimeout);return}if(0===b.here){if("SIMPLE"!==b.result.slice(0,6))return}else if(0===c.ncard&& +"XTENSION"!==b.result.slice(0,8))return;b.here+=2880;for(a=0;2880>a;c.ncard++,a+=80){d=b.result.slice(a,a+80);c.card[c.ncard]=d;if("END "===d.slice(0,8)){e=1;break}d=Fitsy.cardpars(d);void 0!==d&&(c.head[d[0]]=d[1])}if(e){c.axis=[];c.dataseek=b.here;c.naxis=c.head.NAXIS;c.bitpix=c.head.BITPIX;c.bscale=c.head.BSCALE;c.bzero=c.head.BZERO;c.pixlbytes=Math.abs(c.bitpix)/8;c.datapixls=0!==c.naxis?1:0;for(a=1;a<=c.naxis;a++)c.axis[a]=c.head["NAXIS"+a],c.datapixls*=c.axis[a];c.databytes=c.datapixls* +c.pixlbytes;c.databloks=(c.databytes+2879)/2880|0;b.here+=2880*c.databloks;b.nhdu++;c.type="image";c.filehead=c.head;c.filecard=c.card;if("BINTABLE"===c.head.XTENSION||"A3DTABLE"===c.head.XTENSION||"3DTABLE"===c.head.XTENSION){c.type="table";c.table={};c.width=c.axis[1];c.length=c.axis[2];var f,g,j=0;for(a=1;a<=c.head.TFIELDS;a++)f=c.head["TFORM"+a].match(/([0-9]*)([LXBIJKAEDCMPQ])/),e=""===f[0]?1:+f[1],d=TableTFORM[f[2]].type,f=TableTFORM[f[2]].size,g=e*f,c.table[c.head["TTYPE"+a]]={type:d,size:f, +width:g,rept:e,offs:j,unit:c.head["TUNIT"+a],disp:c.head["TDISP"+a],zero:c.head["TZERO"+a],scale:c.head["TSCAL"+a],min:c.head["TDMIN"+a]||c.head["TLMIN"+a],max:c.head["TDMAX"+a]||c.head["TLMAX"+a],ith:a},j+=g}}b.here>=b.size&&-1!==b.size?(Fitsy.waiting(!1),b.handler(b)):Fitsy.getDataSlice(b,"asString",b.here,b.here+2880,Fitsy.readHeaderBlock,Fitsy.readError,b)}; +Fitsy.fitsopen=function(b,a){var d={hdu:[]};d.read=new FileReader;d.handler=a;b||Fitsy.readError(null);d.name=b.name;d.size=b.size;d.file=b;d.ftype="file";d.nhdu=0;d.here=0;Fitsy.getDataSlice(d,"asString",0,2880,Fitsy.readHeaderBlock,Fitsy.readError,d)}; +Fitsy.template=function(b,a){return b.replace(/\{\{([a-zA-Z0-9_.]+)(%([sfd])(\.([0-9]+))?)?\}\}/g,function(b,e,c,f,g,j){c=a;e=e.split(".");for(b=0;b=h.nx*h.ny)for(f=0;f "/dev/stderr" + exit 1 + } + } + else{ + mode = 3 + } + next +} +END{ + printf "]}" +} +' files="$files" +exit 0 diff --git a/funhist2flot b/funhist2flot new file mode 100755 index 00000000..34d4cf8f --- /dev/null +++ b/funhist2flot @@ -0,0 +1,79 @@ +#!/bin/sh + +LC_NUMERIC=en_US.ISO8859-1 +export LC_NUMERIC + +files="None" +while [ x"$1" != x ]; do + case $1 in + -title) + title="$2" + shift + shift + continue;; + -file) + files="$2" + shift + shift + continue;; + *) + break;; + esac +done + +awk -v title="$title" ' +BEGIN{ + mode=1 + initparam=0 + npts=0 +} +mode==1{ + if( initparam == 0 ){ + if( files == "None" ){ + files="" + dofile="true" + } + else{ + dofile="false" + } + initparam=1 + if( title == "" ){ + title = "Funhist" + } + } + if( dofile == "true" && $1 == "#" && $2 == "data" && $3 == "file:" ){ + if( files != "" ) files = files "," + files = files $4 + } + else if( $1 == "#" && $2 == "column:" ){ + column = $3 + } + else if( $1 == "------" ){ + gsub(/"/,"\\\"", files) + printf "{\042color\042: \042blue\042, \042label\042 : \042counts vs %s_bin\042, ", column + mode = 2 + next + } +} +mode==2{ + if( NF == 4 ){ + if( npts == 0 ){ + printf "\042data\042 : [" + } else { + printf "," + } + npts = npts + 1 + printf "[%.2f, %s]", ($3+$4)/2, $2 + } + else{ + mode = 3 + } + next +} +END{ + if( mode > 1 ){ + printf "]}" + } +} +' files="$files" +exit 0 diff --git a/help/changelog.html b/help/changelog.html new file mode 100644 index 00000000..b06ac8cc --- /dev/null +++ b/help/changelog.html @@ -0,0 +1,205 @@ + + + +JS9 ChangeLog + + + +

+

JS9 ChangeLog

+ +

Public Release 1.0 (September 30, 2014)

+
    +
  • NB: change to the Public API: id is no longer first argument. See API doc. +
  • infobox plugin upgraded to a tabular display +
  • node.js server sends unique pageid back to JS9 +
  • JS9 menus now cover light windows (higher zindex) +
  • improved accuracy of polygon points for contours +
  • moving a polygon point now calls listRegion +
  • added missing commas in WCS display of polygon points +
  • corrected WCS for drag/drop of sections of FITS binary tables +
  • fixed incorrect region size when binning FITS binary tables +
  • fixed memory leak in astroem reg2wcs routine +
  • plugin divs can now set height and width using CSS +
  • added defensive code to remove bash functions from CGI and node calls +
  • updated fabric.js to 1.4.11 +
+ +

Release 1-epsilon (July 28, 2014)

+
    +
  • JS9.Load() can now load FITS files directly (rather than converting to PNG) +
  • added support for FITS binary tables, including binning and filtering +
  • added support for gzip'ed FITS files +
  • added support for "physical" coordinates (i.e., tied to original data file) +
  • changed 2D graphics subsystem from Kinetic.js to fabric.js +
  • added generalized shape layer support for regions, catalogs, contours, etc. +
  • region context menu is now a light-weight web page with many new features +
  • added text and point regions +
  • position of a pixel is now in the center of the pixel +
  • accelerator key changed from shift key to meta key (command on Mac, control elsewhere) +
  • reduced number of js9 files to load in a web page +
  • redesigned and flattened returned region object +
  • redesigned public API +
  • changed Public routines JS9.Pix2WCS and JS9.WCS2Pix to be 1-indexed +
  • added ability to group and move regions +
  • box rotation is now around the center of the region +
  • all image coordinate are now 1-indexed throughout +
  • fixed bug where adding a polygon pt didn't show until region was selected +
  • changed polygon points to an array of objects {x, y} instead of just x, y +
  • fixed various layout bugs in plugins +
  • updated emscripten to latest version +
  • updated flot to latest version +
  • updated jquery to 1.11.1 +
+ +

Beta Release 13 (April 6, 2014)

+
    +
  • added support for handling NaN values +
+ +

Beta Release 12 (March 10, 2014)

+
    +
  • added support for browser-based analysis via plugins (JS9.RegisterPlugin) +
  • converted Menubar, Info, Panner, Magnifier to plugins +
  • initial version of imexam plugin available (in plugins directory) +
  • initial version of archive/catalog server plugin available +
  • added support for zscale (IRAF min/max algorithm for scaling) +
  • added support for user scale limits +
  • regions can now be moved off the image +
  • shift key disables mouse plugin callbacks +
  • zooming a small image will use all of the available display canvas +
  • added support for sub-pixel zooming +
  • added ability to process all keys in keypress callback +
  • added arrow key support for moving regions +
  • added fractional pixel positions for zoomed images +
  • fixed bug which reset pan when changing colormaps on a zoomed image +
  • added strict mode +
  • upgrade emscripten to 1.8.2 +
+ +

Beta Release 11 (December 18, 2013)

+
    +
  • initial port to iPad +
  • removed notifyHelper message when mouse enters image window +
  • fixed tpos crash when converting really large images +
  • updated jquery.contextMenu.js +
+ +

Beta Release 10 (December 9, 2013)

+
    +
  • added support for RGB composite display +
  • added support for reading in auxiliary files via auxFiles preference +
  • added support for overlaying FITS image masks +
  • added support so that drag and drop files can be found by local analysis +
  • added analOpts.dataPath to specify where to look for drag and drop files +
  • box regions need to rotate around upper left point to ensure consistency +
  • changed name of fitshelper to js9helper +
  • changed JS9.submitAnalysis() to JS9.SubmitAnalysis() +
  • changed analOpts.datadir to analOpts.dataDir +
  • removed wcs event processing from node and CGI helper (use browser wcs) +
  • js9helper not run as a server from js9Helper.js any more (scales better) +
  • added ability to turn off redraw when creating a large number of regions +
  • fixed bug in panner display for non-square images +
  • added work-around for Google Chrome v31 bug (regions not drawn) +
+ +

Beta Release 9 (October 23, 2013)

+
    +
  • added support for client-based WCS using emscripten 1.5.6 +
  • added drag and drop of FITS images (binary tables are coming) +
  • added support for region callbacks (executed when a region changes) +
  • added JS9.Regions() public routine to retrieve and modify selected regions +
  • added Close Image button to File menu +
  • reduced size of panner when created by View menu +
  • updated Kinetic.js to v4.7.2 +
  • minor bug fixes (e.g., annuli strokeWidth not resizing properly) +
+ +

Beta Release 8 (September 23, 2013)

+
    +
  • fixed security in node.js support by requiring use of wrapper scripts +
  • added support for CGI-based back-end helpers +
  • implemented automatic discovery of analysis definitions +
  • added timer-based management of WCS update requests +
  • updated socket.io to 0.9.16 +
  • changed routine name from JS9.preloadImages() back to JS9.Preload()! +
+ +

Beta Release 7 (August 19, 2013)

+
    +
  • fits2png: added support for "%cookie" in odir specification +
  • js9.js and js9Helper.js both now use js9Prefs.json for setting preferences +
  • fixed bug in display/manipulation of panner when image is zoomed +
  • added "none" as an analysis return type to support hidden analysis +
  • changed routine name JS9.Preload() to JS9.preloadImages() +
  • added clipping to region manipulation +
  • fixed region strokewidth problem when zooming image +
  • fixed magnifier and panner where multiple instances of js9 are present +
  • numerous changes to pass new JSLint rules +
  • upgraded jquery to 1.10.2 +
  • upgraded jquery.flot to 0.8.2 +
  • removed references to of jquery-ui in demo files (its not used) +
+ +

Beta Release 6 (July 22, 2013)

+
    +
  • added support for panner window, including ability to zoom the panner +
  • added support for magnifier window, including ability to change magnification +
  • implemented zoom menu (zoomIn, zoomOut, zoom1, zoom2, zoom4, zoom8) +
  • added support for all FITS data types (silrd) in js9.js and tpos.c +
  • png file now contains FITS header in json format +
  • NB: the format of the PNG representation file has changed substantially! +
  • raw arrays now implemented as a typed array, using DataView to unpack it +
  • updated Kinetic.js to v4.5.4 (multiple changes required to code) +
+ +

Beta Release 5 (May 20, 2013)

+
    +
  • added support for dynamic creation of js9 instances (new or light window) +
  • added support for pre-loading images into a js9 on page load +
  • added support for running analysis Web page buttons, forms, etc. +
  • added support for printing the image +
  • added new demo pages +
  • changed js9msg script name to js9 +
  • loading javascript files is "generic" (no version numbers in filenames) +
  • updated Kinetic.js to v4.5.1 +
+ +

Beta Release 4 (April 26, 2013)

+
    +
  • added support for polygon regions +
  • added support for fixing (i.e. freezing) regions in place +
  • added support for container regions (constrain position of other regions) +
  • added support for shift key accelerator +
  • fixed multiple bugs in region listOnChange support +
  • updated Kinetic.js to v4.4.3 +
+ +

Beta Release 3 (April 2, 2013)

+
    +
  • updated Kinetic.js to v4.4.0 to fix new chrome v26.0.1410.43 (whoah!) +
+ +

Beta Release 2 (April 1, 2013)

+
    +
  • added support for executing analysis from console window +
  • added support for messaging to js9 via Node-based js9Msg.js +
  • added ability to specify params to region creation +
  • added server mode and input from stdin to js9Msg.js +
+ +

Beta Release 1 (February 27, 2013)

+
    +
  • initial beta release with support for displaying FITS images, scaling, +colormaps, external analysis, regions, wcs +
+ +
Last updated: June 14, 2014
+
+ + + diff --git a/help/extmsg.html b/help/extmsg.html new file mode 100644 index 00000000..80fc46fa --- /dev/null +++ b/help/extmsg.html @@ -0,0 +1,192 @@ + + + + + +
+External Communication with JS9 +

External Communication with JS9

+ +

+The JS9 Analysis menu provides flexible support for running a +macro-expanded external analysis command on the Web server and +displaying results in the browser. But there are other scenarios in which +it might be desirable for an external process to communicate with the +JS9 client: + +

    +
  • JS9 might be part of a larger Web-based analysis system +(i.e. instead of the analysis being incorporated into the Analysis +menu). An analysis task might want to query JS9 for its regions. +
  • A Web site might offer "live" tutorials in which JS9 in the +browser is manipulated automatically from the server. +
  • A Web site might wish to modify a JS9 client's user interface based +on the level of expertise of a given user. +
  • A user running JS9 locally might want to interact with her JS9 client from within a local analysis script. +
  • A remote user might want to interact with her JS9 client in a similar way. +
+ +

+If you run the Node.js-based helper (instead of the CGI helper), this +sort of external communication is supported by the js9 script +and its underlying js9Msg.js. The script runs +Node.js with js9Msg.js as its first argument. Using command +line syntax, it will send a single JS9 command to the browser and +return the results: +

+  sh> js9 cmap heat        # change colormap to heat
+  OK
+  sh> js9 cmap             # return the current colormap
+  heat
+
+

+Alternatively, if no command-line arguments are specified, js9 will +enter a "read-line" loop, executing commands as they are input: +

+  sh> js9 
+  JS9> cmap heat
+  OK
+  JS9> cmap
+  heat
+
+

+You also can send multiple commands to the script's standard input: +

+  sh> cat test.reg
+  region circle {"x":588, "y":590, "radius":30, "tags":"source"}
+  region circle {"x":588, "y":590, "radius":10, "tags":"exclude"}
+  region circle {"x":390, "y":430, "radius":50, "tags":"background"}
+  region circle {"x":390, "y":430, "radius":10, "tags":"background,exclude"}
+  sh> cat test.reg | js9    # send regions to JS9
+
+(Note: currently, redirecting to stdin does not appear to display +return messages. We'll fix this in a future release.) + +

+A list of available JS9 commands can be retrieved using the ''help' command: +

+  sh> js9 help
+  analysis     	run/list analysis for current image (ana)
+  colormap     	set/get colormap for current image (cmap)
+  colormaps    	get list of available colormaps (cmaps)
+  help     	get list of available commands
+  helper     	get/set helper connection
+  image     	get name of currently loaded image or display specified image
+  images     	get list of currently loaded images
+  load     	load image(s)
+  pan     	set/get pan location for current image
+  pix2wcs     	get image pixel value for specified wcs position
+  print     	print image window
+  regions     	add region to current image or list all regions (reg, region)
+  scale     	set/get scaling for current image
+  scales     	get list of available scales
+  url     	display a url
+  wcssys     	set/get wcs system for current image
+  wcsu     	set/get wcs units used for current image
+  wcssystems   	get list of available wcs systems
+  wcsunits     	get list of available wcs units
+  wcs2pix     	get wcs position for specified image pixel
+  zoom     	set/get zoom for current image
+
+These are the same commands that are available to the JS9 light-weight +Console window. + +

+One of the most important JS9 commands is the 'region' command, which +will create a new region or display the current region(s): +

+  sh> js9 region circle
+  OK
+  sh> js9 regions
+  ICRS; circle(23:23:26.929, +58:48:50.381, 14.76")
+
+

+Region-specific properties can be supplied in JSON format after the +shape is specified (see http://www.json.org/). You can pass any +property value found in the JS9.Regions.opts object. For example: +

+  sh> js9 region circle '{"x":495, "y":495, "radius":25, "color":"yellow"}'
+  OK
+
+

+The js9 script can talk to a JS9 instance if the script is run from: +

    +
  • the local host running the Web service and back-end helper +
  • the same host that is running the target browser, regardless of +where the helper resides +
+Note that the js9 script on one host cannot communicate with a +target browser on another host (unless the first host is the helper host). +

+If a JS9 instance is connected to a helper on a remote host, you can +use the -helper switch to specify the remote host to +contact. For example, if the helper is running on js9.cfa.harvard.edu, +you can send a command to your instance of JS9 this way: +

+  sh> js9 -helper js9.cfa.harvard.edu region circle
+  OK
+
+

+If more than one instance of JS9 appears on a single Web page, the +-id switch can differentiate between instances. The value of +the id switch is the div id for that JS9 instance. For example, if +two instances of JS9 having div ids of "JS9" and "myJS9" are defined +on the same page, then js9 can communicate with the latter in this way: +

+  sh> js9 -id myJS9 region circle
+  OK
+  sh> js9 -id myJS9 region 
+  ICRS; circle(23:23:26.929, +58:48:50.381, 14.76")
+
+or, from the readline loop: +
+  sh> js9 -id myJS9
+  JS9> region circle
+  OK
+  JS9> region -id myJS9
+  ICRS; circle(23:23:26.929, +58:48:50.381, 14.76")
+
+

+Putting the last two techniques together, you can talk to one of many JS9 +instances on a page connected to a remote helper this way: +

+  sh> js9 -helper js9.cfa.harvard.edu -id myJS9 cmap heat
+  OK
+
+

+A final esoteric note: special considerations are required when a helper +host wants to talk to one of several instances of JS9 connected to the +helper. Being on the same host as the helper, the js9 script is +allowed to send messages to any of these clients. But for security +reasons, it can only send a message to an individual browser, not to all +browsers at once. If the target browser's ip address is known, +the -browser switch can be used to differentiate browsers +running the same page. For example, if you want to talk to the JS9 +client browser on bynars: +

+  sh> js9 -browser bynars.cfa.harvard.edu -id myJS9 region circle
+  OK
+  sh> js9 -browser bynars.cfa.harvard.edu -id JS9 region 
+  ICRS; circle(23:23:26.929, +58:48:50.381, 14.76")
+
+or, from the readline loop: +
+  sh> js9 -browser bynars.cfa.harvard.edu -id myJS9
+  JS9> region circle
+  OK
+  JS9> region 
+  ICRS; circle(23:23:26.929, +58:48:50.381, 14.76")
+
+

+The js9 interface will evolve to meet the needs of the astronomical +community. + +

Last updated: September 4, 2014
+
+ + + diff --git a/help/helper.html b/help/helper.html new file mode 100644 index 00000000..5b0fface --- /dev/null +++ b/help/helper.html @@ -0,0 +1,231 @@ + + + + + +
+Adding a JS9 Server-side Helper +

Adding a JS9 Server-side Helper

+ +

Do You Need a Server-side Helper? Which One?

+JS9 supports server-side analysis on FITS data, allowing you to +execute virtually any command-line analysis program from JS9, run that +analysis command on the back-end, and view results on your Web page. +

+The server-side analysis capability is especially useful for archive +centers, but also can be attractive to individual users who want to +integrate their own data analysis programs into JS9. You configure a +JS9 server-side helper by adding additional switches to the configure +command described in Installing JS9. + +

+JS9 supports two techniques for server-side analysis: you can use your +own Web server as the JS9 back-end helper using CGI calls, or you can +run a separate Node.js-based server to process JS9 back-end +requests. The Node.js server-side helper is faster and more flexible +than the CGI helper (e.g., it supports messaging between the command +line and the browser). However, it obviously requires installation of +Node.js, and uses its own socket port to communicate with the outside +world. You should decide which server-side helper to use before +running configure. Please contact us if you want to discuss the +issues. + +

Consider Adding Analysis Tasks

+

+When configuring server-side analysis, you add server-side analysis tasks +to JS9 (or change the default analysis tasks) by adding or modifying +json files in the analysis-plugins directory (and optionally, +by adding wrapper files to the analysis-wrappers directory.) +See Server-based Tasks for a description of +how to configure server-side analysis tasks for your site. + +

+[Esoteric note: one of the plug-in files in +the analysis-plugins directory is the fits2png.json +plugin. This file specifies the command line for the fits2png +conversion program. If you wish to change that command line, it should +be done before building the system, since the CGI processing +script js9Helper.cgi is generated using this information.] + +

Add Switches to Configure the Server-side Helper

+

+JS9 is built using the standard GNU ./configure; make; make +install technique. When configuring server-side analysis, you will +add switches to the configure command line. The most important of +these switches are: +

+--prefix=[path]         location to install the non-Web programs and scripts
+--with-helper=[type]    type of server-side helper: nodejs, get or post (for CGI)
+
+to specify the program install directory and the type of server-side +helper you are using. Other important switches are: +
+--with-cgidir=[path]     cgi install directory e.g. /var/www/public_html/cgi-bin
+--with-cgiurl=[url]      cgi url relative to the Web root, e.g. ./cgi-bin/js9
+--with-cgixpath=[dirs]   directories to add to cgi path
+--with-funtools=[path]   funtools directory for build e.g. /soft/funtools
+--with-png=[path]        directory containing lib/png e.g. /usr/local
+
+ +

+Non-Web files, programs, and scripts (e.g., js9helper and fits2png) +will be installed in accordance with the --prefix=[dir] switch. +The default is /usr/local. + +

+If you want to utilize the Node.js-based helper, you do not have to +add any special nodejs switches. If you want to utilize a CGI-based +back-end, you must specify the --with-cgidir +and --with-cgiurl switches on the configure command +line. Optionally, you also can specify the +--with-cgixpath switch if you want to add directories to the CGI path: + +

    +
  • The --with-cgidir switch specifies the directory into which to +install the js9Helper.cgi wrapper script. That script is generated by +the build. All CGI requests are processed through this js9Helper.cgi wrapper. + +
  • The --with-cgiurl switch specifies the URL of the +js9Helper.cgi script relative to your Web document root. The +value of this switch is combined with the CGI wrapper filename and the +result stored in the js9Prefs.json file, telling JS9 how to call the +CGI back-end helper script. + +
  • The --with-cgxpath switch specifies a semi-colon delimited +list of directories to add to the CGI path. You can use this switch to +make accessible the executables that will be used in your CGI +processing. Of course, setting up the CGI path also can be done in +many ways, e.g., inside your analysis wrapper scripts or even in the +Web server itself. +
+ +

+The build of the JS9 server-side tpos program (which converts FITS +files to the JS9 representation file) requires the libpng library. If +libpng is not already installed on your system, it is available at: +

+    http://www.libpng.org/pub/png/libpng.html
+
+Of course, Linux users can install libpng in the "usual way", e.g. for CentOS: +
+    sudo yum install libpng-devel
+
+Any relatively modern version of the png library should suffice +(subject to security fixes, etc.) +

+[Esoteric note: It sometimes happens that incompatible png versions +1.2 and 1.5 are installed on the same machine. This can lead to link +errors if the include file from one version is used with the libraries +from another. If this happens on your system, you can tell configure +where to look for the libraries and include files of one version only +using the --with-png=[dir] switch.] + +

+The build of the JS9 tpos program also requires the funtools package. +Funtools is available on the JS9 Web site: +

+    http://js9.si.edu
+
+To tell configure where funtools libraries and executables are +located, use the --with-funtools=[dir] switch, +e.g. --with-funtools=/usr/local will find the funtools libraries in +/usr/local/lib. +

+Example configure commands are shown below for a typical Linux Apache setup +and for a personal Mac setup: +

+  linux-cgi)
+  ./configure 	--prefix=/soft/saord					\
+		--with-helper=get					\
+		--with-webdir=/var/www/htdocs/js9			\
+		--with-cgidir=/var/www/cgi-bin/js9			\
+		--with-cgiurl=./cgi-bin/js9				\
+		--with-cgixpath=/soft/saord/bin				\
+		--with-funtools=/soft/saord				\
+		--with-png=/soft/saord/linux64				\
+  		CC=gcc $*
+
+  mac-nodejs)
+  ./configure 	--prefix=$HOME						\
+		--with-helper=nodejs					\
+		--with-webdir=/Users/me/Sites/js9			\
+		--with-funtools=/usr/local				\
+		CC=gcc $*
+
+
+In these examples, the JS9 Web files (JavsScript, CSS etc.) will be +installed in a js9 sub-directory of htdocs in the /var/www directory +or in the Mac user's personal Sites directory. JS9 CGI files will be +installed in a subdirectory of the cgi-bin directory. C programs and +shell scripts will be installed in sub-directories of the user's home +directory. Funtools is located in /soft/saord or /usr/local (i.e. with +executables in /soft/saord/bin and libraries in /soft/saord/lib. etc.). + +

Build the JS9 System

+

Once the configure arguments are set up, you run configure, etc. +as described in the basic install instructions at: +Installing JS9. +

+Some additional notes on getting the server-side helpers working are +added below. + +

Notes on the CGI-based Server-side helper

+ +

+All JS9-specific CGI files and programs should have been built and installed +during the standard configure, make, make install process. In +particular, the globalOpts.helperType variable in the +js9Prefs.json file should have a value of "get" (or you can use +"post", if you reset the value manually. Not sure why you would do +this but ...) + +

+Of course, you must now ensure that your Web server can run the +js9Helper.cgi script successfully to execute JS9 CGI commands. Normal +Web debugging techniques come into play here: check the CGI section of +your Web server's configuration file and review the Web access and +error logs. If you continue to have problems, please let us know and +we will try to help. + +

Notes on Installing the Node.js-based Server-side helper

+

+The Node.js server-side helper is noticeably faster than CGI. It also +offers more power and flexibility, e.g., the node server supports +external control of the browser from the command line via the + and it's underlying js9Msg facility +(see

  • External Messaging with JS9 for +more information). However, Node.js requires that you open another +Internet port to the outside world. + +Node is available at: +
    +    http://nodejs.org/
    +
    +Once Node.js is installed, you must start the server-side helper from the JS9 +Web install directory: +
    +    node js9Helper.js >& node.log &
    +
    +Unlike CGI, Node can be run as any user: it does not have to be run as +the http daemon user. It certainly should not be run as root! We run +it as a non-privileged user with sufficient permissions to run analysis +programs. In any case, it should be run with its Unix PATH set to +include the directory containing the JS9 helper program, as well as +any analysis programs that will be executed by the JS9 server-side +helper when requested by the client. + +

    +Clients will automatically connect to the Node.js helper when an image +is loaded into JS9. The server-side helper listens on a port specified +in the js9Prefs.json file by the globalOpts.helper.Port value. The +default is 2718, but you can change this to any open port you like. + +

    Last updated: September 4, 2014
    +
  • + + + diff --git a/help/install.html b/help/install.html new file mode 100644 index 00000000..02f2ac20 --- /dev/null +++ b/help/install.html @@ -0,0 +1,154 @@ + + + + + +
    +Installing JS9 +

    Installing JS9

    + +

    Summary for the Impatient

    +
      +
    • retrieve and unpack the source code tar file or clone the js9 repository +
    • JS9 is now ready for drag-and-drop image files using the file:// URI +
    • to install JS9 into a Web server tree, run configure with this switch: +
      +  ./configure --with-webdir=[path] where path specifies the location to install the JS9 Web files
      +
      +
    • edit the js9Prefs.js to set up your site-specific JS9 parameters +
    • build, install, clean up: make; make install; make clean +
    + +

    Retrieve and Unpack the Source Code Tar File

    +

    +The current JS9 source tar file is available at: +

    +    http://js9.si.edu
    +
    +The source tar file will unpack into a js9-[version] directory with +the usual tar command, e.g: +
    +    tar xfz js9-[version].tar.gz
    +
    +You also can clone JS9 from github: +
    +    https://github.com/ericmandel/js9
    +
    + +

    Run JS9 using the file:// URI

    +Once the tar file is unpacked, you should be able to load any of the +js9*.html Web pages into your browser using the file:// URI. For +example, if you unpacked the tar file into /Users/me on a Mac, then +you can point your browser to: +
    +    file:///Users/me/js9-[version]/js9basics.html
    +
    +to see the basic JS9 demo page. You then can drag any FITS image file onto +the JS9 display and view it, change contrast/bias, colormaps, +scale, create regions, etc. Furthermore, if you load the imexam Web page: +
    +    file:///Users/me/js9-[version]/js9imexam.html
    +
    +you can move a region around and run browser-based analysis as +the region changes. +

    +NB: The file://URI does not work in Google Chrome: Chrome doesn't +permit a local HTML file to read other local files. The workaround is +to start Chrome with the --allow-file-access-from-files switch: +

    +    # Linux:
    +    chrome --allow-file-access-from-files
    +    # Mac:
    +    open /Applications/Google\ Chrome.app --args --allow-file-access-from-files
    +
    +Firefox and Safari do not have this restriction. +

    +If you just want to run JS9 in this simple way, you are done. However, +you might want to edit the js9Prefs.json file to set up default values +for colormaps, scaling, etc. See: +JS9 Site Preferences for a +description of the available parameters. + +

    Do You Want to Install JS9 in a Web Server?

    If you want to +run JS9 in a "real" Web server tree, build and install the JS9 tools and +files using the standard GNU ./configure; make; make install +technique. You should run configure with +the --with-webdir=[path] switch, which specifies the directory +into which the JS9 Web files (JavaScript, CSS, etc.) will be +installed. We recommend that this directory only contain the +installed JS9 files, i.e. that you install JS9 into its own +self-contained directory. This will make upgrading to new versions +much easier. + +

    Do You Want to Configure Server-side Analysis?

    +

    +JS9 supports server-side ("back-end") analysis on FITS data using a +server-side helper. This capability allows you to execute virtually +any command-line analysis program from JS9. The analysis command is +run on the back-end server and results viewed on your Web page. You can +utilize your own Web server as the JS9 back-end helper using CGI +calls, or you can run a separate Node.js-based server to process JS9 +back-end requests. The server-side analysis capability is especially +useful for archive centers, but also can be attractive to individual +users who want to integrate their own data analysis programs into JS9. +

    +In addition, JS9 supports communication with external processes via the +js9 script. This capability requires the configuration of a +Node.js-based server-side helper. +

    +You configure a JS9 back-end helper by adding additional switches to +the configure command. See: +Installing a Server-side Helper +for details. + +

    Build the JS9 System

    +Once you have decided on the configuration of your JS9 system, run +configure to generate various build files: +
    +  ./configure [your JS9 switches]
    +
    +

    +and then build the JS9 system using the make command: +

    +   make
    +
    + +

    Finalize Your Site Preferences

    +

    +When JS9 is loaded into your browser, it reads a file called +js9Prefs.json from the JS9 Web directory. This file contains +various default settings for JS9, e.g. default colormap and scale for +image display. Feel free to edit this file to set up your own +site-specific parameters. See +JS9 Site Preferences for a +description of the available parameters. + +

    Install the JS9 System

    +

    When the build is completed, you can install the JS9 into your Web tree: +

    +    make install
    +
    +

    +and then clean up the build directory using the command: +

    +    make clean
    +
    +

    Optionally Install the JS9 Test Data Files

    +

    +If you want to display our test data files in the JS9 demo pages, +retrieve the JS9 data file tar file from the JS9 Web site: +

    +    http://js9.si.edu
    +
    +and untar it into the JS9 Web install directory. This will create +sub-directories containing the image data. + +
    Last updated: September 4, 2014
    +
    + + + diff --git a/help/knownissues.html b/help/knownissues.html new file mode 100644 index 00000000..662fb699 --- /dev/null +++ b/help/knownissues.html @@ -0,0 +1,87 @@ + + + +JS9 Known Issues + + +
    +

    JS9 Known Issues

    + +
      +
    1. All platforms, especially Chrome (June 21, 2014 : NOT resolved) +

      +Available memory can be a problem when loading very large gzip'ed FITS +files, especially in 32-bit Chrome. JS9 currently reads the entire +FITS file or gzip'ed file and inflates parts as needed. It can process +files up to approx. 200Mb in size before Chrome runs out of heap +space. Note that Chrome often will load an ungzip'ed FITS file in +cases where the gzip'ed file fails (though there still are upper +limits on the total space available). We hope that the 64-bit version +of Chrome (in early Canary release as of 7/1/2014) will alleviate +these problems. Otherwise, we will take a more drastic approach to +memory management within JS9 (at the expense of speed). + +

    2. All platforms (June 21, 2014 : NOT resolved) +

      +The zscale algorithm requires allocation of a fixed-size static memory +buffer. We have limited the size of this secondary buffer to be large +enough to handle a 4096 x 4096 x 4-byte image. If your image is larger +than this, zscale will not run. We will revisit the size of the +static buffer as we gain more experience with the size of images being +analyzed (or eventually rewrite the algorithm). + +

    3. All platforms (June 13, 2014 : NOT resolved) +

      +When resizing a box region in one direction only (i.e., width or +height), the width of the region's border will be different in each +direction. This is due to the underlying graphics algorithm used to +resize the region, which changes the scale factor in each direction +individually and ties the border width to that scale factor. We will +fix this in a future release. + +

    4. All platforms using Chrome (March 27, 2014 : resolved) +

      +One of the simplest ways to use JS9 locally is by means of the file:// +URL scheme, e.g., point your browser to file:///home/me/js9/js9basics.html. +

      +This does not work in Google Chrome because Chrome does not permit a +local HTML file to read other local files. You can read a relatively +emotional argument about this restriction at: +

      +    https://code.google.com/p/chromium/issues/detail?id=37586
      +
      +

      +The workaround is to start Chrome with the +--allow-file-access-from-files switch. On Linux: +

      +    chrome --allow-file-access-from-files
      +
      +On a Mac: +
      +    open /Applications/Google\ Chrome.app --args --allow-file-access-from-files
      +
      + +
    5. All platforms (May 20, 2013: resolved) +

      +If the "load image" command is part of a group of commands passed to +the js9 script, a race condition can occur when subsequent commands +are executed before the image is fully loaded. To avoid this problem, +images should be loaded in a separate js9 command and the load status +checked for completion before proceeding to manipulate the image. See +the js9load script for details (or just use the script itself +to load images). (Technical details: images are loaded asynchronously, +so that other parts of the Web page are available during the load +process. A synchronous load could freeze the Web page while +loading. To avoid this situation, external processes should use the +"status load" command to check for a completed load before sending +further processing commands). + +

      Last updated: September 4, 2014
      +
    + + + diff --git a/help/localtasks.html b/help/localtasks.html new file mode 100644 index 00000000..e4168f3a --- /dev/null +++ b/help/localtasks.html @@ -0,0 +1,219 @@ + + + + + +
    +Local (Browser-Based) Analysis Tasks +

    Adding Local (Browser-Based) Analysis Tasks to JS9

    + +

    +JS9 supports the ability to perform local analysis, i.e. tasks +executed in your browser (not on the back-end server). This is +accomplished by offering access to the image data and region +information via a +JS9 Public API. Obviously, all of JS9 +JavaScript code is available to you within a Web page, but the public +API is designed to stable and well-documented. + +

    +Adding Simple Analysis Tasks to Your Web Page +

    +For simple analysis (i.e., no mouse or keyboard event processing), it +often is sufficient to define GUI elements directly on the Web page, +adding Javascript code to interact with these elements and call the +public JS9 functions as needed. In particular, +the JS9.GetImage() function will return a handle for the +currently displayed image and the the various JS9.Region +functions allow you to manipulate regions. These routines are +described in the JS9 Public API. + +

    +The js9onchange.html demo Web page illustrates these simple +capabilities. It shows how to run a task every time a region +changes, i.e. when it is moved, resized, or deleted. This is +accomplished by setting the JS9.Regions.opts.onchange +parameter to a function (if you are setting via JavaScript) or a +string routine name (if you are setting via json in the prefs file): +

    +    // via JavaScript    
    +    JS9.Regions.opts.onchange = myRegionChanged;
    +
    +or: +
    +    // from within js9Prefs.json
    +    { ... "Regions.opts":  {"onchange": "myRegionChanged"} ... }
    +
    +The calling sequence of the xeqonchange function is: +
    +    function myRegionChanged(im, xreg)
    +
    +where im is the image handle of the currently displayed image, and +xreg is an object containing information about the changed region. +See below for a description of the returned region +object. Note that you can turn off region change processing for +individual regions or for all regions by means of the xeqonchange +menu option in a given region's context menu or the global Regions menu, +respectively. + +

    +The js9onchange.html demo Web page also shows how +server-side JS9 analysis tasks can be executed directly from the +Web page using HTML elements (buttons, forms, etc.) instead of the +Analysis menu. See Server-side +Analysis Tasks for more information. + +

    +

    Adding Plugins to Your Web Page

    +

    +For anything other than the simplest analysis, you can write a JS9 +Plugin module. A plugin is a Javascript module that contains +a constructor function to create a plugin GUI, and, optionally, +one or more event callbacks to process desired events. At the +end of the file, the plugin calls RegisterPlugin() to make +itself known to JS9. Plugin modules should be stored in the +js9/plugins directory (or in a sub-directory therein) and should be +loaded into JS9-enabled Web pages after js9.js itself is loaded. + +

    +To create instances of the plugin GUI, the constructor function gets +called for each plugin div defined on the Web page. +The this context is seeded with a few JS9 properties, including: +

      +
    • this.div: the DOM element representing the div for this plugin +
    • this.divjq: the jquery object representing the div for this plugin +
    • this.id: the id of the div (or the plugin name as a default) +
    • this.winType: "div" (in-page div element) or "light" (from view menu) +
    • this.winHandle: handle returned from light window create routine +
    • this.display: the display object associated with this plugin +
    • this.plugin: plugin class object (contains user opts in opts sub-object) +
    • this.status: "active" or "inactive" or undefined +
    +The most important of these properties is the div property +specifying the DOM element of the containing div. You add your GUI +(HTML elements) to this.div and use the events to control +the action. The type property tells you whether the instance is +being created for an in-page div element or from the View menu, in +case configuration is different for these cases. +The plugintest.js module +provides a fairly complete example and should be studied in +conjunction with this help page. + +

    +A JS9 plugin is registered at the end of the module using +the JS9.RegisterPlugin() public routine: +

    +  JS9.RegisterPlugin(xclass, xname, func, opts)
    +
    +where: +
      +
    • xclass: class of the plugin +
    • xname: name of plugin +
    • func: the constructor function +
    • opts: an object containing plugin options +
    +The xclass and xname values together make up +the class of the div element. Thus, if the plugin xclass +is "JS9" and the plugin xname is "Menubar", then the div which +will hold the menubar has a class of "JS9Menubar". Note that these +strings must adhere to CSS grammar rules, e.g. start with a letter, +followed by letters, numbers, dashes and underscores, no spaces allowed. +

    +This class/name separation has been made so that multiple plugins can +be written as part of one class and processed together as part of that +class, e.g., displayed together in the View and Help menus. +

    +The optional opts object contains the following elements, +all of which also are optional: +

      +
    • onmouseup: callback function(im, ipos, evt) for mouse up events +
    • onmousedown: callback function(im, ipos, evt) for mouse down events +
    • onmousemove: callback function(im, ipos, evt) for mouse move events +
    • onmouseover: callback function(im, ipos, evt) for mouse over events +
    • onmouseout: callback function(im, ipos, evt) for mouse out events +
    • onkeypress: callback function(im, ipos, evt) for keypress events +
    • on[layer]change: function(im, xreg) for when a shapes changes in a layer (e.g. onregionschange for region changes) +
    • onimageload: callback function(im) when an image is loaded +
    • onimagedisplay: callback function(im) when an image is (re)displayed +
    • divArgs: [arg1, arg2, ...] arguments passed to div-based constructor +
    • menuItem: menuname in specified menu (default is View menu) +
    • menu: add plugin to this menu (only View or Analysis right now!) +
    • winDims: [width, height] +
    • winTitle: string +
    • toolbarHTML: string +
    • toolbarSeparate: boolean +
    • help: path html file for help, relative to js9/plugins directory +
    +

    +Each of the callback functions are routines which get executed when +the specified event takes place. The routines are passed the following +arguments: current image object handle, the 1-indexed image position +of the mouse and, for all but the on[layer]change, +onimageload and onimagedisplay routines, the original event +that triggered the callback. The on[layer]change callback gets +passed the same xreg object as is used for the +JS9.Regions() routine and the JS9.Regions.opts.onchange +parameter. See below for a description of its contents. + +

    +Holding down the Shift key (where available) will turn off execution of all +mouse event callbacks. This allows you to move the mouse to a specific +location, and then move away without triggering a callback. The +xeqonchange menu option in the Regions menu and each region's +context menu can be used to turn off execution of the region onchange callback. +The former does this globally, the latter only for the specific region. + +

    +The divArgs is an array specifying arguments to pass to the constructor +function, when a div element is found in the Web page. For example, the Panner +and Magnifier plugins pass a width and height to the constructor in this way. + +

    +The menuItem is a string which specifies the name that will be +used in the View menu when a plugin div is not found on the Web +page. If no menuItem is specified, the plugin will not appear +in the View menu. + +

    +Furthermore, the menu property can be used to change the menu +in which the above-mentioned menuItem plugin will be +placed. For example, an Imexam plugin situates +its plugins in the Analysis menu instead of the View menu. NB: At the +moment, only the View and Analysis menus are supported +for placement. + +

    +The winDims is an array specifying the width and height of the +light window that will get created for this plugin via the View menu. +The winTitle is a string specifying the title of the light window. +The default is no title. + +

    +You can add HTML (e.g. command buttons) to the light window titlebar +by putting an HTML string into the toolbarHTML property. The +panner and magnifier use this technique to add zoom buttons. You also +can add HTML onto a Web-page plugin div, but in this case, where the +HTML is placed depends on the value of the toolbarSeparate +property. If the value of toolbarSeparate is true, then a +titlebar is created above the plugin and the HTML is added to it. +Otherwise, the HTML is placed in top of the plugin itself. + +

    +The help property specifies the pathname of an html file that will +be placed in the Help menu. This pathname should be relative to +the plugins directory. + +

    +Within a callback, you can use the JS9 Public API to manipulate data, as +detailed in the JS9 Public API. + +

    +

    Last updated: September 4, 2014
    +
    + + + diff --git a/help/preferences.html b/help/preferences.html new file mode 100644 index 00000000..3cff9f38 --- /dev/null +++ b/help/preferences.html @@ -0,0 +1,74 @@ + + + + + +
    +Site Preferences +

    Configuring JS9 Site Preferences

    + +

    +JS9 supports a site configuration file that is read after the +JavaScript variables are loaded but before JavaScript code is compiled +and executed. This file allow you to tailor JS9 to meet the needs of +your site without having to modify the js9.js file directly. + +

    +To support site configuration, JS9 tries to load a json file called +js9Prefs.json from the same server on which the main +js9-[version].js file resides. The file will be looked for first in +the same directory as the Web page and then in the js9 install directory. + +

    +This preference file can be used to override the default parameter +settings for JS9. A look through the beginning of JS9 code will show +a number of Javascript objects containing these default +parameters. They all have names ending in Opts, +i.e. JS9.imageOpts, JS9.analysisOpts, etc. A description of some of +these objects is given below: + +

      +
    1. JS9.globalOpts: this JavaScript object contains global +information, including parameters concerned with the back-end services +used by JS9. Currently, it allows you to specify the helperPort +on which to connect. Note that this same preference file is read the +Node-based js9Helper, so changing the helper port in this file will +change both the client and server. + +

      +

    2. JS9.imageOpts: This JavaScript object contains initial +values for image parameters such as: contrast, bias, +whether to invert the +colormap, colormap, scale, WCS system , WCS +units, whether to display value/position, and whether to +list regions when they change (listonchange). + +

    3. JS9.analOpts This JavaScript object contains +the dataDir option, which specifies the pathname prefix to add +to each FITS filename instead of the pathname stored in the PNG +file. You can set this variable if you have moved the location of the +raw FITS files after generating the PNG files. + +

    4. JS9.Regions.opts: This JavaScript object contains default +values for regions, including the initial size of various regions, +initial inner and outer radii for annuli, initial angle, etc. + +

    5. JS9.menuButtonOptsArr: this JavaScript array of objects allows +you to change and re-arrange which menu options are provided. If you +prefix the name of a menu option with '#', that option is disabled. + +

    +In addition to the above-mentioned objects, the preference file can be +used to set some internal variables. The JS9.DEBUG parameter is an +example, as shown in the default preference file. Ordinarily, users +need not be concerned with these variables. + +
    Last updated: September 4, 2014
    +
    + + + diff --git a/help/publicapi.html b/help/publicapi.html new file mode 100644 index 00000000..d2700c4c --- /dev/null +++ b/help/publicapi.html @@ -0,0 +1,1130 @@ + + + + + +
    +The JS9 Public API +

    The JS9 Public API

    + +

    +The JS9 Public API provides a JavaScript programming interface for +interacting with JS9. Obviously, all of JS9 JavaScript code is +available to you within a Web page, but the public API is designed to +stable and well-documented for users and Web designers. It also will +provide the basis for planned language bindings (python, perhaps C/Fortran). +

    +In general, the public API routines act on the current image being +displayed in the default JS9 div element. Since most Web pages will +have only a single JS9 div element, this behavior is usually what you +want. It parallels DS9's behavior in which XPA commands act on the +currently displayed image. For example, to change the colormap of the +current image, use: +

    +  JS9.SetColormap("cool");
    +
    + +

    +However, for cases where multiple JS9 div elements are defined on a +single page, you can specify the specific div element to process by +adding an display object argument to the calling sequence with +a single display property: +

    +  {display: [div_id]}
    +
    +where [div_id] is the id of the target JS9 div element. For example, +if two JS9 divs with ids "JS9" and "myJS9", respectively, are present +on a single Web page, you can set the colormap of the second one this way: +
    +  JS9.SetColormap("cool", {display: "myJS9"})
    +
    +Note that this display object contains only the display +property and always is specified as the final argument in a call. +

    +The display property can specify an image handle instead of +a JS9 div element id. This is a minor optimization for cases where you want +to call a routine such as JS9.WCSToPix() or JS9.PixtoWCS() many times: +

    +  var im = JS9.GetImage({display: "myJS9"});
    +  for(i=0; i<1000; i++){
    +    x = ...
    +    y = ... 
    +    wcs = JS9.PixtoWCS(x, y, {display: im});
    +    console.log("%s %s -> %s %s", x, y, wcs.ra, wcs.dec);
    +  }
    +
    +Passing the image handle will speed up processing very slightly, but +it makes us programmers feel much better. +

    +The optional display object argument is not explicitly +documented in the routines below (except as an example +in JS9.Load()), but it is always available. + +

    +Choose from the following sections: +

    + +

    +

    +Loading Images +
    + +

    +● Load an image into JS9 +

    +JS9.Load(url, opts, func) +

    +where: +

      +
    • url: url to load +
    • opts: object containing image parameters +
    • func: optional function to call when image load is complete +
    +

    +Load a FITS file or a PNG representation file into JS9. +To override default image parameters, pass the image opts argument: +

    +    href='javascript:JS9.Load("png/m13.png", {scale:"linear", colormap:"sls"});'
    +
    +

    +If a callback function is specified, it will be called after the image +is loaded: +

    +    href='javascript:JS9.Load("fits/3c273.fits", {scale: "linear"}, func);'
    +
    +The image handle is passed as the first argument to the callback. +

    +To load an image into a specified display, pass the display object as the last argument: +

    +    href='javascript:JS9.Load("fits/3c273.fits", {scale: "linear"}, {display: "myJS9"});'
    +
    +

    +

    +See Displaying Your Data for further discussion of +how to use this routine. + +

    +● Load an image into a light window or a new (separate) window +

    +JS9.LoadWindow(url, opts, type, html, winopts) +

    +where: +

      +
    • url: url to load +
    • opts: optional object containing image parameters +
    • type: "light" or "new" +
    • html: html for the new page (default is to display a menubar above the image) +
    • winopts: for "light", optional dhtml window options +
    +This routine will load an image into a light-weight window or an entirely new +window. The url and opts arguments are identical to the standard +JS9.Load() call. The type argument determines whether to create +a light-weight window or a new (separate) window. +

    +By default, the new window will contain a Menubar above an image display area: +

    +    <div class='JS9Menubar' id='[id]Menubar'></div>
    +    <div class='JS9' id='[id]'></div>
    +
    +You can use the html argument to supply different Web page elements +for the window. Furthermore, if you create a light window, a default +set of DynamicDrive dhtmlwindow parameters will be used to make the +window the correct size for the default html: +
    +    "width=512px,height=542px,center=1,resize=1,scrolling=1"
    +
    +You can supply your own parameters for the new dhtmlwindow using the +winOpts argument. See: + +DynamicDrive for more information about their light-weight window. +

    +See js9create.html for examples of how to use this routine. + +

    +● Load one or more images when the Web page is ready +

    +JS9.Preload(url1, opts1, url2, opts2, ... url2, optsn) +

    +where: +

      +
    • url: url to load +
    • opts: optional object containing image parameters +
    +This routine will pre-load images into a JS9 display when the Web page +is loaded and JS9 is initialized. It can be added to the Web page body +element using the onload() JavaScript call or called directly in a +JavaScript init routine. See index.html and js9preload.html for examples. + +

    +

    +Working with Images +
    +

    + +

    +● Get image handle for the current image +

    +im = JS9.GetImage() +

      +
    • im: image handle +
    +

    +The routine returns the image handle associated with the current image. +

    +The returned image handle can be passed in the display object. This +is marginally more efficient than the default behavior, which is to +determine the current image for each call. + +

    +● Get image data and auxiliary info for the specified image +

    +imgdata = JS9.GetImageData(dflag) +where: +

      +
    • dflag: true if you want the data returned (as an HTML5 typed array) +
    +

    +The image data object contains the following information: +

      +
    • id: the id of the file that was loaded into JS9 +
    • file: the file or URL that was loaded into JS9 +
    • source: "fits" if a FITS file was downloaded, "fits2png" if a representation file was retrieved +
    • imtab: "image" for FITS images and png files, "table" for FITS binary tables +
    • width: x dimension of image +
    • height: y dimension of image +
    • bitpix: FITS bits/pixel of each image element (8 for unsigned char, 16, 32 for signed integer, -32 or -64 for float) +
    • header: JavaScript object containing FITS header values +
    • data: if dflag is true, a pointer to HTML5 typed array +containing image data +
    +This call returns raw data for subsequent use in local analysis tasks. The data +buffer is a reference to the real data, so be careful about changing values. +

    +Given a FITS-standard 1-indexed image pixel x,y, you can find the data value +at that location using: +

    +    val = obj.data[Math.floor(y-0.5) * obj.width + Math.floor(x-0.5)];
    +
    +Note the need to integerize the x and y values: JavaScript arrays are +objects and so floating point array indices do not get truncated +automatically as in C. They will return null values. +

    +Also note that since we need 0-based data array indexes, we subtract 1 from +the 1-based image position. But then we must add 0.5 before rounding because +by convention, x.0, y.0 is the middle of the pixel. +

    +● Display an image +

    +JS9.DisplayImage(step) +

    +where: +

      +
    • step: starting step to take when displaying the image +
    +The display steps are: "colors" (remake color data when cmap has changed), +"scaled" (rescale data values), "primary" (convert scaled data values +to color values), and "display" (write color values to the Web page). +

    +The default step is "primary", which displays the image without recalculating +color data, scaled data, etc. This generally is what you want, unless you have +explicitly changed parameter(s) used in a prior step. + +

    +● Re-read the data from a FITS file and re-display +

    +JS9.RefreshImage(fitsobj, func) +

    +where: +

      +
    • fitsobj: new FITS object from which to take raw data for display +
    • func: optional function to call when image load is complete +
    +This routine can be used, for example, in laboratory settings where +data is being gathered in real-time and the JS9 display needs to be +refreshed periodically. The call takes a fits object as the second +argument. It will refresh the display using the new data contained in that +object. +

    +The fits object should contains the following properties: +

      +
    • naxis: number of axes in the image +
    • axis: array of image dimensions for each axis +
    • bitpix: FITS bitpix value +
    • image: typed data array containing current image data +
    • head: object containing header keywords as properties +
    • card: string version of the header with comments (optional) +
    • dmin: data min (optional) +
    • dmax: data max (optional) +
    + +

    +● Clear the image from the display and mark resources for release +

    +JS9.CloseImage() +

    +Each loaded image claims a non-trivial amount of memory from a finite +amount of browser heap space. For example, the default 32-bit version +of Google Chrome has a memory limit of approximately 500Mb. If you are +finished viewing an image, closing it tells the browser that the +image's memory can be freed. In principle, this is can help reduce +overall memory usage as successive images are loaded and +discarded. Note, however, that closing an image only provides a hint +to the browser, since this sort of garbage collection is not directly +accessible to JavaScript programming. +

    +Some day, all browsers will support full 64-bit addressing and this problem will +go away ... +

    +● Get the image colormap +

    +cmap = JS9.GetColormap() +

    +returns: +

      +
    • cmap: string containing colormap name +
    +Get the current colormap name. + +

    +● Set the image colormap +

    +JS9.SetColormap(cmap, [contrast, bias]) +

    +where: +

      +
    • cmap: colormap name +
    • contrast: contrast value (range: 0 to 10) +
    • bias: bias value (range 0 to 1) +
    +Set the current colormap, contrast/bias, or both. This call takes one +(colormap), two (contrast, bias) or three (colormap, contrast, bias) +arguments. + +

    +● Get the image scale +

    +scale = JS9.GetScale() +

    +returns: +

      +
    • scale: string containing scale name +
    +Get the current scale name. + +

    +● Set the image scale +

    +JS9.SetScale(scale, smin, smax) +

    +where: +

      +
    • scale: scale name +
    • smin: scale min value +
    • smax: scale max value +
    +Set the current scale, min/max, or both. This call takes one +(scale), two (smin, max) or three (scale, smin, smax) arguments. + +

    +● Get the image zoom factor +

    +zoom = JS9.GetZoom() +

    +returns: +

      +
    • zoom: floating point zoom factor +
    +Get the zoom factor. + +

    +● Set the image zoom factor +

    +JS9.SetZoom(zoom) +

    +where: +

      +
    • zoom: floating or integer zoom factor or zoom directive string +
    +The zoom directives are: +
      +
    • x[n]|X[n]: multiply the zoom by n (e.g. "x2") +
    • /[n]: divide the zoom by n (e.g. "/2") +
    • in|In: zoom in by a factor of two +
    • out|Out: zoom out by a factor of two +
    • toFit|ToFit: zoom to fit image in display +
    + +

    +● Get the image pan position +

    +ipos = JS9.GetPan() +

    +returns: +

      +
    • ipos: image position object containing x and y image +coordinate values +
    +Get the current pan position in image coordinates. + +

    +● Set the image pan position +

    +JS9.SetPan(x, y) +

    +where: +

      +
    • x: x image coordinate +
    • y: y image coordinate +
    +Set the current pan position using image coordinates. +Note that you can use JS9.WCSToPix() and JS9.PixToWCS() to +convert between image and WCS coordinates. + +

    +● Get the display coordinates from an event +

    +dpos = JS9.EventToDisplayPos(evt) +

    +where: +

      +
    • evt: a JavaScript event +
    +returns: +
      +
    • dpos: display position object containing x and y display +coordinate values +
    +If you define your own event callbacks, you can use this routine to convert +the event position to a display position, which can then be used to get the +image position (see below). + +

    +● Get the image coordinates from the display coordinates +

    +ipos = JS9.DisplayToImagePos(dpos) +

    +where: +

      +
    • dpos: display position object containing x and y display +coordinate values +
    +returns: +
      +
    • ipos: image position object containing x and y image +coordinate values +
    +Note that image coordinates are one-indexed, as per FITS conventions, while +display coordinate are 0-indexed. +

    +● Get the display coordinates from the image coordinates +

    +dpos = JS9.ImageToDisplayPos(ipos) +

    +where: +

      +
    • ipos: image position object containing x and y image +coordinate values +
    +returns: +
      +
    • dpos: display position object containing x and y display +coordinate values +
    +Get display (screen) coordinates from image coordinates. Note that +image coordinates are one-indexed, as per FITS conventions, while +display coordinate are 0-indexed. + +

    +● Update value/position information +

    +valpos = JS9.UpdateValpos(ipos, display) +

    +where: +

      +
    • ipos: image position object containing x and y image +coordinate values +
    • display: boolean value specifying whether the info box display should be updated (default is true) +
    +This routine determines the data value at a given image position +and returns an object containing the following information: +
      +
    • ix: image x coordinate +
    • iy: image y coordinate +
    • isys: image system (i.e. "image") +
    • px: physical x coordinate +
    • py: physical y coordinate +
    • psys: currently selected pixel-based system (i.e. "image" +or "physical") for the above px, py values +
    • ra: ra in degrees (if WCS is available) +
    • dec: dec in degrees (if WCS is available) +
    • wcssys: wcs system (if WCS is available) +
    • val: floating point pixel value +
    • val3: pixel value as a string truncated to 3 decimal digits +
    • vstr: string containing value and position info +
    • id: id of the image +
    • file: filename of the image +
    • object: object name of the image from the FITS header +
    + +

    +● Get the current WCS units +

    +unitsstr = JS9.GetWCSUnits() +

    +returns: +

      +
    • unitstr: "pixels", "degrees" or "sexagesimal" +
    +Get the current WCS units. + +

    +● Set the current WCS units +

    +JS9.SetWCSUnits(unitsstr) +

    +where: +

      +
    • unitstr: "pixels", "degrees" or "sexagesimal" +
    +Set the current WCS units. + +

    +● Get the current World Coordinate System +

    +sysstr = JS9.GetWCSSys() +

    +returns: +

      +
    • sysstr: current World Coordinate System ("FK4", "FK5", "ICRS", +"galactic", "ecliptic", "image", or "physical"); +
    +Get current WCS system. + +

    +● Set the current World Coordinate System +

    +JS9.SetWCSSys(sysstr) +

    +where: +

      +
    • sysstr: World Coordinate System ("FK4", "FK5", "ICRS", +"galactic", "ecliptic", "image", or "physical") +
    +Set current WCS system. The WCS systems are available only if WCS +information is contained in the FITS header. Also note that "physical" +coordinates are the coordinates tied to the original file. They are +mainly used in X-ray astronomy where individually detected photon +events are binned into an image, possibly using a blocking factor. +For optical images, image and physical coordinate usually are identical. + +

    +● Convert image pixel position to WCS position +

    +wcsobj = JS9.PixToWCS(x, y) +

    +where: +

      +
    • x: x image coordinate +
    • y: y image coordinate +
    +returns: +
      +
    • wcsobj: world coordinate system object +
    +

    +The wcs object contains the following properties: + +

      +
    • ra: right ascension in floating point degrees +
    • dec: declination in floating point degrees +
    • sys: current world coordinate system being used +
    • str: string of wcs in current system ("[ra] [dec] [sys]") +
    + +

    +● Convert WCS position to image pixel position +

    +pixobj = JS9.WCSToPix(ra, dec) +

    +where: +

      +
    • ra: right ascension in floating point degrees +
    • dec: declination in floating point degrees +
    +returns: +
      +
    • pixobj: pixel object +
    +The pixel object contains the following properties: + +
      +
    • x: x image coordinate +
    • y: y image coordinate +
    • str: string of pixel values ("[x]" "[y]") +
    + +

    +

    +Working with Regions +
    +

    +Spatial regions of interest are a crucial part of astronomical data +analysis. The regions layer is a special case of the more generalized +shape layers, automatically created by JS9 to support the options in +the Regions menu, as well as local and server-side data analysis +using regions. +

    +The regions layer has the special property that, by default, +its z-index is higher than other shape layers, so that regions +are displayed on top of other shape layers. +

    +Note that the GetRegions(), ChangeRegions(), RemoveRegions() calls +all take a regions specification as the second argument, which can be +any of the following (in order of precedence): +

      +
    • "all": all regions +
    • [id]: a specific region id returned by JS9.AddRegions() +
    • "selected": the selected region (or all regions in the selected group) +
    • [color]: all regions having the specified color (e.g., "red") +
    • [shape]: all regions having the specified shape (e.g., "circle") +
    • [tag]: all regions containing the specified tag (e.g., "source") +
    +Thus, it is possible to act on multiple regions at the same time. + +

    +● Add one or more regions to the regions layer +

    +id = JS9.AddRegions(rarr, opts) +

    +where: +

      +
    • rarr: a shape string, region object or an array of region objects +
    • opts: global values to apply to each created region +
    +returns: +
      +
    • id: id of last region created +
    +The rarr argument can be a region shape ("annulus", "box", +"circle", "ellipse", "point", "polygon", "text"), a single region +object, or an array of region objects. Region objects contain one or +more properties, of which the most important are: +
      +
    • shape: "annulus", "box", "circle", "ellipse", "point", "polygon", "text" [REQUIRED] +
    • x: image x position +
    • y: image y position +
    • lcs: object containing logical x, y and sys (e.g. "physical") +
    • dx: increment from current image x position +
    • dy: increment from current image y position +
    • tags: comma separated list of tag strings +
    • radii: array of radii for annulus region +
    • width: width for box region +
    • height: height for box region +
    • radius: radius value for circle region +
    • r1: x radius for ellipse region (misnomer noted) +
    • r2: y radius for ellipse region (misnomer noted) +
    • pts: array of objects containing x and y positions for polygons +
    • points: array of objects containing x and y offsets from the center for polygons +
    • angle: angle in degrees for box and ellipse regions +
    • color: region color (string name or #rrggbb syntax) +
    • text: text associated with text region +
    +Other available properties include: +
      +
    • fixinplace: if true, region cannot be moved or resized +
    • lockMovementX: region cannot be moved in the x direction +
    • lockMovementY: region cannot be moved in the y direction +
    • lockRotation: region cannot be rotated +
    • lockScalingX: region cannot be resized in the x direction +
    • lockScalingY: region cannot be resized in the y direction +
    • fontFamily: font parameter for text region +
    • fontSize: font parameter for text region +
    • fontStyle: font parameter for text region +
    • fontWeight: font parameter for text region +
    + +

    +● Get information about one or more regions +

    +rarr = JS9.GetRegions(regions) +

    +where: +

      +
    • regions: which regions to retrieve +
    +returns: +
      +
    • rarr: array of region objects +
    +

    +Each returned region object contains the following properties: + +

      +
    • id: numeric region id (assigned by JS9 automatically) +
    • mode: "add", "remove" or "change" +
    • shape: region shape ("annulus", "box", "circle", "ellipse", +"point", "polygon", "text") +
    • tags: comma delimited list of region tags (e.g., "source", "include") +
    • color: region color +
    • x,y: image coordinates of region +
    • radii: array of radii for annulus region +
    • width: width for box region +
    • height: height for box region +
    • radius: radius value for circle region +
    • r1: x radius for ellipse region (misnomer noted) +
    • r2: y radius for ellipse region (misnomer noted) +
    • pts: array of objects containing x and y positions, for polygons +
    • points: array of objects containing x and y offsets from the specified center, for polygons +
    • angle: angle in degrees for box and ellipse regions +
    • wcsstr: region string in wcs coordinates +
    • wcssys: wcs system (e.g. "FK5") +
    • imstr: region string in image or physical coordinates +
    • imsys: image system ("image" or "physical") +
    +The image position can be used to access the image data returned by the +JS9.GetImageData() routine: +
    +    obj = JS9.GetImageData();
    +    xreg = JS9.GetRegions("selected")[0];
    +    val = obj.data[Math.floor(xreg.y-0.5) * obj.width + Math.floor(xreg.x-0.5)];
    +
    +

    +Note the need to integerize the x and y values: JavaScript arrays are +objects and so floating point array indices do not get truncated +automatically as in C. They will return null values. +

    +Also note that since we need 0-based data array indexes, we subtract 1 from +the 1-based image position. But then we must add 0.5 before rounding because +by convention, x.0, y.0 is the middle of the pixel. + +

    +● Change one or more regions +

    +JS9.ChangeRegions(regions, opts) +

    +where: +

      +
    • regions: which regions to change +
    • opts: object containing options to change in each region +
    +Change one or more regions. The opts object can contain the parameters +described in the JS9.AddRegions() section. However, you cannot (yet) +change the shape itself (e.g. from "box" to "circle"). See js9onchange.html +for examples of how to use this routine. + +

    +● Remove one or more regions from the region layer +

    +JS9.RemoveRegions(regions) +

    +where: +

      +
    • regions: which regions to remove +
    + +

    +

    +Working with Shape Layers +
    +

    +

    +JS9 supports individual layers for drawing 2D graphics. The regions +layer is a special case of a shape layer, created automatically by +JS9. The Catalog plugin creates a separate layer for each catalog. +You can define your own shape layer using the NewShapeLayer() +call and then add geometric shapes to it. +

    +Note that the JS9.GetShapes(), JS9.ChangeShapes(), JS9.RemoveShapes() +calls all take a shape specification as the second argument, which can +be any of the following (in order of precedence): +

      +
    • "all": all regions +
    • [id]: a specific region id returned by JS9.AddRegions() +
    • "selected": the selected region (or all regions in the selected group) +
    • [color]: all regions having the specified color (e.g., "red") +
    • [shape]: all regions having the specified shape (e.g., "circle") +
    • [tag]: all regions containing the specified tag (e.g., "source") +
    +Thus, it is possible to act on multiple shapes at the same time. + +

    +● Create a new shape layer +

    +lid = JS9.NewShapeLayer(layer, opts) +

    +where: +

      +
    • layer: name of the layer to create +
    • opts: default options for this layer +
    +returns: +
      +
    • lid: layer id +
    +This routine creates a new named shape layer. You can then, add, change, +and remove shapes in this layer using the routines below. The catalogs +displayed by the Catalog plugin are examples of separate shape layers. +

    +The optional opts parameter allows you to specify default +options for this layer. You can set a default for any property needed +by your shape layer. See JS9.Regions.opts in js9.js for an example of +the default options for the regions layer. + +

    +● Show or hide the specified shape layer +

    +JS9.ShowShapeLayer(layer, mode) +

    +where: +

      +
    • layer: name of layer +
    • mode: true (show layer) or false (hide layer) +
    +Shape layers can be hidden from display. This could be useful, for +example, if you have several catalogs loaded into a display and +want to view one at a time. + +

    +● Add one or more shapes to the specified layer +

    +JS9.AddShapes(layer, sarr, opts) +

    +where: +

      +
    • layer: name of layer +
    • sarr: a shape string, shape object, or an array of shape objects +
    • opts: global values to apply to each created shape +
    +returns: +
      +
    • id: id of last shape created +
    +The sarr argument can be a shape ("annulus", "box", +"circle", "ellipse", "point", "polygon", "text"), a single shape +object, or an array of shape objects. Shape objects contain one or +more properties, of which the most important are: +
      +
    • shape: "annulus", "box", "circle", "ellipse", "point", "polygon", "text" [REQUIRED] +
    • x: image x position +
    • y: image y position +
    • dx: increment from current image x position +
    • dy: increment from current image y position +
    • tags: comma separated list of tag strings +
    • radii: array of radii for annulus shape +
    • width: width for box shape +
    • height: height for box shape +
    • radius: radius value for circle shape +
    • r1: x radius for ellipse shape (misnomer noted) +
    • r2: y radius for ellipse shape (misnomer noted) +
    • pts: array of objects containing x and y positions, for polygons +
    • points: array of objects containing x and y offsets from the specified center, for polygons +
    • angle: angle in degrees for box and ellipse shapes +
    • color: shape color (string name or #rrggbb syntax) +
    • text: text associated with text shape +
    +Other available properties include: +
      +
    • fixinplace: if true, shape cannot be moved or resized +
    • lockMovementX: shape cannot be moved in the x direction +
    • lockMovementY: shape cannot be moved in the y direction +
    • lockRotation: shape cannot be rotated +
    • lockScalingX: shape cannot be resized in the x direction +
    • lockScalingY: shape cannot be resized in the y direction +
    • fontFamily: font parameter for text shape +
    • fontSize: font parameter for text shape +
    • fontStyle: font parameter for text shape +
    • fontWeight: font parameter for text shape +
    + +

    +● Remove one or more shapes from the specified shape layer +

    +JS9.RemoveShapes(layer, shapes) +

    +where: +

      +
    • layer: name of layer +
    • shapes: which shapes to remove +
    + +

    +● Get information about one or more shapes in the specified shape layer +

    +JS9.GetShapes(layer, shapes) +

    +where: +

      +
    • layer: name of layer +
    • shapes: which shapes to retrieve +
    +returns: +
      +
    • sarr: array of shape objects +
    +

    +Each returned shape object contains the following properties: + +

      +
    • id: numeric region id (assigned by JS9 automatically) +
    • mode: "add", "remove", or "change" +
    • shape: region shape ("annulus", "box", "circle", "ellipse", +"point", "polygon", "text") +
    • tags: comma delimited list of region tags (e.g., "source", "include") +
    • color: region color +
    • x,y: image coordinates of region +
    • size: object containing width and height for box region +
    • radius: radius value for circle region +
    • radii: array of radii for annulus region +
    • eradius: object containing x and y radii for ellipse regions +
    • pts: array of objects containing x and y positions, for polygons +
    • angle: angle in degrees for box and ellipse regions +
    + +

    +● Change one or more shapes in the specified layer +

    +JS9.ChangeShapes(layer, shapes, opts) +

    +where: +

      +
    • layer: name of layer +
    • shapes: which shapes to change +
    • opts: object containing options to change in each shape +
    +Change one or more shapes. The opts object can contain the parameters +described in the JS9.AddShapes() section. However, you cannot (yet) +change the shape itself (e.g. from "box" to "circle"). + +

    +

    +Server-side Analysis +
    +

    + +

    +● Run a simple server-side analysis task +

    +JS9.RunAnalysis(aname, parr, func) +

    +where: +

      +
    • aname: name of analysis tool +
    • parr: optional array of macro-expansion options for command line +
    • func: optional routine to call when analysis is completed on server +
    +The JS9.RunAnalysis() routine is used to execute a server-side +analysis task and return the results for further processing within the +Web page. +
  • The optional parr array of parameters is passed to the JS9 +analysis macro expander so that values can be added to the command +line. The array is in jQuery name/value serialized object format, +which is described here: +
    +    http://api.jquery.com/serializeArray/
    +
    +
  • func: a function to process the returned data when the task is complete. + +

    +The func() routine is a callback function to process the returned +results from the analysis task. The calling sequence is: +

    +    func(stdout, stderr, aobj)
    +
    +where: +
      +
    • stdout: a string containing the standard output from the task +
    • stderr: a string containing the standard error from the task +
    • aobj: the analysis object from the js9Analysis.json file, containing, + among other things, the important rtype: "text" or "plot" +
    +Typically, you would check stderr string first and issue an error +message if there is an error. Otherwise, the stdout string can be +processed based on the return type (rtype) property of the output +(e.g., "text" or "plot"). For plotting, you can use flot +functionality already loaded into JS9, or you can use your own chosen +plotting package. +

    +If no func callback is specified, the default processing will +display "text" in a new light window. If the return type is "plot", +the results are assumed to be in flot format and will be plotted. + +

    +● Run a server-side analysis task utilizing +parameters in a form +

    +JS9.SubmitAnalysis(el, aname, func) +

    +where: +

      +
    • el: form element (unused at present) +
    • aname: name of analysis tool +
    • func: optional routine to call when analysis is completed on server +
    +The JS9.SubmitAnalysis() routine is used to run an analysis +task with input parameters from a form. Typically used as +the Run button action in a form, it automatically serializes +the form values and passes them to the JS9 analysis macro expander so +that these values can be integrated into the analysis command line. +See js9analysis.html for a simple example. +

    +The func callback is the same as for JS9.RunAnalysis() above. + +


    +

    +Miscellaneous +
    +

    + +

    +● Print an image +

    +JS9.Print() +

    +Print the currently displayed image. A new window is displayed +containing the image, along with regions and other graphical layers +(the 2D graphics having been converted to a re-scalable format). The +standard Print dialog box also is displayed and can be used to print +this new window. Dismiss both windows when you are finished. + +

    +● Display help in a light window +

    +JS9.DisplayHelp(name) +

    +where: +

      +
    • name: name of a help file or url of a Web site to display +
    +The help file names are the property names in JS9.helpOpts (e.g., "user" for +the user page, "install" for the install page, etc.). Alternatively, you can +specify an arbitrary URL to display (just because). + +

    +● Get location of JS9 installation directory +

    +rpath = JS9.InstallDir(file) +

    +where: +

      +
    • file: file or directory to convert +
    +returns: +
      +
    • rpath: path of the file relative to the JS9 install directory +
    +Sometimes a plugin needs to load an auxiliary file inside the plugins +sub-directory. The Web page loading the plugin has an arbitrary +location relative to the JS9 install directory, so this routine +returns a relative path to the js9 install directory. + +

    +

    +Prototype Routines (not ready for prime time) +
    +

    +NB: The routines in this section are prototypes and therefore are +subject to change. Feel free to contact us to discuss your needs so +that we can gain a better understanding of is required in these cases. +

    +● Load an auxiliary file +

    +JS9.LoadAuxFile(name, func) +

    +where: +

      +
    • name: class name of auxiliary file to load +
    • func: function to call once the file is loaded +
    +

    It sometimes is desirable to process auxiliary files when an image +is first loaded. Examples include overlaying an image mask on an +image, and pre-loading regions from a region file. +The JS9.LoadAuxFile prototypes this sort of functionality. +

    +Auxiliary files are defined in the js9Prefs.json file by means of the +JS9.auxfiles array containing one or more auxfile objects. Each +auxfile specification has the following properties: +

      +
    • type: type of auxiliary file: currently "mask" or "region" +
    • name: the class name of the auxiliary file +
    • image: image (or template) for which this auxfile is valid +
    • url: URL of the auxfile +
    +For example, the following defines two auxfiles: +
    +  "auxFiles":   [{"type":	     "mask",
    +		  "name":	     "sciencemasks",
    +		  "image": 	     "casa.*.png",
    +		  "url":	     "../myauxfiles/casa-mask.png"},
    +		 {"type":	     "regions",
    +		  "name":	     "scienceregions",
    +		  "image": 	     "casa.*.png",
    +		  "url":	     "../myauxfiles/casa.reg"}],
    +
    +Here, a mask auxfile and a regions auxfile are defined for Cas-A +dataset(s). These auxfiles are brought into play as follows: +
    +    // run this routine after loading each image
    +    function onImageLoad(im){
    +      JS9.LoadAuxFile("sciencemasks", function(im, aux){
    +        // if we succeed in loading the mask, set up the onchange callback
    +        im.onregionschange = regionOnChange;
    +        // view the image through the mask data
    +        im.maskData = aux.im.raw.data;
    +        // I mean now!
    +	im.displayImage("all");
    +      });
    +    JS9.LoadAuxFile("scienceregions");
    +  }
    +
    +  // tell JS9 about the onload callback
    +  JS9.imageOpts.onload = onImageLoad;
    +
    +An onImageLoad function is defined that will try to load auxfiles of +types "sciencemasks" and "scienceregions". This routine is set to +be called whenever a new image is loaded. +

    +On image load, when JS9.LoadAuxFile() is called, it looks in +the list of known auxfiles for an entry that matches both +the class name and the image name. If found (in the example above, +for Cas-A datasets), the associated auxfile URL is loaded and +type-specific processing is performed: +

      +
    • masks: the mask file is loaded into the Web page as an +off-screen image and an aux object is created as a property of the +image object. This aux object can be used for subsequent processing +(see below). +
    • regions: the regions in the region file are created and +displayed on the image. +
    +Once the initial auxfile processing has been performed, the optional +callback function will be called. For the "mask" example above, the +onregionchange property is set to call a JavaScript function (not +shown here) whenever a region changes. The maskData property is set to +point to the raw data of the auxfile (i.e., aux.im.raw.data). Finally, +the image is redisplayed. Setting the maskData property and +redisplaying the image causes the auxfile's data to be displayed as an +opaque overlay on top of the currently displayed image. +

    +As should be clear from the description above, considerable "black +magic" currently is involved when processing auxiliary files. +Visibility is required into the inner properties of the image +object. Please contact us if you want to work with auxiliary files, so +that we can continue to think about what is required for their support. + +

    Last updated: September 4, 2014
    +
  • + + + diff --git a/help/repfile.html b/help/repfile.html new file mode 100644 index 00000000..745f5dbc --- /dev/null +++ b/help/repfile.html @@ -0,0 +1,262 @@ + + + + + +
    +The PNG Representation File +

    The PNG Representation File

    + +

    +X-ray archives present special problems for displaying data. Instead +of images, X-ray data consists of detected photons stored in FITS +binary tables. This means that the file size is related to the number +of detected photons, not the image dimensions. Indeed, X-ray data +files can be hundreds of megabytes in size. Downloading (and then +binning) these tables can be painfully slow, especially if the aim +simply is to offer a quick look at the data. On the other hand, simply +generating a FITS image from the binary table for download breaks the +connection with the original events, which might be needed for +server-side analysis. + +

    +To remedy this situation, JS9 supports use of a special +PNG representation file, explicitly tied to the original event +data. Once downloaded into JS9, the image can be reconstructed +from this file for display. The file maintains information about the +original FITS binary table for use in remote analysis. The idea is +that you create a representation file from the original FITS +binary table and use that file for display in JS9, while supporting +server-side analysis on the original FITS event file. +

    +Display of a representation file is fully integrated into JS9: +

      +
    • The relatively small PNG file is downloaded and read using +standard, optimized browser support. +
    • RGB image values are retrieved using getImageData() into an +off-screen (non-visible) canvas. This is the packed representation of the FITS file. +
    • The FITS header is extracted into a JavaScript object, and actual image dimensions and datatype are determined. +
    • The original image data is unpacked into an HTML5 typed array of the specified data type, with endian conversion applied as necessary. +
    • The standard DS9 algorithm is applied to this array to convert pixel +values to an array of RGB values. +
    • The converted RGB array is sent to the screen using putImageData() +and displayed by the browser. +
    + +

    +Using this representation file, image data values are available to the +client JavaScript code without having to download the much larger +binary table. This means that the contrast/bias conversion can be +performed, image positions/values displayed, etc. using standard +browser capabilities and relatively straight-forward array +manipulation code. Browser-based image plugins can process the image +data, and JS9 can communicate with a back-end server to provide more +sophisticated FITS-based analysis support. + +

    +Note that JS9 is able to distinguish between PNG representation files and +ordinary PNG files and will correctly load either type. + +

    The PNG Representation File

    +

    +The PNG +representation file contains the following information: +

      +
    • fitsfile: the pathname of the FITS file used to generate this PNG +file, including the FITS bracket extension (if present) +
    • fitsheader: a FITS header containing the WCS information +for the generated image +
    • image: a PNG image containing a json version of the FITS header and image data (in its native data type) packed into RGB triplets +
    + +

    Generating the PNG file using tpos and fits2png

    +

    +A PNG representation file can be created either statically or +dynamically at display time as needed. The low-level tpos +program and high-level fits2png script facilitate this conversion: +

    +    tpos [ifits] [opng]
    +or
    +    fits2png [switches] [ifits] [opng]
    +    switches:
    +    -abs	# convert relative path to absolute path for storage in PNG
    +    -gzip       # assume the file is in gzip format, regardless of its extension
    +    -dim	# dimension for PNG image (use to calculate block factor)
    +    -js9	# set dim, odir, repl parameters for automatic JS9  conversion
    +    -odir	# specify output directory (default: from opng path)
    +    -repl	# replace existing PNG? (default: true)
    +
    + +

    +The fits2png switches are meant to provide flexibility when running +tpos in batch mode. The fits2png script also is used to generate PNG +files on the fly (i.e., when offering FITS files on your Web page +directly instead of the PNG representation.) + +

    +By default, tpos and fits2png will convert a FITS image or binary +table to a PNG representation file having the same image dimensions: +

    +    tpos m13.fits m13.png
    +
    +However, current browsers have a working limit to the image size they +can reasonably handle: 2048x2048 works well; anything larger can be +subject to performance degradation. For maximum flexibility, you can +use Funtools syntax to limit the size of the generated PNG file. For +example: +
    +    tpos 'casa.fits[1024@4027,1024@3944,2]' casa.png
    +
    +Here, the PNG file is generated by extracting a 1024x1024 image +centered on a specific point (4027,3994) and then blocking it by a +factor of 2 to create a final 512x512 image. + +

    +For automatic processing with fits2png, specifying the -dims +switch will tell fits2png to calculate the block factor in such a way +as to generate an image of the specified size: +

    +    fits2png -dims 512 512 casa.fits casa.png
    +
    +This will block the 8192x8192 Chandra ACIS data by a factor of 16 to +make a 512x512 image centered on the the point (4096,4096). + +

    +In addition to the image, the (generated) FITS image header and the +FITS pathname are stored in the PNG file for use by both the browser +and the server-side helper programs. The image header is used to +provide WCS information for individual pixels as the mouse is moved +across the image. It also is used to provide region information in WCS +format (i.e. independent of block factor). The FITS pathname is used +to locate the original FITS file in order to execute analysis tasks. + +

    +In order to run analysis tasks, the FITS data must be accessible to the +server-side helper program. Therefore, it seems preferable to store +an absolute pathname in the PNG file, but more experience is needed on +this score. You can specify the absolute pathname on the tpos command line, +or else specify the -abs switch on fits2png and it will be determined by the +script. + +

    +If you store a relative path in the PNG file, note that this +path will be utilized by the server-side JS9 helper to locate the FITS +file. This means that if the helper is not started in the same +directory that tpos (fits2png) was run, the relative path will not be +correct. In this case, you can set the JS9.analOpts.dataDir +parameter in the js9Prefs.json file to a path that will be used +instead of the relative path. + +

    +You also must decide where to store the PNG files, e.g. with the FITS +data or in a separate directory. Clearly, this will depend on how your +archive is set up and where you have write access. By default, PNG files +will simply be stored in the path specified on the tpos command +line. You can use the -odir switch on the fits2png script to specify a +generic location: +

    +    tpos ./png ./fits/casa.fits ./png/casa.png    # store in png subdirectory
    +    tpos -odir ./png ./fits/casa.fits casa.png    # same
    +
    + +

    +The -odir switch can be used to specify a session-based +directory in which to store PNG files. This facility could be used, +for example, in a case where each user has files stored in her or her +own directory, which might be removed at the end of the session. To +facilitate session-based directory specification, a standard HTML cookie +is used to pass the session information between client and server as follows: +

      +
    • When a JS9-enabled page is loaded, a cookie is set containing the +session id in the Web page. For example, one might a set a cookie +whose name is JS9_ID and whose values is 0x1234. +
    • The odir switch is given a directory value containing the cookie +name as part of the string, preceded by a percent sign, %. For +example, odir might be set to ./png/%JS9_ID. +
    • When fits2png is executed, the %cookie name is replaced by the +cookie value. In the example above, the resulting odir value is +./png/0x1234. +
    • The PNG representation file is stored in this odir directory, as usual. +
    +Note that the name of the cookie is arbitrary, but is case sensitive. + +

    +Finally, the special value of @IFILE@ tells fits2png to +store the PNG file in the same directory as the FITS file: +

    +    tpos -odir @IFILE@ .../casa.fits casa.png     # store PNG with FITS file
    +
    +Again, these switches are meant to provide initial flexibility while we gain +more experience with community needs. Please let us know how to improve this +part of the system. + +

    +Regardless of where the PNG files are stored, you must adhere to +the W3C "same-origin" security policy, i.e. the PNG data files must be +hosted on the same Web server as the JS9 code. This means that your PNG +files must either be stored in the Web site directory tree, or you +must make a link within the Web site tree to the top level PNG directory. +Also note that Google Chrome's implementation of this policy prevents +you from using JS9 with a +file:// URL. (On Linux and Macs, you can start Chrome with the +--allow-file-access-from-files switch to work around this restriction.) + +

    Loading a PNG File From Your Web Page

    +

    +Once you have generated your PNG files, you can make them available on your +JS9 Web page by creating URLs that call the JS9.Load() routine: +

    +    href='javascript:JS9.Load(filename, opts);'
    +
    +where filename is the file to load and +opts is an object containing params to be merged with the +default JS9.imageOpts object. + +

    +For example: +

    +    href='javascript:JS9.Load("png/casa.png", {scale: "log"});'
    +
    +Clicking on this URL will cause the casa.png file (here, stored in the +png directory) to be loaded into JS9, using the log scale as a +default. If the JS9 server-side helper is running, it will be alerted +about this new file so that it can run analysis, etc. +

    +See JS9 Public API for complete +documentation about the JS9.Load() routine. + +

    Run-time Conversion of FITS to PNG

    +

    +If you don't generate PNG files beforehand, you can still specify a +FITS file as the first argument to JS9.Load() and have the JS9 +server-side helper run fits2png at run-time.. To do this, you set +the fits2png property in js9Prefs.json: +

    +{
    +  "globalOpts": {"fits2png": true ...}
    +}
    +
    +This tells JS9 to convert FITS files instead of downloading them +directly. Then you can use JS9.Load() as usual: +
    +    href='javascript:JS9.Load("fits/3c58.fits");'
    +
    +The default command for this conversion is contained in the js9Helper.js file: +
    +    fits2png -js9 -odir ./png
    +
    +The -js9 switch will calculate a block factor to generate a 512x512 +PNG image. It will not replace an existing PNG file, if it +exists. Note that the output directory is set explicitly to be the png +subdirectory of the sample installation. You can change this command +to suite your site needs. + +
    Last updated: September 4, 2014
    +
    + + + diff --git a/help/serverside.html b/help/serverside.html new file mode 100644 index 00000000..68614c49 --- /dev/null +++ b/help/serverside.html @@ -0,0 +1,238 @@ + + + + + +
    +Server-side Analysis Tasks + +

    Adding Server-side Analysis Tasks to JS9

    + +

    +A JS9 Web site can define analysis tools that will be loaded into the +user's JS9 Analysis menu. These analysis tasks are then +executed by the back-end (CGI or node.js) server using the original +FITS data, with results sent back to the browser for display. + +

    To learn how to install the back-end helper, see: +Installing a Server-side Helper. + +

    +Analysis tools are defined within files contained in the +analysis-plugins directory. If a file in this directory +ends with a ".json" extension, it is assumed to be an analysis +definition file. The following sample analysis definition files will +be found in the analysis-plugins directory by default: +

      +
    • fits2png.json: the command line for converting FITS to PNG files +
    • js9Analysis-fits.json: generic FITS tasks (e.g. display header) +
    • js9Analysis-funtools.json: funtools-based analysis tasks +
    +If you plan to allow dynamic conversion of FITS files to PNG +representation files, the fits2png.json file should be left in +the plugin directory. The other two are optional and should be removed +if funtools is not available. + +

    +Analysis definition files are in JSON format +(http://www.json.org/) and consist of an array of JavaScript objects, +one for each analysis tool. The properties which define an analysis +tool are: +

      +
    • name: a short identifier string (typically one word) +
    • title: a longer string that will be displayed in the Analysis menu +
    • files: a rule that a filename will be matched against to determine +whether this task is available for the current image (not yet implemented) +
    • purl: a URL pointing to a Web page containing a user parameter form +
    • action: The command to execute on the server side +
    • rtype: a return type, which can be text or plot +
    • hidden: if true, the analysis task is not shown in the Analysis menu +
    +See the sample json files in the analysis-plugins directory for the +JSON syntax of this file. + +

    +The action string contains the command to execute. For security +reasons, this action is never executed directly. Instead, the first +argument of the command must be a wrapper script contained in +the analysis-wrappers directory. The js9Xeq wrapper +script contained therein is the default script for running JS9 +analysis. The second argument in the action string is a command id, +which is executed within the command-processing case statement of +the js9Xeq. This wrapper script checks for valid commands and +arguments, and then executes the specified command in a way that +protects against malicious attack. You can modify this script to meet +your needs by adding case statements for each of the new tasks you +want to run. + +

    +Alternatively, you can run your analysis tasks through your own +wrapper script, by placing it in the analysis-wrappers +directory. Using your own wrapper script allows you to perform your +own special setup (e.g., setting environment variables, cd to work +directory) before executing a task. Obviously you can +use js9Xeq as an example and modify it to suit your needs. + +

    +In either case, note that execution of a wrapper script is +accomplished by pre-pending the path of the analysis wrapper directory +to the wrapper script name and executing that full pathname directly. +This prevents a would-be attacker from executing anything except the +wrapper itself. Of course, you still have to be careful to avoid +insecure shell coding in your wrapper script. +See The World +Wide Web Security FAQ for advice on writing CGI scripts. + +Note that JS9 scripts generally use bash or sh. Please make sure your +bash and sh programs are properly patched to protect against the bash +bug (CVE-2014-6271). + +

    +The action command line can contain macros (strings prefixed +with the $ character) that will be expanded by the browser before +the action is sent to the server for processing. Typically, these macros are +used to specify filenames, regions, and (possibly) user parameters. The +following intrinsic macros are defined: +

      +
    • $filename: pathname of the original FITS file +
    • $regions: all currently defined regions +
    • $sregions: all source regions +
    • $bregions: all background regions +
    +For example, to run the funcnts program, specifying the original FITS +file as well as source and background regions, use: +
    +    funcnts $filename $sregions $bregions
    +
    + +

    +Many analysis tasks do not require the user to select additional parameter +options and can can be executed immediately. Other command require +user-selected options. These latter options should be put into a Web +form, whose location is specified by the purl option. See +the params/histplot.html file for an example. + +

    +Parameter options in a parameter form should have unique ids. These +ids can then be added as macros to the action command line by +prefixing them with a $. For example, the histplot command is: +

    +    js9Xeq histplot '$filename[$regions]' '$norm $bwidth' $column $bins
    +
    +Here, the norm, bwidth, column, and bins +parameters are taken from the Web form for histplot. The $filename +and $regions macros are intrinsic to JS9. + +

    +The input element of the analysis form should run +the JS9.SubmitAnalysis() command, which will serialize the form, +pass it to the macro expander, and then send the resulting command string +to the server for execution. See histplot.html for sample syntax. + +

    +The rtype property determine how JS9 handles return values: +

      +
    • text: the returned text is displayed in a lightweight window +
    • plot: the returned plot data is plotted using the jQuery +flot widget (see http://www.flotcharts.org/) +
    +Sample scripts such as funcnts2flot and funhist2plot +generate a JSON string that contains a valid flot object. For +example, the radial profile plot contains x, y, and error values: +
    +{
    +  "color": "green", 
    +  "label" : "surf_bri(...) vs. avg_radius(...)", 
    +  "points" : {"errorbars" : "y", 
    +              "yerr" : {"show" : "true", "color" : "red"}},
    +  "data": [[x1, y1, e1], [x2, y2, e2], ... [xn, xn, en]]
    +}
    +
    +while the histogram plot contains only x and y values: +
    +{
    +  "color": "blue", 
    +  "label" : "counts vs. ...bin", 
    +  "data": [[x1, y1], [x2, y2], ... [xn, xn]]
    +}
    +
    +If your analysis task generates one of these two plot formats, JS9 +will display the plot data. Plotting is still somewhat experimental +and rudimentary. We will be adding features with time (e.g. ability to +change scales between linear and log). Please work with us to improve +plotting support. + +

    +Finally, the hidden value determines whether or not a task is +displayed in the Analysis menu. If hidden value is true, the +analysis task is not shown. However, it still is available to the +JS9.RunAnalysis() routine. The fits2png command in the +fits2png.json definition file is an example of a hidden +command: it is run indirectly by JS9 and need not be listed as a user +task. + +

    +

    Adding Analysis Tasks Directly to Your Web Page

    +

    +By default, server-side JS9 analysis tasks are executed using +the Analysis menu, but they also can be executed directly from +the Web page by means of HTML elements (buttons, forms, etc.) To do +this, a Web page author simply creates the desired interface and calls +either JS9.RunAnalysis() (for buttons, menus, etc.) +or JS9.SubmitAnalysis() (for forms). These are described +below. See the js9analysis.html page for an example. + +

    +The JS9.RunAnalysis() routine is used to execute an analysis task and +return the results for further processing within the Web page. The +JS9.SubmitAnalysis() routine works similarly, but it is used +with a form: it automatically serializes the form values and passes +them to the analysis macro expander so that these values can be put +into the analysis command line. The calling sequences for these +routines are similar: +

    +    JS9.RunAnalysis(aname, [options], returnFunc);
    +    JS9.SubmitAnalysis(this, aname, returnFunc);
    +
    +where: +
      +
    • aname: the name value of the task (as defined in the js9Analysis.json file) +
    • options: an optional array of parameters to pass to the analysis +macro expander. The array is in jQuery name/value serialized object +format, which is described here: +
      +    http://api.jquery.com/serializeArray/
      +
      +
    • returnFunc: a function to process the returned data when the task is +completed +
    • this: the 'this' value of the form element +
    +

    +The returnFunc() routine is a callback function to process the returned +data from the analysis task. The calling sequence is: +

    +    returnFunc(stdout, stderr, aobj)
    +
    +where: +
      +
    • stdout: a string containing the standard output from the task +
    • stderr: a string containing the standard error from the task +
    • aobj: the analysis object from the js9Analysis.json file, containing + the rtype (e.g. "text" or "plot") property +
    +Typically, you would check the stderr string first and issue an error +message if there is an error. Otherwise, the stdout string can be +processed based on the return type (rtype) of output (e.g., "text" or +"plot"). For plotting, you can use the flot functionality that +is loaded into JS9, or you can use your own chosen plotting +package. See js9analysis.html for a simple example. + +
    Last updated: September 4, 2014
    +
    + + + diff --git a/help/user.html b/help/user.html new file mode 100644 index 00000000..cdb1784c --- /dev/null +++ b/help/user.html @@ -0,0 +1,409 @@ + + + +The JS9 Help Facility + + +
    +
    +

    JS9: image display right in your browser

    +Eric Mandel, John Roll, Alexey Vikhlinin +
    +Harvard-Smithsonian Center for Astrophysics +
    +Cambridge, MA 02138 +
    + +

    +

    Introduction to JS9

    +

    +JS9 is a JavaScript version of the de facto standard DS9 image display +program. It allows you to view and manipulate astronomical image data +in your browser. +

    +Please choose from the following topics: +

    + +

    +

    Getting Started with JS9

    +

    +JS9 provides astronomical image display capabilities right in your browser. +JS9 takes both its name and its core functionality from the de facto standard +DS9 image display program for desktop use, which is available at: +

    +    http://ds9.si.edu
    +
    +The JS9 display consists of one or more components that can be added +to a Web page by the Web page designer. At a minimum, the JS9 display +will contain an image display canvas. It usually also will display a +menu strip containing several pull-down menus. Traditionally, this +menu strip is placed on top of the image canvas, but Web designers +have complete control over its placement. JS9 also can display an info +box, a command-line window, a pan window, a zoom window, as well as +other plugins. All of these windows can be brought up dynamically from +the View menu. + +

    +Astronomical image data usually is offered on a JS9 Web page as one or more +clickable URLs. When you click on a data URL, it is displayed on the JS9 image +canvas. Multiple images can be loaded into a single JS9 display. The File +menu allows you to switch between these images. + +

    +Once an image is loaded, you can move the mouse (or a single finger on +a touch screen) to display position and pixel value +information. Pressing the left mouse button and moving the mouse (or +using two fingers on a touch screen) will change the contrast/bias of +the displayed image, bringing image features into relief. + +

    +Menu options allow you to change the scaling algorithm and/or color +map, add geometric regions of interest, change world coordinate system +(WCS) parameters, and run site-specific astronomical analysis tasks on +the original FITS data. + +

    +

    JS9 Menus

    +

    +The following menus are in the default JS9 menu bar. Note that Web +designers have control over which menus are displayed (or even whether +the menu bar itself is displayed). Thus, not all of the menus listed below +will be found on all Web pages: +

      + +
    • File: The File menu displays a list of all images +currently loaded into this instance of JS9. The displayed image is +marked with a star burst. To display a different image, simply choose +it in the menu. The menu contains an open ... options which +displays a file browser for loading FITS files (compressed or +uncompressed). It also contains options to: +

        +
      • print ... to print the current image display window +
      • display FITS header for the current image +
      • display pageID, a unique ID that can be used when +communicating with JS9 externally +
      • close image to close the image and release browser resources +
      + +
    • View: The display value/position option specifies whether +image position and image pixel value is displayed as the mouse (or +finger) moves over the image. By default, this information is +displayed in the upper left of the image. You can redirect the display +to a movable, light-weight window by choosing the InfoBox menu +option. The Console menu option will bring up a movable, light-weight +console window into which JS9 commands can be entered. +The Magnifier menu option will bring up a movable, +light-weight window showing a blocked image of the data in an area +surrounding the mouse as it moves. The default magnification of four +can be changed using command buttons on the magnifier window. +The Panner menu option will bring up a movable, +light-weight panner window that displays the full image along with a +viewport rectangle showing the currently displayed image section in +the primary image window. The viewport can be moved around in order to pan +to different locations in the primary image. The panner also has +command button options to zoom the viewport itself. (This makes +the viewport rectangle larger at the expense of displaying only a +section of the full image. It is useful for panning in a very large +image.) +

      +In addition to these core options, the View menu also lists the +currently loaded View Plugins. JS9 itself supplies the following plugins: +

        +
      • Archive and Catalogs: allows you to display image data retrieved +from various archives and overlay catalog information +
      • Binning: supports binning and column filtering on FITS binary tables +
      • Pixel Table: displays an array of pixel values around the current mouse position +
      +

      +Web developers can develop and register other plugins (which generally are +loaded into either the View or Analysis menus). + +

    • Zoom: The zoomIn and zoomOut menu options +zoom the primary image in or out by a factor of +two. The zoomToFit options calculates a zoom factor that fits +the entire image into the JS9 display. You also can set the zoom +factor to a pre-specified value using menu options. You can specify +any floating point zoom factor in the numeric zoom value text +box. The pan to center option pans to the center of the image, while +the reset zoom/pan sets the zoom to 1 and centers the display. + +

    • Scale:Each scale option specifies a different scaling +algorithm to use when converting image pixel values to RGB +values. (The procedure for doing this conversion is detailed in the +DS9 documentation titled "How It Works".) The log scale, for example, +is especially useful with X-ray data. The current scale is marked +with a star burst. + +

      +You also can change the low and high values used to clip the image +data before scaling by changing the low value for clipping +and/or high value for clipping numbers. These values are set +initially with the data's min and max values or the z1,z2 values +calculated by the IRAF zscale algorithm (depending on the value +of the Web site's JS9.imageOpts.scaleclipping parameter. The +default usually is "dataminmax".). Finally, you can set (or reset) the +low and high values to data min,max or zscale z1,z2 using the set +vals to data min/max or set vals to zscale z1/z2 options, +respectively. (Note that zscale requires a considerable amount of +memory and does not work on very large images. We will try to remove +this restriction in the future.) + +

    • Colormap: Each colormap option specifies a different +distribution of RGB values to use when converting image pixel values to RGB. +(The procedure for doing this conversion is detailed in the +DS9 documentation titled "How It Works".) Choose the colormap you like best, +or try different ones to see how data features can be brought to the fore +by color and contrast/bias. + +

      +You can enter a floating point value into the contrast value and +bias value text boxes to set the contrast/bias. Note that the +contrast value ranges from 0 to 10 and the bias ranges from 0 to 1 +(following DS9 conventions). + +

      +The reset contrast/bias option restores the original +contrast/bias value (which is especially useful if you changed the +contrast/bias or scale and now can't see any features at all!) + +

      +The invert cmap option inverts the colormap (e.g. in the gray map, +this will change white to black and vice versa). + +

      +If you have three images of the same size, scale, and pointing +direction (e.g. three energy cuts of a Chandra data set), you can +display each one separately and assign to them one of the red, +green, or blue colormaps. If you then select the RGB mode +menu option, they will be displayed as one RGB composite image. The +current image (as shown in the File menu) determines which of +the three independent colormaps is changed by the contrast/bias +manipulation. To remove an image from the RGB composite, give it a +different colormap. Re-join (or add a new image) by assigning one of +the RGB colormaps. Simply turn off RGB mode to display the images +separately. + +

    • Region: Choose the appropriate menu option to create a +region of type annulus, box, circle, ellipse, +point, polygon, text. +(see below for details on how to use regions). One or more regions can +be created and manipulated on a single image. + +

      +The listRegions menu option will display all regions. +The listOnChange menu option will cause all regions to be listed +whenever one changes.The deleteRegions menu option will delete +all regions. Note that each individual region has a configuration +menu (double-click inside the region) that supports +these options for that region only. + +

    • WCS: Use this menu option to select a world coordinate +system when displaying pixel positions and regions (assuming +the data file supports WCS). Available systems are: FK4, FK5, +ICRS, galactic, or ecliptic. The native +option chooses the system stored in the data file. The image +and physical systems will display only image coordinates (not +WCS coordinates). Physical coordinates are tied to the original +(block 1) file coordinates while image coordinates are tied to +the current image data being displayed. Server-side X-ray analysis +routines operating on the original file generally want physical coords +rather than image coords. Browser-based plugin routines generally use +image coordinates to operate on the in-memory image data. + +

      +You also can choose the units in which WCS information is displayed: +degrees, radians, or sexagesimal. Image and +physical coordinates are displayed in units of pixels. + +

    • Analysis: Each JS9 site can define server-side analysis +tasks to be run from the Analysis menu. Tasks are of two types: +

        +
      • immediate tasks: These tasks are executed directly and +immediately from the Analysis menu. No parameter setup is needed. +
      • parameter tasks: These tasks bring up a lightweight +parameter window allowing various parameters to be set before +executing the task. Parameter tasks are identified by the presence of +an ellipsis (...) after the task name. +
      +

      +For example, the sample implementation of JS9 offers the following tasks: +

        +
      • Counts in Regions: Run the funcnts program on the specified +source and background regions and return a text display (immediate task). +
      • Radial Profile: Run the funcnts program on the specified +source and background regions and return a plot display. The source regions +consist of circles or annuli (immediate task). +
      • Energy Plot: Create a histogram of the pi column of a +binary table and return a plot display (immediate task). The pi column +must exist in the data file (e.g., Chandra ACIS data but not Chandra +HRC data). +
      • Histogram Plot: Create a histogram of the user-specified +column of a binary table and return a plot display (parameter +task). Parameters include: histogram column name, number of bins, use +bin width instead of bin size, and an option to normalize by bin +width. A help file is appended to the parameter display. +
      + +

      +In addition to server-side analysis, the Analysis menu lists +the currently loaded Analysis Plugins. JS9 itself supplies the +Imexam plugin, which offers the following tasks: +

        +
      • Encircled Energy +
      • Radial Proj +
      • Histogram +
      • Region Stats +
      • X Proj +
      • Y Proj +
      • 3dPlot +
      +

      +Finally the set data path ... option allows you to specify a +colon-separated list of directories for JS9 to search when looking for +FITS data files that have been dropped onto the display. This is used +by JS9 when performing server-side data analysis on local +drag-and-drop FITS files. It is necessary to specify data paths +explicitly since Web pages are not allowed to determine the pathname +of such files automatically (for obvious security reasons). + +

    • Help: Show this and other JS9 help pages. The Help menu +also contains help for Plugins, including the Imexam plugins +listed above. +

    + +

    +

    JS9 Mouse Interaction

    +

    +In keeping with the needs of mobile devices, JS9 utilizes a single +mouse button for user interaction. Keyboard input also is minimized. +Moving the mouse (or a single finger on a tablet) over the image will +display the position/value of individual pixels. Pressing and moving +the mouse (or two fingers) will change the contrast and bias of the +image. A double-click (or double-tap) inside a region will bring up +the configuration menu for that region. + +

    +

    JS9 Regions

    +

    +Regions are geometric shapes that can be used to mark part of an image +for analysis. JS9 allows you to create the following region +types: annulus, box, circle, ellipse, point, polygon. +A text region also can be created to annotate an image. When one +of these options is selected, the region is created in the center of +the image. It then can be dragged to the desired location. Arrow keys +also will move the region one screen pixel in the specified direction. +A selected region can be deleted by pressing the Delete key (where +available. On a tablet, use the delete option in the configuration menu). +

    +Click inside a region to select it and display the resize/rotate +controls around its perimeter. Grabbing a handle allows the size of +the region to be adjusted or rotated. In the case of the box and +ellipse regions, the width and height are controlled separately. Click +outside the region to de-select (or click another region to select +that one). + +

    +A double-click inside a region brings up a configuration menu. You can +change various values associated with a region by entering new values +in the appropriate text boxes and the clicking Apply. + +

    +The configuration menu has the following standard options: +

      +
    • id: the id of this region, which can be used programmatically to select it for processing (read-only) +
    • type: the type of region (read-only) +
    • image center: new image pixel values can be entered to change the region position +
    • WCS center: new WCS position values can be entered to change the region position (where WCS is available) +
    • Tags: the default tags (source, background, include, exclude) +are used in X-ray astronomy but you can enter any string to tag this region and then select programmatically using tags +
    • WCS Region: the WCS representation of this region, where applicable (read-only) +
    • Image Region: the image representation of this region, where applicable (read-only) +
    • Options: +
        +
      • List On Change: list this region when it's moved or resized +
      • Fix in Place: disable move and resize capability +
      • Delete: delete this region. On an iPad, this currently is +the only way to delete a region. +
      +
    +

    +In addition, regions of different type support specific configuration +parameters in this menu. +
    +The annulus region supports: +

      +
    • Radii: change the radii of the region (in pixels) +
    +The box region supports: +
      +
    • Width: change the width of the region (in pixels) +
    • Height: change the height of the region (in pixels) +
    • Angle: change the angle of the region (in degrees, counter-clockwise) +
    +The circle region supports: +
      +
    • Radius: change the radius of the region (in pixels) +
    +The ellipse region supports: +
      +
    • Radii: change the r1 and r2 radii of the region (in pixels) +
    • Angle: change the angle of the region (in degrees, counter-clockwise) +
    +The polygon region supports: +
      +
    • Points: change the image points of the region (in pixels) +
    • Angle: change the angle of the region (in degrees, counter-clockwise) +
    +The text region supports: +
      +
    • Text: change the text of the region +
    • Angle: change the angle of the region (in degrees, counter-clockwise) +
    + +

    +

    Meta Key Accelerator

    +

    +The meta key is the Command key on a Mac and the Control +key everywhere else. + +

    +When a keyboard is available, pressing the meta key while +clicking in the primary image window will pan the image so that the +clicked location is in the center of the display. + +

    +The meta key also disables execution of plugin callbacks on +all mouse events. See Local Tasks for +more information about plugins and browser-based analysis. + +

    +Within a polygon, if you press meta and click the mouse on the +polygon border, a new point will be added at that point. If you press +the meta key and click on an existing point, it will be deleted. + +

    +

    Drag and Drop FITS Images

    +

    +You can drag and drop FITS images and binary tables onto JS9 to +display the image data. All browser-based functions (scaling, +colormap, pan, zoom, regions, WCS) should work as expected. You can +run server-side analysis tasks on these data files if the back-end +server is on your local host machine. In this case, you must set your +DataPath variable in the Analysis menu to help JS9 locate the original +data file. + +

    Last updated: September 4, 2014
    +
    + + + diff --git a/help/webpage.html b/help/webpage.html new file mode 100644 index 00000000..0891eb46 --- /dev/null +++ b/help/webpage.html @@ -0,0 +1,166 @@ + + + + + +
    +Creating a JS9 Web Page + +

    Creating a JS9 Web Page

    + +

    Adding JS9 to Your Web Page

    +

    +The sample js9basics.html file shows how to add JS9 to a Web page by +assigning JS9 CSS classes to "div" elements. The js9multi.html Web +page goes further by showing how multiple instances of JS9 can be +added to a Web page using unique IDs. + +

    +To start, a few JavaScript and CSS files must be loaded into the Web +page. Ordinarily this is done in the page's header, which typically +will look something like this: +

    +  
    +  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    +  <meta http-equiv="X-UA-Compatible" content="IE=Edge;chrome=1" > 
    +  <link type="image/x-icon" rel="shortcut icon" href="./favicon.ico">
    +  <link type="text/css" rel="stylesheet" href="js9support.css">
    +  <link type="text/css" rel="stylesheet" href="js9.css">
    +  <script type="text/javascript" src="js9support.min.js"></script>
    +  <script type="text/javascript" src="fitsy.min.js"></script>
    +  <script type="text/javascript" src="js9.min.js"></script>
    +  <script type="text/javascript" src="js9plugins.js"></script>
    +  </head>
    +
    +Order is important: you must load js9support.min.js before you load +js9.min.js. You must load the plugin files after you load js9.min.js. +You can simply copy the order of files as specified in the JS9 demo files. + +

    +The text file js9support.txt is a list of the files contained +in js9support.css, js9support.js, js9support.min,js, and +js9plugins.js. Note that jquery v1.11.1 is one of the files loaded by +js9support.js. All of these files are contained in the js and css +sub-directories. + +

    +The fitsy.js and js9.js files (or their minified counterparts) +are loaded separately so that we can offer easy updates. as needed. +Fitsy.js contains basic FITS support and js9.js is the core JS9 module. + +

    +Instances of JS9 are placed on a Web page by assigning JS9 classes +to ordinary "div" elements. The two important JS9 classes are: +

      +
    • JS9: this class will display the main JS9 image window +
    • JS9Menubar: this class will display the JS9 menu bar +
    + +

    +You also can use these classes: +

      +
    • JS9Console: this class will display a console window for executing +typed commands (very retro, but often quite useful!) +
    • JS9Info: this class will display position, value, and +region information (patterned after DS9's display window). It's nicer +and more complete than the default display in the upper left of the +image, but takes up more screen real estate. +
    • JS9Magnifier: this class will display the magnifier window +
    • JS9Panner: this class will display panner window +
    +

    +NB: all of these secondary windows can be displayed as light windows +using the appropriate View menu options. Light windows can +moved around on the page. Also note that if a window is declared +statically in a page, it will not be made available in the View +menu. + +

    +Placement of JS9 div elements should follow standard Web page rules +and constraints. This means that div elements can be placed in any +order to create different graphical views. For example, the +js9basics.html page places the menubar above the image display, in +keeping with the traditional layout of DS9. The entire JS9 construct +is placed in a data cell of a table, next to a data cell containing +data URLs. + +

    +Multiple instances of JS9 can be added to a single Web page. This is done by +giving each JS9 div element a unique ID. In order to tie otherwise separate +JS9 components together, the IDs should be specified as follows: +

      +
    • start with a unique ID name, e.g. "myJS9". +
    • follow with an optional dash or underscore (not needed for the main window) +
    • finish with the type of JS9 element: +"Menubar", "Panner", "Magnifier" "Info", or "Console" +
    + +

    An example of how to define multiple instances of JS9 is found in +the js9multi.html file. Two DS9 instances are defined, having IDs of +"JS9" (the default) and "myJS9". When "myJS9" is the display ID, +"myJS9-Menubar" specifies the associated menu bar and "myJS9Console" +specifies the associated console. + +

    +The ID is not required if there is only one JS9 instance on the page, +since it defaults to "JS9". However, if your site needs to communicate +with clients using the js9 script for external communication, +you can differentiate between clients loading the same JS9-enabled Web +page by supplying a unique ID when the JS9 page is served. + +

    +The js9.css file contains CSS directives for various parts of +JS9. These can be modified (or overwritten) as needed, subject to +ordinary CSS rules. In general, we recommend overwriting CSS rules by +loading a site-specific CSS file after the js9.css file. This makes +updating much easier. + +

    +

    Adding Server-side Analysis Tasks to Your Web Page

    + +

    +Server-side JS9 analysis tasks can be executed using +the Analysis menu, but they also can be executed directly from +the Web page using HTML elements (buttons, forms, etc.) To do this, a +Web page author simply creates the Web interface and calls +either JS9.RunAnalysis() (for buttons, menus, etc.) +or JS9.SubmitAnalysis() (for forms). These are described +in the Local Tasks web page. + +

    +

    Adding Local Analysis Tasks to Your Web Page

    + +

    +JS9 also supports the ability to perform local analysis, i.e., +analysis tasks defined and executed right on your Web page, rather +than being executed by a back-end server. This is accomplished by +offering access to the image data and region information via +a public JS9 API. See the +Local Tasks for more information. + +

    +

    Adding JS9 Display Windows Dynamically

    +

    +JS9 display windows can be created dynamically using the JS9 Public API call +JS9.LoadWindow(). You can create a light window to hold a new +JS9 display on the same page or you can create an entirely separate +pop-up window. See the +JS9 Public API for more information. + +

    +

    Adding Data Files to a Web page

    +

    +Data files are added to a Web page by supplying URLs that call +the JS9.Load() routine. See: +Adding Data Files To a Web Page for more +information. + +

    Last updated: September 4, 2014
    +
    + + + diff --git a/help/yourdata.html b/help/yourdata.html new file mode 100644 index 00000000..7cc86ce8 --- /dev/null +++ b/help/yourdata.html @@ -0,0 +1,77 @@ + + + + + +
    +Displaying Your Data + +

    Displaying Your Data With JS9

    + +

    Loading a FITS File From Your Web Page

    +

    +Once you have your Web page set up, you can make your FITS data files +available on your JS9 Web page by creating URLs that call +the JS9.Load() routine: +

    +    href='javascript:JS9.Load(filename, opts);'
    +
    +where opts can be: +
      +
    • filename is the path relative to the current Web page location +
    • imageOpts: an object containing params to be merged with the +default JS9.imageOpts object +
    +

    +For example: +

    +    href='javascript:JS9.Load("fits/casa.fits");'
    +
    +Clicking on this URL will load the casa.fits file (here, stored in the +fits directory directly beneath the Web page location). If the JS9 +server-side helper is running, it will be alerted about this new file +so that it can run analysis, etc. +

    +To override default image parameters, specify imgOpts parameters as the second argument: +

    +    href='javascript:JS9.Load("fits/m13.fits", {scale:"linear", colormap:"sls"});'
    +
    +

    +To load an image into a specified display, pass the display id in an object as +the last argument in the call. This can be the second or third argument, +depending whether the image object also is passed: +

    +    # the display object can be passed as the second argument ...
    +    href='javascript:JS9.Load("fits/casa.fits", {display: "myJS9"});'
    +    # but when image opts is also passed, it's the third argument  
    +    href='javascript:JS9.Load("fits/3c273.fits", {scale: "linear"}, {display: "myJS9"});'
    +
    +

    + +

    Pre-Loading a File From Your Web Page

    +

    +You can pre-load one or more data files into JS9 when the Web page +itself is loaded by adding the JS9.Preload() routine to +the onload event in your Web page body element: +

    +<body onload="JS9.Preload('fits/casa.fits', 
    +		          'fits/snr.fits', {colormap:'heat'},
    +		          'fits/3c58.fits',
    +		          'fits/m13.fits', {scale:'linear', colormap:'sls'},
    +		          'fits/3c273.fits',
    +		          'fits/ngc1316.fits', {scale:'linear'},
    +		          'fits/ngkper.fits', {colormap:'grey'});">
    +
    +Note that this routine takes a list of images, each of which +optionally can have an associated imgOpts argument. The display +opts can be passed as the final argument and will apply to all images. + +
    Last updated: September 4, 2014
    +
    + + + diff --git a/images/4arrow.png b/images/4arrow.png new file mode 100644 index 00000000..36b875ad Binary files /dev/null and b/images/4arrow.png differ diff --git a/images/close.gif b/images/close.gif new file mode 100644 index 00000000..af01282c Binary files /dev/null and b/images/close.gif differ diff --git a/images/indentbg.gif b/images/indentbg.gif new file mode 100644 index 00000000..d78ffd58 Binary files /dev/null and b/images/indentbg.gif differ diff --git a/images/indentbg2.gif b/images/indentbg2.gif new file mode 100644 index 00000000..5c81d842 Binary files /dev/null and b/images/indentbg2.gif differ diff --git a/images/indentbg2_grey.png b/images/indentbg2_grey.png new file mode 100644 index 00000000..a3ceb2a0 Binary files /dev/null and b/images/indentbg2_grey.png differ diff --git a/images/indentbg_grey.png b/images/indentbg_grey.png new file mode 100644 index 00000000..a8723f17 Binary files /dev/null and b/images/indentbg_grey.png differ diff --git a/images/min.gif b/images/min.gif new file mode 100644 index 00000000..ce83aa82 Binary files /dev/null and b/images/min.gif differ diff --git a/images/resize.gif b/images/resize.gif new file mode 100644 index 00000000..751ff640 Binary files /dev/null and b/images/resize.gif differ diff --git a/images/restore.gif b/images/restore.gif new file mode 100644 index 00000000..d00ca4f2 Binary files /dev/null and b/images/restore.gif differ diff --git a/images/shade.gif b/images/shade.gif new file mode 100644 index 00000000..72b13c58 Binary files /dev/null and b/images/shade.gif differ diff --git a/images/shadeactive.gif b/images/shadeactive.gif new file mode 100644 index 00000000..e5c8097e Binary files /dev/null and b/images/shadeactive.gif differ diff --git a/images/sun.png b/images/sun.png new file mode 100644 index 00000000..42e3fc8a Binary files /dev/null and b/images/sun.png differ diff --git a/index.html b/index.html new file mode 100644 index 00000000..8a0ed557 --- /dev/null +++ b/index.html @@ -0,0 +1,462 @@ + + + + + + + + + + + + + + + + + + + + +SAOimage JS9 + + + +

    JS9: image display right in your browser

    + + + + + +
    +
    +
    + +
    + Questions? Please contact + + Eric Mandel + +
    +
    +
    +
    + +
    + +
    +
    + JS9 is our Web-based implementation of DS9: +
      +
    • display URL-based FITS images and binary tables +
    • drag and drop FITS images and binary tables +
    • change the colormap and scale +
    • manipulate the contrast/bias with the mouse +
    • display pixel values and WCS position information +
    • create and manipulate geometric regions of interest +
    • add your own extensions using plugins and the Public API +
    • perform data analysis (local and server-side) +
    • display RGB composite images +
    • control JS9 from the command line +
    • print images +
    +

    + JS9 can change how we think about image display and analysis, + moving beyond the Desktop into the Web. You can simply drag and + drop a FITS image from your computer onto this JS9 display. All + of basic JS9 functionality is immediately available: zoom, pan, + colormaps, scaling, regions, WCS, analysis ... +

    + You can extend JS9 using the plugin facility in combination + with the JS9 Public API. For example, you can perform + browser-based analysis on the displayed image. Click the + Plugins tab, create a region, and move it around ... +

    + In addition, data files loaded from the server support + server-side analysis (using the original data files on the + back-end server). Server-side analysis can be run, for example, + in response to region changes, with the results displayed back + in your browser. For the Cas-A X-ray image currently being + displayed, click the Analysis tab, choose a task, create a + region, and move it around ... +

    +

    +
    +
    + Energy Spectrum + Counts in Regions + Radial Profile +
    +
    +
    + A quick introduction to JS9, regions, and server-side data analysis: +
      +
    • Press the mouse in the image and move around to change the contrast and bias (to bring out features). +

      +

    • Create one or more regions using the JS9 Region menu. +
    • Pres the mouse inside a region and drag it to the + desired location. +
    • Resize or rotate the region by clicking to + select it, and then moving one of the handles. +
    • Temporarily group regions by pressing the meta key + and using mouse selection. You then can + move/resize/rotate them together. +

      +

    • Choose an analysis to run on the back-end server: +
        +
      • Energy Spectrum plots a histogram of the energy + value of photons in the region(s). +
      • Counts in Regions presents a text display of the + number of photons found in the region(s). +
      • Radial Profile plots the number of photons in each + region of an annulus. +
      +
    • As you move or resize, the task will run and + results will be displayed here. +
    • The region context menu has lots of region options. +
    • These tasks also can be run from the JS9 Analysis menu. +
    + See the Plugins tab for a demo of browser-based analysis. +
    +
    +
    +
    +
    +

    + JS9 plugins allow you to perform browser-based analysis: create a + region and move it around ... +

    + + + + + +
    +

    + See the Local Analysis Tasks help page for info about plugins. +

    +

    +
    + + +
    + Release 1.0 marks the first official public release of + JS9. The core system (images, regions, pan, zoom, scaling, + local plugins, remote analysis) has benefited from more than a + year of beta testing . The Public API is stable and will provide + a solid basis for community-driven extensions. We believe that + JS9 is ready to serve the evolving needs of the astronomical + community. +

    + JS9 work on browsers that support the HTML5 canvas element. It + has been tested on the following browsers: +

      +
    • Firefox 18+ +
    • Chrome +
    • Safari (including the iPad) +
    • IE9 (IE8 doesn't support the HTML5 canvas element) +
    + JS9 is powered by the following technologies, to whom grateful acknowledgment is made: +
      +
    • emscripten for C-to-JavaScript (https://github.com/kripken/emscripten) +
    • dynamic drive for light windows (http://www.dynamicdrive.com/dynamicindex8/dhtmlwindow/index.htm) +
    • fabric.js for regions and other 2D graphics (http://fabricjs.com/) +
    • flot for internal plotting (http://www.flotcharts.org/) +
    • HTML5 for image display and most everything +
    • jquery for programming ease (http://jquery.com/) +
    • jquery.contextMenu for menus (http://medialize.github.io/jQuery-contextMenu/) +
    +

    + JS9 is distributed under the terms of The MIT License. +

    + If you have questions or comments, please contact:
    + Eric Mandel, Harvard-Smithsonian Center for Astrophysics +

    +
    + The JS9 source tar file is available below. This + will suffice to display FITS images via drag-and-drop, and to + utilize browser-based plugins. +

    + If you want the JS9 demo pages to work at your site, you will + need to download the JS9 data tar file. +

    + If you want to configure a back-end helper (for server-side analysis + and creation of png representation files), you will need to + download the funtools tar file. +
    +

    +

    + JS9 also is available on github: +
    +

    + We look forward to your pull requests ... +

    + Development of JS9 at the + Harvard-Smithsonian Center for Astrophysics + is supported by + Smithsonian Institution + and the + Chandra X-ray Science Center. +

    +

    +
    +
    +
    + + + + + + + + + +
    + +About |  +Research |  +Education & Outreach |  +Facilities |  +Opportunities |  +Events |  +Press Room |  +Contacts |  +Support CfA |  +Privacy + +
         +Harvard Logo +Smithsonian Logo + +  HARVARD-SMITHSONIAN CENTER FOR ASTROPHYSICS  |   +60 GARDEN STREET  |   +CAMBRIDGE, MA 02138 + +
    + + + + + + + + + + + + + + + + +
    + + diff --git a/install-sh b/install-sh new file mode 100755 index 00000000..36f96f3e --- /dev/null +++ b/install-sh @@ -0,0 +1,276 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd=$cpprog + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "$0: no input file specified" >&2 + exit 1 +else + : +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d "$dst" ]; then + instcmd=: + chmodcmd="" + else + instcmd=$mkdirprog + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f "$src" ] || [ -d "$src" ] + then + : + else + echo "$0: $src does not exist" >&2 + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "$0: no destination specified" >&2 + exit 1 + else + : + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d "$dst" ] + then + dst=$dst/`basename "$src"` + else + : + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' + ' +IFS="${IFS-$defaultIFS}" + +oIFS=$IFS +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS=$oIFS + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp=$pathcomp$1 + shift + + if [ ! -d "$pathcomp" ] ; + then + $mkdirprog "$pathcomp" + else + : + fi + + pathcomp=$pathcomp/ +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd "$dst" && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename "$dst"` + else + dstfile=`basename "$dst" $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename "$dst"` + else + : + fi + +# Make a couple of temp file names in the proper directory. + + dsttmp=$dstdir/#inst.$$# + rmtmp=$dstdir/#rm.$$# + +# Trap to clean up temp files at exit. + + trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 + trap '(exit $?); exit' 1 2 13 15 + +# Move or copy the file name to the temp name + + $doit $instcmd "$src" "$dsttmp" && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && + +# Now remove or move aside any old file at destination location. We try this +# two ways since rm can't unlink itself on some systems and the destination +# file might be busy for other reasons. In this case, the final cleanup +# might fail but the new file should still install successfully. + +{ + if [ -f "$dstdir/$dstfile" ] + then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || + $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || + { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi +} && + +# Now rename the file to the real destination. + + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + +fi && + +# The final little trick to "correctly" pass the exit status to the exit trap. + +{ + (exit 0); exit +} diff --git a/js/README b/js/README new file mode 100644 index 00000000..fb980a01 --- /dev/null +++ b/js/README @@ -0,0 +1,12 @@ +The following files were minified using the Google Closure Compiler service: + + http://closure-compiler.appspot.com/home + +file date +-------------------------------- ---------- +dhtmlwindow.min.js 02/12/2013 +jquery.contextMenu.min.js 02/12/2013 +jquery.flot.errorbars.min.js 02/12/2013 +jquery.flot.min.js 02/12/2013 +sprintf.min.js 02/12/2013 + diff --git a/js/astroem.js b/js/astroem.js new file mode 100644 index 00000000..5cb6b583 --- /dev/null +++ b/js/astroem.js @@ -0,0 +1,7937 @@ + +// astroem.js: astronomy utilities compiled to js + +var Astroem = (function() { + + +var Module = { + 'noExitRuntime': true +}; + + +// The Module object: Our interface to the outside world. We import +// and export values on it, and do the work to get that through +// closure compiler if necessary. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to do an eval in order to handle the closure compiler +// case, where this code here is minified but Module was defined +// elsewhere (e.g. case 4 above). We also need to check if Module +// already exists (e.g. case 3 above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module; +if (!Module) Module = (typeof Module !== 'undefined' ? Module : null) || {}; + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. +var moduleOverrides = {}; +for (var key in Module) { + if (Module.hasOwnProperty(key)) { + moduleOverrides[key] = Module[key]; + } +} + +// The environment setup code below is customized to use Module. +// *** Environment setup code *** +var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function'; +var ENVIRONMENT_IS_WEB = typeof window === 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + +if (ENVIRONMENT_IS_NODE) { + // Expose functionality in the same simple way that the shells work + // Note that we pollute the global namespace here, otherwise we break in node + if (!Module['print']) Module['print'] = function print(x) { + process['stdout'].write(x + '\n'); + }; + if (!Module['printErr']) Module['printErr'] = function printErr(x) { + process['stderr'].write(x + '\n'); + }; + + var nodeFS = require('fs'); + var nodePath = require('path'); + + Module['read'] = function read(filename, binary) { + filename = nodePath['normalize'](filename); + var ret = nodeFS['readFileSync'](filename); + // The path is absolute if the normalized version is the same as the resolved. + if (!ret && filename != nodePath['resolve'](filename)) { + filename = path.join(__dirname, '..', 'src', filename); + ret = nodeFS['readFileSync'](filename); + } + if (ret && !binary) ret = ret.toString(); + return ret; + }; + + Module['readBinary'] = function readBinary(filename) { return Module['read'](filename, true) }; + + Module['load'] = function load(f) { + globalEval(read(f)); + }; + + Module['arguments'] = process['argv'].slice(2); + + module['exports'] = Module; +} +else if (ENVIRONMENT_IS_SHELL) { + if (!Module['print']) Module['print'] = print; + if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm + + if (typeof read != 'undefined') { + Module['read'] = read; + } else { + Module['read'] = function read() { throw 'no read() available (jsc?)' }; + } + + Module['readBinary'] = function readBinary(f) { + return read(f, 'binary'); + }; + + if (typeof scriptArgs != 'undefined') { + Module['arguments'] = scriptArgs; + } else if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + + this['Module'] = Module; + + eval("if (typeof gc === 'function' && gc.toString().indexOf('[native code]') > 0) var gc = undefined"); // wipe out the SpiderMonkey shell 'gc' function, which can confuse closure (uses it as a minified name, and it is then initted to a non-falsey value unexpectedly) +} +else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + Module['read'] = function read(url) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + }; + + if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + + if (typeof console !== 'undefined') { + if (!Module['print']) Module['print'] = function print(x) { + console.log(x); + }; + if (!Module['printErr']) Module['printErr'] = function printErr(x) { + console.log(x); + }; + } else { + // Probably a worker, and without console.log. We can do very little here... + var TRY_USE_DUMP = false; + if (!Module['print']) Module['print'] = (TRY_USE_DUMP && (typeof(dump) !== "undefined") ? (function(x) { + dump(x); + }) : (function(x) { + // self.postMessage(x); // enable this if you want stdout to be sent as messages + })); + } + + if (ENVIRONMENT_IS_WEB) { + window['Module'] = Module; + } else { + Module['load'] = importScripts; + } +} +else { + // Unreachable because SHELL is dependant on the others + throw 'Unknown runtime environment. Where are we?'; +} + +function globalEval(x) { + eval.call(null, x); +} +if (!Module['load'] == 'undefined' && Module['read']) { + Module['load'] = function load(f) { + globalEval(Module['read'](f)); + }; +} +if (!Module['print']) { + Module['print'] = function(){}; +} +if (!Module['printErr']) { + Module['printErr'] = Module['print']; +} +if (!Module['arguments']) { + Module['arguments'] = []; +} +// *** Environment setup code *** + +// Closure helpers +Module.print = Module['print']; +Module.printErr = Module['printErr']; + +// Callbacks +Module['preRun'] = []; +Module['postRun'] = []; + +// Merge back in the overrides +for (var key in moduleOverrides) { + if (moduleOverrides.hasOwnProperty(key)) { + Module[key] = moduleOverrides[key]; + } +} + + + +// === Auto-generated preamble library stuff === + +//======================================== +// Runtime code shared with compiler +//======================================== + +var Runtime = { + stackSave: function () { + return STACKTOP; + }, + stackRestore: function (stackTop) { + STACKTOP = stackTop; + }, + forceAlign: function (target, quantum) { + quantum = quantum || 4; + if (quantum == 1) return target; + if (isNumber(target) && isNumber(quantum)) { + return Math.ceil(target/quantum)*quantum; + } else if (isNumber(quantum) && isPowerOfTwo(quantum)) { + return '(((' +target + ')+' + (quantum-1) + ')&' + -quantum + ')'; + } + return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum; + }, + isNumberType: function (type) { + return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES; + }, + isPointerType: function isPointerType(type) { + return type[type.length-1] == '*'; +}, + isStructType: function isStructType(type) { + if (isPointerType(type)) return false; + if (isArrayType(type)) return true; + if (/?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types + // See comment in isStructPointerType() + return type[0] == '%'; +}, + INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0}, + FLOAT_TYPES: {"float":0,"double":0}, + or64: function (x, y) { + var l = (x | 0) | (y | 0); + var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + and64: function (x, y) { + var l = (x | 0) & (y | 0); + var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + xor64: function (x, y) { + var l = (x | 0) ^ (y | 0); + var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + getNativeTypeSize: function (type) { + switch (type) { + case 'i1': case 'i8': return 1; + case 'i16': return 2; + case 'i32': return 4; + case 'i64': return 8; + case 'float': return 4; + case 'double': return 8; + default: { + if (type[type.length-1] === '*') { + return Runtime.QUANTUM_SIZE; // A pointer + } else if (type[0] === 'i') { + var bits = parseInt(type.substr(1)); + assert(bits % 8 === 0); + return bits/8; + } else { + return 0; + } + } + } + }, + getNativeFieldSize: function (type) { + return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE); + }, + dedup: function dedup(items, ident) { + var seen = {}; + if (ident) { + return items.filter(function(item) { + if (seen[item[ident]]) return false; + seen[item[ident]] = true; + return true; + }); + } else { + return items.filter(function(item) { + if (seen[item]) return false; + seen[item] = true; + return true; + }); + } +}, + set: function set() { + var args = typeof arguments[0] === 'object' ? arguments[0] : arguments; + var ret = {}; + for (var i = 0; i < args.length; i++) { + ret[args[i]] = 0; + } + return ret; +}, + STACK_ALIGN: 8, + getAlignSize: function (type, size, vararg) { + // we align i64s and doubles on 64-bit boundaries, unlike x86 + if (!vararg && (type == 'i64' || type == 'double')) return 8; + if (!type) return Math.min(size, 8); // align structures internally to 64 bits + return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE); + }, + calculateStructAlignment: function calculateStructAlignment(type) { + type.flatSize = 0; + type.alignSize = 0; + var diffs = []; + var prev = -1; + var index = 0; + type.flatIndexes = type.fields.map(function(field) { + index++; + var size, alignSize; + if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) { + size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s. + alignSize = Runtime.getAlignSize(field, size); + } else if (Runtime.isStructType(field)) { + if (field[1] === '0') { + // this is [0 x something]. When inside another structure like here, it must be at the end, + // and it adds no size + // XXX this happens in java-nbody for example... assert(index === type.fields.length, 'zero-length in the middle!'); + size = 0; + if (Types.types[field]) { + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } else { + alignSize = type.alignSize || QUANTUM_SIZE; + } + } else { + size = Types.types[field].flatSize; + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } + } else if (field[0] == 'b') { + // bN, large number field, like a [N x i8] + size = field.substr(1)|0; + alignSize = 1; + } else if (field[0] === '<') { + // vector type + size = alignSize = Types.types[field].flatSize; // fully aligned + } else if (field[0] === 'i') { + // illegal integer field, that could not be legalized because it is an internal structure field + // it is ok to have such fields, if we just use them as markers of field size and nothing more complex + size = alignSize = parseInt(field.substr(1))/8; + assert(size % 1 === 0, 'cannot handle non-byte-size field ' + field); + } else { + assert(false, 'invalid type for calculateStructAlignment'); + } + if (type.packed) alignSize = 1; + type.alignSize = Math.max(type.alignSize, alignSize); + var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory + type.flatSize = curr + size; + if (prev >= 0) { + diffs.push(curr-prev); + } + prev = curr; + return curr; + }); + if (type.name_ && type.name_[0] === '[') { + // arrays have 2 elements, so we get the proper difference. then we scale here. that way we avoid + // allocating a potentially huge array for [999999 x i8] etc. + type.flatSize = parseInt(type.name_.substr(1))*type.flatSize/2; + } + type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize); + if (diffs.length == 0) { + type.flatFactor = type.flatSize; + } else if (Runtime.dedup(diffs).length == 1) { + type.flatFactor = diffs[0]; + } + type.needsFlattening = (type.flatFactor != 1); + return type.flatIndexes; + }, + generateStructInfo: function (struct, typeName, offset) { + var type, alignment; + if (typeName) { + offset = offset || 0; + type = (typeof Types === 'undefined' ? Runtime.typeInfo : Types.types)[typeName]; + if (!type) return null; + if (type.fields.length != struct.length) { + printErr('Number of named fields must match the type for ' + typeName + ': possibly duplicate struct names. Cannot return structInfo'); + return null; + } + alignment = type.flatIndexes; + } else { + var type = { fields: struct.map(function(item) { return item[0] }) }; + alignment = Runtime.calculateStructAlignment(type); + } + var ret = { + __size__: type.flatSize + }; + if (typeName) { + struct.forEach(function(item, i) { + if (typeof item === 'string') { + ret[item] = alignment[i] + offset; + } else { + // embedded struct + var key; + for (var k in item) key = k; + ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]); + } + }); + } else { + struct.forEach(function(item, i) { + ret[item[1]] = alignment[i]; + }); + } + return ret; + }, + dynCall: function (sig, ptr, args) { + if (args && args.length) { + if (!args.splice) args = Array.prototype.slice.call(args); + args.splice(0, 0, ptr); + return Module['dynCall_' + sig].apply(null, args); + } else { + return Module['dynCall_' + sig].call(null, ptr); + } + }, + functionPointers: [], + addFunction: function (func) { + for (var i = 0; i < Runtime.functionPointers.length; i++) { + if (!Runtime.functionPointers[i]) { + Runtime.functionPointers[i] = func; + return 2*(1 + i); + } + } + throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; + }, + removeFunction: function (index) { + Runtime.functionPointers[(index-2)/2] = null; + }, + getAsmConst: function (code, numArgs) { + // code is a constant string on the heap, so we can cache these + if (!Runtime.asmConstCache) Runtime.asmConstCache = {}; + var func = Runtime.asmConstCache[code]; + if (func) return func; + var args = []; + for (var i = 0; i < numArgs; i++) { + args.push(String.fromCharCode(36) + i); // $0, $1 etc + } + var source = Pointer_stringify(code); + if (source[0] === '"') { + // tolerate EM_ASM("..code..") even though EM_ASM(..code..) is correct + if (source.indexOf('"', 1) === source.length-1) { + source = source.substr(1, source.length-2); + } else { + // something invalid happened, e.g. EM_ASM("..code($0)..", input) + abort('invalid EM_ASM input |' + source + '|. Please use EM_ASM(..code..) (no quotes) or EM_ASM({ ..code($0).. }, input) (to input values)'); + } + } + try { + var evalled = eval('(function(' + args.join(',') + '){ ' + source + ' })'); // new Function does not allow upvars in node + } catch(e) { + Module.printErr('error in executing inline EM_ASM code: ' + e + ' on: \n\n' + source + '\n\nwith args |' + args + '| (make sure to use the right one out of EM_ASM, EM_ASM_ARGS, etc.)'); + throw e; + } + return Runtime.asmConstCache[code] = evalled; + }, + warnOnce: function (text) { + if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; + if (!Runtime.warnOnce.shown[text]) { + Runtime.warnOnce.shown[text] = 1; + Module.printErr(text); + } + }, + funcWrappers: {}, + getFuncWrapper: function (func, sig) { + assert(sig); + if (!Runtime.funcWrappers[func]) { + Runtime.funcWrappers[func] = function dynCall_wrapper() { + return Runtime.dynCall(sig, func, arguments); + }; + } + return Runtime.funcWrappers[func]; + }, + UTF8Processor: function () { + var buffer = []; + var needed = 0; + this.processCChar = function (code) { + code = code & 0xFF; + + if (buffer.length == 0) { + if ((code & 0x80) == 0x00) { // 0xxxxxxx + return String.fromCharCode(code); + } + buffer.push(code); + if ((code & 0xE0) == 0xC0) { // 110xxxxx + needed = 1; + } else if ((code & 0xF0) == 0xE0) { // 1110xxxx + needed = 2; + } else { // 11110xxx + needed = 3; + } + return ''; + } + + if (needed) { + buffer.push(code); + needed--; + if (needed > 0) return ''; + } + + var c1 = buffer[0]; + var c2 = buffer[1]; + var c3 = buffer[2]; + var c4 = buffer[3]; + var ret; + if (buffer.length == 2) { + ret = String.fromCharCode(((c1 & 0x1F) << 6) | (c2 & 0x3F)); + } else if (buffer.length == 3) { + ret = String.fromCharCode(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); + } else { + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + var codePoint = ((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) | + ((c3 & 0x3F) << 6) | (c4 & 0x3F); + ret = String.fromCharCode( + Math.floor((codePoint - 0x10000) / 0x400) + 0xD800, + (codePoint - 0x10000) % 0x400 + 0xDC00); + } + buffer.length = 0; + return ret; + } + this.processJSString = function processJSString(string) { + /* TODO: use TextEncoder when present, + var encoder = new TextEncoder(); + encoder['encoding'] = "utf-8"; + var utf8Array = encoder['encode'](aMsg.data); + */ + string = unescape(encodeURIComponent(string)); + var ret = []; + for (var i = 0; i < string.length; i++) { + ret.push(string.charCodeAt(i)); + } + return ret; + } + }, + getCompilerSetting: function (name) { + throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work'; + }, + stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = (((STACKTOP)+7)&-8); return ret; }, + staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = (((STATICTOP)+7)&-8); return ret; }, + dynamicAlloc: function (size) { var ret = DYNAMICTOP;DYNAMICTOP = (DYNAMICTOP + size)|0;DYNAMICTOP = (((DYNAMICTOP)+7)&-8); if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();; return ret; }, + alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 8))*(quantum ? quantum : 8); return ret; }, + makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+((low>>>0)))+((+((high>>>0)))*(+4294967296))) : ((+((low>>>0)))+((+((high|0)))*(+4294967296)))); return ret; }, + GLOBAL_BASE: 8, + QUANTUM_SIZE: 4, + __dummy__: 0 +} + + +Module['Runtime'] = Runtime; + + + + + + + + + +//======================================== +// Runtime essentials +//======================================== + +var __THREW__ = 0; // Used in checking for thrown exceptions. + +var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort() +var EXITSTATUS = 0; + +var undef = 0; +// tempInt is used for 32-bit signed values or smaller. tempBigInt is used +// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt +var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD, tempDouble, tempFloat; +var tempI64, tempI64b; +var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9; + +function assert(condition, text) { + if (!condition) { + abort('Assertion failed: ' + text); + } +} + +var globalScope = this; + +// C calling interface. A convenient way to call C functions (in C files, or +// defined with extern "C"). +// +// Note: LLVM optimizations can inline and remove functions, after which you will not be +// able to call them. Closure can also do so. To avoid that, add your function to +// the exports using something like +// +// -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]' +// +// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C") +// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and +// 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit). +// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType, +// except that 'array' is not possible (there is no way for us to know the length of the array) +// @param args An array of the arguments to the function, as native JS values (as in returnType) +// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack). +// @return The return value, as a native JS value (as in returnType) +function ccall(ident, returnType, argTypes, args) { + return ccallFunc(getCFunc(ident), returnType, argTypes, args); +} +Module["ccall"] = ccall; + +// Returns the C function with a specified identifier (for C++, you need to do manual name mangling) +function getCFunc(ident) { + try { + var func = Module['_' + ident]; // closure exported function + if (!func) func = eval('_' + ident); // explicit lookup + } catch(e) { + } + assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)'); + return func; +} + +// Internal function that does a C call using a function, not an identifier +function ccallFunc(func, returnType, argTypes, args) { + var stack = 0; + function toC(value, type) { + if (type == 'string') { + if (value === null || value === undefined || value === 0) return 0; // null string + value = intArrayFromString(value); + type = 'array'; + } + if (type == 'array') { + if (!stack) stack = Runtime.stackSave(); + var ret = Runtime.stackAlloc(value.length); + writeArrayToMemory(value, ret); + return ret; + } + return value; + } + function fromC(value, type) { + if (type == 'string') { + return Pointer_stringify(value); + } + assert(type != 'array'); + return value; + } + var i = 0; + var cArgs = args ? args.map(function(arg) { + return toC(arg, argTypes[i++]); + }) : []; + var ret = fromC(func.apply(null, cArgs), returnType); + if (stack) Runtime.stackRestore(stack); + return ret; +} + +// Returns a native JS wrapper for a C function. This is similar to ccall, but +// returns a function you can call repeatedly in a normal way. For example: +// +// var my_function = cwrap('my_c_function', 'number', ['number', 'number']); +// alert(my_function(5, 22)); +// alert(my_function(99, 12)); +// +function cwrap(ident, returnType, argTypes) { + var func = getCFunc(ident); + return function() { + return ccallFunc(func, returnType, argTypes, Array.prototype.slice.call(arguments)); + } +} +Module["cwrap"] = cwrap; + +// Sets a value in memory in a dynamic way at run-time. Uses the +// type data. This is the same as makeSetValue, except that +// makeSetValue is done at compile-time and generates the needed +// code then, whereas this function picks the right code at +// run-time. +// Note that setValue and getValue only do *aligned* writes and reads! +// Note that ccall uses JS types as for defining types, while setValue and +// getValue need LLVM types ('i8', 'i32') - this is a lower-level operation +function setValue(ptr, value, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': HEAP8[(ptr)]=value; break; + case 'i8': HEAP8[(ptr)]=value; break; + case 'i16': HEAP16[((ptr)>>1)]=value; break; + case 'i32': HEAP32[((ptr)>>2)]=value; break; + case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= (+1) ? (tempDouble > (+0) ? ((Math_min((+(Math_floor((tempDouble)/(+4294967296)))), (+4294967295)))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/(+4294967296))))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break; + case 'float': HEAPF32[((ptr)>>2)]=value; break; + case 'double': HEAPF64[((ptr)>>3)]=value; break; + default: abort('invalid type for setValue: ' + type); + } +} +Module['setValue'] = setValue; + +// Parallel to setValue. +function getValue(ptr, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': return HEAP8[(ptr)]; + case 'i8': return HEAP8[(ptr)]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': return HEAP32[((ptr)>>2)]; + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + default: abort('invalid type for setValue: ' + type); + } + return null; +} +Module['getValue'] = getValue; + +var ALLOC_NORMAL = 0; // Tries to use _malloc() +var ALLOC_STACK = 1; // Lives for the duration of the current function call +var ALLOC_STATIC = 2; // Cannot be freed +var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk +var ALLOC_NONE = 4; // Do not allocate +Module['ALLOC_NORMAL'] = ALLOC_NORMAL; +Module['ALLOC_STACK'] = ALLOC_STACK; +Module['ALLOC_STATIC'] = ALLOC_STATIC; +Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC; +Module['ALLOC_NONE'] = ALLOC_NONE; + +// allocate(): This is for internal use. You can use it yourself as well, but the interface +// is a little tricky (see docs right below). The reason is that it is optimized +// for multiple syntaxes to save space in generated code. So you should +// normally not use allocate(), and instead allocate memory using _malloc(), +// initialize it with setValue(), and so forth. +// @slab: An array of data, or a number. If a number, then the size of the block to allocate, +// in *bytes* (note that this is sometimes confusing: the next parameter does not +// affect this!) +// @types: Either an array of types, one for each byte (or 0 if no type at that position), +// or a single type which is used for the entire block. This only matters if there +// is initial data - if @slab is a number, then this does not matter at all and is +// ignored. +// @allocator: How to allocate memory, see ALLOC_* +function allocate(slab, types, allocator, ptr) { + var zeroinit, size; + if (typeof slab === 'number') { + zeroinit = true; + size = slab; + } else { + zeroinit = false; + size = slab.length; + } + + var singleType = typeof types === 'string' ? types : null; + + var ret; + if (allocator == ALLOC_NONE) { + ret = ptr; + } else { + ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); + } + + if (zeroinit) { + var ptr = ret, stop; + assert((ret & 3) == 0); + stop = ret + (size & ~3); + for (; ptr < stop; ptr += 4) { + HEAP32[((ptr)>>2)]=0; + } + stop = ret + size; + while (ptr < stop) { + HEAP8[((ptr++)|0)]=0; + } + return ret; + } + + if (singleType === 'i8') { + if (slab.subarray || slab.slice) { + HEAPU8.set(slab, ret); + } else { + HEAPU8.set(new Uint8Array(slab), ret); + } + return ret; + } + + var i = 0, type, typeSize, previousType; + while (i < size) { + var curr = slab[i]; + + if (typeof curr === 'function') { + curr = Runtime.getFunctionIndex(curr); + } + + type = singleType || types[i]; + if (type === 0) { + i++; + continue; + } + + if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later + + setValue(ret+i, curr, type); + + // no need to look up size unless type changes, so cache it + if (previousType !== type) { + typeSize = Runtime.getNativeTypeSize(type); + previousType = type; + } + i += typeSize; + } + + return ret; +} +Module['allocate'] = allocate; + +function Pointer_stringify(ptr, /* optional */ length) { + // TODO: use TextDecoder + // Find the length, and check for UTF while doing so + var hasUtf = false; + var t; + var i = 0; + while (1) { + t = HEAPU8[(((ptr)+(i))|0)]; + if (t >= 128) hasUtf = true; + else if (t == 0 && !length) break; + i++; + if (length && i == length) break; + } + if (!length) length = i; + + var ret = ''; + + if (!hasUtf) { + var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack + var curr; + while (length > 0) { + curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); + ret = ret ? ret + curr : curr; + ptr += MAX_CHUNK; + length -= MAX_CHUNK; + } + return ret; + } + + var utf8 = new Runtime.UTF8Processor(); + for (i = 0; i < length; i++) { + t = HEAPU8[(((ptr)+(i))|0)]; + ret += utf8.processCChar(t); + } + return ret; +} +Module['Pointer_stringify'] = Pointer_stringify; + +// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns +// a copy of that string as a Javascript String object. +function UTF16ToString(ptr) { + var i = 0; + + var str = ''; + while (1) { + var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; + if (codeUnit == 0) + return str; + ++i; + // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through. + str += String.fromCharCode(codeUnit); + } +} +Module['UTF16ToString'] = UTF16ToString; + +// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', +// null-terminated and encoded in UTF16LE form. The copy will require at most (str.length*2+1)*2 bytes of space in the HEAP. +function stringToUTF16(str, outPtr) { + for(var i = 0; i < str.length; ++i) { + // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. + var codeUnit = str.charCodeAt(i); // possibly a lead surrogate + HEAP16[(((outPtr)+(i*2))>>1)]=codeUnit; + } + // Null-terminate the pointer to the HEAP. + HEAP16[(((outPtr)+(str.length*2))>>1)]=0; +} +Module['stringToUTF16'] = stringToUTF16; + +// Given a pointer 'ptr' to a null-terminated UTF32LE-encoded string in the emscripten HEAP, returns +// a copy of that string as a Javascript String object. +function UTF32ToString(ptr) { + var i = 0; + + var str = ''; + while (1) { + var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; + if (utf32 == 0) + return str; + ++i; + // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. + if (utf32 >= 0x10000) { + var ch = utf32 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } else { + str += String.fromCharCode(utf32); + } + } +} +Module['UTF32ToString'] = UTF32ToString; + +// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', +// null-terminated and encoded in UTF32LE form. The copy will require at most (str.length+1)*4 bytes of space in the HEAP, +// but can use less, since str.length does not return the number of characters in the string, but the number of UTF-16 code units in the string. +function stringToUTF32(str, outPtr) { + var iChar = 0; + for(var iCodeUnit = 0; iCodeUnit < str.length; ++iCodeUnit) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. + var codeUnit = str.charCodeAt(iCodeUnit); // possibly a lead surrogate + if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { + var trailSurrogate = str.charCodeAt(++iCodeUnit); + codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); + } + HEAP32[(((outPtr)+(iChar*4))>>2)]=codeUnit; + ++iChar; + } + // Null-terminate the pointer to the HEAP. + HEAP32[(((outPtr)+(iChar*4))>>2)]=0; +} +Module['stringToUTF32'] = stringToUTF32; + +function demangle(func) { + var i = 3; + // params, etc. + var basicTypes = { + 'v': 'void', + 'b': 'bool', + 'c': 'char', + 's': 'short', + 'i': 'int', + 'l': 'long', + 'f': 'float', + 'd': 'double', + 'w': 'wchar_t', + 'a': 'signed char', + 'h': 'unsigned char', + 't': 'unsigned short', + 'j': 'unsigned int', + 'm': 'unsigned long', + 'x': 'long long', + 'y': 'unsigned long long', + 'z': '...' + }; + var subs = []; + var first = true; + function dump(x) { + //return; + if (x) Module.print(x); + Module.print(func); + var pre = ''; + for (var a = 0; a < i; a++) pre += ' '; + Module.print (pre + '^'); + } + function parseNested() { + i++; + if (func[i] === 'K') i++; // ignore const + var parts = []; + while (func[i] !== 'E') { + if (func[i] === 'S') { // substitution + i++; + var next = func.indexOf('_', i); + var num = func.substring(i, next) || 0; + parts.push(subs[num] || '?'); + i = next+1; + continue; + } + if (func[i] === 'C') { // constructor + parts.push(parts[parts.length-1]); + i += 2; + continue; + } + var size = parseInt(func.substr(i)); + var pre = size.toString().length; + if (!size || !pre) { i--; break; } // counter i++ below us + var curr = func.substr(i + pre, size); + parts.push(curr); + subs.push(curr); + i += pre + size; + } + i++; // skip E + return parts; + } + function parse(rawList, limit, allowVoid) { // main parser + limit = limit || Infinity; + var ret = '', list = []; + function flushList() { + return '(' + list.join(', ') + ')'; + } + var name; + if (func[i] === 'N') { + // namespaced N-E + name = parseNested().join('::'); + limit--; + if (limit === 0) return rawList ? [name] : name; + } else { + // not namespaced + if (func[i] === 'K' || (first && func[i] === 'L')) i++; // ignore const and first 'L' + var size = parseInt(func.substr(i)); + if (size) { + var pre = size.toString().length; + name = func.substr(i + pre, size); + i += pre + size; + } + } + first = false; + if (func[i] === 'I') { + i++; + var iList = parse(true); + var iRet = parse(true, 1, true); + ret += iRet[0] + ' ' + name + '<' + iList.join(', ') + '>'; + } else { + ret = name; + } + paramLoop: while (i < func.length && limit-- > 0) { + //dump('paramLoop'); + var c = func[i++]; + if (c in basicTypes) { + list.push(basicTypes[c]); + } else { + switch (c) { + case 'P': list.push(parse(true, 1, true)[0] + '*'); break; // pointer + case 'R': list.push(parse(true, 1, true)[0] + '&'); break; // reference + case 'L': { // literal + i++; // skip basic type + var end = func.indexOf('E', i); + var size = end - i; + list.push(func.substr(i, size)); + i += size + 2; // size + 'EE' + break; + } + case 'A': { // array + var size = parseInt(func.substr(i)); + i += size.toString().length; + if (func[i] !== '_') throw '?'; + i++; // skip _ + list.push(parse(true, 1, true)[0] + ' [' + size + ']'); + break; + } + case 'E': break paramLoop; + default: ret += '?' + c; break paramLoop; + } + } + } + if (!allowVoid && list.length === 1 && list[0] === 'void') list = []; // avoid (void) + if (rawList) { + if (ret) { + list.push(ret + '?'); + } + return list; + } else { + return ret + flushList(); + } + } + try { + // Special-case the entry point, since its name differs from other name mangling. + if (func == 'Object._main' || func == '_main') { + return 'main()'; + } + if (typeof func === 'number') func = Pointer_stringify(func); + if (func[0] !== '_') return func; + if (func[1] !== '_') return func; // C function + if (func[2] !== 'Z') return func; + switch (func[3]) { + case 'n': return 'operator new()'; + case 'd': return 'operator delete()'; + } + return parse(); + } catch(e) { + return func; + } +} + +function demangleAll(text) { + return text.replace(/__Z[\w\d_]+/g, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']') }); +} + +function stackTrace() { + var stack = new Error().stack; + return stack ? demangleAll(stack) : '(no stack trace available)'; // Stack trace is not available at least on IE10 and Safari 6. +} + +// Memory management + +var PAGE_SIZE = 4096; +function alignMemoryPage(x) { + return (x+4095)&-4096; +} + +var HEAP; +var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; + +var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area +var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area +var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk + +function enlargeMemory() { + abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.'); +} + +var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; +var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 67108864; +var FAST_MEMORY = Module['FAST_MEMORY'] || 2097152; + +var totalMemory = 4096; +while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) { + if (totalMemory < 16*1024*1024) { + totalMemory *= 2; + } else { + totalMemory += 16*1024*1024 + } +} +if (totalMemory !== TOTAL_MEMORY) { + Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be more reasonable'); + TOTAL_MEMORY = totalMemory; +} + +// Initialize the runtime's memory +// check for full engine support (use string 'subarray' to avoid closure compiler confusion) +assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']), + 'JS engine does not provide full typed array support'); + +var buffer = new ArrayBuffer(TOTAL_MEMORY); +HEAP8 = new Int8Array(buffer); +HEAP16 = new Int16Array(buffer); +HEAP32 = new Int32Array(buffer); +HEAPU8 = new Uint8Array(buffer); +HEAPU16 = new Uint16Array(buffer); +HEAPU32 = new Uint32Array(buffer); +HEAPF32 = new Float32Array(buffer); +HEAPF64 = new Float64Array(buffer); + +// Endianness check (note: assumes compiler arch was little-endian) +HEAP32[0] = 255; +assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system'); + +Module['HEAP'] = HEAP; +Module['HEAP8'] = HEAP8; +Module['HEAP16'] = HEAP16; +Module['HEAP32'] = HEAP32; +Module['HEAPU8'] = HEAPU8; +Module['HEAPU16'] = HEAPU16; +Module['HEAPU32'] = HEAPU32; +Module['HEAPF32'] = HEAPF32; +Module['HEAPF64'] = HEAPF64; + +function callRuntimeCallbacks(callbacks) { + while(callbacks.length > 0) { + var callback = callbacks.shift(); + if (typeof callback == 'function') { + callback(); + continue; + } + var func = callback.func; + if (typeof func === 'number') { + if (callback.arg === undefined) { + Runtime.dynCall('v', func); + } else { + Runtime.dynCall('vi', func, [callback.arg]); + } + } else { + func(callback.arg === undefined ? null : callback.arg); + } + } +} + +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATMAIN__ = []; // functions called when main() is to be run +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the runtime has exited + +var runtimeInitialized = false; + +function preRun() { + // compatibility - merge in anything from Module['preRun'] at this time + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + callRuntimeCallbacks(__ATPRERUN__); +} + +function ensureInitRuntime() { + if (runtimeInitialized) return; + runtimeInitialized = true; + callRuntimeCallbacks(__ATINIT__); +} + +function preMain() { + callRuntimeCallbacks(__ATMAIN__); +} + +function exitRuntime() { + callRuntimeCallbacks(__ATEXIT__); +} + +function postRun() { + // compatibility - merge in anything from Module['postRun'] at this time + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + callRuntimeCallbacks(__ATPOSTRUN__); +} + +function addOnPreRun(cb) { + __ATPRERUN__.unshift(cb); +} +Module['addOnPreRun'] = Module.addOnPreRun = addOnPreRun; + +function addOnInit(cb) { + __ATINIT__.unshift(cb); +} +Module['addOnInit'] = Module.addOnInit = addOnInit; + +function addOnPreMain(cb) { + __ATMAIN__.unshift(cb); +} +Module['addOnPreMain'] = Module.addOnPreMain = addOnPreMain; + +function addOnExit(cb) { + __ATEXIT__.unshift(cb); +} +Module['addOnExit'] = Module.addOnExit = addOnExit; + +function addOnPostRun(cb) { + __ATPOSTRUN__.unshift(cb); +} +Module['addOnPostRun'] = Module.addOnPostRun = addOnPostRun; + +// Tools + +// This processes a JS string into a C-line array of numbers, 0-terminated. +// For LLVM-originating strings, see parser.js:parseLLVMString function +function intArrayFromString(stringy, dontAddNull, length /* optional */) { + var ret = (new Runtime.UTF8Processor()).processJSString(stringy); + if (length) { + ret.length = length; + } + if (!dontAddNull) { + ret.push(0); + } + return ret; +} +Module['intArrayFromString'] = intArrayFromString; + +function intArrayToString(array) { + var ret = []; + for (var i = 0; i < array.length; i++) { + var chr = array[i]; + if (chr > 0xFF) { + chr &= 0xFF; + } + ret.push(String.fromCharCode(chr)); + } + return ret.join(''); +} +Module['intArrayToString'] = intArrayToString; + +// Write a Javascript array to somewhere in the heap +function writeStringToMemory(string, buffer, dontAddNull) { + var array = intArrayFromString(string, dontAddNull); + var i = 0; + while (i < array.length) { + var chr = array[i]; + HEAP8[(((buffer)+(i))|0)]=chr; + i = i + 1; + } +} +Module['writeStringToMemory'] = writeStringToMemory; + +function writeArrayToMemory(array, buffer) { + for (var i = 0; i < array.length; i++) { + HEAP8[(((buffer)+(i))|0)]=array[i]; + } +} +Module['writeArrayToMemory'] = writeArrayToMemory; + +function writeAsciiToMemory(str, buffer, dontAddNull) { + for (var i = 0; i < str.length; i++) { + HEAP8[(((buffer)+(i))|0)]=str.charCodeAt(i); + } + if (!dontAddNull) HEAP8[(((buffer)+(str.length))|0)]=0; +} +Module['writeAsciiToMemory'] = writeAsciiToMemory; + +function unSign(value, bits, ignore) { + if (value >= 0) { + return value; + } + return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts + : Math.pow(2, bits) + value; +} +function reSign(value, bits, ignore) { + if (value <= 0) { + return value; + } + var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 + : Math.pow(2, bits-1); + if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that + // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors + // TODO: In i64 mode 1, resign the two parts separately and safely + value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts + } + return value; +} + +// check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 ) +if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) { + var ah = a >>> 16; + var al = a & 0xffff; + var bh = b >>> 16; + var bl = b & 0xffff; + return (al*bl + ((ah*bl + al*bh) << 16))|0; +}; +Math.imul = Math['imul']; + + +var Math_abs = Math.abs; +var Math_cos = Math.cos; +var Math_sin = Math.sin; +var Math_tan = Math.tan; +var Math_acos = Math.acos; +var Math_asin = Math.asin; +var Math_atan = Math.atan; +var Math_atan2 = Math.atan2; +var Math_exp = Math.exp; +var Math_log = Math.log; +var Math_sqrt = Math.sqrt; +var Math_ceil = Math.ceil; +var Math_floor = Math.floor; +var Math_pow = Math.pow; +var Math_imul = Math.imul; +var Math_fround = Math.fround; +var Math_min = Math.min; + +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// PRE_RUN_ADDITIONS (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled + +function addRunDependency(id) { + runDependencies++; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } +} +Module['addRunDependency'] = addRunDependency; +function removeRunDependency(id) { + runDependencies--; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } +} +Module['removeRunDependency'] = removeRunDependency; + +Module["preloadedImages"] = {}; // maps url to image data +Module["preloadedAudios"] = {}; // maps url to audio data + + +var memoryInitializer = null; + +// === Body === + + + + + +STATIC_BASE = 8; + +STATICTOP = STATIC_BASE + Runtime.alignMemory(28211); +/* global initializers */ __ATINIT__.push(); + + +/* memory initializer */ allocate([37,46,51,102,32,37,46,51,102,0,0,0,0,0,0,0,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,0,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,0,108,105,110,101,97,114,0,0,100,101,103,114,101,101,115,0,115,101,120,97,103,101,115,105,109,97,108,0,0,0,0,0,59,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,115,40,0,0,0,0,0,37,46,54,102,44,32,37,46,54,102,0,0,0,0,0,0,37,115,44,32,37,115,0,0,112,111,108,121,103,111,110,0,44,32,37,46,54,102,44,32,37,46,54,102,0,0,0,0,44,32,37,115,44,32,37,115,0,0,0,0,0,0,0,0,44,32,37,46,50,102,34,0,44,32,37,46,54,102,39,0,44,32,37,46,54,102,100,0,98,111,120,0,0,0,0,0,101,108,108,105,112,115,101,0,44,32,37,46,51,102,0,0,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,102,32,37,102], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE); +/* memory initializer */ allocate([1,0,0,0,0,0,0,0,87,67,83,73,78,73,84,78,58,32,87,67,83,32,110,97,109,101,32,37,115,32,110,111,116,32,109,97,116,99,104,101,100,32,105,110,32,70,73,84,83,32,104,101,97,100,101,114,10,0,0,0,0,0,0,0,87,67,83,78,65,77,69,0,87,67,83,65,88,69,83,0,78,65,88,73,83,0,0,0,87,67,83,68,73,77,0,0,87,67,83,73,78,73,84,58,32,78,111,32,87,67,83,65,88,69,83,44,32,78,65,88,73,83,44,32,111,114,32,87,67,83,68,73,77,32,107,101,121,119,111,114,100,0,0,0,78,65,88,73,83,49,0,0,73,77,65,71,69,87,0,0,87,67,83,73,78,73,84,58,32,78,111,32,78,65,88,73,83,49,32,111,114,32,73,77,65,71,69,87,32,107,101,121,119,111,114,100,0,0,0,0,78,65,88,73,83,50,0,0,73,77,65,71,69,72,0,0,87,67,83,73,78,73,84,58,32,78,111,32,78,65,88,73,83,50,32,111,114,32,73,77,65,71,69,72,32,107,101,121,119,111,114,100,0,0,0,0,37,100,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,77,105,115,115,105,110,103,32,107,101,121,119,111,114,100,32,37,115,32,97,115,115,117,109,101,100,32,49,10,0,0,67,84,89,80,69,0,0,0,45,84,65,66,0,0,0,0,73,78,83,84,82,85,77,69,0,0,0,0,0,0,0,0,68,69,84,69,67,84,79,82,0,0,0,0,0,0,0,0,68,67,45,70,76,65,71,0,87,67,83,68,69,80,0,0,87,67,83,73,78,73,84,58,32,100,101,112,101,110,100,101,100,32,111,110,32,87,67,83,32,99,111,117,108,100,32,110,111,116,32,98,101,32,115,101,116,0,0,0,0,0,0,0,86,83,79,85,82,67,69,0,90,83,79,85,82,67,69,0,86,69,76,79,67,73,84,89,0,0,0,0,0,0,0,0,67,84,89,80,69,49,0,0,67,84,89,80,69,50,0,0,76,65,84,0,0,0,0,0,68,69,67,0,0,0,0,0,67,84,89,80,69,51,0,0,67,84,89,80,69,52,0,0,67,85,78,73,84,49,0,0,87,65,84,49,0,0,0,0,117,110,105,116,115,0,0,0,112,105,120,101,108,0,0,0,67,85,78,73,84,50,0,0,87,65,84,50,0,0,0,0,67,82,80,73,88,49,0,0,67,82,80,73,88,50,0,0,67,82,86,65,76,49,0,0,67,82,86,65,76,50,0,0,76,79,78,80,79,76,69,0,76,65,84,80,79,76,69,0,80,82,79,74,82,48,0,0,80,82,79,74,80,37,100,0,80,86,37,100,95,49,0,0,80,86,37,100,95,50,0,0,80,86,37,100,95,51,0,0,80,86,37,100,95,37,100,0,67,68,49,95,49,0,0,0,67,68,49,95,50,0,0,0,67,68,50,95,49,0,0,0,67,68,50,95,50,0,0,0,67,79,49,95,49,0,0,0,80,76,65,84,69,0,0,0,67,79,49,95,37,100,0,0,67,79,50,95,49,0,0,0,67,79,50,95,37,100,0,0,67,68,69,76,84,49,0,0,67,68,69,76,84,50,0,0,83,69,67,80,73,88,0,0,80,73,88,83,67,65,76,69,0,0,0,0,0,0,0,0,80,73,88,83,67,65,76,49,0,0,0,0,0,0,0,0,88,80,73,88,83,73,90,69,0,0,0,0,0,0,0,0,83,69,67,80,73,88,49,0,83,69,67,80,73,88,50,0,89,80,73,88,83,73,90,69,0,0,0,0,0,0,0,0,80,73,88,83,67,65,76,50,0,0,0,0,0,0,0,0,80,67,48,48,49,48,48,49,0,0,0,0,0,0,0,0,80,67,48,48,37,49,100,48,48,37,49,100,0,0,0,0,80,67,49,95,49,0,0,0,80,67,37,49,100,95,37,49,100,0,0,0,0,0,0,0,67,82,79,84,65,50,0,0,67,82,79,84,65,49,0,0,87,67,83,73,78,73,84,58,32,115,101,116,116,105,110,103,32,67,68,69,76,84,32,116,111,32,49,0,0,0,0,0,76,73,78,69,65,82,0,0,80,73,88,69,76,0,0,0,77,74,68,45,79,66,83,0,68,65,84,69,45,79,66,83,0,0,0,0,0,0,0,0,68,65,84,69,0,0,0,0,69,80,79,67,72,0,0,0,85,84,0,0,0,0,0,0,85,84,77,73,68,0,0,0,87,67,83,73,78,73,84,67,58,32,78,111,32,105,109,97,103,101,32,115,99,97,108,101,32,102,111,114,32,87,67,83,32,37,99,0,0,0,0,0,80,76,84,82,65,72,0,0,80,76,84,82,65,77,0,0,80,76,84,82,65,83,0,0,80,76,84,68,69,67,83,78,0,0,0,0,0,0,0,0,80,76,84,68,69,67,68,0,80,76,84,68,69,67,77,0,80,76,84,68,69,67,83,0,69,81,85,73,78,79,88,0,70,75,52,0,0,0,0,0,70,75,53,0,0,0,0,0,37,50,46,48,102,58,37,50,46,48,102,58,37,53,46,51,102,32,37,99,37,50,46,48,102,58,37,50,46,48,102,58,37,53,46,51,102,32,37,115,0,0,0,0,0,0,0,0,80,76,84,83,67,65,76,69,0,0,0,0,0,0,0,0,88,80,73,88,69,76,83,90,0,0,0,0,0,0,0,0,89,80,73,88,69,76,83,90,0,0,0,0,0,0,0,0,67,78,80,73,88,49,0,0,67,78,80,73,88,50,0,0,80,80,79,49,0,0,0,0,80,80,79,37,100,0,0,0,65,77,68,88,49,0,0,0,65,77,68,88,37,100,0,0,65,77,68,89,49,0,0,0,65,77,68,89,37,100,0,0,82,65,0,0,0,0,0,0,82,65,45,45,45,68,83,83,0,0,0,0,0,0,0,0,68,69,67,45,45,68,83,83,0,0,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,78,111,32,82,65,32,119,105,116,104,32,83,69,67,80,73,88,44,32,110,111,32,87,67,83,0,0,0,0,0,0,87,67,83,73,78,73,84,32,78,111,32,68,69,67,32,119,105,116,104,32,83,69,67,80,73,88,44,32,110,111,32,87,67,83,0,0,0,0,0,0,76,79,78,71,80,79,76,69,0,0,0,0,0,0,0,0,82,65,45,45,45,84,65,78,0,0,0,0,0,0,0,0,68,69,67,45,45,84,65,78,0,0,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,78,111,32,105,109,97,103,101,32,115,99,97,108,101,0,84,65,78,0,0,0,0,0,42,69,114,114,111,114,42,58,32,105,110,99,111,114,114,101,99,116,32,108,105,110,101,97,114,32,99,111,110,118,101,114,115,105,111,110,32,105,110,32,37,115,0,0,0,0,0,0,87,65,82,78,73,78,71,58,32,83,105,103,110,105,102,105,99,97,110,116,32,105,110,97,99,99,117,114,97,99,121,32,108,105,107,101,108,121,32,116,111,32,111,99,99,117,114,32,105,110,32,112,114,111,106,101,99,116,105,111,110,0,0,0,69,81,85,73,78,79,88,37,99,0,0,0,0,0,0,0,82,65,68,69,67,83,89,83,37,99,0,0,0,0,0,0,82,65,68,69,67,83,89,83,0,0,0,0,0,0,0,0,73,67,82,83,0,0,0,0,71,65,76,0,0,0,0,0,69,67,76,0,0,0,0,0,71,65,76,65,67,84,73,67,0,0,0,0,0,0,0,0,69,67,76,73,80,84,73,67,0,0,0,0,0,0,0,0,83,71,65,76,65,67,84,67,0,0,0,0,0,0,0,0,72,69,76,73,79,69,67,76,0,0,0,0,0,0,0,0,65,76,84,65,90,0,0,0,0,0,0,0,0,0,0,0,68,69,67,0,0,0,0,0,76,79,78,71,0,0,0,0,76,73,78,69,65,82,0,0,80,73,88,69,76,0,0,0,68,69,84,0,0,0,0,0,37,45,52,115,37,52,115,0,78,80,79,76,0,0,0,0,76,65,84,0,0,0,0,0,78,80,79,76,69,0,0,0,83,80,65,45,0,0,0,0,73,77,83,89,83,0,0,0,105,109,115,121,115,0,0,0,37,46,52,102,0,0,0,0,66,49,57,53,48,0,0,0,74,50,48,48,48,0,0,0,37,115,9,37,115,0,0,0,37,115,32,37,115,0,0,0,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,42,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,9,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,32,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,9,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,32,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,9,108,111,110,103,45,110,112,97,0,0,0,0,0,0,0,32,108,111,110,103,45,110,112,97,0,0,0,0,0,0,0,9,108,111,110,103,45,115,112,97,0,0,0,0,0,0,0,32,108,111,110,103,45,115,112,97,0,0,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,67,83,95,67,79,77,77,65,78,68,0,0,0,0,0,87,67,83,95,67,79,77,77,65,78,68,37,100,0,0,0,50,48,48,48,0,0,0,0,50,48,48,48,46,48,0,0,73,67,82,83,0,0,0,0,105,99,114,115,0,0,0,0,70,75,53,0,0,0,0,0,102,107,53,0,0,0,0,0,49,57,53,48,0,0,0,0,49,57,53,48,46,48,0,0,70,75,52,0,0,0,0,0,102,107,52,0,0,0,0,0,112,105,120,101,108,0,0,0,44,66,124,35,100,255,239,63,206,4,147,55,81,230,134,63,201,87,119,237,8,231,115,63,8,49,216,60,72,85,196,190,141,82,239,197,175,26,93,190,79,75,150,130,180,74,73,190,206,4,147,55,81,230,134,191,110,20,118,229,124,255,239,63,190,2,89,23,76,127,252,190,141,82,239,197,175,26,93,62,186,92,192,248,87,85,196,190,213,61,80,36,200,25,210,61,192,143,86,244,8,231,115,191,40,252,144,126,141,121,252,190,190,45,6,62,231,255,239,63,79,75,150,130,180,74,73,62,213,61,80,36,200,25,210,61,56,97,156,141,155,85,196,190,37,201,115,125,31,14,66,191,237,156,102,129,118,135,206,63,237,128,235,138,25,225,219,191,138,238,48,88,55,255,239,63,235,42,147,208,76,230,134,63,26,132,28,8,135,230,115,63,12,31,17,83,34,137,206,191,58,234,232,184,26,217,101,191,7,35,246,9,160,24,137,63,235,42,147,208,76,230,134,191,233,248,162,28,80,255,239,63,8,168,211,46,100,125,252,190,137,181,248,20,0,227,219,63,180,173,102,157,241,125,129,191,174,14,128,184,171,87,97,63,26,132,28,8,135,230,115,191,247,97,247,252,180,122,252,190,137,77,92,117,186,255,239,63,125,150,201,34,100,255,239,63,15,157,207,213,158,230,134,191,92,113,244,103,237,229,115,191,26,77,59,180,100,85,196,62,52,175,17,131,3,27,93,190,173,87,210,121,59,74,73,190,20,1,96,210,158,230,134,63,3,186,248,225,124,255,239,63,250,59,9,220,34,127,252,190,52,175,17,131,3,27,93,62,91,229,82,109,116,85,196,62,232,167,8,110,48,27,210,189,73,225,178,117,237,229,115,63,235,19,108,31,83,119,252,190,10,30,195,64,231,255,239,63,173,87,210,121,59,74,73,62,185,158,187,181,171,23,210,189,73,125,255,4,184,85,196,62,37,201,115,125,31,14,66,191,211,48,124,68,76,137,206,191,34,223,165,212,37,227,219,63,45,6,81,239,144,255,239,63,108,197,229,21,219,230,134,191,214,96,142,220,162,229,115,191,180,174,209,114,160,135,206,63,58,234,232,184,26,217,101,191,180,173,102,157,241,125,129,191,108,197,229,21,219,230,134,63,26,73,6,169,169,255,239,63,26,238,175,96,19,128,252,190,134,170,152,74,63,225,219,191,7,35,246,9,160,24,137,63,174,14,128,184,171,87,97,63,214,96,142,220,162,229,115,63,212,213,62,153,86,117,252,190,150,50,62,6,10,0,240,63,0,0,0,0,0,0,0,0,70,75,52,50,71,65,76,58,32,66,49,57,53,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,52,50,71,65,76,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,52,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,52,58,32,66,49,57,53,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,53,50,71,65,76,58,32,74,50,48,48,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,53,50,71,65,76,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,53,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,53,58,32,74,50,48,48,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,32,37,99,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,0,0,0,0,0,0,0,69,78,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,28,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,37,115,95,49,0,0,0,0,37,115,95,37,100,0,0,0,37,115,95,48,49,0,0,0,37,115,95,48,48,49,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,48,0,0,0,0,0,0,37,100,0,0,0,0,0,0,37,37,46,37,100,102,0,0,37,48,50,100,58,37,48,50,100,58,37,48,57,46,54,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,56,46,53,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,55,46,52,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,52,46,49,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,50,100,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,57,46,54,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,56,46,53,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,55,46,52,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,52,46,49,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,50,100,0,0,0,0,0,0,0,0,37,37,37,100,46,37,100,102,0,0,0,0,0,0,0,0,37,37,37,52,100,0,0,0,37,37,37,100,100], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+4352); +/* memory initializer */ allocate([87,65,84,49,0,0,0,0,87,65,84,50,0,0,0,0,108,111,110,103,112,111,108,101,0,0,0,0,0,0,0,0,114,111,0,0,0,0,0,0,108,110,103,99,111,114,0,0,108,97,116,99,111,114,0,0,84,78,88,95,71,83,69,86,65,76,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,10,0,0,0,0,0,0,0,84,78,88,95,71,83,68,69,82,58,32,111,114,100,101,114,32,111,102,32,100,101,114,105,118,97,116,105,118,101,115,32,99,97,110,110,111,116,32,98,101,32,60,32,48,10,0,0,84,78,88,95,71,83,68,69,82,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,32,37,100,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,120,32,111,114,100,101,114,32,37,100,10,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,121,32,111,114,100,101,114,32,37,100,10,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,120,32,114,97,110,103,101,32,37,102,45,37,102,10,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,121,32,114,97,110,103,101,32,37,102,45,37,102,10,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,32,37,100,10,0,0,87,65,84,49,0,0,0,0,87,65,84,49,95,48,48,49,61,32,39,119,116,121,112,101,61,122,112,120,32,97,120,116,121,112,101,61,114,97,32,112,114,111,106,112,48,61,48,46,32,112,114,111,106,112,49,61,49,46,32,112,114,111,106,112,50,61,48,46,32,112,114,111,106,112,51,61,51,51,55,46,55,52,32,112,114,111,106,39,87,65,84,50,95,48,48,49,61,32,39,119,116,121,112,101,61,122,112,120,32,97,120,116,121,112,101,61,100,101,99,32,112,114,111,106,112,48,61,48,46,32,112,114,111,106,112,49,61,49,46,32,112,114,111,106,112,50,61,48,46,32,112,114,111,106,112,51,61,51,51,55,46,55,52,32,112,114,111,39,0,0,0,0,0,0,0,0,87,65,84,50,0,0,0,0,108,111,110,103,112,111,108,101,0,0,0,0,0,0,0,0,114,111,0,0,0,0,0,0,112,114,111,106,112,37,100,0,108,110,103,99,111,114,0,0,108,97,116,99,111,114,0,0,10,62,32,37,115,37,115,10,10,0,0,0,0,0,0,0,78,111,116,32,101,110,111,117,103,104,32,109,101,109,111,114,121,32,102,111,114,32,0,0,112,111,108,121,32,40,49,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,84,104,101,32,100,105,109,101,110,115,105,111,110,97,108,105,116,121,32,111,102,32,116,104,101,32,112,111,108,121,110,111,109,32,40,37,100,41,32,101,120,99,101,101,100,115,32,116,104,101,32,109,97,120,105,109,117,109,10,97,108,108,111,119,101,100,32,111,110,101,32,40,37,100,41,0,0,0,0,0,42,69,114,114,111,114,42,58,32,0,0,0,0,0,0,0,112,111,108,121,45,62,103,114,111,117,112,32,40,112,111,108,121,45,62,110,100,105,109,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,112,111,108,121,45,62,100,101,103,114,101,101,32,40,112,111,108,121,45,62,110,103,114,111,117,112,32,101,108,101,109,101,110,116,115,41,32,33,0,0,42,69,114,114,111,114,42,58,32,112,111,108,121,110,111,109,105,97,108,32,71,82,79,85,80,32,111,117,116,32,111,102,32,114,97,110,103,101,0,0,0,0,0,0,0,0,0,0,84,104,101,32,100,101,103,114,101,101,32,111,102,32,116,104,101,32,112,111,108,121,110,111,109,32,40,37,100,41,32,101,120,99,101,101,100,115,32,116,104,101,32,109,97,120,105,109,117,109,10,97,108,108,111,119,101,100,32,111,110,101,32,40,37,100,41,0,0,0,0,0,112,111,108,121,45,62,98,97,115,105,115,32,40,112,111,108,121,45,62,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,112,111,108,121,45,62,99,111,101,102,102,32,40,112,111,108,121,45,62,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,42,73,110,116,101,114,110,97,108,32,69,114,114,111,114,42,58,32,79,110,101,32,111,102,32,120,32,111,114,32,101,120,116,98,97,115,105,115,32,115,104,111,117,108,100,32,98,101,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,78,85,76,76,10,105,110,32,0,0,0,0,0,0,0,0,112,111,108,121,95,102,117,110,99,40,41,0,0,0,0,0,97,108,112,104,97,32,40,109,97,116,115,105,122,101,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,98,101,116,97,32,40,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,0,0,118,109,97,116,32,40,110,42,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,119,109,97,116,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,112,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,0,0,42,69,114,114,111,114,42,58,32,78,111,116,32,101,110,111,117,103,104,32,114,111,119,115,32,102,111,114,32,115,111,108,118,105,110,103,32,116,104,101,32,115,121,115,116,101,109,32,0,0,0,0,0,0,0,0,105,110,32,115,118,100,102,105,116,40,41,0,0,0,0,0,114,118,49,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,116,109,112,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,42,69,114,114,111,114,42,58,32,78,111,32,99,111,110,118,101,114,103,101,110,99,101,32,105,110,32,49,48,48,32,83,86,68,32,105,116,101,114,97,116,105,111,110,115,32,0,0,67,85,66,69,70,65,67,69,0,0,0,0,0,0,0,0,37,46,51,115,0,0,0,0,82,65,45,45,0,0,0,0,82,65,0,0,0,0,0,0,68,69,67,45,45,37,115,0,68,69,67,45,0,0,0,0,82,65,45,45,45,37,115,0,76,79,78,0,0,0,0,0,37,99,76,79,78,0,0,0,37,99,76,65,84,0,0,0,37,115,45,37,115,0,0,0,76,65,84,0,0,0,0,0,76,78,0,0,0,0,0,0,37,99,37,99,76,78,0,0,37,99,37,99,76,84,0,0,76,84,0,0,0,0,0,0,71,76,83,0,0,0,0,0,78,67,80,0,0,0,0,0,26,0,0,0,0,0,0,0,65,90,80,0,83,90,80,0,84,65,78,0,83,84,71,0,83,73,78,0,65,82,67,0,90,80,78,0,90,69,65,0,65,73,82,0,67,89,80,0,67,69,65,0,67,65,82,0,77,69,82,0,67,79,80,0,67,79,69,0,67,79,68,0,67,79,79,0,83,70,76,0,80,65,82,0,77,79,76,0,65,73,84,0,66,79,78,0,80,67,79,0,84,83,67,0,67,83,67,0,81,83,67,0,65,90,80,0,0,0,0,0,83,90,80,0,0,0,0,0,84,65,78,0,0,0,0,0,83,84,71,0,0,0,0,0,83,73,78,0,0,0,0,0,65,82,67,0,0,0,0,0,90,80,78,0,0,0,0,0,90,69,65,0,0,0,0,0,65,73,82,0,0,0,0,0,67,89,80,0,0,0,0,0,67,69,65,0,0,0,0,0,67,65,82,0,0,0,0,0,77,69,82,0,0,0,0,0,83,70,76,0,0,0,0,0,80,65,82,0,0,0,0,0,77,79,76,0,0,0,0,0,65,73,84,0,0,0,0,0,67,79,80,0,0,0,0,0,67,79,69,0,0,0,0,0,67,79,68,0,0,0,0,0,67,79,79,0,0,0,0,0,66,79,78,0,0,0,0,0,80,67,79,0,0,0,0,0,84,83,67,0,0,0,0,0,67,83,67,0,0,0,0,0,81,83,67,0,0,0,0,0,65,95,79,82,68,69,82,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,65,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,0,65,95,37,100,95,37,100,0,66,95,79,82,68,69,82,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,66,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,0,66,95,37,100,95,37,100,0,65,80,95,79,82,68,69,82,0,0,0,0,0,0,0,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,65,80,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,65,80,95,37,100,95,37,100,0,0,0,0,0,0,0,0,66,80,95,79,82,68,69,82,0,0,0,0,0,0,0,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,66,80,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,66,80,95,37,100,95,37,100,0,0,0,0,0,0,0,0,45,83,73,80,0,0,0,0,0,0,0,0,0,0,0,0,91,99,100,108,95,122,115,99,97,108,101,93,32,37,100,120,37,100,45,37,100,32,32,99,111,110,116,61,37,103,32,111,112,116,115,122,61,37,100,32,108,101,110,61,37,100,10,0,91,99,100,108,95,122,115,99,97,108,101,93,32,122,109,105,110,61,37,103,32,122,109,97,120,61,37,103,32,108,101,102,116,61,37,103,32,109,101,100,105,97,110,61,37,103,10,0,91,99,100,108,95,122,115,99,97,108,101,93,32,109,105,110,112,105,120,61,37,100,32,110,103,114,111,119,61,37,100,32,110,103,111,111,100,112,105,120,61,37,100,10,0,0,0,0,91,99,100,108,95,122,115,99,97,108,101,93,32,122,115,108,111,112,101,61,37,103,32,99,101,110,116,101,114,95,112,105,120,61,37,100,32,122,49,61,37,103,32,122,50,61,37,103,10,0,0,0,0,0,0,0,91,115,97,109,112,108,101,73,109,97,103,101,93,32,111,112,116,95,110,112,105,120,47,108,105,110,101,61,37,100,32,99,111,108,95,115,116,101,112,61,37,100,32,110,47,108,105,110,101,61,37,100,10,0,0,0,91,115,97,109,112,108,101,73,109,97,103,101,93,32,110,108,95,105,110,95,115,97,109,112,61,37,100,47,37,100,32,111,112,116,95,110,108,47,115,97,109,112,61,37,100,32,108,115,116,101,112,61,37,100,10,0,0,0,0,0,150,48,7,119,44,97,14,238,186,81,9,153,25,196,109,7,143,244,106,112,53,165,99,233,163,149,100,158,50,136,219,14,164,184,220,121,30,233,213,224,136,217,210,151,43,76,182,9,189,124,177,126,7,45,184,231,145,29,191,144,100,16,183,29,242,32,176,106,72,113,185,243,222,65,190,132,125,212,218,26,235,228,221,109,81,181,212,244,199,133,211,131,86,152,108,19,192,168,107,100,122,249,98,253,236,201,101,138,79,92,1,20,217,108,6,99,99,61,15,250,245,13,8,141,200,32,110,59,94,16,105,76,228,65,96,213,114,113,103,162,209,228,3,60,71,212,4,75,253,133,13,210,107,181,10,165,250,168,181,53,108,152,178,66,214,201,187,219,64,249,188,172,227,108,216,50,117,92,223,69,207,13,214,220,89,61,209,171,172,48,217,38,58,0,222,81,128,81,215,200,22,97,208,191,181,244,180,33,35,196,179,86,153,149,186,207,15,165,189,184,158,184,2,40,8,136,5,95,178,217,12,198,36,233,11,177,135,124,111,47,17,76,104,88,171,29,97,193,61,45,102,182,144,65,220,118,6,113,219,1,188,32,210,152,42,16,213,239,137,133,177,113,31,181,182,6,165,228,191,159,51,212,184,232,162,201,7,120,52,249,0,15,142,168,9,150,24,152,14,225,187,13,106,127,45,61,109,8,151,108,100,145,1,92,99,230,244,81,107,107,98,97,108,28,216,48,101,133,78,0,98,242,237,149,6,108,123,165,1,27,193,244,8,130,87,196,15,245,198,217,176,101,80,233,183,18,234,184,190,139,124,136,185,252,223,29,221,98,73,45,218,21,243,124,211,140,101,76,212,251,88,97,178,77,206,81,181,58,116,0,188,163,226,48,187,212,65,165,223,74,215,149,216,61,109,196,209,164,251,244,214,211,106,233,105,67,252,217,110,52,70,136,103,173,208,184,96,218,115,45,4,68,229,29,3,51,95,76,10,170,201,124,13,221,60,113,5,80,170,65,2,39,16,16,11,190,134,32,12,201,37,181,104,87,179,133,111,32,9,212,102,185,159,228,97,206,14,249,222,94,152,201,217,41,34,152,208,176,180,168,215,199,23,61,179,89,129,13,180,46,59,92,189,183,173,108,186,192,32,131,184,237,182,179,191,154,12,226,182,3,154,210,177,116,57,71,213,234,175,119,210,157,21,38,219,4,131,22,220,115,18,11,99,227,132,59,100,148,62,106,109,13,168,90,106,122,11,207,14,228,157,255,9,147,39,174,0,10,177,158,7,125,68,147,15,240,210,163,8,135,104,242,1,30,254,194,6,105,93,87,98,247,203,103,101,128,113,54,108,25,231,6,107,110,118,27,212,254,224,43,211,137,90,122,218,16,204,74,221,103,111,223,185,249,249,239,190,142,67,190,183,23,213,142,176,96,232,163,214,214,126,147,209,161,196,194,216,56,82,242,223,79,241,103,187,209,103,87,188,166,221,6,181,63,75,54,178,72,218,43,13,216,76,27,10,175,246,74,3,54,96,122,4,65,195,239,96,223,85,223,103,168,239,142,110,49,121,190,105,70,140,179,97,203,26,131,102,188,160,210,111,37,54,226,104,82,149,119,12,204,3,71,11,187,185,22,2,34,47,38,5,85,190,59,186,197,40,11,189,178,146,90,180,43,4,106,179,92,167,255,215,194,49,207,208,181,139,158,217,44,29,174,222,91,176,194,100,155,38,242,99,236,156,163,106,117,10,147,109,2,169,6,9,156,63,54,14,235,133,103,7,114,19,87,0,5,130,74,191,149,20,122,184,226,174,43,177,123,56,27,182,12,155,142,210,146,13,190,213,229,183,239,220,124,33,223,219,11,212,210,211,134,66,226,212,241,248,179,221,104,110,131,218,31,205,22,190,129,91,38,185,246,225,119,176,111,119,71,183,24,230,90,8,136,112,106,15,255,202,59,6,102,92,11,1,17,255,158,101,143,105,174,98,248,211,255,107,97,69,207,108,22,120,226,10,160,238,210,13,215,84,131,4,78,194,179,3,57,97,38,103,167,247,22,96,208,77,71,105,73,219,119,110,62,74,106,209,174,220,90,214,217,102,11,223,64,240,59,216,55,83,174,188,169,197,158,187,222,127,207,178,71,233,255,181,48,28,242,189,189,138,194,186,202,48,147,179,83,166,163,180,36,5,54,208,186,147,6,215,205,41,87,222,84,191,103,217,35,46,122,102,179,184,74,97,196,2,27,104,93,148,43,111,42,55,190,11,180,161,142,12,195,27,223,5,90,141,239,2,45,0,0,0,0,65,49,27,25,130,98,54,50,195,83,45,43,4,197,108,100,69,244,119,125,134,167,90,86,199,150,65,79,8,138,217,200,73,187,194,209,138,232,239,250,203,217,244,227,12,79,181,172,77,126,174,181,142,45,131,158,207,28,152,135,81,18,194,74,16,35,217,83,211,112,244,120,146,65,239,97,85,215,174,46,20,230,181,55,215,181,152,28,150,132,131,5,89,152,27,130,24,169,0,155,219,250,45,176,154,203,54,169,93,93,119,230,28,108,108,255,223,63,65,212,158,14,90,205,162,36,132,149,227,21,159,140,32,70,178,167,97,119,169,190,166,225,232,241,231,208,243,232,36,131,222,195,101,178,197,218,170,174,93,93,235,159,70,68,40,204,107,111,105,253,112,118,174,107,49,57,239,90,42,32,44,9,7,11,109,56,28,18,243,54,70,223,178,7,93,198,113,84,112,237,48,101,107,244,247,243,42,187,182,194,49,162,117,145,28,137,52,160,7,144,251,188,159,23,186,141,132,14,121,222,169,37,56,239,178,60,255,121,243,115,190,72,232,106,125,27,197,65,60,42,222,88,5,79,121,240,68,126,98,233,135,45,79,194,198,28,84,219,1,138,21,148,64,187,14,141,131,232,35,166,194,217,56,191,13,197,160,56,76,244,187,33,143,167,150,10,206,150,141,19,9,0,204,92,72,49,215,69,139,98,250,110,202,83,225,119,84,93,187,186,21,108,160,163,214,63,141,136,151,14,150,145,80,152,215,222,17,169,204,199,210,250,225,236,147,203,250,245,92,215,98,114,29,230,121,107,222,181,84,64,159,132,79,89,88,18,14,22,25,35,21,15,218,112,56,36,155,65,35,61,167,107,253,101,230,90,230,124,37,9,203,87,100,56,208,78,163,174,145,1,226,159,138,24,33,204,167,51,96,253,188,42,175,225,36,173,238,208,63,180,45,131,18,159,108,178,9,134,171,36,72,201,234,21,83,208,41,70,126,251,104,119,101,226,246,121,63,47,183,72,36,54,116,27,9,29,53,42,18,4,242,188,83,75,179,141,72,82,112,222,101,121,49,239,126,96,254,243,230,231,191,194,253,254,124,145,208,213,61,160,203,204,250,54,138,131,187,7,145,154,120,84,188,177,57,101,167,168,75,152,131,59,10,169,152,34,201,250,181,9,136,203,174,16,79,93,239,95,14,108,244,70,205,63,217,109,140,14,194,116,67,18,90,243,2,35,65,234,193,112,108,193,128,65,119,216,71,215,54,151,6,230,45,142,197,181,0,165,132,132,27,188,26,138,65,113,91,187,90,104,152,232,119,67,217,217,108,90,30,79,45,21,95,126,54,12,156,45,27,39,221,28,0,62,18,0,152,185,83,49,131,160,144,98,174,139,209,83,181,146,22,197,244,221,87,244,239,196,148,167,194,239,213,150,217,246,233,188,7,174,168,141,28,183,107,222,49,156,42,239,42,133,237,121,107,202,172,72,112,211,111,27,93,248,46,42,70,225,225,54,222,102,160,7,197,127,99,84,232,84,34,101,243,77,229,243,178,2,164,194,169,27,103,145,132,48,38,160,159,41,184,174,197,228,249,159,222,253,58,204,243,214,123,253,232,207,188,107,169,128,253,90,178,153,62,9,159,178,127,56,132,171,176,36,28,44,241,21,7,53,50,70,42,30,115,119,49,7,180,225,112,72,245,208,107,81,54,131,70,122,119,178,93,99,78,215,250,203,15,230,225,210,204,181,204,249,141,132,215,224,74,18,150,175,11,35,141,182,200,112,160,157,137,65,187,132,70,93,35,3,7,108,56,26,196,63,21,49,133,14,14,40,66,152,79,103,3,169,84,126,192,250,121,85,129,203,98,76,31,197,56,129,94,244,35,152,157,167,14,179,220,150,21,170,27,0,84,229,90,49,79,252,153,98,98,215,216,83,121,206,23,79,225,73,86,126,250,80,149,45,215,123,212,28,204,98,19,138,141,45,82,187,150,52,145,232,187,31,208,217,160,6,236,243,126,94,173,194,101,71,110,145,72,108,47,160,83,117,232,54,18,58,169,7,9,35,106,84,36,8,43,101,63,17,228,121,167,150,165,72,188,143,102,27,145,164,39,42,138,189,224,188,203,242,161,141,208,235,98,222,253,192,35,239,230,217,189,225,188,20,252,208,167,13,63,131,138,38,126,178,145,63,185,36,208,112,248,21,203,105,59,70,230,66,122,119,253,91,181,107,101,220,244,90,126,197,55,9,83,238,118,56,72,247,177,174,9,184,240,159,18,161,51,204,63,138,114,253,36,147,0,0,0,0,55,106,194,1,110,212,132,3,89,190,70,2,220,168,9,7,235,194,203,6,178,124,141,4,133,22,79,5,184,81,19,14,143,59,209,15,214,133,151,13,225,239,85,12,100,249,26,9,83,147,216,8,10,45,158,10,61,71,92,11,112,163,38,28,71,201,228,29,30,119,162,31,41,29,96,30,172,11,47,27,155,97,237,26,194,223,171,24,245,181,105,25,200,242,53,18,255,152,247,19,166,38,177,17,145,76,115,16,20,90,60,21,35,48,254,20,122,142,184,22,77,228,122,23,224,70,77,56,215,44,143,57,142,146,201,59,185,248,11,58,60,238,68,63,11,132,134,62,82,58,192,60,101,80,2,61,88,23,94,54,111,125,156,55,54,195,218,53,1,169,24,52,132,191,87,49,179,213,149,48,234,107,211,50,221,1,17,51,144,229,107,36,167,143,169,37,254,49,239,39,201,91,45,38,76,77,98,35,123,39,160,34,34,153,230,32,21,243,36,33,40,180,120,42,31,222,186,43,70,96,252,41,113,10,62,40,244,28,113,45,195,118,179,44,154,200,245,46,173,162,55,47,192,141,154,112,247,231,88,113,174,89,30,115,153,51,220,114,28,37,147,119,43,79,81,118,114,241,23,116,69,155,213,117,120,220,137,126,79,182,75,127,22,8,13,125,33,98,207,124,164,116,128,121,147,30,66,120,202,160,4,122,253,202,198,123,176,46,188,108,135,68,126,109,222,250,56,111,233,144,250,110,108,134,181,107,91,236,119,106,2,82,49,104,53,56,243,105,8,127,175,98,63,21,109,99,102,171,43,97,81,193,233,96,212,215,166,101,227,189,100,100,186,3,34,102,141,105,224,103,32,203,215,72,23,161,21,73,78,31,83,75,121,117,145,74,252,99,222,79,203,9,28,78,146,183,90,76,165,221,152,77,152,154,196,70,175,240,6,71,246,78,64,69,193,36,130,68,68,50,205,65,115,88,15,64,42,230,73,66,29,140,139,67,80,104,241,84,103,2,51,85,62,188,117,87,9,214,183,86,140,192,248,83,187,170,58,82,226,20,124,80,213,126,190,81,232,57,226,90,223,83,32,91,134,237,102,89,177,135,164,88,52,145,235,93,3,251,41,92,90,69,111,94,109,47,173,95,128,27,53,225,183,113,247,224,238,207,177,226,217,165,115,227,92,179,60,230,107,217,254,231,50,103,184,229,5,13,122,228,56,74,38,239,15,32,228,238,86,158,162,236,97,244,96,237,228,226,47,232,211,136,237,233,138,54,171,235,189,92,105,234,240,184,19,253,199,210,209,252,158,108,151,254,169,6,85,255,44,16,26,250,27,122,216,251,66,196,158,249,117,174,92,248,72,233,0,243,127,131,194,242,38,61,132,240,17,87,70,241,148,65,9,244,163,43,203,245,250,149,141,247,205,255,79,246,96,93,120,217,87,55,186,216,14,137,252,218,57,227,62,219,188,245,113,222,139,159,179,223,210,33,245,221,229,75,55,220,216,12,107,215,239,102,169,214,182,216,239,212,129,178,45,213,4,164,98,208,51,206,160,209,106,112,230,211,93,26,36,210,16,254,94,197,39,148,156,196,126,42,218,198,73,64,24,199,204,86,87,194,251,60,149,195,162,130,211,193,149,232,17,192,168,175,77,203,159,197,143,202,198,123,201,200,241,17,11,201,116,7,68,204,67,109,134,205,26,211,192,207,45,185,2,206,64,150,175,145,119,252,109,144,46,66,43,146,25,40,233,147,156,62,166,150,171,84,100,151,242,234,34,149,197,128,224,148,248,199,188,159,207,173,126,158,150,19,56,156,161,121,250,157,36,111,181,152,19,5,119,153,74,187,49,155,125,209,243,154,48,53,137,141,7,95,75,140,94,225,13,142,105,139,207,143,236,157,128,138,219,247,66,139,130,73,4,137,181,35,198,136,136,100,154,131,191,14,88,130,230,176,30,128,209,218,220,129,84,204,147,132,99,166,81,133,58,24,23,135,13,114,213,134,160,208,226,169,151,186,32,168,206,4,102,170,249,110,164,171,124,120,235,174,75,18,41,175,18,172,111,173,37,198,173,172,24,129,241,167,47,235,51,166,118,85,117,164,65,63,183,165,196,41,248,160,243,67,58,161,170,253,124,163,157,151,190,162,208,115,196,181,231,25,6,180,190,167,64,182,137,205,130,183,12,219,205,178,59,177,15,179,98,15,73,177,85,101,139,176,104,34,215,187,95,72,21,186,6,246,83,184,49,156,145,185,180,138,222,188,131,224,28,189,218,94,90,191,237,52,152,190,0,0,0,0,101,103,188,184,139,200,9,170,238,175,181,18,87,151,98,143,50,240,222,55,220,95,107,37,185,56,215,157,239,40,180,197,138,79,8,125,100,224,189,111,1,135,1,215,184,191,214,74,221,216,106,242,51,119,223,224,86,16,99,88,159,87,25,80,250,48,165,232,20,159,16,250,113,248,172,66,200,192,123,223,173,167,199,103,67,8,114,117,38,111,206,205,112,127,173,149,21,24,17,45,251,183,164,63,158,208,24,135,39,232,207,26,66,143,115,162,172,32,198,176,201,71,122,8,62,175,50,160,91,200,142,24,181,103,59,10,208,0,135,178,105,56,80,47,12,95,236,151,226,240,89,133,135,151,229,61,209,135,134,101,180,224,58,221,90,79,143,207,63,40,51,119,134,16,228,234,227,119,88,82,13,216,237,64,104,191,81,248,161,248,43,240,196,159,151,72,42,48,34,90,79,87,158,226,246,111,73,127,147,8,245,199,125,167,64,213,24,192,252,109,78,208,159,53,43,183,35,141,197,24,150,159,160,127,42,39,25,71,253,186,124,32,65,2,146,143,244,16,247,232,72,168,61,88,20,155,88,63,168,35,182,144,29,49,211,247,161,137,106,207,118,20,15,168,202,172,225,7,127,190,132,96,195,6,210,112,160,94,183,23,28,230,89,184,169,244,60,223,21,76,133,231,194,209,224,128,126,105,14,47,203,123,107,72,119,195,162,15,13,203,199,104,177,115,41,199,4,97,76,160,184,217,245,152,111,68,144,255,211,252,126,80,102,238,27,55,218,86,77,39,185,14,40,64,5,182,198,239,176,164,163,136,12,28,26,176,219,129,127,215,103,57,145,120,210,43,244,31,110,147,3,247,38,59,102,144,154,131,136,63,47,145,237,88,147,41,84,96,68,180,49,7,248,12,223,168,77,30,186,207,241,166,236,223,146,254,137,184,46,70,103,23,155,84,2,112,39,236,187,72,240,113,222,47,76,201,48,128,249,219,85,231,69,99,156,160,63,107,249,199,131,211,23,104,54,193,114,15,138,121,203,55,93,228,174,80,225,92,64,255,84,78,37,152,232,246,115,136,139,174,22,239,55,22,248,64,130,4,157,39,62,188,36,31,233,33,65,120,85,153,175,215,224,139,202,176,92,51,59,182,89,237,94,209,229,85,176,126,80,71,213,25,236,255,108,33,59,98,9,70,135,218,231,233,50,200,130,142,142,112,212,158,237,40,177,249,81,144,95,86,228,130,58,49,88,58,131,9,143,167,230,110,51,31,8,193,134,13,109,166,58,181,164,225,64,189,193,134,252,5,47,41,73,23,74,78,245,175,243,118,34,50,150,17,158,138,120,190,43,152,29,217,151,32,75,201,244,120,46,174,72,192,192,1,253,210,165,102,65,106,28,94,150,247,121,57,42,79,151,150,159,93,242,241,35,229,5,25,107,77,96,126,215,245,142,209,98,231,235,182,222,95,82,142,9,194,55,233,181,122,217,70,0,104,188,33,188,208,234,49,223,136,143,86,99,48,97,249,214,34,4,158,106,154,189,166,189,7,216,193,1,191,54,110,180,173,83,9,8,21,154,78,114,29,255,41,206,165,17,134,123,183,116,225,199,15,205,217,16,146,168,190,172,42,70,17,25,56,35,118,165,128,117,102,198,216,16,1,122,96,254,174,207,114,155,201,115,202,34,241,164,87,71,150,24,239,169,57,173,253,204,94,17,69,6,238,77,118,99,137,241,206,141,38,68,220,232,65,248,100,81,121,47,249,52,30,147,65,218,177,38,83,191,214,154,235,233,198,249,179,140,161,69,11,98,14,240,25,7,105,76,161,190,81,155,60,219,54,39,132,53,153,146,150,80,254,46,46,153,185,84,38,252,222,232,158,18,113,93,140,119,22,225,52,206,46,54,169,171,73,138,17,69,230,63,3,32,129,131,187,118,145,224,227,19,246,92,91,253,89,233,73,152,62,85,241,33,6,130,108,68,97,62,212,170,206,139,198,207,169,55,126,56,65,127,214,93,38,195,110,179,137,118,124,214,238,202,196,111,214,29,89,10,177,161,225,228,30,20,243,129,121,168,75,215,105,203,19,178,14,119,171,92,161,194,185,57,198,126,1,128,254,169,156,229,153,21,36,11,54,160,54,110,81,28,142,167,22,102,134,194,113,218,62,44,222,111,44,73,185,211,148,240,129,4,9,149,230,184,177,123,73,13,163,30,46,177,27,72,62,210,67,45,89,110,251,195,246,219,233,166,145,103,81,31,169,176,204,122,206,12,116,148,97,185,102,241,6,5,222,0,0,0,0,119,7,48,150,238,14,97,44,153,9,81,186,7,109,196,25,112,106,244,143,233,99,165,53,158,100,149,163,14,219,136,50,121,220,184,164,224,213,233,30,151,210,217,136,9,182,76,43,126,177,124,189,231,184,45,7,144,191,29,145,29,183,16,100,106,176,32,242,243,185,113,72,132,190,65,222,26,218,212,125,109,221,228,235,244,212,181,81,131,211,133,199,19,108,152,86,100,107,168,192,253,98,249,122,138,101,201,236,20,1,92,79,99,6,108,217,250,15,61,99,141,8,13,245,59,110,32,200,76,105,16,94,213,96,65,228,162,103,113,114,60,3,228,209,75,4,212,71,210,13,133,253,165,10,181,107,53,181,168,250,66,178,152,108,219,187,201,214,172,188,249,64,50,216,108,227,69,223,92,117,220,214,13,207,171,209,61,89,38,217,48,172,81,222,0,58,200,215,81,128,191,208,97,22,33,180,244,181,86,179,196,35,207,186,149,153,184,189,165,15,40,2,184,158,95,5,136,8,198,12,217,178,177,11,233,36,47,111,124,135,88,104,76,17,193,97,29,171,182,102,45,61,118,220,65,144,1,219,113,6,152,210,32,188,239,213,16,42,113,177,133,137,6,182,181,31,159,191,228,165,232,184,212,51,120,7,201,162,15,0,249,52,150,9,168,142,225,14,152,24,127,106,13,187,8,109,61,45,145,100,108,151,230,99,92,1,107,107,81,244,28,108,97,98,133,101,48,216,242,98,0,78,108,6,149,237,27,1,165,123,130,8,244,193,245,15,196,87,101,176,217,198,18,183,233,80,139,190,184,234,252,185,136,124,98,221,29,223,21,218,45,73,140,211,124,243,251,212,76,101,77,178,97,88,58,181,81,206,163,188,0,116,212,187,48,226,74,223,165,65,61,216,149,215,164,209,196,109,211,214,244,251,67,105,233,106,52,110,217,252,173,103,136,70,218,96,184,208,68,4,45,115,51,3,29,229,170,10,76,95,221,13,124,201,80,5,113,60,39,2,65,170,190,11,16,16,201,12,32,134,87,104,181,37,32,111,133,179,185,102,212,9,206,97,228,159,94,222,249,14,41,217,201,152,176,208,152,34,199,215,168,180,89,179,61,23,46,180,13,129,183,189,92,59,192,186,108,173,237,184,131,32,154,191,179,182,3,182,226,12,116,177,210,154,234,213,71,57,157,210,119,175,4,219,38,21,115,220,22,131,227,99,11,18,148,100,59,132,13,109,106,62,122,106,90,168,228,14,207,11,147,9,255,157,10,0,174,39,125,7,158,177,240,15,147,68,135,8,163,210,30,1,242,104,105,6,194,254,247,98,87,93,128,101,103,203,25,108,54,113,110,107,6,231,254,212,27,118,137,211,43,224,16,218,122,90,103,221,74,204,249,185,223,111,142,190,239,249,23,183,190,67,96,176,142,213,214,214,163,232,161,209,147,126,56,216,194,196,79,223,242,82,209,187,103,241,166,188,87,103,63,181,6,221,72,178,54,75,216,13,43,218,175,10,27,76,54,3,74,246,65,4,122,96,223,96,239,195,168,103,223,85,49,110,142,239,70,105,190,121,203,97,179,140,188,102,131,26,37,111,210,160,82,104,226,54,204,12,119,149,187,11,71,3,34,2,22,185,85,5,38,47,197,186,59,190,178,189,11,40,43,180,90,146,92,179,106,4,194,215,255,167,181,208,207,49,44,217,158,139,91,222,174,29,155,100,194,176,236,99,242,38,117,106,163,156,2,109,147,10,156,9,6,169,235,14,54,63,114,7,103,133,5,0,87,19,149,191,74,130,226,184,122,20,123,177,43,174,12,182,27,56,146,210,142,155,229,213,190,13,124,220,239,183,11,219,223,33,134,211,210,212,241,212,226,66,104,221,179,248,31,218,131,110,129,190,22,205,246,185,38,91,111,176,119,225,24,183,71,119,136,8,90,230,255,15,106,112,102,6,59,202,17,1,11,92,143,101,158,255,248,98,174,105,97,107,255,211,22,108,207,69,160,10,226,120,215,13,210,238,78,4,131,84,57,3,179,194,167,103,38,97,208,96,22,247,73,105,71,77,62,110,119,219,174,209,106,74,217,214,90,220,64,223,11,102,55,216,59,240,169,188,174,83,222,187,158,197,71,178,207,127,48,181,255,233,189,189,242,28,202,186,194,138,83,179,147,48,36,180,163,166,186,208,54,5,205,215,6,147,84,222,87,41,35,217,103,191,179,102,122,46,196,97,74,184,93,104,27,2,42,111,43,148,180,11,190,55,195,12,142,161,90,5,223,27,45,2,239,141,0,0,0,0,25,27,49,65,50,54,98,130,43,45,83,195,100,108,197,4,125,119,244,69,86,90,167,134,79,65,150,199,200,217,138,8,209,194,187,73,250,239,232,138,227,244,217,203,172,181,79,12,181,174,126,77,158,131,45,142,135,152,28,207,74,194,18,81,83,217,35,16,120,244,112,211,97,239,65,146,46,174,215,85,55,181,230,20,28,152,181,215,5,131,132,150,130,27,152,89,155,0,169,24,176,45,250,219,169,54,203,154,230,119,93,93,255,108,108,28,212,65,63,223,205,90,14,158,149,132,36,162,140,159,21,227,167,178,70,32,190,169,119,97,241,232,225,166,232,243,208,231,195,222,131,36,218,197,178,101,93,93,174,170,68,70,159,235,111,107,204,40,118,112,253,105,57,49,107,174,32,42,90,239,11,7,9,44,18,28,56,109,223,70,54,243,198,93,7,178,237,112,84,113,244,107,101,48,187,42,243,247,162,49,194,182,137,28,145,117,144,7,160,52,23,159,188,251,14,132,141,186,37,169,222,121,60,178,239,56,115,243,121,255,106,232,72,190,65,197,27,125,88,222,42,60,240,121,79,5,233,98,126,68,194,79,45,135,219,84,28,198,148,21,138,1,141,14,187,64,166,35,232,131,191,56,217,194,56,160,197,13,33,187,244,76,10,150,167,143,19,141,150,206,92,204,0,9,69,215,49,72,110,250,98,139,119,225,83,202,186,187,93,84,163,160,108,21,136,141,63,214,145,150,14,151,222,215,152,80,199,204,169,17,236,225,250,210,245,250,203,147,114,98,215,92,107,121,230,29,64,84,181,222,89,79,132,159,22,14,18,88,15,21,35,25,36,56,112,218,61,35,65,155,101,253,107,167,124,230,90,230,87,203,9,37,78,208,56,100,1,145,174,163,24,138,159,226,51,167,204,33,42,188,253,96,173,36,225,175,180,63,208,238,159,18,131,45,134,9,178,108,201,72,36,171,208,83,21,234,251,126,70,41,226,101,119,104,47,63,121,246,54,36,72,183,29,9,27,116,4,18,42,53,75,83,188,242,82,72,141,179,121,101,222,112,96,126,239,49,231,230,243,254,254,253,194,191,213,208,145,124,204,203,160,61,131,138,54,250,154,145,7,187,177,188,84,120,168,167,101,57,59,131,152,75,34,152,169,10,9,181,250,201,16,174,203,136,95,239,93,79,70,244,108,14,109,217,63,205,116,194,14,140,243,90,18,67,234,65,35,2,193,108,112,193,216,119,65,128,151,54,215,71,142,45,230,6,165,0,181,197,188,27,132,132,113,65,138,26,104,90,187,91,67,119,232,152,90,108,217,217,21,45,79,30,12,54,126,95,39,27,45,156,62,0,28,221,185,152,0,18,160,131,49,83,139,174,98,144,146,181,83,209,221,244,197,22,196,239,244,87,239,194,167,148,246,217,150,213,174,7,188,233,183,28,141,168,156,49,222,107,133,42,239,42,202,107,121,237,211,112,72,172,248,93,27,111,225,70,42,46,102,222,54,225,127,197,7,160,84,232,84,99,77,243,101,34,2,178,243,229,27,169,194,164,48,132,145,103,41,159,160,38,228,197,174,184,253,222,159,249,214,243,204,58,207,232,253,123,128,169,107,188,153,178,90,253,178,159,9,62,171,132,56,127,44,28,36,176,53,7,21,241,30,42,70,50,7,49,119,115,72,112,225,180,81,107,208,245,122,70,131,54,99,93,178,119,203,250,215,78,210,225,230,15,249,204,181,204,224,215,132,141,175,150,18,74,182,141,35,11,157,160,112,200,132,187,65,137,3,35,93,70,26,56,108,7,49,21,63,196,40,14,14,133,103,79,152,66,126,84,169,3,85,121,250,192,76,98,203,129,129,56,197,31,152,35,244,94,179,14,167,157,170,21,150,220,229,84,0,27,252,79,49,90,215,98,98,153,206,121,83,216,73,225,79,23,80,250,126,86,123,215,45,149,98,204,28,212,45,141,138,19,52,150,187,82,31,187,232,145,6,160,217,208,94,126,243,236,71,101,194,173,108,72,145,110,117,83,160,47,58,18,54,232,35,9,7,169,8,36,84,106,17,63,101,43,150,167,121,228,143,188,72,165,164,145,27,102,189,138,42,39,242,203,188,224,235,208,141,161,192,253,222,98,217,230,239,35,20,188,225,189,13,167,208,252,38,138,131,63,63,145,178,126,112,208,36,185,105,203,21,248,66,230,70,59,91,253,119,122,220,101,107,181,197,126,90,244,238,83,9,55,247,72,56,118,184,9,174,177,161,18,159,240,138,63,204,51,147,36,253,114,0,0,0,0,1,194,106,55,3,132,212,110,2,70,190,89,7,9,168,220,6,203,194,235,4,141,124,178,5,79,22,133,14,19,81,184,15,209,59,143,13,151,133,214,12,85,239,225,9,26,249,100,8,216,147,83,10,158,45,10,11,92,71,61,28,38,163,112,29,228,201,71,31,162,119,30,30,96,29,41,27,47,11,172,26,237,97,155,24,171,223,194,25,105,181,245,18,53,242,200,19,247,152,255,17,177,38,166,16,115,76,145,21,60,90,20,20,254,48,35,22,184,142,122,23,122,228,77,56,77,70,224,57,143,44,215,59,201,146,142,58,11,248,185,63,68,238,60,62,134,132,11,60,192,58,82,61,2,80,101,54,94,23,88,55,156,125,111,53,218,195,54,52,24,169,1,49,87,191,132,48,149,213,179,50,211,107,234,51,17,1,221,36,107,229,144,37,169,143,167,39,239,49,254,38,45,91,201,35,98,77,76,34,160,39,123,32,230,153,34,33,36,243,21,42,120,180,40,43,186,222,31,41,252,96,70,40,62,10,113,45,113,28,244,44,179,118,195,46,245,200,154,47,55,162,173,112,154,141,192,113,88,231,247,115,30,89,174,114,220,51,153,119,147,37,28,118,81,79,43,116,23,241,114,117,213,155,69,126,137,220,120,127,75,182,79,125,13,8,22,124,207,98,33,121,128,116,164,120,66,30,147,122,4,160,202,123,198,202,253,108,188,46,176,109,126,68,135,111,56,250,222,110,250,144,233,107,181,134,108,106,119,236,91,104,49,82,2,105,243,56,53,98,175,127,8,99,109,21,63,97,43,171,102,96,233,193,81,101,166,215,212,100,100,189,227,102,34,3,186,103,224,105,141,72,215,203,32,73,21,161,23,75,83,31,78,74,145,117,121,79,222,99,252,78,28,9,203,76,90,183,146,77,152,221,165,70,196,154,152,71,6,240,175,69,64,78,246,68,130,36,193,65,205,50,68,64,15,88,115,66,73,230,42,67,139,140,29,84,241,104,80,85,51,2,103,87,117,188,62,86,183,214,9,83,248,192,140,82,58,170,187,80,124,20,226,81,190,126,213,90,226,57,232,91,32,83,223,89,102,237,134,88,164,135,177,93,235,145,52,92,41,251,3,94,111,69,90,95,173,47,109,225,53,27,128,224,247,113,183,226,177,207,238,227,115,165,217,230,60,179,92,231,254,217,107,229,184,103,50,228,122,13,5,239,38,74,56,238,228,32,15,236,162,158,86,237,96,244,97,232,47,226,228,233,237,136,211,235,171,54,138,234,105,92,189,253,19,184,240,252,209,210,199,254,151,108,158,255,85,6,169,250,26,16,44,251,216,122,27,249,158,196,66,248,92,174,117,243,0,233,72,242,194,131,127,240,132,61,38,241,70,87,17,244,9,65,148,245,203,43,163,247,141,149,250,246,79,255,205,217,120,93,96,216,186,55,87,218,252,137,14,219,62,227,57,222,113,245,188,223,179,159,139,221,245,33,210,220,55,75,229,215,107,12,216,214,169,102,239,212,239,216,182,213,45,178,129,208,98,164,4,209,160,206,51,211,230,112,106,210,36,26,93,197,94,254,16,196,156,148,39,198,218,42,126,199,24,64,73,194,87,86,204,195,149,60,251,193,211,130,162,192,17,232,149,203,77,175,168,202,143,197,159,200,201,123,198,201,11,17,241,204,68,7,116,205,134,109,67,207,192,211,26,206,2,185,45,145,175,150,64,144,109,252,119,146,43,66,46,147,233,40,25,150,166,62,156,151,100,84,171,149,34,234,242,148,224,128,197,159,188,199,248,158,126,173,207,156,56,19,150,157,250,121,161,152,181,111,36,153,119,5,19,155,49,187,74,154,243,209,125,141,137,53,48,140,75,95,7,142,13,225,94,143,207,139,105,138,128,157,236,139,66,247,219,137,4,73,130,136,198,35,181,131,154,100,136,130,88,14,191,128,30,176,230,129,220,218,209,132,147,204,84,133,81,166,99,135,23,24,58,134,213,114,13,169,226,208,160,168,32,186,151,170,102,4,206,171,164,110,249,174,235,120,124,175,41,18,75,173,111,172,18,172,173,198,37,167,241,129,24,166,51,235,47,164,117,85,118,165,183,63,65,160,248,41,196,161,58,67,243,163,124,253,170,162,190,151,157,181,196,115,208,180,6,25,231,182,64,167,190,183,130,205,137,178,205,219,12,179,15,177,59,177,73,15,98,176,139,101,85,187,215,34,104,186,21,72,95,184,83,246,6,185,145,156,49,188,222,138,180,189,28,224,131,191,90,94,218,190,152,52,237,0,0,0,0,184,188,103,101,170,9,200,139,18,181,175,238,143,98,151,87,55,222,240,50,37,107,95,220,157,215,56,185,197,180,40,239,125,8,79,138,111,189,224,100,215,1,135,1,74,214,191,184,242,106,216,221,224,223,119,51,88,99,16,86,80,25,87,159,232,165,48,250,250,16,159,20,66,172,248,113,223,123,192,200,103,199,167,173,117,114,8,67,205,206,111,38,149,173,127,112,45,17,24,21,63,164,183,251,135,24,208,158,26,207,232,39,162,115,143,66,176,198,32,172,8,122,71,201,160,50,175,62,24,142,200,91,10,59,103,181,178,135,0,208,47,80,56,105,151,236,95,12,133,89,240,226,61,229,151,135,101,134,135,209,221,58,224,180,207,143,79,90,119,51,40,63,234,228,16,134,82,88,119,227,64,237,216,13,248,81,191,104,240,43,248,161,72,151,159,196,90,34,48,42,226,158,87,79,127,73,111,246,199,245,8,147,213,64,167,125,109,252,192,24,53,159,208,78,141,35,183,43,159,150,24,197,39,42,127,160,186,253,71,25,2,65,32,124,16,244,143,146,168,72,232,247,155,20,88,61,35,168,63,88,49,29,144,182,137,161,247,211,20,118,207,106,172,202,168,15,190,127,7,225,6,195,96,132,94,160,112,210,230,28,23,183,244,169,184,89,76,21,223,60,209,194,231,133,105,126,128,224,123,203,47,14,195,119,72,107,203,13,15,162,115,177,104,199,97,4,199,41,217,184,160,76,68,111,152,245,252,211,255,144,238,102,80,126,86,218,55,27,14,185,39,77,182,5,64,40,164,176,239,198,28,12,136,163,129,219,176,26,57,103,215,127,43,210,120,145,147,110,31,244,59,38,247,3,131,154,144,102,145,47,63,136,41,147,88,237,180,68,96,84,12,248,7,49,30,77,168,223,166,241,207,186,254,146,223,236,70,46,184,137,84,155,23,103,236,39,112,2,113,240,72,187,201,76,47,222,219,249,128,48,99,69,231,85], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+10336); +/* memory initializer */ allocate([107,63,160,156,211,131,199,249,193,54,104,23,121,138,15,114,228,93,55,203,92,225,80,174,78,84,255,64,246,232,152,37,174,139,136,115,22,55,239,22,4,130,64,248,188,62,39,157,33,233,31,36,153,85,120,65,139,224,215,175,51,92,176,202,237,89,182,59,85,229,209,94,71,80,126,176,255,236,25,213,98,59,33,108,218,135,70,9,200,50,233,231,112,142,142,130,40,237,158,212,144,81,249,177,130,228,86,95,58,88,49,58,167,143,9,131,31,51,110,230,13,134,193,8,181,58,166,109,189,64,225,164,5,252,134,193,23,73,41,47,175,245,78,74,50,34,118,243,138,158,17,150,152,43,190,120,32,151,217,29,120,244,201,75,192,72,174,46,210,253,1,192,106,65,102,165,247,150,94,28,79,42,57,121,93,159,150,151,229,35,241,242,77,107,25,5,245,215,126,96,231,98,209,142,95,222,182,235,194,9,142,82,122,181,233,55,104,0,70,217,208,188,33,188,136,223,49,234,48,99,86,143,34,214,249,97,154,106,158,4,7,189,166,189,191,1,193,216,173,180,110,54,21,8,9,83,29,114,78,154,165,206,41,255,183,123,134,17,15,199,225,116,146,16,217,205,42,172,190,168,56,25,17,70,128,165,118,35,216,198,102,117,96,122,1,16,114,207,174,254,202,115,201,155,87,164,241,34,239,24,150,71,253,173,57,169,69,17,94,204,118,77,238,6,206,241,137,99,220,68,38,141,100,248,65,232,249,47,121,81,65,147,30,52,83,38,177,218,235,154,214,191,179,249,198,233,11,69,161,140,25,240,14,98,161,76,105,7,60,155,81,190,132,39,54,219,150,146,153,53,46,46,254,80,38,84,185,153,158,232,222,252,140,93,113,18,52,225,22,119,169,54,46,206,17,138,73,171,3,63,230,69,187,131,129,32,227,224,145,118,91,92,246,19,73,233,89,253,241,85,62,152,108,130,6,33,212,62,97,68,198,139,206,170,126,55,169,207,214,127,65,56,110,195,38,93,124,118,137,179,196,202,238,214,89,29,214,111,225,161,177,10,243,20,30,228,75,168,121,129,19,203,105,215,171,119,14,178,185,194,161,92,1,126,198,57,156,169,254,128,36,21,153,229,54,160,54,11,142,28,81,110,134,102,22,167,62,218,113,194,44,111,222,44,148,211,185,73,9,4,129,240,177,184,230,149,163,13,73,123,27,177,46,30,67,210,62,72,251,110,89,45,233,219,246,195,81,103,145,166,204,176,169,31,116,12,206,122,102,185,97,148,222,5,6,241,0,0,0,0,0,0,0,0,1,0,0,0,4,0,4,0,8,0,4,0,2,0,0,0,4,0,5,0,16,0,8,0,2,0,0,0,4,0,6,0,32,0,32,0,2,0,0,0,4,0,4,0,16,0,16,0,3,0,0,0,8,0,16,0,32,0,32,0,3,0,0,0,8,0,16,0,128,0,128,0,3,0,0,0,8,0,32,0,128,0,0,1,3,0,0,0,32,0,128,0,2,1,0,4,3,0,0,0,32,0,2,1,2,1,0,16,3,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,58,32,0,0,0,0,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,49,46,50,46,53,0,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,117,110,101,120,112,101,99,116,101,100,32,101,110,100,32,111,102,32,102,105,108,101,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,105,110,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,99,111,109,112,114,101,115,115,101,100,32,100,97,116,97,32,101,114,114,111,114,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,100,101,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,49,46,50,46,53,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,16,0,17,0,18,0,0,0,8,0,7,0,9,0,6,0,10,0,5,0,11,0,4,0,12,0,3,0,13,0,2,0,14,0,1,0,15,0,0,0,105,110,99,111,114,114,101,99,116,32,104,101,97,100,101,114,32,99,104,101,99,107,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,105,110,118,97,108,105,100,32,119,105,110,100,111,119,32,115,105,122,101,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,104,101,97,100,101,114,32,99,114,99,32,109,105,115,109,97,116,99,104,0,0,0,0,0,105,110,118,97,108,105,100,32,98,108,111,99,107,32,116,121,112,101,0,0,0,0,0,0,105,110,118,97,108,105,100,32,115,116,111,114,101,100,32,98,108,111,99,107,32,108,101,110,103,116,104,115,0,0,0,0,116,111,111,32,109,97,110,121,32,108,101,110,103,116,104,32,111,114,32,100,105,115,116,97,110,99,101,32,115,121,109,98,111,108,115,0,0,0,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,0,0,0,105,110,118,97,108,105,100,32,98,105,116,32,108,101,110,103,116,104,32,114,101,112,101,97,116,0,0,0,0,0,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,45,45,32,109,105,115,115,105,110,103,32,101,110,100,45,111,102,45,98,108,111,99,107,0,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,115,32,115,101,116,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,192,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,160,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,224,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,144,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,208,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,176,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,240,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,200,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,168,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,232,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,152,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,216,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,184,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,248,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,196,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,164,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,228,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,148,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,212,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,180,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,244,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,204,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,172,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,236,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,156,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,220,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,188,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,252,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,194,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,162,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,226,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,146,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,210,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,178,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,242,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,202,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,170,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,234,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,154,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,218,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,186,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,250,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,198,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,166,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,230,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,150,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,214,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,182,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,246,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,206,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,174,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,238,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,158,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,222,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,190,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,254,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,193,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,161,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,225,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,145,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,209,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,177,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,241,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,201,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,169,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,233,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,153,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,217,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,185,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,249,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,197,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,165,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,229,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,149,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,213,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,181,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,245,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,205,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,173,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,237,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,157,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,221,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,189,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,253,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,195,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,163,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,227,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,147,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,211,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,179,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,243,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,203,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,171,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,235,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,155,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,219,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,187,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,251,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,199,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,167,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,231,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,151,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,215,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,183,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,247,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,207,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,175,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,239,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,159,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,223,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,191,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,255,0,16,5,1,0,23,5,1,1,19,5,17,0,27,5,1,16,17,5,5,0,25,5,1,4,21,5,65,0,29,5,1,64,16,5,3,0,24,5,1,2,20,5,33,0,28,5,1,32,18,5,9,0,26,5,1,8,22,5,129,0,64,5,0,0,16,5,2,0,23,5,129,1,19,5,25,0,27,5,1,24,17,5,7,0,25,5,1,6,21,5,97,0,29,5,1,96,16,5,4,0,24,5,1,3,20,5,49,0,28,5,1,48,18,5,13,0,26,5,1,12,22,5,193,0,64,5,0,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,13,0,15,0,17,0,19,0,23,0,27,0,31,0,35,0,43,0,51,0,59,0,67,0,83,0,99,0,115,0,131,0,163,0,195,0,227,0,2,1,0,0,0,0,0,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,17,0,17,0,17,0,17,0,18,0,18,0,18,0,18,0,19,0,19,0,19,0,19,0,20,0,20,0,20,0,20,0,21,0,21,0,21,0,21,0,16,0,73,0,195,0,0,0,1,0,2,0,3,0,4,0,5,0,7,0,9,0,13,0,17,0,25,0,33,0,49,0,65,0,97,0,129,0,193,0,1,1,129,1,1,2,1,3,1,4,1,6,1,8,1,12,1,16,1,24,1,32,1,48,1,64,1,96,0,0,0,0,16,0,16,0,16,0,16,0,17,0,17,0,18,0,18,0,19,0,19,0,20,0,20,0,21,0,21,0,22,0,22,0,23,0,23,0,24,0,24,0,25,0,25,0,26,0,26,0,27,0,27,0,28,0,28,0,29,0,29,0,64,0,64,0,0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,0,100,0,0,248,104,0,0,1,1,0,0,30,1,0,0,15,0,0,0,0,0,0,0,128,104,0,0,232,105,0,0,0,0,0,0,30,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,240,106,0,0,0,0,0,0,19,0,0,0,7,0,0,0,0,0,0,0,12,0,8,0,140,0,8,0,76,0,8,0,204,0,8,0,44,0,8,0,172,0,8,0,108,0,8,0,236,0,8,0,28,0,8,0,156,0,8,0,92,0,8,0,220,0,8,0,60,0,8,0,188,0,8,0,124,0,8,0,252,0,8,0,2,0,8,0,130,0,8,0,66,0,8,0,194,0,8,0,34,0,8,0,162,0,8,0,98,0,8,0,226,0,8,0,18,0,8,0,146,0,8,0,82,0,8,0,210,0,8,0,50,0,8,0,178,0,8,0,114,0,8,0,242,0,8,0,10,0,8,0,138,0,8,0,74,0,8,0,202,0,8,0,42,0,8,0,170,0,8,0,106,0,8,0,234,0,8,0,26,0,8,0,154,0,8,0,90,0,8,0,218,0,8,0,58,0,8,0,186,0,8,0,122,0,8,0,250,0,8,0,6,0,8,0,134,0,8,0,70,0,8,0,198,0,8,0,38,0,8,0,166,0,8,0,102,0,8,0,230,0,8,0,22,0,8,0,150,0,8,0,86,0,8,0,214,0,8,0,54,0,8,0,182,0,8,0,118,0,8,0,246,0,8,0,14,0,8,0,142,0,8,0,78,0,8,0,206,0,8,0,46,0,8,0,174,0,8,0,110,0,8,0,238,0,8,0,30,0,8,0,158,0,8,0,94,0,8,0,222,0,8,0,62,0,8,0,190,0,8,0,126,0,8,0,254,0,8,0,1,0,8,0,129,0,8,0,65,0,8,0,193,0,8,0,33,0,8,0,161,0,8,0,97,0,8,0,225,0,8,0,17,0,8,0,145,0,8,0,81,0,8,0,209,0,8,0,49,0,8,0,177,0,8,0,113,0,8,0,241,0,8,0,9,0,8,0,137,0,8,0,73,0,8,0,201,0,8,0,41,0,8,0,169,0,8,0,105,0,8,0,233,0,8,0,25,0,8,0,153,0,8,0,89,0,8,0,217,0,8,0,57,0,8,0,185,0,8,0,121,0,8,0,249,0,8,0,5,0,8,0,133,0,8,0,69,0,8,0,197,0,8,0,37,0,8,0,165,0,8,0,101,0,8,0,229,0,8,0,21,0,8,0,149,0,8,0,85,0,8,0,213,0,8,0,53,0,8,0,181,0,8,0,117,0,8,0,245,0,8,0,13,0,8,0,141,0,8,0,77,0,8,0,205,0,8,0,45,0,8,0,173,0,8,0,109,0,8,0,237,0,8,0,29,0,8,0,157,0,8,0,93,0,8,0,221,0,8,0,61,0,8,0,189,0,8,0,125,0,8,0,253,0,8,0,19,0,9,0,19,1,9,0,147,0,9,0,147,1,9,0,83,0,9,0,83,1,9,0,211,0,9,0,211,1,9,0,51,0,9,0,51,1,9,0,179,0,9,0,179,1,9,0,115,0,9,0,115,1,9,0,243,0,9,0,243,1,9,0,11,0,9,0,11,1,9,0,139,0,9,0,139,1,9,0,75,0,9,0,75,1,9,0,203,0,9,0,203,1,9,0,43,0,9,0,43,1,9,0,171,0,9,0,171,1,9,0,107,0,9,0,107,1,9,0,235,0,9,0,235,1,9,0,27,0,9,0,27,1,9,0,155,0,9,0,155,1,9,0,91,0,9,0,91,1,9,0,219,0,9,0,219,1,9,0,59,0,9,0,59,1,9,0,187,0,9,0,187,1,9,0,123,0,9,0,123,1,9,0,251,0,9,0,251,1,9,0,7,0,9,0,7,1,9,0,135,0,9,0,135,1,9,0,71,0,9,0,71,1,9,0,199,0,9,0,199,1,9,0,39,0,9,0,39,1,9,0,167,0,9,0,167,1,9,0,103,0,9,0,103,1,9,0,231,0,9,0,231,1,9,0,23,0,9,0,23,1,9,0,151,0,9,0,151,1,9,0,87,0,9,0,87,1,9,0,215,0,9,0,215,1,9,0,55,0,9,0,55,1,9,0,183,0,9,0,183,1,9,0,119,0,9,0,119,1,9,0,247,0,9,0,247,1,9,0,15,0,9,0,15,1,9,0,143,0,9,0,143,1,9,0,79,0,9,0,79,1,9,0,207,0,9,0,207,1,9,0,47,0,9,0,47,1,9,0,175,0,9,0,175,1,9,0,111,0,9,0,111,1,9,0,239,0,9,0,239,1,9,0,31,0,9,0,31,1,9,0,159,0,9,0,159,1,9,0,95,0,9,0,95,1,9,0,223,0,9,0,223,1,9,0,63,0,9,0,63,1,9,0,191,0,9,0,191,1,9,0,127,0,9,0,127,1,9,0,255,0,9,0,255,1,9,0,0,0,7,0,64,0,7,0,32,0,7,0,96,0,7,0,16,0,7,0,80,0,7,0,48,0,7,0,112,0,7,0,8,0,7,0,72,0,7,0,40,0,7,0,104,0,7,0,24,0,7,0,88,0,7,0,56,0,7,0,120,0,7,0,4,0,7,0,68,0,7,0,36,0,7,0,100,0,7,0,20,0,7,0,84,0,7,0,52,0,7,0,116,0,7,0,3,0,8,0,131,0,8,0,67,0,8,0,195,0,8,0,35,0,8,0,163,0,8,0,99,0,8,0,227,0,8,0,0,0,5,0,16,0,5,0,8,0,5,0,24,0,5,0,4,0,5,0,20,0,5,0,12,0,5,0,28,0,5,0,2,0,5,0,18,0,5,0,10,0,5,0,26,0,5,0,6,0,5,0,22,0,5,0,14,0,5,0,30,0,5,0,1,0,5,0,17,0,5,0,9,0,5,0,25,0,5,0,5,0,5,0,21,0,5,0,13,0,5,0,29,0,5,0,3,0,5,0,19,0,5,0,11,0,5,0,27,0,5,0,7,0,5,0,23,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,8,0,0,0,10,0,0,0,12,0,0,0,14,0,0,0,16,0,0,0,20,0,0,0,24,0,0,0,28,0,0,0,32,0,0,0,40,0,0,0,48,0,0,0,56,0,0,0,64,0,0,0,80,0,0,0,96,0,0,0,112,0,0,0,128,0,0,0,160,0,0,0,192,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,6,0,0,0,6,0,0,0,7,0,0,0,7,0,0,0,8,0,0,0,8,0,0,0,9,0,0,0,9,0,0,0,10,0,0,0,10,0,0,0,11,0,0,0,11,0,0,0,12,0,0,0,12,0,0,0,13,0,0,0,13,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,0,128,0,0,0,192,0,0,0,0,1,0,0,128,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,7,0,0,0,0,0,0,0,110,101,101,100,32,100,105,99,116,105,111,110,97,114,121,0,115,116,114,101,97,109,32,101,110,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,105,108,101,32,101,114,114,111,114,0,0,0,0,0,0,115,116,114,101,97,109,32,101,114,114,111,114,0,0,0,0,100,97,116,97,32,101,114,114,111,114,0,0,0,0,0,0,105,110,115,117,102,102,105,99,105,101,110,116,32,109,101,109,111,114,121,0,0,0,0,0,98,117,102,102,101,114,32,101,114,114,111,114,0,0,0,0,105,110,99,111,109,112,97,116,105,98,108,101,32,118,101,114,115,105,111,110,0,0,0,0,64,107,0,0,80,107,0,0,96,107,0,0,104,107,0,0,120,107,0,0,136,107,0,0,152,107,0,0,176,107,0,0,192,107,0,0,96,107,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,105,110,102,105,110,105,116,121,0,0,0,0,0,0,0,0,110,97,110,0,0,0,0,0,95,112,137,0,255,9,47,15,10,0,0,0,100,0,0,0,232,3,0,0,16,39,0,0,160,134,1,0,64,66,15,0,128,150,152,0,0,225,245,5], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+20576); + + + + +var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8); + +assert(tempDoublePtr % 8 == 0); + +function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much + + HEAP8[tempDoublePtr] = HEAP8[ptr]; + + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + +} + +function copyTempDouble(ptr) { + + HEAP8[tempDoublePtr] = HEAP8[ptr]; + + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + + HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; + + HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; + + HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; + + HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; + +} + + + + + var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86}; + + var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"}; + + + var ___errno_state=0;function ___setErrNo(value) { + // For convenient setting and returning of errno. + HEAP32[((___errno_state)>>2)]=value; + return value; + } + + var PATH={splitPath:function (filename) { + var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + return splitPathRe.exec(filename).slice(1); + },normalizeArray:function (parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + 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 the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + return parts; + },normalize:function (path) { + var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.substr(-1) === '/'; + // Normalize the path + path = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), !isAbsolute).join('/'); + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + return (isAbsolute ? '/' : '') + path; + },dirname:function (path) { + var result = PATH.splitPath(path), + root = result[0], + dir = result[1]; + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + return root + dir; + },basename:function (path) { + // EMSCRIPTEN return '/'' for '/', not an empty string + if (path === '/') return '/'; + var lastSlash = path.lastIndexOf('/'); + if (lastSlash === -1) return path; + return path.substr(lastSlash+1); + },extname:function (path) { + return PATH.splitPath(path)[3]; + },join:function () { + var paths = Array.prototype.slice.call(arguments, 0); + return PATH.normalize(paths.join('/')); + },join2:function (l, r) { + return PATH.normalize(l + '/' + r); + },resolve:function () { + var resolvedPath = '', + resolvedAbsolute = false; + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : FS.cwd(); + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + },relative:function (from, to) { + from = PATH.resolve(from).substr(1); + to = PATH.resolve(to).substr(1); + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + var end = arr.length - 1; + for (; end >= 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 < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + return outputParts.join('/'); + }}; + + var TTY={ttys:[],init:function () { + // https://github.com/kripken/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // currently, FS.init does not distinguish if process.stdin is a file or TTY + // // device, it always assumes it's a TTY device. because of this, we're forcing + // // process.stdin to UTF8 encoding to at least make stdin reading compatible + // // with text files until FS.init can be refactored. + // process['stdin']['setEncoding']('utf8'); + // } + },shutdown:function () { + // https://github.com/kripken/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? + // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation + // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists? + // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle + // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call + // process['stdin']['pause'](); + // } + },register:function (dev, ops) { + TTY.ttys[dev] = { input: [], output: [], ops: ops }; + FS.registerDevice(dev, TTY.stream_ops); + },stream_ops:{open:function (stream) { + var tty = TTY.ttys[stream.node.rdev]; + if (!tty) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + stream.tty = tty; + stream.seekable = false; + },close:function (stream) { + // flush any pending line data + if (stream.tty.output.length) { + stream.tty.ops.put_char(stream.tty, 10); + } + },read:function (stream, buffer, offset, length, pos /* ignored */) { + if (!stream.tty || !stream.tty.ops.get_char) { + throw new FS.ErrnoError(ERRNO_CODES.ENXIO); + } + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = stream.tty.ops.get_char(stream.tty); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + },write:function (stream, buffer, offset, length, pos) { + if (!stream.tty || !stream.tty.ops.put_char) { + throw new FS.ErrnoError(ERRNO_CODES.ENXIO); + } + for (var i = 0; i < length; i++) { + try { + stream.tty.ops.put_char(stream.tty, buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + }},default_tty_ops:{get_char:function (tty) { + if (!tty.input.length) { + var result = null; + if (ENVIRONMENT_IS_NODE) { + result = process['stdin']['read'](); + if (!result) { + if (process['stdin']['_readableState'] && process['stdin']['_readableState']['ended']) { + return null; // EOF + } + return undefined; // no data available + } + } else if (typeof window != 'undefined' && + typeof window.prompt == 'function') { + // Browser. + result = window.prompt('Input: '); // returns null on cancel + if (result !== null) { + result += '\n'; + } + } else if (typeof readline == 'function') { + // Command line. + result = readline(); + if (result !== null) { + result += '\n'; + } + } + if (!result) { + return null; + } + tty.input = intArrayFromString(result, true); + } + return tty.input.shift(); + },put_char:function (tty, val) { + if (val === null || val === 10) { + Module['print'](tty.output.join('')); + tty.output = []; + } else { + tty.output.push(TTY.utf8.processCChar(val)); + } + }},default_tty1_ops:{put_char:function (tty, val) { + if (val === null || val === 10) { + Module['printErr'](tty.output.join('')); + tty.output = []; + } else { + tty.output.push(TTY.utf8.processCChar(val)); + } + }}}; + + var MEMFS={ops_table:null,CONTENT_OWNING:1,CONTENT_FLEXIBLE:2,CONTENT_FIXED:3,mount:function (mount) { + return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + },createNode:function (parent, name, mode, dev) { + if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { + // no supported + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (!MEMFS.ops_table) { + 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, + allocate: MEMFS.stream_ops.allocate, + mmap: MEMFS.stream_ops.mmap + } + }, + 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.contents = []; + node.contentMode = MEMFS.CONTENT_FLEXIBLE; + } 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.timestamp = Date.now(); + // add the new node to the parent + if (parent) { + parent.contents[name] = node; + } + return node; + },ensureFlexible:function (node) { + if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) { + var contents = node.contents; + node.contents = Array.prototype.slice.call(contents); + node.contentMode = MEMFS.CONTENT_FLEXIBLE; + } + },node_ops:{getattr:function (node) { + var attr = {}; + // device numbers reuse inode numbers. + 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.contents.length; + } else if (FS.isLink(node.mode)) { + attr.size = node.link.length; + } else { + attr.size = 0; + } + attr.atime = new Date(node.timestamp); + attr.mtime = new Date(node.timestamp); + attr.ctime = new Date(node.timestamp); + // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), + // but this is not required by the standard. + attr.blksize = 4096; + attr.blocks = Math.ceil(attr.size / attr.blksize); + return attr; + },setattr:function (node, attr) { + if (attr.mode !== undefined) { + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + node.timestamp = attr.timestamp; + } + if (attr.size !== undefined) { + MEMFS.ensureFlexible(node); + var contents = node.contents; + if (attr.size < contents.length) contents.length = attr.size; + else while (attr.size > contents.length) contents.push(0); + } + },lookup:function (parent, name) { + throw FS.genericErrors[ERRNO_CODES.ENOENT]; + },mknod:function (parent, name, mode, dev) { + return MEMFS.createNode(parent, name, mode, dev); + },rename:function (old_node, new_dir, new_name) { + // if we're overwriting a directory at new_name, make sure it's empty. + if (FS.isDir(old_node.mode)) { + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + } + if (new_node) { + for (var i in new_node.contents) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + } + } + // do the internal rewiring + delete old_node.parent.contents[old_node.name]; + old_node.name = new_name; + new_dir.contents[new_name] = old_node; + old_node.parent = new_dir; + },unlink:function (parent, name) { + delete parent.contents[name]; + },rmdir:function (parent, name) { + var node = FS.lookupNode(parent, name); + for (var i in node.contents) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + delete parent.contents[name]; + },readdir:function (node) { + var entries = ['.', '..'] + for (var key in node.contents) { + if (!node.contents.hasOwnProperty(key)) { + continue; + } + entries.push(key); + } + return entries; + },symlink:function (parent, newname, oldpath) { + var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0); + node.link = oldpath; + return node; + },readlink:function (node) { + if (!FS.isLink(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + return node.link; + }},stream_ops:{read:function (stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (size > 8 && contents.subarray) { // non-trivial, and typed array + buffer.set(contents.subarray(position, position + size), offset); + } else + { + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } + return size; + },write:function (stream, buffer, offset, length, position, canOwn) { + var node = stream.node; + node.timestamp = Date.now(); + var contents = node.contents; + if (length && contents.length === 0 && position === 0 && buffer.subarray) { + // just replace it with the new data + if (canOwn && offset === 0) { + node.contents = buffer; // this could be a subarray of Emscripten HEAP, or allocated from some other source. + node.contentMode = (buffer.buffer === HEAP8.buffer) ? MEMFS.CONTENT_OWNING : MEMFS.CONTENT_FIXED; + } else { + node.contents = new Uint8Array(buffer.subarray(offset, offset+length)); + node.contentMode = MEMFS.CONTENT_FIXED; + } + return length; + } + MEMFS.ensureFlexible(node); + var contents = node.contents; + while (contents.length < position) contents.push(0); + for (var i = 0; i < length; i++) { + contents[position + i] = buffer[offset + i]; + } + return length; + },llseek:function (stream, offset, whence) { + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + if (FS.isFile(stream.node.mode)) { + position += stream.node.contents.length; + } + } + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + stream.ungotten = []; + stream.position = position; + return position; + },allocate:function (stream, offset, length) { + MEMFS.ensureFlexible(stream.node); + var contents = stream.node.contents; + var limit = offset + length; + while (limit > contents.length) contents.push(0); + },mmap:function (stream, buffer, offset, length, position, prot, flags) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + var ptr; + var allocated; + var contents = stream.node.contents; + // Only make a new copy when MAP_PRIVATE is specified. + if ( !(flags & 2) && + (contents.buffer === buffer || contents.buffer === buffer.buffer) ) { + // We can't emulate MAP_SHARED when the file is not backed by the buffer + // we're mapping to (e.g. the HEAP buffer). + allocated = false; + ptr = contents.byteOffset; + } else { + // Try to avoid unnecessary slices. + if (position > 0 || position + length < contents.length) { + if (contents.subarray) { + contents = contents.subarray(position, position + length); + } else { + contents = Array.prototype.slice.call(contents, position, position + length); + } + } + allocated = true; + ptr = _malloc(length); + if (!ptr) { + throw new FS.ErrnoError(ERRNO_CODES.ENOMEM); + } + buffer.set(contents, ptr); + } + return { ptr: ptr, allocated: allocated }; + }}}; + + var IDBFS={dbs:{},indexedDB:function () { + return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + },DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:function (mount) { + // reuse all of the core MEMFS functionality + return MEMFS.mount.apply(null, arguments); + },syncfs:function (mount, populate, callback) { + IDBFS.getLocalSet(mount, function(err, local) { + if (err) return callback(err); + + IDBFS.getRemoteSet(mount, function(err, remote) { + if (err) return callback(err); + + var src = populate ? remote : local; + var dst = populate ? local : remote; + + IDBFS.reconcile(src, dst, callback); + }); + }); + },getDB:function (name, callback) { + // check the cache first + var db = IDBFS.dbs[name]; + if (db) { + return callback(null, db); + } + + var req; + try { + req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION); + } catch (e) { + return callback(e); + } + req.onupgradeneeded = function(e) { + var db = e.target.result; + var transaction = e.target.transaction; + + var fileStore; + + if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) { + fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME); + } else { + fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME); + } + + fileStore.createIndex('timestamp', 'timestamp', { unique: false }); + }; + req.onsuccess = function() { + db = req.result; + + // add to the cache + IDBFS.dbs[name] = db; + callback(null, db); + }; + req.onerror = function() { + callback(this.error); + }; + },getLocalSet:function (mount, callback) { + var entries = {}; + + function isRealDir(p) { + return p !== '.' && p !== '..'; + }; + function toAbsolute(root) { + return function(p) { + return PATH.join2(root, p); + } + }; + + var check = FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint)); + + while (check.length) { + var path = check.pop(); + var stat; + + try { + stat = FS.stat(path); + } catch (e) { + return callback(e); + } + + if (FS.isDir(stat.mode)) { + check.push.apply(check, FS.readdir(path).filter(isRealDir).map(toAbsolute(path))); + } + + entries[path] = { timestamp: stat.mtime }; + } + + return callback(null, { type: 'local', entries: entries }); + },getRemoteSet:function (mount, callback) { + var entries = {}; + + IDBFS.getDB(mount.mountpoint, function(err, db) { + if (err) return callback(err); + + var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readonly'); + transaction.onerror = function() { callback(this.error); }; + + var store = transaction.objectStore(IDBFS.DB_STORE_NAME); + var index = store.index('timestamp'); + + index.openKeyCursor().onsuccess = function(event) { + var cursor = event.target.result; + + if (!cursor) { + return callback(null, { type: 'remote', db: db, entries: entries }); + } + + entries[cursor.primaryKey] = { timestamp: cursor.key }; + + cursor.continue(); + }; + }); + },loadLocalEntry:function (path, callback) { + var stat, node; + + try { + var lookup = FS.lookupPath(path); + node = lookup.node; + stat = FS.stat(path); + } catch (e) { + return callback(e); + } + + if (FS.isDir(stat.mode)) { + return callback(null, { timestamp: stat.mtime, mode: stat.mode }); + } else if (FS.isFile(stat.mode)) { + return callback(null, { timestamp: stat.mtime, mode: stat.mode, contents: node.contents }); + } else { + return callback(new Error('node type not supported')); + } + },storeLocalEntry:function (path, entry, callback) { + try { + if (FS.isDir(entry.mode)) { + FS.mkdir(path, entry.mode); + } else if (FS.isFile(entry.mode)) { + FS.writeFile(path, entry.contents, { encoding: 'binary', canOwn: true }); + } else { + return callback(new Error('node type not supported')); + } + + FS.utime(path, entry.timestamp, entry.timestamp); + } catch (e) { + return callback(e); + } + + callback(null); + },removeLocalEntry:function (path, callback) { + try { + var lookup = FS.lookupPath(path); + var stat = FS.stat(path); + + if (FS.isDir(stat.mode)) { + FS.rmdir(path); + } else if (FS.isFile(stat.mode)) { + FS.unlink(path); + } + } catch (e) { + return callback(e); + } + + callback(null); + },loadRemoteEntry:function (store, path, callback) { + var req = store.get(path); + req.onsuccess = function(event) { callback(null, event.target.result); }; + req.onerror = function() { callback(this.error); }; + },storeRemoteEntry:function (store, path, entry, callback) { + var req = store.put(entry, path); + req.onsuccess = function() { callback(null); }; + req.onerror = function() { callback(this.error); }; + },removeRemoteEntry:function (store, path, callback) { + var req = store.delete(path); + req.onsuccess = function() { callback(null); }; + req.onerror = function() { callback(this.error); }; + },reconcile:function (src, dst, callback) { + var total = 0; + + var create = []; + Object.keys(src.entries).forEach(function (key) { + var e = src.entries[key]; + var e2 = dst.entries[key]; + if (!e2 || e.timestamp > e2.timestamp) { + create.push(key); + total++; + } + }); + + var remove = []; + Object.keys(dst.entries).forEach(function (key) { + var e = dst.entries[key]; + var e2 = src.entries[key]; + if (!e2) { + remove.push(key); + total++; + } + }); + + if (!total) { + return callback(null); + } + + var errored = false; + var completed = 0; + var db = src.type === 'remote' ? src.db : dst.db; + var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite'); + var store = transaction.objectStore(IDBFS.DB_STORE_NAME); + + function done(err) { + if (err) { + if (!done.errored) { + done.errored = true; + return callback(err); + } + return; + } + if (++completed >= total) { + return callback(null); + } + }; + + transaction.onerror = function() { done(this.error); }; + + // sort paths in ascending order so directory entries are created + // before the files inside them + create.sort().forEach(function (path) { + if (dst.type === 'local') { + IDBFS.loadRemoteEntry(store, path, function (err, entry) { + if (err) return done(err); + IDBFS.storeLocalEntry(path, entry, done); + }); + } else { + IDBFS.loadLocalEntry(path, function (err, entry) { + if (err) return done(err); + IDBFS.storeRemoteEntry(store, path, entry, done); + }); + } + }); + + // sort paths in descending order so files are deleted before their + // parent directories + remove.sort().reverse().forEach(function(path) { + if (dst.type === 'local') { + IDBFS.removeLocalEntry(path, done); + } else { + IDBFS.removeRemoteEntry(store, path, done); + } + }); + }}; + + var NODEFS={isWindows:false,staticInit:function () { + NODEFS.isWindows = !!process.platform.match(/^win/); + },mount:function (mount) { + assert(ENVIRONMENT_IS_NODE); + return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0); + },createNode:function (parent, name, mode, dev) { + if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node = FS.createNode(parent, name, mode); + node.node_ops = NODEFS.node_ops; + node.stream_ops = NODEFS.stream_ops; + return node; + },getMode:function (path) { + var stat; + try { + stat = fs.lstatSync(path); + if (NODEFS.isWindows) { + // On Windows, directories return permission bits 'rw-rw-rw-', even though they have 'rwxrwxrwx', so + // propagate write bits to execute bits. + stat.mode = stat.mode | ((stat.mode & 146) >> 1); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return stat.mode; + },realPath:function (node) { + var parts = []; + while (node.parent !== node) { + parts.push(node.name); + node = node.parent; + } + parts.push(node.mount.opts.root); + parts.reverse(); + return PATH.join.apply(null, parts); + },flagsToPermissionStringMap:{0:"r",1:"r+",2:"r+",64:"r",65:"r+",66:"r+",129:"rx+",193:"rx+",514:"w+",577:"w",578:"w+",705:"wx",706:"wx+",1024:"a",1025:"a",1026:"a+",1089:"a",1090:"a+",1153:"ax",1154:"ax+",1217:"ax",1218:"ax+",4096:"rs",4098:"rs+"},flagsToPermissionString:function (flags) { + if (flags in NODEFS.flagsToPermissionStringMap) { + return NODEFS.flagsToPermissionStringMap[flags]; + } else { + return flags; + } + },node_ops:{getattr:function (node) { + var path = NODEFS.realPath(node); + var stat; + try { + stat = fs.lstatSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + // node.js v0.10.20 doesn't report blksize and blocks on Windows. Fake them with default blksize of 4096. + // See http://support.microsoft.com/kb/140365 + if (NODEFS.isWindows && !stat.blksize) { + stat.blksize = 4096; + } + if (NODEFS.isWindows && !stat.blocks) { + stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0; + } + return { + dev: stat.dev, + ino: stat.ino, + mode: stat.mode, + nlink: stat.nlink, + uid: stat.uid, + gid: stat.gid, + rdev: stat.rdev, + size: stat.size, + atime: stat.atime, + mtime: stat.mtime, + ctime: stat.ctime, + blksize: stat.blksize, + blocks: stat.blocks + }; + },setattr:function (node, attr) { + var path = NODEFS.realPath(node); + try { + if (attr.mode !== undefined) { + fs.chmodSync(path, attr.mode); + // update the common node structure mode as well + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + var date = new Date(attr.timestamp); + fs.utimesSync(path, date, date); + } + if (attr.size !== undefined) { + fs.truncateSync(path, attr.size); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },lookup:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + var mode = NODEFS.getMode(path); + return NODEFS.createNode(parent, name, mode); + },mknod:function (parent, name, mode, dev) { + var node = NODEFS.createNode(parent, name, mode, dev); + // create the backing node for this in the fs root as well + var path = NODEFS.realPath(node); + try { + if (FS.isDir(node.mode)) { + fs.mkdirSync(path, node.mode); + } else { + fs.writeFileSync(path, '', { mode: node.mode }); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return node; + },rename:function (oldNode, newDir, newName) { + var oldPath = NODEFS.realPath(oldNode); + var newPath = PATH.join2(NODEFS.realPath(newDir), newName); + try { + fs.renameSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },unlink:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.unlinkSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },rmdir:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.rmdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },readdir:function (node) { + var path = NODEFS.realPath(node); + try { + return fs.readdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },symlink:function (parent, newName, oldPath) { + var newPath = PATH.join2(NODEFS.realPath(parent), newName); + try { + fs.symlinkSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },readlink:function (node) { + var path = NODEFS.realPath(node); + try { + return fs.readlinkSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }},stream_ops:{open:function (stream) { + var path = NODEFS.realPath(stream.node); + try { + if (FS.isFile(stream.node.mode)) { + stream.nfd = fs.openSync(path, NODEFS.flagsToPermissionString(stream.flags)); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },close:function (stream) { + try { + if (FS.isFile(stream.node.mode) && stream.nfd) { + fs.closeSync(stream.nfd); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },read:function (stream, buffer, offset, length, position) { + // FIXME this is terrible. + var nbuffer = new Buffer(length); + var res; + try { + res = fs.readSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + if (res > 0) { + for (var i = 0; i < res; i++) { + buffer[offset + i] = nbuffer[i]; + } + } + return res; + },write:function (stream, buffer, offset, length, position) { + // FIXME this is terrible. + var nbuffer = new Buffer(buffer.subarray(offset, offset + length)); + var res; + try { + res = fs.writeSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return res; + },llseek:function (stream, offset, whence) { + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + if (FS.isFile(stream.node.mode)) { + try { + var stat = fs.fstatSync(stream.nfd); + position += stat.size; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + } + } + + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + stream.position = position; + return position; + }}}; + + var _stdin=allocate(1, "i32*", ALLOC_STATIC); + + var _stdout=allocate(1, "i32*", ALLOC_STATIC); + + var _stderr=allocate(1, "i32*", ALLOC_STATIC); + + function _fflush(stream) { + // int fflush(FILE *stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fflush.html + // we don't currently perform any user-space buffering of data + }var FS={root:null,mounts:[],devices:[null],streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},handleFSError:function (e) { + if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace(); + return ___setErrNo(e.errno); + },lookupPath:function (path, opts) { + path = PATH.resolve(FS.cwd(), path); + opts = opts || {}; + + var defaults = { + follow_mount: true, + recurse_count: 0 + }; + for (var key in defaults) { + if (opts[key] === undefined) { + opts[key] = defaults[key]; + } + } + + if (opts.recurse_count > 8) { // max recursive lookup of 8 + throw new FS.ErrnoError(ERRNO_CODES.ELOOP); + } + + // split the path + var parts = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), false); + + // start at the root + var current = FS.root; + var current_path = '/'; + + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + // stop resolving + break; + } + + current = FS.lookupNode(current, parts[i]); + current_path = PATH.join2(current_path, parts[i]); + + // jump to the mount's root node if this is a mountpoint + if (FS.isMountpoint(current)) { + if (!islast || (islast && opts.follow_mount)) { + current = current.mounted.root; + } + } + + // by default, lookupPath will not follow a symlink if it is the final path component. + // setting opts.follow = true will override this behavior. + if (!islast || opts.follow) { + var count = 0; + while (FS.isLink(current.mode)) { + var link = FS.readlink(current_path); + current_path = PATH.resolve(PATH.dirname(current_path), link); + + var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count }); + current = lookup.node; + + if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX). + throw new FS.ErrnoError(ERRNO_CODES.ELOOP); + } + } + } + } + + return { path: current_path, node: current }; + },getPath:function (node) { + var path; + while (true) { + if (FS.isRoot(node)) { + var mount = node.mount.mountpoint; + if (!path) return mount; + return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path; + } + path = path ? node.name + '/' + path : node.name; + node = node.parent; + } + },hashName:function (parentid, name) { + var hash = 0; + + + for (var i = 0; i < name.length; i++) { + hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; + } + return ((parentid + hash) >>> 0) % FS.nameTable.length; + },hashAddNode:function (node) { + var hash = FS.hashName(node.parent.id, node.name); + node.name_next = FS.nameTable[hash]; + FS.nameTable[hash] = node; + },hashRemoveNode:function (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:function (parent, name) { + var err = FS.mayLookup(parent); + if (err) { + throw new FS.ErrnoError(err); + } + 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; + } + } + // if we failed to find it in the cache, call into the VFS + return FS.lookup(parent, name); + },createNode:function (parent, name, mode, rdev) { + if (!FS.FSNode) { + FS.FSNode = function(parent, name, mode, rdev) { + if (!parent) { + parent = this; // root node sets parent to itself + } + this.parent = parent; + this.mount = parent.mount; + this.mounted = null; + this.id = FS.nextInode++; + this.name = name; + this.mode = mode; + this.node_ops = {}; + this.stream_ops = {}; + this.rdev = rdev; + }; + + FS.FSNode.prototype = {}; + + // compatibility + var readMode = 292 | 73; + var writeMode = 146; + + // NOTE we must use Object.defineProperties instead of individual calls to + // Object.defineProperty in order to make closure compiler happy + Object.defineProperties(FS.FSNode.prototype, { + read: { + get: function() { return (this.mode & readMode) === readMode; }, + set: function(val) { val ? this.mode |= readMode : this.mode &= ~readMode; } + }, + write: { + get: function() { return (this.mode & writeMode) === writeMode; }, + set: function(val) { val ? this.mode |= writeMode : this.mode &= ~writeMode; } + }, + isFolder: { + get: function() { return FS.isDir(this.mode); }, + }, + isDevice: { + get: function() { return FS.isChrdev(this.mode); }, + }, + }); + } + + var node = new FS.FSNode(parent, name, mode, rdev); + + FS.hashAddNode(node); + + return node; + },destroyNode:function (node) { + FS.hashRemoveNode(node); + },isRoot:function (node) { + return node === node.parent; + },isMountpoint:function (node) { + return !!node.mounted; + },isFile:function (mode) { + return (mode & 61440) === 32768; + },isDir:function (mode) { + return (mode & 61440) === 16384; + },isLink:function (mode) { + return (mode & 61440) === 40960; + },isChrdev:function (mode) { + return (mode & 61440) === 8192; + },isBlkdev:function (mode) { + return (mode & 61440) === 24576; + },isFIFO:function (mode) { + return (mode & 61440) === 4096; + },isSocket:function (mode) { + return (mode & 49152) === 49152; + },flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function (str) { + var flags = FS.flagModes[str]; + if (typeof flags === 'undefined') { + throw new Error('Unknown file open mode: ' + str); + } + return flags; + },flagsToPermissionString:function (flag) { + var accmode = flag & 2097155; + var perms = ['r', 'w', 'rw'][accmode]; + if ((flag & 512)) { + perms += 'w'; + } + return perms; + },nodePermissions:function (node, perms) { + if (FS.ignorePermissions) { + return 0; + } + // return 0 if any user, group or owner bits are set. + if (perms.indexOf('r') !== -1 && !(node.mode & 292)) { + return ERRNO_CODES.EACCES; + } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) { + return ERRNO_CODES.EACCES; + } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) { + return ERRNO_CODES.EACCES; + } + return 0; + },mayLookup:function (dir) { + return FS.nodePermissions(dir, 'x'); + },mayCreate:function (dir, name) { + try { + var node = FS.lookupNode(dir, name); + return ERRNO_CODES.EEXIST; + } catch (e) { + } + return FS.nodePermissions(dir, 'wx'); + },mayDelete:function (dir, name, isdir) { + var node; + try { + node = FS.lookupNode(dir, name); + } catch (e) { + return e.errno; + } + var err = FS.nodePermissions(dir, 'wx'); + if (err) { + return err; + } + if (isdir) { + if (!FS.isDir(node.mode)) { + return ERRNO_CODES.ENOTDIR; + } + if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { + return ERRNO_CODES.EBUSY; + } + } else { + if (FS.isDir(node.mode)) { + return ERRNO_CODES.EISDIR; + } + } + return 0; + },mayOpen:function (node, flags) { + if (!node) { + return ERRNO_CODES.ENOENT; + } + if (FS.isLink(node.mode)) { + return ERRNO_CODES.ELOOP; + } else if (FS.isDir(node.mode)) { + if ((flags & 2097155) !== 0 || // opening for write + (flags & 512)) { + return ERRNO_CODES.EISDIR; + } + } + return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); + },MAX_OPEN_FDS:4096,nextfd:function (fd_start, fd_end) { + fd_start = fd_start || 0; + fd_end = fd_end || FS.MAX_OPEN_FDS; + for (var fd = fd_start; fd <= fd_end; fd++) { + if (!FS.streams[fd]) { + return fd; + } + } + throw new FS.ErrnoError(ERRNO_CODES.EMFILE); + },getStream:function (fd) { + return FS.streams[fd]; + },createStream:function (stream, fd_start, fd_end) { + if (!FS.FSStream) { + FS.FSStream = function(){}; + FS.FSStream.prototype = {}; + // compatibility + Object.defineProperties(FS.FSStream.prototype, { + object: { + get: function() { return this.node; }, + set: function(val) { this.node = val; } + }, + isRead: { + get: function() { return (this.flags & 2097155) !== 1; } + }, + isWrite: { + get: function() { return (this.flags & 2097155) !== 0; } + }, + isAppend: { + get: function() { return (this.flags & 1024); } + } + }); + } + // clone it, so we can return an instance of FSStream + var newStream = new FS.FSStream(); + for (var p in stream) { + newStream[p] = stream[p]; + } + stream = newStream; + var fd = FS.nextfd(fd_start, fd_end); + stream.fd = fd; + FS.streams[fd] = stream; + return stream; + },closeStream:function (fd) { + FS.streams[fd] = null; + },getStreamFromPtr:function (ptr) { + return FS.streams[ptr - 1]; + },getPtrForStream:function (stream) { + return stream ? stream.fd + 1 : 0; + },chrdev_stream_ops:{open:function (stream) { + var device = FS.getDevice(stream.node.rdev); + // override node's stream ops with the device's + stream.stream_ops = device.stream_ops; + // forward the open call + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + },llseek:function () { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + }},major:function (dev) { + return ((dev) >> 8); + },minor:function (dev) { + return ((dev) & 0xff); + },makedev:function (ma, mi) { + return ((ma) << 8 | (mi)); + },registerDevice:function (dev, ops) { + FS.devices[dev] = { stream_ops: ops }; + },getDevice:function (dev) { + return FS.devices[dev]; + },getMounts:function (mount) { + var mounts = []; + var check = [mount]; + + while (check.length) { + var m = check.pop(); + + mounts.push(m); + + check.push.apply(check, m.mounts); + } + + return mounts; + },syncfs:function (populate, callback) { + if (typeof(populate) === 'function') { + callback = populate; + populate = false; + } + + var mounts = FS.getMounts(FS.root.mount); + var completed = 0; + + function done(err) { + if (err) { + if (!done.errored) { + done.errored = true; + return callback(err); + } + return; + } + if (++completed >= mounts.length) { + callback(null); + } + }; + + // sync all mounts + mounts.forEach(function (mount) { + if (!mount.type.syncfs) { + return done(null); + } + mount.type.syncfs(mount, populate, done); + }); + },mount:function (type, opts, mountpoint) { + var root = mountpoint === '/'; + var pseudo = !mountpoint; + var node; + + if (root && FS.root) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } else if (!root && !pseudo) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + mountpoint = lookup.path; // use the absolute path + node = lookup.node; + + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + + if (!FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + } + + var mount = { + type: type, + opts: opts, + mountpoint: mountpoint, + mounts: [] + }; + + // create a root node for the fs + var mountRoot = type.mount(mount); + mountRoot.mount = mount; + mount.root = mountRoot; + + if (root) { + FS.root = mountRoot; + } else if (node) { + // set as a mountpoint + node.mounted = mount; + + // add the new mount to the current mount's children + if (node.mount) { + node.mount.mounts.push(mount); + } + } + + return mountRoot; + },unmount:function (mountpoint) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + if (!FS.isMountpoint(lookup.node)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + // destroy the nodes for this mount, and all its child mounts + var node = lookup.node; + var mount = node.mounted; + var mounts = FS.getMounts(mount); + + Object.keys(FS.nameTable).forEach(function (hash) { + var current = FS.nameTable[hash]; + + while (current) { + var next = current.name_next; + + if (mounts.indexOf(current.mount) !== -1) { + FS.destroyNode(current); + } + + current = next; + } + }); + + // no longer a mountpoint + node.mounted = null; + + // remove this mount from the child mounts + var idx = node.mount.mounts.indexOf(mount); + assert(idx !== -1); + node.mount.mounts.splice(idx, 1); + },lookup:function (parent, name) { + return parent.node_ops.lookup(parent, name); + },mknod:function (path, mode, dev) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var err = FS.mayCreate(parent, name); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.mknod) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return parent.node_ops.mknod(parent, name, mode, dev); + },create:function (path, mode) { + mode = mode !== undefined ? mode : 438 /* 0666 */; + mode &= 4095; + mode |= 32768; + return FS.mknod(path, mode, 0); + },mkdir:function (path, mode) { + mode = mode !== undefined ? mode : 511 /* 0777 */; + mode &= 511 | 512; + mode |= 16384; + return FS.mknod(path, mode, 0); + },mkdev:function (path, mode, dev) { + if (typeof(dev) === 'undefined') { + dev = mode; + mode = 438 /* 0666 */; + } + mode |= 8192; + return FS.mknod(path, mode, dev); + },symlink:function (oldpath, newpath) { + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + var newname = PATH.basename(newpath); + var err = FS.mayCreate(parent, newname); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.symlink) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return parent.node_ops.symlink(parent, newname, oldpath); + },rename:function (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); + // parents must exist + var lookup, old_dir, new_dir; + try { + lookup = FS.lookupPath(old_path, { parent: true }); + old_dir = lookup.node; + lookup = FS.lookupPath(new_path, { parent: true }); + new_dir = lookup.node; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + // need to be part of the same mount + if (old_dir.mount !== new_dir.mount) { + throw new FS.ErrnoError(ERRNO_CODES.EXDEV); + } + // source must exist + var old_node = FS.lookupNode(old_dir, old_name); + // old path should not be an ancestor of the new path + var relative = PATH.relative(old_path, new_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + // new path should not be an ancestor of the old path + relative = PATH.relative(new_path, old_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + // see if the new path already exists + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + // not fatal + } + // early out if nothing needs to change + if (old_node === new_node) { + return; + } + // we'll need to delete the old entry + var isdir = FS.isDir(old_node.mode); + var err = FS.mayDelete(old_dir, old_name, isdir); + if (err) { + throw new FS.ErrnoError(err); + } + // need delete permissions if we'll be overwriting. + // need create permissions if new doesn't already exist. + err = new_node ? + FS.mayDelete(new_dir, new_name, isdir) : + FS.mayCreate(new_dir, new_name); + if (err) { + throw new FS.ErrnoError(err); + } + if (!old_dir.node_ops.rename) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + // if we are going to change the parent, check write permissions + if (new_dir !== old_dir) { + err = FS.nodePermissions(old_dir, 'w'); + if (err) { + throw new FS.ErrnoError(err); + } + } + // remove the node from the lookup hash + FS.hashRemoveNode(old_node); + // do the underlying fs rename + try { + old_dir.node_ops.rename(old_node, new_dir, new_name); + } catch (e) { + throw e; + } finally { + // add the node back to the hash (in case node_ops.rename + // changed its name) + FS.hashAddNode(old_node); + } + },rmdir:function (path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var err = FS.mayDelete(parent, name, true); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.rmdir) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + parent.node_ops.rmdir(parent, name); + FS.destroyNode(node); + },readdir:function (path) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node.node_ops.readdir) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + return node.node_ops.readdir(node); + },unlink:function (path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var err = FS.mayDelete(parent, name, false); + if (err) { + // POSIX says unlink should set EPERM, not EISDIR + if (err === ERRNO_CODES.EISDIR) err = ERRNO_CODES.EPERM; + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.unlink) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + parent.node_ops.unlink(parent, name); + FS.destroyNode(node); + },readlink:function (path) { + var lookup = FS.lookupPath(path); + var link = lookup.node; + if (!link.node_ops.readlink) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + return link.node_ops.readlink(link); + },stat:function (path, dontFollow) { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var node = lookup.node; + if (!node.node_ops.getattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return node.node_ops.getattr(node); + },lstat:function (path) { + return FS.stat(path, true); + },chmod:function (path, mode, dontFollow) { + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + node.node_ops.setattr(node, { + mode: (mode & 4095) | (node.mode & ~4095), + timestamp: Date.now() + }); + },lchmod:function (path, mode) { + FS.chmod(path, mode, true); + },fchmod:function (fd, mode) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + FS.chmod(stream.node, mode); + },chown:function (path, uid, gid, dontFollow) { + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + node.node_ops.setattr(node, { + timestamp: Date.now() + // we ignore the uid / gid for now + }); + },lchown:function (path, uid, gid) { + FS.chown(path, uid, gid, true); + },fchown:function (fd, uid, gid) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + FS.chown(stream.node, uid, gid); + },truncate:function (path, len) { + if (len < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: true }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!FS.isFile(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var err = FS.nodePermissions(node, 'w'); + if (err) { + throw new FS.ErrnoError(err); + } + node.node_ops.setattr(node, { + size: len, + timestamp: Date.now() + }); + },ftruncate:function (fd, len) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + FS.truncate(stream.node, len); + },utime:function (path, atime, mtime) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + node.node_ops.setattr(node, { + timestamp: Math.max(atime, mtime) + }); + },open:function (path, flags, mode, fd_start, fd_end) { + flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags; + mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode; + if ((flags & 64)) { + mode = (mode & 4095) | 32768; + } else { + mode = 0; + } + var node; + if (typeof path === 'object') { + node = path; + } else { + path = PATH.normalize(path); + try { + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072) + }); + node = lookup.node; + } catch (e) { + // ignore + } + } + // perhaps we need to create the node + if ((flags & 64)) { + if (node) { + // if O_CREAT and O_EXCL are set, error out if the node already exists + if ((flags & 128)) { + throw new FS.ErrnoError(ERRNO_CODES.EEXIST); + } + } else { + // node doesn't exist, try to create it + node = FS.mknod(path, mode, 0); + } + } + if (!node) { + throw new FS.ErrnoError(ERRNO_CODES.ENOENT); + } + // can't truncate a device + if (FS.isChrdev(node.mode)) { + flags &= ~512; + } + // check permissions + var err = FS.mayOpen(node, flags); + if (err) { + throw new FS.ErrnoError(err); + } + // do truncation if necessary + if ((flags & 512)) { + FS.truncate(node, 0); + } + // we've already handled these, don't pass down to the underlying vfs + flags &= ~(128 | 512); + + // register the stream with the filesystem + var stream = FS.createStream({ + node: node, + path: FS.getPath(node), // we want the absolute path to the node + flags: flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + // used by the file family libc calls (fopen, fwrite, ferror, etc.) + ungotten: [], + error: false + }, fd_start, fd_end); + // call the new stream's open function + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + if (Module['logReadFiles'] && !(flags & 1)) { + if (!FS.readFiles) FS.readFiles = {}; + if (!(path in FS.readFiles)) { + FS.readFiles[path] = 1; + Module['printErr']('read file: ' + path); + } + } + return stream; + },close:function (stream) { + try { + if (stream.stream_ops.close) { + stream.stream_ops.close(stream); + } + } catch (e) { + throw e; + } finally { + FS.closeStream(stream.fd); + } + },llseek:function (stream, offset, whence) { + if (!stream.seekable || !stream.stream_ops.llseek) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + return stream.stream_ops.llseek(stream, offset, whence); + },read:function (stream, buffer, offset, length, position) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!stream.stream_ops.read) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var seeking = true; + if (typeof position === 'undefined') { + position = stream.position; + seeking = false; + } else if (!stream.seekable) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); + if (!seeking) stream.position += bytesRead; + return bytesRead; + },write:function (stream, buffer, offset, length, position, canOwn) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!stream.stream_ops.write) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var seeking = true; + if (typeof position === 'undefined') { + position = stream.position; + seeking = false; + } else if (!stream.seekable) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + if (stream.flags & 1024) { + // seek to the end before writing in append mode + FS.llseek(stream, 0, 2); + } + var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); + if (!seeking) stream.position += bytesWritten; + return bytesWritten; + },allocate:function (stream, offset, length) { + if (offset < 0 || length <= 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (!FS.isFile(stream.node.mode) && !FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + if (!stream.stream_ops.allocate) { + throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP); + } + stream.stream_ops.allocate(stream, offset, length); + },mmap:function (stream, buffer, offset, length, position, prot, flags) { + // TODO if PROT is PROT_WRITE, make sure we have write access + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(ERRNO_CODES.EACCES); + } + if (!stream.stream_ops.mmap) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + return stream.stream_ops.mmap(stream, buffer, offset, length, position, prot, flags); + },ioctl:function (stream, cmd, arg) { + if (!stream.stream_ops.ioctl) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTTY); + } + return stream.stream_ops.ioctl(stream, cmd, arg); + },readFile:function (path, opts) { + opts = opts || {}; + opts.flags = opts.flags || 'r'; + opts.encoding = opts.encoding || 'binary'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error('Invalid encoding type "' + opts.encoding + '"'); + } + var ret; + 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') { + ret = ''; + var utf8 = new Runtime.UTF8Processor(); + for (var i = 0; i < length; i++) { + ret += utf8.processCChar(buf[i]); + } + } else if (opts.encoding === 'binary') { + ret = buf; + } + FS.close(stream); + return ret; + },writeFile:function (path, data, opts) { + opts = opts || {}; + opts.flags = opts.flags || 'w'; + opts.encoding = opts.encoding || 'utf8'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error('Invalid encoding type "' + opts.encoding + '"'); + } + var stream = FS.open(path, opts.flags, opts.mode); + if (opts.encoding === 'utf8') { + var utf8 = new Runtime.UTF8Processor(); + var buf = new Uint8Array(utf8.processJSString(data)); + FS.write(stream, buf, 0, buf.length, 0, opts.canOwn); + } else if (opts.encoding === 'binary') { + FS.write(stream, data, 0, data.length, 0, opts.canOwn); + } + FS.close(stream); + },cwd:function () { + return FS.currentPath; + },chdir:function (path) { + var lookup = FS.lookupPath(path, { follow: true }); + if (!FS.isDir(lookup.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + var err = FS.nodePermissions(lookup.node, 'x'); + if (err) { + throw new FS.ErrnoError(err); + } + FS.currentPath = lookup.path; + },createDefaultDirectories:function () { + FS.mkdir('/tmp'); + },createDefaultDevices:function () { + // create /dev + FS.mkdir('/dev'); + // setup /dev/null + FS.registerDevice(FS.makedev(1, 3), { + read: function() { return 0; }, + write: function() { return 0; } + }); + FS.mkdev('/dev/null', FS.makedev(1, 3)); + // setup /dev/tty and /dev/tty1 + // stderr needs to print output using Module['printErr'] + // so we register a second tty just for it. + 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)); + // we're not going to emulate the actual shm device, + // just create the tmp dirs that reside in it commonly + FS.mkdir('/dev/shm'); + FS.mkdir('/dev/shm/tmp'); + },createStandardStreams:function () { + // TODO deprecate the old functionality of a single + // input / output callback and that utilizes FS.createDevice + // and instead require a unique set of stream ops + + // by default, we symlink the standard streams to the + // default tty devices. however, if the standard streams + // have been overwritten we create a unique device for + // them instead. + if (Module['stdin']) { + FS.createDevice('/dev', 'stdin', Module['stdin']); + } else { + FS.symlink('/dev/tty', '/dev/stdin'); + } + if (Module['stdout']) { + FS.createDevice('/dev', 'stdout', null, Module['stdout']); + } else { + FS.symlink('/dev/tty', '/dev/stdout'); + } + if (Module['stderr']) { + FS.createDevice('/dev', 'stderr', null, Module['stderr']); + } else { + FS.symlink('/dev/tty1', '/dev/stderr'); + } + + // open default streams for the stdin, stdout and stderr devices + var stdin = FS.open('/dev/stdin', 'r'); + HEAP32[((_stdin)>>2)]=FS.getPtrForStream(stdin); + assert(stdin.fd === 0, 'invalid handle for stdin (' + stdin.fd + ')'); + + var stdout = FS.open('/dev/stdout', 'w'); + HEAP32[((_stdout)>>2)]=FS.getPtrForStream(stdout); + assert(stdout.fd === 1, 'invalid handle for stdout (' + stdout.fd + ')'); + + var stderr = FS.open('/dev/stderr', 'w'); + HEAP32[((_stderr)>>2)]=FS.getPtrForStream(stderr); + assert(stderr.fd === 2, 'invalid handle for stderr (' + stderr.fd + ')'); + },ensureErrnoError:function () { + if (FS.ErrnoError) return; + FS.ErrnoError = function ErrnoError(errno) { + this.errno = errno; + for (var key in ERRNO_CODES) { + if (ERRNO_CODES[key] === errno) { + this.code = key; + break; + } + } + this.message = ERRNO_MESSAGES[errno]; + }; + FS.ErrnoError.prototype = new Error(); + FS.ErrnoError.prototype.constructor = FS.ErrnoError; + // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info) + [ERRNO_CODES.ENOENT].forEach(function(code) { + FS.genericErrors[code] = new FS.ErrnoError(code); + FS.genericErrors[code].stack = ''; + }); + },staticInit:function () { + FS.ensureErrnoError(); + + FS.nameTable = new Array(4096); + + FS.mount(MEMFS, {}, '/'); + + FS.createDefaultDirectories(); + FS.createDefaultDevices(); + },init:function (input, output, error) { + assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); + FS.init.initialized = true; + + FS.ensureErrnoError(); + + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + Module['stdin'] = input || Module['stdin']; + Module['stdout'] = output || Module['stdout']; + Module['stderr'] = error || Module['stderr']; + + FS.createStandardStreams(); + },quit:function () { + FS.init.initialized = false; + for (var i = 0; i < FS.streams.length; i++) { + var stream = FS.streams[i]; + if (!stream) { + continue; + } + FS.close(stream); + } + },getMode:function (canRead, canWrite) { + var mode = 0; + if (canRead) mode |= 292 | 73; + if (canWrite) mode |= 146; + return mode; + },joinPath:function (parts, forceRelative) { + var path = PATH.join.apply(null, parts); + if (forceRelative && path[0] == '/') path = path.substr(1); + return path; + },absolutePath:function (relative, base) { + return PATH.resolve(base, relative); + },standardizePath:function (path) { + return PATH.normalize(path); + },findObject:function (path, dontResolveLastLink) { + var ret = FS.analyzePath(path, dontResolveLastLink); + if (ret.exists) { + return ret.object; + } else { + ___setErrNo(ret.error); + return null; + } + },analyzePath:function (path, dontResolveLastLink) { + // operate from within the context of the symlink's target + 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; + },createFolder:function (parent, name, canRead, canWrite) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var mode = FS.getMode(canRead, canWrite); + return FS.mkdir(path, mode); + },createPath:function (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) { + // ignore EEXIST + } + parent = current; + } + return current; + },createFile:function (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:function (parent, name, data, canRead, canWrite, canOwn) { + var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(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; i < len; ++i) arr[i] = data.charCodeAt(i); + data = arr; + } + // make sure we can write to the file + FS.chmod(node, mode | 146); + var stream = FS.open(node, 'w'); + FS.write(stream, data, 0, data.length, 0, canOwn); + FS.close(stream); + FS.chmod(node, mode); + } + return node; + },createDevice:function (parent, name, input, output) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var mode = FS.getMode(!!input, !!output); + if (!FS.createDevice.major) FS.createDevice.major = 64; + var dev = FS.makedev(FS.createDevice.major++, 0); + // Create a fake device that a set of stream ops to emulate + // the old behavior. + FS.registerDevice(dev, { + open: function(stream) { + stream.seekable = false; + }, + close: function(stream) { + // flush any pending line data + if (output && output.buffer && output.buffer.length) { + output(10); + } + }, + read: function(stream, buffer, offset, length, pos /* ignored */) { + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = input(); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + }, + write: function(stream, buffer, offset, length, pos) { + for (var i = 0; i < length; i++) { + try { + output(buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + } + }); + return FS.mkdev(path, mode, dev); + },createLink:function (parent, name, target, canRead, canWrite) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + return FS.symlink(target, path); + },forceLoadFile:function (obj) { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + var success = true; + if (typeof XMLHttpRequest !== 'undefined') { + throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else if (Module['read']) { + // Command-line. + try { + // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as + // read() will try to parse UTF8. + obj.contents = intArrayFromString(Module['read'](obj.url), true); + } catch (e) { + success = false; + } + } else { + throw new Error('Cannot load without read() or XMLHttpRequest.'); + } + if (!success) ___setErrNo(ERRNO_CODES.EIO); + return success; + },createLazyFile:function (parent, name, url, canRead, canWrite) { + // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. + function LazyUint8Array() { + this.lengthKnown = false; + this.chunks = []; // Loaded chunks. Index is the chunk number + } + LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = Math.floor(idx / this.chunkSize); + return this.getter(chunkNum)[chunkOffset]; + } + LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) { + this.getter = getter; + } + LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("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 chunkSize = 1024*1024; // Chunk size in bytes + + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (function(from, to) { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + if (typeof Uint8Array != 'undefined') 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)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(xhr.response || []); + } else { + return intArrayFromString(xhr.responseText || '', true); + } + }); + var lazyArray = this; + lazyArray.setDataGetter(function(chunkNum) { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); + return lazyArray.chunks[chunkNum]; + }); + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } + if (typeof XMLHttpRequest !== 'undefined') { + if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; + var lazyArray = new LazyUint8Array(); + Object.defineProperty(lazyArray, "length", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + }); + Object.defineProperty(lazyArray, "chunkSize", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + }); + + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + + var node = FS.createFile(parent, name, properties, canRead, canWrite); + // This is a total hack, but I want to get this lazy file code out of the + // core of MEMFS. If we want to keep this lazy file concept I feel it should + // be its own thin LAZYFS proxying calls to MEMFS. + if (properties.contents) { + node.contents = properties.contents; + } else if (properties.url) { + node.contents = null; + node.url = properties.url; + } + // override each stream op with one that tries to force load the lazy file first + var stream_ops = {}; + var keys = Object.keys(node.stream_ops); + keys.forEach(function(key) { + var fn = node.stream_ops[key]; + stream_ops[key] = function forceLoadLazyFile() { + if (!FS.forceLoadFile(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + return fn.apply(null, arguments); + }; + }); + // use a custom read function + stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) { + if (!FS.forceLoadFile(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (contents.slice) { // normal array + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } else { + for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR + buffer[offset + i] = contents.get(position + i); + } + } + return size; + }; + node.stream_ops = stream_ops; + return node; + },createPreloadedFile:function (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn) { + Browser.init(); + // TODO we should allow people to just pass in a complete filename instead + // of parent and name being that we just join them anyways + var fullname = name ? PATH.resolve(PATH.join2(parent, name)) : parent; + function processData(byteArray) { + function finish(byteArray) { + if (!dontCreateFile) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + } + if (onload) onload(); + removeRunDependency('cp ' + fullname); + } + var handled = false; + Module['preloadPlugins'].forEach(function(plugin) { + if (handled) return; + if (plugin['canHandle'](fullname)) { + plugin['handle'](byteArray, fullname, finish, function() { + if (onerror) onerror(); + removeRunDependency('cp ' + fullname); + }); + handled = true; + } + }); + if (!handled) finish(byteArray); + } + addRunDependency('cp ' + fullname); + if (typeof url == 'string') { + Browser.asyncLoad(url, function(byteArray) { + processData(byteArray); + }, onerror); + } else { + processData(url); + } + },indexedDB:function () { + return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + },DB_NAME:function () { + return 'EM_FS_' + window.location.pathname; + },DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function (paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = function openRequest_onupgradeneeded() { + console.log('creating db'); + var db = openRequest.result; + db.createObjectStore(FS.DB_STORE_NAME); + }; + openRequest.onsuccess = function openRequest_onsuccess() { + var db = openRequest.result; + var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite'); + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var putRequest = files.put(FS.analyzePath(path).object.contents, path); + putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) finish() }; + putRequest.onerror = function putRequest_onerror() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + },loadFilesFromDB:function (paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = onerror; // no database to load from + openRequest.onsuccess = function openRequest_onsuccess() { + var db = openRequest.result; + try { + var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly'); + } catch(e) { + onerror(e); + return; + } + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var getRequest = files.get(path); + getRequest.onsuccess = function getRequest_onsuccess() { + if (FS.analyzePath(path).exists) { + FS.unlink(path); + } + FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true); + ok++; + if (ok + fail == total) finish(); + }; + getRequest.onerror = function getRequest_onerror() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + }};function _lseek(fildes, offset, whence) { + // off_t lseek(int fildes, off_t offset, int whence); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/lseek.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + return FS.llseek(stream, offset, whence); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + + Module["_i64Subtract"] = _i64Subtract; + + var _fabsf=Math_abs; + + + + + Module["_strlen"] = _strlen; + + function __reallyNegative(x) { + return x < 0 || (x === 0 && (1/x) === -Infinity); + }function __formatString(format, varargs) { + var textIndex = format; + var argIndex = 0; + function getNextArg(type) { + // NOTE: Explicitly ignoring type safety. Otherwise this fails: + // int x = 4; printf("%c\n", (char)x); + var ret; + if (type === 'double') { + ret = (HEAP32[((tempDoublePtr)>>2)]=HEAP32[(((varargs)+(argIndex))>>2)],HEAP32[(((tempDoublePtr)+(4))>>2)]=HEAP32[(((varargs)+((argIndex)+(4)))>>2)],(+(HEAPF64[(tempDoublePtr)>>3]))); + } else if (type == 'i64') { + ret = [HEAP32[(((varargs)+(argIndex))>>2)], + HEAP32[(((varargs)+(argIndex+4))>>2)]]; + + } else { + type = 'i32'; // varargs are always i32, i64, or double + ret = HEAP32[(((varargs)+(argIndex))>>2)]; + } + argIndex += Runtime.getNativeFieldSize(type); + return ret; + } + + var ret = []; + var curr, next, currArg; + while(1) { + var startTextIndex = textIndex; + curr = HEAP8[(textIndex)]; + if (curr === 0) break; + next = HEAP8[((textIndex+1)|0)]; + if (curr == 37) { + // Handle flags. + var flagAlwaysSigned = false; + var flagLeftAlign = false; + var flagAlternative = false; + var flagZeroPad = false; + var flagPadSign = false; + flagsLoop: while (1) { + switch (next) { + case 43: + flagAlwaysSigned = true; + break; + case 45: + flagLeftAlign = true; + break; + case 35: + flagAlternative = true; + break; + case 48: + if (flagZeroPad) { + break flagsLoop; + } else { + flagZeroPad = true; + break; + } + case 32: + flagPadSign = true; + break; + default: + break flagsLoop; + } + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } + + // Handle width. + var width = 0; + if (next == 42) { + width = getNextArg('i32'); + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } else { + while (next >= 48 && next <= 57) { + width = width * 10 + (next - 48); + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } + } + + // Handle precision. + var precisionSet = false, precision = -1; + if (next == 46) { + precision = 0; + precisionSet = true; + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + if (next == 42) { + precision = getNextArg('i32'); + textIndex++; + } else { + while(1) { + var precisionChr = HEAP8[((textIndex+1)|0)]; + if (precisionChr < 48 || + precisionChr > 57) break; + precision = precision * 10 + (precisionChr - 48); + textIndex++; + } + } + next = HEAP8[((textIndex+1)|0)]; + } + if (precision < 0) { + precision = 6; // Standard default. + precisionSet = false; + } + + // Handle integer sizes. WARNING: These assume a 32-bit architecture! + var argSize; + switch (String.fromCharCode(next)) { + case 'h': + var nextNext = HEAP8[((textIndex+2)|0)]; + if (nextNext == 104) { + textIndex++; + argSize = 1; // char (actually i32 in varargs) + } else { + argSize = 2; // short (actually i32 in varargs) + } + break; + case 'l': + var nextNext = HEAP8[((textIndex+2)|0)]; + if (nextNext == 108) { + textIndex++; + argSize = 8; // long long + } else { + argSize = 4; // long + } + break; + case 'L': // long long + case 'q': // int64_t + case 'j': // intmax_t + argSize = 8; + break; + case 'z': // size_t + case 't': // ptrdiff_t + case 'I': // signed ptrdiff_t or unsigned size_t + argSize = 4; + break; + default: + argSize = null; + } + if (argSize) textIndex++; + next = HEAP8[((textIndex+1)|0)]; + + // Handle type specifier. + switch (String.fromCharCode(next)) { + case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': case 'p': { + // Integer. + var signed = next == 100 || next == 105; + argSize = argSize || 4; + var currArg = getNextArg('i' + (argSize * 8)); + var origArg = currArg; + var argText; + // Flatten i64-1 [low, high] into a (slightly rounded) double + if (argSize == 8) { + currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == 117); + } + // Truncate to requested size. + if (argSize <= 4) { + var limit = Math.pow(256, argSize) - 1; + currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8); + } + // Format the number. + var currAbsArg = Math.abs(currArg); + var prefix = ''; + if (next == 100 || next == 105) { + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else + argText = reSign(currArg, 8 * argSize, 1).toString(10); + } else if (next == 117) { + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else + argText = unSign(currArg, 8 * argSize, 1).toString(10); + currArg = Math.abs(currArg); + } else if (next == 111) { + argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8); + } else if (next == 120 || next == 88) { + prefix = (flagAlternative && currArg != 0) ? '0x' : ''; + if (argSize == 8 && i64Math) { + if (origArg[1]) { + argText = (origArg[1]>>>0).toString(16); + var lower = (origArg[0]>>>0).toString(16); + while (lower.length < 8) lower = '0' + lower; + argText += lower; + } else { + argText = (origArg[0]>>>0).toString(16); + } + } else + if (currArg < 0) { + // Represent negative numbers in hex as 2's complement. + currArg = -currArg; + argText = (currAbsArg - 1).toString(16); + var buffer = []; + for (var i = 0; i < argText.length; i++) { + buffer.push((0xF - parseInt(argText[i], 16)).toString(16)); + } + argText = buffer.join(''); + while (argText.length < argSize * 2) argText = 'f' + argText; + } else { + argText = currAbsArg.toString(16); + } + if (next == 88) { + prefix = prefix.toUpperCase(); + argText = argText.toUpperCase(); + } + } else if (next == 112) { + if (currAbsArg === 0) { + argText = '(nil)'; + } else { + prefix = '0x'; + argText = currAbsArg.toString(16); + } + } + if (precisionSet) { + while (argText.length < precision) { + argText = '0' + argText; + } + } + + // Add sign if needed + if (currArg >= 0) { + if (flagAlwaysSigned) { + prefix = '+' + prefix; + } else if (flagPadSign) { + prefix = ' ' + prefix; + } + } + + // Move sign to prefix so we zero-pad after the sign + if (argText.charAt(0) == '-') { + prefix = '-' + prefix; + argText = argText.substr(1); + } + + // Add padding. + while (prefix.length + argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad) { + argText = '0' + argText; + } else { + prefix = ' ' + prefix; + } + } + } + + // Insert the result into the buffer. + argText = prefix + argText; + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; + } + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': { + // Float. + var currArg = getNextArg('double'); + var argText; + if (isNaN(currArg)) { + argText = 'nan'; + flagZeroPad = false; + } else if (!isFinite(currArg)) { + argText = (currArg < 0 ? '-' : '') + 'inf'; + flagZeroPad = false; + } else { + var isGeneral = false; + var effectivePrecision = Math.min(precision, 20); + + // Convert g/G to f/F or e/E, as per: + // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html + if (next == 103 || next == 71) { + isGeneral = true; + precision = precision || 1; + var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10); + if (precision > exponent && exponent >= -4) { + next = ((next == 103) ? 'f' : 'F').charCodeAt(0); + precision -= exponent + 1; + } else { + next = ((next == 103) ? 'e' : 'E').charCodeAt(0); + precision--; + } + effectivePrecision = Math.min(precision, 20); + } + + if (next == 101 || next == 69) { + argText = currArg.toExponential(effectivePrecision); + // Make sure the exponent has at least 2 digits. + if (/[eE][-+]\d$/.test(argText)) { + argText = argText.slice(0, -1) + '0' + argText.slice(-1); + } + } else if (next == 102 || next == 70) { + argText = currArg.toFixed(effectivePrecision); + if (currArg === 0 && __reallyNegative(currArg)) { + argText = '-' + argText; + } + } + + var parts = argText.split('e'); + if (isGeneral && !flagAlternative) { + // Discard trailing zeros and periods. + while (parts[0].length > 1 && parts[0].indexOf('.') != -1 && + (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) { + parts[0] = parts[0].slice(0, -1); + } + } else { + // Make sure we have a period in alternative mode. + if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.'; + // Zero pad until required precision. + while (precision > effectivePrecision++) parts[0] += '0'; + } + argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : ''); + + // Capitalize 'E' if needed. + if (next == 69) argText = argText.toUpperCase(); + + // Add sign. + if (currArg >= 0) { + if (flagAlwaysSigned) { + argText = '+' + argText; + } else if (flagPadSign) { + argText = ' ' + argText; + } + } + } + + // Add padding. + while (argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) { + argText = argText[0] + '0' + argText.slice(1); + } else { + argText = (flagZeroPad ? '0' : ' ') + argText; + } + } + } + + // Adjust case. + if (next < 97) argText = argText.toUpperCase(); + + // Insert the result into the buffer. + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; + } + case 's': { + // String. + var arg = getNextArg('i8*'); + var argLength = arg ? _strlen(arg) : '(null)'.length; + if (precisionSet) argLength = Math.min(argLength, precision); + if (!flagLeftAlign) { + while (argLength < width--) { + ret.push(32); + } + } + if (arg) { + for (var i = 0; i < argLength; i++) { + ret.push(HEAPU8[((arg++)|0)]); + } + } else { + ret = ret.concat(intArrayFromString('(null)'.substr(0, argLength), true)); + } + if (flagLeftAlign) { + while (argLength < width--) { + ret.push(32); + } + } + break; + } + case 'c': { + // Character. + if (flagLeftAlign) ret.push(getNextArg('i8')); + while (--width > 0) { + ret.push(32); + } + if (!flagLeftAlign) ret.push(getNextArg('i8')); + break; + } + case 'n': { + // Write the length written so far to the next parameter. + var ptr = getNextArg('i32*'); + HEAP32[((ptr)>>2)]=ret.length; + break; + } + case '%': { + // Literal percent sign. + ret.push(curr); + break; + } + default: { + // Unknown specifiers remain untouched. + for (var i = startTextIndex; i < textIndex + 2; i++) { + ret.push(HEAP8[(i)]); + } + } + } + textIndex += 2; + // TODO: Support a/A (hex float) and m (last error) specifiers. + // TODO: Support %1${specifier} for arg selection. + } else { + ret.push(curr); + textIndex += 1; + } + } + return ret; + } + + function _malloc(bytes) { + /* Over-allocate to make sure it is byte-aligned by 8. + * This will leak memory, but this is only the dummy + * implementation (replaced by dlmalloc normally) so + * not an issue. + */ + var ptr = Runtime.dynamicAlloc(bytes + 8); + return (ptr+8) & 0xFFFFFFF8; + } + Module["_malloc"] = _malloc;function _snprintf(s, n, format, varargs) { + // int snprintf(char *restrict s, size_t n, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var result = __formatString(format, varargs); + var limit = (n === undefined) ? result.length + : Math.min(result.length, Math.max(n - 1, 0)); + if (s < 0) { + s = -s; + var buf = _malloc(limit+1); + HEAP32[((s)>>2)]=buf; + s = buf; + } + for (var i = 0; i < limit; i++) { + HEAP8[(((s)+(i))|0)]=result[i]; + } + if (limit < n || (n === undefined)) HEAP8[(((s)+(i))|0)]=0; + return result.length; + } + + + Module["_memset"] = _memset; + + + Module["_strcat"] = _strcat; + + + function _strerror_r(errnum, strerrbuf, buflen) { + if (errnum in ERRNO_MESSAGES) { + if (ERRNO_MESSAGES[errnum].length > buflen - 1) { + return ___setErrNo(ERRNO_CODES.ERANGE); + } else { + var msg = ERRNO_MESSAGES[errnum]; + writeAsciiToMemory(msg, strerrbuf); + return 0; + } + } else { + return ___setErrNo(ERRNO_CODES.EINVAL); + } + }function _strerror(errnum) { + if (!_strerror.buffer) _strerror.buffer = _malloc(256); + _strerror_r(errnum, _strerror.buffer, 256); + return _strerror.buffer; + } + + + Module["_bitshift64Shl"] = _bitshift64Shl; + + function _abort() { + Module['abort'](); + } + + + + + + + function _mkport() { throw 'TODO' }var SOCKFS={mount:function (mount) { + return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + },createSocket:function (family, type, protocol) { + var streaming = type == 1; + if (protocol) { + assert(streaming == (protocol == 6)); // if SOCK_STREAM, must be tcp + } + + // create our internal socket structure + var sock = { + family: family, + type: type, + protocol: protocol, + server: null, + peers: {}, + pending: [], + recv_queue: [], + sock_ops: SOCKFS.websocket_sock_ops + }; + + // create the filesystem node to store the socket structure + var name = SOCKFS.nextname(); + var node = FS.createNode(SOCKFS.root, name, 49152, 0); + node.sock = sock; + + // and the wrapping stream that enables library functions such + // as read and write to indirectly interact with the socket + var stream = FS.createStream({ + path: name, + node: node, + flags: FS.modeStringToFlags('r+'), + seekable: false, + stream_ops: SOCKFS.stream_ops + }); + + // map the new stream to the socket structure (sockets have a 1:1 + // relationship with a stream) + sock.stream = stream; + + return sock; + },getSocket:function (fd) { + var stream = FS.getStream(fd); + if (!stream || !FS.isSocket(stream.node.mode)) { + return null; + } + return stream.node.sock; + },stream_ops:{poll:function (stream) { + var sock = stream.node.sock; + return sock.sock_ops.poll(sock); + },ioctl:function (stream, request, varargs) { + var sock = stream.node.sock; + return sock.sock_ops.ioctl(sock, request, varargs); + },read:function (stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + var msg = sock.sock_ops.recvmsg(sock, length); + if (!msg) { + // socket is closed + return 0; + } + buffer.set(msg.buffer, offset); + return msg.buffer.length; + },write:function (stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + return sock.sock_ops.sendmsg(sock, buffer, offset, length); + },close:function (stream) { + var sock = stream.node.sock; + sock.sock_ops.close(sock); + }},nextname:function () { + if (!SOCKFS.nextname.current) { + SOCKFS.nextname.current = 0; + } + return 'socket[' + (SOCKFS.nextname.current++) + ']'; + },websocket_sock_ops:{createPeer:function (sock, addr, port) { + var ws; + + if (typeof addr === 'object') { + ws = addr; + addr = null; + port = null; + } + + if (ws) { + // for sockets that've already connected (e.g. we're the server) + // we can inspect the _socket property for the address + if (ws._socket) { + addr = ws._socket.remoteAddress; + port = ws._socket.remotePort; + } + // if we're just now initializing a connection to the remote, + // inspect the url property + else { + var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url); + if (!result) { + throw new Error('WebSocket URL must be in the format ws(s)://address:port'); + } + addr = result[1]; + port = parseInt(result[2], 10); + } + } else { + // create the actual websocket object and connect + try { + // runtimeConfig gets set to true if WebSocket runtime configuration is available. + var runtimeConfig = (Module['websocket'] && ('object' === typeof Module['websocket'])); + + // The default value is 'ws://' the replace is needed because the compiler replaces "//" comments with '#' + // comments without checking context, so we'd end up with ws:#, the replace swaps the "#" for "//" again. + var url = 'ws:#'.replace('#', '//'); + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['url']) { + url = Module['websocket']['url']; // Fetch runtime WebSocket URL config. + } + } + + if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it. + url = url + addr + ':' + port; + } + + // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set. + var subProtocols = 'binary'; // The default value is 'binary' + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['subprotocol']) { + subProtocols = Module['websocket']['subprotocol']; // Fetch runtime WebSocket subprotocol config. + } + } + + // The regex trims the string (removes spaces at the beginning and end, then splits the string by + // , into an Array. Whitespace removal is important for Websockify and ws. + subProtocols = subProtocols.replace(/^ +| +$/g,"").split(/ *, */); + + // The node ws library API for specifying optional subprotocol is slightly different than the browser's. + var opts = ENVIRONMENT_IS_NODE ? {'protocol': subProtocols.toString()} : subProtocols; + + // If node we use the ws library. + var WebSocket = ENVIRONMENT_IS_NODE ? require('ws') : window['WebSocket']; + ws = new WebSocket(url, opts); + ws.binaryType = 'arraybuffer'; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EHOSTUNREACH); + } + } + + + var peer = { + addr: addr, + port: port, + socket: ws, + dgram_send_queue: [] + }; + + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer); + + // if this is a bound dgram socket, send the port number first to allow + // us to override the ephemeral port reported to us by remotePort on the + // remote end. + if (sock.type === 2 && typeof sock.sport !== 'undefined') { + peer.dgram_send_queue.push(new Uint8Array([ + 255, 255, 255, 255, + 'p'.charCodeAt(0), 'o'.charCodeAt(0), 'r'.charCodeAt(0), 't'.charCodeAt(0), + ((sock.sport & 0xff00) >> 8) , (sock.sport & 0xff) + ])); + } + + return peer; + },getPeer:function (sock, addr, port) { + return sock.peers[addr + ':' + port]; + },addPeer:function (sock, peer) { + sock.peers[peer.addr + ':' + peer.port] = peer; + },removePeer:function (sock, peer) { + delete sock.peers[peer.addr + ':' + peer.port]; + },handlePeerEvents:function (sock, peer) { + var first = true; + + var handleOpen = function () { + try { + var queued = peer.dgram_send_queue.shift(); + while (queued) { + peer.socket.send(queued); + queued = peer.dgram_send_queue.shift(); + } + } catch (e) { + // not much we can do here in the way of proper error handling as we've already + // lied and said this data was sent. shut it down. + peer.socket.close(); + } + }; + + function handleMessage(data) { + assert(typeof data !== 'string' && data.byteLength !== undefined); // must receive an ArrayBuffer + data = new Uint8Array(data); // make a typed array view on the array buffer + + + // if this is the port message, override the peer's port with it + var wasfirst = first; + first = false; + if (wasfirst && + data.length === 10 && + data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 && + data[4] === 'p'.charCodeAt(0) && data[5] === 'o'.charCodeAt(0) && data[6] === 'r'.charCodeAt(0) && data[7] === 't'.charCodeAt(0)) { + // update the peer's port and it's key in the peer map + var newport = ((data[8] << 8) | data[9]); + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + peer.port = newport; + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + return; + } + + sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data }); + }; + + if (ENVIRONMENT_IS_NODE) { + peer.socket.on('open', handleOpen); + peer.socket.on('message', function(data, flags) { + if (!flags.binary) { + return; + } + handleMessage((new Uint8Array(data)).buffer); // copy from node Buffer -> ArrayBuffer + }); + peer.socket.on('error', function() { + // don't throw + }); + } else { + peer.socket.onopen = handleOpen; + peer.socket.onmessage = function peer_socket_onmessage(event) { + handleMessage(event.data); + }; + } + },poll:function (sock) { + if (sock.type === 1 && sock.server) { + // listen sockets should only say they're available for reading + // if there are pending clients. + return sock.pending.length ? (64 | 1) : 0; + } + + var mask = 0; + var dest = sock.type === 1 ? // we only care about the socket state for connection-based sockets + SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) : + null; + + if (sock.recv_queue.length || + !dest || // connection-less sockets are always ready to read + (dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { // let recv return 0 once closed + mask |= (64 | 1); + } + + if (!dest || // connection-less sockets are always ready to write + (dest && dest.socket.readyState === dest.socket.OPEN)) { + mask |= 4; + } + + if ((dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { + mask |= 16; + } + + return mask; + },ioctl:function (sock, request, arg) { + switch (request) { + case 21531: + var bytes = 0; + if (sock.recv_queue.length) { + bytes = sock.recv_queue[0].data.length; + } + HEAP32[((arg)>>2)]=bytes; + return 0; + default: + return ERRNO_CODES.EINVAL; + } + },close:function (sock) { + // if we've spawned a listen server, close it + if (sock.server) { + try { + sock.server.close(); + } catch (e) { + } + sock.server = null; + } + // close any peer connections + var peers = Object.keys(sock.peers); + for (var i = 0; i < peers.length; i++) { + var peer = sock.peers[peers[i]]; + try { + peer.socket.close(); + } catch (e) { + } + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + } + return 0; + },bind:function (sock, addr, port) { + if (typeof sock.saddr !== 'undefined' || typeof sock.sport !== 'undefined') { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); // already bound + } + sock.saddr = addr; + sock.sport = port || _mkport(); + // in order to emulate dgram sockets, we need to launch a listen server when + // binding on a connection-less socket + // note: this is only required on the server side + if (sock.type === 2) { + // close the existing server if it exists + if (sock.server) { + sock.server.close(); + sock.server = null; + } + // swallow error operation not supported error that occurs when binding in the + // browser where this isn't supported + try { + sock.sock_ops.listen(sock, 0); + } catch (e) { + if (!(e instanceof FS.ErrnoError)) throw e; + if (e.errno !== ERRNO_CODES.EOPNOTSUPP) throw e; + } + } + },connect:function (sock, addr, port) { + if (sock.server) { + throw new FS.ErrnoError(ERRNO_CODS.EOPNOTSUPP); + } + + // TODO autobind + // if (!sock.addr && sock.type == 2) { + // } + + // early out if we're already connected / in the middle of connecting + if (typeof sock.daddr !== 'undefined' && typeof sock.dport !== 'undefined') { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + if (dest) { + if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(ERRNO_CODES.EALREADY); + } else { + throw new FS.ErrnoError(ERRNO_CODES.EISCONN); + } + } + } + + // add the socket to our peer list and set our + // destination address / port to match + var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + sock.daddr = peer.addr; + sock.dport = peer.port; + + // always "fail" in non-blocking mode + throw new FS.ErrnoError(ERRNO_CODES.EINPROGRESS); + },listen:function (sock, backlog) { + if (!ENVIRONMENT_IS_NODE) { + throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP); + } + if (sock.server) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); // already listening + } + var WebSocketServer = require('ws').Server; + var host = sock.saddr; + sock.server = new WebSocketServer({ + host: host, + port: sock.sport + // TODO support backlog + }); + + sock.server.on('connection', function(ws) { + if (sock.type === 1) { + var newsock = SOCKFS.createSocket(sock.family, sock.type, sock.protocol); + + // create a peer on the new socket + var peer = SOCKFS.websocket_sock_ops.createPeer(newsock, ws); + newsock.daddr = peer.addr; + newsock.dport = peer.port; + + // push to queue for accept to pick up + sock.pending.push(newsock); + } else { + // create a peer on the listen socket so calling sendto + // with the listen socket and an address will resolve + // to the correct client + SOCKFS.websocket_sock_ops.createPeer(sock, ws); + } + }); + sock.server.on('closed', function() { + sock.server = null; + }); + sock.server.on('error', function() { + // don't throw + }); + },accept:function (listensock) { + if (!listensock.server) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var newsock = listensock.pending.shift(); + newsock.stream.flags = listensock.stream.flags; + return newsock; + },getname:function (sock, peer) { + var addr, port; + if (peer) { + if (sock.daddr === undefined || sock.dport === undefined) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + addr = sock.daddr; + port = sock.dport; + } else { + // TODO saddr and sport will be set for bind()'d UDP sockets, but what + // should we be returning for TCP sockets that've been connect()'d? + addr = sock.saddr || 0; + port = sock.sport || 0; + } + return { addr: addr, port: port }; + },sendmsg:function (sock, buffer, offset, length, addr, port) { + if (sock.type === 2) { + // connection-less sockets will honor the message address, + // and otherwise fall back to the bound destination address + if (addr === undefined || port === undefined) { + addr = sock.daddr; + port = sock.dport; + } + // if there was no address to fall back to, error out + if (addr === undefined || port === undefined) { + throw new FS.ErrnoError(ERRNO_CODES.EDESTADDRREQ); + } + } else { + // connection-based sockets will only use the bound + addr = sock.daddr; + port = sock.dport; + } + + // find the peer for the destination address + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port); + + // early out if not connected with a connection-based socket + if (sock.type === 1) { + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } else if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } + + // create a copy of the incoming data to send, as the WebSocket API + // doesn't work entirely with an ArrayBufferView, it'll just send + // the entire underlying buffer + var data; + if (buffer instanceof Array || buffer instanceof ArrayBuffer) { + data = buffer.slice(offset, offset + length); + } else { // ArrayBufferView + data = buffer.buffer.slice(buffer.byteOffset + offset, buffer.byteOffset + offset + length); + } + + // if we're emulating a connection-less dgram socket and don't have + // a cached connection, queue the buffer to send upon connect and + // lie, saying the data was sent now. + if (sock.type === 2) { + if (!dest || dest.socket.readyState !== dest.socket.OPEN) { + // if we're not connected, open a new connection + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + } + dest.dgram_send_queue.push(data); + return length; + } + } + + try { + // send the actual data + dest.socket.send(data); + return length; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + },recvmsg:function (sock, length) { + // http://pubs.opengroup.org/onlinepubs/7908799/xns/recvmsg.html + if (sock.type === 1 && sock.server) { + // tcp servers should not be recv()'ing on the listen socket + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + + var queued = sock.recv_queue.shift(); + if (!queued) { + if (sock.type === 1) { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + + if (!dest) { + // if we have a destination address but are not connected, error out + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + else if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + // return null if the socket has closed + return null; + } + else { + // else, our socket is in a valid state but truly has nothing available + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } else { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } + + // queued.data will be an ArrayBuffer if it's unadulterated, but if it's + // requeued TCP data it'll be an ArrayBufferView + var queuedLength = queued.data.byteLength || queued.data.length; + var queuedOffset = queued.data.byteOffset || 0; + var queuedBuffer = queued.data.buffer || queued.data; + var bytesRead = Math.min(length, queuedLength); + var res = { + buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead), + addr: queued.addr, + port: queued.port + }; + + + // push back any unread data for TCP connections + if (sock.type === 1 && bytesRead < queuedLength) { + var bytesRemaining = queuedLength - bytesRead; + queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining); + sock.recv_queue.unshift(queued); + } + + return res; + }}};function _send(fd, buf, len, flags) { + var sock = SOCKFS.getSocket(fd); + if (!sock) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + // TODO honor flags + return _write(fd, buf, len); + } + + function _pwrite(fildes, buf, nbyte, offset) { + // ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + var slab = HEAP8; + return FS.write(stream, slab, buf, nbyte, offset); + } catch (e) { + FS.handleFSError(e); + return -1; + } + }function _write(fildes, buf, nbyte) { + // ssize_t write(int fildes, const void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + + + try { + var slab = HEAP8; + return FS.write(stream, slab, buf, nbyte); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + function _fileno(stream) { + // int fileno(FILE *stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fileno.html + stream = FS.getStreamFromPtr(stream); + if (!stream) return -1; + return stream.fd; + }function _fwrite(ptr, size, nitems, stream) { + // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fwrite.html + var bytesToWrite = nitems * size; + if (bytesToWrite == 0) return 0; + var fd = _fileno(stream); + var bytesWritten = _write(fd, ptr, bytesToWrite); + if (bytesWritten == -1) { + var streamObj = FS.getStreamFromPtr(stream); + if (streamObj) streamObj.error = true; + return 0; + } else { + return Math.floor(bytesWritten / size); + } + }function _fprintf(stream, format, varargs) { + // int fprintf(FILE *restrict stream, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var result = __formatString(format, varargs); + var stack = Runtime.stackSave(); + var ret = _fwrite(allocate(result, 'i8', ALLOC_STACK), 1, result.length, stream); + Runtime.stackRestore(stack); + return ret; + } + + function _toupper(chr) { + if (chr >= 97 && chr <= 122) { + return chr - 97 + 65; + } else { + return chr; + } + } + + function _printf(format, varargs) { + // int printf(const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var stdout = HEAP32[((_stdout)>>2)]; + return _fprintf(stdout, format, varargs); + } + + function _isdigit(chr) { + return chr >= 48 && chr <= 57; + } + + function _close(fildes) { + // int close(int fildes); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/close.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + FS.close(stream); + return 0; + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + var _tan=Math_tan; + + + + Module["_strncpy"] = _strncpy; + + var _asin=Math_asin; + + + Module["_i64Add"] = _i64Add; + + var _fabs=Math_abs; + + function _open(path, oflag, varargs) { + // int open(const char *path, int oflag, ...); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html + var mode = HEAP32[((varargs)>>2)]; + path = Pointer_stringify(path); + try { + var stream = FS.open(path, oflag, mode); + return stream.fd; + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + + function _copysign(a, b) { + return __reallyNegative(a) === __reallyNegative(b) ? a : -a; + }var _copysignl=_copysign; + + var _sqrt=Math_sqrt; + + + var Browser={mainLoop:{scheduler:null,method:"",shouldPause:false,paused:false,queue:[],pause:function () { + Browser.mainLoop.shouldPause = true; + },resume:function () { + if (Browser.mainLoop.paused) { + Browser.mainLoop.paused = false; + Browser.mainLoop.scheduler(); + } + Browser.mainLoop.shouldPause = false; + },updateStatus:function () { + if (Module['setStatus']) { + var message = Module['statusMessage'] || 'Please wait...'; + var remaining = Browser.mainLoop.remainingBlockers; + var expected = Browser.mainLoop.expectedBlockers; + if (remaining) { + if (remaining < expected) { + Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')'); + } else { + Module['setStatus'](message); + } + } else { + Module['setStatus'](''); + } + } + }},isFullScreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function () { + if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers + + if (Browser.initted || ENVIRONMENT_IS_WORKER) return; + Browser.initted = true; + + try { + new Blob(); + Browser.hasBlobConstructor = true; + } catch(e) { + Browser.hasBlobConstructor = false; + console.log("warning: no blob constructor, cannot create blobs with mimetypes"); + } + Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null)); + Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined; + if (!Module.noImageDecoding && typeof Browser.URLObject === 'undefined') { + console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."); + Module.noImageDecoding = true; + } + + // Support for plugins that can process preloaded files. You can add more of these to + // your app by creating and appending to Module.preloadPlugins. + // + // Each plugin is asked if it can handle a file based on the file's name. If it can, + // it is given the file's raw data. When it is done, it calls a callback with the file's + // (possibly modified) data. For example, a plugin might decompress a file, or it + // might create some side data structure for use later (like an Image element, etc.). + + var imagePlugin = {}; + imagePlugin['canHandle'] = function imagePlugin_canHandle(name) { + return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name); + }; + imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) { + var b = null; + if (Browser.hasBlobConstructor) { + try { + b = new Blob([byteArray], { type: Browser.getMimetype(name) }); + if (b.size !== byteArray.length) { // Safari bug #118630 + // Safari's Blob can only take an ArrayBuffer + b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) }); + } + } catch(e) { + Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder'); + } + } + if (!b) { + var bb = new Browser.BlobBuilder(); + bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range + b = bb.getBlob(); + } + var url = Browser.URLObject.createObjectURL(b); + var img = new Image(); + img.onload = function img_onload() { + assert(img.complete, 'Image ' + name + ' could not be decoded'); + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + Module["preloadedImages"][name] = canvas; + Browser.URLObject.revokeObjectURL(url); + if (onload) onload(byteArray); + }; + img.onerror = function img_onerror(event) { + console.log('Image ' + url + ' could not be decoded'); + if (onerror) onerror(); + }; + img.src = url; + }; + Module['preloadPlugins'].push(imagePlugin); + + var audioPlugin = {}; + audioPlugin['canHandle'] = function audioPlugin_canHandle(name) { + return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; + }; + audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) { + var done = false; + function finish(audio) { + if (done) return; + done = true; + Module["preloadedAudios"][name] = audio; + if (onload) onload(byteArray); + } + function fail() { + if (done) return; + done = true; + Module["preloadedAudios"][name] = new Audio(); // empty shim + if (onerror) onerror(); + } + if (Browser.hasBlobConstructor) { + try { + var b = new Blob([byteArray], { type: Browser.getMimetype(name) }); + } catch(e) { + return fail(); + } + var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! + var audio = new Audio(); + audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926 + audio.onerror = function audio_onerror(event) { + if (done) return; + console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach'); + function encode64(data) { + var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + var PAD = '='; + var ret = ''; + var leftchar = 0; + var leftbits = 0; + for (var i = 0; i < data.length; i++) { + leftchar = (leftchar << 8) | data[i]; + leftbits += 8; + while (leftbits >= 6) { + var curr = (leftchar >> (leftbits-6)) & 0x3f; + leftbits -= 6; + ret += BASE[curr]; + } + } + if (leftbits == 2) { + ret += BASE[(leftchar&3) << 4]; + ret += PAD + PAD; + } else if (leftbits == 4) { + ret += BASE[(leftchar&0xf) << 2]; + ret += PAD; + } + return ret; + } + audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray); + finish(audio); // we don't wait for confirmation this worked - but it's worth trying + }; + audio.src = url; + // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror + Browser.safeSetTimeout(function() { + finish(audio); // try to use it even though it is not necessarily ready to play + }, 10000); + } else { + return fail(); + } + }; + Module['preloadPlugins'].push(audioPlugin); + + // Canvas event setup + + var canvas = Module['canvas']; + + // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module + // Module['forcedAspectRatio'] = 4 / 3; + + canvas.requestPointerLock = canvas['requestPointerLock'] || + canvas['mozRequestPointerLock'] || + canvas['webkitRequestPointerLock'] || + canvas['msRequestPointerLock'] || + function(){}; + canvas.exitPointerLock = document['exitPointerLock'] || + document['mozExitPointerLock'] || + document['webkitExitPointerLock'] || + document['msExitPointerLock'] || + function(){}; // no-op if function does not exist + canvas.exitPointerLock = canvas.exitPointerLock.bind(document); + + function pointerLockChange() { + Browser.pointerLock = document['pointerLockElement'] === canvas || + document['mozPointerLockElement'] === canvas || + document['webkitPointerLockElement'] === canvas || + document['msPointerLockElement'] === canvas; + } + + document.addEventListener('pointerlockchange', pointerLockChange, false); + document.addEventListener('mozpointerlockchange', pointerLockChange, false); + document.addEventListener('webkitpointerlockchange', pointerLockChange, false); + document.addEventListener('mspointerlockchange', pointerLockChange, false); + + if (Module['elementPointerLock']) { + canvas.addEventListener("click", function(ev) { + if (!Browser.pointerLock && canvas.requestPointerLock) { + canvas.requestPointerLock(); + ev.preventDefault(); + } + }, false); + } + },createContext:function (canvas, useWebGL, setInModule, webGLContextAttributes) { + var ctx; + var errorInfo = '?'; + function onContextCreationError(event) { + errorInfo = event.statusMessage || errorInfo; + } + try { + if (useWebGL) { + var contextAttributes = { + antialias: false, + alpha: false + }; + + if (webGLContextAttributes) { + for (var attribute in webGLContextAttributes) { + contextAttributes[attribute] = webGLContextAttributes[attribute]; + } + } + + + canvas.addEventListener('webglcontextcreationerror', onContextCreationError, false); + try { + ['experimental-webgl', 'webgl'].some(function(webglId) { + return ctx = canvas.getContext(webglId, contextAttributes); + }); + } finally { + canvas.removeEventListener('webglcontextcreationerror', onContextCreationError, false); + } + } else { + ctx = canvas.getContext('2d'); + } + if (!ctx) throw ':('; + } catch (e) { + Module.print('Could not create canvas: ' + [errorInfo, e]); + return null; + } + if (useWebGL) { + // Set the background of the WebGL canvas to black + canvas.style.backgroundColor = "black"; + + // Warn on context loss + canvas.addEventListener('webglcontextlost', function(event) { + alert('WebGL context lost. You will need to reload the page.'); + }, false); + } + if (setInModule) { + GLctx = Module.ctx = ctx; + Module.useWebGL = useWebGL; + Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); + Browser.init(); + } + return ctx; + },destroyContext:function (canvas, useWebGL, setInModule) {},fullScreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullScreen:function (lockPointer, resizeCanvas) { + Browser.lockPointer = lockPointer; + Browser.resizeCanvas = resizeCanvas; + if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true; + if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false; + + var canvas = Module['canvas']; + function fullScreenChange() { + Browser.isFullScreen = false; + var canvasContainer = canvas.parentNode; + if ((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement'] || + document['msFullScreenElement'] || document['msFullscreenElement'] || + document['webkitCurrentFullScreenElement']) === canvasContainer) { + canvas.cancelFullScreen = document['cancelFullScreen'] || + document['mozCancelFullScreen'] || + document['webkitCancelFullScreen'] || + document['msExitFullscreen'] || + document['exitFullscreen'] || + function() {}; + canvas.cancelFullScreen = canvas.cancelFullScreen.bind(document); + if (Browser.lockPointer) canvas.requestPointerLock(); + Browser.isFullScreen = true; + if (Browser.resizeCanvas) Browser.setFullScreenCanvasSize(); + } else { + + // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen + canvasContainer.parentNode.insertBefore(canvas, canvasContainer); + canvasContainer.parentNode.removeChild(canvasContainer); + + if (Browser.resizeCanvas) Browser.setWindowedCanvasSize(); + } + if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullScreen); + Browser.updateCanvasDimensions(canvas); + } + + if (!Browser.fullScreenHandlersInstalled) { + Browser.fullScreenHandlersInstalled = true; + document.addEventListener('fullscreenchange', fullScreenChange, false); + document.addEventListener('mozfullscreenchange', fullScreenChange, false); + document.addEventListener('webkitfullscreenchange', fullScreenChange, false); + document.addEventListener('MSFullscreenChange', fullScreenChange, false); + } + + // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root + var canvasContainer = document.createElement("div"); + canvas.parentNode.insertBefore(canvasContainer, canvas); + canvasContainer.appendChild(canvas); + + // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size) + canvasContainer.requestFullScreen = canvasContainer['requestFullScreen'] || + canvasContainer['mozRequestFullScreen'] || + canvasContainer['msRequestFullscreen'] || + (canvasContainer['webkitRequestFullScreen'] ? function() { canvasContainer['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null); + canvasContainer.requestFullScreen(); + },requestAnimationFrame:function requestAnimationFrame(func) { + if (typeof window === 'undefined') { // Provide fallback to setTimeout if window is undefined (e.g. in Node.js) + setTimeout(func, 1000/60); + } else { + if (!window.requestAnimationFrame) { + window.requestAnimationFrame = window['requestAnimationFrame'] || + window['mozRequestAnimationFrame'] || + window['webkitRequestAnimationFrame'] || + window['msRequestAnimationFrame'] || + window['oRequestAnimationFrame'] || + window['setTimeout']; + } + window.requestAnimationFrame(func); + } + },safeCallback:function (func) { + return function() { + if (!ABORT) return func.apply(null, arguments); + }; + },safeRequestAnimationFrame:function (func) { + return Browser.requestAnimationFrame(function() { + if (!ABORT) func(); + }); + },safeSetTimeout:function (func, timeout) { + return setTimeout(function() { + if (!ABORT) func(); + }, timeout); + },safeSetInterval:function (func, timeout) { + return setInterval(function() { + if (!ABORT) func(); + }, timeout); + },getMimetype:function (name) { + return { + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'png': 'image/png', + 'bmp': 'image/bmp', + 'ogg': 'audio/ogg', + 'wav': 'audio/wav', + 'mp3': 'audio/mpeg' + }[name.substr(name.lastIndexOf('.')+1)]; + },getUserMedia:function (func) { + if(!window.getUserMedia) { + window.getUserMedia = navigator['getUserMedia'] || + navigator['mozGetUserMedia']; + } + window.getUserMedia(func); + },getMovementX:function (event) { + return event['movementX'] || + event['mozMovementX'] || + event['webkitMovementX'] || + 0; + },getMovementY:function (event) { + return event['movementY'] || + event['mozMovementY'] || + event['webkitMovementY'] || + 0; + },getMouseWheelDelta:function (event) { + return Math.max(-1, Math.min(1, event.type === 'DOMMouseScroll' ? event.detail : -event.wheelDelta)); + },mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function (event) { // event should be mousemove, mousedown or mouseup + if (Browser.pointerLock) { + // When the pointer is locked, calculate the coordinates + // based on the movement of the mouse. + // Workaround for Firefox bug 764498 + if (event.type != 'mousemove' && + ('mozMovementX' in event)) { + Browser.mouseMovementX = Browser.mouseMovementY = 0; + } else { + Browser.mouseMovementX = Browser.getMovementX(event); + Browser.mouseMovementY = Browser.getMovementY(event); + } + + // check if SDL is available + if (typeof SDL != "undefined") { + Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; + Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; + } else { + // just add the mouse delta to the current absolut mouse position + // FIXME: ideally this should be clamped against the canvas size and zero + Browser.mouseX += Browser.mouseMovementX; + Browser.mouseY += Browser.mouseMovementY; + } + } else { + // Otherwise, calculate the movement based on the changes + // in the coordinates. + var rect = Module["canvas"].getBoundingClientRect(); + var cw = Module["canvas"].width; + var ch = Module["canvas"].height; + + // Neither .scrollX or .pageXOffset are defined in a spec, but + // we prefer .scrollX because it is currently in a spec draft. + // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/) + var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset); + var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset); + + if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') { + var touch = event.touch; + if (touch === undefined) { + return; // the "touch" property is only defined in SDL + + } + var adjustedX = touch.pageX - (scrollX + rect.left); + var adjustedY = touch.pageY - (scrollY + rect.top); + + adjustedX = adjustedX * (cw / rect.width); + adjustedY = adjustedY * (ch / rect.height); + + var coords = { x: adjustedX, y: adjustedY }; + + if (event.type === 'touchstart') { + Browser.lastTouches[touch.identifier] = coords; + Browser.touches[touch.identifier] = coords; + } else if (event.type === 'touchend' || event.type === 'touchmove') { + Browser.lastTouches[touch.identifier] = Browser.touches[touch.identifier]; + Browser.touches[touch.identifier] = { x: adjustedX, y: adjustedY }; + } + return; + } + + var x = event.pageX - (scrollX + rect.left); + var y = event.pageY - (scrollY + rect.top); + + // the canvas might be CSS-scaled compared to its backbuffer; + // SDL-using content will want mouse coordinates in terms + // of backbuffer units. + x = x * (cw / rect.width); + y = y * (ch / rect.height); + + Browser.mouseMovementX = x - Browser.mouseX; + Browser.mouseMovementY = y - Browser.mouseY; + Browser.mouseX = x; + Browser.mouseY = y; + } + },xhrLoad:function (url, onload, onerror) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = function xhr_onload() { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + } else { + onerror(); + } + }; + xhr.onerror = onerror; + xhr.send(null); + },asyncLoad:function (url, onload, onerror, noRunDep) { + Browser.xhrLoad(url, function(arrayBuffer) { + assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).'); + onload(new Uint8Array(arrayBuffer)); + if (!noRunDep) removeRunDependency('al ' + url); + }, function(event) { + if (onerror) { + onerror(); + } else { + throw 'Loading data file "' + url + '" failed.'; + } + }); + if (!noRunDep) addRunDependency('al ' + url); + },resizeListeners:[],updateResizeListeners:function () { + var canvas = Module['canvas']; + Browser.resizeListeners.forEach(function(listener) { + listener(canvas.width, canvas.height); + }); + },setCanvasSize:function (width, height, noUpdates) { + var canvas = Module['canvas']; + Browser.updateCanvasDimensions(canvas, width, height); + if (!noUpdates) Browser.updateResizeListeners(); + },windowedWidth:0,windowedHeight:0,setFullScreenCanvasSize:function () { + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags | 0x00800000; // set SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },setWindowedCanvasSize:function () { + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },updateCanvasDimensions:function (canvas, wNative, hNative) { + if (wNative && hNative) { + canvas.widthNative = wNative; + canvas.heightNative = hNative; + } else { + wNative = canvas.widthNative; + hNative = canvas.heightNative; + } + var w = wNative; + var h = hNative; + if (Module['forcedAspectRatio'] && Module['forcedAspectRatio'] > 0) { + if (w/h < Module['forcedAspectRatio']) { + w = Math.round(h * Module['forcedAspectRatio']); + } else { + h = Math.round(w / Module['forcedAspectRatio']); + } + } + if (((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement'] || + document['msFullScreenElement'] || document['msFullscreenElement'] || + document['webkitCurrentFullScreenElement']) === canvas.parentNode) && (typeof screen != 'undefined')) { + var factor = Math.min(screen.width / w, screen.height / h); + w = Math.round(w * factor); + h = Math.round(h * factor); + } + if (Browser.resizeCanvas) { + if (canvas.width != w) canvas.width = w; + if (canvas.height != h) canvas.height = h; + if (typeof canvas.style != 'undefined') { + canvas.style.removeProperty( "width"); + canvas.style.removeProperty("height"); + } + } else { + if (canvas.width != wNative) canvas.width = wNative; + if (canvas.height != hNative) canvas.height = hNative; + if (typeof canvas.style != 'undefined') { + if (w != wNative || h != hNative) { + canvas.style.setProperty( "width", w + "px", "important"); + canvas.style.setProperty("height", h + "px", "important"); + } else { + canvas.style.removeProperty( "width"); + canvas.style.removeProperty("height"); + } + } + } + }}; + + function _sprintf(s, format, varargs) { + // int sprintf(char *restrict s, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + return _snprintf(s, undefined, format, varargs); + } + + + function __exit(status) { + // void _exit(int status); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html + Module['exit'](status); + }function _exit(status) { + __exit(status); + } + + function _isspace(chr) { + return (chr == 32) || (chr >= 9 && chr <= 13); + } + + + function _fmod(x, y) { + return x % y; + }var _fmodl=_fmod; + + function _sysconf(name) { + // long sysconf(int name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/sysconf.html + switch(name) { + case 30: return PAGE_SIZE; + case 132: + case 133: + case 12: + case 137: + case 138: + case 15: + case 235: + case 16: + case 17: + case 18: + case 19: + case 20: + case 149: + case 13: + case 10: + case 236: + case 153: + case 9: + case 21: + case 22: + case 159: + case 154: + case 14: + case 77: + case 78: + case 139: + case 80: + case 81: + case 79: + case 82: + case 68: + case 67: + case 164: + case 11: + case 29: + case 47: + case 48: + case 95: + case 52: + case 51: + case 46: + return 200809; + case 27: + case 246: + case 127: + case 128: + case 23: + case 24: + case 160: + case 161: + case 181: + case 182: + case 242: + case 183: + case 184: + case 243: + case 244: + case 245: + case 165: + case 178: + case 179: + case 49: + case 50: + case 168: + case 169: + case 175: + case 170: + case 171: + case 172: + case 97: + case 76: + case 32: + case 173: + case 35: + return -1; + case 176: + case 177: + case 7: + case 155: + case 8: + case 157: + case 125: + case 126: + case 92: + case 93: + case 129: + case 130: + case 131: + case 94: + case 91: + return 1; + case 74: + case 60: + case 69: + case 70: + case 4: + return 1024; + case 31: + case 42: + case 72: + return 32; + case 87: + case 26: + case 33: + return 2147483647; + case 34: + case 1: + return 47839; + case 38: + case 36: + return 99; + case 43: + case 37: + return 2048; + case 0: return 2097152; + case 3: return 65536; + case 28: return 32768; + case 44: return 32767; + case 75: return 16384; + case 39: return 1000; + case 89: return 700; + case 71: return 256; + case 40: return 255; + case 2: return 100; + case 180: return 64; + case 25: return 20; + case 5: return 16; + case 6: return 6; + case 73: return 4; + case 84: return 1; + } + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + + + Module["_tolower"] = _tolower; + + var _atan=Math_atan; + + + function _recv(fd, buf, len, flags) { + var sock = SOCKFS.getSocket(fd); + if (!sock) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + // TODO honor flags + return _read(fd, buf, len); + } + + function _pread(fildes, buf, nbyte, offset) { + // ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + var slab = HEAP8; + return FS.read(stream, slab, buf, nbyte, offset); + } catch (e) { + FS.handleFSError(e); + return -1; + } + }function _read(fildes, buf, nbyte) { + // ssize_t read(int fildes, void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + + + try { + var slab = HEAP8; + return FS.read(stream, slab, buf, nbyte); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + function _time(ptr) { + var ret = Math.floor(Date.now()/1000); + if (ptr) { + HEAP32[((ptr)>>2)]=ret; + } + return ret; + } + + + + + + + var _environ=allocate(1, "i32*", ALLOC_STATIC);var ___environ=_environ;function ___buildEnvironment(env) { + // WARNING: Arbitrary limit! + var MAX_ENV_VALUES = 64; + var TOTAL_ENV_SIZE = 1024; + + // Statically allocate memory for the environment. + var poolPtr; + var envPtr; + if (!___buildEnvironment.called) { + ___buildEnvironment.called = true; + // Set default values. Use string keys for Closure Compiler compatibility. + ENV['USER'] = 'root'; + ENV['PATH'] = '/'; + ENV['PWD'] = '/'; + ENV['HOME'] = '/home/emscripten'; + ENV['LANG'] = 'en_US.UTF-8'; + ENV['_'] = './this.program'; + // Allocate memory. + poolPtr = allocate(TOTAL_ENV_SIZE, 'i8', ALLOC_STATIC); + envPtr = allocate(MAX_ENV_VALUES * 4, + 'i8*', ALLOC_STATIC); + HEAP32[((envPtr)>>2)]=poolPtr; + HEAP32[((_environ)>>2)]=envPtr; + } else { + envPtr = HEAP32[((_environ)>>2)]; + poolPtr = HEAP32[((envPtr)>>2)]; + } + + // Collect key=value lines. + var strings = []; + var totalSize = 0; + for (var key in env) { + if (typeof env[key] === 'string') { + var line = key + '=' + env[key]; + strings.push(line); + totalSize += line.length; + } + } + if (totalSize > TOTAL_ENV_SIZE) { + throw new Error('Environment size exceeded TOTAL_ENV_SIZE!'); + } + + // Make new. + var ptrSize = 4; + for (var i = 0; i < strings.length; i++) { + var line = strings[i]; + writeAsciiToMemory(line, poolPtr); + HEAP32[(((envPtr)+(i * ptrSize))>>2)]=poolPtr; + poolPtr += line.length + 1; + } + HEAP32[(((envPtr)+(strings.length * ptrSize))>>2)]=0; + }var ENV={};function _getenv(name) { + // char *getenv(const char *name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html + if (name === 0) return 0; + name = Pointer_stringify(name); + if (!ENV.hasOwnProperty(name)) return 0; + + if (_getenv.ret) _free(_getenv.ret); + _getenv.ret = allocate(intArrayFromString(ENV[name]), 'i8', ALLOC_NORMAL); + return _getenv.ret; + } + + + function _emscripten_memcpy_big(dest, src, num) { + HEAPU8.set(HEAPU8.subarray(src, src+num), dest); + return dest; + } + Module["_memcpy"] = _memcpy; + + var _log=Math_log; + + var _cos=Math_cos; + + var _llvm_pow_f64=Math_pow; + + function _sbrk(bytes) { + // Implement a Linux-like 'memory area' for our 'process'. + // Changes the size of the memory area by |bytes|; returns the + // address of the previous top ('break') of the memory area + // We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP + var self = _sbrk; + if (!self.called) { + DYNAMICTOP = alignMemoryPage(DYNAMICTOP); // make sure we start out aligned + self.called = true; + assert(Runtime.dynamicAlloc); + self.alloc = Runtime.dynamicAlloc; + Runtime.dynamicAlloc = function() { abort('cannot dynamically allocate, sbrk now has control') }; + } + var ret = DYNAMICTOP; + if (bytes != 0) self.alloc(bytes); + return ret; // Previous break location. + } + + function ___errno_location() { + return ___errno_state; + } + + var _BItoD=true; + + var _sin=Math_sin; + + var _atan2=Math_atan2; + + + Module["_strcpy"] = _strcpy; + + function _llvm_bswap_i32(x) { + return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24); + } + + + + function _islower(chr) { + return chr >= 97 && chr <= 122; + } + + var _exp=Math_exp; + + var _acos=Math_acos; + + function _isupper(chr) { + return chr >= 65 && chr <= 90; + } + +FS.staticInit();__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });__ATEXIT__.push({ func: function() { FS.quit() } });Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice; +___errno_state = Runtime.staticAlloc(4); HEAP32[((___errno_state)>>2)]=0; +__ATINIT__.unshift({ func: function() { TTY.init() } });__ATEXIT__.push({ func: function() { TTY.shutdown() } });TTY.utf8 = new Runtime.UTF8Processor(); +if (ENVIRONMENT_IS_NODE) { var fs = require("fs"); NODEFS.staticInit(); } +__ATINIT__.push({ func: function() { SOCKFS.root = FS.mount(SOCKFS, {}, null); } }); +Module["requestFullScreen"] = function Module_requestFullScreen(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) }; + Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) }; + Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) }; + Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() }; + Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() }; + Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() } +___buildEnvironment(ENV); +STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP); + +staticSealed = true; // seal the static portion of memory + +STACK_MAX = STACK_BASE + 5242880; + +DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX); + +assert(DYNAMIC_BASE < TOTAL_MEMORY, "TOTAL_MEMORY not big enough for stack"); + + var ctlz_i8 = allocate([8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], "i8", ALLOC_DYNAMIC); + var cttz_i8 = allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0], "i8", ALLOC_DYNAMIC); + +var Math_min = Math.min; +function invoke_iiii(index,a1,a2,a3) { + try { + return Module["dynCall_iiii"](index,a1,a2,a3); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_iddiii(index,a1,a2,a3,a4,a5) { + try { + return Module["dynCall_iddiii"](index,a1,a2,a3,a4,a5); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_vii(index,a1,a2) { + try { + Module["dynCall_vii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_iii(index,a1,a2) { + try { + return Module["dynCall_iii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function asmPrintInt(x, y) { + Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack); +} +function asmPrintFloat(x, y) { + Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack); +} +// EMSCRIPTEN_START_ASM +var asm=(function(global,env,buffer){"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=env.cttz_i8|0;var n=env.ctlz_i8|0;var o=env._stderr|0;var p=0;var q=0;var r=0;var s=0;var t=+env.NaN,u=+env.Infinity;var v=0,w=0,x=0,y=0,z=0.0,A=0,B=0,C=0,D=0.0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=0;var M=0;var N=0;var O=global.Math.floor;var P=global.Math.abs;var Q=global.Math.sqrt;var R=global.Math.pow;var S=global.Math.cos;var T=global.Math.sin;var U=global.Math.tan;var V=global.Math.acos;var W=global.Math.asin;var X=global.Math.atan;var Y=global.Math.atan2;var Z=global.Math.exp;var _=global.Math.log;var $=global.Math.ceil;var aa=global.Math.imul;var ba=env.abort;var ca=env.assert;var da=env.asmPrintInt;var ea=env.asmPrintFloat;var fa=env.min;var ga=env.invoke_iiii;var ha=env.invoke_iddiii;var ia=env.invoke_vii;var ja=env.invoke_iii;var ka=env._fabs;var la=env._sin;var ma=env._exp;var na=env._llvm_pow_f64;var oa=env._acos;var pa=env._atan2;var qa=env._fmod;var ra=env._lseek;var sa=env.__reallyNegative;var ta=env._asin;var ua=env._atan;var va=env.___buildEnvironment;var wa=env._fflush;var xa=env._pwrite;var ya=env._strerror_r;var za=env._fprintf;var Aa=env._open;var Ba=env._fabsf;var Ca=env._sbrk;var Da=env._send;var Ea=env._snprintf;var Fa=env._llvm_bswap_i32;var Ga=env._emscripten_memcpy_big;var Ha=env._fileno;var Ia=env._sysconf;var Ja=env.___setErrNo;var Ka=env._cos;var La=env._pread;var Ma=env._printf;var Na=env._sprintf;var Oa=env._log;var Pa=env._toupper;var Qa=env._write;var Ra=env._isupper;var Sa=env.___errno_location;var Ta=env._recv;var Ua=env._tan;var Va=env._copysign;var Wa=env._getenv;var Xa=env._mkport;var Ya=env.__exit;var Za=env._read;var _a=env._abort;var $a=env._islower;var ab=env._fwrite;var bb=env._time;var cb=env._isdigit;var db=env._strerror;var eb=env.__formatString;var fb=env._isspace;var gb=env._sqrt;var hb=env._exit;var ib=env._close;var jb=0.0; +// EMSCRIPTEN_START_FUNCS +function ob(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+7&-8;return b|0}function pb(){return i|0}function qb(a){a=a|0;i=a}function rb(a,b){a=a|0;b=b|0;if((p|0)==0){p=a;q=b}}function sb(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0]}function tb(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0];a[k+4|0]=a[b+4|0];a[k+5|0]=a[b+5|0];a[k+6|0]=a[b+6|0];a[k+7|0]=a[b+7|0]}function ub(a){a=a|0;E=a}function vb(a){a=a|0;F=a}function wb(a){a=a|0;G=a}function xb(a){a=a|0;H=a}function yb(a){a=a|0;I=a}function zb(a){a=a|0;J=a}function Ab(a){a=a|0;K=a}function Bb(a){a=a|0;L=a}function Cb(a){a=a|0;M=a}function Db(a){a=a|0;N=a}function Eb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;if((d|0)>0){f=Ob(b,d)|0}else{f=Pb(b)|0}b=(f|0)==0;if(!b){Xb(f,hc(f)|0)}d=c[1086]|0;if((d|0)==0){c[1086]=10;g=gg(41040)|0;c[1088]=g;if((g|0)==0){h=-4;i=e;return h|0}else{j=10}}else{j=d}d=c[1090]|0;a:do{if((d|0)<(j|0)){k=d}else{g=j;l=c[1088]|0;while(1){m=g+10|0;c[1086]=m;n=jg(l,m*4104|0)|0;c[1088]=n;if((n|0)==0){h=-3;break}m=c[1086]|0;o=c[1090]|0;if((o|0)<(m|0)){k=o;break a}else{g=m;l=n}}i=e;return h|0}}while(0);if(b){h=-1;i=e;return h|0}c[(c[1088]|0)+(k*4104|0)>>2]=f;f=c[1088]|0;c[f+(k*4104|0)+4>>2]=0;a[f+((c[1090]|0)*4104|0)+8|0]=0;c[1090]=(c[1090]|0)+1;h=k;i=e;return h|0}function Fb(b,d,e){b=b|0;d=+d;e=+e;var f=0,g=0,h=0,j=0,k=0;f=i;g=c[1088]|0;h=c[g+(b*4104|0)>>2]|0;if((h|0)==0){j=0;i=f;return j|0}k=g+(b*4104|0)+8|0;a[k]=0;dc(h,d+-1.0,e+-1.0,k,4096)|0;j=k;i=f;return j|0}function Gb(b,d,e){b=b|0;d=+d;e=+e;var f=0,g=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+4144|0;g=f+16|0;j=f+40|0;l=f+8|0;m=f;if((b|0)>0&(c[1086]|0)>(b|0)){n=(c[1088]|0)+(b*4104|0)|0}else{n=0}b=c[n>>2]|0;if((b|0)==0){o=0;i=f;return o|0}cc(b,d,e,l,m,f+32|0);e=+h[m>>3]+1.0;h[k>>3]=+h[l>>3]+1.0;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];l=g+8|0;h[k>>3]=e;c[l>>2]=c[k>>2];c[l+4>>2]=c[k+4>>2];Ea(j|0,4095,8,g|0)|0;g=n+8|0;n=a[j]|0;a:do{if(!(n<<24>>24==0)){l=j;m=n;while(1){b=l+1|0;if((fb(m<<24>>24|0)|0)==0){break}m=a[b]|0;if(m<<24>>24==0){break a}else{l=b}}m=a[l]|0;if(!(m<<24>>24==0)){b=g;p=l;q=m;while(1){m=p+1|0;r=b+1|0;a[b]=q;s=a[m]|0;if(s<<24>>24==0){break}else{b=r;p=m;q=s}}a[r]=0;if((r|0)==(g|0)){o=g;i=f;return o|0}q=r;p=r-g|0;while(1){b=q+ -1|0;if((fb(a[b]|0)|0)==0){o=g;t=14;break}a[b]=0;l=p+ -1|0;if((l|0)==0){o=g;t=14;break}else{q=b;p=l}}if((t|0)==14){i=f;return o|0}}}}while(0);a[g]=0;o=g;i=f;return o|0}function Hb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;if((b|0)>0&(c[1086]|0)>(b|0)){f=(c[1088]|0)+(b*4104|0)|0}else{f=0}b=c[f>>2]|0;if((b|0)==0){g=0;i=e;return g|0}h=f+8|0;a[h]=0;do{if((d|0)!=0?(a[d]|0)!=0:0){if(((xg(d,24)|0)!=0?(xg(d,40)|0)!=0:0)?(xg(d,56)|0)!=0:0){if(!(+oc(d)>0.0)){break}j=c[f>>2]|0}else{j=b}Xb(j,d)}}while(0);Hg(h|0,fc(c[f>>2]|0)|0,4096)|0;if((xg(h,24)|0)==0){k=h+0|0;l=24|0;m=k+9|0;do{a[k]=a[l]|0;k=k+1|0;l=l+1|0}while((k|0)<(m|0));g=h;i=e;return g|0}if((xg(h,40)|0)==0){k=h+0|0;l=40|0;m=k+9|0;do{a[k]=a[l]|0;k=k+1|0;l=l+1|0}while((k|0)<(m|0));g=h;i=e;return g|0}l=a[h]|0;if(l<<24>>24==0){g=h;i=e;return g|0}else{n=h;o=l}while(1){if(($a(o<<24>>24|0)|0)!=0){a[n]=Pa(a[n]|0)|0}l=n+1|0;k=a[l]|0;if(k<<24>>24==0){g=h;break}else{n=l;o=k}}i=e;return g|0}function Ib(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;if((b|0)>0&(c[1086]|0)>(b|0)){f=(c[1088]|0)+(b*4104|0)|0}else{f=0}b=c[f>>2]|0;if((b|0)==0){g=0;i=e;return g|0}h=f+8|0;a[h]=0;do{if((d|0)!=0?(a[d]|0)!=0:0){if((xg(d,64)|0)==0){gc(b,1)|0;c[f+4>>2]=1;break}else{gc(b,0)|0;c[f+4>>2]=0;break}}}while(0);b=c[f+4>>2]|0;if((b|0)==1){Hg(h|0,64,4095)|0}else if((b|0)==0){Hg(h|0,72,4095)|0}b=a[h]|0;if(b<<24>>24==0){g=h;i=e;return g|0}else{j=h;k=b}while(1){if((Ra(k<<24>>24|0)|0)!=0){a[j]=Jg(a[j]|0)|0}b=j+1|0;f=a[b]|0;if(f<<24>>24==0){g=h;break}else{j=b;k=f}}i=e;return g|0}function Jb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0.0,C=0.0,D=0,E=0.0,F=0.0,G=0,H=0,I=0.0,J=0.0,K=0.0;e=i;i=i+12352|0;f=e+32|0;g=e+56|0;j=e+4152|0;l=e+8248|0;m=e+48|0;n=e+52|0;o=e+24|0;p=e;q=e+8|0;r=e+16|0;if((b|0)>0&(c[1086]|0)>(b|0)){s=(c[1088]|0)+(b*4104|0)|0}else{s=0}c[m>>2]=0;c[n>>2]=0;if((c[s>>2]|0)==0){t=0;i=e;return t|0}u=Hb(b,0)|0;if(((yg(u,24)|0)!=0?(yg(u,40)|0)!=0:0)?(yg(u,56)|0)!=0:0){v=0}else{v=1}u=s+8|0;a[u]=0;b=cg(d)|0;d=fg(b,88)|0;if((d|0)!=0){w=s+4|0;x=(v|0)==0;v=d;do{d=$f(v,32)|0;if((d|0)==0){c[m>>2]=96;y=96;z=0}else{A=d+1|0;c[m>>2]=A;a[d]=0;y=A;z=v}B=+wg(y,n);if(B!=0.0?(C=+wg(c[n>>2]|0,m),C!=0.0):0){bc(c[s>>2]|0,B,C,o,p);A=(z|0)!=0;if(A){c[f>>2]=z;Ea(g|0,4096,104,f|0)|0;dg(u,g,4095)|0}d=c[w>>2]|0;if((d|0)==0){C=+h[o>>3];if(x){Tc(j,4095,C,3)}else{Uc(j,4095,C,3)}Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,128,f|0)|0;dg(u,g,4095)|0}else if((d|0)==1){C=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];d=f+8|0;h[k>>3]=C;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];Ea(g|0,4096,112,f|0)|0;dg(u,g,4095)|0}else{C=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];d=f+8|0;h[k>>3]=C;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];Ea(g|0,4096,112,f|0)|0;dg(u,g,4095)|0}d=(yg(z,136)|0)==0;C=+wg(c[m>>2]|0,n);D=C!=0.0;a:do{if(d){if(D){if(x){B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);G=c[w>>2]|0;if((G|0)==0){Tc(j,4095,+h[o>>3],3);Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,160,f|0)|0;dg(u,g,4095)|0}else if((G|0)==1){E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}else{E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}E=+wg(c[m>>2]|0,n);if(E!=0.0){B=E}else{F=E;break}}}else{B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);G=c[w>>2]|0;if((G|0)==1){E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];H=f+8|0;h[k>>3]=E;c[H>>2]=c[k>>2];c[H+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}else if((G|0)==0){Uc(j,4095,+h[o>>3],3);Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,160,f|0)|0;dg(u,g,4095)|0}else{E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}E=+wg(c[m>>2]|0,n);if(E!=0.0){B=E}else{F=E;break}}}}else{F=C}}else{if(D){B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}I=+wg(c[m>>2]|0,n);if(!(I!=0.0)){F=B;break a}J=+wg(c[n>>2]|0,m);if(!(J!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);bc(c[s>>2]|0,I,J,q,r);J=+ec(+h[o>>3],+h[p>>3],+h[q>>3],+h[r>>3])*3600.0;do{if(!(J<=60.0)){if(!(J<=3600.0)){h[k>>3]=J/3600.0;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,192,f|0)|0;dg(u,g,4095)|0;break}else{h[k>>3]=J/60.0;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,184,f|0)|0;dg(u,g,4095)|0;break}}else{h[k>>3]=J;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,176,f|0)|0;dg(u,g,4095)|0}}while(0);J=+wg(c[m>>2]|0,n);if(J!=0.0){B=J}else{F=J;break}}}else{F=C}}}while(0);if(!((yg(z,200)|0)!=0?(yg(z,208)|0)!=0:0)){if(F<0.0){C=F;while(1){B=C+6.283185307179586;if(B<0.0){C=B}else{K=B;break}}}else{K=F}h[k>>3]=K*57.29577951308232;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,216,f|0)|0;dg(u,g,4095)|0}if(A){Ea(g|0,4096,224,f|0)|0;dg(u,g,4095)|0}Ea(g|0,4096,88,f|0)|0;dg(u,g,4095)|0}v=fg(0,88)|0}while((v|0)!=0)}if((b|0)==0){t=u;i=e;return t|0}hg(b);t=u;i=e;return t|0}function Kb(a){a=a|0;var b=0,c=0.0;b=i;c=+af(a,0);i=b;return+c}function Lb(b,d,e,f,j,l,m){b=b|0;d=d|0;e=e|0;f=f|0;j=+j;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0;n=i;i=i+4128|0;o=n;p=n+20|0;q=n+16|0;r=n+24|0;bf(b,d,e,f,p,q,j,l,m);j=+g[q>>2];h[k>>3]=+g[p>>2];c[o>>2]=c[k>>2];c[o+4>>2]=c[k+4>>2];p=o+8|0;h[k>>3]=j;c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];Ea(r|0,4095,240,o|0)|0;o=a[r]|0;a:do{if(!(o<<24>>24==0)){p=r;q=o;while(1){m=p+1|0;if((fb(q<<24>>24|0)|0)==0){break}q=a[m]|0;if(q<<24>>24==0){break a}else{p=m}}q=a[p]|0;if(!(q<<24>>24==0)){m=248;l=p;f=q;while(1){q=l+1|0;s=m+1|0;a[m]=f;e=a[q]|0;if(e<<24>>24==0){break}else{m=s;l=q;f=e}}a[s]=0;if((s|0)==248){i=n;return 248}f=s;l=s-248|0;while(1){m=f+ -1|0;if((fb(a[m]|0)|0)==0){t=11;break}a[m]=0;p=l+ -1|0;if((p|0)==0){t=11;break}else{f=m;l=p}}if((t|0)==11){i=n;return 248}}}}while(0);a[248]=0;i=n;return 248}function Mb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0.0,ha=0.0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0.0,sa=0.0,ta=0.0,ua=0,va=0.0,wa=0,xa=0,ya=0.0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0.0,La=0.0,Ma=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0;e=i;i=i+1184|0;f=e+672|0;g=e+1176|0;j=e+1144|0;l=e+1112|0;m=e+1048|0;n=e+1040|0;p=e+1024|0;q=e+1032|0;r=e+1080|0;s=e+848|0;t=e;u=e+752|0;v=e+744|0;w=e+656|0;x=e+760|0;y=e+664|0;z=e+816|0;A=e+856|0;B=e+736|0;C=e+840|0;D=e+824|0;E=e+808|0;F=e+768|0;G=e+8|0;H=e+1088|0;I=e+868|0;J=e+864|0;K=e+872|0;L=e+880|0;M=e+960|0;N=e+1104|0;O=e+832|0;P=e+800|0;Q=e+728|0;R=ig(1,9336)|0;U=a[d]|0;d=U<<24>>24==32?0:U;a[N]=d;a[R+9324|0]=d;if((Oc(b,4424,N,63,M)|0)!=0){d=ig((Dg(M|0)|0)+2|0,1)|0;c[R+9320>>2]=d;Lg(d|0,M|0)|0}d=R+3984|0;c[d>>2]=0;c[R+3956>>2]=0;c[R+3924>>2]=0;c[R+3952>>2]=-1;U=R+3268|0;c[U>>2]=0;V=R+3272|0;c[V>>2]=0;h[D>>3]=0.0;h[E>>3]=0.0;W=F+8|0;X=F+16|0;Y=F+24|0;c[F+0>>2]=0;c[F+4>>2]=0;c[F+8>>2]=0;c[F+12>>2]=0;c[F+16>>2]=0;c[F+20>>2]=0;c[F+24>>2]=0;c[F+28>>2]=0;h[G>>3]=0.0;Z=R+3300|0;c[Z>>2]=0;_=R+48|0;h[_>>3]=0.0;c[K>>2]=0;Dc(b,4432,N,K)|0;$=c[K>>2]|0;if(($|0)==0){Ec(b,4432,K)|0;ba=c[K>>2]|0;if((ba|0)==0){Ec(b,4440,K)|0;ca=c[K>>2]|0;if((ca|0)==0){Ec(b,4448,K)|0;da=c[K>>2]|0}else{da=ca}}else{da=ba}}else{da=$}if((da|0)<1){_b(4456);Tb(R);ea=0;i=e;return ea|0}if((da|0)>2){c[K>>2]=2;fa=2}else{fa=da}da=R+3316|0;c[da>>2]=fa;$=R+3320|0;c[$>>2]=fa;c[R+3960>>2]=fa;fa=R+136|0;h[fa>>3]=0.0;Lc(b,4504,fa)|0;ga=+h[fa>>3];if(ga<1.0){Lc(b,4512,fa)|0;ha=+h[fa>>3]}else{ha=ga}if(ha<1.0){_b(4520);Tb(R);ea=0;i=e;return ea|0}ba=R+144|0;h[ba>>3]=0.0;Lc(b,4560,ba)|0;if(+h[ba>>3]<1.0){Lc(b,4568,ba)|0}ca=c[K>>2]|0;if((ca|0)>1){if(+h[ba>>3]<1.0){_b(4576);Tb(R);ea=0;i=e;return ea|0}else{ia=19}}else{if((ca|0)>0){ia=19}else{ja=0}}if((ia|0)==19){ca=c[o>>2]|0;ka=0;la=0;while(1){a[H+0|0]=a[4440|0]|0;a[H+1|0]=a[4441|0]|0;a[H+2|0]=a[4442|0]|0;a[H+3|0]=a[4443|0]|0;a[H+4|0]=a[4444|0]|0;a[H+5|0]=a[4445|0]|0;ma=ka+1|0;c[f>>2]=ma;Na(L|0,4616,f|0)|0;Fg(H|0,L|0)|0;do{if((Ec(b,H,J)|0)==0){if((ka|0)==0){ha=+h[fa>>3];if(ha>1.0){c[J>>2]=~~ha;break}}else if((ka|0)==1?(ha=+h[ba>>3],ha>1.0):0){c[J>>2]=~~ha;break}c[f>>2]=H;za(ca|0,4624,f|0)|0}}while(0);a[H+0|0]=a[4664|0]|0;a[H+1|0]=a[4665|0]|0;a[H+2|0]=a[4666|0]|0;a[H+3|0]=a[4667|0]|0;a[H+4|0]=a[4668|0]|0;a[H+5|0]=a[4669|0]|0;Fg(H|0,L|0)|0;if((Pc(b,H,16,L)|0)!=0?(Qc(L,4672)|0)!=0:0){c[J>>2]=0}na=((c[J>>2]|0)>1)+la|0;if((ma|0)<(c[K>>2]|0)){ka=ma;la=na}else{ja=na;break}}}c[K>>2]=ja;c[$>>2]=ja;c[da>>2]=ja;Pc(b,4680,16,R+3336|0)|0;Ec(b,4696,R+3332|0)|0;ja=R+3324|0;c[ja>>2]=kc()|0;$=R+9328|0;c[$>>2]=0;Ec(b,4712,$)|0;$=R+832|0;Eg($|0,0,648)|0;Eg(G|0,0,648)|0;la=c[K>>2]|0;ka=(la|0)>0;if(ka){ca=0;do{h[$+((aa(la,ca)|0)+ca<<3)>>3]=1.0;ca=ca+1|0}while((ca|0)<(la|0));if(ka){ca=0;do{h[G+((aa(la,ca)|0)+ca<<3)>>3]=1.0;ca=ca+1|0}while((ca|0)<(la|0));ca=R+760|0;oa=ca+0|0;pa=oa+72|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));if(ka){ka=0;while(1){h[ca+(ka<<3)>>3]=1.0;na=ka+1|0;if((na|0)<(la|0)){ka=na}else{qa=ca;break}}}else{qa=ca}}else{ia=37}}else{ia=37}if((ia|0)==37){ca=R+760|0;oa=ca+0|0;pa=oa+72|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));qa=ca}do{if((Oc(b,4720,N,63,M)|0)==0){c[R+9312>>2]=0}else{ca=Nb(b,M)|0;a[g]=ca;if(!(ca<<24>>24==95)){ca=Mb(b,g)|0;c[R+9312>>2]=ca;if((ca|0)!=0){c[ca+9316>>2]=R;break}}else{ca=c[o>>2]|0;c[f>>2]=M;za(ca|0,4368,f|0)|0;c[R+9312>>2]=0}_b(4728);Tb(R);ea=0;i=e;return ea|0}}while(0);M=R+3224|0;g=R+3232|0;c[M+0>>2]=0;c[M+4>>2]=0;c[M+8>>2]=0;c[M+12>>2]=0;do{if((Kc(b,4776,N,M)|0)==0){if((Kc(b,4784,N,g)|0)!=0){h[M>>3]=+h[g>>3]*299792.5;break}if((Lc(b,4792,M)|0)!=0){h[g>>3]=+h[M>>3]/299792.5}}else{h[g>>3]=+h[M>>3]/299792.5}}while(0);M=R+4096|0;oa=M+0|0;pa=oa+80|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));do{if((Oc(b,4808,N,16,j)|0)==0){g=a[N]|0;if(!(g<<24>>24==32|g<<24>>24==0)){c[f>>2]=g<<24>>24;Na(L|0,5368,f|0)|0;_b(L);Tb(R);ea=0;i=e;return ea|0}if((Cc(b,5408)|0)!=0){c[R+3260>>2]=29;g=Cc(b,5408)|0;Lc(g,5408,s)|0;Lc(g,5416,t)|0;Lc(g,5424,u)|0;h[R+152>>3]=(+h[s>>3]+ +h[t>>3]/60.0+ +h[u>>3]/3600.0)*15.0*3.141592653589793/180.0;a[r]=43;Pc(g,5432,1,r)|0;ha=(a[r]|0)==45?-1.0:1.0;Lc(g,5448,v)|0;Lc(g,5456,w)|0;Lc(g,5464,x)|0;h[R+160>>3]=ha*(+h[v>>3]+ +h[w>>3]/60.0+ +h[x>>3]/3600.0)*3.141592653589793/180.0;g=R+120|0;Lc(b,5472,g)|0;Ec(b,5472,I)|0;ca=R+3764|0;ka=(c[I>>2]|0)==1950?3427142:3492678;a[ca]=ka;a[ca+1|0]=ka>>8;a[ca+2|0]=ka>>16;a[ca+3|0]=ka>>24;ka=R+128|0;h[ka>>3]=+h[g>>3];Lc(b,5344,ka)|0;ha=+h[t>>3];ga=+h[u>>3];ka=a[r]|0;ra=+h[v>>3];sa=+h[w>>3];ta=+h[x>>3];h[k>>3]=+h[s>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];g=f+8|0;h[k>>3]=ha;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];g=f+16|0;h[k>>3]=ga;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];c[f+24>>2]=ka;ka=f+28|0;h[k>>3]=ra;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];ka=f+36|0;h[k>>3]=sa;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];ka=f+44|0;h[k>>3]=ta;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];c[f+52>>2]=ca;Na(R+3892|0,5496,f|0)|0;Lc(b,5544,R+168|0)|0;Lc(b,5560,R+192|0)|0;Lc(b,5576,R+200|0)|0;Lc(b,5592,R+176|0)|0;Lc(b,5600,R+184|0)|0;ca=Cc(b,5608)|0;ka=R+208|0;c[f>>2]=1;Na(H|0,5616,f|0)|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=2;Na(H|0,5616,f|0)|0;ka=R+216|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=3;Na(H|0,5616,f|0)|0;ka=R+224|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=4;Na(H|0,5616,f|0)|0;ka=R+232|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=5;Na(H|0,5616,f|0)|0;ka=R+240|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=6;Na(H|0,5616,f|0)|0;ka=R+248|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;ka=Cc(b,5624)|0;ca=R+256|0;g=0;while(1){la=g+1|0;c[f>>2]=la;Na(H|0,5632,f|0)|0;na=ca+(g<<3)|0;h[na>>3]=0.0;Lc(ka,H,na)|0;if((la|0)==20){break}else{g=la}}g=Cc(b,5640)|0;ka=R+416|0;ca=0;while(1){ma=ca+1|0;c[f>>2]=ma;Na(H|0,5648,f|0)|0;la=ka+(ca<<3)|0;h[la>>3]=0.0;Lc(g,H,la)|0;if((ma|0)==20){break}else{ca=ma}}ca=R+3312|0;c[ca>>2]=1;g=R+3449|0;a[g+0|0]=a[5656|0]|0;a[g+1|0]=a[5657|0]|0;a[g+2|0]=a[5658|0]|0;g=R+3458|0;a[g]=4408644;a[g+1|0]=17221;a[g+2|0]=67;a[g+3|0]=0;g=R+3467|0;a[g]=5460804;a[g+1|0]=21331;a[g+2|0]=83;a[g+3|0]=0;c[R+3292>>2]=0;c[R+3288>>2]=3;oa=R+3368|0;g=5664|0;pa=oa+9|0;do{a[oa]=a[g]|0;oa=oa+1|0;g=g+1|0}while((oa|0)<(pa|0));oa=R+3377|0;g=5680|0;pa=oa+9|0;do{a[oa]=a[g]|0;oa=oa+1|0;g=g+1|0}while((oa|0)<(pa|0));ta=+h[fa>>3]*.5;g=R+616|0;h[g>>3]=ta;sa=+h[ba>>3]*.5;ka=R+624|0;h[ka>>3]=sa;h[R+16>>3]=ta;h[R+24>>3]=sa;nd(ta,sa,R,z,B)|0;sa=+h[z>>3];h[R+688>>3]=sa;ta=+h[B>>3];h[R+696>>3]=ta;h[R>>3]=sa;h[R+8>>3]=ta;nd(+h[g>>3],+h[ka>>3]+1.0,R,A,C)|0;ta=+h[C>>3]- +h[B>>3];h[R+40>>3]=ta;h[R+32>>3]=-ta;Sb(R);c[ca>>2]=1;ac(R);ta=+h[_>>3]*3.141592653589793/180.0;h[P>>3]=ta;sa=+h[g>>3]+ +S(+ta);nd(sa,+h[ka>>3]+ +T(+ta),R,A,C)|0;h[qa>>3]=-+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);ta=+h[P>>3];sa=+h[g>>3]+ +T(+ta);nd(sa,+h[ka>>3]+ +S(+ta),R,A,C)|0;ta=+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[R+768>>3]=ta;Wb(R,+h[qa>>3],ta,+h[_>>3]);ua=qa;break}if(((((Cc(b,5088)|0)==0?(Cc(b,5096)|0)==0:0)?(Cc(b,5112)|0)==0:0)?(Cc(b,5128)|0)==0:0)?(Cc(b,5144)|0)==0:0){_b(5824);Tb(R);ea=0;i=e;return ea|0}h[y>>3]=0.0;Lc(b,5088,y)|0;ta=+h[y>>3];if(ta==0.0){Lc(b,5096,y)|0;va=+h[y>>3]}else{va=ta}do{if(va==0.0){Lc(b,5144,y)|0;ta=+h[y>>3];if(ta!=0.0){h[D>>3]=-ta/3600.0;Lc(b,5152,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}Lc(b,5128,y)|0;ta=+h[y>>3];if(ta!=0.0){h[D>>3]=-ta/3600.0;Lc(b,5160,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}else{Lc(b,5112,y)|0;h[D>>3]=-+h[y>>3]/3600.0;Lc(b,5176,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}}else{ta=va/3600.0;h[E>>3]=ta;h[D>>3]=-ta}}while(0);h[P>>3]=0.0;Lc(b,5256,P)|0;if(+h[_>>3]==0.0){Lc(b,5248,P)|0}Wb(R,+h[D>>3],+h[E>>3],+h[P>>3]);ca=R+616|0;h[ca>>3]=+h[fa>>3]*.5+.5;ka=R+624|0;h[ka>>3]=+h[ba>>3]*.5+.5;if((Cc(b,4904)|0)!=0){Lc(b,4904,ca)|0;Lc(b,4912,ka)|0}h[R+16>>3]=+h[ca>>3];h[R+24>>3]=+h[ka>>3];ka=R+688|0;h[ka>>3]=-999.0;if((Hc(b,5656,ka)|0)==0){_b(5696);Tb(R);ea=0;i=e;return ea|0}ca=R+696|0;h[ca>>3]=-999.0;if((Ic(b,4832,ca)|0)==0){_b(5736);Tb(R);ea=0;i=e;return ea|0}ta=+h[ka>>3];h[R>>3]=ta;sa=+h[ca>>3];h[R+8>>3]=sa;ca=R+3304|0;c[ca>>2]=0;h[R+3992>>3]=ta;h[R+4e3>>3]=sa;ka=R+4008|0;h[ka>>3]=999.0;if((Lc(b,4936,ka)|0)==0){Lc(b,5776,ka)|0}ka=R+4016|0;h[ka>>3]=999.0;Lc(b,4944,ka)|0;do{if((Lc(b,5312,O)|0)==0){ka=R+128|0;if((Mc(b,5320,ka)|0)==0){if((Mc(b,5336,ka)|0)!=0){break}if((Lc(b,5344,ka)|0)!=0){break}h[ka>>3]=+h[R+120>>3];break}Pc(b,5320,32,m)|0;if(($f(m,84)|0)==0){if((Lc(b,5352,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744;break}if((Lc(b,5360,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744}}}else{h[R+128>>3]=(+h[O>>3]+-15019.81352)/365.242198781+1900.0}}while(0);Vb(R,5792,5808)|0;c[ca>>2]=0;a[f]=0;Rb(b,R,f);Sb(R);c[R+3292>>2]=0;c[R+3288>>2]=3;c[R+3312>>2]=1;ua=qa}else{Lg(l|0,j|0)|0;ka=(Oc(b,4816,N,16,l)|0)==0;Lg(R+3368|0,j|0)|0;Lg(R+3377|0,l|0)|0;if((Qc(l,4824)|0)==0){g=(Qc(l,4832)|0)==0;wa=g?1:2}else{wa=2}g=R+3386|0;a[g]=0;Oc(b,4840,N,9,g)|0;g=R+3395|0;a[g]=0;Oc(b,4848,N,9,g)|0;if((Vb(R,j,l)|0)!=0){Tb(R);ea=0;i=e;return ea|0}g=R+3260|0;if((c[g>>2]|0)==0){ma=R+3476|0;if((Oc(b,4856,N,16,ma)|0)==0?(Yc(b,4864,4872,16,ma)|0)==0:0){a[ma]=0}if((yg(ma,4880)|0)==0){c[g>>2]=-1}if(!ka){ka=R+3508|0;if((Oc(b,4888,N,16,ka)|0)==0?(Yc(b,4896,4872,16,ka)|0)==0:0){a[ka]=0}if((yg(ma,4880)|0)==0){c[g>>2]=-1}}}ma=R+616|0;h[ma>>3]=1.0;Kc(b,4904,N,ma)|0;ka=R+624|0;h[ka>>3]=1.0;Kc(b,4912,N,ka)|0;h[R+16>>3]=+h[ma>>3];h[R+24>>3]=+h[ka>>3];la=R+688|0;h[la>>3]=0.0;Kc(b,4920,N,la)|0;na=R+696|0;h[na>>3]=0.0;Kc(b,4928,N,na)|0;xa=c[R+3884>>2]|0;if((xa|0)==7){h[na>>3]=90.0- +h[na>>3];ia=74}else if((xa|0)==8){sa=+h[na>>3]+-90.0;h[na>>3]=sa;ya=sa}else{ia=74}if((ia|0)==74){ya=+h[na>>3]}sa=+h[la>>3];h[R>>3]=sa;h[R+8>>3]=ya;la=R+3992|0;if((c[R+3304>>2]|0)==0){h[la>>3]=sa;h[R+4e3>>3]=ya}else{h[la>>3]=ya;h[R+4e3>>3]=sa}la=R+3176|0;h[la>>3]=999.0;Kc(b,4936,N,la)|0;h[R+4008>>3]=+h[la>>3];la=R+3184|0;h[la>>3]=999.0;Kc(b,4944,N,la)|0;h[R+4016>>3]=+h[la>>3];c[R+3964>>2]=ma;c[R+3972>>2]=qa;c[R+3968>>2]=$;la=R+4088|0;h[la>>3]=0.0;Kc(b,4952,N,la)|0;c[f>>2]=0;Na(H|0,4960,f|0)|0;Kc(b,H,N,M)|0;c[f>>2]=1;Na(H|0,4960,f|0)|0;la=R+4104|0;Kc(b,H,N,la)|0;c[f>>2]=2;Na(H|0,4960,f|0)|0;na=R+4112|0;Kc(b,H,N,na)|0;c[f>>2]=3;Na(H|0,4960,f|0)|0;xa=R+4120|0;Kc(b,H,N,xa)|0;c[f>>2]=4;Na(H|0,4960,f|0)|0;Aa=R+4128|0;Kc(b,H,N,Aa)|0;c[f>>2]=5;Na(H|0,4960,f|0)|0;Ba=R+4136|0;Kc(b,H,N,Ba)|0;c[f>>2]=6;Na(H|0,4960,f|0)|0;Ca=R+4144|0;Kc(b,H,N,Ca)|0;c[f>>2]=7;Na(H|0,4960,f|0)|0;Da=R+4152|0;Kc(b,H,N,Da)|0;c[f>>2]=8;Na(H|0,4960,f|0)|0;Ea=R+4160|0;Kc(b,H,N,Ea)|0;c[f>>2]=9;Na(H|0,4960,f|0)|0;Fa=R+4168|0;Kc(b,H,N,Fa)|0;c[f>>2]=wa;Na(n|0,4968,f|0)|0;c[f>>2]=wa;Na(p|0,4976,f|0)|0;c[f>>2]=wa;Na(q|0,4984,f|0)|0;Ga=c[g>>2]|0;switch(Ga|0){case 7:{c[f>>2]=wa;c[f+4>>2]=0;Na(H|0,4992,f|0)|0;Kc(b,H,N,M)|0;c[f>>2]=wa;c[f+4>>2]=1;Na(H|0,4992,f|0)|0;Kc(b,H,N,la)|0;c[f>>2]=wa;c[f+4>>2]=2;Na(H|0,4992,f|0)|0;Kc(b,H,N,na)|0;c[f>>2]=wa;c[f+4>>2]=3;Na(H|0,4992,f|0)|0;Kc(b,H,N,xa)|0;c[f>>2]=wa;c[f+4>>2]=4;Na(H|0,4992,f|0)|0;Kc(b,H,N,Aa)|0;c[f>>2]=wa;c[f+4>>2]=5;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ba)|0;c[f>>2]=wa;c[f+4>>2]=6;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ca)|0;c[f>>2]=wa;c[f+4>>2]=7;Na(H|0,4992,f|0)|0;Kc(b,H,N,Da)|0;c[f>>2]=wa;c[f+4>>2]=8;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ea)|0;c[f>>2]=wa;c[f+4>>2]=9;Na(H|0,4992,f|0)|0;Kc(b,H,N,Fa)|0;ia=97;break};case 17:case 15:case 16:case 14:case 4:case 1:{Kc(b,n,N,R+4104|0)|0;Kc(b,p,N,R+4112|0)|0;ia=97;break};case 2:{Kc(b,n,N,R+4104|0)|0;Kc(b,p,N,R+4112|0)|0;Fa=R+4120|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=90.0}Kc(b,q,N,Fa)|0;ia=97;break};case 13:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,n,N,Fa)|0;ia=97;break};case 10:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,n,N,Fa)|0;Fa=R+4112|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,p,N,Fa)|0;ia=97;break};case 9:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=90.0}Kc(b,n,N,Fa)|0;ia=97;break};case 18:{Kc(b,n,N,R+4104|0)|0;ia=97;break};default:{Ha=Ga}}if((ia|0)==97){Ha=c[g>>2]|0}do{if((Ha|0)==31){if((dd(b,R)|0)==0){Ia=c[g>>2]|0;ia=102;break}else{a[R+3374|0]=65;a[R+3375|0]=78;a[R+3383|0]=65;a[R+3384|0]=78;c[g>>2]=3;break}}else{Ia=Ha;ia=102}}while(0);a:do{if((ia|0)==102){do{if((Ia|0)==32){if((kd(b,R)|0)==0){Ja=c[g>>2]|0;break}else{a[R+3375|0]=78;a[R+3384|0]=78;c[g>>2]=7;break a}}else{Ja=Ia}}while(0);if((Ja|0)==33){a[R+3374|0]=65;a[R+3375|0]=78;a[R+3383|0]=65;a[R+3384|0]=78;c[g>>2]=3}}}while(0);if((c[ja>>2]|0)>0){Rb(b,R,N)}Sb(R);Ye(R,b);c[U>>2]=0;c[V>>2]=0;ca=Kc(b,5e3,N,F)|0;Ga=Kc(b,5008,N,W)|0;Fa=Kc(b,5016,N,X)|0;Ea=Kc(b,5024,N,Y)|0;if((c[ja>>2]|0)!=2?(Da=Cc(b,5032)|0,(Da|0)!=0):0){c[g>>2]=30;Ca=R+3467|0;a[Ca+0|0]=a[5040|0]|0;a[Ca+1|0]=a[5041|0]|0;a[Ca+2|0]=a[5042|0]|0;a[Ca+3|0]=a[5043|0]|0;a[Ca+4|0]=a[5044|0]|0;a[Ca+5|0]=a[5045|0]|0;Ca=R+256|0;Ba=0;while(1){Aa=Ba+1|0;c[f>>2]=Aa;Na(H|0,5048,f|0)|0;xa=Ca+(Ba<<3)|0;h[xa>>3]=0.0;if((Lc(Da,H,xa)|0)!=0){c[U>>2]=Aa}if((Aa|0)==20){break}else{Ba=Aa}}Ba=Cc(b,5056)|0;Da=R+416|0;Ca=0;while(1){Aa=Ca+1|0;c[f>>2]=Aa;Na(H|0,5064,f|0)|0;xa=Da+(Ca<<3)|0;h[xa>>3]=0.0;if((Lc(Ba,H,xa)|0)!=0){c[V>>2]=Aa}if((Aa|0)==20){break}else{Ca=Aa}}bd(+h[ma>>3],+h[ka>>3],R,z,B)|0;bd(+h[ma>>3],+h[ka>>3]+1.0,R,A,C)|0;sa=+h[C>>3]- +h[B>>3];Ca=R+40|0;h[Ca>>3]=sa;Ba=R+32|0;h[Ba>>3]=-sa;c[R+3312>>2]=1;ac(R);h[P>>3]=+h[_>>3]*3.141592653589793/180.0;bd(+h[ma>>3],+h[ka>>3],R,z,B)|0;sa=+h[P>>3];ta=+h[ma>>3]+ +S(+sa);bd(ta,+h[ka>>3]+ +T(+sa),R,A,C)|0;sa=-+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[qa>>3]=sa;h[Ba>>3]=sa;sa=+h[P>>3];ta=+h[ma>>3]+ +T(+sa);bd(ta,+h[ka>>3]+ +S(+sa),R,A,C)|0;sa=+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[R+768>>3]=sa;h[Ca>>3]=sa;Ca=R+56|0;h[Ca>>3]=+h[F>>3];h[R+64>>3]=+h[W>>3];h[R+72>>3]=+h[X>>3];h[R+80>>3]=+h[Y>>3];Bd(2,Ca,R+88|0)|0}else{ia=121}do{if((ia|0)==121){if((Ga|ca|Fa|Ea|0)!=0){c[Z>>2]=1;Zb(R,F);break}if((Kc(b,5072,N,D)|0)==0){h[R+32>>3]=1.0;h[R+40>>3]=1.0;h[qa>>3]=1.0;h[R+768>>3]=1.0;h[_>>3]=0.0;c[Z>>2]=0;_b(5264);break}Kc(b,5080,N,E)|0;if(!(+h[D>>3]==0.0)){if(+h[ba>>3]>1.0){sa=+h[E>>3];if(sa==0.0){ia=127}else{Ka=sa}}else{ia=154}}else{ia=127}do{if((ia|0)==127){if(((((Cc(b,5088)|0)==0?(Cc(b,5096)|0)==0:0)?(Cc(b,5112)|0)==0:0)?(Cc(b,5128)|0)==0:0)?(Cc(b,5144)|0)==0:0){ia=154;break}h[y>>3]=0.0;Lc(b,5088,y)|0;sa=+h[y>>3];if(sa==0.0){Lc(b,5096,y)|0;La=+h[y>>3]}else{La=sa}if(!(La==0.0)){if(+h[D>>3]==0.0){h[D>>3]=-La/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}sa=La/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5144,y)|0;sa=+h[y>>3];if(sa!=0.0){if(+h[D>>3]==0.0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}Lc(b,5152,y)|0;sa=+h[y>>3]/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5128,y)|0;sa=+h[y>>3];if(sa!=0.0){if(+h[D>>3]==0.0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}Lc(b,5160,y)|0;sa=+h[y>>3]/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5112,y)|0;sa=+h[y>>3];if(sa!=0.0?+h[D>>3]==0.0:0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(sa==0.0){Lc(b,5176,y)|0;ta=+h[y>>3]/3600.0;h[E>>3]=ta;Ka=ta}else{Ka=sa}}}while(0);if((ia|0)==154){Ka=+h[E>>3]}if(Ka==0.0?+h[ba>>3]>1.0:0){h[E>>3]=-+h[D>>3]}h[R+776>>3]=1.0;h[R+784>>3]=1.0;Eg(G|0,0,648)|0;Eg($|0,0,648)|0;Ca=c[K>>2]|0;if((Ca|0)>0){Ba=0;do{h[G+((aa(Ca,Ba)|0)+Ba<<3)>>3]=1.0;Ba=Ba+1|0}while((Ba|0)<(Ca|0))}if((a[N]|0)==0?(Lc(b,5192,G)|0)!=0:0){Ca=c[K>>2]|0;if((Ca|0)>0){Ba=Ca;Ca=0;Da=0;while(1){c[J>>2]=0;Aa=Ca+1|0;if((Ba|0)>0){xa=0;na=Da;while(1){la=G+(na<<3)|0;h[la>>3]=(Ca|0)==(xa|0)?1.0:0.0;c[f>>2]=Aa;c[f+4>>2]=xa+1;Na(H|0,5208,f|0)|0;Ma=na+1|0;Lc(b,H,la)|0;la=(c[J>>2]|0)+1|0;c[J>>2]=la;Oa=c[K>>2]|0;if((la|0)<(Oa|0)){xa=la;na=Ma}else{Pa=Oa;Qa=Ma;break}}}else{Pa=Ba;Qa=Da}if((Aa|0)<(Pa|0)){Ba=Pa;Ca=Aa;Da=Qa}else{break}}}$b(R,+h[D>>3],+h[E>>3],G);break}if((Kc(b,5224,N,G)|0)==0){h[P>>3]=0.0;if((wa|0)==2){Kc(b,5248,N,P)|0}else{Kc(b,5256,N,P)|0}Wb(R,+h[D>>3],+h[E>>3],+h[P>>3]);break}Da=c[K>>2]|0;if((Da|0)>0){Ca=Da;Da=0;Ba=0;while(1){c[J>>2]=0;na=Da+1|0;if((Ca|0)>0){xa=0;Ma=Ba;while(1){Oa=G+(Ma<<3)|0;h[Oa>>3]=(Da|0)==(xa|0)?1.0:0.0;c[f>>2]=na;c[f+4>>2]=xa+1;Na(H|0,5232,f|0)|0;la=Ma+1|0;Kc(b,H,N,Oa)|0;Oa=(c[J>>2]|0)+1|0;c[J>>2]=Oa;Ra=c[K>>2]|0;if((Oa|0)<(Ra|0)){xa=Oa;Ma=la}else{Sa=Ra;Ta=la;break}}}else{Sa=Ca;Ta=Ba}if((na|0)<(Sa|0)){Ca=Sa;Da=na;Ba=Ta}else{break}}}$b(R,+h[D>>3],+h[E>>3],G)}}while(0);if((c[g>>2]|0)==3?(c[da>>2]|0)==2:0){Ea=R+3168|0;Fa=c[Ea>>2]|0;if((Fa|0)!=0){rd(Fa);c[Ea>>2]=0}Ea=R+3172|0;Fa=c[Ea>>2]|0;if((Fa|0)!=0){rd(Fa);c[Ea>>2]=0}c[R+1560>>2]=0;Ea=R+1568|0;Fa=R+4344|0;ca=0;do{h[Ea+(ca<<3)>>3]=0.0;h[Fa+(ca<<3)>>3]=0.0;ca=ca+1|0}while((ca|0)!=200);c[J>>2]=0;ca=0;g=0;while(1){c[f>>2]=1;c[f+4>>2]=g;Na(H|0,4992,f|0)|0;if((Kc(b,H,N,Ea+(c[J>>2]<<3)|0)|0)==0){Ga=c[J>>2]|0;h[Ea+(Ga<<3)>>3]=0.0;Ua=Ga;Va=ca}else{Ua=c[J>>2]|0;Va=ca+1|0}g=Ua+1|0;c[J>>2]=g;if((g|0)>=100){break}else{ca=Va}}c[J>>2]=0;ca=Va;g=0;while(1){c[f>>2]=2;c[f+4>>2]=g;Na(H|0,4992,f|0)|0;if((Kc(b,H,N,Ea+((c[J>>2]|0)+100<<3)|0)|0)==0){Ga=c[J>>2]|0;h[Ea+(Ga+100<<3)>>3]=0.0;Wa=Ga;Xa=ca}else{Wa=c[J>>2]|0;Xa=ca+1|0}g=Wa+1|0;c[J>>2]=g;if((g|0)>=100){break}else{ca=Xa}}if((Xa|0)>0){ca=R+3948|0;g=R+3944|0;Ga=100;ka=0;while(1){sa=+h[Ea+(((c[ca>>2]|0)*100|0)+Ga<<3)>>3];h[Fa+(Ga<<3)>>3]=sa;ta=+h[Ea+(((c[g>>2]|0)*100|0)+Ga<<3)>>3];h[Fa+(Ga+100<<3)>>3]=ta;if((ka|0)==0){Ya=sa!=0.0|ta!=0.0?Ga+1|0:0}else{Ya=ka}if((Ga|0)>0){Ga=Ga+ -1|0;ka=Ya}else{break}}Qb(R);c[d>>2]=0}}ka=R+3467|0;if(!((Ag(ka,5296,6)|0)!=0?(Ag(ka,5304,5)|0)!=0:0)){c[R+3292>>2]=-1;c[R+3288>>2]=5}do{if((Lc(b,5312,O)|0)==0){ka=R+128|0;if((Mc(b,5320,ka)|0)==0){if((Mc(b,5336,ka)|0)!=0){break}if((Lc(b,5344,ka)|0)!=0){break}h[ka>>3]=+h[R+120>>3];break}Pc(b,5320,32,m)|0;if(($f(m,84)|0)==0){if((Lc(b,5352,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744;break}if((Lc(b,5360,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744}}}else{h[R+128>>3]=(+h[O>>3]+-15019.81352)/365.242198781+1900.0}}while(0);c[R+3312>>2]=1;ua=qa}}while(0);c[R+3964>>2]=R+616;c[R+3972>>2]=ua;c[R+3968>>2]=$;c[R+3284>>2]=1;c[R+3296>>2]=0;c[R+3328>>2]=0;Yb(R);ea=R;i=e;return ea|0}function Nb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=i;i=i+96|0;f=e;g=e+16|0;if((d|0)==0){h=0;i=e;return h|0}j=Dg(d|0)|0;k=ig(1,j+1|0)|0;if((j|0)>0){l=0;do{m=a[d+l|0]|0;if((m+ -97<<24>>24&255)<26){a[k+l|0]=(m&255)+224}else{a[k+l|0]=m}l=l+1|0}while((l|0)!=(j|0))}a[k+j|0]=0;if((Dg(k|0)|0)==1){h=a[k]|0;i=e;return h|0}j=f;c[j>>2]=1314079575;c[j+4>>2]=4541761;a[f+8|0]=0;j=f+7|0;l=95;d=0;while(1){if((d|0)>0){n=d+64&255}else{n=0}a[j]=n;if((Pc(b,f,72,g)|0)==0){o=l}else{m=Dg(g|0)|0;p=ig(1,m+1|0)|0;if((m|0)>0){q=0;do{r=a[g+q|0]|0;if((r+ -97<<24>>24&255)<26){a[p+q|0]=(r&255)+224}else{a[p+q|0]=r}q=q+1|0}while((q|0)!=(m|0))}a[p+m|0]=0;q=(yg(p,k)|0)==0;hg(p);o=q?n:l}d=d+1|0;if((d|0)==27){break}else{l=o}}hg(k);h=o;i=e;return h|0}function Ob(b,c){b=b|0;c=c|0;var d=0,e=0;d=i;i=i+16|0;e=d;a[e]=0;Bc(b,c)|0;c=Mb(b,e)|0;i=d;return c|0}function Pb(b){b=b|0;var c=0,d=0,e=0;c=i;i=i+16|0;d=c;a[d]=0;e=Mb(b,d)|0;i=c;return e|0}function Qb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;b=i;i=i+176|0;d=b+88|0;e=b+40|0;f=b+16|0;g=b+56|0;j=b+80|0;k=b+168|0;l=b+32|0;m=b+72|0;n=b+8|0;o=b;p=j;c[p>>2]=1;c[p+4>>2]=1;p=c[a+3944>>2]|0;q=c[a+3948>>2]|0;if((c[a+3316>>2]|0)!=2){i=b;return}r=a+3928|0;if((yg(r,5848)|0)!=0){i=b;return}if(+h[a+((p*100|1)<<3)+1568>>3]==0.0?+h[a+((q*100|1)<<3)+1568>>3]==0.0:0){i=b;return}s=a+9312|0;t=c[s>>2]|0;if((t|0)==0){h[l>>3]=0.0;h[m>>3]=0.0;h[n>>3]=+h[a+136>>3];h[o>>3]=+h[a+144>>3]}else{bc(t,0.0,0.0,l,m);bc(c[s>>2]|0,+h[a+136>>3],+h[a+144>>3],n,o)}if((p|0)==0){u=+h[l>>3];v=+h[m>>3];w=v;x=+h[o>>3]-v;y=u;z=+h[n>>3]-u}else{u=+h[m>>3];v=+h[l>>3];w=v;x=+h[n>>3]-v;y=u;z=+h[o>>3]-u}u=x/11.0;x=z/11.0;o=ig(288,8)|0;n=ig(144,8)|0;l=ig(144,8)|0;z=w+.5;m=g+(q<<3)|0;h[m>>3]=z;s=f+(q<<3)|0;h[s>>3]=z;z=y+.5;t=g+(p<<3)|0;h[t>>3]=z;A=f+(p<<3)|0;h[A>>3]=z;B=a+3956|0;C=e+(p<<3)|0;p=e+(q<<3)|0;q=a+4064|0;y=z;D=11;E=l;F=n;G=o;while(1){h[A>>3]=y;H=E+96|0;I=11;J=E;K=F;L=G;while(1){if((Dd(f,B,e)|0)!=0){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}h[K>>3]=+h[C>>3];h[J>>3]=+h[p>>3];Wd(q,+h[C>>3],+h[p>>3],L,L+8|0)|0;h[A>>3]=x+ +h[A>>3];if((I|0)==0){break}else{I=I+ -1|0;J=J+8|0;K=K+8|0;L=L+16|0}}h[s>>3]=u+ +h[s>>3];if((D|0)==0){break}y=+h[t>>3];D=D+ -1|0;E=H;F=F+96|0;G=G+192|0}Dd(g,B,e)|0;h[C>>3]=+h[C>>3]+.0002777777777777778;Cd(e,B,f)|0;y=+h[A>>3]- +h[t>>3];u=+h[s>>3]- +h[m>>3];x=+Q(+(y*y+u*u))*3600.0;if(!(x!=0.0)){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}u=.04/x;c[k>>2]=1;C=0;G=1;a:while(1){if((G|0)>1){rd(C)}M=qd(j,2,k,1)|0;td(M,o,n,0,144,0);F=143;E=n;D=o;while(1){x=+sd(M,D);if(+P(+(x- +h[E>>3]))>u){break}if((F|0)==0){N=26;break a}else{F=F+ -1|0;E=E+8|0;D=D+16|0}}D=c[k>>2]|0;E=D+1|0;c[k>>2]=E;if((D|0)>8){N=28;break}else{C=M;G=E}}if((N|0)==26){c[k>>2]=(c[k>>2]|0)+1}else if((N|0)==28){_b(5904);c[a+1560>>2]=1}c[a+3168>>2]=M;c[a+5944>>2]=M;Dd(g,B,e)|0;h[p>>3]=+h[p>>3]+.0002777777777777778;Cd(e,B,f)|0;u=+h[A>>3]- +h[t>>3];x=+h[s>>3]- +h[m>>3];y=+Q(+(u*u+x*x))*3600.0;if(!(y!=0.0)){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}x=.04/y;c[k>>2]=1;d=M;M=1;b:while(1){if((M|0)>1){rd(d)}O=qd(j,2,k,1)|0;td(O,o,l,0,144,0);r=143;m=l;s=o;while(1){y=+sd(O,s);if(+P(+(y- +h[m>>3]))>x){break}if((r|0)==0){N=37;break b}else{r=r+ -1|0;m=m+8|0;s=s+16|0}}s=c[k>>2]|0;m=s+1|0;c[k>>2]=m;if((s|0)>8){N=39;break}else{d=O;M=m}}if((N|0)==37){c[k>>2]=(c[k>>2]|0)+1}else if((N|0)==39){_b(5904);c[a+1560>>2]=1}c[a+3172>>2]=O;c[a+5948>>2]=O;hg(o);hg(n);hg(l);i=b;return}function Rb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0,z=0.0,A=0,B=0,C=0;f=i;i=i+144|0;g=f+24|0;j=f+28|0;k=f+32|0;l=f+112|0;m=f+96|0;n=f+8|0;o=f+64|0;p=f;c[j>>2]=0;a[k]=0;a[l]=0;q=a[e]|0;if(q<<24>>24==0){r=n;c[r>>2]=1230328133;c[r+4>>2]=5787470;s=m+0|0;t=6e3|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0))}else{c[g>>2]=q<<24>>24;Na(n|0,5968,g|0)|0;c[g>>2]=a[e]|0;Na(m|0,5984,g|0)|0}if((Pc(b,n,31,l)|0)==0?(Pc(b,5472,31,l)|0)!=0:0){g=n;c[g>>2]=1230328133;c[g+4>>2]=5787470}if((Pc(b,m,31,k)|0)==0?(Pc(b,6e3,31,k)|0)!=0:0){s=m+0|0;t=6e3|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0))}g=a[l]|0;do{if(g<<24>>24==74){e=l+1|0;h[d+120>>3]=+ug(e);c[j>>2]=vg(e)|0;c[k>>2]=3492678;v=0;w=30}else if(!(g<<24>>24==66)){if((Ec(b,n,j)|0)!=0){Lc(b,n,d+120|0)|0;v=1;w=30;break}if((Ec(b,5344,j)|0)!=0){if((c[j>>2]|0)==0){c[j>>2]=1950;h[d+120>>3]=1950.0;v=0;w=30;break}else{Lc(b,5344,d+120|0)|0;v=1;w=30;break}}if((a[k]|0)!=0){if((Ag(k,5480,3)|0)==0){h[d+120>>3]=1950.0;c[j>>2]=1950;x=0;break}if((Ag(k,6016,4)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,5488,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,6024,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,6032,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0}else{v=0;w=30}}else{v=0;w=30}}else{e=l+1|0;h[d+120>>3]=+ug(e);c[j>>2]=~~+ug(e);c[k>>2]=3427142;v=0;w=30}}while(0);do{if((w|0)==30){if((c[j>>2]|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;l=d+3449|0;if((Ag(l,5656,2)|0)!=0?(Ag(l,4832,3)|0)!=0:0){x=v;break}c[k>>2]=3492678;x=v}else{x=v}}}while(0);v=d+128|0;do{if((Mc(b,5320,v)|0)==0){if((Mc(b,5336,v)|0)==0?(Lc(b,5344,v)|0)==0:0){y=+h[d+120>>3];h[v>>3]=y;z=y}else{w=43}}else{Pc(b,5320,32,o)|0;if(($f(o,84)|0)==0){if((Lc(b,5352,p)|0)!=0){y=+h[v>>3]+ +h[p>>3]/8765.812770744;h[v>>3]=y;z=y;break}if((Lc(b,5360,p)|0)!=0){y=+h[v>>3]+ +h[p>>3]/8765.812770744;h[v>>3]=y;z=y}else{w=43}}else{w=43}}}while(0);if((w|0)==43){z=+h[v>>3]}if(z==0.0){h[v>>3]=+h[d+120>>3]}do{if((a[k]|0)==0?(Pc(b,m,31,k)|0,(a[k]|0)==0):0){if((c[d+3884>>2]|0)!=7){v=d+3764|0;if((c[j>>2]|0)>1980){a[v]=3492678;a[v+1|0]=13643;a[v+2|0]=53;a[v+3|0]=0;break}else{a[v]=3427142;a[v+1|0]=13387;a[v+2|0]=52;a[v+3|0]=0;break}}}else{w=48}}while(0);do{if((w|0)==48?(m=d+3764|0,Lg(m|0,k|0)|0,(x|0)==0):0){if((Ag(m,5480,3)|0)==0){h[d+120>>3]=1950.0;break}if((Ag(m,5488,3)|0)==0){h[d+120>>3]=2.0e3;break}if((Ag(m,6016,4)|0)==0){h[d+120>>3]=2.0e3;break}if((Ag(m,6024,3)|0)==0?(c[j>>2]|0)==0:0){h[d+120>>3]=2.0e3}}}while(0);switch(a[d+3449|0]|0){case 71:{j=d+3764|0;s=j+0|0;t=6040|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 72:{j=d+3764|0;s=j+0|0;t=6088|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 65:{j=d+3764|0;a[j+0|0]=a[6104|0]|0;a[j+1|0]=a[6105|0]|0;a[j+2|0]=a[6106|0]|0;a[j+3|0]=a[6107|0]|0;a[j+4|0]=a[6108|0]|0;a[j+5|0]=a[6109|0]|0;A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 76:{j=d+3764|0;a[j+0|0]=a[5296|0]|0;a[j+1|0]=a[5297|0]|0;a[j+2|0]=a[5298|0]|0;a[j+3|0]=a[5299|0]|0;a[j+4|0]=a[5300|0]|0;a[j+5|0]=a[5301|0]|0;a[j+6|0]=a[5302|0]|0;A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 69:{j=d+3764|0;s=j+0|0;t=6056|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 83:{j=d+3764|0;s=j+0|0;t=6072|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};default:{A=d+3764|0;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return}}}function Sb(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0;d=i;e=b+3764|0;f=c[b+3260>>2]|0;if((a[e]|0)!=0){if((f|0)==0){g=0;j=3}else{k=f}}else{g=f;j=3}if((j|0)==3){a[e+0|0]=a[5296|0]|0;a[e+1|0]=a[5297|0]|0;a[e+2|0]=a[5298|0]|0;a[e+3|0]=a[5299|0]|0;a[e+4|0]=a[5300|0]|0;a[e+5|0]=a[5301|0]|0;a[e+6|0]=a[5302|0]|0;k=g}if((k|0)==-1){a[e+0|0]=a[5304|0]|0;a[e+1|0]=a[5305|0]|0;a[e+2|0]=a[5306|0]|0;a[e+3|0]=a[5307|0]|0;a[e+4|0]=a[5308|0]|0;a[e+5|0]=a[5309|0]|0}k=nc(e)|0;c[b+3884>>2]=k;do{if((k|0)!=2){g=b+3796|0;if((k|0)==1){a[g]=3492678;a[g+1|0]=13643;a[g+2|0]=53;a[g+3|0]=0;break}else{Lg(g|0,e|0)|0;break}}else{g=b+3796|0;a[g]=3427142;a[g+1|0]=13387;a[g+2|0]=52;a[g+3|0]=0}}while(0);c[b+3888>>2]=nc(b+3796|0)|0;k=b+120|0;h[b+3872>>3]=+h[k>>3];g=b+3828|0;Lg(g|0,e|0)|0;c[b+3880>>2]=nc(g)|0;h[b+3864>>3]=+h[k>>3];i=d;return}function Tb(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){i=b;return}if((c[a+3312>>2]|0)==0){hg(a);i=b;return}d=a+9312|0;e=c[d>>2]|0;if((e|0)!=0){Tb(e);c[d>>2]=0}Ub(a);d=c[a+9320>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3980>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3976>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3168>>2]|0;if((d|0)!=0){rd(d)}d=c[a+3172>>2]|0;if((d|0)!=0){rd(d)}hg(a);i=b;return}function Ub(a){a=a|0;var b=0,d=0;b=i;d=c[1654]|0;if((d|0)!=0){hg(d);c[1654]=0}d=c[6620>>2]|0;if((d|0)!=0){hg(d);c[6620>>2]=0}d=c[6624>>2]|0;if((d|0)!=0){hg(d);c[6624>>2]=0}d=c[6628>>2]|0;if((d|0)!=0){hg(d);c[6628>>2]=0}d=c[6632>>2]|0;if((d|0)!=0){hg(d);c[6632>>2]=0}d=c[6636>>2]|0;if((d|0)!=0){hg(d);c[6636>>2]=0}d=c[6640>>2]|0;if((d|0)!=0){hg(d);c[6640>>2]=0}d=c[6644>>2]|0;if((d|0)!=0){hg(d);c[6644>>2]=0}d=c[6648>>2]|0;if((d|0)!=0){hg(d);c[6648>>2]=0}d=c[6652>>2]|0;if((d|0)!=0){hg(d);c[6652>>2]=0}if((a|0)==0){i=b;return}if((c[a+3312>>2]|0)==0){i=b;return}d=c[a+9208>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9212>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9216>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9220>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9224>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9228>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9232>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9236>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9240>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9244>>2]|0;if((d|0)==0){i=b;return}hg(d);i=b;return}function Vb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+144|0;g=f;h=f+8|0;c[h>>2]=5130572;c[h+4>>2]=5265985;c[h+8>>2]=5266003;c[h+12>>2]=5128532;c[h+16>>2]=5130579;c[h+20>>2]=4674643;c[h+24>>2]=4411969;c[h+28>>2]=5132378;c[h+32>>2]=4277594;c[h+36>>2]=5392705;c[h+40>>2]=5265731;c[h+44>>2]=5390659;c[h+48>>2]=5391693;c[h+52>>2]=4277571;c[h+56>>2]=5263171;c[h+60>>2]=4476739;c[h+64>>2]=4542275;c[h+68>>2]=5197635;c[h+72>>2]=5132098;c[h+76>>2]=5194576;c[h+80>>2]=4998739;c[h+84>>2]=5390672;c[h+88>>2]=5523777;c[h+92>>2]=5001037;c[h+96>>2]=4412227;c[h+100>>2]=4412241;c[h+104>>2]=4412244;c[h+108>>2]=5260110;c[h+112>>2]=5459015;c[h+116>>2]=5460804;c[h+120>>2]=5524560;c[h+124>>2]=5787220;c[h+128>>2]=5787738;c[h+132>>2]=5656660;if((Ag(d,6128,4)|0)==0){a[d]=1313819736;a[d+1|0]=5132108;a[d+2|0]=20047;a[d+3|0]=78}j=b+3368|0;Lg(j|0,d|0)|0;k=b+3449|0;Lg(k|0,d|0)|0;l=b+3467|0;Lg(l|0,d|0)|0;do{if((Ag(d,6136,6)|0)!=0){if((Ag(d,6144,6)|0)==0){c[b+3260>>2]=-1;break}if((Qc(d,6152)|0)!=0){c[b+3260>>2]=-1;break}m=a[d]|0;if(!(m<<24>>24==65|m<<24>>24==68|m<<24>>24==82)?(a[d+1|0]|0)!=76:0){c[b+3260>>2]=0;i=f;return 0}a[k]=m;a[b+3450|0]=a[d+1|0]|0;m=a[d+2|0]|0;n=b+3451|0;do{if(!(m<<24>>24==45)){a[n]=m;o=a[d+3|0]|0;p=b+3452|0;if(o<<24>>24==45){a[p]=0;q=4;break}else{a[p]=o;a[b+3453|0]=0;q=4;break}}else{a[n]=0;q=3}}while(0);n=((a[d+q|0]|0)==45)+q|0;m=n+((a[d+n|0]|0)==45)|0;n=m+((a[d+m|0]|0)==45)|0;m=n+((a[d+n|0]|0)==45)|0;a[l]=a[d+m|0]|0;a[b+3468|0]=a[d+(m+1)|0]|0;a[b+3469|0]=a[d+(m+2)|0]|0;a[b+3470|0]=0;c[g>>2]=k;c[g+4>>2]=l;Na(j|0,6160,g|0)|0;if((a[j]|0)==32){a[j]=45}m=b+3369|0;if((a[m]|0)==32){a[m]=45}m=b+3370|0;if((a[m]|0)==32){a[m]=45}m=b+3371|0;if((a[m]|0)==32){a[m]=45}m=b+3372|0;if((a[m]|0)==32){a[m]=45}m=b+3373|0;if((a[m]|0)==32){a[m]=45}m=b+3374|0;if((a[m]|0)==32){a[m]=45}n=b+3375|0;if((a[n]|0)==32){a[n]=45}o=b+3260|0;c[o>>2]=0;p=0;r=1;while(1){if((Ag(l,h+(r<<2)|0,3)|0)==0){c[o>>2]=r;s=r}else{s=p}r=r+1|0;if((r|0)==34){break}else{p=s}}p=b+3324|0;r=c[p>>2]|0;if((r|0)==0){c[p>>2]=3;break}else if((r|0)==1){c[p>>2]=2}else if((r|0)!=2){break}if((s|0)==31){a[m]=65;a[n]=78;c[o>>2]=3;break}else if((s|0)==32){a[m]=80;a[n]=78;c[o>>2]=7;break}else{break}}else{c[b+3260>>2]=0}}while(0);do{if((Ag(e,6168,4)|0)!=0){if((Ag(e,6192,4)|0)==0){a[e]=a[d]|0;s=e+1|0;a[s+0|0]=a[6176|0]|0;a[s+1|0]=a[6177|0]|0;a[s+2|0]=a[6178|0]|0;c[b+3264>>2]=-90;s=b+3764|0;a[s]=4280403;a[s+1|0]=16720;a[s+2|0]=65;a[s+3|0]=0;c[b+3884>>2]=8;break}else{c[b+3264>>2]=0;break}}else{a[e]=a[d]|0;s=e+1|0;a[s+0|0]=a[6176|0]|0;a[s+1|0]=a[6177|0]|0;a[s+2|0]=a[6178|0]|0;c[b+3264>>2]=90;s=b+3764|0;a[s+0|0]=a[6184|0]|0;a[s+1|0]=a[6185|0]|0;a[s+2|0]=a[6186|0]|0;a[s+3|0]=a[6187|0]|0;a[s+4|0]=a[6188|0]|0;a[s+5|0]=a[6189|0]|0;c[b+3884>>2]=7}}while(0);s=b+3377|0;Lg(s|0,e|0)|0;h=b+3458|0;Lg(h|0,e|0)|0;do{if((Ag(e,6136,6)|0)!=0){if((Ag(e,6144,6)|0)==0){c[b+3260>>2]=-1;break}j=a[e]|0;if(!(j<<24>>24==65|j<<24>>24==68|j<<24>>24==82)?(a[e+1|0]|0)!=76:0){c[b+3260>>2]=0;break}a[h]=j;j=e+1|0;a[b+3459|0]=a[j]|0;k=a[e+2|0]|0;q=b+3460|0;do{if(!(k<<24>>24==45)){a[q]=k;r=a[e+3|0]|0;p=b+3461|0;if(r<<24>>24==45){a[p]=0;t=4;break}else{a[p]=r;a[b+3462|0]=0;t=4;break}}else{a[q]=0;t=3}}while(0);q=((a[e+t|0]|0)==45)+t|0;k=q+((a[e+q|0]|0)==45)|0;q=k+((a[e+k|0]|0)==45)|0;k=q+((a[e+q|0]|0)==45)|0;a[l]=a[e+k|0]|0;a[b+3468|0]=a[e+(k+1)|0]|0;a[b+3469|0]=a[e+(k+2)|0]|0;a[b+3470|0]=0;if((Ag(d,6120,3)|0)!=0?(Ag(d+1|0,6176,3)|0)!=0:0){c[b+3304>>2]=0}else{c[b+3304>>2]=1}if((a[j]|0)!=76?(a[e]|0)!=65:0){c[b+3292>>2]=0;c[b+3288>>2]=3}else{c[b+3292>>2]=1;c[b+3288>>2]=5}c[g>>2]=h;c[g+4>>2]=l;Na(s|0,6160,g|0)|0;if((a[s]|0)==32){a[s]=45}k=b+3378|0;if((a[k]|0)==32){a[k]=45}k=b+3379|0;if((a[k]|0)==32){a[k]=45}k=b+3380|0;if((a[k]|0)==32){a[k]=45}k=b+3381|0;if((a[k]|0)==32){a[k]=45}k=b+3382|0;if((a[k]|0)==32){a[k]=45}k=b+3383|0;if((a[k]|0)==32){a[k]=45}k=b+3384|0;if((a[k]|0)==32){a[k]=45}}else{c[b+3260>>2]=0}}while(0);$e(b,d);i=f;return 0}function Wb(a,b,d,e){a=a|0;b=+b;d=+d;e=+e;var f=0,g=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0;f=i;g=c[a+3316>>2]|0;j=a+760|0;h[j>>3]=b;k=a+768|0;l=d!=0.0?d:b;h[k>>3]=l;h[a+32>>3]=b;h[a+40>>3]=l;if((g|0)>0){m=(g|0)<2?g:2;g=0;n=a+832|0;while(1){o=0;p=n;while(1){h[p>>3]=(g|0)==(o|0)?1.0:0.0;o=o+1|0;if((o|0)==(m|0)){break}else{p=p+8|0}}g=g+1|0;if((g|0)==(m|0)){break}else{n=n+(m<<3)|0}}}c[a+3300>>2]=0;m=a+48|0;if(e<0.0){q=e+360.0}else{q=e}if(!(q>=360.0)){r=q}else{r=q+-360.0}h[m>>3]=r;q=r*3.141592653589793/180.0;r=+S(+q);if(b*d>0.0){s=-q}else{s=q}q=+T(+s);s=+h[j>>3];n=a+56|0;h[n>>3]=r*s;d=+h[k>>3];b=q*+P(+d);if(s<0.0){h[a+64>>3]=-b}else{h[a+64>>3]=b}b=q*+P(+s);if(d<0.0){h[a+72>>3]=b}else{h[a+72>>3]=-b}h[a+80>>3]=r*d;Bd(2,n,a+88|0)|0;lc(a);d=+h[j>>3];j=d<0.0;if((c[a+3304>>2]|0)!=0){if(j?+h[k>>3]>0.0:0){c[a+3256>>2]=1;r=+h[m>>3];b=r+-90.0;n=a+3200|0;if(b<-180.0){h[n>>3]=b+360.0;h[a+3208>>3]=r;h[a+3216>>3]=b+360.0;i=f;return}else{h[n>>3]=b;h[a+3208>>3]=r;h[a+3216>>3]=b;i=f;return}}do{if(d>0.0){if(!(+h[k>>3]<0.0)){if(!(+h[k>>3]>0.0)){break}c[a+3256>>2]=0;b=+h[m>>3]+90.0;n=a+3200|0;if(b>180.0){r=b+-360.0;h[n>>3]=r;h[a+3208>>3]=r;h[a+3216>>3]=b+-360.0;i=f;return}else{h[n>>3]=b;h[a+3208>>3]=b;h[a+3216>>3]=b;i=f;return}}else{c[a+3256>>2]=1;b=+h[m>>3];r=b+90.0;if(r>180.0){t=r+-360.0}else{t=r}h[a+3200>>3]=t;h[a+3208>>3]=b;r=b+-90.0;n=a+3216|0;h[n>>3]=r;if(!(r<-180.0)){i=f;return}h[n>>3]=r+360.0;i=f;return}}}while(0);if(!j){i=f;return}if(!(+h[k>>3]<0.0)){i=f;return}c[a+3256>>2]=0;t=+h[m>>3];r=t+-90.0;if(r<-180.0){u=r+360.0}else{u=r}h[a+3200>>3]=u;h[a+3208>>3]=u;u=t+90.0;n=a+3216|0;h[n>>3]=u;if(!(u>180.0)){i=f;return}h[n>>3]=u+-360.0;i=f;return}if(j?+h[k>>3]>0.0:0){c[a+3256>>2]=0;u=+h[m>>3];h[a+3200>>3]=u;t=u+90.0;if(t>180.0){v=t+-360.0}else{v=t}h[a+3208>>3]=v;v=u+180.0;n=a+3216|0;h[n>>3]=v;if(!(v>180.0)){i=f;return}h[n>>3]=v+-360.0;i=f;return}do{if(d>0.0){if(!(+h[k>>3]<0.0)){if(!(+h[k>>3]>0.0)){break}c[a+3256>>2]=1;v=+h[m>>3];h[a+3200>>3]=-v;u=90.0-v;if(u>180.0){w=u+-360.0}else{w=u}h[a+3208>>3]=w;h[a+3216>>3]=v;i=f;return}c[a+3256>>2]=0;v=+h[m>>3]+180.0;if(v>180.0){x=v+-360.0}else{x=v}h[a+3200>>3]=x;v=x+90.0;if(v>180.0){y=v+-360.0}else{y=v}h[a+3208>>3]=y;v=x+180.0;n=a+3216|0;h[n>>3]=v;if(!(v>180.0)){i=f;return}h[n>>3]=v+-360.0;i=f;return}}while(0);if(!j){i=f;return}if(!(+h[k>>3]<0.0)){i=f;return}c[a+3256>>2]=1;x=+h[m>>3];y=x+180.0;if(y>180.0){z=y+-360.0}else{z=y}h[a+3200>>3]=z;y=z+90.0;if(y>180.0){A=y+-360.0}else{A=y}h[a+3208>>3]=A;A=x+90.0;m=a+3216|0;h[m>>3]=A;if(!(A>180.0)){i=f;return}h[m>>3]=A+-360.0;i=f;return}function Xb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,o=0.0;e=i;i=i+16|0;f=e;if((b|0)==0){i=e;return}g=b+3312|0;if((c[g>>2]|0)==0){i=e;return}do{if((((d|0)!=0?(a[d]|0)!=0:0)?(yg(d,6200)|0)!=0:0)?(yg(d,6208)|0)!=0:0){j=nc(d)|0;if((j|0)<0){i=e;return}l=c[b+3884>>2]|0;if((j|0)!=(l|0)&(l+ -5|0)>>>0<2){i=e;return}else{Lg(b+3796|0,d|0)|0;h[b+3872>>3]=+oc(d);m=j;break}}else{n=7}}while(0);do{if((n|0)==7){d=c[b+3884>>2]|0;j=b+3796|0;Lg(j|0,b+3764|0)|0;o=+h[b+120>>3];h[b+3872>>3]=o;if((d|0)==1){if(!(o!=2.0e3)){a[j+0|0]=a[6232|0]|0;a[j+1|0]=a[6233|0]|0;a[j+2|0]=a[6234|0]|0;a[j+3|0]=a[6235|0]|0;a[j+4|0]=a[6236|0]|0;a[j+5|0]=a[6237|0]|0;m=1;break}a[j]=74;h[k>>3]=o;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Na(b+3797|0,6216,f|0)|0;l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)!=48){m=1;break}a[l]=0;m=1;break}else if((d|0)==2){if(!(o!=1950.0)){a[j+0|0]=a[6224|0]|0;a[j+1|0]=a[6225|0]|0;a[j+2|0]=a[6226|0]|0;a[j+3|0]=a[6227|0]|0;a[j+4|0]=a[6228|0]|0;a[j+5|0]=a[6229|0]|0;m=2;break}a[j]=66;h[k>>3]=o;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Na(b+3797|0,6216,f|0)|0;l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)!=48){m=2;break}a[l]=0;m=2;break}else{m=d;break}}}while(0);c[b+3888>>2]=m;if((c[g>>2]|0)==0){i=e;return}switch(m|0){case 5:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};case 8:case 7:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};case 9:case 4:case 3:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};default:{c[b+3292>>2]=0;c[b+3288>>2]=3;i=e;return}}}function Yb(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;d=i;i=i+32|0;e=d;f=d+8|0;if((b|0)==0){i=d;return}g=b+3312|0;if((c[g>>2]|0)==0){i=d;return}h=0;a:while(1){if((h|0)==0){j=f+0|0;k=6656|0;l=j+12|0;do{a[j]=a[k]|0;j=j+1|0;k=k+1|0}while((j|0)<(l|0))}else{c[e>>2]=h;Na(f|0,6672,e|0)|0}k=c[6616+(h<<2)>>2]|0;b:do{if((k|0)!=0){if((c[g>>2]|0)!=0?(j=Dg(k|0)|0,(j|0)>0):0){l=b+(h<<2)+9208|0;m=c[l>>2]|0;if((m|0)!=0){hg(m)}m=ig(j+2|0,1)|0;c[l>>2]=m;if((m|0)!=0){n=m;m=0;do{o=a[k+m|0]|0;a[n+m|0]=o<<24>>24==95?32:o;m=m+1|0;n=c[l>>2]|0}while((m|0)!=(j|0));a[n+j|0]=0}}}else{m=Wa(f|0)|0;if((m|0)!=0){if((c[g>>2]|0)==0){break}l=Dg(m|0)|0;if((l|0)<=0){break}o=b+(h<<2)+9208|0;p=c[o>>2]|0;if((p|0)!=0){hg(p)}p=ig(l+2|0,1)|0;c[o>>2]=p;if((p|0)==0){break}else{q=p;r=0}do{p=a[m+r|0]|0;a[q+r|0]=p<<24>>24==95?32:p;r=r+1|0;q=c[o>>2]|0}while((r|0)!=(l|0));a[q+l|0]=0;break}switch(h|0){case 4:{if((c[g>>2]|0)!=0){o=b+9224|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=112;a[m+2|0]=112;a[m+3|0]=109;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};case 2:{if((c[g>>2]|0)!=0){m=b+9216|0;o=c[m>>2]|0;if((o|0)!=0){hg(o)}o=ig(13,1)|0;c[m>>2]=o;if((o|0)==0){break b}a[o]=115;a[o+1|0]=103;a[o+2|0]=115;a[o+3|0]=99;a[o+4|0]=32;a[o+5|0]=45;a[o+6|0]=97;a[o+7|0]=104;a[o+8|0]=32;a[o+9|0]=37;a[o+10|0]=115;a[o+11|0]=0;break b}break};case 3:{if((c[g>>2]|0)!=0){o=b+9220|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=116;a[m+2|0]=121;a[m+3|0]=50;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};case 5:{if((c[g>>2]|0)!=0){m=b+9228|0;o=c[m>>2]|0;if((o|0)!=0){hg(o)}o=ig(13,1)|0;c[m>>2]=o;if((o|0)==0){break b}a[o]=115;a[o+1|0]=115;a[o+2|0]=97;a[o+3|0]=111;a[o+4|0]=32;a[o+5|0]=45;a[o+6|0]=97;a[o+7|0]=104;a[o+8|0]=32;a[o+9|0]=37;a[o+10|0]=115;a[o+11|0]=0;break b}break};case 1:{if((c[g>>2]|0)!=0){o=b+9212|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=117;a[m+2|0]=97;a[m+3|0]=50;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};default:{c[b+(h<<2)+9208>>2]=0;break b}}h=h+1|0;continue a}}while(0);h=h+1|0;if((h|0)==10){break}}i=d;return}function Zb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0.0,l=0.0;d=i;if((b|0)==0){i=d;return}c[a+3300>>2]=1;e=a+56|0;h[e>>3]=+h[b>>3];f=b+8|0;h[a+64>>3]=+h[f>>3];g=b+16|0;h[a+72>>3]=+h[g>>3];j=b+24|0;h[a+80>>3]=+h[j>>3];Bd(2,e,a+88|0)|0;k=+h[b>>3];l=+h[g>>3];b=a+32|0;h[b>>3]=+Q(+(k*k+l*l));l=+h[f>>3];k=+h[j>>3];j=a+40|0;h[j>>3]=+Q(+(l*l+k*k));if((c[a+3304>>2]|0)!=0){k=+h[f>>3];h[f>>3]=-+h[g>>3];h[g>>3]=-k}lc(a);c[a+3312>>2]=1;ac(a);h[a+760>>3]=+h[b>>3];h[a+768>>3]=+h[j>>3];i=d;return}function _b(a){a=a|0;var b=0;b=i;Lg(6536,a|0)|0;i=b;return}function $b(a,b,d,e){a=a|0;b=+b;d=+d;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;f=i;if((e|0)==0){i=f;return}g=a+3316|0;j=c[g>>2]|0;if((j+ -1|0)>>>0>8){k=c[a+3320>>2]|0;c[g>>2]=k;l=k}else{l=j}j=a+760|0;h[j>>3]=b;k=a+768|0;m=d!=0.0?d:b;h[k>>3]=m;h[a+32>>3]=b;h[a+40>>3]=m;if((l|0)>0){g=0;n=e;o=a+832|0;while(1){p=n+(l<<3)|0;q=0;r=n;s=o;while(1){h[s>>3]=+h[r>>3];q=q+1|0;if((q|0)==(l|0)){break}else{r=r+8|0;s=s+8|0}}s=g+1|0;if((s|0)==(l|0)){break}else{g=s;n=p;o=o+(l<<3)|0}}m=+h[j>>3];j=a+56|0;h[j>>3]=+h[e>>3]*m;if((l|0)>1){h[a+64>>3]=+h[e+8>>3]*m;m=+h[k>>3];h[a+72>>3]=+h[e+(l<<3)>>3]*m;h[a+80>>3]=+h[e+(l+1<<3)>>3]*m;t=j}else{u=j;v=11}}else{j=a+56|0;h[j>>3]=+h[e>>3]*b;u=j;v=11}if((v|0)==11){v=a+64|0;j=a+80|0;c[v+0>>2]=0;c[v+4>>2]=0;c[v+8>>2]=0;c[v+12>>2]=0;h[j>>3]=1.0;t=u}Bd(2,t,a+88|0)|0;c[a+3300>>2]=1;Ad(a+3956|0)|0;c[a+3312>>2]=1;ac(a);i=f;return}function ac(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;b=i;i=i+64|0;d=b+48|0;e=b+24|0;f=b+16|0;g=b+40|0;j=b;k=b+32|0;l=b+8|0;if(!(+h[a+136>>3]<1.5)?!(+h[a+144>>3]<1.5):0){if((c[a+3884>>2]|0)==6){i=b;return}m=a+32|0;h[m>>3]=+P(+(+h[m>>3]));n=a+40|0;h[n>>3]=+P(+(+h[n>>3]));o=+h[a+16>>3];p=+h[a+24>>3];bc(a,o,p,e,f);q=a+3304|0;r=+h[e>>3];if((c[q>>2]|0)==0){s=+h[f>>3];e=a+3828|0;ic(a,r+ +h[m>>3],s,e,j,l,d);ic(a,r,s+ +h[n>>3],e,g,k,d)}else{s=+h[f>>3];f=a+3828|0;ic(a,r+ +h[n>>3],s,f,j,l,d);ic(a,r,s+ +h[m>>3],f,g,k,d)}s=+Y(+(+h[k>>3]-p),+(+h[g>>3]-o))*180.0/3.141592653589793;if(s<-90.0){t=s+360.0}else{t=s}h[a+3208>>3]=t;s=+Y(+(+h[l>>3]-p),+(+h[j>>3]-o))*180.0/3.141592653589793;if(s<-90.0){u=s+360.0}else{u=s}h[a+3216>>3]=u;if(t<-90.0){s=t+270.0;h[a+3200>>3]=s;v=s}else{s=t+-90.0;h[a+3200>>3]=s;v=s}j=(c[q>>2]|0)==0;if(!j){s=v+90.0;q=a+48|0;h[q>>3]=s;if(s<0.0){o=s+360.0;h[q>>3]=o;w=o}else{w=s}}else{h[a+48>>3]=v;w=v}q=a+48|0;if(w<0.0){v=w+360.0;h[q>>3]=v;x=v}else{x=w}if(x>=360.0){h[q>>3]=x+-360.0}x=u-t;w=t-u;q=w>80.0&w<100.0?1:x<280.0&x>260.0?1:x<-80.0&x>-100.0&1;c[a+3256>>2]=q;l=(q|0)!=0;if(j){if(l){i=b;return}h[m>>3]=-+h[m>>3];i=b;return}else{if(!l){i=b;return}h[n>>3]=-+h[n>>3];i=b;return}}x=+h[a+48>>3];h[a+3200>>3]=x;h[a+3208>>3]=x+90.0;h[a+3216>>3]=x+180.0;i=b;return}function bc(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0.0,x=0.0,y=0.0;g=i;i=i+144|0;j=g+104|0;k=g+56|0;l=g+8|0;m=g+40|0;n=g+136|0;o=g;p=g+48|0;q=g+96|0;r=g+88|0;if((a|0)==0){i=g;return}if((c[a+3312>>2]|0)==0){i=g;return}h[a+576>>3]=b;h[a+584>>3]=d;h[a+592>>3]=+h[815];s=a+3308|0;c[s>>2]=0;t=c[a+9312>>2]|0;if((t|0)==0){_e(a,b,d,o,p)}else{bc(t,b,d,o,p)}t=a+3260|0;u=c[t>>2]|0;do{if((u|0)==30){if((bd(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==31){if((ed(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==32){if((ld(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==29){if((nd(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else{d=+h[o>>3];b=+h[p>>3];if((c[a+3324>>2]|0)==2|(u|0)<1){if(($c(d,b,a,q,r)|0)==0){v=24;break}c[s>>2]=1;w=0.0;x=0.0;break}h[q>>3]=0.0;h[r>>3]=0.0;h[l>>3]=d;h[l+8>>3]=b;if((u+ -24|0)>>>0<3){h[l+16>>3]=+((c[1632]|0)+1|0)}else{h[l+16>>3]=+h[815]}h[l+24>>3]=1.0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;c[k+16>>2]=0;c[k+20>>2]=0;c[k+24>>2]=0;c[k+28>>2]=0;if((zd(a+3368|0,a+3924|0,l,a+3956|0,k,a+4064|0,m,n,a+688|0,a+3984|0,j)|0)==0){h[q>>3]=+h[j+(c[a+3944>>2]<<3)>>3];h[r>>3]=+h[j+(c[a+3948>>2]<<3)>>3];v=24;break}else{c[s>>2]=1;w=0.0;x=0.0;break}}}while(0);if((v|0)==24){if((c[s>>2]|0)==0){if((c[t>>2]|0)>0){mc(c[a+3884>>2]|0,c[a+3888>>2]|0,+h[a+120>>3],+h[a+3872>>3],q,r,+h[a+128>>3])}t=c[a+3264>>2]|0;if((t|0)==90){b=90.0- +h[r>>3];h[r>>3]=b;y=b}else if((t|0)==-90){b=+h[r>>3]+-90.0;h[r>>3]=b;y=b}else{y=+h[r>>3]}b=+h[q>>3];h[a+600>>3]=b;h[a+608>>3]=y;w=y;x=b}else{w=0.0;x=0.0}}h[e>>3]=x;h[f>>3]=w;f=c[a+3888>>2]|0;if((f|0)<1){i=g;return}if((f|0)==6|(f|0)==10){i=g;return}w=+h[e>>3];if(w<0.0){h[e>>3]=w+360.0;i=g;return}if(!(w>360.0)){i=g;return}h[e>>3]=w+-360.0;i=g;return}function cc(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=d|0;e=e|0;f=f|0;var g=0;g=i;ic(a,b,c,a+3828|0,d,e,f);i=g;return}function dc(b,d,e,f,g){b=b|0;d=+d;e=+e;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+96|0;k=j+16|0;l=j+8|0;m=j;n=j+56|0;o=j+24|0;if((b|0)!=0?(c[b+3312>>2]|0)!=0:0){bc(b,d,e,l,m);if((c[b+3308>>2]|0)!=0){p=f;q=p;a[q]=543581775;a[q+1|0]=2123366;a[q+2|0]=8294;a[q+3|0]=32;q=p+4|0;a[q]=7364973;a[q+1|0]=28769;a[q+2|0]=112;a[q+3|0]=0;r=1;i=j;return r|0}q=c[b+3292>>2]|0;do{if((q|0)==0){p=b+3288|0;s=c[p>>2]|0;t=(s<<1)+18|0;if((t|0)>=(g|0)){if((c[b+3296>>2]|0)==0){Hg(f|0,6336,g|0)|0;u=0;break}else{Hg(f|0,6304,g|0)|0;u=0;break}}e=+h[l>>3];if(((c[b+3888>>2]|0)+ -1|0)>>>0<2){Tc(n,32,e,s);Uc(o,32,+h[m>>3],(c[p>>2]|0)+ -1|0)}else{Uc(n,32,e,s);Uc(o,32,+h[m>>3],c[p>>2]|0)}if((c[b+3296>>2]|0)==0){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0}u=g-t|0}else if((q|0)==1){t=b+3288|0;p=c[t>>2]|0;s=(p<<1)+9|0;if((s|0)>=(g|0)){if((c[b+3296>>2]|0)==0){Hg(f|0,6280,g|0)|0;u=0;break}else{Hg(f|0,6256,g|0)|0;u=0;break}}Vc(n,32,+h[l>>3],p);Vc(o,32,+h[m>>3],c[t>>2]|0);if((c[b+3296>>2]|0)==0){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0}u=g-s|0}else{u=g}}while(0);switch(c[b+3888>>2]|0){case 5:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(q){q=s;t=q;a[t]=1953259808;a[t+1|0]=7629921;a[t+2|0]=29804;a[t+3|0]=116;t=q+4|0;a[t]=8020269;a[t+1|0]=31329;a[t+2|0]=122;a[t+3|0]=0;r=1;i=j;return r|0}else{t=s;s=t;a[s]=1953259785;a[s+1|0]=7629921;a[s+2|0]=29804;a[s+3|0]=116;s=t+4|0;a[s]=8020269;a[s+1|0]=31329;a[s+2|0]=122;a[s+3|0]=0;r=1;i=j;return r|0}break};case 4:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;t=f+(Dg(f|0)|0)|0;if(s){v=t+0|0;w=6416|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=t+0|0;w=6400|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 9:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}t=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(t){t=s;q=t;a[q]=1634496544;a[q+1|0]=6384752;a[q+2|0]=24940;a[q+3|0]=97;q=t+4|0;a[q]=7628142;a[q+1|0]=29797;a[q+2|0]=116;a[q+3|0]=0;r=1;i=j;return r|0}else{q=s;s=q;a[s]=1634496521;a[s+1|0]=6384752;a[s+2|0]=24940;a[s+3|0]=97;s=q+4|0;a[s]=7628142;a[s+1|0]=29797;a[s+2|0]=116;a[s+3|0]=0;r=1;i=j;return r|0}break};case 8:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;q=f+(Dg(f|0)|0)|0;if(s){v=q+0|0;w=6480|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=q+0|0;w=6464|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 7:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(q){v=s+0|0;w=6448|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=s+0|0;w=6432|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 1:case 2:{s=b+3796|0;if((u|0)<=((Dg(s|0)|0)+1|0)){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;t=f+(Dg(f|0)|0)|0;p=q?32:9;a[t]=p;a[t+1|0]=p>>8;Fg(f|0,s|0)|0;r=1;i=j;return r|0};case 3:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;p=f+(Dg(f|0)|0)|0;if(s){v=p+0|0;w=6384|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=p+0|0;w=6368|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};default:{w=b+3288|0;Wc(n,+h[l>>3],0,c[w>>2]|0);Wc(o,+h[m>>3],0,c[w>>2]|0);w=Dg(n|0)|0;m=w+1+(Dg(o|0)|0)|0;l=b+3476|0;v=b+3508|0;x=(Dg(l|0)|0)+2+(Dg(v|0)|0)|0;p=b+3884|0;if(((c[p>>2]|0)==6?(c[b+3328>>2]|0)==1:0)?(s=x+m|0,(u|0)>(s|0)):0){if((a[l]|0)!=0){t=n+w|0;a[t]=32;a[t+1|0]=0;Fg(n|0,l|0)|0}if((a[v]|0)==0){y=s}else{t=o+(Dg(o|0)|0)|0;a[t]=32;a[t+1|0]=0;Fg(o|0,v|0)|0;y=s}}else{y=m}m=(c[b+3296>>2]|0)!=0;do{if((u|0)>(y|0)){if(m){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0;break}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0;break}}else{if(m){Hg(f|0,6496,u|0)|0;break}else{Hg(f|0,6280,u|0)|0;break}}}while(0);if((c[p>>2]|0)!=6){r=1;i=j;return r|0}m=b+3328|0;if((c[m>>2]|0)==1){r=1;i=j;return r|0}if((u|0)>(y+7|0)?(b=f+(Dg(f|0)|0)|0,k=b,a[k]=1852402720,a[k+1|0]=7235948,a[k+2|0]=28265,a[k+3|0]=110,k=b+4|0,a[k]=7496037,a[k+1|0]=29281,a[k+2|0]=114,a[k+3|0]=0,(c[p>>2]|0)!=6):0){r=1;i=j;return r|0}if((c[m>>2]|0)!=2){r=1;i=j;return r|0}if((u|0)<=(x+7+y|0)){r=1;i=j;return r|0}if((a[l]|0)!=0){y=f+(Dg(f|0)|0)|0;a[y]=32;a[y+1|0]=0;Fg(f|0,l|0)|0}if((a[v]|0)==0){r=1;i=j;return r|0}l=f+(Dg(f|0)|0)|0;a[l]=32;a[l+1|0]=0;Fg(f|0,v|0)|0;r=1;i=j;return r|0}}}if((g|0)<=0){r=0;i=j;return r|0}a[f]=0;r=0;i=j;return r|0}function ec(a,b,c,d){a=+a;b=+b;c=+c;d=+d;var e=0,f=0,g=0;e=i;i=i+48|0;f=e+24|0;g=e;Ac(a,b,1.0,f);Ac(c,d,1.0,g);d=+h[f>>3]- +h[g>>3];c=+h[f+8>>3]- +h[g+8>>3];b=+h[f+16>>3]- +h[g+16>>3];a=(d*d+0.0+c*c+b*b)*.25;b=a>1.0?1.0:a;a=+Y(+(+Q(+b)),+(+Q(+(1.0-b))))*2.0*180.0/3.141592653589793;i=e;return+a}function fc(a){a=a|0;var b=0;if((a|0)==0){b=0}else{b=(c[a+3312>>2]|0)!=0}return(b?a+3796|0:0)|0}function gc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;if((a|0)!=0?(c[a+3312>>2]|0)!=0:0){e=a+3292|0;f=c[e>>2]|0;c[e>>2]=b;if((b|0)==1&(f|0)==0?(e=a+3288|0,(c[e>>2]|0)==3):0){c[e>>2]=6}if((b|0)==0&(f|0)==1){b=a+3288|0;if((c[b>>2]|0)==5){c[b>>2]=3;g=1}else{g=1}}else{g=f}}else{g=0}i=d;return g|0}function hc(a){a=a|0;var b=0;if((a|0)==0){b=0}else{b=(c[a+3312>>2]|0)!=0}return(b?a+3764|0:0)|0}function ic(a,b,d,e,f,g,j){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0;k=i;i=i+32|0;l=k+24|0;m=k+16|0;n=k+8|0;o=k;if((a|0)==0){i=k;return}if((c[a+3312>>2]|0)==0){i=k;return}c[j>>2]=0;h[l>>3]=b;h[m>>3]=d;p=c[a+3264>>2]|0;if((p|0)==90){h[m>>3]=90.0-d}else if((p|0)==-90){h[m>>3]=d+-90.0}if((e|0)==0){q=+h[a+120>>3];r=c[a+3884>>2]|0}else{p=nc(e)|0;q=+oc(e);r=p}h[a+592>>3]=1.0;if((r|0)>0?!((r|0)==6|(r|0)==10):0){mc(r,c[a+3884>>2]|0,q,+h[a+120>>3],l,m,+h[a+128>>3])}r=c[a+3260>>2]|0;do{if((r|0)==32){if((md(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==30){if((cd(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==29){if((od(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==31){if((fd(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else{q=+h[l>>3];s=+h[m>>3];if((c[a+3324>>2]|0)==2|(r|0)<1){if((ad(q,s,a,n,o)|0)==0){break}c[j>>2]=1;break}else{if((jc(q,s,a,n,o)|0)==0){break}c[j>>2]=1;break}}}while(0);r=c[a+9312>>2]|0;s=+h[n>>3];q=+h[o>>3];do{if((r|0)==0){Ze(a,s,q,f,g);o=c[j>>2]|0;if((o|0)==0){t=+h[f>>3];if(!(t<.5)?(u=+h[g>>3],!(u<.5)):0){if(!(t>+h[a+136>>3]+.5)?!(u>+h[a+144>>3]+.5):0){v=0;break}c[j>>2]=2;v=2;break}c[j>>2]=2;v=2}else{v=o}}else{ic(r,s,q,0,f,g,j);v=c[j>>2]|0}}while(0);c[a+3308>>2]=v;h[a+600>>3]=b;h[a+608>>3]=d;h[a+576>>3]=+h[f>>3];h[a+584>>3]=+h[g>>3];i=k;return}function jc(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+112|0;j=g+80|0;k=g+48|0;l=g+16|0;m=g+8|0;n=g;h[e>>3]=0.0;h[f>>3]=0.0;o=d+3924|0;if((c[o>>2]|0)!=137){p=d+3368|0;if((xd(c[d+3960>>2]|0,p,o)|0)==0){q=p}else{r=1;i=g;return r|0}}else{q=d+3368|0}p=d+3944|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;c[j+16>>2]=0;c[j+20>>2]=0;c[j+24>>2]=0;c[j+28>>2]=0;h[j+(c[p>>2]<<3)>>3]=a;h[j+(c[d+3948>>2]<<3)>>3]=b;p=l+16|0;c[l+0>>2]=0;c[l+4>>2]=0;c[l+8>>2]=0;c[l+12>>2]=0;h[p>>3]=1.0;h[l+24>>3]=1.0;s=k+16|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;h[s>>3]=1.0;h[k+24>>3]=1.0;s=yd(q,o,j,d+688|0,d+3984|0,m,n,d+4064|0,k,d+3956|0,l)|0;if((s|0)!=0){r=s;i=g;return r|0}h[e>>3]=+h[l>>3];h[f>>3]=+h[l+8>>3];b=+h[p>>3];if(((c[d+3260>>2]|0)+ -24|0)>>>0<3){h[d+592>>3]=b+-1.0;r=0;i=g;return r|0}else{h[d+592>>3]=b;r=0;i=g;return r|0}return 0}function kc(){return c[1528]|0}function lc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0;b=i;d=a+3316|0;e=c[d>>2]|0;f=(e|0)>2?2:e;if((f+ -1|0)>>>0>8){e=c[a+3320>>2]|0;c[d>>2]=e;g=e}else{g=f}f=aa(g<<3,g)|0;e=a+3976|0;d=c[e>>2]|0;if((d|0)==0){j=gg(f)|0;c[e>>2]=j;if((j|0)==0){i=b;return}else{k=j}}else{k=d}d=a+3980|0;if((c[d>>2]|0)==0?(j=gg(f)|0,c[d>>2]=j,(j|0)==0):0){i=b;return}j=a+3956|0;c[j>>2]=137;if((g|0)==3){l=k+0|0;m=l+72|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));f=c[e>>2]|0;h[f>>3]=+h[a+56>>3];h[f+8>>3]=+h[a+64>>3];h[f+24>>3]=+h[a+72>>3];h[f+32>>3]=+h[a+80>>3];h[f+64>>3]=1.0;n=f}else if((g|0)==2){h[k>>3]=+h[a+56>>3];h[k+8>>3]=+h[a+64>>3];h[k+16>>3]=+h[a+72>>3];h[k+24>>3]=+h[a+80>>3];n=k}else if((g|0)==4){l=k+0|0;m=l+128|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));l=c[e>>2]|0;h[l>>3]=+h[a+56>>3];h[l+8>>3]=+h[a+64>>3];h[l+32>>3]=+h[a+72>>3];h[l+40>>3]=+h[a+80>>3];h[l+80>>3]=1.0;h[l+120>>3]=1.0;n=l}else{n=k}Bd(g,n,c[d>>2]|0)|0;c[a+3964>>2]=a+616;c[a+3972>>2]=a+760;c[a+3968>>2]=a+832;c[j>>2]=137;i=b;return}function mc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=+c;d=+d;e=e|0;f=f|0;g=+g;var j=0,k=0,l=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0,s=0,t=0.0;j=i;i=i+32|0;k=j+24|0;l=j+16|0;m=j+8|0;n=j;if(c==0.0){o=(a|0)==2?1950.0:2.0e3}else{o=c}if(d==0.0){p=(b|0)==2?1950.0:2.0e3}else{p=d}q=(b|0)==11;r=(a|0)==1&q&o==2.0e3;d=r?o:(a|0)==11&q?o:p;q=r?b:a;a=(b|0)==1;r=(q|0)==11&a&d==2.0e3;p=r?d:o;s=r?b:q;if((s|0)==(b|0)&p==d){i=j;return}q=p!=d;if(q){if((s|0)==2&p!=1950.0){xc(p,1950.0,e,f)}if((s|0)==1&p!=2.0e3){yc(p,2.0e3,e,f)}}r=(b|0)==2;do{if(r){if((s|0)==3){sc(e,f);break}else if((s|0)==4){if(g>0.0){wc(e,f,g);h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);p=g+-1950.0;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{wc(e,f,1950.0);h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);h[e>>3]=+h[e>>3]+ +h[m>>3]*0.0;h[f>>3]=+h[f>>3]+ +h[n>>3]*0.0;break}}else if((s|0)==1){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);p=g+-1950.0;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);break}}else{break}}else{if((b|0)==4){if((s|0)==1){if(g>0.0){vc(e,f,g);break}else{vc(e,f,2.0e3);break}}else if((s|0)==3){uc(e,f);if(g>0.0){vc(e,f,g);break}else{vc(e,f,2.0e3);break}}else if((s|0)==2){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);p=g+-2.0e3;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];vc(e,f,g);break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);h[e>>3]=+h[e>>3]+ +h[m>>3]*-50.0;h[f>>3]=+h[f>>3]+ +h[n>>3]*-50.0;vc(e,f,1950.0);break}}else{break}}else if((b|0)==3){if((s|0)==4){if(g>0.0){wc(e,f,g)}else{wc(e,f,2.0e3)}tc(e,f);break}else if((s|0)==2){rc(e,f);break}else if((s|0)==1){tc(e,f);break}else{break}}else if((b|0)==1){if((s|0)==3){uc(e,f);break}else if((s|0)==4){if(g>0.0){wc(e,f,g);break}else{wc(e,f,2.0e3);break}}else if((s|0)==2){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);p=g+-2.0e3;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);break}}else{break}}else{break}}}while(0);if(q){if(r&d!=1950.0){xc(1950.0,d,e,f)}if(a&d!=2.0e3){yc(2.0e3,d,e,f)}}d=+h[f>>3];do{if(!(d>90.0)){if(d<-90.0){h[f>>3]=-180.0-d;g=+h[e>>3]+180.0;h[e>>3]=g;t=g;break}else{t=+h[e>>3];break}}else{h[f>>3]=180.0-d;g=+h[e>>3]+180.0;h[e>>3]=g;t=g}}while(0);if(t>360.0){h[e>>3]=t+-360.0;i=j;return}if(!(t<0.0)){i=j;return}h[e>>3]=t+360.0;i=j;return}function nc(b){b=b|0;var c=0,d=0,e=0,f=0.0;c=i;d=a[b]|0;a:do{if((((((!(d<<24>>24==106|d<<24>>24==74)?(yg(b,6688)|0)!=0:0)?(yg(b,6696)|0)!=0:0)?(yg(b,6704)|0)!=0:0)?(yg(b,6712)|0)!=0:0)?(Ag(b,6720,3)|0)!=0:0)?(Ag(b,6728,3)|0)!=0:0){if((((!(d<<24>>24==98|d<<24>>24==66)?(yg(b,6736)|0)!=0:0)?(yg(b,6744)|0)!=0:0)?(Ag(b,6752,3)|0)!=0:0)?(Ag(b,6760,3)|0)!=0:0){switch(d<<24>>24){case 105:case 73:{e=11;break a;break};case 108:case 76:{e=6;break a;break};case 101:case 69:{e=4;break a;break};case 97:case 65:{e=5;break a;break};case 110:case 78:{e=7;break a;break};case 103:case 71:{e=3;break a;break};default:{if((zg(b,6768,5)|0)==0){e=10;break a}if(d<<24>>24==112|d<<24>>24==80){e=9;break a}if((Gc(b)|0)==0){e=-1;break a}f=+ug(b);if(f>1980.0){e=1;break a}e=f>1900.0?2:-1;break a}}}else{e=2}}else{e=1}}while(0);i=c;return e|0}function oc(b){b=b|0;var c=0,d=0,e=0.0;c=i;d=a[b]|0;if(!(d<<24>>24==98|d<<24>>24==66|d<<24>>24==106|d<<24>>24==74)){if((Ag(b,6752,3)|0)!=0?(Ag(b,6760,3)|0)!=0:0){if((((Ag(b,6720,3)|0)!=0?(Ag(b,6728,3)|0)!=0:0)?(Ag(b,6704,4)|0)!=0:0)?(Ag(b,6712,4)|0)!=0:0){if((d+ -49<<24>>24&255)<2){e=+ug(b)}else{e=0.0}}else{e=2.0e3}}else{e=1950.0}}else{e=+ug(b+1|0)}i=c;return+e}function pc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0;g=i;i=i+48|0;j=g;k=+h[a>>3]*3.141592653589793/180.0;l=+h[b>>3]*3.141592653589793/180.0;m=+h[c>>3]*36.0e4;n=+h[d>>3]*36.0e4;o=+T(+k);p=+S(+k);k=+T(+l);q=+S(+l);l=p*q;r=o*q;if(m!=0.0|n!=0.0){s=-(m*r)-n*p*k;t=m*l-n*o*k;u=n*q}else{s=0.0;t=0.0;u=0.0}v=0;do{h[j+(v<<3)>>3]=+h[6776+(v*48|0)>>3]*l+0.0+ +h[6784+(v*48|0)>>3]*r+ +h[6792+(v*48|0)>>3]*k+ +h[6800+(v*48|0)>>3]*s+ +h[6808+(v*48|0)>>3]*t+ +h[6816+(v*48|0)>>3]*u;v=v+1|0}while((v|0)!=6);u=+h[j>>3];t=+h[j+8>>3];s=+h[j+16>>3];k=+Q(+(u*u+t*t+s*s));r=u*-162557.0e-11+t*-3.1919e-7+s*-1.3843e-7;l=u*r;q=u+k*-162557.0e-11-l;o=t*r;p=t+k*-3.1919e-7-o;w=s*r;r=s+k*-1.3843e-7-w;k=+Q(+(r*r+(q*q+p*p)));p=u*.001245+t*-.00158+s*-659.0e-6;q=u+k*-162557.0e-11-l;l=t+k*-3.1919e-7-o;o=s+k*-1.3843e-7-w;w=+h[j+24>>3]+k*.001245-p*q;s=k*-.00158+ +h[j+32>>3]-p*l;t=k*-659.0e-6+ +h[j+40>>3]-p*o;p=q*q+l*l;u=+Q(+p);if(!(q==0.0&l==0.0)){r=+Y(+l,+q);if(r<0.0){x=r+6.283185307179586}else{x=r}}else{x=0.0}r=+Y(+o,+u);if(u>1.0e-30){y=(t*p-o*(q*w+l*s))/(u*(o*o+p));z=(q*s-l*w)/p}else{y=n;z=m}m=+h[e>>3];if(!(m>1.0e-30)){A=x*180.0;B=A/3.141592653589793;h[a>>3]=B;C=r*180.0;D=C/3.141592653589793;h[b>>3]=D;E=z/36.0e4;h[c>>3]=E;F=y/36.0e4;h[d>>3]=F;i=g;return}h[f>>3]=(o*t+(q*w+l*s))/(k*m*21.095);h[e>>3]=+h[e>>3]/k;A=x*180.0;B=A/3.141592653589793;h[a>>3]=B;C=r*180.0;D=C/3.141592653589793;h[b>>3]=D;E=z/36.0e4;h[c>>3]=E;F=y/36.0e4;h[d>>3]=F;i=g;return}function qc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0;g=i;i=i+48|0;j=g;k=+h[a>>3]*3.141592653589793/180.0;l=+h[b>>3]*3.141592653589793/180.0;m=+h[c>>3]*36.0e4;n=+h[d>>3]*36.0e4;o=+T(+k);p=+S(+k);k=+T(+l);q=+S(+l);l=p*q;r=o*q;s=+h[f>>3];t=+h[e>>3];u=s*21.095*t;if(!(m!=0.0|n!=0.0)?!(s!=0.0&t!=0.0):0){v=-.001245;w=.00158;x=659.0e-6}else{v=-(m*r)-n*p*k+u*l+-.001245;w=m*l-n*o*k+u*r+.00158;x=n*q+u*k+659.0e-6}u=l*-162557.0e-11+r*-3.1919e-7+k*-1.3843e-7;q=u*l+(l+162557.0e-11);o=u*r+(r+3.1919e-7);p=u*k+(k+1.3843e-7);u=l*.001245+r*-.00158+k*-659.0e-6;s=v+u*l;l=w+u*r;r=x+u*k;y=0;do{h[j+(y<<3)>>3]=+h[7064+(y*48|0)>>3]*q+0.0+ +h[7072+(y*48|0)>>3]*o+ +h[7080+(y*48|0)>>3]*p+ +h[7088+(y*48|0)>>3]*s+ +h[7096+(y*48|0)>>3]*l+ +h[7104+(y*48|0)>>3]*r;y=y+1|0}while((y|0)!=6);r=+h[j>>3];l=+h[j+8>>3];s=+h[j+16>>3];p=+h[j+24>>3];o=+h[j+32>>3];q=+h[j+40>>3];k=r*r+l*l;u=+Q(+k);x=k+s*s;w=+Q(+x);v=r*p+l*o;z=v+s*q;if(!(r==0.0&l==0.0)){A=+Y(+l,+r);if(A<0.0){B=A+6.283185307179586}else{B=A}}else{B=0.0}A=+Y(+s,+u);if(u>1.0e-30){C=(k*q-s*v)/(x*u);D=(r*o-l*p)/k}else{C=n;D=m}if(!(t>1.0e-30)){E=B*180.0;F=E/3.141592653589793;h[a>>3]=F;G=A*180.0;H=G/3.141592653589793;h[b>>3]=H;I=D/36.0e4;h[c>>3]=I;J=C/36.0e4;h[d>>3]=J;i=g;return}h[f>>3]=z/(w*t*21.095);h[e>>3]=+h[e>>3]/w;E=B*180.0;F=E/3.141592653589793;h[a>>3]=F;G=A*180.0;H=G/3.141592653589793;h[b>>3]=H;I=D/36.0e4;h[c>>3]=I;J=C/36.0e4;h[d>>3]=J;i=g;return}function rc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0,x=0,y=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.066988739415+q*-.872755765852+l*-.483538914632;n=p*.492728466075+q*-.45034695802+l*.744584633283;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.867600811151+q*-.188374601723+l*.460199784784),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}n=g/15.0;d=~~n;g=(n- +(d|0))*60.0;b=~~g;if(j<0.0){u=45;v=-j}else{u=43;v=j}w=~~v;j=(v- +(w|0))*60.0;x=~~j;y=gg(32)|0;c[f>>2]=d;c[f+4>>2]=b;d=f+8|0;h[k>>3]=(g- +(b|0))*60.0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[f+16>>2]=u;c[f+20>>2]=w;c[f+24>>2]=x;w=f+28|0;h[k>>3]=(j- +(x|0))*60.0;c[w>>2]=c[k>>2];c[w+4>>2]=c[k+4>>2];Na(y|0,7648,f|0)|0;w=y+6|0;if((a[w]|0)==32){a[w]=48}w=y+20|0;if((a[w]|0)==32){a[w]=48}w=c[o>>2]|0;c[f>>2]=y;za(w|0,7360,f|0)|0;h[k>>3]=s;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];x=f+8|0;h[k>>3]=t;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];za(w|0,7392,f|0)|0;hg(y);i=e;return}function sc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0.0,x=0,y=0,z=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.066988739415+q*.492728466075+l*-.867600811151;n=p*-.872755765852+q*-.45034695802+l*-.188374601723;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.483538914632+q*.744584633283+l*.460199784784),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}d=c[o>>2]|0;h[k>>3]=g;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];b=f+8|0;h[k>>3]=j;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];za(d|0,7432,f|0)|0;j=s/15.0;b=~~j;s=(j- +(b|0))*60.0;u=~~s;if(t<0.0){v=45;w=-t}else{v=43;w=t}x=~~w;t=(w- +(x|0))*60.0;y=~~t;z=gg(32)|0;c[f>>2]=b;c[f+4>>2]=u;b=f+8|0;h[k>>3]=(s- +(u|0))*60.0;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];c[f+16>>2]=v;c[f+20>>2]=x;c[f+24>>2]=y;x=f+28|0;h[k>>3]=(t- +(y|0))*60.0;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];Na(z|0,7648,f|0)|0;x=z+6|0;if((a[x]|0)==32){a[x]=48}x=z+20|0;if((a[x]|0)==32){a[x]=48}c[f>>2]=z;za(d|0,7472,f|0)|0;hg(z);i=e;return}function tc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0,x=0,y=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.054875539726+q*-.87343710801+l*-.483834985808;n=p*.494109453312+q*-.444829589425+l*.74698225181;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.867666135858+q*-.198076386122+l*.455983795705),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}n=g/15.0;d=~~n;g=(n- +(d|0))*60.0;b=~~g;if(j<0.0){u=45;v=-j}else{u=43;v=j}w=~~v;j=(v- +(w|0))*60.0;x=~~j;y=gg(32)|0;c[f>>2]=d;c[f+4>>2]=b;d=f+8|0;h[k>>3]=(g- +(b|0))*60.0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[f+16>>2]=u;c[f+20>>2]=w;c[f+24>>2]=x;w=f+28|0;h[k>>3]=(j- +(x|0))*60.0;c[w>>2]=c[k>>2];c[w+4>>2]=c[k+4>>2];Na(y|0,7648,f|0)|0;w=y+6|0;if((a[w]|0)==32){a[w]=48}w=y+20|0;if((a[w]|0)==32){a[w]=48}w=c[o>>2]|0;c[f>>2]=y;za(w|0,7504,f|0)|0;h[k>>3]=s;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];x=f+8|0;h[k>>3]=t;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];za(w|0,7536,f|0)|0;hg(y);i=e;return}function uc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0.0,x=0,y=0,z=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.054875539726+q*.494109453312+l*-.867666135858;n=p*-.87343710801+q*-.444829589425+l*-.198076386122;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.483834985808+q*.74698225181+l*.455983795705),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}d=c[o>>2]|0;h[k>>3]=g;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];b=f+8|0;h[k>>3]=j;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];za(d|0,7576,f|0)|0;j=s/15.0;b=~~j;s=(j- +(b|0))*60.0;u=~~s;if(t<0.0){v=45;w=-t}else{v=43;w=t}x=~~w;t=(w- +(x|0))*60.0;y=~~t;z=gg(32)|0;c[f>>2]=b;c[f+4>>2]=u;b=f+8|0;h[k>>3]=(s- +(u|0))*60.0;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];c[f+16>>2]=v;c[f+20>>2]=x;c[f+24>>2]=y;x=f+28|0;h[k>>3]=(t- +(y|0))*60.0;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];Na(z|0,7648,f|0)|0;x=z+6|0;if((a[x]|0)==32){a[x]=48}x=z+20|0;if((a[x]|0)==32){a[x]=48}c[f>>2]=z;za(d|0,7616,f|0)|0;hg(z);i=e;return}function vc(a,b,c){a=a|0;b=b|0;c=+c;var d=0,e=0,f=0.0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0;d=i;i=i+80|0;e=d;if(c!=2.0e3){yc(2.0e3,c,a,b)}f=+h[a>>3]*3.141592653589793/180.0;g=+h[b>>3]*3.141592653589793/180.0;j=+S(+g);k=+S(+f)*j;l=j*+T(+f);f=+T(+g);g=(c+-2.0e3)*.01;zc(1,(g*(g*(g*.001813+-59.0e-5)+-46.815)+84381.448)*48481368110953.0e-19,0.0,0.0,e);g=+h[e>>3]*k+0.0+ +h[e+8>>3]*l+ +h[e+16>>3]*f;c=+h[e+24>>3]*k+0.0+ +h[e+32>>3]*l+ +h[e+40>>3]*f;j=+h[e+48>>3]*k+0.0+ +h[e+56>>3]*l+ +h[e+64>>3]*f;f=+Y(+c,+g);if(f<0.0){m=f+6.283185307179586}else{m=f}if(!(m>6.283185307179586)){n=m;o=g*g;p=c*c;q=o+p;r=+Q(+q);s=+Y(+j,+r);t=n*180.0;u=t/3.141592653589793;h[a>>3]=u;v=s*180.0;w=v/3.141592653589793;h[b>>3]=w;i=d;return}n=m+-6.283185307179586;o=g*g;p=c*c;q=o+p;r=+Q(+q);s=+Y(+j,+r);t=n*180.0;u=t/3.141592653589793;h[a>>3]=u;v=s*180.0;w=v/3.141592653589793;h[b>>3]=w;i=d;return}function wc(a,b,c){a=a|0;b=b|0;c=+c;var d=0,e=0,f=0.0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0;d=i;i=i+80|0;e=d;f=+h[a>>3]*3.141592653589793/180.0;g=+h[b>>3]*3.141592653589793/180.0;j=+S(+g);k=+S(+f)*j;l=j*+T(+f);f=+T(+g);g=(c+-2.0e3)*.01;zc(1,(g*(g*(g*.001813+-59.0e-5)+-46.815)+84381.448)*48481368110953.0e-19,0.0,0.0,e);g=+h[e>>3]*k+0.0+ +h[e+24>>3]*l+ +h[e+48>>3]*f;j=+h[e+8>>3]*k+0.0+ +h[e+32>>3]*l+ +h[e+56>>3]*f;m=+Y(+j,+g);if(m<0.0){n=m+6.283185307179586}else{n=m}if(n>6.283185307179586){o=n+-6.283185307179586}else{o=n}n=+Y(+(+h[e+16>>3]*k+0.0+ +h[e+40>>3]*l+ +h[e+64>>3]*f),+(+Q(+(g*g+j*j))));h[a>>3]=o*180.0/3.141592653589793;h[b>>3]=n*180.0/3.141592653589793;if(!(c!=2.0e3)){i=d;return}yc(c,2.0e3,a,b);i=d;return}function xc(a,b,c,d){a=+a;b=+b;c=c|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;e=i;i=i+80|0;f=e;g=+h[c>>3]*3.141592653589793/180.0;j=+h[d>>3]*3.141592653589793/180.0;k=(a+-1850.0)/100.0;l=(b-a)/100.0;a=l*48481368110953.0e-19;b=k*(k*59.0e-6+1.3972)+2303.5548;m=k*365.0e-6;zc(323,-(a*(b+l*(.30242-k*269.0e-6+l*.017996))),a*(k*(-.85294-m)+2005.1125+l*(-.42647-m-l*.041802)),-(a*(b+l*(k*387.0e-6+1.09478+l*.018324))),f);l=+S(+j);k=+S(+g)*l;b=l*+T(+g);g=+T(+j);j=+h[f>>3]*k+0.0+ +h[f+8>>3]*b+ +h[f+16>>3]*g;l=+h[f+24>>3]*k+0.0+ +h[f+32>>3]*b+ +h[f+40>>3]*g;a=+h[f+48>>3]*k+0.0+ +h[f+56>>3]*b+ +h[f+64>>3]*g;g=+Y(+l,+j);if(g<0.0){n=g+6.283185307179586}else{n=g}if(!(n>6.283185307179586)){o=n;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}o=n+-6.283185307179586;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}function yc(a,b,c,d){a=+a;b=+b;c=c|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;e=i;i=i+80|0;f=e;g=+h[c>>3]*3.141592653589793/180.0;j=+h[d>>3]*3.141592653589793/180.0;k=(a+-2.0e3)/100.0;l=(b-a)/100.0;a=l*48481368110953.0e-19;b=k*(1.39656-k*139.0e-6)+2306.2181;m=k*217.0e-6;zc(323,-(a*(b+l*(.30188-k*344.0e-6+l*.017998))),a*(k*(-.8533-m)+2004.3109+l*(-.42665-m-l*.041833)),-(a*(b+l*(k*66.0e-6+1.09468+l*.018203))),f);l=+S(+j);k=+S(+g)*l;b=l*+T(+g);g=+T(+j);j=k*+h[f>>3]+0.0+b*+h[f+8>>3]+g*+h[f+16>>3];l=k*+h[f+24>>3]+0.0+b*+h[f+32>>3]+g*+h[f+40>>3];a=k*+h[f+48>>3]+0.0+b*+h[f+56>>3]+g*+h[f+64>>3];g=+Y(+l,+j);if(g<0.0){n=g+6.283185307179586}else{n=g}if(!(n>6.283185307179586)){o=n;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}o=n+-6.283185307179586;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}function zc(a,b,d,e,f){a=a|0;b=+b;d=+d;e=+e;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0,B=0.0,C=0.0,D=0,E=0.0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0,L=0.0,M=0,N=0.0;g=i;i=i+192|0;j=g+144|0;k=g+72|0;l=g;m=g+168|0;n=f+8|0;h[f>>3]=1.0;o=f+16|0;h[n>>3]=0.0;h[o>>3]=0.0;p=f+24|0;h[p>>3]=0.0;h[f+32>>3]=1.0;h[f+40>>3]=0.0;h[f+48>>3]=0.0;h[f+56>>3]=0.0;h[f+64>>3]=1.0;q=(a|0)/100|0;c[m>>2]=q;if((a|0)>99){r=(aa(q,-100)|0)+a|0;s=1}else{r=a;s=0}a=(r|0)/10|0;c[m+(s<<2)>>2]=a;if((r|0)>9){t=(aa(a,-10)|0)+r|0;u=s+1|0}else{t=r;u=s}c[m+(u<<2)>>2]=t;s=((t|0)>0)+u|0;h[j>>3]=b;h[j+8>>3]=d;h[j+16>>3]=e;if((s|0)<=0){i=g;return}u=l+32|0;t=l+40|0;r=l+56|0;a=l+64|0;q=l+16|0;v=l+48|0;w=l+8|0;x=l+24|0;y=k+8|0;e=b;b=1.0;d=0.0;z=1.0;A=0;while(1){h[l>>3]=1.0;h[l+8>>3]=0.0;h[l+16>>3]=0.0;h[l+24>>3]=0.0;h[l+32>>3]=1.0;h[l+40>>3]=0.0;h[l+48>>3]=0.0;h[l+56>>3]=0.0;h[l+64>>3]=1.0;B=+T(+e);C=+S(+e);D=c[m+(A<<2)>>2]|0;do{if((D|0)!=1){h[l>>3]=C;if((D|0)==2){h[q>>3]=-B;h[v>>3]=B;h[a>>3]=C;break}else{h[w>>3]=B;h[x>>3]=-B;h[u>>3]=C;break}}else{h[u>>3]=C;h[t>>3]=B;h[r>>3]=-B;h[a>>3]=C}}while(0);C=+h[p>>3];B=+h[n>>3];E=+h[f+32>>3];F=+h[f+56>>3];G=+h[f+16>>3];H=+h[f+40>>3];D=0;do{I=D*3|0;J=+h[l+(I<<3)>>3];K=I+1|0;L=+h[l+(K<<3)>>3];M=I+2|0;N=+h[l+(M<<3)>>3];h[k+(I<<3)>>3]=J*b+0.0+L*C+N*d;h[k+(K<<3)>>3]=J*B+0.0+L*E+N*F;h[k+(M<<3)>>3]=J*G+0.0+L*H+N*z;D=D+1|0}while((D|0)!=3);H=+h[k>>3];h[f>>3]=H;h[n>>3]=+h[y>>3];h[o>>3]=+h[k+16>>3];h[f+24>>3]=+h[k+24>>3];h[f+32>>3]=+h[k+32>>3];h[f+40>>3]=+h[k+40>>3];G=+h[k+48>>3];h[f+48>>3]=G;h[f+56>>3]=+h[k+56>>3];F=+h[k+64>>3];h[f+64>>3]=F;D=A+1|0;if((D|0)==(s|0)){break}e=+h[j+(D<<3)>>3];b=H;d=G;z=F;A=D}i=g;return}function Ac(a,b,c,d){a=+a;b=+b;c=+c;d=d|0;var e=0.0;e=a*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+a);h[d>>3]=+S(+e)*c*b;h[d+8>>3]=b*+T(+e)*c;h[d+16>>3]=+T(+a)*c;return}function Bc(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;if((b|0)>0){e=b}else{c[1922]=0;e=(Cc(a,7696)|0)+80-a|0}c[1922]=e;i=d;return e|0}function Cc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;e=i;f=c[1922]|0;g=(f|0)==0?256e3:f;if((g|0)>0){h=0}else{j=0;i=e;return j|0}while(1){f=h+1|0;if((a[b+h|0]|0)<1){k=h;break}if((f|0)<(g|0)){h=f}else{k=f;break}}h=b+k|0;g=h;if((k|0)<=0){j=0;i=e;return j|0}k=b;f=b;a:while(1){b=Rc(f,d,g-f|0)|0;if((b|0)==0){j=0;l=17;break}m=(b-k|0)%80|0;n=a[b+(Dg(d|0)|0)|0]|0;do{if((m|0)<=7){if(n<<24>>24>32?!(n<<24>>24==61|n<<24>>24==127):0){o=b+1|0;break}p=0-m|0;q=b+p|0;if((p|0)<0){p=b+1|0;r=f;s=q;while(1){t=(a[s]|0)==32?r:p;u=s+1|0;if(u>>>0>>0){r=t;s=u}else{v=t;break}}}else{v=f}if(b>>>0>>0){o=v}else{j=q;l=17;break a}}else{o=b+1|0}}while(0);if(o>>>0>>0){f=o}else{j=0;l=17;break}}if((l|0)==17){i=e;return j|0}return 0}function Dc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;i=i+16|0;g=f;if((a[d]|0)<64){h=Ec(b,c,e)|0;i=f;return h|0}else{Lg(g|0,c|0)|0;j=Dg(c|0)|0;a[g+j|0]=a[d]|0;a[g+(j+1)|0]=0;h=Ec(b,g,e)|0;i=f;return h|0}return 0}function Ec(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0.0,k=0.0;f=i;g=Fc(b,d)|0;if((g|0)==0){h=0;i=f;return h|0}d=(a[g]|0)==35?g+1|0:g;if((Dg(d|0)|0)>81){Hg(7704,d|0,81)|0;a[7785|0]=0}else{Lg(7704,d|0)|0}if((Gc(7704)|0)==2){d=$f(7704,68)|0;if((d|0)!=0){a[d]=101}d=$f(7704,100)|0;if((d|0)!=0){a[d]=101}d=$f(7704,69)|0;if((d|0)!=0){a[d]=101}}j=+ug(7704);k=j+.001;if(k>2147483647.0){c[e>>2]=2147483647;h=1;i=f;return h|0}if(j>=0.0){c[e>>2]=~~k;h=1;i=f;return h|0}k=j+-.001;if(k<-2147483648.0){c[e>>2]=-2147483648;h=1;i=f;return h|0}else{c[e>>2]=~~k;h=1;i=f;return h|0}return 0}function Fc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;e=i;i=i+208|0;f=e+194|0;g=e+8|0;h=e+2|0;j=e+4|0;k=e+196|0;l=e;m=e+6|0;n=e+112|0;o=e+12|0;a[g]=39;a[g+1|0]=0;a[h]=34;a[h+1|0]=0;a[j]=91;a[j+1|0]=0;a[m]=44;a[m+1|0]=0;a[k]=93;a[k+1|0]=0;a[l]=47;a[l+1|0]=0;Hg(n|0,d|0,80)|0;d=Dg(n|0)|0;p=Dg(j|0)|0;a:do{if((p|0)!=0){if((d|0)!=0?(q=p+ -1|0,r=a[j+q|0]|0,s=d+1-p|0,t=n+s|0,(s|0)>0):0){s=(p|0)==1;u=(p|0)<3;v=n;do{b:do{if((a[v]|0)==91){if(s){w=v;x=23;break a}if((a[v+q|0]|0)==r<<24>>24){if(u){w=v;x=23;break a}else{y=1}while(1){z=y+1|0;if((a[v+y|0]|0)!=(a[j+y|0]|0)){break b}if((z|0)<(p|0)){y=z}else{w=v;x=23;break a}}}}}while(0);v=v+1|0}while(v>>>0>>0)}t=Dg(n|0)|0;v=Dg(m|0)|0;if((v|0)!=0){if((t|0)!=0?(u=v+ -1|0,r=a[m+u|0]|0,q=t+1-v|0,t=n+q|0,(q|0)>0):0){q=(v|0)==1;s=(v|0)<3;z=n;while(1){c:do{if((a[z]|0)==44){if(q){w=z;x=23;break a}if((a[z+u|0]|0)==r<<24>>24){if(s){w=z;x=23;break a}else{A=1}while(1){B=A+1|0;if((a[z+A|0]|0)!=(a[m+A|0]|0)){break c}if((B|0)<(v|0)){A=B}else{w=z;x=23;break a}}}}}while(0);B=z+1|0;if(B>>>0>>0){z=B}else{C=0;break}}}else{C=0}}else{w=n;x=23}}else{w=n;x=23}}while(0);if((x|0)==23){a[w]=0;C=w+1|0}w=Cc(b,n)|0;if((w|0)==0){D=0;i=e;return D|0}n=o+0|0;b=n+100|0;do{a[n]=0;n=n+1|0}while((n|0)<(b|0));Hg(o|0,w|0,80)|0;w=Dg(o|0)|0;n=Dg(g|0)|0;d:do{if((n|0)!=0){if((w|0)!=0?(b=a[g]|0,A=n+ -1|0,m=a[g+A|0]|0,y=w+1-n|0,p=o+y|0,(y|0)>0):0){y=(n|0)==1;j=(n|0)<3;d=o;while(1){e:do{if((a[d]|0)==b<<24>>24){if(y){E=d;break d}if((a[d+A|0]|0)==m<<24>>24){if(j){E=d;break d}else{F=1}while(1){z=F+1|0;if((a[d+F|0]|0)!=(a[g+F|0]|0)){break e}if((z|0)<(n|0)){F=z}else{E=d;break d}}}}}while(0);z=d+1|0;if(z>>>0

    >>0){d=z}else{E=0;break}}}else{E=0}}else{E=o}}while(0);F=Dg(o|0)|0;n=Dg(l|0)|0;f:do{if((n|0)!=0){if((F|0)!=0?(w=a[l]|0,d=n+ -1|0,p=a[l+d|0]|0,j=F+1-n|0,m=o+j|0,(j|0)>0):0){j=(n|0)==1;A=(n|0)<3;y=o;while(1){g:do{if((a[y]|0)==w<<24>>24){if(j){G=y;break f}if((a[y+d|0]|0)==p<<24>>24){if(A){G=y;break f}else{H=1}while(1){b=H+1|0;if((a[y+H|0]|0)!=(a[l+H|0]|0)){break g}if((b|0)<(n|0)){H=b}else{G=y;break f}}}}}while(0);b=y+1|0;if(b>>>0>>0){y=b}else{G=0;break}}}else{G=0}}else{G=o}}while(0);h:do{if((E|0)==0){H=Dg(o|0)|0;n=Dg(h|0)|0;i:do{if((n|0)==0){I=o}else{if((H|0)==0){x=116;break h}l=a[h]|0;F=n+ -1|0;y=a[h+F|0]|0;m=H+1-n|0;A=o+m|0;if((m|0)<=0){x=116;break h}m=(n|0)==1;p=(n|0)<3;d=o;while(1){j:do{if((a[d]|0)==l<<24>>24){if(m){I=d;break i}if((a[d+F|0]|0)==y<<24>>24){if(p){I=d;break i}else{J=1}while(1){j=J+1|0;if((a[d+J|0]|0)!=(a[h+J|0]|0)){break j}if((j|0)<(n|0)){J=j}else{I=d;break i}}}}}while(0);j=d+1|0;if(j>>>0>>0){d=j}else{x=116;break h}}}}while(0);if((G|0)!=0&I>>>0>>0){n=I+1|0;H=Dg(n|0)|0;d=Dg(h|0)|0;if((d|0)==0){K=I;L=n;x=115;break}if((H|0)!=0?(A=a[h]|0,p=d+ -1|0,y=a[h+p|0]|0,F=H+1-d|0,H=I+(F+1)|0,(F|0)>0):0){F=(d|0)==1;m=(d|0)<3;l=n;while(1){k:do{if((a[l]|0)==A<<24>>24){if(F){K=I;L=l;x=115;break h}if((a[l+p|0]|0)==y<<24>>24){if(m){K=I;L=l;x=115;break h}else{M=1}while(1){n=M+1|0;if((a[l+M|0]|0)!=(a[h+M|0]|0)){break k}if((n|0)<(d|0)){M=n}else{K=I;L=l;x=115;break h}}}}}while(0);n=l+1|0;if(n>>>0>>0){l=n}else{N=G;break}}}else{N=G}while(1){l=N+ -1|0;if((a[l]|0)==32){N=l}else{K=I;L=N;x=115;break h}}}if((G|0)==0){l=I+1|0;H=Dg(l|0)|0;d=Dg(h|0)|0;if((d|0)==0){K=I;L=l;x=115}else{if((H|0)!=0?(m=a[h]|0,y=d+ -1|0,p=a[h+y|0]|0,F=H+1-d|0,H=I+(F+1)|0,(F|0)>0):0){F=(d|0)==1;A=(d|0)<3;n=l;do{l:do{if((a[n]|0)==m<<24>>24){if(F){K=I;L=n;x=115;break h}if((a[n+y|0]|0)==p<<24>>24){if(A){K=I;L=n;x=115;break h}else{O=1}while(1){l=O+1|0;if((a[n+O|0]|0)!=(a[h+O|0]|0)){break l}if((l|0)<(d|0)){O=l}else{K=I;L=n;x=115;break h}}}}}while(0);n=n+1|0}while(n>>>0>>0)}H=o+79|0;while(1){if((a[H]|0)==32){H=H+ -1|0}else{break}}K=I;L=H+1|0;x=115}}else{x=116}}else{if((G|0)!=0&E>>>0>>0){n=E+1|0;d=Dg(n|0)|0;A=Dg(g|0)|0;if((A|0)==0){K=E;L=n;x=115;break}if((d|0)!=0?(p=a[g]|0,y=A+ -1|0,F=a[g+y|0]|0,m=d+1-A|0,d=E+(m+1)|0,(m|0)>0):0){m=(A|0)==1;l=(A|0)<3;j=n;while(1){m:do{if((a[j]|0)==p<<24>>24){if(m){K=E;L=j;x=115;break h}if((a[j+y|0]|0)==F<<24>>24){if(l){K=E;L=j;x=115;break h}else{P=1}while(1){n=P+1|0;if((a[j+P|0]|0)!=(a[g+P|0]|0)){break m}if((n|0)<(A|0)){P=n}else{K=E;L=j;x=115;break h}}}}}while(0);n=j+1|0;if(n>>>0>>0){j=n}else{Q=G;break}}}else{Q=G}while(1){j=Q+ -1|0;if((a[j]|0)==32){Q=j}else{K=E;L=Q;x=115;break h}}}if((G|0)==0){j=E+1|0;d=Dg(j|0)|0;A=Dg(g|0)|0;if((A|0)==0){K=E;L=j;x=115}else{if((d|0)!=0?(l=a[g]|0,F=A+ -1|0,y=a[g+F|0]|0,m=d+1-A|0,d=E+(m+1)|0,(m|0)>0):0){m=(A|0)==1;p=(A|0)<3;H=j;do{n:do{if((a[H]|0)==l<<24>>24){if(m){K=E;L=H;x=115;break h}if((a[H+F|0]|0)==y<<24>>24){if(p){K=E;L=H;x=115;break h}else{R=1}while(1){j=R+1|0;if((a[H+R|0]|0)!=(a[g+R|0]|0)){break n}if((j|0)<(A|0)){R=j}else{K=E;L=H;x=115;break h}}}}}while(0);H=H+1|0}while(H>>>0>>0)}d=o+79|0;while(1){if((a[d]|0)==32){d=d+ -1|0}else{break}}K=E;L=d+1|0;x=115}}else{x=116}}}while(0);if((x|0)==115){S=K+1|0;T=L}else if((x|0)==116){L=Dg(o|0)|0;o:do{if((L|0)!=0?(K=o+L|0,(L|0)>0):0){E=o;while(1){if((a[E]|0)==61){U=E;break o}R=E+1|0;if(R>>>0>>0){E=R}else{U=0;break}}}else{U=0}}while(0);L=(U|0)==0?o+9|0:U+1|0;U=Dg(o|0)|0;p:do{if((U|0)!=0?(E=o+U|0,(U|0)>0):0){K=o;while(1){if((a[K]|0)==47){V=K;break p}d=K+1|0;if(d>>>0>>0){K=d}else{V=0;break}}}else{V=0}}while(0);S=L;T=(V|0)==0?o+79|0:V}if((c[1968]|0)==0){V=S;while(1){if((a[V]|0)==32&V>>>0>>0){V=V+1|0}else{W=V;break}}}else{W=S}a[T]=0;q:do{if((c[1968]|0)==0){S=T;while(1){V=S+ -1|0;o=a[V]|0;if(!(o<<24>>24==13|o<<24>>24==32)){break q}if(!(V>>>0>W>>>0)){break q}a[V]=0;S=V}}}while(0);T=(yg(W,7960)|0)==0;S=T?W+1|0:W;Lg(7880,S|0)|0;if((C|0)==0){D=7880;i=e;return D|0}W=Dg(C|0)|0;T=Dg(k|0)|0;r:do{if((T|0)!=0){if((W|0)!=0?(V=a[k]|0,o=T+ -1|0,L=a[k+o|0]|0,U=W+1-T|0,K=C+U|0,(U|0)>0):0){U=(T|0)==1;E=(T|0)<3;d=C;s:while(1){t:do{if((a[d]|0)==V<<24>>24){if(U){break s}if((a[d+o|0]|0)==L<<24>>24){if(E){break s}else{X=1}while(1){R=X+1|0;if((a[d+X|0]|0)!=(a[k+X|0]|0)){break t}if((R|0)<(T|0)){X=R}else{break s}}}}}while(0);R=d+1|0;if(R>>>0>>0){d=R}else{break r}}if((d|0)!=0){Y=d;x=144}}}else{Y=C;x=144}}while(0);if((x|0)==144){a[Y]=0}if((Gc(C)|0)==0){Y=Dg(C|0)|0;if((Y|0)>0){x=0;do{X=C+x|0;T=a[X]|0;if((T+ -65<<24>>24&255)<26){a[X]=(T&255)+32}x=x+1|0}while((x|0)!=(Y|0))}Y=_c(7880,C)|0;if((Y|0)==0){D=0;i=e;return D|0}Lg(7880,Y|0)|0;D=7880;i=e;return D|0}Y=vg(C)|0;a[f]=32;a[f+1|0]=0;if((Y|0)>0){C=1;x=S;while(1){Z=fg(x,f)|0;if((C|0)==(Y|0)){break}else{C=C+1|0;x=0}}if((Z|0)==0){D=0;i=e;return D|0}Lg(7880,Z|0)|0;D=7880;i=e;return D|0}if((Y|0)>=0){D=7880;i=e;return D|0}Z=0-Y|0;u:do{if((Z|0)<=1){if((S|0)==0){D=0;i=e;return D|0}else{_=S}}else{Y=1;x=S;while(1){C=$f(x,32)|0;if((C|0)==0){D=0;break}f=C+1|0;C=Y+1|0;if((C|0)<(Z|0)){Y=C;x=f}else{_=f;break u}}i=e;return D|0}}while(0);Lg(7880,_|0)|0;D=7880;i=e;return D|0}function Gc(b){b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;c=i;a:do{if((b|0)!=0?(d=a[b]|0,!(d<<24>>24==101|d<<24>>24==69|d<<24>>24==100|d<<24>>24==68)):0){e=Dg(b|0)|0;while(1){f=e+ -1|0;if((a[b+f|0]|0)==32){e=f}else{break}}if((e|0)>0){f=d;g=0;h=1;j=0;k=0;while(1){if(f<<24>>24==32){if((k|0)==0){l=g;m=h;n=0}else{o=0;break a}}else if(!(f<<24>>24==10)){b:do{if(!((f+ -48<<24>>24&255)<10)){switch(f<<24>>24){case 45:case 43:{break};case 101:case 100:case 69:case 68:case 58:case 46:{p=13;break b;break};default:{o=0;break a}}q=a[b+(j+1)|0]|0;if(q<<24>>24==43|q<<24>>24==45){o=0;break a}if((j|0)>0){switch(a[b+(j+ -1)|0]|0){case 32:case 58:case 101:case 69:case 100:case 68:{r=g;s=k;break};default:{o=0;break a}}}else{r=g;s=k}}else{p=13}}while(0);do{if((p|0)==13){p=0;if((f+ -47<<24>>24&255)<11){r=g;s=k+1|0;break}else{r=(f<<24>>24==58)+g|0;s=k;break}}}while(0);if(f<<24>>24==101|f<<24>>24==100|f<<24>>24==46){l=r;m=2;n=s}else{l=r;m=h;n=s}}else{t=g;u=h;v=k;break}q=j+1|0;if((q|0)>=(e|0)){t=l;u=m;v=n;break}f=a[b+q|0]|0;g=l;h=m;j=q;k=n}if((v|0)>0){o=(t|0)==0?u:3}else{o=0}}else{o=0}}else{o=0}}while(0);i=c;return o|0}function Hc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,j=0.0,k=0,l=0,m=0.0;e=i;f=Fc(b,c)|0;if((f|0)==0){g=0;i=e;return g|0}j=+Jc(f);c=Dg(f|0)|0;a:do{if((c|0)!=0?(b=f+c|0,(c|0)>0):0){k=f;while(1){if((a[k]|0)==58){break}l=k+1|0;if(l>>>0>>0){k=l}else{m=j;break a}}if((k|0)!=0){m=j*15.0}else{m=j}}else{m=j}}while(0);h[d>>3]=m;g=1;i=e;return g|0}function Ic(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;d=i;e=Fc(a,b)|0;if((e|0)==0){f=0}else{h[c>>3]=+Jc(e);f=1}i=d;return f|0}function Jc(b){b=b|0;var c=0,d=0.0,e=0,f=0,g=0,h=0,j=0.0,k=0,l=0.0,m=0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0,w=0.0,x=0.0;c=i;if((b|0)==0){d=0.0;i=c;return+d}e=a[b]|0;if(e<<24>>24==0){d=0.0;i=c;return+d}else{f=e;g=b}while(1){if(f<<24>>24==43){h=5;break}else if(f<<24>>24==45){j=-1.0;h=6;break}else if(!(f<<24>>24==32)){h=7;break}b=g+1|0;f=a[b]|0;g=b}if((h|0)==5){j=1.0;h=6}else if((h|0)==7){f=Dg(g|0)|0;if((g|0)==0){k=1;l=1.0;m=0}else{n=f;o=1.0;p=g;h=8}}if((h|0)==6){f=g+1|0;n=Dg(f|0)|0;o=j;p=f;h=8}a:do{if((h|0)==8){if((n|0)!=0?(f=p+n|0,(n|0)>0):0){g=p;while(1){if((a[g]|0)==44){break}b=g+1|0;if(b>>>0>>0){g=b}else{k=0;l=o;m=p;break a}}if((g|0)!=0){a[g]=32;k=0;l=o;m=p}else{k=0;l=o;m=p}}else{k=0;l=o;m=p}}}while(0);p=Dg(m|0)|0;while(1){n=p+ -1|0;if((a[m+n|0]|0)==32){p=n}else{break}}n=Dg(m|0)|0;b:do{if(!k){c:do{if((n|0)!=0?(f=m+n|0,(n|0)>0):0){b=m;while(1){if((a[b]|0)==58){break}e=b+1|0;if(e>>>0>>0){b=e}else{h=22;break c}}if((b|0)!=0){q=b}else{h=22}}else{h=22}}while(0);if((h|0)==22){if((p|0)==0){break}g=m+p|0;if((p|0)>0){r=m}else{break}while(1){if((a[r]|0)==32){break}f=r+1|0;if(f>>>0>>0){r=f}else{break b}}if((r|0)==0){break}else{q=r}}a[q]=0;o=+(vg(m)|0);a[q]=58;g=q+1|0;f=Dg(g|0)|0;d:do{if((f|0)!=0?(e=q+(f+1)|0,(f|0)>0):0){s=g;while(1){if((a[s]|0)==58){t=s;h=35;break d}u=s+1|0;if(u>>>0>>0){s=u}else{h=31;break}}}else{h=31}}while(0);e:do{if((h|0)==31){f=Dg(g|0)|0;if((f|0)!=0?(s=q+(f+1)|0,(f|0)>0):0){f=g;do{if((a[f]|0)==32){t=f;h=35;break e}f=f+1|0}while(f>>>0>>0)}s=Dg(g|0)|0;f:do{if((s|0)!=0?(f=q+(s+1)|0,(s|0)>0):0){e=g;while(1){if((a[e]|0)==46){break}b=e+1|0;if(b>>>0>>0){e=b}else{v=0.0;break f}}v=+ug(g)}else{v=0.0}}while(0);if((a[g]|0)==0){w=v;x=0.0}else{w=+(vg(g)|0);x=0.0}}}while(0);if((h|0)==35){a[t]=0;j=+(vg(g)|0);a[t]=58;w=j;x=+ug(t+1|0)}d=l*(o+w/60.0+x/3600.0);i=c;return+d}}while(0);if((Gc(m)|0)!=2){d=l*+(vg(m)|0);i=c;return+d}t=$f(m,68)|0;if((t|0)!=0){a[t]=101}t=$f(m,100)|0;if((t|0)!=0){a[t]=101}t=$f(m,69)|0;if((t|0)!=0){a[t]=101}d=l*+ug(m);i=c;return+d}function Kc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;i=i+16|0;g=f;if((a[d]|0)<64){h=Lc(b,c,e)|0;i=f;return h|0}else{Lg(g|0,c|0)|0;j=Dg(c|0)|0;a[g+j|0]=a[d]|0;a[g+(j+1)|0]=0;h=Lc(b,g,e)|0;i=f;return h|0}return 0}function Lc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;e=i;f=Fc(b,c)|0;if((f|0)==0){g=0;i=e;return g|0}c=(a[f]|0)==35?f+1|0:f;if((Dg(c|0)|0)>81){Hg(7704,c|0,81)|0;a[7785|0]=0}else{Lg(7704,c|0)|0}if((Gc(7704)|0)==2){c=$f(7704,68)|0;if((c|0)!=0){a[c]=101}c=$f(7704,100)|0;if((c|0)!=0){a[c]=101}c=$f(7704,69)|0;if((c|0)!=0){a[c]=101}}h[d>>3]=+ug(7704);g=1;i=e;return g|0}function Mc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0;f=i;g=Fc(b,d)|0;if((g|0)==0){j=0;i=f;return j|0}d=$f(g,47)|0;b=$f(g,45)|0;if(d>>>0>g>>>0){a[d]=0;k=~~+ug(g);a[d]=47;l=d+1|0;d=$f(l,47)|0;if((d|0)==0){m=$f(l,45)|0}else{m=d}if(!(m>>>0>g>>>0)){j=0;i=f;return j|0}a[m]=0;d=~~+ug(l);a[m]=47;l=~~+ug(m+1|0);m=(k|0)>31;n=m?k:l;o=m?l:k;if(n>>>0<50){p=n+2e3|0}else{p=(n|0)<100?n+1900|0:n}n=((p|0)%100|0|0)!=0|((p|0)%400|0|0)==0?(p&3|0)==0?29:28:28;c[7796>>2]=n;k=d+ -1|0;d=c[7792+(k<<2)>>2]|0;if((o|0)>(d|0)){q=d}else{q=(o|0)<1?1:o}r=(n|0)==28?365.0:366.0;n=q+ -1|0;if((k|0)>0){q=0;o=n;while(1){d=(c[7792+(q<<2)>>2]|0)+o|0;l=q+1|0;if((l|0)==(k|0)){s=d;break}else{q=l;o=d}}}else{s=n}h[e>>3]=+(p|0)+ +(s|0)/r;j=1;i=f;return j|0}if(!(b>>>0>g>>>0)){j=0;i=f;return j|0}a[b]=0;s=~~+ug(g);a[b]=45;p=b+1|0;b=$f(p,45)|0;do{if(b>>>0>g>>>0){a[b]=0;n=~~+ug(p);a[b]=45;o=b+1|0;q=$f(o,84)|0;if(q>>>0>g>>>0){a[q]=0;k=~~+ug(o);a[q]=84;t=k;u=n;v=q;break}else{t=~~+ug(o);u=n;v=q;break}}else{t=1;u=1;v=0}}while(0);b=(s|0)<32;p=b?t+1900|0:s;q=b?s:t;t=((p|0)%100|0|0)!=0|((p|0)%400|0|0)==0?(p&3|0)==0?29:28:28;c[7796>>2]=t;s=u+ -1|0;u=c[7792+(s<<2)>>2]|0;if((q|0)>(u|0)){w=u}else{w=(q|0)<1?1:q}r=(t|0)==28?365.0:366.0;t=w+ -1|0;if((s|0)>0){w=0;q=t;while(1){u=(c[7792+(w<<2)>>2]|0)+q|0;b=w+1|0;if((b|0)==(s|0)){x=u;break}else{w=b;q=u}}}else{x=t}h[e>>3]=+(p|0)+ +(x|0)/r;if(!(v>>>0>g>>>0)){j=1;i=f;return j|0}x=v+1|0;v=$f(x,58)|0;do{if(v>>>0>g>>>0){a[v]=0;p=~~+ug(x);a[v]=58;t=v+1|0;q=$f(t,58)|0;if(q>>>0>g>>>0){a[q]=0;w=~~+ug(t);a[q]=58;y=p;z=w;A=+ug(q+1|0);break}else{y=p;z=~~+ug(t);A=0.0;break}}else{y=0;z=0;A=0.0}}while(0);h[e>>3]=+h[e>>3]+(A+(+(y|0)*3600.0+ +(z|0)*60.0))/86400.0/r;j=1;i=f;return j|0}function Nc(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+32|0;h=g+8|0;j=g+16|0;k=g;c[h>>2]=d;Na(j|0,7840,h|0)|0;do{if((Cc(b,j)|0)==0){c[h>>2]=d;Na(j|0,7856,h|0)|0;if((Cc(b,j)|0)!=0){l=k;c[l>>2]=627012389;c[l+4>>2]=6566448;break}c[h>>2]=d;Na(j|0,7864,h|0)|0;if((Cc(b,j)|0)!=0){l=k;c[l>>2]=627012389;c[l+4>>2]=6566704;break}if((Cc(b,j)|0)==0){m=0;i=g;return m|0}else{l=k;c[l>>2]=627012389;c[l+4>>2]=6566704;break}}else{a[k+0|0]=a[7848|0]|0;a[k+1|0]=a[7849|0]|0;a[k+2|0]=a[7850|0]|0;a[k+3|0]=a[7851|0]|0;a[k+4|0]=a[7852|0]|0;a[k+5|0]=a[7853|0]|0}}while(0);c[1968]=1;l=1;n=e;e=f;while(1){c[h>>2]=d;c[h+4>>2]=l;Na(j|0,k|0,h|0)|0;o=Fc(b,j)|0;if((o|0)==0){p=l;break}q=Dg(o|0)|0;if((q|0)>=(n|0)){r=13;break}Lg(e|0,o|0)|0;s=l+1|0;if((s|0)<500){l=s;n=n-q|0;e=e+q|0}else{p=s;break}}do{if((r|0)==13){if((n|0)>1){Hg(e|0,o|0,n+ -1|0)|0;a[e+n|0]=0;p=l;break}else{a[f]=a[o]|0;p=l;break}}}while(0);c[1968]=0;m=(p|0)>1|0;i=g;return m|0}function Oc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;g=i;i=i+16|0;h=g;do{if((a[d]|0)<64){j=Fc(b,c)|0;if((j|0)!=0){if((Dg(j|0)|0)<(e|0)){Lg(f|0,j|0)|0;k=1;break}if((e|0)>1){Hg(f|0,j|0,e+ -1|0)|0;k=1;break}else{a[f]=a[j]|0;k=1;break}}else{k=0}}else{Lg(h|0,c|0)|0;j=Dg(c|0)|0;a[h+j|0]=a[d]|0;a[h+(j+1)|0]=0;j=Fc(b,h)|0;if((j|0)!=0){if((Dg(j|0)|0)<(e|0)){Lg(f|0,j|0)|0;k=1;break}if((e|0)>1){Hg(f|0,j|0,e+ -1|0)|0;k=1;break}else{a[f]=a[j]|0;k=1;break}}else{k=0}}}while(0);i=g;return k|0}function Pc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=i;g=Fc(b,c)|0;do{if((g|0)!=0){if((Dg(g|0)|0)<(d|0)){Lg(e|0,g|0)|0;h=1;break}if((d|0)>1){Hg(e|0,g|0,d+ -1|0)|0;h=1;break}else{a[e]=a[g]|0;h=1;break}}else{h=0}}while(0);i=f;return h|0}function Qc(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;d=i;e=Dg(b|0)|0;a:do{if(!((b|0)==0|(c|0)==0)){f=Dg(c|0)|0;if((f|0)!=0){if((e|0)!=0?(g=a[c]|0,h=f+ -1|0,j=a[c+h|0]|0,k=e+1-f|0,l=b+k|0,(k|0)>0):0){k=(f|0)==1;m=(f|0)<3;n=b;while(1){b:do{if((a[n]|0)==g<<24>>24){if(k){o=n;break a}if((a[n+h|0]|0)==j<<24>>24){if(m){o=n;break a}else{p=1}while(1){q=p+1|0;if((a[n+p|0]|0)!=(a[c+p|0]|0)){break b}if((q|0)<(f|0)){p=q}else{o=n;break a}}}}}while(0);q=n+1|0;if(q>>>0>>0){n=q}else{o=0;break}}}else{o=0}}else{o=b}}else{o=0}}while(0);i=d;return o|0}function Rc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;e=i;if((b|0)==0|(c|0)==0){f=0;i=e;return f|0}g=Dg(c|0)|0;if((g|0)==0){f=b;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}do{if((g|0)<3){h=a[c]|0;j=h<<24>>24;if(!((h+ -97<<24>>24&255)<26)){if((h+ -65<<24>>24&255)<26){k=j+32&255}else{k=h}}else{k=j+224&255}if((g|0)>1){j=a[c+1|0]|0;l=j<<24>>24;if((j+ -97<<24>>24&255)<26){m=h;n=j;o=k;p=l+224&255;q=0;break}if((j+ -65<<24>>24&255)<26){m=h;n=j;o=k;p=l+32&255;q=0}else{m=h;n=j;o=k;p=j;q=0}}else{m=h;n=32;o=k;p=32;q=0}}else{h=ig(g,1)|0;j=0;do{l=a[c+j|0]|0;r=l&255;do{if(!((l+ -97<<24>>24&255)<26)){if((l+ -65<<24>>24&255)<26){a[h+j|0]=r+32;break}else{a[h+j|0]=l;break}}else{a[h+j|0]=r+224}}while(0);j=j+1|0}while((j|0)!=(g|0));j=g+ -1|0;m=a[c]|0;n=a[c+j|0]|0;o=a[h]|0;p=a[h+j|0]|0;q=h}}while(0);k=d+1-g|0;d=b+k|0;a:do{if((k|0)>0){j=g+ -1|0;r=(g|0)>1;if((g|0)==2){l=b;while(1){s=a[l]|0;if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24?(s=a[l+j|0]|0,s<<24>>24==n<<24>>24|s<<24>>24==p<<24>>24):0){break}s=l+1|0;if(s>>>0>>0){l=s}else{break a}}if((q|0)==0){f=l;i=e;return f|0}hg(q);f=l;i=e;return f|0}else if((g|0)==1){h=b;while(1){s=a[h]|0;if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24){break}s=h+1|0;if(s>>>0>>0){h=s}else{break a}}if((q|0)==0){f=h;i=e;return f|0}hg(q);f=h;i=e;return f|0}else{l=b;b:while(1){s=a[l]|0;c:do{if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24?(t=a[l+j|0]|0,t<<24>>24==n<<24>>24|t<<24>>24==p<<24>>24):0){if(r){u=1}else{break b}while(1){t=a[l+u|0]|0;if(!(t<<24>>24==(a[c+u|0]|0))?!(t<<24>>24==(a[q+u|0]|0)):0){break c}u=u+1|0;if((u|0)>=(g|0)){break b}}}}while(0);s=l+1|0;if(s>>>0>>0){l=s}else{break a}}if((q|0)==0){f=l;i=e;return f|0}hg(q);f=l;i=e;return f|0}}}while(0);if((q|0)==0){f=0;i=e;return f|0}hg(q);f=0;i=e;return f|0}function Sc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;a:do{if(!((b|0)==0|(c|0)==0)){f=Dg(c|0)|0;if((f|0)!=0){if((d|0)!=0?(g=a[c]|0,h=f+ -1|0,j=a[c+h|0]|0,k=d+1-f|0,l=b+k|0,(k|0)>0):0){k=(f|0)==1;m=b;while(1){b:do{if((a[m]|0)==g<<24>>24){if(k){n=m;break a}if((a[m+h|0]|0)==j<<24>>24){if((f|0)<3){n=m;break a}else{o=1}while(1){p=o+1|0;if((a[m+o|0]|0)!=(a[c+o|0]|0)){break b}if((p|0)<(f|0)){o=p}else{n=m;break a}}}}}while(0);p=m+1|0;if(p>>>0>>0){m=p}else{n=0;break}}}else{n=0}}else{n=b}}else{n=0}}while(0);i=e;return n|0}function Tc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0;g=i;i=i+80|0;j=g;l=g+16|0;if(e<0.0){m=-e;n=-1.0}else{m=e;n=1.0}e=n*+qa(+m,360.0);if(e<0.0){o=e+360.0}else{o=e}e=o/15.0;p=~~e;o=(e- +(p|0))*60.0;q=~~o;e=(o- +(q|0))*60.0;do{if((f|0)<=5){if((f|0)>4){r=e>59.99999;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8008,j|0)|0;break}if((f|0)>3){s=e>59.9999;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,8032,j|0)|0;break}if((f|0)>2){r=e>59.999;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8056,j|0)|0;break}if((f|0)>1){s=e>59.99;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,8080,j|0)|0;break}if((f|0)>0){r=e>59.9;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8104,j|0)|0;break}else{s=~~(e+.5);r=(s|0)>59;t=(r&1)+q|0;u=(t|0)>59;c[j>>2]=((u&1)+p|0)%24|0;c[j+4>>2]=u?0:t;c[j+8>>2]=r?0:s;Na(l|0,8128,j|0)|0;break}}else{s=e>59.999999;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,7984,j|0)|0}}while(0);j=d+ -1|0;if((Dg(l|0)|0)<(j|0)){Lg(b|0,l|0)|0;i=g;return}else{Hg(b|0,l|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Uc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;g=i;i=i+96|0;j=g;l=g+24|0;if(e<0.0){m=-e;n=-1.0}else{m=e;n=1.0}e=n*+qa(+m,360.0);if(!(e<=-180.0)){o=e}else{o=e+360.0}if(o<0.0){p=-o;q=45}else{p=o;q=43}r=~~p;o=(p- +(r|0))*60.0;s=~~o;p=(o- +(s|0))*60.0;do{if((f|0)<=5){if((f|0)>4){t=p>59.99999;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8168,j|0)|0;break}if((f|0)>3){u=p>59.9999;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8192,j|0)|0;break}if((f|0)>2){t=p>59.999;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8216,j|0)|0;break}if((f|0)>1){u=p>59.99;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8240,j|0)|0;break}if((f|0)>0){t=p>59.9;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8264,j|0)|0;break}else{u=~~(p+.5);t=(u|0)>59;v=(t&1)+s|0;w=(v|0)>59;c[j>>2]=q&255;c[j+4>>2]=(w&1)+r;c[j+8>>2]=w?0:v;c[j+12>>2]=t?0:u;Na(l|0,8288,j|0)|0;break}}else{u=p>59.999999;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8144,j|0)|0}}while(0);j=d+ -1|0;if((Dg(l|0)|0)<(j|0)){Lg(b|0,l|0)|0;i=g;return}else{Hg(b|0,l|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Vc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0;g=i;i=i+80|0;j=g;l=g+72|0;m=g+8|0;if(e<0.0){n=-e;o=-1.0}else{n=e;o=1.0}e=o*+qa(+n,360.0);if(!(e<=-180.0)){p=e}else{p=e+360.0}q=f+4|0;if((f|0)>0){c[j>>2]=q;c[j+4>>2]=f;Na(l|0,8312,j|0)|0;h[k>>3]=p;c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];Na(m|0,l|0,j|0)|0}else{c[j>>2]=q;Na(l|0,8328,j|0)|0;c[j>>2]=~~p;Na(m|0,l|0,j|0)|0}j=d+ -1|0;if((Dg(m|0)|0)<(j|0)){Lg(b|0,m|0)|0;i=g;return}else{Hg(b|0,m|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Wc(a,b,d,e){a=a|0;b=+b;d=d|0;e=e|0;var f=0,g=0,j=0,l=0;f=i;i=i+16|0;g=f;j=f+8|0;l=(e|0)>0;if((d|0)>0){if(l){c[g>>2]=d;c[g+4>>2]=e;Na(j|0,8312,g|0)|0;h[k>>3]=b;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];Na(a|0,j|0,g|0)|0;i=f;return}else{c[g>>2]=d;Na(j|0,8336,g|0)|0;c[g>>2]=~~b;Na(a|0,j|0,g|0)|0;i=f;return}}else{if(l){c[g>>2]=e;Na(j|0,7976,g|0)|0;h[k>>3]=b;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];Na(a|0,j|0,g|0)|0;i=f;return}else{c[g>>2]=~~b;Na(a|0,7968,g|0)|0;i=f;return}}}function Xc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=i;i=i+32|0;e=d;f=_c(a,b)|0;if((f|0)==0){g=0;i=d;return g|0}Lg(e|0,f|0)|0;h[c>>3]=+ug(e);g=1;i=d;return g|0}function Yc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;g=i;h=gg(2e3)|0;if((Nc(b,c,2e3,h)|0)==0){hg(h);j=0;i=g;return j|0}c=_c(h,d)|0;do{if((c|0)!=0){if((Dg(c|0)|0)<(e|0)){Lg(f|0,c|0)|0;k=1;break}if((e|0)>1){Hg(f|0,c|0,e+ -1|0)|0;k=1;break}else{a[f]=a[c]|0;k=1;break}}else{k=0}}while(0);hg(h);j=k;i=g;return j|0}function Zc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=i;g=_c(b,c)|0;do{if((g|0)!=0){if((Dg(g|0)|0)<(d|0)){Lg(e|0,g|0)|0;h=1;break}if((d|0)>1){Hg(e|0,g|0,d+ -1|0)|0;h=1;break}else{a[e]=a[g]|0;h=1;break}}else{h=0}}while(0);i=f;return h|0}function _c(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=i;i=i+2032|0;e=d+2024|0;f=d+2018|0;g=d+2016|0;h=d+2e3|0;j=d;a[f]=91;a[f+1|0]=0;a[g]=93;a[g+1|0]=0;Lg(h|0,c|0)|0;c=Qc(h,f)|0;f=(c|0)!=0;if(f){a[c]=0;k=0}else{k=0}while(1){l=k+1|0;if((a[b+k|0]|0)==0){m=6;break}if((l|0)<57600){k=l}else{m=4;break}}if((m|0)==4){n=l;o=Dg(h|0)|0}else if((m|0)==6){l=Dg(h|0)|0;if((k|0)>0){n=k;o=l}else{p=0;i=d;return p|0}}l=b+n|0;n=l;k=b;while(1){q=Sc(k,h,n-k|0)|0;if((q|0)==0){p=0;m=34;break}r=a[q+o|0]|0;s=a[q+ -1|0]|0;if(!(r<<24>>24>32?!(r<<24>>24==61|r<<24>>24==127):0)){if((q|0)==(b|0)){t=b;m=14;break}if(s<<24>>24==9|s<<24>>24==32){t=q;m=14;break}}s=q+1|0;if(s>>>0>>0){k=s}else{p=0;m=34;break}}if((m|0)==14){if((t|0)==0){p=0;i=d;return p|0}k=t+o|0;while(1){o=a[k]|0;if(!(o<<24>>24==61|o<<24>>24==32)){break}k=k+1|0}if((k|0)==0){p=0;i=d;return p|0}Eg(j|0,0,2e3)|0;o=a[k]|0;a:do{if(o<<24>>24==34){t=k;l=0;while(1){b=t+1|0;n=a[b]|0;if(n<<24>>24==34|n<<24>>24==0){break a}if((l|0)>=2e3){break a}a[j+l|0]=n;t=b;l=l+1|0}}else{l=o;t=0;b=k;while(1){if(l<<24>>24==9|l<<24>>24==32){break a}if(!(l<<24>>24>0&(t|0)<2e3)){break a}n=b+1|0;a[j+t|0]=l;l=a[n]|0;t=t+1|0;b=n}}}while(0);if(!f){Lg(8344,j|0)|0;p=8344;i=d;return p|0}f=c+1|0;c=Qc(f,g)|0;if((c|0)==0){p=8344;i=d;return p|0}a[c]=0;c=vg(f)|0;if((c|0)<=0){p=8344;i=d;return p|0}a[e]=32;a[e+1|0]=44;a[e+2|0]=0;f=fg(j,e)|0;if((c|0)>1){j=1;while(1){g=fg(0,e)|0;k=j+1|0;if((k|0)==(c|0)){u=g;break}else{j=k}}}else{u=f}if((u|0)==0){p=8344;i=d;return p|0}Lg(8344,u|0)|0;p=8344;i=d;return p|0}else if((m|0)==34){i=d;return p|0}return 0}function $c(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0;g=i;j=c[d+3260>>2]|0;k=+h[d>>3];l=+h[d+8>>3];m=+h[d+32>>3];n=+h[d+40>>3];o=+h[d+48>>3]*3.141592653589793/180.0;p=+S(+o);q=+T(+o);r=a- +h[d+16>>3];a=b- +h[d+24>>3];do{if((c[d+3300>>2]|0)==0){if(m==0.0|n==0.0){h[e>>3]=0.0;h[f>>3]=0.0;s=2;i=g;return s|0}else{b=r*m;t=a*n;if(!(o!=0.0)){u=b;v=t;break}u=b*p-t*q;v=t*p+b*q;break}}else{u=r*+h[d+56>>3]+a*+h[d+64>>3];v=r*+h[d+72>>3]+a*+h[d+80>>3]}}while(0);w=(c[d+3304>>2]|0)==0;a=w?v:u;r=w?u:v;h[e>>3]=k+r;h[f>>3]=l+a;if((j|0)<1){s=0;i=g;return s|0}v=k*3.141592653589793/180.0;k=l*3.141592653589793/180.0;u=w?k:v;o=w?v:k;v=r*3.141592653589793/180.0;r=a*3.141592653589793/180.0;a=v*v;b=a+r*r;t=+S(+u);x=+T(+u);a:do{switch(j|0){case 11:{y=u+r;z=o+v;break};case 32:case 33:case 31:case 3:{if(b>1.0){s=1;i=g;return s|0}A=t-r*x;if(A==0.0){s=1;i=g;return s|0}else{B=o+ +Y(+v,+A);y=+X(+((r*t+x)*+S(+(B-o))/A));z=B;break a}break};case 6:{if(b>=9.869604401089369){s=1;i=g;return s|0}B=+Q(+b);A=+S(+B);if(B!=0.0){C=+T(+B)/B}else{C=1.0}B=x*A+r*t*C;if(B>1.0|B<-1.0){s=1;i=g;return s|0}D=A-x*B;A=t*v*C;if(D==0.0&A==0.0){s=1;i=g;return s|0}else{y=+W(+B);z=o+ +Y(+A,+D);break a}break};case 22:{D=n*p+m*q;A=(D==0.0?3.141592653589793:D*3.141592653589793)/180.0;D=k+A;B=+T(+k);E=+S(+k);F=+Q(+((E+1.0)*.5));G=+T(+D)/+Q(+((+S(+D)+1.0)*.5))-B/F;D=A/(G==0.0?1.0:G);G=m*p-n*q;A=(G==0.0?3.141592653589793:G*3.141592653589793)/180.0;G=A*.5;H=E*2.0*+T(+G);I=A*+Q(+((E*+S(+G)+1.0)*.5))/(H==0.0?1.0:H);if(!(v==0.0&r==0.0)){H=r+B*D/F;F=H/D;B=4.0-a/(I*I*4.0)-F*F;if(B>4.0|B<2.0){s=1;i=g;return s|0}F=+Q(+B)*.5;B=H*F/D;if(+P(+B)>1.0){s=1;i=g;return s|0}D=+W(+B);B=+S(+D);if(+P(+B)<1.0e-5){s=1;i=g;return s|0}H=v*F/(I*2.0*B);if(+P(+H)>1.0){s=1;i=g;return s|0}else{y=D;z=o+ +W(+H)*2.0;break a}}else{y=u;z=o}break};case 5:{H=(4.0-b)/(b+4.0);if(+P(+H)>1.0){s=1;i=g;return s|0}D=H+1.0;B=x*H+r*t*D*.5;if(+P(+B)>1.0){s=1;i=g;return s|0}H=+W(+B);B=+S(+H);if(+P(+B)<1.0e-5){s=1;i=g;return s|0}I=v*D/(B*2.0);if(+P(+I)>1.0){s=1;i=g;return s|0}D=+W(+I);I=+T(+H);F=+S(+D);G=x*I+1.0+t*B*F;if(+P(+G)<1.0e-5){s=1;i=g;return s|0}if(+P(+((t*I-x*B*F)*2.0/G-r))>1.0e-5){J=3.141592653589795-D}else{J=D}y=H;z=o+J;break};case 20:case 28:{H=u+r;if(+P(+H)>1.5707963267948974){s=1;i=g;return s|0}D=+S(+H);if(+P(+v)>D*6.28318530717959*.5){s=1;i=g;return s|0}if(D>1.0e-5){y=H;z=o+v/D}else{y=H;z=o}break};case 27:{H=t-r*x;if(H==0.0){s=1;i=g;return s|0}D=o+ +Y(+v,+H);G=+S(+(D-o));if(G==0.0){s=1;i=g;return s|0}F=H/G;if(F>1.0|F<-1.0){s=1;i=g;return s|0}G=+V(+F);if(u<0.0){y=-G;z=D}else{y=G;z=D}break};case 12:{D=n*p+m*q;G=D==0.0?1.0:D;D=(l*.5+45.0)*3.141592653589793/180.0;F=+_(+(+U(+D)));H=G*3.141592653589793/180.0/(+_(+(+U(+(G*.5*.01745329252+D))))-F);D=+S(+k);G=o+v/(!(D<=0.0)?D:1.0);if(+P(+(G-o))>6.28318530717959){s=1;i=g;return s|0}if(H!=0.0){K=(r+F*H)/H}else{K=0.0}y=+X(+(+Z(+K)))*2.0+-1.5707963267948974;z=G;break};case 4:{if(b>1.0){s=1;i=g;return s|0}G=+Q(+(1.0-b));H=r*t+x*G;if(H>1.0|H<-1.0){s=1;i=g;return s|0}F=t*G-r*x;if(F==0.0&v==0.0){s=1;i=g;return s|0}else{y=+W(+H);z=o+ +Y(+v,+F);break a}break};case 16:{F=1.0/+U(+u)-r;if(u<0.0){L=-F}else{L=F}y=+W(+((x*x*(1.0-(a+F*F))+1.0)*(1.0/(x*2.0))));z=o- +Y(+v,+L)/x;break};default:{y=0.0;z=0.0}}}while(0);if(z-o>3.141592653589795){M=z+-6.28318530717959}else{M=z}if(M-o<-3.141592653589795){N=M+6.28318530717959}else{N=M}if(N<0.0){O=N+6.28318530717959}else{O=N}h[e>>3]=O*180.0/3.141592653589793;h[f>>3]=y*180.0/3.141592653589793;s=0;i=g;return s|0}function ad(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0,N=0.0,O=0.0,R=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0;g=i;j=+h[d>>3];k=+h[d+8>>3];l=+h[d+16>>3];m=+h[d+24>>3];n=+h[d+32>>3];o=+h[d+40>>3];p=+h[d+48>>3]*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=c[d+3260>>2]|0;t=(s|0)>0;if(t){u=(c[d+3304>>2]|0)==0;v=j*3.141592653589793/180.0;w=k*3.141592653589793/180.0;x=u?w:v;y=u?v:w;w=a-(u?j:k);v=l*n;if(v>180.0|v<-180.0){if(w>360.0){z=a+-360.0}else{z=a}if(w<0.0){A=z+360.0}else{A=z}}else{if(w>180.0){B=a+-360.0}else{B=a}if(w<-180.0){A=B+360.0}else{A=B}}B=A*3.141592653589793/180.0;w=b*3.141592653589793/180.0;z=+S(+w);v=+T(+w);C=B-y;D=A;E=z;F=w;G=x;H=z*+T(+C);I=B;J=y;K=v;L=v*+T(+x)+z*+S(+x)*+S(+C)}else{D=a;E=0.0;F=0.0;G=0.0;H=0.0;I=0.0;J=0.0;K=0.0;L=0.0}a:do{switch(s|0){case 22:{a=(I-J)*.5;if(+P(+a)>1.5707963267948974){M=1;i=g;return M|0}C=o*q+n*r;x=(C==0.0?3.141592653589793:C*3.141592653589793)/180.0;C=k*3.141592653589793/180.0;z=x+C;v=+T(+C);y=+S(+C);C=+Q(+((y+1.0)*.5));B=+T(+z)/+Q(+((+S(+z)+1.0)*.5))-v/C;z=x/(B==0.0?1.0:B);B=n*q-o*r;x=(B==0.0?3.141592653589793:B*3.141592653589793)/180.0;B=x*.5;w=y*2.0*+T(+B);A=+S(+F);N=+Q(+((A*+S(+a)+1.0)*.5));if(+P(+N)<1.0e-5){M=3;i=g;return M|0}else{O=+T(+a)*A*x*+Q(+((y*+S(+B)+1.0)*.5))/(w==0.0?1.0:w)*2.0/N;R=z*+T(+F)/N-v*z/C;break a}break};case 3:case 32:case 33:case 31:{if(!(L<=0.0)){C=+T(+G);z=+S(+G);v=+S(+(I-J));N=K*C+E*z*v;O=H/N;R=(K*z-E*C*v)/N;break a}else{M=1;i=g;return M|0}break};case 16:{N=+U(+G);v=1.0/N;C=N*-2.0;z=N*N;w=N/3.0;N=C*C;B=(J-I)*+T(+G);y=F-G;x=v*(y*(C*.5+y*(z*.5+N*-.125+y*(w*.5+(z*C*-.25+C*N*.0625)+y*(z*.1875*N+(z*z*-.125-C*.25*w)-N*N*.0390625))))+1.0);N=B*B;if((c[d+3300>>2]|0)==0){W=n/+P(+n)}else{w=+h[d+56>>3];W=w/+P(+w)}O=(1.0-N/6.0)*B*x*W;R=v-(1.0-N*.5)*x;break};case 27:{if(G==0.0){M=1;i=g;return M|0}else{O=H;R=(+S(+G)-E*+S(+(I-J)))/+T(+G);break a}break};case 12:{x=o*q+n*r;N=x==0.0?1.0:x;x=(k*.5+45.0)*3.141592653589793/180.0;v=+_(+(+U(+x)));B=N*3.141592653589793/180.0/(+_(+(+U(+(N*.5*.01745329252+x))))-v);x=+S(+(k*3.141592653589793/180.0));N=+U(+(F*.5+.7853981633974487));if(N<1.0e-5){M=2;i=g;return M|0}else{O=(I-J)*(!(x<=0.0)?x:1.0);R=B*+_(+N)-v*B;break a}break};case 6:{B=+T(+G);v=+S(+G);N=+S(+(I-J));x=K*B+E*v*N;w=x<-1.0?-1.0:x;x=+V(+(w>1.0?1.0:w));if(x!=0.0){X=x/+T(+x)}else{X=1.0}O=H*X;R=(K*v-E*B*N)*X;break};case 20:case 28:{if(+P(+F)>1.5707963267948974){M=1;i=g;return M|0}if(+P(+G)>1.5707963267948974){M=1;i=g;return M|0}else{O=E*(I-J);R=F-G;break a}break};case 11:{O=I-J;R=F-G;break};case 4:{if(L<0.0){M=1;i=g;return M|0}else{O=H;R=K*+S(+G)-E*+T(+G)*+S(+(I-J));break a}break};case 5:{if(+P(+F)>1.5707963267948974){M=1;i=g;return M|0}N=+T(+G);B=+S(+G);v=+S(+(I-J));x=K*N+1.0+E*B*v;if(+P(+x)<1.0e-5){M=1;i=g;return M|0}else{w=2.0/x;O=H*w;R=(K*B-E*N*v)*w;break a}break};default:{O=H;R=0.0}}}while(0);if(t){Y=O*180.0/3.141592653589793;Z=R*180.0/3.141592653589793}else{Y=D-j;Z=b-k}t=(c[d+3304>>2]|0)==0;k=t?Z:Y;b=t?Y:Z;if((c[d+3300>>2]|0)==0){if(p!=0.0){$=q*b+r*k;aa=q*k-r*b}else{$=b;aa=k}if(n!=0.0){ba=$/n}else{ba=$}if(o!=0.0){ca=ba;da=aa/o}else{ca=ba;da=aa}}else{ca=b*+h[d+88>>3]+k*+h[d+96>>3];da=b*+h[d+104>>3]+k*+h[d+112>>3]}k=l+ca;h[e>>3]=k;do{if((s|0)==11){ca=+h[d+136>>3];if(k>ca){l=k-360.0/n;if(!(l>0.0)){break}h[e>>3]=l;break}if(k<0.0?(l=k+360.0/n,l<=ca):0){h[e>>3]=l}}}while(0);h[f>>3]=m+da;M=0;i=g;return M|0}function bd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0;g=i;j=c[d+3268>>2]|0;k=c[d+3272>>2]|0;l=a- +h[d+616>>3];a=b- +h[d+624>>3];b=l*l;m=a*a;n=l*b;o=a*m;p=b+m;q=+h[d+256>>3]+l*+h[d+264>>3]+a*+h[d+272>>3]+b*+h[d+280>>3]+m*+h[d+288>>3]+a*l*+h[d+296>>3];if((j|0)>6){r=q+n*+h[d+304>>3]+o*+h[d+312>>3];if((j|0)>8){s=p*+h[d+336>>3]+(r+a*b*+h[d+320>>3]+m*l*+h[d+328>>3])+p*l*+h[d+344>>3]+p*a*+h[d+352>>3]}else{s=r}}else{s=q}q=+h[d+416>>3]+l*+h[d+424>>3]+a*+h[d+432>>3]+b*+h[d+440>>3]+m*+h[d+448>>3]+a*l*+h[d+456>>3];if((k|0)>6){r=q+n*+h[d+464>>3]+o*+h[d+472>>3];if((k|0)>8){t=p*+h[d+496>>3]+(r+a*b*+h[d+480>>3]+l*m*+h[d+488>>3])+p*l*+h[d+504>>3]+p*a*+h[d+512>>3]}else{t=r}}else{t=q}q=t*3.141592653589793/180.0;t=+h[d+696>>3]*3.141592653589793/180.0;r=+U(+t);a=1.0-q*r;p=+Y(+(s*3.141592653589793/180.0/+S(+t)),+a);t=+h[d+688>>3]*3.141592653589793/180.0+p;if(!(t<0.0)){u=t;v=u*180.0;w=v/3.141592653589793;h[e>>3]=w;x=+S(+p);y=q+r;z=a/y;A=x/z;B=+X(+A);C=B*180.0;D=C/3.141592653589793;h[f>>3]=D;i=g;return 0}u=t+6.28318530717959;v=u*180.0;w=v/3.141592653589793;h[e>>3]=w;x=+S(+p);y=q+r;z=a/y;A=x/z;B=+X(+A);C=B*180.0;D=C/3.141592653589793;h[f>>3]=D;i=g;return 0}function cd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0,M=0,N=0,O=0,Q=0,R=0,T=0,V=0,W=0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0,va=0.0,wa=0.0,xa=0,ya=0.0,za=0.0,Aa=0.0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0;g=i;j=c[d+3268>>2]|0;k=c[d+3272>>2]|0;l=+U(+(b*3.141592653589793/180.0));b=+h[d+696>>3]*3.141592653589793/180.0;m=+U(+b);n=a*3.141592653589793/180.0- +h[d+688>>3]*3.141592653589793/180.0;a=+S(+n);o=(1.0-m*a/l)/(m+a/l);l=+S(+b)*+U(+n)*(1.0-m*o)*180.0/3.141592653589793;m=o*180.0/3.141592653589793;o=l*+h[d+88>>3]+m*+h[d+96>>3];n=l*+h[d+104>>3]+m*+h[d+112>>3];b=+h[d+256>>3];a=+h[d+264>>3];p=+h[d+272>>3];q=+h[d+280>>3];r=+h[d+288>>3];s=+h[d+296>>3];t=q*2.0;u=r*2.0;v=d+304|0;w=d+312|0;x=(j|0)>8;y=d+320|0;z=d+328|0;A=d+336|0;B=d+344|0;C=d+352|0;D=+h[d+416>>3];E=+h[d+424>>3];F=+h[d+432>>3];G=+h[d+440>>3];H=+h[d+448>>3];I=+h[d+456>>3];J=G*2.0;K=H*2.0;L=(k|0)>6;M=d+464|0;N=d+472|0;O=(k|0)>8;k=d+480|0;Q=d+488|0;R=d+496|0;T=d+504|0;V=d+512|0;a:do{if((j|0)>6){W=0;X=o;Y=n;while(1){Z=Y*X;_=X*X;$=Y*Y;aa=X*_;ba=Y*$;ca=Y*_;da=$*X;ea=$+_;fa=+h[v>>3];ga=+h[w>>3];ha=b+X*a+Y*p+_*q+$*r+Z*s+aa*fa+ba*ga;ia=a+X*t+Y*s+_*fa*3.0;fa=X*s+(p+Y*u)+$*ga*3.0;if(x){ga=+h[y>>3];ja=+h[z>>3];ka=+h[A>>3];la=+h[B>>3];ma=+h[C>>3];na=ka*2.0;oa=ha+ca*ga+da*ja+ea*ka+ea*X*la+ea*Y*ma;pa=($+_*3.0)*la+($*ja+(ia+Z*ga*2.0)+X*na)+Z*ma*2.0;qa=($*3.0+_)*ma+(fa+_*ga+Z*ja*2.0+Y*na+Z*la*2.0)}else{oa=ha;pa=ia;qa=fa}fa=D+X*E+Y*F+_*G+$*H+Z*I;ia=E+X*J+Y*I;ha=X*I+(F+Y*K);if(L){la=+h[M>>3];na=+h[N>>3];ja=fa+aa*la+ba*na;ba=ia+_*la*3.0;la=ha+$*na*3.0;if(O){na=+h[k>>3];aa=+h[Q>>3];ga=+h[R>>3];ma=+h[T>>3];ka=+h[V>>3];ra=ga*2.0;sa=ja+ca*na+da*aa+ea*ga+ea*X*ma+ea*Y*ka;ta=($+_*3.0)*ma+($*aa+(ba+Z*na*2.0)+X*ra)+Z*ka*2.0;ua=($*3.0+_)*ka+(la+_*na+Z*aa*2.0+Y*ra+Z*ma*2.0)}else{sa=ja;ta=ba;ua=la}}else{sa=fa;ta=ia;ua=ha}ha=oa-l;ia=sa-m;fa=pa*ua-qa*ta;la=(qa*ia-ha*ua)/fa;ba=(ha*ta-pa*ia)/fa;fa=X+la;ia=Y+ba;if(+P(+la)<5.0e-7?+P(+ba)<5.0e-7:0){va=fa;wa=ia;break a}xa=W+1|0;if((xa|0)<50){W=xa;X=fa;Y=ia}else{va=fa;wa=ia;break}}}else{W=0;Y=o;X=n;while(1){ia=X*Y;fa=Y*Y;ba=X*X;la=X*fa;ha=ba*Y;ja=ba+fa;ma=b+Y*a+X*p+fa*q+ba*r+ia*s;Z=a+Y*t+X*s;ra=Y*s+(p+X*u);aa=D+Y*E+X*F+fa*G+ba*H+ia*I;na=E+Y*J+X*I;_=Y*I+(F+X*K);if(L){ka=+h[M>>3];$=+h[N>>3];ea=aa+Y*fa*ka+X*ba*$;ga=na+fa*ka*3.0;ka=_+ba*$*3.0;if(O){$=+h[k>>3];da=+h[Q>>3];ca=+h[R>>3];ya=+h[T>>3];za=+h[V>>3];Aa=ca*2.0;Ba=ea+la*$+ha*da+ja*ca+ja*Y*ya+ja*X*za;Ca=(ba+fa*3.0)*ya+(ba*da+(ga+ia*$*2.0)+Y*Aa)+ia*za*2.0;Da=(ba*3.0+fa)*za+(ka+fa*$+ia*da*2.0+X*Aa+ia*ya*2.0)}else{Ba=ea;Ca=ga;Da=ka}}else{Ba=aa;Ca=na;Da=_}_=ma-l;ma=Ba-m;na=Z*Da-ra*Ca;aa=(ra*ma-_*Da)/na;ra=(_*Ca-Z*ma)/na;na=Y+aa;ma=X+ra;if(+P(+aa)<5.0e-7?+P(+ra)<5.0e-7:0){va=na;wa=ma;break a}xa=W+1|0;if((xa|0)<50){W=xa;Y=na;X=ma}else{va=na;wa=ma;break}}}}while(0);h[e>>3]=va+ +h[d+616>>3];va=wa+ +h[d+624>>3];h[f>>3]=va;wa=+h[e>>3];if(wa<.5){Ea=-1;i=g;return Ea|0}if(wa>+h[d+136>>3]+.5|va<.5){Ea=-1;i=g;return Ea|0}if(va>+h[d+144>>3]+.5){Ea=-1;i=g;return Ea|0}Ea=0;i=g;return Ea|0}function dd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0;d=i;e=gg(2e3)|0;f=gg(2e3)|0;Nc(a,10344,2e3,e)|0;Nc(a,10352,2e3,f)|0;a=gg(2e3)|0;g=gg(2e3)|0;j=b+3176|0;if((+h[j>>3]>360.0?(Xc(e,10360,j)|0)==0:0)?(Xc(f,10360,j)|0)==0:0){h[j>>3]=180.0}j=b+3192|0;if((Xc(e,10376,j)|0)==0?(Xc(f,10376,j)|0)==0:0){h[j>>3]=57.29577951308232}do{if((Zc(e,10384,2e3,a)|0)==0){if((Zc(f,10384,2e3,a)|0)==0){c[b+5960>>2]=0;break}else{c[b+5960>>2]=gd(a)|0;break}}else{c[b+5960>>2]=gd(a)|0}}while(0);do{if((Zc(f,10392,2e3,g)|0)==0){if((Zc(e,10392,2e3,g)|0)==0){c[b+5964>>2]=0;break}else{c[b+5964>>2]=gd(g)|0;break}}else{c[b+5964>>2]=gd(g)|0}}while(0);ac(b);hg(e);hg(f);hg(a);hg(g);if((c[b+5964>>2]|0)==0?(c[b+5960>>2]|0)==0:0){k=1;i=d;return k|0}k=0;i=d;return k|0}function ed(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0;g=i;j=a- +h[d+616>>3];a=b- +h[d+624>>3];if((c[d+3300>>2]|0)==0){b=+h[d+760>>3];if(b==0.0){k=2;l=0.0;m=0.0;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}n=+h[d+768>>3];if(n==0.0){k=2;l=0.0;m=0.0;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}o=j*b;b=a*n;n=+h[d+48>>3];if(n!=0.0){p=n*3.141592653589793/180.0;n=+S(+p);q=+T(+p);r=o*n-b*q;s=b*n+o*q}else{r=o;s=b}}else{r=j*+h[d+56>>3]+a*+h[d+64>>3];s=j*+h[d+72>>3]+a*+h[d+80>>3]}t=(c[d+3304>>2]|0)==0|0;a=(90.0- +h[d+(t<<3)+688>>3])*3.141592653589793/180.0;j=+S(+a);b=+T(+a);o=+h[d+3176>>3]*3.141592653589793/180.0;u=c[d+5960>>2]|0;if((u|0)==0){v=r}else{v=r+ +hd(u,r,s)}u=c[d+5964>>2]|0;if((u|0)==0){w=s}else{w=s+ +hd(u,r,s)}s=+Q(+(v*v+w*w));if(s==0.0){x=0.0}else{x=+Y(+v,+-w)}w=+Y(+(+h[d+3192>>3]),+s);s=+S(+w);v=+T(+w);r=x-o;o=+S(+r);x=+T(+r);q=j*s;n=b*v-q*o;if(+P(+n)<1.0e-5){y=q*(1.0-o)- +S(+(a+w))}else{y=n}n=s*x;if(y!=0.0|n!=-0.0){z=+Y(+-n,+y)}else{z=r+3.141592653589793}x=+h[d+((t^1)<<3)+688>>3];q=x+z*180.0/3.141592653589793;if(!(x>=0.0)){if(q>0.0){A=q+-360.0}else{A=q}}else{if(q<0.0){A=q+360.0}else{A=q}}if(!(A>360.0)){if(A<-360.0){B=A+360.0}else{B=A}}else{B=A+-360.0}if(+qa(+r,3.141592653589793)==0.0){r=(w+a*o)*180.0/3.141592653589793;if(r>90.0){C=180.0-r}else{C=r}if(!(C<-90.0)){k=0;l=C;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}k=0;l=-180.0-C;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}C=j*v+b*s*o;if(!(+P(+C)>.99)){k=0;l=+W(+C)*180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}o=+V(+(+Q(+(n*n+y*y))));if(!(C>=0.0)){k=0;l=o*-180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}else{k=0;l=o*180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}return 0}function fd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0,D=0,E=0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0,U=0.0,X=0.0,Z=0.0,_=0,$=0.0,aa=0.0,ba=0.0;g=i;j=d+3304|0;k=(c[j>>2]|0)==0|0;l=(a- +h[d+((k^1)<<3)+688>>3])*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+l);m=+T(+l);n=+S(+a);o=+T(+a);p=(90.0- +h[d+(k<<3)+688>>3])*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=+h[d+3176>>3];if(s==999.0){t=3.141592653589793}else{t=s*3.141592653589793/180.0}s=n*q;u=o*r-b*s;if(+P(+u)<1.0e-5){v=(1.0-b)*s- +S(+(a+p))}else{v=u}u=m*n;if(v!=0.0|u!=-0.0){w=+Y(+-u,+v)}else{w=l+-3.141592653589793}m=t+w;if(!(m>3.141592653589793)){if(m<-3.141592653589793){x=m+6.283185307179586}else{x=m}}else{x=m+-6.283185307179586}do{if(+qa(+l,3.141592653589793)==0.0){m=a+b*p;if(m>1.5707963267948966){y=3.141592653589793-m}else{y=m}if(y<-1.5707963267948966){z=-3.141592653589793-y}else{z=y}}else{m=o*q+b*n*r;if(!(+P(+m)>.99)){z=+W(+m);break}w=+V(+(+Q(+(u*u+v*v))));if(!(m>=0.0)){z=-w}else{z=w}}}while(0);v=+T(+z);do{if(v==0.0){A=0.0;B=0.0}else{u=+h[d+3192>>3]*+S(+z)/v;k=d+5960|0;C=c[k>>2]|0;D=d+5964|0;if((C|0)==0?(c[D>>2]|0)==0:0){E=(c[j>>2]|0)==0;r=u*+T(+x);n=-(u*+S(+x));A=E?r:n;B=E?n:r;break}r=u*+T(+x);n=u*+S(+x);E=C;C=1;u=r;b=-n;while(1){if((E|0)==0){F=u;G=1.0;H=0.0}else{q=u+ +hd(E,u,b);o=+id(c[k>>2]|0,u,b,1,0)+1.0;F=q;G=o;H=+id(c[k>>2]|0,u,b,0,1)}o=F-r;I=c[D>>2]|0;if((I|0)==0){J=b;K=0.0;L=1.0}else{q=b+ +hd(I,u,b);y=+id(c[D>>2]|0,u,b,1,0);J=q;K=y;L=+id(c[D>>2]|0,u,b,0,1)+1.0}y=n+J;q=G*L-H*K;if(q==0.0){M=u;N=b;break}p=(H*y-o*L)/q;a=(o*K-G*y)/q;q=u+p;l=b+a;I=+P(+p)>+P(+a);w=I?p:a;a=+P(+w);I=+P(+o)>+P(+y);p=I?o:y;I=a>+P(+p);if(!(!(+P(+(I?w:p))<2.8e-8)&(C|0)<500)){M=q;N=l;break}E=c[k>>2]|0;C=C+1|0;u=q;b=l}C=(c[j>>2]|0)==0;A=C?M:N;B=C?N:M}}while(0);if((c[d+3300>>2]|0)!=0){h[e>>3]=A*+h[d+88>>3]+B*+h[d+96>>3];h[f>>3]=A*+h[d+104>>3]+B*+h[d+112>>3];O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}M=+h[d+48>>3];if(M!=0.0){N=M*3.141592653589793/180.0;M=+S(+N);G=+T(+N);h[e>>3]=A*M+B*G;ba=B*M-A*G}else{h[e>>3]=A;ba=B}h[f>>3]=ba;ba=+h[d+32>>3];if(ba!=0.0){h[e>>3]=+h[e>>3]/ba}ba=+h[d+40>>3];if(!(ba!=0.0)){O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}h[f>>3]=+h[f>>3]/ba;O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}function gd(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=i;i=i+16|0;e=d;if((a[b+1|0]|0)==0){f=0;i=d;return f|0}g=gg(160)|0;c[e>>2]=b;j=b;k=b;b=g;g=0;l=20;a:while(1){if((a[k]|0)==0){break}m=+wg(j,e);n=c[e>>2]|0;o=a[n]|0;if(o<<24>>24==46){p=n+1|0;c[e>>2]=p;q=a[p]|0;r=p}else{q=o;r=n}if(q<<24>>24==0){break}n=g+1|0;if((n|0)<(l|0)){s=r;t=b;u=l}else{o=l+20|0;p=jg(b,o<<3)|0;s=c[e>>2]|0;t=p;u=o}h[t+(g<<3)>>3]=m;o=s;while(1){if((a[o]|0)==32){o=o+1|0}else{j=o;k=s;b=t;g=n;l=u;continue a}}}u=jd(b)|0;hg(b);f=(g|0)==0?0:u;i=d;return f|0}function hd(a,b,d){a=a|0;b=+b;d=+d;var e=0,f=0,g=0,j=0.0,k=0.0,l=0,m=0.0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0,F=0,G=0,H=0,I=0,J=0.0,K=0,L=0.0,M=0,N=0.0,O=0;e=i;f=c[a+32>>2]|0;if((f|0)==1){g=c[a+36>>2]|0;j=+h[a+8>>3];k=+h[a>>3];l=c[a+56>>2]|0;h[l>>3]=1.0;if(((g|0)!=1?(m=(j+b)*k,h[l+8>>3]=m,(g|0)>2):0)?(k=m*2.0,j=k*m+-1.0,h[l+16>>3]=j,(g|0)!=3):0){m=j;n=3;p=2;while(1){m=k*m- +h[l+(p+ -1<<3)>>3];h[l+(n<<3)>>3]=m;q=n+1|0;if((q|0)==(g|0)){break}else{r=n;n=q;p=r}}}p=c[a+40>>2]|0;m=+h[a+24>>3];k=+h[a+16>>3];n=c[a+60>>2]|0;h[n>>3]=1.0;if((p|0)!=1){j=(m+d)*k;h[n+8>>3]=j;if((p|0)>2){k=j*2.0;m=k*j+-1.0;h[n+16>>3]=m;if((p|0)==3){s=l;t=n;u=3;v=g;w=25}else{j=m;r=3;q=2;while(1){m=k*j- +h[n+(q+ -1<<3)>>3];h[n+(r<<3)>>3]=m;x=r+1|0;if((x|0)==(p|0)){y=g;z=p;A=l;B=n;w=26;break}else{C=r;j=m;r=x;q=C}}}}else{y=g;z=p;A=l;B=n;w=26}}else{s=l;t=n;u=1;v=g;w=25}}else if((f|0)==3){g=c[a+36>>2]|0;n=c[a+56>>2]|0;h[n>>3]=1.0;if((g|0)!=1?(h[n+8>>3]=b,(g|0)>2):0){j=b;l=2;do{j=j*b;h[n+(l<<3)>>3]=j;l=l+1|0}while((l|0)!=(g|0))}l=c[a+40>>2]|0;p=c[a+60>>2]|0;h[p>>3]=1.0;if((l|0)!=1){h[p+8>>3]=d;if((l|0)>2){j=d;q=2;while(1){k=j*d;h[p+(q<<3)>>3]=k;r=q+1|0;if((r|0)==(l|0)){y=g;z=l;A=n;B=p;w=26;break}else{j=k;q=r}}}else{y=g;z=l;A=n;B=p;w=26}}else{s=n;t=p;u=1;v=g;w=25}}else if((f|0)==2){f=c[a+36>>2]|0;j=+h[a+8>>3];k=+h[a>>3];g=c[a+56>>2]|0;h[g>>3]=1.0;if(((f|0)!=1?(m=(j+b)*k,h[g+8>>3]=m,(f|0)>2):0)?(k=(m*m*3.0+-1.0)*.5,h[g+16>>3]=k,(f|0)!=3):0){p=3;b=k;n=2;while(1){k=+(p|0);b=(b*m*(k*2.0+-1.0)- +h[g+(n+ -1<<3)>>3]*(k+-1.0))/k;h[g+(p<<3)>>3]=b;l=p+1|0;if((l|0)==(f|0)){break}else{q=p;p=l;n=q}}}n=c[a+40>>2]|0;b=+h[a+24>>3];m=+h[a+16>>3];p=c[a+60>>2]|0;h[p>>3]=1.0;if((n|0)!=1){k=(b+d)*m;h[p+8>>3]=k;if((n|0)>2){m=(k*k*3.0+-1.0)*.5;h[p+16>>3]=m;if((n|0)==3){s=g;t=p;u=3;v=f;w=25}else{q=3;d=m;l=2;while(1){m=+(q|0);b=(d*k*(m*2.0+-1.0)- +h[p+(l+ -1<<3)>>3]*(m+-1.0))/m;h[p+(q<<3)>>3]=b;r=q+1|0;if((r|0)==(n|0)){y=f;z=n;A=g;B=p;w=26;break}else{C=q;q=r;d=b;l=C}}}}else{y=f;z=n;A=g;B=p;w=26}}else{s=g;t=p;u=1;v=f;w=25}}else{ab(10400,33,1,c[o>>2]|0)|0;D=0.0;i=e;return+D}if((w|0)==25){E=(v|0)>(u|0)?v:u;F=t;G=u;H=s;I=v}else if((w|0)==26){if((z|0)>0){E=(y|0)>(z|0)?y:z;F=B;G=z;H=A;I=y}else{D=0.0;i=e;return+D}}y=c[a+44>>2]|0;A=a+52|0;if((y|0)==2){a=0;z=0;d=0.0;B=I;while(1){if((B|0)>0){w=c[A>>2]|0;k=0.0;v=z;s=0;while(1){k=k+ +h[w+(v<<3)>>3]*+h[H+(s<<3)>>3];s=s+1|0;if((s|0)==(B|0)){break}else{v=v+1|0}}J=k;K=B+z|0}else{J=0.0;K=z}b=d+J*+h[F+(a<<3)>>3];v=(((a+1+I|0)>(E|0))<<31>>31)+B|0;s=a+1|0;if((s|0)<(G|0)){a=s;z=K;d=b;B=v}else{D=b;break}}i=e;return+D}else if((y|0)==0){y=0;B=0;d=0.0;K=I;while(1){if((K|0)>0){z=c[A>>2]|0;J=0.0;a=B;E=0;while(1){J=J+ +h[z+(a<<3)>>3]*+h[H+(E<<3)>>3];E=E+1|0;if((E|0)==(K|0)){break}else{a=a+1|0}}L=J;M=K+B|0}else{L=0.0;M=B}k=d+L*+h[F+(y<<3)>>3];a=y+1|0;if((a|0)<(G|0)){y=a;B=M;d=k;K=1}else{D=k;break}}i=e;return+D}else{K=0;M=0;d=0.0;while(1){if((I|0)>0){B=c[A>>2]|0;L=0.0;y=M;a=0;while(1){L=L+ +h[B+(y<<3)>>3]*+h[H+(a<<3)>>3];a=a+1|0;if((a|0)==(I|0)){break}else{y=y+1|0}}N=L;O=I+M|0}else{N=0.0;O=M}J=d+N*+h[F+(K<<3)>>3];y=K+1|0;if((y|0)<(G|0)){K=y;M=O;d=J}else{D=J;break}}i=e;return+D}return 0.0}function id(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0.0,O=0,P=0,Q=0,S=0,T=0.0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0.0,$=0.0,ba=0.0,ca=0.0,da=0,ea=0.0,fa=0.0;g=i;i=i+16|0;j=g;if((a|0)==0){k=0.0;i=g;return+k}l=f|e;if((l|0)<0){ab(10440,46,1,c[o>>2]|0)|0;k=0.0;i=g;return+k}if((l|0)==0){k=+hd(a,b,d);i=g;return+k}l=gg(64)|0;m=a+36|0;n=c[m>>2]|0;p=n+ -1|0;q=(p|0)>(e|0)?e:p;p=a+40|0;e=c[p>>2]|0;r=e+ -1|0;s=(r|0)>(f|0)?f:r;r=c[a+32>>2]|0;t=l+32|0;c[t>>2]=r;if(!((r+ -1|0)>>>0<3)){u=c[o>>2]|0;c[j>>2]=r;za(u|0,10488,j|0)|0;k=0.0;i=g;return+k}j=c[a+44>>2]|0;u=l+44|0;c[u>>2]=j;do{if((j|0)==2){r=((n|0)>(e|0)?n:e)-s-q|0;v=n-q|0;w=(r|0)<(v|0)?r:v;v=(w|0)<1?1:w;w=l+36|0;c[w>>2]=v;x=e-s|0;y=(r|0)<(x|0)?r:x;x=(y|0)<1?1:y;y=l+40|0;c[y>>2]=x;r=(v|0)<(x|0)?v:x;z=(aa(x,v)|0)-((aa(r+ -1|0,r)|0)/2|0)|0;r=l+48|0;c[r>>2]=z;A=r;B=w;C=y;D=z;E=v;F=x}else if((j|0)==0){x=(q|0)>0;v=(s|0)>0;if(x&v){z=l+36|0;c[z>>2]=1;y=l+40|0;c[y>>2]=1;w=l+48|0;c[w>>2]=1;A=w;B=z;C=y;D=1;E=1;F=1;break}if(x){x=n-q|0;y=(x|0)<1?1:x;x=l+36|0;c[x>>2]=y;z=l+40|0;c[z>>2]=1;w=l+48|0;c[w>>2]=y;A=w;B=x;C=z;D=y;E=y;F=1;break}if(v){v=l+36|0;c[v>>2]=1;y=e-s|0;z=(y|0)<1?1:y;y=l+40|0;c[y>>2]=z;x=l+48|0;c[x>>2]=z;A=x;B=v;C=y;D=z;E=1;F=z;break}else{A=l+48|0;B=l+36|0;C=l+40|0;D=0;E=0;F=0;break}}else{z=n-q|0;y=(z|0)<1?1:z;z=l+36|0;c[z>>2]=y;v=e-s|0;x=(v|0)<1?1:v;v=l+40|0;c[v>>2]=x;w=aa(x,y)|0;r=l+48|0;c[r>>2]=w;A=r;B=z;C=v;D=w;E=y;F=x}}while(0);h[l>>3]=+h[a>>3];h[l+8>>3]=+h[a+8>>3];n=l+16|0;h[n>>3]=+h[a+16>>3];h[l+24>>3]=+h[a+24>>3];j=l+52|0;c[j>>2]=gg(D<<3)|0;D=l+56|0;c[D>>2]=gg(E<<3)|0;E=l+60|0;c[E>>2]=gg(F<<3)|0;F=a+48|0;x=c[F>>2]|0;y=x<<3;w=c[2632]|0;if((y|0)>(w|0)){if((w|0)>0){G=jg(c[2634]|0,y)|0}else{G=gg(y)|0}c[2634]=G;c[2632]=y;H=G;I=c[F>>2]|0}else{H=c[2634]|0;I=x}if((I|0)>0){x=c[a+52>>2]|0;a=0;do{h[H+(a<<3)>>3]=+h[x+(a<<3)>>3];a=a+1|0}while((a|0)!=(I|0))}a=c[u>>2]|0;a:do{if((a|0)==1){u=c[p>>2]|0;x=u+ -1|0;if((u|0)>(s|0)){u=c[m>>2]|0;F=c[B>>2]|0;G=aa(x,u)|0;y=aa((c[C>>2]|0)+ -1|0,F)|0;w=1-s|0;v=q+1|0;z=(u|0)<(v|0);r=(F|0)>0;J=0-u|0;K=1-q|0;L=x;x=H+(G<<3)|0;G=(c[j>>2]|0)+(y<<3)|0;while(1){y=w+L|0;if((L|0)>=(y|0)){M=L;while(1){if(r){N=+(M|0);O=0;do{P=x+(O+q<<3)|0;h[P>>3]=N*+h[P>>3];O=O+1|0}while((O|0)<(F|0))}if((M|0)>(y|0)){M=M+ -1|0}else{break}}}if(!z){M=u;while(1){y=K+M|0;O=M+ -1|0;if((M|0)>=(y|0)){P=x+(O<<3)|0;N=+h[P>>3];Q=M;while(1){S=Q+ -1|0;T=+(S|0)*N;if((Q|0)>(y|0)){N=T;Q=S}else{break}}h[P>>3]=T}if((M|0)>(v|0)){M=O}else{break}}}if(r){M=0;do{h[G+(M<<3)>>3]=+h[x+(M+q<<3)>>3];M=M+1|0}while((M|0)<(F|0))}if((L|0)>(s|0)){L=L+ -1|0;x=x+(J<<3)|0;G=G+(0-F<<3)|0}else{break}}}}else if((a|0)==2){F=c[m>>2]|0;G=c[p>>2]|0;J=((F|0)>(G|0)?F:G)+1|0;x=c[B>>2]|0;L=c[C>>2]|0;r=s+1|0;if((G|0)>=(r|0)){v=r+((x|0)>(L|0)?x:L)|0;L=1-s|0;K=q+1|0;u=1-q|0;z=G;G=H+(I<<3)|0;w=(c[j>>2]|0)+(c[A>>2]<<3)|0;while(1){M=J-z|0;Q=(M|0)<(F|0)?M:F;M=(Q|0)<0?0:Q;Q=v-z|0;y=(Q|0)<(x|0)?Q:x;Q=(y|0)<0?0:y;y=G+(0-M<<3)|0;S=w+(0-Q<<3)|0;U=L+z|0;if((z|0)>(U|0)){V=(Q|0)>0;W=q-M|0;X=z;do{X=X+ -1|0;if(V){N=+(X|0);Y=0;do{Z=G+(W+Y<<3)|0;h[Z>>3]=N*+h[Z>>3];Y=Y+1|0}while((Y|0)<(Q|0))}}while((X|0)>(U|0))}if((M|0)>=(K|0)){U=M;while(1){X=u+U|0;W=U+ -1|0;if((U|0)>=(X|0)){V=G+(W-M<<3)|0;N=+h[V>>3];Y=U;while(1){O=Y+ -1|0;_=+(O|0)*N;if((Y|0)>(X|0)){N=_;Y=O}else{break}}h[V>>3]=_}if((U|0)>(K|0)){U=W}else{break}}}if((Q|0)>0){U=q-M|0;Y=0;do{h[w+(Y-Q<<3)>>3]=+h[G+(U+Y<<3)>>3];Y=Y+1|0}while((Y|0)<(Q|0))}if((z|0)>(r|0)){z=z+ -1|0;G=y;w=S}else{break}}}}else{w=(q|0)>0;G=(s|0)>0;if(w&G){h[c[j>>2]>>3]=0.0;break}if(w){w=c[m>>2]|0;z=q+1|0;if((w|0)<(z|0)){break}r=1-q|0;K=w;w=(c[j>>2]|0)+((c[A>>2]|0)+ -1<<3)|0;while(1){u=r+K|0;L=K+ -1|0;x=H+(L<<3)|0;N=+h[x>>3];if((K|0)<(u|0)){$=N}else{ba=N;v=K;while(1){F=v+ -1|0;ca=ba*+(F|0);if((v|0)>(u|0)){ba=ca;v=F}else{break}}h[x>>3]=ca;$=ca}h[w>>3]=$;if((K|0)>(z|0)){K=L;w=w+ -8|0}else{break a}}}if(G){w=H+(I+ -1<<3)|0;K=c[j>>2]|0;z=c[p>>2]|0;r=s+1|0;if((z|0)<(r|0)){da=w}else{v=1-s|0;u=0-e|0;S=~f;y=((u|0)>(S|0)?u:S)+ -1|0;S=~z;u=I+ -3-(z+((y|0)>(S|0)?y:S))|0;S=z;z=w;while(1){w=v+S|0;if((S|0)>=(w|0)){ba=+h[z>>3];y=S;while(1){F=y+ -1|0;ea=+(F|0)*ba;if((y|0)>(w|0)){ba=ea;y=F}else{break}}h[z>>3]=ea}if((S|0)>(r|0)){S=S+ -1|0;z=z+ -8|0}else{break}}da=H+(u<<3)|0}z=c[A>>2]|0;if((z|0)>0){S=0;while(1){r=S+1|0;h[K+(S<<3)>>3]=+h[da+(r<<3)>>3];if((r|0)<(z|0)){S=r}else{break}}}}}}while(0);ea=+hd(l,b,d);if((c[t>>2]|0)==3){if((l|0)==0){k=ea;i=g;return+k}else{fa=ea}}else{d=+R(+(+h[l>>3]),+(+(q|0)));fa=ea*d*+R(+(+h[n>>3]),+(+(s|0)))}s=c[D>>2]|0;if((s|0)!=0){hg(s)}s=c[E>>2]|0;if((s|0)!=0){hg(s)}s=c[j>>2]|0;if((s|0)!=0){hg(s)}hg(l);k=fa;i=g;return+k}function jd(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,l=0.0,m=0.0,n=0,p=0.0,q=0.0,r=0,s=0,t=0;b=i;i=i+16|0;d=b;e=~~(+h[a+8>>3]+.5);if((e|0)<1){f=c[o>>2]|0;c[d>>2]=e;za(f|0,10544,d|0)|0;g=0;i=b;return g|0}f=~~(+h[a+16>>3]+.5);if((f|0)<1){j=c[o>>2]|0;c[d>>2]=f;za(j|0,10584,d|0)|0;g=0;i=b;return g|0}l=+h[a+32>>3];m=+h[a+40>>3];if(m<=l){j=c[o>>2]|0;h[k>>3]=l;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];n=d+8|0;h[k>>3]=m;c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];za(j|0,10624,d|0)|0;g=0;i=b;return g|0}p=+h[a+48>>3];q=+h[a+56>>3];if(q<=p){j=c[o>>2]|0;h[k>>3]=p;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];n=d+8|0;h[k>>3]=q;c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];za(j|0,10664,d|0)|0;g=0;i=b;return g|0}j=~~(+h[a>>3]+.5);if(!((j+ -1|0)>>>0<3)){n=c[o>>2]|0;c[d>>2]=j;za(n|0,10704,d|0)|0;g=0;i=b;return g|0}d=gg(64)|0;c[d+36>>2]=e;h[d>>3]=2.0/(m-l);h[d+8>>3]=(l+m)*-.5;c[d+40>>2]=f;h[d+16>>3]=2.0/(q-p);h[d+24>>3]=(p+q)*-.5;n=~~+h[a+24>>3];c[d+44>>2]=n;if((n|0)==1){r=aa(f,e)|0;c[d+48>>2]=r;s=r}else if((n|0)==2){r=(e|0)<(f|0)?e:f;t=(aa(f,e)|0)-((aa(r+ -1|0,r)|0)/2|0)|0;c[d+48>>2]=t;s=t}else if((n|0)==0){n=e+ -1+f|0;c[d+48>>2]=n;s=n}else{s=0}c[d+32>>2]=j;j=gg(s<<3)|0;c[d+52>>2]=j;if((s|0)>0){n=0;do{h[j+(n<<3)>>3]=+h[a+(n+8<<3)>>3];n=n+1|0}while((n|0)<(s|0))}c[d+56>>2]=gg(e<<3)|0;c[d+60>>2]=gg(f<<3)|0;g=d;i=b;return g|0}function kd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0;d=i;i=i+16|0;e=d;f=d+8|0;g=gg(2e3)|0;j=gg(2e3)|0;if((Nc(a,10744,2e3,g)|0)==0){k=gg((Dg(a|0)|0)+200|0)|0;Kg(k|0,10752,161)|0;Fg(k|0,a|0)|0;Nc(k,10744,2e3,g)|0;Nc(k,10920,2e3,j)|0;hg(k)}Nc(a,10920,2e3,j)|0;a=gg(2e3)|0;k=gg(2e3)|0;l=b+3176|0;if((+h[l>>3]>360.0?(Xc(g,10928,l)|0)==0:0)?(Xc(j,10928,l)|0)==0:0){h[l>>3]=180.0}l=b+3192|0;if((Xc(g,10944,l)|0)==0?(Xc(j,10944,l)|0)==0:0){h[l>>3]=57.29577951308232}l=0;do{c[e>>2]=l;Na(f|0,10952,e|0)|0;m=b+(l<<3)+4096|0;if((Xc(g,f,m)|0)==0){h[m>>3]=0.0}l=l+1|0}while((l|0)!=10);do{if((Zc(g,10960,2e3,a)|0)==0){if((Zc(j,10960,2e3,a)|0)==0){c[b+5960>>2]=0;break}else{c[b+5960>>2]=gd(a)|0;break}}else{c[b+5960>>2]=gd(a)|0}}while(0);do{if((Zc(j,10968,2e3,k)|0)==0){if((Zc(g,10968,2e3,k)|0)==0){c[b+5964>>2]=0;n=9;break}else{c[b+5964>>2]=gd(k)|0;n=9;break}}else{c[b+5964>>2]=gd(k)|0;n=9}}while(0);while(1){o=n+ -1|0;if(!(+h[b+(n<<3)+4096>>3]==0.0)){p=27;break}if((n|0)>0){n=o}else{p=25;break}}if((p|0)==25){c[b+3276>>2]=o}else if((p|0)==27?(c[b+3276>>2]=n,(n|0)>2):0){q=+h[b+4104>>3];p=1;r=0.0;while(1){s=+(p|0)*3.141592653589793/180.0;t=0.0;o=n;do{t=s*t+ +(o|0)*+h[b+(o<<3)+4096>>3];o=o+ -1|0}while((o|0)>0);o=p+1|0;if(t<=0.0){u=q;v=r;break}if((o|0)<181){q=t;p=o;r=s}else{u=t;v=s;break}}a:do{if(!(t<=0.0)){w=3.141592653589793}else{r=u;q=t;p=1;x=v;y=s;while(1){z=x-r*(y-x)/(q-r);A=0.0;o=n;do{A=z*A+ +(o|0)*+h[b+(o<<3)+4096>>3];o=o+ -1|0}while((o|0)>0);if(+P(+A)<1.0e-13){w=z;break a}o=A<0.0;l=p+1|0;if((l|0)<11){r=o?r:A;q=o?A:q;p=l;x=o?x:z;y=o?z:y}else{w=z;break}}}}while(0);if((n|0)>-1){p=n;s=0.0;while(1){v=w*s+ +h[b+(p<<3)+4096>>3];if((p|0)>0){p=p+ -1|0;s=v}else{B=v;break}}}else{B=0.0}h[b+3240>>3]=w;h[b+3248>>3]=B}ac(b);hg(g);hg(j);hg(a);hg(k);if((c[b+5964>>2]|0)==0?(c[b+5960>>2]|0)==0:0){C=1;i=d;return C|0}C=0;i=d;return C|0} + + + +function ld(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,U=0.0,X=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0;g=i;j=a- +h[d+616>>3];a=b- +h[d+624>>3];do{if((c[d+3300>>2]|0)==0){b=+h[d+760>>3];if(!(b==0.0)?(k=+h[d+768>>3],!(k==0.0)):0){l=j*b;b=a*k;k=+h[d+48>>3];if(!(k!=0.0)){m=l;n=b;break}o=k*3.141592653589793/180.0;k=+S(+o);p=+T(+o);m=l*k-b*p;n=b*k+l*p;break}h[e>>3]=0.0;h[f>>3]=0.0;q=2;i=g;return q|0}else{m=j*+h[d+56>>3]+a*+h[d+64>>3];n=j*+h[d+72>>3]+a*+h[d+80>>3]}}while(0);r=(c[d+3304>>2]|0)==0|0;s=r^1;a=(90.0- +h[d+(r<<3)+688>>3])*3.141592653589793/180.0;j=+S(+a);p=+T(+a);l=+h[d+3176>>3]*3.141592653589793/180.0;r=c[d+3276>>2]|0;t=c[d+5960>>2]|0;if((t|0)==0){u=m}else{u=m+ +hd(t,m,n)}t=c[d+5964>>2]|0;if((t|0)==0){v=n}else{v=n+ +hd(t,m,n)}n=+Q(+(u*u+v*v));m=n/+h[d+3192>>3];if((r|0)<1){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}a:do{if((r|0)==2){n=+h[d+4112>>3];k=+h[d+4104>>3];b=k*k-n*4.0*(+h[d+4096>>3]-m);if(b<0.0){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}o=+Q(+b);b=n*2.0;n=(o-k)/b;w=(-k-o)/b;b=nw?n:w}else{x=b}if(x<0.0){if(!(x<-1.0e-13)){y=0.0;break}h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if(x>3.141592653589793){if(x>3.141592653589893){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}else{y=3.141592653589793}}else{y=x}}else if((r|0)==1){y=(m- +h[d+4096>>3])/+h[d+4104>>3]}else{b=+h[d+4096>>3];w=+h[d+3240>>3];n=+h[d+3248>>3];if(m>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if(m>n){if(!(m>n+1.0e-13)){y=w;break}h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if((r|0)>-1){z=0;A=b;B=n;C=0.0;D=w}else{o=0.0-m;t=0;k=b;b=n;n=0.0;E=w;while(1){w=(b-m)/(b-k);if(!(w<.1)){if(w>.9){F=.9}else{F=w}}else{F=.1}w=E-(E-n)*F;if(m>0.0){if(m<1.0e-13){y=w;break a}else{G=0.0;H=b;I=w;J=E}}else{if(o<1.0e-13){y=w;break a}else{G=k;H=0.0;I=n;J=w}}K=t+1|0;if(!(+P(+(J-I))<1.0e-13)&(K|0)<100){t=K;k=G;b=H;n=I;E=J}else{y=w;break a}}}while(1){E=(B-m)/(B-A);if(!(E<.1)){if(E>.9){L=.9}else{L=E}}else{L=.1}E=D-(D-C)*L;t=r;n=0.0;while(1){n=E*n+ +h[d+(t<<3)+4096>>3];if((t|0)<=0){break}else{t=t+ -1|0}}if(n>3];R=U+Z*180.0/3.141592653589793;if(!(U>=0.0)){if(R>0.0){_=R+-360.0}else{_=R}}else{if(R<0.0){_=R+360.0}else{_=R}}if(!(_>360.0)){if(_<-360.0){$=_+360.0}else{$=_}}else{$=_+-360.0}do{if(+qa(+m,3.141592653589793)==0.0){_=(v+a*l)*180.0/3.141592653589793;if(_>90.0){aa=180.0-_}else{aa=_}if(aa<-90.0){ba=-180.0-aa}else{ba=aa}}else{_=j*u+p*y*l;if(!(+P(+_)>.99)){ba=+W(+_)*180.0/3.141592653589793;break}R=+V(+(+Q(+(D*D+X*X))));if(!(_>=0.0)){ba=R*-180.0/3.141592653589793;break}else{ba=R*180.0/3.141592653589793;break}}}while(0);h[e>>3]=$;h[f>>3]=ba;q=0;i=g;return q|0}function md(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0,U=0.0,X=0.0,Z=0.0,_=0,$=0.0,aa=0.0,ba=0.0;g=i;j=d+3304|0;k=(c[j>>2]|0)==0|0;l=(a- +h[d+((k^1)<<3)+688>>3])*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+l);m=+T(+l);n=+S(+a);o=+T(+a);p=(90.0- +h[d+(k<<3)+688>>3])*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=+h[d+3176>>3];if(s==999.0){t=3.141592653589793}else{t=s*3.141592653589793/180.0}s=n*q;u=o*r-b*s;if(+P(+u)<1.0e-5){v=(1.0-b)*s- +S(+(a+p))}else{v=u}u=m*n;if(v!=0.0|u!=-0.0){w=+Y(+-u,+v)}else{w=l+-3.141592653589793}m=t+w;if(!(m>3.141592653589793)){if(m<-3.141592653589793){x=m+6.283185307179586}else{x=m}}else{x=m+-6.283185307179586}do{if(+qa(+l,3.141592653589793)==0.0){m=a+b*p;if(m>1.5707963267948966){y=3.141592653589793-m}else{y=m}if(y<-1.5707963267948966){z=-3.141592653589793-y}else{z=y}}else{m=o*q+b*n*r;if(!(+P(+m)>.99)){z=+W(+m);break}w=+V(+(+Q(+(u*u+v*v))));if(!(m>=0.0)){z=-w}else{z=w}}}while(0);v=1.5707963267948966-z;z=(v*(v*(v*(v*(v*(v*(v*(v*(v*(v*0.0+ +h[d+4168>>3])+ +h[d+4160>>3])+ +h[d+4152>>3])+ +h[d+4144>>3])+ +h[d+4136>>3])+ +h[d+4128>>3])+ +h[d+4120>>3])+ +h[d+4112>>3])+ +h[d+4104>>3])+ +h[d+4096>>3])*+h[d+3192>>3];k=d+5960|0;A=c[k>>2]|0;B=d+5964|0;if((A|0)==0?(c[B>>2]|0)==0:0){C=(c[j>>2]|0)==0;v=z*+T(+x);u=-(z*+S(+x));D=C?v:u;E=C?u:v}else{v=z*+T(+x);u=z*+S(+x);C=A;A=1;x=v;z=-u;while(1){if((C|0)==0){F=x;G=1.0;H=0.0}else{r=x+ +hd(C,x,z);n=+id(c[k>>2]|0,x,z,1,0)+1.0;F=r;G=n;H=+id(c[k>>2]|0,x,z,0,1)}n=F-v;I=c[B>>2]|0;if((I|0)==0){J=z;K=0.0;L=1.0}else{r=z+ +hd(I,x,z);b=+id(c[B>>2]|0,x,z,1,0);J=r;K=b;L=+id(c[B>>2]|0,x,z,0,1)+1.0}b=u+J;r=G*L-H*K;if(r==0.0){M=x;N=z;break}q=(H*b-n*L)/r;o=(n*K-G*b)/r;r=x+q;y=z+o;I=+P(+q)>+P(+o);p=I?q:o;o=+P(+p);I=+P(+n)>+P(+b);q=I?n:b;I=o>+P(+q);if(!(!(+P(+(I?p:q))<2.8e-8)&(A|0)<500)){M=r;N=y;break}C=c[k>>2]|0;A=A+1|0;x=r;z=y}A=(c[j>>2]|0)==0;D=A?M:N;E=A?N:M}if((c[d+3300>>2]|0)!=0){h[e>>3]=D*+h[d+88>>3]+E*+h[d+96>>3];h[f>>3]=D*+h[d+104>>3]+E*+h[d+112>>3];O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}M=+h[d+48>>3];if(M!=0.0){N=M*3.141592653589793/180.0;M=+S(+N);z=+T(+N);h[e>>3]=D*M+E*z;ba=E*M-D*z}else{h[e>>3]=D;ba=E}h[f>>3]=ba;ba=+h[d+32>>3];if(ba!=0.0){h[e>>3]=+h[e>>3]/ba}ba=+h[d+40>>3];if(!(ba!=0.0)){O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}h[f>>3]=+h[f>>3]/ba;O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}function nd(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0;f=i;g=(+h[c+224>>3]-(+h[c+176>>3]+a+-1.0+.5)*+h[c+192>>3])/1.0e3;a=((+h[c+184>>3]+b+-1.0+.5)*+h[c+200>>3]- +h[c+248>>3])/1.0e3;b=g*g;j=a*a;k=g*b;l=a*j;m=b+j;n=(k*+h[c+496>>3]+(l*+h[c+472>>3]+(m*+h[c+464>>3]+(b*+h[c+456>>3]+(+h[c+432>>3]+(a*+h[c+416>>3]+g*+h[c+424>>3])+j*+h[c+440>>3]+a*g*+h[c+448>>3])))+g*j*+h[c+480>>3]+b*a*+h[c+488>>3])+m*a*+h[c+504>>3]+m*m*a*+h[c+512>>3])/206264.8062470964;o=+h[c+160>>3];p=+U(+o);q=1.0-n*p;r=+Y(+((l*+h[c+336>>3]+(k*+h[c+312>>3]+(m*+h[c+304>>3]+(j*+h[c+296>>3]+(+h[c+272>>3]+(g*+h[c+256>>3]+a*+h[c+264>>3])+b*+h[c+280>>3]+a*g*+h[c+288>>3])))+a*b*+h[c+320>>3]+j*g*+h[c+328>>3])+m*g*+h[c+344>>3]+m*m*g*+h[c+352>>3])/206264.8062470964/+S(+o)),+q);o=r+ +h[c+152>>3];if(!(o<0.0)){s=o;t=s/.01745329252;h[d>>3]=t;u=+S(+r);v=n+p;w=v/q;x=u*w;y=+X(+x);z=y/.01745329252;h[e>>3]=z;i=f;return 0}s=o+6.28318530717959;t=s/.01745329252;h[d>>3]=t;u=+S(+r);v=n+p;w=v/q;x=u*w;y=+X(+x);z=y/.01745329252;h[e>>3]=z;i=f;return 0}function od(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,Q=0.0,R=0.0,U=0.0,V=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0;f=i;h[d>>3]=0.0;h[e>>3]=0.0;g=b*3.141592653589793/180.0;b=+T(+g);j=+S(+g);k=c+160|0;g=+h[k>>3];if(g==0.0){l=+h[c+8>>3]*3.141592653589793/180.0;h[k>>3]=l;m=l}else{m=g}g=+T(+m);l=+S(+m);k=c+152|0;m=+h[k>>3];if(m==0.0){n=+h[c+8>>3]*3.141592653589793/180.0;h[k>>3]=n;o=n}else{o=m}m=a*3.141592653589793/180.0-o;o=+S(+m);a=b*g+j*l*o;if(a==0.0){p=1;i=f;return p|0}n=j*+T(+m)*206264.8062470964/a;m=(b*l-j*g*o)*206264.8062470964/a;a=+h[c+168>>3];if(a==0.0){p=1;i=f;return p|0}o=+h[c+256>>3];g=+h[c+264>>3];j=+h[c+272>>3];l=+h[c+280>>3];b=+h[c+288>>3];q=+h[c+296>>3];r=+h[c+304>>3];s=+h[c+312>>3];t=+h[c+320>>3];u=+h[c+328>>3];v=+h[c+336>>3];w=+h[c+344>>3];x=+h[c+352>>3];y=l*2.0;z=r*2.0;A=s*3.0;B=t*2.0;C=q*2.0;D=u*2.0;E=v*3.0;F=w*2.0;G=x*4.0;H=+h[c+416>>3];I=+h[c+424>>3];J=+h[c+432>>3];K=+h[c+440>>3];L=+h[c+448>>3];M=+h[c+456>>3];N=+h[c+464>>3];O=+h[c+472>>3];Q=+h[c+480>>3];R=+h[c+488>>3];U=+h[c+496>>3];V=+h[c+504>>3];W=+h[c+512>>3];X=M*2.0;Y=N*2.0;Z=R*2.0;_=U*3.0;$=V*2.0;aa=W*4.0;ba=K*2.0;ca=O*3.0;da=Q*2.0;k=0;ea=n/a;fa=m/a;do{a=fa*ea;ga=ea*ea;ha=fa*fa;ia=fa*ga;ja=ha*ea;ka=ha+ga;la=ka*ka;ma=ea*ga;na=fa*ha;oa=ga*ga;pa=ha*ha;qa=ha*ga*6.0;ra=ha*u+(fa*b+(o+ea*y)+ea*z+ga*A+a*B)+(ha+ga*3.0)*w+(pa+(oa*5.0+qa))*x;sa=g+ea*b+fa*C+fa*z+ga*t+a*D+ha*E+a*F+ka*a*G;ta=I+fa*L+ea*X+ea*Y+ha*Q+a*Z+ga*_+a*$+ka*a*aa;ua=ga*R+(ea*L+(H+fa*ba)+fa*Y+ha*ca+a*da)+(ha*3.0+ga)*V+(oa+(pa*5.0+qa))*W;qa=j+(ea*o+fa*g)+ga*l+a*b+ha*q+ka*r+ma*s+ia*t+ja*u+na*v+ka*ea*w+la*ea*x-n;pa=J+(fa*H+ea*I)+ha*K+a*L+ga*M+ka*N+na*O+ja*Q+ia*R+ma*U+ka*fa*V+la*fa*W-m;la=ra*ua-sa*ta;ka=(sa*pa-qa*ua)/la;ua=(qa*ta-ra*pa)/la;ea=ea+ka;fa=fa+ua;if(+P(+ka)<5.0e-7?+P(+ua)<5.0e-7:0){break}k=k+1|0}while((k|0)<50);m=+h[c+192>>3];if(m==0.0){p=1;i=f;return p|0}W=+h[c+200>>3];if(W==0.0){p=1;i=f;return p|0}V=(fa*1.0e3+ +h[c+248>>3])/W;h[d>>3]=(+h[c+224>>3]-ea*1.0e3)/m- +h[c+176>>3]+1.0+-.5;m=V- +h[c+184>>3]+1.0+-.5;h[e>>3]=m;V=+h[d>>3];if(V<.5){p=-1;i=f;return p|0}if(V>+h[c+136>>3]+.5|m<.5){p=-1;i=f;return p|0}if(m>+h[c+144>>3]+.5){p=-1;i=f;return p|0}p=0;i=f;return p|0}function pd(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;i=i+16|0;e=d;d=c[o>>2]|0;c[e>>2]=a;c[e+4>>2]=b;za(d|0,10976,e|0)|0;hb(-1)}function qd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;f=i;i=i+544|0;g=f;h=f+24|0;j=f+8|0;k=ig(1,28)|0;if((k|0)==0){pd(10992,11016)}c[k+16>>2]=b;if((b|0)>4){c[g>>2]=b;c[g+4>>2]=4;Na(h|0,11040,g|0)|0;pd(11120,h)}if((b|0)==0){l=k+12|0}else{m=gg(b<<2)|0;n=k+12|0;c[n>>2]=m;if((m|0)==0){pd(10992,11136)}m=a;a=b;o=c[n>>2]|0;while(1){p=a+ -1|0;c[o>>2]=(c[m>>2]|0)+ -1;if((p|0)==0){l=n;break}else{m=m+4|0;a=p;o=o+4|0}}}c[k+24>>2]=e;a:do{if((e|0)!=0){o=c[l>>2]|0;a=e<<2;m=gg(a)|0;c[k+20>>2]=m;if((m|0)==0){pd(10992,11176)}Eg(j|0,0,a|0)|0;b:do{if((b|0)>0){a=0;while(1){m=c[o+(a<<2)>>2]|0;if((m|0)>=(e|0)){break}n=j+(m<<2)|0;c[n>>2]=(c[n>>2]|0)+1;a=a+1|0;if((a|0)>=(b|0)){break b}}pd(11216,11256)}}while(0);o=k+8|0;c[o>>2]=1;if((e|0)>0){a=c[k+20>>2]|0;n=d;m=1;p=0;while(1){q=n+4|0;r=c[n>>2]|0;c[a+(p<<2)>>2]=r;if((r|0)>10){break}s=c[j+(p<<2)>>2]|0;if((r|0)==0){t=1;u=1}else{v=r;w=1;x=1;while(1){y=aa(x,v+s|0)|0;z=v+ -1|0;A=aa(w,v)|0;if((z|0)==0){t=A;u=y;break}else{v=z;w=A;x=y}}}x=aa(m,(u|0)/(t|0)|0)|0;c[o>>2]=x;w=p+1|0;if((w|0)<(e|0)){n=q;m=x;p=w}else{B=x;break a}}c[g>>2]=r;c[g+4>>2]=10;Na(h|0,11264,g|0)|0;pd(11120,h)}else{B=1}}else{c[k+8>>2]=1;B=1}}while(0);h=gg(B<<3)|0;c[k>>2]=h;if((h|0)==0){pd(10992,11336)}h=ig(B,8)|0;c[k+4>>2]=h;if((h|0)==0){pd(10992,11376)}else{i=f;return k|0}return 0}function rd(a){a=a|0;var b=0;b=i;if((a|0)==0){i=b;return}hg(c[a+4>>2]|0);hg(c[a>>2]|0);hg(c[a+20>>2]|0);hg(c[a+12>>2]|0);hg(a);i=b;return}function sd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0.0,z=0.0,A=0,B=0,C=0,D=0;d=i;i=i+80|0;e=d;f=d+60|0;g=d+40|0;j=c[a+16>>2]|0;k=c[a>>2]|0;l=c[a+4>>2]|0;m=c[a+12>>2]|0;n=c[a+20>>2]|0;if((j|0)!=0){o=j+ -1|0;if((o|0)!=0){p=o;o=f;q=e;do{q=q+8|0;h[q>>3]=1.0;o=o+4|0;c[o>>2]=0;p=p+ -1|0}while((p|0)!=0)}p=c[a+24>>2]|0;if((p|0)!=0){o=n;n=p;p=g;while(1){n=n+ -1|0;c[p>>2]=c[o>>2];if((n|0)==0){break}else{o=o+4|0;p=p+4|0}}}p=g+(c[m>>2]<<2)|0;o=c[p>>2]|0;if((o|0)!=0){c[p>>2]=o+ -1}}o=l+8|0;r=+h[l>>3];l=k+8|0;h[k>>3]=1.0;c[f>>2]=1;s=+h[b>>3];h[e>>3]=s;k=(c[a+8>>2]|0)+ -1|0;if((k|0)==0){t=r;i=d;return+t}if((j|0)>0){u=s;v=k;w=l;x=o;y=r}else{z=s;a=k;k=l;l=o;s=r;while(1){h[k>>3]=z;r=s+z*+h[l>>3];o=a+ -1|0;if((o|0)==0){t=r;break}z=+h[e>>3];a=o;k=k+8|0;l=l+8|0;s=r}i=d;return+t}while(1){l=w+8|0;h[w>>3]=u;k=x+8|0;s=y+u*+h[x>>3];a=0;o=f;p=m;n=b;q=e;while(1){A=g+(c[p>>2]<<2)|0;B=c[A>>2]|0;c[A>>2]=B+ -1;C=c[o>>2]|0;if((B|0)!=0){D=13;break}c[g+(c[p>>2]<<2)>>2]=C;c[o>>2]=0;h[q>>3]=1.0;B=a+1|0;if((B|0)>=(j|0)){break}a=B;o=o+4|0;p=p+4|0;n=n+8|0;q=q+8|0}if((D|0)==13?(D=0,c[o>>2]=C+1,z=+h[n>>3]*+h[q>>3],h[q>>3]=z,(a|0)!=0):0){p=a;B=q;do{B=B+ -8|0;p=p+ -1|0;h[B>>3]=z}while((p|0)!=0)}p=v+ -1|0;if((p|0)==0){t=s;break}u=+h[e>>3];v=p;w=l;x=k;y=s}i=d;return+t}function td(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0.0,D=0.0,E=0,F=0,G=0,H=0,I=0.0,J=0,K=0,L=0,M=0;j=i;i=i+32|0;k=j;l=(b|0)!=0;m=(g|0)==0;if(m&(l^1)){pd(11416,11496)}n=c[a+8>>2]|0;o=c[a+16>>2]|0;p=aa(n,n)|0;q=c[a>>2]|0;r=ig(p,8)|0;if((r|0)==0){pd(10992,11512)}p=ig(n,8)|0;if((p|0)==0){pd(10992,11544)}if((f|0)!=0){s=(n|0)==0;t=(o|0)>0;u=e;e=d;d=f;f=g;g=b;while(1){b=d+ -1|0;if(l){if(t){v=0;w=g;while(1){h[k+(v<<3)>>3]=+h[w>>3];v=v+1|0;if((v|0)==(o|0)){break}else{w=w+8|0}}x=g+(o<<3)|0}else{x=g}+sd(a,k);if(m|s){y=f;z=x}else{w=q;v=f;A=n;while(1){A=A+ -1|0;h[v>>3]=+h[w>>3];if((A|0)==0){break}else{w=w+8|0;v=v+8|0}}y=f+(n<<3)|0;z=x}}else{if(s){y=f;z=g}else{v=q;w=f;A=n;while(1){A=A+ -1|0;h[v>>3]=+h[w>>3];if((A|0)==0){break}else{v=v+8|0;w=w+8|0}}y=f+(n<<3)|0;z=g}}if((u|0)==0){B=0;C=1.0}else{B=u+8|0;C=+h[u>>3]}w=e+8|0;D=+h[e>>3];if(!s){v=n;A=r;E=q;F=p;while(1){G=v+ -1|0;H=E+8|0;I=C*+h[E>>3];J=F+8|0;h[F>>3]=+h[F>>3]+D*I;K=A;L=q;M=n;while(1){M=M+ -1|0;h[K>>3]=+h[K>>3]+I*+h[L>>3];if((M|0)==0){break}else{K=K+8|0;L=L+8|0}}if((G|0)==0){break}else{v=G;A=A+(n<<3)|0;E=H;F=J}}}if((b|0)==0){break}else{u=B;e=w;d=b;f=y;g=z}}}ud(r,p,n);hg(r);if((n|0)==0){hg(p);i=j;return}r=p;z=c[a+4>>2]|0;a=n;while(1){a=a+ -1|0;h[z>>3]=+h[r>>3];if((a|0)==0){break}else{r=r+8|0;z=z+8|0}}hg(p);i=j;return}function ud(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=i;if((vd(a,b,c)|0)==0){i=d;return}e=c<<3;f=gg(aa(e,c)|0)|0;if((f|0)==0){pd(10992,11576)}g=gg(e)|0;if((g|0)==0){pd(10992,11600)}wd(a,b,c,c,f,g);hg(f);hg(g);i=d;return}function vd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0;d=i;e=gg(c<<3)|0;if((e|0)==0){pd(10992,11624)}f=(c|0)>0;if(f){g=0;a:do{j=aa(g,c)|0;k=e+(g<<3)|0;if((g|0)>0){l=g;do{m=aa(l,c)|0;n=g;o=+h[a+(l+j<<3)>>3];do{n=n+ -1|0;o=o- +h[a+(n+j<<3)>>3]*+h[a+(n+m<<3)>>3]}while((n|0)>0);if((g|0)==(l|0)){if(o<=0.0){p=15;break a}h[k>>3]=+Q(+o)}else{h[a+((aa(l,c)|0)+g<<3)>>3]=o/+h[k>>3]}l=l+1|0}while((l|0)<(c|0))}else{l=g;do{q=+h[a+(l+j<<3)>>3];if((g|0)==(l|0)){if(q<=0.0){p=15;break a}h[k>>3]=+Q(+q)}else{h[a+((aa(l,c)|0)+g<<3)>>3]=q/+h[k>>3]}l=l+1|0}while((l|0)<(c|0))}g=g+1|0}while((g|0)<(c|0));if((p|0)==15){hg(e);r=-1;i=d;return r|0}if(f){p=0;do{g=b+(p<<3)|0;q=+h[g>>3];if((p|0)>0){l=aa(p,c)|0;k=p;s=q;while(1){j=k+ -1|0;t=s- +h[a+(j+l<<3)>>3]*+h[b+(j<<3)>>3];if((j|0)>0){k=j;s=t}else{u=t;break}}}else{u=q}h[g>>3]=u/+h[e+(p<<3)>>3];p=p+1|0}while((p|0)!=(c|0));if(f){f=c;while(1){p=f+ -1|0;k=b+(p<<3)|0;u=+h[k>>3];if((f|0)<(c|0)){l=f;s=u;while(1){t=+h[a+((aa(l,c)|0)+p<<3)>>3];v=s-t*+h[b+(l<<3)>>3];j=l+1|0;if((j|0)==(c|0)){w=v;break}else{l=j;s=v}}}else{w=u}h[k>>3]=w/+h[e+(p<<3)>>3];if((p|0)>0){f=p}else{break}}}}}hg(e);r=0;i=d;return r|0}function wd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0.0,B=0.0,C=0,D=0.0,E=0.0,F=0.0,G=0,H=0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,S=0.0,T=0,U=0,V=0,W=0,X=0.0,Y=0,Z=0,_=0,$=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0.0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0.0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0.0,Fa=0.0,Ga=0.0,Ha=0.0,Ia=0.0,Ja=0.0,Ka=0.0,La=0.0,Ma=0.0,Na=0.0,Oa=0.0,Pa=0,Qa=0,Ra=0.0,Sa=0,Ta=0.0,Ua=0,Va=0,Wa=0.0;g=i;if((c|0)<(d|0)){pd(11648,11704)}j=d<<3;k=gg(j)|0;if((k|0)==0){pd(10992,11720)}l=gg(j)|0;if((l|0)==0){pd(10992,11744)}j=(d|0)>0;a:do{if(j){m=c+1|0;n=0.0;o=0.0;p=0;q=0.0;while(1){r=p+1|0;s=d-r|0;t=k+(p<<3)|0;h[t>>3]=o*q;u=c-p|0;b:do{if((u|0)>0?(v=a+((aa(p,m)|0)<<3)|0,w=(p|0)==(c|0),!w):0){x=v;y=u;z=0.0;while(1){y=y+ -1|0;z=z+ +P(+(+h[x>>3]));if((y|0)==0){break}else{x=x+8|0}}if(z!=0.0){if(w){A=0.0}else{x=v;y=u;B=0.0;while(1){C=y+ -1|0;D=+h[x>>3]/z;h[x>>3]=D;E=B+D*D;if((C|0)==0){A=E;break}else{x=x+8|0;y=C;B=E}}}B=+h[v>>3];E=+P(+(+Q(+A)));if(!(B>=0.0)){F=-E}else{F=E}E=-F;D=B*E-A;h[v>>3]=B+F;if((r|0)!=(d|0)){y=s;x=a+((aa(r,c)|0)+p<<3)|0;while(1){y=y+ -1|0;c:do{if(!w){C=v;G=x;H=u;B=0.0;while(1){I=H+ -1|0;J=B+ +h[G>>3]*+h[C>>3];if((I|0)==0){break}C=C+8|0;G=G+8|0;H=I;B=J}B=J/D;if(!w){H=v;G=x;C=u;while(1){I=C+ -1|0;h[G>>3]=+h[G>>3]+B*+h[H>>3];if((I|0)==0){break c}H=H+8|0;G=G+8|0;C=I}}}}while(0);if((y|0)==0){break}else{x=x+(c<<3)|0}}}if(w){K=E;L=z}else{x=v;y=u;while(1){C=y+ -1|0;h[x>>3]=z*+h[x>>3];if((C|0)==0){K=E;L=z;break b}x=x+8|0;y=C}}}else{K=0.0;L=z}}else{K=0.0;L=0.0}}while(0);E=K*L;u=f+(p<<3)|0;h[u>>3]=E;if(!((p|0)>=(c|0)|(r|0)==(d|0))){y=aa(r,c)|0;x=a+(y+p<<3)|0;v=x;w=s;D=0.0;while(1){w=w+ -1|0;D=D+ +P(+(+h[v>>3]));if((w|0)==0){break}else{v=v+(c<<3)|0}}if(D!=0.0){v=x;w=s;B=0.0;while(1){w=w+ -1|0;M=+h[v>>3]/D;h[v>>3]=M;B=B+M*M;if((w|0)==0){break}else{v=v+(c<<3)|0}}M=+h[x>>3];N=+P(+(+Q(+B)));if(!(M>=0.0)){O=-N}else{O=N}N=-O;R=M*N-B;S=M+O;h[x>>3]=S;v=k+(r<<3)|0;M=S;w=x;C=s;G=v;while(1){H=C+ -1|0;h[G>>3]=M/R;I=w+(c<<3)|0;if((H|0)==0){break}M=+h[I>>3];w=I;C=H;G=G+8|0}if((r|0)==(c|0)){T=x;U=s}else{G=c-r|0;C=a+(y+r<<3)|0;while(1){w=G+ -1|0;H=x;I=C;V=s;M=0.0;while(1){W=V+ -1|0;X=M+ +h[I>>3]*+h[H>>3];if((W|0)==0){Y=C;Z=s;_=v;break}H=H+(c<<3)|0;I=I+(c<<3)|0;V=W;M=X}while(1){Z=Z+ -1|0;h[Y>>3]=+h[Y>>3]+X*+h[_>>3];if((Z|0)==0){break}else{Y=Y+(c<<3)|0;_=_+8|0}}if((w|0)==0){T=x;U=s;break}else{G=w;C=C+8|0}}}while(1){C=U+ -1|0;h[T>>3]=D*+h[T>>3];if((C|0)==0){break}T=T+(c<<3)|0;U=C}$=+h[u>>3];ba=N;ca=D}else{$=E;ba=0.0;ca=D}}else{$=E;ba=0.0;ca=0.0}M=+P(+$);z=M+ +P(+(+h[t>>3]));da=n>z?n:z;if((r|0)==(d|0)){break}else{n=da;o=ba;p=r;q=ca}}p=d+ -1|0;if(j){q=ba;m=p;C=0;G=d;s=0;while(1){do{if((m|0)<(p|0)){if(q!=0.0){x=a+(m+(aa(G,c)|0)<<3)|0;v=e+((aa(m,d)|0)+G<<3)|0;y=e+((aa(G,d)|0)+G<<3)|0;o=+h[x>>3];n=q*o;V=(s|0)==0;if(V){break}else{ea=o;fa=x;ga=s;ha=v}while(1){I=ga+ -1|0;h[ha>>3]=ea/n;H=fa+(c<<3)|0;if((I|0)==0){break}ea=+h[H>>3];fa=H;ga=I;ha=ha+8|0}if(V){break}else{ia=s;ja=y}while(1){ia=ia+ -1|0;w=x;I=s;n=0.0;H=ja;while(1){W=I+ -1|0;ka=n+ +h[w>>3]*+h[H>>3];if((W|0)==0){la=s;ma=v;na=ja;break}w=w+(c<<3)|0;I=W;n=ka;H=H+8|0}while(1){la=la+ -1|0;h[na>>3]=+h[na>>3]+ka*+h[ma>>3];if((la|0)==0){break}else{ma=ma+8|0;na=na+8|0}}if((ia|0)==0){break}else{ja=ja+(d<<3)|0}}}if((s|0)!=0){v=s;x=e+(m+(aa(G,d)|0)<<3)|0;y=e+((aa(m,d)|0)+G<<3)|0;while(1){v=v+ -1|0;h[y>>3]=0.0;h[x>>3]=0.0;if((v|0)==0){break}else{x=x+(d<<3)|0;y=y+8|0}}}}}while(0);h[e+((aa(m,d)|0)+m<<3)>>3]=1.0;s=d-m|0;C=C+1|0;if((C|0)==(d|0)){break}else{r=m;q=+h[k+(m<<3)>>3];m=m+ -1|0;G=r}}if(j){G=~d;m=~c;C=(G|0)>(m|0)?G:m;m=a+((aa(-2-C|0,c)|0)+ -2-C<<3)|0;G=-8-(c<<3)|0;s=(C+c<<3)+16|0;p=~C;C=d;r=0;while(1){t=m+(aa(G,r)|0)|0;u=s+(r<<3)|0;y=C+ -1|0;x=d-C|0;v=c-y|0;q=+h[f+(y<<3)>>3];V=(aa(y,c)|0)+y|0;H=a+(V<<3)|0;I=a+(V+c<<3)|0;V=(C|0)==(d|0);if(!V){w=I;W=x;while(1){W=W+ -1|0;h[w>>3]=0.0;if((W|0)==0){break}else{w=w+(c<<3)|0}}}d:do{if(q!=0.0){E=1.0/q;if(!V){w=v+ -1|0;W=(w|0)==0;oa=(y|0)==(c|0);pa=x;qa=I;while(1){pa=pa+ -1|0;if(W){ra=0.0}else{sa=w;ta=H;ua=qa;D=0.0;while(1){va=ta+8|0;wa=ua+8|0;N=D+ +h[va>>3]*+h[wa>>3];xa=sa+ -1|0;if((xa|0)==0){ra=N;break}else{sa=xa;ta=va;ua=wa;D=N}}}D=+h[H>>3];N=E*(ra/D);e:do{if(!oa){n=D;ua=H;ta=qa;sa=v;while(1){wa=sa+ -1|0;va=ua+8|0;h[ta>>3]=+h[ta>>3]+N*n;if((wa|0)==0){break e}n=+h[va>>3];ua=va;ta=ta+8|0;sa=wa}}}while(0);if((pa|0)==0){break}else{qa=qa+(c<<3)|0}}}if((y|0)!=(c|0)){qa=H;pa=v;while(1){oa=pa+ -1|0;h[qa>>3]=E*+h[qa>>3];if((oa|0)==0){break d}qa=qa+8|0;pa=oa}}}else{if((y|0)!=(c|0)){Eg(t|0,0,u|0)|0}}}while(0);h[H>>3]=+h[H>>3]+1.0;u=r+1|0;if((u|0)==(p|0)){break}else{C=y;r=u}}if(j){r=(c|0)==0;C=d;p=0;f:while(1){s=C+ -1|0;G=f+(s<<3)|0;m=C+ -2|0;u=f+(m<<3)|0;t=k+(m<<3)|0;v=k+(s<<3)|0;I=0;x=p;while(1){V=s;pa=x;while(1){if(!((V|0)>-1)){ya=pa;za=93;break}qa=V+ -1|0;if(da+ +P(+(+h[k+(V<<3)>>3]))==da){Aa=qa;break}if(da+ +P(+(+h[f+(qa<<3)>>3]))==da){ya=qa;za=93;break}else{V=qa;pa=qa}}g:do{if((za|0)==93){za=0;pa=a+((aa(ya,c)|0)<<3)|0;if((V|0)>(s|0)){Aa=ya}else{qa=a+((aa(V,c)|0)<<3)|0;oa=V;q=1.0;while(1){E=q*+h[k+(oa<<3)>>3];N=+P(+E);if(da+N==da){Aa=ya;break g}w=f+(oa<<3)|0;D=+h[w>>3];n=+P(+D);if(!(N>n)){if(D!=0.0){o=N/n;Ba=n*+Q(+(o*o+1.0))}else{Ba=0.0}}else{o=n/N;Ba=N*+Q(+(o*o+1.0))}h[w>>3]=Ba;o=1.0/Ba;N=D*o;D=-(E*o);if(!r){w=pa;W=qa;sa=c;while(1){sa=sa+ -1|0;o=+h[W>>3];E=+h[w>>3];h[w>>3]=o*D+N*E;h[W>>3]=N*o-E*D;if((sa|0)==0){break}else{w=w+8|0;W=W+8|0}}}if((oa|0)>=(s|0)){Aa=ya;break g}qa=qa+(c<<3)|0;oa=oa+1|0;q=D}}}}while(0);Ca=+h[G>>3];if((V|0)==(s|0)){za=105;break}if((I|0)==99){break f}q=+h[f+(V<<3)>>3];N=+h[u>>3];E=+h[t>>3];o=+h[v>>3];n=((N-Ca)*(Ca+N)+(E-o)*(E+o))/(N*o*2.0);E=+P(+n);if(E>1.0){z=1.0/E;Da=E*+Q(+(z*z+1.0))}else{Da=+Q(+(E*E+1.0))}E=+P(+Da);if(!(n>=0.0)){Ea=-E}else{Ea=E}E=((q-Ca)*(Ca+q)+o*(N/(n+Ea)-o))/q;if((V|0)>(m|0)){Fa=E;Ga=q}else{oa=a+((aa(V,c)|0)<<3)|0;o=1.0;n=E;qa=V;E=1.0;pa=e+((aa(V,d)|0)<<3)|0;N=q;while(1){W=qa+1|0;q=+h[k+(W<<3)>>3];z=+h[f+(W<<3)>>3];M=E*q;R=o*q;q=+P(+n);B=+P(+M);if(!(q>B)){if(M!=0.0){S=q/B;Ha=B*+Q(+(S*S+1.0))}else{Ha=0.0}}else{S=B/q;Ha=q*+Q(+(S*S+1.0))}h[k+(qa<<3)>>3]=Ha;S=n/Ha;q=M/Ha;M=N*S+R*q;B=R*S-N*q;R=z*q;Ia=z*S;w=pa+(d<<3)|0;sa=d;ta=w;ua=pa;while(1){sa=sa+ -1|0;z=+h[ta>>3];Ja=+h[ua>>3];h[ua>>3]=q*z+S*Ja;h[ta>>3]=S*z-q*Ja;if((sa|0)==0){break}else{ta=ta+8|0;ua=ua+8|0}}Ja=+P(+M);z=+P(+R);do{if(!(Ja>z)){if(R!=0.0){Ka=Ja/z;La=z*+Q(+(Ka*Ka+1.0));za=130;break}else{h[f+(qa<<3)>>3]=0.0;Ma=S;Na=q;break}}else{Ka=z/Ja;La=Ja*+Q(+(Ka*Ka+1.0));za=130}}while(0);if((za|0)==130){za=0;h[f+(qa<<3)>>3]=La;if(La!=0.0){Ja=1.0/La;Ma=M*Ja;Na=R*Ja}else{Ma=S;Na=q}}Ja=B*Ma+Ia*Na;z=Ia*Ma-B*Na;ua=oa+(c<<3)|0;if(!r){ta=ua;sa=oa;wa=c;while(1){wa=wa+ -1|0;Ka=+h[ta>>3];Oa=+h[sa>>3];h[sa>>3]=Na*Ka+Ma*Oa;h[ta>>3]=Ma*Ka-Na*Oa;if((wa|0)==0){break}else{ta=ta+8|0;sa=sa+8|0}}}if((qa|0)<(m|0)){oa=ua;o=Ma;n=Ja;qa=W;E=Na;pa=w;N=z}else{Fa=Ja;Ga=z;break}}}h[k+(V<<3)>>3]=0.0;h[v>>3]=Fa;h[G>>3]=Ga;pa=I+1|0;if((pa|0)<100){I=pa;x=m}else{Pa=m;break}}if((za|0)==105){za=0;if(Ca<0.0){h[G>>3]=-Ca;m=d;x=e+((aa(s,d)|0)<<3)|0;while(1){I=m+ -1|0;h[x>>3]=-+h[x>>3];if((I|0)==0){Pa=Aa;break}else{m=I;x=x+8|0}}}else{Pa=Aa}}if((s|0)>0){C=s;p=Pa}else{break a}}pd(11768,11704)}}}}}while(0);Pa=(d|0)==0;if(!Pa){Aa=d;za=f;Ca=0.0;while(1){Aa=Aa+ -1|0;Ga=+h[za>>3];Ca=Ga>Ca?Ga:Ca;if((Aa|0)==0){break}else{za=za+8|0}}Ga=Ca*1.0e-11;if(!Pa){za=d;Aa=f;while(1){za=za+ -1|0;if(+h[Aa>>3]>3]=0.0}if((za|0)==0){break}else{Aa=Aa+8|0}}if(!Pa){Pa=(c|0)==0;Aa=d;za=a;a=l;ya=f;while(1){Aa=Aa+ -1|0;Ga=+h[ya>>3];if(Ga!=0.0){if(Pa){Qa=za;Ra=0.0}else{f=za;ja=b;ia=c;Ca=0.0;while(1){ia=ia+ -1|0;Ca=Ca+ +h[f>>3]*+h[ja>>3];if((ia|0)==0){break}else{f=f+8|0;ja=ja+8|0}}Qa=za+(c<<3)|0;Ra=Ca}Sa=Qa;Ta=Ra/Ga}else{Sa=za+(c<<3)|0;Ta=0.0}h[a>>3]=Ta;if((Aa|0)==0){break}else{za=Sa;a=a+8|0;ya=ya+8|0}}}}}if(j){Ua=0;Va=e}else{hg(l);hg(k);i=g;return}while(1){e=d;Ta=0.0;j=l;ya=Va;while(1){a=e+ -1|0;Wa=Ta+ +h[ya>>3]*+h[j>>3];if((a|0)==0){break}e=a;Ta=Wa;j=j+8|0;ya=ya+(d<<3)|0}h[b+(Ua<<3)>>3]=Wa;Ua=Ua+1|0;if((Ua|0)==(d|0)){break}else{Va=Va+8|0}}hg(l);hg(k);i=g;return}function xd(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0;f=i;i=i+32|0;g=f+8|0;h=f;j=f+16|0;k=h;c[k>>2]=5260110;c[k+4>>2]=5459015;k=e+4|0;a[k]=0;a[j]=0;l=e+20|0;c[l>>2]=-1;m=e+24|0;c[m>>2]=-1;n=e+28|0;c[n>>2]=-1;do{if((b|0)>0){o=e+8|0;p=e+13|0;q=0;r=0;a:while(1){s=d+(q*9|0)|0;do{if((a[d+(q*9|0)+4|0]|0)!=45){if((yg(s,11816)|0)==0){if(!((c[n>>2]|0)==-1)){t=1;u=35;break a}c[n>>2]=q;v=r}else{v=r}}else{w=d+(q*9|0)+5|0;x=c[2992]|0;b:do{if((x|0)>0){y=0;while(1){z=y+1|0;if((Ag(w,11976+(y<<2)|0,3)|0)==0){A=y;break b}if((z|0)<(x|0)){y=z}else{A=z;break}}}else{A=0}}while(0);if((A|0)==(x|0)){y=0;while(1){z=y+1|0;if((Ag(w,h+(y<<2)|0,3)|0)==0){B=y;break}if((z|0)<2){y=z}else{B=z;break}}if((B|0)==2){v=r;break}}if((a[k]|0)!=0){if((Ag(s,j,8)|0)!=0|(r|0)==0){t=1;u=35;break a}c[r>>2]=q;a[j]=0;v=r;break}c[g>>2]=w;Na(k|0,11832,g|0)|0;if((Ag(s,11840,4)|0)==0){c[l>>2]=q;a[o+0|0]=a[11848|0]|0;a[o+1|0]=a[11849|0]|0;a[o+2|0]=a[11850|0]|0;a[p]=4408644;a[p+1|0]=17221;a[p+2|0]=67;a[p+3|0]=0;c[g>>2]=k;Na(j|0,11856,g|0)|0;v=m;break}if((Ag(s,11864,4)|0)==0){c[m>>2]=q;a[o+0|0]=a[11848|0]|0;a[o+1|0]=a[11849|0]|0;a[o+2|0]=a[11850|0]|0;a[p]=4408644;a[p+1|0]=17221;a[p+2|0]=67;a[p+3|0]=0;c[g>>2]=k;Na(j|0,11872,g|0)|0;v=l;break}y=d+(q*9|0)+1|0;if((Ag(y,11880,3)|0)==0){c[l>>2]=q;c[g>>2]=a[s]|0;Na(o|0,11888,g|0)|0;c[g>>2]=a[s]|0;Na(p|0,11896,g|0)|0;c[g>>2]=p;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=m;break}if((Ag(y,11912,3)|0)==0){c[m>>2]=q;c[g>>2]=a[s]|0;Na(o|0,11888,g|0)|0;c[g>>2]=a[s]|0;Na(p|0,11896,g|0)|0;c[g>>2]=o;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=l;break}x=d+(q*9|0)+2|0;if((Ag(x,11920,2)|0)==0){c[l>>2]=q;z=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=z;Na(o|0,11928,g|0)|0;z=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=z;Na(p|0,11936,g|0)|0;c[g>>2]=p;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=m;break}if((Ag(x,11944,2)|0)!=0){t=1;u=35;break a}c[m>>2]=q;x=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=x;Na(o|0,11928,g|0)|0;x=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=x;Na(p|0,11936,g|0)|0;c[g>>2]=o;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=l}}while(0);s=q+1|0;if((s|0)<(b|0)){q=s;r=v}else{u=30;break}}if((u|0)==30){if((a[j]|0)==0){break}else{t=1}i=f;return t|0}else if((u|0)==35){i=f;return t|0}}}while(0);if((Ag(k,11952,3)|0)==0){a[k]=4998739;a[k+1|0]=19526;a[k+2|0]=76;a[k+3|0]=0;C=137}else{C=(a[k]|0)==0?999:137}c[e>>2]=C;t=0;i=f;return t|0}function yd(b,d,e,f,g,j,k,l,m,n,o){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0,t=0,u=0.0,v=0,w=0.0,x=0.0;p=i;q=n+4|0;if((c[d>>2]|0)!=137?(xd(c[q>>2]|0,b,d)|0)!=0:0){r=1;i=p;return r|0}b=c[q>>2]|0;if((b|0)>0){q=c[d+20>>2]|0;s=d+24|0;t=0;do{if((t|0)!=(q|0)?(t|0)!=(c[s>>2]|0):0){h[m+(t<<3)>>3]=+h[e+(t<<3)>>3]- +h[f+(t<<3)>>3]}t=t+1|0}while((t|0)<(b|0))}do{if((c[d>>2]|0)!=999){b=d+4|0;do{if((yg(b,11960)|0)==0){t=g+16|0;if(+h[t>>3]==0.0){r=2;i=p;return r|0}else{a[b]=5130579;a[b+1|0]=20041;a[b+2|0]=78;a[b+3|0]=0;h[l+40>>3]=0.0;u=+Re(+h[t>>3]);h[l+48>>3]=u/+Se(+h[t>>3]);t=l+4|0;c[t>>2]=c[t>>2]>>31;break}}}while(0);t=d+20|0;f=c[t>>2]|0;s=d+24|0;q=c[s>>2]|0;v=Fd(b,+h[e+(f<<3)>>3],+h[e+(q<<3)>>3],g,j,k,l,m+(f<<3)|0,m+(q<<3)|0)|0;if((v|0)!=0){r=v;i=p;return r|0}v=c[d+28>>2]|0;if(!((v|0)==-1)){u=+h[l+24>>3];if(u==0.0){w=90.0}else{w=u*3.141592653589793*.5}q=m+(c[s>>2]<<3)|0;u=+h[q>>3];if(u>3]=w+u;h[m+(v<<3)>>3]=5.0;break}x=w*.5;if(u>x){h[q>>3]=u-w;h[m+(v<<3)>>3]=0.0;break}q=m+(c[t>>2]<<3)|0;u=+h[q>>3];if(u>w*2.5){h[q>>3]=u-w*3.0;h[m+(v<<3)>>3]=4.0;break}if(u>w*1.5){h[q>>3]=u-w*2.0;h[m+(v<<3)>>3]=3.0;break}if(u>x){h[q>>3]=u-w;h[m+(v<<3)>>3]=2.0;break}else{h[m+(v<<3)>>3]=1.0;break}}}}while(0);l=(Cd(m,n,o)|0)==0;r=l?0:4;i=p;return r|0}function zd(b,d,e,f,g,j,k,l,m,n,o){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0.0,t=0.0;p=i;if((c[d>>2]|0)!=137?(xd(c[f+4>>2]|0,b,d)|0)!=0:0){q=1;i=p;return q|0}if((Dd(e,f,g)|0)!=0){q=4;i=p;return q|0}e=c[f+4>>2]|0;if((e|0)>0){f=c[d+20>>2]|0;b=d+24|0;r=0;do{if((r|0)!=(f|0)?(r|0)!=(c[b>>2]|0):0){h[o+(r<<3)>>3]=+h[g+(r<<3)>>3]+ +h[m+(r<<3)>>3]}r=r+1|0}while((r|0)<(e|0))}if((c[d>>2]|0)!=999){e=c[d+28>>2]|0;a:do{if(!((e|0)==-1)){s=+h[g+(e<<3)>>3];r=~~(s+.5);if(+P(+(s- +(r|0)))>1.0e-10){q=3;i=p;return q|0}s=+h[j+24>>3];if(s==0.0){t=90.0}else{t=s*3.141592653589793*.5}switch(r|0){case 2:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t+ +h[r>>3];break a;break};case 4:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t*3.0+ +h[r>>3];break a;break};case 3:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t*2.0+ +h[r>>3];break a;break};case 0:{r=g+(c[d+24>>2]<<3)|0;h[r>>3]=t+ +h[r>>3];break a;break};case 5:{r=g+(c[d+24>>2]<<3)|0;h[r>>3]=+h[r>>3]-t;break a;break};case 1:{break a;break};default:{q=3;i=p;return q|0}}}}while(0);e=d+4|0;do{if((yg(e,11960)|0)==0){r=n+16|0;if(+h[r>>3]==0.0){q=2;i=p;return q|0}else{a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;h[j+40>>3]=0.0;t=+Re(+h[r>>3]);h[j+48>>3]=t/+Se(+h[r>>3]);r=j+4|0;c[r>>2]=c[r>>2]>>31;break}}}while(0);r=c[d+20>>2]|0;m=c[d+24>>2]|0;d=Gd(e,+h[g+(r<<3)>>3],+h[g+(m<<3)>>3],j,k,l,n,o+(r<<3)|0,o+(m<<3)|0)|0;if((d|0)!=0){q=d;i=p;return q|0}}q=0;i=p;return q|0}function Ad(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;b=i;d=c[a+4>>2]|0;e=aa(d<<3,d)|0;f=gg(e)|0;c[a+20>>2]=f;if((f|0)==0){g=1;i=b;return g|0}j=gg(e)|0;c[a+24>>2]=j;if((j|0)==0){hg(f);g=1;i=b;return g|0}if((d|0)>0){e=a+16|0;k=a+12|0;l=0;m=0;while(1){n=(c[e>>2]|0)+(l<<3)|0;o=c[k>>2]|0;p=m;q=0;while(1){h[f+(p<<3)>>3]=+h[n>>3]*+h[o+(p<<3)>>3];q=q+1|0;if((q|0)==(d|0)){break}else{p=p+1|0}}l=l+1|0;if((l|0)==(d|0)){break}else{m=d+m|0}}}if((Bd(d,f,j)|0)!=0){g=2;i=b;return g|0}c[a>>2]=137;g=0;i=b;return g|0}function Bd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0,x=0,y=0,z=0,A=0,B=0;e=i;f=a<<2;g=gg(f)|0;if((g|0)==0){j=1;i=e;return j|0}k=gg(f)|0;if((k|0)==0){hg(g);j=1;i=e;return j|0}f=a<<3;l=gg(f)|0;if((l|0)==0){hg(g);hg(k);j=1;i=e;return j|0}m=gg(aa(f,a)|0)|0;if((m|0)==0){hg(g);hg(k);hg(l);j=1;i=e;return j|0}f=(a|0)>0;if(f){n=a<<3;o=0;p=0;while(1){c[g+(o<<2)>>2]=o;q=l+(o<<3)|0;h[q>>3]=0.0;Kg(m+(p<<3)|0,b+(p<<3)|0,n|0)|0;r=0.0;s=p;t=0;while(1){u=+P(+(+h[b+(s<<3)>>3]));if(u>r){h[q>>3]=u;v=u}else{v=r}t=t+1|0;if((t|0)==(a|0)){break}else{r=v;s=s+1|0}}o=o+1|0;if(v==0.0){w=17;break}if((o|0)>=(a|0)){break}else{p=p+a|0}}if((w|0)==17){hg(g);hg(k);hg(l);hg(m);j=2;i=e;return j|0}if(f){w=0;while(1){p=aa(w,a)|0;o=m+(p+w<<3)|0;b=l+(w<<3)|0;n=w+1|0;s=(n|0)<(a|0);if(s){v=+P(+(+h[o>>3]))/+h[b>>3];t=n;q=w;while(1){r=+P(+(+h[m+((aa(t,a)|0)+w<<3)>>3]));u=r/+h[l+(t<<3)>>3];x=u>v;q=x?t:q;t=t+1|0;if((t|0)==(a|0)){break}else{v=x?u:v}}if((q|0)>(w|0)){t=0;x=p;y=aa(q,a)|0;while(1){z=m+(y<<3)|0;v=+h[z>>3];A=m+(x<<3)|0;h[z>>3]=+h[A>>3];h[A>>3]=v;t=t+1|0;if((t|0)==(a|0)){break}else{x=x+1|0;y=y+1|0}}y=l+(q<<3)|0;v=+h[y>>3];h[y>>3]=+h[b>>3];h[b>>3]=v;y=g+(q<<2)|0;x=c[y>>2]|0;t=g+(w<<2)|0;c[y>>2]=c[t>>2];c[t>>2]=x}if(s){x=n;do{t=aa(x,a)|0;y=m+(t+w<<3)|0;v=+h[y>>3];a:do{if(v!=0.0){u=v/+h[o>>3];h[y>>3]=u;r=u;A=n;while(1){z=m+(A+t<<3)|0;h[z>>3]=+h[z>>3]-r*+h[m+(A+p<<3)>>3];z=A+1|0;if((z|0)==(a|0)){break a}r=+h[y>>3];A=z}}}while(0);x=x+1|0}while((x|0)!=(a|0))}}if((n|0)==(a|0)){break}else{w=n}}if(f){w=0;do{c[k+(c[g+(w<<2)>>2]<<2)>>2]=w;w=w+1|0}while((w|0)!=(a|0));if(f){w=a<<3;x=0;p=0;while(1){Eg(d+(p<<3)|0,0,w|0)|0;x=x+1|0;if((x|0)==(a|0)){break}else{p=p+a|0}}if(f){f=0;do{p=c[k+(f<<2)>>2]|0;h[d+((aa(p,a)|0)+f<<3)>>3]=1.0;x=p+1|0;if((x|0)<(a|0)){w=x;while(1){if((p|0)<(w|0)){x=aa(w,a)|0;o=d+(x+f<<3)|0;v=+h[o>>3];s=p;do{v=v- +h[m+(s+x<<3)>>3]*+h[d+((aa(s,a)|0)+f<<3)>>3];h[o>>3]=v;s=s+1|0}while((s|0)!=(w|0))}s=w+1|0;if((s|0)==(a|0)){B=a;break}else{w=s}}}else{B=a}while(1){w=B+ -1|0;p=aa(w,a)|0;n=d+(p+f<<3)|0;if((B|0)<(a|0)){v=+h[n>>3];s=B;do{v=v- +h[m+(s+p<<3)>>3]*+h[d+((aa(s,a)|0)+f<<3)>>3];h[n>>3]=v;s=s+1|0}while((s|0)!=(a|0))}h[n>>3]=+h[n>>3]/+h[m+(p+w<<3)>>3];if((w|0)>0){B=w}else{break}}f=f+1|0}while((f|0)!=(a|0))}}}}}hg(g);hg(k);hg(l);hg(m);j=0;i=e;return j|0}function Cd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0,r=0;e=i;f=c[b+4>>2]|0;if((c[b>>2]|0)!=137?(Ad(b)|0)!=0:0){g=1;i=e;return g|0}j=(f|0)>0;if(!j){g=0;i=e;return g|0}k=b+24|0;l=0;m=0;while(1){n=d+(l<<3)|0;h[n>>3]=0.0;o=c[k>>2]|0;p=0.0;q=m;r=0;while(1){p=p+ +h[o+(q<<3)>>3]*+h[a+(r<<3)>>3];h[n>>3]=p;r=r+1|0;if((r|0)==(f|0)){break}else{q=q+1|0}}l=l+1|0;if((l|0)==(f|0)){break}else{m=f+m|0}}if(!j){g=0;i=e;return g|0}j=c[b+8>>2]|0;b=0;while(1){m=d+(b<<3)|0;h[m>>3]=+h[j+(b<<3)>>3]+ +h[m>>3];m=b+1|0;if((m|0)==(f|0)){g=0;break}else{b=m}}i=e;return g|0}function Dd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0;e=i;f=c[b+4>>2]|0;if((c[b>>2]|0)!=137?(Ad(b)|0)!=0:0){g=1;i=e;return g|0}if((f|0)<=0){g=0;i=e;return g|0}Eg(d|0,0,f<<3|0)|0;j=c[b+8>>2]|0;k=b+20|0;b=0;while(1){l=+h[a+(b<<3)>>3]- +h[j+(b<<3)>>3];m=c[k>>2]|0;n=0;o=b;while(1){p=d+(n<<3)|0;h[p>>3]=+h[p>>3]+l*+h[m+(o<<3)>>3];n=n+1|0;if((n|0)==(f|0)){break}else{o=o+f|0}}o=b+1|0;if((o|0)==(f|0)){g=0;break}else{b=o}}i=e;return g|0}function Ed(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0,C=0.0,D=0.0;e=i;if((Hd(a,d)|0)!=0){f=1;i=e;return f|0}a=b+8|0;g=b+24|0;j=+h[g>>3]==999.0;k=d+16|0;l=+h[k>>3];do{if(!(l==90.0)){m=+h[b+16>>3];if(j){h[g>>3]=m>3]);o=+Re(+h[g>>3]);p=+Se(+h[g>>3]);q=+Re(+h[k>>3]);r=+Se(+h[k>>3]);s=o*q;o=+Q(+(s*s+r*r));do{if(o==0.0){if(m!=0.0){f=1;i=e;return f|0}else{t=+h[b+32>>3];break}}else{u=m/o;if(+P(+u)>1.0){f=1;i=e;return f|0}v=+Xe(r,s);w=+Ue(u);u=v+w;if(!(u>180.0)){if(u<-180.0){x=u+360.0}else{x=u}}else{x=u+-360.0}u=v-w;if(!(u>180.0)){if(u<-180.0){y=u+360.0}else{y=u}}else{y=u+-360.0}d=b+32|0;u=+h[d>>3];if(+P(+(u-x))<+P(+(u-y))){z=+P(+x)<90.0000000001;A=z?x:y}else{z=+P(+y)<90.0000000001;A=z?y:x}h[d>>3]=A;t=A}}while(0);d=b+40|0;z=b+48|0;h[z>>3]=90.0-t;s=n*+Re(t);do{if(+P(+s)<1.0e-10){if(+P(+n)<1.0e-10){o=+h[a>>3];h[d>>3]=o;h[z>>3]=90.0- +h[k>>3];B=a;C=o;break}if(t>0.0){o=+h[a>>3]+ +h[g>>3]+-180.0;h[d>>3]=o;h[z>>3]=0.0;B=a;C=o;break}if(t<0.0){o=+h[a>>3]- +h[g>>3];h[d>>3]=o;h[z>>3]=180.0;B=a;C=o;break}else{B=a;C=+h[d>>3];break}}else{o=(r-m*+Se(t))/s;u=p*q/n;if(o==0.0&u==0.0){f=1;i=e;return f|0}else{w=+h[a>>3];v=w- +Xe(u,o);h[d>>3]=v;B=a;C=v;break}}}while(0);if(!(+h[B>>3]>=0.0)){if(!(C>0.0)){D=t;break}h[d>>3]=C+-360.0;D=t;break}else{if(!(C<0.0)){D=t;break}h[d>>3]=C+360.0;D=t;break}}else{if(j){h[g>>3]=180.0}n=+h[b+16>>3];h[b+32>>3]=n;h[b+40>>3]=+h[a>>3];h[b+48>>3]=90.0-n;D=n}}while(0);h[b+56>>3]=+h[g>>3];g=b+48|0;h[b+64>>3]=+Re(+h[g>>3]);h[b+72>>3]=+Se(+h[g>>3]);c[b>>2]=137;b=+P(+D)>90.0000000001;f=b?2:0;i=e;return f|0}function Fd(a,b,d,e,f,g,j,k,l){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;m=i;if((c[e>>2]|0)!=137?(Ed(a,e,j)|0)!=0:0){n=1;i=m;return n|0}Pe(b,d,e+40|0,f,g)|0;e=lb[c[j+1888>>2]&63](+h[f>>3],+h[g>>3],j,k,l)|0;if((e|0)==0){n=0;i=m;return n|0}n=(e|0)==1?2:3;i=m;return n|0}function Gd(a,b,d,e,f,g,j,k,l){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;m=i;if((c[j>>2]|0)!=137?(Ed(a,j,e)|0)!=0:0){n=1;i=m;return n|0}a=lb[c[e+1892>>2]&63](b,d,e,f,g)|0;if((a|0)==0){Qe(+h[f>>3],+h[g>>3],j+40|0,k,l)|0;n=0;i=m;return n|0}else{n=(a|0)==1?2:3;i=m;return n|0}return 0}function Hd(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;e=i;if((yg(b,12080)|0)==0){Id(d)|0;f=0;i=e;return f|0}if((yg(b,12088)|0)==0){Jd(d)|0;f=0;i=e;return f|0}if((yg(b,12096)|0)==0){a[d]=5128532;a[d+1|0]=20033;a[d+2|0]=78;a[d+3|0]=0;g=d+4|0;c[g>>2]=(c[g>>2]>>31&-206)+103;h[d+8>>3]=0.0;h[d+16>>3]=90.0;g=d+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}c[d+1888>>2]=1;c[d+1892>>2]=2;g=99;while(1){if(!(+h[d+(g<<3)+280>>3]==0.0)){j=g;break}k=g+ -1|0;if(!(+h[d+(g+100<<3)+280>>3]==0.0)){j=g;break}if((g|0)>0){g=k}else{j=k;break}}c[d+276>>2]=(j|0)<0?0:j;f=0;i=e;return f|0}if((yg(b,12104)|0)==0){a[d]=4674643;a[d+1|0]=18260;a[d+2|0]=71;a[d+3|0]=0;c[d+4>>2]=104;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=114.59155902616465;h[d+120>>3]=.008726646259971648}else{m=l*2.0;h[d+112>>3]=m;h[d+120>>3]=1.0/m}c[d+1888>>2]=3;c[d+1892>>2]=4;f=0;i=e;return f|0}if((yg(b,12112)|0)==0){a[d]=5130579;a[d+1|0]=20041;a[d+2|0]=78;a[d+3|0]=0;j=d+4|0;c[j>>2]=(c[j>>2]>>31&-210)+105;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;m=+h[j>>3];if(m==0.0){h[j>>3]=57.29577951308232;n=57.29577951308232}else{n=m}h[d+112>>3]=1.0/n;n=+h[d+40>>3];m=+h[d+48>>3];l=n*n+m*m;h[d+120>>3]=l;h[d+128>>3]=l+1.0;h[d+136>>3]=l+-1.0;c[d+1888>>2]=5;c[d+1892>>2]=6;f=0;i=e;return f|0}if((yg(b,12120)|0)==0){a[d]=4411969;a[d+1|0]=17234;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=106;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{m=l*3.141592653589793/180.0;h[d+112>>3]=m;h[d+120>>3]=1.0/m}c[d+1888>>2]=7;c[d+1892>>2]=8;f=0;i=e;return f|0}if((yg(b,12128)|0)==0){Kd(d)|0;f=0;i=e;return f|0}if((yg(b,12136)|0)==0){a[d]=4277594;a[d+1|0]=16709;a[d+2|0]=65;a[d+3|0]=0;c[d+4>>2]=108;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;m=+h[j>>3];if(m==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=114.59155902616465;h[d+120>>3]=.008726646259971648}else{l=m*2.0;h[d+112>>3]=l;h[d+120>>3]=1.0/l}c[d+1888>>2]=9;c[d+1892>>2]=10;f=0;i=e;return f|0}if((yg(b,12144)|0)==0){a[d]=5392705;a[d+1|0]=21065;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=109;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;o=57.29577951308232}else{o=l}l=o*2.0;j=d+112|0;h[j>>3]=l;o=+h[d+40>>3];do{if(!(o==90.0)){if(o>-90.0){m=+Re((90.0-o)*.5);n=m*m;p=+_(+m)*n/(1.0-n);h[d+120>>3]=p;n=.5-p;h[d+128>>3]=n;q=n;r=+h[j>>3];break}else{f=0;i=e;return f|0}}else{h[d+120>>3]=-.5;h[d+128>>3]=1.0;q=1.0;r=l}}while(0);h[d+136>>3]=q*r;h[d+144>>3]=1.0e-4;h[d+152>>3]=q*1.0e-4;h[d+160>>3]=57.29577951308232/q;c[d+1888>>2]=11;c[d+1892>>2]=12;f=0;i=e;return f|0}if((yg(b,12152)|0)==0){a[d]=5265731;a[d+1|0]=20569;a[d+2|0]=80;a[d+3|0]=0;c[d+4>>2]=201;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];do{if(q==0.0){h[g>>3]=57.29577951308232;r=+h[d+48>>3];h[d+112>>3]=r;if(r==0.0){f=0;i=e;return f|0}h[d+120>>3]=1.0/r;l=(r+ +h[d+40>>3])*57.29577951308232;h[d+128>>3]=l;if(l==0.0){f=0;i=e;return f|0}else{h[d+136>>3]=1.0/l;break}}else{l=+h[d+48>>3];r=q*l*3.141592653589793/180.0;h[d+112>>3]=r;if(r==0.0){f=0;i=e;return f|0}h[d+120>>3]=1.0/r;r=q*(l+ +h[d+40>>3]);h[d+128>>3]=r;if(r==0.0){f=0;i=e;return f|0}else{h[d+136>>3]=1.0/r;break}}}while(0);c[d+1888>>2]=13;c[d+1892>>2]=14;f=0;i=e;return f|0}if((yg(b,12160)|0)==0){a[d]=4277571;a[d+1|0]=16709;a[d+2|0]=65;a[d+3|0]=0;c[d+4>>2]=202;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;q=+h[j>>3];do{if(q==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;r=+h[d+40>>3];if(r<=0.0|r>1.0){f=0;i=e;return f|0}else{h[d+128>>3]=57.29577951308232/r;h[d+136>>3]=r/57.29577951308232;break}}else{h[d+112>>3]=q*3.141592653589793/180.0;h[d+120>>3]=57.29577951308232/q;r=+h[d+40>>3];if(r<=0.0|r>1.0){f=0;i=e;return f|0}else{h[d+128>>3]=q/r;h[d+136>>3]=r/q;break}}}while(0);c[d+1888>>2]=15;c[d+1892>>2]=16;f=0;i=e;return f|0}if((yg(b,12168)|0)==0){a[d]=5390659;a[d+1|0]=21057;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=203;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{r=q*3.141592653589793/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r}c[d+1888>>2]=17;c[d+1892>>2]=18;f=0;i=e;return f|0}if((yg(b,12176)|0)==0){a[d]=5391693;a[d+1|0]=21061;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=204;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;r=+h[j>>3];if(r==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{q=r*3.141592653589793/180.0;h[d+112>>3]=q;h[d+120>>3]=1.0/q}c[d+1888>>2]=19;c[d+1892>>2]=20;f=0;i=e;return f|0}if((yg(b,12184)|0)==0){a[d]=4998739;a[d+1|0]=19526;a[d+2|0]=76;a[d+3|0]=0;c[d+4>>2]=301;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{r=q*3.141592653589793/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r}c[d+1888>>2]=21;c[d+1892>>2]=22;f=0;i=e;return f|0}if((yg(b,12192)|0)==0){a[d]=5390672;a[d+1|0]=21057;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=302;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;r=+h[j>>3];if(r==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;h[d+128>>3]=180.0;h[d+136>>3]=.005555555555555556}else{q=r*3.141592653589793;r=q/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r;h[d+128>>3]=q;h[d+136>>3]=1.0/q}c[d+1888>>2]=23;c[d+1892>>2]=24;f=0;i=e;return f|0}if((yg(b,12200)|0)==0){a[d]=5001037;a[d+1|0]=19535;a[d+2|0]=76;a[d+3|0]=0;c[d+4>>2]=303;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;s=57.29577951308232}else{s=q}q=s*1.4142135623730951;h[d+112>>3]=q;h[d+120>>3]=q/90.0;h[d+128>>3]=1.0/q;h[d+136>>3]=90.0/s;h[d+144>>3]=.6366197723675814;c[d+1888>>2]=25;c[d+1892>>2]=26;f=0;i=e;return f|0}if((yg(b,12208)|0)==0){a[d]=5523777;a[d+1|0]=21577;a[d+2|0]=84;a[d+3|0]=0;c[d+4>>2]=401;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;s=+h[j>>3];if(s==0.0){h[j>>3]=57.29577951308232;t=57.29577951308232}else{t=s}s=t*2.0;q=t*s;h[d+112>>3]=q;t=1.0/(q*2.0);h[d+120>>3]=t;h[d+128>>3]=t*.25;h[d+136>>3]=1.0/s;c[d+1888>>2]=27;c[d+1892>>2]=28;f=0;i=e;return f|0}if((yg(b,12216)|0)==0){Ld(d)|0;f=0;i=e;return f|0}if((yg(b,12224)|0)==0){Md(d)|0;f=0;i=e;return f|0}if((yg(b,12232)|0)==0){Nd(d)|0;f=0;i=e;return f|0}if((yg(b,12240)|0)==0){Od(d)|0;f=0;i=e;return f|0}if((yg(b,12248)|0)==0){Pd(d)|0;f=0;i=e;return f|0}if((yg(b,12256)|0)==0){a[d]=5194576;a[d+1|0]=20291;a[d+2|0]=79;a[d+3|0]=0;c[d+4>>2]=602;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;s=+h[g>>3];if(s==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;h[d+128>>3]=114.59155902616465}else{t=s*3.141592653589793/180.0;h[d+112>>3]=t;h[d+120>>3]=1.0/t;h[d+128>>3]=s*2.0}c[d+1888>>2]=29;c[d+1892>>2]=30;f=0;i=e;return f|0}if((yg(b,12264)|0)==0){a[d]=4412244;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=701;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;s=+h[j>>3];if(s==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{t=s*3.141592653589793*.25;h[d+112>>3]=t;h[d+120>>3]=1.0/t}c[d+1888>>2]=31;c[d+1892>>2]=32;f=0;i=e;return f|0}if((yg(b,12272)|0)==0){a[d]=4412227;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=702;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;t=+h[g>>3];if(t==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{s=t*3.141592653589793*.25;h[d+112>>3]=s;h[d+120>>3]=1.0/s}c[d+1888>>2]=33;c[d+1892>>2]=34;f=0;i=e;return f|0}if((yg(b,12280)|0)!=0){f=1;i=e;return f|0}a[d]=4412241;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=703;b=d+8|0;g=d+24|0;c[b+0>>2]=0;c[b+4>>2]=0;c[b+8>>2]=0;c[b+12>>2]=0;s=+h[g>>3];if(s==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{t=s*3.141592653589793*.25;h[d+112>>3]=t;h[d+120>>3]=1.0/t}c[d+1888>>2]=35;c[d+1892>>2]=36;f=0;i=e;return f|0}function Id(b){b=b|0;var d=0,e=0,f=0.0,g=0.0,j=0,k=0,l=0,m=0.0,n=0.0;d=i;a[b]=5265985;a[b+1|0]=20570;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-202)+101;h[b+8>>3]=0.0;h[b+16>>3]=90.0;e=b+24|0;f=+h[e>>3];if(f==0.0){h[e>>3]=57.29577951308232;g=57.29577951308232}else{g=f}e=b+40|0;f=g*(+h[e>>3]+1.0);h[b+112>>3]=f;if(f==0.0){j=1;i=d;return j|0}k=b+48|0;f=+Re(+h[k>>3]);l=b+136|0;h[l>>3]=f;if(f==0.0){j=1;i=d;return j|0}h[b+128>>3]=1.0/f;f=+Se(+h[k>>3]);h[b+144>>3]=f;g=+h[l>>3];h[b+120>>3]=f/g;f=+h[e>>3];if(+P(+f)>1.0){h[b+152>>3]=+Ve(-1.0/f);m=+h[e>>3];n=+h[l>>3]}else{h[b+152>>3]=-90.0;m=f;n=g}g=m*n;h[b+160>>3]=g;l=+P(+g)<1.0;h[b+168>>3]=l?1.0:0.0;c[b+1888>>2]=37;c[b+1892>>2]=38;j=0;i=d;return j|0}function Jd(b){b=b|0;var d=0,e=0,f=0.0,g=0.0,j=0,k=0,l=0,m=0,n=0,o=0;d=i;a[b]=5266003;a[b+1|0]=20570;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-204)+102;h[b+8>>3]=0.0;h[b+16>>3]=90.0;e=b+24|0;f=+h[e>>3];if(f==0.0){h[e>>3]=57.29577951308232;g=57.29577951308232}else{g=f}h[b+112>>3]=1.0/g;j=b+40|0;g=+h[j>>3];k=b+56|0;f=g*+Se(+h[k>>3])+1.0;l=b+136|0;h[l>>3]=f;if(f==0.0){m=1;i=d;return m|0}f=+h[j>>3];g=f*+Re(+h[k>>3]);n=b+48|0;o=b+120|0;h[o>>3]=-(g*+Se(+h[n>>3]));g=+h[j>>3];f=g*+Re(+h[k>>3]);g=f*+Re(+h[n>>3]);h[b+128>>3]=g;f=+h[e>>3];h[b+144>>3]=f*+h[o>>3];h[b+152>>3]=f*g;g=+h[l>>3];h[b+160>>3]=f*g;f=g+-1.0;h[b+168>>3]=g*f+-1.0;if(+P(+f)<1.0){h[b+176>>3]=+Ve(1.0-g)}else{h[b+176>>3]=-90.0}c[b+1888>>2]=39;c[b+1892>>2]=40;m=0;i=d;return m|0}function Kd(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0.0,l=0.0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0.0,C=0.0,D=0.0;d=i;a[b]=5132378;a[b+1|0]=20048;a[b+2|0]=78;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-214)+107;f=b+8|0;h[f>>3]=0.0;g=b+16|0;h[g>>3]=90.0;j=b+24|0;k=+h[j>>3];if(k==0.0){h[j>>3]=57.29577951308232;l=57.29577951308232}else{l=k}m=9;while(1){if(!(+h[b+(m<<3)+32>>3]==0.0)){break}if((m|0)>0){m=m+ -1|0}else{n=6;break}}if((n|0)==6){a[b]=4411969;a[b+1|0]=17234;a[b+2|0]=67;a[b+3|0]=0;c[e>>2]=106;h[f>>3]=0.0;h[g>>3]=90.0;if(l==0.0){h[j>>3]=57.29577951308232;h[b+112>>3]=1.0;h[b+120>>3]=1.0}else{k=l*3.141592653589793/180.0;h[b+112>>3]=k;h[b+120>>3]=1.0/k}c[b+1888>>2]=7;c[b+1892>>2]=8;o=0;i=d;return o|0}c[b+272>>2]=m;c[b+1888>>2]=41;c[b+1892>>2]=42;if((m|0)<=2){o=0;i=d;return o|0}k=+h[b+40>>3];if(k<=0.0){o=1;i=d;return o|0}j=(m|0)>0;a:do{if(j){l=k;g=0;p=0.0;while(1){q=+(g|0)*3.141592653589793/180.0;r=0.0;f=m;do{r=q*r+ +(f|0)*+h[b+(f<<3)+32>>3];f=f+ -1|0}while((f|0)>0);f=g+1|0;if(r<=0.0){s=l;t=r;u=g;v=p;w=q;break a}if((f|0)<180){l=r;g=f;p=q}else{s=r;t=r;u=f;v=q;w=q;break}}}else{s=k;t=0.0;u=0;v=0.0;w=0.0}}while(0);b:do{if((u|0)==180){x=3.141592653589793}else{if(j){y=s;z=t;A=1;B=v;C=w}else{x=v-s*(w-v)/(t-s);break}while(1){k=B-y*(C-B)/(z-y);p=0.0;g=m;do{p=k*p+ +(g|0)*+h[b+(g<<3)+32>>3];g=g+ -1|0}while((g|0)>0);if(+P(+p)<1.0e-13){x=k;break b}g=p<0.0;f=A+1|0;if((f|0)<11){y=g?y:p;z=g?p:z;A=f;B=g?B:k;C=g?k:C}else{x=k;break}}}}while(0);if((m|0)>-1){A=m;C=0.0;while(1){B=x*C+ +h[b+(A<<3)+32>>3];if((A|0)>0){A=A+ -1|0;C=B}else{D=B;break}}}else{D=0.0}h[b+112>>3]=x;h[b+120>>3]=D;o=0;i=d;return o|0}function Ld(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0;d=i;a[b]=5263171;a[b+1|0]=20559;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-1002)+501;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+Se(f);h[b+112>>3]=j;if(j==0.0){k=1;i=d;return k|0}h[b+120>>3]=1.0/j;j=+h[g>>3];f=j*+Re(+h[b+48>>3]);g=b+136|0;h[g>>3]=f;if(f==0.0){k=1;i=d;return k|0}h[b+144>>3]=1.0/f;f=1.0/+Te(+h[e>>3]);h[b+152>>3]=f;h[b+128>>3]=f*+h[g>>3];c[b+1888>>2]=43;c[b+1892>>2]=44;k=0;i=d;return k|0}function Md(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0;d=i;a[b]=4542275;a[b+1|0]=17743;a[b+2|0]=69;a[b+3|0]=0;c[b+4>>2]=502;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+h[b+48>>3];k=f-j;l=f+j;j=+Se(k);f=(j+ +Se(l))*.5;m=b+112|0;h[m>>3]=f;if(f==0.0){n=1;i=d;return n|0}h[b+120>>3]=1.0/f;o=b+136|0;h[o>>3]=+h[g>>3]/f;f=+Se(k);k=f*+Se(l)+1.0;h[b+144>>3]=k;l=+h[m>>3]*2.0;h[b+152>>3]=l;f=+h[o>>3];h[b+160>>3]=f*f*k;h[b+168>>3]=1.0/(+h[g>>3]*2.0*f);h[b+176>>3]=f*+Q(+(k+l));h[b+128>>3]=f*+Q(+(k-l*+Se(+h[e>>3])));c[b+1888>>2]=45;c[b+1892>>2]=46;n=0;i=d;return n|0}function Nd(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0,m=0,n=0.0,o=0;d=i;a[b]=4476739;a[b+1|0]=17487;a[b+2|0]=68;a[b+3|0]=0;c[b+4>>2]=503;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;j=+h[g>>3];if(j==0.0){h[g>>3]=57.29577951308232;k=57.29577951308232}else{k=j}l=b+48|0;m=+h[l>>3]==0.0;j=k*+Se(f);if(m){f=j*3.141592653589793/180.0;h[b+112>>3]=f;n=f}else{f=j*+Se(+h[l>>3]);j=f/+h[l>>3];h[b+112>>3]=j;n=j}if(n==0.0){o=1;i=d;return o|0}h[b+120>>3]=1.0/n;n=+h[g>>3];j=n*+Re(+h[l>>3]);n=j*+Re(+h[e>>3]);j=n/+h[b+112>>3];h[b+128>>3]=j;h[b+136>>3]=j+ +h[e>>3];c[b+1888>>2]=47;c[b+1892>>2]=48;o=0;i=d;return o|0}function Od(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0;d=i;a[b]=5197635;a[b+1|0]=20303;a[b+2|0]=79;a[b+3|0]=0;c[b+4>>2]=504;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+h[b+48>>3];k=f-j;l=f+j;j=+Te((90.0-k)*.5);f=+Re(k);if(k==l){m=+Se(k);h[b+112>>3]=m;n=m}else{m=+Te((90.0-l)*.5);k=+_(+(+Re(l)/f))/+_(+(m/j));h[b+112>>3]=k;n=k}if(n==0.0){o=1;i=d;return o|0}h[b+120>>3]=1.0/n;k=+h[g>>3]*(f/n)/+R(+j,+n);g=b+136|0;h[g>>3]=k;if(k==0.0){o=1;i=d;return o|0}n=+Te((90.0- +h[e>>3])*.5);h[b+128>>3]=k*+R(+n,+(+h[b+112>>3]));h[b+144>>3]=1.0/+h[g>>3];c[b+1888>>2]=49;c[b+1892>>2]=50;o=0;i=d;return o|0}function Pd(b){b=b|0;var d=0,e=0,f=0,g=0.0,j=0.0,k=0.0,l=0,m=0;d=i;a[b]=5132098;a[b+1|0]=20047;a[b+2|0]=78;a[b+3|0]=0;c[b+4>>2]=601;e=b+8|0;f=b+24|0;c[e+0>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;g=+h[f>>3];if(g==0.0){h[f>>3]=57.29577951308232;h[b+120>>3]=1.0;f=b+40|0;j=+Re(+h[f>>3])*57.29577951308232;k=j/+Se(+h[f>>3]);h[b+128>>3]=k+ +h[f>>3];l=b+1888|0;c[l>>2]=51;m=b+1892|0;c[m>>2]=52;i=d;return 0}else{h[b+120>>3]=g*3.141592653589793/180.0;f=b+40|0;k=+Re(+h[f>>3]);j=k/+Se(+h[f>>3]);h[b+128>>3]=g*(j+ +h[f>>3]*3.141592653589793/180.0);l=b+1888|0;c[l>>2]=51;m=b+1892|0;c[m>>2]=52;i=d;return 0}return 0}function Qd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=101?(Id(d)|0)!=0:0){l=1;i=g;return l|0}m=+Re(a);n=+Re(b);o=m*+h[d+120>>3];k=d+40|0;p=+h[k>>3];q=n*o+(p+ +Se(b));if(q==0.0){l=2;i=g;return l|0}p=n*+h[d+112>>3]/q;h[e>>3]=p*+Se(a);h[f>>3]=-(m*p*+h[d+128>>3]);if((c[j>>2]|0)>0){if(+h[d+152>>3]>b){l=2;i=g;return l|0}if(+h[d+168>>3]>0.0?(p=+h[k>>3]/+Q(+(o*o+1.0)),+P(+p)<=1.0):0){m=+We(-o);o=+Ve(p);p=m-o;a=m+o+180.0;if(p>90.0){r=p+-360.0}else{r=p}if(a>90.0){s=a+-360.0}else{s=a}if((r>s?r:s)>b){l=2;i=g;return l|0}}}l=0;i=g;return l|0}function Rd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=101?(Id(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+136>>3]*b;m=+Q(+(a*a+l*l));if(m==0.0){h[e>>3]=0.0;n=90.0}else{h[e>>3]=+Xe(a,-l);l=m/(+h[d+112>>3]+ +h[d+144>>3]*b);b=l*+h[d+40>>3]/+Q(+(l*l+1.0));m=+Xe(1.0,l);if(+P(+b)>1.0){l=b<0.0?-90.0:90.0;if(+P(+l)>1.0000000000001){k=2;i=g;return k|0}else{o=l}}else{o=+Ve(b)}b=m-o;l=m+o+180.0;if(b>90.0){p=b+-360.0}else{p=b}if(l>90.0){q=l+-360.0}else{q=l}n=p>q?p:q}h[f>>3]=n;k=0;i=g;return k|0}function Sd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=102?(Jd(d)|0)!=0:0){l=1;i=g;return l|0}m=+Re(a);n=+Se(a);a=+Re(b);o=1.0- +Se(b);k=d+136|0;p=+h[k>>3]-o;if(p==0.0){l=2;i=g;return l|0}q=d+160|0;h[e>>3]=(n*a*+h[q>>3]-o*+h[d+144>>3])/p;h[f>>3]=-(m*a*+h[q>>3]+o*+h[d+152>>3])/p;if((c[j>>2]|0)>0){if(+h[d+176>>3]>b){l=2;i=g;return l|0}if(+P(+(+h[d+40>>3]))>1.0?(p=n*+h[d+120>>3]-m*+h[d+128>>3],m=1.0/+Q(+(+h[d+168>>3]+p*p)),+P(+m)<=1.0):0){n=+Xe(p,+h[k>>3]+-1.0);p=+Ve(m);m=n-p;o=n+p+180.0;if(m>90.0){r=m+-360.0}else{r=m}if(o>90.0){s=o+-360.0}else{s=o}if((r>s?r:s)>b){l=2;i=g;return l|0}}}l=0;i=g;return l|0}function Td(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=102?(Jd(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+112>>3];m=l*a;a=l*b;b=m*m+a*a;l=+h[d+136>>3];n=(m- +h[d+120>>3])/l;o=(a- +h[d+128>>3])/l;l=m*n+a*o;do{if(!(b<1.0e-10)){p=n*n+o*o;q=p+1.0;r=l-p;s=r*r-q*(p+(b-l-l)+-1.0);if(s<0.0){k=2;i=g;return k|0}p=+Q(+s);s=(p-r)/q;t=(-r-p)/q;q=s>t?s:t;if(q>1.0){if(q+-1.0<1.0e-13){u=1.0}else{u=s-1.0e-13?-1.0:u;if(q>1.0|q<-1.0){k=2;i=g;return k|0}else{h[f>>3]=+Ve(q);v=1.0-q;break}}else{h[f>>3]=90.0- +Q(+(b/(l+1.0)))*57.29577951308232;v=b*.5}}while(0);h[e>>3]=+Xe(m-n*v,-(a-o*v));k=0;i=g;return k|0}function Ud(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+16|0;k=j;l=e+4|0;m=c[l>>2]|0;if((((m|0)>-1?m:0-m|0)|0)!=103){a[e]=5128532;a[e+1|0]=20033;a[e+2|0]=78;a[e+3|0]=0;c[l>>2]=(m>>31&-206)+103;h[e+8>>3]=0.0;h[e+16>>3]=90.0;m=e+24|0;if(+h[m>>3]==0.0){h[m>>3]=57.29577951308232}c[e+1888>>2]=1;c[e+1892>>2]=2;m=99;while(1){if(!(+h[e+(m<<3)+280>>3]==0.0)){n=m;break}o=m+ -1|0;if(!(+h[e+(m+100<<3)+280>>3]==0.0)){n=m;break}if((m|0)>0){m=o}else{n=o;break}}c[e+276>>2]=(n|0)<0?0:n}p=+Se(d);if(p<=0.0){i=j;return 2}q=+h[e+24>>3];r=q*+Re(d)/p;h[k>>3]=r*+Se(b);n=k+8|0;h[n>>3]=-(r*+Re(b));m=c[e+1880>>2]|0;if((m|0)==0){s=+h[k>>3]}else{s=+sd(m,k)}h[f>>3]=s;f=c[e+1884>>2]|0;if((f|0)==0){t=+h[n>>3];h[g>>3]=t;u=c[l>>2]|0;v=(u|0)>0;w=p<0.0;x=v&w;y=x?2:0;i=j;return y|0}else{t=+sd(f,k);h[g>>3]=t;u=c[l>>2]|0;v=(u|0)>0;w=p<0.0;x=v&w;y=x?2:0;i=j;return y|0}return 0}function Vd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0;j=i;i=i+16|0;k=j+8|0;l=j;m=e+4|0;n=c[m>>2]|0;if((((n|0)>-1?n:0-n|0)|0)==103){o=c[e+276>>2]|0}else{a[e]=5128532;a[e+1|0]=20033;a[e+2|0]=78;a[e+3|0]=0;c[m>>2]=(n>>31&-206)+103;h[e+8>>3]=0.0;h[e+16>>3]=90.0;n=e+24|0;if(+h[n>>3]==0.0){h[n>>3]=57.29577951308232}c[e+1888>>2]=1;c[e+1892>>2]=2;n=99;while(1){if(!(+h[e+(n<<3)+280>>3]==0.0)){p=n;break}m=n+ -1|0;if(!(+h[e+(n+100<<3)+280>>3]==0.0)){p=n;break}if((n|0)>0){n=m}else{p=m;break}}n=(p|0)<0?0:p;c[e+276>>2]=n;o=n}if((o|0)==0){h[k>>3]=b;h[l>>3]=d;q=b;r=d}else{Wd(e,b,d,k,l)|0;q=+h[k>>3];r=+h[l>>3]}d=+Q(+(q*q+r*r));if(d==0.0){s=0.0;h[f>>3]=s;t=e+24|0;u=+h[t>>3];v=+Xe(u,d);h[g>>3]=v;i=j;return 0}s=+Xe(q,-r);h[f>>3]=s;t=e+24|0;u=+h[t>>3];v=+Xe(u,d);h[g>>3]=v;i=j;return 0}function Wd(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,P=0.0,R=0.0,S=0.0,T=0.0,U=0.0,V=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0,va=0.0,wa=0.0,xa=0.0,ya=0.0,za=0.0,Aa=0.0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0.0,Fa=0.0,Ga=0.0,Ha=0.0,Ia=0.0,Ja=0.0,Ka=0.0,La=0.0,Ma=0.0,Na=0.0,Oa=0.0,Pa=0.0;g=i;j=c[a+276>>2]|0;k=+h[a+1080>>3]+ +h[a+1088>>3]*b;l=+h[a+280>>3]+ +h[a+288>>3]*d;if((j|0)!=1){m=k+ +h[a+1096>>3]*d;n=l+ +h[a+296>>3]*b;if((j|0)!=2){o=b*b;p=d*d;q=+Q(+(o+p));r=m+q*+h[a+1104>>3];s=n+q*+h[a+304>>3];if((j|0)!=3){t=r+o*+h[a+1112>>3];u=s+p*+h[a+312>>3];if((j|0)!=4){v=b*d;w=t+v*+h[a+1120>>3];x=u+v*+h[a+320>>3];if((j|0)!=5){v=w+p*+h[a+1128>>3];y=x+o*+h[a+328>>3];if((j|0)!=6){z=o*b;A=v+z*+h[a+1136>>3];B=p*d;C=y+B*+h[a+336>>3];if((j|0)!=7){D=A+o*+h[a+1144>>3]*d;E=C+p*+h[a+344>>3]*b;if((j|0)!=8){F=D+p*+h[a+1152>>3]*b;G=E+o*+h[a+352>>3]*d;if((j|0)!=9){H=F+B*+h[a+1160>>3];I=G+z*+h[a+360>>3];if((j|0)!=10){J=q*q*q;K=H+J*+h[a+1168>>3];L=I+J*+h[a+368>>3];if((j|0)!=11){M=o*o;N=K+M*+h[a+1176>>3];O=p*p;P=L+O*+h[a+376>>3];if((j|0)!=12){R=N+z*+h[a+1184>>3]*d;S=P+B*+h[a+384>>3]*b;if((j|0)!=13){T=R+p*o*+h[a+1192>>3];U=S+p*o*+h[a+392>>3];if((j|0)!=14){V=T+B*+h[a+1200>>3]*b;W=U+z*+h[a+400>>3]*d;if((j|0)!=15){X=V+O*+h[a+1208>>3];Y=W+M*+h[a+408>>3];if((j|0)!=16){Z=M*b;_=X+Z*+h[a+1216>>3];$=O*d;aa=Y+$*+h[a+416>>3];if((j|0)!=17){ba=_+M*+h[a+1224>>3]*d;ca=aa+O*+h[a+424>>3]*b;if((j|0)!=18){da=ba+p*z*+h[a+1232>>3];ea=ca+o*B*+h[a+432>>3];if((j|0)!=19){fa=da+B*o*+h[a+1240>>3];ga=ea+z*p*+h[a+440>>3];if((j|0)!=20){ha=fa+O*+h[a+1248>>3]*b;ia=ga+M*+h[a+448>>3]*d;if((j|0)!=21){ja=ha+$*+h[a+1256>>3];ka=ia+Z*+h[a+456>>3];if((j|0)!=22){la=q*q*J;J=ja+la*+h[a+1264>>3];ma=ka+la*+h[a+464>>3];if((j|0)!=23){na=Z*b;oa=J+na*+h[a+1272>>3];pa=$*d;qa=ma+pa*+h[a+472>>3];if((j|0)!=24){ra=oa+Z*+h[a+1280>>3]*d;sa=qa+$*+h[a+480>>3]*b;if((j|0)!=25){ta=ra+p*M*+h[a+1288>>3];ua=sa+o*O*+h[a+488>>3];if((j|0)!=26){va=ta+B*z*+h[a+1296>>3];wa=ua+z*B*+h[a+496>>3];if((j|0)!=27){xa=va+O*o*+h[a+1304>>3];ya=wa+M*p*+h[a+504>>3];if((j|0)!=28){za=xa+$*+h[a+1312>>3]*b;Aa=ya+Z*+h[a+512>>3]*d;if((j|0)!=29){Ba=za+pa*+h[a+1320>>3];Ca=Aa+na*+h[a+520>>3];if((j|0)!=30){Da=na*b;Ea=Ba+Da*+h[a+1328>>3];Fa=pa*d;Ga=Ca+Fa*+h[a+528>>3];if((j|0)!=31){Ha=Ea+na*+h[a+1336>>3]*d;Ia=Ga+pa*+h[a+536>>3]*b;if((j|0)!=32){Ja=Ha+p*Z*+h[a+1344>>3];Ka=Ia+o*$*+h[a+544>>3];if((j|0)!=33){La=Ja+B*M*+h[a+1352>>3];Ma=Ka+z*O*+h[a+552>>3];if((j|0)!=34){Na=La+O*z*+h[a+1360>>3];z=Ma+M*B*+h[a+560>>3];if((j|0)!=35){B=Na+$*o*+h[a+1368>>3];o=z+Z*p*+h[a+568>>3];if((j|0)!=36){p=B+pa*+h[a+1376>>3]*b;b=o+na*+h[a+576>>3]*d;if((j|0)!=37){d=p+Fa*+h[a+1384>>3];Fa=b+Da*+h[a+584>>3];if((j|0)==38){Oa=d;Pa=Fa}else{Da=q*q*la;Oa=d+Da*+h[a+1392>>3];Pa=Fa+Da*+h[a+592>>3]}}else{Oa=p;Pa=b}}else{Oa=B;Pa=o}}else{Oa=Na;Pa=z}}else{Oa=La;Pa=Ma}}else{Oa=Ja;Pa=Ka}}else{Oa=Ha;Pa=Ia}}else{Oa=Ea;Pa=Ga}}else{Oa=Ba;Pa=Ca}}else{Oa=za;Pa=Aa}}else{Oa=xa;Pa=ya}}else{Oa=va;Pa=wa}}else{Oa=ta;Pa=ua}}else{Oa=ra;Pa=sa}}else{Oa=oa;Pa=qa}}else{Oa=J;Pa=ma}}else{Oa=ja;Pa=ka}}else{Oa=ha;Pa=ia}}else{Oa=fa;Pa=ga}}else{Oa=da;Pa=ea}}else{Oa=ba;Pa=ca}}else{Oa=_;Pa=aa}}else{Oa=X;Pa=Y}}else{Oa=V;Pa=W}}else{Oa=T;Pa=U}}else{Oa=R;Pa=S}}else{Oa=N;Pa=P}}else{Oa=K;Pa=L}}else{Oa=H;Pa=I}}else{Oa=F;Pa=G}}else{Oa=D;Pa=E}}else{Oa=A;Pa=C}}else{Oa=v;Pa=y}}else{Oa=w;Pa=x}}else{Oa=t;Pa=u}}else{Oa=r;Pa=s}}else{Oa=m;Pa=n}}else{Oa=k;Pa=l}h[e>>3]=Oa;h[f>>3]=Pa;i=g;return 0}function Xd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0,o=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=104){a[e]=4674643;a[e+1|0]=18260;a[e+2|0]=71;a[e+3|0]=0;c[k>>2]=104;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=3;c[e+1892>>2]=4}m=+Se(d)+1.0;if(m==0.0){n=2;i=j;return n|0}l=+h[e+112>>3];o=l*+Re(d)/m;h[f>>3]=o*+Se(b);h[g>>3]=-(o*+Re(b));n=0;i=j;return n|0}function Yd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=104){a[e]=4674643;a[e+1|0]=18260;a[e+2|0]=71;a[e+3|0]=0;c[k>>2]=104;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=3;c[e+1892>>2]=4}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0;h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=+We(q);s=r*2.0;t=90.0-s;h[g>>3]=t;i=j;return 0}n=+Xe(b,-d);h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=+We(q);s=r*2.0;t=90.0-s;h[g>>3]=t;i=j;return 0}function Zd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0;j=i;k=e+4|0;l=c[k>>2]|0;if((((l|0)>-1?l:0-l|0)|0)!=105){a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;c[k>>2]=(l>>31&-210)+105;h[e+8>>3]=0.0;h[e+16>>3]=90.0;l=e+24|0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;n=57.29577951308232}else{n=m}h[e+112>>3]=1.0/n;n=+h[e+40>>3];m=+h[e+48>>3];o=n*n+m*m;h[e+120>>3]=o;h[e+128>>3]=o+1.0;h[e+136>>3]=o+-1.0;c[e+1888>>2]=5;c[e+1892>>2]=6}o=(90.0- +P(+d))*3.141592653589793/180.0;if(o<1.0e-5){m=o*o*.5;if(d>0.0){p=o;q=m}else{p=o;q=2.0-m}}else{m=1.0- +Se(d);p=+Re(d);q=m}m=+Re(b);o=+Se(b);l=e+24|0;r=e+40|0;h[f>>3]=+h[l>>3]*(p*o+q*+h[r>>3]);f=e+48|0;h[g>>3]=-(+h[l>>3]*(p*m-q*+h[f>>3]));do{if((c[k>>2]|0)>0){if(+h[e+120>>3]==0.0){if(d<0.0){s=2}else{break}i=j;return s|0}else{if(d<-+We(o*+h[r>>3]-m*+h[f>>3])){s=2}else{break}i=j;return s|0}}}while(0);s=0;i=j;return s|0}function _d(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0;j=i;k=e+4|0;l=c[k>>2]|0;if((((l|0)>-1?l:0-l|0)|0)==105){m=+h[e+112>>3];n=+h[e+120>>3]}else{a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;c[k>>2]=(l>>31&-210)+105;h[e+8>>3]=0.0;h[e+16>>3]=90.0;l=e+24|0;o=+h[l>>3];if(o==0.0){h[l>>3]=57.29577951308232;p=57.29577951308232}else{p=o}o=1.0/p;h[e+112>>3]=o;p=+h[e+40>>3];q=+h[e+48>>3];r=p*p+q*q;h[e+120>>3]=r;h[e+128>>3]=r+1.0;h[e+136>>3]=r+-1.0;c[e+1888>>2]=5;c[e+1892>>2]=6;m=o;n=r}r=m*b;b=m*d;d=r*r+b*b;if(n==0.0){if(d!=0.0){s=+Xe(r,-b)}else{s=0.0}h[f>>3]=s;if(d<.5){h[g>>3]=+Ue(+Q(+d));t=0;i=j;return t|0}if(!(d<=1.0)){t=2;i=j;return t|0}h[g>>3]=+Ve(+Q(+(1.0-d)));t=0;i=j;return t|0}l=e+40|0;k=e+48|0;s=r*+h[l>>3]+b*+h[k>>3];do{if(!(d<1.0e-10)){m=+h[e+128>>3];o=s-n;q=o*o-m*(d-s-s+ +h[e+136>>3]);if(q<0.0){t=2;i=j;return t|0}p=+Q(+q);q=(p-o)/m;u=(-o-p)/m;m=q>u?q:u;if(m>1.0){if(m+-1.0<1.0e-13){v=1.0}else{v=q-1.0e-13?-1.0:v;if(m>1.0|m<-1.0){t=2;i=j;return t|0}else{h[g>>3]=+Ve(m);w=1.0-m;break}}else{h[g>>3]=90.0- +Q(+(d/(s+1.0)))*57.29577951308232;w=d*.5}}while(0);d=w*+h[k>>3]-b;b=r-w*+h[l>>3];if(d==0.0&b==0.0){h[f>>3]=0.0;t=0;i=j;return t|0}else{h[f>>3]=+Xe(b,d);t=0;i=j;return t|0}return 0}function $d(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==106){l=+h[e+112>>3];m=90.0-d;n=m*l;o=+Se(b);p=n*o;h[f>>3]=p;q=+Re(b);r=n*q;s=-r;h[g>>3]=s;i=j;return 0}a[e]=4411969;a[e+1|0]=17234;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=106;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;t=+h[k>>3];if(t==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;u=1.0}else{v=t*3.141592653589793/180.0;h[e+112>>3]=v;h[e+120>>3]=1.0/v;u=v}c[e+1888>>2]=7;c[e+1892>>2]=8;l=u;m=90.0-d;n=m*l;o=+Se(b);p=n*o;h[f>>3]=p;q=+Re(b);r=n*q;s=-r;h[g>>3]=s;i=j;return 0}function ae(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0,p=0.0,q=0.0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=106){a[e]=4411969;a[e+1|0]=17234;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=106;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0}else{m=l*3.141592653589793/180.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=7;c[e+1892>>2]=8}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0;h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=90.0-q;h[g>>3]=r;i=j;return 0}n=+Xe(b,-d);h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=90.0-q;h[g>>3]=r;i=j;return 0}function be(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=107?(Kd(d)|0)!=0:0){l=1;i=g;return l|0}m=(90.0-b)*3.141592653589793/180.0;b=(m*(m*(m*(m*(m*(m*(m*(m*(m*(m*0.0+ +h[d+104>>3])+ +h[d+96>>3])+ +h[d+88>>3])+ +h[d+80>>3])+ +h[d+72>>3])+ +h[d+64>>3])+ +h[d+56>>3])+ +h[d+48>>3])+ +h[d+40>>3])+ +h[d+32>>3])*+h[d+24>>3];h[e>>3]=b*+Se(a);h[f>>3]=-(b*+Re(a));if((c[j>>2]|0)>0?m>+h[d+112>>3]:0){l=2;i=g;return l|0}l=0;i=g;return l|0}function ce(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=107?(Kd(d)|0)!=0:0){k=1;i=g;return k|0}j=c[d+272>>2]|0;l=+Q(+(a*a+b*b));m=l/+h[d+24>>3];if((j|0)<1){k=1;i=g;return k|0}a:do{if((j|0)==2){l=+h[d+48>>3];n=+h[d+40>>3];o=n*n-l*4.0*(+h[d+32>>3]-m);if(o<0.0){k=2;i=g;return k|0}p=+Q(+o);o=l*2.0;l=(p-n)/o;q=(-n-p)/o;o=lq?l:q}else{r=o}if(r<0.0){if(r<-1.0e-13){k=2}else{s=0.0;break}i=g;return k|0}if(r>3.141592653589793){if(r>3.141592653589893){k=2;i=g;return k|0}else{s=3.141592653589793}}else{s=r}}else if((j|0)==1){s=(m- +h[d+32>>3])/+h[d+40>>3]}else{o=+h[d+32>>3];q=+h[d+112>>3];l=+h[d+120>>3];if(ml){if(m>l+1.0e-13){k=2}else{s=q;break}i=g;return k|0}if((j|0)>-1){t=0;u=o;v=l;w=0.0;x=q}else{p=0.0-m;y=0;n=o;o=l;l=0.0;z=q;while(1){q=(o-m)/(o-n);if(!(q<.1)){if(q>.9){A=.9}else{A=q}}else{A=.1}q=z-(z-l)*A;if(m>0.0){if(m<1.0e-13){s=q;break a}else{B=0.0;C=o;D=q;E=z}}else{if(p<1.0e-13){s=q;break a}else{B=n;C=0.0;D=l;E=q}}F=y+1|0;if(!(+P(+(E-D))<1.0e-13)&(F|0)<100){y=F;n=B;o=C;l=D;z=E}else{s=q;break a}}}while(1){z=(v-m)/(v-u);if(!(z<.1)){if(z>.9){G=.9}else{G=z}}else{G=.1}z=x-(x-w)*G;y=j;l=0.0;while(1){l=z*l+ +h[d+(y<<3)+32>>3];if((y|0)<=0){break}else{y=y+ -1|0}}if(l>3]=L;h[f>>3]=90.0-s*180.0/3.141592653589793;k=0;i=g;return k|0}function de(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==108){l=+h[e+112>>3]}else{a[e]=4277594;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=108;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;m=+h[k>>3];if(m==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648;n=114.59155902616465}else{o=m*2.0;h[e+112>>3]=o;h[e+120>>3]=1.0/o;n=o}c[e+1888>>2]=9;c[e+1892>>2]=10;l=n}n=l*+Se((90.0-d)*.5);h[f>>3]=n*+Se(b);h[g>>3]=-(n*+Re(b));i=j;return 0}function ee(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0;j=i;k=e+4|0;if((c[k>>2]|0)!=108){a[e]=4277594;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=108;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=9;c[e+1892>>2]=10}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0}else{n=+Xe(b,-d)}h[f>>3]=n;n=m*+h[e+120>>3];if(+P(+n)>1.0){if(+P(+(m- +h[e+112>>3]))<1.0e-12){o=-90.0}else{p=2;i=j;return p|0}}else{o=90.0- +Ve(n)*2.0}h[g>>3]=o;p=0;i=j;return p|0}function fe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=109){a[e]=5392705;a[e+1|0]=21065;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=109;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;m=57.29577951308232}else{m=l}l=m*2.0;k=e+112|0;h[k>>3]=l;m=+h[e+40>>3];do{if(!(m==90.0)){if(m>-90.0){n=+Re((90.0-m)*.5);o=n*n;p=+_(+n)*o/(1.0-o);h[e+120>>3]=p;o=.5-p;h[e+128>>3]=o;q=o;r=+h[k>>3];break}else{s=1;i=j;return s|0}}else{h[e+120>>3]=-.5;h[e+128>>3]=1.0;q=1.0;r=l}}while(0);h[e+136>>3]=q*r;h[e+144>>3]=1.0e-4;h[e+152>>3]=q*1.0e-4;h[e+160>>3]=57.29577951308232/q;c[e+1888>>2]=11;c[e+1892>>2]=12}do{if(!(d==90.0)){if(!(d>-90.0)){s=2;i=j;return s|0}q=90.0-d;r=q*.017453292519943295*.5;if(r<+h[e+144>>3]){t=r*+h[e+136>>3];break}else{r=+Re(q*.5);q=+Q(+(1.0-r*r))/r;l=+_(+r)/q;t=-(+h[e+112>>3]*(l+q*+h[e+120>>3]));break}}else{t=0.0}}while(0);h[f>>3]=t*+Se(b);h[g>>3]=-(t*+Re(b));s=0;i=j;return s|0}function ge(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0,A=0.0,B=0.0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==109){l=+h[e+112>>3]}else{a[e]=5392705;a[e+1|0]=21065;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=109;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;m=+h[k>>3];if(m==0.0){h[k>>3]=57.29577951308232;n=57.29577951308232}else{n=m}m=n*2.0;k=e+112|0;h[k>>3]=m;n=+h[e+40>>3];do{if(!(n==90.0)){if(n>-90.0){o=+Re((90.0-n)*.5);p=o*o;q=+_(+o)*p/(1.0-p);h[e+120>>3]=q;p=.5-q;h[e+128>>3]=p;r=p;s=+h[k>>3];break}else{t=1;i=j;return t|0}}else{h[e+120>>3]=-.5;h[e+128>>3]=1.0;r=1.0;s=m}}while(0);h[e+136>>3]=r*s;h[e+144>>3]=1.0e-4;h[e+152>>3]=r*1.0e-4;h[e+160>>3]=57.29577951308232/r;c[e+1888>>2]=11;c[e+1892>>2]=12;l=s}s=+Q(+(b*b+d*d))/l;if(s==0.0){u=0.0;v=0.0}else{do{if(!(s<+h[e+152>>3])){l=+h[e+120>>3];k=0;r=0.0;m=1.0;while(1){w=m*.5;n=+Q(+(1.0-w*w))/w;x=-(+_(+w)/n+n*l);y=k+1|0;if(s<=x){z=k;A=r;B=m;break}if((y|0)<30){k=y;r=x;m=w}else{z=y;A=x;B=w;break}}if((z|0)==30){t=2;i=j;return t|0}else{C=0;D=A;E=x;F=B;G=w}while(1){m=(E-s)/(E-D);if(!(m<.1)){if(m>.9){H=.9}else{H=m}}else{H=.1}I=G-(G-F)*H;m=+Q(+(1.0-I*I))/I;r=+_(+I)/m+m*l;m=-r;if(s>m){if(s+r<1.0e-12){J=C;break}else{K=m;L=E;M=I;N=G}}else{if(m-s<1.0e-12){J=C;break}else{K=D;L=m;M=F;N=I}}k=C+1|0;if((k|0)<100){C=k;D=K;E=L;F=M;G=N}else{J=k;break}}if((J|0)==100){t=2;i=j;return t|0}else{O=+Ue(I);break}}else{O=s*+h[e+160>>3]}}while(0);u=+Xe(b,-d);v=O}h[f>>3]=u;h[g>>3]=90.0-v*2.0;t=0;i=j;return t|0}function he(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==201){l=+h[e+40>>3]}else{a[e]=5265731;a[e+1|0]=20569;a[e+2|0]=80;a[e+3|0]=0;c[k>>2]=201;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;o=+h[e+48>>3];h[e+112>>3]=o;if(o==0.0){p=1;i=j;return p|0}h[e+120>>3]=1.0/o;q=+h[e+40>>3];r=(o+q)*57.29577951308232;h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=q;break}}else{q=+h[e+48>>3];r=n*q*3.141592653589793/180.0;h[e+112>>3]=r;if(r==0.0){p=1;i=j;return p|0}h[e+120>>3]=1.0/r;r=+h[e+40>>3];o=n*(q+r);h[e+128>>3]=o;if(o==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/o;s=r;break}}}while(0);c[e+1888>>2]=13;c[e+1892>>2]=14;l=s}s=l+ +Re(d);if(s==0.0){p=2;i=j;return p|0}h[f>>3]=+h[e+112>>3]*b;b=+h[e+128>>3];h[g>>3]=b*+Se(d)/s;p=0;i=j;return p|0}function ie(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==201){l=+h[e+120>>3]}else{a[e]=5265731;a[e+1|0]=20569;a[e+2|0]=80;a[e+3|0]=0;c[k>>2]=201;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;o=+h[e+48>>3];h[e+112>>3]=o;if(o==0.0){p=1;i=j;return p|0}q=1.0/o;h[e+120>>3]=q;r=(o+ +h[e+40>>3])*57.29577951308232;h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=q;break}}else{q=+h[e+48>>3];r=n*q*3.141592653589793/180.0;h[e+112>>3]=r;if(r==0.0){p=1;i=j;return p|0}o=1.0/r;h[e+120>>3]=o;r=n*(q+ +h[e+40>>3]);h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=o;break}}}while(0);c[e+1888>>2]=13;c[e+1892>>2]=14;l=s}h[f>>3]=l*b;b=+h[e+136>>3]*d;d=+Xe(b,1.0);h[g>>3]=d+ +Ve(b*+h[e+40>>3]/+Q(+(b*b+1.0)));p=0;i=j;return p|0}function je(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==202){l=+h[e+112>>3]}else{a[e]=4277571;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=202;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=+h[e+40>>3];if(o<=0.0|o>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=57.29577951308232/o;h[e+136>>3]=o/57.29577951308232;q=1.0;break}}else{o=n*3.141592653589793/180.0;h[e+112>>3]=o;h[e+120>>3]=57.29577951308232/n;r=+h[e+40>>3];if(r<=0.0|r>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=n/r;h[e+136>>3]=r/n;q=o;break}}}while(0);c[e+1888>>2]=15;c[e+1892>>2]=16;l=q}h[f>>3]=l*b;b=+h[e+128>>3];h[g>>3]=b*+Se(d);p=0;i=j;return p|0}function ke(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==202){l=+h[e+136>>3]}else{a[e]=4277571;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=202;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=+h[e+40>>3];if(o<=0.0|o>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=57.29577951308232/o;q=o/57.29577951308232;h[e+136>>3]=q;r=q;break}}else{h[e+112>>3]=n*3.141592653589793/180.0;h[e+120>>3]=57.29577951308232/n;q=+h[e+40>>3];if(q<=0.0|q>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=n/q;o=q/n;h[e+136>>3]=o;r=o;break}}}while(0);c[e+1888>>2]=15;c[e+1892>>2]=16;l=r}r=l*d;d=+P(+r);do{if(d>1.0){if(d>1.0000000000001){p=2;i=j;return p|0}else{s=r<0.0?-1.0:1.0;break}}else{s=r}}while(0);h[f>>3]=+h[e+120>>3]*b;h[g>>3]=+Ve(s);p=0;i=j;return p|0}function le(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==203){l=e+112|0;m=l;n=+h[l>>3];o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}a[e]=5390659;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=203;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;r=+h[l>>3];if(r==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;s=1.0}else{t=r*3.141592653589793/180.0;h[e+112>>3]=t;h[e+120>>3]=1.0/t;s=t}c[e+1888>>2]=17;c[e+1892>>2]=18;m=e+112|0;n=s;o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}function me(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==203){l=e+120|0;m=l;n=+h[l>>3];o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}a[e]=5390659;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=203;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;r=+h[l>>3];if(r==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;s=1.0}else{t=r*3.141592653589793/180.0;h[e+112>>3]=t;r=1.0/t;h[e+120>>3]=r;s=r}c[e+1888>>2]=17;c[e+1892>>2]=18;m=e+120|0;n=s;o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}function ne(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0;j=i;k=e+4|0;if((c[k>>2]|0)!=204){a[e]=5391693;a[e+1|0]=21061;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=204;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0}else{n=m*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=19;c[e+1892>>2]=20}if(d<=-90.0|d>=90.0){o=2;i=j;return o|0}h[f>>3]=+h[e+112>>3]*b;b=+h[e+24>>3];h[g>>3]=b*+_(+(+Te((d+90.0)*.5)));o=0;i=j;return o|0}function oe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0,o=0.0,p=0.0,q=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==204){l=e+24|0;m=+h[e+120>>3]}else{a[e]=5391693;a[e+1|0]=21061;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=204;k=e+8|0;n=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;o=+h[n>>3];if(o==0.0){h[n>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;p=1.0}else{q=o*3.141592653589793/180.0;h[e+112>>3]=q;o=1.0/q;h[e+120>>3]=o;p=o}c[e+1888>>2]=19;c[e+1892>>2]=20;l=n;m=p}h[f>>3]=m*b;h[g>>3]=+We(+Z(+(d/+h[l>>3])))*2.0+-90.0;i=j;return 0}function pe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==301){l=e+112|0;m=l;n=+h[l>>3];o=n*b;p=+Re(d);q=o*p;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;t=+h[l>>3];if(t==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;u=1.0}else{v=t*3.141592653589793/180.0;h[e+112>>3]=v;h[e+120>>3]=1.0/v;u=v}c[e+1888>>2]=21;c[e+1892>>2]=22;m=e+112|0;n=u;o=n*b;p=+Re(d);q=o*p;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}function qe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==301){l=+h[e+24>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=57.29577951308232}else{p=n*3.141592653589793/180.0;h[e+112>>3]=p;h[e+120>>3]=1.0/p;o=n}c[e+1888>>2]=21;c[e+1892>>2]=22;l=o}o=+S(+(d/l));m=e+120|0;if(o==0.0){q=0.0;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}q=+h[m>>3]*b/o;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}function re(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=302){a[e]=5390672;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=302;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=180.0;h[e+136>>3]=.005555555555555556}else{n=m*3.141592653589793;m=n/180.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m;h[e+128>>3]=n;h[e+136>>3]=1.0/n}c[e+1888>>2]=23;c[e+1892>>2]=24}n=+Se(d/3.0);h[f>>3]=+h[e+112>>3]*b*(1.0-n*n*4.0);h[g>>3]=n*+h[e+128>>3];i=j;return 0}function se(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==302){l=+h[e+136>>3]}else{a[e]=5390672;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=302;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=180.0;h[e+136>>3]=.005555555555555556;o=.005555555555555556}else{p=n*3.141592653589793;n=p/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;h[e+128>>3]=p;n=1.0/p;h[e+136>>3]=n;o=n}c[e+1888>>2]=23;c[e+1892>>2]=24;l=o}o=l*d;if(o>1.0|o<-1.0){q=2;i=j;return q|0}d=1.0-o*o*4.0;if(d==0.0){if(b==0.0){r=0.0}else{q=2;i=j;return q|0}}else{r=+h[e+120>>3]*b/d}h[f>>3]=r;h[g>>3]=+Ve(o)*3.0;q=0;i=j;return q|0}function te(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=303){a[e]=5001037;a[e+1|0]=19535;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=303;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;n=57.29577951308232}else{n=m}m=n*1.4142135623730951;h[e+112>>3]=m;h[e+120>>3]=m/90.0;h[e+128>>3]=1.0/m;h[e+136>>3]=90.0/n;h[e+144>>3]=.6366197723675814;c[e+1888>>2]=25;c[e+1892>>2]=26}if(+P(+d)==90.0){h[f>>3]=0.0;n=+P(+(+h[e+112>>3]));if(d<0.0){o=-n}else{o=n}h[g>>3]=o;i=j;return 0}if(d==0.0){h[f>>3]=+h[e+120>>3]*b;h[g>>3]=0.0;i=j;return 0}o=+Se(d)*3.141592653589793;l=0;d=o;n=-3.141592653589793;m=3.141592653589793;while(1){p=d-o+ +T(+d);if(p<0.0){if(p>-1.0e-13){q=d;break}else{r=d;s=m}}else{if(p<1.0e-13){q=d;break}else{r=n;s=d}}p=(r+s)*.5;k=l+1|0;if((k|0)<100){l=k;d=p;n=r;m=s}else{q=p;break}}s=q*.5;h[f>>3]=+h[e+120>>3]*b*+S(+s);h[g>>3]=+h[e+112>>3]*+T(+s);i=j;return 0}function ue(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==303){l=+h[e+24>>3]}else{a[e]=5001037;a[e+1|0]=19535;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=303;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;o=57.29577951308232}else{o=n}n=o*1.4142135623730951;h[e+112>>3]=n;h[e+120>>3]=n/90.0;h[e+128>>3]=1.0/n;h[e+136>>3]=90.0/o;h[e+144>>3]=.6366197723675814;c[e+1888>>2]=25;c[e+1892>>2]=26;l=o}o=d/l;l=2.0-o*o;if(l<=1.0e-12){if(l<-1.0e-12){p=2;i=j;return p|0}if(+P(+b)>1.0e-12){p=2;i=j;return p|0}else{q=0.0;r=0.0}}else{n=+Q(+l);q=n;r=+h[e+136>>3]*b/n}h[f>>3]=r;r=+h[e+128>>3]*d;d=+P(+r);do{if(d>1.0){if(d>1.000000000001){p=2;i=j;return p|0}else{s=(r<0.0?-1.0:1.0)+o*q/3.141592653589793;break}}else{n=+W(+r);s=n*+h[e+144>>3]+o*q/3.141592653589793}}while(0);q=+P(+s);do{if(q>1.0){if(q>1.000000000001){p=2;i=j;return p|0}else{t=s<0.0?-1.0:1.0;break}}else{t=s}}while(0);h[g>>3]=+Ve(t);p=0;i=j;return p|0}function ve(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==401){l=e+112|0}else{a[e]=5523777;a[e+1|0]=21577;a[e+2|0]=84;a[e+3|0]=0;c[k>>2]=401;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;o=57.29577951308232}else{o=n}n=o*2.0;p=o*n;m=e+112|0;h[m>>3]=p;o=1.0/(p*2.0);h[e+120>>3]=o;h[e+128>>3]=o*.25;h[e+136>>3]=1.0/n;c[e+1888>>2]=27;c[e+1892>>2]=28;l=m}n=+Re(d);o=+h[l>>3];p=b*.5;b=+Q(+(o/(n*+Re(p)+1.0)));h[f>>3]=+Se(p)*n*b*2.0;h[g>>3]=b*+Se(d);i=j;return 0}function we(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==401){l=+h[e+128>>3];m=+h[e+120>>3]}else{a[e]=5523777;a[e+1|0]=21577;a[e+2|0]=84;a[e+3|0]=0;c[k>>2]=401;k=e+8|0;n=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;o=+h[n>>3];if(o==0.0){h[n>>3]=57.29577951308232;p=57.29577951308232}else{p=o}o=p*2.0;q=p*o;h[e+112>>3]=q;p=1.0/(q*2.0);h[e+120>>3]=p;q=p*.25;h[e+128>>3]=q;h[e+136>>3]=1.0/o;c[e+1888>>2]=27;c[e+1892>>2]=28;l=q;m=p}p=1.0-b*b*l-d*d*m;if(p<0.0){if(p<-1.0e-13){r=2;i=j;return r|0}else{s=0.0}}else{s=p}p=+Q(+s);s=p*d/+h[e+24>>3];d=+P(+s);do{if(d>1.0){if(d>1.0000000000001){r=2;i=j;return r|0}else{t=s<0.0?-1.0:1.0;break}}else{t=s}}while(0);s=p*p*2.0+-1.0;d=p*b*+h[e+136>>3];if(s==0.0&d==0.0){u=0.0}else{u=+Xe(d,s)*2.0}h[f>>3]=u;h[g>>3]=+Ve(t);r=0;i=j;return r|0}function xe(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0,p=0.0,q=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=501?(Ld(d)|0)!=0:0){l=1;i=g;return l|0}m=b- +h[d+40>>3];b=+Re(m);if(b==0.0){l=2;i=g;return l|0}k=d+112|0;n=+h[k>>3]*a;o=d+128|0;a=+h[o>>3];p=+h[d+136>>3];q=a-p*+Se(m)/b;h[e>>3]=q*+Se(n);b=+h[o>>3];h[f>>3]=b-q*+Re(n);if((c[j>>2]|0)>0?q*+h[k>>3]<0.0:0){l=2;i=g;return l|0}l=0;i=g;return l|0}function ye(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=501?(Ld(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+128>>3]-b;b=+Q(+(a*a+l*l));j=d+40|0;if(+h[j>>3]<0.0){m=-b}else{m=b}if(m==0.0){n=0.0}else{n=+Xe(a/m,l/m)}h[e>>3]=n*+h[d+120>>3];n=+h[j>>3];h[f>>3]=n+ +We(+h[d+152>>3]-m*+h[d+144>>3]);k=0;i=g;return k|0}function ze(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0;g=i;if((c[d+4>>2]|0)!=502?(Md(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+112>>3]*a;if(b==-90.0){l=+h[d+176>>3]}else{a=+h[d+136>>3];m=+h[d+144>>3];n=+h[d+152>>3];l=a*+Q(+(m-n*+Se(b)))}h[e>>3]=l*+Se(k);b=+h[d+128>>3];h[f>>3]=b-l*+Re(k);j=0;i=g;return j|0}function Ae(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0;g=i;if((c[d+4>>2]|0)!=502?(Md(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){m=0.0}else{m=+Xe(a/l,k/l)}h[e>>3]=m*+h[d+120>>3];if(+P(+(l- +h[d+176>>3]))<1.0e-12){h[f>>3]=-90.0;j=0;i=g;return j|0}m=(+h[d+160>>3]-l*l)*+h[d+168>>3];if(!(+P(+m)>1.0)){h[f>>3]=+Ve(m);j=0;i=g;return j|0}if(+P(+(m+-1.0))<1.0e-12){h[f>>3]=90.0;j=0;i=g;return j|0}if(!(+P(+(m+1.0))<1.0e-12)){j=2;i=g;return j|0}h[f>>3]=-90.0;j=0;i=g;return j|0}function Be(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0;g=i;if((c[d+4>>2]|0)!=503?(Nd(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+112>>3]*a;a=+h[d+136>>3]-b;h[e>>3]=a*+Se(k);b=+h[d+128>>3];h[f>>3]=b-a*+Re(k);j=0;i=g;return j|0}function Ce(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0;g=i;if((c[d+4>>2]|0)!=503?(Nd(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){m=0.0}else{m=+Xe(a/l,k/l)}h[e>>3]=m*+h[d+120>>3];h[f>>3]=+h[d+136>>3]-l;j=0;i=g;return j|0}function De(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0;g=i;if((c[d+4>>2]|0)!=504?(Od(d)|0)!=0:0){j=1;i=g;return j|0}k=d+112|0;l=+h[k>>3];m=l*a;if(b==-90.0){if(l<0.0){n=0.0}else{j=2;i=g;return j|0}}else{l=+h[d+136>>3];a=+Te((90.0-b)*.5);n=l*+R(+a,+(+h[k>>3]))}h[e>>3]=n*+Se(m);a=+h[d+128>>3];h[f>>3]=a-n*+Re(m);j=0;i=g;return j|0}function Ee(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0;g=i;if((c[d+4>>2]|0)!=504?(Od(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){h[e>>3]=+h[d+120>>3]*0.0;if(+h[d+112>>3]<0.0){m=-90.0}else{j=2;i=g;return j|0}}else{b=+Xe(a/l,k/l);n=d+120|0;h[e>>3]=b*+h[n>>3];m=90.0- +We(+R(+(l*+h[d+144>>3]),+(+h[n>>3])))*2.0}h[f>>3]=m;j=0;i=g;return j|0}function Fe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0;j=i;k=e+4|0;l=c[k>>2]|0;if(!(+h[e+40>>3]==0.0)){if((l|0)!=601){Pd(e)|0}m=e+128|0;n=+h[m>>3]- +h[e+120>>3]*d;o=+h[e+24>>3]*b;p=o*+Re(d)/n;h[f>>3]=n*+Se(p);o=+h[m>>3];q=o-n*+Re(p);h[g>>3]=q;i=j;return 0}if((l|0)==301){l=e+112|0;r=l;s=+h[l>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;p=+h[l>>3];if(p==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;t=1.0}else{n=p*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;t=n}c[e+1888>>2]=21;c[e+1892>>2]=22;r=e+112|0;s=t}h[f>>3]=s*b*+Re(d);q=+h[r>>3]*d;h[g>>3]=q;i=j;return 0}function Ge(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0;j=i;k=e+40|0;l=+h[k>>3];m=e+4|0;n=c[m>>2]|0;if(l==0.0){if((n|0)==301){o=+h[e+24>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[m>>2]=301;m=e+8|0;p=e+24|0;c[m+0>>2]=0;c[m+4>>2]=0;c[m+8>>2]=0;c[m+12>>2]=0;q=+h[p>>3];if(q==0.0){h[p>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;r=57.29577951308232}else{s=q*3.141592653589793/180.0;h[e+112>>3]=s;h[e+120>>3]=1.0/s;r=q}c[e+1888>>2]=21;c[e+1892>>2]=22;o=r}r=+S(+(d/o));p=e+120|0;if(r==0.0){t=0.0}else{t=+h[p>>3]*b/r}h[f>>3]=t;h[g>>3]=+h[p>>3]*d;i=j;return 0}else{if((n|0)==601){u=l}else{Pd(e)|0;u=+h[k>>3]}k=e+128|0;l=+h[k>>3];t=l-d;d=+Q(+(b*b+t*t));if(u<0.0){v=-d}else{v=d}if(v==0.0){w=l;x=0.0}else{l=+Xe(b/v,t/v);w=+h[k>>3];x=l}l=(w-v)/+h[e+120>>3];h[g>>3]=l;w=+Re(l);if(w==0.0){y=0.0}else{y=x*(v/+h[e+24>>3])/w}h[f>>3]=y;i=j;return 0}return 0}function He(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=602){a[e]=5194576;a[e+1|0]=20291;a[e+2|0]=79;a[e+3|0]=0;c[k>>2]=602;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=114.59155902616465}else{n=m*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;h[e+128>>3]=m*2.0}c[e+1888>>2]=29;c[e+1892>>2]=30}m=+Re(d);n=+Se(d);o=n*b;if(n==0.0){h[f>>3]=+h[e+112>>3]*b;p=0.0;h[g>>3]=p;i=j;return 0}else{b=m/n;l=e+24|0;n=b*+h[l>>3];h[f>>3]=n*+Se(o);n=+h[l>>3];p=n*(d*3.141592653589793/180.0+b*(1.0- +Re(o)));h[g>>3]=p;i=j;return 0}return 0}function Ie(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0,y=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==602){l=+h[e+120>>3]}else{a[e]=5194576;a[e+1|0]=20291;a[e+2|0]=79;a[e+3|0]=0;c[k>>2]=602;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=114.59155902616465;o=1.0}else{p=n*3.141592653589793/180.0;h[e+112>>3]=p;q=1.0/p;h[e+120>>3]=q;h[e+128>>3]=n*2.0;o=q}c[e+1888>>2]=29;c[e+1892>>2]=30;l=o}o=+P(+(l*d));if(o<1.0e-12){h[f>>3]=l*b;h[g>>3]=0.0;i=j;return 0}if(+P(+(o+-90.0))<1.0e-12){h[f>>3]=0.0;h[g>>3]=d<0.0?-90.0:90.0;i=j;return 0}o=d>0.0?90.0:-90.0;l=b*b;m=e+112|0;q=d-o*+h[m>>3];k=e+128|0;n=-999.0;p=l+q*q;r=0;q=0.0;s=o;while(1){if(n<-100.0){t=(q+s)*.5}else{o=p/(p-n);if(!(o<.1)){if(o>.9){u=.9}else{u=o}}else{u=.1}t=s-(s-q)*u}h[g>>3]=t;v=d-t*+h[m>>3];w=+Te(t);o=l+v*(v- +h[k>>3]/w);if(+P(+o)<1.0e-12){break}if(+P(+(s-q))<1.0e-12){break}x=o>0.0;y=+h[g>>3];r=r+1|0;if((r|0)>=64){break}else{n=x?n:o;p=x?o:p;q=x?q:y;s=x?y:s}}s=+h[e+24>>3]-w*v;v=w*b;if(s==0.0&v==0.0){h[f>>3]=0.0;i=j;return 0}else{b=+Xe(v,s);h[f>>3]=b/+Se(+h[g>>3]);i=j;return 0}return 0}function Je(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=701){a[e]=4412244;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=701;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=31;c[e+1892>>2]=32}n=+Re(d);m=n*+Re(b);o=n*+Se(b);b=+Se(d);l=m>b;d=l?m:b;k=o>d;n=k?o:d;d=-m;p=n1.0){if(u>1.000000000001){z=2;i=j;return z|0}else{A=w<0.0?-1.0:1.0;break}}else{A=w}}while(0);w=+P(+y);do{if(w>1.0){if(w>1.000000000001){z=2;i=j;return z|0}else{B=y<0.0?-1.0:1.0;break}}else{B=y}}while(0);l=e+112|0;h[f>>3]=(v+A)*+h[l>>3];h[g>>3]=(x+B)*+h[l>>3];z=0;i=j;return z|0}function Ke(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==701){l=+h[e+120>>3]}else{a[e]=4412244;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=701;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=31;c[e+1892>>2]=32;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){o=r+-4.0;d=-1.0/+Q(+(b*b+(o*o+1.0)));s=d;t=o*d;u=-(b*d);break}if(r>1.0){d=r+-2.0;o=1.0/+Q(+(b*b+(d*d+1.0)));s=-(d*o);t=o;u=b*o;break}if(b>1.0){o=b+-2.0;d=1.0/+Q(+(o*o+(r*r+1.0)));s=-(o*d);t=r*d;u=d;break}if(b<-1.0){d=b+2.0;o=-1.0/+Q(+(d*d+(r*r+1.0)));l=-o;s=d*l;t=r*l;u=o;break}else{o=1.0/+Q(+(b*b+(r*r+1.0)));s=o;t=r*o;u=b*o;break}}else{o=r+-6.0;l=-1.0/+Q(+(b*b+(o*o+1.0)));d=-l;s=o*d;t=l;u=b*d}}while(0);if(s==0.0&t==0.0){v=0.0}else{v=+Xe(t,s)}h[f>>3]=v;h[g>>3]=+Ve(u);q=0;i=j;return q|0}function Le(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0,E=0.0,F=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=702){a[e]=4412227;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=702;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=33;c[e+1892>>2]=34}n=+Re(d);m=n*+Re(b);o=n*+Se(b);b=+Se(d);l=m>b;d=l?m:b;k=o>d;n=k?o:d;d=-m;p=n1.0e-16){A=u*u}else{A=0.0}if(w>1.0e-16){B=w*w}else{B=0.0}if(b>1.0e-16){C=u*w*.15384112298488617}else{C=0.0}b=o*(u+m*(u*(-.15959623456001282-m*(u*-.021776249632239342+.07591962069272995))+(w*(u*.004869491793215275+m*-.1316167116165161+n*(B*.10695946961641312+(A*-.1782512068748474+(u*.08097013086080551+.14118963479995728+w*-.2815285325050354+C))))+1.374848484992981)));o=y*(w+n*(w*(-.15959623456001282-n*(w*-.021776249632239342+.07591962069272995))+(u*(w*.004869491793215275+n*-.1316167116165161+m*(A*.10695946961641312+(B*-.1782512068748474+(u*-.2815285325050354+(w*.08097013086080551+.14118963479995728)+C))))+1.374848484992981)));C=+P(+b);do{if(C>1.0){if(C>1.0000001000000012){D=2;i=j;return D|0}else{E=b<0.0?-1.0:1.0;break}}else{E=b}}while(0);b=+P(+o);do{if(b>1.0){if(b>1.0000001000000012){D=2;i=j;return D|0}else{F=o<0.0?-1.0:1.0;break}}else{F=o}}while(0);l=e+112|0;h[f>>3]=(x+E)*+h[l>>3];h[g>>3]=+h[l>>3]*(z+F);D=0;i=j;return D|0}function Me(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==702){l=+h[e+120>>3]}else{a[e]=4412227;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=702;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=33;c[e+1892>>2]=34;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){s=3;t=r+-4.0;u=b;break}if(r>1.0){s=2;t=r+-2.0;u=b;break}if(b>1.0){s=0;t=r;u=b+-2.0;break}if(b<-1.0){s=5;t=r;u=b+2.0}else{s=1;t=r;u=b}}else{s=4;t=r+-6.0;u=b}}while(0);b=t*t;r=u*u;o=t;t=o+o*(1.0-b)*(b*(b*(b*(b*(b*(b*.025843750685453415+.25795793533325195)+-.6293006539344788)+.5485238432884216)+-.22797055542469025)+-.07629968971014023)+-.2729269564151764+r*(b*(b*(b*(b*(b*-.5302233695983887+1.715475082397461)+-1.7411445379257202)+.48051509261131287)+-.014715650118887424)+-.028194520622491837+r*(b*(b*(b*(b*-.8318046927452087+.9893810153007507)+.30803316831588745)+-.5680093765258789)+.27058160305023193+r*(b*(b*(b*.08693841099739075+-.9367857575416565)+1.5088008642196655)+-.6044155955314636+r*(b*(b*.3388744592666626+-1.4160192012786865)+.934120774269104+r*(r*.14381584525108337+(b*.5203223824501038+-.6391530632972717)))))));o=u;u=o+o*(1.0-r)*(r*(r*(r*(r*(r*(r*.025843750685453415+.25795793533325195)+-.6293006539344788)+.5485238432884216)+-.22797055542469025)+-.07629968971014023)+-.2729269564151764+b*(r*(r*(r*(r*(r*-.5302233695983887+1.715475082397461)+-1.7411445379257202)+.48051509261131287)+-.014715650118887424)+-.028194520622491837+b*(r*(r*(r*(r*-.8318046927452087+.9893810153007507)+.30803316831588745)+-.5680093765258789)+.27058160305023193+b*(r*(r*(r*.08693841099739075+-.9367857575416565)+1.5088008642196655)+-.6044155955314636+b*(r*(r*.3388744592666626+-1.4160192012786865)+.934120774269104+b*(r*.5203223824501038+-.6391530632972717+b*.14381584525108337))))));switch(s|0){case 1:{b=1.0/+Q(+(u*u+t*t+1.0));v=b;w=t*b;x=u*b;break};case 4:{b=-1.0/+Q(+(u*u+t*t+1.0));v=-t*b;w=b;x=-u*b;break};case 0:{b=1.0/+Q(+(u*u+t*t+1.0));v=-u*b;w=t*b;x=b;break};case 5:{b=-1.0/+Q(+(u*u+t*t+1.0));v=-u*b;w=-t*b;x=b;break};case 3:{b=-1.0/+Q(+(u*u+t*t+1.0));v=b;w=t*b;x=-u*b;break};case 2:{b=1.0/+Q(+(u*u+t*t+1.0));v=-t*b;w=b;x=u*b;break};default:{v=0.0;w=0.0;x=0.0}}if(v==0.0&w==0.0){y=0.0}else{y=+Xe(w,v)}h[f>>3]=y;h[g>>3]=+Ve(x);q=0;i=j;return q|0}function Ne(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0,t=0.0,u=0,v=0.0,w=0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=703){a[e]=4412241;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=703;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=35;c[e+1892>>2]=36}if(+P(+d)==90.0){h[f>>3]=0.0;n=+P(+(+h[e+112>>3]*2.0));if(d<0.0){o=-n}else{o=n}h[g>>3]=o;p=0;i=j;return p|0}o=+Re(d);n=o*+Re(b);m=o*+Se(b);o=+Se(d);l=n>o;q=l?n:o;k=m>q;r=k?m:q;q=-n;s=r180.0){z=y+-360.0}else{z=y}y=z*.017453292519943295;A=o;B=(v*v+y*y)*.5;C=0.0;D=m;E=0.0}else{A=o;B=x;C=0.0;D=m;E=0.0}break};case 3:{if(x<1.0e-8){y=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v<0.0){F=v+360.0}else{F=v}v=(180.0-F)*3.141592653589793/180.0;A=o;B=(y*y+v*v)*.5;C=4.0;D=r;E=0.0}else{A=o;B=x;C=4.0;D=r;E=0.0}break};case 0:{if(x<1.0e-8){r=(90.0-d)*3.141592653589793/180.0;A=q;B=r*r*.5;C=0.0;D=m;E=2.0}else{A=q;B=x;C=0.0;D=m;E=2.0}break};case 2:{if(x<1.0e-8){r=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v<-180.0){G=v+360.0}else{G=v}v=(90.0-G)*3.141592653589793/180.0;A=o;B=(r*r+v*v)*.5;C=2.0;D=q;E=0.0}else{A=o;B=x;C=2.0;D=q;E=0.0}break};case 4:{if(x<1.0e-8){q=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v>180.0){H=v+-360.0}else{H=v}v=H*((H+90.0)*3.141592653589793/180.0);A=o;B=(q*q+v*v)*.5;C=6.0;D=n;E=0.0}else{A=o;B=x;C=6.0;D=n;E=0.0}break};case 5:{if(x<1.0e-8){o=(d+90.0)*3.141592653589793/180.0;A=n;B=o*o*.5;C=0.0;D=m;E=-2.0}else{A=n;B=x;C=0.0;D=m;E=-2.0}break};default:{A=0.0;B=x;C=0.0;D=0.0;E=0.0}}do{if(!(D==0.0&A==0.0)){x=+P(+A);if(x<=-D){m=A/D;n=m*m+1.0;o=-+Q(+(B/(1.0-1.0/+Q(+(n+1.0)))));d=+We(m);I=o;J=o/15.0*(d- +Ve(m/+Q(+(n+n))));break}if(D>=x){x=A/D;n=x*x+1.0;m=+Q(+(B/(1.0-1.0/+Q(+(n+1.0)))));d=+We(x);I=m;J=m/15.0*(d- +Ve(x/+Q(+(n+n))));break}n=+P(+D);if(n<-A){x=D/A;d=x*x+1.0;m=-+Q(+(B/(1.0-1.0/+Q(+(d+1.0)))));o=+We(x);I=m/15.0*(o- +Ve(x/+Q(+(d+d))));J=m;break}if(A>n){n=D/A;m=n*n+1.0;d=+Q(+(B/(1.0-1.0/+Q(+(m+1.0)))));x=+We(n);I=d/15.0*(x- +Ve(n/+Q(+(m+m))));J=d}else{I=0.0;J=0.0}}else{I=0.0;J=0.0}}while(0);B=+P(+I);do{if(B>1.0){if(B>1.000000000001){p=2;i=j;return p|0}else{K=I<0.0?-1.0:1.0;break}}else{K=I}}while(0);I=+P(+J);do{if(I>1.0){if(I>1.000000000001){p=2;i=j;return p|0}else{L=J<0.0?-1.0:1.0;break}}else{L=J}}while(0);l=e+112|0;h[f>>3]=(C+K)*+h[l>>3];h[g>>3]=(E+L)*+h[l>>3];p=0;i=j;return p|0}function Oe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,S=0.0,T=0.0,U=0.0,V=0.0,W=0.0,X=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==703){l=+h[e+120>>3]}else{a[e]=4412241;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=703;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=35;c[e+1892>>2]=36;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){s=3;t=r+-4.0;u=b;break}if(r>1.0){s=2;t=r+-2.0;u=b;break}if(b>1.0){s=0;t=r;u=b+-2.0;break}if(b<-1.0){s=5;t=r;u=b+2.0}else{s=1;t=r;u=b}}else{s=4;t=r+-6.0;u=b}}while(0);e=+P(+t)>+P(+u);if(e){if(t==0.0){v=0.0;w=1.0;x=0.0;y=1.0;z=30}else{b=u*15.0/t;r=+Se(b);o=r/(+Re(b)+-.7071067811865475);b=o*o+1.0;A=t*t*(1.0-1.0/+Q(+(b+1.0)));B=o;C=b;z=28}}else{if(u==0.0){v=0.0;w=1.0;x=0.0;y=1.0;z=30}else{b=t*15.0/u;o=+Se(b);r=o/(+Re(b)+-.7071067811865475);b=r*r+1.0;A=u*u*(1.0-1.0/+Q(+(b+1.0)));B=r;C=b;z=28}}if((z|0)==28){b=1.0-A;if(b<-1.0){if(b<-1.000000000001){q=2;i=j;return q|0}else{D=B;E=-1.0;F=0.0}}else{v=B;w=b;x=A;y=C;z=30}}if((z|0)==30){D=v;E=w;F=+Q(+(x*(2.0-x)/y))}a:do{switch(s|0){case 2:{if(e){if(t>0.0){G=-F}else{G=F}H=G;I=E;J=-(D*G);break a}else{if(u<0.0){K=-F}else{K=F}H=-(D*K);I=E;J=K;break a}break};case 3:{y=-E;if(e){if(t>0.0){L=-F}else{L=F}H=y;I=L;J=-(D*L);break a}else{if(u<0.0){M=-F}else{M=F}H=y;I=-(D*M);J=M;break a}break};case 1:{if(e){if(t<0.0){N=-F}else{N=F}H=E;I=N;J=D*N;break a}else{if(u<0.0){O=-F}else{O=F}H=E;I=D*O;J=O;break a}break};case 5:{y=-E;if(e){if(t<0.0){R=-F}else{R=F}H=D*R;I=R;J=y;break a}else{if(u<0.0){S=-F}else{S=F}H=S;I=D*S;J=y;break a}break};case 4:{y=-E;if(e){if(t<0.0){T=-F}else{T=F}H=T;I=y;J=D*T;break a}else{if(u<0.0){U=-F}else{U=F}H=D*U;I=y;J=U;break a}break};case 0:{if(e){if(t<0.0){V=-F}else{V=F}H=-(D*V);I=V;J=E;break a}else{if(u>0.0){W=-F}else{W=F}H=W;I=-(D*W);J=E;break a}break};default:{H=0.0;I=0.0;J=0.0}}}while(0);if(H==0.0&I==0.0){X=0.0}else{X=+Xe(I,H)}h[f>>3]=X;h[g>>3]=+Ve(J);q=0;i=j;return q|0}function Pe(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;f=i;g=+Re(b);j=+Se(b);k=a- +h[c>>3];a=+Re(k);l=+Se(k);m=c+32|0;n=c+24|0;o=j*+h[m>>3]-a*g*+h[n>>3];if(+P(+o)<1.0e-5){p=+Re(+h[c+8>>3]+b);q=(1.0-a)*g*+h[n>>3]-p}else{q=o}o=g*l;if(q!=0.0|o!=-0.0){r=+Xe(-o,q)}else{r=k+-180.0}l=r+ +h[c+16>>3];h[d>>3]=l;if(!(l>180.0)){if(l<-180.0){h[d>>3]=l+360.0}}else{h[d>>3]=l+-360.0}if(+qa(+k,180.0)==0.0){k=a*+h[c+8>>3]+b;if(k>90.0){s=180.0-k}else{s=k}h[e>>3]=s;if(!(s<-90.0)){i=f;return 0}h[e>>3]=-180.0-s;i=f;return 0}s=j*+h[n>>3]+a*g*+h[m>>3];if(!(+P(+s)>.99)){h[e>>3]=+Ve(s);i=f;return 0}g=+Ue(+Q(+(o*o+q*q)));if(s<0.0){h[e>>3]=-g;i=f;return 0}else{h[e>>3]=g;i=f;return 0}return 0}function Qe(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;f=i;g=+Re(b);j=+Se(b);k=a- +h[c+16>>3];a=+Re(k);l=+Se(k);m=c+32|0;n=c+24|0;o=j*+h[m>>3]-a*g*+h[n>>3];if(+P(+o)<1.0e-5){p=+Re(+h[c+8>>3]+b);q=(1.0-a)*g*+h[n>>3]-p}else{q=o}o=g*l;if(q!=0.0|o!=-0.0){r=+Xe(-o,q)}else{r=k+180.0}l=r+ +h[c>>3];h[d>>3]=l;if(!(+h[c>>3]>=0.0)){if(l>0.0){r=l+-360.0;h[d>>3]=r;s=r}else{s=l}}else{if(l<0.0){r=l+360.0;h[d>>3]=r;s=r}else{s=l}}if(!(s>360.0)){if(s<-360.0){h[d>>3]=s+360.0}}else{h[d>>3]=s+-360.0}if(+qa(+k,180.0)==0.0){k=a*+h[c+8>>3]+b;if(k>90.0){t=180.0-k}else{t=k}h[e>>3]=t;if(!(t<-90.0)){i=f;return 0}h[e>>3]=-180.0-t;i=f;return 0}t=j*+h[n>>3]+a*g*+h[m>>3];if(!(+P(+t)>.99)){h[e>>3]=+Ve(t);i=f;return 0}g=+Ue(+Q(+(o*o+q*q)));if(t<0.0){h[e>>3]=-g;i=f;return 0}else{h[e>>3]=g;i=f;return 0}return 0}function Re(a){a=+a;var b=0,c=0.0,d=0.0,e=0.0;b=i;c=+qa(+a,360.0);d=+P(+c);if(!(c==0.0)){if(!(d==90.0)){if(!(d==180.0)){if(d==270.0){e=0.0}else{e=+S(+(a*.017453292519943295))}}else{e=-1.0}}else{e=0.0}}else{e=1.0}i=b;return+e}function Se(a){a=+a;var b=0,c=0.0,d=0.0;b=i;c=+qa(+(a+-90.0),360.0);if(!(c==0.0)){if(!(c==90.0)){if(!(c==180.0)){if(c==270.0){d=0.0}else{d=+T(+(a*.017453292519943295))}}else{d=-1.0}}else{d=0.0}}else{d=1.0}i=b;return+d}function Te(a){a=+a;var b=0,c=0.0,d=0.0;b=i;c=+qa(+a,360.0);if(!(c==0.0)?!(+P(+c)==180.0):0){if(!(c==45.0|c==225.0)){if(c==-135.0|c==-315.0){d=-1.0}else{d=+U(+(a*.017453292519943295))}}else{d=1.0}}else{d=0.0}i=b;return+d}function Ue(a){a=+a;var b=0,c=0.0,d=0;b=i;if(!(a>=1.0)){if(!(a==0.0)){if(a<=-1.0&a+1.0>-1.0e-10){c=180.0}else{d=5}}else{c=90.0}}else{if(a+-1.0<1.0e-10){c=0.0}else{d=5}}if((d|0)==5){c=+V(+a)*57.29577951308232}i=b;return+c}function Ve(a){a=+a;var b=0,c=0.0,d=0;b=i;if(!(a<=-1.0)){if(!(a==0.0)){if(a>=1.0&a+-1.0<1.0e-10){c=90.0}else{d=5}}else{c=0.0}}else{if(a+1.0>-1.0e-10){c=-90.0}else{d=5}}if((d|0)==5){c=+W(+a)*57.29577951308232}i=b;return+c}function We(a){a=+a;var b=0,c=0.0;b=i;if(!(a==-1.0)){if(!(a==0.0)){if(a==1.0){c=45.0}else{c=+X(+a)*57.29577951308232}}else{c=0.0}}else{c=-45.0}i=b;return+c}function Xe(a,b){a=+a;b=+b;var c=0,d=0.0,e=0;c=i;if(a==0.0){if(!(b>=0.0)){if(b<0.0){d=180.0}else{e=7}}else{d=0.0}}else{if(b==0.0){if(!(a>0.0)){if(a<0.0){d=-90.0}else{e=7}}else{d=90.0}}else{e=7}}if((e|0)==7){d=+Y(+a,+b)*57.29577951308232}i=c;return+d}function Ye(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;i=i+32|0;e=d;f=d+8|0;if((c[a+5968>>2]|0)!=1){i=d;return}g=a+3324|0;if((c[g>>2]|0)==2){c[g>>2]=3;c[a+5976>>2]=0;c[a+6784>>2]=0;c[a+7592>>2]=0;c[a+8400>>2]=0;i=d;return}g=a+5976|0;if((Ec(b,12288,g)|0)!=0){h=c[g>>2]|0;g=(h|0)<0;if(!g){j=(h<<3)+8|0;k=0;while(1){Eg(a+(k*80|0)+5984|0,0,j|0)|0;if((k|0)==(h|0)){break}else{k=k+1|0}}if(!g){g=h+1|0;k=0;j=g;while(1){if((h-k|0)>=0){l=0;do{c[e>>2]=k;c[e+4>>2]=l;Na(f|0,12360,e|0)|0;Lc(b,f,a+(k*80|0)+(l<<3)+5984|0)|0;l=l+1|0}while((l|0)!=(j|0))}k=k+1|0;if((k|0)==(g|0)){break}else{j=j+ -1|0}}}}}else{_b(12296)}j=a+6784|0;if((Ec(b,12368,j)|0)!=0){g=c[j>>2]|0;j=(g|0)<0;if(!j){k=(g<<3)+8|0;h=0;while(1){Eg(a+(h*80|0)+6792|0,0,k|0)|0;if((h|0)==(g|0)){break}else{h=h+1|0}}if(!j){j=g+1|0;h=0;k=j;while(1){if((g-h|0)>=0){l=0;do{c[e>>2]=h;c[e+4>>2]=l;Na(f|0,12440,e|0)|0;Lc(b,f,a+(h*80|0)+(l<<3)+6792|0)|0;l=l+1|0}while((l|0)!=(k|0))}h=h+1|0;if((h|0)==(j|0)){break}else{k=k+ -1|0}}}}}else{_b(12376)}k=a+7592|0;if((Ec(b,12448,k)|0)!=0){j=c[k>>2]|0;k=(j|0)<0;if(!k){h=(j<<3)+8|0;g=0;while(1){Eg(a+(g*80|0)+7600|0,0,h|0)|0;if((g|0)==(j|0)){break}else{g=g+1|0}}if(!k){k=j+1|0;g=0;h=k;while(1){if((j-g|0)>=0){l=0;do{c[e>>2]=g;c[e+4>>2]=l;Na(f|0,12528,e|0)|0;Lc(b,f,a+(g*80|0)+(l<<3)+7600|0)|0;l=l+1|0}while((l|0)!=(h|0))}g=g+1|0;if((g|0)==(k|0)){break}else{h=h+ -1|0}}}}}else{_b(12464)}h=a+8400|0;if((Ec(b,12544,h)|0)==0){_b(12560);i=d;return}k=c[h>>2]|0;h=(k|0)<0;if(h){i=d;return}g=(k<<3)+8|0;j=0;while(1){Eg(a+(j*80|0)+8408|0,0,g|0)|0;if((j|0)==(k|0)){break}else{j=j+1|0}}if(h){i=d;return}h=k+1|0;j=0;g=h;while(1){if((k-j|0)>=0){l=0;do{c[e>>2]=j;c[e+4>>2]=l;Na(f|0,12624,e|0)|0;Lc(b,f,a+(j*80|0)+(l<<3)+8408|0)|0;l=l+1|0}while((l|0)!=(g|0))}j=j+1|0;if((j|0)==(h|0)){break}else{g=g+ -1|0}}i=d;return}function Ze(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0,y=0.0,z=0.0;g=i;i=i+80|0;j=g;if((c[a+5968>>2]|0)!=1){h[e>>3]=b;k=d;h[f>>3]=k;i=g;return}l=c[a+7592>>2]|0;m=c[a+8400>>2]|0;n=b- +h[a+16>>3];o=d- +h[a+24>>3];if((l|0)>=0){p=0;while(1){q=l-p|0;r=+h[a+(q*80|0)+(p<<3)+7600>>3];s=j+(p<<3)|0;h[s>>3]=r;if((p|0)>0){t=p;u=r;do{t=t+ -1|0;u=o*u+ +h[a+(q*80|0)+(t<<3)+7600>>3]}while((t|0)>0);h[s>>3]=u}if((p|0)==(l|0)){break}else{p=p+1|0}}r=+h[j>>3];if((l|0)>0){p=l+1|0;t=l;v=r;while(1){w=n*v+ +h[j+(p-t<<3)>>3];l=t+ -1|0;if((l|0)>0){t=l;v=w}else{x=j;y=w;break}}}else{x=j;y=r}}else{x=j;y=0.0}h[e>>3]=y;if((m|0)>=0){t=0;while(1){p=m-t|0;y=+h[a+(p*80|0)+(t<<3)+8408>>3];l=j+(t<<3)|0;h[l>>3]=y;if((t|0)>0){q=t;r=y;do{q=q+ -1|0;r=o*r+ +h[a+(p*80|0)+(q<<3)+8408>>3]}while((q|0)>0);h[l>>3]=r}if((t|0)==(m|0)){break}else{t=t+1|0}}o=+h[x>>3];if((m|0)>0){t=m+1|0;a=m;u=o;while(1){y=n*u+ +h[j+(t-a<<3)>>3];m=a+ -1|0;if((m|0)>0){a=m;u=y}else{z=y;break}}}else{z=o}}else{z=+h[x>>3]}h[f>>3]=z;h[e>>3]=+h[e>>3]+b;k=+h[f>>3]+d;h[f>>3]=k;i=g;return}function _e(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0,y=0.0,z=0.0;g=i;i=i+80|0;j=g;if((c[a+5968>>2]|0)!=1){h[e>>3]=b;k=d;h[f>>3]=k;i=g;return}l=c[a+5976>>2]|0;m=c[a+6784>>2]|0;n=b- +h[a+16>>3];o=d- +h[a+24>>3];if((l|0)>=0){p=0;while(1){q=l-p|0;r=+h[a+(q*80|0)+(p<<3)+5984>>3];s=j+(p<<3)|0;h[s>>3]=r;if((p|0)>0){t=p;u=r;do{t=t+ -1|0;u=o*u+ +h[a+(q*80|0)+(t<<3)+5984>>3]}while((t|0)>0);h[s>>3]=u}if((p|0)==(l|0)){break}else{p=p+1|0}}r=+h[j>>3];if((l|0)>0){p=l+1|0;t=l;v=r;while(1){w=n*v+ +h[j+(p-t<<3)>>3];l=t+ -1|0;if((l|0)>0){t=l;v=w}else{x=j;y=w;break}}}else{x=j;y=r}}else{x=j;y=0.0}h[e>>3]=y;if((m|0)>=0){t=0;while(1){p=m-t|0;y=+h[a+(p*80|0)+(t<<3)+6792>>3];l=j+(t<<3)|0;h[l>>3]=y;if((t|0)>0){q=t;r=y;do{q=q+ -1|0;r=o*r+ +h[a+(p*80|0)+(q<<3)+6792>>3]}while((q|0)>0);h[l>>3]=r}if((t|0)==(m|0)){break}else{t=t+1|0}}o=+h[x>>3];if((m|0)>0){t=m+1|0;a=m;u=o;while(1){y=n*u+ +h[j+(t-a<<3)>>3];m=a+ -1|0;if((m|0)>0){a=m;u=y}else{z=y;break}}}else{z=o}}else{z=+h[x>>3]}h[f>>3]=z;h[e>>3]=+h[e>>3]+b;k=+h[f>>3]+d;h[f>>3]=k;i=g;return}function $e(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;if((Dg(b|0)|0)<9){c[a+5968>>2]=0;i=d;return}e=a+5968|0;if((Ag(b+8|0,12640,4)|0)==0){c[e>>2]=1;i=d;return}else{c[e>>2]=0;i=d;return}}function af(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0.0,k=0.0,l=0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;e=i;i=i+16|0;f=e;c[3162]=0;g=(d|0)==0;h=b;while(1){if((a[h]|0)==32){h=h+1|0}else{break}}b=g?f:d;j=+wg(h,b);d=c[b>>2]|0;if(($f(h,46)|0)!=0){c[3162]=46}f=a[d]|0;g=f<<24>>24;switch(f<<24>>24){case 32:case 58:case 100:case 104:case 109:{break};default:{k=j;i=e;return+k}}l=d;if((l-h|0)>=5){k=j;i=e;return+k}m=d+1|0;n=a[m]|0;if(!(((n<<24>>24)+ -48|0)>>>0<10)){if(!(n<<24>>24==32)){k=j;i=e;return+k}if(!(((a[d+2|0]|0)+ -48|0)>>>0<10)){k=j;i=e;return+k}}c[3162]=g;c[b>>2]=m;if((a[h]|0)==45){o=-j;p=-1.0}else{o=j;p=1.0}j=+wg(m,b);do{if(!(f<<24>>24==109)){m=c[b>>2]|0;h=a[m]|0;if(h<<24>>24==32|h<<24>>24==58|h<<24>>24==109?(m-l|0)<4:0){h=m+1|0;g=a[h]|0;if(!(((g<<24>>24)+ -48|0)>>>0<10)){if(!(g<<24>>24==32)){q=o;r=j;s=0.0;break}if(!(((a[m+2|0]|0)+ -48|0)>>>0<10)){q=o;r=j;s=0.0;break}}c[b>>2]=h;q=o;r=j;s=+wg(h,b)}else{q=o;r=j;s=0.0}}else{q=0.0;r=o;s=j}}while(0);k=p*(q+r/60.0+s/3600.0);i=e;return+k}function bf(a,b,d,e,f,j,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;j=j|0;l=+l;m=m|0;n=n|0;var o=0,p=0,q=0,r=0,s=0.0,t=0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0;o=i;i=i+48|0;p=o;q=o+36|0;r=o+32|0;s=l;c[r>>2]=0;if((c[58]|0)!=0){c[p>>2]=b;c[p+4>>2]=d;c[p+8>>2]=e;t=p+12|0;h[k>>3]=s;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];c[p+20>>2]=m;c[p+24>>2]=n;Ma(12656,p|0)|0}t=cf(a,e,r,b,d,m,n)|0;n=c[r>>2]|0;Zf(n,t,4,4);l=+g[n>>2];u=+g[n+(t+ -1<<2)>>2];r=t+1|0;if((r|0)<2){v=1}else{v=(r|0)/2|0}r=v+ -1|0;m=n+(r<<2)|0;w=+g[m>>2];if(((t|0)%2|0|0)!=1&(v|0)<(t|0)){x=(w+ +g[n+(v<<2)>>2])*.5}else{x=w}w=+(t|0);d=~~(w*.5);b=(d|0)<5?5:d;d=~~(w*.01+.5);e=(d|0)<1?1:d;d=df(n,t,o+40|0,q,2.5,e,5)|0;if((d|0)<(b|0)){g[f>>2]=l;y=u}else{w=+g[q>>2];if(s>0.0){z=w/s;g[q>>2]=z;A=z}else{A=w}w=x- +(r|0)*A;g[f>>2]=l>w?l:w;w=x+ +(t-v|0)*A;y=u>2]=y;if((c[58]|0)==0){hg(n);i=o;return}y=+g[m>>2];h[k>>3]=l;c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];m=p+8|0;h[k>>3]=u;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];m=p+16|0;h[k>>3]=y;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];m=p+24|0;h[k>>3]=x;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];Ma(12704,p|0)|0;c[p>>2]=b;c[p+4>>2]=e;c[p+8>>2]=d;Ma(12752,p|0)|0;x=+g[f>>2];y=+g[j>>2];h[k>>3]=+g[q>>2];c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];c[p+8>>2]=v;v=p+12|0;h[k>>3]=x;c[v>>2]=c[k>>2];c[v+4>>2]=c[k+4>>2];v=p+20|0;h[k>>3]=y;c[v>>2]=c[k>>2];c[v+4>>2]=c[k+4>>2];Ma(12800,p|0)|0;hg(n);i=o;return}function cf(d,e,f,j,k,l,m){d=d|0;e=e|0;f=f|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;n=i;i=i+16|0;o=n;p=(j|0)<(m|0)?j:m;q=(p|0)<1?1:p;p=j+ -1|0;r=(p+q|0)/(q|0)|0;s=(r|0)<2?2:r;r=(p+s|0)/(s|0)|0;p=(r|0)<1?1:r;if((c[58]|0)==0){t=1}else{c[o>>2]=q;c[o+4>>2]=s;c[o+8>>2]=p;Ma(12856,o|0)|0;t=(c[58]|0)==0}q=(l|0)/(m|0)|0;m=(q|0)<1?1:q;q=(l+ -1+p|0)/(p|0)|0;l=(q|0)>(k|0)?k:q;q=(m|0)>(l|0)?m:l;l=(k|0)/(q|0)|0;r=(l|0)<2?2:l;u=(k+ -1+r|0)/(r|0)|0;if(!t){c[o>>2]=m;c[o+4>>2]=q;c[o+8>>2]=r;c[o+12>>2]=u;Ma(12912,o|0)|0}o=aa(u,p)|0;u=gg(o<<2)|0;c[f>>2]=u;f=j<<2;q=gg(f)|0;m=(r+1|0)/2|0;if((m|0)>=(k|0)){v=0;hg(q);i=n;return v|0}t=(p|0)>0;w=(j|0)>0;x=j<<1;y=j<<3;if((e|0)==8){z=m;A=0;B=u;while(1){C=aa(z+ -1|0,j)|0;if(w){D=0;do{g[q+(D<<2)>>2]=+(a[d+(D+C)|0]|0);D=D+1|0}while((D|0)!=(j|0))}a:do{if(t){D=0;C=0;while(1){g[B+(D<<2)>>2]=+g[q+(C<<2)>>2];E=D+1|0;if((E|0)==(p|0)){break a}D=E;C=C+s|0}}}while(0);C=A+p|0;if((C|0)>(o|0)){v=C;F=29;break}D=z+r|0;if((D|0)<(k|0)){z=D;A=C;B=B+(p<<2)|0}else{v=C;F=29;break}}if((F|0)==29){hg(q);i=n;return v|0}}B=(aa(m+ -1|0,j)|0)<<2;A=(aa((l|0)>2?l:2,j)|0)<<2;l=j<<2;z=0;C=m;m=0;D=u;while(1){u=d+(B+(aa(A,z)|0))|0;if((e|0)==32){E=d+(aa(f,C+ -1|0)|0)|0;if(w){G=0;do{g[q+(G<<2)>>2]=+(c[E+(G<<2)>>2]|0);G=G+1|0}while((G|0)!=(j|0))}}else if((e|0)==-32){if(w){Kg(q|0,u|0,l|0)|0}}else if((e|0)==-64){G=d+(aa(y,C+ -1|0)|0)|0;if(w){E=0;do{g[q+(E<<2)>>2]=+h[G+(E<<3)>>3];E=E+1|0}while((E|0)!=(j|0))}}else if((e|0)==16?(E=d+(aa(x,C+ -1|0)|0)|0,w):0){G=0;do{g[q+(G<<2)>>2]=+(b[E+(G<<1)>>1]|0);G=G+1|0}while((G|0)!=(j|0))}b:do{if(t){G=0;E=0;while(1){g[D+(G<<2)>>2]=+g[q+(E<<2)>>2];u=G+1|0;if((u|0)==(p|0)){break b}G=u;E=E+s|0}}}while(0);E=m+p|0;if((E|0)>(o|0)){v=E;F=29;break}G=C+r|0;if((G|0)<(k|0)){z=z+1|0;C=G;m=E;D=D+(p<<2)|0}else{v=E;F=29;break}}if((F|0)==29){hg(q);i=n;return v|0}return 0}function df(b,c,d,e,f,h,j){b=b|0;c=c|0;d=d|0;e=e|0;f=+f;h=h|0;j=j|0;var k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0.0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0.0,D=0,E=0,F=0,G=0,H=0.0,I=0.0,J=0.0,K=0,L=0.0,M=0.0,N=0.0,O=0.0,P=0.0,R=0.0,S=0.0,T=0.0,U=0,V=0,W=0.0,X=0,Y=0,Z=0.0,_=0.0,$=0.0,ba=0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0,oa=0.0,pa=0.0,qa=0.0,ra=0,sa=0.0,ta=0.0;k=i;l=f;if((c|0)<1){m=0;i=k;return m|0}if((c|0)==1){g[d>>2]=+g[b+4>>2];g[e>>2]=0.0;m=1;i=k;return m|0}f=2.0/+(c+ -1|0);n=c<<2;o=gg(n)|0;p=gg(n)|0;n=ig(c,1)|0;q=0;while(1){g[p+(q<<2)>>2]=f*+(q|0)+-1.0;r=q+1|0;if((r|0)==(c|0)){s=0.0;t=0.0;u=0.0;v=0;break}else{q=r}}do{w=+g[p+(v<<2)>>2];x=+g[b+(v<<2)>>2];s=s+w*w;t=t+w*x;u=u+x;v=v+1|0}while((v|0)!=(c|0));x=+(c|0);w=u/x;y=t/s;v=~~(x*.5);q=(v|0)<5?5:v;if((j|0)>0){x=l;v=~h;r=~c;l=0.0;z=u;u=t;t=s;s=y;A=c;B=0;C=w;while(1){D=0;while(1){g[o+(D<<2)>>2]=+g[b+(D<<2)>>2]-(C+s*+g[p+(D<<2)>>2]);E=D+1|0;if((E|0)==(c|0)){F=0;G=0;H=0.0;I=0.0;break}else{D=E}}while(1){if((a[n+F|0]|0)==0){J=+g[o+(F<<2)>>2];K=G+1|0;L=H+J;M=I+J*J}else{K=G;L=H;M=I}F=F+1|0;if((F|0)==(c|0)){break}else{G=K;H=L;I=M}}if(!(K>>>0<2)){D=K+ -1|0;J=M/+(D|0)-L*L/+(aa(D,K)|0);if(J<0.0){N=0.0}else{N=+Q(+J)}}else{N=-999.0}J=x*N;O=-J;P=t;R=u;S=z;T=l;D=0;E=v;U=c;while(1){V=~((E|0)>(r|0)?E:r);if((a[n+D|0]|0)!=1){W=+g[o+(D<<2)>>2];if(WJ?(X=D-h|0,Y=(X|0)<0?0:X,X=D+h|0,(Y|0)<(((X|0)>(c|0)?c:X)|0)):0){W=P;Z=R;_=T;$=S;X=Y;Y=U;while(1){ba=n+X|0;do{if((a[ba]|0)!=1){if((X|0)>(D|0)){a[ba]=2;ca=W;da=Z;ea=$;fa=_;ga=Y;break}else{ha=+g[p+(X<<2)>>2];ia=+g[b+(X<<2)>>2];a[ba]=1;ca=W-ha*ha;da=Z-ha*ia;ea=$-ia;fa=_-ha;ga=Y+ -1|0;break}}else{ca=W;da=Z;ea=$;fa=_;ga=Y}}while(0);ba=X+1|0;if((ba|0)==(V|0)){ja=fa;ka=ca;la=da;ma=ea;na=ga;break}else{W=ca;Z=da;_=fa;$=ea;X=ba;Y=ga}}}else{ja=T;ka=P;la=R;ma=S;na=U}}else{ja=T;ka=P;la=R;ma=S;na=U+ -1|0}D=D+1|0;if((D|0)==(c|0)){break}else{P=ka;R=la;S=ma;T=ja;E=E+ -1|0;U=na}}if((na|0)>0){T=ja/ka;S=(ma-la*T)/(+(na|0)-ja*T);oa=(la-ja*S)/ka;pa=S}else{oa=s;pa=C}U=B+1|0;if((na|0)>=(q|0)&(na|0)<(A|0)&(U|0)<(j|0)){l=ja;z=ma;u=la;t=ka;s=oa;A=na;B=U;C=pa}else{qa=oa;ra=na;sa=pa;break}}}else{qa=y;ra=c;sa=w}g[d>>2]=sa-qa;sa=f*qa;g[e>>2]=sa;if(!(sa>=0.0)){ta=-sa}else{ta=sa}if(ta<.001){g[e>>2]=f*y}hg(o);hg(p);hg(n);m=ra;i=k;return m|0}function ef(a,b){a=a|0;b=b|0;return(+g[a>>2]<=+g[b>>2]?-1:1)|0}function ff(a,b,c){a=a|0;b=b|0;c=c|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0;e=i;f=a>>>16;g=a&65535;if((c|0)==1){a=(d[b]|0)+g|0;h=a>>>0>65520?a+ -65521|0:a;a=h+f|0;j=(a>>>0>65520?a+15|0:a)<<16|h;i=e;return j|0}if((b|0)==0){j=1;i=e;return j|0}if(c>>>0<16){if((c|0)==0){k=g;l=f}else{h=b;a=c;m=g;n=f;while(1){o=a+ -1|0;p=(d[h]|0)+m|0;q=p+n|0;if((o|0)==0){k=p;l=q;break}else{h=h+1|0;a=o;m=p;n=q}}}j=((l>>>0)%65521|0)<<16|(k>>>0>65520?k+ -65521|0:k);i=e;return j|0}if(c>>>0>5551){k=b;l=c;n=g;m=f;do{l=l+ -5552|0;a=k;h=n;q=347;p=m;while(1){o=(d[a]|0)+h|0;r=o+(d[a+1|0]|0)|0;s=r+(d[a+2|0]|0)|0;t=s+(d[a+3|0]|0)|0;u=t+(d[a+4|0]|0)|0;v=u+(d[a+5|0]|0)|0;w=v+(d[a+6|0]|0)|0;x=w+(d[a+7|0]|0)|0;y=x+(d[a+8|0]|0)|0;z=y+(d[a+9|0]|0)|0;A=z+(d[a+10|0]|0)|0;B=A+(d[a+11|0]|0)|0;C=B+(d[a+12|0]|0)|0;D=C+(d[a+13|0]|0)|0;E=D+(d[a+14|0]|0)|0;h=E+(d[a+15|0]|0)|0;p=o+p+r+s+t+u+v+w+x+y+z+A+B+C+D+E+h|0;q=q+ -1|0;if((q|0)==0){break}else{a=a+16|0}}k=k+5552|0;n=(h>>>0)%65521|0;m=(p>>>0)%65521|0}while(l>>>0>5551);if((l|0)!=0){if(l>>>0>15){F=l;G=k;H=n;I=m;J=15}else{K=l;L=k;M=n;N=m;J=16}}else{O=n;P=m}}else{F=c;G=b;H=g;I=f;J=15}if((J|0)==15){while(1){J=0;F=F+ -16|0;f=(d[G]|0)+H|0;g=f+(d[G+1|0]|0)|0;b=g+(d[G+2|0]|0)|0;c=b+(d[G+3|0]|0)|0;m=c+(d[G+4|0]|0)|0;n=m+(d[G+5|0]|0)|0;k=n+(d[G+6|0]|0)|0;l=k+(d[G+7|0]|0)|0;a=l+(d[G+8|0]|0)|0;q=a+(d[G+9|0]|0)|0;E=q+(d[G+10|0]|0)|0;D=E+(d[G+11|0]|0)|0;C=D+(d[G+12|0]|0)|0;B=C+(d[G+13|0]|0)|0;A=B+(d[G+14|0]|0)|0;H=A+(d[G+15|0]|0)|0;I=f+I+g+b+c+m+n+k+l+a+q+E+D+C+B+A+H|0;G=G+16|0;if(!(F>>>0>15)){break}else{J=15}}if((F|0)==0){Q=H;R=I;J=17}else{K=F;L=G;M=H;N=I;J=16}}if((J|0)==16){while(1){J=0;I=K+ -1|0;H=(d[L]|0)+M|0;G=H+N|0;if((I|0)==0){Q=H;R=G;J=17;break}else{K=I;L=L+1|0;M=H;N=G;J=16}}}if((J|0)==17){O=(Q>>>0)%65521|0;P=(R>>>0)%65521|0}j=P<<16|O;i=e;return j|0}function gf(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;f=i;if((b|0)==0){g=0;i=f;return g|0}h=~a;a:do{if((e|0)!=0){a=b;j=e;k=h;while(1){if((a&3|0)==0){break}l=c[12968+(((d[a]|0)^k&255)<<2)>>2]^k>>>8;m=j+ -1|0;if((m|0)==0){n=l;break a}else{a=a+1|0;j=m;k=l}}if(j>>>0>31){l=j;m=a;o=k;while(1){p=c[m>>2]^o;q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+4>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+8>>2];q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+12>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+16>>2];q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+20>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+24>>2];q=m+32|0;r=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+28>>2];p=c[15016+((r>>>8&255)<<2)>>2]^c[16040+((r&255)<<2)>>2]^c[13992+((r>>>16&255)<<2)>>2]^c[12968+(r>>>24<<2)>>2];r=l+ -32|0;if(r>>>0>31){l=r;m=q;o=p}else{s=r;t=q;u=p;break}}}else{s=j;t=a;u=k}if(s>>>0>3){o=s;m=t;l=u;while(1){p=m+4|0;q=c[m>>2]^l;r=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2];q=o+ -4|0;if(q>>>0>3){o=q;m=p;l=r}else{v=q;w=p;x=r;break}}}else{v=s;w=t;x=u}if((v|0)==0){n=x}else{l=w;m=v;o=x;while(1){k=c[12968+(((d[l]|0)^o&255)<<2)>>2]^o>>>8;a=m+ -1|0;if((a|0)==0){n=k;break}else{l=l+1|0;m=a;o=k}}}}else{n=h}}while(0);g=~n;i=f;return g|0}function hf(b,d,e,f,g,h,j,k){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0;l=i;if((j|0)==0){m=-6;i=l;return m|0}if(!((a[j]|0)==49&(k|0)==56)){m=-6;i=l;return m|0}if((b|0)==0){m=-2;i=l;return m|0}k=b+24|0;c[k>>2]=0;j=b+32|0;n=c[j>>2]|0;if((n|0)==0){c[j>>2]=1;c[b+40>>2]=0;o=1}else{o=n}n=b+36|0;if((c[n>>2]|0)==0){c[n>>2]=1}n=(d|0)==-1?6:d;if((f|0)<0){p=0-f|0;q=0}else{d=(f|0)>15;p=d?f+ -16|0:f;q=d?2:1}if(!((g+ -1|0)>>>0<9&(e|0)==8)){m=-2;i=l;return m|0}if((p+ -8|0)>>>0>7|n>>>0>9|h>>>0>4){m=-2;i=l;return m|0}e=(p|0)==8?9:p;p=b+40|0;d=kb[o&1](c[p>>2]|0,1,5828)|0;if((d|0)==0){m=-4;i=l;return m|0}c[b+28>>2]=d;c[d>>2]=b;c[d+24>>2]=q;c[d+28>>2]=0;c[d+48>>2]=e;q=1<>2]=q;c[d+52>>2]=q+ -1;o=g+7|0;c[d+80>>2]=o;f=1<>2]=f;c[d+84>>2]=f+ -1;c[d+88>>2]=((g+9|0)>>>0)/3|0;f=d+56|0;c[f>>2]=kb[c[j>>2]&1](c[p>>2]|0,q,2)|0;q=kb[c[j>>2]&1](c[p>>2]|0,c[e>>2]|0,2)|0;r=d+64|0;c[r>>2]=q;Eg(q|0,0,c[e>>2]<<1|0)|0;e=d+68|0;c[e>>2]=kb[c[j>>2]&1](c[p>>2]|0,c[o>>2]|0,2)|0;c[d+5824>>2]=0;o=1<>2]=o;q=kb[c[j>>2]&1](c[p>>2]|0,o,4)|0;c[d+8>>2]=q;o=c[g>>2]|0;c[d+12>>2]=o<<2;if(((c[f>>2]|0)!=0?(c[r>>2]|0)!=0:0)?!((c[e>>2]|0)==0|(q|0)==0):0){c[d+5796>>2]=q+(o>>>1<<1);c[d+5784>>2]=q+(o*3|0);c[d+132>>2]=n;c[d+136>>2]=h;a[d+36|0]=8;m=kf(b)|0;i=l;return m|0}c[d+4>>2]=666;c[k>>2]=c[27632>>2];jf(b)|0;m=-4;i=l;return m|0}function jf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;i=b;return d|0}g=c[f+4>>2]|0;switch(g|0){case 42:case 69:case 73:case 91:case 103:case 113:case 666:{break};default:{d=-2;i=b;return d|0}}h=c[f+8>>2]|0;if((h|0)==0){j=f}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);j=c[e>>2]|0}h=c[j+68>>2]|0;if((h|0)==0){k=j}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);k=c[e>>2]|0}h=c[k+64>>2]|0;if((h|0)==0){l=k}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);l=c[e>>2]|0}h=c[l+56>>2]|0;k=a+36|0;if((h|0)==0){m=a+40|0;n=l}else{l=a+40|0;mb[c[k>>2]&1](c[l>>2]|0,h);m=l;n=c[e>>2]|0}mb[c[k>>2]&1](c[m>>2]|0,n);c[e>>2]=0;d=(g|0)==113?-3:0;i=b;return d|0}function kf(a){a=a|0;var d=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;d=i;if((a|0)==0){f=-2;i=d;return f|0}g=c[a+28>>2]|0;if((g|0)==0){f=-2;i=d;return f|0}if((c[a+32>>2]|0)==0){f=-2;i=d;return f|0}if((c[a+36>>2]|0)==0){f=-2;i=d;return f|0}c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+44>>2]=2;c[g+20>>2]=0;c[g+16>>2]=c[g+8>>2];h=g+24|0;j=c[h>>2]|0;if((j|0)<0){k=0-j|0;c[h>>2]=k;l=k}else{l=j}c[g+4>>2]=(l|0)!=0?42:113;if((l|0)==2){m=gf(0,0,0)|0}else{m=ff(0,0,0)|0}c[a+48>>2]=m;c[g+40>>2]=0;Of(g);c[g+60>>2]=c[g+44>>2]<<1;m=c[g+76>>2]|0;a=c[g+68>>2]|0;b[a+(m+ -1<<1)>>1]=0;Eg(a|0,0,(m<<1)+ -2|0)|0;m=c[g+132>>2]|0;c[g+128>>2]=e[21162+(m*12|0)>>1]|0;c[g+140>>2]=e[21160+(m*12|0)>>1]|0;c[g+144>>2]=e[21164+(m*12|0)>>1]|0;c[g+124>>2]=e[21166+(m*12|0)>>1]|0;c[g+108>>2]=0;c[g+92>>2]=0;c[g+116>>2]=0;c[g+120>>2]=2;c[g+96>>2]=2;c[g+112>>2]=0;c[g+104>>2]=0;c[g+72>>2]=0;f=0;i=d;return f|0} + + + +function lf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0;g=i;if((e|0)==0){h=-2;i=g;return h|0}j=e+28|0;k=c[j>>2]|0;if((k|0)==0|f>>>0>5){h=-2;i=g;return h|0}l=e+12|0;do{if((c[l>>2]|0)!=0){if((c[e>>2]|0)==0?(c[e+4>>2]|0)!=0:0){break}m=k+4|0;n=c[m>>2]|0;o=(f|0)==4;if((n|0)!=666|o){p=e+16|0;if((c[p>>2]|0)==0){c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}c[k>>2]=e;q=k+40|0;r=c[q>>2]|0;c[q>>2]=f;do{if((n|0)==42){if((c[k+24>>2]|0)!=2){s=(c[k+48>>2]<<12)+ -30720|0;if((c[k+136>>2]|0)<=1?(t=c[k+132>>2]|0,(t|0)>=2):0){if((t|0)<6){u=64}else{u=(t|0)==6?128:192}}else{u=0}t=u|s;s=k+108|0;v=(c[s>>2]|0)==0?t:t|32;c[m>>2]=113;t=k+20|0;w=c[t>>2]|0;c[t>>2]=w+1;x=k+8|0;a[(c[x>>2]|0)+w|0]=v>>>8;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=(v|((v>>>0)%31|0))^31;v=e+48|0;if((c[s>>2]|0)!=0){s=c[v>>2]|0;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>24;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>16;s=c[v>>2]|0;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>8;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s}c[v>>2]=ff(0,0,0)|0;y=c[m>>2]|0;z=32;break}v=e+48|0;c[v>>2]=gf(0,0,0)|0;s=k+20|0;w=c[s>>2]|0;c[s>>2]=w+1;x=k+8|0;a[(c[x>>2]|0)+w|0]=31;w=c[s>>2]|0;c[s>>2]=w+1;a[(c[x>>2]|0)+w|0]=-117;w=c[s>>2]|0;c[s>>2]=w+1;a[(c[x>>2]|0)+w|0]=8;w=k+28|0;t=c[w>>2]|0;if((t|0)==0){A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[k+132>>2]|0;if((A|0)!=9){if((c[k+136>>2]|0)>1){B=4}else{B=(A|0)<2?4:0}}else{B=2}A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=B;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=3;c[m>>2]=113;break}A=(((c[t+44>>2]|0)!=0?2:0)|(c[t>>2]|0)!=0|((c[t+16>>2]|0)==0?0:4)|((c[t+28>>2]|0)==0?0:8)|((c[t+36>>2]|0)==0?0:16))&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[(c[w>>2]|0)+4>>2]&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>8&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>16&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>24&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[k+132>>2]|0;if((A|0)!=9){if((c[k+136>>2]|0)>1){C=4}else{C=(A|0)<2?4:0}}else{C=2}A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=C;A=c[(c[w>>2]|0)+12>>2]&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[w>>2]|0;if((c[A+16>>2]|0)==0){D=A}else{t=c[A+20>>2]&255;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=t;t=(c[(c[w>>2]|0)+20>>2]|0)>>>8&255;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=t;D=c[w>>2]|0}if((c[D+44>>2]|0)!=0){c[v>>2]=gf(c[v>>2]|0,c[x>>2]|0,c[s>>2]|0)|0}c[k+32>>2]=0;c[m>>2]=69;E=w;z=34}else{y=n;z=32}}while(0);if((z|0)==32){if((y|0)==69){E=k+28|0;z=34}else{F=y;z=55}}do{if((z|0)==34){n=c[E>>2]|0;if((c[n+16>>2]|0)==0){c[m>>2]=73;G=n;z=57;break}w=k+20|0;s=c[w>>2]|0;x=k+32|0;v=c[x>>2]|0;a:do{if(v>>>0<(c[n+20>>2]&65535)>>>0){t=k+12|0;A=e+48|0;H=k+8|0;I=e+20|0;J=v;K=s;L=n;M=s;while(1){if((K|0)==(c[t>>2]|0)){if((c[L+44>>2]|0)!=0&K>>>0>M>>>0){c[A>>2]=gf(c[A>>2]|0,(c[H>>2]|0)+M|0,K-M|0)|0}N=c[j>>2]|0;O=c[N+20>>2]|0;P=c[p>>2]|0;Q=O>>>0>P>>>0?P:O;if((Q|0)!=0?(Kg(c[l>>2]|0,c[N+16>>2]|0,Q|0)|0,c[l>>2]=(c[l>>2]|0)+Q,N=(c[j>>2]|0)+16|0,c[N>>2]=(c[N>>2]|0)+Q,c[I>>2]=(c[I>>2]|0)+Q,c[p>>2]=(c[p>>2]|0)-Q,N=c[j>>2]|0,O=N+20|0,P=c[O>>2]|0,c[O>>2]=P-Q,(P|0)==(Q|0)):0){c[N+16>>2]=c[N+8>>2]}R=c[w>>2]|0;if((R|0)==(c[t>>2]|0)){break}S=c[E>>2]|0;T=c[x>>2]|0;U=R;V=R}else{S=L;T=J;U=K;V=M}N=a[(c[S+16>>2]|0)+T|0]|0;c[w>>2]=U+1;a[(c[H>>2]|0)+U|0]=N;N=(c[x>>2]|0)+1|0;c[x>>2]=N;Q=c[E>>2]|0;if(!(N>>>0<(c[Q+20>>2]&65535)>>>0)){W=Q;X=V;break a}J=N;K=c[w>>2]|0;L=Q;M=V}W=c[E>>2]|0;X=R}else{W=n;X=s}}while(0);if((c[W+44>>2]|0)!=0?(s=c[w>>2]|0,s>>>0>X>>>0):0){n=e+48|0;c[n>>2]=gf(c[n>>2]|0,(c[k+8>>2]|0)+X|0,s-X|0)|0;Y=c[E>>2]|0}else{Y=W}if((c[x>>2]|0)==(c[Y+20>>2]|0)){c[x>>2]=0;c[m>>2]=73;G=Y;z=57;break}else{F=c[m>>2]|0;z=55;break}}}while(0);if((z|0)==55){if((F|0)==73){G=c[k+28>>2]|0;z=57}else{Z=F;z=76}}do{if((z|0)==57){s=k+28|0;if((c[G+28>>2]|0)==0){c[m>>2]=91;_=s;z=78;break}n=k+20|0;v=c[n>>2]|0;M=k+12|0;L=e+48|0;K=k+8|0;J=e+20|0;H=k+32|0;t=v;I=v;while(1){if((t|0)==(c[M>>2]|0)){if((c[(c[s>>2]|0)+44>>2]|0)!=0&t>>>0>I>>>0){c[L>>2]=gf(c[L>>2]|0,(c[K>>2]|0)+I|0,t-I|0)|0}v=c[j>>2]|0;A=c[v+20>>2]|0;Q=c[p>>2]|0;N=A>>>0>Q>>>0?Q:A;if((N|0)!=0?(Kg(c[l>>2]|0,c[v+16>>2]|0,N|0)|0,c[l>>2]=(c[l>>2]|0)+N,v=(c[j>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+N,c[J>>2]=(c[J>>2]|0)+N,c[p>>2]=(c[p>>2]|0)-N,v=c[j>>2]|0,A=v+20|0,Q=c[A>>2]|0,c[A>>2]=Q-N,(Q|0)==(N|0)):0){c[v+16>>2]=c[v+8>>2]}v=c[n>>2]|0;if((v|0)==(c[M>>2]|0)){$=v;aa=1;break}else{ba=v;ca=v}}else{ba=t;ca=I}v=c[H>>2]|0;c[H>>2]=v+1;da=a[(c[(c[s>>2]|0)+28>>2]|0)+v|0]|0;c[n>>2]=ba+1;a[(c[K>>2]|0)+ba|0]=da;if(da<<24>>24==0){z=68;break}t=c[n>>2]|0;I=ca}if((z|0)==68){$=ca;aa=da&255}if((c[(c[s>>2]|0)+44>>2]|0)!=0?(I=c[n>>2]|0,I>>>0>$>>>0):0){c[L>>2]=gf(c[L>>2]|0,(c[K>>2]|0)+$|0,I-$|0)|0}if((aa|0)==0){c[H>>2]=0;c[m>>2]=91;_=s;z=78;break}else{Z=c[m>>2]|0;z=76;break}}}while(0);if((z|0)==76){if((Z|0)==91){_=k+28|0;z=78}else{ea=Z;z=97}}do{if((z|0)==78){if((c[(c[_>>2]|0)+36>>2]|0)==0){c[m>>2]=103;fa=_;z=99;break}I=k+20|0;t=c[I>>2]|0;M=k+12|0;J=e+48|0;x=k+8|0;w=e+20|0;v=k+32|0;N=t;Q=t;while(1){if((N|0)==(c[M>>2]|0)){if((c[(c[_>>2]|0)+44>>2]|0)!=0&N>>>0>Q>>>0){c[J>>2]=gf(c[J>>2]|0,(c[x>>2]|0)+Q|0,N-Q|0)|0}t=c[j>>2]|0;A=c[t+20>>2]|0;P=c[p>>2]|0;O=A>>>0>P>>>0?P:A;if((O|0)!=0?(Kg(c[l>>2]|0,c[t+16>>2]|0,O|0)|0,c[l>>2]=(c[l>>2]|0)+O,t=(c[j>>2]|0)+16|0,c[t>>2]=(c[t>>2]|0)+O,c[w>>2]=(c[w>>2]|0)+O,c[p>>2]=(c[p>>2]|0)-O,t=c[j>>2]|0,A=t+20|0,P=c[A>>2]|0,c[A>>2]=P-O,(P|0)==(O|0)):0){c[t+16>>2]=c[t+8>>2]}t=c[I>>2]|0;if((t|0)==(c[M>>2]|0)){ga=t;ha=1;break}else{ia=t;ja=t}}else{ia=N;ja=Q}t=c[v>>2]|0;c[v>>2]=t+1;ka=a[(c[(c[_>>2]|0)+36>>2]|0)+t|0]|0;c[I>>2]=ia+1;a[(c[x>>2]|0)+ia|0]=ka;if(ka<<24>>24==0){z=89;break}N=c[I>>2]|0;Q=ja}if((z|0)==89){ga=ja;ha=ka&255}if((c[(c[_>>2]|0)+44>>2]|0)!=0?(Q=c[I>>2]|0,Q>>>0>ga>>>0):0){c[J>>2]=gf(c[J>>2]|0,(c[x>>2]|0)+ga|0,Q-ga|0)|0}if((ha|0)==0){c[m>>2]=103;fa=_;z=99;break}else{ea=c[m>>2]|0;z=97;break}}}while(0);if((z|0)==97?(ea|0)==103:0){fa=k+28|0;z=99}do{if((z|0)==99){if((c[(c[fa>>2]|0)+44>>2]|0)==0){c[m>>2]=113;break}Q=k+20|0;N=k+12|0;if((((c[Q>>2]|0)+2|0)>>>0>(c[N>>2]|0)>>>0?(v=c[j>>2]|0,M=c[v+20>>2]|0,w=c[p>>2]|0,s=M>>>0>w>>>0?w:M,(s|0)!=0):0)?(Kg(c[l>>2]|0,c[v+16>>2]|0,s|0)|0,c[l>>2]=(c[l>>2]|0)+s,v=(c[j>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+s,v=e+20|0,c[v>>2]=(c[v>>2]|0)+s,c[p>>2]=(c[p>>2]|0)-s,v=c[j>>2]|0,M=v+20|0,w=c[M>>2]|0,c[M>>2]=w-s,(w|0)==(s|0)):0){c[v+16>>2]=c[v+8>>2]}v=c[Q>>2]|0;if(!((v+2|0)>>>0>(c[N>>2]|0)>>>0)){N=e+48|0;s=c[N>>2]&255;c[Q>>2]=v+1;w=k+8|0;a[(c[w>>2]|0)+v|0]=s;s=(c[N>>2]|0)>>>8&255;v=c[Q>>2]|0;c[Q>>2]=v+1;a[(c[w>>2]|0)+v|0]=s;c[N>>2]=gf(0,0,0)|0;c[m>>2]=113}}}while(0);N=k+20|0;if((c[N>>2]|0)==0){if((c[e+4>>2]|0)==0?(r|0)>=(f|0)&(f|0)!=4:0){c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}}else{s=c[j>>2]|0;v=c[s+20>>2]|0;w=c[p>>2]|0;Q=v>>>0>w>>>0?w:v;if((Q|0)==0){la=w}else{Kg(c[l>>2]|0,c[s+16>>2]|0,Q|0)|0;c[l>>2]=(c[l>>2]|0)+Q;s=(c[j>>2]|0)+16|0;c[s>>2]=(c[s>>2]|0)+Q;s=e+20|0;c[s>>2]=(c[s>>2]|0)+Q;c[p>>2]=(c[p>>2]|0)-Q;s=c[j>>2]|0;w=s+20|0;v=c[w>>2]|0;c[w>>2]=v-Q;if((v|0)==(Q|0)){c[s+16>>2]=c[s+8>>2]}la=c[p>>2]|0}if((la|0)==0){c[q>>2]=-1;h=0;i=g;return h|0}}s=(c[m>>2]|0)==666;Q=(c[e+4>>2]|0)==0;if(s){if(Q){z=121}else{c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}}else{if(Q){z=121}else{z=124}}do{if((z|0)==121){if((c[k+116>>2]|0)==0){if((f|0)!=0){if(s){break}else{z=124;break}}else{h=0;i=g;return h|0}}else{z=124}}}while(0);do{if((z|0)==124){s=c[k+136>>2]|0;b:do{if((s|0)==3){r=k+116|0;Q=(f|0)==0;v=k+96|0;w=k+108|0;M=k+5792|0;H=k+5796|0;K=k+5784|0;L=k+(d[24760]<<2)+2440|0;n=k+5788|0;t=k+56|0;O=k+92|0;while(1){P=c[r>>2]|0;if(P>>>0<258){mf(k);A=c[r>>2]|0;if(A>>>0<258&Q){break b}if((A|0)==0){break}c[v>>2]=0;if(A>>>0>2){ma=A;z=151}else{na=c[w>>2]|0;z=166}}else{c[v>>2]=0;ma=P;z=151}if((z|0)==151){z=0;P=c[w>>2]|0;if((P|0)!=0){A=c[t>>2]|0;oa=a[A+(P+ -1)|0]|0;if((oa<<24>>24==(a[A+P|0]|0)?oa<<24>>24==(a[A+(P+1)|0]|0):0)?(pa=A+(P+2)|0,oa<<24>>24==(a[pa]|0)):0){qa=A+(P+258)|0;A=pa;while(1){pa=A+1|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+2|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+3|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+4|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+5|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+6|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+7|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+8|0;if(oa<<24>>24==(a[pa]|0)&pa>>>0>>0){A=pa}else{ra=pa;break}}A=ra-qa+258|0;oa=A>>>0>ma>>>0?ma:A;c[v>>2]=oa;if(oa>>>0>2){A=oa+253|0;oa=c[M>>2]|0;b[(c[H>>2]|0)+(oa<<1)>>1]=1;c[M>>2]=oa+1;a[(c[K>>2]|0)+oa|0]=A;oa=k+((d[25272+(A&255)|0]|256)+1<<2)+148|0;b[oa>>1]=(b[oa>>1]|0)+1<<16>>16;b[L>>1]=(b[L>>1]|0)+1<<16>>16;oa=(c[M>>2]|0)==((c[n>>2]|0)+ -1|0)|0;A=c[v>>2]|0;c[r>>2]=(c[r>>2]|0)-A;pa=(c[w>>2]|0)+A|0;c[w>>2]=pa;c[v>>2]=0;sa=pa;ta=oa}else{na=P;z=166}}else{na=P;z=166}}else{na=0;z=166}}if((z|0)==166){z=0;oa=a[(c[t>>2]|0)+na|0]|0;pa=c[M>>2]|0;b[(c[H>>2]|0)+(pa<<1)>>1]=0;c[M>>2]=pa+1;a[(c[K>>2]|0)+pa|0]=oa;pa=k+((oa&255)<<2)+148|0;b[pa>>1]=(b[pa>>1]|0)+1<<16>>16;pa=(c[M>>2]|0)==((c[n>>2]|0)+ -1|0)|0;c[r>>2]=(c[r>>2]|0)+ -1;oa=(c[w>>2]|0)+1|0;c[w>>2]=oa;sa=oa;ta=pa}if((ta|0)==0){continue}pa=c[O>>2]|0;if((pa|0)>-1){ua=(c[t>>2]|0)+pa|0}else{ua=0}Sf(k,ua,sa-pa|0,0);c[O>>2]=c[w>>2];pa=c[k>>2]|0;oa=pa+28|0;A=c[oa>>2]|0;va=c[A+20>>2]|0;wa=pa+16|0;xa=c[wa>>2]|0;ya=va>>>0>xa>>>0?xa:va;if((ya|0)!=0?(va=pa+12|0,Kg(c[va>>2]|0,c[A+16>>2]|0,ya|0)|0,c[va>>2]=(c[va>>2]|0)+ya,va=(c[oa>>2]|0)+16|0,c[va>>2]=(c[va>>2]|0)+ya,va=pa+20|0,c[va>>2]=(c[va>>2]|0)+ya,c[wa>>2]=(c[wa>>2]|0)-ya,wa=c[oa>>2]|0,oa=wa+20|0,va=c[oa>>2]|0,c[oa>>2]=va-ya,(va|0)==(ya|0)):0){c[wa+16>>2]=c[wa+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){break b}}r=c[O>>2]|0;if((r|0)>-1){za=(c[t>>2]|0)+r|0}else{za=0}Sf(k,za,(c[w>>2]|0)-r|0,o&1);c[O>>2]=c[w>>2];r=c[k>>2]|0;n=r+28|0;M=c[n>>2]|0;K=c[M+20>>2]|0;H=r+16|0;v=c[H>>2]|0;L=K>>>0>v>>>0?v:K;if((L|0)!=0?(K=r+12|0,Kg(c[K>>2]|0,c[M+16>>2]|0,L|0)|0,c[K>>2]=(c[K>>2]|0)+L,K=(c[n>>2]|0)+16|0,c[K>>2]=(c[K>>2]|0)+L,K=r+20|0,c[K>>2]=(c[K>>2]|0)+L,c[H>>2]=(c[H>>2]|0)-L,H=c[n>>2]|0,n=H+20|0,K=c[n>>2]|0,c[n>>2]=K-L,(K|0)==(L|0)):0){c[H+16>>2]=c[H+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){Aa=o?2:0;z=183;break}else{Aa=o?3:1;z=183;break}}else if((s|0)==2){H=k+116|0;L=k+96|0;K=k+108|0;n=k+56|0;r=k+5792|0;M=k+5796|0;v=k+5784|0;Q=k+5788|0;wa=k+92|0;while(1){if((c[H>>2]|0)==0?(mf(k),(c[H>>2]|0)==0):0){break}c[L>>2]=0;ya=a[(c[n>>2]|0)+(c[K>>2]|0)|0]|0;va=c[r>>2]|0;b[(c[M>>2]|0)+(va<<1)>>1]=0;c[r>>2]=va+1;a[(c[v>>2]|0)+va|0]=ya;va=k+((ya&255)<<2)+148|0;b[va>>1]=(b[va>>1]|0)+1<<16>>16;va=(c[r>>2]|0)==((c[Q>>2]|0)+ -1|0);c[H>>2]=(c[H>>2]|0)+ -1;ya=(c[K>>2]|0)+1|0;c[K>>2]=ya;if(!va){continue}va=c[wa>>2]|0;if((va|0)>-1){Ba=(c[n>>2]|0)+va|0}else{Ba=0}Sf(k,Ba,ya-va|0,0);c[wa>>2]=c[K>>2];va=c[k>>2]|0;ya=va+28|0;oa=c[ya>>2]|0;pa=c[oa+20>>2]|0;A=va+16|0;xa=c[A>>2]|0;Ca=pa>>>0>xa>>>0?xa:pa;if((Ca|0)!=0?(pa=va+12|0,Kg(c[pa>>2]|0,c[oa+16>>2]|0,Ca|0)|0,c[pa>>2]=(c[pa>>2]|0)+Ca,pa=(c[ya>>2]|0)+16|0,c[pa>>2]=(c[pa>>2]|0)+Ca,pa=va+20|0,c[pa>>2]=(c[pa>>2]|0)+Ca,c[A>>2]=(c[A>>2]|0)-Ca,A=c[ya>>2]|0,ya=A+20|0,pa=c[ya>>2]|0,c[ya>>2]=pa-Ca,(pa|0)==(Ca|0)):0){c[A+16>>2]=c[A+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){break b}}if((f|0)!=0){H=c[wa>>2]|0;if((H|0)>-1){Da=(c[n>>2]|0)+H|0}else{Da=0}Sf(k,Da,(c[K>>2]|0)-H|0,o&1);c[wa>>2]=c[K>>2];H=c[k>>2]|0;Q=H+28|0;r=c[Q>>2]|0;v=c[r+20>>2]|0;M=H+16|0;L=c[M>>2]|0;w=v>>>0>L>>>0?L:v;if((w|0)!=0?(v=H+12|0,Kg(c[v>>2]|0,c[r+16>>2]|0,w|0)|0,c[v>>2]=(c[v>>2]|0)+w,v=(c[Q>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+w,v=H+20|0,c[v>>2]=(c[v>>2]|0)+w,c[M>>2]=(c[M>>2]|0)-w,M=c[Q>>2]|0,Q=M+20|0,v=c[Q>>2]|0,c[Q>>2]=v-w,(v|0)==(w|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){Aa=o?2:0;z=183;break}else{Aa=o?3:1;z=183;break}}}else{Aa=nb[c[21168+((c[k+132>>2]|0)*12|0)>>2]&7](k,f)|0;z=183}}while(0);if((z|0)==183){if((Aa&-2|0)==2){c[m>>2]=666}if((Aa&-3|0)!=0){if((Aa|0)!=1){break}if((f|0)==1){Rf(k)}else if(((f|0)!=5?(Qf(k,0,0,0),(f|0)==3):0)?(s=c[k+76>>2]|0,x=c[k+68>>2]|0,b[x+(s+ -1<<1)>>1]=0,Eg(x|0,0,(s<<1)+ -2|0)|0,(c[k+116>>2]|0)==0):0){c[k+108>>2]=0;c[k+92>>2]=0}s=c[j>>2]|0;x=c[s+20>>2]|0;J=c[p>>2]|0;I=x>>>0>J>>>0?J:x;if((I|0)==0){Ea=J}else{Kg(c[l>>2]|0,c[s+16>>2]|0,I|0)|0;c[l>>2]=(c[l>>2]|0)+I;s=(c[j>>2]|0)+16|0;c[s>>2]=(c[s>>2]|0)+I;s=e+20|0;c[s>>2]=(c[s>>2]|0)+I;c[p>>2]=(c[p>>2]|0)-I;s=c[j>>2]|0;J=s+20|0;x=c[J>>2]|0;c[J>>2]=x-I;if((x|0)==(I|0)){c[s+16>>2]=c[s+8>>2]}Ea=c[p>>2]|0}if((Ea|0)!=0){break}c[q>>2]=-1;h=0;i=g;return h|0}}if((c[p>>2]|0)!=0){h=0;i=g;return h|0}c[q>>2]=-1;h=0;i=g;return h|0}}while(0);if(!o){h=0;i=g;return h|0}q=k+24|0;m=c[q>>2]|0;if((m|0)<1){h=1;i=g;return h|0}s=e+48|0;I=c[s>>2]|0;if((m|0)==2){m=c[N>>2]|0;c[N>>2]=m+1;x=k+8|0;a[(c[x>>2]|0)+m|0]=I;m=(c[s>>2]|0)>>>8&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=(c[s>>2]|0)>>>16&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=(c[s>>2]|0)>>>24&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=e+8|0;J=c[m>>2]&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>8&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>16&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>24&255;m=c[N>>2]|0;c[N>>2]=m+1;a[(c[x>>2]|0)+m|0]=J}else{J=c[N>>2]|0;c[N>>2]=J+1;m=k+8|0;a[(c[m>>2]|0)+J|0]=I>>>24;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[m>>2]|0)+J|0]=I>>>16;I=c[s>>2]|0;s=c[N>>2]|0;c[N>>2]=s+1;a[(c[m>>2]|0)+s|0]=I>>>8;s=c[N>>2]|0;c[N>>2]=s+1;a[(c[m>>2]|0)+s|0]=I}I=c[j>>2]|0;s=c[I+20>>2]|0;m=c[p>>2]|0;J=s>>>0>m>>>0?m:s;if((J|0)!=0?(Kg(c[l>>2]|0,c[I+16>>2]|0,J|0)|0,c[l>>2]=(c[l>>2]|0)+J,I=(c[j>>2]|0)+16|0,c[I>>2]=(c[I>>2]|0)+J,I=e+20|0,c[I>>2]=(c[I>>2]|0)+J,c[p>>2]=(c[p>>2]|0)-J,I=c[j>>2]|0,s=I+20|0,m=c[s>>2]|0,c[s>>2]=m-J,(m|0)==(J|0)):0){c[I+16>>2]=c[I+8>>2]}I=c[q>>2]|0;if((I|0)>0){c[q>>2]=0-I}h=(c[N>>2]|0)==0|0;i=g;return h|0}}}while(0);c[e+24>>2]=c[27624>>2];h=-2;i=g;return h|0}function mf(a){a=a|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;f=i;g=a+44|0;h=c[g>>2]|0;j=a+60|0;k=a+116|0;l=a+108|0;m=h+ -262|0;n=a+56|0;o=a+72|0;p=a+88|0;q=a+84|0;r=a+112|0;s=a+92|0;t=a+76|0;u=a+68|0;v=a+64|0;w=c[k>>2]|0;x=h;while(1){y=c[l>>2]|0;z=(c[j>>2]|0)-w-y|0;if(y>>>0<(m+x|0)>>>0){A=y;B=z}else{y=c[n>>2]|0;Kg(y|0,y+h|0,h|0)|0;c[r>>2]=(c[r>>2]|0)-h;y=(c[l>>2]|0)-h|0;c[l>>2]=y;c[s>>2]=(c[s>>2]|0)-h;C=c[t>>2]|0;D=C;E=(c[u>>2]|0)+(C<<1)|0;do{E=E+ -2|0;C=e[E>>1]|0;if(C>>>0>>0){F=0}else{F=C-h&65535}b[E>>1]=F;D=D+ -1|0}while((D|0)!=0);D=h;E=(c[v>>2]|0)+(h<<1)|0;do{E=E+ -2|0;C=e[E>>1]|0;if(C>>>0>>0){G=0}else{G=C-h&65535}b[E>>1]=G;D=D+ -1|0}while((D|0)!=0);A=y;B=z+h|0}D=c[a>>2]|0;E=D+4|0;C=c[E>>2]|0;if((C|0)==0){H=28;break}I=c[k>>2]|0;J=(c[n>>2]|0)+(I+A)|0;K=C>>>0>B>>>0?B:C;if((K|0)==0){L=0;M=I}else{c[E>>2]=C-K;C=c[(c[D+28>>2]|0)+24>>2]|0;if((C|0)==2){E=D+48|0;c[E>>2]=gf(c[E>>2]|0,c[D>>2]|0,K)|0;N=D}else if((C|0)==1){C=D+48|0;c[C>>2]=ff(c[C>>2]|0,c[D>>2]|0,K)|0;N=D}else{N=D}Kg(J|0,c[N>>2]|0,K|0)|0;c[N>>2]=(c[N>>2]|0)+K;J=D+8|0;c[J>>2]=(c[J>>2]|0)+K;L=K;M=c[k>>2]|0}O=M+L|0;c[k>>2]=O;if(O>>>0>2?(K=c[l>>2]|0,J=c[n>>2]|0,D=d[J+K|0]|0,c[o>>2]=D,c[o>>2]=((d[J+(K+1)|0]|0)^D<>2])&c[q>>2],!(O>>>0<262)):0){break}if((c[(c[a>>2]|0)+4>>2]|0)==0){break}w=O;x=c[g>>2]|0}if((H|0)==28){i=f;return}H=a+5824|0;a=c[H>>2]|0;g=c[j>>2]|0;if(!(a>>>0>>0)){i=f;return}j=O+(c[l>>2]|0)|0;if(a>>>0>>0){l=g-j|0;O=l>>>0>258?258:l;Eg((c[n>>2]|0)+j|0,0,O|0)|0;c[H>>2]=O+j;i=f;return}O=j+258|0;if(!(a>>>0>>0)){i=f;return}j=O-a|0;O=g-a|0;g=j>>>0>O>>>0?O:j;Eg((c[n>>2]|0)+a|0,0,g|0)|0;c[H>>2]=(c[H>>2]|0)+g;i=f;return}function nf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;d=i;e=(c[a+12>>2]|0)+ -5|0;f=e>>>0<65535?e:65535;e=a+116|0;g=a+108|0;h=a+92|0;j=a+44|0;k=a+56|0;while(1){l=c[e>>2]|0;if(l>>>0<2){mf(a);m=c[e>>2]|0;if((m|b|0)==0){n=0;o=28;break}if((m|0)==0){o=20;break}else{p=m}}else{p=l}l=(c[g>>2]|0)+p|0;c[g>>2]=l;c[e>>2]=0;m=c[h>>2]|0;q=m+f|0;if((l|0)!=0&l>>>0>>0){r=l;s=m}else{c[e>>2]=l-q;c[g>>2]=q;if((m|0)>-1){t=(c[k>>2]|0)+m|0}else{t=0}Sf(a,t,f,0);c[h>>2]=c[g>>2];m=c[a>>2]|0;q=m+28|0;l=c[q>>2]|0;u=c[l+20>>2]|0;v=m+16|0;w=c[v>>2]|0;x=u>>>0>w>>>0?w:u;if((x|0)!=0?(u=m+12|0,Kg(c[u>>2]|0,c[l+16>>2]|0,x|0)|0,c[u>>2]=(c[u>>2]|0)+x,u=(c[q>>2]|0)+16|0,c[u>>2]=(c[u>>2]|0)+x,u=m+20|0,c[u>>2]=(c[u>>2]|0)+x,c[v>>2]=(c[v>>2]|0)-x,v=c[q>>2]|0,q=v+20|0,u=c[q>>2]|0,c[q>>2]=u-x,(u|0)==(x|0)):0){c[v+16>>2]=c[v+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=0;o=28;break}r=c[g>>2]|0;s=c[h>>2]|0}v=r-s|0;if(v>>>0<((c[j>>2]|0)+ -262|0)>>>0){continue}if((s|0)>-1){y=(c[k>>2]|0)+s|0}else{y=0}Sf(a,y,v,0);c[h>>2]=c[g>>2];v=c[a>>2]|0;x=v+28|0;u=c[x>>2]|0;q=c[u+20>>2]|0;m=v+16|0;l=c[m>>2]|0;w=q>>>0>l>>>0?l:q;if((w|0)!=0?(q=v+12|0,Kg(c[q>>2]|0,c[u+16>>2]|0,w|0)|0,c[q>>2]=(c[q>>2]|0)+w,q=(c[x>>2]|0)+16|0,c[q>>2]=(c[q>>2]|0)+w,q=v+20|0,c[q>>2]=(c[q>>2]|0)+w,c[m>>2]=(c[m>>2]|0)-w,m=c[x>>2]|0,x=m+20|0,q=c[x>>2]|0,c[x>>2]=q-w,(q|0)==(w|0)):0){c[m+16>>2]=c[m+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=0;o=28;break}}if((o|0)==20){y=c[h>>2]|0;if((y|0)>-1){z=(c[k>>2]|0)+y|0}else{z=0}k=(b|0)==4;Sf(a,z,(c[g>>2]|0)-y|0,k&1);c[h>>2]=c[g>>2];g=c[a>>2]|0;h=g+28|0;y=c[h>>2]|0;z=c[y+20>>2]|0;b=g+16|0;s=c[b>>2]|0;j=z>>>0>s>>>0?s:z;if((j|0)!=0?(z=g+12|0,Kg(c[z>>2]|0,c[y+16>>2]|0,j|0)|0,c[z>>2]=(c[z>>2]|0)+j,z=(c[h>>2]|0)+16|0,c[z>>2]=(c[z>>2]|0)+j,z=g+20|0,c[z>>2]=(c[z>>2]|0)+j,c[b>>2]=(c[b>>2]|0)-j,b=c[h>>2]|0,h=b+20|0,z=c[h>>2]|0,c[h>>2]=z-j,(z|0)==(j|0)):0){c[b+16>>2]=c[b+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=k?2:0;i=d;return n|0}else{n=k?3:1;i=d;return n|0}}else if((o|0)==28){i=d;return n|0}return 0}function of(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0;g=i;h=e+116|0;j=(f|0)==0;k=e+72|0;l=e+88|0;m=e+108|0;n=e+56|0;o=e+84|0;p=e+68|0;q=e+52|0;r=e+64|0;s=e+44|0;t=e+96|0;u=e+112|0;v=e+5792|0;w=e+5796|0;x=e+5784|0;y=e+5788|0;z=e+128|0;A=e+92|0;while(1){if((c[h>>2]|0)>>>0<262){mf(e);B=c[h>>2]|0;if(B>>>0<262&j){C=0;D=34;break}if((B|0)==0){D=26;break}if(!(B>>>0>2)){D=9}else{D=6}}else{D=6}if((D|0)==6){D=0;B=c[m>>2]|0;E=((d[(c[n>>2]|0)+(B+2)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=E;F=(c[p>>2]|0)+(E<<1)|0;E=b[F>>1]|0;b[(c[r>>2]|0)+((c[q>>2]&B)<<1)>>1]=E;G=E&65535;b[F>>1]=B;if(!(E<<16>>16==0)?!((B-G|0)>>>0>((c[s>>2]|0)+ -262|0)>>>0):0){B=qf(e,G)|0;c[t>>2]=B;H=B}else{D=9}}if((D|0)==9){D=0;H=c[t>>2]|0}do{if(H>>>0>2){B=H+253|0;G=(c[m>>2]|0)-(c[u>>2]|0)|0;E=c[v>>2]|0;b[(c[w>>2]|0)+(E<<1)>>1]=G;c[v>>2]=E+1;a[(c[x>>2]|0)+E|0]=B;E=e+((d[25272+(B&255)|0]|0|256)+1<<2)+148|0;b[E>>1]=(b[E>>1]|0)+1<<16>>16;E=G+65535&65535;if(E>>>0<256){I=E}else{I=(E>>>7)+256|0}E=e+((d[24760+I|0]|0)<<2)+2440|0;b[E>>1]=(b[E>>1]|0)+1<<16>>16;E=(c[v>>2]|0)==((c[y>>2]|0)+ -1|0)|0;G=c[t>>2]|0;B=(c[h>>2]|0)-G|0;c[h>>2]=B;if(!(G>>>0<=(c[z>>2]|0)>>>0&B>>>0>2)){B=(c[m>>2]|0)+G|0;c[m>>2]=B;c[t>>2]=0;F=c[n>>2]|0;J=d[F+B|0]|0;c[k>>2]=J;c[k>>2]=((d[F+(B+1)|0]|0)^J<>2])&c[o>>2];K=B;L=E;break}B=G+ -1|0;c[t>>2]=B;G=c[l>>2]|0;J=c[n>>2]|0;F=c[o>>2]|0;M=c[p>>2]|0;N=c[q>>2]|0;O=c[r>>2]|0;P=B;B=c[m>>2]|0;Q=c[k>>2]|0;while(1){R=B+1|0;c[m>>2]=R;Q=((d[J+(B+3)|0]|0)^Q<>2]=Q;S=M+(Q<<1)|0;b[O+((N&R)<<1)>>1]=b[S>>1]|0;b[S>>1]=R;P=P+ -1|0;c[t>>2]=P;if((P|0)==0){break}else{B=R}}P=B+2|0;c[m>>2]=P;K=P;L=E}else{P=a[(c[n>>2]|0)+(c[m>>2]|0)|0]|0;N=c[v>>2]|0;b[(c[w>>2]|0)+(N<<1)>>1]=0;c[v>>2]=N+1;a[(c[x>>2]|0)+N|0]=P;N=e+((P&255)<<2)+148|0;b[N>>1]=(b[N>>1]|0)+1<<16>>16;N=(c[v>>2]|0)==((c[y>>2]|0)+ -1|0)|0;c[h>>2]=(c[h>>2]|0)+ -1;P=(c[m>>2]|0)+1|0;c[m>>2]=P;K=P;L=N}}while(0);if((L|0)==0){continue}N=c[A>>2]|0;if((N|0)>-1){T=(c[n>>2]|0)+N|0}else{T=0}Sf(e,T,K-N|0,0);c[A>>2]=c[m>>2];N=c[e>>2]|0;P=N+28|0;O=c[P>>2]|0;Q=c[O+20>>2]|0;M=N+16|0;F=c[M>>2]|0;G=Q>>>0>F>>>0?F:Q;if((G|0)!=0?(Q=N+12|0,Kg(c[Q>>2]|0,c[O+16>>2]|0,G|0)|0,c[Q>>2]=(c[Q>>2]|0)+G,Q=(c[P>>2]|0)+16|0,c[Q>>2]=(c[Q>>2]|0)+G,Q=N+20|0,c[Q>>2]=(c[Q>>2]|0)+G,c[M>>2]=(c[M>>2]|0)-G,M=c[P>>2]|0,P=M+20|0,Q=c[P>>2]|0,c[P>>2]=Q-G,(Q|0)==(G|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){C=0;D=34;break}}if((D|0)==26){K=c[A>>2]|0;if((K|0)>-1){U=(c[n>>2]|0)+K|0}else{U=0}n=(f|0)==4;Sf(e,U,(c[m>>2]|0)-K|0,n&1);c[A>>2]=c[m>>2];m=c[e>>2]|0;A=m+28|0;K=c[A>>2]|0;U=c[K+20>>2]|0;f=m+16|0;T=c[f>>2]|0;L=U>>>0>T>>>0?T:U;if((L|0)!=0?(U=m+12|0,Kg(c[U>>2]|0,c[K+16>>2]|0,L|0)|0,c[U>>2]=(c[U>>2]|0)+L,U=(c[A>>2]|0)+16|0,c[U>>2]=(c[U>>2]|0)+L,U=m+20|0,c[U>>2]=(c[U>>2]|0)+L,c[f>>2]=(c[f>>2]|0)-L,f=c[A>>2]|0,A=f+20|0,U=c[A>>2]|0,c[A>>2]=U-L,(U|0)==(L|0)):0){c[f+16>>2]=c[f+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){C=n?2:0;i=g;return C|0}else{C=n?3:1;i=g;return C|0}}else if((D|0)==34){i=g;return C|0}return 0}function pf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0;g=i;h=e+116|0;j=(f|0)==0;k=e+72|0;l=e+88|0;m=e+108|0;n=e+56|0;o=e+84|0;p=e+68|0;q=e+52|0;r=e+64|0;s=e+96|0;t=e+120|0;u=e+112|0;v=e+100|0;w=e+5792|0;x=e+5796|0;y=e+5784|0;z=e+5788|0;A=e+104|0;B=e+92|0;C=e+128|0;D=e+44|0;E=e+136|0;a:while(1){F=c[h>>2]|0;while(1){if(F>>>0<262){mf(e);G=c[h>>2]|0;if(G>>>0<262&j){H=0;I=50;break a}if((G|0)==0){I=40;break a}if(!(G>>>0>2)){c[t>>2]=c[s>>2];c[v>>2]=c[u>>2];c[s>>2]=2;J=2;I=16}else{I=8}}else{I=8}do{if((I|0)==8){I=0;G=c[m>>2]|0;K=((d[(c[n>>2]|0)+(G+2)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=K;L=(c[p>>2]|0)+(K<<1)|0;K=b[L>>1]|0;b[(c[r>>2]|0)+((c[q>>2]&G)<<1)>>1]=K;M=K&65535;b[L>>1]=G;G=c[s>>2]|0;c[t>>2]=G;c[v>>2]=c[u>>2];c[s>>2]=2;if(!(K<<16>>16==0)){if(G>>>0<(c[C>>2]|0)>>>0){if(!(((c[m>>2]|0)-M|0)>>>0>((c[D>>2]|0)+ -262|0)>>>0)){K=qf(e,M)|0;c[s>>2]=K;if(K>>>0<6){if((c[E>>2]|0)!=1){if((K|0)!=3){J=K;I=16;break}if(!(((c[m>>2]|0)-(c[u>>2]|0)|0)>>>0>4096)){J=3;I=16;break}}c[s>>2]=2;J=2;I=16}else{J=K;I=16}}else{J=2;I=16}}else{N=G;O=2}}else{J=2;I=16}}}while(0);if((I|0)==16){I=0;N=c[t>>2]|0;O=J}if(!(N>>>0<3|O>>>0>N>>>0)){break}if((c[A>>2]|0)==0){c[A>>2]=1;c[m>>2]=(c[m>>2]|0)+1;G=(c[h>>2]|0)+ -1|0;c[h>>2]=G;F=G;continue}G=a[(c[n>>2]|0)+((c[m>>2]|0)+ -1)|0]|0;K=c[w>>2]|0;b[(c[x>>2]|0)+(K<<1)>>1]=0;c[w>>2]=K+1;a[(c[y>>2]|0)+K|0]=G;K=e+((G&255)<<2)+148|0;b[K>>1]=(b[K>>1]|0)+1<<16>>16;if((c[w>>2]|0)==((c[z>>2]|0)+ -1|0)){K=c[B>>2]|0;if((K|0)>-1){P=(c[n>>2]|0)+K|0}else{P=0}Sf(e,P,(c[m>>2]|0)-K|0,0);c[B>>2]=c[m>>2];K=c[e>>2]|0;G=K+28|0;M=c[G>>2]|0;L=c[M+20>>2]|0;Q=K+16|0;R=c[Q>>2]|0;S=L>>>0>R>>>0?R:L;if((S|0)!=0?(L=K+12|0,Kg(c[L>>2]|0,c[M+16>>2]|0,S|0)|0,c[L>>2]=(c[L>>2]|0)+S,L=(c[G>>2]|0)+16|0,c[L>>2]=(c[L>>2]|0)+S,L=K+20|0,c[L>>2]=(c[L>>2]|0)+S,c[Q>>2]=(c[Q>>2]|0)-S,Q=c[G>>2]|0,G=Q+20|0,L=c[G>>2]|0,c[G>>2]=L-S,(L|0)==(S|0)):0){c[Q+16>>2]=c[Q+8>>2]}}c[m>>2]=(c[m>>2]|0)+1;Q=(c[h>>2]|0)+ -1|0;c[h>>2]=Q;if((c[(c[e>>2]|0)+16>>2]|0)==0){H=0;I=50;break a}else{F=Q}}F=c[m>>2]|0;Q=F+ -3+(c[h>>2]|0)|0;S=N+253|0;L=F+65535-(c[v>>2]|0)|0;F=c[w>>2]|0;b[(c[x>>2]|0)+(F<<1)>>1]=L;c[w>>2]=F+1;a[(c[y>>2]|0)+F|0]=S;F=e+((d[25272+(S&255)|0]|0|256)+1<<2)+148|0;b[F>>1]=(b[F>>1]|0)+1<<16>>16;F=L+65535&65535;if(F>>>0<256){T=F}else{T=(F>>>7)+256|0}F=e+((d[24760+T|0]|0)<<2)+2440|0;b[F>>1]=(b[F>>1]|0)+1<<16>>16;F=c[w>>2]|0;L=(c[z>>2]|0)+ -1|0;S=c[t>>2]|0;c[h>>2]=1-S+(c[h>>2]|0);G=S+ -2|0;c[t>>2]=G;S=c[m>>2]|0;K=G;while(1){G=S+1|0;c[m>>2]=G;if(!(G>>>0>Q>>>0)){M=((d[(c[n>>2]|0)+(S+3)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=M;R=(c[p>>2]|0)+(M<<1)|0;b[(c[r>>2]|0)+((c[q>>2]&G)<<1)>>1]=b[R>>1]|0;b[R>>1]=G}K=K+ -1|0;c[t>>2]=K;if((K|0)==0){break}else{S=G}}c[A>>2]=0;c[s>>2]=2;K=S+2|0;c[m>>2]=K;if((F|0)!=(L|0)){continue}Q=c[B>>2]|0;if((Q|0)>-1){U=(c[n>>2]|0)+Q|0}else{U=0}Sf(e,U,K-Q|0,0);c[B>>2]=c[m>>2];Q=c[e>>2]|0;K=Q+28|0;G=c[K>>2]|0;R=c[G+20>>2]|0;M=Q+16|0;V=c[M>>2]|0;W=R>>>0>V>>>0?V:R;if((W|0)!=0?(R=Q+12|0,Kg(c[R>>2]|0,c[G+16>>2]|0,W|0)|0,c[R>>2]=(c[R>>2]|0)+W,R=(c[K>>2]|0)+16|0,c[R>>2]=(c[R>>2]|0)+W,R=Q+20|0,c[R>>2]=(c[R>>2]|0)+W,c[M>>2]=(c[M>>2]|0)-W,M=c[K>>2]|0,K=M+20|0,R=c[K>>2]|0,c[K>>2]=R-W,(R|0)==(W|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){H=0;I=50;break}}if((I|0)==40){if((c[A>>2]|0)!=0){U=a[(c[n>>2]|0)+((c[m>>2]|0)+ -1)|0]|0;s=c[w>>2]|0;b[(c[x>>2]|0)+(s<<1)>>1]=0;c[w>>2]=s+1;a[(c[y>>2]|0)+s|0]=U;s=e+((U&255)<<2)+148|0;b[s>>1]=(b[s>>1]|0)+1<<16>>16;c[A>>2]=0}A=c[B>>2]|0;if((A|0)>-1){X=(c[n>>2]|0)+A|0}else{X=0}n=(f|0)==4;Sf(e,X,(c[m>>2]|0)-A|0,n&1);c[B>>2]=c[m>>2];m=c[e>>2]|0;B=m+28|0;A=c[B>>2]|0;X=c[A+20>>2]|0;f=m+16|0;s=c[f>>2]|0;U=X>>>0>s>>>0?s:X;if((U|0)!=0?(X=m+12|0,Kg(c[X>>2]|0,c[A+16>>2]|0,U|0)|0,c[X>>2]=(c[X>>2]|0)+U,X=(c[B>>2]|0)+16|0,c[X>>2]=(c[X>>2]|0)+U,X=m+20|0,c[X>>2]=(c[X>>2]|0)+U,c[f>>2]=(c[f>>2]|0)-U,f=c[B>>2]|0,B=f+20|0,X=c[B>>2]|0,c[B>>2]=X-U,(X|0)==(U|0)):0){c[f+16>>2]=c[f+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){H=n?2:0;i=g;return H|0}else{H=n?3:1;i=g;return H|0}}else if((I|0)==50){i=g;return H|0}return 0}function qf(b,d){b=b|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;f=i;g=c[b+124>>2]|0;h=c[b+56>>2]|0;j=c[b+108>>2]|0;k=h+j|0;l=c[b+120>>2]|0;m=c[b+144>>2]|0;n=(c[b+44>>2]|0)+ -262|0;o=j>>>0>n>>>0?j-n|0:0;n=c[b+64>>2]|0;p=c[b+52>>2]|0;q=h+(j+258)|0;r=c[b+116>>2]|0;s=m>>>0>r>>>0?r:m;m=b+112|0;t=h+(j+1)|0;u=h+(j+2)|0;v=q;w=j+257|0;x=d;d=l;y=l>>>0<(c[b+140>>2]|0)>>>0?g:g>>>2;g=a[h+(l+j)|0]|0;b=a[h+(j+ -1+l)|0]|0;while(1){l=h+x|0;if((((a[h+(x+d)|0]|0)==g<<24>>24?(a[h+(d+ -1+x)|0]|0)==b<<24>>24:0)?(a[l]|0)==(a[k]|0):0)?(a[h+(x+1)|0]|0)==(a[t]|0):0){l=h+(x+2)|0;z=u;while(1){A=z+1|0;if((a[A]|0)!=(a[l+1|0]|0)){B=A;break}A=z+2|0;if((a[A]|0)!=(a[l+2|0]|0)){B=A;break}A=z+3|0;if((a[A]|0)!=(a[l+3|0]|0)){B=A;break}A=z+4|0;if((a[A]|0)!=(a[l+4|0]|0)){B=A;break}A=z+5|0;if((a[A]|0)!=(a[l+5|0]|0)){B=A;break}A=z+6|0;if((a[A]|0)!=(a[l+6|0]|0)){B=A;break}A=z+7|0;if((a[A]|0)!=(a[l+7|0]|0)){B=A;break}A=z+8|0;C=l+8|0;if((a[A]|0)==(a[C]|0)&A>>>0>>0){l=C;z=A}else{B=A;break}}z=B-v|0;l=z+258|0;if((l|0)>(d|0)){c[m>>2]=x;if((l|0)>=(s|0)){D=l;E=20;break}F=l;G=a[h+(l+j)|0]|0;H=a[h+(w+z)|0]|0}else{F=d;G=g;H=b}}else{F=d;G=g;H=b}z=e[n+((x&p)<<1)>>1]|0;if(!(z>>>0>o>>>0)){D=F;E=20;break}l=y+ -1|0;if((l|0)==0){D=F;E=20;break}else{x=z;d=F;y=l;g=G;b=H}}if((E|0)==20){i=f;return(D>>>0>r>>>0?r:D)|0}return 0}function rf(a){a=a|0;var b=0,d=0;b=i;do{if((a|0)!=0){if((c[a>>2]|0)==7247){d=Af(a)|0;break}else{d=Ff(a)|0;break}}else{d=-2}}while(0);i=b;return d|0}function sf(a,b){a=a|0;b=b|0;var c=0,d=0;c=i;d=tf(a,-1,b)|0;i=c;return d|0}function tf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+16|0;g=f;h=gg(140)|0;if((h|0)==0){j=0;i=f;return j|0}c[h+16>>2]=0;c[h+20>>2]=8192;k=h+80|0;c[k>>2]=0;c[h>>2]=0;l=h+60|0;c[l>>2]=-1;m=h+64|0;c[m>>2]=0;n=a[e]|0;if(!(n<<24>>24==0)){o=e;e=n;n=0;a:while(1){p=e<<24>>24;b:do{if((e+ -48<<24>>24&255)<10){c[l>>2]=p+ -48;q=n}else{switch(p|0){case 70:{c[m>>2]=4;q=n;break b;break};case 43:{r=9;break a;break};case 82:{c[m>>2]=3;q=n;break b;break};case 102:{c[m>>2]=1;q=n;break b;break};case 104:{c[m>>2]=2;q=n;break b;break};case 119:{c[h>>2]=31153;q=31153;break b;break};case 97:{c[h>>2]=1;q=1;break b;break};case 114:{c[h>>2]=7247;q=7247;break b;break};default:{q=n;break b}}}}while(0);o=o+1|0;e=a[o]|0;if(e<<24>>24==0){break}else{n=q}}if((r|0)==9){hg(h);j=0;i=f;return j|0}if((q|0)!=0){q=gg((Dg(b|0)|0)+1|0)|0;r=h+8|0;c[r>>2]=q;if((q|0)==0){hg(h);j=0;i=f;return j|0}Lg(q|0,b|0)|0;if((d|0)==-1){q=c[h>>2]|0;if((q|0)==7247){s=32768}else{s=(q|0)==31153?33345:33857}c[g>>2]=438;q=Aa(b|0,s|0,g|0)|0;c[h+4>>2]=q;if((q|0)==-1){hg(c[r>>2]|0);hg(h);j=0;i=f;return j|0}else{t=q}}else{c[h+4>>2]=d;t=d}d=c[h>>2]|0;if((d|0)==1){c[h>>2]=31153}else if((d|0)==7247?(d=ra(t|0,0,1)|0,c[h+44>>2]=(d|0)==-1?0:d,(c[h>>2]|0)==7247):0){c[h+36>>2]=0;c[h+40>>2]=0;c[h+52>>2]=0;c[h+56>>2]=1}c[h+72>>2]=0;d=c[k>>2]|0;t=h+76|0;if((d|0)!=0){if(!((c[t>>2]|0)==-4)){hg(d)}c[k>>2]=0}c[t>>2]=0;c[h+12>>2]=0;c[h+88>>2]=0;j=h;i=f;return j|0}}hg(h);j=0;i=f;return j|0}function uf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;e=i;if((a|0)==0){f=-1;i=e;return f|0}g=c[a>>2]|0;if(!((g|0)==31153|(g|0)==7247)){f=-1;i=e;return f|0}h=a+76|0;if((c[h>>2]|0)!=0|d>>>0>1){f=-1;i=e;return f|0}if((d|0)!=0){d=a+72|0;if((c[d>>2]|0)==0){j=b;k=d}else{j=(c[a+68>>2]|0)+b|0;k=d}}else{j=b-(c[a+12>>2]|0)|0;k=a+72|0}c[k>>2]=0;b=(g|0)==7247;if((b?(c[a+52>>2]|0)==1:0)?(d=a+12|0,((c[d>>2]|0)+j|0)>=(c[a+48>>2]|0)):0){l=a+36|0;if((ra(c[a+4>>2]|0,j-(c[l>>2]|0)|0,1)|0)==-1){f=-1;i=e;return f|0}c[l>>2]=0;c[a+40>>2]=0;c[k>>2]=0;l=a+80|0;m=c[l>>2]|0;if((m|0)!=0){if(!((c[h>>2]|0)==-4)){hg(m)}c[l>>2]=0}c[h>>2]=0;c[a+88>>2]=0;l=(c[d>>2]|0)+j|0;c[d>>2]=l;f=l;i=e;return f|0}if((j|0)<0){if(!b){f=-1;i=e;return f|0}b=a+12|0;l=(c[b>>2]|0)+j|0;if((l|0)<0){f=-1;i=e;return f|0}if((ra(c[a+4>>2]|0,c[a+44>>2]|0,0)|0)==-1){f=-1;i=e;return f|0}d=c[a>>2]|0;if((d|0)==7247){c[a+36>>2]=0;c[a+40>>2]=0;c[a+52>>2]=0;c[a+56>>2]=1}c[k>>2]=0;m=a+80|0;n=c[m>>2]|0;if((n|0)==0){o=d}else{if((c[h>>2]|0)==-4){p=d}else{hg(n);p=c[a>>2]|0}c[m>>2]=0;o=p}c[h>>2]=0;c[b>>2]=0;c[a+88>>2]=0;q=l;r=o}else{q=j;r=g}if((r|0)==7247){r=a+36|0;g=c[r>>2]|0;j=(g|0)<0|(g|0)>(q|0)?q:g;c[r>>2]=g-j;g=a+32|0;c[g>>2]=(c[g>>2]|0)+j;g=a+12|0;c[g>>2]=j+(c[g>>2]|0);s=q-j|0}else{s=q}if((s|0)!=0){c[k>>2]=1;c[a+68>>2]=s}f=(c[a+12>>2]|0)+s|0;i=e;return f|0}function vf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;g=b+80|0;h=c[g>>2]|0;j=b+76|0;if((h|0)!=0){if(!((c[j>>2]|0)==-4)){hg(h)}c[g>>2]=0}c[j>>2]=d;if((e|0)==0){i=f;return}if((d|0)==-4){c[g>>2]=e;i=f;return}d=c[b+8>>2]|0;b=Dg(d|0)|0;h=gg(b+3+(Dg(e|0)|0)|0)|0;c[g>>2]=h;if((h|0)==0){c[j>>2]=-4;c[g>>2]=21280;i=f;return}else{Lg(h|0,d|0)|0;d=c[g>>2]|0;h=d+(Dg(d|0)|0)|0;a[h+0|0]=a[21296|0]|0;a[h+1|0]=a[21297|0]|0;a[h+2|0]=a[21298|0]|0;Fg(c[g>>2]|0,e|0)|0;i=f;return}}function wf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=uf(a,b,c)|0;i=d;return e|0}function xf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0;e=i;if((a|0)==0){f=-1;i=e;return f|0}if((c[a>>2]|0)!=7247){f=-1;i=e;return f|0}if((c[a+76>>2]|0)!=0){f=-1;i=e;return f|0}if((d|0)<0){vf(a,-5,21304);f=-1;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}g=a+72|0;a:do{if((c[g>>2]|0)!=0){c[g>>2]=0;h=c[a+68>>2]|0;j=a+36|0;k=a+40|0;l=a+88|0;m=a+32|0;n=a+12|0;if((h|0)!=0){o=a+52|0;p=a+28|0;q=a+16|0;r=a+4|0;s=a+100|0;t=a+96|0;u=h;b:while(1){c:while(1){v=c[j>>2]|0;while(1){if((v|0)!=0){break c}if((c[k>>2]|0)!=0?(c[l>>2]|0)==0:0){w=j;x=k;y=m;z=l;A=n;break a}h=c[o>>2]|0;if((h|0)!=0){B=h;break}if((zf(a)|0)==-1){f=-1;C=59;break b}h=c[j>>2]|0;if((h|0)==0){C=21;break}else{v=h}}if((C|0)==21){C=0;B=c[o>>2]|0}if((B|0)==2){c[s>>2]=c[q>>2]<<1;c[t>>2]=c[p>>2];if((yf(a)|0)==-1){f=-1;C=59;break b}else{continue}}else if((B|0)!=1){continue}h=c[p>>2]|0;D=c[q>>2]<<1;c[j>>2]=0;E=0;do{F=Za(c[r>>2]|0,h+E|0,D-E|0)|0;if((F|0)<1){C=26;break}E=(c[j>>2]|0)+F|0;c[j>>2]=E}while(E>>>0>>0);if((C|0)==26){C=0;if((F|0)<0){C=28;break b}c[k>>2]=1}c[m>>2]=c[p>>2]}D=(v|0)<0|(v|0)>(u|0)?u:v;c[j>>2]=v-D;c[m>>2]=(c[m>>2]|0)+D;c[n>>2]=(c[n>>2]|0)+D;if((u|0)==(D|0)){w=j;x=k;y=m;z=l;A=n;break a}else{u=u-D|0}}if((C|0)==28){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==59){i=e;return f|0}}else{w=j;x=k;y=m;z=l;A=n}}else{w=a+36|0;x=a+40|0;y=a+32|0;z=a+88|0;A=a+12|0}}while(0);v=a+52|0;F=a+28|0;B=a+16|0;g=a+4|0;u=a+100|0;p=a+96|0;r=b;b=d;d=0;d:while(1){q=c[w>>2]|0;e:do{if((q|0)==0){if((c[x>>2]|0)!=0?(c[z>>2]|0)==0:0){f=d;C=59;break d}t=c[v>>2]|0;if((t|0)!=0){if(b>>>0>2]<<1>>>0){G=t}else{if((t|0)==1){H=0}else{c[u>>2]=b;c[p>>2]=r;if((yf(a)|0)==-1){f=-1;C=59;break d}t=c[w>>2]|0;c[w>>2]=0;I=t;C=57;break}while(1){J=Za(c[g>>2]|0,r+H|0,b-H|0)|0;if((J|0)<1){break}t=J+H|0;if(t>>>0>>0){H=t}else{I=t;C=57;break e}}if((J|0)<0){C=54;break d}c[x>>2]=1;I=H;C=57;break}}else{if((zf(a)|0)==-1){f=-1;C=59;break d}if((c[w>>2]|0)!=0){K=r;L=b;M=d;break}G=c[v>>2]|0}if((G|0)==2){c[u>>2]=c[B>>2]<<1;c[p>>2]=c[F>>2];if((yf(a)|0)==-1){f=-1;C=59;break d}else{K=r;L=b;M=d;break}}else if((G|0)!=1){K=r;L=b;M=d;break}t=c[F>>2]|0;s=c[B>>2]<<1;c[w>>2]=0;o=0;do{N=Za(c[g>>2]|0,t+o|0,s-o|0)|0;if((N|0)<1){C=44;break}o=(c[w>>2]|0)+N|0;c[w>>2]=o}while(o>>>0>>0);if((C|0)==44){C=0;if((N|0)<0){C=46;break d}c[x>>2]=1}c[y>>2]=c[F>>2];K=r;L=b;M=d}else{s=q>>>0>b>>>0?b:q;Kg(r|0,c[y>>2]|0,s|0)|0;c[y>>2]=(c[y>>2]|0)+s;c[w>>2]=(c[w>>2]|0)-s;I=s;C=57}}while(0);if((C|0)==57){C=0;c[A>>2]=(c[A>>2]|0)+I;K=r+I|0;L=b-I|0;M=I+d|0}if((L|0)==0){f=M;C=59;break}else{r=K;b=L;d=M}}if((C|0)==46){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==54){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==59){i=e;return f|0}return 0}function yf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;b=i;i=i+16|0;d=b+4|0;e=b;f=a+84|0;g=a+100|0;h=c[g>>2]|0;j=a+88|0;k=a+76|0;l=a+40|0;m=a+24|0;n=a+16|0;o=a+4|0;p=a+84|0;while(1){if((c[j>>2]|0)==0){if((c[k>>2]|0)!=0){q=-1;r=27;break}if((c[l>>2]|0)!=0){r=12;break}s=c[m>>2]|0;t=c[n>>2]|0;c[j>>2]=0;u=0;while(1){v=Za(c[o>>2]|0,s+u|0,t-u|0)|0;if((v|0)<1){r=8;break}w=(c[j>>2]|0)+v|0;c[j>>2]=w;if(w>>>0>>0){u=w}else{x=w;break}}if((r|0)==8){r=0;if((v|0)<0){r=10;break}c[l>>2]=1;x=c[j>>2]|0}c[p>>2]=c[m>>2];if((x|0)==0){r=12;break}}u=Kf(f,0)|0;if((u|0)==-4){r=15;break}else if((u|0)==-3){r=16;break}else if((u|0)==2|(u|0)==-2){r=14;break}y=c[g>>2]|0;z=(u|0)==1;if((y|0)==0|z){r=18;break}}if((r|0)==10){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);q=-1;i=b;return q|0}else if((r|0)==12){vf(a,-3,21432);q=-1;i=b;return q|0}else if((r|0)==14){vf(a,-2,21456);q=-1;i=b;return q|0}else if((r|0)==15){vf(a,-4,21344);q=-1;i=b;return q|0}else if((r|0)==16){g=c[a+108>>2]|0;vf(a,-3,(g|0)==0?21496:g);q=-1;i=b;return q|0}else if((r|0)==18){g=h-y|0;c[a+36>>2]=g;y=(c[a+96>>2]|0)+(0-g)|0;c[a+32>>2]=y;h=a+132|0;c[h>>2]=gf(c[h>>2]|0,y,g)|0;if(!z){q=0;i=b;return q|0}if(!((Bf(a,d)|0)==-1)?!((Bf(a,e)|0)==-1):0){if((c[d>>2]|0)!=(c[h>>2]|0)){vf(a,-3,21520);q=-1;i=b;return q|0}if((c[e>>2]|0)==(c[a+104>>2]|0)){c[a+52>>2]=0;q=0;i=b;return q|0}else{vf(a,-3,21544);q=-1;i=b;return q|0}}vf(a,-3,21432);q=-1;i=b;return q|0}else if((r|0)==27){i=b;return q|0}return 0}function zf(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0;e=i;f=b+84|0;g=b+16|0;do{if((c[g>>2]|0)==0){h=c[b+20>>2]|0;j=gg(h)|0;k=b+24|0;c[k>>2]=j;l=gg(h<<1)|0;m=b+28|0;c[m>>2]=l;n=(l|0)==0;if(!((j|0)==0|n)){c[g>>2]=h;c[b+116>>2]=0;c[b+120>>2]=0;c[b+124>>2]=0;h=b+88|0;c[h>>2]=0;c[f>>2]=0;if((Jf(f,-15,21360,56)|0)==0){o=h;break}hg(c[m>>2]|0);hg(c[k>>2]|0);c[g>>2]=0;vf(b,-4,21344);p=-1;i=e;return p|0}if(n){q=j}else{hg(l);q=c[k>>2]|0}if((q|0)!=0){hg(q)}vf(b,-4,21344);p=-1;i=e;return p|0}else{o=b+88|0}}while(0);q=c[o>>2]|0;if((q|0)==0){if((c[b+76>>2]|0)!=0){p=-1;i=e;return p|0}k=b+40|0;if((c[k>>2]|0)!=0){p=0;i=e;return p|0}l=b+24|0;j=c[l>>2]|0;n=c[g>>2]|0;c[o>>2]=0;m=b+4|0;h=0;while(1){r=Za(c[m>>2]|0,j+h|0,n-h|0)|0;if((r|0)<1){s=17;break}t=(c[o>>2]|0)+r|0;c[o>>2]=t;if(t>>>0>>0){h=t}else{u=t;break}}do{if((s|0)==17){if((r|0)>=0){c[k>>2]=1;u=c[o>>2]|0;break}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);p=-1;i=e;return p|0}}while(0);c[b+84>>2]=c[l>>2];if((u|0)==0){p=0;i=e;return p|0}else{v=u}}else{v=q}q=c[f>>2]|0;if((a[q]|0)==31){u=v+ -1|0;c[o>>2]=u;l=q+1|0;c[f>>2]=l;if((u|0)==0){if((c[b+76>>2]|0)!=0){p=-1;i=e;return p|0}q=b+40|0;if((c[q>>2]|0)==0){k=b+24|0;r=c[k>>2]|0;h=c[g>>2]|0;c[o>>2]=0;n=b+4|0;j=0;while(1){w=Za(c[n>>2]|0,r+j|0,h-j|0)|0;if((w|0)<1){s=29;break}m=(c[o>>2]|0)+w|0;c[o>>2]=m;if(m>>>0>>0){j=m}else{x=m;break}}do{if((s|0)==29){if((w|0)>=0){c[q>>2]=1;x=c[o>>2]|0;break}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);p=-1;i=e;return p|0}}while(0);q=c[k>>2]|0;c[b+84>>2]=q;if((x|0)!=0){y=q;z=x;s=33}}}else{y=l;z=u;s=33}if((s|0)==33?(a[y]|0)==-117:0){u=z+ -1|0;c[o>>2]=u;z=y+1|0;c[f>>2]=z;a:do{if((u|0)==0){if((c[b+76>>2]|0)==0?(y=b+40|0,(c[y>>2]|0)==0):0){l=b+24|0;x=c[l>>2]|0;q=c[g>>2]|0;c[o>>2]=0;k=b+4|0;w=0;while(1){A=Za(c[k>>2]|0,x+w|0,q-w|0)|0;if((A|0)<1){s=40;break}j=(c[o>>2]|0)+A|0;c[o>>2]=j;if(j>>>0>>0){w=j}else{B=j;break}}do{if((s|0)==40){if((A|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break a}else{c[y>>2]=1;B=c[o>>2]|0;break}}}while(0);y=c[l>>2]|0;c[b+84>>2]=y;if((B|0)!=0){C=B;D=y;s=44}}}else{C=u;D=z;s=44}}while(0);if((s|0)==44?(z=C+ -1|0,c[o>>2]=z,C=D+1|0,c[f>>2]=C,(a[D]|0)==8):0){b:do{if((z|0)==0){if((c[b+76>>2]|0)==0?(D=b+40|0,(c[D>>2]|0)==0):0){u=b+24|0;B=c[u>>2]|0;A=c[g>>2]|0;c[o>>2]=0;y=b+4|0;w=0;while(1){E=Za(c[y>>2]|0,B+w|0,A-w|0)|0;if((E|0)<1){s=52;break}q=(c[o>>2]|0)+E|0;c[o>>2]=q;if(q>>>0>>0){w=q}else{F=q;break}}do{if((s|0)==52){if((E|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break b}else{c[D>>2]=1;F=c[o>>2]|0;break}}}while(0);D=c[u>>2]|0;c[b+84>>2]=D;if((F|0)!=0){G=F;H=D;s=56}}}else{G=z;H=C;s=56}}while(0);if((s|0)==56?(C=G+ -1|0,c[o>>2]=C,G=H+1|0,c[f>>2]=G,z=d[H]|0,(z&224|0)==0):0){c:do{if((C|0)==0){H=b+76|0;if((c[H>>2]|0)==0){F=b+40|0;if((c[F>>2]|0)==0){E=b+24|0;D=c[E>>2]|0;w=c[g>>2]|0;c[o>>2]=0;A=b+4|0;B=0;while(1){I=Za(c[A>>2]|0,D+B|0,w-B|0)|0;if((I|0)<1){s=64;break}y=(c[o>>2]|0)+I|0;c[o>>2]=y;if(y>>>0>>0){B=y}else{J=y;break}}do{if((s|0)==64){if((I|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);K=c[o>>2]|0;s=69;break c}else{c[F>>2]=1;J=c[o>>2]|0;break}}}while(0);F=c[E>>2]|0;c[b+84>>2]=F;if((J|0)!=0){L=J;M=F;s=68}else{N=H;s=71}}else{N=H;s=71}}else{s=70}}else{L=C;M=G;s=68}}while(0);if((s|0)==68){G=L+ -1|0;c[o>>2]=G;c[f>>2]=M+1;K=G;s=69}if((s|0)==69){if((K|0)==0){s=70}else{O=K;s=80}}if((s|0)==70){N=b+76|0;s=71}d:do{if((s|0)==71){if((c[N>>2]|0)==0){K=b+40|0;if((c[K>>2]|0)==0){G=b+24|0;M=c[G>>2]|0;L=c[g>>2]|0;c[o>>2]=0;C=b+4|0;J=0;while(1){P=Za(c[C>>2]|0,M+J|0,L-J|0)|0;if((P|0)<1){s=76;break}I=(c[o>>2]|0)+P|0;c[o>>2]=I;if(I>>>0>>0){J=I}else{Q=I;break}}do{if((s|0)==76){if((P|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);R=c[o>>2]|0;s=81;break d}else{c[K>>2]=1;Q=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[G>>2];if((Q|0)!=0){O=Q;s=80}else{S=N;s=83}}else{S=N;s=83}}else{s=82}}}while(0);if((s|0)==80){N=O+ -1|0;c[o>>2]=N;c[f>>2]=(c[f>>2]|0)+1;R=N;s=81}if((s|0)==81){if((R|0)==0){s=82}else{T=R;s=92}}if((s|0)==82){S=b+76|0;s=83}e:do{if((s|0)==83){if((c[S>>2]|0)==0){R=b+40|0;if((c[R>>2]|0)==0){N=b+24|0;O=c[N>>2]|0;Q=c[g>>2]|0;c[o>>2]=0;P=b+4|0;K=0;while(1){U=Za(c[P>>2]|0,O+K|0,Q-K|0)|0;if((U|0)<1){s=88;break}J=(c[o>>2]|0)+U|0;c[o>>2]=J;if(J>>>0>>0){K=J}else{V=J;break}}do{if((s|0)==88){if((U|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);W=c[o>>2]|0;s=93;break e}else{c[R>>2]=1;V=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[N>>2];if((V|0)!=0){T=V;s=92}else{X=S;s=95}}else{X=S;s=95}}else{s=94}}}while(0);if((s|0)==92){S=T+ -1|0;c[o>>2]=S;c[f>>2]=(c[f>>2]|0)+1;W=S;s=93}if((s|0)==93){if((W|0)==0){s=94}else{Y=W;s=104}}if((s|0)==94){X=b+76|0;s=95}f:do{if((s|0)==95){if((c[X>>2]|0)==0){W=b+40|0;if((c[W>>2]|0)==0){S=b+24|0;T=c[S>>2]|0;V=c[g>>2]|0;c[o>>2]=0;U=b+4|0;R=0;while(1){Z=Za(c[U>>2]|0,T+R|0,V-R|0)|0;if((Z|0)<1){s=100;break}K=(c[o>>2]|0)+Z|0;c[o>>2]=K;if(K>>>0>>0){R=K}else{_=K;break}}do{if((s|0)==100){if((Z|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);$=c[o>>2]|0;s=105;break f}else{c[W>>2]=1;_=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[S>>2];if((_|0)!=0){Y=_;s=104}else{aa=X;s=107}}else{aa=X;s=107}}else{s=106}}}while(0);if((s|0)==104){X=Y+ -1|0;c[o>>2]=X;c[f>>2]=(c[f>>2]|0)+1;$=X;s=105}if((s|0)==105){if(($|0)==0){s=106}else{ba=$;s=116}}if((s|0)==106){aa=b+76|0;s=107}g:do{if((s|0)==107){if((c[aa>>2]|0)==0){$=b+40|0;if((c[$>>2]|0)==0){X=b+24|0;Y=c[X>>2]|0;_=c[g>>2]|0;c[o>>2]=0;Z=b+4|0;W=0;while(1){ca=Za(c[Z>>2]|0,Y+W|0,_-W|0)|0;if((ca|0)<1){s=112;break}R=(c[o>>2]|0)+ca|0;c[o>>2]=R;if(R>>>0<_>>>0){W=R}else{da=R;break}}do{if((s|0)==112){if((ca|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);ea=c[o>>2]|0;s=117;break g}else{c[$>>2]=1;da=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[X>>2];if((da|0)!=0){ba=da;s=116}else{fa=aa;s=119}}else{fa=aa;s=119}}else{s=118}}}while(0);if((s|0)==116){aa=ba+ -1|0;c[o>>2]=aa;c[f>>2]=(c[f>>2]|0)+1;ea=aa;s=117}if((s|0)==117){if((ea|0)==0){s=118}else{ga=ea;s=128}}if((s|0)==118){fa=b+76|0;s=119}h:do{if(((s|0)==119?(c[fa>>2]|0)==0:0)?(ea=b+40|0,(c[ea>>2]|0)==0):0){aa=b+24|0;ba=c[aa>>2]|0;da=c[g>>2]|0;c[o>>2]=0;ca=b+4|0;$=0;while(1){ha=Za(c[ca>>2]|0,ba+$|0,da-$|0)|0;if((ha|0)<1){s=124;break}W=(c[o>>2]|0)+ha|0;c[o>>2]=W;if(W>>>0>>0){$=W}else{ia=W;break}}do{if((s|0)==124){if((ha|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break h}else{c[ea>>2]=1;ia=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[aa>>2];if((ia|0)!=0){ga=ia;s=128}}}while(0);if((s|0)==128){c[o>>2]=ga+ -1;c[f>>2]=(c[f>>2]|0)+1}i:do{if((z&4|0)!=0){ga=c[o>>2]|0;j:do{if((ga|0)==0){ia=b+76|0;if((c[ia>>2]|0)==0){ha=b+40|0;if((c[ha>>2]|0)==0){fa=b+24|0;ea=c[fa>>2]|0;$=c[g>>2]|0;c[o>>2]=0;da=b+4|0;ba=0;while(1){ja=Za(c[da>>2]|0,ea+ba|0,$-ba|0)|0;if((ja|0)<1){s=136;break}ca=(c[o>>2]|0)+ja|0;c[o>>2]=ca;if(ca>>>0<$>>>0){ba=ca}else{ka=ca;break}}do{if((s|0)==136){if((ja|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);la=-1;ma=c[o>>2]|0;s=141;break j}else{c[ha>>2]=1;ka=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[fa>>2];if((ka|0)!=0){na=ka;s=140}else{oa=ia;pa=-1;s=143}}else{oa=ia;pa=-1;s=143}}else{qa=-1;s=142}}else{na=ga;s=140}}while(0);if((s|0)==140){ga=na+ -1|0;c[o>>2]=ga;aa=c[f>>2]|0;c[f>>2]=aa+1;la=d[aa]|0;ma=ga;s=141}if((s|0)==141){if((ma|0)==0){qa=la;s=142}else{ra=ma;sa=la;s=152}}if((s|0)==142){oa=b+76|0;pa=qa;s=143}k:do{if((s|0)==143){if((c[oa>>2]|0)==0?(ga=b+40|0,(c[ga>>2]|0)==0):0){aa=b+24|0;ha=c[aa>>2]|0;ba=c[g>>2]|0;c[o>>2]=0;$=b+4|0;ea=0;while(1){ta=Za(c[$>>2]|0,ha+ea|0,ba-ea|0)|0;if((ta|0)<1){s=148;break}da=(c[o>>2]|0)+ta|0;c[o>>2]=da;if(da>>>0>>0){ea=da}else{ua=da;break}}do{if((s|0)==148){if((ta|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);va=-256;wa=pa;break k}else{c[ga>>2]=1;ua=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[aa>>2];if((ua|0)!=0){ra=ua;sa=pa;s=152}else{va=-256;wa=pa}}else{va=-256;wa=pa}}}while(0);if((s|0)==152){c[o>>2]=ra+ -1;ga=c[f>>2]|0;c[f>>2]=ga+1;va=d[ga]<<8;wa=sa}ga=va+wa|0;if((ga|0)!=0){ea=b+76|0;ba=b+40|0;ha=b+24|0;$=b+4|0;ia=b+84|0;fa=ga;ga=c[o>>2]|0;while(1){fa=fa+ -1|0;if((ga|0)==0){if((c[ea>>2]|0)!=0){break i}if((c[ba>>2]|0)!=0){break i}da=c[ha>>2]|0;ca=c[g>>2]|0;c[o>>2]=0;X=0;while(1){xa=Za(c[$>>2]|0,da+X|0,ca-X|0)|0;if((xa|0)<1){s=161;break}W=(c[o>>2]|0)+xa|0;c[o>>2]=W;if(W>>>0>>0){X=W}else{ya=W;break}}if((s|0)==161){s=0;if((xa|0)<0){break}c[ba>>2]=1;ya=c[o>>2]|0}c[ia>>2]=c[ha>>2];if((ya|0)==0){break i}else{za=ya}}else{za=ga}ga=za+ -1|0;c[o>>2]=ga;c[f>>2]=(c[f>>2]|0)+1;if((fa|0)==0){break i}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}}while(0);l:do{if((z&8|0)!=0){za=b+76|0;ya=b+40|0;xa=b+24|0;wa=b+4|0;va=b+84|0;sa=c[o>>2]|0;while(1){if((sa|0)==0){if((c[za>>2]|0)!=0){break l}if((c[ya>>2]|0)!=0){break l}ra=c[xa>>2]|0;pa=c[g>>2]|0;c[o>>2]=0;ua=0;while(1){Aa=Za(c[wa>>2]|0,ra+ua|0,pa-ua|0)|0;if((Aa|0)<1){s=174;break}ta=(c[o>>2]|0)+Aa|0;c[o>>2]=ta;if(ta>>>0>>0){ua=ta}else{Ba=ta;break}}if((s|0)==174){s=0;if((Aa|0)<0){break}c[ya>>2]=1;Ba=c[o>>2]|0}c[va>>2]=c[xa>>2];if((Ba|0)==0){break l}else{Ca=Ba}}else{Ca=sa}sa=Ca+ -1|0;c[o>>2]=sa;ua=c[f>>2]|0;c[f>>2]=ua+1;if((a[ua]|0)==0){break l}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}while(0);m:do{if((z&16|0)!=0){Ca=b+76|0;Ba=b+40|0;Aa=b+24|0;sa=b+4|0;xa=b+84|0;va=c[o>>2]|0;while(1){if((va|0)==0){if((c[Ca>>2]|0)!=0){break m}if((c[Ba>>2]|0)!=0){break m}ya=c[Aa>>2]|0;wa=c[g>>2]|0;c[o>>2]=0;za=0;while(1){Da=Za(c[sa>>2]|0,ya+za|0,wa-za|0)|0;if((Da|0)<1){s=187;break}ua=(c[o>>2]|0)+Da|0;c[o>>2]=ua;if(ua>>>0>>0){za=ua}else{Ea=ua;break}}if((s|0)==187){s=0;if((Da|0)<0){break}c[Ba>>2]=1;Ea=c[o>>2]|0}c[xa>>2]=c[Aa>>2];if((Ea|0)==0){break m}else{Fa=Ea}}else{Fa=va}va=Fa+ -1|0;c[o>>2]=va;za=c[f>>2]|0;c[f>>2]=za+1;if((a[za]|0)==0){break m}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}while(0);n:do{if((z&2|0)!=0){Fa=c[o>>2]|0;o:do{if((Fa|0)==0){Ea=b+76|0;if((c[Ea>>2]|0)==0){Da=b+40|0;if((c[Da>>2]|0)==0){va=b+24|0;Aa=c[va>>2]|0;xa=c[g>>2]|0;c[o>>2]=0;Ba=b+4|0;sa=0;while(1){Ga=Za(c[Ba>>2]|0,Aa+sa|0,xa-sa|0)|0;if((Ga|0)<1){s=199;break}Ca=(c[o>>2]|0)+Ga|0;c[o>>2]=Ca;if(Ca>>>0>>0){sa=Ca}else{Ha=Ca;break}}do{if((s|0)==199){if((Ga|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);Ia=c[o>>2]|0;s=204;break o}else{c[Da>>2]=1;Ha=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[va>>2];if((Ha|0)!=0){Ja=Ha;s=203}else{Ka=Ea;s=206}}else{Ka=Ea;s=206}}else{s=205}}else{Ja=Fa;s=203}}while(0);if((s|0)==203){Fa=Ja+ -1|0;c[o>>2]=Fa;c[f>>2]=(c[f>>2]|0)+1;Ia=Fa;s=204}if((s|0)==204){if((Ia|0)==0){s=205}else{La=Ia}}if((s|0)==205){Ka=b+76|0;s=206}if((s|0)==206){if((c[Ka>>2]|0)!=0){break}Fa=b+40|0;if((c[Fa>>2]|0)!=0){break}Da=b+24|0;sa=c[Da>>2]|0;xa=c[g>>2]|0;c[o>>2]=0;Aa=b+4|0;Ba=0;while(1){Ma=Za(c[Aa>>2]|0,sa+Ba|0,xa-Ba|0)|0;if((Ma|0)<1){s=211;break}Ca=(c[o>>2]|0)+Ma|0;c[o>>2]=Ca;if(Ca>>>0>>0){Ba=Ca}else{Na=Ca;break}}do{if((s|0)==211){if((Ma|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break n}else{c[Fa>>2]=1;Na=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[Da>>2];if((Na|0)==0){break}else{La=Na}}c[o>>2]=La+ -1;c[f>>2]=(c[f>>2]|0)+1}}while(0);Hf(f)|0;c[b+132>>2]=gf(0,0,0)|0;c[b+52>>2]=2;c[b+56>>2]=0;p=0;i=e;return p|0}vf(b,-3,21400);p=-1;i=e;return p|0}vf(b,-3,21368);p=-1;i=e;return p|0}La=b+28|0;a[c[La>>2]|0]=31;c[b+36>>2]=1;Oa=La;Pa=c[o>>2]|0}else{Oa=b+28|0;Pa=v}c[b+48>>2]=c[b+12>>2];v=c[Oa>>2]|0;c[b+32>>2]=v;if((Pa|0)!=0){Oa=b+36|0;Kg(v+(c[Oa>>2]|0)|0,c[f>>2]|0,Pa|0)|0;c[Oa>>2]=(c[Oa>>2]|0)+(c[o>>2]|0);c[o>>2]=0}c[b+52>>2]=1;c[b+56>>2]=1;p=0;i=e;return p|0}function Af(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}if((c[a>>2]|0)!=7247){d=-2;i=b;return d|0}if((c[a+16>>2]|0)!=0){Mf(a+84|0)|0;hg(c[a+28>>2]|0);hg(c[a+24>>2]|0)}vf(a,0,0);hg(c[a+8>>2]|0);e=ib(c[a+4>>2]|0)|0;hg(a);d=((e|0)!=0)<<31>>31;i=b;return d|0}function Bf(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0;e=i;f=a+84|0;g=a+88|0;h=c[g>>2]|0;a:do{if((h|0)==0){j=a+76|0;if((c[j>>2]|0)==0){k=a+40|0;if((c[k>>2]|0)==0){l=a+24|0;m=c[l>>2]|0;n=c[a+16>>2]|0;c[g>>2]=0;o=a+4|0;p=0;while(1){q=Za(c[o>>2]|0,m+p|0,n-p|0)|0;if((q|0)<1){r=7;break}s=(c[g>>2]|0)+q|0;c[g>>2]=s;if(s>>>0>>0){p=s}else{t=s;break}}do{if((r|0)==7){if((q|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);u=-1;v=c[g>>2]|0;r=12;break a}else{c[k>>2]=1;t=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[l>>2];if((t|0)!=0){w=t;r=11}else{x=j;y=-1;r=14}}else{x=j;y=-1;r=14}}else{z=-1;r=13}}else{w=h;r=11}}while(0);if((r|0)==11){h=w+ -1|0;c[g>>2]=h;w=c[f>>2]|0;c[f>>2]=w+1;u=d[w]|0;v=h;r=12}if((r|0)==12){if((v|0)==0){z=u;r=13}else{A=u;B=v;r=25}}if((r|0)==13){x=a+76|0;y=z;r=14}b:do{if((r|0)==14){if((c[x>>2]|0)!=0){C=y+ -256|0;r=27;break}z=a+40|0;if((c[z>>2]|0)==0){v=a+24|0;u=c[v>>2]|0;h=c[a+16>>2]|0;c[g>>2]=0;w=a+4|0;t=0;while(1){D=Za(c[w>>2]|0,u+t|0,h-t|0)|0;if((D|0)<1){r=20;break}q=(c[g>>2]|0)+D|0;c[g>>2]=q;if(q>>>0>>0){t=q}else{E=q;break}}do{if((r|0)==20){if((D|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);F=y;G=-256;H=c[g>>2]|0;r=26;break b}else{c[z>>2]=1;E=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[v>>2];if((E|0)!=0){A=y;B=E;r=25;break}}I=x;J=y+ -256|0;r=28}}while(0);if((r|0)==25){y=B+ -1|0;c[g>>2]=y;B=c[f>>2]|0;c[f>>2]=B+1;F=A;G=(d[B]|0)<<8;H=y;r=26}if((r|0)==26){y=G+F|0;if((H|0)==0){C=y;r=27}else{K=H;L=y;r=39}}if((r|0)==27){I=a+76|0;J=C;r=28}c:do{if((r|0)==28){if((c[I>>2]|0)!=0){M=J+ -65536|0;r=41;break}C=a+40|0;if((c[C>>2]|0)==0){y=a+24|0;H=c[y>>2]|0;F=c[a+16>>2]|0;c[g>>2]=0;G=a+4|0;B=0;while(1){N=Za(c[G>>2]|0,H+B|0,F-B|0)|0;if((N|0)<1){r=34;break}A=(c[g>>2]|0)+N|0;c[g>>2]=A;if(A>>>0>>0){B=A}else{O=A;break}}do{if((r|0)==34){if((N|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);P=J;Q=-65536;R=c[g>>2]|0;r=40;break c}else{c[C>>2]=1;O=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[y>>2];if((O|0)!=0){K=O;L=J;r=39;break}}S=I;T=J+ -65536|0;r=42}}while(0);if((r|0)==39){J=K+ -1|0;c[g>>2]=J;K=c[f>>2]|0;c[f>>2]=K+1;P=L;Q=(d[K]|0)<<16;R=J;r=40}if((r|0)==40){J=Q+P|0;if((R|0)==0){M=J;r=41}else{U=R;V=J}}if((r|0)==41){S=a+76|0;T=M;r=42}if((r|0)==42){if((c[S>>2]|0)!=0){W=-1;i=e;return W|0}S=a+40|0;if((c[S>>2]|0)!=0){W=-1;i=e;return W|0}M=a+24|0;J=c[M>>2]|0;R=c[a+16>>2]|0;c[g>>2]=0;P=a+4|0;Q=0;while(1){X=Za(c[P>>2]|0,J+Q|0,R-Q|0)|0;if((X|0)<1){r=47;break}K=(c[g>>2]|0)+X|0;c[g>>2]=K;if(K>>>0>>0){Q=K}else{Y=K;break}}do{if((r|0)==47){if((X|0)>=0){c[S>>2]=1;Y=c[g>>2]|0;break}vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);W=-1;i=e;return W|0}}while(0);c[a+84>>2]=c[M>>2];if((Y|0)==0){W=-1;i=e;return W|0}else{U=Y;V=T}}c[g>>2]=U+ -1;U=c[f>>2]|0;c[f>>2]=U+1;c[b>>2]=((d[U]|0)<<24)+V;W=0;i=e;return W|0}function Cf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=i;if((a|0)==0){f=0;i=e;return f|0}g=a+84|0;if((c[a>>2]|0)!=31153){f=0;i=e;return f|0}if((c[a+76>>2]|0)!=0){f=0;i=e;return f|0}if((d|0)<0){vf(a,-5,21568);f=0;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}h=a+16|0;if((c[h>>2]|0)==0?(Df(a)|0)==-1:0){f=0;i=e;return f|0}j=a+72|0;a:do{if((c[j>>2]|0)!=0){c[j>>2]=0;k=c[a+68>>2]|0;l=a+88|0;if((c[l>>2]|0)!=0?(Ef(a,0)|0)==-1:0){f=0;i=e;return f|0}if((k|0)!=0){m=a+24|0;n=a+12|0;o=k;k=0;while(1){p=c[h>>2]|0;q=(p|0)<0|(p|0)>(o|0)?o:p;if(!k){Eg(c[m>>2]|0,0,q|0)|0}c[l>>2]=q;c[g>>2]=c[m>>2];c[n>>2]=(c[n>>2]|0)+q;if((Ef(a,0)|0)==-1){f=0;break}if((o|0)==(q|0)){break a}o=o-q|0;k=1}i=e;return f|0}}}while(0);j=a+88|0;b:do{if(!((c[h>>2]|0)>>>0>d>>>0)){if((c[j>>2]|0)!=0?(Ef(a,0)|0)==-1:0){f=0;i=e;return f|0}c[j>>2]=d;c[g>>2]=b;k=a+12|0;c[k>>2]=(c[k>>2]|0)+d;if((Ef(a,0)|0)==-1){f=0;i=e;return f|0}}else{k=a+24|0;o=a+12|0;n=b;m=d;while(1){l=c[j>>2]|0;if((l|0)==0){q=c[k>>2]|0;c[g>>2]=q;r=q}else{r=c[g>>2]|0}q=(c[h>>2]|0)-l|0;p=q>>>0>m>>>0?m:q;Kg(r+l|0,n|0,p|0)|0;c[j>>2]=(c[j>>2]|0)+p;c[o>>2]=(c[o>>2]|0)+p;if((m|0)==(p|0)){break b}if((Ef(a,0)|0)==-1){f=0;break}n=n+p|0;m=m-p|0}i=e;return f|0}}while(0);f=d;i=e;return f|0}function Df(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;b=i;d=a+20|0;e=c[d>>2]|0;f=gg(e)|0;g=a+24|0;c[g>>2]=f;h=gg(e)|0;e=a+28|0;c[e>>2]=h;j=(h|0)==0;if(!((f|0)==0|j)){c[a+116>>2]=0;c[a+120>>2]=0;c[a+124>>2]=0;if((hf(a+84|0,c[a+60>>2]|0,8,31,8,c[a+64>>2]|0,21664,56)|0)==0){k=c[d>>2]|0;c[a+16>>2]=k;c[a+100>>2]=k;k=c[e>>2]|0;c[a+96>>2]=k;c[a+32>>2]=k;l=0;i=b;return l|0}else{hg(c[g>>2]|0);vf(a,-4,21648);l=-1;i=b;return l|0}}if(j){m=f}else{hg(h);m=c[g>>2]|0}if((m|0)!=0){hg(m)}vf(a,-4,21648);l=-1;i=b;return l|0}function Ef(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;d=i;e=a+84|0;f=a+16|0;if((c[f>>2]|0)==0?(Df(a)|0)==-1:0){g=-1;i=d;return g|0}h=a+100|0;j=a+96|0;k=a+32|0;l=a+28|0;m=a+4|0;a:do{if((b|0)==4){n=c[h>>2]|0;o=0;while(1){if((n|0)==0|(o|0)==1){p=c[j>>2]|0;q=c[k>>2]|0;r=p-q|0;if((p|0)==(q|0)){s=n}else{p=Qa(c[m>>2]|0,q|0,r|0)|0;if(!((p|0)>-1&(p|0)==(r|0))){t=30;break a}s=c[h>>2]|0}if((s|0)==0){r=c[f>>2]|0;c[h>>2]=r;p=c[l>>2]|0;c[j>>2]=p;u=p;v=r}else{u=c[j>>2]|0;v=s}c[k>>2]=u;w=v}else{w=n}r=lf(e,4)|0;if((r|0)==-2){t=36;break a}p=c[h>>2]|0;if((w|0)==(p|0)){t=38;break}else{n=p;o=r}}}else if((b|0)==0){o=c[h>>2]|0;while(1){if((o|0)==0){n=c[j>>2]|0;r=c[k>>2]|0;p=n-r|0;if((n|0)!=(r|0)){n=Qa(c[m>>2]|0,r|0,p|0)|0;if(!((n|0)>-1&(n|0)==(p|0))){t=30;break a}p=c[h>>2]|0;if((p|0)!=0){x=c[j>>2]|0;y=p}else{t=10}}else{t=10}if((t|0)==10){t=0;p=c[f>>2]|0;c[h>>2]=p;n=c[l>>2]|0;c[j>>2]=n;x=n;y=p}c[k>>2]=x;z=y}else{z=o}if((lf(e,0)|0)==-2){t=36;break a}p=c[h>>2]|0;if((z|0)==(p|0)){t=38;break}else{o=p}}}else{o=c[h>>2]|0;while(1){if((o|0)!=0&(b|0)==0){A=o}else{p=c[j>>2]|0;n=c[k>>2]|0;r=p-n|0;if((p|0)==(n|0)){B=o}else{p=Qa(c[m>>2]|0,n|0,r|0)|0;if(!((p|0)>-1&(p|0)==(r|0))){t=30;break a}B=c[h>>2]|0}if((B|0)==0){r=c[f>>2]|0;c[h>>2]=r;p=c[l>>2]|0;c[j>>2]=p;C=p;D=r}else{C=c[j>>2]|0;D=B}c[k>>2]=C;A=D}if((lf(e,b)|0)==-2){t=36;break a}r=c[h>>2]|0;if((A|0)==(r|0)){t=38;break}else{o=r}}}}while(0);if((t|0)==30){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);g=-1;i=d;return g|0}else if((t|0)==36){vf(a,-2,21608);g=-1;i=d;return g|0}else if((t|0)==38){if((b|0)!=4){g=0;i=d;return g|0}kf(e)|0;g=0;i=d;return g|0}return 0}function Ff(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}if((c[a>>2]|0)!=31153){d=-2;i=b;return d|0}e=a+72|0;a:do{if((c[e>>2]|0)!=0){c[e>>2]=0;f=c[a+68>>2]|0;g=a+88|0;if((c[g>>2]|0)!=0?(Ef(a,0)|0)==-1:0){h=-1;break}if((f|0)!=0){j=a+16|0;k=a+24|0;l=a+84|0;m=a+12|0;n=f;f=0;while(1){o=c[j>>2]|0;p=(o|0)<0|(o|0)>(n|0)?n:o;if(!f){Eg(c[k>>2]|0,0,p|0)|0}c[g>>2]=p;c[l>>2]=c[k>>2];c[m>>2]=(c[m>>2]|0)+p;if((Ef(a,0)|0)==-1){h=-1;break a}if((n|0)==(p|0)){h=0;break}else{n=n-p|0;f=1}}}else{h=0}}else{h=0}}while(0);e=(Ef(a,4)|0)+h|0;jf(a+84|0)|0;hg(c[a+28>>2]|0);hg(c[a+24>>2]|0);vf(a,0,0);hg(c[a+8>>2]|0);h=ib(c[a+4>>2]|0)|0;hg(a);d=((e|0)!=(0-h|0))<<31>>31;i=b;return d|0}function Gf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0;g=i;h=c[e+28>>2]|0;j=c[e>>2]|0;k=e+4|0;l=j+((c[k>>2]|0)+ -6)|0;m=e+12|0;n=c[m>>2]|0;o=e+16|0;p=c[o>>2]|0;q=n+(p+ -258)|0;r=c[h+44>>2]|0;s=c[h+48>>2]|0;t=c[h+52>>2]|0;u=h+56|0;v=h+60|0;w=c[h+76>>2]|0;x=c[h+80>>2]|0;y=(1<>2])+ -1|0;z=(1<>2])+ -1|0;A=n+(p+~f)|0;f=h+7104|0;p=t+ -1|0;B=(s|0)==0;C=(c[h+40>>2]|0)+ -1|0;D=C+s|0;E=s+ -1|0;F=A+ -1|0;G=A-s|0;H=c[v>>2]|0;I=c[u>>2]|0;J=j+ -1|0;j=n+ -1|0;a:while(1){if(H>>>0<15){n=J+2|0;K=H+16|0;L=((d[J+1|0]|0)<>1]|0;P=d[w+(n<<2)+1|0]|0;n=L>>>P;Q=K-P|0;do{if(!(N<<24>>24==0)){R=N&255;S=Q;T=n;P=O;while(1){if((R&16|0)!=0){break}if((R&64|0)!=0){U=55;break a}V=(T&(1<>1]|0;Y=d[w+(V<<2)+1|0]|0;Z=T>>>Y;_=S-Y|0;if(W<<24>>24==0){U=6;break}else{R=W&255;S=_;T=Z;P=X}}if((U|0)==6){U=0;$=Z;aa=_;ba=X&255;U=7;break}W=P&65535;Y=R&15;if((Y|0)==0){ca=S;da=T;ea=M;fa=W}else{if(S>>>0>>0){V=M+1|0;ga=S+8|0;ha=((d[V]|0)<>>Y;ea=ia;fa=(ha&(1<>>0<15){W=ea+2|0;ja=ca+16|0;ka=((d[ea+1|0]|0)<>1]|0;V=d[x+(W<<2)+1|0]|0;ma=ka>>>V;na=ja-V|0;V=d[x+(W<<2)|0]|0;if((V&16|0)==0){W=V;oa=ma;pa=na;qa=Y;while(1){if((W&64|0)!=0){U=52;break a}ra=(oa&(1<>1]|0;ta=d[x+(ra<<2)+1|0]|0;ua=oa>>>ta;va=pa-ta|0;ta=d[x+(ra<<2)|0]|0;if((ta&16|0)==0){W=ta;oa=ua;pa=va;qa=sa}else{wa=ua;xa=va;ya=ta;za=sa;break}}}else{wa=ma;xa=na;ya=V;za=Y}qa=za&65535;W=ya&15;if(xa>>>0>>0){P=la+1|0;sa=((d[P]|0)<>>0>>0){va=la+2|0;Aa=xa+16|0;Ba=((d[va]|0)<>>W;Ea=Aa-W|0;W=j;qa=W-A|0;if(!(P>>>0>qa>>>0)){sa=j+(0-P)|0;ta=fa;va=j;while(1){a[va+1|0]=a[sa+1|0]|0;a[va+2|0]=a[sa+2|0]|0;ua=sa+3|0;Fa=va+3|0;a[Fa]=a[ua]|0;ta=ta+ -3|0;if(!(ta>>>0>2)){break}else{sa=ua;va=Fa}}if((ta|0)==0){Ga=Ea;Ha=Da;Ia=Ca;Ja=Fa;break}Y=va+4|0;a[Y]=a[sa+4|0]|0;if(!(ta>>>0>1)){Ga=Ea;Ha=Da;Ia=Ca;Ja=Y;break}Y=va+5|0;a[Y]=a[sa+5|0]|0;Ga=Ea;Ha=Da;Ia=Ca;Ja=Y;break}Y=P-qa|0;if(Y>>>0>r>>>0?(c[f>>2]|0)!=0:0){U=22;break a}do{if(B){V=t+(C-Y)|0;if(Y>>>0>>0){na=fa-Y|0;ma=P-W|0;ua=V;ra=Y;Ka=j;do{ua=ua+1|0;Ka=Ka+1|0;a[Ka]=a[ua]|0;ra=ra+ -1|0}while((ra|0)!=0);La=j+(F+ma+(1-P))|0;Ma=na;Na=j+(A+ma)|0}else{La=V;Ma=fa;Na=j}}else{if(!(s>>>0>>0)){ra=t+(E-Y)|0;if(!(Y>>>0>>0)){La=ra;Ma=fa;Na=j;break}ua=fa-Y|0;Ka=P-W|0;Oa=ra;ra=Y;Pa=j;do{Oa=Oa+1|0;Pa=Pa+1|0;a[Pa]=a[Oa]|0;ra=ra+ -1|0}while((ra|0)!=0);La=j+(F+Ka+(1-P))|0;Ma=ua;Na=j+(A+Ka)|0;break}ra=t+(D-Y)|0;Oa=Y-s|0;if(Oa>>>0>>0){Pa=fa-Oa|0;V=P-W|0;ma=ra;na=Oa;Oa=j;do{ma=ma+1|0;Oa=Oa+1|0;a[Oa]=a[ma]|0;na=na+ -1|0}while((na|0)!=0);na=j+(G+V)|0;if(s>>>0>>0){ma=Pa-s|0;Oa=p;Ka=s;ua=na;do{Oa=Oa+1|0;ua=ua+1|0;a[ua]=a[Oa]|0;Ka=Ka+ -1|0}while((Ka|0)!=0);La=j+(F+V+(1-P))|0;Ma=ma;Na=j+(A+V)|0}else{La=p;Ma=Pa;Na=na}}else{La=ra;Ma=fa;Na=j}}}while(0);if(Ma>>>0>2){P=La;W=Ma;Y=Na;while(1){a[Y+1|0]=a[P+1|0]|0;a[Y+2|0]=a[P+2|0]|0;qa=P+3|0;sa=Y+3|0;a[sa]=a[qa]|0;va=W+ -3|0;if(va>>>0>2){P=qa;W=va;Y=sa}else{Qa=qa;Ra=va;Sa=sa;break}}}else{Qa=La;Ra=Ma;Sa=Na}if((Ra|0)!=0){Y=Sa+1|0;a[Y]=a[Qa+1|0]|0;if(Ra>>>0>1){W=Sa+2|0;a[W]=a[Qa+2|0]|0;Ga=Ea;Ha=Da;Ia=Ca;Ja=W}else{Ga=Ea;Ha=Da;Ia=Ca;Ja=Y}}else{Ga=Ea;Ha=Da;Ia=Ca;Ja=Sa}}else{$=n;aa=Q;ba=O&255;U=7}}while(0);if((U|0)==7){U=0;O=j+1|0;a[O]=ba;Ga=aa;Ha=$;Ia=M;Ja=O}if(Ia>>>0>>0&Ja>>>0>>0){H=Ga;I=Ha;J=Ia;j=Ja}else{Ta=Ga;Ua=Ha;Va=Ia;Wa=Ja;break}}do{if((U|0)==22){c[e+24>>2]=21672;c[h>>2]=29;Ta=Ea;Ua=Da;Va=Ca;Wa=j}else if((U|0)==52){c[e+24>>2]=21704;c[h>>2]=29;Ta=pa;Ua=oa;Va=la;Wa=j}else if((U|0)==55){if((R&32|0)==0){c[e+24>>2]=21728;c[h>>2]=29;Ta=S;Ua=T;Va=M;Wa=j;break}else{c[h>>2]=11;Ta=S;Ua=T;Va=M;Wa=j;break}}}while(0);j=Ta>>>3;M=Va+(0-j)|0;T=Ta-(j<<3)|0;Ta=(1<>2]=Va+(1-j);c[m>>2]=Wa+1;if(M>>>0>>0){Xa=l-M|0}else{Xa=l-M|0}c[k>>2]=Xa+5;if(Wa>>>0>>0){Ya=q-Wa|0;Za=Ya+257|0;c[o>>2]=Za;c[u>>2]=Ta;c[v>>2]=T;i=g;return}else{Ya=q-Wa|0;Za=Ya+257|0;c[o>>2]=Za;c[u>>2]=Ta;c[v>>2]=T;i=g;return}}function Hf(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=c[a+28>>2]|0;if((e|0)==0){d=-2;i=b;return d|0}c[e+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[e>>2]=0;c[e+4>>2]=0;c[e+12>>2]=0;c[e+20>>2]=32768;c[e+32>>2]=0;c[e+40>>2]=0;c[e+44>>2]=0;c[e+48>>2]=0;c[e+56>>2]=0;c[e+60>>2]=0;a=e+1328|0;c[e+108>>2]=a;c[e+80>>2]=a;c[e+76>>2]=a;c[e+7104>>2]=1;c[e+7108>>2]=-1;d=0;i=b;return d|0}function If(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;if((a|0)==0){e=-2;i=d;return e|0}f=a+28|0;g=c[f>>2]|0;if((g|0)==0){e=-2;i=d;return e|0}if((b|0)<0){h=0-b|0;j=0}else{h=(b|0)<48?b&15:b;j=(b>>4)+1|0}if((h|0)!=0&(h+ -8|0)>>>0>7){e=-2;i=d;return e|0}b=g+52|0;k=c[b>>2]|0;l=g+36|0;if((k|0)!=0?(c[l>>2]|0)!=(h|0):0){mb[c[a+36>>2]&1](c[a+40>>2]|0,k);c[b>>2]=0}c[g+8>>2]=j;c[l>>2]=h;h=c[f>>2]|0;if((h|0)==0){e=-2;i=d;return e|0}c[h+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[h>>2]=0;c[h+4>>2]=0;c[h+12>>2]=0;c[h+20>>2]=32768;c[h+32>>2]=0;c[h+40>>2]=0;c[h+44>>2]=0;c[h+48>>2]=0;c[h+56>>2]=0;c[h+60>>2]=0;a=h+1328|0;c[h+108>>2]=a;c[h+80>>2]=a;c[h+76>>2]=a;c[h+7104>>2]=1;c[h+7108>>2]=-1;e=0;i=d;return e|0}function Jf(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0;g=i;if((e|0)==0){h=-6;i=g;return h|0}if(!((a[e]|0)==49&(f|0)==56)){h=-6;i=g;return h|0}if((b|0)==0){h=-2;i=g;return h|0}c[b+24>>2]=0;f=b+32|0;e=c[f>>2]|0;if((e|0)==0){c[f>>2]=1;c[b+40>>2]=0;j=1}else{j=e}e=b+36|0;if((c[e>>2]|0)==0){c[e>>2]=1}f=b+40|0;k=kb[j&1](c[f>>2]|0,1,7116)|0;if((k|0)==0){h=-4;i=g;return h|0}j=b+28|0;c[j>>2]=k;c[k+52>>2]=0;l=If(b,d)|0;if((l|0)==0){h=0;i=g;return h|0}mb[c[e>>2]&1](c[f>>2]|0,k);c[j>>2]=0;h=l;i=g;return h|0}function Kf(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,fb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0,sc=0,tc=0,uc=0,vc=0,wc=0,xc=0,yc=0,zc=0,Ac=0,Bc=0,Cc=0,Dc=0,Ec=0,Fc=0,Gc=0,Hc=0,Ic=0,Jc=0,Kc=0,Lc=0,Mc=0,Nc=0,Oc=0,Pc=0,Qc=0,Rc=0,Sc=0,Tc=0,Uc=0,Vc=0,Wc=0,Xc=0,Yc=0,Zc=0,_c=0,$c=0,ad=0,bd=0,cd=0,dd=0,ed=0,fd=0,gd=0,hd=0,id=0,jd=0,kd=0,ld=0,md=0,nd=0,od=0,pd=0,qd=0,rd=0,sd=0,td=0,ud=0,vd=0,wd=0,xd=0,yd=0,zd=0,Ad=0,Bd=0,Cd=0,Dd=0,Ed=0,Fd=0,Gd=0,Hd=0,Id=0,Jd=0,Kd=0,Ld=0,Md=0,Nd=0,Od=0,Pd=0,Qd=0,Rd=0,Sd=0,Td=0,Ud=0,Vd=0,Wd=0,Xd=0,Yd=0,Zd=0,_d=0,$d=0,ae=0,be=0,ce=0,de=0,ee=0,fe=0,ge=0,he=0,ie=0,je=0,ke=0,le=0,me=0,ne=0,oe=0,pe=0,qe=0,re=0,se=0,te=0,ue=0,ve=0,we=0,xe=0,ye=0,ze=0,Ae=0,Be=0,Ce=0,De=0,Ee=0,Fe=0,Ge=0,He=0,Ie=0,Je=0,Ke=0,Le=0,Me=0,Ne=0,Oe=0,Pe=0,Qe=0,Re=0,Se=0,Te=0,Ue=0,Ve=0,We=0,Xe=0,Ye=0,Ze=0,_e=0,$e=0,af=0,bf=0,cf=0,df=0,ef=0,hf=0,jf=0,kf=0,lf=0,mf=0,nf=0,of=0,pf=0,qf=0,rf=0,sf=0,tf=0,uf=0,vf=0,wf=0,xf=0,yf=0,zf=0,Af=0,Bf=0,Cf=0,Df=0,Ef=0,Ff=0,Hf=0,If=0,Jf=0,Kf=0,Mf=0,Of=0,Pf=0,Qf=0,Rf=0,Sf=0,Tf=0,Uf=0,Vf=0,Wf=0,Xf=0,Yf=0,Zf=0,_f=0,$f=0,ag=0,bg=0,cg=0,dg=0,eg=0,fg=0,gg=0,hg=0,ig=0,jg=0,kg=0,lg=0,mg=0,ng=0,og=0,pg=0,qg=0,rg=0,sg=0,tg=0,ug=0,vg=0,wg=0,xg=0,yg=0,zg=0,Ag=0,Bg=0,Cg=0,Dg=0,Eg=0,Fg=0,Gg=0,Hg=0,Ig=0,Jg=0;h=i;i=i+16|0;j=h;if((f|0)==0){k=-2;i=h;return k|0}l=c[f+28>>2]|0;if((l|0)==0){k=-2;i=h;return k|0}m=f+12|0;n=c[m>>2]|0;if((n|0)==0){k=-2;i=h;return k|0}o=c[f>>2]|0;if((o|0)==0?(c[f+4>>2]|0)!=0:0){k=-2;i=h;return k|0}p=c[l>>2]|0;if((p|0)==11){c[l>>2]=12;q=12;r=c[f>>2]|0;s=c[m>>2]|0}else{q=p;r=o;s=n}n=f+16|0;o=c[n>>2]|0;p=f+4|0;t=c[p>>2]|0;u=l+56|0;v=l+60|0;w=l+8|0;x=l+24|0;y=j+1|0;z=l+16|0;A=l+32|0;B=f+24|0;C=l+36|0;D=l+20|0;E=f+48|0;F=l+64|0;G=l+12|0;H=(g+ -5|0)>>>0<2;I=l+4|0;J=l+76|0;K=l+84|0;L=l+80|0;M=l+88|0;N=(g|0)==6;O=l+7108|0;P=l+72|0;Q=l+7112|0;R=l+68|0;S=l+44|0;T=l+7104|0;U=l+48|0;V=l+52|0;W=l+40|0;X=f+20|0;Y=l+28|0;Z=l+96|0;_=l+100|0;$=l+92|0;aa=l+104|0;ba=l+1328|0;ca=l+108|0;da=l+112|0;ea=l+752|0;fa=l+624|0;ga=j+2|0;ha=j+3|0;ia=q;q=c[v>>2]|0;ja=t;ka=c[u>>2]|0;la=o;ma=r;r=o;o=s;s=0;a:while(1){b:do{switch(ia|0){case 28:{na=q;oa=ja;pa=ka;qa=la;ra=ma;sa=1;ta=285;break a;break};case 16:{if(q>>>0<14){ua=q;va=ja;wa=ka;xa=ma;while(1){if((va|0)==0){ya=ua;za=0;Aa=wa;Ba=la;Ca=xa;Da=r;Ea=s;break a}Ga=va+ -1|0;Ha=xa+1|0;Ia=(d[xa]<>>0<14){ua=Ja;va=Ga;wa=Ia;xa=Ha}else{Ka=Ja;La=Ga;Ma=Ia;Na=Ha;break}}}else{Ka=q;La=ja;Ma=ka;Na=ma}xa=(Ma&31)+257|0;c[Z>>2]=xa;wa=(Ma>>>5&31)+1|0;c[_>>2]=wa;c[$>>2]=(Ma>>>10&15)+4;va=Ma>>>14;ua=Ka+ -14|0;if(xa>>>0>286|wa>>>0>30){c[B>>2]=21992;c[l>>2]=29;Oa=ua;Pa=La;Qa=va;Ra=la;Sa=Na;Ta=r;Ua=o;Va=s;break b}else{c[aa>>2]=0;c[l>>2]=17;Wa=0;Xa=ua;Ya=La;Za=va;_a=Na;ta=154;break b}break};case 21:{$a=c[P>>2]|0;ab=q;bb=ja;cb=ka;db=ma;eb=s;ta=221;break};case 23:{fb=c[P>>2]|0;gb=q;hb=ja;ib=ka;jb=ma;kb=s;ta=240;break};case 1:{if(q>>>0<16){va=q;ua=ja;wa=ka;xa=ma;while(1){if((ua|0)==0){ya=va;za=0;Aa=wa;Ba=la;Ca=xa;Da=r;Ea=s;break a}Ha=ua+ -1|0;Ia=xa+1|0;Ga=(d[xa]<>>0<16){va=Ja;ua=Ha;wa=Ga;xa=Ia}else{lb=Ja;mb=Ha;nb=Ga;ob=Ia;break}}}else{lb=q;mb=ja;nb=ka;ob=ma}c[z>>2]=nb;if((nb&255|0)!=8){c[B>>2]=21824;c[l>>2]=29;Oa=lb;Pa=mb;Qa=nb;Ra=la;Sa=ob;Ta=r;Ua=o;Va=s;break b}if((nb&57344|0)!=0){c[B>>2]=21880;c[l>>2]=29;Oa=lb;Pa=mb;Qa=nb;Ra=la;Sa=ob;Ta=r;Ua=o;Va=s;break b}xa=c[A>>2]|0;if((xa|0)==0){pb=nb}else{c[xa>>2]=nb>>>8&1;pb=c[z>>2]|0}if((pb&512|0)!=0){a[j]=nb;a[y]=nb>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0}c[l>>2]=2;qb=0;rb=mb;sb=0;tb=ob;ta=47;break};case 22:{ub=q;vb=ja;wb=ka;xb=ma;yb=s;ta=228;break};case 10:{zb=q;Ab=ja;Bb=ka;Cb=ma;ta=121;break};case 7:{Db=q;Eb=ja;Fb=ka;Gb=ma;ta=96;break};case 5:{Hb=q;Ib=ja;Jb=ka;Kb=ma;ta=73;break};case 8:{Lb=q;Mb=ja;Nb=ka;Ob=ma;ta=109;break};case 11:{Pb=q;Qb=ja;Rb=ka;Sb=ma;ta=124;break};case 12:{Tb=q;Ub=ja;Vb=ka;Wb=ma;ta=125;break};case 13:{xa=q&7;wa=ka>>>xa;ua=q-xa|0;if(ua>>>0<32){xa=ua;va=ja;Ia=wa;Ga=ma;while(1){if((va|0)==0){ya=xa;za=0;Aa=Ia;Ba=la;Ca=Ga;Da=r;Ea=s;break a}Ha=va+ -1|0;Ja=Ga+1|0;Xb=(d[Ga]<>>0<32){xa=Yb;va=Ha;Ia=Xb;Ga=Ja}else{Zb=Yb;_b=Ha;$b=Xb;ac=Ja;break}}}else{Zb=ua;_b=ja;$b=wa;ac=ma}Ga=$b&65535;if((Ga|0)==($b>>>16^65535|0)){c[F>>2]=Ga;c[l>>2]=14;if(N){na=0;oa=_b;pa=0;qa=la;ra=ac;sa=s;ta=285;break a}else{bc=0;cc=_b;dc=0;ec=ac;ta=143;break b}}else{c[B>>2]=21960;c[l>>2]=29;Oa=Zb;Pa=_b;Qa=$b;Ra=la;Sa=ac;Ta=r;Ua=o;Va=s;break b}break};case 14:{bc=q;cc=ja;dc=ka;ec=ma;ta=143;break};case 15:{fc=q;gc=ja;hc=ka;ic=ma;ta=144;break};case 17:{Ga=c[aa>>2]|0;if(Ga>>>0<(c[$>>2]|0)>>>0){Wa=Ga;Xa=q;Ya=ja;Za=ka;_a=ma;ta=154}else{jc=Ga;kc=q;lc=ja;mc=ka;nc=ma;ta=158}break};case 0:{Ga=c[w>>2]|0;if((Ga|0)==0){c[l>>2]=12;Oa=q;Pa=ja;Qa=ka;Ra=la;Sa=ma;Ta=r;Ua=o;Va=s;break b}if(q>>>0<16){Ia=q;va=ja;xa=ka;Ja=ma;while(1){if((va|0)==0){ya=Ia;za=0;Aa=xa;Ba=la;Ca=Ja;Da=r;Ea=s;break a}Xb=va+ -1|0;Ha=Ja+1|0;Yb=(d[Ja]<>>0<16){Ia=oc;va=Xb;xa=Yb;Ja=Ha}else{pc=oc;qc=Xb;rc=Yb;sc=Ha;break}}}else{pc=q;qc=ja;rc=ka;sc=ma}if((Ga&2|0)!=0&(rc|0)==35615){c[x>>2]=gf(0,0,0)|0;a[j]=31;a[y]=-117;c[x>>2]=gf(c[x>>2]|0,j,2)|0;c[l>>2]=1;Oa=0;Pa=qc;Qa=0;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}c[z>>2]=0;Ja=c[A>>2]|0;if((Ja|0)==0){tc=Ga}else{c[Ja+48>>2]=-1;tc=c[w>>2]|0}if((tc&1|0)!=0?((((rc<<8&65280)+(rc>>>8)|0)>>>0)%31|0|0)==0:0){if((rc&15|0)!=8){c[B>>2]=21824;c[l>>2]=29;Oa=pc;Pa=qc;Qa=rc;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}Ja=rc>>>4;xa=pc+ -4|0;va=(Ja&15)+8|0;Ia=c[C>>2]|0;if((Ia|0)!=0){if(va>>>0>Ia>>>0){c[B>>2]=21856;c[l>>2]=29;Oa=xa;Pa=qc;Qa=Ja;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}}else{c[C>>2]=va}c[D>>2]=1<>2]=va;c[E>>2]=va;c[l>>2]=rc>>>12&2^11;Oa=0;Pa=qc;Qa=0;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}c[B>>2]=21800;c[l>>2]=29;Oa=pc;Pa=qc;Qa=rc;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break};case 24:{uc=q;vc=ja;wc=ka;xc=ma;yc=s;ta=246;break};case 9:{if(q>>>0<32){va=q;Ja=ja;xa=ka;Ia=ma;while(1){if((Ja|0)==0){ya=va;za=0;Aa=xa;Ba=la;Ca=Ia;Da=r;Ea=s;break a}wa=Ja+ -1|0;ua=Ia+1|0;Ha=(d[Ia]<>>0<32){va=Yb;Ja=wa;xa=Ha;Ia=ua}else{zc=wa;Ac=Ha;Bc=ua;break}}}else{zc=ja;Ac=ka;Bc=ma}Ia=Fa(Ac|0)|0;c[x>>2]=Ia;c[E>>2]=Ia;c[l>>2]=10;zb=0;Ab=zc;Bb=0;Cb=Bc;ta=121;break};case 30:{ta=299;break a;break};case 18:{Cc=c[aa>>2]|0;Dc=q;Ec=ja;Fc=ka;Gc=ma;Hc=s;ta=164;break};case 6:{Ic=q;Jc=ja;Kc=ka;Lc=ma;ta=83;break};case 29:{ya=q;za=ja;Aa=ka;Ba=la;Ca=ma;Da=r;Ea=-3;break a;break};case 19:{Mc=q;Nc=ja;Oc=ka;Pc=ma;Qc=s;ta=201;break};case 20:{Rc=q;Sc=ja;Tc=ka;Uc=ma;Vc=s;ta=202;break};case 25:{if((la|0)==0){na=q;oa=ja;pa=ka;qa=0;ra=ma;sa=s;ta=285;break a}a[o]=c[F>>2];c[l>>2]=20;Oa=q;Pa=ja;Qa=ka;Ra=la+ -1|0;Sa=ma;Ta=r;Ua=o+1|0;Va=s;break};case 26:{if((c[w>>2]|0)!=0){if(q>>>0<32){Ia=q;xa=ja;Ja=ka;va=ma;while(1){if((xa|0)==0){ya=Ia;za=0;Aa=Ja;Ba=la;Ca=va;Da=r;Ea=s;break a}Ga=xa+ -1|0;ua=va+1|0;Ha=(d[va]<>>0<32){Ia=wa;xa=Ga;Ja=Ha;va=ua}else{Wc=wa;Xc=Ga;Yc=Ha;Zc=ua;break}}}else{Wc=q;Xc=ja;Yc=ka;Zc=ma}va=r-la|0;c[X>>2]=(c[X>>2]|0)+va;c[Y>>2]=(c[Y>>2]|0)+va;if((r|0)!=(la|0)){Ja=c[x>>2]|0;xa=o+(0-va)|0;if((c[z>>2]|0)==0){_c=ff(Ja,xa,va)|0}else{_c=gf(Ja,xa,va)|0}c[x>>2]=_c;c[E>>2]=_c}if((c[z>>2]|0)==0){$c=Fa(Yc|0)|0}else{$c=Yc}if(($c|0)==(c[x>>2]|0)){ad=0;bd=Xc;cd=0;dd=Zc;ed=la}else{c[B>>2]=22280;c[l>>2]=29;Oa=Wc;Pa=Xc;Qa=Yc;Ra=la;Sa=Zc;Ta=la;Ua=o;Va=s;break b}}else{ad=q;bd=ja;cd=ka;dd=ma;ed=r}c[l>>2]=27;fd=ad;gd=bd;hd=cd;id=dd;jd=ed;ta=277;break};case 27:{fd=q;gd=ja;hd=ka;id=ma;jd=r;ta=277;break};case 2:{if(q>>>0<32){qb=q;rb=ja;sb=ka;tb=ma;ta=47}else{kd=ja;ld=ka;md=ma;ta=49}break};case 4:{nd=q;od=ja;pd=ka;qd=ma;ta=62;break};case 3:{if(q>>>0<16){rd=q;sd=ja;td=ka;ud=ma;ta=55}else{vd=ja;wd=ka;xd=ma;ta=57}break};default:{k=-2;ta=300;break a}}}while(0);if((ta|0)==47){while(1){ta=0;if((rb|0)==0){ya=qb;za=0;Aa=sb;Ba=la;Ca=tb;Da=r;Ea=s;break a}va=rb+ -1|0;xa=tb+1|0;Ja=(d[tb]<>>0<32){qb=Ia;rb=va;sb=Ja;tb=xa;ta=47}else{kd=va;ld=Ja;md=xa;ta=49;break}}}else if((ta|0)==121){ta=0;if((c[G>>2]|0)==0){ta=122;break}xa=ff(0,0,0)|0;c[x>>2]=xa;c[E>>2]=xa;c[l>>2]=11;Pb=zb;Qb=Ab;Rb=Bb;Sb=Cb;ta=124}else if((ta|0)==143){ta=0;c[l>>2]=15;fc=bc;gc=cc;hc=dc;ic=ec;ta=144}else if((ta|0)==154){while(1){ta=0;if(Xa>>>0<3){xa=Xa;Ja=Ya;va=Za;Ia=_a;while(1){if((Ja|0)==0){ya=xa;za=0;Aa=va;Ba=la;Ca=Ia;Da=r;Ea=s;break a}ua=Ja+ -1|0;Ha=Ia+1|0;Ga=(d[Ia]<>>0<3){xa=wa;Ja=ua;va=Ga;Ia=Ha}else{yd=wa;zd=ua;Ad=Ga;Bd=Ha;break}}}else{yd=Xa;zd=Ya;Ad=Za;Bd=_a}c[aa>>2]=Wa+1;b[l+(e[21760+(Wa<<1)>>1]<<1)+112>>1]=Ad&7;Ia=Ad>>>3;va=yd+ -3|0;Ja=c[aa>>2]|0;if(Ja>>>0<(c[$>>2]|0)>>>0){Wa=Ja;Xa=va;Ya=zd;Za=Ia;_a=Bd;ta=154}else{jc=Ja;kc=va;lc=zd;mc=Ia;nc=Bd;ta=158;break}}}else if((ta|0)==277){ta=0;if((c[w>>2]|0)==0){Cd=fd;Dd=gd;Ed=hd;Fd=id;ta=284;break}if((c[z>>2]|0)==0){Cd=fd;Dd=gd;Ed=hd;Fd=id;ta=284;break}if(fd>>>0<32){Ia=fd;va=gd;Ja=hd;xa=id;while(1){if((va|0)==0){ya=Ia;za=0;Aa=Ja;Ba=la;Ca=xa;Da=jd;Ea=s;break a}Ha=va+ -1|0;Ga=xa+1|0;ua=(d[xa]<>>0<32){Ia=wa;va=Ha;Ja=ua;xa=Ga}else{Gd=wa;Hd=Ha;Id=ua;Jd=Ga;break}}}else{Gd=fd;Hd=gd;Id=hd;Jd=id}if((Id|0)==(c[Y>>2]|0)){Cd=0;Dd=Hd;Ed=0;Fd=Jd;ta=284;break}c[B>>2]=22304;c[l>>2]=29;Oa=Gd;Pa=Hd;Qa=Id;Ra=la;Sa=Jd;Ta=jd;Ua=o;Va=s}do{if((ta|0)==49){ta=0;xa=c[A>>2]|0;if((xa|0)!=0){c[xa+4>>2]=ld}if((c[z>>2]&512|0)!=0){a[j]=ld;a[y]=ld>>>8;a[ga]=ld>>>16;a[ha]=ld>>>24;c[x>>2]=gf(c[x>>2]|0,j,4)|0}c[l>>2]=3;rd=0;sd=kd;td=0;ud=md;ta=55}else if((ta|0)==124){ta=0;if(H){na=Pb;oa=Qb;pa=Rb;qa=la;ra=Sb;sa=s;ta=285;break a}else{Tb=Pb;Ub=Qb;Vb=Rb;Wb=Sb;ta=125}}else if((ta|0)==144){ta=0;xa=c[F>>2]|0;if((xa|0)==0){c[l>>2]=11;Oa=fc;Pa=gc;Qa=hc;Ra=la;Sa=ic;Ta=r;Ua=o;Va=s;break}Ja=xa>>>0>gc>>>0?gc:xa;xa=Ja>>>0>la>>>0?la:Ja;if((xa|0)==0){na=fc;oa=gc;pa=hc;qa=la;ra=ic;sa=s;ta=285;break a}Kg(o|0,ic|0,xa|0)|0;c[F>>2]=(c[F>>2]|0)-xa;Oa=fc;Pa=gc-xa|0;Qa=hc;Ra=la-xa|0;Sa=ic+xa|0;Ta=r;Ua=o+xa|0;Va=s}else if((ta|0)==158){ta=0;if(jc>>>0<19){xa=jc;while(1){Ja=xa+1|0;b[l+(e[21760+(xa<<1)>>1]<<1)+112>>1]=0;if((Ja|0)==19){break}else{xa=Ja}}c[aa>>2]=19}c[ca>>2]=ba;c[J>>2]=ba;c[K>>2]=7;xa=Nf(0,da,19,ca,K,ea)|0;if((xa|0)==0){c[aa>>2]=0;c[l>>2]=18;Cc=0;Dc=kc;Ec=lc;Fc=mc;Gc=nc;Hc=0;ta=164;break}else{c[B>>2]=22032;c[l>>2]=29;Oa=kc;Pa=lc;Qa=mc;Ra=la;Sa=nc;Ta=r;Ua=o;Va=xa;break}}}while(0);c:do{if((ta|0)==55){while(1){ta=0;if((sd|0)==0){ya=rd;za=0;Aa=td;Ba=la;Ca=ud;Da=r;Ea=s;break a}xa=sd+ -1|0;Ja=ud+1|0;va=(d[ud]<>>0<16){rd=Ia;sd=xa;td=va;ud=Ja;ta=55}else{vd=xa;wd=va;xd=Ja;ta=57;break}}}else if((ta|0)==125){ta=0;if((c[I>>2]|0)!=0){Ja=Tb&7;c[l>>2]=26;Oa=Tb-Ja|0;Pa=Ub;Qa=Vb>>>Ja;Ra=la;Sa=Wb;Ta=r;Ua=o;Va=s;break}if(Tb>>>0<3){Ja=Tb;va=Ub;xa=Vb;Ia=Wb;while(1){if((va|0)==0){ya=Ja;za=0;Aa=xa;Ba=la;Ca=Ia;Da=r;Ea=s;break a}Ga=va+ -1|0;ua=Ia+1|0;Ha=(d[Ia]<>>0<3){Ja=wa;va=Ga;xa=Ha;Ia=ua}else{Kd=wa;Ld=Ga;Md=Ha;Nd=ua;break}}}else{Kd=Tb;Ld=Ub;Md=Vb;Nd=Wb}c[I>>2]=Md&1;Ia=Md>>>1&3;if((Ia|0)==0){c[l>>2]=13}else if((Ia|0)==1){c[J>>2]=22328;c[K>>2]=9;c[L>>2]=24376;c[M>>2]=5;c[l>>2]=19;if(N){ta=133;break a}}else if((Ia|0)==2){c[l>>2]=16}else if((Ia|0)==3){c[B>>2]=21936;c[l>>2]=29}Oa=Kd+ -3|0;Pa=Ld;Qa=Md>>>3;Ra=la;Sa=Nd;Ta=r;Ua=o;Va=s}else if((ta|0)==164){ta=0;Ia=c[Z>>2]|0;xa=c[_>>2]|0;do{if(Cc>>>0<(xa+Ia|0)>>>0){va=Cc;Ja=xa;ua=Ia;Ha=Dc;Ga=Ec;wa=Fc;Yb=Gc;d:while(1){Xb=(1<>2])+ -1|0;oc=Xb&wa;Od=c[J>>2]|0;Pd=d[Od+(oc<<2)+1|0]|0;if(Pd>>>0>Ha>>>0){Qd=Ha;Rd=Ga;Sd=wa;Td=Yb;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Td;Da=r;Ea=Hc;break a}Ud=Rd+ -1|0;Vd=Td+1|0;Wd=(d[Td]<>>0>Xd>>>0){Qd=Xd;Rd=Ud;Sd=Wd;Td=Vd}else{_d=Zd;$d=Yd;ae=Xd;be=Ud;ce=Wd;de=Vd;break}}}else{_d=Pd;$d=oc;ae=Ha;be=Ga;ce=wa;de=Yb}Td=b[Od+($d<<2)+2>>1]|0;e:do{if((Td&65535)<16){if(ae>>>0<_d>>>0){Sd=ae;Rd=be;Qd=ce;Xb=de;while(1){if((Rd|0)==0){ya=Sd;za=0;Aa=Qd;Ba=la;Ca=Xb;Da=r;Ea=Hc;break a}Vd=Rd+ -1|0;Wd=Xb+1|0;Ud=(d[Xb]<>>0<_d>>>0){Sd=Xd;Rd=Vd;Qd=Ud;Xb=Wd}else{ee=Xd;fe=Vd;ge=Ud;he=Wd;break}}}else{ee=ae;fe=be;ge=ce;he=de}c[aa>>2]=va+1;b[l+(va<<1)+112>>1]=Td;ie=ee-_d|0;je=fe;ke=ge>>>_d;le=he}else{if(Td<<16>>16==16){Xb=_d+2|0;if(ae>>>0>>0){Qd=ae;Rd=be;Sd=ce;Wd=de;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Wd;Da=r;Ea=Hc;break a}Ud=Rd+ -1|0;Vd=Wd+1|0;Xd=(d[Wd]<>>0>>0){Qd=Yd;Rd=Ud;Sd=Xd;Wd=Vd}else{me=Yd;ne=Ud;oe=Xd;pe=Vd;break}}}else{me=ae;ne=be;oe=ce;pe=de}qe=oe>>>_d;re=me-_d|0;if((va|0)==0){ta=181;break d}se=re+ -2|0;te=(qe&3)+3|0;ue=ne;ve=qe>>>2;we=b[l+(va+ -1<<1)+112>>1]|0;xe=pe}else if(Td<<16>>16==17){Wd=_d+3|0;if(ae>>>0>>0){Sd=ae;Rd=be;Qd=ce;Xb=de;while(1){if((Rd|0)==0){ya=Sd;za=0;Aa=Qd;Ba=la;Ca=Xb;Da=r;Ea=Hc;break a}Vd=Rd+ -1|0;Xd=Xb+1|0;Ud=(d[Xb]<>>0>>0){Sd=Yd;Rd=Vd;Qd=Ud;Xb=Xd}else{ye=Yd;ze=Vd;Ae=Ud;Be=Xd;break}}}else{ye=ae;ze=be;Ae=ce;Be=de}Xb=Ae>>>_d;se=-3-_d+ye|0;te=(Xb&7)+3|0;ue=ze;ve=Xb>>>3;we=0;xe=Be}else{Xb=_d+7|0;if(ae>>>0>>0){Qd=ae;Rd=be;Sd=ce;Wd=de;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Wd;Da=r;Ea=Hc;break a}Xd=Rd+ -1|0;Ud=Wd+1|0;Vd=(d[Wd]<>>0>>0){Qd=Yd;Rd=Xd;Sd=Vd;Wd=Ud}else{Ce=Yd;De=Xd;Ee=Vd;Fe=Ud;break}}}else{Ce=ae;De=be;Ee=ce;Fe=de}Wd=Ee>>>_d;se=-7-_d+Ce|0;te=(Wd&127)+11|0;ue=De;ve=Wd>>>7;we=0;xe=Fe}if((va+te|0)>>>0>(Ja+ua|0)>>>0){ta=190;break d}else{Ge=va;He=te}while(1){Wd=He+ -1|0;c[aa>>2]=Ge+1;b[l+(Ge<<1)+112>>1]=we;if((Wd|0)==0){ie=se;je=ue;ke=ve;le=xe;break e}Ge=c[aa>>2]|0;He=Wd}}}while(0);Td=c[aa>>2]|0;Ie=c[Z>>2]|0;Od=c[_>>2]|0;if(Td>>>0<(Od+Ie|0)>>>0){va=Td;Ja=Od;ua=Ie;Ha=ie;Ga=je;wa=ke;Yb=le}else{ta=193;break}}if((ta|0)==181){ta=0;c[B>>2]=22064;c[l>>2]=29;Oa=re;Pa=ne;Qa=qe;Ra=la;Sa=pe;Ta=r;Ua=o;Va=Hc;break c}else if((ta|0)==190){ta=0;c[B>>2]=22064;c[l>>2]=29;Oa=se;Pa=ue;Qa=ve;Ra=la;Sa=xe;Ta=r;Ua=o;Va=Hc;break c}else if((ta|0)==193){ta=0;if((c[l>>2]|0)==29){Oa=ie;Pa=je;Qa=ke;Ra=la;Sa=le;Ta=r;Ua=o;Va=Hc;break c}else{Je=Ie;Ke=ie;Le=je;Me=ke;Ne=le;break}}}else{Je=Ia;Ke=Dc;Le=Ec;Me=Fc;Ne=Gc}}while(0);if((b[fa>>1]|0)==0){c[B>>2]=22096;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Hc;break}c[ca>>2]=ba;c[J>>2]=ba;c[K>>2]=9;Ia=Nf(1,da,Je,ca,K,ea)|0;if((Ia|0)!=0){c[B>>2]=22136;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Ia;break}c[L>>2]=c[ca>>2];c[M>>2]=6;Ia=Nf(2,l+(c[Z>>2]<<1)+112|0,c[_>>2]|0,ca,M,ea)|0;if((Ia|0)==0){c[l>>2]=19;if(N){na=Ke;oa=Le;pa=Me;qa=la;ra=Ne;sa=0;ta=285;break a}else{Mc=Ke;Nc=Le;Oc=Me;Pc=Ne;Qc=0;ta=201;break}}else{c[B>>2]=22168;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Ia;break}}}while(0);if((ta|0)==57){ta=0;Ia=c[A>>2]|0;if((Ia|0)!=0){c[Ia+8>>2]=wd&255;c[Ia+12>>2]=wd>>>8}if((c[z>>2]&512|0)!=0){a[j]=wd;a[y]=wd>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0}c[l>>2]=4;nd=0;od=vd;pd=0;qd=xd;ta=62}else if((ta|0)==201){ta=0;c[l>>2]=20;Rc=Mc;Sc=Nc;Tc=Oc;Uc=Pc;Vc=Qc;ta=202}do{if((ta|0)==62){ta=0;Ia=c[z>>2]|0;if((Ia&1024|0)==0){xa=c[A>>2]|0;if((xa|0)==0){Oe=nd;Pe=od;Qe=pd;Re=qd}else{c[xa+16>>2]=0;Oe=nd;Pe=od;Qe=pd;Re=qd}}else{if(nd>>>0<16){xa=nd;Yb=od;wa=pd;Ga=qd;while(1){if((Yb|0)==0){ya=xa;za=0;Aa=wa;Ba=la;Ca=Ga;Da=r;Ea=s;break a}Ha=Yb+ -1|0;ua=Ga+1|0;Ja=(d[Ga]<>>0<16){xa=va;Yb=Ha;wa=Ja;Ga=ua}else{Se=Ha;Te=Ja;Ue=ua;break}}}else{Se=od;Te=pd;Ue=qd}c[F>>2]=Te;Ga=c[A>>2]|0;if((Ga|0)==0){Ve=Ia}else{c[Ga+20>>2]=Te;Ve=c[z>>2]|0}if((Ve&512|0)==0){Oe=0;Pe=Se;Qe=0;Re=Ue}else{a[j]=Te;a[y]=Te>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0;Oe=0;Pe=Se;Qe=0;Re=Ue}}c[l>>2]=5;Hb=Oe;Ib=Pe;Jb=Qe;Kb=Re;ta=73}else if((ta|0)==202){ta=0;if(Sc>>>0>5&la>>>0>257){c[m>>2]=o;c[n>>2]=la;c[f>>2]=Uc;c[p>>2]=Sc;c[u>>2]=Tc;c[v>>2]=Rc;Gf(f,r);Ga=c[m>>2]|0;wa=c[n>>2]|0;Yb=c[f>>2]|0;xa=c[p>>2]|0;ua=c[u>>2]|0;Ja=c[v>>2]|0;if((c[l>>2]|0)!=11){Oa=Ja;Pa=xa;Qa=ua;Ra=wa;Sa=Yb;Ta=r;Ua=Ga;Va=Vc;break}c[O>>2]=-1;Oa=Ja;Pa=xa;Qa=ua;Ra=wa;Sa=Yb;Ta=r;Ua=Ga;Va=Vc;break}c[O>>2]=0;Ga=(1<>2])+ -1|0;Yb=Ga&Tc;wa=c[J>>2]|0;ua=a[wa+(Yb<<2)+1|0]|0;xa=ua&255;if(xa>>>0>Rc>>>0){Ja=Rc;Ha=Sc;va=Tc;Od=Uc;while(1){if((Ha|0)==0){ya=Ja;za=0;Aa=va;Ba=la;Ca=Od;Da=r;Ea=Vc;break a}Td=Ha+ -1|0;oc=Od+1|0;Pd=(d[Od]<>>0>Wd>>>0){Ja=Wd;Ha=Td;va=Pd;Od=oc}else{We=Rd;Xe=Qd;Ye=Sd;Ze=Wd;_e=Td;$e=Pd;af=oc;break}}}else{We=ua;Xe=xa;Ye=Yb;Ze=Rc;_e=Sc;$e=Tc;af=Uc}Od=a[wa+(Ye<<2)|0]|0;va=b[wa+(Ye<<2)+2>>1]|0;Ha=Od&255;if(!(Od<<24>>24==0)){if((Ha&240|0)==0){Ja=va&65535;Ga=(1<>>Xe)+Ja|0;Ia=a[wa+(Ha<<2)+1|0]|0;if(((Ia&255)+Xe|0)>>>0>Ze>>>0){oc=Ze;Pd=_e;Td=$e;Wd=af;while(1){if((Pd|0)==0){ya=oc;za=0;Aa=Td;Ba=la;Ca=Wd;Da=r;Ea=Vc;break a}Sd=Pd+ -1|0;Qd=Wd+1|0;Rd=(d[Wd]<>>Xe)+Ja|0;Vd=a[wa+(Ud<<2)+1|0]|0;if(((Vd&255)+Xe|0)>>>0>Xb>>>0){oc=Xb;Pd=Sd;Td=Rd;Wd=Qd}else{bf=Ud;cf=Vd;df=Xb;ef=Sd;hf=Rd;jf=Qd;break}}}else{bf=Ha;cf=Ia;df=Ze;ef=_e;hf=$e;jf=af}Wd=b[wa+(bf<<2)+2>>1]|0;Td=a[wa+(bf<<2)|0]|0;c[O>>2]=Xe;kf=Xe;lf=df-Xe|0;mf=ef;nf=Td;of=cf;pf=Wd;qf=hf>>>Xe;rf=jf}else{kf=0;lf=Ze;mf=_e;nf=Od;of=We;pf=va;qf=$e;rf=af}}else{kf=0;lf=Ze;mf=_e;nf=0;of=We;pf=va;qf=$e;rf=af}Wd=of&255;Td=qf>>>Wd;Pd=lf-Wd|0;c[O>>2]=kf+Wd;c[F>>2]=pf&65535;Wd=nf&255;if(nf<<24>>24==0){c[l>>2]=25;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}if((Wd&32|0)!=0){c[O>>2]=-1;c[l>>2]=11;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}if((Wd&64|0)==0){oc=Wd&15;c[P>>2]=oc;c[l>>2]=21;$a=oc;ab=Pd;bb=mf;cb=Td;db=rf;eb=Vc;ta=221;break}else{c[B>>2]=22192;c[l>>2]=29;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}}}while(0);if((ta|0)==73){ta=0;Td=c[z>>2]|0;if((Td&1024|0)!=0){Pd=c[F>>2]|0;oc=Pd>>>0>Ib>>>0?Ib:Pd;if((oc|0)==0){sf=Pd;tf=Ib;uf=Kb}else{Wd=c[A>>2]|0;if((Wd|0)!=0?(Ja=c[Wd+16>>2]|0,(Ja|0)!=0):0){Ga=(c[Wd+20>>2]|0)-Pd|0;Pd=c[Wd+24>>2]|0;Kg(Ja+Ga|0,Kb|0,((Ga+oc|0)>>>0>Pd>>>0?Pd-Ga|0:oc)|0)|0;vf=c[z>>2]|0}else{vf=Td}if((vf&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Kb,oc)|0}Td=(c[F>>2]|0)-oc|0;c[F>>2]=Td;sf=Td;tf=Ib-oc|0;uf=Kb+oc|0}if((sf|0)==0){wf=tf;xf=uf}else{na=Hb;oa=tf;pa=Jb;qa=la;ra=uf;sa=s;ta=285;break}}else{wf=Ib;xf=Kb}c[F>>2]=0;c[l>>2]=6;Ic=Hb;Jc=wf;Kc=Jb;Lc=xf;ta=83}else if((ta|0)==221){ta=0;if(($a|0)==0){yf=c[F>>2]|0;zf=ab;Af=bb;Bf=cb;Cf=db}else{if(ab>>>0<$a>>>0){oc=ab;Td=bb;Ga=cb;Pd=db;while(1){if((Td|0)==0){ya=oc;za=0;Aa=Ga;Ba=la;Ca=Pd;Da=r;Ea=eb;break a}Ja=Td+ -1|0;Wd=Pd+1|0;Yb=(d[Pd]<>>0<$a>>>0){oc=xa;Td=Ja;Ga=Yb;Pd=Wd}else{Df=xa;Ef=Ja;Ff=Yb;Hf=Wd;break}}}else{Df=ab;Ef=bb;Ff=cb;Hf=db}Pd=(c[F>>2]|0)+((1<<$a)+ -1&Ff)|0;c[F>>2]=Pd;c[O>>2]=(c[O>>2]|0)+$a;yf=Pd;zf=Df-$a|0;Af=Ef;Bf=Ff>>>$a;Cf=Hf}c[Q>>2]=yf;c[l>>2]=22;ub=zf;vb=Af;wb=Bf;xb=Cf;yb=eb;ta=228}do{if((ta|0)==83){ta=0;if((c[z>>2]&2048|0)==0){Pd=c[A>>2]|0;if((Pd|0)==0){If=Jc;Jf=Lc}else{c[Pd+28>>2]=0;If=Jc;Jf=Lc}}else{if((Jc|0)==0){na=Ic;oa=0;pa=Kc;qa=la;ra=Lc;sa=s;ta=285;break a}else{Kf=0}while(1){Mf=Kf+1|0;Pd=a[Lc+Kf|0]|0;Ga=c[A>>2]|0;if(((Ga|0)!=0?(Td=c[Ga+28>>2]|0,(Td|0)!=0):0)?(oc=c[F>>2]|0,oc>>>0<(c[Ga+32>>2]|0)>>>0):0){c[F>>2]=oc+1;a[Td+oc|0]=Pd}Of=Pd<<24>>24!=0;if(Of&Mf>>>0>>0){Kf=Mf}else{break}}if((c[z>>2]&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Lc,Mf)|0}va=Jc-Mf|0;Od=Lc+Mf|0;if(Of){na=Ic;oa=va;pa=Kc;qa=la;ra=Od;sa=s;ta=285;break a}else{If=va;Jf=Od}}c[F>>2]=0;c[l>>2]=7;Db=Ic;Eb=If;Fb=Kc;Gb=Jf;ta=96}else if((ta|0)==228){ta=0;Od=(1<>2])+ -1|0;va=Od&wb;wa=c[L>>2]|0;Ia=a[wa+(va<<2)+1|0]|0;Ha=Ia&255;if(Ha>>>0>ub>>>0){Pd=ub;oc=vb;Td=wb;Ga=xb;while(1){if((oc|0)==0){ya=Pd;za=0;Aa=Td;Ba=la;Ca=Ga;Da=r;Ea=yb;break a}Wd=oc+ -1|0;Yb=Ga+1|0;Ja=(d[Ga]<>>0>xa>>>0){Pd=xa;oc=Wd;Td=Ja;Ga=Yb}else{Pf=Qd;Qf=Rd;Rf=ua;Sf=xa;Tf=Wd;Uf=Ja;Vf=Yb;break}}}else{Pf=Ia;Qf=Ha;Rf=va;Sf=ub;Tf=vb;Uf=wb;Vf=xb}Ga=a[wa+(Rf<<2)|0]|0;Td=b[wa+(Rf<<2)+2>>1]|0;oc=Ga&255;if((oc&240|0)==0){Pd=Td&65535;Od=(1<>>Qf)+Pd|0;Yb=a[wa+(oc<<2)+1|0]|0;if(((Yb&255)+Qf|0)>>>0>Sf>>>0){Ja=Sf;Wd=Tf;xa=Uf;ua=Vf;while(1){if((Wd|0)==0){ya=Ja;za=0;Aa=xa;Ba=la;Ca=ua;Da=r;Ea=yb;break a}Rd=Wd+ -1|0;Qd=ua+1|0;Sd=(d[ua]<>>Qf)+Pd|0;Ud=a[wa+(Vd<<2)+1|0]|0;if(((Ud&255)+Qf|0)>>>0>Xb>>>0){Ja=Xb;Wd=Rd;xa=Sd;ua=Qd}else{Wf=Vd;Xf=Ud;Yf=Xb;Zf=Rd;_f=Sd;$f=Qd;break}}}else{Wf=oc;Xf=Yb;Yf=Sf;Zf=Tf;_f=Uf;$f=Vf}ua=b[wa+(Wf<<2)+2>>1]|0;xa=a[wa+(Wf<<2)|0]|0;Wd=(c[O>>2]|0)+Qf|0;c[O>>2]=Wd;ag=Wd;bg=Yf-Qf|0;cg=Zf;dg=xa;eg=Xf;fg=ua;gg=_f>>>Qf;hg=$f}else{ag=c[O>>2]|0;bg=Sf;cg=Tf;dg=Ga;eg=Pf;fg=Td;gg=Uf;hg=Vf}ua=eg&255;xa=gg>>>ua;Wd=bg-ua|0;c[O>>2]=ag+ua;ua=dg&255;if((ua&64|0)==0){c[R>>2]=fg&65535;Ja=ua&15;c[P>>2]=Ja;c[l>>2]=23;fb=Ja;gb=Wd;hb=cg;ib=xa;jb=hg;kb=yb;ta=240;break}else{c[B>>2]=22224;c[l>>2]=29;Oa=Wd;Pa=cg;Qa=xa;Ra=la;Sa=hg;Ta=r;Ua=o;Va=yb;break}}}while(0);if((ta|0)==96){ta=0;if((c[z>>2]&4096|0)==0){xa=c[A>>2]|0;if((xa|0)==0){ig=Eb;jg=Gb}else{c[xa+36>>2]=0;ig=Eb;jg=Gb}}else{if((Eb|0)==0){na=Db;oa=0;pa=Fb;qa=la;ra=Gb;sa=s;ta=285;break}else{kg=0}while(1){lg=kg+1|0;xa=a[Gb+kg|0]|0;Wd=c[A>>2]|0;if(((Wd|0)!=0?(Ja=c[Wd+36>>2]|0,(Ja|0)!=0):0)?(ua=c[F>>2]|0,ua>>>0<(c[Wd+40>>2]|0)>>>0):0){c[F>>2]=ua+1;a[Ja+ua|0]=xa}mg=xa<<24>>24!=0;if(mg&lg>>>0>>0){kg=lg}else{break}}if((c[z>>2]&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Gb,lg)|0}xa=Eb-lg|0;ua=Gb+lg|0;if(mg){na=Db;oa=xa;pa=Fb;qa=la;ra=ua;sa=s;ta=285;break}else{ig=xa;jg=ua}}c[l>>2]=8;Lb=Db;Mb=ig;Nb=Fb;Ob=jg;ta=109}else if((ta|0)==240){ta=0;if((fb|0)==0){ng=gb;og=hb;pg=ib;qg=jb}else{if(gb>>>0>>0){ua=gb;xa=hb;Ja=ib;Wd=jb;while(1){if((xa|0)==0){ya=ua;za=0;Aa=Ja;Ba=la;Ca=Wd;Da=r;Ea=kb;break a}Pd=xa+ -1|0;Od=Wd+1|0;va=(d[Wd]<>>0>>0){ua=Ha;xa=Pd;Ja=va;Wd=Od}else{rg=Ha;sg=Pd;tg=va;ug=Od;break}}}else{rg=gb;sg=hb;tg=ib;ug=jb}c[R>>2]=(c[R>>2]|0)+((1<>2]=(c[O>>2]|0)+fb;ng=rg-fb|0;og=sg;pg=tg>>>fb;qg=ug}c[l>>2]=24;uc=ng;vc=og;wc=pg;xc=qg;yc=kb;ta=246}do{if((ta|0)==109){ta=0;Wd=c[z>>2]|0;if((Wd&512|0)!=0){if(Lb>>>0<16){Ja=Lb;xa=Mb;ua=Nb;Od=Ob;while(1){if((xa|0)==0){ya=Ja;za=0;Aa=ua;Ba=la;Ca=Od;Da=r;Ea=s;break a}va=xa+ -1|0;Pd=Od+1|0;Ha=(d[Od]<>>0<16){Ja=Ia;xa=va;ua=Ha;Od=Pd}else{vg=Ia;wg=va;xg=Ha;yg=Pd;break}}}else{vg=Lb;wg=Mb;xg=Nb;yg=Ob}if((xg|0)==(c[x>>2]&65535|0)){zg=0;Ag=wg;Bg=0;Cg=yg}else{c[B>>2]=21912;c[l>>2]=29;Oa=vg;Pa=wg;Qa=xg;Ra=la;Sa=yg;Ta=r;Ua=o;Va=s;break}}else{zg=Lb;Ag=Mb;Bg=Nb;Cg=Ob}Od=c[A>>2]|0;if((Od|0)!=0){c[Od+44>>2]=Wd>>>9&1;c[Od+48>>2]=1}Od=gf(0,0,0)|0;c[x>>2]=Od;c[E>>2]=Od;c[l>>2]=11;Oa=zg;Pa=Ag;Qa=Bg;Ra=la;Sa=Cg;Ta=r;Ua=o;Va=s}else if((ta|0)==246){ta=0;if((la|0)==0){na=uc;oa=vc;pa=wc;qa=0;ra=xc;sa=yc;ta=285;break a}Od=r-la|0;ua=c[R>>2]|0;if(ua>>>0>Od>>>0){xa=ua-Od|0;if(xa>>>0>(c[S>>2]|0)>>>0?(c[T>>2]|0)!=0:0){c[B>>2]=22248;c[l>>2]=29;Oa=uc;Pa=vc;Qa=wc;Ra=la;Sa=xc;Ta=r;Ua=o;Va=yc;break}Od=c[U>>2]|0;if(xa>>>0>Od>>>0){Ja=xa-Od|0;Dg=Ja;Eg=(c[V>>2]|0)+((c[W>>2]|0)-Ja)|0}else{Dg=xa;Eg=(c[V>>2]|0)+(Od-xa)|0}xa=c[F>>2]|0;Fg=xa;Gg=Dg>>>0>xa>>>0?xa:Dg;Hg=Eg}else{xa=c[F>>2]|0;Fg=xa;Gg=xa;Hg=o+(0-ua)|0}ua=Gg>>>0>la>>>0?la:Gg;c[F>>2]=Fg-ua;xa=~la;Od=~Gg;Ja=xa>>>0>Od>>>0?xa:Od;Od=ua;xa=Hg;Td=o;while(1){a[Td]=a[xa]|0;Od=Od+ -1|0;if((Od|0)==0){break}else{xa=xa+1|0;Td=Td+1|0}}Td=la-ua|0;xa=o+~Ja|0;if((c[F>>2]|0)==0){c[l>>2]=20;Oa=uc;Pa=vc;Qa=wc;Ra=Td;Sa=xc;Ta=r;Ua=xa;Va=yc}else{Oa=uc;Pa=vc;Qa=wc;Ra=Td;Sa=xc;Ta=r;Ua=xa;Va=yc}}}while(0);ia=c[l>>2]|0;q=Oa;ja=Pa;ka=Qa;la=Ra;ma=Sa;r=Ta;o=Ua;s=Va}if((ta|0)==122){c[m>>2]=o;c[n>>2]=la;c[f>>2]=Cb;c[p>>2]=Ab;c[u>>2]=Bb;c[v>>2]=zb;k=2;i=h;return k|0}else if((ta|0)==133){ya=Kd+ -3|0;za=Ld;Aa=Md>>>3;Ba=la;Ca=Nd;Da=r;Ea=s}else if((ta|0)==284){c[l>>2]=28;ya=Cd;za=Dd;Aa=Ed;Ba=la;Ca=Fd;Da=jd;Ea=1}else if((ta|0)==285){ya=na;za=oa;Aa=pa;Ba=qa;Ca=ra;Da=r;Ea=sa}else if((ta|0)==299){k=-4;i=h;return k|0}else if((ta|0)==300){i=h;return k|0}c[m>>2]=o;c[n>>2]=Ba;c[f>>2]=Ca;c[p>>2]=za;c[u>>2]=Aa;c[v>>2]=ya;if((c[W>>2]|0)==0){if((c[l>>2]|0)>>>0<26?(Da|0)!=(c[n>>2]|0):0){ta=289}}else{ta=289}if((ta|0)==289?(Lf(f,Da)|0)!=0:0){c[l>>2]=30;k=-4;i=h;return k|0}ta=c[p>>2]|0;p=c[n>>2]|0;n=Da-p|0;W=f+8|0;c[W>>2]=t-ta+(c[W>>2]|0);c[X>>2]=(c[X>>2]|0)+n;c[Y>>2]=(c[Y>>2]|0)+n;Y=(Da|0)==(p|0);if(!((c[w>>2]|0)==0|Y)){w=c[x>>2]|0;p=(c[m>>2]|0)+(0-n)|0;if((c[z>>2]|0)==0){Ig=ff(w,p,n)|0}else{Ig=gf(w,p,n)|0}c[x>>2]=Ig;c[E>>2]=Ig}Ig=c[l>>2]|0;if((Ig|0)==19){Jg=256}else{Jg=(Ig|0)==14?256:0}c[f+44>>2]=((c[I>>2]|0)!=0?64:0)+(c[v>>2]|0)+((Ig|0)==11?128:0)+Jg;k=((t|0)==(ta|0)&Y|(g|0)==4)&(Ea|0)==0?-5:Ea;i=h;return k|0}function Lf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;e=c[a+28>>2]|0;f=e+52|0;g=c[f>>2]|0;if((g|0)==0){h=kb[c[a+32>>2]&1](c[a+40>>2]|0,1<>2],1)|0;c[f>>2]=h;if((h|0)==0){j=1;i=d;return j|0}else{k=h}}else{k=g}g=e+40|0;h=c[g>>2]|0;if((h|0)==0){l=1<>2];c[g>>2]=l;c[e+48>>2]=0;c[e+44>>2]=0;m=l}else{m=h}h=b-(c[a+16>>2]|0)|0;if(!(h>>>0>>0)){Kg(k|0,(c[a+12>>2]|0)+(0-m)|0,m|0)|0;c[e+48>>2]=0;c[e+44>>2]=c[g>>2];j=0;i=d;return j|0}b=e+48|0;l=c[b>>2]|0;n=m-l|0;m=n>>>0>h>>>0?h:n;n=a+12|0;Kg(k+l|0,(c[n>>2]|0)+(0-h)|0,m|0)|0;l=h-m|0;if((h|0)!=(m|0)){Kg(c[f>>2]|0,(c[n>>2]|0)+(0-l)|0,l|0)|0;c[b>>2]=l;c[e+44>>2]=c[g>>2];j=0;i=d;return j|0}l=(c[b>>2]|0)+h|0;n=c[g>>2]|0;c[b>>2]=(l|0)==(n|0)?0:l;l=e+44|0;e=c[l>>2]|0;if(!(e>>>0>>0)){j=0;i=d;return j|0}c[l>>2]=e+h;j=0;i=d;return j|0}function Mf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;i=b;return d|0}g=a+36|0;h=c[g>>2]|0;if((h|0)==0){d=-2;i=b;return d|0}j=c[f+52>>2]|0;k=a+40|0;if((j|0)==0){l=h;m=f}else{mb[h&1](c[k>>2]|0,j);l=c[g>>2]|0;m=c[e>>2]|0}mb[l&1](c[k>>2]|0,m);c[e>>2]=0;d=0;i=b;return d|0}function Nf(d,f,g,h,j,k){d=d|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;l=i;i=i+64|0;m=l+32|0;n=l;o=m+0|0;p=o+32|0;do{b[o>>1]=0;o=o+2|0}while((o|0)<(p|0));o=(g|0)==0;if(!o){p=0;do{q=m+(e[f+(p<<1)>>1]<<1)|0;b[q>>1]=(b[q>>1]|0)+1<<16>>16;p=p+1|0}while((p|0)!=(g|0))}p=c[j>>2]|0;q=15;while(1){r=q+ -1|0;if((b[m+(q<<1)>>1]|0)!=0){break}if((r|0)==0){s=7;break}else{q=r}}if((s|0)==7){r=c[h>>2]|0;c[h>>2]=r+4;a[r]=64;a[r+1|0]=1;b[r+2>>1]=0;r=c[h>>2]|0;c[h>>2]=r+4;a[r]=64;a[r+1|0]=1;b[r+2>>1]=0;c[j>>2]=1;t=0;i=l;return t|0}r=p>>>0>q>>>0?q:p;a:do{if(q>>>0>1){p=1;while(1){u=p+1|0;if((b[m+(p<<1)>>1]|0)!=0){v=p;break a}if(u>>>0>>0){p=u}else{v=u;break}}}else{v=1}}while(0);p=r>>>0>>0?v:r;r=1;u=1;do{r=(r<<1)-(e[m+(u<<1)>>1]|0)|0;u=u+1|0;if((r|0)<0){t=-1;s=56;break}}while(u>>>0<16);if((s|0)==56){i=l;return t|0}if((r|0)>0?!((d|0)!=0&(q|0)==1):0){t=-1;i=l;return t|0}b[n+2>>1]=0;r=0;u=1;do{r=(e[m+(u<<1)>>1]|0)+(r&65535)|0;u=u+1|0;b[n+(u<<1)>>1]=r}while((u|0)!=15);if(!o){o=0;do{u=b[f+(o<<1)>>1]|0;if(!(u<<16>>16==0)){r=n+((u&65535)<<1)|0;u=b[r>>1]|0;b[r>>1]=u+1<<16>>16;b[k+((u&65535)<<1)>>1]=o}o=o+1|0}while((o|0)!=(g|0))}if((d|0)==0){w=0;x=1<>>0>851){t=1;i=l;return t|0}else{w=0;x=g;y=1;z=24504+ -514|0;A=256;B=24568+ -514|0}}else{g=1<>>0>591){t=1;i=l;return t|0}else{w=o;x=g;y=0;z=24632;A=-1;B=24696}}g=x+ -1|0;o=p&255;d=p;n=0;u=0;r=v;v=-1;C=c[h>>2]|0;D=0;E=x;b:while(1){x=1<>1]|0;L=K&65535;if((L|0)>=(A|0)){if((L|0)>(A|0)){M=b[B+(L<<1)>>1]&255;N=b[z+(L<<1)>>1]|0}else{M=96;N=0}}else{M=0;N=K}K=1<>>n;L=x;while(1){O=L-K|0;P=O+I|0;a[C+(P<<2)|0]=M;a[C+(P<<2)+1|0]=J;b[C+(P<<2)+2>>1]=N;if((L|0)==(K|0)){break}else{L=O}}L=1<>>1}}if((L|0)==0){Q=0}else{Q=(L+ -1&F)+L|0}R=H+1|0;K=m+(G<<1)|0;I=(b[K>>1]|0)+ -1<<16>>16;b[K>>1]=I;if(I<<16>>16==0){if((G|0)==(q|0)){break b}S=e[f+(e[k+(R<<1)>>1]<<1)>>1]|0}else{S=G}if(!(S>>>0>p>>>0)){F=Q;G=S;H=R;continue}T=Q&g;if((T|0)==(v|0)){F=Q;G=S;H=R}else{break}}H=(n|0)==0?p:n;G=C+(x<<2)|0;F=S-H|0;c:do{if(S>>>0>>0){I=S;K=F;O=1<>1]|0)|0;if((P|0)<1){U=K;break c}V=K+1|0;W=V+H|0;if(W>>>0>>0){I=W;K=V;O=P<<1}else{U=V;break}}}else{U=F}}while(0);F=(1<>>0>851|w&F>>>0>591){t=1;s=56;break}a[(c[h>>2]|0)+(T<<2)|0]=U;a[(c[h>>2]|0)+(T<<2)+1|0]=o;x=c[h>>2]|0;b[x+(T<<2)+2>>1]=(G-x|0)>>>2;d=U;n=H;u=Q;r=S;v=T;C=G;D=R;E=F}if((s|0)==56){i=l;return t|0}d:do{if((Q|0)!=0){s=n;R=J;D=Q;T=q;S=C;while(1){if((s|0)!=0){if((D&g|0)==(v|0)){X=s;Y=R;Z=T;_=S}else{X=0;Y=o;Z=p;_=c[h>>2]|0}}else{X=0;Y=R;Z=T;_=S}r=D>>>X;a[_+(r<<2)|0]=64;a[_+(r<<2)+1|0]=Y;b[_+(r<<2)+2>>1]=0;r=1<>>1}}if((r|0)==0){break d}D=(r+ -1&D)+r|0;if((D|0)==0){break}else{s=X;R=Y;T=Z;S=_}}}}while(0);c[h>>2]=(c[h>>2]|0)+(E<<2);c[j>>2]=p;t=0;i=l;return t|0}function Of(a){a=a|0;var d=0;d=i;c[a+2840>>2]=a+148;c[a+2848>>2]=25528;c[a+2852>>2]=a+2440;c[a+2860>>2]=25552;c[a+2864>>2]=a+2684;c[a+2872>>2]=25576;b[a+5816>>1]=0;c[a+5820>>2]=0;c[a+5812>>2]=8;Pf(a);i=d;return}function Pf(a){a=a|0;var d=0,e=0;d=i;e=0;do{b[a+(e<<2)+148>>1]=0;e=e+1|0}while((e|0)!=286);b[a+2440>>1]=0;b[a+2444>>1]=0;b[a+2448>>1]=0;b[a+2452>>1]=0;b[a+2456>>1]=0;b[a+2460>>1]=0;b[a+2464>>1]=0;b[a+2468>>1]=0;b[a+2472>>1]=0;b[a+2476>>1]=0;b[a+2480>>1]=0;b[a+2484>>1]=0;b[a+2488>>1]=0;b[a+2492>>1]=0;b[a+2496>>1]=0;b[a+2500>>1]=0;b[a+2504>>1]=0;b[a+2508>>1]=0;b[a+2512>>1]=0;b[a+2516>>1]=0;b[a+2520>>1]=0;b[a+2524>>1]=0;b[a+2528>>1]=0;b[a+2532>>1]=0;b[a+2536>>1]=0;b[a+2540>>1]=0;b[a+2544>>1]=0;b[a+2548>>1]=0;b[a+2552>>1]=0;b[a+2556>>1]=0;b[a+2684>>1]=0;b[a+2688>>1]=0;b[a+2692>>1]=0;b[a+2696>>1]=0;b[a+2700>>1]=0;b[a+2704>>1]=0;b[a+2708>>1]=0;b[a+2712>>1]=0;b[a+2716>>1]=0;b[a+2720>>1]=0;b[a+2724>>1]=0;b[a+2728>>1]=0;b[a+2732>>1]=0;b[a+2736>>1]=0;b[a+2740>>1]=0;b[a+2744>>1]=0;b[a+2748>>1]=0;b[a+2752>>1]=0;b[a+2756>>1]=0;b[a+1172>>1]=1;c[a+5804>>2]=0;c[a+5800>>2]=0;c[a+5808>>2]=0;c[a+5792>>2]=0;i=d;return}function Qf(d,f,g,h){d=d|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;j=i;k=d+5820|0;l=c[k>>2]|0;m=h&65535;h=d+5816|0;n=e[h>>1]|0|m<>1]=n;if((l|0)>13){o=d+20|0;p=c[o>>2]|0;c[o>>2]=p+1;q=d+8|0;a[(c[q>>2]|0)+p|0]=n;p=(e[h>>1]|0)>>>8&255;r=c[o>>2]|0;c[o>>2]=r+1;a[(c[q>>2]|0)+r|0]=p;p=c[k>>2]|0;r=m>>>(16-p|0);b[h>>1]=r;s=r;t=p+ -13|0}else{s=n;t=l+3|0}l=s&255;c[k>>2]=t;do{if((t|0)<=8){s=d+20|0;if((t|0)>0){n=c[s>>2]|0;c[s>>2]=n+1;p=d+8|0;a[(c[p>>2]|0)+n|0]=l;u=s;v=p;break}else{u=s;v=d+8|0;break}}else{s=d+20|0;p=c[s>>2]|0;c[s>>2]=p+1;n=d+8|0;a[(c[n>>2]|0)+p|0]=l;p=(e[h>>1]|0)>>>8&255;r=c[s>>2]|0;c[s>>2]=r+1;a[(c[n>>2]|0)+r|0]=p;u=s;v=n}}while(0);b[h>>1]=0;c[k>>2]=0;c[d+5812>>2]=8;d=c[u>>2]|0;c[u>>2]=d+1;a[(c[v>>2]|0)+d|0]=g;d=c[u>>2]|0;c[u>>2]=d+1;a[(c[v>>2]|0)+d|0]=g>>>8;d=g&65535^65535;k=c[u>>2]|0;c[u>>2]=k+1;a[(c[v>>2]|0)+k|0]=d;k=c[u>>2]|0;c[u>>2]=k+1;a[(c[v>>2]|0)+k|0]=d>>>8;if((g|0)==0){i=j;return}else{w=g;x=f}while(1){w=w+ -1|0;f=a[x]|0;g=c[u>>2]|0;c[u>>2]=g+1;a[(c[v>>2]|0)+g|0]=f;if((w|0)==0){break}else{x=x+1|0}}i=j;return}function Rf(d){d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;f=i;g=d+5820|0;h=c[g>>2]|0;j=d+5816|0;k=e[j>>1]|0|2<>1]=l;if((h|0)>13){m=d+20|0;n=c[m>>2]|0;c[m>>2]=n+1;o=d+8|0;a[(c[o>>2]|0)+n|0]=k;k=(e[j>>1]|0)>>>8&255;n=c[m>>2]|0;c[m>>2]=n+1;a[(c[o>>2]|0)+n|0]=k;k=c[g>>2]|0;n=2>>>(16-k|0)&65535;b[j>>1]=n;p=n;q=k+ -13|0}else{p=l;q=h+3|0}c[g>>2]=q;if((q|0)>9){h=d+20|0;l=c[h>>2]|0;c[h>>2]=l+1;k=d+8|0;a[(c[k>>2]|0)+l|0]=p;l=(e[j>>1]|0)>>>8&255;n=c[h>>2]|0;c[h>>2]=n+1;a[(c[k>>2]|0)+n|0]=l;b[j>>1]=0;r=(c[g>>2]|0)+ -9|0;s=0}else{r=q+7|0;s=p}c[g>>2]=r;if((r|0)!=16){if((r|0)>7){p=d+20|0;q=c[p>>2]|0;c[p>>2]=q+1;a[(c[d+8>>2]|0)+q|0]=s;q=(e[j>>1]|0)>>>8;b[j>>1]=q;p=(c[g>>2]|0)+ -8|0;c[g>>2]=p;t=p;u=q}else{t=r;u=s}}else{r=d+20|0;q=c[r>>2]|0;c[r>>2]=q+1;p=d+8|0;a[(c[p>>2]|0)+q|0]=s;s=(e[j>>1]|0)>>>8&255;q=c[r>>2]|0;c[r>>2]=q+1;a[(c[p>>2]|0)+q|0]=s;b[j>>1]=0;c[g>>2]=0;t=0;u=0}s=d+5812|0;if((11-t+(c[s>>2]|0)|0)>=9){c[s>>2]=7;i=f;return}q=u&65535|2<>1]=q;if((t|0)>13){u=d+20|0;p=c[u>>2]|0;c[u>>2]=p+1;r=d+8|0;a[(c[r>>2]|0)+p|0]=q;p=(e[j>>1]|0)>>>8&255;l=c[u>>2]|0;c[u>>2]=l+1;a[(c[r>>2]|0)+l|0]=p;p=c[g>>2]|0;l=2>>>(16-p|0);b[j>>1]=l;v=l;w=p+ -13|0}else{v=q;w=t+3|0}t=v&255;c[g>>2]=w;if((w|0)>9){v=d+20|0;q=c[v>>2]|0;c[v>>2]=q+1;p=d+8|0;a[(c[p>>2]|0)+q|0]=t;q=(e[j>>1]|0)>>>8&255;l=c[v>>2]|0;c[v>>2]=l+1;a[(c[p>>2]|0)+l|0]=q;b[j>>1]=0;x=0;y=(c[g>>2]|0)+ -9|0}else{x=t;y=w+7|0}c[g>>2]=y;if((y|0)==16){w=d+20|0;t=c[w>>2]|0;c[w>>2]=t+1;q=d+8|0;a[(c[q>>2]|0)+t|0]=x;t=(e[j>>1]|0)>>>8&255;l=c[w>>2]|0;c[w>>2]=l+1;a[(c[q>>2]|0)+l|0]=t;b[j>>1]=0;c[g>>2]=0;c[s>>2]=7;i=f;return}if((y|0)<=7){c[s>>2]=7;i=f;return}y=d+20|0;t=c[y>>2]|0;c[y>>2]=t+1;a[(c[d+8>>2]|0)+t|0]=x;b[j>>1]=(e[j>>1]|0)>>>8;c[g>>2]=(c[g>>2]|0)+ -8;c[s>>2]=7;i=f;return}function Sf(f,g,h,j){f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;k=i;if((c[f+132>>2]|0)>0){l=(c[f>>2]|0)+44|0;if((c[l>>2]|0)==2){m=-201342849;n=0;while(1){if((m&1|0)!=0?(b[f+(n<<2)+148>>1]|0)!=0:0){o=0;break}p=n+1|0;if((p|0)<32){m=m>>>1;n=p}else{q=6;break}}a:do{if((q|0)==6){if(((b[f+184>>1]|0)==0?(b[f+188>>1]|0)==0:0)?(b[f+200>>1]|0)==0:0){n=32;while(1){m=n+1|0;if((b[f+(n<<2)+148>>1]|0)!=0){o=1;break a}if((m|0)<256){n=m}else{o=0;break}}}else{o=1}}}while(0);c[l>>2]=o}Tf(f,f+2840|0);Tf(f,f+2852|0);Wf(f,f+148|0,c[f+2844>>2]|0);Wf(f,f+2440|0,c[f+2856>>2]|0);Tf(f,f+2864|0);o=18;while(1){l=o+ -1|0;if((b[f+(d[27352+o|0]<<2)+2686>>1]|0)!=0){r=o;break}if((l|0)>2){o=l}else{r=l;break}}o=f+5800|0;l=(r*3|0)+17+(c[o>>2]|0)|0;c[o>>2]=l;o=(l+10|0)>>>3;l=((c[f+5804>>2]|0)+10|0)>>>3;s=r;t=l>>>0>o>>>0?o:l;u=l}else{l=h+5|0;s=0;t=l;u=l}do{if((h+4|0)>>>0>t>>>0|(g|0)==0){l=f+5820|0;o=c[l>>2]|0;r=(o|0)>13;if((c[f+136>>2]|0)==4|(u|0)==(t|0)){q=j+2&65535;n=f+5816|0;m=e[n>>1]|q<>1]=m;if(r){p=f+20|0;v=c[p>>2]|0;c[p>>2]=v+1;w=f+8|0;a[(c[w>>2]|0)+v|0]=m;m=(e[n>>1]|0)>>>8&255;v=c[p>>2]|0;c[p>>2]=v+1;a[(c[w>>2]|0)+v|0]=m;m=c[l>>2]|0;b[n>>1]=q>>>(16-m|0);x=m+ -13|0}else{x=o+3|0}c[l>>2]=x;Uf(f,25600,26752);break}m=j+4&65535;q=f+5816|0;n=e[q>>1]|m<>1]=n;if(r){r=f+20|0;v=c[r>>2]|0;c[r>>2]=v+1;w=f+8|0;a[(c[w>>2]|0)+v|0]=n;v=(e[q>>1]|0)>>>8&255;p=c[r>>2]|0;c[r>>2]=p+1;a[(c[w>>2]|0)+p|0]=v;v=c[l>>2]|0;p=m>>>(16-v|0);b[q>>1]=p;y=p;z=v+ -13|0}else{y=n;z=o+3|0}c[l>>2]=z;o=c[f+2844>>2]|0;n=c[f+2856>>2]|0;v=o+65280&65535;p=y&65535|v<>1]=p;if((z|0)>11){m=f+20|0;w=c[m>>2]|0;c[m>>2]=w+1;r=f+8|0;a[(c[r>>2]|0)+w|0]=p;w=(e[q>>1]|0)>>>8&255;A=c[m>>2]|0;c[m>>2]=A+1;a[(c[r>>2]|0)+A|0]=w;w=c[l>>2]|0;A=v>>>(16-w|0);b[q>>1]=A;B=w+ -11|0;C=A}else{B=z+5|0;C=p}c[l>>2]=B;p=n&65535;A=p<>1]=A;if((B|0)>11){w=f+20|0;v=c[w>>2]|0;c[w>>2]=v+1;r=f+8|0;a[(c[r>>2]|0)+v|0]=A;v=(e[q>>1]|0)>>>8&255;m=c[w>>2]|0;c[w>>2]=m+1;a[(c[r>>2]|0)+m|0]=v;v=c[l>>2]|0;m=p>>>(16-v|0);b[q>>1]=m;D=v+ -11|0;E=m}else{D=B+5|0;E=A}c[l>>2]=D;A=s+65533&65535;m=A<>1]=m;if((D|0)>12){v=f+20|0;p=c[v>>2]|0;c[v>>2]=p+1;r=f+8|0;a[(c[r>>2]|0)+p|0]=m;p=(e[q>>1]|0)>>>8&255;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[r>>2]|0)+w|0]=p;p=c[l>>2]|0;w=A>>>(16-p|0);b[q>>1]=w;F=w;G=p+ -12|0}else{F=m;G=D+4|0}c[l>>2]=G;if((s|0)>-1){m=f+20|0;p=f+8|0;w=G;A=F;r=0;while(1){v=e[f+(d[27352+r|0]<<2)+2686>>1]|0;H=v<>1]=H;if((w|0)>13){I=c[m>>2]|0;c[m>>2]=I+1;a[(c[p>>2]|0)+I|0]=H;I=(e[q>>1]|0)>>>8&255;J=c[m>>2]|0;c[m>>2]=J+1;a[(c[p>>2]|0)+J|0]=I;I=c[l>>2]|0;J=v>>>(16-I|0);b[q>>1]=J;K=J;L=I+ -13|0}else{K=H;L=w+3|0}c[l>>2]=L;if((r|0)==(s|0)){break}else{w=L;A=K;r=r+1|0}}}r=f+148|0;Vf(f,r,o);A=f+2440|0;Vf(f,A,n);Uf(f,r,A)}else{Qf(f,g,h,j)}}while(0);Pf(f);if((j|0)==0){i=k;return}j=f+5820|0;h=c[j>>2]|0;if((h|0)<=8){g=f+5816|0;if((h|0)>0){h=b[g>>1]&255;K=f+20|0;L=c[K>>2]|0;c[K>>2]=L+1;a[(c[f+8>>2]|0)+L|0]=h;M=g}else{M=g}}else{g=f+5816|0;h=b[g>>1]&255;L=f+20|0;K=c[L>>2]|0;c[L>>2]=K+1;s=f+8|0;a[(c[s>>2]|0)+K|0]=h;h=(e[g>>1]|0)>>>8&255;K=c[L>>2]|0;c[L>>2]=K+1;a[(c[s>>2]|0)+K|0]=h;M=g}b[M>>1]=0;c[j>>2]=0;i=k;return}function Tf(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0;h=i;i=i+32|0;j=h;k=c[g>>2]|0;l=g+8|0;m=c[l>>2]|0;n=c[m>>2]|0;o=c[m+12>>2]|0;m=f+5200|0;c[m>>2]=0;p=f+5204|0;c[p>>2]=573;if((o|0)>0){q=-1;r=0;while(1){if((b[k+(r<<2)>>1]|0)==0){b[k+(r<<2)+2>>1]=0;s=q}else{t=(c[m>>2]|0)+1|0;c[m>>2]=t;c[f+(t<<2)+2908>>2]=r;a[f+r+5208|0]=0;s=r}r=r+1|0;if((r|0)==(o|0)){break}else{q=s}}q=c[m>>2]|0;if((q|0)<2){u=q;v=s;w=3}else{x=s}}else{u=0;v=-1;w=3}if((w|0)==3){w=f+5800|0;s=f+5804|0;if((n|0)==0){q=u;r=v;while(1){t=(r|0)<2;y=r+1|0;z=t?y:r;A=t?y:0;y=q+1|0;c[m>>2]=y;c[f+(y<<2)+2908>>2]=A;b[k+(A<<2)>>1]=1;a[f+A+5208|0]=0;c[w>>2]=(c[w>>2]|0)+ -1;A=c[m>>2]|0;if((A|0)<2){q=A;r=z}else{x=z;break}}}else{r=u;u=v;while(1){v=(u|0)<2;q=u+1|0;z=v?q:u;A=v?q:0;q=r+1|0;c[m>>2]=q;c[f+(q<<2)+2908>>2]=A;b[k+(A<<2)>>1]=1;a[f+A+5208|0]=0;c[w>>2]=(c[w>>2]|0)+ -1;c[s>>2]=(c[s>>2]|0)-(e[n+(A<<2)+2>>1]|0);A=c[m>>2]|0;if((A|0)<2){r=A;u=z}else{x=z;break}}}}u=g+4|0;c[u>>2]=x;r=c[m>>2]|0;if((r|0)>1){n=r;s=(r|0)/2|0;while(1){w=c[f+(s<<2)+2908>>2]|0;z=f+w+5208|0;A=s<<1;a:do{if((A|0)>(n|0)){B=s}else{q=k+(w<<2)|0;v=s;y=n;t=A;while(1){do{if((t|0)<(y|0)){C=t|1;D=c[f+(C<<2)+2908>>2]|0;E=b[k+(D<<2)>>1]|0;F=c[f+(t<<2)+2908>>2]|0;G=b[k+(F<<2)>>1]|0;if(!((E&65535)<(G&65535))){if(!(E<<16>>16==G<<16>>16)){H=t;break}if((d[f+D+5208|0]|0)>(d[f+F+5208|0]|0)){H=t;break}}H=C}else{H=t}}while(0);C=b[q>>1]|0;F=c[f+(H<<2)+2908>>2]|0;D=b[k+(F<<2)>>1]|0;if((C&65535)<(D&65535)){B=v;break a}if(C<<16>>16==D<<16>>16?(d[z]|0)<=(d[f+F+5208|0]|0):0){B=v;break a}c[f+(v<<2)+2908>>2]=F;F=H<<1;D=c[m>>2]|0;if((F|0)>(D|0)){B=H;break}else{v=H;y=D;t=F}}}}while(0);c[f+(B<<2)+2908>>2]=w;z=s+ -1|0;A=c[m>>2]|0;if((z|0)>0){n=A;s=z}else{I=A;break}}}else{I=r}r=f+2912|0;s=I;I=o;while(1){o=c[r>>2]|0;n=s+ -1|0;c[m>>2]=n;B=c[f+(s<<2)+2908>>2]|0;c[r>>2]=B;H=f+B+5208|0;b:do{if((s|0)<3){J=1}else{A=k+(B<<2)|0;z=1;t=n;y=2;while(1){do{if((y|0)<(t|0)){v=y|1;q=c[f+(v<<2)+2908>>2]|0;F=b[k+(q<<2)>>1]|0;D=c[f+(y<<2)+2908>>2]|0;C=b[k+(D<<2)>>1]|0;if(!((F&65535)<(C&65535))){if(!(F<<16>>16==C<<16>>16)){K=y;break}if((d[f+q+5208|0]|0)>(d[f+D+5208|0]|0)){K=y;break}}K=v}else{K=y}}while(0);v=b[A>>1]|0;D=c[f+(K<<2)+2908>>2]|0;q=b[k+(D<<2)>>1]|0;if((v&65535)<(q&65535)){J=z;break b}if(v<<16>>16==q<<16>>16?(d[H]|0)<=(d[f+D+5208|0]|0):0){J=z;break b}c[f+(z<<2)+2908>>2]=D;D=K<<1;q=c[m>>2]|0;if((D|0)>(q|0)){J=K;break}else{z=K;t=q;y=D}}}}while(0);c[f+(J<<2)+2908>>2]=B;H=c[r>>2]|0;n=(c[p>>2]|0)+ -1|0;c[p>>2]=n;c[f+(n<<2)+2908>>2]=o;n=(c[p>>2]|0)+ -1|0;c[p>>2]=n;c[f+(n<<2)+2908>>2]=H;n=k+(I<<2)|0;b[n>>1]=(e[k+(H<<2)>>1]|0)+(e[k+(o<<2)>>1]|0);w=a[f+o+5208|0]|0;y=a[f+H+5208|0]|0;t=f+I+5208|0;a[t]=(((w&255)<(y&255)?y:w)&255)+1;w=I&65535;b[k+(H<<2)+2>>1]=w;b[k+(o<<2)+2>>1]=w;w=I+1|0;c[r>>2]=I;H=c[m>>2]|0;c:do{if((H|0)<2){L=1}else{y=1;z=H;A=2;while(1){do{if((A|0)<(z|0)){D=A|1;q=c[f+(D<<2)+2908>>2]|0;v=b[k+(q<<2)>>1]|0;C=c[f+(A<<2)+2908>>2]|0;F=b[k+(C<<2)>>1]|0;if(!((v&65535)<(F&65535))){if(!(v<<16>>16==F<<16>>16)){M=A;break}if((d[f+q+5208|0]|0)>(d[f+C+5208|0]|0)){M=A;break}}M=D}else{M=A}}while(0);D=b[n>>1]|0;C=c[f+(M<<2)+2908>>2]|0;q=b[k+(C<<2)>>1]|0;if((D&65535)<(q&65535)){L=y;break c}if(D<<16>>16==q<<16>>16?(d[t]|0)<=(d[f+C+5208|0]|0):0){L=y;break c}c[f+(y<<2)+2908>>2]=C;C=M<<1;q=c[m>>2]|0;if((C|0)>(q|0)){L=M;break}else{y=M;z=q;A=C}}}}while(0);c[f+(L<<2)+2908>>2]=I;t=c[m>>2]|0;if((t|0)>1){s=t;I=w}else{break}}I=c[r>>2]|0;r=(c[p>>2]|0)+ -1|0;c[p>>2]=r;c[f+(r<<2)+2908>>2]=I;I=c[g>>2]|0;g=c[u>>2]|0;u=c[l>>2]|0;l=c[u>>2]|0;r=c[u+4>>2]|0;s=c[u+8>>2]|0;m=c[u+16>>2]|0;u=f+2876|0;L=u+32|0;do{b[u>>1]=0;u=u+2|0}while((u|0)<(L|0));u=c[p>>2]|0;b[I+(c[f+(u<<2)+2908>>2]<<2)+2>>1]=0;p=u+1|0;d:do{if((p|0)<573){u=f+5800|0;L=f+5804|0;if((l|0)==0){M=p;J=0;while(1){K=c[f+(M<<2)+2908>>2]|0;t=I+(K<<2)+2|0;n=e[I+(e[t>>1]<<2)+2>>1]|0;H=(n|0)<(m|0);o=H?n+1|0:m;n=(H&1^1)+J|0;b[t>>1]=o;if((K|0)<=(g|0)){t=f+(o<<1)+2876|0;b[t>>1]=(b[t>>1]|0)+1<<16>>16;if((K|0)<(s|0)){N=0}else{N=c[r+(K-s<<2)>>2]|0}t=aa(e[I+(K<<2)>>1]|0,N+o|0)|0;c[u>>2]=t+(c[u>>2]|0)}t=M+1|0;if((t|0)==573){O=n;break}else{M=t;J=n}}}else{J=p;M=0;while(1){w=c[f+(J<<2)+2908>>2]|0;n=I+(w<<2)+2|0;t=e[I+(e[n>>1]<<2)+2>>1]|0;o=(t|0)<(m|0);K=o?t+1|0:m;t=(o&1^1)+M|0;b[n>>1]=K;if((w|0)<=(g|0)){n=f+(K<<1)+2876|0;b[n>>1]=(b[n>>1]|0)+1<<16>>16;if((w|0)<(s|0)){P=0}else{P=c[r+(w-s<<2)>>2]|0}n=e[I+(w<<2)>>1]|0;o=aa(n,P+K|0)|0;c[u>>2]=o+(c[u>>2]|0);o=aa((e[l+(w<<2)+2>>1]|0)+P|0,n)|0;c[L>>2]=o+(c[L>>2]|0)}o=J+1|0;if((o|0)==573){O=t;break}else{J=o;M=t}}}if((O|0)!=0){M=f+(m<<1)+2876|0;J=O;do{L=m;while(1){t=L+ -1|0;Q=f+(t<<1)+2876|0;R=b[Q>>1]|0;if(R<<16>>16==0){L=t}else{break}}b[Q>>1]=R+ -1<<16>>16;t=f+(L<<1)+2876|0;b[t>>1]=(e[t>>1]|0)+2;S=(b[M>>1]|0)+ -1<<16>>16;b[M>>1]=S;J=J+ -2|0}while((J|0)>0);if((m|0)!=0){J=S;M=m;t=573;while(1){o=M&65535;if(J<<16>>16==0){T=t}else{n=t;w=J&65535;while(1){K=n;do{K=K+ -1|0;U=c[f+(K<<2)+2908>>2]|0}while((U|0)>(g|0));H=I+(U<<2)+2|0;B=e[H>>1]|0;if((B|0)!=(M|0)){A=aa(e[I+(U<<2)>>1]|0,M-B|0)|0;c[u>>2]=A+(c[u>>2]|0);b[H>>1]=o}H=w+ -1|0;if((H|0)==0){T=K;break}else{n=K;w=H}}}w=M+ -1|0;if((w|0)==0){break d}J=b[f+(w<<1)+2876>>1]|0;M=w;t=T}}}}}while(0);T=1;U=0;do{U=(e[f+(T+ -1<<1)+2876>>1]|0)+(U&65534)<<1;b[j+(T<<1)>>1]=U;T=T+1|0}while((T|0)!=16);if((x|0)<0){i=h;return}else{V=0}while(1){T=b[k+(V<<2)+2>>1]|0;U=T&65535;if(!(T<<16>>16==0)){T=j+(U<<1)|0;f=b[T>>1]|0;b[T>>1]=f+1<<16>>16;T=U;U=f&65535;f=0;while(1){W=f|U&1;T=T+ -1|0;if((T|0)<=0){break}else{U=U>>>1;f=W<<1}}b[k+(V<<2)>>1]=W}if((V|0)==(x|0)){break}else{V=V+1|0}}i=h;return}function Uf(f,g,h){f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0;j=i;k=f+5792|0;if((c[k>>2]|0)==0){l=c[f+5820>>2]|0;m=b[f+5816>>1]|0}else{n=f+5796|0;o=f+5784|0;p=f+5820|0;q=f+5816|0;r=f+20|0;s=f+8|0;t=0;while(1){u=b[(c[n>>2]|0)+(t<<1)>>1]|0;v=u&65535;w=t+1|0;x=d[(c[o>>2]|0)+t|0]|0;do{if(u<<16>>16==0){y=e[g+(x<<2)+2>>1]|0;z=c[p>>2]|0;A=e[g+(x<<2)>>1]|0;B=e[q>>1]|0|A<>1]=C;if((z|0)>(16-y|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=B;B=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=B;B=c[p>>2]|0;D=A>>>(16-B|0)&65535;b[q>>1]=D;A=y+ -16+B|0;c[p>>2]=A;E=D;F=A;break}else{A=z+y|0;c[p>>2]=A;E=C;F=A;break}}else{A=d[25272+x|0]|0;C=(A|256)+1|0;y=e[g+(C<<2)+2>>1]|0;z=c[p>>2]|0;D=e[g+(C<<2)>>1]|0;C=e[q>>1]|0|D<>1]=B;if((z|0)>(16-y|0)){G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=C;C=(e[q>>1]|0)>>>8&255;G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=C;C=c[p>>2]|0;G=D>>>(16-C|0)&65535;b[q>>1]=G;H=G;I=y+ -16+C|0}else{H=B;I=z+y|0}c[p>>2]=I;y=c[26872+(A<<2)>>2]|0;do{if((A+ -8|0)>>>0<20){z=x-(c[26992+(A<<2)>>2]|0)&65535;B=z<>1]=C;if((I|0)>(16-y|0)){G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=B;B=(e[q>>1]|0)>>>8&255;G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=B;B=c[p>>2]|0;G=z>>>(16-B|0)&65535;b[q>>1]=G;z=y+ -16+B|0;c[p>>2]=z;J=z;K=G;break}else{G=I+y|0;c[p>>2]=G;J=G;K=C;break}}else{J=I;K=H}}while(0);y=v+ -1|0;if(y>>>0<256){L=y}else{L=(y>>>7)+256|0}A=d[24760+L|0]|0;C=e[h+(A<<2)+2>>1]|0;G=e[h+(A<<2)>>1]|0;z=K&65535|G<>1]=B;if((J|0)>(16-C|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=z;z=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=z;z=c[p>>2]|0;D=G>>>(16-z|0)&65535;b[q>>1]=D;M=C+ -16+z|0;N=D}else{M=J+C|0;N=B}c[p>>2]=M;B=c[27112+(A<<2)>>2]|0;if((A+ -4|0)>>>0<26){C=y-(c[27232+(A<<2)>>2]|0)&65535;A=C<>1]=y;if((M|0)>(16-B|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=A;A=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=A;A=c[p>>2]|0;D=C>>>(16-A|0)&65535;b[q>>1]=D;C=B+ -16+A|0;c[p>>2]=C;E=D;F=C;break}else{C=M+B|0;c[p>>2]=C;E=y;F=C;break}}else{E=N;F=M}}}while(0);if(w>>>0<(c[k>>2]|0)>>>0){t=w}else{l=F;m=E;break}}}E=g+1026|0;F=e[E>>1]|0;t=f+5820|0;k=e[g+1024>>1]|0;g=f+5816|0;M=m&65535|k<>1]=M;if((l|0)>(16-F|0)){m=f+20|0;N=c[m>>2]|0;c[m>>2]=N+1;p=f+8|0;a[(c[p>>2]|0)+N|0]=M;M=(e[g>>1]|0)>>>8&255;N=c[m>>2]|0;c[m>>2]=N+1;a[(c[p>>2]|0)+N|0]=M;M=c[t>>2]|0;b[g>>1]=k>>>(16-M|0);O=F+ -16+M|0;c[t>>2]=O;P=b[E>>1]|0;Q=P&65535;R=f+5812|0;c[R>>2]=Q;i=j;return}else{O=l+F|0;c[t>>2]=O;P=b[E>>1]|0;Q=P&65535;R=f+5812|0;c[R>>2]=Q;i=j;return}}function Vf(d,f,g){d=d|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0;h=i;j=b[f+2>>1]|0;k=j<<16>>16==0;l=d+2754|0;m=d+5820|0;n=d+2752|0;o=d+5816|0;p=d+20|0;q=d+8|0;r=d+2758|0;s=d+2756|0;t=d+2750|0;u=d+2748|0;v=k?138:7;w=k?3:4;k=0;x=j&65535;j=-1;a:while(1){y=0;z=k;while(1){if((z|0)>(g|0)){break a}z=z+1|0;A=b[f+(z<<2)+2>>1]|0;B=A&65535;C=y+1|0;D=(x|0)==(B|0);if(!((C|0)<(v|0)&D)){break}else{y=C}}do{if((C|0)>=(w|0)){if((x|0)!=0){if((x|0)==(j|0)){E=b[o>>1]|0;F=c[m>>2]|0;G=C}else{H=e[d+(x<<2)+2686>>1]|0;I=c[m>>2]|0;J=e[d+(x<<2)+2684>>1]|0;K=e[o>>1]|0|J<>1]=L;if((I|0)>(16-H|0)){M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=c[m>>2]|0;M=J>>>(16-K|0)&65535;b[o>>1]=M;N=M;O=H+ -16+K|0}else{N=L;O=I+H|0}c[m>>2]=O;E=N;F=O;G=y}H=e[t>>1]|0;I=e[u>>1]|0;L=E&65535|I<>1]=L;if((F|0)>(16-H|0)){K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=L;K=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=c[m>>2]|0;M=I>>>(16-K|0);b[o>>1]=M;P=H+ -16+K|0;Q=M}else{P=F+H|0;Q=L}c[m>>2]=P;L=G+65533&65535;H=Q&65535|L<>1]=H;if((P|0)>14){M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=H;H=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=H;H=c[m>>2]|0;b[o>>1]=L>>>(16-H|0);c[m>>2]=H+ -14;break}else{c[m>>2]=P+2;break}}if((C|0)<11){H=e[l>>1]|0;L=c[m>>2]|0;M=e[n>>1]|0;K=e[o>>1]|0|M<>1]=K;if((L|0)>(16-H|0)){I=c[p>>2]|0;c[p>>2]=I+1;a[(c[q>>2]|0)+I|0]=K;I=(e[o>>1]|0)>>>8&255;J=c[p>>2]|0;c[p>>2]=J+1;a[(c[q>>2]|0)+J|0]=I;I=c[m>>2]|0;J=M>>>(16-I|0);b[o>>1]=J;R=H+ -16+I|0;S=J}else{R=L+H|0;S=K}c[m>>2]=R;K=y+65534&65535;H=S&65535|K<>1]=H;if((R|0)>13){L=c[p>>2]|0;c[p>>2]=L+1;a[(c[q>>2]|0)+L|0]=H;H=(e[o>>1]|0)>>>8&255;L=c[p>>2]|0;c[p>>2]=L+1;a[(c[q>>2]|0)+L|0]=H;H=c[m>>2]|0;b[o>>1]=K>>>(16-H|0);c[m>>2]=H+ -13;break}else{c[m>>2]=R+3;break}}else{H=e[r>>1]|0;K=c[m>>2]|0;L=e[s>>1]|0;J=e[o>>1]|0|L<>1]=J;if((K|0)>(16-H|0)){I=c[p>>2]|0;c[p>>2]=I+1;a[(c[q>>2]|0)+I|0]=J;I=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=I;I=c[m>>2]|0;M=L>>>(16-I|0);b[o>>1]=M;T=H+ -16+I|0;U=M}else{T=K+H|0;U=J}c[m>>2]=T;J=y+65526&65535;H=U&65535|J<>1]=H;if((T|0)>9){K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=H;H=(e[o>>1]|0)>>>8&255;K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=H;H=c[m>>2]|0;b[o>>1]=J>>>(16-H|0);c[m>>2]=H+ -9;break}else{c[m>>2]=T+7;break}}}else{H=d+(x<<2)+2686|0;J=d+(x<<2)+2684|0;K=c[m>>2]|0;M=b[o>>1]|0;I=C;while(1){L=e[H>>1]|0;V=e[J>>1]|0;W=M&65535|V<>1]=X;if((K|0)>(16-L|0)){Y=c[p>>2]|0;c[p>>2]=Y+1;a[(c[q>>2]|0)+Y|0]=W;W=(e[o>>1]|0)>>>8&255;Y=c[p>>2]|0;c[p>>2]=Y+1;a[(c[q>>2]|0)+Y|0]=W;W=c[m>>2]|0;Y=V>>>(16-W|0)&65535;b[o>>1]=Y;Z=Y;_=L+ -16+W|0}else{Z=X;_=K+L|0}c[m>>2]=_;I=I+ -1|0;if((I|0)==0){break}else{K=_;M=Z}}}}while(0);if(A<<16>>16==0){$=x;v=138;w=3;k=z;x=B;j=$;continue}$=x;v=D?6:7;w=D?3:4;k=z;x=B;j=$}i=h;return}function Wf(a,c,d){a=a|0;c=c|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;f=i;g=b[c+2>>1]|0;h=g<<16>>16==0;b[c+(d+1<<2)+2>>1]=-1;j=a+2752|0;k=a+2756|0;l=a+2748|0;m=h?138:7;n=h?3:4;h=0;o=g&65535;g=-1;a:while(1){p=0;q=h;do{if((q|0)>(d|0)){break a}q=q+1|0;r=b[c+(q<<2)+2>>1]|0;s=r&65535;p=p+1|0;t=(o|0)==(s|0)}while((p|0)<(m|0)&t);do{if((p|0)>=(n|0)){if((o|0)==0){if((p|0)<11){b[j>>1]=(b[j>>1]|0)+1<<16>>16;break}else{b[k>>1]=(b[k>>1]|0)+1<<16>>16;break}}else{if((o|0)!=(g|0)){u=a+(o<<2)+2684|0;b[u>>1]=(b[u>>1]|0)+1<<16>>16}b[l>>1]=(b[l>>1]|0)+1<<16>>16;break}}else{u=a+(o<<2)+2684|0;b[u>>1]=(e[u>>1]|0)+p}}while(0);if(r<<16>>16==0){v=o;m=138;n=3;h=q;o=s;g=v;continue}v=o;m=t?6:7;n=t?3:4;h=q;o=s;g=v}i=f;return}function Xf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;a=i;d=gg(aa(c,b)|0)|0;i=a;return d|0}function Yf(a,b){a=a|0;b=b|0;a=i;hg(b);i=a;return}function Zf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0;f=i;i=i+944|0;g=f+680|0;h=f+424|0;j=f+192|0;k=f;l=aa(d,b)|0;if((l|0)==0){i=f;return}b=l-d|0;c[k+4>>2]=d;c[k>>2]=d;m=d;n=d;o=2;while(1){p=m+d+n|0;c[k+(o<<2)>>2]=p;if(p>>>0>>0){q=n;n=p;o=o+1|0;m=q}else{break}}m=0-d|0;o=a+b|0;if((b|0)>0){b=(d|0)==0;n=d>>>0>256?256:d;l=(n|0)==(d|0);q=o;p=1;r=0;s=a;t=1;while(1){do{if((p&3|0)!=3){u=t+ -1|0;a:do{if((c[k+(u<<2)>>2]|0)>>>0<(q-s|0)>>>0){c[j>>2]=s;if((t|0)>1){v=t;w=s;x=s;y=1;while(1){z=w+m|0;A=v+ -2|0;B=w+(0-((c[k+(A<<2)>>2]|0)+d))|0;if((nb[e&7](x,B)|0)>-1?(nb[e&7](x,z)|0)>-1:0){C=y;break}D=y+1|0;E=j+(y<<2)|0;if((nb[e&7](B,z)|0)>-1){c[E>>2]=B;F=B;G=v+ -1|0}else{c[E>>2]=z;F=z;G=A}if((G|0)<=1){C=D;break}v=G;w=F;x=c[j>>2]|0;y=D}if((C|0)>=2?(y=j+(C<<2)|0,c[y>>2]=g,!b):0){if((C|0)>0){H=d;I=g}else{x=c[j>>2]|0;Kg(g|0,x|0,n|0)|0;if(l){break}else{J=d;K=n}while(1){J=J-K|0;K=J>>>0>256?256:J;Kg(g|0,x|0,K|0)|0;if((J|0)==(K|0)){break a}}}while(1){x=H>>>0>256?256:H;w=c[j>>2]|0;Kg(I|0,w|0,x|0)|0;v=w;w=0;while(1){D=w+1|0;A=c[j+(D<<2)>>2]|0;Kg(v|0,A|0,x|0)|0;c[j+(w<<2)>>2]=v+x;if((D|0)==(C|0)){break}else{v=A;w=D}}if((H|0)==(x|0)){break a}H=H-x|0;I=c[y>>2]|0}}}}else{_f(s,d,e,p,r,t,0,k)}}while(0);if((t|0)==1){L=p<<1;M=p>>>31|r<<1;N=0;break}else{y=u>>>0>31;w=y?0:p;v=y?t+ -33|0:u;L=w<>>(32-v|0)|(y?p:r)<>2]=s;b:do{if((t|0)>1){v=t;y=s;w=s;D=1;while(1){A=y+m|0;z=v+ -2|0;E=y+(0-((c[k+(z<<2)>>2]|0)+d))|0;if((nb[e&7](w,E)|0)>-1?(nb[e&7](w,A)|0)>-1:0){O=D;break}B=D+1|0;P=j+(D<<2)|0;if((nb[e&7](E,A)|0)>-1){c[P>>2]=E;Q=E;R=v+ -1|0}else{c[P>>2]=A;Q=A;R=z}if((R|0)<=1){O=B;break}v=R;y=Q;w=c[j>>2]|0;D=B}if((O|0)>=2?(D=j+(O<<2)|0,c[D>>2]=h,!b):0){if((O|0)>0){S=d;T=h}else{w=c[j>>2]|0;Kg(h|0,w|0,n|0)|0;if(l){break}else{U=d;V=n}while(1){U=U-V|0;V=U>>>0>256?256:U;Kg(h|0,w|0,V|0)|0;if((U|0)==(V|0)){break b}}}while(1){w=S>>>0>256?256:S;y=c[j>>2]|0;Kg(T|0,y|0,w|0)|0;v=y;y=0;while(1){B=y+1|0;z=c[j+(B<<2)>>2]|0;Kg(v|0,z|0,w|0)|0;c[j+(y<<2)>>2]=v+w;if((B|0)==(O|0)){break}else{v=z;y=B}}if((S|0)==(w|0)){break b}S=S-w|0;T=c[D>>2]|0}}}}while(0);L=p>>>2|r<<30;M=r>>>2;N=t+2|0}}while(0);u=L|1;D=s+d|0;if(D>>>0>>0){p=u;r=M;s=D;t=N}else{W=M;X=u;Y=D;Z=N;break}}}else{W=0;X=1;Y=a;Z=1}_f(Y,d,e,X,W,Z,0,k);a=X;X=W;W=Y;Y=Z;while(1){if((Y|0)==1){if((a|0)==1){if((X|0)==0){break}else{_=52}}}else{_=52}if((_|0)==52?(_=0,(Y|0)>=2):0){Z=a>>>30;N=Y+ -2|0;M=(a<<1&2147483646|Z<<31)^3;t=(Z|X<<2)>>>1;_f(W+(0-((c[k+(N<<2)>>2]|0)+d))|0,d,e,M,t,Y+ -1|0,1,k);s=t<<1|Z&1;Z=M<<1|1;M=W+m|0;_f(M,d,e,Z,s,N,1,k);a=Z;X=s;W=M;Y=N;continue}N=a+ -1|0;if((N|0)!=0){if((N&1|0)==0){M=N;N=0;do{N=N+1|0;M=M>>>1}while((M&1|0)==0);if((N|0)!=0){$=N}else{_=57}}else{_=57}if((_|0)==57){_=0;if((X|0)!=0){if((X&1|0)==0){M=X;s=0;while(1){Z=s+1|0;t=M>>>1;if((t&1|0)==0){M=t;s=Z}else{ba=Z;break}}}else{ba=0}}else{ba=32}$=(ba|0)==0?0:ba+32|0}if($>>>0>31){ca=$;_=62}else{da=$;ea=a;fa=X;ga=$}}else{ca=32;_=62}if((_|0)==62){_=0;da=ca+ -32|0;ea=X;fa=0;ga=ca}a=fa<<32-da|ea>>>da;X=fa>>>da;W=W+m|0;Y=ga+Y|0}i=f;return}function _f(a,b,d,e,f,g,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0;k=i;i=i+752|0;l=k+232|0;m=k+488|0;n=k;c[n>>2]=a;o=0-b|0;a:do{if((e|0)==1&(f|0)==0){p=a;q=g;r=h;s=1;t=18}else{u=g;v=a;w=h;x=e;y=f;z=a;A=1;while(1){B=v+(0-(c[j+(u<<2)>>2]|0))|0;if((nb[d&7](B,z)|0)<1){p=v;q=u;r=w;s=A;t=18;break a}if((w|0)==0&(u|0)>1){C=c[j+(u+ -2<<2)>>2]|0;if((nb[d&7](v+o|0,B)|0)>-1){D=v;E=u;F=A;break a}if((nb[d&7](v+(0-(C+b))|0,B)|0)>-1){D=v;E=u;F=A;break a}}C=A+1|0;c[n+(A<<2)>>2]=B;G=x+ -1|0;if((G|0)!=0){if((G&1|0)==0){H=G;G=0;do{G=G+1|0;H=H>>>1}while((H&1|0)==0);if((G|0)!=0){I=G}else{t=10}}else{t=10}if((t|0)==10){t=0;if((y|0)!=0){if((y&1|0)==0){H=y;J=0;while(1){K=J+1|0;L=H>>>1;if((L&1|0)==0){H=L;J=K}else{M=K;break}}}else{M=0}}else{M=32}I=(M|0)==0?0:M+32|0}if(I>>>0>31){N=I;t=15}else{O=I;P=x;Q=y;R=I}}else{N=32;t=15}if((t|0)==15){t=0;O=N+ -32|0;P=y;Q=0;R=N}J=Q<<32-O|P>>>O;H=Q>>>O;G=R+u|0;if((J|0)==1&(H|0)==0){D=B;E=G;F=C;break a}u=G;v=B;w=0;x=J;y=H;z=c[n>>2]|0;A=C}}}while(0);if((t|0)==18){if((r|0)==0){D=p;E=q;F=s}else{i=k;return}}b:do{if((F|0)>=2?(s=n+(F<<2)|0,c[s>>2]=l,(b|0)!=0):0){if((F|0)>0){S=b;T=l}else{q=b>>>0>256?256:b;p=c[n>>2]|0;Kg(l|0,p|0,q|0)|0;if((q|0)==(b|0)){break}else{U=b;V=q}while(1){U=U-V|0;V=U>>>0>256?256:U;Kg(l|0,p|0,V|0)|0;if((U|0)==(V|0)){break b}}}while(1){p=S>>>0>256?256:S;q=c[n>>2]|0;Kg(T|0,q|0,p|0)|0;r=q;q=0;while(1){t=q+1|0;R=c[n+(t<<2)>>2]|0;Kg(r|0,R|0,p|0)|0;c[n+(q<<2)>>2]=r+p;if((t|0)==(F|0)){break}else{r=R;q=t}}if((S|0)==(p|0)){break b}S=S-p|0;T=c[s>>2]|0}}}while(0);c[l>>2]=D;c:do{if((E|0)>1){T=E;S=D;F=D;n=1;while(1){V=S+o|0;U=T+ -2|0;s=S+(0-((c[j+(U<<2)>>2]|0)+b))|0;if((nb[d&7](F,s)|0)>-1?(nb[d&7](F,V)|0)>-1:0){W=n;break}q=n+1|0;r=l+(n<<2)|0;if((nb[d&7](s,V)|0)>-1){c[r>>2]=s;X=s;Y=T+ -1|0}else{c[r>>2]=V;X=V;Y=U}if((Y|0)<=1){W=q;break}T=Y;S=X;F=c[l>>2]|0;n=q}if((W|0)>=2?(n=l+(W<<2)|0,c[n>>2]=m,(b|0)!=0):0){if((W|0)>0){Z=b;_=m}else{F=b>>>0>256?256:b;S=c[l>>2]|0;Kg(m|0,S|0,F|0)|0;if((F|0)==(b|0)){$=m;break}else{aa=b;ba=F}while(1){F=aa-ba|0;T=F>>>0>256?256:F;Kg(m|0,S|0,T|0)|0;if((F|0)==(T|0)){$=m;break c}else{aa=F;ba=T}}}while(1){S=Z>>>0>256?256:Z;T=c[l>>2]|0;Kg(_|0,T|0,S|0)|0;F=T;T=0;while(1){q=T+1|0;U=c[l+(q<<2)>>2]|0;Kg(F|0,U|0,S|0)|0;c[l+(T<<2)>>2]=F+S;if((q|0)==(W|0)){break}else{F=U;T=q}}if((Z|0)==(S|0)){$=m;break c}Z=Z-S|0;_=c[n>>2]|0}}else{$=m}}else{$=m}}while(0);i=k;return}function $f(b,c){b=b|0;c=c|0;var d=0,e=0;d=i;e=ag(b,c)|0;i=d;return((a[e]|0)==(c&255)<<24>>24?e:0)|0}function ag(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;f=d&255;if((f|0)==0){g=b+(Dg(b|0)|0)|0;i=e;return g|0}a:do{if((b&3|0)!=0){h=d&255;j=b;while(1){k=a[j]|0;if(k<<24>>24==0){g=j;l=13;break}m=j+1|0;if(k<<24>>24==h<<24>>24){g=j;l=13;break}if((m&3|0)==0){n=m;break a}else{j=m}}if((l|0)==13){i=e;return g|0}}else{n=b}}while(0);b=aa(f,16843009)|0;f=c[n>>2]|0;b:do{if(((f&-2139062144^-2139062144)&f+ -16843009|0)==0){l=f;j=n;while(1){h=l^b;m=j+4|0;if(((h&-2139062144^-2139062144)&h+ -16843009|0)!=0){o=j;break b}h=c[m>>2]|0;if(((h&-2139062144^-2139062144)&h+ -16843009|0)==0){l=h;j=m}else{o=m;break}}}else{o=n}}while(0);n=d&255;d=o;while(1){o=a[d]|0;if(o<<24>>24==0|o<<24>>24==n<<24>>24){g=d;break}else{d=d+1|0}}i=e;return g|0}function bg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+32|0;f=e;g=a[d]|0;if(!(g<<24>>24==0)?(a[d+1|0]|0)!=0:0){c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[f+24>>2]=0;c[f+28>>2]=0;h=d;d=g;do{j=d&255;k=f+(j>>>5<<2)|0;c[k>>2]=c[k>>2]|1<<(j&31);h=h+1|0;d=a[h]|0}while(!(d<<24>>24==0));d=a[b]|0;a:do{if(d<<24>>24==0){l=b}else{h=b;j=d;while(1){k=j&255;m=h+1|0;if((c[f+(k>>>5<<2)>>2]&1<<(k&31)|0)!=0){l=h;break a}k=a[m]|0;if(k<<24>>24==0){l=m;break}else{h=m;j=k}}}}while(0);n=l-b|0;i=e;return n|0}n=(ag(b,g<<24>>24)|0)-b|0;i=e;return n|0}function cg(a){a=a|0;var b=0,c=0,d=0,e=0;b=i;c=(Dg(a|0)|0)+1|0;d=gg(c)|0;if((d|0)==0){e=0;i=b;return e|0}Kg(d|0,a|0,c|0)|0;e=d;i=b;return e|0}function dg(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;f=b+(Dg(b|0)|0)|0;a:do{if((d|0)==0){g=f}else{h=d;j=c;k=f;while(1){l=a[j]|0;if(l<<24>>24==0){g=k;break a}m=h+ -1|0;n=k+1|0;a[k]=l;if((m|0)==0){g=n;break}else{h=m;j=j+1|0;k=n}}}}while(0);a[g]=0;i=e;return b|0}function eg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e;c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[f+24>>2]=0;c[f+28>>2]=0;g=a[d]|0;if(g<<24>>24==0){h=0;i=e;return h|0}if((a[d+1|0]|0)==0){j=b;while(1){if((a[j]|0)==g<<24>>24){j=j+1|0}else{break}}h=j-b|0;i=e;return h|0}else{k=d;l=g}do{g=l&255;d=f+(g>>>5<<2)|0;c[d>>2]=c[d>>2]|1<<(g&31);k=k+1|0;l=a[k]|0}while(!(l<<24>>24==0));l=a[b]|0;a:do{if(l<<24>>24==0){m=b}else{k=b;g=l;while(1){d=g&255;j=k+1|0;if((c[f+(d>>>5<<2)>>2]&1<<(d&31)|0)==0){m=k;break a}d=a[j]|0;if(d<<24>>24==0){m=j;break}else{k=j;g=d}}}}while(0);h=m-b|0;i=e;return h|0}function fg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;e=i;if((b|0)==0){f=c[6912]|0;if((f|0)==0){g=0;i=e;return g|0}else{h=f}}else{h=b}b=eg(h,d)|0;f=h+b|0;if((a[f]|0)==0){c[6912]=0;g=0;i=e;return g|0}j=(bg(f,d)|0)+b|0;b=h+j|0;c[6912]=b;if((a[b]|0)==0){c[6912]=0;g=f;i=e;return g|0}else{c[6912]=h+(j+1);a[b]=0;g=f;i=e;return g|0}return 0} + + + +function gg(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ja=0,Ka=0,La=0,Ma=0;b=i;do{if(a>>>0<245){if(a>>>0<11){d=16}else{d=a+11&-8}e=d>>>3;f=c[6914]|0;g=f>>>e;if((g&3|0)!=0){h=(g&1^1)+e|0;j=h<<1;k=27696+(j<<2)|0;l=27696+(j+2<<2)|0;j=c[l>>2]|0;m=j+8|0;n=c[m>>2]|0;do{if((k|0)!=(n|0)){if(n>>>0<(c[27672>>2]|0)>>>0){_a()}o=n+12|0;if((c[o>>2]|0)==(j|0)){c[o>>2]=k;c[l>>2]=n;break}else{_a()}}else{c[6914]=f&~(1<>2]=n|3;l=j+(n|4)|0;c[l>>2]=c[l>>2]|1;p=m;i=b;return p|0}if(d>>>0>(c[27664>>2]|0)>>>0){if((g|0)!=0){l=2<>>12&16;k=l>>>n;l=k>>>5&8;o=k>>>l;k=o>>>2&4;q=o>>>k;o=q>>>1&2;r=q>>>o;q=r>>>1&1;s=(l|n|k|o|q)+(r>>>q)|0;q=s<<1;r=27696+(q<<2)|0;o=27696+(q+2<<2)|0;q=c[o>>2]|0;k=q+8|0;n=c[k>>2]|0;do{if((r|0)!=(n|0)){if(n>>>0<(c[27672>>2]|0)>>>0){_a()}l=n+12|0;if((c[l>>2]|0)==(q|0)){c[l>>2]=r;c[o>>2]=n;break}else{_a()}}else{c[6914]=f&~(1<>2]=d|3;o=q+d|0;c[q+(d|4)>>2]=n|1;c[q+f>>2]=n;f=c[27664>>2]|0;if((f|0)!=0){r=c[27676>>2]|0;e=f>>>3;f=e<<1;g=27696+(f<<2)|0;m=c[6914]|0;j=1<>2]|0;if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{t=e;u=h}}else{c[6914]=m|j;t=27696+(f+2<<2)|0;u=g}c[t>>2]=r;c[u+12>>2]=r;c[r+8>>2]=u;c[r+12>>2]=g}c[27664>>2]=n;c[27676>>2]=o;p=k;i=b;return p|0}o=c[27660>>2]|0;if((o|0)!=0){n=(o&0-o)+ -1|0;o=n>>>12&16;g=n>>>o;n=g>>>5&8;r=g>>>n;g=r>>>2&4;f=r>>>g;r=f>>>1&2;j=f>>>r;f=j>>>1&1;m=c[27960+((n|o|g|r|f)+(j>>>f)<<2)>>2]|0;f=(c[m+4>>2]&-8)-d|0;j=m;r=m;while(1){m=c[j+16>>2]|0;if((m|0)==0){g=c[j+20>>2]|0;if((g|0)==0){break}else{v=g}}else{v=m}m=(c[v+4>>2]&-8)-d|0;g=m>>>0>>0;f=g?m:f;j=v;r=g?v:r}j=c[27672>>2]|0;if(r>>>0>>0){_a()}k=r+d|0;if(!(r>>>0>>0)){_a()}q=c[r+24>>2]|0;s=c[r+12>>2]|0;do{if((s|0)==(r|0)){g=r+20|0;m=c[g>>2]|0;if((m|0)==0){o=r+16|0;n=c[o>>2]|0;if((n|0)==0){w=0;break}else{x=n;y=o}}else{x=m;y=g}while(1){g=x+20|0;m=c[g>>2]|0;if((m|0)!=0){x=m;y=g;continue}g=x+16|0;m=c[g>>2]|0;if((m|0)==0){break}else{x=m;y=g}}if(y>>>0>>0){_a()}else{c[y>>2]=0;w=x;break}}else{g=c[r+8>>2]|0;if(g>>>0>>0){_a()}m=g+12|0;if((c[m>>2]|0)!=(r|0)){_a()}o=s+8|0;if((c[o>>2]|0)==(r|0)){c[m>>2]=s;c[o>>2]=g;w=s;break}else{_a()}}}while(0);do{if((q|0)!=0){s=c[r+28>>2]|0;j=27960+(s<<2)|0;if((r|0)==(c[j>>2]|0)){c[j>>2]=w;if((w|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}s=q+16|0;if((c[s>>2]|0)==(r|0)){c[s>>2]=w}else{c[q+20>>2]=w}if((w|0)==0){break}}if(w>>>0<(c[27672>>2]|0)>>>0){_a()}c[w+24>>2]=q;s=c[r+16>>2]|0;do{if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+16>>2]=s;c[s+24>>2]=w;break}}}while(0);s=c[r+20>>2]|0;if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+20>>2]=s;c[s+24>>2]=w;break}}}}while(0);if(f>>>0<16){q=f+d|0;c[r+4>>2]=q|3;s=r+(q+4)|0;c[s>>2]=c[s>>2]|1}else{c[r+4>>2]=d|3;c[r+(d|4)>>2]=f|1;c[r+(f+d)>>2]=f;s=c[27664>>2]|0;if((s|0)!=0){q=c[27676>>2]|0;j=s>>>3;s=j<<1;g=27696+(s<<2)|0;o=c[6914]|0;m=1<>2]|0;if(n>>>0<(c[27672>>2]|0)>>>0){_a()}else{z=j;A=n}}else{c[6914]=o|m;z=27696+(s+2<<2)|0;A=g}c[z>>2]=q;c[A+12>>2]=q;c[q+8>>2]=A;c[q+12>>2]=g}c[27664>>2]=f;c[27676>>2]=k}p=r+8|0;i=b;return p|0}else{B=d}}else{B=d}}else{if(!(a>>>0>4294967231)){g=a+11|0;q=g&-8;s=c[27660>>2]|0;if((s|0)!=0){m=0-q|0;o=g>>>8;if((o|0)!=0){if(q>>>0>16777215){C=31}else{g=(o+1048320|0)>>>16&8;n=o<>>16&4;j=n<>>16&2;h=14-(o|g|n)+(j<>>15)|0;C=q>>>(h+7|0)&1|h<<1}}else{C=0}h=c[27960+(C<<2)>>2]|0;a:do{if((h|0)==0){D=m;E=0;F=0}else{if((C|0)==31){G=0}else{G=25-(C>>>1)|0}n=m;j=0;g=q<>2]&-8;H=l-q|0;if(H>>>0>>0){if((l|0)==(q|0)){D=H;E=o;F=o;break a}else{I=H;J=o}}else{I=n;J=e}H=c[o+20>>2]|0;l=c[o+(g>>>31<<2)+16>>2]|0;K=(H|0)==0|(H|0)==(l|0)?j:H;if((l|0)==0){D=I;E=K;F=J;break}else{n=I;j=K;g=g<<1;o=l;e=J}}}}while(0);if((E|0)==0&(F|0)==0){h=2<>>12&16;r=h>>>m;h=r>>>5&8;k=r>>>h;r=k>>>2&4;f=k>>>r;k=f>>>1&2;e=f>>>k;f=e>>>1&1;L=c[27960+((h|m|r|k|f)+(e>>>f)<<2)>>2]|0}else{L=E}if((L|0)==0){M=D;N=F}else{f=D;e=L;k=F;while(1){r=(c[e+4>>2]&-8)-q|0;m=r>>>0>>0;h=m?r:f;r=m?e:k;m=c[e+16>>2]|0;if((m|0)!=0){f=h;e=m;k=r;continue}m=c[e+20>>2]|0;if((m|0)==0){M=h;N=r;break}else{f=h;e=m;k=r}}}if((N|0)!=0?M>>>0<((c[27664>>2]|0)-q|0)>>>0:0){k=c[27672>>2]|0;if(N>>>0>>0){_a()}e=N+q|0;if(!(N>>>0>>0)){_a()}f=c[N+24>>2]|0;s=c[N+12>>2]|0;do{if((s|0)==(N|0)){r=N+20|0;m=c[r>>2]|0;if((m|0)==0){h=N+16|0;o=c[h>>2]|0;if((o|0)==0){O=0;break}else{P=o;Q=h}}else{P=m;Q=r}while(1){r=P+20|0;m=c[r>>2]|0;if((m|0)!=0){P=m;Q=r;continue}r=P+16|0;m=c[r>>2]|0;if((m|0)==0){break}else{P=m;Q=r}}if(Q>>>0>>0){_a()}else{c[Q>>2]=0;O=P;break}}else{r=c[N+8>>2]|0;if(r>>>0>>0){_a()}m=r+12|0;if((c[m>>2]|0)!=(N|0)){_a()}h=s+8|0;if((c[h>>2]|0)==(N|0)){c[m>>2]=s;c[h>>2]=r;O=s;break}else{_a()}}}while(0);do{if((f|0)!=0){s=c[N+28>>2]|0;k=27960+(s<<2)|0;if((N|0)==(c[k>>2]|0)){c[k>>2]=O;if((O|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}s=f+16|0;if((c[s>>2]|0)==(N|0)){c[s>>2]=O}else{c[f+20>>2]=O}if((O|0)==0){break}}if(O>>>0<(c[27672>>2]|0)>>>0){_a()}c[O+24>>2]=f;s=c[N+16>>2]|0;do{if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[O+16>>2]=s;c[s+24>>2]=O;break}}}while(0);s=c[N+20>>2]|0;if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[O+20>>2]=s;c[s+24>>2]=O;break}}}}while(0);b:do{if(!(M>>>0<16)){c[N+4>>2]=q|3;c[N+(q|4)>>2]=M|1;c[N+(M+q)>>2]=M;f=M>>>3;if(M>>>0<256){s=f<<1;k=27696+(s<<2)|0;r=c[6914]|0;h=1<>2]|0;if(m>>>0<(c[27672>>2]|0)>>>0){_a()}else{R=f;S=m}}else{c[6914]=r|h;R=27696+(s+2<<2)|0;S=k}c[R>>2]=e;c[S+12>>2]=e;c[N+(q+8)>>2]=S;c[N+(q+12)>>2]=k;break}k=M>>>8;if((k|0)!=0){if(M>>>0>16777215){T=31}else{s=(k+1048320|0)>>>16&8;h=k<>>16&4;r=h<>>16&2;m=14-(k|s|h)+(r<>>15)|0;T=M>>>(m+7|0)&1|m<<1}}else{T=0}m=27960+(T<<2)|0;c[N+(q+28)>>2]=T;c[N+(q+20)>>2]=0;c[N+(q+16)>>2]=0;h=c[27660>>2]|0;r=1<>2]=h|r;c[m>>2]=e;c[N+(q+24)>>2]=m;c[N+(q+12)>>2]=e;c[N+(q+8)>>2]=e;break}r=c[m>>2]|0;if((T|0)==31){U=0}else{U=25-(T>>>1)|0}c:do{if((c[r+4>>2]&-8|0)!=(M|0)){m=M<>>31<<2)+16|0;s=c[V>>2]|0;if((s|0)==0){break}if((c[s+4>>2]&-8|0)==(M|0)){W=s;break c}else{m=m<<1;h=s}}if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[V>>2]=e;c[N+(q+24)>>2]=h;c[N+(q+12)>>2]=e;c[N+(q+8)>>2]=e;break b}}else{W=r}}while(0);r=W+8|0;m=c[r>>2]|0;s=c[27672>>2]|0;if(W>>>0>>0){_a()}if(m>>>0>>0){_a()}else{c[m+12>>2]=e;c[r>>2]=e;c[N+(q+8)>>2]=m;c[N+(q+12)>>2]=W;c[N+(q+24)>>2]=0;break}}else{m=M+q|0;c[N+4>>2]=m|3;r=N+(m+4)|0;c[r>>2]=c[r>>2]|1}}while(0);p=N+8|0;i=b;return p|0}else{B=q}}else{B=q}}else{B=-1}}}while(0);N=c[27664>>2]|0;if(!(B>>>0>N>>>0)){M=N-B|0;W=c[27676>>2]|0;if(M>>>0>15){c[27676>>2]=W+B;c[27664>>2]=M;c[W+(B+4)>>2]=M|1;c[W+N>>2]=M;c[W+4>>2]=B|3}else{c[27664>>2]=0;c[27676>>2]=0;c[W+4>>2]=N|3;M=W+(N+4)|0;c[M>>2]=c[M>>2]|1}p=W+8|0;i=b;return p|0}W=c[27668>>2]|0;if(B>>>0>>0){M=W-B|0;c[27668>>2]=M;W=c[27680>>2]|0;c[27680>>2]=W+B;c[W+(B+4)>>2]=M|1;c[W+4>>2]=B|3;p=W+8|0;i=b;return p|0}do{if((c[7032]|0)==0){W=Ia(30)|0;if((W+ -1&W|0)==0){c[28136>>2]=W;c[28132>>2]=W;c[28140>>2]=-1;c[28144>>2]=-1;c[28148>>2]=0;c[28100>>2]=0;c[7032]=(bb(0)|0)&-16^1431655768;break}else{_a()}}}while(0);W=B+48|0;M=c[28136>>2]|0;N=B+47|0;V=M+N|0;U=0-M|0;M=V&U;if(!(M>>>0>B>>>0)){p=0;i=b;return p|0}T=c[28096>>2]|0;if((T|0)!=0?(S=c[28088>>2]|0,R=S+M|0,R>>>0<=S>>>0|R>>>0>T>>>0):0){p=0;i=b;return p|0}d:do{if((c[28100>>2]&4|0)==0){T=c[27680>>2]|0;e:do{if((T|0)!=0){R=28104|0;while(1){S=c[R>>2]|0;if(!(S>>>0>T>>>0)?(X=R+4|0,(S+(c[X>>2]|0)|0)>>>0>T>>>0):0){break}S=c[R+8>>2]|0;if((S|0)==0){Y=182;break e}else{R=S}}if((R|0)!=0){S=V-(c[27668>>2]|0)&U;if(S>>>0<2147483647){O=Ca(S|0)|0;P=(O|0)==((c[R>>2]|0)+(c[X>>2]|0)|0);Z=O;_=S;$=P?O:-1;aa=P?S:0;Y=191}else{ba=0}}else{Y=182}}else{Y=182}}while(0);do{if((Y|0)==182){T=Ca(0)|0;if((T|0)!=(-1|0)){q=T;S=c[28132>>2]|0;P=S+ -1|0;if((P&q|0)==0){ca=M}else{ca=M-q+(P+q&0-S)|0}S=c[28088>>2]|0;q=S+ca|0;if(ca>>>0>B>>>0&ca>>>0<2147483647){P=c[28096>>2]|0;if((P|0)!=0?q>>>0<=S>>>0|q>>>0>P>>>0:0){ba=0;break}P=Ca(ca|0)|0;q=(P|0)==(T|0);Z=P;_=ca;$=q?T:-1;aa=q?ca:0;Y=191}else{ba=0}}else{ba=0}}}while(0);f:do{if((Y|0)==191){q=0-_|0;if(($|0)!=(-1|0)){da=$;ea=aa;Y=202;break d}do{if((Z|0)!=(-1|0)&_>>>0<2147483647&_>>>0>>0?(T=c[28136>>2]|0,P=N-_+T&0-T,P>>>0<2147483647):0){if((Ca(P|0)|0)==(-1|0)){Ca(q|0)|0;ba=aa;break f}else{fa=P+_|0;break}}else{fa=_}}while(0);if((Z|0)==(-1|0)){ba=aa}else{da=Z;ea=fa;Y=202;break d}}}while(0);c[28100>>2]=c[28100>>2]|4;ga=ba;Y=199}else{ga=0;Y=199}}while(0);if((((Y|0)==199?M>>>0<2147483647:0)?(ba=Ca(M|0)|0,M=Ca(0)|0,(M|0)!=(-1|0)&(ba|0)!=(-1|0)&ba>>>0>>0):0)?(fa=M-ba|0,M=fa>>>0>(B+40|0)>>>0,M):0){da=ba;ea=M?fa:ga;Y=202}if((Y|0)==202){ga=(c[28088>>2]|0)+ea|0;c[28088>>2]=ga;if(ga>>>0>(c[28092>>2]|0)>>>0){c[28092>>2]=ga}ga=c[27680>>2]|0;g:do{if((ga|0)!=0){fa=28104|0;while(1){ha=c[fa>>2]|0;ia=fa+4|0;ja=c[ia>>2]|0;if((da|0)==(ha+ja|0)){Y=214;break}M=c[fa+8>>2]|0;if((M|0)==0){break}else{fa=M}}if(((Y|0)==214?(c[fa+12>>2]&8|0)==0:0)?ga>>>0>=ha>>>0&ga>>>0>>0:0){c[ia>>2]=ja+ea;M=(c[27668>>2]|0)+ea|0;ba=ga+8|0;if((ba&7|0)==0){ka=0}else{ka=0-ba&7}ba=M-ka|0;c[27680>>2]=ga+ka;c[27668>>2]=ba;c[ga+(ka+4)>>2]=ba|1;c[ga+(M+4)>>2]=40;c[27684>>2]=c[28144>>2];break}if(da>>>0<(c[27672>>2]|0)>>>0){c[27672>>2]=da}M=da+ea|0;ba=28104|0;while(1){if((c[ba>>2]|0)==(M|0)){Y=224;break}Z=c[ba+8>>2]|0;if((Z|0)==0){break}else{ba=Z}}if((Y|0)==224?(c[ba+12>>2]&8|0)==0:0){c[ba>>2]=da;M=ba+4|0;c[M>>2]=(c[M>>2]|0)+ea;M=da+8|0;if((M&7|0)==0){la=0}else{la=0-M&7}M=da+(ea+8)|0;if((M&7|0)==0){ma=0}else{ma=0-M&7}M=da+(ma+ea)|0;fa=la+B|0;Z=da+fa|0;aa=M-(da+la)-B|0;c[da+(la+4)>>2]=B|3;h:do{if((M|0)!=(c[27680>>2]|0)){if((M|0)==(c[27676>>2]|0)){_=(c[27664>>2]|0)+aa|0;c[27664>>2]=_;c[27676>>2]=Z;c[da+(fa+4)>>2]=_|1;c[da+(_+fa)>>2]=_;break}_=ea+4|0;N=c[da+(_+ma)>>2]|0;if((N&3|0)==1){W=N&-8;$=N>>>3;do{if(!(N>>>0<256)){ca=c[da+((ma|24)+ea)>>2]|0;X=c[da+(ea+12+ma)>>2]|0;do{if((X|0)==(M|0)){U=ma|16;V=da+(_+U)|0;q=c[V>>2]|0;if((q|0)==0){R=da+(U+ea)|0;U=c[R>>2]|0;if((U|0)==0){na=0;break}else{oa=U;pa=R}}else{oa=q;pa=V}while(1){V=oa+20|0;q=c[V>>2]|0;if((q|0)!=0){oa=q;pa=V;continue}V=oa+16|0;q=c[V>>2]|0;if((q|0)==0){break}else{oa=q;pa=V}}if(pa>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[pa>>2]=0;na=oa;break}}else{V=c[da+((ma|8)+ea)>>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}q=V+12|0;if((c[q>>2]|0)!=(M|0)){_a()}R=X+8|0;if((c[R>>2]|0)==(M|0)){c[q>>2]=X;c[R>>2]=V;na=X;break}else{_a()}}}while(0);if((ca|0)!=0){X=c[da+(ea+28+ma)>>2]|0;h=27960+(X<<2)|0;if((M|0)==(c[h>>2]|0)){c[h>>2]=na;if((na|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}X=ca+16|0;if((c[X>>2]|0)==(M|0)){c[X>>2]=na}else{c[ca+20>>2]=na}if((na|0)==0){break}}if(na>>>0<(c[27672>>2]|0)>>>0){_a()}c[na+24>>2]=ca;X=ma|16;h=c[da+(X+ea)>>2]|0;do{if((h|0)!=0){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[na+16>>2]=h;c[h+24>>2]=na;break}}}while(0);h=c[da+(_+X)>>2]|0;if((h|0)!=0){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[na+20>>2]=h;c[h+24>>2]=na;break}}}}else{h=c[da+((ma|8)+ea)>>2]|0;ca=c[da+(ea+12+ma)>>2]|0;V=27696+($<<1<<2)|0;if((h|0)!=(V|0)){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}if((c[h+12>>2]|0)!=(M|0)){_a()}}if((ca|0)==(h|0)){c[6914]=c[6914]&~(1<<$);break}if((ca|0)!=(V|0)){if(ca>>>0<(c[27672>>2]|0)>>>0){_a()}V=ca+8|0;if((c[V>>2]|0)==(M|0)){qa=V}else{_a()}}else{qa=ca+8|0}c[h+12>>2]=ca;c[qa>>2]=h}}while(0);ra=da+((W|ma)+ea)|0;sa=W+aa|0}else{ra=M;sa=aa}$=ra+4|0;c[$>>2]=c[$>>2]&-2;c[da+(fa+4)>>2]=sa|1;c[da+(sa+fa)>>2]=sa;$=sa>>>3;if(sa>>>0<256){_=$<<1;N=27696+(_<<2)|0;h=c[6914]|0;ca=1<<$;if((h&ca|0)!=0){$=27696+(_+2<<2)|0;V=c[$>>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{ta=$;ua=V}}else{c[6914]=h|ca;ta=27696+(_+2<<2)|0;ua=N}c[ta>>2]=Z;c[ua+12>>2]=Z;c[da+(fa+8)>>2]=ua;c[da+(fa+12)>>2]=N;break}N=sa>>>8;if((N|0)!=0){if(sa>>>0>16777215){va=31}else{_=(N+1048320|0)>>>16&8;ca=N<<_;N=(ca+520192|0)>>>16&4;h=ca<>>16&2;V=14-(N|_|ca)+(h<>>15)|0;va=sa>>>(V+7|0)&1|V<<1}}else{va=0}V=27960+(va<<2)|0;c[da+(fa+28)>>2]=va;c[da+(fa+20)>>2]=0;c[da+(fa+16)>>2]=0;ca=c[27660>>2]|0;h=1<>2]=ca|h;c[V>>2]=Z;c[da+(fa+24)>>2]=V;c[da+(fa+12)>>2]=Z;c[da+(fa+8)>>2]=Z;break}h=c[V>>2]|0;if((va|0)==31){wa=0}else{wa=25-(va>>>1)|0}i:do{if((c[h+4>>2]&-8|0)!=(sa|0)){V=sa<>>31<<2)+16|0;_=c[xa>>2]|0;if((_|0)==0){break}if((c[_+4>>2]&-8|0)==(sa|0)){ya=_;break i}else{V=V<<1;ca=_}}if(xa>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[xa>>2]=Z;c[da+(fa+24)>>2]=ca;c[da+(fa+12)>>2]=Z;c[da+(fa+8)>>2]=Z;break h}}else{ya=h}}while(0);h=ya+8|0;W=c[h>>2]|0;V=c[27672>>2]|0;if(ya>>>0>>0){_a()}if(W>>>0>>0){_a()}else{c[W+12>>2]=Z;c[h>>2]=Z;c[da+(fa+8)>>2]=W;c[da+(fa+12)>>2]=ya;c[da+(fa+24)>>2]=0;break}}else{W=(c[27668>>2]|0)+aa|0;c[27668>>2]=W;c[27680>>2]=Z;c[da+(fa+4)>>2]=W|1}}while(0);p=da+(la|8)|0;i=b;return p|0}fa=28104|0;while(1){za=c[fa>>2]|0;if(!(za>>>0>ga>>>0)?(Aa=c[fa+4>>2]|0,Ba=za+Aa|0,Ba>>>0>ga>>>0):0){break}fa=c[fa+8>>2]|0}fa=za+(Aa+ -39)|0;if((fa&7|0)==0){Da=0}else{Da=0-fa&7}fa=za+(Aa+ -47+Da)|0;Z=fa>>>0<(ga+16|0)>>>0?ga:fa;fa=Z+8|0;aa=da+8|0;if((aa&7|0)==0){Ea=0}else{Ea=0-aa&7}aa=ea+ -40-Ea|0;c[27680>>2]=da+Ea;c[27668>>2]=aa;c[da+(Ea+4)>>2]=aa|1;c[da+(ea+ -36)>>2]=40;c[27684>>2]=c[28144>>2];c[Z+4>>2]=27;c[fa+0>>2]=c[28104>>2];c[fa+4>>2]=c[28108>>2];c[fa+8>>2]=c[28112>>2];c[fa+12>>2]=c[28116>>2];c[28104>>2]=da;c[28108>>2]=ea;c[28116>>2]=0;c[28112>>2]=fa;fa=Z+28|0;c[fa>>2]=7;if((Z+32|0)>>>0>>0){aa=fa;while(1){fa=aa+4|0;c[fa>>2]=7;if((aa+8|0)>>>0>>0){aa=fa}else{break}}}if((Z|0)!=(ga|0)){aa=Z-ga|0;fa=ga+(aa+4)|0;c[fa>>2]=c[fa>>2]&-2;c[ga+4>>2]=aa|1;c[ga+aa>>2]=aa;fa=aa>>>3;if(aa>>>0<256){M=fa<<1;ba=27696+(M<<2)|0;W=c[6914]|0;h=1<>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{Fa=fa;Ga=V}}else{c[6914]=W|h;Fa=27696+(M+2<<2)|0;Ga=ba}c[Fa>>2]=ga;c[Ga+12>>2]=ga;c[ga+8>>2]=Ga;c[ga+12>>2]=ba;break}ba=aa>>>8;if((ba|0)!=0){if(aa>>>0>16777215){Ha=31}else{M=(ba+1048320|0)>>>16&8;h=ba<>>16&4;W=h<>>16&2;V=14-(ba|M|h)+(W<>>15)|0;Ha=aa>>>(V+7|0)&1|V<<1}}else{Ha=0}V=27960+(Ha<<2)|0;c[ga+28>>2]=Ha;c[ga+20>>2]=0;c[ga+16>>2]=0;h=c[27660>>2]|0;W=1<>2]=h|W;c[V>>2]=ga;c[ga+24>>2]=V;c[ga+12>>2]=ga;c[ga+8>>2]=ga;break}W=c[V>>2]|0;if((Ha|0)==31){Ja=0}else{Ja=25-(Ha>>>1)|0}j:do{if((c[W+4>>2]&-8|0)!=(aa|0)){V=aa<>>31<<2)+16|0;M=c[Ka>>2]|0;if((M|0)==0){break}if((c[M+4>>2]&-8|0)==(aa|0)){La=M;break j}else{V=V<<1;h=M}}if(Ka>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[Ka>>2]=ga;c[ga+24>>2]=h;c[ga+12>>2]=ga;c[ga+8>>2]=ga;break g}}else{La=W}}while(0);W=La+8|0;aa=c[W>>2]|0;Z=c[27672>>2]|0;if(La>>>0>>0){_a()}if(aa>>>0>>0){_a()}else{c[aa+12>>2]=ga;c[W>>2]=ga;c[ga+8>>2]=aa;c[ga+12>>2]=La;c[ga+24>>2]=0;break}}}else{aa=c[27672>>2]|0;if((aa|0)==0|da>>>0>>0){c[27672>>2]=da}c[28104>>2]=da;c[28108>>2]=ea;c[28116>>2]=0;c[27692>>2]=c[7032];c[27688>>2]=-1;aa=0;do{W=aa<<1;Z=27696+(W<<2)|0;c[27696+(W+3<<2)>>2]=Z;c[27696+(W+2<<2)>>2]=Z;aa=aa+1|0}while((aa|0)!=32);aa=da+8|0;if((aa&7|0)==0){Ma=0}else{Ma=0-aa&7}aa=ea+ -40-Ma|0;c[27680>>2]=da+Ma;c[27668>>2]=aa;c[da+(Ma+4)>>2]=aa|1;c[da+(ea+ -36)>>2]=40;c[27684>>2]=c[28144>>2]}}while(0);ea=c[27668>>2]|0;if(ea>>>0>B>>>0){da=ea-B|0;c[27668>>2]=da;ea=c[27680>>2]|0;c[27680>>2]=ea+B;c[ea+(B+4)>>2]=da|1;c[ea+4>>2]=B|3;p=ea+8|0;i=b;return p|0}}c[(Sa()|0)>>2]=12;p=0;i=b;return p|0}function hg(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0;b=i;if((a|0)==0){i=b;return}d=a+ -8|0;e=c[27672>>2]|0;if(d>>>0>>0){_a()}f=c[a+ -4>>2]|0;g=f&3;if((g|0)==1){_a()}h=f&-8;j=a+(h+ -8)|0;do{if((f&1|0)==0){k=c[d>>2]|0;if((g|0)==0){i=b;return}l=-8-k|0;m=a+l|0;n=k+h|0;if(m>>>0>>0){_a()}if((m|0)==(c[27676>>2]|0)){o=a+(h+ -4)|0;if((c[o>>2]&3|0)!=3){p=m;q=n;break}c[27664>>2]=n;c[o>>2]=c[o>>2]&-2;c[a+(l+4)>>2]=n|1;c[j>>2]=n;i=b;return}o=k>>>3;if(k>>>0<256){k=c[a+(l+8)>>2]|0;r=c[a+(l+12)>>2]|0;s=27696+(o<<1<<2)|0;if((k|0)!=(s|0)){if(k>>>0>>0){_a()}if((c[k+12>>2]|0)!=(m|0)){_a()}}if((r|0)==(k|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}s=r+8|0;if((c[s>>2]|0)==(m|0)){t=s}else{_a()}}else{t=r+8|0}c[k+12>>2]=r;c[t>>2]=k;p=m;q=n;break}k=c[a+(l+24)>>2]|0;r=c[a+(l+12)>>2]|0;do{if((r|0)==(m|0)){s=a+(l+20)|0;o=c[s>>2]|0;if((o|0)==0){u=a+(l+16)|0;v=c[u>>2]|0;if((v|0)==0){w=0;break}else{x=v;y=u}}else{x=o;y=s}while(1){s=x+20|0;o=c[s>>2]|0;if((o|0)!=0){x=o;y=s;continue}s=x+16|0;o=c[s>>2]|0;if((o|0)==0){break}else{x=o;y=s}}if(y>>>0>>0){_a()}else{c[y>>2]=0;w=x;break}}else{s=c[a+(l+8)>>2]|0;if(s>>>0>>0){_a()}o=s+12|0;if((c[o>>2]|0)!=(m|0)){_a()}u=r+8|0;if((c[u>>2]|0)==(m|0)){c[o>>2]=r;c[u>>2]=s;w=r;break}else{_a()}}}while(0);if((k|0)!=0){r=c[a+(l+28)>>2]|0;s=27960+(r<<2)|0;if((m|0)==(c[s>>2]|0)){c[s>>2]=w;if((w|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}r=k+16|0;if((c[r>>2]|0)==(m|0)){c[r>>2]=w}else{c[k+20>>2]=w}if((w|0)==0){p=m;q=n;break}}if(w>>>0<(c[27672>>2]|0)>>>0){_a()}c[w+24>>2]=k;r=c[a+(l+16)>>2]|0;do{if((r|0)!=0){if(r>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+16>>2]=r;c[r+24>>2]=w;break}}}while(0);r=c[a+(l+20)>>2]|0;if((r|0)!=0){if(r>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+20>>2]=r;c[r+24>>2]=w;p=m;q=n;break}}else{p=m;q=n}}else{p=m;q=n}}else{p=d;q=h}}while(0);if(!(p>>>0>>0)){_a()}d=a+(h+ -4)|0;w=c[d>>2]|0;if((w&1|0)==0){_a()}if((w&2|0)==0){if((j|0)==(c[27680>>2]|0)){e=(c[27668>>2]|0)+q|0;c[27668>>2]=e;c[27680>>2]=p;c[p+4>>2]=e|1;if((p|0)!=(c[27676>>2]|0)){i=b;return}c[27676>>2]=0;c[27664>>2]=0;i=b;return}if((j|0)==(c[27676>>2]|0)){e=(c[27664>>2]|0)+q|0;c[27664>>2]=e;c[27676>>2]=p;c[p+4>>2]=e|1;c[p+e>>2]=e;i=b;return}e=(w&-8)+q|0;x=w>>>3;do{if(!(w>>>0<256)){y=c[a+(h+16)>>2]|0;t=c[a+(h|4)>>2]|0;do{if((t|0)==(j|0)){g=a+(h+12)|0;f=c[g>>2]|0;if((f|0)==0){r=a+(h+8)|0;k=c[r>>2]|0;if((k|0)==0){z=0;break}else{A=k;B=r}}else{A=f;B=g}while(1){g=A+20|0;f=c[g>>2]|0;if((f|0)!=0){A=f;B=g;continue}g=A+16|0;f=c[g>>2]|0;if((f|0)==0){break}else{A=f;B=g}}if(B>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[B>>2]=0;z=A;break}}else{g=c[a+h>>2]|0;if(g>>>0<(c[27672>>2]|0)>>>0){_a()}f=g+12|0;if((c[f>>2]|0)!=(j|0)){_a()}r=t+8|0;if((c[r>>2]|0)==(j|0)){c[f>>2]=t;c[r>>2]=g;z=t;break}else{_a()}}}while(0);if((y|0)!=0){t=c[a+(h+20)>>2]|0;n=27960+(t<<2)|0;if((j|0)==(c[n>>2]|0)){c[n>>2]=z;if((z|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}t=y+16|0;if((c[t>>2]|0)==(j|0)){c[t>>2]=z}else{c[y+20>>2]=z}if((z|0)==0){break}}if(z>>>0<(c[27672>>2]|0)>>>0){_a()}c[z+24>>2]=y;t=c[a+(h+8)>>2]|0;do{if((t|0)!=0){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[z+16>>2]=t;c[t+24>>2]=z;break}}}while(0);t=c[a+(h+12)>>2]|0;if((t|0)!=0){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[z+20>>2]=t;c[t+24>>2]=z;break}}}}else{t=c[a+h>>2]|0;y=c[a+(h|4)>>2]|0;n=27696+(x<<1<<2)|0;if((t|0)!=(n|0)){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}if((c[t+12>>2]|0)!=(j|0)){_a()}}if((y|0)==(t|0)){c[6914]=c[6914]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}n=y+8|0;if((c[n>>2]|0)==(j|0)){C=n}else{_a()}}else{C=y+8|0}c[t+12>>2]=y;c[C>>2]=t}}while(0);c[p+4>>2]=e|1;c[p+e>>2]=e;if((p|0)==(c[27676>>2]|0)){c[27664>>2]=e;i=b;return}else{D=e}}else{c[d>>2]=w&-2;c[p+4>>2]=q|1;c[p+q>>2]=q;D=q}q=D>>>3;if(D>>>0<256){w=q<<1;d=27696+(w<<2)|0;e=c[6914]|0;C=1<>2]|0;if(j>>>0<(c[27672>>2]|0)>>>0){_a()}else{E=q;F=j}}else{c[6914]=e|C;E=27696+(w+2<<2)|0;F=d}c[E>>2]=p;c[F+12>>2]=p;c[p+8>>2]=F;c[p+12>>2]=d;i=b;return}d=D>>>8;if((d|0)!=0){if(D>>>0>16777215){G=31}else{F=(d+1048320|0)>>>16&8;E=d<>>16&4;w=E<>>16&2;C=14-(d|F|E)+(w<>>15)|0;G=D>>>(C+7|0)&1|C<<1}}else{G=0}C=27960+(G<<2)|0;c[p+28>>2]=G;c[p+20>>2]=0;c[p+16>>2]=0;E=c[27660>>2]|0;w=1<>2]|0;if((G|0)==31){H=0}else{H=25-(G>>>1)|0}b:do{if((c[F+4>>2]&-8|0)!=(D|0)){d=D<>>31<<2)+16|0;j=c[I>>2]|0;if((j|0)==0){break}if((c[j+4>>2]&-8|0)==(D|0)){J=j;break b}else{d=d<<1;e=j}}if(I>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[I>>2]=p;c[p+24>>2]=e;c[p+12>>2]=p;c[p+8>>2]=p;break a}}else{J=F}}while(0);F=J+8|0;d=c[F>>2]|0;j=c[27672>>2]|0;if(J>>>0>>0){_a()}if(d>>>0>>0){_a()}else{c[d+12>>2]=p;c[F>>2]=p;c[p+8>>2]=d;c[p+12>>2]=J;c[p+24>>2]=0;break}}else{c[27660>>2]=E|w;c[C>>2]=p;c[p+24>>2]=C;c[p+12>>2]=p;c[p+8>>2]=p}}while(0);p=(c[27688>>2]|0)+ -1|0;c[27688>>2]=p;if((p|0)==0){K=28112|0}else{i=b;return}while(1){p=c[K>>2]|0;if((p|0)==0){break}else{K=p+8|0}}c[27688>>2]=-1;i=b;return}function ig(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;if((a|0)!=0){e=aa(b,a)|0;if((b|a)>>>0>65535){f=((e>>>0)/(a>>>0)|0|0)==(b|0)?e:-1}else{f=e}}else{f=0}e=gg(f)|0;if((e|0)==0){i=d;return e|0}if((c[e+ -4>>2]&3|0)==0){i=d;return e|0}Eg(e|0,0,f|0)|0;i=d;return e|0}function jg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;do{if((a|0)!=0){if(b>>>0>4294967231){c[(Sa()|0)>>2]=12;e=0;break}if(b>>>0<11){f=16}else{f=b+11&-8}g=kg(a+ -8|0,f)|0;if((g|0)!=0){e=g+8|0;break}g=gg(b)|0;if((g|0)==0){e=0}else{h=c[a+ -4>>2]|0;j=(h&-8)-((h&3|0)==0?8:4)|0;Kg(g|0,a|0,(j>>>0>>0?j:b)|0)|0;hg(a);e=g}}else{e=gg(b)|0}}while(0);i=d;return e|0}function kg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;d=i;e=a+4|0;f=c[e>>2]|0;g=f&-8;h=a+g|0;j=c[27672>>2]|0;if(a>>>0>>0){_a()}k=f&3;if(!((k|0)!=1&a>>>0>>0)){_a()}l=a+(g|4)|0;m=c[l>>2]|0;if((m&1|0)==0){_a()}if((k|0)==0){if(b>>>0<256){n=0;i=d;return n|0}if(!(g>>>0<(b+4|0)>>>0)?!((g-b|0)>>>0>c[28136>>2]<<1>>>0):0){n=a;i=d;return n|0}n=0;i=d;return n|0}if(!(g>>>0>>0)){k=g-b|0;if(!(k>>>0>15)){n=a;i=d;return n|0}c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=k|3;c[l>>2]=c[l>>2]|1;lg(a+b|0,k);n=a;i=d;return n|0}if((h|0)==(c[27680>>2]|0)){k=(c[27668>>2]|0)+g|0;if(!(k>>>0>b>>>0)){n=0;i=d;return n|0}l=k-b|0;c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=l|1;c[27680>>2]=a+b;c[27668>>2]=l;n=a;i=d;return n|0}if((h|0)==(c[27676>>2]|0)){l=(c[27664>>2]|0)+g|0;if(l>>>0>>0){n=0;i=d;return n|0}k=l-b|0;if(k>>>0>15){c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=k|1;c[a+l>>2]=k;o=a+(l+4)|0;c[o>>2]=c[o>>2]&-2;p=a+b|0;q=k}else{c[e>>2]=f&1|l|2;f=a+(l+4)|0;c[f>>2]=c[f>>2]|1;p=0;q=0}c[27664>>2]=q;c[27676>>2]=p;n=a;i=d;return n|0}if((m&2|0)!=0){n=0;i=d;return n|0}p=(m&-8)+g|0;if(p>>>0>>0){n=0;i=d;return n|0}q=p-b|0;f=m>>>3;do{if(!(m>>>0<256)){l=c[a+(g+24)>>2]|0;k=c[a+(g+12)>>2]|0;do{if((k|0)==(h|0)){o=a+(g+20)|0;r=c[o>>2]|0;if((r|0)==0){s=a+(g+16)|0;t=c[s>>2]|0;if((t|0)==0){u=0;break}else{v=t;w=s}}else{v=r;w=o}while(1){o=v+20|0;r=c[o>>2]|0;if((r|0)!=0){v=r;w=o;continue}o=v+16|0;r=c[o>>2]|0;if((r|0)==0){break}else{v=r;w=o}}if(w>>>0>>0){_a()}else{c[w>>2]=0;u=v;break}}else{o=c[a+(g+8)>>2]|0;if(o>>>0>>0){_a()}r=o+12|0;if((c[r>>2]|0)!=(h|0)){_a()}s=k+8|0;if((c[s>>2]|0)==(h|0)){c[r>>2]=k;c[s>>2]=o;u=k;break}else{_a()}}}while(0);if((l|0)!=0){k=c[a+(g+28)>>2]|0;o=27960+(k<<2)|0;if((h|0)==(c[o>>2]|0)){c[o>>2]=u;if((u|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}k=l+16|0;if((c[k>>2]|0)==(h|0)){c[k>>2]=u}else{c[l+20>>2]=u}if((u|0)==0){break}}if(u>>>0<(c[27672>>2]|0)>>>0){_a()}c[u+24>>2]=l;k=c[a+(g+16)>>2]|0;do{if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+16>>2]=k;c[k+24>>2]=u;break}}}while(0);k=c[a+(g+20)>>2]|0;if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+20>>2]=k;c[k+24>>2]=u;break}}}}else{k=c[a+(g+8)>>2]|0;l=c[a+(g+12)>>2]|0;o=27696+(f<<1<<2)|0;if((k|0)!=(o|0)){if(k>>>0>>0){_a()}if((c[k+12>>2]|0)!=(h|0)){_a()}}if((l|0)==(k|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}o=l+8|0;if((c[o>>2]|0)==(h|0)){x=o}else{_a()}}else{x=l+8|0}c[k+12>>2]=l;c[x>>2]=k}}while(0);if(q>>>0<16){c[e>>2]=p|c[e>>2]&1|2;x=a+(p|4)|0;c[x>>2]=c[x>>2]|1;n=a;i=d;return n|0}else{c[e>>2]=c[e>>2]&1|b|2;c[a+(b+4)>>2]=q|3;e=a+(p|4)|0;c[e>>2]=c[e>>2]|1;lg(a+b|0,q);n=a;i=d;return n|0}return 0}function lg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;d=i;e=a+b|0;f=c[a+4>>2]|0;do{if((f&1|0)==0){g=c[a>>2]|0;if((f&3|0)==0){i=d;return}h=a+(0-g)|0;j=g+b|0;k=c[27672>>2]|0;if(h>>>0>>0){_a()}if((h|0)==(c[27676>>2]|0)){l=a+(b+4)|0;if((c[l>>2]&3|0)!=3){m=h;n=j;break}c[27664>>2]=j;c[l>>2]=c[l>>2]&-2;c[a+(4-g)>>2]=j|1;c[e>>2]=j;i=d;return}l=g>>>3;if(g>>>0<256){o=c[a+(8-g)>>2]|0;p=c[a+(12-g)>>2]|0;q=27696+(l<<1<<2)|0;if((o|0)!=(q|0)){if(o>>>0>>0){_a()}if((c[o+12>>2]|0)!=(h|0)){_a()}}if((p|0)==(o|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}q=p+8|0;if((c[q>>2]|0)==(h|0)){r=q}else{_a()}}else{r=p+8|0}c[o+12>>2]=p;c[r>>2]=o;m=h;n=j;break}o=c[a+(24-g)>>2]|0;p=c[a+(12-g)>>2]|0;do{if((p|0)==(h|0)){q=16-g|0;l=a+(q+4)|0;s=c[l>>2]|0;if((s|0)==0){t=a+q|0;q=c[t>>2]|0;if((q|0)==0){u=0;break}else{v=q;w=t}}else{v=s;w=l}while(1){l=v+20|0;s=c[l>>2]|0;if((s|0)!=0){v=s;w=l;continue}l=v+16|0;s=c[l>>2]|0;if((s|0)==0){break}else{v=s;w=l}}if(w>>>0>>0){_a()}else{c[w>>2]=0;u=v;break}}else{l=c[a+(8-g)>>2]|0;if(l>>>0>>0){_a()}s=l+12|0;if((c[s>>2]|0)!=(h|0)){_a()}t=p+8|0;if((c[t>>2]|0)==(h|0)){c[s>>2]=p;c[t>>2]=l;u=p;break}else{_a()}}}while(0);if((o|0)!=0){p=c[a+(28-g)>>2]|0;k=27960+(p<<2)|0;if((h|0)==(c[k>>2]|0)){c[k>>2]=u;if((u|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}p=o+16|0;if((c[p>>2]|0)==(h|0)){c[p>>2]=u}else{c[o+20>>2]=u}if((u|0)==0){m=h;n=j;break}}if(u>>>0<(c[27672>>2]|0)>>>0){_a()}c[u+24>>2]=o;p=16-g|0;k=c[a+p>>2]|0;do{if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+16>>2]=k;c[k+24>>2]=u;break}}}while(0);k=c[a+(p+4)>>2]|0;if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+20>>2]=k;c[k+24>>2]=u;m=h;n=j;break}}else{m=h;n=j}}else{m=h;n=j}}else{m=a;n=b}}while(0);u=c[27672>>2]|0;if(e>>>0>>0){_a()}v=a+(b+4)|0;w=c[v>>2]|0;if((w&2|0)==0){if((e|0)==(c[27680>>2]|0)){r=(c[27668>>2]|0)+n|0;c[27668>>2]=r;c[27680>>2]=m;c[m+4>>2]=r|1;if((m|0)!=(c[27676>>2]|0)){i=d;return}c[27676>>2]=0;c[27664>>2]=0;i=d;return}if((e|0)==(c[27676>>2]|0)){r=(c[27664>>2]|0)+n|0;c[27664>>2]=r;c[27676>>2]=m;c[m+4>>2]=r|1;c[m+r>>2]=r;i=d;return}r=(w&-8)+n|0;f=w>>>3;do{if(!(w>>>0<256)){k=c[a+(b+24)>>2]|0;g=c[a+(b+12)>>2]|0;do{if((g|0)==(e|0)){o=a+(b+20)|0;l=c[o>>2]|0;if((l|0)==0){t=a+(b+16)|0;s=c[t>>2]|0;if((s|0)==0){x=0;break}else{y=s;z=t}}else{y=l;z=o}while(1){o=y+20|0;l=c[o>>2]|0;if((l|0)!=0){y=l;z=o;continue}o=y+16|0;l=c[o>>2]|0;if((l|0)==0){break}else{y=l;z=o}}if(z>>>0>>0){_a()}else{c[z>>2]=0;x=y;break}}else{o=c[a+(b+8)>>2]|0;if(o>>>0>>0){_a()}l=o+12|0;if((c[l>>2]|0)!=(e|0)){_a()}t=g+8|0;if((c[t>>2]|0)==(e|0)){c[l>>2]=g;c[t>>2]=o;x=g;break}else{_a()}}}while(0);if((k|0)!=0){g=c[a+(b+28)>>2]|0;j=27960+(g<<2)|0;if((e|0)==(c[j>>2]|0)){c[j>>2]=x;if((x|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}g=k+16|0;if((c[g>>2]|0)==(e|0)){c[g>>2]=x}else{c[k+20>>2]=x}if((x|0)==0){break}}if(x>>>0<(c[27672>>2]|0)>>>0){_a()}c[x+24>>2]=k;g=c[a+(b+16)>>2]|0;do{if((g|0)!=0){if(g>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[x+16>>2]=g;c[g+24>>2]=x;break}}}while(0);g=c[a+(b+20)>>2]|0;if((g|0)!=0){if(g>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[x+20>>2]=g;c[g+24>>2]=x;break}}}}else{g=c[a+(b+8)>>2]|0;k=c[a+(b+12)>>2]|0;j=27696+(f<<1<<2)|0;if((g|0)!=(j|0)){if(g>>>0>>0){_a()}if((c[g+12>>2]|0)!=(e|0)){_a()}}if((k|0)==(g|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}j=k+8|0;if((c[j>>2]|0)==(e|0)){A=j}else{_a()}}else{A=k+8|0}c[g+12>>2]=k;c[A>>2]=g}}while(0);c[m+4>>2]=r|1;c[m+r>>2]=r;if((m|0)==(c[27676>>2]|0)){c[27664>>2]=r;i=d;return}else{B=r}}else{c[v>>2]=w&-2;c[m+4>>2]=n|1;c[m+n>>2]=n;B=n}n=B>>>3;if(B>>>0<256){w=n<<1;v=27696+(w<<2)|0;r=c[6914]|0;A=1<>2]|0;if(e>>>0<(c[27672>>2]|0)>>>0){_a()}else{C=n;D=e}}else{c[6914]=r|A;C=27696+(w+2<<2)|0;D=v}c[C>>2]=m;c[D+12>>2]=m;c[m+8>>2]=D;c[m+12>>2]=v;i=d;return}v=B>>>8;if((v|0)!=0){if(B>>>0>16777215){E=31}else{D=(v+1048320|0)>>>16&8;C=v<>>16&4;w=C<>>16&2;A=14-(v|D|C)+(w<>>15)|0;E=B>>>(A+7|0)&1|A<<1}}else{E=0}A=27960+(E<<2)|0;c[m+28>>2]=E;c[m+20>>2]=0;c[m+16>>2]=0;C=c[27660>>2]|0;w=1<>2]=C|w;c[A>>2]=m;c[m+24>>2]=A;c[m+12>>2]=m;c[m+8>>2]=m;i=d;return}w=c[A>>2]|0;if((E|0)==31){F=0}else{F=25-(E>>>1)|0}a:do{if((c[w+4>>2]&-8|0)==(B|0)){G=w}else{E=B<>>31<<2)+16|0;C=c[H>>2]|0;if((C|0)==0){break}if((c[C+4>>2]&-8|0)==(B|0)){G=C;break a}else{E=E<<1;A=C}}if(H>>>0<(c[27672>>2]|0)>>>0){_a()}c[H>>2]=m;c[m+24>>2]=A;c[m+12>>2]=m;c[m+8>>2]=m;i=d;return}}while(0);H=G+8|0;B=c[H>>2]|0;w=c[27672>>2]|0;if(G>>>0>>0){_a()}if(B>>>0>>0){_a()}c[B+12>>2]=m;c[H>>2]=m;c[m+8>>2]=B;c[m+12>>2]=G;c[m+24>>2]=0;i=d;return}function mg(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0.0,Q=0,R=0.0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0.0,ca=0,da=0.0,ea=0,fa=0.0,ga=0,ha=0.0,ia=0,ja=0.0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,ra=0,sa=0.0,ta=0,ua=0.0,va=0,wa=0,xa=0,ya=0,za=0.0,Aa=0,Ba=0.0,Ca=0.0,Da=0,Ea=0.0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Ta=0,Ua=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0.0,sc=0,tc=0,uc=0.0,vc=0.0,wc=0.0,xc=0.0,yc=0.0,zc=0.0,Ac=0,Bc=0,Cc=0.0,Dc=0,Ec=0.0,Fc=0,Gc=0,Hc=0,Ic=0;g=i;i=i+512|0;h=g;if((e|0)==1){j=53;k=-1074}else if((e|0)==0){j=24;k=-149}else if((e|0)==2){j=53;k=-1074}else{l=0.0;i=g;return+l}e=b+4|0;m=b+100|0;do{n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;o=d[n]|0}else{o=pg(b)|0}}while((fb(o|0)|0)!=0);do{if((o|0)==43|(o|0)==45){n=1-(((o|0)==45)<<1)|0;p=c[e>>2]|0;if(p>>>0<(c[m>>2]|0)>>>0){c[e>>2]=p+1;q=d[p]|0;r=n;break}else{q=pg(b)|0;r=n;break}}else{q=o;r=1}}while(0);o=q;q=0;while(1){if((o|32|0)!=(a[28152+q|0]|0)){s=o;v=q;break}do{if(q>>>0<7){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;w=d[n]|0;break}else{w=pg(b)|0;break}}else{w=o}}while(0);n=q+1|0;if(n>>>0<8){o=w;q=n}else{s=w;v=n;break}}do{if((v|0)==3){x=23}else if((v|0)!=8){w=(f|0)==0;if(!(v>>>0<4|w)){if((v|0)==8){break}else{x=23;break}}a:do{if((v|0)==0){q=s;o=0;while(1){if((q|32|0)!=(a[28168+o|0]|0)){y=q;z=o;break a}do{if(o>>>0<2){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;A=d[n]|0;break}else{A=pg(b)|0;break}}else{A=q}}while(0);n=o+1|0;if(n>>>0<3){q=A;o=n}else{y=A;z=n;break}}}else{y=s;z=v}}while(0);if((z|0)==0){do{if((y|0)==48){o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;B=d[o]|0}else{B=pg(b)|0}if((B|32|0)!=120){if((c[m>>2]|0)==0){C=48;break}c[e>>2]=(c[e>>2]|0)+ -1;C=48;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;D=d[o]|0;F=0}else{D=pg(b)|0;F=0}while(1){if((D|0)==46){x=70;break}else if((D|0)!=48){G=0;H=0;I=0;J=0;K=D;L=F;M=0;N=0;O=1.0;Q=0;R=0.0;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;D=d[o]|0;F=1;continue}else{D=pg(b)|0;F=1;continue}}b:do{if((x|0)==70){o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;S=d[o]|0}else{S=pg(b)|0}if((S|0)==48){o=-1;q=-1;while(1){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;T=d[n]|0}else{T=pg(b)|0}if((T|0)!=48){G=0;H=0;I=o;J=q;K=T;L=1;M=1;N=0;O=1.0;Q=0;R=0.0;break b}n=Ig(o|0,q|0,-1,-1)|0;o=n;q=E}}else{G=0;H=0;I=0;J=0;K=S;L=F;M=1;N=0;O=1.0;Q=0;R=0.0}}}while(0);c:while(1){q=K+ -48|0;do{if(!(q>>>0<10)){o=K|32;n=(K|0)==46;if(!((o+ -97|0)>>>0<6|n)){U=K;break c}if(n){if((M|0)==0){V=H;W=G;X=H;Y=G;Z=L;_=1;$=N;ba=O;ca=Q;da=R;break}else{U=46;break c}}else{ea=(K|0)>57?o+ -87|0:q;x=84;break}}else{ea=q;x=84}}while(0);if((x|0)==84){x=0;do{if(!((G|0)<0|(G|0)==0&H>>>0<8)){if((G|0)<0|(G|0)==0&H>>>0<14){fa=O*.0625;ga=N;ha=fa;ia=Q;ja=R+fa*+(ea|0);break}if((ea|0)!=0&(N|0)==0){ga=1;ha=O;ia=Q;ja=R+O*.5}else{ga=N;ha=O;ia=Q;ja=R}}else{ga=N;ha=O;ia=ea+(Q<<4)|0;ja=R}}while(0);q=Ig(H|0,G|0,1,0)|0;V=I;W=J;X=q;Y=E;Z=1;_=M;$=ga;ba=ha;ca=ia;da=ja}q=c[e>>2]|0;if(q>>>0<(c[m>>2]|0)>>>0){c[e>>2]=q+1;G=Y;H=X;I=V;J=W;K=d[q]|0;L=Z;M=_;N=$;O=ba;Q=ca;R=da;continue}else{G=Y;H=X;I=V;J=W;K=pg(b)|0;L=Z;M=_;N=$;O=ba;Q=ca;R=da;continue}}if((L|0)==0){q=(c[m>>2]|0)==0;if(!q){c[e>>2]=(c[e>>2]|0)+ -1}if(!w){if(!q?(q=c[e>>2]|0,c[e>>2]=q+ -1,(M|0)!=0):0){c[e>>2]=q+ -2}}else{og(b,0)}l=+(r|0)*0.0;i=g;return+l}q=(M|0)==0;o=q?H:I;n=q?G:J;if((G|0)<0|(G|0)==0&H>>>0<8){q=H;p=G;ka=Q;while(1){la=ka<<4;ma=Ig(q|0,p|0,1,0)|0;na=E;if((na|0)<0|(na|0)==0&ma>>>0<8){q=ma;p=na;ka=la}else{oa=la;break}}}else{oa=Q}do{if((U|32|0)==112){ka=ng(b,f)|0;p=E;if((ka|0)==0&(p|0)==-2147483648){if(w){og(b,0);l=0.0;i=g;return+l}else{if((c[m>>2]|0)==0){pa=0;ra=0;break}c[e>>2]=(c[e>>2]|0)+ -1;pa=0;ra=0;break}}else{pa=ka;ra=p}}else{if((c[m>>2]|0)==0){pa=0;ra=0}else{c[e>>2]=(c[e>>2]|0)+ -1;pa=0;ra=0}}}while(0);p=Gg(o|0,n|0,2)|0;ka=Ig(p|0,E|0,-32,-1)|0;p=Ig(ka|0,E|0,pa|0,ra|0)|0;ka=E;if((oa|0)==0){l=+(r|0)*0.0;i=g;return+l}if((ka|0)>0|(ka|0)==0&p>>>0>(0-k|0)>>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+l}q=k+ -106|0;la=((q|0)<0)<<31>>31;if((ka|0)<(la|0)|(ka|0)==(la|0)&p>>>0>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+l}if((oa|0)>-1){q=p;la=ka;na=oa;fa=R;while(1){ma=na<<1;if(!(fa>=.5)){sa=fa;ta=ma}else{sa=fa+-1.0;ta=ma|1}ua=fa+sa;ma=Ig(q|0,la|0,-1,-1)|0;va=E;if((ta|0)>-1){q=ma;la=va;na=ta;fa=ua}else{wa=ma;xa=va;ya=ta;za=ua;break}}}else{wa=p;xa=ka;ya=oa;za=R}na=Cg(32,0,k|0,((k|0)<0)<<31>>31|0)|0;la=Ig(wa|0,xa|0,na|0,E|0)|0;na=E;if(0>(na|0)|0==(na|0)&j>>>0>la>>>0){Aa=(la|0)<0?0:la}else{Aa=j}if((Aa|0)<53){fa=+(r|0);ua=+Va(+(+qg(1.0,84-Aa|0)),+fa);if((Aa|0)<32&za!=0.0){la=ya&1;Ba=fa;Ca=ua;Da=(la^1)+ya|0;Ea=(la|0)==0?0.0:za}else{Ba=fa;Ca=ua;Da=ya;Ea=za}}else{Ba=+(r|0);Ca=0.0;Da=ya;Ea=za}ua=Ba*Ea+(Ca+Ba*+(Da>>>0))-Ca;if(!(ua!=0.0)){c[(Sa()|0)>>2]=34}l=+rg(ua,wa);i=g;return+l}else{C=y}}while(0);la=k+j|0;na=0-la|0;q=C;n=0;while(1){if((q|0)==46){x=139;break}else if((q|0)!=48){Fa=q;Ga=0;Ha=0;Ia=n;Ja=0;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;q=d[o]|0;n=1;continue}else{q=pg(b)|0;n=1;continue}}d:do{if((x|0)==139){q=c[e>>2]|0;if(q>>>0<(c[m>>2]|0)>>>0){c[e>>2]=q+1;Ka=d[q]|0}else{Ka=pg(b)|0}if((Ka|0)==48){q=-1;o=-1;while(1){va=c[e>>2]|0;if(va>>>0<(c[m>>2]|0)>>>0){c[e>>2]=va+1;La=d[va]|0}else{La=pg(b)|0}if((La|0)!=48){Fa=La;Ga=q;Ha=o;Ia=1;Ja=1;break d}va=Ig(q|0,o|0,-1,-1)|0;q=va;o=E}}else{Fa=Ka;Ga=0;Ha=0;Ia=n;Ja=1}}}while(0);c[h>>2]=0;n=Fa+ -48|0;o=(Fa|0)==46;e:do{if(n>>>0<10|o){q=h+496|0;ka=Fa;p=0;va=0;ma=o;Ma=n;Na=Ga;Oa=Ha;Pa=Ia;Qa=Ja;Ra=0;Ta=0;Ua=0;while(1){do{if(ma){if((Qa|0)==0){Wa=p;Xa=va;Ya=p;Za=va;_a=Pa;$a=1;ab=Ra;bb=Ta;cb=Ua}else{db=ka;eb=Na;gb=Oa;hb=p;ib=va;jb=Pa;kb=Ra;lb=Ta;mb=Ua;break e}}else{nb=Ig(p|0,va|0,1,0)|0;ob=E;pb=(ka|0)!=48;if((Ta|0)>=125){if(!pb){Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=Pa;$a=Qa;ab=Ra;bb=Ta;cb=Ua;break}c[q>>2]=c[q>>2]|1;Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=Pa;$a=Qa;ab=Ra;bb=Ta;cb=Ua;break}qb=h+(Ta<<2)|0;if((Ra|0)==0){rb=Ma}else{rb=ka+ -48+((c[qb>>2]|0)*10|0)|0}c[qb>>2]=rb;qb=Ra+1|0;sb=(qb|0)==9;Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=1;$a=Qa;ab=sb?0:qb;bb=(sb&1)+Ta|0;cb=pb?nb:Ua}}while(0);nb=c[e>>2]|0;if(nb>>>0<(c[m>>2]|0)>>>0){c[e>>2]=nb+1;tb=d[nb]|0}else{tb=pg(b)|0}nb=tb+ -48|0;pb=(tb|0)==46;if(nb>>>0<10|pb){ka=tb;p=Ya;va=Za;ma=pb;Ma=nb;Na=Wa;Oa=Xa;Pa=_a;Qa=$a;Ra=ab;Ta=bb;Ua=cb}else{ub=tb;vb=Ya;wb=Wa;xb=Za;yb=Xa;zb=_a;Ab=$a;Bb=ab;Cb=bb;Db=cb;x=162;break}}}else{ub=Fa;vb=0;wb=Ga;xb=0;yb=Ha;zb=Ia;Ab=Ja;Bb=0;Cb=0;Db=0;x=162}}while(0);if((x|0)==162){n=(Ab|0)==0;db=ub;eb=n?vb:wb;gb=n?xb:yb;hb=vb;ib=xb;jb=zb;kb=Bb;lb=Cb;mb=Db}n=(jb|0)!=0;if(n?(db|32|0)==101:0){o=ng(b,f)|0;Ua=E;do{if((o|0)==0&(Ua|0)==-2147483648){if(w){og(b,0);l=0.0;i=g;return+l}else{if((c[m>>2]|0)==0){Eb=0;Fb=0;break}c[e>>2]=(c[e>>2]|0)+ -1;Eb=0;Fb=0;break}}else{Eb=o;Fb=Ua}}while(0);Ua=Ig(Eb|0,Fb|0,eb|0,gb|0)|0;Gb=Ua;Hb=E}else{if((db|0)>-1?(c[m>>2]|0)!=0:0){c[e>>2]=(c[e>>2]|0)+ -1;Gb=eb;Hb=gb}else{Gb=eb;Hb=gb}}if(!n){c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}Ua=c[h>>2]|0;if((Ua|0)==0){l=+(r|0)*0.0;i=g;return+l}do{if((Gb|0)==(hb|0)&(Hb|0)==(ib|0)&((ib|0)<0|(ib|0)==0&hb>>>0<10)){if(!(j>>>0>30)?(Ua>>>j|0)!=0:0){break}l=+(r|0)*+(Ua>>>0);i=g;return+l}}while(0);Ua=(k|0)/-2|0;n=((Ua|0)<0)<<31>>31;if((Hb|0)>(n|0)|(Hb|0)==(n|0)&Gb>>>0>Ua>>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+l}Ua=k+ -106|0;n=((Ua|0)<0)<<31>>31;if((Hb|0)<(n|0)|(Hb|0)==(n|0)&Gb>>>0>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+l}if((kb|0)==0){Ib=lb}else{if((kb|0)<9){Ua=h+(lb<<2)|0;n=c[Ua>>2]|0;o=kb;do{n=n*10|0;o=o+1|0}while((o|0)!=9);c[Ua>>2]=n}Ib=lb+1|0}do{if((mb|0)<9?(mb|0)<=(Gb|0)&(Gb|0)<18:0){if((Gb|0)==9){l=+(r|0)*+((c[h>>2]|0)>>>0);i=g;return+l}if((Gb|0)<9){l=+(r|0)*+((c[h>>2]|0)>>>0)/+(c[28184+(8-Gb<<2)>>2]|0);i=g;return+l}o=j+27+(aa(Gb,-3)|0)|0;Ta=c[h>>2]|0;if((o|0)<=30?(Ta>>>o|0)!=0:0){break}l=+(r|0)*+(Ta>>>0)*+(c[28184+(Gb+ -10<<2)>>2]|0);i=g;return+l}}while(0);n=(Gb|0)%9|0;if((n|0)==0){Jb=0;Kb=0;Lb=Gb;Mb=Ib}else{Ua=(Gb|0)>-1?n:n+9|0;n=c[28184+(8-Ua<<2)>>2]|0;if((Ib|0)!=0){Ta=1e9/(n|0)|0;o=0;Ra=0;Qa=0;Pa=Gb;while(1){Oa=h+(Qa<<2)|0;Na=c[Oa>>2]|0;Ma=((Na>>>0)/(n>>>0)|0)+Ra|0;c[Oa>>2]=Ma;Nb=aa((Na>>>0)%(n>>>0)|0,Ta)|0;Na=Qa+1|0;if((Qa|0)==(o|0)&(Ma|0)==0){Ob=Na&127;Pb=Pa+ -9|0}else{Ob=o;Pb=Pa}if((Na|0)==(Ib|0)){break}else{o=Ob;Ra=Nb;Qa=Na;Pa=Pb}}if((Nb|0)==0){Qb=Ob;Rb=Pb;Sb=Ib}else{c[h+(Ib<<2)>>2]=Nb;Qb=Ob;Rb=Pb;Sb=Ib+1|0}}else{Qb=0;Rb=Gb;Sb=0}Jb=Qb;Kb=0;Lb=9-Ua+Rb|0;Mb=Sb}f:while(1){Pa=h+(Jb<<2)|0;if((Lb|0)<18){Qa=Kb;Ra=Mb;while(1){o=0;Ta=Ra+127|0;n=Ra;while(1){Na=Ta&127;Ma=h+(Na<<2)|0;Oa=Gg(c[Ma>>2]|0,0,29)|0;ma=Ig(Oa|0,E|0,o|0,0)|0;Oa=E;if(Oa>>>0>0|(Oa|0)==0&ma>>>0>1e9){va=Ug(ma|0,Oa|0,1e9,0)|0;p=Vg(ma|0,Oa|0,1e9,0)|0;Tb=p;Ub=va}else{Tb=ma;Ub=0}c[Ma>>2]=Tb;Ma=(Na|0)==(Jb|0);if((Na|0)!=(n+127&127|0)|Ma){Vb=n}else{Vb=(Tb|0)==0?Na:n}if(Ma){break}else{o=Ub;Ta=Na+ -1|0;n=Vb}}n=Qa+ -29|0;if((Ub|0)==0){Qa=n;Ra=Vb}else{Wb=n;Xb=Ub;Yb=Vb;break}}}else{if((Lb|0)==18){Zb=Kb;_b=Mb}else{$b=Jb;ac=Kb;bc=Lb;cc=Mb;break}while(1){if(!((c[Pa>>2]|0)>>>0<9007199)){$b=Jb;ac=Zb;bc=18;cc=_b;break f}Ra=0;Qa=_b+127|0;n=_b;while(1){Ta=Qa&127;o=h+(Ta<<2)|0;Na=Gg(c[o>>2]|0,0,29)|0;Ma=Ig(Na|0,E|0,Ra|0,0)|0;Na=E;if(Na>>>0>0|(Na|0)==0&Ma>>>0>1e9){ma=Ug(Ma|0,Na|0,1e9,0)|0;va=Vg(Ma|0,Na|0,1e9,0)|0;dc=va;ec=ma}else{dc=Ma;ec=0}c[o>>2]=dc;o=(Ta|0)==(Jb|0);if((Ta|0)!=(n+127&127|0)|o){fc=n}else{fc=(dc|0)==0?Ta:n}if(o){break}else{Ra=ec;Qa=Ta+ -1|0;n=fc}}n=Zb+ -29|0;if((ec|0)==0){Zb=n;_b=fc}else{Wb=n;Xb=ec;Yb=fc;break}}}Pa=Jb+127&127;if((Pa|0)==(Yb|0)){n=Yb+127&127;Qa=h+((Yb+126&127)<<2)|0;c[Qa>>2]=c[Qa>>2]|c[h+(n<<2)>>2];gc=n}else{gc=Yb}c[h+(Pa<<2)>>2]=Xb;Jb=Pa;Kb=Wb;Lb=Lb+9|0;Mb=gc}g:while(1){hc=cc+1&127;Ua=h+((cc+127&127)<<2)|0;Pa=$b;n=ac;Qa=bc;while(1){Ra=(Qa|0)==18;Ta=(Qa|0)>27?9:1;ic=Pa;jc=n;while(1){o=0;while(1){Ma=o+ic&127;if((Ma|0)==(cc|0)){kc=2;break}ma=c[h+(Ma<<2)>>2]|0;Ma=c[28176+(o<<2)>>2]|0;if(ma>>>0>>0){kc=2;break}va=o+1|0;if(ma>>>0>Ma>>>0){kc=o;break}if((va|0)<2){o=va}else{kc=va;break}}if((kc|0)==2&Ra){break g}lc=Ta+jc|0;if((ic|0)==(cc|0)){ic=cc;jc=lc}else{break}}Ra=(1<>>Ta;mc=ic;nc=0;va=ic;oc=Qa;do{Ma=h+(va<<2)|0;ma=c[Ma>>2]|0;Na=(ma>>>Ta)+nc|0;c[Ma>>2]=Na;nc=aa(ma&Ra,o)|0;ma=(va|0)==(mc|0)&(Na|0)==0;va=va+1&127;oc=ma?oc+ -9|0:oc;mc=ma?va:mc}while((va|0)!=(cc|0));if((nc|0)==0){Pa=mc;n=lc;Qa=oc;continue}if((hc|0)!=(mc|0)){break}c[Ua>>2]=c[Ua>>2]|1;Pa=mc;n=lc;Qa=oc}c[h+(cc<<2)>>2]=nc;$b=mc;ac=lc;bc=oc;cc=hc}Qa=ic&127;if((Qa|0)==(cc|0)){c[h+(hc+ -1<<2)>>2]=0;pc=hc}else{pc=cc}ua=+((c[h+(Qa<<2)>>2]|0)>>>0);Qa=ic+1&127;if((Qa|0)==(pc|0)){n=pc+1&127;c[h+(n+ -1<<2)>>2]=0;qc=n}else{qc=pc}fa=+(r|0);rc=fa*(ua*1.0e9+ +((c[h+(Qa<<2)>>2]|0)>>>0));Qa=jc+53|0;n=Qa-k|0;if((n|0)<(j|0)){sc=(n|0)<0?0:n;tc=1}else{sc=j;tc=0}if((sc|0)<53){ua=+Va(+(+qg(1.0,105-sc|0)),+rc);uc=+qa(+rc,+(+qg(1.0,53-sc|0)));vc=ua;wc=uc;xc=ua+(rc-uc)}else{vc=0.0;wc=0.0;xc=rc}Pa=ic+2&127;if((Pa|0)!=(qc|0)){Ua=c[h+(Pa<<2)>>2]|0;do{if(!(Ua>>>0<5e8)){if(Ua>>>0>5e8){yc=fa*.75+wc;break}if((ic+3&127|0)==(qc|0)){yc=fa*.5+wc;break}else{yc=fa*.75+wc;break}}else{if((Ua|0)==0?(ic+3&127|0)==(qc|0):0){yc=wc;break}yc=fa*.25+wc}}while(0);if((53-sc|0)>1?!(+qa(+yc,1.0)!=0.0):0){zc=yc+1.0}else{zc=yc}}else{zc=wc}fa=xc+zc-vc;do{if((Qa&2147483647|0)>(-2-la|0)){if(!(+P(+fa)>=9007199254740992.0)){Ac=tc;Bc=jc;Cc=fa}else{Ac=(tc|0)!=0&(sc|0)==(n|0)?0:tc;Bc=jc+1|0;Cc=fa*.5}if((Bc+50|0)<=(na|0)?!((Ac|0)!=0&zc!=0.0):0){Dc=Bc;Ec=Cc;break}c[(Sa()|0)>>2]=34;Dc=Bc;Ec=Cc}else{Dc=jc;Ec=fa}}while(0);l=+rg(Ec,Dc);i=g;return+l}else if((z|0)==3){na=c[e>>2]|0;if(na>>>0<(c[m>>2]|0)>>>0){c[e>>2]=na+1;Fc=d[na]|0}else{Fc=pg(b)|0}if((Fc|0)==40){Gc=1}else{if((c[m>>2]|0)==0){l=t;i=g;return+l}c[e>>2]=(c[e>>2]|0)+ -1;l=t;i=g;return+l}while(1){na=c[e>>2]|0;if(na>>>0<(c[m>>2]|0)>>>0){c[e>>2]=na+1;Hc=d[na]|0}else{Hc=pg(b)|0}if(!((Hc+ -48|0)>>>0<10|(Hc+ -65|0)>>>0<26)?!((Hc+ -97|0)>>>0<26|(Hc|0)==95):0){break}Gc=Gc+1|0}if((Hc|0)==41){l=t;i=g;return+l}na=(c[m>>2]|0)==0;if(!na){c[e>>2]=(c[e>>2]|0)+ -1}if(w){c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}if((Gc|0)==0|na){l=t;i=g;return+l}else{Ic=Gc}while(1){na=Ic+ -1|0;c[e>>2]=(c[e>>2]|0)+ -1;if((na|0)==0){l=t;break}else{Ic=na}}i=g;return+l}else{if((c[m>>2]|0)!=0){c[e>>2]=(c[e>>2]|0)+ -1}c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}}}while(0);if((x|0)==23){x=(c[m>>2]|0)==0;if(!x){c[e>>2]=(c[e>>2]|0)+ -1}if(!(v>>>0<4|(f|0)==0|x)){x=v;do{c[e>>2]=(c[e>>2]|0)+ -1;x=x+ -1|0}while(x>>>0>3)}}l=+(r|0)*u;i=g;return+l}function ng(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;e=i;f=a+4|0;g=c[f>>2]|0;h=a+100|0;if(g>>>0<(c[h>>2]|0)>>>0){c[f>>2]=g+1;j=d[g]|0}else{j=pg(a)|0}if((j|0)==43|(j|0)==45){g=(j|0)==45|0;k=c[f>>2]|0;if(k>>>0<(c[h>>2]|0)>>>0){c[f>>2]=k+1;l=d[k]|0}else{l=pg(a)|0}if(!((l+ -48|0)>>>0<10|(b|0)==0)?(c[h>>2]|0)!=0:0){c[f>>2]=(c[f>>2]|0)+ -1;m=l;n=g}else{m=l;n=g}}else{m=j;n=0}if((m+ -48|0)>>>0>9){if((c[h>>2]|0)==0){o=-2147483648;p=0;E=o;i=e;return p|0}c[f>>2]=(c[f>>2]|0)+ -1;o=-2147483648;p=0;E=o;i=e;return p|0}else{q=m;r=0}while(1){s=q+ -48+r|0;m=c[f>>2]|0;if(m>>>0<(c[h>>2]|0)>>>0){c[f>>2]=m+1;t=d[m]|0}else{t=pg(a)|0}if(!((t+ -48|0)>>>0<10&(s|0)<214748364)){break}q=t;r=s*10|0}r=((s|0)<0)<<31>>31;if((t+ -48|0)>>>0<10){q=s;m=r;j=t;while(1){g=Tg(q|0,m|0,10,0)|0;l=E;b=Ig(j|0,((j|0)<0)<<31>>31|0,-48,-1)|0;k=Ig(b|0,E|0,g|0,l|0)|0;l=E;g=c[f>>2]|0;if(g>>>0<(c[h>>2]|0)>>>0){c[f>>2]=g+1;u=d[g]|0}else{u=pg(a)|0}if((u+ -48|0)>>>0<10&((l|0)<21474836|(l|0)==21474836&k>>>0<2061584302)){q=k;m=l;j=u}else{v=k;w=l;x=u;break}}}else{v=s;w=r;x=t}if((x+ -48|0)>>>0<10){do{x=c[f>>2]|0;if(x>>>0<(c[h>>2]|0)>>>0){c[f>>2]=x+1;y=d[x]|0}else{y=pg(a)|0}}while((y+ -48|0)>>>0<10)}if((c[h>>2]|0)!=0){c[f>>2]=(c[f>>2]|0)+ -1}f=(n|0)!=0;n=Cg(0,0,v|0,w|0)|0;o=f?E:w;p=f?n:v;E=o;i=e;return p|0}function og(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;c[a+104>>2]=b;e=c[a+8>>2]|0;f=c[a+4>>2]|0;g=e-f|0;c[a+108>>2]=g;if((b|0)!=0&(g|0)>(b|0)){c[a+100>>2]=f+b;i=d;return}else{c[a+100>>2]=e;i=d;return}}function pg(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;f=b+104|0;g=c[f>>2]|0;if(!((g|0)!=0?(c[b+108>>2]|0)>=(g|0):0)){h=3}if((h|0)==3?(h=tg(b)|0,(h|0)>=0):0){g=c[f>>2]|0;f=c[b+8>>2]|0;if((g|0)!=0?(j=c[b+4>>2]|0,k=g-(c[b+108>>2]|0)+ -1|0,(f-j|0)>(k|0)):0){c[b+100>>2]=j+k}else{c[b+100>>2]=f}k=c[b+4>>2]|0;if((f|0)!=0){j=b+108|0;c[j>>2]=f+1-k+(c[j>>2]|0)}j=k+ -1|0;if((d[j]|0|0)==(h|0)){l=h;i=e;return l|0}a[j]=h;l=h;i=e;return l|0}c[b+100>>2]=0;l=-1;i=e;return l|0}function qg(a,b){a=+a;b=b|0;var d=0,e=0.0,f=0,g=0,j=0,l=0.0;d=i;if((b|0)>1023){e=a*8.98846567431158e+307;f=b+ -1023|0;if((f|0)>1023){g=b+ -2046|0;j=(g|0)>1023?1023:g;l=e*8.98846567431158e+307}else{j=f;l=e}}else{if((b|0)<-1022){e=a*2.2250738585072014e-308;f=b+1022|0;if((f|0)<-1022){g=b+2044|0;j=(g|0)<-1022?-1022:g;l=e*2.2250738585072014e-308}else{j=f;l=e}}else{j=b;l=a}}b=Gg(j+1023|0,0,52)|0;j=E;c[k>>2]=b;c[k+4>>2]=j;a=l*+h[k>>3];i=d;return+a}function rg(a,b){a=+a;b=b|0;var c=0,d=0.0;c=i;d=+qg(a,b);i=c;return+d}function sg(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;e=b+74|0;f=a[e]|0;a[e]=f+255|f;f=b+20|0;e=b+44|0;if((c[f>>2]|0)>>>0>(c[e>>2]|0)>>>0){kb[c[b+36>>2]&1](b,0,0)|0}c[b+16>>2]=0;c[b+28>>2]=0;c[f>>2]=0;f=c[b>>2]|0;if((f&20|0)==0){g=c[e>>2]|0;c[b+8>>2]=g;c[b+4>>2]=g;h=0;i=d;return h|0}if((f&4|0)==0){h=-1;i=d;return h|0}c[b>>2]=f|32;h=-1;i=d;return h|0}function tg(a){a=a|0;var b=0,e=0,f=0;b=i;i=i+16|0;e=b;if((c[a+8>>2]|0)==0?(sg(a)|0)!=0:0){f=-1}else{if((kb[c[a+32>>2]&1](a,e,1)|0)==1){f=d[e]|0}else{f=-1}}i=b;return f|0}function ug(a){a=a|0;var b=0,c=0.0;b=i;c=+wg(a,0);i=b;return+c}function vg(b){b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;c=i;d=b;while(1){e=d+1|0;if((fb(a[d]|0)|0)==0){break}else{d=e}}b=a[d]|0;f=b<<24>>24;if((f|0)==45){g=1;h=5}else if((f|0)==43){g=0;h=5}else{j=d;k=b;l=0}if((h|0)==5){j=e;k=a[e]|0;l=g}if((cb(k<<24>>24|0)|0)==0){m=0;n=(l|0)!=0;o=0-m|0;p=n?m:o;i=c;return p|0}else{q=j;r=0}while(1){j=q+1|0;k=(r*10|0)+48-(a[q]|0)|0;if((cb(a[j]|0)|0)==0){m=k;break}else{q=j;r=k}}n=(l|0)!=0;o=0-m|0;p=n?m:o;i=c;return p|0}function wg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0.0,j=0,k=0;d=i;i=i+112|0;e=d;f=e+0|0;g=f+112|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(g|0));f=e+4|0;c[f>>2]=a;g=e+8|0;c[g>>2]=-1;c[e+44>>2]=a;c[e+76>>2]=-1;og(e,0);h=+mg(e,1,1);j=(c[f>>2]|0)-(c[g>>2]|0)+(c[e+108>>2]|0)|0;if((b|0)==0){i=d;return+h}if((j|0)==0){k=a}else{k=a+j|0}c[b>>2]=k;i=d;return+h}function xg(b,c){b=b|0;c=c|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;f=a[b]|0;a:do{if(f<<24>>24==0){g=0;h=c}else{j=f;k=f&255;l=b;m=c;while(1){n=a[m]|0;if(n<<24>>24==0){g=j;h=m;break a}if(!(j<<24>>24==n<<24>>24)?(n=Jg(k|0)|0,(n|0)!=(Jg(d[m]|0|0)|0)):0){break}n=l+1|0;o=m+1|0;p=a[n]|0;if(p<<24>>24==0){g=0;h=o;break a}else{j=p;k=p&255;l=n;m=o}}g=a[l]|0;h=m}}while(0);c=Jg(g&255|0)|0;g=c-(Jg(d[h]|0|0)|0)|0;i=e;return g|0}function yg(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;e=a[b]|0;f=a[c]|0;if(e<<24>>24!=f<<24>>24|e<<24>>24==0|f<<24>>24==0){g=e;h=f;j=g&255;k=h&255;l=j-k|0;i=d;return l|0}else{m=b;n=c}while(1){c=m+1|0;b=n+1|0;f=a[c]|0;e=a[b]|0;if(f<<24>>24!=e<<24>>24|f<<24>>24==0|e<<24>>24==0){g=f;h=e;break}else{m=c;n=b}}j=g&255;k=h&255;l=j-k|0;i=d;return l|0}function zg(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;if((e|0)==0){g=0;i=f;return g|0}h=a[b]|0;a:do{if(h<<24>>24==0){j=0;k=c}else{l=e;m=h;n=h&255;o=b;p=c;while(1){q=l+ -1|0;r=a[p]|0;if(r<<24>>24==0|(q|0)==0){j=m;k=p;break a}if(!(m<<24>>24==r<<24>>24)?(r=Jg(n|0)|0,(r|0)!=(Jg(d[p]|0|0)|0)):0){break}r=o+1|0;s=p+1|0;t=a[r]|0;if(t<<24>>24==0){j=0;k=s;break a}else{l=q;m=t;n=t&255;o=r;p=s}}j=a[o]|0;k=p}}while(0);c=Jg(j&255|0)|0;g=c-(Jg(d[k]|0|0)|0)|0;i=f;return g|0}function Ag(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;f=i;if((e|0)==0){g=0;i=f;return g|0}h=a[b]|0;a:do{if(h<<24>>24==0){j=0;k=c}else{l=e;m=h;n=b;o=c;while(1){p=l+ -1|0;q=a[o]|0;if(!((p|0)!=0&q<<24>>24!=0&m<<24>>24==q<<24>>24)){j=m;k=o;break a}q=n+1|0;r=o+1|0;s=a[q]|0;if(s<<24>>24==0){j=0;k=r;break}else{l=p;m=s;n=q;o=r}}}}while(0);g=(j&255)-(d[k]|0)|0;i=f;return g|0}function Bg(){}function Cg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=b-d>>>0;e=b-d-(c>>>0>a>>>0|0)>>>0;return(E=e,a-c>>>0|0)|0}function Dg(b){b=b|0;var c=0;c=b;while(a[c]|0){c=c+1|0}return c-b|0}function Eg(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0)>=20){d=d&255;g=b&3;h=d|d<<8|d<<16|d<<24;i=f&~3;if(g){g=b+4-g|0;while((b|0)<(g|0)){a[b]=d;b=b+1|0}}while((b|0)<(i|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b]=d;b=b+1|0}return b-e|0}function Fg(b,c){b=b|0;c=c|0;var d=0,e=0;d=b+(Dg(b)|0)|0;do{a[d+e|0]=a[c+e|0];e=e+1|0}while(a[c+(e-1)|0]|0);return b|0}function Gg(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b<>>32-c;return a<>>0;return(E=b+d+(e>>>0>>0|0)>>>0,e|0)|0}function Jg(a){a=a|0;if((a|0)<65)return a|0;if((a|0)>90)return a|0;return a-65+97|0}function Kg(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return Ga(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if((e|0)==0)return f|0;a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function Lg(b,c){b=b|0;c=c|0;var d=0;do{a[b+d|0]=a[c+d|0];d=d+1|0}while(a[c+(d-1)|0]|0);return b|0}function Mg(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b>>>c;return a>>>c|(b&(1<>>c-32|0}function Ng(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b>>c;return a>>>c|(b&(1<>c-32|0}function Og(b){b=b|0;var c=0;c=a[n+(b>>>24)|0]|0;if((c|0)<8)return c|0;c=a[n+(b>>16&255)|0]|0;if((c|0)<8)return c+8|0;c=a[n+(b>>8&255)|0]|0;if((c|0)<8)return c+16|0;return(a[n+(b&255)|0]|0)+24|0}function Pg(b){b=b|0;var c=0;c=a[m+(b&255)|0]|0;if((c|0)<8)return c|0;c=a[m+(b>>8&255)|0]|0;if((c|0)<8)return c+8|0;c=a[m+(b>>16&255)|0]|0;if((c|0)<8)return c+16|0;return(a[m+(b>>>24)|0]|0)+24|0}function Qg(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=a&65535;d=b&65535;e=aa(d,c)|0;f=a>>>16;a=(e>>>16)+(aa(d,f)|0)|0;d=b>>>16;b=aa(d,c)|0;return(E=(a>>>16)+(aa(d,f)|0)+(((a&65535)+b|0)>>>16)|0,a+b<<16|e&65535|0)|0}function Rg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;e=b>>31|((b|0)<0?-1:0)<<1;f=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;g=d>>31|((d|0)<0?-1:0)<<1;h=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;i=Cg(e^a,f^b,e,f)|0;b=E;a=g^e;e=h^f;f=Cg((Wg(i,b,Cg(g^c,h^d,g,h)|0,E,0)|0)^a,E^e,a,e)|0;return f|0}function Sg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+8|0;g=f|0;h=b>>31|((b|0)<0?-1:0)<<1;j=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;k=e>>31|((e|0)<0?-1:0)<<1;l=((e|0)<0?-1:0)>>31|((e|0)<0?-1:0)<<1;m=Cg(h^a,j^b,h,j)|0;b=E;Wg(m,b,Cg(k^d,l^e,k,l)|0,E,g)|0;l=Cg(c[g>>2]^h,c[g+4>>2]^j,h,j)|0;j=E;i=f;return(E=j,l)|0}function Tg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;a=c;c=Qg(e,a)|0;f=E;return(E=(aa(b,a)|0)+(aa(d,e)|0)+f|f&0,c|0|0)|0}function Ug(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=Wg(a,b,c,d,0)|0;return e|0}function Vg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=i;i=i+8|0;g=f|0;Wg(a,b,d,e,g)|0;i=f;return(E=c[g+4>>2]|0,c[g>>2]|0)|0}function Wg(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;g=a;h=b;i=h;j=d;k=e;l=k;if((i|0)==0){m=(f|0)!=0;if((l|0)==0){if(m){c[f>>2]=(g>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(g>>>0)/(j>>>0)>>>0;return(E=n,o)|0}else{if(!m){n=0;o=0;return(E=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;n=0;o=0;return(E=n,o)|0}}m=(l|0)==0;do{if((j|0)!=0){if(!m){p=(Og(l|0)|0)-(Og(i|0)|0)|0;if(p>>>0<=31){q=p+1|0;r=31-p|0;s=p-31>>31;t=q;u=g>>>(q>>>0)&s|i<>>(q>>>0)&s;w=0;x=g<>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return(E=n,o)|0}r=j-1|0;if((r&j|0)!=0){s=(Og(j|0)|0)+33-(Og(i|0)|0)|0;q=64-s|0;p=32-s|0;y=p>>31;z=s-32|0;A=z>>31;t=s;u=p-1>>31&i>>>(z>>>0)|(i<>>(s>>>0))&A;v=A&i>>>(s>>>0);w=g<>>(z>>>0))&y|g<>31;break}if((f|0)!=0){c[f>>2]=r&g;c[f+4>>2]=0}if((j|0)==1){n=h|b&0;o=a|0|0;return(E=n,o)|0}else{r=Pg(j|0)|0;n=i>>>(r>>>0)|0;o=i<<32-r|g>>>(r>>>0)|0;return(E=n,o)|0}}else{if(m){if((f|0)!=0){c[f>>2]=(i>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(i>>>0)/(j>>>0)>>>0;return(E=n,o)|0}if((g|0)==0){if((f|0)!=0){c[f>>2]=0;c[f+4>>2]=(i>>>0)%(l>>>0)}n=0;o=(i>>>0)/(l>>>0)>>>0;return(E=n,o)|0}r=l-1|0;if((r&l|0)==0){if((f|0)!=0){c[f>>2]=a|0;c[f+4>>2]=r&i|b&0}n=0;o=i>>>((Pg(l|0)|0)>>>0);return(E=n,o)|0}r=(Og(l|0)|0)-(Og(i|0)|0)|0;if(r>>>0<=30){s=r+1|0;p=31-r|0;t=s;u=i<>>(s>>>0);v=i>>>(s>>>0);w=0;x=g<>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return(E=n,o)|0}}while(0);if((t|0)==0){B=x;C=w;D=v;F=u;G=0;H=0}else{b=d|0|0;d=k|e&0;e=Ig(b,d,-1,-1)|0;k=E;h=x;x=w;w=v;v=u;u=t;t=0;while(1){I=x>>>31|h<<1;J=t|x<<1;a=v<<1|h>>>31|0;g=v>>>31|w<<1|0;Cg(e,k,a,g)|0;i=E;l=i>>31|((i|0)<0?-1:0)<<1;K=l&1;L=Cg(a,g,l&b,(((i|0)<0?-1:0)>>31|((i|0)<0?-1:0)<<1)&d)|0;M=E;i=u-1|0;if((i|0)==0){break}else{h=I;x=J;w=M;v=L;u=i;t=K}}B=I;C=J;D=M;F=L;G=0;H=K}K=C;C=0;if((f|0)!=0){c[f>>2]=F;c[f+4>>2]=D}n=(K|0)>>>31|(B|C)<<1|(C<<1|K>>>31)&0|G;o=(K<<1|0>>>31)&-2|H;return(E=n,o)|0}function Xg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return kb[a&1](b|0,c|0,d|0)|0}function Yg(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=d|0;e=e|0;f=f|0;return lb[a&63](+b,+c,d|0,e|0,f|0)|0}function Zg(a,b,c){a=a|0;b=b|0;c=c|0;mb[a&1](b|0,c|0)}function _g(a,b,c){a=a|0;b=b|0;c=c|0;return nb[a&7](b|0,c|0)|0}function $g(a,b,c){a=a|0;b=b|0;c=c|0;ba(0);return 0}function ah(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;ba(1);return 0}function bh(a,b){a=a|0;b=b|0;ba(2)}function ch(a,b){a=a|0;b=b|0;ba(3);return 0} + + + + +// EMSCRIPTEN_END_FUNCS +var kb=[$g,Xf];var lb=[ah,Ud,Vd,Xd,Yd,Zd,_d,$d,ae,de,ee,fe,ge,he,ie,je,ke,le,me,ne,oe,pe,qe,re,se,te,ue,ve,we,He,Ie,Je,Ke,Le,Me,Ne,Oe,Qd,Rd,Sd,Td,be,ce,xe,ye,ze,Ae,Be,Ce,De,Ee,Fe,Ge,ah,ah,ah,ah,ah,ah,ah,ah,ah,ah,ah];var mb=[bh,Yf];var nb=[ch,nf,of,pf,ef,ch,ch,ch];return{_strlen:Dg,_strcat:Fg,_gzread:xf,_wcsunits:Ib,_zscale:Lb,_initwcs:Eb,_wcssys:Hb,_pix2wcsstr:Fb,_calloc:ig,_bitshift64Shl:Gg,_gzwrite:Cf,_saostrtod:Kb,_strncpy:Hg,_memset:Eg,_memcpy:Kg,_gzclose:rf,_i64Subtract:Cg,_realloc:jg,_i64Add:Ig,_wcs2pixstr:Gb,_gzopen:sf,_gzseek:wf,_free:hg,_tolower:Jg,_malloc:gg,_reg2wcsstr:Jb,_strcpy:Lg,runPostSets:Bg,stackAlloc:ob,stackSave:pb,stackRestore:qb,setThrew:rb,setTempRet0:ub,setTempRet1:vb,setTempRet2:wb,setTempRet3:xb,setTempRet4:yb,setTempRet5:zb,setTempRet6:Ab,setTempRet7:Bb,setTempRet8:Cb,setTempRet9:Db,dynCall_iiii:Xg,dynCall_iddiii:Yg,dynCall_vii:Zg,dynCall_iii:_g}}) + + +// EMSCRIPTEN_END_ASM +({ "Math": Math, "Int8Array": Int8Array, "Int16Array": Int16Array, "Int32Array": Int32Array, "Uint8Array": Uint8Array, "Uint16Array": Uint16Array, "Uint32Array": Uint32Array, "Float32Array": Float32Array, "Float64Array": Float64Array }, { "abort": abort, "assert": assert, "asmPrintInt": asmPrintInt, "asmPrintFloat": asmPrintFloat, "min": Math_min, "invoke_iiii": invoke_iiii, "invoke_iddiii": invoke_iddiii, "invoke_vii": invoke_vii, "invoke_iii": invoke_iii, "_fabs": _fabs, "_sin": _sin, "_exp": _exp, "_llvm_pow_f64": _llvm_pow_f64, "_acos": _acos, "_atan2": _atan2, "_fmod": _fmod, "_lseek": _lseek, "__reallyNegative": __reallyNegative, "_asin": _asin, "_atan": _atan, "___buildEnvironment": ___buildEnvironment, "_fflush": _fflush, "_pwrite": _pwrite, "_strerror_r": _strerror_r, "_fprintf": _fprintf, "_open": _open, "_fabsf": _fabsf, "_sbrk": _sbrk, "_send": _send, "_snprintf": _snprintf, "_llvm_bswap_i32": _llvm_bswap_i32, "_emscripten_memcpy_big": _emscripten_memcpy_big, "_fileno": _fileno, "_sysconf": _sysconf, "___setErrNo": ___setErrNo, "_cos": _cos, "_pread": _pread, "_printf": _printf, "_sprintf": _sprintf, "_log": _log, "_toupper": _toupper, "_write": _write, "_isupper": _isupper, "___errno_location": ___errno_location, "_recv": _recv, "_tan": _tan, "_copysign": _copysign, "_getenv": _getenv, "_mkport": _mkport, "__exit": __exit, "_read": _read, "_abort": _abort, "_islower": _islower, "_fwrite": _fwrite, "_time": _time, "_isdigit": _isdigit, "_strerror": _strerror, "__formatString": __formatString, "_isspace": _isspace, "_sqrt": _sqrt, "_exit": _exit, "_close": _close, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "cttz_i8": cttz_i8, "ctlz_i8": ctlz_i8, "NaN": NaN, "Infinity": Infinity, "_stderr": _stderr }, buffer); +var _strlen = Module["_strlen"] = asm["_strlen"]; +var _strcat = Module["_strcat"] = asm["_strcat"]; +var _gzread = Module["_gzread"] = asm["_gzread"]; +var _wcsunits = Module["_wcsunits"] = asm["_wcsunits"]; +var _zscale = Module["_zscale"] = asm["_zscale"]; +var _initwcs = Module["_initwcs"] = asm["_initwcs"]; +var _wcssys = Module["_wcssys"] = asm["_wcssys"]; +var _pix2wcsstr = Module["_pix2wcsstr"] = asm["_pix2wcsstr"]; +var _calloc = Module["_calloc"] = asm["_calloc"]; +var _bitshift64Shl = Module["_bitshift64Shl"] = asm["_bitshift64Shl"]; +var _gzwrite = Module["_gzwrite"] = asm["_gzwrite"]; +var _saostrtod = Module["_saostrtod"] = asm["_saostrtod"]; +var _strncpy = Module["_strncpy"] = asm["_strncpy"]; +var _memset = Module["_memset"] = asm["_memset"]; +var _memcpy = Module["_memcpy"] = asm["_memcpy"]; +var _gzclose = Module["_gzclose"] = asm["_gzclose"]; +var _i64Subtract = Module["_i64Subtract"] = asm["_i64Subtract"]; +var _realloc = Module["_realloc"] = asm["_realloc"]; +var _i64Add = Module["_i64Add"] = asm["_i64Add"]; +var _wcs2pixstr = Module["_wcs2pixstr"] = asm["_wcs2pixstr"]; +var _gzopen = Module["_gzopen"] = asm["_gzopen"]; +var _gzseek = Module["_gzseek"] = asm["_gzseek"]; +var _free = Module["_free"] = asm["_free"]; +var _tolower = Module["_tolower"] = asm["_tolower"]; +var _malloc = Module["_malloc"] = asm["_malloc"]; +var _reg2wcsstr = Module["_reg2wcsstr"] = asm["_reg2wcsstr"]; +var _strcpy = Module["_strcpy"] = asm["_strcpy"]; +var runPostSets = Module["runPostSets"] = asm["runPostSets"]; +var dynCall_iiii = Module["dynCall_iiii"] = asm["dynCall_iiii"]; +var dynCall_iddiii = Module["dynCall_iddiii"] = asm["dynCall_iddiii"]; +var dynCall_vii = Module["dynCall_vii"] = asm["dynCall_vii"]; +var dynCall_iii = Module["dynCall_iii"] = asm["dynCall_iii"]; + +Runtime.stackAlloc = function(size) { return asm['stackAlloc'](size) }; +Runtime.stackSave = function() { return asm['stackSave']() }; +Runtime.stackRestore = function(top) { asm['stackRestore'](top) }; + + +// TODO: strip out parts of this we do not need + +//======= begin closure i64 code ======= + +// Copyright 2009 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Defines a Long class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "long". This + * implementation is derived from LongLib in GWT. + * + */ + +var i64Math = (function() { // Emscripten wrapper + var goog = { math: {} }; + + + /** + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @param {number} low The low (signed) 32 bits of the long. + * @param {number} high The high (signed) 32 bits of the long. + * @constructor + */ + goog.math.Long = function(low, high) { + /** + * @type {number} + * @private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @private + */ + this.high_ = high | 0; // force into 32 signed bits. + }; + + + // NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the + // from* methods on which they depend. + + + /** + * A cache of the Long representations of small integer values. + * @type {!Object} + * @private + */ + goog.math.Long.IntCache_ = {}; + + + /** + * Returns a Long representing the given (32-bit) integer value. + * @param {number} value The 32-bit integer in question. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = goog.math.Long.IntCache_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new goog.math.Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + goog.math.Long.IntCache_[value] = obj; + } + return obj; + }; + + + /** + * Returns a Long representing the given value, provided that it is a finite + * number. Otherwise, zero is returned. + * @param {number} value The number in question. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return goog.math.Long.ZERO; + } else if (value <= -goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MIN_VALUE; + } else if (value + 1 >= goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MAX_VALUE; + } else if (value < 0) { + return goog.math.Long.fromNumber(-value).negate(); + } else { + return new goog.math.Long( + (value % goog.math.Long.TWO_PWR_32_DBL_) | 0, + (value / goog.math.Long.TWO_PWR_32_DBL_) | 0); + } + }; + + + /** + * Returns a Long representing the 64-bit integer that comes by concatenating + * the given high and low bits. Each is assumed to use 32 bits. + * @param {number} lowBits The low 32-bits. + * @param {number} highBits The high 32-bits. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromBits = function(lowBits, highBits) { + return new goog.math.Long(lowBits, highBits); + }; + + + /** + * Returns a Long representation of the given string, written using the given + * radix. + * @param {string} str The textual representation of the Long. + * @param {number=} opt_radix The radix in which the text is written. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return goog.math.Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 8)); + + var result = goog.math.Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = goog.math.Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(goog.math.Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(goog.math.Long.fromNumber(value)); + } + } + return result; + }; + + + // NOTE: the compiler should inline these constant values below and then remove + // these variables, so there should be no runtime penalty for these. + + + /** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_16_DBL_ = 1 << 16; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_24_DBL_ = 1 << 24; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_32_DBL_ = + goog.math.Long.TWO_PWR_16_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_31_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ / 2; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_48_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_64_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_32_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_63_DBL_ = + goog.math.Long.TWO_PWR_64_DBL_ / 2; + + + /** @type {!goog.math.Long} */ + goog.math.Long.ZERO = goog.math.Long.fromInt(0); + + + /** @type {!goog.math.Long} */ + goog.math.Long.ONE = goog.math.Long.fromInt(1); + + + /** @type {!goog.math.Long} */ + goog.math.Long.NEG_ONE = goog.math.Long.fromInt(-1); + + + /** @type {!goog.math.Long} */ + goog.math.Long.MAX_VALUE = + goog.math.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + + + /** @type {!goog.math.Long} */ + goog.math.Long.MIN_VALUE = goog.math.Long.fromBits(0, 0x80000000 | 0); + + + /** + * @type {!goog.math.Long} + * @private + */ + goog.math.Long.TWO_PWR_24_ = goog.math.Long.fromInt(1 << 24); + + + /** @return {number} The value, assuming it is a 32-bit integer. */ + goog.math.Long.prototype.toInt = function() { + return this.low_; + }; + + + /** @return {number} The closest floating-point representation to this value. */ + goog.math.Long.prototype.toNumber = function() { + return this.high_ * goog.math.Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); + }; + + + /** + * @param {number=} opt_radix The radix in which the text should be written. + * @return {string} The textual representation of this value. + */ + goog.math.Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = goog.math.Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } + }; + + + /** @return {number} The high 32-bits as a signed value. */ + goog.math.Long.prototype.getHighBits = function() { + return this.high_; + }; + + + /** @return {number} The low 32-bits as a signed value. */ + goog.math.Long.prototype.getLowBits = function() { + return this.low_; + }; + + + /** @return {number} The low 32-bits as an unsigned value. */ + goog.math.Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : goog.math.Long.TWO_PWR_32_DBL_ + this.low_; + }; + + + /** + * @return {number} Returns the number of bits needed to represent the absolute + * value of this Long. + */ + goog.math.Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } + }; + + + /** @return {boolean} Whether this value is zero. */ + goog.math.Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; + }; + + + /** @return {boolean} Whether this value is negative. */ + goog.math.Long.prototype.isNegative = function() { + return this.high_ < 0; + }; + + + /** @return {boolean} Whether this value is odd. */ + goog.math.Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long equals the other. + */ + goog.math.Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long does not equal the other. + */ + goog.math.Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than the other. + */ + goog.math.Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than or equal to the other. + */ + goog.math.Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than the other. + */ + goog.math.Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than or equal to the other. + */ + goog.math.Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; + }; + + + /** + * Compares this Long with the given one. + * @param {goog.math.Long} other Long to compare against. + * @return {number} 0 if they are the same, 1 if the this is greater, and -1 + * if the given one is greater. + */ + goog.math.Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } + }; + + + /** @return {!goog.math.Long} The negation of this value. */ + goog.math.Long.prototype.negate = function() { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.MIN_VALUE; + } else { + return this.not().add(goog.math.Long.ONE); + } + }; + + + /** + * Returns the sum of this and the given Long. + * @param {goog.math.Long} other Long to add to this one. + * @return {!goog.math.Long} The sum of this and the given Long. + */ + goog.math.Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); + }; + + + /** + * Returns the difference of this and the given Long. + * @param {goog.math.Long} other Long to subtract from this. + * @return {!goog.math.Long} The difference of this and the given Long. + */ + goog.math.Long.prototype.subtract = function(other) { + return this.add(other.negate()); + }; + + + /** + * Returns the product of this and the given long. + * @param {goog.math.Long} other Long to multiply with this. + * @return {!goog.math.Long} The product of this and the other. + */ + goog.math.Long.prototype.multiply = function(other) { + if (this.isZero()) { + return goog.math.Long.ZERO; + } else if (other.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + return other.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return this.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both longs are small, use float multiplication + if (this.lessThan(goog.math.Long.TWO_PWR_24_) && + other.lessThan(goog.math.Long.TWO_PWR_24_)) { + return goog.math.Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); + }; + + + /** + * Returns this Long divided by the given one. + * @param {goog.math.Long} other Long by which to divide. + * @return {!goog.math.Long} This Long divided by the given one. + */ + goog.math.Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + if (other.equals(goog.math.Long.ONE) || + other.equals(goog.math.Long.NEG_ONE)) { + return goog.math.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(goog.math.Long.ZERO)) { + return other.isNegative() ? goog.math.Long.ONE : goog.math.Long.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = goog.math.Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = goog.math.Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = goog.math.Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = goog.math.Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; + }; + + + /** + * Returns this Long modulo the given one. + * @param {goog.math.Long} other Long by which to mod. + * @return {!goog.math.Long} This Long modulo the given one. + */ + goog.math.Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); + }; + + + /** @return {!goog.math.Long} The bitwise-NOT of this value. */ + goog.math.Long.prototype.not = function() { + return goog.math.Long.fromBits(~this.low_, ~this.high_); + }; + + + /** + * Returns the bitwise-AND of this Long and the given one. + * @param {goog.math.Long} other The Long with which to AND. + * @return {!goog.math.Long} The bitwise-AND of this and the other. + */ + goog.math.Long.prototype.and = function(other) { + return goog.math.Long.fromBits(this.low_ & other.low_, + this.high_ & other.high_); + }; + + + /** + * Returns the bitwise-OR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to OR. + * @return {!goog.math.Long} The bitwise-OR of this and the other. + */ + goog.math.Long.prototype.or = function(other) { + return goog.math.Long.fromBits(this.low_ | other.low_, + this.high_ | other.high_); + }; + + + /** + * Returns the bitwise-XOR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to XOR. + * @return {!goog.math.Long} The bitwise-XOR of this and the other. + */ + goog.math.Long.prototype.xor = function(other) { + return goog.math.Long.fromBits(this.low_ ^ other.low_, + this.high_ ^ other.high_); + }; + + + /** + * Returns this Long with bits shifted to the left by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the left by the given amount. + */ + goog.math.Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return goog.math.Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return goog.math.Long.fromBits(0, low << (numBits - 32)); + } + } + }; + + + /** + * Returns this Long with bits shifted to the right by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount. + */ + goog.math.Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return goog.math.Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } + }; + + + /** + * Returns this Long with bits shifted to the right by the given amount, with + * the new top bits matching the current sign bit. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount, with + * zeros placed into the new leading bits. + */ + goog.math.Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return goog.math.Long.fromBits(high, 0); + } else { + return goog.math.Long.fromBits(high >>> (numBits - 32), 0); + } + } + }; + + //======= begin jsbn ======= + + var navigator = { appName: 'Modern Browser' }; // polyfill a little + + // Copyright (c) 2005 Tom Wu + // All Rights Reserved. + // http://www-cs-students.stanford.edu/~tjw/jsbn/ + + /* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ + + // Basic JavaScript BN library - subset useful for RSA encryption. + + // Bits per digit + var dbits; + + // JavaScript engine analysis + var canary = 0xdeadbeefcafe; + var j_lm = ((canary&0xffffff)==0xefcafe); + + // (public) Constructor + function BigInteger(a,b,c) { + if(a != null) + if("number" == typeof a) this.fromNumber(a,b,c); + else if(b == null && "string" != typeof a) this.fromString(a,256); + else this.fromString(a,b); + } + + // return new, unset BigInteger + function nbi() { return new BigInteger(null); } + + // am: Compute w_j += (x*this_i), propagate carries, + // c is initial carry, returns final carry. + // c < 3*dvalue, x < 2*dvalue, this_i < dvalue + // We need to select the fastest one that works in this environment. + + // am1: use a single mult and divide to get the high bits, + // max digit bits should be 26 because + // max internal value = 2*dvalue^2-2*dvalue (< 2^53) + function am1(i,x,w,j,c,n) { + while(--n >= 0) { + var v = x*this[i++]+w[j]+c; + c = Math.floor(v/0x4000000); + w[j++] = v&0x3ffffff; + } + return c; + } + // am2 avoids a big mult-and-extract completely. + // Max digit bits should be <= 30 because we do bitwise ops + // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) + function am2(i,x,w,j,c,n) { + var xl = x&0x7fff, xh = x>>15; + while(--n >= 0) { + var l = this[i]&0x7fff; + var h = this[i++]>>15; + var m = xh*l+h*xl; + l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); + c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); + w[j++] = l&0x3fffffff; + } + return c; + } + // Alternately, set max digit bits to 28 since some + // browsers slow down when dealing with 32-bit numbers. + function am3(i,x,w,j,c,n) { + var xl = x&0x3fff, xh = x>>14; + while(--n >= 0) { + var l = this[i]&0x3fff; + var h = this[i++]>>14; + var m = xh*l+h*xl; + l = xl*l+((m&0x3fff)<<14)+w[j]+c; + c = (l>>28)+(m>>14)+xh*h; + w[j++] = l&0xfffffff; + } + return c; + } + if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { + BigInteger.prototype.am = am2; + dbits = 30; + } + else if(j_lm && (navigator.appName != "Netscape")) { + BigInteger.prototype.am = am1; + dbits = 26; + } + else { // Mozilla/Netscape seems to prefer am3 + BigInteger.prototype.am = am3; + dbits = 28; + } + + BigInteger.prototype.DB = dbits; + BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; + r.t = this.t; + r.s = this.s; + } + + // (protected) set from integer value x, -DV <= x < DV + function bnpFromInt(x) { + this.t = 1; + this.s = (x<0)?-1:0; + if(x > 0) this[0] = x; + else if(x < -1) this[0] = x+DV; + else this.t = 0; + } + + // return bigint initialized to value + function nbv(i) { var r = nbi(); r.fromInt(i); return r; } + + // (protected) set from string and radix + function bnpFromString(s,b) { + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 256) k = 8; // byte array + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else { this.fromRadix(s,b); return; } + this.t = 0; + this.s = 0; + var i = s.length, mi = false, sh = 0; + while(--i >= 0) { + var x = (k==8)?s[i]&0xff:intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if(sh == 0) + this[this.t++] = x; + else if(sh+k > this.DB) { + this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); + } + else + this[this.t-1] |= x<= this.DB) sh -= this.DB; + } + if(k == 8 && (s[0]&0x80) != 0) { + this.s = -1; + if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; + } + + // (public) return string representation in given radix + function bnToString(b) { + if(this.s < 0) return "-"+this.negate().toString(b); + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else return this.toRadix(b); + var km = (1< 0) { + if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } + while(i >= 0) { + if(p < k) { + d = (this[i]&((1<>(p+=this.DB-k); + } + else { + d = (this[i]>>(p-=k))&km; + if(p <= 0) { p += this.DB; --i; } + } + if(d > 0) m = true; + if(m) r += int2char(d); + } + } + return m?r:"0"; + } + + // (public) -this + function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } + + // (public) |this| + function bnAbs() { return (this.s<0)?this.negate():this; } + + // (public) return + if this > a, - if this < a, 0 if equal + function bnCompareTo(a) { + var r = this.s-a.s; + if(r != 0) return r; + var i = this.t; + r = i-a.t; + if(r != 0) return (this.s<0)?-r:r; + while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; + return 0; + } + + // returns bit length of the integer x + function nbits(x) { + var r = 1, t; + if((t=x>>>16) != 0) { x = t; r += 16; } + if((t=x>>8) != 0) { x = t; r += 8; } + if((t=x>>4) != 0) { x = t; r += 4; } + if((t=x>>2) != 0) { x = t; r += 2; } + if((t=x>>1) != 0) { x = t; r += 1; } + return r; + } + + // (public) return the number of bits in "this" + function bnBitLength() { + if(this.t <= 0) return 0; + return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); + } + + // (protected) r = this << n*DB + function bnpDLShiftTo(n,r) { + var i; + for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; + for(i = n-1; i >= 0; --i) r[i] = 0; + r.t = this.t+n; + r.s = this.s; + } + + // (protected) r = this >> n*DB + function bnpDRShiftTo(n,r) { + for(var i = n; i < this.t; ++i) r[i-n] = this[i]; + r.t = Math.max(this.t-n,0); + r.s = this.s; + } + + // (protected) r = this << n + function bnpLShiftTo(n,r) { + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<= 0; --i) { + r[i+ds+1] = (this[i]>>cbs)|c; + c = (this[i]&bm)<= 0; --i) r[i] = 0; + r[ds] = c; + r.t = this.t+ds+1; + r.s = this.s; + r.clamp(); + } + + // (protected) r = this >> n + function bnpRShiftTo(n,r) { + r.s = this.s; + var ds = Math.floor(n/this.DB); + if(ds >= this.t) { r.t = 0; return; } + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<>bs; + for(var i = ds+1; i < this.t; ++i) { + r[i-ds-1] |= (this[i]&bm)<>bs; + } + if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; + } + if(a.t < this.t) { + c -= a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c -= a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c<0)?-1:0; + if(c < -1) r[i++] = this.DV+c; + else if(c > 0) r[i++] = c; + r.t = i; + r.clamp(); + } + + // (protected) r = this * a, r != this,a (HAC 14.12) + // "this" should be the larger one if appropriate. + function bnpMultiplyTo(a,r) { + var x = this.abs(), y = a.abs(); + var i = x.t; + r.t = i+y.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); + r.s = 0; + r.clamp(); + if(this.s != a.s) BigInteger.ZERO.subTo(r,r); + } + + // (protected) r = this^2, r != this (HAC 14.16) + function bnpSquareTo(r) { + var x = this.abs(); + var i = r.t = 2*x.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < x.t-1; ++i) { + var c = x.am(i,x[i],r,2*i,0,1); + if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { + r[i+x.t] -= x.DV; + r[i+x.t+1] = 1; + } + } + if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); + r.s = 0; + r.clamp(); + } + + // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) + // r != q, this != m. q or r may be null. + function bnpDivRemTo(m,q,r) { + var pm = m.abs(); + if(pm.t <= 0) return; + var pt = this.abs(); + if(pt.t < pm.t) { + if(q != null) q.fromInt(0); + if(r != null) this.copyTo(r); + return; + } + if(r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus + if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } + else { pm.copyTo(y); pt.copyTo(r); } + var ys = y.t; + var y0 = y[ys-1]; + if(y0 == 0) return; + var yt = y0*(1<1)?y[ys-2]>>this.F2:0); + var d1 = this.FV/yt, d2 = (1<= 0) { + r[r.t++] = 1; + r.subTo(t,r); + } + BigInteger.ONE.dlShiftTo(ys,t); + t.subTo(y,y); // "negative" y so we can replace sub with am later + while(y.t < ys) y[y.t++] = 0; + while(--j >= 0) { + // Estimate quotient digit + var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); + if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out + y.dlShiftTo(j,t); + r.subTo(t,r); + while(r[i] < --qd) r.subTo(t,r); + } + } + if(q != null) { + r.drShiftTo(ys,q); + if(ts != ms) BigInteger.ZERO.subTo(q,q); + } + r.t = ys; + r.clamp(); + if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder + if(ts < 0) BigInteger.ZERO.subTo(r,r); + } + + // (public) this mod a + function bnMod(a) { + var r = nbi(); + this.abs().divRemTo(a,null,r); + if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); + return r; + } + + // Modular reduction using "classic" algorithm + function Classic(m) { this.m = m; } + function cConvert(x) { + if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; + } + function cRevert(x) { return x; } + function cReduce(x) { x.divRemTo(this.m,null,x); } + function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + Classic.prototype.convert = cConvert; + Classic.prototype.revert = cRevert; + Classic.prototype.reduce = cReduce; + Classic.prototype.mulTo = cMulTo; + Classic.prototype.sqrTo = cSqrTo; + + // (protected) return "-1/this % 2^DB"; useful for Mont. reduction + // justification: + // xy == 1 (mod m) + // xy = 1+km + // xy(2-xy) = (1+km)(1-km) + // x[y(2-xy)] = 1-k^2m^2 + // x[y(2-xy)] == 1 (mod m^2) + // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 + // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. + // JS multiply "overflows" differently from C/C++, so care is needed here. + function bnpInvDigit() { + if(this.t < 1) return 0; + var x = this[0]; + if((x&1) == 0) return 0; + var y = x&3; // y == 1/x mod 2^2 + y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 + y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 + y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y>0)?this.DV-y:-y; + } + + // Montgomery reduction + function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp&0x7fff; + this.mph = this.mp>>15; + this.um = (1<<(m.DB-15))-1; + this.mt2 = 2*m.t; + } + + // xR mod m + function montConvert(x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t,r); + r.divRemTo(this.m,null,r); + if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); + return r; + } + + // x/R mod m + function montRevert(x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + + // x = x/R mod m (HAC 14.32) + function montReduce(x) { + while(x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0; + for(var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i]&0x7fff; + var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; + // use am to combine the multiply-shift-add into one call + j = i+this.m.t; + x[j] += this.m.am(0,u0,x,i,0,this.m.t); + // propagate carry + while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } + } + x.clamp(); + x.drShiftTo(this.m.t,x); + if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); + } + + // r = "x^2/R mod m"; x != r + function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + // r = "xy/R mod m"; x,y != r + function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + + Montgomery.prototype.convert = montConvert; + Montgomery.prototype.revert = montRevert; + Montgomery.prototype.reduce = montReduce; + Montgomery.prototype.mulTo = montMulTo; + Montgomery.prototype.sqrTo = montSqrTo; + + // (protected) true iff this is even + function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } + + // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) + function bnpExp(e,z) { + if(e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; + g.copyTo(r); + while(--i >= 0) { + z.sqrTo(r,r2); + if((e&(1< 0) z.mulTo(r2,g,r); + else { var t = r; r = r2; r2 = t; } + } + return z.revert(r); + } + + // (public) this^e % m, 0 <= e < 2^32 + function bnModPowInt(e,m) { + var z; + if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e,z); + } + + // protected + BigInteger.prototype.copyTo = bnpCopyTo; + BigInteger.prototype.fromInt = bnpFromInt; + BigInteger.prototype.fromString = bnpFromString; + BigInteger.prototype.clamp = bnpClamp; + BigInteger.prototype.dlShiftTo = bnpDLShiftTo; + BigInteger.prototype.drShiftTo = bnpDRShiftTo; + BigInteger.prototype.lShiftTo = bnpLShiftTo; + BigInteger.prototype.rShiftTo = bnpRShiftTo; + BigInteger.prototype.subTo = bnpSubTo; + BigInteger.prototype.multiplyTo = bnpMultiplyTo; + BigInteger.prototype.squareTo = bnpSquareTo; + BigInteger.prototype.divRemTo = bnpDivRemTo; + BigInteger.prototype.invDigit = bnpInvDigit; + BigInteger.prototype.isEven = bnpIsEven; + BigInteger.prototype.exp = bnpExp; + + // public + BigInteger.prototype.toString = bnToString; + BigInteger.prototype.negate = bnNegate; + BigInteger.prototype.abs = bnAbs; + BigInteger.prototype.compareTo = bnCompareTo; + BigInteger.prototype.bitLength = bnBitLength; + BigInteger.prototype.mod = bnMod; + BigInteger.prototype.modPowInt = bnModPowInt; + + // "constants" + BigInteger.ZERO = nbv(0); + BigInteger.ONE = nbv(1); + + // jsbn2 stuff + + // (protected) convert from radix string + function bnpFromRadix(s,b) { + this.fromInt(0); + if(b == null) b = 10; + var cs = this.chunkSize(b); + var d = Math.pow(b,cs), mi = false, j = 0, w = 0; + for(var i = 0; i < s.length; ++i) { + var x = intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-" && this.signum() == 0) mi = true; + continue; + } + w = b*w+x; + if(++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w,0); + j = 0; + w = 0; + } + } + if(j > 0) { + this.dMultiply(Math.pow(b,j)); + this.dAddOffset(w,0); + } + if(mi) BigInteger.ZERO.subTo(this,this); + } + + // (protected) return x s.t. r^x < DV + function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } + + // (public) 0 if this == 0, 1 if this > 0 + function bnSigNum() { + if(this.s < 0) return -1; + else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; + else return 1; + } + + // (protected) this *= n, this >= 0, 1 < n < DV + function bnpDMultiply(n) { + this[this.t] = this.am(0,n-1,this,0,0,this.t); + ++this.t; + this.clamp(); + } + + // (protected) this += n << w words, this >= 0 + function bnpDAddOffset(n,w) { + if(n == 0) return; + while(this.t <= w) this[this.t++] = 0; + this[w] += n; + while(this[w] >= this.DV) { + this[w] -= this.DV; + if(++w >= this.t) this[this.t++] = 0; + ++this[w]; + } + } + + // (protected) convert to radix string + function bnpToRadix(b) { + if(b == null) b = 10; + if(this.signum() == 0 || b < 2 || b > 36) return "0"; + var cs = this.chunkSize(b); + var a = Math.pow(b,cs); + var d = nbv(a), y = nbi(), z = nbi(), r = ""; + this.divRemTo(d,y,z); + while(y.signum() > 0) { + r = (a+z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d,y,z); + } + return z.intValue().toString(b) + r; + } + + // (public) return value as integer + function bnIntValue() { + if(this.s < 0) { + if(this.t == 1) return this[0]-this.DV; + else if(this.t == 0) return -1; + } + else if(this.t == 1) return this[0]; + else if(this.t == 0) return 0; + // assumes 16 < DB < 32 + return ((this[1]&((1<<(32-this.DB))-1))<>= this.DB; + } + if(a.t < this.t) { + c += a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c += a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += a.s; + } + r.s = (c<0)?-1:0; + if(c > 0) r[i++] = c; + else if(c < -1) r[i++] = this.DV+c; + r.t = i; + r.clamp(); + } + + BigInteger.prototype.fromRadix = bnpFromRadix; + BigInteger.prototype.chunkSize = bnpChunkSize; + BigInteger.prototype.signum = bnSigNum; + BigInteger.prototype.dMultiply = bnpDMultiply; + BigInteger.prototype.dAddOffset = bnpDAddOffset; + BigInteger.prototype.toRadix = bnpToRadix; + BigInteger.prototype.intValue = bnIntValue; + BigInteger.prototype.addTo = bnpAddTo; + + //======= end jsbn ======= + + // Emscripten wrapper + var Wrapper = { + abs: function(l, h) { + var x = new goog.math.Long(l, h); + var ret; + if (x.isNegative()) { + ret = x.negate(); + } else { + ret = x; + } + HEAP32[tempDoublePtr>>2] = ret.low_; + HEAP32[tempDoublePtr+4>>2] = ret.high_; + }, + ensureTemps: function() { + if (Wrapper.ensuredTemps) return; + Wrapper.ensuredTemps = true; + Wrapper.two32 = new BigInteger(); + Wrapper.two32.fromString('4294967296', 10); + Wrapper.two64 = new BigInteger(); + Wrapper.two64.fromString('18446744073709551616', 10); + Wrapper.temp1 = new BigInteger(); + Wrapper.temp2 = new BigInteger(); + }, + lh2bignum: function(l, h) { + var a = new BigInteger(); + a.fromString(h.toString(), 10); + var b = new BigInteger(); + a.multiplyTo(Wrapper.two32, b); + var c = new BigInteger(); + c.fromString(l.toString(), 10); + var d = new BigInteger(); + c.addTo(b, d); + return d; + }, + stringify: function(l, h, unsigned) { + var ret = new goog.math.Long(l, h).toString(); + if (unsigned && ret[0] == '-') { + // unsign slowly using jsbn bignums + Wrapper.ensureTemps(); + var bignum = new BigInteger(); + bignum.fromString(ret, 10); + ret = new BigInteger(); + Wrapper.two64.addTo(bignum, ret); + ret = ret.toString(10); + } + return ret; + }, + fromString: function(str, base, min, max, unsigned) { + Wrapper.ensureTemps(); + var bignum = new BigInteger(); + bignum.fromString(str, base); + var bigmin = new BigInteger(); + bigmin.fromString(min, 10); + var bigmax = new BigInteger(); + bigmax.fromString(max, 10); + if (unsigned && bignum.compareTo(BigInteger.ZERO) < 0) { + var temp = new BigInteger(); + bignum.addTo(Wrapper.two64, temp); + bignum = temp; + } + var error = false; + if (bignum.compareTo(bigmin) < 0) { + bignum = bigmin; + error = true; + } else if (bignum.compareTo(bigmax) > 0) { + bignum = bigmax; + error = true; + } + var ret = goog.math.Long.fromString(bignum.toString()); // min-max checks should have clamped this to a range goog.math.Long can handle well + HEAP32[tempDoublePtr>>2] = ret.low_; + HEAP32[tempDoublePtr+4>>2] = ret.high_; + if (error) throw 'range error'; + } + }; + return Wrapper; +})(); + +//======= end closure i64 code ======= + + + +// === Auto-generated postamble setup entry stuff === + +if (memoryInitializer) { + if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) { + var data = Module['readBinary'](memoryInitializer); + HEAPU8.set(data, STATIC_BASE); + } else { + addRunDependency('memory initializer'); + Browser.asyncLoad(memoryInitializer, function(data) { + HEAPU8.set(data, STATIC_BASE); + removeRunDependency('memory initializer'); + }, function(data) { + throw 'could not load memory initializer ' + memoryInitializer; + }); + } +} + +function ExitStatus(status) { + this.name = "ExitStatus"; + this.message = "Program terminated with exit(" + status + ")"; + this.status = status; +}; +ExitStatus.prototype = new Error(); +ExitStatus.prototype.constructor = ExitStatus; + +var initialStackTop; +var preloadStartTime = null; +var calledMain = false; + +dependenciesFulfilled = function runCaller() { + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!Module['calledRun'] && shouldRunNow) run(); + if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled +} + +Module['callMain'] = Module.callMain = function callMain(args) { + assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)'); + assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called'); + + args = args || []; + + ensureInitRuntime(); + + var argc = args.length+1; + function pad() { + for (var i = 0; i < 4-1; i++) { + argv.push(0); + } + } + var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL) ]; + pad(); + for (var i = 0; i < argc-1; i = i + 1) { + argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL)); + pad(); + } + argv.push(0); + argv = allocate(argv, 'i32', ALLOC_NORMAL); + + initialStackTop = STACKTOP; + + try { + + var ret = Module['_main'](argc, argv, 0); + + + // if we're not running an evented main loop, it's time to exit + if (!Module['noExitRuntime']) { + exit(ret); + } + } + catch(e) { + if (e instanceof ExitStatus) { + // exit() throws this once it's done to make sure execution + // has been stopped completely + return; + } else if (e == 'SimulateInfiniteLoop') { + // running an evented main loop, don't immediately exit + Module['noExitRuntime'] = true; + return; + } else { + if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]); + throw e; + } + } finally { + calledMain = true; + } +} + + + + +function run(args) { + args = args || Module['arguments']; + + if (preloadStartTime === null) preloadStartTime = Date.now(); + + if (runDependencies > 0) { + Module.printErr('run() called, but dependencies remain, so not running'); + return; + } + + preRun(); + + if (runDependencies > 0) return; // a preRun added a dependency, run will be called later + if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame + + function doRun() { + if (Module['calledRun']) return; // run may have just been called while the async setStatus time below was happening + Module['calledRun'] = true; + + ensureInitRuntime(); + + preMain(); + + if (ENVIRONMENT_IS_WEB && preloadStartTime !== null) { + Module.printErr('pre-main prep time: ' + (Date.now() - preloadStartTime) + ' ms'); + } + + if (Module['_main'] && shouldRunNow) { + Module['callMain'](args); + } + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + if (!ABORT) doRun(); + }, 1); + } else { + doRun(); + } +} +Module['run'] = Module.run = run; + +function exit(status) { + ABORT = true; + EXITSTATUS = status; + STACKTOP = initialStackTop; + + // exit the runtime + exitRuntime(); + + // TODO We should handle this differently based on environment. + // In the browser, the best we can do is throw an exception + // to halt execution, but in node we could process.exit and + // I'd imagine SM shell would have something equivalent. + // This would let us set a proper exit status (which + // would be great for checking test exit statuses). + // https://github.com/kripken/emscripten/issues/1371 + + // throw an exception to halt the current execution + throw new ExitStatus(status); +} +Module['exit'] = Module.exit = exit; + +function abort(text) { + if (text) { + Module.print(text); + Module.printErr(text); + } + + ABORT = true; + EXITSTATUS = 1; + + var extra = '\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.'; + + throw 'abort() at ' + stackTrace() + extra; +} +Module['abort'] = Module.abort = abort; + +// {{PRE_RUN_ADDITIONS}} + +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} + +// shouldRunNow refers to calling main(), not run(). +var shouldRunNow = true; +if (Module['noInitialRun']) { + shouldRunNow = false; +} + + +run(); + +// {{POST_RUN_ADDITIONS}} + + + + + + +// {{MODULE_ADDITIONS}} + + + + + +Module['arrfile'] = function(filename, arr) { + try{ FS.unlink("/" + filename); } + catch(e){ ; } + FS.createDataFile("/", filename, arr, true, true); + return {path: filename, size: arr.byteLength}; +}; + +Module['gzcompress'] = function(data) { // TODO: Accept strings + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['output.gz', 'wb']); + var buffer = _malloc(data.length); + HEAPU8.set(data, buffer); + ccall('gzwrite', 'number', ['number', 'number', 'number'], [gzFile, buffer, data.length]); + ccall('gzclose', 'number', ['number'], [gzFile]); + _free(buffer); + var ret = new Uint8Array(FS.root.contents['output.gz'].contents); + FS.unlink('output.gz'); + return ret; +}; + +Module['gzdecompress'] = function(data) { + var BUFSIZE = 1024*1024; + FS.createDataFile('/', 'input.gz', data, true, true); + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['input.gz', 'rb']); + var buffer = _malloc(BUFSIZE); + var chunks = []; + var total = 0; + var len; + while( (len = ccall('gzread', 'number', ['number', 'number', 'number'], [gzFile, buffer, BUFSIZE])) > 0) { + chunks.push(new Uint8Array(len)); + chunks[chunks.length-1].set(HEAPU8.subarray(buffer, buffer+len)); + total += len; + } + ccall('gzclose', 'number', ['number'], [gzFile]); + FS.unlink('input.gz'); + _free(buffer); + var ret = new Uint8Array(total); + var curr = 0; + for (var i = 0; i < chunks.length; i++) { + ret.set(chunks[i], curr); + curr += chunks[i].length; + } + return ret; +}; + + + + return { + initwcs: Module.cwrap('initwcs', 'number', ['string', 'number']), + wcssys: Module.cwrap('wcssys', 'string', ['number', 'string']), + wcsunits: Module.cwrap('wcsunits', 'string', ['number', 'string']), + pix2wcs: Module.cwrap('pix2wcsstr', 'string', ['number', 'number', 'number']), + wcs2pix: Module.cwrap('wcs2pixstr', 'string', ['number', 'number', 'number']), + reg2wcs: Module.cwrap('reg2wcsstr', 'string', ['number', 'string']), + saostrtod: Module.cwrap('saostrtod', 'number', ['string']), + zscale: Module.cwrap('zscale', 'string', ['number', 'number', 'number', 'number', 'number', 'number']), + arrfile: Module["arrfile"], + gzopen: Module.cwrap('gzopen', 'number', ['string', 'string']), + gzread: Module.cwrap('gzread', 'number', ['number', 'number', 'number']), + gzwrite: Module.cwrap('gzwrite', 'number', ['number', 'number', 'number']), + gzclose: Module.cwrap('gzclose', 'number', ['number']), + gzseek: Module.cwrap('gzseek', 'number', ['number', 'number', 'number']), + compress: Module['gzcompress'], + decompress: Module['gzdecompress'] + }; +})(); + diff --git a/js/bzip2.js b/js/bzip2.js new file mode 100644 index 00000000..f23d9234 --- /dev/null +++ b/js/bzip2.js @@ -0,0 +1,283 @@ +/* + bzip2.js - a small bzip2 decompression implementation + + Copyright 2011 by antimatter15 (antimatter15@gmail.com) + + Based on micro-bunzip by Rob Landley (rob@landley.net). + + Copyright (c) 2011 by antimatter15 (antimatter15@gmail.com). + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH + THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +var bzip2 = {}; + +bzip2.array = function(bytes){ + var bit = 0, byte = 0; + var BITMASK = [0, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF ]; + return function(n){ + var result = 0; + while(n > 0){ + var left = 8 - bit; + if(n >= left){ + result <<= left; + result |= (BITMASK[left] & bytes[byte++]); + bit = 0; + n -= left; + }else{ + result <<= n; + result |= ((bytes[byte] & (BITMASK[n] << (8 - n - bit))) >> (8 - n - bit)); + bit += n; + n = 0; + } + } + return result + } +} + +bzip2.simple = function(bits){ + var size = bzip2.header(bits); + var all = [], chunk = [] + do{ + all = all.concat(all, chunk); + chunk = bzip2.decompress(bits, size); + }while(chunk != -1); + return all; +} + +bzip2.header = function(bits){ + if(bits(8*3) != 4348520) throw "No magic number found"; + var i = bits(8) - 48; + if(i < 1 || i > 9) throw "Not a BZIP archive"; + return i; +}; + + +//takes a function for reading the block data (starting with 0x314159265359) +//a block size (0-9) (optional, defaults to 9) +//a length at which to stop decompressing and return the output +bzip2.decompress = function(bits, size, len){ + var MAX_HUFCODE_BITS = 20; + var MAX_SYMBOLS = 258; + var SYMBOL_RUNA = 0; + var SYMBOL_RUNB = 1; + var GROUP_SIZE = 50; + + var bufsize = 100000 * size; + for(var h = '', i = 0; i < 6; i++) h += bits(8).toString(16); + if(h == "177245385090") return -1; //last block + if(h != "314159265359") throw "eek not valid bzip data"; + bits(32); //ignore CRC codes + if(bits(1)) throw "unsupported obsolete version"; + var origPtr = bits(24); + if(origPtr > bufsize) throw "Initial position larger than buffer size"; + var t = bits(16); + var symToByte = new Uint8Array(256), + symTotal = 0; + for (i = 0; i < 16; i++) { + if(t & (1 << (15 - i))) { + var k = bits(16); + for(j = 0; j < 16; j++){ + if(k & (1 << (15 - j))){ + symToByte[symTotal++] = (16 * i) + j; + } + } + } + } + + var groupCount = bits(3); + if(groupCount < 2 || groupCount > 6) throw "another error"; + var nSelectors = bits(15); + if(nSelectors == 0) throw "meh"; + var mtfSymbol = []; //TODO: possibly replace JS array with typed arrays + for(var i = 0; i < groupCount; i++) mtfSymbol[i] = i; + var selectors = new Uint8Array(32768); + + for(var i = 0; i < nSelectors; i++){ + for(var j = 0; bits(1); j++) if(j >= groupCount) throw "whoops another error"; + var uc = mtfSymbol[j]; + mtfSymbol.splice(j, 1); //this is a probably inefficient MTF transform + mtfSymbol.splice(0, 0, uc); + selectors[i] = uc; + } + + var symCount = symTotal + 2; + var groups = []; + for(var j = 0; j < groupCount; j++){ + var length = new Uint8Array(MAX_SYMBOLS), + temp = new Uint8Array(MAX_HUFCODE_BITS+1); + t = bits(5); //lengths + for(var i = 0; i < symCount; i++){ + while(true){ + if (t < 1 || t > MAX_HUFCODE_BITS) throw "I gave up a while ago on writing error messages"; + if(!bits(1)) break; + if(!bits(1)) t++; + else t--; + } + length[i] = t; + } + var minLen, maxLen; + minLen = maxLen = length[0]; + for(var i = 1; i < symCount; i++){ + if(length[i] > maxLen) maxLen = length[i]; + else if(length[i] < minLen) minLen = length[i]; + } + var hufGroup; + hufGroup = groups[j] = {}; + hufGroup.permute = new Uint32Array(MAX_SYMBOLS); + hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 1); + hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); + hufGroup.minLen = minLen; + hufGroup.maxLen = maxLen; + var base = hufGroup.base.subarray(1); + var limit = hufGroup.limit.subarray(1); + var pp = 0; + for(var i = minLen; i <= maxLen; i++) + for(var t = 0; t < symCount; t++) + if(length[t] == i) hufGroup.permute[pp++] = t; + for(i = minLen; i <= maxLen; i++) temp[i] = limit[i] = 0; + for(i = 0; i < symCount; i++) temp[length[i]]++; + pp = t = 0; + for(i = minLen; i < maxLen; i++) { + pp += temp[i]; + limit[i] = pp - 1; + pp <<= 1; + base[i+1] = pp - (t += temp[i]); + } + limit[maxLen]=pp+temp[maxLen]-1; + base[minLen]=0; + } + var byteCount = new Uint32Array(256); + for(var i = 0; i < 256; i++) mtfSymbol[i] = i; + var runPos, count, symCount, selector; + runPos = count = symCount = selector = 0; + var buf = new Uint32Array(bufsize); + while(true){ + if(!(symCount--)){ + symCount = GROUP_SIZE - 1; + if(selector >= nSelectors) throw "meow i'm a kitty, that's an error"; + hufGroup = groups[selectors[selector++]]; + base = hufGroup.base.subarray(1); + limit = hufGroup.limit.subarray(1); + } + i = hufGroup.minLen; + j = bits(i); + while(true){ + if(i > hufGroup.maxLen) throw "rawr i'm a dinosaur"; + if(j <= limit[i]) break; + i++; + j = (j << 1) | bits(1); + } + j -= base[i]; + if(j < 0 || j >= MAX_SYMBOLS) throw "moo i'm a cow"; + var nextSym = hufGroup.permute[j]; + if (nextSym == SYMBOL_RUNA || nextSym == SYMBOL_RUNB) { + if(!runPos){ + runPos = 1; + t = 0; + } + if(nextSym == SYMBOL_RUNA) t += runPos; + else t += 2 * runPos; + runPos <<= 1; + continue; + } + if(runPos){ + runPos = 0; + if(count + t >= bufsize) throw "Boom."; + uc = symToByte[mtfSymbol[0]]; + byteCount[uc] += t; + while(t--) buf[count++] = uc; + } + if(nextSym > symTotal) break; + if(count >= bufsize) throw "I can't think of anything. Error"; + i = nextSym -1; + uc = mtfSymbol[i]; + mtfSymbol.splice(i, 1); + mtfSymbol.splice(0, 0, uc); + uc = symToByte[uc]; + byteCount[uc]++; + buf[count++] = uc; + } + if(origPtr < 0 || origPtr >= count) throw "I'm a monkey and I'm throwing something at someone, namely you"; + var j = 0; + for(var i = 0; i < 256; i++){ + k = j + byteCount[i]; + byteCount[i] = j; + j = k; + } + for(var i = 0; i < count; i++){ + uc = buf[i] & 0xff; + buf[byteCount[uc]] |= (i << 8); + byteCount[uc]++; + } + var pos = 0, current = 0, run = 0; + if(count) { + pos = buf[origPtr]; + current = (pos & 0xff); + pos >>= 8; + run = -1; + } + count = count; + + var maxindex = 10000000; + var output = []; + var bindex = maxindex + 1; + var outbuf; + + var copies, previous, outbyte; + if(!len) len = Infinity; + while(count){ + count--; + previous = current; + pos = buf[pos]; + current = pos & 0xff; + pos >>= 8; + if(run++ == 3){ + copies = current; + outbyte = previous; + current = -1; + }else{ + copies = 1; + outbyte = current; + } + while(copies--){ + if ( bindex >= maxindex ) { + if ( outbuf !== undefined ) { + output.push(outbuf); + } + outbuf = new Uint8Array(maxindex); + bindex = 0; + } + + outbuf[bindex++] = outbyte; + + if(!--len) { + outbuf = outbuf.subarray(0, bindex); + output.push(outbuf); + return output; + } + } + if(current != previous) run = 0; + + } + + outbuf = outbuf.subarray(0, bindex); + output.push(outbuf); + return output; +} diff --git a/js/dhtmlwindow.js b/js/dhtmlwindow.js new file mode 100644 index 00000000..c53bdde1 --- /dev/null +++ b/js/dhtmlwindow.js @@ -0,0 +1,412 @@ +// ------------------------------------------------------------------- +// DHTML Window Widget- By Dynamic Drive, available at: http://www.dynamicdrive.com +// v1.0: Script created Feb 15th, 07' +// v1.01: Feb 21th, 07' (see changelog.txt) +// v1.02: March 26th, 07' (see changelog.txt) +// v1.03: May 5th, 07' (see changelog.txt) +// v1.1: Oct 29th, 07' (see changelog.txt) +// ------------------------------------------------------------------- + +var dhtmlwindow={ +imagefiles:['windowfiles/min.gif', 'windowfiles/close.gif', 'windowfiles/restore.gif', 'windowfiles/resize.gif'], //Path to 4 images used by script, in that order +ajaxbustcache: true, //Bust caching when fetching a file via Ajax? +ajaxloadinghtml: 'Loading Page. Please wait...', //HTML to show while window fetches Ajax Content? + +minimizeorder: 0, +zIndexvalue:100, +tobjects: [], //object to contain references to dhtml window divs, for cleanup purposes +lastactivet: {}, //reference to last active DHTML window + +init:function(t){ + var domwindow=document.createElement("div") //create dhtml window div + domwindow.id=t + domwindow.className="dhtmlwindow" + var domwindowdata='' + domwindowdata='

    ' + domwindowdata+='
    ' + domwindowdata+='
     
    ' + domwindowdata+='' + domwindow.innerHTML=domwindowdata + document.getElementById("dhtmlwindowholder").appendChild(domwindow) + //this.zIndexvalue=(this.zIndexvalue)? this.zIndexvalue+1 : 100 //z-index value for DHTML window: starts at 0, increments whenever a window has focus + var t=document.getElementById(t) + var divs=t.getElementsByTagName("div") + for (var i=0; i' + window.frames["_iframe-"+t.id].location.replace(contentsource) //set location of iframe window to specified URL + } + else if (contenttype=="ajax"){ + this.ajax_connect(contentsource, t) //populate window with external contents fetched via Ajax + } + t.contentarea.datatype=contenttype //store contenttype of current window for future reference +}, + +setupdrag:function(e){ + var d=dhtmlwindow //reference dhtml window object + var t=this._parent //reference dhtml window div + d.etarget=this //remember div mouse is currently held down on ("handle" or "resize" div) + var e=window.event || e + // d.initmousex=e.clientX //store x position of mouse onmousedown + // d.initmousey=e.clientY + if( e.touches && e.touches.length ){ + d.initmousex = e.touches[0].clientX; + d.initmousey = e.touches[0].clientY; + } else { + // mouse events + d.initmousex = e.clientX; + d.initmousey = e.clientY; + } + d.initx=parseInt(t.offsetLeft) //store offset x of window div onmousedown + d.inity=parseInt(t.offsetTop) + d.width=parseInt(t.offsetWidth) //store width of window div + d.contentheight=parseInt(t.contentarea.offsetHeight) //store height of window div's content div + if (t.contentarea.datatype=="iframe"){ //if content of this window div is "iframe" + t.style.backgroundColor="#F8F8F8" //colorize and hide content div (while window is being dragged) + t.contentarea.style.visibility="hidden" + } + document.onmousemove=d.getdistance //get distance travelled by mouse as it moves + document.ontouchmove=d.getdistance //get distance travelled by mouse as it moves + document.onmouseup=function(){ + if (t.contentarea.datatype=="iframe"){ //restore color and visibility of content div onmouseup + t.contentarea.style.backgroundColor="white" + t.contentarea.style.visibility="visible" + } + d.stop() + } + document.ontouchend=function(){ + if (t.contentarea.datatype=="iframe"){ //restore color and visibility of content div onmouseup + t.contentarea.style.backgroundColor="white" + t.contentarea.style.visibility="visible" + } + d.stop() + } + return false +}, + +getdistance:function(e){ + var d=dhtmlwindow + var etarget=d.etarget + var e=window.event || e + // d.distancex=e.clientX-d.initmousex //horizontal distance travelled relative to starting point + // d.distancey=e.clientY-d.initmousey + if( e.touches && e.touches.length ){ + d.distancex=e.touches[0].clientX-d.initmousex //horizontal distance travelled relative to starting point + d.distancey=e.touches[0].clientY-d.initmousey + } else { + // mouse events + d.distancex=e.clientX-d.initmousex //horizontal distance travelled relative to starting point + d.distancey=e.clientY-d.initmousey + } + if (etarget.className=="drag-handle") //if target element is "handle" div + d.move(etarget._parent, e) + else if (etarget.className=="drag-resizearea") //if target element is "resize" div + d.resize(etarget._parent, e) + return false //cancel default dragging behavior +}, + +getviewpoint:function(){ //get window viewpoint numbers + var ie=document.all && !window.opera + var domclientWidth=document.documentElement && parseInt(document.documentElement.clientWidth) || 100000 //Preliminary doc width in non IE browsers + this.standardbody=(document.compatMode=="CSS1Compat")? document.documentElement : document.body //create reference to common "body" across doctypes + this.scroll_top=(ie)? this.standardbody.scrollTop : window.pageYOffset + this.scroll_left=(ie)? this.standardbody.scrollLeft : window.pageXOffset + this.docwidth=(ie)? this.standardbody.clientWidth : (/Safari/i.test(navigator.userAgent))? window.innerWidth : Math.min(domclientWidth, window.innerWidth-16) + this.docheight=(ie)? this.standardbody.clientHeight: window.innerHeight +}, + +rememberattrs:function(t){ //remember certain attributes of the window when it's minimized or closed, such as dimensions, position on page + this.getviewpoint() //Get current window viewpoint numbers + t.lastx=parseInt((t.style.left || t.offsetLeft))-dhtmlwindow.scroll_left //store last known x coord of window just before minimizing + t.lasty=parseInt((t.style.top || t.offsetTop))-dhtmlwindow.scroll_top + t.lastwidth=parseInt(t.style.width) //store last known width of window just before minimizing/ closing +}, + +move:function(t, e){ + t.style.left=dhtmlwindow.distancex+dhtmlwindow.initx+"px" + t.style.top=dhtmlwindow.distancey+dhtmlwindow.inity+"px" +}, + +resize:function(t, e){ + t.style.width=Math.max(dhtmlwindow.width+dhtmlwindow.distancex, 150)+"px" + t.contentarea.style.height=Math.max(dhtmlwindow.contentheight+dhtmlwindow.distancey, 100)+"px" +}, + +enablecontrols:function(e){ + var d=dhtmlwindow + var sourceobj=window.event? window.event.srcElement : e.target //Get element within "handle" div mouse is currently on (the controls) + if (/Minimize/i.test(sourceobj.getAttribute("title"))) //if this is the "minimize" control + d.minimize(sourceobj, this._parent) + else if (/Restore/i.test(sourceobj.getAttribute("title"))) //if this is the "restore" control + d.restore(sourceobj, this._parent) + else if (/Close/i.test(sourceobj.getAttribute("title"))) //if this is the "close" control + d.close(this._parent) + return false +}, + +minimize:function(button, t){ + dhtmlwindow.rememberattrs(t) + button.setAttribute("src", dhtmlwindow.imagefiles[2]) + button.setAttribute("title", "Restore") + t.state="minimized" //indicate the state of the window as being "minimized" + t.contentarea.style.display="none" + t.statusarea.style.display="none" + if (typeof t.minimizeorder=="undefined"){ //stack order of minmized window on screen relative to any other minimized windows + dhtmlwindow.minimizeorder++ //increment order + t.minimizeorder=dhtmlwindow.minimizeorder + } + t.style.left="10px" //left coord of minmized window + t.style.width="200px" + var windowspacing=t.minimizeorder*10 //spacing (gap) between each minmized window(s) + t.style.top=dhtmlwindow.scroll_top+dhtmlwindow.docheight-(t.handle.offsetHeight*t.minimizeorder)-windowspacing+"px" +}, + +restore:function(button, t){ + dhtmlwindow.getviewpoint() + button.setAttribute("src", dhtmlwindow.imagefiles[0]) + button.setAttribute("title", "Minimize") + t.state="fullview" //indicate the state of the window as being "fullview" + t.style.display="block" + t.contentarea.style.display="block" + if (t.resizeBool) //if this window is resizable, enable the resize icon + t.statusarea.style.display="block" + t.style.left=parseInt(t.lastx)+dhtmlwindow.scroll_left+"px" //position window to last known x coord just before minimizing + t.style.top=parseInt(t.lasty)+dhtmlwindow.scroll_top+"px" + t.style.width=parseInt(t.lastwidth)+"px" +}, + + +close:function(t){ + try{ + var closewinbol=t.onclose() + } + catch(err){ //In non IE browsers, all errors are caught, so just run the below + var closewinbol=true + } + finally{ //In IE, not all errors are caught, so check if variable isn't defined in IE in those cases + if (typeof closewinbol=="undefined"){ + alert("An error has occured somwhere inside your \"onclose\" event handler") + var closewinbol=true + } + } + if (closewinbol){ //if custom event handler function returns true + if (t.state!="minimized") //if this window isn't currently minimized + dhtmlwindow.rememberattrs(t) //remember window's dimensions/position on the page before closing + if (window.frames["_iframe-"+t.id]) //if this is an IFRAME DHTML window + window.frames["_iframe-"+t.id].location.replace("about:blank") + else + t.contentarea.innerHTML="" + t.style.display="none" + t.isClosed=true //tell script this window is closed (for detection in t.show()) + } + return closewinbol +}, + + +setopacity:function(targetobject, value){ //Sets the opacity of targetobject based on the passed in value setting (0 to 1 and in between) + if (!targetobject) + return + if (targetobject.filters && targetobject.filters[0]){ //IE syntax + if (typeof targetobject.filters[0].opacity=="number") //IE6 + targetobject.filters[0].opacity=value*100 + else //IE 5.5 + targetobject.style.filter="alpha(opacity="+value*100+")" + } + else if (typeof targetobject.style.MozOpacity!="undefined") //Old Mozilla syntax + targetobject.style.MozOpacity=value + else if (typeof targetobject.style.opacity!="undefined") //Standard opacity syntax + targetobject.style.opacity=value +}, + +setfocus:function(t){ //Sets focus to the currently active window + this.zIndexvalue++ + t.style.zIndex=this.zIndexvalue + t.isClosed=false //tell script this window isn't closed (for detection in t.show()) + this.setopacity(this.lastactivet.handle, 0.5) //unfocus last active window + this.setopacity(t.handle, 1) //focus currently active window + this.lastactivet=t //remember last active window +}, + + +show:function(t){ + if (t.isClosed){ + alert("DHTML Window has been closed, so nothing to show. Open/Create the window again.") + return + } + if (t.lastx) //If there exists previously stored information such as last x position on window attributes (meaning it's been minimized or closed) + dhtmlwindow.restore(t.controls.firstChild, t) //restore the window using that info + else + t.style.display="block" + this.setfocus(t) + t.state="fullview" //indicate the state of the window as being "fullview" +}, + +hide:function(t){ + t.style.display="none" +}, + +ajax_connect:function(url, t){ + var page_request = false + var bustcacheparameter="" + if (window.XMLHttpRequest) // if Mozilla, IE7, Safari etc + page_request = new XMLHttpRequest() + else if (window.ActiveXObject){ // if IE6 or below + try { + page_request = new ActiveXObject("Msxml2.XMLHTTP") + } + catch (e){ + try{ + page_request = new ActiveXObject("Microsoft.XMLHTTP") + } + catch (e){} + } + } + else + return false + t.contentarea.innerHTML=this.ajaxloadinghtml + page_request.onreadystatechange=function(){dhtmlwindow.ajax_loadpage(page_request, t)} + if (this.ajaxbustcache) //if bust caching of external page + bustcacheparameter=(url.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime() + page_request.open('GET', url+bustcacheparameter, true) + page_request.send(null) +}, + +ajax_loadpage:function(page_request, t){ + if (page_request.readyState == 4 && (page_request.status==200 || window.location.href.indexOf("http")==-1)){ + t.contentarea.innerHTML=page_request.responseText + } +}, + + +stop:function(){ + dhtmlwindow.etarget=null //clean up + document.onmousemove=null + document.ontouchmove=null + document.onmouseup=null + document.ontouchend=null +}, + +addEvent:function(target, functionref, tasktype){ //assign a function to execute to an event handler (ie: onunload) + var tasktype=(window.addEventListener)? tasktype : "on"+tasktype + if (target.addEventListener) + target.addEventListener(tasktype, functionref, false) + else if (target.attachEvent) + target.attachEvent(tasktype, functionref) +}, + +cleanup:function(){ + for (var i=0; i.') //container that holds all dhtml window divs on page +window.onunload=dhtmlwindow.cleanup diff --git a/js/dhtmlwindow.js-rev1 b/js/dhtmlwindow.js-rev1 new file mode 100644 index 00000000..2c45fbc2 --- /dev/null +++ b/js/dhtmlwindow.js-rev1 @@ -0,0 +1,412 @@ +// ------------------------------------------------------------------- +// DHTML Window Widget- By Dynamic Drive, available at: http://www.dynamicdrive.com +// v1.0: Script created Feb 15th, 07' +// v1.01: Feb 21th, 07' (see changelog.txt) +// v1.02: March 26th, 07' (see changelog.txt) +// v1.03: May 5th, 07' (see changelog.txt) +// v1.1: Oct 29th, 07' (see changelog.txt) +// ------------------------------------------------------------------- + +var dhtmlwindow={ +imagefiles:['windowfiles/min.gif', 'windowfiles/close.gif', 'windowfiles/restore.gif', 'windowfiles/resize.gif'], //Path to 4 images used by script, in that order +ajaxbustcache: true, //Bust caching when fetching a file via Ajax? +ajaxloadinghtml: 'Loading Page. Please wait...', //HTML to show while window fetches Ajax Content? + +minimizeorder: 0, +zIndexvalue:100, +tobjects: [], //object to contain references to dhtml window divs, for cleanup purposes +lastactivet: {}, //reference to last active DHTML window + +init:function(t){ + var domwindow=document.createElement("div") //create dhtml window div + domwindow.id=t + domwindow.className="dhtmlwindow" + var domwindowdata='' + domwindowdata='
    ' + domwindowdata+='DHTML Window
    ' + domwindowdata+='
    ' + domwindowdata+='
    ' + domwindowdata+='
     
    ' + domwindowdata+='' + domwindow.innerHTML=domwindowdata + document.getElementById("dhtmlwindowholder").appendChild(domwindow) + //this.zIndexvalue=(this.zIndexvalue)? this.zIndexvalue+1 : 100 //z-index value for DHTML window: starts at 0, increments whenever a window has focus + var t=document.getElementById(t) + var divs=t.getElementsByTagName("div") + for (var i=0; i' + window.frames["_iframe-"+t.id].location.replace(contentsource) //set location of iframe window to specified URL + } + else if (contenttype=="ajax"){ + this.ajax_connect(contentsource, t) //populate window with external contents fetched via Ajax + } + t.contentarea.datatype=contenttype //store contenttype of current window for future reference +}, + +setupdrag:function(e){ + var d=dhtmlwindow //reference dhtml window object + var t=this._parent //reference dhtml window div + d.etarget=this //remember div mouse is currently held down on ("handle" or "resize" div) + var e=window.event || e + // d.initmousex=e.clientX //store x position of mouse onmousedown + // d.initmousey=e.clientY + if( e.touches && e.touches.length ){ + d.initmousex = e.touches[0].clientX; + d.initmousey = e.touches[0].clientY; + } else { + // mouse events + d.initmousex = e.clientX; + d.initmousey = e.clientY; + } + d.initx=parseInt(t.offsetLeft) //store offset x of window div onmousedown + d.inity=parseInt(t.offsetTop) + d.width=parseInt(t.offsetWidth) //store width of window div + d.contentheight=parseInt(t.contentarea.offsetHeight) //store height of window div's content div + if (t.contentarea.datatype=="iframe"){ //if content of this window div is "iframe" + t.style.backgroundColor="#F8F8F8" //colorize and hide content div (while window is being dragged) + t.contentarea.style.visibility="hidden" + } + document.onmousemove=d.getdistance //get distance travelled by mouse as it moves + document.ontouchmove=d.getdistance //get distance travelled by mouse as it moves + document.onmouseup=function(){ + if (t.contentarea.datatype=="iframe"){ //restore color and visibility of content div onmouseup + t.contentarea.style.backgroundColor="white" + t.contentarea.style.visibility="visible" + } + d.stop() + } + document.ontouchend=function(){ + if (t.contentarea.datatype=="iframe"){ //restore color and visibility of content div onmouseup + t.contentarea.style.backgroundColor="white" + t.contentarea.style.visibility="visible" + } + d.stop() + } + return false +}, + +getdistance:function(e){ + var d=dhtmlwindow + var etarget=d.etarget + var e=window.event || e + // d.distancex=e.clientX-d.initmousex //horizontal distance travelled relative to starting point + // d.distancey=e.clientY-d.initmousey + if( e.touches && e.touches.length ){ + d.distancex=e.touches[0].clientX-d.initmousex //horizontal distance travelled relative to starting point + d.distancey=e.touches[0].clienty-d.initmousey + } else { + // mouse events + d.distancex=e.clientX-d.initmousex //horizontal distance travelled relative to starting point + d.distancey=e.clientY-d.initmousey + } + if (etarget.className=="drag-handle") //if target element is "handle" div + d.move(etarget._parent, e) + else if (etarget.className=="drag-resizearea") //if target element is "resize" div + d.resize(etarget._parent, e) + return false //cancel default dragging behavior +}, + +getviewpoint:function(){ //get window viewpoint numbers + var ie=document.all && !window.opera + var domclientWidth=document.documentElement && parseInt(document.documentElement.clientWidth) || 100000 //Preliminary doc width in non IE browsers + this.standardbody=(document.compatMode=="CSS1Compat")? document.documentElement : document.body //create reference to common "body" across doctypes + this.scroll_top=(ie)? this.standardbody.scrollTop : window.pageYOffset + this.scroll_left=(ie)? this.standardbody.scrollLeft : window.pageXOffset + this.docwidth=(ie)? this.standardbody.clientWidth : (/Safari/i.test(navigator.userAgent))? window.innerWidth : Math.min(domclientWidth, window.innerWidth-16) + this.docheight=(ie)? this.standardbody.clientHeight: window.innerHeight +}, + +rememberattrs:function(t){ //remember certain attributes of the window when it's minimized or closed, such as dimensions, position on page + this.getviewpoint() //Get current window viewpoint numbers + t.lastx=parseInt((t.style.left || t.offsetLeft))-dhtmlwindow.scroll_left //store last known x coord of window just before minimizing + t.lasty=parseInt((t.style.top || t.offsetTop))-dhtmlwindow.scroll_top + t.lastwidth=parseInt(t.style.width) //store last known width of window just before minimizing/ closing +}, + +move:function(t, e){ + t.style.left=dhtmlwindow.distancex+dhtmlwindow.initx+"px" + t.style.top=dhtmlwindow.distancey+dhtmlwindow.inity+"px" +}, + +resize:function(t, e){ + t.style.width=Math.max(dhtmlwindow.width+dhtmlwindow.distancex, 150)+"px" + t.contentarea.style.height=Math.max(dhtmlwindow.contentheight+dhtmlwindow.distancey, 100)+"px" +}, + +enablecontrols:function(e){ + var d=dhtmlwindow + var sourceobj=window.event? window.event.srcElement : e.target //Get element within "handle" div mouse is currently on (the controls) + if (/Minimize/i.test(sourceobj.getAttribute("title"))) //if this is the "minimize" control + d.minimize(sourceobj, this._parent) + else if (/Restore/i.test(sourceobj.getAttribute("title"))) //if this is the "restore" control + d.restore(sourceobj, this._parent) + else if (/Close/i.test(sourceobj.getAttribute("title"))) //if this is the "close" control + d.close(this._parent) + return false +}, + +minimize:function(button, t){ + dhtmlwindow.rememberattrs(t) + button.setAttribute("src", dhtmlwindow.imagefiles[2]) + button.setAttribute("title", "Restore") + t.state="minimized" //indicate the state of the window as being "minimized" + t.contentarea.style.display="none" + t.statusarea.style.display="none" + if (typeof t.minimizeorder=="undefined"){ //stack order of minmized window on screen relative to any other minimized windows + dhtmlwindow.minimizeorder++ //increment order + t.minimizeorder=dhtmlwindow.minimizeorder + } + t.style.left="10px" //left coord of minmized window + t.style.width="200px" + var windowspacing=t.minimizeorder*10 //spacing (gap) between each minmized window(s) + t.style.top=dhtmlwindow.scroll_top+dhtmlwindow.docheight-(t.handle.offsetHeight*t.minimizeorder)-windowspacing+"px" +}, + +restore:function(button, t){ + dhtmlwindow.getviewpoint() + button.setAttribute("src", dhtmlwindow.imagefiles[0]) + button.setAttribute("title", "Minimize") + t.state="fullview" //indicate the state of the window as being "fullview" + t.style.display="block" + t.contentarea.style.display="block" + if (t.resizeBool) //if this window is resizable, enable the resize icon + t.statusarea.style.display="block" + t.style.left=parseInt(t.lastx)+dhtmlwindow.scroll_left+"px" //position window to last known x coord just before minimizing + t.style.top=parseInt(t.lasty)+dhtmlwindow.scroll_top+"px" + t.style.width=parseInt(t.lastwidth)+"px" +}, + + +close:function(t){ + try{ + var closewinbol=t.onclose() + } + catch(err){ //In non IE browsers, all errors are caught, so just run the below + var closewinbol=true + } + finally{ //In IE, not all errors are caught, so check if variable isn't defined in IE in those cases + if (typeof closewinbol=="undefined"){ + alert("An error has occured somwhere inside your \"onclose\" event handler") + var closewinbol=true + } + } + if (closewinbol){ //if custom event handler function returns true + if (t.state!="minimized") //if this window isn't currently minimized + dhtmlwindow.rememberattrs(t) //remember window's dimensions/position on the page before closing + if (window.frames["_iframe-"+t.id]) //if this is an IFRAME DHTML window + window.frames["_iframe-"+t.id].location.replace("about:blank") + else + t.contentarea.innerHTML="" + t.style.display="none" + t.isClosed=true //tell script this window is closed (for detection in t.show()) + } + return closewinbol +}, + + +setopacity:function(targetobject, value){ //Sets the opacity of targetobject based on the passed in value setting (0 to 1 and in between) + if (!targetobject) + return + if (targetobject.filters && targetobject.filters[0]){ //IE syntax + if (typeof targetobject.filters[0].opacity=="number") //IE6 + targetobject.filters[0].opacity=value*100 + else //IE 5.5 + targetobject.style.filter="alpha(opacity="+value*100+")" + } + else if (typeof targetobject.style.MozOpacity!="undefined") //Old Mozilla syntax + targetobject.style.MozOpacity=value + else if (typeof targetobject.style.opacity!="undefined") //Standard opacity syntax + targetobject.style.opacity=value +}, + +setfocus:function(t){ //Sets focus to the currently active window + this.zIndexvalue++ + t.style.zIndex=this.zIndexvalue + t.isClosed=false //tell script this window isn't closed (for detection in t.show()) + this.setopacity(this.lastactivet.handle, 0.5) //unfocus last active window + this.setopacity(t.handle, 1) //focus currently active window + this.lastactivet=t //remember last active window +}, + + +show:function(t){ + if (t.isClosed){ + alert("DHTML Window has been closed, so nothing to show. Open/Create the window again.") + return + } + if (t.lastx) //If there exists previously stored information such as last x position on window attributes (meaning it's been minimized or closed) + dhtmlwindow.restore(t.controls.firstChild, t) //restore the window using that info + else + t.style.display="block" + this.setfocus(t) + t.state="fullview" //indicate the state of the window as being "fullview" +}, + +hide:function(t){ + t.style.display="none" +}, + +ajax_connect:function(url, t){ + var page_request = false + var bustcacheparameter="" + if (window.XMLHttpRequest) // if Mozilla, IE7, Safari etc + page_request = new XMLHttpRequest() + else if (window.ActiveXObject){ // if IE6 or below + try { + page_request = new ActiveXObject("Msxml2.XMLHTTP") + } + catch (e){ + try{ + page_request = new ActiveXObject("Microsoft.XMLHTTP") + } + catch (e){} + } + } + else + return false + t.contentarea.innerHTML=this.ajaxloadinghtml + page_request.onreadystatechange=function(){dhtmlwindow.ajax_loadpage(page_request, t)} + if (this.ajaxbustcache) //if bust caching of external page + bustcacheparameter=(url.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime() + page_request.open('GET', url+bustcacheparameter, true) + page_request.send(null) +}, + +ajax_loadpage:function(page_request, t){ + if (page_request.readyState == 4 && (page_request.status==200 || window.location.href.indexOf("http")==-1)){ + t.contentarea.innerHTML=page_request.responseText + } +}, + + +stop:function(){ + dhtmlwindow.etarget=null //clean up + document.onmousemove=null + document.ontouchmove=null + document.onmouseup=null + document.ontouchend=null +}, + +addEvent:function(target, functionref, tasktype){ //assign a function to execute to an event handler (ie: onunload) + var tasktype=(window.addEventListener)? tasktype : "on"+tasktype + if (target.addEventListener) + target.addEventListener(tasktype, functionref, false) + else if (target.attachEvent) + target.attachEvent(tasktype, functionref) +}, + +cleanup:function(){ + for (var i=0; i.') //container that holds all dhtml window divs on page +window.onunload=dhtmlwindow.cleanup diff --git a/js/dhtmlwindow.min.js b/js/dhtmlwindow.min.js new file mode 100644 index 00000000..87c55ac4 --- /dev/null +++ b/js/dhtmlwindow.min.js @@ -0,0 +1,20 @@ +var dhtmlwindow={imagefiles:["windowfiles/min.gif","windowfiles/close.gif","windowfiles/restore.gif","windowfiles/resize.gif"],ajaxbustcache:!0,ajaxloadinghtml:"Loading Page. Please wait...",minimizeorder:0,zIndexvalue:100,tobjects:[],lastactivet:{},init:function(a){var b=document.createElement("div");b.id=a;b.className="dhtmlwindow";var c="",c='
    '+('DHTML Window
    '),c=c+'
    ',c=c+('
     
    '),c=c+"";b.innerHTML=c;document.getElementById("dhtmlwindowholder").appendChild(b);a=document.getElementById(a);b=a.getElementsByTagName("div");for(c=0;c';window.frames["_iframe-"+ +a.id].location.replace(c)}else"ajax"==b&&this.ajax_connect(c,a);a.contentarea.datatype=b}},setupdrag:function(a){var b=dhtmlwindow,c=this._parent;b.etarget=this;a=window.event||a;a.touches&&a.touches.length?(b.initmousex=a.touches[0].clientX,b.initmousey=a.touches[0].clientY):(b.initmousex=a.clientX,b.initmousey=a.clientY);b.initx=parseInt(c.offsetLeft);b.inity=parseInt(c.offsetTop);b.width=parseInt(c.offsetWidth);b.contentheight=parseInt(c.contentarea.offsetHeight);"iframe"==c.contentarea.datatype&& +(c.style.backgroundColor="#F8F8F8",c.contentarea.style.visibility="hidden");document.onmousemove=b.getdistance;document.ontouchmove=b.getdistance;document.onmouseup=function(){"iframe"==c.contentarea.datatype&&(c.contentarea.style.backgroundColor="white",c.contentarea.style.visibility="visible");b.stop()};document.ontouchend=function(){"iframe"==c.contentarea.datatype&&(c.contentarea.style.backgroundColor="white",c.contentarea.style.visibility="visible");b.stop()};return!1},getdistance:function(a){var b= +dhtmlwindow,c=b.etarget;a=window.event||a;a.touches&&a.touches.length?(b.distancex=a.touches[0].clientX-b.initmousex,b.distancey=a.touches[0].clientY-b.initmousey):(b.distancex=a.clientX-b.initmousex,b.distancey=a.clientY-b.initmousey);"drag-handle"==c.className?b.move(c._parent,a):"drag-resizearea"==c.className&&b.resize(c._parent,a);return!1},getviewpoint:function(){var a=document.all&&!window.opera,b=document.documentElement&&parseInt(document.documentElement.clientWidth)||1E5;this.standardbody= +"CSS1Compat"==document.compatMode?document.documentElement:document.body;this.scroll_top=a?this.standardbody.scrollTop:window.pageYOffset;this.scroll_left=a?this.standardbody.scrollLeft:window.pageXOffset;this.docwidth=a?this.standardbody.clientWidth:/Safari/i.test(navigator.userAgent)?window.innerWidth:Math.min(b,window.innerWidth-16);this.docheight=a?this.standardbody.clientHeight:window.innerHeight},rememberattrs:function(a){this.getviewpoint();a.lastx=parseInt(a.style.left||a.offsetLeft)-dhtmlwindow.scroll_left; +a.lasty=parseInt(a.style.top||a.offsetTop)-dhtmlwindow.scroll_top;a.lastwidth=parseInt(a.style.width)},move:function(a){a.style.left=dhtmlwindow.distancex+dhtmlwindow.initx+"px";a.style.top=dhtmlwindow.distancey+dhtmlwindow.inity+"px"},resize:function(a){a.style.width=Math.max(dhtmlwindow.width+dhtmlwindow.distancex,150)+"px";a.contentarea.style.height=Math.max(dhtmlwindow.contentheight+dhtmlwindow.distancey,100)+"px"},enablecontrols:function(a){var b=dhtmlwindow;a=window.event?window.event.srcElement: +a.target;/Minimize/i.test(a.getAttribute("title"))?b.minimize(a,this._parent):/Restore/i.test(a.getAttribute("title"))?b.restore(a,this._parent):/Close/i.test(a.getAttribute("title"))&&b.close(this._parent);return!1},minimize:function(a,b){dhtmlwindow.rememberattrs(b);a.setAttribute("src",dhtmlwindow.imagefiles[2]);a.setAttribute("title","Restore");b.state="minimized";b.contentarea.style.display="none";b.statusarea.style.display="none";"undefined"==typeof b.minimizeorder&&(dhtmlwindow.minimizeorder++, +b.minimizeorder=dhtmlwindow.minimizeorder);b.style.left="10px";b.style.width="200px";b.style.top=dhtmlwindow.scroll_top+dhtmlwindow.docheight-b.handle.offsetHeight*b.minimizeorder-10*b.minimizeorder+"px"},restore:function(a,b){dhtmlwindow.getviewpoint();a.setAttribute("src",dhtmlwindow.imagefiles[0]);a.setAttribute("title","Minimize");b.state="fullview";b.style.display="block";b.contentarea.style.display="block";b.resizeBool&&(b.statusarea.style.display="block");b.style.left=parseInt(b.lastx)+dhtmlwindow.scroll_left+ +"px";b.style.top=parseInt(b.lasty)+dhtmlwindow.scroll_top+"px";b.style.width=parseInt(b.lastwidth)+"px"},close:function(a){try{var b=a.onclose()}catch(c){b=!0}finally{"undefined"==typeof b&&(alert('An error has occured somwhere inside your "onclose" event handler'),b=!0)}b&&("minimized"!=a.state&&dhtmlwindow.rememberattrs(a),window.frames["_iframe-"+a.id]?window.frames["_iframe-"+a.id].location.replace("about:blank"):a.contentarea.innerHTML="",a.style.display="none",a.isClosed=!0);return b},setopacity:function(a, +b){a&&(a.filters&&a.filters[0]?"number"==typeof a.filters[0].opacity?a.filters[0].opacity=100*b:a.style.filter="alpha(opacity="+100*b+")":"undefined"!=typeof a.style.MozOpacity?a.style.MozOpacity=b:"undefined"!=typeof a.style.opacity&&(a.style.opacity=b))},setfocus:function(a){this.zIndexvalue++;a.style.zIndex=this.zIndexvalue;a.isClosed=!1;this.setopacity(this.lastactivet.handle,0.5);this.setopacity(a.handle,1);this.lastactivet=a},show:function(a){a.isClosed?alert("DHTML Window has been closed, so nothing to show. Open/Create the window again."): +(a.lastx?dhtmlwindow.restore(a.controls.firstChild,a):a.style.display="block",this.setfocus(a),a.state="fullview")},hide:function(a){a.style.display="none"},ajax_connect:function(a,b){var c=!1,e="";if(window.XMLHttpRequest)c=new XMLHttpRequest;else if(window.ActiveXObject)try{c=new ActiveXObject("Msxml2.XMLHTTP")}catch(j){try{c=new ActiveXObject("Microsoft.XMLHTTP")}catch(f){}}else return!1;b.contentarea.innerHTML=this.ajaxloadinghtml;c.onreadystatechange=function(){dhtmlwindow.ajax_loadpage(c,b)}; +this.ajaxbustcache&&(e=-1!=a.indexOf("?")?"&"+(new Date).getTime():"?"+(new Date).getTime());c.open("GET",a+e,!0);c.send(null)},ajax_loadpage:function(a,b){if(4==a.readyState&&(200==a.status||-1==window.location.href.indexOf("http")))b.contentarea.innerHTML=a.responseText},stop:function(){dhtmlwindow.etarget=null;document.onmousemove=null;document.ontouchmove=null;document.onmouseup=null;document.ontouchend=null},addEvent:function(a,b,c){c=window.addEventListener?c:"on"+c;a.addEventListener?a.addEventListener(c, +b,!1):a.attachEvent&&a.attachEvent(c,b)},cleanup:function(){for(var a=0;a"); + + fabric.window = fabric.document.createWindow(); +} + +/** + * True when in environment that supports touch events + * @type boolean + */ +fabric.isTouchSupported = "ontouchstart" in fabric.document.documentElement; + +/** + * True when in environment that's probably Node.js + * @type boolean + */ +fabric.isLikelyNode = typeof Buffer !== 'undefined' && + typeof window === 'undefined'; + + +/** + * Attributes parsed from all SVG elements + * @type array + */ +fabric.SHARED_ATTRIBUTES = [ + "transform", + "fill", "fill-opacity", "fill-rule", + "opacity", + "stroke", "stroke-dasharray", "stroke-linecap", + "stroke-linejoin", "stroke-miterlimit", + "stroke-opacity", "stroke-width" +]; +/*! + * Copyright (c) 2009 Simo Kinnunen. + * Licensed under the MIT license. + */ + +var Cufon = (function() { + + /** @ignore */ + var api = function() { + return api.replace.apply(null, arguments); + }; + + /** @ignore */ + var DOM = api.DOM = { + + ready: (function() { + + var complete = false, readyStatus = { loaded: 1, complete: 1 }; + + var queue = [], /** @ignore */ perform = function() { + if (complete) return; + complete = true; + for (var fn; fn = queue.shift(); fn()); + }; + + // Gecko, Opera, WebKit r26101+ + + if (fabric.document.addEventListener) { + fabric.document.addEventListener('DOMContentLoaded', perform, false); + fabric.window.addEventListener('pageshow', perform, false); // For cached Gecko pages + } + + // Old WebKit, Internet Explorer + + if (!fabric.window.opera && fabric.document.readyState) (function() { + readyStatus[fabric.document.readyState] ? perform() : setTimeout(arguments.callee, 10); + })(); + + // Internet Explorer + + if (fabric.document.readyState && fabric.document.createStyleSheet) (function() { + try { + fabric.document.body.doScroll('left'); + perform(); + } + catch (e) { + setTimeout(arguments.callee, 1); + } + })(); + + addEvent(fabric.window, 'load', perform); // Fallback + + return function(listener) { + if (!arguments.length) perform(); + else complete ? listener() : queue.push(listener); + }; + + })() + + }; + + /** @ignore */ + var CSS = api.CSS = /** @ignore */ { + + /** @ignore */ + Size: function(value, base) { + + this.value = parseFloat(value); + this.unit = String(value).match(/[a-z%]*$/)[0] || 'px'; + + /** @ignore */ + this.convert = function(value) { + return value / base * this.value; + }; + + /** @ignore */ + this.convertFrom = function(value) { + return value / this.value * base; + }; + + /** @ignore */ + this.toString = function() { + return this.value + this.unit; + }; + + }, + + /** @ignore */ + getStyle: function(el) { + return new Style(el.style); + /* + var view = document.defaultView; + if (view && view.getComputedStyle) return new Style(view.getComputedStyle(el, null)); + if (el.currentStyle) return new Style(el.currentStyle); + return new Style(el.style); + */ + }, + + quotedList: cached(function(value) { + // doesn't work properly with empty quoted strings (""), but + // it's not worth the extra code. + var list = [], re = /\s*((["'])([\s\S]*?[^\\])\2|[^,]+)\s*/g, match; + while (match = re.exec(value)) list.push(match[3] || match[1]); + return list; + }), + + ready: (function() { + + var complete = false; + + var queue = [], perform = function() { + complete = true; + for (var fn; fn = queue.shift(); fn()); + }; + + // Safari 2 does not include '); + + function getFontSizeInPixels(el, value) { + return getSizeInPixels(el, /(?:em|ex|%)$/i.test(value) ? '1em' : value); + } + + // Original by Dead Edwards. + // Combined with getFontSizeInPixels it also works with relative units. + function getSizeInPixels(el, value) { + if (/px$/i.test(value)) return parseFloat(value); + var style = el.style.left, runtimeStyle = el.runtimeStyle.left; + el.runtimeStyle.left = el.currentStyle.left; + el.style.left = value; + var result = el.style.pixelLeft; + el.style.left = style; + el.runtimeStyle.left = runtimeStyle; + return result; + } + + return function(font, text, style, options, node, el, hasNext) { + var redraw = (text === null); + + if (redraw) text = node.alt; + + // @todo word-spacing, text-decoration + + var viewBox = font.viewBox; + + var size = style.computedFontSize || + (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize)); + + var letterSpacing = style.computedLSpacing; + + if (letterSpacing == undefined) { + letterSpacing = style.get('letterSpacing'); + style.computedLSpacing = letterSpacing = + (letterSpacing == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, letterSpacing)); + } + + var wrapper, canvas; + + if (redraw) { + wrapper = node; + canvas = node.firstChild; + } + else { + wrapper = fabric.document.createElement('span'); + wrapper.className = 'cufon cufon-vml'; + wrapper.alt = text; + + canvas = fabric.document.createElement('span'); + canvas.className = 'cufon-vml-canvas'; + wrapper.appendChild(canvas); + + if (options.printable) { + var print = fabric.document.createElement('span'); + print.className = 'cufon-alt'; + print.appendChild(fabric.document.createTextNode(text)); + wrapper.appendChild(print); + } + + // ie6, for some reason, has trouble rendering the last VML element in the document. + // we can work around this by injecting a dummy element where needed. + // @todo find a better solution + if (!hasNext) wrapper.appendChild(fabric.document.createElement('cvml:shape')); + } + + var wStyle = wrapper.style; + var cStyle = canvas.style; + + var height = size.convert(viewBox.height), roundedHeight = Math.ceil(height); + var roundingFactor = roundedHeight / height; + var minX = viewBox.minX, minY = viewBox.minY; + + cStyle.height = roundedHeight; + cStyle.top = Math.round(size.convert(minY - font.ascent)); + cStyle.left = Math.round(size.convert(minX)); + + wStyle.height = size.convert(font.height) + 'px'; + + var textDecoration = Cufon.getTextDecoration(options); + + var color = style.get('color'); + + var chars = Cufon.CSS.textTransform(text, style).split(''); + + var width = 0, offsetX = 0, advance = null; + + var glyph, shape, shadows = options.textShadow; + + // pre-calculate width + for (var i = 0, k = 0, l = chars.length; i < l; ++i) { + glyph = font.glyphs[chars[i]] || font.missingGlyph; + if (glyph) width += advance = ~~(glyph.w || font.w) + letterSpacing; + } + + if (advance === null) return null; + + var fullWidth = -minX + width + (viewBox.width - advance); + + var shapeWidth = size.convert(fullWidth * roundingFactor), roundedShapeWidth = Math.round(shapeWidth); + + var coordSize = fullWidth + ',' + viewBox.height, coordOrigin; + var stretch = 'r' + coordSize + 'nsnf'; + + for (i = 0; i < l; ++i) { + + glyph = font.glyphs[chars[i]] || font.missingGlyph; + if (!glyph) continue; + + if (redraw) { + // some glyphs may be missing so we can't use i + shape = canvas.childNodes[k]; + if (shape.firstChild) shape.removeChild(shape.firstChild); // shadow + } + else { + shape = fabric.document.createElement('cvml:shape'); + canvas.appendChild(shape); + } + + shape.stroked = 'f'; + shape.coordsize = coordSize; + shape.coordorigin = coordOrigin = (minX - offsetX) + ',' + minY; + shape.path = (glyph.d ? 'm' + glyph.d + 'xe' : '') + 'm' + coordOrigin + stretch; + shape.fillcolor = color; + + // it's important to not set top/left or IE8 will grind to a halt + var sStyle = shape.style; + sStyle.width = roundedShapeWidth; + sStyle.height = roundedHeight; + + if (shadows) { + // due to the limitations of the VML shadow element there + // can only be two visible shadows. opacity is shared + // for all shadows. + var shadow1 = shadows[0], shadow2 = shadows[1]; + var color1 = Cufon.CSS.color(shadow1.color), color2; + var shadow = fabric.document.createElement('cvml:shadow'); + shadow.on = 't'; + shadow.color = color1.color; + shadow.offset = shadow1.offX + ',' + shadow1.offY; + if (shadow2) { + color2 = Cufon.CSS.color(shadow2.color); + shadow.type = 'double'; + shadow.color2 = color2.color; + shadow.offset2 = shadow2.offX + ',' + shadow2.offY; + } + shadow.opacity = color1.opacity || (color2 && color2.opacity) || 1; + shape.appendChild(shadow); + } + + offsetX += ~~(glyph.w || font.w) + letterSpacing; + + ++k; + + } + + wStyle.width = Math.max(Math.ceil(size.convert(width * roundingFactor)), 0); + + return wrapper; + + }; + +})()); + +Cufon.getTextDecoration = function(options) { + return { + underline: options.textDecoration === 'underline', + overline: options.textDecoration === 'overline', + 'line-through': options.textDecoration === 'line-through' + }; +}; + +if (typeof exports != 'undefined') { + exports.Cufon = Cufon; +} +/* + json2.js + 2011-10-19 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, regexp: true */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +var JSON; +if (!JSON) { + JSON = {}; +} + +(function () { + 'use strict'; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + /** @ignore */ + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) + ? this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' + : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + /** @ignore */ + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' + ? c + : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 + ? '[]' + : gap + ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' + : '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + if (typeof rep[i] === 'string') { + k = rep[i]; + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 + ? '{}' + : gap + ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' + : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + /** @ignore */ + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + /** @ignore */ + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ + .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') + .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' + ? walk({'': j}, '') + : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}());/* + ---------------------------------------------------- + Event.js : 1.1.3 : 2013/07/17 : MIT License + ---------------------------------------------------- + https://github.com/mudcube/Event.js + ---------------------------------------------------- + https://github.com/rykerwilliams/Event.js + ---------------------------------------------------- + 1 : click, dblclick, dbltap + 1+ : tap, longpress, drag, swipe + 2+ : pinch, rotate + : mousewheel, devicemotion, shake + ---------------------------------------------------- + Ideas for the future + ---------------------------------------------------- + * GamePad, and other input abstractions. + * Event batching - i.e. for every x fingers down a new gesture is created. + ---------------------------------------------------- + http://www.w3.org/TR/2011/WD-touch-events-20110505/ + ---------------------------------------------------- + +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(eventjs) === "undefined") var eventjs = Event; + +(function(root) { "use strict"; + +// Add custom *EventListener commands to HTMLElements (set false to prevent funkiness). +root.modifyEventListener = true; + +// Add bulk *EventListener commands on NodeLists from querySelectorAll and others (set false to prevent funkiness). +root.modifySelectors = true; + +// Event maintenance. +root.add = function(target, type, listener, configure) { + return eventManager(target, type, listener, configure, "add"); +}; + +root.remove = function(target, type, listener, configure) { + return eventManager(target, type, listener, configure, "remove"); +}; + +root.stop = function(event) { + if (!event) return; + if (event.stopPropagation) event.stopPropagation(); + event.cancelBubble = true; // <= IE8 + event.bubble = 0; +}; + +root.prevent = function(event) { + if (!event) return; + if (event.preventDefault) event.preventDefault(); + if (event.preventManipulation) event.preventManipulation(); // MS + event.returnValue = false; // <= IE8 +}; + +root.cancel = function(event) { + root.stop(event); + root.prevent(event); +}; + +// Check whether event is natively supported (via @kangax) +root.getEventSupport = function (target, type) { + if (typeof(target) === "string") { + type = target; + target = window; + } + type = "on" + type; + if (type in target) return true; + if (!target.setAttribute) target = document.createElement("div"); + if (target.setAttribute && target.removeAttribute) { + target.setAttribute(type, ""); + var isSupported = typeof target[type] === "function"; + if (typeof target[type] !== "undefined") target[type] = null; + target.removeAttribute(type); + return isSupported; + } +}; + +var clone = function (obj) { + if (!obj || typeof (obj) !== 'object') return obj; + var temp = new obj.constructor(); + for (var key in obj) { + if (!obj[key] || typeof (obj[key]) !== 'object') { + temp[key] = obj[key]; + } else { // clone sub-object + temp[key] = clone(obj[key]); + } + } + return temp; +}; + +/// Handle custom *EventListener commands. +var eventManager = function(target, type, listener, configure, trigger, fromOverwrite) { + configure = configure || {}; + // Check whether target is a configuration variable; + if (String(target) === "[object Object]") { + var data = target; + target = data.target; + type = data.type; + listener = data.listener; + delete data.target; + delete data.type; + delete data.listener; + for (var key in data) { + configure[key] = data[key]; + } + } + /// + if (!target || !type || !listener) return; + // Check for element to load on interval (before onload). + if (typeof(target) === "string" && type === "ready") { + var time = (new Date()).getTime(); + var timeout = configure.timeout; + var ms = configure.interval || 1000 / 60; + var interval = window.setInterval(function() { + if ((new Date()).getTime() - time > timeout) { + window.clearInterval(interval); + } + if (document.querySelector(target)) { + window.clearInterval(interval); + setTimeout(listener, 1); + } + }, ms); + return; + } + // Get DOM element from Query Selector. + if (typeof(target) === "string") { + target = document.querySelectorAll(target); + if (target.length === 0) return createError("Missing target on listener!", arguments); // No results. + if (target.length === 1) { // Single target. + target = target[0]; + } + } + + /// Handle multiple targets. + var event; + var events = {}; + if (target.length > 0 && target !== window) { + for (var n0 = 0, length0 = target.length; n0 < length0; n0 ++) { + event = eventManager(target[n0], type, listener, clone(configure), trigger); + if (event) events[n0] = event; + } + return createBatchCommands(events); + } + // Check for multiple events in one string. + if (type.indexOf && type.indexOf(" ") !== -1) type = type.split(" "); + if (type.indexOf && type.indexOf(",") !== -1) type = type.split(","); + // Attach or remove multiple events associated with a target. + if (typeof(type) !== "string") { // Has multiple events. + if (typeof(type.length) === "number") { // Handle multiple listeners glued together. + for (var n1 = 0, length1 = type.length; n1 < length1; n1 ++) { // Array [type] + event = eventManager(target, type[n1], listener, clone(configure), trigger); + if (event) events[type[n1]] = event; + } + } else { // Handle multiple listeners. + for (var key in type) { // Object {type} + if (typeof(type[key]) === "function") { // without configuration. + event = eventManager(target, key, type[key], clone(configure), trigger); + } else { // with configuration. + event = eventManager(target, key, type[key].listener, clone(type[key]), trigger); + } + if (event) events[key] = event; + } + } + return createBatchCommands(events); + } + // Ensure listener is a function. + if (typeof(target) !== "object") return createError("Target is not defined!", arguments); + if (typeof(listener) !== "function") return createError("Listener is not a function!", arguments); + // Generate a unique wrapper identifier. + var useCapture = configure.useCapture || false; + var id = getID(target) + "." + getID(listener) + "." + (useCapture ? 1 : 0); + // Handle the event. + if (root.Gesture && root.Gesture._gestureHandlers[type]) { // Fire custom event. + id = type + id; + if (trigger === "remove") { // Remove event listener. + if (!wrappers[id]) return; // Already removed. + wrappers[id].remove(); + delete wrappers[id]; + } else if (trigger === "add") { // Attach event listener. + if (wrappers[id]) { + wrappers[id].add(); + return wrappers[id]; // Already attached. + } + // Retains "this" orientation. + if (configure.useCall && !root.modifyEventListener) { + var tmp = listener; + listener = function(event, self) { + for (var key in self) event[key] = self[key]; + return tmp.call(target, event); + }; + } + // Create listener proxy. + configure.gesture = type; + configure.target = target; + configure.listener = listener; + configure.fromOverwrite = fromOverwrite; + // Record wrapper. + wrappers[id] = root.proxy[type](configure); + } + return wrappers[id]; + } else { // Fire native event. + var eventList = getEventList(type); + for (var n = 0, eventId; n < eventList.length; n ++) { + type = eventList[n]; + eventId = type + "." + id; + if (trigger === "remove") { // Remove event listener. + if (!wrappers[eventId]) continue; // Already removed. + target[remove](type, listener, useCapture); + delete wrappers[eventId]; + } else if (trigger === "add") { // Attach event listener. + if (wrappers[eventId]) return wrappers[eventId]; // Already attached. + target[add](type, listener, useCapture); + // Record wrapper. + wrappers[eventId] = { + id: eventId, + type: type, + target: target, + listener: listener, + remove: function() { + for (var n = 0; n < eventList.length; n ++) { + root.remove(target, eventList[n], listener, configure); + } + } + }; + } + } + return wrappers[eventId]; + } +}; + +/// Perform batch actions on multiple events. +var createBatchCommands = function(events) { + return { + remove: function() { // Remove multiple events. + for (var key in events) { + events[key].remove(); + } + }, + add: function() { // Add multiple events. + for (var key in events) { + events[key].add(); + } + } + }; +}; + +/// Display error message in console. +var createError = function(message, data) { + if (typeof(console) === "undefined") return; + if (typeof(console.error) === "undefined") return; + console.error(message, data); +}; + +/// Handle naming discrepancies between platforms. +var pointerDefs = { + "msPointer": [ "MSPointerDown", "MSPointerMove", "MSPointerUp" ], + "touch": [ "touchstart", "touchmove", "touchend" ], + "mouse": [ "mousedown", "mousemove", "mouseup" ] +}; + +var pointerDetect = { + // MSPointer + "MSPointerDown": 0, + "MSPointerMove": 1, + "MSPointerUp": 2, + // Touch + "touchstart": 0, + "touchmove": 1, + "touchend": 2, + // Mouse + "mousedown": 0, + "mousemove": 1, + "mouseup": 2 +}; + +var getEventSupport = (function() { + root.supports = {}; + if (window.navigator.msPointerEnabled) { + root.supports.msPointer = true; + } + if (root.getEventSupport("touchstart")) { + root.supports.touch = true; + } + if (root.getEventSupport("mousedown")) { + root.supports.mouse = true; + } +})(); + +var getEventList = (function() { + return function(type) { + var prefix = document.addEventListener ? "" : "on"; // IE + var idx = pointerDetect[type]; + if (isFinite(idx)) { + var types = []; + for (var key in root.supports) { + types.push(prefix + pointerDefs[key][idx]); + } + return types; + } else { + return [ prefix + type ]; + } + }; +})(); + +/// Event wrappers to keep track of all events placed in the window. +var wrappers = {}; +var counter = 0; +var getID = function(object) { + if (object === window) return "#window"; + if (object === document) return "#document"; + if (!object.uniqueID) object.uniqueID = "e" + counter ++; + return object.uniqueID; +}; + +/// Detect platforms native *EventListener command. +var add = document.addEventListener ? "addEventListener" : "attachEvent"; +var remove = document.removeEventListener ? "removeEventListener" : "detachEvent"; + +/* + Pointer.js + ------------------------ + Modified from; https://github.com/borismus/pointer.js +*/ + +root.createPointerEvent = function (event, self, preventRecord) { + var eventName = self.gesture; + var target = self.target; + var pts = event.changedTouches || root.proxy.getCoords(event); + if (pts.length) { + var pt = pts[0]; + self.pointers = preventRecord ? [] : pts; + self.pageX = pt.pageX; + self.pageY = pt.pageY; + self.x = self.pageX; + self.y = self.pageY; + } + /// + var newEvent = document.createEvent("Event"); + newEvent.initEvent(eventName, true, true); + newEvent.originalEvent = event; + for (var k in self) { + if (k === "target") continue; + newEvent[k] = self[k]; + } + /// + var type = newEvent.type; + if (root.Gesture && root.Gesture._gestureHandlers[type]) { // capture custom events. +// target.dispatchEvent(newEvent); + self.oldListener.call(target, newEvent, self, false); + } +}; + +/// Allows *EventListener to use custom event proxies. +if (root.modifyEventListener && window.HTMLElement) (function() { + var augmentEventListener = function(proto) { + var recall = function(trigger) { // overwrite native *EventListener's + var handle = trigger + "EventListener"; + var handler = proto[handle]; + proto[handle] = function (type, listener, useCapture) { + if (root.Gesture && root.Gesture._gestureHandlers[type]) { // capture custom events. + var configure = useCapture; + if (typeof(useCapture) === "object") { + configure.useCall = true; + } else { // convert to configuration object. + configure = { + useCall: true, + useCapture: useCapture + }; + } + eventManager(this, type, listener, configure, trigger, true); +// handler.call(this, type, listener, useCapture); + } else { // use native function. + var types = getEventList(type); + for (var n = 0; n < types.length; n ++) { + handler.call(this, types[n], listener, useCapture); + } + } + }; + }; + recall("add"); + recall("remove"); + }; + // NOTE: overwriting HTMLElement doesn't do anything in Firefox. + if (navigator.userAgent.match(/Firefox/)) { + // TODO: fix Firefox for the general case. + augmentEventListener(HTMLDivElement.prototype); + augmentEventListener(HTMLCanvasElement.prototype); + } else { + augmentEventListener(HTMLElement.prototype); + } + augmentEventListener(document); + augmentEventListener(window); +})(); + +/// Allows querySelectorAll and other NodeLists to perform *EventListener commands in bulk. +if (root.modifySelectors) (function() { + var proto = NodeList.prototype; + proto.removeEventListener = function(type, listener, useCapture) { + for (var n = 0, length = this.length; n < length; n ++) { + this[n].removeEventListener(type, listener, useCapture); + } + }; + proto.addEventListener = function(type, listener, useCapture) { + for (var n = 0, length = this.length; n < length; n ++) { + this[n].addEventListener(type, listener, useCapture); + } + }; +})(); + +return root; + +})(Event); +/* + ---------------------------------------------------- + Event.proxy : 0.4.3 : 2013/07/17 : MIT License + ---------------------------------------------------- + https://github.com/mudcube/Event.js + ---------------------------------------------------- +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(Event.proxy) === "undefined") Event.proxy = {}; + +Event.proxy = (function(root) { "use strict"; + +/* + Create a new pointer gesture instance. +*/ + +root.pointerSetup = function(conf, self) { + /// Configure. + conf.doc = conf.target.ownerDocument || conf.target; // Associated document. + conf.minFingers = conf.minFingers || conf.fingers || 1; // Minimum required fingers. + conf.maxFingers = conf.maxFingers || conf.fingers || Infinity; // Maximum allowed fingers. + conf.position = conf.position || "relative"; // Determines what coordinate system points are returned. + delete conf.fingers; //- + /// Convenience data. + self = self || {}; + self.enabled = true; + self.gesture = conf.gesture; + self.target = conf.target; + self.env = conf.env; + /// + if (Event.modifyEventListener && conf.fromOverwrite) { + conf.oldListener = conf.listener; + conf.listener = Event.createPointerEvent; + } + /// Convenience commands. + var fingers = 0; + var type = self.gesture.indexOf("pointer") === 0 && Event.modifyEventListener ? "pointer" : "mouse"; + if (conf.oldListener) self.oldListener = conf.oldListener; + self.listener = conf.listener; + self.proxy = function(listener) { + self.defaultListener = conf.listener; + conf.listener = listener; + listener(conf.event, self); + }; + self.add = function() { + if (self.enabled === true) return; + if (conf.onPointerDown) Event.add(conf.target, type + "down", conf.onPointerDown); + if (conf.onPointerMove) Event.add(conf.doc, type + "move", conf.onPointerMove); + if (conf.onPointerUp) Event.add(conf.doc, type + "up", conf.onPointerUp); + self.enabled = true; + }; + self.remove = function() { + if (self.enabled === false) return; + if (conf.onPointerDown) Event.remove(conf.target, type + "down", conf.onPointerDown); + if (conf.onPointerMove) Event.remove(conf.doc, type + "move", conf.onPointerMove); + if (conf.onPointerUp) Event.remove(conf.doc, type + "up", conf.onPointerUp); + self.reset(); + self.enabled = false; + }; + self.pause = function(opt) { + if (conf.onPointerMove && (!opt || opt.move)) Event.remove(conf.doc, type + "move", conf.onPointerMove); + if (conf.onPointerUp && (!opt || opt.up)) Event.remove(conf.doc, type + "up", conf.onPointerUp); + fingers = conf.fingers; + conf.fingers = 0; + }; + self.resume = function(opt) { + if (conf.onPointerMove && (!opt || opt.move)) Event.add(conf.doc, type + "move", conf.onPointerMove); + if (conf.onPointerUp && (!opt || opt.up)) Event.add(conf.doc, type + "up", conf.onPointerUp); + conf.fingers = fingers; + }; + self.reset = function() { + conf.tracker = {}; + conf.fingers = 0; + }; + /// + return self; +}; + +/* + Begin proxied pointer command. +*/ + +var sp = Event.supports; +Event.pointerType = sp.mouse ? "mouse" : sp.touch ? "touch" : "mspointer"; +root.pointerStart = function(event, self, conf) { + var type = (event.type || "mousedown").toUpperCase(); + if (type.indexOf("MOUSE") === 0) Event.pointerType = "mouse"; + else if (type.indexOf("TOUCH") === 0) Event.pointerType = "touch"; + else if (type.indexOf("MSPOINTER") === 0) Event.pointerType = "mspointer"; + /// + var addTouchStart = function(touch, sid) { + var bbox = conf.bbox; + var pt = track[sid] = {}; + /// + switch(conf.position) { + case "absolute": // Absolute from within window. + pt.offsetX = 0; + pt.offsetY = 0; + break; + case "differenceFromLast": // Since last coordinate recorded. + pt.offsetX = touch.pageX; + pt.offsetY = touch.pageY; + break; + case "difference": // Relative from origin. + pt.offsetX = touch.pageX; + pt.offsetY = touch.pageY; + break; + case "move": // Move target element. + pt.offsetX = touch.pageX - bbox.x1; + pt.offsetY = touch.pageY - bbox.y1; + break; + default: // Relative from within target. + pt.offsetX = bbox.x1; + pt.offsetY = bbox.y1; + break; + } + /// + if (conf.position === "relative") { + var x = (touch.pageX + bbox.scrollLeft - pt.offsetX); + var y = (touch.pageY + bbox.scrollTop - pt.offsetY); + } else { + var x = (touch.pageX - pt.offsetX); + var y = (touch.pageY - pt.offsetY); + } + /// + pt.rotation = 0; + pt.scale = 1; + pt.startTime = pt.moveTime = (new Date()).getTime(); + pt.move = { x: x, y: y }; + pt.start = { x: x, y: y }; + /// + conf.fingers ++; + }; + /// + conf.event = event; + if (self.defaultListener) { + conf.listener = self.defaultListener; + delete self.defaultListener; + } + /// + var isTouchStart = !conf.fingers; + var track = conf.tracker; + var touches = event.changedTouches || root.getCoords(event); + var length = touches.length; + // Adding touch events to tracking. + for (var i = 0; i < length; i ++) { + var touch = touches[i]; + var sid = touch.identifier || Infinity; // Touch ID. + // Track the current state of the touches. + if (conf.fingers) { + if (conf.fingers >= conf.maxFingers) { + var ids = []; + for (var sid in conf.tracker) ids.push(sid); + self.identifier = ids.join(","); + return isTouchStart; + } + var fingers = 0; // Finger ID. + for (var rid in track) { + // Replace removed finger. + if (track[rid].up) { + delete track[rid]; + addTouchStart(touch, sid); + conf.cancel = true; + break; + } + fingers ++; + } + // Add additional finger. + if (track[sid]) continue; + addTouchStart(touch, sid); + } else { // Start tracking fingers. + track = conf.tracker = {}; + self.bbox = conf.bbox = root.getBoundingBox(conf.target); + conf.fingers = 0; + conf.cancel = false; + addTouchStart(touch, sid); + } + } + /// + var ids = []; + for (var sid in conf.tracker) ids.push(sid); + self.identifier = ids.join(","); + /// + return isTouchStart; +}; + +/* + End proxied pointer command. +*/ + +root.pointerEnd = function(event, self, conf, onPointerUp) { + // Record changed touches have ended (iOS changedTouches is not reliable). + var touches = event.touches || []; + var length = touches.length; + var exists = {}; + for (var i = 0; i < length; i ++) { + var touch = touches[i]; + var sid = touch.identifier; + exists[sid || Infinity] = true; + } + for (var sid in conf.tracker) { + var track = conf.tracker[sid]; + if (exists[sid] || track.up) continue; + if (onPointerUp) { // add changedTouches to mouse. + onPointerUp({ + pageX: track.pageX, + pageY: track.pageY, + changedTouches: [{ + pageX: track.pageX, + pageY: track.pageY, + identifier: sid === "Infinity" ? Infinity : sid + }] + }, "up"); + } + track.up = true; + conf.fingers --; + } +/* // This should work but fails in Safari on iOS4 so not using it. + var touches = event.changedTouches || root.getCoords(event); + var length = touches.length; + // Record changed touches have ended (this should work). + for (var i = 0; i < length; i ++) { + var touch = touches[i]; + var sid = touch.identifier || Infinity; + var track = conf.tracker[sid]; + if (track && !track.up) { + if (onPointerUp) { // add changedTouches to mouse. + onPointerUp({ + changedTouches: [{ + pageX: track.pageX, + pageY: track.pageY, + identifier: sid === "Infinity" ? Infinity : sid + }] + }, "up"); + } + track.up = true; + conf.fingers --; + } + } */ + // Wait for all fingers to be released. + if (conf.fingers !== 0) return false; + // Record total number of fingers gesture used. + var ids = []; + conf.gestureFingers = 0; + for (var sid in conf.tracker) { + conf.gestureFingers ++; + ids.push(sid); + } + self.identifier = ids.join(","); + // Our pointer gesture has ended. + return true; +}; + +/* + Returns mouse coords in an array to match event.*Touches + ------------------------------------------------------------ + var touch = event.changedTouches || root.getCoords(event); +*/ + +root.getCoords = function(event) { + if (typeof(event.pageX) !== "undefined") { // Desktop browsers. + root.getCoords = function(event) { + return Array({ + type: "mouse", + x: event.pageX, + y: event.pageY, + pageX: event.pageX, + pageY: event.pageY, + identifier: event.pointerId || Infinity // pointerId is MS + }); + }; + } else { // Internet Explorer <= 8.0 + root.getCoords = function(event) { + event = event || window.event; + return Array({ + type: "mouse", + x: event.clientX + document.documentElement.scrollLeft, + y: event.clientY + document.documentElement.scrollTop, + pageX: event.clientX + document.documentElement.scrollLeft, + pageY: event.clientY + document.documentElement.scrollTop, + identifier: Infinity + }); + }; + } + return root.getCoords(event); +}; + +/* + Returns single coords in an object. + ------------------------------------------------------------ + var mouse = root.getCoord(event); +*/ + +root.getCoord = function(event) { + if ("ontouchstart" in window) { // Mobile browsers. + var pX = 0; + var pY = 0; + root.getCoord = function(event) { + var touches = event.changedTouches; + if (touches && touches.length) { // ontouchstart + ontouchmove + return { + x: pX = touches[0].pageX, + y: pY = touches[0].pageY + }; + } else { // ontouchend + return { + x: pX, + y: pY + }; + } + }; + } else if(typeof(event.pageX) !== "undefined" && typeof(event.pageY) !== "undefined") { // Desktop browsers. + root.getCoord = function(event) { + return { + x: event.pageX, + y: event.pageY + }; + }; + } else { // Internet Explorer <=8.0 + root.getCoord = function(event) { + event = event || window.event; + return { + x: event.clientX + document.documentElement.scrollLeft, + y: event.clientY + document.documentElement.scrollTop + }; + }; + } + return root.getCoord(event); +}; + +/* + Get target scale and position in space. +*/ + +root.getBoundingBox = function(o) { + if (o === window || o === document) o = document.body; + /// + var bbox = {}; + var bcr = o.getBoundingClientRect(); + bbox.width = bcr.width; + bbox.height = bcr.height; + bbox.x1 = bcr.left; + bbox.y1 = bcr.top; + bbox.x2 = bbox.x1 + bbox.width; + bbox.y2 = bbox.y1 + bbox.height; + bbox.scaleX = bcr.width / o.offsetWidth || 1; + bbox.scaleY = bcr.height / o.offsetHeight || 1; + bbox.scrollLeft = 0; + bbox.scrollTop = 0; + + /// Get the scroll of container element. + var tmp = o.parentNode; + while (tmp !== null) { + if (tmp === document.body) break; + if (tmp.scrollTop === undefined) break; + var style = window.getComputedStyle(tmp); + var position = style.getPropertyValue("position"); + if (position === "absolute") { + break; + } else if (position === "fixed") { + bbox.scrollTop -= tmp.parentNode.scrollTop; + break; + } else { + bbox.scrollLeft += tmp.scrollLeft; + bbox.scrollTop += tmp.scrollTop; + } + tmp = tmp.parentNode; + }; + /// + return bbox; +}; + +/* + Keep track of metaKey, the proper ctrlKey for users platform. +*/ + +(function() { + var agent = navigator.userAgent.toLowerCase(); + var mac = agent.indexOf("macintosh") !== -1; + if (mac && agent.indexOf("khtml") !== -1) { // chrome, safari. + var watch = { 91: true, 93: true }; + } else if (mac && agent.indexOf("firefox") !== -1) { // mac firefox. + var watch = { 224: true }; + } else { // windows, linux, or mac opera. + var watch = { 17: true }; + } + root.metaTrackerReset = function() { + root.metaKey = false; + root.ctrlKey = false; + root.shiftKey = false; + root.altKey = false; + }; + root.metaTracker = function(event) { + var check = !!watch[event.keyCode]; + if (check) root.metaKey = event.type === "keydown"; + root.ctrlKey = event.ctrlKey; + root.shiftKey = event.shiftKey; + root.altKey = event.altKey; + return check; + }; +})(); + +return root; + +})(Event.proxy); +/* + ---------------------------------------------------- + "MutationObserver" event proxy. + ---------------------------------------------------- + Author: Selvakumar Arumugam (MIT LICENSE) + http://stackoverflow.com/questions/10868104/can-you-have-a-javascript-hook-trigger-after-a-dom-elements-style-object-change + ---------------------------------------------------- +*/ +if (typeof(Event) === "undefined") var Event = {}; + +Event.MutationObserver = (function() { + var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; + var DOMAttrModifiedSupported = (function() { + var p = document.createElement("p"); + var flag = false; + var fn = function() { flag = true }; + if (p.addEventListener) { + p.addEventListener("DOMAttrModified", fn, false); + } else if (p.attachEvent) { + p.attachEvent("onDOMAttrModified", fn); + } else { + return false; + } + /// + p.setAttribute("id", "target"); + /// + return flag; + })(); + /// + return function(container, callback) { + if (MutationObserver) { + var options = { + subtree: false, + attributes: true + }; + var observer = new MutationObserver(function(mutations) { + mutations.forEach(function(e) { + callback.call(e.target, e.attributeName); + }); + }); + observer.observe(container, options) + } else if (DOMAttrModifiedSupported) { + Event.add(container, "DOMAttrModified", function(e) { + callback.call(container, e.attrName); + }); + } else if ("onpropertychange" in document.body) { + Event.add(container, "propertychange", function(e) { + callback.call(container, window.event.propertyName); + }); + } + } +})(); +/* + "Click" event proxy. + ---------------------------------------------------- + Event.add(window, "click", function(event, self) {}); +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(Event.proxy) === "undefined") Event.proxy = {}; + +Event.proxy = (function(root) { "use strict"; + +root.click = function(conf) { + conf.gesture = conf.gesture || "click"; + conf.maxFingers = conf.maxFingers || conf.fingers || 1; + // Setting up local variables. + var EVENT; + // Tracking the events. + conf.onPointerDown = function (event) { + if (root.pointerStart(event, self, conf)) { + Event.add(conf.doc, "mousemove", conf.onPointerMove).listener(event); + Event.add(conf.doc, "mouseup", conf.onPointerUp); + } + }; + conf.onPointerMove = function (event) { + EVENT = event; + }; + conf.onPointerUp = function(event) { + if (root.pointerEnd(event, self, conf)) { + Event.remove(conf.doc, "mousemove", conf.onPointerMove); + Event.remove(conf.doc, "mouseup", conf.onPointerUp); + if (EVENT.cancelBubble && ++ EVENT.bubble > 1) return; + var pointers = EVENT.changedTouches || root.getCoords(EVENT); + var pointer = pointers[0]; + var bbox = conf.bbox; + var newbbox = root.getBoundingBox(conf.target); + if (conf.position === "relative") { + var ax = (pointer.pageX + bbox.scrollLeft - bbox.x1); + var ay = (pointer.pageY + bbox.scrollTop - bbox.y1); + } else { + var ax = (pointer.pageX - bbox.x1); + var ay = (pointer.pageY - bbox.y1); + } + if (ax > 0 && ax < bbox.width && // Within target coordinates. + ay > 0 && ay < bbox.height && + bbox.scrollTop === newbbox.scrollTop) { + /// + for (var key in conf.tracker) break; //- should be modularized? in dblclick too + var point = conf.tracker[key]; + self.x = point.start.x; + self.y = point.start.y; + /// + conf.listener(EVENT, self); + } + } + }; + // Generate maintenance commands, and other configurations. + var self = root.pointerSetup(conf); + self.state = "click"; + // Attach events. + Event.add(conf.target, "mousedown", conf.onPointerDown); + // Return this object. + return self; +}; + +Event.Gesture = Event.Gesture || {}; +Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {}; +Event.Gesture._gestureHandlers.click = root.click; + +return root; + +})(Event.proxy); +/* + "Double-Click" aka "Double-Tap" event proxy. + ---------------------------------------------------- + Event.add(window, "dblclick", function(event, self) {}); + ---------------------------------------------------- + Touch an target twice for <= 700ms, with less than 25 pixel drift. +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(Event.proxy) === "undefined") Event.proxy = {}; + +Event.proxy = (function(root) { "use strict"; + +root.dbltap = +root.dblclick = function(conf) { + conf.gesture = conf.gesture || "dbltap"; + conf.maxFingers = conf.maxFingers || conf.fingers || 1; + // Setting up local variables. + var delay = 700; // in milliseconds + var time0, time1, timeout; + var pointer0, pointer1; + // Tracking the events. + conf.onPointerDown = function (event) { + var pointers = event.changedTouches || root.getCoords(event); + if (time0 && !time1) { // Click #2 + pointer1 = pointers[0]; + time1 = (new Date()).getTime() - time0; + } else { // Click #1 + pointer0 = pointers[0]; + time0 = (new Date()).getTime(); + time1 = 0; + clearTimeout(timeout); + timeout = setTimeout(function() { + time0 = 0; + }, delay); + } + if (root.pointerStart(event, self, conf)) { + Event.add(conf.doc, "mousemove", conf.onPointerMove).listener(event); + Event.add(conf.doc, "mouseup", conf.onPointerUp); + } + }; + conf.onPointerMove = function (event) { + if (time0 && !time1) { + var pointers = event.changedTouches || root.getCoords(event); + pointer1 = pointers[0]; + } + var bbox = conf.bbox; + if (conf.position === "relative") { + var ax = (pointer1.pageX + bbox.scrollLeft - bbox.x1); + var ay = (pointer1.pageY + bbox.scrollTop - bbox.y1); + } else { + var ax = (pointer1.pageX - bbox.x1); + var ay = (pointer1.pageY - bbox.y1); + } + if (!(ax > 0 && ax < bbox.width && // Within target coordinates.. + ay > 0 && ay < bbox.height && + Math.abs(pointer1.pageX - pointer0.pageX) <= 25 && // Within drift deviance. + Math.abs(pointer1.pageY - pointer0.pageY) <= 25)) { + // Cancel out this listener. + Event.remove(conf.doc, "mousemove", conf.onPointerMove); + clearTimeout(timeout); + time0 = time1 = 0; + } + }; + conf.onPointerUp = function(event) { + if (root.pointerEnd(event, self, conf)) { + Event.remove(conf.doc, "mousemove", conf.onPointerMove); + Event.remove(conf.doc, "mouseup", conf.onPointerUp); + } + if (time0 && time1) { + if (time1 <= delay && !(event.cancelBubble && ++event.bubble > 1)) { + self.state = conf.gesture; + for (var key in conf.tracker) break; + var point = conf.tracker[key]; + self.x = point.start.x; + self.y = point.start.y; + conf.listener(event, self); + } + clearTimeout(timeout); + time0 = time1 = 0; + } + }; + // Generate maintenance commands, and other configurations. + var self = root.pointerSetup(conf); + self.state = "dblclick"; + // Attach events. + Event.add(conf.target, "mousedown", conf.onPointerDown); + // Return this object. + return self; +}; + +Event.Gesture = Event.Gesture || {}; +Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {}; +Event.Gesture._gestureHandlers.dbltap = root.dbltap; +Event.Gesture._gestureHandlers.dblclick = root.dblclick; + +return root; + +})(Event.proxy); +/* + "Drag" event proxy (1+ fingers). + ---------------------------------------------------- + CONFIGURE: maxFingers, position. + ---------------------------------------------------- + Event.add(window, "drag", function(event, self) { + console.log(self.gesture, self.state, self.start, self.x, self.y, self.bbox); + }); +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(Event.proxy) === "undefined") Event.proxy = {}; + +Event.proxy = (function(root) { "use strict"; + +root.dragElement = function(that, event) { + root.drag({ + event: event, + target: that, + position: "move", + listener: function(event, self) { + that.style.left = self.x + "px"; + that.style.top = self.y + "px"; + Event.prevent(event); + } + }); +}; + +root.drag = function(conf) { + conf.gesture = "drag"; + conf.onPointerDown = function (event) { + if (root.pointerStart(event, self, conf)) { + if (!conf.monitor) { + Event.add(conf.doc, "mousemove", conf.onPointerMove); + Event.add(conf.doc, "mouseup", conf.onPointerUp); + } + } + // Process event listener. + conf.onPointerMove(event, "down"); + }; + conf.onPointerMove = function (event, state) { + if (!conf.tracker) return conf.onPointerDown(event); + var bbox = conf.bbox; + var touches = event.changedTouches || root.getCoords(event); + var length = touches.length; + for (var i = 0; i < length; i ++) { + var touch = touches[i]; + var identifier = touch.identifier || Infinity; + var pt = conf.tracker[identifier]; + // Identifier defined outside of listener. + if (!pt) continue; + pt.pageX = touch.pageX; + pt.pageY = touch.pageY; + // Record data. + self.state = state || "move"; + self.identifier = identifier; + self.start = pt.start; + self.fingers = conf.fingers; + if (conf.position === "differenceFromLast") { + self.x = (pt.pageX - pt.offsetX); + self.y = (pt.pageY - pt.offsetY); + pt.offsetX = pt.pageX; + pt.offsetY = pt.pageY; + } else if (conf.position === "relative") { + self.x = (pt.pageX + bbox.scrollLeft - pt.offsetX); + self.y = (pt.pageY + bbox.scrollTop - pt.offsetY); + } else { + self.x = (pt.pageX - pt.offsetX); + self.y = (pt.pageY - pt.offsetY); + } + /// + conf.listener(event, self); + } + }; + conf.onPointerUp = function(event) { + // Remove tracking for touch. + if (root.pointerEnd(event, self, conf, conf.onPointerMove)) { + if (!conf.monitor) { + Event.remove(conf.doc, "mousemove", conf.onPointerMove); + Event.remove(conf.doc, "mouseup", conf.onPointerUp); + } + } + }; + // Generate maintenance commands, and other configurations. + var self = root.pointerSetup(conf); + // Attach events. + if (conf.event) { + conf.onPointerDown(conf.event); + } else { // + Event.add(conf.target, "mousedown", conf.onPointerDown); + if (conf.monitor) { + Event.add(conf.doc, "mousemove", conf.onPointerMove); + Event.add(conf.doc, "mouseup", conf.onPointerUp); + } + } + // Return this object. + return self; +}; + +Event.Gesture = Event.Gesture || {}; +Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {}; +Event.Gesture._gestureHandlers.drag = root.drag; + +return root; + +})(Event.proxy); +/* + "Gesture" event proxy (2+ fingers). + ---------------------------------------------------- + CONFIGURE: minFingers, maxFingers. + ---------------------------------------------------- + Event.add(window, "gesture", function(event, self) { + console.log(self.rotation, self.scale, self.fingers, self.state); + }); +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(Event.proxy) === "undefined") Event.proxy = {}; + +Event.proxy = (function(root) { "use strict"; + +var RAD_DEG = Math.PI / 180; + +root.gesture = function(conf) { + conf.gesture = conf.gesture || "gesture"; + conf.minFingers = conf.minFingers || conf.fingers || 2; + // Tracking the events. + conf.onPointerDown = function (event) { + var fingers = conf.fingers; + if (root.pointerStart(event, self, conf)) { + Event.add(conf.doc, "mousemove", conf.onPointerMove); + Event.add(conf.doc, "mouseup", conf.onPointerUp); + } + // Record gesture start. + if (conf.fingers === conf.minFingers && fingers !== conf.fingers) { + self.fingers = conf.minFingers; + self.scale = 1; + self.rotation = 0; + self.state = "start"; + var sids = ""; //- FIXME(mud): can generate duplicate IDs. + for (var key in conf.tracker) sids += key; + self.identifier = parseInt(sids); + conf.listener(event, self); + } + }; + /// + conf.onPointerMove = function (event, state) { + var bbox = conf.bbox; + var points = conf.tracker; + var touches = event.changedTouches || root.getCoords(event); + var length = touches.length; + // Update tracker coordinates. + for (var i = 0; i < length; i ++) { + var touch = touches[i]; + var sid = touch.identifier || Infinity; + var pt = points[sid]; + // Check whether "pt" is used by another gesture. + if (!pt) continue; + // Find the actual coordinates. + if (conf.position === "relative") { + pt.move.x = (touch.pageX + bbox.scrollLeft - bbox.x1); + pt.move.y = (touch.pageY + bbox.scrollTop - bbox.y1); + } else { + pt.move.x = (touch.pageX - bbox.x1); + pt.move.y = (touch.pageY - bbox.y1); + } + } + /// + if (conf.fingers < conf.minFingers) return; + /// + var touches = []; + var scale = 0; + var rotation = 0; + /// Calculate centroid of gesture. + var centroidx = 0; + var centroidy = 0; + var length = 0; + for (var sid in points) { + var touch = points[sid]; + if (touch.up) continue; + centroidx += touch.move.x; + centroidy += touch.move.y; + length ++; + } + centroidx /= length; + centroidy /= length; + /// + for (var sid in points) { + var touch = points[sid]; + if (touch.up) continue; + var start = touch.start; + if (!start.distance) { + var dx = start.x - centroidx; + var dy = start.y - centroidy; + start.distance = Math.sqrt(dx * dx + dy * dy); + start.angle = Math.atan2(dx, dy) / RAD_DEG; + } + // Calculate scale. + var dx = touch.move.x - centroidx; + var dy = touch.move.y - centroidy; + var distance = Math.sqrt(dx * dx + dy * dy); + scale += distance / start.distance; + // Calculate rotation. + var angle = Math.atan2(dx, dy) / RAD_DEG; + var rotate = (start.angle - angle + 360) % 360 - 180; + touch.DEG2 = touch.DEG1; // Previous degree. + touch.DEG1 = rotate > 0 ? rotate : -rotate; // Current degree. + if (typeof(touch.DEG2) !== "undefined") { + if (rotate > 0) { + touch.rotation += touch.DEG1 - touch.DEG2; + } else { + touch.rotation -= touch.DEG1 - touch.DEG2; + } + rotation += touch.rotation; + } + // Attach current points to self. + touches.push(touch.move); + } + /// + self.touches = touches; + self.fingers = conf.fingers; + self.scale = scale / conf.fingers; + self.rotation = rotation / conf.fingers; + self.state = "change"; + conf.listener(event, self); + }; + conf.onPointerUp = function(event) { + // Remove tracking for touch. + var fingers = conf.fingers; + if (root.pointerEnd(event, self, conf)) { + Event.remove(conf.doc, "mousemove", conf.onPointerMove); + Event.remove(conf.doc, "mouseup", conf.onPointerUp); + } + // Check whether fingers has dropped below minFingers. + if (fingers === conf.minFingers && conf.fingers < conf.minFingers) { + self.fingers = conf.fingers; + self.state = "end"; + conf.listener(event, self); + } + }; + // Generate maintenance commands, and other configurations. + var self = root.pointerSetup(conf); + // Attach events. + Event.add(conf.target, "mousedown", conf.onPointerDown); + // Return this object. + return self; +}; + +Event.Gesture = Event.Gesture || {}; +Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {}; +Event.Gesture._gestureHandlers.gesture = root.gesture; + +return root; + +})(Event.proxy); +/* + "Pointer" event proxy (1+ fingers). + ---------------------------------------------------- + CONFIGURE: minFingers, maxFingers. + ---------------------------------------------------- + Event.add(window, "gesture", function(event, self) { + console.log(self.rotation, self.scale, self.fingers, self.state); + }); +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(Event.proxy) === "undefined") Event.proxy = {}; + +Event.proxy = (function(root) { "use strict"; + +root.pointerdown = +root.pointermove = +root.pointerup = function(conf) { + conf.gesture = conf.gesture || "pointer"; + if (conf.target.isPointerEmitter) return; + // Tracking the events. + var isDown = true; + conf.onPointerDown = function (event) { + isDown = false; + self.gesture = "pointerdown"; + conf.listener(event, self); + }; + conf.onPointerMove = function (event) { + self.gesture = "pointermove"; + conf.listener(event, self, isDown); + }; + conf.onPointerUp = function (event) { + isDown = true; + self.gesture = "pointerup"; + conf.listener(event, self, true); + }; + // Generate maintenance commands, and other configurations. + var self = root.pointerSetup(conf); + // Attach events. + Event.add(conf.target, "mousedown", conf.onPointerDown); + Event.add(conf.target, "mousemove", conf.onPointerMove); + Event.add(conf.doc, "mouseup", conf.onPointerUp); + // Return this object. + conf.target.isPointerEmitter = true; + return self; +}; + +Event.Gesture = Event.Gesture || {}; +Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {}; +Event.Gesture._gestureHandlers.pointerdown = root.pointerdown; +Event.Gesture._gestureHandlers.pointermove = root.pointermove; +Event.Gesture._gestureHandlers.pointerup = root.pointerup; + +return root; + +})(Event.proxy); +/* + "Device Motion" and "Shake" event proxy. + ---------------------------------------------------- + http://developer.android.com/reference/android/hardware/SensorEvent.html#values + ---------------------------------------------------- + Event.add(window, "shake", function(event, self) {}); + Event.add(window, "devicemotion", function(event, self) { + console.log(self.acceleration, self.accelerationIncludingGravity); + }); +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(Event.proxy) === "undefined") Event.proxy = {}; + +Event.proxy = (function(root) { "use strict"; + +root.shake = function(conf) { + // Externally accessible data. + var self = { + gesture: "devicemotion", + acceleration: {}, + accelerationIncludingGravity: {}, + target: conf.target, + listener: conf.listener, + remove: function() { + window.removeEventListener('devicemotion', onDeviceMotion, false); + } + }; + // Setting up local variables. + var threshold = 4; // Gravitational threshold. + var timeout = 1000; // Timeout between shake events. + var timeframe = 200; // Time between shakes. + var shakes = 3; // Minimum shakes to trigger event. + var lastShake = (new Date()).getTime(); + var gravity = { x: 0, y: 0, z: 0 }; + var delta = { + x: { count: 0, value: 0 }, + y: { count: 0, value: 0 }, + z: { count: 0, value: 0 } + }; + // Tracking the events. + var onDeviceMotion = function(e) { + var alpha = 0.8; // Low pass filter. + var o = e.accelerationIncludingGravity; + gravity.x = alpha * gravity.x + (1 - alpha) * o.x; + gravity.y = alpha * gravity.y + (1 - alpha) * o.y; + gravity.z = alpha * gravity.z + (1 - alpha) * o.z; + self.accelerationIncludingGravity = gravity; + self.acceleration.x = o.x - gravity.x; + self.acceleration.y = o.y - gravity.y; + self.acceleration.z = o.z - gravity.z; + /// + if (conf.gesture === "devicemotion") { + conf.listener(e, self); + return; + } + var data = "xyz"; + var now = (new Date()).getTime(); + for (var n = 0, length = data.length; n < length; n ++) { + var letter = data[n]; + var ACCELERATION = self.acceleration[letter]; + var DELTA = delta[letter]; + var abs = Math.abs(ACCELERATION); + /// Check whether another shake event was recently registered. + if (now - lastShake < timeout) continue; + /// Check whether delta surpasses threshold. + if (abs > threshold) { + var idx = now * ACCELERATION / abs; + var span = Math.abs(idx + DELTA.value); + // Check whether last delta was registered within timeframe. + if (DELTA.value && span < timeframe) { + DELTA.value = idx; + DELTA.count ++; + // Check whether delta count has enough shakes. + if (DELTA.count === shakes) { + conf.listener(e, self); + // Reset tracking. + lastShake = now; + DELTA.value = 0; + DELTA.count = 0; + } + } else { + // Track first shake. + DELTA.value = idx; + DELTA.count = 1; + } + } + } + }; + // Attach events. + if (!window.addEventListener) return; + window.addEventListener('devicemotion', onDeviceMotion, false); + // Return this object. + return self; +}; + +Event.Gesture = Event.Gesture || {}; +Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {}; +Event.Gesture._gestureHandlers.shake = root.shake; + +return root; + +})(Event.proxy); +/* + "Swipe" event proxy (1+ fingers). + ---------------------------------------------------- + CONFIGURE: snap, threshold, maxFingers. + ---------------------------------------------------- + Event.add(window, "swipe", function(event, self) { + console.log(self.velocity, self.angle); + }); +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(Event.proxy) === "undefined") Event.proxy = {}; + +Event.proxy = (function(root) { "use strict"; + +var RAD_DEG = Math.PI / 180; + +root.swipe = function(conf) { + conf.snap = conf.snap || 90; // angle snap. + conf.threshold = conf.threshold || 1; // velocity threshold. + conf.gesture = conf.gesture || "swipe"; + // Tracking the events. + conf.onPointerDown = function (event) { + if (root.pointerStart(event, self, conf)) { + Event.add(conf.doc, "mousemove", conf.onPointerMove).listener(event); + Event.add(conf.doc, "mouseup", conf.onPointerUp); + } + }; + conf.onPointerMove = function (event) { + var touches = event.changedTouches || root.getCoords(event); + var length = touches.length; + for (var i = 0; i < length; i ++) { + var touch = touches[i]; + var sid = touch.identifier || Infinity; + var o = conf.tracker[sid]; + // Identifier defined outside of listener. + if (!o) continue; + o.move.x = touch.pageX; + o.move.y = touch.pageY; + o.moveTime = (new Date()).getTime(); + } + }; + conf.onPointerUp = function(event) { + if (root.pointerEnd(event, self, conf)) { + Event.remove(conf.doc, "mousemove", conf.onPointerMove); + Event.remove(conf.doc, "mouseup", conf.onPointerUp); + /// + var velocity1; + var velocity2 + var degree1; + var degree2; + /// Calculate centroid of gesture. + var start = { x: 0, y: 0 }; + var endx = 0; + var endy = 0; + var length = 0; + /// + for (var sid in conf.tracker) { + var touch = conf.tracker[sid]; + var xdist = touch.move.x - touch.start.x; + var ydist = touch.move.y - touch.start.y; + /// + endx += touch.move.x; + endy += touch.move.y; + start.x += touch.start.x; + start.y += touch.start.y; + length ++; + /// + var distance = Math.sqrt(xdist * xdist + ydist * ydist); + var ms = touch.moveTime - touch.startTime; + var degree2 = Math.atan2(xdist, ydist) / RAD_DEG + 180; + var velocity2 = ms ? distance / ms : 0; + if (typeof(degree1) === "undefined") { + degree1 = degree2; + velocity1 = velocity2; + } else if (Math.abs(degree2 - degree1) <= 20) { + degree1 = (degree1 + degree2) / 2; + velocity1 = (velocity1 + velocity2) / 2; + } else { + return; + } + } + /// + var fingers = conf.gestureFingers; + if (conf.minFingers <= fingers && conf.maxFingers >= fingers) { + if (velocity1 > conf.threshold) { + start.x /= length; + start.y /= length; + self.start = start; + self.x = endx / length; + self.y = endy / length; + self.angle = -((((degree1 / conf.snap + 0.5) >> 0) * conf.snap || 360) - 360); + self.velocity = velocity1; + self.fingers = fingers; + self.state = "swipe"; + conf.listener(event, self); + } + } + } + }; + // Generate maintenance commands, and other configurations. + var self = root.pointerSetup(conf); + // Attach events. + Event.add(conf.target, "mousedown", conf.onPointerDown); + // Return this object. + return self; +}; + +Event.Gesture = Event.Gesture || {}; +Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {}; +Event.Gesture._gestureHandlers.swipe = root.swipe; + +return root; + +})(Event.proxy); +/* + "Tap" and "Longpress" event proxy. + ---------------------------------------------------- + CONFIGURE: delay (longpress), timeout (tap). + ---------------------------------------------------- + Event.add(window, "tap", function(event, self) { + console.log(self.fingers); + }); + ---------------------------------------------------- + multi-finger tap // touch an target for <= 250ms. + multi-finger longpress // touch an target for >= 500ms +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(Event.proxy) === "undefined") Event.proxy = {}; + +Event.proxy = (function(root) { "use strict"; + +root.longpress = function(conf) { + conf.gesture = "longpress"; + return root.tap(conf); +}; + +root.tap = function(conf) { + conf.delay = conf.delay || 500; + conf.timeout = conf.timeout || 250; + conf.driftDeviance = conf.driftDeviance || 10; + conf.gesture = conf.gesture || "tap"; + // Setting up local variables. + var timestamp, timeout; + // Tracking the events. + conf.onPointerDown = function (event) { + if (root.pointerStart(event, self, conf)) { + timestamp = (new Date()).getTime(); + // Initialize event listeners. + Event.add(conf.doc, "mousemove", conf.onPointerMove).listener(event); + Event.add(conf.doc, "mouseup", conf.onPointerUp); + // Make sure this is a "longpress" event. + if (conf.gesture !== "longpress") return; + timeout = setTimeout(function() { + if (event.cancelBubble && ++event.bubble > 1) return; + // Make sure no fingers have been changed. + var fingers = 0; + for (var key in conf.tracker) { + var point = conf.tracker[key]; + if (point.end === true) return; + if (conf.cancel) return; + fingers ++; + } + // Send callback. + if (conf.minFingers <= fingers && conf.maxFingers >= fingers) { + self.state = "start"; + self.fingers = fingers; + self.x = point.start.x; + self.y = point.start.y; + conf.listener(event, self); + } + }, conf.delay); + } + }; + conf.onPointerMove = function (event) { + var bbox = conf.bbox; + var touches = event.changedTouches || root.getCoords(event); + var length = touches.length; + for (var i = 0; i < length; i ++) { + var touch = touches[i]; + var identifier = touch.identifier || Infinity; + var pt = conf.tracker[identifier]; + if (!pt) continue; + if (conf.position === "relative") { + var x = (touch.pageX + bbox.scrollLeft - bbox.x1); + var y = (touch.pageY + bbox.scrollTop - bbox.y1); + } else { + var x = (touch.pageX - bbox.x1); + var y = (touch.pageY - bbox.y1); + } + /// + var dx = x - pt.start.x; + var dy = y - pt.start.y; + var distance = Math.sqrt(dx * dx + dy * dy); + if (!(x > 0 && x < bbox.width && // Within target coordinates.. + y > 0 && y < bbox.height && + distance <= conf.driftDeviance)) { // Within drift deviance. + // Cancel out this listener. + Event.remove(conf.doc, "mousemove", conf.onPointerMove); + conf.cancel = true; + return; + } + } + }; + conf.onPointerUp = function(event) { + if (root.pointerEnd(event, self, conf)) { + clearTimeout(timeout); + Event.remove(conf.doc, "mousemove", conf.onPointerMove); + Event.remove(conf.doc, "mouseup", conf.onPointerUp); + if (event.cancelBubble && ++event.bubble > 1) return; + // Callback release on longpress. + if (conf.gesture === "longpress") { + if (self.state === "start") { + self.state = "end"; + conf.listener(event, self); + } + return; + } + // Cancel event due to movement. + if (conf.cancel) return; + // Ensure delay is within margins. + if ((new Date()).getTime() - timestamp > conf.timeout) return; + // Send callback. + var fingers = conf.gestureFingers; + if (conf.minFingers <= fingers && conf.maxFingers >= fingers) { + self.state = "tap"; + self.fingers = conf.gestureFingers; + conf.listener(event, self); + } + } + }; + // Generate maintenance commands, and other configurations. + var self = root.pointerSetup(conf); + // Attach events. + Event.add(conf.target, "mousedown", conf.onPointerDown); + // Return this object. + return self; +}; + +Event.Gesture = Event.Gesture || {}; +Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {}; +Event.Gesture._gestureHandlers.tap = root.tap; +Event.Gesture._gestureHandlers.longpress = root.longpress; + +return root; + +})(Event.proxy); +/* + "Mouse Wheel" event proxy. + ---------------------------------------------------- + Event.add(window, "wheel", function(event, self) { + console.log(self.state, self.wheelDelta); + }); +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(Event.proxy) === "undefined") Event.proxy = {}; + +Event.proxy = (function(root) { "use strict"; + +root.wheel = function(conf) { + // Configure event listener. + var interval; + var timeout = conf.timeout || 150; + var count = 0; + // Externally accessible data. + var self = { + gesture: "wheel", + state: "start", + wheelDelta: 0, + target: conf.target, + listener: conf.listener, + preventElasticBounce: function() { + var target = this.target; + var scrollTop = target.scrollTop; + var top = scrollTop + target.offsetHeight; + var height = target.scrollHeight; + if (top === height && this.wheelDelta <= 0) Event.cancel(event); + else if (scrollTop === 0 && this.wheelDelta >= 0) Event.cancel(event); + Event.stop(event); + }, + add: function() { + conf.target[add](type, onMouseWheel, false); + }, + remove: function() { + conf.target[remove](type, onMouseWheel, false); + } + }; + // Tracking the events. + var onMouseWheel = function(event) { + event = event || window.event; + self.state = count++ ? "change" : "start"; + self.wheelDelta = event.detail ? event.detail * -20 : event.wheelDelta; + conf.listener(event, self); + clearTimeout(interval); + interval = setTimeout(function() { + count = 0; + self.state = "end"; + self.wheelDelta = 0; + conf.listener(event, self); + }, timeout); + }; + // Attach events. + var add = document.addEventListener ? "addEventListener" : "attachEvent"; + var remove = document.removeEventListener ? "removeEventListener" : "detachEvent"; + var type = Event.getEventSupport("mousewheel") ? "mousewheel" : "DOMMouseScroll"; + conf.target[add](type, onMouseWheel, false); + // Return this object. + return self; +}; + +Event.Gesture = Event.Gesture || {}; +Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {}; +Event.Gesture._gestureHandlers.wheel = root.wheel; + +return root; + +})(Event.proxy); +/* + "Orientation Change" + ---------------------------------------------------- + https://developer.apple.com/library/safari/documentation/SafariDOMAdditions/Reference/DeviceOrientationEventClassRef/DeviceOrientationEvent/DeviceOrientationEvent.html#//apple_ref/doc/uid/TP40010526 + ---------------------------------------------------- + Event.add(window, "deviceorientation", function(event, self) {}); +*/ + +if (typeof(Event) === "undefined") var Event = {}; +if (typeof(Event.proxy) === "undefined") Event.proxy = {}; + +Event.proxy = (function(root) { "use strict"; + +root.orientation = function(conf) { + // Externally accessible data. + var self = { + gesture: "orientationchange", + previous: null, /* Report the previous orientation */ + current: window.orientation, + target: conf.target, + listener: conf.listener, + remove: function() { + window.removeEventListener('orientationchange', onOrientationChange, false); + } + }; + + // Tracking the events. + var onOrientationChange = function(e) { + + self.previous = self.current; + self.current = window.orientation; + if(self.previous !== null && self.previous != self.current) { + conf.listener(e, self); + return; + } + + + }; + // Attach events. + if (window.DeviceOrientationEvent) { + window.addEventListener("orientationchange", onOrientationChange, false); + } + // Return this object. + return self; +}; + +Event.Gesture = Event.Gesture || {}; +Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {}; +Event.Gesture._gestureHandlers.orientation = root.orientation; + +return root; + +})(Event.proxy); +(function(){ + + /** + * @private + * @param {String} eventName + * @param {Function} handler + */ + function _removeEventListener(eventName, handler) { + if (!this.__eventListeners[eventName]) return; + + if (handler) { + fabric.util.removeFromArray(this.__eventListeners[eventName], handler); + } + else { + this.__eventListeners[eventName].length = 0; + } + } + + /** + * Observes specified event + * @deprecated `observe` deprecated since 0.8.34 (use `on` instead) + * @memberOf fabric.Observable + * @alias on + * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler}) + * @param {Function} handler Function that receives a notification when an event of the specified type occurs + * @return {Self} thisArg + * @chainable + */ + function observe(eventName, handler) { + if (!this.__eventListeners) { + this.__eventListeners = { }; + } + // one object with key/value pairs was passed + if (arguments.length === 1) { + for (var prop in eventName) { + this.on(prop, eventName[prop]); + } + } + else { + if (!this.__eventListeners[eventName]) { + this.__eventListeners[eventName] = [ ]; + } + this.__eventListeners[eventName].push(handler); + } + return this; + } + + /** + * Stops event observing for a particular event handler. Calling this method + * without arguments removes all handlers for all events + * @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead) + * @memberOf fabric.Observable + * @alias off + * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler}) + * @param {Function} handler Function to be deleted from EventListeners + * @return {Self} thisArg + * @chainable + */ + function stopObserving(eventName, handler) { + if (!this.__eventListeners) return; + + // remove all key/value pairs (event name -> event handler) + if (arguments.length === 0) { + this.__eventListeners = { }; + } + // one object with key/value pairs was passed + else if (arguments.length === 1 && typeof arguments[0] === 'object') { + for (var prop in eventName) { + _removeEventListener.call(this, prop, eventName[prop]); + } + } + else { + _removeEventListener.call(this, eventName, handler); + } + return this; + } + + /** + * Fires event with an optional options object + * @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead) + * @memberOf fabric.Observable + * @alias trigger + * @param {String} eventName Event name to fire + * @param {Object} [options] Options object + * @return {Self} thisArg + * @chainable + */ + function fire(eventName, options) { + if (!this.__eventListeners) return; + + var listenersForEvent = this.__eventListeners[eventName]; + if (!listenersForEvent) return; + for (var i = 0, len = listenersForEvent.length; i < len; i++) { + // avoiding try/catch for perf. reasons + listenersForEvent[i].call(this, options || { }); + } + return this; + } + + /** + * @namespace fabric.Observable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#events} + * @see {@link http://fabricjs.com/events/|Events demo} + */ + fabric.Observable = { + observe: observe, + stopObserving: stopObserving, + fire: fire, + + on: observe, + off: stopObserving, + trigger: fire + }; +})(); +/** + * @namespace fabric.Collection + */ +fabric.Collection = { + + /** + * Adds objects to collection, then renders canvas (if `renderOnAddRemove` is not `false`) + * Objects should be instances of (or inherit from) fabric.Object + * @param [...] Zero or more fabric instances + * @return {Self} thisArg + */ + add: function () { + this._objects.push.apply(this._objects, arguments); + for (var i = arguments.length; i--; ) { + this._onObjectAdded(arguments[i]); + } + this.renderOnAddRemove && this.renderAll(); + return this; + }, + + /** + * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`) + * An object should be an instance of (or inherit from) fabric.Object + * @param {Object} object Object to insert + * @param {Number} index Index to insert object at + * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs + * @return {Self} thisArg + */ + insertAt: function (object, index, nonSplicing) { + var objects = this.getObjects(); + if (nonSplicing) { + objects[index] = object; + } + else { + objects.splice(index, 0, object); + } + this._onObjectAdded(object); + this.renderOnAddRemove && this.renderAll(); + return this; + }, + + /** + * Removes an object from a collection, then renders canvas (if `renderOnAddRemove` is not `false`) + * @param {Object} object Object to remove + * @return {Self} thisArg + */ + remove: function(object) { + var objects = this.getObjects(), + index = objects.indexOf(object); + + // only call onObjectRemoved if an object was actually removed + if (index !== -1) { + objects.splice(index, 1); + this._onObjectRemoved(object); + } + + this.renderOnAddRemove && this.renderAll(); + return object; + }, + + /** + * Executes given function for each object in this group + * @param {Function} callback + * Callback invoked with current object as first argument, + * index - as second and an array of all objects - as third. + * Iteration happens in reverse order (for performance reasons). + * Callback is invoked in a context of Global Object (e.g. `window`) + * when no `context` argument is given + * + * @param {Object} context Context (aka thisObject) + * @return {Self} thisArg + */ + forEachObject: function(callback, context) { + var objects = this.getObjects(), + i = objects.length; + while (i--) { + callback.call(context, objects[i], i, objects); + } + return this; + }, + + /** + * Returns an array of children objects of this instance + * Type parameter introduced in 1.3.10 + * @param {String} [type] When specified, only objects of this type are returned + * @return {Array} + */ + getObjects: function(type) { + if (typeof type === 'undefined') { + return this._objects; + } + return this._objects.filter(function(o) { + return o.type === type; + }); + }, + + /** + * Returns object at specified index + * @param {Number} index + * @return {Self} thisArg + */ + item: function (index) { + return this.getObjects()[index]; + }, + + /** + * Returns true if collection contains no objects + * @return {Boolean} true if collection is empty + */ + isEmpty: function () { + return this.getObjects().length === 0; + }, + + /** + * Returns a size of a collection (i.e: length of an array containing its objects) + * @return {Number} Collection size + */ + size: function() { + return this.getObjects().length; + }, + + /** + * Returns true if collection contains an object + * @param {Object} object Object to check against + * @return {Boolean} `true` if collection contains an object + */ + contains: function(object) { + return this.getObjects().indexOf(object) > -1; + }, + + /** + * Returns number representation of a collection complexity + * @return {Number} complexity + */ + complexity: function () { + return this.getObjects().reduce(function (memo, current) { + memo += current.complexity ? current.complexity() : 0; + return memo; + }, 0); + } +}; +(function(global) { + + var sqrt = Math.sqrt, + atan2 = Math.atan2, + PiBy180 = Math.PI / 180; + + /** + * @namespace fabric.util + */ + fabric.util = { + + /** + * Removes value from an array. + * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf` + * @static + * @memberOf fabric.util + * @param {Array} array + * @param {Any} value + * @return {Array} original array + */ + removeFromArray: function(array, value) { + var idx = array.indexOf(value); + if (idx !== -1) { + array.splice(idx, 1); + } + return array; + }, + + /** + * Returns random number between 2 specified ones. + * @static + * @memberOf fabric.util + * @param {Number} min lower limit + * @param {Number} max upper limit + * @return {Number} random value (between min and max) + */ + getRandomInt: function(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + }, + + /** + * Transforms degrees to radians. + * @static + * @memberOf fabric.util + * @param {Number} degrees value in degrees + * @return {Number} value in radians + */ + degreesToRadians: function(degrees) { + return degrees * PiBy180; + }, + + /** + * Transforms radians to degrees. + * @static + * @memberOf fabric.util + * @param {Number} radians value in radians + * @return {Number} value in degrees + */ + radiansToDegrees: function(radians) { + return radians / PiBy180; + }, + + /** + * Rotates `point` around `origin` with `radians` + * @static + * @memberOf fabric.util + * @param {fabric.Point} The point to rotate + * @param {fabric.Point} The origin of the rotation + * @param {Number} The radians of the angle for the rotation + * @return {fabric.Point} The new rotated point + */ + rotatePoint: function(point, origin, radians) { + var sin = Math.sin(radians), + cos = Math.cos(radians); + + point.subtractEquals(origin); + + var rx = point.x * cos - point.y * sin, + ry = point.x * sin + point.y * cos; + + return new fabric.Point(rx, ry).addEquals(origin); + }, + + /** + * A wrapper around Number#toFixed, which contrary to native method returns number, not string. + * @static + * @memberOf fabric.util + * @param {Number | String} number number to operate on + * @param {Number} fractionDigits number of fraction digits to "leave" + * @return {Number} + */ + toFixed: function(number, fractionDigits) { + return parseFloat(Number(number).toFixed(fractionDigits)); + }, + + /** + * Function which always returns `false`. + * @static + * @memberOf fabric.util + * @return {Boolean} + */ + falseFunction: function() { + return false; + }, + + /** + * Returns klass "Class" object of given namespace + * @memberOf fabric.util + * @param {String} type Type of object (eg. 'circle') + * @param {String} namespace Namespace to get klass "Class" object from + * @return {Object} klass "Class" + */ + getKlass: function(type, namespace) { + // capitalize first letter only + type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1)); + return fabric.util.resolveNamespace(namespace)[type]; + }, + + /** + * Returns object of given namespace + * @memberOf fabric.util + * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric' + * @return {Object} Object for given namespace (default fabric) + */ + resolveNamespace: function(namespace) { + if (!namespace) return fabric; + + var parts = namespace.split('.'), + len = parts.length, + obj = global || fabric.window; + + for (var i = 0; i < len; ++i) { + obj = obj[parts[i]]; + } + + return obj; + }, + + /** + * Loads image element from given url and passes it to a callback + * @memberOf fabric.util + * @param {String} url URL representing an image + * @param {Function} callback Callback; invoked with loaded image + * @param {Any} [context] Context to invoke callback in + * @param {Object} [crossOrigin] crossOrigin value to set image element to + */ + loadImage: function(url, callback, context, crossOrigin) { + if (!url) { + callback && callback.call(context, url); + return; + } + + var img = fabric.util.createImage(); + + /** @ignore */ + img.onload = function () { + callback && callback.call(context, img); + img = img.onload = img.onerror = null; + }; + + /** @ignore */ + img.onerror = function() { + fabric.log('Error loading ' + img.src); + callback && callback.call(context, null, true); + img = img.onload = img.onerror = null; + }; + + // data-urls appear to be buggy with crossOrigin + // https://github.com/kangax/fabric.js/commit/d0abb90f1cd5c5ef9d2a94d3fb21a22330da3e0a#commitcomment-4513767 + // see https://code.google.com/p/chromium/issues/detail?id=315152 + // https://bugzilla.mozilla.org/show_bug.cgi?id=935069 + if (url.indexOf('data') !== 0 && typeof crossOrigin !== 'undefined') { + img.crossOrigin = crossOrigin; + } + + img.src = url; + }, + + /** + * Creates corresponding fabric instances from their object representations + * @static + * @memberOf fabric.util + * @param {Array} objects Objects to enliven + * @param {Function} callback Callback to invoke when all objects are created + * @param {Function} [reviver] Method for further parsing of object elements, + * called after each fabric object created. + */ + enlivenObjects: function(objects, callback, namespace, reviver) { + objects = objects || [ ]; + + function onLoaded() { + if (++numLoadedObjects === numTotalObjects) { + callback && callback(enlivenedObjects); + } + } + + var enlivenedObjects = [ ], + numLoadedObjects = 0, + numTotalObjects = objects.length; + + if (!numTotalObjects) { + callback && callback(enlivenedObjects); + return; + } + + objects.forEach(function (o, index) { + // if sparse array + if (!o || !o.type) { + onLoaded(); + return; + } + var klass = fabric.util.getKlass(o.type, namespace); + if (klass.async) { + klass.fromObject(o, function (obj, error) { + if (!error) { + enlivenedObjects[index] = obj; + reviver && reviver(o, enlivenedObjects[index]); + } + onLoaded(); + }); + } + else { + enlivenedObjects[index] = klass.fromObject(o); + reviver && reviver(o, enlivenedObjects[index]); + onLoaded(); + } + }); + }, + + /** + * Groups SVG elements (usually those retrieved from SVG document) + * @static + * @memberOf fabric.util + * @param {Array} elements SVG elements to group + * @param {Object} [options] Options object + * @return {fabric.Object|fabric.PathGroup} + */ + groupSVGElements: function(elements, options, path) { + var object; + + if (elements.length > 1) { + object = new fabric.PathGroup(elements, options); + } + else { + object = elements[0]; + } + + if (typeof path !== 'undefined') { + object.setSourcePath(path); + } + return object; + }, + + /** + * Populates an object with properties of another object + * @static + * @memberOf fabric.util + * @param {Object} source Source object + * @param {Object} destination Destination object + * @return {Array} properties Propertie names to include + */ + populateWithProperties: function(source, destination, properties) { + if (properties && Object.prototype.toString.call(properties) === '[object Array]') { + for (var i = 0, len = properties.length; i < len; i++) { + if (properties[i] in source) { + destination[properties[i]] = source[properties[i]]; + } + } + } + }, + + /** + * Draws a dashed line between two points + * + * This method is used to draw dashed line around selection area. + * See
    dotted stroke in canvas + * + * @param {CanvasRenderingContext2D} ctx context + * @param {Number} x start x coordinate + * @param {Number} y start y coordinate + * @param {Number} x2 end x coordinate + * @param {Number} y2 end y coordinate + * @param {Array} da dash array pattern + */ + drawDashedLine: function(ctx, x, y, x2, y2, da) { + var dx = x2 - x, + dy = y2 - y, + len = sqrt(dx*dx + dy*dy), + rot = atan2(dy, dx), + dc = da.length, + di = 0, + draw = true; + + ctx.save(); + ctx.translate(x, y); + ctx.moveTo(0, 0); + ctx.rotate(rot); + + x = 0; + while (len > x) { + x += da[di++ % dc]; + if (x > len) { + x = len; + } + ctx[draw ? 'lineTo' : 'moveTo'](x, 0); + draw = !draw; + } + + ctx.restore(); + }, + + /** + * Creates canvas element and initializes it via excanvas if necessary + * @static + * @memberOf fabric.util + * @param {CanvasElement} [canvasEl] optional canvas element to initialize; + * when not given, element is created implicitly + * @return {CanvasElement} initialized canvas element + */ + createCanvasElement: function(canvasEl) { + canvasEl || (canvasEl = fabric.document.createElement('canvas')); + if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') { + G_vmlCanvasManager.initElement(canvasEl); + } + return canvasEl; + }, + + /** + * Creates image element (works on client and node) + * @static + * @memberOf fabric.util + * @return {HTMLImageElement} HTML image element + */ + createImage: function() { + return fabric.isLikelyNode + ? new (require('canvas').Image)() + : fabric.document.createElement('img'); + }, + + /** + * Creates accessors (getXXX, setXXX) for a "class", based on "stateProperties" array + * @static + * @memberOf fabric.util + * @param {Object} klass "Class" to create accessors for + */ + createAccessors: function(klass) { + var proto = klass.prototype; + + for (var i = proto.stateProperties.length; i--; ) { + + var propName = proto.stateProperties[i], + capitalizedPropName = propName.charAt(0).toUpperCase() + propName.slice(1), + setterName = 'set' + capitalizedPropName, + getterName = 'get' + capitalizedPropName; + + // using `new Function` for better introspection + if (!proto[getterName]) { + proto[getterName] = (function(property) { + return new Function('return this.get("' + property + '")'); + })(propName); + } + if (!proto[setterName]) { + proto[setterName] = (function(property) { + return new Function('value', 'return this.set("' + property + '", value)'); + })(propName); + } + } + }, + + /** + * @static + * @memberOf fabric.util + * @param {fabric.Object} receiver Object implementing `clipTo` method + * @param {CanvasRenderingContext2D} ctx Context to clip + */ + clipContext: function(receiver, ctx) { + ctx.save(); + ctx.beginPath(); + receiver.clipTo(ctx); + ctx.clip(); + }, + + /** + * Multiply matrix A by matrix B to nest transformations + * @static + * @memberOf fabric.util + * @param {Array} matrixA First transformMatrix + * @param {Array} matrixB Second transformMatrix + * @return {Array} The product of the two transform matrices + */ + multiplyTransformMatrices: function(matrixA, matrixB) { + // Matrix multiply matrixA * matrixB + var a = [ + [matrixA[0], matrixA[2], matrixA[4]], + [matrixA[1], matrixA[3], matrixA[5]], + [0 , 0 , 1 ] + ]; + + var b = [ + [matrixB[0], matrixB[2], matrixB[4]], + [matrixB[1], matrixB[3], matrixB[5]], + [0 , 0 , 1 ] + ]; + + var result = []; + for (var r=0; r<3; r++) { + result[r] = []; + for (var c=0; c<3; c++) { + var sum = 0; + for (var k=0; k<3; k++) { + sum += a[r][k]*b[k][c]; + } + + result[r][c] = sum; + } + } + + return [ + result[0][0], + result[1][0], + result[0][1], + result[1][1], + result[0][2], + result[1][2] + ]; + }, + + /** + * Returns string representation of function body + * @param {Function} fn Function to get body of + * @return {String} Function body + */ + getFunctionBody: function(fn) { + return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1]; + }, + + /** + * Normalizes polygon/polyline points according to their dimensions + * @param {Array} points + * @param {Object} options + */ + normalizePoints: function(points, options) { + var minX = fabric.util.array.min(points, 'x'), + minY = fabric.util.array.min(points, 'y'); + + minX = minX < 0 ? minX : 0; + minY = minX < 0 ? minY : 0; + + for (var i = 0, len = points.length; i < len; i++) { + // normalize coordinates, according to containing box + // (dimensions of which are passed via `options`) + points[i].x -= (options.width / 2 + minX) || 0; + points[i].y -= (options.height / 2 + minY) || 0; + } + }, + + /** + * Returns true if context has transparent pixel + * at specified location (taking tolerance into account) + * @param {CanvasRenderingContext2D} ctx context + * @param {Number} x x coordinate + * @param {Number} y y coordinate + * @param {Number} tolerance Tolerance + */ + isTransparent: function(ctx, x, y, tolerance) { + + // If tolerance is > 0 adjust start coords to take into account. + // If moves off Canvas fix to 0 + if (tolerance > 0) { + if (x > tolerance) { + x -= tolerance; + } + else { + x = 0; + } + if (y > tolerance) { + y -= tolerance; + } + else { + y = 0; + } + } + + var _isTransparent = true; + var imageData = ctx.getImageData( + x, y, (tolerance * 2) || 1, (tolerance * 2) || 1); + + // Split image data - for tolerance > 1, pixelDataSize = 4; + for (var i = 3, l = imageData.data.length; i < l; i += 4) { + var temp = imageData.data[i]; + _isTransparent = temp <= 0; + if (_isTransparent === false) break; // Stop if colour found + } + + imageData = null; + + return _isTransparent; + } + }; + +})(typeof exports !== 'undefined' ? exports : this); +(function() { + + var arcToSegmentsCache = { }, + segmentToBezierCache = { }, + _join = Array.prototype.join, + argsString; + + // Generous contribution by Raph Levien, from libsvg-0.1.0.tar.gz + function arcToSegments(x, y, rx, ry, large, sweep, rotateX, ox, oy) { + + argsString = _join.call(arguments); + + if (arcToSegmentsCache[argsString]) { + return arcToSegmentsCache[argsString]; + } + + var coords = getXYCoords(rotateX, rx, ry, ox, oy, x, y); + + var d = (coords.x1-coords.x0) * (coords.x1-coords.x0) + + (coords.y1-coords.y0) * (coords.y1-coords.y0); + + var sfactor_sq = 1 / d - 0.25; + if (sfactor_sq < 0) sfactor_sq = 0; + + var sfactor = Math.sqrt(sfactor_sq); + if (sweep === large) sfactor = -sfactor; + + var xc = 0.5 * (coords.x0 + coords.x1) - sfactor * (coords.y1-coords.y0); + var yc = 0.5 * (coords.y0 + coords.y1) + sfactor * (coords.x1-coords.x0); + + var th0 = Math.atan2(coords.y0-yc, coords.x0-xc); + var th1 = Math.atan2(coords.y1-yc, coords.x1-xc); + + var th_arc = th1-th0; + if (th_arc < 0 && sweep === 1) { + th_arc += 2*Math.PI; + } + else if (th_arc > 0 && sweep === 0) { + th_arc -= 2 * Math.PI; + } + + var segments = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001))); + var result = []; + for (var i=0; i 1) { + pl = Math.sqrt(pl); + rx *= pl; + ry *= pl; + } + + var a00 = cos_th / rx; + var a01 = sin_th / rx; + var a10 = (-sin_th) / ry; + var a11 = (cos_th) / ry; + + return { + x0: a00 * ox + a01 * oy, + y0: a10 * ox + a11 * oy, + x1: a00 * x + a01 * y, + y1: a10 * x + a11 * y, + sin_th: sin_th, + cos_th: cos_th + }; + } + + function segmentToBezier(cx, cy, th0, th1, rx, ry, sin_th, cos_th) { + argsString = _join.call(arguments); + if (segmentToBezierCache[argsString]) { + return segmentToBezierCache[argsString]; + } + + var a00 = cos_th * rx; + var a01 = -sin_th * ry; + var a10 = sin_th * rx; + var a11 = cos_th * ry; + + var th_half = 0.5 * (th1 - th0); + var t = (8/3) * Math.sin(th_half * 0.5) * + Math.sin(th_half * 0.5) / Math.sin(th_half); + + var x1 = cx + Math.cos(th0) - t * Math.sin(th0); + var y1 = cy + Math.sin(th0) + t * Math.cos(th0); + var x3 = cx + Math.cos(th1); + var y3 = cy + Math.sin(th1); + var x2 = x3 + t * Math.sin(th1); + var y2 = y3 - t * Math.cos(th1); + + segmentToBezierCache[argsString] = [ + a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, + a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, + a00 * x3 + a01 * y3, a10 * x3 + a11 * y3 + ]; + + return segmentToBezierCache[argsString]; + } + + /** + * Draws arc + * @param {CanvasRenderingContext2D} ctx + * @param {Number} x + * @param {Number} y + * @param {Array} coords + */ + fabric.util.drawArc = function(ctx, x, y, coords) { + var rx = coords[0]; + var ry = coords[1]; + var rot = coords[2]; + var large = coords[3]; + var sweep = coords[4]; + var ex = coords[5]; + var ey = coords[6]; + var segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, x, y); + for (var i=0; i>> 0; + if (len === 0) { + return -1; + } + var n = 0; + if (arguments.length > 0) { + n = Number(arguments[1]); + if (n !== n) { // shortcut for verifying if it's NaN + n = 0; + } + else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + } + if (n >= len) { + return -1; + } + var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); + for (; k < len; k++) { + if (k in t && t[k] === searchElement) { + return k; + } + } + return -1; + }; + } + + if (!Array.prototype.forEach) { + /** + * Iterates an array, invoking callback for each element + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.forEach = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + fn.call(context, this[i], i, this); + } + } + }; + } + + if (!Array.prototype.map) { + /** + * Returns a result of iterating over an array, invoking callback for each element + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.map = function(fn, context) { + var result = [ ]; + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + result[i] = fn.call(context, this[i], i, this); + } + } + return result; + }; + } + + if (!Array.prototype.every) { + /** + * Returns true if a callback returns truthy value for all elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Boolean} + */ + Array.prototype.every = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this && !fn.call(context, this[i], i, this)) { + return false; + } + } + return true; + }; + } + + if (!Array.prototype.some) { + /** + * Returns true if a callback returns truthy value for at least one element in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Boolean} + */ + Array.prototype.some = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this && fn.call(context, this[i], i, this)) { + return true; + } + } + return false; + }; + } + + if (!Array.prototype.filter) { + /** + * Returns the result of iterating over elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.filter = function(fn, context) { + var result = [ ], val; + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + val = this[i]; // in case fn mutates this + if (fn.call(context, val, i, this)) { + result.push(val); + } + } + } + return result; + }; + } + + if (!Array.prototype.reduce) { + /** + * Returns "folded" (reduced) result of iterating over elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Any} + */ + Array.prototype.reduce = function(fn /*, initial*/) { + var len = this.length >>> 0, + i = 0, + rv; + + if (arguments.length > 1) { + rv = arguments[1]; + } + else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) { + throw new TypeError(); + } + } + while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fn.call(null, rv, this[i], i, this); + } + } + return rv; + }; + } + + /* _ES5_COMPAT_END_ */ + + /** + * Invokes method on all items in a given array + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} method Name of a method to invoke + * @return {Array} + */ + function invoke(array, method) { + var args = slice.call(arguments, 2), result = [ ]; + for (var i = 0, len = array.length; i < len; i++) { + result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]); + } + return result; + } + + /** + * Finds maximum value in array (not necessarily "first" one) + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} byProperty + * @return {Any} + */ + function max(array, byProperty) { + return find(array, byProperty, function(value1, value2) { + return value1 >= value2; + }); + } + + /** + * Finds minimum value in array (not necessarily "first" one) + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} byProperty + * @return {Any} + */ + function min(array, byProperty) { + return find(array, byProperty, function(value1, value2) { + return value1 < value2; + }); + } + + /** + * @private + */ + function find(array, byProperty, condition) { + if (!array || array.length === 0) return undefined; + + var i = array.length - 1, + result = byProperty ? array[i][byProperty] : array[i]; + if (byProperty) { + while (i--) { + if (condition(array[i][byProperty], result)) { + result = array[i][byProperty]; + } + } + } + else { + while (i--) { + if (condition(array[i], result)) { + result = array[i]; + } + } + } + return result; + } + + /** + * @namespace fabric.util.array + */ + fabric.util.array = { + invoke: invoke, + min: min, + max: max + }; + +})(); +(function(){ + + /** + * Copies all enumerable properties of one object to another + * @memberOf fabric.util.object + * @param {Object} destination Where to copy to + * @param {Object} source Where to copy from + * @return {Object} + */ + function extend(destination, source) { + // JScript DontEnum bug is not taken care of + for (var property in source) { + destination[property] = source[property]; + } + return destination; + } + + /** + * Creates an empty object and copies all enumerable properties of another object to it + * @memberOf fabric.util.object + * @param {Object} object Object to clone + * @return {Object} + */ + function clone(object) { + return extend({ }, object); + } + + /** @namespace fabric.util.object */ + fabric.util.object = { + extend: extend, + clone: clone + }; + +})(); +(function() { + +/* _ES5_COMPAT_START_ */ +if (!String.prototype.trim) { + /** + * Trims a string (removing whitespace from the beginning and the end) + * @function external:String#trim + * @see String#trim on MDN + */ + String.prototype.trim = function () { + // this trim is not fully ES3 or ES5 compliant, but it should cover most cases for now + return this.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, ''); + }; +} +/* _ES5_COMPAT_END_ */ + +/** + * Camelizes a string + * @memberOf fabric.util.string + * @param {String} string String to camelize + * @return {String} Camelized version of a string + */ +function camelize(string) { + return string.replace(/-+(.)?/g, function(match, character) { + return character ? character.toUpperCase() : ''; + }); +} + +/** + * Capitalizes a string + * @memberOf fabric.util.string + * @param {String} string String to capitalize + * @param {Boolean} [firstLetterOnly] If true only first letter is capitalized + * and other letters stay untouched, if false first letter is capitalized + * and other letters are converted to lowercase. + * @return {String} Capitalized version of a string + */ +function capitalize(string, firstLetterOnly) { + return string.charAt(0).toUpperCase() + + (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()); +} + +/** + * Escapes XML in a string + * @memberOf fabric.util.string + * @param {String} string String to escape + * @return {String} Escaped version of a string + */ +function escapeXml(string) { + return string.replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); +} + +/** + * String utilities + * @namespace fabric.util.string + */ +fabric.util.string = { + camelize: camelize, + capitalize: capitalize, + escapeXml: escapeXml +}; +}()); +/* _ES5_COMPAT_START_ */ +(function() { + + var slice = Array.prototype.slice, + apply = Function.prototype.apply, + Dummy = function() { }; + + if (!Function.prototype.bind) { + /** + * Cross-browser approximation of ES5 Function.prototype.bind (not fully spec conforming) + * @see Function#bind on MDN + * @param {Object} thisArg Object to bind function to + * @param {Any[]} [...] Values to pass to a bound function + * @return {Function} + */ + Function.prototype.bind = function(thisArg) { + var fn = this, args = slice.call(arguments, 1), bound; + if (args.length) { + bound = function() { + return apply.call(fn, this instanceof Dummy ? this : thisArg, args.concat(slice.call(arguments))); + }; + } + else { + /** @ignore */ + bound = function() { + return apply.call(fn, this instanceof Dummy ? this : thisArg, arguments); + }; + } + Dummy.prototype = this.prototype; + bound.prototype = new Dummy(); + + return bound; + }; + } + +})(); +/* _ES5_COMPAT_END_ */ +(function() { + + var slice = Array.prototype.slice, emptyFunction = function() { }; + + var IS_DONTENUM_BUGGY = (function(){ + for (var p in { toString: 1 }) { + if (p === 'toString') return false; + } + return true; + })(); + + /** @ignore */ + var addMethods = function(klass, source, parent) { + for (var property in source) { + + if (property in klass.prototype && + typeof klass.prototype[property] === 'function' && + (source[property] + '').indexOf('callSuper') > -1) { + + klass.prototype[property] = (function(property) { + return function() { + + var superclass = this.constructor.superclass; + this.constructor.superclass = parent; + var returnValue = source[property].apply(this, arguments); + this.constructor.superclass = superclass; + + if (property !== 'initialize') { + return returnValue; + } + }; + })(property); + } + else { + klass.prototype[property] = source[property]; + } + + if (IS_DONTENUM_BUGGY) { + if (source.toString !== Object.prototype.toString) { + klass.prototype.toString = source.toString; + } + if (source.valueOf !== Object.prototype.valueOf) { + klass.prototype.valueOf = source.valueOf; + } + } + } + }; + + function Subclass() { } + + function callSuper(methodName) { + var fn = this.constructor.superclass.prototype[methodName]; + return (arguments.length > 1) + ? fn.apply(this, slice.call(arguments, 1)) + : fn.call(this); + } + + /** + * Helper for creation of "classes". + * @memberOf fabric.util + * @param parent optional "Class" to inherit from + * @param properties Properties shared by all instances of this class + * (be careful modifying objects defined here as this would affect all instances) + */ + function createClass() { + var parent = null, + properties = slice.call(arguments, 0); + + if (typeof properties[0] === 'function') { + parent = properties.shift(); + } + function klass() { + this.initialize.apply(this, arguments); + } + + klass.superclass = parent; + klass.subclasses = [ ]; + + if (parent) { + Subclass.prototype = parent.prototype; + klass.prototype = new Subclass(); + parent.subclasses.push(klass); + } + for (var i = 0, length = properties.length; i < length; i++) { + addMethods(klass, properties[i], parent); + } + if (!klass.prototype.initialize) { + klass.prototype.initialize = emptyFunction; + } + klass.prototype.constructor = klass; + klass.prototype.callSuper = callSuper; + return klass; + } + + fabric.util.createClass = createClass; +})(); +(function () { + + var unknown = 'unknown'; + + /* EVENT HANDLING */ + + function areHostMethods(object) { + var methodNames = Array.prototype.slice.call(arguments, 1), + t, i, len = methodNames.length; + for (i = 0; i < len; i++) { + t = typeof object[methodNames[i]]; + if (!(/^(?:function|object|unknown)$/).test(t)) return false; + } + return true; + } + var getUniqueId = (function () { + var uid = 0; + return function (element) { + return element.__uniqueID || (element.__uniqueID = 'uniqueID__' + uid++); + }; + })(); + + /** @ignore */ + var getElement, setElement; + + (function () { + var elements = { }; + /** @ignore */ + getElement = function (uid) { + return elements[uid]; + }; + /** @ignore */ + setElement = function (uid, element) { + elements[uid] = element; + }; + })(); + + function createListener(uid, handler) { + return { + handler: handler, + wrappedHandler: createWrappedHandler(uid, handler) + }; + } + + function createWrappedHandler(uid, handler) { + return function (e) { + handler.call(getElement(uid), e || fabric.window.event); + }; + } + + function createDispatcher(uid, eventName) { + return function (e) { + if (handlers[uid] && handlers[uid][eventName]) { + var handlersForEvent = handlers[uid][eventName]; + for (var i = 0, len = handlersForEvent.length; i < len; i++) { + handlersForEvent[i].call(this, e || fabric.window.event); + } + } + }; + } + + var shouldUseAddListenerRemoveListener = ( + areHostMethods(fabric.document.documentElement, 'addEventListener', 'removeEventListener') && + areHostMethods(fabric.window, 'addEventListener', 'removeEventListener')), + + shouldUseAttachEventDetachEvent = ( + areHostMethods(fabric.document.documentElement, 'attachEvent', 'detachEvent') && + areHostMethods(fabric.window, 'attachEvent', 'detachEvent')), + + // IE branch + listeners = { }, + + // DOM L0 branch + handlers = { }, + + addListener, removeListener; + + if (shouldUseAddListenerRemoveListener) { + /** @ignore */ + addListener = function (element, eventName, handler) { + element.addEventListener(eventName, handler, false); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + element.removeEventListener(eventName, handler, false); + }; + } + + else if (shouldUseAttachEventDetachEvent) { + /** @ignore */ + addListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + setElement(uid, element); + if (!listeners[uid]) { + listeners[uid] = { }; + } + if (!listeners[uid][eventName]) { + listeners[uid][eventName] = [ ]; + + } + var listener = createListener(uid, handler); + listeners[uid][eventName].push(listener); + element.attachEvent('on' + eventName, listener.wrappedHandler); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + var uid = getUniqueId(element), listener; + if (listeners[uid] && listeners[uid][eventName]) { + for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) { + listener = listeners[uid][eventName][i]; + if (listener && listener.handler === handler) { + element.detachEvent('on' + eventName, listener.wrappedHandler); + listeners[uid][eventName][i] = null; + } + } + } + }; + } + else { + /** @ignore */ + addListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + if (!handlers[uid]) { + handlers[uid] = { }; + } + if (!handlers[uid][eventName]) { + handlers[uid][eventName] = [ ]; + var existingHandler = element['on' + eventName]; + if (existingHandler) { + handlers[uid][eventName].push(existingHandler); + } + element['on' + eventName] = createDispatcher(uid, eventName); + } + handlers[uid][eventName].push(handler); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + if (handlers[uid] && handlers[uid][eventName]) { + var handlersForEvent = handlers[uid][eventName]; + for (var i = 0, len = handlersForEvent.length; i < len; i++) { + if (handlersForEvent[i] === handler) { + handlersForEvent.splice(i, 1); + } + } + } + }; + } + + /** + * Adds an event listener to an element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {String} eventName + * @param {Function} handler + */ + fabric.util.addListener = addListener; + + /** + * Removes an event listener from an element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {String} eventName + * @param {Function} handler + */ + fabric.util.removeListener = removeListener; + + /** + * Cross-browser wrapper for getting event's coordinates + * @memberOf fabric.util + * @param {Event} event Event object + * @param {HTMLCanvasElement} upperCanvasEl <canvas> element on which object selection is drawn + */ + function getPointer(event, upperCanvasEl) { + event || (event = fabric.window.event); + + var element = event.target || + (typeof event.srcElement !== unknown ? event.srcElement : null); + + var scroll = fabric.util.getScrollLeftTop(element, upperCanvasEl); + + return { + x: pointerX(event) + scroll.left, + y: pointerY(event) + scroll.top + }; + } + + var pointerX = function(event) { + // looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element) + // is represented as COM object, with all the consequences, like "unknown" type and error on [[Get]] + // need to investigate later + return (typeof event.clientX !== unknown ? event.clientX : 0); + }; + + var pointerY = function(event) { + return (typeof event.clientY !== unknown ? event.clientY : 0); + }; + + function _getPointer(event, pageProp, clientProp) { + var touchProp = event.type === 'touchend' ? 'changedTouches' : 'touches'; + + return (event[touchProp] && event[touchProp][0] + ? (event[touchProp][0][pageProp] - (event[touchProp][0][pageProp] - event[touchProp][0][clientProp])) + || event[clientProp] + : event[clientProp]); + } + + if (fabric.isTouchSupported) { + pointerX = function(event) { + return _getPointer(event, 'pageX', 'clientX'); + }; + pointerY = function(event) { + return _getPointer(event, 'pageY', 'clientY'); + }; + } + + fabric.util.getPointer = getPointer; + + fabric.util.object.extend(fabric.util, fabric.Observable); + +})(); +(function () { + + /** + * Cross-browser wrapper for setting element's style + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {Object} styles + * @return {HTMLElement} Element that was passed as a first argument + */ + function setStyle(element, styles) { + var elementStyle = element.style; + if (!elementStyle) { + return element; + } + if (typeof styles === 'string') { + element.style.cssText += ';' + styles; + return styles.indexOf('opacity') > -1 + ? setOpacity(element, styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) + : element; + } + for (var property in styles) { + if (property === 'opacity') { + setOpacity(element, styles[property]); + } + else { + var normalizedProperty = (property === 'float' || property === 'cssFloat') + ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat') + : property; + elementStyle[normalizedProperty] = styles[property]; + } + } + return element; + } + + var parseEl = fabric.document.createElement('div'), + supportsOpacity = typeof parseEl.style.opacity === 'string', + supportsFilters = typeof parseEl.style.filter === 'string', + reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/, + + /** @ignore */ + setOpacity = function (element) { return element; }; + + if (supportsOpacity) { + /** @ignore */ + setOpacity = function(element, value) { + element.style.opacity = value; + return element; + }; + } + else if (supportsFilters) { + /** @ignore */ + setOpacity = function(element, value) { + var es = element.style; + if (element.currentStyle && !element.currentStyle.hasLayout) { + es.zoom = 1; + } + if (reOpacity.test(es.filter)) { + value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')'); + es.filter = es.filter.replace(reOpacity, value); + } + else { + es.filter += ' alpha(opacity=' + (value * 100) + ')'; + } + return element; + }; + } + + fabric.util.setStyle = setStyle; + +})(); +(function() { + + var _slice = Array.prototype.slice; + + /** + * Takes id and returns an element with that id (if one exists in a document) + * @memberOf fabric.util + * @param {String|HTMLElement} id + * @return {HTMLElement|null} + */ + function getById(id) { + return typeof id === 'string' ? fabric.document.getElementById(id) : id; + } + + /** + * Converts an array-like object (e.g. arguments or NodeList) to an array + * @memberOf fabric.util + * @param {Object} arrayLike + * @return {Array} + */ + var toArray = function(arrayLike) { + return _slice.call(arrayLike, 0); + }; + + var sliceCanConvertNodelists; + try { + sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array; + } + catch(err) { } + + if (!sliceCanConvertNodelists) { + toArray = function(arrayLike) { + var arr = new Array(arrayLike.length), i = arrayLike.length; + while (i--) { + arr[i] = arrayLike[i]; + } + return arr; + }; + } + + /** + * Creates specified element with specified attributes + * @memberOf fabric.util + * @param {String} tagName Type of an element to create + * @param {Object} [attributes] Attributes to set on an element + * @return {HTMLElement} Newly created element + */ + function makeElement(tagName, attributes) { + var el = fabric.document.createElement(tagName); + for (var prop in attributes) { + if (prop === 'class') { + el.className = attributes[prop]; + } + else if (prop === 'for') { + el.htmlFor = attributes[prop]; + } + else { + el.setAttribute(prop, attributes[prop]); + } + } + return el; + } + + /** + * Adds class to an element + * @memberOf fabric.util + * @param {HTMLElement} element Element to add class to + * @param {String} className Class to add to an element + */ + function addClass(element, className) { + if ((' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) { + element.className += (element.className ? ' ' : '') + className; + } + } + + /** + * Wraps element with another element + * @memberOf fabric.util + * @param {HTMLElement} element Element to wrap + * @param {HTMLElement|String} wrapper Element to wrap with + * @param {Object} [attributes] Attributes to set on a wrapper + * @return {HTMLElement} wrapper + */ + function wrapElement(element, wrapper, attributes) { + if (typeof wrapper === 'string') { + wrapper = makeElement(wrapper, attributes); + } + if (element.parentNode) { + element.parentNode.replaceChild(wrapper, element); + } + wrapper.appendChild(element); + return wrapper; + } + + function getScrollLeftTop(element, upperCanvasEl) { + + var firstFixedAncestor, + origElement, + left = 0, + top = 0, + docElement = fabric.document.documentElement, + body = fabric.document.body || { + scrollLeft: 0, scrollTop: 0 + }; + + origElement = element; + + while (element && element.parentNode && !firstFixedAncestor) { + + element = element.parentNode; + + if (element !== fabric.document && + fabric.util.getElementStyle(element, 'position') === 'fixed') { + firstFixedAncestor = element; + } + + if (element !== fabric.document && + origElement !== upperCanvasEl && + fabric.util.getElementStyle(element, 'position') === 'absolute') { + left = 0; + top = 0; + } + else if (element === fabric.document) { + left = body.scrollLeft || docElement.scrollLeft || 0; + top = body.scrollTop || docElement.scrollTop || 0; + } + else { + left += element.scrollLeft || 0; + top += element.scrollTop || 0; + } + } + + return { left: left, top: top }; + } + + /** + * Returns offset for a given element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element Element to get offset for + * @return {Object} Object with "left" and "top" properties + */ + function getElementOffset(element) { + var docElem, + box = {left: 0, top: 0}, + doc = element && element.ownerDocument, + offset = {left: 0, top: 0}, + scrollLeftTop, + offsetAttributes = { + 'borderLeftWidth': 'left', + 'borderTopWidth': 'top', + 'paddingLeft': 'left', + 'paddingTop': 'top' + }; + + if (!doc){ + return {left: 0, top: 0}; + } + + for (var attr in offsetAttributes) { + offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0; + } + + docElem = doc.documentElement; + if ( typeof element.getBoundingClientRect !== "undefined" ) { + box = element.getBoundingClientRect(); + } + + scrollLeftTop = fabric.util.getScrollLeftTop(element, null); + + return { + left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left, + top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top + }; + } + + /** + * Returns style attribute value of a given element + * @memberOf fabric.util + * @param {HTMLElement} element Element to get style attribute for + * @param {String} attr Style attribute to get for element + * @return {String} Style attribute value of the given element. + */ + function getElementStyle(element, attr) { + if (!element.style) { + element.style = { }; + } + + if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) { + return fabric.document.defaultView.getComputedStyle(element, null)[attr]; + } + else { + var value = element.style[attr]; + if (!value && element.currentStyle) value = element.currentStyle[attr]; + return value; + } + } + + (function () { + var style = fabric.document.documentElement.style; + + var selectProp = 'userSelect' in style + ? 'userSelect' + : 'MozUserSelect' in style + ? 'MozUserSelect' + : 'WebkitUserSelect' in style + ? 'WebkitUserSelect' + : 'KhtmlUserSelect' in style + ? 'KhtmlUserSelect' + : ''; + + /** + * Makes element unselectable + * @memberOf fabric.util + * @param {HTMLElement} element Element to make unselectable + * @return {HTMLElement} Element that was passed in + */ + function makeElementUnselectable(element) { + if (typeof element.onselectstart !== 'undefined') { + element.onselectstart = fabric.util.falseFunction; + } + if (selectProp) { + element.style[selectProp] = 'none'; + } + else if (typeof element.unselectable === 'string') { + element.unselectable = 'on'; + } + return element; + } + + /** + * Makes element selectable + * @memberOf fabric.util + * @param {HTMLElement} element Element to make selectable + * @return {HTMLElement} Element that was passed in + */ + function makeElementSelectable(element) { + if (typeof element.onselectstart !== 'undefined') { + element.onselectstart = null; + } + if (selectProp) { + element.style[selectProp] = ''; + } + else if (typeof element.unselectable === 'string') { + element.unselectable = ''; + } + return element; + } + + fabric.util.makeElementUnselectable = makeElementUnselectable; + fabric.util.makeElementSelectable = makeElementSelectable; + })(); + + (function() { + + /** + * Inserts a script element with a given url into a document; invokes callback, when that script is finished loading + * @memberOf fabric.util + * @param {String} url URL of a script to load + * @param {Function} callback Callback to execute when script is finished loading + */ + function getScript(url, callback) { + var headEl = fabric.document.getElementsByTagName("head")[0], + scriptEl = fabric.document.createElement('script'), + loading = true; + + /** @ignore */ + scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) { + if (loading) { + if (typeof this.readyState === 'string' && + this.readyState !== 'loaded' && + this.readyState !== 'complete') return; + loading = false; + callback(e || fabric.window.event); + scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null; + } + }; + scriptEl.src = url; + headEl.appendChild(scriptEl); + // causes issue in Opera + // headEl.removeChild(scriptEl); + } + + fabric.util.getScript = getScript; + })(); + + fabric.util.getById = getById; + fabric.util.toArray = toArray; + fabric.util.makeElement = makeElement; + fabric.util.addClass = addClass; + fabric.util.wrapElement = wrapElement; + fabric.util.getScrollLeftTop = getScrollLeftTop; + fabric.util.getElementOffset = getElementOffset; + fabric.util.getElementStyle = getElementStyle; + +})(); +(function(){ + + function addParamToUrl(url, param) { + return url + (/\?/.test(url) ? '&' : '?') + param; + } + + var makeXHR = (function() { + var factories = [ + function() { return new ActiveXObject("Microsoft.XMLHTTP"); }, + function() { return new ActiveXObject("Msxml2.XMLHTTP"); }, + function() { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }, + function() { return new XMLHttpRequest(); } + ]; + for (var i = factories.length; i--; ) { + try { + var req = factories[i](); + if (req) { + return factories[i]; + } + } + catch (err) { } + } + })(); + + function emptyFn() { } + + /** + * Cross-browser abstraction for sending XMLHttpRequest + * @memberOf fabric.util + * @param {String} url URL to send XMLHttpRequest to + * @param {Object} [options] Options object + * @param {String} [options.method="GET"] + * @param {Function} options.onComplete Callback to invoke when request is completed + * @return {XMLHttpRequest} request + */ + function request(url, options) { + + options || (options = { }); + + var method = options.method ? options.method.toUpperCase() : 'GET', + onComplete = options.onComplete || function() { }, + xhr = makeXHR(), + body; + + /** @ignore */ + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + onComplete(xhr); + xhr.onreadystatechange = emptyFn; + } + }; + + if (method === 'GET') { + body = null; + if (typeof options.parameters === 'string') { + url = addParamToUrl(url, options.parameters); + } + } + + xhr.open(method, url, true); + + if (method === 'POST' || method === 'PUT') { + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + } + + xhr.send(body); + return xhr; + } + + fabric.util.request = request; +})(); +/** + * Wrapper around `console.log` (when available) + * @param {Any} values Values to log + */ +fabric.log = function() { }; + +/** + * Wrapper around `console.warn` (when available) + * @param {Any} Values to log as a warning + */ +fabric.warn = function() { }; + +if (typeof console !== 'undefined') { + ['log', 'warn'].forEach(function(methodName) { + if (typeof console[methodName] !== 'undefined' && console[methodName].apply) { + fabric[methodName] = function() { + return console[methodName].apply(console, arguments); + }; + } + }); +} +(function(global) { + + "use strict"; + + /** + * @name fabric + * @namespace + */ + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + capitalize = fabric.util.string.capitalize, + clone = fabric.util.object.clone, + toFixed = fabric.util.toFixed, + multiplyTransformMatrices = fabric.util.multiplyTransformMatrices; + + var attributesMap = { + 'fill-opacity': 'fillOpacity', + 'fill-rule': 'fillRule', + 'font-family': 'fontFamily', + 'font-size': 'fontSize', + 'font-style': 'fontStyle', + 'font-weight': 'fontWeight', + 'cx': 'left', + 'x': 'left', + 'r': 'radius', + 'stroke-dasharray': 'strokeDashArray', + 'stroke-linecap': 'strokeLineCap', + 'stroke-linejoin': 'strokeLineJoin', + 'stroke-miterlimit':'strokeMiterLimit', + 'stroke-opacity': 'strokeOpacity', + 'stroke-width': 'strokeWidth', + 'text-decoration': 'textDecoration', + 'cy': 'top', + 'y': 'top', + 'transform': 'transformMatrix' + }; + + var colorAttributes = { + 'stroke': 'strokeOpacity', + 'fill': 'fillOpacity' + }; + + function normalizeAttr(attr) { + // transform attribute names + if (attr in attributesMap) { + return attributesMap[attr]; + } + return attr; + } + + function normalizeValue(attr, value, parentAttributes) { + var isArray; + + if ((attr === 'fill' || attr === 'stroke') && value === 'none') { + value = ''; + } + else if (attr === 'fillRule') { + value = (value === 'evenodd') ? 'destination-over' : value; + } + else if (attr === 'strokeDashArray') { + value = value.replace(/,/g, ' ').split(/\s+/); + } + else if (attr === 'transformMatrix') { + if (parentAttributes && parentAttributes.transformMatrix) { + value = multiplyTransformMatrices( + parentAttributes.transformMatrix, fabric.parseTransformAttribute(value)); + } + else { + value = fabric.parseTransformAttribute(value); + } + } + + isArray = Object.prototype.toString.call(value) === '[object Array]'; + + // TODO: need to normalize em, %, pt, etc. to px (!) + var parsed = isArray ? value.map(parseFloat) : parseFloat(value); + + return (!isArray && isNaN(parsed) ? value : parsed); + } + + /** + * @private + * @param {Object} attributes Array of attributes to parse + */ + function _setStrokeFillOpacity(attributes) { + for (var attr in colorAttributes) { + + if (!attributes[attr] || typeof attributes[colorAttributes[attr]] === 'undefined') continue; + + if (attributes[attr].indexOf('url(') === 0) continue; + + var color = new fabric.Color(attributes[attr]); + attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba(); + + delete attributes[colorAttributes[attr]]; + } + return attributes; + } + + /** + * Parses "transform" attribute, returning an array of values + * @static + * @function + * @memberOf fabric + * @param {String} attributeValue String containing attribute value + * @return {Array} Array of 6 elements representing transformation matrix + */ + fabric.parseTransformAttribute = (function() { + function rotateMatrix(matrix, args) { + var angle = args[0]; + + matrix[0] = Math.cos(angle); + matrix[1] = Math.sin(angle); + matrix[2] = -Math.sin(angle); + matrix[3] = Math.cos(angle); + } + + function scaleMatrix(matrix, args) { + var multiplierX = args[0], + multiplierY = (args.length === 2) ? args[1] : args[0]; + + matrix[0] = multiplierX; + matrix[3] = multiplierY; + } + + function skewXMatrix(matrix, args) { + matrix[2] = args[0]; + } + + function skewYMatrix(matrix, args) { + matrix[1] = args[0]; + } + + function translateMatrix(matrix, args) { + matrix[4] = args[0]; + if (args.length === 2) { + matrix[5] = args[1]; + } + } + + // identity matrix + var iMatrix = [ + 1, // a + 0, // b + 0, // c + 1, // d + 0, // e + 0 // f + ], + + // == begin transform regexp + number = '(?:[-+]?\\d+(?:\\.\\d+)?(?:e[-+]?\\d+)?)', + + comma_wsp = '(?:\\s+,?\\s*|,\\s*)', + + skewX = '(?:(skewX)\\s*\\(\\s*(' + number + ')\\s*\\))', + + skewY = '(?:(skewY)\\s*\\(\\s*(' + number + ')\\s*\\))', + + rotate = '(?:(rotate)\\s*\\(\\s*(' + number + ')(?:' + + comma_wsp + '(' + number + ')' + + comma_wsp + '(' + number + '))?\\s*\\))', + + scale = '(?:(scale)\\s*\\(\\s*(' + number + ')(?:' + + comma_wsp + '(' + number + '))?\\s*\\))', + + translate = '(?:(translate)\\s*\\(\\s*(' + number + ')(?:' + + comma_wsp + '(' + number + '))?\\s*\\))', + + matrix = '(?:(matrix)\\s*\\(\\s*' + + '(' + number + ')' + comma_wsp + + '(' + number + ')' + comma_wsp + + '(' + number + ')' + comma_wsp + + '(' + number + ')' + comma_wsp + + '(' + number + ')' + comma_wsp + + '(' + number + ')' + + '\\s*\\))', + + transform = '(?:' + + matrix + '|' + + translate + '|' + + scale + '|' + + rotate + '|' + + skewX + '|' + + skewY + + ')', + + transforms = '(?:' + transform + '(?:' + comma_wsp + transform + ')*' + ')', + + transform_list = '^\\s*(?:' + transforms + '?)\\s*$', + + // http://www.w3.org/TR/SVG/coords.html#TransformAttribute + reTransformList = new RegExp(transform_list), + // == end transform regexp + + reTransform = new RegExp(transform, 'g'); + + return function(attributeValue) { + + // start with identity matrix + var matrix = iMatrix.concat(); + var matrices = [ ]; + + // return if no argument was given or + // an argument does not match transform attribute regexp + if (!attributeValue || (attributeValue && !reTransformList.test(attributeValue))) { + return matrix; + } + + attributeValue.replace(reTransform, function(match) { + + var m = new RegExp(transform).exec(match).filter(function (match) { + return (match !== '' && match != null); + }), + operation = m[1], + args = m.slice(2).map(parseFloat); + + switch(operation) { + case 'translate': + translateMatrix(matrix, args); + break; + case 'rotate': + rotateMatrix(matrix, args); + break; + case 'scale': + scaleMatrix(matrix, args); + break; + case 'skewX': + skewXMatrix(matrix, args); + break; + case 'skewY': + skewYMatrix(matrix, args); + break; + case 'matrix': + matrix = args; + break; + } + + // snapshot current matrix into matrices array + matrices.push(matrix.concat()); + // reset + matrix = iMatrix.concat(); + }); + + var combinedMatrix = matrices[0]; + while (matrices.length > 1) { + matrices.shift(); + combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]); + } + return combinedMatrix; + }; + })(); + + function parseFontDeclaration(value, oStyle) { + + // TODO: support non-px font size + var match = value.match(/(normal|italic)?\s*(normal|small-caps)?\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\s*(\d+)px(?:\/(normal|[\d\.]+))?\s+(.*)/); + + if (!match) return; + + var fontStyle = match[1]; + // Font variant is not used + // var fontVariant = match[2]; + var fontWeight = match[3]; + var fontSize = match[4]; + var lineHeight = match[5]; + var fontFamily = match[6]; + + if (fontStyle) { + oStyle.fontStyle = fontStyle; + } + if (fontWeight) { + oStyle.fontSize = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight); + } + if (fontSize) { + oStyle.fontSize = parseFloat(fontSize); + } + if (fontFamily) { + oStyle.fontFamily = fontFamily; + } + if (lineHeight) { + oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight; + } + } + + /** + * @private + */ + function parseStyleString(style, oStyle) { + var attr, value; + style.replace(/;$/, '').split(';').forEach(function (chunk) { + var pair = chunk.split(':'); + + attr = normalizeAttr(pair[0].trim().toLowerCase()); + value = normalizeValue(attr, pair[1].trim()); + + if (attr === 'font') { + parseFontDeclaration(value, oStyle); + } + else { + oStyle[attr] = value; + } + }); + } + + /** + * @private + */ + function parseStyleObject(style, oStyle) { + var attr, value; + for (var prop in style) { + if (typeof style[prop] === 'undefined') continue; + + attr = normalizeAttr(prop.toLowerCase()); + value = normalizeValue(attr, style[prop]); + + if (attr === 'font') { + parseFontDeclaration(value, oStyle); + } + else { + oStyle[attr] = value; + } + } + } + + /** + * @private + */ + function getGlobalStylesForElement(element) { + var nodeName = element.nodeName, + className = element.getAttribute('class'), + id = element.getAttribute('id'), + styles = { }; + + for (var rule in fabric.cssRules) { + var ruleMatchesElement = (className && new RegExp('^\\.' + className).test(rule)) || + (id && new RegExp('^#' + id).test(rule)) || + (new RegExp('^' + nodeName).test(rule)); + + if (ruleMatchesElement) { + for (var property in fabric.cssRules[rule]) { + styles[property] = fabric.cssRules[rule][property]; + } + } + } + + return styles; + } + + /** + * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @param {Function} callback Callback to call when parsing is finished; It's being passed an array of elements (parsed from a document). + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + fabric.parseSVGDocument = (function() { + + var reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/; + + // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute + // \d doesn't quite cut it (as we need to match an actual float number) + + // matches, e.g.: +14.56e-12, etc. + var reNum = '(?:[-+]?\\d+(?:\\.\\d+)?(?:e[-+]?\\d+)?)'; + + var reViewBoxAttrValue = new RegExp( + '^' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*' + + '$' + ); + + function hasAncestorWithNodeName(element, nodeName) { + while (element && (element = element.parentNode)) { + if (nodeName.test(element.nodeName)) { + return true; + } + } + return false; + } + + return function(doc, callback, reviver) { + if (!doc) return; + + var startTime = new Date(), + descendants = fabric.util.toArray(doc.getElementsByTagName('*')); + + if (descendants.length === 0) { + // we're likely in node, where "o3-xml" library fails to gEBTN("*") + // https://github.com/ajaxorg/node-o3-xml/issues/21 + descendants = doc.selectNodes("//*[name(.)!='svg']"); + var arr = [ ]; + for (var i = 0, len = descendants.length; i < len; i++) { + arr[i] = descendants[i]; + } + descendants = arr; + } + + var elements = descendants.filter(function(el) { + return reAllowedSVGTagNames.test(el.tagName) && + !hasAncestorWithNodeName(el, /^(?:pattern|defs)$/); // http://www.w3.org/TR/SVG/struct.html#DefsElement + }); + + if (!elements || (elements && !elements.length)) return; + + var viewBoxAttr = doc.getAttribute('viewBox'), + widthAttr = doc.getAttribute('width'), + heightAttr = doc.getAttribute('height'), + width = null, + height = null, + minX, + minY; + + if (viewBoxAttr && (viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))) { + minX = parseInt(viewBoxAttr[1], 10); + minY = parseInt(viewBoxAttr[2], 10); + width = parseInt(viewBoxAttr[3], 10); + height = parseInt(viewBoxAttr[4], 10); + } + + // values of width/height attributes overwrite those extracted from viewbox attribute + width = widthAttr ? parseFloat(widthAttr) : width; + height = heightAttr ? parseFloat(heightAttr) : height; + + var options = { + width: width, + height: height + }; + + fabric.gradientDefs = fabric.getGradientDefs(doc); + fabric.cssRules = fabric.getCSSRules(doc); + + // Precedence of rules: style > class > attribute + + fabric.parseElements(elements, function(instances) { + fabric.documentParsingTime = new Date() - startTime; + if (callback) { + callback(instances, options); + } + }, clone(options), reviver); + }; + })(); + + /** + * Used for caching SVG documents (loaded via `fabric.Canvas#loadSVGFromURL`) + * @namespace + */ + var svgCache = { + + /** + * @param {String} name + * @param {Function} callback + */ + has: function (name, callback) { + callback(false); + }, + + /** + * @param {String} url + * @param {Function} callback + */ + get: function () { + /* NOOP */ + }, + + /** + * @param {String} url + * @param {Object} object + */ + set: function () { + /* NOOP */ + } + }; + + /** + * @private + */ + function _enlivenCachedObject(cachedObject) { + + var objects = cachedObject.objects, + options = cachedObject.options; + + objects = objects.map(function (o) { + return fabric[capitalize(o.type)].fromObject(o); + }); + + return ({ objects: objects, options: options }); + } + + /** + * @private + */ + function _createSVGPattern(markup, canvas, property) { + if (canvas[property] && canvas[property].toSVG) { + markup.push( + '', + '' + ); + } + } + + extend(fabric, { + + /** + * Initializes gradients on instances, according to gradients parsed from a document + * @param {Array} instances + */ + resolveGradients: function(instances) { + for (var i = instances.length; i--; ) { + var instanceFillValue = instances[i].get('fill'); + + if (!(/^url\(/).test(instanceFillValue)) continue; + + var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1); + + if (fabric.gradientDefs[gradientId]) { + instances[i].set('fill', + fabric.Gradient.fromElement(fabric.gradientDefs[gradientId], instances[i])); + } + } + }, + + /** + * Parses an SVG document, returning all of the gradient declarations found in it + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element + */ + getGradientDefs: function(doc) { + var linearGradientEls = doc.getElementsByTagName('linearGradient'), + radialGradientEls = doc.getElementsByTagName('radialGradient'), + el, i, + gradientDefs = { }; + + i = linearGradientEls.length; + for (; i--; ) { + el = linearGradientEls[i]; + gradientDefs[el.getAttribute('id')] = el; + } + + i = radialGradientEls.length; + for (; i--; ) { + el = radialGradientEls[i]; + gradientDefs[el.getAttribute('id')] = el; + } + + return gradientDefs; + }, + + /** + * Returns an object of attributes' name/value, given element and an array of attribute names; + * Parses parent "g" nodes recursively upwards. + * @static + * @memberOf fabric + * @param {DOMElement} element Element to parse + * @param {Array} attributes Array of attributes to parse + * @return {Object} object containing parsed attributes' names/values + */ + parseAttributes: function(element, attributes) { + + if (!element) { + return; + } + + var value, + parentAttributes = { }; + + // if there's a parent container (`g` node), parse its attributes recursively upwards + if (element.parentNode && /^g$/i.test(element.parentNode.nodeName)) { + parentAttributes = fabric.parseAttributes(element.parentNode, attributes); + } + + var ownAttributes = attributes.reduce(function(memo, attr) { + value = element.getAttribute(attr); + if (value) { + attr = normalizeAttr(attr); + value = normalizeValue(attr, value, parentAttributes); + + memo[attr] = value; + } + return memo; + }, { }); + + // add values parsed from style, which take precedence over attributes + // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes) + ownAttributes = extend(ownAttributes, + extend(getGlobalStylesForElement(element), fabric.parseStyleAttribute(element))); + + return _setStrokeFillOpacity(extend(parentAttributes, ownAttributes)); + }, + + /** + * Transforms an array of svg elements to corresponding fabric.* instances + * @static + * @memberOf fabric + * @param {Array} elements Array of elements to parse + * @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements) + * @param {Object} [options] Options object + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + parseElements: function(elements, callback, options, reviver) { + fabric.ElementsParser.parse(elements, callback, options, reviver); + }, + + /** + * Parses "style" attribute, retuning an object with values + * @static + * @memberOf fabric + * @param {SVGElement} element Element to parse + * @return {Object} Objects with values parsed from style attribute of an element + */ + parseStyleAttribute: function(element) { + var oStyle = { }, + style = element.getAttribute('style'); + + if (!style) return oStyle; + + if (typeof style === 'string') { + parseStyleString(style, oStyle); + } + else { + parseStyleObject(style, oStyle); + } + + return oStyle; + }, + + /** + * Parses "points" attribute, returning an array of values + * @static + * @memberOf fabric + * @param points {String} points attribute string + * @return {Array} array of points + */ + parsePointsAttribute: function(points) { + + // points attribute is required and must not be empty + if (!points) return null; + + points = points.trim(); + var asPairs = points.indexOf(',') > -1; + + points = points.split(/\s+/); + var parsedPoints = [ ], i, len; + + // points could look like "10,20 30,40" or "10 20 30 40" + if (asPairs) { + i = 0; + len = points.length; + for (; i < len; i++) { + var pair = points[i].split(','); + parsedPoints.push({ x: parseFloat(pair[0]), y: parseFloat(pair[1]) }); + } + } + else { + i = 0; + len = points.length; + for (; i < len; i+=2) { + parsedPoints.push({ x: parseFloat(points[i]), y: parseFloat(points[i+1]) }); + } + } + + // odd number of points is an error + if (parsedPoints.length % 2 !== 0) { + // return null; + } + + return parsedPoints; + }, + + /** + * Returns CSS rules for a given SVG document + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @return {Object} CSS rules of this document + */ + getCSSRules: function(doc) { + var styles = doc.getElementsByTagName('style'), + allRules = { }, + rules; + + // very crude parsing of style contents + for (var i = 0, len = styles.length; i < len; i++) { + var styleContents = styles[0].textContent; + + // remove comments + styleContents = styleContents.replace(/\/\*[\s\S]*?\*\//g, ''); + + rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g); + rules = rules.map(function(rule) { return rule.trim(); }); + + rules.forEach(function(rule) { + var match = rule.match(/([\s\S]*?)\s*\{([^}]*)\}/); + rule = match[1]; + var declaration = match[2].trim(), + propertyValuePairs = declaration.replace(/;$/, '').split(/\s*;\s*/); + + if (!allRules[rule]) { + allRules[rule] = { }; + } + + for (var i = 0, len = propertyValuePairs.length; i < len; i++) { + var pair = propertyValuePairs[i].split(/\s*:\s*/), + property = pair[0], + value = pair[1]; + + allRules[rule][property] = value; + } + }); + } + + return allRules; + }, + + /** + * Takes url corresponding to an SVG document, and parses it into a set of fabric objects. Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy) + * @memberof fabric + * @param {String} url + * @param {Function} callback + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + loadSVGFromURL: function(url, callback, reviver) { + + url = url.replace(/^\n\s*/, '').trim(); + + svgCache.has(url, function (hasUrl) { + if (hasUrl) { + svgCache.get(url, function (value) { + var enlivedRecord = _enlivenCachedObject(value); + callback(enlivedRecord.objects, enlivedRecord.options); + }); + } + else { + new fabric.util.request(url, { + method: 'get', + onComplete: onComplete + }); + } + }); + + function onComplete(r) { + + var xml = r.responseXML; + if (!xml.documentElement && fabric.window.ActiveXObject && r.responseText) { + xml = new ActiveXObject('Microsoft.XMLDOM'); + xml.async = 'false'; + //IE chokes on DOCTYPE + xml.loadXML(r.responseText.replace(//i,'')); + } + if (!xml.documentElement) return; + + fabric.parseSVGDocument(xml.documentElement, function (results, options) { + svgCache.set(url, { + objects: fabric.util.array.invoke(results, 'toObject'), + options: options + }); + callback(results, options); + }, reviver); + } + }, + + /** + * Takes string corresponding to an SVG document, and parses it into a set of fabric objects + * @memberof fabric + * @param {String} string + * @param {Function} callback + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + loadSVGFromString: function(string, callback, reviver) { + string = string.trim(); + var doc; + if (typeof DOMParser !== 'undefined') { + var parser = new DOMParser(); + if (parser && parser.parseFromString) { + doc = parser.parseFromString(string, 'text/xml'); + } + } + else if (fabric.window.ActiveXObject) { + doc = new ActiveXObject('Microsoft.XMLDOM'); + doc.async = 'false'; + //IE chokes on DOCTYPE + doc.loadXML(string.replace(//i,'')); + } + + fabric.parseSVGDocument(doc.documentElement, function (results, options) { + callback(results, options); + }, reviver); + }, + + /** + * Creates markup containing SVG font faces + * @param {Array} objects Array of fabric objects + * @return {String} + */ + createSVGFontFacesMarkup: function(objects) { + var markup = ''; + + for (var i = 0, len = objects.length; i < len; i++) { + if (objects[i].type !== 'text' || !objects[i].path) continue; + + markup += [ + '@font-face {', + 'font-family: ', objects[i].fontFamily, '; ', + 'src: url(\'', objects[i].path, '\')', + '}' + ].join(''); + } + + if (markup) { + markup = [ + '' + ].join(''); + } + + return markup; + }, + + /** + * Creates markup containing SVG referenced elements like patterns, gradients etc. + * @param {fabric.Canvas} canvas instance of fabric.Canvas + * @return {String} + */ + createSVGRefElementsMarkup: function(canvas) { + var markup = [ ]; + + _createSVGPattern(markup, canvas, 'backgroundColor'); + _createSVGPattern(markup, canvas, 'overlayColor'); + + return markup.join(''); + } + }); + +})(typeof exports !== 'undefined' ? exports : this); +fabric.ElementsParser = { + + parse: function(elements, callback, options, reviver) { + + this.elements = elements; + this.callback = callback; + this.options = options; + this.reviver = reviver; + + this.instances = new Array(elements.length); + this.numElements = elements.length; + + this.createObjects(); + }, + + createObjects: function() { + for (var i = 0, len = this.elements.length; i < len; i++) { + this.createObject(this.elements[i], i); + } + }, + + createObject: function(el, index) { + var klass = fabric[fabric.util.string.capitalize(el.tagName)]; + if (klass && klass.fromElement) { + try { + this._createObject(klass, el, index); + } + catch(err) { + fabric.log(err); + } + } + else { + this.checkIfDone(); + } + }, + + _createObject: function(klass, el, index) { + if (klass.async) { + klass.fromElement(el, this.createCallback(index, el), this.options); + } + else { + var obj = klass.fromElement(el, this.options); + this.reviver && this.reviver(el, obj); + this.instances.splice(index, 0, obj); + this.checkIfDone(); + } + }, + + createCallback: function(index, el) { + var _this = this; + return function(obj) { + _this.reviver && _this.reviver(el, obj); + _this.instances.splice(index, 0, obj); + _this.checkIfDone(); + }; + }, + + checkIfDone: function() { + if (--this.numElements === 0) { + this.instances = this.instances.filter(function(el) { + return el != null; + }); + fabric.resolveGradients(this.instances); + this.callback(this.instances); + } + } +}; +(function(global) { + + "use strict"; + + /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Point) { + fabric.warn('fabric.Point is already defined'); + return; + } + + fabric.Point = Point; + + /** + * Point class + * @class fabric.Point + * @memberOf fabric + * @constructor + * @param {Number} x + * @param {Number} y + * @return {fabric.Point} thisArg + */ + function Point(x, y) { + this.x = x; + this.y = y; + } + + Point.prototype = /** @lends fabric.Point.prototype */ { + + constructor: Point, + + /** + * Adds another point to this one and returns another one + * @param {fabric.Point} that + * @return {fabric.Point} new Point instance with added values + */ + add: function (that) { + return new Point(this.x + that.x, this.y + that.y); + }, + + /** + * Adds another point to this one + * @param {fabric.Point} that + * @return {fabric.Point} thisArg + */ + addEquals: function (that) { + this.x += that.x; + this.y += that.y; + return this; + }, + + /** + * Adds value to this point and returns a new one + * @param {Number} scalar + * @return {fabric.Point} new Point with added value + */ + scalarAdd: function (scalar) { + return new Point(this.x + scalar, this.y + scalar); + }, + + /** + * Adds value to this point + * @param {Number} scalar + * @param {fabric.Point} thisArg + */ + scalarAddEquals: function (scalar) { + this.x += scalar; + this.y += scalar; + return this; + }, + + /** + * Subtracts another point from this point and returns a new one + * @param {fabric.Point} that + * @return {fabric.Point} new Point object with subtracted values + */ + subtract: function (that) { + return new Point(this.x - that.x, this.y - that.y); + }, + + /** + * Subtracts another point from this point + * @param {fabric.Point} that + * @return {fabric.Point} thisArg + */ + subtractEquals: function (that) { + this.x -= that.x; + this.y -= that.y; + return this; + }, + + /** + * Subtracts value from this point and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + scalarSubtract: function (scalar) { + return new Point(this.x - scalar, this.y - scalar); + }, + + /** + * Subtracts value from this point + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + scalarSubtractEquals: function (scalar) { + this.x -= scalar; + this.y -= scalar; + return this; + }, + + /** + * Miltiplies this point by a value and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + multiply: function (scalar) { + return new Point(this.x * scalar, this.y * scalar); + }, + + /** + * Miltiplies this point by a value + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + multiplyEquals: function (scalar) { + this.x *= scalar; + this.y *= scalar; + return this; + }, + + /** + * Divides this point by a value and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + divide: function (scalar) { + return new Point(this.x / scalar, this.y / scalar); + }, + + /** + * Divides this point by a value + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + divideEquals: function (scalar) { + this.x /= scalar; + this.y /= scalar; + return this; + }, + + /** + * Returns true if this point is equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + eq: function (that) { + return (this.x === that.x && this.y === that.y); + }, + + /** + * Returns true if this point is less than another one + * @param {fabric.Point} that + * @return {Boolean} + */ + lt: function (that) { + return (this.x < that.x && this.y < that.y); + }, + + /** + * Returns true if this point is less than or equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + lte: function (that) { + return (this.x <= that.x && this.y <= that.y); + }, + + /** + + * Returns true if this point is greater another one + * @param {fabric.Point} that + * @return {Boolean} + */ + gt: function (that) { + return (this.x > that.x && this.y > that.y); + }, + + /** + * Returns true if this point is greater than or equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + gte: function (that) { + return (this.x >= that.x && this.y >= that.y); + }, + + /** + * Returns new point which is the result of linear interpolation with this one and another one + * @param {fabric.Point} that + * @param {Number} t + * @return {fabric.Point} + */ + lerp: function (that, t) { + return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t); + }, + + /** + * Returns distance from this point and another one + * @param {fabric.Point} that + * @return {Number} + */ + distanceFrom: function (that) { + var dx = this.x - that.x, + dy = this.y - that.y; + return Math.sqrt(dx * dx + dy * dy); + }, + + /** + * Returns the point between this point and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + midPointFrom: function (that) { + return new Point(this.x + (that.x - this.x)/2, this.y + (that.y - this.y)/2); + }, + + /** + * Returns a new point which is the min of this and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + min: function (that) { + return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y)); + }, + + /** + * Returns a new point which is the max of this and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + max: function (that) { + return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y)); + }, + + /** + * Returns string representation of this point + * @return {String} + */ + toString: function () { + return this.x + "," + this.y; + }, + + /** + * Sets x/y of this point + * @param {Number} x + * @return {Number} y + */ + setXY: function (x, y) { + this.x = x; + this.y = y; + }, + + /** + * Sets x/y of this point from another point + * @param {fabric.Point} that + */ + setFromPoint: function (that) { + this.x = that.x; + this.y = that.y; + }, + + /** + * Swaps x/y of this point and another point + * @param {fabric.Point} that + */ + swap: function (that) { + var x = this.x, + y = this.y; + this.x = that.x; + this.y = that.y; + that.x = x; + that.y = y; + } + }; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global) { + + "use strict"; + + /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Intersection) { + fabric.warn('fabric.Intersection is already defined'); + return; + } + + /** + * Intersection class + * @class fabric.Intersection + * @memberOf fabric + * @constructor + */ + function Intersection(status) { + this.status = status; + this.points = []; + } + + fabric.Intersection = Intersection; + + fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ { + + /** + * Appends a point to intersection + * @param {fabric.Point} point + */ + appendPoint: function (point) { + this.points.push(point); + }, + + /** + * Appends points to intersection + * @param {Array} points + */ + appendPoints: function (points) { + this.points = this.points.concat(points); + } + }; + + /** + * Checks if one line intersects another + * @static + * @param {fabric.Point} a1 + * @param {fabric.Point} a2 + * @param {fabric.Point} b1 + * @param {fabric.Point} b2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) { + var result, + ua_t = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), + ub_t = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), + u_b = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); + if (u_b !== 0) { + var ua = ua_t / u_b, + ub = ub_t / u_b; + if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { + result = new Intersection("Intersection"); + result.points.push(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); + } + else { + result = new Intersection(); + } + } + else { + if (ua_t === 0 || ub_t === 0) { + result = new Intersection("Coincident"); + } + else { + result = new Intersection("Parallel"); + } + } + return result; + }; + + /** + * Checks if line intersects polygon + * @static + * @param {fabric.Point} a1 + * @param {fabric.Point} a2 + * @param {Array} points + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectLinePolygon = function(a1,a2,points){ + var result = new Intersection(), + length = points.length; + + for (var i = 0; i < length; i++) { + var b1 = points[i], + b2 = points[(i+1) % length], + inter = Intersection.intersectLineLine(a1, a2, b1, b2); + + result.appendPoints(inter.points); + } + if (result.points.length > 0) { + result.status = "Intersection"; + } + return result; + }; + + /** + * Checks if polygon intersects another polygon + * @static + * @param {Array} points1 + * @param {Array} points2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectPolygonPolygon = function (points1, points2) { + var result = new Intersection(), + length = points1.length; + + for (var i = 0; i < length; i++) { + var a1 = points1[i], + a2 = points1[(i+1) % length], + inter = Intersection.intersectLinePolygon(a1, a2, points2); + + result.appendPoints(inter.points); + } + if (result.points.length > 0) { + result.status = "Intersection"; + } + return result; + }; + + /** + * Checks if polygon intersects rectangle + * @static + * @param {Array} points + * @param {Number} r1 + * @param {Number} r2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) { + var min = r1.min(r2), + max = r1.max(r2), + topRight = new fabric.Point(max.x, min.y), + bottomLeft = new fabric.Point(min.x, max.y), + inter1 = Intersection.intersectLinePolygon(min, topRight, points), + inter2 = Intersection.intersectLinePolygon(topRight, max, points), + inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points), + inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points), + result = new Intersection(); + + result.appendPoints(inter1.points); + result.appendPoints(inter2.points); + result.appendPoints(inter3.points); + result.appendPoints(inter4.points); + + if (result.points.length > 0) { + result.status = "Intersection"; + } + return result; + }; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global) { + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Color) { + fabric.warn('fabric.Color is already defined.'); + return; + } + + /** + * Color class + * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations; + * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects. + * + * @class fabric.Color + * @param {String} color optional in hex or rgb(a) format + * @return {fabric.Color} thisArg + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors} + */ + function Color(color) { + if (!color) { + this.setSource([0, 0, 0, 1]); + } + else { + this._tryParsingColor(color); + } + } + + fabric.Color = Color; + + fabric.Color.prototype = /** @lends fabric.Color.prototype */ { + + /** + * @private + * @param {String|Array} color Color value to parse + */ + _tryParsingColor: function(color) { + var source; + + if (color in Color.colorNameMap) { + color = Color.colorNameMap[color]; + } + + source = Color.sourceFromHex(color); + + if (!source) { + source = Color.sourceFromRgb(color); + } + if (!source) { + source = Color.sourceFromHsl(color); + } + if (source) { + this.setSource(source); + } + }, + + /** + * Adapted from https://github.com/mjijackson + * @private + * @param {Number} r Red color value + * @param {Number} g Green color value + * @param {Number} b Blue color value + * @return {Array} Hsl color + */ + _rgbToHsl: function(r, g, b) { + r /= 255, g /= 255, b /= 255; + + var h, s, l, + max = fabric.util.array.max([r, g, b]), + min = fabric.util.array.min([r, g, b]); + + l = (max + min) / 2; + + if (max === min) { + h = s = 0; // achromatic + } + else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + + return [ + Math.round(h * 360), + Math.round(s * 100), + Math.round(l * 100) + ]; + }, + + /** + * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1]) + * @return {Array} + */ + getSource: function() { + return this._source; + }, + + /** + * Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1]) + * @param {Array} source + */ + setSource: function(source) { + this._source = source; + }, + + /** + * Returns color represenation in RGB format + * @return {String} ex: rgb(0-255,0-255,0-255) + */ + toRgb: function() { + var source = this.getSource(); + return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')'; + }, + + /** + * Returns color represenation in RGBA format + * @return {String} ex: rgba(0-255,0-255,0-255,0-1) + */ + toRgba: function() { + var source = this.getSource(); + return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')'; + }, + + /** + * Returns color represenation in HSL format + * @return {String} ex: hsl(0-360,0%-100%,0%-100%) + */ + toHsl: function() { + var source = this.getSource(), + hsl = this._rgbToHsl(source[0], source[1], source[2]); + + return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)'; + }, + + /** + * Returns color represenation in HSLA format + * @return {String} ex: hsla(0-360,0%-100%,0%-100%,0-1) + */ + toHsla: function() { + var source = this.getSource(), + hsl = this._rgbToHsl(source[0], source[1], source[2]); + + return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')'; + }, + + /** + * Returns color represenation in HEX format + * @return {String} ex: FF5555 + */ + toHex: function() { + var source = this.getSource(); + + var r = source[0].toString(16); + r = (r.length === 1) ? ('0' + r) : r; + + var g = source[1].toString(16); + g = (g.length === 1) ? ('0' + g) : g; + + var b = source[2].toString(16); + b = (b.length === 1) ? ('0' + b) : b; + + return r.toUpperCase() + g.toUpperCase() + b.toUpperCase(); + }, + + /** + * Gets value of alpha channel for this color + * @return {Number} 0-1 + */ + getAlpha: function() { + return this.getSource()[3]; + }, + + /** + * Sets value of alpha channel for this color + * @param {Number} alpha Alpha value 0-1 + * @return {fabric.Color} thisArg + */ + setAlpha: function(alpha) { + var source = this.getSource(); + source[3] = alpha; + this.setSource(source); + return this; + }, + + /** + * Transforms color to its grayscale representation + * @return {fabric.Color} thisArg + */ + toGrayscale: function() { + var source = this.getSource(), + average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10), + currentAlpha = source[3]; + this.setSource([average, average, average, currentAlpha]); + return this; + }, + + /** + * Transforms color to its black and white representation + * @param {Number} threshold + * @return {fabric.Color} thisArg + */ + toBlackWhite: function(threshold) { + var source = this.getSource(), + average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), + currentAlpha = source[3]; + + threshold = threshold || 127; + + average = (Number(average) < Number(threshold)) ? 0 : 255; + this.setSource([average, average, average, currentAlpha]); + return this; + }, + + /** + * Overlays color with another color + * @param {String|fabric.Color} otherColor + * @return {fabric.Color} thisArg + */ + overlayWith: function(otherColor) { + if (!(otherColor instanceof Color)) { + otherColor = new Color(otherColor); + } + + var result = [], + alpha = this.getAlpha(), + otherAlpha = 0.5, + source = this.getSource(), + otherSource = otherColor.getSource(); + + for (var i = 0; i < 3; i++) { + result.push(Math.round((source[i] * (1 - otherAlpha)) + (otherSource[i] * otherAlpha))); + } + + result[3] = alpha; + this.setSource(result); + return this; + } + }; + + /** + * Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5)) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reRGBa = /^rgba?\(\s*(\d{1,3}\%?)\s*,\s*(\d{1,3}\%?)\s*,\s*(\d{1,3}\%?)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; + + /** + * Regex matching color in HSL or HSLA formats (ex: hsl(200, 80%, 10%), hsla(300, 50%, 80%, 0.5), hsla( 300 , 50% , 80% , 0.5 )) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; + + /** + * Regex matching color in HEX format (ex: #FF5555, 010155, aff) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reHex = /^#?([0-9a-f]{6}|[0-9a-f]{3})$/i; + + /** + * Map of the 17 basic color names with HEX code + * @static + * @field + * @memberOf fabric.Color + * @see: http://www.w3.org/TR/CSS2/syndata.html#color-units + */ + fabric.Color.colorNameMap = { + 'aqua': '#00FFFF', + 'black': '#000000', + 'blue': '#0000FF', + 'fuchsia': '#FF00FF', + 'gray': '#808080', + 'green': '#008000', + 'lime': '#00FF00', + 'maroon': '#800000', + 'navy': '#000080', + 'olive': '#808000', + 'orange': '#FFA500', + 'purple': '#800080', + 'red': '#FF0000', + 'silver': '#C0C0C0', + 'teal': '#008080', + 'white': '#FFFFFF', + 'yellow': '#FFFF00' + }; + + /** + * @private + * @param {Number} p + * @param {Number} q + * @param {Number} t + * @return {Number} + */ + function hue2rgb(p, q, t){ + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1/6) return p + (q - p) * 6 * t; + if (t < 1/2) return q; + if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + } + + /** + * Returns new color object, when given a color in RGB format + * @memberOf fabric.Color + * @param {String} color Color value ex: rgb(0-255,0-255,0-255) + * @return {fabric.Color} + */ + fabric.Color.fromRgb = function(color) { + return Color.fromSource(Color.sourceFromRgb(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format + * @memberOf fabric.Color + * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%) + * @return {Array} source + */ + fabric.Color.sourceFromRgb = function(color) { + var match = color.match(Color.reRGBa); + if (match) { + var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1), + g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1), + b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1); + + return [ + parseInt(r, 10), + parseInt(g, 10), + parseInt(b, 10), + match[4] ? parseFloat(match[4]) : 1 + ]; + } + }; + + /** + * Returns new color object, when given a color in RGBA format + * @static + * @function + * @memberOf fabric.Color + * @param {String} color + * @return {fabric.Color} + */ + fabric.Color.fromRgba = Color.fromRgb; + + /** + * Returns new color object, when given a color in HSL format + * @param {String} color Color value ex: hsl(0-260,0%-100%,0%-100%) + * @memberOf fabric.Color + * @return {fabric.Color} + */ + fabric.Color.fromHsl = function(color) { + return Color.fromSource(Color.sourceFromHsl(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format. + * Adapted from https://github.com/mjijackson + * @memberOf fabric.Color + * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1) + * @return {Array} source + * @see http://http://www.w3.org/TR/css3-color/#hsl-color + */ + fabric.Color.sourceFromHsl = function(color) { + var match = color.match(Color.reHSLa); + if (!match) return; + + var h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360, + s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1), + l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1), + r, g, b; + + if (s === 0) { + r = g = b = l; + } + else { + var q = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var p = l * 2 - q; + + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return [ + Math.round(r * 255), + Math.round(g * 255), + Math.round(b * 255), + match[4] ? parseFloat(match[4]) : 1 + ]; + }; + + /** + * Returns new color object, when given a color in HSLA format + * @static + * @function + * @memberOf fabric.Color + * @param {String} color + * @return {fabric.Color} + */ + fabric.Color.fromHsla = Color.fromHsl; + + /** + * Returns new color object, when given a color in HEX format + * @static + * @memberOf fabric.Color + * @param {String} color Color value ex: FF5555 + * @return {fabric.Color} + */ + fabric.Color.fromHex = function(color) { + return Color.fromSource(Color.sourceFromHex(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HEX format + * @static + * @memberOf fabric.Color + * @param {String} color ex: FF5555 + * @return {Array} source + */ + fabric.Color.sourceFromHex = function(color) { + if (color.match(Color.reHex)) { + var value = color.slice(color.indexOf('#') + 1), + isShortNotation = (value.length === 3), + r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2), + g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4), + b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6); + + return [ + parseInt(r, 16), + parseInt(g, 16), + parseInt(b, 16), + 1 + ]; + } + }; + + /** + * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5]) + * @static + * @memberOf fabric.Color + * @param {Array} source + * @return {fabric.Color} + */ + fabric.Color.fromSource = function(source) { + var oColor = new Color(); + oColor.setSource(source); + return oColor; + }; + +})(typeof exports !== 'undefined' ? exports : this); +/** + * Pattern class + * @class fabric.Pattern + * @see {@link http://fabricjs.com/patterns/|Pattern demo} + * @see {@link http://fabricjs.com/dynamic-patterns/|DynamicPattern demo} + * @see {@link fabric.Pattern#initialize} for constructor definition + */ +fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ { + + /** + * Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat) + * @type String + * @default + */ + repeat: 'repeat', + + /** + * Pattern horizontal offset from object's left/top corner + * @type Number + * @default + */ + offsetX: 0, + + /** + * Pattern vertical offset from object's left/top corner + * @type Number + * @default + */ + offsetY: 0, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Pattern} thisArg + */ + initialize: function(options) { + options || (options = { }); + + this.id = fabric.Object.__uid++; + + if (options.source) { + if (typeof options.source === 'string') { + // function string + if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') { + this.source = new Function(fabric.util.getFunctionBody(options.source)); + } + else { + // img src string + var _this = this; + this.source = fabric.util.createImage(); + fabric.util.loadImage(options.source, function(img) { + _this.source = img; + }); + } + } + else { + // img element + this.source = options.source; + } + } + if (options.repeat) { + this.repeat = options.repeat; + } + if (options.offsetX) { + this.offsetX = options.offsetX; + } + if (options.offsetY) { + this.offsetY = options.offsetY; + } + }, + + /** + * Returns object representation of a pattern + * @return {Object} Object representation of a pattern instance + */ + toObject: function() { + + var source; + + // callback + if (typeof this.source === 'function') { + source = String(this.source); + } + // element + else if (typeof this.source.src === 'string') { + source = this.source.src; + } + + return { + source: source, + repeat: this.repeat, + offsetX: this.offsetX, + offsetY: this.offsetY + }; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of a pattern + * @param {fabric.Object} object + * @return {String} SVG representation of a pattern + */ + toSVG: function(object) { + var patternSource = typeof this.source === 'function' ? this.source() : this.source; + var patternWidth = patternSource.width / object.getWidth(); + var patternHeight = patternSource.height / object.getHeight(); + var patternImgSrc = ''; + + if (patternSource.src) { + patternImgSrc = patternSource.src; + } + else if (patternSource.toDataURL) { + patternImgSrc = patternSource.toDataURL(); + } + + return '' + + '' + + ''; + }, + /* _TO_SVG_END_ */ + + /** + * Returns an instance of CanvasPattern + * @param {CanvasRenderingContext2D} ctx Context to create pattern + * @return {CanvasPattern} + */ + toLive: function(ctx) { + var source = typeof this.source === 'function' ? this.source() : this.source; + // if an image + if (typeof source.src !== 'undefined') { + if (!source.complete) return ''; + if (source.naturalWidth === 0 || source.naturalHeight === 0) return ''; + } + return ctx.createPattern(source, this.repeat); + } +}); +(function () { + + "use strict"; + + if (fabric.StaticCanvas) { + fabric.warn('fabric.StaticCanvas is already defined.'); + return; + } + + // aliases for faster resolution + var extend = fabric.util.object.extend, + getElementOffset = fabric.util.getElementOffset, + removeFromArray = fabric.util.removeFromArray, + + CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element'); + + /** + * Static canvas class + * @class fabric.StaticCanvas + * @mixes fabric.Collection + * @mixes fabric.Observable + * @see {@link http://fabricjs.com/static_canvas/|StaticCanvas demo} + * @see {@link fabric.StaticCanvas#initialize} for constructor definition + * @fires before:render + * @fires after:render + * @fires canvas:cleared + * @fires object:added + * @fires object:removed + */ + fabric.StaticCanvas = fabric.util.createClass(/** @lends fabric.StaticCanvas.prototype */ { + + /** + * Constructor + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(el, options) { + options || (options = { }); + + this._initStatic(el, options); + fabric.StaticCanvas.activeInstance = this; + }, + + /** + * Background color of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setBackgroundColor}. + * @type {(String|fabric.Pattern)} + * @default + */ + backgroundColor: '', + + /** + * Background image of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setBackgroundImage}. + * Backwards incompatibility note: The "backgroundImageOpacity" + * and "backgroundImageStretch" properties are deprecated since 1.3.9. + * Use {@link fabric.Image#opacity}, {@link fabric.Image#width} and {@link fabric.Image#height}. + * @type fabric.Image + * @default + */ + backgroundImage: null, + + /** + * Overlay color of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setOverlayColor} + * @since 1.3.9 + * @type {(String|fabric.Pattern)} + * @default + */ + overlayColor: '', + + /** + * Overlay image of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setOverlayImage}. + * Backwards incompatibility note: The "overlayImageLeft" + * and "overlayImageTop" properties are deprecated since 1.3.9. + * Use {@link fabric.Image#left} and {@link fabric.Image#top}. + * @type fabric.Image + * @default + */ + overlayImage: null, + + /** + * Indicates whether toObject/toDatalessObject should include default values + * @type Boolean + * @default + */ + includeDefaultValues: true, + + /** + * Indicates whether objects' state should be saved + * @type Boolean + * @default + */ + stateful: true, + + /** + * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove} should also re-render canvas. + * Disabling this option could give a great performance boost when adding/removing a lot of objects to/from canvas at once + * (followed by a manual rendering after addition/deletion) + * @type Boolean + * @default + */ + renderOnAddRemove: true, + + /** + * Function that determines clipping of entire canvas area + * Being passed context as first argument. See clipping canvas area in {@link https://github.com/kangax/fabric.js/wiki/FAQ} + * @type Function + * @default + */ + clipTo: null, + + /** + * Indicates whether object controls (borders/controls) are rendered above overlay image + * @type Boolean + * @default + */ + controlsAboveOverlay: false, + + /** + * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas + * @type Boolean + * @default + */ + allowTouchScrolling: false, + + /** + * Callback; invoked right before object is about to be scaled/rotated + * @param {fabric.Object} target Object that's about to be scaled/rotated + */ + onBeforeScaleRotate: function () { + /* NOOP */ + }, + + /** + * @private + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + */ + _initStatic: function(el, options) { + this._objects = []; + + this._createLowerCanvas(el); + this._initOptions(options); + + if (options.overlayImage) { + this.setOverlayImage(options.overlayImage, this.renderAll.bind(this)); + } + if (options.backgroundImage) { + this.setBackgroundImage(options.backgroundImage, this.renderAll.bind(this)); + } + if (options.backgroundColor) { + this.setBackgroundColor(options.backgroundColor, this.renderAll.bind(this)); + } + if (options.overlayColor) { + this.setOverlayColor(options.overlayColor, this.renderAll.bind(this)); + } + this.calcOffset(); + }, + + /** + * Calculates canvas element offset relative to the document + * This method is also attached as "resize" event handler of window + * @return {fabric.Canvas} instance + * @chainable + */ + calcOffset: function () { + this._offset = getElementOffset(this.lowerCanvasEl); + return this; + }, + + /** + * Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas + * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set overlay to + * @param {Function} callback callback to invoke when image is loaded and set as an overlay + * @param {Object} [options] Optional options to set for the {@link fabric.Image|overlay image}. + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo} + * @example Normal overlayImage with left/top = 0 + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * // Needed to position overlayImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + * @example overlayImage with different properties + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * opacity: 0.5, + * angle: 45, + * left: 400, + * top: 400, + * originX: 'left', + * originY: 'top' + * }); + * @example Stretched overlayImage #1 - width/height correspond to canvas width/height + * fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img) { + * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); + * canvas.setOverlayImage(img, canvas.renderAll.bind(canvas)); + * }); + * @example Stretched overlayImage #2 - width/height correspond to canvas width/height + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * width: canvas.width, + * height: canvas.height, + * // Needed to position overlayImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + */ + setOverlayImage: function (image, callback, options) { + return this.__setBgOverlayImage('overlayImage', image, callback, options); + }, + + /** + * Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas + * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background to + * @param {Function} callback Callback to invoke when image is loaded and set as background + * @param {Object} [options] Optional options to set for the {@link fabric.Image|background image}. + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/YH9yD/|jsFiddle demo} + * @example Normal backgroundImage with left/top = 0 + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * // Needed to position backgroundImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + * @example backgroundImage with different properties + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * opacity: 0.5, + * angle: 45, + * left: 400, + * top: 400, + * originX: 'left', + * originY: 'top' + * }); + * @example Stretched backgroundImage #1 - width/height correspond to canvas width/height + * fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img) { + * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); + * canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas)); + * }); + * @example Stretched backgroundImage #2 - width/height correspond to canvas width/height + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * width: canvas.width, + * height: canvas.height, + * // Needed to position backgroundImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + */ + setBackgroundImage: function (image, callback, options) { + return this.__setBgOverlayImage('backgroundImage', image, callback, options); + }, + + /** + * Sets {@link fabric.StaticCanvas#overlayColor|background color} for this canvas + * @param {(String|fabric.Pattern)} overlayColor Color or pattern to set background color to + * @param {Function} callback Callback to invoke when background color is set + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/pB55h/|jsFiddle demo} + * @example Normal overlayColor - color value + * canvas.setOverlayColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as overlayColor + * canvas.setOverlayColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png' + * }, canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as overlayColor with repeat and offset + * canvas.setOverlayColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png', + * repeat: 'repeat', + * offsetX: 200, + * offsetY: 100 + * }, canvas.renderAll.bind(canvas)); + */ + setOverlayColor: function(overlayColor, callback) { + return this.__setBgOverlayColor('overlayColor', overlayColor, callback); + }, + + /** + * Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas + * @param {(String|fabric.Pattern)} backgroundColor Color or pattern to set background color to + * @param {Function} callback Callback to invoke when background color is set + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo} + * @example Normal backgroundColor - color value + * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as backgroundColor + * canvas.setBackgroundColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png' + * }, canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as backgroundColor with repeat and offset + * canvas.setBackgroundColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png', + * repeat: 'repeat', + * offsetX: 200, + * offsetY: 100 + * }, canvas.renderAll.bind(canvas)); + */ + setBackgroundColor: function(backgroundColor, callback) { + return this.__setBgOverlayColor('backgroundColor', backgroundColor, callback); + }, + + /** + * @private + * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage} + * or {@link fabric.StaticCanvas#overlayImage|overlayImage}) + * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background or overlay to + * @param {Function} callback Callback to invoke when image is loaded and set as background or overlay + * @param {Object} [options] Optional options to set for the {@link fabric.Image|image}. + */ + __setBgOverlayImage: function(property, image, callback, options) { + if (typeof image === 'string') { + fabric.util.loadImage(image, function(img) { + this[property] = new fabric.Image(img, options); + callback && callback(); + }, this); + } + else { + this[property] = image; + callback && callback(); + } + + return this; + }, + + /** + * @private + * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundColor|backgroundColor} + * or {@link fabric.StaticCanvas#overlayColor|overlayColor}) + * @param {(Object|String)} color Object with pattern information or color value + * @param {Function} [callback] Callback is invoked when color is set + */ + __setBgOverlayColor: function(property, color, callback) { + if (color.source) { + var _this = this; + fabric.util.loadImage(color.source, function(img) { + _this[property] = new fabric.Pattern({ + source: img, + repeat: color.repeat, + offsetX: color.offsetX, + offsetY: color.offsetY + }); + callback && callback(); + }); + } + else { + this[property] = color; + callback && callback(); + } + + return this; + }, + + /** + * @private + */ + _createCanvasElement: function() { + var element = fabric.document.createElement('canvas'); + if (!element.style) { + element.style = { }; + } + if (!element) { + throw CANVAS_INIT_ERROR; + } + this._initCanvasElement(element); + return element; + }, + + /** + * @private + * @param {HTMLElement} element + */ + _initCanvasElement: function(element) { + fabric.util.createCanvasElement(element); + + if (typeof element.getContext === 'undefined') { + throw CANVAS_INIT_ERROR; + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initOptions: function (options) { + for (var prop in options) { + this[prop] = options[prop]; + } + + this.width = parseInt(this.lowerCanvasEl.width, 10) || 0; + this.height = parseInt(this.lowerCanvasEl.height, 10) || 0; + + if (!this.lowerCanvasEl.style) return; + + this.lowerCanvasEl.style.width = this.width + 'px'; + this.lowerCanvasEl.style.height = this.height + 'px'; + }, + + /** + * Creates a bottom canvas + * @private + * @param {HTMLElement} [canvasEl] + */ + _createLowerCanvas: function (canvasEl) { + this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement(); + this._initCanvasElement(this.lowerCanvasEl); + + fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas'); + + if (this.interactive) { + this._applyCanvasStyle(this.lowerCanvasEl); + } + + this.contextContainer = this.lowerCanvasEl.getContext('2d'); + }, + + /** + * Returns canvas width (in px) + * @return {Number} + */ + getWidth: function () { + return this.width; + }, + + /** + * Returns canvas height (in px) + * @return {Number} + */ + getHeight: function () { + return this.height; + }, + + /** + * Sets width of this canvas instance + * @param {Number} width value to set width to + * @return {fabric.Canvas} instance + * @chainable true + */ + setWidth: function (value) { + return this._setDimension('width', value); + }, + + /** + * Sets height of this canvas instance + * @param {Number} height value to set height to + * @return {fabric.Canvas} instance + * @chainable true + */ + setHeight: function (value) { + return this._setDimension('height', value); + }, + + /** + * Sets dimensions (width, height) of this canvas instance + * @param {Object} dimensions Object with width/height properties + * @param {Number} [dimensions.width] Width of canvas element + * @param {Number} [dimensions.height] Height of canvas element + * @return {fabric.Canvas} thisArg + * @chainable + */ + setDimensions: function(dimensions) { + for (var prop in dimensions) { + this._setDimension(prop, dimensions[prop]); + } + return this; + }, + + /** + * Helper for setting width/height + * @private + * @param {String} prop property (width|height) + * @param {Number} value value to set property to + * @return {fabric.Canvas} instance + * @chainable true + */ + _setDimension: function (prop, value) { + this.lowerCanvasEl[prop] = value; + this.lowerCanvasEl.style[prop] = value + 'px'; + + if (this.upperCanvasEl) { + this.upperCanvasEl[prop] = value; + this.upperCanvasEl.style[prop] = value + 'px'; + } + + if (this.cacheCanvasEl) { + this.cacheCanvasEl[prop] = value; + } + + if (this.wrapperEl) { + this.wrapperEl.style[prop] = value + 'px'; + } + + this[prop] = value; + + this.calcOffset(); + this.renderAll(); + + return this; + }, + + /** + * Returns <canvas> element corresponding to this instance + * @return {HTMLCanvasElement} + */ + getElement: function () { + return this.lowerCanvasEl; + }, + + /** + * Returns currently selected object, if any + * @return {fabric.Object} + */ + getActiveObject: function() { + return null; + }, + + /** + * Returns currently selected group of object, if any + * @return {fabric.Group} + */ + getActiveGroup: function() { + return null; + }, + + /** + * Given a context, renders an object on that context + * @param {CanvasRenderingContext2D} ctx Context to render object on + * @param {fabric.Object} object Object to render + * @private + */ + _draw: function (ctx, object) { + if (!object) return; + + if (this.controlsAboveOverlay) { + var hasBorders = object.hasBorders, hasControls = object.hasControls; + object.hasBorders = object.hasControls = false; + object.render(ctx); + object.hasBorders = hasBorders; + object.hasControls = hasControls; + } + else { + object.render(ctx); + } + }, + + /** + * @private + * @param {fabric.Object} obj Object that was added + */ + _onObjectAdded: function(obj) { + this.stateful && obj.setupState(); + obj.setCoords(); + obj.canvas = this; + this.fire('object:added', { target: obj }); + obj.fire('added'); + }, + + /** + * @private + * @param {fabric.Object} obj Object that was removed + */ + _onObjectRemoved: function(obj) { + // removing active object should fire "selection:cleared" events + if (this.getActiveObject() === obj) { + this.fire('before:selection:cleared', { target: obj }); + this._discardActiveObject(); + this.fire('selection:cleared'); + } + + this.fire('object:removed', { target: obj }); + obj.fire('removed'); + }, + + /** + * Clears specified context of canvas element + * @param {CanvasRenderingContext2D} ctx Context to clear + * @return {fabric.Canvas} thisArg + * @chainable + */ + clearContext: function(ctx) { + ctx.clearRect(0, 0, this.width, this.height); + return this; + }, + + /** + * Returns context of canvas where objects are drawn + * @return {CanvasRenderingContext2D} + */ + getContext: function () { + return this.contextContainer; + }, + + /** + * Clears all contexts (background, main, top) of an instance + * @return {fabric.Canvas} thisArg + * @chainable + */ + clear: function () { + this._objects.length = 0; + if (this.discardActiveGroup) { + this.discardActiveGroup(); + } + if (this.discardActiveObject) { + this.discardActiveObject(); + } + this.clearContext(this.contextContainer); + if (this.contextTop) { + this.clearContext(this.contextTop); + } + this.fire('canvas:cleared'); + this.renderAll(); + return this; + }, + + /** + * Renders both the top canvas and the secondary container canvas. + * @param {Boolean} [allOnTop] Whether we want to force all images to be rendered on the top canvas + * @return {fabric.Canvas} instance + * @chainable + */ + renderAll: function (allOnTop) { + + var canvasToDrawOn = this[(allOnTop === true && this.interactive) ? 'contextTop' : 'contextContainer']; + var activeGroup = this.getActiveGroup(); + + if (this.contextTop && this.selection && !this._groupSelector) { + this.clearContext(this.contextTop); + } + + if (!allOnTop) { + this.clearContext(canvasToDrawOn); + } + + this.fire('before:render'); + + if (this.clipTo) { + fabric.util.clipContext(this, canvasToDrawOn); + } + + this._renderBackground(canvasToDrawOn); + this._renderObjects(canvasToDrawOn, activeGroup); + this._renderActiveGroup(canvasToDrawOn, activeGroup); + + if (this.clipTo) { + canvasToDrawOn.restore(); + } + + this._renderOverlay(canvasToDrawOn); + + if (this.controlsAboveOverlay && this.interactive) { + this.drawControls(canvasToDrawOn); + } + + this.fire('after:render'); + + return this; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {fabric.Group} activeGroup + */ + _renderObjects: function(ctx, activeGroup) { + for (var i = 0, length = this._objects.length; i < length; ++i) { + if (!activeGroup || + (activeGroup && this._objects[i] && !activeGroup.contains(this._objects[i]))) { + this._draw(ctx, this._objects[i]); + } + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {fabric.Group} activeGroup + */ + _renderActiveGroup: function(ctx, activeGroup) { + + // delegate rendering to group selection (if one exists) + if (activeGroup) { + + //Store objects in group preserving order, then replace + var sortedObjects = []; + this.forEachObject(function (object) { + if (activeGroup.contains(object)) { + sortedObjects.push(object); + } + }); + activeGroup._set('objects', sortedObjects); + this._draw(ctx, activeGroup); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderBackground: function(ctx) { + if (this.backgroundColor) { + ctx.fillStyle = this.backgroundColor.toLive + ? this.backgroundColor.toLive(ctx) + : this.backgroundColor; + + ctx.fillRect( + this.backgroundColor.offsetX || 0, + this.backgroundColor.offsetY || 0, + this.width, + this.height); + } + if (this.backgroundImage) { + this.backgroundImage.render(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderOverlay: function(ctx) { + if (this.overlayColor) { + ctx.fillStyle = this.overlayColor.toLive + ? this.overlayColor.toLive(ctx) + : this.overlayColor; + + ctx.fillRect( + this.overlayColor.offsetX || 0, + this.overlayColor.offsetY || 0, + this.width, + this.height); + } + if (this.overlayImage) { + this.overlayImage.render(ctx); + } + }, + + /** + * Method to render only the top canvas. + * Also used to render the group selection box. + * @return {fabric.Canvas} thisArg + * @chainable + */ + renderTop: function () { + var ctx = this.contextTop || this.contextContainer; + this.clearContext(ctx); + + // we render the top context - last object + if (this.selection && this._groupSelector) { + this._drawSelection(); + } + + // delegate rendering to group selection if one exists + // used for drawing selection borders/controls + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + activeGroup.render(ctx); + } + + if (this.overlayImage) { + ctx.drawImage(this.overlayImage, this.overlayImageLeft, this.overlayImageTop); + } + + this.fire('after:render'); + + return this; + }, + + /** + * Returns coordinates of a center of canvas. + * Returned value is an object with top and left properties + * @return {Object} object with "top" and "left" number values + */ + getCenter: function () { + return { + top: this.getHeight() / 2, + left: this.getWidth() / 2 + }; + }, + + /** + * Centers object horizontally. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center horizontally + * @return {fabric.Canvas} thisArg + */ + centerObjectH: function (object) { + this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y)); + this.renderAll(); + return this; + }, + + /** + * Centers object vertically. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center vertically + * @return {fabric.Canvas} thisArg + * @chainable + */ + centerObjectV: function (object) { + this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top)); + this.renderAll(); + return this; + }, + + /** + * Centers object vertically and horizontally. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center vertically and horizontally + * @return {fabric.Canvas} thisArg + * @chainable + */ + centerObject: function(object) { + var center = this.getCenter(); + + this._centerObject(object, new fabric.Point(center.left, center.top)); + this.renderAll(); + return this; + }, + + /** + * @private + * @param {fabric.Object} object Object to center + * @param {fabric.Point} center Center point + * @return {fabric.Canvas} thisArg + * @chainable + */ + _centerObject: function(object, center) { + object.setPositionByOrigin(center, 'center', 'center'); + return this; + }, + + /** + * Returs dataless JSON representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {String} json string + */ + toDatalessJSON: function (propertiesToInclude) { + return this.toDatalessObject(propertiesToInclude); + }, + + /** + * Returns object representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function (propertiesToInclude) { + return this._toObjectMethod('toObject', propertiesToInclude); + }, + + /** + * Returns dataless object representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toDatalessObject: function (propertiesToInclude) { + return this._toObjectMethod('toDatalessObject', propertiesToInclude); + }, + + /** + * @private + */ + _toObjectMethod: function (methodName, propertiesToInclude) { + + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this.discardActiveGroup(); + } + + var data = { + objects: this._toObjects(methodName, propertiesToInclude) + }; + + extend(data, this.__serializeBgOverlay()); + + fabric.util.populateWithProperties(this, data, propertiesToInclude); + + if (activeGroup) { + this.setActiveGroup(new fabric.Group(activeGroup.getObjects())); + activeGroup.forEachObject(function(o) { + o.set('active', true); + }); + } + return data; + }, + + /** + * @private + */ + _toObjects: function(methodName, propertiesToInclude) { + return this.getObjects().map(function(instance) { + return this._toObject(instance, methodName, propertiesToInclude); + }, this); + }, + + /** + * @private + */ + _toObject: function(instance, methodName, propertiesToInclude) { + var originalValue; + + if (!this.includeDefaultValues) { + originalValue = instance.includeDefaultValues; + instance.includeDefaultValues = false; + } + var object = instance[methodName](propertiesToInclude); + if (!this.includeDefaultValues) { + instance.includeDefaultValues = originalValue; + } + return object; + }, + + /** + * @private + */ + __serializeBgOverlay: function() { + var data = { + background: (this.backgroundColor && this.backgroundColor.toObject) + ? this.backgroundColor.toObject() + : this.backgroundColor + }; + + if (this.overlayColor) { + data.overlay = this.overlayColor.toObject + ? this.overlayColor.toObject() + : this.overlayColor; + } + if (this.backgroundImage) { + data.backgroundImage = this.backgroundImage.toObject(); + } + if (this.overlayImage) { + data.overlayImage = this.overlayImage.toObject(); + } + + return data; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of canvas + * @function + * @param {Object} [options] Options object for SVG output + * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included + * @param {Object} [options.viewBox] SVG viewbox object + * @param {Number} [options.viewBox.x] x-cooridnate of viewbox + * @param {Number} [options.viewBox.y] y-coordinate of viewbox + * @param {Number} [options.viewBox.width] Width of viewbox + * @param {Number} [options.viewBox.height] Height of viewbox + * @param {String} [options.encoding=UTF-8] Encoding of SVG output + * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation. + * @return {String} SVG string + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization} + * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo} + * @example Normal SVG output + * var svg = canvas.toSVG(); + * @example SVG output without preamble (without <?xml ../>) + * var svg = canvas.toSVG({suppressPreamble: true}); + * @example SVG output with viewBox attribute + * var svg = canvas.toSVG({ + * viewBox: { + * x: 100, + * y: 100, + * width: 200, + * height: 300 + * } + * }); + * @example SVG output with different encoding (default: UTF-8) + * var svg = canvas.toSVG({encoding: 'ISO-8859-1'}); + * @example Modify SVG output with reviver function + * var svg = canvas.toSVG(null, function(svg) { + * return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', ''); + * }); + */ + toSVG: function(options, reviver) { + options || (options = { }); + + var markup = []; + + this._setSVGPreamble(markup, options); + this._setSVGHeader(markup, options); + + this._setSVGBgOverlayColor(markup, 'backgroundColor'); + this._setSVGBgOverlayImage(markup, 'backgroundImage'); + + this._setSVGObjects(markup, reviver); + + this._setSVGBgOverlayColor(markup, 'overlayColor'); + this._setSVGBgOverlayImage(markup, 'overlayImage'); + + markup.push(''); + + return markup.join(''); + }, + + /** + * @private + */ + _setSVGPreamble: function(markup, options) { + if (!options.suppressPreamble) { + markup.push( + '', + '\n' + ); + } + }, + + /** + * @private + */ + _setSVGHeader: function(markup, options) { + markup.push( + '', + 'Created with Fabric.js ', fabric.version, '', + '', + fabric.createSVGFontFacesMarkup(this.getObjects()), + fabric.createSVGRefElementsMarkup(this), + '' + ); + }, + + /** + * @private + */ + _setSVGObjects: function(markup, reviver) { + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this.discardActiveGroup(); + } + for (var i = 0, objects = this.getObjects(), len = objects.length; i < len; i++) { + markup.push(objects[i].toSVG(reviver)); + } + if (activeGroup) { + this.setActiveGroup(new fabric.Group(activeGroup.getObjects())); + activeGroup.forEachObject(function(o) { + o.set('active', true); + }); + } + }, + + /** + * @private + */ + _setSVGBgOverlayImage: function(markup, property) { + if (this[property] && this[property].toSVG) { + markup.push(this[property].toSVG()); + } + }, + + /** + * @private + */ + _setSVGBgOverlayColor: function(markup, property) { + if (this[property] && this[property].source) { + markup.push( + '' + ); + } + else if (this[property] && property === 'overlayColor') { + markup.push( + '' + ); + } + }, + /* _TO_SVG_END_ */ + + /** + * Moves an object to the bottom of the stack of drawn objects + * @param {fabric.Object} object Object to send to back + * @return {fabric.Canvas} thisArg + * @chainable + */ + sendToBack: function (object) { + removeFromArray(this._objects, object); + this._objects.unshift(object); + return this.renderAll && this.renderAll(); + }, + + /** + * Moves an object to the top of the stack of drawn objects + * @param {fabric.Object} object Object to send + * @return {fabric.Canvas} thisArg + * @chainable + */ + bringToFront: function (object) { + removeFromArray(this._objects, object); + this._objects.push(object); + return this.renderAll && this.renderAll(); + }, + + /** + * Moves an object down in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object + * @return {fabric.Canvas} thisArg + * @chainable + */ + sendBackwards: function (object, intersecting) { + var idx = this._objects.indexOf(object); + + // if object is not on the bottom of stack + if (idx !== 0) { + var newIdx = this._findNewLowerIndex(object, idx, intersecting); + + removeFromArray(this._objects, object); + this._objects.splice(newIdx, 0, object); + this.renderAll && this.renderAll(); + } + return this; + }, + + /** + * @private + */ + _findNewLowerIndex: function(object, idx, intersecting) { + var newIdx; + + if (intersecting) { + newIdx = idx; + + // traverse down the stack looking for the nearest intersecting object + for (var i=idx-1; i>=0; --i) { + + var isIntersecting = object.intersectsWithObject(this._objects[i]) || + object.isContainedWithinObject(this._objects[i]) || + this._objects[i].isContainedWithinObject(object); + + if (isIntersecting) { + newIdx = i; + break; + } + } + } + else { + newIdx = idx - 1; + } + + return newIdx; + }, + + /** + * Moves an object up in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object + * @return {fabric.Canvas} thisArg + * @chainable + */ + bringForward: function (object, intersecting) { + var idx = this._objects.indexOf(object); + + // if object is not on top of stack (last item in an array) + if (idx !== this._objects.length-1) { + var newIdx = this._findNewUpperIndex(object, idx, intersecting); + + removeFromArray(this._objects, object); + this._objects.splice(newIdx, 0, object); + this.renderAll && this.renderAll(); + } + return this; + }, + + /** + * @private + */ + _findNewUpperIndex: function(object, idx, intersecting) { + var newIdx; + + if (intersecting) { + newIdx = idx; + + // traverse up the stack looking for the nearest intersecting object + for (var i = idx + 1; i < this._objects.length; ++i) { + + var isIntersecting = object.intersectsWithObject(this._objects[i]) || + object.isContainedWithinObject(this._objects[i]) || + this._objects[i].isContainedWithinObject(object); + + if (isIntersecting) { + newIdx = i; + break; + } + } + } + else { + newIdx = idx+1; + } + + return newIdx; + }, + + /** + * Moves an object to specified level in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Number} index Position to move to + * @return {fabric.Canvas} thisArg + * @chainable + */ + moveTo: function (object, index) { + removeFromArray(this._objects, object); + this._objects.splice(index, 0, object); + return this.renderAll && this.renderAll(); + }, + + /** + * Clears a canvas element and removes all event listeners + * @return {fabric.Canvas} thisArg + * @chainable + */ + dispose: function () { + this.clear(); + this.interactive && this.removeListeners(); + return this; + }, + + /** + * Returns a string representation of an instance + * @return {String} string representation of an instance + */ + toString: function () { + return '#'; + } + }); + + extend(fabric.StaticCanvas.prototype, fabric.Observable); + extend(fabric.StaticCanvas.prototype, fabric.Collection); + extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter); + + extend(fabric.StaticCanvas, /** @lends fabric.StaticCanvas */ { + + /** + * @static + * @type String + * @default + */ + EMPTY_JSON: '{"objects": [], "background": "white"}', + + /** + * Provides a way to check support of some of the canvas methods + * (either those of HTMLCanvasElement itself, or rendering context) + * + * @param methodName {String} Method to check support for; + * Could be one of "getImageData", "toDataURL", "toDataURLWithQuality" or "setLineDash" + * @return {Boolean | null} `true` if method is supported (or at least exists), + * `null` if canvas element or context can not be initialized + */ + supports: function (methodName) { + var el = fabric.util.createCanvasElement(); + + if (!el || !el.getContext) { + return null; + } + + var ctx = el.getContext('2d'); + if (!ctx) { + return null; + } + + switch (methodName) { + + case 'getImageData': + return typeof ctx.getImageData !== 'undefined'; + + case 'setLineDash': + return typeof ctx.setLineDash !== 'undefined'; + + case 'toDataURL': + return typeof el.toDataURL !== 'undefined'; + + case 'toDataURLWithQuality': + try { + el.toDataURL('image/jpeg', 0); + return true; + } + catch (e) { } + return false; + + default: + return null; + } + } + }); + + /** + * Returns JSON representation of canvas + * @function + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {String} JSON string + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization} + * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo} + * @example JSON without additional properties + * var json = canvas.toJSON(); + * @example JSON with additional properties included + * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY', 'lockUniScaling']); + * @example JSON without default values + * canvas.includeDefaultValues = false; + * var json = canvas.toJSON(); + */ + fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject; + +})(); +/** + * BaseBrush class + * @class fabric.BaseBrush + * @see {@link http://fabricjs.com/freedrawing/|Freedrawing demo} + */ +fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ { + + /** + * Color of a brush + * @type String + * @default + */ + color: 'rgb(0, 0, 0)', + + /** + * Width of a brush + * @type Number + * @default + */ + width: 1, + + /** + * Shadow object representing shadow of this shape. + * Backwards incompatibility note: This property replaces "shadowColor" (String), "shadowOffsetX" (Number), + * "shadowOffsetY" (Number) and "shadowBlur" (Number) since v1.2.12 + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Line endings style of a brush (one of "butt", "round", "square") + * @type String + * @default + */ + strokeLineCap: 'round', + + /** + * Corner style of a brush (one of "bevil", "round", "miter") + * @type String + * @default + */ + strokeLineJoin: 'round', + + /** + * Sets shadow of an object + * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") + * @return {fabric.Object} thisArg + * @chainable + */ + setShadow: function(options) { + this.shadow = new fabric.Shadow(options); + return this; + }, + + /** + * Sets brush styles + * @private + */ + _setBrushStyles: function() { + var ctx = this.canvas.contextTop; + + ctx.strokeStyle = this.color; + ctx.lineWidth = this.width; + ctx.lineCap = this.strokeLineCap; + ctx.lineJoin = this.strokeLineJoin; + }, + + /** + * Sets brush shadow styles + * @private + */ + _setShadow: function() { + if (!this.shadow) return; + + var ctx = this.canvas.contextTop; + + ctx.shadowColor = this.shadow.color; + ctx.shadowBlur = this.shadow.blur; + ctx.shadowOffsetX = this.shadow.offsetX; + ctx.shadowOffsetY = this.shadow.offsetY; + }, + + /** + * Removes brush shadow styles + * @private + */ + _resetShadow: function() { + var ctx = this.canvas.contextTop; + + ctx.shadowColor = ''; + ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; + } +}); +(function() { + + var utilMin = fabric.util.array.min, + utilMax = fabric.util.array.max; + + /** + * PencilBrush class + * @class fabric.PencilBrush + * @extends fabric.BaseBrush + */ + fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.PencilBrush.prototype */ { + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.PencilBrush} Instance of a pencil brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this._points = [ ]; + }, + + /** + * Inovoked on mouse down + * @param {Object} pointer + */ + onMouseDown: function(pointer) { + this._prepareForDrawing(pointer); + // capture coordinates immediately + // this allows to draw dots (when movement never occurs) + this._captureDrawingPath(pointer); + this._render(); + }, + + /** + * Inovoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this._captureDrawingPath(pointer); + // redraw curve + // clear top canvas + this.canvas.clearContext(this.canvas.contextTop); + this._render(); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + this._finalizeAndAddPath(); + }, + + /** + * @param {Object} pointer + */ + _prepareForDrawing: function(pointer) { + + var p = new fabric.Point(pointer.x, pointer.y); + + this._reset(); + this._addPoint(p); + + this.canvas.contextTop.moveTo(p.x, p.y); + }, + + /** + * @private + * @param {fabric.Point} point + */ + _addPoint: function(point) { + this._points.push(point); + }, + + /** + * Clear points array and set contextTop canvas + * style. + * + * @private + * + */ + _reset: function() { + this._points.length = 0; + + this._setBrushStyles(); + this._setShadow(); + }, + + /** + * @private + * + * @param point {pointer} (fabric.util.pointer) actual mouse position + * related to the canvas. + */ + _captureDrawingPath: function(pointer) { + var pointerPoint = new fabric.Point(pointer.x, pointer.y); + this._addPoint(pointerPoint); + }, + + /** + * Draw a smooth path on the topCanvas using quadraticCurveTo + * + * @private + */ + _render: function() { + var ctx = this.canvas.contextTop; + ctx.beginPath(); + + var p1 = this._points[0]; + var p2 = this._points[1]; + + //if we only have 2 points in the path and they are the same + //it means that the user only clicked the canvas without moving the mouse + //then we should be drawing a dot. A path isn't drawn between two identical dots + //that's why we set them apart a bit + if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) { + p1.x -= 0.5; + p2.x += 0.5; + } + ctx.moveTo(p1.x, p1.y); + + for (var i = 1, len = this._points.length; i < len; i++) { + // we pick the point between pi+1 & pi+2 as the + // end point and p1 as our control point. + var midPoint = p1.midPointFrom(p2); + ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y); + + p1 = this._points[i]; + p2 = this._points[i+1]; + } + // Draw last line as a straight line while + // we wait for the next point to be able to calculate + // the bezier control point + ctx.lineTo(p1.x, p1.y); + ctx.stroke(); + }, + + /** + * Return an SVG path based on our captured points and their bounding box + * + * @private + */ + _getSVGPathData: function() { + this.box = this.getPathBoundingBox(this._points); + return this.convertPointsToSVGPath( + this._points, this.box.minx, this.box.maxx, this.box.miny, this.box.maxy); + }, + + /** + * Returns bounding box of a path based on given points + * @param {Array} points + * @return {Object} object with minx, miny, maxx, maxy + */ + getPathBoundingBox: function(points) { + var xBounds = [], + yBounds = [], + p1 = points[0], + p2 = points[1], + startPoint = p1; + + for (var i = 1, len = points.length; i < len; i++) { + var midPoint = p1.midPointFrom(p2); + // with startPoint, p1 as control point, midpoint as end point + xBounds.push(startPoint.x); + xBounds.push(midPoint.x); + yBounds.push(startPoint.y); + yBounds.push(midPoint.y); + + p1 = points[i]; + p2 = points[i+1]; + startPoint = midPoint; + } // end for + + xBounds.push(p1.x); + yBounds.push(p1.y); + + return { + minx: utilMin(xBounds), + miny: utilMin(yBounds), + maxx: utilMax(xBounds), + maxy: utilMax(yBounds) + }; + }, + + /** + * Converts points to SVG path + * @param {Array} points Array of points + * @return {String} SVG path + */ + convertPointsToSVGPath: function(points, minX, maxX, minY) { + var path = []; + var p1 = new fabric.Point(points[0].x - minX, points[0].y - minY); + var p2 = new fabric.Point(points[1].x - minX, points[1].y - minY); + + path.push('M ', points[0].x - minX, ' ', points[0].y - minY, ' '); + for (var i = 1, len = points.length; i < len; i++) { + var midPoint = p1.midPointFrom(p2); + // p1 is our bezier control point + // midpoint is our endpoint + // start point is p(i-1) value. + path.push('Q ', p1.x, ' ', p1.y, ' ', midPoint.x, ' ', midPoint.y, ' '); + p1 = new fabric.Point(points[i].x - minX, points[i].y - minY); + if ((i+1) < points.length) { + p2 = new fabric.Point(points[i+1].x - minX, points[i+1].y - minY); + } + } + path.push('L ', p1.x, ' ', p1.y, ' '); + return path; + }, + + /** + * Creates fabric.Path object to add on canvas + * @param {String} pathData Path data + * @return {fabric.Path} path to add on canvas + */ + createPath: function(pathData) { + var path = new fabric.Path(pathData); + path.fill = null; + path.stroke = this.color; + path.strokeWidth = this.width; + path.strokeLineCap = this.strokeLineCap; + path.strokeLineJoin = this.strokeLineJoin; + + if (this.shadow) { + this.shadow.affectStroke = true; + path.setShadow(this.shadow); + } + + return path; + }, + + /** + * On mouseup after drawing the path on contextTop canvas + * we use the points captured to create an new fabric path object + * and add it to the fabric canvas. + * + */ + _finalizeAndAddPath: function() { + var ctx = this.canvas.contextTop; + ctx.closePath(); + + var pathData = this._getSVGPathData().join(''); + if (pathData === "M 0 0 Q 0 0 0 0 L 0 0") { + // do not create 0 width/height paths, as they are + // rendered inconsistently across browsers + // Firefox 4, for example, renders a dot, + // whereas Chrome 10 renders nothing + this.canvas.renderAll(); + return; + } + + // set path origin coordinates based on our bounding box + var originLeft = this.box.minx + (this.box.maxx - this.box.minx) /2; + var originTop = this.box.miny + (this.box.maxy - this.box.miny) /2; + + this.canvas.contextTop.arc(originLeft, originTop, 3, 0, Math.PI * 2, false); + + var path = this.createPath(pathData); + path.set({ + left: originLeft, + top: originTop, + originX: 'center', + originY: 'center' + }); + + this.canvas.add(path); + path.setCoords(); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderAll(); + + // fire event 'path' created + this.canvas.fire('path:created', { path: path }); + } + }); +})(); +/** + * CircleBrush class + * @class fabric.CircleBrush + */ +fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.CircleBrush.prototype */ { + + /** + * Width of a brush + * @type Number + * @default + */ + width: 10, + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.CircleBrush} Instance of a circle brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this.points = [ ]; + }, + /** + * Invoked inside on mouse down and mouse move + * @param {Object} pointer + */ + drawDot: function(pointer) { + var point = this.addPoint(pointer); + var ctx = this.canvas.contextTop; + + ctx.fillStyle = point.fill; + ctx.beginPath(); + ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false); + ctx.closePath(); + ctx.fill(); + }, + + /** + * Invoked on mouse down + */ + onMouseDown: function(pointer) { + this.points.length = 0; + this.canvas.clearContext(this.canvas.contextTop); + this._setShadow(); + this.drawDot(pointer); + }, + + /** + * Invoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this.drawDot(pointer); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; + this.canvas.renderOnAddRemove = false; + + var circles = [ ]; + + for (var i = 0, len = this.points.length; i < len; i++) { + var point = this.points[i]; + var circle = new fabric.Circle({ + radius: point.radius, + left: point.x, + top: point.y, + originX: 'center', + originY: 'center', + fill: point.fill + }); + + this.shadow && circle.setShadow(this.shadow); + + circles.push(circle); + } + var group = new fabric.Group(circles, { originX: 'center', originY: 'center' }); + + this.canvas.add(group); + this.canvas.fire('path:created', { path: group }); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderOnAddRemove = originalRenderOnAddRemove; + this.canvas.renderAll(); + }, + + /** + * @param {Object} pointer + * @return {fabric.Point} Just added pointer point + */ + addPoint: function(pointer) { + var pointerPoint = new fabric.Point(pointer.x, pointer.y); + + var circleRadius = fabric.util.getRandomInt( + Math.max(0, this.width - 20), this.width + 20) / 2; + + var circleColor = new fabric.Color(this.color) + .setAlpha(fabric.util.getRandomInt(0, 100) / 100) + .toRgba(); + + pointerPoint.radius = circleRadius; + pointerPoint.fill = circleColor; + + this.points.push(pointerPoint); + + return pointerPoint; + } +}); +/** + * SprayBrush class + * @class fabric.SprayBrush + */ +fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric.SprayBrush.prototype */ { + + /** + * Width of a spray + * @type Number + * @default + */ + width: 10, + + /** + * Density of a spray (number of dots per chunk) + * @type Number + * @default + */ + density: 20, + + /** + * Width of spray dots + * @type Number + * @default + */ + dotWidth: 1, + + /** + * Width variance of spray dots + * @type Number + * @default + */ + dotWidthVariance: 1, + + /** + * Whether opacity of a dot should be random + * @type Boolean + * @default + */ + randomOpacity: false, + + /** + * Whether overlapping dots (rectangles) should be removed (for performance reasons) + * @type Boolean + * @default + */ + optimizeOverlapping: true, + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.SprayBrush} Instance of a spray brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this.sprayChunks = [ ]; + }, + + /** + * Invoked on mouse down + * @param {Object} pointer + */ + onMouseDown: function(pointer) { + this.sprayChunks.length = 0; + this.canvas.clearContext(this.canvas.contextTop); + this._setShadow(); + + this.addSprayChunk(pointer); + this.render(); + }, + + /** + * Invoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this.addSprayChunk(pointer); + this.render(); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; + this.canvas.renderOnAddRemove = false; + + var rects = [ ]; + + for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) { + var sprayChunk = this.sprayChunks[i]; + + for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) { + + var rect = new fabric.Rect({ + width: sprayChunk[j].width, + height: sprayChunk[j].width, + left: sprayChunk[j].x + 1, + top: sprayChunk[j].y + 1, + originX: 'center', + originY: 'center', + fill: this.color + }); + + this.shadow && rect.setShadow(this.shadow); + rects.push(rect); + } + } + + if (this.optimizeOverlapping) { + rects = this._getOptimizedRects(rects); + } + + var group = new fabric.Group(rects, { originX: 'center', originY: 'center' }); + this.canvas.add(group); + this.canvas.fire('path:created', { path: group }); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderOnAddRemove = originalRenderOnAddRemove; + this.canvas.renderAll(); + }, + + _getOptimizedRects: function(rects) { + + // avoid creating duplicate rects at the same coordinates + var uniqueRects = { }, key; + + for (var i = 0, len = rects.length; i < len; i++) { + key = rects[i].left + '' + rects[i].top; + if (!uniqueRects[key]) { + uniqueRects[key] = rects[i]; + } + } + var uniqueRectsArray = [ ]; + for (key in uniqueRects) { + uniqueRectsArray.push(uniqueRects[key]); + } + + return uniqueRectsArray; + }, + + /** + * Renders brush + */ + render: function() { + var ctx = this.canvas.contextTop; + ctx.fillStyle = this.color; + ctx.save(); + + for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) { + var point = this.sprayChunkPoints[i]; + if (typeof point.opacity !== 'undefined') { + ctx.globalAlpha = point.opacity; + } + ctx.fillRect(point.x, point.y, point.width, point.width); + } + ctx.restore(); + }, + + /** + * @param {Object} pointer + */ + addSprayChunk: function(pointer) { + this.sprayChunkPoints = [ ]; + + var x, y, width, radius = this.width / 2; + + for (var i = 0; i < this.density; i++) { + + x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius); + y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius); + + if (this.dotWidthVariance) { + width = fabric.util.getRandomInt( + // bottom clamp width to 1 + Math.max(1, this.dotWidth - this.dotWidthVariance), + this.dotWidth + this.dotWidthVariance); + } + else { + width = this.dotWidth; + } + + var point = { x: x, y: y, width: width }; + + if (this.randomOpacity) { + point.opacity = fabric.util.getRandomInt(0, 100) / 100; + } + + this.sprayChunkPoints.push(point); + } + + this.sprayChunks.push(this.sprayChunkPoints); + } +}); +/** + * PatternBrush class + * @class fabric.PatternBrush + * @extends fabric.BaseBrush + */ +fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fabric.PatternBrush.prototype */ { + + getPatternSrc: function() { + + var dotWidth = 20, + dotDistance = 5, + patternCanvas = fabric.document.createElement('canvas'), + patternCtx = patternCanvas.getContext('2d'); + + patternCanvas.width = patternCanvas.height = dotWidth + dotDistance; + + patternCtx.fillStyle = this.color; + patternCtx.beginPath(); + patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); + patternCtx.closePath(); + patternCtx.fill(); + + return patternCanvas; + }, + + getPatternSrcFunction: function() { + return String(this.getPatternSrc).replace('this.color', '"' + this.color + '"'); + }, + + /** + * Creates "pattern" instance property + */ + getPattern: function() { + return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), 'repeat'); + }, + + /** + * Sets brush styles + */ + _setBrushStyles: function() { + this.callSuper('_setBrushStyles'); + this.canvas.contextTop.strokeStyle = this.getPattern(); + }, + + /** + * Creates path + */ + createPath: function(pathData) { + var path = this.callSuper('createPath', pathData); + path.stroke = new fabric.Pattern({ + source: this.source || this.getPatternSrcFunction() + }); + return path; + } +}); +(function() { + + var getPointer = fabric.util.getPointer, + degreesToRadians = fabric.util.degreesToRadians, + radiansToDegrees = fabric.util.radiansToDegrees, + atan2 = Math.atan2, + abs = Math.abs, + + STROKE_OFFSET = 0.5; + + /** + * Canvas class + * @class fabric.Canvas + * @extends fabric.StaticCanvas + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#canvas} + * @see {@link fabric.Canvas#initialize} for constructor definition + * + * @fires object:modified + * @fires object:rotating + * @fires object:scaling + * @fires object:moving + * @fires object:selected + * + * @fires before:selection:cleared + * @fires selection:cleared + * @fires selection:created + * + * @fires path:created + * @fires mouse:down + * @fires mouse:move + * @fires mouse:up + * + */ + fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ { + + /** + * Constructor + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(el, options) { + options || (options = { }); + + this._initStatic(el, options); + this._initInteractive(); + this._createCacheCanvas(); + + fabric.Canvas.activeInstance = this; + }, + + /** + * When true, objects can be transformed by one side (unproportionally) + * @type Boolean + * @default + */ + uniScaleTransform: false, + + /** + * When true, objects use center point as the origin of scale transformation. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredScaling: false, + + /** + * When true, objects use center point as the origin of rotate transformation. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredRotation: false, + + /** + * Indicates that canvas is interactive. This property should not be changed. + * @type Boolean + * @default + */ + interactive: true, + + /** + * Indicates whether group selection should be enabled + * @type Boolean + * @default + */ + selection: true, + + /** + * Color of selection + * @type String + * @default + */ + selectionColor: 'rgba(100, 100, 255, 0.3)', // blue + + /** + * Default dash array pattern + * If not empty the selection border is dashed + * @type Array + */ + selectionDashArray: [ ], + + /** + * Color of the border of selection (usually slightly darker than color of selection itself) + * @type String + * @default + */ + selectionBorderColor: 'rgba(255, 255, 255, 0.3)', + + /** + * Width of a line used in object/group selection + * @type Number + * @default + */ + selectionLineWidth: 1, + + /** + * Default cursor value used when hovering over an object on canvas + * @type String + * @default + */ + hoverCursor: 'move', + + /** + * Default cursor value used when moving an object on canvas + * @type String + * @default + */ + moveCursor: 'move', + + /** + * Default cursor value used for the entire canvas + * @type String + * @default + */ + defaultCursor: 'default', + + /** + * Cursor value used during free drawing + * @type String + * @default + */ + freeDrawingCursor: 'crosshair', + + /** + * Cursor value used for rotation point + * @type String + * @default + */ + rotationCursor: 'crosshair', + + /** + * Default element class that's given to wrapper (div) element of canvas + * @type String + * @default + */ + containerClass: 'canvas-container', + + /** + * When true, object detection happens on per-pixel basis rather than on per-bounding-box + * @type Boolean + * @default + */ + perPixelTargetFind: false, + + /** + * Number of pixels around target pixel to tolerate (consider active) during object detection + * @type Number + * @default + */ + targetFindTolerance: 0, + + /** + * When true, target detection is skipped when hovering over canvas. This can be used to improve performance. + * @type Boolean + * @default + */ + skipTargetFind: false, + + /** + * @private + */ + _initInteractive: function() { + this._currentTransform = null; + this._groupSelector = null; + this._initWrapperElement(); + this._createUpperCanvas(); + this._initEventListeners(); + + this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this); + + this.calcOffset(); + }, + + /** + * Resets the current transform to its original values and chooses the type of resizing based on the event + * @private + * @param {Event} e Event object fired on mousemove + */ + _resetCurrentTransform: function(e) { + var t = this._currentTransform; + + t.target.set({ + 'scaleX': t.original.scaleX, + 'scaleY': t.original.scaleY, + 'left': t.original.left, + 'top': t.original.top + }); + + if (this._shouldCenterTransform(e, t.target)) { + if (t.action === 'rotate') { + this._setOriginToCenter(t.target); + } + else { + if (t.originX !== 'center') { + if (t.originX === 'right') { + t.mouseXSign = -1; + } + else { + t.mouseXSign = 1; + } + } + if (t.originY !== 'center') { + if (t.originY === 'bottom') { + t.mouseYSign = -1; + } + else { + t.mouseYSign = 1; + } + } + + t.originX = 'center'; + t.originY = 'center'; + } + } + else { + t.originX = t.original.originX; + t.originY = t.original.originY; + } + }, + + /** + * Checks if point is contained within an area of given object + * @param {Event} e Event object + * @param {fabric.Object} target Object to test against + * @return {Boolean} true if point is contained within an area of given object + */ + containsPoint: function (e, target) { + var pointer = this.getPointer(e), + xy = this._normalizePointer(target, pointer); + + // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html + // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html + return (target.containsPoint(xy) || target._findTargetCorner(e, this._offset)); + }, + + /** + * @private + */ + _normalizePointer: function (object, pointer) { + var activeGroup = this.getActiveGroup(), + x = pointer.x, + y = pointer.y; + + var isObjectInGroup = ( + activeGroup && + object.type !== 'group' && + activeGroup.contains(object) + ); + + if (isObjectInGroup) { + x -= activeGroup.left; + y -= activeGroup.top; + } + return { x: x, y: y }; + }, + + /** + * Returns true if object is transparent at a certain location + * @param {fabric.Object} target Object to check + * @param {Number} x Left coordinate + * @param {Number} y Top coordinate + * @return {Boolean} + */ + isTargetTransparent: function (target, x, y) { + var hasBorders = target.hasBorders, + transparentCorners = target.transparentCorners; + + target.hasBorders = target.transparentCorners = false; + + this._draw(this.contextCache, target); + + target.hasBorders = hasBorders; + target.transparentCorners = transparentCorners; + + var isTransparent = fabric.util.isTransparent( + this.contextCache, x, y, this.targetFindTolerance); + + this.clearContext(this.contextCache); + + return isTransparent; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _shouldClearSelection: function (e, target) { + var activeGroup = this.getActiveGroup(), + activeObject = this.getActiveObject(); + + return ( + !target + || + (target && + activeGroup && + !activeGroup.contains(target) && + activeGroup !== target && + !e.shiftKey) + || + (target && !target.evented) + || + (target && + !target.selectable && + activeObject && + activeObject !== target) + ); + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _shouldCenterTransform: function (e, target) { + if (!target) return; + + var t = this._currentTransform, + centerTransform; + + if (t.action === 'scale' || t.action === 'scaleX' || t.action === 'scaleY') { + centerTransform = this.centeredScaling || target.centeredScaling; + } + else if (t.action === 'rotate') { + centerTransform = this.centeredRotation || target.centeredRotation; + } + + return centerTransform ? !e.altKey : e.altKey; + }, + + /** + * @private + */ + _getOriginFromCorner: function(target, corner) { + var origin = { + x: target.originX, + y: target.originY + }; + + if (corner === 'ml' || corner === 'tl' || corner === 'bl') { + origin.x = 'right'; + } + else if (corner === 'mr' || corner === 'tr' || corner === 'br') { + origin.x = 'left'; + } + + if (corner === 'tl' || corner === 'mt' || corner === 'tr') { + origin.y = 'bottom'; + } + else if (corner === 'bl' || corner === 'mb' || corner === 'br') { + origin.y = 'top'; + } + + return origin; + }, + + /** + * @private + */ + _getActionFromCorner: function(target, corner) { + var action = 'drag'; + if (corner) { + action = (corner === 'ml' || corner === 'mr') + ? 'scaleX' + : (corner === 'mt' || corner === 'mb') + ? 'scaleY' + : corner === 'mtr' + ? 'rotate' + : 'scale'; + } + return action; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _setupCurrentTransform: function (e, target) { + if (!target) return; + + var corner = target._findTargetCorner(e, this._offset), + pointer = getPointer(e, target.canvas.upperCanvasEl), + action = this._getActionFromCorner(target, corner), + origin = this._getOriginFromCorner(target, corner); + + this._currentTransform = { + target: target, + action: action, + scaleX: target.scaleX, + scaleY: target.scaleY, + offsetX: pointer.x - target.left, + offsetY: pointer.y - target.top, + originX: origin.x, + originY: origin.y, + ex: pointer.x, + ey: pointer.y, + left: target.left, + top: target.top, + theta: degreesToRadians(target.angle), + width: target.width * target.scaleX, + mouseXSign: 1, + mouseYSign: 1 + }; + + this._currentTransform.original = { + left: target.left, + top: target.top, + scaleX: target.scaleX, + scaleY: target.scaleY, + originX: origin.x, + originY: origin.y + }; + + this._resetCurrentTransform(e); + }, + + /** + * Translates object by "setting" its left/top + * @private + * @param x {Number} pointer's x coordinate + * @param y {Number} pointer's y coordinate + */ + _translateObject: function (x, y) { + var target = this._currentTransform.target; + + if (!target.get('lockMovementX')) { + target.set('left', x - this._currentTransform.offsetX); + } + if (!target.get('lockMovementY')) { + target.set('top', y - this._currentTransform.offsetY); + } + }, + + /** + * Scales object by invoking its scaleX/scaleY methods + * @private + * @param x {Number} pointer's x coordinate + * @param y {Number} pointer's y coordinate + * @param by {String} Either 'x' or 'y' - specifies dimension constraint by which to scale an object. + * When not provided, an object is scaled by both dimensions equally + */ + _scaleObject: function (x, y, by) { + var t = this._currentTransform, + offset = this._offset, + target = t.target, + lockScalingX = target.get('lockScalingX'), + lockScalingY = target.get('lockScalingY'); + + if (lockScalingX && lockScalingY) return; + + // Get the constraint point + var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY); + var localMouse = target.toLocalPoint(new fabric.Point(x - offset.left, y - offset.top), t.originX, t.originY); + + this._setLocalMouse(localMouse, t); + + // Actually scale the object + this._setObjectScale(localMouse, t, lockScalingX, lockScalingY, by); + + // Make sure the constraints apply + target.setPositionByOrigin(constraintPosition, t.originX, t.originY); + }, + + /** + * @private + */ + _setObjectScale: function(localMouse, transform, lockScalingX, lockScalingY, by) { + var target = transform.target; + + transform.newScaleX = target.scaleX; + transform.newScaleY = target.scaleY; + + if (by === 'equally' && !lockScalingX && !lockScalingY) { + this._scaleObjectEqually(localMouse, target, transform); + } + else if (!by) { + transform.newScaleX = localMouse.x / (target.width + target.strokeWidth); + transform.newScaleY = localMouse.y / (target.height + target.strokeWidth); + + lockScalingX || target.set('scaleX', transform.newScaleX); + lockScalingY || target.set('scaleY', transform.newScaleY); + } + else if (by === 'x' && !target.get('lockUniScaling')) { + transform.newScaleX = localMouse.x / (target.width + target.strokeWidth); + lockScalingX || target.set('scaleX', transform.newScaleX); + } + else if (by === 'y' && !target.get('lockUniScaling')) { + transform.newScaleY = localMouse.y / (target.height + target.strokeWidth); + lockScalingY || target.set('scaleY', transform.newScaleY); + } + + this._flipObject(transform); + }, + + /** + * @private + */ + _scaleObjectEqually: function(localMouse, target, transform) { + + var dist = localMouse.y + localMouse.x; + + var lastDist = (target.height + (target.strokeWidth)) * transform.original.scaleY + + (target.width + (target.strokeWidth)) * transform.original.scaleX; + + // We use transform.scaleX/Y instead of target.scaleX/Y + // because the object may have a min scale and we'll loose the proportions + transform.newScaleX = transform.original.scaleX * dist / lastDist; + transform.newScaleY = transform.original.scaleY * dist / lastDist; + + target.set('scaleX', transform.newScaleX); + target.set('scaleY', transform.newScaleY); + }, + + /** + * @private + */ + _flipObject: function(transform) { + if (transform.newScaleX < 0) { + if (transform.originX === 'left') { + transform.originX = 'right'; + } + else if (transform.originX === 'right') { + transform.originX = 'left'; + } + } + + if (transform.newScaleY < 0) { + if (transform.originY === 'top') { + transform.originY = 'bottom'; + } + else if (transform.originY === 'bottom') { + transform.originY = 'top'; + } + } + }, + + /** + * @private + */ + _setLocalMouse: function(localMouse, t) { + var target = t.target; + + if (t.originX === 'right') { + localMouse.x *= -1; + } + else if (t.originX === 'center') { + localMouse.x *= t.mouseXSign * 2; + + if (localMouse.x < 0) { + t.mouseXSign = -t.mouseXSign; + } + } + + if (t.originY === 'bottom') { + localMouse.y *= -1; + } + else if (t.originY === 'center') { + localMouse.y *= t.mouseYSign * 2; + + if (localMouse.y < 0) { + t.mouseYSign = -t.mouseYSign; + } + } + + // adjust the mouse coordinates when dealing with padding + if (abs(localMouse.x) > target.padding) { + if (localMouse.x < 0) { + localMouse.x += target.padding; + } + else { + localMouse.x -= target.padding; + } + } + else { // mouse is within the padding, set to 0 + localMouse.x = 0; + } + + if (abs(localMouse.y) > target.padding) { + if (localMouse.y < 0) { + localMouse.y += target.padding; + } + else { + localMouse.y -= target.padding; + } + } + else { + localMouse.y = 0; + } + }, + + /** + * Rotates object by invoking its rotate method + * @private + * @param x {Number} pointer's x coordinate + * @param y {Number} pointer's y coordinate + */ + _rotateObject: function (x, y) { + + var t = this._currentTransform, + o = this._offset; + + if (t.target.get('lockRotation')) return; + + var lastAngle = atan2(t.ey - t.top - o.top, t.ex - t.left - o.left), + curAngle = atan2(y - t.top - o.top, x - t.left - o.left), + angle = radiansToDegrees(curAngle - lastAngle + t.theta); + + // normalize angle to positive value + if (angle < 0) { + angle = 360 + angle; + } + + t.target.angle = angle; + }, + + /** + * @private + */ + _setCursor: function (value) { + this.upperCanvasEl.style.cursor = value; + }, + + /** + * @private + */ + _resetObjectTransform: function (target) { + target.scaleX = 1; + target.scaleY = 1; + target.setAngle(0); + }, + + /** + * @private + */ + _drawSelection: function () { + var ctx = this.contextTop, + groupSelector = this._groupSelector, + left = groupSelector.left, + top = groupSelector.top, + aleft = abs(left), + atop = abs(top); + + ctx.fillStyle = this.selectionColor; + + ctx.fillRect( + groupSelector.ex - ((left > 0) ? 0 : -left), + groupSelector.ey - ((top > 0) ? 0 : -top), + aleft, + atop + ); + + ctx.lineWidth = this.selectionLineWidth; + ctx.strokeStyle = this.selectionBorderColor; + + // selection border + if (this.selectionDashArray.length > 1) { + + var px = groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0: aleft); + var py = groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0: atop); + + ctx.beginPath(); + + fabric.util.drawDashedLine(ctx, px, py, px+aleft, py, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px, py+atop-1, px+aleft, py+atop-1, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px, py, px, py+atop, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px+aleft-1, py, px+aleft-1, py+atop, this.selectionDashArray); + + ctx.closePath(); + ctx.stroke(); + } + else { + ctx.strokeRect( + groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft), + groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop), + aleft, + atop + ); + } + }, + + /** + * @private + */ + _isLastRenderedObject: function(e) { + return ( + this.controlsAboveOverlay && + this.lastRenderedObjectWithControlsAboveOverlay && + this.lastRenderedObjectWithControlsAboveOverlay.visible && + this.containsPoint(e, this.lastRenderedObjectWithControlsAboveOverlay) && + this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(e, this._offset)); + }, + + /** + * Method that determines what object we are clicking on + * @param {Event} e mouse event + * @param {Boolean} skipGroup when true, group is skipped and only objects are traversed through + */ + findTarget: function (e, skipGroup) { + if (this.skipTargetFind) return; + + if (this._isLastRenderedObject(e)) { + return this.lastRenderedObjectWithControlsAboveOverlay; + } + + // first check current group (if one exists) + var activeGroup = this.getActiveGroup(); + if (activeGroup && !skipGroup && this.containsPoint(e, activeGroup)) { + return activeGroup; + } + + return this._searchPossibleTargets(e); + }, + + /** + * @private + */ + _searchPossibleTargets: function(e) { + + // Cache all targets where their bounding box contains point. + var possibleTargets = [], + target, + pointer = this.getPointer(e); + + for (var i = this._objects.length; i--; ) { + if (this._objects[i] && + this._objects[i].visible && + this._objects[i].evented && + this.containsPoint(e, this._objects[i])) { + + if (this.perPixelTargetFind || this._objects[i].perPixelTargetFind) { + possibleTargets[possibleTargets.length] = this._objects[i]; + } + else { + target = this._objects[i]; + this.relatedTarget = target; + break; + } + } + } + + for (var j = 0, len = possibleTargets.length; j < len; j++) { + pointer = this.getPointer(e); + var isTransparent = this.isTargetTransparent(possibleTargets[j], pointer.x, pointer.y); + if (!isTransparent) { + target = possibleTargets[j]; + this.relatedTarget = target; + break; + } + } + + return target; + }, + + /** + * Returns pointer coordinates relative to canvas. + * @param {Event} e + * @return {Object} object with "x" and "y" number values + */ + getPointer: function (e) { + var pointer = getPointer(e, this.upperCanvasEl); + return { + x: pointer.x - this._offset.left, + y: pointer.y - this._offset.top + }; + }, + + /** + * @private + * @param {HTMLElement|String} canvasEl Canvas element + * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized + */ + _createUpperCanvas: function () { + var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/, ''); + + this.upperCanvasEl = this._createCanvasElement(); + fabric.util.addClass(this.upperCanvasEl, 'upper-canvas ' + lowerCanvasClass); + + this.wrapperEl.appendChild(this.upperCanvasEl); + + this._copyCanvasStyle(this.lowerCanvasEl, this.upperCanvasEl); + this._applyCanvasStyle(this.upperCanvasEl); + this.contextTop = this.upperCanvasEl.getContext('2d'); + }, + + /** + * @private + */ + _createCacheCanvas: function () { + this.cacheCanvasEl = this._createCanvasElement(); + this.cacheCanvasEl.setAttribute('width', this.width); + this.cacheCanvasEl.setAttribute('height', this.height); + this.contextCache = this.cacheCanvasEl.getContext('2d'); + }, + + /** + * @private + * @param {Number} width + * @param {Number} height + */ + _initWrapperElement: function () { + this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', { + 'class': this.containerClass + }); + fabric.util.setStyle(this.wrapperEl, { + width: this.getWidth() + 'px', + height: this.getHeight() + 'px', + position: 'relative' + }); + fabric.util.makeElementUnselectable(this.wrapperEl); + }, + + /** + * @private + * @param {Element} element + */ + _applyCanvasStyle: function (element) { + var width = this.getWidth() || element.width, + height = this.getHeight() || element.height; + + fabric.util.setStyle(element, { + position: 'absolute', + width: width + 'px', + height: height + 'px', + left: 0, + top: 0 + }); + element.width = width; + element.height = height; + fabric.util.makeElementUnselectable(element); + }, + + /** + * Copys the the entire inline style from one element (fromEl) to another (toEl) + * @private + * @param {Element} fromEl Element style is copied from + * @param {Element} toEl Element copied style is applied to + */ + _copyCanvasStyle: function (fromEl, toEl) { + toEl.style.cssText = fromEl.style.cssText; + }, + + /** + * Returns context of canvas where object selection is drawn + * @return {CanvasRenderingContext2D} + */ + getSelectionContext: function() { + return this.contextTop; + }, + + /** + * Returns <canvas> element on which object selection is drawn + * @return {HTMLCanvasElement} + */ + getSelectionElement: function () { + return this.upperCanvasEl; + }, + + /** + * @private + * @param {Object} object + */ + _setActiveObject: function(object) { + if (this._activeObject) { + this._activeObject.set('active', false); + } + this._activeObject = object; + object.set('active', true); + }, + + /** + * Sets given object as the only active object on canvas + * @param {fabric.Object} object Object to set as an active one + * @param {Event} [e] Event (passed along when firing "object:selected") + * @return {fabric.Canvas} thisArg + * @chainable + */ + setActiveObject: function (object, e) { + this._setActiveObject(object); + this.renderAll(); + this.fire('object:selected', { target: object, e: e }); + object.fire('selected', { e: e }); + return this; + }, + + /** + * Returns currently active object + * @return {fabric.Object} active object + */ + getActiveObject: function () { + return this._activeObject; + }, + + /** + * @private + */ + _discardActiveObject: function() { + if (this._activeObject) { + this._activeObject.set('active', false); + } + this._activeObject = null; + }, + + /** + * Discards currently active object + * @return {fabric.Canvas} thisArg + * @chainable + */ + discardActiveObject: function (e) { + this._discardActiveObject(); + this.renderAll(); + this.fire('selection:cleared', { e: e }); + return this; + }, + + /** + * @private + * @param {fabric.Group} group + */ + _setActiveGroup: function(group) { + this._activeGroup = group; + if (group) { + group.canvas = this; + group.set('active', true); + } + }, + + /** + * Sets active group to a speicified one + * @param {fabric.Group} group Group to set as a current one + * @return {fabric.Canvas} thisArg + * @chainable + */ + setActiveGroup: function (group, e) { + this._setActiveGroup(group); + if (group) { + this.fire('object:selected', { target: group, e: e }); + group.fire('selected', { e: e }); + } + return this; + }, + + /** + * Returns currently active group + * @return {fabric.Group} Current group + */ + getActiveGroup: function () { + return this._activeGroup; + }, + + /** + * @private + */ + _discardActiveGroup: function() { + var g = this.getActiveGroup(); + if (g) { + g.destroy(); + } + this.setActiveGroup(null); + }, + + /** + * Discards currently active group + * @return {fabric.Canvas} thisArg + */ + discardActiveGroup: function (e) { + this._discardActiveGroup(); + this.fire('selection:cleared', { e: e }); + return this; + }, + + /** + * Deactivates all objects on canvas, removing any active group or object + * @return {fabric.Canvas} thisArg + */ + deactivateAll: function () { + var allObjects = this.getObjects(), + i = 0, + len = allObjects.length; + for ( ; i < len; i++) { + allObjects[i].set('active', false); + } + this._discardActiveGroup(); + this._discardActiveObject(); + return this; + }, + + /** + * Deactivates all objects and dispatches appropriate events + * @return {fabric.Canvas} thisArg + */ + deactivateAllWithDispatch: function (e) { + var activeObject = this.getActiveGroup() || this.getActiveObject(); + if (activeObject) { + this.fire('before:selection:cleared', { target: activeObject, e: e }); + } + this.deactivateAll(); + if (activeObject) { + this.fire('selection:cleared', { e: e }); + } + return this; + }, + + /** + * Draws objects' controls (borders/controls) + * @param {CanvasRenderingContext2D} ctx Context to render controls on + */ + drawControls: function(ctx) { + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this._drawGroupControls(ctx, activeGroup); + } + else { + this._drawObjectsControls(ctx); + } + }, + + /** + * @private + */ + _drawGroupControls: function(ctx, activeGroup) { + this._drawControls(ctx, activeGroup, 'Group'); + }, + + /** + * @private + */ + _drawObjectsControls: function(ctx) { + for (var i = 0, len = this._objects.length; i < len; ++i) { + if (!this._objects[i] || !this._objects[i].active) continue; + this._drawControls(ctx, this._objects[i], 'Object'); + this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i]; + } + }, + + /** + * @private + */ + _drawControls: function(ctx, object, klass) { + ctx.save(); + fabric[klass].prototype.transform.call(object, ctx); + object.drawBorders(ctx).drawControls(ctx); + ctx.restore(); + } + }); + + // copying static properties manually to work around Opera's bug, + // where "prototype" property is enumerable and overrides existing prototype + for (var prop in fabric.StaticCanvas) { + if (prop !== 'prototype') { + fabric.Canvas[prop] = fabric.StaticCanvas[prop]; + } + } + + if (fabric.isTouchSupported) { + /** @ignore */ + fabric.Canvas.prototype._setCursorFromEvent = function() { }; + } + + /** + * @class fabric.Element + * @alias fabric.Canvas + * @deprecated Use {@link fabric.Canvas} instead. + * @constructor + */ + fabric.Element = fabric.Canvas; +})(); +(function(){ + + var cursorMap = [ + 'n-resize', + 'ne-resize', + 'e-resize', + 'se-resize', + 's-resize', + 'sw-resize', + 'w-resize', + 'nw-resize' + ], + cursorOffset = { + 'mt': 0, // n + 'tr': 1, // ne + 'mr': 2, // e + 'br': 3, // se + 'mb': 4, // s + 'bl': 5, // sw + 'ml': 6, // w + 'tl': 7 // nw + }, + addListener = fabric.util.addListener, + removeListener = fabric.util.removeListener, + getPointer = fabric.util.getPointer; + + fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ { + + /** + * Adds mouse listeners to canvas + * @private + */ + _initEventListeners: function () { + + this._bindEvents(); + + addListener(fabric.window, 'resize', this._onResize); + + // mouse events + addListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); + addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + addListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel); + + // touch events + addListener(this.upperCanvasEl, 'touchstart', this._onMouseDown); + addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (typeof Event !== 'undefined' && 'add' in Event) { + Event.add(this.upperCanvasEl, 'gesture', this._onGesture); + Event.add(this.upperCanvasEl, 'drag', this._onDrag); + Event.add(this.upperCanvasEl, 'orientation', this._onOrientationChange); + Event.add(this.upperCanvasEl, 'shake', this._onShake); + } + }, + + /** + * @private + */ + _bindEvents: function() { + this._onMouseDown = this._onMouseDown.bind(this); + this._onMouseMove = this._onMouseMove.bind(this); + this._onMouseUp = this._onMouseUp.bind(this); + this._onResize = this._onResize.bind(this); + this._onGesture = this._onGesture.bind(this); + this._onDrag = this._onDrag.bind(this); + this._onShake = this._onShake.bind(this); + this._onOrientationChange = this._onOrientationChange.bind(this); + this._onMouseWheel = this._onMouseWheel.bind(this); + }, + + /** + * Removes all event listeners + */ + removeListeners: function() { + removeListener(fabric.window, 'resize', this._onResize); + + removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); + removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + removeListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel); + + removeListener(this.upperCanvasEl, 'touchstart', this._onMouseDown); + removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (typeof Event !== 'undefined' && 'remove' in Event) { + Event.remove(this.upperCanvasEl, 'gesture', this._onGesture); + Event.remove(this.upperCanvasEl, 'drag', this._onDrag); + Event.remove(this.upperCanvasEl, 'orientation', this._onOrientationChange); + Event.remove(this.upperCanvasEl, 'shake', this._onShake); + } + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js gesture + * @param {Event} [self] Inner Event object + */ + _onGesture: function(e, s) { + this.__onTransformGesture && this.__onTransformGesture(e, s); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js drag + * @param {Event} [self] Inner Event object + */ + _onDrag: function(e, s) { + this.__onDrag && this.__onDrag(e, s); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js wheel event + * @param {Event} [self] Inner Event object + */ + _onMouseWheel: function(e, s) { + this.__onMouseWheel && this.__onMouseWheel(e, s); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js orientation change + * @param {Event} [self] Inner Event object + */ + _onOrientationChange: function(e,s) { + this.__onOrientationChange && this.__onOrientationChange(e,s); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js shake + * @param {Event} [self] Inner Event object + */ + _onShake: function(e,s) { + this.__onShake && this.__onShake(e,s); + }, + + /** + * @private + * @param {Event} e Event object fired on mousedown + */ + _onMouseDown: function (e) { + this.__onMouseDown(e); + + addListener(fabric.document, 'mouseup', this._onMouseUp); + addListener(fabric.document, 'touchend', this._onMouseUp); + + addListener(fabric.document, 'mousemove', this._onMouseMove); + addListener(fabric.document, 'touchmove', this._onMouseMove); + + removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + }, + + /** + * @private + * @param {Event} e Event object fired on mouseup + */ + _onMouseUp: function (e) { + this.__onMouseUp(e); + + removeListener(fabric.document, 'mouseup', this._onMouseUp); + removeListener(fabric.document, 'touchend', this._onMouseUp); + + removeListener(fabric.document, 'mousemove', this._onMouseMove); + removeListener(fabric.document, 'touchmove', this._onMouseMove); + + addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + }, + + /** + * @private + * @param {Event} e Event object fired on mousemove + */ + _onMouseMove: function (e) { + !this.allowTouchScrolling && e.preventDefault && e.preventDefault(); + this.__onMouseMove(e); + }, + + /** + * @private + */ + _onResize: function () { + this.calcOffset(); + }, + + /** + * Decides whether the canvas should be redrawn in mouseup and mousedown events. + * @private + * @param {Object} target + * @param {Object} pointer + */ + _shouldRender: function(target, pointer) { + var activeObject = this.getActiveGroup() || this.getActiveObject(); + + return !!( + (target && ( + target.isMoving || + target !== activeObject)) + || + (!target && !!activeObject) + || + (!target && !activeObject && !this._groupSelector) + || + (pointer && + this._previousPointer && + this.selection && ( + pointer.x !== this._previousPointer.x || + pointer.y !== this._previousPointer.y)) + ); + }, + + /** + * Method that defines the actions when mouse is released on canvas. + * The method resets the currentTransform parameters, store the image corner + * position in the image object and render the canvas on top. + * @private + * @param {Event} e Event object fired on mouseup + */ + __onMouseUp: function (e) { + var target; + + if (this.isDrawingMode && this._isCurrentlyDrawing) { + this._onMouseUpInDrawingMode(e); + return; + } + + if (this._currentTransform) { + this._finalizeCurrentTransform(); + target = this._currentTransform.target; + } + else { + target = this.findTarget(e, true); + } + + var shouldRender = this._shouldRender(target, this.getPointer(e)); + + this._maybeGroupObjects(e); + + if (target) { + target.isMoving = false; + } + + shouldRender && this.renderAll(); + + this._handleCursorAndEvent(e, target); + }, + + _handleCursorAndEvent: function(e, target) { + this._setCursorFromEvent(e, target); + + // TODO: why are we doing this? + var _this = this; + setTimeout(function () { + _this._setCursorFromEvent(e, target); + }, 50); + + this.fire('mouse:up', { target: target, e: e }); + target && target.fire('mouseup', { e: e }); + }, + + /** + * @private + */ + _finalizeCurrentTransform: function() { + + var transform = this._currentTransform; + var target = transform.target; + + if (target._scaling) { + target._scaling = false; + } + + target.setCoords(); + + // only fire :modified event if target coordinates were changed during mousedown-mouseup + if (this.stateful && target.hasStateChanged()) { + this.fire('object:modified', { target: target }); + target.fire('modified'); + } + + this._restoreOriginXY(target); + }, + + /** + * @private + * @param {Object} target Object to restore + */ + _restoreOriginXY: function(target) { + if (this._previousOriginX && this._previousOriginY) { + + var originPoint = target.translateToOriginPoint( + target.getCenterPoint(), + this._previousOriginX, + this._previousOriginY); + + target.originX = this._previousOriginX; + target.originY = this._previousOriginY; + + target.left = originPoint.x; + target.top = originPoint.y; + + this._previousOriginX = null; + this._previousOriginY = null; + } + }, + + /** + * @private + * @param {Event} e Event object fired on mousedown + */ + _onMouseDownInDrawingMode: function(e) { + this._isCurrentlyDrawing = true; + this.discardActiveObject(e).renderAll(); + if (this.clipTo) { + fabric.util.clipContext(this, this.contextTop); + } + this.freeDrawingBrush.onMouseDown(this.getPointer(e)); + this.fire('mouse:down', { e: e }); + }, + + /** + * @private + * @param {Event} e Event object fired on mousemove + */ + _onMouseMoveInDrawingMode: function(e) { + if (this._isCurrentlyDrawing) { + var pointer = this.getPointer(e); + this.freeDrawingBrush.onMouseMove(pointer); + } + this.upperCanvasEl.style.cursor = this.freeDrawingCursor; + this.fire('mouse:move', { e: e }); + }, + + /** + * @private + * @param {Event} e Event object fired on mouseup + */ + _onMouseUpInDrawingMode: function(e) { + this._isCurrentlyDrawing = false; + if (this.clipTo) { + this.contextTop.restore(); + } + this.freeDrawingBrush.onMouseUp(); + this.fire('mouse:up', { e: e }); + }, + + /** + * Method that defines the actions when mouse is clic ked on canvas. + * The method inits the currentTransform parameters and renders all the + * canvas so the current image can be placed on the top canvas and the rest + * in on the container one. + * @private + * @param {Event} e Event object fired on mousedown + */ + __onMouseDown: function (e) { + + // accept only left clicks + var isLeftClick = 'which' in e ? e.which === 1 : e.button === 1; + if (!isLeftClick && !fabric.isTouchSupported) return; + + if (this.isDrawingMode) { + this._onMouseDownInDrawingMode(e); + return; + } + + // ignore if some object is being transformed at this moment + if (this._currentTransform) return; + + var target = this.findTarget(e), + pointer = this.getPointer(e); + + // save pointer for check in __onMouseUp event + this._previousPointer = pointer; + + var shouldRender = this._shouldRender(target, pointer), + shouldGroup = this._shouldGroup(e, target); + + if (this._shouldClearSelection(e, target)) { + this._clearSelection(e, target, pointer); + } + else if (shouldGroup) { + this._handleGrouping(e, target); + target = this.getActiveGroup(); + } + + if (target && target.selectable && !shouldGroup) { + this._beforeTransform(e, target); + this._setupCurrentTransform(e, target); + } + // we must renderAll so that active image is placed on the top canvas + shouldRender && this.renderAll(); + + this.fire('mouse:down', { target: target, e: e }); + target && target.fire('mousedown', { e: e }); + }, + + /** + * @private + */ + _beforeTransform: function(e, target) { + var corner; + + this.stateful && target.saveState(); + + // determine if it's a drag or rotate case + if ((corner = target._findTargetCorner(e, this._offset))) { + this.onBeforeScaleRotate(target); + } + + if (target !== this.getActiveGroup() && target !== this.getActiveObject()) { + this.deactivateAll(); + this.setActiveObject(target, e); + } + }, + + /** + * @private + */ + _clearSelection: function(e, target, pointer) { + this.deactivateAllWithDispatch(e); + + if (target && target.selectable) { + this.setActiveObject(target, e); + } + else if (this.selection) { + this._groupSelector = { + ex: pointer.x, + ey: pointer.y, + top: 0, + left: 0 + }; + } + }, + + /** + * @private + * @param {Object} target Object for that origin is set to center + */ + _setOriginToCenter: function(target) { + this._previousOriginX = this._currentTransform.target.originX; + this._previousOriginY = this._currentTransform.target.originY; + + var center = target.getCenterPoint(); + + target.originX = 'center'; + target.originY = 'center'; + + target.left = center.x; + target.top = center.y; + + this._currentTransform.left = target.left; + this._currentTransform.top = target.top; + }, + + /** + * @private + * @param {Object} target Object for that center is set to origin + */ + _setCenterToOrigin: function(target) { + var originPoint = target.translateToOriginPoint( + target.getCenterPoint(), + this._previousOriginX, + this._previousOriginY); + + target.originX = this._previousOriginX; + target.originY = this._previousOriginY; + + target.left = originPoint.x; + target.top = originPoint.y; + + this._previousOriginX = null; + this._previousOriginY = null; + }, + + /** + * Method that defines the actions when mouse is hovering the canvas. + * The currentTransform parameter will definde whether the user is rotating/scaling/translating + * an image or neither of them (only hovering). A group selection is also possible and would cancel + * all any other type of action. + * In case of an image transformation only the top canvas will be rendered. + * @private + * @param {Event} e Event object fired on mousemove + */ + __onMouseMove: function (e) { + + var target, pointer; + + if (this.isDrawingMode) { + this._onMouseMoveInDrawingMode(e); + return; + } + + var groupSelector = this._groupSelector; + + // We initially clicked in an empty area, so we draw a box for multiple selection + if (groupSelector) { + pointer = getPointer(e, this.upperCanvasEl); + + groupSelector.left = pointer.x - this._offset.left - groupSelector.ex; + groupSelector.top = pointer.y - this._offset.top - groupSelector.ey; + + this.renderTop(); + } + else if (!this._currentTransform) { + + target = this.findTarget(e); + + if (!target || target && !target.selectable) { + this.upperCanvasEl.style.cursor = this.defaultCursor; + } + else { + this._setCursorFromEvent(e, target); + } + } + else { + this._transformObject(e); + } + + this.fire('mouse:move', { target: target, e: e }); + target && target.fire('mousemove', { e: e }); + }, + + /** + * @private + * @param {Event} e Event fired on mousemove + */ + _transformObject: function(e) { + + var pointer = getPointer(e, this.upperCanvasEl), + transform = this._currentTransform; + + transform.reset = false, + transform.target.isMoving = true; + + this._beforeScaleTransform(e, transform); + this._performTransformAction(e, transform, pointer); + + this.renderAll(); + }, + + /** + * @private + */ + _performTransformAction: function(e, transform, pointer) { + var x = pointer.x, + y = pointer.y, + target = transform.target, + action = transform.action; + + if (action === 'rotate') { + this._rotateObject(x, y); + this._fire('rotating', target, e); + } + else if (action === 'scale') { + this._onScale(e, transform, x, y); + this._fire('scaling', target, e); + } + else if (action === 'scaleX') { + this._scaleObject(x, y, 'x'); + this._fire('scaling', target, e); + } + else if (action === 'scaleY') { + this._scaleObject(x, y, 'y'); + this._fire('scaling', target, e); + } + else { + this._translateObject(x, y); + this._fire('moving', target, e); + this._setCursor(this.moveCursor); + } + }, + + /** + * @private + */ + _fire: function(eventName, target, e) { + this.fire('object:' + eventName, { target: target, e: e}); + target.fire(eventName, { e: e }); + }, + + /** + * @private + */ + _beforeScaleTransform: function(e, transform) { + if (transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') { + var centerTransform = this._shouldCenterTransform(e, transform.target); + + // Switch from a normal resize to center-based + if ((centerTransform && (transform.originX !== 'center' || transform.originY !== 'center')) || + // Switch from center-based resize to normal one + (!centerTransform && transform.originX === 'center' && transform.originY === 'center') + ) { + this._resetCurrentTransform(e); + transform.reset = true; + } + } + }, + + /** + * @private + */ + _onScale: function(e, transform, x, y) { + // rotate object only if shift key is not pressed + // and if it is not a group we are transforming + if ((e.shiftKey || this.uniScaleTransform) && !transform.target.get('lockUniScaling')) { + transform.currentAction = 'scale'; + this._scaleObject(x, y); + } + else { + // Switch from a normal resize to proportional + if (!transform.reset && transform.currentAction === 'scale') { + this._resetCurrentTransform(e, transform.target); + } + + transform.currentAction = 'scaleEqually'; + this._scaleObject(x, y, 'equally'); + } + }, + + /** + * Sets the cursor depending on where the canvas is being hovered. + * Note: very buggy in Opera + * @param {Event} e Event object + * @param {Object} target Object that the mouse is hovering, if so. + */ + _setCursorFromEvent: function (e, target) { + var style = this.upperCanvasEl.style; + + if (!target || !target.selectable) { + style.cursor = this.defaultCursor; + return false; + } + else { + var activeGroup = this.getActiveGroup(); + // only show proper corner when group selection is not active + var corner = target._findTargetCorner + && (!activeGroup || !activeGroup.contains(target)) + && target._findTargetCorner(e, this._offset); + + if (!corner) { + style.cursor = target.hoverCursor || this.hoverCursor; + } + else { + this._setCornerCursor(corner, target); + } + } + return true; + }, + + /** + * @private + */ + _setCornerCursor: function(corner, target) { + var style = this.upperCanvasEl.style; + + if (corner in cursorOffset) { + style.cursor = this._getRotatedCornerCursor(corner, target); + } + else if (corner === 'mtr' && target.hasRotatingPoint) { + style.cursor = this.rotationCursor; + } + else { + style.cursor = this.defaultCursor; + return false; + } + }, + + /** + * @private + */ + _getRotatedCornerCursor: function(corner, target) { + var n = Math.round((target.getAngle() % 360) / 45); + + if (n < 0) { + n += 8; // full circle ahead + } + n += cursorOffset[corner]; + // normalize n to be from 0 to 7 + n %= 8; + + return cursorMap[n]; + } + }); +})(); +(function(){ + + var min = Math.min, + max = Math.max; + + fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ { + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + * @return {Boolean} + */ + _shouldGroup: function(e, target) { + var activeObject = this.getActiveObject(); + return e.shiftKey && + (this.getActiveGroup() || (activeObject && activeObject !== target)) + && this.selection; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _handleGrouping: function (e, target) { + + if (target === this.getActiveGroup()) { + + // if it's a group, find target again, this time skipping group + target = this.findTarget(e, true); + + // if even object is not found, bail out + if (!target || target.isType('group')) { + return; + } + } + if (this.getActiveGroup()) { + this._updateActiveGroup(target, e); + } + else { + this._createActiveGroup(target, e); + } + + if (this._activeGroup) { + this._activeGroup.saveCoords(); + } + }, + + /** + * @private + */ + _updateActiveGroup: function(target, e) { + var activeGroup = this.getActiveGroup(); + + if (activeGroup.contains(target)) { + + activeGroup.removeWithUpdate(target); + this._resetObjectTransform(activeGroup); + target.set('active', false); + + if (activeGroup.size() === 1) { + // remove group alltogether if after removal it only contains 1 object + this.discardActiveGroup(e); + // activate last remaining object + this.setActiveObject(activeGroup.item(0)); + return; + } + } + else { + activeGroup.addWithUpdate(target); + this._resetObjectTransform(activeGroup); + } + this.fire('selection:created', { target: activeGroup, e: e }); + activeGroup.set('active', true); + }, + + /** + * @private + */ + _createActiveGroup: function(target, e) { + + if (this._activeObject && target !== this._activeObject) { + + var group = this._createGroup(target); + + this.setActiveGroup(group); + this._activeObject = null; + + this.fire('selection:created', { target: group, e: e }); + } + + target.set('active', true); + }, + + /** + * @private + * @param {Object} target + */ + _createGroup: function(target) { + + var objects = this.getObjects(); + + var isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target); + + var groupObjects = isActiveLower + ? [ this._activeObject, target ] + : [ target, this._activeObject ]; + + return new fabric.Group(groupObjects, { + originX: 'center', + originY: 'center' + }); + }, + + /** + * @private + * @param {Event} e mouse event + */ + _groupSelectedObjects: function (e) { + + var group = this._collectObjects(); + + // do not create group for 1 element only + if (group.length === 1) { + this.setActiveObject(group[0], e); + } + else if (group.length > 1) { + group = new fabric.Group(group.reverse(), { + originX: 'center', + originY: 'center' + }); + this.setActiveGroup(group, e); + group.saveCoords(); + this.fire('selection:created', { target: group }); + this.renderAll(); + } + }, + + /** + * @private + */ + _collectObjects: function() { + var group = [ ], + currentObject, + x1 = this._groupSelector.ex, + y1 = this._groupSelector.ey, + x2 = x1 + this._groupSelector.left, + y2 = y1 + this._groupSelector.top, + selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)), + selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)), + isClick = x1 === x2 && y1 === y2; + + for (var i = this._objects.length; i--; ) { + currentObject = this._objects[i]; + + if (!currentObject || !currentObject.selectable || !currentObject.visible) continue; + + if (currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) || + currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) || + currentObject.containsPoint(selectionX1Y1) || + currentObject.containsPoint(selectionX2Y2) + ) { + currentObject.set('active', true); + group.push(currentObject); + + // only add one object if it's a click + if (isClick) break; + } + } + + return group; + }, + + /** + * @private + */ + _maybeGroupObjects: function(e) { + if (this.selection && this._groupSelector) { + this._groupSelectedObjects(e); + } + + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + activeGroup.setObjectsCoords().setCoords(); + activeGroup.isMoving = false; + this._setCursor(this.defaultCursor); + } + + // clear selection and current transformation + this._groupSelector = null; + this._currentTransform = null; + } + }); + +})(); +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately + * @param {Object} [options] Options object + * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png" + * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg. + * @param {Number} [options.multiplier=1] Multiplier to scale by + * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14 + * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14 + * @param {Number} [options.width] Cropping width. Introduced in v1.2.14 + * @param {Number} [options.height] Cropping height. Introduced in v1.2.14 + * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format + * @see {@link http://jsfiddle.net/fabricjs/NfZVb/|jsFiddle demo} + * @example Generate jpeg dataURL with lower quality + * var dataURL = canvas.toDataURL({ + * format: 'jpeg', + * quality: 0.8 + * }); + * @example Generate cropped png dataURL (clipping of canvas) + * var dataURL = canvas.toDataURL({ + * format: 'png', + * left: 100, + * top: 100, + * width: 200, + * height: 200 + * }); + * @example Generate double scaled png dataURL + * var dataURL = canvas.toDataURL({ + * format: 'png', + * multiplier: 2 + * }); + */ + toDataURL: function (options) { + options || (options = { }); + + var format = options.format || 'png', + quality = options.quality || 1, + multiplier = options.multiplier || 1, + cropping = { + left: options.left, + top: options.top, + width: options.width, + height: options.height + }; + + if (multiplier !== 1) { + return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier); + } + else { + return this.__toDataURL(format, quality, cropping); + } + }, + + /** + * @private + */ + __toDataURL: function(format, quality, cropping) { + + this.renderAll(true); + + var canvasEl = this.upperCanvasEl || this.lowerCanvasEl; + var croppedCanvasEl = this.__getCroppedCanvas(canvasEl, cropping); + + // to avoid common confusion https://github.com/kangax/fabric.js/issues/806 + if (format === 'jpg') { + format = 'jpeg'; + } + + var data = (fabric.StaticCanvas.supports('toDataURLWithQuality')) + ? (croppedCanvasEl || canvasEl).toDataURL('image/' + format, quality) + : (croppedCanvasEl || canvasEl).toDataURL('image/' + format); + + this.contextTop && this.clearContext(this.contextTop); + this.renderAll(); + + if (croppedCanvasEl) { + croppedCanvasEl = null; + } + + return data; + }, + + /** + * @private + */ + __getCroppedCanvas: function(canvasEl, cropping) { + + var croppedCanvasEl, + croppedCtx; + + var shouldCrop = 'left' in cropping || + 'top' in cropping || + 'width' in cropping || + 'height' in cropping; + + if (shouldCrop) { + + croppedCanvasEl = fabric.util.createCanvasElement(); + croppedCtx = croppedCanvasEl.getContext('2d'); + + croppedCanvasEl.width = cropping.width || this.width; + croppedCanvasEl.height = cropping.height || this.height; + + croppedCtx.drawImage(canvasEl, -cropping.left || 0, -cropping.top || 0); + } + + return croppedCanvasEl; + }, + + /** + * @private + */ + __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) { + + var origWidth = this.getWidth(), + origHeight = this.getHeight(), + scaledWidth = origWidth * multiplier, + scaledHeight = origHeight * multiplier, + activeObject = this.getActiveObject(), + activeGroup = this.getActiveGroup(), + + ctx = this.contextTop || this.contextContainer; + + this.setWidth(scaledWidth).setHeight(scaledHeight); + ctx.scale(multiplier, multiplier); + + if (cropping.left) { + cropping.left *= multiplier; + } + if (cropping.top) { + cropping.top *= multiplier; + } + if (cropping.width) { + cropping.width *= multiplier; + } + if (cropping.height) { + cropping.height *= multiplier; + } + + if (activeGroup) { + // not removing group due to complications with restoring it with correct state afterwords + this._tempRemoveBordersControlsFromGroup(activeGroup); + } + else if (activeObject && this.deactivateAll) { + this.deactivateAll(); + } + + this.renderAll(true); + + var data = this.__toDataURL(format, quality, cropping); + + // restoring width, height for `renderAll` to draw + // background properly (while context is scaled) + this.width = origWidth; + this.height = origHeight; + + ctx.scale(1 / multiplier, 1 / multiplier); + this.setWidth(origWidth).setHeight(origHeight); + + if (activeGroup) { + this._restoreBordersControlsOnGroup(activeGroup); + } + else if (activeObject && this.setActiveObject) { + this.setActiveObject(activeObject); + } + + this.contextTop && this.clearContext(this.contextTop); + this.renderAll(); + + return data; + }, + + /** + * Exports canvas element to a dataurl image (allowing to change image size via multiplier). + * @deprecated since 1.0.13 + * @param {String} format (png|jpeg) + * @param {Number} multiplier + * @param {Number} quality (0..1) + * @return {String} + */ + toDataURLWithMultiplier: function (format, multiplier, quality) { + return this.toDataURL({ + format: format, + multiplier: multiplier, + quality: quality + }); + }, + + /** + * @private + */ + _tempRemoveBordersControlsFromGroup: function(group) { + group.origHasControls = group.hasControls; + group.origBorderColor = group.borderColor; + + group.hasControls = true; + group.borderColor = 'rgba(0,0,0,0)'; + + group.forEachObject(function(o) { + o.origBorderColor = o.borderColor; + o.borderColor = 'rgba(0,0,0,0)'; + }); + }, + + /** + * @private + */ + _restoreBordersControlsOnGroup: function(group) { + group.hideControls = group.origHideControls; + group.borderColor = group.origBorderColor; + + group.forEachObject(function(o) { + o.borderColor = o.origBorderColor; + delete o.origBorderColor; + }); + } +}); +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Populates canvas with data from the specified dataless JSON. + * JSON format must conform to the one of {@link fabric.Canvas#toDatalessJSON} + * @deprecated since 1.2.2 + * @param {String|Object} json JSON string or object + * @param {Function} callback Callback, invoked when json is parsed + * and corresponding objects (e.g: {@link fabric.Image}) + * are initialized + * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created. + * @return {fabric.Canvas} instance + * @chainable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization} + */ + loadFromDatalessJSON: function (json, callback, reviver) { + return this.loadFromJSON(json, callback, reviver); + }, + + /** + * Populates canvas with data from the specified JSON. + * JSON format must conform to the one of {@link fabric.Canvas#toJSON} + * @param {String|Object} json JSON string or object + * @param {Function} callback Callback, invoked when json is parsed + * and corresponding objects (e.g: {@link fabric.Image}) + * are initialized + * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created. + * @return {fabric.Canvas} instance + * @chainable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization} + * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo} + * @example loadFromJSON + * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas)); + * @example loadFromJSON with reviver + * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) { + * // `o` = json object + * // `object` = fabric.Object instance + * // ... do some stuff ... + * }); + */ + loadFromJSON: function (json, callback, reviver) { + if (!json) return; + + // serialize if it wasn't already + var serialized = (typeof json === 'string') + ? JSON.parse(json) + : json; + + this.clear(); + + var _this = this; + this._enlivenObjects(serialized.objects, function () { + _this._setBgOverlay(serialized, callback); + }, reviver); + + return this; + }, + + /** + * @private + * @param {Object} serialized Object with background and overlay information + * @param {Function} callback Invoked after all background and overlay images/patterns loaded + */ + _setBgOverlay: function(serialized, callback) { + var _this = this, + loaded = { + backgroundColor: false, + overlayColor: false, + backgroundImage: false, + overlayImage: false + }; + + if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) { + callback && callback(); + return; + } + + var cbIfLoaded = function () { + if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) { + _this.renderAll(); + callback && callback(); + } + }; + + this.__setBgOverlay('backgroundImage', serialized.backgroundImage, loaded, cbIfLoaded); + this.__setBgOverlay('overlayImage', serialized.overlayImage, loaded, cbIfLoaded); + this.__setBgOverlay('backgroundColor', serialized.background, loaded, cbIfLoaded); + this.__setBgOverlay('overlayColor', serialized.overlay, loaded, cbIfLoaded); + + cbIfLoaded(); + }, + + /** + * @private + * @param {String} property Property to set (backgroundImage, overlayImage, backgroundColor, overlayColor) + * @param {(Object|String)} value Value to set + * @param {Object} loaded Set loaded property to true if property is set + * @param {Object} callback Callback function to invoke after property is set + */ + __setBgOverlay: function(property, value, loaded, callback) { + var _this = this; + + if (!value) { + loaded[property] = true; + return; + } + + if (property === 'backgroundImage' || property === 'overlayImage') { + fabric.Image.fromObject(value, function(img) { + _this[property] = img; + loaded[property] = true; + callback && callback(); + }); + } + else { + this['set' + fabric.util.string.capitalize(property, true)](value, function() { + loaded[property] = true; + callback && callback(); + }); + } + }, + + /** + * @private + * @param {Array} objects + * @param {Function} callback + * @param {Function} [reviver] + */ + _enlivenObjects: function (objects, callback, reviver) { + var _this = this; + + if (objects.length === 0) { + callback && callback(); + } + + var renderOnAddRemove = this.renderOnAddRemove; + this.renderOnAddRemove = false; + + fabric.util.enlivenObjects(objects, function(enlivenedObjects) { + enlivenedObjects.forEach(function(obj, index) { + _this.insertAt(obj, index, true); + }); + + _this.renderOnAddRemove = renderOnAddRemove; + callback && callback(); + }, null, reviver); + }, + + /** + * @private + * @param {String} format + * @param {Function} callback + */ + _toDataURL: function (format, callback) { + this.clone(function (clone) { + callback(clone.toDataURL(format)); + }); + }, + + /** + * @private + * @param {String} format + * @param {Number} multiplier + * @param {Function} callback + */ + _toDataURLWithMultiplier: function (format, multiplier, callback) { + this.clone(function (clone) { + callback(clone.toDataURLWithMultiplier(format, multiplier)); + }); + }, + + /** + * Clones canvas instance + * @param {Object} [callback] Receives cloned instance as a first argument + * @param {Array} [properties] Array of properties to include in the cloned canvas and children + */ + clone: function (callback, properties) { + var data = JSON.stringify(this.toJSON(properties)); + this.cloneWithoutData(function(clone) { + clone.loadFromJSON(data, function() { + callback && callback(clone); + }); + }); + }, + + /** + * Clones canvas instance without cloning existing data. + * This essentially copies canvas dimensions, clipping properties, etc. + * but leaves data empty (so that you can populate it with your own) + * @param {Object} [callback] Receives cloned instance as a first argument + */ + cloneWithoutData: function(callback) { + var el = fabric.document.createElement('canvas'); + + el.width = this.getWidth(); + el.height = this.getHeight(); + + var clone = new fabric.Canvas(el); + clone.clipTo = this.clipTo; + if (this.backgroundImage) { + clone.setBackgroundImage(this.backgroundImage.src, function() { + clone.renderAll(); + callback && callback(clone); + }); + clone.backgroundImageOpacity = this.backgroundImageOpacity; + clone.backgroundImageStretch = this.backgroundImageStretch; + } + else { + callback && callback(clone); + } + } +}); +(function() { + + var degreesToRadians = fabric.util.degreesToRadians, + radiansToDegrees = fabric.util.radiansToDegrees; + + fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ { + + /** + * Method that defines actions when an Event.js gesture is detected on an object. Currently only supports + * 2 finger gestures. + * + * @param e Event object by Event.js + * @param self Event proxy object by Event.js + */ + __onTransformGesture: function(e, self) { + + if (this.isDrawingMode || e.touches.length !== 2 || 'gesture' !== self.gesture) { + return; + } + + var target = this.findTarget(e); + if ('undefined' !== typeof target) { + this.onBeforeScaleRotate(target); + this._rotateObjectByAngle(self.rotation); + this._scaleObjectBy(self.scale); + } + + this.fire('touch:gesture', {target: target, e: e, self: self}); + }, + + /** + * Method that defines actions when an Event.js drag is detected. + * + * @param e Event object by Event.js + * @param self Event proxy object by Event.js + */ + __onDrag: function(e, self) { + this.fire('touch:drag', {e: e, self: self}); + }, + + /** + * Method that defines actions when an Event.js orientation event is detected. + * + * @param e Event object by Event.js + * @param self Event proxy object by Event.js + */ + __onOrientationChange: function(e, self) { + this.fire('touch:orientation', {e: e, self: self}); + }, + + /** + * Method that defines actions when an Event.js shake event is detected. + * + * @param e Event object by Event.js + * @param self Event proxy object by Event.js + */ + __onShake: function(e, self) { + this.fire('touch:shake', {e: e, self: self}); + }, + + /** + * Scales an object by a factor + * @param s {Number} The scale factor to apply to the current scale level + * @param by {String} Either 'x' or 'y' - specifies dimension constraint by which to scale an object. + * When not provided, an object is scaled by both dimensions equally + */ + _scaleObjectBy: function(s, by) { + var t = this._currentTransform, + target = t.target; + + var lockScalingX = target.get('lockScalingX'), + lockScalingY = target.get('lockScalingY'); + + if (lockScalingX && lockScalingY) return; + + target._scaling = true; + + if (!by) { + if (!lockScalingX) { + target.set('scaleX', t.scaleX * s); + } + if (!lockScalingY) { + target.set('scaleY', t.scaleY * s); + } + } + else if (by === 'x' && !target.get('lockUniScaling')) { + lockScalingX || target.set('scaleX', t.scaleX * s); + } + else if (by === 'y' && !target.get('lockUniScaling')) { + lockScalingY || target.set('scaleY', t.scaleY * s); + } + }, + + /** + * Rotates object by an angle + * @param curAngle {Number} the angle of rotation in degrees + */ + _rotateObjectByAngle: function(curAngle) { + var t = this._currentTransform; + + if (t.target.get('lockRotation')) return; + t.target.angle = radiansToDegrees(degreesToRadians(curAngle) + t.theta); + } + }); +})(); +(function(global) { + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + toFixed = fabric.util.toFixed, + capitalize = fabric.util.string.capitalize, + degreesToRadians = fabric.util.degreesToRadians, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Object) { + return; + } + + /** + * Root object class from which all 2d shape classes inherit from + * @class fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#objects} + * @see {@link fabric.Object#initialize} for constructor definition + * + * @fires added + * @fires removed + * + * @fires selected + * @fires modified + * @fires rotating + * @fires scaling + * @fires moving + * + * @fires mousedown + * @fires mouseup + */ + fabric.Object = fabric.util.createClass(/** @lends fabric.Object.prototype */ { + + /** + * Retrieves object's {@link fabric.Object#clipTo|clipping function} + * @method getClipTo + * @memberOf fabric.Object.prototype + * @return {Function} + */ + + /** + * Sets object's {@link fabric.Object#clipTo|clipping function} + * @method setClipTo + * @memberOf fabric.Object.prototype + * @param {Function} clipTo Clipping function + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#transformMatrix|transformMatrix} + * @method getTransformMatrix + * @memberOf fabric.Object.prototype + * @return {Array} transformMatrix + */ + + /** + * Sets object's {@link fabric.Object#transformMatrix|transformMatrix} + * @method setTransformMatrix + * @memberOf fabric.Object.prototype + * @param {Array} transformMatrix + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#visible|visible} state + * @method getVisible + * @memberOf fabric.Object.prototype + * @return {Boolean} True if visible + */ + + /** + * Sets object's {@link fabric.Object#visible|visible} state + * @method setVisible + * @memberOf fabric.Object.prototype + * @param {Boolean} value visible value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#shadow|shadow} + * @method getShadow + * @memberOf fabric.Object.prototype + * @return {Object} Shadow instance + */ + + /** + * Retrieves object's {@link fabric.Object#stroke|stroke} + * @method getStroke + * @memberOf fabric.Object.prototype + * @return {String} stroke value + */ + + /** + * Sets object's {@link fabric.Object#stroke|stroke} + * @method setStroke + * @memberOf fabric.Object.prototype + * @param {String} value stroke value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#strokeWidth|strokeWidth} + * @method getStrokeWidth + * @memberOf fabric.Object.prototype + * @return {Number} strokeWidth value + */ + + /** + * Sets object's {@link fabric.Object#strokeWidth|strokeWidth} + * @method setStrokeWidth + * @memberOf fabric.Object.prototype + * @param {Number} value strokeWidth value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#originX|originX} + * @method getOriginX + * @memberOf fabric.Object.prototype + * @return {String} originX value + */ + + /** + * Sets object's {@link fabric.Object#originX|originX} + * @method setOriginX + * @memberOf fabric.Object.prototype + * @param {String} value originX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#originY|originY} + * @method getOriginY + * @memberOf fabric.Object.prototype + * @return {String} originY value + */ + + /** + * Sets object's {@link fabric.Object#originY|originY} + * @method setOriginY + * @memberOf fabric.Object.prototype + * @param {String} value originY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#fill|fill} + * @method getFill + * @memberOf fabric.Object.prototype + * @return {String} Fill value + */ + + /** + * Sets object's {@link fabric.Object#fill|fill} + * @method setFill + * @memberOf fabric.Object.prototype + * @param {String} value Fill value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#opacity|opacity} + * @method getOpacity + * @memberOf fabric.Object.prototype + * @return {Number} Opacity value (0-1) + */ + + /** + * Sets object's {@link fabric.Object#opacity|opacity} + * @method setOpacity + * @memberOf fabric.Object.prototype + * @param {Number} value Opacity value (0-1) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#angle|angle} (in degrees) + * @method getAngle + * @memberOf fabric.Object.prototype + * @return {Number} + */ + + /** + * Sets object's {@link fabric.Object#angle|angle} + * @method setAngle + * @memberOf fabric.Object.prototype + * @param {Number} value Angle value (in degrees) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#top|top position} + * @method getTop + * @memberOf fabric.Object.prototype + * @return {Number} Top value (in pixels) + */ + + /** + * Sets object's {@link fabric.Object#top|top position} + * @method setTop + * @memberOf fabric.Object.prototype + * @param {Number} value Top value (in pixels) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#left|left position} + * @method getLeft + * @memberOf fabric.Object.prototype + * @return {Number} Left value (in pixels) + */ + + /** + * Sets object's {@link fabric.Object#left|left position} + * @method setLeft + * @memberOf fabric.Object.prototype + * @param {Number} value Left value (in pixels) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#scaleX|scaleX} value + * @method getScaleX + * @memberOf fabric.Object.prototype + * @return {Number} scaleX value + */ + + /** + * Sets object's {@link fabric.Object#scaleX|scaleX} value + * @method setScaleX + * @memberOf fabric.Object.prototype + * @param {Number} value scaleX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#scaleY|scaleY} value + * @method getScaleY + * @memberOf fabric.Object.prototype + * @return {Number} scaleY value + */ + + /** + * Sets object's {@link fabric.Object#scaleY|scaleY} value + * @method setScaleY + * @memberOf fabric.Object.prototype + * @param {Number} value scaleY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#flipX|flipX} value + * @method getFlipX + * @memberOf fabric.Object.prototype + * @return {Boolean} flipX value + */ + + /** + * Sets object's {@link fabric.Object#flipX|flipX} value + * @method setFlipX + * @memberOf fabric.Object.prototype + * @param {Boolean} value flipX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#flipY|flipY} value + * @method getFlipY + * @memberOf fabric.Object.prototype + * @return {Boolean} flipY value + */ + + /** + * Sets object's {@link fabric.Object#flipY|flipY} value + * @method setFlipY + * @memberOf fabric.Object.prototype + * @param {Boolean} value flipY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Type of an object (rect, circle, path, etc.) + * @type String + * @default + */ + type: 'object', + + /** + * Horizontal origin of transformation of an object (one of "left", "right", "center") + * @type String + * @default + */ + originX: 'left', + + /** + * Vertical origin of transformation of an object (one of "top", "bottom", "center") + * @type String + * @default + */ + originY: 'top', + + /** + * Top position of an object. Note that by default it's relative to object center. You can change this by setting originY={top/center/bottom} + * @type Number + * @default + */ + top: 0, + + /** + * Left position of an object. Note that by default it's relative to object center. You can change this by setting originX={left/center/right} + * @type Number + * @default + */ + left: 0, + + /** + * Object width + * @type Number + * @default + */ + width: 0, + + /** + * Object height + * @type Number + * @default + */ + height: 0, + + /** + * Object scale factor (horizontal) + * @type Number + * @default + */ + scaleX: 1, + + /** + * Object scale factor (vertical) + * @type Number + * @default + */ + scaleY: 1, + + /** + * When true, an object is rendered as flipped horizontally + * @type Boolean + * @default + */ + flipX: false, + + /** + * When true, an object is rendered as flipped vertically + * @type Boolean + * @default + */ + flipY: false, + + /** + * Opacity of an object + * @type Number + * @default + */ + opacity: 1, + + /** + * Angle of rotation of an object (in degrees) + * @type Number + * @default + */ + angle: 0, + + /** + * Size of object's controlling corners (in pixels) + * @type Number + * @default + */ + cornerSize: 12, + + /** + * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill) + * @type Boolean + * @default + */ + transparentCorners: true, + + /** + * Default cursor value used when hovering over this object on canvas + * @type String + * @default + */ + hoverCursor: null, + + /** + * Padding between object and its controlling borders (in pixels) + * @type Number + * @default + */ + padding: 0, + + /** + * Color of controlling borders of an object (when it's active) + * @type String + * @default + */ + borderColor: 'rgba(102,153,255,0.75)', + + /** + * Color of controlling corners of an object (when it's active) + * @type String + * @default + */ + cornerColor: 'rgba(102,153,255,0.5)', + + /** + * When true, this object will use center point as the origin of transformation + * when being scaled via the controls. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredScaling: false, + + /** + * When true, this object will use center point as the origin of transformation + * when being rotated via the controls. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredRotation: true, + + /** + * Color of object's fill + * @type String + * @default + */ + fill: 'rgb(0,0,0)', + + /** + * Fill rule used to fill an object + * @type String + * @default + */ + fillRule: 'source-over', + + /** + * Background color of an object. Only works with text objects at the moment. + * @type String + * @default + */ + backgroundColor: '', + + /** + * When defined, an object is rendered via stroke and this property specifies its color + * @type String + * @default + */ + stroke: null, + + /** + * Width of a stroke used to render this object + * @type Number + * @default + */ + strokeWidth: 1, + + /** + * Array specifying dash pattern of an object's stroke (stroke must be defined) + * @type Array + */ + strokeDashArray: null, + + /** + * Line endings style of an object's stroke (one of "butt", "round", "square") + * @type String + * @default + */ + strokeLineCap: 'butt', + + /** + * Corner style of an object's stroke (one of "bevil", "round", "miter") + * @type String + * @default + */ + strokeLineJoin: 'miter', + + /** + * Maximum miter length (used for strokeLineJoin = "miter") of an object's stroke + * @type Number + * @default + */ + strokeMiterLimit: 10, + + /** + * Shadow object representing shadow of this shape + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Opacity of object's controlling borders when object is active and moving + * @type Number + * @default + */ + borderOpacityWhenMoving: 0.4, + + /** + * Scale factor of object's controlling borders + * @type Number + * @default + */ + borderScaleFactor: 1, + + /** + * Transform matrix (similar to SVG's transform matrix) + * @type Array + */ + transformMatrix: null, + + /** + * Minimum allowed scale value of an object + * @type Number + * @default + */ + minScaleLimit: 0.01, + + /** + * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection). + * But events still fire on it. + * @type Boolean + * @default + */ + selectable: true, + + /** + * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4 + * @type Boolean + * @default + */ + evented: true, + + /** + * When set to `false`, an object is not rendered on canvas + * @type Boolean + * @default + */ + visible: true, + + /** + * When set to `false`, object's controls are not displayed and can not be used to manipulate object + * @type Boolean + * @default + */ + hasControls: true, + + /** + * When set to `false`, object's controlling borders are not rendered + * @type Boolean + * @default + */ + hasBorders: true, + + /** + * When set to `false`, object's controlling rotating point will not be visible or selectable + * @type Boolean + * @default + */ + hasRotatingPoint: true, + + /** + * Offset for object's controlling rotating point (when enabled via `hasRotatingPoint`) + * @type Number + * @default + */ + rotatingPointOffset: 40, + + /** + * When set to `true`, objects are "found" on canvas on per-pixel basis rather than according to bounding box + * @type Boolean + * @default + */ + perPixelTargetFind: false, + + /** + * When `false`, default object's values are not included in its serialization + * @type Boolean + * @default + */ + includeDefaultValues: true, + + /** + * Function that determines clipping of an object (context is passed as a first argument) + * @type Function + */ + clipTo: null, + + /** + * When `true`, object horizontal movement is locked + * @type Boolean + * @default + */ + lockMovementX: false, + + /** + * When `true`, object vertical movement is locked + * @type Boolean + * @default + */ + lockMovementY: false, + + /** + * When `true`, object rotation is locked + * @type Boolean + * @default + */ + lockRotation: false, + + /** + * When `true`, object horizontal scaling is locked + * @type Boolean + * @default + */ + lockScalingX: false, + + /** + * When `true`, object vertical scaling is locked + * @type Boolean + * @default + */ + lockScalingY: false, + + /** + * When `true`, object non-uniform scaling is locked + * @type Boolean + * @default + */ + lockUniScaling: false, + + /** + * List of properties to consider when checking if state + * of an object is changed (fabric.Object#hasStateChanged) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: ( + 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' + + 'stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit ' + + 'angle opacity fill fillRule shadow clipTo visible backgroundColor' + ).split(' '), + + /** + * Constructor + * @param {Object} [options] Options object + */ + initialize: function(options) { + if (options) { + this.setOptions(options); + } + }, + + /** + * @private + */ + _initGradient: function(options) { + if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) { + this.set('fill', new fabric.Gradient(options.fill)); + } + }, + + /** + * @private + */ + _initPattern: function(options) { + if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) { + this.set('fill', new fabric.Pattern(options.fill)); + } + if (options.stroke && options.stroke.source && !(options.stroke instanceof fabric.Pattern)) { + this.set('stroke', new fabric.Pattern(options.stroke)); + } + }, + + /** + * @private + */ + _initClipping: function(options) { + if (!options.clipTo || typeof options.clipTo !== 'string') return; + + var functionBody = fabric.util.getFunctionBody(options.clipTo); + if (typeof functionBody !== 'undefined') { + this.clipTo = new Function('ctx', functionBody); + } + }, + + /** + * Sets object's properties from options + * @param {Object} [options] Options object + */ + setOptions: function(options) { + for (var prop in options) { + this.set(prop, options[prop]); + } + this._initGradient(options); + this._initPattern(options); + this._initClipping(options); + }, + + /** + * Transforms context when rendering an object + * @param {CanvasRenderingContext2D} ctx Context + * @param {Boolean} fromLeft When true, context is transformed to object's top/left corner. This is used when rendering text on Node + */ + transform: function(ctx, fromLeft) { + ctx.globalAlpha = this.opacity; + + var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint(); + ctx.translate(center.x, center.y); + ctx.rotate(degreesToRadians(this.angle)); + ctx.scale( + this.scaleX * (this.flipX ? -1 : 1), + this.scaleY * (this.flipY ? -1 : 1) + ); + }, + + /** + * Returns an object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + + var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; + + var object = { + type: this.type, + originX: this.originX, + originY: this.originY, + left: toFixed(this.left, NUM_FRACTION_DIGITS), + top: toFixed(this.top, NUM_FRACTION_DIGITS), + width: toFixed(this.width, NUM_FRACTION_DIGITS), + height: toFixed(this.height, NUM_FRACTION_DIGITS), + fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill, + stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke, + strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS), + strokeDashArray: this.strokeDashArray, + strokeLineCap: this.strokeLineCap, + strokeLineJoin: this.strokeLineJoin, + strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS), + scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS), + scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS), + angle: toFixed(this.getAngle(), NUM_FRACTION_DIGITS), + flipX: this.flipX, + flipY: this.flipY, + opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS), + shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow, + visible: this.visible, + clipTo: this.clipTo && String(this.clipTo), + backgroundColor: this.backgroundColor + }; + + if (!this.includeDefaultValues) { + object = this._removeDefaultValues(object); + } + + fabric.util.populateWithProperties(this, object, propertiesToInclude); + + return object; + }, + + /** + * Returns (dataless) object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + // will be overwritten by subclasses + return this.toObject(propertiesToInclude); + }, + + /** + * @private + * @param {Object} object + */ + _removeDefaultValues: function(object) { + var prototype = fabric.util.getKlass(object.type).prototype; + var stateProperties = prototype.stateProperties; + + stateProperties.forEach(function(prop) { + if (object[prop] === prototype[prop]) { + delete object[prop]; + } + }); + + return object; + }, + + /** + * Returns a string representation of an instance + * @return {String} + */ + toString: function() { + return "#"; + }, + + /** + * Basic getter + * @param {String} property Property name + * @return {Any} value of a property + */ + get: function(property) { + return this[property]; + }, + + /** + * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`. + * @param {String|Object} key Property name or object (if object, iterate over the object properties) + * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one) + * @return {fabric.Object} thisArg + * @chainable + */ + set: function(key, value) { + if (typeof key === 'object') { + for (var prop in key) { + this._set(prop, key[prop]); + } + } + else { + if (typeof value === 'function' && key !== 'clipTo') { + this._set(key, value(this.get(key))); + } + else { + this._set(key, value); + } + } + return this; + }, + + /** + * @private + * @param {String} key + * @param {Any} value + * @return {fabric.Object} thisArg + */ + _set: function(key, value) { + var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY'); + + if (shouldConstrainValue) { + value = this._constrainScale(value); + } + if (key === 'scaleX' && value < 0) { + this.flipX = !this.flipX; + value *= -1; + } + else if (key === 'scaleY' && value < 0) { + this.flipY = !this.flipY; + value *= -1; + } + else if (key === 'width' || key === 'height') { + this.minScaleLimit = toFixed(Math.min(0.1, 1/Math.max(this.width, this.height)), 2); + } + else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) { + value = new fabric.Shadow(value); + } + + this[key] = value; + + return this; + }, + + /** + * Toggles specified property from `true` to `false` or from `false` to `true` + * @param {String} property Property to toggle + * @return {fabric.Object} thisArg + * @chainable + */ + toggle: function(property) { + var value = this.get(property); + if (typeof value === 'boolean') { + this.set(property, !value); + } + return this; + }, + + /** + * Sets sourcePath of an object + * @param {String} value Value to set sourcePath to + * @return {fabric.Object} thisArg + * @chainable + */ + setSourcePath: function(value) { + this.sourcePath = value; + return this; + }, + + /** + * Renders an object on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if width/height are zeros or object is not visible + if (this.width === 0 || this.height === 0 || !this.visible) return; + + ctx.save(); + + this._transform(ctx, noTransform); + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); + + var m = this.transformMatrix; + if (m && this.group) { + ctx.translate(-this.group.width/2, -this.group.height/2); + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + this._render(ctx, noTransform); + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + + if (this.active && !noTransform) { + this.drawBorders(ctx); + this.drawControls(ctx); + } + ctx.restore(); + }, + + _transform: function(ctx, noTransform) { + var m = this.transformMatrix; + if (m && !this.group) { + ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + if (!noTransform) { + this.transform(ctx); + } + }, + + _setStrokeStyles: function(ctx) { + if (this.stroke) { + ctx.lineWidth = this.strokeWidth; + ctx.lineCap = this.strokeLineCap; + ctx.lineJoin = this.strokeLineJoin; + ctx.miterLimit = this.strokeMiterLimit; + ctx.strokeStyle = this.stroke.toLive + ? this.stroke.toLive(ctx) + : this.stroke; + } + }, + + _setFillStyles: function(ctx) { + if (this.fill) { + ctx.fillStyle = this.fill.toLive + ? this.fill.toLive(ctx) + : this.fill; + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _setShadow: function(ctx) { + if (!this.shadow) return; + + ctx.shadowColor = this.shadow.color; + ctx.shadowBlur = this.shadow.blur; + ctx.shadowOffsetX = this.shadow.offsetX; + ctx.shadowOffsetY = this.shadow.offsetY; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _removeShadow: function(ctx) { + ctx.shadowColor = ''; + ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderFill: function(ctx) { + if (!this.fill) return; + + if (this.fill.toLive) { + ctx.save(); + ctx.translate( + -this.width / 2 + this.fill.offsetX || 0, + -this.height / 2 + this.fill.offsetY || 0); + } + ctx.fill(); + if (this.fill.toLive) { + ctx.restore(); + } + if (this.shadow && !this.shadow.affectStroke) { + this._removeShadow(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderStroke: function(ctx) { + if (!this.stroke) return; + + ctx.save(); + if (this.strokeDashArray) { + // Spec requires the concatenation of two copies the dash list when the number of elements is odd + if (1 & this.strokeDashArray.length) { + this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); + } + + if (supportsLineDash) { + ctx.setLineDash(this.strokeDashArray); + this._stroke && this._stroke(ctx); + } + else { + this._renderDashedStroke && this._renderDashedStroke(ctx); + } + ctx.stroke(); + } + else { + this._stroke ? this._stroke(ctx) : ctx.stroke(); + } + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * Clones an instance + * @param {Function} callback Callback is invoked with a clone as a first argument + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {fabric.Object} clone of an instance + */ + clone: function(callback, propertiesToInclude) { + if (this.constructor.fromObject) { + return this.constructor.fromObject(this.toObject(propertiesToInclude), callback); + } + return new fabric.Object(this.toObject(propertiesToInclude)); + }, + + /** + * Creates an instance of fabric.Image out of an object + * @param callback {Function} callback, invoked with an instance as a first argument + * @return {fabric.Object} thisArg + */ + cloneAsImage: function(callback) { + var dataUrl = this.toDataURL(); + fabric.util.loadImage(dataUrl, function(img) { + if (callback) { + callback(new fabric.Image(img)); + } + }); + return this; + }, + + /** + * Converts an object into a data-url-like string + * @param {Object} options Options object + * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png" + * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg. + * @param {Number} [options.multiplier=1] Multiplier to scale by + * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14 + * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14 + * @param {Number} [options.width] Cropping width. Introduced in v1.2.14 + * @param {Number} [options.height] Cropping height. Introduced in v1.2.14 + * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format + */ + toDataURL: function(options) { + options || (options = { }); + + var el = fabric.util.createCanvasElement(), + boundingRect = this.getBoundingRect(); + + el.width = boundingRect.width; + el.height = boundingRect.height; + + fabric.util.wrapElement(el, 'div'); + var canvas = new fabric.Canvas(el); + + // to avoid common confusion https://github.com/kangax/fabric.js/issues/806 + if (options.format === 'jpg') { + options.format = 'jpeg'; + } + + if (options.format === 'jpeg') { + canvas.backgroundColor = '#fff'; + } + + var origParams = { + active: this.get('active'), + left: this.getLeft(), + top: this.getTop() + }; + + this.set('active', false); + this.setPositionByOrigin(new fabric.Point(el.width / 2, el.height / 2), 'center', 'center'); + + var originalCanvas = this.canvas; + canvas.add(this); + var data = canvas.toDataURL(options); + + this.set(origParams).setCoords(); + this.canvas = originalCanvas; + + canvas.dispose(); + canvas = null; + + return data; + }, + + /** + * Returns true if specified type is identical to the type of an instance + * @param type {String} type Type to check against + * @return {Boolean} + */ + isType: function(type) { + return this.type === type; + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 0; + }, + + /** + * Returns a JSON representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} JSON + */ + toJSON: function(propertiesToInclude) { + // delegate, not alias + return this.toObject(propertiesToInclude); + }, + + /** + * Sets gradient (fill or stroke) of an object + * Backwards incompatibility note: This method was named "setGradientFill" until v1.1.0 + * @param {String} property Property name 'stroke' or 'fill' + * @param {Object} [options] Options object + * @param {String} [options.type] Type of gradient 'radial' or 'linear' + * @param {Number} [options.x1=0] x-coordinate of start point + * @param {Number} [options.y1=0] y-coordinate of start point + * @param {Number} [options.x2=0] x-coordinate of end point + * @param {Number} [options.y2=0] y-coordinate of end point + * @param {Number} [options.r1=0] Radius of start point (only for radial gradients) + * @param {Number} [options.r2=0] Radius of end point (only for radial gradients) + * @param {Object} [options.colorStops] Color stops object eg. {0: 'ff0000', 1: '000000'} + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/58y8b/|jsFiddle demo} + * @example Set linear gradient + * object.setGradient('fill', { + * type: 'linear', + * x1: -object.width / 2, + * y1: 0, + * x2: object.width / 2, + * y2: 0, + * colorStops: { + * 0: 'red', + * 0.5: '#005555', + * 1: 'rgba(0,0,255,0.5)' + * } + * }); + * canvas.renderAll(); + * @example Set radial gradient + * object.setGradient('fill', { + * type: 'radial', + * x1: 0, + * y1: 0, + * x2: 0, + * y2: 0, + * r1: object.width / 2, + * r2: 10, + * colorStops: { + * 0: 'red', + * 0.5: '#005555', + * 1: 'rgba(0,0,255,0.5)' + * } + * }); + * canvas.renderAll(); + */ + setGradient: function(property, options) { + options || (options = { }); + + var gradient = {colorStops: []}; + + gradient.type = options.type || (options.r1 || options.r2 ? 'radial' : 'linear'); + gradient.coords = { + x1: options.x1, + y1: options.y1, + x2: options.x2, + y2: options.y2 + }; + + if (options.r1 || options.r2) { + gradient.coords.r1 = options.r1; + gradient.coords.r2 = options.r2; + } + + for (var position in options.colorStops) { + var color = new fabric.Color(options.colorStops[position]); + gradient.colorStops.push({offset: position, color: color.toRgb(), opacity: color.getAlpha()}); + } + + return this.set(property, fabric.Gradient.forObject(this, gradient)); + }, + + /** + * Sets pattern fill of an object + * @param {Object} options Options object + * @param {(String|HTMLImageElement)} options.source Pattern source + * @param {String} [options.repeat=repeat] Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat) + * @param {Number} [options.offsetX=0] Pattern horizontal offset from object's left/top corner + * @param {Number} [options.offsetY=0] Pattern vertical offset from object's left/top corner + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/QT3pa/|jsFiddle demo} + * @example Set pattern + * fabric.util.loadImage('http://fabricjs.com/assets/escheresque_ste.png', function(img) { + * object.setPatternFill({ + * source: img, + * repeat: 'repeat' + * }); + * canvas.renderAll(); + * }); + */ + setPatternFill: function(options) { + return this.set('fill', new fabric.Pattern(options)); + }, + + /** + * Sets {@link fabric.Object#shadow|shadow} of an object + * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") + * @param {String} [options.color=rgb(0,0,0)] Shadow color + * @param {Number} [options.blur=0] Shadow blur + * @param {Number} [options.offsetX=0] Shadow horizontal offset + * @param {Number} [options.offsetY=0] Shadow vertical offset + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/7gvJG/|jsFiddle demo} + * @example Set shadow with string notation + * object.setShadow('2px 2px 10px rgba(0,0,0,0.2)'); + * canvas.renderAll(); + * @example Set shadow with object notation + * object.setShadow({ + * color: 'red', + * blur: 10, + * offsetX: 20, + * offsetY: 20 + * }); + * canvas.renderAll(); + */ + setShadow: function(options) { + return this.set('shadow', new fabric.Shadow(options)); + }, + + /** + * Sets "color" of an instance (alias of `set('fill', …)`) + * @param {String} color Color value + * @return {fabric.Text} thisArg + * @chainable + */ + setColor: function(color) { + this.set('fill', color); + return this; + }, + + /** + * Centers object horizontally on canvas to which it was added last. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + centerH: function () { + this.canvas.centerObjectH(this); + return this; + }, + + /** + * Centers object vertically on canvas to which it was added last. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + centerV: function () { + this.canvas.centerObjectV(this); + return this; + }, + + /** + * Centers object vertically and horizontally on canvas to which is was added last + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + center: function () { + this.canvas.centerObject(this); + return this; + }, + + /** + * Removes object from canvas to which it was added last + * @return {fabric.Object} thisArg + * @chainable + */ + remove: function() { + return this.canvas.remove(this); + }, + + /** + * Returns coordinates of a pointer relative to an object + * @param {Event} e Event to operate upon + * @param {Object} [pointer] Pointer to operate upon (instead of event) + * @return {Object} Coordinates of a pointer (x, y) + */ + getLocalPointer: function(e, pointer) { + pointer = pointer || this.canvas.getPointer(e); + var objectLeftTop = this.translateToOriginPoint(this.getCenterPoint(), 'left', 'top'); + return { + x: pointer.x - objectLeftTop.x, + y: pointer.y - objectLeftTop.y + }; + } + }); + + fabric.util.createAccessors(fabric.Object); + + /** + * Alias for {@link fabric.Object.prototype.setAngle} + * @alias rotate -> setAngle + * @memberof fabric.Object + */ + fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle; + + extend(fabric.Object.prototype, fabric.Observable); + + /** + * Defines the number of fraction digits to use when serializing object values. + * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc. + * @static + * @memberof fabric.Object + * @constant + * @type Number + */ + fabric.Object.NUM_FRACTION_DIGITS = 2; + + /** + * Unique id used internally when creating SVG elements + * @static + * @memberof fabric.Object + * @type Number + */ + fabric.Object.__uid = 0; + +})(typeof exports !== 'undefined' ? exports : this); +(function() { + + var degreesToRadians = fabric.util.degreesToRadians; + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Translates the coordinates from origin to center coordinates (based on the object's dimensions) + * @param {fabric.Point} point The point which corresponds to the originX and originY params + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + translateToCenterPoint: function(point, originX, originY) { + var cx = point.x, + cy = point.y, + strokeWidth = this.stroke ? this.strokeWidth : 0; + + if (originX === "left") { + cx = point.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === "right") { + cx = point.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + + if (originY === "top") { + cy = point.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === "bottom") { + cy = point.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + + // Apply the reverse rotation to the point (it's already scaled properly) + return fabric.util.rotatePoint(new fabric.Point(cx, cy), point, degreesToRadians(this.angle)); + }, + + /** + * Translates the coordinates from center to origin coordinates (based on the object's dimensions) + * @param {fabric.Point} point The point which corresponds to center of the object + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + translateToOriginPoint: function(center, originX, originY) { + var x = center.x, + y = center.y, + strokeWidth = this.stroke ? this.strokeWidth : 0; + + // Get the point coordinates + if (originX === "left") { + x = center.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === "right") { + x = center.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + if (originY === "top") { + y = center.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === "bottom") { + y = center.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + + // Apply the rotation to the point (it's already scaled properly) + return fabric.util.rotatePoint(new fabric.Point(x, y), center, degreesToRadians(this.angle)); + }, + + /** + * Returns the real center coordinates of the object + * @return {fabric.Point} + */ + getCenterPoint: function() { + var leftTop = new fabric.Point(this.left, this.top); + return this.translateToCenterPoint(leftTop, this.originX, this.originY); + }, + + /** + * Returns the coordinates of the object based on center coordinates + * @param {fabric.Point} point The point which corresponds to the originX and originY params + * @return {fabric.Point} + */ + // getOriginPoint: function(center) { + // return this.translateToOriginPoint(center, this.originX, this.originY); + // }, + + /** + * Returns the coordinates of the object as if it has a different origin + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + getPointByOrigin: function(originX, originY) { + var center = this.getCenterPoint(); + return this.translateToOriginPoint(center, originX, originY); + }, + + /** + * Returns the point in local coordinates + * @param {fabric.Point} point The point relative to the global coordinate system + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + toLocalPoint: function(point, originX, originY) { + var center = this.getCenterPoint(), + strokeWidth = this.stroke ? this.strokeWidth : 0, + x, y; + + if (originX && originY) { + if (originX === "left") { + x = center.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === "right") { + x = center.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else { + x = center.x; + } + + if (originY === "top") { + y = center.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === "bottom") { + y = center.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else { + y = center.y; + } + } + else { + x = this.left; + y = this.top; + } + + return fabric.util.rotatePoint(new fabric.Point(point.x, point.y), center, -degreesToRadians(this.angle)) + .subtractEquals(new fabric.Point(x, y)); + }, + + /** + * Returns the point in global coordinates + * @param {fabric.Point} The point relative to the local coordinate system + * @return {fabric.Point} + */ + // toGlobalPoint: function(point) { + // return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top)); + // }, + + /** + * Sets the position of the object taking into consideration the object's origin + * @param {fabric.Point} point The new position of the object + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {void} + */ + setPositionByOrigin: function(pos, originX, originY) { + var center = this.translateToCenterPoint(pos, originX, originY); + var position = this.translateToOriginPoint(center, this.originX, this.originY); + + this.set('left', position.x); + this.set('top', position.y); + }, + + /** + * @param {String} to One of 'left', 'center', 'right' + */ + adjustPosition: function(to) { + var angle = degreesToRadians(this.angle); + var hypotHalf = this.getWidth() / 2; + var xHalf = Math.cos(angle) * hypotHalf; + var yHalf = Math.sin(angle) * hypotHalf; + var hypotFull = this.getWidth(); + var xFull = Math.cos(angle) * hypotFull; + var yFull = Math.sin(angle) * hypotFull; + + if (this.originX === 'center' && to === 'left' || + this.originX === 'right' && to === 'center') { + // move half left + this.left -= xHalf; + this.top -= yHalf; + } + else if (this.originX === 'left' && to === 'center' || + this.originX === 'center' && to === 'right') { + // move half right + this.left += xHalf; + this.top += yHalf; + } + else if (this.originX === 'left' && to === 'right') { + // move full right + this.left += xFull; + this.top += yFull; + } + else if (this.originX === 'right' && to === 'left') { + // move full left + this.left -= xFull; + this.top -= yFull; + } + + this.setCoords(); + this.originX = to; + }, + + /** + * @private + */ + _getLeftTopCoords: function() { + return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'center'); + } + }); + +})(); +(function() { + + var degreesToRadians = fabric.util.degreesToRadians; + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Object containing coordinates of object's controls + * @type Object + * @default + */ + oCoords: null, + + /** + * Checks if object intersects with an area formed by 2 points + * @param {Object} pointTL top-left point of area + * @param {Object} pointBR bottom-right point of area + * @return {Boolean} true if object intersects with an area formed by 2 points + */ + intersectsWithRect: function(pointTL, pointBR) { + var oCoords = this.oCoords, + tl = new fabric.Point(oCoords.tl.x, oCoords.tl.y), + tr = new fabric.Point(oCoords.tr.x, oCoords.tr.y), + bl = new fabric.Point(oCoords.bl.x, oCoords.bl.y), + br = new fabric.Point(oCoords.br.x, oCoords.br.y); + + var intersection = fabric.Intersection.intersectPolygonRectangle( + [tl, tr, br, bl], + pointTL, + pointBR + ); + return intersection.status === 'Intersection'; + }, + + /** + * Checks if object intersects with another object + * @param {Object} other Object to test + * @return {Boolean} true if object intersects with another object + */ + intersectsWithObject: function(other) { + // extracts coords + function getCoords(oCoords) { + return { + tl: new fabric.Point(oCoords.tl.x, oCoords.tl.y), + tr: new fabric.Point(oCoords.tr.x, oCoords.tr.y), + bl: new fabric.Point(oCoords.bl.x, oCoords.bl.y), + br: new fabric.Point(oCoords.br.x, oCoords.br.y) + }; + } + var thisCoords = getCoords(this.oCoords), + otherCoords = getCoords(other.oCoords); + + var intersection = fabric.Intersection.intersectPolygonPolygon( + [thisCoords.tl, thisCoords.tr, thisCoords.br, thisCoords.bl], + [otherCoords.tl, otherCoords.tr, otherCoords.br, otherCoords.bl] + ); + + return intersection.status === 'Intersection'; + }, + + /** + * Checks if object is fully contained within area of another object + * @param {Object} other Object to test + * @return {Boolean} true if object is fully contained within area of another object + */ + isContainedWithinObject: function(other) { + var boundingRect = other.getBoundingRect(), + point1 = new fabric.Point(boundingRect.left, boundingRect.top), + point2 = new fabric.Point(boundingRect.left + boundingRect.width, boundingRect.top + boundingRect.height); + + return this.isContainedWithinRect(point1, point2); + }, + + /** + * Checks if object is fully contained within area formed by 2 points + * @param {Object} pointTL top-left point of area + * @param {Object} pointBR bottom-right point of area + * @return {Boolean} true if object is fully contained within area formed by 2 points + */ + isContainedWithinRect: function(pointTL, pointBR) { + var boundingRect = this.getBoundingRect(); + + return ( + boundingRect.left > pointTL.x && + boundingRect.left + boundingRect.width < pointBR.x && + boundingRect.top > pointTL.y && + boundingRect.top + boundingRect.height < pointBR.y + ); + }, + + /** + * Checks if point is inside the object + * @param {fabric.Point} point Point to check against + * @return {Boolean} true if point is inside the object + */ + containsPoint: function(point) { + var lines = this._getImageLines(this.oCoords), + xPoints = this._findCrossPoints(point, lines); + + // if xPoints is odd then point is inside the object + return (xPoints !== 0 && xPoints % 2 === 1); + }, + + /** + * Method that returns an object with the object edges in it, given the coordinates of the corners + * @private + * @param {Object} oCoords Coordinates of the object corners + */ + _getImageLines: function(oCoords) { + return { + topline: { + o: oCoords.tl, + d: oCoords.tr + }, + rightline: { + o: oCoords.tr, + d: oCoords.br + }, + bottomline: { + o: oCoords.br, + d: oCoords.bl + }, + leftline: { + o: oCoords.bl, + d: oCoords.tl + } + }; + }, + + /** + * Helper method to determine how many cross points are between the 4 object edges + * and the horizontal line determined by a point on canvas + * @private + * @param {fabric.Point} point Point to check + * @param {Object} oCoords Coordinates of the object being evaluated + */ + _findCrossPoints: function(point, oCoords) { + var b1, b2, a1, a2, xi, yi, + xcount = 0, + iLine; + + for (var lineKey in oCoords) { + iLine = oCoords[lineKey]; + // optimisation 1: line below point. no cross + if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) { + continue; + } + // optimisation 2: line above point. no cross + if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) { + continue; + } + // optimisation 3: vertical line case + if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) { + xi = iLine.o.x; + yi = point.y; + } + // calculate the intersection point + else { + b1 = 0; + b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x); + a1 = point.y- b1 * point.x; + a2 = iLine.o.y - b2 * iLine.o.x; + + xi = - (a1 - a2) / (b1 - b2); + yi = a1 + b1 * xi; + } + // dont count xi < point.x cases + if (xi >= point.x) { + xcount += 1; + } + // optimisation 4: specific for square images + if (xcount === 2) { + break; + } + } + return xcount; + }, + + /** + * Returns width of an object's bounding rectangle + * @deprecated since 1.0.4 + * @return {Number} width value + */ + getBoundingRectWidth: function() { + return this.getBoundingRect().width; + }, + + /** + * Returns height of an object's bounding rectangle + * @deprecated since 1.0.4 + * @return {Number} height value + */ + getBoundingRectHeight: function() { + return this.getBoundingRect().height; + }, + + /** + * Returns coordinates of object's bounding rectangle (left, top, width, height) + * @return {Object} Object with left, top, width, height properties + */ + getBoundingRect: function() { + this.oCoords || this.setCoords(); + + var xCoords = [this.oCoords.tl.x, this.oCoords.tr.x, this.oCoords.br.x, this.oCoords.bl.x]; + var minX = fabric.util.array.min(xCoords); + var maxX = fabric.util.array.max(xCoords); + var width = Math.abs(minX - maxX); + + var yCoords = [this.oCoords.tl.y, this.oCoords.tr.y, this.oCoords.br.y, this.oCoords.bl.y]; + var minY = fabric.util.array.min(yCoords); + var maxY = fabric.util.array.max(yCoords); + var height = Math.abs(minY - maxY); + + return { + left: minX, + top: minY, + width: width, + height: height + }; + }, + + /** + * Returns width of an object + * @return {Number} width value + */ + getWidth: function() { + return this.width * this.scaleX; + }, + + /** + * Returns height of an object + * @return {Number} height value + */ + getHeight: function() { + return this.height * this.scaleY; + }, + + /** + * Makes sure the scale is valid and modifies it if necessary + * @private + * @param {Number} value + * @return {Number} + */ + _constrainScale: function(value) { + if (Math.abs(value) < this.minScaleLimit) { + if (value < 0) + return -this.minScaleLimit; + else + return this.minScaleLimit; + } + + return value; + }, + + /** + * Scales an object (equally by x and y) + * @param value {Number} scale factor + * @return {fabric.Object} thisArg + * @chainable + */ + scale: function(value) { + value = this._constrainScale(value); + + if (value < 0) { + this.flipX = !this.flipX; + this.flipY = !this.flipY; + value *= -1; + } + + this.scaleX = value; + this.scaleY = value; + this.setCoords(); + return this; + }, + + /** + * Scales an object to a given width, with respect to bounding box (scaling by x/y equally) + * @param value {Number} new width value + * @return {fabric.Object} thisArg + * @chainable + */ + scaleToWidth: function(value) { + // adjust to bounding rect factor so that rotated shapes would fit as well + var boundingRectFactor = this.getBoundingRectWidth() / this.getWidth(); + return this.scale(value / this.width / boundingRectFactor); + }, + + /** + * Scales an object to a given height, with respect to bounding box (scaling by x/y equally) + * @param value {Number} new height value + * @return {fabric.Object} thisArg + * @chainable + */ + scaleToHeight: function(value) { + // adjust to bounding rect factor so that rotated shapes would fit as well + var boundingRectFactor = this.getBoundingRectHeight() / this.getHeight(); + return this.scale(value / this.height / boundingRectFactor); + }, + + /** + * Sets corner position coordinates based on current angle, width and height + * @return {fabric.Object} thisArg + * @chainable + */ + setCoords: function() { + + var strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, + padding = this.padding, + theta = degreesToRadians(this.angle); + + this.currentWidth = (this.width + strokeWidth) * this.scaleX + padding * 2; + this.currentHeight = (this.height + strokeWidth) * this.scaleY + padding * 2; + + // If width is negative, make postive. Fixes path selection issue + if (this.currentWidth < 0) { + this.currentWidth = Math.abs(this.currentWidth); + } + + var _hypotenuse = Math.sqrt( + Math.pow(this.currentWidth / 2, 2) + + Math.pow(this.currentHeight / 2, 2)); + + var _angle = Math.atan(isFinite(this.currentHeight / this.currentWidth) ? this.currentHeight / this.currentWidth : 0); + + // offset added for rotate and scale actions + var offsetX = Math.cos(_angle + theta) * _hypotenuse, + offsetY = Math.sin(_angle + theta) * _hypotenuse, + sinTh = Math.sin(theta), + cosTh = Math.cos(theta); + + var coords = this.getCenterPoint(); + var tl = { + x: coords.x - offsetX, + y: coords.y - offsetY + }; + var tr = { + x: tl.x + (this.currentWidth * cosTh), + y: tl.y + (this.currentWidth * sinTh) + }; + var br = { + x: tr.x - (this.currentHeight * sinTh), + y: tr.y + (this.currentHeight * cosTh) + }; + var bl = { + x: tl.x - (this.currentHeight * sinTh), + y: tl.y + (this.currentHeight * cosTh) + }; + var ml = { + x: tl.x - (this.currentHeight/2 * sinTh), + y: tl.y + (this.currentHeight/2 * cosTh) + }; + var mt = { + x: tl.x + (this.currentWidth/2 * cosTh), + y: tl.y + (this.currentWidth/2 * sinTh) + }; + var mr = { + x: tr.x - (this.currentHeight/2 * sinTh), + y: tr.y + (this.currentHeight/2 * cosTh) + }; + var mb = { + x: bl.x + (this.currentWidth/2 * cosTh), + y: bl.y + (this.currentWidth/2 * sinTh) + }; + var mtr = { + x: mt.x, + y: mt.y + }; + + // debugging + + // setTimeout(function() { + // canvas.contextTop.fillStyle = 'green'; + // canvas.contextTop.fillRect(mb.x, mb.y, 3, 3); + // canvas.contextTop.fillRect(bl.x, bl.y, 3, 3); + // canvas.contextTop.fillRect(br.x, br.y, 3, 3); + // canvas.contextTop.fillRect(tl.x, tl.y, 3, 3); + // canvas.contextTop.fillRect(tr.x, tr.y, 3, 3); + // canvas.contextTop.fillRect(ml.x, ml.y, 3, 3); + // canvas.contextTop.fillRect(mr.x, mr.y, 3, 3); + // canvas.contextTop.fillRect(mt.x, mt.y, 3, 3); + // }, 50); + + this.oCoords = { + // corners + tl: tl, tr: tr, br: br, bl: bl, + // middle + ml: ml, mt: mt, mr: mr, mb: mb, + // rotating point + mtr: mtr + }; + + // set coordinates of the draggable boxes in the corners used to scale/rotate the image + this._setCornerCoords && this._setCornerCoords(); + + return this; + } + }); +})(); +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Moves an object to the bottom of the stack of drawn objects + * @return {fabric.Object} thisArg + * @chainable + */ + sendToBack: function() { + if (this.group) { + fabric.StaticCanvas.prototype.sendToBack.call(this.group, this); + } + else { + this.canvas.sendToBack(this); + } + return this; + }, + + /** + * Moves an object to the top of the stack of drawn objects + * @return {fabric.Object} thisArg + * @chainable + */ + bringToFront: function() { + if (this.group) { + fabric.StaticCanvas.prototype.bringToFront.call(this.group, this); + } + else { + this.canvas.bringToFront(this); + } + return this; + }, + + /** + * Moves an object down in stack of drawn objects + * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object + * @return {fabric.Object} thisArg + * @chainable + */ + sendBackwards: function(intersecting) { + if (this.group) { + fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting); + } + else { + this.canvas.sendBackwards(this, intersecting); + } + return this; + }, + + /** + * Moves an object up in stack of drawn objects + * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object + * @return {fabric.Object} thisArg + * @chainable + */ + bringForward: function(intersecting) { + if (this.group) { + fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting); + } + else { + this.canvas.bringForward(this, intersecting); + } + return this; + }, + + /** + * Moves an object to specified level in stack of drawn objects + * @param {Number} index New position of object + * @return {fabric.Object} thisArg + * @chainable + */ + moveTo: function(index) { + if (this.group) { + fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index); + } + else { + this.canvas.moveTo(this, index); + } + return this; + } +}); +/* _TO_SVG_START_ */ +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Returns styles-string for svg-export + * @return {String} + */ + getSvgStyles: function() { + + var fill = this.fill + ? (this.fill.toLive ? 'url(#SVGID_' + this.fill.id + ')' : this.fill) + : 'none'; + + var stroke = this.stroke + ? (this.stroke.toLive ? 'url(#SVGID_' + this.stroke.id + ')' : this.stroke) + : 'none'; + + var strokeWidth = this.strokeWidth ? this.strokeWidth : '0'; + var strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : ''; + var strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt'; + var strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter'; + var strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4'; + var opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1'; + + var visibility = this.visible ? '' : " visibility: hidden;"; + var filter = this.shadow && this.type !== 'text' ? 'filter: url(#SVGID_' + this.shadow.id + ');' : ''; + + return [ + "stroke: ", stroke, "; ", + "stroke-width: ", strokeWidth, "; ", + "stroke-dasharray: ", strokeDashArray, "; ", + "stroke-linecap: ", strokeLineCap, "; ", + "stroke-linejoin: ", strokeLineJoin, "; ", + "stroke-miterlimit: ", strokeMiterLimit, "; ", + "fill: ", fill, "; ", + "opacity: ", opacity, ";", + filter, + visibility + ].join(''); + }, + + /** + * Returns transform-string for svg-export + * @return {String} + */ + getSvgTransform: function() { + var toFixed = fabric.util.toFixed; + var angle = this.getAngle(); + var center = this.getCenterPoint(); + + var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; + + var translatePart = "translate(" + + toFixed(center.x, NUM_FRACTION_DIGITS) + + " " + + toFixed(center.y, NUM_FRACTION_DIGITS) + + ")"; + + var anglePart = angle !== 0 + ? (" rotate(" + toFixed(angle, NUM_FRACTION_DIGITS) + ")") + : ''; + + var scalePart = (this.scaleX === 1 && this.scaleY === 1) + ? '' : + (" scale(" + + toFixed(this.scaleX, NUM_FRACTION_DIGITS) + + " " + + toFixed(this.scaleY, NUM_FRACTION_DIGITS) + + ")"); + + var flipXPart = this.flipX ? "matrix(-1 0 0 1 0 0) " : ""; + var flipYPart = this.flipY ? "matrix(1 0 0 -1 0 0)" : ""; + + return [ translatePart, anglePart, scalePart, flipXPart, flipYPart ].join(''); + }, + + /** + * @private + */ + _createBaseSVGMarkup: function() { + var markup = [ ]; + + if (this.fill && this.fill.toLive) { + markup.push(this.fill.toSVG(this, false)); + } + if (this.stroke && this.stroke.toLive) { + markup.push(this.stroke.toSVG(this, false)); + } + if (this.shadow) { + markup.push(this.shadow.toSVG(this)); + } + return markup; + } +}); +/* _TO_SVG_END_ */ +/* + Depends on `stateProperties` +*/ +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Returns true if object state (one of its state properties) was changed + * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called + */ + hasStateChanged: function() { + return this.stateProperties.some(function(prop) { + return this.get(prop) !== this.originalState[prop]; + }, this); + }, + + /** + * Saves state of an object + * @param {Object} [options] Object with additional `stateProperties` array to include when saving state + * @return {fabric.Object} thisArg + */ + saveState: function(options) { + this.stateProperties.forEach(function(prop) { + this.originalState[prop] = this.get(prop); + }, this); + + if (options && options.stateProperties) { + options.stateProperties.forEach(function(prop) { + this.originalState[prop] = this.get(prop); + }, this); + } + + return this; + }, + + /** + * Setups state of an object + * @return {fabric.Object} thisArg + */ + setupState: function() { + this.originalState = { }; + this.saveState(); + + return this; + } +}); +(function(){ + + var getPointer = fabric.util.getPointer, + degreesToRadians = fabric.util.degreesToRadians, + isVML = typeof G_vmlCanvasManager !== 'undefined'; + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * The object interactivity controls. + * @private + */ + _controlsVisibility: null, + + /** + * Determines which corner has been clicked + * @private + * @param {Event} e Event object + * @param {Object} offset Canvas offset + * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found + */ + _findTargetCorner: function(e, offset) { + if (!this.hasControls || !this.active) return false; + + var pointer = getPointer(e, this.canvas.upperCanvasEl), + ex = pointer.x - offset.left, + ey = pointer.y - offset.top, + xPoints, + lines; + + for (var i in this.oCoords) { + + if (!this.isControlVisible(i)) { + continue; + } + + if (i === 'mtr' && !this.hasRotatingPoint) { + continue; + } + + if (this.get('lockUniScaling') && (i === 'mt' || i === 'mr' || i === 'mb' || i === 'ml')) { + continue; + } + + lines = this._getImageLines(this.oCoords[i].corner); + + // debugging + + // canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2); + + xPoints = this._findCrossPoints({x: ex, y: ey}, lines); + if (xPoints !== 0 && xPoints % 2 === 1) { + this.__corner = i; + return i; + } + } + return false; + }, + + /** + * Sets the coordinates of the draggable boxes in the corners of + * the image used to scale/rotate it. + * @private + */ + _setCornerCoords: function() { + var coords = this.oCoords, + theta = degreesToRadians(this.angle), + newTheta = degreesToRadians(45 - this.angle), + cornerHypotenuse = Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, + cosHalfOffset = cornerHypotenuse * Math.cos(newTheta), + sinHalfOffset = cornerHypotenuse * Math.sin(newTheta), + sinTh = Math.sin(theta), + cosTh = Math.cos(theta); + + coords.tl.corner = { + tl: { + x: coords.tl.x - sinHalfOffset, + y: coords.tl.y - cosHalfOffset + }, + tr: { + x: coords.tl.x + cosHalfOffset, + y: coords.tl.y - sinHalfOffset + }, + bl: { + x: coords.tl.x - cosHalfOffset, + y: coords.tl.y + sinHalfOffset + }, + br: { + x: coords.tl.x + sinHalfOffset, + y: coords.tl.y + cosHalfOffset + } + }; + + coords.tr.corner = { + tl: { + x: coords.tr.x - sinHalfOffset, + y: coords.tr.y - cosHalfOffset + }, + tr: { + x: coords.tr.x + cosHalfOffset, + y: coords.tr.y - sinHalfOffset + }, + br: { + x: coords.tr.x + sinHalfOffset, + y: coords.tr.y + cosHalfOffset + }, + bl: { + x: coords.tr.x - cosHalfOffset, + y: coords.tr.y + sinHalfOffset + } + }; + + coords.bl.corner = { + tl: { + x: coords.bl.x - sinHalfOffset, + y: coords.bl.y - cosHalfOffset + }, + bl: { + x: coords.bl.x - cosHalfOffset, + y: coords.bl.y + sinHalfOffset + }, + br: { + x: coords.bl.x + sinHalfOffset, + y: coords.bl.y + cosHalfOffset + }, + tr: { + x: coords.bl.x + cosHalfOffset, + y: coords.bl.y - sinHalfOffset + } + }; + + coords.br.corner = { + tr: { + x: coords.br.x + cosHalfOffset, + y: coords.br.y - sinHalfOffset + }, + bl: { + x: coords.br.x - cosHalfOffset, + y: coords.br.y + sinHalfOffset + }, + br: { + x: coords.br.x + sinHalfOffset, + y: coords.br.y + cosHalfOffset + }, + tl: { + x: coords.br.x - sinHalfOffset, + y: coords.br.y - cosHalfOffset + } + }; + + coords.ml.corner = { + tl: { + x: coords.ml.x - sinHalfOffset, + y: coords.ml.y - cosHalfOffset + }, + tr: { + x: coords.ml.x + cosHalfOffset, + y: coords.ml.y - sinHalfOffset + }, + bl: { + x: coords.ml.x - cosHalfOffset, + y: coords.ml.y + sinHalfOffset + }, + br: { + x: coords.ml.x + sinHalfOffset, + y: coords.ml.y + cosHalfOffset + } + }; + + coords.mt.corner = { + tl: { + x: coords.mt.x - sinHalfOffset, + y: coords.mt.y - cosHalfOffset + }, + tr: { + x: coords.mt.x + cosHalfOffset, + y: coords.mt.y - sinHalfOffset + }, + bl: { + x: coords.mt.x - cosHalfOffset, + y: coords.mt.y + sinHalfOffset + }, + br: { + x: coords.mt.x + sinHalfOffset, + y: coords.mt.y + cosHalfOffset + } + }; + + coords.mr.corner = { + tl: { + x: coords.mr.x - sinHalfOffset, + y: coords.mr.y - cosHalfOffset + }, + tr: { + x: coords.mr.x + cosHalfOffset, + y: coords.mr.y - sinHalfOffset + }, + bl: { + x: coords.mr.x - cosHalfOffset, + y: coords.mr.y + sinHalfOffset + }, + br: { + x: coords.mr.x + sinHalfOffset, + y: coords.mr.y + cosHalfOffset + } + }; + + coords.mb.corner = { + tl: { + x: coords.mb.x - sinHalfOffset, + y: coords.mb.y - cosHalfOffset + }, + tr: { + x: coords.mb.x + cosHalfOffset, + y: coords.mb.y - sinHalfOffset + }, + bl: { + x: coords.mb.x - cosHalfOffset, + y: coords.mb.y + sinHalfOffset + }, + br: { + x: coords.mb.x + sinHalfOffset, + y: coords.mb.y + cosHalfOffset + } + }; + + coords.mtr.corner = { + tl: { + x: coords.mtr.x - sinHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y - cosHalfOffset - (cosTh * this.rotatingPointOffset) + }, + tr: { + x: coords.mtr.x + cosHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y - sinHalfOffset - (cosTh * this.rotatingPointOffset) + }, + bl: { + x: coords.mtr.x - cosHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y + sinHalfOffset - (cosTh * this.rotatingPointOffset) + }, + br: { + x: coords.mtr.x + sinHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y + cosHalfOffset - (cosTh * this.rotatingPointOffset) + } + }; + }, + /** + * Draws borders of an object's bounding box. + * Requires public properties: width, height + * Requires public options: padding, borderColor + * @param {CanvasRenderingContext2D} ctx Context to draw on + * @return {fabric.Object} thisArg + * @chainable + */ + drawBorders: function(ctx) { + if (!this.hasBorders) return this; + + var padding = this.padding, + padding2 = padding * 2, + strokeWidth = ~~(this.strokeWidth / 2) * 2; // Round down to even number + + ctx.save(); + + ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; + ctx.strokeStyle = this.borderColor; + + var scaleX = 1 / this._constrainScale(this.scaleX), + scaleY = 1 / this._constrainScale(this.scaleY); + + ctx.lineWidth = 1 / this.borderScaleFactor; + + ctx.scale(scaleX, scaleY); + + var w = this.getWidth(), + h = this.getHeight(); + + ctx.strokeRect( + ~~(-(w / 2) - padding - strokeWidth / 2 * this.scaleX) - 0.5, // offset needed to make lines look sharper + ~~(-(h / 2) - padding - strokeWidth / 2 * this.scaleY) - 0.5, + ~~(w + padding2 + strokeWidth * this.scaleX) + 1, // double offset needed to make lines look sharper + ~~(h + padding2 + strokeWidth * this.scaleY) + 1 + ); + + if (this.hasRotatingPoint && this.isControlVisible('mtr') && !this.get('lockRotation') && this.hasControls) { + + var rotateHeight = ( + this.flipY + ? h + (strokeWidth * this.scaleY) + (padding * 2) + : -h - (strokeWidth * this.scaleY) - (padding * 2) + ) / 2; + + ctx.beginPath(); + ctx.moveTo(0, rotateHeight); + ctx.lineTo(0, rotateHeight + (this.flipY ? this.rotatingPointOffset : -this.rotatingPointOffset)); + ctx.closePath(); + ctx.stroke(); + } + + ctx.restore(); + return this; + }, + + /** + * Draws corners of an object's bounding box. + * Requires public properties: width, height, scaleX, scaleY + * Requires public options: cornerSize, padding + * @param {CanvasRenderingContext2D} ctx Context to draw on + * @return {fabric.Object} thisArg + * @chainable + */ + drawControls: function(ctx) { + if (!this.hasControls) return this; + + var size = this.cornerSize, + size2 = size / 2, + strokeWidth2 = ~~(this.strokeWidth / 2), // half strokeWidth rounded down + left = -(this.width / 2), + top = -(this.height / 2), + paddingX = this.padding / this.scaleX, + paddingY = this.padding / this.scaleY, + scaleOffsetY = size2 / this.scaleY, + scaleOffsetX = size2 / this.scaleX, + scaleOffsetSizeX = (size2 - size) / this.scaleX, + scaleOffsetSizeY = (size2 - size) / this.scaleY, + height = this.height, + width = this.width, + methodName = this.transparentCorners ? 'strokeRect' : 'fillRect'; + + ctx.save(); + + ctx.lineWidth = 1 / Math.max(this.scaleX, this.scaleY); + + ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; + ctx.strokeStyle = ctx.fillStyle = this.cornerColor; + + // top-left + this._drawControl('tl', ctx, methodName, + left - scaleOffsetX - strokeWidth2 - paddingX, + top - scaleOffsetY - strokeWidth2 - paddingY); + + // top-right + this._drawControl('tr', ctx, methodName, + left + width - scaleOffsetX + strokeWidth2 + paddingX, + top - scaleOffsetY - strokeWidth2 - paddingY); + + // bottom-left + this._drawControl('tr', ctx, methodName, + left - scaleOffsetX - strokeWidth2 - paddingX, + top + height + scaleOffsetSizeY + strokeWidth2 + paddingY); + + // bottom-right + this._drawControl('br', ctx, methodName, + left + width + scaleOffsetSizeX + strokeWidth2 + paddingX, + top + height + scaleOffsetSizeY + strokeWidth2 + paddingY); + + if (!this.get('lockUniScaling')) { + + // middle-top + this._drawControl('mt', ctx, methodName, + left + width/2 - scaleOffsetX, + top - scaleOffsetY - strokeWidth2 - paddingY); + + // middle-bottom + this._drawControl('mb', ctx, methodName, + left + width/2 - scaleOffsetX, + top + height + scaleOffsetSizeY + strokeWidth2 + paddingY); + + // middle-right + this._drawControl('mb', ctx, methodName, + left + width + scaleOffsetSizeX + strokeWidth2 + paddingX, + top + height/2 - scaleOffsetY); + + // middle-left + this._drawControl('ml', ctx, methodName, + left - scaleOffsetX - strokeWidth2 - paddingX, + top + height/2 - scaleOffsetY); + } + + // middle-top-rotate + if (this.hasRotatingPoint) { + this._drawControl('mtr', ctx, methodName, + left + width/2 - scaleOffsetX, + this.flipY + ? (top + height + (this.rotatingPointOffset / this.scaleY) - this.cornerSize/this.scaleX/2 + strokeWidth2 + paddingY) + : (top - (this.rotatingPointOffset / this.scaleY) - this.cornerSize/this.scaleY/2 - strokeWidth2 - paddingY)); + } + + ctx.restore(); + + return this; + }, + + /** + * @private + */ + _drawControl: function(control, ctx, methodName, left, top) { + var sizeX = this.cornerSize / this.scaleX, + sizeY = this.cornerSize / this.scaleY; + + if (this.isControlVisible(control)) { + isVML || this.transparentCorners || ctx.clearRect(left, top, sizeX, sizeY); + ctx[methodName](left, top, sizeX, sizeY); + } + }, + + /** + * Returns true if the specified control is visible, false otherwise. + * @param {String} controlName The name of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'. + * @returns {Boolean} true if the specified control is visible, false otherwise + */ + isControlVisible: function(controlName) { + return this._getControlsVisibility()[controlName]; + }, + + /** + * Sets the visibility of the specified control. + * @param {String} controlName The name of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'. + * @param {Boolean} visible true to set the specified control visible, false otherwise + * @return {fabric.Object} thisArg + * @chainable + */ + setControlVisible: function(controlName, visible) { + this._getControlsVisibility()[controlName] = visible; + return this; + }, + + /** + * Sets the visibility state of object controls. + * @param {Object} [options] Options object + * @param {Boolean} [options.bl] true to enable the bottom-left control, false to disable it + * @param {Boolean} [options.br] true to enable the bottom-right control, false to disable it + * @param {Boolean} [options.mb] true to enable the middle-bottom control, false to disable it + * @param {Boolean} [options.ml] true to enable the middle-left control, false to disable it + * @param {Boolean} [options.mr] true to enable the middle-right control, false to disable it + * @param {Boolean} [options.mt] true to enable the middle-top control, false to disable it + * @param {Boolean} [options.tl] true to enable the top-left control, false to disable it + * @param {Boolean} [options.tr] true to enable the top-right control, false to disable it + * @param {Boolean} [options.mtr] true to enable the middle-top-rotate control, false to disable it + * @return {fabric.Object} thisArg + * @chainable + */ + setControlsVisibility: function(options) { + options || (options = { }); + + for (var p in options) { + this.setControlVisible(p, options[p]); + } + return this; + }, + + /** + * Returns the instance of the control visibility set for this object. + * @private + * @returns {Object} + */ + _getControlsVisibility: function() { + if (!this._controlsVisibility) { + this._controlsVisibility = { + tl: true, + tr: true, + br: true, + bl: true, + ml: true, + mt: true, + mr: true, + mb: true, + mtr: true + }; + } + return this._controlsVisibility; + } + }); +})(); +(function(global) { + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + coordProps = { 'x1': 1, 'x2': 1, 'y1': 1, 'y2': 1 }, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Line) { + fabric.warn('fabric.Line is already defined'); + return; + } + + /** + * Line class + * @class fabric.Line + * @extends fabric.Object + * @see {@link fabric.Line#initialize} for constructor definition + */ + fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'line', + + /** + * Constructor + * @param {Array} [points] Array of points + * @param {Object} [options] Options object + * @return {fabric.Line} thisArg + */ + initialize: function(points, options) { + options = options || { }; + + if (!points) { + points = [0, 0, 0, 0]; + } + + this.callSuper('initialize', options); + + this.set('x1', points[0]); + this.set('y1', points[1]); + this.set('x2', points[2]); + this.set('y2', points[3]); + + this._setWidthHeight(options); + }, + + /** + * @private + * @param {Object} [options] Options + */ + _setWidthHeight: function(options) { + options || (options = { }); + + this.set('width', Math.abs(this.x2 - this.x1) || 1); + this.set('height', Math.abs(this.y2 - this.y1) || 1); + + this.set('left', 'left' in options ? options.left : (Math.min(this.x1, this.x2) + this.width / 2)); + this.set('top', 'top' in options ? options.top : (Math.min(this.y1, this.y2) + this.height / 2)); + }, + + /** + * @private + * @param {String} key + * @param {Any} value + */ + _set: function(key, value) { + this[key] = value; + if (key in coordProps) { + this._setWidthHeight(); + } + return this; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + ctx.beginPath(); + + var isInPathGroup = this.group && this.group.type === 'path-group'; + if (isInPathGroup && !this.transformMatrix) { + ctx.translate(-this.group.width/2 + this.left, -this.group.height / 2 + this.top); + } + + if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) { + + // move from center (of virtual box) to its left/top corner + // we can't assume x1, y1 is top left and x2, y2 is bottom right + var xMult = this.x1 <= this.x2 ? -1 : 1; + var yMult = this.y1 <= this.y2 ? -1 : 1; + + ctx.moveTo( + this.width === 1 ? 0 : (xMult * this.width / 2), + this.height === 1 ? 0 : (yMult * this.height / 2)); + + ctx.lineTo( + this.width === 1 ? 0 : (xMult * -1 * this.width / 2), + this.height === 1 ? 0 : (yMult * -1 * this.height / 2)); + } + + ctx.lineWidth = this.strokeWidth; + + // TODO: test this + // make sure setting "fill" changes color of a line + // (by copying fillStyle to strokeStyle, since line is stroked, not filled) + var origStrokeStyle = ctx.strokeStyle; + ctx.strokeStyle = this.stroke || ctx.fillStyle; + this._renderStroke(ctx); + ctx.strokeStyle = origStrokeStyle; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var + xMult = this.x1 <= this.x2 ? -1 : 1, + yMult = this.y1 <= this.y2 ? -1 : 1, + x = this.width === 1 ? 0 : xMult * this.width / 2, + y = this.height === 1 ? 0 : yMult * this.height / 2; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, -x, -y, this.strokeDashArray); + ctx.closePath(); + }, + + /** + * Returns object representation of an instance + * @methd toObject + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + x1: this.get('x1'), + y1: this.get('y1'), + x2: this.get('x2'), + y2: this.get('y2') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(); + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement}) + * @static + * @memberOf fabric.Line + * @see http://www.w3.org/TR/SVG/shapes.html#LineElement + */ + fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' ')); + + /** + * Returns fabric.Line instance from an SVG element + * @static + * @memberOf fabric.Line + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Line} instance of fabric.Line + */ + fabric.Line.fromElement = function(element, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES); + var points = [ + parsedAttributes.x1 || 0, + parsedAttributes.y1 || 0, + parsedAttributes.x2 || 0, + parsedAttributes.y2 || 0 + ]; + return new fabric.Line(points, extend(parsedAttributes, options)); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Line instance from an object representation + * @static + * @memberOf fabric.Line + * @param {Object} object Object to create an instance from + * @return {fabric.Line} instance of fabric.Line + */ + fabric.Line.fromObject = function(object) { + var points = [object.x1, object.y1, object.x2, object.y2]; + return new fabric.Line(points, object); + }; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global) { + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }), + piBy2 = Math.PI * 2, + extend = fabric.util.object.extend; + + if (fabric.Circle) { + fabric.warn('fabric.Circle is already defined.'); + return; + } + + /** + * Circle class + * @class fabric.Circle + * @extends fabric.Object + * @see {@link fabric.Circle#initialize} for constructor definition + */ + fabric.Circle = fabric.util.createClass(fabric.Object, /** @lends fabric.Circle.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'circle', + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Circle} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.set('radius', options.radius || 0); + this.callSuper('initialize', options); + }, + + /** + * @private + * @param {String} key + * @param {Any} value + * @return {fabric.Circle} thisArg + */ + _set: function(key, value) { + this.callSuper('_set', key, value); + + if (key === 'radius') { + this.setRadius(value); + } + + return this; + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + radius: this.get('radius') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(); + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param ctx {CanvasRenderingContext2D} context to render on + */ + _render: function(ctx, noTransform) { + ctx.beginPath(); + // multiply by currently set alpha (the one that was set by path group where this object is contained, for example) + ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; + ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.radius, 0, piBy2, false); + ctx.closePath(); + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * Returns horizontal radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusX: function() { + return this.get('radius') * this.get('scaleX'); + }, + + /** + * Returns vertical radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusY: function() { + return this.get('radius') * this.get('scaleY'); + }, + + /** + * Sets radius of an object (and updates width accordingly) + * @return {Number} + */ + setRadius: function(value) { + this.radius = value; + this.set('width', value * 2).set('height', value * 2); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Circle.fromElement}) + * @static + * @memberOf fabric.Circle + * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement + */ + fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy r'.split(' ')); + + /** + * Returns {@link fabric.Circle} instance from an SVG element + * @static + * @memberOf fabric.Circle + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @throws {Error} If value of `r` attribute is missing or invalid + * @return {fabric.Circle} Instance of fabric.Circle + */ + fabric.Circle.fromElement = function(element, options) { + options || (options = { }); + var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES); + if (!isValidRadius(parsedAttributes)) { + throw new Error('value of `r` attribute is required and can not be negative'); + } + if ('left' in parsedAttributes) { + parsedAttributes.left -= (options.width / 2) || 0; + } + if ('top' in parsedAttributes) { + parsedAttributes.top -= (options.height / 2) || 0; + } + var obj = new fabric.Circle(extend(parsedAttributes, options)); + + obj.cx = parseFloat(element.getAttribute('cx')) || 0; + obj.cy = parseFloat(element.getAttribute('cy')) || 0; + + return obj; + }; + + /** + * @private + */ + function isValidRadius(attributes) { + return (('radius' in attributes) && (attributes.radius > 0)); + } + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Circle} instance from an object representation + * @static + * @memberOf fabric.Circle + * @param {Object} object Object to create an instance from + * @return {Object} Instance of fabric.Circle + */ + fabric.Circle.fromObject = function(object) { + return new fabric.Circle(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global) { + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Triangle) { + fabric.warn('fabric.Triangle is already defined'); + return; + } + + /** + * Triangle class + * @class fabric.Triangle + * @extends fabric.Object + * @return {fabric.Triangle} thisArg + * @see {@link fabric.Triangle#initialize} for constructor definition + */ + fabric.Triangle = fabric.util.createClass(fabric.Object, /** @lends fabric.Triangle.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'triangle', + + /** + * Constructor + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + + this.set('width', options.width || 100) + .set('height', options.height || 100); + }, + + /** + * @private + * @param ctx {CanvasRenderingContext2D} Context to render on + */ + _render: function(ctx) { + var widthBy2 = this.width / 2, + heightBy2 = this.height / 2; + + ctx.beginPath(); + ctx.moveTo(-widthBy2, heightBy2); + ctx.lineTo(0, -heightBy2); + ctx.lineTo(widthBy2, heightBy2); + ctx.closePath(); + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param ctx {CanvasRenderingContext2D} Context to render on + */ + _renderDashedStroke: function(ctx) { + var widthBy2 = this.width / 2, + heightBy2 = this.height / 2; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray); + ctx.closePath(); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), + widthBy2 = this.width / 2, + heightBy2 = this.height / 2; + + var points = [ + -widthBy2 + " " + heightBy2, + "0 " + -heightBy2, + widthBy2 + " " + heightBy2 + ].join(","); + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /** + * Returns fabric.Triangle instance from an object representation + * @static + * @memberOf fabric.Triangle + * @param object {Object} object to create an instance from + * @return {Object} instance of Canvas.Triangle + */ + fabric.Triangle.fromObject = function(object) { + return new fabric.Triangle(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global){ + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }), + piBy2 = Math.PI * 2, + extend = fabric.util.object.extend; + + if (fabric.Ellipse) { + fabric.warn('fabric.Ellipse is already defined.'); + return; + } + + /** + * Ellipse class + * @class fabric.Ellipse + * @extends fabric.Object + * @return {fabric.Ellipse} thisArg + * @see {@link fabric.Ellipse#initialize} for constructor definition + */ + fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @lends fabric.Ellipse.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'ellipse', + + /** + * Horizontal radius + * @type Number + * @default + */ + rx: 0, + + /** + * Vertical radius + * @type Number + * @default + */ + ry: 0, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Ellipse} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + + this.set('rx', options.rx || 0); + this.set('ry', options.ry || 0); + + this.set('width', this.get('rx') * 2); + this.set('height', this.get('ry') * 2); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + rx: this.get('rx'), + ry: this.get('ry') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(); + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Renders this instance on a given context + * @param ctx {CanvasRenderingContext2D} context to render on + * @param noTransform {Boolean} context is not transformed when set to true + */ + render: function(ctx, noTransform) { + // do not use `get` for perf. reasons + if (this.rx === 0 || this.ry === 0) return; + return this.callSuper('render', ctx, noTransform); + }, + + /** + * @private + * @param ctx {CanvasRenderingContext2D} context to render on + */ + _render: function(ctx, noTransform) { + ctx.beginPath(); + ctx.save(); + ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; + if (this.transformMatrix && this.group) { + ctx.translate(this.cx, this.cy); + } + ctx.transform(1, 0, 0, this.ry/this.rx, 0, 0); + ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.rx, 0, piBy2, false); + + this._renderFill(ctx); + this._renderStroke(ctx); + ctx.restore(); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement}) + * @static + * @memberOf fabric.Ellipse + * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement + */ + fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy rx ry'.split(' ')); + + /** + * Returns {@link fabric.Ellipse} instance from an SVG element + * @static + * @memberOf fabric.Ellipse + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Ellipse} + */ + fabric.Ellipse.fromElement = function(element, options) { + options || (options = { }); + + var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES); + var cx = parsedAttributes.left; + var cy = parsedAttributes.top; + + if ('left' in parsedAttributes) { + parsedAttributes.left -= (options.width / 2) || 0; + } + if ('top' in parsedAttributes) { + parsedAttributes.top -= (options.height / 2) || 0; + } + + var ellipse = new fabric.Ellipse(extend(parsedAttributes, options)); + + ellipse.cx = cx || 0; + ellipse.cy = cy || 0; + + return ellipse; + }; + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Ellipse} instance from an object representation + * @static + * @memberOf fabric.Ellipse + * @param {Object} object Object to create an instance from + * @return {fabric.Ellipse} + */ + fabric.Ellipse.fromObject = function(object) { + return new fabric.Ellipse(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global) { + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + if (fabric.Rect) { + console.warn('fabric.Rect is already defined'); + return; + } + + var stateProperties = fabric.Object.prototype.stateProperties.concat(); + stateProperties.push('rx', 'ry', 'x', 'y'); + + /** + * Rectangle class + * @class fabric.Rect + * @extends fabric.Object + * @return {fabric.Rect} thisArg + * @see {@link fabric.Rect#initialize} for constructor definition + */ + fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ { + + /** + * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged}) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: stateProperties, + + /** + * Type of an object + * @type String + * @default + */ + type: 'rect', + + /** + * Horizontal border radius + * @type Number + * @default + */ + rx: 0, + + /** + * Vertical border radius + * @type Number + * @default + */ + ry: 0, + + /** + * @type Number + * @default + */ + x: 0, + + /** + * @type Number + * @default + */ + y: 0, + + /** + * Used to specify dash pattern for stroke on this object + * @type Array + */ + strokeDashArray: null, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + this._initRxRy(); + + this.x = options.x || 0; + this.y = options.y || 0; + }, + + /** + * Initializes rx/ry attributes + * @private + */ + _initRxRy: function() { + if (this.rx && !this.ry) { + this.ry = this.rx; + } + else if (this.ry && !this.rx) { + this.rx = this.ry; + } + }, + + /** + * @private + * @param ctx {CanvasRenderingContext2D} context to render on + */ + _render: function(ctx) { + var rx = this.rx || 0, + ry = this.ry || 0, + x = -this.width / 2, + y = -this.height / 2, + w = this.width, + h = this.height, + isInPathGroup = this.group && this.group.type === 'path-group'; + + ctx.beginPath(); + ctx.globalAlpha = isInPathGroup ? (ctx.globalAlpha * this.opacity) : this.opacity; + + if (this.transformMatrix && isInPathGroup) { + ctx.translate( + this.width / 2 + this.x, + this.height / 2 + this.y); + } + if (!this.transformMatrix && isInPathGroup) { + ctx.translate( + -this.group.width / 2 + this.width / 2 + this.x, + -this.group.height / 2 + this.height / 2 + this.y); + } + + var isRounded = rx !== 0 || ry !== 0; + + ctx.moveTo(x+rx, y); + ctx.lineTo(x+w-rx, y); + isRounded && ctx.quadraticCurveTo(x+w, y, x+w, y+ry, x+w, y+ry); + ctx.lineTo(x+w, y+h-ry); + isRounded && ctx.quadraticCurveTo(x+w,y+h,x+w-rx,y+h,x+w-rx,y+h); + ctx.lineTo(x+rx,y+h); + isRounded && ctx.quadraticCurveTo(x,y+h,x,y+h-ry,x,y+h-ry); + ctx.lineTo(x,y+ry); + isRounded && ctx.quadraticCurveTo(x,y,x+rx,y,x+rx,y); + ctx.closePath(); + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param ctx {CanvasRenderingContext2D} context to render on + */ + _renderDashedStroke: function(ctx) { + var x = -this.width/2, + y = -this.height/2, + w = this.width, + h = this.height; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, x+w, y, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x+w, y, x+w, y+h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x+w, y+h, x, y+h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x, y+h, x, y, this.strokeDashArray); + ctx.closePath(); + }, + + /** + * Since coordinate system differs from that of SVG + * @private + */ + _normalizeLeftTopProperties: function(parsedAttributes) { + if ('left' in parsedAttributes) { + this.set('left', parsedAttributes.left + this.getWidth() / 2); + } + this.set('x', parsedAttributes.left || 0); + if ('top' in parsedAttributes) { + this.set('top', parsedAttributes.top + this.getHeight() / 2); + } + this.set('y', parsedAttributes.top || 0); + return this; + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var object = extend(this.callSuper('toObject', propertiesToInclude), { + rx: this.get('rx') || 0, + ry: this.get('ry') || 0, + x: this.get('x'), + y: this.get('y') + }); + if (!this.includeDefaultValues) { + this._removeDefaultValues(object); + } + return object; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(); + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`) + * @static + * @memberOf fabric.Rect + * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement + */ + fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' ')); + + /** + * @private + */ + function _setDefaultLeftTopValues(attributes) { + attributes.left = attributes.left || 0; + attributes.top = attributes.top || 0; + return attributes; + } + + /** + * Returns {@link fabric.Rect} instance from an SVG element + * @static + * @memberOf fabric.Rect + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Rect} Instance of fabric.Rect + */ + fabric.Rect.fromElement = function(element, options) { + if (!element) { + return null; + } + + var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES); + parsedAttributes = _setDefaultLeftTopValues(parsedAttributes); + + var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + rect._normalizeLeftTopProperties(parsedAttributes); + + return rect; + }; + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Rect} instance from an object representation + * @static + * @memberOf fabric.Rect + * @param object {Object} object to create an instance from + * @return {Object} instance of fabric.Rect + */ + fabric.Rect.fromObject = function(object) { + return new fabric.Rect(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global) { + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }), + toFixed = fabric.util.toFixed; + + if (fabric.Polyline) { + fabric.warn('fabric.Polyline is already defined'); + return; + } + + /** + * Polyline class + * @class fabric.Polyline + * @extends fabric.Object + * @see {@link fabric.Polyline#initialize} for constructor definition + */ + fabric.Polyline = fabric.util.createClass(fabric.Object, /** @lends fabric.Polyline.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'polyline', + + /** + * Constructor + * @param {Array} points Array of points (where each point is an object with x and y) + * @param {Object} [options] Options object + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + * @return {fabric.Polyline} thisArg + * @example + * var poly = new fabric.Polyline([ + * { x: 10, y: 10 }, + * { x: 50, y: 30 }, + * { x: 40, y: 70 }, + * { x: 60, y: 50 }, + * { x: 100, y: 150 }, + * { x: 40, y: 100 } + * ], { + * stroke: 'red', + * left: 100, + * top: 100 + * }); + */ + initialize: function(points, options, skipOffset) { + options = options || { }; + this.set('points', points); + this.callSuper('initialize', options); + this._calcDimensions(skipOffset); + }, + + /** + * @private + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + */ + _calcDimensions: function(skipOffset) { + return fabric.Polygon.prototype._calcDimensions.call(this, skipOffset); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return fabric.Polygon.prototype.toObject.call(this, propertiesToInclude); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var points = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.points.length; i < len; i++) { + points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' '); + } + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + var point; + ctx.beginPath(); + ctx.moveTo(this.points[0].x, this.points[0].y); + for (var i = 0, len = this.points.length; i < len; i++) { + point = this.points[i]; + ctx.lineTo(point.x, point.y); + } + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var p1, p2; + + ctx.beginPath(); + for (var i = 0, len = this.points.length; i < len; i++) { + p1 = this.points[i]; + p2 = this.points[i+1] || p1; + fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); + } + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.get('points').length; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement}) + * @static + * @memberOf fabric.Polyline + * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement + */ + fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + + /** + * Returns fabric.Polyline instance from an SVG element + * @static + * @memberOf fabric.Polyline + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Polyline} Instance of fabric.Polyline + */ + fabric.Polyline.fromElement = function(element, options) { + if (!element) { + return null; + } + options || (options = { }); + + var points = fabric.parsePointsAttribute(element.getAttribute('points')), + parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES); + + fabric.util.normalizePoints(points, options); + + return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options), true); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Polyline instance from an object representation + * @static + * @memberOf fabric.Polyline + * @param object {Object} object Object to create an instance from + * @return {fabric.Polyline} Instance of fabric.Polyline + */ + fabric.Polyline.fromObject = function(object) { + var points = object.points; + return new fabric.Polyline(points, object, true); + }; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global) { + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + min = fabric.util.array.min, + max = fabric.util.array.max, + toFixed = fabric.util.toFixed; + + if (fabric.Polygon) { + fabric.warn('fabric.Polygon is already defined'); + return; + } + + /** + * Polygon class + * @class fabric.Polygon + * @extends fabric.Object + * @see {@link fabric.Polygon#initialize} for constructor definition + */ + fabric.Polygon = fabric.util.createClass(fabric.Object, /** @lends fabric.Polygon.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'polygon', + + /** + * Constructor + * @param {Array} points Array of points + * @param {Object} [options] Options object + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + * @return {fabric.Polygon} thisArg + */ + initialize: function(points, options, skipOffset) { + options = options || { }; + this.points = points; + this.callSuper('initialize', options); + this._calcDimensions(skipOffset); + }, + + /** + * @private + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + */ + _calcDimensions: function(skipOffset) { + + var points = this.points, + minX = min(points, 'x'), + minY = min(points, 'y'), + maxX = max(points, 'x'), + maxY = max(points, 'y'); + + this.width = (maxX - minX) || 1; + this.height = (maxY - minY) || 1; + + this.minX = minX; + this.minY = minY; + + if (skipOffset) return; + + var halfWidth = this.width / 2 + this.minX, + halfHeight = this.height / 2 + this.minY; + + // change points to offset polygon into a bounding box + this.points.forEach(function(p) { + p.x -= halfWidth; + p.y -= halfHeight; + }, this); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + points: this.points.concat() + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var points = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.points.length; i < len; i++) { + points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' '); + } + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + var point; + ctx.beginPath(); + ctx.moveTo(this.points[0].x, this.points[0].y); + for (var i = 0, len = this.points.length; i < len; i++) { + point = this.points[i]; + ctx.lineTo(point.x, point.y); + } + this._renderFill(ctx); + if (this.stroke || this.strokeDashArray) { + ctx.closePath(); + this._renderStroke(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var p1, p2; + + ctx.beginPath(); + for (var i = 0, len = this.points.length; i < len; i++) { + p1 = this.points[i]; + p2 = this.points[i+1] || this.points[0]; + fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); + } + ctx.closePath(); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.points.length; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`) + * @static + * @memberOf fabric.Polygon + * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement + */ + fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + + /** + * Returns {@link fabric.Polygon} instance from an SVG element + * @static + * @memberOf fabric.Polygon + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Polygon} Instance of fabric.Polygon + */ + fabric.Polygon.fromElement = function(element, options) { + if (!element) { + return null; + } + options || (options = { }); + + var points = fabric.parsePointsAttribute(element.getAttribute('points')), + parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES); + + fabric.util.normalizePoints(points, options); + + return new fabric.Polygon(points, extend(parsedAttributes, options), true); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Polygon instance from an object representation + * @static + * @memberOf fabric.Polygon + * @param object {Object} object Object to create an instance from + * @return {fabric.Polygon} Instance of fabric.Polygon + */ + fabric.Polygon.fromObject = function(object) { + return new fabric.Polygon(object.points, object, true); + }; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global) { + + var commandLengths = { + m: 2, + l: 2, + h: 1, + v: 1, + c: 6, + s: 4, + q: 4, + t: 2, + a: 7 + }; + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }), + min = fabric.util.array.min, + max = fabric.util.array.max, + extend = fabric.util.object.extend, + _toString = Object.prototype.toString, + drawArc = fabric.util.drawArc; + + if (fabric.Path) { + fabric.warn('fabric.Path is already defined'); + return; + } + + /** + * @private + */ + function getX(item) { + if (item[0] === 'H') { + return item[1]; + } + return item[item.length - 2]; + } + + /** + * @private + */ + function getY(item) { + if (item[0] === 'V') { + return item[1]; + } + return item[item.length - 1]; + } + + /** + * Path class + * @class fabric.Path + * @extends fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup} + * @see {@link fabric.Path#initialize} for constructor definition + */ + fabric.Path = fabric.util.createClass(fabric.Object, /** @lends fabric.Path.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'path', + + /** + * Constructor + * @param {Array|String} path Path data (sequence of coordinates and corresponding "command" tokens) + * @param {Object} [options] Options object + * @return {fabric.Path} thisArg + */ + initialize: function(path, options) { + options = options || { }; + + this.setOptions(options); + + if (!path) { + throw new Error('`path` argument is required'); + } + + var fromArray = _toString.call(path) === '[object Array]'; + + this.path = fromArray + ? path + // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values) + : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi); + + if (!this.path) return; + + if (!fromArray) { + this.path = this._parsePath(); + } + this._initializePath(options); + + if (options.sourcePath) { + this.setSourcePath(options.sourcePath); + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initializePath: function (options) { + var isWidthSet = 'width' in options && options.width != null, + isHeightSet = 'height' in options && options.width != null, + isLeftSet = 'left' in options, + isTopSet = 'top' in options, + origLeft = isLeftSet ? this.left : 0, + origTop = isTopSet ? this.top : 0; + + if (!isWidthSet || !isHeightSet) { + extend(this, this._parseDimensions()); + if (isWidthSet) { + this.width = options.width; + } + if (isHeightSet) { + this.height = options.height; + } + } + else { //Set center location relative to given height/width if not specified + if (!isTopSet) { + this.top = this.height / 2; + } + if (!isLeftSet) { + this.left = this.width / 2; + } + } + this.pathOffset = this.pathOffset || this._calculatePathOffset(origLeft, origTop); //Save top-left coords as offset + }, + + /** + * @private + * @param {Boolean} positionSet When false, path offset is returned otherwise 0 + */ + _calculatePathOffset: function (origLeft, origTop) { + return { + x: this.left - origLeft - (this.width / 2), + y: this.top - origTop - (this.height / 2) + }; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx context to render path on + */ + _render: function(ctx) { + var current, // current instruction + previous = null, + x = 0, // current x + y = 0, // current y + controlX = 0, // current control point x + controlY = 0, // current control point y + tempX, + tempY, + tempControlX, + tempControlY, + l = -((this.width / 2) + this.pathOffset.x), + t = -((this.height / 2) + this.pathOffset.y), + methodName; + + for (var i = 0, len = this.path.length; i < len; ++i) { + + current = this.path[i]; + + switch (current[0]) { // first letter + + case 'l': // lineto, relative + x += current[1]; + y += current[2]; + ctx.lineTo(x + l, y + t); + break; + + case 'L': // lineto, absolute + x = current[1]; + y = current[2]; + ctx.lineTo(x + l, y + t); + break; + + case 'h': // horizontal lineto, relative + x += current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'H': // horizontal lineto, absolute + x = current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'v': // vertical lineto, relative + y += current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'V': // verical lineto, absolute + y = current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'm': // moveTo, relative + x += current[1]; + y += current[2]; + // draw a line if previous command was moveTo as well (otherwise, it will have no effect) + methodName = (previous && (previous[0] === 'm' || previous[0] === 'M')) + ? 'lineTo' + : 'moveTo'; + ctx[methodName](x + l, y + t); + break; + + case 'M': // moveTo, absolute + x = current[1]; + y = current[2]; + // draw a line if previous command was moveTo as well (otherwise, it will have no effect) + methodName = (previous && (previous[0] === 'm' || previous[0] === 'M')) + ? 'lineTo' + : 'moveTo'; + ctx[methodName](x + l, y + t); + break; + + case 'c': // bezierCurveTo, relative + tempX = x + current[5]; + tempY = y + current[6]; + controlX = x + current[3]; + controlY = y + current[4]; + ctx.bezierCurveTo( + x + current[1] + l, // x1 + y + current[2] + t, // y1 + controlX + l, // x2 + controlY + t, // y2 + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'C': // bezierCurveTo, absolute + x = current[5]; + y = current[6]; + controlX = current[3]; + controlY = current[4]; + ctx.bezierCurveTo( + current[1] + l, + current[2] + t, + controlX + l, + controlY + t, + x + l, + y + t + ); + break; + + case 's': // shorthand cubic bezierCurveTo, relative + + // transform to absolute x,y + tempX = x + current[3]; + tempY = y + current[4]; + + // calculate reflection of previous control points + controlX = controlX ? (2 * x - controlX) : x; + controlY = controlY ? (2 * y - controlY) : y; + + ctx.bezierCurveTo( + controlX + l, + controlY + t, + x + current[1] + l, + y + current[2] + t, + tempX + l, + tempY + t + ); + // set control point to 2nd one of this command + // "... the first control point is assumed to be + // the reflection of the second control point on + // the previous command relative to the current point." + controlX = x + current[1]; + controlY = y + current[2]; + + x = tempX; + y = tempY; + break; + + case 'S': // shorthand cubic bezierCurveTo, absolute + tempX = current[3]; + tempY = current[4]; + // calculate reflection of previous control points + controlX = 2*x - controlX; + controlY = 2*y - controlY; + ctx.bezierCurveTo( + controlX + l, + controlY + t, + current[1] + l, + current[2] + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + + // set control point to 2nd one of this command + // "... the first control point is assumed to be + // the reflection of the second control point on + // the previous command relative to the current point." + controlX = current[1]; + controlY = current[2]; + + break; + + case 'q': // quadraticCurveTo, relative + // transform to absolute x,y + tempX = x + current[3]; + tempY = y + current[4]; + + controlX = x + current[1]; + controlY = y + current[2]; + + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'Q': // quadraticCurveTo, absolute + tempX = current[3]; + tempY = current[4]; + + ctx.quadraticCurveTo( + current[1] + l, + current[2] + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + controlX = current[1]; + controlY = current[2]; + break; + + case 't': // shorthand quadraticCurveTo, relative + + // transform to absolute x,y + tempX = x + current[1]; + tempY = y + current[2]; + + + if (previous[0].match(/[QqTt]/) === null) { + // If there is no previous command or if the previous command was not a Q, q, T or t, + // assume the control point is coincident with the current point + controlX = x; + controlY = y; + } + else if (previous[0] === 't') { + // calculate reflection of previous control points for t + controlX = 2 * x - tempControlX; + controlY = 2 * y - tempControlY; + } + else if (previous[0] === 'q') { + // calculate reflection of previous control points for q + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + + tempControlX = controlX; + tempControlY = controlY; + + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + controlX = x + current[1]; + controlY = y + current[2]; + break; + + case 'T': + tempX = current[1]; + tempY = current[2]; + + // calculate reflection of previous control points + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'a': + // TODO: optimize this + drawArc(ctx, x + l, y + t, [ + current[1], + current[2], + current[3], + current[4], + current[5], + current[6] + x + l, + current[7] + y + t + ]); + x += current[6]; + y += current[7]; + break; + + case 'A': + // TODO: optimize this + drawArc(ctx, x + l, y + t, [ + current[1], + current[2], + current[3], + current[4], + current[5], + current[6] + l, + current[7] + t + ]); + x = current[6]; + y = current[7]; + break; + + case 'z': + case 'Z': + ctx.closePath(); + break; + } + previous = current; + } + }, + + /** + * Renders path on a specified context + * @param {CanvasRenderingContext2D} ctx context to render path on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if object is not visible + if (!this.visible) return; + + ctx.save(); + var m = this.transformMatrix; + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + if (!noTransform) { + this.transform(ctx); + } + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + ctx.beginPath(); + + this._render(ctx); + this._renderFill(ctx); + this._renderStroke(ctx); + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + + if (!noTransform && this.active) { + this.drawBorders(ctx); + this.drawControls(ctx); + } + ctx.restore(); + }, + + /** + * Returns string representation of an instance + * @return {String} string representation of an instance + */ + toString: function() { + return '#'; + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var o = extend(this.callSuper('toObject', propertiesToInclude), { + path: this.path, + pathOffset: this.pathOffset + }); + if (this.sourcePath) { + o.sourcePath = this.sourcePath; + } + if (this.transformMatrix) { + o.transformMatrix = this.transformMatrix; + } + return o; + }, + + /** + * Returns dataless object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + var o = this.toObject(propertiesToInclude); + if (this.sourcePath) { + o.path = this.sourcePath; + } + delete o.sourcePath; + return o; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var chunks = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.path.length; i < len; i++) { + chunks.push(this.path[i].join(' ')); + } + var path = chunks.join(' '); + + markup.push( + '', + '', + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns number representation of an instance complexity + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.path.length; + }, + + /** + * @private + */ + _parsePath: function() { + var result = [ ], + coords = [ ], + currentPath, + parsed, + re = /(-?\.\d+)|(-?\d+(\.\d+)?)/g, + match, + coordsStr; + + for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) { + currentPath = this.path[i]; + + coordsStr = currentPath.slice(1).trim(); + coords.length = 0; + + while ((match = re.exec(coordsStr))) { + coords.push(match[0]); + } + + coordsParsed = [ currentPath.charAt(0) ]; + + for (var j = 0, jlen = coords.length; j < jlen; j++) { + parsed = parseFloat(coords[j]); + if (!isNaN(parsed)) { + coordsParsed.push(parsed); + } + } + + var command = coordsParsed[0].toLowerCase(), + commandLength = commandLengths[command]; + + if (coordsParsed.length - 1 > commandLength) { + for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) { + result.push([ coordsParsed[0] ].concat(coordsParsed.slice(k, k + commandLength))); + } + } + else { + result.push(coordsParsed); + } + } + + return result; + }, + + /** + * @private + */ + _parseDimensions: function() { + var aX = [], + aY = [], + previous = { }; + + this.path.forEach(function(item, i) { + this._getCoordsFromCommand(item, i, aX, aY, previous); + }, this); + + var minX = min(aX), + minY = min(aY), + maxX = max(aX), + maxY = max(aY), + deltaX = maxX - minX, + deltaY = maxY - minY; + + var o = { + left: this.left + (minX + deltaX / 2), + top: this.top + (minY + deltaY / 2), + width: deltaX, + height: deltaY + }; + + return o; + }, + + _getCoordsFromCommand: function(item, i, aX, aY, previous) { + var isLowerCase = false; + + if (item[0] !== 'H') { + previous.x = (i === 0) ? getX(item) : getX(this.path[i - 1]); + } + if (item[0] !== 'V') { + previous.y = (i === 0) ? getY(item) : getY(this.path[i - 1]); + } + + // lowercased letter denotes relative position; + // transform to absolute + if (item[0] === item[0].toLowerCase()) { + isLowerCase = true; + } + + var xy = this._getXY(item, isLowerCase, previous); + + var val = parseInt(xy.x, 10); + if (!isNaN(val)) aX.push(val); + + val = parseInt(xy.y, 10); + if (!isNaN(val)) aY.push(val); + }, + + _getXY: function(item, isLowerCase, previous) { + + // last 2 items in an array of coordinates are the actualy x/y (except H/V), collect them + // TODO (kangax): support relative h/v commands + + var x = isLowerCase + ? previous.x + getX(item) + : item[0] === 'V' + ? previous.x + : getX(item); + + var y = isLowerCase + ? previous.y + getY(item) + : item[0] === 'H' + ? previous.y + : getY(item); + + return { x: x, y: y }; + } + }); + + /** + * Creates an instance of fabric.Path from an object + * @static + * @memberOf fabric.Path + * @param {Object} object + * @param {Function} callback Callback to invoke when an fabric.Path instance is created + */ + fabric.Path.fromObject = function(object, callback) { + if (typeof object.path === 'string') { + fabric.loadSVGFromURL(object.path, function (elements) { + var path = elements[0]; + + var pathUrl = object.path; + delete object.path; + + fabric.util.object.extend(path, object); + path.setSourcePath(pathUrl); + + callback(path); + }); + } + else { + callback(new fabric.Path(object.path, object)); + } + }; + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Path.fromElement`) + * @static + * @memberOf fabric.Path + * @see http://www.w3.org/TR/SVG/paths.html#PathElement + */ + fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(['d']); + + /** + * Creates an instance of fabric.Path from an SVG element + * @static + * @memberOf fabric.Path + * @param {SVGElement} element to parse + * @param {Function} callback Callback to invoke when an fabric.Path instance is created + * @param {Object} [options] Options object + */ + fabric.Path.fromElement = function(element, callback, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES); + callback && callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options))); + }; + /* _FROM_SVG_END_ */ + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.Path + * @type Boolean + * @default + */ + fabric.Path.async = true; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global) { + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + invoke = fabric.util.array.invoke, + parentToObject = fabric.Object.prototype.toObject; + + if (fabric.PathGroup) { + fabric.warn('fabric.PathGroup is already defined'); + return; + } + + /** + * Path group class + * @class fabric.PathGroup + * @extends fabric.Path + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup} + * @see {@link fabric.PathGroup#initialize} for constructor definition + */ + fabric.PathGroup = fabric.util.createClass(fabric.Path, /** @lends fabric.PathGroup.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'path-group', + + /** + * Fill value + * @type String + * @default + */ + fill: '', + + /** + * Constructor + * @param {Array} paths + * @param {Object} [options] Options object + * @return {fabric.PathGroup} thisArg + */ + initialize: function(paths, options) { + + options = options || { }; + this.paths = paths || [ ]; + + for (var i = this.paths.length; i--; ) { + this.paths[i].group = this; + } + + this.setOptions(options); + this.setCoords(); + + if (options.sourcePath) { + this.setSourcePath(options.sourcePath); + } + }, + + /** + * Renders this group on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render this instance on + */ + render: function(ctx) { + // do not render if object is not visible + if (!this.visible) return; + + ctx.save(); + + var m = this.transformMatrix; + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + + this.transform(ctx); + + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + for (var i = 0, l = this.paths.length; i < l; ++i) { + this.paths[i].render(ctx, true); + } + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + + if (this.active) { + this.drawBorders(ctx); + this.drawControls(ctx); + } + ctx.restore(); + }, + + /** + * Sets certain property to a certain value + * @param {String} prop + * @param {Any} value + * @return {fabric.PathGroup} thisArg + */ + _set: function(prop, value) { + + if (prop === 'fill' && value && this.isSameColor()) { + var i = this.paths.length; + while (i--) { + this.paths[i]._set(prop, value); + } + } + + return this.callSuper('_set', prop, value); + }, + + /** + * Returns object representation of this path group + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var o = extend(parentToObject.call(this, propertiesToInclude), { + paths: invoke(this.getObjects(), 'toObject', propertiesToInclude) + }); + if (this.sourcePath) { + o.sourcePath = this.sourcePath; + } + return o; + }, + + /** + * Returns dataless object representation of this path group + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} dataless object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + var o = this.toObject(propertiesToInclude); + if (this.sourcePath) { + o.paths = this.sourcePath; + } + return o; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var objects = this.getObjects(); + var markup = [ + '' + ]; + + for (var i = 0, len = objects.length; i < len; i++) { + markup.push(objects[i].toSVG(reviver)); + } + markup.push(''); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns a string representation of this path group + * @return {String} string representation of an object + */ + toString: function() { + return '#'; + }, + + /** + * Returns true if all paths in this group are of same color + * @return {Boolean} true if all paths are of the same color (`fill`) + */ + isSameColor: function() { + var firstPathFill = this.getObjects()[0].get('fill'); + return this.getObjects().every(function(path) { + return path.get('fill') === firstPathFill; + }); + }, + + /** + * Returns number representation of object's complexity + * @return {Number} complexity + */ + complexity: function() { + return this.paths.reduce(function(total, path) { + return total + ((path && path.complexity) ? path.complexity() : 0); + }, 0); + }, + + /** + * Returns all paths in this path group + * @return {Array} array of path objects included in this path group + */ + getObjects: function() { + return this.paths; + } + }); + + /** + * Creates fabric.PathGroup instance from an object representation + * @static + * @memberOf fabric.PathGroup + * @param {Object} object Object to create an instance from + * @param {Function} callback Callback to invoke when an fabric.PathGroup instance is created + */ + fabric.PathGroup.fromObject = function(object, callback) { + if (typeof object.paths === 'string') { + fabric.loadSVGFromURL(object.paths, function (elements) { + + var pathUrl = object.paths; + delete object.paths; + + var pathGroup = fabric.util.groupSVGElements(elements, object, pathUrl); + + callback(pathGroup); + }); + } + else { + fabric.util.enlivenObjects(object.paths, function(enlivenedObjects) { + delete object.paths; + callback(new fabric.PathGroup(enlivenedObjects, object)); + }); + } + }; + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.PathGroup + * @type Boolean + * @default + */ + fabric.PathGroup.async = true; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global){ + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + min = fabric.util.array.min, + max = fabric.util.array.max, + invoke = fabric.util.array.invoke; + + if (fabric.Group) { + return; + } + + // lock-related properties, for use in fabric.Group#get + // to enable locking behavior on group + // when one of its objects has lock-related properties set + var _lockProperties = { + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + lockUniScaling: true + }; + + /** + * Group class + * @class fabric.Group + * @extends fabric.Object + * @mixes fabric.Collection + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#groups} + * @see {@link fabric.Group#initialize} for constructor definition + */ + fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, /** @lends fabric.Group.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'group', + + /** + * Constructor + * @param {Object} objects Group objects + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(objects, options) { + options = options || { }; + + this._objects = objects || []; + for (var i = this._objects.length; i--; ) { + this._objects[i].group = this; + } + + this.originalState = { }; + this.callSuper('initialize'); + + this._calcBounds(); + this._updateObjectsCoords(); + + if (options) { + extend(this, options); + } + this._setOpacityIfSame(); + + this.setCoords(true); + this.saveCoords(); + }, + + /** + * @private + */ + _updateObjectsCoords: function() { + this.forEachObject(this._updateObjectCoords, this); + }, + + /** + * @private + */ + _updateObjectCoords: function(object) { + var objectLeft = object.getLeft(), + objectTop = object.getTop(); + + object.set({ + originalLeft: objectLeft, + originalTop: objectTop, + left: objectLeft - this.left, + top: objectTop - this.top + }); + + object.setCoords(); + + // do not display corners of objects enclosed in a group + object.__origHasControls = object.hasControls; + object.hasControls = false; + }, + + /** + * Returns string represenation of a group + * @return {String} + */ + toString: function() { + return '#'; + }, + + /** + * Adds an object to a group; Then recalculates group's dimension, position. + * @param {Object} object + * @return {fabric.Group} thisArg + * @chainable + */ + addWithUpdate: function(object) { + this._restoreObjectsState(); + this._objects.push(object); + object.group = this; + // since _restoreObjectsState set objects inactive + this.forEachObject(this._setObjectActive, this); + this._calcBounds(); + this._updateObjectsCoords(); + return this; + }, + + /** + * @private + */ + _setObjectActive: function(object) { + object.set('active', true); + object.group = this; + }, + + /** + * Removes an object from a group; Then recalculates group's dimension, position. + * @param {Object} object + * @return {fabric.Group} thisArg + * @chainable + */ + removeWithUpdate: function(object) { + this._moveFlippedObject(object); + this._restoreObjectsState(); + + // since _restoreObjectsState set objects inactive + this.forEachObject(this._setObjectActive, this); + + this.remove(object); + this._calcBounds(); + this._updateObjectsCoords(); + + return this; + }, + + /** + * @private + */ + _onObjectAdded: function(object) { + object.group = this; + }, + + /** + * @private + */ + _onObjectRemoved: function(object) { + delete object.group; + object.set('active', false); + }, + + /** + * Properties that are delegated to group objects when reading/writing + * @param {Object} delegatedProperties + */ + delegatedProperties: { + fill: true, + opacity: true, + fontFamily: true, + fontWeight: true, + fontSize: true, + fontStyle: true, + lineHeight: true, + textDecoration: true, + textAlign: true, + backgroundColor: true + }, + + /** + * @private + */ + _set: function(key, value) { + if (key in this.delegatedProperties) { + var i = this._objects.length; + this[key] = value; + while (i--) { + this._objects[i].set(key, value); + } + } + else { + this[key] = value; + } + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + objects: invoke(this._objects, 'toObject', propertiesToInclude) + }); + }, + + /** + * Renders instance on a given context + * @param {CanvasRenderingContext2D} ctx context to render instance on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if object is not visible + if (!this.visible) return; + + ctx.save(); + this.transform(ctx); + + this.clipTo && fabric.util.clipContext(this, ctx); + + // the array is now sorted in order of highest first, so start from end + for (var i = 0, len = this._objects.length; i < len; i++) { + this._renderObject(this._objects[i], ctx); + } + + this.clipTo && ctx.restore(); + + if (!noTransform && this.active) { + this.drawBorders(ctx); + this.drawControls(ctx); + } + ctx.restore(); + }, + + /** + * @private + */ + _renderObject: function(object, ctx) { + + var originalScaleFactor = object.borderScaleFactor, + originalHasRotatingPoint = object.hasRotatingPoint, + groupScaleFactor = Math.max(this.scaleX, this.scaleY); + + // do not render if object is not visible + if (!object.visible) return; + + object.borderScaleFactor = groupScaleFactor; + object.hasRotatingPoint = false; + + object.render(ctx); + + object.borderScaleFactor = originalScaleFactor; + object.hasRotatingPoint = originalHasRotatingPoint; + }, + + /** + * Retores original state of each of group objects (original state is that which was before group was created). + * @private + * @return {fabric.Group} thisArg + * @chainable + */ + _restoreObjectsState: function() { + this._objects.forEach(this._restoreObjectState, this); + return this; + }, + + /** + * Moves a flipped object to the position where it's displayed + * @private + * @param {fabric.Object} object + * @return {fabric.Group} thisArg + */ + _moveFlippedObject: function(object) { + var oldOriginX = object.get('originX'), + oldOriginY = object.get('originY'), + center = object.getCenterPoint(); + + object.set({ + originX: 'center', + originY: 'center', + left: center.x, + top: center.y + }); + + this._toggleFlipping(object); + + var newOrigin = object.getPointByOrigin(oldOriginX, oldOriginY); + + object.set({ + originX: oldOriginX, + originY: oldOriginY, + left: newOrigin.x, + top: newOrigin.y + }); + + return this; + }, + + /** + * @private + */ + _toggleFlipping: function(object) { + if (this.flipX) { + object.toggle('flipX'); + object.set('left', -object.get('left')); + object.setAngle(-object.getAngle()); + } + if (this.flipY) { + object.toggle('flipY'); + object.set('top', -object.get('top')); + object.setAngle(-object.getAngle()); + } + }, + + /** + * Restores original state of a specified object in group + * @private + * @param {fabric.Object} object + * @return {fabric.Group} thisArg + */ + _restoreObjectState: function(object) { + this._setObjectPosition(object); + + object.setCoords(); + object.hasControls = object.__origHasControls; + delete object.__origHasControls; + object.set('active', false); + object.setCoords(); + delete object.group; + + return this; + }, + + /** + * @private + */ + _setObjectPosition: function(object) { + var groupLeft = this.getLeft(), + groupTop = this.getTop(), + rotated = this._getRotatedLeftTop(object); + + object.set({ + angle: object.getAngle() + this.getAngle(), + left: groupLeft + rotated.left, + top: groupTop + rotated.top, + scaleX: object.get('scaleX') * this.get('scaleX'), + scaleY: object.get('scaleY') * this.get('scaleY') + }); + }, + + /** + * @private + */ + _getRotatedLeftTop: function(object) { + var groupAngle = this.getAngle() * (Math.PI / 180); + return { + left: (-Math.sin(groupAngle) * object.getTop() * this.get('scaleY') + + Math.cos(groupAngle) * object.getLeft() * this.get('scaleX')), + + top: (Math.cos(groupAngle) * object.getTop() * this.get('scaleY') + + Math.sin(groupAngle) * object.getLeft() * this.get('scaleX')) + }; + }, + + /** + * Destroys a group (restoring state of its objects) + * @return {fabric.Group} thisArg + * @chainable + */ + destroy: function() { + this._objects.forEach(this._moveFlippedObject, this); + return this._restoreObjectsState(); + }, + + /** + * Saves coordinates of this instance (to be used together with `hasMoved`) + * @saveCoords + * @return {fabric.Group} thisArg + * @chainable + */ + saveCoords: function() { + this._originalLeft = this.get('left'); + this._originalTop = this.get('top'); + return this; + }, + + /** + * Checks whether this group was moved (since `saveCoords` was called last) + * @return {Boolean} true if an object was moved (since fabric.Group#saveCoords was called) + */ + hasMoved: function() { + return this._originalLeft !== this.get('left') || + this._originalTop !== this.get('top'); + }, + + /** + * Sets coordinates of all group objects + * @return {fabric.Group} thisArg + * @chainable + */ + setObjectsCoords: function() { + this.forEachObject(function(object) { + object.setCoords(); + }); + return this; + }, + + /** + * @private + */ + _setOpacityIfSame: function() { + var objects = this.getObjects(), + firstValue = objects[0] ? objects[0].get('opacity') : 1; + + var isSameOpacity = objects.every(function(o) { + return o.get('opacity') === firstValue; + }); + + if (isSameOpacity) { + this.opacity = firstValue; + } + }, + + /** + * @private + */ + _calcBounds: function() { + var aX = [], + aY = [], + o; + + for (var i = 0, len = this._objects.length; i < len; ++i) { + o = this._objects[i]; + o.setCoords(); + for (var prop in o.oCoords) { + aX.push(o.oCoords[prop].x); + aY.push(o.oCoords[prop].y); + } + } + + this.set(this._getBounds(aX, aY)); + }, + + /** + * @private + */ + _getBounds: function(aX, aY) { + var minX = min(aX), + maxX = max(aX), + minY = min(aY), + maxY = max(aY), + width = (maxX - minX) || 0, + height = (maxY - minY) || 0; + + return { + width: width, + height: height, + left: (minX + width / 2) || 0, + top: (minY + height / 2) || 0 + }; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = [ + '' + ]; + + for (var i = 0, len = this._objects.length; i < len; i++) { + markup.push(this._objects[i].toSVG(reviver)); + } + + markup.push(''); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns requested property + * @param {String} prop Property to get + * @return {Any} + */ + get: function(prop) { + if (prop in _lockProperties) { + if (this[prop]) { + return this[prop]; + } + else { + for (var i = 0, len = this._objects.length; i < len; i++) { + if (this._objects[i][prop]) { + return true; + } + } + return false; + } + } + else { + if (prop in this.delegatedProperties) { + return this._objects[0] && this._objects[0].get(prop); + } + return this[prop]; + } + } + }); + + /** + * Returns {@link fabric.Group} instance from an object representation + * @static + * @memberOf fabric.Group + * @param {Object} object Object to create a group from + * @param {Object} [options] Options object + * @return {fabric.Group} An instance of fabric.Group + */ + fabric.Group.fromObject = function(object, callback) { + fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) { + delete object.objects; + callback && callback(new fabric.Group(enlivenedObjects, object)); + }); + }; + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.Group + * @type Boolean + * @default + */ + fabric.Group.async = true; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global) { + + "use strict"; + + var extend = fabric.util.object.extend; + + if (!global.fabric) { + global.fabric = { }; + } + + if (global.fabric.Image) { + fabric.warn('fabric.Image is already defined.'); + return; + } + + /** + * Image class + * @class fabric.Image + * @extends fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#images} + * @see {@link fabric.Image#initialize} for constructor definition + */ + fabric.Image = fabric.util.createClass(fabric.Object, /** @lends fabric.Image.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'image', + + /** + * crossOrigin value (one of "", "anonymous", "allow-credentials") + * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes + * @type String + * @default + */ + crossOrigin: '', + + /** + * Constructor + * @param {HTMLImageElement | String} element Image element + * @param {Object} [options] Options object + * @return {fabric.Image} thisArg + */ + initialize: function(element, options) { + options || (options = { }); + + this.filters = [ ]; + + this.callSuper('initialize', options); + + this._initElement(element, options); + this._initConfig(options); + + if (options.filters) { + this.filters = options.filters; + this.applyFilters(); + } + }, + + /** + * Returns image element which this instance if based on + * @return {HTMLImageElement} Image element + */ + getElement: function() { + return this._element; + }, + + /** + * Sets image element for this instance to a specified one. + * If filters defined they are applied to new image. + * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area. + * @param {HTMLImageElement} element + * @param {Function} [callback] Callback is invoked when all filters have been applied and new image is generated + * @return {fabric.Image} thisArg + * @chainable + */ + setElement: function(element, callback) { + this._element = element; + this._originalElement = element; + this._initConfig(); + + if (this.filters.length !== 0) { + this.applyFilters(callback); + } + + return this; + }, + + /** + * Sets crossOrigin value (on an instance and corresponding image element) + * @return {fabric.Image} thisArg + * @chainable + */ + setCrossOrigin: function(value) { + this.crossOrigin = value; + this._element.crossOrigin = value; + + return this; + }, + + /** + * Returns original size of an image + * @return {Object} Object with "width" and "height" properties + */ + getOriginalSize: function() { + var element = this.getElement(); + return { + width: element.width, + height: element.height + }; + }, + + /** + * Renders image on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if object is not visible + if (!this.visible) return; + + ctx.save(); + var m = this.transformMatrix; + var isInPathGroup = this.group && this.group.type === 'path-group'; + + // this._resetWidthHeight(); + if (isInPathGroup) { + ctx.translate(-this.group.width/2 + this.width/2, -this.group.height/2 + this.height/2); + } + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + if (!noTransform) { + this.transform(ctx); + } + + ctx.save(); + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + this._render(ctx); + if (this.shadow && !this.shadow.affectStroke) { + this._removeShadow(ctx); + } + this._renderStroke(ctx); + this.clipTo && ctx.restore(); + ctx.restore(); + + if (this.active && !noTransform) { + this.drawBorders(ctx); + this.drawControls(ctx); + } + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _stroke: function(ctx) { + ctx.save(); + this._setStrokeStyles(ctx); + ctx.beginPath(); + ctx.strokeRect(-this.width / 2, -this.height / 2, this.width, this.height); + ctx.closePath(); + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var x = -this.width/2, + y = -this.height/2, + w = this.width, + h = this.height; + + ctx.save(); + this._setStrokeStyles(ctx); + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, x+w, y, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x+w, y, x+w, y+h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x+w, y+h, x, y+h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x, y+h, x, y, this.strokeDashArray); + ctx.closePath(); + ctx.restore(); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + src: this._originalElement.src || this._originalElement._src, + filters: this.filters.map(function(filterObj) { + return filterObj && filterObj.toObject(); + }), + crossOrigin: this.crossOrigin + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = []; + + markup.push( + '', + '' + ); + + if (this.stroke || this.strokeDashArray) { + var origFill = this.fill; + this.fill = null; + markup.push( + '' + ); + this.fill = origFill; + } + + markup.push(''); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns source of an image + * @return {String} Source of an image + */ + getSrc: function() { + return this.getElement().src || this.getElement()._src; + }, + + /** + * Returns string representation of an instance + * @return {String} String representation of an instance + */ + toString: function() { + return '#'; + }, + + /** + * Returns a clone of an instance + * @param {Function} callback Callback is invoked with a clone as a first argument + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + */ + clone: function(callback, propertiesToInclude) { + this.constructor.fromObject(this.toObject(propertiesToInclude), callback); + }, + + /** + * Applies filters assigned to this image (from "filters" array) + * @mthod applyFilters + * @param {Function} callback Callback is invoked when all filters have been applied and new image is generated + * @return {fabric.Image} thisArg + * @chainable + */ + applyFilters: function(callback) { + + if (this.filters.length === 0) { + this._element = this._originalElement; + callback && callback(); + return; + } + + var imgEl = this._originalElement, + canvasEl = fabric.util.createCanvasElement(), + replacement = fabric.util.createImage(), + _this = this; + + canvasEl.width = imgEl.width; + canvasEl.height = imgEl.height; + + canvasEl.getContext('2d').drawImage(imgEl, 0, 0, imgEl.width, imgEl.height); + + this.filters.forEach(function(filter) { + filter && filter.applyTo(canvasEl); + }); + + /** @ignore */ + + replacement.width = imgEl.width; + replacement.height = imgEl.height; + + if (fabric.isLikelyNode) { + replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression); + + // onload doesn't fire in some node versions, so we invoke callback manually + _this._element = replacement; + callback && callback(); + } + else { + replacement.onload = function() { + _this._element = replacement; + callback && callback(); + replacement.onload = canvasEl = imgEl = null; + }; + replacement.src = canvasEl.toDataURL('image/png'); + } + + return this; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + ctx.drawImage( + this._element, + -this.width / 2, + -this.height / 2, + this.width, + this.height + ); + }, + + /** + * @private + */ + _resetWidthHeight: function() { + var element = this.getElement(); + + this.set('width', element.width); + this.set('height', element.height); + }, + + /** + * The Image class's initialization method. This method is automatically + * called by the constructor. + * @private + * @param {HTMLImageElement|String} element The element representing the image + */ + _initElement: function(element) { + this.setElement(fabric.util.getById(element)); + fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS); + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initConfig: function(options) { + options || (options = { }); + this.setOptions(options); + this._setWidthHeight(options); + this._element.crossOrigin = this.crossOrigin; + }, + + /** + * @private + * @param {Object} object Object with filters property + * @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created + */ + _initFilters: function(object, callback) { + if (object.filters && object.filters.length) { + fabric.util.enlivenObjects(object.filters, function(enlivenedObjects) { + callback && callback(enlivenedObjects); + }, 'fabric.Image.filters'); + } + else { + callback && callback(); + } + }, + + /** + * @private + * @param {Object} [options] Object with width/height properties + */ + _setWidthHeight: function(options) { + this.width = 'width' in options + ? options.width + : (this.getElement().width || 0); + + this.height = 'height' in options + ? options.height + : (this.getElement().height || 0); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /** + * Default CSS class name for canvas + * @static + * @type String + * @default + */ + fabric.Image.CSS_CANVAS = "canvas-img"; + + /** + * Alias for getSrc + * @static + */ + fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc; + + /** + * Creates an instance of fabric.Image from its object representation + * @static + * @param {Object} object Object to create an instance from + * @param {Function} [callback] Callback to invoke when an image instance is created + */ + fabric.Image.fromObject = function(object, callback) { + fabric.util.loadImage(object.src, function(img) { + fabric.Image.prototype._initFilters.call(object, object, function(filters) { + object.filters = filters || [ ]; + var instance = new fabric.Image(img, object); + callback && callback(instance); + }); + }, null, object.crossOrigin); + }; + + /** + * Creates an instance of fabric.Image from an URL string + * @static + * @param {String} url URL to create an image from + * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument) + * @param {Object} [imgOptions] Options object + */ + fabric.Image.fromURL = function(url, callback, imgOptions) { + fabric.util.loadImage(url, function(img) { + callback(new fabric.Image(img, imgOptions)); + }, null, imgOptions && imgOptions.crossOrigin); + }; + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement}) + * @static + * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement} + */ + fabric.Image.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y width height xlink:href'.split(' ')); + + /** + * Returns {@link fabric.Image} instance from an SVG element + * @static + * @param {SVGElement} element Element to parse + * @param {Function} callback Callback to execute when fabric.Image object is created + * @param {Object} [options] Options object + * @return {fabric.Image} Instance of fabric.Image + */ + fabric.Image.fromElement = function(element, callback, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES); + + fabric.Image.fromURL(parsedAttributes['xlink:href'], callback, + extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + }; + /* _FROM_SVG_END_ */ + + /** + * Indicates that instances of this type are async + * @static + * @type Boolean + * @default + */ + fabric.Image.async = true; + + /** + * Indicates compression level used when generating PNG under Node (in applyFilters). Any of 0-9 + * @static + * @type Number + * @default + */ + fabric.Image.pngCompression = 1; + +})(typeof exports !== 'undefined' ? exports : this); +(function(global) { + + "use strict"; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + clone = fabric.util.object.clone, + toFixed = fabric.util.toFixed, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Text) { + fabric.warn('fabric.Text is already defined'); + return; + } + + var stateProperties = fabric.Object.prototype.stateProperties.concat(); + stateProperties.push( + 'fontFamily', + 'fontWeight', + 'fontSize', + 'text', + 'textDecoration', + 'textAlign', + 'fontStyle', + 'lineHeight', + 'textBackgroundColor', + 'useNative', + 'path' + ); + + /** + * Text class + * @class fabric.Text + * @extends fabric.Object + * @return {fabric.Text} thisArg + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#text} + * @see {@link fabric.Text#initialize} for constructor definition + */ + fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ { + + /** + * Properties which when set cause object to change dimensions + * @type Object + * @private + */ + _dimensionAffectingProps: { + fontSize: true, + fontWeight: true, + fontFamily: true, + textDecoration: true, + fontStyle: true, + lineHeight: true, + stroke: true, + strokeWidth: true, + text: true + }, + + /** + * @private + */ + _reNewline: /\r?\n/, + + /** + * Retrieves object's fontSize + * @method getFontSize + * @memberOf fabric.Text.prototype + * @return {String} Font size (in pixels) + */ + + /** + * Sets object's fontSize + * @method setFontSize + * @memberOf fabric.Text.prototype + * @param {Number} fontSize Font size (in pixels) + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontWeight + * @method getFontWeight + * @memberOf fabric.Text.prototype + * @return {(String|Number)} Font weight + */ + + /** + * Sets object's fontWeight + * @method setFontWeight + * @memberOf fabric.Text.prototype + * @param {(Number|String)} fontWeight Font weight + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontFamily + * @method getFontFamily + * @memberOf fabric.Text.prototype + * @return {String} Font family + */ + + /** + * Sets object's fontFamily + * @method setFontFamily + * @memberOf fabric.Text.prototype + * @param {String} fontFamily Font family + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's text + * @method getText + * @memberOf fabric.Text.prototype + * @return {String} text + */ + + /** + * Sets object's text + * @method setText + * @memberOf fabric.Text.prototype + * @param {String} text Text + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textDecoration + * @method getTextDecoration + * @memberOf fabric.Text.prototype + * @return {String} Text decoration + */ + + /** + * Sets object's textDecoration + * @method setTextDecoration + * @memberOf fabric.Text.prototype + * @param {String} textDecoration Text decoration + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontStyle + * @method getFontStyle + * @memberOf fabric.Text.prototype + * @return {String} Font style + */ + + /** + * Sets object's fontStyle + * @method setFontStyle + * @memberOf fabric.Text.prototype + * @param {String} fontStyle Font style + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's lineHeight + * @method getLineHeight + * @memberOf fabric.Text.prototype + * @return {Number} Line height + */ + + /** + * Sets object's lineHeight + * @method setLineHeight + * @memberOf fabric.Text.prototype + * @param {Number} lineHeight Line height + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textAlign + * @method getTextAlign + * @memberOf fabric.Text.prototype + * @return {String} Text alignment + */ + + /** + * Sets object's textAlign + * @method setTextAlign + * @memberOf fabric.Text.prototype + * @param {String} textAlign Text alignment + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textBackgroundColor + * @method getTextBackgroundColor + * @memberOf fabric.Text.prototype + * @return {String} Text background color + */ + + /** + * Sets object's textBackgroundColor + * @method setTextBackgroundColor + * @memberOf fabric.Text.prototype + * @param {String} textBackgroundColor Text background color + * @return {fabric.Text} + * @chainable + */ + + /** + * Type of an object + * @type String + * @default + */ + type: 'text', + + /** + * Font size (in pixels) + * @type Number + * @default + */ + fontSize: 40, + + /** + * Font weight (e.g. bold, normal, 400, 600, 800) + * @type {(Number|String)} + * @default + */ + fontWeight: 'normal', + + /** + * Font family + * @type String + * @default + */ + fontFamily: 'Times New Roman', + + /** + * Text decoration Possible values: "", "underline", "overline" or "line-through". + * @type String + * @default + */ + textDecoration: '', + + /** + * Text alignment. Possible values: "left", "center", or "right". + * @type String + * @default + */ + textAlign: 'left', + + /** + * Font style . Possible values: "", "normal", "italic" or "oblique". + * @type String + * @default + */ + fontStyle: '', + + /** + * Line height + * @type Number + * @default + */ + lineHeight: 1.3, + + /** + * Background color of text lines + * @type String + * @default + */ + textBackgroundColor: '', + + /** + * URL of a font file, when using Cufon + * @type String | null + * @default + */ + path: null, + + /** + * Indicates whether canvas native text methods should be used to render text (otherwise, Cufon is used) + * @type Boolean + * @default + */ + useNative: true, + + /** + * List of properties to consider when checking if + * state of an object is changed ({@link fabric.Object#hasStateChanged}) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: stateProperties, + + /** + * When defined, an object is rendered via stroke and this property specifies its color. + * Backwards incompatibility note: This property was named "strokeStyle" until v1.1.6 + * @type String + * @default + */ + stroke: null, + + /** + * Shadow object representing shadow of this shape. + * Backwards incompatibility note: This property was named "textShadow" (String) until v1.2.11 + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Constructor + * @param {String} text Text string + * @param {Object} [options] Options object + * @return {fabric.Text} thisArg + */ + initialize: function(text, options) { + options = options || { }; + + this.text = text; + this.__skipDimension = true; + this.setOptions(options); + this.__skipDimension = false; + this._initDimensions(); + this.setCoords(); + }, + + /** + * Renders text object on offscreen canvas, so that it would get dimensions + * @private + */ + _initDimensions: function() { + if (this.__skipDimension) return; + var canvasEl = fabric.util.createCanvasElement(); + this._render(canvasEl.getContext('2d')); + }, + + /** + * Returns string representation of an instance + * @return {String} String representation of text object + */ + toString: function() { + return '#'; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + + var isInPathGroup = this.group && this.group.type === 'path-group'; + if (isInPathGroup && !this.transformMatrix) { + ctx.translate(-this.group.width/2 + this.left, -this.group.height / 2 + this.top); + } + else if (isInPathGroup && this.transformMatrix) { + ctx.translate(-this.group.width/2, -this.group.height/2); + } + + if (typeof Cufon === 'undefined' || this.useNative === true) { + this._renderViaNative(ctx); + } + else { + this._renderViaCufon(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderViaNative: function(ctx) { + var textLines = this.text.split(this._reNewline); + + this.transform(ctx, fabric.isLikelyNode); + + this._setTextStyles(ctx); + + this.width = this._getTextWidth(ctx, textLines); + this.height = this._getTextHeight(ctx, textLines); + + this.clipTo && fabric.util.clipContext(this, ctx); + + this._renderTextBackground(ctx, textLines); + this._translateForTextAlign(ctx); + this._renderText(ctx, textLines); + + if (this.textAlign !== 'left' && this.textAlign !== 'justify') { + ctx.restore(); + } + + this._renderTextDecoration(ctx, textLines); + this.clipTo && ctx.restore(); + + this._setBoundaries(ctx, textLines); + this._totalLineHeight = 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderText: function(ctx, textLines) { + ctx.save(); + this._setShadow(ctx); + this._renderTextFill(ctx, textLines); + this._renderTextStroke(ctx, textLines); + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _translateForTextAlign: function(ctx) { + if (this.textAlign !== 'left' && this.textAlign !== 'justify') { + ctx.save(); + ctx.translate(this.textAlign === 'center' ? (this.width / 2) : this.width, 0); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _setBoundaries: function(ctx, textLines) { + this._boundaries = [ ]; + + for (var i = 0, len = textLines.length; i < len; i++) { + + var lineWidth = this._getLineWidth(ctx, textLines[i]); + var lineLeftOffset = this._getLineLeftOffset(lineWidth); + + this._boundaries.push({ + height: this.fontSize * this.lineHeight, + width: lineWidth, + left: lineLeftOffset + }); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _setTextStyles: function(ctx) { + this._setFillStyles(ctx); + this._setStrokeStyles(ctx); + ctx.textBaseline = 'alphabetic'; + if (!this.skipTextAlign) { + ctx.textAlign = this.textAlign; + } + ctx.font = this._getFontDeclaration(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + * @return {Number} Height of fabric.Text object + */ + _getTextHeight: function(ctx, textLines) { + return this.fontSize * textLines.length * this.lineHeight; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + * @return {Number} Maximum width of fabric.Text object + */ + _getTextWidth: function(ctx, textLines) { + var maxWidth = ctx.measureText(textLines[0] || '|').width; + + for (var i = 1, len = textLines.length; i < len; i++) { + var currentLineWidth = ctx.measureText(textLines[i]).width; + if (currentLineWidth > maxWidth) { + maxWidth = currentLineWidth; + } + } + return maxWidth; + }, + + /** + * @private + * @param {String} method Method name ("fillText" or "strokeText") + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Chars to render + * @param {Number} left Left position of text + * @param {Number} top Top position of text + */ + _renderChars: function(method, ctx, chars, left, top) { + ctx[method](chars, left, top); + }, + + /** + * @private + * @param {String} method Method name ("fillText" or "strokeText") + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Text to render + * @param {Number} left Left position of text + * @param {Number} top Top position of text + * @param {Number} lineIndex Index of a line in a text + */ + _renderTextLine: function(method, ctx, line, left, top, lineIndex) { + // lift the line by quarter of fontSize + top -= this.fontSize / 4; + + // short-circuit + if (this.textAlign !== 'justify') { + this._renderChars(method, ctx, line, left, top, lineIndex); + return; + } + + var lineWidth = ctx.measureText(line).width; + var totalWidth = this.width; + + if (totalWidth > lineWidth) { + // stretch the line + var words = line.split(/\s+/); + var wordsWidth = ctx.measureText(line.replace(/\s+/g, '')).width; + var widthDiff = totalWidth - wordsWidth; + var numSpaces = words.length - 1; + var spaceWidth = widthDiff / numSpaces; + + var leftOffset = 0; + for (var i = 0, len = words.length; i < len; i++) { + this._renderChars(method, ctx, words[i], left + leftOffset, top, lineIndex); + leftOffset += ctx.measureText(words[i]).width + spaceWidth; + } + } + else { + this._renderChars(method, ctx, line, left, top, lineIndex); + } + }, + + /** + * @private + * @return {Number} Left offset + */ + _getLeftOffset: function() { + if (fabric.isLikelyNode) { + return 0; + } + return -this.width / 2; + }, + + /** + * @private + * @return {Number} Top offset + */ + _getTopOffset: function() { + return -this.height / 2; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextFill: function(ctx, textLines) { + if (!this.fill && !this._skipFillStrokeCheck) return; + + this._boundaries = [ ]; + var lineHeights = 0; + + for (var i = 0, len = textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i, textLines); + lineHeights += heightOfLine; + + this._renderTextLine( + 'fillText', + ctx, + textLines[i], + this._getLeftOffset(), + this._getTopOffset() + lineHeights, + i + ); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextStroke: function(ctx, textLines) { + if (!this.stroke && !this._skipFillStrokeCheck) return; + + var lineHeights = 0; + + ctx.save(); + if (this.strokeDashArray) { + // Spec requires the concatenation of two copies the dash list when the number of elements is odd + if (1 & this.strokeDashArray.length) { + this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); + } + supportsLineDash && ctx.setLineDash(this.strokeDashArray); + } + + ctx.beginPath(); + for (var i = 0, len = textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i, textLines); + lineHeights += heightOfLine; + + this._renderTextLine( + 'strokeText', + ctx, + textLines[i], + this._getLeftOffset(), + this._getTopOffset() + lineHeights, + i + ); + } + ctx.closePath(); + ctx.restore(); + }, + + _getHeightOfLine: function() { + return this.fontSize * this.lineHeight; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextBackground: function(ctx, textLines) { + this._renderTextBoxBackground(ctx); + this._renderTextLinesBackground(ctx, textLines); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderTextBoxBackground: function(ctx) { + if (!this.backgroundColor) return; + + ctx.save(); + ctx.fillStyle = this.backgroundColor; + + ctx.fillRect( + this._getLeftOffset(), + this._getTopOffset(), + this.width, + this.height + ); + + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextLinesBackground: function(ctx, textLines) { + if (!this.textBackgroundColor) return; + + ctx.save(); + ctx.fillStyle = this.textBackgroundColor; + + for (var i = 0, len = textLines.length; i < len; i++) { + + if (textLines[i] !== '') { + + var lineWidth = this._getLineWidth(ctx, textLines[i]); + var lineLeftOffset = this._getLineLeftOffset(lineWidth); + + ctx.fillRect( + this._getLeftOffset() + lineLeftOffset, + this._getTopOffset() + (i * this.fontSize * this.lineHeight), + lineWidth, + this.fontSize * this.lineHeight + ); + } + } + ctx.restore(); + }, + + /** + * @private + * @param {Number} lineWidth Width of text line + * @return {Number} Line left offset + */ + _getLineLeftOffset: function(lineWidth) { + if (this.textAlign === 'center') { + return (this.width - lineWidth) / 2; + } + if (this.textAlign === 'right') { + return this.width - lineWidth; + } + return 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Text line + * @return {Number} Line width + */ + _getLineWidth: function(ctx, line) { + return this.textAlign === 'justify' + ? this.width + : ctx.measureText(line).width; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextDecoration: function(ctx, textLines) { + if (!this.textDecoration) return; + + // var halfOfVerticalBox = this.originY === 'top' ? 0 : this._getTextHeight(ctx, textLines) / 2; + var halfOfVerticalBox = this._getTextHeight(ctx, textLines) / 2; + var _this = this; + + /** @ignore */ + function renderLinesAtOffset(offset) { + for (var i = 0, len = textLines.length; i < len; i++) { + + var lineWidth = _this._getLineWidth(ctx, textLines[i]); + var lineLeftOffset = _this._getLineLeftOffset(lineWidth); + + ctx.fillRect( + _this._getLeftOffset() + lineLeftOffset, + ~~((offset + (i * _this._getHeightOfLine(ctx, i, textLines))) - halfOfVerticalBox), + lineWidth, + 1); + } + } + + if (this.textDecoration.indexOf('underline') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight); + } + if (this.textDecoration.indexOf('line-through') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize / 2); + } + if (this.textDecoration.indexOf('overline') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize); + } + }, + + /** + * @private + */ + _getFontDeclaration: function() { + return [ + // node-canvas needs "weight style", while browsers need "style weight" + (fabric.isLikelyNode ? this.fontWeight : this.fontStyle), + (fabric.isLikelyNode ? this.fontStyle : this.fontWeight), + this.fontSize + 'px', + (fabric.isLikelyNode ? ('"' + this.fontFamily + '"') : this.fontFamily) + ].join(' '); + }, + + /** + * Renders text instance on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if object is not visible + if (!this.visible) return; + + ctx.save(); + this._render(ctx); + if (!noTransform && this.active) { + this.drawBorders(ctx); + this.drawControls(ctx); + } + ctx.restore(); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + var object = extend(this.callSuper('toObject', propertiesToInclude), { + text: this.text, + fontSize: this.fontSize, + fontWeight: this.fontWeight, + fontFamily: this.fontFamily, + fontStyle: this.fontStyle, + lineHeight: this.lineHeight, + textDecoration: this.textDecoration, + textAlign: this.textAlign, + path: this.path, + textBackgroundColor: this.textBackgroundColor, + useNative: this.useNative + }); + if (!this.includeDefaultValues) { + this._removeDefaultValues(object); + } + return object; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = [ ], + textLines = this.text.split(this._reNewline), + offsets = this._getSVGLeftTopOffsets(textLines), + textAndBg = this._getSVGTextAndBg(offsets.lineTop, offsets.textLeft, textLines), + shadowSpans = this._getSVGShadows(offsets.lineTop, textLines); + + // move top offset by an ascent + offsets.textTop += (this._fontAscent ? ((this._fontAscent / 5) * this.lineHeight) : 0); + + this._wrapSVGTextAndBg(markup, textAndBg, shadowSpans, offsets); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + + /** + * @private + */ + _getSVGLeftTopOffsets: function(textLines) { + var lineTop = this.useNative + ? this.fontSize * this.lineHeight + : (-this._fontAscent - ((this._fontAscent / 5) * this.lineHeight)), + + textLeft = -(this.width/2), + textTop = this.useNative + ? this.fontSize - 1 + : (this.height/2) - (textLines.length * this.fontSize) - this._totalLineHeight; + + return { + textLeft: textLeft, + textTop: textTop, + lineTop: lineTop + }; + }, + + /** + * @private + */ + _wrapSVGTextAndBg: function(markup, textAndBg, shadowSpans, offsets) { + markup.push( + '', + textAndBg.textBgRects.join(''), + '', + shadowSpans.join(''), + textAndBg.textSpans.join(''), + '', + '' + ); + }, + + /** + * @private + * @param {Number} lineHeight + * @param {Array} textLines Array of all text lines + * @return {Array} + */ + _getSVGShadows: function(lineHeight, textLines) { + var shadowSpans = [], + i, len, + lineTopOffsetMultiplier = 1; + + if (!this.shadow || !this._boundaries) { + return shadowSpans; + } + + for (i = 0, len = textLines.length; i < len; i++) { + if (textLines[i] !== '') { + var lineLeftOffset = (this._boundaries && this._boundaries[i]) ? this._boundaries[i].left : 0; + shadowSpans.push( + '', + fabric.util.string.escapeXml(textLines[i]), + ''); + lineTopOffsetMultiplier = 1; + } + else { + // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier + // prevents empty tspans + lineTopOffsetMultiplier++; + } + } + + return shadowSpans; + }, + + /** + * @private + * @param {Number} lineHeight + * @param {Number} textLeftOffset Text left offset + * @param {Array} textLines Array of all text lines + * @return {Object} + */ + _getSVGTextAndBg: function(lineHeight, textLeftOffset, textLines) { + var textSpans = [ ], + textBgRects = [ ], + lineTopOffsetMultiplier = 1; + + // bounding-box background + this._setSVGBg(textBgRects); + + // text and text-background + for (var i = 0, len = textLines.length; i < len; i++) { + if (textLines[i] !== '') { + this._setSVGTextLineText(textLines[i], i, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects); + lineTopOffsetMultiplier = 1; + } + else { + // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier + // prevents empty tspans + lineTopOffsetMultiplier++; + } + + if (!this.textBackgroundColor || !this._boundaries) continue; + + this._setSVGTextLineBg(textBgRects, i, textLeftOffset, lineHeight); + } + + return { + textSpans: textSpans, + textBgRects: textBgRects + }; + }, + + _setSVGTextLineText: function(textLine, i, textSpans, lineHeight, lineTopOffsetMultiplier) { + var lineLeftOffset = (this._boundaries && this._boundaries[i]) + ? toFixed(this._boundaries[i].left, 2) + : 0; + + textSpans.push( + ' elements since setting opacity + // on containing one doesn't work in Illustrator + this._getFillAttributes(this.fill), '>', + fabric.util.string.escapeXml(textLine), + '' + ); + }, + + _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, lineHeight) { + textBgRects.push( + ''); + }, + + _setSVGBg: function(textBgRects) { + if (this.backgroundColor && this._boundaries) { + textBgRects.push( + ''); + } + }, + + /** + * Adobe Illustrator (at least CS5) is unable to render rgba()-based fill values + * we work around it by "moving" alpha channel into opacity attribute and setting fill's alpha to 1 + * + * @private + * @param {Any} value + * @return {String} + */ + _getFillAttributes: function(value) { + var fillColor = (value && typeof value === 'string') ? new fabric.Color(value) : ''; + if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) { + return 'fill="' + value + '"'; + } + return 'opacity="' + fillColor.getAlpha() + '" fill="' + fillColor.setAlpha(1).toRgb() + '"'; + }, + /* _TO_SVG_END_ */ + + /** + * Sets specified property to a specified value + * @param {String} key + * @param {Any} value + * @return {fabric.Text} thisArg + * @chainable + */ + _set: function(key, value) { + if (key === 'fontFamily' && this.path) { + this.path = this.path.replace(/(.*?)([^\/]*)(\.font\.js)/, '$1' + value + '$3'); + } + this.callSuper('_set', key, value); + + if (key in this._dimensionAffectingProps) { + this._initDimensions(); + this.setCoords(); + } + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement}) + * @static + * @memberOf fabric.Text + * @see: http://www.w3.org/TR/SVG/text.html#TextElement + */ + fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat( + 'x y font-family font-style font-weight font-size text-decoration'.split(' ')); + + /** + * Returns fabric.Text instance from an SVG element (not yet implemented) + * @static + * @memberOf fabric.Text + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Text} Instance of fabric.Text + */ + fabric.Text.fromElement = function(element, options) { + if (!element) { + return null; + } + + var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES); + options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes); + + var text = new fabric.Text(element.textContent, options); + + /* + Adjust positioning: + x/y attributes in SVG correspond to the bottom-left corner of text bounding box + top/left properties in Fabric correspond to center point of text bounding box + */ + + text.set({ + left: text.getLeft() + text.getWidth() / 2, + top: text.getTop() - text.getHeight() / 2 + }); + + return text; + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Text instance from an object representation + * @static + * @memberOf fabric.Text + * @param object {Object} object Object to create an instance from + * @return {fabric.Text} Instance of fabric.Text + */ + fabric.Text.fromObject = function(object) { + return new fabric.Text(object.text, clone(object)); + }; + + fabric.util.createAccessors(fabric.Text); + +})(typeof exports !== 'undefined' ? exports : this); diff --git a/js/fabric-v1.4.0.min.js b/js/fabric-v1.4.0.min.js new file mode 100644 index 00000000..6fdc8b4b --- /dev/null +++ b/js/fabric-v1.4.0.min.js @@ -0,0 +1,2 @@ +/* build: `node build.js modules=text,gestures,parser,freedrawing,interaction,serialization,pattern minifier=uglifyjs` */ +var fabric=fabric||{version:"1.4.0"};typeof exports!="undefined"&&(exports.fabric=fabric),typeof document!="undefined"&&typeof window!="undefined"?(fabric.document=document,fabric.window=window):(fabric.document=require("jsdom").jsdom(""),fabric.window=fabric.document.createWindow()),fabric.isTouchSupported="ontouchstart"in fabric.document.documentElement,fabric.isLikelyNode=typeof Buffer!="undefined"&&typeof window=="undefined",fabric.SHARED_ATTRIBUTES=["transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width"];var Cufon=function(){function r(e){var t=this.face=e.face;this.glyphs=e.glyphs,this.w=e.w,this.baseSize=parseInt(t["units-per-em"],10),this.family=t["font-family"].toLowerCase(),this.weight=t["font-weight"],this.style=t["font-style"]||"normal",this.viewBox=function(){var e=t.bbox.split(/\s+/),n={minX:parseInt(e[0],10),minY:parseInt(e[1],10),maxX:parseInt(e[2],10),maxY:parseInt(e[3],10)};return n.width=n.maxX-n.minX,n.height=n.maxY-n.minY,n.toString=function(){return[this.minX,this.minY,this.width,this.height].join(" ")},n}(),this.ascent=-parseInt(t.ascent,10),this.descent=-parseInt(t.descent,10),this.height=-this.ascent+this.descent}function i(){var e={},t={oblique:"italic",italic:"oblique"};this.add=function(t){(e[t.style]||(e[t.style]={}))[t.weight]=t},this.get=function(n,r){var i=e[n]||e[t[n]]||e.normal||e.italic||e.oblique;if(!i)return null;r={normal:400,bold:700}[r]||parseInt(r,10);if(i[r])return i[r];var s={1:1,99:0}[r%100],o=[],u,a;s===undefined&&(s=r>400),r==500&&(r=400);for(var f in i){f=parseInt(f,10);if(!u||fa)a=f;o.push(f)}return ra&&(r=a),o.sort(function(e,t){return(s?e>r&&t>r?et:et:e=i.length+e?r():setTimeout(arguments.callee,10)}),function(t){e?t():n.push(t)}}(),supports:function(e,t){var n=fabric.document.createElement("span").style;return n[e]===undefined?!1:(n[e]=t,n[e]===t)},textAlign:function(e,t,n,r){return t.get("textAlign")=="right"?n>0&&(e=" "+e):nk&&(k=N),A.push(N),N=0;continue}var O=t.glyphs[T[b]]||t.missingGlyph;if(!O)continue;N+=C=Number(O.w||t.w)+h}A.push(N),N=Math.max(k,N);var M=[];for(var b=A.length;b--;)M[b]=N-A[b];if(C===null)return null;d+=l.width-C,m+=l.minX;var _,D;if(f)_=u,D=u.firstChild;else{_=fabric.document.createElement("span"),_.className="cufon cufon-canvas",_.alt=n,D=fabric.document.createElement("canvas"),_.appendChild(D);if(i.printable){var P=fabric.document.createElement("span");P.className="cufon-alt",P.appendChild(fabric.document.createTextNode(n)),_.appendChild(P)}}var H=_.style,B=D.style||{},j=c.convert(l.height-p+v),F=Math.ceil(j),I=F/j;D.width=Math.ceil(c.convert(N+d-m)*I),D.height=F,p+=l.minY,B.top=Math.round(c.convert(p-t.ascent))+"px",B.left=Math.round(c.convert(m))+"px";var q=Math.ceil(c.convert(N*I)),R=q+"px",U=c.convert(t.height),z=(i.lineHeight-1)*c.convert(-t.ascent/5)*(L-1);Cufon.textOptions.width=q,Cufon.textOptions.height=U*L+z,Cufon.textOptions.lines=L,Cufon.textOptions.totalLineHeight=z,e?(H.width=R,H.height=U+"px"):(H.paddingLeft=R,H.paddingBottom=U-1+"px");var W=Cufon.textOptions.context||D.getContext("2d"),X=F/l.height;Cufon.textOptions.fontAscent=t.ascent*X,Cufon.textOptions.boundaries=null;for(var V=Cufon.textOptions.shadowOffsets,b=y.length;b--;)V[b]=[y[b][0]*X,y[b][1]*X];W.save(),W.scale(X,X),W.translate(-m-1/X*D.width/2+(Cufon.fonts[t.family].offsetLeft||0),-p-Cufon.textOptions.height/X/2+(Cufon.fonts[t.family].offsetTop||0)),W.lineWidth=t.face["underline-thickness"],W.save();var J=Cufon.getTextDecoration(i),K=i.fontStyle==="italic";W.save(),Q();if(g)for(var b=0,w=g.length;b.cufon-vml-canvas{text-indent:0}@media screen{cvml\\:shape,cvml\\:shadow{behavior:url(#default#VML);display:block;antialias:true;position:absolute}.cufon-vml-canvas{position:absolute;text-align:left}.cufon-vml{display:inline-block;position:relative;vertical-align:middle}.cufon-vml .cufon-alt{position:absolute;left:-10000in;font-size:1px}a .cufon-vml{cursor:pointer}}@media print{.cufon-vml *{display:none}.cufon-vml .cufon-alt{display:inline}}'),function(e,t,i,s,o,u,a){var f=t===null;f&&(t=o.alt);var l=e.viewBox,c=i.computedFontSize||(i.computedFontSize=new Cufon.CSS.Size(n(u,i.get("fontSize"))+"px",e.baseSize)),h=i.computedLSpacing;h==undefined&&(h=i.get("letterSpacing"),i.computedLSpacing=h=h=="normal"?0:~~c.convertFrom(r(u,h)));var p,d;if(f)p=o,d=o.firstChild;else{p=fabric.document.createElement("span"),p.className="cufon cufon-vml",p.alt=t,d=fabric.document.createElement("span"),d.className="cufon-vml-canvas",p.appendChild(d);if(s.printable){var v=fabric.document.createElement("span");v.className="cufon-alt",v.appendChild(fabric.document.createTextNode(t)),p.appendChild(v)}a||p.appendChild(fabric.document.createElement("cvml:shape"))}var m=p.style,g=d.style,y=c.convert(l.height),b=Math.ceil(y),w=b/y,E=l.minX,S=l.minY;g.height=b,g.top=Math.round(c.convert(S-e.ascent)),g.left=Math.round(c.convert(E)),m.height=c.convert(e.height)+"px";var x=Cufon.getTextDecoration(s),T=i.get("color"),N=Cufon.CSS.textTransform(t,i).split(""),C=0,k=0,L=null,A,O,M=s.textShadow;for(var _=0,D=0,P=N.length;_b&&window.clearInterval(E),document.querySelector(s)&&(window.clearInterval(E),setTimeout(u,1))},w);return}if(typeof s=="string"){s=document.querySelectorAll(s);if(s.length===0)return i("Missing target on listener!",arguments);s.length===1&&(s=s[0])}var S,x={};if(s.length>0&&s!==window){for(var T=0,N=s.length;T=r.maxFingers){var p=[];for(var h in r.tracker)p.push(h);return n.identifier=p.join(","),o}var d=0;for(var v in u){if(u[v].up){delete u[v],s(c,h),r.cancel=!0;break}d++}if(u[h])continue;s(c,h)}else u=r.tracker={},n.bbox=r.bbox=e.getBoundingBox(r.target),r.fingers=0,r.cancel=!1,s(c,h)}var p=[];for(var h in r.tracker)p.push(h);return n.identifier=p.join(","),o},e.pointerEnd=function(e,t,n,r){var i=e.touches||[],s=i.length,o={};for(var u=0;u1)return;var s=n.changedTouches||e.getCoords(n),o=s[0],u=t.bbox,a=e.getBoundingBox(t.target);if(t.position==="relative")var f=o.pageX+u.scrollLeft-u.x1,l=o.pageY+u.scrollTop-u.y1;else var f=o.pageX-u.x1,l=o.pageY-u.y1;if(f>0&&f0&&l0&&l0&&c1)){a.state=t.gesture;for(var u in t.tracker)break;var f=t.tracker[u];a.x=f.start.x,a.y=f.start.y,t.listener(o,a)}clearTimeout(s),r=i=0}};var a=e.pointerSetup(t);return a.state="dblclick",Event.add(t.target,"mousedown",t.onPointerDown),a},Event.Gesture=Event.Gesture||{},Event.Gesture._gestureHandlers=Event.Gesture._gestureHandlers||{},Event.Gesture._gestureHandlers.dbltap=e.dbltap,Event.Gesture._gestureHandlers.dblclick=e.dblclick,e}(Event.proxy);if(typeof Event=="undefined")var Event={};typeof Event.proxy=="undefined"&&(Event.proxy={}),Event.proxy=function(e){"use strict";return e.dragElement=function(t,n){e.drag({event:n,target:t,position:"move",listener:function(e,n){t.style.left=n.x+"px",t.style.top=n.y+"px",Event.prevent(e)}})},e.drag=function(t){t.gesture="drag",t.onPointerDown=function(r){e.pointerStart(r,n,t)&&(t.monitor||(Event.add(t.doc,"mousemove",t.onPointerMove),Event.add(t.doc,"mouseup",t.onPointerUp))),t.onPointerMove(r,"down")},t.onPointerMove=function(r,i){if(!t.tracker)return t.onPointerDown(r);var s=t.bbox,o=r.changedTouches||e.getCoords(r),u=o.length;for(var a=0;a0?x:-x,typeof c.DEG2!="undefined"&&(x>0?c.rotation+=c.DEG1-c.DEG2:c.rotation-=c.DEG1-c.DEG2,v+=c.rotation),a.push(c.move)}r.touches=a,r.fingers=n.fingers,r.scale=d/n.fingers,r.rotation=v/n.fingers,r.state="change",n.listener(i,r)},n.onPointerUp=function(t){var i=n.fingers;e.pointerEnd(t,r,n)&&(Event.remove(n.doc,"mousemove",n.onPointerMove),Event.remove(n.doc,"mouseup",n.onPointerUp)),i===n.minFingers&&n.fingersn){var w=p*g/b,E=Math.abs(w+y.value);y.value&&E=b&&s>n.threshold&&(f.x/=h,f.y/=h,r.start=f,r.x=l/h,r.y=c/h,r.angle=-(((u/n.snap+.5>>0)*n.snap||360)-360),r.velocity=s,r.fingers=b,r.state="swipe",n.listener(i,r))}};var r=e.pointerSetup(n);return Event.add(n.target,"mousedown",n.onPointerDown),r},Event.Gesture=Event.Gesture||{},Event.Gesture._gestureHandlers=Event.Gesture._gestureHandlers||{},Event.Gesture._gestureHandlers.swipe=e.swipe,e}(Event.proxy);if(typeof Event=="undefined")var Event={};typeof Event.proxy=="undefined"&&(Event.proxy={}),Event.proxy=function(e){"use strict";return e.longpress=function(t){return t.gesture="longpress",e.tap(t)},e.tap=function(t){t.delay=t.delay||500,t.timeout=t.timeout||250,t.driftDeviance=t.driftDeviance||10,t.gesture=t.gesture||"tap";var n,r;t.onPointerDown=function(s){if(e.pointerStart(s,i,t)){n=(new Date).getTime(),Event.add(t.doc,"mousemove",t.onPointerMove).listener(s),Event.add(t.doc,"mouseup",t.onPointerUp);if(t.gesture!=="longpress")return;r=setTimeout(function(){if(s.cancelBubble&&++s.bubble>1)return;var e=0;for(var n in t.tracker){var r=t.tracker[n];if(r.end===!0)return;if(t.cancel)return;e++}t.minFingers<=e&&t.maxFingers>=e&&(i.state="start",i.fingers=e,i.x=r.start.x,i.y=r.start.y,t.listener(s,i))},t.delay)}},t.onPointerMove=function(n){var r=t.bbox,i=n.changedTouches||e.getCoords(n),s=i.length;for(var o=0;o0&&l0&&c1)return;if(t.gesture==="longpress"){i.state==="start"&&(i.state="end",t.listener(s,i));return}if(t.cancel)return;if((new Date).getTime()-n>t.timeout)return;var o=t.gestureFingers;t.minFingers<=o&&t.maxFingers>=o&&(i.state="tap",i.fingers=t.gestureFingers,t.listener(s,i))}};var i=e.pointerSetup(t);return Event.add(t.target,"mousedown",t.onPointerDown),i},Event.Gesture=Event.Gesture||{},Event.Gesture._gestureHandlers=Event.Gesture._gestureHandlers||{},Event.Gesture._gestureHandlers.tap=e.tap,Event.Gesture._gestureHandlers.longpress=e.longpress,e}(Event.proxy);if(typeof Event=="undefined")var Event={};typeof Event.proxy=="undefined"&&(Event.proxy={}),Event.proxy=function(e){"use strict";return e.wheel=function(e){var t,n=e.timeout||150,r=0,i={gesture:"wheel",state:"start",wheelDelta:0,target:e.target,listener:e.listener,preventElasticBounce:function(){var e=this.target,t=e.scrollTop,n=t+e.offsetHeight,r=e.scrollHeight;n===r&&this.wheelDelta<=0?Event.cancel(event):t===0&&this.wheelDelta>=0&&Event.cancel(event),Event.stop(event)},add:function(){e.target[o](a,s,!1)},remove:function(){e.target[u](a,s,!1)}},s=function(s){s=s||window.event,i.state=r++?"change":"start",i.wheelDelta=s.detail?s.detail*-20:s.wheelDelta,e.listener(s,i),clearTimeout(t),t=setTimeout(function(){r=0,i.state="end",i.wheelDelta=0,e.listener(s,i)},n)},o=document.addEventListener?"addEventListener":"attachEvent",u=document.removeEventListener?"removeEventListener":"detachEvent",a=Event.getEventSupport("mousewheel")?"mousewheel":"DOMMouseScroll";return e.target[o](a,s,!1),i},Event.Gesture=Event.Gesture||{},Event.Gesture._gestureHandlers=Event.Gesture._gestureHandlers||{},Event.Gesture._gestureHandlers.wheel=e.wheel,e}(Event.proxy);if(typeof Event=="undefined")var Event={};typeof Event.proxy=="undefined"&&(Event.proxy={}),Event.proxy=function(e){"use strict";return e.orientation=function(e){var t={gesture:"orientationchange",previous:null,current:window.orientation,target:e.target,listener:e.listener,remove:function(){window.removeEventListener("orientationchange",n,!1)}},n=function(n){t.previous=t.current,t.current=window.orientation;if(t.previous!==null&&t.previous!=t.current){e.listener(n,t);return}};return window.DeviceOrientationEvent&&window.addEventListener("orientationchange",n,!1),t},Event.Gesture=Event.Gesture||{},Event.Gesture._gestureHandlers=Event.Gesture._gestureHandlers||{},Event.Gesture._gestureHandlers.orientation=e.orientation,e}(Event.proxy);(function(){function e(e,t){if(!this.__eventListeners[e])return;t?fabric.util.removeFromArray(this.__eventListeners[e],t):this.__eventListeners[e].length=0}function t(e,t){this.__eventListeners||(this.__eventListeners={});if(arguments.length===1)for(var n in e)this.on(n,e[n]);else this.__eventListeners[e]||(this.__eventListeners[e]=[]),this.__eventListeners[e].push(t);return this}function n(t,n){if(!this.__eventListeners)return;if(arguments.length===0)this.__eventListeners={};else if(arguments.length===1&&typeof arguments[0]=="object")for(var r in t)e.call(this,r,t[r]);else e.call(this,t,n);return this}function r(e,t){if(!this.__eventListeners)return;var n=this.__eventListeners[e];if(!n)return;for(var r=0,i=n.length;r-1},complexity:function(){return this.getObjects().reduce(function(e,t){return e+=t.complexity?t.complexity():0,e},0)}};(function(e){var t=Math.sqrt,n=Math.atan2,r=Math.PI/180;fabric.util={removeFromArray:function(e,t){var n=e.indexOf(t);return n!==-1&&e.splice(n,1),e},getRandomInt:function(e,t){return Math.floor(Math.random()*(t-e+1))+e},degreesToRadians:function(e){return e*r},radiansToDegrees:function(e){return e/r},rotatePoint:function(e,t,n){var r=Math.sin(n),i=Math.cos(n);e.subtractEquals(t);var s=e.x*i-e.y*r,o=e.x*r+e.y*i;return(new fabric.Point(s,o)).addEquals(t)},toFixed:function(e,t){return parseFloat(Number(e).toFixed(t))},falseFunction:function(){return!1},getKlass:function(e,t){return e=fabric.util.string.camelize(e.charAt(0).toUpperCase()+e.slice(1)),fabric.util.resolveNamespace(t)[e]},resolveNamespace:function(t){if(!t)return fabric;var n=t.split("."),r=n.length,i=e||fabric.window;for(var s=0;s1?r=new fabric.PathGroup(e,t):r=e[0],typeof n!="undefined"&&r.setSourcePath(n),r},populateWithProperties:function(e,t,n){if(n&&Object.prototype.toString.call(n)==="[object Array]")for(var r=0,i=n.length;rr)r+=u[p++%h],r>l&&(r=l),e[d?"lineTo":"moveTo"](r,0),d=!d;e.restore()},createCanvasElement:function(e){return e||(e=fabric.document.createElement("canvas")),!e.getContext&&typeof G_vmlCanvasManager!="undefined"&&G_vmlCanvasManager.initElement(e),e},createImage:function(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")},createAccessors:function(e){var t=e.prototype;for(var n=t.stateProperties.length;n--;){var r=t.stateProperties[n],i=r.charAt(0).toUpperCase()+r.slice(1),s="set"+i,o="get"+i;t[o]||(t[o]=function(e){return new Function('return this.get("'+e+'")')}(r)),t[s]||(t[s]=function(e){return new Function("value",'return this.set("'+e+'", value)')}(r))}},clipContext:function(e,t){t.save(),t.beginPath(),e.clipTo(t),t.clip()},multiplyTransformMatrices:function(e,t){var n=[[e[0],e[2],e[4]],[e[1],e[3],e[5]],[0,0,1]],r=[[t[0],t[2],t[4]],[t[1],t[3],t[5]],[0,0,1]],i=[];for(var s=0;s<3;s++){i[s]=[];for(var o=0;o<3;o++){var u=0;for(var a=0;a<3;a++)u+=n[s][a]*r[a][o];i[s][o]=u}}return[i[0][0],i[1][0],i[0][1],i[1][1],i[0][2],i[1][2]]},getFunctionBody:function(e){return(String(e).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},normalizePoints:function(e,t){var n=fabric.util.array.min(e,"x"),r=fabric.util.array.min(e,"y");n=n<0?n:0,r=n<0?r:0;for(var i=0,s=e.length;i0&&(t>r?t-=r:t=0,n>r?n-=r:n=0);var i=!0,s=e.getImageData(t,n,r*2||1,r*2||1);for(var o=3,u=s.data.length;o0&&f===0&&(E-=2*Math.PI);var S=Math.ceil(Math.abs(E/(Math.PI*.5+.001))),x=[];for(var T=0;T1&&(h=Math.sqrt(h),t*=h,n*=h);var p=f/t,d=a/t,v=-a/n,m=f/n;return{x0:p*r+d*i,y0:v*r+m*i,x1:p*s+d*o,y1:v*s+m*o,sin_th:a,cos_th:f}}function o(e,i,s,o,u,a,f,l){r=n.call(arguments);if(t[r])return t[r];var c=l*u,h=-f*a,p=f*u,d=l*a,v=.5*(o-s),m=8/3*Math.sin(v*.5)*Math.sin(v*.5)/Math.sin(v),g=e+Math.cos(s)-m*Math.sin(s),y=i+Math.sin(s)+m*Math.cos(s),b=e+Math.cos(o),w=i+Math.sin(o),E=b+m*Math.sin(o),S=w-m*Math.cos(o);return t[r]=[c*g+h*y,p*g+d*y,c*E+h*S,p*E+d*S,c*b+h*w,p*b+d*w],t[r]}var e={},t={},n=Array.prototype.join,r;fabric.util.drawArc=function(e,t,n,r){var s=r[0],u=r[1],a=r[2],f=r[3],l=r[4],c=r[5],h=r[6],p=i(c,h,s,u,f,l,a,t,n);for(var d=0;d=t})}function r(e,t){return i(e,t,function(e,t){return e>>0;if(n===0)return-1;var r=0;arguments.length>0&&(r=Number(arguments[1]),r!==r?r=0:r!==0&&r!==Number.POSITIVE_INFINITY&&r!==Number.NEGATIVE_INFINITY&&(r=(r>0||-1)*Math.floor(Math.abs(r))));if(r>=n)return-1;var i=r>=0?r:Math.max(n-Math.abs(r),0);for(;i>>0;n>>0;r>>0;n>>0;n>>0;i>>0,n=0,r;if(arguments.length>1)r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n/g,">")}String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^[\s\xA0]+/,"").replace(/[\s\xA0]+$/,"")}),fabric.util.string={camelize:e,capitalize:t,escapeXml:n}})();(function(){var e=Array.prototype.slice,t=Function.prototype.apply,n=function(){};Function.prototype.bind||(Function.prototype.bind=function(r){var i=this,s=e.call(arguments,1),o;return s.length?o=function(){return t.call(i,this instanceof n?this:r,s.concat(e.call(arguments)))}:o=function(){return t.call(i,this instanceof n?this:r,arguments)},n.prototype=this.prototype,o.prototype=new n,o})})();(function(){function i(){}function s(t){var n=this.constructor.superclass.prototype[t];return arguments.length>1?n.apply(this,e.call(arguments,1)):n.call(this)}function o(){function u(){this.initialize.apply(this,arguments)}var n=null,o=e.call(arguments,0);typeof o[0]=="function"&&(n=o.shift()),u.superclass=n,u.subclasses=[],n&&(i.prototype=n.prototype,u.prototype=new i,n.subclasses.push(u));for(var a=0,f=o.length;a-1?e.prototype[i]=function(e){return function(){var n=this.constructor.superclass;this.constructor.superclass=r;var i=t[e].apply(this,arguments);this.constructor.superclass=n;if(e!=="initialize")return i}}(i):e.prototype[i]=t[i],n&&(t.toString!==Object.prototype.toString&&(e.prototype.toString=t.toString),t.valueOf!==Object.prototype.valueOf&&(e.prototype.valueOf=t.valueOf))};fabric.util.createClass=o})();(function(){function t(e){var t=Array.prototype.slice.call(arguments,1),n,r,i=t.length;for(r=0;r-1?s(e,t.match(/opacity:\s*(\d?\.?\d*)/)[1]):e;for(var r in t)if(r==="opacity")s(e,t[r]);else{var i=r==="float"||r==="cssFloat"?typeof n.styleFloat=="undefined"?"cssFloat":"styleFloat":r;n[i]=t[r]}return e}var t=fabric.document.createElement("div"),n=typeof t.style.opacity=="string",r=typeof t.style.filter=="string",i=/alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,s=function(e){return e};n?s=function(e,t){return e.style.opacity=t,e}:r&&(s=function(e,t){var n=e.style;return e.currentStyle&&!e.currentStyle.hasLayout&&(n.zoom=1),i.test(n.filter)?(t=t>=.9999?"":"alpha(opacity="+t*100+")",n.filter=n.filter.replace(i,t)):n.filter+=" alpha(opacity="+t*100+")",e}),fabric.util.setStyle=e})();(function(){function t(e){return typeof e=="string"?fabric.document.getElementById(e):e}function s(e,t){var n=fabric.document.createElement(e);for(var r in t)r==="class"?n.className=t[r]:r==="for"?n.htmlFor=t[r]:n.setAttribute(r,t[r]);return n}function o(e,t){(" "+e.className+" ").indexOf(" "+t+" ")===-1&&(e.className+=(e.className?" ":"")+t)}function u(e,t,n){return typeof t=="string"&&(t=s(t,n)),e.parentNode&&e.parentNode.replaceChild(t,e),t.appendChild(e),t}function a(e,t){var n,r,i=0,s=0,o=fabric.document.documentElement,u=fabric.document.body||{scrollLeft:0,scrollTop:0};r=e;while(e&&e.parentNode&&!n)e=e.parentNode,e!==fabric.document&&fabric.util.getElementStyle(e,"position")==="fixed"&&(n=e),e!==fabric.document&&r!==t&&fabric.util.getElementStyle(e,"position")==="absolute"?(i=0,s=0):e===fabric.document?(i=u.scrollLeft||o.scrollLeft||0,s=u.scrollTop||o.scrollTop||0):(i+=e.scrollLeft||0,s+=e.scrollTop||0);return{left:i,top:s}}function f(e){var t,n={left:0,top:0},r=e&&e.ownerDocument,i={left:0,top:0},s,o={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!r)return{left:0,top:0};for(var u in o)i[o[u]]+=parseInt(l(e,u),10)||0;return t=r.documentElement,typeof e.getBoundingClientRect!="undefined"&&(n=e.getBoundingClientRect()),s=fabric.util.getScrollLeftTop(e,null),{left:n.left+s.left-(t.clientLeft||0)+i.left,top:n.top+s.top-(t.clientTop||0)+i.top}}function l(e,t){e.style||(e.style={});if(fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle)return fabric.document.defaultView.getComputedStyle(e,null)[t];var n=e.style[t];return!n&&e.currentStyle&&(n=e.currentStyle[t]),n}var e=Array.prototype.slice,n=function(t){return e.call(t,0)},r;try{r=n(fabric.document.childNodes)instanceof Array}catch(i){}r||(n=function(e){var t=new Array(e.length),n=e.length;while(n--)t[n]=e[n];return t}),function(){function n(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=fabric.util.falseFunction),t?e.style[t]="none":typeof e.unselectable=="string"&&(e.unselectable="on"),e}function r(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=null),t?e.style[t]="":typeof e.unselectable=="string"&&(e.unselectable=""),e}var e=fabric.document.documentElement.style,t="userSelect"in e?"userSelect":"MozUserSelect"in e?"MozUserSelect":"WebkitUserSelect"in e?"WebkitUserSelect":"KhtmlUserSelect"in e?"KhtmlUserSelect":"";fabric.util.makeElementUnselectable=n,fabric.util.makeElementSelectable=r}(),function(){function e(e,t){var n=fabric.document.getElementsByTagName("head")[0],r=fabric.document.createElement("script"),i=!0;r.onload=r.onreadystatechange=function(e){if(i){if(typeof this.readyState=="string"&&this.readyState!=="loaded"&&this.readyState!=="complete")return;i=!1,t(e||fabric.window.event),r=r.onload=r.onreadystatechange=null}},r.src=e,n.appendChild(r)}fabric.util.getScript=e}(),fabric.util.getById=t,fabric.util.toArray=n,fabric.util.makeElement=s,fabric.util.addClass=o,fabric.util.wrapElement=u,fabric.util.getScrollLeftTop=a,fabric.util.getElementOffset=f,fabric.util.getElementStyle=l})();(function(){function e(e,t){return e+(/\?/.test(e)?"&":"?")+t}function n(){}function r(r,i){i||(i={});var s=i.method?i.method.toUpperCase():"GET",o=i.onComplete||function(){},u=t(),a;return u.onreadystatechange=function(){u.readyState===4&&(o(u),u.onreadystatechange=n)},s==="GET"&&(a=null,typeof i.parameters=="string"&&(r=e(r,i.parameters))),u.open(s,r,!0),(s==="POST"||s==="PUT")&&u.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),u.send(a),u}var t=function(){var e=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0")},function(){return new XMLHttpRequest}];for(var t=e.length;t--;)try{var n=e[t]();if(n)return e[t]}catch(r){}}();fabric.util.request=r})();fabric.log=function(){},fabric.warn=function(){},typeof console!="undefined"&&["log","warn"].forEach(function(e){typeof console[e]!="undefined"&&console[e].apply&&(fabric[e]=function(){return console[e].apply(console,arguments)})});(function(e){"use strict";function f(e){return e in u?u[e]:e}function l(e,n,r){var i;e!=="fill"&&e!=="stroke"||n!=="none"?e==="fillRule"?n=n==="evenodd"?"destination-over":n:e==="strokeDashArray"?n=n.replace(/,/g," ").split(/\s+/):e==="transformMatrix"&&(r&&r.transformMatrix?n=o(r.transformMatrix,t.parseTransformAttribute(n)):n=t.parseTransformAttribute(n)):n="",i=Object.prototype.toString.call(n)==="[object Array]";var s=i?n.map(parseFloat):parseFloat(n);return!i&&isNaN(s)?n:s}function c(e){for(var n in a){if(!e[n]||typeof e[a[n]]=="undefined")continue;if(e[n].indexOf("url(")===0)continue;var r=new t.Color(e[n]);e[n]=r.setAlpha(s(r.getAlpha()*e[a[n]],2)).toRgba(),delete e[a[n]]}return e}function h(e,t){var n=e.match(/(normal|italic)?\s*(normal|small-caps)?\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\s*(\d+)px(?:\/(normal|[\d\.]+))?\s+(.*)/);if(!n)return;var r=n[1],i=n[3],s=n[4],o=n[5],u=n[6];r&&(t.fontStyle=r),i&&(t.fontSize=isNaN(parseFloat(i))?i:parseFloat(i)),s&&(t.fontSize=parseFloat(s)),u&&(t.fontFamily=u),o&&(t.lineHeight=o==="normal"?1:o)}function p(e,t){var n,r;e.replace(/;$/,"").split(";").forEach(function(e){var i=e.split(":");n=f(i[0].trim().toLowerCase()),r=l(n,i[1].trim()),n==="font"?h(r,t):t[n]=r})}function d(e,t){var n,r;for(var i in e){if(typeof e[i]=="undefined")continue;n=f(i.toLowerCase()),r=l(n,e[i]),n==="font"?h(r,t):t[n]=r}}function v(e){var n=e.nodeName,r=e.getAttribute("class"),i=e.getAttribute("id"),s={};for(var o in t.cssRules){var u=r&&(new RegExp("^\\."+r)).test(o)||i&&(new RegExp("^#"+i)).test(o)||(new RegExp("^"+n)).test(o);if(u)for(var a in t.cssRules[o])s[a]=t.cssRules[o][a]}return s}function g(e){var n=e.objects,i=e.options;return n=n.map(function(e){return t[r(e.type)].fromObject(e)}),{objects:n,options:i}}function y(e,t,n){t[n]&&t[n].toSVG&&e.push('','')}var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.string.capitalize,i=t.util.object.clone,s=t.util.toFixed,o=t.util.multiplyTransformMatrices,u={"fill-opacity":"fillOpacity","fill-rule":"fillRule","font-family":"fontFamily","font-size":"fontSize","font-style":"fontStyle","font-weight":"fontWeight",cx:"left",x:"left",r:"radius","stroke-dasharray":"strokeDashArray","stroke-linecap":"strokeLineCap","stroke-linejoin":"strokeLineJoin","stroke-miterlimit":"strokeMiterLimit","stroke-opacity":"strokeOpacity","stroke-width":"strokeWidth","text-decoration":"textDecoration",cy:"top",y:"top",transform:"transformMatrix"},a={stroke:"strokeOpacity",fill:"fillOpacity"};t.parseTransformAttribute=function(){function e(e,t){var n=t[0];e[0]=Math.cos(n),e[1]=Math.sin(n),e[2]=-Math.sin(n),e[3]=Math.cos(n)}function n(e,t){var n=t[0],r=t.length===2?t[1]:t[0];e[0]=n,e[3]=r}function r(e,t){e[2]=t[0]}function i(e,t){e[1]=t[0]}function s(e,t){e[4]=t[0],t.length===2&&(e[5]=t[1])}var o=[1,0,0,1,0,0],u="(?:[-+]?\\d+(?:\\.\\d+)?(?:e[-+]?\\d+)?)",a="(?:\\s+,?\\s*|,\\s*)",f="(?:(skewX)\\s*\\(\\s*("+u+")\\s*\\))",l="(?:(skewY)\\s*\\(\\s*("+u+")\\s*\\))",c="(?:(rotate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+")"+a+"("+u+"))?\\s*\\))",h="(?:(scale)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",p="(?:(translate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",d="(?:(matrix)\\s*\\(\\s*("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+"\\s*\\))",v="(?:"+d+"|"+p+"|"+h+"|"+c+"|"+f+"|"+l+")",m="(?:"+v+"(?:"+a+v+")*"+")",g="^\\s*(?:"+m+"?)\\s*$",y=new RegExp(g),b=new RegExp(v,"g");return function(u){var a=o.concat(),f=[];if(!u||u&&!y.test(u))return a;u.replace(b,function(t){var u=(new RegExp(v)).exec(t).filter(function(e){return e!==""&&e!=null}),l=u[1],c=u.slice(2).map(parseFloat);switch(l){case"translate":s(a,c);break;case"rotate":e(a,c);break;case"scale":n(a,c);break;case"skewX":r(a,c);break;case"skewY":i(a,c);break;case"matrix":a=c}f.push(a.concat()),a=o.concat()});var l=f[0];while(f.length>1)f.shift(),l=t.util.multiplyTransformMatrices(l,f[0]);return l}}(),t.parseSVGDocument=function(){function s(e,t){while(e&&(e=e.parentNode))if(t.test(e.nodeName))return!0;return!1}var e=/^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/,n="(?:[-+]?\\d+(?:\\.\\d+)?(?:e[-+]?\\d+)?)",r=new RegExp("^\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*"+"$");return function(n,o,u){if(!n)return;var a=new Date,f=t.util.toArray(n.getElementsByTagName("*"));if(f.length===0){f=n.selectNodes("//*[name(.)!='svg']");var l=[];for(var c=0,h=f.length;c-1;e=e.split(/\s+/);var n=[],r,i;if(t){r=0,i=e.length;for(;r/i,"")));if(!s.documentElement)return;t.parseSVGDocument(s.documentElement,function(r,i){m.set(e,{objects:t.util.array.invoke(r,"toObject"),options:i}),n(r,i)},r)}e=e.replace(/^\n\s*/,"").trim(),m.has(e,function(r){r?m.get(e,function(e){var t=g(e);n(t.objects,t.options)}):new t.util.request(e,{method:"get",onComplete:i})})},loadSVGFromString:function(e,n,r){e=e.trim();var i;if(typeof DOMParser!="undefined"){var s=new DOMParser;s&&s.parseFromString&&(i=s.parseFromString(e,"text/xml"))}else t.window.ActiveXObject&&(i=new ActiveXObject("Microsoft.XMLDOM"),i.async="false",i.loadXML(e.replace(//i,"")));t.parseSVGDocument(i.documentElement,function(e,t){n(e,t)},r)},createSVGFontFacesMarkup:function(e){var t="";for(var n=0,r=e.length;n',"",""].join("")),t},createSVGRefElementsMarkup:function(e){var t=[];return y(t,e,"backgroundColor"),y(t,e,"overlayColor"),t.join("")}})})(typeof exports!="undefined"?exports:this);fabric.ElementsParser={parse:function(e,t,n,r){this.elements=e,this.callback=t,this.options=n,this.reviver=r,this.instances=new Array(e.length),this.numElements=e.length,this.createObjects()},createObjects:function(){for(var e=0,t=this.elements.length;ee.x&&this.y>e.y},gte:function(e){return this.x>=e.x&&this.y>=e.y},lerp:function(e,t){return new n(this.x+(e.x-this.x)*t,this.y+(e.y-this.y)*t)},distanceFrom:function(e){var t=this.x-e.x,n=this.y-e.y;return Math.sqrt(t*t+n*n)},midPointFrom:function(e){return new n(this.x+(e.x-this.x)/2,this.y+(e.y-this.y)/2)},min:function(e){return new n(Math.min(this.x,e.x),Math.min(this.y,e.y))},max:function(e){return new n(Math.max(this.x,e.x),Math.max(this.y,e.y))},toString:function(){return this.x+","+this.y},setXY:function(e,t){this.x=e,this.y=t},setFromPoint:function(e){this.x=e.x,this.y=e.y},swap:function(e){var t=this.x,n=this.y;this.x=e.x,this.y=e.y,e.x=t,e.y=n}}})(typeof exports!="undefined"?exports:this);(function(e){"use strict";function n(e){this.status=e,this.points=[]}var t=e.fabric||(e.fabric={});if(t.Intersection){t.warn("fabric.Intersection is already defined");return}t.Intersection=n,t.Intersection.prototype={appendPoint:function(e){this.points.push(e)},appendPoints:function(e){this.points=this.points.concat(e)}},t.Intersection.intersectLineLine=function(e,r,i,s){var o,u=(s.x-i.x)*(e.y-i.y)-(s.y-i.y)*(e.x-i.x),a=(r.x-e.x)*(e.y-i.y)-(r.y-e.y)*(e.x-i.x),f=(s.y-i.y)*(r.x-e.x)-(s.x-i.x)*(r.y-e.y);if(f!==0){var l=u/f,c=a/f;0<=l&&l<=1&&0<=c&&c<=1?(o=new n("Intersection"),o.points.push(new t.Point(e.x+l*(r.x-e.x),e.y+l*(r.y-e.y)))):o=new n}else u===0||a===0?o=new n("Coincident"):o=new n("Parallel");return o},t.Intersection.intersectLinePolygon=function(e,t,r){var i=new n,s=r.length;for(var o=0;o0&&(i.status="Intersection"),i},t.Intersection.intersectPolygonPolygon=function(e,t){var r=new n,i=e.length;for(var s=0;s0&&(r.status="Intersection"),r},t.Intersection.intersectPolygonRectangle=function(e,r,i){var s=r.min(i),o=r.max(i),u=new t.Point(o.x,s.y),a=new t.Point(s.x,o.y),f=n.intersectLinePolygon(s,u,e),l=n.intersectLinePolygon(u,o,e),c=n.intersectLinePolygon(o,a,e),h=n.intersectLinePolygon(a,s,e),p=new n;return p.appendPoints(f.points),p.appendPoints(l.points),p.appendPoints(c.points),p.appendPoints(h.points),p.points.length>0&&(p.status="Intersection"),p}})(typeof exports!="undefined"?exports:this);(function(e){"use strict";function n(e){e?this._tryParsingColor(e):this.setSource([0,0,0,1])}function r(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*6*n:n<.5?t:n<2/3?e+(t-e)*(2/3-n)*6:e}var t=e.fabric||(e.fabric={});if(t.Color){t.warn("fabric.Color is already defined.");return}t.Color=n,t.Color.prototype={_tryParsingColor:function(e){var t;e in n.colorNameMap&&(e=n.colorNameMap[e]),t=n.sourceFromHex(e),t||(t=n.sourceFromRgb(e)),t||(t=n.sourceFromHsl(e)),t&&this.setSource(t)},_rgbToHsl:function(e,n,r){e/=255,n/=255,r/=255;var i,s,o,u=t.util.array.max([e,n,r]),a=t.util.array.min([e,n,r]);o=(u+a)/2;if(u===a)i=s=0;else{var f=u-a;s=o>.5?f/(2-u-a):f/(u+a);switch(u){case e:i=(n-r)/f+(n'+''+""},toLive:function(e){var t=typeof this.source=="function"?this.source():this.source;if(typeof t.src!="undefined"){if(!t.complete)return"";if(t.naturalWidth===0||t.naturalHeight===0)return""}return e.createPattern(t,this.repeat)}});(function(){"use strict";if(fabric.StaticCanvas){fabric.warn("fabric.StaticCanvas is already defined.");return}var e=fabric.util.object.extend,t=fabric.util.getElementOffset,n=fabric.util.removeFromArray,r=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass({initialize:function(e,t){t||(t={}),this._initStatic(e,t),fabric.StaticCanvas.activeInstance=this},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:!0,stateful:!0,renderOnAddRemove:!0,clipTo:null,controlsAboveOverlay:!1,allowTouchScrolling:!1,onBeforeScaleRotate:function(){},_initStatic:function(e,t){this._objects=[],this._createLowerCanvas(e),this._initOptions(t),t.overlayImage&&this.setOverlayImage(t.overlayImage,this.renderAll.bind(this)),t.backgroundImage&&this.setBackgroundImage(t.backgroundImage,this.renderAll.bind(this)),t.backgroundColor&&this.setBackgroundColor(t.backgroundColor,this.renderAll.bind(this)),t.overlayColor&&this.setOverlayColor(t.overlayColor,this.renderAll.bind(this)),this.calcOffset()},calcOffset:function(){return this._offset=t(this.lowerCanvasEl),this},setOverlayImage:function(e,t,n){return this.__setBgOverlayImage("overlayImage",e,t,n)},setBackgroundImage:function(e,t,n){return this.__setBgOverlayImage("backgroundImage",e,t,n)},setOverlayColor:function(e,t){return this.__setBgOverlayColor("overlayColor",e,t)},setBackgroundColor:function(e,t){return this.__setBgOverlayColor("backgroundColor",e,t)},__setBgOverlayImage:function(e,t,n,r){return typeof t=="string"?fabric.util.loadImage(t,function(t){this[e]=new fabric.Image(t,r),n&&n()},this):(this[e]=t,n&&n()),this},__setBgOverlayColor:function(e,t,n){if(t.source){var r=this;fabric.util.loadImage(t.source,function(i){r[e]=new fabric.Pattern({source:i,repeat:t.repeat,offsetX:t.offsetX,offsetY:t.offsetY}),n&&n()})}else this[e]=t,n&&n();return this},_createCanvasElement:function(){var e=fabric.document.createElement("canvas");e.style||(e.style={});if(!e)throw r;return this._initCanvasElement(e),e},_initCanvasElement:function(e){fabric.util.createCanvasElement(e);if(typeof e.getContext=="undefined")throw r},_initOptions:function(e){for(var t in e)this[t]=e[t];this.width=parseInt(this.lowerCanvasEl.width,10)||0,this.height=parseInt(this.lowerCanvasEl.height,10)||0;if(!this.lowerCanvasEl.style)return;this.lowerCanvasEl.style.width=this.width+"px",this.lowerCanvasEl.style.height=this.height+"px"},_createLowerCanvas:function(e){this.lowerCanvasEl=fabric.util.getById(e)||this._createCanvasElement(),this._initCanvasElement(this.lowerCanvasEl),fabric.util.addClass(this.lowerCanvasEl,"lower-canvas"),this.interactive&&this._applyCanvasStyle(this.lowerCanvasEl),this.contextContainer=this.lowerCanvasEl.getContext("2d")},getWidth:function(){return this.width},getHeight:function(){return this.height},setWidth:function(e){return this._setDimension("width",e)},setHeight:function(e){return this._setDimension("height",e)},setDimensions:function(e){for(var t in e)this._setDimension(t,e[t]);return this},_setDimension:function(e,t){return this.lowerCanvasEl[e]=t,this.lowerCanvasEl.style[e]=t+"px",this.upperCanvasEl&&(this.upperCanvasEl[e]=t,this.upperCanvasEl.style[e]=t+"px"),this.cacheCanvasEl&&(this.cacheCanvasEl[e]=t),this.wrapperEl&&(this.wrapperEl.style[e]=t+"px"),this[e]=t,this.calcOffset(),this.renderAll(),this},getElement:function(){return this.lowerCanvasEl},getActiveObject:function(){return null},getActiveGroup:function(){return null},_draw:function(e,t){if(!t)return;if(this.controlsAboveOverlay){var n=t.hasBorders,r=t.hasControls;t.hasBorders=t.hasControls=!1,t.render(e),t.hasBorders=n,t.hasControls=r}else t.render(e)},_onObjectAdded:function(e){this.stateful&&e.setupState(),e.setCoords(),e.canvas=this,this.fire("object:added",{target:e}),e.fire("added")},_onObjectRemoved:function(e){this.getActiveObject()===e&&(this.fire("before:selection:cleared",{target:e}),this._discardActiveObject(),this.fire("selection:cleared")),this.fire("object:removed",{target:e}),e.fire("removed")},clearContext:function(e){return e.clearRect(0,0,this.width,this.height),this},getContext:function(){return this.contextContainer},clear:function(){return this._objects.length=0,this.discardActiveGroup&&this.discardActiveGroup(),this.discardActiveObject&&this.discardActiveObject(),this.clearContext(this.contextContainer),this.contextTop&&this.clearContext(this.contextTop),this.fire("canvas:cleared"),this.renderAll(),this},renderAll:function(e){var t=this[e===!0&&this.interactive?"contextTop":"contextContainer"],n=this.getActiveGroup();return this.contextTop&&this.selection&&!this._groupSelector&&this.clearContext(this.contextTop),e||this.clearContext(t),this.fire("before:render"),this.clipTo&&fabric.util.clipContext(this,t),this._renderBackground(t),this._renderObjects(t,n),this._renderActiveGroup(t,n),this.clipTo&&t.restore(),this._renderOverlay(t),this.controlsAboveOverlay&&this.interactive&&this.drawControls(t),this.fire("after:render"),this},_renderObjects:function(e,t){for(var n=0,r=this._objects.length;n"),n.join("")},_setSVGPreamble:function(e,t){t.suppressPreamble||e.push('','\n')},_setSVGHeader:function(e,t){e.push("',"Created with Fabric.js ",fabric.version,"","",fabric.createSVGFontFacesMarkup(this.getObjects()),fabric.createSVGRefElementsMarkup(this),"")},_setSVGObjects:function(e,t){var n=this.getActiveGroup();n&&this.discardActiveGroup();for(var r=0,i=this.getObjects(),s=i.length;r"):this[t]&&t==="overlayColor"&&e.push('")},sendToBack:function(e){return n(this._objects,e),this._objects.unshift(e),this.renderAll&&this.renderAll()},bringToFront:function(e){return n(this._objects,e),this._objects.push(e),this.renderAll&&this.renderAll()},sendBackwards:function(e,t){var r=this._objects.indexOf(e);if(r!==0){var i=this._findNewLowerIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewLowerIndex:function(e,t,n){var r;if(n){r=t;for(var i=t-1;i>=0;--i){var s=e.intersectsWithObject(this._objects[i])||e.isContainedWithinObject(this._objects[i])||this._objects[i].isContainedWithinObject(e);if(s){r=i;break}}}else r=t-1;return r},bringForward:function(e,t){var r=this._objects.indexOf(e);if(r!==this._objects.length-1){var i=this._findNewUpperIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewUpperIndex:function(e,t,n){var r;if(n){r=t;for(var i=t+1;i"}}),e(fabric.StaticCanvas.prototype,fabric.Observable),e(fabric.StaticCanvas.prototype,fabric.Collection),e(fabric.StaticCanvas.prototype,fabric.DataURLExporter),e(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(e){var t=fabric.util.createCanvasElement();if(!t||!t.getContext)return null;var n=t.getContext("2d");if(!n)return null;switch(e){case"getImageData":return typeof n.getImageData!="undefined";case"setLineDash":return typeof n.setLineDash!="undefined";case"toDataURL":return typeof t.toDataURL!="undefined";case"toDataURLWithQuality":try{return t.toDataURL("image/jpeg",0),!0}catch(r){}return!1;default:return null}}}),fabric.StaticCanvas.prototype.toJSON=fabric.StaticCanvas.prototype.toObject})();fabric.BaseBrush=fabric.util.createClass({color:"rgb(0, 0, 0)",width:1,shadow:null,strokeLineCap:"round",strokeLineJoin:"round",setShadow:function(e){return this.shadow=new fabric.Shadow(e),this},_setBrushStyles:function(){var e=this.canvas.contextTop;e.strokeStyle=this.color,e.lineWidth=this.width,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin},_setShadow:function(){if(!this.shadow)return;var e=this.canvas.contextTop;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_resetShadow:function(){var e=this.canvas.contextTop;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0}});(function(){var e=fabric.util.array.min,t=fabric.util.array.max;fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(e){this.canvas=e,this._points=[]},onMouseDown:function(e){this._prepareForDrawing(e),this._captureDrawingPath(e),this._render()},onMouseMove:function(e){this._captureDrawingPath(e),this.canvas.clearContext(this.canvas.contextTop),this._render()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(e){var t=new fabric.Point(e.x,e.y);this._reset(),this._addPoint(t),this.canvas.contextTop.moveTo(t.x,t.y)},_addPoint:function(e){this._points.push(e)},_reset:function(){this._points.length=0,this._setBrushStyles(),this._setShadow()},_captureDrawingPath:function(e){var t=new fabric.Point(e.x,e.y);this._addPoint(t)},_render:function(){var e=this.canvas.contextTop;e.beginPath();var t=this._points[0],n=this._points[1];this._points.length===2&&t.x===n.x&&t.y===n.y&&(t.x-=.5,n.x+=.5),e.moveTo(t.x,t.y);for(var r=1,i=this._points.length;rn.padding?e.x<0?e.x+=n.padding:e.x-=n.padding:e.x=0,i(e.y)>n.padding?e.y<0?e.y+=n.padding:e.y-=n.padding:e.y=0},_rotateObject:function(e,t){var i=this._currentTransform,s=this._offset;if(i.target.get("lockRotation"))return;var o=r(i.ey-i.top-s.top,i.ex-i.left-s.left),u=r(t-i.top-s.top,e-i.left-s.left),a=n(u-o+i.theta);a<0&&(a=360+a),i.target.angle=a},_setCursor:function(e){this.upperCanvasEl.style.cursor=e},_resetObjectTransform:function(e){e.scaleX=1,e.scaleY=1,e.setAngle(0)},_drawSelection:function(){var e=this.contextTop,t=this._groupSelector,n=t.left,r=t.top,o=i(n),u=i(r);e.fillStyle=this.selectionColor,e.fillRect(t.ex-(n>0?0:-n),t.ey-(r>0?0:-r),o,u),e.lineWidth=this.selectionLineWidth,e.strokeStyle=this.selectionBorderColor;if(this.selectionDashArray.length>1){var a=t.ex+s-(n>0?0:o),f=t.ey+s-(r>0?0:u);e.beginPath(),fabric.util.drawDashedLine(e,a,f,a+o,f,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f+u-1,a+o,f+u-1,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f,a,f+u,this.selectionDashArray),fabric.util.drawDashedLine(e,a+o-1,f,a+o-1,f+u,this.selectionDashArray),e.closePath(),e.stroke()}else e.strokeRect(t.ex+s-(n>0?0:o),t.ey+s-(r>0?0:u),o,u)},_isLastRenderedObject:function(e){return this.controlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay.visible&&this.containsPoint(e,this.lastRenderedObjectWithControlsAboveOverlay)&&this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(e,this._offset)},findTarget:function(e,t){if(this.skipTargetFind)return;if(this._isLastRenderedObject(e))return this.lastRenderedObjectWithControlsAboveOverlay;var n=this.getActiveGroup();return n&&!t&&this.containsPoint(e,n)?n:this._searchPossibleTargets(e)},_searchPossibleTargets:function(e){var t=[],n,r=this.getPointer(e);for(var i=this._objects.length;i--;)if(this._objects[i]&&this._objects[i].visible&&this._objects[i].evented&&this.containsPoint(e,this._objects[i])){if(!this.perPixelTargetFind&&!this._objects[i].perPixelTargetFind){n=this._objects[i],this.relatedTarget=n;break}t[t.length]=this._objects[i]}for(var s=0,o=t.length;s1&&(t=new fabric.Group(t.reverse(),{originX:"center",originY:"center"}),this.setActiveGroup(t,e),t.saveCoords(),this.fire("selection:created",{target:t}),this.renderAll())},_collectObjects:function(){var n=[],r,i=this._groupSelector.ex,s=this._groupSelector.ey,o=i+this._groupSelector.left,u=s+this._groupSelector.top,a=new fabric.Point(e(i,o),e(s,u)),f=new fabric.Point(t(i,o),t(s,u)),l=i===o&&s===u;for(var c=this._objects.length;c--;){r=this._objects[c];if(!r||!r.selectable||!r.visible)continue;if(r.intersectsWithRect(a,f)||r.isContainedWithinRect(a,f)||r.containsPoint(a)||r.containsPoint(f)){r.set("active",!0),n.push(r);if(l)break}}return n},_maybeGroupObjects:function(e){this.selection&&this._groupSelector&&this._groupSelectedObjects(e);var t=this.getActiveGroup();t&&(t.setObjectsCoords().setCoords(),t.isMoving=!1,this._setCursor(this.defaultCursor)),this._groupSelector=null,this._currentTransform=null}})})();fabric.util.object.extend(fabric.StaticCanvas.prototype,{toDataURL:function(e){e||(e={});var t=e.format||"png",n=e.quality||1,r=e.multiplier||1,i={left:e.left,top:e.top,width:e.width,height:e.height};return r!==1?this.__toDataURLWithMultiplier(t,n,i,r):this.__toDataURL(t,n,i)},__toDataURL:function(e,t,n){this.renderAll(!0);var r=this.upperCanvasEl||this.lowerCanvasEl,i=this.__getCroppedCanvas(r,n);e==="jpg"&&(e="jpeg");var s=fabric.StaticCanvas.supports("toDataURLWithQuality")?(i||r).toDataURL("image/"+e,t):(i||r).toDataURL("image/"+e);return this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),i&&(i=null),s},__getCroppedCanvas:function(e,t){var n,r,i="left"in t||"top"in t||"width"in t||"height"in t;return i&&(n=fabric.util.createCanvasElement(),r=n.getContext("2d"),n.width=t.width||this.width,n.height=t.height||this.height,r.drawImage(e,-t.left||0,-t.top||0)),n},__toDataURLWithMultiplier:function(e,t,n,r){var i=this.getWidth(),s=this.getHeight(),o=i*r,u=s*r,a=this.getActiveObject(),f=this.getActiveGroup(),l=this.contextTop||this.contextContainer;this.setWidth(o).setHeight(u),l.scale(r,r),n.left&&(n.left*=r),n.top&&(n.top*=r),n.width&&(n.width*=r),n.height&&(n.height*=r),f?this._tempRemoveBordersControlsFromGroup(f):a&&this.deactivateAll&&this.deactivateAll(),this.renderAll(!0);var c=this.__toDataURL(e,t,n);return this.width=i,this.height=s,l.scale(1/r,1/r),this.setWidth(i).setHeight(s),f?this._restoreBordersControlsOnGroup(f):a&&this.setActiveObject&&this.setActiveObject(a),this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),c},toDataURLWithMultiplier:function(e,t,n){return this.toDataURL({format:e,multiplier:t,quality:n})},_tempRemoveBordersControlsFromGroup:function(e){e.origHasControls=e.hasControls,e.origBorderColor=e.borderColor,e.hasControls=!0,e.borderColor="rgba(0,0,0,0)",e.forEachObject(function(e){e.origBorderColor=e.borderColor,e.borderColor="rgba(0,0,0,0)"})},_restoreBordersControlsOnGroup:function(e){e.hideControls=e.origHideControls,e.borderColor=e.origBorderColor,e.forEachObject(function(e){e.borderColor=e.origBorderColor,delete e.origBorderColor})}});fabric.util.object.extend(fabric.StaticCanvas.prototype,{loadFromDatalessJSON:function(e,t,n){return this.loadFromJSON(e,t,n)},loadFromJSON:function(e,t,n){if(!e)return;var r=typeof e=="string"?JSON.parse(e):e;this.clear();var i=this;return this._enlivenObjects(r.objects,function(){i._setBgOverlay(r,t)},n),this},_setBgOverlay:function(e,t){var n=this,r={backgroundColor:!1,overlayColor:!1,backgroundImage:!1,overlayImage:!1};if(!e.backgroundImage&&!e.overlayImage&&!e.background&&!e.overlay){t&&t();return}var i=function(){r.backgroundImage&&r.overlayImage&&r.backgroundColor&&r.overlayColor&&(n.renderAll(),t&&t())};this.__setBgOverlay("backgroundImage",e.backgroundImage,r,i),this.__setBgOverlay("overlayImage",e.overlayImage,r,i),this.__setBgOverlay("backgroundColor",e.background,r,i),this.__setBgOverlay("overlayColor",e.overlay,r,i),i()},__setBgOverlay:function(e,t,n,r){var i=this;if(!t){n[e]=!0;return}e==="backgroundImage"||e==="overlayImage"?fabric.Image.fromObject(t,function(t){i[e]=t,n[e]=!0,r&&r()}):this["set"+fabric.util.string.capitalize(e,!0)](t,function(){n[e]=!0,r&&r()})},_enlivenObjects:function(e,t,n){var r=this;e.length===0&&t&&t();var i=this.renderOnAddRemove;this.renderOnAddRemove=!1,fabric.util.enlivenObjects(e,function(e){e.forEach(function(e,t){r.insertAt(e,t,!0)}),r.renderOnAddRemove=i,t&&t()},null,n)},_toDataURL:function(e,t){this.clone(function(n){t(n.toDataURL(e))})},_toDataURLWithMultiplier:function(e,t,n){this.clone(function(r){n(r.toDataURLWithMultiplier(e,t))})},clone:function(e,t){var n=JSON.stringify(this.toJSON(t));this.cloneWithoutData(function(t){t.loadFromJSON(n,function(){e&&e(t)})})},cloneWithoutData:function(e){var t=fabric.document.createElement("canvas");t.width=this.getWidth(),t.height=this.getHeight();var n=new fabric.Canvas(t);n.clipTo=this.clipTo,this.backgroundImage?(n.setBackgroundImage(this.backgroundImage.src,function(){n.renderAll(),e&&e(n)}),n.backgroundImageOpacity=this.backgroundImageOpacity,n.backgroundImageStretch=this.backgroundImageStretch):e&&e(n)}});(function(){var e=fabric.util.degreesToRadians,t=fabric.util.radiansToDegrees;fabric.util.object.extend(fabric.Canvas.prototype,{__onTransformGesture:function(e,t){if(this.isDrawingMode||e.touches.length!==2||"gesture"!==t.gesture)return;var n=this.findTarget(e);"undefined"!=typeof n&&(this.onBeforeScaleRotate(n),this._rotateObjectByAngle(t.rotation),this._scaleObjectBy(t.scale)),this.fire("touch:gesture",{target:n,e:e,self:t})},__onDrag:function(e,t){this.fire("touch:drag",{e:e,self:t})},__onOrientationChange:function(e,t){this.fire("touch:orientation",{e:e,self:t})},__onShake:function(e,t){this.fire("touch:shake",{e:e,self:t})},_scaleObjectBy:function(e,t){var n=this._currentTransform,r=n.target,i=r.get("lockScalingX"),s=r.get("lockScalingY");if(i&&s)return;r._scaling=!0,t?t==="x"&&!r.get("lockUniScaling")?i||r.set("scaleX",n.scaleX*e):t==="y"&&!r.get("lockUniScaling")&&(s||r.set("scaleY",n.scaleY*e)):(i||r.set("scaleX",n.scaleX*e),s||r.set("scaleY",n.scaleY*e))},_rotateObjectByAngle:function(n){var r=this._currentTransform;if(r.target.get("lockRotation"))return;r.target.angle=t(e(n)+r.theta)}})})();(function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.toFixed,i=t.util.string.capitalize,s=t.util.degreesToRadians,o=t.StaticCanvas.supports("setLineDash");if(t.Object)return;t.Object=t.util.createClass({type:"object",originX:"left",originY:"top",top:0,left:0,width:0,height:0,scaleX:1,scaleY:1,flipX:!1,flipY:!1,opacity:1,angle:0,cornerSize:12,transparentCorners:!0,hoverCursor:null,padding:0,borderColor:"rgba(102,153,255,0.75)",cornerColor:"rgba(102,153,255,0.5)",centeredScaling:!1,centeredRotation:!0,fill:"rgb(0,0,0)",fillRule:"source-over",backgroundColor:"",stroke:null,strokeWidth:1,strokeDashArray:null,strokeLineCap:"butt",strokeLineJoin:"miter",strokeMiterLimit:10,shadow:null,borderOpacityWhenMoving:.4,borderScaleFactor:1,transformMatrix:null,minScaleLimit:.01,selectable:!0,evented:!0,visible:!0,hasControls:!0,hasBorders:!0,hasRotatingPoint:!0,rotatingPointOffset:40,perPixelTargetFind:!1,includeDefaultValues:!0,clipTo:null,lockMovementX:!1,lockMovementY:!1,lockRotation:!1,lockScalingX:!1,lockScalingY:!1,lockUniScaling:!1,stateProperties:"top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill fillRule shadow clipTo visible backgroundColor".split(" "),initialize:function(e){e&&this.setOptions(e)},_initGradient:function(e){e.fill&&e.fill.colorStops&&!(e.fill instanceof t.Gradient)&&this.set("fill",new t.Gradient(e.fill))},_initPattern:function(e){e.fill&&e.fill.source&&!(e.fill instanceof t.Pattern)&&this.set("fill",new t.Pattern(e.fill)),e.stroke&&e.stroke.source&&!(e.stroke instanceof t.Pattern)&&this.set("stroke",new t.Pattern(e.stroke))},_initClipping:function(e){if(!e.clipTo||typeof e.clipTo!="string")return;var n=t.util.getFunctionBody(e.clipTo);typeof n!="undefined"&&(this.clipTo=new Function("ctx",n))},setOptions:function(e){for(var t in e)this.set(t,e[t]);this._initGradient(e),this._initPattern(e),this._initClipping(e)},transform:function(e,t){e.globalAlpha=this.opacity;var n=t?this._getLeftTopCoords():this.getCenterPoint();e.translate(n.x,n.y),e.rotate(s(this.angle)),e.scale(this.scaleX*(this.flipX?-1:1),this.scaleY*(this.flipY?-1:1))},toObject:function(e){var n=t.Object.NUM_FRACTION_DIGITS,i={type:this.type,originX:this.originX,originY:this.originY,left:r(this.left,n),top:r(this.top,n),width:r(this.width,n),height:r(this.height,n),fill:this.fill&&this.fill.toObject?this.fill.toObject():this.fill,stroke:this.stroke&&this.stroke.toObject?this.stroke.toObject():this.stroke,strokeWidth:r(this.strokeWidth,n),strokeDashArray:this.strokeDashArray,strokeLineCap:this.strokeLineCap,strokeLineJoin:this.strokeLineJoin,strokeMiterLimit:r(this.strokeMiterLimit,n),scaleX:r(this.scaleX,n),scaleY:r(this.scaleY,n),angle:r(this.getAngle(),n),flipX:this.flipX,flipY:this.flipY,opacity:r(this.opacity,n),shadow:this.shadow&&this.shadow.toObject?this.shadow.toObject():this.shadow,visible:this.visible,clipTo:this.clipTo&&String(this.clipTo),backgroundColor:this.backgroundColor};return this.includeDefaultValues||(i=this._removeDefaultValues(i)),t.util.populateWithProperties(this,i,e),i},toDatalessObject:function(e){return this.toObject(e)},_removeDefaultValues:function(e){var n=t.util.getKlass(e.type).prototype,r=n.stateProperties;return r.forEach(function(t){e[t]===n[t]&&delete e[t]}),e},toString:function(){return"#"},get:function(e){return this[e]},set:function(e,t){if(typeof e=="object")for(var n in e)this._set(n,e[n]);else typeof t=="function"&&e!=="clipTo"?this._set(e,t(this.get(e))):this._set(e,t);return this},_set:function(e,n){var i=e==="scaleX"||e==="scaleY";return i&&(n=this._constrainScale(n)),e==="scaleX"&&n<0?(this.flipX=!this.flipX,n*=-1):e==="scaleY"&&n<0?(this.flipY=!this.flipY,n*=-1):e==="width"||e==="height"?this.minScaleLimit=r(Math.min(.1,1/Math.max(this.width,this.height)),2):e==="shadow"&&n&&!(n instanceof t.Shadow)&&(n=new t.Shadow(n)),this[e]=n,this},toggle:function(e){var t=this.get(e);return typeof t=="boolean"&&this.set(e,!t),this},setSourcePath:function(e){return this.sourcePath=e,this},render:function(e,n){if(this.width===0||this.height===0||!this.visible)return;e.save(),this._transform(e,n),this._setStrokeStyles(e),this._setFillStyles(e);var r=this.transformMatrix;r&&this.group&&(e.translate(-this.group.width/2,-this.group.height/2),e.transform(r[0],r[1],r[2],r[3],r[4],r[5])),this._setShadow(e),this.clipTo&&t.util.clipContext(this,e),this._render(e,n),this.clipTo&&e.restore(),this._removeShadow(e),this.active&&!n&&(this.drawBorders(e),this.drawControls(e)),e.restore()},_transform:function(e,t){var n=this.transformMatrix;n&&!this.group&&e.setTransform(n[0],n[1],n[2],n[3],n[4],n[5]),t||this.transform(e)},_setStrokeStyles:function(e){this.stroke&&(e.lineWidth=this.strokeWidth,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin,e.miterLimit=this.strokeMiterLimit,e.strokeStyle=this.stroke.toLive?this.stroke.toLive(e):this.stroke)},_setFillStyles:function(e){this.fill&&(e.fillStyle=this.fill.toLive?this.fill.toLive(e):this.fill)},_setShadow:function(e){if(!this.shadow)return;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_removeShadow:function(e){e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0},_renderFill:function(e){if(!this.fill)return;this.fill.toLive&&(e.save(),e.translate(-this.width/2+this.fill.offsetX||0,-this.height/2+this.fill.offsetY||0)),e.fill(),this.fill.toLive&&e.restore(),this.shadow&&!this.shadow.affectStroke&&this._removeShadow(e)},_renderStroke:function(e){if(!this.stroke)return;e.save(),this.strokeDashArray?(1&this.strokeDashArray.length&&this.strokeDashArray.push.apply(this.strokeDashArray,this.strokeDashArray),o?(e.setLineDash(this.strokeDashArray),this._stroke&&this._stroke(e)):this._renderDashedStroke&&this._renderDashedStroke(e),e.stroke()):this._stroke?this._stroke(e):e.stroke(),this._removeShadow(e),e.restore()},clone:function(e,n){return this.constructor.fromObject?this.constructor.fromObject(this.toObject(n),e):new t.Object(this.toObject(n))},cloneAsImage:function(e){var n=this.toDataURL();return t.util.loadImage(n,function(n){e&&e(new t.Image(n))}),this},toDataURL:function(e){e||(e={});var n=t.util.createCanvasElement(),r=this.getBoundingRect();n.width=r.width,n.height=r.height,t.util.wrapElement(n,"div");var i=new t.Canvas(n);e.format==="jpg"&&(e.format="jpeg"),e.format==="jpeg"&&(i.backgroundColor="#fff");var s={active:this.get("active"),left:this.getLeft(),top:this.getTop()};this.set("active",!1),this.setPositionByOrigin(new t.Point(n.width/2,n.height/2),"center","center");var o=this.canvas;i.add(this);var u=i.toDataURL(e);return this.set(s).setCoords(),this.canvas=o,i.dispose(),i=null,u},isType:function(e){return this.type===e},complexity:function(){return 0},toJSON:function(e){return this.toObject(e)},setGradient:function(e,n){n||(n={});var r={colorStops:[]};r.type=n.type||(n.r1||n.r2?"radial":"linear"),r.coords={x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y2};if(n.r1||n.r2)r.coords.r1=n.r1,r.coords.r2=n.r2;for(var i in n.colorStops){var s=new t.Color(n.colorStops[i]);r.colorStops.push({offset:i,color:s.toRgb(),opacity:s.getAlpha()})}return this.set(e,t.Gradient.forObject(this,r))},setPatternFill:function(e){return this.set("fill",new t.Pattern(e))},setShadow:function(e){return this.set("shadow",new t.Shadow(e))},setColor:function(e){return this.set("fill",e),this},centerH:function(){return this.canvas.centerObjectH(this),this},centerV:function(){return this.canvas.centerObjectV(this),this},center:function(){return this.canvas.centerObject(this),this},remove:function(){return this.canvas.remove(this)},getLocalPointer:function(e,t){t=t||this.canvas.getPointer(e);var n=this.translateToOriginPoint(this.getCenterPoint(),"left","top");return{x:t.x-n.x,y:t.y-n.y}}}),t.util.createAccessors(t.Object),t.Object.prototype.rotate=t.Object.prototype.setAngle,n(t.Object.prototype,t.Observable),t.Object.NUM_FRACTION_DIGITS=2,t.Object.__uid=0})(typeof exports!="undefined"?exports:this);(function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{translateToCenterPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x+(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x-(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y+(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y-(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},translateToOriginPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x-(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x+(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y-(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y+(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},getCenterPoint:function(){var e=new fabric.Point(this.left,this.top);return this.translateToCenterPoint(e,this.originX,this.originY)},getPointByOrigin:function(e,t){var n=this.getCenterPoint();return this.translateToOriginPoint(n,e,t)},toLocalPoint:function(t,n,r){var i=this.getCenterPoint(),s=this.stroke?this.strokeWidth:0,o,u;return n&&r?(n==="left"?o=i.x-(this.getWidth()+s*this.scaleX)/2:n==="right"?o=i.x+(this.getWidth()+s*this.scaleX)/2:o=i.x,r==="top"?u=i.y-(this.getHeight()+s*this.scaleY)/2:r==="bottom"?u=i.y+(this.getHeight()+s*this.scaleY)/2:u=i.y):(o=this.left,u=this.top),fabric.util.rotatePoint(new fabric.Point(t.x,t.y),i,-e(this.angle)).subtractEquals(new fabric.Point(o,u))},setPositionByOrigin:function(e,t,n){var r=this.translateToCenterPoint(e,t,n),i=this.translateToOriginPoint(r,this.originX,this.originY);this.set("left",i.x),this.set("top",i.y)},adjustPosition:function(t){var n=e(this.angle),r=this.getWidth()/2,i=Math.cos(n)*r,s=Math.sin(n)*r,o=this.getWidth(),u=Math.cos(n)*o,a=Math.sin(n)*o;this.originX==="center"&&t==="left"||this.originX==="right"&&t==="center"?(this.left-=i,this.top-=s):this.originX==="left"&&t==="center"||this.originX==="center"&&t==="right"?(this.left+=i,this.top+=s):this.originX==="left"&&t==="right"?(this.left+=u,this.top+=a):this.originX==="right"&&t==="left"&&(this.left-=u,this.top-=a),this.setCoords(),this.originX=t},_getLeftTopCoords:function(){return this.translateToOriginPoint(this.getCenterPoint(),"left","center")}})})();(function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{oCoords:null,intersectsWithRect:function(e,t){var n=this.oCoords,r=new fabric.Point(n.tl.x,n.tl.y),i=new fabric.Point(n.tr.x,n.tr.y),s=new fabric.Point(n.bl.x,n.bl.y),o=new fabric.Point(n.br.x,n.br.y),u=fabric.Intersection.intersectPolygonRectangle([r,i,o,s],e,t);return u.status==="Intersection"},intersectsWithObject:function(e){function t(e){return{tl:new fabric.Point(e.tl.x,e.tl.y),tr:new fabric.Point(e.tr.x,e.tr.y),bl:new fabric.Point(e.bl.x,e.bl.y),br:new fabric.Point(e.br.x,e.br.y)}}var n=t(this.oCoords),r=t(e.oCoords),i=fabric.Intersection.intersectPolygonPolygon([n.tl,n.tr,n.br,n.bl],[r.tl,r.tr,r.br,r.bl]);return i.status==="Intersection"},isContainedWithinObject:function(e){var t=e.getBoundingRect(),n=new fabric.Point(t.left,t.top),r=new fabric.Point(t.left+t.width,t.top+t.height);return this.isContainedWithinRect(n,r)},isContainedWithinRect:function(e,t){var n=this.getBoundingRect();return n.left>e.x&&n.left+n.widthe.y&&n.top+n.height=e.y&&f.d.y>=e.y)continue;f.o.x===f.d.x&&f.o.x>=e.x?(o=f.o.x,u=e.y):(n=0,r=(f.d.y-f.o.y)/(f.d.x-f.o.x),i=e.y-n*e.x,s=f.o.y-r*f.o.x,o=-(i-s)/(n-r),u=i+n*o),o>=e.x&&(a+=1);if(a===2)break}return a},getBoundingRectWidth:function(){return this.getBoundingRect().width},getBoundingRectHeight:function(){return this.getBoundingRect().height},getBoundingRect:function(){this.oCoords||this.setCoords();var e=[this.oCoords.tl.x,this.oCoords.tr.x,this.oCoords.br.x,this.oCoords.bl.x],t=fabric.util.array.min(e),n=fabric.util.array.max(e),r=Math.abs(t-n),i=[this.oCoords.tl.y,this.oCoords.tr.y,this.oCoords.br.y,this.oCoords.bl.y],s=fabric.util.array.min(i),o=fabric.util.array.max(i),u=Math.abs(s-o);return{left:t,top:s,width:r,height:u}},getWidth:function(){return this.width*this.scaleX},getHeight:function(){return this.height*this.scaleY},_constrainScale:function(e){return Math.abs(e)1?this.strokeWidth:0,n=this.padding,r=e(this.angle);this.currentWidth=(this.width+t)*this.scaleX+n*2,this.currentHeight=(this.height+t)*this.scaleY+n*2,this.currentWidth<0&&(this.currentWidth=Math.abs(this.currentWidth));var i=Math.sqrt(Math.pow(this.currentWidth/2,2)+Math.pow(this.currentHeight/2,2)),s=Math.atan(isFinite(this.currentHeight/this.currentWidth)?this.currentHeight/this.currentWidth:0),o=Math.cos(s+r)*i,u=Math.sin(s+r)*i,a=Math.sin(r),f=Math.cos(r),l=this.getCenterPoint(),c={x:l.x-o,y:l.y-u},h={x:c.x+this.currentWidth*f,y:c.y+this.currentWidth*a},p={x:h.x-this.currentHeight*a,y:h.y+this.currentHeight*f},d={x:c.x-this.currentHeight*a,y:c.y+this.currentHeight*f},v={x:c.x-this.currentHeight/2*a,y:c.y+this.currentHeight/2*f},m={x:c.x+this.currentWidth/2*f,y:c.y+this.currentWidth/2*a},g={x:h.x-this.currentHeight/2*a,y:h.y+this.currentHeight/2*f},y={x:d.x+this.currentWidth/2*f,y:d.y+this.currentWidth/2*a},b={x:m.x,y:m.y};return this.oCoords={tl:c,tr:h,br:p,bl:d,ml:v,mt:m,mr:g,mb:y,mtr:b},this._setCornerCoords&&this._setCornerCoords(),this}})})();fabric.util.object.extend(fabric.Object.prototype,{sendToBack:function(){return this.group?fabric.StaticCanvas.prototype.sendToBack.call(this.group,this):this.canvas.sendToBack(this),this},bringToFront:function(){return this.group?fabric.StaticCanvas.prototype.bringToFront.call(this.group,this):this.canvas.bringToFront(this),this},sendBackwards:function(e){return this.group?fabric.StaticCanvas.prototype.sendBackwards.call(this.group,this,e):this.canvas.sendBackwards(this,e),this},bringForward:function(e){return this.group?fabric.StaticCanvas.prototype.bringForward.call(this.group,this,e):this.canvas.bringForward(this,e),this},moveTo:function(e){return this.group?fabric.StaticCanvas.prototype.moveTo.call(this.group,this,e):this.canvas.moveTo(this,e),this}});fabric.util.object.extend(fabric.Object.prototype,{getSvgStyles:function(){var e=this.fill?this.fill.toLive?"url(#SVGID_"+this.fill.id+")":this.fill:"none",t=this.stroke?this.stroke.toLive?"url(#SVGID_"+this.stroke.id+")":this.stroke:"none",n=this.strokeWidth?this.strokeWidth:"0",r=this.strokeDashArray?this.strokeDashArray.join(" "):"",i=this.strokeLineCap?this.strokeLineCap:"butt",s=this.strokeLineJoin?this.strokeLineJoin:"miter",o=this.strokeMiterLimit?this.strokeMiterLimit:"4",u=typeof this.opacity!="undefined"?this.opacity:"1",a=this.visible?"":" visibility: hidden;",f=this.shadow&&this.type!=="text"?"filter: url(#SVGID_"+this.shadow.id+");":"";return["stroke: ",t,"; ","stroke-width: ",n,"; ","stroke-dasharray: ",r,"; ","stroke-linecap: ",i,"; ","stroke-linejoin: ",s,"; ","stroke-miterlimit: ",o,"; ","fill: ",e,"; ","opacity: ",u,";",f,a].join("")},getSvgTransform:function(){var e=fabric.util.toFixed,t=this.getAngle(),n=this.getCenterPoint(),r=fabric.Object.NUM_FRACTION_DIGITS,i="translate("+e(n.x,r)+" "+e(n.y,r)+")",s=t!==0?" rotate("+e(t,r)+")":"",o=this.scaleX===1&&this.scaleY===1?"":" scale("+e(this.scaleX,r)+" "+e(this.scaleY,r)+")",u=this.flipX?"matrix(-1 0 0 1 0 0) ":"",a=this.flipY?"matrix(1 0 0 -1 0 0)":"";return[i,s,o,u,a].join("")},_createBaseSVGMarkup:function(){var e=[];return this.fill&&this.fill.toLive&&e.push(this.fill.toSVG(this,!1)),this.stroke&&this.stroke.toLive&&e.push(this.stroke.toSVG(this,!1)),this.shadow&&e.push(this.shadow.toSVG(this)),e}});fabric.util.object.extend(fabric.Object.prototype,{hasStateChanged:function(){return this.stateProperties.some(function(e){return this.get(e)!==this.originalState[e]},this)},saveState:function(e){return this.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),e&&e.stateProperties&&e.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),this},setupState:function(){return this.originalState={},this.saveState(),this}});(function(){var e=fabric.util.getPointer,t=fabric.util.degreesToRadians,n=typeof G_vmlCanvasManager!="undefined";fabric.util.object.extend(fabric.Object.prototype,{_controlsVisibility:null,_findTargetCorner:function(t,n){if(!this.hasControls||!this.active)return!1;var r=e(t,this.canvas.upperCanvasEl),i=r.x-n.left,s=r.y-n.top,o,u;for(var a in this.oCoords){if(!this.isControlVisible(a))continue;if(a==="mtr"&&!this.hasRotatingPoint)continue;if(!(!this.get("lockUniScaling")||a!=="mt"&&a!=="mr"&&a!=="mb"&&a!=="ml"))continue;u=this._getImageLines(this.oCoords[a].corner),o=this._findCrossPoints({x:i,y:s},u);if(o!==0&&o%2===1)return this.__corner=a,a}return!1},_setCornerCoords:function(){var e=this.oCoords,n=t(this.angle),r=t(45-this.angle),i=Math.sqrt(2*Math.pow(this.cornerSize,2))/2,s=i*Math.cos(r),o=i*Math.sin(r),u=Math.sin(n),a=Math.cos(n);e.tl.corner={tl:{x:e.tl.x-o,y:e.tl.y-s},tr:{x:e.tl.x+s,y:e.tl.y-o},bl:{x:e.tl.x-s,y:e.tl.y+o},br:{x:e.tl.x+o,y:e.tl.y+s}},e.tr.corner={tl:{x:e.tr.x-o,y:e.tr.y-s},tr:{x:e.tr.x+s,y:e.tr.y-o},br:{x:e.tr.x+o,y:e.tr.y+s},bl:{x:e.tr.x-s,y:e.tr.y+o}},e.bl.corner={tl:{x:e.bl.x-o,y:e.bl.y-s},bl:{x:e.bl.x-s,y:e.bl.y+o},br:{x:e.bl.x+o,y:e.bl.y+s},tr:{x:e.bl.x+s,y:e.bl.y-o}},e.br.corner={tr:{x:e.br.x+s,y:e.br.y-o},bl:{x:e.br.x-s,y:e.br.y+o},br:{x:e.br.x+o,y:e.br.y+s},tl:{x:e.br.x-o,y:e.br.y-s}},e.ml.corner={tl:{x:e.ml.x-o,y:e.ml.y-s},tr:{x:e.ml.x+s,y:e.ml.y-o},bl:{x:e.ml.x-s,y:e.ml.y+o},br:{x:e.ml.x+o,y:e.ml.y+s}},e.mt.corner={tl:{x:e.mt.x-o,y:e.mt.y-s},tr:{x:e.mt.x+s,y:e.mt.y-o},bl:{x:e.mt.x-s,y:e.mt.y+o},br:{x:e.mt.x+o,y:e.mt.y+s}},e.mr.corner={tl:{x:e.mr.x-o,y:e.mr.y-s},tr:{x:e.mr.x+s,y:e.mr.y-o},bl:{x:e.mr.x-s,y:e.mr.y+o},br:{x:e.mr.x+o,y:e.mr.y+s}},e.mb.corner={tl:{x:e.mb.x-o,y:e.mb.y-s},tr:{x:e.mb.x+s,y:e.mb.y-o},bl:{x:e.mb.x-s,y:e.mb.y+o},br:{x:e.mb.x+o,y:e.mb.y+s}},e.mtr.corner={tl:{x:e.mtr.x-o+u*this.rotatingPointOffset,y:e.mtr.y-s-a*this.rotatingPointOffset},tr:{x:e.mtr.x+s+u*this.rotatingPointOffset,y:e.mtr.y-o-a*this.rotatingPointOffset},bl:{x:e.mtr.x-s+u*this.rotatingPointOffset,y:e.mtr.y+o-a*this.rotatingPointOffset},br:{x:e.mtr.x+o+u*this.rotatingPointOffset,y:e.mtr.y+s-a*this.rotatingPointOffset}}},drawBorders:function(e){if(!this.hasBorders)return this;var t=this.padding,n=t*2,r=~~(this.strokeWidth/2)*2;e.save(),e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=this.borderColor;var i=1/this._constrainScale(this.scaleX),s=1/this._constrainScale(this.scaleY);e.lineWidth=1/this.borderScaleFactor,e.scale(i,s);var o=this.getWidth(),u=this.getHeight();e.strokeRect(~~(-(o/2)-t-r/2*this.scaleX)-.5,~~(-(u/2)-t-r/2*this.scaleY)-.5,~~(o+n+r*this.scaleX)+1,~~(u+n+r*this.scaleY)+1);if(this.hasRotatingPoint&&this.isControlVisible("mtr")&&!this.get("lockRotation")&&this.hasControls){var a=(this.flipY?u+r*this.scaleY+t*2:-u-r*this.scaleY-t*2)/2;e.beginPath(),e.moveTo(0,a),e.lineTo(0,a+(this.flipY?this.rotatingPointOffset:-this.rotatingPointOffset)),e.closePath(),e.stroke()}return e.restore(),this},drawControls:function(e){if(!this.hasControls)return this;var t=this.cornerSize,n=t/2,r=~~(this.strokeWidth/2),i=-(this.width/2),s=-(this.height/2),o=this.padding/this.scaleX,u=this.padding/this.scaleY,a=n/this.scaleY,f=n/this.scaleX,l=(n-t)/this.scaleX,c=(n-t)/this.scaleY,h=this.height,p=this.width,d=this.transparentCorners?"strokeRect":"fillRect";return e.save(),e.lineWidth=1/Math.max(this.scaleX,this.scaleY),e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=e.fillStyle=this.cornerColor,this._drawControl("tl",e,d,i-f-r-o,s-a-r-u),this._drawControl("tr",e,d,i+p-f+r+o,s-a-r-u),this._drawControl("tr",e,d,i-f-r-o,s+h+c+r+u),this._drawControl("br",e,d,i+p+l+r+o,s+h+c+r+u),this.get("lockUniScaling")||(this._drawControl("mt",e,d,i+p/2-f,s-a-r-u),this._drawControl("mb",e,d,i+p/2-f,s+h+c+r+u),this._drawControl("mb",e,d,i+p+l+r+o,s+h/2-a),this._drawControl("ml",e,d,i-f-r-o,s+h/2-a)),this.hasRotatingPoint&&this._drawControl("mtr",e,d,i+p/2-f,this.flipY?s+h+this.rotatingPointOffset/this.scaleY-this.cornerSize/this.scaleX/2+r+u:s-this.rotatingPointOffset/this.scaleY-this.cornerSize/this.scaleY/2-r-u),e.restore(),this},_drawControl:function(e,t,r,i,s){var o=this.cornerSize/this.scaleX,u=this.cornerSize/this.scaleY;this.isControlVisible(e)&&(n||this.transparentCorners||t.clearRect(i,s,o,u),t[r](i,s,o,u))},isControlVisible:function(e){return this._getControlsVisibility()[e]},setControlVisible:function(e,t){return this._getControlsVisibility()[e]=t,this},setControlsVisibility:function(e){e||(e={});for(var t in e)this.setControlVisible(t,e[t]);return this},_getControlsVisibility:function(){return this._controlsVisibility||(this._controlsVisibility={tl:!0,tr:!0,br:!0,bl:!0,ml:!0,mt:!0,mr:!0,mb:!0,mtr:!0}),this._controlsVisibility}})})();(function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r={x1:1,x2:1,y1:1,y2:1},i=t.StaticCanvas.supports("setLineDash");if(t.Line){t.warn("fabric.Line is already defined");return}t.Line=t.util.createClass(t.Object,{type:"line",initialize:function(e,t){t=t||{},e||(e=[0,0,0,0]),this.callSuper("initialize",t),this.set("x1",e[0]),this.set("y1",e[1]),this.set("x2",e[2]),this.set("y2",e[3]),this._setWidthHeight(t)},_setWidthHeight:function(e){e||(e={}),this.set("width",Math.abs(this.x2-this.x1)||1),this.set("height",Math.abs(this.y2-this.y1)||1),this.set("left","left"in e?e.left:Math.min(this.x1,this.x2)+this.width/2),this.set("top","top"in e?e.top:Math.min(this.y1,this.y2)+this.height/2)},_set:function(e,t){return this[e]=t,e in r&&this._setWidthHeight(),this},_render:function(e){e.beginPath();var t=this.group&&this.group.type==="path-group";t&&!this.transformMatrix&&e.translate(-this.group.width/2+this.left,-this.group.height/2+this.top);if(!this.strokeDashArray||this.strokeDashArray&&i){var n=this.x1<=this.x2?-1:1,r=this.y1<=this.y2?-1:1;e.moveTo(this.width===1?0:n*this.width/2,this.height===1?0:r*this.height/2),e.lineTo(this.width===1?0:n*-1*this.width/2,this.height===1?0:r*-1*this.height/2)}e.lineWidth=this.strokeWidth;var s=e.strokeStyle;e.strokeStyle=this.stroke||e.fillStyle,this._renderStroke(e),e.strokeStyle=s},_renderDashedStroke:function(e){var n=this.x1<=this.x2?-1:1,r=this.y1<=this.y2?-1:1,i=this.width===1?0:n*this.width/2,s=this.height===1?0:r*this.height/2;e.beginPath(),t.util.drawDashedLine(e,i,s,-i,-s,this.strokeDashArray),e.closePath()},toObject:function(e){return n(this.callSuper("toObject",e),{x1:this.get("x1"),y1:this.get("y1"),x2:this.get("x2"),y2:this.get("y2")})},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Line.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" ")),t.Line.fromElement=function(e,r){var i=t.parseAttributes(e,t.Line.ATTRIBUTE_NAMES),s=[i.x1||0,i.y1||0,i.x2||0,i.y2||0];return new t.Line(s,n(i,r))},t.Line.fromObject=function(e){var n=[e.x1,e.y1,e.x2,e.y2];return new t.Line(n,e)}})(typeof exports!="undefined"?exports:this);(function(e){"use strict";function i(e){return"radius"in e&&e.radius>0}var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Circle){t.warn("fabric.Circle is already defined.");return}t.Circle=t.util.createClass(t.Object,{type:"circle",initialize:function(e){e=e||{},this.set("radius",e.radius||0),this.callSuper("initialize",e)},_set:function(e,t){return this.callSuper("_set",e,t),e==="radius"&&this.setRadius(t),this},toObject:function(e){return r(this.callSuper("toObject",e),{radius:this.get("radius")})},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,e.arc(t?this.left:0,t?this.top:0,this.radius,0,n,!1),e.closePath(),this._renderFill(e),this._renderStroke(e)},getRadiusX:function(){return this.get("radius")*this.get("scaleX")},getRadiusY:function(){return this.get("radius")*this.get("scaleY")},setRadius:function(e){this.radius=e,this.set("width",e*2).set("height",e*2)},complexity:function(){return 1}}),t.Circle.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy r".split(" ")),t.Circle.fromElement=function(e,n){n||(n={});var s=t.parseAttributes(e,t.Circle.ATTRIBUTE_NAMES);if(!i(s))throw new Error("value of `r` attribute is required and can not be negative");"left"in s&&(s.left-=n.width/2||0),"top"in s&&(s.top-=n.height/2||0);var o=new t.Circle(r(s,n));return o.cx=parseFloat(e.getAttribute("cx"))||0,o.cy=parseFloat(e.getAttribute("cy"))||0,o},t.Circle.fromObject=function(e){return new t.Circle(e)}})(typeof exports!="undefined"?exports:this);(function(e){"use strict";var t=e.fabric||(e.fabric={});if(t.Triangle){t.warn("fabric.Triangle is already defined");return}t.Triangle=t.util.createClass(t.Object,{type:"triangle",initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("width",e.width||100).set("height",e.height||100)},_render:function(e){var t=this.width/2,n=this.height/2;e.beginPath(),e.moveTo(-t,n),e.lineTo(0,-n),e.lineTo(t,n),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=this.width/2,r=this.height/2;e.beginPath(),t.util.drawDashedLine(e,-n,r,0,-r,this.strokeDashArray),t.util.drawDashedLine(e,0,-r,n,r,this.strokeDashArray),t.util.drawDashedLine(e,n,r,-n,r,this.strokeDashArray),e.closePath()},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=this.width/2,r=this.height/2,i=[-n+" "+r,"0 "+ -r,n+" "+r].join(",");return t.push("'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Triangle.fromObject=function(e){return new t.Triangle(e)}})(typeof exports!="undefined"?exports:this);(function(e){"use strict";var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Ellipse){t.warn("fabric.Ellipse is already defined.");return}t.Ellipse=t.util.createClass(t.Object,{type:"ellipse",rx:0,ry:0,initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("rx",e.rx||0),this.set("ry",e.ry||0),this.set("width",this.get("rx")*2),this.set("height",this.get("ry")*2)},toObject:function(e){return r(this.callSuper("toObject",e),{rx:this.get("rx"),ry:this.get("ry")})},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},render:function(e,t){if(this.rx===0||this.ry===0)return;return this.callSuper("render",e,t)},_render:function(e,t){e.beginPath(),e.save(),e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,this.transformMatrix&&this.group&&e.translate(this.cx,this.cy),e.transform(1,0,0,this.ry/this.rx,0,0),e.arc(t?this.left:0,t?this.top:0,this.rx,0,n,!1),this._renderFill(e),this._renderStroke(e),e.restore()},complexity:function(){return 1}}),t.Ellipse.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" ")),t.Ellipse.fromElement=function(e,n){n||(n={});var i=t.parseAttributes(e,t.Ellipse.ATTRIBUTE_NAMES),s=i.left,o=i.top;"left"in i&&(i.left-=n.width/2||0),"top"in i&&(i.top-=n.height/2||0);var u=new t.Ellipse(r(i,n));return u.cx=s||0,u.cy=o||0,u},t.Ellipse.fromObject=function(e){return new t.Ellipse(e)}})(typeof exports!="undefined"?exports:this);(function(e){"use strict";function i(e){return e.left=e.left||0,e.top=e.top||0,e}var t=e.fabric||(e.fabric={}),n=t.util.object.extend;if(t.Rect){console.warn("fabric.Rect is already defined");return}var r=t.Object.prototype.stateProperties.concat();r.push("rx","ry","x","y"),t.Rect=t.util.createClass(t.Object,{stateProperties:r,type:"rect",rx:0,ry:0,x:0,y:0,strokeDashArray:null,initialize:function(e){e=e||{},this.callSuper("initialize",e),this._initRxRy(),this.x=e.x||0,this.y=e.y||0},_initRxRy:function(){this.rx&&!this.ry?this.ry=this.rx:this.ry&&!this.rx&&(this.rx=this.ry)},_render:function(e){var t=this.rx||0,n=this.ry||0,r=-this.width/2,i=-this.height/2,s=this.width,o=this.height,u=this.group&&this.group.type==="path-group";e.beginPath(),e.globalAlpha=u?e.globalAlpha*this.opacity:this.opacity,this.transformMatrix&&u&&e.translate(this.width/2+this.x,this.height/2+this.y),!this.transformMatrix&&u&&e.translate(-this.group.width/2+this.width/2+this.x,-this.group.height/2+this.height/2+this.y);var a=t!==0||n!==0;e.moveTo(r+t,i),e.lineTo(r+s-t,i),a&&e.quadraticCurveTo(r+s,i,r+s,i+n,r+s,i+n),e.lineTo(r+s,i+o-n),a&&e.quadraticCurveTo(r+s,i+o,r+s-t,i+o,r+s-t,i+o),e.lineTo(r+t,i+o),a&&e.quadraticCurveTo(r,i+o,r,i+o-n,r,i+o-n),e.lineTo(r,i+n),a&&e.quadraticCurveTo(r,i,r+t,i,r+t,i),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=-this.width/2,r=-this.height/2,i=this.width,s=this.height;e.beginPath(),t.util.drawDashedLine(e,n,r,n+i,r,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r,n+i,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r+s,n,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n,r+s,n,r,this.strokeDashArray),e.closePath()},_normalizeLeftTopProperties:function(e){return"left"in e&&this.set("left",e.left+this.getWidth()/2),this.set("x",e.left||0),"top"in e&&this.set("top",e.top+this.getHeight()/2),this.set("y",e.top||0),this},toObject:function(e){var t=n(this.callSuper("toObject",e),{rx:this.get("rx")||0,ry:this.get("ry")||0,x:this.get("x"),y:this.get("y")});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Rect.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" ")),t.Rect.fromElement=function(e,r){if(!e)return null;var s=t.parseAttributes(e,t.Rect.ATTRIBUTE_NAMES);s=i(s);var o=new t.Rect(n(r?t.util.object.clone(r):{},s));return o._normalizeLeftTopProperties(s),o},t.Rect.fromObject=function(e){return new t.Rect(e)}})(typeof exports!="undefined"?exports:this);(function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.toFixed;if(t.Polyline){t.warn("fabric.Polyline is already defined");return}t.Polyline=t.util.createClass(t.Object,{type:"polyline",initialize:function(e,t,n){t=t||{},this.set("points",e),this.callSuper("initialize",t),this._calcDimensions(n)},_calcDimensions:function(e){return t.Polygon.prototype._calcDimensions.call(this,e)},toObject:function(e){return t.Polygon.prototype.toObject.call(this,e)},toSVG:function(e){var t=[],r=this._createBaseSVGMarkup();for(var i=0,s=this.points.length;i'),e?e(r.join("")):r.join("")},_render:function(e){var t;e.beginPath(),e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n'),e?e(n.join("")):n.join("")},_render:function(e){var t;e.beginPath(),e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n"},toObject:function(e){var t=s(this.callSuper("toObject",e),{path:this.path,pathOffset:this.pathOffset});return this.sourcePath&&(t.sourcePath=this.sourcePath),this.transformMatrix&&(t.transformMatrix=this.transformMatrix),t},toDatalessObject:function(e){var t=this.toObject(e);return this.sourcePath&&(t.path=this.sourcePath),delete t.sourcePath,t},toSVG:function(e){var t=[],n=this._createBaseSVGMarkup();for(var r=0,i=this.path.length;r',"",""),e?e(n.join("")):n.join("")},complexity:function(){return this.path.length},_parsePath:function(){var e=[],n=[],r,i,s=/(-?\.\d+)|(-?\d+(\.\d+)?)/g,o,u;for(var a=0,f,l=this.path.length;ad)for(var v=1,m=f.length;v"];for(var r=0,i=t.length;r"),e?e(n.join("")):n.join("")},toString:function(){return"#"},isSameColor:function(){var e=this.getObjects()[0].get("fill");return this.getObjects().every(function(t){return t.get("fill")===e})},complexity:function(){return this.paths.reduce(function(e,t){return e+(t&&t.complexity?t.complexity():0)},0)},getObjects:function(){return this.paths}}),t.PathGroup.fromObject=function(e,n){typeof e.paths=="string"?t.loadSVGFromURL(e.paths,function(r){var i=e.paths;delete e.paths;var s=t.util.groupSVGElements(r,e,i);n(s)}):t.util.enlivenObjects(e.paths,function(r){delete e.paths,n(new t.PathGroup(r,e))})},t.PathGroup.async=!0})(typeof exports!="undefined"?exports:this);(function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.array.min,i=t.util.array.max,s=t.util.array.invoke;if(t.Group)return;var o={lockMovementX:!0,lockMovementY:!0,lockRotation:!0,lockScalingX:!0,lockScalingY:!0,lockUniScaling:!0};t.Group=t.util.createClass(t.Object,t.Collection,{type:"group",initialize:function(e,t){t=t||{},this._objects=e||[];for(var r=this._objects.length;r--;)this._objects[r].group=this;this.originalState={},this.callSuper("initialize"),this._calcBounds(),this._updateObjectsCoords(),t&&n(this,t),this._setOpacityIfSame(),this.setCoords(!0),this.saveCoords()},_updateObjectsCoords:function(){this.forEachObject(this._updateObjectCoords,this)},_updateObjectCoords:function(e){var t=e.getLeft(),n=e.getTop();e.set({originalLeft:t,originalTop:n,left:t-this.left,top:n-this.top}),e.setCoords(),e.__origHasControls=e.hasControls,e.hasControls=!1},toString:function(){return"#"},addWithUpdate:function(e){return this._restoreObjectsState(),this._objects.push(e),e.group=this,this.forEachObject(this._setObjectActive,this),this._calcBounds(),this._updateObjectsCoords(),this},_setObjectActive:function(e){e.set("active",!0),e.group=this},removeWithUpdate:function(e){return this._moveFlippedObject(e),this._restoreObjectsState(),this.forEachObject(this._setObjectActive,this),this.remove(e),this._calcBounds(),this._updateObjectsCoords(),this},_onObjectAdded:function(e){e.group=this},_onObjectRemoved:function(e){delete e.group,e.set("active",!1)},delegatedProperties:{fill:!0,opacity:!0,fontFamily:!0,fontWeight:!0,fontSize:!0,fontStyle:!0,lineHeight:!0,textDecoration:!0,textAlign:!0,backgroundColor:!0},_set:function(e,t){if(e in this.delegatedProperties){var n=this._objects.length;this[e]=t;while(n--)this._objects[n].set(e,t)}else this[e]=t},toObject:function(e){return n(this.callSuper("toObject",e),{objects:s(this._objects,"toObject",e)})},render:function(e,n){if(!this.visible)return;e.save(),this.transform(e),this.clipTo&&t.util.clipContext(this,e);for(var r=0,i=this._objects.length;r'];for(var n=0,r=this._objects.length;n"),e?e(t.join("")):t.join("")},get:function(e){if(e in o){if(this[e])return this[e];for(var t=0,n=this._objects.length;t','");if(this.stroke||this.strokeDashArray){var n=this.fill;this.fill=null,t.push("'),this.fill=n}return t.push(""),e?e(t.join("")):t.join("")},getSrc:function(){return this.getElement().src||this.getElement()._src},toString:function(){return'#'},clone:function(e,t){this.constructor.fromObject(this.toObject(t),e)},applyFilters:function(e){if(this.filters.length===0){this._element=this._originalElement,e&&e();return}var t=this._originalElement,n=fabric.util.createCanvasElement(),r=fabric.util.createImage(),i=this;return n.width=t.width,n.height=t.height,n.getContext("2d").drawImage(t,0,0,t.width,t.height),this.filters.forEach(function(e){e&&e.applyTo(n)}),r.width=t.width,r.height=t.height,fabric.isLikelyNode?(r.src=n.toBuffer(undefined,fabric.Image.pngCompression),i._element=r,e&&e()):(r.onload=function(){i._element=r,e&&e(),r.onload=n=t=null},r.src=n.toDataURL("image/png")),this},_render:function(e){e.drawImage(this._element,-this.width/2,-this.height/2,this.width,this.height)},_resetWidthHeight:function(){var e=this.getElement();this.set("width",e.width),this.set("height",e.height)},_initElement:function(e){this.setElement(fabric.util.getById(e)),fabric.util.addClass(this.getElement(),fabric.Image.CSS_CANVAS)},_initConfig:function(e){e||(e={}),this.setOptions(e),this._setWidthHeight(e),this._element.crossOrigin=this.crossOrigin},_initFilters:function(e,t){e.filters&&e.filters.length?fabric.util.enlivenObjects(e.filters,function(e){t&&t(e)},"fabric.Image.filters"):t&&t()},_setWidthHeight:function(e){this.width="width"in e?e.width:this.getElement().width||0,this.height="height"in e?e.height:this.getElement().height||0},complexity:function(){return 1}}),fabric.Image.CSS_CANVAS="canvas-img",fabric.Image.prototype.getSvgSrc=fabric.Image.prototype.getSrc,fabric.Image.fromObject=function(e,t){fabric.util.loadImage(e.src,function(n){fabric.Image.prototype._initFilters.call(e,e,function(r){e.filters=r||[];var i=new fabric.Image(n,e);t&&t(i)})},null,e.crossOrigin)},fabric.Image.fromURL=function(e,t,n){fabric.util.loadImage(e,function(e){t(new fabric.Image(e,n))},null,n&&n.crossOrigin)},fabric.Image.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y width height xlink:href".split(" ")),fabric.Image.fromElement=function(e,n,r){var i=fabric.parseAttributes(e,fabric.Image.ATTRIBUTE_NAMES);fabric.Image.fromURL(i["xlink:href"],n,t(r?fabric.util.object.clone(r):{},i))},fabric.Image.async=!0,fabric.Image.pngCompression=1})(typeof exports!="undefined"?exports:this);(function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.object.clone,i=t.util.toFixed,s=t.StaticCanvas.supports("setLineDash");if(t.Text){t.warn("fabric.Text is already defined");return}var o=t.Object.prototype.stateProperties.concat();o.push("fontFamily","fontWeight","fontSize","text","textDecoration","textAlign","fontStyle","lineHeight","textBackgroundColor","useNative","path"),t.Text=t.util.createClass(t.Object,{_dimensionAffectingProps:{fontSize:!0,fontWeight:!0,fontFamily:!0,textDecoration:!0,fontStyle:!0,lineHeight:!0,stroke:!0,strokeWidth:!0,text:!0},_reNewline:/\r?\n/,type:"text",fontSize:40,fontWeight:"normal",fontFamily:"Times New Roman",textDecoration:"",textAlign:"left",fontStyle:"",lineHeight:1.3,textBackgroundColor:"",path:null,useNative:!0,stateProperties:o,stroke:null,shadow:null,initialize:function(e,t){t=t||{},this.text=e,this.__skipDimension=!0,this.setOptions(t),this.__skipDimension=!1,this._initDimensions(),this.setCoords()},_initDimensions:function(){if(this.__skipDimension)return;var e=t.util.createCanvasElement();this._render(e.getContext("2d"))},toString:function(){return"#'},_render:function(e){var t=this.group&&this.group.type==="path-group";t&&!this.transformMatrix?e.translate(-this.group.width/2+this.left,-this.group.height/2+this.top):t&&this.transformMatrix&&e.translate(-this.group.width/2,-this.group.height/2),typeof Cufon=="undefined"||this.useNative===!0?this._renderViaNative(e):this._renderViaCufon(e)},_renderViaNative:function(e){var n=this.text.split(this._reNewline);this.transform(e,t.isLikelyNode),this._setTextStyles(e),this.width=this._getTextWidth(e,n),this.height=this._getTextHeight(e,n),this.clipTo&&t.util.clipContext(this,e),this._renderTextBackground(e,n),this._translateForTextAlign(e),this._renderText(e,n),this.textAlign!=="left"&&this.textAlign!=="justify"&&e.restore(),this._renderTextDecoration(e,n),this.clipTo&&e.restore(),this._setBoundaries(e,n),this._totalLineHeight=0},_renderText:function(e,t){e.save(),this._setShadow(e),this._renderTextFill(e,t),this._renderTextStroke(e,t),this._removeShadow(e),e.restore()},_translateForTextAlign:function(e){this.textAlign!=="left"&&this.textAlign!=="justify"&&(e.save(),e.translate(this.textAlign==="center"?this.width/2:this.width,0))},_setBoundaries:function(e,t){this._boundaries=[];for(var n=0,r=t.length;nn&&(n=s)}return n},_renderChars:function(e,t,n,r,i){t[e](n,r,i)},_renderTextLine:function(e,t,n,r,i,s){i-=this.fontSize/4;if(this.textAlign!=="justify"){this._renderChars(e,t,n,r,i,s);return}var o=t.measureText(n).width,u=this.width;if(u>o){var a=n.split(/\s+/),f=t.measureText(n.replace(/\s+/g,"")).width,l=u-f,c=a.length-1,h=l/c,p=0;for(var d=0,v=a.length;d-1&&i(this.fontSize*this.lineHeight),this.textDecoration.indexOf("line-through")>-1&&i(this.fontSize*this.lineHeight-this.fontSize/2),this.textDecoration.indexOf("overline")>-1&&i(this.fontSize*this.lineHeight-this.fontSize)},_getFontDeclaration:function(){return[t.isLikelyNode?this.fontWeight:this.fontStyle,t.isLikelyNode?this.fontStyle:this.fontWeight,this.fontSize+"px",t.isLikelyNode?'"'+this.fontFamily+'"':this.fontFamily].join(" ")},render:function(e,t){if(!this.visible)return;e.save(),this._render(e),!t&&this.active&&(this.drawBorders(e),this.drawControls(e)),e.restore()},toObject:function(e){var t=n(this.callSuper("toObject",e),{text:this.text,fontSize:this.fontSize,fontWeight:this.fontWeight,fontFamily:this.fontFamily,fontStyle:this.fontStyle,lineHeight:this.lineHeight,textDecoration:this.textDecoration,textAlign:this.textAlign,path:this.path,textBackgroundColor:this.textBackgroundColor,useNative:this.useNative});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=[],n=this.text.split(this._reNewline),r=this._getSVGLeftTopOffsets(n),i=this._getSVGTextAndBg(r.lineTop,r.textLeft,n),s=this._getSVGShadows(r.lineTop,n);return r.textTop+=this._fontAscent?this._fontAscent/5*this.lineHeight:0,this._wrapSVGTextAndBg(t,i,s,r),e?e(t.join("")):t.join("")},_getSVGLeftTopOffsets:function(e){var t=this.useNative?this.fontSize*this.lineHeight:-this._fontAscent-this._fontAscent/5*this.lineHeight,n=-(this.width/2),r=this.useNative?this.fontSize-1:this.height/2-e.length*this.fontSize-this._totalLineHeight;return{textLeft:n,textTop:r,lineTop:t}},_wrapSVGTextAndBg:function(e,t,n,r){e.push('',t.textBgRects.join(""),"',n.join(""),t.textSpans.join(""),"","")},_getSVGShadows:function(e,n){var r=[],s,o,u=1;if(!this.shadow||!this._boundaries)return r;for(s=0,o=n.length;s",t.util.string.escapeXml(n[s]),""),u=1}else u++;return r},_getSVGTextAndBg:function(e,t,n){var r=[],i=[],s=1;this._setSVGBg(i);for(var o=0,u=n.length;o",t.util.string.escapeXml(e),"")},_setSVGTextLineBg:function(e,t,n,r){e.push("')},_setSVGBg:function(e){this.backgroundColor&&this._boundaries&&e.push("')},_getFillAttributes:function(e){var n=e&&typeof e=="string"?new t.Color(e):"";return!n||!n.getSource()||n.getAlpha()===1?'fill="'+e+'"':'opacity="'+n.getAlpha()+'" fill="'+n.setAlpha(1).toRgb()+'"'},_set:function(e,t){e==="fontFamily"&&this.path&&(this.path=this.path.replace(/(.*?)([^\/]*)(\.font\.js)/,"$1"+t+"$3")),this.callSuper("_set",e,t),e in this._dimensionAffectingProps&&(this._initDimensions(),this.setCoords())},complexity:function(){return 1}}),t.Text.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y font-family font-style font-weight font-size text-decoration".split(" ")),t.Text.fromElement=function(e,n){if(!e)return null;var r=t.parseAttributes(e,t.Text.ATTRIBUTE_NAMES);n=t.util.object.extend(n?t.util.object.clone(n):{},r);var i=new t.Text(e.textContent,n);return i.set({left:i.getLeft()+i.getWidth()/2,top:i.getTop()-i.getHeight()/2}),i},t.Text.fromObject=function(e){return new t.Text(e.text,r(e))},t.util.createAccessors(t.Text)})(typeof exports!="undefined"?exports:this); \ No newline at end of file diff --git a/js/fabric-v1.4.11.js b/js/fabric-v1.4.11.js new file mode 100644 index 00000000..5b9b5daa --- /dev/null +++ b/js/fabric-v1.4.11.js @@ -0,0 +1,22624 @@ +/* build: `node build.js modules=ALL exclude=gestures,cufon,json minifier=uglifyjs` */ +/*! Fabric.js Copyright 2008-2014, Printio (Juriy Zaytsev, Maxim Chernyak) */ + +var fabric = fabric || { version: "1.4.11" }; +if (typeof exports !== 'undefined') { + exports.fabric = fabric; +} + +if (typeof document !== 'undefined' && typeof window !== 'undefined') { + fabric.document = document; + fabric.window = window; +} +else { + // assume we're running under node.js when document/window are not present + fabric.document = require("jsdom") + .jsdom(""); + + fabric.window = fabric.document.createWindow(); +} + +/** + * True when in environment that supports touch events + * @type boolean + */ +fabric.isTouchSupported = "ontouchstart" in fabric.document.documentElement; + +/** + * True when in environment that's probably Node.js + * @type boolean + */ +fabric.isLikelyNode = typeof Buffer !== 'undefined' && + typeof window === 'undefined'; + + +/** + * Attributes parsed from all SVG elements + * @type array + */ +fabric.SHARED_ATTRIBUTES = [ + "display", + "transform", + "fill", "fill-opacity", "fill-rule", + "opacity", + "stroke", "stroke-dasharray", "stroke-linecap", + "stroke-linejoin", "stroke-miterlimit", + "stroke-opacity", "stroke-width" +]; + +/** + * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion. + */ +fabric.DPI = 96; + + +(function(){ + + /** + * @private + * @param {String} eventName + * @param {Function} handler + */ + function _removeEventListener(eventName, handler) { + if (!this.__eventListeners[eventName]) { + return; + } + + if (handler) { + fabric.util.removeFromArray(this.__eventListeners[eventName], handler); + } + else { + this.__eventListeners[eventName].length = 0; + } + } + + /** + * Observes specified event + * @deprecated `observe` deprecated since 0.8.34 (use `on` instead) + * @memberOf fabric.Observable + * @alias on + * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler}) + * @param {Function} handler Function that receives a notification when an event of the specified type occurs + * @return {Self} thisArg + * @chainable + */ + function observe(eventName, handler) { + if (!this.__eventListeners) { + this.__eventListeners = { }; + } + // one object with key/value pairs was passed + if (arguments.length === 1) { + for (var prop in eventName) { + this.on(prop, eventName[prop]); + } + } + else { + if (!this.__eventListeners[eventName]) { + this.__eventListeners[eventName] = [ ]; + } + this.__eventListeners[eventName].push(handler); + } + return this; + } + + /** + * Stops event observing for a particular event handler. Calling this method + * without arguments removes all handlers for all events + * @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead) + * @memberOf fabric.Observable + * @alias off + * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler}) + * @param {Function} handler Function to be deleted from EventListeners + * @return {Self} thisArg + * @chainable + */ + function stopObserving(eventName, handler) { + if (!this.__eventListeners) { + return; + } + + // remove all key/value pairs (event name -> event handler) + if (arguments.length === 0) { + this.__eventListeners = { }; + } + // one object with key/value pairs was passed + else if (arguments.length === 1 && typeof arguments[0] === 'object') { + for (var prop in eventName) { + _removeEventListener.call(this, prop, eventName[prop]); + } + } + else { + _removeEventListener.call(this, eventName, handler); + } + return this; + } + + /** + * Fires event with an optional options object + * @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead) + * @memberOf fabric.Observable + * @alias trigger + * @param {String} eventName Event name to fire + * @param {Object} [options] Options object + * @return {Self} thisArg + * @chainable + */ + function fire(eventName, options) { + if (!this.__eventListeners) { + return; + } + + var listenersForEvent = this.__eventListeners[eventName]; + if (!listenersForEvent) { + return; + } + + for (var i = 0, len = listenersForEvent.length; i < len; i++) { + // avoiding try/catch for perf. reasons + listenersForEvent[i].call(this, options || { }); + } + return this; + } + + /** + * @namespace fabric.Observable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#events} + * @see {@link http://fabricjs.com/events/|Events demo} + */ + fabric.Observable = { + observe: observe, + stopObserving: stopObserving, + fire: fire, + + on: observe, + off: stopObserving, + trigger: fire + }; +})(); + + +/** + * @namespace fabric.Collection + */ +fabric.Collection = { + + /** + * Adds objects to collection, then renders canvas (if `renderOnAddRemove` is not `false`) + * Objects should be instances of (or inherit from) fabric.Object + * @param {...fabric.Object} object Zero or more fabric instances + * @return {Self} thisArg + */ + add: function () { + this._objects.push.apply(this._objects, arguments); + for (var i = 0, length = arguments.length; i < length; i++) { + this._onObjectAdded(arguments[i]); + } + this.renderOnAddRemove && this.renderAll(); + return this; + }, + + /** + * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`) + * An object should be an instance of (or inherit from) fabric.Object + * @param {Object} object Object to insert + * @param {Number} index Index to insert object at + * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs + * @return {Self} thisArg + * @chainable + */ + insertAt: function (object, index, nonSplicing) { + var objects = this.getObjects(); + if (nonSplicing) { + objects[index] = object; + } + else { + objects.splice(index, 0, object); + } + this._onObjectAdded(object); + this.renderOnAddRemove && this.renderAll(); + return this; + }, + + /** + * Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`) + * @param {...fabric.Object} object Zero or more fabric instances + * @return {Self} thisArg + * @chainable + */ + remove: function() { + var objects = this.getObjects(), + index; + + for (var i = 0, length = arguments.length; i < length; i++) { + index = objects.indexOf(arguments[i]); + + // only call onObjectRemoved if an object was actually removed + if (index !== -1) { + objects.splice(index, 1); + this._onObjectRemoved(arguments[i]); + } + } + + this.renderOnAddRemove && this.renderAll(); + return this; + }, + + /** + * Executes given function for each object in this group + * @param {Function} callback + * Callback invoked with current object as first argument, + * index - as second and an array of all objects - as third. + * Iteration happens in reverse order (for performance reasons). + * Callback is invoked in a context of Global Object (e.g. `window`) + * when no `context` argument is given + * + * @param {Object} context Context (aka thisObject) + * @return {Self} thisArg + */ + forEachObject: function(callback, context) { + var objects = this.getObjects(), + i = objects.length; + while (i--) { + callback.call(context, objects[i], i, objects); + } + return this; + }, + + /** + * Returns an array of children objects of this instance + * Type parameter introduced in 1.3.10 + * @param {String} [type] When specified, only objects of this type are returned + * @return {Array} + */ + getObjects: function(type) { + if (typeof type === 'undefined') { + return this._objects; + } + return this._objects.filter(function(o) { + return o.type === type; + }); + }, + + /** + * Returns object at specified index + * @param {Number} index + * @return {Self} thisArg + */ + item: function (index) { + return this.getObjects()[index]; + }, + + /** + * Returns true if collection contains no objects + * @return {Boolean} true if collection is empty + */ + isEmpty: function () { + return this.getObjects().length === 0; + }, + + /** + * Returns a size of a collection (i.e: length of an array containing its objects) + * @return {Number} Collection size + */ + size: function() { + return this.getObjects().length; + }, + + /** + * Returns true if collection contains an object + * @param {Object} object Object to check against + * @return {Boolean} `true` if collection contains an object + */ + contains: function(object) { + return this.getObjects().indexOf(object) > -1; + }, + + /** + * Returns number representation of a collection complexity + * @return {Number} complexity + */ + complexity: function () { + return this.getObjects().reduce(function (memo, current) { + memo += current.complexity ? current.complexity() : 0; + return memo; + }, 0); + } +}; + + +(function(global) { + + var sqrt = Math.sqrt, + atan2 = Math.atan2, + PiBy180 = Math.PI / 180; + + /** + * @namespace fabric.util + */ + fabric.util = { + + /** + * Removes value from an array. + * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf` + * @static + * @memberOf fabric.util + * @param {Array} array + * @param {Any} value + * @return {Array} original array + */ + removeFromArray: function(array, value) { + var idx = array.indexOf(value); + if (idx !== -1) { + array.splice(idx, 1); + } + return array; + }, + + /** + * Returns random number between 2 specified ones. + * @static + * @memberOf fabric.util + * @param {Number} min lower limit + * @param {Number} max upper limit + * @return {Number} random value (between min and max) + */ + getRandomInt: function(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + }, + + /** + * Transforms degrees to radians. + * @static + * @memberOf fabric.util + * @param {Number} degrees value in degrees + * @return {Number} value in radians + */ + degreesToRadians: function(degrees) { + return degrees * PiBy180; + }, + + /** + * Transforms radians to degrees. + * @static + * @memberOf fabric.util + * @param {Number} radians value in radians + * @return {Number} value in degrees + */ + radiansToDegrees: function(radians) { + return radians / PiBy180; + }, + + /** + * Rotates `point` around `origin` with `radians` + * @static + * @memberOf fabric.util + * @param {fabric.Point} point The point to rotate + * @param {fabric.Point} origin The origin of the rotation + * @param {Number} radians The radians of the angle for the rotation + * @return {fabric.Point} The new rotated point + */ + rotatePoint: function(point, origin, radians) { + var sin = Math.sin(radians), + cos = Math.cos(radians); + + point.subtractEquals(origin); + + var rx = point.x * cos - point.y * sin, + ry = point.x * sin + point.y * cos; + + return new fabric.Point(rx, ry).addEquals(origin); + }, + + /** + * Apply transform t to point p + * @static + * @memberOf fabric.util + * @param {fabric.Point} p The point to transform + * @param {Array} t The transform + * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied + * @return {fabric.Point} The transformed point + */ + transformPoint: function(p, t, ignoreOffset) { + if (ignoreOffset) { + return new fabric.Point( + t[0] * p.x + t[1] * p.y, + t[2] * p.x + t[3] * p.y + ); + } + return new fabric.Point( + t[0] * p.x + t[1] * p.y + t[4], + t[2] * p.x + t[3] * p.y + t[5] + ); + }, + + /** + * Invert transformation t + * @static + * @memberOf fabric.util + * @param {Array} t The transform + * @return {Array} The inverted transform + */ + invertTransform: function(t) { + var r = t.slice(), + a = 1 / (t[0] * t[3] - t[1] * t[2]); + r = [a * t[3], -a * t[1], -a * t[2], a * t[0], 0, 0]; + var o = fabric.util.transformPoint({ x: t[4], y: t[5] }, r); + r[4] = -o.x; + r[5] = -o.y; + return r; + }, + + /** + * A wrapper around Number#toFixed, which contrary to native method returns number, not string. + * @static + * @memberOf fabric.util + * @param {Number|String} number number to operate on + * @param {Number} fractionDigits number of fraction digits to "leave" + * @return {Number} + */ + toFixed: function(number, fractionDigits) { + return parseFloat(Number(number).toFixed(fractionDigits)); + }, + + /** + * Converts from attribute value to pixel value if applicable. + * Returns converted pixels or original value not converted. + * @param {Number|String} value number to operate on + * @return {Number|String} + */ + parseUnit: function(value) { + var unit = /\D{0,2}$/.exec(value), + number = parseFloat(value); + + switch (unit[0]) { + case 'mm': + return number * fabric.DPI / 25.4; + + case 'cm': + return number * fabric.DPI / 2.54; + + case 'in': + return number * fabric.DPI; + + case 'pt': + return number * fabric.DPI / 72; // or * 4 / 3 + + case 'pc': + return number * fabric.DPI / 72 * 12; // or * 16 + + default: + return number; + } + }, + + /** + * Function which always returns `false`. + * @static + * @memberOf fabric.util + * @return {Boolean} + */ + falseFunction: function() { + return false; + }, + + /** + * Returns klass "Class" object of given namespace + * @memberOf fabric.util + * @param {String} type Type of object (eg. 'circle') + * @param {String} namespace Namespace to get klass "Class" object from + * @return {Object} klass "Class" + */ + getKlass: function(type, namespace) { + // capitalize first letter only + type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1)); + return fabric.util.resolveNamespace(namespace)[type]; + }, + + /** + * Returns object of given namespace + * @memberOf fabric.util + * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric' + * @return {Object} Object for given namespace (default fabric) + */ + resolveNamespace: function(namespace) { + if (!namespace) { + return fabric; + } + + var parts = namespace.split('.'), + len = parts.length, + obj = global || fabric.window; + + for (var i = 0; i < len; ++i) { + obj = obj[parts[i]]; + } + + return obj; + }, + + /** + * Loads image element from given url and passes it to a callback + * @memberOf fabric.util + * @param {String} url URL representing an image + * @param {Function} callback Callback; invoked with loaded image + * @param {Any} [context] Context to invoke callback in + * @param {Object} [crossOrigin] crossOrigin value to set image element to + */ + loadImage: function(url, callback, context, crossOrigin) { + if (!url) { + callback && callback.call(context, url); + return; + } + + var img = fabric.util.createImage(); + + /** @ignore */ + img.onload = function () { + callback && callback.call(context, img); + img = img.onload = img.onerror = null; + }; + + /** @ignore */ + img.onerror = function() { + fabric.log('Error loading ' + img.src); + callback && callback.call(context, null, true); + img = img.onload = img.onerror = null; + }; + + // data-urls appear to be buggy with crossOrigin + // https://github.com/kangax/fabric.js/commit/d0abb90f1cd5c5ef9d2a94d3fb21a22330da3e0a#commitcomment-4513767 + // see https://code.google.com/p/chromium/issues/detail?id=315152 + // https://bugzilla.mozilla.org/show_bug.cgi?id=935069 + if (url.indexOf('data') !== 0 && typeof crossOrigin !== 'undefined') { + img.crossOrigin = crossOrigin; + } + + img.src = url; + }, + + /** + * Creates corresponding fabric instances from their object representations + * @static + * @memberOf fabric.util + * @param {Array} objects Objects to enliven + * @param {Function} callback Callback to invoke when all objects are created + * @param {String} namespace Namespace to get klass "Class" object from + * @param {Function} reviver Method for further parsing of object elements, + * called after each fabric object created. + */ + enlivenObjects: function(objects, callback, namespace, reviver) { + objects = objects || [ ]; + + function onLoaded() { + if (++numLoadedObjects === numTotalObjects) { + callback && callback(enlivenedObjects); + } + } + + var enlivenedObjects = [ ], + numLoadedObjects = 0, + numTotalObjects = objects.length; + + if (!numTotalObjects) { + callback && callback(enlivenedObjects); + return; + } + + objects.forEach(function (o, index) { + // if sparse array + if (!o || !o.type) { + onLoaded(); + return; + } + var klass = fabric.util.getKlass(o.type, namespace); + if (klass.async) { + klass.fromObject(o, function (obj, error) { + if (!error) { + enlivenedObjects[index] = obj; + reviver && reviver(o, enlivenedObjects[index]); + } + onLoaded(); + }); + } + else { + enlivenedObjects[index] = klass.fromObject(o); + reviver && reviver(o, enlivenedObjects[index]); + onLoaded(); + } + }); + }, + + /** + * Groups SVG elements (usually those retrieved from SVG document) + * @static + * @memberOf fabric.util + * @param {Array} elements SVG elements to group + * @param {Object} [options] Options object + * @return {fabric.Object|fabric.PathGroup} + */ + groupSVGElements: function(elements, options, path) { + var object; + + object = new fabric.PathGroup(elements, options); + + if (typeof path !== 'undefined') { + object.setSourcePath(path); + } + return object; + }, + + /** + * Populates an object with properties of another object + * @static + * @memberOf fabric.util + * @param {Object} source Source object + * @param {Object} destination Destination object + * @return {Array} properties Propertie names to include + */ + populateWithProperties: function(source, destination, properties) { + if (properties && Object.prototype.toString.call(properties) === '[object Array]') { + for (var i = 0, len = properties.length; i < len; i++) { + if (properties[i] in source) { + destination[properties[i]] = source[properties[i]]; + } + } + } + }, + + /** + * Draws a dashed line between two points + * + * This method is used to draw dashed line around selection area. + * See dotted stroke in canvas + * + * @param {CanvasRenderingContext2D} ctx context + * @param {Number} x start x coordinate + * @param {Number} y start y coordinate + * @param {Number} x2 end x coordinate + * @param {Number} y2 end y coordinate + * @param {Array} da dash array pattern + */ + drawDashedLine: function(ctx, x, y, x2, y2, da) { + var dx = x2 - x, + dy = y2 - y, + len = sqrt(dx * dx + dy * dy), + rot = atan2(dy, dx), + dc = da.length, + di = 0, + draw = true; + + ctx.save(); + ctx.translate(x, y); + ctx.moveTo(0, 0); + ctx.rotate(rot); + + x = 0; + while (len > x) { + x += da[di++ % dc]; + if (x > len) { + x = len; + } + ctx[draw ? 'lineTo' : 'moveTo'](x, 0); + draw = !draw; + } + + ctx.restore(); + }, + + /** + * Creates canvas element and initializes it via excanvas if necessary + * @static + * @memberOf fabric.util + * @param {CanvasElement} [canvasEl] optional canvas element to initialize; + * when not given, element is created implicitly + * @return {CanvasElement} initialized canvas element + */ + createCanvasElement: function(canvasEl) { + canvasEl || (canvasEl = fabric.document.createElement('canvas')); + //jscs:disable requireCamelCaseOrUpperCaseIdentifiers + if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') { + G_vmlCanvasManager.initElement(canvasEl); + } + //jscs:enable requireCamelCaseOrUpperCaseIdentifiers + return canvasEl; + }, + + /** + * Creates image element (works on client and node) + * @static + * @memberOf fabric.util + * @return {HTMLImageElement} HTML image element + */ + createImage: function() { + return fabric.isLikelyNode + ? new (require('canvas').Image)() + : fabric.document.createElement('img'); + }, + + /** + * Creates accessors (getXXX, setXXX) for a "class", based on "stateProperties" array + * @static + * @memberOf fabric.util + * @param {Object} klass "Class" to create accessors for + */ + createAccessors: function(klass) { + var proto = klass.prototype; + + for (var i = proto.stateProperties.length; i--; ) { + + var propName = proto.stateProperties[i], + capitalizedPropName = propName.charAt(0).toUpperCase() + propName.slice(1), + setterName = 'set' + capitalizedPropName, + getterName = 'get' + capitalizedPropName; + + // using `new Function` for better introspection + if (!proto[getterName]) { + proto[getterName] = (function(property) { + return new Function('return this.get("' + property + '")'); + })(propName); + } + if (!proto[setterName]) { + proto[setterName] = (function(property) { + return new Function('value', 'return this.set("' + property + '", value)'); + })(propName); + } + } + }, + + /** + * @static + * @memberOf fabric.util + * @param {fabric.Object} receiver Object implementing `clipTo` method + * @param {CanvasRenderingContext2D} ctx Context to clip + */ + clipContext: function(receiver, ctx) { + ctx.save(); + ctx.beginPath(); + receiver.clipTo(ctx); + ctx.clip(); + }, + + /** + * Multiply matrix A by matrix B to nest transformations + * @static + * @memberOf fabric.util + * @param {Array} matrixA First transformMatrix + * @param {Array} matrixB Second transformMatrix + * @return {Array} The product of the two transform matrices + */ + multiplyTransformMatrices: function(matrixA, matrixB) { + // Matrix multiply matrixA * matrixB + var a = [ + [matrixA[0], matrixA[2], matrixA[4]], + [matrixA[1], matrixA[3], matrixA[5]], + [0, 0, 1 ] + ], + + b = [ + [matrixB[0], matrixB[2], matrixB[4]], + [matrixB[1], matrixB[3], matrixB[5]], + [0, 0, 1 ] + ], + + result = []; + + for (var r = 0; r < 3; r++) { + result[r] = []; + for (var c = 0; c < 3; c++) { + var sum = 0; + for (var k = 0; k < 3; k++) { + sum += a[r][k] * b[k][c]; + } + + result[r][c] = sum; + } + } + + return [ + result[0][0], + result[1][0], + result[0][1], + result[1][1], + result[0][2], + result[1][2] + ]; + }, + + /** + * Returns string representation of function body + * @param {Function} fn Function to get body of + * @return {String} Function body + */ + getFunctionBody: function(fn) { + return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1]; + }, + + /** + * Returns true if context has transparent pixel + * at specified location (taking tolerance into account) + * @param {CanvasRenderingContext2D} ctx context + * @param {Number} x x coordinate + * @param {Number} y y coordinate + * @param {Number} tolerance Tolerance + */ + isTransparent: function(ctx, x, y, tolerance) { + + // If tolerance is > 0 adjust start coords to take into account. + // If moves off Canvas fix to 0 + if (tolerance > 0) { + if (x > tolerance) { + x -= tolerance; + } + else { + x = 0; + } + if (y > tolerance) { + y -= tolerance; + } + else { + y = 0; + } + } + + var _isTransparent = true, + imageData = ctx.getImageData(x, y, (tolerance * 2) || 1, (tolerance * 2) || 1); + + // Split image data - for tolerance > 1, pixelDataSize = 4; + for (var i = 3, l = imageData.data.length; i < l; i += 4) { + var temp = imageData.data[i]; + _isTransparent = temp <= 0; + if (_isTransparent === false) { + break; // Stop if colour found + } + } + + imageData = null; + + return _isTransparent; + } + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + var arcToSegmentsCache = { }, + segmentToBezierCache = { }, + _join = Array.prototype.join; + + /* Adapted from http://dxr.mozilla.org/mozilla-central/source/content/svg/content/src/nsSVGPathDataParser.cpp + * by Andrea Bogazzi code is under MPL. if you don't have a copy of the license you can take it here + * http://mozilla.org/MPL/2.0/ + */ + function arcToSegments(toX, toY, rx, ry, large, sweep, rotateX) { + var argsString = _join.call(arguments); + if (arcToSegmentsCache[argsString]) { + return arcToSegmentsCache[argsString]; + } + + var PI = Math.PI, th = rotateX * (PI / 180), + sinTh = Math.sin(th), + cosTh = Math.cos(th), + fromX = 0, fromY = 0; + + rx = Math.abs(rx); + ry = Math.abs(ry); + + var px = -cosTh * toX - sinTh * toY, + py = -cosTh * toY + sinTh * toX, + rx2 = rx * rx, ry2 = ry * ry, py2 = py * py, px2 = px * px, + pl = 4 * rx2 * ry2 - rx2 * py2 - ry2 * px2, + root = 0; + + if (pl < 0) { + var s = Math.sqrt(1 - 0.25 * pl/(rx2 * ry2)); + rx *= s; + ry *= s; + } else { + root = (large === sweep ? -0.5 : 0.5) * + Math.sqrt( pl /(rx2 * py2 + ry2 * px2)); + } + + var cx = root * rx * py / ry, + cy = -root * ry * px / rx, + cx1 = cosTh * cx - sinTh * cy + toX / 2, + cy1 = sinTh * cx + cosTh * cy + toY / 2, + mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry), + dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px -cx) / rx, (-py -cy) / ry); + + if (sweep === 0 && dtheta > 0) { + dtheta -= 2 * PI; + } else if (sweep === 1 && dtheta < 0) { + dtheta += 2 * PI; + } + + // Convert into cubic bezier segments <= 90deg + var segments = Math.ceil(Math.abs(dtheta / (PI * 0.5))), + result = [], mDelta = dtheta / segments, + mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2), + th3 = mTheta + mDelta; + + for (var i = 0; i < segments; i++) { + result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY); + fromX = result[i][4]; + fromY = result[i][5]; + mTheta += mDelta; + th3 += mDelta; + } + arcToSegmentsCache[argsString] = result; + return result; + } + + function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) { + var argsString2 = _join.call(arguments); + if (segmentToBezierCache[argsString2]) { + return segmentToBezierCache[argsString2]; + } + + var costh2 = Math.cos(th2), + sinth2 = Math.sin(th2), + costh3 = Math.cos(th3), + sinth3 = Math.sin(th3), + toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1, + toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1, + cp1X = fromX + mT * ( - cosTh * rx * sinth2 - sinTh * ry * costh2), + cp1Y = fromY + mT * ( - sinTh * rx * sinth2 + cosTh * ry * costh2), + cp2X = toX + mT * ( cosTh * rx * sinth3 + sinTh * ry * costh3), + cp2Y = toY + mT * ( sinTh * rx * sinth3 - cosTh * ry * costh3); + + segmentToBezierCache[argsString2] = [ + cp1X, cp1Y, + cp2X, cp2Y, + toX, toY + ]; + return segmentToBezierCache[argsString2]; + } + + /* + * Private + */ + function calcVectorAngle(ux, uy, vx, vy) { + var ta = Math.atan2(uy, ux), + tb = Math.atan2(vy, vx); + if (tb >= ta) { + return tb - ta; + } else { + return 2 * Math.PI - (ta - tb); + } + } + + /** + * Draws arc + * @param {CanvasRenderingContext2D} ctx + * @param {Number} x + * @param {Number} y + * @param {Array} coords + */ + fabric.util.drawArc = function(ctx, fx, fy, coords) { + var rx = coords[0], + ry = coords[1], + rot = coords[2], + large = coords[3], + sweep = coords[4], + tx = coords[5], + ty = coords[6], + segs = [[ ], [ ], [ ], [ ]], + segs_norm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot); + for (var i = 0; i < segs_norm.length; i++) { + segs[i][0] = segs_norm[i][0] + fx; + segs[i][1] = segs_norm[i][1] + fy; + segs[i][2] = segs_norm[i][2] + fx; + segs[i][3] = segs_norm[i][3] + fy; + segs[i][4] = segs_norm[i][4] + fx; + segs[i][5] = segs_norm[i][5] + fy; + ctx.bezierCurveTo.apply(ctx, segs[i]); + } + }; +})(); + + +(function() { + + var slice = Array.prototype.slice; + + /* _ES5_COMPAT_START_ */ + + if (!Array.prototype.indexOf) { + /** + * Finds index of an element in an array + * @param {Any} searchElement + * @param {Number} [fromIndex] + * @return {Number} + */ + Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) { + if (this === void 0 || this === null) { + throw new TypeError(); + } + var t = Object(this), len = t.length >>> 0; + if (len === 0) { + return -1; + } + var n = 0; + if (arguments.length > 0) { + n = Number(arguments[1]); + if (n !== n) { // shortcut for verifying if it's NaN + n = 0; + } + else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + } + if (n >= len) { + return -1; + } + var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); + for (; k < len; k++) { + if (k in t && t[k] === searchElement) { + return k; + } + } + return -1; + }; + } + + if (!Array.prototype.forEach) { + /** + * Iterates an array, invoking callback for each element + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.forEach = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + fn.call(context, this[i], i, this); + } + } + }; + } + + if (!Array.prototype.map) { + /** + * Returns a result of iterating over an array, invoking callback for each element + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.map = function(fn, context) { + var result = [ ]; + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + result[i] = fn.call(context, this[i], i, this); + } + } + return result; + }; + } + + if (!Array.prototype.every) { + /** + * Returns true if a callback returns truthy value for all elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Boolean} + */ + Array.prototype.every = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this && !fn.call(context, this[i], i, this)) { + return false; + } + } + return true; + }; + } + + if (!Array.prototype.some) { + /** + * Returns true if a callback returns truthy value for at least one element in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Boolean} + */ + Array.prototype.some = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this && fn.call(context, this[i], i, this)) { + return true; + } + } + return false; + }; + } + + if (!Array.prototype.filter) { + /** + * Returns the result of iterating over elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.filter = function(fn, context) { + var result = [ ], val; + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + val = this[i]; // in case fn mutates this + if (fn.call(context, val, i, this)) { + result.push(val); + } + } + } + return result; + }; + } + + if (!Array.prototype.reduce) { + /** + * Returns "folded" (reduced) result of iterating over elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [initial] Object to use as the first argument to the first call of the callback + * @return {Any} + */ + Array.prototype.reduce = function(fn /*, initial*/) { + var len = this.length >>> 0, + i = 0, + rv; + + if (arguments.length > 1) { + rv = arguments[1]; + } + else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) { + throw new TypeError(); + } + } + while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fn.call(null, rv, this[i], i, this); + } + } + return rv; + }; + } + + /* _ES5_COMPAT_END_ */ + + /** + * Invokes method on all items in a given array + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} method Name of a method to invoke + * @return {Array} + */ + function invoke(array, method) { + var args = slice.call(arguments, 2), result = [ ]; + for (var i = 0, len = array.length; i < len; i++) { + result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]); + } + return result; + } + + /** + * Finds maximum value in array (not necessarily "first" one) + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} byProperty + * @return {Any} + */ + function max(array, byProperty) { + return find(array, byProperty, function(value1, value2) { + return value1 >= value2; + }); + } + + /** + * Finds minimum value in array (not necessarily "first" one) + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} byProperty + * @return {Any} + */ + function min(array, byProperty) { + return find(array, byProperty, function(value1, value2) { + return value1 < value2; + }); + } + + /** + * @private + */ + function find(array, byProperty, condition) { + if (!array || array.length === 0) { + return; + } + + var i = array.length - 1, + result = byProperty ? array[i][byProperty] : array[i]; + if (byProperty) { + while (i--) { + if (condition(array[i][byProperty], result)) { + result = array[i][byProperty]; + } + } + } + else { + while (i--) { + if (condition(array[i], result)) { + result = array[i]; + } + } + } + return result; + } + + /** + * @namespace fabric.util.array + */ + fabric.util.array = { + invoke: invoke, + min: min, + max: max + }; + +})(); + + +(function(){ + + /** + * Copies all enumerable properties of one object to another + * @memberOf fabric.util.object + * @param {Object} destination Where to copy to + * @param {Object} source Where to copy from + * @return {Object} + */ + function extend(destination, source) { + // JScript DontEnum bug is not taken care of + for (var property in source) { + destination[property] = source[property]; + } + return destination; + } + + /** + * Creates an empty object and copies all enumerable properties of another object to it + * @memberOf fabric.util.object + * @param {Object} object Object to clone + * @return {Object} + */ + function clone(object) { + return extend({ }, object); + } + + /** @namespace fabric.util.object */ + fabric.util.object = { + extend: extend, + clone: clone + }; + +})(); + + +(function() { + + /* _ES5_COMPAT_START_ */ + if (!String.prototype.trim) { + /** + * Trims a string (removing whitespace from the beginning and the end) + * @function external:String#trim + * @see String#trim on MDN + */ + String.prototype.trim = function () { + // this trim is not fully ES3 or ES5 compliant, but it should cover most cases for now + return this.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, ''); + }; + } + /* _ES5_COMPAT_END_ */ + + /** + * Camelizes a string + * @memberOf fabric.util.string + * @param {String} string String to camelize + * @return {String} Camelized version of a string + */ + function camelize(string) { + return string.replace(/-+(.)?/g, function(match, character) { + return character ? character.toUpperCase() : ''; + }); + } + + /** + * Capitalizes a string + * @memberOf fabric.util.string + * @param {String} string String to capitalize + * @param {Boolean} [firstLetterOnly] If true only first letter is capitalized + * and other letters stay untouched, if false first letter is capitalized + * and other letters are converted to lowercase. + * @return {String} Capitalized version of a string + */ + function capitalize(string, firstLetterOnly) { + return string.charAt(0).toUpperCase() + + (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()); + } + + /** + * Escapes XML in a string + * @memberOf fabric.util.string + * @param {String} string String to escape + * @return {String} Escaped version of a string + */ + function escapeXml(string) { + return string.replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + } + + /** + * String utilities + * @namespace fabric.util.string + */ + fabric.util.string = { + camelize: camelize, + capitalize: capitalize, + escapeXml: escapeXml + }; +}()); + + +/* _ES5_COMPAT_START_ */ +(function() { + + var slice = Array.prototype.slice, + apply = Function.prototype.apply, + Dummy = function() { }; + + if (!Function.prototype.bind) { + /** + * Cross-browser approximation of ES5 Function.prototype.bind (not fully spec conforming) + * @see Function#bind on MDN + * @param {Object} thisArg Object to bind function to + * @param {Any[]} [...] Values to pass to a bound function + * @return {Function} + */ + Function.prototype.bind = function(thisArg) { + var _this = this, args = slice.call(arguments, 1), bound; + if (args.length) { + bound = function() { + return apply.call(_this, this instanceof Dummy ? this : thisArg, args.concat(slice.call(arguments))); + }; + } + else { + /** @ignore */ + bound = function() { + return apply.call(_this, this instanceof Dummy ? this : thisArg, arguments); + }; + } + Dummy.prototype = this.prototype; + bound.prototype = new Dummy(); + + return bound; + }; + } + +})(); +/* _ES5_COMPAT_END_ */ + + +(function() { + + var slice = Array.prototype.slice, emptyFunction = function() { }, + + IS_DONTENUM_BUGGY = (function(){ + for (var p in { toString: 1 }) { + if (p === 'toString') { + return false; + } + } + return true; + })(), + + /** @ignore */ + addMethods = function(klass, source, parent) { + for (var property in source) { + + if (property in klass.prototype && + typeof klass.prototype[property] === 'function' && + (source[property] + '').indexOf('callSuper') > -1) { + + klass.prototype[property] = (function(property) { + return function() { + + var superclass = this.constructor.superclass; + this.constructor.superclass = parent; + var returnValue = source[property].apply(this, arguments); + this.constructor.superclass = superclass; + + if (property !== 'initialize') { + return returnValue; + } + }; + })(property); + } + else { + klass.prototype[property] = source[property]; + } + + if (IS_DONTENUM_BUGGY) { + if (source.toString !== Object.prototype.toString) { + klass.prototype.toString = source.toString; + } + if (source.valueOf !== Object.prototype.valueOf) { + klass.prototype.valueOf = source.valueOf; + } + } + } + }; + + function Subclass() { } + + function callSuper(methodName) { + var fn = this.constructor.superclass.prototype[methodName]; + return (arguments.length > 1) + ? fn.apply(this, slice.call(arguments, 1)) + : fn.call(this); + } + + /** + * Helper for creation of "classes". + * @memberOf fabric.util + * @param {Function} [parent] optional "Class" to inherit from + * @param {Object} [properties] Properties shared by all instances of this class + * (be careful modifying objects defined here as this would affect all instances) + */ + function createClass() { + var parent = null, + properties = slice.call(arguments, 0); + + if (typeof properties[0] === 'function') { + parent = properties.shift(); + } + function klass() { + this.initialize.apply(this, arguments); + } + + klass.superclass = parent; + klass.subclasses = [ ]; + + if (parent) { + Subclass.prototype = parent.prototype; + klass.prototype = new Subclass(); + parent.subclasses.push(klass); + } + for (var i = 0, length = properties.length; i < length; i++) { + addMethods(klass, properties[i], parent); + } + if (!klass.prototype.initialize) { + klass.prototype.initialize = emptyFunction; + } + klass.prototype.constructor = klass; + klass.prototype.callSuper = callSuper; + return klass; + } + + fabric.util.createClass = createClass; +})(); + + +(function () { + + var unknown = 'unknown'; + + /* EVENT HANDLING */ + + function areHostMethods(object) { + var methodNames = Array.prototype.slice.call(arguments, 1), + t, i, len = methodNames.length; + for (i = 0; i < len; i++) { + t = typeof object[methodNames[i]]; + if (!(/^(?:function|object|unknown)$/).test(t)) { + return false; + } + } + return true; + } + + /** @ignore */ + var getElement, + setElement, + getUniqueId = (function () { + var uid = 0; + return function (element) { + return element.__uniqueID || (element.__uniqueID = 'uniqueID__' + uid++); + }; + })(); + + (function () { + var elements = { }; + /** @ignore */ + getElement = function (uid) { + return elements[uid]; + }; + /** @ignore */ + setElement = function (uid, element) { + elements[uid] = element; + }; + })(); + + function createListener(uid, handler) { + return { + handler: handler, + wrappedHandler: createWrappedHandler(uid, handler) + }; + } + + function createWrappedHandler(uid, handler) { + return function (e) { + handler.call(getElement(uid), e || fabric.window.event); + }; + } + + function createDispatcher(uid, eventName) { + return function (e) { + if (handlers[uid] && handlers[uid][eventName]) { + var handlersForEvent = handlers[uid][eventName]; + for (var i = 0, len = handlersForEvent.length; i < len; i++) { + handlersForEvent[i].call(this, e || fabric.window.event); + } + } + }; + } + + var shouldUseAddListenerRemoveListener = ( + areHostMethods(fabric.document.documentElement, 'addEventListener', 'removeEventListener') && + areHostMethods(fabric.window, 'addEventListener', 'removeEventListener')), + + shouldUseAttachEventDetachEvent = ( + areHostMethods(fabric.document.documentElement, 'attachEvent', 'detachEvent') && + areHostMethods(fabric.window, 'attachEvent', 'detachEvent')), + + // IE branch + listeners = { }, + + // DOM L0 branch + handlers = { }, + + addListener, removeListener; + + if (shouldUseAddListenerRemoveListener) { + /** @ignore */ + addListener = function (element, eventName, handler) { + element.addEventListener(eventName, handler, false); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + element.removeEventListener(eventName, handler, false); + }; + } + + else if (shouldUseAttachEventDetachEvent) { + /** @ignore */ + addListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + setElement(uid, element); + if (!listeners[uid]) { + listeners[uid] = { }; + } + if (!listeners[uid][eventName]) { + listeners[uid][eventName] = [ ]; + + } + var listener = createListener(uid, handler); + listeners[uid][eventName].push(listener); + element.attachEvent('on' + eventName, listener.wrappedHandler); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + var uid = getUniqueId(element), listener; + if (listeners[uid] && listeners[uid][eventName]) { + for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) { + listener = listeners[uid][eventName][i]; + if (listener && listener.handler === handler) { + element.detachEvent('on' + eventName, listener.wrappedHandler); + listeners[uid][eventName][i] = null; + } + } + } + }; + } + else { + /** @ignore */ + addListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + if (!handlers[uid]) { + handlers[uid] = { }; + } + if (!handlers[uid][eventName]) { + handlers[uid][eventName] = [ ]; + var existingHandler = element['on' + eventName]; + if (existingHandler) { + handlers[uid][eventName].push(existingHandler); + } + element['on' + eventName] = createDispatcher(uid, eventName); + } + handlers[uid][eventName].push(handler); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + if (handlers[uid] && handlers[uid][eventName]) { + var handlersForEvent = handlers[uid][eventName]; + for (var i = 0, len = handlersForEvent.length; i < len; i++) { + if (handlersForEvent[i] === handler) { + handlersForEvent.splice(i, 1); + } + } + } + }; + } + + /** + * Adds an event listener to an element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {String} eventName + * @param {Function} handler + */ + fabric.util.addListener = addListener; + + /** + * Removes an event listener from an element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {String} eventName + * @param {Function} handler + */ + fabric.util.removeListener = removeListener; + + /** + * Cross-browser wrapper for getting event's coordinates + * @memberOf fabric.util + * @param {Event} event Event object + * @param {HTMLCanvasElement} upperCanvasEl <canvas> element on which object selection is drawn + */ + function getPointer(event, upperCanvasEl) { + event || (event = fabric.window.event); + + var element = event.target || + (typeof event.srcElement !== unknown ? event.srcElement : null), + + scroll = fabric.util.getScrollLeftTop(element, upperCanvasEl); + + return { + x: pointerX(event) + scroll.left, + y: pointerY(event) + scroll.top + }; + } + + var pointerX = function(event) { + // looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element) + // is represented as COM object, with all the consequences, like "unknown" type and error on [[Get]] + // need to investigate later + return (typeof event.clientX !== unknown ? event.clientX : 0); + }, + + pointerY = function(event) { + return (typeof event.clientY !== unknown ? event.clientY : 0); + }; + + function _getPointer(event, pageProp, clientProp) { + var touchProp = event.type === 'touchend' ? 'changedTouches' : 'touches'; + + return (event[touchProp] && event[touchProp][0] + ? (event[touchProp][0][pageProp] - (event[touchProp][0][pageProp] - event[touchProp][0][clientProp])) + || event[clientProp] + : event[clientProp]); + } + + if (fabric.isTouchSupported) { + pointerX = function(event) { + return _getPointer(event, 'pageX', 'clientX'); + }; + pointerY = function(event) { + return _getPointer(event, 'pageY', 'clientY'); + }; + } + + fabric.util.getPointer = getPointer; + + fabric.util.object.extend(fabric.util, fabric.Observable); + +})(); + + +(function () { + + /** + * Cross-browser wrapper for setting element's style + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {Object} styles + * @return {HTMLElement} Element that was passed as a first argument + */ + function setStyle(element, styles) { + var elementStyle = element.style; + if (!elementStyle) { + return element; + } + if (typeof styles === 'string') { + element.style.cssText += ';' + styles; + return styles.indexOf('opacity') > -1 + ? setOpacity(element, styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) + : element; + } + for (var property in styles) { + if (property === 'opacity') { + setOpacity(element, styles[property]); + } + else { + var normalizedProperty = (property === 'float' || property === 'cssFloat') + ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat') + : property; + elementStyle[normalizedProperty] = styles[property]; + } + } + return element; + } + + var parseEl = fabric.document.createElement('div'), + supportsOpacity = typeof parseEl.style.opacity === 'string', + supportsFilters = typeof parseEl.style.filter === 'string', + reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/, + + /** @ignore */ + setOpacity = function (element) { return element; }; + + if (supportsOpacity) { + /** @ignore */ + setOpacity = function(element, value) { + element.style.opacity = value; + return element; + }; + } + else if (supportsFilters) { + /** @ignore */ + setOpacity = function(element, value) { + var es = element.style; + if (element.currentStyle && !element.currentStyle.hasLayout) { + es.zoom = 1; + } + if (reOpacity.test(es.filter)) { + value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')'); + es.filter = es.filter.replace(reOpacity, value); + } + else { + es.filter += ' alpha(opacity=' + (value * 100) + ')'; + } + return element; + }; + } + + fabric.util.setStyle = setStyle; + +})(); + + +(function() { + + var _slice = Array.prototype.slice; + + /** + * Takes id and returns an element with that id (if one exists in a document) + * @memberOf fabric.util + * @param {String|HTMLElement} id + * @return {HTMLElement|null} + */ + function getById(id) { + return typeof id === 'string' ? fabric.document.getElementById(id) : id; + } + + var sliceCanConvertNodelists, + /** + * Converts an array-like object (e.g. arguments or NodeList) to an array + * @memberOf fabric.util + * @param {Object} arrayLike + * @return {Array} + */ + toArray = function(arrayLike) { + return _slice.call(arrayLike, 0); + }; + + try { + sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array; + } + catch (err) { } + + if (!sliceCanConvertNodelists) { + toArray = function(arrayLike) { + var arr = new Array(arrayLike.length), i = arrayLike.length; + while (i--) { + arr[i] = arrayLike[i]; + } + return arr; + }; + } + + /** + * Creates specified element with specified attributes + * @memberOf fabric.util + * @param {String} tagName Type of an element to create + * @param {Object} [attributes] Attributes to set on an element + * @return {HTMLElement} Newly created element + */ + function makeElement(tagName, attributes) { + var el = fabric.document.createElement(tagName); + for (var prop in attributes) { + if (prop === 'class') { + el.className = attributes[prop]; + } + else if (prop === 'for') { + el.htmlFor = attributes[prop]; + } + else { + el.setAttribute(prop, attributes[prop]); + } + } + return el; + } + + /** + * Adds class to an element + * @memberOf fabric.util + * @param {HTMLElement} element Element to add class to + * @param {String} className Class to add to an element + */ + function addClass(element, className) { + if (element && (' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) { + element.className += (element.className ? ' ' : '') + className; + } + } + + /** + * Wraps element with another element + * @memberOf fabric.util + * @param {HTMLElement} element Element to wrap + * @param {HTMLElement|String} wrapper Element to wrap with + * @param {Object} [attributes] Attributes to set on a wrapper + * @return {HTMLElement} wrapper + */ + function wrapElement(element, wrapper, attributes) { + if (typeof wrapper === 'string') { + wrapper = makeElement(wrapper, attributes); + } + if (element.parentNode) { + element.parentNode.replaceChild(wrapper, element); + } + wrapper.appendChild(element); + return wrapper; + } + + /** + * Returns element scroll offsets + * @memberOf fabric.util + * @param {HTMLElement} element Element to operate on + * @param {HTMLElement} upperCanvasEl Upper canvas element + * @return {Object} Object with left/top values + */ + function getScrollLeftTop(element, upperCanvasEl) { + + var firstFixedAncestor, + origElement, + left = 0, + top = 0, + docElement = fabric.document.documentElement, + body = fabric.document.body || { + scrollLeft: 0, scrollTop: 0 + }; + + origElement = element; + + while (element && element.parentNode && !firstFixedAncestor) { + + element = element.parentNode; + + if (element !== fabric.document && + fabric.util.getElementStyle(element, 'position') === 'fixed') { + firstFixedAncestor = element; + } + + if (element !== fabric.document && + origElement !== upperCanvasEl && + fabric.util.getElementStyle(element, 'position') === 'absolute') { + left = 0; + top = 0; + } + else if (element === fabric.document) { + left = body.scrollLeft || docElement.scrollLeft || 0; + top = body.scrollTop || docElement.scrollTop || 0; + } + else { + left += element.scrollLeft || 0; + top += element.scrollTop || 0; + } + } + + return { left: left, top: top }; + } + + /** + * Returns offset for a given element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element Element to get offset for + * @return {Object} Object with "left" and "top" properties + */ + function getElementOffset(element) { + var docElem, + doc = element && element.ownerDocument, + box = { left: 0, top: 0 }, + offset = { left: 0, top: 0 }, + scrollLeftTop, + offsetAttributes = { + borderLeftWidth: 'left', + borderTopWidth: 'top', + paddingLeft: 'left', + paddingTop: 'top' + }; + + if (!doc) { + return { left: 0, top: 0 }; + } + + for (var attr in offsetAttributes) { + offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0; + } + + docElem = doc.documentElement; + if ( typeof element.getBoundingClientRect !== 'undefined' ) { + box = element.getBoundingClientRect(); + } + + scrollLeftTop = fabric.util.getScrollLeftTop(element, null); + + return { + left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left, + top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top + }; + } + + /** + * Returns style attribute value of a given element + * @memberOf fabric.util + * @param {HTMLElement} element Element to get style attribute for + * @param {String} attr Style attribute to get for element + * @return {String} Style attribute value of the given element. + */ + var getElementStyle; + if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) { + getElementStyle = function(element, attr) { + return fabric.document.defaultView.getComputedStyle(element, null)[attr]; + }; + } + else { + getElementStyle = function(element, attr) { + var value = element.style[attr]; + if (!value && element.currentStyle) { + value = element.currentStyle[attr]; + } + return value; + }; + } + + (function () { + var style = fabric.document.documentElement.style, + selectProp = 'userSelect' in style + ? 'userSelect' + : 'MozUserSelect' in style + ? 'MozUserSelect' + : 'WebkitUserSelect' in style + ? 'WebkitUserSelect' + : 'KhtmlUserSelect' in style + ? 'KhtmlUserSelect' + : ''; + + /** + * Makes element unselectable + * @memberOf fabric.util + * @param {HTMLElement} element Element to make unselectable + * @return {HTMLElement} Element that was passed in + */ + function makeElementUnselectable(element) { + if (typeof element.onselectstart !== 'undefined') { + element.onselectstart = fabric.util.falseFunction; + } + if (selectProp) { + element.style[selectProp] = 'none'; + } + else if (typeof element.unselectable === 'string') { + element.unselectable = 'on'; + } + return element; + } + + /** + * Makes element selectable + * @memberOf fabric.util + * @param {HTMLElement} element Element to make selectable + * @return {HTMLElement} Element that was passed in + */ + function makeElementSelectable(element) { + if (typeof element.onselectstart !== 'undefined') { + element.onselectstart = null; + } + if (selectProp) { + element.style[selectProp] = ''; + } + else if (typeof element.unselectable === 'string') { + element.unselectable = ''; + } + return element; + } + + fabric.util.makeElementUnselectable = makeElementUnselectable; + fabric.util.makeElementSelectable = makeElementSelectable; + })(); + + (function() { + + /** + * Inserts a script element with a given url into a document; invokes callback, when that script is finished loading + * @memberOf fabric.util + * @param {String} url URL of a script to load + * @param {Function} callback Callback to execute when script is finished loading + */ + function getScript(url, callback) { + var headEl = fabric.document.getElementsByTagName('head')[0], + scriptEl = fabric.document.createElement('script'), + loading = true; + + /** @ignore */ + scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) { + if (loading) { + if (typeof this.readyState === 'string' && + this.readyState !== 'loaded' && + this.readyState !== 'complete') { + return; + } + loading = false; + callback(e || fabric.window.event); + scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null; + } + }; + scriptEl.src = url; + headEl.appendChild(scriptEl); + // causes issue in Opera + // headEl.removeChild(scriptEl); + } + + fabric.util.getScript = getScript; + })(); + + fabric.util.getById = getById; + fabric.util.toArray = toArray; + fabric.util.makeElement = makeElement; + fabric.util.addClass = addClass; + fabric.util.wrapElement = wrapElement; + fabric.util.getScrollLeftTop = getScrollLeftTop; + fabric.util.getElementOffset = getElementOffset; + fabric.util.getElementStyle = getElementStyle; + +})(); + + +(function(){ + + function addParamToUrl(url, param) { + return url + (/\?/.test(url) ? '&' : '?') + param; + } + + var makeXHR = (function() { + var factories = [ + function() { return new ActiveXObject('Microsoft.XMLHTTP'); }, + function() { return new ActiveXObject('Msxml2.XMLHTTP'); }, + function() { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); }, + function() { return new XMLHttpRequest(); } + ]; + for (var i = factories.length; i--; ) { + try { + var req = factories[i](); + if (req) { + return factories[i]; + } + } + catch (err) { } + } + })(); + + function emptyFn() { } + + /** + * Cross-browser abstraction for sending XMLHttpRequest + * @memberOf fabric.util + * @param {String} url URL to send XMLHttpRequest to + * @param {Object} [options] Options object + * @param {String} [options.method="GET"] + * @param {Function} options.onComplete Callback to invoke when request is completed + * @return {XMLHttpRequest} request + */ + function request(url, options) { + + options || (options = { }); + + var method = options.method ? options.method.toUpperCase() : 'GET', + onComplete = options.onComplete || function() { }, + xhr = makeXHR(), + body; + + /** @ignore */ + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + onComplete(xhr); + xhr.onreadystatechange = emptyFn; + } + }; + + if (method === 'GET') { + body = null; + if (typeof options.parameters === 'string') { + url = addParamToUrl(url, options.parameters); + } + } + + xhr.open(method, url, true); + + if (method === 'POST' || method === 'PUT') { + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + } + + xhr.send(body); + return xhr; + } + + fabric.util.request = request; +})(); + + +/** + * Wrapper around `console.log` (when available) + * @param {Any} [values] Values to log + */ +fabric.log = function() { }; + +/** + * Wrapper around `console.warn` (when available) + * @param {Any} [values] Values to log as a warning + */ +fabric.warn = function() { }; + +if (typeof console !== 'undefined') { + ['log', 'warn'].forEach(function(methodName) { + if (typeof console[methodName] !== 'undefined' && console[methodName].apply) { + fabric[methodName] = function() { + return console[methodName].apply(console, arguments); + }; + } + }); +} + + +(function() { + + /** + * Changes value from one to another within certain period of time, invoking callbacks as value is being changed. + * @memberOf fabric.util + * @param {Object} [options] Animation options + * @param {Function} [options.onChange] Callback; invoked on every value change + * @param {Function} [options.onComplete] Callback; invoked when value change is completed + * @param {Number} [options.startValue=0] Starting value + * @param {Number} [options.endValue=100] Ending value + * @param {Number} [options.byValue=100] Value to modify the property by + * @param {Function} [options.easing] Easing function + * @param {Number} [options.duration=500] Duration of change (in ms) + */ + function animate(options) { + + requestAnimFrame(function(timestamp) { + options || (options = { }); + + var start = timestamp || +new Date(), + duration = options.duration || 500, + finish = start + duration, time, + onChange = options.onChange || function() { }, + abort = options.abort || function() { return false; }, + easing = options.easing || function(t, b, c, d) {return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;}, + startValue = 'startValue' in options ? options.startValue : 0, + endValue = 'endValue' in options ? options.endValue : 100, + byValue = options.byValue || endValue - startValue; + + options.onStart && options.onStart(); + + (function tick(ticktime) { + time = ticktime || +new Date(); + var currentTime = time > finish ? duration : (time - start); + if (abort()) { + options.onComplete && options.onComplete(); + return; + } + onChange(easing(currentTime, startValue, byValue, duration)); + if (time > finish) { + options.onComplete && options.onComplete(); + return; + } + requestAnimFrame(tick); + })(start); + }); + + } + + var _requestAnimFrame = fabric.window.requestAnimationFrame || + fabric.window.webkitRequestAnimationFrame || + fabric.window.mozRequestAnimationFrame || + fabric.window.oRequestAnimationFrame || + fabric.window.msRequestAnimationFrame || + function(callback) { + fabric.window.setTimeout(callback, 1000 / 60); + }; + /** + * requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + * In order to get a precise start time, `requestAnimFrame` should be called as an entry into the method + * @memberOf fabric.util + * @param {Function} callback Callback to invoke + * @param {DOMElement} element optional Element to associate with animation + */ + function requestAnimFrame() { + return _requestAnimFrame.apply(fabric.window, arguments); + } + + fabric.util.animate = animate; + fabric.util.requestAnimFrame = requestAnimFrame; + +})(); + + +(function() { + + function normalize(a, c, p, s) { + if (a < Math.abs(c)) { + a = c; + s = p / 4; + } + else { + s = p / (2 * Math.PI) * Math.asin(c / a); + } + return { a: a, c: c, p: p, s: s }; + } + + function elastic(opts, t, d) { + return opts.a * + Math.pow(2, 10 * (t -= 1)) * + Math.sin( (t * d - opts.s) * (2 * Math.PI) / opts.p ); + } + + /** + * Cubic easing out + * @memberOf fabric.util.ease + */ + function easeOutCubic(t, b, c, d) { + return c * ((t = t / d - 1) * t * t + 1) + b; + } + + /** + * Cubic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutCubic(t, b, c, d) { + t /= d/2; + if (t < 1) { + return c / 2 * t * t * t + b; + } + return c / 2 * ((t -= 2) * t * t + 2) + b; + } + + /** + * Quartic easing in + * @memberOf fabric.util.ease + */ + function easeInQuart(t, b, c, d) { + return c * (t /= d) * t * t * t + b; + } + + /** + * Quartic easing out + * @memberOf fabric.util.ease + */ + function easeOutQuart(t, b, c, d) { + return -c * ((t = t / d - 1) * t * t * t - 1) + b; + } + + /** + * Quartic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutQuart(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return c / 2 * t * t * t * t + b; + } + return -c / 2 * ((t -= 2) * t * t * t - 2) + b; + } + + /** + * Quintic easing in + * @memberOf fabric.util.ease + */ + function easeInQuint(t, b, c, d) { + return c * (t /= d) * t * t * t * t + b; + } + + /** + * Quintic easing out + * @memberOf fabric.util.ease + */ + function easeOutQuint(t, b, c, d) { + return c * ((t = t / d - 1) * t * t * t * t + 1) + b; + } + + /** + * Quintic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutQuint(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return c / 2 * t * t * t * t * t + b; + } + return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; + } + + /** + * Sinusoidal easing in + * @memberOf fabric.util.ease + */ + function easeInSine(t, b, c, d) { + return -c * Math.cos(t / d * (Math.PI / 2)) + c + b; + } + + /** + * Sinusoidal easing out + * @memberOf fabric.util.ease + */ + function easeOutSine(t, b, c, d) { + return c * Math.sin(t / d * (Math.PI / 2)) + b; + } + + /** + * Sinusoidal easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutSine(t, b, c, d) { + return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b; + } + + /** + * Exponential easing in + * @memberOf fabric.util.ease + */ + function easeInExpo(t, b, c, d) { + return (t === 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b; + } + + /** + * Exponential easing out + * @memberOf fabric.util.ease + */ + function easeOutExpo(t, b, c, d) { + return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b; + } + + /** + * Exponential easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutExpo(t, b, c, d) { + if (t === 0) { + return b; + } + if (t === d) { + return b + c; + } + t /= d / 2; + if (t < 1) { + return c / 2 * Math.pow(2, 10 * (t - 1)) + b; + } + return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b; + } + + /** + * Circular easing in + * @memberOf fabric.util.ease + */ + function easeInCirc(t, b, c, d) { + return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b; + } + + /** + * Circular easing out + * @memberOf fabric.util.ease + */ + function easeOutCirc(t, b, c, d) { + return c * Math.sqrt(1 - (t = t / d - 1) * t) + b; + } + + /** + * Circular easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutCirc(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b; + } + return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b; + } + + /** + * Elastic easing in + * @memberOf fabric.util.ease + */ + function easeInElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d; + if (t === 1) { + return b + c; + } + if (!p) { + p = d * 0.3; + } + var opts = normalize(a, c, p, s); + return -elastic(opts, t, d) + b; + } + + /** + * Elastic easing out + * @memberOf fabric.util.ease + */ + function easeOutElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d; + if (t === 1) { + return b + c; + } + if (!p) { + p = d * 0.3; + } + var opts = normalize(a, c, p, s); + return opts.a * Math.pow(2, -10 * t) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) + opts.c + b; + } + + /** + * Elastic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d / 2; + if (t === 2) { + return b + c; + } + if (!p) { + p = d * (0.3 * 1.5); + } + var opts = normalize(a, c, p, s); + if (t < 1) { + return -0.5 * elastic(opts, t, d) + b; + } + return opts.a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) * 0.5 + opts.c + b; + } + + /** + * Backwards easing in + * @memberOf fabric.util.ease + */ + function easeInBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + return c * (t /= d) * t * ((s + 1) * t - s) + b; + } + + /** + * Backwards easing out + * @memberOf fabric.util.ease + */ + function easeOutBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; + } + + /** + * Backwards easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + t /= d / 2; + if (t < 1) { + return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b; + } + return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b; + } + + /** + * Bouncing easing in + * @memberOf fabric.util.ease + */ + function easeInBounce(t, b, c, d) { + return c - easeOutBounce (d - t, 0, c, d) + b; + } + + /** + * Bouncing easing out + * @memberOf fabric.util.ease + */ + function easeOutBounce(t, b, c, d) { + if ((t /= d) < (1 / 2.75)) { + return c * (7.5625 * t * t) + b; + } + else if (t < (2/2.75)) { + return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b; + } + else if (t < (2.5/2.75)) { + return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b; + } + else { + return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b; + } + } + + /** + * Bouncing easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutBounce(t, b, c, d) { + if (t < d / 2) { + return easeInBounce (t * 2, 0, c, d) * 0.5 + b; + } + return easeOutBounce(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b; + } + + /** + * Easing functions + * See Easing Equations by Robert Penner + * @namespace fabric.util.ease + */ + fabric.util.ease = { + + /** + * Quadratic easing in + * @memberOf fabric.util.ease + */ + easeInQuad: function(t, b, c, d) { + return c * (t /= d) * t + b; + }, + + /** + * Quadratic easing out + * @memberOf fabric.util.ease + */ + easeOutQuad: function(t, b, c, d) { + return -c * (t /= d) * (t - 2) + b; + }, + + /** + * Quadratic easing in and out + * @memberOf fabric.util.ease + */ + easeInOutQuad: function(t, b, c, d) { + t /= (d / 2); + if (t < 1) { + return c / 2 * t * t + b; + } + return -c / 2 * ((--t) * (t - 2) - 1) + b; + }, + + /** + * Cubic easing in + * @memberOf fabric.util.ease + */ + easeInCubic: function(t, b, c, d) { + return c * (t /= d) * t * t + b; + }, + + easeOutCubic: easeOutCubic, + easeInOutCubic: easeInOutCubic, + easeInQuart: easeInQuart, + easeOutQuart: easeOutQuart, + easeInOutQuart: easeInOutQuart, + easeInQuint: easeInQuint, + easeOutQuint: easeOutQuint, + easeInOutQuint: easeInOutQuint, + easeInSine: easeInSine, + easeOutSine: easeOutSine, + easeInOutSine: easeInOutSine, + easeInExpo: easeInExpo, + easeOutExpo: easeOutExpo, + easeInOutExpo: easeInOutExpo, + easeInCirc: easeInCirc, + easeOutCirc: easeOutCirc, + easeInOutCirc: easeInOutCirc, + easeInElastic: easeInElastic, + easeOutElastic: easeOutElastic, + easeInOutElastic: easeInOutElastic, + easeInBack: easeInBack, + easeOutBack: easeOutBack, + easeInOutBack: easeInOutBack, + easeInBounce: easeInBounce, + easeOutBounce: easeOutBounce, + easeInOutBounce: easeInOutBounce + }; + +}()); + + +(function(global) { + + 'use strict'; + + /** + * @name fabric + * @namespace + */ + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + capitalize = fabric.util.string.capitalize, + clone = fabric.util.object.clone, + toFixed = fabric.util.toFixed, + parseUnit = fabric.util.parseUnit, + multiplyTransformMatrices = fabric.util.multiplyTransformMatrices, + + attributesMap = { + cx: 'left', + x: 'left', + r: 'radius', + cy: 'top', + y: 'top', + display: 'visible', + visibility: 'visible', + transform: 'transformMatrix', + 'fill-opacity': 'fillOpacity', + 'fill-rule': 'fillRule', + 'font-family': 'fontFamily', + 'font-size': 'fontSize', + 'font-style': 'fontStyle', + 'font-weight': 'fontWeight', + 'stroke-dasharray': 'strokeDashArray', + 'stroke-linecap': 'strokeLineCap', + 'stroke-linejoin': 'strokeLineJoin', + 'stroke-miterlimit': 'strokeMiterLimit', + 'stroke-opacity': 'strokeOpacity', + 'stroke-width': 'strokeWidth', + 'text-decoration': 'textDecoration', + 'text-anchor': 'originX' + }, + + colorAttributes = { + stroke: 'strokeOpacity', + fill: 'fillOpacity' + }; + + function normalizeAttr(attr) { + // transform attribute names + if (attr in attributesMap) { + return attributesMap[attr]; + } + return attr; + } + + function normalizeValue(attr, value, parentAttributes) { + var isArray = Object.prototype.toString.call(value) === '[object Array]', + parsed; + + if ((attr === 'fill' || attr === 'stroke') && value === 'none') { + value = ''; + } + else if (attr === 'fillRule') { + value = (value === 'evenodd') ? 'destination-over' : value; + } + else if (attr === 'strokeDashArray') { + value = value.replace(/,/g, ' ').split(/\s+/).map(function(n) { + return parseInt(n); + }); + } + else if (attr === 'transformMatrix') { + if (parentAttributes && parentAttributes.transformMatrix) { + value = multiplyTransformMatrices( + parentAttributes.transformMatrix, fabric.parseTransformAttribute(value)); + } + else { + value = fabric.parseTransformAttribute(value); + } + } + else if (attr === 'visible') { + value = (value === 'none' || value === 'hidden') ? false : true; + // display=none on parent element always takes precedence over child element + if (parentAttributes && parentAttributes.visible === false) { + value = false; + } + } + else if (attr === 'originX' /* text-anchor */) { + value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center'; + } + else { + parsed = isArray ? value.map(parseUnit) : parseUnit(value); + } + + return (!isArray && isNaN(parsed) ? value : parsed); + } + + /** + * @private + * @param {Object} attributes Array of attributes to parse + */ + function _setStrokeFillOpacity(attributes) { + for (var attr in colorAttributes) { + + if (!attributes[attr] || typeof attributes[colorAttributes[attr]] === 'undefined') { + continue; + } + + if (attributes[attr].indexOf('url(') === 0) { + continue; + } + + var color = new fabric.Color(attributes[attr]); + attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba(); + } + return attributes; + } + + /** + * Parses "transform" attribute, returning an array of values + * @static + * @function + * @memberOf fabric + * @param {String} attributeValue String containing attribute value + * @return {Array} Array of 6 elements representing transformation matrix + */ + fabric.parseTransformAttribute = (function() { + function rotateMatrix(matrix, args) { + var angle = args[0]; + + matrix[0] = Math.cos(angle); + matrix[1] = Math.sin(angle); + matrix[2] = -Math.sin(angle); + matrix[3] = Math.cos(angle); + } + + function scaleMatrix(matrix, args) { + var multiplierX = args[0], + multiplierY = (args.length === 2) ? args[1] : args[0]; + + matrix[0] = multiplierX; + matrix[3] = multiplierY; + } + + function skewXMatrix(matrix, args) { + matrix[2] = args[0]; + } + + function skewYMatrix(matrix, args) { + matrix[1] = args[0]; + } + + function translateMatrix(matrix, args) { + matrix[4] = args[0]; + if (args.length === 2) { + matrix[5] = args[1]; + } + } + + // identity matrix + var iMatrix = [ + 1, // a + 0, // b + 0, // c + 1, // d + 0, // e + 0 // f + ], + + // == begin transform regexp + number = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)', + + commaWsp = '(?:\\s+,?\\s*|,\\s*)', + + skewX = '(?:(skewX)\\s*\\(\\s*(' + number + ')\\s*\\))', + + skewY = '(?:(skewY)\\s*\\(\\s*(' + number + ')\\s*\\))', + + rotate = '(?:(rotate)\\s*\\(\\s*(' + number + ')(?:' + + commaWsp + '(' + number + ')' + + commaWsp + '(' + number + '))?\\s*\\))', + + scale = '(?:(scale)\\s*\\(\\s*(' + number + ')(?:' + + commaWsp + '(' + number + '))?\\s*\\))', + + translate = '(?:(translate)\\s*\\(\\s*(' + number + ')(?:' + + commaWsp + '(' + number + '))?\\s*\\))', + + matrix = '(?:(matrix)\\s*\\(\\s*' + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + + '\\s*\\))', + + transform = '(?:' + + matrix + '|' + + translate + '|' + + scale + '|' + + rotate + '|' + + skewX + '|' + + skewY + + ')', + + transforms = '(?:' + transform + '(?:' + commaWsp + transform + ')*' + ')', + + transformList = '^\\s*(?:' + transforms + '?)\\s*$', + + // http://www.w3.org/TR/SVG/coords.html#TransformAttribute + reTransformList = new RegExp(transformList), + // == end transform regexp + + reTransform = new RegExp(transform, 'g'); + + return function(attributeValue) { + + // start with identity matrix + var matrix = iMatrix.concat(), + matrices = [ ]; + + // return if no argument was given or + // an argument does not match transform attribute regexp + if (!attributeValue || (attributeValue && !reTransformList.test(attributeValue))) { + return matrix; + } + + attributeValue.replace(reTransform, function(match) { + + var m = new RegExp(transform).exec(match).filter(function (match) { + return (match !== '' && match != null); + }), + operation = m[1], + args = m.slice(2).map(parseFloat); + + switch (operation) { + case 'translate': + translateMatrix(matrix, args); + break; + case 'rotate': + args[0] = fabric.util.degreesToRadians(args[0]); + rotateMatrix(matrix, args); + break; + case 'scale': + scaleMatrix(matrix, args); + break; + case 'skewX': + skewXMatrix(matrix, args); + break; + case 'skewY': + skewYMatrix(matrix, args); + break; + case 'matrix': + matrix = args; + break; + } + + // snapshot current matrix into matrices array + matrices.push(matrix.concat()); + // reset + matrix = iMatrix.concat(); + }); + + var combinedMatrix = matrices[0]; + while (matrices.length > 1) { + matrices.shift(); + combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]); + } + return combinedMatrix; + }; + })(); + + function parseFontDeclaration(value, oStyle) { + + // TODO: support non-px font size + var match = value.match(/(normal|italic)?\s*(normal|small-caps)?\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\s*(\d+)px(?:\/(normal|[\d\.]+))?\s+(.*)/); + + if (!match) { + return; + } + + var fontStyle = match[1], + // font variant is not used + // fontVariant = match[2], + fontWeight = match[3], + fontSize = match[4], + lineHeight = match[5], + fontFamily = match[6]; + + if (fontStyle) { + oStyle.fontStyle = fontStyle; + } + if (fontWeight) { + oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight); + } + if (fontSize) { + oStyle.fontSize = parseFloat(fontSize); + } + if (fontFamily) { + oStyle.fontFamily = fontFamily; + } + if (lineHeight) { + oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight; + } + } + + /** + * @private + */ + function parseStyleString(style, oStyle) { + var attr, value; + style.replace(/;$/, '').split(';').forEach(function (chunk) { + var pair = chunk.split(':'); + + attr = normalizeAttr(pair[0].trim().toLowerCase()); + value = normalizeValue(attr, pair[1].trim()); + + if (attr === 'font') { + parseFontDeclaration(value, oStyle); + } + else { + oStyle[attr] = value; + } + }); + } + + /** + * @private + */ + function parseStyleObject(style, oStyle) { + var attr, value; + for (var prop in style) { + if (typeof style[prop] === 'undefined') { + continue; + } + + attr = normalizeAttr(prop.toLowerCase()); + value = normalizeValue(attr, style[prop]); + + if (attr === 'font') { + parseFontDeclaration(value, oStyle); + } + else { + oStyle[attr] = value; + } + } + } + + /** + * @private + */ + function getGlobalStylesForElement(element) { + var styles = { }; + + for (var rule in fabric.cssRules) { + if (elementMatchesRule(element, rule.split(' '))) { + for (var property in fabric.cssRules[rule]) { + styles[property] = fabric.cssRules[rule][property]; + } + } + } + return styles; + } + + /** + * @private + */ + function elementMatchesRule(element, selectors) { + var firstMatching, parentMatching = true; + //start from rightmost selector. + firstMatching = selectorMatches(element, selectors.pop()); + if (firstMatching && selectors.length) { + parentMatching = doesSomeParentMatch(element, selectors); + } + return firstMatching && parentMatching && (selectors.length === 0); + } + + function doesSomeParentMatch(element, selectors) { + var selector, parentMatching = true; + while (element.parentNode && element.parentNode.nodeType === 1 && selectors.length) { + if (parentMatching) { + selector = selectors.pop(); + } + element = element.parentNode; + parentMatching = selectorMatches(element, selector); + } + return selectors.length === 0; + } + /** + * @private + */ + function selectorMatches(element, selector) { + var nodeName = element.nodeName, + classNames = element.getAttribute('class'), + id = element.getAttribute('id'), matcher; + // i check if a selector matches slicing away part from it. + // if i get empty string i should match + matcher = new RegExp('^' + nodeName, 'i'); + selector = selector.replace(matcher, ''); + if (id && selector.length) { + matcher = new RegExp('#' + id + '(?![a-zA-Z\\-]+)', 'i'); + selector = selector.replace(matcher, ''); + } + if (classNames && selector.length) { + classNames = classNames.split(' '); + for (var i = classNames.length; i--;) { + matcher = new RegExp('\\.' + classNames[i] + '(?![a-zA-Z\\-]+)', 'i'); + selector = selector.replace(matcher, ''); + } + } + return selector.length === 0; + } + + /** + * @private + */ + function parseUseDirectives(doc) { + var nodelist = doc.getElementsByTagName('use'); + while (nodelist.length) { + var el = nodelist[0], + xlink = el.getAttribute('xlink:href').substr(1), + x = el.getAttribute('x') || 0, + y = el.getAttribute('y') || 0, + el2 = doc.getElementById(xlink).cloneNode(true), + currentTrans = (el.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')', + parentNode; + + for (var j = 0, attrs = el.attributes, l = attrs.length; j < l; j++) { + var attr = attrs.item(j); + if (attr.nodeName === 'x' || attr.nodeName === 'y' || attr.nodeName === 'xlink:href') { + continue; + } + + if (attr.nodeName === 'transform') { + currentTrans = currentTrans + ' ' + attr.nodeValue; + } + else { + el2.setAttribute(attr.nodeName, attr.nodeValue); + } + } + + el2.setAttribute('transform', currentTrans); + el2.removeAttribute('id'); + parentNode = el.parentNode; + parentNode.replaceChild(el2, el); + } + } + + /** + * Add a element that envelop all SCG elements and makes the viewbox transformMatrix descend on all elements + */ + function addSvgTransform(doc, matrix) { + matrix[3] = matrix[0] = (matrix[0] > matrix[3] ? matrix[3] : matrix[0]); + if (!(matrix[0] !== 1 || matrix[3] !== 1 || matrix[4] !== 0 || matrix[5] !== 0)) { + return; + } + // default is to preserve aspect ratio + // preserveAspectRatio attribute to be implemented + var el = doc.ownerDocument.createElement('g'); + while (doc.firstChild != null) { + el.appendChild(doc.firstChild); + } + el.setAttribute('transform','matrix(' + matrix[0] + ' ' + matrix[1] + ' ' + matrix[2] + ' ' + matrix[3] + ' ' + matrix[4] + ' ' + matrix[5] + ')'); + doc.appendChild(el); + } + + /** + * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @param {Function} callback Callback to call when parsing is finished; It's being passed an array of elements (parsed from a document). + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + fabric.parseSVGDocument = (function() { + + var reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/, + + // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute + // \d doesn't quite cut it (as we need to match an actual float number) + + // matches, e.g.: +14.56e-12, etc. + reNum = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)', + + reViewBoxAttrValue = new RegExp( + '^' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*' + + '$' + ); + + function hasAncestorWithNodeName(element, nodeName) { + while (element && (element = element.parentNode)) { + if (nodeName.test(element.nodeName)) { + return true; + } + } + return false; + } + + return function(doc, callback, reviver) { + if (!doc) { + return; + } + var startTime = new Date(); + + parseUseDirectives(doc); + + var viewBoxAttr = doc.getAttribute('viewBox'), + widthAttr = parseUnit(doc.getAttribute('width')), + heightAttr = parseUnit(doc.getAttribute('height')), + viewBoxWidth, + viewBoxHeight; + + if (viewBoxAttr && (viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))) { + var minX = parseFloat(viewBoxAttr[1]), + minY = parseFloat(viewBoxAttr[2]), + scaleX = 1, scaleY = 1; + viewBoxWidth = parseFloat(viewBoxAttr[3]); + viewBoxHeight = parseFloat(viewBoxAttr[4]); + if (widthAttr && widthAttr !== viewBoxWidth ) { + scaleX = widthAttr / viewBoxWidth; + } + if (heightAttr && heightAttr !== viewBoxHeight) { + scaleY = heightAttr / viewBoxHeight; + } + addSvgTransform(doc, [scaleX, 0, 0, scaleY, scaleX * -minX, scaleY * -minY]); + } + + var descendants = fabric.util.toArray(doc.getElementsByTagName('*')); + + if (descendants.length === 0 && fabric.isLikelyNode) { + // we're likely in node, where "o3-xml" library fails to gEBTN("*") + // https://github.com/ajaxorg/node-o3-xml/issues/21 + descendants = doc.selectNodes('//*[name(.)!="svg"]'); + var arr = [ ]; + for (var i = 0, len = descendants.length; i < len; i++) { + arr[i] = descendants[i]; + } + descendants = arr; + } + + var elements = descendants.filter(function(el) { + return reAllowedSVGTagNames.test(el.tagName) && + !hasAncestorWithNodeName(el, /^(?:pattern|defs)$/); // http://www.w3.org/TR/SVG/struct.html#DefsElement + }); + + if (!elements || (elements && !elements.length)) { + callback && callback([], {}); + return; + } + + var options = { + width: widthAttr ? widthAttr : viewBoxWidth, + height: heightAttr ? heightAttr : viewBoxHeight, + widthAttr: widthAttr, + heightAttr: heightAttr + }; + + fabric.gradientDefs = fabric.getGradientDefs(doc); + fabric.cssRules = fabric.getCSSRules(doc); + // Precedence of rules: style > class > attribute + + fabric.parseElements(elements, function(instances) { + fabric.documentParsingTime = new Date() - startTime; + if (callback) { + callback(instances, options); + } + }, clone(options), reviver); + }; + })(); + + /** + * Used for caching SVG documents (loaded via `fabric.Canvas#loadSVGFromURL`) + * @namespace + */ + var svgCache = { + + /** + * @param {String} name + * @param {Function} callback + */ + has: function (name, callback) { + callback(false); + }, + + get: function () { + /* NOOP */ + }, + + set: function () { + /* NOOP */ + } + }; + + /** + * @private + */ + function _enlivenCachedObject(cachedObject) { + + var objects = cachedObject.objects, + options = cachedObject.options; + + objects = objects.map(function (o) { + return fabric[capitalize(o.type)].fromObject(o); + }); + + return ({ objects: objects, options: options }); + } + + /** + * @private + */ + function _createSVGPattern(markup, canvas, property) { + if (canvas[property] && canvas[property].toSVG) { + markup.push( + '', + '' + ); + } + } + + extend(fabric, { + + /** + * Parses an SVG document, returning all of the gradient declarations found in it + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element + */ + getGradientDefs: function(doc) { + var linearGradientEls = doc.getElementsByTagName('linearGradient'), + radialGradientEls = doc.getElementsByTagName('radialGradient'), + el, i, j = 0, id, xlink, elList = [ ], + gradientDefs = { }, idsToXlinkMap = { }; + + elList.length = linearGradientEls.length + radialGradientEls.length; + i = linearGradientEls.length; + while (i--) { + elList[j++] = linearGradientEls[i]; + } + i = radialGradientEls.length; + while (i--) { + elList[j++] = radialGradientEls[i]; + } + + while (j--) { + el = elList[j]; + xlink = el.getAttribute('xlink:href'); + id = el.getAttribute('id'); + if (xlink) { + idsToXlinkMap[id] = xlink.substr(1); + } + gradientDefs[id] = el; + } + + for (id in idsToXlinkMap) { + var el2 = gradientDefs[idsToXlinkMap[id]].cloneNode(true); + el = gradientDefs[id]; + while (el2.firstChild) { + el.appendChild(el2.firstChild); + } + } + return gradientDefs; + }, + + /** + * Returns an object of attributes' name/value, given element and an array of attribute names; + * Parses parent "g" nodes recursively upwards. + * @static + * @memberOf fabric + * @param {DOMElement} element Element to parse + * @param {Array} attributes Array of attributes to parse + * @return {Object} object containing parsed attributes' names/values + */ + parseAttributes: function(element, attributes) { + + if (!element) { + return; + } + + var value, + parentAttributes = { }; + + // if there's a parent container (`g` or `a` or `symbol` node), parse its attributes recursively upwards + if (element.parentNode && /^symbol|[g|a]$/i.test(element.parentNode.nodeName)) { + parentAttributes = fabric.parseAttributes(element.parentNode, attributes); + } + + var ownAttributes = attributes.reduce(function(memo, attr) { + value = element.getAttribute(attr); + if (value) { + attr = normalizeAttr(attr); + value = normalizeValue(attr, value, parentAttributes); + + memo[attr] = value; + } + return memo; + }, { }); + + // add values parsed from style, which take precedence over attributes + // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes) + ownAttributes = extend(ownAttributes, + extend(getGlobalStylesForElement(element), fabric.parseStyleAttribute(element))); + + return _setStrokeFillOpacity(extend(parentAttributes, ownAttributes)); + }, + + /** + * Transforms an array of svg elements to corresponding fabric.* instances + * @static + * @memberOf fabric + * @param {Array} elements Array of elements to parse + * @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements) + * @param {Object} [options] Options object + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + parseElements: function(elements, callback, options, reviver) { + new fabric.ElementsParser(elements, callback, options, reviver).parse(); + }, + + /** + * Parses "style" attribute, retuning an object with values + * @static + * @memberOf fabric + * @param {SVGElement} element Element to parse + * @return {Object} Objects with values parsed from style attribute of an element + */ + parseStyleAttribute: function(element) { + var oStyle = { }, + style = element.getAttribute('style'); + + if (!style) { + return oStyle; + } + + if (typeof style === 'string') { + parseStyleString(style, oStyle); + } + else { + parseStyleObject(style, oStyle); + } + + return oStyle; + }, + + /** + * Parses "points" attribute, returning an array of values + * @static + * @memberOf fabric + * @param {String} points points attribute string + * @return {Array} array of points + */ + parsePointsAttribute: function(points) { + + // points attribute is required and must not be empty + if (!points) { + return null; + } + + // replace commas with whitespace and remove bookending whitespace + points = points.replace(/,/g, ' ').trim(); + + points = points.split(/\s+/); + var parsedPoints = [ ], i, len; + + i = 0; + len = points.length; + for (; i < len; i+=2) { + parsedPoints.push({ + x: parseFloat(points[i]), + y: parseFloat(points[i + 1]) + }); + } + + // odd number of points is an error + // if (parsedPoints.length % 2 !== 0) { + // return null; + // } + + return parsedPoints; + }, + + /** + * Returns CSS rules for a given SVG document + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @return {Object} CSS rules of this document + */ + getCSSRules: function(doc) { + var styles = doc.getElementsByTagName('style'), + allRules = { }, rules; + + // very crude parsing of style contents + for (var i = 0, len = styles.length; i < len; i++) { + var styleContents = styles[0].textContent; + + // remove comments + styleContents = styleContents.replace(/\/\*[\s\S]*?\*\//g, ''); + + rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g); + rules = rules.map(function(rule) { return rule.trim(); }); + + rules.forEach(function(rule) { + + var match = rule.match(/([\s\S]*?)\s*\{([^}]*)\}/), + ruleObj = { }, declaration = match[2].trim(), + propertyValuePairs = declaration.replace(/;$/, '').split(/\s*;\s*/); + + for (var i = 0, len = propertyValuePairs.length; i < len; i++) { + var pair = propertyValuePairs[i].split(/\s*:\s*/), + property = normalizeAttr(pair[0]), + value = normalizeValue(property,pair[1],pair[0]); + ruleObj[property] = value; + } + rule = match[1]; + rule.split(',').forEach(function(_rule) { + allRules[_rule.trim()] = fabric.util.object.clone(ruleObj); + }); + }); + } + return allRules; + }, + + /** + * Takes url corresponding to an SVG document, and parses it into a set of fabric objects. Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy) + * @memberof fabric + * @param {String} url + * @param {Function} callback + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + loadSVGFromURL: function(url, callback, reviver) { + + url = url.replace(/^\n\s*/, '').trim(); + svgCache.has(url, function (hasUrl) { + if (hasUrl) { + svgCache.get(url, function (value) { + var enlivedRecord = _enlivenCachedObject(value); + callback(enlivedRecord.objects, enlivedRecord.options); + }); + } + else { + new fabric.util.request(url, { + method: 'get', + onComplete: onComplete + }); + } + }); + + function onComplete(r) { + + var xml = r.responseXML; + if (xml && !xml.documentElement && fabric.window.ActiveXObject && r.responseText) { + xml = new ActiveXObject('Microsoft.XMLDOM'); + xml.async = 'false'; + //IE chokes on DOCTYPE + xml.loadXML(r.responseText.replace(//i,'')); + } + if (!xml || !xml.documentElement) { + return; + } + + fabric.parseSVGDocument(xml.documentElement, function (results, options) { + svgCache.set(url, { + objects: fabric.util.array.invoke(results, 'toObject'), + options: options + }); + callback(results, options); + }, reviver); + } + }, + + /** + * Takes string corresponding to an SVG document, and parses it into a set of fabric objects + * @memberof fabric + * @param {String} string + * @param {Function} callback + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + loadSVGFromString: function(string, callback, reviver) { + string = string.trim(); + var doc; + if (typeof DOMParser !== 'undefined') { + var parser = new DOMParser(); + if (parser && parser.parseFromString) { + doc = parser.parseFromString(string, 'text/xml'); + } + } + else if (fabric.window.ActiveXObject) { + doc = new ActiveXObject('Microsoft.XMLDOM'); + doc.async = 'false'; + //IE chokes on DOCTYPE + doc.loadXML(string.replace(//i,'')); + } + + fabric.parseSVGDocument(doc.documentElement, function (results, options) { + callback(results, options); + }, reviver); + }, + + /** + * Creates markup containing SVG font faces + * @param {Array} objects Array of fabric objects + * @return {String} + */ + createSVGFontFacesMarkup: function(objects) { + var markup = ''; + + for (var i = 0, len = objects.length; i < len; i++) { + if (objects[i].type !== 'text' || !objects[i].path) { + continue; + } + + markup += [ + //jscs:disable validateIndentation + '@font-face {', + 'font-family: ', objects[i].fontFamily, '; ', + 'src: url(\'', objects[i].path, '\')', + '}' + //jscs:enable validateIndentation + ].join(''); + } + + if (markup) { + markup = [ + //jscs:disable validateIndentation + '' + //jscs:enable validateIndentation + ].join(''); + } + + return markup; + }, + + /** + * Creates markup containing SVG referenced elements like patterns, gradients etc. + * @param {fabric.Canvas} canvas instance of fabric.Canvas + * @return {String} + */ + createSVGRefElementsMarkup: function(canvas) { + var markup = [ ]; + + _createSVGPattern(markup, canvas, 'backgroundColor'); + _createSVGPattern(markup, canvas, 'overlayColor'); + + return markup.join(''); + } + }); + +})(typeof exports !== 'undefined' ? exports : this); + + +fabric.ElementsParser = function(elements, callback, options, reviver) { + this.elements = elements; + this.callback = callback; + this.options = options; + this.reviver = reviver; +}; + +fabric.ElementsParser.prototype.parse = function() { + this.instances = new Array(this.elements.length); + this.numElements = this.elements.length; + + this.createObjects(); +}; + +fabric.ElementsParser.prototype.createObjects = function() { + for (var i = 0, len = this.elements.length; i < len; i++) { + (function(_this, i) { + setTimeout(function() { + _this.createObject(_this.elements[i], i); + }, 0); + })(this, i); + } +}; + +fabric.ElementsParser.prototype.createObject = function(el, index) { + var klass = fabric[fabric.util.string.capitalize(el.tagName)]; + if (klass && klass.fromElement) { + try { + this._createObject(klass, el, index); + } + catch (err) { + fabric.log(err); + } + } + else { + this.checkIfDone(); + } +}; + +fabric.ElementsParser.prototype._createObject = function(klass, el, index) { + if (klass.async) { + klass.fromElement(el, this.createCallback(index, el), this.options); + } + else { + var obj = klass.fromElement(el, this.options); + this.resolveGradient(obj, 'fill'); + this.resolveGradient(obj, 'stroke'); + this.reviver && this.reviver(el, obj); + this.instances[index] = obj; + this.checkIfDone(); + } +}; + +fabric.ElementsParser.prototype.createCallback = function(index, el) { + var _this = this; + return function(obj) { + _this.resolveGradient(obj, 'fill'); + _this.resolveGradient(obj, 'stroke'); + _this.reviver && _this.reviver(el, obj); + _this.instances[index] = obj; + _this.checkIfDone(); + }; +}; + +fabric.ElementsParser.prototype.resolveGradient = function(obj, property) { + + var instanceFillValue = obj.get(property); + if (!(/^url\(/).test(instanceFillValue)) { + return; + } + var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1); + if (fabric.gradientDefs[gradientId]) { + obj.set(property, + fabric.Gradient.fromElement(fabric.gradientDefs[gradientId], obj)); + } +}; + +fabric.ElementsParser.prototype.checkIfDone = function() { + if (--this.numElements === 0) { + this.instances = this.instances.filter(function(el) { + return el != null; + }); + this.callback(this.instances); + } +}; + + +(function(global) { + + 'use strict'; + + /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Point) { + fabric.warn('fabric.Point is already defined'); + return; + } + + fabric.Point = Point; + + /** + * Point class + * @class fabric.Point + * @memberOf fabric + * @constructor + * @param {Number} x + * @param {Number} y + * @return {fabric.Point} thisArg + */ + function Point(x, y) { + this.x = x; + this.y = y; + } + + Point.prototype = /** @lends fabric.Point.prototype */ { + + constructor: Point, + + /** + * Adds another point to this one and returns another one + * @param {fabric.Point} that + * @return {fabric.Point} new Point instance with added values + */ + add: function (that) { + return new Point(this.x + that.x, this.y + that.y); + }, + + /** + * Adds another point to this one + * @param {fabric.Point} that + * @return {fabric.Point} thisArg + */ + addEquals: function (that) { + this.x += that.x; + this.y += that.y; + return this; + }, + + /** + * Adds value to this point and returns a new one + * @param {Number} scalar + * @return {fabric.Point} new Point with added value + */ + scalarAdd: function (scalar) { + return new Point(this.x + scalar, this.y + scalar); + }, + + /** + * Adds value to this point + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + scalarAddEquals: function (scalar) { + this.x += scalar; + this.y += scalar; + return this; + }, + + /** + * Subtracts another point from this point and returns a new one + * @param {fabric.Point} that + * @return {fabric.Point} new Point object with subtracted values + */ + subtract: function (that) { + return new Point(this.x - that.x, this.y - that.y); + }, + + /** + * Subtracts another point from this point + * @param {fabric.Point} that + * @return {fabric.Point} thisArg + */ + subtractEquals: function (that) { + this.x -= that.x; + this.y -= that.y; + return this; + }, + + /** + * Subtracts value from this point and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + scalarSubtract: function (scalar) { + return new Point(this.x - scalar, this.y - scalar); + }, + + /** + * Subtracts value from this point + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + scalarSubtractEquals: function (scalar) { + this.x -= scalar; + this.y -= scalar; + return this; + }, + + /** + * Miltiplies this point by a value and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + multiply: function (scalar) { + return new Point(this.x * scalar, this.y * scalar); + }, + + /** + * Miltiplies this point by a value + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + multiplyEquals: function (scalar) { + this.x *= scalar; + this.y *= scalar; + return this; + }, + + /** + * Divides this point by a value and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + divide: function (scalar) { + return new Point(this.x / scalar, this.y / scalar); + }, + + /** + * Divides this point by a value + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + divideEquals: function (scalar) { + this.x /= scalar; + this.y /= scalar; + return this; + }, + + /** + * Returns true if this point is equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + eq: function (that) { + return (this.x === that.x && this.y === that.y); + }, + + /** + * Returns true if this point is less than another one + * @param {fabric.Point} that + * @return {Boolean} + */ + lt: function (that) { + return (this.x < that.x && this.y < that.y); + }, + + /** + * Returns true if this point is less than or equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + lte: function (that) { + return (this.x <= that.x && this.y <= that.y); + }, + + /** + + * Returns true if this point is greater another one + * @param {fabric.Point} that + * @return {Boolean} + */ + gt: function (that) { + return (this.x > that.x && this.y > that.y); + }, + + /** + * Returns true if this point is greater than or equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + gte: function (that) { + return (this.x >= that.x && this.y >= that.y); + }, + + /** + * Returns new point which is the result of linear interpolation with this one and another one + * @param {fabric.Point} that + * @param {Number} t + * @return {fabric.Point} + */ + lerp: function (that, t) { + return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t); + }, + + /** + * Returns distance from this point and another one + * @param {fabric.Point} that + * @return {Number} + */ + distanceFrom: function (that) { + var dx = this.x - that.x, + dy = this.y - that.y; + return Math.sqrt(dx * dx + dy * dy); + }, + + /** + * Returns the point between this point and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + midPointFrom: function (that) { + return new Point(this.x + (that.x - this.x)/2, this.y + (that.y - this.y)/2); + }, + + /** + * Returns a new point which is the min of this and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + min: function (that) { + return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y)); + }, + + /** + * Returns a new point which is the max of this and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + max: function (that) { + return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y)); + }, + + /** + * Returns string representation of this point + * @return {String} + */ + toString: function () { + return this.x + ',' + this.y; + }, + + /** + * Sets x/y of this point + * @param {Number} x + * @return {Number} y + */ + setXY: function (x, y) { + this.x = x; + this.y = y; + }, + + /** + * Sets x/y of this point from another point + * @param {fabric.Point} that + */ + setFromPoint: function (that) { + this.x = that.x; + this.y = that.y; + }, + + /** + * Swaps x/y of this point and another point + * @param {fabric.Point} that + */ + swap: function (that) { + var x = this.x, + y = this.y; + this.x = that.x; + this.y = that.y; + that.x = x; + that.y = y; + } + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Intersection) { + fabric.warn('fabric.Intersection is already defined'); + return; + } + + /** + * Intersection class + * @class fabric.Intersection + * @memberOf fabric + * @constructor + */ + function Intersection(status) { + this.status = status; + this.points = []; + } + + fabric.Intersection = Intersection; + + fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ { + + /** + * Appends a point to intersection + * @param {fabric.Point} point + */ + appendPoint: function (point) { + this.points.push(point); + }, + + /** + * Appends points to intersection + * @param {Array} points + */ + appendPoints: function (points) { + this.points = this.points.concat(points); + } + }; + + /** + * Checks if one line intersects another + * @static + * @param {fabric.Point} a1 + * @param {fabric.Point} a2 + * @param {fabric.Point} b1 + * @param {fabric.Point} b2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) { + var result, + uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), + ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), + uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); + if (uB !== 0) { + var ua = uaT / uB, + ub = ubT / uB; + if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { + result = new Intersection('Intersection'); + result.points.push(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); + } + else { + result = new Intersection(); + } + } + else { + if (uaT === 0 || ubT === 0) { + result = new Intersection('Coincident'); + } + else { + result = new Intersection('Parallel'); + } + } + return result; + }; + + /** + * Checks if line intersects polygon + * @static + * @param {fabric.Point} a1 + * @param {fabric.Point} a2 + * @param {Array} points + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectLinePolygon = function(a1,a2,points){ + var result = new Intersection(), + length = points.length; + + for (var i = 0; i < length; i++) { + var b1 = points[i], + b2 = points[(i + 1) % length], + inter = Intersection.intersectLineLine(a1, a2, b1, b2); + + result.appendPoints(inter.points); + } + if (result.points.length > 0) { + result.status = 'Intersection'; + } + return result; + }; + + /** + * Checks if polygon intersects another polygon + * @static + * @param {Array} points1 + * @param {Array} points2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectPolygonPolygon = function (points1, points2) { + var result = new Intersection(), + length = points1.length; + + for (var i = 0; i < length; i++) { + var a1 = points1[i], + a2 = points1[(i + 1) % length], + inter = Intersection.intersectLinePolygon(a1, a2, points2); + + result.appendPoints(inter.points); + } + if (result.points.length > 0) { + result.status = 'Intersection'; + } + return result; + }; + + /** + * Checks if polygon intersects rectangle + * @static + * @param {Array} points + * @param {Number} r1 + * @param {Number} r2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) { + var min = r1.min(r2), + max = r1.max(r2), + topRight = new fabric.Point(max.x, min.y), + bottomLeft = new fabric.Point(min.x, max.y), + inter1 = Intersection.intersectLinePolygon(min, topRight, points), + inter2 = Intersection.intersectLinePolygon(topRight, max, points), + inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points), + inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points), + result = new Intersection(); + + result.appendPoints(inter1.points); + result.appendPoints(inter2.points); + result.appendPoints(inter3.points); + result.appendPoints(inter4.points); + + if (result.points.length > 0) { + result.status = 'Intersection'; + } + return result; + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Color) { + fabric.warn('fabric.Color is already defined.'); + return; + } + + /** + * Color class + * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations; + * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects. + * + * @class fabric.Color + * @param {String} color optional in hex or rgb(a) format + * @return {fabric.Color} thisArg + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors} + */ + function Color(color) { + if (!color) { + this.setSource([0, 0, 0, 1]); + } + else { + this._tryParsingColor(color); + } + } + + fabric.Color = Color; + + fabric.Color.prototype = /** @lends fabric.Color.prototype */ { + + /** + * @private + * @param {String|Array} color Color value to parse + */ + _tryParsingColor: function(color) { + var source; + + if (color in Color.colorNameMap) { + color = Color.colorNameMap[color]; + } + + if (color === 'transparent') { + this.setSource([255,255,255,0]); + return; + } + + source = Color.sourceFromHex(color); + + if (!source) { + source = Color.sourceFromRgb(color); + } + if (!source) { + source = Color.sourceFromHsl(color); + } + if (source) { + this.setSource(source); + } + }, + + /** + * Adapted from https://github.com/mjijackson + * @private + * @param {Number} r Red color value + * @param {Number} g Green color value + * @param {Number} b Blue color value + * @return {Array} Hsl color + */ + _rgbToHsl: function(r, g, b) { + r /= 255, g /= 255, b /= 255; + + var h, s, l, + max = fabric.util.array.max([r, g, b]), + min = fabric.util.array.min([r, g, b]); + + l = (max + min) / 2; + + if (max === min) { + h = s = 0; // achromatic + } + else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + + return [ + Math.round(h * 360), + Math.round(s * 100), + Math.round(l * 100) + ]; + }, + + /** + * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1]) + * @return {Array} + */ + getSource: function() { + return this._source; + }, + + /** + * Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1]) + * @param {Array} source + */ + setSource: function(source) { + this._source = source; + }, + + /** + * Returns color represenation in RGB format + * @return {String} ex: rgb(0-255,0-255,0-255) + */ + toRgb: function() { + var source = this.getSource(); + return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')'; + }, + + /** + * Returns color represenation in RGBA format + * @return {String} ex: rgba(0-255,0-255,0-255,0-1) + */ + toRgba: function() { + var source = this.getSource(); + return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')'; + }, + + /** + * Returns color represenation in HSL format + * @return {String} ex: hsl(0-360,0%-100%,0%-100%) + */ + toHsl: function() { + var source = this.getSource(), + hsl = this._rgbToHsl(source[0], source[1], source[2]); + + return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)'; + }, + + /** + * Returns color represenation in HSLA format + * @return {String} ex: hsla(0-360,0%-100%,0%-100%,0-1) + */ + toHsla: function() { + var source = this.getSource(), + hsl = this._rgbToHsl(source[0], source[1], source[2]); + + return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')'; + }, + + /** + * Returns color represenation in HEX format + * @return {String} ex: FF5555 + */ + toHex: function() { + var source = this.getSource(), r, g, b; + + r = source[0].toString(16); + r = (r.length === 1) ? ('0' + r) : r; + + g = source[1].toString(16); + g = (g.length === 1) ? ('0' + g) : g; + + b = source[2].toString(16); + b = (b.length === 1) ? ('0' + b) : b; + + return r.toUpperCase() + g.toUpperCase() + b.toUpperCase(); + }, + + /** + * Gets value of alpha channel for this color + * @return {Number} 0-1 + */ + getAlpha: function() { + return this.getSource()[3]; + }, + + /** + * Sets value of alpha channel for this color + * @param {Number} alpha Alpha value 0-1 + * @return {fabric.Color} thisArg + */ + setAlpha: function(alpha) { + var source = this.getSource(); + source[3] = alpha; + this.setSource(source); + return this; + }, + + /** + * Transforms color to its grayscale representation + * @return {fabric.Color} thisArg + */ + toGrayscale: function() { + var source = this.getSource(), + average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10), + currentAlpha = source[3]; + this.setSource([average, average, average, currentAlpha]); + return this; + }, + + /** + * Transforms color to its black and white representation + * @param {Number} threshold + * @return {fabric.Color} thisArg + */ + toBlackWhite: function(threshold) { + var source = this.getSource(), + average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), + currentAlpha = source[3]; + + threshold = threshold || 127; + + average = (Number(average) < Number(threshold)) ? 0 : 255; + this.setSource([average, average, average, currentAlpha]); + return this; + }, + + /** + * Overlays color with another color + * @param {String|fabric.Color} otherColor + * @return {fabric.Color} thisArg + */ + overlayWith: function(otherColor) { + if (!(otherColor instanceof Color)) { + otherColor = new Color(otherColor); + } + + var result = [], + alpha = this.getAlpha(), + otherAlpha = 0.5, + source = this.getSource(), + otherSource = otherColor.getSource(); + + for (var i = 0; i < 3; i++) { + result.push(Math.round((source[i] * (1 - otherAlpha)) + (otherSource[i] * otherAlpha))); + } + + result[3] = alpha; + this.setSource(result); + return this; + } + }; + + /** + * Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5)) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reRGBa = /^rgba?\(\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; + + /** + * Regex matching color in HSL or HSLA formats (ex: hsl(200, 80%, 10%), hsla(300, 50%, 80%, 0.5), hsla( 300 , 50% , 80% , 0.5 )) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; + + /** + * Regex matching color in HEX format (ex: #FF5555, 010155, aff) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reHex = /^#?([0-9a-f]{6}|[0-9a-f]{3})$/i; + + /** + * Map of the 17 basic color names with HEX code + * @static + * @field + * @memberOf fabric.Color + * @see: http://www.w3.org/TR/CSS2/syndata.html#color-units + */ + fabric.Color.colorNameMap = { + aqua: '#00FFFF', + black: '#000000', + blue: '#0000FF', + fuchsia: '#FF00FF', + gray: '#808080', + green: '#008000', + lime: '#00FF00', + maroon: '#800000', + navy: '#000080', + olive: '#808000', + orange: '#FFA500', + purple: '#800080', + red: '#FF0000', + silver: '#C0C0C0', + teal: '#008080', + white: '#FFFFFF', + yellow: '#FFFF00' + }; + + /** + * @private + * @param {Number} p + * @param {Number} q + * @param {Number} t + * @return {Number} + */ + function hue2rgb(p, q, t){ + if (t < 0) { + t += 1; + } + if (t > 1) { + t -= 1; + } + if (t < 1/6) { + return p + (q - p) * 6 * t; + } + if (t < 1/2) { + return q; + } + if (t < 2/3) { + return p + (q - p) * (2/3 - t) * 6; + } + return p; + } + + /** + * Returns new color object, when given a color in RGB format + * @memberOf fabric.Color + * @param {String} color Color value ex: rgb(0-255,0-255,0-255) + * @return {fabric.Color} + */ + fabric.Color.fromRgb = function(color) { + return Color.fromSource(Color.sourceFromRgb(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format + * @memberOf fabric.Color + * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%) + * @return {Array} source + */ + fabric.Color.sourceFromRgb = function(color) { + var match = color.match(Color.reRGBa); + if (match) { + var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1), + g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1), + b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1); + + return [ + parseInt(r, 10), + parseInt(g, 10), + parseInt(b, 10), + match[4] ? parseFloat(match[4]) : 1 + ]; + } + }; + + /** + * Returns new color object, when given a color in RGBA format + * @static + * @function + * @memberOf fabric.Color + * @param {String} color + * @return {fabric.Color} + */ + fabric.Color.fromRgba = Color.fromRgb; + + /** + * Returns new color object, when given a color in HSL format + * @param {String} color Color value ex: hsl(0-260,0%-100%,0%-100%) + * @memberOf fabric.Color + * @return {fabric.Color} + */ + fabric.Color.fromHsl = function(color) { + return Color.fromSource(Color.sourceFromHsl(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format. + * Adapted from https://github.com/mjijackson + * @memberOf fabric.Color + * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1) + * @return {Array} source + * @see http://http://www.w3.org/TR/css3-color/#hsl-color + */ + fabric.Color.sourceFromHsl = function(color) { + var match = color.match(Color.reHSLa); + if (!match) { + return; + } + + var h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360, + s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1), + l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1), + r, g, b; + + if (s === 0) { + r = g = b = l; + } + else { + var q = l <= 0.5 ? l * (s + 1) : l + s - l * s, + p = l * 2 - q; + + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return [ + Math.round(r * 255), + Math.round(g * 255), + Math.round(b * 255), + match[4] ? parseFloat(match[4]) : 1 + ]; + }; + + /** + * Returns new color object, when given a color in HSLA format + * @static + * @function + * @memberOf fabric.Color + * @param {String} color + * @return {fabric.Color} + */ + fabric.Color.fromHsla = Color.fromHsl; + + /** + * Returns new color object, when given a color in HEX format + * @static + * @memberOf fabric.Color + * @param {String} color Color value ex: FF5555 + * @return {fabric.Color} + */ + fabric.Color.fromHex = function(color) { + return Color.fromSource(Color.sourceFromHex(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HEX format + * @static + * @memberOf fabric.Color + * @param {String} color ex: FF5555 + * @return {Array} source + */ + fabric.Color.sourceFromHex = function(color) { + if (color.match(Color.reHex)) { + var value = color.slice(color.indexOf('#') + 1), + isShortNotation = (value.length === 3), + r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2), + g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4), + b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6); + + return [ + parseInt(r, 16), + parseInt(g, 16), + parseInt(b, 16), + 1 + ]; + } + }; + + /** + * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5]) + * @static + * @memberOf fabric.Color + * @param {Array} source + * @return {fabric.Color} + */ + fabric.Color.fromSource = function(source) { + var oColor = new Color(); + oColor.setSource(source); + return oColor; + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + /* _FROM_SVG_START_ */ + function getColorStop(el) { + var style = el.getAttribute('style'), + offset = el.getAttribute('offset'), + color, colorAlpha, opacity; + + // convert percents to absolute values + offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1); + + if (style) { + var keyValuePairs = style.split(/\s*;\s*/); + + if (keyValuePairs[keyValuePairs.length - 1] === '') { + keyValuePairs.pop(); + } + + for (var i = keyValuePairs.length; i--; ) { + + var split = keyValuePairs[i].split(/\s*:\s*/), + key = split[0].trim(), + value = split[1].trim(); + + if (key === 'stop-color') { + color = value; + } + else if (key === 'stop-opacity') { + opacity = value; + } + } + } + + if (!color) { + color = el.getAttribute('stop-color') || 'rgb(0,0,0)'; + } + if (!opacity) { + opacity = el.getAttribute('stop-opacity'); + } + + color = new fabric.Color(color); + colorAlpha = color.getAlpha(); + opacity = isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity); + opacity *= colorAlpha; + + return { + offset: offset, + color: color.toRgb(), + opacity: opacity + }; + } + + function getLinearCoords(el) { + return { + x1: el.getAttribute('x1') || 0, + y1: el.getAttribute('y1') || 0, + x2: el.getAttribute('x2') || '100%', + y2: el.getAttribute('y2') || 0 + }; + } + + function getRadialCoords(el) { + return { + x1: el.getAttribute('fx') || el.getAttribute('cx') || '50%', + y1: el.getAttribute('fy') || el.getAttribute('cy') || '50%', + r1: 0, + x2: el.getAttribute('cx') || '50%', + y2: el.getAttribute('cy') || '50%', + r2: el.getAttribute('r') || '50%' + }; + } + /* _FROM_SVG_END_ */ + + /** + * Gradient class + * @class fabric.Gradient + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#gradients} + * @see {@link fabric.Gradient#initialize} for constructor definition + */ + fabric.Gradient = fabric.util.createClass(/** @lends fabric.Gradient.prototype */ { + /* + * Stores the original position of the gradient when we convert from % to fixed values, for objectBoundingBox case. + * @type Number + * @default 0 + */ + origX: 0, + + /* + * Stores the original position of the gradient when we convert from % to fixed values, for objectBoundingBox case. + * @type Number + * @default 0 + */ + origY: 0, + + /** + * Constructor + * @param {Object} [options] Options object with type, coords, gradientUnits and colorStops + * @return {fabric.Gradient} thisArg + */ + initialize: function(options) { + options || (options = { }); + + var coords = { }; + + this.id = fabric.Object.__uid++; + this.type = options.type || 'linear'; + + coords = { + x1: options.coords.x1 || 0, + y1: options.coords.y1 || 0, + x2: options.coords.x2 || 0, + y2: options.coords.y2 || 0 + }; + + if (this.type === 'radial') { + coords.r1 = options.coords.r1 || 0; + coords.r2 = options.coords.r2 || 0; + } + + this.coords = coords; + this.gradientUnits = options.gradientUnits || 'objectBoundingBox'; + this.colorStops = options.colorStops.slice(); + if (options.gradientTransform) { + this.gradientTransform = options.gradientTransform; + } + this.origX = options.left || this.origX; + this.origY = options.top || this.origY; + }, + + /** + * Adds another colorStop + * @param {Object} colorStop Object with offset and color + * @return {fabric.Gradient} thisArg + */ + addColorStop: function(colorStop) { + for (var position in colorStop) { + var color = new fabric.Color(colorStop[position]); + this.colorStops.push({ + offset: position, + color: color.toRgb(), + opacity: color.getAlpha() + }); + } + return this; + }, + + /** + * Returns object representation of a gradient + * @return {Object} + */ + toObject: function() { + return { + type: this.type, + coords: this.coords, + gradientUnits: this.gradientUnits, + colorStops: this.colorStops + }; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an gradient + * @param {Object} object Object to create a gradient for + * @param {Boolean} normalize Whether coords should be normalized + * @return {String} SVG representation of an gradient (linear/radial) + */ + toSVG: function(object, normalize) { + var coords = fabric.util.object.clone(this.coords), + markup, commonAttributes; + + // colorStops must be sorted ascending + this.colorStops.sort(function(a, b) { + return a.offset - b.offset; + }); + + if (normalize && this.gradientUnits === 'userSpaceOnUse') { + coords.x1 += object.width / 2; + coords.y1 += object.height / 2; + coords.x2 += object.width / 2; + coords.y2 += object.height / 2; + } + else if (this.gradientUnits === 'objectBoundingBox') { + _convertValuesToPercentUnits(object, coords); + } + commonAttributes = 'id="SVGID_' + this.id + + '" gradientUnits="' + this.gradientUnits + '"'; + if (this.gradientTransform) { + commonAttributes += ' gradientTransform="matrix(' + this.gradientTransform.join(' ') + ')" '; + } + if (this.type === 'linear') { + markup = [ + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ]; + } + else if (this.type === 'radial') { + markup = [ + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ]; + } + + for (var i = 0; i < this.colorStops.length; i++) { + markup.push( + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ); + } + + markup.push((this.type === 'linear' ? '\n' : '\n')); + + return markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns an instance of CanvasGradient + * @param {CanvasRenderingContext2D} ctx Context to render on + * @return {CanvasGradient} + */ + toLive: function(ctx) { + var gradient; + + if (!this.type) { + return; + } + + if (this.type === 'linear') { + gradient = ctx.createLinearGradient( + this.coords.x1, this.coords.y1, this.coords.x2, this.coords.y2); + } + else if (this.type === 'radial') { + gradient = ctx.createRadialGradient( + this.coords.x1, this.coords.y1, this.coords.r1, this.coords.x2, this.coords.y2, this.coords.r2); + } + + for (var i = 0, len = this.colorStops.length; i < len; i++) { + var color = this.colorStops[i].color, + opacity = this.colorStops[i].opacity, + offset = this.colorStops[i].offset; + + if (typeof opacity !== 'undefined') { + color = new fabric.Color(color).setAlpha(opacity).toRgba(); + } + gradient.addColorStop(parseFloat(offset), color); + } + + return gradient; + } + }); + + fabric.util.object.extend(fabric.Gradient, { + + /* _FROM_SVG_START_ */ + /** + * Returns {@link fabric.Gradient} instance from an SVG element + * @static + * @memberof fabric.Gradient + * @param {SVGGradientElement} el SVG gradient element + * @param {fabric.Object} instance + * @return {fabric.Gradient} Gradient instance + * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement + * @see http://www.w3.org/TR/SVG/pservers.html#RadialGradientElement + */ + fromElement: function(el, instance) { + + /** + * @example: + * + * + * + * + * + * + * OR + * + * + * + * + * + * + * OR + * + * + * + * + * + * + * + * OR + * + * + * + * + * + * + * + */ + + var colorStopEls = el.getElementsByTagName('stop'), + type = (el.nodeName === 'linearGradient' ? 'linear' : 'radial'), + gradientUnits = el.getAttribute('gradientUnits') || 'objectBoundingBox', + gradientTransform = el.getAttribute('gradientTransform'), + colorStops = [], + coords = { }; + + if (type === 'linear') { + coords = getLinearCoords(el); + } + else if (type === 'radial') { + coords = getRadialCoords(el); + } + + for (var i = colorStopEls.length; i--; ) { + colorStops.push(getColorStop(colorStopEls[i])); + } + + _convertPercentUnitsToValues(instance, coords); + + var gradient = new fabric.Gradient({ + type: type, + coords: coords, + gradientUnits: gradientUnits, + colorStops: colorStops + }); + + if (gradientTransform) { + gradient.gradientTransform = fabric.parseTransformAttribute(gradientTransform); + } + + return gradient; + }, + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Gradient} instance from its object representation + * @static + * @memberof fabric.Gradient + * @param {Object} obj + * @param {Object} [options] Options object + */ + forObject: function(obj, options) { + options || (options = { }); + _convertPercentUnitsToValues(obj, options); + return new fabric.Gradient(options); + } + }); + + /** + * @private + */ + function _convertPercentUnitsToValues(object, options) { + for (var prop in options) { + if (typeof options[prop] === 'string' && /^\d+%$/.test(options[prop])) { + var percents = parseFloat(options[prop], 10); + if (prop === 'x1' || prop === 'x2' || prop === 'r2') { + options[prop] = fabric.util.toFixed(object.width * percents / 100, 2) + object.left; + } + else if (prop === 'y1' || prop === 'y2') { + options[prop] = fabric.util.toFixed(object.height * percents / 100, 2) + object.top; + } + } + } + } + + /* _TO_SVG_START_ */ + /** + * @private + */ + function _convertValuesToPercentUnits(object, options) { + for (var prop in options) { + //convert to percent units + if (prop === 'x1' || prop === 'x2' || prop === 'r2') { + options[prop] = fabric.util.toFixed((options[prop] - object.fill.origX) / object.width * 100, 2) + '%'; + } + else if (prop === 'y1' || prop === 'y2') { + options[prop] = fabric.util.toFixed((options[prop] - object.fill.origY) / object.height * 100, 2) + '%'; + } + } + } + /* _TO_SVG_END_ */ + +})(); + + +/** + * Pattern class + * @class fabric.Pattern + * @see {@link http://fabricjs.com/patterns/|Pattern demo} + * @see {@link http://fabricjs.com/dynamic-patterns/|DynamicPattern demo} + * @see {@link fabric.Pattern#initialize} for constructor definition + */ +fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ { + + /** + * Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat) + * @type String + * @default + */ + repeat: 'repeat', + + /** + * Pattern horizontal offset from object's left/top corner + * @type Number + * @default + */ + offsetX: 0, + + /** + * Pattern vertical offset from object's left/top corner + * @type Number + * @default + */ + offsetY: 0, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Pattern} thisArg + */ + initialize: function(options) { + options || (options = { }); + + this.id = fabric.Object.__uid++; + + if (options.source) { + if (typeof options.source === 'string') { + // function string + if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') { + this.source = new Function(fabric.util.getFunctionBody(options.source)); + } + else { + // img src string + var _this = this; + this.source = fabric.util.createImage(); + fabric.util.loadImage(options.source, function(img) { + _this.source = img; + }); + } + } + else { + // img element + this.source = options.source; + } + } + if (options.repeat) { + this.repeat = options.repeat; + } + if (options.offsetX) { + this.offsetX = options.offsetX; + } + if (options.offsetY) { + this.offsetY = options.offsetY; + } + }, + + /** + * Returns object representation of a pattern + * @return {Object} Object representation of a pattern instance + */ + toObject: function() { + + var source; + + // callback + if (typeof this.source === 'function') { + source = String(this.source); + } + // element + else if (typeof this.source.src === 'string') { + source = this.source.src; + } + + return { + source: source, + repeat: this.repeat, + offsetX: this.offsetX, + offsetY: this.offsetY + }; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of a pattern + * @param {fabric.Object} object + * @return {String} SVG representation of a pattern + */ + toSVG: function(object) { + var patternSource = typeof this.source === 'function' ? this.source() : this.source, + patternWidth = patternSource.width / object.getWidth(), + patternHeight = patternSource.height / object.getHeight(), + patternImgSrc = ''; + + if (patternSource.src) { + patternImgSrc = patternSource.src; + } + else if (patternSource.toDataURL) { + patternImgSrc = patternSource.toDataURL(); + } + + return '' + + '' + + ''; + }, + /* _TO_SVG_END_ */ + + /** + * Returns an instance of CanvasPattern + * @param {CanvasRenderingContext2D} ctx Context to create pattern + * @return {CanvasPattern} + */ + toLive: function(ctx) { + var source = typeof this.source === 'function' + ? this.source() + : this.source; + + // if the image failed to load, return, and allow rest to continue loading + if (!source) { + return ''; + } + + // if an image + if (typeof source.src !== 'undefined') { + if (!source.complete) { + return ''; + } + if (source.naturalWidth === 0 || source.naturalHeight === 0) { + return ''; + } + } + return ctx.createPattern(source, this.repeat); + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Shadow) { + fabric.warn('fabric.Shadow is already defined.'); + return; + } + + /** + * Shadow class + * @class fabric.Shadow + * @see {@link http://fabricjs.com/shadows/|Shadow demo} + * @see {@link fabric.Shadow#initialize} for constructor definition + */ + fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ { + + /** + * Shadow color + * @type String + * @default + */ + color: 'rgb(0,0,0)', + + /** + * Shadow blur + * @type Number + */ + blur: 0, + + /** + * Shadow horizontal offset + * @type Number + * @default + */ + offsetX: 0, + + /** + * Shadow vertical offset + * @type Number + * @default + */ + offsetY: 0, + + /** + * Whether the shadow should affect stroke operations + * @type Boolean + * @default + */ + affectStroke: false, + + /** + * Indicates whether toObject should include default values + * @type Boolean + * @default + */ + includeDefaultValues: true, + + /** + * Constructor + * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetX properties or string (e.g. "rgba(0,0,0,0.2) 2px 2px 10px, "2px 2px 10px rgba(0,0,0,0.2)") + * @return {fabric.Shadow} thisArg + */ + initialize: function(options) { + + if (typeof options === 'string') { + options = this._parseShadow(options); + } + + for (var prop in options) { + this[prop] = options[prop]; + } + + this.id = fabric.Object.__uid++; + }, + + /** + * @private + * @param {String} shadow Shadow value to parse + * @return {Object} Shadow object with color, offsetX, offsetY and blur + */ + _parseShadow: function(shadow) { + var shadowStr = shadow.trim(), + offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [ ], + color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, '') || 'rgb(0,0,0)'; + + return { + color: color.trim(), + offsetX: parseInt(offsetsAndBlur[1], 10) || 0, + offsetY: parseInt(offsetsAndBlur[2], 10) || 0, + blur: parseInt(offsetsAndBlur[3], 10) || 0 + }; + }, + + /** + * Returns a string representation of an instance + * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow + * @return {String} Returns CSS3 text-shadow declaration + */ + toString: function() { + return [this.offsetX, this.offsetY, this.blur, this.color].join('px '); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of a shadow + * @param {fabric.Object} object + * @return {String} SVG representation of a shadow + */ + toSVG: function(object) { + var mode = 'SourceAlpha'; + + if (object && (object.fill === this.color || object.stroke === this.color)) { + mode = 'SourceGraphic'; + } + + return ( + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns object representation of a shadow + * @return {Object} Object representation of a shadow instance + */ + toObject: function() { + if (this.includeDefaultValues) { + return { + color: this.color, + blur: this.blur, + offsetX: this.offsetX, + offsetY: this.offsetY + }; + } + var obj = { }, proto = fabric.Shadow.prototype; + if (this.color !== proto.color) { + obj.color = this.color; + } + if (this.blur !== proto.blur) { + obj.blur = this.blur; + } + if (this.offsetX !== proto.offsetX) { + obj.offsetX = this.offsetX; + } + if (this.offsetY !== proto.offsetY) { + obj.offsetY = this.offsetY; + } + return obj; + } + }); + + /** + * Regex matching shadow offsetX, offsetY and blur (ex: "2px 2px 10px rgba(0,0,0,0.2)", "rgb(0,255,0) 2px 2px") + * @static + * @field + * @memberOf fabric.Shadow + */ + fabric.Shadow.reOffsetsAndBlur = /(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function () { + + 'use strict'; + + if (fabric.StaticCanvas) { + fabric.warn('fabric.StaticCanvas is already defined.'); + return; + } + + // aliases for faster resolution + var extend = fabric.util.object.extend, + getElementOffset = fabric.util.getElementOffset, + removeFromArray = fabric.util.removeFromArray, + + CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element'); + + /** + * Static canvas class + * @class fabric.StaticCanvas + * @mixes fabric.Collection + * @mixes fabric.Observable + * @see {@link http://fabricjs.com/static_canvas/|StaticCanvas demo} + * @see {@link fabric.StaticCanvas#initialize} for constructor definition + * @fires before:render + * @fires after:render + * @fires canvas:cleared + * @fires object:added + * @fires object:removed + */ + fabric.StaticCanvas = fabric.util.createClass(/** @lends fabric.StaticCanvas.prototype */ { + + /** + * Constructor + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(el, options) { + options || (options = { }); + + this._initStatic(el, options); + fabric.StaticCanvas.activeInstance = this; + }, + + /** + * Background color of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setBackgroundColor}. + * @type {(String|fabric.Pattern)} + * @default + */ + backgroundColor: '', + + /** + * Background image of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setBackgroundImage}. + * Backwards incompatibility note: The "backgroundImageOpacity" + * and "backgroundImageStretch" properties are deprecated since 1.3.9. + * Use {@link fabric.Image#opacity}, {@link fabric.Image#width} and {@link fabric.Image#height}. + * @type fabric.Image + * @default + */ + backgroundImage: null, + + /** + * Overlay color of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setOverlayColor} + * @since 1.3.9 + * @type {(String|fabric.Pattern)} + * @default + */ + overlayColor: '', + + /** + * Overlay image of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setOverlayImage}. + * Backwards incompatibility note: The "overlayImageLeft" + * and "overlayImageTop" properties are deprecated since 1.3.9. + * Use {@link fabric.Image#left} and {@link fabric.Image#top}. + * @type fabric.Image + * @default + */ + overlayImage: null, + + /** + * Indicates whether toObject/toDatalessObject should include default values + * @type Boolean + * @default + */ + includeDefaultValues: true, + + /** + * Indicates whether objects' state should be saved + * @type Boolean + * @default + */ + stateful: true, + + /** + * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove} should also re-render canvas. + * Disabling this option could give a great performance boost when adding/removing a lot of objects to/from canvas at once + * (followed by a manual rendering after addition/deletion) + * @type Boolean + * @default + */ + renderOnAddRemove: true, + + /** + * Function that determines clipping of entire canvas area + * Being passed context as first argument. See clipping canvas area in {@link https://github.com/kangax/fabric.js/wiki/FAQ} + * @type Function + * @default + */ + clipTo: null, + + /** + * Indicates whether object controls (borders/controls) are rendered above overlay image + * @type Boolean + * @default + */ + controlsAboveOverlay: false, + + /** + * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas + * @type Boolean + * @default + */ + allowTouchScrolling: false, + + /** + * Indicates whether this canvas will use image smoothing, this is on by default in browsers + * @type Boolean + * @default + */ + imageSmoothingEnabled: true, + + /** + * The transformation (in the format of Canvas transform) which focuses the viewport + * @type Array + * @default + */ + viewportTransform: [1, 0, 0, 1, 0, 0], + + /** + * Callback; invoked right before object is about to be scaled/rotated + */ + onBeforeScaleRotate: function () { + /* NOOP */ + }, + + /** + * @private + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + */ + _initStatic: function(el, options) { + this._objects = []; + + this._createLowerCanvas(el); + this._initOptions(options); + this._setImageSmoothing(); + + if (options.overlayImage) { + this.setOverlayImage(options.overlayImage, this.renderAll.bind(this)); + } + if (options.backgroundImage) { + this.setBackgroundImage(options.backgroundImage, this.renderAll.bind(this)); + } + if (options.backgroundColor) { + this.setBackgroundColor(options.backgroundColor, this.renderAll.bind(this)); + } + if (options.overlayColor) { + this.setOverlayColor(options.overlayColor, this.renderAll.bind(this)); + } + this.calcOffset(); + }, + + /** + * Calculates canvas element offset relative to the document + * This method is also attached as "resize" event handler of window + * @return {fabric.Canvas} instance + * @chainable + */ + calcOffset: function () { + this._offset = getElementOffset(this.lowerCanvasEl); + return this; + }, + + /** + * Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas + * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set overlay to + * @param {Function} callback callback to invoke when image is loaded and set as an overlay + * @param {Object} [options] Optional options to set for the {@link fabric.Image|overlay image}. + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo} + * @example Normal overlayImage with left/top = 0 + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * // Needed to position overlayImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + * @example overlayImage with different properties + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * opacity: 0.5, + * angle: 45, + * left: 400, + * top: 400, + * originX: 'left', + * originY: 'top' + * }); + * @example Stretched overlayImage #1 - width/height correspond to canvas width/height + * fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img) { + * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); + * canvas.setOverlayImage(img, canvas.renderAll.bind(canvas)); + * }); + * @example Stretched overlayImage #2 - width/height correspond to canvas width/height + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * width: canvas.width, + * height: canvas.height, + * // Needed to position overlayImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + */ + setOverlayImage: function (image, callback, options) { + return this.__setBgOverlayImage('overlayImage', image, callback, options); + }, + + /** + * Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas + * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background to + * @param {Function} callback Callback to invoke when image is loaded and set as background + * @param {Object} [options] Optional options to set for the {@link fabric.Image|background image}. + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/YH9yD/|jsFiddle demo} + * @example Normal backgroundImage with left/top = 0 + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * // Needed to position backgroundImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + * @example backgroundImage with different properties + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * opacity: 0.5, + * angle: 45, + * left: 400, + * top: 400, + * originX: 'left', + * originY: 'top' + * }); + * @example Stretched backgroundImage #1 - width/height correspond to canvas width/height + * fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img) { + * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); + * canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas)); + * }); + * @example Stretched backgroundImage #2 - width/height correspond to canvas width/height + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * width: canvas.width, + * height: canvas.height, + * // Needed to position backgroundImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + */ + setBackgroundImage: function (image, callback, options) { + return this.__setBgOverlayImage('backgroundImage', image, callback, options); + }, + + /** + * Sets {@link fabric.StaticCanvas#overlayColor|background color} for this canvas + * @param {(String|fabric.Pattern)} overlayColor Color or pattern to set background color to + * @param {Function} callback Callback to invoke when background color is set + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/pB55h/|jsFiddle demo} + * @example Normal overlayColor - color value + * canvas.setOverlayColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as overlayColor + * canvas.setOverlayColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png' + * }, canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as overlayColor with repeat and offset + * canvas.setOverlayColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png', + * repeat: 'repeat', + * offsetX: 200, + * offsetY: 100 + * }, canvas.renderAll.bind(canvas)); + */ + setOverlayColor: function(overlayColor, callback) { + return this.__setBgOverlayColor('overlayColor', overlayColor, callback); + }, + + /** + * Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas + * @param {(String|fabric.Pattern)} backgroundColor Color or pattern to set background color to + * @param {Function} callback Callback to invoke when background color is set + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo} + * @example Normal backgroundColor - color value + * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as backgroundColor + * canvas.setBackgroundColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png' + * }, canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as backgroundColor with repeat and offset + * canvas.setBackgroundColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png', + * repeat: 'repeat', + * offsetX: 200, + * offsetY: 100 + * }, canvas.renderAll.bind(canvas)); + */ + setBackgroundColor: function(backgroundColor, callback) { + return this.__setBgOverlayColor('backgroundColor', backgroundColor, callback); + }, + + /** + * @private + * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-imagesmoothingenabled|WhatWG Canvas Standard} + */ + _setImageSmoothing: function(){ + var ctx = this.getContext(); + + ctx.imageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.webkitImageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.mozImageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.msImageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.oImageSmoothingEnabled = this.imageSmoothingEnabled; + }, + + /** + * @private + * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage} + * or {@link fabric.StaticCanvas#overlayImage|overlayImage}) + * @param {(fabric.Image|String|null)} image fabric.Image instance, URL of an image or null to set background or overlay to + * @param {Function} callback Callback to invoke when image is loaded and set as background or overlay + * @param {Object} [options] Optional options to set for the {@link fabric.Image|image}. + */ + __setBgOverlayImage: function(property, image, callback, options) { + if (typeof image === 'string') { + fabric.util.loadImage(image, function(img) { + this[property] = new fabric.Image(img, options); + callback && callback(); + }, this); + } + else { + this[property] = image; + callback && callback(); + } + + return this; + }, + + /** + * @private + * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundColor|backgroundColor} + * or {@link fabric.StaticCanvas#overlayColor|overlayColor}) + * @param {(Object|String|null)} color Object with pattern information, color value or null + * @param {Function} [callback] Callback is invoked when color is set + */ + __setBgOverlayColor: function(property, color, callback) { + if (color && color.source) { + var _this = this; + fabric.util.loadImage(color.source, function(img) { + _this[property] = new fabric.Pattern({ + source: img, + repeat: color.repeat, + offsetX: color.offsetX, + offsetY: color.offsetY + }); + callback && callback(); + }); + } + else { + this[property] = color; + callback && callback(); + } + + return this; + }, + + /** + * @private + */ + _createCanvasElement: function() { + var element = fabric.document.createElement('canvas'); + if (!element.style) { + element.style = { }; + } + if (!element) { + throw CANVAS_INIT_ERROR; + } + this._initCanvasElement(element); + return element; + }, + + /** + * @private + * @param {HTMLElement} element + */ + _initCanvasElement: function(element) { + fabric.util.createCanvasElement(element); + + if (typeof element.getContext === 'undefined') { + throw CANVAS_INIT_ERROR; + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initOptions: function (options) { + for (var prop in options) { + this[prop] = options[prop]; + } + + this.width = this.width || parseInt(this.lowerCanvasEl.width, 10) || 0; + this.height = this.height || parseInt(this.lowerCanvasEl.height, 10) || 0; + + if (!this.lowerCanvasEl.style) { + return; + } + + this.lowerCanvasEl.width = this.width; + this.lowerCanvasEl.height = this.height; + + this.lowerCanvasEl.style.width = this.width + 'px'; + this.lowerCanvasEl.style.height = this.height + 'px'; + + this.viewportTransform = this.viewportTransform.slice(); + }, + + /** + * Creates a bottom canvas + * @private + * @param {HTMLElement} [canvasEl] + */ + _createLowerCanvas: function (canvasEl) { + this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement(); + this._initCanvasElement(this.lowerCanvasEl); + + fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas'); + + if (this.interactive) { + this._applyCanvasStyle(this.lowerCanvasEl); + } + + this.contextContainer = this.lowerCanvasEl.getContext('2d'); + }, + + /** + * Returns canvas width (in px) + * @return {Number} + */ + getWidth: function () { + return this.width; + }, + + /** + * Returns canvas height (in px) + * @return {Number} + */ + getHeight: function () { + return this.height; + }, + + /** + * Sets width of this canvas instance + * @param {Number|String} value Value to set width to + * @param {Object} [options] Options object + * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions + * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions + * @return {fabric.Canvas} instance + * @chainable true + */ + setWidth: function (value, options) { + return this.setDimensions({ width: value }, options); + }, + + /** + * Sets height of this canvas instance + * @param {Number|String} value Value to set height to + * @param {Object} [options] Options object + * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions + * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions + * @return {fabric.Canvas} instance + * @chainable true + */ + setHeight: function (value, options) { + return this.setDimensions({ height: value }, options); + }, + + /** + * Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em) + * @param {Object} dimensions Object with width/height properties + * @param {Number|String} [dimensions.width] Width of canvas element + * @param {Number|String} [dimensions.height] Height of canvas element + * @param {Object} [options] Options object + * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions + * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions + * @return {fabric.Canvas} thisArg + * @chainable + */ + setDimensions: function (dimensions, options) { + var cssValue; + + options = options || {}; + + for (var prop in dimensions) { + cssValue = dimensions[prop]; + + if (!options.cssOnly) { + this._setBackstoreDimension(prop, dimensions[prop]); + cssValue += 'px'; + } + + if (!options.backstoreOnly) { + this._setCssDimension(prop, cssValue); + } + } + + if (!options.cssOnly) { + this.renderAll(); + } + + this.calcOffset(); + + return this; + }, + + /** + * Helper for setting width/height + * @private + * @param {String} prop property (width|height) + * @param {Number} value value to set property to + * @return {fabric.Canvas} instance + * @chainable true + */ + _setBackstoreDimension: function (prop, value) { + this.lowerCanvasEl[prop] = value; + + if (this.upperCanvasEl) { + this.upperCanvasEl[prop] = value; + } + + if (this.cacheCanvasEl) { + this.cacheCanvasEl[prop] = value; + } + + this[prop] = value; + + return this; + }, + + /** + * Helper for setting css width/height + * @private + * @param {String} prop property (width|height) + * @param {String} value value to set property to + * @return {fabric.Canvas} instance + * @chainable true + */ + _setCssDimension: function (prop, value) { + this.lowerCanvasEl.style[prop] = value; + + if (this.upperCanvasEl) { + this.upperCanvasEl.style[prop] = value; + } + + if (this.wrapperEl) { + this.wrapperEl.style[prop] = value; + } + + return this; + }, + + /** + * Returns canvas zoom level + * @return {Number} + */ + getZoom: function () { + return Math.sqrt(this.viewportTransform[0] * this.viewportTransform[3]); + }, + + /** + * Sets viewport transform of this canvas instance + * @param {Array} vpt the transform in the form of context.transform + * @return {fabric.Canvas} instance + * @chainable true + */ + setViewportTransform: function (vpt) { + this.viewportTransform = vpt; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + return this; + }, + + /** + * Sets zoom level of this canvas instance, zoom centered around point + * @param {fabric.Point} point to zoom with respect to + * @param {Number} value to set zoom to, less than 1 zooms out + * @return {fabric.Canvas} instance + * @chainable true + */ + zoomToPoint: function (point, value) { + // TODO: just change the scale, preserve other transformations + var before = point; + point = fabric.util.transformPoint(point, fabric.util.invertTransform(this.viewportTransform)); + this.viewportTransform[0] = value; + this.viewportTransform[3] = value; + var after = fabric.util.transformPoint(point, this.viewportTransform); + this.viewportTransform[4] += before.x - after.x; + this.viewportTransform[5] += before.y - after.y; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + return this; + }, + + /** + * Sets zoom level of this canvas instance + * @param {Number} value to set zoom to, less than 1 zooms out + * @return {fabric.Canvas} instance + * @chainable true + */ + setZoom: function (value) { + this.zoomToPoint(new fabric.Point(0, 0), value); + return this; + }, + + /** + * Pan viewport so as to place point at top left corner of canvas + * @param {fabric.Point} point to move to + * @return {fabric.Canvas} instance + * @chainable true + */ + absolutePan: function (point) { + this.viewportTransform[4] = -point.x; + this.viewportTransform[5] = -point.y; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + return this; + }, + + /** + * Pans viewpoint relatively + * @param {fabric.Point} point (position vector) to move by + * @return {fabric.Canvas} instance + * @chainable true + */ + relativePan: function (point) { + return this.absolutePan(new fabric.Point( + -point.x - this.viewportTransform[4], + -point.y - this.viewportTransform[5] + )); + }, + + /** + * Returns <canvas> element corresponding to this instance + * @return {HTMLCanvasElement} + */ + getElement: function () { + return this.lowerCanvasEl; + }, + + /** + * Returns currently selected object, if any + * @return {fabric.Object} + */ + getActiveObject: function() { + return null; + }, + + /** + * Returns currently selected group of object, if any + * @return {fabric.Group} + */ + getActiveGroup: function() { + return null; + }, + + /** + * Given a context, renders an object on that context + * @param {CanvasRenderingContext2D} ctx Context to render object on + * @param {fabric.Object} object Object to render + * @private + */ + _draw: function (ctx, object) { + if (!object) { + return; + } + + ctx.save(); + var v = this.viewportTransform; + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + object.render(ctx); + ctx.restore(); + if (!this.controlsAboveOverlay) { + object._renderControls(ctx); + } + }, + + /** + * @private + * @param {fabric.Object} obj Object that was added + */ + _onObjectAdded: function(obj) { + this.stateful && obj.setupState(); + obj.canvas = this; + obj.setCoords(); + this.fire('object:added', { target: obj }); + obj.fire('added'); + }, + + /** + * @private + * @param {fabric.Object} obj Object that was removed + */ + _onObjectRemoved: function(obj) { + // removing active object should fire "selection:cleared" events + if (this.getActiveObject() === obj) { + this.fire('before:selection:cleared', { target: obj }); + this._discardActiveObject(); + this.fire('selection:cleared'); + } + + this.fire('object:removed', { target: obj }); + obj.fire('removed'); + }, + + /** + * Clears specified context of canvas element + * @param {CanvasRenderingContext2D} ctx Context to clear + * @return {fabric.Canvas} thisArg + * @chainable + */ + clearContext: function(ctx) { + ctx.clearRect(0, 0, this.width, this.height); + return this; + }, + + /** + * Returns context of canvas where objects are drawn + * @return {CanvasRenderingContext2D} + */ + getContext: function () { + return this.contextContainer; + }, + + /** + * Clears all contexts (background, main, top) of an instance + * @return {fabric.Canvas} thisArg + * @chainable + */ + clear: function () { + this._objects.length = 0; + if (this.discardActiveGroup) { + this.discardActiveGroup(); + } + if (this.discardActiveObject) { + this.discardActiveObject(); + } + this.clearContext(this.contextContainer); + if (this.contextTop) { + this.clearContext(this.contextTop); + } + this.fire('canvas:cleared'); + this.renderAll(); + return this; + }, + + /** + * Renders both the top canvas and the secondary container canvas. + * @param {Boolean} [allOnTop] Whether we want to force all images to be rendered on the top canvas + * @return {fabric.Canvas} instance + * @chainable + */ + renderAll: function (allOnTop) { + var canvasToDrawOn = this[(allOnTop === true && this.interactive) ? 'contextTop' : 'contextContainer'], + activeGroup = this.getActiveGroup(); + + if (this.contextTop && this.selection && !this._groupSelector) { + this.clearContext(this.contextTop); + } + + if (!allOnTop) { + this.clearContext(canvasToDrawOn); + } + + this.fire('before:render'); + + if (this.clipTo) { + fabric.util.clipContext(this, canvasToDrawOn); + } + + this._renderBackground(canvasToDrawOn); + this._renderObjects(canvasToDrawOn, activeGroup); + this._renderActiveGroup(canvasToDrawOn, activeGroup); + + if (this.clipTo) { + canvasToDrawOn.restore(); + } + + this._renderOverlay(canvasToDrawOn); + + if (this.controlsAboveOverlay && this.interactive) { + this.drawControls(canvasToDrawOn); + } + + this.fire('after:render'); + + return this; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {fabric.Group} activeGroup + */ + _renderObjects: function(ctx, activeGroup) { + var i, length; + + // fast path + if (!activeGroup) { + for (i = 0, length = this._objects.length; i < length; ++i) { + this._draw(ctx, this._objects[i]); + } + } + else { + for (i = 0, length = this._objects.length; i < length; ++i) { + if (this._objects[i] && !activeGroup.contains(this._objects[i])) { + this._draw(ctx, this._objects[i]); + } + } + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {fabric.Group} activeGroup + */ + _renderActiveGroup: function(ctx, activeGroup) { + + // delegate rendering to group selection (if one exists) + if (activeGroup) { + + //Store objects in group preserving order, then replace + var sortedObjects = []; + this.forEachObject(function (object) { + if (activeGroup.contains(object)) { + sortedObjects.push(object); + } + }); + activeGroup._set('objects', sortedObjects); + this._draw(ctx, activeGroup); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderBackground: function(ctx) { + if (this.backgroundColor) { + ctx.fillStyle = this.backgroundColor.toLive + ? this.backgroundColor.toLive(ctx) + : this.backgroundColor; + + ctx.fillRect( + this.backgroundColor.offsetX || 0, + this.backgroundColor.offsetY || 0, + this.width, + this.height); + } + if (this.backgroundImage) { + this._draw(ctx, this.backgroundImage); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderOverlay: function(ctx) { + if (this.overlayColor) { + ctx.fillStyle = this.overlayColor.toLive + ? this.overlayColor.toLive(ctx) + : this.overlayColor; + + ctx.fillRect( + this.overlayColor.offsetX || 0, + this.overlayColor.offsetY || 0, + this.width, + this.height); + } + if (this.overlayImage) { + this._draw(ctx, this.overlayImage); + } + }, + + /** + * Method to render only the top canvas. + * Also used to render the group selection box. + * @return {fabric.Canvas} thisArg + * @chainable + */ + renderTop: function () { + var ctx = this.contextTop || this.contextContainer; + this.clearContext(ctx); + + // we render the top context - last object + if (this.selection && this._groupSelector) { + this._drawSelection(); + } + + // delegate rendering to group selection if one exists + // used for drawing selection borders/controls + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + activeGroup.render(ctx); + } + + this._renderOverlay(ctx); + + this.fire('after:render'); + + return this; + }, + + /** + * Returns coordinates of a center of canvas. + * Returned value is an object with top and left properties + * @return {Object} object with "top" and "left" number values + */ + getCenter: function () { + return { + top: this.getHeight() / 2, + left: this.getWidth() / 2 + }; + }, + + /** + * Centers object horizontally. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center horizontally + * @return {fabric.Canvas} thisArg + */ + centerObjectH: function (object) { + this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y)); + this.renderAll(); + return this; + }, + + /** + * Centers object vertically. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center vertically + * @return {fabric.Canvas} thisArg + * @chainable + */ + centerObjectV: function (object) { + this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top)); + this.renderAll(); + return this; + }, + + /** + * Centers object vertically and horizontally. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center vertically and horizontally + * @return {fabric.Canvas} thisArg + * @chainable + */ + centerObject: function(object) { + var center = this.getCenter(); + + this._centerObject(object, new fabric.Point(center.left, center.top)); + this.renderAll(); + return this; + }, + + /** + * @private + * @param {fabric.Object} object Object to center + * @param {fabric.Point} center Center point + * @return {fabric.Canvas} thisArg + * @chainable + */ + _centerObject: function(object, center) { + object.setPositionByOrigin(center, 'center', 'center'); + return this; + }, + + /** + * Returs dataless JSON representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {String} json string + */ + toDatalessJSON: function (propertiesToInclude) { + return this.toDatalessObject(propertiesToInclude); + }, + + /** + * Returns object representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function (propertiesToInclude) { + return this._toObjectMethod('toObject', propertiesToInclude); + }, + + /** + * Returns dataless object representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toDatalessObject: function (propertiesToInclude) { + return this._toObjectMethod('toDatalessObject', propertiesToInclude); + }, + + /** + * @private + */ + _toObjectMethod: function (methodName, propertiesToInclude) { + + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this.discardActiveGroup(); + } + + var data = { + objects: this._toObjects(methodName, propertiesToInclude) + }; + + extend(data, this.__serializeBgOverlay()); + + fabric.util.populateWithProperties(this, data, propertiesToInclude); + + if (activeGroup) { + this.setActiveGroup(new fabric.Group(activeGroup.getObjects(), { + originX: 'center', + originY: 'center' + })); + activeGroup.forEachObject(function(o) { + o.set('active', true); + }); + + if (this._currentTransform) { + this._currentTransform.target = this.getActiveGroup(); + } + } + + return data; + }, + + /** + * @private + */ + _toObjects: function(methodName, propertiesToInclude) { + return this.getObjects().map(function(instance) { + return this._toObject(instance, methodName, propertiesToInclude); + }, this); + }, + + /** + * @private + */ + _toObject: function(instance, methodName, propertiesToInclude) { + var originalValue; + + if (!this.includeDefaultValues) { + originalValue = instance.includeDefaultValues; + instance.includeDefaultValues = false; + } + var object = instance[methodName](propertiesToInclude); + if (!this.includeDefaultValues) { + instance.includeDefaultValues = originalValue; + } + return object; + }, + + /** + * @private + */ + __serializeBgOverlay: function() { + var data = { + background: (this.backgroundColor && this.backgroundColor.toObject) + ? this.backgroundColor.toObject() + : this.backgroundColor + }; + + if (this.overlayColor) { + data.overlay = this.overlayColor.toObject + ? this.overlayColor.toObject() + : this.overlayColor; + } + if (this.backgroundImage) { + data.backgroundImage = this.backgroundImage.toObject(); + } + if (this.overlayImage) { + data.overlayImage = this.overlayImage.toObject(); + } + + return data; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of canvas + * @function + * @param {Object} [options] Options object for SVG output + * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included + * @param {Object} [options.viewBox] SVG viewbox object + * @param {Number} [options.viewBox.x] x-cooridnate of viewbox + * @param {Number} [options.viewBox.y] y-coordinate of viewbox + * @param {Number} [options.viewBox.width] Width of viewbox + * @param {Number} [options.viewBox.height] Height of viewbox + * @param {String} [options.encoding=UTF-8] Encoding of SVG output + * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation. + * @return {String} SVG string + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization} + * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo} + * @example Normal SVG output + * var svg = canvas.toSVG(); + * @example SVG output without preamble (without <?xml ../>) + * var svg = canvas.toSVG({suppressPreamble: true}); + * @example SVG output with viewBox attribute + * var svg = canvas.toSVG({ + * viewBox: { + * x: 100, + * y: 100, + * width: 200, + * height: 300 + * } + * }); + * @example SVG output with different encoding (default: UTF-8) + * var svg = canvas.toSVG({encoding: 'ISO-8859-1'}); + * @example Modify SVG output with reviver function + * var svg = canvas.toSVG(null, function(svg) { + * return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', ''); + * }); + */ + toSVG: function(options, reviver) { + options || (options = { }); + + var markup = []; + + this._setSVGPreamble(markup, options); + this._setSVGHeader(markup, options); + + this._setSVGBgOverlayColor(markup, 'backgroundColor'); + this._setSVGBgOverlayImage(markup, 'backgroundImage'); + + this._setSVGObjects(markup, reviver); + + this._setSVGBgOverlayColor(markup, 'overlayColor'); + this._setSVGBgOverlayImage(markup, 'overlayImage'); + + markup.push(''); + + return markup.join(''); + }, + + /** + * @private + */ + _setSVGPreamble: function(markup, options) { + if (!options.suppressPreamble) { + markup.push( + '', + '\n' + ); + } + }, + + /** + * @private + */ + _setSVGHeader: function(markup, options) { + markup.push( + '', + 'Created with Fabric.js ', fabric.version, '', + '', + fabric.createSVGFontFacesMarkup(this.getObjects()), + fabric.createSVGRefElementsMarkup(this), + '' + ); + }, + + /** + * @private + */ + _setSVGObjects: function(markup, reviver) { + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this.discardActiveGroup(); + } + for (var i = 0, objects = this.getObjects(), len = objects.length; i < len; i++) { + markup.push(objects[i].toSVG(reviver)); + } + if (activeGroup) { + this.setActiveGroup(new fabric.Group(activeGroup.getObjects())); + activeGroup.forEachObject(function(o) { + o.set('active', true); + }); + } + }, + + /** + * @private + */ + _setSVGBgOverlayImage: function(markup, property) { + if (this[property] && this[property].toSVG) { + markup.push(this[property].toSVG()); + } + }, + + /** + * @private + */ + _setSVGBgOverlayColor: function(markup, property) { + if (this[property] && this[property].source) { + markup.push( + '' + ); + } + else if (this[property] && property === 'overlayColor') { + markup.push( + '' + ); + } + }, + /* _TO_SVG_END_ */ + + /** + * Moves an object to the bottom of the stack of drawn objects + * @param {fabric.Object} object Object to send to back + * @return {fabric.Canvas} thisArg + * @chainable + */ + sendToBack: function (object) { + removeFromArray(this._objects, object); + this._objects.unshift(object); + return this.renderAll && this.renderAll(); + }, + + /** + * Moves an object to the top of the stack of drawn objects + * @param {fabric.Object} object Object to send + * @return {fabric.Canvas} thisArg + * @chainable + */ + bringToFront: function (object) { + removeFromArray(this._objects, object); + this._objects.push(object); + return this.renderAll && this.renderAll(); + }, + + /** + * Moves an object down in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object + * @return {fabric.Canvas} thisArg + * @chainable + */ + sendBackwards: function (object, intersecting) { + var idx = this._objects.indexOf(object); + + // if object is not on the bottom of stack + if (idx !== 0) { + var newIdx = this._findNewLowerIndex(object, idx, intersecting); + + removeFromArray(this._objects, object); + this._objects.splice(newIdx, 0, object); + this.renderAll && this.renderAll(); + } + return this; + }, + + /** + * @private + */ + _findNewLowerIndex: function(object, idx, intersecting) { + var newIdx; + + if (intersecting) { + newIdx = idx; + + // traverse down the stack looking for the nearest intersecting object + for (var i = idx - 1; i >= 0; --i) { + + var isIntersecting = object.intersectsWithObject(this._objects[i]) || + object.isContainedWithinObject(this._objects[i]) || + this._objects[i].isContainedWithinObject(object); + + if (isIntersecting) { + newIdx = i; + break; + } + } + } + else { + newIdx = idx - 1; + } + + return newIdx; + }, + + /** + * Moves an object up in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object + * @return {fabric.Canvas} thisArg + * @chainable + */ + bringForward: function (object, intersecting) { + var idx = this._objects.indexOf(object); + + // if object is not on top of stack (last item in an array) + if (idx !== this._objects.length - 1) { + var newIdx = this._findNewUpperIndex(object, idx, intersecting); + + removeFromArray(this._objects, object); + this._objects.splice(newIdx, 0, object); + this.renderAll && this.renderAll(); + } + return this; + }, + + /** + * @private + */ + _findNewUpperIndex: function(object, idx, intersecting) { + var newIdx; + + if (intersecting) { + newIdx = idx; + + // traverse up the stack looking for the nearest intersecting object + for (var i = idx + 1; i < this._objects.length; ++i) { + + var isIntersecting = object.intersectsWithObject(this._objects[i]) || + object.isContainedWithinObject(this._objects[i]) || + this._objects[i].isContainedWithinObject(object); + + if (isIntersecting) { + newIdx = i; + break; + } + } + } + else { + newIdx = idx + 1; + } + + return newIdx; + }, + + /** + * Moves an object to specified level in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Number} index Position to move to + * @return {fabric.Canvas} thisArg + * @chainable + */ + moveTo: function (object, index) { + removeFromArray(this._objects, object); + this._objects.splice(index, 0, object); + return this.renderAll && this.renderAll(); + }, + + /** + * Clears a canvas element and removes all event listeners + * @return {fabric.Canvas} thisArg + * @chainable + */ + dispose: function () { + this.clear(); + this.interactive && this.removeListeners(); + return this; + }, + + /** + * Returns a string representation of an instance + * @return {String} string representation of an instance + */ + toString: function () { + return '#'; + } + }); + + extend(fabric.StaticCanvas.prototype, fabric.Observable); + extend(fabric.StaticCanvas.prototype, fabric.Collection); + extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter); + + extend(fabric.StaticCanvas, /** @lends fabric.StaticCanvas */ { + + /** + * @static + * @type String + * @default + */ + EMPTY_JSON: '{"objects": [], "background": "white"}', + + /** + * Provides a way to check support of some of the canvas methods + * (either those of HTMLCanvasElement itself, or rendering context) + * + * @param {String} methodName Method to check support for; + * Could be one of "getImageData", "toDataURL", "toDataURLWithQuality" or "setLineDash" + * @return {Boolean | null} `true` if method is supported (or at least exists), + * `null` if canvas element or context can not be initialized + */ + supports: function (methodName) { + var el = fabric.util.createCanvasElement(); + + if (!el || !el.getContext) { + return null; + } + + var ctx = el.getContext('2d'); + if (!ctx) { + return null; + } + + switch (methodName) { + + case 'getImageData': + return typeof ctx.getImageData !== 'undefined'; + + case 'setLineDash': + return typeof ctx.setLineDash !== 'undefined'; + + case 'toDataURL': + return typeof el.toDataURL !== 'undefined'; + + case 'toDataURLWithQuality': + try { + el.toDataURL('image/jpeg', 0); + return true; + } + catch (e) { } + return false; + + default: + return null; + } + } + }); + + /** + * Returns JSON representation of canvas + * @function + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {String} JSON string + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization} + * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo} + * @example JSON without additional properties + * var json = canvas.toJSON(); + * @example JSON with additional properties included + * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY', 'lockUniScaling']); + * @example JSON without default values + * canvas.includeDefaultValues = false; + * var json = canvas.toJSON(); + */ + fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject; + +})(); + + +/** + * BaseBrush class + * @class fabric.BaseBrush + * @see {@link http://fabricjs.com/freedrawing/|Freedrawing demo} + */ +fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ { + + /** + * Color of a brush + * @type String + * @default + */ + color: 'rgb(0, 0, 0)', + + /** + * Width of a brush + * @type Number + * @default + */ + width: 1, + + /** + * Shadow object representing shadow of this shape. + * Backwards incompatibility note: This property replaces "shadowColor" (String), "shadowOffsetX" (Number), + * "shadowOffsetY" (Number) and "shadowBlur" (Number) since v1.2.12 + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Line endings style of a brush (one of "butt", "round", "square") + * @type String + * @default + */ + strokeLineCap: 'round', + + /** + * Corner style of a brush (one of "bevil", "round", "miter") + * @type String + * @default + */ + strokeLineJoin: 'round', + + /** + * Sets shadow of an object + * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") + * @return {fabric.Object} thisArg + * @chainable + */ + setShadow: function(options) { + this.shadow = new fabric.Shadow(options); + return this; + }, + + /** + * Sets brush styles + * @private + */ + _setBrushStyles: function() { + var ctx = this.canvas.contextTop; + + ctx.strokeStyle = this.color; + ctx.lineWidth = this.width; + ctx.lineCap = this.strokeLineCap; + ctx.lineJoin = this.strokeLineJoin; + }, + + /** + * Sets brush shadow styles + * @private + */ + _setShadow: function() { + if (!this.shadow) { + return; + } + + var ctx = this.canvas.contextTop; + + ctx.shadowColor = this.shadow.color; + ctx.shadowBlur = this.shadow.blur; + ctx.shadowOffsetX = this.shadow.offsetX; + ctx.shadowOffsetY = this.shadow.offsetY; + }, + + /** + * Removes brush shadow styles + * @private + */ + _resetShadow: function() { + var ctx = this.canvas.contextTop; + + ctx.shadowColor = ''; + ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; + } +}); + + +(function() { + + var utilMin = fabric.util.array.min, + utilMax = fabric.util.array.max; + + /** + * PencilBrush class + * @class fabric.PencilBrush + * @extends fabric.BaseBrush + */ + fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.PencilBrush.prototype */ { + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.PencilBrush} Instance of a pencil brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this._points = [ ]; + }, + + /** + * Inovoked on mouse down + * @param {Object} pointer + */ + onMouseDown: function(pointer) { + this._prepareForDrawing(pointer); + // capture coordinates immediately + // this allows to draw dots (when movement never occurs) + this._captureDrawingPath(pointer); + this._render(); + }, + + /** + * Inovoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this._captureDrawingPath(pointer); + // redraw curve + // clear top canvas + this.canvas.clearContext(this.canvas.contextTop); + this._render(); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + this._finalizeAndAddPath(); + }, + + /** + * @private + * @param {Object} pointer Actual mouse position related to the canvas. + */ + _prepareForDrawing: function(pointer) { + + var p = new fabric.Point(pointer.x, pointer.y); + + this._reset(); + this._addPoint(p); + + this.canvas.contextTop.moveTo(p.x, p.y); + }, + + /** + * @private + * @param {fabric.Point} point Point to be added to points array + */ + _addPoint: function(point) { + this._points.push(point); + }, + + /** + * Clear points array and set contextTop canvas style. + * @private + */ + _reset: function() { + this._points.length = 0; + + this._setBrushStyles(); + this._setShadow(); + }, + + /** + * @private + * @param {Object} pointer Actual mouse position related to the canvas. + */ + _captureDrawingPath: function(pointer) { + var pointerPoint = new fabric.Point(pointer.x, pointer.y); + this._addPoint(pointerPoint); + }, + + /** + * Draw a smooth path on the topCanvas using quadraticCurveTo + * @private + */ + _render: function() { + var ctx = this.canvas.contextTop, + v = this.canvas.viewportTransform, + p1 = this._points[0], + p2 = this._points[1]; + + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + ctx.beginPath(); + + //if we only have 2 points in the path and they are the same + //it means that the user only clicked the canvas without moving the mouse + //then we should be drawing a dot. A path isn't drawn between two identical dots + //that's why we set them apart a bit + if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) { + p1.x -= 0.5; + p2.x += 0.5; + } + ctx.moveTo(p1.x, p1.y); + + for (var i = 1, len = this._points.length; i < len; i++) { + // we pick the point between pi + 1 & pi + 2 as the + // end point and p1 as our control point. + var midPoint = p1.midPointFrom(p2); + ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y); + + p1 = this._points[i]; + p2 = this._points[i + 1]; + } + // Draw last line as a straight line while + // we wait for the next point to be able to calculate + // the bezier control point + ctx.lineTo(p1.x, p1.y); + ctx.stroke(); + ctx.restore(); + }, + + /** + * Return an SVG path based on our captured points and their bounding box + * @private + */ + _getSVGPathData: function() { + this.box = this.getPathBoundingBox(this._points); + return this.convertPointsToSVGPath( + this._points, this.box.minX, this.box.minY); + }, + + /** + * Returns bounding box of a path based on given points + * @param {Array} points Array of points + * @return {Object} Object with minX, minY, maxX, maxY + */ + getPathBoundingBox: function(points) { + var xBounds = [], + yBounds = [], + p1 = points[0], + p2 = points[1], + startPoint = p1; + + for (var i = 1, len = points.length; i < len; i++) { + var midPoint = p1.midPointFrom(p2); + // with startPoint, p1 as control point, midpoint as end point + xBounds.push(startPoint.x); + xBounds.push(midPoint.x); + yBounds.push(startPoint.y); + yBounds.push(midPoint.y); + + p1 = points[i]; + p2 = points[i + 1]; + startPoint = midPoint; + } + + xBounds.push(p1.x); + yBounds.push(p1.y); + + return { + minX: utilMin(xBounds), + minY: utilMin(yBounds), + maxX: utilMax(xBounds), + maxY: utilMax(yBounds) + }; + }, + + /** + * Converts points to SVG path + * @param {Array} points Array of points + * @param {Number} minX + * @param {Number} minY + * @return {String} SVG path + */ + convertPointsToSVGPath: function(points, minX, minY) { + var path = [], + p1 = new fabric.Point(points[0].x - minX, points[0].y - minY), + p2 = new fabric.Point(points[1].x - minX, points[1].y - minY); + + path.push('M ', points[0].x - minX, ' ', points[0].y - minY, ' '); + for (var i = 1, len = points.length; i < len; i++) { + var midPoint = p1.midPointFrom(p2); + // p1 is our bezier control point + // midpoint is our endpoint + // start point is p(i-1) value. + path.push('Q ', p1.x, ' ', p1.y, ' ', midPoint.x, ' ', midPoint.y, ' '); + p1 = new fabric.Point(points[i].x - minX, points[i].y - minY); + if ((i + 1) < points.length) { + p2 = new fabric.Point(points[i + 1].x - minX, points[i + 1].y - minY); + } + } + path.push('L ', p1.x, ' ', p1.y, ' '); + return path; + }, + + /** + * Creates fabric.Path object to add on canvas + * @param {String} pathData Path data + * @return {fabric.Path} Path to add on canvas + */ + createPath: function(pathData) { + var path = new fabric.Path(pathData); + path.fill = null; + path.stroke = this.color; + path.strokeWidth = this.width; + path.strokeLineCap = this.strokeLineCap; + path.strokeLineJoin = this.strokeLineJoin; + + if (this.shadow) { + this.shadow.affectStroke = true; + path.setShadow(this.shadow); + } + + return path; + }, + + /** + * On mouseup after drawing the path on contextTop canvas + * we use the points captured to create an new fabric path object + * and add it to the fabric canvas. + */ + _finalizeAndAddPath: function() { + var ctx = this.canvas.contextTop; + ctx.closePath(); + + var pathData = this._getSVGPathData().join(''); + if (pathData === 'M 0 0 Q 0 0 0 0 L 0 0') { + // do not create 0 width/height paths, as they are + // rendered inconsistently across browsers + // Firefox 4, for example, renders a dot, + // whereas Chrome 10 renders nothing + this.canvas.renderAll(); + return; + } + + // set path origin coordinates based on our bounding box + var originLeft = this.box.minX + (this.box.maxX - this.box.minX) / 2, + originTop = this.box.minY + (this.box.maxY - this.box.minY) / 2; + + this.canvas.contextTop.arc(originLeft, originTop, 3, 0, Math.PI * 2, false); + + var path = this.createPath(pathData); + path.set({ + left: originLeft, + top: originTop, + originX: 'center', + originY: 'center' + }); + + this.canvas.add(path); + path.setCoords(); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderAll(); + + // fire event 'path' created + this.canvas.fire('path:created', { path: path }); + } + }); +})(); + + +/** + * CircleBrush class + * @class fabric.CircleBrush + */ +fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.CircleBrush.prototype */ { + + /** + * Width of a brush + * @type Number + * @default + */ + width: 10, + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.CircleBrush} Instance of a circle brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this.points = [ ]; + }, + /** + * Invoked inside on mouse down and mouse move + * @param {Object} pointer + */ + drawDot: function(pointer) { + var point = this.addPoint(pointer), + ctx = this.canvas.contextTop, + v = this.canvas.viewportTransform; + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + + ctx.fillStyle = point.fill; + ctx.beginPath(); + ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false); + ctx.closePath(); + ctx.fill(); + + ctx.restore(); + }, + + /** + * Invoked on mouse down + */ + onMouseDown: function(pointer) { + this.points.length = 0; + this.canvas.clearContext(this.canvas.contextTop); + this._setShadow(); + this.drawDot(pointer); + }, + + /** + * Invoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this.drawDot(pointer); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; + this.canvas.renderOnAddRemove = false; + + var circles = [ ]; + + for (var i = 0, len = this.points.length; i < len; i++) { + var point = this.points[i], + circle = new fabric.Circle({ + radius: point.radius, + left: point.x, + top: point.y, + originX: 'center', + originY: 'center', + fill: point.fill + }); + + this.shadow && circle.setShadow(this.shadow); + + circles.push(circle); + } + var group = new fabric.Group(circles, { originX: 'center', originY: 'center' }); + group.canvas = this.canvas; + + this.canvas.add(group); + this.canvas.fire('path:created', { path: group }); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderOnAddRemove = originalRenderOnAddRemove; + this.canvas.renderAll(); + }, + + /** + * @param {Object} pointer + * @return {fabric.Point} Just added pointer point + */ + addPoint: function(pointer) { + var pointerPoint = new fabric.Point(pointer.x, pointer.y), + + circleRadius = fabric.util.getRandomInt( + Math.max(0, this.width - 20), this.width + 20) / 2, + + circleColor = new fabric.Color(this.color) + .setAlpha(fabric.util.getRandomInt(0, 100) / 100) + .toRgba(); + + pointerPoint.radius = circleRadius; + pointerPoint.fill = circleColor; + + this.points.push(pointerPoint); + + return pointerPoint; + } +}); + + +/** + * SprayBrush class + * @class fabric.SprayBrush + */ +fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric.SprayBrush.prototype */ { + + /** + * Width of a spray + * @type Number + * @default + */ + width: 10, + + /** + * Density of a spray (number of dots per chunk) + * @type Number + * @default + */ + density: 20, + + /** + * Width of spray dots + * @type Number + * @default + */ + dotWidth: 1, + + /** + * Width variance of spray dots + * @type Number + * @default + */ + dotWidthVariance: 1, + + /** + * Whether opacity of a dot should be random + * @type Boolean + * @default + */ + randomOpacity: false, + + /** + * Whether overlapping dots (rectangles) should be removed (for performance reasons) + * @type Boolean + * @default + */ + optimizeOverlapping: true, + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.SprayBrush} Instance of a spray brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this.sprayChunks = [ ]; + }, + + /** + * Invoked on mouse down + * @param {Object} pointer + */ + onMouseDown: function(pointer) { + this.sprayChunks.length = 0; + this.canvas.clearContext(this.canvas.contextTop); + this._setShadow(); + + this.addSprayChunk(pointer); + this.render(); + }, + + /** + * Invoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this.addSprayChunk(pointer); + this.render(); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; + this.canvas.renderOnAddRemove = false; + + var rects = [ ]; + + for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) { + var sprayChunk = this.sprayChunks[i]; + + for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) { + + var rect = new fabric.Rect({ + width: sprayChunk[j].width, + height: sprayChunk[j].width, + left: sprayChunk[j].x + 1, + top: sprayChunk[j].y + 1, + originX: 'center', + originY: 'center', + fill: this.color + }); + + this.shadow && rect.setShadow(this.shadow); + rects.push(rect); + } + } + + if (this.optimizeOverlapping) { + rects = this._getOptimizedRects(rects); + } + + var group = new fabric.Group(rects, { originX: 'center', originY: 'center' }); + group.canvas = this.canvas; + + this.canvas.add(group); + this.canvas.fire('path:created', { path: group }); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderOnAddRemove = originalRenderOnAddRemove; + this.canvas.renderAll(); + }, + + /** + * @private + * @param {Array} rects + */ + _getOptimizedRects: function(rects) { + + // avoid creating duplicate rects at the same coordinates + var uniqueRects = { }, key; + + for (var i = 0, len = rects.length; i < len; i++) { + key = rects[i].left + '' + rects[i].top; + if (!uniqueRects[key]) { + uniqueRects[key] = rects[i]; + } + } + var uniqueRectsArray = [ ]; + for (key in uniqueRects) { + uniqueRectsArray.push(uniqueRects[key]); + } + + return uniqueRectsArray; + }, + + /** + * Renders brush + */ + render: function() { + var ctx = this.canvas.contextTop; + ctx.fillStyle = this.color; + + var v = this.canvas.viewportTransform; + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + + for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) { + var point = this.sprayChunkPoints[i]; + if (typeof point.opacity !== 'undefined') { + ctx.globalAlpha = point.opacity; + } + ctx.fillRect(point.x, point.y, point.width, point.width); + } + ctx.restore(); + }, + + /** + * @param {Object} pointer + */ + addSprayChunk: function(pointer) { + this.sprayChunkPoints = [ ]; + + var x, y, width, radius = this.width / 2; + + for (var i = 0; i < this.density; i++) { + + x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius); + y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius); + + if (this.dotWidthVariance) { + width = fabric.util.getRandomInt( + // bottom clamp width to 1 + Math.max(1, this.dotWidth - this.dotWidthVariance), + this.dotWidth + this.dotWidthVariance); + } + else { + width = this.dotWidth; + } + + var point = new fabric.Point(x, y); + point.width = width; + + if (this.randomOpacity) { + point.opacity = fabric.util.getRandomInt(0, 100) / 100; + } + + this.sprayChunkPoints.push(point); + } + + this.sprayChunks.push(this.sprayChunkPoints); + } +}); + + +/** + * PatternBrush class + * @class fabric.PatternBrush + * @extends fabric.BaseBrush + */ +fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fabric.PatternBrush.prototype */ { + + getPatternSrc: function() { + + var dotWidth = 20, + dotDistance = 5, + patternCanvas = fabric.document.createElement('canvas'), + patternCtx = patternCanvas.getContext('2d'); + + patternCanvas.width = patternCanvas.height = dotWidth + dotDistance; + + patternCtx.fillStyle = this.color; + patternCtx.beginPath(); + patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); + patternCtx.closePath(); + patternCtx.fill(); + + return patternCanvas; + }, + + getPatternSrcFunction: function() { + return String(this.getPatternSrc).replace('this.color', '"' + this.color + '"'); + }, + + /** + * Creates "pattern" instance property + */ + getPattern: function() { + return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), 'repeat'); + }, + + /** + * Sets brush styles + */ + _setBrushStyles: function() { + this.callSuper('_setBrushStyles'); + this.canvas.contextTop.strokeStyle = this.getPattern(); + }, + + /** + * Creates path + */ + createPath: function(pathData) { + var path = this.callSuper('createPath', pathData); + path.stroke = new fabric.Pattern({ + source: this.source || this.getPatternSrcFunction() + }); + return path; + } +}); + + +(function() { + + var getPointer = fabric.util.getPointer, + degreesToRadians = fabric.util.degreesToRadians, + radiansToDegrees = fabric.util.radiansToDegrees, + atan2 = Math.atan2, + abs = Math.abs, + + STROKE_OFFSET = 0.5; + + /** + * Canvas class + * @class fabric.Canvas + * @extends fabric.StaticCanvas + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#canvas} + * @see {@link fabric.Canvas#initialize} for constructor definition + * + * @fires object:modified + * @fires object:rotating + * @fires object:scaling + * @fires object:moving + * @fires object:selected + * + * @fires before:selection:cleared + * @fires selection:cleared + * @fires selection:created + * + * @fires path:created + * @fires mouse:down + * @fires mouse:move + * @fires mouse:up + * @fires mouse:over + * @fires mouse:out + * + */ + fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ { + + /** + * Constructor + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(el, options) { + options || (options = { }); + + this._initStatic(el, options); + this._initInteractive(); + this._createCacheCanvas(); + + fabric.Canvas.activeInstance = this; + }, + + /** + * When true, objects can be transformed by one side (unproportionally) + * @type Boolean + * @default + */ + uniScaleTransform: false, + + /** + * When true, objects use center point as the origin of scale transformation. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredScaling: false, + + /** + * When true, objects use center point as the origin of rotate transformation. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredRotation: false, + + /** + * Indicates that canvas is interactive. This property should not be changed. + * @type Boolean + * @default + */ + interactive: true, + + /** + * Indicates whether group selection should be enabled + * @type Boolean + * @default + */ + selection: true, + + /** + * Color of selection + * @type String + * @default + */ + selectionColor: 'rgba(100, 100, 255, 0.3)', // blue + + /** + * Default dash array pattern + * If not empty the selection border is dashed + * @type Array + */ + selectionDashArray: [ ], + + /** + * Color of the border of selection (usually slightly darker than color of selection itself) + * @type String + * @default + */ + selectionBorderColor: 'rgba(255, 255, 255, 0.3)', + + /** + * Width of a line used in object/group selection + * @type Number + * @default + */ + selectionLineWidth: 1, + + /** + * Default cursor value used when hovering over an object on canvas + * @type String + * @default + */ + hoverCursor: 'move', + + /** + * Default cursor value used when moving an object on canvas + * @type String + * @default + */ + moveCursor: 'move', + + /** + * Default cursor value used for the entire canvas + * @type String + * @default + */ + defaultCursor: 'default', + + /** + * Cursor value used during free drawing + * @type String + * @default + */ + freeDrawingCursor: 'crosshair', + + /** + * Cursor value used for rotation point + * @type String + * @default + */ + rotationCursor: 'crosshair', + + /** + * Default element class that's given to wrapper (div) element of canvas + * @type String + * @default + */ + containerClass: 'canvas-container', + + /** + * When true, object detection happens on per-pixel basis rather than on per-bounding-box + * @type Boolean + * @default + */ + perPixelTargetFind: false, + + /** + * Number of pixels around target pixel to tolerate (consider active) during object detection + * @type Number + * @default + */ + targetFindTolerance: 0, + + /** + * When true, target detection is skipped when hovering over canvas. This can be used to improve performance. + * @type Boolean + * @default + */ + skipTargetFind: false, + + /** + * @private + */ + _initInteractive: function() { + this._currentTransform = null; + this._groupSelector = null; + this._initWrapperElement(); + this._createUpperCanvas(); + this._initEventListeners(); + + this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this); + + this.calcOffset(); + }, + + /** + * Resets the current transform to its original values and chooses the type of resizing based on the event + * @private + * @param {Event} e Event object fired on mousemove + */ + _resetCurrentTransform: function(e) { + var t = this._currentTransform; + + t.target.set({ + scaleX: t.original.scaleX, + scaleY: t.original.scaleY, + left: t.original.left, + top: t.original.top + }); + + if (this._shouldCenterTransform(e, t.target)) { + if (t.action === 'rotate') { + this._setOriginToCenter(t.target); + } + else { + if (t.originX !== 'center') { + if (t.originX === 'right') { + t.mouseXSign = -1; + } + else { + t.mouseXSign = 1; + } + } + if (t.originY !== 'center') { + if (t.originY === 'bottom') { + t.mouseYSign = -1; + } + else { + t.mouseYSign = 1; + } + } + + t.originX = 'center'; + t.originY = 'center'; + } + } + else { + t.originX = t.original.originX; + t.originY = t.original.originY; + } + }, + + /** + * Checks if point is contained within an area of given object + * @param {Event} e Event object + * @param {fabric.Object} target Object to test against + * @return {Boolean} true if point is contained within an area of given object + */ + containsPoint: function (e, target) { + var pointer = this.getPointer(e, true), + xy = this._normalizePointer(target, pointer); + + // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html + // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html + return (target.containsPoint(xy) || target._findTargetCorner(pointer)); + }, + + /** + * @private + */ + _normalizePointer: function (object, pointer) { + var activeGroup = this.getActiveGroup(), + x = pointer.x, + y = pointer.y, + isObjectInGroup = ( + activeGroup && + object.type !== 'group' && + activeGroup.contains(object)), + lt; + + if (isObjectInGroup) { + lt = new fabric.Point(activeGroup.left, activeGroup.top); + lt = fabric.util.transformPoint(lt, this.viewportTransform, true); + x -= lt.x; + y -= lt.y; + } + return { x: x, y: y }; + }, + + /** + * Returns true if object is transparent at a certain location + * @param {fabric.Object} target Object to check + * @param {Number} x Left coordinate + * @param {Number} y Top coordinate + * @return {Boolean} + */ + isTargetTransparent: function (target, x, y) { + var hasBorders = target.hasBorders, + transparentCorners = target.transparentCorners; + + target.hasBorders = target.transparentCorners = false; + + this._draw(this.contextCache, target); + + target.hasBorders = hasBorders; + target.transparentCorners = transparentCorners; + + var isTransparent = fabric.util.isTransparent( + this.contextCache, x, y, this.targetFindTolerance); + + this.clearContext(this.contextCache); + + return isTransparent; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _shouldClearSelection: function (e, target) { + var activeGroup = this.getActiveGroup(), + activeObject = this.getActiveObject(); + + return ( + !target + || + (target && + activeGroup && + !activeGroup.contains(target) && + activeGroup !== target && + !e.shiftKey) + || + (target && !target.evented) + || + (target && + !target.selectable && + activeObject && + activeObject !== target) + ); + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _shouldCenterTransform: function (e, target) { + if (!target) { + return; + } + + var t = this._currentTransform, + centerTransform; + + if (t.action === 'scale' || t.action === 'scaleX' || t.action === 'scaleY') { + centerTransform = this.centeredScaling || target.centeredScaling; + } + else if (t.action === 'rotate') { + centerTransform = this.centeredRotation || target.centeredRotation; + } + + return centerTransform ? !e.altKey : e.altKey; + }, + + /** + * @private + */ + _getOriginFromCorner: function(target, corner) { + var origin = { + x: target.originX, + y: target.originY + }; + + if (corner === 'ml' || corner === 'tl' || corner === 'bl') { + origin.x = 'right'; + } + else if (corner === 'mr' || corner === 'tr' || corner === 'br') { + origin.x = 'left'; + } + + if (corner === 'tl' || corner === 'mt' || corner === 'tr') { + origin.y = 'bottom'; + } + else if (corner === 'bl' || corner === 'mb' || corner === 'br') { + origin.y = 'top'; + } + + return origin; + }, + + /** + * @private + */ + _getActionFromCorner: function(target, corner) { + var action = 'drag'; + if (corner) { + action = (corner === 'ml' || corner === 'mr') + ? 'scaleX' + : (corner === 'mt' || corner === 'mb') + ? 'scaleY' + : corner === 'mtr' + ? 'rotate' + : 'scale'; + } + return action; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _setupCurrentTransform: function (e, target) { + if (!target) { + return; + } + + var pointer = this.getPointer(e), + corner = target._findTargetCorner(this.getPointer(e, true)), + action = this._getActionFromCorner(target, corner), + origin = this._getOriginFromCorner(target, corner); + + this._currentTransform = { + target: target, + action: action, + scaleX: target.scaleX, + scaleY: target.scaleY, + offsetX: pointer.x - target.left, + offsetY: pointer.y - target.top, + originX: origin.x, + originY: origin.y, + ex: pointer.x, + ey: pointer.y, + left: target.left, + top: target.top, + theta: degreesToRadians(target.angle), + width: target.width * target.scaleX, + mouseXSign: 1, + mouseYSign: 1 + }; + + this._currentTransform.original = { + left: target.left, + top: target.top, + scaleX: target.scaleX, + scaleY: target.scaleY, + originX: origin.x, + originY: origin.y + }; + + this._resetCurrentTransform(e); + }, + + /** + * Translates object by "setting" its left/top + * @private + * @param {Number} x pointer's x coordinate + * @param {Number} y pointer's y coordinate + */ + _translateObject: function (x, y) { + var target = this._currentTransform.target; + + if (!target.get('lockMovementX')) { + target.set('left', x - this._currentTransform.offsetX); + } + if (!target.get('lockMovementY')) { + target.set('top', y - this._currentTransform.offsetY); + } + }, + + /** + * Scales object by invoking its scaleX/scaleY methods + * @private + * @param {Number} x pointer's x coordinate + * @param {Number} y pointer's y coordinate + * @param {String} by Either 'x' or 'y' - specifies dimension constraint by which to scale an object. + * When not provided, an object is scaled by both dimensions equally + */ + _scaleObject: function (x, y, by) { + var t = this._currentTransform, + target = t.target, + lockScalingX = target.get('lockScalingX'), + lockScalingY = target.get('lockScalingY'), + lockScalingFlip = target.get('lockScalingFlip'); + + if (lockScalingX && lockScalingY) { + return; + } + + // Get the constraint point + var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY), + localMouse = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY); + + this._setLocalMouse(localMouse, t); + + // Actually scale the object + this._setObjectScale(localMouse, t, lockScalingX, lockScalingY, by, lockScalingFlip); + + // Make sure the constraints apply + target.setPositionByOrigin(constraintPosition, t.originX, t.originY); + }, + + /** + * @private + */ + _setObjectScale: function(localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip) { + var target = transform.target, forbidScalingX = false, forbidScalingY = false; + + transform.newScaleX = localMouse.x / (target.width + target.strokeWidth); + transform.newScaleY = localMouse.y / (target.height + target.strokeWidth); + + if (lockScalingFlip && transform.newScaleX <= 0 && transform.newScaleX < target.scaleX) { + forbidScalingX = true; + } + + if (lockScalingFlip && transform.newScaleY <= 0 && transform.newScaleY < target.scaleY) { + forbidScalingY = true; + } + + if (by === 'equally' && !lockScalingX && !lockScalingY) { + forbidScalingX || forbidScalingY || this._scaleObjectEqually(localMouse, target, transform); + } + else if (!by) { + forbidScalingX || lockScalingX || target.set('scaleX', transform.newScaleX); + forbidScalingY || lockScalingY || target.set('scaleY', transform.newScaleY); + } + else if (by === 'x' && !target.get('lockUniScaling')) { + forbidScalingX || lockScalingX || target.set('scaleX', transform.newScaleX); + } + else if (by === 'y' && !target.get('lockUniScaling')) { + forbidScalingY || lockScalingY || target.set('scaleY', transform.newScaleY); + } + + forbidScalingX || forbidScalingY || this._flipObject(transform); + + }, + + /** + * @private + */ + _scaleObjectEqually: function(localMouse, target, transform) { + + var dist = localMouse.y + localMouse.x, + lastDist = (target.height + (target.strokeWidth)) * transform.original.scaleY + + (target.width + (target.strokeWidth)) * transform.original.scaleX; + + // We use transform.scaleX/Y instead of target.scaleX/Y + // because the object may have a min scale and we'll loose the proportions + transform.newScaleX = transform.original.scaleX * dist / lastDist; + transform.newScaleY = transform.original.scaleY * dist / lastDist; + + target.set('scaleX', transform.newScaleX); + target.set('scaleY', transform.newScaleY); + }, + + /** + * @private + */ + _flipObject: function(transform) { + if (transform.newScaleX < 0) { + if (transform.originX === 'left') { + transform.originX = 'right'; + } + else if (transform.originX === 'right') { + transform.originX = 'left'; + } + } + + if (transform.newScaleY < 0) { + if (transform.originY === 'top') { + transform.originY = 'bottom'; + } + else if (transform.originY === 'bottom') { + transform.originY = 'top'; + } + } + }, + + /** + * @private + */ + _setLocalMouse: function(localMouse, t) { + var target = t.target; + + if (t.originX === 'right') { + localMouse.x *= -1; + } + else if (t.originX === 'center') { + localMouse.x *= t.mouseXSign * 2; + + if (localMouse.x < 0) { + t.mouseXSign = -t.mouseXSign; + } + } + + if (t.originY === 'bottom') { + localMouse.y *= -1; + } + else if (t.originY === 'center') { + localMouse.y *= t.mouseYSign * 2; + + if (localMouse.y < 0) { + t.mouseYSign = -t.mouseYSign; + } + } + + // adjust the mouse coordinates when dealing with padding + if (abs(localMouse.x) > target.padding) { + if (localMouse.x < 0) { + localMouse.x += target.padding; + } + else { + localMouse.x -= target.padding; + } + } + else { // mouse is within the padding, set to 0 + localMouse.x = 0; + } + + if (abs(localMouse.y) > target.padding) { + if (localMouse.y < 0) { + localMouse.y += target.padding; + } + else { + localMouse.y -= target.padding; + } + } + else { + localMouse.y = 0; + } + }, + + /** + * Rotates object by invoking its rotate method + * @private + * @param {Number} x pointer's x coordinate + * @param {Number} y pointer's y coordinate + */ + _rotateObject: function (x, y) { + + var t = this._currentTransform; + + if (t.target.get('lockRotation')) { + return; + } + + var lastAngle = atan2(t.ey - t.top, t.ex - t.left), + curAngle = atan2(y - t.top, x - t.left), + angle = radiansToDegrees(curAngle - lastAngle + t.theta); + + // normalize angle to positive value + if (angle < 0) { + angle = 360 + angle; + } + + t.target.angle = angle; + }, + + /** + * Set the cursor type of the canvas element + * @param {String} value Cursor type of the canvas element. + * @see http://www.w3.org/TR/css3-ui/#cursor + */ + setCursor: function (value) { + this.upperCanvasEl.style.cursor = value; + }, + + /** + * @private + */ + _resetObjectTransform: function (target) { + target.scaleX = 1; + target.scaleY = 1; + target.setAngle(0); + }, + + /** + * @private + */ + _drawSelection: function () { + var ctx = this.contextTop, + groupSelector = this._groupSelector, + left = groupSelector.left, + top = groupSelector.top, + aleft = abs(left), + atop = abs(top); + + ctx.fillStyle = this.selectionColor; + + ctx.fillRect( + groupSelector.ex - ((left > 0) ? 0 : -left), + groupSelector.ey - ((top > 0) ? 0 : -top), + aleft, + atop + ); + + ctx.lineWidth = this.selectionLineWidth; + ctx.strokeStyle = this.selectionBorderColor; + + // selection border + if (this.selectionDashArray.length > 1) { + + var px = groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0: aleft), + py = groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0: atop); + + ctx.beginPath(); + + fabric.util.drawDashedLine(ctx, px, py, px + aleft, py, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px, py + atop - 1, px + aleft, py + atop - 1, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px, py, px, py + atop, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px + aleft - 1, py, px + aleft - 1, py + atop, this.selectionDashArray); + + ctx.closePath(); + ctx.stroke(); + } + else { + ctx.strokeRect( + groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft), + groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop), + aleft, + atop + ); + } + }, + + /** + * @private + */ + _isLastRenderedObject: function(e) { + return ( + this.controlsAboveOverlay && + this.lastRenderedObjectWithControlsAboveOverlay && + this.lastRenderedObjectWithControlsAboveOverlay.visible && + this.containsPoint(e, this.lastRenderedObjectWithControlsAboveOverlay) && + this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e, true))); + }, + + /** + * Method that determines what object we are clicking on + * @param {Event} e mouse event + * @param {Boolean} skipGroup when true, group is skipped and only objects are traversed through + */ + findTarget: function (e, skipGroup) { + if (this.skipTargetFind) { + return; + } + + if (this._isLastRenderedObject(e)) { + return this.lastRenderedObjectWithControlsAboveOverlay; + } + + // first check current group (if one exists) + var activeGroup = this.getActiveGroup(); + if (activeGroup && !skipGroup && this.containsPoint(e, activeGroup)) { + return activeGroup; + } + + var target = this._searchPossibleTargets(e); + this._fireOverOutEvents(target); + + return target; + }, + + /** + * @private + */ + _fireOverOutEvents: function(target) { + if (target) { + if (this._hoveredTarget !== target) { + this.fire('mouse:over', { target: target }); + target.fire('mouseover'); + if (this._hoveredTarget) { + this.fire('mouse:out', { target: this._hoveredTarget }); + this._hoveredTarget.fire('mouseout'); + } + this._hoveredTarget = target; + } + } + else if (this._hoveredTarget) { + this.fire('mouse:out', { target: this._hoveredTarget }); + this._hoveredTarget.fire('mouseout'); + this._hoveredTarget = null; + } + }, + + /** + * @private + */ + _checkTarget: function(e, obj, pointer) { + if (obj && + obj.visible && + obj.evented && + this.containsPoint(e, obj)){ + if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) { + var isTransparent = this.isTargetTransparent(obj, pointer.x, pointer.y); + if (!isTransparent) { + return true; + } + } + else { + return true; + } + } + }, + + /** + * @private + */ + _searchPossibleTargets: function(e) { + + // Cache all targets where their bounding box contains point. + var target, + pointer = this.getPointer(e, true), + i = this._objects.length; + + while (i--) { + if (this._checkTarget(e, this._objects[i], pointer)){ + this.relatedTarget = this._objects[i]; + target = this._objects[i]; + break; + } + } + + return target; + }, + + /** + * Returns pointer coordinates relative to canvas. + * @param {Event} e + * @return {Object} object with "x" and "y" number values + */ + getPointer: function (e, ignoreZoom, upperCanvasEl) { + if (!upperCanvasEl) { + upperCanvasEl = this.upperCanvasEl; + } + var pointer = getPointer(e, upperCanvasEl), + bounds = upperCanvasEl.getBoundingClientRect(), + cssScale; + + this.calcOffset(); + + pointer.x = pointer.x - this._offset.left; + pointer.y = pointer.y - this._offset.top; + if (!ignoreZoom) { + pointer = fabric.util.transformPoint( + pointer, + fabric.util.invertTransform(this.viewportTransform) + ); + } + + if (bounds.width === 0 || bounds.height === 0) { + // If bounds are not available (i.e. not visible), do not apply scale. + cssScale = { width: 1, height: 1 }; + } + else { + cssScale = { + width: upperCanvasEl.width / bounds.width, + height: upperCanvasEl.height / bounds.height + }; + } + + return { + x: pointer.x * cssScale.width, + y: pointer.y * cssScale.height + }; + }, + + /** + * @private + * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized + */ + _createUpperCanvas: function () { + var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/, ''); + + this.upperCanvasEl = this._createCanvasElement(); + fabric.util.addClass(this.upperCanvasEl, 'upper-canvas ' + lowerCanvasClass); + + this.wrapperEl.appendChild(this.upperCanvasEl); + + this._copyCanvasStyle(this.lowerCanvasEl, this.upperCanvasEl); + this._applyCanvasStyle(this.upperCanvasEl); + this.contextTop = this.upperCanvasEl.getContext('2d'); + }, + + /** + * @private + */ + _createCacheCanvas: function () { + this.cacheCanvasEl = this._createCanvasElement(); + this.cacheCanvasEl.setAttribute('width', this.width); + this.cacheCanvasEl.setAttribute('height', this.height); + this.contextCache = this.cacheCanvasEl.getContext('2d'); + }, + + /** + * @private + */ + _initWrapperElement: function () { + this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', { + 'class': this.containerClass + }); + fabric.util.setStyle(this.wrapperEl, { + width: this.getWidth() + 'px', + height: this.getHeight() + 'px', + position: 'relative' + }); + fabric.util.makeElementUnselectable(this.wrapperEl); + }, + + /** + * @private + * @param {HTMLElement} element canvas element to apply styles on + */ + _applyCanvasStyle: function (element) { + var width = this.getWidth() || element.width, + height = this.getHeight() || element.height; + + fabric.util.setStyle(element, { + position: 'absolute', + width: width + 'px', + height: height + 'px', + left: 0, + top: 0 + }); + element.width = width; + element.height = height; + fabric.util.makeElementUnselectable(element); + }, + + /** + * Copys the the entire inline style from one element (fromEl) to another (toEl) + * @private + * @param {Element} fromEl Element style is copied from + * @param {Element} toEl Element copied style is applied to + */ + _copyCanvasStyle: function (fromEl, toEl) { + toEl.style.cssText = fromEl.style.cssText; + }, + + /** + * Returns context of canvas where object selection is drawn + * @return {CanvasRenderingContext2D} + */ + getSelectionContext: function() { + return this.contextTop; + }, + + /** + * Returns <canvas> element on which object selection is drawn + * @return {HTMLCanvasElement} + */ + getSelectionElement: function () { + return this.upperCanvasEl; + }, + + /** + * @private + * @param {Object} object + */ + _setActiveObject: function(object) { + if (this._activeObject) { + this._activeObject.set('active', false); + } + this._activeObject = object; + object.set('active', true); + }, + + /** + * Sets given object as the only active object on canvas + * @param {fabric.Object} object Object to set as an active one + * @param {Event} [e] Event (passed along when firing "object:selected") + * @return {fabric.Canvas} thisArg + * @chainable + */ + setActiveObject: function (object, e) { + this._setActiveObject(object); + this.renderAll(); + this.fire('object:selected', { target: object, e: e }); + object.fire('selected', { e: e }); + return this; + }, + + /** + * Returns currently active object + * @return {fabric.Object} active object + */ + getActiveObject: function () { + return this._activeObject; + }, + + /** + * @private + */ + _discardActiveObject: function() { + if (this._activeObject) { + this._activeObject.set('active', false); + } + this._activeObject = null; + }, + + /** + * Discards currently active object + * @return {fabric.Canvas} thisArg + * @chainable + */ + discardActiveObject: function (e) { + this._discardActiveObject(); + this.renderAll(); + this.fire('selection:cleared', { e: e }); + return this; + }, + + /** + * @private + * @param {fabric.Group} group + */ + _setActiveGroup: function(group) { + this._activeGroup = group; + if (group) { + group.set('active', true); + } + }, + + /** + * Sets active group to a speicified one + * @param {fabric.Group} group Group to set as a current one + * @return {fabric.Canvas} thisArg + * @chainable + */ + setActiveGroup: function (group, e) { + this._setActiveGroup(group); + if (group) { + this.fire('object:selected', { target: group, e: e }); + group.fire('selected', { e: e }); + } + return this; + }, + + /** + * Returns currently active group + * @return {fabric.Group} Current group + */ + getActiveGroup: function () { + return this._activeGroup; + }, + + /** + * @private + */ + _discardActiveGroup: function() { + var g = this.getActiveGroup(); + if (g) { + g.destroy(); + } + this.setActiveGroup(null); + }, + + /** + * Discards currently active group + * @return {fabric.Canvas} thisArg + */ + discardActiveGroup: function (e) { + this._discardActiveGroup(); + this.fire('selection:cleared', { e: e }); + return this; + }, + + /** + * Deactivates all objects on canvas, removing any active group or object + * @return {fabric.Canvas} thisArg + */ + deactivateAll: function () { + var allObjects = this.getObjects(), + i = 0, + len = allObjects.length; + for ( ; i < len; i++) { + allObjects[i].set('active', false); + } + this._discardActiveGroup(); + this._discardActiveObject(); + return this; + }, + + /** + * Deactivates all objects and dispatches appropriate events + * @return {fabric.Canvas} thisArg + */ + deactivateAllWithDispatch: function (e) { + var activeObject = this.getActiveGroup() || this.getActiveObject(); + if (activeObject) { + this.fire('before:selection:cleared', { target: activeObject, e: e }); + } + this.deactivateAll(); + if (activeObject) { + this.fire('selection:cleared', { e: e }); + } + return this; + }, + + /** + * Draws objects' controls (borders/controls) + * @param {CanvasRenderingContext2D} ctx Context to render controls on + */ + drawControls: function(ctx) { + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this._drawGroupControls(ctx, activeGroup); + } + else { + this._drawObjectsControls(ctx); + } + }, + + /** + * @private + */ + _drawGroupControls: function(ctx, activeGroup) { + activeGroup._renderControls(ctx); + }, + + /** + * @private + */ + _drawObjectsControls: function(ctx) { + for (var i = 0, len = this._objects.length; i < len; ++i) { + if (!this._objects[i] || !this._objects[i].active) { + continue; + } + this._objects[i]._renderControls(ctx); + this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i]; + } + } + }); + + // copying static properties manually to work around Opera's bug, + // where "prototype" property is enumerable and overrides existing prototype + for (var prop in fabric.StaticCanvas) { + if (prop !== 'prototype') { + fabric.Canvas[prop] = fabric.StaticCanvas[prop]; + } + } + + if (fabric.isTouchSupported) { + /** @ignore */ + fabric.Canvas.prototype._setCursorFromEvent = function() { }; + } + + /** + * @class fabric.Element + * @alias fabric.Canvas + * @deprecated Use {@link fabric.Canvas} instead. + * @constructor + */ + fabric.Element = fabric.Canvas; +})(); + + +(function(){ + + var cursorOffset = { + mt: 0, // n + tr: 1, // ne + mr: 2, // e + br: 3, // se + mb: 4, // s + bl: 5, // sw + ml: 6, // w + tl: 7 // nw + }, + addListener = fabric.util.addListener, + removeListener = fabric.util.removeListener; + + fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ { + + /** + * Map of cursor style values for each of the object controls + * @private + */ + cursorMap: [ + 'n-resize', + 'ne-resize', + 'e-resize', + 'se-resize', + 's-resize', + 'sw-resize', + 'w-resize', + 'nw-resize' + ], + + /** + * Adds mouse listeners to canvas + * @private + */ + _initEventListeners: function () { + + this._bindEvents(); + + addListener(fabric.window, 'resize', this._onResize); + + // mouse events + addListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); + addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + addListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel); + + // touch events + addListener(this.upperCanvasEl, 'touchstart', this._onMouseDown); + addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (typeof Event !== 'undefined' && 'add' in Event) { + Event.add(this.upperCanvasEl, 'gesture', this._onGesture); + Event.add(this.upperCanvasEl, 'drag', this._onDrag); + Event.add(this.upperCanvasEl, 'orientation', this._onOrientationChange); + Event.add(this.upperCanvasEl, 'shake', this._onShake); + } + }, + + /** + * @private + */ + _bindEvents: function() { + this._onMouseDown = this._onMouseDown.bind(this); + this._onMouseMove = this._onMouseMove.bind(this); + this._onMouseUp = this._onMouseUp.bind(this); + this._onResize = this._onResize.bind(this); + this._onGesture = this._onGesture.bind(this); + this._onDrag = this._onDrag.bind(this); + this._onShake = this._onShake.bind(this); + this._onOrientationChange = this._onOrientationChange.bind(this); + this._onMouseWheel = this._onMouseWheel.bind(this); + }, + + /** + * Removes all event listeners + */ + removeListeners: function() { + removeListener(fabric.window, 'resize', this._onResize); + + removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); + removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + removeListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel); + + removeListener(this.upperCanvasEl, 'touchstart', this._onMouseDown); + removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (typeof Event !== 'undefined' && 'remove' in Event) { + Event.remove(this.upperCanvasEl, 'gesture', this._onGesture); + Event.remove(this.upperCanvasEl, 'drag', this._onDrag); + Event.remove(this.upperCanvasEl, 'orientation', this._onOrientationChange); + Event.remove(this.upperCanvasEl, 'shake', this._onShake); + } + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js gesture + * @param {Event} [self] Inner Event object + */ + _onGesture: function(e, self) { + this.__onTransformGesture && this.__onTransformGesture(e, self); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js drag + * @param {Event} [self] Inner Event object + */ + _onDrag: function(e, self) { + this.__onDrag && this.__onDrag(e, self); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js wheel event + * @param {Event} [self] Inner Event object + */ + _onMouseWheel: function(e, self) { + this.__onMouseWheel && this.__onMouseWheel(e, self); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js orientation change + * @param {Event} [self] Inner Event object + */ + _onOrientationChange: function(e,self) { + this.__onOrientationChange && this.__onOrientationChange(e,self); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js shake + * @param {Event} [self] Inner Event object + */ + _onShake: function(e, self) { + this.__onShake && this.__onShake(e,self); + }, + + /** + * @private + * @param {Event} e Event object fired on mousedown + */ + _onMouseDown: function (e) { + this.__onMouseDown(e); + + addListener(fabric.document, 'touchend', this._onMouseUp); + addListener(fabric.document, 'touchmove', this._onMouseMove); + + removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (e.type === 'touchstart') { + // Unbind mousedown to prevent double triggers from touch devices + removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); + } + else { + addListener(fabric.document, 'mouseup', this._onMouseUp); + addListener(fabric.document, 'mousemove', this._onMouseMove); + } + }, + + /** + * @private + * @param {Event} e Event object fired on mouseup + */ + _onMouseUp: function (e) { + this.__onMouseUp(e); + + removeListener(fabric.document, 'mouseup', this._onMouseUp); + removeListener(fabric.document, 'touchend', this._onMouseUp); + + removeListener(fabric.document, 'mousemove', this._onMouseMove); + removeListener(fabric.document, 'touchmove', this._onMouseMove); + + addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (e.type === 'touchend') { + // Wait 400ms before rebinding mousedown to prevent double triggers + // from touch devices + var _this = this; + setTimeout(function() { + addListener(_this.upperCanvasEl, 'mousedown', _this._onMouseDown); + }, 400); + } + }, + + /** + * @private + * @param {Event} e Event object fired on mousemove + */ + _onMouseMove: function (e) { + !this.allowTouchScrolling && e.preventDefault && e.preventDefault(); + this.__onMouseMove(e); + }, + + /** + * @private + */ + _onResize: function () { + this.calcOffset(); + }, + + /** + * Decides whether the canvas should be redrawn in mouseup and mousedown events. + * @private + * @param {Object} target + * @param {Object} pointer + */ + _shouldRender: function(target, pointer) { + var activeObject = this.getActiveGroup() || this.getActiveObject(); + + return !!( + (target && ( + target.isMoving || + target !== activeObject)) + || + (!target && !!activeObject) + || + (!target && !activeObject && !this._groupSelector) + || + (pointer && + this._previousPointer && + this.selection && ( + pointer.x !== this._previousPointer.x || + pointer.y !== this._previousPointer.y)) + ); + }, + + /** + * Method that defines the actions when mouse is released on canvas. + * The method resets the currentTransform parameters, store the image corner + * position in the image object and render the canvas on top. + * @private + * @param {Event} e Event object fired on mouseup + */ + __onMouseUp: function (e) { + var target; + + if (this.isDrawingMode && this._isCurrentlyDrawing) { + this._onMouseUpInDrawingMode(e); + return; + } + + if (this._currentTransform) { + this._finalizeCurrentTransform(); + target = this._currentTransform.target; + } + else { + target = this.findTarget(e, true); + } + + var shouldRender = this._shouldRender(target, this.getPointer(e)); + + this._maybeGroupObjects(e); + + if (target) { + target.isMoving = false; + } + + shouldRender && this.renderAll(); + + this._handleCursorAndEvent(e, target); + }, + + _handleCursorAndEvent: function(e, target) { + this._setCursorFromEvent(e, target); + + // TODO: why are we doing this? + var _this = this; + setTimeout(function () { + _this._setCursorFromEvent(e, target); + }, 50); + + this.fire('mouse:up', { target: target, e: e }); + target && target.fire('mouseup', { e: e }); + }, + + /** + * @private + */ + _finalizeCurrentTransform: function() { + + var transform = this._currentTransform, + target = transform.target; + + if (target._scaling) { + target._scaling = false; + } + + target.setCoords(); + + // only fire :modified event if target coordinates were changed during mousedown-mouseup + if (this.stateful && target.hasStateChanged()) { + this.fire('object:modified', { target: target }); + target.fire('modified'); + } + + this._restoreOriginXY(target); + }, + + /** + * @private + * @param {Object} target Object to restore + */ + _restoreOriginXY: function(target) { + if (this._previousOriginX && this._previousOriginY) { + + var originPoint = target.translateToOriginPoint( + target.getCenterPoint(), + this._previousOriginX, + this._previousOriginY); + + target.originX = this._previousOriginX; + target.originY = this._previousOriginY; + + target.left = originPoint.x; + target.top = originPoint.y; + + this._previousOriginX = null; + this._previousOriginY = null; + } + }, + + /** + * @private + * @param {Event} e Event object fired on mousedown + */ + _onMouseDownInDrawingMode: function(e) { + this._isCurrentlyDrawing = true; + this.discardActiveObject(e).renderAll(); + if (this.clipTo) { + fabric.util.clipContext(this, this.contextTop); + } + var ivt = fabric.util.invertTransform(this.viewportTransform), + pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt); + this.freeDrawingBrush.onMouseDown(pointer); + this.fire('mouse:down', { e: e }); + }, + + /** + * @private + * @param {Event} e Event object fired on mousemove + */ + _onMouseMoveInDrawingMode: function(e) { + if (this._isCurrentlyDrawing) { + var ivt = fabric.util.invertTransform(this.viewportTransform), + pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt); + this.freeDrawingBrush.onMouseMove(pointer); + } + this.setCursor(this.freeDrawingCursor); + this.fire('mouse:move', { e: e }); + }, + + /** + * @private + * @param {Event} e Event object fired on mouseup + */ + _onMouseUpInDrawingMode: function(e) { + this._isCurrentlyDrawing = false; + if (this.clipTo) { + this.contextTop.restore(); + } + this.freeDrawingBrush.onMouseUp(); + this.fire('mouse:up', { e: e }); + }, + + /** + * Method that defines the actions when mouse is clic ked on canvas. + * The method inits the currentTransform parameters and renders all the + * canvas so the current image can be placed on the top canvas and the rest + * in on the container one. + * @private + * @param {Event} e Event object fired on mousedown + */ + __onMouseDown: function (e) { + + // accept only left clicks + var isLeftClick = 'which' in e ? e.which === 1 : e.button === 1; + if (!isLeftClick && !fabric.isTouchSupported) { + return; + } + + if (this.isDrawingMode) { + this._onMouseDownInDrawingMode(e); + return; + } + + // ignore if some object is being transformed at this moment + if (this._currentTransform) { + return; + } + + var target = this.findTarget(e), + pointer = this.getPointer(e, true); + + // save pointer for check in __onMouseUp event + this._previousPointer = pointer; + + var shouldRender = this._shouldRender(target, pointer), + shouldGroup = this._shouldGroup(e, target); + + if (this._shouldClearSelection(e, target)) { + this._clearSelection(e, target, pointer); + } + else if (shouldGroup) { + this._handleGrouping(e, target); + target = this.getActiveGroup(); + } + + if (target && target.selectable && !shouldGroup) { + this._beforeTransform(e, target); + this._setupCurrentTransform(e, target); + } + // we must renderAll so that active image is placed on the top canvas + shouldRender && this.renderAll(); + + this.fire('mouse:down', { target: target, e: e }); + target && target.fire('mousedown', { e: e }); + }, + + /** + * @private + */ + _beforeTransform: function(e, target) { + var corner; + + this.stateful && target.saveState(); + + // determine if it's a drag or rotate case + if ((corner = target._findTargetCorner(this.getPointer(e)))) { + this.onBeforeScaleRotate(target); + } + + if (target !== this.getActiveGroup() && target !== this.getActiveObject()) { + this.deactivateAll(); + this.setActiveObject(target, e); + } + }, + + /** + * @private + */ + _clearSelection: function(e, target, pointer) { + this.deactivateAllWithDispatch(e); + + if (target && target.selectable) { + this.setActiveObject(target, e); + } + else if (this.selection) { + this._groupSelector = { + ex: pointer.x, + ey: pointer.y, + top: 0, + left: 0 + }; + } + }, + + /** + * @private + * @param {Object} target Object for that origin is set to center + */ + _setOriginToCenter: function(target) { + this._previousOriginX = this._currentTransform.target.originX; + this._previousOriginY = this._currentTransform.target.originY; + + var center = target.getCenterPoint(); + + target.originX = 'center'; + target.originY = 'center'; + + target.left = center.x; + target.top = center.y; + + this._currentTransform.left = target.left; + this._currentTransform.top = target.top; + }, + + /** + * @private + * @param {Object} target Object for that center is set to origin + */ + _setCenterToOrigin: function(target) { + var originPoint = target.translateToOriginPoint( + target.getCenterPoint(), + this._previousOriginX, + this._previousOriginY); + + target.originX = this._previousOriginX; + target.originY = this._previousOriginY; + + target.left = originPoint.x; + target.top = originPoint.y; + + this._previousOriginX = null; + this._previousOriginY = null; + }, + + /** + * Method that defines the actions when mouse is hovering the canvas. + * The currentTransform parameter will definde whether the user is rotating/scaling/translating + * an image or neither of them (only hovering). A group selection is also possible and would cancel + * all any other type of action. + * In case of an image transformation only the top canvas will be rendered. + * @private + * @param {Event} e Event object fired on mousemove + */ + __onMouseMove: function (e) { + + var target, pointer; + + if (this.isDrawingMode) { + this._onMouseMoveInDrawingMode(e); + return; + } + + var groupSelector = this._groupSelector; + + // We initially clicked in an empty area, so we draw a box for multiple selection + if (groupSelector) { + pointer = this.getPointer(e, true); + + groupSelector.left = pointer.x - groupSelector.ex; + groupSelector.top = pointer.y - groupSelector.ey; + + this.renderTop(); + } + else if (!this._currentTransform) { + + target = this.findTarget(e); + + if (!target || target && !target.selectable) { + this.setCursor(this.defaultCursor); + } + else { + this._setCursorFromEvent(e, target); + } + } + else { + this._transformObject(e); + } + + this.fire('mouse:move', { target: target, e: e }); + target && target.fire('mousemove', { e: e }); + }, + + /** + * @private + * @param {Event} e Event fired on mousemove + */ + _transformObject: function(e) { + var pointer = this.getPointer(e), + transform = this._currentTransform; + + transform.reset = false, + transform.target.isMoving = true; + + this._beforeScaleTransform(e, transform); + this._performTransformAction(e, transform, pointer); + + this.renderAll(); + }, + + /** + * @private + */ + _performTransformAction: function(e, transform, pointer) { + var x = pointer.x, + y = pointer.y, + target = transform.target, + action = transform.action; + + if (action === 'rotate') { + this._rotateObject(x, y); + this._fire('rotating', target, e); + } + else if (action === 'scale') { + this._onScale(e, transform, x, y); + this._fire('scaling', target, e); + } + else if (action === 'scaleX') { + this._scaleObject(x, y, 'x'); + this._fire('scaling', target, e); + } + else if (action === 'scaleY') { + this._scaleObject(x, y, 'y'); + this._fire('scaling', target, e); + } + else { + this._translateObject(x, y); + this._fire('moving', target, e); + this.setCursor(this.moveCursor); + } + }, + + /** + * @private + */ + _fire: function(eventName, target, e) { + this.fire('object:' + eventName, { target: target, e: e }); + target.fire(eventName, { e: e }); + }, + + /** + * @private + */ + _beforeScaleTransform: function(e, transform) { + if (transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') { + var centerTransform = this._shouldCenterTransform(e, transform.target); + + // Switch from a normal resize to center-based + if ((centerTransform && (transform.originX !== 'center' || transform.originY !== 'center')) || + // Switch from center-based resize to normal one + (!centerTransform && transform.originX === 'center' && transform.originY === 'center') + ) { + this._resetCurrentTransform(e); + transform.reset = true; + } + } + }, + + /** + * @private + */ + _onScale: function(e, transform, x, y) { + // rotate object only if shift key is not pressed + // and if it is not a group we are transforming + if ((e.shiftKey || this.uniScaleTransform) && !transform.target.get('lockUniScaling')) { + transform.currentAction = 'scale'; + this._scaleObject(x, y); + } + else { + // Switch from a normal resize to proportional + if (!transform.reset && transform.currentAction === 'scale') { + this._resetCurrentTransform(e, transform.target); + } + + transform.currentAction = 'scaleEqually'; + this._scaleObject(x, y, 'equally'); + } + }, + + /** + * Sets the cursor depending on where the canvas is being hovered. + * Note: very buggy in Opera + * @param {Event} e Event object + * @param {Object} target Object that the mouse is hovering, if so. + */ + _setCursorFromEvent: function (e, target) { + if (!target || !target.selectable) { + this.setCursor(this.defaultCursor); + return false; + } + else { + var activeGroup = this.getActiveGroup(), + // only show proper corner when group selection is not active + corner = target._findTargetCorner + && (!activeGroup || !activeGroup.contains(target)) + && target._findTargetCorner(this.getPointer(e, true)); + + if (!corner) { + this.setCursor(target.hoverCursor || this.hoverCursor); + } + else { + this._setCornerCursor(corner, target); + } + } + return true; + }, + + /** + * @private + */ + _setCornerCursor: function(corner, target) { + if (corner in cursorOffset) { + this.setCursor(this._getRotatedCornerCursor(corner, target)); + } + else if (corner === 'mtr' && target.hasRotatingPoint) { + this.setCursor(this.rotationCursor); + } + else { + this.setCursor(this.defaultCursor); + return false; + } + }, + + /** + * @private + */ + _getRotatedCornerCursor: function(corner, target) { + var n = Math.round((target.getAngle() % 360) / 45); + + if (n < 0) { + n += 8; // full circle ahead + } + n += cursorOffset[corner]; + // normalize n to be from 0 to 7 + n %= 8; + + return this.cursorMap[n]; + } + }); +})(); + + +(function(){ + + var min = Math.min, + max = Math.max; + + fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ { + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + * @return {Boolean} + */ + _shouldGroup: function(e, target) { + var activeObject = this.getActiveObject(); + return e.shiftKey && + (this.getActiveGroup() || (activeObject && activeObject !== target)) + && this.selection; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _handleGrouping: function (e, target) { + + if (target === this.getActiveGroup()) { + + // if it's a group, find target again, this time skipping group + target = this.findTarget(e, true); + + // if even object is not found, bail out + if (!target || target.isType('group')) { + return; + } + } + if (this.getActiveGroup()) { + this._updateActiveGroup(target, e); + } + else { + this._createActiveGroup(target, e); + } + + if (this._activeGroup) { + this._activeGroup.saveCoords(); + } + }, + + /** + * @private + */ + _updateActiveGroup: function(target, e) { + var activeGroup = this.getActiveGroup(); + + if (activeGroup.contains(target)) { + + activeGroup.removeWithUpdate(target); + this._resetObjectTransform(activeGroup); + target.set('active', false); + + if (activeGroup.size() === 1) { + // remove group alltogether if after removal it only contains 1 object + this.discardActiveGroup(e); + // activate last remaining object + this.setActiveObject(activeGroup.item(0)); + return; + } + } + else { + activeGroup.addWithUpdate(target); + this._resetObjectTransform(activeGroup); + } + this.fire('selection:created', { target: activeGroup, e: e }); + activeGroup.set('active', true); + }, + + /** + * @private + */ + _createActiveGroup: function(target, e) { + + if (this._activeObject && target !== this._activeObject) { + + var group = this._createGroup(target); + group.addWithUpdate(); + + this.setActiveGroup(group); + this._activeObject = null; + + this.fire('selection:created', { target: group, e: e }); + } + + target.set('active', true); + }, + + /** + * @private + * @param {Object} target + */ + _createGroup: function(target) { + + var objects = this.getObjects(), + isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target), + groupObjects = isActiveLower + ? [ this._activeObject, target ] + : [ target, this._activeObject ]; + + return new fabric.Group(groupObjects, { + originX: 'center', + originY: 'center', + canvas: this + }); + }, + + /** + * @private + * @param {Event} e mouse event + */ + _groupSelectedObjects: function (e) { + + var group = this._collectObjects(); + + // do not create group for 1 element only + if (group.length === 1) { + this.setActiveObject(group[0], e); + } + else if (group.length > 1) { + group = new fabric.Group(group.reverse(), { + originX: 'center', + originY: 'center', + canvas: this + }); + group.addWithUpdate(); + this.setActiveGroup(group, e); + group.saveCoords(); + this.fire('selection:created', { target: group }); + this.renderAll(); + } + }, + + /** + * @private + */ + _collectObjects: function() { + var group = [ ], + currentObject, + x1 = this._groupSelector.ex, + y1 = this._groupSelector.ey, + x2 = x1 + this._groupSelector.left, + y2 = y1 + this._groupSelector.top, + selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)), + selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)), + isClick = x1 === x2 && y1 === y2; + + for (var i = this._objects.length; i--; ) { + currentObject = this._objects[i]; + + if (!currentObject || !currentObject.selectable || !currentObject.visible) { + continue; + } + + if (currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) || + currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) || + currentObject.containsPoint(selectionX1Y1) || + currentObject.containsPoint(selectionX2Y2) + ) { + currentObject.set('active', true); + group.push(currentObject); + + // only add one object if it's a click + if (isClick) { + break; + } + } + } + + return group; + }, + + /** + * @private + */ + _maybeGroupObjects: function(e) { + if (this.selection && this._groupSelector) { + this._groupSelectedObjects(e); + } + + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + activeGroup.setObjectsCoords().setCoords(); + activeGroup.isMoving = false; + this.setCursor(this.defaultCursor); + } + + // clear selection and current transformation + this._groupSelector = null; + this._currentTransform = null; + } + }); + +})(); + + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately + * @param {Object} [options] Options object + * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png" + * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg. + * @param {Number} [options.multiplier=1] Multiplier to scale by + * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14 + * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14 + * @param {Number} [options.width] Cropping width. Introduced in v1.2.14 + * @param {Number} [options.height] Cropping height. Introduced in v1.2.14 + * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format + * @see {@link http://jsfiddle.net/fabricjs/NfZVb/|jsFiddle demo} + * @example Generate jpeg dataURL with lower quality + * var dataURL = canvas.toDataURL({ + * format: 'jpeg', + * quality: 0.8 + * }); + * @example Generate cropped png dataURL (clipping of canvas) + * var dataURL = canvas.toDataURL({ + * format: 'png', + * left: 100, + * top: 100, + * width: 200, + * height: 200 + * }); + * @example Generate double scaled png dataURL + * var dataURL = canvas.toDataURL({ + * format: 'png', + * multiplier: 2 + * }); + */ + toDataURL: function (options) { + options || (options = { }); + + var format = options.format || 'png', + quality = options.quality || 1, + multiplier = options.multiplier || 1, + cropping = { + left: options.left, + top: options.top, + width: options.width, + height: options.height + }; + + if (multiplier !== 1) { + return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier); + } + else { + return this.__toDataURL(format, quality, cropping); + } + }, + + /** + * @private + */ + __toDataURL: function(format, quality, cropping) { + + this.renderAll(true); + + var canvasEl = this.upperCanvasEl || this.lowerCanvasEl, + croppedCanvasEl = this.__getCroppedCanvas(canvasEl, cropping); + + // to avoid common confusion https://github.com/kangax/fabric.js/issues/806 + if (format === 'jpg') { + format = 'jpeg'; + } + + var data = (fabric.StaticCanvas.supports('toDataURLWithQuality')) + ? (croppedCanvasEl || canvasEl).toDataURL('image/' + format, quality) + : (croppedCanvasEl || canvasEl).toDataURL('image/' + format); + + this.contextTop && this.clearContext(this.contextTop); + this.renderAll(); + + if (croppedCanvasEl) { + croppedCanvasEl = null; + } + + return data; + }, + + /** + * @private + */ + __getCroppedCanvas: function(canvasEl, cropping) { + + var croppedCanvasEl, + croppedCtx, + shouldCrop = 'left' in cropping || + 'top' in cropping || + 'width' in cropping || + 'height' in cropping; + + if (shouldCrop) { + + croppedCanvasEl = fabric.util.createCanvasElement(); + croppedCtx = croppedCanvasEl.getContext('2d'); + + croppedCanvasEl.width = cropping.width || this.width; + croppedCanvasEl.height = cropping.height || this.height; + + croppedCtx.drawImage(canvasEl, -cropping.left || 0, -cropping.top || 0); + } + + return croppedCanvasEl; + }, + + /** + * @private + */ + __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) { + + var origWidth = this.getWidth(), + origHeight = this.getHeight(), + scaledWidth = origWidth * multiplier, + scaledHeight = origHeight * multiplier, + activeObject = this.getActiveObject(), + activeGroup = this.getActiveGroup(), + + ctx = this.contextTop || this.contextContainer; + + if (multiplier > 1) { + this.setWidth(scaledWidth).setHeight(scaledHeight); + } + ctx.scale(multiplier, multiplier); + + if (cropping.left) { + cropping.left *= multiplier; + } + if (cropping.top) { + cropping.top *= multiplier; + } + if (cropping.width) { + cropping.width *= multiplier; + } + else if (multiplier < 1) { + cropping.width = scaledWidth; + } + if (cropping.height) { + cropping.height *= multiplier; + } + else if (multiplier < 1) { + cropping.height = scaledHeight; + } + + if (activeGroup) { + // not removing group due to complications with restoring it with correct state afterwords + this._tempRemoveBordersControlsFromGroup(activeGroup); + } + else if (activeObject && this.deactivateAll) { + this.deactivateAll(); + } + + this.renderAll(true); + + var data = this.__toDataURL(format, quality, cropping); + + // restoring width, height for `renderAll` to draw + // background properly (while context is scaled) + this.width = origWidth; + this.height = origHeight; + + ctx.scale(1 / multiplier, 1 / multiplier); + this.setWidth(origWidth).setHeight(origHeight); + + if (activeGroup) { + this._restoreBordersControlsOnGroup(activeGroup); + } + else if (activeObject && this.setActiveObject) { + this.setActiveObject(activeObject); + } + + this.contextTop && this.clearContext(this.contextTop); + this.renderAll(); + + return data; + }, + + /** + * Exports canvas element to a dataurl image (allowing to change image size via multiplier). + * @deprecated since 1.0.13 + * @param {String} format (png|jpeg) + * @param {Number} multiplier + * @param {Number} quality (0..1) + * @return {String} + */ + toDataURLWithMultiplier: function (format, multiplier, quality) { + return this.toDataURL({ + format: format, + multiplier: multiplier, + quality: quality + }); + }, + + /** + * @private + */ + _tempRemoveBordersControlsFromGroup: function(group) { + group.origHasControls = group.hasControls; + group.origBorderColor = group.borderColor; + + group.hasControls = true; + group.borderColor = 'rgba(0,0,0,0)'; + + group.forEachObject(function(o) { + o.origBorderColor = o.borderColor; + o.borderColor = 'rgba(0,0,0,0)'; + }); + }, + + /** + * @private + */ + _restoreBordersControlsOnGroup: function(group) { + group.hideControls = group.origHideControls; + group.borderColor = group.origBorderColor; + + group.forEachObject(function(o) { + o.borderColor = o.origBorderColor; + delete o.origBorderColor; + }); + } +}); + + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Populates canvas with data from the specified dataless JSON. + * JSON format must conform to the one of {@link fabric.Canvas#toDatalessJSON} + * @deprecated since 1.2.2 + * @param {String|Object} json JSON string or object + * @param {Function} callback Callback, invoked when json is parsed + * and corresponding objects (e.g: {@link fabric.Image}) + * are initialized + * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created. + * @return {fabric.Canvas} instance + * @chainable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization} + */ + loadFromDatalessJSON: function (json, callback, reviver) { + return this.loadFromJSON(json, callback, reviver); + }, + + /** + * Populates canvas with data from the specified JSON. + * JSON format must conform to the one of {@link fabric.Canvas#toJSON} + * @param {String|Object} json JSON string or object + * @param {Function} callback Callback, invoked when json is parsed + * and corresponding objects (e.g: {@link fabric.Image}) + * are initialized + * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created. + * @return {fabric.Canvas} instance + * @chainable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization} + * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo} + * @example loadFromJSON + * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas)); + * @example loadFromJSON with reviver + * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) { + * // `o` = json object + * // `object` = fabric.Object instance + * // ... do some stuff ... + * }); + */ + loadFromJSON: function (json, callback, reviver) { + if (!json) { + return; + } + + // serialize if it wasn't already + var serialized = (typeof json === 'string') + ? JSON.parse(json) + : json; + + this.clear(); + + var _this = this; + this._enlivenObjects(serialized.objects, function () { + _this._setBgOverlay(serialized, callback); + }, reviver); + + return this; + }, + + /** + * @private + * @param {Object} serialized Object with background and overlay information + * @param {Function} callback Invoked after all background and overlay images/patterns loaded + */ + _setBgOverlay: function(serialized, callback) { + var _this = this, + loaded = { + backgroundColor: false, + overlayColor: false, + backgroundImage: false, + overlayImage: false + }; + + if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) { + callback && callback(); + return; + } + + var cbIfLoaded = function () { + if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) { + _this.renderAll(); + callback && callback(); + } + }; + + this.__setBgOverlay('backgroundImage', serialized.backgroundImage, loaded, cbIfLoaded); + this.__setBgOverlay('overlayImage', serialized.overlayImage, loaded, cbIfLoaded); + this.__setBgOverlay('backgroundColor', serialized.background, loaded, cbIfLoaded); + this.__setBgOverlay('overlayColor', serialized.overlay, loaded, cbIfLoaded); + + cbIfLoaded(); + }, + + /** + * @private + * @param {String} property Property to set (backgroundImage, overlayImage, backgroundColor, overlayColor) + * @param {(Object|String)} value Value to set + * @param {Object} loaded Set loaded property to true if property is set + * @param {Object} callback Callback function to invoke after property is set + */ + __setBgOverlay: function(property, value, loaded, callback) { + var _this = this; + + if (!value) { + loaded[property] = true; + return; + } + + if (property === 'backgroundImage' || property === 'overlayImage') { + fabric.Image.fromObject(value, function(img) { + _this[property] = img; + loaded[property] = true; + callback && callback(); + }); + } + else { + this['set' + fabric.util.string.capitalize(property, true)](value, function() { + loaded[property] = true; + callback && callback(); + }); + } + }, + + /** + * @private + * @param {Array} objects + * @param {Function} callback + * @param {Function} [reviver] + */ + _enlivenObjects: function (objects, callback, reviver) { + var _this = this; + + if (!objects || objects.length === 0) { + callback && callback(); + return; + } + + var renderOnAddRemove = this.renderOnAddRemove; + this.renderOnAddRemove = false; + + fabric.util.enlivenObjects(objects, function(enlivenedObjects) { + enlivenedObjects.forEach(function(obj, index) { + _this.insertAt(obj, index, true); + }); + + _this.renderOnAddRemove = renderOnAddRemove; + callback && callback(); + }, null, reviver); + }, + + /** + * @private + * @param {String} format + * @param {Function} callback + */ + _toDataURL: function (format, callback) { + this.clone(function (clone) { + callback(clone.toDataURL(format)); + }); + }, + + /** + * @private + * @param {String} format + * @param {Number} multiplier + * @param {Function} callback + */ + _toDataURLWithMultiplier: function (format, multiplier, callback) { + this.clone(function (clone) { + callback(clone.toDataURLWithMultiplier(format, multiplier)); + }); + }, + + /** + * Clones canvas instance + * @param {Object} [callback] Receives cloned instance as a first argument + * @param {Array} [properties] Array of properties to include in the cloned canvas and children + */ + clone: function (callback, properties) { + var data = JSON.stringify(this.toJSON(properties)); + this.cloneWithoutData(function(clone) { + clone.loadFromJSON(data, function() { + callback && callback(clone); + }); + }); + }, + + /** + * Clones canvas instance without cloning existing data. + * This essentially copies canvas dimensions, clipping properties, etc. + * but leaves data empty (so that you can populate it with your own) + * @param {Object} [callback] Receives cloned instance as a first argument + */ + cloneWithoutData: function(callback) { + var el = fabric.document.createElement('canvas'); + + el.width = this.getWidth(); + el.height = this.getHeight(); + + var clone = new fabric.Canvas(el); + clone.clipTo = this.clipTo; + if (this.backgroundImage) { + clone.setBackgroundImage(this.backgroundImage.src, function() { + clone.renderAll(); + callback && callback(clone); + }); + clone.backgroundImageOpacity = this.backgroundImageOpacity; + clone.backgroundImageStretch = this.backgroundImageStretch; + } + else { + callback && callback(clone); + } + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + toFixed = fabric.util.toFixed, + capitalize = fabric.util.string.capitalize, + degreesToRadians = fabric.util.degreesToRadians, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Object) { + return; + } + + /** + * Root object class from which all 2d shape classes inherit from + * @class fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#objects} + * @see {@link fabric.Object#initialize} for constructor definition + * + * @fires added + * @fires removed + * + * @fires selected + * @fires modified + * @fires rotating + * @fires scaling + * @fires moving + * + * @fires mousedown + * @fires mouseup + */ + fabric.Object = fabric.util.createClass(/** @lends fabric.Object.prototype */ { + + /** + * Retrieves object's {@link fabric.Object#clipTo|clipping function} + * @method getClipTo + * @memberOf fabric.Object.prototype + * @return {Function} + */ + + /** + * Sets object's {@link fabric.Object#clipTo|clipping function} + * @method setClipTo + * @memberOf fabric.Object.prototype + * @param {Function} clipTo Clipping function + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#transformMatrix|transformMatrix} + * @method getTransformMatrix + * @memberOf fabric.Object.prototype + * @return {Array} transformMatrix + */ + + /** + * Sets object's {@link fabric.Object#transformMatrix|transformMatrix} + * @method setTransformMatrix + * @memberOf fabric.Object.prototype + * @param {Array} transformMatrix + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#visible|visible} state + * @method getVisible + * @memberOf fabric.Object.prototype + * @return {Boolean} True if visible + */ + + /** + * Sets object's {@link fabric.Object#visible|visible} state + * @method setVisible + * @memberOf fabric.Object.prototype + * @param {Boolean} value visible value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#shadow|shadow} + * @method getShadow + * @memberOf fabric.Object.prototype + * @return {Object} Shadow instance + */ + + /** + * Retrieves object's {@link fabric.Object#stroke|stroke} + * @method getStroke + * @memberOf fabric.Object.prototype + * @return {String} stroke value + */ + + /** + * Sets object's {@link fabric.Object#stroke|stroke} + * @method setStroke + * @memberOf fabric.Object.prototype + * @param {String} value stroke value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#strokeWidth|strokeWidth} + * @method getStrokeWidth + * @memberOf fabric.Object.prototype + * @return {Number} strokeWidth value + */ + + /** + * Sets object's {@link fabric.Object#strokeWidth|strokeWidth} + * @method setStrokeWidth + * @memberOf fabric.Object.prototype + * @param {Number} value strokeWidth value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#originX|originX} + * @method getOriginX + * @memberOf fabric.Object.prototype + * @return {String} originX value + */ + + /** + * Sets object's {@link fabric.Object#originX|originX} + * @method setOriginX + * @memberOf fabric.Object.prototype + * @param {String} value originX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#originY|originY} + * @method getOriginY + * @memberOf fabric.Object.prototype + * @return {String} originY value + */ + + /** + * Sets object's {@link fabric.Object#originY|originY} + * @method setOriginY + * @memberOf fabric.Object.prototype + * @param {String} value originY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#fill|fill} + * @method getFill + * @memberOf fabric.Object.prototype + * @return {String} Fill value + */ + + /** + * Sets object's {@link fabric.Object#fill|fill} + * @method setFill + * @memberOf fabric.Object.prototype + * @param {String} value Fill value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#opacity|opacity} + * @method getOpacity + * @memberOf fabric.Object.prototype + * @return {Number} Opacity value (0-1) + */ + + /** + * Sets object's {@link fabric.Object#opacity|opacity} + * @method setOpacity + * @memberOf fabric.Object.prototype + * @param {Number} value Opacity value (0-1) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#angle|angle} (in degrees) + * @method getAngle + * @memberOf fabric.Object.prototype + * @return {Number} + */ + + /** + * Sets object's {@link fabric.Object#angle|angle} + * @method setAngle + * @memberOf fabric.Object.prototype + * @param {Number} value Angle value (in degrees) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#top|top position} + * @method getTop + * @memberOf fabric.Object.prototype + * @return {Number} Top value (in pixels) + */ + + /** + * Sets object's {@link fabric.Object#top|top position} + * @method setTop + * @memberOf fabric.Object.prototype + * @param {Number} value Top value (in pixels) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#left|left position} + * @method getLeft + * @memberOf fabric.Object.prototype + * @return {Number} Left value (in pixels) + */ + + /** + * Sets object's {@link fabric.Object#left|left position} + * @method setLeft + * @memberOf fabric.Object.prototype + * @param {Number} value Left value (in pixels) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#scaleX|scaleX} value + * @method getScaleX + * @memberOf fabric.Object.prototype + * @return {Number} scaleX value + */ + + /** + * Sets object's {@link fabric.Object#scaleX|scaleX} value + * @method setScaleX + * @memberOf fabric.Object.prototype + * @param {Number} value scaleX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#scaleY|scaleY} value + * @method getScaleY + * @memberOf fabric.Object.prototype + * @return {Number} scaleY value + */ + + /** + * Sets object's {@link fabric.Object#scaleY|scaleY} value + * @method setScaleY + * @memberOf fabric.Object.prototype + * @param {Number} value scaleY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#flipX|flipX} value + * @method getFlipX + * @memberOf fabric.Object.prototype + * @return {Boolean} flipX value + */ + + /** + * Sets object's {@link fabric.Object#flipX|flipX} value + * @method setFlipX + * @memberOf fabric.Object.prototype + * @param {Boolean} value flipX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#flipY|flipY} value + * @method getFlipY + * @memberOf fabric.Object.prototype + * @return {Boolean} flipY value + */ + + /** + * Sets object's {@link fabric.Object#flipY|flipY} value + * @method setFlipY + * @memberOf fabric.Object.prototype + * @param {Boolean} value flipY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Type of an object (rect, circle, path, etc.) + * @type String + * @default + */ + type: 'object', + + /** + * Horizontal origin of transformation of an object (one of "left", "right", "center") + * @type String + * @default + */ + originX: 'left', + + /** + * Vertical origin of transformation of an object (one of "top", "bottom", "center") + * @type String + * @default + */ + originY: 'top', + + /** + * Top position of an object. Note that by default it's relative to object center. You can change this by setting originY={top/center/bottom} + * @type Number + * @default + */ + top: 0, + + /** + * Left position of an object. Note that by default it's relative to object center. You can change this by setting originX={left/center/right} + * @type Number + * @default + */ + left: 0, + + /** + * Object width + * @type Number + * @default + */ + width: 0, + + /** + * Object height + * @type Number + * @default + */ + height: 0, + + /** + * Object scale factor (horizontal) + * @type Number + * @default + */ + scaleX: 1, + + /** + * Object scale factor (vertical) + * @type Number + * @default + */ + scaleY: 1, + + /** + * When true, an object is rendered as flipped horizontally + * @type Boolean + * @default + */ + flipX: false, + + /** + * When true, an object is rendered as flipped vertically + * @type Boolean + * @default + */ + flipY: false, + + /** + * Opacity of an object + * @type Number + * @default + */ + opacity: 1, + + /** + * Angle of rotation of an object (in degrees) + * @type Number + * @default + */ + angle: 0, + + /** + * Size of object's controlling corners (in pixels) + * @type Number + * @default + */ + cornerSize: 12, + + /** + * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill) + * @type Boolean + * @default + */ + transparentCorners: true, + + /** + * Default cursor value used when hovering over this object on canvas + * @type String + * @default + */ + hoverCursor: null, + + /** + * Padding between object and its controlling borders (in pixels) + * @type Number + * @default + */ + padding: 0, + + /** + * Color of controlling borders of an object (when it's active) + * @type String + * @default + */ + borderColor: 'rgba(102,153,255,0.75)', + + /** + * Color of controlling corners of an object (when it's active) + * @type String + * @default + */ + cornerColor: 'rgba(102,153,255,0.5)', + + /** + * When true, this object will use center point as the origin of transformation + * when being scaled via the controls. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredScaling: false, + + /** + * When true, this object will use center point as the origin of transformation + * when being rotated via the controls. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredRotation: true, + + /** + * Color of object's fill + * @type String + * @default + */ + fill: 'rgb(0,0,0)', + + /** + * Fill rule used to fill an object + * @type String + * @default + */ + fillRule: 'source-over', + + /** + * Background color of an object. Only works with text objects at the moment. + * @type String + * @default + */ + backgroundColor: '', + + /** + * When defined, an object is rendered via stroke and this property specifies its color + * @type String + * @default + */ + stroke: null, + + /** + * Width of a stroke used to render this object + * @type Number + * @default + */ + strokeWidth: 1, + + /** + * Array specifying dash pattern of an object's stroke (stroke must be defined) + * @type Array + */ + strokeDashArray: null, + + /** + * Line endings style of an object's stroke (one of "butt", "round", "square") + * @type String + * @default + */ + strokeLineCap: 'butt', + + /** + * Corner style of an object's stroke (one of "bevil", "round", "miter") + * @type String + * @default + */ + strokeLineJoin: 'miter', + + /** + * Maximum miter length (used for strokeLineJoin = "miter") of an object's stroke + * @type Number + * @default + */ + strokeMiterLimit: 10, + + /** + * Shadow object representing shadow of this shape + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Opacity of object's controlling borders when object is active and moving + * @type Number + * @default + */ + borderOpacityWhenMoving: 0.4, + + /** + * Scale factor of object's controlling borders + * @type Number + * @default + */ + borderScaleFactor: 1, + + /** + * Transform matrix (similar to SVG's transform matrix) + * @type Array + */ + transformMatrix: null, + + /** + * Minimum allowed scale value of an object + * @type Number + * @default + */ + minScaleLimit: 0.01, + + /** + * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection). + * But events still fire on it. + * @type Boolean + * @default + */ + selectable: true, + + /** + * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4 + * @type Boolean + * @default + */ + evented: true, + + /** + * When set to `false`, an object is not rendered on canvas + * @type Boolean + * @default + */ + visible: true, + + /** + * When set to `false`, object's controls are not displayed and can not be used to manipulate object + * @type Boolean + * @default + */ + hasControls: true, + + /** + * When set to `false`, object's controlling borders are not rendered + * @type Boolean + * @default + */ + hasBorders: true, + + /** + * When set to `false`, object's controlling rotating point will not be visible or selectable + * @type Boolean + * @default + */ + hasRotatingPoint: true, + + /** + * Offset for object's controlling rotating point (when enabled via `hasRotatingPoint`) + * @type Number + * @default + */ + rotatingPointOffset: 40, + + /** + * When set to `true`, objects are "found" on canvas on per-pixel basis rather than according to bounding box + * @type Boolean + * @default + */ + perPixelTargetFind: false, + + /** + * When `false`, default object's values are not included in its serialization + * @type Boolean + * @default + */ + includeDefaultValues: true, + + /** + * Function that determines clipping of an object (context is passed as a first argument) + * Note that context origin is at the object's center point (not left/top corner) + * @type Function + */ + clipTo: null, + + /** + * When `true`, object horizontal movement is locked + * @type Boolean + * @default + */ + lockMovementX: false, + + /** + * When `true`, object vertical movement is locked + * @type Boolean + * @default + */ + lockMovementY: false, + + /** + * When `true`, object rotation is locked + * @type Boolean + * @default + */ + lockRotation: false, + + /** + * When `true`, object horizontal scaling is locked + * @type Boolean + * @default + */ + lockScalingX: false, + + /** + * When `true`, object vertical scaling is locked + * @type Boolean + * @default + */ + lockScalingY: false, + + /** + * When `true`, object non-uniform scaling is locked + * @type Boolean + * @default + */ + lockUniScaling: false, + + /** + * When `true`, object cannot be flipped by scaling into negative values + * @type Boolean + * @default + */ + + lockScalingFlip: false, + /** + * List of properties to consider when checking if state + * of an object is changed (fabric.Object#hasStateChanged) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: ( + 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' + + 'stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit ' + + 'angle opacity fill fillRule shadow clipTo visible backgroundColor' + ).split(' '), + + /** + * Constructor + * @param {Object} [options] Options object + */ + initialize: function(options) { + if (options) { + this.setOptions(options); + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initGradient: function(options) { + if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) { + this.set('fill', new fabric.Gradient(options.fill)); + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initPattern: function(options) { + if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) { + this.set('fill', new fabric.Pattern(options.fill)); + } + if (options.stroke && options.stroke.source && !(options.stroke instanceof fabric.Pattern)) { + this.set('stroke', new fabric.Pattern(options.stroke)); + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initClipping: function(options) { + if (!options.clipTo || typeof options.clipTo !== 'string') { + return; + } + + var functionBody = fabric.util.getFunctionBody(options.clipTo); + if (typeof functionBody !== 'undefined') { + this.clipTo = new Function('ctx', functionBody); + } + }, + + /** + * Sets object's properties from options + * @param {Object} [options] Options object + */ + setOptions: function(options) { + for (var prop in options) { + this.set(prop, options[prop]); + } + this._initGradient(options); + this._initPattern(options); + this._initClipping(options); + }, + + /** + * Transforms context when rendering an object + * @param {CanvasRenderingContext2D} ctx Context + * @param {Boolean} fromLeft When true, context is transformed to object's top/left corner. This is used when rendering text on Node + */ + transform: function(ctx, fromLeft) { + if (this.group) { + this.group.transform(ctx, fromLeft); + } + ctx.globalAlpha = this.opacity; + + var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint(); + ctx.translate(center.x, center.y); + ctx.rotate(degreesToRadians(this.angle)); + ctx.scale( + this.scaleX * (this.flipX ? -1 : 1), + this.scaleY * (this.flipY ? -1 : 1) + ); + }, + + /** + * Returns an object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, + + object = { + type: this.type, + originX: this.originX, + originY: this.originY, + left: toFixed(this.left, NUM_FRACTION_DIGITS), + top: toFixed(this.top, NUM_FRACTION_DIGITS), + width: toFixed(this.width, NUM_FRACTION_DIGITS), + height: toFixed(this.height, NUM_FRACTION_DIGITS), + fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill, + stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke, + strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS), + strokeDashArray: this.strokeDashArray, + strokeLineCap: this.strokeLineCap, + strokeLineJoin: this.strokeLineJoin, + strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS), + scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS), + scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS), + angle: toFixed(this.getAngle(), NUM_FRACTION_DIGITS), + flipX: this.flipX, + flipY: this.flipY, + opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS), + shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow, + visible: this.visible, + clipTo: this.clipTo && String(this.clipTo), + backgroundColor: this.backgroundColor + }; + + if (!this.includeDefaultValues) { + object = this._removeDefaultValues(object); + } + + fabric.util.populateWithProperties(this, object, propertiesToInclude); + + return object; + }, + + /** + * Returns (dataless) object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + // will be overwritten by subclasses + return this.toObject(propertiesToInclude); + }, + + /** + * @private + * @param {Object} object + */ + _removeDefaultValues: function(object) { + var prototype = fabric.util.getKlass(object.type).prototype, + stateProperties = prototype.stateProperties; + + stateProperties.forEach(function(prop) { + if (object[prop] === prototype[prop]) { + delete object[prop]; + } + }); + + return object; + }, + + /** + * Returns a string representation of an instance + * @return {String} + */ + toString: function() { + return '#'; + }, + + /** + * Basic getter + * @param {String} property Property name + * @return {Any} value of a property + */ + get: function(property) { + return this[property]; + }, + + /** + * @private + */ + _setObject: function(obj) { + for (var prop in obj) { + this._set(prop, obj[prop]); + } + }, + + /** + * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`. + * @param {String|Object} key Property name or object (if object, iterate over the object properties) + * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one) + * @return {fabric.Object} thisArg + * @chainable + */ + set: function(key, value) { + if (typeof key === 'object') { + this._setObject(key); + } + else { + if (typeof value === 'function' && key !== 'clipTo') { + this._set(key, value(this.get(key))); + } + else { + this._set(key, value); + } + } + return this; + }, + + /** + * @private + * @param {String} key + * @param {Any} value + * @return {fabric.Object} thisArg + */ + _set: function(key, value) { + var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY'); + + if (shouldConstrainValue) { + value = this._constrainScale(value); + } + if (key === 'scaleX' && value < 0) { + this.flipX = !this.flipX; + value *= -1; + } + else if (key === 'scaleY' && value < 0) { + this.flipY = !this.flipY; + value *= -1; + } + else if (key === 'width' || key === 'height') { + this.minScaleLimit = toFixed(Math.min(0.1, 1/Math.max(this.width, this.height)), 2); + } + else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) { + value = new fabric.Shadow(value); + } + + this[key] = value; + + return this; + }, + + /** + * Toggles specified property from `true` to `false` or from `false` to `true` + * @param {String} property Property to toggle + * @return {fabric.Object} thisArg + * @chainable + */ + toggle: function(property) { + var value = this.get(property); + if (typeof value === 'boolean') { + this.set(property, !value); + } + return this; + }, + + /** + * Sets sourcePath of an object + * @param {String} value Value to set sourcePath to + * @return {fabric.Object} thisArg + * @chainable + */ + setSourcePath: function(value) { + this.sourcePath = value; + return this; + }, + + /** + * Retrieves viewportTransform from Object's canvas if possible + * @method getViewportTransform + * @memberOf fabric.Object.prototype + * @return {Boolean} flipY value // TODO + */ + getViewportTransform: function() { + if (this.canvas && this.canvas.viewportTransform) { + return this.canvas.viewportTransform; + } + return [1, 0, 0, 1, 0, 0]; + }, + + /** + * Renders an object on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if width/height are zeros or object is not visible + if (this.width === 0 || this.height === 0 || !this.visible) { + return; + } + + ctx.save(); + + //setup fill rule for current object + this._setupFillRule(ctx); + + this._transform(ctx, noTransform); + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); + + if (this.group && this.group.type === 'path-group') { + ctx.translate(-this.group.width/2, -this.group.height/2); + var m = this.transformMatrix; + if (m) { + ctx.transform.apply(ctx, m); + } + } + ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + this._render(ctx, noTransform); + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + this._restoreFillRule(ctx); + + ctx.restore(); + }, + + _transform: function(ctx, noTransform) { + var m = this.transformMatrix; + + if (m && !this.group) { + ctx.setTransform.apply(ctx, m); + } + if (!noTransform) { + this.transform(ctx); + } + }, + + _setStrokeStyles: function(ctx) { + if (this.stroke) { + ctx.lineWidth = this.strokeWidth; + ctx.lineCap = this.strokeLineCap; + ctx.lineJoin = this.strokeLineJoin; + ctx.miterLimit = this.strokeMiterLimit; + ctx.strokeStyle = this.stroke.toLive + ? this.stroke.toLive(ctx) + : this.stroke; + } + }, + + _setFillStyles: function(ctx) { + if (this.fill) { + ctx.fillStyle = this.fill.toLive + ? this.fill.toLive(ctx) + : this.fill; + } + }, + + /** + * Renders controls and borders for the object + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + _renderControls: function(ctx, noTransform) { + var vpt = this.getViewportTransform(); + + ctx.save(); + if (this.active && !noTransform) { + var center; + if (this.group) { + center = fabric.util.transformPoint(this.group.getCenterPoint(), vpt); + ctx.translate(center.x, center.y); + ctx.rotate(degreesToRadians(this.group.angle)); + } + center = fabric.util.transformPoint(this.getCenterPoint(), vpt, null != this.group); + if (this.group) { + center.x *= this.group.scaleX; + center.y *= this.group.scaleY; + } + ctx.translate(center.x, center.y); + ctx.rotate(degreesToRadians(this.angle)); + this.drawBorders(ctx); + this.drawControls(ctx); + } + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _setShadow: function(ctx) { + if (!this.shadow) { + return; + } + + ctx.shadowColor = this.shadow.color; + ctx.shadowBlur = this.shadow.blur; + ctx.shadowOffsetX = this.shadow.offsetX; + ctx.shadowOffsetY = this.shadow.offsetY; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _removeShadow: function(ctx) { + if (!this.shadow) { + return; + } + + ctx.shadowColor = ''; + ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderFill: function(ctx) { + if (!this.fill) { + return; + } + + ctx.save(); + if (this.fill.toLive) { + ctx.translate( + -this.width / 2 + this.fill.offsetX || 0, + -this.height / 2 + this.fill.offsetY || 0); + } + if (this.fill.gradientTransform) { + var g = this.fill.gradientTransform; + ctx.transform.apply(ctx, g); + } + if (this.fillRule === 'destination-over') { + ctx.fill('evenodd'); + } + else { + ctx.fill(); + } + ctx.restore(); + if (this.shadow && !this.shadow.affectStroke) { + this._removeShadow(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderStroke: function(ctx) { + if (!this.stroke || this.strokeWidth === 0) { + return; + } + + ctx.save(); + if (this.strokeDashArray) { + // Spec requires the concatenation of two copies the dash list when the number of elements is odd + if (1 & this.strokeDashArray.length) { + this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); + } + + if (supportsLineDash) { + ctx.setLineDash(this.strokeDashArray); + this._stroke && this._stroke(ctx); + } + else { + this._renderDashedStroke && this._renderDashedStroke(ctx); + } + ctx.stroke(); + } + else { + if (this.stroke.gradientTransform) { + var g = this.stroke.gradientTransform; + ctx.transform.apply(ctx, g); + } + this._stroke ? this._stroke(ctx) : ctx.stroke(); + } + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * Clones an instance + * @param {Function} callback Callback is invoked with a clone as a first argument + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {fabric.Object} clone of an instance + */ + clone: function(callback, propertiesToInclude) { + if (this.constructor.fromObject) { + return this.constructor.fromObject(this.toObject(propertiesToInclude), callback); + } + return new fabric.Object(this.toObject(propertiesToInclude)); + }, + + /** + * Creates an instance of fabric.Image out of an object + * @param {Function} callback callback, invoked with an instance as a first argument + * @return {fabric.Object} thisArg + */ + cloneAsImage: function(callback) { + var dataUrl = this.toDataURL(); + fabric.util.loadImage(dataUrl, function(img) { + if (callback) { + callback(new fabric.Image(img)); + } + }); + return this; + }, + + /** + * Converts an object into a data-url-like string + * @param {Object} options Options object + * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png" + * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg. + * @param {Number} [options.multiplier=1] Multiplier to scale by + * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14 + * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14 + * @param {Number} [options.width] Cropping width. Introduced in v1.2.14 + * @param {Number} [options.height] Cropping height. Introduced in v1.2.14 + * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format + */ + toDataURL: function(options) { + options || (options = { }); + + var el = fabric.util.createCanvasElement(), + boundingRect = this.getBoundingRect(); + + el.width = boundingRect.width; + el.height = boundingRect.height; + + fabric.util.wrapElement(el, 'div'); + var canvas = new fabric.Canvas(el); + + // to avoid common confusion https://github.com/kangax/fabric.js/issues/806 + if (options.format === 'jpg') { + options.format = 'jpeg'; + } + + if (options.format === 'jpeg') { + canvas.backgroundColor = '#fff'; + } + + var origParams = { + active: this.get('active'), + left: this.getLeft(), + top: this.getTop() + }; + + this.set('active', false); + this.setPositionByOrigin(new fabric.Point(el.width / 2, el.height / 2), 'center', 'center'); + + var originalCanvas = this.canvas; + canvas.add(this); + var data = canvas.toDataURL(options); + + this.set(origParams).setCoords(); + this.canvas = originalCanvas; + + canvas.dispose(); + canvas = null; + + return data; + }, + + /** + * Returns true if specified type is identical to the type of an instance + * @param {String} type Type to check against + * @return {Boolean} + */ + isType: function(type) { + return this.type === type; + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 0; + }, + + /** + * Returns a JSON representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} JSON + */ + toJSON: function(propertiesToInclude) { + // delegate, not alias + return this.toObject(propertiesToInclude); + }, + + /** + * Sets gradient (fill or stroke) of an object + * Backwards incompatibility note: This method was named "setGradientFill" until v1.1.0 + * @param {String} property Property name 'stroke' or 'fill' + * @param {Object} [options] Options object + * @param {String} [options.type] Type of gradient 'radial' or 'linear' + * @param {Number} [options.x1=0] x-coordinate of start point + * @param {Number} [options.y1=0] y-coordinate of start point + * @param {Number} [options.x2=0] x-coordinate of end point + * @param {Number} [options.y2=0] y-coordinate of end point + * @param {Number} [options.r1=0] Radius of start point (only for radial gradients) + * @param {Number} [options.r2=0] Radius of end point (only for radial gradients) + * @param {Object} [options.colorStops] Color stops object eg. {0: 'ff0000', 1: '000000'} + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/58y8b/|jsFiddle demo} + * @example Set linear gradient + * object.setGradient('fill', { + * type: 'linear', + * x1: -object.width / 2, + * y1: 0, + * x2: object.width / 2, + * y2: 0, + * colorStops: { + * 0: 'red', + * 0.5: '#005555', + * 1: 'rgba(0,0,255,0.5)' + * } + * }); + * canvas.renderAll(); + * @example Set radial gradient + * object.setGradient('fill', { + * type: 'radial', + * x1: 0, + * y1: 0, + * x2: 0, + * y2: 0, + * r1: object.width / 2, + * r2: 10, + * colorStops: { + * 0: 'red', + * 0.5: '#005555', + * 1: 'rgba(0,0,255,0.5)' + * } + * }); + * canvas.renderAll(); + */ + setGradient: function(property, options) { + options || (options = { }); + + var gradient = { colorStops: [] }; + + gradient.type = options.type || (options.r1 || options.r2 ? 'radial' : 'linear'); + gradient.coords = { + x1: options.x1, + y1: options.y1, + x2: options.x2, + y2: options.y2 + }; + + if (options.r1 || options.r2) { + gradient.coords.r1 = options.r1; + gradient.coords.r2 = options.r2; + } + + for (var position in options.colorStops) { + var color = new fabric.Color(options.colorStops[position]); + gradient.colorStops.push({ + offset: position, + color: color.toRgb(), + opacity: color.getAlpha() + }); + } + + return this.set(property, fabric.Gradient.forObject(this, gradient)); + }, + + /** + * Sets pattern fill of an object + * @param {Object} options Options object + * @param {(String|HTMLImageElement)} options.source Pattern source + * @param {String} [options.repeat=repeat] Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat) + * @param {Number} [options.offsetX=0] Pattern horizontal offset from object's left/top corner + * @param {Number} [options.offsetY=0] Pattern vertical offset from object's left/top corner + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/QT3pa/|jsFiddle demo} + * @example Set pattern + * fabric.util.loadImage('http://fabricjs.com/assets/escheresque_ste.png', function(img) { + * object.setPatternFill({ + * source: img, + * repeat: 'repeat' + * }); + * canvas.renderAll(); + * }); + */ + setPatternFill: function(options) { + return this.set('fill', new fabric.Pattern(options)); + }, + + /** + * Sets {@link fabric.Object#shadow|shadow} of an object + * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") + * @param {String} [options.color=rgb(0,0,0)] Shadow color + * @param {Number} [options.blur=0] Shadow blur + * @param {Number} [options.offsetX=0] Shadow horizontal offset + * @param {Number} [options.offsetY=0] Shadow vertical offset + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/7gvJG/|jsFiddle demo} + * @example Set shadow with string notation + * object.setShadow('2px 2px 10px rgba(0,0,0,0.2)'); + * canvas.renderAll(); + * @example Set shadow with object notation + * object.setShadow({ + * color: 'red', + * blur: 10, + * offsetX: 20, + * offsetY: 20 + * }); + * canvas.renderAll(); + */ + setShadow: function(options) { + return this.set('shadow', options ? new fabric.Shadow(options) : null); + }, + + /** + * Sets "color" of an instance (alias of `set('fill', …)`) + * @param {String} color Color value + * @return {fabric.Object} thisArg + * @chainable + */ + setColor: function(color) { + this.set('fill', color); + return this; + }, + + /** + * Sets "angle" of an instance + * @param {Number} angle Angle value + * @return {fabric.Object} thisArg + * @chainable + */ + setAngle: function(angle) { + var shouldCenterOrigin = (this.originX !== 'center' || this.originY !== 'center') && this.centeredRotation; + + if (shouldCenterOrigin) { + this._setOriginToCenter(); + } + + this.set('angle', angle); + + if (shouldCenterOrigin) { + this._resetOrigin(); + } + + return this; + }, + + /** + * Centers object horizontally on canvas to which it was added last. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + centerH: function () { + this.canvas.centerObjectH(this); + return this; + }, + + /** + * Centers object vertically on canvas to which it was added last. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + centerV: function () { + this.canvas.centerObjectV(this); + return this; + }, + + /** + * Centers object vertically and horizontally on canvas to which is was added last + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + center: function () { + this.canvas.centerObject(this); + return this; + }, + + /** + * Removes object from canvas to which it was added last + * @return {fabric.Object} thisArg + * @chainable + */ + remove: function() { + this.canvas.remove(this); + return this; + }, + + /** + * Returns coordinates of a pointer relative to an object + * @param {Event} e Event to operate upon + * @param {Object} [pointer] Pointer to operate upon (instead of event) + * @return {Object} Coordinates of a pointer (x, y) + */ + getLocalPointer: function(e, pointer) { + pointer = pointer || this.canvas.getPointer(e); + var objectLeftTop = this.translateToOriginPoint(this.getCenterPoint(), 'left', 'top'); + return { + x: pointer.x - objectLeftTop.x, + y: pointer.y - objectLeftTop.y + }; + }, + + /** + * Sets canvas globalCompositeOperation for specific object + * custom composition operation for the particular object can be specifed using fillRule property + * @param {CanvasRenderingContext2D} ctx Rendering canvas context + */ + _setupFillRule: function (ctx) { + if (this.fillRule) { + this._prevFillRule = ctx.globalCompositeOperation; + ctx.globalCompositeOperation = this.fillRule; + } + }, + + /** + * Restores previously saved canvas globalCompositeOperation after obeject rendering + * @param {CanvasRenderingContext2D} ctx Rendering canvas context + */ + _restoreFillRule: function (ctx) { + if (this.fillRule && this._prevFillRule) { + ctx.globalCompositeOperation = this._prevFillRule; + } + } + }); + + fabric.util.createAccessors(fabric.Object); + + /** + * Alias for {@link fabric.Object.prototype.setAngle} + * @alias rotate -> setAngle + * @memberof fabric.Object + */ + fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle; + + extend(fabric.Object.prototype, fabric.Observable); + + /** + * Defines the number of fraction digits to use when serializing object values. + * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc. + * @static + * @memberof fabric.Object + * @constant + * @type Number + */ + fabric.Object.NUM_FRACTION_DIGITS = 2; + + /** + * Unique id used internally when creating SVG elements + * @static + * @memberof fabric.Object + * @type Number + */ + fabric.Object.__uid = 0; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + var degreesToRadians = fabric.util.degreesToRadians; + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Translates the coordinates from origin to center coordinates (based on the object's dimensions) + * @param {fabric.Point} point The point which corresponds to the originX and originY params + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + translateToCenterPoint: function(point, originX, originY) { + var cx = point.x, + cy = point.y, + strokeWidth = this.stroke ? this.strokeWidth : 0; + + if (originX === 'left') { + cx = point.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === 'right') { + cx = point.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + + if (originY === 'top') { + cy = point.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === 'bottom') { + cy = point.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + + // Apply the reverse rotation to the point (it's already scaled properly) + return fabric.util.rotatePoint(new fabric.Point(cx, cy), point, degreesToRadians(this.angle)); + }, + + /** + * Translates the coordinates from center to origin coordinates (based on the object's dimensions) + * @param {fabric.Point} center The point which corresponds to center of the object + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + translateToOriginPoint: function(center, originX, originY) { + var x = center.x, + y = center.y, + strokeWidth = this.stroke ? this.strokeWidth : 0; + + // Get the point coordinates + if (originX === 'left') { + x = center.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === 'right') { + x = center.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + if (originY === 'top') { + y = center.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === 'bottom') { + y = center.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + + // Apply the rotation to the point (it's already scaled properly) + return fabric.util.rotatePoint(new fabric.Point(x, y), center, degreesToRadians(this.angle)); + }, + + /** + * Returns the real center coordinates of the object + * @return {fabric.Point} + */ + getCenterPoint: function() { + var leftTop = new fabric.Point(this.left, this.top); + return this.translateToCenterPoint(leftTop, this.originX, this.originY); + }, + + /** + * Returns the coordinates of the object based on center coordinates + * @param {fabric.Point} point The point which corresponds to the originX and originY params + * @return {fabric.Point} + */ + // getOriginPoint: function(center) { + // return this.translateToOriginPoint(center, this.originX, this.originY); + // }, + + /** + * Returns the coordinates of the object as if it has a different origin + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + getPointByOrigin: function(originX, originY) { + var center = this.getCenterPoint(); + return this.translateToOriginPoint(center, originX, originY); + }, + + /** + * Returns the point in local coordinates + * @param {fabric.Point} point The point relative to the global coordinate system + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + toLocalPoint: function(point, originX, originY) { + var center = this.getCenterPoint(), + strokeWidth = this.stroke ? this.strokeWidth : 0, + x, y; + + if (originX && originY) { + if (originX === 'left') { + x = center.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === 'right') { + x = center.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else { + x = center.x; + } + + if (originY === 'top') { + y = center.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === 'bottom') { + y = center.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else { + y = center.y; + } + } + else { + x = this.left; + y = this.top; + } + + return fabric.util.rotatePoint(new fabric.Point(point.x, point.y), center, -degreesToRadians(this.angle)) + .subtractEquals(new fabric.Point(x, y)); + }, + + /** + * Returns the point in global coordinates + * @param {fabric.Point} The point relative to the local coordinate system + * @return {fabric.Point} + */ + // toGlobalPoint: function(point) { + // return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top)); + // }, + + /** + * Sets the position of the object taking into consideration the object's origin + * @param {fabric.Point} pos The new position of the object + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {void} + */ + setPositionByOrigin: function(pos, originX, originY) { + var center = this.translateToCenterPoint(pos, originX, originY), + position = this.translateToOriginPoint(center, this.originX, this.originY); + + this.set('left', position.x); + this.set('top', position.y); + }, + + /** + * @param {String} to One of 'left', 'center', 'right' + */ + adjustPosition: function(to) { + var angle = degreesToRadians(this.angle), + hypotHalf = this.getWidth() / 2, + xHalf = Math.cos(angle) * hypotHalf, + yHalf = Math.sin(angle) * hypotHalf, + hypotFull = this.getWidth(), + xFull = Math.cos(angle) * hypotFull, + yFull = Math.sin(angle) * hypotFull; + + if (this.originX === 'center' && to === 'left' || + this.originX === 'right' && to === 'center') { + // move half left + this.left -= xHalf; + this.top -= yHalf; + } + else if (this.originX === 'left' && to === 'center' || + this.originX === 'center' && to === 'right') { + // move half right + this.left += xHalf; + this.top += yHalf; + } + else if (this.originX === 'left' && to === 'right') { + // move full right + this.left += xFull; + this.top += yFull; + } + else if (this.originX === 'right' && to === 'left') { + // move full left + this.left -= xFull; + this.top -= yFull; + } + + this.setCoords(); + this.originX = to; + }, + + /** + * Sets the origin/position of the object to it's center point + * @private + * @return {void} + */ + _setOriginToCenter: function() { + this._originalOriginX = this.originX; + this._originalOriginY = this.originY; + + var center = this.getCenterPoint(); + + this.originX = 'center'; + this.originY = 'center'; + + this.left = center.x; + this.top = center.y; + }, + + /** + * Resets the origin/position of the object to it's original origin + * @private + * @return {void} + */ + _resetOrigin: function() { + var originPoint = this.translateToOriginPoint( + this.getCenterPoint(), + this._originalOriginX, + this._originalOriginY); + + this.originX = this._originalOriginX; + this.originY = this._originalOriginY; + + this.left = originPoint.x; + this.top = originPoint.y; + + this._originalOriginX = null; + this._originalOriginY = null; + }, + + /** + * @private + */ + _getLeftTopCoords: function() { + return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'center'); + } + }); + +})(); + + +(function() { + + var degreesToRadians = fabric.util.degreesToRadians; + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Object containing coordinates of object's controls + * @type Object + * @default + */ + oCoords: null, + + /** + * Checks if object intersects with an area formed by 2 points + * @param {Object} pointTL top-left point of area + * @param {Object} pointBR bottom-right point of area + * @return {Boolean} true if object intersects with an area formed by 2 points + */ + intersectsWithRect: function(pointTL, pointBR) { + var oCoords = this.oCoords, + tl = new fabric.Point(oCoords.tl.x, oCoords.tl.y), + tr = new fabric.Point(oCoords.tr.x, oCoords.tr.y), + bl = new fabric.Point(oCoords.bl.x, oCoords.bl.y), + br = new fabric.Point(oCoords.br.x, oCoords.br.y), + intersection = fabric.Intersection.intersectPolygonRectangle( + [tl, tr, br, bl], + pointTL, + pointBR + ); + return intersection.status === 'Intersection'; + }, + + /** + * Checks if object intersects with another object + * @param {Object} other Object to test + * @return {Boolean} true if object intersects with another object + */ + intersectsWithObject: function(other) { + // extracts coords + function getCoords(oCoords) { + return { + tl: new fabric.Point(oCoords.tl.x, oCoords.tl.y), + tr: new fabric.Point(oCoords.tr.x, oCoords.tr.y), + bl: new fabric.Point(oCoords.bl.x, oCoords.bl.y), + br: new fabric.Point(oCoords.br.x, oCoords.br.y) + }; + } + var thisCoords = getCoords(this.oCoords), + otherCoords = getCoords(other.oCoords), + intersection = fabric.Intersection.intersectPolygonPolygon( + [thisCoords.tl, thisCoords.tr, thisCoords.br, thisCoords.bl], + [otherCoords.tl, otherCoords.tr, otherCoords.br, otherCoords.bl] + ); + + return intersection.status === 'Intersection'; + }, + + /** + * Checks if object is fully contained within area of another object + * @param {Object} other Object to test + * @return {Boolean} true if object is fully contained within area of another object + */ + isContainedWithinObject: function(other) { + var boundingRect = other.getBoundingRect(), + point1 = new fabric.Point(boundingRect.left, boundingRect.top), + point2 = new fabric.Point(boundingRect.left + boundingRect.width, boundingRect.top + boundingRect.height); + + return this.isContainedWithinRect(point1, point2); + }, + + /** + * Checks if object is fully contained within area formed by 2 points + * @param {Object} pointTL top-left point of area + * @param {Object} pointBR bottom-right point of area + * @return {Boolean} true if object is fully contained within area formed by 2 points + */ + isContainedWithinRect: function(pointTL, pointBR) { + var boundingRect = this.getBoundingRect(); + + return ( + boundingRect.left >= pointTL.x && + boundingRect.left + boundingRect.width <= pointBR.x && + boundingRect.top >= pointTL.y && + boundingRect.top + boundingRect.height <= pointBR.y + ); + }, + + /** + * Checks if point is inside the object + * @param {fabric.Point} point Point to check against + * @return {Boolean} true if point is inside the object + */ + containsPoint: function(point) { + var lines = this._getImageLines(this.oCoords), + xPoints = this._findCrossPoints(point, lines); + + // if xPoints is odd then point is inside the object + return (xPoints !== 0 && xPoints % 2 === 1); + }, + + /** + * Method that returns an object with the object edges in it, given the coordinates of the corners + * @private + * @param {Object} oCoords Coordinates of the object corners + */ + _getImageLines: function(oCoords) { + return { + topline: { + o: oCoords.tl, + d: oCoords.tr + }, + rightline: { + o: oCoords.tr, + d: oCoords.br + }, + bottomline: { + o: oCoords.br, + d: oCoords.bl + }, + leftline: { + o: oCoords.bl, + d: oCoords.tl + } + }; + }, + + /** + * Helper method to determine how many cross points are between the 4 object edges + * and the horizontal line determined by a point on canvas + * @private + * @param {fabric.Point} point Point to check + * @param {Object} oCoords Coordinates of the object being evaluated + */ + _findCrossPoints: function(point, oCoords) { + var b1, b2, a1, a2, xi, yi, + xcount = 0, + iLine; + + for (var lineKey in oCoords) { + iLine = oCoords[lineKey]; + // optimisation 1: line below point. no cross + if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) { + continue; + } + // optimisation 2: line above point. no cross + if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) { + continue; + } + // optimisation 3: vertical line case + if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) { + xi = iLine.o.x; + yi = point.y; + } + // calculate the intersection point + else { + b1 = 0; + b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x); + a1 = point.y - b1 * point.x; + a2 = iLine.o.y - b2 * iLine.o.x; + + xi = - (a1 - a2) / (b1 - b2); + yi = a1 + b1 * xi; + } + // dont count xi < point.x cases + if (xi >= point.x) { + xcount += 1; + } + // optimisation 4: specific for square images + if (xcount === 2) { + break; + } + } + return xcount; + }, + + /** + * Returns width of an object's bounding rectangle + * @deprecated since 1.0.4 + * @return {Number} width value + */ + getBoundingRectWidth: function() { + return this.getBoundingRect().width; + }, + + /** + * Returns height of an object's bounding rectangle + * @deprecated since 1.0.4 + * @return {Number} height value + */ + getBoundingRectHeight: function() { + return this.getBoundingRect().height; + }, + + /** + * Returns coordinates of object's bounding rectangle (left, top, width, height) + * @return {Object} Object with left, top, width, height properties + */ + getBoundingRect: function() { + this.oCoords || this.setCoords(); + + var xCoords = [this.oCoords.tl.x, this.oCoords.tr.x, this.oCoords.br.x, this.oCoords.bl.x], + minX = fabric.util.array.min(xCoords), + maxX = fabric.util.array.max(xCoords), + width = Math.abs(minX - maxX), + + yCoords = [this.oCoords.tl.y, this.oCoords.tr.y, this.oCoords.br.y, this.oCoords.bl.y], + minY = fabric.util.array.min(yCoords), + maxY = fabric.util.array.max(yCoords), + height = Math.abs(minY - maxY); + + return { + left: minX, + top: minY, + width: width, + height: height + }; + }, + + /** + * Returns width of an object + * @return {Number} width value + */ + getWidth: function() { + return this.width * this.scaleX; + }, + + /** + * Returns height of an object + * @return {Number} height value + */ + getHeight: function() { + return this.height * this.scaleY; + }, + + /** + * Makes sure the scale is valid and modifies it if necessary + * @private + * @param {Number} value + * @return {Number} + */ + _constrainScale: function(value) { + if (Math.abs(value) < this.minScaleLimit) { + if (value < 0) { + return -this.minScaleLimit; + } + else { + return this.minScaleLimit; + } + } + return value; + }, + + /** + * Scales an object (equally by x and y) + * @param {Number} value Scale factor + * @return {fabric.Object} thisArg + * @chainable + */ + scale: function(value) { + value = this._constrainScale(value); + + if (value < 0) { + this.flipX = !this.flipX; + this.flipY = !this.flipY; + value *= -1; + } + + this.scaleX = value; + this.scaleY = value; + this.setCoords(); + return this; + }, + + /** + * Scales an object to a given width, with respect to bounding box (scaling by x/y equally) + * @param {Number} value New width value + * @return {fabric.Object} thisArg + * @chainable + */ + scaleToWidth: function(value) { + // adjust to bounding rect factor so that rotated shapes would fit as well + var boundingRectFactor = this.getBoundingRectWidth() / this.getWidth(); + return this.scale(value / this.width / boundingRectFactor); + }, + + /** + * Scales an object to a given height, with respect to bounding box (scaling by x/y equally) + * @param {Number} value New height value + * @return {fabric.Object} thisArg + * @chainable + */ + scaleToHeight: function(value) { + // adjust to bounding rect factor so that rotated shapes would fit as well + var boundingRectFactor = this.getBoundingRectHeight() / this.getHeight(); + return this.scale(value / this.height / boundingRectFactor); + }, + + /** + * Sets corner position coordinates based on current angle, width and height + * @return {fabric.Object} thisArg + * @chainable + */ + setCoords: function() { + var strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, + theta = degreesToRadians(this.angle), + vpt = this.getViewportTransform(), + f = function (p) { + return fabric.util.transformPoint(p, vpt); + }, + w = this.width, + h = this.height, + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + + if (vLine) { + w = strokeWidth; + } + else if (hLine) { + h = strokeWidth; + } + if (strokeW) { + w += strokeWidth; + } + if (strokeH) { + h += strokeWidth; + } + this.currentWidth = w * this.scaleX; + this.currentHeight = h * this.scaleY; + + // If width is negative, make postive. Fixes path selection issue + if (this.currentWidth < 0) { + this.currentWidth = Math.abs(this.currentWidth); + } + + var _hypotenuse = Math.sqrt( + Math.pow(this.currentWidth / 2, 2) + + Math.pow(this.currentHeight / 2, 2)), + + _angle = Math.atan(isFinite(this.currentHeight / this.currentWidth) ? this.currentHeight / this.currentWidth : 0), + + // offset added for rotate and scale actions + offsetX = Math.cos(_angle + theta) * _hypotenuse, + offsetY = Math.sin(_angle + theta) * _hypotenuse, + sinTh = Math.sin(theta), + cosTh = Math.cos(theta), + coords = this.getCenterPoint(), + wh = new fabric.Point(this.currentWidth, this.currentHeight), + _tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY), + _tr = new fabric.Point(_tl.x + (wh.x * cosTh), _tl.y + (wh.x * sinTh)), + _bl = new fabric.Point(_tl.x - (wh.y * sinTh), _tl.y + (wh.y * cosTh)), + _mt = new fabric.Point(_tl.x + (wh.x/2 * cosTh), _tl.y + (wh.x/2 * sinTh)), + tl = f(_tl), + tr = f(_tr), + br = f(new fabric.Point(_tr.x - (wh.y * sinTh), _tr.y + (wh.y * cosTh))), + bl = f(_bl), + ml = f(new fabric.Point(_tl.x - (wh.y/2 * sinTh), _tl.y + (wh.y/2 * cosTh))), + mt = f(_mt), + mr = f(new fabric.Point(_tr.x - (wh.y/2 * sinTh), _tr.y + (wh.y/2 * cosTh))), + mb = f(new fabric.Point(_bl.x + (wh.x/2 * cosTh), _bl.y + (wh.x/2 * sinTh))), + mtr = f(new fabric.Point(_mt.x, _mt.y)), + + // padding + padX = Math.cos(_angle + theta) * this.padding * Math.sqrt(2), + padY = Math.sin(_angle + theta) * this.padding * Math.sqrt(2); + + tl = tl.add(new fabric.Point(-padX, -padY)); + tr = tr.add(new fabric.Point(padY, -padX)); + br = br.add(new fabric.Point(padX, padY)); + bl = bl.add(new fabric.Point(-padY, padX)); + ml = ml.add(new fabric.Point((-padX - padY) / 2, (-padY + padX) / 2)); + mt = mt.add(new fabric.Point((padY - padX) / 2, -(padY + padX) / 2)); + mr = mr.add(new fabric.Point((padY + padX) / 2, (padY - padX) / 2)); + mb = mb.add(new fabric.Point((padX - padY) / 2, (padX + padY) / 2)); + mtr = mtr.add(new fabric.Point((padY - padX) / 2, -(padY + padX) / 2)); + + // debugging + + // setTimeout(function() { + // canvas.contextTop.fillStyle = 'green'; + // canvas.contextTop.fillRect(mb.x, mb.y, 3, 3); + // canvas.contextTop.fillRect(bl.x, bl.y, 3, 3); + // canvas.contextTop.fillRect(br.x, br.y, 3, 3); + // canvas.contextTop.fillRect(tl.x, tl.y, 3, 3); + // canvas.contextTop.fillRect(tr.x, tr.y, 3, 3); + // canvas.contextTop.fillRect(ml.x, ml.y, 3, 3); + // canvas.contextTop.fillRect(mr.x, mr.y, 3, 3); + // canvas.contextTop.fillRect(mt.x, mt.y, 3, 3); + // }, 50); + + this.oCoords = { + // corners + tl: tl, tr: tr, br: br, bl: bl, + // middle + ml: ml, mt: mt, mr: mr, mb: mb, + // rotating point + mtr: mtr + }; + + // set coordinates of the draggable boxes in the corners used to scale/rotate the image + this._setCornerCoords && this._setCornerCoords(); + + return this; + } + }); +})(); + + +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Moves an object to the bottom of the stack of drawn objects + * @return {fabric.Object} thisArg + * @chainable + */ + sendToBack: function() { + if (this.group) { + fabric.StaticCanvas.prototype.sendToBack.call(this.group, this); + } + else { + this.canvas.sendToBack(this); + } + return this; + }, + + /** + * Moves an object to the top of the stack of drawn objects + * @return {fabric.Object} thisArg + * @chainable + */ + bringToFront: function() { + if (this.group) { + fabric.StaticCanvas.prototype.bringToFront.call(this.group, this); + } + else { + this.canvas.bringToFront(this); + } + return this; + }, + + /** + * Moves an object down in stack of drawn objects + * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object + * @return {fabric.Object} thisArg + * @chainable + */ + sendBackwards: function(intersecting) { + if (this.group) { + fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting); + } + else { + this.canvas.sendBackwards(this, intersecting); + } + return this; + }, + + /** + * Moves an object up in stack of drawn objects + * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object + * @return {fabric.Object} thisArg + * @chainable + */ + bringForward: function(intersecting) { + if (this.group) { + fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting); + } + else { + this.canvas.bringForward(this, intersecting); + } + return this; + }, + + /** + * Moves an object to specified level in stack of drawn objects + * @param {Number} index New position of object + * @return {fabric.Object} thisArg + * @chainable + */ + moveTo: function(index) { + if (this.group) { + fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index); + } + else { + this.canvas.moveTo(this, index); + } + return this; + } +}); + + +/* _TO_SVG_START_ */ +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Returns styles-string for svg-export + * @return {String} + */ + getSvgStyles: function() { + + var fill = this.fill + ? (this.fill.toLive ? 'url(#SVGID_' + this.fill.id + ')' : this.fill) + : 'none', + fillRule = (this.fillRule === 'destination-over' ? 'evenodd' : this.fillRule), + stroke = this.stroke + ? (this.stroke.toLive ? 'url(#SVGID_' + this.stroke.id + ')' : this.stroke) + : 'none', + + strokeWidth = this.strokeWidth ? this.strokeWidth : '0', + strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : '', + strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt', + strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter', + strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4', + opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1', + + visibility = this.visible ? '' : ' visibility: hidden;', + filter = this.shadow && this.type !== 'text' ? 'filter: url(#SVGID_' + this.shadow.id + ');' : ''; + + return [ + 'stroke: ', stroke, '; ', + 'stroke-width: ', strokeWidth, '; ', + 'stroke-dasharray: ', strokeDashArray, '; ', + 'stroke-linecap: ', strokeLineCap, '; ', + 'stroke-linejoin: ', strokeLineJoin, '; ', + 'stroke-miterlimit: ', strokeMiterLimit, '; ', + 'fill: ', fill, '; ', + 'fill-rule: ', fillRule, '; ', + 'opacity: ', opacity, ';', + filter, + visibility + ].join(''); + }, + + /** + * Returns transform-string for svg-export + * @return {String} + */ + getSvgTransform: function() { + if (this.group) return ''; + var toFixed = fabric.util.toFixed, + angle = this.getAngle(), + vpt = this.getViewportTransform(), + center = fabric.util.transformPoint(this.getCenterPoint(), vpt), + + NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, + + translatePart = this.type === 'path-group' ? '' : 'translate(' + + toFixed(center.x, NUM_FRACTION_DIGITS) + + ' ' + + toFixed(center.y, NUM_FRACTION_DIGITS) + + ')', + + anglePart = angle !== 0 + ? (' rotate(' + toFixed(angle, NUM_FRACTION_DIGITS) + ')') + : '', + + scalePart = (this.scaleX === 1 && this.scaleY === 1 && vpt[0] === 1 && vpt[3] === 1) + ? '' : + (' scale(' + + toFixed(this.scaleX * vpt[0], NUM_FRACTION_DIGITS) + + ' ' + + toFixed(this.scaleY * vpt[3], NUM_FRACTION_DIGITS) + + ')'), + addTranslateX = this.type === 'path-group' ? this.width * vpt[0] : 0, + flipXPart = this.flipX ? ' matrix(-1 0 0 1 ' + addTranslateX + ' 0) ' : '', + addTranslateY = this.type === 'path-group' ? this.height * vpt[3] : 0, + flipYPart = this.flipY ? ' matrix(1 0 0 -1 0 ' + addTranslateY + ')' : ''; + + return [ + translatePart, anglePart, scalePart, flipXPart, flipYPart + ].join(''); + }, + + /** + * Returns transform-string for svg-export from the transform matrix of single elements + * @return {String} + */ + getSvgTransformMatrix: function() { + return this.transformMatrix ? ' matrix(' + this.transformMatrix.join(' ') + ')' : ''; + }, + + /** + * @private + */ + _createBaseSVGMarkup: function() { + var markup = [ ]; + + if (this.fill && this.fill.toLive) { + markup.push(this.fill.toSVG(this, false)); + } + if (this.stroke && this.stroke.toLive) { + markup.push(this.stroke.toSVG(this, false)); + } + if (this.shadow) { + markup.push(this.shadow.toSVG(this)); + } + return markup; + } +}); +/* _TO_SVG_END_ */ + + +/* + Depends on `stateProperties` +*/ +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Returns true if object state (one of its state properties) was changed + * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called + */ + hasStateChanged: function() { + return this.stateProperties.some(function(prop) { + return this.get(prop) !== this.originalState[prop]; + }, this); + }, + + /** + * Saves state of an object + * @param {Object} [options] Object with additional `stateProperties` array to include when saving state + * @return {fabric.Object} thisArg + */ + saveState: function(options) { + this.stateProperties.forEach(function(prop) { + this.originalState[prop] = this.get(prop); + }, this); + + if (options && options.stateProperties) { + options.stateProperties.forEach(function(prop) { + this.originalState[prop] = this.get(prop); + }, this); + } + + return this; + }, + + /** + * Setups state of an object + * @return {fabric.Object} thisArg + */ + setupState: function() { + this.originalState = { }; + this.saveState(); + + return this; + } +}); + + +(function(){ + + var degreesToRadians = fabric.util.degreesToRadians, + //jscs:disable requireCamelCaseOrUpperCaseIdentifiers + isVML = function() { return typeof G_vmlCanvasManager !== 'undefined'; }; + //jscs:enable requireCamelCaseOrUpperCaseIdentifiers + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * The object interactivity controls. + * @private + */ + _controlsVisibility: null, + + /** + * Determines which corner has been clicked + * @private + * @param {Object} pointer The pointer indicating the mouse position + * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found + */ + _findTargetCorner: function(pointer) { + if (!this.hasControls || !this.active) { + return false; + } + + var ex = pointer.x, + ey = pointer.y, + xPoints, + lines; + + for (var i in this.oCoords) { + + if (!this.isControlVisible(i)) { + continue; + } + + if (i === 'mtr' && !this.hasRotatingPoint) { + continue; + } + + if (this.get('lockUniScaling') && + (i === 'mt' || i === 'mr' || i === 'mb' || i === 'ml')) { + continue; + } + + lines = this._getImageLines(this.oCoords[i].corner); + + // debugging + + // canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2); + + xPoints = this._findCrossPoints({ x: ex, y: ey }, lines); + if (xPoints !== 0 && xPoints % 2 === 1) { + this.__corner = i; + return i; + } + } + return false; + }, + + /** + * Sets the coordinates of the draggable boxes in the corners of + * the image used to scale/rotate it. + * @private + */ + _setCornerCoords: function() { + var coords = this.oCoords, + theta = degreesToRadians(this.angle), + newTheta = degreesToRadians(45 - this.angle), + cornerHypotenuse = Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, + cosHalfOffset = cornerHypotenuse * Math.cos(newTheta), + sinHalfOffset = cornerHypotenuse * Math.sin(newTheta), + sinTh = Math.sin(theta), + cosTh = Math.cos(theta); + + coords.tl.corner = { + tl: { + x: coords.tl.x - sinHalfOffset, + y: coords.tl.y - cosHalfOffset + }, + tr: { + x: coords.tl.x + cosHalfOffset, + y: coords.tl.y - sinHalfOffset + }, + bl: { + x: coords.tl.x - cosHalfOffset, + y: coords.tl.y + sinHalfOffset + }, + br: { + x: coords.tl.x + sinHalfOffset, + y: coords.tl.y + cosHalfOffset + } + }; + + coords.tr.corner = { + tl: { + x: coords.tr.x - sinHalfOffset, + y: coords.tr.y - cosHalfOffset + }, + tr: { + x: coords.tr.x + cosHalfOffset, + y: coords.tr.y - sinHalfOffset + }, + br: { + x: coords.tr.x + sinHalfOffset, + y: coords.tr.y + cosHalfOffset + }, + bl: { + x: coords.tr.x - cosHalfOffset, + y: coords.tr.y + sinHalfOffset + } + }; + + coords.bl.corner = { + tl: { + x: coords.bl.x - sinHalfOffset, + y: coords.bl.y - cosHalfOffset + }, + bl: { + x: coords.bl.x - cosHalfOffset, + y: coords.bl.y + sinHalfOffset + }, + br: { + x: coords.bl.x + sinHalfOffset, + y: coords.bl.y + cosHalfOffset + }, + tr: { + x: coords.bl.x + cosHalfOffset, + y: coords.bl.y - sinHalfOffset + } + }; + + coords.br.corner = { + tr: { + x: coords.br.x + cosHalfOffset, + y: coords.br.y - sinHalfOffset + }, + bl: { + x: coords.br.x - cosHalfOffset, + y: coords.br.y + sinHalfOffset + }, + br: { + x: coords.br.x + sinHalfOffset, + y: coords.br.y + cosHalfOffset + }, + tl: { + x: coords.br.x - sinHalfOffset, + y: coords.br.y - cosHalfOffset + } + }; + + coords.ml.corner = { + tl: { + x: coords.ml.x - sinHalfOffset, + y: coords.ml.y - cosHalfOffset + }, + tr: { + x: coords.ml.x + cosHalfOffset, + y: coords.ml.y - sinHalfOffset + }, + bl: { + x: coords.ml.x - cosHalfOffset, + y: coords.ml.y + sinHalfOffset + }, + br: { + x: coords.ml.x + sinHalfOffset, + y: coords.ml.y + cosHalfOffset + } + }; + + coords.mt.corner = { + tl: { + x: coords.mt.x - sinHalfOffset, + y: coords.mt.y - cosHalfOffset + }, + tr: { + x: coords.mt.x + cosHalfOffset, + y: coords.mt.y - sinHalfOffset + }, + bl: { + x: coords.mt.x - cosHalfOffset, + y: coords.mt.y + sinHalfOffset + }, + br: { + x: coords.mt.x + sinHalfOffset, + y: coords.mt.y + cosHalfOffset + } + }; + + coords.mr.corner = { + tl: { + x: coords.mr.x - sinHalfOffset, + y: coords.mr.y - cosHalfOffset + }, + tr: { + x: coords.mr.x + cosHalfOffset, + y: coords.mr.y - sinHalfOffset + }, + bl: { + x: coords.mr.x - cosHalfOffset, + y: coords.mr.y + sinHalfOffset + }, + br: { + x: coords.mr.x + sinHalfOffset, + y: coords.mr.y + cosHalfOffset + } + }; + + coords.mb.corner = { + tl: { + x: coords.mb.x - sinHalfOffset, + y: coords.mb.y - cosHalfOffset + }, + tr: { + x: coords.mb.x + cosHalfOffset, + y: coords.mb.y - sinHalfOffset + }, + bl: { + x: coords.mb.x - cosHalfOffset, + y: coords.mb.y + sinHalfOffset + }, + br: { + x: coords.mb.x + sinHalfOffset, + y: coords.mb.y + cosHalfOffset + } + }; + + coords.mtr.corner = { + tl: { + x: coords.mtr.x - sinHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y - cosHalfOffset - (cosTh * this.rotatingPointOffset) + }, + tr: { + x: coords.mtr.x + cosHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y - sinHalfOffset - (cosTh * this.rotatingPointOffset) + }, + bl: { + x: coords.mtr.x - cosHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y + sinHalfOffset - (cosTh * this.rotatingPointOffset) + }, + br: { + x: coords.mtr.x + sinHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y + cosHalfOffset - (cosTh * this.rotatingPointOffset) + } + }; + }, + /** + * Draws borders of an object's bounding box. + * Requires public properties: width, height + * Requires public options: padding, borderColor + * @param {CanvasRenderingContext2D} ctx Context to draw on + * @return {fabric.Object} thisArg + * @chainable + */ + drawBorders: function(ctx) { + if (!this.hasBorders) { + return this; + } + + var padding = this.padding, + padding2 = padding * 2, + vpt = this.getViewportTransform(); + + ctx.save(); + + ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; + ctx.strokeStyle = this.borderColor; + + var scaleX = 1 / this._constrainScale(this.scaleX), + scaleY = 1 / this._constrainScale(this.scaleY); + + ctx.lineWidth = 1 / this.borderScaleFactor; + + var w = this.getWidth(), + h = this.getHeight(), + strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + if (vLine) { + w = strokeWidth / scaleX; + } + else if (hLine) { + h = strokeWidth / scaleY; + } + if (strokeW) { + w += strokeWidth / scaleX; + } + if (strokeH) { + h += strokeWidth / scaleY; + } + var wh = fabric.util.transformPoint(new fabric.Point(w, h), vpt, true), + width = wh.x, + height = wh.y; + if (this.group) { + width = width * this.group.scaleX; + height = height * this.group.scaleY; + } + + ctx.strokeRect( + ~~(-(width / 2) - padding) - 0.5, // offset needed to make lines look sharper + ~~(-(height / 2) - padding) - 0.5, + ~~(width + padding2) + 1, // double offset needed to make lines look sharper + ~~(height + padding2) + 1 + ); + + if (this.hasRotatingPoint && this.isControlVisible('mtr') && !this.get('lockRotation') && this.hasControls) { + + var rotateHeight = ( -height - (padding * 2)) / 2; + + ctx.beginPath(); + ctx.moveTo(0, rotateHeight); + ctx.lineTo(0, rotateHeight - this.rotatingPointOffset); + ctx.closePath(); + ctx.stroke(); + } + + ctx.restore(); + return this; + }, + + /** + * Draws corners of an object's bounding box. + * Requires public properties: width, height + * Requires public options: cornerSize, padding + * @param {CanvasRenderingContext2D} ctx Context to draw on + * @return {fabric.Object} thisArg + * @chainable + */ + drawControls: function(ctx) { + if (!this.hasControls) { + return this; + } + + var size = this.cornerSize, + size2 = size / 2, + vpt = this.getViewportTransform(), + strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, + w = this.width, + h = this.height, + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + + if (vLine) { + w = strokeWidth; + } + else if (hLine) { + h = strokeWidth; + } + if (strokeW) { + w += strokeWidth; + } + if (strokeH) { + h += strokeWidth; + } + w *= this.scaleX; + h *= this.scaleY; + + var wh = fabric.util.transformPoint(new fabric.Point(w, h), vpt, true), + width = wh.x, + height = wh.y, + left = -(width / 2), + top = -(height / 2), + padding = this.padding, + scaleOffset = size2, + scaleOffsetSize = size2 - size, + methodName = this.transparentCorners ? 'strokeRect' : 'fillRect'; + + ctx.save(); + + ctx.lineWidth = 1; + + ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; + ctx.strokeStyle = ctx.fillStyle = this.cornerColor; + + // top-left + this._drawControl('tl', ctx, methodName, + left - scaleOffset - padding, + top - scaleOffset - padding); + + // top-right + this._drawControl('tr', ctx, methodName, + left + width - scaleOffset + padding, + top - scaleOffset - padding); + + // bottom-left + this._drawControl('bl', ctx, methodName, + left - scaleOffset - padding, + top + height + scaleOffsetSize + padding); + + // bottom-right + this._drawControl('br', ctx, methodName, + left + width + scaleOffsetSize + padding, + top + height + scaleOffsetSize + padding); + + if (!this.get('lockUniScaling')) { + + // middle-top + this._drawControl('mt', ctx, methodName, + left + width/2 - scaleOffset, + top - scaleOffset - padding); + + // middle-bottom + this._drawControl('mb', ctx, methodName, + left + width/2 - scaleOffset, + top + height + scaleOffsetSize + padding); + + // middle-right + this._drawControl('mr', ctx, methodName, + left + width + scaleOffsetSize + padding, + top + height/2 - scaleOffset); + + // middle-left + this._drawControl('ml', ctx, methodName, + left - scaleOffset - padding, + top + height/2 - scaleOffset); + } + + // middle-top-rotate + if (this.hasRotatingPoint) { + this._drawControl('mtr', ctx, methodName, + left + width/2 - scaleOffset, + top - this.rotatingPointOffset - this.cornerSize/2 - padding); + } + + ctx.restore(); + + return this; + }, + + /** + * @private + */ + _drawControl: function(control, ctx, methodName, left, top) { + var size = this.cornerSize; + + if (this.isControlVisible(control)) { + isVML() || this.transparentCorners || ctx.clearRect(left, top, size, size); + ctx[methodName](left, top, size, size); + } + }, + + /** + * Returns true if the specified control is visible, false otherwise. + * @param {String} controlName The name of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'. + * @returns {Boolean} true if the specified control is visible, false otherwise + */ + isControlVisible: function(controlName) { + return this._getControlsVisibility()[controlName]; + }, + + /** + * Sets the visibility of the specified control. + * @param {String} controlName The name of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'. + * @param {Boolean} visible true to set the specified control visible, false otherwise + * @return {fabric.Object} thisArg + * @chainable + */ + setControlVisible: function(controlName, visible) { + this._getControlsVisibility()[controlName] = visible; + return this; + }, + + /** + * Sets the visibility state of object controls. + * @param {Object} [options] Options object + * @param {Boolean} [options.bl] true to enable the bottom-left control, false to disable it + * @param {Boolean} [options.br] true to enable the bottom-right control, false to disable it + * @param {Boolean} [options.mb] true to enable the middle-bottom control, false to disable it + * @param {Boolean} [options.ml] true to enable the middle-left control, false to disable it + * @param {Boolean} [options.mr] true to enable the middle-right control, false to disable it + * @param {Boolean} [options.mt] true to enable the middle-top control, false to disable it + * @param {Boolean} [options.tl] true to enable the top-left control, false to disable it + * @param {Boolean} [options.tr] true to enable the top-right control, false to disable it + * @param {Boolean} [options.mtr] true to enable the middle-top-rotate control, false to disable it + * @return {fabric.Object} thisArg + * @chainable + */ + setControlsVisibility: function(options) { + options || (options = { }); + + for (var p in options) { + this.setControlVisible(p, options[p]); + } + return this; + }, + + /** + * Returns the instance of the control visibility set for this object. + * @private + * @returns {Object} + */ + _getControlsVisibility: function() { + if (!this._controlsVisibility) { + this._controlsVisibility = { + tl: true, + tr: true, + br: true, + bl: true, + ml: true, + mt: true, + mr: true, + mb: true, + mtr: true + }; + } + return this._controlsVisibility; + } + }); +})(); + + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Animation duration (in ms) for fx* methods + * @type Number + * @default + */ + FX_DURATION: 500, + + /** + * Centers object horizontally with animation. + * @param {fabric.Object} object Object to center + * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxCenterObjectH: function (object, callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: object.get('left'), + endValue: this.getCenter().left, + duration: this.FX_DURATION, + onChange: function(value) { + object.set('left', value); + _this.renderAll(); + onChange(); + }, + onComplete: function() { + object.setCoords(); + onComplete(); + } + }); + + return this; + }, + + /** + * Centers object vertically with animation. + * @param {fabric.Object} object Object to center + * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxCenterObjectV: function (object, callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: object.get('top'), + endValue: this.getCenter().top, + duration: this.FX_DURATION, + onChange: function(value) { + object.set('top', value); + _this.renderAll(); + onChange(); + }, + onComplete: function() { + object.setCoords(); + onComplete(); + } + }); + + return this; + }, + + /** + * Same as `fabric.Canvas#remove` but animated + * @param {fabric.Object} object Object to remove + * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxRemove: function (object, callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: object.get('opacity'), + endValue: 0, + duration: this.FX_DURATION, + onStart: function() { + object.set('active', false); + }, + onChange: function(value) { + object.set('opacity', value); + _this.renderAll(); + onChange(); + }, + onComplete: function () { + _this.remove(object); + onComplete(); + } + }); + + return this; + } +}); + +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + /** + * Animates object's properties + * @param {String|Object} property Property to animate (if string) or properties to animate (if object) + * @param {Number|Object} value Value to animate property to (if string was given first) or options object + * @return {fabric.Object} thisArg + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#animation} + * @chainable + * + * As object — multiple properties + * + * object.animate({ left: ..., top: ... }); + * object.animate({ left: ..., top: ... }, { duration: ... }); + * + * As string — one property + * + * object.animate('left', ...); + * object.animate('left', { duration: ... }); + * + */ + animate: function() { + if (arguments[0] && typeof arguments[0] === 'object') { + var propsToAnimate = [ ], prop, skipCallbacks; + for (prop in arguments[0]) { + propsToAnimate.push(prop); + } + for (var i = 0, len = propsToAnimate.length; i < len; i++) { + prop = propsToAnimate[i]; + skipCallbacks = i !== len - 1; + this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks); + } + } + else { + this._animate.apply(this, arguments); + } + return this; + }, + + /** + * @private + * @param {String} property Property to animate + * @param {String} to Value to animate to + * @param {Object} [options] Options object + * @param {Boolean} [skipCallbacks] When true, callbacks like onchange and oncomplete are not invoked + */ + _animate: function(property, to, options, skipCallbacks) { + var _this = this, propPair; + + to = to.toString(); + + if (!options) { + options = { }; + } + else { + options = fabric.util.object.clone(options); + } + + if (~property.indexOf('.')) { + propPair = property.split('.'); + } + + var currentValue = propPair + ? this.get(propPair[0])[propPair[1]] + : this.get(property); + + if (!('from' in options)) { + options.from = currentValue; + } + + if (~to.indexOf('=')) { + to = currentValue + parseFloat(to.replace('=', '')); + } + else { + to = parseFloat(to); + } + + fabric.util.animate({ + startValue: options.from, + endValue: to, + byValue: options.by, + easing: options.easing, + duration: options.duration, + abort: options.abort && function() { + return options.abort.call(_this); + }, + onChange: function(value) { + if (propPair) { + _this[propPair[0]][propPair[1]] = value; + } + else { + _this.set(property, value); + } + if (skipCallbacks) { + return; + } + options.onChange && options.onChange(); + }, + onComplete: function() { + if (skipCallbacks) { + return; + } + + _this.setCoords(); + options.onComplete && options.onComplete(); + } + }); + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 }, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Line) { + fabric.warn('fabric.Line is already defined'); + return; + } + + /** + * Line class + * @class fabric.Line + * @extends fabric.Object + * @see {@link fabric.Line#initialize} for constructor definition + */ + fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'line', + + /** + * x value or first line edge + * @type Number + * @default + */ + x1: 0, + + /** + * y value or first line edge + * @type Number + * @default + */ + y1: 0, + + /** + * x value or second line edge + * @type Number + * @default + */ + x2: 0, + + /** + * y value or second line edge + * @type Number + * @default + */ + y2: 0, + + /** + * Constructor + * @param {Array} [points] Array of points + * @param {Object} [options] Options object + * @return {fabric.Line} thisArg + */ + initialize: function(points, options) { + options = options || { }; + + if (!points) { + points = [0, 0, 0, 0]; + } + + this.callSuper('initialize', options); + + this.set('x1', points[0]); + this.set('y1', points[1]); + this.set('x2', points[2]); + this.set('y2', points[3]); + + this._setWidthHeight(options); + }, + + /** + * @private + * @param {Object} [options] Options + */ + _setWidthHeight: function(options) { + options || (options = { }); + + this.width = Math.abs(this.x2 - this.x1) || 1; + this.height = Math.abs(this.y2 - this.y1) || 1; + + this.left = 'left' in options + ? options.left + : this._getLeftToOriginX(); + + this.top = 'top' in options + ? options.top + : this._getTopToOriginY(); + }, + + /** + * @private + * @param {String} key + * @param {Any} value + */ + _set: function(key, value) { + this[key] = value; + if (typeof coordProps[key] !== 'undefined') { + this._setWidthHeight(); + } + return this; + }, + + /** + * @private + * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line. + */ + _getLeftToOriginX: makeEdgeToOriginGetter( + { // property names + origin: 'originX', + axis1: 'x1', + axis2: 'x2', + dimension: 'width' + }, + { // possible values of origin + nearest: 'left', + center: 'center', + farthest: 'right' + } + ), + + /** + * @private + * @return {Number} topToOriginY Distance from top edge of canvas to originY of Line. + */ + _getTopToOriginY: makeEdgeToOriginGetter( + { // property names + origin: 'originY', + axis1: 'y1', + axis2: 'y2', + dimension: 'height' + }, + { // possible values of origin + nearest: 'top', + center: 'center', + farthest: 'bottom' + } + ), + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx, noTransform) { + ctx.beginPath(); + + if (noTransform) { + // Line coords are distances from left-top of canvas to origin of line. + // + // To render line in a path-group, we need to translate them to + // distances from center of path-group to center of line. + var cp = this.getCenterPoint(); + ctx.translate( + cp.x, + cp.y + ); + } + + if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) { + + // move from center (of virtual box) to its left/top corner + // we can't assume x1, y1 is top left and x2, y2 is bottom right + var xMult = this.x1 <= this.x2 ? -1 : 1, + yMult = this.y1 <= this.y2 ? -1 : 1; + + ctx.moveTo( + this.width === 1 ? 0 : (xMult * this.width / 2), + this.height === 1 ? 0 : (yMult * this.height / 2)); + + ctx.lineTo( + this.width === 1 ? 0 : (xMult * -1 * this.width / 2), + this.height === 1 ? 0 : (yMult * -1 * this.height / 2)); + } + + ctx.lineWidth = this.strokeWidth; + + // TODO: test this + // make sure setting "fill" changes color of a line + // (by copying fillStyle to strokeStyle, since line is stroked, not filled) + var origStrokeStyle = ctx.strokeStyle; + ctx.strokeStyle = this.stroke || ctx.fillStyle; + this.stroke && this._renderStroke(ctx); + ctx.strokeStyle = origStrokeStyle; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var + xMult = this.x1 <= this.x2 ? -1 : 1, + yMult = this.y1 <= this.y2 ? -1 : 1, + x = this.width === 1 ? 0 : xMult * this.width / 2, + y = this.height === 1 ? 0 : yMult * this.height / 2; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, -x, -y, this.strokeDashArray); + ctx.closePath(); + }, + + /** + * Returns object representation of an instance + * @methd toObject + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + x1: this.get('x1'), + y1: this.get('y1'), + x2: this.get('x2'), + y2: this.get('y2') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), addTranslate = ''; + if (!this.group) { + var x = - this.width / 2 - (this.x1 > this.x2 ? this.x2 : this.x1), + y = - this.height / 2 - (this.y1 > this.y2 ? this.y2 : this.y1); + addTranslate = 'translate(' + x + ', ' + y + ') '; + } + markup.push( + '\n' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement}) + * @static + * @memberOf fabric.Line + * @see http://www.w3.org/TR/SVG/shapes.html#LineElement + */ + fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' ')); + + /** + * Returns fabric.Line instance from an SVG element + * @static + * @memberOf fabric.Line + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Line} instance of fabric.Line + */ + fabric.Line.fromElement = function(element, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES), + points = [ + parsedAttributes.x1 || 0, + parsedAttributes.y1 || 0, + parsedAttributes.x2 || 0, + parsedAttributes.y2 || 0 + ]; + return new fabric.Line(points, extend(parsedAttributes, options)); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Line instance from an object representation + * @static + * @memberOf fabric.Line + * @param {Object} object Object to create an instance from + * @return {fabric.Line} instance of fabric.Line + */ + fabric.Line.fromObject = function(object) { + var points = [object.x1, object.y1, object.x2, object.y2]; + return new fabric.Line(points, object); + }; + + /** + * Produces a function that calculates distance from canvas edge to Line origin. + */ + function makeEdgeToOriginGetter(propertyNames, originValues) { + var origin = propertyNames.origin, + axis1 = propertyNames.axis1, + axis2 = propertyNames.axis2, + dimension = propertyNames.dimension, + nearest = originValues.nearest, + center = originValues.center, + farthest = originValues.farthest; + + return function() { + switch (this.get(origin)) { + case nearest: + return Math.min(this.get(axis1), this.get(axis2)); + case center: + return Math.min(this.get(axis1), this.get(axis2)) + (0.5 * this.get(dimension)); + case farthest: + return Math.max(this.get(axis1), this.get(axis2)); + } + }; + + } + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + piBy2 = Math.PI * 2, + extend = fabric.util.object.extend; + + if (fabric.Circle) { + fabric.warn('fabric.Circle is already defined.'); + return; + } + + /** + * Circle class + * @class fabric.Circle + * @extends fabric.Object + * @see {@link fabric.Circle#initialize} for constructor definition + */ + fabric.Circle = fabric.util.createClass(fabric.Object, /** @lends fabric.Circle.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'circle', + + /** + * Radius of this circle + * @type Number + * @default + */ + radius: 0, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Circle} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + this.set('radius', options.radius || 0); + }, + + /** + * @private + * @param {String} key + * @param {Any} value + * @return {fabric.Circle} thisArg + */ + _set: function(key, value) { + this.callSuper('_set', key, value); + + if (key === 'radius') { + this.setRadius(value); + } + + return this; + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + radius: this.get('radius') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), x = 0, y = 0; + if (this.group) { + x = this.left + this.radius; + y = this.top + this.radius; + } + markup.push( + '\n' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + _render: function(ctx, noTransform) { + ctx.beginPath(); + ctx.arc(noTransform ? this.left + this.radius : 0, noTransform ? this.top + this.radius : 0, this.radius, 0, piBy2, false); + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * Returns horizontal radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusX: function() { + return this.get('radius') * this.get('scaleX'); + }, + + /** + * Returns vertical radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusY: function() { + return this.get('radius') * this.get('scaleY'); + }, + + /** + * Sets radius of an object (and updates width accordingly) + * @return {Number} + */ + setRadius: function(value) { + this.radius = value; + this.set('width', value * 2).set('height', value * 2); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Circle.fromElement}) + * @static + * @memberOf fabric.Circle + * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement + */ + fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy r'.split(' ')); + + /** + * Returns {@link fabric.Circle} instance from an SVG element + * @static + * @memberOf fabric.Circle + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @throws {Error} If value of `r` attribute is missing or invalid + * @return {fabric.Circle} Instance of fabric.Circle + */ + fabric.Circle.fromElement = function(element, options) { + options || (options = { }); + + var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES); + + if (!isValidRadius(parsedAttributes)) { + throw new Error('value of `r` attribute is required and can not be negative'); + } + + parsedAttributes.left = parsedAttributes.left || 0; + parsedAttributes.top = parsedAttributes.top || 0; + + var obj = new fabric.Circle(extend(parsedAttributes, options)); + + obj.left -= obj.radius; + obj.top -= obj.radius; + return obj; + }; + + /** + * @private + */ + function isValidRadius(attributes) { + return (('radius' in attributes) && (attributes.radius > 0)); + } + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Circle} instance from an object representation + * @static + * @memberOf fabric.Circle + * @param {Object} object Object to create an instance from + * @return {Object} Instance of fabric.Circle + */ + fabric.Circle.fromObject = function(object) { + return new fabric.Circle(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Triangle) { + fabric.warn('fabric.Triangle is already defined'); + return; + } + + /** + * Triangle class + * @class fabric.Triangle + * @extends fabric.Object + * @return {fabric.Triangle} thisArg + * @see {@link fabric.Triangle#initialize} for constructor definition + */ + fabric.Triangle = fabric.util.createClass(fabric.Object, /** @lends fabric.Triangle.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'triangle', + + /** + * Constructor + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + + this.set('width', options.width || 100) + .set('height', options.height || 100); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + var widthBy2 = this.width / 2, + heightBy2 = this.height / 2; + + ctx.beginPath(); + ctx.moveTo(-widthBy2, heightBy2); + ctx.lineTo(0, -heightBy2); + ctx.lineTo(widthBy2, heightBy2); + ctx.closePath(); + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var widthBy2 = this.width / 2, + heightBy2 = this.height / 2; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray); + ctx.closePath(); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), + widthBy2 = this.width / 2, + heightBy2 = this.height / 2, + points = [ + -widthBy2 + ' ' + heightBy2, + '0 ' + -heightBy2, + widthBy2 + ' ' + heightBy2 + ] + .join(','); + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /** + * Returns fabric.Triangle instance from an object representation + * @static + * @memberOf fabric.Triangle + * @param {Object} object Object to create an instance from + * @return {Object} instance of Canvas.Triangle + */ + fabric.Triangle.fromObject = function(object) { + return new fabric.Triangle(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global){ + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + piBy2 = Math.PI * 2, + extend = fabric.util.object.extend; + + if (fabric.Ellipse) { + fabric.warn('fabric.Ellipse is already defined.'); + return; + } + + /** + * Ellipse class + * @class fabric.Ellipse + * @extends fabric.Object + * @return {fabric.Ellipse} thisArg + * @see {@link fabric.Ellipse#initialize} for constructor definition + */ + fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @lends fabric.Ellipse.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'ellipse', + + /** + * Horizontal radius + * @type Number + * @default + */ + rx: 0, + + /** + * Vertical radius + * @type Number + * @default + */ + ry: 0, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Ellipse} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + + this.set('rx', options.rx || 0); + this.set('ry', options.ry || 0); + + this.set('width', this.get('rx') * 2); + this.set('height', this.get('ry') * 2); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + rx: this.get('rx'), + ry: this.get('ry') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), x = 0, y = 0; + if (this.group) { + x = this.left + this.rx; + y = this.top + this.ry; + } + markup.push( + '\n' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + _render: function(ctx, noTransform) { + ctx.beginPath(); + ctx.save(); + ctx.transform(1, 0, 0, this.ry/this.rx, 0, 0); + ctx.arc(noTransform ? this.left + this.rx : 0, noTransform ? (this.top + this.ry) * this.rx/this.ry : 0, this.rx, 0, piBy2, false); + ctx.restore(); + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement}) + * @static + * @memberOf fabric.Ellipse + * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement + */ + fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy rx ry'.split(' ')); + + /** + * Returns {@link fabric.Ellipse} instance from an SVG element + * @static + * @memberOf fabric.Ellipse + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Ellipse} + */ + fabric.Ellipse.fromElement = function(element, options) { + options || (options = { }); + + var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES); + + parsedAttributes.left = parsedAttributes.left || 0; + parsedAttributes.top = parsedAttributes.top || 0; + + var ellipse = new fabric.Ellipse(extend(parsedAttributes, options)); + + ellipse.top -= ellipse.ry; + ellipse.left -= ellipse.rx; + return ellipse; + }; + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Ellipse} instance from an object representation + * @static + * @memberOf fabric.Ellipse + * @param {Object} object Object to create an instance from + * @return {fabric.Ellipse} + */ + fabric.Ellipse.fromObject = function(object) { + return new fabric.Ellipse(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + if (fabric.Rect) { + console.warn('fabric.Rect is already defined'); + return; + } + + var stateProperties = fabric.Object.prototype.stateProperties.concat(); + stateProperties.push('rx', 'ry', 'x', 'y'); + + /** + * Rectangle class + * @class fabric.Rect + * @extends fabric.Object + * @return {fabric.Rect} thisArg + * @see {@link fabric.Rect#initialize} for constructor definition + */ + fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ { + + /** + * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged}) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: stateProperties, + + /** + * Type of an object + * @type String + * @default + */ + type: 'rect', + + /** + * Horizontal border radius + * @type Number + * @default + */ + rx: 0, + + /** + * Vertical border radius + * @type Number + * @default + */ + ry: 0, + + + /** + * Used to specify dash pattern for stroke on this object + * @type Array + */ + strokeDashArray: null, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + this._initRxRy(); + + }, + + /** + * Initializes rx/ry attributes + * @private + */ + _initRxRy: function() { + if (this.rx && !this.ry) { + this.ry = this.rx; + } + else if (this.ry && !this.rx) { + this.rx = this.ry; + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx, noTransform) { + + // optimize 1x1 case (used in spray brush) + if (this.width === 1 && this.height === 1) { + ctx.fillRect(0, 0, 1, 1); + return; + } + + var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0, + ry = this.ry ? Math.min(this.ry, this.height / 2) : 0, + w = this.width, + h = this.height, + x = noTransform ? this.left : 0, + y = noTransform ? this.top : 0, + isRounded = rx !== 0 || ry !== 0, + k = 1 - 0.5522847498 /* "magic number" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */; + + ctx.beginPath(); + + if (!noTransform) { + ctx.translate(-this.width / 2, -this.height / 2); + } + + ctx.moveTo(x + rx, y); + + ctx.lineTo(x + w - rx, y); + isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry); + + ctx.lineTo(x + w, y + h - ry); + isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h); + + ctx.lineTo(x + rx, y + h); + isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry); + + ctx.lineTo(x, y + ry); + isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y); + + ctx.closePath(); + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var x = -this.width / 2, + y = -this.height / 2, + w = this.width, + h = this.height; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray); + ctx.closePath(); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var object = extend(this.callSuper('toObject', propertiesToInclude), { + rx: this.get('rx') || 0, + ry: this.get('ry') || 0 + }); + if (!this.includeDefaultValues) { + this._removeDefaultValues(object); + } + return object; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), x = this.left, y = this.top; + if (!this.group) { + x = -this.width / 2; + y = -this.height / 2; + } + markup.push( + '\n'); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`) + * @static + * @memberOf fabric.Rect + * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement + */ + fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' ')); + + /** + * Returns {@link fabric.Rect} instance from an SVG element + * @static + * @memberOf fabric.Rect + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Rect} Instance of fabric.Rect + */ + fabric.Rect.fromElement = function(element, options) { + if (!element) { + return null; + } + options = options || { }; + + var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES); + + parsedAttributes.left = parsedAttributes.left || 0; + parsedAttributes.top = parsedAttributes.top || 0; + + return new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Rect} instance from an object representation + * @static + * @memberOf fabric.Rect + * @param {Object} object Object to create an instance from + * @return {Object} instance of fabric.Rect + */ + fabric.Rect.fromObject = function(object) { + return new fabric.Rect(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + toFixed = fabric.util.toFixed; + + if (fabric.Polyline) { + fabric.warn('fabric.Polyline is already defined'); + return; + } + + /** + * Polyline class + * @class fabric.Polyline + * @extends fabric.Object + * @see {@link fabric.Polyline#initialize} for constructor definition + */ + fabric.Polyline = fabric.util.createClass(fabric.Object, /** @lends fabric.Polyline.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'polyline', + + /** + * Points array + * @type Array + * @default + */ + points: null, + + /** + * Constructor + * @param {Array} points Array of points (where each point is an object with x and y) + * @param {Object} [options] Options object + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + * @return {fabric.Polyline} thisArg + * @example + * var poly = new fabric.Polyline([ + * { x: 10, y: 10 }, + * { x: 50, y: 30 }, + * { x: 40, y: 70 }, + * { x: 60, y: 50 }, + * { x: 100, y: 150 }, + * { x: 40, y: 100 } + * ], { + * stroke: 'red', + * left: 100, + * top: 100 + * }); + */ + initialize: function(points, options, skipOffset) { + options = options || { }; + this.set('points', points); + this.callSuper('initialize', options); + this._calcDimensions(skipOffset); + }, + + /** + * @private + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + */ + _calcDimensions: function(skipOffset) { + return fabric.Polygon.prototype._calcDimensions.call(this, skipOffset); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return fabric.Polygon.prototype.toObject.call(this, propertiesToInclude); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var points = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.points.length; i < len; i++) { + points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' '); + } + + markup.push( + '\n' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + var point; + ctx.beginPath(); + ctx.moveTo(this.points[0].x, this.points[0].y); + for (var i = 0, len = this.points.length; i < len; i++) { + point = this.points[i]; + ctx.lineTo(point.x, point.y); + } + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var p1, p2; + + ctx.beginPath(); + for (var i = 0, len = this.points.length; i < len; i++) { + p1 = this.points[i]; + p2 = this.points[i + 1] || p1; + fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); + } + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.get('points').length; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement}) + * @static + * @memberOf fabric.Polyline + * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement + */ + fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + + /** + * Returns fabric.Polyline instance from an SVG element + * @static + * @memberOf fabric.Polyline + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Polyline} Instance of fabric.Polyline + */ + fabric.Polyline.fromElement = function(element, options) { + if (!element) { + return null; + } + options || (options = { }); + + var points = fabric.parsePointsAttribute(element.getAttribute('points')), + parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES); + + if (points === null) { + return null; + } + + return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options), true); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Polyline instance from an object representation + * @static + * @memberOf fabric.Polyline + * @param {Object} object Object to create an instance from + * @return {fabric.Polyline} Instance of fabric.Polyline + */ + fabric.Polyline.fromObject = function(object) { + var points = object.points; + return new fabric.Polyline(points, object, true); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + min = fabric.util.array.min, + max = fabric.util.array.max, + toFixed = fabric.util.toFixed; + + if (fabric.Polygon) { + fabric.warn('fabric.Polygon is already defined'); + return; + } + + /** + * Polygon class + * @class fabric.Polygon + * @extends fabric.Object + * @see {@link fabric.Polygon#initialize} for constructor definition + */ + fabric.Polygon = fabric.util.createClass(fabric.Object, /** @lends fabric.Polygon.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'polygon', + + /** + * Points array + * @type Array + * @default + */ + points: null, + + /** + * Constructor + * @param {Array} points Array of points + * @param {Object} [options] Options object + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + * @return {fabric.Polygon} thisArg + */ + initialize: function(points, options, skipOffset) { + options = options || { }; + this.points = points; + this.callSuper('initialize', options); + this._calcDimensions(skipOffset); + }, + + /** + * @private + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + */ + _calcDimensions: function(skipOffset) { + + var points = this.points, + minX = min(points, 'x'), + minY = min(points, 'y'), + maxX = max(points, 'x'), + maxY = max(points, 'y'); + + this.width = (maxX - minX) || 1; + this.height = (maxY - minY) || 1; + + this.minX = minX; + this.minY = minY; + + if (skipOffset) { + return; + } + + var halfWidth = this.width / 2 + this.minX, + halfHeight = this.height / 2 + this.minY; + + // change points to offset polygon into a bounding box + this.points.forEach(function(p) { + p.x -= halfWidth; + p.y -= halfHeight; + }, this); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + points: this.points.concat() + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var points = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.points.length; i < len; i++) { + points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' '); + } + + markup.push( + '\n' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + var point; + ctx.beginPath(); + ctx.moveTo(this.points[0].x, this.points[0].y); + for (var i = 0, len = this.points.length; i < len; i++) { + point = this.points[i]; + ctx.lineTo(point.x, point.y); + } + this._renderFill(ctx); + if (this.stroke || this.strokeDashArray) { + ctx.closePath(); + this._renderStroke(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var p1, p2; + + ctx.beginPath(); + for (var i = 0, len = this.points.length; i < len; i++) { + p1 = this.points[i]; + p2 = this.points[i + 1] || this.points[0]; + fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); + } + ctx.closePath(); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.points.length; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`) + * @static + * @memberOf fabric.Polygon + * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement + */ + fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + + /** + * Returns {@link fabric.Polygon} instance from an SVG element + * @static + * @memberOf fabric.Polygon + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Polygon} Instance of fabric.Polygon + */ + fabric.Polygon.fromElement = function(element, options) { + if (!element) { + return null; + } + + options || (options = { }); + + var points = fabric.parsePointsAttribute(element.getAttribute('points')), + parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES); + + if (points === null) { + return null; + } + + return new fabric.Polygon(points, extend(parsedAttributes, options), true); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Polygon instance from an object representation + * @static + * @memberOf fabric.Polygon + * @param {Object} object Object to create an instance from + * @return {fabric.Polygon} Instance of fabric.Polygon + */ + fabric.Polygon.fromObject = function(object) { + return new fabric.Polygon(object.points, object, true); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + min = fabric.util.array.min, + max = fabric.util.array.max, + extend = fabric.util.object.extend, + _toString = Object.prototype.toString, + drawArc = fabric.util.drawArc, + commandLengths = { + m: 2, + l: 2, + h: 1, + v: 1, + c: 6, + s: 4, + q: 4, + t: 2, + a: 7 + }, + repeatedCommands = { + m: 'l', + M: 'L' + }; + + if (fabric.Path) { + fabric.warn('fabric.Path is already defined'); + return; + } + + /** + * @private + */ + function getX(item) { + if (item[0] === 'H') { + return item[1]; + } + return item[item.length - 2]; + } + + /** + * @private + */ + function getY(item) { + if (item[0] === 'V') { + return item[1]; + } + return item[item.length - 1]; + } + + /** + * Path class + * @class fabric.Path + * @extends fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup} + * @see {@link fabric.Path#initialize} for constructor definition + */ + fabric.Path = fabric.util.createClass(fabric.Object, /** @lends fabric.Path.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'path', + + /** + * Array of path points + * @type Array + * @default + */ + path: null, + + /** + * Constructor + * @param {Array|String} path Path data (sequence of coordinates and corresponding "command" tokens) + * @param {Object} [options] Options object + * @return {fabric.Path} thisArg + */ + initialize: function(path, options) { + options = options || { }; + + this.setOptions(options); + + if (!path) { + throw new Error('`path` argument is required'); + } + + var fromArray = _toString.call(path) === '[object Array]'; + + this.path = fromArray + ? path + // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values) + : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi); + + if (!this.path) { + return; + } + + if (!fromArray) { + this.path = this._parsePath(); + } + this._initializePath(options); + + if (options.sourcePath) { + this.setSourcePath(options.sourcePath); + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initializePath: function (options) { + var isWidthSet = 'width' in options && options.width != null, + isHeightSet = 'height' in options && options.width != null, + isLeftSet = 'left' in options, + isTopSet = 'top' in options, + origLeft = isLeftSet ? this.left : 0, + origTop = isTopSet ? this.top : 0; + + if (!isWidthSet || !isHeightSet) { + extend(this, this._parseDimensions()); + if (isWidthSet) { + this.width = options.width; + } + if (isHeightSet) { + this.height = options.height; + } + } + else { //Set center location relative to given height/width if not specified + if (!isTopSet) { + this.top = this.height / 2; + } + if (!isLeftSet) { + this.left = this.width / 2; + } + } + this.pathOffset = this.pathOffset || + // Save top-left coords as offset + this._calculatePathOffset(origLeft, origTop); + }, + + /** + * @private + * @param {Number} origLeft Original left position + * @param {Number} origTop Original top position + */ + _calculatePathOffset: function (origLeft, origTop) { + return { + x: this.left - origLeft - (this.width / 2), + y: this.top - origTop - (this.height / 2) + }; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx context to render path on + */ + _render: function(ctx, noTransform) { + var current, // current instruction + previous = null, + subpathStartX = 0, + subpathStartY = 0, + x = 0, // current x + y = 0, // current y + controlX = 0, // current control point x + controlY = 0, // current control point y + tempX, + tempY, + tempControlX, + tempControlY, + l = -((this.width / 2) + this.pathOffset.x), + t = -((this.height / 2) + this.pathOffset.y); + + if (noTransform) { + l += this.width / 2; + t += this.height / 2; + } + + for (var i = 0, len = this.path.length; i < len; ++i) { + + current = this.path[i]; + + switch (current[0]) { // first letter + + case 'l': // lineto, relative + x += current[1]; + y += current[2]; + ctx.lineTo(x + l, y + t); + break; + + case 'L': // lineto, absolute + x = current[1]; + y = current[2]; + ctx.lineTo(x + l, y + t); + break; + + case 'h': // horizontal lineto, relative + x += current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'H': // horizontal lineto, absolute + x = current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'v': // vertical lineto, relative + y += current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'V': // verical lineto, absolute + y = current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'm': // moveTo, relative + x += current[1]; + y += current[2]; + subpathStartX = x; + subpathStartY = y; + ctx.moveTo(x + l, y + t); + break; + + case 'M': // moveTo, absolute + x = current[1]; + y = current[2]; + subpathStartX = x; + subpathStartY = y; + ctx.moveTo(x + l, y + t); + break; + + case 'c': // bezierCurveTo, relative + tempX = x + current[5]; + tempY = y + current[6]; + controlX = x + current[3]; + controlY = y + current[4]; + ctx.bezierCurveTo( + x + current[1] + l, // x1 + y + current[2] + t, // y1 + controlX + l, // x2 + controlY + t, // y2 + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'C': // bezierCurveTo, absolute + x = current[5]; + y = current[6]; + controlX = current[3]; + controlY = current[4]; + ctx.bezierCurveTo( + current[1] + l, + current[2] + t, + controlX + l, + controlY + t, + x + l, + y + t + ); + break; + + case 's': // shorthand cubic bezierCurveTo, relative + + // transform to absolute x,y + tempX = x + current[3]; + tempY = y + current[4]; + + // calculate reflection of previous control points + controlX = controlX ? (2 * x - controlX) : x; + controlY = controlY ? (2 * y - controlY) : y; + + ctx.bezierCurveTo( + controlX + l, + controlY + t, + x + current[1] + l, + y + current[2] + t, + tempX + l, + tempY + t + ); + // set control point to 2nd one of this command + // "... the first control point is assumed to be + // the reflection of the second control point on + // the previous command relative to the current point." + controlX = x + current[1]; + controlY = y + current[2]; + + x = tempX; + y = tempY; + break; + + case 'S': // shorthand cubic bezierCurveTo, absolute + tempX = current[3]; + tempY = current[4]; + // calculate reflection of previous control points + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + ctx.bezierCurveTo( + controlX + l, + controlY + t, + current[1] + l, + current[2] + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + + // set control point to 2nd one of this command + // "... the first control point is assumed to be + // the reflection of the second control point on + // the previous command relative to the current point." + controlX = current[1]; + controlY = current[2]; + + break; + + case 'q': // quadraticCurveTo, relative + // transform to absolute x,y + tempX = x + current[3]; + tempY = y + current[4]; + + controlX = x + current[1]; + controlY = y + current[2]; + + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'Q': // quadraticCurveTo, absolute + tempX = current[3]; + tempY = current[4]; + + ctx.quadraticCurveTo( + current[1] + l, + current[2] + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + controlX = current[1]; + controlY = current[2]; + break; + + case 't': // shorthand quadraticCurveTo, relative + + // transform to absolute x,y + tempX = x + current[1]; + tempY = y + current[2]; + + if (previous[0].match(/[QqTt]/) === null) { + // If there is no previous command or if the previous command was not a Q, q, T or t, + // assume the control point is coincident with the current point + controlX = x; + controlY = y; + } + else if (previous[0] === 't') { + // calculate reflection of previous control points for t + controlX = 2 * x - tempControlX; + controlY = 2 * y - tempControlY; + } + else if (previous[0] === 'q') { + // calculate reflection of previous control points for q + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + + tempControlX = controlX; + tempControlY = controlY; + + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + controlX = x + current[1]; + controlY = y + current[2]; + break; + + case 'T': + tempX = current[1]; + tempY = current[2]; + + // calculate reflection of previous control points + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'a': + // TODO: optimize this + drawArc(ctx, x + l, y + t, [ + current[1], + current[2], + current[3], + current[4], + current[5], + current[6] + x + l, + current[7] + y + t + ]); + x += current[6]; + y += current[7]; + break; + + case 'A': + // TODO: optimize this + drawArc(ctx, x + l, y + t, [ + current[1], + current[2], + current[3], + current[4], + current[5], + current[6] + l, + current[7] + t + ]); + x = current[6]; + y = current[7]; + break; + + case 'z': + case 'Z': + x = subpathStartX; + y = subpathStartY; + ctx.closePath(); + break; + } + previous = current; + } + }, + + /** + * Renders path on a specified context + * @param {CanvasRenderingContext2D} ctx context to render path on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if object is not visible + if (!this.visible) { + return; + } + + ctx.save(); + if (noTransform) { + ctx.translate(-this.width/2, -this.height/2); + } + var m = this.transformMatrix; + + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + if (!noTransform) { + this.transform(ctx); + } + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + ctx.beginPath(); + ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; + this._render(ctx, noTransform); + this._renderFill(ctx); + this._renderStroke(ctx); + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * Returns string representation of an instance + * @return {String} string representation of an instance + */ + toString: function() { + return '#'; + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var o = extend(this.callSuper('toObject', propertiesToInclude), { + path: this.path.map(function(item) { return item.slice() }), + pathOffset: this.pathOffset + }); + if (this.sourcePath) { + o.sourcePath = this.sourcePath; + } + if (this.transformMatrix) { + o.transformMatrix = this.transformMatrix; + } + return o; + }, + + /** + * Returns dataless object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + var o = this.toObject(propertiesToInclude); + if (this.sourcePath) { + o.path = this.sourcePath; + } + delete o.sourcePath; + return o; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var chunks = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.path.length; i < len; i++) { + chunks.push(this.path[i].join(' ')); + } + var path = chunks.join(' '); + + markup.push( + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns number representation of an instance complexity + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.path.length; + }, + + /** + * @private + */ + _parsePath: function() { + var result = [ ], + coords = [ ], + currentPath, + parsed, + re = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/ig, + match, + coordsStr; + + for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) { + currentPath = this.path[i]; + + coordsStr = currentPath.slice(1).trim(); + coords.length = 0; + + while ((match = re.exec(coordsStr))) { + coords.push(match[0]); + } + + coordsParsed = [ currentPath.charAt(0) ]; + + for (var j = 0, jlen = coords.length; j < jlen; j++) { + parsed = parseFloat(coords[j]); + if (!isNaN(parsed)) { + coordsParsed.push(parsed); + } + } + + var command = coordsParsed[0], + commandLength = commandLengths[command.toLowerCase()], + repeatedCommand = repeatedCommands[command] || command; + + if (coordsParsed.length - 1 > commandLength) { + for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) { + result.push([ command ].concat(coordsParsed.slice(k, k + commandLength))); + command = repeatedCommand; + } + } + else { + result.push(coordsParsed); + } + } + + return result; + }, + + /** + * @private + */ + _parseDimensions: function() { + var aX = [], + aY = [], + previous = { }; + + this.path.forEach(function(item, i) { + this._getCoordsFromCommand(item, i, aX, aY, previous); + }, this); + + var minX = min(aX), + minY = min(aY), + maxX = max(aX), + maxY = max(aY), + deltaX = maxX - minX, + deltaY = maxY - minY, + + o = { + left: this.left + (minX + deltaX / 2), + top: this.top + (minY + deltaY / 2), + width: deltaX, + height: deltaY + }; + + return o; + }, + + _getCoordsFromCommand: function(item, i, aX, aY, previous) { + var isLowerCase = false; + + if (item[0] !== 'H') { + previous.x = (i === 0) ? getX(item) : getX(this.path[i - 1]); + } + if (item[0] !== 'V') { + previous.y = (i === 0) ? getY(item) : getY(this.path[i - 1]); + } + + // lowercased letter denotes relative position; + // transform to absolute + if (item[0] === item[0].toLowerCase()) { + isLowerCase = true; + } + + var xy = this._getXY(item, isLowerCase, previous), + val; + + val = parseInt(xy.x, 10); + if (!isNaN(val)) { + aX.push(val); + } + + val = parseInt(xy.y, 10); + if (!isNaN(val)) { + aY.push(val); + } + }, + + _getXY: function(item, isLowerCase, previous) { + + // last 2 items in an array of coordinates are the actualy x/y (except H/V), collect them + // TODO (kangax): support relative h/v commands + + var x = isLowerCase + ? previous.x + getX(item) + : item[0] === 'V' + ? previous.x + : getX(item), + + y = isLowerCase + ? previous.y + getY(item) + : item[0] === 'H' + ? previous.y + : getY(item); + + return { x: x, y: y }; + } + }); + + /** + * Creates an instance of fabric.Path from an object + * @static + * @memberOf fabric.Path + * @param {Object} object + * @param {Function} callback Callback to invoke when an fabric.Path instance is created + */ + fabric.Path.fromObject = function(object, callback) { + if (typeof object.path === 'string') { + fabric.loadSVGFromURL(object.path, function (elements) { + var path = elements[0], + pathUrl = object.path; + + delete object.path; + + fabric.util.object.extend(path, object); + path.setSourcePath(pathUrl); + + callback(path); + }); + } + else { + callback(new fabric.Path(object.path, object)); + } + }; + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Path.fromElement`) + * @static + * @memberOf fabric.Path + * @see http://www.w3.org/TR/SVG/paths.html#PathElement + */ + fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(['d']); + + /** + * Creates an instance of fabric.Path from an SVG element + * @static + * @memberOf fabric.Path + * @param {SVGElement} element to parse + * @param {Function} callback Callback to invoke when an fabric.Path instance is created + * @param {Object} [options] Options object + */ + fabric.Path.fromElement = function(element, callback, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES); + callback && callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options))); + }; + /* _FROM_SVG_END_ */ + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.Path + * @type Boolean + * @default + */ + fabric.Path.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + invoke = fabric.util.array.invoke, + parentToObject = fabric.Object.prototype.toObject; + + if (fabric.PathGroup) { + fabric.warn('fabric.PathGroup is already defined'); + return; + } + + /** + * Path group class + * @class fabric.PathGroup + * @extends fabric.Path + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup} + * @see {@link fabric.PathGroup#initialize} for constructor definition + */ + fabric.PathGroup = fabric.util.createClass(fabric.Path, /** @lends fabric.PathGroup.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'path-group', + + /** + * Fill value + * @type String + * @default + */ + fill: '', + + /** + * Constructor + * @param {Array} paths + * @param {Object} [options] Options object + * @return {fabric.PathGroup} thisArg + */ + initialize: function(paths, options) { + + options = options || { }; + this.paths = paths || [ ]; + + for (var i = this.paths.length; i--; ) { + this.paths[i].group = this; + } + + this.setOptions(options); + + if (options.widthAttr) { + this.scaleX = options.widthAttr / options.width; + } + if (options.heightAttr) { + this.scaleY = options.heightAttr / options.height; + } + + this.setCoords(); + + if (options.sourcePath) { + this.setSourcePath(options.sourcePath); + } + }, + + /** + * Renders this group on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render this instance on + */ + render: function(ctx) { + // do not render if object is not visible + if (!this.visible) { + return; + } + + ctx.save(); + + var m = this.transformMatrix; + + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + this.transform(ctx); + + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + for (var i = 0, l = this.paths.length; i < l; ++i) { + this.paths[i].render(ctx, true); + } + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * Sets certain property to a certain value + * @param {String} prop + * @param {Any} value + * @return {fabric.PathGroup} thisArg + */ + _set: function(prop, value) { + + if (prop === 'fill' && value && this.isSameColor()) { + var i = this.paths.length; + while (i--) { + this.paths[i]._set(prop, value); + } + } + + return this.callSuper('_set', prop, value); + }, + + /** + * Returns object representation of this path group + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var o = extend(parentToObject.call(this, propertiesToInclude), { + paths: invoke(this.getObjects(), 'toObject', propertiesToInclude) + }); + if (this.sourcePath) { + o.sourcePath = this.sourcePath; + } + return o; + }, + + /** + * Returns dataless object representation of this path group + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} dataless object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + var o = this.toObject(propertiesToInclude); + if (this.sourcePath) { + o.paths = this.sourcePath; + } + return o; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var objects = this.getObjects(), + translatePart = 'translate(' + this.left + ' ' + this.top + ')', + markup = [ + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ]; + + for (var i = 0, len = objects.length; i < len; i++) { + markup.push(objects[i].toSVG(reviver)); + } + markup.push('\n'); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns a string representation of this path group + * @return {String} string representation of an object + */ + toString: function() { + return '#'; + }, + + /** + * Returns true if all paths in this group are of same color + * @return {Boolean} true if all paths are of the same color (`fill`) + */ + isSameColor: function() { + var firstPathFill = (this.getObjects()[0].get('fill') || '').toLowerCase(); + return this.getObjects().every(function(path) { + return (path.get('fill') || '').toLowerCase() === firstPathFill; + }); + }, + + /** + * Returns number representation of object's complexity + * @return {Number} complexity + */ + complexity: function() { + return this.paths.reduce(function(total, path) { + return total + ((path && path.complexity) ? path.complexity() : 0); + }, 0); + }, + + /** + * Returns all paths in this path group + * @return {Array} array of path objects included in this path group + */ + getObjects: function() { + return this.paths; + } + }); + + /** + * Creates fabric.PathGroup instance from an object representation + * @static + * @memberOf fabric.PathGroup + * @param {Object} object Object to create an instance from + * @param {Function} callback Callback to invoke when an fabric.PathGroup instance is created + */ + fabric.PathGroup.fromObject = function(object, callback) { + if (typeof object.paths === 'string') { + fabric.loadSVGFromURL(object.paths, function (elements) { + + var pathUrl = object.paths; + delete object.paths; + + var pathGroup = fabric.util.groupSVGElements(elements, object, pathUrl); + + callback(pathGroup); + }); + } + else { + fabric.util.enlivenObjects(object.paths, function(enlivenedObjects) { + delete object.paths; + callback(new fabric.PathGroup(enlivenedObjects, object)); + }); + } + }; + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.PathGroup + * @type Boolean + * @default + */ + fabric.PathGroup.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global){ + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + min = fabric.util.array.min, + max = fabric.util.array.max, + invoke = fabric.util.array.invoke; + + if (fabric.Group) { + return; + } + + // lock-related properties, for use in fabric.Group#get + // to enable locking behavior on group + // when one of its objects has lock-related properties set + var _lockProperties = { + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + lockUniScaling: true + }; + + /** + * Group class + * @class fabric.Group + * @extends fabric.Object + * @mixes fabric.Collection + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#groups} + * @see {@link fabric.Group#initialize} for constructor definition + */ + fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, /** @lends fabric.Group.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'group', + + /** + * Constructor + * @param {Object} objects Group objects + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(objects, options) { + options = options || { }; + + this._objects = objects || []; + for (var i = this._objects.length; i--; ) { + this._objects[i].group = this; + } + + this.originalState = { }; + this.callSuper('initialize'); + + this._calcBounds(); + this._updateObjectsCoords(); + + if (options) { + extend(this, options); + } + this._setOpacityIfSame(); + + this.setCoords(); + this.saveCoords(); + }, + + /** + * @private + */ + _updateObjectsCoords: function() { + this.forEachObject(this._updateObjectCoords, this); + }, + + /** + * @private + */ + _updateObjectCoords: function(object) { + var objectLeft = object.getLeft(), + objectTop = object.getTop(); + + object.set({ + originalLeft: objectLeft, + originalTop: objectTop, + left: objectLeft - this.left, + top: objectTop - this.top + }); + + object.setCoords(); + + // do not display corners of objects enclosed in a group + object.__origHasControls = object.hasControls; + object.hasControls = false; + }, + + /** + * Returns string represenation of a group + * @return {String} + */ + toString: function() { + return '#'; + }, + + /** + * Adds an object to a group; Then recalculates group's dimension, position. + * @param {Object} object + * @return {fabric.Group} thisArg + * @chainable + */ + addWithUpdate: function(object) { + this._restoreObjectsState(); + if (object) { + this._objects.push(object); + object.group = this; + } + // since _restoreObjectsState set objects inactive + this.forEachObject(this._setObjectActive, this); + this._calcBounds(); + this._updateObjectsCoords(); + return this; + }, + + /** + * @private + */ + _setObjectActive: function(object) { + object.set('active', true); + object.group = this; + }, + + /** + * Removes an object from a group; Then recalculates group's dimension, position. + * @param {Object} object + * @return {fabric.Group} thisArg + * @chainable + */ + removeWithUpdate: function(object) { + this._moveFlippedObject(object); + this._restoreObjectsState(); + + // since _restoreObjectsState set objects inactive + this.forEachObject(this._setObjectActive, this); + + this.remove(object); + this._calcBounds(); + this._updateObjectsCoords(); + + return this; + }, + + /** + * @private + */ + _onObjectAdded: function(object) { + object.group = this; + }, + + /** + * @private + */ + _onObjectRemoved: function(object) { + delete object.group; + object.set('active', false); + }, + + /** + * Properties that are delegated to group objects when reading/writing + * @param {Object} delegatedProperties + */ + delegatedProperties: { + fill: true, + opacity: true, + fontFamily: true, + fontWeight: true, + fontSize: true, + fontStyle: true, + lineHeight: true, + textDecoration: true, + textAlign: true, + backgroundColor: true + }, + + /** + * @private + */ + _set: function(key, value) { + if (key in this.delegatedProperties) { + var i = this._objects.length; + this[key] = value; + while (i--) { + this._objects[i].set(key, value); + } + } + else { + this[key] = value; + } + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + objects: invoke(this._objects, 'toObject', propertiesToInclude) + }); + }, + + /** + * Renders instance on a given context + * @param {CanvasRenderingContext2D} ctx context to render instance on + */ + render: function(ctx) { + // do not render if object is not visible + if (!this.visible) { + return; + } + + ctx.save(); + this.clipTo && fabric.util.clipContext(this, ctx); + + // the array is now sorted in order of highest first, so start from end + for (var i = 0, len = this._objects.length; i < len; i++) { + this._renderObject(this._objects[i], ctx); + } + + this.clipTo && ctx.restore(); + + ctx.restore(); + }, + + /** + * Renders controls and borders for the object + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + _renderControls: function(ctx, noTransform) { + this.callSuper('_renderControls', ctx, noTransform); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i]._renderControls(ctx); + } + }, + + /** + * @private + */ + _renderObject: function(object, ctx) { + var originalHasRotatingPoint = object.hasRotatingPoint; + + // do not render if object is not visible + if (!object.visible) { + return; + } + + object.hasRotatingPoint = false; + + object.render(ctx); + + object.hasRotatingPoint = originalHasRotatingPoint; + }, + + /** + * Retores original state of each of group objects (original state is that which was before group was created). + * @private + * @return {fabric.Group} thisArg + * @chainable + */ + _restoreObjectsState: function() { + this._objects.forEach(this._restoreObjectState, this); + return this; + }, + + /** + * Moves a flipped object to the position where it's displayed + * @private + * @param {fabric.Object} object + * @return {fabric.Group} thisArg + */ + _moveFlippedObject: function(object) { + var oldOriginX = object.get('originX'), + oldOriginY = object.get('originY'), + center = object.getCenterPoint(); + + object.set({ + originX: 'center', + originY: 'center', + left: center.x, + top: center.y + }); + + this._toggleFlipping(object); + + var newOrigin = object.getPointByOrigin(oldOriginX, oldOriginY); + + object.set({ + originX: oldOriginX, + originY: oldOriginY, + left: newOrigin.x, + top: newOrigin.y + }); + + return this; + }, + + /** + * @private + */ + _toggleFlipping: function(object) { + if (this.flipX) { + object.toggle('flipX'); + object.set('left', -object.get('left')); + object.setAngle(-object.getAngle()); + } + if (this.flipY) { + object.toggle('flipY'); + object.set('top', -object.get('top')); + object.setAngle(-object.getAngle()); + } + }, + + /** + * Restores original state of a specified object in group + * @private + * @param {fabric.Object} object + * @return {fabric.Group} thisArg + */ + _restoreObjectState: function(object) { + this._setObjectPosition(object); + + object.setCoords(); + object.hasControls = object.__origHasControls; + delete object.__origHasControls; + object.set('active', false); + object.setCoords(); + delete object.group; + + return this; + }, + + /** + * @private + */ + _setObjectPosition: function(object) { + var groupLeft = this.getLeft(), + groupTop = this.getTop(), + rotated = this._getRotatedLeftTop(object); + + object.set({ + angle: object.getAngle() + this.getAngle(), + left: groupLeft + rotated.left, + top: groupTop + rotated.top, + scaleX: object.get('scaleX') * this.get('scaleX'), + scaleY: object.get('scaleY') * this.get('scaleY') + }); + }, + + /** + * @private + */ + _getRotatedLeftTop: function(object) { + var groupAngle = this.getAngle() * (Math.PI / 180); + return { + left: (-Math.sin(groupAngle) * object.getTop() * this.get('scaleY') + + Math.cos(groupAngle) * object.getLeft() * this.get('scaleX')), + + top: (Math.cos(groupAngle) * object.getTop() * this.get('scaleY') + + Math.sin(groupAngle) * object.getLeft() * this.get('scaleX')) + }; + }, + + /** + * Destroys a group (restoring state of its objects) + * @return {fabric.Group} thisArg + * @chainable + */ + destroy: function() { + this._objects.forEach(this._moveFlippedObject, this); + return this._restoreObjectsState(); + }, + + /** + * Saves coordinates of this instance (to be used together with `hasMoved`) + * @saveCoords + * @return {fabric.Group} thisArg + * @chainable + */ + saveCoords: function() { + this._originalLeft = this.get('left'); + this._originalTop = this.get('top'); + return this; + }, + + /** + * Checks whether this group was moved (since `saveCoords` was called last) + * @return {Boolean} true if an object was moved (since fabric.Group#saveCoords was called) + */ + hasMoved: function() { + return this._originalLeft !== this.get('left') || + this._originalTop !== this.get('top'); + }, + + /** + * Sets coordinates of all group objects + * @return {fabric.Group} thisArg + * @chainable + */ + setObjectsCoords: function() { + this.forEachObject(function(object) { + object.setCoords(); + }); + return this; + }, + + /** + * @private + */ + _setOpacityIfSame: function() { + var objects = this.getObjects(), + firstValue = objects[0] ? objects[0].get('opacity') : 1, + isSameOpacity = objects.every(function(o) { + return o.get('opacity') === firstValue; + }); + + if (isSameOpacity) { + this.opacity = firstValue; + } + }, + + /** + * @private + */ + _calcBounds: function(onlyWidthHeight) { + var aX = [], + aY = [], + o; + + for (var i = 0, len = this._objects.length; i < len; ++i) { + o = this._objects[i]; + o.setCoords(); + for (var prop in o.oCoords) { + aX.push(o.oCoords[prop].x); + aY.push(o.oCoords[prop].y); + } + } + + this.set(this._getBounds(aX, aY, onlyWidthHeight)); + }, + + /** + * @private + */ + _getBounds: function(aX, aY, onlyWidthHeight) { + var ivt = fabric.util.invertTransform(this.getViewportTransform()), + minXY = fabric.util.transformPoint(new fabric.Point(min(aX), min(aY)), ivt), + maxXY = fabric.util.transformPoint(new fabric.Point(max(aX), max(aY)), ivt), + obj = { + width: (maxXY.x - minXY.x) || 0, + height: (maxXY.y - minXY.y) || 0 + }; + + if (!onlyWidthHeight) { + obj.left = (minXY.x + maxXY.x) / 2 || 0; + obj.top = (minXY.y + maxXY.y) / 2 || 0; + } + return obj; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = [ + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ]; + + for (var i = 0, len = this._objects.length; i < len; i++) { + markup.push(this._objects[i].toSVG(reviver)); + } + + markup.push('\n'); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns requested property + * @param {String} prop Property to get + * @return {Any} + */ + get: function(prop) { + if (prop in _lockProperties) { + if (this[prop]) { + return this[prop]; + } + else { + for (var i = 0, len = this._objects.length; i < len; i++) { + if (this._objects[i][prop]) { + return true; + } + } + return false; + } + } + else { + if (prop in this.delegatedProperties) { + return this._objects[0] && this._objects[0].get(prop); + } + return this[prop]; + } + } + }); + + /** + * Returns {@link fabric.Group} instance from an object representation + * @static + * @memberOf fabric.Group + * @param {Object} object Object to create a group from + * @param {Function} [callback] Callback to invoke when an group instance is created + * @return {fabric.Group} An instance of fabric.Group + */ + fabric.Group.fromObject = function(object, callback) { + fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) { + delete object.objects; + callback && callback(new fabric.Group(enlivenedObjects, object)); + }); + }; + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.Group + * @type Boolean + * @default + */ + fabric.Group.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var extend = fabric.util.object.extend; + + if (!global.fabric) { + global.fabric = { }; + } + + if (global.fabric.Image) { + fabric.warn('fabric.Image is already defined.'); + return; + } + + /** + * Image class + * @class fabric.Image + * @extends fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#images} + * @see {@link fabric.Image#initialize} for constructor definition + */ + fabric.Image = fabric.util.createClass(fabric.Object, /** @lends fabric.Image.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'image', + + /** + * crossOrigin value (one of "", "anonymous", "allow-credentials") + * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes + * @type String + * @default + */ + crossOrigin: '', + + /** + * Constructor + * @param {HTMLImageElement | String} element Image element + * @param {Object} [options] Options object + * @return {fabric.Image} thisArg + */ + initialize: function(element, options) { + options || (options = { }); + + this.filters = [ ]; + + this.callSuper('initialize', options); + + this._initElement(element, options); + this._initConfig(options); + + if (options.filters) { + this.filters = options.filters; + this.applyFilters(); + } + }, + + /** + * Returns image element which this instance if based on + * @return {HTMLImageElement} Image element + */ + getElement: function() { + return this._element; + }, + + /** + * Sets image element for this instance to a specified one. + * If filters defined they are applied to new image. + * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area. + * @param {HTMLImageElement} element + * @param {Function} [callback] Callback is invoked when all filters have been applied and new image is generated + * @return {fabric.Image} thisArg + * @chainable + */ + setElement: function(element, callback) { + this._element = element; + this._originalElement = element; + this._initConfig(); + + if (this.filters.length !== 0) { + this.applyFilters(callback); + } + + return this; + }, + + /** + * Sets crossOrigin value (on an instance and corresponding image element) + * @return {fabric.Image} thisArg + * @chainable + */ + setCrossOrigin: function(value) { + this.crossOrigin = value; + this._element.crossOrigin = value; + + return this; + }, + + /** + * Returns original size of an image + * @return {Object} Object with "width" and "height" properties + */ + getOriginalSize: function() { + var element = this.getElement(); + return { + width: element.width, + height: element.height + }; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _stroke: function(ctx) { + ctx.save(); + this._setStrokeStyles(ctx); + ctx.beginPath(); + ctx.strokeRect(-this.width / 2, -this.height / 2, this.width, this.height); + ctx.closePath(); + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var x = -this.width / 2, + y = -this.height / 2, + w = this.width, + h = this.height; + + ctx.save(); + this._setStrokeStyles(ctx); + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray); + ctx.closePath(); + ctx.restore(); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + src: this._originalElement.src || this._originalElement._src, + filters: this.filters.map(function(filterObj) { + return filterObj && filterObj.toObject(); + }), + crossOrigin: this.crossOrigin + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = [], x = -this.width / 2, y = -this.height / 2; + if (this.group) { + x = this.left; + y = this.top; + } + markup.push( + '\n', + '\n' + ); + + if (this.stroke || this.strokeDashArray) { + var origFill = this.fill; + this.fill = null; + markup.push( + '\n' + ); + this.fill = origFill; + } + + markup.push('\n'); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns source of an image + * @return {String} Source of an image + */ + getSrc: function() { + if (this.getElement()) { + return this.getElement().src || this.getElement()._src; + } + }, + + /** + * Returns string representation of an instance + * @return {String} String representation of an instance + */ + toString: function() { + return '#'; + }, + + /** + * Returns a clone of an instance + * @param {Function} callback Callback is invoked with a clone as a first argument + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + */ + clone: function(callback, propertiesToInclude) { + this.constructor.fromObject(this.toObject(propertiesToInclude), callback); + }, + + /** + * Applies filters assigned to this image (from "filters" array) + * @mthod applyFilters + * @param {Function} callback Callback is invoked when all filters have been applied and new image is generated + * @return {fabric.Image} thisArg + * @chainable + */ + applyFilters: function(callback) { + + if (!this._originalElement) { + return; + } + + if (this.filters.length === 0) { + this._element = this._originalElement; + callback && callback(); + return; + } + + var imgEl = this._originalElement, + canvasEl = fabric.util.createCanvasElement(), + replacement = fabric.util.createImage(), + _this = this; + + canvasEl.width = imgEl.width; + canvasEl.height = imgEl.height; + + canvasEl.getContext('2d').drawImage(imgEl, 0, 0, imgEl.width, imgEl.height); + + this.filters.forEach(function(filter) { + filter && filter.applyTo(canvasEl); + }); + + /** @ignore */ + + replacement.width = imgEl.width; + replacement.height = imgEl.height; + + if (fabric.isLikelyNode) { + replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression); + + // onload doesn't fire in some node versions, so we invoke callback manually + _this._element = replacement; + callback && callback(); + } + else { + replacement.onload = function() { + _this._element = replacement; + callback && callback(); + replacement.onload = canvasEl = imgEl = null; + }; + replacement.src = canvasEl.toDataURL('image/png'); + } + + return this; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx, noTransform) { + this._element && + ctx.drawImage( + this._element, + noTransform ? this.left : -this.width/2, + noTransform ? this.top : -this.height/2, + this.width, + this.height + ); + this._renderStroke(ctx); + }, + + /** + * @private + */ + _resetWidthHeight: function() { + var element = this.getElement(); + + this.set('width', element.width); + this.set('height', element.height); + }, + + /** + * The Image class's initialization method. This method is automatically + * called by the constructor. + * @private + * @param {HTMLImageElement|String} element The element representing the image + */ + _initElement: function(element) { + this.setElement(fabric.util.getById(element)); + fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS); + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initConfig: function(options) { + options || (options = { }); + this.setOptions(options); + this._setWidthHeight(options); + if (this._element && this.crossOrigin) { + this._element.crossOrigin = this.crossOrigin; + } + }, + + /** + * @private + * @param {Object} object Object with filters property + * @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created + */ + _initFilters: function(object, callback) { + if (object.filters && object.filters.length) { + fabric.util.enlivenObjects(object.filters, function(enlivenedObjects) { + callback && callback(enlivenedObjects); + }, 'fabric.Image.filters'); + } + else { + callback && callback(); + } + }, + + /** + * @private + * @param {Object} [options] Object with width/height properties + */ + _setWidthHeight: function(options) { + this.width = 'width' in options + ? options.width + : (this.getElement() + ? this.getElement().width || 0 + : 0); + + this.height = 'height' in options + ? options.height + : (this.getElement() + ? this.getElement().height || 0 + : 0); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /** + * Default CSS class name for canvas + * @static + * @type String + * @default + */ + fabric.Image.CSS_CANVAS = 'canvas-img'; + + /** + * Alias for getSrc + * @static + */ + fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc; + + /** + * Creates an instance of fabric.Image from its object representation + * @static + * @param {Object} object Object to create an instance from + * @param {Function} [callback] Callback to invoke when an image instance is created + */ + fabric.Image.fromObject = function(object, callback) { + fabric.util.loadImage(object.src, function(img) { + fabric.Image.prototype._initFilters.call(object, object, function(filters) { + object.filters = filters || [ ]; + var instance = new fabric.Image(img, object); + callback && callback(instance); + }); + }, null, object.crossOrigin); + }; + + /** + * Creates an instance of fabric.Image from an URL string + * @static + * @param {String} url URL to create an image from + * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument) + * @param {Object} [imgOptions] Options object + */ + fabric.Image.fromURL = function(url, callback, imgOptions) { + fabric.util.loadImage(url, function(img) { + callback(new fabric.Image(img, imgOptions)); + }, null, imgOptions && imgOptions.crossOrigin); + }; + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement}) + * @static + * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement} + */ + fabric.Image.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y width height xlink:href'.split(' ')); + + /** + * Returns {@link fabric.Image} instance from an SVG element + * @static + * @param {SVGElement} element Element to parse + * @param {Function} callback Callback to execute when fabric.Image object is created + * @param {Object} [options] Options object + * @return {fabric.Image} Instance of fabric.Image + */ + fabric.Image.fromElement = function(element, callback, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES); + + fabric.Image.fromURL(parsedAttributes['xlink:href'], callback, + extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + }; + /* _FROM_SVG_END_ */ + + /** + * Indicates that instances of this type are async + * @static + * @type Boolean + * @default + */ + fabric.Image.async = true; + + /** + * Indicates compression level used when generating PNG under Node (in applyFilters). Any of 0-9 + * @static + * @type Number + * @default + */ + fabric.Image.pngCompression = 1; + +})(typeof exports !== 'undefined' ? exports : this); + + +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * @private + * @return {Number} angle value + */ + _getAngleValueForStraighten: function() { + var angle = this.getAngle() % 360; + if (angle > 0) { + return Math.round((angle - 1) / 90) * 90; + } + return Math.round(angle / 90) * 90; + }, + + /** + * Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer) + * @return {fabric.Object} thisArg + * @chainable + */ + straighten: function() { + this.setAngle(this._getAngleValueForStraighten()); + return this; + }, + + /** + * Same as {@link fabric.Object.prototype.straighten} but with animation + * @param {Object} callbacks Object with callback functions + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Object} thisArg + * @chainable + */ + fxStraighten: function(callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: this.get('angle'), + endValue: this._getAngleValueForStraighten(), + duration: this.FX_DURATION, + onChange: function(value) { + _this.setAngle(value); + onChange(); + }, + onComplete: function() { + _this.setCoords(); + onComplete(); + }, + onStart: function() { + _this.set('active', false); + } + }); + + return this; + } +}); + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Straightens object, then rerenders canvas + * @param {fabric.Object} object Object to straighten + * @return {fabric.Canvas} thisArg + * @chainable + */ + straightenObject: function (object) { + object.straighten(); + this.renderAll(); + return this; + }, + + /** + * Same as {@link fabric.Canvas.prototype.straightenObject}, but animated + * @param {fabric.Object} object Object to straighten + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxStraightenObject: function (object) { + object.fxStraighten({ + onChange: this.renderAll.bind(this) + }); + return this; + } +}); + + +/** + * @namespace fabric.Image.filters + * @memberOf fabric.Image + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#image_filters} + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + */ +fabric.Image.filters = fabric.Image.filters || { }; + +/** + * Root filter class from which all filter classes inherit from + * @class fabric.Image.filters.BaseFilter + * @memberOf fabric.Image.filters + */ +fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Image.filters.BaseFilter.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'BaseFilter', + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return { type: this.type }; + }, + + /** + * Returns a JSON representation of an instance + * @return {Object} JSON + */ + toJSON: function() { + // delegate, not alias + return this.toObject(); + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Brightness filter class + * @class fabric.Image.filters.Brightness + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Brightness#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Brightness({ + * brightness: 200 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Brightness = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Brightness.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Brightness', + + /** + * Constructor + * @memberOf fabric.Image.filters.Brightness.prototype + * @param {Object} [options] Options object + * @param {Number} [options.brightness=0] Value to brighten the image up (0..255) + */ + initialize: function(options) { + options = options || { }; + this.brightness = options.brightness || 0; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + brightness = this.brightness; + + for (var i = 0, len = data.length; i < len; i += 4) { + data[i] += brightness; + data[i + 1] += brightness; + data[i + 2] += brightness; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + brightness: this.brightness + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Brightness} Instance of fabric.Image.filters.Brightness + */ + fabric.Image.filters.Brightness.fromObject = function(object) { + return new fabric.Image.filters.Brightness(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Adapted from html5rocks article + * @class fabric.Image.filters.Convolute + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Convolute#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example Sharpen filter + * var filter = new fabric.Image.filters.Convolute({ + * matrix: [ 0, -1, 0, + * -1, 5, -1, + * 0, -1, 0 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example Blur filter + * var filter = new fabric.Image.filters.Convolute({ + * matrix: [ 1/9, 1/9, 1/9, + * 1/9, 1/9, 1/9, + * 1/9, 1/9, 1/9 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example Emboss filter + * var filter = new fabric.Image.filters.Convolute({ + * matrix: [ 1, 1, 1, + * 1, 0.7, -1, + * -1, -1, -1 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example Emboss filter with opaqueness + * var filter = new fabric.Image.filters.Convolute({ + * opaque: true, + * matrix: [ 1, 1, 1, + * 1, 0.7, -1, + * -1, -1, -1 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Convolute = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Convolute.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Convolute', + + /** + * Constructor + * @memberOf fabric.Image.filters.Convolute.prototype + * @param {Object} [options] Options object + * @param {Boolean} [options.opaque=false] Opaque value (true/false) + * @param {Array} [options.matrix] Filter matrix + */ + initialize: function(options) { + options = options || { }; + + this.opaque = options.opaque; + this.matrix = options.matrix || [ + 0, 0, 0, + 0, 1, 0, + 0, 0, 0 + ]; + + var canvasEl = fabric.util.createCanvasElement(); + this.tmpCtx = canvasEl.getContext('2d'); + }, + + /** + * @private + */ + _createImageData: function(w, h) { + return this.tmpCtx.createImageData(w, h); + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + + var weights = this.matrix, + context = canvasEl.getContext('2d'), + pixels = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + + side = Math.round(Math.sqrt(weights.length)), + halfSide = Math.floor(side/2), + src = pixels.data, + sw = pixels.width, + sh = pixels.height, + + // pad output by the convolution matrix + w = sw, + h = sh, + output = this._createImageData(w, h), + + dst = output.data, + + // go through the destination image pixels + alphaFac = this.opaque ? 1 : 0; + + for (var y = 0; y < h; y++) { + for (var x = 0; x < w; x++) { + var sy = y, + sx = x, + dstOff = (y * w + x) * 4, + // calculate the weighed sum of the source image pixels that + // fall under the convolution matrix + r = 0, g = 0, b = 0, a = 0; + + for (var cy = 0; cy < side; cy++) { + for (var cx = 0; cx < side; cx++) { + + var scy = sy + cy - halfSide, + scx = sx + cx - halfSide; + + /* jshint maxdepth:5 */ + if (scy < 0 || scy > sh || scx < 0 || scx > sw) { + continue; + } + + var srcOff = (scy * sw + scx) * 4, + wt = weights[cy * side + cx]; + + r += src[srcOff] * wt; + g += src[srcOff + 1] * wt; + b += src[srcOff + 2] * wt; + a += src[srcOff + 3] * wt; + } + } + dst[dstOff] = r; + dst[dstOff + 1] = g; + dst[dstOff + 2] = b; + dst[dstOff + 3] = a + alphaFac * (255 - a); + } + } + + context.putImageData(output, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + opaque: this.opaque, + matrix: this.matrix + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Convolute} Instance of fabric.Image.filters.Convolute + */ + fabric.Image.filters.Convolute.fromObject = function(object) { + return new fabric.Image.filters.Convolute(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * GradientTransparency filter class + * @class fabric.Image.filters.GradientTransparency + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.GradientTransparency#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.GradientTransparency({ + * threshold: 200 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.GradientTransparency = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.GradientTransparency.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'GradientTransparency', + + /** + * Constructor + * @memberOf fabric.Image.filters.GradientTransparency.prototype + * @param {Object} [options] Options object + * @param {Number} [options.threshold=100] Threshold value + */ + initialize: function(options) { + options = options || { }; + this.threshold = options.threshold || 100; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + threshold = this.threshold, + total = data.length; + + for (var i = 0, len = data.length; i < len; i += 4) { + data[i + 3] = threshold + 255 * (total - i) / total; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + threshold: this.threshold + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.GradientTransparency} Instance of fabric.Image.filters.GradientTransparency + */ + fabric.Image.filters.GradientTransparency.fromObject = function(object) { + return new fabric.Image.filters.GradientTransparency(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Grayscale image filter class + * @class fabric.Image.filters.Grayscale + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Grayscale(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Grayscale = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Grayscale.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Grayscale', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Grayscale.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + len = imageData.width * imageData.height * 4, + index = 0, + average; + + while (index < len) { + average = (data[index] + data[index + 1] + data[index + 2]) / 3; + data[index] = average; + data[index + 1] = average; + data[index + 2] = average; + index += 4; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale + */ + fabric.Image.filters.Grayscale.fromObject = function() { + return new fabric.Image.filters.Grayscale(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Invert filter class + * @class fabric.Image.filters.Invert + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Invert(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Invert = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Invert.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Invert', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Invert.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i; + + for (i = 0; i < iLen; i+=4) { + data[i] = 255 - data[i]; + data[i + 1] = 255 - data[i + 1]; + data[i + 2] = 255 - data[i + 2]; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Invert} Instance of fabric.Image.filters.Invert + */ + fabric.Image.filters.Invert.fromObject = function() { + return new fabric.Image.filters.Invert(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Mask filter class + * See http://resources.aleph-1.com/mask/ + * @class fabric.Image.filters.Mask + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Mask#initialize} for constructor definition + */ + fabric.Image.filters.Mask = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Mask.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Mask', + + /** + * Constructor + * @memberOf fabric.Image.filters.Mask.prototype + * @param {Object} [options] Options object + * @param {fabric.Image} [options.mask] Mask image object + * @param {Number} [options.channel=0] Rgb channel (0, 1, 2 or 3) + */ + initialize: function(options) { + options = options || { }; + + this.mask = options.mask; + this.channel = [ 0, 1, 2, 3 ].indexOf(options.channel) > -1 ? options.channel : 0; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + if (!this.mask) { + return; + } + + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + maskEl = this.mask.getElement(), + maskCanvasEl = fabric.util.createCanvasElement(), + channel = this.channel, + i, + iLen = imageData.width * imageData.height * 4; + + maskCanvasEl.width = maskEl.width; + maskCanvasEl.height = maskEl.height; + + maskCanvasEl.getContext('2d').drawImage(maskEl, 0, 0, maskEl.width, maskEl.height); + + var maskImageData = maskCanvasEl.getContext('2d').getImageData(0, 0, maskEl.width, maskEl.height), + maskData = maskImageData.data; + + for (i = 0; i < iLen; i += 4) { + data[i + 3] = maskData[i + channel]; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + mask: this.mask.toObject(), + channel: this.channel + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @param {Function} [callback] Callback to invoke when a mask filter instance is created + */ + fabric.Image.filters.Mask.fromObject = function(object, callback) { + fabric.util.loadImage(object.mask.src, function(img) { + object.mask = new fabric.Image(img, object.mask); + callback && callback(new fabric.Image.filters.Mask(object)); + }); + }; + + /** + * Indicates that instances of this type are async + * @static + * @type Boolean + * @default + */ + fabric.Image.filters.Mask.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Noise filter class + * @class fabric.Image.filters.Noise + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Noise#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Noise({ + * noise: 700 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Noise = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Noise.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Noise', + + /** + * Constructor + * @memberOf fabric.Image.filters.Noise.prototype + * @param {Object} [options] Options object + * @param {Number} [options.noise=0] Noise value + */ + initialize: function(options) { + options = options || { }; + this.noise = options.noise || 0; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + noise = this.noise, rand; + + for (var i = 0, len = data.length; i < len; i += 4) { + + rand = (0.5 - Math.random()) * noise; + + data[i] += rand; + data[i + 1] += rand; + data[i + 2] += rand; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + noise: this.noise + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Noise} Instance of fabric.Image.filters.Noise + */ + fabric.Image.filters.Noise.fromObject = function(object) { + return new fabric.Image.filters.Noise(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Pixelate filter class + * @class fabric.Image.filters.Pixelate + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Pixelate#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Pixelate({ + * blocksize: 8 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Pixelate = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Pixelate.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Pixelate', + + /** + * Constructor + * @memberOf fabric.Image.filters.Pixelate.prototype + * @param {Object} [options] Options object + * @param {Number} [options.blocksize=4] Blocksize for pixelate + */ + initialize: function(options) { + options = options || { }; + this.blocksize = options.blocksize || 4; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = imageData.height, + jLen = imageData.width, + index, i, j, r, g, b, a; + + for (i = 0; i < iLen; i += this.blocksize) { + for (j = 0; j < jLen; j += this.blocksize) { + + index = (i * 4) * jLen + (j * 4); + + r = data[index]; + g = data[index + 1]; + b = data[index + 2]; + a = data[index + 3]; + + /* + blocksize: 4 + + [1,x,x,x,1] + [x,x,x,x,1] + [x,x,x,x,1] + [x,x,x,x,1] + [1,1,1,1,1] + */ + + for (var _i = i, _ilen = i + this.blocksize; _i < _ilen; _i++) { + for (var _j = j, _jlen = j + this.blocksize; _j < _jlen; _j++) { + index = (_i * 4) * jLen + (_j * 4); + data[index] = r; + data[index + 1] = g; + data[index + 2] = b; + data[index + 3] = a; + } + } + } + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + blocksize: this.blocksize + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Pixelate} Instance of fabric.Image.filters.Pixelate + */ + fabric.Image.filters.Pixelate.fromObject = function(object) { + return new fabric.Image.filters.Pixelate(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Remove white filter class + * @class fabric.Image.filters.RemoveWhite + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.RemoveWhite#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.RemoveWhite({ + * threshold: 40, + * distance: 140 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.RemoveWhite = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.RemoveWhite.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'RemoveWhite', + + /** + * Constructor + * @memberOf fabric.Image.filters.RemoveWhite.prototype + * @param {Object} [options] Options object + * @param {Number} [options.threshold=30] Threshold value + * @param {Number} [options.distance=20] Distance value + */ + initialize: function(options) { + options = options || { }; + this.threshold = options.threshold || 30; + this.distance = options.distance || 20; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + threshold = this.threshold, + distance = this.distance, + limit = 255 - threshold, + abs = Math.abs, + r, g, b; + + for (var i = 0, len = data.length; i < len; i += 4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + if (r > limit && + g > limit && + b > limit && + abs(r - g) < distance && + abs(r - b) < distance && + abs(g - b) < distance + ) { + data[i + 3] = 1; + } + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + threshold: this.threshold, + distance: this.distance + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.RemoveWhite} Instance of fabric.Image.filters.RemoveWhite + */ + fabric.Image.filters.RemoveWhite.fromObject = function(object) { + return new fabric.Image.filters.RemoveWhite(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Sepia filter class + * @class fabric.Image.filters.Sepia + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Sepia(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Sepia = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Sepia', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Sepia.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, avg; + + for (i = 0; i < iLen; i+=4) { + avg = 0.3 * data[i] + 0.59 * data[i + 1] + 0.11 * data[i + 2]; + data[i] = avg + 100; + data[i + 1] = avg + 50; + data[i + 2] = avg + 255; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Sepia} Instance of fabric.Image.filters.Sepia + */ + fabric.Image.filters.Sepia.fromObject = function() { + return new fabric.Image.filters.Sepia(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Sepia2 filter class + * @class fabric.Image.filters.Sepia2 + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Sepia2(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Sepia2 = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia2.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Sepia2', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Sepia.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, r, g, b; + + for (i = 0; i < iLen; i+=4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + data[i] = (r * 0.393 + g * 0.769 + b * 0.189 ) / 1.351; + data[i + 1] = (r * 0.349 + g * 0.686 + b * 0.168 ) / 1.203; + data[i + 2] = (r * 0.272 + g * 0.534 + b * 0.131 ) / 2.140; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Sepia2} Instance of fabric.Image.filters.Sepia2 + */ + fabric.Image.filters.Sepia2.fromObject = function() { + return new fabric.Image.filters.Sepia2(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Tint filter class + * Adapted from https://github.com/mezzoblue/PaintbrushJS + * @class fabric.Image.filters.Tint + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Tint#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example Tint filter with hex color and opacity + * var filter = new fabric.Image.filters.Tint({ + * color: '#3513B0', + * opacity: 0.5 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example Tint filter with rgba color + * var filter = new fabric.Image.filters.Tint({ + * color: 'rgba(53, 21, 176, 0.5)' + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Tint = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Tint.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Tint', + + /** + * Constructor + * @memberOf fabric.Image.filters.Tint.prototype + * @param {Object} [options] Options object + * @param {String} [options.color=#000000] Color to tint the image with + * @param {Number} [options.opacity] Opacity value that controls the tint effect's transparency (0..1) + */ + initialize: function(options) { + options = options || { }; + + this.color = options.color || '#000000'; + this.opacity = typeof options.opacity !== 'undefined' + ? options.opacity + : new fabric.Color(this.color).getAlpha(); + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, + tintR, tintG, tintB, + r, g, b, alpha1, + source; + + source = new fabric.Color(this.color).getSource(); + + tintR = source[0] * this.opacity; + tintG = source[1] * this.opacity; + tintB = source[2] * this.opacity; + + alpha1 = 1 - this.opacity; + + for (i = 0; i < iLen; i+=4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + // alpha compositing + data[i] = tintR + r * alpha1; + data[i + 1] = tintG + g * alpha1; + data[i + 2] = tintB + b * alpha1; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + color: this.color, + opacity: this.opacity + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Tint} Instance of fabric.Image.filters.Tint + */ + fabric.Image.filters.Tint.fromObject = function(object) { + return new fabric.Image.filters.Tint(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Multiply filter class + * Adapted from http://www.laurenscorijn.com/articles/colormath-basics + * @class fabric.Image.filters.Multiply + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @example Multiply filter with hex color + * var filter = new fabric.Image.filters.Multiply({ + * color: '#F0F' + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example Multiply filter with rgb color + * var filter = new fabric.Image.filters.Multiply({ + * color: 'rgb(53, 21, 176)' + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Multiply = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Multiply.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Multiply', + + /** + * Constructor + * @memberOf fabric.Image.filters.Multiply.prototype + * @param {Object} [options] Options object + * @param {String} [options.color=#000000] Color to multiply the image pixels with + */ + initialize: function(options) { + options = options || { }; + + this.color = options.color || '#000000'; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, + source; + + source = new fabric.Color(this.color).getSource(); + + for (i = 0; i < iLen; i+=4) { + data[i] *= source[0] / 255; + data[i + 1] *= source[1] / 255; + data[i + 2] *= source[2] / 255; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + color: this.color + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Multiply} Instance of fabric.Image.filters.Multiply + */ + fabric.Image.filters.Multiply.fromObject = function(object) { + return new fabric.Image.filters.Multiply(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global){ + 'use strict'; + + var fabric = global.fabric; + + /** + * Color Blend filter class + * @class fabric.Image.filter.Blend + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @example + * var filter = new fabric.Image.filters.Blend({ + * color: '#000', + * mode: 'multiply' + * }); + * + * var filter = new fabric.Image.filters.Blend({ + * image: fabricImageObject, + * mode: 'multiply', + * alpha: 0.5 + * }); + + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Blend = fabric.util.createClass({ + type: 'Blend', + + initialize: function(options){ + options = options || {}; + this.color = options.color || '#000'; + this.image = options.image || false; + this.mode = options.mode || 'multiply'; + this.alpha = options.alpha || 1; + }, + + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + tr, tg, tb, + r, g, b, + source, + isImage = false; + + if (this.image) { + // Blend images + isImage = true; + + var _el = fabric.util.createCanvasElement(); + _el.width = this.image.width; + _el.height = this.image.height; + + var tmpCanvas = new fabric.StaticCanvas(_el); + tmpCanvas.add(this.image); + var context2 = tmpCanvas.getContext('2d'); + source = context2.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height).data; + } + else { + // Blend color + source = new fabric.Color(this.color).getSource(); + + tr = source[0] * this.alpha; + tg = source[1] * this.alpha; + tb = source[2] * this.alpha; + } + + for (var i = 0, len = data.length; i < len; i += 4) { + + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + if (isImage) { + tr = source[i] * this.alpha; + tg = source[i + 1] * this.alpha; + tb = source[i + 2] * this.alpha; + } + + switch (this.mode) { + case 'multiply': + data[i] = r * tr / 255; + data[i + 1] = g * tg / 255; + data[i + 2] = b * tb / 255; + break; + case 'screen': + data[i] = 1 - (1 - r) * (1 - tr); + data[i + 1] = 1 - (1 - g) * (1 - tg); + data[i + 2] = 1 - (1 - b) * (1 - tb); + break; + case 'add': + data[i] = Math.min(255, r + tr); + data[i + 1] = Math.min(255, g + tg); + data[i + 2] = Math.min(255, b + tb); + break; + case 'diff': + case 'difference': + data[i] = Math.abs(r - tr); + data[i + 1] = Math.abs(g - tg); + data[i + 2] = Math.abs(b - tb); + break; + case 'subtract': + var _r = r-tr; + var _g = g-tg; + var _b = b-tb; + + data[i] = (_r < 0) ? 0 : _r; + data[i + 1] = (_g < 0) ? 0 : _g; + data[i + 2] = (_b < 0) ? 0 : _b; + break; + case 'darken': + data[i] = Math.min(r, tr); + data[i + 1] = Math.min(g, tg); + data[i + 2] = Math.min(b, tb); + break; + case 'lighten': + data[i] = Math.max(r, tr); + data[i + 1] = Math.max(g, tg); + data[i + 2] = Math.max(b, tb); + break; + } + } + + context.putImageData(imageData, 0, 0); + } + }); + + fabric.Image.filters.Blend.fromObject = function(object) { + return new fabric.Image.filters.Blend(object); + }; +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + clone = fabric.util.object.clone, + toFixed = fabric.util.toFixed, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Text) { + fabric.warn('fabric.Text is already defined'); + return; + } + + var stateProperties = fabric.Object.prototype.stateProperties.concat(); + stateProperties.push( + 'fontFamily', + 'fontWeight', + 'fontSize', + 'text', + 'textDecoration', + 'textAlign', + 'fontStyle', + 'lineHeight', + 'textBackgroundColor', + 'useNative', + 'path' + ); + + /** + * Text class + * @class fabric.Text + * @extends fabric.Object + * @return {fabric.Text} thisArg + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#text} + * @see {@link fabric.Text#initialize} for constructor definition + */ + fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ { + + /** + * Properties which when set cause object to change dimensions + * @type Object + * @private + */ + _dimensionAffectingProps: { + fontSize: true, + fontWeight: true, + fontFamily: true, + textDecoration: true, + fontStyle: true, + lineHeight: true, + stroke: true, + strokeWidth: true, + text: true + }, + + /** + * @private + */ + _reNewline: /\r?\n/, + + /** + * Retrieves object's fontSize + * @method getFontSize + * @memberOf fabric.Text.prototype + * @return {String} Font size (in pixels) + */ + + /** + * Sets object's fontSize + * @method setFontSize + * @memberOf fabric.Text.prototype + * @param {Number} fontSize Font size (in pixels) + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontWeight + * @method getFontWeight + * @memberOf fabric.Text.prototype + * @return {(String|Number)} Font weight + */ + + /** + * Sets object's fontWeight + * @method setFontWeight + * @memberOf fabric.Text.prototype + * @param {(Number|String)} fontWeight Font weight + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontFamily + * @method getFontFamily + * @memberOf fabric.Text.prototype + * @return {String} Font family + */ + + /** + * Sets object's fontFamily + * @method setFontFamily + * @memberOf fabric.Text.prototype + * @param {String} fontFamily Font family + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's text + * @method getText + * @memberOf fabric.Text.prototype + * @return {String} text + */ + + /** + * Sets object's text + * @method setText + * @memberOf fabric.Text.prototype + * @param {String} text Text + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textDecoration + * @method getTextDecoration + * @memberOf fabric.Text.prototype + * @return {String} Text decoration + */ + + /** + * Sets object's textDecoration + * @method setTextDecoration + * @memberOf fabric.Text.prototype + * @param {String} textDecoration Text decoration + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontStyle + * @method getFontStyle + * @memberOf fabric.Text.prototype + * @return {String} Font style + */ + + /** + * Sets object's fontStyle + * @method setFontStyle + * @memberOf fabric.Text.prototype + * @param {String} fontStyle Font style + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's lineHeight + * @method getLineHeight + * @memberOf fabric.Text.prototype + * @return {Number} Line height + */ + + /** + * Sets object's lineHeight + * @method setLineHeight + * @memberOf fabric.Text.prototype + * @param {Number} lineHeight Line height + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textAlign + * @method getTextAlign + * @memberOf fabric.Text.prototype + * @return {String} Text alignment + */ + + /** + * Sets object's textAlign + * @method setTextAlign + * @memberOf fabric.Text.prototype + * @param {String} textAlign Text alignment + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textBackgroundColor + * @method getTextBackgroundColor + * @memberOf fabric.Text.prototype + * @return {String} Text background color + */ + + /** + * Sets object's textBackgroundColor + * @method setTextBackgroundColor + * @memberOf fabric.Text.prototype + * @param {String} textBackgroundColor Text background color + * @return {fabric.Text} + * @chainable + */ + + /** + * Type of an object + * @type String + * @default + */ + type: 'text', + + /** + * Font size (in pixels) + * @type Number + * @default + */ + fontSize: 40, + + /** + * Font weight (e.g. bold, normal, 400, 600, 800) + * @type {(Number|String)} + * @default + */ + fontWeight: 'normal', + + /** + * Font family + * @type String + * @default + */ + fontFamily: 'Times New Roman', + + /** + * Text decoration Possible values: "", "underline", "overline" or "line-through". + * @type String + * @default + */ + textDecoration: '', + + /** + * Text alignment. Possible values: "left", "center", or "right". + * @type String + * @default + */ + textAlign: 'left', + + /** + * Font style . Possible values: "", "normal", "italic" or "oblique". + * @type String + * @default + */ + fontStyle: '', + + /** + * Line height + * @type Number + * @default + */ + lineHeight: 1.3, + + /** + * Background color of text lines + * @type String + * @default + */ + textBackgroundColor: '', + + /** + * URL of a font file, when using Cufon + * @type String | null + * @default + */ + path: null, + + /** + * Indicates whether canvas native text methods should be used to render text (otherwise, Cufon is used) + * @type Boolean + * @default + */ + useNative: true, + + /** + * List of properties to consider when checking if + * state of an object is changed ({@link fabric.Object#hasStateChanged}) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: stateProperties, + + /** + * When defined, an object is rendered via stroke and this property specifies its color. + * Backwards incompatibility note: This property was named "strokeStyle" until v1.1.6 + * @type String + * @default + */ + stroke: null, + + /** + * Shadow object representing shadow of this shape. + * Backwards incompatibility note: This property was named "textShadow" (String) until v1.2.11 + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Constructor + * @param {String} text Text string + * @param {Object} [options] Options object + * @return {fabric.Text} thisArg + */ + initialize: function(text, options) { + options = options || { }; + + this.text = text; + this.__skipDimension = true; + this.setOptions(options); + this.__skipDimension = false; + this._initDimensions(); + }, + + /** + * Renders text object on offscreen canvas, so that it would get dimensions + * @private + */ + _initDimensions: function() { + if (this.__skipDimension) { + return; + } + var canvasEl = fabric.util.createCanvasElement(); + this._render(canvasEl.getContext('2d')); + }, + + /** + * Returns string representation of an instance + * @return {String} String representation of text object + */ + toString: function() { + return '#'; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + + if (typeof Cufon === 'undefined' || this.useNative === true) { + this._renderViaNative(ctx); + } + else { + this._renderViaCufon(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderViaNative: function(ctx) { + var textLines = this.text.split(this._reNewline); + + this._setTextStyles(ctx); + + this.width = this._getTextWidth(ctx, textLines); + this.height = this._getTextHeight(ctx, textLines); + + this.clipTo && fabric.util.clipContext(this, ctx); + + this._renderTextBackground(ctx, textLines); + this._translateForTextAlign(ctx); + this._renderText(ctx, textLines); + + if (this.textAlign !== 'left' && this.textAlign !== 'justify') { + ctx.restore(); + } + + this._renderTextDecoration(ctx, textLines); + this.clipTo && ctx.restore(); + + this._setBoundaries(ctx, textLines); + this._totalLineHeight = 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderText: function(ctx, textLines) { + ctx.save(); + this._setShadow(ctx); + this._setupFillRule(ctx); + this._renderTextFill(ctx, textLines); + this._renderTextStroke(ctx, textLines); + this._restoreFillRule(ctx); + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _translateForTextAlign: function(ctx) { + if (this.textAlign !== 'left' && this.textAlign !== 'justify') { + ctx.save(); + ctx.translate(this.textAlign === 'center' ? (this.width / 2) : this.width, 0); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _setBoundaries: function(ctx, textLines) { + this._boundaries = [ ]; + + for (var i = 0, len = textLines.length; i < len; i++) { + + var lineWidth = this._getLineWidth(ctx, textLines[i]), + lineLeftOffset = this._getLineLeftOffset(lineWidth); + + this._boundaries.push({ + height: this.fontSize * this.lineHeight, + width: lineWidth, + left: lineLeftOffset + }); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _setTextStyles: function(ctx) { + this._setFillStyles(ctx); + this._setStrokeStyles(ctx); + ctx.textBaseline = 'alphabetic'; + if (!this.skipTextAlign) { + ctx.textAlign = this.textAlign; + } + ctx.font = this._getFontDeclaration(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + * @return {Number} Height of fabric.Text object + */ + _getTextHeight: function(ctx, textLines) { + return this.fontSize * textLines.length * this.lineHeight; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + * @return {Number} Maximum width of fabric.Text object + */ + _getTextWidth: function(ctx, textLines) { + var maxWidth = ctx.measureText(textLines[0] || '|').width; + + for (var i = 1, len = textLines.length; i < len; i++) { + var currentLineWidth = ctx.measureText(textLines[i]).width; + if (currentLineWidth > maxWidth) { + maxWidth = currentLineWidth; + } + } + return maxWidth; + }, + + /** + * @private + * @param {String} method Method name ("fillText" or "strokeText") + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} chars Chars to render + * @param {Number} left Left position of text + * @param {Number} top Top position of text + */ + _renderChars: function(method, ctx, chars, left, top) { + ctx[method](chars, left, top); + }, + + /** + * @private + * @param {String} method Method name ("fillText" or "strokeText") + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Text to render + * @param {Number} left Left position of text + * @param {Number} top Top position of text + * @param {Number} lineIndex Index of a line in a text + */ + _renderTextLine: function(method, ctx, line, left, top, lineIndex) { + // lift the line by quarter of fontSize + top -= this.fontSize / 4; + + // short-circuit + if (this.textAlign !== 'justify') { + this._renderChars(method, ctx, line, left, top, lineIndex); + return; + } + + var lineWidth = ctx.measureText(line).width, + totalWidth = this.width; + + if (totalWidth > lineWidth) { + // stretch the line + var words = line.split(/\s+/), + wordsWidth = ctx.measureText(line.replace(/\s+/g, '')).width, + widthDiff = totalWidth - wordsWidth, + numSpaces = words.length - 1, + spaceWidth = widthDiff / numSpaces, + leftOffset = 0; + + for (var i = 0, len = words.length; i < len; i++) { + this._renderChars(method, ctx, words[i], left + leftOffset, top, lineIndex); + leftOffset += ctx.measureText(words[i]).width + spaceWidth; + } + } + else { + this._renderChars(method, ctx, line, left, top, lineIndex); + } + }, + + /** + * @private + * @return {Number} Left offset + */ + _getLeftOffset: function() { + if (fabric.isLikelyNode) { + return 0; + } + return -this.width / 2; + }, + + /** + * @private + * @return {Number} Top offset + */ + _getTopOffset: function() { + return -this.height / 2; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextFill: function(ctx, textLines) { + if (!this.fill && !this._skipFillStrokeCheck) { + return; + } + + this._boundaries = [ ]; + var lineHeights = 0; + + for (var i = 0, len = textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i, textLines); + lineHeights += heightOfLine; + + this._renderTextLine( + 'fillText', + ctx, + textLines[i], + this._getLeftOffset(), + this._getTopOffset() + lineHeights, + i + ); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextStroke: function(ctx, textLines) { + if ((!this.stroke || this.strokeWidth === 0) && !this._skipFillStrokeCheck) { + return; + } + + var lineHeights = 0; + + ctx.save(); + if (this.strokeDashArray) { + // Spec requires the concatenation of two copies the dash list when the number of elements is odd + if (1 & this.strokeDashArray.length) { + this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); + } + supportsLineDash && ctx.setLineDash(this.strokeDashArray); + } + + ctx.beginPath(); + for (var i = 0, len = textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i, textLines); + lineHeights += heightOfLine; + + this._renderTextLine( + 'strokeText', + ctx, + textLines[i], + this._getLeftOffset(), + this._getTopOffset() + lineHeights, + i + ); + } + ctx.closePath(); + ctx.restore(); + }, + + _getHeightOfLine: function() { + return this.fontSize * this.lineHeight; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextBackground: function(ctx, textLines) { + this._renderTextBoxBackground(ctx); + this._renderTextLinesBackground(ctx, textLines); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderTextBoxBackground: function(ctx) { + if (!this.backgroundColor) { + return; + } + + ctx.save(); + ctx.fillStyle = this.backgroundColor; + + ctx.fillRect( + this._getLeftOffset(), + this._getTopOffset(), + this.width, + this.height + ); + + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextLinesBackground: function(ctx, textLines) { + if (!this.textBackgroundColor) { + return; + } + + ctx.save(); + ctx.fillStyle = this.textBackgroundColor; + + for (var i = 0, len = textLines.length; i < len; i++) { + + if (textLines[i] !== '') { + + var lineWidth = this._getLineWidth(ctx, textLines[i]), + lineLeftOffset = this._getLineLeftOffset(lineWidth); + + ctx.fillRect( + this._getLeftOffset() + lineLeftOffset, + this._getTopOffset() + (i * this.fontSize * this.lineHeight), + lineWidth, + this.fontSize * this.lineHeight + ); + } + } + ctx.restore(); + }, + + /** + * @private + * @param {Number} lineWidth Width of text line + * @return {Number} Line left offset + */ + _getLineLeftOffset: function(lineWidth) { + if (this.textAlign === 'center') { + return (this.width - lineWidth) / 2; + } + if (this.textAlign === 'right') { + return this.width - lineWidth; + } + return 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Text line + * @return {Number} Line width + */ + _getLineWidth: function(ctx, line) { + return this.textAlign === 'justify' + ? this.width + : ctx.measureText(line).width; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextDecoration: function(ctx, textLines) { + if (!this.textDecoration) { + return; + } + + // var halfOfVerticalBox = this.originY === 'top' ? 0 : this._getTextHeight(ctx, textLines) / 2; + var halfOfVerticalBox = this._getTextHeight(ctx, textLines) / 2, + _this = this; + + /** @ignore */ + function renderLinesAtOffset(offset) { + for (var i = 0, len = textLines.length; i < len; i++) { + + var lineWidth = _this._getLineWidth(ctx, textLines[i]), + lineLeftOffset = _this._getLineLeftOffset(lineWidth); + + ctx.fillRect( + _this._getLeftOffset() + lineLeftOffset, + ~~((offset + (i * _this._getHeightOfLine(ctx, i, textLines))) - halfOfVerticalBox), + lineWidth, + 1); + } + } + + if (this.textDecoration.indexOf('underline') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight); + } + if (this.textDecoration.indexOf('line-through') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize / 2); + } + if (this.textDecoration.indexOf('overline') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize); + } + }, + + /** + * @private + */ + _getFontDeclaration: function() { + return [ + // node-canvas needs "weight style", while browsers need "style weight" + (fabric.isLikelyNode ? this.fontWeight : this.fontStyle), + (fabric.isLikelyNode ? this.fontStyle : this.fontWeight), + this.fontSize + 'px', + (fabric.isLikelyNode ? ('"' + this.fontFamily + '"') : this.fontFamily) + ].join(' '); + }, + + /** + * Renders text instance on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + render: function(ctx, noTransform) { + // do not render if object is not visible + if (!this.visible) { + return; + } + + ctx.save(); + this._transform(ctx, noTransform); + + var m = this.transformMatrix, + isInPathGroup = this.group && this.group.type === 'path-group'; + + if (isInPathGroup) { + ctx.translate(-this.group.width/2, -this.group.height/2); + } + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + if (isInPathGroup) { + ctx.translate(this.left, this.top); + } + this._render(ctx); + ctx.restore(); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + var object = extend(this.callSuper('toObject', propertiesToInclude), { + text: this.text, + fontSize: this.fontSize, + fontWeight: this.fontWeight, + fontFamily: this.fontFamily, + fontStyle: this.fontStyle, + lineHeight: this.lineHeight, + textDecoration: this.textDecoration, + textAlign: this.textAlign, + path: this.path, + textBackgroundColor: this.textBackgroundColor, + useNative: this.useNative + }); + if (!this.includeDefaultValues) { + this._removeDefaultValues(object); + } + return object; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = [ ], + textLines = this.text.split(this._reNewline), + offsets = this._getSVGLeftTopOffsets(textLines), + textAndBg = this._getSVGTextAndBg(offsets.lineTop, offsets.textLeft, textLines), + shadowSpans = this._getSVGShadows(offsets.lineTop, textLines); + + // move top offset by an ascent + offsets.textTop += (this._fontAscent ? ((this._fontAscent / 5) * this.lineHeight) : 0); + + this._wrapSVGTextAndBg(markup, textAndBg, shadowSpans, offsets); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + + /** + * @private + */ + _getSVGLeftTopOffsets: function(textLines) { + var lineTop = this.useNative + ? this.fontSize * this.lineHeight + : (-this._fontAscent - ((this._fontAscent / 5) * this.lineHeight)), + + textLeft = -(this.width/2), + textTop = this.useNative + ? this.fontSize - 1 + : (this.height/2) - (textLines.length * this.fontSize) - this._totalLineHeight; + + return { + textLeft: textLeft + (this.group ? this.left : 0), + textTop: textTop + (this.group ? this.top : 0), + lineTop: lineTop + }; + }, + + /** + * @private + */ + _wrapSVGTextAndBg: function(markup, textAndBg, shadowSpans, offsets) { + markup.push( + '\n', + textAndBg.textBgRects.join(''), + '', + shadowSpans.join(''), + textAndBg.textSpans.join(''), + '\n', + '\n' + ); + }, + + /** + * @private + * @param {Number} lineHeight + * @param {Array} textLines Array of all text lines + * @return {Array} + */ + _getSVGShadows: function(lineHeight, textLines) { + var shadowSpans = [], + i, len, + lineTopOffsetMultiplier = 1; + + if (!this.shadow || !this._boundaries) { + return shadowSpans; + } + + for (i = 0, len = textLines.length; i < len; i++) { + if (textLines[i] !== '') { + var lineLeftOffset = (this._boundaries && this._boundaries[i]) ? this._boundaries[i].left : 0; + shadowSpans.push( + '', + fabric.util.string.escapeXml(textLines[i]), + ''); + lineTopOffsetMultiplier = 1; + } + else { + // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier + // prevents empty tspans + lineTopOffsetMultiplier++; + } + } + + return shadowSpans; + }, + + /** + * @private + * @param {Number} lineHeight + * @param {Number} textLeftOffset Text left offset + * @param {Array} textLines Array of all text lines + * @return {Object} + */ + _getSVGTextAndBg: function(lineHeight, textLeftOffset, textLines) { + var textSpans = [ ], + textBgRects = [ ], + lineTopOffsetMultiplier = 1; + + // bounding-box background + this._setSVGBg(textBgRects); + + // text and text-background + for (var i = 0, len = textLines.length; i < len; i++) { + if (textLines[i] !== '') { + this._setSVGTextLineText(textLines[i], i, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects); + lineTopOffsetMultiplier = 1; + } + else { + // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier + // prevents empty tspans + lineTopOffsetMultiplier++; + } + + if (!this.textBackgroundColor || !this._boundaries) { + continue; + } + + this._setSVGTextLineBg(textBgRects, i, textLeftOffset, lineHeight); + } + + return { + textSpans: textSpans, + textBgRects: textBgRects + }; + }, + + _setSVGTextLineText: function(textLine, i, textSpans, lineHeight, lineTopOffsetMultiplier) { + var lineLeftOffset = (this._boundaries && this._boundaries[i]) + ? toFixed(this._boundaries[i].left, 2) + : 0; + + textSpans.push( + ' elements since setting opacity + // on containing one doesn't work in Illustrator + this._getFillAttributes(this.fill), '>', + fabric.util.string.escapeXml(textLine), + '' + ); + }, + + _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, lineHeight) { + textBgRects.push( + '\n'); + }, + + _setSVGBg: function(textBgRects) { + if (this.backgroundColor && this._boundaries) { + textBgRects.push( + ''); + } + }, + + /** + * Adobe Illustrator (at least CS5) is unable to render rgba()-based fill values + * we work around it by "moving" alpha channel into opacity attribute and setting fill's alpha to 1 + * + * @private + * @param {Any} value + * @return {String} + */ + _getFillAttributes: function(value) { + var fillColor = (value && typeof value === 'string') ? new fabric.Color(value) : ''; + if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) { + return 'fill="' + value + '"'; + } + return 'opacity="' + fillColor.getAlpha() + '" fill="' + fillColor.setAlpha(1).toRgb() + '"'; + }, + /* _TO_SVG_END_ */ + + /** + * Sets specified property to a specified value + * @param {String} key + * @param {Any} value + * @return {fabric.Text} thisArg + * @chainable + */ + _set: function(key, value) { + if (key === 'fontFamily' && this.path) { + this.path = this.path.replace(/(.*?)([^\/]*)(\.font\.js)/, '$1' + value + '$3'); + } + this.callSuper('_set', key, value); + + if (key in this._dimensionAffectingProps) { + this._initDimensions(); + this.setCoords(); + } + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement}) + * @static + * @memberOf fabric.Text + * @see: http://www.w3.org/TR/SVG/text.html#TextElement + */ + fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat( + 'x y dx dy font-family font-style font-weight font-size text-decoration text-anchor'.split(' ')); + + /** + * Default SVG font size + * @static + * @memberOf fabric.Text + */ + fabric.Text.DEFAULT_SVG_FONT_SIZE = 16; + + /** + * Returns fabric.Text instance from an SVG element (not yet implemented) + * @static + * @memberOf fabric.Text + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Text} Instance of fabric.Text + */ + fabric.Text.fromElement = function(element, options) { + if (!element) { + return null; + } + + var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES); + options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes); + + if ('dx' in parsedAttributes) { + options.left += parsedAttributes.dx; + } + if ('dy' in parsedAttributes) { + options.top += parsedAttributes.dy; + } + if (!('fontSize' in options)) { + options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE; + } + + if (!options.originX) { + options.originX = 'left'; + } + + var text = new fabric.Text(element.textContent, options), + /* + Adjust positioning: + x/y attributes in SVG correspond to the bottom-left corner of text bounding box + top/left properties in Fabric correspond to center point of text bounding box + */ + offX = 0; + + if (text.originX === 'left') { + offX = text.getWidth() / 2; + } + if (text.originX === 'right') { + offX = -text.getWidth() / 2; + } + text.set({ + left: text.getLeft() + offX, + top: text.getTop() - text.getHeight() / 2 + }); + + return text; + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Text instance from an object representation + * @static + * @memberOf fabric.Text + * @param {Object} object Object to create an instance from + * @return {fabric.Text} Instance of fabric.Text + */ + fabric.Text.fromObject = function(object) { + return new fabric.Text(object.text, clone(object)); + }; + + fabric.util.createAccessors(fabric.Text); + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + var clone = fabric.util.object.clone; + + /** + * IText class (introduced in v1.4) Events are also fired with "text:" + * prefix when observing canvas. + * @class fabric.IText + * @extends fabric.Text + * @mixes fabric.Observable + * + * @fires changed + * @fires selection:changed + * @fires editing:entered + * @fires editing:exited + * + * @return {fabric.IText} thisArg + * @see {@link fabric.IText#initialize} for constructor definition + * + *

    Supported key combinations:

    + *
    +    *   Move cursor:                    left, right, up, down
    +    *   Select character:               shift + left, shift + right
    +    *   Select text vertically:         shift + up, shift + down
    +    *   Move cursor by word:            alt + left, alt + right
    +    *   Select words:                   shift + alt + left, shift + alt + right
    +    *   Move cursor to line start/end:  cmd + left, cmd + right
    +    *   Select till start/end of line:  cmd + shift + left, cmd + shift + right
    +    *   Jump to start/end of text:      cmd + up, cmd + down
    +    *   Select till start/end of text:  cmd + shift + up, cmd + shift + down
    +    *   Delete character:               backspace
    +    *   Delete word:                    alt + backspace
    +    *   Delete line:                    cmd + backspace
    +    *   Forward delete:                 delete
    +    *   Copy text:                      ctrl/cmd + c
    +    *   Paste text:                     ctrl/cmd + v
    +    *   Cut text:                       ctrl/cmd + x
    +    *   Select entire text:             ctrl/cmd + a
    +    * 
    + * + *

    Supported mouse/touch combination

    + *
    +    *   Position cursor:                click/touch
    +    *   Create selection:               click/touch & drag
    +    *   Create selection:               click & shift + click
    +    *   Select word:                    double click
    +    *   Select line:                    triple click
    +    * 
    + */ + fabric.IText = fabric.util.createClass(fabric.Text, fabric.Observable, /** @lends fabric.IText.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'i-text', + + /** + * Index where text selection starts (or where cursor is when there is no selection) + * @type Nubmer + * @default + */ + selectionStart: 0, + + /** + * Index where text selection ends + * @type Nubmer + * @default + */ + selectionEnd: 0, + + /** + * Color of text selection + * @type String + * @default + */ + selectionColor: 'rgba(17,119,255,0.3)', + + /** + * Indicates whether text is in editing mode + * @type Boolean + * @default + */ + isEditing: false, + + /** + * Indicates whether a text can be edited + * @type Boolean + * @default + */ + editable: true, + + /** + * Border color of text object while it's in editing mode + * @type String + * @default + */ + editingBorderColor: 'rgba(102,153,255,0.25)', + + /** + * Width of cursor (in px) + * @type Number + * @default + */ + cursorWidth: 2, + + /** + * Color of default cursor (when not overwritten by character style) + * @type String + * @default + */ + cursorColor: '#333', + + /** + * Delay between cursor blink (in ms) + * @type Number + * @default + */ + cursorDelay: 1000, + + /** + * Duration of cursor fadein (in ms) + * @type Number + * @default + */ + cursorDuration: 600, + + /** + * Object containing character styles + * (where top-level properties corresponds to line number and 2nd-level properties -- to char number in a line) + * @type Object + * @default + */ + styles: null, + + /** + * Indicates whether internal text char widths can be cached + * @type Boolean + * @default + */ + caching: true, + + /** + * @private + * @type Boolean + * @default + */ + _skipFillStrokeCheck: true, + + /** + * @private + */ + _reSpace: /\s|\n/, + + /** + * @private + */ + _fontSizeFraction: 4, + + /** + * @private + */ + _currentCursorOpacity: 0, + + /** + * @private + */ + _selectionDirection: null, + + /** + * @private + */ + _abortCursorAnimation: false, + + /** + * @private + */ + _charWidthsCache: { }, + + /** + * Constructor + * @param {String} text Text string + * @param {Object} [options] Options object + * @return {fabric.IText} thisArg + */ + initialize: function(text, options) { + this.styles = options ? (options.styles || { }) : { }; + this.callSuper('initialize', text, options); + this.initBehavior(); + + fabric.IText.instances.push(this); + + // caching + this.__lineWidths = { }; + this.__lineHeights = { }; + this.__lineOffsets = { }; + }, + + /** + * Returns true if object has no styling + */ + isEmptyStyles: function() { + if (!this.styles) { + return true; + } + var obj = this.styles; + + for (var p1 in obj) { + for (var p2 in obj[p1]) { + /*jshint unused:false */ + for (var p3 in obj[p1][p2]) { + return false; + } + } + } + return true; + }, + + /** + * Sets selection start (left boundary of a selection) + * @param {Number} index Index to set selection start to + */ + setSelectionStart: function(index) { + if (this.selectionStart !== index) { + this.fire('selection:changed'); + this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + } + this.selectionStart = index; + this.hiddenTextarea && (this.hiddenTextarea.selectionStart = index); + }, + + /** + * Sets selection end (right boundary of a selection) + * @param {Number} index Index to set selection end to + */ + setSelectionEnd: function(index) { + if (this.selectionEnd !== index) { + this.fire('selection:changed'); + this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + } + this.selectionEnd = index; + this.hiddenTextarea && (this.hiddenTextarea.selectionEnd = index); + }, + + /** + * Gets style of a current selection/cursor (at the start position) + * @param {Number} [startIndex] Start index to get styles at + * @param {Number} [endIndex] End index to get styles at + * @return {Object} styles Style object at a specified (or current) index + */ + getSelectionStyles: function(startIndex, endIndex) { + + if (arguments.length === 2) { + var styles = [ ]; + for (var i = startIndex; i < endIndex; i++) { + styles.push(this.getSelectionStyles(i)); + } + return styles; + } + + var loc = this.get2DCursorLocation(startIndex); + if (this.styles[loc.lineIndex]) { + return this.styles[loc.lineIndex][loc.charIndex] || { }; + } + + return { }; + }, + + /** + * Sets style of a current selection + * @param {Object} [styles] Styles object + * @return {fabric.IText} thisArg + * @chainable + */ + setSelectionStyles: function(styles) { + if (this.selectionStart === this.selectionEnd) { + this._extendStyles(this.selectionStart, styles); + } + else { + for (var i = this.selectionStart; i < this.selectionEnd; i++) { + this._extendStyles(i, styles); + } + } + return this; + }, + + /** + * @private + */ + _extendStyles: function(index, styles) { + var loc = this.get2DCursorLocation(index); + + if (!this.styles[loc.lineIndex]) { + this.styles[loc.lineIndex] = { }; + } + if (!this.styles[loc.lineIndex][loc.charIndex]) { + this.styles[loc.lineIndex][loc.charIndex] = { }; + } + + fabric.util.object.extend(this.styles[loc.lineIndex][loc.charIndex], styles); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + this.callSuper('_render', ctx); + this.ctx = ctx; + this.isEditing && this.renderCursorOrSelection(); + }, + + /** + * Renders cursor or selection (depending on what exists) + */ + renderCursorOrSelection: function() { + if (!this.active) { + return; + } + + var chars = this.text.split(''), + boundaries; + + if (this.selectionStart === this.selectionEnd) { + boundaries = this._getCursorBoundaries(chars, 'cursor'); + this.renderCursor(boundaries); + } + else { + boundaries = this._getCursorBoundaries(chars, 'selection'); + this.renderSelection(chars, boundaries); + } + }, + + /** + * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start) + * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used. + */ + get2DCursorLocation: function(selectionStart) { + if (typeof selectionStart === 'undefined') { + selectionStart = this.selectionStart; + } + var textBeforeCursor = this.text.slice(0, selectionStart), + linesBeforeCursor = textBeforeCursor.split(this._reNewline); + + return { + lineIndex: linesBeforeCursor.length - 1, + charIndex: linesBeforeCursor[linesBeforeCursor.length - 1].length + }; + }, + + /** + * Returns complete style of char at the current cursor + * @param {Number} lineIndex Line index + * @param {Number} charIndex Char index + * @return {Object} Character style + */ + getCurrentCharStyle: function(lineIndex, charIndex) { + var style = this.styles[lineIndex] && this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)]; + + return { + fontSize: style && style.fontSize || this.fontSize, + fill: style && style.fill || this.fill, + textBackgroundColor: style && style.textBackgroundColor || this.textBackgroundColor, + textDecoration: style && style.textDecoration || this.textDecoration, + fontFamily: style && style.fontFamily || this.fontFamily, + fontWeight: style && style.fontWeight || this.fontWeight, + fontStyle: style && style.fontStyle || this.fontStyle, + stroke: style && style.stroke || this.stroke, + strokeWidth: style && style.strokeWidth || this.strokeWidth + }; + }, + + /** + * Returns fontSize of char at the current cursor + * @param {Number} lineIndex Line index + * @param {Number} charIndex Char index + * @return {Number} Character font size + */ + getCurrentCharFontSize: function(lineIndex, charIndex) { + return ( + this.styles[lineIndex] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)].fontSize) || this.fontSize; + }, + + /** + * Returns color (fill) of char at the current cursor + * @param {Number} lineIndex Line index + * @param {Number} charIndex Char index + * @return {String} Character color (fill) + */ + getCurrentCharColor: function(lineIndex, charIndex) { + return ( + this.styles[lineIndex] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)].fill) || this.cursorColor; + }, + + /** + * Returns cursor boundaries (left, top, leftOffset, topOffset) + * @private + * @param {Array} chars Array of characters + * @param {String} typeOfBoundaries + */ + _getCursorBoundaries: function(chars, typeOfBoundaries) { + + var cursorLocation = this.get2DCursorLocation(), + + textLines = this.text.split(this._reNewline), + + // left/top are left/top of entire text box + // leftOffset/topOffset are offset from that left/top point of a text box + + left = Math.round(this._getLeftOffset()), + top = -this.height / 2, + + offsets = this._getCursorBoundariesOffsets( + chars, typeOfBoundaries, cursorLocation, textLines); + + return { + left: left, + top: top, + leftOffset: offsets.left + offsets.lineLeft, + topOffset: offsets.top + }; + }, + + /** + * @private + */ + _getCursorBoundariesOffsets: function(chars, typeOfBoundaries, cursorLocation, textLines) { + + var lineLeftOffset = 0, + + lineIndex = 0, + charIndex = 0, + + leftOffset = 0, + topOffset = typeOfBoundaries === 'cursor' + // selection starts at the very top of the line, + // whereas cursor starts at the padding created by line height + ? (this._getHeightOfLine(this.ctx, 0) - + this.getCurrentCharFontSize(cursorLocation.lineIndex, cursorLocation.charIndex)) + : 0; + + for (var i = 0; i < this.selectionStart; i++) { + if (chars[i] === '\n') { + leftOffset = 0; + var index = lineIndex + (typeOfBoundaries === 'cursor' ? 1 : 0); + topOffset += this._getCachedLineHeight(index); + + lineIndex++; + charIndex = 0; + } + else { + leftOffset += this._getWidthOfChar(this.ctx, chars[i], lineIndex, charIndex); + charIndex++; + } + + lineLeftOffset = this._getCachedLineOffset(lineIndex, textLines); + } + + this._clearCache(); + + return { + top: topOffset, + left: leftOffset, + lineLeft: lineLeftOffset + }; + }, + + /** + * @private + */ + _clearCache: function() { + this.__lineWidths = { }; + this.__lineHeights = { }; + this.__lineOffsets = { }; + }, + + /** + * @private + */ + _getCachedLineHeight: function(index) { + return this.__lineHeights[index] || + (this.__lineHeights[index] = this._getHeightOfLine(this.ctx, index)); + }, + + /** + * @private + */ + _getCachedLineWidth: function(lineIndex, textLines) { + return this.__lineWidths[lineIndex] || + (this.__lineWidths[lineIndex] = this._getWidthOfLine(this.ctx, lineIndex, textLines)); + }, + + /** + * @private + */ + _getCachedLineOffset: function(lineIndex, textLines) { + var widthOfLine = this._getCachedLineWidth(lineIndex, textLines); + + return this.__lineOffsets[lineIndex] || + (this.__lineOffsets[lineIndex] = this._getLineLeftOffset(widthOfLine)); + }, + + /** + * Renders cursor + * @param {Object} boundaries + */ + renderCursor: function(boundaries) { + var ctx = this.ctx; + + ctx.save(); + + var cursorLocation = this.get2DCursorLocation(), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex, + charHeight = this.getCurrentCharFontSize(lineIndex, charIndex), + leftOffset = (lineIndex === 0 && charIndex === 0) + ? this._getCachedLineOffset(lineIndex, this.text.split(this._reNewline)) + : boundaries.leftOffset; + + ctx.fillStyle = this.getCurrentCharColor(lineIndex, charIndex); + ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity; + + ctx.fillRect( + boundaries.left + leftOffset, + boundaries.top + boundaries.topOffset, + this.cursorWidth / this.scaleX, + charHeight); + + ctx.restore(); + }, + + /** + * Renders text selection + * @param {Array} chars Array of characters + * @param {Object} boundaries Object with left/top/leftOffset/topOffset + */ + renderSelection: function(chars, boundaries) { + var ctx = this.ctx; + + ctx.save(); + + ctx.fillStyle = this.selectionColor; + + var start = this.get2DCursorLocation(this.selectionStart), + end = this.get2DCursorLocation(this.selectionEnd), + startLine = start.lineIndex, + endLine = end.lineIndex, + textLines = this.text.split(this._reNewline); + + for (var i = startLine; i <= endLine; i++) { + var lineOffset = this._getCachedLineOffset(i, textLines) || 0, + lineHeight = this._getCachedLineHeight(i), + boxWidth = 0; + + if (i === startLine) { + for (var j = 0, len = textLines[i].length; j < len; j++) { + if (j >= start.charIndex && (i !== endLine || j < end.charIndex)) { + boxWidth += this._getWidthOfChar(ctx, textLines[i][j], i, j); + } + if (j < start.charIndex) { + lineOffset += this._getWidthOfChar(ctx, textLines[i][j], i, j); + } + } + } + else if (i > startLine && i < endLine) { + boxWidth += this._getCachedLineWidth(i, textLines) || 5; + } + else if (i === endLine) { + for (var j2 = 0, j2len = end.charIndex; j2 < j2len; j2++) { + boxWidth += this._getWidthOfChar(ctx, textLines[i][j2], i, j2); + } + } + + ctx.fillRect( + boundaries.left + lineOffset, + boundaries.top + boundaries.topOffset, + boxWidth, + lineHeight); + + boundaries.topOffset += lineHeight; + } + ctx.restore(); + }, + + /** + * @private + * @param {String} method + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderChars: function(method, ctx, line, left, top, lineIndex) { + + if (this.isEmptyStyles()) { + return this._renderCharsFast(method, ctx, line, left, top); + } + + this.skipTextAlign = true; + + // set proper box offset + left -= this.textAlign === 'center' + ? (this.width / 2) + : (this.textAlign === 'right') + ? this.width + : 0; + + // set proper line offset + var textLines = this.text.split(this._reNewline), + lineWidth = this._getWidthOfLine(ctx, lineIndex, textLines), + lineHeight = this._getHeightOfLine(ctx, lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(lineWidth), + chars = line.split(''), + prevStyle, + charsToRender = ''; + + left += lineLeftOffset || 0; + + ctx.save(); + + for (var i = 0, len = chars.length; i <= len; i++) { + prevStyle = prevStyle || this.getCurrentCharStyle(lineIndex, i); + var thisStyle = this.getCurrentCharStyle(lineIndex, i + 1); + + if (this._hasStyleChanged(prevStyle, thisStyle) || i === len) { + this._renderChar(method, ctx, lineIndex, i - 1, charsToRender, left, top, lineHeight); + charsToRender = ''; + prevStyle = thisStyle; + } + charsToRender += chars[i]; + } + + ctx.restore(); + }, + + /** + * @private + * @param {String} method + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Content of the line + * @param {Number} left Left coordinate + * @param {Number} top Top coordinate + */ + _renderCharsFast: function(method, ctx, line, left, top) { + this.skipTextAlign = false; + + if (method === 'fillText' && this.fill) { + this.callSuper('_renderChars', method, ctx, line, left, top); + } + if (method === 'strokeText' && this.stroke) { + this.callSuper('_renderChars', method, ctx, line, left, top); + } + }, + + /** + * @private + * @param {String} method + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Number} lineIndex + * @param {Number} i + * @param {String} _char + * @param {Number} left Left coordinate + * @param {Number} top Top coordinate + * @param {Number} lineHeight Height of the line + */ + _renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) { + var decl, charWidth, charHeight; + + if (this.styles && this.styles[lineIndex] && (decl = this.styles[lineIndex][i])) { + + var shouldStroke = decl.stroke || this.stroke, + shouldFill = decl.fill || this.fill; + + ctx.save(); + charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i, decl); + charHeight = this._getHeightOfChar(ctx, _char, lineIndex, i); + + if (shouldFill) { + ctx.fillText(_char, left, top); + } + if (shouldStroke) { + ctx.strokeText(_char, left, top); + } + + this._renderCharDecoration(ctx, decl, left, top, charWidth, lineHeight, charHeight); + ctx.restore(); + + ctx.translate(charWidth, 0); + } + else { + if (method === 'strokeText' && this.stroke) { + ctx[method](_char, left, top); + } + if (method === 'fillText' && this.fill) { + ctx[method](_char, left, top); + } + charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i); + this._renderCharDecoration(ctx, null, left, top, charWidth, lineHeight); + + ctx.translate(ctx.measureText(_char).width, 0); + } + }, + + /** + * @private + * @param {Object} prevStyle + * @param {Object} thisStyle + */ + _hasStyleChanged: function(prevStyle, thisStyle) { + return (prevStyle.fill !== thisStyle.fill || + prevStyle.fontSize !== thisStyle.fontSize || + prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor || + prevStyle.textDecoration !== thisStyle.textDecoration || + prevStyle.fontFamily !== thisStyle.fontFamily || + prevStyle.fontWeight !== thisStyle.fontWeight || + prevStyle.fontStyle !== thisStyle.fontStyle || + prevStyle.stroke !== thisStyle.stroke || + prevStyle.strokeWidth !== thisStyle.strokeWidth + ); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderCharDecoration: function(ctx, styleDeclaration, left, top, charWidth, lineHeight, charHeight) { + + var textDecoration = styleDeclaration + ? (styleDeclaration.textDecoration || this.textDecoration) + : this.textDecoration, + + fontSize = (styleDeclaration ? styleDeclaration.fontSize : null) || this.fontSize; + + if (!textDecoration) { + return; + } + + if (textDecoration.indexOf('underline') > -1) { + this._renderCharDecorationAtOffset( + ctx, + left, + top + (this.fontSize / this._fontSizeFraction), + charWidth, + 0, + this.fontSize / 20 + ); + } + if (textDecoration.indexOf('line-through') > -1) { + this._renderCharDecorationAtOffset( + ctx, + left, + top + (this.fontSize / this._fontSizeFraction), + charWidth, + charHeight / 2, + fontSize / 20 + ); + } + if (textDecoration.indexOf('overline') > -1) { + this._renderCharDecorationAtOffset( + ctx, + left, + top, + charWidth, + lineHeight - (this.fontSize / this._fontSizeFraction), + this.fontSize / 20 + ); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderCharDecorationAtOffset: function(ctx, left, top, charWidth, offset, thickness) { + ctx.fillRect(left, top - offset, charWidth, thickness); + }, + + /** + * @private + * @param {String} method + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line + */ + _renderTextLine: function(method, ctx, line, left, top, lineIndex) { + // to "cancel" this.fontSize subtraction in fabric.Text#_renderTextLine + top += this.fontSize / 4; + this.callSuper('_renderTextLine', method, ctx, line, left, top, lineIndex); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines + */ + _renderTextDecoration: function(ctx, textLines) { + if (this.isEmptyStyles()) { + return this.callSuper('_renderTextDecoration', ctx, textLines); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextLinesBackground: function(ctx, textLines) { + if (!this.textBackgroundColor && !this.styles) { + return; + } + + ctx.save(); + + if (this.textBackgroundColor) { + ctx.fillStyle = this.textBackgroundColor; + } + + var lineHeights = 0, + fractionOfFontSize = this.fontSize / this._fontSizeFraction; + + for (var i = 0, len = textLines.length; i < len; i++) { + + var heightOfLine = this._getHeightOfLine(ctx, i, textLines); + if (textLines[i] === '') { + lineHeights += heightOfLine; + continue; + } + + var lineWidth = this._getWidthOfLine(ctx, i, textLines), + lineLeftOffset = this._getLineLeftOffset(lineWidth); + + if (this.textBackgroundColor) { + ctx.fillStyle = this.textBackgroundColor; + + ctx.fillRect( + this._getLeftOffset() + lineLeftOffset, + this._getTopOffset() + lineHeights + fractionOfFontSize, + lineWidth, + heightOfLine + ); + } + if (this.styles[i]) { + for (var j = 0, jlen = textLines[i].length; j < jlen; j++) { + if (this.styles[i] && this.styles[i][j] && this.styles[i][j].textBackgroundColor) { + + var _char = textLines[i][j]; + + ctx.fillStyle = this.styles[i][j].textBackgroundColor; + + ctx.fillRect( + this._getLeftOffset() + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j, textLines), + this._getTopOffset() + lineHeights + fractionOfFontSize, + this._getWidthOfChar(ctx, _char, i, j, textLines) + 1, + heightOfLine + ); + } + } + } + lineHeights += heightOfLine; + } + ctx.restore(); + }, + + /** + * @private + */ + _getCacheProp: function(_char, styleDeclaration) { + return _char + + + styleDeclaration.fontFamily + + styleDeclaration.fontSize + + styleDeclaration.fontWeight + + styleDeclaration.fontStyle + + + styleDeclaration.shadow; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} _char + * @param {Number} lineIndex + * @param {Number} charIndex + * @param {Object} [decl] + */ + _applyCharStylesGetWidth: function(ctx, _char, lineIndex, charIndex, decl) { + var styleDeclaration = decl || + (this.styles[lineIndex] && + this.styles[lineIndex][charIndex]); + + if (styleDeclaration) { + // cloning so that original style object is not polluted with following font declarations + styleDeclaration = clone(styleDeclaration); + } + else { + styleDeclaration = { }; + } + + this._applyFontStyles(styleDeclaration); + + var cacheProp = this._getCacheProp(_char, styleDeclaration); + + // short-circuit if no styles + if (this.isEmptyStyles() && this._charWidthsCache[cacheProp] && this.caching) { + return this._charWidthsCache[cacheProp]; + } + + if (typeof styleDeclaration.shadow === 'string') { + styleDeclaration.shadow = new fabric.Shadow(styleDeclaration.shadow); + } + + var fill = styleDeclaration.fill || this.fill; + ctx.fillStyle = fill.toLive + ? fill.toLive(ctx) + : fill; + + if (styleDeclaration.stroke) { + ctx.strokeStyle = (styleDeclaration.stroke && styleDeclaration.stroke.toLive) + ? styleDeclaration.stroke.toLive(ctx) + : styleDeclaration.stroke; + } + + ctx.lineWidth = styleDeclaration.strokeWidth || this.strokeWidth; + ctx.font = this._getFontDeclaration.call(styleDeclaration); + this._setShadow.call(styleDeclaration, ctx); + + if (!this.caching) { + return ctx.measureText(_char).width; + } + + if (!this._charWidthsCache[cacheProp]) { + this._charWidthsCache[cacheProp] = ctx.measureText(_char).width; + } + + return this._charWidthsCache[cacheProp]; + }, + + /** + * @private + * @param {Object} styleDeclaration + */ + _applyFontStyles: function(styleDeclaration) { + if (!styleDeclaration.fontFamily) { + styleDeclaration.fontFamily = this.fontFamily; + } + if (!styleDeclaration.fontSize) { + styleDeclaration.fontSize = this.fontSize; + } + if (!styleDeclaration.fontWeight) { + styleDeclaration.fontWeight = this.fontWeight; + } + if (!styleDeclaration.fontStyle) { + styleDeclaration.fontStyle = this.fontStyle; + } + }, + + /** + * @private + * @param {Number} lineIndex + * @param {Number} charIndex + */ + _getStyleDeclaration: function(lineIndex, charIndex) { + return (this.styles[lineIndex] && this.styles[lineIndex][charIndex]) + ? clone(this.styles[lineIndex][charIndex]) + : { }; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfChar: function(ctx, _char, lineIndex, charIndex) { + var styleDeclaration = this._getStyleDeclaration(lineIndex, charIndex); + this._applyFontStyles(styleDeclaration); + var cacheProp = this._getCacheProp(_char, styleDeclaration); + + if (this._charWidthsCache[cacheProp] && this.caching) { + return this._charWidthsCache[cacheProp]; + } + else if (ctx) { + ctx.save(); + var width = this._applyCharStylesGetWidth(ctx, _char, lineIndex, charIndex); + ctx.restore(); + return width; + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getHeightOfChar: function(ctx, _char, lineIndex, charIndex) { + if (this.styles[lineIndex] && this.styles[lineIndex][charIndex]) { + return this.styles[lineIndex][charIndex].fontSize || this.fontSize; + } + return this.fontSize; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfCharAt: function(ctx, lineIndex, charIndex, lines) { + lines = lines || this.text.split(this._reNewline); + var _char = lines[lineIndex].split('')[charIndex]; + return this._getWidthOfChar(ctx, _char, lineIndex, charIndex); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getHeightOfCharAt: function(ctx, lineIndex, charIndex, lines) { + lines = lines || this.text.split(this._reNewline); + var _char = lines[lineIndex].split('')[charIndex]; + return this._getHeightOfChar(ctx, _char, lineIndex, charIndex); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfCharsAt: function(ctx, lineIndex, charIndex, lines) { + var width = 0; + for (var i = 0; i < charIndex; i++) { + width += this._getWidthOfCharAt(ctx, lineIndex, i, lines); + } + return width; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfLine: function(ctx, lineIndex, textLines) { + // if (!this.styles[lineIndex]) { + // return this.callSuper('_getLineWidth', ctx, textLines[lineIndex]); + // } + return this._getWidthOfCharsAt(ctx, lineIndex, textLines[lineIndex].length, textLines); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getTextWidth: function(ctx, textLines) { + + if (this.isEmptyStyles()) { + return this.callSuper('_getTextWidth', ctx, textLines); + } + + var maxWidth = this._getWidthOfLine(ctx, 0, textLines); + + for (var i = 1, len = textLines.length; i < len; i++) { + var currentLineWidth = this._getWidthOfLine(ctx, i, textLines); + if (currentLineWidth > maxWidth) { + maxWidth = currentLineWidth; + } + } + return maxWidth; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getHeightOfLine: function(ctx, lineIndex, textLines) { + + textLines = textLines || this.text.split(this._reNewline); + + var maxHeight = this._getHeightOfChar(ctx, textLines[lineIndex][0], lineIndex, 0), + line = textLines[lineIndex], + chars = line.split(''); + + for (var i = 1, len = chars.length; i < len; i++) { + var currentCharHeight = this._getHeightOfChar(ctx, chars[i], lineIndex, i); + if (currentCharHeight > maxHeight) { + maxHeight = currentCharHeight; + } + } + + return maxHeight * this.lineHeight; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _getTextHeight: function(ctx, textLines) { + var height = 0; + for (var i = 0, len = textLines.length; i < len; i++) { + height += this._getHeightOfLine(ctx, i, textLines); + } + return height; + }, + + /** + * @private + */ + _getTopOffset: function() { + var topOffset = fabric.Text.prototype._getTopOffset.call(this); + return topOffset - (this.fontSize / this._fontSizeFraction); + }, + + /** + * This method is overwritten to account for different top offset + * @private + */ + _renderTextBoxBackground: function(ctx) { + if (!this.backgroundColor) { + return; + } + + ctx.save(); + ctx.fillStyle = this.backgroundColor; + + ctx.fillRect( + this._getLeftOffset(), + this._getTopOffset() + (this.fontSize / this._fontSizeFraction), + this.width, + this.height + ); + + ctx.restore(); + }, + + /** + * Returns object representation of an instance + * @method toObject + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), { + styles: clone(this.styles) + }); + } + }); + + /** + * Returns fabric.IText instance from an object representation + * @static + * @memberOf fabric.IText + * @param {Object} object Object to create an instance from + * @return {fabric.IText} instance of fabric.IText + */ + fabric.IText.fromObject = function(object) { + return new fabric.IText(object.text, clone(object)); + }; + + /** + * Contains all fabric.IText objects that have been created + * @static + * @memberof fabric.IText + * @type Array + */ + fabric.IText.instances = [ ]; + +})(); + + +(function() { + + var clone = fabric.util.object.clone; + + fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + + /** + * Initializes all the interactive behavior of IText + */ + initBehavior: function() { + this.initAddedHandler(); + this.initCursorSelectionHandlers(); + this.initDoubleClickSimulation(); + }, + + /** + * Initializes "selected" event handler + */ + initSelectedHandler: function() { + this.on('selected', function() { + + var _this = this; + setTimeout(function() { + _this.selected = true; + }, 100); + }); + }, + + /** + * Initializes "added" event handler + */ + initAddedHandler: function() { + this.on('added', function() { + if (this.canvas && !this.canvas._hasITextHandlers) { + this.canvas._hasITextHandlers = true; + this._initCanvasHandlers(); + } + }); + }, + + /** + * @private + */ + _initCanvasHandlers: function() { + this.canvas.on('selection:cleared', function() { + fabric.IText.prototype.exitEditingOnOthers.call(); + }); + + this.canvas.on('mouse:up', function() { + fabric.IText.instances.forEach(function(obj) { + obj.__isMousedown = false; + }); + }); + + this.canvas.on('object:selected', function(options) { + fabric.IText.prototype.exitEditingOnOthers.call(options.target); + }); + }, + + /** + * @private + */ + _tick: function() { + if (this._abortCursorAnimation) { + return; + } + + var _this = this; + + this.animate('_currentCursorOpacity', 1, { + + duration: this.cursorDuration, + + onComplete: function() { + _this._onTickComplete(); + }, + + onChange: function() { + _this.canvas && _this.canvas.renderAll(); + }, + + abort: function() { + return _this._abortCursorAnimation; + } + }); + }, + + /** + * @private + */ + _onTickComplete: function() { + if (this._abortCursorAnimation) { + return; + } + + var _this = this; + if (this._cursorTimeout1) { + clearTimeout(this._cursorTimeout1); + } + this._cursorTimeout1 = setTimeout(function() { + _this.animate('_currentCursorOpacity', 0, { + duration: this.cursorDuration / 2, + onComplete: function() { + _this._tick(); + }, + onChange: function() { + _this.canvas && _this.canvas.renderAll(); + }, + abort: function() { + return _this._abortCursorAnimation; + } + }); + }, 100); + }, + + /** + * Initializes delayed cursor + */ + initDelayedCursor: function(restart) { + var _this = this, + delay = restart ? 0 : this.cursorDelay; + + if (restart) { + this._abortCursorAnimation = true; + clearTimeout(this._cursorTimeout1); + this._currentCursorOpacity = 1; + this.canvas && this.canvas.renderAll(); + } + if (this._cursorTimeout2) { + clearTimeout(this._cursorTimeout2); + } + this._cursorTimeout2 = setTimeout(function() { + _this._abortCursorAnimation = false; + _this._tick(); + }, delay); + }, + + /** + * Aborts cursor animation and clears all timeouts + */ + abortCursorAnimation: function() { + this._abortCursorAnimation = true; + + clearTimeout(this._cursorTimeout1); + clearTimeout(this._cursorTimeout2); + + this._currentCursorOpacity = 0; + this.canvas && this.canvas.renderAll(); + + var _this = this; + setTimeout(function() { + _this._abortCursorAnimation = false; + }, 10); + }, + + /** + * Selects entire text + */ + selectAll: function() { + this.selectionStart = 0; + this.selectionEnd = this.text.length; + this.fire('selection:changed'); + this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + }, + + /** + * Returns selected text + * @return {String} + */ + getSelectedText: function() { + return this.text.slice(this.selectionStart, this.selectionEnd); + }, + + /** + * Find new selection index representing start of current word according to current selection index + * @param {Number} startFrom Surrent selection index + * @return {Number} New selection index + */ + findWordBoundaryLeft: function(startFrom) { + var offset = 0, index = startFrom - 1; + + // remove space before cursor first + if (this._reSpace.test(this.text.charAt(index))) { + while (this._reSpace.test(this.text.charAt(index))) { + offset++; + index--; + } + } + while (/\S/.test(this.text.charAt(index)) && index > -1) { + offset++; + index--; + } + + return startFrom - offset; + }, + + /** + * Find new selection index representing end of current word according to current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index + */ + findWordBoundaryRight: function(startFrom) { + var offset = 0, index = startFrom; + + // remove space after cursor first + if (this._reSpace.test(this.text.charAt(index))) { + while (this._reSpace.test(this.text.charAt(index))) { + offset++; + index++; + } + } + while (/\S/.test(this.text.charAt(index)) && index < this.text.length) { + offset++; + index++; + } + + return startFrom + offset; + }, + + /** + * Find new selection index representing start of current line according to current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index + */ + findLineBoundaryLeft: function(startFrom) { + var offset = 0, index = startFrom - 1; + + while (!/\n/.test(this.text.charAt(index)) && index > -1) { + offset++; + index--; + } + + return startFrom - offset; + }, + + /** + * Find new selection index representing end of current line according to current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index + */ + findLineBoundaryRight: function(startFrom) { + var offset = 0, index = startFrom; + + while (!/\n/.test(this.text.charAt(index)) && index < this.text.length) { + offset++; + index++; + } + + return startFrom + offset; + }, + + /** + * Returns number of newlines in selected text + * @return {Number} Number of newlines in selected text + */ + getNumNewLinesInSelectedText: function() { + var selectedText = this.getSelectedText(), + numNewLines = 0; + + for (var i = 0, chars = selectedText.split(''), len = chars.length; i < len; i++) { + if (chars[i] === '\n') { + numNewLines++; + } + } + return numNewLines; + }, + + /** + * Finds index corresponding to beginning or end of a word + * @param {Number} selectionStart Index of a character + * @param {Number} direction: 1 or -1 + * @return {Number} Index of the beginning or end of a word + */ + searchWordBoundary: function(selectionStart, direction) { + var index = this._reSpace.test(this.text.charAt(selectionStart)) ? selectionStart - 1 : selectionStart, + _char = this.text.charAt(index), + reNonWord = /[ \n\.,;!\?\-]/; + + while (!reNonWord.test(_char) && index > 0 && index < this.text.length) { + index += direction; + _char = this.text.charAt(index); + } + if (reNonWord.test(_char) && _char !== '\n') { + index += direction === 1 ? 0 : 1; + } + return index; + }, + + /** + * Selects a word based on the index + * @param {Number} selectionStart Index of a character + */ + selectWord: function(selectionStart) { + var newSelectionStart = this.searchWordBoundary(selectionStart, -1), /* search backwards */ + newSelectionEnd = this.searchWordBoundary(selectionStart, 1); /* search forward */ + + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionEnd); + this.initDelayedCursor(true); + }, + + /** + * Selects a line based on the index + * @param {Number} selectionStart Index of a character + */ + selectLine: function(selectionStart) { + var newSelectionStart = this.findLineBoundaryLeft(selectionStart), + newSelectionEnd = this.findLineBoundaryRight(selectionStart); + + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionEnd); + this.initDelayedCursor(true); + }, + + /** + * Enters editing state + * @return {fabric.IText} thisArg + * @chainable + */ + enterEditing: function() { + if (this.isEditing || !this.editable) { + return; + } + + this.exitEditingOnOthers(); + + this.isEditing = true; + + this.initHiddenTextarea(); + this._updateTextarea(); + this._saveEditingProps(); + this._setEditingProps(); + + this._tick(); + this.canvas && this.canvas.renderAll(); + + this.fire('editing:entered'); + this.canvas && this.canvas.fire('text:editing:entered', { target: this }); + + return this; + }, + + exitEditingOnOthers: function() { + fabric.IText.instances.forEach(function(obj) { + obj.selected = false; + if (obj.isEditing) { + obj.exitEditing(); + } + }, this); + }, + + /** + * @private + */ + _setEditingProps: function() { + this.hoverCursor = 'text'; + + if (this.canvas) { + this.canvas.defaultCursor = this.canvas.moveCursor = 'text'; + } + + this.borderColor = this.editingBorderColor; + + this.hasControls = this.selectable = false; + this.lockMovementX = this.lockMovementY = true; + }, + + /** + * @private + */ + _updateTextarea: function() { + if (!this.hiddenTextarea) { + return; + } + + this.hiddenTextarea.value = this.text; + this.hiddenTextarea.selectionStart = this.selectionStart; + }, + + /** + * @private + */ + _saveEditingProps: function() { + this._savedProps = { + hasControls: this.hasControls, + borderColor: this.borderColor, + lockMovementX: this.lockMovementX, + lockMovementY: this.lockMovementY, + hoverCursor: this.hoverCursor, + defaultCursor: this.canvas && this.canvas.defaultCursor, + moveCursor: this.canvas && this.canvas.moveCursor + }; + }, + + /** + * @private + */ + _restoreEditingProps: function() { + if (!this._savedProps) { + return; + } + + this.hoverCursor = this._savedProps.overCursor; + this.hasControls = this._savedProps.hasControls; + this.borderColor = this._savedProps.borderColor; + this.lockMovementX = this._savedProps.lockMovementX; + this.lockMovementY = this._savedProps.lockMovementY; + + if (this.canvas) { + this.canvas.defaultCursor = this._savedProps.defaultCursor; + this.canvas.moveCursor = this._savedProps.moveCursor; + } + }, + + /** + * Exits from editing state + * @return {fabric.IText} thisArg + * @chainable + */ + exitEditing: function() { + + this.selected = false; + this.isEditing = false; + this.selectable = true; + + this.selectionEnd = this.selectionStart; + this.hiddenTextarea && this.canvas && this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea); + this.hiddenTextarea = null; + + this.abortCursorAnimation(); + this._restoreEditingProps(); + this._currentCursorOpacity = 0; + + this.fire('editing:exited'); + this.canvas && this.canvas.fire('text:editing:exited', { target: this }); + + return this; + }, + + /** + * @private + */ + _removeExtraneousStyles: function() { + var textLines = this.text.split(this._reNewline); + for (var prop in this.styles) { + if (!textLines[prop]) { + delete this.styles[prop]; + } + } + }, + + /** + * @private + */ + _removeCharsFromTo: function(start, end) { + + var i = end; + while (i !== start) { + + var prevIndex = this.get2DCursorLocation(i).charIndex; + i--; + + var index = this.get2DCursorLocation(i).charIndex, + isNewline = index > prevIndex; + + if (isNewline) { + this.removeStyleObject(isNewline, i + 1); + } + else { + this.removeStyleObject(this.get2DCursorLocation(i).charIndex === 0, i); + } + + } + + this.text = this.text.slice(0, start) + + this.text.slice(end); + }, + + /** + * Inserts a character where cursor is (replacing selection if one exists) + * @param {String} _chars Characters to insert + */ + insertChars: function(_chars) { + var isEndOfLine = this.text.slice(this.selectionStart, this.selectionStart + 1) === '\n'; + + this.text = this.text.slice(0, this.selectionStart) + + _chars + + this.text.slice(this.selectionEnd); + + if (this.selectionStart === this.selectionEnd) { + this.insertStyleObjects(_chars, isEndOfLine, this.copiedStyles); + } + // else if (this.selectionEnd - this.selectionStart > 1) { + // TODO: replace styles properly + // console.log('replacing MORE than 1 char'); + // } + + this.selectionStart += _chars.length; + this.selectionEnd = this.selectionStart; + + if (this.canvas) { + // TODO: double renderAll gets rid of text box shift happenning sometimes + // need to find out what exactly causes it and fix it + this.canvas.renderAll().renderAll(); + } + + this.setCoords(); + this.fire('changed'); + this.canvas && this.canvas.fire('text:changed', { target: this }); + }, + + /** + * Inserts new style object + * @param {Number} lineIndex Index of a line + * @param {Number} charIndex Index of a char + * @param {Boolean} isEndOfLine True if it's end of line + */ + insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) { + + this.shiftLineStyles(lineIndex, +1); + + if (!this.styles[lineIndex + 1]) { + this.styles[lineIndex + 1] = { }; + } + + var currentCharStyle = this.styles[lineIndex][charIndex - 1], + newLineStyles = { }; + + // if there's nothing after cursor, + // we clone current char style onto the next (otherwise empty) line + if (isEndOfLine) { + newLineStyles[0] = clone(currentCharStyle); + this.styles[lineIndex + 1] = newLineStyles; + } + // otherwise we clone styles of all chars + // after cursor onto the next line, from the beginning + else { + for (var index in this.styles[lineIndex]) { + if (parseInt(index, 10) >= charIndex) { + newLineStyles[parseInt(index, 10) - charIndex] = this.styles[lineIndex][index]; + // remove lines from the previous line since they're on a new line now + delete this.styles[lineIndex][index]; + } + } + this.styles[lineIndex + 1] = newLineStyles; + } + }, + + /** + * Inserts style object for a given line/char index + * @param {Number} lineIndex Index of a line + * @param {Number} charIndex Index of a char + * @param {Object} [style] Style object to insert, if given + */ + insertCharStyleObject: function(lineIndex, charIndex, style) { + + var currentLineStyles = this.styles[lineIndex], + currentLineStylesCloned = clone(currentLineStyles); + + if (charIndex === 0 && !style) { + charIndex = 1; + } + + // shift all char styles by 1 forward + // 0,1,2,3 -> (charIndex=2) -> 0,1,3,4 -> (insert 2) -> 0,1,2,3,4 + for (var index in currentLineStylesCloned) { + var numericIndex = parseInt(index, 10); + if (numericIndex >= charIndex) { + currentLineStyles[numericIndex + 1] = currentLineStylesCloned[numericIndex]; + //delete currentLineStyles[index]; + } + } + + this.styles[lineIndex][charIndex] = + style || clone(currentLineStyles[charIndex - 1]); + }, + + /** + * Inserts style object(s) + * @param {String} _chars Characters at the location where style is inserted + * @param {Boolean} isEndOfLine True if it's end of line + * @param {Array} [styles] Styles to insert + */ + insertStyleObjects: function(_chars, isEndOfLine, styles) { + + // short-circuit + if (this.isEmptyStyles()) { + return; + } + + var cursorLocation = this.get2DCursorLocation(), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex; + + if (!this.styles[lineIndex]) { + this.styles[lineIndex] = { }; + } + + if (_chars === '\n') { + this.insertNewlineStyleObject(lineIndex, charIndex, isEndOfLine); + } + else { + if (styles) { + this._insertStyles(styles); + } + else { + // TODO: support multiple style insertion if _chars.length > 1 + this.insertCharStyleObject(lineIndex, charIndex); + } + } + }, + + /** + * @private + */ + _insertStyles: function(styles) { + for (var i = 0, len = styles.length; i < len; i++) { + + var cursorLocation = this.get2DCursorLocation(this.selectionStart + i), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex; + + this.insertCharStyleObject(lineIndex, charIndex, styles[i]); + } + }, + + /** + * Shifts line styles up or down + * @param {Number} lineIndex Index of a line + * @param {Number} offset Can be -1 or +1 + */ + shiftLineStyles: function(lineIndex, offset) { + // shift all line styles by 1 upward + var clonedStyles = clone(this.styles); + for (var line in this.styles) { + var numericLine = parseInt(line, 10); + if (numericLine > lineIndex) { + this.styles[numericLine + offset] = clonedStyles[numericLine]; + } + } + }, + + /** + * Removes style object + * @param {Boolean} isBeginningOfLine True if cursor is at the beginning of line + * @param {Number} [index] Optional index. When not given, current selectionStart is used. + */ + removeStyleObject: function(isBeginningOfLine, index) { + + var cursorLocation = this.get2DCursorLocation(index), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex; + + if (isBeginningOfLine) { + + var textLines = this.text.split(this._reNewline), + textOnPreviousLine = textLines[lineIndex - 1], + newCharIndexOnPrevLine = textOnPreviousLine + ? textOnPreviousLine.length + : 0; + + if (!this.styles[lineIndex - 1]) { + this.styles[lineIndex - 1] = { }; + } + + for (charIndex in this.styles[lineIndex]) { + this.styles[lineIndex - 1][parseInt(charIndex, 10) + newCharIndexOnPrevLine] + = this.styles[lineIndex][charIndex]; + } + + this.shiftLineStyles(lineIndex, -1); + } + else { + var currentLineStyles = this.styles[lineIndex]; + + if (currentLineStyles) { + var offset = this.selectionStart === this.selectionEnd ? -1 : 0; + delete currentLineStyles[charIndex + offset]; + // console.log('deleting', lineIndex, charIndex + offset); + } + + var currentLineStylesCloned = clone(currentLineStyles); + + // shift all styles by 1 backwards + for (var i in currentLineStylesCloned) { + var numericIndex = parseInt(i, 10); + if (numericIndex >= charIndex && numericIndex !== 0) { + currentLineStyles[numericIndex - 1] = currentLineStylesCloned[numericIndex]; + delete currentLineStyles[numericIndex]; + } + } + } + }, + + /** + * Inserts new line + */ + insertNewline: function() { + this.insertChars('\n'); + } + }); +})(); + + +fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + /** + * Initializes "dbclick" event handler + */ + initDoubleClickSimulation: function() { + + // for double click + this.__lastClickTime = +new Date(); + + // for triple click + this.__lastLastClickTime = +new Date(); + + this.__lastPointer = { }; + + this.on('mousedown', this.onMouseDown.bind(this)); + }, + + onMouseDown: function(options) { + + this.__newClickTime = +new Date(); + var newPointer = this.canvas.getPointer(options.e); + + if (this.isTripleClick(newPointer)) { + this.fire('tripleclick', options); + this._stopEvent(options.e); + } + else if (this.isDoubleClick(newPointer)) { + this.fire('dblclick', options); + this._stopEvent(options.e); + } + + this.__lastLastClickTime = this.__lastClickTime; + this.__lastClickTime = this.__newClickTime; + this.__lastPointer = newPointer; + this.__lastIsEditing = this.isEditing; + this.__lastSelected = this.selected; + }, + + isDoubleClick: function(newPointer) { + return this.__newClickTime - this.__lastClickTime < 500 && + this.__lastPointer.x === newPointer.x && + this.__lastPointer.y === newPointer.y && this.__lastIsEditing; + }, + + isTripleClick: function(newPointer) { + return this.__newClickTime - this.__lastClickTime < 500 && + this.__lastClickTime - this.__lastLastClickTime < 500 && + this.__lastPointer.x === newPointer.x && + this.__lastPointer.y === newPointer.y; + }, + + /** + * @private + */ + _stopEvent: function(e) { + e.preventDefault && e.preventDefault(); + e.stopPropagation && e.stopPropagation(); + }, + + /** + * Initializes event handlers related to cursor or selection + */ + initCursorSelectionHandlers: function() { + this.initSelectedHandler(); + this.initMousedownHandler(); + this.initMousemoveHandler(); + this.initMouseupHandler(); + this.initClicks(); + }, + + /** + * Initializes double and triple click event handlers + */ + initClicks: function() { + this.on('dblclick', function(options) { + this.selectWord(this.getSelectionStartFromPointer(options.e)); + }); + this.on('tripleclick', function(options) { + this.selectLine(this.getSelectionStartFromPointer(options.e)); + }); + }, + + /** + * Initializes "mousedown" event handler + */ + initMousedownHandler: function() { + this.on('mousedown', function(options) { + + var pointer = this.canvas.getPointer(options.e); + + this.__mousedownX = pointer.x; + this.__mousedownY = pointer.y; + this.__isMousedown = true; + + if (this.hiddenTextarea && this.canvas) { + this.canvas.wrapperEl.appendChild(this.hiddenTextarea); + } + + if (this.selected) { + this.setCursorByClick(options.e); + } + + if (this.isEditing) { + this.__selectionStartOnMouseDown = this.selectionStart; + this.initDelayedCursor(true); + } + }); + }, + + /** + * Initializes "mousemove" event handler + */ + initMousemoveHandler: function() { + this.on('mousemove', function(options) { + if (!this.__isMousedown || !this.isEditing) { + return; + } + + var newSelectionStart = this.getSelectionStartFromPointer(options.e); + + if (newSelectionStart >= this.__selectionStartOnMouseDown) { + this.setSelectionStart(this.__selectionStartOnMouseDown); + this.setSelectionEnd(newSelectionStart); + } + else { + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(this.__selectionStartOnMouseDown); + } + }); + }, + + /** + * @private + */ + _isObjectMoved: function(e) { + var pointer = this.canvas.getPointer(e); + + return this.__mousedownX !== pointer.x || + this.__mousedownY !== pointer.y; + }, + + /** + * Initializes "mouseup" event handler + */ + initMouseupHandler: function() { + this.on('mouseup', function(options) { + this.__isMousedown = false; + if (this._isObjectMoved(options.e)) { + return; + } + + if (this.__lastSelected) { + this.enterEditing(); + this.initDelayedCursor(true); + } + this.selected = true; + }); + }, + + /** + * Changes cursor location in a text depending on passed pointer (x/y) object + * @param {Event} e Event object + */ + setCursorByClick: function(e) { + var newSelectionStart = this.getSelectionStartFromPointer(e); + + if (e.shiftKey) { + if (newSelectionStart < this.selectionStart) { + this.setSelectionEnd(this.selectionStart); + this.setSelectionStart(newSelectionStart); + } + else { + this.setSelectionEnd(newSelectionStart); + } + } + else { + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionStart); + } + }, + + /** + * @private + * @param {Event} e Event object + * @return {Object} Coordinates of a pointer (x, y) + */ + _getLocalRotatedPointer: function(e) { + var pointer = this.canvas.getPointer(e), + + pClicked = new fabric.Point(pointer.x, pointer.y), + pLeftTop = new fabric.Point(this.left, this.top), + + rotated = fabric.util.rotatePoint( + pClicked, pLeftTop, fabric.util.degreesToRadians(-this.angle)); + + return this.getLocalPointer(e, rotated); + }, + + /** + * Returns index of a character corresponding to where an object was clicked + * @param {Event} e Event object + * @return {Number} Index of a character + */ + getSelectionStartFromPointer: function(e) { + var mouseOffset = this._getLocalRotatedPointer(e), + textLines = this.text.split(this._reNewline), + prevWidth = 0, + width = 0, + height = 0, + charIndex = 0, + newSelectionStart; + + for (var i = 0, len = textLines.length; i < len; i++) { + + height += this._getHeightOfLine(this.ctx, i) * this.scaleY; + + var widthOfLine = this._getWidthOfLine(this.ctx, i, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfLine); + + width = lineLeftOffset * this.scaleX; + + if (this.flipX) { + // when oject is horizontally flipped we reverse chars + textLines[i] = textLines[i].split('').reverse().join(''); + } + + for (var j = 0, jlen = textLines[i].length; j < jlen; j++) { + + var _char = textLines[i][j]; + prevWidth = width; + + width += this._getWidthOfChar(this.ctx, _char, i, this.flipX ? jlen - j : j) * + this.scaleX; + + if (height <= mouseOffset.y || width <= mouseOffset.x) { + charIndex++; + continue; + } + + return this._getNewSelectionStartFromOffset( + mouseOffset, prevWidth, width, charIndex + i, jlen); + } + + if (mouseOffset.y < height) { + return this._getNewSelectionStartFromOffset( + mouseOffset, prevWidth, width, charIndex + i, jlen); + } + } + + // clicked somewhere after all chars, so set at the end + if (typeof newSelectionStart === 'undefined') { + return this.text.length; + } + }, + + /** + * @private + */ + _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen) { + + var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth, + distanceBtwNextCharAndCursor = width - mouseOffset.x, + offset = distanceBtwNextCharAndCursor > distanceBtwLastCharAndCursor ? 0 : 1, + newSelectionStart = index + offset; + + // if object is horizontally flipped, mirror cursor location from the end + if (this.flipX) { + newSelectionStart = jlen - newSelectionStart; + } + + if (newSelectionStart > this.text.length) { + newSelectionStart = this.text.length; + } + + return newSelectionStart; + } +}); + + +fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + + /** + * Initializes hidden textarea (needed to bring up keyboard in iOS) + */ + initHiddenTextarea: function() { + this.hiddenTextarea = fabric.document.createElement('textarea'); + + this.hiddenTextarea.setAttribute('autocapitalize', 'off'); + this.hiddenTextarea.style.cssText = 'position: absolute; top: 0; left: -9999px'; + + fabric.document.body.appendChild(this.hiddenTextarea); + + fabric.util.addListener(this.hiddenTextarea, 'keydown', this.onKeyDown.bind(this)); + fabric.util.addListener(this.hiddenTextarea, 'keypress', this.onKeyPress.bind(this)); + fabric.util.addListener(this.hiddenTextarea, 'copy', this.copy.bind(this)); + fabric.util.addListener(this.hiddenTextarea, 'paste', this.paste.bind(this)); + + if (!this._clickHandlerInitialized && this.canvas) { + fabric.util.addListener(this.canvas.upperCanvasEl, 'click', this.onClick.bind(this)); + this._clickHandlerInitialized = true; + } + }, + + /** + * @private + */ + _keysMap: { + 8: 'removeChars', + 13: 'insertNewline', + 37: 'moveCursorLeft', + 38: 'moveCursorUp', + 39: 'moveCursorRight', + 40: 'moveCursorDown', + 46: 'forwardDelete' + }, + + /** + * @private + */ + _ctrlKeysMap: { + 65: 'selectAll', + 88: 'cut' + }, + + onClick: function() { + // No need to trigger click event here, focus is enough to have the keyboard appear on Android + this.hiddenTextarea && this.hiddenTextarea.focus(); + }, + + /** + * Handles keyup event + * @param {Event} e Event object + */ + onKeyDown: function(e) { + if (!this.isEditing) { + return; + } + + if (e.keyCode in this._keysMap && e.charCode === 0) { + this[this._keysMap[e.keyCode]](e); + } + else if ((e.keyCode in this._ctrlKeysMap) && (e.ctrlKey || e.metaKey)) { + this[this._ctrlKeysMap[e.keyCode]](e); + } + else { + return; + } + + e.stopPropagation(); + + this.canvas && this.canvas.renderAll(); + }, + + /** + * Forward delete + */ + forwardDelete: function(e) { + if (this.selectionStart === this.selectionEnd) { + this.moveCursorRight(e); + } + this.removeChars(e); + }, + + /** + * Copies selected text + * @param {Event} e Event object + */ + copy: function(e) { + var selectedText = this.getSelectedText(), + clipboardData = this._getClipboardData(e); + + // Check for backward compatibility with old browsers + if (clipboardData) { + clipboardData.setData('text', selectedText); + } + + this.copiedText = selectedText; + this.copiedStyles = this.getSelectionStyles( + this.selectionStart, + this.selectionEnd); + }, + + /** + * Pastes text + * @param {Event} e Event object + */ + paste: function(e) { + var copiedText = null, + clipboardData = this._getClipboardData(e); + + // Check for backward compatibility with old browsers + if (clipboardData) { + copiedText = clipboardData.getData('text'); + } + else { + copiedText = this.copiedText; + } + + if (copiedText) { + this.insertChars(copiedText); + } + }, + + /** + * Cuts text + * @param {Event} e Event object + */ + cut: function(e) { + if (this.selectionStart === this.selectionEnd) { + return; + } + + this.copy(); + this.removeChars(e); + }, + + /** + * @private + * @param {Event} e Event object + * @return {Object} Clipboard data object + */ + _getClipboardData: function(e) { + return e && (e.clipboardData || fabric.window.clipboardData); + }, + + /** + * Handles keypress event + * @param {Event} e Event object + */ + onKeyPress: function(e) { + if (!this.isEditing || e.metaKey || e.ctrlKey || ( e.keyCode in this._keysMap && e.charCode === 0 )) { + return; + } + + this.insertChars(String.fromCharCode(e.which)); + + e.stopPropagation(); + }, + + /** + * Gets start offset of a selection + * @param {Event} e Event object + * @param {Boolean} isRight + * @return {Number} + */ + getDownCursorOffset: function(e, isRight) { + var selectionProp = isRight ? this.selectionEnd : this.selectionStart, + textLines = this.text.split(this._reNewline), + _char, + lineLeftOffset, + + textBeforeCursor = this.text.slice(0, selectionProp), + textAfterCursor = this.text.slice(selectionProp), + + textOnSameLineBeforeCursor = textBeforeCursor.slice(textBeforeCursor.lastIndexOf('\n') + 1), + textOnSameLineAfterCursor = textAfterCursor.match(/(.*)\n?/)[1], + textOnNextLine = (textAfterCursor.match(/.*\n(.*)\n?/) || { })[1] || '', + + cursorLocation = this.get2DCursorLocation(selectionProp); + + // if on last line, down cursor goes to end of line + if (cursorLocation.lineIndex === textLines.length - 1 || e.metaKey) { + + // move to the end of a text + return this.text.length - selectionProp; + } + + var widthOfSameLineBeforeCursor = this._getWidthOfLine(this.ctx, cursorLocation.lineIndex, textLines); + lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor); + + var widthOfCharsOnSameLineBeforeCursor = lineLeftOffset, + lineIndex = cursorLocation.lineIndex; + + for (var i = 0, len = textOnSameLineBeforeCursor.length; i < len; i++) { + _char = textOnSameLineBeforeCursor[i]; + widthOfCharsOnSameLineBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i); + } + + var indexOnNextLine = this._getIndexOnNextLine( + cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines); + + return textOnSameLineAfterCursor.length + 1 + indexOnNextLine; + }, + + /** + * @private + */ + _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines) { + var lineIndex = cursorLocation.lineIndex + 1, + widthOfNextLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfNextLine), + widthOfCharsOnNextLine = lineLeftOffset, + indexOnNextLine = 0, + foundMatch; + + for (var j = 0, jlen = textOnNextLine.length; j < jlen; j++) { + + var _char = textOnNextLine[j], + widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j); + + widthOfCharsOnNextLine += widthOfChar; + + if (widthOfCharsOnNextLine > widthOfCharsOnSameLineBeforeCursor) { + + foundMatch = true; + + var leftEdge = widthOfCharsOnNextLine - widthOfChar, + rightEdge = widthOfCharsOnNextLine, + offsetFromLeftEdge = Math.abs(leftEdge - widthOfCharsOnSameLineBeforeCursor), + offsetFromRightEdge = Math.abs(rightEdge - widthOfCharsOnSameLineBeforeCursor); + + indexOnNextLine = offsetFromRightEdge < offsetFromLeftEdge ? j + 1 : j; + + break; + } + } + + // reached end + if (!foundMatch) { + indexOnNextLine = textOnNextLine.length; + } + + return indexOnNextLine; + }, + + /** + * Moves cursor down + * @param {Event} e Event object + */ + moveCursorDown: function(e) { + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + var offset = this.getDownCursorOffset(e, this._selectionDirection === 'right'); + + if (e.shiftKey) { + this.moveCursorDownWithShift(offset); + } + else { + this.moveCursorDownWithoutShift(offset); + } + + this.initDelayedCursor(); + }, + + /** + * Moves cursor down without keeping selection + * @param {Number} offset + */ + moveCursorDownWithoutShift: function(offset) { + this._selectionDirection = 'right'; + this.selectionStart += offset; + + if (this.selectionStart > this.text.length) { + this.selectionStart = this.text.length; + } + this.selectionEnd = this.selectionStart; + }, + + /** + * Moves cursor down while keeping selection + * @param {Number} offset + */ + moveCursorDownWithShift: function(offset) { + if (this._selectionDirection === 'left' && (this.selectionStart !== this.selectionEnd)) { + this.selectionStart += offset; + this._selectionDirection = 'left'; + return; + } + else { + this._selectionDirection = 'right'; + this.selectionEnd += offset; + + if (this.selectionEnd > this.text.length) { + this.selectionEnd = this.text.length; + } + } + }, + + /** + * @param {Event} e Event object + * @param {Boolean} isRight + * @return {Number} + */ + getUpCursorOffset: function(e, isRight) { + var selectionProp = isRight ? this.selectionEnd : this.selectionStart, + cursorLocation = this.get2DCursorLocation(selectionProp); + + // if on first line, up cursor goes to start of line + if (cursorLocation.lineIndex === 0 || e.metaKey) { + return selectionProp; + } + + var textBeforeCursor = this.text.slice(0, selectionProp), + textOnSameLineBeforeCursor = textBeforeCursor.slice(textBeforeCursor.lastIndexOf('\n') + 1), + textOnPreviousLine = (textBeforeCursor.match(/\n?(.*)\n.*$/) || {})[1] || '', + textLines = this.text.split(this._reNewline), + _char, + widthOfSameLineBeforeCursor = this._getWidthOfLine(this.ctx, cursorLocation.lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor), + widthOfCharsOnSameLineBeforeCursor = lineLeftOffset, + lineIndex = cursorLocation.lineIndex; + + for (var i = 0, len = textOnSameLineBeforeCursor.length; i < len; i++) { + _char = textOnSameLineBeforeCursor[i]; + widthOfCharsOnSameLineBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i); + } + + var indexOnPrevLine = this._getIndexOnPrevLine( + cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor, textLines); + + return textOnPreviousLine.length - indexOnPrevLine + textOnSameLineBeforeCursor.length; + }, + + /** + * @private + */ + _getIndexOnPrevLine: function(cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor, textLines) { + + var lineIndex = cursorLocation.lineIndex - 1, + widthOfPreviousLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfPreviousLine), + widthOfCharsOnPreviousLine = lineLeftOffset, + indexOnPrevLine = 0, + foundMatch; + + for (var j = 0, jlen = textOnPreviousLine.length; j < jlen; j++) { + + var _char = textOnPreviousLine[j], + widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j); + + widthOfCharsOnPreviousLine += widthOfChar; + + if (widthOfCharsOnPreviousLine > widthOfCharsOnSameLineBeforeCursor) { + + foundMatch = true; + + var leftEdge = widthOfCharsOnPreviousLine - widthOfChar, + rightEdge = widthOfCharsOnPreviousLine, + offsetFromLeftEdge = Math.abs(leftEdge - widthOfCharsOnSameLineBeforeCursor), + offsetFromRightEdge = Math.abs(rightEdge - widthOfCharsOnSameLineBeforeCursor); + + indexOnPrevLine = offsetFromRightEdge < offsetFromLeftEdge ? j : (j - 1); + + break; + } + } + + // reached end + if (!foundMatch) { + indexOnPrevLine = textOnPreviousLine.length - 1; + } + + return indexOnPrevLine; + }, + + /** + * Moves cursor up + * @param {Event} e Event object + */ + moveCursorUp: function(e) { + + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + var offset = this.getUpCursorOffset(e, this._selectionDirection === 'right'); + + if (e.shiftKey) { + this.moveCursorUpWithShift(offset); + } + else { + this.moveCursorUpWithoutShift(offset); + } + + this.initDelayedCursor(); + }, + + /** + * Moves cursor up with shift + * @param {Number} offset + */ + moveCursorUpWithShift: function(offset) { + + if (this.selectionStart === this.selectionEnd) { + this.selectionStart -= offset; + } + else { + if (this._selectionDirection === 'right') { + this.selectionEnd -= offset; + this._selectionDirection = 'right'; + return; + } + else { + this.selectionStart -= offset; + } + } + + if (this.selectionStart < 0) { + this.selectionStart = 0; + } + + this._selectionDirection = 'left'; + }, + + /** + * Moves cursor up without shift + * @param {Number} offset + */ + moveCursorUpWithoutShift: function(offset) { + if (this.selectionStart === this.selectionEnd) { + this.selectionStart -= offset; + } + if (this.selectionStart < 0) { + this.selectionStart = 0; + } + this.selectionEnd = this.selectionStart; + + this._selectionDirection = 'left'; + }, + + /** + * Moves cursor left + * @param {Event} e Event object + */ + moveCursorLeft: function(e) { + if (this.selectionStart === 0 && this.selectionEnd === 0) { + return; + } + + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + if (e.shiftKey) { + this.moveCursorLeftWithShift(e); + } + else { + this.moveCursorLeftWithoutShift(e); + } + + this.initDelayedCursor(); + }, + + /** + * @private + */ + _move: function(e, prop, direction) { + if (e.altKey) { + this[prop] = this['findWordBoundary' + direction](this[prop]); + } + else if (e.metaKey) { + this[prop] = this['findLineBoundary' + direction](this[prop]); + } + else { + this[prop] += (direction === 'Left' ? -1 : 1); + } + }, + + /** + * @private + */ + _moveLeft: function(e, prop) { + this._move(e, prop, 'Left'); + }, + + /** + * @private + */ + _moveRight: function(e, prop) { + this._move(e, prop, 'Right'); + }, + + /** + * Moves cursor left without keeping selection + * @param {Event} e + */ + moveCursorLeftWithoutShift: function(e) { + this._selectionDirection = 'left'; + + // only move cursor when there is no selection, + // otherwise we discard it, and leave cursor on same place + if (this.selectionEnd === this.selectionStart) { + this._moveLeft(e, 'selectionStart'); + } + this.selectionEnd = this.selectionStart; + }, + + /** + * Moves cursor left while keeping selection + * @param {Event} e + */ + moveCursorLeftWithShift: function(e) { + if (this._selectionDirection === 'right' && this.selectionStart !== this.selectionEnd) { + this._moveLeft(e, 'selectionEnd'); + } + else { + this._selectionDirection = 'left'; + this._moveLeft(e, 'selectionStart'); + + // increase selection by one if it's a newline + if (this.text.charAt(this.selectionStart) === '\n') { + this.selectionStart--; + } + if (this.selectionStart < 0) { + this.selectionStart = 0; + } + } + }, + + /** + * Moves cursor right + * @param {Event} e Event object + */ + moveCursorRight: function(e) { + if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) { + return; + } + + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + if (e.shiftKey) { + this.moveCursorRightWithShift(e); + } + else { + this.moveCursorRightWithoutShift(e); + } + + this.initDelayedCursor(); + }, + + /** + * Moves cursor right while keeping selection + * @param {Event} e + */ + moveCursorRightWithShift: function(e) { + if (this._selectionDirection === 'left' && this.selectionStart !== this.selectionEnd) { + this._moveRight(e, 'selectionStart'); + } + else { + this._selectionDirection = 'right'; + this._moveRight(e, 'selectionEnd'); + + // increase selection by one if it's a newline + if (this.text.charAt(this.selectionEnd - 1) === '\n') { + this.selectionEnd++; + } + if (this.selectionEnd > this.text.length) { + this.selectionEnd = this.text.length; + } + } + }, + + /** + * Moves cursor right without keeping selection + * @param {Event} e Event object + */ + moveCursorRightWithoutShift: function(e) { + this._selectionDirection = 'right'; + + if (this.selectionStart === this.selectionEnd) { + this._moveRight(e, 'selectionStart'); + this.selectionEnd = this.selectionStart; + } + else { + this.selectionEnd += this.getNumNewLinesInSelectedText(); + if (this.selectionEnd > this.text.length) { + this.selectionEnd = this.text.length; + } + this.selectionStart = this.selectionEnd; + } + }, + + /** + * Inserts a character where cursor is (replacing selection if one exists) + * @param {Event} e Event object + */ + removeChars: function(e) { + if (this.selectionStart === this.selectionEnd) { + this._removeCharsNearCursor(e); + } + else { + this._removeCharsFromTo(this.selectionStart, this.selectionEnd); + } + + this.selectionEnd = this.selectionStart; + + this._removeExtraneousStyles(); + + if (this.canvas) { + // TODO: double renderAll gets rid of text box shift happenning sometimes + // need to find out what exactly causes it and fix it + this.canvas.renderAll().renderAll(); + } + + this.setCoords(); + this.fire('changed'); + this.canvas && this.canvas.fire('text:changed', { target: this }); + }, + + /** + * @private + * @param {Event} e Event object + */ + _removeCharsNearCursor: function(e) { + if (this.selectionStart !== 0) { + + if (e.metaKey) { + // remove all till the start of current line + var leftLineBoundary = this.findLineBoundaryLeft(this.selectionStart); + + this._removeCharsFromTo(leftLineBoundary, this.selectionStart); + this.selectionStart = leftLineBoundary; + } + else if (e.altKey) { + // remove all till the start of current word + var leftWordBoundary = this.findWordBoundaryLeft(this.selectionStart); + + this._removeCharsFromTo(leftWordBoundary, this.selectionStart); + this.selectionStart = leftWordBoundary; + } + else { + var isBeginningOfLine = this.text.slice(this.selectionStart - 1, this.selectionStart) === '\n'; + this.removeStyleObject(isBeginningOfLine); + + this.selectionStart--; + this.text = this.text.slice(0, this.selectionStart) + + this.text.slice(this.selectionStart + 1); + } + } + } +}); + + +/* _TO_SVG_START_ */ +fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + + /** + * @private + */ + _setSVGTextLineText: function(textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects) { + if (!this.styles[lineIndex]) { + this.callSuper('_setSVGTextLineText', + textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier); + } + else { + this._setSVGTextLineChars( + textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects); + } + }, + + /** + * @private + */ + _setSVGTextLineChars: function(textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects) { + + var yProp = lineIndex === 0 || this.useNative ? 'y' : 'dy', + chars = textLine.split(''), + charOffset = 0, + lineLeftOffset = this._getSVGLineLeftOffset(lineIndex), + lineTopOffset = this._getSVGLineTopOffset(lineIndex), + heightOfLine = this._getHeightOfLine(this.ctx, lineIndex); + + for (var i = 0, len = chars.length; i < len; i++) { + var styleDecl = this.styles[lineIndex][i] || { }; + + textSpans.push( + this._createTextCharSpan( + chars[i], styleDecl, lineLeftOffset, lineTopOffset, yProp, charOffset)); + + var charWidth = this._getWidthOfChar(this.ctx, chars[i], lineIndex, i); + + if (styleDecl.textBackgroundColor) { + textBgRects.push( + this._createTextCharBg( + styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset)); + } + + charOffset += charWidth; + } + }, + + /** + * @private + */ + _getSVGLineLeftOffset: function(lineIndex) { + return (this._boundaries && this._boundaries[lineIndex]) + ? fabric.util.toFixed(this._boundaries[lineIndex].left, 2) + : 0; + }, + + /** + * @private + */ + _getSVGLineTopOffset: function(lineIndex) { + var lineTopOffset = 0; + for (var j = 0; j <= lineIndex; j++) { + lineTopOffset += this._getHeightOfLine(this.ctx, j); + } + return lineTopOffset - this.height / 2; + }, + + /** + * @private + */ + _createTextCharBg: function(styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset) { + return [ + //jscs:disable validateIndentation + '' + //jscs:enable validateIndentation + ].join(''); + }, + + /** + * @private + */ + _createTextCharSpan: function(_char, styleDecl, lineLeftOffset, lineTopOffset, yProp, charOffset) { + + var fillStyles = this.getSvgStyles.call(fabric.util.object.extend({ + visible: true, + fill: this.fill, + stroke: this.stroke, + type: 'text' + }, styleDecl)); + + return [ + //jscs:disable validateIndentation + '', + + fabric.util.string.escapeXml(_char), + '' + //jscs:enable validateIndentation + ].join(''); + } +}); +/* _TO_SVG_END_ */ + + +(function() { + + if (typeof document !== 'undefined' && typeof window !== 'undefined') { + return; + } + + var DOMParser = require('xmldom').DOMParser, + URL = require('url'), + HTTP = require('http'), + HTTPS = require('https'), + + Canvas = require('canvas'), + Image = require('canvas').Image; + + /** @private */ + function request(url, encoding, callback) { + var oURL = URL.parse(url); + + // detect if http or https is used + if ( !oURL.port ) { + oURL.port = ( oURL.protocol.indexOf('https:') === 0 ) ? 443 : 80; + } + + // assign request handler based on protocol + var reqHandler = ( oURL.port === 443 ) ? HTTPS : HTTP, + req = reqHandler.request({ + hostname: oURL.hostname, + port: oURL.port, + path: oURL.path, + method: 'GET' + }, function(response) { + var body = ''; + if (encoding) { + response.setEncoding(encoding); + } + response.on('end', function () { + callback(body); + }); + response.on('data', function (chunk) { + if (response.statusCode === 200) { + body += chunk; + } + }); + }); + + req.on('error', function(err) { + if (err.errno === process.ECONNREFUSED) { + fabric.log('ECONNREFUSED: connection refused to ' + oURL.hostname + ':' + oURL.port); + } + else { + fabric.log(err.message); + } + }); + + req.end(); + } + + /** @private */ + function requestFs(path, callback){ + var fs = require('fs'); + fs.readFile(path, function (err, data) { + if (err) { + fabric.log(err); + throw err; + } + else { + callback(data); + } + }); + } + + fabric.util.loadImage = function(url, callback, context) { + function createImageAndCallBack(data) { + img.src = new Buffer(data, 'binary'); + // preserving original url, which seems to be lost in node-canvas + img._src = url; + callback && callback.call(context, img); + } + var img = new Image(); + if (url && (url instanceof Buffer || url.indexOf('data') === 0)) { + img.src = img._src = url; + callback && callback.call(context, img); + } + else if (url && url.indexOf('http') !== 0) { + requestFs(url, createImageAndCallBack); + } + else if (url) { + request(url, 'binary', createImageAndCallBack); + } + else { + callback && callback.call(context, url); + } + }; + + fabric.loadSVGFromURL = function(url, callback, reviver) { + url = url.replace(/^\n\s*/, '').replace(/\?.*$/, '').trim(); + if (url.indexOf('http') !== 0) { + requestFs(url, function(body) { + fabric.loadSVGFromString(body.toString(), callback, reviver); + }); + } + else { + request(url, '', function(body) { + fabric.loadSVGFromString(body, callback, reviver); + }); + } + }; + + fabric.loadSVGFromString = function(string, callback, reviver) { + var doc = new DOMParser().parseFromString(string); + fabric.parseSVGDocument(doc.documentElement, function(results, options) { + callback && callback(results, options); + }, reviver); + }; + + fabric.util.getScript = function(url, callback) { + request(url, '', function(body) { + eval(body); + callback && callback(); + }); + }; + + fabric.Image.fromObject = function(object, callback) { + fabric.util.loadImage(object.src, function(img) { + var oImg = new fabric.Image(img); + + oImg._initConfig(object); + oImg._initFilters(object, function(filters) { + oImg.filters = filters || [ ]; + callback && callback(oImg); + }); + }); + }; + + /** + * Only available when running fabric on node.js + * @param {Number} width Canvas width + * @param {Number} height Canvas height + * @param {Object} [options] Options to pass to FabricCanvas. + * @param {Object} [nodeCanvasOptions] Options to pass to NodeCanvas. + * @return {Object} wrapped canvas instance + */ + fabric.createCanvasForNode = function(width, height, options, nodeCanvasOptions) { + nodeCanvasOptions = nodeCanvasOptions || options; + + var canvasEl = fabric.document.createElement('canvas'), + nodeCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions); + + // jsdom doesn't create style on canvas element, so here be temp. workaround + canvasEl.style = { }; + + canvasEl.width = nodeCanvas.width; + canvasEl.height = nodeCanvas.height; + + var FabricCanvas = fabric.Canvas || fabric.StaticCanvas, + fabricCanvas = new FabricCanvas(canvasEl, options); + + fabricCanvas.contextContainer = nodeCanvas.getContext('2d'); + fabricCanvas.nodeCanvas = nodeCanvas; + fabricCanvas.Font = Canvas.Font; + + return fabricCanvas; + }; + + /** @ignore */ + fabric.StaticCanvas.prototype.createPNGStream = function() { + return this.nodeCanvas.createPNGStream(); + }; + + fabric.StaticCanvas.prototype.createJPEGStream = function(opts) { + return this.nodeCanvas.createJPEGStream(opts); + }; + + var origSetWidth = fabric.StaticCanvas.prototype.setWidth; + fabric.StaticCanvas.prototype.setWidth = function(width, options) { + origSetWidth.call(this, width, options); + this.nodeCanvas.width = width; + return this; + }; + if (fabric.Canvas) { + fabric.Canvas.prototype.setWidth = fabric.StaticCanvas.prototype.setWidth; + } + + var origSetHeight = fabric.StaticCanvas.prototype.setHeight; + fabric.StaticCanvas.prototype.setHeight = function(height, options) { + origSetHeight.call(this, height, options); + this.nodeCanvas.height = height; + return this; + }; + if (fabric.Canvas) { + fabric.Canvas.prototype.setHeight = fabric.StaticCanvas.prototype.setHeight; + } + +})(); + diff --git a/js/fabric-v1.4.11.min.js b/js/fabric-v1.4.11.min.js new file mode 100644 index 00000000..726a28b9 --- /dev/null +++ b/js/fabric-v1.4.11.min.js @@ -0,0 +1,7 @@ +/* build: `node build.js modules=ALL exclude=gestures,cufon,json minifier=uglifyjs` *//*! Fabric.js Copyright 2008-2014, Printio (Juriy Zaytsev, Maxim Chernyak) */var fabric=fabric||{version:"1.4.11"};typeof exports!="undefined"&&(exports.fabric=fabric),typeof document!="undefined"&&typeof window!="undefined"?(fabric.document=document,fabric.window=window):(fabric.document=require("jsdom").jsdom(""),fabric.window=fabric.document.createWindow()),fabric.isTouchSupported="ontouchstart"in fabric.document.documentElement,fabric.isLikelyNode=typeof Buffer!="undefined"&&typeof window=="undefined",fabric.SHARED_ATTRIBUTES=["display","transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width"],fabric.DPI=96,function(){function e(e,t){if(!this.__eventListeners[e])return;t?fabric.util.removeFromArray(this.__eventListeners[e],t):this.__eventListeners[e].length=0}function t(e,t){this.__eventListeners||(this.__eventListeners={});if(arguments.length===1)for(var n in e)this.on(n,e[n]);else this.__eventListeners[e]||(this.__eventListeners[e]=[]),this.__eventListeners[e].push(t);return this}function n(t,n){if(!this.__eventListeners)return;if(arguments.length===0)this.__eventListeners={};else if(arguments.length===1&&typeof arguments[0]=="object")for(var r in t)e.call(this,r,t[r]);else e.call(this,t,n);return this}function r(e,t){if(!this.__eventListeners)return;var n=this.__eventListeners[e];if(!n)return;for(var r=0,i=n.length;r-1},complexity:function(){return this.getObjects().reduce(function(e,t){return e+=t.complexity?t.complexity():0,e},0)}},function(e){var t=Math.sqrt,n=Math.atan2,r=Math.PI/180;fabric.util={removeFromArray:function(e,t){var n=e.indexOf(t);return n!==-1&&e.splice(n,1),e},getRandomInt:function(e,t){return Math.floor(Math.random()*(t-e+1))+e},degreesToRadians:function(e){return e*r},radiansToDegrees:function(e){return e/r},rotatePoint:function(e,t,n){var r=Math.sin(n),i=Math.cos(n);e.subtractEquals(t);var s=e.x*i-e.y*r,o=e.x*r+e.y*i;return(new fabric.Point(s,o)).addEquals(t)},transformPoint:function(e,t,n){return n?new fabric.Point(t[0]*e.x+t[1]*e.y,t[2]*e.x+t[3]*e.y):new fabric.Point(t[0]*e.x+t[1]*e.y+t[4],t[2]*e.x+t[3]*e.y+t[5])},invertTransform:function(e){var t=e.slice(),n=1/(e[0]*e[3]-e[1]*e[2]);t=[n*e[3],-n*e[1],-n*e[2],n*e[0],0,0];var r=fabric.util.transformPoint({x:e[4],y:e[5]},t);return t[4]=-r.x,t[5]=-r.y,t},toFixed:function(e,t){return parseFloat(Number(e).toFixed(t))},parseUnit:function(e){var t=/\D{0,2}$/.exec(e),n=parseFloat(e);switch(t[0]){case"mm":return n*fabric.DPI/25.4;case"cm":return n*fabric.DPI/2.54;case"in":return n*fabric.DPI;case"pt":return n*fabric.DPI/72;case"pc":return n*fabric.DPI/72*12;default:return n}},falseFunction:function(){return!1},getKlass:function(e,t){return e=fabric.util.string.camelize(e.charAt(0).toUpperCase()+e.slice(1)),fabric.util.resolveNamespace(t)[e]},resolveNamespace:function(t){if(!t)return fabric;var n=t.split("."),r=n.length,i=e||fabric.window;for(var s=0;sr)r+=u[p++%h],r>l&&(r=l),e[d?"lineTo":"moveTo"](r,0),d=!d;e.restore()},createCanvasElement:function(e){return e||(e=fabric.document.createElement("canvas")),!e.getContext&&typeof G_vmlCanvasManager!="undefined"&&G_vmlCanvasManager.initElement(e),e},createImage:function(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")},createAccessors:function(e){var t=e.prototype;for(var n=t.stateProperties.length;n--;){var r=t.stateProperties[n],i=r.charAt(0).toUpperCase()+r.slice(1),s="set"+i,o="get"+i;t[o]||(t[o]=function(e){return new Function('return this.get("'+e+'")')}(r)),t[s]||(t[s]=function(e){return new Function("value",'return this.set("'+e+'", value)')}(r))}},clipContext:function(e,t){t.save(),t.beginPath(),e.clipTo(t),t.clip()},multiplyTransformMatrices:function(e,t){var n=[[e[0],e[2],e[4]],[e[1],e[3],e[5]],[0,0,1]],r=[[t[0],t[2],t[4]],[t[1],t[3],t[5]],[0,0,1]],i=[];for(var s=0;s<3;s++){i[s]=[];for(var o=0;o<3;o++){var u=0;for(var a=0;a<3;a++)u+=n[s][a]*r[a][o];i[s][o]=u}}return[i[0][0],i[1][0],i[0][1],i[1][1],i[0][2],i[1][2]]},getFunctionBody:function(e){return(String(e).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},isTransparent:function(e,t,n,r){r>0&&(t>r?t-=r:t=0,n>r?n-=r:n=0);var i=!0,s=e.getImageData(t,n,r*2||1,r*2||1);for(var o=3,u=s.data.length;o0?_-=2*h:f===1&&_<0&&(_+=2*h);var D=Math.ceil(Math.abs(_/(h*.5))),P=[],H=_/D,B=8/3*Math.sin(H/4)*Math.sin(H/4)/Math.sin(H/2),j=M+H;for(var F=0;F=i?s-i:2*Math.PI-(i-s)}var e={},t={},n=Array.prototype.join;fabric.util.drawArc=function(e,t,n,i){var s=i[0],o=i[1],u=i[2],a=i[3],f=i[4],l=i[5],c=i[6],h=[[],[],[],[]],p=r(l-t,c-n,s,o,a,f,u);for(var d=0;d=t})}function r(e,t){return i(e,t,function(e,t){return e>>0;if(n===0)return-1;var r=0;arguments.length>0&&(r=Number(arguments[1]),r!==r?r=0:r!==0&&r!==Number.POSITIVE_INFINITY&&r!==Number.NEGATIVE_INFINITY&&(r=(r>0||-1)*Math.floor(Math.abs(r))));if(r>=n)return-1;var i=r>=0?r:Math.max(n-Math.abs(r),0);for(;i>>0;n>>0;r>>0;n>>0;n>>0;i>>0,n=0,r;if(arguments.length>1)r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n/g,">")}String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^[\s\xA0]+/,"").replace(/[\s\xA0]+$/,"")}),fabric.util.string={camelize:e,capitalize:t,escapeXml:n}}(),function(){var e=Array.prototype.slice,t=Function.prototype.apply,n=function(){};Function.prototype.bind||(Function.prototype.bind=function(r){var i=this,s=e.call(arguments,1),o;return s.length?o=function(){return t.call(i,this instanceof n?this:r,s.concat(e.call(arguments)))}:o=function(){return t.call(i,this instanceof n?this:r,arguments)},n.prototype=this.prototype,o.prototype=new n,o})}(),function(){function i(){}function s(t){var n=this.constructor.superclass.prototype[t];return arguments.length>1?n.apply(this,e.call(arguments,1)):n.call(this)}function o(){function u(){this.initialize.apply(this,arguments)}var n=null,o=e.call(arguments,0);typeof o[0]=="function"&&(n=o.shift()),u.superclass=n,u.subclasses=[],n&&(i.prototype=n.prototype,u.prototype=new i,n.subclasses.push(u));for(var a=0,f=o.length;a-1?e.prototype[i]=function(e){return function(){var n=this.constructor.superclass;this.constructor.superclass=r;var i=t[e].apply(this,arguments);this.constructor.superclass=n;if(e!=="initialize")return i}}(i):e.prototype[i]=t[i],n&&(t.toString!==Object.prototype.toString&&(e.prototype.toString=t.toString),t.valueOf!==Object.prototype.valueOf&&(e.prototype.valueOf=t.valueOf))};fabric.util.createClass=o}(),function(){function t(e){var t=Array.prototype.slice.call(arguments,1),n,r,i=t.length;for(r=0;r-1?s(e,t.match(/opacity:\s*(\d?\.?\d*)/)[1]):e;for(var r in t)if(r==="opacity")s(e,t[r]);else{var i=r==="float"||r==="cssFloat"?typeof n.styleFloat=="undefined"?"cssFloat":"styleFloat":r;n[i]=t[r]}return e}var t=fabric.document.createElement("div"),n=typeof t.style.opacity=="string",r=typeof t.style.filter=="string",i=/alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,s=function(e){return e};n?s=function(e,t){return e.style.opacity=t,e}:r&&(s=function(e,t){var n=e.style;return e.currentStyle&&!e.currentStyle.hasLayout&&(n.zoom=1),i.test(n.filter)?(t=t>=.9999?"":"alpha(opacity="+t*100+")",n.filter=n.filter.replace(i,t)):n.filter+=" alpha(opacity="+t*100+")",e}),fabric.util.setStyle=e}(),function(){function t(e){return typeof e=="string"?fabric.document.getElementById(e):e}function s(e,t){var n=fabric.document.createElement(e);for(var r in t)r==="class"?n.className=t[r]:r==="for"?n.htmlFor=t[r]:n.setAttribute(r,t[r]);return n}function o(e,t){e&&(" "+e.className+" ").indexOf(" "+t+" ")===-1&&(e.className+=(e.className?" ":"")+t)}function u(e,t,n){return typeof t=="string"&&(t=s(t,n)),e.parentNode&&e.parentNode.replaceChild(t,e),t.appendChild(e),t}function a(e,t){var n,r,i=0,s=0,o=fabric.document.documentElement,u=fabric.document.body||{scrollLeft:0,scrollTop:0};r=e;while(e&&e.parentNode&&!n)e=e.parentNode,e!==fabric.document&&fabric.util.getElementStyle(e,"position")==="fixed"&&(n=e),e!==fabric.document&&r!==t&&fabric.util.getElementStyle(e,"position")==="absolute"?(i=0,s=0):e===fabric.document?(i=u.scrollLeft||o.scrollLeft||0,s=u.scrollTop||o.scrollTop||0):(i+=e.scrollLeft||0,s+=e.scrollTop||0);return{left:i,top:s}}function f(e){var t,n=e&&e.ownerDocument,r={left:0,top:0},i={left:0,top:0},s,o={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!n)return{left:0,top:0};for(var u in o)i[o[u]]+=parseInt(l(e,u),10)||0;return t=n.documentElement,typeof e.getBoundingClientRect!="undefined"&&(r=e.getBoundingClientRect()),s=fabric.util.getScrollLeftTop(e,null),{left:r.left+s.left-(t.clientLeft||0)+i.left,top:r.top+s.top-(t.clientTop||0)+i.top}}var e=Array.prototype.slice,n,r=function(t){return e.call(t,0)};try{n=r(fabric.document.childNodes)instanceof Array}catch(i){}n||(r=function(e){var t=new Array(e.length),n=e.length;while(n--)t[n]=e[n];return t});var l;fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle?l=function(e,t){return fabric.document.defaultView.getComputedStyle(e,null)[t]}:l=function(e,t){var n=e.style[t];return!n&&e.currentStyle&&(n=e.currentStyle[t]),n},function(){function n(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=fabric.util.falseFunction),t?e.style[t]="none":typeof e.unselectable=="string"&&(e.unselectable="on"),e}function r(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=null),t?e.style[t]="":typeof e.unselectable=="string"&&(e.unselectable=""),e}var e=fabric.document.documentElement.style,t="userSelect"in e?"userSelect":"MozUserSelect"in e?"MozUserSelect":"WebkitUserSelect"in e?"WebkitUserSelect":"KhtmlUserSelect"in e?"KhtmlUserSelect":"";fabric.util.makeElementUnselectable=n,fabric.util.makeElementSelectable=r}(),function(){function e(e,t){var n=fabric.document.getElementsByTagName("head")[0],r=fabric.document.createElement("script"),i=!0;r.onload=r.onreadystatechange=function(e){if(i){if(typeof this.readyState=="string"&&this.readyState!=="loaded"&&this.readyState!=="complete")return;i=!1,t(e||fabric.window.event),r=r.onload=r.onreadystatechange=null}},r.src=e,n.appendChild(r)}fabric.util.getScript=e}(),fabric.util.getById=t,fabric.util.toArray=r,fabric.util.makeElement=s,fabric.util.addClass=o,fabric.util.wrapElement=u,fabric.util.getScrollLeftTop=a,fabric.util.getElementOffset=f,fabric.util.getElementStyle=l}(),function(){function e(e,t){return e+(/\?/.test(e)?"&":"?")+t}function n(){}function r(r,i){i||(i={});var s=i.method?i.method.toUpperCase():"GET",o=i.onComplete||function(){},u=t(),a;return u.onreadystatechange=function(){u.readyState===4&&(o(u),u.onreadystatechange=n)},s==="GET"&&(a=null,typeof i.parameters=="string"&&(r=e(r,i.parameters))),u.open(s,r,!0),(s==="POST"||s==="PUT")&&u.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),u.send(a),u}var t=function(){var e=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0")},function(){return new XMLHttpRequest}];for(var t=e.length;t--;)try{var n=e[t]();if(n)return e[t]}catch(r){}}();fabric.util.request=r}(),fabric.log=function(){},fabric.warn=function(){},typeof console!="undefined"&&["log","warn"].forEach(function(e){typeof console[e]!="undefined"&&console[e].apply&&(fabric[e]=function(){return console[e].apply(console,arguments)})}),function(){function e(e){n(function(t){e||(e={});var r=t||+(new Date),i=e.duration||500,s=r+i,o,u=e.onChange||function(){},a=e.abort||function(){return!1},f=e.easing||function(e,t,n,r){return-n*Math.cos(e/r*(Math.PI/2))+n+t},l="startValue"in e?e.startValue:0,c="endValue"in e?e.endValue:100,h=e.byValue||c-l;e.onStart&&e.onStart(),function p(t){o=t||+(new Date);var c=o>s?i:o-r;if(a()){e.onComplete&&e.onComplete();return}u(f(c,l,h,i));if(o>s){e.onComplete&&e.onComplete();return}n(p)}(r)})}function n(){return t.apply(fabric.window,arguments)}var t=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(e){fabric.window.setTimeout(e,1e3/60)};fabric.util.animate=e,fabric.util.requestAnimFrame=n}(),function(){function e(e,t,n,r){return et[3]?t[3]:t[0];if(t[0]===1&&t[3]===1&&t[4]===0&&t[5]===0)return;var n=e.ownerDocument.createElement("g");while(e.firstChild!=null)n.appendChild(e.firstChild);n.setAttribute("transform","matrix("+t[0]+" "+t[1]+" "+t[2]+" "+t[3]+" "+t[4]+" "+t[5]+")"),e.appendChild(n)}function x(e){var n=e.objects,i=e.options;return n=n.map(function(e){return t[r(e.type)].fromObject(e)}),{objects:n,options:i}}function T(e,t,n){t[n]&&t[n].toSVG&&e.push('','')}var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.string.capitalize,i=t.util.object.clone,s=t.util.toFixed,o=t.util.parseUnit,u=t.util.multiplyTransformMatrices,a={cx:"left",x:"left",r:"radius",cy:"top",y:"top",display:"visible",visibility:"visible",transform:"transformMatrix","fill-opacity":"fillOpacity","fill-rule":"fillRule","font-family":"fontFamily","font-size":"fontSize","font-style":"fontStyle","font-weight":"fontWeight","stroke-dasharray":"strokeDashArray","stroke-linecap":"strokeLineCap","stroke-linejoin":"strokeLineJoin","stroke-miterlimit":"strokeMiterLimit","stroke-opacity":"strokeOpacity","stroke-width":"strokeWidth","text-decoration":"textDecoration","text-anchor":"originX"},f={stroke:"strokeOpacity",fill:"fillOpacity"};t.parseTransformAttribute=function(){function e(e,t){var n=t[0];e[0]=Math.cos(n),e[1]=Math.sin(n),e[2]=-Math.sin(n),e[3]=Math.cos(n)}function n(e,t){var n=t[0],r=t.length===2?t[1]:t[0];e[0]=n,e[3]=r}function r(e,t){e[2]=t[0]}function i(e,t){e[1]=t[0]}function s(e,t){e[4]=t[0],t.length===2&&(e[5]=t[1])}var o=[1,0,0,1,0,0],u="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",a="(?:\\s+,?\\s*|,\\s*)",f="(?:(skewX)\\s*\\(\\s*("+u+")\\s*\\))",l="(?:(skewY)\\s*\\(\\s*("+u+")\\s*\\))",c="(?:(rotate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+")"+a+"("+u+"))?\\s*\\))",h="(?:(scale)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",p="(?:(translate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",d="(?:(matrix)\\s*\\(\\s*("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+"\\s*\\))",v="(?:"+d+"|"+p+"|"+h+"|"+c+"|"+f+"|"+l+")",m="(?:"+v+"(?:"+a+v+")*"+")",g="^\\s*(?:"+m+"?)\\s*$",y=new RegExp(g),b=new RegExp(v,"g");return function(u){var a=o.concat(),f=[];if(!u||u&&!y.test(u))return a;u.replace(b,function(u){var l=(new RegExp(v)).exec(u).filter(function(e){return e!==""&&e!=null}),c=l[1],h=l.slice(2).map(parseFloat);switch(c){case"translate":s(a,h);break;case"rotate":h[0]=t.util.degreesToRadians(h[0]),e(a,h);break;case"scale":n(a,h);break;case"skewX":r(a,h);break;case"skewY":i(a,h);break;case"matrix":a=h}f.push(a.concat()),a=o.concat()});var l=f[0];while(f.length>1)f.shift(),l=t.util.multiplyTransformMatrices(l,f[0]);return l}}(),t.parseSVGDocument=function(){function s(e,t){while(e&&(e=e.parentNode))if(t.test(e.nodeName))return!0;return!1}var e=/^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/,n="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",r=new RegExp("^\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*"+"$");return function(n,u,a){if(!n)return;var f=new Date;w(n);var l=n.getAttribute("viewBox"),c=o(n.getAttribute("width")),h=o(n.getAttribute("height")),p,d;if(l&&(l=l.match(r))){var v=parseFloat(l[1]),m=parseFloat(l[2]),g=1,y=1;p=parseFloat(l[3]),d=parseFloat(l[4]),c&&c!==p&&(g=c/p),h&&h!==d&&(y=h/d),E(n,[g,0,0,y,g*-v,y*-m])}var b=t.util.toArray(n.getElementsByTagName("*"));if(b.length===0&&t.isLikelyNode){b=n.selectNodes('//*[name(.)!="svg"]');var S=[];for(var x=0,T=b.length;x/i,"")));if(!s||!s.documentElement)return;t.parseSVGDocument(s.documentElement,function(r,i){S.set(e,{objects:t.util.array.invoke(r,"toObject"),options:i}),n(r,i)},r)}e=e.replace(/^\n\s*/,"").trim(),S.has(e,function(r){r?S.get(e,function(e){var t=x(e);n(t.objects,t.options)}):new t.util.request(e,{method +:"get",onComplete:i})})},loadSVGFromString:function(e,n,r){e=e.trim();var i;if(typeof DOMParser!="undefined"){var s=new DOMParser;s&&s.parseFromString&&(i=s.parseFromString(e,"text/xml"))}else t.window.ActiveXObject&&(i=new ActiveXObject("Microsoft.XMLDOM"),i.async="false",i.loadXML(e.replace(//i,"")));t.parseSVGDocument(i.documentElement,function(e,t){n(e,t)},r)},createSVGFontFacesMarkup:function(e){var t="";for(var n=0,r=e.length;n',"",""].join("")),t},createSVGRefElementsMarkup:function(e){var t=[];return T(t,e,"backgroundColor"),T(t,e,"overlayColor"),t.join("")}})}(typeof exports!="undefined"?exports:this),fabric.ElementsParser=function(e,t,n,r){this.elements=e,this.callback=t,this.options=n,this.reviver=r},fabric.ElementsParser.prototype.parse=function(){this.instances=new Array(this.elements.length),this.numElements=this.elements.length,this.createObjects()},fabric.ElementsParser.prototype.createObjects=function(){for(var e=0,t=this.elements.length;ee.x&&this.y>e.y},gte:function(e){return this.x>=e.x&&this.y>=e.y},lerp:function(e,t){return new n(this.x+(e.x-this.x)*t,this.y+(e.y-this.y)*t)},distanceFrom:function(e){var t=this.x-e.x,n=this.y-e.y;return Math.sqrt(t*t+n*n)},midPointFrom:function(e){return new n(this.x+(e.x-this.x)/2,this.y+(e.y-this.y)/2)},min:function(e){return new n(Math.min(this.x,e.x),Math.min(this.y,e.y))},max:function(e){return new n(Math.max(this.x,e.x),Math.max(this.y,e.y))},toString:function(){return this.x+","+this.y},setXY:function(e,t){this.x=e,this.y=t},setFromPoint:function(e){this.x=e.x,this.y=e.y},swap:function(e){var t=this.x,n=this.y;this.x=e.x,this.y=e.y,e.x=t,e.y=n}}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function n(e){this.status=e,this.points=[]}var t=e.fabric||(e.fabric={});if(t.Intersection){t.warn("fabric.Intersection is already defined");return}t.Intersection=n,t.Intersection.prototype={appendPoint:function(e){this.points.push(e)},appendPoints:function(e){this.points=this.points.concat(e)}},t.Intersection.intersectLineLine=function(e,r,i,s){var o,u=(s.x-i.x)*(e.y-i.y)-(s.y-i.y)*(e.x-i.x),a=(r.x-e.x)*(e.y-i.y)-(r.y-e.y)*(e.x-i.x),f=(s.y-i.y)*(r.x-e.x)-(s.x-i.x)*(r.y-e.y);if(f!==0){var l=u/f,c=a/f;0<=l&&l<=1&&0<=c&&c<=1?(o=new n("Intersection"),o.points.push(new t.Point(e.x+l*(r.x-e.x),e.y+l*(r.y-e.y)))):o=new n}else u===0||a===0?o=new n("Coincident"):o=new n("Parallel");return o},t.Intersection.intersectLinePolygon=function(e,t,r){var i=new n,s=r.length;for(var o=0;o0&&(i.status="Intersection"),i},t.Intersection.intersectPolygonPolygon=function(e,t){var r=new n,i=e.length;for(var s=0;s0&&(r.status="Intersection"),r},t.Intersection.intersectPolygonRectangle=function(e,r,i){var s=r.min(i),o=r.max(i),u=new t.Point(o.x,s.y),a=new t.Point(s.x,o.y),f=n.intersectLinePolygon(s,u,e),l=n.intersectLinePolygon(u,o,e),c=n.intersectLinePolygon(o,a,e),h=n.intersectLinePolygon(a,s,e),p=new n;return p.appendPoints(f.points),p.appendPoints(l.points),p.appendPoints(c.points),p.appendPoints(h.points),p.points.length>0&&(p.status="Intersection"),p}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function n(e){e?this._tryParsingColor(e):this.setSource([0,0,0,1])}function r(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*6*n:n<.5?t:n<2/3?e+(t-e)*(2/3-n)*6:e}var t=e.fabric||(e.fabric={});if(t.Color){t.warn("fabric.Color is already defined.");return}t.Color=n,t.Color.prototype={_tryParsingColor:function(e){var t;e in n.colorNameMap&&(e=n.colorNameMap[e]);if(e==="transparent"){this.setSource([255,255,255,0]);return}t=n.sourceFromHex(e),t||(t=n.sourceFromRgb(e)),t||(t=n.sourceFromHsl(e)),t&&this.setSource(t)},_rgbToHsl:function(e,n,r){e/=255,n/=255,r/=255;var i,s,o,u=t.util.array.max([e,n,r]),a=t.util.array.min([e,n,r]);o=(u+a)/2;if(u===a)i=s=0;else{var f=u-a;s=o>.5?f/(2-u-a):f/(u+a);switch(u){case e:i=(n-r)/f+(n\n']:this.type==="radial"&&(r=["\n']);for(var o=0;o\n');return r.push(this.type==="linear"?"\n":"\n"),r.join("")},toLive:function(e){var t;if(!this.type)return;this.type==="linear"?t=e.createLinearGradient(this.coords.x1,this.coords.y1,this.coords.x2,this.coords.y2):this.type==="radial"&&(t=e.createRadialGradient(this.coords.x1,this.coords.y1,this.coords.r1,this.coords.x2,this.coords.y2,this.coords.r2));for(var n=0,r=this.colorStops.length;n'+''+""},toLive:function(e){var t=typeof this.source=="function"?this.source():this.source;if(!t)return"";if(typeof t.src!="undefined"){if(!t.complete)return"";if(t.naturalWidth===0||t.naturalHeight===0)return""}return e.createPattern(t,this.repeat)}}),function(e){"use strict";var t=e.fabric||(e.fabric={});if(t.Shadow){t.warn("fabric.Shadow is already defined.");return}t.Shadow=t.util.createClass({color:"rgb(0,0,0)",blur:0,offsetX:0,offsetY:0,affectStroke:!1,includeDefaultValues:!0,initialize:function(e){typeof e=="string"&&(e=this._parseShadow(e));for(var n in e)this[n]=e[n];this.id=t.Object.__uid++},_parseShadow:function(e){var n=e.trim(),r=t.Shadow.reOffsetsAndBlur.exec(n)||[],i=n.replace(t.Shadow.reOffsetsAndBlur,"")||"rgb(0,0,0)";return{color:i.trim(),offsetX:parseInt(r[1],10)||0,offsetY:parseInt(r[2],10)||0,blur:parseInt(r[3],10)||0}},toString:function(){return[this.offsetX,this.offsetY,this.blur,this.color].join("px ")},toSVG:function(e){var t="SourceAlpha";return e&&(e.fill===this.color||e.stroke===this.color)&&(t="SourceGraphic"),''+''+''+""+""+''+""+""},toObject:function(){if(this.includeDefaultValues)return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY};var e={},n=t.Shadow.prototype;return this.color!==n.color&&(e.color=this.color),this.blur!==n.blur&&(e.blur=this.blur),this.offsetX!==n.offsetX&&(e.offsetX=this.offsetX),this.offsetY!==n.offsetY&&(e.offsetY=this.offsetY),e}}),t.Shadow.reOffsetsAndBlur=/(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/}(typeof exports!="undefined"?exports:this),function(){"use strict";if(fabric.StaticCanvas){fabric.warn("fabric.StaticCanvas is already defined.");return}var e=fabric.util.object.extend,t=fabric.util.getElementOffset,n=fabric.util.removeFromArray,r=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass({initialize:function(e,t){t||(t={}),this._initStatic(e,t),fabric.StaticCanvas.activeInstance=this},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:!0,stateful:!0,renderOnAddRemove:!0,clipTo:null,controlsAboveOverlay:!1,allowTouchScrolling:!1,imageSmoothingEnabled:!0,viewportTransform:[1,0,0,1,0,0],onBeforeScaleRotate:function(){},_initStatic:function(e,t){this._objects=[],this._createLowerCanvas(e),this._initOptions(t),this._setImageSmoothing(),t.overlayImage&&this.setOverlayImage(t.overlayImage,this.renderAll.bind(this)),t.backgroundImage&&this.setBackgroundImage(t.backgroundImage,this.renderAll.bind(this)),t.backgroundColor&&this.setBackgroundColor(t.backgroundColor,this.renderAll.bind(this)),t.overlayColor&&this.setOverlayColor(t.overlayColor,this.renderAll.bind(this)),this.calcOffset()},calcOffset:function(){return this._offset=t(this.lowerCanvasEl),this},setOverlayImage:function(e,t,n){return this.__setBgOverlayImage("overlayImage",e,t,n)},setBackgroundImage:function(e,t,n){return this.__setBgOverlayImage("backgroundImage",e,t,n)},setOverlayColor:function(e,t){return this.__setBgOverlayColor("overlayColor",e,t)},setBackgroundColor:function(e,t){return this.__setBgOverlayColor("backgroundColor",e,t)},_setImageSmoothing:function(){var e=this.getContext();e.imageSmoothingEnabled=this.imageSmoothingEnabled,e.webkitImageSmoothingEnabled=this.imageSmoothingEnabled,e.mozImageSmoothingEnabled=this.imageSmoothingEnabled,e.msImageSmoothingEnabled=this.imageSmoothingEnabled,e.oImageSmoothingEnabled=this.imageSmoothingEnabled},__setBgOverlayImage:function(e,t,n,r){return typeof t=="string"?fabric.util.loadImage(t,function(t){this[e]=new fabric.Image(t,r),n&&n()},this):(this[e]=t,n&&n()),this},__setBgOverlayColor:function(e,t,n){if(t&&t.source){var r=this;fabric.util.loadImage(t.source,function(i){r[e]=new fabric.Pattern({source:i,repeat:t.repeat,offsetX:t.offsetX,offsetY:t.offsetY}),n&&n()})}else this[e]=t,n&&n();return this},_createCanvasElement:function(){var e=fabric.document.createElement("canvas");e.style||(e.style={});if(!e)throw r;return this._initCanvasElement(e),e},_initCanvasElement:function(e){fabric.util.createCanvasElement(e);if(typeof e.getContext=="undefined")throw r},_initOptions:function(e){for(var t in e)this[t]=e[t];this.width=this.width||parseInt(this.lowerCanvasEl.width,10)||0,this.height=this.height||parseInt(this.lowerCanvasEl.height,10)||0;if(!this.lowerCanvasEl.style)return;this.lowerCanvasEl.width=this.width,this.lowerCanvasEl.height=this.height,this.lowerCanvasEl.style.width=this.width+"px",this.lowerCanvasEl.style.height=this.height+"px",this.viewportTransform=this.viewportTransform.slice()},_createLowerCanvas:function(e){this.lowerCanvasEl=fabric.util.getById(e)||this._createCanvasElement(),this._initCanvasElement(this.lowerCanvasEl),fabric.util.addClass(this.lowerCanvasEl,"lower-canvas"),this.interactive&&this._applyCanvasStyle(this.lowerCanvasEl),this.contextContainer=this.lowerCanvasEl.getContext("2d")},getWidth:function(){return this.width},getHeight:function(){return this.height},setWidth:function(e,t){return this.setDimensions({width:e},t)},setHeight:function(e,t){return this.setDimensions({height:e},t)},setDimensions:function(e,t){var n;t=t||{};for(var r in e)n=e[r],t.cssOnly||(this._setBackstoreDimension(r,e[r]),n+="px"),t.backstoreOnly||this._setCssDimension(r,n);return t.cssOnly||this.renderAll(),this.calcOffset(),this},_setBackstoreDimension:function(e,t){return this.lowerCanvasEl[e]=t,this.upperCanvasEl&&(this.upperCanvasEl[e]=t),this.cacheCanvasEl&&(this.cacheCanvasEl[e]=t),this[e]=t,this},_setCssDimension:function(e,t){return this.lowerCanvasEl.style[e]=t,this.upperCanvasEl&&(this.upperCanvasEl.style[e]=t),this.wrapperEl&&(this.wrapperEl.style[e]=t),this},getZoom:function(){return Math.sqrt(this.viewportTransform[0]*this.viewportTransform[3])},setViewportTransform:function(e){this.viewportTransform=e,this.renderAll();for(var t=0,n=this._objects.length;t"),n.join("")},_setSVGPreamble:function(e,t){t.suppressPreamble||e.push('','\n')},_setSVGHeader:function(e,t){e.push("',"Created with Fabric.js ",fabric.version,"","",fabric.createSVGFontFacesMarkup(this.getObjects()),fabric.createSVGRefElementsMarkup(this),"")},_setSVGObjects:function(e,t){var n=this.getActiveGroup();n&&this.discardActiveGroup();for(var r=0,i=this.getObjects(),s=i.length;r
    "):this[t]&&t==="overlayColor"&&e.push('")},sendToBack:function(e){return n(this._objects,e),this._objects.unshift(e),this.renderAll&&this.renderAll()},bringToFront:function(e){return n(this._objects,e),this._objects.push(e),this.renderAll&&this.renderAll()},sendBackwards:function(e,t){var r=this._objects.indexOf(e);if(r!==0){var i=this._findNewLowerIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewLowerIndex:function(e,t,n){var r;if(n){r=t;for(var i=t-1;i>=0;--i){var s=e.intersectsWithObject(this._objects[i])||e.isContainedWithinObject(this._objects[i])||this._objects[i].isContainedWithinObject(e);if(s){r=i;break}}}else r=t-1;return r},bringForward:function(e,t){var r=this._objects.indexOf(e);if(r!==this._objects.length-1){var i=this._findNewUpperIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewUpperIndex:function(e,t,n){var r;if(n){r=t;for(var i=t+1;i"}}),e(fabric.StaticCanvas.prototype,fabric.Observable),e(fabric.StaticCanvas.prototype,fabric.Collection),e(fabric.StaticCanvas.prototype,fabric.DataURLExporter),e(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(e){var t=fabric.util.createCanvasElement();if(!t||!t.getContext)return null;var n=t.getContext("2d");if(!n)return null;switch(e){case"getImageData":return typeof n.getImageData!="undefined";case"setLineDash":return typeof n.setLineDash!="undefined";case"toDataURL":return typeof t.toDataURL!="undefined";case"toDataURLWithQuality":try{return t.toDataURL("image/jpeg",0),!0}catch(r){}return!1;default:return null}}}),fabric.StaticCanvas.prototype.toJSON=fabric.StaticCanvas.prototype.toObject}(),fabric.BaseBrush=fabric.util.createClass({color:"rgb(0, 0, 0)",width:1,shadow:null,strokeLineCap:"round",strokeLineJoin:"round",setShadow:function(e){return this.shadow=new fabric.Shadow(e),this},_setBrushStyles:function(){var e=this.canvas.contextTop;e.strokeStyle=this.color,e.lineWidth=this.width,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin},_setShadow:function(){if(!this.shadow)return;var e=this.canvas.contextTop;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_resetShadow:function(){var e=this.canvas.contextTop;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0}}),function(){var e=fabric.util.array.min,t=fabric.util.array.max;fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(e){this.canvas=e,this._points=[]},onMouseDown:function(e){this._prepareForDrawing(e),this._captureDrawingPath(e),this._render()},onMouseMove:function(e){this._captureDrawingPath(e),this.canvas.clearContext(this.canvas.contextTop),this._render +()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(e){var t=new fabric.Point(e.x,e.y);this._reset(),this._addPoint(t),this.canvas.contextTop.moveTo(t.x,t.y)},_addPoint:function(e){this._points.push(e)},_reset:function(){this._points.length=0,this._setBrushStyles(),this._setShadow()},_captureDrawingPath:function(e){var t=new fabric.Point(e.x,e.y);this._addPoint(t)},_render:function(){var e=this.canvas.contextTop,t=this.canvas.viewportTransform,n=this._points[0],r=this._points[1];e.save(),e.transform(t[0],t[1],t[2],t[3],t[4],t[5]),e.beginPath(),this._points.length===2&&n.x===r.x&&n.y===r.y&&(n.x-=.5,r.x+=.5),e.moveTo(n.x,n.y);for(var i=1,s=this._points.length;in.padding?e.x<0?e.x+=n.padding:e.x-=n.padding:e.x=0,i(e.y)>n.padding?e.y<0?e.y+=n.padding:e.y-=n.padding:e.y=0},_rotateObject:function(e,t){var i=this._currentTransform;if(i.target.get("lockRotation"))return;var s=r(i.ey-i.top,i.ex-i.left),o=r(t-i.top,e-i.left),u=n(o-s+i.theta);u<0&&(u=360+u),i.target.angle=u},setCursor:function(e){this.upperCanvasEl.style.cursor=e},_resetObjectTransform:function(e){e.scaleX=1,e.scaleY=1,e.setAngle(0)},_drawSelection:function(){var e=this.contextTop,t=this._groupSelector,n=t.left,r=t.top,o=i(n),u=i(r);e.fillStyle=this.selectionColor,e.fillRect(t.ex-(n>0?0:-n),t.ey-(r>0?0:-r),o,u),e.lineWidth=this.selectionLineWidth,e.strokeStyle=this.selectionBorderColor;if(this.selectionDashArray.length>1){var a=t.ex+s-(n>0?0:o),f=t.ey+s-(r>0?0:u);e.beginPath(),fabric.util.drawDashedLine(e,a,f,a+o,f,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f+u-1,a+o,f+u-1,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f,a,f+u,this.selectionDashArray),fabric.util.drawDashedLine(e,a+o-1,f,a+o-1,f+u,this.selectionDashArray),e.closePath(),e.stroke()}else e.strokeRect(t.ex+s-(n>0?0:o),t.ey+s-(r>0?0:u),o,u)},_isLastRenderedObject:function(e){return this.controlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay.visible&&this.containsPoint(e,this.lastRenderedObjectWithControlsAboveOverlay)&&this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e,!0))},findTarget:function(e,t){if(this.skipTargetFind)return;if(this._isLastRenderedObject(e))return this.lastRenderedObjectWithControlsAboveOverlay;var n=this.getActiveGroup();if(n&&!t&&this.containsPoint(e,n))return n;var r=this._searchPossibleTargets(e);return this._fireOverOutEvents(r),r},_fireOverOutEvents:function(e){e?this._hoveredTarget!==e&&(this.fire("mouse:over",{target:e}),e.fire("mouseover"),this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget}),this._hoveredTarget.fire("mouseout")),this._hoveredTarget=e):this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget}),this._hoveredTarget.fire("mouseout"),this._hoveredTarget=null)},_checkTarget:function(e,t,n){if(t&&t.visible&&t.evented&&this.containsPoint(e,t)){if(!this.perPixelTargetFind&&!t.perPixelTargetFind||!!t.isEditing)return!0;var r=this.isTargetTransparent(t,n.x,n.y);if(!r)return!0}},_searchPossibleTargets:function(e){var t,n=this.getPointer(e,!0),r=this._objects.length;while(r--)if(this._checkTarget(e,this._objects[r],n)){this.relatedTarget=this._objects[r],t=this._objects[r];break}return t},getPointer:function(t,n,r){r||(r=this.upperCanvasEl);var i=e(t,r),s=r.getBoundingClientRect(),o;return this.calcOffset(),i.x=i.x-this._offset.left,i.y=i.y-this._offset.top,n||(i=fabric.util.transformPoint(i,fabric.util.invertTransform(this.viewportTransform))),s.width===0||s.height===0?o={width:1,height:1}:o={width:r.width/s.width,height:r.height/s.height},{x:i.x*o.width,y:i.y*o.height}},_createUpperCanvas:function(){var e=this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/,"");this.upperCanvasEl=this._createCanvasElement(),fabric.util.addClass(this.upperCanvasEl,"upper-canvas "+e),this.wrapperEl.appendChild(this.upperCanvasEl),this._copyCanvasStyle(this.lowerCanvasEl,this.upperCanvasEl),this._applyCanvasStyle(this.upperCanvasEl),this.contextTop=this.upperCanvasEl.getContext("2d")},_createCacheCanvas:function(){this.cacheCanvasEl=this._createCanvasElement(),this.cacheCanvasEl.setAttribute("width",this.width),this.cacheCanvasEl.setAttribute("height",this.height),this.contextCache=this.cacheCanvasEl.getContext("2d")},_initWrapperElement:function(){this.wrapperEl=fabric.util.wrapElement(this.lowerCanvasEl,"div",{"class":this.containerClass}),fabric.util.setStyle(this.wrapperEl,{width:this.getWidth()+"px",height:this.getHeight()+"px",position:"relative"}),fabric.util.makeElementUnselectable(this.wrapperEl)},_applyCanvasStyle:function(e){var t=this.getWidth()||e.width,n=this.getHeight()||e.height;fabric.util.setStyle(e,{position:"absolute",width:t+"px",height:n+"px",left:0,top:0}),e.width=t,e.height=n,fabric.util.makeElementUnselectable(e)},_copyCanvasStyle:function(e,t){t.style.cssText=e.style.cssText},getSelectionContext:function(){return this.contextTop},getSelectionElement:function(){return this.upperCanvasEl},_setActiveObject:function(e){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=e,e.set("active",!0)},setActiveObject:function(e,t){return this._setActiveObject(e),this.renderAll(),this.fire("object:selected",{target:e,e:t}),e.fire("selected",{e:t}),this},getActiveObject:function(){return this._activeObject},_discardActiveObject:function(){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=null},discardActiveObject:function(e){return this._discardActiveObject(),this.renderAll(),this.fire("selection:cleared",{e:e}),this},_setActiveGroup:function(e){this._activeGroup=e,e&&e.set("active",!0)},setActiveGroup:function(e,t){return this._setActiveGroup(e),e&&(this.fire("object:selected",{target:e,e:t}),e.fire("selected",{e:t})),this},getActiveGroup:function(){return this._activeGroup},_discardActiveGroup:function(){var e=this.getActiveGroup();e&&e.destroy(),this.setActiveGroup(null)},discardActiveGroup:function(e){return this._discardActiveGroup(),this.fire("selection:cleared",{e:e}),this},deactivateAll:function(){var e=this.getObjects(),t=0,n=e.length;for(;t1&&(t=new fabric.Group(t.reverse(),{originX:"center",originY:"center",canvas:this}),t.addWithUpdate(),this.setActiveGroup(t,e),t.saveCoords(),this.fire("selection:created",{target:t}),this.renderAll())},_collectObjects:function(){var n=[],r,i=this._groupSelector.ex,s=this._groupSelector.ey,o=i+this._groupSelector.left,u=s+this._groupSelector.top,a=new fabric.Point(e(i,o),e(s,u)),f=new fabric.Point(t(i,o),t(s,u)),l=i===o&&s===u;for(var c=this._objects.length;c--;){r=this._objects[c];if(!r||!r.selectable||!r.visible)continue;if(r.intersectsWithRect(a,f)||r.isContainedWithinRect(a,f)||r.containsPoint(a)||r.containsPoint(f)){r.set("active",!0),n.push(r);if(l)break}}return n},_maybeGroupObjects:function(e){this.selection&&this._groupSelector&&this._groupSelectedObjects(e);var t=this.getActiveGroup();t&&(t.setObjectsCoords().setCoords(),t.isMoving=!1,this.setCursor(this.defaultCursor)),this._groupSelector=null,this._currentTransform=null}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{toDataURL:function(e){e||(e={});var t=e.format||"png",n=e.quality||1,r=e.multiplier||1,i={left:e.left,top:e.top,width:e.width,height:e.height};return r!==1?this.__toDataURLWithMultiplier(t,n,i,r):this.__toDataURL(t,n,i)},__toDataURL:function(e,t,n){this.renderAll(!0);var r=this.upperCanvasEl||this.lowerCanvasEl,i=this.__getCroppedCanvas(r,n);e==="jpg"&&(e="jpeg");var s=fabric.StaticCanvas.supports("toDataURLWithQuality")?(i||r).toDataURL("image/"+e,t):(i||r).toDataURL("image/"+e);return this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),i&&(i=null),s},__getCroppedCanvas:function(e,t){var n,r,i="left"in t||"top"in t||"width"in t||"height"in t;return i&&(n=fabric.util.createCanvasElement(),r=n.getContext("2d"),n.width=t.width||this.width,n.height=t.height||this.height,r.drawImage(e,-t.left||0,-t.top||0)),n},__toDataURLWithMultiplier:function(e,t,n,r){var i=this.getWidth(),s=this.getHeight(),o=i*r,u=s*r,a=this.getActiveObject(),f=this.getActiveGroup(),l=this.contextTop||this.contextContainer;r>1&&this.setWidth(o).setHeight(u),l.scale(r,r),n.left&&(n.left*=r),n.top&&(n.top*=r),n.width?n.width*=r:r<1&&(n.width=o),n.height?n.height*=r:r<1&&(n.height=u),f?this._tempRemoveBordersControlsFromGroup(f):a&&this.deactivateAll&&this.deactivateAll(),this.renderAll(!0);var c=this.__toDataURL(e,t,n);return this.width=i,this.height=s,l.scale(1/r,1/r),this.setWidth(i).setHeight(s),f?this._restoreBordersControlsOnGroup(f):a&&this.setActiveObject&&this.setActiveObject(a),this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),c},toDataURLWithMultiplier:function(e,t,n){return this.toDataURL({format:e,multiplier:t,quality:n})},_tempRemoveBordersControlsFromGroup:function(e){e.origHasControls=e.hasControls,e.origBorderColor=e.borderColor,e.hasControls=!0,e.borderColor="rgba(0,0,0,0)",e.forEachObject(function(e){e.origBorderColor=e.borderColor,e.borderColor="rgba(0,0,0,0)"})},_restoreBordersControlsOnGroup:function(e){e.hideControls=e.origHideControls,e.borderColor=e.origBorderColor,e.forEachObject(function(e){e.borderColor=e.origBorderColor,delete e.origBorderColor})}}),fabric.util +.object.extend(fabric.StaticCanvas.prototype,{loadFromDatalessJSON:function(e,t,n){return this.loadFromJSON(e,t,n)},loadFromJSON:function(e,t,n){if(!e)return;var r=typeof e=="string"?JSON.parse(e):e;this.clear();var i=this;return this._enlivenObjects(r.objects,function(){i._setBgOverlay(r,t)},n),this},_setBgOverlay:function(e,t){var n=this,r={backgroundColor:!1,overlayColor:!1,backgroundImage:!1,overlayImage:!1};if(!e.backgroundImage&&!e.overlayImage&&!e.background&&!e.overlay){t&&t();return}var i=function(){r.backgroundImage&&r.overlayImage&&r.backgroundColor&&r.overlayColor&&(n.renderAll(),t&&t())};this.__setBgOverlay("backgroundImage",e.backgroundImage,r,i),this.__setBgOverlay("overlayImage",e.overlayImage,r,i),this.__setBgOverlay("backgroundColor",e.background,r,i),this.__setBgOverlay("overlayColor",e.overlay,r,i),i()},__setBgOverlay:function(e,t,n,r){var i=this;if(!t){n[e]=!0;return}e==="backgroundImage"||e==="overlayImage"?fabric.Image.fromObject(t,function(t){i[e]=t,n[e]=!0,r&&r()}):this["set"+fabric.util.string.capitalize(e,!0)](t,function(){n[e]=!0,r&&r()})},_enlivenObjects:function(e,t,n){var r=this;if(!e||e.length===0){t&&t();return}var i=this.renderOnAddRemove;this.renderOnAddRemove=!1,fabric.util.enlivenObjects(e,function(e){e.forEach(function(e,t){r.insertAt(e,t,!0)}),r.renderOnAddRemove=i,t&&t()},null,n)},_toDataURL:function(e,t){this.clone(function(n){t(n.toDataURL(e))})},_toDataURLWithMultiplier:function(e,t,n){this.clone(function(r){n(r.toDataURLWithMultiplier(e,t))})},clone:function(e,t){var n=JSON.stringify(this.toJSON(t));this.cloneWithoutData(function(t){t.loadFromJSON(n,function(){e&&e(t)})})},cloneWithoutData:function(e){var t=fabric.document.createElement("canvas");t.width=this.getWidth(),t.height=this.getHeight();var n=new fabric.Canvas(t);n.clipTo=this.clipTo,this.backgroundImage?(n.setBackgroundImage(this.backgroundImage.src,function(){n.renderAll(),e&&e(n)}),n.backgroundImageOpacity=this.backgroundImageOpacity,n.backgroundImageStretch=this.backgroundImageStretch):e&&e(n)}}),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.toFixed,i=t.util.string.capitalize,s=t.util.degreesToRadians,o=t.StaticCanvas.supports("setLineDash");if(t.Object)return;t.Object=t.util.createClass({type:"object",originX:"left",originY:"top",top:0,left:0,width:0,height:0,scaleX:1,scaleY:1,flipX:!1,flipY:!1,opacity:1,angle:0,cornerSize:12,transparentCorners:!0,hoverCursor:null,padding:0,borderColor:"rgba(102,153,255,0.75)",cornerColor:"rgba(102,153,255,0.5)",centeredScaling:!1,centeredRotation:!0,fill:"rgb(0,0,0)",fillRule:"source-over",backgroundColor:"",stroke:null,strokeWidth:1,strokeDashArray:null,strokeLineCap:"butt",strokeLineJoin:"miter",strokeMiterLimit:10,shadow:null,borderOpacityWhenMoving:.4,borderScaleFactor:1,transformMatrix:null,minScaleLimit:.01,selectable:!0,evented:!0,visible:!0,hasControls:!0,hasBorders:!0,hasRotatingPoint:!0,rotatingPointOffset:40,perPixelTargetFind:!1,includeDefaultValues:!0,clipTo:null,lockMovementX:!1,lockMovementY:!1,lockRotation:!1,lockScalingX:!1,lockScalingY:!1,lockUniScaling:!1,lockScalingFlip:!1,stateProperties:"top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill fillRule shadow clipTo visible backgroundColor".split(" "),initialize:function(e){e&&this.setOptions(e)},_initGradient:function(e){e.fill&&e.fill.colorStops&&!(e.fill instanceof t.Gradient)&&this.set("fill",new t.Gradient(e.fill))},_initPattern:function(e){e.fill&&e.fill.source&&!(e.fill instanceof t.Pattern)&&this.set("fill",new t.Pattern(e.fill)),e.stroke&&e.stroke.source&&!(e.stroke instanceof t.Pattern)&&this.set("stroke",new t.Pattern(e.stroke))},_initClipping:function(e){if(!e.clipTo||typeof e.clipTo!="string")return;var n=t.util.getFunctionBody(e.clipTo);typeof n!="undefined"&&(this.clipTo=new Function("ctx",n))},setOptions:function(e){for(var t in e)this.set(t,e[t]);this._initGradient(e),this._initPattern(e),this._initClipping(e)},transform:function(e,t){this.group&&this.group.transform(e,t),e.globalAlpha=this.opacity;var n=t?this._getLeftTopCoords():this.getCenterPoint();e.translate(n.x,n.y),e.rotate(s(this.angle)),e.scale(this.scaleX*(this.flipX?-1:1),this.scaleY*(this.flipY?-1:1))},toObject:function(e){var n=t.Object.NUM_FRACTION_DIGITS,i={type:this.type,originX:this.originX,originY:this.originY,left:r(this.left,n),top:r(this.top,n),width:r(this.width,n),height:r(this.height,n),fill:this.fill&&this.fill.toObject?this.fill.toObject():this.fill,stroke:this.stroke&&this.stroke.toObject?this.stroke.toObject():this.stroke,strokeWidth:r(this.strokeWidth,n),strokeDashArray:this.strokeDashArray,strokeLineCap:this.strokeLineCap,strokeLineJoin:this.strokeLineJoin,strokeMiterLimit:r(this.strokeMiterLimit,n),scaleX:r(this.scaleX,n),scaleY:r(this.scaleY,n),angle:r(this.getAngle(),n),flipX:this.flipX,flipY:this.flipY,opacity:r(this.opacity,n),shadow:this.shadow&&this.shadow.toObject?this.shadow.toObject():this.shadow,visible:this.visible,clipTo:this.clipTo&&String(this.clipTo),backgroundColor:this.backgroundColor};return this.includeDefaultValues||(i=this._removeDefaultValues(i)),t.util.populateWithProperties(this,i,e),i},toDatalessObject:function(e){return this.toObject(e)},_removeDefaultValues:function(e){var n=t.util.getKlass(e.type).prototype,r=n.stateProperties;return r.forEach(function(t){e[t]===n[t]&&delete e[t]}),e},toString:function(){return"#"},get:function(e){return this[e]},_setObject:function(e){for(var t in e)this._set(t,e[t])},set:function(e,t){return typeof e=="object"?this._setObject(e):typeof t=="function"&&e!=="clipTo"?this._set(e,t(this.get(e))):this._set(e,t),this},_set:function(e,n){var i=e==="scaleX"||e==="scaleY";return i&&(n=this._constrainScale(n)),e==="scaleX"&&n<0?(this.flipX=!this.flipX,n*=-1):e==="scaleY"&&n<0?(this.flipY=!this.flipY,n*=-1):e==="width"||e==="height"?this.minScaleLimit=r(Math.min(.1,1/Math.max(this.width,this.height)),2):e==="shadow"&&n&&!(n instanceof t.Shadow)&&(n=new t.Shadow(n)),this[e]=n,this},toggle:function(e){var t=this.get(e);return typeof t=="boolean"&&this.set(e,!t),this},setSourcePath:function(e){return this.sourcePath=e,this},getViewportTransform:function(){return this.canvas&&this.canvas.viewportTransform?this.canvas.viewportTransform:[1,0,0,1,0,0]},render:function(e,n){if(this.width===0||this.height===0||!this.visible)return;e.save(),this._setupFillRule(e),this._transform(e,n),this._setStrokeStyles(e),this._setFillStyles(e);if(this.group&&this.group.type==="path-group"){e.translate(-this.group.width/2,-this.group.height/2);var r=this.transformMatrix;r&&e.transform.apply(e,r)}e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,this._setShadow(e),this.clipTo&&t.util.clipContext(this,e),this._render(e,n),this.clipTo&&e.restore(),this._removeShadow(e),this._restoreFillRule(e),e.restore()},_transform:function(e,t){var n=this.transformMatrix;n&&!this.group&&e.setTransform.apply(e,n),t||this.transform(e)},_setStrokeStyles:function(e){this.stroke&&(e.lineWidth=this.strokeWidth,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin,e.miterLimit=this.strokeMiterLimit,e.strokeStyle=this.stroke.toLive?this.stroke.toLive(e):this.stroke)},_setFillStyles:function(e){this.fill&&(e.fillStyle=this.fill.toLive?this.fill.toLive(e):this.fill)},_renderControls:function(e,n){var r=this.getViewportTransform();e.save();if(this.active&&!n){var i;this.group&&(i=t.util.transformPoint(this.group.getCenterPoint(),r),e.translate(i.x,i.y),e.rotate(s(this.group.angle))),i=t.util.transformPoint(this.getCenterPoint(),r,null!=this.group),this.group&&(i.x*=this.group.scaleX,i.y*=this.group.scaleY),e.translate(i.x,i.y),e.rotate(s(this.angle)),this.drawBorders(e),this.drawControls(e)}e.restore()},_setShadow:function(e){if(!this.shadow)return;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_removeShadow:function(e){if(!this.shadow)return;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0},_renderFill:function(e){if(!this.fill)return;e.save(),this.fill.toLive&&e.translate(-this.width/2+this.fill.offsetX||0,-this.height/2+this.fill.offsetY||0);if(this.fill.gradientTransform){var t=this.fill.gradientTransform;e.transform.apply(e,t)}this.fillRule==="destination-over"?e.fill("evenodd"):e.fill(),e.restore(),this.shadow&&!this.shadow.affectStroke&&this._removeShadow(e)},_renderStroke:function(e){if(!this.stroke||this.strokeWidth===0)return;e.save();if(this.strokeDashArray)1&this.strokeDashArray.length&&this.strokeDashArray.push.apply(this.strokeDashArray,this.strokeDashArray),o?(e.setLineDash(this.strokeDashArray),this._stroke&&this._stroke(e)):this._renderDashedStroke&&this._renderDashedStroke(e),e.stroke();else{if(this.stroke.gradientTransform){var t=this.stroke.gradientTransform;e.transform.apply(e,t)}this._stroke?this._stroke(e):e.stroke()}this._removeShadow(e),e.restore()},clone:function(e,n){return this.constructor.fromObject?this.constructor.fromObject(this.toObject(n),e):new t.Object(this.toObject(n))},cloneAsImage:function(e){var n=this.toDataURL();return t.util.loadImage(n,function(n){e&&e(new t.Image(n))}),this},toDataURL:function(e){e||(e={});var n=t.util.createCanvasElement(),r=this.getBoundingRect();n.width=r.width,n.height=r.height,t.util.wrapElement(n,"div");var i=new t.Canvas(n);e.format==="jpg"&&(e.format="jpeg"),e.format==="jpeg"&&(i.backgroundColor="#fff");var s={active:this.get("active"),left:this.getLeft(),top:this.getTop()};this.set("active",!1),this.setPositionByOrigin(new t.Point(n.width/2,n.height/2),"center","center");var o=this.canvas;i.add(this);var u=i.toDataURL(e);return this.set(s).setCoords(),this.canvas=o,i.dispose(),i=null,u},isType:function(e){return this.type===e},complexity:function(){return 0},toJSON:function(e){return this.toObject(e)},setGradient:function(e,n){n||(n={});var r={colorStops:[]};r.type=n.type||(n.r1||n.r2?"radial":"linear"),r.coords={x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y2};if(n.r1||n.r2)r.coords.r1=n.r1,r.coords.r2=n.r2;for(var i in n.colorStops){var s=new t.Color(n.colorStops[i]);r.colorStops.push({offset:i,color:s.toRgb(),opacity:s.getAlpha()})}return this.set(e,t.Gradient.forObject(this,r))},setPatternFill:function(e){return this.set("fill",new t.Pattern(e))},setShadow:function(e){return this.set("shadow",e?new t.Shadow(e):null)},setColor:function(e){return this.set("fill",e),this},setAngle:function(e){var t=(this.originX!=="center"||this.originY!=="center")&&this.centeredRotation;return t&&this._setOriginToCenter(),this.set("angle",e),t&&this._resetOrigin(),this},centerH:function(){return this.canvas.centerObjectH(this),this},centerV:function(){return this.canvas.centerObjectV(this),this},center:function(){return this.canvas.centerObject(this),this},remove:function(){return this.canvas.remove(this),this},getLocalPointer:function(e,t){t=t||this.canvas.getPointer(e);var n=this.translateToOriginPoint(this.getCenterPoint(),"left","top");return{x:t.x-n.x,y:t.y-n.y}},_setupFillRule:function(e){this.fillRule&&(this._prevFillRule=e.globalCompositeOperation,e.globalCompositeOperation=this.fillRule)},_restoreFillRule:function(e){this.fillRule&&this._prevFillRule&&(e.globalCompositeOperation=this._prevFillRule)}}),t.util.createAccessors(t.Object),t.Object.prototype.rotate=t.Object.prototype.setAngle,n(t.Object.prototype,t.Observable),t.Object.NUM_FRACTION_DIGITS=2,t.Object.__uid=0}(typeof exports!="undefined"?exports:this),function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{translateToCenterPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x+(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x-(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y+(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y-(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},translateToOriginPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x-(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x+(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y-(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y+(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},getCenterPoint:function(){var e=new fabric.Point(this.left,this.top);return this.translateToCenterPoint(e,this.originX,this.originY)},getPointByOrigin:function(e,t){var n=this.getCenterPoint();return this.translateToOriginPoint(n,e,t)},toLocalPoint:function(t,n,r){var i=this.getCenterPoint(),s=this.stroke?this.strokeWidth:0,o,u;return n&&r?(n==="left"?o=i.x-(this.getWidth()+s*this.scaleX)/2:n==="right"?o=i.x+(this.getWidth()+s*this.scaleX)/2:o=i.x,r==="top"?u=i.y-(this.getHeight()+s*this.scaleY)/2:r==="bottom"?u=i.y+(this.getHeight()+s*this.scaleY)/2:u=i.y):(o=this.left,u=this.top),fabric.util.rotatePoint(new fabric.Point(t.x,t.y),i,-e(this.angle)).subtractEquals(new fabric.Point(o,u))},setPositionByOrigin:function(e,t,n){var r=this.translateToCenterPoint(e,t,n),i=this.translateToOriginPoint(r,this.originX,this.originY);this.set("left",i.x),this.set("top",i.y)},adjustPosition:function(t){var n=e(this.angle),r=this.getWidth()/2,i=Math.cos(n)*r,s=Math.sin(n)*r,o=this.getWidth(),u=Math.cos(n)*o,a=Math.sin(n)*o;this.originX==="center"&&t==="left"||this.originX==="right"&&t==="center"?(this.left-=i,this.top-=s):this.originX==="left"&&t==="center"||this.originX==="center"&&t==="right"?(this.left+=i,this.top+=s):this.originX==="left"&&t==="right"?(this.left+=u,this.top+=a):this.originX==="right"&&t==="left"&&(this.left-=u,this.top-=a),this.setCoords(),this.originX=t},_setOriginToCenter:function(){this._originalOriginX=this.originX,this._originalOriginY=this.originY;var e=this.getCenterPoint();this.originX="center",this.originY="center",this.left=e.x,this.top=e.y},_resetOrigin:function(){var e=this.translateToOriginPoint(this.getCenterPoint(),this._originalOriginX,this._originalOriginY);this.originX=this._originalOriginX,this.originY=this._originalOriginY,this.left=e.x,this.top=e.y,this._originalOriginX=null,this._originalOriginY=null},_getLeftTopCoords:function(){return this.translateToOriginPoint(this.getCenterPoint(),"left","center")}})}(),function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{oCoords:null,intersectsWithRect:function(e,t){var n=this.oCoords,r=new fabric.Point(n.tl.x,n.tl.y),i=new fabric.Point(n.tr.x,n.tr.y),s=new fabric.Point(n.bl.x,n.bl.y),o=new fabric.Point(n.br.x,n.br.y),u=fabric.Intersection.intersectPolygonRectangle([r,i,o,s],e,t);return u.status==="Intersection"},intersectsWithObject:function(e){function t(e){return{tl:new fabric.Point(e.tl.x,e.tl.y),tr:new fabric.Point(e.tr.x,e.tr.y),bl:new fabric.Point(e.bl.x,e.bl.y),br:new fabric.Point(e.br.x,e.br.y)}}var n=t(this.oCoords),r=t(e.oCoords),i=fabric.Intersection.intersectPolygonPolygon([n.tl,n.tr,n.br,n.bl],[r.tl,r.tr,r.br,r.bl]);return i.status==="Intersection"},isContainedWithinObject:function(e){var t=e.getBoundingRect(),n=new fabric.Point(t.left,t.top),r=new fabric.Point(t.left+t.width,t.top+t.height);return this.isContainedWithinRect(n,r)},isContainedWithinRect:function(e,t){var n=this.getBoundingRect();return n.left>=e.x&&n.left+n.width<=t.x&&n.top>=e.y&&n.top+n.height<=t.y},containsPoint:function(e){var t=this._getImageLines(this.oCoords),n=this._findCrossPoints(e,t);return n!==0&&n%2===1},_getImageLines:function(e){return{topline:{o:e.tl,d:e.tr},rightline:{o:e.tr,d:e.br},bottomline:{o:e.br,d:e.bl},leftline:{o:e.bl,d:e.tl}}},_findCrossPoints:function(e,t){var n,r,i,s,o,u,a=0,f;for(var l in t){f=t[l];if(f.o.y=e.y&&f.d.y>=e.y)continue;f.o.x===f.d.x&&f.o.x>=e.x?(o=f.o.x,u=e.y):(n=0,r=(f.d.y-f.o.y)/(f.d.x-f.o.x),i=e.y-n*e.x,s=f.o.y-r*f.o.x,o=-(i-s)/(n-r),u=i+n*o),o>=e.x&&(a+=1);if(a===2)break}return a},getBoundingRectWidth:function(){return this.getBoundingRect().width},getBoundingRectHeight:function(){return this.getBoundingRect().height},getBoundingRect:function(){this.oCoords||this.setCoords();var e=[this.oCoords.tl.x,this.oCoords.tr.x,this.oCoords.br.x,this.oCoords.bl.x],t=fabric.util.array.min(e),n=fabric.util.array.max(e),r=Math.abs(t-n),i=[this.oCoords.tl.y,this.oCoords.tr.y,this.oCoords.br.y,this.oCoords.bl.y],s=fabric.util.array.min(i),o=fabric.util.array.max(i),u=Math.abs(s-o);return{left:t,top:s,width:r,height:u}},getWidth:function(){return this.width*this.scaleX},getHeight:function(){return this.height*this.scaleY},_constrainScale:function(e){return Math.abs(e)1?this.strokeWidth:0,n=e(this.angle),r=this.getViewportTransform(),i=function(e){return fabric.util.transformPoint(e,r)},s=this.width,o=this.height,u=this.strokeLineCap==="round"||this.strokeLineCap==="square",a=this.type==="line"&&this.width===1,f=this.type==="line"&&this.height===1,l=u&&f||this.type!=="line",c=u&&a||this.type!=="line";a?s=t:f&&(o=t),l&&(s+=t),c&&(o+=t),this.currentWidth=s*this.scaleX,this.currentHeight=o*this.scaleY,this.currentWidth<0&&(this.currentWidth=Math.abs(this.currentWidth));var h=Math.sqrt(Math.pow(this.currentWidth/2,2)+Math.pow(this.currentHeight/2,2)),p=Math.atan(isFinite(this.currentHeight/this.currentWidth)?this.currentHeight/this.currentWidth:0),d=Math.cos(p+n)*h,v=Math.sin(p+n)*h,m=Math.sin(n),g=Math.cos(n),y=this.getCenterPoint(),b=new fabric.Point(this.currentWidth,this.currentHeight),w=new fabric.Point(y.x-d,y.y-v),E=new fabric.Point(w.x+b.x*g,w.y+b.x*m),S=new fabric.Point(w.x-b.y*m,w.y+b.y*g),x=new fabric.Point(w.x+b.x/2*g,w.y+b.x/2*m),T=i(w),N=i(E),C=i(new fabric.Point(E.x-b.y*m,E.y+b.y*g)),k=i(S),L=i(new fabric.Point(w.x-b.y/2*m,w.y+b.y/2*g)),A=i(x),O=i(new fabric.Point(E.x-b.y/2*m,E.y+b.y/2*g)),M=i(new fabric.Point(S.x+b.x/2*g,S.y+b.x/2*m)),_=i(new fabric.Point(x.x,x.y)),D=Math.cos(p+n)*this.padding*Math.sqrt(2),P=Math.sin(p+n)*this.padding*Math.sqrt(2);return T=T.add(new fabric.Point(-D,-P)),N=N.add(new fabric.Point(P,-D)),C=C.add(new fabric.Point(D,P)),k=k.add(new fabric.Point(-P,D)),L=L.add(new fabric.Point((-D-P)/2,(-P+D)/2)),A=A.add(new fabric.Point((P-D)/2,-(P+D)/2)),O=O.add(new fabric.Point((P+D)/2,(P-D)/2)),M=M.add(new fabric.Point((D-P)/2,(D+P)/2)),_=_.add(new fabric.Point((P-D)/2,-(P+D)/2)),this.oCoords={tl:T,tr:N,br:C,bl:k,ml:L,mt:A,mr:O,mb:M,mtr:_},this._setCornerCoords&&this._setCornerCoords(),this}})}(),fabric.util.object.extend(fabric.Object.prototype,{sendToBack:function(){return this.group?fabric.StaticCanvas.prototype.sendToBack.call(this.group,this):this.canvas.sendToBack(this),this},bringToFront:function(){return this.group?fabric.StaticCanvas.prototype.bringToFront.call(this.group,this):this.canvas.bringToFront(this),this},sendBackwards:function(e){return this.group?fabric.StaticCanvas.prototype.sendBackwards.call(this.group,this,e):this.canvas.sendBackwards(this,e),this},bringForward:function(e){return this.group?fabric.StaticCanvas.prototype.bringForward.call(this.group,this,e):this.canvas.bringForward(this,e),this},moveTo:function(e){return this.group?fabric.StaticCanvas.prototype.moveTo.call(this.group,this,e):this.canvas.moveTo(this,e),this}}),fabric.util.object.extend(fabric.Object.prototype,{getSvgStyles:function(){var e=this.fill?this.fill.toLive?"url(#SVGID_"+this.fill.id+")":this.fill:"none",t=this.fillRule==="destination-over"?"evenodd":this.fillRule,n=this.stroke?this.stroke.toLive?"url(#SVGID_"+this.stroke.id+")":this.stroke:"none",r=this.strokeWidth?this.strokeWidth:"0",i=this.strokeDashArray?this.strokeDashArray.join(" "):"",s=this.strokeLineCap?this.strokeLineCap:"butt",o=this.strokeLineJoin?this.strokeLineJoin:"miter",u=this.strokeMiterLimit?this.strokeMiterLimit:"4",a=typeof this.opacity!="undefined"?this.opacity:"1",f=this.visible?"":" visibility: hidden;",l=this.shadow&&this.type!=="text"?"filter: url(#SVGID_"+this.shadow.id+");":"";return["stroke: ",n,"; ","stroke-width: ",r,"; ","stroke-dasharray: ",i,"; ","stroke-linecap: ",s,"; ","stroke-linejoin: ",o,"; ","stroke-miterlimit: ",u,"; ","fill: ",e,"; ","fill-rule: ",t,"; ","opacity: ",a,";",l,f].join("")},getSvgTransform:function(){if(this.group)return"";var e=fabric.util.toFixed,t=this.getAngle(),n=this.getViewportTransform(),r=fabric.util.transformPoint(this.getCenterPoint(),n),i=fabric.Object.NUM_FRACTION_DIGITS,s=this.type==="path-group"?"":"translate("+e(r.x,i)+" "+e(r.y,i)+")",o=t!==0?" rotate("+e(t,i)+")":"",u=this.scaleX===1&&this.scaleY===1&&n[0]===1&&n[3]===1?"":" scale("+e(this.scaleX*n[0],i)+" "+e(this.scaleY*n[3],i)+")",a=this.type==="path-group"?this.width*n[0]:0,f=this.flipX?" matrix(-1 0 0 1 "+a+" 0) ":"",l=this.type==="path-group"?this.height*n[3]:0,c=this.flipY?" matrix(1 0 0 -1 0 "+l+")":"";return[s,o,u,f,c].join("")},getSvgTransformMatrix:function(){return this.transformMatrix?" matrix("+this.transformMatrix.join(" ")+")":""},_createBaseSVGMarkup:function(){var e=[];return this.fill&&this.fill.toLive&&e.push(this.fill.toSVG(this,!1)),this.stroke&&this.stroke.toLive&&e.push(this.stroke.toSVG(this,!1)),this.shadow&&e.push(this.shadow.toSVG(this)),e}}),fabric.util.object.extend(fabric.Object.prototype,{hasStateChanged:function(){return this.stateProperties.some(function(e){return this.get(e)!==this.originalState[e]},this)},saveState:function(e){return this.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),e&&e.stateProperties&&e.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),this},setupState:function(){return this.originalState={},this.saveState(),this}}),function(){var e=fabric.util.degreesToRadians,t=function(){return typeof G_vmlCanvasManager!="undefined"};fabric.util.object.extend(fabric.Object.prototype,{_controlsVisibility:null,_findTargetCorner:function(e){if(!this.hasControls||!this.active)return!1;var t=e.x,n=e.y,r,i;for(var s in this.oCoords){if(!this.isControlVisible(s))continue;if(s==="mtr"&&!this.hasRotatingPoint)continue;if(!(!this.get("lockUniScaling")||s!=="mt"&&s!=="mr"&&s!=="mb"&&s!=="ml"))continue;i=this._getImageLines(this.oCoords[s].corner),r=this._findCrossPoints({x:t,y:n},i);if(r!==0&&r%2===1)return this.__corner=s,s}return!1},_setCornerCoords:function(){var t=this.oCoords,n=e(this.angle),r=e(45-this.angle),i=Math.sqrt(2*Math.pow(this.cornerSize,2))/2,s=i*Math.cos(r),o=i*Math.sin(r),u=Math.sin(n),a=Math.cos(n);t.tl.corner={tl:{x:t.tl.x-o,y:t.tl.y-s},tr:{x:t.tl.x+s,y:t.tl.y-o},bl:{x:t.tl.x-s,y:t.tl.y+o},br:{x:t.tl.x+o,y:t.tl.y+s}},t.tr.corner={tl:{x:t.tr.x-o,y:t.tr.y-s},tr:{x:t.tr.x+s,y:t.tr.y-o},br:{x:t.tr.x+o,y:t.tr.y+s},bl:{x:t.tr.x-s,y:t.tr.y+o}},t.bl.corner={tl:{x:t.bl.x-o,y:t.bl.y-s},bl:{x:t.bl.x-s,y:t.bl.y+o},br:{x:t.bl.x+o,y:t.bl.y+s},tr:{x:t.bl.x+s,y:t.bl.y-o}},t.br.corner={tr:{x:t.br.x+s,y:t.br.y-o},bl:{x:t.br.x-s,y:t.br.y+o},br:{x:t.br.x+o,y:t.br.y+s},tl:{x:t.br.x-o,y:t.br.y-s}},t.ml.corner={tl:{x:t.ml.x-o,y:t.ml.y-s},tr:{x:t.ml.x+s,y:t.ml.y-o},bl:{x:t.ml.x-s,y:t.ml.y+o},br:{x:t.ml.x+o,y:t.ml.y+s}},t.mt.corner={tl:{x:t.mt.x-o,y:t.mt.y-s},tr:{x:t.mt.x+s,y:t.mt.y-o},bl:{x:t.mt.x-s,y:t.mt.y+o},br:{x:t.mt.x+o,y:t.mt.y+s}},t.mr.corner={tl:{x:t.mr.x-o,y:t.mr.y-s},tr:{x:t.mr.x+s,y:t.mr.y-o},bl:{x:t.mr.x-s,y:t.mr.y+o},br:{x:t.mr.x+o,y:t.mr.y+s}},t.mb.corner={tl:{x:t.mb.x-o,y:t.mb.y-s},tr:{x:t.mb.x+s,y:t.mb.y-o},bl:{x:t.mb.x-s,y:t.mb.y+o},br:{x:t.mb.x+o,y:t.mb.y+s}},t.mtr.corner={tl:{x:t.mtr.x-o+u*this.rotatingPointOffset,y:t.mtr.y-s-a*this.rotatingPointOffset},tr:{x:t.mtr.x+s+u*this.rotatingPointOffset,y:t.mtr.y-o-a*this.rotatingPointOffset},bl:{x:t.mtr.x-s+u*this.rotatingPointOffset,y:t.mtr.y+o-a*this.rotatingPointOffset},br:{x:t.mtr.x+o+u*this.rotatingPointOffset,y:t.mtr.y+s-a*this.rotatingPointOffset}}},drawBorders:function(e){if(!this.hasBorders)return this;var t=this.padding,n=t*2,r=this.getViewportTransform();e.save(),e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=this.borderColor;var i=1/this._constrainScale(this.scaleX),s=1/this._constrainScale(this.scaleY);e.lineWidth=1/this.borderScaleFactor;var o=this.getWidth(),u=this.getHeight(),a=this.strokeWidth>1?this.strokeWidth:0,f=this.strokeLineCap==="round"||this.strokeLineCap==="square",l=this.type==="line"&&this.width===1,c=this.type==="line"&&this.height===1,h=f&&c||this.type!=="line",p=f&&l||this.type!=="line";l?o=a/i:c&&(u=a/s),h&&(o+=a/i),p&&(u+=a/s);var d=fabric.util.transformPoint(new fabric.Point(o,u),r,!0),v=d.x,m=d.y;this.group&&(v*=this.group.scaleX,m*=this.group.scaleY),e.strokeRect(~~(-(v/2)-t)-.5,~~(-(m/2)-t)-.5,~~(v+n)+1,~~(m+n)+1);if(this.hasRotatingPoint&&this.isControlVisible("mtr")&&!this.get("lockRotation")&&this.hasControls){var g=(-m-t*2)/2;e.beginPath(),e.moveTo(0,g),e.lineTo(0,g-this.rotatingPointOffset),e.closePath(),e.stroke()}return e.restore(),this},drawControls:function(e){if(!this.hasControls)return this;var t=this.cornerSize,n=t/2,r=this.getViewportTransform(),i=this.strokeWidth>1?this.strokeWidth:0,s=this.width,o=this.height,u=this.strokeLineCap==="round"||this.strokeLineCap==="square",a=this.type==="line"&&this.width===1,f=this.type==="line"&&this.height===1,l=u&&f||this.type!=="line",c=u&&a||this.type!=="line";a?s=i:f&&(o=i),l&&(s+=i),c&&(o+=i),s*=this.scaleX,o*=this.scaleY;var h=fabric.util.transformPoint(new fabric.Point(s,o),r,!0),p=h.x,d=h.y,v=-(p/2),m=-(d/2),g=this.padding,y=n,b=n-t,w=this.transparentCorners?"strokeRect":"fillRect";return e.save(),e.lineWidth=1,e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=e.fillStyle=this.cornerColor,this._drawControl("tl",e,w,v-y-g,m-y-g),this._drawControl("tr",e,w,v+p-y+g,m-y-g),this._drawControl("bl",e,w,v-y-g,m+d+b+g),this._drawControl("br",e,w,v+p+b+g,m+d+b+g),this.get("lockUniScaling")||(this._drawControl("mt",e,w,v+p/2-y,m-y-g),this._drawControl("mb",e,w,v+p/2-y,m+d+b+g),this._drawControl("mr",e,w,v+p+b+g,m+d/2-y),this._drawControl("ml",e,w,v-y-g,m+d/2-y)),this.hasRotatingPoint&&this._drawControl("mtr",e,w,v+p/2-y,m-this.rotatingPointOffset-this.cornerSize/2-g),e.restore(),this},_drawControl:function(e,n,r,i,s){var o=this.cornerSize;this.isControlVisible(e)&&(t()||this.transparentCorners||n.clearRect(i,s,o,o),n[r](i,s,o,o))},isControlVisible:function(e){return this._getControlsVisibility()[e]},setControlVisible:function(e,t){return this._getControlsVisibility()[e]=t,this},setControlsVisibility:function(e){e||(e={});for(var t in e)this.setControlVisible(t,e[t]);return this},_getControlsVisibility:function(){return this._controlsVisibility||(this._controlsVisibility={tl:!0,tr:!0,br:!0,bl:!0,ml:!0,mt:!0,mr:!0,mb:!0,mtr:!0}),this._controlsVisibility}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{FX_DURATION:500,fxCenterObjectH:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("left"),endValue:this.getCenter().left,duration:this.FX_DURATION,onChange:function(t){e.set("left",t),s.renderAll(),i()},onComplete:function(){e.setCoords(),r()}}),this},fxCenterObjectV:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("top"),endValue:this.getCenter().top,duration:this.FX_DURATION,onChange:function(t){e.set("top",t),s.renderAll(),i()},onComplete:function(){e.setCoords(),r()}}),this},fxRemove:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("opacity"),endValue:0,duration:this.FX_DURATION,onStart:function(){e.set("active",!1)},onChange:function(t){e.set("opacity",t),s.renderAll(),i()},onComplete:function(){s.remove(e),r()}}),this}}),fabric.util.object.extend(fabric.Object.prototype,{animate:function(){if(arguments[0]&&typeof arguments[0]=="object"){var e=[],t,n;for(t in arguments[0])e.push(t);for(var r=0,i=e.length;rthis.x2?this.x2:this.x1),i=-this.height/2-(this.y1>this.y2?this.y2:this.y1);n="translate("+r+", "+i+") "}return t.push("\n'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Line.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" ")),t.Line.fromElement=function(e,r){var i=t.parseAttributes(e,t.Line.ATTRIBUTE_NAMES),s=[i.x1||0,i.y1||0,i.x2||0,i.y2||0];return new t.Line(s,n(i,r))},t.Line.fromObject=function(e){var n=[e.x1,e.y1,e.x2,e.y2];return new t.Line(n,e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function i(e){return"radius"in e&&e.radius>0}var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Circle){t.warn("fabric.Circle is already defined.");return}t.Circle=t.util.createClass(t.Object,{type:"circle",radius:0,initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("radius",e.radius||0)},_set:function(e,t){return this.callSuper("_set",e,t),e==="radius"&&this.setRadius(t),this},toObject:function(e){return r(this.callSuper("toObject",e),{radius:this.get("radius")})},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=0,r=0;return this.group&&(n=this.left+this.radius,r=this.top+ +this.radius),t.push("\n'),e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.arc(t?this.left+this.radius:0,t?this.top+this.radius:0,this.radius,0,n,!1),this._renderFill(e),this._renderStroke(e)},getRadiusX:function(){return this.get("radius")*this.get("scaleX")},getRadiusY:function(){return this.get("radius")*this.get("scaleY")},setRadius:function(e){this.radius=e,this.set("width",e*2).set("height",e*2)},complexity:function(){return 1}}),t.Circle.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy r".split(" ")),t.Circle.fromElement=function(e,n){n||(n={});var s=t.parseAttributes(e,t.Circle.ATTRIBUTE_NAMES);if(!i(s))throw new Error("value of `r` attribute is required and can not be negative");s.left=s.left||0,s.top=s.top||0;var o=new t.Circle(r(s,n));return o.left-=o.radius,o.top-=o.radius,o},t.Circle.fromObject=function(e){return new t.Circle(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={});if(t.Triangle){t.warn("fabric.Triangle is already defined");return}t.Triangle=t.util.createClass(t.Object,{type:"triangle",initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("width",e.width||100).set("height",e.height||100)},_render:function(e){var t=this.width/2,n=this.height/2;e.beginPath(),e.moveTo(-t,n),e.lineTo(0,-n),e.lineTo(t,n),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=this.width/2,r=this.height/2;e.beginPath(),t.util.drawDashedLine(e,-n,r,0,-r,this.strokeDashArray),t.util.drawDashedLine(e,0,-r,n,r,this.strokeDashArray),t.util.drawDashedLine(e,n,r,-n,r,this.strokeDashArray),e.closePath()},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=this.width/2,r=this.height/2,i=[-n+" "+r,"0 "+ -r,n+" "+r].join(",");return t.push("'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Triangle.fromObject=function(e){return new t.Triangle(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Ellipse){t.warn("fabric.Ellipse is already defined.");return}t.Ellipse=t.util.createClass(t.Object,{type:"ellipse",rx:0,ry:0,initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("rx",e.rx||0),this.set("ry",e.ry||0),this.set("width",this.get("rx")*2),this.set("height",this.get("ry")*2)},toObject:function(e){return r(this.callSuper("toObject",e),{rx:this.get("rx"),ry:this.get("ry")})},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=0,r=0;return this.group&&(n=this.left+this.rx,r=this.top+this.ry),t.push("\n'),e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.save(),e.transform(1,0,0,this.ry/this.rx,0,0),e.arc(t?this.left+this.rx:0,t?(this.top+this.ry)*this.rx/this.ry:0,this.rx,0,n,!1),e.restore(),this._renderFill(e),this._renderStroke(e)},complexity:function(){return 1}}),t.Ellipse.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" ")),t.Ellipse.fromElement=function(e,n){n||(n={});var i=t.parseAttributes(e,t.Ellipse.ATTRIBUTE_NAMES);i.left=i.left||0,i.top=i.top||0;var s=new t.Ellipse(r(i,n));return s.top-=s.ry,s.left-=s.rx,s},t.Ellipse.fromObject=function(e){return new t.Ellipse(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;if(t.Rect){console.warn("fabric.Rect is already defined");return}var r=t.Object.prototype.stateProperties.concat();r.push("rx","ry","x","y"),t.Rect=t.util.createClass(t.Object,{stateProperties:r,type:"rect",rx:0,ry:0,strokeDashArray:null,initialize:function(e){e=e||{},this.callSuper("initialize",e),this._initRxRy()},_initRxRy:function(){this.rx&&!this.ry?this.ry=this.rx:this.ry&&!this.rx&&(this.rx=this.ry)},_render:function(e,t){if(this.width===1&&this.height===1){e.fillRect(0,0,1,1);return}var n=this.rx?Math.min(this.rx,this.width/2):0,r=this.ry?Math.min(this.ry,this.height/2):0,i=this.width,s=this.height,o=t?this.left:0,u=t?this.top:0,a=n!==0||r!==0,f=.4477152502;e.beginPath(),t||e.translate(-this.width/2,-this.height/2),e.moveTo(o+n,u),e.lineTo(o+i-n,u),a&&e.bezierCurveTo(o+i-f*n,u,o+i,u+f*r,o+i,u+r),e.lineTo(o+i,u+s-r),a&&e.bezierCurveTo(o+i,u+s-f*r,o+i-f*n,u+s,o+i-n,u+s),e.lineTo(o+n,u+s),a&&e.bezierCurveTo(o+f*n,u+s,o,u+s-f*r,o,u+s-r),e.lineTo(o,u+r),a&&e.bezierCurveTo(o,u+f*r,o+f*n,u,o+n,u),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=-this.width/2,r=-this.height/2,i=this.width,s=this.height;e.beginPath(),t.util.drawDashedLine(e,n,r,n+i,r,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r,n+i,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r+s,n,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n,r+s,n,r,this.strokeDashArray),e.closePath()},toObject:function(e){var t=n(this.callSuper("toObject",e),{rx:this.get("rx")||0,ry:this.get("ry")||0});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=this.left,r=this.top;return this.group||(n=-this.width/2,r=-this.height/2),t.push("\n'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Rect.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" ")),t.Rect.fromElement=function(e,r){if(!e)return null;r=r||{};var i=t.parseAttributes(e,t.Rect.ATTRIBUTE_NAMES);return i.left=i.left||0,i.top=i.top||0,new t.Rect(n(r?t.util.object.clone(r):{},i))},t.Rect.fromObject=function(e){return new t.Rect(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.toFixed;if(t.Polyline){t.warn("fabric.Polyline is already defined");return}t.Polyline=t.util.createClass(t.Object,{type:"polyline",points:null,initialize:function(e,t,n){t=t||{},this.set("points",e),this.callSuper("initialize",t),this._calcDimensions(n)},_calcDimensions:function(e){return t.Polygon.prototype._calcDimensions.call(this,e)},toObject:function(e){return t.Polygon.prototype.toObject.call(this,e)},toSVG:function(e){var t=[],r=this._createBaseSVGMarkup();for(var i=0,s=this.points.length;i\n'),e?e(r.join("")):r.join("")},_render:function(e){var t;e.beginPath(),e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n\n'),e?e(n.join("")):n.join("")},_render:function(e){var t;e.beginPath(),e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n"},toObject:function(e){var t=i(this.callSuper("toObject",e),{path:this.path.map(function(e){return e.slice()}),pathOffset:this.pathOffset});return this.sourcePath&&(t.sourcePath=this.sourcePath),this.transformMatrix&&(t.transformMatrix=this.transformMatrix),t},toDatalessObject:function(e){var t=this.toObject(e);return this.sourcePath&&(t.path=this.sourcePath),delete t.sourcePath,t},toSVG:function(e){var t=[],n=this._createBaseSVGMarkup();for(var r=0,i=this.path.length;r\n"),e?e(n.join("")):n.join("")},complexity:function(){return this.path.length},_parsePath:function(){var e=[],t=[],n,r,i=/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/ig,s,o;for(var f=0,l,c=this.path.length;fv)for(var g=1,y=l.length;g\n"];for(var i=0,s=t.length;i\n"),e?e(r.join("")):r.join("")},toString:function(){return"#"},isSameColor:function(){var e=(this.getObjects()[0].get("fill")||"").toLowerCase();return this.getObjects().every(function(t){return(t.get("fill")||"").toLowerCase()===e})},complexity:function(){return this.paths.reduce(function(e,t){return e+(t&&t.complexity?t.complexity():0)},0)},getObjects:function(){return this.paths}}),t.PathGroup.fromObject=function(e,n){typeof e.paths=="string"?t.loadSVGFromURL(e.paths,function(r){var i=e.paths;delete e.paths;var s=t.util.groupSVGElements(r,e,i);n(s)}):t.util.enlivenObjects(e.paths,function(r){delete e.paths,n(new t.PathGroup(r,e))})},t.PathGroup.async=!0}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.array.min,i=t.util.array.max,s=t.util.array.invoke;if(t.Group)return;var o={lockMovementX:!0,lockMovementY:!0,lockRotation:!0,lockScalingX:!0,lockScalingY:!0,lockUniScaling:!0};t.Group=t.util.createClass(t.Object,t.Collection,{type:"group",initialize:function(e,t){t=t||{},this._objects=e||[];for(var r=this._objects.length;r--;)this._objects[r].group=this;this.originalState={},this.callSuper("initialize"),this._calcBounds(),this._updateObjectsCoords(),t&&n(this,t),this._setOpacityIfSame(),this.setCoords(),this.saveCoords()},_updateObjectsCoords:function(){this.forEachObject(this._updateObjectCoords,this)},_updateObjectCoords:function(e){var t=e.getLeft(),n=e.getTop();e.set({originalLeft:t,originalTop:n,left:t-this.left,top:n-this.top}),e.setCoords(),e.__origHasControls=e.hasControls,e.hasControls=!1},toString:function(){return"#"},addWithUpdate:function(e){return this._restoreObjectsState(),e&&(this._objects.push(e),e.group=this),this.forEachObject(this._setObjectActive,this),this._calcBounds(),this._updateObjectsCoords(),this},_setObjectActive:function(e){e.set("active",!0),e.group=this},removeWithUpdate:function(e){return this._moveFlippedObject(e),this._restoreObjectsState(),this.forEachObject(this._setObjectActive,this),this.remove(e),this._calcBounds(),this._updateObjectsCoords(),this},_onObjectAdded:function(e){e.group=this},_onObjectRemoved:function(e){delete e.group,e.set("active",!1)},delegatedProperties:{fill:!0,opacity:!0,fontFamily:!0,fontWeight:!0,fontSize:!0,fontStyle:!0,lineHeight:!0,textDecoration:!0,textAlign:!0,backgroundColor:!0},_set:function(e,t){if(e in this.delegatedProperties){var n=this._objects.length;this[e]=t;while(n--)this._objects[n].set(e,t)}else this[e]=t},toObject:function(e){return n(this.callSuper("toObject",e),{objects:s(this._objects,"toObject",e)})},render:function(e){if(!this.visible)return;e.save(),this.clipTo&&t.util.clipContext(this,e);for(var n=0,r=this._objects.length;n\n'];for(var n=0,r=this._objects.length;n\n"),e?e(t.join("")):t.join("")},get:function(e){if(e in o){if(this[e])return this[e];for(var t=0,n=this._objects.length;t\n','\n");if(this.stroke||this.strokeDashArray){var i=this.fill;this.fill=null,t.push("\n'),this.fill=i}return t.push("
    \n"),e?e(t.join("")):t.join("")},getSrc:function(){if(this.getElement())return this.getElement().src||this.getElement()._src},toString:function(){return'#'},clone:function(e,t){this.constructor.fromObject(this.toObject(t),e)},applyFilters:function(e){if(!this._originalElement)return;if(this.filters.length===0){this._element=this._originalElement,e&&e();return}var t=this._originalElement,n=fabric.util.createCanvasElement(),r=fabric.util.createImage(),i=this;return n.width=t.width,n.height=t.height,n.getContext("2d").drawImage(t,0,0,t.width,t.height),this.filters.forEach(function(e){e&&e.applyTo(n)}),r.width=t.width,r.height=t.height,fabric.isLikelyNode?(r.src=n.toBuffer(undefined,fabric.Image.pngCompression),i._element=r,e&&e()):(r.onload=function(){i._element=r,e&&e(),r.onload=n=t=null},r.src=n.toDataURL("image/png")),this},_render:function(e,t){this._element&&e.drawImage(this._element,t?this.left:-this.width/2,t?this.top:-this.height/2,this.width,this.height),this._renderStroke(e)},_resetWidthHeight:function(){var e=this.getElement();this.set("width",e.width),this.set("height",e.height)},_initElement:function(e){this.setElement(fabric.util.getById(e)),fabric.util.addClass(this.getElement(),fabric.Image.CSS_CANVAS)},_initConfig:function(e){e||(e={}),this.setOptions(e),this._setWidthHeight(e),this._element&&this.crossOrigin&&(this._element.crossOrigin=this.crossOrigin)},_initFilters:function(e,t){e.filters&&e.filters.length?fabric.util.enlivenObjects(e.filters,function(e){t&&t(e)},"fabric.Image.filters"):t&&t()},_setWidthHeight:function(e){this.width="width"in e?e.width:this.getElement()?this.getElement().width||0:0,this.height="height"in e?e.height:this.getElement()?this.getElement().height||0:0},complexity:function(){return 1}}),fabric.Image.CSS_CANVAS="canvas-img",fabric.Image.prototype.getSvgSrc=fabric.Image.prototype.getSrc,fabric.Image.fromObject=function(e,t){fabric.util.loadImage(e.src,function(n){fabric.Image.prototype._initFilters.call(e,e,function(r){e.filters=r||[];var i=new fabric.Image(n,e);t&&t(i)})},null,e.crossOrigin)},fabric.Image.fromURL=function(e,t,n){fabric.util.loadImage(e,function(e){t(new fabric.Image(e,n))},null,n&&n.crossOrigin)},fabric.Image.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y width height xlink:href".split(" ")),fabric.Image.fromElement=function(e,n,r){var i=fabric.parseAttributes(e,fabric.Image.ATTRIBUTE_NAMES);fabric.Image.fromURL(i["xlink:href"],n,t(r?fabric.util.object.clone(r):{},i))},fabric.Image.async=!0,fabric.Image.pngCompression=1}(typeof exports!="undefined"?exports:this),fabric.util.object.extend(fabric.Object.prototype,{_getAngleValueForStraighten:function(){var e=this.getAngle()%360;return e>0?Math.round((e-1)/90)*90:Math.round(e/90)*90},straighten:function(){return this.setAngle(this._getAngleValueForStraighten()),this},fxStraighten:function(e){e=e||{};var t=function(){},n=e.onComplete||t,r=e.onChange||t,i=this;return fabric.util.animate({startValue:this.get("angle"),endValue:this._getAngleValueForStraighten(),duration:this.FX_DURATION,onChange:function(e){i.setAngle(e),r()},onComplete:function(){i.setCoords(),n()},onStart:function(){i.set("active",!1)}}),this}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{straightenObject:function(e){return e.straighten(),this.renderAll(),this},fxStraightenObject:function(e){return e.fxStraighten({onChange:this.renderAll.bind(this)}),this}}),fabric.Image.filters=fabric.Image.filters||{},fabric.Image.filters.BaseFilter=fabric.util.createClass({type:"BaseFilter",toObject:function(){return{type:this.type}},toJSON:function(){return this.toObject()}}),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;t.Image.filters.Brightness=t.util.createClass(t.Image.filters.BaseFilter,{type:"Brightness",initialize:function(e){e=e||{},this.brightness=e.brightness||0},applyTo:function(e){var t=e.getContext("2d"),n=t.getImageData(0,0,e.width,e.height),r=n.data,i=this.brightness;for(var s=0,o=r.length;sa||C<0||C>u)continue;var k=(N*u+C)*4,L=t[x*i+T];b+=o[k]*L,w+=o[k+1]*L,E+=o[k+2]*L,S+=o[k+3]*L}h[y]=b,h[y+1]=w,h[y+2]=E,h[y+3]=S+p*(255-S)}n.putImageData(c,0,0)},toObject:function(){return n(this.callSuper("toObject"),{opaque:this.opaque,matrix:this.matrix})}}),t.Image.filters.Convolute.fromObject=function(e){return new t.Image.filters.Convolute(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;t.Image.filters.GradientTransparency=t.util.createClass(t.Image.filters.BaseFilter,{type:"GradientTransparency",initialize:function(e){e=e||{},this.threshold=e.threshold||100},applyTo:function(e){var t=e.getContext("2d"),n=t.getImageData(0,0,e.width,e.height),r=n.data,i=this.threshold,s=r.length;for(var o=0,u=r.length;o-1?e.channel:0},applyTo:function(e){if(!this.mask)return;var n=e.getContext("2d"),r=n.getImageData(0,0,e.width,e.height),i=r.data,s=this.mask.getElement(),o=t.util.createCanvasElement(),u=this.channel,a,f=r.width*r.height*4;o.width=s.width,o.height=s.height,o.getContext("2d").drawImage(s,0,0,s.width,s.height);var l=o.getContext("2d").getImageData(0,0,s.width,s.height),c=l.data;for(a=0;ao&&f>o&&l>o&&u(a-f)'},_render:function(e){typeof Cufon=="undefined"||this.useNative===!0?this._renderViaNative(e):this._renderViaCufon(e)},_renderViaNative:function(e){var n=this.text.split(this._reNewline);this._setTextStyles(e),this.width=this._getTextWidth(e,n),this.height=this._getTextHeight(e,n),this.clipTo&&t.util.clipContext(this,e),this._renderTextBackground(e,n),this._translateForTextAlign(e),this._renderText(e,n),this.textAlign!=="left"&&this.textAlign!=="justify"&&e.restore(),this._renderTextDecoration(e,n),this.clipTo&&e.restore(),this._setBoundaries(e,n),this._totalLineHeight=0},_renderText:function(e,t){e.save(),this._setShadow(e),this._setupFillRule(e),this._renderTextFill(e,t),this._renderTextStroke(e,t),this._restoreFillRule(e),this._removeShadow(e),e.restore()},_translateForTextAlign:function(e){this.textAlign!=="left"&&this.textAlign!=="justify"&&(e.save(),e.translate(this.textAlign==="center"?this.width/2:this.width,0))},_setBoundaries:function(e,t){this._boundaries=[];for(var n=0,r=t.length;nn&&(n=s)}return n},_renderChars:function(e,t,n,r,i){t[e](n,r,i)},_renderTextLine:function(e,t,n,r,i,s){i-=this.fontSize/4;if(this.textAlign!=="justify"){this._renderChars(e,t,n,r,i,s);return}var o=t.measureText(n).width,u=this.width;if(u>o){var a=n.split(/\s+/),f=t.measureText(n.replace(/\s+/g,"")).width,l=u-f,c=a.length-1,h=l/c,p=0;for(var d=0,v=a.length;d-1&&i(this.fontSize*this.lineHeight),this.textDecoration.indexOf("line-through")>-1&&i(this.fontSize*this.lineHeight-this.fontSize/2),this.textDecoration.indexOf("overline")>-1&&i(this.fontSize*this.lineHeight-this.fontSize)},_getFontDeclaration:function(){return[t.isLikelyNode?this.fontWeight:this.fontStyle,t.isLikelyNode?this.fontStyle:this.fontWeight,this.fontSize+"px",t.isLikelyNode?'"'+this.fontFamily+'"':this.fontFamily].join(" ")},render:function(e,t){if(!this.visible)return;e.save(),this._transform(e,t);var n=this.transformMatrix,r=this.group&&this.group.type==="path-group";r&&e.translate(-this.group.width/2,-this.group.height/2),n&&e.transform(n[0],n[1],n[2],n[3],n[4],n[5]),r&&e.translate(this.left,this.top),this._render(e),e.restore()},toObject:function(e){var t=n(this.callSuper("toObject",e),{text:this.text,fontSize:this.fontSize,fontWeight:this.fontWeight,fontFamily:this.fontFamily,fontStyle:this.fontStyle,lineHeight:this.lineHeight,textDecoration:this.textDecoration,textAlign:this.textAlign,path:this.path,textBackgroundColor:this.textBackgroundColor,useNative:this.useNative});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=[],n=this.text.split(this._reNewline),r=this._getSVGLeftTopOffsets(n),i=this._getSVGTextAndBg(r.lineTop,r.textLeft,n),s=this._getSVGShadows(r.lineTop,n);return r.textTop+=this._fontAscent?this._fontAscent/5*this.lineHeight:0,this._wrapSVGTextAndBg(t,i,s,r),e?e(t.join("")):t.join("")},_getSVGLeftTopOffsets:function(e){var t=this.useNative?this.fontSize*this.lineHeight:-this._fontAscent-this._fontAscent/5*this.lineHeight,n=-(this.width/2),r=this.useNative?this.fontSize-1:this.height/2-e.length*this.fontSize-this._totalLineHeight;return{textLeft:n+(this.group?this.left:0),textTop:r+(this.group?this.top:0),lineTop:t}},_wrapSVGTextAndBg:function(e,t,n,r){e.push('\n',t.textBgRects.join(""),"',n.join(""),t.textSpans.join(""),"\n","\n")},_getSVGShadows:function(e,n){var r=[],s,o,u=1;if(!this.shadow||!this._boundaries)return r;for(s=0,o=n.length;s",t.util.string.escapeXml(n[s]),""),u=1}else u++;return r},_getSVGTextAndBg:function(e,t,n){var r=[],i=[],s=1;this._setSVGBg(i);for(var o=0,u=n.length;o",t.util.string.escapeXml(e),"")},_setSVGTextLineBg:function(e,t,n,r){e.push("\n')},_setSVGBg:function(e){this.backgroundColor&&this._boundaries&&e.push("')},_getFillAttributes:function(e){var n=e&&typeof e=="string"?new t.Color(e):"";return!n||!n.getSource()||n.getAlpha()===1?'fill="'+e+'"':'opacity="'+n.getAlpha()+'" fill="'+n.setAlpha(1).toRgb()+'"'},_set:function(e,t){e==="fontFamily"&&this.path&&(this.path=this.path.replace(/(.*?)([^\/]*)(\.font\.js)/,"$1"+t+"$3")),this.callSuper("_set",e,t),e in this._dimensionAffectingProps&&(this._initDimensions(),this.setCoords())},complexity:function(){return 1}}),t.Text.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size text-decoration text-anchor".split(" ")),t.Text.DEFAULT_SVG_FONT_SIZE=16,t.Text.fromElement=function(e,n){if(!e)return null;var r=t.parseAttributes(e,t.Text.ATTRIBUTE_NAMES);n=t.util.object.extend(n?t.util.object.clone(n):{},r),"dx"in r&&(n.left+=r.dx),"dy"in r&&(n.top+=r.dy),"fontSize"in n||(n.fontSize=t.Text.DEFAULT_SVG_FONT_SIZE),n.originX||(n.originX="left");var i=new t.Text(e.textContent,n),s=0;return i.originX==="left"&&(s=i.getWidth()/2),i.originX==="right"&&(s=-i.getWidth()/2),i.set({left:i.getLeft()+s,top:i.getTop()-i.getHeight()/2}),i},t.Text.fromObject=function(e){return new t.Text(e.text,r(e))},t.util.createAccessors(t.Text)}(typeof exports!="undefined"?exports:this),function(){var e=fabric.util.object.clone;fabric.IText=fabric.util.createClass(fabric.Text,fabric.Observable,{type:"i-text",selectionStart:0,selectionEnd:0,selectionColor:"rgba(17,119,255,0.3)",isEditing:!1,editable:!0,editingBorderColor:"rgba(102,153,255,0.25)",cursorWidth:2,cursorColor:"#333",cursorDelay:1e3,cursorDuration:600,styles:null,caching:!0,_skipFillStrokeCheck:!0,_reSpace:/\s|\n/,_fontSizeFraction:4,_currentCursorOpacity:0,_selectionDirection:null,_abortCursorAnimation:!1,_charWidthsCache:{},initialize:function(e,t){this.styles=t?t.styles||{}:{},this.callSuper("initialize",e,t),this.initBehavior(),fabric.IText.instances.push(this),this.__lineWidths={},this.__lineHeights={},this.__lineOffsets={}},isEmptyStyles:function(){if(!this.styles)return!0;var e=this.styles;for(var t in e)for(var n in e[t])for(var r in e[t][n])return!1;return!0},setSelectionStart:function(e){this.selectionStart!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})),this.selectionStart=e,this.hiddenTextarea&&(this.hiddenTextarea.selectionStart=e)},setSelectionEnd:function(e){this.selectionEnd!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})),this.selectionEnd=e,this.hiddenTextarea&&(this.hiddenTextarea.selectionEnd=e)},getSelectionStyles:function(e,t){if(arguments.length===2){var n=[];for(var r=e;r=r.charIndex&&(a!==o||hs&&a-1&&this._renderCharDecorationAtOffset(e,n,r+this.fontSize/this._fontSizeFraction,i,0,this.fontSize/20),u.indexOf("line-through")>-1&&this._renderCharDecorationAtOffset(e,n,r+this.fontSize/this._fontSizeFraction,i,o/2,a/20),u.indexOf("overline")>-1&&this._renderCharDecorationAtOffset(e,n,r,i,s-this.fontSize/this._fontSizeFraction,this.fontSize/20)},_renderCharDecorationAtOffset:function(e,t,n,r,i,s){e.fillRect(t,n-i,r,s)},_renderTextLine:function(e,t,n,r,i,s){i+=this.fontSize/4,this.callSuper("_renderTextLine",e,t,n,r,i,s)},_renderTextDecoration:function(e,t){if(this.isEmptyStyles())return this.callSuper("_renderTextDecoration",e,t)},_renderTextLinesBackground:function(e,t){if(!this.textBackgroundColor&&!this.styles)return;e.save(),this.textBackgroundColor&&(e.fillStyle=this.textBackgroundColor);var n=0,r=this.fontSize/this._fontSizeFraction;for(var i=0,s=t.length;in&&(n=s)}return n},_getHeightOfLine:function(e,t,n){n=n||this.text.split(this._reNewline);var r=this._getHeightOfChar(e,n[t][0],t,0),i=n[t],s=i.split("");for(var o=1,u=s.length;or&&(r=a)}return r*this.lineHeight},_getTextHeight:function(e,t){var n=0;for(var r=0,i=t.length;r-1)t++,n--;return e-t},findWordBoundaryRight:function(e){var t=0,n=e;if(this._reSpace.test(this.text.charAt(n)))while(this._reSpace.test(this.text.charAt(n)))t++,n++;while(/\S/.test(this.text.charAt(n))&&n-1)t++,n--;return e-t},findLineBoundaryRight:function(e){var t=0,n=e;while(!/\n/.test(this.text.charAt(n))&&n0&&nr;s?this.removeStyleObject(s,n+1):this.removeStyleObject(this.get2DCursorLocation(n).charIndex===0,n)}this.text=this.text.slice(0,e)+this.text.slice(t)},insertChars:function(e){var t=this.text.slice(this.selectionStart,this.selectionStart+1)==="\n";this.text=this.text.slice(0,this.selectionStart)+e+this.text.slice(this.selectionEnd),this.selectionStart===this.selectionEnd&&this.insertStyleObjects(e,t,this.copiedStyles),this.selectionStart+=e.length,this.selectionEnd=this.selectionStart,this.canvas&&this.canvas.renderAll().renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},insertNewlineStyleObject:function(t,n,r){this.shiftLineStyles(t,1),this.styles[t+1]||(this.styles[t+1]={});var i=this.styles[t][n-1],s={};if(r)s[0]=e(i),this.styles[t+1]=s;else{for(var o in this.styles[t])parseInt(o,10)>=n&&(s[parseInt(o,10)-n]=this.styles[t][o],delete this.styles[t][o]);this.styles[t+1]=s}},insertCharStyleObject:function(t,n,r){var i=this.styles[t],s=e(i);n===0&&!r&&(n=1);for(var o in s){var u=parseInt(o,10);u>=n&&(i[u+1]=s[u])}this.styles[t][n]=r||e(i[n-1])},insertStyleObjects:function(e,t,n){if(this.isEmptyStyles())return;var r=this.get2DCursorLocation(),i=r.lineIndex,s=r.charIndex;this.styles[i]||(this.styles[i]={}),e==="\n"?this.insertNewlineStyleObject(i,s,t):n?this._insertStyles(n):this.insertCharStyleObject(i,s)},_insertStyles:function(e){for(var t=0,n=e.length;tt&&(this.styles[s+n]=r[s])}},removeStyleObject:function(t,n){var r=this.get2DCursorLocation(n),i=r.lineIndex,s=r.charIndex;if(t){var o=this.text.split(this._reNewline),u=o[i-1],a=u?u.length:0;this.styles[i-1]||(this.styles[i-1]={});for(s in this.styles[i])this.styles[i-1][parseInt(s,10)+a]=this.styles[i][s];this.shiftLineStyles(i,-1)}else{var f=this.styles[i];if(f){var l=this.selectionStart===this.selectionEnd?-1:0;delete f[s+l]}var c=e(f);for(var h in c){var p=parseInt(h,10);p>=s&&p!==0&&(f[p-1]=c[p],delete f[p])}}},insertNewline:function(){this.insertChars("\n")}})}(),fabric.util.object.extend(fabric.IText.prototype,{initDoubleClickSimulation:function(){this.__lastClickTime=+(new Date),this.__lastLastClickTime=+(new Date),this.__lastPointer={},this.on("mousedown",this.onMouseDown.bind(this))},onMouseDown:function(e){this.__newClickTime=+(new Date);var t=this.canvas.getPointer(e.e);this.isTripleClick(t)?(this.fire("tripleclick",e),this._stopEvent(e.e)):this.isDoubleClick(t)&&(this.fire("dblclick",e),this._stopEvent(e.e)),this.__lastLastClickTime=this.__lastClickTime,this.__lastClickTime=this.__newClickTime,this.__lastPointer=t,this.__lastIsEditing=this.isEditing,this.__lastSelected=this.selected},isDoubleClick:function(e){return this.__newClickTime-this.__lastClickTime<500&&this.__lastPointer.x===e.x&&this.__lastPointer.y===e.y&&this.__lastIsEditing},isTripleClick:function(e){return this.__newClickTime-this.__lastClickTime<500&&this.__lastClickTime-this.__lastLastClickTime<500&&this.__lastPointer.x===e.x&&this.__lastPointer.y===e.y},_stopEvent:function(e){e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation()},initCursorSelectionHandlers:function(){this.initSelectedHandler(),this.initMousedownHandler(),this.initMousemoveHandler(),this.initMouseupHandler(),this.initClicks()},initClicks:function(){this.on("dblclick",function(e){this.selectWord(this.getSelectionStartFromPointer(e.e))}),this.on("tripleclick",function(e){this.selectLine(this.getSelectionStartFromPointer(e.e))})},initMousedownHandler:function(){this.on("mousedown",function(e){var t=this.canvas.getPointer(e.e);this.__mousedownX=t.x,this.__mousedownY=t.y,this.__isMousedown=!0,this.hiddenTextarea&&this.canvas&&this.canvas.wrapperEl.appendChild(this.hiddenTextarea),this.selected&&this.setCursorByClick(e.e),this.isEditing&&(this.__selectionStartOnMouseDown=this.selectionStart,this.initDelayedCursor(!0))})},initMousemoveHandler:function(){this.on("mousemove",function(e){if(!this.__isMousedown||!this.isEditing)return;var t=this.getSelectionStartFromPointer(e.e);t>=this.__selectionStartOnMouseDown?(this.setSelectionStart(this.__selectionStartOnMouseDown),this.setSelectionEnd(t)):(this.setSelectionStart(t),this.setSelectionEnd(this.__selectionStartOnMouseDown))})},_isObjectMoved:function(e){var t=this.canvas.getPointer(e);return this.__mousedownX!==t.x||this.__mousedownY!==t.y},initMouseupHandler:function(){this.on("mouseup",function(e){this.__isMousedown=!1;if(this._isObjectMoved(e.e))return;this.__lastSelected&&(this.enterEditing(),this.initDelayedCursor(!0)),this.selected=!0})},setCursorByClick:function(e){var t=this.getSelectionStartFromPointer(e);e.shiftKey?ts?0:1,a=r+u;return this.flipX&&(a=i-a),a>this.text.length&&(a=this.text.length),a}}),fabric.util.object.extend(fabric.IText.prototype,{initHiddenTextarea:function(){this.hiddenTextarea=fabric.document.createElement("textarea"),this.hiddenTextarea.setAttribute("autocapitalize","off"),this.hiddenTextarea.style.cssText="position: absolute; top: 0; left: -9999px",fabric.document.body.appendChild(this.hiddenTextarea),fabric.util.addListener(this.hiddenTextarea,"keydown",this.onKeyDown.bind(this)),fabric.util.addListener(this.hiddenTextarea,"keypress",this.onKeyPress.bind(this)),fabric.util.addListener(this.hiddenTextarea,"copy",this.copy.bind(this)),fabric.util.addListener(this.hiddenTextarea,"paste",this.paste.bind(this)),!this._clickHandlerInitialized&&this.canvas&&(fabric.util.addListener(this.canvas.upperCanvasEl,"click",this.onClick.bind(this)),this._clickHandlerInitialized=!0)},_keysMap:{8:"removeChars",13:"insertNewline",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown",46:"forwardDelete"},_ctrlKeysMap:{65:"selectAll",88:"cut"},onClick:function(){this.hiddenTextarea&&this.hiddenTextarea.focus()},onKeyDown:function(e){if(!this.isEditing)return;if(e.keyCode in this._keysMap&&e.charCode===0)this[this._keysMap[e.keyCode]](e);else{if(!(e.keyCode in this._ctrlKeysMap&&(e.ctrlKey||e.metaKey)))return;this[this._ctrlKeysMap[e.keyCode]](e)}e.stopPropagation(),this.canvas&&this.canvas.renderAll()},forwardDelete:function(e){this.selectionStart===this.selectionEnd&&this.moveCursorRight(e),this.removeChars(e)},copy:function(e){var t=this.getSelectedText(),n=this._getClipboardData(e);n&&n.setData("text",t),this.copiedText=t,this.copiedStyles=this.getSelectionStyles(this.selectionStart,this.selectionEnd)},paste:function(e){var t=null,n=this._getClipboardData(e);n?t=n.getData("text"):t=this.copiedText,t&&this.insertChars(t)},cut:function(e){if(this.selectionStart===this.selectionEnd)return;this.copy(),this.removeChars(e)},_getClipboardData:function(e){return e&&(e.clipboardData||fabric.window.clipboardData)},onKeyPress:function(e){if(!this.isEditing||e.metaKey||e.ctrlKey||e.keyCode in this._keysMap&&e.charCode===0)return;this.insertChars(String.fromCharCode(e.which)),e.stopPropagation()},getDownCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.text.split(this._reNewline),i,s,o=this.text.slice(0,n),u=this.text.slice(n),a=o.slice(o.lastIndexOf("\n")+1),f=u.match(/(.*)\n?/)[1],l=(u.match(/.*\n(.*)\n?/)||{})[1]||"",c=this.get2DCursorLocation(n);if(c.lineIndex===r.length-1||e.metaKey)return this.text.length-n;var h=this._getWidthOfLine(this.ctx,c.lineIndex,r);s=this._getLineLeftOffset(h);var p=s,d=c.lineIndex;for(var v=0,m=a.length;vn){f=!0;var d=u-p,v=u,m=Math.abs(d-n),g=Math.abs(v-n);a=gthis.text.length&&(this.selectionStart=this.text.length),this.selectionEnd=this.selectionStart},moveCursorDownWithShift:function(e){if(this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd){this.selectionStart+=e,this._selectionDirection="left";return}this._selectionDirection="right",this.selectionEnd+=e,this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length)},getUpCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.get2DCursorLocation(n);if(r.lineIndex===0||e.metaKey)return n;var i=this.text.slice(0,n),s=i.slice(i.lastIndexOf("\n")+1),o=(i.match(/\n?(.*)\n.*$/)||{})[1]||"",u=this.text.split(this._reNewline),a,f=this._getWidthOfLine(this.ctx,r.lineIndex,u),l=this._getLineLeftOffset(f),c=l,h=r.lineIndex;for(var p=0,d=s.length;pn){f=!0;var d=u-p,v=u,m=Math.abs(d-n),g=Math.abs(v-n);a=g=this.text.length&&this.selectionEnd>=this.text.length)return;this.abortCursorAnimation(),this._currentCursorOpacity=1,e.shiftKey?this.moveCursorRightWithShift(e):this.moveCursorRightWithoutShift(e),this.initDelayedCursor()},moveCursorRightWithShift:function(e){this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd?this._moveRight(e,"selectionStart"):(this._selectionDirection="right",this._moveRight(e,"selectionEnd"),this.text.charAt(this.selectionEnd-1)==="\n"&&this.selectionEnd++,this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length))},moveCursorRightWithoutShift:function(e){this._selectionDirection="right",this.selectionStart===this.selectionEnd?(this._moveRight(e,"selectionStart"),this.selectionEnd=this.selectionStart):(this.selectionEnd+=this.getNumNewLinesInSelectedText(),this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length),this.selectionStart=this.selectionEnd)},removeChars:function(e){this.selectionStart===this.selectionEnd?this._removeCharsNearCursor(e):this._removeCharsFromTo(this.selectionStart,this.selectionEnd),this.selectionEnd=this.selectionStart,this._removeExtraneousStyles(),this.canvas&&this.canvas.renderAll().renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},_removeCharsNearCursor:function(e){if(this.selectionStart!==0)if(e.metaKey){var t=this.findLineBoundaryLeft(this.selectionStart);this._removeCharsFromTo(t,this.selectionStart),this.selectionStart=t}else if(e.altKey){var n=this.findWordBoundaryLeft(this.selectionStart);this._removeCharsFromTo(n,this.selectionStart),this.selectionStart=n}else{var r=this.text.slice(this.selectionStart-1,this.selectionStart)==="\n";this.removeStyleObject(r),this.selectionStart--,this.text=this.text.slice(0,this.selectionStart)+this.text.slice(this.selectionStart+1)}}}),fabric.util.object.extend(fabric.IText.prototype,{_setSVGTextLineText:function(e,t,n,r,i,s){this.styles[t]?this._setSVGTextLineChars(e,t,n,r,i,s):this.callSuper("_setSVGTextLineText",e,t,n,r,i)},_setSVGTextLineChars:function(e,t,n,r,i,s){var o=t===0||this.useNative?"y":"dy",u=e.split(""),a=0,f=this._getSVGLineLeftOffset(t),l=this._getSVGLineTopOffset(t),c=this._getHeightOfLine(this.ctx,t);for(var h=0,p=u.length;h
    '].join("")},_createTextCharSpan:function(e,t,n,r,i,s){var o=this.getSvgStyles.call(fabric.util.object.extend({visible:!0,fill:this.fill,stroke:this.stroke,type:"text"},t));return['',fabric.util.string.escapeXml(e),""].join("")}}),function(){function request(e,t,n){var r=URL.parse(e);r.port||(r.port=r.protocol.indexOf("https:")===0?443:80);var i=r.port===443?HTTPS:HTTP,s=i.request({hostname:r.hostname,port:r.port,path:r.path,method:"GET"},function(e){var r="";t&&e.setEncoding(t),e.on("end",function(){n(r)}),e.on("data",function(t){e.statusCode===200&&(r+=t)})});s.on("error",function(e){e.errno===process.ECONNREFUSED?fabric.log("ECONNREFUSED: connection refused to "+r.hostname+":"+r.port):fabric.log(e.message)}),s.end()}function requestFs(e,t){var n=require("fs");n.readFile(e,function(e,n){if(e)throw fabric.log(e),e;t(n)})}if(typeof document!="undefined"&&typeof window!="undefined")return;var DOMParser=require("xmldom").DOMParser,URL=require("url"),HTTP=require("http"),HTTPS=require("https"),Canvas=require("canvas"),Image=require("canvas").Image;fabric.util.loadImage=function(e,t,n){function r(r){i.src=new Buffer(r,"binary"),i._src=e,t&&t.call(n,i)}var i=new Image;e&&(e instanceof Buffer||e.indexOf("data")===0)?(i.src=i._src=e,t&&t.call(n,i)):e&&e.indexOf("http")!==0?requestFs(e,r):e?request(e,"binary",r):t&&t.call(n,e)},fabric.loadSVGFromURL=function(e,t,n){e=e.replace(/^\n\s*/,"").replace(/\?.*$/,"").trim(),e.indexOf("http")!==0?requestFs(e,function(e){fabric.loadSVGFromString(e.toString(),t,n)}):request(e,"",function(e){fabric.loadSVGFromString(e,t,n)})},fabric.loadSVGFromString=function(e,t,n){var r=(new DOMParser).parseFromString(e);fabric.parseSVGDocument(r.documentElement,function(e,n){t&&t(e,n)},n)},fabric.util.getScript=function(url,callback){request(url,"",function(body){eval(body),callback&&callback()})},fabric.Image.fromObject=function(e,t){fabric.util.loadImage(e.src,function(n){var r=new fabric.Image(n);r._initConfig(e),r._initFilters(e,function(e){r.filters=e||[],t&&t(r)})})},fabric.createCanvasForNode=function(e,t,n,r){r=r||n;var i=fabric.document.createElement("canvas"),s=new Canvas(e||600,t||600,r);i.style={},i.width=s.width,i.height=s.height;var o=fabric.Canvas||fabric.StaticCanvas,u=new o(i,n);return u.contextContainer=s.getContext("2d"),u.nodeCanvas=s,u.Font=Canvas.Font,u},fabric.StaticCanvas.prototype.createPNGStream=function(){return this.nodeCanvas.createPNGStream()},fabric.StaticCanvas.prototype.createJPEGStream=function(e){return this.nodeCanvas.createJPEGStream(e)};var origSetWidth=fabric.StaticCanvas.prototype.setWidth;fabric.StaticCanvas.prototype.setWidth=function(e,t){return origSetWidth.call(this,e,t),this.nodeCanvas.width=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setWidth=fabric.StaticCanvas.prototype.setWidth);var origSetHeight=fabric.StaticCanvas.prototype.setHeight;fabric.StaticCanvas.prototype.setHeight=function(e,t){return origSetHeight.call(this,e,t),this.nodeCanvas.height=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setHeight=fabric.StaticCanvas.prototype.setHeight)}(); \ No newline at end of file diff --git a/js/fabric-v1.4.8.js b/js/fabric-v1.4.8.js new file mode 100644 index 00000000..7f334b56 --- /dev/null +++ b/js/fabric-v1.4.8.js @@ -0,0 +1,22199 @@ +/* build: `node build.js modules=ALL exclude=gestures,cufon,json minifier=uglifyjs` */ +/*! Fabric.js Copyright 2008-2014, Printio (Juriy Zaytsev, Maxim Chernyak) */ + +var fabric = fabric || { version: "1.4.8" }; +if (typeof exports !== 'undefined') { + exports.fabric = fabric; +} + +if (typeof document !== 'undefined' && typeof window !== 'undefined') { + fabric.document = document; + fabric.window = window; +} +else { + // assume we're running under node.js when document/window are not present + fabric.document = require("jsdom") + .jsdom(""); + + fabric.window = fabric.document.createWindow(); +} + +/** + * True when in environment that supports touch events + * @type boolean + */ +fabric.isTouchSupported = "ontouchstart" in fabric.document.documentElement; + +/** + * True when in environment that's probably Node.js + * @type boolean + */ +fabric.isLikelyNode = typeof Buffer !== 'undefined' && + typeof window === 'undefined'; + + +/** + * Attributes parsed from all SVG elements + * @type array + */ +fabric.SHARED_ATTRIBUTES = [ + "display", + "transform", + "fill", "fill-opacity", "fill-rule", + "opacity", + "stroke", "stroke-dasharray", "stroke-linecap", + "stroke-linejoin", "stroke-miterlimit", + "stroke-opacity", "stroke-width" +]; + + +(function(){ + + /** + * @private + * @param {String} eventName + * @param {Function} handler + */ + function _removeEventListener(eventName, handler) { + if (!this.__eventListeners[eventName]) return; + + if (handler) { + fabric.util.removeFromArray(this.__eventListeners[eventName], handler); + } + else { + this.__eventListeners[eventName].length = 0; + } + } + + /** + * Observes specified event + * @deprecated `observe` deprecated since 0.8.34 (use `on` instead) + * @memberOf fabric.Observable + * @alias on + * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler}) + * @param {Function} handler Function that receives a notification when an event of the specified type occurs + * @return {Self} thisArg + * @chainable + */ + function observe(eventName, handler) { + if (!this.__eventListeners) { + this.__eventListeners = { }; + } + // one object with key/value pairs was passed + if (arguments.length === 1) { + for (var prop in eventName) { + this.on(prop, eventName[prop]); + } + } + else { + if (!this.__eventListeners[eventName]) { + this.__eventListeners[eventName] = [ ]; + } + this.__eventListeners[eventName].push(handler); + } + return this; + } + + /** + * Stops event observing for a particular event handler. Calling this method + * without arguments removes all handlers for all events + * @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead) + * @memberOf fabric.Observable + * @alias off + * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler}) + * @param {Function} handler Function to be deleted from EventListeners + * @return {Self} thisArg + * @chainable + */ + function stopObserving(eventName, handler) { + if (!this.__eventListeners) return; + + // remove all key/value pairs (event name -> event handler) + if (arguments.length === 0) { + this.__eventListeners = { }; + } + // one object with key/value pairs was passed + else if (arguments.length === 1 && typeof arguments[0] === 'object') { + for (var prop in eventName) { + _removeEventListener.call(this, prop, eventName[prop]); + } + } + else { + _removeEventListener.call(this, eventName, handler); + } + return this; + } + + /** + * Fires event with an optional options object + * @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead) + * @memberOf fabric.Observable + * @alias trigger + * @param {String} eventName Event name to fire + * @param {Object} [options] Options object + * @return {Self} thisArg + * @chainable + */ + function fire(eventName, options) { + if (!this.__eventListeners) return; + + var listenersForEvent = this.__eventListeners[eventName]; + if (!listenersForEvent) return; + for (var i = 0, len = listenersForEvent.length; i < len; i++) { + // avoiding try/catch for perf. reasons + listenersForEvent[i].call(this, options || { }); + } + return this; + } + + /** + * @namespace fabric.Observable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#events} + * @see {@link http://fabricjs.com/events/|Events demo} + */ + fabric.Observable = { + observe: observe, + stopObserving: stopObserving, + fire: fire, + + on: observe, + off: stopObserving, + trigger: fire + }; +})(); + + +/** + * @namespace fabric.Collection + */ +fabric.Collection = { + + /** + * Adds objects to collection, then renders canvas (if `renderOnAddRemove` is not `false`) + * Objects should be instances of (or inherit from) fabric.Object + * @param {...fabric.Object} object Zero or more fabric instances + * @return {Self} thisArg + */ + add: function () { + this._objects.push.apply(this._objects, arguments); + for (var i = 0, length = arguments.length; i < length; i++) { + this._onObjectAdded(arguments[i]); + } + this.renderOnAddRemove && this.renderAll(); + return this; + }, + + /** + * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`) + * An object should be an instance of (or inherit from) fabric.Object + * @param {Object} object Object to insert + * @param {Number} index Index to insert object at + * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs + * @return {Self} thisArg + * @chainable + */ + insertAt: function (object, index, nonSplicing) { + var objects = this.getObjects(); + if (nonSplicing) { + objects[index] = object; + } + else { + objects.splice(index, 0, object); + } + this._onObjectAdded(object); + this.renderOnAddRemove && this.renderAll(); + return this; + }, + + /** + * Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`) + * @param {...fabric.Object} object Zero or more fabric instances + * @return {Self} thisArg + * @chainable + */ + remove: function() { + var objects = this.getObjects(), + index; + + for (var i = 0, length = arguments.length; i < length; i++) { + index = objects.indexOf(arguments[i]); + + // only call onObjectRemoved if an object was actually removed + if (index !== -1) { + objects.splice(index, 1); + this._onObjectRemoved(arguments[i]); + } + } + + this.renderOnAddRemove && this.renderAll(); + return this; + }, + + /** + * Executes given function for each object in this group + * @param {Function} callback + * Callback invoked with current object as first argument, + * index - as second and an array of all objects - as third. + * Iteration happens in reverse order (for performance reasons). + * Callback is invoked in a context of Global Object (e.g. `window`) + * when no `context` argument is given + * + * @param {Object} context Context (aka thisObject) + * @return {Self} thisArg + */ + forEachObject: function(callback, context) { + var objects = this.getObjects(), + i = objects.length; + while (i--) { + callback.call(context, objects[i], i, objects); + } + return this; + }, + + /** + * Returns an array of children objects of this instance + * Type parameter introduced in 1.3.10 + * @param {String} [type] When specified, only objects of this type are returned + * @return {Array} + */ + getObjects: function(type) { + if (typeof type === 'undefined') { + return this._objects; + } + return this._objects.filter(function(o) { + return o.type === type; + }); + }, + + /** + * Returns object at specified index + * @param {Number} index + * @return {Self} thisArg + */ + item: function (index) { + return this.getObjects()[index]; + }, + + /** + * Returns true if collection contains no objects + * @return {Boolean} true if collection is empty + */ + isEmpty: function () { + return this.getObjects().length === 0; + }, + + /** + * Returns a size of a collection (i.e: length of an array containing its objects) + * @return {Number} Collection size + */ + size: function() { + return this.getObjects().length; + }, + + /** + * Returns true if collection contains an object + * @param {Object} object Object to check against + * @return {Boolean} `true` if collection contains an object + */ + contains: function(object) { + return this.getObjects().indexOf(object) > -1; + }, + + /** + * Returns number representation of a collection complexity + * @return {Number} complexity + */ + complexity: function () { + return this.getObjects().reduce(function (memo, current) { + memo += current.complexity ? current.complexity() : 0; + return memo; + }, 0); + } +}; + + +(function(global) { + + var sqrt = Math.sqrt, + atan2 = Math.atan2, + PiBy180 = Math.PI / 180; + + /** + * @namespace fabric.util + */ + fabric.util = { + + /** + * Removes value from an array. + * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf` + * @static + * @memberOf fabric.util + * @param {Array} array + * @param {Any} value + * @return {Array} original array + */ + removeFromArray: function(array, value) { + var idx = array.indexOf(value); + if (idx !== -1) { + array.splice(idx, 1); + } + return array; + }, + + /** + * Returns random number between 2 specified ones. + * @static + * @memberOf fabric.util + * @param {Number} min lower limit + * @param {Number} max upper limit + * @return {Number} random value (between min and max) + */ + getRandomInt: function(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + }, + + /** + * Transforms degrees to radians. + * @static + * @memberOf fabric.util + * @param {Number} degrees value in degrees + * @return {Number} value in radians + */ + degreesToRadians: function(degrees) { + return degrees * PiBy180; + }, + + /** + * Transforms radians to degrees. + * @static + * @memberOf fabric.util + * @param {Number} radians value in radians + * @return {Number} value in degrees + */ + radiansToDegrees: function(radians) { + return radians / PiBy180; + }, + + /** + * Rotates `point` around `origin` with `radians` + * @static + * @memberOf fabric.util + * @param {fabric.Point} The point to rotate + * @param {fabric.Point} The origin of the rotation + * @param {Number} The radians of the angle for the rotation + * @return {fabric.Point} The new rotated point + */ + rotatePoint: function(point, origin, radians) { + var sin = Math.sin(radians), + cos = Math.cos(radians); + + point.subtractEquals(origin); + + var rx = point.x * cos - point.y * sin, + ry = point.x * sin + point.y * cos; + + return new fabric.Point(rx, ry).addEquals(origin); + }, + + /** + * Apply transform t to point p + * @static + * @memberOf fabric.util + * @param {fabric.Point} p The point to transform + * @param {Array} t The transform + * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied + * @return {fabric.Point} The transformed point + */ + transformPoint: function(p, t, ignoreOffset) { + if (ignoreOffset) { + return new fabric.Point( + t[0] * p.x + t[1] * p.y, + t[2] * p.x + t[3] * p.y + ); + } + return new fabric.Point( + t[0] * p.x + t[1] * p.y + t[4], + t[2] * p.x + t[3] * p.y + t[5] + ); + }, + + /** + * Invert transformation t + * @static + * @memberOf fabric.util + * @param {Array} t The transform + * @return {Array} The inverted transform + */ + invertTransform: function(t) { + var r = t.slice(), + a = 1 / (t[0] * t[3] - t[1] * t[2]); + r = [a * t[3], -a * t[1], -a * t[2], a * t[0], 0, 0]; + var o = fabric.util.transformPoint({x: t[4], y: t[5]}, r); + r[4] = -o.x; + r[5] = -o.y; + return r; + }, + + /** + * A wrapper around Number#toFixed, which contrary to native method returns number, not string. + * @static + * @memberOf fabric.util + * @param {Number | String} number number to operate on + * @param {Number} fractionDigits number of fraction digits to "leave" + * @return {Number} + */ + toFixed: function(number, fractionDigits) { + return parseFloat(Number(number).toFixed(fractionDigits)); + }, + + /** + * Function which always returns `false`. + * @static + * @memberOf fabric.util + * @return {Boolean} + */ + falseFunction: function() { + return false; + }, + + /** + * Returns klass "Class" object of given namespace + * @memberOf fabric.util + * @param {String} type Type of object (eg. 'circle') + * @param {String} namespace Namespace to get klass "Class" object from + * @return {Object} klass "Class" + */ + getKlass: function(type, namespace) { + // capitalize first letter only + type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1)); + return fabric.util.resolveNamespace(namespace)[type]; + }, + + /** + * Returns object of given namespace + * @memberOf fabric.util + * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric' + * @return {Object} Object for given namespace (default fabric) + */ + resolveNamespace: function(namespace) { + if (!namespace) { + return fabric; + } + + var parts = namespace.split('.'), + len = parts.length, + obj = global || fabric.window; + + for (var i = 0; i < len; ++i) { + obj = obj[parts[i]]; + } + + return obj; + }, + + /** + * Loads image element from given url and passes it to a callback + * @memberOf fabric.util + * @param {String} url URL representing an image + * @param {Function} callback Callback; invoked with loaded image + * @param {Any} [context] Context to invoke callback in + * @param {Object} [crossOrigin] crossOrigin value to set image element to + */ + loadImage: function(url, callback, context, crossOrigin) { + if (!url) { + callback && callback.call(context, url); + return; + } + + var img = fabric.util.createImage(); + + /** @ignore */ + img.onload = function () { + callback && callback.call(context, img); + img = img.onload = img.onerror = null; + }; + + /** @ignore */ + img.onerror = function() { + fabric.log('Error loading ' + img.src); + callback && callback.call(context, null, true); + img = img.onload = img.onerror = null; + }; + + // data-urls appear to be buggy with crossOrigin + // https://github.com/kangax/fabric.js/commit/d0abb90f1cd5c5ef9d2a94d3fb21a22330da3e0a#commitcomment-4513767 + // see https://code.google.com/p/chromium/issues/detail?id=315152 + // https://bugzilla.mozilla.org/show_bug.cgi?id=935069 + if (url.indexOf('data') !== 0 && typeof crossOrigin !== 'undefined') { + img.crossOrigin = crossOrigin; + } + + img.src = url; + }, + + /** + * Creates corresponding fabric instances from their object representations + * @static + * @memberOf fabric.util + * @param {Array} objects Objects to enliven + * @param {Function} callback Callback to invoke when all objects are created + * @param {Function} [reviver] Method for further parsing of object elements, + * called after each fabric object created. + */ + enlivenObjects: function(objects, callback, namespace, reviver) { + objects = objects || [ ]; + + function onLoaded() { + if (++numLoadedObjects === numTotalObjects) { + callback && callback(enlivenedObjects); + } + } + + var enlivenedObjects = [ ], + numLoadedObjects = 0, + numTotalObjects = objects.length; + + if (!numTotalObjects) { + callback && callback(enlivenedObjects); + return; + } + + objects.forEach(function (o, index) { + // if sparse array + if (!o || !o.type) { + onLoaded(); + return; + } + var klass = fabric.util.getKlass(o.type, namespace); + if (klass.async) { + klass.fromObject(o, function (obj, error) { + if (!error) { + enlivenedObjects[index] = obj; + reviver && reviver(o, enlivenedObjects[index]); + } + onLoaded(); + }); + } + else { + enlivenedObjects[index] = klass.fromObject(o); + reviver && reviver(o, enlivenedObjects[index]); + onLoaded(); + } + }); + }, + + /** + * Groups SVG elements (usually those retrieved from SVG document) + * @static + * @memberOf fabric.util + * @param {Array} elements SVG elements to group + * @param {Object} [options] Options object + * @return {fabric.Object|fabric.PathGroup} + */ + groupSVGElements: function(elements, options, path) { + var object; + + if (elements.length > 1) { + object = new fabric.PathGroup(elements, options); + } + else { + object = elements[0]; + } + + if (typeof path !== 'undefined') { + object.setSourcePath(path); + } + return object; + }, + + /** + * Populates an object with properties of another object + * @static + * @memberOf fabric.util + * @param {Object} source Source object + * @param {Object} destination Destination object + * @return {Array} properties Propertie names to include + */ + populateWithProperties: function(source, destination, properties) { + if (properties && Object.prototype.toString.call(properties) === '[object Array]') { + for (var i = 0, len = properties.length; i < len; i++) { + if (properties[i] in source) { + destination[properties[i]] = source[properties[i]]; + } + } + } + }, + + /** + * Draws a dashed line between two points + * + * This method is used to draw dashed line around selection area. + * See dotted stroke in canvas + * + * @param {CanvasRenderingContext2D} ctx context + * @param {Number} x start x coordinate + * @param {Number} y start y coordinate + * @param {Number} x2 end x coordinate + * @param {Number} y2 end y coordinate + * @param {Array} da dash array pattern + */ + drawDashedLine: function(ctx, x, y, x2, y2, da) { + var dx = x2 - x, + dy = y2 - y, + len = sqrt(dx * dx + dy * dy), + rot = atan2(dy, dx), + dc = da.length, + di = 0, + draw = true; + + ctx.save(); + ctx.translate(x, y); + ctx.moveTo(0, 0); + ctx.rotate(rot); + + x = 0; + while (len > x) { + x += da[di++ % dc]; + if (x > len) { + x = len; + } + ctx[draw ? 'lineTo' : 'moveTo'](x, 0); + draw = !draw; + } + + ctx.restore(); + }, + + /** + * Creates canvas element and initializes it via excanvas if necessary + * @static + * @memberOf fabric.util + * @param {CanvasElement} [canvasEl] optional canvas element to initialize; + * when not given, element is created implicitly + * @return {CanvasElement} initialized canvas element + */ + createCanvasElement: function(canvasEl) { + canvasEl || (canvasEl = fabric.document.createElement('canvas')); + if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') { + G_vmlCanvasManager.initElement(canvasEl); + } + return canvasEl; + }, + + /** + * Creates image element (works on client and node) + * @static + * @memberOf fabric.util + * @return {HTMLImageElement} HTML image element + */ + createImage: function() { + return fabric.isLikelyNode + ? new (require('canvas').Image)() + : fabric.document.createElement('img'); + }, + + /** + * Creates accessors (getXXX, setXXX) for a "class", based on "stateProperties" array + * @static + * @memberOf fabric.util + * @param {Object} klass "Class" to create accessors for + */ + createAccessors: function(klass) { + var proto = klass.prototype; + + for (var i = proto.stateProperties.length; i--; ) { + + var propName = proto.stateProperties[i], + capitalizedPropName = propName.charAt(0).toUpperCase() + propName.slice(1), + setterName = 'set' + capitalizedPropName, + getterName = 'get' + capitalizedPropName; + + // using `new Function` for better introspection + if (!proto[getterName]) { + proto[getterName] = (function(property) { + return new Function('return this.get("' + property + '")'); + })(propName); + } + if (!proto[setterName]) { + proto[setterName] = (function(property) { + return new Function('value', 'return this.set("' + property + '", value)'); + })(propName); + } + } + }, + + /** + * @static + * @memberOf fabric.util + * @param {fabric.Object} receiver Object implementing `clipTo` method + * @param {CanvasRenderingContext2D} ctx Context to clip + */ + clipContext: function(receiver, ctx) { + ctx.save(); + ctx.beginPath(); + receiver.clipTo(ctx); + ctx.clip(); + }, + + /** + * Multiply matrix A by matrix B to nest transformations + * @static + * @memberOf fabric.util + * @param {Array} matrixA First transformMatrix + * @param {Array} matrixB Second transformMatrix + * @return {Array} The product of the two transform matrices + */ + multiplyTransformMatrices: function(matrixA, matrixB) { + // Matrix multiply matrixA * matrixB + var a = [ + [matrixA[0], matrixA[2], matrixA[4]], + [matrixA[1], matrixA[3], matrixA[5]], + [0, 0, 1 ] + ], + + b = [ + [matrixB[0], matrixB[2], matrixB[4]], + [matrixB[1], matrixB[3], matrixB[5]], + [0, 0, 1 ] + ], + + result = []; + + for (var r = 0; r < 3; r++) { + result[r] = []; + for (var c = 0; c < 3; c++) { + var sum = 0; + for (var k = 0; k < 3; k++) { + sum += a[r][k] * b[k][c]; + } + + result[r][c] = sum; + } + } + + return [ + result[0][0], + result[1][0], + result[0][1], + result[1][1], + result[0][2], + result[1][2] + ]; + }, + + /** + * Returns string representation of function body + * @param {Function} fn Function to get body of + * @return {String} Function body + */ + getFunctionBody: function(fn) { + return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1]; + }, + + /** + * Normalizes polygon/polyline points according to their dimensions + * @param {Array} points + * @param {Object} options + */ + normalizePoints: function(points, options) { + var minX = fabric.util.array.min(points, 'x'), + minY = fabric.util.array.min(points, 'y'); + + minX = minX < 0 ? minX : 0; + minY = minX < 0 ? minY : 0; + + for (var i = 0, len = points.length; i < len; i++) { + // normalize coordinates, according to containing box + // (dimensions of which are passed via `options`) + points[i].x -= (options.width / 2 + minX) || 0; + points[i].y -= (options.height / 2 + minY) || 0; + } + }, + + /** + * Returns true if context has transparent pixel + * at specified location (taking tolerance into account) + * @param {CanvasRenderingContext2D} ctx context + * @param {Number} x x coordinate + * @param {Number} y y coordinate + * @param {Number} tolerance Tolerance + */ + isTransparent: function(ctx, x, y, tolerance) { + + // If tolerance is > 0 adjust start coords to take into account. + // If moves off Canvas fix to 0 + if (tolerance > 0) { + if (x > tolerance) { + x -= tolerance; + } + else { + x = 0; + } + if (y > tolerance) { + y -= tolerance; + } + else { + y = 0; + } + } + + var _isTransparent = true, + imageData = ctx.getImageData(x, y, (tolerance * 2) || 1, (tolerance * 2) || 1); + + // Split image data - for tolerance > 1, pixelDataSize = 4; + for (var i = 3, l = imageData.data.length; i < l; i += 4) { + var temp = imageData.data[i]; + _isTransparent = temp <= 0; + if (_isTransparent === false) break; // Stop if colour found + } + + imageData = null; + + return _isTransparent; + } + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + var arcToSegmentsCache = { }, + segmentToBezierCache = { }, + _join = Array.prototype.join, + argsString; + + // Generous contribution by Raph Levien, from libsvg-0.1.0.tar.gz + function arcToSegments(x, y, rx, ry, large, sweep, rotateX, ox, oy) { + + argsString = _join.call(arguments); + + if (arcToSegmentsCache[argsString]) { + return arcToSegmentsCache[argsString]; + } + + var coords = getXYCoords(rotateX, rx, ry, ox, oy, x, y), + + d = (coords.x1 - coords.x0) * (coords.x1 - coords.x0) + + (coords.y1 - coords.y0) * (coords.y1 - coords.y0), + + sfactorSq = 1 / d - 0.25; + + if (sfactorSq < 0) { + sfactorSq = 0; + } + + var sfactor = Math.sqrt(sfactorSq); + if (sweep === large) { + sfactor = -sfactor; + } + + var xc = 0.5 * (coords.x0 + coords.x1) - sfactor * (coords.y1 - coords.y0), + yc = 0.5 * (coords.y0 + coords.y1) + sfactor * (coords.x1 - coords.x0), + th0 = Math.atan2(coords.y0 - yc, coords.x0 - xc), + th1 = Math.atan2(coords.y1 - yc, coords.x1 - xc), + thArc = th1 - th0; + + if (thArc < 0 && sweep === 1) { + thArc += 2 * Math.PI; + } + else if (thArc > 0 && sweep === 0) { + thArc -= 2 * Math.PI; + } + + var segments = Math.ceil(Math.abs(thArc / (Math.PI * 0.5 + 0.001))), + result = []; + + for (var i = 0; i < segments; i++) { + var th2 = th0 + i * thArc / segments, + th3 = th0 + (i + 1) * thArc / segments; + + result[i] = [xc, yc, th2, th3, rx, ry, coords.sinTh, coords.cosTh]; + } + + arcToSegmentsCache[argsString] = result; + return result; + } + + function getXYCoords(rotateX, rx, ry, ox, oy, x, y) { + + var th = rotateX * (Math.PI / 180), + sinTh = Math.sin(th), + cosTh = Math.cos(th); + + rx = Math.abs(rx); + ry = Math.abs(ry); + + var px = cosTh * (ox - x) + sinTh * (oy - y), + py = cosTh * (oy - y) - sinTh * (ox - x), + pl = (px * px) / (rx * rx) + (py * py) / (ry * ry); + + pl *= 0.25; + + if (pl > 1) { + pl = Math.sqrt(pl); + rx *= pl; + ry *= pl; + } + + var a00 = cosTh / rx, + a01 = sinTh / rx, + a10 = (-sinTh) / ry, + a11 = (cosTh) / ry; + + return { + x0: a00 * ox + a01 * oy, + y0: a10 * ox + a11 * oy, + x1: a00 * x + a01 * y, + y1: a10 * x + a11 * y, + sinTh: sinTh, + cosTh: cosTh + }; + } + + function segmentToBezier(cx, cy, th0, th1, rx, ry, sinTh, cosTh) { + argsString = _join.call(arguments); + + if (segmentToBezierCache[argsString]) { + return segmentToBezierCache[argsString]; + } + + var sinTh0 = Math.sin(th0), + cosTh0 = Math.cos(th0), + sinTh1 = Math.sin(th1), + cosTh1 = Math.cos(th1), + + a00 = cosTh * rx, + a01 = -sinTh * ry, + a10 = sinTh * rx, + a11 = cosTh * ry, + thHalf = 0.25 * (th1 - th0), + + t = (8 / 3) * Math.sin(thHalf) * + Math.sin(thHalf) / Math.sin(thHalf * 2), + + x1 = cx + cosTh0 - t * sinTh0, + y1 = cy + sinTh0 + t * cosTh0, + x3 = cx + cosTh1, + y3 = cy + sinTh1, + x2 = x3 + t * sinTh1, + y2 = y3 - t * cosTh1; + + segmentToBezierCache[argsString] = [ + a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, + a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, + a00 * x3 + a01 * y3, a10 * x3 + a11 * y3 + ]; + + return segmentToBezierCache[argsString]; + } + + /** + * Draws arc + * @param {CanvasRenderingContext2D} ctx + * @param {Number} x + * @param {Number} y + * @param {Array} coords + */ + fabric.util.drawArc = function(ctx, x, y, coords) { + var rx = coords[0], + ry = coords[1], + rot = coords[2], + large = coords[3], + sweep = coords[4], + ex = coords[5], + ey = coords[6], + segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, x, y); + for (var i = 0; i < segs.length; i++) { + var bez = segmentToBezier.apply(this, segs[i]); + ctx.bezierCurveTo.apply(ctx, bez); + } + }; +})(); + + +(function() { + + var slice = Array.prototype.slice; + + /* _ES5_COMPAT_START_ */ + + if (!Array.prototype.indexOf) { + /** + * Finds index of an element in an array + * @param {Any} searchElement + * @param {Number} [fromIndex] + * @return {Number} + */ + Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) { + if (this === void 0 || this === null) { + throw new TypeError(); + } + var t = Object(this), len = t.length >>> 0; + if (len === 0) { + return -1; + } + var n = 0; + if (arguments.length > 0) { + n = Number(arguments[1]); + if (n !== n) { // shortcut for verifying if it's NaN + n = 0; + } + else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + } + if (n >= len) { + return -1; + } + var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); + for (; k < len; k++) { + if (k in t && t[k] === searchElement) { + return k; + } + } + return -1; + }; + } + + if (!Array.prototype.forEach) { + /** + * Iterates an array, invoking callback for each element + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.forEach = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + fn.call(context, this[i], i, this); + } + } + }; + } + + if (!Array.prototype.map) { + /** + * Returns a result of iterating over an array, invoking callback for each element + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.map = function(fn, context) { + var result = [ ]; + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + result[i] = fn.call(context, this[i], i, this); + } + } + return result; + }; + } + + if (!Array.prototype.every) { + /** + * Returns true if a callback returns truthy value for all elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Boolean} + */ + Array.prototype.every = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this && !fn.call(context, this[i], i, this)) { + return false; + } + } + return true; + }; + } + + if (!Array.prototype.some) { + /** + * Returns true if a callback returns truthy value for at least one element in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Boolean} + */ + Array.prototype.some = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this && fn.call(context, this[i], i, this)) { + return true; + } + } + return false; + }; + } + + if (!Array.prototype.filter) { + /** + * Returns the result of iterating over elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.filter = function(fn, context) { + var result = [ ], val; + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + val = this[i]; // in case fn mutates this + if (fn.call(context, val, i, this)) { + result.push(val); + } + } + } + return result; + }; + } + + if (!Array.prototype.reduce) { + /** + * Returns "folded" (reduced) result of iterating over elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Any} + */ + Array.prototype.reduce = function(fn /*, initial*/) { + var len = this.length >>> 0, + i = 0, + rv; + + if (arguments.length > 1) { + rv = arguments[1]; + } + else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) { + throw new TypeError(); + } + } + while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fn.call(null, rv, this[i], i, this); + } + } + return rv; + }; + } + + /* _ES5_COMPAT_END_ */ + + /** + * Invokes method on all items in a given array + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} method Name of a method to invoke + * @return {Array} + */ + function invoke(array, method) { + var args = slice.call(arguments, 2), result = [ ]; + for (var i = 0, len = array.length; i < len; i++) { + result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]); + } + return result; + } + + /** + * Finds maximum value in array (not necessarily "first" one) + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} byProperty + * @return {Any} + */ + function max(array, byProperty) { + return find(array, byProperty, function(value1, value2) { + return value1 >= value2; + }); + } + + /** + * Finds minimum value in array (not necessarily "first" one) + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} byProperty + * @return {Any} + */ + function min(array, byProperty) { + return find(array, byProperty, function(value1, value2) { + return value1 < value2; + }); + } + + /** + * @private + */ + function find(array, byProperty, condition) { + if (!array || array.length === 0) return; + + var i = array.length - 1, + result = byProperty ? array[i][byProperty] : array[i]; + if (byProperty) { + while (i--) { + if (condition(array[i][byProperty], result)) { + result = array[i][byProperty]; + } + } + } + else { + while (i--) { + if (condition(array[i], result)) { + result = array[i]; + } + } + } + return result; + } + + /** + * @namespace fabric.util.array + */ + fabric.util.array = { + invoke: invoke, + min: min, + max: max + }; + +})(); + + +(function(){ + + /** + * Copies all enumerable properties of one object to another + * @memberOf fabric.util.object + * @param {Object} destination Where to copy to + * @param {Object} source Where to copy from + * @return {Object} + */ + function extend(destination, source) { + // JScript DontEnum bug is not taken care of + for (var property in source) { + destination[property] = source[property]; + } + return destination; + } + + /** + * Creates an empty object and copies all enumerable properties of another object to it + * @memberOf fabric.util.object + * @param {Object} object Object to clone + * @return {Object} + */ + function clone(object) { + return extend({ }, object); + } + + /** @namespace fabric.util.object */ + fabric.util.object = { + extend: extend, + clone: clone + }; + +})(); + + +(function() { + + /* _ES5_COMPAT_START_ */ + if (!String.prototype.trim) { + /** + * Trims a string (removing whitespace from the beginning and the end) + * @function external:String#trim + * @see String#trim on MDN + */ + String.prototype.trim = function () { + // this trim is not fully ES3 or ES5 compliant, but it should cover most cases for now + return this.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, ''); + }; + } + /* _ES5_COMPAT_END_ */ + + /** + * Camelizes a string + * @memberOf fabric.util.string + * @param {String} string String to camelize + * @return {String} Camelized version of a string + */ + function camelize(string) { + return string.replace(/-+(.)?/g, function(match, character) { + return character ? character.toUpperCase() : ''; + }); + } + + /** + * Capitalizes a string + * @memberOf fabric.util.string + * @param {String} string String to capitalize + * @param {Boolean} [firstLetterOnly] If true only first letter is capitalized + * and other letters stay untouched, if false first letter is capitalized + * and other letters are converted to lowercase. + * @return {String} Capitalized version of a string + */ + function capitalize(string, firstLetterOnly) { + return string.charAt(0).toUpperCase() + + (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()); + } + + /** + * Escapes XML in a string + * @memberOf fabric.util.string + * @param {String} string String to escape + * @return {String} Escaped version of a string + */ + function escapeXml(string) { + return string.replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + } + + /** + * String utilities + * @namespace fabric.util.string + */ + fabric.util.string = { + camelize: camelize, + capitalize: capitalize, + escapeXml: escapeXml + }; +}()); + + +/* _ES5_COMPAT_START_ */ +(function() { + + var slice = Array.prototype.slice, + apply = Function.prototype.apply, + Dummy = function() { }; + + if (!Function.prototype.bind) { + /** + * Cross-browser approximation of ES5 Function.prototype.bind (not fully spec conforming) + * @see Function#bind on MDN + * @param {Object} thisArg Object to bind function to + * @param {Any[]} [...] Values to pass to a bound function + * @return {Function} + */ + Function.prototype.bind = function(thisArg) { + var _this = this, args = slice.call(arguments, 1), bound; + if (args.length) { + bound = function() { + return apply.call(_this, this instanceof Dummy ? this : thisArg, args.concat(slice.call(arguments))); + }; + } + else { + /** @ignore */ + bound = function() { + return apply.call(_this, this instanceof Dummy ? this : thisArg, arguments); + }; + } + Dummy.prototype = this.prototype; + bound.prototype = new Dummy(); + + return bound; + }; + } + +})(); +/* _ES5_COMPAT_END_ */ + + +(function() { + + var slice = Array.prototype.slice, emptyFunction = function() { }, + + IS_DONTENUM_BUGGY = (function(){ + for (var p in { toString: 1 }) { + if (p === 'toString') { + return false; + } + } + return true; + })(), + + /** @ignore */ + addMethods = function(klass, source, parent) { + for (var property in source) { + + if (property in klass.prototype && + typeof klass.prototype[property] === 'function' && + (source[property] + '').indexOf('callSuper') > -1) { + + klass.prototype[property] = (function(property) { + return function() { + + var superclass = this.constructor.superclass; + this.constructor.superclass = parent; + var returnValue = source[property].apply(this, arguments); + this.constructor.superclass = superclass; + + if (property !== 'initialize') { + return returnValue; + } + }; + })(property); + } + else { + klass.prototype[property] = source[property]; + } + + if (IS_DONTENUM_BUGGY) { + if (source.toString !== Object.prototype.toString) { + klass.prototype.toString = source.toString; + } + if (source.valueOf !== Object.prototype.valueOf) { + klass.prototype.valueOf = source.valueOf; + } + } + } + }; + + function Subclass() { } + + function callSuper(methodName) { + var fn = this.constructor.superclass.prototype[methodName]; + return (arguments.length > 1) + ? fn.apply(this, slice.call(arguments, 1)) + : fn.call(this); + } + + /** + * Helper for creation of "classes". + * @memberOf fabric.util + * @param parent optional "Class" to inherit from + * @param properties Properties shared by all instances of this class + * (be careful modifying objects defined here as this would affect all instances) + */ + function createClass() { + var parent = null, + properties = slice.call(arguments, 0); + + if (typeof properties[0] === 'function') { + parent = properties.shift(); + } + function klass() { + this.initialize.apply(this, arguments); + } + + klass.superclass = parent; + klass.subclasses = [ ]; + + if (parent) { + Subclass.prototype = parent.prototype; + klass.prototype = new Subclass(); + parent.subclasses.push(klass); + } + for (var i = 0, length = properties.length; i < length; i++) { + addMethods(klass, properties[i], parent); + } + if (!klass.prototype.initialize) { + klass.prototype.initialize = emptyFunction; + } + klass.prototype.constructor = klass; + klass.prototype.callSuper = callSuper; + return klass; + } + + fabric.util.createClass = createClass; +})(); + + +(function () { + + var unknown = 'unknown'; + + /* EVENT HANDLING */ + + function areHostMethods(object) { + var methodNames = Array.prototype.slice.call(arguments, 1), + t, i, len = methodNames.length; + for (i = 0; i < len; i++) { + t = typeof object[methodNames[i]]; + if (!(/^(?:function|object|unknown)$/).test(t)) { + return false; + } + } + return true; + } + + /** @ignore */ + var getElement, + setElement, + getUniqueId = (function () { + var uid = 0; + return function (element) { + return element.__uniqueID || (element.__uniqueID = 'uniqueID__' + uid++); + }; + })(); + + (function () { + var elements = { }; + /** @ignore */ + getElement = function (uid) { + return elements[uid]; + }; + /** @ignore */ + setElement = function (uid, element) { + elements[uid] = element; + }; + })(); + + function createListener(uid, handler) { + return { + handler: handler, + wrappedHandler: createWrappedHandler(uid, handler) + }; + } + + function createWrappedHandler(uid, handler) { + return function (e) { + handler.call(getElement(uid), e || fabric.window.event); + }; + } + + function createDispatcher(uid, eventName) { + return function (e) { + if (handlers[uid] && handlers[uid][eventName]) { + var handlersForEvent = handlers[uid][eventName]; + for (var i = 0, len = handlersForEvent.length; i < len; i++) { + handlersForEvent[i].call(this, e || fabric.window.event); + } + } + }; + } + + var shouldUseAddListenerRemoveListener = ( + areHostMethods(fabric.document.documentElement, 'addEventListener', 'removeEventListener') && + areHostMethods(fabric.window, 'addEventListener', 'removeEventListener')), + + shouldUseAttachEventDetachEvent = ( + areHostMethods(fabric.document.documentElement, 'attachEvent', 'detachEvent') && + areHostMethods(fabric.window, 'attachEvent', 'detachEvent')), + + // IE branch + listeners = { }, + + // DOM L0 branch + handlers = { }, + + addListener, removeListener; + + if (shouldUseAddListenerRemoveListener) { + /** @ignore */ + addListener = function (element, eventName, handler) { + element.addEventListener(eventName, handler, false); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + element.removeEventListener(eventName, handler, false); + }; + } + + else if (shouldUseAttachEventDetachEvent) { + /** @ignore */ + addListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + setElement(uid, element); + if (!listeners[uid]) { + listeners[uid] = { }; + } + if (!listeners[uid][eventName]) { + listeners[uid][eventName] = [ ]; + + } + var listener = createListener(uid, handler); + listeners[uid][eventName].push(listener); + element.attachEvent('on' + eventName, listener.wrappedHandler); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + var uid = getUniqueId(element), listener; + if (listeners[uid] && listeners[uid][eventName]) { + for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) { + listener = listeners[uid][eventName][i]; + if (listener && listener.handler === handler) { + element.detachEvent('on' + eventName, listener.wrappedHandler); + listeners[uid][eventName][i] = null; + } + } + } + }; + } + else { + /** @ignore */ + addListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + if (!handlers[uid]) { + handlers[uid] = { }; + } + if (!handlers[uid][eventName]) { + handlers[uid][eventName] = [ ]; + var existingHandler = element['on' + eventName]; + if (existingHandler) { + handlers[uid][eventName].push(existingHandler); + } + element['on' + eventName] = createDispatcher(uid, eventName); + } + handlers[uid][eventName].push(handler); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + if (handlers[uid] && handlers[uid][eventName]) { + var handlersForEvent = handlers[uid][eventName]; + for (var i = 0, len = handlersForEvent.length; i < len; i++) { + if (handlersForEvent[i] === handler) { + handlersForEvent.splice(i, 1); + } + } + } + }; + } + + /** + * Adds an event listener to an element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {String} eventName + * @param {Function} handler + */ + fabric.util.addListener = addListener; + + /** + * Removes an event listener from an element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {String} eventName + * @param {Function} handler + */ + fabric.util.removeListener = removeListener; + + /** + * Cross-browser wrapper for getting event's coordinates + * @memberOf fabric.util + * @param {Event} event Event object + * @param {HTMLCanvasElement} upperCanvasEl <canvas> element on which object selection is drawn + */ + function getPointer(event, upperCanvasEl) { + event || (event = fabric.window.event); + + var element = event.target || + (typeof event.srcElement !== unknown ? event.srcElement : null), + + scroll = fabric.util.getScrollLeftTop(element, upperCanvasEl); + + return { + x: pointerX(event) + scroll.left, + y: pointerY(event) + scroll.top + }; + } + + var pointerX = function(event) { + // looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element) + // is represented as COM object, with all the consequences, like "unknown" type and error on [[Get]] + // need to investigate later + return (typeof event.clientX !== unknown ? event.clientX : 0); + }, + + pointerY = function(event) { + return (typeof event.clientY !== unknown ? event.clientY : 0); + }; + + function _getPointer(event, pageProp, clientProp) { + var touchProp = event.type === 'touchend' ? 'changedTouches' : 'touches'; + + return (event[touchProp] && event[touchProp][0] + ? (event[touchProp][0][pageProp] - (event[touchProp][0][pageProp] - event[touchProp][0][clientProp])) + || event[clientProp] + : event[clientProp]); + } + + if (fabric.isTouchSupported) { + pointerX = function(event) { + return _getPointer(event, 'pageX', 'clientX'); + }; + pointerY = function(event) { + return _getPointer(event, 'pageY', 'clientY'); + }; + } + + fabric.util.getPointer = getPointer; + + fabric.util.object.extend(fabric.util, fabric.Observable); + +})(); + + +(function () { + + /** + * Cross-browser wrapper for setting element's style + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {Object} styles + * @return {HTMLElement} Element that was passed as a first argument + */ + function setStyle(element, styles) { + var elementStyle = element.style; + if (!elementStyle) { + return element; + } + if (typeof styles === 'string') { + element.style.cssText += ';' + styles; + return styles.indexOf('opacity') > -1 + ? setOpacity(element, styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) + : element; + } + for (var property in styles) { + if (property === 'opacity') { + setOpacity(element, styles[property]); + } + else { + var normalizedProperty = (property === 'float' || property === 'cssFloat') + ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat') + : property; + elementStyle[normalizedProperty] = styles[property]; + } + } + return element; + } + + var parseEl = fabric.document.createElement('div'), + supportsOpacity = typeof parseEl.style.opacity === 'string', + supportsFilters = typeof parseEl.style.filter === 'string', + reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/, + + /** @ignore */ + setOpacity = function (element) { return element; }; + + if (supportsOpacity) { + /** @ignore */ + setOpacity = function(element, value) { + element.style.opacity = value; + return element; + }; + } + else if (supportsFilters) { + /** @ignore */ + setOpacity = function(element, value) { + var es = element.style; + if (element.currentStyle && !element.currentStyle.hasLayout) { + es.zoom = 1; + } + if (reOpacity.test(es.filter)) { + value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')'); + es.filter = es.filter.replace(reOpacity, value); + } + else { + es.filter += ' alpha(opacity=' + (value * 100) + ')'; + } + return element; + }; + } + + fabric.util.setStyle = setStyle; + +})(); + + +(function() { + + var _slice = Array.prototype.slice; + + /** + * Takes id and returns an element with that id (if one exists in a document) + * @memberOf fabric.util + * @param {String|HTMLElement} id + * @return {HTMLElement|null} + */ + function getById(id) { + return typeof id === 'string' ? fabric.document.getElementById(id) : id; + } + + var sliceCanConvertNodelists, + /** + * Converts an array-like object (e.g. arguments or NodeList) to an array + * @memberOf fabric.util + * @param {Object} arrayLike + * @return {Array} + */ + toArray = function(arrayLike) { + return _slice.call(arrayLike, 0); + }; + + try { + sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array; + } + catch (err) { } + + if (!sliceCanConvertNodelists) { + toArray = function(arrayLike) { + var arr = new Array(arrayLike.length), i = arrayLike.length; + while (i--) { + arr[i] = arrayLike[i]; + } + return arr; + }; + } + + /** + * Creates specified element with specified attributes + * @memberOf fabric.util + * @param {String} tagName Type of an element to create + * @param {Object} [attributes] Attributes to set on an element + * @return {HTMLElement} Newly created element + */ + function makeElement(tagName, attributes) { + var el = fabric.document.createElement(tagName); + for (var prop in attributes) { + if (prop === 'class') { + el.className = attributes[prop]; + } + else if (prop === 'for') { + el.htmlFor = attributes[prop]; + } + else { + el.setAttribute(prop, attributes[prop]); + } + } + return el; + } + + /** + * Adds class to an element + * @memberOf fabric.util + * @param {HTMLElement} element Element to add class to + * @param {String} className Class to add to an element + */ + function addClass(element, className) { + if (element && (' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) { + element.className += (element.className ? ' ' : '') + className; + } + } + + /** + * Wraps element with another element + * @memberOf fabric.util + * @param {HTMLElement} element Element to wrap + * @param {HTMLElement|String} wrapper Element to wrap with + * @param {Object} [attributes] Attributes to set on a wrapper + * @return {HTMLElement} wrapper + */ + function wrapElement(element, wrapper, attributes) { + if (typeof wrapper === 'string') { + wrapper = makeElement(wrapper, attributes); + } + if (element.parentNode) { + element.parentNode.replaceChild(wrapper, element); + } + wrapper.appendChild(element); + return wrapper; + } + + /** + * Returns element scroll offsets + * @memberOf fabric.util + * @param {HTMLElement} element Element to operate on + * @param {HTMLElement} upperCanvasEl Upper canvas element + * @return {Object} Object with left/top values + */ + function getScrollLeftTop(element, upperCanvasEl) { + + var firstFixedAncestor, + origElement, + left = 0, + top = 0, + docElement = fabric.document.documentElement, + body = fabric.document.body || { + scrollLeft: 0, scrollTop: 0 + }; + + origElement = element; + + while (element && element.parentNode && !firstFixedAncestor) { + + element = element.parentNode; + + if (element !== fabric.document && + fabric.util.getElementStyle(element, 'position') === 'fixed') { + firstFixedAncestor = element; + } + + if (element !== fabric.document && + origElement !== upperCanvasEl && + fabric.util.getElementStyle(element, 'position') === 'absolute') { + left = 0; + top = 0; + } + else if (element === fabric.document) { + left = body.scrollLeft || docElement.scrollLeft || 0; + top = body.scrollTop || docElement.scrollTop || 0; + } + else { + left += element.scrollLeft || 0; + top += element.scrollTop || 0; + } + } + + return { left: left, top: top }; + } + + /** + * Returns offset for a given element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element Element to get offset for + * @return {Object} Object with "left" and "top" properties + */ + function getElementOffset(element) { + var docElem, + doc = element && element.ownerDocument, + box = { left: 0, top: 0 }, + offset = { left: 0, top: 0 }, + scrollLeftTop, + offsetAttributes = { + borderLeftWidth: 'left', + borderTopWidth: 'top', + paddingLeft: 'left', + paddingTop: 'top' + }; + + if (!doc) { + return { left: 0, top: 0 }; + } + + for (var attr in offsetAttributes) { + offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0; + } + + docElem = doc.documentElement; + if ( typeof element.getBoundingClientRect !== 'undefined' ) { + box = element.getBoundingClientRect(); + } + + scrollLeftTop = fabric.util.getScrollLeftTop(element, null); + + return { + left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left, + top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top + }; + } + + /** + * Returns style attribute value of a given element + * @memberOf fabric.util + * @param {HTMLElement} element Element to get style attribute for + * @param {String} attr Style attribute to get for element + * @return {String} Style attribute value of the given element. + */ + var getElementStyle; + if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) { + getElementStyle = function(element, attr) { + return fabric.document.defaultView.getComputedStyle(element, null)[attr]; + }; + } + else { + getElementStyle = function(element, attr) { + var value = element.style[attr]; + if (!value && element.currentStyle) { + value = element.currentStyle[attr]; + } + return value; + }; + } + + (function () { + var style = fabric.document.documentElement.style, + selectProp = 'userSelect' in style + ? 'userSelect' + : 'MozUserSelect' in style + ? 'MozUserSelect' + : 'WebkitUserSelect' in style + ? 'WebkitUserSelect' + : 'KhtmlUserSelect' in style + ? 'KhtmlUserSelect' + : ''; + + /** + * Makes element unselectable + * @memberOf fabric.util + * @param {HTMLElement} element Element to make unselectable + * @return {HTMLElement} Element that was passed in + */ + function makeElementUnselectable(element) { + if (typeof element.onselectstart !== 'undefined') { + element.onselectstart = fabric.util.falseFunction; + } + if (selectProp) { + element.style[selectProp] = 'none'; + } + else if (typeof element.unselectable === 'string') { + element.unselectable = 'on'; + } + return element; + } + + /** + * Makes element selectable + * @memberOf fabric.util + * @param {HTMLElement} element Element to make selectable + * @return {HTMLElement} Element that was passed in + */ + function makeElementSelectable(element) { + if (typeof element.onselectstart !== 'undefined') { + element.onselectstart = null; + } + if (selectProp) { + element.style[selectProp] = ''; + } + else if (typeof element.unselectable === 'string') { + element.unselectable = ''; + } + return element; + } + + fabric.util.makeElementUnselectable = makeElementUnselectable; + fabric.util.makeElementSelectable = makeElementSelectable; + })(); + + (function() { + + /** + * Inserts a script element with a given url into a document; invokes callback, when that script is finished loading + * @memberOf fabric.util + * @param {String} url URL of a script to load + * @param {Function} callback Callback to execute when script is finished loading + */ + function getScript(url, callback) { + var headEl = fabric.document.getElementsByTagName('head')[0], + scriptEl = fabric.document.createElement('script'), + loading = true; + + /** @ignore */ + scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) { + if (loading) { + if (typeof this.readyState === 'string' && + this.readyState !== 'loaded' && + this.readyState !== 'complete') return; + loading = false; + callback(e || fabric.window.event); + scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null; + } + }; + scriptEl.src = url; + headEl.appendChild(scriptEl); + // causes issue in Opera + // headEl.removeChild(scriptEl); + } + + fabric.util.getScript = getScript; + })(); + + fabric.util.getById = getById; + fabric.util.toArray = toArray; + fabric.util.makeElement = makeElement; + fabric.util.addClass = addClass; + fabric.util.wrapElement = wrapElement; + fabric.util.getScrollLeftTop = getScrollLeftTop; + fabric.util.getElementOffset = getElementOffset; + fabric.util.getElementStyle = getElementStyle; + +})(); + + +(function(){ + + function addParamToUrl(url, param) { + return url + (/\?/.test(url) ? '&' : '?') + param; + } + + var makeXHR = (function() { + var factories = [ + function() { return new ActiveXObject('Microsoft.XMLHTTP'); }, + function() { return new ActiveXObject('Msxml2.XMLHTTP'); }, + function() { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); }, + function() { return new XMLHttpRequest(); } + ]; + for (var i = factories.length; i--; ) { + try { + var req = factories[i](); + if (req) { + return factories[i]; + } + } + catch (err) { } + } + })(); + + function emptyFn() { } + + /** + * Cross-browser abstraction for sending XMLHttpRequest + * @memberOf fabric.util + * @param {String} url URL to send XMLHttpRequest to + * @param {Object} [options] Options object + * @param {String} [options.method="GET"] + * @param {Function} options.onComplete Callback to invoke when request is completed + * @return {XMLHttpRequest} request + */ + function request(url, options) { + + options || (options = { }); + + var method = options.method ? options.method.toUpperCase() : 'GET', + onComplete = options.onComplete || function() { }, + xhr = makeXHR(), + body; + + /** @ignore */ + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + onComplete(xhr); + xhr.onreadystatechange = emptyFn; + } + }; + + if (method === 'GET') { + body = null; + if (typeof options.parameters === 'string') { + url = addParamToUrl(url, options.parameters); + } + } + + xhr.open(method, url, true); + + if (method === 'POST' || method === 'PUT') { + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + } + + xhr.send(body); + return xhr; + } + + fabric.util.request = request; +})(); + + +/** + * Wrapper around `console.log` (when available) + * @param {Any} values Values to log + */ +fabric.log = function() { }; + +/** + * Wrapper around `console.warn` (when available) + * @param {Any} Values to log as a warning + */ +fabric.warn = function() { }; + +if (typeof console !== 'undefined') { + ['log', 'warn'].forEach(function(methodName) { + if (typeof console[methodName] !== 'undefined' && console[methodName].apply) { + fabric[methodName] = function() { + return console[methodName].apply(console, arguments); + }; + } + }); +} + + +(function() { + + /** + * Changes value from one to another within certain period of time, invoking callbacks as value is being changed. + * @memberOf fabric.util + * @param {Object} [options] Animation options + * @param {Function} [options.onChange] Callback; invoked on every value change + * @param {Function} [options.onComplete] Callback; invoked when value change is completed + * @param {Number} [options.startValue=0] Starting value + * @param {Number} [options.endValue=100] Ending value + * @param {Number} [options.byValue=100] Value to modify the property by + * @param {Function} [options.easing] Easing function + * @param {Number} [options.duration=500] Duration of change (in ms) + */ + function animate(options) { + + requestAnimFrame(function(timestamp) { + options || (options = { }); + + var start = timestamp || +new Date(), + duration = options.duration || 500, + finish = start + duration, time, + onChange = options.onChange || function() { }, + abort = options.abort || function() { return false; }, + easing = options.easing || function(t, b, c, d) {return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;}, + startValue = 'startValue' in options ? options.startValue : 0, + endValue = 'endValue' in options ? options.endValue : 100, + byValue = options.byValue || endValue - startValue; + + options.onStart && options.onStart(); + + (function tick(ticktime) { + time = ticktime || +new Date(); + var currentTime = time > finish ? duration : (time - start); + if (abort()) { + options.onComplete && options.onComplete(); + return; + } + onChange(easing(currentTime, startValue, byValue, duration)); + if (time > finish) { + options.onComplete && options.onComplete(); + return; + } + requestAnimFrame(tick); + })(start); + }); + + } + + var _requestAnimFrame = fabric.window.requestAnimationFrame || + fabric.window.webkitRequestAnimationFrame || + fabric.window.mozRequestAnimationFrame || + fabric.window.oRequestAnimationFrame || + fabric.window.msRequestAnimationFrame || + function(callback) { + fabric.window.setTimeout(callback, 1000 / 60); + }; + /** + * requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + * In order to get a precise start time, `requestAnimFrame` should be called as an entry into the method + * @memberOf fabric.util + * @param {Function} callback Callback to invoke + * @param {DOMElement} element optional Element to associate with animation + */ + function requestAnimFrame() { + return _requestAnimFrame.apply(fabric.window, arguments); + } + + fabric.util.animate = animate; + fabric.util.requestAnimFrame = requestAnimFrame; + +})(); + + +(function() { + + function normalize(a, c, p, s) { + if (a < Math.abs(c)) { + a = c; + s = p / 4; + } + else { + s = p / (2 * Math.PI) * Math.asin(c / a); + } + return { a: a, c: c, p: p, s: s }; + } + + function elastic(opts, t, d) { + return opts.a * + Math.pow(2, 10 * (t -= 1)) * + Math.sin( (t * d - opts.s) * (2 * Math.PI) / opts.p ); + } + + /** + * Cubic easing out + * @memberOf fabric.util.ease + */ + function easeOutCubic(t, b, c, d) { + return c * ((t = t / d - 1) * t * t + 1) + b; + } + + /** + * Cubic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutCubic(t, b, c, d) { + t /= d/2; + if (t < 1) { + return c / 2 * t * t * t + b; + } + return c / 2 * ((t -= 2) * t * t + 2) + b; + } + + /** + * Quartic easing in + * @memberOf fabric.util.ease + */ + function easeInQuart(t, b, c, d) { + return c * (t /= d) * t * t * t + b; + } + + /** + * Quartic easing out + * @memberOf fabric.util.ease + */ + function easeOutQuart(t, b, c, d) { + return -c * ((t = t / d - 1) * t * t * t - 1) + b; + } + + /** + * Quartic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutQuart(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return c / 2 * t * t * t * t + b; + } + return -c / 2 * ((t -= 2) * t * t * t - 2) + b; + } + + /** + * Quintic easing in + * @memberOf fabric.util.ease + */ + function easeInQuint(t, b, c, d) { + return c * (t /= d) * t * t * t * t + b; + } + + /** + * Quintic easing out + * @memberOf fabric.util.ease + */ + function easeOutQuint(t, b, c, d) { + return c * ((t = t / d - 1) * t * t * t * t + 1) + b; + } + + /** + * Quintic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutQuint(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return c / 2 * t * t * t * t * t + b; + } + return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; + } + + /** + * Sinusoidal easing in + * @memberOf fabric.util.ease + */ + function easeInSine(t, b, c, d) { + return -c * Math.cos(t / d * (Math.PI / 2)) + c + b; + } + + /** + * Sinusoidal easing out + * @memberOf fabric.util.ease + */ + function easeOutSine(t, b, c, d) { + return c * Math.sin(t / d * (Math.PI / 2)) + b; + } + + /** + * Sinusoidal easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutSine(t, b, c, d) { + return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b; + } + + /** + * Exponential easing in + * @memberOf fabric.util.ease + */ + function easeInExpo(t, b, c, d) { + return (t === 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b; + } + + /** + * Exponential easing out + * @memberOf fabric.util.ease + */ + function easeOutExpo(t, b, c, d) { + return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b; + } + + /** + * Exponential easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutExpo(t, b, c, d) { + if (t === 0) { + return b; + } + if (t === d) { + return b + c; + } + t /= d / 2; + if (t < 1) { + return c / 2 * Math.pow(2, 10 * (t - 1)) + b; + } + return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b; + } + + /** + * Circular easing in + * @memberOf fabric.util.ease + */ + function easeInCirc(t, b, c, d) { + return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b; + } + + /** + * Circular easing out + * @memberOf fabric.util.ease + */ + function easeOutCirc(t, b, c, d) { + return c * Math.sqrt(1 - (t = t / d - 1) * t) + b; + } + + /** + * Circular easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutCirc(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b; + } + return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b; + } + + /** + * Elastic easing in + * @memberOf fabric.util.ease + */ + function easeInElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d; + if (t === 1) { + return b + c; + } + if (!p) { + p = d * 0.3; + } + var opts = normalize(a, c, p, s); + return -elastic(opts, t, d) + b; + } + + /** + * Elastic easing out + * @memberOf fabric.util.ease + */ + function easeOutElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d; + if (t === 1) { + return b + c; + } + if (!p) { + p = d * 0.3; + } + var opts = normalize(a, c, p, s); + return opts.a * Math.pow(2, -10 * t) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) + opts.c + b; + } + + /** + * Elastic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d / 2; + if (t === 2) { + return b + c; + } + if (!p) { + p = d * (0.3 * 1.5); + } + var opts = normalize(a, c, p, s); + if (t < 1) { + return -0.5 * elastic(opts, t, d) + b; + } + return opts.a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) * 0.5 + opts.c + b; + } + + /** + * Backwards easing in + * @memberOf fabric.util.ease + */ + function easeInBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + return c * (t /= d) * t * ((s + 1) * t - s) + b; + } + + /** + * Backwards easing out + * @memberOf fabric.util.ease + */ + function easeOutBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; + } + + /** + * Backwards easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + t /= d / 2; + if (t < 1) { + return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b; + } + return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b; + } + + /** + * Bouncing easing in + * @memberOf fabric.util.ease + */ + function easeInBounce(t, b, c, d) { + return c - easeOutBounce (d - t, 0, c, d) + b; + } + + /** + * Bouncing easing out + * @memberOf fabric.util.ease + */ + function easeOutBounce(t, b, c, d) { + if ((t /= d) < (1 / 2.75)) { + return c * (7.5625 * t * t) + b; + } + else if (t < (2/2.75)) { + return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b; + } + else if (t < (2.5/2.75)) { + return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b; + } + else { + return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b; + } + } + + /** + * Bouncing easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutBounce(t, b, c, d) { + if (t < d / 2) { + return easeInBounce (t * 2, 0, c, d) * 0.5 + b; + } + return easeOutBounce(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b; + } + + /** + * Easing functions + * See Easing Equations by Robert Penner + * @namespace fabric.util.ease + */ + fabric.util.ease = { + + /** + * Quadratic easing in + * @memberOf fabric.util.ease + */ + easeInQuad: function(t, b, c, d) { + return c * (t /= d) * t + b; + }, + + /** + * Quadratic easing out + * @memberOf fabric.util.ease + */ + easeOutQuad: function(t, b, c, d) { + return -c * (t /= d) * (t - 2) + b; + }, + + /** + * Quadratic easing in and out + * @memberOf fabric.util.ease + */ + easeInOutQuad: function(t, b, c, d) { + t /= (d / 2); + if (t < 1) { + return c / 2 * t * t + b; + } + return -c / 2 * ((--t) * (t - 2) - 1) + b; + }, + + /** + * Cubic easing in + * @memberOf fabric.util.ease + */ + easeInCubic: function(t, b, c, d) { + return c * (t /= d) * t * t + b; + }, + + easeOutCubic: easeOutCubic, + easeInOutCubic: easeInOutCubic, + easeInQuart: easeInQuart, + easeOutQuart: easeOutQuart, + easeInOutQuart: easeInOutQuart, + easeInQuint: easeInQuint, + easeOutQuint: easeOutQuint, + easeInOutQuint: easeInOutQuint, + easeInSine: easeInSine, + easeOutSine: easeOutSine, + easeInOutSine: easeInOutSine, + easeInExpo: easeInExpo, + easeOutExpo: easeOutExpo, + easeInOutExpo: easeInOutExpo, + easeInCirc: easeInCirc, + easeOutCirc: easeOutCirc, + easeInOutCirc: easeInOutCirc, + easeInElastic: easeInElastic, + easeOutElastic: easeOutElastic, + easeInOutElastic: easeInOutElastic, + easeInBack: easeInBack, + easeOutBack: easeOutBack, + easeInOutBack: easeInOutBack, + easeInBounce: easeInBounce, + easeOutBounce: easeOutBounce, + easeInOutBounce: easeInOutBounce + }; + +}()); + + +(function(global) { + + 'use strict'; + + /** + * @name fabric + * @namespace + */ + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + capitalize = fabric.util.string.capitalize, + clone = fabric.util.object.clone, + toFixed = fabric.util.toFixed, + multiplyTransformMatrices = fabric.util.multiplyTransformMatrices, + + attributesMap = { + cx: 'left', + x: 'left', + r: 'radius', + cy: 'top', + y: 'top', + display: 'visible', + visibility: 'visible', + transform: 'transformMatrix', + 'fill-opacity': 'fillOpacity', + 'fill-rule': 'fillRule', + 'font-family': 'fontFamily', + 'font-size': 'fontSize', + 'font-style': 'fontStyle', + 'font-weight': 'fontWeight', + 'stroke-dasharray': 'strokeDashArray', + 'stroke-linecap': 'strokeLineCap', + 'stroke-linejoin': 'strokeLineJoin', + 'stroke-miterlimit': 'strokeMiterLimit', + 'stroke-opacity': 'strokeOpacity', + 'stroke-width': 'strokeWidth', + 'text-decoration': 'textDecoration', + 'text-anchor': 'originX' + }, + + colorAttributes = { + stroke: 'strokeOpacity', + fill: 'fillOpacity' + }; + + function normalizeAttr(attr) { + // transform attribute names + if (attr in attributesMap) { + return attributesMap[attr]; + } + return attr; + } + + function normalizeValue(attr, value, parentAttributes) { + var isArray; + + if ((attr === 'fill' || attr === 'stroke') && value === 'none') { + value = ''; + } + else if (attr === 'fillRule') { + value = (value === 'evenodd') ? 'destination-over' : value; + } + else if (attr === 'strokeDashArray') { + value = value.replace(/,/g, ' ').split(/\s+/); + } + else if (attr === 'transformMatrix') { + if (parentAttributes && parentAttributes.transformMatrix) { + value = multiplyTransformMatrices( + parentAttributes.transformMatrix, fabric.parseTransformAttribute(value)); + } + else { + value = fabric.parseTransformAttribute(value); + } + } + else if (attr === 'visible') { + value = (value === 'none' || value === 'hidden') ? false : true; + // display=none on parent element always takes precedence over child element + if (parentAttributes && parentAttributes.visible === false) { + value = false; + } + } + else if (attr === 'originX' /* text-anchor */) { + value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center'; + } + + isArray = Object.prototype.toString.call(value) === '[object Array]'; + + // TODO: need to normalize em, %, pt, etc. to px (!) + var parsed = isArray ? value.map(parseFloat) : parseFloat(value); + + return (!isArray && isNaN(parsed) ? value : parsed); + } + + /** + * @private + * @param {Object} attributes Array of attributes to parse + */ + function _setStrokeFillOpacity(attributes) { + for (var attr in colorAttributes) { + + if (!attributes[attr] || typeof attributes[colorAttributes[attr]] === 'undefined') continue; + + if (attributes[attr].indexOf('url(') === 0) continue; + + var color = new fabric.Color(attributes[attr]); + attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba(); + + delete attributes[colorAttributes[attr]]; + } + return attributes; + } + + /** + * Parses "transform" attribute, returning an array of values + * @static + * @function + * @memberOf fabric + * @param {String} attributeValue String containing attribute value + * @return {Array} Array of 6 elements representing transformation matrix + */ + fabric.parseTransformAttribute = (function() { + function rotateMatrix(matrix, args) { + var angle = args[0]; + + matrix[0] = Math.cos(angle); + matrix[1] = Math.sin(angle); + matrix[2] = -Math.sin(angle); + matrix[3] = Math.cos(angle); + } + + function scaleMatrix(matrix, args) { + var multiplierX = args[0], + multiplierY = (args.length === 2) ? args[1] : args[0]; + + matrix[0] = multiplierX; + matrix[3] = multiplierY; + } + + function skewXMatrix(matrix, args) { + matrix[2] = args[0]; + } + + function skewYMatrix(matrix, args) { + matrix[1] = args[0]; + } + + function translateMatrix(matrix, args) { + matrix[4] = args[0]; + if (args.length === 2) { + matrix[5] = args[1]; + } + } + + // identity matrix + var iMatrix = [ + 1, // a + 0, // b + 0, // c + 1, // d + 0, // e + 0 // f + ], + + // == begin transform regexp + number = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)', + + commaWsp = '(?:\\s+,?\\s*|,\\s*)', + + skewX = '(?:(skewX)\\s*\\(\\s*(' + number + ')\\s*\\))', + + skewY = '(?:(skewY)\\s*\\(\\s*(' + number + ')\\s*\\))', + + rotate = '(?:(rotate)\\s*\\(\\s*(' + number + ')(?:' + + commaWsp + '(' + number + ')' + + commaWsp + '(' + number + '))?\\s*\\))', + + scale = '(?:(scale)\\s*\\(\\s*(' + number + ')(?:' + + commaWsp + '(' + number + '))?\\s*\\))', + + translate = '(?:(translate)\\s*\\(\\s*(' + number + ')(?:' + + commaWsp + '(' + number + '))?\\s*\\))', + + matrix = '(?:(matrix)\\s*\\(\\s*' + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + + '\\s*\\))', + + transform = '(?:' + + matrix + '|' + + translate + '|' + + scale + '|' + + rotate + '|' + + skewX + '|' + + skewY + + ')', + + transforms = '(?:' + transform + '(?:' + commaWsp + transform + ')*' + ')', + + transformList = '^\\s*(?:' + transforms + '?)\\s*$', + + // http://www.w3.org/TR/SVG/coords.html#TransformAttribute + reTransformList = new RegExp(transformList), + // == end transform regexp + + reTransform = new RegExp(transform, 'g'); + + return function(attributeValue) { + + // start with identity matrix + var matrix = iMatrix.concat(), + matrices = [ ]; + + // return if no argument was given or + // an argument does not match transform attribute regexp + if (!attributeValue || (attributeValue && !reTransformList.test(attributeValue))) { + return matrix; + } + + attributeValue.replace(reTransform, function(match) { + + var m = new RegExp(transform).exec(match).filter(function (match) { + return (match !== '' && match != null); + }), + operation = m[1], + args = m.slice(2).map(parseFloat); + + switch (operation) { + case 'translate': + translateMatrix(matrix, args); + break; + case 'rotate': + args[0] = fabric.util.degreesToRadians(args[0]); + rotateMatrix(matrix, args); + break; + case 'scale': + scaleMatrix(matrix, args); + break; + case 'skewX': + skewXMatrix(matrix, args); + break; + case 'skewY': + skewYMatrix(matrix, args); + break; + case 'matrix': + matrix = args; + break; + } + + // snapshot current matrix into matrices array + matrices.push(matrix.concat()); + // reset + matrix = iMatrix.concat(); + }); + + var combinedMatrix = matrices[0]; + while (matrices.length > 1) { + matrices.shift(); + combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]); + } + return combinedMatrix; + }; + })(); + + function parseFontDeclaration(value, oStyle) { + + // TODO: support non-px font size + var match = value.match(/(normal|italic)?\s*(normal|small-caps)?\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\s*(\d+)px(?:\/(normal|[\d\.]+))?\s+(.*)/); + + if (!match) return; + + var fontStyle = match[1], + // font variant is not used + // fontVariant = match[2], + fontWeight = match[3], + fontSize = match[4], + lineHeight = match[5], + fontFamily = match[6]; + + if (fontStyle) { + oStyle.fontStyle = fontStyle; + } + if (fontWeight) { + oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight); + } + if (fontSize) { + oStyle.fontSize = parseFloat(fontSize); + } + if (fontFamily) { + oStyle.fontFamily = fontFamily; + } + if (lineHeight) { + oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight; + } + } + + /** + * @private + */ + function parseStyleString(style, oStyle) { + var attr, value; + style.replace(/;$/, '').split(';').forEach(function (chunk) { + var pair = chunk.split(':'); + + attr = normalizeAttr(pair[0].trim().toLowerCase()); + value = normalizeValue(attr, pair[1].trim()); + + if (attr === 'font') { + parseFontDeclaration(value, oStyle); + } + else { + oStyle[attr] = value; + } + }); + } + + /** + * @private + */ + function parseStyleObject(style, oStyle) { + var attr, value; + for (var prop in style) { + if (typeof style[prop] === 'undefined') continue; + + attr = normalizeAttr(prop.toLowerCase()); + value = normalizeValue(attr, style[prop]); + + if (attr === 'font') { + parseFontDeclaration(value, oStyle); + } + else { + oStyle[attr] = value; + } + } + } + + /** + * @private + */ + function getGlobalStylesForElement(element) { + var nodeName = element.nodeName, + className = element.getAttribute('class'), + id = element.getAttribute('id'), + styles = { }; + + for (var rule in fabric.cssRules) { + var ruleMatchesElement = (className && new RegExp('^\\.' + className).test(rule)) || + (id && new RegExp('^#' + id).test(rule)) || + (new RegExp('^' + nodeName).test(rule)); + + if (ruleMatchesElement) { + for (var property in fabric.cssRules[rule]) { + var attr = normalizeAttr(property), + value = normalizeValue(attr, fabric.cssRules[rule][property]); + styles[attr] = value; + } + } + } + + return styles; + } + + /** + * @private + */ + function parseUseDirectives(doc) { + var nodelist = doc.querySelectorAll("use"); + for (var i = 0; i < nodelist.length; i++) { + var el = nodelist[i]; + var xlink = el.getAttribute('xlink:href').substr(1); + var x = el.getAttribute('x') || 0; + var y = el.getAttribute('y') || 0; + var el2 = doc.getElementById(xlink).cloneNode(true); + var currentTrans = (el.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')'; + for (var j = 0, attrs = el.attributes, l = attrs.length; j < l; j++) { + var attr = attrs.item(j); + if (attr.nodeName !== 'x' && attr.nodeName !== 'y' && attr.nodeName !== 'xlink:href') { + if (attr.nodeName === 'transform') { + currentTrans = currentTrans + ' ' + attr.nodeValue; + } else { + el2.setAttribute(attr.nodeName, attr.nodeValue); + } + } + } + el2.setAttribute('transform', currentTrans); + el2.removeAttribute('id'); + var pNode=el.parentNode; + pNode.replaceChild(el2, el); + } + } + + /** + * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @param {Function} callback Callback to call when parsing is finished; It's being passed an array of elements (parsed from a document). + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + fabric.parseSVGDocument = (function() { + + var reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/, + + // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute + // \d doesn't quite cut it (as we need to match an actual float number) + + // matches, e.g.: +14.56e-12, etc. + reNum = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)', + + reViewBoxAttrValue = new RegExp( + '^' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*' + + '$' + ); + + function hasAncestorWithNodeName(element, nodeName) { + while (element && (element = element.parentNode)) { + if (nodeName.test(element.nodeName)) { + return true; + } + } + return false; + } + + return function(doc, callback, reviver) { + if (!doc) return; + var startTime = new Date(); + + parseUseDirectives(doc); + + var descendants = fabric.util.toArray(doc.getElementsByTagName('*')); + + if (descendants.length === 0 && fabric.isLikelyNode) { + // we're likely in node, where "o3-xml" library fails to gEBTN("*") + // https://github.com/ajaxorg/node-o3-xml/issues/21 + descendants = doc.selectNodes('//*[name(.)!="svg"]'); + var arr = [ ]; + for (var i = 0, len = descendants.length; i < len; i++) { + arr[i] = descendants[i]; + } + descendants = arr; + } + + var elements = descendants.filter(function(el) { + return reAllowedSVGTagNames.test(el.tagName) && + !hasAncestorWithNodeName(el, /^(?:pattern|defs)$/); // http://www.w3.org/TR/SVG/struct.html#DefsElement + }); + + if (!elements || (elements && !elements.length)) { + callback && callback([], {}); + return; + } + + var viewBoxAttr = doc.getAttribute('viewBox'), + widthAttr = parseFloat(doc.getAttribute('width')), + heightAttr = parseFloat(doc.getAttribute('height')), + width = null, + height = null, + viewBoxWidth, + viewBoxHeight, + minX, + minY; + + if (viewBoxAttr && (viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))) { + minX = parseFloat(viewBoxAttr[1]); + minY = parseFloat(viewBoxAttr[2]); + viewBoxWidth = parseFloat(viewBoxAttr[3]); + viewBoxHeight = parseFloat(viewBoxAttr[4]); + } + + if (viewBoxWidth && widthAttr && viewBoxWidth !== widthAttr) { + width = viewBoxWidth; + height = viewBoxHeight; + } + else { + // values of width/height attributes overwrite those extracted from viewbox attribute + width = widthAttr ? widthAttr : viewBoxWidth; + height = heightAttr ? heightAttr : viewBoxHeight; + } + + var options = { + width: width, + height: height, + widthAttr: widthAttr, + heightAttr: heightAttr + }; + + fabric.gradientDefs = fabric.getGradientDefs(doc); + fabric.cssRules = fabric.getCSSRules(doc); + // Precedence of rules: style > class > attribute + + fabric.parseElements(elements, function(instances) { + fabric.documentParsingTime = new Date() - startTime; + if (callback) { + callback(instances, options); + } + }, clone(options), reviver); + }; + })(); + + /** + * Used for caching SVG documents (loaded via `fabric.Canvas#loadSVGFromURL`) + * @namespace + */ + var svgCache = { + + /** + * @param {String} name + * @param {Function} callback + */ + has: function (name, callback) { + callback(false); + }, + + /** + * @param {String} url + * @param {Function} callback + */ + get: function () { + /* NOOP */ + }, + + /** + * @param {String} url + * @param {Object} object + */ + set: function () { + /* NOOP */ + } + }; + + /** + * @private + */ + function _enlivenCachedObject(cachedObject) { + + var objects = cachedObject.objects, + options = cachedObject.options; + + objects = objects.map(function (o) { + return fabric[capitalize(o.type)].fromObject(o); + }); + + return ({ objects: objects, options: options }); + } + + /** + * @private + */ + function _createSVGPattern(markup, canvas, property) { + if (canvas[property] && canvas[property].toSVG) { + markup.push( + '', + '' + ); + } + } + + extend(fabric, { + + /** + * Initializes gradients on instances, according to gradients parsed from a document + * @param {Array} instances + */ + resolveGradients: function(instances) { + for (var i = instances.length; i--; ) { + var instanceFillValue = instances[i].get('fill'); + + if (!(/^url\(/).test(instanceFillValue)) continue; + + var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1); + + if (fabric.gradientDefs[gradientId]) { + instances[i].set('fill', + fabric.Gradient.fromElement(fabric.gradientDefs[gradientId], instances[i])); + } + } + }, + + /** + * Parses an SVG document, returning all of the gradient declarations found in it + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element + */ + getGradientDefs: function(doc) { + var linearGradientEls = doc.getElementsByTagName('linearGradient'), + radialGradientEls = doc.getElementsByTagName('radialGradient'), + el, i, + gradientDefs = { }; + + i = linearGradientEls.length; + for (; i--; ) { + el = linearGradientEls[i]; + gradientDefs[el.getAttribute('id')] = el; + } + + i = radialGradientEls.length; + for (; i--; ) { + el = radialGradientEls[i]; + gradientDefs[el.getAttribute('id')] = el; + } + + return gradientDefs; + }, + + /** + * Returns an object of attributes' name/value, given element and an array of attribute names; + * Parses parent "g" nodes recursively upwards. + * @static + * @memberOf fabric + * @param {DOMElement} element Element to parse + * @param {Array} attributes Array of attributes to parse + * @return {Object} object containing parsed attributes' names/values + */ + parseAttributes: function(element, attributes) { + + if (!element) { + return; + } + + var value, + parentAttributes = { }; + + // if there's a parent container (`g` node), parse its attributes recursively upwards + if (element.parentNode && /^g$/i.test(element.parentNode.nodeName)) { + parentAttributes = fabric.parseAttributes(element.parentNode, attributes); + } + + var ownAttributes = attributes.reduce(function(memo, attr) { + value = element.getAttribute(attr); + if (value) { + attr = normalizeAttr(attr); + value = normalizeValue(attr, value, parentAttributes); + + memo[attr] = value; + } + return memo; + }, { }); + + // add values parsed from style, which take precedence over attributes + // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes) + ownAttributes = extend(ownAttributes, + extend(getGlobalStylesForElement(element), fabric.parseStyleAttribute(element))); + + return _setStrokeFillOpacity(extend(parentAttributes, ownAttributes)); + }, + + /** + * Transforms an array of svg elements to corresponding fabric.* instances + * @static + * @memberOf fabric + * @param {Array} elements Array of elements to parse + * @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements) + * @param {Object} [options] Options object + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + parseElements: function(elements, callback, options, reviver) { + new fabric.ElementsParser(elements, callback, options, reviver).parse(); + }, + + /** + * Parses "style" attribute, retuning an object with values + * @static + * @memberOf fabric + * @param {SVGElement} element Element to parse + * @return {Object} Objects with values parsed from style attribute of an element + */ + parseStyleAttribute: function(element) { + var oStyle = { }, + style = element.getAttribute('style'); + + if (!style) { + return oStyle; + } + + if (typeof style === 'string') { + parseStyleString(style, oStyle); + } + else { + parseStyleObject(style, oStyle); + } + + return oStyle; + }, + + /** + * Parses "points" attribute, returning an array of values + * @static + * @memberOf fabric + * @param points {String} points attribute string + * @return {Array} array of points + */ + parsePointsAttribute: function(points) { + + // points attribute is required and must not be empty + if (!points) return null; + + points = points.trim(); + var asPairs = points.indexOf(',') > -1; + + points = points.split(/\s+/); + var parsedPoints = [ ], i, len; + + // points could look like "10,20 30,40" or "10 20 30 40" + if (asPairs) { + i = 0; + len = points.length; + for (; i < len; i++) { + var pair = points[i].split(','); + parsedPoints.push({ + x: parseFloat(pair[0]), + y: parseFloat(pair[1]) + }); + } + } + else { + i = 0; + len = points.length; + for (; i < len; i+=2) { + parsedPoints.push({ + x: parseFloat(points[i]), + y: parseFloat(points[i + 1]) + }); + } + } + + // odd number of points is an error + // if (parsedPoints.length % 2 !== 0) { + // return null; + // } + + return parsedPoints; + }, + + /** + * Returns CSS rules for a given SVG document + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @return {Object} CSS rules of this document + */ + getCSSRules: function(doc) { + var styles = doc.getElementsByTagName('style'), + allRules = { }, + rules; + + // very crude parsing of style contents + for (var i = 0, len = styles.length; i < len; i++) { + var styleContents = styles[0].textContent; + + // remove comments + styleContents = styleContents.replace(/\/\*[\s\S]*?\*\//g, ''); + + rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g); + rules = rules.map(function(rule) { return rule.trim(); }); + + rules.forEach(function(rule) { + var match = rule.match(/([\s\S]*?)\s*\{([^}]*)\}/); + rule = match[1]; + var declaration = match[2].trim(), + propertyValuePairs = declaration.replace(/;$/, '').split(/\s*;\s*/); + + if (!allRules[rule]) { + allRules[rule] = { }; + } + + for (var i = 0, len = propertyValuePairs.length; i < len; i++) { + var pair = propertyValuePairs[i].split(/\s*:\s*/), + property = pair[0], + value = pair[1]; + + allRules[rule][property] = value; + } + }); + } + + return allRules; + }, + + /** + * Takes url corresponding to an SVG document, and parses it into a set of fabric objects. Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy) + * @memberof fabric + * @param {String} url + * @param {Function} callback + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + loadSVGFromURL: function(url, callback, reviver) { + + url = url.replace(/^\n\s*/, '').trim(); + svgCache.has(url, function (hasUrl) { + if (hasUrl) { + svgCache.get(url, function (value) { + var enlivedRecord = _enlivenCachedObject(value); + callback(enlivedRecord.objects, enlivedRecord.options); + }); + } + else { + new fabric.util.request(url, { + method: 'get', + onComplete: onComplete + }); + } + }); + + function onComplete(r) { + + var xml = r.responseXML; + if (xml && !xml.documentElement && fabric.window.ActiveXObject && r.responseText) { + xml = new ActiveXObject('Microsoft.XMLDOM'); + xml.async = 'false'; + //IE chokes on DOCTYPE + xml.loadXML(r.responseText.replace(//i,'')); + } + if (!xml || !xml.documentElement) return; + + fabric.parseSVGDocument(xml.documentElement, function (results, options) { + svgCache.set(url, { + objects: fabric.util.array.invoke(results, 'toObject'), + options: options + }); + callback(results, options); + }, reviver); + } + }, + + /** + * Takes string corresponding to an SVG document, and parses it into a set of fabric objects + * @memberof fabric + * @param {String} string + * @param {Function} callback + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + loadSVGFromString: function(string, callback, reviver) { + string = string.trim(); + var doc; + if (typeof DOMParser !== 'undefined') { + var parser = new DOMParser(); + if (parser && parser.parseFromString) { + doc = parser.parseFromString(string, 'text/xml'); + } + } + else if (fabric.window.ActiveXObject) { + doc = new ActiveXObject('Microsoft.XMLDOM'); + doc.async = 'false'; + //IE chokes on DOCTYPE + doc.loadXML(string.replace(//i,'')); + } + + fabric.parseSVGDocument(doc.documentElement, function (results, options) { + callback(results, options); + }, reviver); + }, + + /** + * Creates markup containing SVG font faces + * @param {Array} objects Array of fabric objects + * @return {String} + */ + createSVGFontFacesMarkup: function(objects) { + var markup = ''; + + for (var i = 0, len = objects.length; i < len; i++) { + if (objects[i].type !== 'text' || !objects[i].path) continue; + + markup += [ + '@font-face {', + 'font-family: ', objects[i].fontFamily, '; ', + 'src: url(\'', objects[i].path, '\')', + '}' + ].join(''); + } + + if (markup) { + markup = [ + '' + ].join(''); + } + + return markup; + }, + + /** + * Creates markup containing SVG referenced elements like patterns, gradients etc. + * @param {fabric.Canvas} canvas instance of fabric.Canvas + * @return {String} + */ + createSVGRefElementsMarkup: function(canvas) { + var markup = [ ]; + + _createSVGPattern(markup, canvas, 'backgroundColor'); + _createSVGPattern(markup, canvas, 'overlayColor'); + + return markup.join(''); + } + }); + +})(typeof exports !== 'undefined' ? exports : this); + + +fabric.ElementsParser = function(elements, callback, options, reviver) { + this.elements = elements; + this.callback = callback; + this.options = options; + this.reviver = reviver; +}; + +fabric.ElementsParser.prototype.parse = function() { + this.instances = new Array(this.elements.length); + this.numElements = this.elements.length; + + this.createObjects(); +}; + +fabric.ElementsParser.prototype.createObjects = function() { + for (var i = 0, len = this.elements.length; i < len; i++) { + (function(_this, i) { + setTimeout(function() { + _this.createObject(_this.elements[i], i); + }, 0); + })(this, i); + } +}; + +fabric.ElementsParser.prototype.createObject = function(el, index) { + var klass = fabric[fabric.util.string.capitalize(el.tagName)]; + if (klass && klass.fromElement) { + try { + this._createObject(klass, el, index); + } + catch (err) { + fabric.log(err); + } + } + else { + this.checkIfDone(); + } +}; + +fabric.ElementsParser.prototype._createObject = function(klass, el, index) { + if (klass.async) { + klass.fromElement(el, this.createCallback(index, el), this.options); + } + else { + var obj = klass.fromElement(el, this.options); + this.reviver && this.reviver(el, obj); + this.instances.splice(index, 0, obj); + this.checkIfDone(); + } +}; + +fabric.ElementsParser.prototype.createCallback = function(index, el) { + var _this = this; + return function(obj) { + _this.reviver && _this.reviver(el, obj); + _this.instances.splice(index, 0, obj); + _this.checkIfDone(); + }; +}; + +fabric.ElementsParser.prototype.checkIfDone = function() { + if (--this.numElements === 0) { + this.instances = this.instances.filter(function(el) { + return el != null; + }); + fabric.resolveGradients(this.instances); + this.callback(this.instances); + } +}; + + +(function(global) { + + 'use strict'; + + /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Point) { + fabric.warn('fabric.Point is already defined'); + return; + } + + fabric.Point = Point; + + /** + * Point class + * @class fabric.Point + * @memberOf fabric + * @constructor + * @param {Number} x + * @param {Number} y + * @return {fabric.Point} thisArg + */ + function Point(x, y) { + this.x = x; + this.y = y; + } + + Point.prototype = /** @lends fabric.Point.prototype */ { + + constructor: Point, + + /** + * Adds another point to this one and returns another one + * @param {fabric.Point} that + * @return {fabric.Point} new Point instance with added values + */ + add: function (that) { + return new Point(this.x + that.x, this.y + that.y); + }, + + /** + * Adds another point to this one + * @param {fabric.Point} that + * @return {fabric.Point} thisArg + */ + addEquals: function (that) { + this.x += that.x; + this.y += that.y; + return this; + }, + + /** + * Adds value to this point and returns a new one + * @param {Number} scalar + * @return {fabric.Point} new Point with added value + */ + scalarAdd: function (scalar) { + return new Point(this.x + scalar, this.y + scalar); + }, + + /** + * Adds value to this point + * @param {Number} scalar + * @param {fabric.Point} thisArg + */ + scalarAddEquals: function (scalar) { + this.x += scalar; + this.y += scalar; + return this; + }, + + /** + * Subtracts another point from this point and returns a new one + * @param {fabric.Point} that + * @return {fabric.Point} new Point object with subtracted values + */ + subtract: function (that) { + return new Point(this.x - that.x, this.y - that.y); + }, + + /** + * Subtracts another point from this point + * @param {fabric.Point} that + * @return {fabric.Point} thisArg + */ + subtractEquals: function (that) { + this.x -= that.x; + this.y -= that.y; + return this; + }, + + /** + * Subtracts value from this point and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + scalarSubtract: function (scalar) { + return new Point(this.x - scalar, this.y - scalar); + }, + + /** + * Subtracts value from this point + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + scalarSubtractEquals: function (scalar) { + this.x -= scalar; + this.y -= scalar; + return this; + }, + + /** + * Miltiplies this point by a value and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + multiply: function (scalar) { + return new Point(this.x * scalar, this.y * scalar); + }, + + /** + * Miltiplies this point by a value + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + multiplyEquals: function (scalar) { + this.x *= scalar; + this.y *= scalar; + return this; + }, + + /** + * Divides this point by a value and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + divide: function (scalar) { + return new Point(this.x / scalar, this.y / scalar); + }, + + /** + * Divides this point by a value + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + divideEquals: function (scalar) { + this.x /= scalar; + this.y /= scalar; + return this; + }, + + /** + * Returns true if this point is equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + eq: function (that) { + return (this.x === that.x && this.y === that.y); + }, + + /** + * Returns true if this point is less than another one + * @param {fabric.Point} that + * @return {Boolean} + */ + lt: function (that) { + return (this.x < that.x && this.y < that.y); + }, + + /** + * Returns true if this point is less than or equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + lte: function (that) { + return (this.x <= that.x && this.y <= that.y); + }, + + /** + + * Returns true if this point is greater another one + * @param {fabric.Point} that + * @return {Boolean} + */ + gt: function (that) { + return (this.x > that.x && this.y > that.y); + }, + + /** + * Returns true if this point is greater than or equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + gte: function (that) { + return (this.x >= that.x && this.y >= that.y); + }, + + /** + * Returns new point which is the result of linear interpolation with this one and another one + * @param {fabric.Point} that + * @param {Number} t + * @return {fabric.Point} + */ + lerp: function (that, t) { + return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t); + }, + + /** + * Returns distance from this point and another one + * @param {fabric.Point} that + * @return {Number} + */ + distanceFrom: function (that) { + var dx = this.x - that.x, + dy = this.y - that.y; + return Math.sqrt(dx * dx + dy * dy); + }, + + /** + * Returns the point between this point and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + midPointFrom: function (that) { + return new Point(this.x + (that.x - this.x)/2, this.y + (that.y - this.y)/2); + }, + + /** + * Returns a new point which is the min of this and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + min: function (that) { + return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y)); + }, + + /** + * Returns a new point which is the max of this and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + max: function (that) { + return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y)); + }, + + /** + * Returns string representation of this point + * @return {String} + */ + toString: function () { + return this.x + ',' + this.y; + }, + + /** + * Sets x/y of this point + * @param {Number} x + * @return {Number} y + */ + setXY: function (x, y) { + this.x = x; + this.y = y; + }, + + /** + * Sets x/y of this point from another point + * @param {fabric.Point} that + */ + setFromPoint: function (that) { + this.x = that.x; + this.y = that.y; + }, + + /** + * Swaps x/y of this point and another point + * @param {fabric.Point} that + */ + swap: function (that) { + var x = this.x, + y = this.y; + this.x = that.x; + this.y = that.y; + that.x = x; + that.y = y; + } + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Intersection) { + fabric.warn('fabric.Intersection is already defined'); + return; + } + + /** + * Intersection class + * @class fabric.Intersection + * @memberOf fabric + * @constructor + */ + function Intersection(status) { + this.status = status; + this.points = []; + } + + fabric.Intersection = Intersection; + + fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ { + + /** + * Appends a point to intersection + * @param {fabric.Point} point + */ + appendPoint: function (point) { + this.points.push(point); + }, + + /** + * Appends points to intersection + * @param {Array} points + */ + appendPoints: function (points) { + this.points = this.points.concat(points); + } + }; + + /** + * Checks if one line intersects another + * @static + * @param {fabric.Point} a1 + * @param {fabric.Point} a2 + * @param {fabric.Point} b1 + * @param {fabric.Point} b2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) { + var result, + uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), + ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), + uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); + if (uB !== 0) { + var ua = uaT / uB, + ub = ubT / uB; + if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { + result = new Intersection('Intersection'); + result.points.push(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); + } + else { + result = new Intersection(); + } + } + else { + if (uaT === 0 || ubT === 0) { + result = new Intersection('Coincident'); + } + else { + result = new Intersection('Parallel'); + } + } + return result; + }; + + /** + * Checks if line intersects polygon + * @static + * @param {fabric.Point} a1 + * @param {fabric.Point} a2 + * @param {Array} points + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectLinePolygon = function(a1,a2,points){ + var result = new Intersection(), + length = points.length; + + for (var i = 0; i < length; i++) { + var b1 = points[i], + b2 = points[(i + 1) % length], + inter = Intersection.intersectLineLine(a1, a2, b1, b2); + + result.appendPoints(inter.points); + } + if (result.points.length > 0) { + result.status = 'Intersection'; + } + return result; + }; + + /** + * Checks if polygon intersects another polygon + * @static + * @param {Array} points1 + * @param {Array} points2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectPolygonPolygon = function (points1, points2) { + var result = new Intersection(), + length = points1.length; + + for (var i = 0; i < length; i++) { + var a1 = points1[i], + a2 = points1[(i + 1) % length], + inter = Intersection.intersectLinePolygon(a1, a2, points2); + + result.appendPoints(inter.points); + } + if (result.points.length > 0) { + result.status = 'Intersection'; + } + return result; + }; + + /** + * Checks if polygon intersects rectangle + * @static + * @param {Array} points + * @param {Number} r1 + * @param {Number} r2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) { + var min = r1.min(r2), + max = r1.max(r2), + topRight = new fabric.Point(max.x, min.y), + bottomLeft = new fabric.Point(min.x, max.y), + inter1 = Intersection.intersectLinePolygon(min, topRight, points), + inter2 = Intersection.intersectLinePolygon(topRight, max, points), + inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points), + inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points), + result = new Intersection(); + + result.appendPoints(inter1.points); + result.appendPoints(inter2.points); + result.appendPoints(inter3.points); + result.appendPoints(inter4.points); + + if (result.points.length > 0) { + result.status = 'Intersection'; + } + return result; + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Color) { + fabric.warn('fabric.Color is already defined.'); + return; + } + + /** + * Color class + * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations; + * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects. + * + * @class fabric.Color + * @param {String} color optional in hex or rgb(a) format + * @return {fabric.Color} thisArg + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors} + */ + function Color(color) { + if (!color) { + this.setSource([0, 0, 0, 1]); + } + else { + this._tryParsingColor(color); + } + } + + fabric.Color = Color; + + fabric.Color.prototype = /** @lends fabric.Color.prototype */ { + + /** + * @private + * @param {String|Array} color Color value to parse + */ + _tryParsingColor: function(color) { + var source; + + if (color in Color.colorNameMap) { + color = Color.colorNameMap[color]; + } + + if (color === 'transparent') { + this.setSource([255,255,255,0]); + return; + } + + source = Color.sourceFromHex(color); + + if (!source) { + source = Color.sourceFromRgb(color); + } + if (!source) { + source = Color.sourceFromHsl(color); + } + if (source) { + this.setSource(source); + } + }, + + /** + * Adapted from https://github.com/mjijackson + * @private + * @param {Number} r Red color value + * @param {Number} g Green color value + * @param {Number} b Blue color value + * @return {Array} Hsl color + */ + _rgbToHsl: function(r, g, b) { + r /= 255, g /= 255, b /= 255; + + var h, s, l, + max = fabric.util.array.max([r, g, b]), + min = fabric.util.array.min([r, g, b]); + + l = (max + min) / 2; + + if (max === min) { + h = s = 0; // achromatic + } + else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + + return [ + Math.round(h * 360), + Math.round(s * 100), + Math.round(l * 100) + ]; + }, + + /** + * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1]) + * @return {Array} + */ + getSource: function() { + return this._source; + }, + + /** + * Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1]) + * @param {Array} source + */ + setSource: function(source) { + this._source = source; + }, + + /** + * Returns color represenation in RGB format + * @return {String} ex: rgb(0-255,0-255,0-255) + */ + toRgb: function() { + var source = this.getSource(); + return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')'; + }, + + /** + * Returns color represenation in RGBA format + * @return {String} ex: rgba(0-255,0-255,0-255,0-1) + */ + toRgba: function() { + var source = this.getSource(); + return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')'; + }, + + /** + * Returns color represenation in HSL format + * @return {String} ex: hsl(0-360,0%-100%,0%-100%) + */ + toHsl: function() { + var source = this.getSource(), + hsl = this._rgbToHsl(source[0], source[1], source[2]); + + return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)'; + }, + + /** + * Returns color represenation in HSLA format + * @return {String} ex: hsla(0-360,0%-100%,0%-100%,0-1) + */ + toHsla: function() { + var source = this.getSource(), + hsl = this._rgbToHsl(source[0], source[1], source[2]); + + return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')'; + }, + + /** + * Returns color represenation in HEX format + * @return {String} ex: FF5555 + */ + toHex: function() { + var source = this.getSource(), r, g, b; + + r = source[0].toString(16); + r = (r.length === 1) ? ('0' + r) : r; + + g = source[1].toString(16); + g = (g.length === 1) ? ('0' + g) : g; + + b = source[2].toString(16); + b = (b.length === 1) ? ('0' + b) : b; + + return r.toUpperCase() + g.toUpperCase() + b.toUpperCase(); + }, + + /** + * Gets value of alpha channel for this color + * @return {Number} 0-1 + */ + getAlpha: function() { + return this.getSource()[3]; + }, + + /** + * Sets value of alpha channel for this color + * @param {Number} alpha Alpha value 0-1 + * @return {fabric.Color} thisArg + */ + setAlpha: function(alpha) { + var source = this.getSource(); + source[3] = alpha; + this.setSource(source); + return this; + }, + + /** + * Transforms color to its grayscale representation + * @return {fabric.Color} thisArg + */ + toGrayscale: function() { + var source = this.getSource(), + average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10), + currentAlpha = source[3]; + this.setSource([average, average, average, currentAlpha]); + return this; + }, + + /** + * Transforms color to its black and white representation + * @param {Number} threshold + * @return {fabric.Color} thisArg + */ + toBlackWhite: function(threshold) { + var source = this.getSource(), + average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), + currentAlpha = source[3]; + + threshold = threshold || 127; + + average = (Number(average) < Number(threshold)) ? 0 : 255; + this.setSource([average, average, average, currentAlpha]); + return this; + }, + + /** + * Overlays color with another color + * @param {String|fabric.Color} otherColor + * @return {fabric.Color} thisArg + */ + overlayWith: function(otherColor) { + if (!(otherColor instanceof Color)) { + otherColor = new Color(otherColor); + } + + var result = [], + alpha = this.getAlpha(), + otherAlpha = 0.5, + source = this.getSource(), + otherSource = otherColor.getSource(); + + for (var i = 0; i < 3; i++) { + result.push(Math.round((source[i] * (1 - otherAlpha)) + (otherSource[i] * otherAlpha))); + } + + result[3] = alpha; + this.setSource(result); + return this; + } + }; + + /** + * Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5)) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reRGBa = /^rgba?\(\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; + + /** + * Regex matching color in HSL or HSLA formats (ex: hsl(200, 80%, 10%), hsla(300, 50%, 80%, 0.5), hsla( 300 , 50% , 80% , 0.5 )) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; + + /** + * Regex matching color in HEX format (ex: #FF5555, 010155, aff) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reHex = /^#?([0-9a-f]{6}|[0-9a-f]{3})$/i; + + /** + * Map of the 17 basic color names with HEX code + * @static + * @field + * @memberOf fabric.Color + * @see: http://www.w3.org/TR/CSS2/syndata.html#color-units + */ + fabric.Color.colorNameMap = { + aqua: '#00FFFF', + black: '#000000', + blue: '#0000FF', + fuchsia: '#FF00FF', + gray: '#808080', + green: '#008000', + lime: '#00FF00', + maroon: '#800000', + navy: '#000080', + olive: '#808000', + orange: '#FFA500', + purple: '#800080', + red: '#FF0000', + silver: '#C0C0C0', + teal: '#008080', + white: '#FFFFFF', + yellow: '#FFFF00' + }; + + /** + * @private + * @param {Number} p + * @param {Number} q + * @param {Number} t + * @return {Number} + */ + function hue2rgb(p, q, t){ + if (t < 0) { + t += 1; + } + if (t > 1) { + t -= 1; + } + if (t < 1/6) { + return p + (q - p) * 6 * t; + } + if (t < 1/2) { + return q; + } + if (t < 2/3) { + return p + (q - p) * (2/3 - t) * 6; + } + return p; + } + + /** + * Returns new color object, when given a color in RGB format + * @memberOf fabric.Color + * @param {String} color Color value ex: rgb(0-255,0-255,0-255) + * @return {fabric.Color} + */ + fabric.Color.fromRgb = function(color) { + return Color.fromSource(Color.sourceFromRgb(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format + * @memberOf fabric.Color + * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%) + * @return {Array} source + */ + fabric.Color.sourceFromRgb = function(color) { + var match = color.match(Color.reRGBa); + if (match) { + var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1), + g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1), + b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1); + + return [ + parseInt(r, 10), + parseInt(g, 10), + parseInt(b, 10), + match[4] ? parseFloat(match[4]) : 1 + ]; + } + }; + + /** + * Returns new color object, when given a color in RGBA format + * @static + * @function + * @memberOf fabric.Color + * @param {String} color + * @return {fabric.Color} + */ + fabric.Color.fromRgba = Color.fromRgb; + + /** + * Returns new color object, when given a color in HSL format + * @param {String} color Color value ex: hsl(0-260,0%-100%,0%-100%) + * @memberOf fabric.Color + * @return {fabric.Color} + */ + fabric.Color.fromHsl = function(color) { + return Color.fromSource(Color.sourceFromHsl(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format. + * Adapted from https://github.com/mjijackson + * @memberOf fabric.Color + * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1) + * @return {Array} source + * @see http://http://www.w3.org/TR/css3-color/#hsl-color + */ + fabric.Color.sourceFromHsl = function(color) { + var match = color.match(Color.reHSLa); + if (!match) return; + + var h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360, + s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1), + l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1), + r, g, b; + + if (s === 0) { + r = g = b = l; + } + else { + var q = l <= 0.5 ? l * (s + 1) : l + s - l * s, + p = l * 2 - q; + + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return [ + Math.round(r * 255), + Math.round(g * 255), + Math.round(b * 255), + match[4] ? parseFloat(match[4]) : 1 + ]; + }; + + /** + * Returns new color object, when given a color in HSLA format + * @static + * @function + * @memberOf fabric.Color + * @param {String} color + * @return {fabric.Color} + */ + fabric.Color.fromHsla = Color.fromHsl; + + /** + * Returns new color object, when given a color in HEX format + * @static + * @memberOf fabric.Color + * @param {String} color Color value ex: FF5555 + * @return {fabric.Color} + */ + fabric.Color.fromHex = function(color) { + return Color.fromSource(Color.sourceFromHex(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HEX format + * @static + * @memberOf fabric.Color + * @param {String} color ex: FF5555 + * @return {Array} source + */ + fabric.Color.sourceFromHex = function(color) { + if (color.match(Color.reHex)) { + var value = color.slice(color.indexOf('#') + 1), + isShortNotation = (value.length === 3), + r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2), + g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4), + b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6); + + return [ + parseInt(r, 16), + parseInt(g, 16), + parseInt(b, 16), + 1 + ]; + } + }; + + /** + * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5]) + * @static + * @memberOf fabric.Color + * @param {Array} source + * @return {fabric.Color} + */ + fabric.Color.fromSource = function(source) { + var oColor = new Color(); + oColor.setSource(source); + return oColor; + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + /* _FROM_SVG_START_ */ + function getColorStop(el) { + var style = el.getAttribute('style'), + offset = el.getAttribute('offset'), + color, opacity; + + // convert percents to absolute values + offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1); + + if (style) { + var keyValuePairs = style.split(/\s*;\s*/); + + if (keyValuePairs[keyValuePairs.length - 1] === '') { + keyValuePairs.pop(); + } + + for (var i = keyValuePairs.length; i--; ) { + + var split = keyValuePairs[i].split(/\s*:\s*/), + key = split[0].trim(), + value = split[1].trim(); + + if (key === 'stop-color') { + color = value; + } + else if (key === 'stop-opacity') { + opacity = value; + } + } + } + + if (!color) { + color = el.getAttribute('stop-color') || 'rgb(0,0,0)'; + } + if (!opacity) { + opacity = el.getAttribute('stop-opacity'); + } + + // convert rgba color to rgb color - alpha value has no affect in svg + color = new fabric.Color(color).toRgb(); + + return { + offset: offset, + color: color, + opacity: isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity) + }; + } + + function getLinearCoords(el) { + return { + x1: el.getAttribute('x1') || 0, + y1: el.getAttribute('y1') || 0, + x2: el.getAttribute('x2') || '100%', + y2: el.getAttribute('y2') || 0 + }; + } + + function getRadialCoords(el) { + return { + x1: el.getAttribute('fx') || el.getAttribute('cx') || '50%', + y1: el.getAttribute('fy') || el.getAttribute('cy') || '50%', + r1: 0, + x2: el.getAttribute('cx') || '50%', + y2: el.getAttribute('cy') || '50%', + r2: el.getAttribute('r') || '50%' + }; + } + /* _FROM_SVG_END_ */ + + /** + * Gradient class + * @class fabric.Gradient + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#gradients} + * @see {@link fabric.Gradient#initialize} for constructor definition + */ + fabric.Gradient = fabric.util.createClass(/** @lends fabric.Gradient.prototype */ { + + /** + * Constructor + * @param {Object} [options] Options object with type, coords, gradientUnits and colorStops + * @return {fabric.Gradient} thisArg + */ + initialize: function(options) { + options || (options = { }); + + var coords = { }; + + this.id = fabric.Object.__uid++; + this.type = options.type || 'linear'; + + coords = { + x1: options.coords.x1 || 0, + y1: options.coords.y1 || 0, + x2: options.coords.x2 || 0, + y2: options.coords.y2 || 0 + }; + + if (this.type === 'radial') { + coords.r1 = options.coords.r1 || 0; + coords.r2 = options.coords.r2 || 0; + } + + this.coords = coords; + this.gradientUnits = options.gradientUnits || 'objectBoundingBox'; + this.colorStops = options.colorStops.slice(); + }, + + /** + * Adds another colorStop + * @param {Object} colorStop Object with offset and color + * @return {fabric.Gradient} thisArg + */ + addColorStop: function(colorStop) { + for (var position in colorStop) { + var color = new fabric.Color(colorStop[position]); + this.colorStops.push({ + offset: position, + color: color.toRgb(), + opacity: color.getAlpha() + }); + } + return this; + }, + + /** + * Returns object representation of a gradient + * @return {Object} + */ + toObject: function() { + return { + type: this.type, + coords: this.coords, + gradientUnits: this.gradientUnits, + colorStops: this.colorStops + }; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an gradient + * @param {Object} object Object to create a gradient for + * @param {Boolean} normalize Whether coords should be normalized + * @return {String} SVG representation of an gradient (linear/radial) + */ + toSVG: function(object, normalize) { + var coords = fabric.util.object.clone(this.coords), + markup; + + // colorStops must be sorted ascending + this.colorStops.sort(function(a, b) { + return a.offset - b.offset; + }); + + if (normalize && this.gradientUnits === 'userSpaceOnUse') { + coords.x1 += object.width / 2; + coords.y1 += object.height / 2; + coords.x2 += object.width / 2; + coords.y2 += object.height / 2; + } + else if (this.gradientUnits === 'objectBoundingBox') { + _convertValuesToPercentUnits(object, coords); + } + + if (this.type === 'linear') { + markup = [ + '' + ]; + } + else if (this.type === 'radial') { + markup = [ + '' + ]; + } + + for (var i = 0; i < this.colorStops.length; i++) { + markup.push( + '' + ); + } + + markup.push((this.type === 'linear' ? '' : '')); + + return markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns an instance of CanvasGradient + * @param {CanvasRenderingContext2D} ctx Context to render on + * @return {CanvasGradient} + */ + toLive: function(ctx) { + var gradient; + + if (!this.type) return; + + if (this.type === 'linear') { + gradient = ctx.createLinearGradient( + this.coords.x1, this.coords.y1, this.coords.x2, this.coords.y2); + } + else if (this.type === 'radial') { + gradient = ctx.createRadialGradient( + this.coords.x1, this.coords.y1, this.coords.r1, this.coords.x2, this.coords.y2, this.coords.r2); + } + + for (var i = 0, len = this.colorStops.length; i < len; i++) { + var color = this.colorStops[i].color, + opacity = this.colorStops[i].opacity, + offset = this.colorStops[i].offset; + + if (typeof opacity !== 'undefined') { + color = new fabric.Color(color).setAlpha(opacity).toRgba(); + } + gradient.addColorStop(parseFloat(offset), color); + } + + return gradient; + } + }); + + fabric.util.object.extend(fabric.Gradient, { + + /* _FROM_SVG_START_ */ + /** + * Returns {@link fabric.Gradient} instance from an SVG element + * @static + * @memberof fabric.Gradient + * @param {SVGGradientElement} el SVG gradient element + * @param {fabric.Object} instance + * @return {fabric.Gradient} Gradient instance + * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement + * @see http://www.w3.org/TR/SVG/pservers.html#RadialGradientElement + */ + fromElement: function(el, instance) { + + /** + * @example: + * + * + * + * + * + * + * OR + * + * + * + * + * + * + * OR + * + * + * + * + * + * + * + * OR + * + * + * + * + * + * + * + */ + + var colorStopEls = el.getElementsByTagName('stop'), + type = (el.nodeName === 'linearGradient' ? 'linear' : 'radial'), + gradientUnits = el.getAttribute('gradientUnits') || 'objectBoundingBox', + colorStops = [], + coords = { }; + + if (type === 'linear') { + coords = getLinearCoords(el); + } + else if (type === 'radial') { + coords = getRadialCoords(el); + } + + for (var i = colorStopEls.length; i--; ) { + colorStops.push(getColorStop(colorStopEls[i])); + } + + _convertPercentUnitsToValues(instance, coords); + + return new fabric.Gradient({ + type: type, + coords: coords, + gradientUnits: gradientUnits, + colorStops: colorStops + }); + }, + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Gradient} instance from its object representation + * @static + * @memberof fabric.Gradient + * @param {Object} obj + * @param {Object} [options] Options object + */ + forObject: function(obj, options) { + options || (options = { }); + _convertPercentUnitsToValues(obj, options); + return new fabric.Gradient(options); + } + }); + + /** + * @private + */ + function _convertPercentUnitsToValues(object, options) { + for (var prop in options) { + if (typeof options[prop] === 'string' && /^\d+%$/.test(options[prop])) { + var percents = parseFloat(options[prop], 10); + if (prop === 'x1' || prop === 'x2' || prop === 'r2') { + options[prop] = fabric.util.toFixed(object.width * percents / 100, 2); + } + else if (prop === 'y1' || prop === 'y2') { + options[prop] = fabric.util.toFixed(object.height * percents / 100, 2); + } + } + normalize(options, prop, object); + } + } + + // normalize rendering point (should be from top/left corner rather than center of the shape) + function normalize(options, prop, object) { + if (prop === 'x1' || prop === 'x2') { + options[prop] -= fabric.util.toFixed(object.width / 2, 2); + } + else if (prop === 'y1' || prop === 'y2') { + options[prop] -= fabric.util.toFixed(object.height / 2, 2); + } + } + + /* _TO_SVG_START_ */ + /** + * @private + */ + function _convertValuesToPercentUnits(object, options) { + for (var prop in options) { + + normalize(options, prop, object); + + // convert to percent units + if (prop === 'x1' || prop === 'x2' || prop === 'r2') { + options[prop] = fabric.util.toFixed(options[prop] / object.width * 100, 2) + '%'; + } + else if (prop === 'y1' || prop === 'y2') { + options[prop] = fabric.util.toFixed(options[prop] / object.height * 100, 2) + '%'; + } + } + } + /* _TO_SVG_END_ */ + +})(); + + +/** + * Pattern class + * @class fabric.Pattern + * @see {@link http://fabricjs.com/patterns/|Pattern demo} + * @see {@link http://fabricjs.com/dynamic-patterns/|DynamicPattern demo} + * @see {@link fabric.Pattern#initialize} for constructor definition + */ +fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ { + + /** + * Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat) + * @type String + * @default + */ + repeat: 'repeat', + + /** + * Pattern horizontal offset from object's left/top corner + * @type Number + * @default + */ + offsetX: 0, + + /** + * Pattern vertical offset from object's left/top corner + * @type Number + * @default + */ + offsetY: 0, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Pattern} thisArg + */ + initialize: function(options) { + options || (options = { }); + + this.id = fabric.Object.__uid++; + + if (options.source) { + if (typeof options.source === 'string') { + // function string + if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') { + this.source = new Function(fabric.util.getFunctionBody(options.source)); + } + else { + // img src string + var _this = this; + this.source = fabric.util.createImage(); + fabric.util.loadImage(options.source, function(img) { + _this.source = img; + }); + } + } + else { + // img element + this.source = options.source; + } + } + if (options.repeat) { + this.repeat = options.repeat; + } + if (options.offsetX) { + this.offsetX = options.offsetX; + } + if (options.offsetY) { + this.offsetY = options.offsetY; + } + }, + + /** + * Returns object representation of a pattern + * @return {Object} Object representation of a pattern instance + */ + toObject: function() { + + var source; + + // callback + if (typeof this.source === 'function') { + source = String(this.source); + } + // element + else if (typeof this.source.src === 'string') { + source = this.source.src; + } + + return { + source: source, + repeat: this.repeat, + offsetX: this.offsetX, + offsetY: this.offsetY + }; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of a pattern + * @param {fabric.Object} object + * @return {String} SVG representation of a pattern + */ + toSVG: function(object) { + var patternSource = typeof this.source === 'function' ? this.source() : this.source, + patternWidth = patternSource.width / object.getWidth(), + patternHeight = patternSource.height / object.getHeight(), + patternImgSrc = ''; + + if (patternSource.src) { + patternImgSrc = patternSource.src; + } + else if (patternSource.toDataURL) { + patternImgSrc = patternSource.toDataURL(); + } + + return '' + + '' + + ''; + }, + /* _TO_SVG_END_ */ + + /** + * Returns an instance of CanvasPattern + * @param {CanvasRenderingContext2D} ctx Context to create pattern + * @return {CanvasPattern} + */ + toLive: function(ctx) { + var source = typeof this.source === 'function' + ? this.source() + : this.source; + + // if the image failed to load, return, and allow rest to continue loading + if (!source) { + return ''; + } + + // if an image + if (typeof source.src !== 'undefined') { + if (!source.complete) { + return ''; + } + if (source.naturalWidth === 0 || source.naturalHeight === 0) { + return ''; + } + } + return ctx.createPattern(source, this.repeat); + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Shadow) { + fabric.warn('fabric.Shadow is already defined.'); + return; + } + + /** + * Shadow class + * @class fabric.Shadow + * @see {@link http://fabricjs.com/shadows/|Shadow demo} + * @see {@link fabric.Shadow#initialize} for constructor definition + */ + fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ { + + /** + * Shadow color + * @type String + * @default + */ + color: 'rgb(0,0,0)', + + /** + * Shadow blur + * @type Number + */ + blur: 0, + + /** + * Shadow horizontal offset + * @type Number + * @default + */ + offsetX: 0, + + /** + * Shadow vertical offset + * @type Number + * @default + */ + offsetY: 0, + + /** + * Whether the shadow should affect stroke operations + * @type Boolean + * @default + */ + affectStroke: false, + + /** + * Indicates whether toObject should include default values + * @type Boolean + * @default + */ + includeDefaultValues: true, + + /** + * Constructor + * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetX properties or string (e.g. "rgba(0,0,0,0.2) 2px 2px 10px, "2px 2px 10px rgba(0,0,0,0.2)") + * @return {fabric.Shadow} thisArg + */ + initialize: function(options) { + + if (typeof options === 'string') { + options = this._parseShadow(options); + } + + for (var prop in options) { + this[prop] = options[prop]; + } + + this.id = fabric.Object.__uid++; + }, + + /** + * @private + * @param {String} shadow Shadow value to parse + * @return {Object} Shadow object with color, offsetX, offsetY and blur + */ + _parseShadow: function(shadow) { + var shadowStr = shadow.trim(), + offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [ ], + color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, '') || 'rgb(0,0,0)'; + + return { + color: color.trim(), + offsetX: parseInt(offsetsAndBlur[1], 10) || 0, + offsetY: parseInt(offsetsAndBlur[2], 10) || 0, + blur: parseInt(offsetsAndBlur[3], 10) || 0 + }; + }, + + /** + * Returns a string representation of an instance + * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow + * @return {String} Returns CSS3 text-shadow declaration + */ + toString: function() { + return [this.offsetX, this.offsetY, this.blur, this.color].join('px '); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of a shadow + * @param {fabric.Object} object + * @return {String} SVG representation of a shadow + */ + toSVG: function(object) { + var mode = 'SourceAlpha'; + + if (object && (object.fill === this.color || object.stroke === this.color)) { + mode = 'SourceGraphic'; + } + + return ( + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns object representation of a shadow + * @return {Object} Object representation of a shadow instance + */ + toObject: function() { + if (this.includeDefaultValues) { + return { + color: this.color, + blur: this.blur, + offsetX: this.offsetX, + offsetY: this.offsetY + }; + } + var obj = { }, proto = fabric.Shadow.prototype; + if (this.color !== proto.color) { + obj.color = this.color; + } + if (this.blur !== proto.blur) { + obj.blur = this.blur; + } + if (this.offsetX !== proto.offsetX) { + obj.offsetX = this.offsetX; + } + if (this.offsetY !== proto.offsetY) { + obj.offsetY = this.offsetY; + } + return obj; + } + }); + + /** + * Regex matching shadow offsetX, offsetY and blur (ex: "2px 2px 10px rgba(0,0,0,0.2)", "rgb(0,255,0) 2px 2px") + * @static + * @field + * @memberOf fabric.Shadow + */ + fabric.Shadow.reOffsetsAndBlur = /(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function () { + + 'use strict'; + + if (fabric.StaticCanvas) { + fabric.warn('fabric.StaticCanvas is already defined.'); + return; + } + + // aliases for faster resolution + var extend = fabric.util.object.extend, + getElementOffset = fabric.util.getElementOffset, + removeFromArray = fabric.util.removeFromArray, + + CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element'); + + /** + * Static canvas class + * @class fabric.StaticCanvas + * @mixes fabric.Collection + * @mixes fabric.Observable + * @see {@link http://fabricjs.com/static_canvas/|StaticCanvas demo} + * @see {@link fabric.StaticCanvas#initialize} for constructor definition + * @fires before:render + * @fires after:render + * @fires canvas:cleared + * @fires object:added + * @fires object:removed + */ + fabric.StaticCanvas = fabric.util.createClass(/** @lends fabric.StaticCanvas.prototype */ { + + /** + * Constructor + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(el, options) { + options || (options = { }); + + this._initStatic(el, options); + fabric.StaticCanvas.activeInstance = this; + }, + + /** + * Background color of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setBackgroundColor}. + * @type {(String|fabric.Pattern)} + * @default + */ + backgroundColor: '', + + /** + * Background image of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setBackgroundImage}. + * Backwards incompatibility note: The "backgroundImageOpacity" + * and "backgroundImageStretch" properties are deprecated since 1.3.9. + * Use {@link fabric.Image#opacity}, {@link fabric.Image#width} and {@link fabric.Image#height}. + * @type fabric.Image + * @default + */ + backgroundImage: null, + + /** + * Overlay color of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setOverlayColor} + * @since 1.3.9 + * @type {(String|fabric.Pattern)} + * @default + */ + overlayColor: '', + + /** + * Overlay image of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setOverlayImage}. + * Backwards incompatibility note: The "overlayImageLeft" + * and "overlayImageTop" properties are deprecated since 1.3.9. + * Use {@link fabric.Image#left} and {@link fabric.Image#top}. + * @type fabric.Image + * @default + */ + overlayImage: null, + + /** + * Indicates whether toObject/toDatalessObject should include default values + * @type Boolean + * @default + */ + includeDefaultValues: true, + + /** + * Indicates whether objects' state should be saved + * @type Boolean + * @default + */ + stateful: true, + + /** + * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove} should also re-render canvas. + * Disabling this option could give a great performance boost when adding/removing a lot of objects to/from canvas at once + * (followed by a manual rendering after addition/deletion) + * @type Boolean + * @default + */ + renderOnAddRemove: true, + + /** + * Function that determines clipping of entire canvas area + * Being passed context as first argument. See clipping canvas area in {@link https://github.com/kangax/fabric.js/wiki/FAQ} + * @type Function + * @default + */ + clipTo: null, + + /** + * Indicates whether object controls (borders/controls) are rendered above overlay image + * @type Boolean + * @default + */ + controlsAboveOverlay: false, + + /** + * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas + * @type Boolean + * @default + */ + allowTouchScrolling: false, + + /** + * Indicates whether this canvas will use image smoothing, this is on by default in browsers + * @type Boolean + * @default + */ + imageSmoothingEnabled: true, + + /** + * The transformation (in the format of Canvas transform) which focuses the viewport + * @type Array + * @default + */ + viewportTransform: [1, 0, 0, 1, 0, 0], + + /** + * Callback; invoked right before object is about to be scaled/rotated + * @param {fabric.Object} target Object that's about to be scaled/rotated + */ + onBeforeScaleRotate: function () { + /* NOOP */ + }, + + /** + * @private + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + */ + _initStatic: function(el, options) { + this._objects = []; + + this._createLowerCanvas(el); + this._initOptions(options); + this._setImageSmoothing(); + + if (options.overlayImage) { + this.setOverlayImage(options.overlayImage, this.renderAll.bind(this)); + } + if (options.backgroundImage) { + this.setBackgroundImage(options.backgroundImage, this.renderAll.bind(this)); + } + if (options.backgroundColor) { + this.setBackgroundColor(options.backgroundColor, this.renderAll.bind(this)); + } + if (options.overlayColor) { + this.setOverlayColor(options.overlayColor, this.renderAll.bind(this)); + } + this.calcOffset(); + }, + + /** + * Calculates canvas element offset relative to the document + * This method is also attached as "resize" event handler of window + * @return {fabric.Canvas} instance + * @chainable + */ + calcOffset: function () { + this._offset = getElementOffset(this.lowerCanvasEl); + return this; + }, + + /** + * Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas + * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set overlay to + * @param {Function} callback callback to invoke when image is loaded and set as an overlay + * @param {Object} [options] Optional options to set for the {@link fabric.Image|overlay image}. + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo} + * @example Normal overlayImage with left/top = 0 + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * // Needed to position overlayImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + * @example overlayImage with different properties + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * opacity: 0.5, + * angle: 45, + * left: 400, + * top: 400, + * originX: 'left', + * originY: 'top' + * }); + * @example Stretched overlayImage #1 - width/height correspond to canvas width/height + * fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img) { + * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); + * canvas.setOverlayImage(img, canvas.renderAll.bind(canvas)); + * }); + * @example Stretched overlayImage #2 - width/height correspond to canvas width/height + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * width: canvas.width, + * height: canvas.height, + * // Needed to position overlayImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + */ + setOverlayImage: function (image, callback, options) { + return this.__setBgOverlayImage('overlayImage', image, callback, options); + }, + + /** + * Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas + * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background to + * @param {Function} callback Callback to invoke when image is loaded and set as background + * @param {Object} [options] Optional options to set for the {@link fabric.Image|background image}. + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/YH9yD/|jsFiddle demo} + * @example Normal backgroundImage with left/top = 0 + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * // Needed to position backgroundImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + * @example backgroundImage with different properties + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * opacity: 0.5, + * angle: 45, + * left: 400, + * top: 400, + * originX: 'left', + * originY: 'top' + * }); + * @example Stretched backgroundImage #1 - width/height correspond to canvas width/height + * fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img) { + * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); + * canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas)); + * }); + * @example Stretched backgroundImage #2 - width/height correspond to canvas width/height + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * width: canvas.width, + * height: canvas.height, + * // Needed to position backgroundImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + */ + setBackgroundImage: function (image, callback, options) { + return this.__setBgOverlayImage('backgroundImage', image, callback, options); + }, + + /** + * Sets {@link fabric.StaticCanvas#overlayColor|background color} for this canvas + * @param {(String|fabric.Pattern)} overlayColor Color or pattern to set background color to + * @param {Function} callback Callback to invoke when background color is set + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/pB55h/|jsFiddle demo} + * @example Normal overlayColor - color value + * canvas.setOverlayColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as overlayColor + * canvas.setOverlayColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png' + * }, canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as overlayColor with repeat and offset + * canvas.setOverlayColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png', + * repeat: 'repeat', + * offsetX: 200, + * offsetY: 100 + * }, canvas.renderAll.bind(canvas)); + */ + setOverlayColor: function(overlayColor, callback) { + return this.__setBgOverlayColor('overlayColor', overlayColor, callback); + }, + + /** + * Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas + * @param {(String|fabric.Pattern)} backgroundColor Color or pattern to set background color to + * @param {Function} callback Callback to invoke when background color is set + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo} + * @example Normal backgroundColor - color value + * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as backgroundColor + * canvas.setBackgroundColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png' + * }, canvas.renderAll.bind(canvas)); + * @example fabric.Pattern used as backgroundColor with repeat and offset + * canvas.setBackgroundColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png', + * repeat: 'repeat', + * offsetX: 200, + * offsetY: 100 + * }, canvas.renderAll.bind(canvas)); + */ + setBackgroundColor: function(backgroundColor, callback) { + return this.__setBgOverlayColor('backgroundColor', backgroundColor, callback); + }, + + /** + * @private + * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-imagesmoothingenabled|WhatWG Canvas Standard} + */ + _setImageSmoothing: function(){ + var ctx = this.getContext(); + + ctx.imageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.webkitImageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.mozImageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.msImageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.oImageSmoothingEnabled = this.imageSmoothingEnabled; + }, + + /** + * @private + * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage} + * or {@link fabric.StaticCanvas#overlayImage|overlayImage}) + * @param {(fabric.Image|String|null)} image fabric.Image instance, URL of an image or null to set background or overlay to + * @param {Function} callback Callback to invoke when image is loaded and set as background or overlay + * @param {Object} [options] Optional options to set for the {@link fabric.Image|image}. + */ + __setBgOverlayImage: function(property, image, callback, options) { + if (typeof image === 'string') { + fabric.util.loadImage(image, function(img) { + this[property] = new fabric.Image(img, options); + callback && callback(); + }, this); + } + else { + this[property] = image; + callback && callback(); + } + + return this; + }, + + /** + * @private + * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundColor|backgroundColor} + * or {@link fabric.StaticCanvas#overlayColor|overlayColor}) + * @param {(Object|String|null)} color Object with pattern information, color value or null + * @param {Function} [callback] Callback is invoked when color is set + */ + __setBgOverlayColor: function(property, color, callback) { + if (color && color.source) { + var _this = this; + fabric.util.loadImage(color.source, function(img) { + _this[property] = new fabric.Pattern({ + source: img, + repeat: color.repeat, + offsetX: color.offsetX, + offsetY: color.offsetY + }); + callback && callback(); + }); + } + else { + this[property] = color; + callback && callback(); + } + + return this; + }, + + /** + * @private + */ + _createCanvasElement: function() { + var element = fabric.document.createElement('canvas'); + if (!element.style) { + element.style = { }; + } + if (!element) { + throw CANVAS_INIT_ERROR; + } + this._initCanvasElement(element); + return element; + }, + + /** + * @private + * @param {HTMLElement} element + */ + _initCanvasElement: function(element) { + fabric.util.createCanvasElement(element); + + if (typeof element.getContext === 'undefined') { + throw CANVAS_INIT_ERROR; + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initOptions: function (options) { + for (var prop in options) { + this[prop] = options[prop]; + } + + this.width = this.width || parseInt(this.lowerCanvasEl.width, 10) || 0; + this.height = this.height || parseInt(this.lowerCanvasEl.height, 10) || 0; + + if (!this.lowerCanvasEl.style) return; + + this.lowerCanvasEl.width = this.width; + this.lowerCanvasEl.height = this.height; + + this.lowerCanvasEl.style.width = this.width + 'px'; + this.lowerCanvasEl.style.height = this.height + 'px'; + }, + + /** + * Creates a bottom canvas + * @private + * @param {HTMLElement} [canvasEl] + */ + _createLowerCanvas: function (canvasEl) { + this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement(); + this._initCanvasElement(this.lowerCanvasEl); + + fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas'); + + if (this.interactive) { + this._applyCanvasStyle(this.lowerCanvasEl); + } + + this.contextContainer = this.lowerCanvasEl.getContext('2d'); + }, + + /** + * Returns canvas width (in px) + * @return {Number} + */ + getWidth: function () { + return this.width; + }, + + /** + * Returns canvas height (in px) + * @return {Number} + */ + getHeight: function () { + return this.height; + }, + + /** + * Sets width of this canvas instance + * @param {Number} width value to set width to + * @return {fabric.Canvas} instance + * @chainable true + */ + setWidth: function (value) { + return this._setDimension('width', value); + }, + + /** + * Sets height of this canvas instance + * @param {Number} height value to set height to + * @return {fabric.Canvas} instance + * @chainable true + */ + setHeight: function (value) { + return this._setDimension('height', value); + }, + + /** + * Sets dimensions (width, height) of this canvas instance + * @param {Object} dimensions Object with width/height properties + * @param {Number} [dimensions.width] Width of canvas element + * @param {Number} [dimensions.height] Height of canvas element + * @return {fabric.Canvas} thisArg + * @chainable + */ + setDimensions: function(dimensions) { + for (var prop in dimensions) { + this._setDimension(prop, dimensions[prop]); + } + return this; + }, + + /** + * Helper for setting width/height + * @private + * @param {String} prop property (width|height) + * @param {Number} value value to set property to + * @return {fabric.Canvas} instance + * @chainable true + */ + _setDimension: function (prop, value) { + this.lowerCanvasEl[prop] = value; + this.lowerCanvasEl.style[prop] = value + 'px'; + + if (this.upperCanvasEl) { + this.upperCanvasEl[prop] = value; + this.upperCanvasEl.style[prop] = value + 'px'; + } + + if (this.cacheCanvasEl) { + this.cacheCanvasEl[prop] = value; + } + + if (this.wrapperEl) { + this.wrapperEl.style[prop] = value + 'px'; + } + + this[prop] = value; + + this.calcOffset(); + this.renderAll(); + + return this; + }, + + /** + * Returns canvas zoom level + * @return {Number} + */ + getZoom: function () { + return Math.sqrt(this.viewportTransform[0] * this.viewportTransform[3]); + }, + + /** + * Sets viewport transform of this canvas instance + * @param {Array} vpt the transform in the form of context.transform + * @return {fabric.Canvas} instance + * @chainable true + */ + setViewportTransform: function (vpt) { + this.viewportTransform = vpt; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + return this; + }, + + /** + * Sets zoom level of this canvas instance, zoom centered around point + * @param {fabric.Point} point to zoom with respect to + * @param {Number} value to set zoom to, less than 1 zooms out + * @return {fabric.Canvas} instance + * @chainable true + */ + zoomToPoint: function (point, value) { + // TODO: just change the scale, preserve other transformations + var before = point; + point = fabric.util.transformPoint(point, fabric.util.invertTransform(this.viewportTransform)); + this.viewportTransform[0] = value; + this.viewportTransform[3] = value; + var after = fabric.util.transformPoint(point, this.viewportTransform); + this.viewportTransform[4] += before.x - after.x; + this.viewportTransform[5] += before.y - after.y; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + return this; + }, + + /** + * Sets zoom level of this canvas instance + * @param {Number} value to set zoom to, less than 1 zooms out + * @return {fabric.Canvas} instance + * @chainable true + */ + setZoom: function (value) { + this.zoomToPoint(new fabric.Point(0, 0), value); + return this; + }, + + /** + * Pan viewport so as to place point at top left corner of canvas + * @param {fabric.Point} point to move to + * @return {fabric.Canvas} instance + * @chainable true + */ + absolutePan: function (point) { + this.viewportTransform[4] = -point.x; + this.viewportTransform[5] = -point.y; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + return this; + }, + + /** + * Pans viewpoint relatively + * @param {fabric.Point} point (position vector) to move by + * @return {fabric.Canvas} instance + * @chainable true + */ + relativePan: function (point) { + return this.absolutePan(new fabric.Point( + -point.x - this.viewportTransform[4], + -point.y - this.viewportTransform[5] + )); + }, + + /** + * Returns <canvas> element corresponding to this instance + * @return {HTMLCanvasElement} + */ + getElement: function () { + return this.lowerCanvasEl; + }, + + /** + * Returns currently selected object, if any + * @return {fabric.Object} + */ + getActiveObject: function() { + return null; + }, + + /** + * Returns currently selected group of object, if any + * @return {fabric.Group} + */ + getActiveGroup: function() { + return null; + }, + + /** + * Given a context, renders an object on that context + * @param {CanvasRenderingContext2D} ctx Context to render object on + * @param {fabric.Object} object Object to render + * @private + */ + _draw: function (ctx, object) { + if (!object) return; + + ctx.save(); + var v = this.viewportTransform; + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + object.render(ctx); + ctx.restore(); + if (!this.controlsAboveOverlay) object._renderControls(ctx); + }, + + /** + * @private + * @param {fabric.Object} obj Object that was added + */ + _onObjectAdded: function(obj) { + this.stateful && obj.setupState(); + obj.canvas = this; + obj.setCoords(); + this.fire('object:added', { target: obj }); + obj.fire('added'); + }, + + /** + * @private + * @param {fabric.Object} obj Object that was removed + */ + _onObjectRemoved: function(obj) { + // removing active object should fire "selection:cleared" events + if (this.getActiveObject() === obj) { + this.fire('before:selection:cleared', { target: obj }); + this._discardActiveObject(); + this.fire('selection:cleared'); + } + + this.fire('object:removed', { target: obj }); + obj.fire('removed'); + }, + + /** + * Clears specified context of canvas element + * @param {CanvasRenderingContext2D} ctx Context to clear + * @return {fabric.Canvas} thisArg + * @chainable + */ + clearContext: function(ctx) { + ctx.clearRect(0, 0, this.width, this.height); + return this; + }, + + /** + * Returns context of canvas where objects are drawn + * @return {CanvasRenderingContext2D} + */ + getContext: function () { + return this.contextContainer; + }, + + /** + * Clears all contexts (background, main, top) of an instance + * @return {fabric.Canvas} thisArg + * @chainable + */ + clear: function () { + this._objects.length = 0; + if (this.discardActiveGroup) { + this.discardActiveGroup(); + } + if (this.discardActiveObject) { + this.discardActiveObject(); + } + this.clearContext(this.contextContainer); + if (this.contextTop) { + this.clearContext(this.contextTop); + } + this.fire('canvas:cleared'); + this.renderAll(); + return this; + }, + + /** + * Renders both the top canvas and the secondary container canvas. + * @param {Boolean} [allOnTop] Whether we want to force all images to be rendered on the top canvas + * @return {fabric.Canvas} instance + * @chainable + */ + renderAll: function (allOnTop) { + var canvasToDrawOn = this[(allOnTop === true && this.interactive) ? 'contextTop' : 'contextContainer'], + activeGroup = this.getActiveGroup(); + + if (this.contextTop && this.selection && !this._groupSelector) { + this.clearContext(this.contextTop); + } + + if (!allOnTop) { + this.clearContext(canvasToDrawOn); + } + + this.fire('before:render'); + + if (this.clipTo) { + fabric.util.clipContext(this, canvasToDrawOn); + } + + this._renderBackground(canvasToDrawOn); + this._renderObjects(canvasToDrawOn, activeGroup); + this._renderActiveGroup(canvasToDrawOn, activeGroup); + + if (this.clipTo) { + canvasToDrawOn.restore(); + } + + this._renderOverlay(canvasToDrawOn); + + if (this.controlsAboveOverlay && this.interactive) { + this.drawControls(canvasToDrawOn); + } + + this.fire('after:render'); + + return this; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {fabric.Group} activeGroup + */ + _renderObjects: function(ctx, activeGroup) { + var i, length; + + // fast path + if (!activeGroup) { + for (i = 0, length = this._objects.length; i < length; ++i) { + this._draw(ctx, this._objects[i]); + } + } + else { + for (i = 0, length = this._objects.length; i < length; ++i) { + if (this._objects[i] && !activeGroup.contains(this._objects[i])) { + this._draw(ctx, this._objects[i]); + } + } + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {fabric.Group} activeGroup + */ + _renderActiveGroup: function(ctx, activeGroup) { + + // delegate rendering to group selection (if one exists) + if (activeGroup) { + + //Store objects in group preserving order, then replace + var sortedObjects = []; + this.forEachObject(function (object) { + if (activeGroup.contains(object)) { + sortedObjects.push(object); + } + }); + activeGroup._set('objects', sortedObjects); + this._draw(ctx, activeGroup); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderBackground: function(ctx) { + if (this.backgroundColor) { + ctx.fillStyle = this.backgroundColor.toLive + ? this.backgroundColor.toLive(ctx) + : this.backgroundColor; + + ctx.fillRect( + this.backgroundColor.offsetX || 0, + this.backgroundColor.offsetY || 0, + this.width, + this.height); + } + if (this.backgroundImage) { + this._draw(ctx, this.backgroundImage); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderOverlay: function(ctx) { + if (this.overlayColor) { + ctx.fillStyle = this.overlayColor.toLive + ? this.overlayColor.toLive(ctx) + : this.overlayColor; + + ctx.fillRect( + this.overlayColor.offsetX || 0, + this.overlayColor.offsetY || 0, + this.width, + this.height); + } + if (this.overlayImage) { + this._draw(ctx, this.overlayImage); + } + }, + + /** + * Method to render only the top canvas. + * Also used to render the group selection box. + * @return {fabric.Canvas} thisArg + * @chainable + */ + renderTop: function () { + var ctx = this.contextTop || this.contextContainer; + this.clearContext(ctx); + + // we render the top context - last object + if (this.selection && this._groupSelector) { + this._drawSelection(); + } + + // delegate rendering to group selection if one exists + // used for drawing selection borders/controls + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + activeGroup.render(ctx); + } + + this._renderOverlay(ctx); + + this.fire('after:render'); + + return this; + }, + + /** + * Returns coordinates of a center of canvas. + * Returned value is an object with top and left properties + * @return {Object} object with "top" and "left" number values + */ + getCenter: function () { + return { + top: this.getHeight() / 2, + left: this.getWidth() / 2 + }; + }, + + /** + * Centers object horizontally. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center horizontally + * @return {fabric.Canvas} thisArg + */ + centerObjectH: function (object) { + this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y)); + this.renderAll(); + return this; + }, + + /** + * Centers object vertically. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center vertically + * @return {fabric.Canvas} thisArg + * @chainable + */ + centerObjectV: function (object) { + this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top)); + this.renderAll(); + return this; + }, + + /** + * Centers object vertically and horizontally. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center vertically and horizontally + * @return {fabric.Canvas} thisArg + * @chainable + */ + centerObject: function(object) { + var center = this.getCenter(); + + this._centerObject(object, new fabric.Point(center.left, center.top)); + this.renderAll(); + return this; + }, + + /** + * @private + * @param {fabric.Object} object Object to center + * @param {fabric.Point} center Center point + * @return {fabric.Canvas} thisArg + * @chainable + */ + _centerObject: function(object, center) { + object.setPositionByOrigin(center, 'center', 'center'); + return this; + }, + + /** + * Returs dataless JSON representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {String} json string + */ + toDatalessJSON: function (propertiesToInclude) { + return this.toDatalessObject(propertiesToInclude); + }, + + /** + * Returns object representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function (propertiesToInclude) { + return this._toObjectMethod('toObject', propertiesToInclude); + }, + + /** + * Returns dataless object representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toDatalessObject: function (propertiesToInclude) { + return this._toObjectMethod('toDatalessObject', propertiesToInclude); + }, + + /** + * @private + */ + _toObjectMethod: function (methodName, propertiesToInclude) { + + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this.discardActiveGroup(); + } + + var data = { + objects: this._toObjects(methodName, propertiesToInclude) + }; + + extend(data, this.__serializeBgOverlay()); + + fabric.util.populateWithProperties(this, data, propertiesToInclude); + + if (activeGroup) { + this.setActiveGroup(new fabric.Group(activeGroup.getObjects(), { + originX: 'center', + originY: 'center' + })); + activeGroup.forEachObject(function(o) { + o.set('active', true); + }); + + if (this._currentTransform) { + this._currentTransform.target = this.getActiveGroup(); + } + } + + return data; + }, + + /** + * @private + */ + _toObjects: function(methodName, propertiesToInclude) { + return this.getObjects().map(function(instance) { + return this._toObject(instance, methodName, propertiesToInclude); + }, this); + }, + + /** + * @private + */ + _toObject: function(instance, methodName, propertiesToInclude) { + var originalValue; + + if (!this.includeDefaultValues) { + originalValue = instance.includeDefaultValues; + instance.includeDefaultValues = false; + } + var object = instance[methodName](propertiesToInclude); + if (!this.includeDefaultValues) { + instance.includeDefaultValues = originalValue; + } + return object; + }, + + /** + * @private + */ + __serializeBgOverlay: function() { + var data = { + background: (this.backgroundColor && this.backgroundColor.toObject) + ? this.backgroundColor.toObject() + : this.backgroundColor + }; + + if (this.overlayColor) { + data.overlay = this.overlayColor.toObject + ? this.overlayColor.toObject() + : this.overlayColor; + } + if (this.backgroundImage) { + data.backgroundImage = this.backgroundImage.toObject(); + } + if (this.overlayImage) { + data.overlayImage = this.overlayImage.toObject(); + } + + return data; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of canvas + * @function + * @param {Object} [options] Options object for SVG output + * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included + * @param {Object} [options.viewBox] SVG viewbox object + * @param {Number} [options.viewBox.x] x-cooridnate of viewbox + * @param {Number} [options.viewBox.y] y-coordinate of viewbox + * @param {Number} [options.viewBox.width] Width of viewbox + * @param {Number} [options.viewBox.height] Height of viewbox + * @param {String} [options.encoding=UTF-8] Encoding of SVG output + * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation. + * @return {String} SVG string + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization} + * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo} + * @example Normal SVG output + * var svg = canvas.toSVG(); + * @example SVG output without preamble (without <?xml ../>) + * var svg = canvas.toSVG({suppressPreamble: true}); + * @example SVG output with viewBox attribute + * var svg = canvas.toSVG({ + * viewBox: { + * x: 100, + * y: 100, + * width: 200, + * height: 300 + * } + * }); + * @example SVG output with different encoding (default: UTF-8) + * var svg = canvas.toSVG({encoding: 'ISO-8859-1'}); + * @example Modify SVG output with reviver function + * var svg = canvas.toSVG(null, function(svg) { + * return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', ''); + * }); + */ + toSVG: function(options, reviver) { + options || (options = { }); + + var markup = []; + + this._setSVGPreamble(markup, options); + this._setSVGHeader(markup, options); + + this._setSVGBgOverlayColor(markup, 'backgroundColor'); + this._setSVGBgOverlayImage(markup, 'backgroundImage'); + + this._setSVGObjects(markup, reviver); + + this._setSVGBgOverlayColor(markup, 'overlayColor'); + this._setSVGBgOverlayImage(markup, 'overlayImage'); + + markup.push(''); + + return markup.join(''); + }, + + /** + * @private + */ + _setSVGPreamble: function(markup, options) { + if (!options.suppressPreamble) { + markup.push( + '', + '\n' + ); + } + }, + + /** + * @private + */ + _setSVGHeader: function(markup, options) { + markup.push( + '', + 'Created with Fabric.js ', fabric.version, '', + '', + fabric.createSVGFontFacesMarkup(this.getObjects()), + fabric.createSVGRefElementsMarkup(this), + '' + ); + }, + + /** + * @private + */ + _setSVGObjects: function(markup, reviver) { + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this.discardActiveGroup(); + } + for (var i = 0, objects = this.getObjects(), len = objects.length; i < len; i++) { + markup.push(objects[i].toSVG(reviver)); + } + if (activeGroup) { + this.setActiveGroup(new fabric.Group(activeGroup.getObjects())); + activeGroup.forEachObject(function(o) { + o.set('active', true); + }); + } + }, + + /** + * @private + */ + _setSVGBgOverlayImage: function(markup, property) { + if (this[property] && this[property].toSVG) { + markup.push(this[property].toSVG()); + } + }, + + /** + * @private + */ + _setSVGBgOverlayColor: function(markup, property) { + if (this[property] && this[property].source) { + markup.push( + '' + ); + } + else if (this[property] && property === 'overlayColor') { + markup.push( + '' + ); + } + }, + /* _TO_SVG_END_ */ + + /** + * Moves an object to the bottom of the stack of drawn objects + * @param {fabric.Object} object Object to send to back + * @return {fabric.Canvas} thisArg + * @chainable + */ + sendToBack: function (object) { + removeFromArray(this._objects, object); + this._objects.unshift(object); + return this.renderAll && this.renderAll(); + }, + + /** + * Moves an object to the top of the stack of drawn objects + * @param {fabric.Object} object Object to send + * @return {fabric.Canvas} thisArg + * @chainable + */ + bringToFront: function (object) { + removeFromArray(this._objects, object); + this._objects.push(object); + return this.renderAll && this.renderAll(); + }, + + /** + * Moves an object down in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object + * @return {fabric.Canvas} thisArg + * @chainable + */ + sendBackwards: function (object, intersecting) { + var idx = this._objects.indexOf(object); + + // if object is not on the bottom of stack + if (idx !== 0) { + var newIdx = this._findNewLowerIndex(object, idx, intersecting); + + removeFromArray(this._objects, object); + this._objects.splice(newIdx, 0, object); + this.renderAll && this.renderAll(); + } + return this; + }, + + /** + * @private + */ + _findNewLowerIndex: function(object, idx, intersecting) { + var newIdx; + + if (intersecting) { + newIdx = idx; + + // traverse down the stack looking for the nearest intersecting object + for (var i = idx - 1; i >= 0; --i) { + + var isIntersecting = object.intersectsWithObject(this._objects[i]) || + object.isContainedWithinObject(this._objects[i]) || + this._objects[i].isContainedWithinObject(object); + + if (isIntersecting) { + newIdx = i; + break; + } + } + } + else { + newIdx = idx - 1; + } + + return newIdx; + }, + + /** + * Moves an object up in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object + * @return {fabric.Canvas} thisArg + * @chainable + */ + bringForward: function (object, intersecting) { + var idx = this._objects.indexOf(object); + + // if object is not on top of stack (last item in an array) + if (idx !== this._objects.length - 1) { + var newIdx = this._findNewUpperIndex(object, idx, intersecting); + + removeFromArray(this._objects, object); + this._objects.splice(newIdx, 0, object); + this.renderAll && this.renderAll(); + } + return this; + }, + + /** + * @private + */ + _findNewUpperIndex: function(object, idx, intersecting) { + var newIdx; + + if (intersecting) { + newIdx = idx; + + // traverse up the stack looking for the nearest intersecting object + for (var i = idx + 1; i < this._objects.length; ++i) { + + var isIntersecting = object.intersectsWithObject(this._objects[i]) || + object.isContainedWithinObject(this._objects[i]) || + this._objects[i].isContainedWithinObject(object); + + if (isIntersecting) { + newIdx = i; + break; + } + } + } + else { + newIdx = idx + 1; + } + + return newIdx; + }, + + /** + * Moves an object to specified level in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Number} index Position to move to + * @return {fabric.Canvas} thisArg + * @chainable + */ + moveTo: function (object, index) { + removeFromArray(this._objects, object); + this._objects.splice(index, 0, object); + return this.renderAll && this.renderAll(); + }, + + /** + * Clears a canvas element and removes all event listeners + * @return {fabric.Canvas} thisArg + * @chainable + */ + dispose: function () { + this.clear(); + this.interactive && this.removeListeners(); + return this; + }, + + /** + * Returns a string representation of an instance + * @return {String} string representation of an instance + */ + toString: function () { + return '#'; + } + }); + + extend(fabric.StaticCanvas.prototype, fabric.Observable); + extend(fabric.StaticCanvas.prototype, fabric.Collection); + extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter); + + extend(fabric.StaticCanvas, /** @lends fabric.StaticCanvas */ { + + /** + * @static + * @type String + * @default + */ + EMPTY_JSON: '{"objects": [], "background": "white"}', + + /** + * Provides a way to check support of some of the canvas methods + * (either those of HTMLCanvasElement itself, or rendering context) + * + * @param methodName {String} Method to check support for; + * Could be one of "getImageData", "toDataURL", "toDataURLWithQuality" or "setLineDash" + * @return {Boolean | null} `true` if method is supported (or at least exists), + * `null` if canvas element or context can not be initialized + */ + supports: function (methodName) { + var el = fabric.util.createCanvasElement(); + + if (!el || !el.getContext) { + return null; + } + + var ctx = el.getContext('2d'); + if (!ctx) { + return null; + } + + switch (methodName) { + + case 'getImageData': + return typeof ctx.getImageData !== 'undefined'; + + case 'setLineDash': + return typeof ctx.setLineDash !== 'undefined'; + + case 'toDataURL': + return typeof el.toDataURL !== 'undefined'; + + case 'toDataURLWithQuality': + try { + el.toDataURL('image/jpeg', 0); + return true; + } + catch (e) { } + return false; + + default: + return null; + } + } + }); + + /** + * Returns JSON representation of canvas + * @function + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {String} JSON string + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization} + * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo} + * @example JSON without additional properties + * var json = canvas.toJSON(); + * @example JSON with additional properties included + * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY', 'lockUniScaling']); + * @example JSON without default values + * canvas.includeDefaultValues = false; + * var json = canvas.toJSON(); + */ + fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject; + +})(); + + +/** + * BaseBrush class + * @class fabric.BaseBrush + * @see {@link http://fabricjs.com/freedrawing/|Freedrawing demo} + */ +fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ { + + /** + * Color of a brush + * @type String + * @default + */ + color: 'rgb(0, 0, 0)', + + /** + * Width of a brush + * @type Number + * @default + */ + width: 1, + + /** + * Shadow object representing shadow of this shape. + * Backwards incompatibility note: This property replaces "shadowColor" (String), "shadowOffsetX" (Number), + * "shadowOffsetY" (Number) and "shadowBlur" (Number) since v1.2.12 + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Line endings style of a brush (one of "butt", "round", "square") + * @type String + * @default + */ + strokeLineCap: 'round', + + /** + * Corner style of a brush (one of "bevil", "round", "miter") + * @type String + * @default + */ + strokeLineJoin: 'round', + + /** + * Sets shadow of an object + * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") + * @return {fabric.Object} thisArg + * @chainable + */ + setShadow: function(options) { + this.shadow = new fabric.Shadow(options); + return this; + }, + + /** + * Sets brush styles + * @private + */ + _setBrushStyles: function() { + var ctx = this.canvas.contextTop; + + ctx.strokeStyle = this.color; + ctx.lineWidth = this.width; + ctx.lineCap = this.strokeLineCap; + ctx.lineJoin = this.strokeLineJoin; + }, + + /** + * Sets brush shadow styles + * @private + */ + _setShadow: function() { + if (!this.shadow) return; + + var ctx = this.canvas.contextTop; + + ctx.shadowColor = this.shadow.color; + ctx.shadowBlur = this.shadow.blur; + ctx.shadowOffsetX = this.shadow.offsetX; + ctx.shadowOffsetY = this.shadow.offsetY; + }, + + /** + * Removes brush shadow styles + * @private + */ + _resetShadow: function() { + var ctx = this.canvas.contextTop; + + ctx.shadowColor = ''; + ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; + } +}); + + +(function() { + + var utilMin = fabric.util.array.min, + utilMax = fabric.util.array.max; + + /** + * PencilBrush class + * @class fabric.PencilBrush + * @extends fabric.BaseBrush + */ + fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.PencilBrush.prototype */ { + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.PencilBrush} Instance of a pencil brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this._points = [ ]; + }, + + /** + * Inovoked on mouse down + * @param {Object} pointer + */ + onMouseDown: function(pointer) { + this._prepareForDrawing(pointer); + // capture coordinates immediately + // this allows to draw dots (when movement never occurs) + this._captureDrawingPath(pointer); + this._render(); + }, + + /** + * Inovoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this._captureDrawingPath(pointer); + // redraw curve + // clear top canvas + this.canvas.clearContext(this.canvas.contextTop); + this._render(); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + this._finalizeAndAddPath(); + }, + + /** + * @param {Object} pointer + */ + _prepareForDrawing: function(pointer) { + + var p = new fabric.Point(pointer.x, pointer.y); + + this._reset(); + this._addPoint(p); + + this.canvas.contextTop.moveTo(p.x, p.y); + }, + + /** + * @private + * @param {fabric.Point} point + */ + _addPoint: function(point) { + this._points.push(point); + }, + + /** + * Clear points array and set contextTop canvas + * style. + * + * @private + * + */ + _reset: function() { + this._points.length = 0; + + this._setBrushStyles(); + this._setShadow(); + }, + + /** + * @private + * + * @param point {pointer} (fabric.util.pointer) actual mouse position + * related to the canvas. + */ + _captureDrawingPath: function(pointer) { + var pointerPoint = new fabric.Point(pointer.x, pointer.y); + this._addPoint(pointerPoint); + }, + + /** + * Draw a smooth path on the topCanvas using quadraticCurveTo + * + * @private + */ + _render: function() { + var ctx = this.canvas.contextTop; + var v = this.canvas.viewportTransform; + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + ctx.beginPath(); + + var p1 = this._points[0], + p2 = this._points[1]; + + //if we only have 2 points in the path and they are the same + //it means that the user only clicked the canvas without moving the mouse + //then we should be drawing a dot. A path isn't drawn between two identical dots + //that's why we set them apart a bit + if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) { + p1.x -= 0.5; + p2.x += 0.5; + } + ctx.moveTo(p1.x, p1.y); + + for (var i = 1, len = this._points.length; i < len; i++) { + // we pick the point between pi + 1 & pi + 2 as the + // end point and p1 as our control point. + var midPoint = p1.midPointFrom(p2); + ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y); + + p1 = this._points[i]; + p2 = this._points[i + 1]; + } + // Draw last line as a straight line while + // we wait for the next point to be able to calculate + // the bezier control point + ctx.lineTo(p1.x, p1.y); + ctx.stroke(); + ctx.restore(); + }, + + /** + * Return an SVG path based on our captured points and their bounding box + * + * @private + */ + _getSVGPathData: function() { + this.box = this.getPathBoundingBox(this._points); + return this.convertPointsToSVGPath( + this._points, this.box.minx, this.box.maxx, this.box.miny, this.box.maxy); + }, + + /** + * Returns bounding box of a path based on given points + * @param {Array} points + * @return {Object} object with minx, miny, maxx, maxy + */ + getPathBoundingBox: function(points) { + var xBounds = [], + yBounds = [], + p1 = points[0], + p2 = points[1], + startPoint = p1; + + for (var i = 1, len = points.length; i < len; i++) { + var midPoint = p1.midPointFrom(p2); + // with startPoint, p1 as control point, midpoint as end point + xBounds.push(startPoint.x); + xBounds.push(midPoint.x); + yBounds.push(startPoint.y); + yBounds.push(midPoint.y); + + p1 = points[i]; + p2 = points[i + 1]; + startPoint = midPoint; + } + + xBounds.push(p1.x); + yBounds.push(p1.y); + + return { + minx: utilMin(xBounds), + miny: utilMin(yBounds), + maxx: utilMax(xBounds), + maxy: utilMax(yBounds) + }; + }, + + /** + * Converts points to SVG path + * @param {Array} points Array of points + * @return {String} SVG path + */ + convertPointsToSVGPath: function(points, minX, maxX, minY) { + var path = [], + p1 = new fabric.Point(points[0].x - minX, points[0].y - minY), + p2 = new fabric.Point(points[1].x - minX, points[1].y - minY); + + path.push('M ', points[0].x - minX, ' ', points[0].y - minY, ' '); + for (var i = 1, len = points.length; i < len; i++) { + var midPoint = p1.midPointFrom(p2); + // p1 is our bezier control point + // midpoint is our endpoint + // start point is p(i-1) value. + path.push('Q ', p1.x, ' ', p1.y, ' ', midPoint.x, ' ', midPoint.y, ' '); + p1 = new fabric.Point(points[i].x - minX, points[i].y - minY); + if ((i + 1) < points.length) { + p2 = new fabric.Point(points[i + 1].x - minX, points[i + 1].y - minY); + } + } + path.push('L ', p1.x, ' ', p1.y, ' '); + return path; + }, + + /** + * Creates fabric.Path object to add on canvas + * @param {String} pathData Path data + * @return {fabric.Path} path to add on canvas + */ + createPath: function(pathData) { + var path = new fabric.Path(pathData); + path.fill = null; + path.stroke = this.color; + path.strokeWidth = this.width; + path.strokeLineCap = this.strokeLineCap; + path.strokeLineJoin = this.strokeLineJoin; + + if (this.shadow) { + this.shadow.affectStroke = true; + path.setShadow(this.shadow); + } + + return path; + }, + + /** + * On mouseup after drawing the path on contextTop canvas + * we use the points captured to create an new fabric path object + * and add it to the fabric canvas. + * + */ + _finalizeAndAddPath: function() { + var ctx = this.canvas.contextTop; + ctx.closePath(); + + var pathData = this._getSVGPathData().join(''); + if (pathData === 'M 0 0 Q 0 0 0 0 L 0 0') { + // do not create 0 width/height paths, as they are + // rendered inconsistently across browsers + // Firefox 4, for example, renders a dot, + // whereas Chrome 10 renders nothing + this.canvas.renderAll(); + return; + } + + // set path origin coordinates based on our bounding box + var originLeft = this.box.minx + (this.box.maxx - this.box.minx) / 2, + originTop = this.box.miny + (this.box.maxy - this.box.miny) / 2; + + this.canvas.contextTop.arc(originLeft, originTop, 3, 0, Math.PI * 2, false); + + var path = this.createPath(pathData); + path.set({ + left: originLeft, + top: originTop, + originX: 'center', + originY: 'center' + }); + + this.canvas.add(path); + path.setCoords(); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderAll(); + + // fire event 'path' created + this.canvas.fire('path:created', { path: path }); + } + }); +})(); + + +/** + * CircleBrush class + * @class fabric.CircleBrush + */ +fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.CircleBrush.prototype */ { + + /** + * Width of a brush + * @type Number + * @default + */ + width: 10, + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.CircleBrush} Instance of a circle brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this.points = [ ]; + }, + /** + * Invoked inside on mouse down and mouse move + * @param {Object} pointer + */ + drawDot: function(pointer) { + var point = this.addPoint(pointer), + ctx = this.canvas.contextTop, + v = this.canvas.viewportTransform; + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + + ctx.fillStyle = point.fill; + ctx.beginPath(); + ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false); + ctx.closePath(); + ctx.fill(); + + ctx.restore(); + }, + + /** + * Invoked on mouse down + */ + onMouseDown: function(pointer) { + this.points.length = 0; + this.canvas.clearContext(this.canvas.contextTop); + this._setShadow(); + this.drawDot(pointer); + }, + + /** + * Invoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this.drawDot(pointer); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; + this.canvas.renderOnAddRemove = false; + + var circles = [ ]; + + for (var i = 0, len = this.points.length; i < len; i++) { + var point = this.points[i], + circle = new fabric.Circle({ + radius: point.radius, + left: point.x, + top: point.y, + originX: 'center', + originY: 'center', + fill: point.fill + }); + + this.shadow && circle.setShadow(this.shadow); + + circles.push(circle); + } + var group = new fabric.Group(circles, { originX: 'center', originY: 'center' }); + group.canvas = this.canvas; + + this.canvas.add(group); + this.canvas.fire('path:created', { path: group }); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderOnAddRemove = originalRenderOnAddRemove; + this.canvas.renderAll(); + }, + + /** + * @param {Object} pointer + * @return {fabric.Point} Just added pointer point + */ + addPoint: function(pointer) { + var pointerPoint = new fabric.Point(pointer.x, pointer.y), + + circleRadius = fabric.util.getRandomInt( + Math.max(0, this.width - 20), this.width + 20) / 2, + + circleColor = new fabric.Color(this.color) + .setAlpha(fabric.util.getRandomInt(0, 100) / 100) + .toRgba(); + + pointerPoint.radius = circleRadius; + pointerPoint.fill = circleColor; + + this.points.push(pointerPoint); + + return pointerPoint; + } +}); + + +/** + * SprayBrush class + * @class fabric.SprayBrush + */ +fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric.SprayBrush.prototype */ { + + /** + * Width of a spray + * @type Number + * @default + */ + width: 10, + + /** + * Density of a spray (number of dots per chunk) + * @type Number + * @default + */ + density: 20, + + /** + * Width of spray dots + * @type Number + * @default + */ + dotWidth: 1, + + /** + * Width variance of spray dots + * @type Number + * @default + */ + dotWidthVariance: 1, + + /** + * Whether opacity of a dot should be random + * @type Boolean + * @default + */ + randomOpacity: false, + + /** + * Whether overlapping dots (rectangles) should be removed (for performance reasons) + * @type Boolean + * @default + */ + optimizeOverlapping: true, + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.SprayBrush} Instance of a spray brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this.sprayChunks = [ ]; + }, + + /** + * Invoked on mouse down + * @param {Object} pointer + */ + onMouseDown: function(pointer) { + this.sprayChunks.length = 0; + this.canvas.clearContext(this.canvas.contextTop); + this._setShadow(); + + this.addSprayChunk(pointer); + this.render(); + }, + + /** + * Invoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this.addSprayChunk(pointer); + this.render(); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; + this.canvas.renderOnAddRemove = false; + + var rects = [ ]; + + for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) { + var sprayChunk = this.sprayChunks[i]; + + for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) { + + var rect = new fabric.Rect({ + width: sprayChunk[j].width, + height: sprayChunk[j].width, + left: sprayChunk[j].x + 1, + top: sprayChunk[j].y + 1, + originX: 'center', + originY: 'center', + fill: this.color + }); + + this.shadow && rect.setShadow(this.shadow); + rects.push(rect); + } + } + + if (this.optimizeOverlapping) { + rects = this._getOptimizedRects(rects); + } + + var group = new fabric.Group(rects, { originX: 'center', originY: 'center' }); + group.canvas = this.canvas; + + this.canvas.add(group); + this.canvas.fire('path:created', { path: group }); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderOnAddRemove = originalRenderOnAddRemove; + this.canvas.renderAll(); + }, + + _getOptimizedRects: function(rects) { + + // avoid creating duplicate rects at the same coordinates + var uniqueRects = { }, key; + + for (var i = 0, len = rects.length; i < len; i++) { + key = rects[i].left + '' + rects[i].top; + if (!uniqueRects[key]) { + uniqueRects[key] = rects[i]; + } + } + var uniqueRectsArray = [ ]; + for (key in uniqueRects) { + uniqueRectsArray.push(uniqueRects[key]); + } + + return uniqueRectsArray; + }, + + /** + * Renders brush + */ + render: function() { + var ctx = this.canvas.contextTop; + ctx.fillStyle = this.color; + + var v = this.canvas.viewportTransform; + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + + for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) { + var point = this.sprayChunkPoints[i]; + if (typeof point.opacity !== 'undefined') { + ctx.globalAlpha = point.opacity; + } + ctx.fillRect(point.x, point.y, point.width, point.width); + } + ctx.restore(); + }, + + /** + * @param {Object} pointer + */ + addSprayChunk: function(pointer) { + this.sprayChunkPoints = [ ]; + + var x, y, width, radius = this.width / 2; + + for (var i = 0; i < this.density; i++) { + + x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius); + y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius); + + if (this.dotWidthVariance) { + width = fabric.util.getRandomInt( + // bottom clamp width to 1 + Math.max(1, this.dotWidth - this.dotWidthVariance), + this.dotWidth + this.dotWidthVariance); + } + else { + width = this.dotWidth; + } + + var point = new fabric.Point(x, y); + point.width = width; + + if (this.randomOpacity) { + point.opacity = fabric.util.getRandomInt(0, 100) / 100; + } + + this.sprayChunkPoints.push(point); + } + + this.sprayChunks.push(this.sprayChunkPoints); + } +}); + + +/** + * PatternBrush class + * @class fabric.PatternBrush + * @extends fabric.BaseBrush + */ +fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fabric.PatternBrush.prototype */ { + + getPatternSrc: function() { + + var dotWidth = 20, + dotDistance = 5, + patternCanvas = fabric.document.createElement('canvas'), + patternCtx = patternCanvas.getContext('2d'); + + patternCanvas.width = patternCanvas.height = dotWidth + dotDistance; + + patternCtx.fillStyle = this.color; + patternCtx.beginPath(); + patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); + patternCtx.closePath(); + patternCtx.fill(); + + return patternCanvas; + }, + + getPatternSrcFunction: function() { + return String(this.getPatternSrc).replace('this.color', '"' + this.color + '"'); + }, + + /** + * Creates "pattern" instance property + */ + getPattern: function() { + return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), 'repeat'); + }, + + /** + * Sets brush styles + */ + _setBrushStyles: function() { + this.callSuper('_setBrushStyles'); + this.canvas.contextTop.strokeStyle = this.getPattern(); + }, + + /** + * Creates path + */ + createPath: function(pathData) { + var path = this.callSuper('createPath', pathData); + path.stroke = new fabric.Pattern({ + source: this.source || this.getPatternSrcFunction() + }); + return path; + } +}); + + +(function() { + + var getPointer = fabric.util.getPointer, + degreesToRadians = fabric.util.degreesToRadians, + radiansToDegrees = fabric.util.radiansToDegrees, + atan2 = Math.atan2, + abs = Math.abs, + + STROKE_OFFSET = 0.5; + + /** + * Canvas class + * @class fabric.Canvas + * @extends fabric.StaticCanvas + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#canvas} + * @see {@link fabric.Canvas#initialize} for constructor definition + * + * @fires object:modified + * @fires object:rotating + * @fires object:scaling + * @fires object:moving + * @fires object:selected + * + * @fires before:selection:cleared + * @fires selection:cleared + * @fires selection:created + * + * @fires path:created + * @fires mouse:down + * @fires mouse:move + * @fires mouse:up + * @fires mouse:over + * @fires mouse:out + * + */ + fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ { + + /** + * Constructor + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(el, options) { + options || (options = { }); + + this._initStatic(el, options); + this._initInteractive(); + this._createCacheCanvas(); + + fabric.Canvas.activeInstance = this; + }, + + /** + * When true, objects can be transformed by one side (unproportionally) + * @type Boolean + * @default + */ + uniScaleTransform: false, + + /** + * When true, objects use center point as the origin of scale transformation. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredScaling: false, + + /** + * When true, objects use center point as the origin of rotate transformation. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredRotation: false, + + /** + * Indicates that canvas is interactive. This property should not be changed. + * @type Boolean + * @default + */ + interactive: true, + + /** + * Indicates whether group selection should be enabled + * @type Boolean + * @default + */ + selection: true, + + /** + * Color of selection + * @type String + * @default + */ + selectionColor: 'rgba(100, 100, 255, 0.3)', // blue + + /** + * Default dash array pattern + * If not empty the selection border is dashed + * @type Array + */ + selectionDashArray: [ ], + + /** + * Color of the border of selection (usually slightly darker than color of selection itself) + * @type String + * @default + */ + selectionBorderColor: 'rgba(255, 255, 255, 0.3)', + + /** + * Width of a line used in object/group selection + * @type Number + * @default + */ + selectionLineWidth: 1, + + /** + * Default cursor value used when hovering over an object on canvas + * @type String + * @default + */ + hoverCursor: 'move', + + /** + * Default cursor value used when moving an object on canvas + * @type String + * @default + */ + moveCursor: 'move', + + /** + * Default cursor value used for the entire canvas + * @type String + * @default + */ + defaultCursor: 'default', + + /** + * Cursor value used during free drawing + * @type String + * @default + */ + freeDrawingCursor: 'crosshair', + + /** + * Cursor value used for rotation point + * @type String + * @default + */ + rotationCursor: 'crosshair', + + /** + * Default element class that's given to wrapper (div) element of canvas + * @type String + * @default + */ + containerClass: 'canvas-container', + + /** + * When true, object detection happens on per-pixel basis rather than on per-bounding-box + * @type Boolean + * @default + */ + perPixelTargetFind: false, + + /** + * Number of pixels around target pixel to tolerate (consider active) during object detection + * @type Number + * @default + */ + targetFindTolerance: 0, + + /** + * When true, target detection is skipped when hovering over canvas. This can be used to improve performance. + * @type Boolean + * @default + */ + skipTargetFind: false, + + /** + * @private + */ + _initInteractive: function() { + this._currentTransform = null; + this._groupSelector = null; + this._initWrapperElement(); + this._createUpperCanvas(); + this._initEventListeners(); + + this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this); + + this.calcOffset(); + }, + + /** + * Resets the current transform to its original values and chooses the type of resizing based on the event + * @private + * @param {Event} e Event object fired on mousemove + */ + _resetCurrentTransform: function(e) { + var t = this._currentTransform; + + t.target.set({ + scaleX: t.original.scaleX, + scaleY: t.original.scaleY, + left: t.original.left, + top: t.original.top + }); + + if (this._shouldCenterTransform(e, t.target)) { + if (t.action === 'rotate') { + this._setOriginToCenter(t.target); + } + else { + if (t.originX !== 'center') { + if (t.originX === 'right') { + t.mouseXSign = -1; + } + else { + t.mouseXSign = 1; + } + } + if (t.originY !== 'center') { + if (t.originY === 'bottom') { + t.mouseYSign = -1; + } + else { + t.mouseYSign = 1; + } + } + + t.originX = 'center'; + t.originY = 'center'; + } + } + else { + t.originX = t.original.originX; + t.originY = t.original.originY; + } + }, + + /** + * Checks if point is contained within an area of given object + * @param {Event} e Event object + * @param {fabric.Object} target Object to test against + * @return {Boolean} true if point is contained within an area of given object + */ + containsPoint: function (e, target) { + var pointer = this.getPointer(e, true), + xy = this._normalizePointer(target, pointer); + + // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html + // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html + return (target.containsPoint(xy) || target._findTargetCorner(pointer)); + }, + + /** + * @private + */ + _normalizePointer: function (object, pointer) { + var activeGroup = this.getActiveGroup(), + x = pointer.x, + y = pointer.y, + isObjectInGroup = ( + activeGroup && + object.type !== 'group' && + activeGroup.contains(object)), + lt; + + if (isObjectInGroup) { + lt = new fabric.Point(activeGroup.left, activeGroup.top); + lt = fabric.util.transformPoint(lt, this.viewportTransform, true); + x -= lt.x; + y -= lt.y; + } + return { x: x, y: y }; + }, + + /** + * Returns true if object is transparent at a certain location + * @param {fabric.Object} target Object to check + * @param {Number} x Left coordinate + * @param {Number} y Top coordinate + * @return {Boolean} + */ + isTargetTransparent: function (target, x, y) { + var hasBorders = target.hasBorders, + transparentCorners = target.transparentCorners; + + target.hasBorders = target.transparentCorners = false; + + this._draw(this.contextCache, target); + + target.hasBorders = hasBorders; + target.transparentCorners = transparentCorners; + + var isTransparent = fabric.util.isTransparent( + this.contextCache, x, y, this.targetFindTolerance); + + this.clearContext(this.contextCache); + + return isTransparent; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _shouldClearSelection: function (e, target) { + var activeGroup = this.getActiveGroup(), + activeObject = this.getActiveObject(); + + return ( + !target + || + (target && + activeGroup && + !activeGroup.contains(target) && + activeGroup !== target && + !e.shiftKey) + || + (target && !target.evented) + || + (target && + !target.selectable && + activeObject && + activeObject !== target) + ); + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _shouldCenterTransform: function (e, target) { + if (!target) return; + + var t = this._currentTransform, + centerTransform; + + if (t.action === 'scale' || t.action === 'scaleX' || t.action === 'scaleY') { + centerTransform = this.centeredScaling || target.centeredScaling; + } + else if (t.action === 'rotate') { + centerTransform = this.centeredRotation || target.centeredRotation; + } + + return centerTransform ? !e.altKey : e.altKey; + }, + + /** + * @private + */ + _getOriginFromCorner: function(target, corner) { + var origin = { + x: target.originX, + y: target.originY + }; + + if (corner === 'ml' || corner === 'tl' || corner === 'bl') { + origin.x = 'right'; + } + else if (corner === 'mr' || corner === 'tr' || corner === 'br') { + origin.x = 'left'; + } + + if (corner === 'tl' || corner === 'mt' || corner === 'tr') { + origin.y = 'bottom'; + } + else if (corner === 'bl' || corner === 'mb' || corner === 'br') { + origin.y = 'top'; + } + + return origin; + }, + + /** + * @private + */ + _getActionFromCorner: function(target, corner) { + var action = 'drag'; + if (corner) { + action = (corner === 'ml' || corner === 'mr') + ? 'scaleX' + : (corner === 'mt' || corner === 'mb') + ? 'scaleY' + : corner === 'mtr' + ? 'rotate' + : 'scale'; + } + return action; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _setupCurrentTransform: function (e, target) { + if (!target) return; + + var pointer = this.getPointer(e), + corner = target._findTargetCorner(this.getPointer(e, true)), + action = this._getActionFromCorner(target, corner), + origin = this._getOriginFromCorner(target, corner); + + this._currentTransform = { + target: target, + action: action, + scaleX: target.scaleX, + scaleY: target.scaleY, + offsetX: pointer.x - target.left, + offsetY: pointer.y - target.top, + originX: origin.x, + originY: origin.y, + ex: pointer.x, + ey: pointer.y, + left: target.left, + top: target.top, + theta: degreesToRadians(target.angle), + width: target.width * target.scaleX, + mouseXSign: 1, + mouseYSign: 1 + }; + + this._currentTransform.original = { + left: target.left, + top: target.top, + scaleX: target.scaleX, + scaleY: target.scaleY, + originX: origin.x, + originY: origin.y + }; + + this._resetCurrentTransform(e); + }, + + /** + * Translates object by "setting" its left/top + * @private + * @param x {Number} pointer's x coordinate + * @param y {Number} pointer's y coordinate + */ + _translateObject: function (x, y) { + var target = this._currentTransform.target; + + if (!target.get('lockMovementX')) { + target.set('left', x - this._currentTransform.offsetX); + } + if (!target.get('lockMovementY')) { + target.set('top', y - this._currentTransform.offsetY); + } + }, + + /** + * Scales object by invoking its scaleX/scaleY methods + * @private + * @param x {Number} pointer's x coordinate + * @param y {Number} pointer's y coordinate + * @param by {String} Either 'x' or 'y' - specifies dimension constraint by which to scale an object. + * When not provided, an object is scaled by both dimensions equally + */ + _scaleObject: function (x, y, by) { + var t = this._currentTransform, + target = t.target, + lockScalingX = target.get('lockScalingX'), + lockScalingY = target.get('lockScalingY'); + + if (lockScalingX && lockScalingY) return; + + // Get the constraint point + var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY), + localMouse = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY); + + this._setLocalMouse(localMouse, t); + + // Actually scale the object + this._setObjectScale(localMouse, t, lockScalingX, lockScalingY, by); + + // Make sure the constraints apply + target.setPositionByOrigin(constraintPosition, t.originX, t.originY); + }, + + /** + * @private + */ + _setObjectScale: function(localMouse, transform, lockScalingX, lockScalingY, by) { + var target = transform.target; + + transform.newScaleX = target.scaleX; + transform.newScaleY = target.scaleY; + + if (by === 'equally' && !lockScalingX && !lockScalingY) { + this._scaleObjectEqually(localMouse, target, transform); + } + else if (!by) { + transform.newScaleX = localMouse.x / (target.width + target.strokeWidth); + transform.newScaleY = localMouse.y / (target.height + target.strokeWidth); + + lockScalingX || target.set('scaleX', transform.newScaleX); + lockScalingY || target.set('scaleY', transform.newScaleY); + } + else if (by === 'x' && !target.get('lockUniScaling')) { + transform.newScaleX = localMouse.x / (target.width + target.strokeWidth); + lockScalingX || target.set('scaleX', transform.newScaleX); + } + else if (by === 'y' && !target.get('lockUniScaling')) { + transform.newScaleY = localMouse.y / (target.height + target.strokeWidth); + lockScalingY || target.set('scaleY', transform.newScaleY); + } + + this._flipObject(transform); + }, + + /** + * @private + */ + _scaleObjectEqually: function(localMouse, target, transform) { + + var dist = localMouse.y + localMouse.x, + lastDist = (target.height + (target.strokeWidth)) * transform.original.scaleY + + (target.width + (target.strokeWidth)) * transform.original.scaleX; + + // We use transform.scaleX/Y instead of target.scaleX/Y + // because the object may have a min scale and we'll loose the proportions + transform.newScaleX = transform.original.scaleX * dist / lastDist; + transform.newScaleY = transform.original.scaleY * dist / lastDist; + + target.set('scaleX', transform.newScaleX); + target.set('scaleY', transform.newScaleY); + }, + + /** + * @private + */ + _flipObject: function(transform) { + if (transform.newScaleX < 0) { + if (transform.originX === 'left') { + transform.originX = 'right'; + } + else if (transform.originX === 'right') { + transform.originX = 'left'; + } + } + + if (transform.newScaleY < 0) { + if (transform.originY === 'top') { + transform.originY = 'bottom'; + } + else if (transform.originY === 'bottom') { + transform.originY = 'top'; + } + } + }, + + /** + * @private + */ + _setLocalMouse: function(localMouse, t) { + var target = t.target; + + if (t.originX === 'right') { + localMouse.x *= -1; + } + else if (t.originX === 'center') { + localMouse.x *= t.mouseXSign * 2; + + if (localMouse.x < 0) { + t.mouseXSign = -t.mouseXSign; + } + } + + if (t.originY === 'bottom') { + localMouse.y *= -1; + } + else if (t.originY === 'center') { + localMouse.y *= t.mouseYSign * 2; + + if (localMouse.y < 0) { + t.mouseYSign = -t.mouseYSign; + } + } + + // adjust the mouse coordinates when dealing with padding + if (abs(localMouse.x) > target.padding) { + if (localMouse.x < 0) { + localMouse.x += target.padding; + } + else { + localMouse.x -= target.padding; + } + } + else { // mouse is within the padding, set to 0 + localMouse.x = 0; + } + + if (abs(localMouse.y) > target.padding) { + if (localMouse.y < 0) { + localMouse.y += target.padding; + } + else { + localMouse.y -= target.padding; + } + } + else { + localMouse.y = 0; + } + }, + + /** + * Rotates object by invoking its rotate method + * @private + * @param {Number} x pointer's x coordinate + * @param {Number} y pointer's y coordinate + */ + _rotateObject: function (x, y) { + + var t = this._currentTransform; + + if (t.target.get('lockRotation')) return; + + var lastAngle = atan2(t.ey - t.top, t.ex - t.left), + curAngle = atan2(y - t.top, x - t.left), + angle = radiansToDegrees(curAngle - lastAngle + t.theta); + + // normalize angle to positive value + if (angle < 0) { + angle = 360 + angle; + } + + t.target.angle = angle; + }, + + /** + * Set the cursor type of the canvas element + * @param {String} value Cursor type of the canvas element. + * @see http://www.w3.org/TR/css3-ui/#cursor + */ + setCursor: function (value) { + this.upperCanvasEl.style.cursor = value; + }, + + /** + * @private + */ + _resetObjectTransform: function (target) { + target.scaleX = 1; + target.scaleY = 1; + target.setAngle(0); + }, + + /** + * @private + */ + _drawSelection: function () { + var ctx = this.contextTop, + groupSelector = this._groupSelector, + left = groupSelector.left, + top = groupSelector.top, + aleft = abs(left), + atop = abs(top); + + ctx.fillStyle = this.selectionColor; + + ctx.fillRect( + groupSelector.ex - ((left > 0) ? 0 : -left), + groupSelector.ey - ((top > 0) ? 0 : -top), + aleft, + atop + ); + + ctx.lineWidth = this.selectionLineWidth; + ctx.strokeStyle = this.selectionBorderColor; + + // selection border + if (this.selectionDashArray.length > 1) { + + var px = groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0: aleft), + py = groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0: atop); + + ctx.beginPath(); + + fabric.util.drawDashedLine(ctx, px, py, px + aleft, py, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px, py + atop - 1, px + aleft, py + atop - 1, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px, py, px, py + atop, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px + aleft - 1, py, px + aleft - 1, py + atop, this.selectionDashArray); + + ctx.closePath(); + ctx.stroke(); + } + else { + ctx.strokeRect( + groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft), + groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop), + aleft, + atop + ); + } + }, + + /** + * @private + */ + _isLastRenderedObject: function(e) { + return ( + this.controlsAboveOverlay && + this.lastRenderedObjectWithControlsAboveOverlay && + this.lastRenderedObjectWithControlsAboveOverlay.visible && + this.containsPoint(e, this.lastRenderedObjectWithControlsAboveOverlay) && + this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e, true))); + }, + + /** + * Method that determines what object we are clicking on + * @param {Event} e mouse event + * @param {Boolean} skipGroup when true, group is skipped and only objects are traversed through + */ + findTarget: function (e, skipGroup) { + if (this.skipTargetFind) return; + + if (this._isLastRenderedObject(e)) { + return this.lastRenderedObjectWithControlsAboveOverlay; + } + + // first check current group (if one exists) + var activeGroup = this.getActiveGroup(); + if (activeGroup && !skipGroup && this.containsPoint(e, activeGroup)) { + return activeGroup; + } + + var target = this._searchPossibleTargets(e); + this._fireOverOutEvents(target); + + return target; + }, + + /** + * @private + */ + _fireOverOutEvents: function(target) { + if (target) { + if (this._hoveredTarget !== target) { + this.fire('mouse:over', { target: target }); + target.fire('mouseover'); + if (this._hoveredTarget) { + this.fire('mouse:out', { target: this._hoveredTarget }); + this._hoveredTarget.fire('mouseout'); + } + this._hoveredTarget = target; + } + } + else if (this._hoveredTarget) { + this.fire('mouse:out', { target: this._hoveredTarget }); + this._hoveredTarget.fire('mouseout'); + this._hoveredTarget = null; + } + }, + + /** + * @private + */ + _checkTarget: function(e, obj, pointer) { + if (obj && + obj.visible && + obj.evented && + this.containsPoint(e, obj)){ + if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) { + var isTransparent = this.isTargetTransparent(obj, pointer.x, pointer.y); + if (!isTransparent) { + return true; + } + } + else { + return true; + } + } + }, + + /** + * @private + */ + _searchPossibleTargets: function(e) { + + // Cache all targets where their bounding box contains point. + var target, + pointer = this.getPointer(e, true), + i = this._objects.length; + + while (i--) { + if (this._checkTarget(e, this._objects[i], pointer)){ + this.relatedTarget = this._objects[i]; + target = this._objects[i]; + break; + } + } + + return target; + }, + + /** + * Returns pointer coordinates relative to canvas. + * @param {Event} e + * @return {Object} object with "x" and "y" number values + */ + getPointer: function (e, ignoreZoom, upperCanvasEl) { + if (!upperCanvasEl) { + upperCanvasEl = this.upperCanvasEl; + } + var pointer = getPointer(e, upperCanvasEl), + bounds = upperCanvasEl.getBoundingClientRect(), + cssScale; + + pointer.x = pointer.x - this._offset.left; + pointer.y = pointer.y - this._offset.top; + if (!ignoreZoom) { + pointer = fabric.util.transformPoint( + pointer, + fabric.util.invertTransform(this.viewportTransform) + ); + } + + if (bounds.width === 0 || bounds.height === 0) { + // If bounds are not available (i.e. not visible), do not apply scale. + cssScale = { width: 1, height: 1 }; + } + else { + cssScale = { + width: upperCanvasEl.width / bounds.width, + height: upperCanvasEl.height / bounds.height + }; + } + return { + x: pointer.x * cssScale.width, + y: pointer.y * cssScale.height + }; + }, + + /** + * @private + * @param {HTMLElement|String} canvasEl Canvas element + * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized + */ + _createUpperCanvas: function () { + var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/, ''); + + this.upperCanvasEl = this._createCanvasElement(); + fabric.util.addClass(this.upperCanvasEl, 'upper-canvas ' + lowerCanvasClass); + + this.wrapperEl.appendChild(this.upperCanvasEl); + + this._copyCanvasStyle(this.lowerCanvasEl, this.upperCanvasEl); + this._applyCanvasStyle(this.upperCanvasEl); + this.contextTop = this.upperCanvasEl.getContext('2d'); + }, + + /** + * @private + */ + _createCacheCanvas: function () { + this.cacheCanvasEl = this._createCanvasElement(); + this.cacheCanvasEl.setAttribute('width', this.width); + this.cacheCanvasEl.setAttribute('height', this.height); + this.contextCache = this.cacheCanvasEl.getContext('2d'); + }, + + /** + * @private + * @param {Number} width + * @param {Number} height + */ + _initWrapperElement: function () { + this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', { + 'class': this.containerClass + }); + fabric.util.setStyle(this.wrapperEl, { + width: this.getWidth() + 'px', + height: this.getHeight() + 'px', + position: 'relative' + }); + fabric.util.makeElementUnselectable(this.wrapperEl); + }, + + /** + * @private + * @param {Element} element + */ + _applyCanvasStyle: function (element) { + var width = this.getWidth() || element.width, + height = this.getHeight() || element.height; + + fabric.util.setStyle(element, { + position: 'absolute', + width: width + 'px', + height: height + 'px', + left: 0, + top: 0 + }); + element.width = width; + element.height = height; + fabric.util.makeElementUnselectable(element); + }, + + /** + * Copys the the entire inline style from one element (fromEl) to another (toEl) + * @private + * @param {Element} fromEl Element style is copied from + * @param {Element} toEl Element copied style is applied to + */ + _copyCanvasStyle: function (fromEl, toEl) { + toEl.style.cssText = fromEl.style.cssText; + }, + + /** + * Returns context of canvas where object selection is drawn + * @return {CanvasRenderingContext2D} + */ + getSelectionContext: function() { + return this.contextTop; + }, + + /** + * Returns <canvas> element on which object selection is drawn + * @return {HTMLCanvasElement} + */ + getSelectionElement: function () { + return this.upperCanvasEl; + }, + + /** + * @private + * @param {Object} object + */ + _setActiveObject: function(object) { + if (this._activeObject) { + this._activeObject.set('active', false); + } + this._activeObject = object; + object.set('active', true); + }, + + /** + * Sets given object as the only active object on canvas + * @param {fabric.Object} object Object to set as an active one + * @param {Event} [e] Event (passed along when firing "object:selected") + * @return {fabric.Canvas} thisArg + * @chainable + */ + setActiveObject: function (object, e) { + this._setActiveObject(object); + this.renderAll(); + this.fire('object:selected', { target: object, e: e }); + object.fire('selected', { e: e }); + return this; + }, + + /** + * Returns currently active object + * @return {fabric.Object} active object + */ + getActiveObject: function () { + return this._activeObject; + }, + + /** + * @private + */ + _discardActiveObject: function() { + if (this._activeObject) { + this._activeObject.set('active', false); + } + this._activeObject = null; + }, + + /** + * Discards currently active object + * @return {fabric.Canvas} thisArg + * @chainable + */ + discardActiveObject: function (e) { + this._discardActiveObject(); + this.renderAll(); + this.fire('selection:cleared', { e: e }); + return this; + }, + + /** + * @private + * @param {fabric.Group} group + */ + _setActiveGroup: function(group) { + this._activeGroup = group; + if (group) { + group.set('active', true); + } + }, + + /** + * Sets active group to a speicified one + * @param {fabric.Group} group Group to set as a current one + * @return {fabric.Canvas} thisArg + * @chainable + */ + setActiveGroup: function (group, e) { + this._setActiveGroup(group); + if (group) { + this.fire('object:selected', { target: group, e: e }); + group.fire('selected', { e: e }); + } + return this; + }, + + /** + * Returns currently active group + * @return {fabric.Group} Current group + */ + getActiveGroup: function () { + return this._activeGroup; + }, + + /** + * @private + */ + _discardActiveGroup: function() { + var g = this.getActiveGroup(); + if (g) { + g.destroy(); + } + this.setActiveGroup(null); + }, + + /** + * Discards currently active group + * @return {fabric.Canvas} thisArg + */ + discardActiveGroup: function (e) { + this._discardActiveGroup(); + this.fire('selection:cleared', { e: e }); + return this; + }, + + /** + * Deactivates all objects on canvas, removing any active group or object + * @return {fabric.Canvas} thisArg + */ + deactivateAll: function () { + var allObjects = this.getObjects(), + i = 0, + len = allObjects.length; + for ( ; i < len; i++) { + allObjects[i].set('active', false); + } + this._discardActiveGroup(); + this._discardActiveObject(); + return this; + }, + + /** + * Deactivates all objects and dispatches appropriate events + * @return {fabric.Canvas} thisArg + */ + deactivateAllWithDispatch: function (e) { + var activeObject = this.getActiveGroup() || this.getActiveObject(); + if (activeObject) { + this.fire('before:selection:cleared', { target: activeObject, e: e }); + } + this.deactivateAll(); + if (activeObject) { + this.fire('selection:cleared', { e: e }); + } + return this; + }, + + /** + * Draws objects' controls (borders/controls) + * @param {CanvasRenderingContext2D} ctx Context to render controls on + */ + drawControls: function(ctx) { + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this._drawGroupControls(ctx, activeGroup); + } + else { + this._drawObjectsControls(ctx); + } + }, + + /** + * @private + */ + _drawGroupControls: function(ctx, activeGroup) { + activeGroup._renderControls(ctx); + }, + + /** + * @private + */ + _drawObjectsControls: function(ctx) { + for (var i = 0, len = this._objects.length; i < len; ++i) { + if (!this._objects[i] || !this._objects[i].active) continue; + this._objects[i]._renderControls(ctx); + this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i]; + } + } + }); + + // copying static properties manually to work around Opera's bug, + // where "prototype" property is enumerable and overrides existing prototype + for (var prop in fabric.StaticCanvas) { + if (prop !== 'prototype') { + fabric.Canvas[prop] = fabric.StaticCanvas[prop]; + } + } + + if (fabric.isTouchSupported) { + /** @ignore */ + fabric.Canvas.prototype._setCursorFromEvent = function() { }; + } + + /** + * @class fabric.Element + * @alias fabric.Canvas + * @deprecated Use {@link fabric.Canvas} instead. + * @constructor + */ + fabric.Element = fabric.Canvas; +})(); + + +(function(){ + + var cursorOffset = { + mt: 0, // n + tr: 1, // ne + mr: 2, // e + br: 3, // se + mb: 4, // s + bl: 5, // sw + ml: 6, // w + tl: 7 // nw + }, + addListener = fabric.util.addListener, + removeListener = fabric.util.removeListener; + + fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ { + + /** + * Map of cursor style values for each of the object controls + * @private + */ + cursorMap: [ + 'n-resize', + 'ne-resize', + 'e-resize', + 'se-resize', + 's-resize', + 'sw-resize', + 'w-resize', + 'nw-resize' + ], + + /** + * Adds mouse listeners to canvas + * @private + */ + _initEventListeners: function () { + + this._bindEvents(); + + addListener(fabric.window, 'resize', this._onResize); + + // mouse events + addListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); + addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + addListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel); + + // touch events + addListener(this.upperCanvasEl, 'touchstart', this._onMouseDown); + addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (typeof Event !== 'undefined' && 'add' in Event) { + Event.add(this.upperCanvasEl, 'gesture', this._onGesture); + Event.add(this.upperCanvasEl, 'drag', this._onDrag); + Event.add(this.upperCanvasEl, 'orientation', this._onOrientationChange); + Event.add(this.upperCanvasEl, 'shake', this._onShake); + } + }, + + /** + * @private + */ + _bindEvents: function() { + this._onMouseDown = this._onMouseDown.bind(this); + this._onMouseMove = this._onMouseMove.bind(this); + this._onMouseUp = this._onMouseUp.bind(this); + this._onResize = this._onResize.bind(this); + this._onGesture = this._onGesture.bind(this); + this._onDrag = this._onDrag.bind(this); + this._onShake = this._onShake.bind(this); + this._onOrientationChange = this._onOrientationChange.bind(this); + this._onMouseWheel = this._onMouseWheel.bind(this); + }, + + /** + * Removes all event listeners + */ + removeListeners: function() { + removeListener(fabric.window, 'resize', this._onResize); + + removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); + removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + removeListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel); + + removeListener(this.upperCanvasEl, 'touchstart', this._onMouseDown); + removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (typeof Event !== 'undefined' && 'remove' in Event) { + Event.remove(this.upperCanvasEl, 'gesture', this._onGesture); + Event.remove(this.upperCanvasEl, 'drag', this._onDrag); + Event.remove(this.upperCanvasEl, 'orientation', this._onOrientationChange); + Event.remove(this.upperCanvasEl, 'shake', this._onShake); + } + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js gesture + * @param {Event} [self] Inner Event object + */ + _onGesture: function(e, s) { + this.__onTransformGesture && this.__onTransformGesture(e, s); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js drag + * @param {Event} [self] Inner Event object + */ + _onDrag: function(e, s) { + this.__onDrag && this.__onDrag(e, s); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js wheel event + * @param {Event} [self] Inner Event object + */ + _onMouseWheel: function(e, s) { + this.__onMouseWheel && this.__onMouseWheel(e, s); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js orientation change + * @param {Event} [self] Inner Event object + */ + _onOrientationChange: function(e,s) { + this.__onOrientationChange && this.__onOrientationChange(e,s); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js shake + * @param {Event} [self] Inner Event object + */ + _onShake: function(e,s) { + this.__onShake && this.__onShake(e,s); + }, + + /** + * @private + * @param {Event} e Event object fired on mousedown + */ + _onMouseDown: function (e) { + this.__onMouseDown(e); + + addListener(fabric.document, 'touchend', this._onMouseUp); + addListener(fabric.document, 'touchmove', this._onMouseMove); + + removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (e.type === 'touchstart') { + // Unbind mousedown to prevent double triggers from touch devices + removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); + } + else { + addListener(fabric.document, 'mouseup', this._onMouseUp); + addListener(fabric.document, 'mousemove', this._onMouseMove); + } + }, + + /** + * @private + * @param {Event} e Event object fired on mouseup + */ + _onMouseUp: function (e) { + this.__onMouseUp(e); + + removeListener(fabric.document, 'mouseup', this._onMouseUp); + removeListener(fabric.document, 'touchend', this._onMouseUp); + + removeListener(fabric.document, 'mousemove', this._onMouseMove); + removeListener(fabric.document, 'touchmove', this._onMouseMove); + + addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (e.type === 'touchend') { + // Wait 400ms before rebinding mousedown to prevent double triggers + // from touch devices + var _this = this; + setTimeout(function() { + addListener(_this.upperCanvasEl, 'mousedown', _this._onMouseDown); + }, 400); + } + }, + + /** + * @private + * @param {Event} e Event object fired on mousemove + */ + _onMouseMove: function (e) { + !this.allowTouchScrolling && e.preventDefault && e.preventDefault(); + this.__onMouseMove(e); + }, + + /** + * @private + */ + _onResize: function () { + this.calcOffset(); + }, + + /** + * Decides whether the canvas should be redrawn in mouseup and mousedown events. + * @private + * @param {Object} target + * @param {Object} pointer + */ + _shouldRender: function(target, pointer) { + var activeObject = this.getActiveGroup() || this.getActiveObject(); + + return !!( + (target && ( + target.isMoving || + target !== activeObject)) + || + (!target && !!activeObject) + || + (!target && !activeObject && !this._groupSelector) + || + (pointer && + this._previousPointer && + this.selection && ( + pointer.x !== this._previousPointer.x || + pointer.y !== this._previousPointer.y)) + ); + }, + + /** + * Method that defines the actions when mouse is released on canvas. + * The method resets the currentTransform parameters, store the image corner + * position in the image object and render the canvas on top. + * @private + * @param {Event} e Event object fired on mouseup + */ + __onMouseUp: function (e) { + var target; + + if (this.isDrawingMode && this._isCurrentlyDrawing) { + this._onMouseUpInDrawingMode(e); + return; + } + + if (this._currentTransform) { + this._finalizeCurrentTransform(); + target = this._currentTransform.target; + } + else { + target = this.findTarget(e, true); + } + + var shouldRender = this._shouldRender(target, this.getPointer(e)); + + this._maybeGroupObjects(e); + + if (target) { + target.isMoving = false; + } + + shouldRender && this.renderAll(); + + this._handleCursorAndEvent(e, target); + }, + + _handleCursorAndEvent: function(e, target) { + this._setCursorFromEvent(e, target); + + // TODO: why are we doing this? + var _this = this; + setTimeout(function () { + _this._setCursorFromEvent(e, target); + }, 50); + + this.fire('mouse:up', { target: target, e: e }); + target && target.fire('mouseup', { e: e }); + }, + + /** + * @private + */ + _finalizeCurrentTransform: function() { + + var transform = this._currentTransform, + target = transform.target; + + if (target._scaling) { + target._scaling = false; + } + + target.setCoords(); + + // only fire :modified event if target coordinates were changed during mousedown-mouseup + if (this.stateful && target.hasStateChanged()) { + this.fire('object:modified', { target: target }); + target.fire('modified'); + } + + this._restoreOriginXY(target); + }, + + /** + * @private + * @param {Object} target Object to restore + */ + _restoreOriginXY: function(target) { + if (this._previousOriginX && this._previousOriginY) { + + var originPoint = target.translateToOriginPoint( + target.getCenterPoint(), + this._previousOriginX, + this._previousOriginY); + + target.originX = this._previousOriginX; + target.originY = this._previousOriginY; + + target.left = originPoint.x; + target.top = originPoint.y; + + this._previousOriginX = null; + this._previousOriginY = null; + } + }, + + /** + * @private + * @param {Event} e Event object fired on mousedown + */ + _onMouseDownInDrawingMode: function(e) { + this._isCurrentlyDrawing = true; + this.discardActiveObject(e).renderAll(); + if (this.clipTo) { + fabric.util.clipContext(this, this.contextTop); + } + var ivt = fabric.util.invertTransform(this.viewportTransform), + pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt); + this.freeDrawingBrush.onMouseDown(pointer); + this.fire('mouse:down', { e: e }); + }, + + /** + * @private + * @param {Event} e Event object fired on mousemove + */ + _onMouseMoveInDrawingMode: function(e) { + if (this._isCurrentlyDrawing) { + var ivt = fabric.util.invertTransform(this.viewportTransform), + pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt); + this.freeDrawingBrush.onMouseMove(pointer); + } + this.setCursor(this.freeDrawingCursor); + this.fire('mouse:move', { e: e }); + }, + + /** + * @private + * @param {Event} e Event object fired on mouseup + */ + _onMouseUpInDrawingMode: function(e) { + this._isCurrentlyDrawing = false; + if (this.clipTo) { + this.contextTop.restore(); + } + this.freeDrawingBrush.onMouseUp(); + this.fire('mouse:up', { e: e }); + }, + + /** + * Method that defines the actions when mouse is clic ked on canvas. + * The method inits the currentTransform parameters and renders all the + * canvas so the current image can be placed on the top canvas and the rest + * in on the container one. + * @private + * @param {Event} e Event object fired on mousedown + */ + __onMouseDown: function (e) { + + // accept only left clicks + var isLeftClick = 'which' in e ? e.which === 1 : e.button === 1; + if (!isLeftClick && !fabric.isTouchSupported) return; + + if (this.isDrawingMode) { + this._onMouseDownInDrawingMode(e); + return; + } + + // ignore if some object is being transformed at this moment + if (this._currentTransform) return; + + var target = this.findTarget(e), + pointer = this.getPointer(e, true); + + // save pointer for check in __onMouseUp event + this._previousPointer = pointer; + + var shouldRender = this._shouldRender(target, pointer), + shouldGroup = this._shouldGroup(e, target); + + if (this._shouldClearSelection(e, target)) { + this._clearSelection(e, target, pointer); + } + else if (shouldGroup) { + this._handleGrouping(e, target); + target = this.getActiveGroup(); + } + + if (target && target.selectable && !shouldGroup) { + this._beforeTransform(e, target); + this._setupCurrentTransform(e, target); + } + // we must renderAll so that active image is placed on the top canvas + shouldRender && this.renderAll(); + + this.fire('mouse:down', { target: target, e: e }); + target && target.fire('mousedown', { e: e }); + }, + + /** + * @private + */ + _beforeTransform: function(e, target) { + var corner; + + this.stateful && target.saveState(); + + // determine if it's a drag or rotate case + if ((corner = target._findTargetCorner(this.getPointer(e)))) { + this.onBeforeScaleRotate(target); + } + + if (target !== this.getActiveGroup() && target !== this.getActiveObject()) { + this.deactivateAll(); + this.setActiveObject(target, e); + } + }, + + /** + * @private + */ + _clearSelection: function(e, target, pointer) { + this.deactivateAllWithDispatch(e); + + if (target && target.selectable) { + this.setActiveObject(target, e); + } + else if (this.selection) { + this._groupSelector = { + ex: pointer.x, + ey: pointer.y, + top: 0, + left: 0 + }; + } + }, + + /** + * @private + * @param {Object} target Object for that origin is set to center + */ + _setOriginToCenter: function(target) { + this._previousOriginX = this._currentTransform.target.originX; + this._previousOriginY = this._currentTransform.target.originY; + + var center = target.getCenterPoint(); + + target.originX = 'center'; + target.originY = 'center'; + + target.left = center.x; + target.top = center.y; + + this._currentTransform.left = target.left; + this._currentTransform.top = target.top; + }, + + /** + * @private + * @param {Object} target Object for that center is set to origin + */ + _setCenterToOrigin: function(target) { + var originPoint = target.translateToOriginPoint( + target.getCenterPoint(), + this._previousOriginX, + this._previousOriginY); + + target.originX = this._previousOriginX; + target.originY = this._previousOriginY; + + target.left = originPoint.x; + target.top = originPoint.y; + + this._previousOriginX = null; + this._previousOriginY = null; + }, + + /** + * Method that defines the actions when mouse is hovering the canvas. + * The currentTransform parameter will definde whether the user is rotating/scaling/translating + * an image or neither of them (only hovering). A group selection is also possible and would cancel + * all any other type of action. + * In case of an image transformation only the top canvas will be rendered. + * @private + * @param {Event} e Event object fired on mousemove + */ + __onMouseMove: function (e) { + + var target, pointer; + + if (this.isDrawingMode) { + this._onMouseMoveInDrawingMode(e); + return; + } + + var groupSelector = this._groupSelector; + + // We initially clicked in an empty area, so we draw a box for multiple selection + if (groupSelector) { + pointer = this.getPointer(e, true); + + groupSelector.left = pointer.x - groupSelector.ex; + groupSelector.top = pointer.y - groupSelector.ey; + + this.renderTop(); + } + else if (!this._currentTransform) { + + target = this.findTarget(e); + + if (!target || target && !target.selectable) { + this.setCursor(this.defaultCursor); + } + else { + this._setCursorFromEvent(e, target); + } + } + else { + this._transformObject(e); + } + + this.fire('mouse:move', { target: target, e: e }); + target && target.fire('mousemove', { e: e }); + }, + + /** + * @private + * @param {Event} e Event fired on mousemove + */ + _transformObject: function(e) { + var pointer = this.getPointer(e), + transform = this._currentTransform; + + transform.reset = false, + transform.target.isMoving = true; + + this._beforeScaleTransform(e, transform); + this._performTransformAction(e, transform, pointer); + + this.renderAll(); + }, + + /** + * @private + */ + _performTransformAction: function(e, transform, pointer) { + var x = pointer.x, + y = pointer.y, + target = transform.target, + action = transform.action; + + if (action === 'rotate') { + this._rotateObject(x, y); + this._fire('rotating', target, e); + } + else if (action === 'scale') { + this._onScale(e, transform, x, y); + this._fire('scaling', target, e); + } + else if (action === 'scaleX') { + this._scaleObject(x, y, 'x'); + this._fire('scaling', target, e); + } + else if (action === 'scaleY') { + this._scaleObject(x, y, 'y'); + this._fire('scaling', target, e); + } + else { + this._translateObject(x, y); + this._fire('moving', target, e); + this.setCursor(this.moveCursor); + } + }, + + /** + * @private + */ + _fire: function(eventName, target, e) { + this.fire('object:' + eventName, { target: target, e: e }); + target.fire(eventName, { e: e }); + }, + + /** + * @private + */ + _beforeScaleTransform: function(e, transform) { + if (transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') { + var centerTransform = this._shouldCenterTransform(e, transform.target); + + // Switch from a normal resize to center-based + if ((centerTransform && (transform.originX !== 'center' || transform.originY !== 'center')) || + // Switch from center-based resize to normal one + (!centerTransform && transform.originX === 'center' && transform.originY === 'center') + ) { + this._resetCurrentTransform(e); + transform.reset = true; + } + } + }, + + /** + * @private + */ + _onScale: function(e, transform, x, y) { + // rotate object only if shift key is not pressed + // and if it is not a group we are transforming + if ((e.shiftKey || this.uniScaleTransform) && !transform.target.get('lockUniScaling')) { + transform.currentAction = 'scale'; + this._scaleObject(x, y); + } + else { + // Switch from a normal resize to proportional + if (!transform.reset && transform.currentAction === 'scale') { + this._resetCurrentTransform(e, transform.target); + } + + transform.currentAction = 'scaleEqually'; + this._scaleObject(x, y, 'equally'); + } + }, + + /** + * Sets the cursor depending on where the canvas is being hovered. + * Note: very buggy in Opera + * @param {Event} e Event object + * @param {Object} target Object that the mouse is hovering, if so. + */ + _setCursorFromEvent: function (e, target) { + if (!target || !target.selectable) { + this.setCursor(this.defaultCursor); + return false; + } + else { + var activeGroup = this.getActiveGroup(), + // only show proper corner when group selection is not active + corner = target._findTargetCorner + && (!activeGroup || !activeGroup.contains(target)) + && target._findTargetCorner(this.getPointer(e, true)); + + if (!corner) { + this.setCursor(target.hoverCursor || this.hoverCursor); + } + else { + this._setCornerCursor(corner, target); + } + } + return true; + }, + + /** + * @private + */ + _setCornerCursor: function(corner, target) { + if (corner in cursorOffset) { + this.setCursor(this._getRotatedCornerCursor(corner, target)); + } + else if (corner === 'mtr' && target.hasRotatingPoint) { + this.setCursor(this.rotationCursor); + } + else { + this.setCursor(this.defaultCursor); + return false; + } + }, + + /** + * @private + */ + _getRotatedCornerCursor: function(corner, target) { + var n = Math.round((target.getAngle() % 360) / 45); + + if (n < 0) { + n += 8; // full circle ahead + } + n += cursorOffset[corner]; + // normalize n to be from 0 to 7 + n %= 8; + + return this.cursorMap[n]; + } + }); +})(); + + +(function(){ + + var min = Math.min, + max = Math.max; + + fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ { + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + * @return {Boolean} + */ + _shouldGroup: function(e, target) { + var activeObject = this.getActiveObject(); + return e.shiftKey && + (this.getActiveGroup() || (activeObject && activeObject !== target)) + && this.selection; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _handleGrouping: function (e, target) { + + if (target === this.getActiveGroup()) { + + // if it's a group, find target again, this time skipping group + target = this.findTarget(e, true); + + // if even object is not found, bail out + if (!target || target.isType('group')) { + return; + } + } + if (this.getActiveGroup()) { + this._updateActiveGroup(target, e); + } + else { + this._createActiveGroup(target, e); + } + + if (this._activeGroup) { + this._activeGroup.saveCoords(); + } + }, + + /** + * @private + */ + _updateActiveGroup: function(target, e) { + var activeGroup = this.getActiveGroup(); + + if (activeGroup.contains(target)) { + + activeGroup.removeWithUpdate(target); + this._resetObjectTransform(activeGroup); + target.set('active', false); + + if (activeGroup.size() === 1) { + // remove group alltogether if after removal it only contains 1 object + this.discardActiveGroup(e); + // activate last remaining object + this.setActiveObject(activeGroup.item(0)); + return; + } + } + else { + activeGroup.addWithUpdate(target); + this._resetObjectTransform(activeGroup); + } + this.fire('selection:created', { target: activeGroup, e: e }); + activeGroup.set('active', true); + }, + + /** + * @private + */ + _createActiveGroup: function(target, e) { + + if (this._activeObject && target !== this._activeObject) { + + var group = this._createGroup(target); + group.addWithUpdate(); + + this.setActiveGroup(group); + this._activeObject = null; + + this.fire('selection:created', { target: group, e: e }); + } + + target.set('active', true); + }, + + /** + * @private + * @param {Object} target + */ + _createGroup: function(target) { + + var objects = this.getObjects(), + isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target), + groupObjects = isActiveLower + ? [ this._activeObject, target ] + : [ target, this._activeObject ]; + + return new fabric.Group(groupObjects, { + originX: 'center', + originY: 'center', + canvas: this + }); + }, + + /** + * @private + * @param {Event} e mouse event + */ + _groupSelectedObjects: function (e) { + + var group = this._collectObjects(); + + // do not create group for 1 element only + if (group.length === 1) { + this.setActiveObject(group[0], e); + } + else if (group.length > 1) { + group = new fabric.Group(group.reverse(), { + originX: 'center', + originY: 'center', + canvas: this + }); + group.addWithUpdate(); + this.setActiveGroup(group, e); + group.saveCoords(); + this.fire('selection:created', { target: group }); + this.renderAll(); + } + }, + + /** + * @private + */ + _collectObjects: function() { + var group = [ ], + currentObject, + x1 = this._groupSelector.ex, + y1 = this._groupSelector.ey, + x2 = x1 + this._groupSelector.left, + y2 = y1 + this._groupSelector.top, + selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)), + selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)), + isClick = x1 === x2 && y1 === y2; + + for (var i = this._objects.length; i--; ) { + currentObject = this._objects[i]; + + if (!currentObject || !currentObject.selectable || !currentObject.visible) continue; + + if (currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) || + currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) || + currentObject.containsPoint(selectionX1Y1) || + currentObject.containsPoint(selectionX2Y2) + ) { + currentObject.set('active', true); + group.push(currentObject); + + // only add one object if it's a click + if (isClick) break; + } + } + + return group; + }, + + /** + * @private + */ + _maybeGroupObjects: function(e) { + if (this.selection && this._groupSelector) { + this._groupSelectedObjects(e); + } + + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + activeGroup.setObjectsCoords().setCoords(); + activeGroup.isMoving = false; + this.setCursor(this.defaultCursor); + } + + // clear selection and current transformation + this._groupSelector = null; + this._currentTransform = null; + } + }); + +})(); + + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately + * @param {Object} [options] Options object + * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png" + * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg. + * @param {Number} [options.multiplier=1] Multiplier to scale by + * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14 + * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14 + * @param {Number} [options.width] Cropping width. Introduced in v1.2.14 + * @param {Number} [options.height] Cropping height. Introduced in v1.2.14 + * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format + * @see {@link http://jsfiddle.net/fabricjs/NfZVb/|jsFiddle demo} + * @example Generate jpeg dataURL with lower quality + * var dataURL = canvas.toDataURL({ + * format: 'jpeg', + * quality: 0.8 + * }); + * @example Generate cropped png dataURL (clipping of canvas) + * var dataURL = canvas.toDataURL({ + * format: 'png', + * left: 100, + * top: 100, + * width: 200, + * height: 200 + * }); + * @example Generate double scaled png dataURL + * var dataURL = canvas.toDataURL({ + * format: 'png', + * multiplier: 2 + * }); + */ + toDataURL: function (options) { + options || (options = { }); + + var format = options.format || 'png', + quality = options.quality || 1, + multiplier = options.multiplier || 1, + cropping = { + left: options.left, + top: options.top, + width: options.width, + height: options.height + }; + + if (multiplier !== 1) { + return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier); + } + else { + return this.__toDataURL(format, quality, cropping); + } + }, + + /** + * @private + */ + __toDataURL: function(format, quality, cropping) { + + this.renderAll(true); + + var canvasEl = this.upperCanvasEl || this.lowerCanvasEl, + croppedCanvasEl = this.__getCroppedCanvas(canvasEl, cropping); + + // to avoid common confusion https://github.com/kangax/fabric.js/issues/806 + if (format === 'jpg') { + format = 'jpeg'; + } + + var data = (fabric.StaticCanvas.supports('toDataURLWithQuality')) + ? (croppedCanvasEl || canvasEl).toDataURL('image/' + format, quality) + : (croppedCanvasEl || canvasEl).toDataURL('image/' + format); + + this.contextTop && this.clearContext(this.contextTop); + this.renderAll(); + + if (croppedCanvasEl) { + croppedCanvasEl = null; + } + + return data; + }, + + /** + * @private + */ + __getCroppedCanvas: function(canvasEl, cropping) { + + var croppedCanvasEl, + croppedCtx, + shouldCrop = 'left' in cropping || + 'top' in cropping || + 'width' in cropping || + 'height' in cropping; + + if (shouldCrop) { + + croppedCanvasEl = fabric.util.createCanvasElement(); + croppedCtx = croppedCanvasEl.getContext('2d'); + + croppedCanvasEl.width = cropping.width || this.width; + croppedCanvasEl.height = cropping.height || this.height; + + croppedCtx.drawImage(canvasEl, -cropping.left || 0, -cropping.top || 0); + } + + return croppedCanvasEl; + }, + + /** + * @private + */ + __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) { + + var origWidth = this.getWidth(), + origHeight = this.getHeight(), + scaledWidth = origWidth * multiplier, + scaledHeight = origHeight * multiplier, + activeObject = this.getActiveObject(), + activeGroup = this.getActiveGroup(), + + ctx = this.contextTop || this.contextContainer; + + if (multiplier > 1) { + this.setWidth(scaledWidth).setHeight(scaledHeight); + } + ctx.scale(multiplier, multiplier); + + if (cropping.left) { + cropping.left *= multiplier; + } + if (cropping.top) { + cropping.top *= multiplier; + } + if (cropping.width) { + cropping.width *= multiplier; + } + else if (multiplier < 1) { + cropping.width = scaledWidth; + } + if (cropping.height) { + cropping.height *= multiplier; + } + else if (multiplier < 1) { + cropping.height = scaledHeight; + } + + if (activeGroup) { + // not removing group due to complications with restoring it with correct state afterwords + this._tempRemoveBordersControlsFromGroup(activeGroup); + } + else if (activeObject && this.deactivateAll) { + this.deactivateAll(); + } + + this.renderAll(true); + + var data = this.__toDataURL(format, quality, cropping); + + // restoring width, height for `renderAll` to draw + // background properly (while context is scaled) + this.width = origWidth; + this.height = origHeight; + + ctx.scale(1 / multiplier, 1 / multiplier); + this.setWidth(origWidth).setHeight(origHeight); + + if (activeGroup) { + this._restoreBordersControlsOnGroup(activeGroup); + } + else if (activeObject && this.setActiveObject) { + this.setActiveObject(activeObject); + } + + this.contextTop && this.clearContext(this.contextTop); + this.renderAll(); + + return data; + }, + + /** + * Exports canvas element to a dataurl image (allowing to change image size via multiplier). + * @deprecated since 1.0.13 + * @param {String} format (png|jpeg) + * @param {Number} multiplier + * @param {Number} quality (0..1) + * @return {String} + */ + toDataURLWithMultiplier: function (format, multiplier, quality) { + return this.toDataURL({ + format: format, + multiplier: multiplier, + quality: quality + }); + }, + + /** + * @private + */ + _tempRemoveBordersControlsFromGroup: function(group) { + group.origHasControls = group.hasControls; + group.origBorderColor = group.borderColor; + + group.hasControls = true; + group.borderColor = 'rgba(0,0,0,0)'; + + group.forEachObject(function(o) { + o.origBorderColor = o.borderColor; + o.borderColor = 'rgba(0,0,0,0)'; + }); + }, + + /** + * @private + */ + _restoreBordersControlsOnGroup: function(group) { + group.hideControls = group.origHideControls; + group.borderColor = group.origBorderColor; + + group.forEachObject(function(o) { + o.borderColor = o.origBorderColor; + delete o.origBorderColor; + }); + } +}); + + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Populates canvas with data from the specified dataless JSON. + * JSON format must conform to the one of {@link fabric.Canvas#toDatalessJSON} + * @deprecated since 1.2.2 + * @param {String|Object} json JSON string or object + * @param {Function} callback Callback, invoked when json is parsed + * and corresponding objects (e.g: {@link fabric.Image}) + * are initialized + * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created. + * @return {fabric.Canvas} instance + * @chainable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization} + */ + loadFromDatalessJSON: function (json, callback, reviver) { + return this.loadFromJSON(json, callback, reviver); + }, + + /** + * Populates canvas with data from the specified JSON. + * JSON format must conform to the one of {@link fabric.Canvas#toJSON} + * @param {String|Object} json JSON string or object + * @param {Function} callback Callback, invoked when json is parsed + * and corresponding objects (e.g: {@link fabric.Image}) + * are initialized + * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created. + * @return {fabric.Canvas} instance + * @chainable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization} + * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo} + * @example loadFromJSON + * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas)); + * @example loadFromJSON with reviver + * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) { + * // `o` = json object + * // `object` = fabric.Object instance + * // ... do some stuff ... + * }); + */ + loadFromJSON: function (json, callback, reviver) { + if (!json) return; + + // serialize if it wasn't already + var serialized = (typeof json === 'string') + ? JSON.parse(json) + : json; + + this.clear(); + + var _this = this; + this._enlivenObjects(serialized.objects, function () { + _this._setBgOverlay(serialized, callback); + }, reviver); + + return this; + }, + + /** + * @private + * @param {Object} serialized Object with background and overlay information + * @param {Function} callback Invoked after all background and overlay images/patterns loaded + */ + _setBgOverlay: function(serialized, callback) { + var _this = this, + loaded = { + backgroundColor: false, + overlayColor: false, + backgroundImage: false, + overlayImage: false + }; + + if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) { + callback && callback(); + return; + } + + var cbIfLoaded = function () { + if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) { + _this.renderAll(); + callback && callback(); + } + }; + + this.__setBgOverlay('backgroundImage', serialized.backgroundImage, loaded, cbIfLoaded); + this.__setBgOverlay('overlayImage', serialized.overlayImage, loaded, cbIfLoaded); + this.__setBgOverlay('backgroundColor', serialized.background, loaded, cbIfLoaded); + this.__setBgOverlay('overlayColor', serialized.overlay, loaded, cbIfLoaded); + + cbIfLoaded(); + }, + + /** + * @private + * @param {String} property Property to set (backgroundImage, overlayImage, backgroundColor, overlayColor) + * @param {(Object|String)} value Value to set + * @param {Object} loaded Set loaded property to true if property is set + * @param {Object} callback Callback function to invoke after property is set + */ + __setBgOverlay: function(property, value, loaded, callback) { + var _this = this; + + if (!value) { + loaded[property] = true; + return; + } + + if (property === 'backgroundImage' || property === 'overlayImage') { + fabric.Image.fromObject(value, function(img) { + _this[property] = img; + loaded[property] = true; + callback && callback(); + }); + } + else { + this['set' + fabric.util.string.capitalize(property, true)](value, function() { + loaded[property] = true; + callback && callback(); + }); + } + }, + + /** + * @private + * @param {Array} objects + * @param {Function} callback + * @param {Function} [reviver] + */ + _enlivenObjects: function (objects, callback, reviver) { + var _this = this; + + if (!objects || objects.length === 0) { + callback && callback(); + return; + } + + var renderOnAddRemove = this.renderOnAddRemove; + this.renderOnAddRemove = false; + + fabric.util.enlivenObjects(objects, function(enlivenedObjects) { + enlivenedObjects.forEach(function(obj, index) { + _this.insertAt(obj, index, true); + }); + + _this.renderOnAddRemove = renderOnAddRemove; + callback && callback(); + }, null, reviver); + }, + + /** + * @private + * @param {String} format + * @param {Function} callback + */ + _toDataURL: function (format, callback) { + this.clone(function (clone) { + callback(clone.toDataURL(format)); + }); + }, + + /** + * @private + * @param {String} format + * @param {Number} multiplier + * @param {Function} callback + */ + _toDataURLWithMultiplier: function (format, multiplier, callback) { + this.clone(function (clone) { + callback(clone.toDataURLWithMultiplier(format, multiplier)); + }); + }, + + /** + * Clones canvas instance + * @param {Object} [callback] Receives cloned instance as a first argument + * @param {Array} [properties] Array of properties to include in the cloned canvas and children + */ + clone: function (callback, properties) { + var data = JSON.stringify(this.toJSON(properties)); + this.cloneWithoutData(function(clone) { + clone.loadFromJSON(data, function() { + callback && callback(clone); + }); + }); + }, + + /** + * Clones canvas instance without cloning existing data. + * This essentially copies canvas dimensions, clipping properties, etc. + * but leaves data empty (so that you can populate it with your own) + * @param {Object} [callback] Receives cloned instance as a first argument + */ + cloneWithoutData: function(callback) { + var el = fabric.document.createElement('canvas'); + + el.width = this.getWidth(); + el.height = this.getHeight(); + + var clone = new fabric.Canvas(el); + clone.clipTo = this.clipTo; + if (this.backgroundImage) { + clone.setBackgroundImage(this.backgroundImage.src, function() { + clone.renderAll(); + callback && callback(clone); + }); + clone.backgroundImageOpacity = this.backgroundImageOpacity; + clone.backgroundImageStretch = this.backgroundImageStretch; + } + else { + callback && callback(clone); + } + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + toFixed = fabric.util.toFixed, + capitalize = fabric.util.string.capitalize, + degreesToRadians = fabric.util.degreesToRadians, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Object) { + return; + } + + /** + * Root object class from which all 2d shape classes inherit from + * @class fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#objects} + * @see {@link fabric.Object#initialize} for constructor definition + * + * @fires added + * @fires removed + * + * @fires selected + * @fires modified + * @fires rotating + * @fires scaling + * @fires moving + * + * @fires mousedown + * @fires mouseup + */ + fabric.Object = fabric.util.createClass(/** @lends fabric.Object.prototype */ { + + /** + * Retrieves object's {@link fabric.Object#clipTo|clipping function} + * @method getClipTo + * @memberOf fabric.Object.prototype + * @return {Function} + */ + + /** + * Sets object's {@link fabric.Object#clipTo|clipping function} + * @method setClipTo + * @memberOf fabric.Object.prototype + * @param {Function} clipTo Clipping function + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#transformMatrix|transformMatrix} + * @method getTransformMatrix + * @memberOf fabric.Object.prototype + * @return {Array} transformMatrix + */ + + /** + * Sets object's {@link fabric.Object#transformMatrix|transformMatrix} + * @method setTransformMatrix + * @memberOf fabric.Object.prototype + * @param {Array} transformMatrix + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#visible|visible} state + * @method getVisible + * @memberOf fabric.Object.prototype + * @return {Boolean} True if visible + */ + + /** + * Sets object's {@link fabric.Object#visible|visible} state + * @method setVisible + * @memberOf fabric.Object.prototype + * @param {Boolean} value visible value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#shadow|shadow} + * @method getShadow + * @memberOf fabric.Object.prototype + * @return {Object} Shadow instance + */ + + /** + * Retrieves object's {@link fabric.Object#stroke|stroke} + * @method getStroke + * @memberOf fabric.Object.prototype + * @return {String} stroke value + */ + + /** + * Sets object's {@link fabric.Object#stroke|stroke} + * @method setStroke + * @memberOf fabric.Object.prototype + * @param {String} value stroke value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#strokeWidth|strokeWidth} + * @method getStrokeWidth + * @memberOf fabric.Object.prototype + * @return {Number} strokeWidth value + */ + + /** + * Sets object's {@link fabric.Object#strokeWidth|strokeWidth} + * @method setStrokeWidth + * @memberOf fabric.Object.prototype + * @param {Number} value strokeWidth value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#originX|originX} + * @method getOriginX + * @memberOf fabric.Object.prototype + * @return {String} originX value + */ + + /** + * Sets object's {@link fabric.Object#originX|originX} + * @method setOriginX + * @memberOf fabric.Object.prototype + * @param {String} value originX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#originY|originY} + * @method getOriginY + * @memberOf fabric.Object.prototype + * @return {String} originY value + */ + + /** + * Sets object's {@link fabric.Object#originY|originY} + * @method setOriginY + * @memberOf fabric.Object.prototype + * @param {String} value originY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#fill|fill} + * @method getFill + * @memberOf fabric.Object.prototype + * @return {String} Fill value + */ + + /** + * Sets object's {@link fabric.Object#fill|fill} + * @method setFill + * @memberOf fabric.Object.prototype + * @param {String} value Fill value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#opacity|opacity} + * @method getOpacity + * @memberOf fabric.Object.prototype + * @return {Number} Opacity value (0-1) + */ + + /** + * Sets object's {@link fabric.Object#opacity|opacity} + * @method setOpacity + * @memberOf fabric.Object.prototype + * @param {Number} value Opacity value (0-1) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#angle|angle} (in degrees) + * @method getAngle + * @memberOf fabric.Object.prototype + * @return {Number} + */ + + /** + * Sets object's {@link fabric.Object#angle|angle} + * @method setAngle + * @memberOf fabric.Object.prototype + * @param {Number} value Angle value (in degrees) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#top|top position} + * @method getTop + * @memberOf fabric.Object.prototype + * @return {Number} Top value (in pixels) + */ + + /** + * Sets object's {@link fabric.Object#top|top position} + * @method setTop + * @memberOf fabric.Object.prototype + * @param {Number} value Top value (in pixels) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#left|left position} + * @method getLeft + * @memberOf fabric.Object.prototype + * @return {Number} Left value (in pixels) + */ + + /** + * Sets object's {@link fabric.Object#left|left position} + * @method setLeft + * @memberOf fabric.Object.prototype + * @param {Number} value Left value (in pixels) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#scaleX|scaleX} value + * @method getScaleX + * @memberOf fabric.Object.prototype + * @return {Number} scaleX value + */ + + /** + * Sets object's {@link fabric.Object#scaleX|scaleX} value + * @method setScaleX + * @memberOf fabric.Object.prototype + * @param {Number} value scaleX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#scaleY|scaleY} value + * @method getScaleY + * @memberOf fabric.Object.prototype + * @return {Number} scaleY value + */ + + /** + * Sets object's {@link fabric.Object#scaleY|scaleY} value + * @method setScaleY + * @memberOf fabric.Object.prototype + * @param {Number} value scaleY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#flipX|flipX} value + * @method getFlipX + * @memberOf fabric.Object.prototype + * @return {Boolean} flipX value + */ + + /** + * Sets object's {@link fabric.Object#flipX|flipX} value + * @method setFlipX + * @memberOf fabric.Object.prototype + * @param {Boolean} value flipX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#flipY|flipY} value + * @method getFlipY + * @memberOf fabric.Object.prototype + * @return {Boolean} flipY value + */ + + /** + * Sets object's {@link fabric.Object#flipY|flipY} value + * @method setFlipY + * @memberOf fabric.Object.prototype + * @param {Boolean} value flipY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Type of an object (rect, circle, path, etc.) + * @type String + * @default + */ + type: 'object', + + /** + * Horizontal origin of transformation of an object (one of "left", "right", "center") + * @type String + * @default + */ + originX: 'left', + + /** + * Vertical origin of transformation of an object (one of "top", "bottom", "center") + * @type String + * @default + */ + originY: 'top', + + /** + * Top position of an object. Note that by default it's relative to object center. You can change this by setting originY={top/center/bottom} + * @type Number + * @default + */ + top: 0, + + /** + * Left position of an object. Note that by default it's relative to object center. You can change this by setting originX={left/center/right} + * @type Number + * @default + */ + left: 0, + + /** + * Object width + * @type Number + * @default + */ + width: 0, + + /** + * Object height + * @type Number + * @default + */ + height: 0, + + /** + * Object scale factor (horizontal) + * @type Number + * @default + */ + scaleX: 1, + + /** + * Object scale factor (vertical) + * @type Number + * @default + */ + scaleY: 1, + + /** + * When true, an object is rendered as flipped horizontally + * @type Boolean + * @default + */ + flipX: false, + + /** + * When true, an object is rendered as flipped vertically + * @type Boolean + * @default + */ + flipY: false, + + /** + * Opacity of an object + * @type Number + * @default + */ + opacity: 1, + + /** + * Angle of rotation of an object (in degrees) + * @type Number + * @default + */ + angle: 0, + + /** + * Size of object's controlling corners (in pixels) + * @type Number + * @default + */ + cornerSize: 12, + + /** + * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill) + * @type Boolean + * @default + */ + transparentCorners: true, + + /** + * Default cursor value used when hovering over this object on canvas + * @type String + * @default + */ + hoverCursor: null, + + /** + * Padding between object and its controlling borders (in pixels) + * @type Number + * @default + */ + padding: 0, + + /** + * Color of controlling borders of an object (when it's active) + * @type String + * @default + */ + borderColor: 'rgba(102,153,255,0.75)', + + /** + * Color of controlling corners of an object (when it's active) + * @type String + * @default + */ + cornerColor: 'rgba(102,153,255,0.5)', + + /** + * When true, this object will use center point as the origin of transformation + * when being scaled via the controls. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredScaling: false, + + /** + * When true, this object will use center point as the origin of transformation + * when being rotated via the controls. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredRotation: true, + + /** + * Color of object's fill + * @type String + * @default + */ + fill: 'rgb(0,0,0)', + + /** + * Fill rule used to fill an object + * @type String + * @default + */ + fillRule: 'source-over', + + /** + * Background color of an object. Only works with text objects at the moment. + * @type String + * @default + */ + backgroundColor: '', + + /** + * When defined, an object is rendered via stroke and this property specifies its color + * @type String + * @default + */ + stroke: null, + + /** + * Width of a stroke used to render this object + * @type Number + * @default + */ + strokeWidth: 1, + + /** + * Array specifying dash pattern of an object's stroke (stroke must be defined) + * @type Array + */ + strokeDashArray: null, + + /** + * Line endings style of an object's stroke (one of "butt", "round", "square") + * @type String + * @default + */ + strokeLineCap: 'butt', + + /** + * Corner style of an object's stroke (one of "bevil", "round", "miter") + * @type String + * @default + */ + strokeLineJoin: 'miter', + + /** + * Maximum miter length (used for strokeLineJoin = "miter") of an object's stroke + * @type Number + * @default + */ + strokeMiterLimit: 10, + + /** + * Shadow object representing shadow of this shape + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Opacity of object's controlling borders when object is active and moving + * @type Number + * @default + */ + borderOpacityWhenMoving: 0.4, + + /** + * Scale factor of object's controlling borders + * @type Number + * @default + */ + borderScaleFactor: 1, + + /** + * Transform matrix (similar to SVG's transform matrix) + * @type Array + */ + transformMatrix: null, + + /** + * Minimum allowed scale value of an object + * @type Number + * @default + */ + minScaleLimit: 0.01, + + /** + * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection). + * But events still fire on it. + * @type Boolean + * @default + */ + selectable: true, + + /** + * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4 + * @type Boolean + * @default + */ + evented: true, + + /** + * When set to `false`, an object is not rendered on canvas + * @type Boolean + * @default + */ + visible: true, + + /** + * When set to `false`, object's controls are not displayed and can not be used to manipulate object + * @type Boolean + * @default + */ + hasControls: true, + + /** + * When set to `false`, object's controlling borders are not rendered + * @type Boolean + * @default + */ + hasBorders: true, + + /** + * When set to `false`, object's controlling rotating point will not be visible or selectable + * @type Boolean + * @default + */ + hasRotatingPoint: true, + + /** + * Offset for object's controlling rotating point (when enabled via `hasRotatingPoint`) + * @type Number + * @default + */ + rotatingPointOffset: 40, + + /** + * When set to `true`, objects are "found" on canvas on per-pixel basis rather than according to bounding box + * @type Boolean + * @default + */ + perPixelTargetFind: false, + + /** + * When `false`, default object's values are not included in its serialization + * @type Boolean + * @default + */ + includeDefaultValues: true, + + /** + * Function that determines clipping of an object (context is passed as a first argument) + * Note that context origin is at the object's center point (not left/top corner) + * @type Function + */ + clipTo: null, + + /** + * When `true`, object horizontal movement is locked + * @type Boolean + * @default + */ + lockMovementX: false, + + /** + * When `true`, object vertical movement is locked + * @type Boolean + * @default + */ + lockMovementY: false, + + /** + * When `true`, object rotation is locked + * @type Boolean + * @default + */ + lockRotation: false, + + /** + * When `true`, object horizontal scaling is locked + * @type Boolean + * @default + */ + lockScalingX: false, + + /** + * When `true`, object vertical scaling is locked + * @type Boolean + * @default + */ + lockScalingY: false, + + /** + * When `true`, object non-uniform scaling is locked + * @type Boolean + * @default + */ + lockUniScaling: false, + + /** + * List of properties to consider when checking if state + * of an object is changed (fabric.Object#hasStateChanged) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: ( + 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' + + 'stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit ' + + 'angle opacity fill fillRule shadow clipTo visible backgroundColor' + ).split(' '), + + /** + * Constructor + * @param {Object} [options] Options object + */ + initialize: function(options) { + if (options) { + this.setOptions(options); + } + }, + + /** + * @private + */ + _initGradient: function(options) { + if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) { + this.set('fill', new fabric.Gradient(options.fill)); + } + }, + + /** + * @private + */ + _initPattern: function(options) { + if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) { + this.set('fill', new fabric.Pattern(options.fill)); + } + if (options.stroke && options.stroke.source && !(options.stroke instanceof fabric.Pattern)) { + this.set('stroke', new fabric.Pattern(options.stroke)); + } + }, + + /** + * @private + */ + _initClipping: function(options) { + if (!options.clipTo || typeof options.clipTo !== 'string') return; + + var functionBody = fabric.util.getFunctionBody(options.clipTo); + if (typeof functionBody !== 'undefined') { + this.clipTo = new Function('ctx', functionBody); + } + }, + + /** + * Sets object's properties from options + * @param {Object} [options] Options object + */ + setOptions: function(options) { + for (var prop in options) { + this.set(prop, options[prop]); + } + this._initGradient(options); + this._initPattern(options); + this._initClipping(options); + }, + + /** + * Transforms context when rendering an object + * @param {CanvasRenderingContext2D} ctx Context + * @param {Boolean} fromLeft When true, context is transformed to object's top/left corner. This is used when rendering text on Node + */ + transform: function(ctx, fromLeft) { + if (this.group) { + this.group.transform(ctx, fromLeft); + } + ctx.globalAlpha = this.opacity; + + var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint(); + ctx.translate(center.x, center.y); + ctx.rotate(degreesToRadians(this.angle)); + ctx.scale( + this.scaleX * (this.flipX ? -1 : 1), + this.scaleY * (this.flipY ? -1 : 1) + ); + }, + + /** + * Returns an object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + + var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, + + object = { + type: this.type, + originX: this.originX, + originY: this.originY, + left: toFixed(this.left, NUM_FRACTION_DIGITS), + top: toFixed(this.top, NUM_FRACTION_DIGITS), + width: toFixed(this.width, NUM_FRACTION_DIGITS), + height: toFixed(this.height, NUM_FRACTION_DIGITS), + fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill, + stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke, + strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS), + strokeDashArray: this.strokeDashArray, + strokeLineCap: this.strokeLineCap, + strokeLineJoin: this.strokeLineJoin, + strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS), + scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS), + scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS), + angle: toFixed(this.getAngle(), NUM_FRACTION_DIGITS), + flipX: this.flipX, + flipY: this.flipY, + opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS), + shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow, + visible: this.visible, + clipTo: this.clipTo && String(this.clipTo), + backgroundColor: this.backgroundColor + }; + + if (!this.includeDefaultValues) { + object = this._removeDefaultValues(object); + } + + fabric.util.populateWithProperties(this, object, propertiesToInclude); + + return object; + }, + + /** + * Returns (dataless) object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + // will be overwritten by subclasses + return this.toObject(propertiesToInclude); + }, + + /** + * @private + * @param {Object} object + */ + _removeDefaultValues: function(object) { + var prototype = fabric.util.getKlass(object.type).prototype, + stateProperties = prototype.stateProperties; + + stateProperties.forEach(function(prop) { + if (object[prop] === prototype[prop]) { + delete object[prop]; + } + }); + + return object; + }, + + /** + * Returns a string representation of an instance + * @return {String} + */ + toString: function() { + return '#'; + }, + + /** + * Basic getter + * @param {String} property Property name + * @return {Any} value of a property + */ + get: function(property) { + return this[property]; + }, + + /** + * @private + */ + _setObject: function(obj) { + for (var prop in obj) { + this._set(prop, obj[prop]); + } + }, + + /** + * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`. + * @param {String|Object} key Property name or object (if object, iterate over the object properties) + * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one) + * @return {fabric.Object} thisArg + * @chainable + */ + set: function(key, value) { + if (typeof key === 'object') { + this._setObject(key); + } + else { + if (typeof value === 'function' && key !== 'clipTo') { + this._set(key, value(this.get(key))); + } + else { + this._set(key, value); + } + } + return this; + }, + + /** + * @private + * @param {String} key + * @param {Any} value + * @return {fabric.Object} thisArg + */ + _set: function(key, value) { + var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY'); + + if (shouldConstrainValue) { + value = this._constrainScale(value); + } + if (key === 'scaleX' && value < 0) { + this.flipX = !this.flipX; + value *= -1; + } + else if (key === 'scaleY' && value < 0) { + this.flipY = !this.flipY; + value *= -1; + } + else if (key === 'width' || key === 'height') { + this.minScaleLimit = toFixed(Math.min(0.1, 1/Math.max(this.width, this.height)), 2); + } + else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) { + value = new fabric.Shadow(value); + } + + this[key] = value; + + return this; + }, + + /** + * Toggles specified property from `true` to `false` or from `false` to `true` + * @param {String} property Property to toggle + * @return {fabric.Object} thisArg + * @chainable + */ + toggle: function(property) { + var value = this.get(property); + if (typeof value === 'boolean') { + this.set(property, !value); + } + return this; + }, + + /** + * Sets sourcePath of an object + * @param {String} value Value to set sourcePath to + * @return {fabric.Object} thisArg + * @chainable + */ + setSourcePath: function(value) { + this.sourcePath = value; + return this; + }, + + /** + * Retrieves viewportTransform from Object's canvas if possible + * @method getViewportTransform + * @memberOf fabric.Object.prototype + * @return {Boolean} flipY value // TODO + */ + getViewportTransform: function() { + if (this.canvas && this.canvas.viewportTransform) + return this.canvas.viewportTransform; + return [1, 0, 0, 1, 0, 0]; + }, + + /** + * Renders an object on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if width/height are zeros or object is not visible + if (this.width === 0 || this.height === 0 || !this.visible) return; + + ctx.save(); + + //setup fill rule for current object + this._setupFillRule(ctx); + + this._transform(ctx, noTransform); + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); + + var m = this.transformMatrix; + if (m && this.group) { + ctx.translate(-this.group.width/2, -this.group.height/2); + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + this._render(ctx, noTransform); + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + this._restoreFillRule(ctx); + + ctx.restore(); + }, + + _transform: function(ctx, noTransform) { + var m = this.transformMatrix; + + if (m && !this.group) { + ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + if (!noTransform) { + this.transform(ctx); + } + }, + + _setStrokeStyles: function(ctx) { + if (this.stroke) { + ctx.lineWidth = this.strokeWidth; + ctx.lineCap = this.strokeLineCap; + ctx.lineJoin = this.strokeLineJoin; + ctx.miterLimit = this.strokeMiterLimit; + ctx.strokeStyle = this.stroke.toLive + ? this.stroke.toLive(ctx) + : this.stroke; + } + }, + + _setFillStyles: function(ctx) { + if (this.fill) { + ctx.fillStyle = this.fill.toLive + ? this.fill.toLive(ctx) + : this.fill; + } + }, + + /** + * Renders controls and borders for the object + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + _renderControls: function(ctx, noTransform) { + var v = this.getViewportTransform(); + + ctx.save(); + if (this.active && !noTransform) { + var center; + if (this.group) { + center = fabric.util.transformPoint(this.group.getCenterPoint(), v); + ctx.translate(center.x, center.y); + ctx.rotate(degreesToRadians(this.group.angle)); + } + center = fabric.util.transformPoint(this.getCenterPoint(), v, null != this.group); + if (this.group) { + center.x *= this.group.scaleX; + center.y *= this.group.scaleY; + } + ctx.translate(center.x, center.y); + ctx.rotate(degreesToRadians(this.angle)); + this.drawBorders(ctx); + this.drawControls(ctx); + } + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _setShadow: function(ctx) { + if (!this.shadow) return; + + ctx.shadowColor = this.shadow.color; + ctx.shadowBlur = this.shadow.blur; + ctx.shadowOffsetX = this.shadow.offsetX; + ctx.shadowOffsetY = this.shadow.offsetY; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _removeShadow: function(ctx) { + if (!this.shadow) return; + + ctx.shadowColor = ''; + ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderFill: function(ctx) { + if (!this.fill) return; + + if (this.fill.toLive) { + ctx.save(); + ctx.translate( + -this.width / 2 + this.fill.offsetX || 0, + -this.height / 2 + this.fill.offsetY || 0); + } + if (this.fillRule === 'destination-over') { + ctx.fill('evenodd'); + } + else { + ctx.fill(); + } + if (this.fill.toLive) { + ctx.restore(); + } + if (this.shadow && !this.shadow.affectStroke) { + this._removeShadow(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderStroke: function(ctx) { + if (!this.stroke) return; + + ctx.save(); + if (this.strokeDashArray) { + // Spec requires the concatenation of two copies the dash list when the number of elements is odd + if (1 & this.strokeDashArray.length) { + this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); + } + + if (supportsLineDash) { + ctx.setLineDash(this.strokeDashArray); + this._stroke && this._stroke(ctx); + } + else { + this._renderDashedStroke && this._renderDashedStroke(ctx); + } + ctx.stroke(); + } + else { + this._stroke ? this._stroke(ctx) : ctx.stroke(); + } + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * Clones an instance + * @param {Function} callback Callback is invoked with a clone as a first argument + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {fabric.Object} clone of an instance + */ + clone: function(callback, propertiesToInclude) { + if (this.constructor.fromObject) { + return this.constructor.fromObject(this.toObject(propertiesToInclude), callback); + } + return new fabric.Object(this.toObject(propertiesToInclude)); + }, + + /** + * Creates an instance of fabric.Image out of an object + * @param callback {Function} callback, invoked with an instance as a first argument + * @return {fabric.Object} thisArg + */ + cloneAsImage: function(callback) { + var dataUrl = this.toDataURL(); + fabric.util.loadImage(dataUrl, function(img) { + if (callback) { + callback(new fabric.Image(img)); + } + }); + return this; + }, + + /** + * Converts an object into a data-url-like string + * @param {Object} options Options object + * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png" + * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg. + * @param {Number} [options.multiplier=1] Multiplier to scale by + * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14 + * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14 + * @param {Number} [options.width] Cropping width. Introduced in v1.2.14 + * @param {Number} [options.height] Cropping height. Introduced in v1.2.14 + * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format + */ + toDataURL: function(options) { + options || (options = { }); + + var el = fabric.util.createCanvasElement(), + boundingRect = this.getBoundingRect(); + + el.width = boundingRect.width; + el.height = boundingRect.height; + + fabric.util.wrapElement(el, 'div'); + var canvas = new fabric.Canvas(el); + + // to avoid common confusion https://github.com/kangax/fabric.js/issues/806 + if (options.format === 'jpg') { + options.format = 'jpeg'; + } + + if (options.format === 'jpeg') { + canvas.backgroundColor = '#fff'; + } + + var origParams = { + active: this.get('active'), + left: this.getLeft(), + top: this.getTop() + }; + + this.set('active', false); + this.setPositionByOrigin(new fabric.Point(el.width / 2, el.height / 2), 'center', 'center'); + + var originalCanvas = this.canvas; + canvas.add(this); + var data = canvas.toDataURL(options); + + this.set(origParams).setCoords(); + this.canvas = originalCanvas; + + canvas.dispose(); + canvas = null; + + return data; + }, + + /** + * Returns true if specified type is identical to the type of an instance + * @param type {String} type Type to check against + * @return {Boolean} + */ + isType: function(type) { + return this.type === type; + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 0; + }, + + /** + * Returns a JSON representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} JSON + */ + toJSON: function(propertiesToInclude) { + // delegate, not alias + return this.toObject(propertiesToInclude); + }, + + /** + * Sets gradient (fill or stroke) of an object + * Backwards incompatibility note: This method was named "setGradientFill" until v1.1.0 + * @param {String} property Property name 'stroke' or 'fill' + * @param {Object} [options] Options object + * @param {String} [options.type] Type of gradient 'radial' or 'linear' + * @param {Number} [options.x1=0] x-coordinate of start point + * @param {Number} [options.y1=0] y-coordinate of start point + * @param {Number} [options.x2=0] x-coordinate of end point + * @param {Number} [options.y2=0] y-coordinate of end point + * @param {Number} [options.r1=0] Radius of start point (only for radial gradients) + * @param {Number} [options.r2=0] Radius of end point (only for radial gradients) + * @param {Object} [options.colorStops] Color stops object eg. {0: 'ff0000', 1: '000000'} + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/58y8b/|jsFiddle demo} + * @example Set linear gradient + * object.setGradient('fill', { + * type: 'linear', + * x1: -object.width / 2, + * y1: 0, + * x2: object.width / 2, + * y2: 0, + * colorStops: { + * 0: 'red', + * 0.5: '#005555', + * 1: 'rgba(0,0,255,0.5)' + * } + * }); + * canvas.renderAll(); + * @example Set radial gradient + * object.setGradient('fill', { + * type: 'radial', + * x1: 0, + * y1: 0, + * x2: 0, + * y2: 0, + * r1: object.width / 2, + * r2: 10, + * colorStops: { + * 0: 'red', + * 0.5: '#005555', + * 1: 'rgba(0,0,255,0.5)' + * } + * }); + * canvas.renderAll(); + */ + setGradient: function(property, options) { + options || (options = { }); + + var gradient = { colorStops: [] }; + + gradient.type = options.type || (options.r1 || options.r2 ? 'radial' : 'linear'); + gradient.coords = { + x1: options.x1, + y1: options.y1, + x2: options.x2, + y2: options.y2 + }; + + if (options.r1 || options.r2) { + gradient.coords.r1 = options.r1; + gradient.coords.r2 = options.r2; + } + + for (var position in options.colorStops) { + var color = new fabric.Color(options.colorStops[position]); + gradient.colorStops.push({ + offset: position, + color: color.toRgb(), + opacity: color.getAlpha() + }); + } + + return this.set(property, fabric.Gradient.forObject(this, gradient)); + }, + + /** + * Sets pattern fill of an object + * @param {Object} options Options object + * @param {(String|HTMLImageElement)} options.source Pattern source + * @param {String} [options.repeat=repeat] Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat) + * @param {Number} [options.offsetX=0] Pattern horizontal offset from object's left/top corner + * @param {Number} [options.offsetY=0] Pattern vertical offset from object's left/top corner + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/QT3pa/|jsFiddle demo} + * @example Set pattern + * fabric.util.loadImage('http://fabricjs.com/assets/escheresque_ste.png', function(img) { + * object.setPatternFill({ + * source: img, + * repeat: 'repeat' + * }); + * canvas.renderAll(); + * }); + */ + setPatternFill: function(options) { + return this.set('fill', new fabric.Pattern(options)); + }, + + /** + * Sets {@link fabric.Object#shadow|shadow} of an object + * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") + * @param {String} [options.color=rgb(0,0,0)] Shadow color + * @param {Number} [options.blur=0] Shadow blur + * @param {Number} [options.offsetX=0] Shadow horizontal offset + * @param {Number} [options.offsetY=0] Shadow vertical offset + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/7gvJG/|jsFiddle demo} + * @example Set shadow with string notation + * object.setShadow('2px 2px 10px rgba(0,0,0,0.2)'); + * canvas.renderAll(); + * @example Set shadow with object notation + * object.setShadow({ + * color: 'red', + * blur: 10, + * offsetX: 20, + * offsetY: 20 + * }); + * canvas.renderAll(); + */ + setShadow: function(options) { + return this.set('shadow', options ? new fabric.Shadow(options) : null); + }, + + /** + * Sets "color" of an instance (alias of `set('fill', …)`) + * @param {String} color Color value + * @return {fabric.Object} thisArg + * @chainable + */ + setColor: function(color) { + this.set('fill', color); + return this; + }, + + /** + * Sets "angle" of an instance + * @param {Number} angle Angle value + * @return {fabric.Object} thisArg + * @chainable + */ + setAngle: function(angle) { + var shouldCenterOrigin = (this.originX !== 'center' || this.originY !== 'center') && this.centeredRotation; + + if (shouldCenterOrigin) { + this._setOriginToCenter(); + } + + this.set('angle', angle); + + if (shouldCenterOrigin) { + this._resetOrigin(); + } + + return this; + }, + + /** + * Centers object horizontally on canvas to which it was added last. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + centerH: function () { + this.canvas.centerObjectH(this); + return this; + }, + + /** + * Centers object vertically on canvas to which it was added last. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + centerV: function () { + this.canvas.centerObjectV(this); + return this; + }, + + /** + * Centers object vertically and horizontally on canvas to which is was added last + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + center: function () { + this.canvas.centerObject(this); + return this; + }, + + /** + * Removes object from canvas to which it was added last + * @return {fabric.Object} thisArg + * @chainable + */ + remove: function() { + this.canvas.remove(this); + return this; + }, + + /** + * Returns coordinates of a pointer relative to an object + * @param {Event} e Event to operate upon + * @param {Object} [pointer] Pointer to operate upon (instead of event) + * @return {Object} Coordinates of a pointer (x, y) + */ + getLocalPointer: function(e, pointer) { + pointer = pointer || this.canvas.getPointer(e); + var objectLeftTop = this.translateToOriginPoint(this.getCenterPoint(), 'left', 'top'); + return { + x: pointer.x - objectLeftTop.x, + y: pointer.y - objectLeftTop.y + }; + }, + + /** + * Sets canvas globalCompositeOperation for specific object + * custom composition operation for the particular object can be specifed using fillRule property + * @param {CanvasRenderingContext2D} ctx Rendering canvas context + */ + _setupFillRule: function (ctx) { + if (this.fillRule) { + this._prevFillRule = ctx.globalCompositeOperation; + ctx.globalCompositeOperation = this.fillRule; + } + }, + + /** + * Restores previously saved canvas globalCompositeOperation after obeject rendering + * @param {CanvasRenderingContext2D} ctx Rendering canvas context + */ + _restoreFillRule: function (ctx) { + if (this.fillRule && this._prevFillRule) { + ctx.globalCompositeOperation = this._prevFillRule; + } + } + }); + + fabric.util.createAccessors(fabric.Object); + + /** + * Alias for {@link fabric.Object.prototype.setAngle} + * @alias rotate -> setAngle + * @memberof fabric.Object + */ + fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle; + + extend(fabric.Object.prototype, fabric.Observable); + + /** + * Defines the number of fraction digits to use when serializing object values. + * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc. + * @static + * @memberof fabric.Object + * @constant + * @type Number + */ + fabric.Object.NUM_FRACTION_DIGITS = 2; + + /** + * Unique id used internally when creating SVG elements + * @static + * @memberof fabric.Object + * @type Number + */ + fabric.Object.__uid = 0; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + var degreesToRadians = fabric.util.degreesToRadians; + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Translates the coordinates from origin to center coordinates (based on the object's dimensions) + * @param {fabric.Point} point The point which corresponds to the originX and originY params + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + translateToCenterPoint: function(point, originX, originY) { + var cx = point.x, + cy = point.y, + strokeWidth = this.stroke ? this.strokeWidth : 0; + + if (originX === 'left') { + cx = point.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === 'right') { + cx = point.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + + if (originY === 'top') { + cy = point.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === 'bottom') { + cy = point.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + + // Apply the reverse rotation to the point (it's already scaled properly) + return fabric.util.rotatePoint(new fabric.Point(cx, cy), point, degreesToRadians(this.angle)); + }, + + /** + * Translates the coordinates from center to origin coordinates (based on the object's dimensions) + * @param {fabric.Point} point The point which corresponds to center of the object + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + translateToOriginPoint: function(center, originX, originY) { + var x = center.x, + y = center.y, + strokeWidth = this.stroke ? this.strokeWidth : 0; + + // Get the point coordinates + if (originX === 'left') { + x = center.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === 'right') { + x = center.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + if (originY === 'top') { + y = center.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === 'bottom') { + y = center.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + + // Apply the rotation to the point (it's already scaled properly) + return fabric.util.rotatePoint(new fabric.Point(x, y), center, degreesToRadians(this.angle)); + }, + + /** + * Returns the real center coordinates of the object + * @return {fabric.Point} + */ + getCenterPoint: function() { + var leftTop = new fabric.Point(this.left, this.top); + return this.translateToCenterPoint(leftTop, this.originX, this.originY); + }, + + /** + * Returns the coordinates of the object based on center coordinates + * @param {fabric.Point} point The point which corresponds to the originX and originY params + * @return {fabric.Point} + */ + // getOriginPoint: function(center) { + // return this.translateToOriginPoint(center, this.originX, this.originY); + // }, + + /** + * Returns the coordinates of the object as if it has a different origin + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + getPointByOrigin: function(originX, originY) { + var center = this.getCenterPoint(); + return this.translateToOriginPoint(center, originX, originY); + }, + + /** + * Returns the point in local coordinates + * @param {fabric.Point} point The point relative to the global coordinate system + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + toLocalPoint: function(point, originX, originY) { + var center = this.getCenterPoint(), + strokeWidth = this.stroke ? this.strokeWidth : 0, + x, y; + + if (originX && originY) { + if (originX === 'left') { + x = center.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === 'right') { + x = center.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else { + x = center.x; + } + + if (originY === 'top') { + y = center.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === 'bottom') { + y = center.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else { + y = center.y; + } + } + else { + x = this.left; + y = this.top; + } + + return fabric.util.rotatePoint(new fabric.Point(point.x, point.y), center, -degreesToRadians(this.angle)) + .subtractEquals(new fabric.Point(x, y)); + }, + + /** + * Returns the point in global coordinates + * @param {fabric.Point} The point relative to the local coordinate system + * @return {fabric.Point} + */ + // toGlobalPoint: function(point) { + // return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top)); + // }, + + /** + * Sets the position of the object taking into consideration the object's origin + * @param {fabric.Point} point The new position of the object + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {void} + */ + setPositionByOrigin: function(pos, originX, originY) { + var center = this.translateToCenterPoint(pos, originX, originY), + position = this.translateToOriginPoint(center, this.originX, this.originY); + + this.set('left', position.x); + this.set('top', position.y); + }, + + /** + * @param {String} to One of 'left', 'center', 'right' + */ + adjustPosition: function(to) { + var angle = degreesToRadians(this.angle), + hypotHalf = this.getWidth() / 2, + xHalf = Math.cos(angle) * hypotHalf, + yHalf = Math.sin(angle) * hypotHalf, + hypotFull = this.getWidth(), + xFull = Math.cos(angle) * hypotFull, + yFull = Math.sin(angle) * hypotFull; + + if (this.originX === 'center' && to === 'left' || + this.originX === 'right' && to === 'center') { + // move half left + this.left -= xHalf; + this.top -= yHalf; + } + else if (this.originX === 'left' && to === 'center' || + this.originX === 'center' && to === 'right') { + // move half right + this.left += xHalf; + this.top += yHalf; + } + else if (this.originX === 'left' && to === 'right') { + // move full right + this.left += xFull; + this.top += yFull; + } + else if (this.originX === 'right' && to === 'left') { + // move full left + this.left -= xFull; + this.top -= yFull; + } + + this.setCoords(); + this.originX = to; + }, + + /** + * @private + * Sets the origin/position of the object to it's center point + * @return {void} + */ + _setOriginToCenter: function() { + this._originalOriginX = this.originX; + this._originalOriginY = this.originY; + + var center = this.getCenterPoint(); + + this.originX = 'center'; + this.originY = 'center'; + + this.left = center.x; + this.top = center.y; + }, + + /** + * @private + * Resets the origin/position of the object to it's original origin + * @return {void} + */ + _resetOrigin: function() { + var originPoint = this.translateToOriginPoint( + this.getCenterPoint(), + this._originalOriginX, + this._originalOriginY); + + this.originX = this._originalOriginX; + this.originY = this._originalOriginY; + + this.left = originPoint.x; + this.top = originPoint.y; + + this._originalOriginX = null; + this._originalOriginY = null; + }, + + /** + * @private + */ + _getLeftTopCoords: function() { + return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'center'); + } + }); + +})(); + + +(function() { + + var degreesToRadians = fabric.util.degreesToRadians; + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Object containing coordinates of object's controls + * @type Object + * @default + */ + oCoords: null, + + /** + * Checks if object intersects with an area formed by 2 points + * @param {Object} pointTL top-left point of area + * @param {Object} pointBR bottom-right point of area + * @return {Boolean} true if object intersects with an area formed by 2 points + */ + intersectsWithRect: function(pointTL, pointBR) { + var oCoords = this.oCoords, + tl = new fabric.Point(oCoords.tl.x, oCoords.tl.y), + tr = new fabric.Point(oCoords.tr.x, oCoords.tr.y), + bl = new fabric.Point(oCoords.bl.x, oCoords.bl.y), + br = new fabric.Point(oCoords.br.x, oCoords.br.y), + intersection = fabric.Intersection.intersectPolygonRectangle( + [tl, tr, br, bl], + pointTL, + pointBR + ); + return intersection.status === 'Intersection'; + }, + + /** + * Checks if object intersects with another object + * @param {Object} other Object to test + * @return {Boolean} true if object intersects with another object + */ + intersectsWithObject: function(other) { + // extracts coords + function getCoords(oCoords) { + return { + tl: new fabric.Point(oCoords.tl.x, oCoords.tl.y), + tr: new fabric.Point(oCoords.tr.x, oCoords.tr.y), + bl: new fabric.Point(oCoords.bl.x, oCoords.bl.y), + br: new fabric.Point(oCoords.br.x, oCoords.br.y) + }; + } + var thisCoords = getCoords(this.oCoords), + otherCoords = getCoords(other.oCoords), + intersection = fabric.Intersection.intersectPolygonPolygon( + [thisCoords.tl, thisCoords.tr, thisCoords.br, thisCoords.bl], + [otherCoords.tl, otherCoords.tr, otherCoords.br, otherCoords.bl] + ); + + return intersection.status === 'Intersection'; + }, + + /** + * Checks if object is fully contained within area of another object + * @param {Object} other Object to test + * @return {Boolean} true if object is fully contained within area of another object + */ + isContainedWithinObject: function(other) { + var boundingRect = other.getBoundingRect(), + point1 = new fabric.Point(boundingRect.left, boundingRect.top), + point2 = new fabric.Point(boundingRect.left + boundingRect.width, boundingRect.top + boundingRect.height); + + return this.isContainedWithinRect(point1, point2); + }, + + /** + * Checks if object is fully contained within area formed by 2 points + * @param {Object} pointTL top-left point of area + * @param {Object} pointBR bottom-right point of area + * @return {Boolean} true if object is fully contained within area formed by 2 points + */ + isContainedWithinRect: function(pointTL, pointBR) { + var boundingRect = this.getBoundingRect(); + + return ( + boundingRect.left >= pointTL.x && + boundingRect.left + boundingRect.width <= pointBR.x && + boundingRect.top >= pointTL.y && + boundingRect.top + boundingRect.height <= pointBR.y + ); + }, + + /** + * Checks if point is inside the object + * @param {fabric.Point} point Point to check against + * @return {Boolean} true if point is inside the object + */ + containsPoint: function(point) { + var lines = this._getImageLines(this.oCoords), + xPoints = this._findCrossPoints(point, lines); + + // if xPoints is odd then point is inside the object + return (xPoints !== 0 && xPoints % 2 === 1); + }, + + /** + * Method that returns an object with the object edges in it, given the coordinates of the corners + * @private + * @param {Object} oCoords Coordinates of the object corners + */ + _getImageLines: function(oCoords) { + return { + topline: { + o: oCoords.tl, + d: oCoords.tr + }, + rightline: { + o: oCoords.tr, + d: oCoords.br + }, + bottomline: { + o: oCoords.br, + d: oCoords.bl + }, + leftline: { + o: oCoords.bl, + d: oCoords.tl + } + }; + }, + + /** + * Helper method to determine how many cross points are between the 4 object edges + * and the horizontal line determined by a point on canvas + * @private + * @param {fabric.Point} point Point to check + * @param {Object} oCoords Coordinates of the object being evaluated + */ + _findCrossPoints: function(point, oCoords) { + var b1, b2, a1, a2, xi, yi, + xcount = 0, + iLine; + + for (var lineKey in oCoords) { + iLine = oCoords[lineKey]; + // optimisation 1: line below point. no cross + if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) { + continue; + } + // optimisation 2: line above point. no cross + if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) { + continue; + } + // optimisation 3: vertical line case + if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) { + xi = iLine.o.x; + yi = point.y; + } + // calculate the intersection point + else { + b1 = 0; + b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x); + a1 = point.y - b1 * point.x; + a2 = iLine.o.y - b2 * iLine.o.x; + + xi = - (a1 - a2) / (b1 - b2); + yi = a1 + b1 * xi; + } + // dont count xi < point.x cases + if (xi >= point.x) { + xcount += 1; + } + // optimisation 4: specific for square images + if (xcount === 2) { + break; + } + } + return xcount; + }, + + /** + * Returns width of an object's bounding rectangle + * @deprecated since 1.0.4 + * @return {Number} width value + */ + getBoundingRectWidth: function() { + return this.getBoundingRect().width; + }, + + /** + * Returns height of an object's bounding rectangle + * @deprecated since 1.0.4 + * @return {Number} height value + */ + getBoundingRectHeight: function() { + return this.getBoundingRect().height; + }, + + /** + * Returns coordinates of object's bounding rectangle (left, top, width, height) + * @return {Object} Object with left, top, width, height properties + */ + getBoundingRect: function() { + this.oCoords || this.setCoords(); + + var xCoords = [this.oCoords.tl.x, this.oCoords.tr.x, this.oCoords.br.x, this.oCoords.bl.x], + minX = fabric.util.array.min(xCoords), + maxX = fabric.util.array.max(xCoords), + width = Math.abs(minX - maxX), + + yCoords = [this.oCoords.tl.y, this.oCoords.tr.y, this.oCoords.br.y, this.oCoords.bl.y], + minY = fabric.util.array.min(yCoords), + maxY = fabric.util.array.max(yCoords), + height = Math.abs(minY - maxY); + + return { + left: minX, + top: minY, + width: width, + height: height + }; + }, + + /** + * Returns width of an object + * @return {Number} width value + */ + getWidth: function() { + return this.width * this.scaleX; + }, + + /** + * Returns height of an object + * @return {Number} height value + */ + getHeight: function() { + return this.height * this.scaleY; + }, + + /** + * Makes sure the scale is valid and modifies it if necessary + * @private + * @param {Number} value + * @return {Number} + */ + _constrainScale: function(value) { + if (Math.abs(value) < this.minScaleLimit) { + if (value < 0) { + return -this.minScaleLimit; + } + else { + return this.minScaleLimit; + } + } + return value; + }, + + /** + * Scales an object (equally by x and y) + * @param value {Number} scale factor + * @return {fabric.Object} thisArg + * @chainable + */ + scale: function(value) { + value = this._constrainScale(value); + + if (value < 0) { + this.flipX = !this.flipX; + this.flipY = !this.flipY; + value *= -1; + } + + this.scaleX = value; + this.scaleY = value; + this.setCoords(); + return this; + }, + + /** + * Scales an object to a given width, with respect to bounding box (scaling by x/y equally) + * @param value {Number} new width value + * @return {fabric.Object} thisArg + * @chainable + */ + scaleToWidth: function(value) { + // adjust to bounding rect factor so that rotated shapes would fit as well + var boundingRectFactor = this.getBoundingRectWidth() / this.getWidth(); + return this.scale(value / this.width / boundingRectFactor); + }, + + /** + * Scales an object to a given height, with respect to bounding box (scaling by x/y equally) + * @param value {Number} new height value + * @return {fabric.Object} thisArg + * @chainable + */ + scaleToHeight: function(value) { + // adjust to bounding rect factor so that rotated shapes would fit as well + var boundingRectFactor = this.getBoundingRectHeight() / this.getHeight(); + return this.scale(value / this.height / boundingRectFactor); + }, + + /** + * Sets corner position coordinates based on current angle, width and height + * @return {fabric.Object} thisArg + * @chainable + */ + setCoords: function() { + + var strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, + theta = degreesToRadians(this.angle), + vpt = this.getViewportTransform(); + + var f = function (p) { + return fabric.util.transformPoint(p, vpt); + }; + + this.currentWidth = (this.width + strokeWidth) * this.scaleX; + this.currentHeight = (this.height + strokeWidth) * this.scaleY; + + // If width is negative, make postive. Fixes path selection issue + if (this.currentWidth < 0) { + this.currentWidth = Math.abs(this.currentWidth); + } + + var _hypotenuse = Math.sqrt( + Math.pow(this.currentWidth / 2, 2) + + Math.pow(this.currentHeight / 2, 2)), + + _angle = Math.atan(isFinite(this.currentHeight / this.currentWidth) ? this.currentHeight / this.currentWidth : 0), + + // offset added for rotate and scale actions + offsetX = Math.cos(_angle + theta) * _hypotenuse, + offsetY = Math.sin(_angle + theta) * _hypotenuse, + sinTh = Math.sin(theta), + cosTh = Math.cos(theta), + coords = this.getCenterPoint(), + wh = new fabric.Point(this.currentWidth, this.currentHeight), + _tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY), + _tr = new fabric.Point(_tl.x + (wh.x * cosTh), _tl.y + (wh.x * sinTh)), + _bl = new fabric.Point(_tl.x - (wh.y * sinTh), _tl.y + (wh.y * cosTh)), + _mt = new fabric.Point(_tl.x + (wh.x/2 * cosTh), _tl.y + (wh.x/2 * sinTh)), + tl = f(_tl), + tr = f(_tr), + br = f(new fabric.Point(_tr.x - (wh.y * sinTh), _tr.y + (wh.y * cosTh))), + bl = f(_bl), + ml = f(new fabric.Point(_tl.x - (wh.y/2 * sinTh), _tl.y + (wh.y/2 * cosTh))), + mt = f(_mt), + mr = f(new fabric.Point(_tr.x - (wh.y/2 * sinTh), _tr.y + (wh.y/2 * cosTh))), + mb = f(new fabric.Point(_bl.x + (wh.x/2 * cosTh), _bl.y + (wh.x/2 * sinTh))), + mtr = f(new fabric.Point(_mt.x, _mt.y)); + + // padding + var padX = Math.cos(_angle + theta) * this.padding * Math.sqrt(2), + padY = Math.sin(_angle + theta) * this.padding * Math.sqrt(2); + tl = tl.add(new fabric.Point(-padX, -padY)); + tr = tr.add(new fabric.Point(padY, -padX)); + br = br.add(new fabric.Point(padX, padY)); + bl = bl.add(new fabric.Point(-padY, padX)); + ml = ml.add(new fabric.Point((-padX - padY) / 2, (-padY + padX) / 2)); + mt = mt.add(new fabric.Point((padY - padX) / 2, -(padY + padX) / 2)); + mr = mr.add(new fabric.Point((padY + padX) / 2, (padY - padX) / 2)); + mb = mb.add(new fabric.Point((padX - padY) / 2, (padX + padY) / 2)); + mtr = mtr.add(new fabric.Point((padY - padX) / 2, -(padY + padX) / 2)); + + // debugging + + // setTimeout(function() { + // canvas.contextTop.fillStyle = 'green'; + // canvas.contextTop.fillRect(mb.x, mb.y, 3, 3); + // canvas.contextTop.fillRect(bl.x, bl.y, 3, 3); + // canvas.contextTop.fillRect(br.x, br.y, 3, 3); + // canvas.contextTop.fillRect(tl.x, tl.y, 3, 3); + // canvas.contextTop.fillRect(tr.x, tr.y, 3, 3); + // canvas.contextTop.fillRect(ml.x, ml.y, 3, 3); + // canvas.contextTop.fillRect(mr.x, mr.y, 3, 3); + // canvas.contextTop.fillRect(mt.x, mt.y, 3, 3); + // }, 50); + + this.oCoords = { + // corners + tl: tl, tr: tr, br: br, bl: bl, + // middle + ml: ml, mt: mt, mr: mr, mb: mb, + // rotating point + mtr: mtr + }; + + // set coordinates of the draggable boxes in the corners used to scale/rotate the image + this._setCornerCoords && this._setCornerCoords(); + + return this; + } + }); +})(); + + +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Moves an object to the bottom of the stack of drawn objects + * @return {fabric.Object} thisArg + * @chainable + */ + sendToBack: function() { + if (this.group) { + fabric.StaticCanvas.prototype.sendToBack.call(this.group, this); + } + else { + this.canvas.sendToBack(this); + } + return this; + }, + + /** + * Moves an object to the top of the stack of drawn objects + * @return {fabric.Object} thisArg + * @chainable + */ + bringToFront: function() { + if (this.group) { + fabric.StaticCanvas.prototype.bringToFront.call(this.group, this); + } + else { + this.canvas.bringToFront(this); + } + return this; + }, + + /** + * Moves an object down in stack of drawn objects + * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object + * @return {fabric.Object} thisArg + * @chainable + */ + sendBackwards: function(intersecting) { + if (this.group) { + fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting); + } + else { + this.canvas.sendBackwards(this, intersecting); + } + return this; + }, + + /** + * Moves an object up in stack of drawn objects + * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object + * @return {fabric.Object} thisArg + * @chainable + */ + bringForward: function(intersecting) { + if (this.group) { + fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting); + } + else { + this.canvas.bringForward(this, intersecting); + } + return this; + }, + + /** + * Moves an object to specified level in stack of drawn objects + * @param {Number} index New position of object + * @return {fabric.Object} thisArg + * @chainable + */ + moveTo: function(index) { + if (this.group) { + fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index); + } + else { + this.canvas.moveTo(this, index); + } + return this; + } +}); + + +/* _TO_SVG_START_ */ +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Returns styles-string for svg-export + * @return {String} + */ + getSvgStyles: function() { + + var fill = this.fill + ? (this.fill.toLive ? 'url(#SVGID_' + this.fill.id + ')' : this.fill) + : 'none', + + stroke = this.stroke + ? (this.stroke.toLive ? 'url(#SVGID_' + this.stroke.id + ')' : this.stroke) + : 'none', + + strokeWidth = this.strokeWidth ? this.strokeWidth : '0', + strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : '', + strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt', + strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter', + strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4', + opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1', + + visibility = this.visible ? '' : ' visibility: hidden;', + filter = this.shadow && this.type !== 'text' ? 'filter: url(#SVGID_' + this.shadow.id + ');' : ''; + + return [ + 'stroke: ', stroke, '; ', + 'stroke-width: ', strokeWidth, '; ', + 'stroke-dasharray: ', strokeDashArray, '; ', + 'stroke-linecap: ', strokeLineCap, '; ', + 'stroke-linejoin: ', strokeLineJoin, '; ', + 'stroke-miterlimit: ', strokeMiterLimit, '; ', + 'fill: ', fill, '; ', + 'opacity: ', opacity, ';', + filter, + visibility + ].join(''); + }, + + /** + * Returns transform-string for svg-export + * @return {String} + */ + getSvgTransform: function() { + var toFixed = fabric.util.toFixed, + angle = this.getAngle(), + vpt = this.getViewportTransform(), + center = fabric.util.transformPoint(this.getCenterPoint(), vpt), + + NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, + + translatePart = 'translate(' + + toFixed(center.x, NUM_FRACTION_DIGITS) + + ' ' + + toFixed(center.y, NUM_FRACTION_DIGITS) + + ')', + + anglePart = angle !== 0 + ? (' rotate(' + toFixed(angle, NUM_FRACTION_DIGITS) + ')') + : '', + + scalePart = (this.scaleX === 1 && this.scaleY === 1 && vpt[0] === 1 && vpt[3] === 1) + ? '' : + (' scale(' + + toFixed(this.scaleX * vpt[0], NUM_FRACTION_DIGITS) + + ' ' + + toFixed(this.scaleY * vpt[3], NUM_FRACTION_DIGITS) + + ')'), + + flipXPart = this.flipX ? 'matrix(-1 0 0 1 0 0) ' : '', + + flipYPart = this.flipY ? 'matrix(1 0 0 -1 0 0)' : ''; + + return [ + translatePart, anglePart, scalePart, flipXPart, flipYPart + ].join(''); + }, + + /** + * @private + */ + _createBaseSVGMarkup: function() { + var markup = [ ]; + + if (this.fill && this.fill.toLive) { + markup.push(this.fill.toSVG(this, false)); + } + if (this.stroke && this.stroke.toLive) { + markup.push(this.stroke.toSVG(this, false)); + } + if (this.shadow) { + markup.push(this.shadow.toSVG(this)); + } + return markup; + } +}); +/* _TO_SVG_END_ */ + + +/* + Depends on `stateProperties` +*/ +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Returns true if object state (one of its state properties) was changed + * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called + */ + hasStateChanged: function() { + return this.stateProperties.some(function(prop) { + return this.get(prop) !== this.originalState[prop]; + }, this); + }, + + /** + * Saves state of an object + * @param {Object} [options] Object with additional `stateProperties` array to include when saving state + * @return {fabric.Object} thisArg + */ + saveState: function(options) { + this.stateProperties.forEach(function(prop) { + this.originalState[prop] = this.get(prop); + }, this); + + if (options && options.stateProperties) { + options.stateProperties.forEach(function(prop) { + this.originalState[prop] = this.get(prop); + }, this); + } + + return this; + }, + + /** + * Setups state of an object + * @return {fabric.Object} thisArg + */ + setupState: function() { + this.originalState = { }; + this.saveState(); + + return this; + } +}); + + +(function(){ + + var degreesToRadians = fabric.util.degreesToRadians, + isVML = function() { return typeof G_vmlCanvasManager !== 'undefined'; }; + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * The object interactivity controls. + * @private + */ + _controlsVisibility: null, + + /** + * Determines which corner has been clicked + * @private + * @param {Object} pointer The pointer indicating the mouse position + * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found + */ + _findTargetCorner: function(pointer) { + if (!this.hasControls || !this.active) { + return false; + } + + var ex = pointer.x, + ey = pointer.y, + xPoints, + lines; + + for (var i in this.oCoords) { + + if (!this.isControlVisible(i)) { + continue; + } + + if (i === 'mtr' && !this.hasRotatingPoint) { + continue; + } + + if (this.get('lockUniScaling') && + (i === 'mt' || i === 'mr' || i === 'mb' || i === 'ml')) { + continue; + } + + lines = this._getImageLines(this.oCoords[i].corner); + + // debugging + + // canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2); + + xPoints = this._findCrossPoints({ x: ex, y: ey }, lines); + if (xPoints !== 0 && xPoints % 2 === 1) { + this.__corner = i; + return i; + } + } + return false; + }, + + /** + * Sets the coordinates of the draggable boxes in the corners of + * the image used to scale/rotate it. + * @private + */ + _setCornerCoords: function() { + var coords = this.oCoords, + theta = degreesToRadians(this.angle), + newTheta = degreesToRadians(45 - this.angle), + cornerHypotenuse = Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, + cosHalfOffset = cornerHypotenuse * Math.cos(newTheta), + sinHalfOffset = cornerHypotenuse * Math.sin(newTheta), + sinTh = Math.sin(theta), + cosTh = Math.cos(theta); + + coords.tl.corner = { + tl: { + x: coords.tl.x - sinHalfOffset, + y: coords.tl.y - cosHalfOffset + }, + tr: { + x: coords.tl.x + cosHalfOffset, + y: coords.tl.y - sinHalfOffset + }, + bl: { + x: coords.tl.x - cosHalfOffset, + y: coords.tl.y + sinHalfOffset + }, + br: { + x: coords.tl.x + sinHalfOffset, + y: coords.tl.y + cosHalfOffset + } + }; + + coords.tr.corner = { + tl: { + x: coords.tr.x - sinHalfOffset, + y: coords.tr.y - cosHalfOffset + }, + tr: { + x: coords.tr.x + cosHalfOffset, + y: coords.tr.y - sinHalfOffset + }, + br: { + x: coords.tr.x + sinHalfOffset, + y: coords.tr.y + cosHalfOffset + }, + bl: { + x: coords.tr.x - cosHalfOffset, + y: coords.tr.y + sinHalfOffset + } + }; + + coords.bl.corner = { + tl: { + x: coords.bl.x - sinHalfOffset, + y: coords.bl.y - cosHalfOffset + }, + bl: { + x: coords.bl.x - cosHalfOffset, + y: coords.bl.y + sinHalfOffset + }, + br: { + x: coords.bl.x + sinHalfOffset, + y: coords.bl.y + cosHalfOffset + }, + tr: { + x: coords.bl.x + cosHalfOffset, + y: coords.bl.y - sinHalfOffset + } + }; + + coords.br.corner = { + tr: { + x: coords.br.x + cosHalfOffset, + y: coords.br.y - sinHalfOffset + }, + bl: { + x: coords.br.x - cosHalfOffset, + y: coords.br.y + sinHalfOffset + }, + br: { + x: coords.br.x + sinHalfOffset, + y: coords.br.y + cosHalfOffset + }, + tl: { + x: coords.br.x - sinHalfOffset, + y: coords.br.y - cosHalfOffset + } + }; + + coords.ml.corner = { + tl: { + x: coords.ml.x - sinHalfOffset, + y: coords.ml.y - cosHalfOffset + }, + tr: { + x: coords.ml.x + cosHalfOffset, + y: coords.ml.y - sinHalfOffset + }, + bl: { + x: coords.ml.x - cosHalfOffset, + y: coords.ml.y + sinHalfOffset + }, + br: { + x: coords.ml.x + sinHalfOffset, + y: coords.ml.y + cosHalfOffset + } + }; + + coords.mt.corner = { + tl: { + x: coords.mt.x - sinHalfOffset, + y: coords.mt.y - cosHalfOffset + }, + tr: { + x: coords.mt.x + cosHalfOffset, + y: coords.mt.y - sinHalfOffset + }, + bl: { + x: coords.mt.x - cosHalfOffset, + y: coords.mt.y + sinHalfOffset + }, + br: { + x: coords.mt.x + sinHalfOffset, + y: coords.mt.y + cosHalfOffset + } + }; + + coords.mr.corner = { + tl: { + x: coords.mr.x - sinHalfOffset, + y: coords.mr.y - cosHalfOffset + }, + tr: { + x: coords.mr.x + cosHalfOffset, + y: coords.mr.y - sinHalfOffset + }, + bl: { + x: coords.mr.x - cosHalfOffset, + y: coords.mr.y + sinHalfOffset + }, + br: { + x: coords.mr.x + sinHalfOffset, + y: coords.mr.y + cosHalfOffset + } + }; + + coords.mb.corner = { + tl: { + x: coords.mb.x - sinHalfOffset, + y: coords.mb.y - cosHalfOffset + }, + tr: { + x: coords.mb.x + cosHalfOffset, + y: coords.mb.y - sinHalfOffset + }, + bl: { + x: coords.mb.x - cosHalfOffset, + y: coords.mb.y + sinHalfOffset + }, + br: { + x: coords.mb.x + sinHalfOffset, + y: coords.mb.y + cosHalfOffset + } + }; + + coords.mtr.corner = { + tl: { + x: coords.mtr.x - sinHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y - cosHalfOffset - (cosTh * this.rotatingPointOffset) + }, + tr: { + x: coords.mtr.x + cosHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y - sinHalfOffset - (cosTh * this.rotatingPointOffset) + }, + bl: { + x: coords.mtr.x - cosHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y + sinHalfOffset - (cosTh * this.rotatingPointOffset) + }, + br: { + x: coords.mtr.x + sinHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y + cosHalfOffset - (cosTh * this.rotatingPointOffset) + } + }; + }, + /** + * Draws borders of an object's bounding box. + * Requires public properties: width, height + * Requires public options: padding, borderColor + * @param {CanvasRenderingContext2D} ctx Context to draw on + * @return {fabric.Object} thisArg + * @chainable + */ + drawBorders: function(ctx) { + if (!this.hasBorders) return this; + + var padding = this.padding, + padding2 = padding * 2, + strokeWidth = ~~(this.strokeWidth / 2) * 2; // Round down to even number + + ctx.save(); + + ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; + ctx.strokeStyle = this.borderColor; + + var scaleX = 1 / this._constrainScale(this.scaleX), + scaleY = 1 / this._constrainScale(this.scaleY); + + ctx.lineWidth = 1 / this.borderScaleFactor; + + var vpt = this.getViewportTransform(), + wh = fabric.util.transformPoint(new fabric.Point(this.getWidth(), this.getHeight()), vpt, true), + sxy = fabric.util.transformPoint(new fabric.Point(scaleX, scaleY), vpt, true), + w = wh.x, + h = wh.y, + sx= sxy.x, + sy= sxy.y; + if (this.group) { + w = w * this.group.scaleX; + h = h * this.group.scaleY; + } + + ctx.strokeRect( + ~~(-(w / 2) - padding - strokeWidth / 2 * sx) - 0.5, // offset needed to make lines look sharper + ~~(-(h / 2) - padding - strokeWidth / 2 * sy) - 0.5, + ~~(w + padding2 + strokeWidth * sx) + 1, // double offset needed to make lines look sharper + ~~(h + padding2 + strokeWidth * sy) + 1 + ); + + if (this.hasRotatingPoint && this.isControlVisible('mtr') && !this.get('lockRotation') && this.hasControls) { + + var rotateHeight = ( + this.flipY + ? h + (strokeWidth * sx) + (padding * 2) + : -h - (strokeWidth * sy) - (padding * 2) + ) / 2; + + ctx.beginPath(); + ctx.moveTo(0, rotateHeight); + ctx.lineTo(0, rotateHeight + (this.flipY ? this.rotatingPointOffset : -this.rotatingPointOffset)); + ctx.closePath(); + ctx.stroke(); + } + + ctx.restore(); + return this; + }, + + /** + * Draws corners of an object's bounding box. + * Requires public properties: width, height + * Requires public options: cornerSize, padding + * @param {CanvasRenderingContext2D} ctx Context to draw on + * @return {fabric.Object} thisArg + * @chainable + */ + drawControls: function(ctx) { + if (!this.hasControls) return this; + + var size = this.cornerSize, + size2 = size / 2, + strokeWidth2 = ~~(this.strokeWidth / 2), // half strokeWidth rounded down + wh = fabric.util.transformPoint(new fabric.Point(this.getWidth(), this.getHeight()), this.getViewportTransform(), true), + width = wh.x, + height = wh.y, + left = -(width / 2), + top = -(height / 2), + padding = this.padding, + scaleOffset = size2, + scaleOffsetSize = size2 - size, + methodName = this.transparentCorners ? 'strokeRect' : 'fillRect'; + + ctx.save(); + + ctx.lineWidth = 1; + + ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; + ctx.strokeStyle = ctx.fillStyle = this.cornerColor; + + // top-left + this._drawControl('tl', ctx, methodName, + left - scaleOffset - strokeWidth2 - padding, + top - scaleOffset - strokeWidth2 - padding); + + // top-right + this._drawControl('tr', ctx, methodName, + left + width - scaleOffset + strokeWidth2 + padding, + top - scaleOffset - strokeWidth2 - padding); + + // bottom-left + this._drawControl('bl', ctx, methodName, + left - scaleOffset - strokeWidth2 - padding, + top + height + scaleOffsetSize + strokeWidth2 + padding); + + // bottom-right + this._drawControl('br', ctx, methodName, + left + width + scaleOffsetSize + strokeWidth2 + padding, + top + height + scaleOffsetSize + strokeWidth2 + padding); + + if (!this.get('lockUniScaling')) { + + // middle-top + this._drawControl('mt', ctx, methodName, + left + width/2 - scaleOffset, + top - scaleOffset - strokeWidth2 - padding); + + // middle-bottom + this._drawControl('mb', ctx, methodName, + left + width/2 - scaleOffset, + top + height + scaleOffsetSize + strokeWidth2 + padding); + + // middle-right + this._drawControl('mr', ctx, methodName, + left + width + scaleOffsetSize + strokeWidth2 + padding, + top + height/2 - scaleOffset); + + // middle-left + this._drawControl('ml', ctx, methodName, + left - scaleOffset - strokeWidth2 - padding, + top + height/2 - scaleOffset); + } + + // middle-top-rotate + if (this.hasRotatingPoint) { + this._drawControl('mtr', ctx, methodName, + left + width/2 - scaleOffset, + this.flipY + ? (top + height + this.rotatingPointOffset - this.cornerSize/2 + strokeWidth2 + padding) + : (top - this.rotatingPointOffset - this.cornerSize/2 - strokeWidth2 - padding)); + } + + ctx.restore(); + + return this; + }, + + /** + * @private + */ + _drawControl: function(control, ctx, methodName, left, top) { + var size = this.cornerSize; + + if (this.isControlVisible(control)) { + isVML() || this.transparentCorners || ctx.clearRect(left, top, size, size); + ctx[methodName](left, top, size, size); + } + }, + + /** + * Returns true if the specified control is visible, false otherwise. + * @param {String} controlName The name of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'. + * @returns {Boolean} true if the specified control is visible, false otherwise + */ + isControlVisible: function(controlName) { + return this._getControlsVisibility()[controlName]; + }, + + /** + * Sets the visibility of the specified control. + * @param {String} controlName The name of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'. + * @param {Boolean} visible true to set the specified control visible, false otherwise + * @return {fabric.Object} thisArg + * @chainable + */ + setControlVisible: function(controlName, visible) { + this._getControlsVisibility()[controlName] = visible; + return this; + }, + + /** + * Sets the visibility state of object controls. + * @param {Object} [options] Options object + * @param {Boolean} [options.bl] true to enable the bottom-left control, false to disable it + * @param {Boolean} [options.br] true to enable the bottom-right control, false to disable it + * @param {Boolean} [options.mb] true to enable the middle-bottom control, false to disable it + * @param {Boolean} [options.ml] true to enable the middle-left control, false to disable it + * @param {Boolean} [options.mr] true to enable the middle-right control, false to disable it + * @param {Boolean} [options.mt] true to enable the middle-top control, false to disable it + * @param {Boolean} [options.tl] true to enable the top-left control, false to disable it + * @param {Boolean} [options.tr] true to enable the top-right control, false to disable it + * @param {Boolean} [options.mtr] true to enable the middle-top-rotate control, false to disable it + * @return {fabric.Object} thisArg + * @chainable + */ + setControlsVisibility: function(options) { + options || (options = { }); + + for (var p in options) { + this.setControlVisible(p, options[p]); + } + return this; + }, + + /** + * Returns the instance of the control visibility set for this object. + * @private + * @returns {Object} + */ + _getControlsVisibility: function() { + if (!this._controlsVisibility) { + this._controlsVisibility = { + tl: true, + tr: true, + br: true, + bl: true, + ml: true, + mt: true, + mr: true, + mb: true, + mtr: true + }; + } + return this._controlsVisibility; + } + }); +})(); + + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Animation duration (in ms) for fx* methods + * @type Number + * @default + */ + FX_DURATION: 500, + + /** + * Centers object horizontally with animation. + * @param {fabric.Object} object Object to center + * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxCenterObjectH: function (object, callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: object.get('left'), + endValue: this.getCenter().left, + duration: this.FX_DURATION, + onChange: function(value) { + object.set('left', value); + _this.renderAll(); + onChange(); + }, + onComplete: function() { + object.setCoords(); + onComplete(); + } + }); + + return this; + }, + + /** + * Centers object vertically with animation. + * @param {fabric.Object} object Object to center + * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxCenterObjectV: function (object, callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: object.get('top'), + endValue: this.getCenter().top, + duration: this.FX_DURATION, + onChange: function(value) { + object.set('top', value); + _this.renderAll(); + onChange(); + }, + onComplete: function() { + object.setCoords(); + onComplete(); + } + }); + + return this; + }, + + /** + * Same as `fabric.Canvas#remove` but animated + * @param {fabric.Object} object Object to remove + * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxRemove: function (object, callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: object.get('opacity'), + endValue: 0, + duration: this.FX_DURATION, + onStart: function() { + object.set('active', false); + }, + onChange: function(value) { + object.set('opacity', value); + _this.renderAll(); + onChange(); + }, + onComplete: function () { + _this.remove(object); + onComplete(); + } + }); + + return this; + } +}); + +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + /** + * Animates object's properties + * @param {String|Object} property to animate (if string) or properties to animate (if object) + * @param {Number|Object} value to animate property to (if string was given first) or options object + * @return {fabric.Object} thisArg + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#animation} + * @chainable + * + * As object — multiple properties + * + * object.animate({ left: ..., top: ... }); + * object.animate({ left: ..., top: ... }, { duration: ... }); + * + * As string — one property + * + * object.animate('left', ...); + * object.animate('left', { duration: ... }); + * + */ + animate: function() { + if (arguments[0] && typeof arguments[0] === 'object') { + var propsToAnimate = [ ], prop, skipCallbacks; + for (prop in arguments[0]) { + propsToAnimate.push(prop); + } + for (var i = 0, len = propsToAnimate.length; i < len; i++) { + prop = propsToAnimate[i]; + skipCallbacks = i !== len - 1; + this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks); + } + } + else { + this._animate.apply(this, arguments); + } + return this; + }, + + /** + * @private + * @param {String} property Property to animate + * @param {String} to Value to animate to + * @param {Object} [options] Options object + * @param {Boolean} [skipCallbacks] When true, callbacks like onchange and oncomplete are not invoked + */ + _animate: function(property, to, options, skipCallbacks) { + var _this = this, propPair; + + to = to.toString(); + + if (!options) { + options = { }; + } + else { + options = fabric.util.object.clone(options); + } + + if (~property.indexOf('.')) { + propPair = property.split('.'); + } + + var currentValue = propPair + ? this.get(propPair[0])[propPair[1]] + : this.get(property); + + if (!('from' in options)) { + options.from = currentValue; + } + + if (~to.indexOf('=')) { + to = currentValue + parseFloat(to.replace('=', '')); + } + else { + to = parseFloat(to); + } + + fabric.util.animate({ + startValue: options.from, + endValue: to, + byValue: options.by, + easing: options.easing, + duration: options.duration, + abort: options.abort && function() { + return options.abort.call(_this); + }, + onChange: function(value) { + if (propPair) { + _this[propPair[0]][propPair[1]] = value; + } + else { + _this.set(property, value); + } + if (skipCallbacks) return; + options.onChange && options.onChange(); + }, + onComplete: function() { + if (skipCallbacks) return; + + _this.setCoords(); + options.onComplete && options.onComplete(); + } + }); + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 }, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Line) { + fabric.warn('fabric.Line is already defined'); + return; + } + + /** + * Line class + * @class fabric.Line + * @extends fabric.Object + * @see {@link fabric.Line#initialize} for constructor definition + */ + fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'line', + + /** + * x value or first line edge + * @type Number + * @default + */ + x1: 0, + + /** + * y value or first line edge + * @type Number + * @default + */ + y1: 0, + + /** + * x value or second line edge + * @type Number + * @default + */ + x2: 0, + + /** + * y value or second line edge + * @type Number + * @default + */ + y2: 0, + + /** + * Constructor + * @param {Array} [points] Array of points + * @param {Object} [options] Options object + * @return {fabric.Line} thisArg + */ + initialize: function(points, options) { + options = options || { }; + + if (!points) { + points = [0, 0, 0, 0]; + } + + this.callSuper('initialize', options); + + this.set('x1', points[0]); + this.set('y1', points[1]); + this.set('x2', points[2]); + this.set('y2', points[3]); + + this._setWidthHeight(options); + }, + + /** + * @private + * @param {Object} [options] Options + */ + _setWidthHeight: function(options) { + options || (options = { }); + + this.width = Math.abs(this.x2 - this.x1) || 1; + this.height = Math.abs(this.y2 - this.y1) || 1; + + this.left = 'left' in options + ? options.left + : this._getLeftToOriginX(); + + this.top = 'top' in options + ? options.top + : this._getTopToOriginY(); + }, + + /** + * @private + * @param {String} key + * @param {Any} value + */ + _set: function(key, value) { + this[key] = value; + if (typeof coordProps[key] !== 'undefined') { + this._setWidthHeight(); + } + return this; + }, + + /** + * @private + * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line. + */ + _getLeftToOriginX: makeEdgeToOriginGetter( + { // property names + origin: 'originX', + axis1: 'x1', + axis2: 'x2', + dimension: 'width' + }, + { // possible values of origin + nearest: 'left', + center: 'center', + farthest: 'right' + } + ), + + /** + * @private + * @return {Number} topToOriginY Distance from top edge of canvas to originY of Line. + */ + _getTopToOriginY: makeEdgeToOriginGetter( + { // property names + origin: 'originY', + axis1: 'y1', + axis2: 'y2', + dimension: 'height' + }, + { // possible values of origin + nearest: 'top', + center: 'center', + farthest: 'bottom' + } + ), + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + ctx.beginPath(); + + var isInPathGroup = this.group && this.group.type === 'path-group'; + if (isInPathGroup && !this.transformMatrix) { + // Line coords are distances from left-top of canvas to origin of line. + // + // To render line in a path-group, we need to translate them to + // distances from center of path-group to center of line. + var cp = this.getCenterPoint(); + ctx.translate( + -this.group.width/2 + cp.x, + -this.group.height / 2 + cp.y + ); + } + + if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) { + + // move from center (of virtual box) to its left/top corner + // we can't assume x1, y1 is top left and x2, y2 is bottom right + var xMult = this.x1 <= this.x2 ? -1 : 1, + yMult = this.y1 <= this.y2 ? -1 : 1; + + ctx.moveTo( + this.width === 1 ? 0 : (xMult * this.width / 2), + this.height === 1 ? 0 : (yMult * this.height / 2)); + + ctx.lineTo( + this.width === 1 ? 0 : (xMult * -1 * this.width / 2), + this.height === 1 ? 0 : (yMult * -1 * this.height / 2)); + } + + ctx.lineWidth = this.strokeWidth; + + // TODO: test this + // make sure setting "fill" changes color of a line + // (by copying fillStyle to strokeStyle, since line is stroked, not filled) + var origStrokeStyle = ctx.strokeStyle; + ctx.strokeStyle = this.stroke || ctx.fillStyle; + this.stroke && this._renderStroke(ctx); + ctx.strokeStyle = origStrokeStyle; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var + xMult = this.x1 <= this.x2 ? -1 : 1, + yMult = this.y1 <= this.y2 ? -1 : 1, + x = this.width === 1 ? 0 : xMult * this.width / 2, + y = this.height === 1 ? 0 : yMult * this.height / 2; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, -x, -y, this.strokeDashArray); + ctx.closePath(); + }, + + /** + * Returns object representation of an instance + * @methd toObject + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + x1: this.get('x1'), + y1: this.get('y1'), + x2: this.get('x2'), + y2: this.get('y2') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(); + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement}) + * @static + * @memberOf fabric.Line + * @see http://www.w3.org/TR/SVG/shapes.html#LineElement + */ + fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' ')); + + /** + * Returns fabric.Line instance from an SVG element + * @static + * @memberOf fabric.Line + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Line} instance of fabric.Line + */ + fabric.Line.fromElement = function(element, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES), + points = [ + parsedAttributes.x1 || 0, + parsedAttributes.y1 || 0, + parsedAttributes.x2 || 0, + parsedAttributes.y2 || 0 + ]; + return new fabric.Line(points, extend(parsedAttributes, options)); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Line instance from an object representation + * @static + * @memberOf fabric.Line + * @param {Object} object Object to create an instance from + * @return {fabric.Line} instance of fabric.Line + */ + fabric.Line.fromObject = function(object) { + var points = [object.x1, object.y1, object.x2, object.y2]; + return new fabric.Line(points, object); + }; + + /** + * Produces a function that calculates distance from canvas edge to Line origin. + */ + function makeEdgeToOriginGetter(propertyNames, originValues) { + var origin = propertyNames.origin, + axis1 = propertyNames.axis1, + axis2 = propertyNames.axis2, + dimension = propertyNames.dimension, + nearest = originValues.nearest, + center = originValues.center, + farthest = originValues.farthest; + + return function() { + switch (this.get(origin)) { + case nearest: + return Math.min(this.get(axis1), this.get(axis2)); + case center: + return Math.min(this.get(axis1), this.get(axis2)) + (0.5 * this.get(dimension)); + case farthest: + return Math.max(this.get(axis1), this.get(axis2)); + } + }; + + } + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + piBy2 = Math.PI * 2, + extend = fabric.util.object.extend; + + if (fabric.Circle) { + fabric.warn('fabric.Circle is already defined.'); + return; + } + + /** + * Circle class + * @class fabric.Circle + * @extends fabric.Object + * @see {@link fabric.Circle#initialize} for constructor definition + */ + fabric.Circle = fabric.util.createClass(fabric.Object, /** @lends fabric.Circle.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'circle', + + /** + * Radius of this circle + * @type Number + * @default + */ + radius: 0, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Circle} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.set('radius', options.radius || 0); + this.callSuper('initialize', options); + }, + + /** + * @private + * @param {String} key + * @param {Any} value + * @return {fabric.Circle} thisArg + */ + _set: function(key, value) { + this.callSuper('_set', key, value); + + if (key === 'radius') { + this.setRadius(value); + } + + return this; + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + radius: this.get('radius') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(); + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param ctx {CanvasRenderingContext2D} context to render on + */ + _render: function(ctx, noTransform) { + ctx.beginPath(); + // multiply by currently set alpha (the one that was set by path group where this object is contained, for example) + ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; + ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.radius, 0, piBy2, false); + this._renderFill(ctx); + this.stroke && this._renderStroke(ctx); + }, + + /** + * Returns horizontal radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusX: function() { + return this.get('radius') * this.get('scaleX'); + }, + + /** + * Returns vertical radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusY: function() { + return this.get('radius') * this.get('scaleY'); + }, + + /** + * Sets radius of an object (and updates width accordingly) + * @return {Number} + */ + setRadius: function(value) { + this.radius = value; + this.set('width', value * 2).set('height', value * 2); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Circle.fromElement}) + * @static + * @memberOf fabric.Circle + * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement + */ + fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy r'.split(' ')); + + /** + * Returns {@link fabric.Circle} instance from an SVG element + * @static + * @memberOf fabric.Circle + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @throws {Error} If value of `r` attribute is missing or invalid + * @return {fabric.Circle} Instance of fabric.Circle + */ + fabric.Circle.fromElement = function(element, options) { + options || (options = { }); + + var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES); + + if (!isValidRadius(parsedAttributes)) { + throw new Error('value of `r` attribute is required and can not be negative'); + } + + if (!('left' in parsedAttributes)) { + parsedAttributes.left = 0; + } + if (!('top' in parsedAttributes)) { + parsedAttributes.top = 0; + } + if (!('transformMatrix' in parsedAttributes)) { + parsedAttributes.left -= (options.width / 2); + parsedAttributes.top -= (options.height / 2); + } + + var obj = new fabric.Circle(extend(parsedAttributes, options)); + + obj.cx = parseFloat(element.getAttribute('cx')) || 0; + obj.cy = parseFloat(element.getAttribute('cy')) || 0; + + return obj; + }; + + /** + * @private + */ + function isValidRadius(attributes) { + return (('radius' in attributes) && (attributes.radius > 0)); + } + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Circle} instance from an object representation + * @static + * @memberOf fabric.Circle + * @param {Object} object Object to create an instance from + * @return {Object} Instance of fabric.Circle + */ + fabric.Circle.fromObject = function(object) { + return new fabric.Circle(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Triangle) { + fabric.warn('fabric.Triangle is already defined'); + return; + } + + /** + * Triangle class + * @class fabric.Triangle + * @extends fabric.Object + * @return {fabric.Triangle} thisArg + * @see {@link fabric.Triangle#initialize} for constructor definition + */ + fabric.Triangle = fabric.util.createClass(fabric.Object, /** @lends fabric.Triangle.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'triangle', + + /** + * Constructor + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + + this.set('width', options.width || 100) + .set('height', options.height || 100); + }, + + /** + * @private + * @param ctx {CanvasRenderingContext2D} Context to render on + */ + _render: function(ctx) { + var widthBy2 = this.width / 2, + heightBy2 = this.height / 2; + + ctx.beginPath(); + ctx.moveTo(-widthBy2, heightBy2); + ctx.lineTo(0, -heightBy2); + ctx.lineTo(widthBy2, heightBy2); + ctx.closePath(); + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param ctx {CanvasRenderingContext2D} Context to render on + */ + _renderDashedStroke: function(ctx) { + var widthBy2 = this.width / 2, + heightBy2 = this.height / 2; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray); + ctx.closePath(); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), + widthBy2 = this.width / 2, + heightBy2 = this.height / 2, + points = [ + -widthBy2 + ' ' + heightBy2, + '0 ' + -heightBy2, + widthBy2 + ' ' + heightBy2 + ] + .join(','); + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /** + * Returns fabric.Triangle instance from an object representation + * @static + * @memberOf fabric.Triangle + * @param object {Object} object to create an instance from + * @return {Object} instance of Canvas.Triangle + */ + fabric.Triangle.fromObject = function(object) { + return new fabric.Triangle(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global){ + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + piBy2 = Math.PI * 2, + extend = fabric.util.object.extend; + + if (fabric.Ellipse) { + fabric.warn('fabric.Ellipse is already defined.'); + return; + } + + /** + * Ellipse class + * @class fabric.Ellipse + * @extends fabric.Object + * @return {fabric.Ellipse} thisArg + * @see {@link fabric.Ellipse#initialize} for constructor definition + */ + fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @lends fabric.Ellipse.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'ellipse', + + /** + * Horizontal radius + * @type Number + * @default + */ + rx: 0, + + /** + * Vertical radius + * @type Number + * @default + */ + ry: 0, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Ellipse} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + + this.set('rx', options.rx || 0); + this.set('ry', options.ry || 0); + + this.set('width', this.get('rx') * 2); + this.set('height', this.get('ry') * 2); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + rx: this.get('rx'), + ry: this.get('ry') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(); + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Renders this instance on a given context + * @param ctx {CanvasRenderingContext2D} context to render on + * @param noTransform {Boolean} context is not transformed when set to true + */ + render: function(ctx, noTransform) { + // do not use `get` for perf. reasons + if (this.rx === 0 || this.ry === 0) return; + return this.callSuper('render', ctx, noTransform); + }, + + /** + * @private + * @param ctx {CanvasRenderingContext2D} context to render on + */ + _render: function(ctx, noTransform) { + ctx.beginPath(); + ctx.save(); + ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; + ctx.transform(1, 0, 0, this.ry/this.rx, 0, 0); + ctx.arc(noTransform ? this.left : 0, noTransform ? this.top * this.rx/this.ry : 0, this.rx, 0, piBy2, false); + this._renderFill(ctx); + this._renderStroke(ctx); + ctx.restore(); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement}) + * @static + * @memberOf fabric.Ellipse + * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement + */ + fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy rx ry'.split(' ')); + + /** + * Returns {@link fabric.Ellipse} instance from an SVG element + * @static + * @memberOf fabric.Ellipse + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Ellipse} + */ + fabric.Ellipse.fromElement = function(element, options) { + options || (options = { }); + + var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES); + + if (!('left' in parsedAttributes)) { + parsedAttributes.left = 0; + } + if (!('top' in parsedAttributes)) { + parsedAttributes.top = 0; + } + if (!('transformMatrix' in parsedAttributes)) { + parsedAttributes.left -= (options.width / 2); + parsedAttributes.top -= (options.height / 2); + } + var ellipse = new fabric.Ellipse(extend(parsedAttributes, options)); + + ellipse.cx = parseFloat(element.getAttribute('cx')) || 0; + ellipse.cy = parseFloat(element.getAttribute('cy')) || 0; + + return ellipse; + }; + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Ellipse} instance from an object representation + * @static + * @memberOf fabric.Ellipse + * @param {Object} object Object to create an instance from + * @return {fabric.Ellipse} + */ + fabric.Ellipse.fromObject = function(object) { + return new fabric.Ellipse(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + if (fabric.Rect) { + console.warn('fabric.Rect is already defined'); + return; + } + + var stateProperties = fabric.Object.prototype.stateProperties.concat(); + stateProperties.push('rx', 'ry', 'x', 'y'); + + /** + * Rectangle class + * @class fabric.Rect + * @extends fabric.Object + * @return {fabric.Rect} thisArg + * @see {@link fabric.Rect#initialize} for constructor definition + */ + fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ { + + /** + * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged}) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: stateProperties, + + /** + * Type of an object + * @type String + * @default + */ + type: 'rect', + + /** + * Horizontal border radius + * @type Number + * @default + */ + rx: 0, + + /** + * Vertical border radius + * @type Number + * @default + */ + ry: 0, + + /** + * @type Number + * @default + */ + x: 0, + + /** + * @type Number + * @default + */ + y: 0, + + /** + * Used to specify dash pattern for stroke on this object + * @type Array + */ + strokeDashArray: null, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + this._initRxRy(); + + this.x = options.x || 0; + this.y = options.y || 0; + }, + + /** + * Initializes rx/ry attributes + * @private + */ + _initRxRy: function() { + if (this.rx && !this.ry) { + this.ry = this.rx; + } + else if (this.ry && !this.rx) { + this.rx = this.ry; + } + }, + + /** + * @private + * @param ctx {CanvasRenderingContext2D} context to render on + */ + _render: function(ctx) { + + // optimize 1x1 case (used in spray brush) + if (this.width === 1 && this.height === 1) { + ctx.fillRect(0, 0, 1, 1); + return; + } + + var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0, + ry = this.ry ? Math.min(this.ry, this.height / 2) : 0, + w = this.width, + h = this.height, + x = -w / 2, + y = -h / 2, + isInPathGroup = this.group && this.group.type === 'path-group', + isRounded = rx !== 0 || ry !== 0, + k = 1 - 0.5522847498 /* "magic number" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */; + + ctx.beginPath(); + ctx.globalAlpha = isInPathGroup ? (ctx.globalAlpha * this.opacity) : this.opacity; + + if (this.transformMatrix && isInPathGroup) { + ctx.translate( + this.width / 2 + this.x, + this.height / 2 + this.y); + } + if (!this.transformMatrix && isInPathGroup) { + ctx.translate( + -this.group.width / 2 + this.width / 2 + this.x, + -this.group.height / 2 + this.height / 2 + this.y); + } + + ctx.moveTo(x + rx, y); + + ctx.lineTo(x + w - rx, y); + isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry); + + ctx.lineTo(x + w, y + h - ry); + isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h); + + ctx.lineTo(x + rx, y + h); + isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry); + + ctx.lineTo(x, y + ry); + isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y); + + ctx.closePath(); + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param ctx {CanvasRenderingContext2D} context to render on + */ + _renderDashedStroke: function(ctx) { + var x = -this.width / 2, + y = -this.height / 2, + w = this.width, + h = this.height; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray); + ctx.closePath(); + }, + + /** + * Since coordinate system differs from that of SVG + * @private + */ + _normalizeLeftTopProperties: function(parsedAttributes) { + if ('left' in parsedAttributes) { + this.set('left', parsedAttributes.left + this.getWidth() / 2); + } + this.set('x', parsedAttributes.left || 0); + if ('top' in parsedAttributes) { + this.set('top', parsedAttributes.top + this.getHeight() / 2); + } + this.set('y', parsedAttributes.top || 0); + return this; + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var object = extend(this.callSuper('toObject', propertiesToInclude), { + rx: this.get('rx') || 0, + ry: this.get('ry') || 0, + x: this.get('x'), + y: this.get('y') + }); + if (!this.includeDefaultValues) { + this._removeDefaultValues(object); + } + return object; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(); + + markup.push( + ''); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`) + * @static + * @memberOf fabric.Rect + * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement + */ + fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' ')); + + /** + * @private + */ + function _setDefaultLeftTopValues(attributes) { + attributes.left = attributes.left || 0; + attributes.top = attributes.top || 0; + return attributes; + } + + /** + * Returns {@link fabric.Rect} instance from an SVG element + * @static + * @memberOf fabric.Rect + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Rect} Instance of fabric.Rect + */ + fabric.Rect.fromElement = function(element, options) { + if (!element) { + return null; + } + + var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES); + parsedAttributes = _setDefaultLeftTopValues(parsedAttributes); + + var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + rect._normalizeLeftTopProperties(parsedAttributes); + + return rect; + }; + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Rect} instance from an object representation + * @static + * @memberOf fabric.Rect + * @param object {Object} object to create an instance from + * @return {Object} instance of fabric.Rect + */ + fabric.Rect.fromObject = function(object) { + return new fabric.Rect(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + toFixed = fabric.util.toFixed; + + if (fabric.Polyline) { + fabric.warn('fabric.Polyline is already defined'); + return; + } + + /** + * Polyline class + * @class fabric.Polyline + * @extends fabric.Object + * @see {@link fabric.Polyline#initialize} for constructor definition + */ + fabric.Polyline = fabric.util.createClass(fabric.Object, /** @lends fabric.Polyline.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'polyline', + + /** + * Points array + * @type Array + * @default + */ + points: null, + + /** + * Constructor + * @param {Array} points Array of points (where each point is an object with x and y) + * @param {Object} [options] Options object + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + * @return {fabric.Polyline} thisArg + * @example + * var poly = new fabric.Polyline([ + * { x: 10, y: 10 }, + * { x: 50, y: 30 }, + * { x: 40, y: 70 }, + * { x: 60, y: 50 }, + * { x: 100, y: 150 }, + * { x: 40, y: 100 } + * ], { + * stroke: 'red', + * left: 100, + * top: 100 + * }); + */ + initialize: function(points, options, skipOffset) { + options = options || { }; + this.set('points', points); + this.callSuper('initialize', options); + this._calcDimensions(skipOffset); + }, + + /** + * @private + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + */ + _calcDimensions: function(skipOffset) { + return fabric.Polygon.prototype._calcDimensions.call(this, skipOffset); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return fabric.Polygon.prototype.toObject.call(this, propertiesToInclude); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var points = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.points.length; i < len; i++) { + points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' '); + } + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + var point; + ctx.beginPath(); + ctx.moveTo(this.points[0].x, this.points[0].y); + for (var i = 0, len = this.points.length; i < len; i++) { + point = this.points[i]; + ctx.lineTo(point.x, point.y); + } + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var p1, p2; + + ctx.beginPath(); + for (var i = 0, len = this.points.length; i < len; i++) { + p1 = this.points[i]; + p2 = this.points[i + 1] || p1; + fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); + } + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.get('points').length; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement}) + * @static + * @memberOf fabric.Polyline + * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement + */ + fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + + /** + * Returns fabric.Polyline instance from an SVG element + * @static + * @memberOf fabric.Polyline + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Polyline} Instance of fabric.Polyline + */ + fabric.Polyline.fromElement = function(element, options) { + if (!element) { + return null; + } + options || (options = { }); + + var points = fabric.parsePointsAttribute(element.getAttribute('points')), + parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES); + + fabric.util.normalizePoints(points, options); + + return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options), true); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Polyline instance from an object representation + * @static + * @memberOf fabric.Polyline + * @param object {Object} object Object to create an instance from + * @return {fabric.Polyline} Instance of fabric.Polyline + */ + fabric.Polyline.fromObject = function(object) { + var points = object.points; + return new fabric.Polyline(points, object, true); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + min = fabric.util.array.min, + max = fabric.util.array.max, + toFixed = fabric.util.toFixed; + + if (fabric.Polygon) { + fabric.warn('fabric.Polygon is already defined'); + return; + } + + /** + * Polygon class + * @class fabric.Polygon + * @extends fabric.Object + * @see {@link fabric.Polygon#initialize} for constructor definition + */ + fabric.Polygon = fabric.util.createClass(fabric.Object, /** @lends fabric.Polygon.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'polygon', + + /** + * Points array + * @type Array + * @default + */ + points: null, + + /** + * Constructor + * @param {Array} points Array of points + * @param {Object} [options] Options object + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + * @return {fabric.Polygon} thisArg + */ + initialize: function(points, options, skipOffset) { + options = options || { }; + this.points = points; + this.callSuper('initialize', options); + this._calcDimensions(skipOffset); + }, + + /** + * @private + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + */ + _calcDimensions: function(skipOffset) { + + var points = this.points, + minX = min(points, 'x'), + minY = min(points, 'y'), + maxX = max(points, 'x'), + maxY = max(points, 'y'); + + this.width = (maxX - minX) || 1; + this.height = (maxY - minY) || 1; + + this.minX = minX; + this.minY = minY; + + if (skipOffset) return; + + var halfWidth = this.width / 2 + this.minX, + halfHeight = this.height / 2 + this.minY; + + // change points to offset polygon into a bounding box + this.points.forEach(function(p) { + p.x -= halfWidth; + p.y -= halfHeight; + }, this); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + points: this.points.concat() + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var points = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.points.length; i < len; i++) { + points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' '); + } + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + var point; + ctx.beginPath(); + ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; + ctx.moveTo(this.points[0].x, this.points[0].y); + for (var i = 0, len = this.points.length; i < len; i++) { + point = this.points[i]; + ctx.lineTo(point.x, point.y); + } + this._renderFill(ctx); + if (this.stroke || this.strokeDashArray) { + ctx.closePath(); + this._renderStroke(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var p1, p2; + + ctx.beginPath(); + for (var i = 0, len = this.points.length; i < len; i++) { + p1 = this.points[i]; + p2 = this.points[i + 1] || this.points[0]; + fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); + } + ctx.closePath(); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.points.length; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`) + * @static + * @memberOf fabric.Polygon + * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement + */ + fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + + /** + * Returns {@link fabric.Polygon} instance from an SVG element + * @static + * @memberOf fabric.Polygon + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Polygon} Instance of fabric.Polygon + */ + fabric.Polygon.fromElement = function(element, options) { + if (!element) { + return null; + } + options || (options = { }); + + var points = fabric.parsePointsAttribute(element.getAttribute('points')), + parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES); + + fabric.util.normalizePoints(points, options); + + return new fabric.Polygon(points, extend(parsedAttributes, options), true); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Polygon instance from an object representation + * @static + * @memberOf fabric.Polygon + * @param object {Object} object Object to create an instance from + * @return {fabric.Polygon} Instance of fabric.Polygon + */ + fabric.Polygon.fromObject = function(object) { + return new fabric.Polygon(object.points, object, true); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + min = fabric.util.array.min, + max = fabric.util.array.max, + extend = fabric.util.object.extend, + _toString = Object.prototype.toString, + drawArc = fabric.util.drawArc, + commandLengths = { + m: 2, + l: 2, + h: 1, + v: 1, + c: 6, + s: 4, + q: 4, + t: 2, + a: 7 + }, + repeatedCommands = { + m: 'l', + M: 'L' + }; + + if (fabric.Path) { + fabric.warn('fabric.Path is already defined'); + return; + } + + /** + * @private + */ + function getX(item) { + if (item[0] === 'H') { + return item[1]; + } + return item[item.length - 2]; + } + + /** + * @private + */ + function getY(item) { + if (item[0] === 'V') { + return item[1]; + } + return item[item.length - 1]; + } + + /** + * Path class + * @class fabric.Path + * @extends fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup} + * @see {@link fabric.Path#initialize} for constructor definition + */ + fabric.Path = fabric.util.createClass(fabric.Object, /** @lends fabric.Path.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'path', + + /** + * Array of path points + * @type Array + * @default + */ + path: null, + + /** + * Constructor + * @param {Array|String} path Path data (sequence of coordinates and corresponding "command" tokens) + * @param {Object} [options] Options object + * @return {fabric.Path} thisArg + */ + initialize: function(path, options) { + options = options || { }; + + this.setOptions(options); + + if (!path) { + throw new Error('`path` argument is required'); + } + + var fromArray = _toString.call(path) === '[object Array]'; + + this.path = fromArray + ? path + // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values) + : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi); + + if (!this.path) return; + + if (!fromArray) { + this.path = this._parsePath(); + } + this._initializePath(options); + + if (options.sourcePath) { + this.setSourcePath(options.sourcePath); + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initializePath: function (options) { + var isWidthSet = 'width' in options && options.width != null, + isHeightSet = 'height' in options && options.width != null, + isLeftSet = 'left' in options, + isTopSet = 'top' in options, + origLeft = isLeftSet ? this.left : 0, + origTop = isTopSet ? this.top : 0; + + if (!isWidthSet || !isHeightSet) { + extend(this, this._parseDimensions()); + if (isWidthSet) { + this.width = options.width; + } + if (isHeightSet) { + this.height = options.height; + } + } + else { //Set center location relative to given height/width if not specified + if (!isTopSet) { + this.top = this.height / 2; + } + if (!isLeftSet) { + this.left = this.width / 2; + } + } + this.pathOffset = this.pathOffset || + // Save top-left coords as offset + this._calculatePathOffset(origLeft, origTop); + }, + + /** + * @private + * @param {Boolean} positionSet When false, path offset is returned otherwise 0 + */ + _calculatePathOffset: function (origLeft, origTop) { + return { + x: this.left - origLeft - (this.width / 2), + y: this.top - origTop - (this.height / 2) + }; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx context to render path on + */ + _render: function(ctx) { + var current, // current instruction + previous = null, + subpathStartX = 0, + subpathStartY = 0, + x = 0, // current x + y = 0, // current y + controlX = 0, // current control point x + controlY = 0, // current control point y + tempX, + tempY, + tempControlX, + tempControlY, + l = -((this.width / 2) + this.pathOffset.x), + t = -((this.height / 2) + this.pathOffset.y); + + for (var i = 0, len = this.path.length; i < len; ++i) { + + current = this.path[i]; + + switch (current[0]) { // first letter + + case 'l': // lineto, relative + x += current[1]; + y += current[2]; + ctx.lineTo(x + l, y + t); + break; + + case 'L': // lineto, absolute + x = current[1]; + y = current[2]; + ctx.lineTo(x + l, y + t); + break; + + case 'h': // horizontal lineto, relative + x += current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'H': // horizontal lineto, absolute + x = current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'v': // vertical lineto, relative + y += current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'V': // verical lineto, absolute + y = current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'm': // moveTo, relative + x += current[1]; + y += current[2]; + subpathStartX = x; + subpathStartY = y; + ctx.moveTo(x + l, y + t); + break; + + case 'M': // moveTo, absolute + x = current[1]; + y = current[2]; + subpathStartX = x; + subpathStartY = y; + ctx.moveTo(x + l, y + t); + break; + + case 'c': // bezierCurveTo, relative + tempX = x + current[5]; + tempY = y + current[6]; + controlX = x + current[3]; + controlY = y + current[4]; + ctx.bezierCurveTo( + x + current[1] + l, // x1 + y + current[2] + t, // y1 + controlX + l, // x2 + controlY + t, // y2 + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'C': // bezierCurveTo, absolute + x = current[5]; + y = current[6]; + controlX = current[3]; + controlY = current[4]; + ctx.bezierCurveTo( + current[1] + l, + current[2] + t, + controlX + l, + controlY + t, + x + l, + y + t + ); + break; + + case 's': // shorthand cubic bezierCurveTo, relative + + // transform to absolute x,y + tempX = x + current[3]; + tempY = y + current[4]; + + // calculate reflection of previous control points + controlX = controlX ? (2 * x - controlX) : x; + controlY = controlY ? (2 * y - controlY) : y; + + ctx.bezierCurveTo( + controlX + l, + controlY + t, + x + current[1] + l, + y + current[2] + t, + tempX + l, + tempY + t + ); + // set control point to 2nd one of this command + // "... the first control point is assumed to be + // the reflection of the second control point on + // the previous command relative to the current point." + controlX = x + current[1]; + controlY = y + current[2]; + + x = tempX; + y = tempY; + break; + + case 'S': // shorthand cubic bezierCurveTo, absolute + tempX = current[3]; + tempY = current[4]; + // calculate reflection of previous control points + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + ctx.bezierCurveTo( + controlX + l, + controlY + t, + current[1] + l, + current[2] + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + + // set control point to 2nd one of this command + // "... the first control point is assumed to be + // the reflection of the second control point on + // the previous command relative to the current point." + controlX = current[1]; + controlY = current[2]; + + break; + + case 'q': // quadraticCurveTo, relative + // transform to absolute x,y + tempX = x + current[3]; + tempY = y + current[4]; + + controlX = x + current[1]; + controlY = y + current[2]; + + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'Q': // quadraticCurveTo, absolute + tempX = current[3]; + tempY = current[4]; + + ctx.quadraticCurveTo( + current[1] + l, + current[2] + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + controlX = current[1]; + controlY = current[2]; + break; + + case 't': // shorthand quadraticCurveTo, relative + + // transform to absolute x,y + tempX = x + current[1]; + tempY = y + current[2]; + + if (previous[0].match(/[QqTt]/) === null) { + // If there is no previous command or if the previous command was not a Q, q, T or t, + // assume the control point is coincident with the current point + controlX = x; + controlY = y; + } + else if (previous[0] === 't') { + // calculate reflection of previous control points for t + controlX = 2 * x - tempControlX; + controlY = 2 * y - tempControlY; + } + else if (previous[0] === 'q') { + // calculate reflection of previous control points for q + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + + tempControlX = controlX; + tempControlY = controlY; + + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + controlX = x + current[1]; + controlY = y + current[2]; + break; + + case 'T': + tempX = current[1]; + tempY = current[2]; + + // calculate reflection of previous control points + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'a': + // TODO: optimize this + drawArc(ctx, x + l, y + t, [ + current[1], + current[2], + current[3], + current[4], + current[5], + current[6] + x + l, + current[7] + y + t + ]); + x += current[6]; + y += current[7]; + break; + + case 'A': + // TODO: optimize this + drawArc(ctx, x + l, y + t, [ + current[1], + current[2], + current[3], + current[4], + current[5], + current[6] + l, + current[7] + t + ]); + x = current[6]; + y = current[7]; + break; + + case 'z': + case 'Z': + x = subpathStartX; + y = subpathStartY; + ctx.closePath(); + break; + } + previous = current; + } + }, + + /** + * Renders path on a specified context + * @param {CanvasRenderingContext2D} ctx context to render path on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if object is not visible + if (!this.visible) return; + + ctx.save(); + var m = this.transformMatrix; + + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + if (!noTransform) { + this.transform(ctx); + } + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + ctx.beginPath(); + ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; + this._render(ctx); + this._renderFill(ctx); + this._renderStroke(ctx); + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * Returns string representation of an instance + * @return {String} string representation of an instance + */ + toString: function() { + return '#'; + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var o = extend(this.callSuper('toObject', propertiesToInclude), { + path: this.path.map(function(item) { return item.slice() }), + pathOffset: this.pathOffset + }); + if (this.sourcePath) { + o.sourcePath = this.sourcePath; + } + if (this.transformMatrix) { + o.transformMatrix = this.transformMatrix; + } + return o; + }, + + /** + * Returns dataless object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + var o = this.toObject(propertiesToInclude); + if (this.sourcePath) { + o.path = this.sourcePath; + } + delete o.sourcePath; + return o; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var chunks = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.path.length; i < len; i++) { + chunks.push(this.path[i].join(' ')); + } + var path = chunks.join(' '); + + markup.push( + '', + '', + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns number representation of an instance complexity + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.path.length; + }, + + /** + * @private + */ + _parsePath: function() { + var result = [ ], + coords = [ ], + currentPath, + parsed, + re = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/ig, + match, + coordsStr; + + for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) { + currentPath = this.path[i]; + + coordsStr = currentPath.slice(1).trim(); + coords.length = 0; + + while ((match = re.exec(coordsStr))) { + coords.push(match[0]); + } + + coordsParsed = [ currentPath.charAt(0) ]; + + for (var j = 0, jlen = coords.length; j < jlen; j++) { + parsed = parseFloat(coords[j]); + if (!isNaN(parsed)) { + coordsParsed.push(parsed); + } + } + + var command = coordsParsed[0], + commandLength = commandLengths[command.toLowerCase()], + repeatedCommand = repeatedCommands[command] || command; + + if (coordsParsed.length - 1 > commandLength) { + for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) { + result.push([ command ].concat(coordsParsed.slice(k, k + commandLength))); + command = repeatedCommand; + } + } + else { + result.push(coordsParsed); + } + } + + return result; + }, + + /** + * @private + */ + _parseDimensions: function() { + var aX = [], + aY = [], + previous = { }; + + this.path.forEach(function(item, i) { + this._getCoordsFromCommand(item, i, aX, aY, previous); + }, this); + + var minX = min(aX), + minY = min(aY), + maxX = max(aX), + maxY = max(aY), + deltaX = maxX - minX, + deltaY = maxY - minY, + + o = { + left: this.left + (minX + deltaX / 2), + top: this.top + (minY + deltaY / 2), + width: deltaX, + height: deltaY + }; + + return o; + }, + + _getCoordsFromCommand: function(item, i, aX, aY, previous) { + var isLowerCase = false; + + if (item[0] !== 'H') { + previous.x = (i === 0) ? getX(item) : getX(this.path[i - 1]); + } + if (item[0] !== 'V') { + previous.y = (i === 0) ? getY(item) : getY(this.path[i - 1]); + } + + // lowercased letter denotes relative position; + // transform to absolute + if (item[0] === item[0].toLowerCase()) { + isLowerCase = true; + } + + var xy = this._getXY(item, isLowerCase, previous), + val; + + val = parseInt(xy.x, 10); + if (!isNaN(val)) { + aX.push(val); + } + + val = parseInt(xy.y, 10); + if (!isNaN(val)) { + aY.push(val); + } + }, + + _getXY: function(item, isLowerCase, previous) { + + // last 2 items in an array of coordinates are the actualy x/y (except H/V), collect them + // TODO (kangax): support relative h/v commands + + var x = isLowerCase + ? previous.x + getX(item) + : item[0] === 'V' + ? previous.x + : getX(item), + + y = isLowerCase + ? previous.y + getY(item) + : item[0] === 'H' + ? previous.y + : getY(item); + + return { x: x, y: y }; + } + }); + + /** + * Creates an instance of fabric.Path from an object + * @static + * @memberOf fabric.Path + * @param {Object} object + * @param {Function} callback Callback to invoke when an fabric.Path instance is created + */ + fabric.Path.fromObject = function(object, callback) { + if (typeof object.path === 'string') { + fabric.loadSVGFromURL(object.path, function (elements) { + var path = elements[0], + pathUrl = object.path; + + delete object.path; + + fabric.util.object.extend(path, object); + path.setSourcePath(pathUrl); + + callback(path); + }); + } + else { + callback(new fabric.Path(object.path, object)); + } + }; + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Path.fromElement`) + * @static + * @memberOf fabric.Path + * @see http://www.w3.org/TR/SVG/paths.html#PathElement + */ + fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(['d']); + + /** + * Creates an instance of fabric.Path from an SVG element + * @static + * @memberOf fabric.Path + * @param {SVGElement} element to parse + * @param {Function} callback Callback to invoke when an fabric.Path instance is created + * @param {Object} [options] Options object + */ + fabric.Path.fromElement = function(element, callback, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES); + callback && callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options))); + }; + /* _FROM_SVG_END_ */ + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.Path + * @type Boolean + * @default + */ + fabric.Path.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + invoke = fabric.util.array.invoke, + parentToObject = fabric.Object.prototype.toObject; + + if (fabric.PathGroup) { + fabric.warn('fabric.PathGroup is already defined'); + return; + } + + /** + * Path group class + * @class fabric.PathGroup + * @extends fabric.Path + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup} + * @see {@link fabric.PathGroup#initialize} for constructor definition + */ + fabric.PathGroup = fabric.util.createClass(fabric.Path, /** @lends fabric.PathGroup.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'path-group', + + /** + * Fill value + * @type String + * @default + */ + fill: '', + + /** + * Constructor + * @param {Array} paths + * @param {Object} [options] Options object + * @return {fabric.PathGroup} thisArg + */ + initialize: function(paths, options) { + + options = options || { }; + this.paths = paths || [ ]; + + for (var i = this.paths.length; i--; ) { + this.paths[i].group = this; + } + + this.setOptions(options); + + if (options.widthAttr) { + this.scaleX = options.widthAttr / options.width; + } + if (options.heightAttr) { + this.scaleY = options.heightAttr / options.height; + } + + this.setCoords(); + + if (options.sourcePath) { + this.setSourcePath(options.sourcePath); + } + }, + + /** + * Renders this group on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render this instance on + */ + render: function(ctx) { + // do not render if object is not visible + if (!this.visible) return; + + ctx.save(); + + var m = this.transformMatrix; + + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + this.transform(ctx); + + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + for (var i = 0, l = this.paths.length; i < l; ++i) { + this.paths[i].render(ctx, true); + } + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * Sets certain property to a certain value + * @param {String} prop + * @param {Any} value + * @return {fabric.PathGroup} thisArg + */ + _set: function(prop, value) { + + if (prop === 'fill' && value && this.isSameColor()) { + var i = this.paths.length; + while (i--) { + this.paths[i]._set(prop, value); + } + } + + return this.callSuper('_set', prop, value); + }, + + /** + * Returns object representation of this path group + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var o = extend(parentToObject.call(this, propertiesToInclude), { + paths: invoke(this.getObjects(), 'toObject', propertiesToInclude) + }); + if (this.sourcePath) { + o.sourcePath = this.sourcePath; + } + return o; + }, + + /** + * Returns dataless object representation of this path group + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} dataless object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + var o = this.toObject(propertiesToInclude); + if (this.sourcePath) { + o.paths = this.sourcePath; + } + return o; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var objects = this.getObjects(), + markup = [ + '' + ]; + + for (var i = 0, len = objects.length; i < len; i++) { + markup.push(objects[i].toSVG(reviver)); + } + markup.push(''); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns a string representation of this path group + * @return {String} string representation of an object + */ + toString: function() { + return '#'; + }, + + /** + * Returns true if all paths in this group are of same color + * @return {Boolean} true if all paths are of the same color (`fill`) + */ + isSameColor: function() { + var firstPathFill = (this.getObjects()[0].get('fill') || '').toLowerCase(); + return this.getObjects().every(function(path) { + return (path.get('fill') || '').toLowerCase() === firstPathFill; + }); + }, + + /** + * Returns number representation of object's complexity + * @return {Number} complexity + */ + complexity: function() { + return this.paths.reduce(function(total, path) { + return total + ((path && path.complexity) ? path.complexity() : 0); + }, 0); + }, + + /** + * Returns all paths in this path group + * @return {Array} array of path objects included in this path group + */ + getObjects: function() { + return this.paths; + } + }); + + /** + * Creates fabric.PathGroup instance from an object representation + * @static + * @memberOf fabric.PathGroup + * @param {Object} object Object to create an instance from + * @param {Function} callback Callback to invoke when an fabric.PathGroup instance is created + */ + fabric.PathGroup.fromObject = function(object, callback) { + if (typeof object.paths === 'string') { + fabric.loadSVGFromURL(object.paths, function (elements) { + + var pathUrl = object.paths; + delete object.paths; + + var pathGroup = fabric.util.groupSVGElements(elements, object, pathUrl); + + callback(pathGroup); + }); + } + else { + fabric.util.enlivenObjects(object.paths, function(enlivenedObjects) { + delete object.paths; + callback(new fabric.PathGroup(enlivenedObjects, object)); + }); + } + }; + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.PathGroup + * @type Boolean + * @default + */ + fabric.PathGroup.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global){ + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + min = fabric.util.array.min, + max = fabric.util.array.max, + invoke = fabric.util.array.invoke; + + if (fabric.Group) { + return; + } + + // lock-related properties, for use in fabric.Group#get + // to enable locking behavior on group + // when one of its objects has lock-related properties set + var _lockProperties = { + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + lockUniScaling: true + }; + + /** + * Group class + * @class fabric.Group + * @extends fabric.Object + * @mixes fabric.Collection + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#groups} + * @see {@link fabric.Group#initialize} for constructor definition + */ + fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, /** @lends fabric.Group.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'group', + + /** + * Constructor + * @param {Object} objects Group objects + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(objects, options) { + options = options || { }; + + this._objects = objects || []; + for (var i = this._objects.length; i--; ) { + this._objects[i].group = this; + } + + this.originalState = { }; + this.callSuper('initialize'); + + this._calcBounds(); + this._updateObjectsCoords(); + + if (options) { + extend(this, options); + } + this._setOpacityIfSame(); + + this.setCoords(); + this.saveCoords(); + }, + + /** + * @private + */ + _updateObjectsCoords: function() { + this.forEachObject(this._updateObjectCoords, this); + }, + + /** + * @private + */ + _updateObjectCoords: function(object) { + var objectLeft = object.getLeft(), + objectTop = object.getTop(); + + object.set({ + originalLeft: objectLeft, + originalTop: objectTop, + left: objectLeft - this.left, + top: objectTop - this.top + }); + + object.setCoords(); + + // do not display corners of objects enclosed in a group + object.__origHasControls = object.hasControls; + object.hasControls = false; + }, + + /** + * Returns string represenation of a group + * @return {String} + */ + toString: function() { + return '#'; + }, + + /** + * Adds an object to a group; Then recalculates group's dimension, position. + * @param {Object} object + * @return {fabric.Group} thisArg + * @chainable + */ + addWithUpdate: function(object) { + this._restoreObjectsState(); + if (object) { + this._objects.push(object); + object.group = this; + } + // since _restoreObjectsState set objects inactive + this.forEachObject(this._setObjectActive, this); + this._calcBounds(); + this._updateObjectsCoords(); + return this; + }, + + /** + * @private + */ + _setObjectActive: function(object) { + object.set('active', true); + object.group = this; + }, + + /** + * Removes an object from a group; Then recalculates group's dimension, position. + * @param {Object} object + * @return {fabric.Group} thisArg + * @chainable + */ + removeWithUpdate: function(object) { + this._moveFlippedObject(object); + this._restoreObjectsState(); + + // since _restoreObjectsState set objects inactive + this.forEachObject(this._setObjectActive, this); + + this.remove(object); + this._calcBounds(); + this._updateObjectsCoords(); + + return this; + }, + + /** + * @private + */ + _onObjectAdded: function(object) { + object.group = this; + }, + + /** + * @private + */ + _onObjectRemoved: function(object) { + delete object.group; + object.set('active', false); + }, + + /** + * Properties that are delegated to group objects when reading/writing + * @param {Object} delegatedProperties + */ + delegatedProperties: { + fill: true, + opacity: true, + fontFamily: true, + fontWeight: true, + fontSize: true, + fontStyle: true, + lineHeight: true, + textDecoration: true, + textAlign: true, + backgroundColor: true + }, + + /** + * @private + */ + _set: function(key, value) { + if (key in this.delegatedProperties) { + var i = this._objects.length; + this[key] = value; + while (i--) { + this._objects[i].set(key, value); + } + } + else { + this[key] = value; + } + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + objects: invoke(this._objects, 'toObject', propertiesToInclude) + }); + }, + + /** + * Renders instance on a given context + * @param {CanvasRenderingContext2D} ctx context to render instance on + */ + render: function(ctx) { + // do not render if object is not visible + if (!this.visible) return; + + ctx.save(); + this.clipTo && fabric.util.clipContext(this, ctx); + + // the array is now sorted in order of highest first, so start from end + for (var i = 0, len = this._objects.length; i < len; i++) { + this._renderObject(this._objects[i], ctx); + } + + this.clipTo && ctx.restore(); + + ctx.restore(); + }, + + /** + * Renders controls and borders for the object + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + _renderControls: function(ctx, noTransform) { + this.callSuper('_renderControls', ctx, noTransform); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i]._renderControls(ctx); + } + }, + + /** + * @private + */ + _renderObject: function(object, ctx) { + var originalHasRotatingPoint = object.hasRotatingPoint; + + // do not render if object is not visible + if (!object.visible) return; + + object.hasRotatingPoint = false; + + object.render(ctx); + + object.hasRotatingPoint = originalHasRotatingPoint; + }, + + /** + * Retores original state of each of group objects (original state is that which was before group was created). + * @private + * @return {fabric.Group} thisArg + * @chainable + */ + _restoreObjectsState: function() { + this._objects.forEach(this._restoreObjectState, this); + return this; + }, + + /** + * Moves a flipped object to the position where it's displayed + * @private + * @param {fabric.Object} object + * @return {fabric.Group} thisArg + */ + _moveFlippedObject: function(object) { + var oldOriginX = object.get('originX'), + oldOriginY = object.get('originY'), + center = object.getCenterPoint(); + + object.set({ + originX: 'center', + originY: 'center', + left: center.x, + top: center.y + }); + + this._toggleFlipping(object); + + var newOrigin = object.getPointByOrigin(oldOriginX, oldOriginY); + + object.set({ + originX: oldOriginX, + originY: oldOriginY, + left: newOrigin.x, + top: newOrigin.y + }); + + return this; + }, + + /** + * @private + */ + _toggleFlipping: function(object) { + if (this.flipX) { + object.toggle('flipX'); + object.set('left', -object.get('left')); + object.setAngle(-object.getAngle()); + } + if (this.flipY) { + object.toggle('flipY'); + object.set('top', -object.get('top')); + object.setAngle(-object.getAngle()); + } + }, + + /** + * Restores original state of a specified object in group + * @private + * @param {fabric.Object} object + * @return {fabric.Group} thisArg + */ + _restoreObjectState: function(object) { + this._setObjectPosition(object); + + object.setCoords(); + object.hasControls = object.__origHasControls; + delete object.__origHasControls; + object.set('active', false); + object.setCoords(); + delete object.group; + + return this; + }, + + /** + * @private + */ + _setObjectPosition: function(object) { + var groupLeft = this.getLeft(), + groupTop = this.getTop(), + rotated = this._getRotatedLeftTop(object); + + object.set({ + angle: object.getAngle() + this.getAngle(), + left: groupLeft + rotated.left, + top: groupTop + rotated.top, + scaleX: object.get('scaleX') * this.get('scaleX'), + scaleY: object.get('scaleY') * this.get('scaleY') + }); + }, + + /** + * @private + */ + _getRotatedLeftTop: function(object) { + var groupAngle = this.getAngle() * (Math.PI / 180); + return { + left: (-Math.sin(groupAngle) * object.getTop() * this.get('scaleY') + + Math.cos(groupAngle) * object.getLeft() * this.get('scaleX')), + + top: (Math.cos(groupAngle) * object.getTop() * this.get('scaleY') + + Math.sin(groupAngle) * object.getLeft() * this.get('scaleX')) + }; + }, + + /** + * Destroys a group (restoring state of its objects) + * @return {fabric.Group} thisArg + * @chainable + */ + destroy: function() { + this._objects.forEach(this._moveFlippedObject, this); + return this._restoreObjectsState(); + }, + + /** + * Saves coordinates of this instance (to be used together with `hasMoved`) + * @saveCoords + * @return {fabric.Group} thisArg + * @chainable + */ + saveCoords: function() { + this._originalLeft = this.get('left'); + this._originalTop = this.get('top'); + return this; + }, + + /** + * Checks whether this group was moved (since `saveCoords` was called last) + * @return {Boolean} true if an object was moved (since fabric.Group#saveCoords was called) + */ + hasMoved: function() { + return this._originalLeft !== this.get('left') || + this._originalTop !== this.get('top'); + }, + + /** + * Sets coordinates of all group objects + * @return {fabric.Group} thisArg + * @chainable + */ + setObjectsCoords: function() { + this.forEachObject(function(object) { + object.setCoords(); + }); + return this; + }, + + /** + * @private + */ + _setOpacityIfSame: function() { + var objects = this.getObjects(), + firstValue = objects[0] ? objects[0].get('opacity') : 1, + isSameOpacity = objects.every(function(o) { + return o.get('opacity') === firstValue; + }); + + if (isSameOpacity) { + this.opacity = firstValue; + } + }, + + /** + * @private + */ + _calcBounds: function(onlyWidthHeight) { + var aX = [], + aY = [], + o; + + for (var i = 0, len = this._objects.length; i < len; ++i) { + o = this._objects[i]; + o.setCoords(); + for (var prop in o.oCoords) { + aX.push(o.oCoords[prop].x); + aY.push(o.oCoords[prop].y); + } + } + + this.set(this._getBounds(aX, aY, onlyWidthHeight)); + }, + + /** + * @private + */ + _getBounds: function(aX, aY, onlyWidthHeight) { + var ivt = fabric.util.invertTransform(this.getViewportTransform()), + minXY = fabric.util.transformPoint(new fabric.Point(min(aX), min(aY)), ivt), + maxXY = fabric.util.transformPoint(new fabric.Point(max(aX), max(aY)), ivt), + obj = { + width: (maxXY.x - minXY.x) || 0, + height: (maxXY.y - minXY.y) || 0 + }; + + if (!onlyWidthHeight) { + obj.left = (minXY.x + maxXY.x) / 2 || 0; + obj.top = (minXY.y + maxXY.y) / 2 || 0; + } + return obj; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = [ + '' + ]; + + for (var i = 0, len = this._objects.length; i < len; i++) { + markup.push(this._objects[i].toSVG(reviver)); + } + + markup.push(''); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns requested property + * @param {String} prop Property to get + * @return {Any} + */ + get: function(prop) { + if (prop in _lockProperties) { + if (this[prop]) { + return this[prop]; + } + else { + for (var i = 0, len = this._objects.length; i < len; i++) { + if (this._objects[i][prop]) { + return true; + } + } + return false; + } + } + else { + if (prop in this.delegatedProperties) { + return this._objects[0] && this._objects[0].get(prop); + } + return this[prop]; + } + } + }); + + /** + * Returns {@link fabric.Group} instance from an object representation + * @static + * @memberOf fabric.Group + * @param {Object} object Object to create a group from + * @param {Object} [options] Options object + * @return {fabric.Group} An instance of fabric.Group + */ + fabric.Group.fromObject = function(object, callback) { + fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) { + delete object.objects; + callback && callback(new fabric.Group(enlivenedObjects, object)); + }); + }; + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.Group + * @type Boolean + * @default + */ + fabric.Group.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var extend = fabric.util.object.extend; + + if (!global.fabric) { + global.fabric = { }; + } + + if (global.fabric.Image) { + fabric.warn('fabric.Image is already defined.'); + return; + } + + /** + * Image class + * @class fabric.Image + * @extends fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#images} + * @see {@link fabric.Image#initialize} for constructor definition + */ + fabric.Image = fabric.util.createClass(fabric.Object, /** @lends fabric.Image.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'image', + + /** + * crossOrigin value (one of "", "anonymous", "allow-credentials") + * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes + * @type String + * @default + */ + crossOrigin: '', + + /** + * Constructor + * @param {HTMLImageElement | String} element Image element + * @param {Object} [options] Options object + * @return {fabric.Image} thisArg + */ + initialize: function(element, options) { + options || (options = { }); + + this.filters = [ ]; + + this.callSuper('initialize', options); + + this._initElement(element, options); + this._initConfig(options); + + if (options.filters) { + this.filters = options.filters; + this.applyFilters(); + } + }, + + /** + * Returns image element which this instance if based on + * @return {HTMLImageElement} Image element + */ + getElement: function() { + return this._element; + }, + + /** + * Sets image element for this instance to a specified one. + * If filters defined they are applied to new image. + * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area. + * @param {HTMLImageElement} element + * @param {Function} [callback] Callback is invoked when all filters have been applied and new image is generated + * @return {fabric.Image} thisArg + * @chainable + */ + setElement: function(element, callback) { + this._element = element; + this._originalElement = element; + this._initConfig(); + + if (this.filters.length !== 0) { + this.applyFilters(callback); + } + + return this; + }, + + /** + * Sets crossOrigin value (on an instance and corresponding image element) + * @return {fabric.Image} thisArg + * @chainable + */ + setCrossOrigin: function(value) { + this.crossOrigin = value; + this._element.crossOrigin = value; + + return this; + }, + + /** + * Returns original size of an image + * @return {Object} Object with "width" and "height" properties + */ + getOriginalSize: function() { + var element = this.getElement(); + return { + width: element.width, + height: element.height + }; + }, + + /** + * Renders image on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if object is not visible + if (!this.visible) return; + + ctx.save(); + var m = this.transformMatrix, + isInPathGroup = this.group && this.group.type === 'path-group'; + + // this._resetWidthHeight(); + if (isInPathGroup) { + ctx.translate(-this.group.width/2, -this.group.height/2); + } + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + if (!noTransform) { + this.transform(ctx); + } + if (isInPathGroup) { + ctx.translate(this.width/2, this.height/2); + } + + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + this._render(ctx); + if (this.shadow && !this.shadow.affectStroke) { + this._removeShadow(ctx); + } + this._renderStroke(ctx); + this.clipTo && ctx.restore(); + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _stroke: function(ctx) { + ctx.save(); + this._setStrokeStyles(ctx); + ctx.beginPath(); + ctx.strokeRect(-this.width / 2, -this.height / 2, this.width, this.height); + ctx.closePath(); + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var x = -this.width / 2, + y = -this.height / 2, + w = this.width, + h = this.height; + + ctx.save(); + this._setStrokeStyles(ctx); + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray); + ctx.closePath(); + ctx.restore(); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + src: this._originalElement.src || this._originalElement._src, + filters: this.filters.map(function(filterObj) { + return filterObj && filterObj.toObject(); + }), + crossOrigin: this.crossOrigin + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = []; + + markup.push( + '', + '' + ); + + if (this.stroke || this.strokeDashArray) { + var origFill = this.fill; + this.fill = null; + markup.push( + '' + ); + this.fill = origFill; + } + + markup.push(''); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns source of an image + * @return {String} Source of an image + */ + getSrc: function() { + if (this.getElement()) { + return this.getElement().src || this.getElement()._src; + } + }, + + /** + * Returns string representation of an instance + * @return {String} String representation of an instance + */ + toString: function() { + return '#'; + }, + + /** + * Returns a clone of an instance + * @param {Function} callback Callback is invoked with a clone as a first argument + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + */ + clone: function(callback, propertiesToInclude) { + this.constructor.fromObject(this.toObject(propertiesToInclude), callback); + }, + + /** + * Applies filters assigned to this image (from "filters" array) + * @mthod applyFilters + * @param {Function} callback Callback is invoked when all filters have been applied and new image is generated + * @return {fabric.Image} thisArg + * @chainable + */ + applyFilters: function(callback) { + + if (!this._originalElement) { + return; + } + + if (this.filters.length === 0) { + this._element = this._originalElement; + callback && callback(); + return; + } + + var imgEl = this._originalElement, + canvasEl = fabric.util.createCanvasElement(), + replacement = fabric.util.createImage(), + _this = this; + + canvasEl.width = imgEl.width; + canvasEl.height = imgEl.height; + + canvasEl.getContext('2d').drawImage(imgEl, 0, 0, imgEl.width, imgEl.height); + + this.filters.forEach(function(filter) { + filter && filter.applyTo(canvasEl); + }); + + /** @ignore */ + + replacement.width = imgEl.width; + replacement.height = imgEl.height; + + if (fabric.isLikelyNode) { + replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression); + + // onload doesn't fire in some node versions, so we invoke callback manually + _this._element = replacement; + callback && callback(); + } + else { + replacement.onload = function() { + _this._element = replacement; + callback && callback(); + replacement.onload = canvasEl = imgEl = null; + }; + replacement.src = canvasEl.toDataURL('image/png'); + } + + return this; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + this._element && + ctx.drawImage( + this._element, + -this.width / 2, + -this.height / 2, + this.width, + this.height + ); + }, + + /** + * @private + */ + _resetWidthHeight: function() { + var element = this.getElement(); + + this.set('width', element.width); + this.set('height', element.height); + }, + + /** + * The Image class's initialization method. This method is automatically + * called by the constructor. + * @private + * @param {HTMLImageElement|String} element The element representing the image + */ + _initElement: function(element) { + this.setElement(fabric.util.getById(element)); + fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS); + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initConfig: function(options) { + options || (options = { }); + this.setOptions(options); + this._setWidthHeight(options); + if (this._element && this.crossOrigin) { + this._element.crossOrigin = this.crossOrigin; + } + }, + + /** + * @private + * @param {Object} object Object with filters property + * @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created + */ + _initFilters: function(object, callback) { + if (object.filters && object.filters.length) { + fabric.util.enlivenObjects(object.filters, function(enlivenedObjects) { + callback && callback(enlivenedObjects); + }, 'fabric.Image.filters'); + } + else { + callback && callback(); + } + }, + + /** + * @private + * @param {Object} [options] Object with width/height properties + */ + _setWidthHeight: function(options) { + this.width = 'width' in options + ? options.width + : (this.getElement() + ? this.getElement().width || 0 + : 0); + + this.height = 'height' in options + ? options.height + : (this.getElement() + ? this.getElement().height || 0 + : 0); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /** + * Default CSS class name for canvas + * @static + * @type String + * @default + */ + fabric.Image.CSS_CANVAS = 'canvas-img'; + + /** + * Alias for getSrc + * @static + */ + fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc; + + /** + * Creates an instance of fabric.Image from its object representation + * @static + * @param {Object} object Object to create an instance from + * @param {Function} [callback] Callback to invoke when an image instance is created + */ + fabric.Image.fromObject = function(object, callback) { + fabric.util.loadImage(object.src, function(img) { + fabric.Image.prototype._initFilters.call(object, object, function(filters) { + object.filters = filters || [ ]; + var instance = new fabric.Image(img, object); + callback && callback(instance); + }); + }, null, object.crossOrigin); + }; + + /** + * Creates an instance of fabric.Image from an URL string + * @static + * @param {String} url URL to create an image from + * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument) + * @param {Object} [imgOptions] Options object + */ + fabric.Image.fromURL = function(url, callback, imgOptions) { + fabric.util.loadImage(url, function(img) { + callback(new fabric.Image(img, imgOptions)); + }, null, imgOptions && imgOptions.crossOrigin); + }; + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement}) + * @static + * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement} + */ + fabric.Image.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y width height xlink:href'.split(' ')); + + /** + * Returns {@link fabric.Image} instance from an SVG element + * @static + * @param {SVGElement} element Element to parse + * @param {Function} callback Callback to execute when fabric.Image object is created + * @param {Object} [options] Options object + * @return {fabric.Image} Instance of fabric.Image + */ + fabric.Image.fromElement = function(element, callback, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES); + + fabric.Image.fromURL(parsedAttributes['xlink:href'], callback, + extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + }; + /* _FROM_SVG_END_ */ + + /** + * Indicates that instances of this type are async + * @static + * @type Boolean + * @default + */ + fabric.Image.async = true; + + /** + * Indicates compression level used when generating PNG under Node (in applyFilters). Any of 0-9 + * @static + * @type Number + * @default + */ + fabric.Image.pngCompression = 1; + +})(typeof exports !== 'undefined' ? exports : this); + + +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * @private + * @return {Number} angle value + */ + _getAngleValueForStraighten: function() { + var angle = this.getAngle() % 360; + if (angle > 0) { + return Math.round((angle - 1) / 90) * 90; + } + return Math.round(angle / 90) * 90; + }, + + /** + * Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer) + * @return {fabric.Object} thisArg + * @chainable + */ + straighten: function() { + this.setAngle(this._getAngleValueForStraighten()); + return this; + }, + + /** + * Same as {@link fabric.Object.prototype.straighten} but with animation + * @param {Object} callbacks Object with callback functions + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Object} thisArg + * @chainable + */ + fxStraighten: function(callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: this.get('angle'), + endValue: this._getAngleValueForStraighten(), + duration: this.FX_DURATION, + onChange: function(value) { + _this.setAngle(value); + onChange(); + }, + onComplete: function() { + _this.setCoords(); + onComplete(); + }, + onStart: function() { + _this.set('active', false); + } + }); + + return this; + } +}); + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Straightens object, then rerenders canvas + * @param {fabric.Object} object Object to straighten + * @return {fabric.Canvas} thisArg + * @chainable + */ + straightenObject: function (object) { + object.straighten(); + this.renderAll(); + return this; + }, + + /** + * Same as {@link fabric.Canvas.prototype.straightenObject}, but animated + * @param {fabric.Object} object Object to straighten + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxStraightenObject: function (object) { + object.fxStraighten({ + onChange: this.renderAll.bind(this) + }); + return this; + } +}); + + +/** + * @namespace fabric.Image.filters + * @memberOf fabric.Image + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#image_filters} + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + */ +fabric.Image.filters = fabric.Image.filters || { }; + +/** + * Root filter class from which all filter classes inherit from + * @class fabric.Image.filters.BaseFilter + * @memberOf fabric.Image.filters + */ +fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Image.filters.BaseFilter.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'BaseFilter', + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return { type: this.type }; + }, + + /** + * Returns a JSON representation of an instance + * @return {Object} JSON + */ + toJSON: function() { + // delegate, not alias + return this.toObject(); + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Brightness filter class + * @class fabric.Image.filters.Brightness + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Brightness#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Brightness({ + * brightness: 200 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Brightness = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Brightness.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Brightness', + + /** + * Constructor + * @memberOf fabric.Image.filters.Brightness.prototype + * @param {Object} [options] Options object + * @param {Number} [options.brightness=0] Value to brighten the image up (0..255) + */ + initialize: function(options) { + options = options || { }; + this.brightness = options.brightness || 0; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + brightness = this.brightness; + + for (var i = 0, len = data.length; i < len; i += 4) { + data[i] += brightness; + data[i + 1] += brightness; + data[i + 2] += brightness; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + brightness: this.brightness + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Brightness} Instance of fabric.Image.filters.Brightness + */ + fabric.Image.filters.Brightness.fromObject = function(object) { + return new fabric.Image.filters.Brightness(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Adapted from html5rocks article + * @class fabric.Image.filters.Convolute + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Convolute#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example Sharpen filter + * var filter = new fabric.Image.filters.Convolute({ + * matrix: [ 0, -1, 0, + * -1, 5, -1, + * 0, -1, 0 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example Blur filter + * var filter = new fabric.Image.filters.Convolute({ + * matrix: [ 1/9, 1/9, 1/9, + * 1/9, 1/9, 1/9, + * 1/9, 1/9, 1/9 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example Emboss filter + * var filter = new fabric.Image.filters.Convolute({ + * matrix: [ 1, 1, 1, + * 1, 0.7, -1, + * -1, -1, -1 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example Emboss filter with opaqueness + * var filter = new fabric.Image.filters.Convolute({ + * opaque: true, + * matrix: [ 1, 1, 1, + * 1, 0.7, -1, + * -1, -1, -1 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Convolute = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Convolute.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Convolute', + + /** + * Constructor + * @memberOf fabric.Image.filters.Convolute.prototype + * @param {Object} [options] Options object + * @param {Boolean} [options.opaque=false] Opaque value (true/false) + * @param {Array} [options.matrix] Filter matrix + */ + initialize: function(options) { + options = options || { }; + + this.opaque = options.opaque; + this.matrix = options.matrix || [ + 0, 0, 0, + 0, 1, 0, + 0, 0, 0 + ]; + + var canvasEl = fabric.util.createCanvasElement(); + this.tmpCtx = canvasEl.getContext('2d'); + }, + + /** + * @private + */ + _createImageData: function(w, h) { + return this.tmpCtx.createImageData(w, h); + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + + var weights = this.matrix, + context = canvasEl.getContext('2d'), + pixels = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + + side = Math.round(Math.sqrt(weights.length)), + halfSide = Math.floor(side/2), + src = pixels.data, + sw = pixels.width, + sh = pixels.height, + + // pad output by the convolution matrix + w = sw, + h = sh, + output = this._createImageData(w, h), + + dst = output.data, + + // go through the destination image pixels + alphaFac = this.opaque ? 1 : 0; + + for (var y = 0; y < h; y++) { + for (var x = 0; x < w; x++) { + var sy = y, + sx = x, + dstOff = (y * w + x) * 4, + // calculate the weighed sum of the source image pixels that + // fall under the convolution matrix + r = 0, g = 0, b = 0, a = 0; + + for (var cy = 0; cy < side; cy++) { + for (var cx = 0; cx < side; cx++) { + + var scy = sy + cy - halfSide, + scx = sx + cx - halfSide; + + /* jshint maxdepth:5 */ + if (scy < 0 || scy > sh || scx < 0 || scx > sw) continue; + + var srcOff = (scy * sw + scx) * 4, + wt = weights[cy * side + cx]; + + r += src[srcOff] * wt; + g += src[srcOff + 1] * wt; + b += src[srcOff + 2] * wt; + a += src[srcOff + 3] * wt; + } + } + dst[dstOff] = r; + dst[dstOff + 1] = g; + dst[dstOff + 2] = b; + dst[dstOff + 3] = a + alphaFac * (255 - a); + } + } + + context.putImageData(output, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + opaque: this.opaque, + matrix: this.matrix + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Convolute} Instance of fabric.Image.filters.Convolute + */ + fabric.Image.filters.Convolute.fromObject = function(object) { + return new fabric.Image.filters.Convolute(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * GradientTransparency filter class + * @class fabric.Image.filters.GradientTransparency + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.GradientTransparency#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.GradientTransparency({ + * threshold: 200 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.GradientTransparency = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.GradientTransparency.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'GradientTransparency', + + /** + * Constructor + * @memberOf fabric.Image.filters.GradientTransparency.prototype + * @param {Object} [options] Options object + * @param {Number} [options.threshold=100] Threshold value + */ + initialize: function(options) { + options = options || { }; + this.threshold = options.threshold || 100; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + threshold = this.threshold, + total = data.length; + + for (var i = 0, len = data.length; i < len; i += 4) { + data[i + 3] = threshold + 255 * (total - i) / total; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + threshold: this.threshold + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.GradientTransparency} Instance of fabric.Image.filters.GradientTransparency + */ + fabric.Image.filters.GradientTransparency.fromObject = function(object) { + return new fabric.Image.filters.GradientTransparency(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Grayscale image filter class + * @class fabric.Image.filters.Grayscale + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Grayscale(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Grayscale = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Grayscale.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Grayscale', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Grayscale.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + len = imageData.width * imageData.height * 4, + index = 0, + average; + + while (index < len) { + average = (data[index] + data[index + 1] + data[index + 2]) / 3; + data[index] = average; + data[index + 1] = average; + data[index + 2] = average; + index += 4; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale + */ + fabric.Image.filters.Grayscale.fromObject = function() { + return new fabric.Image.filters.Grayscale(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Invert filter class + * @class fabric.Image.filters.Invert + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Invert(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Invert = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Invert.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Invert', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Invert.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i; + + for (i = 0; i < iLen; i+=4) { + data[i] = 255 - data[i]; + data[i + 1] = 255 - data[i + 1]; + data[i + 2] = 255 - data[i + 2]; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Invert} Instance of fabric.Image.filters.Invert + */ + fabric.Image.filters.Invert.fromObject = function() { + return new fabric.Image.filters.Invert(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Mask filter class + * See http://resources.aleph-1.com/mask/ + * @class fabric.Image.filters.Mask + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Mask#initialize} for constructor definition + */ + fabric.Image.filters.Mask = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Mask.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Mask', + + /** + * Constructor + * @memberOf fabric.Image.filters.Mask.prototype + * @param {Object} [options] Options object + * @param {fabric.Image} [options.mask] Mask image object + * @param {Number} [options.channel=0] Rgb channel (0, 1, 2 or 3) + */ + initialize: function(options) { + options = options || { }; + + this.mask = options.mask; + this.channel = [ 0, 1, 2, 3 ].indexOf(options.channel) > -1 ? options.channel : 0; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + if (!this.mask) return; + + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + maskEl = this.mask.getElement(), + maskCanvasEl = fabric.util.createCanvasElement(), + channel = this.channel, + i, + iLen = imageData.width * imageData.height * 4; + + maskCanvasEl.width = maskEl.width; + maskCanvasEl.height = maskEl.height; + + maskCanvasEl.getContext('2d').drawImage(maskEl, 0, 0, maskEl.width, maskEl.height); + + var maskImageData = maskCanvasEl.getContext('2d').getImageData(0, 0, maskEl.width, maskEl.height), + maskData = maskImageData.data; + + for (i = 0; i < iLen; i += 4) { + data[i + 3] = maskData[i + channel]; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + mask: this.mask.toObject(), + channel: this.channel + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @param {Function} [callback] Callback to invoke when a mask filter instance is created + */ + fabric.Image.filters.Mask.fromObject = function(object, callback) { + fabric.util.loadImage(object.mask.src, function(img) { + object.mask = new fabric.Image(img, object.mask); + callback && callback(new fabric.Image.filters.Mask(object)); + }); + }; + + /** + * Indicates that instances of this type are async + * @static + * @type Boolean + * @default + */ + fabric.Image.filters.Mask.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Noise filter class + * @class fabric.Image.filters.Noise + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Noise#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Noise({ + * noise: 700 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Noise = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Noise.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Noise', + + /** + * Constructor + * @memberOf fabric.Image.filters.Noise.prototype + * @param {Object} [options] Options object + * @param {Number} [options.noise=0] Noise value + */ + initialize: function(options) { + options = options || { }; + this.noise = options.noise || 0; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + noise = this.noise, rand; + + for (var i = 0, len = data.length; i < len; i += 4) { + + rand = (0.5 - Math.random()) * noise; + + data[i] += rand; + data[i + 1] += rand; + data[i + 2] += rand; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + noise: this.noise + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Noise} Instance of fabric.Image.filters.Noise + */ + fabric.Image.filters.Noise.fromObject = function(object) { + return new fabric.Image.filters.Noise(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Pixelate filter class + * @class fabric.Image.filters.Pixelate + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Pixelate#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Pixelate({ + * blocksize: 8 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Pixelate = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Pixelate.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Pixelate', + + /** + * Constructor + * @memberOf fabric.Image.filters.Pixelate.prototype + * @param {Object} [options] Options object + * @param {Number} [options.blocksize=4] Blocksize for pixelate + */ + initialize: function(options) { + options = options || { }; + this.blocksize = options.blocksize || 4; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = imageData.height, + jLen = imageData.width, + index, i, j, r, g, b, a; + + for (i = 0; i < iLen; i += this.blocksize) { + for (j = 0; j < jLen; j += this.blocksize) { + + index = (i * 4) * jLen + (j * 4); + + r = data[index]; + g = data[index + 1]; + b = data[index + 2]; + a = data[index + 3]; + + /* + blocksize: 4 + + [1,x,x,x,1] + [x,x,x,x,1] + [x,x,x,x,1] + [x,x,x,x,1] + [1,1,1,1,1] + */ + + for (var _i = i, _ilen = i + this.blocksize; _i < _ilen; _i++) { + for (var _j = j, _jlen = j + this.blocksize; _j < _jlen; _j++) { + index = (_i * 4) * jLen + (_j * 4); + data[index] = r; + data[index + 1] = g; + data[index + 2] = b; + data[index + 3] = a; + } + } + } + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + blocksize: this.blocksize + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Pixelate} Instance of fabric.Image.filters.Pixelate + */ + fabric.Image.filters.Pixelate.fromObject = function(object) { + return new fabric.Image.filters.Pixelate(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Remove white filter class + * @class fabric.Image.filters.RemoveWhite + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.RemoveWhite#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.RemoveWhite({ + * threshold: 40, + * distance: 140 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.RemoveWhite = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.RemoveWhite.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'RemoveWhite', + + /** + * Constructor + * @memberOf fabric.Image.filters.RemoveWhite.prototype + * @param {Object} [options] Options object + * @param {Number} [options.threshold=30] Threshold value + * @param {Number} [options.distance=20] Distance value + */ + initialize: function(options) { + options = options || { }; + this.threshold = options.threshold || 30; + this.distance = options.distance || 20; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + threshold = this.threshold, + distance = this.distance, + limit = 255 - threshold, + abs = Math.abs, + r, g, b; + + for (var i = 0, len = data.length; i < len; i += 4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + if (r > limit && + g > limit && + b > limit && + abs(r - g) < distance && + abs(r - b) < distance && + abs(g - b) < distance + ) { + data[i + 3] = 1; + } + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + threshold: this.threshold, + distance: this.distance + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.RemoveWhite} Instance of fabric.Image.filters.RemoveWhite + */ + fabric.Image.filters.RemoveWhite.fromObject = function(object) { + return new fabric.Image.filters.RemoveWhite(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Sepia filter class + * @class fabric.Image.filters.Sepia + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Sepia(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Sepia = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Sepia', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Sepia.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, avg; + + for (i = 0; i < iLen; i+=4) { + avg = 0.3 * data[i] + 0.59 * data[i + 1] + 0.11 * data[i + 2]; + data[i] = avg + 100; + data[i + 1] = avg + 50; + data[i + 2] = avg + 255; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Sepia} Instance of fabric.Image.filters.Sepia + */ + fabric.Image.filters.Sepia.fromObject = function() { + return new fabric.Image.filters.Sepia(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Sepia2 filter class + * @class fabric.Image.filters.Sepia2 + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Sepia2(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Sepia2 = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia2.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Sepia2', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Sepia.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, r, g, b; + + for (i = 0; i < iLen; i+=4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + data[i] = (r * 0.393 + g * 0.769 + b * 0.189 ) / 1.351; + data[i + 1] = (r * 0.349 + g * 0.686 + b * 0.168 ) / 1.203; + data[i + 2] = (r * 0.272 + g * 0.534 + b * 0.131 ) / 2.140; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Sepia2} Instance of fabric.Image.filters.Sepia2 + */ + fabric.Image.filters.Sepia2.fromObject = function() { + return new fabric.Image.filters.Sepia2(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Tint filter class + * Adapted from https://github.com/mezzoblue/PaintbrushJS + * @class fabric.Image.filters.Tint + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Tint#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example Tint filter with hex color and opacity + * var filter = new fabric.Image.filters.Tint({ + * color: '#3513B0', + * opacity: 0.5 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example Tint filter with rgba color + * var filter = new fabric.Image.filters.Tint({ + * color: 'rgba(53, 21, 176, 0.5)' + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Tint = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Tint.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Tint', + + /** + * Constructor + * @memberOf fabric.Image.filters.Tint.prototype + * @param {Object} [options] Options object + * @param {String} [options.color=#000000] Color to tint the image with + * @param {Number} [options.opacity] Opacity value that controls the tint effect's transparency (0..1) + */ + initialize: function(options) { + options = options || { }; + + this.color = options.color || '#000000'; + this.opacity = typeof options.opacity !== 'undefined' + ? options.opacity + : new fabric.Color(this.color).getAlpha(); + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, + tintR, tintG, tintB, + r, g, b, alpha1, + source; + + source = new fabric.Color(this.color).getSource(); + + tintR = source[0] * this.opacity; + tintG = source[1] * this.opacity; + tintB = source[2] * this.opacity; + + alpha1 = 1 - this.opacity; + + for (i = 0; i < iLen; i+=4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + // alpha compositing + data[i] = tintR + r * alpha1; + data[i + 1] = tintG + g * alpha1; + data[i + 2] = tintB + b * alpha1; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + color: this.color, + opacity: this.opacity + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Tint} Instance of fabric.Image.filters.Tint + */ + fabric.Image.filters.Tint.fromObject = function(object) { + return new fabric.Image.filters.Tint(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Multiply filter class + * Adapted from http://www.laurenscorijn.com/articles/colormath-basics + * @class fabric.Image.filters.Multiply + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @example Multiply filter with hex color + * var filter = new fabric.Image.filters.Multiply({ + * color: '#F0F' + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example Multiply filter with rgb color + * var filter = new fabric.Image.filters.Multiply({ + * color: 'rgb(53, 21, 176)' + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Multiply = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Multiply.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Multiply', + + /** + * Constructor + * @memberOf fabric.Image.filters.Multiply.prototype + * @param {Object} [options] Options object + * @param {String} [options.color=#000000] Color to multiply the image pixels with + */ + initialize: function(options) { + options = options || { }; + + this.color = options.color || '#000000'; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, + source; + + source = new fabric.Color(this.color).getSource(); + + for (i = 0; i < iLen; i+=4) { + data[i] *= source[0] / 255; + data[i + 1] *= source[1] / 255; + data[i + 2] *= source[2] / 255; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + color: this.color + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Multiply} Instance of fabric.Image.filters.Multiply + */ + fabric.Image.filters.Multiply.fromObject = function(object) { + return new fabric.Image.filters.Multiply(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + clone = fabric.util.object.clone, + toFixed = fabric.util.toFixed, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Text) { + fabric.warn('fabric.Text is already defined'); + return; + } + + var stateProperties = fabric.Object.prototype.stateProperties.concat(); + stateProperties.push( + 'fontFamily', + 'fontWeight', + 'fontSize', + 'text', + 'textDecoration', + 'textAlign', + 'fontStyle', + 'lineHeight', + 'textBackgroundColor', + 'useNative', + 'path' + ); + + /** + * Text class + * @class fabric.Text + * @extends fabric.Object + * @return {fabric.Text} thisArg + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#text} + * @see {@link fabric.Text#initialize} for constructor definition + */ + fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ { + + /** + * Properties which when set cause object to change dimensions + * @type Object + * @private + */ + _dimensionAffectingProps: { + fontSize: true, + fontWeight: true, + fontFamily: true, + textDecoration: true, + fontStyle: true, + lineHeight: true, + stroke: true, + strokeWidth: true, + text: true + }, + + /** + * @private + */ + _reNewline: /\r?\n/, + + /** + * Retrieves object's fontSize + * @method getFontSize + * @memberOf fabric.Text.prototype + * @return {String} Font size (in pixels) + */ + + /** + * Sets object's fontSize + * @method setFontSize + * @memberOf fabric.Text.prototype + * @param {Number} fontSize Font size (in pixels) + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontWeight + * @method getFontWeight + * @memberOf fabric.Text.prototype + * @return {(String|Number)} Font weight + */ + + /** + * Sets object's fontWeight + * @method setFontWeight + * @memberOf fabric.Text.prototype + * @param {(Number|String)} fontWeight Font weight + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontFamily + * @method getFontFamily + * @memberOf fabric.Text.prototype + * @return {String} Font family + */ + + /** + * Sets object's fontFamily + * @method setFontFamily + * @memberOf fabric.Text.prototype + * @param {String} fontFamily Font family + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's text + * @method getText + * @memberOf fabric.Text.prototype + * @return {String} text + */ + + /** + * Sets object's text + * @method setText + * @memberOf fabric.Text.prototype + * @param {String} text Text + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textDecoration + * @method getTextDecoration + * @memberOf fabric.Text.prototype + * @return {String} Text decoration + */ + + /** + * Sets object's textDecoration + * @method setTextDecoration + * @memberOf fabric.Text.prototype + * @param {String} textDecoration Text decoration + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontStyle + * @method getFontStyle + * @memberOf fabric.Text.prototype + * @return {String} Font style + */ + + /** + * Sets object's fontStyle + * @method setFontStyle + * @memberOf fabric.Text.prototype + * @param {String} fontStyle Font style + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's lineHeight + * @method getLineHeight + * @memberOf fabric.Text.prototype + * @return {Number} Line height + */ + + /** + * Sets object's lineHeight + * @method setLineHeight + * @memberOf fabric.Text.prototype + * @param {Number} lineHeight Line height + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textAlign + * @method getTextAlign + * @memberOf fabric.Text.prototype + * @return {String} Text alignment + */ + + /** + * Sets object's textAlign + * @method setTextAlign + * @memberOf fabric.Text.prototype + * @param {String} textAlign Text alignment + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textBackgroundColor + * @method getTextBackgroundColor + * @memberOf fabric.Text.prototype + * @return {String} Text background color + */ + + /** + * Sets object's textBackgroundColor + * @method setTextBackgroundColor + * @memberOf fabric.Text.prototype + * @param {String} textBackgroundColor Text background color + * @return {fabric.Text} + * @chainable + */ + + /** + * Type of an object + * @type String + * @default + */ + type: 'text', + + /** + * Font size (in pixels) + * @type Number + * @default + */ + fontSize: 40, + + /** + * Font weight (e.g. bold, normal, 400, 600, 800) + * @type {(Number|String)} + * @default + */ + fontWeight: 'normal', + + /** + * Font family + * @type String + * @default + */ + fontFamily: 'Times New Roman', + + /** + * Text decoration Possible values: "", "underline", "overline" or "line-through". + * @type String + * @default + */ + textDecoration: '', + + /** + * Text alignment. Possible values: "left", "center", or "right". + * @type String + * @default + */ + textAlign: 'left', + + /** + * Font style . Possible values: "", "normal", "italic" or "oblique". + * @type String + * @default + */ + fontStyle: '', + + /** + * Line height + * @type Number + * @default + */ + lineHeight: 1.3, + + /** + * Background color of text lines + * @type String + * @default + */ + textBackgroundColor: '', + + /** + * URL of a font file, when using Cufon + * @type String | null + * @default + */ + path: null, + + /** + * Indicates whether canvas native text methods should be used to render text (otherwise, Cufon is used) + * @type Boolean + * @default + */ + useNative: true, + + /** + * List of properties to consider when checking if + * state of an object is changed ({@link fabric.Object#hasStateChanged}) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: stateProperties, + + /** + * When defined, an object is rendered via stroke and this property specifies its color. + * Backwards incompatibility note: This property was named "strokeStyle" until v1.1.6 + * @type String + * @default + */ + stroke: null, + + /** + * Shadow object representing shadow of this shape. + * Backwards incompatibility note: This property was named "textShadow" (String) until v1.2.11 + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Constructor + * @param {String} text Text string + * @param {Object} [options] Options object + * @return {fabric.Text} thisArg + */ + initialize: function(text, options) { + options = options || { }; + + this.text = text; + this.__skipDimension = true; + this.setOptions(options); + this.__skipDimension = false; + this._initDimensions(); + }, + + /** + * Renders text object on offscreen canvas, so that it would get dimensions + * @private + */ + _initDimensions: function() { + if (this.__skipDimension) return; + var canvasEl = fabric.util.createCanvasElement(); + this._render(canvasEl.getContext('2d')); + }, + + /** + * Returns string representation of an instance + * @return {String} String representation of text object + */ + toString: function() { + return '#'; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + + var isInPathGroup = this.group && this.group.type === 'path-group'; + if (isInPathGroup && !this.transformMatrix) { + ctx.translate(-this.group.width/2 + this.left, -this.group.height / 2 + this.top); + } + else if (isInPathGroup && this.transformMatrix) { + ctx.translate(-this.group.width/2, -this.group.height/2); + } + + if (typeof Cufon === 'undefined' || this.useNative === true) { + this._renderViaNative(ctx); + } + else { + this._renderViaCufon(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderViaNative: function(ctx) { + var textLines = this.text.split(this._reNewline); + + this.transform(ctx, fabric.isLikelyNode); + + this._setTextStyles(ctx); + + this.width = this._getTextWidth(ctx, textLines); + this.height = this._getTextHeight(ctx, textLines); + + this.clipTo && fabric.util.clipContext(this, ctx); + + this._renderTextBackground(ctx, textLines); + this._translateForTextAlign(ctx); + this._renderText(ctx, textLines); + + if (this.textAlign !== 'left' && this.textAlign !== 'justify') { + ctx.restore(); + } + + this._renderTextDecoration(ctx, textLines); + this.clipTo && ctx.restore(); + + this._setBoundaries(ctx, textLines); + this._totalLineHeight = 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderText: function(ctx, textLines) { + ctx.save(); + this._setShadow(ctx); + this._renderTextFill(ctx, textLines); + this._renderTextStroke(ctx, textLines); + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _translateForTextAlign: function(ctx) { + if (this.textAlign !== 'left' && this.textAlign !== 'justify') { + ctx.save(); + ctx.translate(this.textAlign === 'center' ? (this.width / 2) : this.width, 0); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _setBoundaries: function(ctx, textLines) { + this._boundaries = [ ]; + + for (var i = 0, len = textLines.length; i < len; i++) { + + var lineWidth = this._getLineWidth(ctx, textLines[i]), + lineLeftOffset = this._getLineLeftOffset(lineWidth); + + this._boundaries.push({ + height: this.fontSize * this.lineHeight, + width: lineWidth, + left: lineLeftOffset + }); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _setTextStyles: function(ctx) { + this._setFillStyles(ctx); + this._setStrokeStyles(ctx); + ctx.textBaseline = 'alphabetic'; + if (!this.skipTextAlign) { + ctx.textAlign = this.textAlign; + } + ctx.font = this._getFontDeclaration(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + * @return {Number} Height of fabric.Text object + */ + _getTextHeight: function(ctx, textLines) { + return this.fontSize * textLines.length * this.lineHeight; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + * @return {Number} Maximum width of fabric.Text object + */ + _getTextWidth: function(ctx, textLines) { + var maxWidth = ctx.measureText(textLines[0] || '|').width; + + for (var i = 1, len = textLines.length; i < len; i++) { + var currentLineWidth = ctx.measureText(textLines[i]).width; + if (currentLineWidth > maxWidth) { + maxWidth = currentLineWidth; + } + } + return maxWidth; + }, + + /** + * @private + * @param {String} method Method name ("fillText" or "strokeText") + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Chars to render + * @param {Number} left Left position of text + * @param {Number} top Top position of text + */ + _renderChars: function(method, ctx, chars, left, top) { + ctx[method](chars, left, top); + }, + + /** + * @private + * @param {String} method Method name ("fillText" or "strokeText") + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Text to render + * @param {Number} left Left position of text + * @param {Number} top Top position of text + * @param {Number} lineIndex Index of a line in a text + */ + _renderTextLine: function(method, ctx, line, left, top, lineIndex) { + // lift the line by quarter of fontSize + top -= this.fontSize / 4; + + // short-circuit + if (this.textAlign !== 'justify') { + this._renderChars(method, ctx, line, left, top, lineIndex); + return; + } + + var lineWidth = ctx.measureText(line).width, + totalWidth = this.width; + + if (totalWidth > lineWidth) { + // stretch the line + var words = line.split(/\s+/), + wordsWidth = ctx.measureText(line.replace(/\s+/g, '')).width, + widthDiff = totalWidth - wordsWidth, + numSpaces = words.length - 1, + spaceWidth = widthDiff / numSpaces, + leftOffset = 0; + + for (var i = 0, len = words.length; i < len; i++) { + this._renderChars(method, ctx, words[i], left + leftOffset, top, lineIndex); + leftOffset += ctx.measureText(words[i]).width + spaceWidth; + } + } + else { + this._renderChars(method, ctx, line, left, top, lineIndex); + } + }, + + /** + * @private + * @return {Number} Left offset + */ + _getLeftOffset: function() { + if (fabric.isLikelyNode) { + return 0; + } + return -this.width / 2; + }, + + /** + * @private + * @return {Number} Top offset + */ + _getTopOffset: function() { + return -this.height / 2; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextFill: function(ctx, textLines) { + if (!this.fill && !this._skipFillStrokeCheck) return; + + this._boundaries = [ ]; + var lineHeights = 0; + + for (var i = 0, len = textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i, textLines); + lineHeights += heightOfLine; + + this._renderTextLine( + 'fillText', + ctx, + textLines[i], + this._getLeftOffset(), + this._getTopOffset() + lineHeights, + i + ); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextStroke: function(ctx, textLines) { + if (!this.stroke && !this._skipFillStrokeCheck) return; + + var lineHeights = 0; + + ctx.save(); + if (this.strokeDashArray) { + // Spec requires the concatenation of two copies the dash list when the number of elements is odd + if (1 & this.strokeDashArray.length) { + this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); + } + supportsLineDash && ctx.setLineDash(this.strokeDashArray); + } + + ctx.beginPath(); + for (var i = 0, len = textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i, textLines); + lineHeights += heightOfLine; + + this._renderTextLine( + 'strokeText', + ctx, + textLines[i], + this._getLeftOffset(), + this._getTopOffset() + lineHeights, + i + ); + } + ctx.closePath(); + ctx.restore(); + }, + + _getHeightOfLine: function() { + return this.fontSize * this.lineHeight; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextBackground: function(ctx, textLines) { + this._renderTextBoxBackground(ctx); + this._renderTextLinesBackground(ctx, textLines); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderTextBoxBackground: function(ctx) { + if (!this.backgroundColor) return; + + ctx.save(); + ctx.fillStyle = this.backgroundColor; + + ctx.fillRect( + this._getLeftOffset(), + this._getTopOffset(), + this.width, + this.height + ); + + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextLinesBackground: function(ctx, textLines) { + if (!this.textBackgroundColor) return; + + ctx.save(); + ctx.fillStyle = this.textBackgroundColor; + + for (var i = 0, len = textLines.length; i < len; i++) { + + if (textLines[i] !== '') { + + var lineWidth = this._getLineWidth(ctx, textLines[i]), + lineLeftOffset = this._getLineLeftOffset(lineWidth); + + ctx.fillRect( + this._getLeftOffset() + lineLeftOffset, + this._getTopOffset() + (i * this.fontSize * this.lineHeight), + lineWidth, + this.fontSize * this.lineHeight + ); + } + } + ctx.restore(); + }, + + /** + * @private + * @param {Number} lineWidth Width of text line + * @return {Number} Line left offset + */ + _getLineLeftOffset: function(lineWidth) { + if (this.textAlign === 'center') { + return (this.width - lineWidth) / 2; + } + if (this.textAlign === 'right') { + return this.width - lineWidth; + } + return 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Text line + * @return {Number} Line width + */ + _getLineWidth: function(ctx, line) { + return this.textAlign === 'justify' + ? this.width + : ctx.measureText(line).width; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextDecoration: function(ctx, textLines) { + if (!this.textDecoration) return; + + // var halfOfVerticalBox = this.originY === 'top' ? 0 : this._getTextHeight(ctx, textLines) / 2; + var halfOfVerticalBox = this._getTextHeight(ctx, textLines) / 2, + _this = this; + + /** @ignore */ + function renderLinesAtOffset(offset) { + for (var i = 0, len = textLines.length; i < len; i++) { + + var lineWidth = _this._getLineWidth(ctx, textLines[i]), + lineLeftOffset = _this._getLineLeftOffset(lineWidth); + + ctx.fillRect( + _this._getLeftOffset() + lineLeftOffset, + ~~((offset + (i * _this._getHeightOfLine(ctx, i, textLines))) - halfOfVerticalBox), + lineWidth, + 1); + } + } + + if (this.textDecoration.indexOf('underline') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight); + } + if (this.textDecoration.indexOf('line-through') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize / 2); + } + if (this.textDecoration.indexOf('overline') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize); + } + }, + + /** + * @private + */ + _getFontDeclaration: function() { + return [ + // node-canvas needs "weight style", while browsers need "style weight" + (fabric.isLikelyNode ? this.fontWeight : this.fontStyle), + (fabric.isLikelyNode ? this.fontStyle : this.fontWeight), + this.fontSize + 'px', + (fabric.isLikelyNode ? ('"' + this.fontFamily + '"') : this.fontFamily) + ].join(' '); + }, + + /** + * Renders text instance on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + render: function(ctx) { + // do not render if object is not visible + if (!this.visible) return; + + ctx.save(); + var m = this.transformMatrix; + if (m && (!this.group || this.group.type === 'path-group')) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + this._render(ctx); + ctx.restore(); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + var object = extend(this.callSuper('toObject', propertiesToInclude), { + text: this.text, + fontSize: this.fontSize, + fontWeight: this.fontWeight, + fontFamily: this.fontFamily, + fontStyle: this.fontStyle, + lineHeight: this.lineHeight, + textDecoration: this.textDecoration, + textAlign: this.textAlign, + path: this.path, + textBackgroundColor: this.textBackgroundColor, + useNative: this.useNative + }); + if (!this.includeDefaultValues) { + this._removeDefaultValues(object); + } + return object; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = [ ], + textLines = this.text.split(this._reNewline), + offsets = this._getSVGLeftTopOffsets(textLines), + textAndBg = this._getSVGTextAndBg(offsets.lineTop, offsets.textLeft, textLines), + shadowSpans = this._getSVGShadows(offsets.lineTop, textLines); + + // move top offset by an ascent + offsets.textTop += (this._fontAscent ? ((this._fontAscent / 5) * this.lineHeight) : 0); + + this._wrapSVGTextAndBg(markup, textAndBg, shadowSpans, offsets); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + + /** + * @private + */ + _getSVGLeftTopOffsets: function(textLines) { + var lineTop = this.useNative + ? this.fontSize * this.lineHeight + : (-this._fontAscent - ((this._fontAscent / 5) * this.lineHeight)), + + textLeft = -(this.width/2), + textTop = this.useNative + ? this.fontSize - 1 + : (this.height/2) - (textLines.length * this.fontSize) - this._totalLineHeight; + + return { + textLeft: textLeft, + textTop: textTop, + lineTop: lineTop + }; + }, + + /** + * @private + */ + _wrapSVGTextAndBg: function(markup, textAndBg, shadowSpans, offsets) { + markup.push( + '', + textAndBg.textBgRects.join(''), + '', + shadowSpans.join(''), + textAndBg.textSpans.join(''), + '', + '' + ); + }, + + /** + * @private + * @param {Number} lineHeight + * @param {Array} textLines Array of all text lines + * @return {Array} + */ + _getSVGShadows: function(lineHeight, textLines) { + var shadowSpans = [], + i, len, + lineTopOffsetMultiplier = 1; + + if (!this.shadow || !this._boundaries) { + return shadowSpans; + } + + for (i = 0, len = textLines.length; i < len; i++) { + if (textLines[i] !== '') { + var lineLeftOffset = (this._boundaries && this._boundaries[i]) ? this._boundaries[i].left : 0; + shadowSpans.push( + '', + fabric.util.string.escapeXml(textLines[i]), + ''); + lineTopOffsetMultiplier = 1; + } + else { + // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier + // prevents empty tspans + lineTopOffsetMultiplier++; + } + } + + return shadowSpans; + }, + + /** + * @private + * @param {Number} lineHeight + * @param {Number} textLeftOffset Text left offset + * @param {Array} textLines Array of all text lines + * @return {Object} + */ + _getSVGTextAndBg: function(lineHeight, textLeftOffset, textLines) { + var textSpans = [ ], + textBgRects = [ ], + lineTopOffsetMultiplier = 1; + + // bounding-box background + this._setSVGBg(textBgRects); + + // text and text-background + for (var i = 0, len = textLines.length; i < len; i++) { + if (textLines[i] !== '') { + this._setSVGTextLineText(textLines[i], i, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects); + lineTopOffsetMultiplier = 1; + } + else { + // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier + // prevents empty tspans + lineTopOffsetMultiplier++; + } + + if (!this.textBackgroundColor || !this._boundaries) continue; + + this._setSVGTextLineBg(textBgRects, i, textLeftOffset, lineHeight); + } + + return { + textSpans: textSpans, + textBgRects: textBgRects + }; + }, + + _setSVGTextLineText: function(textLine, i, textSpans, lineHeight, lineTopOffsetMultiplier) { + var lineLeftOffset = (this._boundaries && this._boundaries[i]) + ? toFixed(this._boundaries[i].left, 2) + : 0; + + textSpans.push( + ' elements since setting opacity + // on containing one doesn't work in Illustrator + this._getFillAttributes(this.fill), '>', + fabric.util.string.escapeXml(textLine), + '' + ); + }, + + _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, lineHeight) { + textBgRects.push( + ''); + }, + + _setSVGBg: function(textBgRects) { + if (this.backgroundColor && this._boundaries) { + textBgRects.push( + ''); + } + }, + + /** + * Adobe Illustrator (at least CS5) is unable to render rgba()-based fill values + * we work around it by "moving" alpha channel into opacity attribute and setting fill's alpha to 1 + * + * @private + * @param {Any} value + * @return {String} + */ + _getFillAttributes: function(value) { + var fillColor = (value && typeof value === 'string') ? new fabric.Color(value) : ''; + if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) { + return 'fill="' + value + '"'; + } + return 'opacity="' + fillColor.getAlpha() + '" fill="' + fillColor.setAlpha(1).toRgb() + '"'; + }, + /* _TO_SVG_END_ */ + + /** + * Sets specified property to a specified value + * @param {String} key + * @param {Any} value + * @return {fabric.Text} thisArg + * @chainable + */ + _set: function(key, value) { + if (key === 'fontFamily' && this.path) { + this.path = this.path.replace(/(.*?)([^\/]*)(\.font\.js)/, '$1' + value + '$3'); + } + this.callSuper('_set', key, value); + + if (key in this._dimensionAffectingProps) { + this._initDimensions(); + this.setCoords(); + } + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement}) + * @static + * @memberOf fabric.Text + * @see: http://www.w3.org/TR/SVG/text.html#TextElement + */ + fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat( + 'x y dx dy font-family font-style font-weight font-size text-decoration text-anchor'.split(' ')); + + /** + * Default SVG font size + * @static + * @memberOf fabric.Text + */ + fabric.Text.DEFAULT_SVG_FONT_SIZE = 16; + + /** + * Returns fabric.Text instance from an SVG element (not yet implemented) + * @static + * @memberOf fabric.Text + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Text} Instance of fabric.Text + */ + fabric.Text.fromElement = function(element, options) { + if (!element) { + return null; + } + + var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES); + options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes); + + if ('dx' in parsedAttributes) { + options.left += parsedAttributes.dx; + } + if ('dy' in parsedAttributes) { + options.top += parsedAttributes.dy; + } + if (!('fontSize' in options)) { + options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE; + } + + if (!options.originX) { + options.originX = 'center'; + } + + var text = new fabric.Text(element.textContent, options); + + /* + Adjust positioning: + x/y attributes in SVG correspond to the bottom-left corner of text bounding box + top/left properties in Fabric correspond to center point of text bounding box + */ + + text.set({ + left: text.getLeft() + text.getWidth() / 2, + top: text.getTop() - text.getHeight() / 2 + }); + + return text; + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Text instance from an object representation + * @static + * @memberOf fabric.Text + * @param object {Object} object Object to create an instance from + * @return {fabric.Text} Instance of fabric.Text + */ + fabric.Text.fromObject = function(object) { + return new fabric.Text(object.text, clone(object)); + }; + + fabric.util.createAccessors(fabric.Text); + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + var clone = fabric.util.object.clone; + + /** + * IText class (introduced in v1.4) + * @class fabric.IText + * @extends fabric.Text + * @mixes fabric.Observable + * + * @fires changed ("text:changed" when observing canvas) + * @fires selection:changed ("text:selection:changed" when observing canvas) + * @fires editing:entered ("text:editing:entered" when observing canvas) + * @fires editing:exited ("text:editing:exited" when observing canvas) + * + * @return {fabric.IText} thisArg + * @see {@link fabric.IText#initialize} for constructor definition + * + *

    Supported key combinations:

    + *
    +    *   Move cursor:                    left, right, up, down
    +    *   Select character:               shift + left, shift + right
    +    *   Select text vertically:         shift + up, shift + down
    +    *   Move cursor by word:            alt + left, alt + right
    +    *   Select words:                   shift + alt + left, shift + alt + right
    +    *   Move cursor to line start/end:  cmd + left, cmd + right
    +    *   Select till start/end of line:  cmd + shift + left, cmd + shift + right
    +    *   Jump to start/end of text:      cmd + up, cmd + down
    +    *   Select till start/end of text:  cmd + shift + up, cmd + shift + down
    +    *   Delete character:               backspace
    +    *   Delete word:                    alt + backspace
    +    *   Delete line:                    cmd + backspace
    +    *   Forward delete:                 delete
    +    *   Copy text:                      ctrl/cmd + c
    +    *   Paste text:                     ctrl/cmd + v
    +    *   Cut text:                       ctrl/cmd + x
    +    *   Select entire text:             ctrl/cmd + a
    +    * 
    + * + *

    Supported mouse/touch combination

    + *
    +    *   Position cursor:                click/touch
    +    *   Create selection:               click/touch & drag
    +    *   Create selection:               click & shift + click
    +    *   Select word:                    double click
    +    *   Select line:                    triple click
    +    * 
    + */ + fabric.IText = fabric.util.createClass(fabric.Text, fabric.Observable, /** @lends fabric.IText.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'i-text', + + /** + * Index where text selection starts (or where cursor is when there is no selection) + * @type Nubmer + * @default + */ + selectionStart: 0, + + /** + * Index where text selection ends + * @type Nubmer + * @default + */ + selectionEnd: 0, + + /** + * Color of text selection + * @type String + * @default + */ + selectionColor: 'rgba(17,119,255,0.3)', + + /** + * Indicates whether text is in editing mode + * @type Boolean + * @default + */ + isEditing: false, + + /** + * Indicates whether a text can be edited + * @type Boolean + * @default + */ + editable: true, + + /** + * Border color of text object while it's in editing mode + * @type String + * @default + */ + editingBorderColor: 'rgba(102,153,255,0.25)', + + /** + * Width of cursor (in px) + * @type Number + * @default + */ + cursorWidth: 2, + + /** + * Color of default cursor (when not overwritten by character style) + * @type String + * @default + */ + cursorColor: '#333', + + /** + * Delay between cursor blink (in ms) + * @type Number + * @default + */ + cursorDelay: 1000, + + /** + * Duration of cursor fadein (in ms) + * @type Number + * @default + */ + cursorDuration: 600, + + /** + * Object containing character styles + * (where top-level properties corresponds to line number and 2nd-level properties -- to char number in a line) + * @type Object + * @default + */ + styles: null, + + /** + * Indicates whether internal text char widths can be cached + * @type Boolean + * @default + */ + caching: true, + + /** + * @private + * @type Boolean + * @default + */ + _skipFillStrokeCheck: true, + + /** + * @private + */ + _reSpace: /\s|\n/, + + /** + * @private + */ + _fontSizeFraction: 4, + + /** + * @private + */ + _currentCursorOpacity: 0, + + /** + * @private + */ + _selectionDirection: null, + + /** + * @private + */ + _abortCursorAnimation: false, + + /** + * @private + */ + _charWidthsCache: { }, + + /** + * Constructor + * @param {String} text Text string + * @param {Object} [options] Options object + * @return {fabric.IText} thisArg + */ + initialize: function(text, options) { + this.styles = options ? (options.styles || { }) : { }; + this.callSuper('initialize', text, options); + this.initBehavior(); + + fabric.IText.instances.push(this); + + // caching + this.__lineWidths = { }; + this.__lineHeights = { }; + this.__lineOffsets = { }; + }, + + /** + * Returns true if object has no styling + */ + isEmptyStyles: function() { + if (!this.styles) return true; + var obj = this.styles; + + for (var p1 in obj) { + for (var p2 in obj[p1]) { + /*jshint unused:false */ + for (var p3 in obj[p1][p2]) { + return false; + } + } + } + return true; + }, + + /** + * Sets selection start (left boundary of a selection) + * @param {Number} index Index to set selection start to + */ + setSelectionStart: function(index) { + if (this.selectionStart !== index) { + this.fire('selection:changed'); + this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + } + this.selectionStart = index; + this.hiddenTextarea && (this.hiddenTextarea.selectionStart = index); + }, + + /** + * Sets selection end (right boundary of a selection) + * @param {Number} index Index to set selection end to + */ + setSelectionEnd: function(index) { + if (this.selectionEnd !== index) { + this.fire('selection:changed'); + this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + } + this.selectionEnd = index; + this.hiddenTextarea && (this.hiddenTextarea.selectionEnd = index); + }, + + /** + * Gets style of a current selection/cursor (at the start position) + * @param {Number} [startIndex] Start index to get styles at + * @param {Number} [endIndex] End index to get styles at + * @return {Object} styles Style object at a specified (or current) index + */ + getSelectionStyles: function(startIndex, endIndex) { + + if (arguments.length === 2) { + var styles = [ ]; + for (var i = startIndex; i < endIndex; i++) { + styles.push(this.getSelectionStyles(i)); + } + return styles; + } + + var loc = this.get2DCursorLocation(startIndex); + if (this.styles[loc.lineIndex]) { + return this.styles[loc.lineIndex][loc.charIndex] || { }; + } + + return { }; + }, + + /** + * Sets style of a current selection + * @param {Object} [styles] Styles object + * @return {fabric.IText} thisArg + * @chainable + */ + setSelectionStyles: function(styles) { + if (this.selectionStart === this.selectionEnd) { + this._extendStyles(this.selectionStart, styles); + } + else { + for (var i = this.selectionStart; i < this.selectionEnd; i++) { + this._extendStyles(i, styles); + } + } + return this; + }, + + /** + * @private + */ + _extendStyles: function(index, styles) { + var loc = this.get2DCursorLocation(index); + + if (!this.styles[loc.lineIndex]) { + this.styles[loc.lineIndex] = { }; + } + if (!this.styles[loc.lineIndex][loc.charIndex]) { + this.styles[loc.lineIndex][loc.charIndex] = { }; + } + + fabric.util.object.extend(this.styles[loc.lineIndex][loc.charIndex], styles); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + this.callSuper('_render', ctx); + this.ctx = ctx; + this.isEditing && this.renderCursorOrSelection(); + }, + + /** + * Renders cursor or selection (depending on what exists) + */ + renderCursorOrSelection: function() { + if (!this.active) return; + + var chars = this.text.split(''), + boundaries; + + if (this.selectionStart === this.selectionEnd) { + boundaries = this._getCursorBoundaries(chars, 'cursor'); + this.renderCursor(boundaries); + } + else { + boundaries = this._getCursorBoundaries(chars, 'selection'); + this.renderSelection(chars, boundaries); + } + }, + + /** + * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start) + * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used. + */ + get2DCursorLocation: function(selectionStart) { + if (typeof selectionStart === 'undefined') { + selectionStart = this.selectionStart; + } + var textBeforeCursor = this.text.slice(0, selectionStart), + linesBeforeCursor = textBeforeCursor.split(this._reNewline); + + return { + lineIndex: linesBeforeCursor.length - 1, + charIndex: linesBeforeCursor[linesBeforeCursor.length - 1].length + }; + }, + + /** + * Returns complete style of char at the current cursor + * @param {Number} lineIndex Line index + * @param {Number} charIndex Char index + * @return {Object} Character style + */ + getCurrentCharStyle: function(lineIndex, charIndex) { + var style = this.styles[lineIndex] && this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)]; + + return { + fontSize: style && style.fontSize || this.fontSize, + fill: style && style.fill || this.fill, + textBackgroundColor: style && style.textBackgroundColor || this.textBackgroundColor, + textDecoration: style && style.textDecoration || this.textDecoration, + fontFamily: style && style.fontFamily || this.fontFamily, + fontWeight: style && style.fontWeight || this.fontWeight, + fontStyle: style && style.fontStyle || this.fontStyle, + stroke: style && style.stroke || this.stroke, + strokeWidth: style && style.strokeWidth || this.strokeWidth + }; + }, + + /** + * Returns fontSize of char at the current cursor + * @param {Number} lineIndex Line index + * @param {Number} charIndex Char index + * @return {Number} Character font size + */ + getCurrentCharFontSize: function(lineIndex, charIndex) { + return ( + this.styles[lineIndex] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)].fontSize) || this.fontSize; + }, + + /** + * Returns color (fill) of char at the current cursor + * @param {Number} lineIndex Line index + * @param {Number} charIndex Char index + * @return {String} Character color (fill) + */ + getCurrentCharColor: function(lineIndex, charIndex) { + return ( + this.styles[lineIndex] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)].fill) || this.cursorColor; + }, + + /** + * Returns cursor boundaries (left, top, leftOffset, topOffset) + * @private + * @param {Array} chars Array of characters + * @param {String} typeOfBoundaries + */ + _getCursorBoundaries: function(chars, typeOfBoundaries) { + + var cursorLocation = this.get2DCursorLocation(), + + textLines = this.text.split(this._reNewline), + + // left/top are left/top of entire text box + // leftOffset/topOffset are offset from that left/top point of a text box + + left = Math.round(this._getLeftOffset()), + top = -this.height / 2, + + offsets = this._getCursorBoundariesOffsets( + chars, typeOfBoundaries, cursorLocation, textLines); + + return { + left: left, + top: top, + leftOffset: offsets.left + offsets.lineLeft, + topOffset: offsets.top + }; + }, + + /** + * @private + */ + _getCursorBoundariesOffsets: function(chars, typeOfBoundaries, cursorLocation, textLines) { + + var lineLeftOffset = 0, + + lineIndex = 0, + charIndex = 0, + + leftOffset = 0, + topOffset = typeOfBoundaries === 'cursor' + // selection starts at the very top of the line, + // whereas cursor starts at the padding created by line height + ? (this._getHeightOfLine(this.ctx, 0) - + this.getCurrentCharFontSize(cursorLocation.lineIndex, cursorLocation.charIndex)) + : 0; + + for (var i = 0; i < this.selectionStart; i++) { + if (chars[i] === '\n') { + leftOffset = 0; + var index = lineIndex + (typeOfBoundaries === 'cursor' ? 1 : 0); + topOffset += this._getCachedLineHeight(index); + + lineIndex++; + charIndex = 0; + } + else { + leftOffset += this._getWidthOfChar(this.ctx, chars[i], lineIndex, charIndex); + charIndex++; + } + + lineLeftOffset = this._getCachedLineOffset(lineIndex, textLines); + } + + this._clearCache(); + + return { + top: topOffset, + left: leftOffset, + lineLeft: lineLeftOffset + }; + }, + + /** + * @private + */ + _clearCache: function() { + this.__lineWidths = { }; + this.__lineHeights = { }; + this.__lineOffsets = { }; + }, + + /** + * @private + */ + _getCachedLineHeight: function(index) { + return this.__lineHeights[index] || + (this.__lineHeights[index] = this._getHeightOfLine(this.ctx, index)); + }, + + /** + * @private + */ + _getCachedLineWidth: function(lineIndex, textLines) { + return this.__lineWidths[lineIndex] || + (this.__lineWidths[lineIndex] = this._getWidthOfLine(this.ctx, lineIndex, textLines)); + }, + + /** + * @private + */ + _getCachedLineOffset: function(lineIndex, textLines) { + var widthOfLine = this._getCachedLineWidth(lineIndex, textLines); + + return this.__lineOffsets[lineIndex] || + (this.__lineOffsets[lineIndex] = this._getLineLeftOffset(widthOfLine)); + }, + + /** + * Renders cursor + * @param {Object} boundaries + */ + renderCursor: function(boundaries) { + var ctx = this.ctx; + + ctx.save(); + + var cursorLocation = this.get2DCursorLocation(), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex, + charHeight = this.getCurrentCharFontSize(lineIndex, charIndex), + leftOffset = (lineIndex === 0 && charIndex === 0) + ? this._getCachedLineOffset(lineIndex, this.text.split(this._reNewline)) + : boundaries.leftOffset; + + ctx.fillStyle = this.getCurrentCharColor(lineIndex, charIndex); + ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity; + + ctx.fillRect( + boundaries.left + leftOffset, + boundaries.top + boundaries.topOffset, + this.cursorWidth / this.scaleX, + charHeight); + + ctx.restore(); + }, + + /** + * Renders text selection + * @param {Array} chars Array of characters + * @param {Object} boundaries Object with left/top/leftOffset/topOffset + */ + renderSelection: function(chars, boundaries) { + var ctx = this.ctx; + + ctx.save(); + + ctx.fillStyle = this.selectionColor; + + var start = this.get2DCursorLocation(this.selectionStart), + end = this.get2DCursorLocation(this.selectionEnd), + startLine = start.lineIndex, + endLine = end.lineIndex, + textLines = this.text.split(this._reNewline); + + for (var i = startLine; i <= endLine; i++) { + var lineOffset = this._getCachedLineOffset(i, textLines) || 0, + lineHeight = this._getCachedLineHeight(i), + boxWidth = 0; + + if (i === startLine) { + for (var j = 0, len = textLines[i].length; j < len; j++) { + if (j >= start.charIndex && (i !== endLine || j < end.charIndex)) { + boxWidth += this._getWidthOfChar(ctx, textLines[i][j], i, j); + } + if (j < start.charIndex) { + lineOffset += this._getWidthOfChar(ctx, textLines[i][j], i, j); + } + } + } + else if (i > startLine && i < endLine) { + boxWidth += this._getCachedLineWidth(i, textLines) || 5; + } + else if (i === endLine) { + for (var j2 = 0, j2len = end.charIndex; j2 < j2len; j2++) { + boxWidth += this._getWidthOfChar(ctx, textLines[i][j2], i, j2); + } + } + + ctx.fillRect( + boundaries.left + lineOffset, + boundaries.top + boundaries.topOffset, + boxWidth, + lineHeight); + + boundaries.topOffset += lineHeight; + } + ctx.restore(); + }, + + /** + * @private + * @param {String} method + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderChars: function(method, ctx, line, left, top, lineIndex) { + + if (this.isEmptyStyles()) { + return this._renderCharsFast(method, ctx, line, left, top); + } + + this.skipTextAlign = true; + + // set proper box offset + left -= this.textAlign === 'center' + ? (this.width / 2) + : (this.textAlign === 'right') + ? this.width + : 0; + + // set proper line offset + var textLines = this.text.split(this._reNewline), + lineWidth = this._getWidthOfLine(ctx, lineIndex, textLines), + lineHeight = this._getHeightOfLine(ctx, lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(lineWidth), + chars = line.split(''), + prevStyle, + charsToRender = ''; + + left += lineLeftOffset || 0; + + ctx.save(); + + for (var i = 0, len = chars.length; i <= len; i++) { + prevStyle = prevStyle || this.getCurrentCharStyle(lineIndex, i); + var thisStyle = this.getCurrentCharStyle(lineIndex, i + 1); + + if (this._hasStyleChanged(prevStyle, thisStyle) || i === len) { + this._renderChar(method, ctx, lineIndex, i - 1, charsToRender, left, top, lineHeight); + charsToRender = ''; + prevStyle = thisStyle; + } + charsToRender += chars[i]; + } + + ctx.restore(); + }, + + /** + * @private + * @param {String} method + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line + */ + _renderCharsFast: function(method, ctx, line, left, top) { + this.skipTextAlign = false; + + if (method === 'fillText' && this.fill) { + this.callSuper('_renderChars', method, ctx, line, left, top); + } + if (method === 'strokeText' && this.stroke) { + this.callSuper('_renderChars', method, ctx, line, left, top); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) { + var decl, charWidth, charHeight; + + if (this.styles && this.styles[lineIndex] && (decl = this.styles[lineIndex][i])) { + + var shouldStroke = decl.stroke || this.stroke, + shouldFill = decl.fill || this.fill; + + ctx.save(); + charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i, decl); + charHeight = this._getHeightOfChar(ctx, _char, lineIndex, i); + + if (shouldFill) { + ctx.fillText(_char, left, top); + } + if (shouldStroke) { + ctx.strokeText(_char, left, top); + } + + this._renderCharDecoration(ctx, decl, left, top, charWidth, lineHeight, charHeight); + ctx.restore(); + + ctx.translate(charWidth, 0); + } + else { + if (method === 'strokeText' && this.stroke) { + ctx[method](_char, left, top); + } + if (method === 'fillText' && this.fill) { + ctx[method](_char, left, top); + } + charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i); + this._renderCharDecoration(ctx, null, left, top, charWidth, lineHeight); + + ctx.translate(ctx.measureText(_char).width, 0); + } + }, + + /** + * @private + * @param {Object} prevStyle + * @param {Object} thisStyle + */ + _hasStyleChanged: function(prevStyle, thisStyle) { + return (prevStyle.fill !== thisStyle.fill || + prevStyle.fontSize !== thisStyle.fontSize || + prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor || + prevStyle.textDecoration !== thisStyle.textDecoration || + prevStyle.fontFamily !== thisStyle.fontFamily || + prevStyle.fontWeight !== thisStyle.fontWeight || + prevStyle.fontStyle !== thisStyle.fontStyle || + prevStyle.stroke !== thisStyle.stroke || + prevStyle.strokeWidth !== thisStyle.strokeWidth + ); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderCharDecoration: function(ctx, styleDeclaration, left, top, charWidth, lineHeight, charHeight) { + + var textDecoration = styleDeclaration + ? (styleDeclaration.textDecoration || this.textDecoration) + : this.textDecoration, + + fontSize = (styleDeclaration ? styleDeclaration.fontSize : null) || this.fontSize; + + if (!textDecoration) return; + + if (textDecoration.indexOf('underline') > -1) { + this._renderCharDecorationAtOffset( + ctx, + left, + top + (this.fontSize / this._fontSizeFraction), + charWidth, + 0, + this.fontSize / 20 + ); + } + if (textDecoration.indexOf('line-through') > -1) { + this._renderCharDecorationAtOffset( + ctx, + left, + top + (this.fontSize / this._fontSizeFraction), + charWidth, + charHeight / 2, + fontSize / 20 + ); + } + if (textDecoration.indexOf('overline') > -1) { + this._renderCharDecorationAtOffset( + ctx, + left, + top, + charWidth, + lineHeight - (this.fontSize / this._fontSizeFraction), + this.fontSize / 20 + ); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderCharDecorationAtOffset: function(ctx, left, top, charWidth, offset, thickness) { + ctx.fillRect(left, top - offset, charWidth, thickness); + }, + + /** + * @private + * @param {String} method + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line + */ + _renderTextLine: function(method, ctx, line, left, top, lineIndex) { + // to "cancel" this.fontSize subtraction in fabric.Text#_renderTextLine + top += this.fontSize / 4; + this.callSuper('_renderTextLine', method, ctx, line, left, top, lineIndex); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines + */ + _renderTextDecoration: function(ctx, textLines) { + if (this.isEmptyStyles()) { + return this.callSuper('_renderTextDecoration', ctx, textLines); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextLinesBackground: function(ctx, textLines) { + if (!this.textBackgroundColor && !this.styles) return; + + ctx.save(); + + if (this.textBackgroundColor) { + ctx.fillStyle = this.textBackgroundColor; + } + + var lineHeights = 0, + fractionOfFontSize = this.fontSize / this._fontSizeFraction; + + for (var i = 0, len = textLines.length; i < len; i++) { + + var heightOfLine = this._getHeightOfLine(ctx, i, textLines); + if (textLines[i] === '') { + lineHeights += heightOfLine; + continue; + } + + var lineWidth = this._getWidthOfLine(ctx, i, textLines), + lineLeftOffset = this._getLineLeftOffset(lineWidth); + + if (this.textBackgroundColor) { + ctx.fillStyle = this.textBackgroundColor; + + ctx.fillRect( + this._getLeftOffset() + lineLeftOffset, + this._getTopOffset() + lineHeights + fractionOfFontSize, + lineWidth, + heightOfLine + ); + } + if (this.styles[i]) { + for (var j = 0, jlen = textLines[i].length; j < jlen; j++) { + if (this.styles[i] && this.styles[i][j] && this.styles[i][j].textBackgroundColor) { + + var _char = textLines[i][j]; + + ctx.fillStyle = this.styles[i][j].textBackgroundColor; + + ctx.fillRect( + this._getLeftOffset() + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j, textLines), + this._getTopOffset() + lineHeights + fractionOfFontSize, + this._getWidthOfChar(ctx, _char, i, j, textLines) + 1, + heightOfLine + ); + } + } + } + lineHeights += heightOfLine; + } + ctx.restore(); + }, + + /** + * @private + */ + _getCacheProp: function(_char, styleDeclaration) { + return _char + + + styleDeclaration.fontFamily + + styleDeclaration.fontSize + + styleDeclaration.fontWeight + + styleDeclaration.fontStyle + + + styleDeclaration.shadow; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} _char + * @param {Number} lineIndex + * @param {Number} charIndex + * @param {Object} [decl] + */ + _applyCharStylesGetWidth: function(ctx, _char, lineIndex, charIndex, decl) { + var styleDeclaration = decl || + (this.styles[lineIndex] && + this.styles[lineIndex][charIndex]); + + if (styleDeclaration) { + // cloning so that original style object is not polluted with following font declarations + styleDeclaration = clone(styleDeclaration); + } + else { + styleDeclaration = { }; + } + + this._applyFontStyles(styleDeclaration); + + var cacheProp = this._getCacheProp(_char, styleDeclaration); + + // short-circuit if no styles + if (this.isEmptyStyles() && this._charWidthsCache[cacheProp] && this.caching) { + return this._charWidthsCache[cacheProp]; + } + + if (typeof styleDeclaration.shadow === 'string') { + styleDeclaration.shadow = new fabric.Shadow(styleDeclaration.shadow); + } + + var fill = styleDeclaration.fill || this.fill; + ctx.fillStyle = fill.toLive + ? fill.toLive(ctx) + : fill; + + if (styleDeclaration.stroke) { + ctx.strokeStyle = (styleDeclaration.stroke && styleDeclaration.stroke.toLive) + ? styleDeclaration.stroke.toLive(ctx) + : styleDeclaration.stroke; + } + + ctx.lineWidth = styleDeclaration.strokeWidth || this.strokeWidth; + ctx.font = this._getFontDeclaration.call(styleDeclaration); + this._setShadow.call(styleDeclaration, ctx); + + if (!this.caching) { + return ctx.measureText(_char).width; + } + + if (!this._charWidthsCache[cacheProp]) { + this._charWidthsCache[cacheProp] = ctx.measureText(_char).width; + } + + return this._charWidthsCache[cacheProp]; + }, + + /** + * @private + * @param {Object} styleDeclaration + */ + _applyFontStyles: function(styleDeclaration) { + if (!styleDeclaration.fontFamily) { + styleDeclaration.fontFamily = this.fontFamily; + } + if (!styleDeclaration.fontSize) { + styleDeclaration.fontSize = this.fontSize; + } + if (!styleDeclaration.fontWeight) { + styleDeclaration.fontWeight = this.fontWeight; + } + if (!styleDeclaration.fontStyle) { + styleDeclaration.fontStyle = this.fontStyle; + } + }, + + /** + * @private + * @param {Number} lineIndex + * @param {Number} charIndex + */ + _getStyleDeclaration: function(lineIndex, charIndex) { + return (this.styles[lineIndex] && this.styles[lineIndex][charIndex]) + ? clone(this.styles[lineIndex][charIndex]) + : { }; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfChar: function(ctx, _char, lineIndex, charIndex) { + var styleDeclaration = this._getStyleDeclaration(lineIndex, charIndex); + this._applyFontStyles(styleDeclaration); + var cacheProp = this._getCacheProp(_char, styleDeclaration); + + if (this._charWidthsCache[cacheProp] && this.caching) { + return this._charWidthsCache[cacheProp]; + } + else if (ctx) { + ctx.save(); + var width = this._applyCharStylesGetWidth(ctx, _char, lineIndex, charIndex); + ctx.restore(); + return width; + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getHeightOfChar: function(ctx, _char, lineIndex, charIndex) { + if (this.styles[lineIndex] && this.styles[lineIndex][charIndex]) { + return this.styles[lineIndex][charIndex].fontSize || this.fontSize; + } + return this.fontSize; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfCharAt: function(ctx, lineIndex, charIndex, lines) { + lines = lines || this.text.split(this._reNewline); + var _char = lines[lineIndex].split('')[charIndex]; + return this._getWidthOfChar(ctx, _char, lineIndex, charIndex); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getHeightOfCharAt: function(ctx, lineIndex, charIndex, lines) { + lines = lines || this.text.split(this._reNewline); + var _char = lines[lineIndex].split('')[charIndex]; + return this._getHeightOfChar(ctx, _char, lineIndex, charIndex); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfCharsAt: function(ctx, lineIndex, charIndex, lines) { + var width = 0; + for (var i = 0; i < charIndex; i++) { + width += this._getWidthOfCharAt(ctx, lineIndex, i, lines); + } + return width; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfLine: function(ctx, lineIndex, textLines) { + // if (!this.styles[lineIndex]) { + // return this.callSuper('_getLineWidth', ctx, textLines[lineIndex]); + // } + return this._getWidthOfCharsAt(ctx, lineIndex, textLines[lineIndex].length, textLines); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getTextWidth: function(ctx, textLines) { + + if (this.isEmptyStyles()) { + return this.callSuper('_getTextWidth', ctx, textLines); + } + + var maxWidth = this._getWidthOfLine(ctx, 0, textLines); + + for (var i = 1, len = textLines.length; i < len; i++) { + var currentLineWidth = this._getWidthOfLine(ctx, i, textLines); + if (currentLineWidth > maxWidth) { + maxWidth = currentLineWidth; + } + } + return maxWidth; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getHeightOfLine: function(ctx, lineIndex, textLines) { + + textLines = textLines || this.text.split(this._reNewline); + + var maxHeight = this._getHeightOfChar(ctx, textLines[lineIndex][0], lineIndex, 0), + line = textLines[lineIndex], + chars = line.split(''); + + for (var i = 1, len = chars.length; i < len; i++) { + var currentCharHeight = this._getHeightOfChar(ctx, chars[i], lineIndex, i); + if (currentCharHeight > maxHeight) { + maxHeight = currentCharHeight; + } + } + + return maxHeight * this.lineHeight; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getTextHeight: function(ctx, textLines) { + var height = 0; + for (var i = 0, len = textLines.length; i < len; i++) { + height += this._getHeightOfLine(ctx, i, textLines); + } + return height; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getTopOffset: function() { + var topOffset = fabric.Text.prototype._getTopOffset.call(this); + return topOffset - (this.fontSize / this._fontSizeFraction); + }, + + /** + * @private + * This method is overwritten to account for different top offset + */ + _renderTextBoxBackground: function(ctx) { + if (!this.backgroundColor) return; + + ctx.save(); + ctx.fillStyle = this.backgroundColor; + + ctx.fillRect( + this._getLeftOffset(), + this._getTopOffset() + (this.fontSize / this._fontSizeFraction), + this.width, + this.height + ); + + ctx.restore(); + }, + + /** + * Returns object representation of an instance + * @methd toObject + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), { + styles: clone(this.styles) + }); + } + }); + + /** + * Returns fabric.IText instance from an object representation + * @static + * @memberOf fabric.IText + * @param {Object} object Object to create an instance from + * @return {fabric.IText} instance of fabric.IText + */ + fabric.IText.fromObject = function(object) { + return new fabric.IText(object.text, clone(object)); + }; + + /** + * Contains all fabric.IText objects that have been created + * @static + * @memberof fabric.IText + * @type Array + */ + fabric.IText.instances = [ ]; + +})(); + + +(function() { + + var clone = fabric.util.object.clone; + + fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + + /** + * Initializes all the interactive behavior of IText + */ + initBehavior: function() { + this.initAddedHandler(); + this.initCursorSelectionHandlers(); + this.initDoubleClickSimulation(); + }, + + /** + * Initializes "selected" event handler + */ + initSelectedHandler: function() { + this.on('selected', function() { + + var _this = this; + setTimeout(function() { + _this.selected = true; + }, 100); + }); + }, + + /** + * Initializes "added" event handler + */ + initAddedHandler: function() { + this.on('added', function() { + if (this.canvas && !this.canvas._hasITextHandlers) { + this.canvas._hasITextHandlers = true; + this._initCanvasHandlers(); + } + }); + }, + + /** + * @private + */ + _initCanvasHandlers: function() { + this.canvas.on('selection:cleared', function() { + fabric.IText.prototype.exitEditingOnOthers.call(); + }); + + this.canvas.on('mouse:up', function() { + fabric.IText.instances.forEach(function(obj) { + obj.__isMousedown = false; + }); + }); + + this.canvas.on('object:selected', function(options) { + fabric.IText.prototype.exitEditingOnOthers.call(options.target); + }); + }, + + /** + * @private + */ + _tick: function() { + + var _this = this; + + if (this._abortCursorAnimation) return; + + this.animate('_currentCursorOpacity', 1, { + + duration: this.cursorDuration, + + onComplete: function() { + _this._onTickComplete(); + }, + + onChange: function() { + _this.canvas && _this.canvas.renderAll(); + }, + + abort: function() { + return _this._abortCursorAnimation; + } + }); + }, + + /** + * @private + */ + _onTickComplete: function() { + if (this._abortCursorAnimation) return; + + var _this = this; + if (this._cursorTimeout1) { + clearTimeout(this._cursorTimeout1); + } + this._cursorTimeout1 = setTimeout(function() { + _this.animate('_currentCursorOpacity', 0, { + duration: this.cursorDuration / 2, + onComplete: function() { + _this._tick(); + }, + onChange: function() { + _this.canvas && _this.canvas.renderAll(); + }, + abort: function() { + return _this._abortCursorAnimation; + } + }); + }, 100); + }, + + /** + * Initializes delayed cursor + */ + initDelayedCursor: function(restart) { + var _this = this, + delay = restart ? 0 : this.cursorDelay; + + if (restart) { + this._abortCursorAnimation = true; + clearTimeout(this._cursorTimeout1); + this._currentCursorOpacity = 1; + this.canvas && this.canvas.renderAll(); + } + if (this._cursorTimeout2) { + clearTimeout(this._cursorTimeout2); + } + this._cursorTimeout2 = setTimeout(function() { + _this._abortCursorAnimation = false; + _this._tick(); + }, delay); + }, + + /** + * Aborts cursor animation and clears all timeouts + */ + abortCursorAnimation: function() { + this._abortCursorAnimation = true; + + clearTimeout(this._cursorTimeout1); + clearTimeout(this._cursorTimeout2); + + this._currentCursorOpacity = 0; + this.canvas && this.canvas.renderAll(); + + var _this = this; + setTimeout(function() { + _this._abortCursorAnimation = false; + }, 10); + }, + + /** + * Selects entire text + */ + selectAll: function() { + this.selectionStart = 0; + this.selectionEnd = this.text.length; + this.fire('selection:changed'); + this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + }, + + /** + * Returns selected text + * @return {String} + */ + getSelectedText: function() { + return this.text.slice(this.selectionStart, this.selectionEnd); + }, + + /** + * Find new selection index representing start of current word according to current selection index + * @param {Number} startFrom Surrent selection index + * @return {Number} New selection index + */ + findWordBoundaryLeft: function(startFrom) { + var offset = 0, index = startFrom - 1; + + // remove space before cursor first + if (this._reSpace.test(this.text.charAt(index))) { + while (this._reSpace.test(this.text.charAt(index))) { + offset++; + index--; + } + } + while (/\S/.test(this.text.charAt(index)) && index > -1) { + offset++; + index--; + } + + return startFrom - offset; + }, + + /** + * Find new selection index representing end of current word according to current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index + */ + findWordBoundaryRight: function(startFrom) { + var offset = 0, index = startFrom; + + // remove space after cursor first + if (this._reSpace.test(this.text.charAt(index))) { + while (this._reSpace.test(this.text.charAt(index))) { + offset++; + index++; + } + } + while (/\S/.test(this.text.charAt(index)) && index < this.text.length) { + offset++; + index++; + } + + return startFrom + offset; + }, + + /** + * Find new selection index representing start of current line according to current selection index + * @param {Number} current selection index + */ + findLineBoundaryLeft: function(startFrom) { + var offset = 0, index = startFrom - 1; + + while (!/\n/.test(this.text.charAt(index)) && index > -1) { + offset++; + index--; + } + + return startFrom - offset; + }, + + /** + * Find new selection index representing end of current line according to current selection index + * @param {Number} current selection index + */ + findLineBoundaryRight: function(startFrom) { + var offset = 0, index = startFrom; + + while (!/\n/.test(this.text.charAt(index)) && index < this.text.length) { + offset++; + index++; + } + + return startFrom + offset; + }, + + /** + * Returns number of newlines in selected text + * @return {Number} Number of newlines in selected text + */ + getNumNewLinesInSelectedText: function() { + var selectedText = this.getSelectedText(), + numNewLines = 0; + + for (var i = 0, chars = selectedText.split(''), len = chars.length; i < len; i++) { + if (chars[i] === '\n') { + numNewLines++; + } + } + return numNewLines; + }, + + /** + * Finds index corresponding to beginning or end of a word + * @param {Number} selectionStart Index of a character + * @param {Number} direction: 1 or -1 + */ + searchWordBoundary: function(selectionStart, direction) { + var index = this._reSpace.test(this.text.charAt(selectionStart)) ? selectionStart - 1 : selectionStart, + _char = this.text.charAt(index), + reNonWord = /[ \n\.,;!\?\-]/; + + while (!reNonWord.test(_char) && index > 0 && index < this.text.length) { + index += direction; + _char = this.text.charAt(index); + } + if (reNonWord.test(_char) && _char !== '\n') { + index += direction === 1 ? 0 : 1; + } + return index; + }, + + /** + * Selects a word based on the index + * @param {Number} selectionStart Index of a character + */ + selectWord: function(selectionStart) { + var newSelectionStart = this.searchWordBoundary(selectionStart, -1), /* search backwards */ + newSelectionEnd = this.searchWordBoundary(selectionStart, 1); /* search forward */ + + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionEnd); + this.initDelayedCursor(true); + }, + + /** + * Selects a line based on the index + * @param {Number} selectionStart Index of a character + */ + selectLine: function(selectionStart) { + var newSelectionStart = this.findLineBoundaryLeft(selectionStart), + newSelectionEnd = this.findLineBoundaryRight(selectionStart); + + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionEnd); + this.initDelayedCursor(true); + }, + + /** + * Enters editing state + * @return {fabric.IText} thisArg + * @chainable + */ + enterEditing: function() { + if (this.isEditing || !this.editable) return; + + this.exitEditingOnOthers(); + + this.isEditing = true; + + this.initHiddenTextarea(); + this._updateTextarea(); + this._saveEditingProps(); + this._setEditingProps(); + + this._tick(); + this.canvas && this.canvas.renderAll(); + + this.fire('editing:entered'); + this.canvas && this.canvas.fire('text:editing:entered', { target: this }); + + return this; + }, + + exitEditingOnOthers: function() { + fabric.IText.instances.forEach(function(obj) { + obj.selected = false; + if (obj.isEditing) { + obj.exitEditing(); + } + }, this); + }, + + /** + * @private + */ + _setEditingProps: function() { + this.hoverCursor = 'text'; + + if (this.canvas) { + this.canvas.defaultCursor = this.canvas.moveCursor = 'text'; + } + + this.borderColor = this.editingBorderColor; + + this.hasControls = this.selectable = false; + this.lockMovementX = this.lockMovementY = true; + }, + + /** + * @private + */ + _updateTextarea: function() { + if (!this.hiddenTextarea) return; + + this.hiddenTextarea.value = this.text; + this.hiddenTextarea.selectionStart = this.selectionStart; + }, + + /** + * @private + */ + _saveEditingProps: function() { + this._savedProps = { + hasControls: this.hasControls, + borderColor: this.borderColor, + lockMovementX: this.lockMovementX, + lockMovementY: this.lockMovementY, + hoverCursor: this.hoverCursor, + defaultCursor: this.canvas && this.canvas.defaultCursor, + moveCursor: this.canvas && this.canvas.moveCursor + }; + }, + + /** + * @private + */ + _restoreEditingProps: function() { + if (!this._savedProps) return; + + this.hoverCursor = this._savedProps.overCursor; + this.hasControls = this._savedProps.hasControls; + this.borderColor = this._savedProps.borderColor; + this.lockMovementX = this._savedProps.lockMovementX; + this.lockMovementY = this._savedProps.lockMovementY; + + if (this.canvas) { + this.canvas.defaultCursor = this._savedProps.defaultCursor; + this.canvas.moveCursor = this._savedProps.moveCursor; + } + }, + + /** + * Exits from editing state + * @return {fabric.IText} thisArg + * @chainable + */ + exitEditing: function() { + + this.selected = false; + this.isEditing = false; + this.selectable = true; + + this.selectionEnd = this.selectionStart; + this.hiddenTextarea && this.canvas && this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea); + this.hiddenTextarea = null; + + this.abortCursorAnimation(); + this._restoreEditingProps(); + this._currentCursorOpacity = 0; + + this.fire('editing:exited'); + this.canvas && this.canvas.fire('text:editing:exited', { target: this }); + + return this; + }, + + /** + * @private + */ + _removeExtraneousStyles: function() { + var textLines = this.text.split(this._reNewline); + for (var prop in this.styles) { + if (!textLines[prop]) { + delete this.styles[prop]; + } + } + }, + + /** + * @private + */ + _removeCharsFromTo: function(start, end) { + + var i = end; + while (i !== start) { + + var prevIndex = this.get2DCursorLocation(i).charIndex; + i--; + + var index = this.get2DCursorLocation(i).charIndex, + isNewline = index > prevIndex; + + if (isNewline) { + this.removeStyleObject(isNewline, i + 1); + } + else { + this.removeStyleObject(this.get2DCursorLocation(i).charIndex === 0, i); + } + + } + + this.text = this.text.slice(0, start) + + this.text.slice(end); + }, + + /** + * Inserts a character where cursor is (replacing selection if one exists) + * @param {String} _chars Characters to insert + */ + insertChars: function(_chars) { + var isEndOfLine = this.text.slice(this.selectionStart, this.selectionStart + 1) === '\n'; + + this.text = this.text.slice(0, this.selectionStart) + + _chars + + this.text.slice(this.selectionEnd); + + if (this.selectionStart === this.selectionEnd) { + this.insertStyleObjects(_chars, isEndOfLine, this.copiedStyles); + } + // else if (this.selectionEnd - this.selectionStart > 1) { + // TODO: replace styles properly + // console.log('replacing MORE than 1 char'); + // } + + this.selectionStart += _chars.length; + this.selectionEnd = this.selectionStart; + + if (this.canvas) { + // TODO: double renderAll gets rid of text box shift happenning sometimes + // need to find out what exactly causes it and fix it + this.canvas.renderAll().renderAll(); + } + + this.setCoords(); + this.fire('changed'); + this.canvas && this.canvas.fire('text:changed', { target: this }); + }, + + /** + * Inserts new style object + * @param {Number} lineIndex Index of a line + * @param {Number} charIndex Index of a char + * @param {Boolean} isEndOfLine True if it's end of line + */ + insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) { + + this.shiftLineStyles(lineIndex, +1); + + if (!this.styles[lineIndex + 1]) { + this.styles[lineIndex + 1] = { }; + } + + var currentCharStyle = this.styles[lineIndex][charIndex - 1], + newLineStyles = { }; + + // if there's nothing after cursor, + // we clone current char style onto the next (otherwise empty) line + if (isEndOfLine) { + newLineStyles[0] = clone(currentCharStyle); + this.styles[lineIndex + 1] = newLineStyles; + } + // otherwise we clone styles of all chars + // after cursor onto the next line, from the beginning + else { + for (var index in this.styles[lineIndex]) { + if (parseInt(index, 10) >= charIndex) { + newLineStyles[parseInt(index, 10) - charIndex] = this.styles[lineIndex][index]; + // remove lines from the previous line since they're on a new line now + delete this.styles[lineIndex][index]; + } + } + this.styles[lineIndex + 1] = newLineStyles; + } + }, + + /** + * Inserts style object for a given line/char index + * @param {Number} lineIndex Index of a line + * @param {Number} charIndex Index of a char + * @param {Object} [style] Style object to insert, if given + */ + insertCharStyleObject: function(lineIndex, charIndex, style) { + + var currentLineStyles = this.styles[lineIndex], + currentLineStylesCloned = clone(currentLineStyles); + + if (charIndex === 0 && !style) { + charIndex = 1; + } + + // shift all char styles by 1 forward + // 0,1,2,3 -> (charIndex=2) -> 0,1,3,4 -> (insert 2) -> 0,1,2,3,4 + for (var index in currentLineStylesCloned) { + var numericIndex = parseInt(index, 10); + if (numericIndex >= charIndex) { + currentLineStyles[numericIndex + 1] = currentLineStylesCloned[numericIndex]; + //delete currentLineStyles[index]; + } + } + + this.styles[lineIndex][charIndex] = + style || clone(currentLineStyles[charIndex - 1]); + }, + + /** + * Inserts style object(s) + * @param {String} _chars Characters at the location where style is inserted + * @param {Boolean} isEndOfLine True if it's end of line + * @param {Array} [styles] Styles to insert + */ + insertStyleObjects: function(_chars, isEndOfLine, styles) { + + // short-circuit + if (this.isEmptyStyles()) return; + + var cursorLocation = this.get2DCursorLocation(), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex; + + if (!this.styles[lineIndex]) { + this.styles[lineIndex] = { }; + } + + if (_chars === '\n') { + this.insertNewlineStyleObject(lineIndex, charIndex, isEndOfLine); + } + else { + if (styles) { + this._insertStyles(styles); + } + else { + // TODO: support multiple style insertion if _chars.length > 1 + this.insertCharStyleObject(lineIndex, charIndex); + } + } + }, + + /** + * @private + */ + _insertStyles: function(styles) { + for (var i = 0, len = styles.length; i < len; i++) { + + var cursorLocation = this.get2DCursorLocation(this.selectionStart + i), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex; + + this.insertCharStyleObject(lineIndex, charIndex, styles[i]); + } + }, + + /** + * Shifts line styles up or down + * @param {Number} lineIndex Index of a line + * @param {Number} offset Can be -1 or +1 + */ + shiftLineStyles: function(lineIndex, offset) { + // shift all line styles by 1 upward + var clonedStyles = clone(this.styles); + for (var line in this.styles) { + var numericLine = parseInt(line, 10); + if (numericLine > lineIndex) { + this.styles[numericLine + offset] = clonedStyles[numericLine]; + } + } + }, + + /** + * Removes style object + * @param {Boolean} isBeginningOfLine True if cursor is at the beginning of line + * @param {Number} [index] Optional index. When not given, current selectionStart is used. + */ + removeStyleObject: function(isBeginningOfLine, index) { + + var cursorLocation = this.get2DCursorLocation(index), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex; + + if (isBeginningOfLine) { + + var textLines = this.text.split(this._reNewline), + textOnPreviousLine = textLines[lineIndex - 1], + newCharIndexOnPrevLine = textOnPreviousLine + ? textOnPreviousLine.length + : 0; + + if (!this.styles[lineIndex - 1]) { + this.styles[lineIndex - 1] = { }; + } + + for (charIndex in this.styles[lineIndex]) { + this.styles[lineIndex - 1][parseInt(charIndex, 10) + newCharIndexOnPrevLine] + = this.styles[lineIndex][charIndex]; + } + + this.shiftLineStyles(lineIndex, -1); + } + else { + var currentLineStyles = this.styles[lineIndex]; + + if (currentLineStyles) { + var offset = this.selectionStart === this.selectionEnd ? -1 : 0; + delete currentLineStyles[charIndex + offset]; + // console.log('deleting', lineIndex, charIndex + offset); + } + + var currentLineStylesCloned = clone(currentLineStyles); + + // shift all styles by 1 backwards + for (var i in currentLineStylesCloned) { + var numericIndex = parseInt(i, 10); + if (numericIndex >= charIndex && numericIndex !== 0) { + currentLineStyles[numericIndex - 1] = currentLineStylesCloned[numericIndex]; + delete currentLineStyles[numericIndex]; + } + } + } + }, + + /** + * Inserts new line + */ + insertNewline: function() { + this.insertChars('\n'); + } + }); +})(); + + +fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + /** + * Initializes "dbclick" event handler + */ + initDoubleClickSimulation: function() { + + // for double click + this.__lastClickTime = +new Date(); + + // for triple click + this.__lastLastClickTime = +new Date(); + + this.__lastPointer = { }; + + this.on('mousedown', this.onMouseDown.bind(this)); + }, + + onMouseDown: function(options) { + + this.__newClickTime = +new Date(); + var newPointer = this.canvas.getPointer(options.e); + + if (this.isTripleClick(newPointer)) { + this.fire('tripleclick', options); + this._stopEvent(options.e); + } + else if (this.isDoubleClick(newPointer)) { + this.fire('dblclick', options); + this._stopEvent(options.e); + } + + this.__lastLastClickTime = this.__lastClickTime; + this.__lastClickTime = this.__newClickTime; + this.__lastPointer = newPointer; + this.__lastIsEditing = this.isEditing; + this.__lastSelected = this.selected; + }, + + isDoubleClick: function(newPointer) { + return this.__newClickTime - this.__lastClickTime < 500 && + this.__lastPointer.x === newPointer.x && + this.__lastPointer.y === newPointer.y && this.__lastIsEditing; + }, + + isTripleClick: function(newPointer) { + return this.__newClickTime - this.__lastClickTime < 500 && + this.__lastClickTime - this.__lastLastClickTime < 500 && + this.__lastPointer.x === newPointer.x && + this.__lastPointer.y === newPointer.y; + }, + + /** + * @private + */ + _stopEvent: function(e) { + e.preventDefault && e.preventDefault(); + e.stopPropagation && e.stopPropagation(); + }, + + /** + * Initializes event handlers related to cursor or selection + */ + initCursorSelectionHandlers: function() { + this.initSelectedHandler(); + this.initMousedownHandler(); + this.initMousemoveHandler(); + this.initMouseupHandler(); + this.initClicks(); + }, + + /** + * Initializes double and triple click event handlers + */ + initClicks: function() { + this.on('dblclick', function(options) { + this.selectWord(this.getSelectionStartFromPointer(options.e)); + }); + this.on('tripleclick', function(options) { + this.selectLine(this.getSelectionStartFromPointer(options.e)); + }); + }, + + /** + * Initializes "mousedown" event handler + */ + initMousedownHandler: function() { + this.on('mousedown', function(options) { + + var pointer = this.canvas.getPointer(options.e); + + this.__mousedownX = pointer.x; + this.__mousedownY = pointer.y; + this.__isMousedown = true; + + if (this.hiddenTextarea && this.canvas) { + this.canvas.wrapperEl.appendChild(this.hiddenTextarea); + } + + if (this.selected) { + this.setCursorByClick(options.e); + } + + if (this.isEditing) { + this.__selectionStartOnMouseDown = this.selectionStart; + this.initDelayedCursor(true); + } + }); + }, + + /** + * Initializes "mousemove" event handler + */ + initMousemoveHandler: function() { + this.on('mousemove', function(options) { + if (!this.__isMousedown || !this.isEditing) return; + + var newSelectionStart = this.getSelectionStartFromPointer(options.e); + + if (newSelectionStart >= this.__selectionStartOnMouseDown) { + this.setSelectionStart(this.__selectionStartOnMouseDown); + this.setSelectionEnd(newSelectionStart); + } + else { + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(this.__selectionStartOnMouseDown); + } + }); + }, + + /** + * @private + */ + _isObjectMoved: function(e) { + var pointer = this.canvas.getPointer(e); + + return this.__mousedownX !== pointer.x || + this.__mousedownY !== pointer.y; + }, + + /** + * Initializes "mouseup" event handler + */ + initMouseupHandler: function() { + this.on('mouseup', function(options) { + this.__isMousedown = false; + if (this._isObjectMoved(options.e)) return; + + if (this.__lastSelected) { + this.enterEditing(); + this.initDelayedCursor(true); + } + this.selected = true; + }); + }, + + /** + * Changes cursor location in a text depending on passed pointer (x/y) object + * @param {Object} pointer Pointer object with x and y numeric properties + */ + setCursorByClick: function(e) { + var newSelectionStart = this.getSelectionStartFromPointer(e); + + if (e.shiftKey) { + if (newSelectionStart < this.selectionStart) { + this.setSelectionEnd(this.selectionStart); + this.setSelectionStart(newSelectionStart); + } + else { + this.setSelectionEnd(newSelectionStart); + } + } + else { + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionStart); + } + }, + + /** + * @private + * @param {Event} e Event object + * @param {Object} Object with x/y corresponding to local offset (according to object rotation) + */ + _getLocalRotatedPointer: function(e) { + var pointer = this.canvas.getPointer(e), + + pClicked = new fabric.Point(pointer.x, pointer.y), + pLeftTop = new fabric.Point(this.left, this.top), + + rotated = fabric.util.rotatePoint( + pClicked, pLeftTop, fabric.util.degreesToRadians(-this.angle)); + + return this.getLocalPointer(e, rotated); + }, + + /** + * Returns index of a character corresponding to where an object was clicked + * @param {Event} e Event object + * @return {Number} Index of a character + */ + getSelectionStartFromPointer: function(e) { + + var mouseOffset = this._getLocalRotatedPointer(e), + textLines = this.text.split(this._reNewline), + prevWidth = 0, + width = 0, + height = 0, + charIndex = 0, + newSelectionStart; + + for (var i = 0, len = textLines.length; i < len; i++) { + + height += this._getHeightOfLine(this.ctx, i) * this.scaleY; + + var widthOfLine = this._getWidthOfLine(this.ctx, i, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfLine); + + width = lineLeftOffset * this.scaleX; + + if (this.flipX) { + // when oject is horizontally flipped we reverse chars + textLines[i] = textLines[i].split('').reverse().join(''); + } + + for (var j = 0, jlen = textLines[i].length; j < jlen; j++) { + + var _char = textLines[i][j]; + prevWidth = width; + + width += this._getWidthOfChar(this.ctx, _char, i, this.flipX ? jlen - j : j) * + this.scaleX; + + if (height <= mouseOffset.y || width <= mouseOffset.x) { + charIndex++; + continue; + } + + return this._getNewSelectionStartFromOffset( + mouseOffset, prevWidth, width, charIndex + i, jlen); + } + + if (mouseOffset.y < height) { + return this._getNewSelectionStartFromOffset( + mouseOffset, prevWidth, width, charIndex + i, jlen, j); + } + } + + // clicked somewhere after all chars, so set at the end + if (typeof newSelectionStart === 'undefined') { + return this.text.length; + } + }, + + /** + * @private + */ + _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen, j) { + + var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth, + distanceBtwNextCharAndCursor = width - mouseOffset.x, + offset = distanceBtwNextCharAndCursor > distanceBtwLastCharAndCursor ? 0 : 1, + newSelectionStart = index + offset; + + // if object is horizontally flipped, mirror cursor location from the end + if (this.flipX) { + newSelectionStart = jlen - newSelectionStart; + } + + if (newSelectionStart > this.text.length) { + newSelectionStart = this.text.length; + } + + if (j === jlen) { + newSelectionStart--; + } + + return newSelectionStart; + } +}); + + +fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + + /** + * Initializes hidden textarea (needed to bring up keyboard in iOS) + */ + initHiddenTextarea: function() { + this.hiddenTextarea = fabric.document.createElement('textarea'); + + this.hiddenTextarea.setAttribute('autocapitalize', 'off'); + this.hiddenTextarea.style.cssText = 'position: absolute; top: 0; left: -9999px'; + + fabric.document.body.appendChild(this.hiddenTextarea); + + fabric.util.addListener(this.hiddenTextarea, 'keydown', this.onKeyDown.bind(this)); + fabric.util.addListener(this.hiddenTextarea, 'keypress', this.onKeyPress.bind(this)); + fabric.util.addListener(this.hiddenTextarea, 'copy', this.copy.bind(this)); + fabric.util.addListener(this.hiddenTextarea, 'paste', this.paste.bind(this)); + + if (!this._clickHandlerInitialized && this.canvas) { + fabric.util.addListener(this.canvas.upperCanvasEl, 'click', this.onClick.bind(this)); + this._clickHandlerInitialized = true; + } + }, + + /** + * @private + */ + _keysMap: { + 8: 'removeChars', + 13: 'insertNewline', + 37: 'moveCursorLeft', + 38: 'moveCursorUp', + 39: 'moveCursorRight', + 40: 'moveCursorDown', + 46: 'forwardDelete' + }, + + /** + * @private + */ + _ctrlKeysMap: { + 65: 'selectAll', + 88: 'cut' + }, + + onClick: function() { + // No need to trigger click event here, focus is enough to have the keyboard appear on Android + this.hiddenTextarea && this.hiddenTextarea.focus(); + }, + + /** + * Handles keyup event + * @param {Event} e Event object + */ + onKeyDown: function(e) { + if (!this.isEditing) return; + + if (e.keyCode in this._keysMap) { + this[this._keysMap[e.keyCode]](e); + } + else if ((e.keyCode in this._ctrlKeysMap) && (e.ctrlKey || e.metaKey)) { + this[this._ctrlKeysMap[e.keyCode]](e); + } + else { + return; + } + + e.stopPropagation(); + + this.canvas && this.canvas.renderAll(); + }, + + /** + * Forward delete + */ + forwardDelete: function(e) { + if (this.selectionStart === this.selectionEnd) { + this.moveCursorRight(e); + } + this.removeChars(e); + }, + + /** + * Copies selected text + * @param {Event} e Event object + */ + copy: function(e) { + var selectedText = this.getSelectedText(), + clipboardData = this._getClipboardData(e); + + // Check for backward compatibility with old browsers + if (clipboardData) { + clipboardData.setData('text', selectedText); + } + + this.copiedText = selectedText; + this.copiedStyles = this.getSelectionStyles( + this.selectionStart, + this.selectionEnd); + }, + + /** + * Pastes text + * @param {Event} e Event object + */ + paste: function(e) { + var copiedText = null, + clipboardData = this._getClipboardData(e); + + // Check for backward compatibility with old browsers + if (clipboardData) { + copiedText = clipboardData.getData('text'); + } else { + copiedText = this.copiedText; + } + + if (copiedText) { + this.insertChars(copiedText); + } + }, + + /** + * Cuts text + * @param {Event} e Event object + */ + cut: function(e) { + if (this.selectionStart === this.selectionEnd) { + return; + } + + this.copy(); + this.removeChars(e); + }, + + /** + * @private + * @param {Event} e Event object + */ + _getClipboardData: function(e) { + return e && (e.clipboardData || fabric.window.clipboardData); + }, + + /** + * Handles keypress event + * @param {Event} e Event object + */ + onKeyPress: function(e) { + if (!this.isEditing || e.metaKey || e.ctrlKey || e.keyCode === 8 || e.keyCode === 13) { + return; + } + + this.insertChars(String.fromCharCode(e.which)); + + e.stopPropagation(); + }, + + /** + * Gets start offset of a selection + * @return {Number} + */ + getDownCursorOffset: function(e, isRight) { + + var selectionProp = isRight ? this.selectionEnd : this.selectionStart, + textLines = this.text.split(this._reNewline), + _char, + lineLeftOffset, + + textBeforeCursor = this.text.slice(0, selectionProp), + textAfterCursor = this.text.slice(selectionProp), + + textOnSameLineBeforeCursor = textBeforeCursor.slice(textBeforeCursor.lastIndexOf('\n') + 1), + textOnSameLineAfterCursor = textAfterCursor.match(/(.*)\n?/)[1], + textOnNextLine = (textAfterCursor.match(/.*\n(.*)\n?/) || { })[1] || '', + + cursorLocation = this.get2DCursorLocation(selectionProp); + + // if on last line, down cursor goes to end of line + if (cursorLocation.lineIndex === textLines.length - 1 || e.metaKey) { + + // move to the end of a text + return this.text.length - selectionProp; + } + + var widthOfSameLineBeforeCursor = this._getWidthOfLine(this.ctx, cursorLocation.lineIndex, textLines); + lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor); + + var widthOfCharsOnSameLineBeforeCursor = lineLeftOffset, + lineIndex = cursorLocation.lineIndex; + + for (var i = 0, len = textOnSameLineBeforeCursor.length; i < len; i++) { + _char = textOnSameLineBeforeCursor[i]; + widthOfCharsOnSameLineBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i); + } + + var indexOnNextLine = this._getIndexOnNextLine( + cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines); + + return textOnSameLineAfterCursor.length + 1 + indexOnNextLine; + }, + + /** + * @private + */ + _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines) { + + var lineIndex = cursorLocation.lineIndex + 1, + widthOfNextLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfNextLine), + widthOfCharsOnNextLine = lineLeftOffset, + indexOnNextLine = 0, + foundMatch; + + for (var j = 0, jlen = textOnNextLine.length; j < jlen; j++) { + + var _char = textOnNextLine[j], + widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j); + + widthOfCharsOnNextLine += widthOfChar; + + if (widthOfCharsOnNextLine > widthOfCharsOnSameLineBeforeCursor) { + + foundMatch = true; + + var leftEdge = widthOfCharsOnNextLine - widthOfChar, + rightEdge = widthOfCharsOnNextLine, + offsetFromLeftEdge = Math.abs(leftEdge - widthOfCharsOnSameLineBeforeCursor), + offsetFromRightEdge = Math.abs(rightEdge - widthOfCharsOnSameLineBeforeCursor); + + indexOnNextLine = offsetFromRightEdge < offsetFromLeftEdge ? j + 1 : j; + + break; + } + } + + // reached end + if (!foundMatch) { + indexOnNextLine = textOnNextLine.length; + } + + return indexOnNextLine; + }, + + /** + * Moves cursor down + * @param {Event} e Event object + */ + moveCursorDown: function(e) { + + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + var offset = this.getDownCursorOffset(e, this._selectionDirection === 'right'); + + if (e.shiftKey) { + this.moveCursorDownWithShift(offset); + } + else { + this.moveCursorDownWithoutShift(offset); + } + + this.initDelayedCursor(); + }, + + /** + * Moves cursor down without keeping selection + * @param {Number} offset + */ + moveCursorDownWithoutShift: function(offset) { + + this._selectionDirection = 'right'; + this.selectionStart += offset; + + if (this.selectionStart > this.text.length) { + this.selectionStart = this.text.length; + } + this.selectionEnd = this.selectionStart; + }, + + /** + * Moves cursor down while keeping selection + * @param {Number} offset + */ + moveCursorDownWithShift: function(offset) { + + if (this._selectionDirection === 'left' && (this.selectionStart !== this.selectionEnd)) { + this.selectionStart += offset; + this._selectionDirection = 'left'; + return; + } + else { + this._selectionDirection = 'right'; + this.selectionEnd += offset; + + if (this.selectionEnd > this.text.length) { + this.selectionEnd = this.text.length; + } + } + }, + + getUpCursorOffset: function(e, isRight) { + + var selectionProp = isRight ? this.selectionEnd : this.selectionStart, + cursorLocation = this.get2DCursorLocation(selectionProp); + + // if on first line, up cursor goes to start of line + if (cursorLocation.lineIndex === 0 || e.metaKey) { + return selectionProp; + } + + var textBeforeCursor = this.text.slice(0, selectionProp), + textOnSameLineBeforeCursor = textBeforeCursor.slice(textBeforeCursor.lastIndexOf('\n') + 1), + textOnPreviousLine = (textBeforeCursor.match(/\n?(.*)\n.*$/) || {})[1] || '', + textLines = this.text.split(this._reNewline), + _char, + widthOfSameLineBeforeCursor = this._getWidthOfLine(this.ctx, cursorLocation.lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor), + widthOfCharsOnSameLineBeforeCursor = lineLeftOffset, + lineIndex = cursorLocation.lineIndex; + + for (var i = 0, len = textOnSameLineBeforeCursor.length; i < len; i++) { + _char = textOnSameLineBeforeCursor[i]; + widthOfCharsOnSameLineBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i); + } + + var indexOnPrevLine = this._getIndexOnPrevLine( + cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor, textLines); + + return textOnPreviousLine.length - indexOnPrevLine + textOnSameLineBeforeCursor.length; + }, + + /** + * @private + */ + _getIndexOnPrevLine: function(cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor, textLines) { + + var lineIndex = cursorLocation.lineIndex - 1, + widthOfPreviousLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfPreviousLine), + widthOfCharsOnPreviousLine = lineLeftOffset, + indexOnPrevLine = 0, + foundMatch; + + for (var j = 0, jlen = textOnPreviousLine.length; j < jlen; j++) { + + var _char = textOnPreviousLine[j], + widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j); + + widthOfCharsOnPreviousLine += widthOfChar; + + if (widthOfCharsOnPreviousLine > widthOfCharsOnSameLineBeforeCursor) { + + foundMatch = true; + + var leftEdge = widthOfCharsOnPreviousLine - widthOfChar, + rightEdge = widthOfCharsOnPreviousLine, + offsetFromLeftEdge = Math.abs(leftEdge - widthOfCharsOnSameLineBeforeCursor), + offsetFromRightEdge = Math.abs(rightEdge - widthOfCharsOnSameLineBeforeCursor); + + indexOnPrevLine = offsetFromRightEdge < offsetFromLeftEdge ? j : (j - 1); + + break; + } + } + + // reached end + if (!foundMatch) { + indexOnPrevLine = textOnPreviousLine.length - 1; + } + + return indexOnPrevLine; + }, + + /** + * Moves cursor up + * @param {Event} e Event object + */ + moveCursorUp: function(e) { + + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + var offset = this.getUpCursorOffset(e, this._selectionDirection === 'right'); + + if (e.shiftKey) { + this.moveCursorUpWithShift(offset); + } + else { + this.moveCursorUpWithoutShift(offset); + } + + this.initDelayedCursor(); + }, + + /** + * Moves cursor up with shift + * @param {Number} offset + */ + moveCursorUpWithShift: function(offset) { + + if (this.selectionStart === this.selectionEnd) { + this.selectionStart -= offset; + } + else { + if (this._selectionDirection === 'right') { + this.selectionEnd -= offset; + this._selectionDirection = 'right'; + return; + } + else { + this.selectionStart -= offset; + } + } + + if (this.selectionStart < 0) { + this.selectionStart = 0; + } + + this._selectionDirection = 'left'; + }, + + /** + * Moves cursor up without shift + * @param {Number} offset + */ + moveCursorUpWithoutShift: function(offset) { + if (this.selectionStart === this.selectionEnd) { + this.selectionStart -= offset; + } + if (this.selectionStart < 0) { + this.selectionStart = 0; + } + this.selectionEnd = this.selectionStart; + + this._selectionDirection = 'left'; + }, + + /** + * Moves cursor left + * @param {Event} e Event object + */ + moveCursorLeft: function(e) { + if (this.selectionStart === 0 && this.selectionEnd === 0) return; + + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + if (e.shiftKey) { + this.moveCursorLeftWithShift(e); + } + else { + this.moveCursorLeftWithoutShift(e); + } + + this.initDelayedCursor(); + }, + + /** + * @private + */ + _move: function(e, prop, direction) { + if (e.altKey) { + this[prop] = this['findWordBoundary' + direction](this[prop]); + } + else if (e.metaKey) { + this[prop] = this['findLineBoundary' + direction](this[prop]); + } + else { + this[prop] += (direction === 'Left' ? -1 : 1); + } + }, + + /** + * @private + */ + _moveLeft: function(e, prop) { + this._move(e, prop, 'Left'); + }, + + /** + * @private + */ + _moveRight: function(e, prop) { + this._move(e, prop, 'Right'); + }, + + /** + * Moves cursor left without keeping selection + * @param {Event} e + */ + moveCursorLeftWithoutShift: function(e) { + this._selectionDirection = 'left'; + + // only move cursor when there is no selection, + // otherwise we discard it, and leave cursor on same place + if (this.selectionEnd === this.selectionStart) { + this._moveLeft(e, 'selectionStart'); + } + this.selectionEnd = this.selectionStart; + }, + + /** + * Moves cursor left while keeping selection + * @param {Event} e + */ + moveCursorLeftWithShift: function(e) { + if (this._selectionDirection === 'right' && this.selectionStart !== this.selectionEnd) { + this._moveLeft(e, 'selectionEnd'); + } + else { + this._selectionDirection = 'left'; + this._moveLeft(e, 'selectionStart'); + + // increase selection by one if it's a newline + if (this.text.charAt(this.selectionStart) === '\n') { + this.selectionStart--; + } + if (this.selectionStart < 0) { + this.selectionStart = 0; + } + } + }, + + /** + * Moves cursor right + * @param {Event} e Event object + */ + moveCursorRight: function(e) { + if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) return; + + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + if (e.shiftKey) { + this.moveCursorRightWithShift(e); + } + else { + this.moveCursorRightWithoutShift(e); + } + + this.initDelayedCursor(); + }, + + /** + * Moves cursor right while keeping selection + * @param {Event} e + */ + moveCursorRightWithShift: function(e) { + if (this._selectionDirection === 'left' && this.selectionStart !== this.selectionEnd) { + this._moveRight(e, 'selectionStart'); + } + else { + this._selectionDirection = 'right'; + this._moveRight(e, 'selectionEnd'); + + // increase selection by one if it's a newline + if (this.text.charAt(this.selectionEnd - 1) === '\n') { + this.selectionEnd++; + } + if (this.selectionEnd > this.text.length) { + this.selectionEnd = this.text.length; + } + } + }, + + /** + * Moves cursor right without keeping selection + * @param {Event} e + */ + moveCursorRightWithoutShift: function(e) { + this._selectionDirection = 'right'; + + if (this.selectionStart === this.selectionEnd) { + this._moveRight(e, 'selectionStart'); + this.selectionEnd = this.selectionStart; + } + else { + this.selectionEnd += this.getNumNewLinesInSelectedText(); + if (this.selectionEnd > this.text.length) { + this.selectionEnd = this.text.length; + } + this.selectionStart = this.selectionEnd; + } + }, + + /** + * Inserts a character where cursor is (replacing selection if one exists) + */ + removeChars: function(e) { + if (this.selectionStart === this.selectionEnd) { + this._removeCharsNearCursor(e); + } + else { + this._removeCharsFromTo(this.selectionStart, this.selectionEnd); + } + + this.selectionEnd = this.selectionStart; + + this._removeExtraneousStyles(); + + if (this.canvas) { + // TODO: double renderAll gets rid of text box shift happenning sometimes + // need to find out what exactly causes it and fix it + this.canvas.renderAll().renderAll(); + } + + this.setCoords(); + this.fire('changed'); + this.canvas && this.canvas.fire('text:changed', { target: this }); + }, + + /** + * @private + */ + _removeCharsNearCursor: function(e) { + if (this.selectionStart !== 0) { + + if (e.metaKey) { + // remove all till the start of current line + var leftLineBoundary = this.findLineBoundaryLeft(this.selectionStart); + + this._removeCharsFromTo(leftLineBoundary, this.selectionStart); + this.selectionStart = leftLineBoundary; + } + else if (e.altKey) { + // remove all till the start of current word + var leftWordBoundary = this.findWordBoundaryLeft(this.selectionStart); + + this._removeCharsFromTo(leftWordBoundary, this.selectionStart); + this.selectionStart = leftWordBoundary; + } + else { + var isBeginningOfLine = this.text.slice(this.selectionStart - 1, this.selectionStart) === '\n'; + this.removeStyleObject(isBeginningOfLine); + + this.selectionStart--; + this.text = this.text.slice(0, this.selectionStart) + + this.text.slice(this.selectionStart + 1); + } + } + } +}); + + +/* _TO_SVG_START_ */ +fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + + /** + * @private + */ + _setSVGTextLineText: function(textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects) { + if (!this.styles[lineIndex]) { + this.callSuper('_setSVGTextLineText', + textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier); + } + else { + this._setSVGTextLineChars( + textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects); + } + }, + + /** + * @private + */ + _setSVGTextLineChars: function(textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects) { + + var yProp = lineIndex === 0 || this.useNative ? 'y' : 'dy', + chars = textLine.split(''), + charOffset = 0, + lineLeftOffset = this._getSVGLineLeftOffset(lineIndex), + lineTopOffset = this._getSVGLineTopOffset(lineIndex), + heightOfLine = this._getHeightOfLine(this.ctx, lineIndex); + + for (var i = 0, len = chars.length; i < len; i++) { + var styleDecl = this.styles[lineIndex][i] || { }; + + textSpans.push( + this._createTextCharSpan( + chars[i], styleDecl, lineLeftOffset, lineTopOffset, yProp, charOffset)); + + var charWidth = this._getWidthOfChar(this.ctx, chars[i], lineIndex, i); + + if (styleDecl.textBackgroundColor) { + textBgRects.push( + this._createTextCharBg( + styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset)); + } + + charOffset += charWidth; + } + }, + + /** + * @private + */ + _getSVGLineLeftOffset: function(lineIndex) { + return (this._boundaries && this._boundaries[lineIndex]) + ? fabric.util.toFixed(this._boundaries[lineIndex].left, 2) + : 0; + }, + + /** + * @private + */ + _getSVGLineTopOffset: function(lineIndex) { + var lineTopOffset = 0; + for (var j = 0; j <= lineIndex; j++) { + lineTopOffset += this._getHeightOfLine(this.ctx, j); + } + return lineTopOffset - this.height / 2; + }, + + /** + * @private + */ + _createTextCharBg: function(styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset) { + return [ + '' + ].join(''); + }, + + /** + * @private + */ + _createTextCharSpan: function(_char, styleDecl, lineLeftOffset, lineTopOffset, yProp, charOffset) { + + var fillStyles = this.getSvgStyles.call(fabric.util.object.extend({ + visible: true, + fill: this.fill, + stroke: this.stroke, + type: 'text' + }, styleDecl)); + + return [ + '', + + fabric.util.string.escapeXml(_char), + '' + ].join(''); + } +}); +/* _TO_SVG_END_ */ + + +(function() { + + if (typeof document !== 'undefined' && typeof window !== 'undefined') { + return; + } + + var DOMParser = require('xmldom').DOMParser, + URL = require('url'), + HTTP = require('http'), + HTTPS = require('https'), + + Canvas = require('canvas'), + Image = require('canvas').Image; + + /** @private */ + function request(url, encoding, callback) { + var oURL = URL.parse(url); + + // detect if http or https is used + if ( !oURL.port ) { + oURL.port = ( oURL.protocol.indexOf('https:') === 0 ) ? 443 : 80; + } + + // assign request handler based on protocol + var reqHandler = ( oURL.port === 443 ) ? HTTPS : HTTP, + req = reqHandler.request({ + hostname: oURL.hostname, + port: oURL.port, + path: oURL.path, + method: 'GET' + }, function(response) { + var body = ''; + if (encoding) { + response.setEncoding(encoding); + } + response.on('end', function () { + callback(body); + }); + response.on('data', function (chunk) { + if (response.statusCode === 200) { + body += chunk; + } + }); + }); + + req.on('error', function(err) { + if (err.errno === process.ECONNREFUSED) { + fabric.log('ECONNREFUSED: connection refused to ' + oURL.hostname + ':' + oURL.port); + } + else { + fabric.log(err.message); + } + }); + + req.end(); + } + + /** @private */ + function requestFs(path, callback){ + var fs = require('fs'); + fs.readFile(path, function (err, data) { + if (err) { + fabric.log(err); + throw err; + } + else { + callback(data); + } + }); + } + + fabric.util.loadImage = function(url, callback, context) { + function createImageAndCallBack(data) { + img.src = new Buffer(data, 'binary'); + // preserving original url, which seems to be lost in node-canvas + img._src = url; + callback && callback.call(context, img); + } + var img = new Image(); + if (url && (url instanceof Buffer || url.indexOf('data') === 0)) { + img.src = img._src = url; + callback && callback.call(context, img); + } + else if (url && url.indexOf('http') !== 0) { + requestFs(url, createImageAndCallBack); + } + else if (url) { + request(url, 'binary', createImageAndCallBack); + } + else { + callback && callback.call(context, url); + } + }; + + fabric.loadSVGFromURL = function(url, callback, reviver) { + url = url.replace(/^\n\s*/, '').replace(/\?.*$/, '').trim(); + if (url.indexOf('http') !== 0) { + requestFs(url, function(body) { + fabric.loadSVGFromString(body.toString(), callback, reviver); + }); + } + else { + request(url, '', function(body) { + fabric.loadSVGFromString(body, callback, reviver); + }); + } + }; + + fabric.loadSVGFromString = function(string, callback, reviver) { + var doc = new DOMParser().parseFromString(string); + fabric.parseSVGDocument(doc.documentElement, function(results, options) { + callback && callback(results, options); + }, reviver); + }; + + fabric.util.getScript = function(url, callback) { + request(url, '', function(body) { + eval(body); + callback && callback(); + }); + }; + + fabric.Image.fromObject = function(object, callback) { + fabric.util.loadImage(object.src, function(img) { + var oImg = new fabric.Image(img); + + oImg._initConfig(object); + oImg._initFilters(object, function(filters) { + oImg.filters = filters || [ ]; + callback && callback(oImg); + }); + }); + }; + + /** + * Only available when running fabric on node.js + * @param width Canvas width + * @param height Canvas height + * @param {Object} options to pass to FabricCanvas. + * @param {Object} options to pass to NodeCanvas. + * @return {Object} wrapped canvas instance + */ + fabric.createCanvasForNode = function(width, height, options, nodeCanvasOptions) { + nodeCanvasOptions = nodeCanvasOptions || options; + + var canvasEl = fabric.document.createElement('canvas'), + nodeCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions); + + // jsdom doesn't create style on canvas element, so here be temp. workaround + canvasEl.style = { }; + + canvasEl.width = nodeCanvas.width; + canvasEl.height = nodeCanvas.height; + + var FabricCanvas = fabric.Canvas || fabric.StaticCanvas, + fabricCanvas = new FabricCanvas(canvasEl, options); + + fabricCanvas.contextContainer = nodeCanvas.getContext('2d'); + fabricCanvas.nodeCanvas = nodeCanvas; + fabricCanvas.Font = Canvas.Font; + + return fabricCanvas; + }; + + /** @ignore */ + fabric.StaticCanvas.prototype.createPNGStream = function() { + return this.nodeCanvas.createPNGStream(); + }; + + fabric.StaticCanvas.prototype.createJPEGStream = function(opts) { + return this.nodeCanvas.createJPEGStream(opts); + }; + + var origSetWidth = fabric.StaticCanvas.prototype.setWidth; + fabric.StaticCanvas.prototype.setWidth = function(width) { + origSetWidth.call(this, width); + this.nodeCanvas.width = width; + return this; + }; + if (fabric.Canvas) { + fabric.Canvas.prototype.setWidth = fabric.StaticCanvas.prototype.setWidth; + } + + var origSetHeight = fabric.StaticCanvas.prototype.setHeight; + fabric.StaticCanvas.prototype.setHeight = function(height) { + origSetHeight.call(this, height); + this.nodeCanvas.height = height; + return this; + }; + if (fabric.Canvas) { + fabric.Canvas.prototype.setHeight = fabric.StaticCanvas.prototype.setHeight; + } + +})(); + diff --git a/js/fabric-v1.4.8.min.js b/js/fabric-v1.4.8.min.js new file mode 100644 index 00000000..435595b4 --- /dev/null +++ b/js/fabric-v1.4.8.min.js @@ -0,0 +1,7 @@ +/* build: `node build.js modules=ALL exclude=gestures,cufon,json minifier=uglifyjs` *//*! Fabric.js Copyright 2008-2014, Printio (Juriy Zaytsev, Maxim Chernyak) */var fabric=fabric||{version:"1.4.8"};typeof exports!="undefined"&&(exports.fabric=fabric),typeof document!="undefined"&&typeof window!="undefined"?(fabric.document=document,fabric.window=window):(fabric.document=require("jsdom").jsdom(""),fabric.window=fabric.document.createWindow()),fabric.isTouchSupported="ontouchstart"in fabric.document.documentElement,fabric.isLikelyNode=typeof Buffer!="undefined"&&typeof window=="undefined",fabric.SHARED_ATTRIBUTES=["display","transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width"],function(){function e(e,t){if(!this.__eventListeners[e])return;t?fabric.util.removeFromArray(this.__eventListeners[e],t):this.__eventListeners[e].length=0}function t(e,t){this.__eventListeners||(this.__eventListeners={});if(arguments.length===1)for(var n in e)this.on(n,e[n]);else this.__eventListeners[e]||(this.__eventListeners[e]=[]),this.__eventListeners[e].push(t);return this}function n(t,n){if(!this.__eventListeners)return;if(arguments.length===0)this.__eventListeners={};else if(arguments.length===1&&typeof arguments[0]=="object")for(var r in t)e.call(this,r,t[r]);else e.call(this,t,n);return this}function r(e,t){if(!this.__eventListeners)return;var n=this.__eventListeners[e];if(!n)return;for(var r=0,i=n.length;r-1},complexity:function(){return this.getObjects().reduce(function(e,t){return e+=t.complexity?t.complexity():0,e},0)}},function(e){var t=Math.sqrt,n=Math.atan2,r=Math.PI/180;fabric.util={removeFromArray:function(e,t){var n=e.indexOf(t);return n!==-1&&e.splice(n,1),e},getRandomInt:function(e,t){return Math.floor(Math.random()*(t-e+1))+e},degreesToRadians:function(e){return e*r},radiansToDegrees:function(e){return e/r},rotatePoint:function(e,t,n){var r=Math.sin(n),i=Math.cos(n);e.subtractEquals(t);var s=e.x*i-e.y*r,o=e.x*r+e.y*i;return(new fabric.Point(s,o)).addEquals(t)},transformPoint:function(e,t,n){return n?new fabric.Point(t[0]*e.x+t[1]*e.y,t[2]*e.x+t[3]*e.y):new fabric.Point(t[0]*e.x+t[1]*e.y+t[4],t[2]*e.x+t[3]*e.y+t[5])},invertTransform:function(e){var t=e.slice(),n=1/(e[0]*e[3]-e[1]*e[2]);t=[n*e[3],-n*e[1],-n*e[2],n*e[0],0,0];var r=fabric.util.transformPoint({x:e[4],y:e[5]},t);return t[4]=-r.x,t[5]=-r.y,t},toFixed:function(e,t){return parseFloat(Number(e).toFixed(t))},falseFunction:function(){return!1},getKlass:function(e,t){return e=fabric.util.string.camelize(e.charAt(0).toUpperCase()+e.slice(1)),fabric.util.resolveNamespace(t)[e]},resolveNamespace:function(t){if(!t)return fabric;var n=t.split("."),r=n.length,i=e||fabric.window;for(var s=0;s1?r=new fabric.PathGroup(e,t):r=e[0],typeof n!="undefined"&&r.setSourcePath(n),r},populateWithProperties:function(e,t,n){if(n&&Object.prototype.toString.call(n)==="[object Array]")for(var r=0,i=n.length;rr)r+=u[p++%h],r>l&&(r=l),e[d?"lineTo":"moveTo"](r,0),d=!d;e.restore()},createCanvasElement:function(e){return e||(e=fabric.document.createElement("canvas")),!e.getContext&&typeof G_vmlCanvasManager!="undefined"&&G_vmlCanvasManager.initElement(e),e},createImage:function(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")},createAccessors:function(e){var t=e.prototype;for(var n=t.stateProperties.length;n--;){var r=t.stateProperties[n],i=r.charAt(0).toUpperCase()+r.slice(1),s="set"+i,o="get"+i;t[o]||(t[o]=function(e){return new Function('return this.get("'+e+'")')}(r)),t[s]||(t[s]=function(e){return new Function("value",'return this.set("'+e+'", value)')}(r))}},clipContext:function(e,t){t.save(),t.beginPath(),e.clipTo(t),t.clip()},multiplyTransformMatrices:function(e,t){var n=[[e[0],e[2],e[4]],[e[1],e[3],e[5]],[0,0,1]],r=[[t[0],t[2],t[4]],[t[1],t[3],t[5]],[0,0,1]],i=[];for(var s=0;s<3;s++){i[s]=[];for(var o=0;o<3;o++){var u=0;for(var a=0;a<3;a++)u+=n[s][a]*r[a][o];i[s][o]=u}}return[i[0][0],i[1][0],i[0][1],i[1][1],i[0][2],i[1][2]]},getFunctionBody:function(e){return(String(e).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},normalizePoints:function(e,t){var n=fabric.util.array.min(e,"x"),r=fabric.util.array.min(e,"y");n=n<0?n:0,r=n<0?r:0;for(var i=0,s=e.length;i0&&(t>r?t-=r:t=0,n>r?n-=r:n=0);var i=!0,s=e.getImageData(t,n,r*2||1,r*2||1);for(var o=3,u=s.data.length;o0&&f===0&&(E-=2*Math.PI);var S=Math.ceil(Math.abs(E/(Math.PI*.5+.001))),x=[];for(var T=0;T1&&(h=Math.sqrt(h),t*=h,n*=h);var p=f/t,d=a/t,v=-a/n,m=f/n;return{x0:p*r+d*i,y0:v*r+m*i,x1:p*s+d*o,y1:v*s+m*o,sinTh:a,cosTh:f}}function o(e,i,s,o,u,a,f,l){r=n.call(arguments);if(t[r])return t[r];var c=Math.sin(s),h=Math.cos(s),p=Math.sin(o),d=Math.cos(o),v=l*u,m=-f*a,g=f*u,y=l*a,b=.25*(o-s),w=8/3*Math.sin(b)*Math.sin(b)/Math.sin(b*2),E=e+h-w*c,S=i+c+w*h,x=e+d,T=i+p,N=x+w*p,C=T-w*d;return t[r]=[v*E+m*S,g*E+y*S,v*N+m*C,g*N+y*C,v*x+m*T,g*x+y*T],t[r]}var e={},t={},n=Array.prototype.join,r;fabric.util.drawArc=function(e,t,n,r){var s=r[0],u=r[1],a=r[2],f=r[3],l=r[4],c=r[5],h=r[6],p=i(c,h,s,u,f,l,a,t,n);for(var d=0;d=t})}function r(e,t){return i(e,t,function(e,t){return e>>0;if(n===0)return-1;var r=0;arguments.length>0&&(r=Number(arguments[1]),r!==r?r=0:r!==0&&r!==Number.POSITIVE_INFINITY&&r!==Number.NEGATIVE_INFINITY&&(r=(r>0||-1)*Math.floor(Math.abs(r))));if(r>=n)return-1;var i=r>=0?r:Math.max(n-Math.abs(r),0);for(;i>>0;n>>0;r>>0;n>>0;n>>0;i>>0,n=0,r;if(arguments.length>1)r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n/g,">")}String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^[\s\xA0]+/,"").replace(/[\s\xA0]+$/,"")}),fabric.util.string={camelize:e,capitalize:t,escapeXml:n}}(),function(){var e=Array.prototype.slice,t=Function.prototype.apply,n=function(){};Function.prototype.bind||(Function.prototype.bind=function(r){var i=this,s=e.call(arguments,1),o;return s.length?o=function(){return t.call(i,this instanceof n?this:r,s.concat(e.call(arguments)))}:o=function(){return t.call(i,this instanceof n?this:r,arguments)},n.prototype=this.prototype,o.prototype=new n,o})}(),function(){function i(){}function s(t){var n=this.constructor.superclass.prototype[t];return arguments.length>1?n.apply(this,e.call(arguments,1)):n.call(this)}function o(){function u(){this.initialize.apply(this,arguments)}var n=null,o=e.call(arguments,0);typeof o[0]=="function"&&(n=o.shift()),u.superclass=n,u.subclasses=[],n&&(i.prototype=n.prototype,u.prototype=new i,n.subclasses.push(u));for(var a=0,f=o.length;a-1?e.prototype[i]=function(e){return function(){var n=this.constructor.superclass;this.constructor.superclass=r;var i=t[e].apply(this,arguments);this.constructor.superclass=n;if(e!=="initialize")return i}}(i):e.prototype[i]=t[i],n&&(t.toString!==Object.prototype.toString&&(e.prototype.toString=t.toString),t.valueOf!==Object.prototype.valueOf&&(e.prototype.valueOf=t.valueOf))};fabric.util.createClass=o}(),function(){function t(e){var t=Array.prototype.slice.call(arguments,1),n,r,i=t.length;for(r=0;r-1?s(e,t.match(/opacity:\s*(\d?\.?\d*)/)[1]):e;for(var r in t)if(r==="opacity")s(e,t[r]);else{var i=r==="float"||r==="cssFloat"?typeof n.styleFloat=="undefined"?"cssFloat":"styleFloat":r;n[i]=t[r]}return e}var t=fabric.document.createElement("div"),n=typeof t.style.opacity=="string",r=typeof t.style.filter=="string",i=/alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,s=function(e){return e};n?s=function(e,t){return e.style.opacity=t,e}:r&&(s=function(e,t){var n=e.style;return e.currentStyle&&!e.currentStyle.hasLayout&&(n.zoom=1),i.test(n.filter)?(t=t>=.9999?"":"alpha(opacity="+t*100+")",n.filter=n.filter.replace(i,t)):n.filter+=" alpha(opacity="+t*100+")",e}),fabric.util.setStyle=e}(),function(){function t(e){return typeof e=="string"?fabric.document.getElementById(e):e}function s(e,t){var n=fabric.document.createElement(e);for(var r in t)r==="class"?n.className=t[r]:r==="for"?n.htmlFor=t[r]:n.setAttribute(r,t[r]);return n}function o(e,t){e&&(" "+e.className+" ").indexOf(" "+t+" ")===-1&&(e.className+=(e.className?" ":"")+t)}function u(e,t,n){return typeof t=="string"&&(t=s(t,n)),e.parentNode&&e.parentNode.replaceChild(t,e),t.appendChild(e),t}function a(e,t){var n,r,i=0,s=0,o=fabric.document.documentElement,u=fabric.document.body||{scrollLeft:0,scrollTop:0};r=e;while(e&&e.parentNode&&!n)e=e.parentNode,e!==fabric.document&&fabric.util.getElementStyle(e,"position")==="fixed"&&(n=e),e!==fabric.document&&r!==t&&fabric.util.getElementStyle(e,"position")==="absolute"?(i=0,s=0):e===fabric.document?(i=u.scrollLeft||o.scrollLeft||0,s=u.scrollTop||o.scrollTop||0):(i+=e.scrollLeft||0,s+=e.scrollTop||0);return{left:i,top:s}}function f(e){var t,n=e&&e.ownerDocument,r={left:0,top:0},i={left:0,top:0},s,o={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!n)return{left:0,top:0};for(var u in o)i[o[u]]+=parseInt(l(e,u),10)||0;return t=n.documentElement,typeof e.getBoundingClientRect!="undefined"&&(r=e.getBoundingClientRect()),s=fabric.util.getScrollLeftTop(e,null),{left:r.left+s.left-(t.clientLeft||0)+i.left,top:r.top+s.top-(t.clientTop||0)+i.top}}var e=Array.prototype.slice,n,r=function(t){return e.call(t,0)};try{n=r(fabric.document.childNodes)instanceof Array}catch(i){}n||(r=function(e){var t=new Array(e.length),n=e.length;while(n--)t[n]=e[n];return t});var l;fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle?l=function(e,t){return fabric.document.defaultView.getComputedStyle(e,null)[t]}:l=function(e,t){var n=e.style[t];return!n&&e.currentStyle&&(n=e.currentStyle[t]),n},function(){function n(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=fabric.util.falseFunction),t?e.style[t]="none":typeof e.unselectable=="string"&&(e.unselectable="on"),e}function r(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=null),t?e.style[t]="":typeof e.unselectable=="string"&&(e.unselectable=""),e}var e=fabric.document.documentElement.style,t="userSelect"in e?"userSelect":"MozUserSelect"in e?"MozUserSelect":"WebkitUserSelect"in e?"WebkitUserSelect":"KhtmlUserSelect"in e?"KhtmlUserSelect":"";fabric.util.makeElementUnselectable=n,fabric.util.makeElementSelectable=r}(),function(){function e(e,t){var n=fabric.document.getElementsByTagName("head")[0],r=fabric.document.createElement("script"),i=!0;r.onload=r.onreadystatechange=function(e){if(i){if(typeof this.readyState=="string"&&this.readyState!=="loaded"&&this.readyState!=="complete")return;i=!1,t(e||fabric.window.event),r=r.onload=r.onreadystatechange=null}},r.src=e,n.appendChild(r)}fabric.util.getScript=e}(),fabric.util.getById=t,fabric.util.toArray=r,fabric.util.makeElement=s,fabric.util.addClass=o,fabric.util.wrapElement=u,fabric.util.getScrollLeftTop=a,fabric.util.getElementOffset=f,fabric.util.getElementStyle=l}(),function(){function e(e,t){return e+(/\?/.test(e)?"&":"?")+t}function n(){}function r(r,i){i||(i={});var s=i.method?i.method.toUpperCase():"GET",o=i.onComplete||function(){},u=t(),a;return u.onreadystatechange=function(){u.readyState===4&&(o(u),u.onreadystatechange=n)},s==="GET"&&(a=null,typeof i.parameters=="string"&&(r=e(r,i.parameters))),u.open(s,r,!0),(s==="POST"||s==="PUT")&&u.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),u.send(a),u}var t=function(){var e=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0")},function(){return new XMLHttpRequest}];for(var t=e.length;t--;)try{var n=e[t]();if(n)return e[t]}catch(r){}}();fabric.util.request=r}(),fabric.log=function(){},fabric.warn=function(){},typeof console!="undefined"&&["log","warn"].forEach(function(e){typeof console[e]!="undefined"&&console[e].apply&&(fabric[e]=function(){return console[e].apply(console,arguments)})}),function(){function e(e){n(function(t){e||(e={});var r=t||+(new Date),i=e.duration||500,s=r+i,o,u=e.onChange||function(){},a=e.abort||function(){return!1},f=e.easing||function(e,t,n,r){return-n*Math.cos(e/r*(Math.PI/2))+n+t},l="startValue"in e?e.startValue:0,c="endValue"in e?e.endValue:100,h=e.byValue||c-l;e.onStart&&e.onStart(),function p(t){o=t||+(new Date);var c=o>s?i:o-r;if(a()){e.onComplete&&e.onComplete();return}u(f(c,l,h,i));if(o>s){e.onComplete&&e.onComplete();return}n(p)}(r)})}function n(){return t.apply(fabric.window,arguments)}var t=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(e){fabric.window.setTimeout(e,1e3/60)};fabric.util.animate=e,fabric.util.requestAnimFrame=n}(),function(){function e(e,t,n,r){return e','')}var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.string.capitalize,i=t.util.object.clone,s=t.util.toFixed,o=t.util.multiplyTransformMatrices,u={cx:"left",x:"left",r:"radius",cy:"top",y:"top",display:"visible",visibility:"visible",transform:"transformMatrix","fill-opacity":"fillOpacity","fill-rule":"fillRule","font-family":"fontFamily","font-size":"fontSize","font-style":"fontStyle","font-weight":"fontWeight","stroke-dasharray":"strokeDashArray","stroke-linecap":"strokeLineCap","stroke-linejoin":"strokeLineJoin","stroke-miterlimit":"strokeMiterLimit","stroke-opacity":"strokeOpacity","stroke-width":"strokeWidth","text-decoration":"textDecoration","text-anchor":"originX"},a={stroke:"strokeOpacity",fill:"fillOpacity"};t.parseTransformAttribute=function(){function e(e,t){var n=t[0];e[0]=Math.cos(n),e[1]=Math.sin(n),e[2]=-Math.sin(n),e[3]=Math.cos(n)}function n(e,t){var n=t[0],r=t.length===2?t[1]:t[0];e[0]=n,e[3]=r}function r(e,t){e[2]=t[0]}function i(e,t){e[1]=t[0]}function s(e,t){e[4]=t[0],t.length===2&&(e[5]=t[1])}var o=[1,0,0,1,0,0],u="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",a="(?:\\s+,?\\s*|,\\s*)",f="(?:(skewX)\\s*\\(\\s*("+u+")\\s*\\))",l="(?:(skewY)\\s*\\(\\s*("+u+")\\s*\\))",c="(?:(rotate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+")"+a+"("+u+"))?\\s*\\))",h="(?:(scale)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",p="(?:(translate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",d="(?:(matrix)\\s*\\(\\s*("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+"\\s*\\))",v="(?:"+d+"|"+p+"|"+h+"|"+c+"|"+f+"|"+l+")",m="(?:"+v+"(?:"+a+v+")*"+")",g="^\\s*(?:"+m+"?)\\s*$",y=new RegExp(g),b=new RegExp(v,"g");return function(u){var a=o.concat(),f=[];if(!u||u&&!y.test(u))return a;u.replace(b,function(u){var l=(new RegExp(v)).exec(u).filter(function(e){return e!==""&&e!=null}),c=l[1],h=l.slice(2).map(parseFloat);switch(c){case"translate":s(a,h);break;case"rotate":h[0]=t.util.degreesToRadians(h[0]),e(a,h);break;case"scale":n(a,h);break;case"skewX":r(a,h);break;case"skewY":i(a,h);break;case"matrix":a=h}f.push(a.concat()),a=o.concat()});var l=f[0];while(f.length>1)f.shift(),l=t.util.multiplyTransformMatrices(l,f[0]);return l}}(),t.parseSVGDocument=function(){function s(e,t){while(e&&(e=e.parentNode))if(t.test(e.nodeName))return!0;return!1}var e=/^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/,n="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",r=new RegExp("^\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*"+"$");return function(n,o,u){if(!n)return;var a=new Date;m(n);var f=t.util.toArray(n.getElementsByTagName("*"));if(f.length===0&&t.isLikelyNode){f=n.selectNodes('//*[name(.)!="svg"]');var l=[];for(var c=0,h=f.length;c-1;e=e.split(/\s+/);var n=[],r,i;if(t){r=0,i=e.length;for(;r/i,"")));if(!s||!s.documentElement)return;t.parseSVGDocument(s.documentElement,function(r,i){g.set(e,{objects:t.util.array.invoke(r,"toObject"),options:i}),n(r,i)},r)}e=e.replace(/^\n\s*/,"").trim(),g.has(e,function(r){r?g.get(e,function(e){var t=y(e);n(t.objects,t.options)}):new t.util.request(e,{method:"get",onComplete:i})})},loadSVGFromString:function(e,n,r){e=e.trim();var i;if(typeof DOMParser!="undefined"){var s=new DOMParser;s&&s.parseFromString&&(i=s.parseFromString(e,"text/xml"))}else t.window.ActiveXObject&&(i=new ActiveXObject("Microsoft.XMLDOM"),i.async="false",i.loadXML(e.replace(//i,"")));t.parseSVGDocument(i.documentElement,function(e,t){n(e,t)},r)},createSVGFontFacesMarkup:function(e){var t="";for(var n=0,r=e.length;n',"",""].join("")),t},createSVGRefElementsMarkup +:function(e){var t=[];return b(t,e,"backgroundColor"),b(t,e,"overlayColor"),t.join("")}})}(typeof exports!="undefined"?exports:this),fabric.ElementsParser=function(e,t,n,r){this.elements=e,this.callback=t,this.options=n,this.reviver=r},fabric.ElementsParser.prototype.parse=function(){this.instances=new Array(this.elements.length),this.numElements=this.elements.length,this.createObjects()},fabric.ElementsParser.prototype.createObjects=function(){for(var e=0,t=this.elements.length;ee.x&&this.y>e.y},gte:function(e){return this.x>=e.x&&this.y>=e.y},lerp:function(e,t){return new n(this.x+(e.x-this.x)*t,this.y+(e.y-this.y)*t)},distanceFrom:function(e){var t=this.x-e.x,n=this.y-e.y;return Math.sqrt(t*t+n*n)},midPointFrom:function(e){return new n(this.x+(e.x-this.x)/2,this.y+(e.y-this.y)/2)},min:function(e){return new n(Math.min(this.x,e.x),Math.min(this.y,e.y))},max:function(e){return new n(Math.max(this.x,e.x),Math.max(this.y,e.y))},toString:function(){return this.x+","+this.y},setXY:function(e,t){this.x=e,this.y=t},setFromPoint:function(e){this.x=e.x,this.y=e.y},swap:function(e){var t=this.x,n=this.y;this.x=e.x,this.y=e.y,e.x=t,e.y=n}}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function n(e){this.status=e,this.points=[]}var t=e.fabric||(e.fabric={});if(t.Intersection){t.warn("fabric.Intersection is already defined");return}t.Intersection=n,t.Intersection.prototype={appendPoint:function(e){this.points.push(e)},appendPoints:function(e){this.points=this.points.concat(e)}},t.Intersection.intersectLineLine=function(e,r,i,s){var o,u=(s.x-i.x)*(e.y-i.y)-(s.y-i.y)*(e.x-i.x),a=(r.x-e.x)*(e.y-i.y)-(r.y-e.y)*(e.x-i.x),f=(s.y-i.y)*(r.x-e.x)-(s.x-i.x)*(r.y-e.y);if(f!==0){var l=u/f,c=a/f;0<=l&&l<=1&&0<=c&&c<=1?(o=new n("Intersection"),o.points.push(new t.Point(e.x+l*(r.x-e.x),e.y+l*(r.y-e.y)))):o=new n}else u===0||a===0?o=new n("Coincident"):o=new n("Parallel");return o},t.Intersection.intersectLinePolygon=function(e,t,r){var i=new n,s=r.length;for(var o=0;o0&&(i.status="Intersection"),i},t.Intersection.intersectPolygonPolygon=function(e,t){var r=new n,i=e.length;for(var s=0;s0&&(r.status="Intersection"),r},t.Intersection.intersectPolygonRectangle=function(e,r,i){var s=r.min(i),o=r.max(i),u=new t.Point(o.x,s.y),a=new t.Point(s.x,o.y),f=n.intersectLinePolygon(s,u,e),l=n.intersectLinePolygon(u,o,e),c=n.intersectLinePolygon(o,a,e),h=n.intersectLinePolygon(a,s,e),p=new n;return p.appendPoints(f.points),p.appendPoints(l.points),p.appendPoints(c.points),p.appendPoints(h.points),p.points.length>0&&(p.status="Intersection"),p}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function n(e){e?this._tryParsingColor(e):this.setSource([0,0,0,1])}function r(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*6*n:n<.5?t:n<2/3?e+(t-e)*(2/3-n)*6:e}var t=e.fabric||(e.fabric={});if(t.Color){t.warn("fabric.Color is already defined.");return}t.Color=n,t.Color.prototype={_tryParsingColor:function(e){var t;e in n.colorNameMap&&(e=n.colorNameMap[e]);if(e==="transparent"){this.setSource([255,255,255,0]);return}t=n.sourceFromHex(e),t||(t=n.sourceFromRgb(e)),t||(t=n.sourceFromHsl(e)),t&&this.setSource(t)},_rgbToHsl:function(e,n,r){e/=255,n/=255,r/=255;var i,s,o,u=t.util.array.max([e,n,r]),a=t.util.array.min([e,n,r]);o=(u+a)/2;if(u===a)i=s=0;else{var f=u-a;s=o>.5?f/(2-u-a):f/(u+a);switch(u){case e:i=(n-r)/f+(n']:this.type==="radial"&&(r=["']);for(var i=0;i');return r.push(this.type==="linear"?"":""),r.join("")},toLive:function(e){var t;if(!this.type)return;this.type==="linear"?t=e.createLinearGradient(this.coords.x1,this.coords.y1,this.coords.x2,this.coords.y2):this.type==="radial"&&(t=e.createRadialGradient(this.coords.x1,this.coords.y1,this.coords.r1,this.coords.x2,this.coords.y2,this.coords.r2));for(var n=0,r=this.colorStops.length;n'+''+""},toLive:function(e){var t=typeof this.source=="function"?this.source():this.source;if(!t)return"";if(typeof t.src!="undefined"){if(!t.complete)return"";if(t.naturalWidth===0||t.naturalHeight===0)return""}return e.createPattern(t,this.repeat)}}),function(e){"use strict";var t=e.fabric||(e.fabric={});if(t.Shadow){t.warn("fabric.Shadow is already defined.");return}t.Shadow=t.util.createClass({color:"rgb(0,0,0)",blur:0,offsetX:0,offsetY:0,affectStroke:!1,includeDefaultValues:!0,initialize:function(e){typeof e=="string"&&(e=this._parseShadow(e));for(var n in e)this[n]=e[n];this.id=t.Object.__uid++},_parseShadow:function(e){var n=e.trim(),r=t.Shadow.reOffsetsAndBlur.exec(n)||[],i=n.replace(t.Shadow.reOffsetsAndBlur,"")||"rgb(0,0,0)";return{color:i.trim(),offsetX:parseInt(r[1],10)||0,offsetY:parseInt(r[2],10)||0,blur:parseInt(r[3],10)||0}},toString:function(){return[this.offsetX,this.offsetY,this.blur,this.color].join("px ")},toSVG:function(e){var t="SourceAlpha";return e&&(e.fill===this.color||e.stroke===this.color)&&(t="SourceGraphic"),''+''+''+""+""+''+""+""},toObject:function(){if(this.includeDefaultValues)return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY};var e={},n=t.Shadow.prototype;return this.color!==n.color&&(e.color=this.color),this.blur!==n.blur&&(e.blur=this.blur),this.offsetX!==n.offsetX&&(e.offsetX=this.offsetX),this.offsetY!==n.offsetY&&(e.offsetY=this.offsetY),e}}),t.Shadow.reOffsetsAndBlur=/(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/}(typeof exports!="undefined"?exports:this),function(){"use strict";if(fabric.StaticCanvas){fabric.warn("fabric.StaticCanvas is already defined.");return}var e=fabric.util.object.extend,t=fabric.util.getElementOffset,n=fabric.util.removeFromArray,r=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass({initialize:function(e,t){t||(t={}),this._initStatic(e,t),fabric.StaticCanvas.activeInstance=this},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:!0,stateful:!0,renderOnAddRemove:!0,clipTo:null,controlsAboveOverlay:!1,allowTouchScrolling:!1,imageSmoothingEnabled:!0,viewportTransform:[1,0,0,1,0,0],onBeforeScaleRotate:function(){},_initStatic:function(e,t){this._objects=[],this._createLowerCanvas(e),this._initOptions(t),this._setImageSmoothing(),t.overlayImage&&this.setOverlayImage(t.overlayImage,this.renderAll.bind(this)),t.backgroundImage&&this.setBackgroundImage(t.backgroundImage,this.renderAll.bind(this)),t.backgroundColor&&this.setBackgroundColor(t.backgroundColor,this.renderAll.bind(this)),t.overlayColor&&this.setOverlayColor(t.overlayColor,this.renderAll.bind(this)),this.calcOffset()},calcOffset:function(){return this._offset=t(this.lowerCanvasEl),this},setOverlayImage:function(e,t,n){return this.__setBgOverlayImage("overlayImage",e,t,n)},setBackgroundImage:function(e,t,n){return this.__setBgOverlayImage("backgroundImage",e,t,n)},setOverlayColor:function(e,t){return this.__setBgOverlayColor("overlayColor",e,t)},setBackgroundColor:function(e,t){return this.__setBgOverlayColor("backgroundColor",e,t)},_setImageSmoothing:function(){var e=this.getContext();e.imageSmoothingEnabled=this.imageSmoothingEnabled,e.webkitImageSmoothingEnabled=this.imageSmoothingEnabled,e.mozImageSmoothingEnabled=this.imageSmoothingEnabled,e.msImageSmoothingEnabled=this.imageSmoothingEnabled,e.oImageSmoothingEnabled=this.imageSmoothingEnabled},__setBgOverlayImage:function(e,t,n,r){return typeof t=="string"?fabric.util.loadImage(t,function(t){this[e]=new fabric.Image(t,r),n&&n()},this):(this[e]=t,n&&n()),this},__setBgOverlayColor:function(e,t,n){if(t&&t.source){var r=this;fabric.util.loadImage(t.source,function(i){r[e]=new fabric.Pattern({source:i,repeat:t.repeat,offsetX:t.offsetX,offsetY:t.offsetY}),n&&n()})}else this[e]=t,n&&n();return this},_createCanvasElement:function(){var e=fabric.document.createElement("canvas");e.style||(e.style={});if(!e)throw r;return this._initCanvasElement(e),e},_initCanvasElement:function(e){fabric.util.createCanvasElement(e);if(typeof e.getContext=="undefined")throw r},_initOptions:function(e){for(var t in e)this[t]=e[t];this.width=this.width||parseInt(this.lowerCanvasEl.width,10)||0,this.height=this.height||parseInt(this.lowerCanvasEl.height,10)||0;if(!this.lowerCanvasEl.style)return;this.lowerCanvasEl.width=this.width,this.lowerCanvasEl.height=this.height,this.lowerCanvasEl.style.width=this.width+"px",this.lowerCanvasEl.style.height=this.height+"px"},_createLowerCanvas:function(e){this.lowerCanvasEl=fabric.util.getById(e)||this._createCanvasElement(),this._initCanvasElement(this.lowerCanvasEl),fabric.util.addClass(this.lowerCanvasEl,"lower-canvas"),this.interactive&&this._applyCanvasStyle(this.lowerCanvasEl),this.contextContainer=this.lowerCanvasEl.getContext("2d")},getWidth:function(){return this.width},getHeight:function(){return this.height},setWidth:function(e){return this._setDimension("width",e)},setHeight:function(e){return this._setDimension("height",e)},setDimensions:function(e){for(var t in e)this._setDimension(t,e[t]);return this},_setDimension:function(e,t){return this.lowerCanvasEl[e]=t,this.lowerCanvasEl.style[e]=t+"px",this.upperCanvasEl&&(this.upperCanvasEl[e]=t,this.upperCanvasEl.style[e]=t+"px"),this.cacheCanvasEl&&(this.cacheCanvasEl[e]=t),this.wrapperEl&&(this.wrapperEl.style[e]=t+"px"),this[e]=t,this.calcOffset(),this.renderAll(),this},getZoom:function(){return Math.sqrt(this.viewportTransform[0]*this.viewportTransform[3])},setViewportTransform:function(e){this.viewportTransform=e,this.renderAll();for(var t=0,n=this._objects.length;t"),n.join("")},_setSVGPreamble:function(e,t){t.suppressPreamble||e.push('','\n')},_setSVGHeader:function(e,t){e.push("',"Created with Fabric.js ",fabric.version,"","",fabric.createSVGFontFacesMarkup(this.getObjects()),fabric.createSVGRefElementsMarkup(this),"")},_setSVGObjects:function(e,t){var n=this.getActiveGroup();n&&this.discardActiveGroup();for(var r=0,i=this.getObjects(),s=i.length;r
    "):this[t]&&t==="overlayColor"&&e.push('")},sendToBack:function(e){return n(this._objects,e),this._objects.unshift(e),this.renderAll&&this.renderAll()},bringToFront:function(e){return n(this._objects,e),this._objects.push(e),this.renderAll&&this.renderAll()},sendBackwards:function(e,t){var r=this._objects.indexOf(e);if(r!==0){var i=this._findNewLowerIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewLowerIndex:function(e,t,n){var r;if(n){r=t;for(var i=t-1;i>=0;--i){var s=e.intersectsWithObject(this._objects[i])||e.isContainedWithinObject(this._objects[i])||this._objects[i].isContainedWithinObject(e);if(s){r=i;break}}}else r=t-1;return r},bringForward:function(e,t){var r=this._objects.indexOf(e);if(r!==this._objects.length-1){var i=this._findNewUpperIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewUpperIndex:function(e,t,n){var r;if(n){r=t;for(var i=t+1;i"}}),e(fabric.StaticCanvas.prototype,fabric.Observable),e(fabric.StaticCanvas.prototype,fabric.Collection),e(fabric.StaticCanvas.prototype,fabric.DataURLExporter),e(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(e){var t=fabric.util.createCanvasElement();if(!t||!t.getContext)return null;var n=t.getContext("2d");if(!n)return null;switch(e){case"getImageData":return typeof n.getImageData!="undefined";case"setLineDash":return typeof n.setLineDash!="undefined";case"toDataURL":return typeof t.toDataURL!="undefined";case"toDataURLWithQuality":try{return t.toDataURL("image/jpeg",0),!0}catch(r){}return!1;default:return null}}}),fabric.StaticCanvas.prototype.toJSON=fabric.StaticCanvas.prototype.toObject}(),fabric.BaseBrush=fabric.util.createClass({color:"rgb(0, 0, 0)",width:1,shadow:null,strokeLineCap:"round",strokeLineJoin:"round",setShadow:function(e){return this.shadow=new fabric.Shadow(e),this},_setBrushStyles:function(){var e=this.canvas.contextTop;e.strokeStyle=this.color,e.lineWidth=this.width,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin},_setShadow:function(){if(!this.shadow)return;var e=this.canvas.contextTop;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_resetShadow:function(){var e=this.canvas.contextTop;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0}}),function(){var e=fabric.util.array.min,t=fabric.util.array.max;fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(e){this.canvas=e,this._points=[]},onMouseDown:function(e){this._prepareForDrawing(e),this._captureDrawingPath(e),this._render()},onMouseMove:function(e){this._captureDrawingPath(e),this.canvas.clearContext(this.canvas.contextTop),this._render()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(e){var t=new fabric.Point(e.x,e.y);this._reset(),this._addPoint(t),this.canvas.contextTop.moveTo(t.x,t.y)},_addPoint:function(e){this._points.push(e)},_reset:function(){this._points.length=0,this._setBrushStyles(),this._setShadow()},_captureDrawingPath:function(e){var t=new fabric.Point(e.x,e.y);this._addPoint(t)},_render:function(){var e=this.canvas.contextTop,t=this.canvas.viewportTransform;e.save(),e.transform(t[0],t[1],t[2],t[3],t[4],t[5]),e.beginPath();var n=this._points[0],r=this._points[1];this._points.length===2&&n.x===r.x&&n.y===r.y&&(n.x-=.5,r.x+=.5),e.moveTo(n.x,n.y);for(var i=1,s=this._points.length;in.padding?e.x<0?e.x+=n.padding:e.x-=n.padding:e.x=0,i(e.y)>n.padding?e.y<0?e.y+=n.padding:e.y-=n.padding:e.y=0},_rotateObject:function(e,t){var i=this._currentTransform;if(i.target.get("lockRotation"))return;var s=r(i.ey-i.top,i.ex-i.left),o=r(t-i.top,e-i.left),u=n(o-s+i.theta);u<0&&(u=360+u),i.target.angle=u},setCursor:function(e){this.upperCanvasEl.style.cursor=e},_resetObjectTransform:function(e){e.scaleX=1,e.scaleY=1,e.setAngle(0)},_drawSelection:function(){var e=this.contextTop,t=this._groupSelector,n=t.left,r=t.top,o=i(n),u=i(r);e.fillStyle=this.selectionColor,e.fillRect(t.ex-(n>0?0:-n),t.ey-(r>0?0:-r),o,u),e.lineWidth=this.selectionLineWidth,e.strokeStyle=this.selectionBorderColor;if(this.selectionDashArray.length>1){var a=t.ex+s-(n>0?0:o),f=t.ey+s-(r>0?0:u);e.beginPath(),fabric.util.drawDashedLine(e,a,f,a+o,f,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f+u-1,a+o,f+u-1,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f,a,f+u,this.selectionDashArray),fabric.util.drawDashedLine(e,a+o-1,f,a+o-1,f+u,this.selectionDashArray),e.closePath(),e.stroke()}else e.strokeRect(t.ex+s-(n>0?0:o),t.ey+s-(r>0?0:u),o,u)},_isLastRenderedObject:function(e){return this.controlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay.visible&&this.containsPoint(e,this.lastRenderedObjectWithControlsAboveOverlay)&&this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e,!0))},findTarget:function(e,t){if(this.skipTargetFind)return;if(this._isLastRenderedObject(e))return this.lastRenderedObjectWithControlsAboveOverlay;var n=this.getActiveGroup();if(n&&!t&&this.containsPoint(e,n))return n;var r=this._searchPossibleTargets(e);return this._fireOverOutEvents(r),r},_fireOverOutEvents:function(e){e?this._hoveredTarget!==e&&(this.fire("mouse:over",{target:e}),e.fire("mouseover"),this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget}),this._hoveredTarget.fire("mouseout")),this._hoveredTarget=e):this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget}),this._hoveredTarget.fire("mouseout"),this._hoveredTarget=null)},_checkTarget:function(e,t,n){if(t&&t.visible&&t.evented&&this.containsPoint(e,t)){if(!this.perPixelTargetFind&&!t.perPixelTargetFind||!!t.isEditing)return!0;var r=this.isTargetTransparent(t,n.x,n.y);if(!r)return!0}},_searchPossibleTargets:function(e){var t,n=this.getPointer(e,!0),r=this._objects.length;while(r--)if(this._checkTarget(e,this._objects[r],n)){this.relatedTarget=this._objects[r],t=this._objects[r];break}return t},getPointer:function(t,n,r){r||(r=this.upperCanvasEl);var i=e(t,r),s=r.getBoundingClientRect(),o;return i.x=i.x-this._offset.left,i.y=i.y-this._offset.top,n||(i=fabric.util.transformPoint(i,fabric.util.invertTransform(this.viewportTransform))),s.width===0||s.height===0?o={width:1,height:1}:o={width:r.width/s.width,height:r.height/s.height},{x:i.x*o.width,y:i.y*o.height}},_createUpperCanvas:function(){var e=this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/,"");this.upperCanvasEl=this._createCanvasElement(),fabric.util.addClass(this.upperCanvasEl,"upper-canvas "+e),this.wrapperEl.appendChild(this.upperCanvasEl),this._copyCanvasStyle(this.lowerCanvasEl,this.upperCanvasEl),this._applyCanvasStyle(this.upperCanvasEl),this.contextTop=this.upperCanvasEl.getContext("2d")},_createCacheCanvas:function(){this.cacheCanvasEl=this._createCanvasElement(),this.cacheCanvasEl.setAttribute("width",this.width),this.cacheCanvasEl.setAttribute("height",this.height),this.contextCache=this.cacheCanvasEl.getContext("2d")},_initWrapperElement:function(){this.wrapperEl=fabric.util.wrapElement(this.lowerCanvasEl,"div",{"class":this.containerClass}),fabric.util.setStyle(this.wrapperEl,{width:this.getWidth()+"px",height:this.getHeight()+"px",position:"relative"}),fabric.util.makeElementUnselectable(this.wrapperEl)},_applyCanvasStyle:function(e){var t=this.getWidth()||e.width,n=this.getHeight()||e.height;fabric.util.setStyle(e,{position:"absolute",width:t+"px",height:n+"px",left:0,top:0}),e.width=t,e.height=n,fabric.util.makeElementUnselectable(e)},_copyCanvasStyle:function(e,t){t.style.cssText=e.style.cssText},getSelectionContext:function(){return this.contextTop},getSelectionElement:function(){return this.upperCanvasEl},_setActiveObject:function(e){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=e,e.set("active",!0)},setActiveObject:function(e,t){return this._setActiveObject(e),this.renderAll(),this.fire("object:selected",{target:e,e:t}),e.fire("selected",{e:t}),this},getActiveObject:function(){return this._activeObject},_discardActiveObject:function(){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=null},discardActiveObject:function(e){return this._discardActiveObject(),this.renderAll(),this.fire("selection:cleared",{e:e}),this},_setActiveGroup:function(e){this._activeGroup=e,e&&e.set("active",!0)},setActiveGroup:function(e,t){return this._setActiveGroup(e),e&&(this.fire("object:selected",{target:e,e:t}),e.fire("selected",{e:t})),this},getActiveGroup:function(){return this._activeGroup},_discardActiveGroup:function(){var e=this.getActiveGroup();e&&e.destroy(),this.setActiveGroup(null)},discardActiveGroup:function(e){return this._discardActiveGroup(),this.fire("selection:cleared",{e:e}),this},deactivateAll:function(){var e=this.getObjects(),t=0,n=e.length;for(;t1&&(t=new fabric.Group(t.reverse(),{originX:"center",originY:"center",canvas:this}),t.addWithUpdate(),this.setActiveGroup(t,e),t.saveCoords(),this.fire("selection:created",{target:t}),this.renderAll())},_collectObjects:function(){var n=[],r,i=this._groupSelector.ex,s=this._groupSelector.ey,o=i+this._groupSelector.left,u=s+this._groupSelector.top,a=new fabric.Point(e(i,o),e(s,u)),f=new fabric.Point(t(i,o),t(s,u)),l=i===o&&s===u;for(var c=this._objects.length;c--;){r=this._objects[c];if(!r||!r.selectable||!r.visible)continue;if(r.intersectsWithRect(a,f)||r.isContainedWithinRect(a,f)||r.containsPoint(a)||r.containsPoint(f)){r.set("active",!0),n.push(r);if(l)break}}return n},_maybeGroupObjects:function(e){this.selection&&this._groupSelector&&this._groupSelectedObjects(e);var t=this.getActiveGroup();t&&(t.setObjectsCoords().setCoords(),t.isMoving=!1,this.setCursor(this.defaultCursor)),this._groupSelector=null,this._currentTransform=null}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{toDataURL:function(e){e||(e={});var t=e.format||"png",n=e.quality||1,r=e.multiplier||1,i={left:e.left,top:e.top,width:e.width,height:e.height};return r!==1?this.__toDataURLWithMultiplier(t,n,i,r):this.__toDataURL(t,n,i)},__toDataURL:function(e,t,n){this.renderAll(!0);var r=this.upperCanvasEl||this.lowerCanvasEl,i=this.__getCroppedCanvas(r,n);e==="jpg"&&(e="jpeg");var s=fabric.StaticCanvas.supports("toDataURLWithQuality")?(i||r).toDataURL("image/"+e,t):(i||r).toDataURL("image/"+e);return this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),i&&(i=null),s},__getCroppedCanvas:function(e,t){var n,r,i="left"in t||"top"in t||"width"in t||"height"in t;return i&&(n=fabric.util.createCanvasElement(),r=n.getContext("2d"),n.width=t.width||this.width,n.height=t.height||this.height,r.drawImage(e,-t.left||0,-t.top||0)),n},__toDataURLWithMultiplier:function(e,t,n,r){var i=this.getWidth(),s=this.getHeight(),o=i*r,u=s*r,a=this.getActiveObject(),f=this.getActiveGroup(),l=this.contextTop||this.contextContainer;r>1&&this.setWidth(o).setHeight(u),l.scale(r,r),n.left&&(n.left*=r),n.top&&(n.top*=r),n.width?n.width*=r:r<1&&(n.width=o),n.height?n.height*=r:r<1&&(n.height=u),f?this._tempRemoveBordersControlsFromGroup(f):a&&this.deactivateAll&&this.deactivateAll(),this.renderAll(!0);var c=this.__toDataURL(e,t,n);return this.width=i,this.height=s,l.scale(1/r,1/r),this.setWidth(i).setHeight(s),f?this._restoreBordersControlsOnGroup(f):a&&this.setActiveObject&&this.setActiveObject(a),this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),c},toDataURLWithMultiplier:function(e,t,n){return this.toDataURL({format:e,multiplier:t,quality:n})},_tempRemoveBordersControlsFromGroup:function(e){e.origHasControls=e.hasControls,e.origBorderColor=e.borderColor,e.hasControls=!0,e.borderColor="rgba(0,0,0,0)",e.forEachObject(function(e){e.origBorderColor=e.borderColor,e.borderColor="rgba(0,0,0,0)"})},_restoreBordersControlsOnGroup:function(e){e.hideControls=e.origHideControls,e.borderColor=e.origBorderColor,e.forEachObject(function(e){e.borderColor=e.origBorderColor,delete e.origBorderColor})}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{loadFromDatalessJSON:function(e,t,n){return this.loadFromJSON(e,t,n)},loadFromJSON:function(e,t,n){if(!e)return;var r=typeof e=="string"?JSON.parse(e):e;this.clear();var i=this;return this._enlivenObjects(r.objects,function(){i._setBgOverlay(r,t)},n),this},_setBgOverlay:function(e,t){var n=this,r={backgroundColor:!1,overlayColor:!1,backgroundImage:!1,overlayImage:!1};if(!e.backgroundImage&&!e.overlayImage&&!e.background&&!e.overlay){t&&t();return}var i=function(){r.backgroundImage&&r.overlayImage&&r.backgroundColor&&r.overlayColor&&(n.renderAll(),t&&t())};this.__setBgOverlay("backgroundImage",e.backgroundImage,r,i),this.__setBgOverlay("overlayImage",e.overlayImage,r,i),this.__setBgOverlay("backgroundColor",e.background,r,i),this.__setBgOverlay("overlayColor",e.overlay,r,i),i()},__setBgOverlay:function(e,t,n,r){var i=this;if(!t){n[e]=!0;return}e==="backgroundImage"||e==="overlayImage"?fabric.Image.fromObject(t,function(t){i[e]=t,n[e]=!0,r&&r()}):this["set"+fabric.util.string.capitalize(e,!0)](t,function(){n[e]=!0,r&&r()})},_enlivenObjects:function(e,t,n){var r=this;if(!e||e.length===0){t&&t();return}var i=this.renderOnAddRemove;this.renderOnAddRemove=!1,fabric.util.enlivenObjects(e,function(e){e.forEach(function(e,t){r.insertAt(e,t,!0)}),r.renderOnAddRemove=i,t&&t()},null,n)},_toDataURL:function(e,t){this.clone(function(n){t(n.toDataURL(e))})},_toDataURLWithMultiplier:function(e,t,n){this.clone(function( +r){n(r.toDataURLWithMultiplier(e,t))})},clone:function(e,t){var n=JSON.stringify(this.toJSON(t));this.cloneWithoutData(function(t){t.loadFromJSON(n,function(){e&&e(t)})})},cloneWithoutData:function(e){var t=fabric.document.createElement("canvas");t.width=this.getWidth(),t.height=this.getHeight();var n=new fabric.Canvas(t);n.clipTo=this.clipTo,this.backgroundImage?(n.setBackgroundImage(this.backgroundImage.src,function(){n.renderAll(),e&&e(n)}),n.backgroundImageOpacity=this.backgroundImageOpacity,n.backgroundImageStretch=this.backgroundImageStretch):e&&e(n)}}),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.toFixed,i=t.util.string.capitalize,s=t.util.degreesToRadians,o=t.StaticCanvas.supports("setLineDash");if(t.Object)return;t.Object=t.util.createClass({type:"object",originX:"left",originY:"top",top:0,left:0,width:0,height:0,scaleX:1,scaleY:1,flipX:!1,flipY:!1,opacity:1,angle:0,cornerSize:12,transparentCorners:!0,hoverCursor:null,padding:0,borderColor:"rgba(102,153,255,0.75)",cornerColor:"rgba(102,153,255,0.5)",centeredScaling:!1,centeredRotation:!0,fill:"rgb(0,0,0)",fillRule:"source-over",backgroundColor:"",stroke:null,strokeWidth:1,strokeDashArray:null,strokeLineCap:"butt",strokeLineJoin:"miter",strokeMiterLimit:10,shadow:null,borderOpacityWhenMoving:.4,borderScaleFactor:1,transformMatrix:null,minScaleLimit:.01,selectable:!0,evented:!0,visible:!0,hasControls:!0,hasBorders:!0,hasRotatingPoint:!0,rotatingPointOffset:40,perPixelTargetFind:!1,includeDefaultValues:!0,clipTo:null,lockMovementX:!1,lockMovementY:!1,lockRotation:!1,lockScalingX:!1,lockScalingY:!1,lockUniScaling:!1,stateProperties:"top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill fillRule shadow clipTo visible backgroundColor".split(" "),initialize:function(e){e&&this.setOptions(e)},_initGradient:function(e){e.fill&&e.fill.colorStops&&!(e.fill instanceof t.Gradient)&&this.set("fill",new t.Gradient(e.fill))},_initPattern:function(e){e.fill&&e.fill.source&&!(e.fill instanceof t.Pattern)&&this.set("fill",new t.Pattern(e.fill)),e.stroke&&e.stroke.source&&!(e.stroke instanceof t.Pattern)&&this.set("stroke",new t.Pattern(e.stroke))},_initClipping:function(e){if(!e.clipTo||typeof e.clipTo!="string")return;var n=t.util.getFunctionBody(e.clipTo);typeof n!="undefined"&&(this.clipTo=new Function("ctx",n))},setOptions:function(e){for(var t in e)this.set(t,e[t]);this._initGradient(e),this._initPattern(e),this._initClipping(e)},transform:function(e,t){this.group&&this.group.transform(e,t),e.globalAlpha=this.opacity;var n=t?this._getLeftTopCoords():this.getCenterPoint();e.translate(n.x,n.y),e.rotate(s(this.angle)),e.scale(this.scaleX*(this.flipX?-1:1),this.scaleY*(this.flipY?-1:1))},toObject:function(e){var n=t.Object.NUM_FRACTION_DIGITS,i={type:this.type,originX:this.originX,originY:this.originY,left:r(this.left,n),top:r(this.top,n),width:r(this.width,n),height:r(this.height,n),fill:this.fill&&this.fill.toObject?this.fill.toObject():this.fill,stroke:this.stroke&&this.stroke.toObject?this.stroke.toObject():this.stroke,strokeWidth:r(this.strokeWidth,n),strokeDashArray:this.strokeDashArray,strokeLineCap:this.strokeLineCap,strokeLineJoin:this.strokeLineJoin,strokeMiterLimit:r(this.strokeMiterLimit,n),scaleX:r(this.scaleX,n),scaleY:r(this.scaleY,n),angle:r(this.getAngle(),n),flipX:this.flipX,flipY:this.flipY,opacity:r(this.opacity,n),shadow:this.shadow&&this.shadow.toObject?this.shadow.toObject():this.shadow,visible:this.visible,clipTo:this.clipTo&&String(this.clipTo),backgroundColor:this.backgroundColor};return this.includeDefaultValues||(i=this._removeDefaultValues(i)),t.util.populateWithProperties(this,i,e),i},toDatalessObject:function(e){return this.toObject(e)},_removeDefaultValues:function(e){var n=t.util.getKlass(e.type).prototype,r=n.stateProperties;return r.forEach(function(t){e[t]===n[t]&&delete e[t]}),e},toString:function(){return"#"},get:function(e){return this[e]},_setObject:function(e){for(var t in e)this._set(t,e[t])},set:function(e,t){return typeof e=="object"?this._setObject(e):typeof t=="function"&&e!=="clipTo"?this._set(e,t(this.get(e))):this._set(e,t),this},_set:function(e,n){var i=e==="scaleX"||e==="scaleY";return i&&(n=this._constrainScale(n)),e==="scaleX"&&n<0?(this.flipX=!this.flipX,n*=-1):e==="scaleY"&&n<0?(this.flipY=!this.flipY,n*=-1):e==="width"||e==="height"?this.minScaleLimit=r(Math.min(.1,1/Math.max(this.width,this.height)),2):e==="shadow"&&n&&!(n instanceof t.Shadow)&&(n=new t.Shadow(n)),this[e]=n,this},toggle:function(e){var t=this.get(e);return typeof t=="boolean"&&this.set(e,!t),this},setSourcePath:function(e){return this.sourcePath=e,this},getViewportTransform:function(){return this.canvas&&this.canvas.viewportTransform?this.canvas.viewportTransform:[1,0,0,1,0,0]},render:function(e,n){if(this.width===0||this.height===0||!this.visible)return;e.save(),this._setupFillRule(e),this._transform(e,n),this._setStrokeStyles(e),this._setFillStyles(e);var r=this.transformMatrix;r&&this.group&&(e.translate(-this.group.width/2,-this.group.height/2),e.transform(r[0],r[1],r[2],r[3],r[4],r[5])),this._setShadow(e),this.clipTo&&t.util.clipContext(this,e),this._render(e,n),this.clipTo&&e.restore(),this._removeShadow(e),this._restoreFillRule(e),e.restore()},_transform:function(e,t){var n=this.transformMatrix;n&&!this.group&&e.setTransform(n[0],n[1],n[2],n[3],n[4],n[5]),t||this.transform(e)},_setStrokeStyles:function(e){this.stroke&&(e.lineWidth=this.strokeWidth,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin,e.miterLimit=this.strokeMiterLimit,e.strokeStyle=this.stroke.toLive?this.stroke.toLive(e):this.stroke)},_setFillStyles:function(e){this.fill&&(e.fillStyle=this.fill.toLive?this.fill.toLive(e):this.fill)},_renderControls:function(e,n){var r=this.getViewportTransform();e.save();if(this.active&&!n){var i;this.group&&(i=t.util.transformPoint(this.group.getCenterPoint(),r),e.translate(i.x,i.y),e.rotate(s(this.group.angle))),i=t.util.transformPoint(this.getCenterPoint(),r,null!=this.group),this.group&&(i.x*=this.group.scaleX,i.y*=this.group.scaleY),e.translate(i.x,i.y),e.rotate(s(this.angle)),this.drawBorders(e),this.drawControls(e)}e.restore()},_setShadow:function(e){if(!this.shadow)return;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_removeShadow:function(e){if(!this.shadow)return;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0},_renderFill:function(e){if(!this.fill)return;this.fill.toLive&&(e.save(),e.translate(-this.width/2+this.fill.offsetX||0,-this.height/2+this.fill.offsetY||0)),this.fillRule==="destination-over"?e.fill("evenodd"):e.fill(),this.fill.toLive&&e.restore(),this.shadow&&!this.shadow.affectStroke&&this._removeShadow(e)},_renderStroke:function(e){if(!this.stroke)return;e.save(),this.strokeDashArray?(1&this.strokeDashArray.length&&this.strokeDashArray.push.apply(this.strokeDashArray,this.strokeDashArray),o?(e.setLineDash(this.strokeDashArray),this._stroke&&this._stroke(e)):this._renderDashedStroke&&this._renderDashedStroke(e),e.stroke()):this._stroke?this._stroke(e):e.stroke(),this._removeShadow(e),e.restore()},clone:function(e,n){return this.constructor.fromObject?this.constructor.fromObject(this.toObject(n),e):new t.Object(this.toObject(n))},cloneAsImage:function(e){var n=this.toDataURL();return t.util.loadImage(n,function(n){e&&e(new t.Image(n))}),this},toDataURL:function(e){e||(e={});var n=t.util.createCanvasElement(),r=this.getBoundingRect();n.width=r.width,n.height=r.height,t.util.wrapElement(n,"div");var i=new t.Canvas(n);e.format==="jpg"&&(e.format="jpeg"),e.format==="jpeg"&&(i.backgroundColor="#fff");var s={active:this.get("active"),left:this.getLeft(),top:this.getTop()};this.set("active",!1),this.setPositionByOrigin(new t.Point(n.width/2,n.height/2),"center","center");var o=this.canvas;i.add(this);var u=i.toDataURL(e);return this.set(s).setCoords(),this.canvas=o,i.dispose(),i=null,u},isType:function(e){return this.type===e},complexity:function(){return 0},toJSON:function(e){return this.toObject(e)},setGradient:function(e,n){n||(n={});var r={colorStops:[]};r.type=n.type||(n.r1||n.r2?"radial":"linear"),r.coords={x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y2};if(n.r1||n.r2)r.coords.r1=n.r1,r.coords.r2=n.r2;for(var i in n.colorStops){var s=new t.Color(n.colorStops[i]);r.colorStops.push({offset:i,color:s.toRgb(),opacity:s.getAlpha()})}return this.set(e,t.Gradient.forObject(this,r))},setPatternFill:function(e){return this.set("fill",new t.Pattern(e))},setShadow:function(e){return this.set("shadow",e?new t.Shadow(e):null)},setColor:function(e){return this.set("fill",e),this},setAngle:function(e){var t=(this.originX!=="center"||this.originY!=="center")&&this.centeredRotation;return t&&this._setOriginToCenter(),this.set("angle",e),t&&this._resetOrigin(),this},centerH:function(){return this.canvas.centerObjectH(this),this},centerV:function(){return this.canvas.centerObjectV(this),this},center:function(){return this.canvas.centerObject(this),this},remove:function(){return this.canvas.remove(this),this},getLocalPointer:function(e,t){t=t||this.canvas.getPointer(e);var n=this.translateToOriginPoint(this.getCenterPoint(),"left","top");return{x:t.x-n.x,y:t.y-n.y}},_setupFillRule:function(e){this.fillRule&&(this._prevFillRule=e.globalCompositeOperation,e.globalCompositeOperation=this.fillRule)},_restoreFillRule:function(e){this.fillRule&&this._prevFillRule&&(e.globalCompositeOperation=this._prevFillRule)}}),t.util.createAccessors(t.Object),t.Object.prototype.rotate=t.Object.prototype.setAngle,n(t.Object.prototype,t.Observable),t.Object.NUM_FRACTION_DIGITS=2,t.Object.__uid=0}(typeof exports!="undefined"?exports:this),function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{translateToCenterPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x+(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x-(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y+(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y-(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},translateToOriginPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x-(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x+(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y-(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y+(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},getCenterPoint:function(){var e=new fabric.Point(this.left,this.top);return this.translateToCenterPoint(e,this.originX,this.originY)},getPointByOrigin:function(e,t){var n=this.getCenterPoint();return this.translateToOriginPoint(n,e,t)},toLocalPoint:function(t,n,r){var i=this.getCenterPoint(),s=this.stroke?this.strokeWidth:0,o,u;return n&&r?(n==="left"?o=i.x-(this.getWidth()+s*this.scaleX)/2:n==="right"?o=i.x+(this.getWidth()+s*this.scaleX)/2:o=i.x,r==="top"?u=i.y-(this.getHeight()+s*this.scaleY)/2:r==="bottom"?u=i.y+(this.getHeight()+s*this.scaleY)/2:u=i.y):(o=this.left,u=this.top),fabric.util.rotatePoint(new fabric.Point(t.x,t.y),i,-e(this.angle)).subtractEquals(new fabric.Point(o,u))},setPositionByOrigin:function(e,t,n){var r=this.translateToCenterPoint(e,t,n),i=this.translateToOriginPoint(r,this.originX,this.originY);this.set("left",i.x),this.set("top",i.y)},adjustPosition:function(t){var n=e(this.angle),r=this.getWidth()/2,i=Math.cos(n)*r,s=Math.sin(n)*r,o=this.getWidth(),u=Math.cos(n)*o,a=Math.sin(n)*o;this.originX==="center"&&t==="left"||this.originX==="right"&&t==="center"?(this.left-=i,this.top-=s):this.originX==="left"&&t==="center"||this.originX==="center"&&t==="right"?(this.left+=i,this.top+=s):this.originX==="left"&&t==="right"?(this.left+=u,this.top+=a):this.originX==="right"&&t==="left"&&(this.left-=u,this.top-=a),this.setCoords(),this.originX=t},_setOriginToCenter:function(){this._originalOriginX=this.originX,this._originalOriginY=this.originY;var e=this.getCenterPoint();this.originX="center",this.originY="center",this.left=e.x,this.top=e.y},_resetOrigin:function(){var e=this.translateToOriginPoint(this.getCenterPoint(),this._originalOriginX,this._originalOriginY);this.originX=this._originalOriginX,this.originY=this._originalOriginY,this.left=e.x,this.top=e.y,this._originalOriginX=null,this._originalOriginY=null},_getLeftTopCoords:function(){return this.translateToOriginPoint(this.getCenterPoint(),"left","center")}})}(),function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{oCoords:null,intersectsWithRect:function(e,t){var n=this.oCoords,r=new fabric.Point(n.tl.x,n.tl.y),i=new fabric.Point(n.tr.x,n.tr.y),s=new fabric.Point(n.bl.x,n.bl.y),o=new fabric.Point(n.br.x,n.br.y),u=fabric.Intersection.intersectPolygonRectangle([r,i,o,s],e,t);return u.status==="Intersection"},intersectsWithObject:function(e){function t(e){return{tl:new fabric.Point(e.tl.x,e.tl.y),tr:new fabric.Point(e.tr.x,e.tr.y),bl:new fabric.Point(e.bl.x,e.bl.y),br:new fabric.Point(e.br.x,e.br.y)}}var n=t(this.oCoords),r=t(e.oCoords),i=fabric.Intersection.intersectPolygonPolygon([n.tl,n.tr,n.br,n.bl],[r.tl,r.tr,r.br,r.bl]);return i.status==="Intersection"},isContainedWithinObject:function(e){var t=e.getBoundingRect(),n=new fabric.Point(t.left,t.top),r=new fabric.Point(t.left+t.width,t.top+t.height);return this.isContainedWithinRect(n,r)},isContainedWithinRect:function(e,t){var n=this.getBoundingRect();return n.left>=e.x&&n.left+n.width<=t.x&&n.top>=e.y&&n.top+n.height<=t.y},containsPoint:function(e){var t=this._getImageLines(this.oCoords),n=this._findCrossPoints(e,t);return n!==0&&n%2===1},_getImageLines:function(e){return{topline:{o:e.tl,d:e.tr},rightline:{o:e.tr,d:e.br},bottomline:{o:e.br,d:e.bl},leftline:{o:e.bl,d:e.tl}}},_findCrossPoints:function(e,t){var n,r,i,s,o,u,a=0,f;for(var l in t){f=t[l];if(f.o.y=e.y&&f.d.y>=e.y)continue;f.o.x===f.d.x&&f.o.x>=e.x?(o=f.o.x,u=e.y):(n=0,r=(f.d.y-f.o.y)/(f.d.x-f.o.x),i=e.y-n*e.x,s=f.o.y-r*f.o.x,o=-(i-s)/(n-r),u=i+n*o),o>=e.x&&(a+=1);if(a===2)break}return a},getBoundingRectWidth:function(){return this.getBoundingRect().width},getBoundingRectHeight:function(){return this.getBoundingRect().height},getBoundingRect:function(){this.oCoords||this.setCoords();var e=[this.oCoords.tl.x,this.oCoords.tr.x,this.oCoords.br.x,this.oCoords.bl.x],t=fabric.util.array.min(e),n=fabric.util.array.max(e),r=Math.abs(t-n),i=[this.oCoords.tl.y,this.oCoords.tr.y,this.oCoords.br.y,this.oCoords.bl.y],s=fabric.util.array.min(i),o=fabric.util.array.max(i),u=Math.abs(s-o);return{left:t,top:s,width:r,height:u}},getWidth:function(){return this.width*this.scaleX},getHeight:function(){return this.height*this.scaleY},_constrainScale:function(e){return Math.abs(e)1?this.strokeWidth:0,n=e(this.angle),r=this.getViewportTransform(),i=function(e){return fabric.util.transformPoint(e,r)};this.currentWidth=(this.width+t)*this.scaleX,this.currentHeight=(this.height+t)*this.scaleY,this.currentWidth<0&&(this.currentWidth=Math.abs(this.currentWidth));var s=Math.sqrt(Math.pow(this.currentWidth/2,2)+Math.pow(this.currentHeight/2,2)),o=Math.atan(isFinite(this.currentHeight/this.currentWidth)?this.currentHeight/this.currentWidth:0),u=Math.cos(o+n)*s,a=Math.sin(o+n)*s,f=Math.sin(n),l=Math.cos(n),c=this.getCenterPoint(),h=new fabric.Point(this.currentWidth,this.currentHeight),p=new fabric.Point(c.x-u,c.y-a),d=new fabric.Point(p.x+h.x*l,p.y+h.x*f),v=new fabric.Point(p.x-h.y*f,p.y+h.y*l),m=new fabric.Point(p.x+h.x/2*l,p.y+h.x/2*f),g=i(p),y=i(d),b=i(new fabric.Point(d.x-h.y*f,d.y+h.y*l)),w=i(v),E=i(new fabric.Point(p.x-h.y/2*f,p.y+h.y/2*l)),S=i(m),x=i(new fabric.Point(d.x-h.y/2*f,d.y+h.y/2*l)),T=i(new fabric.Point(v.x+h.x/2*l,v.y+h.x/2*f)),N=i(new fabric.Point(m.x,m.y)),C=Math.cos(o+n)*this.padding*Math.sqrt(2),k=Math.sin(o+n)*this.padding*Math.sqrt(2);return g=g.add(new fabric.Point(-C,-k)),y=y.add(new fabric.Point(k,-C)),b=b.add(new fabric.Point(C,k)),w=w.add(new fabric.Point(-k,C)),E=E.add(new fabric.Point((-C-k)/2,(-k+C)/2)),S=S.add(new fabric.Point((k-C)/2,-(k+C)/2)),x=x.add(new fabric.Point((k+C)/2,(k-C)/2)),T=T.add(new fabric.Point((C-k)/2,(C+k)/2)),N=N.add(new fabric.Point((k-C)/2,-(k+C)/2)),this.oCoords={tl:g,tr:y,br:b,bl:w,ml:E,mt:S,mr:x,mb:T,mtr:N},this._setCornerCoords&&this._setCornerCoords(),this}})}(),fabric.util.object.extend(fabric.Object.prototype,{sendToBack:function(){return this.group?fabric.StaticCanvas.prototype.sendToBack.call(this.group,this):this.canvas.sendToBack(this),this},bringToFront:function(){return this.group?fabric.StaticCanvas.prototype.bringToFront.call(this.group,this):this.canvas.bringToFront(this),this},sendBackwards:function(e){return this.group?fabric.StaticCanvas.prototype.sendBackwards.call(this.group,this,e):this.canvas.sendBackwards(this,e),this},bringForward:function(e){return this.group?fabric.StaticCanvas.prototype.bringForward.call(this.group,this,e):this.canvas.bringForward(this,e),this},moveTo:function(e){return this.group?fabric.StaticCanvas.prototype.moveTo.call(this.group,this,e):this.canvas.moveTo(this,e),this}}),fabric.util.object.extend(fabric.Object.prototype,{getSvgStyles:function(){var e=this.fill?this.fill.toLive?"url(#SVGID_"+this.fill.id+")":this.fill:"none",t=this.stroke?this.stroke.toLive?"url(#SVGID_"+this.stroke.id+")":this.stroke:"none",n=this.strokeWidth?this.strokeWidth:"0",r=this.strokeDashArray?this.strokeDashArray.join(" "):"",i=this.strokeLineCap?this.strokeLineCap:"butt",s=this.strokeLineJoin?this.strokeLineJoin:"miter",o=this.strokeMiterLimit?this.strokeMiterLimit:"4",u=typeof this.opacity!="undefined"?this.opacity:"1",a=this.visible?"":" visibility: hidden;",f=this.shadow&&this.type!=="text"?"filter: url(#SVGID_"+this.shadow.id+");":"";return["stroke: ",t,"; ","stroke-width: ",n,"; ","stroke-dasharray: ",r,"; ","stroke-linecap: ",i,"; ","stroke-linejoin: ",s,"; ","stroke-miterlimit: ",o,"; ","fill: ",e,"; ","opacity: ",u,";",f,a].join("")},getSvgTransform:function(){var e=fabric.util.toFixed,t=this.getAngle(),n=this.getViewportTransform(),r=fabric.util.transformPoint(this.getCenterPoint(),n),i=fabric.Object.NUM_FRACTION_DIGITS,s="translate("+e(r.x,i)+" "+e(r.y,i)+")",o=t!==0?" rotate("+e(t,i)+")":"",u=this.scaleX===1&&this.scaleY===1&&n[0]===1&&n[3]===1?"":" scale("+e(this.scaleX*n[0],i)+" "+e(this.scaleY*n[3],i)+")",a=this.flipX?"matrix(-1 0 0 1 0 0) ":"",f=this.flipY?"matrix(1 0 0 -1 0 0)":"";return[s,o,u,a,f].join("")},_createBaseSVGMarkup:function(){var e=[];return this.fill&&this.fill.toLive&&e.push(this.fill.toSVG(this,!1)),this.stroke&&this.stroke.toLive&&e.push(this.stroke.toSVG(this,!1)),this.shadow&&e.push(this.shadow.toSVG(this)),e}}),fabric.util.object.extend(fabric.Object.prototype,{hasStateChanged:function(){return this.stateProperties.some(function(e){return this.get(e)!==this.originalState[e]},this)},saveState:function(e){return this.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),e&&e.stateProperties&&e.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),this},setupState:function(){return this.originalState={},this.saveState(),this}}),function(){var e=fabric.util.degreesToRadians,t=function(){return typeof G_vmlCanvasManager!="undefined"};fabric.util.object.extend(fabric.Object.prototype,{_controlsVisibility:null,_findTargetCorner:function(e){if(!this.hasControls||!this.active)return!1;var t=e.x,n=e.y,r,i;for(var s in this.oCoords){if(!this.isControlVisible(s))continue;if(s==="mtr"&&!this.hasRotatingPoint)continue;if(!(!this.get("lockUniScaling")||s!=="mt"&&s!=="mr"&&s!=="mb"&&s!=="ml"))continue;i=this._getImageLines(this.oCoords[s].corner),r=this._findCrossPoints({x:t,y:n},i);if(r!==0&&r%2===1)return this.__corner=s,s}return!1},_setCornerCoords:function(){var t=this.oCoords,n=e(this.angle),r=e(45-this.angle),i=Math.sqrt(2*Math.pow(this.cornerSize,2))/2,s=i*Math.cos(r),o=i*Math.sin(r),u=Math.sin(n),a=Math.cos(n);t.tl.corner={tl:{x:t.tl.x-o,y:t.tl.y-s},tr:{x:t.tl.x+s,y:t.tl.y-o},bl:{x:t.tl.x-s,y:t.tl.y+o},br:{x:t.tl.x+o,y:t.tl.y+s}},t.tr.corner={tl:{x:t.tr.x-o,y:t.tr.y-s},tr:{x:t.tr.x+s,y:t.tr.y-o},br:{x:t.tr.x+o,y:t.tr.y+s},bl:{x:t.tr.x-s,y:t.tr.y+o}},t.bl.corner={tl:{x:t.bl.x-o,y:t.bl.y-s},bl:{x:t.bl.x-s,y:t.bl.y+o},br:{x:t.bl.x+o,y:t.bl.y+s},tr:{x:t.bl.x+s,y:t.bl.y-o}},t.br.corner={tr:{x:t.br.x+s,y:t.br.y-o},bl:{x:t.br.x-s,y:t.br.y+o},br:{x:t.br.x+o,y:t.br.y+s},tl:{x:t.br.x-o,y:t.br.y-s}},t.ml.corner={tl:{x:t.ml.x-o,y:t.ml.y-s},tr:{x:t.ml.x+s,y:t.ml.y-o},bl:{x:t.ml.x-s,y:t.ml.y+o},br:{x:t.ml.x+o,y:t.ml.y+s}},t.mt.corner={tl:{x:t.mt.x-o,y:t.mt.y-s},tr:{x:t.mt.x+s,y:t.mt.y-o},bl:{x:t.mt.x-s,y:t.mt.y+o},br:{x:t.mt.x+o,y:t.mt.y+s}},t.mr.corner={tl:{x:t.mr.x-o,y:t.mr.y-s},tr:{x:t.mr.x+s,y:t.mr.y-o},bl:{x:t.mr.x-s,y:t.mr.y+o},br:{x:t.mr.x+o,y:t.mr.y+s}},t.mb.corner={tl:{x:t.mb.x-o,y:t.mb.y-s},tr:{x:t.mb.x+s,y:t.mb.y-o},bl:{x:t.mb.x-s,y:t.mb.y+o},br:{x:t.mb.x+o,y:t.mb.y+s}},t.mtr.corner={tl:{x:t.mtr.x-o+u*this.rotatingPointOffset,y:t.mtr.y-s-a*this.rotatingPointOffset},tr:{x:t.mtr.x+s+u*this.rotatingPointOffset,y:t.mtr.y-o-a*this.rotatingPointOffset},bl:{x:t.mtr.x-s+u*this.rotatingPointOffset,y:t.mtr.y+o-a*this.rotatingPointOffset},br:{x:t.mtr.x+o+u*this.rotatingPointOffset,y:t.mtr.y+s-a*this.rotatingPointOffset}}},drawBorders:function(e){if(!this.hasBorders)return this;var t=this.padding,n=t*2,r=~~(this.strokeWidth/2)*2;e.save(),e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=this.borderColor;var i=1/this._constrainScale(this.scaleX),s=1/this._constrainScale(this.scaleY);e.lineWidth=1/this.borderScaleFactor;var o=this.getViewportTransform(),u=fabric.util.transformPoint(new fabric.Point(this.getWidth(),this.getHeight()),o,!0),a=fabric.util.transformPoint(new fabric.Point(i,s),o,!0),f=u.x,l=u.y,c=a.x,h=a.y;this.group&&(f*=this.group.scaleX,l*=this.group.scaleY),e.strokeRect(~~(-(f/2)-t-r/2*c)-.5,~~(-(l/2)-t-r/2*h)-.5,~~(f+n+r*c)+1,~~(l+n+r*h)+1);if(this.hasRotatingPoint&&this.isControlVisible("mtr")&&!this.get("lockRotation")&&this.hasControls){var p=(this.flipY?l+r*c+t*2:-l-r*h-t*2)/2;e.beginPath(),e.moveTo(0,p),e.lineTo(0,p+(this.flipY?this.rotatingPointOffset:-this.rotatingPointOffset)),e.closePath(),e.stroke()}return e.restore(),this},drawControls:function(e){if(!this.hasControls)return this;var t=this.cornerSize,n=t/2,r=~~(this.strokeWidth/2),i=fabric.util.transformPoint(new fabric.Point(this.getWidth(),this.getHeight()),this.getViewportTransform(),!0),s=i.x,o=i.y,u=-(s/2),a=-(o/2),f=this.padding,l=n,c=n-t,h=this.transparentCorners?"strokeRect":"fillRect";return e.save(),e.lineWidth=1,e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=e.fillStyle=this.cornerColor,this._drawControl("tl",e,h,u-l-r-f,a-l-r-f),this._drawControl("tr",e,h,u+s-l+r+f,a-l-r-f),this._drawControl("bl",e,h,u-l-r-f,a+o+c+r+f),this._drawControl("br",e,h,u+s+c+r+f,a+o+c+r+f),this.get("lockUniScaling")||(this._drawControl("mt",e,h,u+s/2-l,a-l-r-f),this._drawControl("mb",e,h,u+s/2-l,a+o+c+r+f),this._drawControl("mr",e,h,u+s+c+r+f,a+o/2-l),this._drawControl("ml",e,h,u-l-r-f,a+o/2-l)),this.hasRotatingPoint&&this._drawControl("mtr",e,h,u+s/2-l,this.flipY?a+o+this.rotatingPointOffset-this.cornerSize/2+r+f:a-this.rotatingPointOffset-this.cornerSize/2-r-f),e.restore(),this},_drawControl:function(e,n,r,i,s){var o=this.cornerSize;this.isControlVisible(e)&&(t()||this.transparentCorners||n.clearRect(i,s,o,o),n[r](i,s,o,o))},isControlVisible:function(e){return this._getControlsVisibility()[e]},setControlVisible:function(e,t){return this._getControlsVisibility()[e]=t,this},setControlsVisibility:function(e){e||(e={});for(var t in e)this.setControlVisible(t,e[t]);return this},_getControlsVisibility:function(){return this._controlsVisibility||(this._controlsVisibility={tl:!0,tr:!0,br:!0,bl:!0,ml:!0,mt:!0,mr:!0,mb:!0,mtr:!0}),this._controlsVisibility}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{FX_DURATION:500,fxCenterObjectH:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("left"),endValue:this.getCenter().left,duration:this.FX_DURATION,onChange:function(t){e.set("left",t),s.renderAll(),i()},onComplete:function(){e.setCoords(),r()}}),this},fxCenterObjectV:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("top"),endValue:this.getCenter().top,duration:this.FX_DURATION,onChange:function(t){e.set("top",t),s.renderAll(),i()},onComplete:function(){e.setCoords(),r()}}),this},fxRemove:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("opacity"),endValue:0,duration:this.FX_DURATION,onStart:function(){e.set("active",!1)},onChange:function(t){e.set("opacity",t),s.renderAll(),i()},onComplete:function(){s.remove(e),r()}}),this}}),fabric.util.object.extend(fabric.Object.prototype,{animate:function(){if(arguments[0]&&typeof arguments[0]=="object"){var e=[],t,n;for(t in arguments[0])e.push(t);for(var r=0,i=e.length;r'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Line.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" ")),t.Line.fromElement=function(e,r){var i=t.parseAttributes(e,t.Line.ATTRIBUTE_NAMES),s=[i.x1||0,i.y1||0,i.x2||0,i.y2||0];return new t.Line(s,n(i,r))},t.Line.fromObject=function(e){var n=[e.x1,e.y1,e.x2,e.y2];return new t.Line(n,e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function i(e){return"radius"in e&&e.radius>0}var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Circle){t.warn("fabric.Circle is already defined.");return}t.Circle=t.util.createClass(t.Object,{type:"circle",radius:0,initialize:function(e){e=e||{},this.set("radius",e.radius||0),this.callSuper("initialize",e)},_set:function(e,t){return this.callSuper("_set",e,t),e==="radius"&&this.setRadius(t),this},toObject:function(e){return r(this.callSuper("toObject",e),{radius:this.get("radius")})},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,e.arc(t?this.left:0,t?this.top:0,this.radius,0,n,!1),this._renderFill(e),this.stroke&&this._renderStroke(e)},getRadiusX:function(){return this.get("radius")*this.get("scaleX")},getRadiusY:function(){return this.get("radius")*this.get("scaleY")},setRadius:function(e){this.radius=e,this.set("width",e*2).set("height",e*2)},complexity:function(){return 1}}),t.Circle.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy r".split(" ")),t.Circle.fromElement=function(e,n){n||(n={});var s=t.parseAttributes(e,t.Circle.ATTRIBUTE_NAMES);if(!i(s))throw new Error("value of `r` attribute is required and can not be negative");"left"in s||(s.left=0),"top"in s||(s.top=0),"transformMatrix"in s||(s.left-=n.width/2,s.top-=n.height/2);var o=new t.Circle(r(s,n));return o.cx=parseFloat(e.getAttribute("cx"))||0,o.cy=parseFloat(e.getAttribute("cy"))||0,o},t.Circle.fromObject=function(e){return new t.Circle(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={});if(t.Triangle){t.warn("fabric.Triangle is already defined");return}t.Triangle=t.util.createClass(t.Object,{type:"triangle",initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("width",e.width||100).set("height",e.height||100)},_render:function(e){var t=this.width/2,n=this.height/2;e.beginPath(),e.moveTo(-t,n),e.lineTo(0,-n),e.lineTo(t,n),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=this.width/2,r=this.height/2;e.beginPath(),t.util.drawDashedLine(e,-n,r,0,-r,this.strokeDashArray),t.util.drawDashedLine(e,0,-r,n,r,this.strokeDashArray),t.util.drawDashedLine(e,n,r,-n,r,this.strokeDashArray),e.closePath()},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=this.width/2,r=this.height/2,i=[-n+" "+r,"0 "+ -r,n+" "+r].join(",");return t.push("'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Triangle.fromObject=function(e){return new t.Triangle(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Ellipse){t.warn("fabric.Ellipse is already defined.");return}t.Ellipse=t.util.createClass(t.Object,{type:"ellipse",rx:0,ry:0,initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("rx",e.rx||0),this.set("ry",e.ry||0),this.set("width",this.get("rx")*2),this.set("height",this.get("ry")*2)},toObject:function( +e){return r(this.callSuper("toObject",e),{rx:this.get("rx"),ry:this.get("ry")})},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},render:function(e,t){if(this.rx===0||this.ry===0)return;return this.callSuper("render",e,t)},_render:function(e,t){e.beginPath(),e.save(),e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,e.transform(1,0,0,this.ry/this.rx,0,0),e.arc(t?this.left:0,t?this.top*this.rx/this.ry:0,this.rx,0,n,!1),this._renderFill(e),this._renderStroke(e),e.restore()},complexity:function(){return 1}}),t.Ellipse.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" ")),t.Ellipse.fromElement=function(e,n){n||(n={});var i=t.parseAttributes(e,t.Ellipse.ATTRIBUTE_NAMES);"left"in i||(i.left=0),"top"in i||(i.top=0),"transformMatrix"in i||(i.left-=n.width/2,i.top-=n.height/2);var s=new t.Ellipse(r(i,n));return s.cx=parseFloat(e.getAttribute("cx"))||0,s.cy=parseFloat(e.getAttribute("cy"))||0,s},t.Ellipse.fromObject=function(e){return new t.Ellipse(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function i(e){return e.left=e.left||0,e.top=e.top||0,e}var t=e.fabric||(e.fabric={}),n=t.util.object.extend;if(t.Rect){console.warn("fabric.Rect is already defined");return}var r=t.Object.prototype.stateProperties.concat();r.push("rx","ry","x","y"),t.Rect=t.util.createClass(t.Object,{stateProperties:r,type:"rect",rx:0,ry:0,x:0,y:0,strokeDashArray:null,initialize:function(e){e=e||{},this.callSuper("initialize",e),this._initRxRy(),this.x=e.x||0,this.y=e.y||0},_initRxRy:function(){this.rx&&!this.ry?this.ry=this.rx:this.ry&&!this.rx&&(this.rx=this.ry)},_render:function(e){if(this.width===1&&this.height===1){e.fillRect(0,0,1,1);return}var t=this.rx?Math.min(this.rx,this.width/2):0,n=this.ry?Math.min(this.ry,this.height/2):0,r=this.width,i=this.height,s=-r/2,o=-i/2,u=this.group&&this.group.type==="path-group",a=t!==0||n!==0,f=.4477152502;e.beginPath(),e.globalAlpha=u?e.globalAlpha*this.opacity:this.opacity,this.transformMatrix&&u&&e.translate(this.width/2+this.x,this.height/2+this.y),!this.transformMatrix&&u&&e.translate(-this.group.width/2+this.width/2+this.x,-this.group.height/2+this.height/2+this.y),e.moveTo(s+t,o),e.lineTo(s+r-t,o),a&&e.bezierCurveTo(s+r-f*t,o,s+r,o+f*n,s+r,o+n),e.lineTo(s+r,o+i-n),a&&e.bezierCurveTo(s+r,o+i-f*n,s+r-f*t,o+i,s+r-t,o+i),e.lineTo(s+t,o+i),a&&e.bezierCurveTo(s+f*t,o+i,s,o+i-f*n,s,o+i-n),e.lineTo(s,o+n),a&&e.bezierCurveTo(s,o+f*n,s+f*t,o,s+t,o),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=-this.width/2,r=-this.height/2,i=this.width,s=this.height;e.beginPath(),t.util.drawDashedLine(e,n,r,n+i,r,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r,n+i,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r+s,n,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n,r+s,n,r,this.strokeDashArray),e.closePath()},_normalizeLeftTopProperties:function(e){return"left"in e&&this.set("left",e.left+this.getWidth()/2),this.set("x",e.left||0),"top"in e&&this.set("top",e.top+this.getHeight()/2),this.set("y",e.top||0),this},toObject:function(e){var t=n(this.callSuper("toObject",e),{rx:this.get("rx")||0,ry:this.get("ry")||0,x:this.get("x"),y:this.get("y")});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Rect.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" ")),t.Rect.fromElement=function(e,r){if(!e)return null;var s=t.parseAttributes(e,t.Rect.ATTRIBUTE_NAMES);s=i(s);var o=new t.Rect(n(r?t.util.object.clone(r):{},s));return o._normalizeLeftTopProperties(s),o},t.Rect.fromObject=function(e){return new t.Rect(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.toFixed;if(t.Polyline){t.warn("fabric.Polyline is already defined");return}t.Polyline=t.util.createClass(t.Object,{type:"polyline",points:null,initialize:function(e,t,n){t=t||{},this.set("points",e),this.callSuper("initialize",t),this._calcDimensions(n)},_calcDimensions:function(e){return t.Polygon.prototype._calcDimensions.call(this,e)},toObject:function(e){return t.Polygon.prototype.toObject.call(this,e)},toSVG:function(e){var t=[],r=this._createBaseSVGMarkup();for(var i=0,s=this.points.length;i'),e?e(r.join("")):r.join("")},_render:function(e){var t;e.beginPath(),e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n'),e?e(n.join("")):n.join("")},_render:function(e){var t;e.beginPath(),e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n"},toObject:function(e){var t=i(this.callSuper("toObject",e),{path:this.path.map(function(e){return e.slice()}),pathOffset:this.pathOffset});return this.sourcePath&&(t.sourcePath=this.sourcePath),this.transformMatrix&&(t.transformMatrix=this.transformMatrix),t},toDatalessObject:function(e){var t=this.toObject(e);return this.sourcePath&&(t.path=this.sourcePath),delete t.sourcePath,t},toSVG:function(e){var t=[],n=this._createBaseSVGMarkup();for(var r=0,i=this.path.length;r',"",""),e?e(n.join("")):n.join("")},complexity:function(){return this.path.length},_parsePath:function(){var e=[],t=[],n,r,i=/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/ig,s,o;for(var f=0,l,c=this.path.length;fv)for(var g=1,y=l.length;g"];for(var r=0,i=t.length;r"),e?e(n.join("")):n.join("")},toString:function(){return"#"},isSameColor:function(){var e=(this.getObjects()[0].get("fill")||"").toLowerCase();return this.getObjects().every(function(t){return(t.get("fill")||"").toLowerCase()===e})},complexity:function(){return this.paths.reduce(function(e,t){return e+(t&&t.complexity?t.complexity():0)},0)},getObjects:function(){return this.paths}}),t.PathGroup.fromObject=function(e,n){typeof e.paths=="string"?t.loadSVGFromURL(e.paths,function(r){var i=e.paths;delete e.paths;var s=t.util.groupSVGElements(r,e,i);n(s)}):t.util.enlivenObjects(e.paths,function(r){delete e.paths,n(new t.PathGroup(r,e))})},t.PathGroup.async=!0}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.array.min,i=t.util.array.max,s=t.util.array.invoke;if(t.Group)return;var o={lockMovementX:!0,lockMovementY:!0,lockRotation:!0,lockScalingX:!0,lockScalingY:!0,lockUniScaling:!0};t.Group=t.util.createClass(t.Object,t.Collection,{type:"group",initialize:function(e,t){t=t||{},this._objects=e||[];for(var r=this._objects.length;r--;)this._objects[r].group=this;this.originalState={},this.callSuper("initialize"),this._calcBounds(),this._updateObjectsCoords(),t&&n(this,t),this._setOpacityIfSame(),this.setCoords(),this.saveCoords()},_updateObjectsCoords:function(){this.forEachObject(this._updateObjectCoords,this)},_updateObjectCoords:function(e){var t=e.getLeft(),n=e.getTop();e.set({originalLeft:t,originalTop:n,left:t-this.left,top:n-this.top}),e.setCoords(),e.__origHasControls=e.hasControls,e.hasControls=!1},toString:function(){return"#"},addWithUpdate:function(e){return this._restoreObjectsState(),e&&(this._objects.push(e),e.group=this),this.forEachObject(this._setObjectActive,this),this._calcBounds(),this._updateObjectsCoords(),this},_setObjectActive:function(e){e.set("active",!0),e.group=this},removeWithUpdate:function(e){return this._moveFlippedObject(e),this._restoreObjectsState(),this.forEachObject(this._setObjectActive,this),this.remove(e),this._calcBounds(),this._updateObjectsCoords(),this},_onObjectAdded:function(e){e.group=this},_onObjectRemoved:function(e){delete e.group,e.set("active",!1)},delegatedProperties:{fill:!0,opacity:!0,fontFamily:!0,fontWeight:!0,fontSize:!0,fontStyle:!0,lineHeight:!0,textDecoration:!0,textAlign:!0,backgroundColor:!0},_set:function(e,t){if(e in this.delegatedProperties){var n=this._objects.length;this[e]=t;while(n--)this._objects[n].set(e,t)}else this[e]=t},toObject:function(e){return n(this.callSuper("toObject",e),{objects:s(this._objects,"toObject",e)})},render:function(e){if(!this.visible)return;e.save(),this.clipTo&&t.util.clipContext(this,e);for(var n=0,r=this._objects.length;n'];for(var n=0,r=this._objects.length;n"),e?e(t.join("")):t.join("")},get:function(e){if(e in o){if(this[e])return this[e];for(var t=0,n=this._objects.length;t','");if(this.stroke||this.strokeDashArray){var n=this.fill;this.fill=null,t.push("'),this.fill=n}return t.push(""),e?e(t.join("")):t.join("")},getSrc:function(){if(this.getElement())return this.getElement().src||this.getElement()._src},toString:function(){return'#'},clone:function(e,t){this.constructor.fromObject(this.toObject(t),e)},applyFilters:function(e){if(!this._originalElement)return;if(this.filters.length===0){this._element=this._originalElement,e&&e();return}var t=this._originalElement,n=fabric.util.createCanvasElement(),r=fabric.util.createImage(),i=this;return n.width=t.width,n.height=t.height,n.getContext("2d").drawImage(t,0,0,t.width,t.height),this.filters.forEach(function(e){e&&e.applyTo(n)}),r.width=t.width,r.height=t.height,fabric.isLikelyNode?(r.src=n.toBuffer(undefined,fabric.Image.pngCompression),i._element=r,e&&e()):(r.onload=function(){i._element=r,e&&e(),r.onload=n=t=null},r.src=n.toDataURL("image/png")),this},_render:function(e){this._element&&e.drawImage(this._element,-this.width/2,-this.height/2,this.width,this.height)},_resetWidthHeight:function(){var e=this.getElement();this.set("width",e.width),this.set("height",e.height)},_initElement:function(e){this.setElement(fabric.util.getById(e)),fabric.util.addClass(this.getElement(),fabric.Image.CSS_CANVAS)},_initConfig:function(e){e||(e={}),this.setOptions(e),this._setWidthHeight(e),this._element&&this.crossOrigin&&(this._element.crossOrigin=this.crossOrigin)},_initFilters:function(e,t){e.filters&&e.filters.length?fabric.util.enlivenObjects(e.filters,function(e){t&&t(e)},"fabric.Image.filters"):t&&t()},_setWidthHeight:function(e){this.width="width"in e?e.width:this.getElement()?this.getElement().width||0:0,this.height="height"in e?e.height:this.getElement()?this.getElement().height||0:0},complexity:function(){return 1}}),fabric.Image.CSS_CANVAS="canvas-img",fabric.Image.prototype.getSvgSrc=fabric.Image.prototype.getSrc,fabric.Image.fromObject=function(e,t){fabric.util.loadImage(e.src,function(n){fabric.Image.prototype._initFilters.call(e,e,function(r){e.filters=r||[];var i=new fabric.Image(n,e);t&&t(i)})},null,e.crossOrigin)},fabric.Image.fromURL=function(e,t,n){fabric.util.loadImage(e,function(e){t(new fabric.Image(e,n))},null,n&&n.crossOrigin)},fabric.Image.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y width height xlink:href".split(" ")),fabric.Image.fromElement=function(e,n,r){var i=fabric.parseAttributes(e,fabric.Image.ATTRIBUTE_NAMES);fabric.Image.fromURL(i["xlink:href"],n,t(r?fabric.util.object.clone(r):{},i))},fabric.Image.async=!0,fabric.Image.pngCompression=1}(typeof exports!="undefined"?exports:this),fabric.util.object.extend(fabric.Object.prototype,{_getAngleValueForStraighten:function(){var e=this.getAngle()%360;return e>0?Math.round((e-1)/90)*90:Math.round(e/90)*90},straighten:function(){return this.setAngle(this._getAngleValueForStraighten()),this},fxStraighten:function(e){e=e||{};var t=function(){},n=e.onComplete||t,r=e.onChange||t,i=this;return fabric.util.animate({startValue:this.get("angle"),endValue:this._getAngleValueForStraighten(),duration:this.FX_DURATION,onChange:function(e){i.setAngle(e),r()},onComplete:function(){i.setCoords(),n()},onStart:function(){i.set("active",!1)}}),this}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{straightenObject:function(e){return e.straighten(),this.renderAll(),this},fxStraightenObject:function(e){return e.fxStraighten({onChange:this.renderAll.bind(this)}),this}}),fabric.Image.filters=fabric.Image.filters||{},fabric.Image.filters.BaseFilter=fabric.util.createClass({type:"BaseFilter",toObject:function(){return{type:this.type}},toJSON:function(){return this.toObject()}}),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;t.Image.filters.Brightness=t.util.createClass(t.Image.filters.BaseFilter,{type:"Brightness",initialize:function(e){e=e||{},this.brightness=e.brightness||0},applyTo:function(e){var t=e.getContext("2d"),n=t.getImageData(0,0,e.width,e.height),r=n.data,i=this.brightness;for(var s=0,o=r.length;sa||C<0||C>u)continue;var k=(N*u+C)*4,L=t[x*i+T];b+=o[k]*L,w+=o[k+1]*L,E+=o[k+2]*L,S+=o[k+3]*L}h[y]=b,h[y+1]=w,h[y+2]=E,h[y+3]=S+p*(255-S)}n.putImageData(c,0,0)},toObject:function(){return n(this.callSuper("toObject"),{opaque:this.opaque,matrix:this.matrix})}}),t.Image.filters.Convolute.fromObject=function(e){return new t.Image.filters.Convolute(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;t.Image.filters.GradientTransparency=t.util.createClass(t.Image.filters.BaseFilter,{type:"GradientTransparency",initialize:function(e){e=e||{},this.threshold=e.threshold||100},applyTo:function(e){var t=e.getContext("2d"),n=t.getImageData(0,0,e.width,e.height),r=n.data,i=this.threshold,s=r.length;for(var o=0,u=r.length;o-1?e.channel:0},applyTo:function(e){if(!this.mask)return;var n=e.getContext("2d"),r=n.getImageData(0,0,e.width,e.height),i=r.data,s=this.mask.getElement(),o=t.util.createCanvasElement(),u=this.channel,a,f=r.width*r.height*4;o.width=s.width,o.height=s.height,o.getContext("2d").drawImage(s,0,0,s.width,s.height);var l=o.getContext("2d").getImageData(0,0,s.width,s.height),c=l.data;for(a=0;ao&&f>o&&l>o&&u(a-f)'},_render:function(e){var t=this.group&&this.group.type==="path-group";t&&!this.transformMatrix?e.translate(-this.group.width/2+this.left,-this.group.height/2+this.top):t&&this.transformMatrix&&e.translate(-this.group.width/2,-this.group.height/2),typeof Cufon=="undefined"||this.useNative===!0?this._renderViaNative(e):this._renderViaCufon(e)},_renderViaNative:function(e){var n=this.text.split(this._reNewline);this.transform(e,t.isLikelyNode),this._setTextStyles(e),this.width=this._getTextWidth(e,n),this.height=this._getTextHeight(e,n),this.clipTo&&t.util.clipContext(this,e),this._renderTextBackground(e,n),this._translateForTextAlign(e),this._renderText(e,n),this.textAlign!=="left"&&this.textAlign!=="justify"&&e.restore(),this._renderTextDecoration(e,n),this.clipTo&&e.restore(),this._setBoundaries(e,n),this._totalLineHeight=0},_renderText:function(e,t){e.save(),this._setShadow(e),this._renderTextFill(e,t),this._renderTextStroke(e,t),this._removeShadow(e),e.restore()},_translateForTextAlign:function(e){this.textAlign!=="left"&&this.textAlign!=="justify"&&(e.save(),e.translate(this.textAlign==="center"?this.width/2:this.width,0))},_setBoundaries:function(e,t){this._boundaries=[];for(var n=0,r=t.length;nn&&(n=s)}return n},_renderChars:function(e,t,n,r,i){t[e](n,r,i)},_renderTextLine:function(e,t,n,r,i,s){i-=this.fontSize/4;if(this.textAlign!=="justify"){this._renderChars(e,t,n,r,i,s);return}var o=t.measureText(n).width,u=this.width;if(u>o){var a=n.split(/\s+/),f=t.measureText(n.replace(/\s+/g,"")).width,l=u-f,c=a.length-1,h=l/c,p=0;for(var d=0,v=a.length;d-1&&i(this.fontSize*this.lineHeight),this.textDecoration.indexOf("line-through")>-1&&i(this.fontSize*this.lineHeight-this.fontSize/2),this.textDecoration.indexOf("overline")>-1&&i(this.fontSize*this.lineHeight-this.fontSize)},_getFontDeclaration:function(){return[t.isLikelyNode?this.fontWeight:this.fontStyle,t.isLikelyNode?this.fontStyle:this.fontWeight,this.fontSize+"px",t.isLikelyNode?'"'+this.fontFamily+'"':this.fontFamily].join(" ")},render:function(e){if(!this.visible)return;e.save();var t=this.transformMatrix;t&&(!this.group||this.group.type==="path-group")&&e.transform(t[0],t[1],t[2],t[3],t[4],t[5]),this._render(e),e.restore()},toObject:function(e){var t=n(this.callSuper("toObject",e),{text:this.text,fontSize:this.fontSize,fontWeight:this.fontWeight,fontFamily:this.fontFamily,fontStyle:this.fontStyle,lineHeight:this.lineHeight,textDecoration:this.textDecoration,textAlign:this.textAlign,path:this.path,textBackgroundColor:this.textBackgroundColor,useNative:this.useNative});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=[],n=this.text.split(this._reNewline),r=this._getSVGLeftTopOffsets(n),i=this._getSVGTextAndBg(r.lineTop,r.textLeft,n),s=this._getSVGShadows(r.lineTop,n);return r.textTop+=this._fontAscent?this._fontAscent/5*this.lineHeight:0,this._wrapSVGTextAndBg(t,i,s,r),e?e(t.join("")):t.join("")},_getSVGLeftTopOffsets:function(e){var t=this.useNative?this.fontSize*this.lineHeight:-this._fontAscent-this._fontAscent/5*this.lineHeight,n=-(this.width/2),r=this.useNative?this.fontSize-1:this.height/2-e.length*this.fontSize-this._totalLineHeight;return{textLeft:n,textTop:r,lineTop:t}},_wrapSVGTextAndBg:function(e,t,n,r){e.push('',t.textBgRects.join(""),"',n.join(""),t.textSpans.join(""),"","")},_getSVGShadows:function(e,n){var r=[],s,o,u=1;if(!this.shadow||!this._boundaries)return r;for(s=0,o=n.length;s",t.util.string.escapeXml(n[s]),""),u=1}else u++;return r},_getSVGTextAndBg:function(e,t,n){var r=[],i=[],s=1;this._setSVGBg(i);for(var o=0,u=n.length;o",t.util.string.escapeXml(e),"")},_setSVGTextLineBg:function(e,t,n,r){e.push("')},_setSVGBg:function(e){this.backgroundColor&&this._boundaries&&e.push("')},_getFillAttributes:function(e){var n=e&&typeof e=="string"?new t.Color(e):"";return!n||!n.getSource()||n.getAlpha()===1?'fill="'+e+'"':'opacity="'+n.getAlpha()+'" fill="'+n.setAlpha(1).toRgb()+'"'},_set:function(e,t){e==="fontFamily"&&this.path&&(this.path=this.path.replace(/(.*?)([^\/]*)(\.font\.js)/,"$1"+t+"$3")),this.callSuper("_set",e,t),e in this._dimensionAffectingProps&&(this._initDimensions(),this.setCoords())},complexity:function(){return 1}}),t.Text.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size text-decoration text-anchor".split(" ")),t.Text.DEFAULT_SVG_FONT_SIZE=16,t.Text.fromElement=function(e,n){if(!e)return null;var r=t.parseAttributes(e,t.Text.ATTRIBUTE_NAMES);n=t.util.object.extend(n?t.util.object.clone(n):{},r),"dx"in r&&(n.left+=r.dx),"dy"in r&&(n.top+=r.dy),"fontSize"in n||(n.fontSize=t.Text.DEFAULT_SVG_FONT_SIZE),n.originX||(n.originX="center");var i=new t.Text(e.textContent,n);return i.set({left:i.getLeft()+i.getWidth()/2,top:i.getTop()-i.getHeight()/2}),i},t.Text.fromObject=function(e){return new t.Text(e.text,r(e))},t.util.createAccessors(t.Text)}(typeof exports!="undefined"?exports:this),function(){var e=fabric.util.object.clone;fabric.IText=fabric.util.createClass(fabric.Text,fabric.Observable,{type:"i-text",selectionStart:0,selectionEnd:0,selectionColor:"rgba(17,119,255,0.3)",isEditing:!1,editable:!0,editingBorderColor:"rgba(102,153,255,0.25)",cursorWidth:2,cursorColor:"#333",cursorDelay:1e3,cursorDuration:600,styles:null,caching:!0,_skipFillStrokeCheck:!0,_reSpace:/\s|\n/,_fontSizeFraction:4,_currentCursorOpacity:0,_selectionDirection:null,_abortCursorAnimation:!1,_charWidthsCache:{},initialize:function(e,t){this.styles=t?t.styles||{}:{},this.callSuper("initialize",e,t),this.initBehavior(),fabric.IText.instances.push(this),this.__lineWidths={},this.__lineHeights={},this.__lineOffsets={}},isEmptyStyles:function(){if(!this.styles)return!0;var e=this.styles;for(var t in e)for(var n in e[t])for(var r in e[t][n])return!1;return!0},setSelectionStart:function(e){this.selectionStart!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})),this.selectionStart=e,this.hiddenTextarea&&(this.hiddenTextarea.selectionStart=e)},setSelectionEnd:function(e){this.selectionEnd!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})),this.selectionEnd=e,this.hiddenTextarea&&(this.hiddenTextarea.selectionEnd=e)},getSelectionStyles:function(e,t){if(arguments.length===2){var n=[];for(var r=e;r=r.charIndex&&(a!==o||hs&&a-1&&this._renderCharDecorationAtOffset(e,n,r+this.fontSize/this._fontSizeFraction,i,0,this.fontSize/20),u.indexOf("line-through")>-1&&this._renderCharDecorationAtOffset(e,n,r+this.fontSize/this._fontSizeFraction,i,o/2,a/20),u.indexOf("overline")>-1&&this._renderCharDecorationAtOffset(e,n,r,i,s-this.fontSize/this._fontSizeFraction,this.fontSize/20)},_renderCharDecorationAtOffset:function(e,t,n,r,i,s){e.fillRect(t,n-i,r,s)},_renderTextLine:function(e,t,n,r,i,s){i+=this.fontSize/4,this.callSuper("_renderTextLine",e,t,n,r,i,s)},_renderTextDecoration:function(e,t){if(this.isEmptyStyles())return this.callSuper("_renderTextDecoration",e,t)},_renderTextLinesBackground:function(e,t){if(!this.textBackgroundColor&&!this.styles)return;e.save(),this.textBackgroundColor&&(e.fillStyle=this.textBackgroundColor);var n=0,r=this.fontSize/this._fontSizeFraction;for(var i=0,s=t.length;in&&(n=s)}return n},_getHeightOfLine:function(e,t,n){n=n||this.text.split(this._reNewline);var r=this._getHeightOfChar(e,n[t][0],t,0),i=n[t],s=i.split("");for(var o=1,u=s.length;or&&(r=a)}return r*this.lineHeight},_getTextHeight:function(e,t){var n=0;for(var r=0,i=t.length;r-1)t++,n--;return e-t},findWordBoundaryRight:function(e){var t=0,n=e;if(this._reSpace.test(this.text.charAt(n)))while(this._reSpace.test(this.text.charAt(n)))t++,n++;while(/\S/.test(this.text.charAt(n))&&n-1)t++,n--;return e-t},findLineBoundaryRight:function(e){var t=0,n=e;while(!/\n/.test(this.text.charAt(n))&&n0&&nr;s?this.removeStyleObject(s,n+1):this.removeStyleObject(this.get2DCursorLocation(n).charIndex===0,n)}this.text=this.text.slice(0,e)+this.text.slice(t)},insertChars:function(e){var t=this.text.slice(this.selectionStart,this.selectionStart+1)==="\n";this.text=this.text.slice(0,this.selectionStart)+e+this.text.slice(this.selectionEnd),this.selectionStart===this.selectionEnd&&this.insertStyleObjects(e,t,this.copiedStyles),this.selectionStart+=e.length,this.selectionEnd=this.selectionStart,this.canvas&&this.canvas.renderAll().renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},insertNewlineStyleObject:function(t,n,r){this.shiftLineStyles(t,1),this.styles[t+1]||(this.styles[t+1]={});var i=this.styles[t][n-1],s={};if(r)s[0]=e(i),this.styles[t+1]=s;else{for(var o in this.styles[t])parseInt(o,10)>=n&&(s[parseInt(o,10)-n]=this.styles[t][o],delete this.styles[t][o]);this.styles[t+1]=s}},insertCharStyleObject:function(t,n,r){var i=this.styles[t],s=e(i);n===0&&!r&&(n=1);for(var o in s){var u=parseInt(o,10);u>=n&&(i[u+1]=s[u])}this.styles[t][n]=r||e(i[n-1])},insertStyleObjects:function(e,t,n){if(this.isEmptyStyles())return;var r=this.get2DCursorLocation(),i=r.lineIndex,s=r.charIndex;this.styles[i]||(this.styles[i]={}),e==="\n"?this.insertNewlineStyleObject(i,s,t):n?this._insertStyles(n):this.insertCharStyleObject(i,s)},_insertStyles:function(e){for(var t=0,n=e.length;tt&&(this.styles[s+n]=r[s])}},removeStyleObject:function(t,n){var r=this.get2DCursorLocation(n),i=r.lineIndex,s=r.charIndex;if(t){var o=this.text.split(this._reNewline),u=o[i-1],a=u?u.length:0;this.styles[i-1]||(this.styles[i-1]={});for(s in this.styles[i])this.styles[i-1][parseInt(s,10)+a]=this.styles[i][s];this.shiftLineStyles(i,-1)}else{var f=this.styles[i];if(f){var l=this.selectionStart===this.selectionEnd?-1:0;delete f[s+l]}var c=e(f);for(var h in c){var p=parseInt(h,10);p>=s&&p!==0&&(f[p-1]=c[p],delete f[p])}}},insertNewline:function(){this.insertChars("\n")}})}(),fabric.util.object.extend(fabric.IText.prototype,{initDoubleClickSimulation:function(){this.__lastClickTime=+(new Date),this.__lastLastClickTime=+(new Date),this.__lastPointer={},this.on("mousedown",this.onMouseDown.bind(this))},onMouseDown:function(e){this.__newClickTime=+(new Date);var t=this.canvas.getPointer(e.e);this.isTripleClick(t)?(this.fire("tripleclick",e),this._stopEvent(e.e)):this.isDoubleClick(t)&&(this.fire("dblclick",e),this._stopEvent(e.e)),this.__lastLastClickTime=this.__lastClickTime,this.__lastClickTime=this.__newClickTime,this.__lastPointer=t,this.__lastIsEditing=this.isEditing,this.__lastSelected=this.selected},isDoubleClick:function(e){return this.__newClickTime-this.__lastClickTime<500&&this.__lastPointer.x===e.x&&this.__lastPointer.y===e.y&&this.__lastIsEditing},isTripleClick:function(e){return this.__newClickTime-this.__lastClickTime<500&&this.__lastClickTime-this.__lastLastClickTime<500&&this.__lastPointer.x===e.x&&this.__lastPointer.y===e.y},_stopEvent:function(e){e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation()},initCursorSelectionHandlers:function(){this.initSelectedHandler(),this.initMousedownHandler(),this.initMousemoveHandler(),this.initMouseupHandler(),this.initClicks()},initClicks:function(){this.on("dblclick",function(e){this.selectWord(this.getSelectionStartFromPointer(e.e))}),this.on("tripleclick",function(e){this.selectLine(this.getSelectionStartFromPointer(e.e))})},initMousedownHandler:function(){this.on("mousedown",function(e){var t=this.canvas.getPointer(e.e);this.__mousedownX=t.x,this.__mousedownY=t.y,this.__isMousedown=!0,this.hiddenTextarea&&this.canvas&&this.canvas.wrapperEl.appendChild(this.hiddenTextarea),this.selected&&this.setCursorByClick(e.e),this.isEditing&&(this.__selectionStartOnMouseDown=this.selectionStart,this.initDelayedCursor(!0))})},initMousemoveHandler:function(){this.on("mousemove",function(e){if(!this.__isMousedown||!this.isEditing)return;var t=this.getSelectionStartFromPointer(e.e);t>=this.__selectionStartOnMouseDown?(this.setSelectionStart(this.__selectionStartOnMouseDown),this.setSelectionEnd(t)):(this.setSelectionStart(t),this.setSelectionEnd(this.__selectionStartOnMouseDown))})},_isObjectMoved:function(e){var t=this.canvas.getPointer(e);return this.__mousedownX!==t.x||this.__mousedownY!==t.y},initMouseupHandler:function(){this.on("mouseup",function(e){this.__isMousedown=!1;if(this._isObjectMoved(e.e))return;this.__lastSelected&&(this.enterEditing(),this.initDelayedCursor(!0)),this.selected=!0})},setCursorByClick:function(e){var t=this.getSelectionStartFromPointer(e);e.shiftKey?to?0:1,f=r+a;return this.flipX&&(f=i-f),f>this.text.length&&(f=this.text.length),s===i&&f--,f}}),fabric.util.object.extend(fabric.IText.prototype,{initHiddenTextarea:function(){this.hiddenTextarea=fabric.document.createElement("textarea"),this.hiddenTextarea.setAttribute("autocapitalize","off"),this.hiddenTextarea.style.cssText="position: absolute; top: 0; left: -9999px",fabric.document.body.appendChild(this.hiddenTextarea),fabric.util.addListener(this.hiddenTextarea,"keydown",this.onKeyDown.bind(this)),fabric.util.addListener(this.hiddenTextarea,"keypress",this.onKeyPress.bind(this)),fabric.util.addListener(this.hiddenTextarea,"copy",this.copy.bind(this)),fabric.util.addListener(this.hiddenTextarea,"paste",this.paste.bind(this)),!this._clickHandlerInitialized&&this.canvas&&(fabric.util.addListener(this.canvas.upperCanvasEl,"click",this.onClick.bind(this)),this._clickHandlerInitialized=!0)},_keysMap:{8:"removeChars",13:"insertNewline",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown",46:"forwardDelete"},_ctrlKeysMap:{65:"selectAll",88:"cut"},onClick:function(){this.hiddenTextarea&&this.hiddenTextarea.focus()},onKeyDown:function(e){if(!this.isEditing)return;if(e.keyCode in this._keysMap)this[this._keysMap[e.keyCode]](e);else{if(!(e.keyCode in this._ctrlKeysMap&&(e.ctrlKey||e.metaKey)))return;this[this._ctrlKeysMap[e.keyCode]](e)}e.stopPropagation(),this.canvas&&this.canvas.renderAll()},forwardDelete:function(e){this.selectionStart===this.selectionEnd&&this.moveCursorRight(e),this.removeChars(e)},copy:function(e){var t=this.getSelectedText(),n=this._getClipboardData(e);n&&n.setData("text",t),this.copiedText=t,this.copiedStyles=this.getSelectionStyles(this.selectionStart,this.selectionEnd)},paste:function(e){var t=null,n=this._getClipboardData(e);n?t=n.getData("text"):t=this.copiedText,t&&this.insertChars(t)},cut:function(e){if(this.selectionStart===this.selectionEnd)return;this.copy(),this.removeChars(e)},_getClipboardData:function(e){return e&&(e.clipboardData||fabric.window.clipboardData)},onKeyPress:function(e){if(!this.isEditing||e.metaKey||e.ctrlKey||e.keyCode===8||e.keyCode===13)return;this.insertChars(String.fromCharCode(e.which)),e.stopPropagation()},getDownCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.text.split(this._reNewline),i,s,o=this.text.slice(0,n),u=this.text.slice(n),a=o.slice(o.lastIndexOf("\n")+1),f=u.match(/(.*)\n?/)[1],l=(u.match(/.*\n(.*)\n?/)||{})[1]||"",c=this.get2DCursorLocation(n);if(c.lineIndex===r.length-1||e.metaKey)return this.text.length-n;var h=this._getWidthOfLine(this.ctx,c.lineIndex,r);s=this._getLineLeftOffset(h);var p=s,d=c.lineIndex;for(var v=0,m=a.length;vn){f=!0;var d=u-p,v=u,m=Math.abs(d-n),g=Math.abs(v-n);a=gthis.text.length&&(this.selectionStart=this.text.length),this.selectionEnd=this.selectionStart},moveCursorDownWithShift:function(e){if(this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd){this.selectionStart+=e,this._selectionDirection="left";return}this._selectionDirection="right",this.selectionEnd+=e,this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length)},getUpCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.get2DCursorLocation(n);if(r.lineIndex===0||e.metaKey)return n;var i=this.text.slice(0,n),s=i.slice(i.lastIndexOf("\n")+1),o=(i.match(/\n?(.*)\n.*$/)||{})[1]||"",u=this.text.split(this._reNewline),a,f=this._getWidthOfLine(this.ctx,r.lineIndex,u),l=this._getLineLeftOffset(f),c=l,h=r.lineIndex;for(var p=0,d=s.length;pn){f=!0;var d=u-p,v=u,m=Math.abs(d-n),g=Math.abs(v-n);a=g=this.text.length&&this.selectionEnd>=this.text.length)return;this.abortCursorAnimation(),this._currentCursorOpacity=1,e.shiftKey?this.moveCursorRightWithShift(e):this.moveCursorRightWithoutShift(e),this.initDelayedCursor()},moveCursorRightWithShift:function(e){this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd?this._moveRight(e,"selectionStart"):(this._selectionDirection="right",this._moveRight(e,"selectionEnd"),this.text.charAt(this.selectionEnd-1)==="\n"&&this.selectionEnd++,this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length))},moveCursorRightWithoutShift:function(e){this._selectionDirection="right",this.selectionStart===this.selectionEnd?(this._moveRight(e,"selectionStart"),this.selectionEnd=this.selectionStart):(this.selectionEnd+=this.getNumNewLinesInSelectedText(),this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length),this.selectionStart=this.selectionEnd)},removeChars:function(e){this.selectionStart===this.selectionEnd?this._removeCharsNearCursor(e):this._removeCharsFromTo(this.selectionStart,this.selectionEnd),this.selectionEnd=this.selectionStart,this._removeExtraneousStyles(),this.canvas&&this.canvas.renderAll().renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},_removeCharsNearCursor:function(e){if(this.selectionStart!==0)if(e.metaKey){var t=this.findLineBoundaryLeft(this.selectionStart);this._removeCharsFromTo(t,this.selectionStart),this.selectionStart=t}else if(e.altKey){var n=this.findWordBoundaryLeft(this.selectionStart);this._removeCharsFromTo(n,this.selectionStart),this.selectionStart=n}else{var r=this.text.slice(this.selectionStart-1,this.selectionStart)==="\n";this.removeStyleObject(r),this.selectionStart--,this.text=this.text.slice(0,this.selectionStart)+this.text.slice(this.selectionStart+1)}}}),fabric.util.object.extend(fabric.IText.prototype,{_setSVGTextLineText:function(e,t,n,r,i,s){this.styles[t]?this._setSVGTextLineChars(e,t,n,r,i,s):this.callSuper("_setSVGTextLineText",e,t,n,r,i)},_setSVGTextLineChars:function(e,t,n,r,i,s){var o=t===0||this.useNative?"y":"dy",u=e.split(""),a=0,f=this._getSVGLineLeftOffset(t),l=this._getSVGLineTopOffset(t),c=this._getHeightOfLine(this.ctx,t);for(var h=0,p=u.length;h'].join("")},_createTextCharSpan:function(e,t,n,r,i,s){var o=this.getSvgStyles.call(fabric.util.object.extend({visible:!0,fill:this.fill,stroke:this.stroke,type:"text"},t));return['',fabric.util.string.escapeXml(e),""].join("")}}),function(){function request(e,t,n){var r=URL.parse(e);r.port||(r.port=r.protocol.indexOf("https:")===0?443:80);var i=r.port===443?HTTPS:HTTP,s=i.request({hostname:r.hostname,port:r.port,path:r.path,method:"GET"},function(e){var r="";t&&e.setEncoding(t),e.on("end",function(){n(r)}),e.on("data",function(t){e.statusCode===200&&(r+=t)})});s.on("error",function(e){e.errno===process.ECONNREFUSED?fabric.log("ECONNREFUSED: connection refused to "+r.hostname+":"+r.port):fabric.log(e.message)}),s.end()}function requestFs(e,t){var n=require("fs");n.readFile(e,function(e,n){if(e)throw fabric.log(e),e;t(n)})}if(typeof document!="undefined"&&typeof window!="undefined")return;var DOMParser=require("xmldom").DOMParser,URL=require("url"),HTTP=require("http"),HTTPS=require("https"),Canvas=require("canvas"),Image=require("canvas").Image;fabric.util.loadImage=function(e,t,n){function r(r){i.src=new Buffer(r,"binary"),i._src=e,t&&t.call(n,i)}var i=new Image;e&&(e instanceof Buffer||e.indexOf("data")===0)?(i.src=i._src=e,t&&t.call(n,i)):e&&e.indexOf("http")!==0?requestFs(e,r):e?request(e,"binary",r):t&&t.call(n,e)},fabric.loadSVGFromURL=function(e,t,n){e=e.replace(/^\n\s*/,"").replace(/\?.*$/,"").trim(),e.indexOf("http")!==0?requestFs(e,function(e){fabric.loadSVGFromString(e.toString(),t,n)}):request(e,"",function(e){fabric.loadSVGFromString(e,t,n)})},fabric.loadSVGFromString=function(e,t,n){var r=(new DOMParser).parseFromString(e);fabric.parseSVGDocument(r.documentElement,function(e,n){t&&t(e,n)},n)},fabric.util.getScript=function(url,callback){request(url,"",function(body){eval(body),callback&&callback()})},fabric.Image.fromObject=function(e,t){fabric.util.loadImage(e.src,function(n){var r=new fabric.Image(n);r._initConfig(e),r._initFilters(e,function(e){r.filters=e||[],t&&t(r)})})},fabric.createCanvasForNode=function(e,t,n,r){r=r||n;var i=fabric.document.createElement("canvas"),s=new Canvas(e||600,t||600,r);i.style={},i.width=s.width,i.height=s.height;var o=fabric.Canvas||fabric.StaticCanvas,u=new o(i,n);return u.contextContainer=s.getContext("2d"),u.nodeCanvas=s,u.Font=Canvas.Font,u},fabric.StaticCanvas.prototype.createPNGStream=function(){return this.nodeCanvas.createPNGStream()},fabric.StaticCanvas.prototype.createJPEGStream=function(e){return this.nodeCanvas.createJPEGStream(e)};var origSetWidth=fabric.StaticCanvas.prototype.setWidth;fabric.StaticCanvas.prototype.setWidth=function(e){return origSetWidth.call(this,e),this.nodeCanvas.width=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setWidth=fabric.StaticCanvas.prototype.setWidth);var origSetHeight=fabric.StaticCanvas.prototype.setHeight;fabric.StaticCanvas.prototype.setHeight=function(e){return origSetHeight.call(this,e),this.nodeCanvas.height=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setHeight=fabric.StaticCanvas.prototype.setHeight)}(); \ No newline at end of file diff --git a/js/fabric.js b/js/fabric.js new file mode 120000 index 00000000..9be1b151 --- /dev/null +++ b/js/fabric.js @@ -0,0 +1 @@ +fabric-v1.4.11.js \ No newline at end of file diff --git a/js/fabric.min.js b/js/fabric.min.js new file mode 120000 index 00000000..71d699fe --- /dev/null +++ b/js/fabric.min.js @@ -0,0 +1 @@ +fabric-v1.4.11.min.js \ No newline at end of file diff --git a/js/flot-zoom.js b/js/flot-zoom.js new file mode 100644 index 00000000..3bd00f71 --- /dev/null +++ b/js/flot-zoom.js @@ -0,0 +1,93 @@ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ +/*globals $, JS9 */ + +"use strict"; + + +(function($) { + function zoomStackIn(plot, event, ranges, func) { + var axes = plot.getAxes(); + var div = plot.getPlaceholder(); + + var r = {}; + r.xmin = axes.xaxis.min; + r.xmax = axes.xaxis.max; + r.ymin = axes.yaxis.min; + r.ymax = axes.yaxis.max; + + plot.stack.push(r); + + axes.xaxis.options.min = ranges.xaxis.from; + axes.xaxis.options.max = ranges.xaxis.to; + axes.yaxis.options.min = ranges.yaxis.from; + axes.yaxis.options.max = ranges.yaxis.to; + + plot.clearSelection(true); + + plot.setupGrid(); + plot.draw(); + + $(div).find(".zoomout").css("visibility", "visible"); + + if ( func !== undefined ) { func(plot, r); } + } + + function zoomStackOut(plot, func) { + var r = plot.stack.pop(); + var div = plot.getPlaceholder(); + + if ( plot.stack.length === 0 ) { + $(div).find(".zoomout").css("visibility", "hidden"); + } + + plot.getAxes().xaxis.options.min = r.xmin; + plot.getAxes().xaxis.options.max = r.xmax; + plot.getAxes().yaxis.options.min = r.ymin; + plot.getAxes().yaxis.options.max = r.ymax; + + plot.clearSelection(true); + + plot.setupGrid(); + plot.draw(); + + if ( func !== undefined ) { func(plot, r); } + } + + var enabled = 0; + + function zoomStack(plot, ctx) { + if ( enabled ) { + plot.stack = []; + var div = plot.getPlaceholder(); + var apath = JS9.InstallDir("images/4arrow.png"); + $(div).append("
    \ +
    "); + + $(div).bind("plotselected", function (event, ranges) { zoomStackIn (plot, event, ranges, options.zoomFunc); }); + $(div).find(".zoomout").click(function () { zoomStackOut(plot, options.zoomFunc); }); + + $(div).find(".zoomout").css("visibility", "hidden"); + + enabled = 0; + } + } + + function zoomOptions(plot, options) { + if ( options.zoomStack ) { + enabled = 1; + plot.hooks.drawOverlay.push(zoomStack); + } + } + + function init(plot) { + plot.hooks.processOptions.push(zoomOptions); + } + + var options = { + zoomStack: 0 + , zoomFunc: undefined + }; + + $.plot.plugins.push({ init: init, options: options, name: "zoomStack", version: 0.1 }); +}($)); + diff --git a/js/flot-zoom.min.js b/js/flot-zoom.min.js new file mode 100644 index 00000000..bd13a448 --- /dev/null +++ b/js/flot-zoom.min.js @@ -0,0 +1,3 @@ +(function(e){function f(a){if(h){a.stack=[];var b=a.getPlaceholder(),f=JS9.InstallDir("images/4arrow.png");e(b).append("
    \t\t\t\t
    ");e(b).bind("plotselected",function(b,c){var k=j.zoomFunc,d=a.getAxes(),f=a.getPlaceholder(),g={};g.xmin=d.xaxis.min;g.xmax=d.xaxis.max;g.ymin=d.yaxis.min;g.ymax=d.yaxis.max;a.stack.push(g);d.xaxis.options.min=c.xaxis.from; +d.xaxis.options.max=c.xaxis.to;d.yaxis.options.min=c.yaxis.from;d.yaxis.options.max=c.yaxis.to;a.clearSelection(!0);a.setupGrid();a.draw();e(f).find(".zoomout").css("visibility","visible");void 0!==k&&k(a,g)});e(b).find(".zoomout").click(function(){var b=j.zoomFunc,c=a.stack.pop(),f=a.getPlaceholder();0===a.stack.length&&e(f).find(".zoomout").css("visibility","hidden");a.getAxes().xaxis.options.min=c.xmin;a.getAxes().xaxis.options.max=c.xmax;a.getAxes().yaxis.options.min=c.ymin;a.getAxes().yaxis.options.max= +c.ymax;a.clearSelection(!0);a.setupGrid();a.draw();void 0!==b&&b(a,c)});e(b).find(".zoomout").css("visibility","hidden");h=0}}function l(a,b){b.zoomStack&&(h=1,a.hooks.drawOverlay.push(f))}var h=0,j={zoomStack:0,zoomFunc:void 0};e.plot.plugins.push({init:function(a){a.hooks.processOptions.push(l)},options:j,name:"zoomStack",version:0.1})})($); diff --git a/js/jquery-1.10.2.min.js b/js/jquery-1.10.2.min.js new file mode 100644 index 00000000..da417064 --- /dev/null +++ b/js/jquery-1.10.2.min.js @@ -0,0 +1,6 @@ +/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery-1.10.2.min.map +*/ +(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="
    ",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
    a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
    t
    ",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
    ",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t +}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); +u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("' + window.frames["_iframe-"+t.id].location.replace(contentsource) //set location of iframe window to specified URL + } + else if (contenttype=="ajax"){ + this.ajax_connect(contentsource, t) //populate window with external contents fetched via Ajax + } + t.contentarea.datatype=contenttype //store contenttype of current window for future reference +}, + +setupdrag:function(e){ + var d=dhtmlwindow //reference dhtml window object + var t=this._parent //reference dhtml window div + d.etarget=this //remember div mouse is currently held down on ("handle" or "resize" div) + var e=window.event || e + // d.initmousex=e.clientX //store x position of mouse onmousedown + // d.initmousey=e.clientY + if( e.touches && e.touches.length ){ + d.initmousex = e.touches[0].clientX; + d.initmousey = e.touches[0].clientY; + } else { + // mouse events + d.initmousex = e.clientX; + d.initmousey = e.clientY; + } + d.initx=parseInt(t.offsetLeft) //store offset x of window div onmousedown + d.inity=parseInt(t.offsetTop) + d.width=parseInt(t.offsetWidth) //store width of window div + d.contentheight=parseInt(t.contentarea.offsetHeight) //store height of window div's content div + if (t.contentarea.datatype=="iframe"){ //if content of this window div is "iframe" + t.style.backgroundColor="#F8F8F8" //colorize and hide content div (while window is being dragged) + t.contentarea.style.visibility="hidden" + } + document.onmousemove=d.getdistance //get distance travelled by mouse as it moves + document.ontouchmove=d.getdistance //get distance travelled by mouse as it moves + document.onmouseup=function(){ + if (t.contentarea.datatype=="iframe"){ //restore color and visibility of content div onmouseup + t.contentarea.style.backgroundColor="white" + t.contentarea.style.visibility="visible" + } + d.stop() + } + document.ontouchend=function(){ + if (t.contentarea.datatype=="iframe"){ //restore color and visibility of content div onmouseup + t.contentarea.style.backgroundColor="white" + t.contentarea.style.visibility="visible" + } + d.stop() + } + return false +}, + +getdistance:function(e){ + var d=dhtmlwindow + var etarget=d.etarget + var e=window.event || e + // d.distancex=e.clientX-d.initmousex //horizontal distance travelled relative to starting point + // d.distancey=e.clientY-d.initmousey + if( e.touches && e.touches.length ){ + d.distancex=e.touches[0].clientX-d.initmousex //horizontal distance travelled relative to starting point + d.distancey=e.touches[0].clientY-d.initmousey + } else { + // mouse events + d.distancex=e.clientX-d.initmousex //horizontal distance travelled relative to starting point + d.distancey=e.clientY-d.initmousey + } + if (etarget.className=="drag-handle") //if target element is "handle" div + d.move(etarget._parent, e) + else if (etarget.className=="drag-resizearea") //if target element is "resize" div + d.resize(etarget._parent, e) + return false //cancel default dragging behavior +}, + +getviewpoint:function(){ //get window viewpoint numbers + var ie=document.all && !window.opera + var domclientWidth=document.documentElement && parseInt(document.documentElement.clientWidth) || 100000 //Preliminary doc width in non IE browsers + this.standardbody=(document.compatMode=="CSS1Compat")? document.documentElement : document.body //create reference to common "body" across doctypes + this.scroll_top=(ie)? this.standardbody.scrollTop : window.pageYOffset + this.scroll_left=(ie)? this.standardbody.scrollLeft : window.pageXOffset + this.docwidth=(ie)? this.standardbody.clientWidth : (/Safari/i.test(navigator.userAgent))? window.innerWidth : Math.min(domclientWidth, window.innerWidth-16) + this.docheight=(ie)? this.standardbody.clientHeight: window.innerHeight +}, + +rememberattrs:function(t){ //remember certain attributes of the window when it's minimized or closed, such as dimensions, position on page + this.getviewpoint() //Get current window viewpoint numbers + t.lastx=parseInt((t.style.left || t.offsetLeft))-dhtmlwindow.scroll_left //store last known x coord of window just before minimizing + t.lasty=parseInt((t.style.top || t.offsetTop))-dhtmlwindow.scroll_top + t.lastwidth=parseInt(t.style.width) //store last known width of window just before minimizing/ closing +}, + +move:function(t, e){ + t.style.left=dhtmlwindow.distancex+dhtmlwindow.initx+"px" + t.style.top=dhtmlwindow.distancey+dhtmlwindow.inity+"px" +}, + +resize:function(t, e){ + t.style.width=Math.max(dhtmlwindow.width+dhtmlwindow.distancex, 150)+"px" + t.contentarea.style.height=Math.max(dhtmlwindow.contentheight+dhtmlwindow.distancey, 100)+"px" +}, + +enablecontrols:function(e){ + var d=dhtmlwindow + var sourceobj=window.event? window.event.srcElement : e.target //Get element within "handle" div mouse is currently on (the controls) + if (/Minimize/i.test(sourceobj.getAttribute("title"))) //if this is the "minimize" control + d.minimize(sourceobj, this._parent) + else if (/Restore/i.test(sourceobj.getAttribute("title"))) //if this is the "restore" control + d.restore(sourceobj, this._parent) + else if (/Close/i.test(sourceobj.getAttribute("title"))) //if this is the "close" control + d.close(this._parent) + return false +}, + +minimize:function(button, t){ + dhtmlwindow.rememberattrs(t) + button.setAttribute("src", dhtmlwindow.imagefiles[2]) + button.setAttribute("title", "Restore") + t.state="minimized" //indicate the state of the window as being "minimized" + t.contentarea.style.display="none" + t.statusarea.style.display="none" + if (typeof t.minimizeorder=="undefined"){ //stack order of minmized window on screen relative to any other minimized windows + dhtmlwindow.minimizeorder++ //increment order + t.minimizeorder=dhtmlwindow.minimizeorder + } + t.style.left="10px" //left coord of minmized window + t.style.width="200px" + var windowspacing=t.minimizeorder*10 //spacing (gap) between each minmized window(s) + t.style.top=dhtmlwindow.scroll_top+dhtmlwindow.docheight-(t.handle.offsetHeight*t.minimizeorder)-windowspacing+"px" +}, + +restore:function(button, t){ + dhtmlwindow.getviewpoint() + button.setAttribute("src", dhtmlwindow.imagefiles[0]) + button.setAttribute("title", "Minimize") + t.state="fullview" //indicate the state of the window as being "fullview" + t.style.display="block" + t.contentarea.style.display="block" + if (t.resizeBool) //if this window is resizable, enable the resize icon + t.statusarea.style.display="block" + t.style.left=parseInt(t.lastx)+dhtmlwindow.scroll_left+"px" //position window to last known x coord just before minimizing + t.style.top=parseInt(t.lasty)+dhtmlwindow.scroll_top+"px" + t.style.width=parseInt(t.lastwidth)+"px" +}, + + +close:function(t){ + try{ + var closewinbol=t.onclose() + } + catch(err){ //In non IE browsers, all errors are caught, so just run the below + var closewinbol=true + } + finally{ //In IE, not all errors are caught, so check if variable isn't defined in IE in those cases + if (typeof closewinbol=="undefined"){ + alert("An error has occured somwhere inside your \"onclose\" event handler") + var closewinbol=true + } + } + if (closewinbol){ //if custom event handler function returns true + if (t.state!="minimized") //if this window isn't currently minimized + dhtmlwindow.rememberattrs(t) //remember window's dimensions/position on the page before closing + if (window.frames["_iframe-"+t.id]) //if this is an IFRAME DHTML window + window.frames["_iframe-"+t.id].location.replace("about:blank") + else + t.contentarea.innerHTML="" + t.style.display="none" + t.isClosed=true //tell script this window is closed (for detection in t.show()) + } + return closewinbol +}, + + +setopacity:function(targetobject, value){ //Sets the opacity of targetobject based on the passed in value setting (0 to 1 and in between) + if (!targetobject) + return + if (targetobject.filters && targetobject.filters[0]){ //IE syntax + if (typeof targetobject.filters[0].opacity=="number") //IE6 + targetobject.filters[0].opacity=value*100 + else //IE 5.5 + targetobject.style.filter="alpha(opacity="+value*100+")" + } + else if (typeof targetobject.style.MozOpacity!="undefined") //Old Mozilla syntax + targetobject.style.MozOpacity=value + else if (typeof targetobject.style.opacity!="undefined") //Standard opacity syntax + targetobject.style.opacity=value +}, + +setfocus:function(t){ //Sets focus to the currently active window + this.zIndexvalue++ + t.style.zIndex=this.zIndexvalue + t.isClosed=false //tell script this window isn't closed (for detection in t.show()) + this.setopacity(this.lastactivet.handle, 0.5) //unfocus last active window + this.setopacity(t.handle, 1) //focus currently active window + this.lastactivet=t //remember last active window +}, + + +show:function(t){ + if (t.isClosed){ + alert("DHTML Window has been closed, so nothing to show. Open/Create the window again.") + return + } + if (t.lastx) //If there exists previously stored information such as last x position on window attributes (meaning it's been minimized or closed) + dhtmlwindow.restore(t.controls.firstChild, t) //restore the window using that info + else + t.style.display="block" + this.setfocus(t) + t.state="fullview" //indicate the state of the window as being "fullview" +}, + +hide:function(t){ + t.style.display="none" +}, + +ajax_connect:function(url, t){ + var page_request = false + var bustcacheparameter="" + if (window.XMLHttpRequest) // if Mozilla, IE7, Safari etc + page_request = new XMLHttpRequest() + else if (window.ActiveXObject){ // if IE6 or below + try { + page_request = new ActiveXObject("Msxml2.XMLHTTP") + } + catch (e){ + try{ + page_request = new ActiveXObject("Microsoft.XMLHTTP") + } + catch (e){} + } + } + else + return false + t.contentarea.innerHTML=this.ajaxloadinghtml + page_request.onreadystatechange=function(){dhtmlwindow.ajax_loadpage(page_request, t)} + if (this.ajaxbustcache) //if bust caching of external page + bustcacheparameter=(url.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime() + page_request.open('GET', url+bustcacheparameter, true) + page_request.send(null) +}, + +ajax_loadpage:function(page_request, t){ + if (page_request.readyState == 4 && (page_request.status==200 || window.location.href.indexOf("http")==-1)){ + t.contentarea.innerHTML=page_request.responseText + } +}, + + +stop:function(){ + dhtmlwindow.etarget=null //clean up + document.onmousemove=null + document.ontouchmove=null + document.onmouseup=null + document.ontouchend=null +}, + +addEvent:function(target, functionref, tasktype){ //assign a function to execute to an event handler (ie: onunload) + var tasktype=(window.addEventListener)? tasktype : "on"+tasktype + if (target.addEventListener) + target.addEventListener(tasktype, functionref, false) + else if (target.attachEvent) + target.attachEvent(tasktype, functionref) +}, + +cleanup:function(){ + for (var i=0; i.') //container that holds all dhtml window divs on page +window.onunload=dhtmlwindow.cleanup + /*********************************************** + * DHTML Window Widget- © Dynamic Drive (www.dynamicdrive.com) + * This notice must stay intact for legal use. + * Visit http://www.dynamicdrive.com/ for full source code + ***********************************************/ +/* build: `node build.js modules=ALL exclude=gestures,cufon,json minifier=uglifyjs` */ +/*! Fabric.js Copyright 2008-2014, Printio (Juriy Zaytsev, Maxim Chernyak) */ + +var fabric = fabric || { version: "1.4.11" }; +if (typeof exports !== 'undefined') { + exports.fabric = fabric; +} + +if (typeof document !== 'undefined' && typeof window !== 'undefined') { + fabric.document = document; + fabric.window = window; +} +else { + // assume we're running under node.js when document/window are not present + fabric.document = require("jsdom") + .jsdom(""); + + fabric.window = fabric.document.createWindow(); +} + +/** + * True when in environment that supports touch events + * @type boolean + */ +fabric.isTouchSupported = "ontouchstart" in fabric.document.documentElement; + +/** + * True when in environment that's probably Node.js + * @type boolean + */ +fabric.isLikelyNode = typeof Buffer !== 'undefined' && + typeof window === 'undefined'; + + +/** + * Attributes parsed from all SVG elements + * @type array + */ +fabric.SHARED_ATTRIBUTES = [ + "display", + "transform", + "fill", "fill-opacity", "fill-rule", + "opacity", + "stroke", "stroke-dasharray", "stroke-linecap", + "stroke-linejoin", "stroke-miterlimit", + "stroke-opacity", "stroke-width" +]; + +/** + * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion. + */ +fabric.DPI = 96; + + +(function(){ + + /** + * @private + * @param {String} eventName + * @param {Function} handler + */ + function _removeEventListener(eventName, handler) { + if (!this.__eventListeners[eventName]) { + return; + } + + if (handler) { + fabric.util.removeFromArray(this.__eventListeners[eventName], handler); + } + else { + this.__eventListeners[eventName].length = 0; + } + } + + /** + * Observes specified event + * @deprecated `observe` deprecated since 0.8.34 (use `on` instead) + * @memberOf fabric.Observable + * @alias on + * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler}) + * @param {Function} handler Function that receives a notification when an event of the specified type occurs + * @return {Self} thisArg + * @chainable + */ + function observe(eventName, handler) { + if (!this.__eventListeners) { + this.__eventListeners = { }; + } + // one object with key/value pairs was passed + if (arguments.length === 1) { + for (var prop in eventName) { + this.on(prop, eventName[prop]); + } + } + else { + if (!this.__eventListeners[eventName]) { + this.__eventListeners[eventName] = [ ]; + } + this.__eventListeners[eventName].push(handler); + } + return this; + } + + /** + * Stops event observing for a particular event handler. Calling this method + * without arguments removes all handlers for all events + * @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead) + * @memberOf fabric.Observable + * @alias off + * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler}) + * @param {Function} handler Function to be deleted from EventListeners + * @return {Self} thisArg + * @chainable + */ + function stopObserving(eventName, handler) { + if (!this.__eventListeners) { + return; + } + + // remove all key/value pairs (event name -> event handler) + if (arguments.length === 0) { + this.__eventListeners = { }; + } + // one object with key/value pairs was passed + else if (arguments.length === 1 && typeof arguments[0] === 'object') { + for (var prop in eventName) { + _removeEventListener.call(this, prop, eventName[prop]); + } + } + else { + _removeEventListener.call(this, eventName, handler); + } + return this; + } + + /** + * Fires event with an optional options object + * @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead) + * @memberOf fabric.Observable + * @alias trigger + * @param {String} eventName Event name to fire + * @param {Object} [options] Options object + * @return {Self} thisArg + * @chainable + */ + function fire(eventName, options) { + if (!this.__eventListeners) { + return; + } + + var listenersForEvent = this.__eventListeners[eventName]; + if (!listenersForEvent) { + return; + } + + for (var i = 0, len = listenersForEvent.length; i < len; i++) { + // avoiding try/catch for perf. reasons + listenersForEvent[i].call(this, options || { }); + } + return this; + } + + /** + * @namespace fabric.Observable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#events} + * @see {@link http://fabricjs.com/events/|Events demo} + */ + fabric.Observable = { + observe: observe, + stopObserving: stopObserving, + fire: fire, + + on: observe, + off: stopObserving, + trigger: fire + }; +})(); + + +/** + * @namespace fabric.Collection + */ +fabric.Collection = { + + /** + * Adds objects to collection, then renders canvas (if `renderOnAddRemove` is not `false`) + * Objects should be instances of (or inherit from) fabric.Object + * @param {...fabric.Object} object Zero or more fabric instances + * @return {Self} thisArg + */ + add: function () { + this._objects.push.apply(this._objects, arguments); + for (var i = 0, length = arguments.length; i < length; i++) { + this._onObjectAdded(arguments[i]); + } + this.renderOnAddRemove && this.renderAll(); + return this; + }, + + /** + * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`) + * An object should be an instance of (or inherit from) fabric.Object + * @param {Object} object Object to insert + * @param {Number} index Index to insert object at + * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs + * @return {Self} thisArg + * @chainable + */ + insertAt: function (object, index, nonSplicing) { + var objects = this.getObjects(); + if (nonSplicing) { + objects[index] = object; + } + else { + objects.splice(index, 0, object); + } + this._onObjectAdded(object); + this.renderOnAddRemove && this.renderAll(); + return this; + }, + + /** + * Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`) + * @param {...fabric.Object} object Zero or more fabric instances + * @return {Self} thisArg + * @chainable + */ + remove: function() { + var objects = this.getObjects(), + index; + + for (var i = 0, length = arguments.length; i < length; i++) { + index = objects.indexOf(arguments[i]); + + // only call onObjectRemoved if an object was actually removed + if (index !== -1) { + objects.splice(index, 1); + this._onObjectRemoved(arguments[i]); + } + } + + this.renderOnAddRemove && this.renderAll(); + return this; + }, + + /** + * Executes given function for each object in this group + * @param {Function} callback + * Callback invoked with current object as first argument, + * index - as second and an array of all objects - as third. + * Iteration happens in reverse order (for performance reasons). + * Callback is invoked in a context of Global Object (e.g. `window`) + * when no `context` argument is given + * + * @param {Object} context Context (aka thisObject) + * @return {Self} thisArg + */ + forEachObject: function(callback, context) { + var objects = this.getObjects(), + i = objects.length; + while (i--) { + callback.call(context, objects[i], i, objects); + } + return this; + }, + + /** + * Returns an array of children objects of this instance + * Type parameter introduced in 1.3.10 + * @param {String} [type] When specified, only objects of this type are returned + * @return {Array} + */ + getObjects: function(type) { + if (typeof type === 'undefined') { + return this._objects; + } + return this._objects.filter(function(o) { + return o.type === type; + }); + }, + + /** + * Returns object at specified index + * @param {Number} index + * @return {Self} thisArg + */ + item: function (index) { + return this.getObjects()[index]; + }, + + /** + * Returns true if collection contains no objects + * @return {Boolean} true if collection is empty + */ + isEmpty: function () { + return this.getObjects().length === 0; + }, + + /** + * Returns a size of a collection (i.e: length of an array containing its objects) + * @return {Number} Collection size + */ + size: function() { + return this.getObjects().length; + }, + + /** + * Returns true if collection contains an object + * @param {Object} object Object to check against + * @return {Boolean} `true` if collection contains an object + */ + contains: function(object) { + return this.getObjects().indexOf(object) > -1; + }, + + /** + * Returns number representation of a collection complexity + * @return {Number} complexity + */ + complexity: function () { + return this.getObjects().reduce(function (memo, current) { + memo += current.complexity ? current.complexity() : 0; + return memo; + }, 0); + } +}; + + +(function(global) { + + var sqrt = Math.sqrt, + atan2 = Math.atan2, + PiBy180 = Math.PI / 180; + + /** + * @namespace fabric.util + */ + fabric.util = { + + /** + * Removes value from an array. + * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf` + * @static + * @memberOf fabric.util + * @param {Array} array + * @param {Any} value + * @return {Array} original array + */ + removeFromArray: function(array, value) { + var idx = array.indexOf(value); + if (idx !== -1) { + array.splice(idx, 1); + } + return array; + }, + + /** + * Returns random number between 2 specified ones. + * @static + * @memberOf fabric.util + * @param {Number} min lower limit + * @param {Number} max upper limit + * @return {Number} random value (between min and max) + */ + getRandomInt: function(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + }, + + /** + * Transforms degrees to radians. + * @static + * @memberOf fabric.util + * @param {Number} degrees value in degrees + * @return {Number} value in radians + */ + degreesToRadians: function(degrees) { + return degrees * PiBy180; + }, + + /** + * Transforms radians to degrees. + * @static + * @memberOf fabric.util + * @param {Number} radians value in radians + * @return {Number} value in degrees + */ + radiansToDegrees: function(radians) { + return radians / PiBy180; + }, + + /** + * Rotates `point` around `origin` with `radians` + * @static + * @memberOf fabric.util + * @param {fabric.Point} point The point to rotate + * @param {fabric.Point} origin The origin of the rotation + * @param {Number} radians The radians of the angle for the rotation + * @return {fabric.Point} The new rotated point + */ + rotatePoint: function(point, origin, radians) { + var sin = Math.sin(radians), + cos = Math.cos(radians); + + point.subtractEquals(origin); + + var rx = point.x * cos - point.y * sin, + ry = point.x * sin + point.y * cos; + + return new fabric.Point(rx, ry).addEquals(origin); + }, + + /** + * Apply transform t to point p + * @static + * @memberOf fabric.util + * @param {fabric.Point} p The point to transform + * @param {Array} t The transform + * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied + * @return {fabric.Point} The transformed point + */ + transformPoint: function(p, t, ignoreOffset) { + if (ignoreOffset) { + return new fabric.Point( + t[0] * p.x + t[1] * p.y, + t[2] * p.x + t[3] * p.y + ); + } + return new fabric.Point( + t[0] * p.x + t[1] * p.y + t[4], + t[2] * p.x + t[3] * p.y + t[5] + ); + }, + + /** + * Invert transformation t + * @static + * @memberOf fabric.util + * @param {Array} t The transform + * @return {Array} The inverted transform + */ + invertTransform: function(t) { + var r = t.slice(), + a = 1 / (t[0] * t[3] - t[1] * t[2]); + r = [a * t[3], -a * t[1], -a * t[2], a * t[0], 0, 0]; + var o = fabric.util.transformPoint({ x: t[4], y: t[5] }, r); + r[4] = -o.x; + r[5] = -o.y; + return r; + }, + + /** + * A wrapper around Number#toFixed, which contrary to native method returns number, not string. + * @static + * @memberOf fabric.util + * @param {Number|String} number number to operate on + * @param {Number} fractionDigits number of fraction digits to "leave" + * @return {Number} + */ + toFixed: function(number, fractionDigits) { + return parseFloat(Number(number).toFixed(fractionDigits)); + }, + + /** + * Converts from attribute value to pixel value if applicable. + * Returns converted pixels or original value not converted. + * @param {Number|String} value number to operate on + * @return {Number|String} + */ + parseUnit: function(value) { + var unit = /\D{0,2}$/.exec(value), + number = parseFloat(value); + + switch (unit[0]) { + case 'mm': + return number * fabric.DPI / 25.4; + + case 'cm': + return number * fabric.DPI / 2.54; + + case 'in': + return number * fabric.DPI; + + case 'pt': + return number * fabric.DPI / 72; // or * 4 / 3 + + case 'pc': + return number * fabric.DPI / 72 * 12; // or * 16 + + default: + return number; + } + }, + + /** + * Function which always returns `false`. + * @static + * @memberOf fabric.util + * @return {Boolean} + */ + falseFunction: function() { + return false; + }, + + /** + * Returns klass "Class" object of given namespace + * @memberOf fabric.util + * @param {String} type Type of object (eg. 'circle') + * @param {String} namespace Namespace to get klass "Class" object from + * @return {Object} klass "Class" + */ + getKlass: function(type, namespace) { + // capitalize first letter only + type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1)); + return fabric.util.resolveNamespace(namespace)[type]; + }, + + /** + * Returns object of given namespace + * @memberOf fabric.util + * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric' + * @return {Object} Object for given namespace (default fabric) + */ + resolveNamespace: function(namespace) { + if (!namespace) { + return fabric; + } + + var parts = namespace.split('.'), + len = parts.length, + obj = global || fabric.window; + + for (var i = 0; i < len; ++i) { + obj = obj[parts[i]]; + } + + return obj; + }, + + /** + * Loads image element from given url and passes it to a callback + * @memberOf fabric.util + * @param {String} url URL representing an image + * @param {Function} callback Callback; invoked with loaded image + * @param {Any} [context] Context to invoke callback in + * @param {Object} [crossOrigin] crossOrigin value to set image element to + */ + loadImage: function(url, callback, context, crossOrigin) { + if (!url) { + callback && callback.call(context, url); + return; + } + + var img = fabric.util.createImage(); + + /** @ignore */ + img.onload = function () { + callback && callback.call(context, img); + img = img.onload = img.onerror = null; + }; + + /** @ignore */ + img.onerror = function() { + fabric.log('Error loading ' + img.src); + callback && callback.call(context, null, true); + img = img.onload = img.onerror = null; + }; + + // data-urls appear to be buggy with crossOrigin + // https://github.com/kangax/fabric.js/commit/d0abb90f1cd5c5ef9d2a94d3fb21a22330da3e0a#commitcomment-4513767 + // see https://code.google.com/p/chromium/issues/detail?id=315152 + // https://bugzilla.mozilla.org/show_bug.cgi?id=935069 + if (url.indexOf('data') !== 0 && typeof crossOrigin !== 'undefined') { + img.crossOrigin = crossOrigin; + } + + img.src = url; + }, + + /** + * Creates corresponding fabric instances from their object representations + * @static + * @memberOf fabric.util + * @param {Array} objects Objects to enliven + * @param {Function} callback Callback to invoke when all objects are created + * @param {String} namespace Namespace to get klass "Class" object from + * @param {Function} reviver Method for further parsing of object elements, + * called after each fabric object created. + */ + enlivenObjects: function(objects, callback, namespace, reviver) { + objects = objects || [ ]; + + function onLoaded() { + if (++numLoadedObjects === numTotalObjects) { + callback && callback(enlivenedObjects); + } + } + + var enlivenedObjects = [ ], + numLoadedObjects = 0, + numTotalObjects = objects.length; + + if (!numTotalObjects) { + callback && callback(enlivenedObjects); + return; + } + + objects.forEach(function (o, index) { + // if sparse array + if (!o || !o.type) { + onLoaded(); + return; + } + var klass = fabric.util.getKlass(o.type, namespace); + if (klass.async) { + klass.fromObject(o, function (obj, error) { + if (!error) { + enlivenedObjects[index] = obj; + reviver && reviver(o, enlivenedObjects[index]); + } + onLoaded(); + }); + } + else { + enlivenedObjects[index] = klass.fromObject(o); + reviver && reviver(o, enlivenedObjects[index]); + onLoaded(); + } + }); + }, + + /** + * Groups SVG elements (usually those retrieved from SVG document) + * @static + * @memberOf fabric.util + * @param {Array} elements SVG elements to group + * @param {Object} [options] Options object + * @return {fabric.Object|fabric.PathGroup} + */ + groupSVGElements: function(elements, options, path) { + var object; + + object = new fabric.PathGroup(elements, options); + + if (typeof path !== 'undefined') { + object.setSourcePath(path); + } + return object; + }, + + /** + * Populates an object with properties of another object + * @static + * @memberOf fabric.util + * @param {Object} source Source object + * @param {Object} destination Destination object + * @return {Array} properties Propertie names to include + */ + populateWithProperties: function(source, destination, properties) { + if (properties && Object.prototype.toString.call(properties) === '[object Array]') { + for (var i = 0, len = properties.length; i < len; i++) { + if (properties[i] in source) { + destination[properties[i]] = source[properties[i]]; + } + } + } + }, + + /** + * Draws a dashed line between two points + * + * This method is used to draw dashed line around selection area. + * See dotted stroke in canvas + * + * @param {CanvasRenderingContext2D} ctx context + * @param {Number} x start x coordinate + * @param {Number} y start y coordinate + * @param {Number} x2 end x coordinate + * @param {Number} y2 end y coordinate + * @param {Array} da dash array pattern + */ + drawDashedLine: function(ctx, x, y, x2, y2, da) { + var dx = x2 - x, + dy = y2 - y, + len = sqrt(dx * dx + dy * dy), + rot = atan2(dy, dx), + dc = da.length, + di = 0, + draw = true; + + ctx.save(); + ctx.translate(x, y); + ctx.moveTo(0, 0); + ctx.rotate(rot); + + x = 0; + while (len > x) { + x += da[di++ % dc]; + if (x > len) { + x = len; + } + ctx[draw ? 'lineTo' : 'moveTo'](x, 0); + draw = !draw; + } + + ctx.restore(); + }, + + /** + * Creates canvas element and initializes it via excanvas if necessary + * @static + * @memberOf fabric.util + * @param {CanvasElement} [canvasEl] optional canvas element to initialize; + * when not given, element is created implicitly + * @return {CanvasElement} initialized canvas element + */ + createCanvasElement: function(canvasEl) { + canvasEl || (canvasEl = fabric.document.createElement('canvas')); + //jscs:disable requireCamelCaseOrUpperCaseIdentifiers + if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') { + G_vmlCanvasManager.initElement(canvasEl); + } + //jscs:enable requireCamelCaseOrUpperCaseIdentifiers + return canvasEl; + }, + + /** + * Creates image element (works on client and node) + * @static + * @memberOf fabric.util + * @return {HTMLImageElement} HTML image element + */ + createImage: function() { + return fabric.isLikelyNode + ? new (require('canvas').Image)() + : fabric.document.createElement('img'); + }, + + /** + * Creates accessors (getXXX, setXXX) for a "class", based on "stateProperties" array + * @static + * @memberOf fabric.util + * @param {Object} klass "Class" to create accessors for + */ + createAccessors: function(klass) { + var proto = klass.prototype; + + for (var i = proto.stateProperties.length; i--; ) { + + var propName = proto.stateProperties[i], + capitalizedPropName = propName.charAt(0).toUpperCase() + propName.slice(1), + setterName = 'set' + capitalizedPropName, + getterName = 'get' + capitalizedPropName; + + // using `new Function` for better introspection + if (!proto[getterName]) { + proto[getterName] = (function(property) { + return new Function('return this.get("' + property + '")'); + })(propName); + } + if (!proto[setterName]) { + proto[setterName] = (function(property) { + return new Function('value', 'return this.set("' + property + '", value)'); + })(propName); + } + } + }, + + /** + * @static + * @memberOf fabric.util + * @param {fabric.Object} receiver Object implementing `clipTo` method + * @param {CanvasRenderingContext2D} ctx Context to clip + */ + clipContext: function(receiver, ctx) { + ctx.save(); + ctx.beginPath(); + receiver.clipTo(ctx); + ctx.clip(); + }, + + /** + * Multiply matrix A by matrix B to nest transformations + * @static + * @memberOf fabric.util + * @param {Array} matrixA First transformMatrix + * @param {Array} matrixB Second transformMatrix + * @return {Array} The product of the two transform matrices + */ + multiplyTransformMatrices: function(matrixA, matrixB) { + // Matrix multiply matrixA * matrixB + var a = [ + [matrixA[0], matrixA[2], matrixA[4]], + [matrixA[1], matrixA[3], matrixA[5]], + [0, 0, 1 ] + ], + + b = [ + [matrixB[0], matrixB[2], matrixB[4]], + [matrixB[1], matrixB[3], matrixB[5]], + [0, 0, 1 ] + ], + + result = []; + + for (var r = 0; r < 3; r++) { + result[r] = []; + for (var c = 0; c < 3; c++) { + var sum = 0; + for (var k = 0; k < 3; k++) { + sum += a[r][k] * b[k][c]; + } + + result[r][c] = sum; + } + } + + return [ + result[0][0], + result[1][0], + result[0][1], + result[1][1], + result[0][2], + result[1][2] + ]; + }, + + /** + * Returns string representation of function body + * @param {Function} fn Function to get body of + * @return {String} Function body + */ + getFunctionBody: function(fn) { + return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1]; + }, + + /** + * Returns true if context has transparent pixel + * at specified location (taking tolerance into account) + * @param {CanvasRenderingContext2D} ctx context + * @param {Number} x x coordinate + * @param {Number} y y coordinate + * @param {Number} tolerance Tolerance + */ + isTransparent: function(ctx, x, y, tolerance) { + + // If tolerance is > 0 adjust start coords to take into account. + // If moves off Canvas fix to 0 + if (tolerance > 0) { + if (x > tolerance) { + x -= tolerance; + } + else { + x = 0; + } + if (y > tolerance) { + y -= tolerance; + } + else { + y = 0; + } + } + + var _isTransparent = true, + imageData = ctx.getImageData(x, y, (tolerance * 2) || 1, (tolerance * 2) || 1); + + // Split image data - for tolerance > 1, pixelDataSize = 4; + for (var i = 3, l = imageData.data.length; i < l; i += 4) { + var temp = imageData.data[i]; + _isTransparent = temp <= 0; + if (_isTransparent === false) { + break; // Stop if colour found + } + } + + imageData = null; + + return _isTransparent; + } + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + var arcToSegmentsCache = { }, + segmentToBezierCache = { }, + _join = Array.prototype.join; + + /* Adapted from http://dxr.mozilla.org/mozilla-central/source/content/svg/content/src/nsSVGPathDataParser.cpp + * by Andrea Bogazzi code is under MPL. if you don't have a copy of the license you can take it here + * http://mozilla.org/MPL/2.0/ + */ + function arcToSegments(toX, toY, rx, ry, large, sweep, rotateX) { + var argsString = _join.call(arguments); + if (arcToSegmentsCache[argsString]) { + return arcToSegmentsCache[argsString]; + } + + var PI = Math.PI, th = rotateX * (PI / 180), + sinTh = Math.sin(th), + cosTh = Math.cos(th), + fromX = 0, fromY = 0; + + rx = Math.abs(rx); + ry = Math.abs(ry); + + var px = -cosTh * toX - sinTh * toY, + py = -cosTh * toY + sinTh * toX, + rx2 = rx * rx, ry2 = ry * ry, py2 = py * py, px2 = px * px, + pl = 4 * rx2 * ry2 - rx2 * py2 - ry2 * px2, + root = 0; + + if (pl < 0) { + var s = Math.sqrt(1 - 0.25 * pl/(rx2 * ry2)); + rx *= s; + ry *= s; + } else { + root = (large === sweep ? -0.5 : 0.5) * + Math.sqrt( pl /(rx2 * py2 + ry2 * px2)); + } + + var cx = root * rx * py / ry, + cy = -root * ry * px / rx, + cx1 = cosTh * cx - sinTh * cy + toX / 2, + cy1 = sinTh * cx + cosTh * cy + toY / 2, + mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry), + dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px -cx) / rx, (-py -cy) / ry); + + if (sweep === 0 && dtheta > 0) { + dtheta -= 2 * PI; + } else if (sweep === 1 && dtheta < 0) { + dtheta += 2 * PI; + } + + // Convert into cubic bezier segments <= 90deg + var segments = Math.ceil(Math.abs(dtheta / (PI * 0.5))), + result = [], mDelta = dtheta / segments, + mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2), + th3 = mTheta + mDelta; + + for (var i = 0; i < segments; i++) { + result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY); + fromX = result[i][4]; + fromY = result[i][5]; + mTheta += mDelta; + th3 += mDelta; + } + arcToSegmentsCache[argsString] = result; + return result; + } + + function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) { + var argsString2 = _join.call(arguments); + if (segmentToBezierCache[argsString2]) { + return segmentToBezierCache[argsString2]; + } + + var costh2 = Math.cos(th2), + sinth2 = Math.sin(th2), + costh3 = Math.cos(th3), + sinth3 = Math.sin(th3), + toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1, + toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1, + cp1X = fromX + mT * ( - cosTh * rx * sinth2 - sinTh * ry * costh2), + cp1Y = fromY + mT * ( - sinTh * rx * sinth2 + cosTh * ry * costh2), + cp2X = toX + mT * ( cosTh * rx * sinth3 + sinTh * ry * costh3), + cp2Y = toY + mT * ( sinTh * rx * sinth3 - cosTh * ry * costh3); + + segmentToBezierCache[argsString2] = [ + cp1X, cp1Y, + cp2X, cp2Y, + toX, toY + ]; + return segmentToBezierCache[argsString2]; + } + + /* + * Private + */ + function calcVectorAngle(ux, uy, vx, vy) { + var ta = Math.atan2(uy, ux), + tb = Math.atan2(vy, vx); + if (tb >= ta) { + return tb - ta; + } else { + return 2 * Math.PI - (ta - tb); + } + } + + /** + * Draws arc + * @param {CanvasRenderingContext2D} ctx + * @param {Number} x + * @param {Number} y + * @param {Array} coords + */ + fabric.util.drawArc = function(ctx, fx, fy, coords) { + var rx = coords[0], + ry = coords[1], + rot = coords[2], + large = coords[3], + sweep = coords[4], + tx = coords[5], + ty = coords[6], + segs = [[ ], [ ], [ ], [ ]], + segs_norm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot); + for (var i = 0; i < segs_norm.length; i++) { + segs[i][0] = segs_norm[i][0] + fx; + segs[i][1] = segs_norm[i][1] + fy; + segs[i][2] = segs_norm[i][2] + fx; + segs[i][3] = segs_norm[i][3] + fy; + segs[i][4] = segs_norm[i][4] + fx; + segs[i][5] = segs_norm[i][5] + fy; + ctx.bezierCurveTo.apply(ctx, segs[i]); + } + }; +})(); + + +(function() { + + var slice = Array.prototype.slice; + + /* _ES5_COMPAT_START_ */ + + if (!Array.prototype.indexOf) { + /** + * Finds index of an element in an array + * @param {Any} searchElement + * @param {Number} [fromIndex] + * @return {Number} + */ + Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) { + if (this === void 0 || this === null) { + throw new TypeError(); + } + var t = Object(this), len = t.length >>> 0; + if (len === 0) { + return -1; + } + var n = 0; + if (arguments.length > 0) { + n = Number(arguments[1]); + if (n !== n) { // shortcut for verifying if it's NaN + n = 0; + } + else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + } + if (n >= len) { + return -1; + } + var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); + for (; k < len; k++) { + if (k in t && t[k] === searchElement) { + return k; + } + } + return -1; + }; + } + + if (!Array.prototype.forEach) { + /** + * Iterates an array, invoking callback for each element + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.forEach = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + fn.call(context, this[i], i, this); + } + } + }; + } + + if (!Array.prototype.map) { + /** + * Returns a result of iterating over an array, invoking callback for each element + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.map = function(fn, context) { + var result = [ ]; + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + result[i] = fn.call(context, this[i], i, this); + } + } + return result; + }; + } + + if (!Array.prototype.every) { + /** + * Returns true if a callback returns truthy value for all elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Boolean} + */ + Array.prototype.every = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this && !fn.call(context, this[i], i, this)) { + return false; + } + } + return true; + }; + } + + if (!Array.prototype.some) { + /** + * Returns true if a callback returns truthy value for at least one element in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Boolean} + */ + Array.prototype.some = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this && fn.call(context, this[i], i, this)) { + return true; + } + } + return false; + }; + } + + if (!Array.prototype.filter) { + /** + * Returns the result of iterating over elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [context] Context to invoke callback in + * @return {Array} + */ + Array.prototype.filter = function(fn, context) { + var result = [ ], val; + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + val = this[i]; // in case fn mutates this + if (fn.call(context, val, i, this)) { + result.push(val); + } + } + } + return result; + }; + } + + if (!Array.prototype.reduce) { + /** + * Returns "folded" (reduced) result of iterating over elements in an array + * @param {Function} fn Callback to invoke for each element + * @param {Object} [initial] Object to use as the first argument to the first call of the callback + * @return {Any} + */ + Array.prototype.reduce = function(fn /*, initial*/) { + var len = this.length >>> 0, + i = 0, + rv; + + if (arguments.length > 1) { + rv = arguments[1]; + } + else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) { + throw new TypeError(); + } + } + while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fn.call(null, rv, this[i], i, this); + } + } + return rv; + }; + } + + /* _ES5_COMPAT_END_ */ + + /** + * Invokes method on all items in a given array + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} method Name of a method to invoke + * @return {Array} + */ + function invoke(array, method) { + var args = slice.call(arguments, 2), result = [ ]; + for (var i = 0, len = array.length; i < len; i++) { + result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]); + } + return result; + } + + /** + * Finds maximum value in array (not necessarily "first" one) + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} byProperty + * @return {Any} + */ + function max(array, byProperty) { + return find(array, byProperty, function(value1, value2) { + return value1 >= value2; + }); + } + + /** + * Finds minimum value in array (not necessarily "first" one) + * @memberOf fabric.util.array + * @param {Array} array Array to iterate over + * @param {String} byProperty + * @return {Any} + */ + function min(array, byProperty) { + return find(array, byProperty, function(value1, value2) { + return value1 < value2; + }); + } + + /** + * @private + */ + function find(array, byProperty, condition) { + if (!array || array.length === 0) { + return; + } + + var i = array.length - 1, + result = byProperty ? array[i][byProperty] : array[i]; + if (byProperty) { + while (i--) { + if (condition(array[i][byProperty], result)) { + result = array[i][byProperty]; + } + } + } + else { + while (i--) { + if (condition(array[i], result)) { + result = array[i]; + } + } + } + return result; + } + + /** + * @namespace fabric.util.array + */ + fabric.util.array = { + invoke: invoke, + min: min, + max: max + }; + +})(); + + +(function(){ + + /** + * Copies all enumerable properties of one object to another + * @memberOf fabric.util.object + * @param {Object} destination Where to copy to + * @param {Object} source Where to copy from + * @return {Object} + */ + function extend(destination, source) { + // JScript DontEnum bug is not taken care of + for (var property in source) { + destination[property] = source[property]; + } + return destination; + } + + /** + * Creates an empty object and copies all enumerable properties of another object to it + * @memberOf fabric.util.object + * @param {Object} object Object to clone + * @return {Object} + */ + function clone(object) { + return extend({ }, object); + } + + /** @namespace fabric.util.object */ + fabric.util.object = { + extend: extend, + clone: clone + }; + +})(); + + +(function() { + + /* _ES5_COMPAT_START_ */ + if (!String.prototype.trim) { + /** + * Trims a string (removing whitespace from the beginning and the end) + * @function external:String#trim + * @see String#trim on MDN + */ + String.prototype.trim = function () { + // this trim is not fully ES3 or ES5 compliant, but it should cover most cases for now + return this.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, ''); + }; + } + /* _ES5_COMPAT_END_ */ + + /** + * Camelizes a string + * @memberOf fabric.util.string + * @param {String} string String to camelize + * @return {String} Camelized version of a string + */ + function camelize(string) { + return string.replace(/-+(.)?/g, function(match, character) { + return character ? character.toUpperCase() : ''; + }); + } + + /** + * Capitalizes a string + * @memberOf fabric.util.string + * @param {String} string String to capitalize + * @param {Boolean} [firstLetterOnly] If true only first letter is capitalized + * and other letters stay untouched, if false first letter is capitalized + * and other letters are converted to lowercase. + * @return {String} Capitalized version of a string + */ + function capitalize(string, firstLetterOnly) { + return string.charAt(0).toUpperCase() + + (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()); + } + + /** + * Escapes XML in a string + * @memberOf fabric.util.string + * @param {String} string String to escape + * @return {String} Escaped version of a string + */ + function escapeXml(string) { + return string.replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + } + + /** + * String utilities + * @namespace fabric.util.string + */ + fabric.util.string = { + camelize: camelize, + capitalize: capitalize, + escapeXml: escapeXml + }; +}()); + + +/* _ES5_COMPAT_START_ */ +(function() { + + var slice = Array.prototype.slice, + apply = Function.prototype.apply, + Dummy = function() { }; + + if (!Function.prototype.bind) { + /** + * Cross-browser approximation of ES5 Function.prototype.bind (not fully spec conforming) + * @see Function#bind on MDN + * @param {Object} thisArg Object to bind function to + * @param {Any[]} [...] Values to pass to a bound function + * @return {Function} + */ + Function.prototype.bind = function(thisArg) { + var _this = this, args = slice.call(arguments, 1), bound; + if (args.length) { + bound = function() { + return apply.call(_this, this instanceof Dummy ? this : thisArg, args.concat(slice.call(arguments))); + }; + } + else { + /** @ignore */ + bound = function() { + return apply.call(_this, this instanceof Dummy ? this : thisArg, arguments); + }; + } + Dummy.prototype = this.prototype; + bound.prototype = new Dummy(); + + return bound; + }; + } + +})(); +/* _ES5_COMPAT_END_ */ + + +(function() { + + var slice = Array.prototype.slice, emptyFunction = function() { }, + + IS_DONTENUM_BUGGY = (function(){ + for (var p in { toString: 1 }) { + if (p === 'toString') { + return false; + } + } + return true; + })(), + + /** @ignore */ + addMethods = function(klass, source, parent) { + for (var property in source) { + + if (property in klass.prototype && + typeof klass.prototype[property] === 'function' && + (source[property] + '').indexOf('callSuper') > -1) { + + klass.prototype[property] = (function(property) { + return function() { + + var superclass = this.constructor.superclass; + this.constructor.superclass = parent; + var returnValue = source[property].apply(this, arguments); + this.constructor.superclass = superclass; + + if (property !== 'initialize') { + return returnValue; + } + }; + })(property); + } + else { + klass.prototype[property] = source[property]; + } + + if (IS_DONTENUM_BUGGY) { + if (source.toString !== Object.prototype.toString) { + klass.prototype.toString = source.toString; + } + if (source.valueOf !== Object.prototype.valueOf) { + klass.prototype.valueOf = source.valueOf; + } + } + } + }; + + function Subclass() { } + + function callSuper(methodName) { + var fn = this.constructor.superclass.prototype[methodName]; + return (arguments.length > 1) + ? fn.apply(this, slice.call(arguments, 1)) + : fn.call(this); + } + + /** + * Helper for creation of "classes". + * @memberOf fabric.util + * @param {Function} [parent] optional "Class" to inherit from + * @param {Object} [properties] Properties shared by all instances of this class + * (be careful modifying objects defined here as this would affect all instances) + */ + function createClass() { + var parent = null, + properties = slice.call(arguments, 0); + + if (typeof properties[0] === 'function') { + parent = properties.shift(); + } + function klass() { + this.initialize.apply(this, arguments); + } + + klass.superclass = parent; + klass.subclasses = [ ]; + + if (parent) { + Subclass.prototype = parent.prototype; + klass.prototype = new Subclass(); + parent.subclasses.push(klass); + } + for (var i = 0, length = properties.length; i < length; i++) { + addMethods(klass, properties[i], parent); + } + if (!klass.prototype.initialize) { + klass.prototype.initialize = emptyFunction; + } + klass.prototype.constructor = klass; + klass.prototype.callSuper = callSuper; + return klass; + } + + fabric.util.createClass = createClass; +})(); + + +(function () { + + var unknown = 'unknown'; + + /* EVENT HANDLING */ + + function areHostMethods(object) { + var methodNames = Array.prototype.slice.call(arguments, 1), + t, i, len = methodNames.length; + for (i = 0; i < len; i++) { + t = typeof object[methodNames[i]]; + if (!(/^(?:function|object|unknown)$/).test(t)) { + return false; + } + } + return true; + } + + /** @ignore */ + var getElement, + setElement, + getUniqueId = (function () { + var uid = 0; + return function (element) { + return element.__uniqueID || (element.__uniqueID = 'uniqueID__' + uid++); + }; + })(); + + (function () { + var elements = { }; + /** @ignore */ + getElement = function (uid) { + return elements[uid]; + }; + /** @ignore */ + setElement = function (uid, element) { + elements[uid] = element; + }; + })(); + + function createListener(uid, handler) { + return { + handler: handler, + wrappedHandler: createWrappedHandler(uid, handler) + }; + } + + function createWrappedHandler(uid, handler) { + return function (e) { + handler.call(getElement(uid), e || fabric.window.event); + }; + } + + function createDispatcher(uid, eventName) { + return function (e) { + if (handlers[uid] && handlers[uid][eventName]) { + var handlersForEvent = handlers[uid][eventName]; + for (var i = 0, len = handlersForEvent.length; i < len; i++) { + handlersForEvent[i].call(this, e || fabric.window.event); + } + } + }; + } + + var shouldUseAddListenerRemoveListener = ( + areHostMethods(fabric.document.documentElement, 'addEventListener', 'removeEventListener') && + areHostMethods(fabric.window, 'addEventListener', 'removeEventListener')), + + shouldUseAttachEventDetachEvent = ( + areHostMethods(fabric.document.documentElement, 'attachEvent', 'detachEvent') && + areHostMethods(fabric.window, 'attachEvent', 'detachEvent')), + + // IE branch + listeners = { }, + + // DOM L0 branch + handlers = { }, + + addListener, removeListener; + + if (shouldUseAddListenerRemoveListener) { + /** @ignore */ + addListener = function (element, eventName, handler) { + element.addEventListener(eventName, handler, false); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + element.removeEventListener(eventName, handler, false); + }; + } + + else if (shouldUseAttachEventDetachEvent) { + /** @ignore */ + addListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + setElement(uid, element); + if (!listeners[uid]) { + listeners[uid] = { }; + } + if (!listeners[uid][eventName]) { + listeners[uid][eventName] = [ ]; + + } + var listener = createListener(uid, handler); + listeners[uid][eventName].push(listener); + element.attachEvent('on' + eventName, listener.wrappedHandler); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + var uid = getUniqueId(element), listener; + if (listeners[uid] && listeners[uid][eventName]) { + for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) { + listener = listeners[uid][eventName][i]; + if (listener && listener.handler === handler) { + element.detachEvent('on' + eventName, listener.wrappedHandler); + listeners[uid][eventName][i] = null; + } + } + } + }; + } + else { + /** @ignore */ + addListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + if (!handlers[uid]) { + handlers[uid] = { }; + } + if (!handlers[uid][eventName]) { + handlers[uid][eventName] = [ ]; + var existingHandler = element['on' + eventName]; + if (existingHandler) { + handlers[uid][eventName].push(existingHandler); + } + element['on' + eventName] = createDispatcher(uid, eventName); + } + handlers[uid][eventName].push(handler); + }; + /** @ignore */ + removeListener = function (element, eventName, handler) { + var uid = getUniqueId(element); + if (handlers[uid] && handlers[uid][eventName]) { + var handlersForEvent = handlers[uid][eventName]; + for (var i = 0, len = handlersForEvent.length; i < len; i++) { + if (handlersForEvent[i] === handler) { + handlersForEvent.splice(i, 1); + } + } + } + }; + } + + /** + * Adds an event listener to an element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {String} eventName + * @param {Function} handler + */ + fabric.util.addListener = addListener; + + /** + * Removes an event listener from an element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {String} eventName + * @param {Function} handler + */ + fabric.util.removeListener = removeListener; + + /** + * Cross-browser wrapper for getting event's coordinates + * @memberOf fabric.util + * @param {Event} event Event object + * @param {HTMLCanvasElement} upperCanvasEl <canvas> element on which object selection is drawn + */ + function getPointer(event, upperCanvasEl) { + event || (event = fabric.window.event); + + var element = event.target || + (typeof event.srcElement !== unknown ? event.srcElement : null), + + scroll = fabric.util.getScrollLeftTop(element, upperCanvasEl); + + return { + x: pointerX(event) + scroll.left, + y: pointerY(event) + scroll.top + }; + } + + var pointerX = function(event) { + // looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element) + // is represented as COM object, with all the consequences, like "unknown" type and error on [[Get]] + // need to investigate later + return (typeof event.clientX !== unknown ? event.clientX : 0); + }, + + pointerY = function(event) { + return (typeof event.clientY !== unknown ? event.clientY : 0); + }; + + function _getPointer(event, pageProp, clientProp) { + var touchProp = event.type === 'touchend' ? 'changedTouches' : 'touches'; + + return (event[touchProp] && event[touchProp][0] + ? (event[touchProp][0][pageProp] - (event[touchProp][0][pageProp] - event[touchProp][0][clientProp])) + || event[clientProp] + : event[clientProp]); + } + + if (fabric.isTouchSupported) { + pointerX = function(event) { + return _getPointer(event, 'pageX', 'clientX'); + }; + pointerY = function(event) { + return _getPointer(event, 'pageY', 'clientY'); + }; + } + + fabric.util.getPointer = getPointer; + + fabric.util.object.extend(fabric.util, fabric.Observable); + +})(); + + +(function () { + + /** + * Cross-browser wrapper for setting element's style + * @memberOf fabric.util + * @param {HTMLElement} element + * @param {Object} styles + * @return {HTMLElement} Element that was passed as a first argument + */ + function setStyle(element, styles) { + var elementStyle = element.style; + if (!elementStyle) { + return element; + } + if (typeof styles === 'string') { + element.style.cssText += ';' + styles; + return styles.indexOf('opacity') > -1 + ? setOpacity(element, styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) + : element; + } + for (var property in styles) { + if (property === 'opacity') { + setOpacity(element, styles[property]); + } + else { + var normalizedProperty = (property === 'float' || property === 'cssFloat') + ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat') + : property; + elementStyle[normalizedProperty] = styles[property]; + } + } + return element; + } + + var parseEl = fabric.document.createElement('div'), + supportsOpacity = typeof parseEl.style.opacity === 'string', + supportsFilters = typeof parseEl.style.filter === 'string', + reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/, + + /** @ignore */ + setOpacity = function (element) { return element; }; + + if (supportsOpacity) { + /** @ignore */ + setOpacity = function(element, value) { + element.style.opacity = value; + return element; + }; + } + else if (supportsFilters) { + /** @ignore */ + setOpacity = function(element, value) { + var es = element.style; + if (element.currentStyle && !element.currentStyle.hasLayout) { + es.zoom = 1; + } + if (reOpacity.test(es.filter)) { + value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')'); + es.filter = es.filter.replace(reOpacity, value); + } + else { + es.filter += ' alpha(opacity=' + (value * 100) + ')'; + } + return element; + }; + } + + fabric.util.setStyle = setStyle; + +})(); + + +(function() { + + var _slice = Array.prototype.slice; + + /** + * Takes id and returns an element with that id (if one exists in a document) + * @memberOf fabric.util + * @param {String|HTMLElement} id + * @return {HTMLElement|null} + */ + function getById(id) { + return typeof id === 'string' ? fabric.document.getElementById(id) : id; + } + + var sliceCanConvertNodelists, + /** + * Converts an array-like object (e.g. arguments or NodeList) to an array + * @memberOf fabric.util + * @param {Object} arrayLike + * @return {Array} + */ + toArray = function(arrayLike) { + return _slice.call(arrayLike, 0); + }; + + try { + sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array; + } + catch (err) { } + + if (!sliceCanConvertNodelists) { + toArray = function(arrayLike) { + var arr = new Array(arrayLike.length), i = arrayLike.length; + while (i--) { + arr[i] = arrayLike[i]; + } + return arr; + }; + } + + /** + * Creates specified element with specified attributes + * @memberOf fabric.util + * @param {String} tagName Type of an element to create + * @param {Object} [attributes] Attributes to set on an element + * @return {HTMLElement} Newly created element + */ + function makeElement(tagName, attributes) { + var el = fabric.document.createElement(tagName); + for (var prop in attributes) { + if (prop === 'class') { + el.className = attributes[prop]; + } + else if (prop === 'for') { + el.htmlFor = attributes[prop]; + } + else { + el.setAttribute(prop, attributes[prop]); + } + } + return el; + } + + /** + * Adds class to an element + * @memberOf fabric.util + * @param {HTMLElement} element Element to add class to + * @param {String} className Class to add to an element + */ + function addClass(element, className) { + if (element && (' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) { + element.className += (element.className ? ' ' : '') + className; + } + } + + /** + * Wraps element with another element + * @memberOf fabric.util + * @param {HTMLElement} element Element to wrap + * @param {HTMLElement|String} wrapper Element to wrap with + * @param {Object} [attributes] Attributes to set on a wrapper + * @return {HTMLElement} wrapper + */ + function wrapElement(element, wrapper, attributes) { + if (typeof wrapper === 'string') { + wrapper = makeElement(wrapper, attributes); + } + if (element.parentNode) { + element.parentNode.replaceChild(wrapper, element); + } + wrapper.appendChild(element); + return wrapper; + } + + /** + * Returns element scroll offsets + * @memberOf fabric.util + * @param {HTMLElement} element Element to operate on + * @param {HTMLElement} upperCanvasEl Upper canvas element + * @return {Object} Object with left/top values + */ + function getScrollLeftTop(element, upperCanvasEl) { + + var firstFixedAncestor, + origElement, + left = 0, + top = 0, + docElement = fabric.document.documentElement, + body = fabric.document.body || { + scrollLeft: 0, scrollTop: 0 + }; + + origElement = element; + + while (element && element.parentNode && !firstFixedAncestor) { + + element = element.parentNode; + + if (element !== fabric.document && + fabric.util.getElementStyle(element, 'position') === 'fixed') { + firstFixedAncestor = element; + } + + if (element !== fabric.document && + origElement !== upperCanvasEl && + fabric.util.getElementStyle(element, 'position') === 'absolute') { + left = 0; + top = 0; + } + else if (element === fabric.document) { + left = body.scrollLeft || docElement.scrollLeft || 0; + top = body.scrollTop || docElement.scrollTop || 0; + } + else { + left += element.scrollLeft || 0; + top += element.scrollTop || 0; + } + } + + return { left: left, top: top }; + } + + /** + * Returns offset for a given element + * @function + * @memberOf fabric.util + * @param {HTMLElement} element Element to get offset for + * @return {Object} Object with "left" and "top" properties + */ + function getElementOffset(element) { + var docElem, + doc = element && element.ownerDocument, + box = { left: 0, top: 0 }, + offset = { left: 0, top: 0 }, + scrollLeftTop, + offsetAttributes = { + borderLeftWidth: 'left', + borderTopWidth: 'top', + paddingLeft: 'left', + paddingTop: 'top' + }; + + if (!doc) { + return { left: 0, top: 0 }; + } + + for (var attr in offsetAttributes) { + offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0; + } + + docElem = doc.documentElement; + if ( typeof element.getBoundingClientRect !== 'undefined' ) { + box = element.getBoundingClientRect(); + } + + scrollLeftTop = fabric.util.getScrollLeftTop(element, null); + + return { + left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left, + top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top + }; + } + + /** + * Returns style attribute value of a given element + * @memberOf fabric.util + * @param {HTMLElement} element Element to get style attribute for + * @param {String} attr Style attribute to get for element + * @return {String} Style attribute value of the given element. + */ + var getElementStyle; + if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) { + getElementStyle = function(element, attr) { + return fabric.document.defaultView.getComputedStyle(element, null)[attr]; + }; + } + else { + getElementStyle = function(element, attr) { + var value = element.style[attr]; + if (!value && element.currentStyle) { + value = element.currentStyle[attr]; + } + return value; + }; + } + + (function () { + var style = fabric.document.documentElement.style, + selectProp = 'userSelect' in style + ? 'userSelect' + : 'MozUserSelect' in style + ? 'MozUserSelect' + : 'WebkitUserSelect' in style + ? 'WebkitUserSelect' + : 'KhtmlUserSelect' in style + ? 'KhtmlUserSelect' + : ''; + + /** + * Makes element unselectable + * @memberOf fabric.util + * @param {HTMLElement} element Element to make unselectable + * @return {HTMLElement} Element that was passed in + */ + function makeElementUnselectable(element) { + if (typeof element.onselectstart !== 'undefined') { + element.onselectstart = fabric.util.falseFunction; + } + if (selectProp) { + element.style[selectProp] = 'none'; + } + else if (typeof element.unselectable === 'string') { + element.unselectable = 'on'; + } + return element; + } + + /** + * Makes element selectable + * @memberOf fabric.util + * @param {HTMLElement} element Element to make selectable + * @return {HTMLElement} Element that was passed in + */ + function makeElementSelectable(element) { + if (typeof element.onselectstart !== 'undefined') { + element.onselectstart = null; + } + if (selectProp) { + element.style[selectProp] = ''; + } + else if (typeof element.unselectable === 'string') { + element.unselectable = ''; + } + return element; + } + + fabric.util.makeElementUnselectable = makeElementUnselectable; + fabric.util.makeElementSelectable = makeElementSelectable; + })(); + + (function() { + + /** + * Inserts a script element with a given url into a document; invokes callback, when that script is finished loading + * @memberOf fabric.util + * @param {String} url URL of a script to load + * @param {Function} callback Callback to execute when script is finished loading + */ + function getScript(url, callback) { + var headEl = fabric.document.getElementsByTagName('head')[0], + scriptEl = fabric.document.createElement('script'), + loading = true; + + /** @ignore */ + scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) { + if (loading) { + if (typeof this.readyState === 'string' && + this.readyState !== 'loaded' && + this.readyState !== 'complete') { + return; + } + loading = false; + callback(e || fabric.window.event); + scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null; + } + }; + scriptEl.src = url; + headEl.appendChild(scriptEl); + // causes issue in Opera + // headEl.removeChild(scriptEl); + } + + fabric.util.getScript = getScript; + })(); + + fabric.util.getById = getById; + fabric.util.toArray = toArray; + fabric.util.makeElement = makeElement; + fabric.util.addClass = addClass; + fabric.util.wrapElement = wrapElement; + fabric.util.getScrollLeftTop = getScrollLeftTop; + fabric.util.getElementOffset = getElementOffset; + fabric.util.getElementStyle = getElementStyle; + +})(); + + +(function(){ + + function addParamToUrl(url, param) { + return url + (/\?/.test(url) ? '&' : '?') + param; + } + + var makeXHR = (function() { + var factories = [ + function() { return new ActiveXObject('Microsoft.XMLHTTP'); }, + function() { return new ActiveXObject('Msxml2.XMLHTTP'); }, + function() { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); }, + function() { return new XMLHttpRequest(); } + ]; + for (var i = factories.length; i--; ) { + try { + var req = factories[i](); + if (req) { + return factories[i]; + } + } + catch (err) { } + } + })(); + + function emptyFn() { } + + /** + * Cross-browser abstraction for sending XMLHttpRequest + * @memberOf fabric.util + * @param {String} url URL to send XMLHttpRequest to + * @param {Object} [options] Options object + * @param {String} [options.method="GET"] + * @param {Function} options.onComplete Callback to invoke when request is completed + * @return {XMLHttpRequest} request + */ + function request(url, options) { + + options || (options = { }); + + var method = options.method ? options.method.toUpperCase() : 'GET', + onComplete = options.onComplete || function() { }, + xhr = makeXHR(), + body; + + /** @ignore */ + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + onComplete(xhr); + xhr.onreadystatechange = emptyFn; + } + }; + + if (method === 'GET') { + body = null; + if (typeof options.parameters === 'string') { + url = addParamToUrl(url, options.parameters); + } + } + + xhr.open(method, url, true); + + if (method === 'POST' || method === 'PUT') { + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + } + + xhr.send(body); + return xhr; + } + + fabric.util.request = request; +})(); + + +/** + * Wrapper around `console.log` (when available) + * @param {Any} [values] Values to log + */ +fabric.log = function() { }; + +/** + * Wrapper around `console.warn` (when available) + * @param {Any} [values] Values to log as a warning + */ +fabric.warn = function() { }; + +if (typeof console !== 'undefined') { + ['log', 'warn'].forEach(function(methodName) { + if (typeof console[methodName] !== 'undefined' && console[methodName].apply) { + fabric[methodName] = function() { + return console[methodName].apply(console, arguments); + }; + } + }); +} + + +(function() { + + /** + * Changes value from one to another within certain period of time, invoking callbacks as value is being changed. + * @memberOf fabric.util + * @param {Object} [options] Animation options + * @param {Function} [options.onChange] Callback; invoked on every value change + * @param {Function} [options.onComplete] Callback; invoked when value change is completed + * @param {Number} [options.startValue=0] Starting value + * @param {Number} [options.endValue=100] Ending value + * @param {Number} [options.byValue=100] Value to modify the property by + * @param {Function} [options.easing] Easing function + * @param {Number} [options.duration=500] Duration of change (in ms) + */ + function animate(options) { + + requestAnimFrame(function(timestamp) { + options || (options = { }); + + var start = timestamp || +new Date(), + duration = options.duration || 500, + finish = start + duration, time, + onChange = options.onChange || function() { }, + abort = options.abort || function() { return false; }, + easing = options.easing || function(t, b, c, d) {return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;}, + startValue = 'startValue' in options ? options.startValue : 0, + endValue = 'endValue' in options ? options.endValue : 100, + byValue = options.byValue || endValue - startValue; + + options.onStart && options.onStart(); + + (function tick(ticktime) { + time = ticktime || +new Date(); + var currentTime = time > finish ? duration : (time - start); + if (abort()) { + options.onComplete && options.onComplete(); + return; + } + onChange(easing(currentTime, startValue, byValue, duration)); + if (time > finish) { + options.onComplete && options.onComplete(); + return; + } + requestAnimFrame(tick); + })(start); + }); + + } + + var _requestAnimFrame = fabric.window.requestAnimationFrame || + fabric.window.webkitRequestAnimationFrame || + fabric.window.mozRequestAnimationFrame || + fabric.window.oRequestAnimationFrame || + fabric.window.msRequestAnimationFrame || + function(callback) { + fabric.window.setTimeout(callback, 1000 / 60); + }; + /** + * requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + * In order to get a precise start time, `requestAnimFrame` should be called as an entry into the method + * @memberOf fabric.util + * @param {Function} callback Callback to invoke + * @param {DOMElement} element optional Element to associate with animation + */ + function requestAnimFrame() { + return _requestAnimFrame.apply(fabric.window, arguments); + } + + fabric.util.animate = animate; + fabric.util.requestAnimFrame = requestAnimFrame; + +})(); + + +(function() { + + function normalize(a, c, p, s) { + if (a < Math.abs(c)) { + a = c; + s = p / 4; + } + else { + s = p / (2 * Math.PI) * Math.asin(c / a); + } + return { a: a, c: c, p: p, s: s }; + } + + function elastic(opts, t, d) { + return opts.a * + Math.pow(2, 10 * (t -= 1)) * + Math.sin( (t * d - opts.s) * (2 * Math.PI) / opts.p ); + } + + /** + * Cubic easing out + * @memberOf fabric.util.ease + */ + function easeOutCubic(t, b, c, d) { + return c * ((t = t / d - 1) * t * t + 1) + b; + } + + /** + * Cubic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutCubic(t, b, c, d) { + t /= d/2; + if (t < 1) { + return c / 2 * t * t * t + b; + } + return c / 2 * ((t -= 2) * t * t + 2) + b; + } + + /** + * Quartic easing in + * @memberOf fabric.util.ease + */ + function easeInQuart(t, b, c, d) { + return c * (t /= d) * t * t * t + b; + } + + /** + * Quartic easing out + * @memberOf fabric.util.ease + */ + function easeOutQuart(t, b, c, d) { + return -c * ((t = t / d - 1) * t * t * t - 1) + b; + } + + /** + * Quartic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutQuart(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return c / 2 * t * t * t * t + b; + } + return -c / 2 * ((t -= 2) * t * t * t - 2) + b; + } + + /** + * Quintic easing in + * @memberOf fabric.util.ease + */ + function easeInQuint(t, b, c, d) { + return c * (t /= d) * t * t * t * t + b; + } + + /** + * Quintic easing out + * @memberOf fabric.util.ease + */ + function easeOutQuint(t, b, c, d) { + return c * ((t = t / d - 1) * t * t * t * t + 1) + b; + } + + /** + * Quintic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutQuint(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return c / 2 * t * t * t * t * t + b; + } + return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; + } + + /** + * Sinusoidal easing in + * @memberOf fabric.util.ease + */ + function easeInSine(t, b, c, d) { + return -c * Math.cos(t / d * (Math.PI / 2)) + c + b; + } + + /** + * Sinusoidal easing out + * @memberOf fabric.util.ease + */ + function easeOutSine(t, b, c, d) { + return c * Math.sin(t / d * (Math.PI / 2)) + b; + } + + /** + * Sinusoidal easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutSine(t, b, c, d) { + return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b; + } + + /** + * Exponential easing in + * @memberOf fabric.util.ease + */ + function easeInExpo(t, b, c, d) { + return (t === 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b; + } + + /** + * Exponential easing out + * @memberOf fabric.util.ease + */ + function easeOutExpo(t, b, c, d) { + return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b; + } + + /** + * Exponential easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutExpo(t, b, c, d) { + if (t === 0) { + return b; + } + if (t === d) { + return b + c; + } + t /= d / 2; + if (t < 1) { + return c / 2 * Math.pow(2, 10 * (t - 1)) + b; + } + return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b; + } + + /** + * Circular easing in + * @memberOf fabric.util.ease + */ + function easeInCirc(t, b, c, d) { + return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b; + } + + /** + * Circular easing out + * @memberOf fabric.util.ease + */ + function easeOutCirc(t, b, c, d) { + return c * Math.sqrt(1 - (t = t / d - 1) * t) + b; + } + + /** + * Circular easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutCirc(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b; + } + return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b; + } + + /** + * Elastic easing in + * @memberOf fabric.util.ease + */ + function easeInElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d; + if (t === 1) { + return b + c; + } + if (!p) { + p = d * 0.3; + } + var opts = normalize(a, c, p, s); + return -elastic(opts, t, d) + b; + } + + /** + * Elastic easing out + * @memberOf fabric.util.ease + */ + function easeOutElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d; + if (t === 1) { + return b + c; + } + if (!p) { + p = d * 0.3; + } + var opts = normalize(a, c, p, s); + return opts.a * Math.pow(2, -10 * t) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) + opts.c + b; + } + + /** + * Elastic easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d / 2; + if (t === 2) { + return b + c; + } + if (!p) { + p = d * (0.3 * 1.5); + } + var opts = normalize(a, c, p, s); + if (t < 1) { + return -0.5 * elastic(opts, t, d) + b; + } + return opts.a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) * 0.5 + opts.c + b; + } + + /** + * Backwards easing in + * @memberOf fabric.util.ease + */ + function easeInBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + return c * (t /= d) * t * ((s + 1) * t - s) + b; + } + + /** + * Backwards easing out + * @memberOf fabric.util.ease + */ + function easeOutBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; + } + + /** + * Backwards easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + t /= d / 2; + if (t < 1) { + return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b; + } + return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b; + } + + /** + * Bouncing easing in + * @memberOf fabric.util.ease + */ + function easeInBounce(t, b, c, d) { + return c - easeOutBounce (d - t, 0, c, d) + b; + } + + /** + * Bouncing easing out + * @memberOf fabric.util.ease + */ + function easeOutBounce(t, b, c, d) { + if ((t /= d) < (1 / 2.75)) { + return c * (7.5625 * t * t) + b; + } + else if (t < (2/2.75)) { + return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b; + } + else if (t < (2.5/2.75)) { + return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b; + } + else { + return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b; + } + } + + /** + * Bouncing easing in and out + * @memberOf fabric.util.ease + */ + function easeInOutBounce(t, b, c, d) { + if (t < d / 2) { + return easeInBounce (t * 2, 0, c, d) * 0.5 + b; + } + return easeOutBounce(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b; + } + + /** + * Easing functions + * See Easing Equations by Robert Penner + * @namespace fabric.util.ease + */ + fabric.util.ease = { + + /** + * Quadratic easing in + * @memberOf fabric.util.ease + */ + easeInQuad: function(t, b, c, d) { + return c * (t /= d) * t + b; + }, + + /** + * Quadratic easing out + * @memberOf fabric.util.ease + */ + easeOutQuad: function(t, b, c, d) { + return -c * (t /= d) * (t - 2) + b; + }, + + /** + * Quadratic easing in and out + * @memberOf fabric.util.ease + */ + easeInOutQuad: function(t, b, c, d) { + t /= (d / 2); + if (t < 1) { + return c / 2 * t * t + b; + } + return -c / 2 * ((--t) * (t - 2) - 1) + b; + }, + + /** + * Cubic easing in + * @memberOf fabric.util.ease + */ + easeInCubic: function(t, b, c, d) { + return c * (t /= d) * t * t + b; + }, + + easeOutCubic: easeOutCubic, + easeInOutCubic: easeInOutCubic, + easeInQuart: easeInQuart, + easeOutQuart: easeOutQuart, + easeInOutQuart: easeInOutQuart, + easeInQuint: easeInQuint, + easeOutQuint: easeOutQuint, + easeInOutQuint: easeInOutQuint, + easeInSine: easeInSine, + easeOutSine: easeOutSine, + easeInOutSine: easeInOutSine, + easeInExpo: easeInExpo, + easeOutExpo: easeOutExpo, + easeInOutExpo: easeInOutExpo, + easeInCirc: easeInCirc, + easeOutCirc: easeOutCirc, + easeInOutCirc: easeInOutCirc, + easeInElastic: easeInElastic, + easeOutElastic: easeOutElastic, + easeInOutElastic: easeInOutElastic, + easeInBack: easeInBack, + easeOutBack: easeOutBack, + easeInOutBack: easeInOutBack, + easeInBounce: easeInBounce, + easeOutBounce: easeOutBounce, + easeInOutBounce: easeInOutBounce + }; + +}()); + + +(function(global) { + + 'use strict'; + + /** + * @name fabric + * @namespace + */ + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + capitalize = fabric.util.string.capitalize, + clone = fabric.util.object.clone, + toFixed = fabric.util.toFixed, + parseUnit = fabric.util.parseUnit, + multiplyTransformMatrices = fabric.util.multiplyTransformMatrices, + + attributesMap = { + cx: 'left', + x: 'left', + r: 'radius', + cy: 'top', + y: 'top', + display: 'visible', + visibility: 'visible', + transform: 'transformMatrix', + 'fill-opacity': 'fillOpacity', + 'fill-rule': 'fillRule', + 'font-family': 'fontFamily', + 'font-size': 'fontSize', + 'font-style': 'fontStyle', + 'font-weight': 'fontWeight', + 'stroke-dasharray': 'strokeDashArray', + 'stroke-linecap': 'strokeLineCap', + 'stroke-linejoin': 'strokeLineJoin', + 'stroke-miterlimit': 'strokeMiterLimit', + 'stroke-opacity': 'strokeOpacity', + 'stroke-width': 'strokeWidth', + 'text-decoration': 'textDecoration', + 'text-anchor': 'originX' + }, + + colorAttributes = { + stroke: 'strokeOpacity', + fill: 'fillOpacity' + }; + + function normalizeAttr(attr) { + // transform attribute names + if (attr in attributesMap) { + return attributesMap[attr]; + } + return attr; + } + + function normalizeValue(attr, value, parentAttributes) { + var isArray = Object.prototype.toString.call(value) === '[object Array]', + parsed; + + if ((attr === 'fill' || attr === 'stroke') && value === 'none') { + value = ''; + } + else if (attr === 'fillRule') { + value = (value === 'evenodd') ? 'destination-over' : value; + } + else if (attr === 'strokeDashArray') { + value = value.replace(/,/g, ' ').split(/\s+/).map(function(n) { + return parseInt(n); + }); + } + else if (attr === 'transformMatrix') { + if (parentAttributes && parentAttributes.transformMatrix) { + value = multiplyTransformMatrices( + parentAttributes.transformMatrix, fabric.parseTransformAttribute(value)); + } + else { + value = fabric.parseTransformAttribute(value); + } + } + else if (attr === 'visible') { + value = (value === 'none' || value === 'hidden') ? false : true; + // display=none on parent element always takes precedence over child element + if (parentAttributes && parentAttributes.visible === false) { + value = false; + } + } + else if (attr === 'originX' /* text-anchor */) { + value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center'; + } + else { + parsed = isArray ? value.map(parseUnit) : parseUnit(value); + } + + return (!isArray && isNaN(parsed) ? value : parsed); + } + + /** + * @private + * @param {Object} attributes Array of attributes to parse + */ + function _setStrokeFillOpacity(attributes) { + for (var attr in colorAttributes) { + + if (!attributes[attr] || typeof attributes[colorAttributes[attr]] === 'undefined') { + continue; + } + + if (attributes[attr].indexOf('url(') === 0) { + continue; + } + + var color = new fabric.Color(attributes[attr]); + attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba(); + } + return attributes; + } + + /** + * Parses "transform" attribute, returning an array of values + * @static + * @function + * @memberOf fabric + * @param {String} attributeValue String containing attribute value + * @return {Array} Array of 6 elements representing transformation matrix + */ + fabric.parseTransformAttribute = (function() { + function rotateMatrix(matrix, args) { + var angle = args[0]; + + matrix[0] = Math.cos(angle); + matrix[1] = Math.sin(angle); + matrix[2] = -Math.sin(angle); + matrix[3] = Math.cos(angle); + } + + function scaleMatrix(matrix, args) { + var multiplierX = args[0], + multiplierY = (args.length === 2) ? args[1] : args[0]; + + matrix[0] = multiplierX; + matrix[3] = multiplierY; + } + + function skewXMatrix(matrix, args) { + matrix[2] = args[0]; + } + + function skewYMatrix(matrix, args) { + matrix[1] = args[0]; + } + + function translateMatrix(matrix, args) { + matrix[4] = args[0]; + if (args.length === 2) { + matrix[5] = args[1]; + } + } + + // identity matrix + var iMatrix = [ + 1, // a + 0, // b + 0, // c + 1, // d + 0, // e + 0 // f + ], + + // == begin transform regexp + number = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)', + + commaWsp = '(?:\\s+,?\\s*|,\\s*)', + + skewX = '(?:(skewX)\\s*\\(\\s*(' + number + ')\\s*\\))', + + skewY = '(?:(skewY)\\s*\\(\\s*(' + number + ')\\s*\\))', + + rotate = '(?:(rotate)\\s*\\(\\s*(' + number + ')(?:' + + commaWsp + '(' + number + ')' + + commaWsp + '(' + number + '))?\\s*\\))', + + scale = '(?:(scale)\\s*\\(\\s*(' + number + ')(?:' + + commaWsp + '(' + number + '))?\\s*\\))', + + translate = '(?:(translate)\\s*\\(\\s*(' + number + ')(?:' + + commaWsp + '(' + number + '))?\\s*\\))', + + matrix = '(?:(matrix)\\s*\\(\\s*' + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + commaWsp + + '(' + number + ')' + + '\\s*\\))', + + transform = '(?:' + + matrix + '|' + + translate + '|' + + scale + '|' + + rotate + '|' + + skewX + '|' + + skewY + + ')', + + transforms = '(?:' + transform + '(?:' + commaWsp + transform + ')*' + ')', + + transformList = '^\\s*(?:' + transforms + '?)\\s*$', + + // http://www.w3.org/TR/SVG/coords.html#TransformAttribute + reTransformList = new RegExp(transformList), + // == end transform regexp + + reTransform = new RegExp(transform, 'g'); + + return function(attributeValue) { + + // start with identity matrix + var matrix = iMatrix.concat(), + matrices = [ ]; + + // return if no argument was given or + // an argument does not match transform attribute regexp + if (!attributeValue || (attributeValue && !reTransformList.test(attributeValue))) { + return matrix; + } + + attributeValue.replace(reTransform, function(match) { + + var m = new RegExp(transform).exec(match).filter(function (match) { + return (match !== '' && match != null); + }), + operation = m[1], + args = m.slice(2).map(parseFloat); + + switch (operation) { + case 'translate': + translateMatrix(matrix, args); + break; + case 'rotate': + args[0] = fabric.util.degreesToRadians(args[0]); + rotateMatrix(matrix, args); + break; + case 'scale': + scaleMatrix(matrix, args); + break; + case 'skewX': + skewXMatrix(matrix, args); + break; + case 'skewY': + skewYMatrix(matrix, args); + break; + case 'matrix': + matrix = args; + break; + } + + // snapshot current matrix into matrices array + matrices.push(matrix.concat()); + // reset + matrix = iMatrix.concat(); + }); + + var combinedMatrix = matrices[0]; + while (matrices.length > 1) { + matrices.shift(); + combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]); + } + return combinedMatrix; + }; + })(); + + function parseFontDeclaration(value, oStyle) { + + // TODO: support non-px font size + var match = value.match(/(normal|italic)?\s*(normal|small-caps)?\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\s*(\d+)px(?:\/(normal|[\d\.]+))?\s+(.*)/); + + if (!match) { + return; + } + + var fontStyle = match[1], + // font variant is not used + // fontVariant = match[2], + fontWeight = match[3], + fontSize = match[4], + lineHeight = match[5], + fontFamily = match[6]; + + if (fontStyle) { + oStyle.fontStyle = fontStyle; + } + if (fontWeight) { + oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight); + } + if (fontSize) { + oStyle.fontSize = parseFloat(fontSize); + } + if (fontFamily) { + oStyle.fontFamily = fontFamily; + } + if (lineHeight) { + oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight; + } + } + + /** + * @private + */ + function parseStyleString(style, oStyle) { + var attr, value; + style.replace(/;$/, '').split(';').forEach(function (chunk) { + var pair = chunk.split(':'); + + attr = normalizeAttr(pair[0].trim().toLowerCase()); + value = normalizeValue(attr, pair[1].trim()); + + if (attr === 'font') { + parseFontDeclaration(value, oStyle); + } + else { + oStyle[attr] = value; + } + }); + } + + /** + * @private + */ + function parseStyleObject(style, oStyle) { + var attr, value; + for (var prop in style) { + if (typeof style[prop] === 'undefined') { + continue; + } + + attr = normalizeAttr(prop.toLowerCase()); + value = normalizeValue(attr, style[prop]); + + if (attr === 'font') { + parseFontDeclaration(value, oStyle); + } + else { + oStyle[attr] = value; + } + } + } + + /** + * @private + */ + function getGlobalStylesForElement(element) { + var styles = { }; + + for (var rule in fabric.cssRules) { + if (elementMatchesRule(element, rule.split(' '))) { + for (var property in fabric.cssRules[rule]) { + styles[property] = fabric.cssRules[rule][property]; + } + } + } + return styles; + } + + /** + * @private + */ + function elementMatchesRule(element, selectors) { + var firstMatching, parentMatching = true; + //start from rightmost selector. + firstMatching = selectorMatches(element, selectors.pop()); + if (firstMatching && selectors.length) { + parentMatching = doesSomeParentMatch(element, selectors); + } + return firstMatching && parentMatching && (selectors.length === 0); + } + + function doesSomeParentMatch(element, selectors) { + var selector, parentMatching = true; + while (element.parentNode && element.parentNode.nodeType === 1 && selectors.length) { + if (parentMatching) { + selector = selectors.pop(); + } + element = element.parentNode; + parentMatching = selectorMatches(element, selector); + } + return selectors.length === 0; + } + /** + * @private + */ + function selectorMatches(element, selector) { + var nodeName = element.nodeName, + classNames = element.getAttribute('class'), + id = element.getAttribute('id'), matcher; + // i check if a selector matches slicing away part from it. + // if i get empty string i should match + matcher = new RegExp('^' + nodeName, 'i'); + selector = selector.replace(matcher, ''); + if (id && selector.length) { + matcher = new RegExp('#' + id + '(?![a-zA-Z\\-]+)', 'i'); + selector = selector.replace(matcher, ''); + } + if (classNames && selector.length) { + classNames = classNames.split(' '); + for (var i = classNames.length; i--;) { + matcher = new RegExp('\\.' + classNames[i] + '(?![a-zA-Z\\-]+)', 'i'); + selector = selector.replace(matcher, ''); + } + } + return selector.length === 0; + } + + /** + * @private + */ + function parseUseDirectives(doc) { + var nodelist = doc.getElementsByTagName('use'); + while (nodelist.length) { + var el = nodelist[0], + xlink = el.getAttribute('xlink:href').substr(1), + x = el.getAttribute('x') || 0, + y = el.getAttribute('y') || 0, + el2 = doc.getElementById(xlink).cloneNode(true), + currentTrans = (el.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')', + parentNode; + + for (var j = 0, attrs = el.attributes, l = attrs.length; j < l; j++) { + var attr = attrs.item(j); + if (attr.nodeName === 'x' || attr.nodeName === 'y' || attr.nodeName === 'xlink:href') { + continue; + } + + if (attr.nodeName === 'transform') { + currentTrans = currentTrans + ' ' + attr.nodeValue; + } + else { + el2.setAttribute(attr.nodeName, attr.nodeValue); + } + } + + el2.setAttribute('transform', currentTrans); + el2.removeAttribute('id'); + parentNode = el.parentNode; + parentNode.replaceChild(el2, el); + } + } + + /** + * Add a element that envelop all SCG elements and makes the viewbox transformMatrix descend on all elements + */ + function addSvgTransform(doc, matrix) { + matrix[3] = matrix[0] = (matrix[0] > matrix[3] ? matrix[3] : matrix[0]); + if (!(matrix[0] !== 1 || matrix[3] !== 1 || matrix[4] !== 0 || matrix[5] !== 0)) { + return; + } + // default is to preserve aspect ratio + // preserveAspectRatio attribute to be implemented + var el = doc.ownerDocument.createElement('g'); + while (doc.firstChild != null) { + el.appendChild(doc.firstChild); + } + el.setAttribute('transform','matrix(' + matrix[0] + ' ' + matrix[1] + ' ' + matrix[2] + ' ' + matrix[3] + ' ' + matrix[4] + ' ' + matrix[5] + ')'); + doc.appendChild(el); + } + + /** + * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @param {Function} callback Callback to call when parsing is finished; It's being passed an array of elements (parsed from a document). + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + fabric.parseSVGDocument = (function() { + + var reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/, + + // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute + // \d doesn't quite cut it (as we need to match an actual float number) + + // matches, e.g.: +14.56e-12, etc. + reNum = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)', + + reViewBoxAttrValue = new RegExp( + '^' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*,?' + + '\\s*(' + reNum + '+)\\s*' + + '$' + ); + + function hasAncestorWithNodeName(element, nodeName) { + while (element && (element = element.parentNode)) { + if (nodeName.test(element.nodeName)) { + return true; + } + } + return false; + } + + return function(doc, callback, reviver) { + if (!doc) { + return; + } + var startTime = new Date(); + + parseUseDirectives(doc); + + var viewBoxAttr = doc.getAttribute('viewBox'), + widthAttr = parseUnit(doc.getAttribute('width')), + heightAttr = parseUnit(doc.getAttribute('height')), + viewBoxWidth, + viewBoxHeight; + + if (viewBoxAttr && (viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))) { + var minX = parseFloat(viewBoxAttr[1]), + minY = parseFloat(viewBoxAttr[2]), + scaleX = 1, scaleY = 1; + viewBoxWidth = parseFloat(viewBoxAttr[3]); + viewBoxHeight = parseFloat(viewBoxAttr[4]); + if (widthAttr && widthAttr !== viewBoxWidth ) { + scaleX = widthAttr / viewBoxWidth; + } + if (heightAttr && heightAttr !== viewBoxHeight) { + scaleY = heightAttr / viewBoxHeight; + } + addSvgTransform(doc, [scaleX, 0, 0, scaleY, scaleX * -minX, scaleY * -minY]); + } + + var descendants = fabric.util.toArray(doc.getElementsByTagName('*')); + + if (descendants.length === 0 && fabric.isLikelyNode) { + // we're likely in node, where "o3-xml" library fails to gEBTN("*") + // https://github.com/ajaxorg/node-o3-xml/issues/21 + descendants = doc.selectNodes('//*[name(.)!="svg"]'); + var arr = [ ]; + for (var i = 0, len = descendants.length; i < len; i++) { + arr[i] = descendants[i]; + } + descendants = arr; + } + + var elements = descendants.filter(function(el) { + return reAllowedSVGTagNames.test(el.tagName) && + !hasAncestorWithNodeName(el, /^(?:pattern|defs)$/); // http://www.w3.org/TR/SVG/struct.html#DefsElement + }); + + if (!elements || (elements && !elements.length)) { + callback && callback([], {}); + return; + } + + var options = { + width: widthAttr ? widthAttr : viewBoxWidth, + height: heightAttr ? heightAttr : viewBoxHeight, + widthAttr: widthAttr, + heightAttr: heightAttr + }; + + fabric.gradientDefs = fabric.getGradientDefs(doc); + fabric.cssRules = fabric.getCSSRules(doc); + // Precedence of rules: style > class > attribute + + fabric.parseElements(elements, function(instances) { + fabric.documentParsingTime = new Date() - startTime; + if (callback) { + callback(instances, options); + } + }, clone(options), reviver); + }; + })(); + + /** + * Used for caching SVG documents (loaded via `fabric.Canvas#loadSVGFromURL`) + * @namespace + */ + var svgCache = { + + /** + * @param {String} name + * @param {Function} callback + */ + has: function (name, callback) { + callback(false); + }, + + get: function () { + /* NOOP */ + }, + + set: function () { + /* NOOP */ + } + }; + + /** + * @private + */ + function _enlivenCachedObject(cachedObject) { + + var objects = cachedObject.objects, + options = cachedObject.options; + + objects = objects.map(function (o) { + return fabric[capitalize(o.type)].fromObject(o); + }); + + return ({ objects: objects, options: options }); + } + + /** + * @private + */ + function _createSVGPattern(markup, canvas, property) { + if (canvas[property] && canvas[property].toSVG) { + markup.push( + '', + '' + ); + } + } + + extend(fabric, { + + /** + * Parses an SVG document, returning all of the gradient declarations found in it + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element + */ + getGradientDefs: function(doc) { + var linearGradientEls = doc.getElementsByTagName('linearGradient'), + radialGradientEls = doc.getElementsByTagName('radialGradient'), + el, i, j = 0, id, xlink, elList = [ ], + gradientDefs = { }, idsToXlinkMap = { }; + + elList.length = linearGradientEls.length + radialGradientEls.length; + i = linearGradientEls.length; + while (i--) { + elList[j++] = linearGradientEls[i]; + } + i = radialGradientEls.length; + while (i--) { + elList[j++] = radialGradientEls[i]; + } + + while (j--) { + el = elList[j]; + xlink = el.getAttribute('xlink:href'); + id = el.getAttribute('id'); + if (xlink) { + idsToXlinkMap[id] = xlink.substr(1); + } + gradientDefs[id] = el; + } + + for (id in idsToXlinkMap) { + var el2 = gradientDefs[idsToXlinkMap[id]].cloneNode(true); + el = gradientDefs[id]; + while (el2.firstChild) { + el.appendChild(el2.firstChild); + } + } + return gradientDefs; + }, + + /** + * Returns an object of attributes' name/value, given element and an array of attribute names; + * Parses parent "g" nodes recursively upwards. + * @static + * @memberOf fabric + * @param {DOMElement} element Element to parse + * @param {Array} attributes Array of attributes to parse + * @return {Object} object containing parsed attributes' names/values + */ + parseAttributes: function(element, attributes) { + + if (!element) { + return; + } + + var value, + parentAttributes = { }; + + // if there's a parent container (`g` or `a` or `symbol` node), parse its attributes recursively upwards + if (element.parentNode && /^symbol|[g|a]$/i.test(element.parentNode.nodeName)) { + parentAttributes = fabric.parseAttributes(element.parentNode, attributes); + } + + var ownAttributes = attributes.reduce(function(memo, attr) { + value = element.getAttribute(attr); + if (value) { + attr = normalizeAttr(attr); + value = normalizeValue(attr, value, parentAttributes); + + memo[attr] = value; + } + return memo; + }, { }); + + // add values parsed from style, which take precedence over attributes + // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes) + ownAttributes = extend(ownAttributes, + extend(getGlobalStylesForElement(element), fabric.parseStyleAttribute(element))); + + return _setStrokeFillOpacity(extend(parentAttributes, ownAttributes)); + }, + + /** + * Transforms an array of svg elements to corresponding fabric.* instances + * @static + * @memberOf fabric + * @param {Array} elements Array of elements to parse + * @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements) + * @param {Object} [options] Options object + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + parseElements: function(elements, callback, options, reviver) { + new fabric.ElementsParser(elements, callback, options, reviver).parse(); + }, + + /** + * Parses "style" attribute, retuning an object with values + * @static + * @memberOf fabric + * @param {SVGElement} element Element to parse + * @return {Object} Objects with values parsed from style attribute of an element + */ + parseStyleAttribute: function(element) { + var oStyle = { }, + style = element.getAttribute('style'); + + if (!style) { + return oStyle; + } + + if (typeof style === 'string') { + parseStyleString(style, oStyle); + } + else { + parseStyleObject(style, oStyle); + } + + return oStyle; + }, + + /** + * Parses "points" attribute, returning an array of values + * @static + * @memberOf fabric + * @param {String} points points attribute string + * @return {Array} array of points + */ + parsePointsAttribute: function(points) { + + // points attribute is required and must not be empty + if (!points) { + return null; + } + + // replace commas with whitespace and remove bookending whitespace + points = points.replace(/,/g, ' ').trim(); + + points = points.split(/\s+/); + var parsedPoints = [ ], i, len; + + i = 0; + len = points.length; + for (; i < len; i+=2) { + parsedPoints.push({ + x: parseFloat(points[i]), + y: parseFloat(points[i + 1]) + }); + } + + // odd number of points is an error + // if (parsedPoints.length % 2 !== 0) { + // return null; + // } + + return parsedPoints; + }, + + /** + * Returns CSS rules for a given SVG document + * @static + * @function + * @memberOf fabric + * @param {SVGDocument} doc SVG document to parse + * @return {Object} CSS rules of this document + */ + getCSSRules: function(doc) { + var styles = doc.getElementsByTagName('style'), + allRules = { }, rules; + + // very crude parsing of style contents + for (var i = 0, len = styles.length; i < len; i++) { + var styleContents = styles[0].textContent; + + // remove comments + styleContents = styleContents.replace(/\/\*[\s\S]*?\*\//g, ''); + + rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g); + rules = rules.map(function(rule) { return rule.trim(); }); + + rules.forEach(function(rule) { + + var match = rule.match(/([\s\S]*?)\s*\{([^}]*)\}/), + ruleObj = { }, declaration = match[2].trim(), + propertyValuePairs = declaration.replace(/;$/, '').split(/\s*;\s*/); + + for (var i = 0, len = propertyValuePairs.length; i < len; i++) { + var pair = propertyValuePairs[i].split(/\s*:\s*/), + property = normalizeAttr(pair[0]), + value = normalizeValue(property,pair[1],pair[0]); + ruleObj[property] = value; + } + rule = match[1]; + rule.split(',').forEach(function(_rule) { + allRules[_rule.trim()] = fabric.util.object.clone(ruleObj); + }); + }); + } + return allRules; + }, + + /** + * Takes url corresponding to an SVG document, and parses it into a set of fabric objects. Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy) + * @memberof fabric + * @param {String} url + * @param {Function} callback + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + loadSVGFromURL: function(url, callback, reviver) { + + url = url.replace(/^\n\s*/, '').trim(); + svgCache.has(url, function (hasUrl) { + if (hasUrl) { + svgCache.get(url, function (value) { + var enlivedRecord = _enlivenCachedObject(value); + callback(enlivedRecord.objects, enlivedRecord.options); + }); + } + else { + new fabric.util.request(url, { + method: 'get', + onComplete: onComplete + }); + } + }); + + function onComplete(r) { + + var xml = r.responseXML; + if (xml && !xml.documentElement && fabric.window.ActiveXObject && r.responseText) { + xml = new ActiveXObject('Microsoft.XMLDOM'); + xml.async = 'false'; + //IE chokes on DOCTYPE + xml.loadXML(r.responseText.replace(//i,'')); + } + if (!xml || !xml.documentElement) { + return; + } + + fabric.parseSVGDocument(xml.documentElement, function (results, options) { + svgCache.set(url, { + objects: fabric.util.array.invoke(results, 'toObject'), + options: options + }); + callback(results, options); + }, reviver); + } + }, + + /** + * Takes string corresponding to an SVG document, and parses it into a set of fabric objects + * @memberof fabric + * @param {String} string + * @param {Function} callback + * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. + */ + loadSVGFromString: function(string, callback, reviver) { + string = string.trim(); + var doc; + if (typeof DOMParser !== 'undefined') { + var parser = new DOMParser(); + if (parser && parser.parseFromString) { + doc = parser.parseFromString(string, 'text/xml'); + } + } + else if (fabric.window.ActiveXObject) { + doc = new ActiveXObject('Microsoft.XMLDOM'); + doc.async = 'false'; + //IE chokes on DOCTYPE + doc.loadXML(string.replace(//i,'')); + } + + fabric.parseSVGDocument(doc.documentElement, function (results, options) { + callback(results, options); + }, reviver); + }, + + /** + * Creates markup containing SVG font faces + * @param {Array} objects Array of fabric objects + * @return {String} + */ + createSVGFontFacesMarkup: function(objects) { + var markup = ''; + + for (var i = 0, len = objects.length; i < len; i++) { + if (objects[i].type !== 'text' || !objects[i].path) { + continue; + } + + markup += [ + //jscs:disable validateIndentation + '@font-face {', + 'font-family: ', objects[i].fontFamily, '; ', + 'src: url(\'', objects[i].path, '\')', + '}' + //jscs:enable validateIndentation + ].join(''); + } + + if (markup) { + markup = [ + //jscs:disable validateIndentation + '' + //jscs:enable validateIndentation + ].join(''); + } + + return markup; + }, + + /** + * Creates markup containing SVG referenced elements like patterns, gradients etc. + * @param {fabric.Canvas} canvas instance of fabric.Canvas + * @return {String} + */ + createSVGRefElementsMarkup: function(canvas) { + var markup = [ ]; + + _createSVGPattern(markup, canvas, 'backgroundColor'); + _createSVGPattern(markup, canvas, 'overlayColor'); + + return markup.join(''); + } + }); + +})(typeof exports !== 'undefined' ? exports : this); + + +fabric.ElementsParser = function(elements, callback, options, reviver) { + this.elements = elements; + this.callback = callback; + this.options = options; + this.reviver = reviver; +}; + +fabric.ElementsParser.prototype.parse = function() { + this.instances = new Array(this.elements.length); + this.numElements = this.elements.length; + + this.createObjects(); +}; + +fabric.ElementsParser.prototype.createObjects = function() { + for (var i = 0, len = this.elements.length; i < len; i++) { + (function(_this, i) { + setTimeout(function() { + _this.createObject(_this.elements[i], i); + }, 0); + })(this, i); + } +}; + +fabric.ElementsParser.prototype.createObject = function(el, index) { + var klass = fabric[fabric.util.string.capitalize(el.tagName)]; + if (klass && klass.fromElement) { + try { + this._createObject(klass, el, index); + } + catch (err) { + fabric.log(err); + } + } + else { + this.checkIfDone(); + } +}; + +fabric.ElementsParser.prototype._createObject = function(klass, el, index) { + if (klass.async) { + klass.fromElement(el, this.createCallback(index, el), this.options); + } + else { + var obj = klass.fromElement(el, this.options); + this.resolveGradient(obj, 'fill'); + this.resolveGradient(obj, 'stroke'); + this.reviver && this.reviver(el, obj); + this.instances[index] = obj; + this.checkIfDone(); + } +}; + +fabric.ElementsParser.prototype.createCallback = function(index, el) { + var _this = this; + return function(obj) { + _this.resolveGradient(obj, 'fill'); + _this.resolveGradient(obj, 'stroke'); + _this.reviver && _this.reviver(el, obj); + _this.instances[index] = obj; + _this.checkIfDone(); + }; +}; + +fabric.ElementsParser.prototype.resolveGradient = function(obj, property) { + + var instanceFillValue = obj.get(property); + if (!(/^url\(/).test(instanceFillValue)) { + return; + } + var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1); + if (fabric.gradientDefs[gradientId]) { + obj.set(property, + fabric.Gradient.fromElement(fabric.gradientDefs[gradientId], obj)); + } +}; + +fabric.ElementsParser.prototype.checkIfDone = function() { + if (--this.numElements === 0) { + this.instances = this.instances.filter(function(el) { + return el != null; + }); + this.callback(this.instances); + } +}; + + +(function(global) { + + 'use strict'; + + /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Point) { + fabric.warn('fabric.Point is already defined'); + return; + } + + fabric.Point = Point; + + /** + * Point class + * @class fabric.Point + * @memberOf fabric + * @constructor + * @param {Number} x + * @param {Number} y + * @return {fabric.Point} thisArg + */ + function Point(x, y) { + this.x = x; + this.y = y; + } + + Point.prototype = /** @lends fabric.Point.prototype */ { + + constructor: Point, + + /** + * Adds another point to this one and returns another one + * @param {fabric.Point} that + * @return {fabric.Point} new Point instance with added values + */ + add: function (that) { + return new Point(this.x + that.x, this.y + that.y); + }, + + /** + * Adds another point to this one + * @param {fabric.Point} that + * @return {fabric.Point} thisArg + */ + addEquals: function (that) { + this.x += that.x; + this.y += that.y; + return this; + }, + + /** + * Adds value to this point and returns a new one + * @param {Number} scalar + * @return {fabric.Point} new Point with added value + */ + scalarAdd: function (scalar) { + return new Point(this.x + scalar, this.y + scalar); + }, + + /** + * Adds value to this point + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + scalarAddEquals: function (scalar) { + this.x += scalar; + this.y += scalar; + return this; + }, + + /** + * Subtracts another point from this point and returns a new one + * @param {fabric.Point} that + * @return {fabric.Point} new Point object with subtracted values + */ + subtract: function (that) { + return new Point(this.x - that.x, this.y - that.y); + }, + + /** + * Subtracts another point from this point + * @param {fabric.Point} that + * @return {fabric.Point} thisArg + */ + subtractEquals: function (that) { + this.x -= that.x; + this.y -= that.y; + return this; + }, + + /** + * Subtracts value from this point and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + scalarSubtract: function (scalar) { + return new Point(this.x - scalar, this.y - scalar); + }, + + /** + * Subtracts value from this point + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + scalarSubtractEquals: function (scalar) { + this.x -= scalar; + this.y -= scalar; + return this; + }, + + /** + * Miltiplies this point by a value and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + multiply: function (scalar) { + return new Point(this.x * scalar, this.y * scalar); + }, + + /** + * Miltiplies this point by a value + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + multiplyEquals: function (scalar) { + this.x *= scalar; + this.y *= scalar; + return this; + }, + + /** + * Divides this point by a value and returns a new one + * @param {Number} scalar + * @return {fabric.Point} + */ + divide: function (scalar) { + return new Point(this.x / scalar, this.y / scalar); + }, + + /** + * Divides this point by a value + * @param {Number} scalar + * @return {fabric.Point} thisArg + */ + divideEquals: function (scalar) { + this.x /= scalar; + this.y /= scalar; + return this; + }, + + /** + * Returns true if this point is equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + eq: function (that) { + return (this.x === that.x && this.y === that.y); + }, + + /** + * Returns true if this point is less than another one + * @param {fabric.Point} that + * @return {Boolean} + */ + lt: function (that) { + return (this.x < that.x && this.y < that.y); + }, + + /** + * Returns true if this point is less than or equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + lte: function (that) { + return (this.x <= that.x && this.y <= that.y); + }, + + /** + + * Returns true if this point is greater another one + * @param {fabric.Point} that + * @return {Boolean} + */ + gt: function (that) { + return (this.x > that.x && this.y > that.y); + }, + + /** + * Returns true if this point is greater than or equal to another one + * @param {fabric.Point} that + * @return {Boolean} + */ + gte: function (that) { + return (this.x >= that.x && this.y >= that.y); + }, + + /** + * Returns new point which is the result of linear interpolation with this one and another one + * @param {fabric.Point} that + * @param {Number} t + * @return {fabric.Point} + */ + lerp: function (that, t) { + return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t); + }, + + /** + * Returns distance from this point and another one + * @param {fabric.Point} that + * @return {Number} + */ + distanceFrom: function (that) { + var dx = this.x - that.x, + dy = this.y - that.y; + return Math.sqrt(dx * dx + dy * dy); + }, + + /** + * Returns the point between this point and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + midPointFrom: function (that) { + return new Point(this.x + (that.x - this.x)/2, this.y + (that.y - this.y)/2); + }, + + /** + * Returns a new point which is the min of this and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + min: function (that) { + return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y)); + }, + + /** + * Returns a new point which is the max of this and another one + * @param {fabric.Point} that + * @return {fabric.Point} + */ + max: function (that) { + return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y)); + }, + + /** + * Returns string representation of this point + * @return {String} + */ + toString: function () { + return this.x + ',' + this.y; + }, + + /** + * Sets x/y of this point + * @param {Number} x + * @return {Number} y + */ + setXY: function (x, y) { + this.x = x; + this.y = y; + }, + + /** + * Sets x/y of this point from another point + * @param {fabric.Point} that + */ + setFromPoint: function (that) { + this.x = that.x; + this.y = that.y; + }, + + /** + * Swaps x/y of this point and another point + * @param {fabric.Point} that + */ + swap: function (that) { + var x = this.x, + y = this.y; + this.x = that.x; + this.y = that.y; + that.x = x; + that.y = y; + } + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Intersection) { + fabric.warn('fabric.Intersection is already defined'); + return; + } + + /** + * Intersection class + * @class fabric.Intersection + * @memberOf fabric + * @constructor + */ + function Intersection(status) { + this.status = status; + this.points = []; + } + + fabric.Intersection = Intersection; + + fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ { + + /** + * Appends a point to intersection + * @param {fabric.Point} point + */ + appendPoint: function (point) { + this.points.push(point); + }, + + /** + * Appends points to intersection + * @param {Array} points + */ + appendPoints: function (points) { + this.points = this.points.concat(points); + } + }; + + /** + * Checks if one line intersects another + * @static + * @param {fabric.Point} a1 + * @param {fabric.Point} a2 + * @param {fabric.Point} b1 + * @param {fabric.Point} b2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) { + var result, + uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), + ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), + uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); + if (uB !== 0) { + var ua = uaT / uB, + ub = ubT / uB; + if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { + result = new Intersection('Intersection'); + result.points.push(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); + } + else { + result = new Intersection(); + } + } + else { + if (uaT === 0 || ubT === 0) { + result = new Intersection('Coincident'); + } + else { + result = new Intersection('Parallel'); + } + } + return result; + }; + + /** + * Checks if line intersects polygon + * @static + * @param {fabric.Point} a1 + * @param {fabric.Point} a2 + * @param {Array} points + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectLinePolygon = function(a1,a2,points){ + var result = new Intersection(), + length = points.length; + + for (var i = 0; i < length; i++) { + var b1 = points[i], + b2 = points[(i + 1) % length], + inter = Intersection.intersectLineLine(a1, a2, b1, b2); + + result.appendPoints(inter.points); + } + if (result.points.length > 0) { + result.status = 'Intersection'; + } + return result; + }; + + /** + * Checks if polygon intersects another polygon + * @static + * @param {Array} points1 + * @param {Array} points2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectPolygonPolygon = function (points1, points2) { + var result = new Intersection(), + length = points1.length; + + for (var i = 0; i < length; i++) { + var a1 = points1[i], + a2 = points1[(i + 1) % length], + inter = Intersection.intersectLinePolygon(a1, a2, points2); + + result.appendPoints(inter.points); + } + if (result.points.length > 0) { + result.status = 'Intersection'; + } + return result; + }; + + /** + * Checks if polygon intersects rectangle + * @static + * @param {Array} points + * @param {Number} r1 + * @param {Number} r2 + * @return {fabric.Intersection} + */ + fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) { + var min = r1.min(r2), + max = r1.max(r2), + topRight = new fabric.Point(max.x, min.y), + bottomLeft = new fabric.Point(min.x, max.y), + inter1 = Intersection.intersectLinePolygon(min, topRight, points), + inter2 = Intersection.intersectLinePolygon(topRight, max, points), + inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points), + inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points), + result = new Intersection(); + + result.appendPoints(inter1.points); + result.appendPoints(inter2.points); + result.appendPoints(inter3.points); + result.appendPoints(inter4.points); + + if (result.points.length > 0) { + result.status = 'Intersection'; + } + return result; + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Color) { + fabric.warn('fabric.Color is already defined.'); + return; + } + + /** + * Color class + * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations; + * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects. + * + * @class fabric.Color + * @param {String} color optional in hex or rgb(a) format + * @return {fabric.Color} thisArg + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors} + */ + function Color(color) { + if (!color) { + this.setSource([0, 0, 0, 1]); + } + else { + this._tryParsingColor(color); + } + } + + fabric.Color = Color; + + fabric.Color.prototype = /** @lends fabric.Color.prototype */ { + + /** + * @private + * @param {String|Array} color Color value to parse + */ + _tryParsingColor: function(color) { + var source; + + if (color in Color.colorNameMap) { + color = Color.colorNameMap[color]; + } + + if (color === 'transparent') { + this.setSource([255,255,255,0]); + return; + } + + source = Color.sourceFromHex(color); + + if (!source) { + source = Color.sourceFromRgb(color); + } + if (!source) { + source = Color.sourceFromHsl(color); + } + if (source) { + this.setSource(source); + } + }, + + /** + * Adapted from https://github.com/mjijackson + * @private + * @param {Number} r Red color value + * @param {Number} g Green color value + * @param {Number} b Blue color value + * @return {Array} Hsl color + */ + _rgbToHsl: function(r, g, b) { + r /= 255, g /= 255, b /= 255; + + var h, s, l, + max = fabric.util.array.max([r, g, b]), + min = fabric.util.array.min([r, g, b]); + + l = (max + min) / 2; + + if (max === min) { + h = s = 0; // achromatic + } + else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + + return [ + Math.round(h * 360), + Math.round(s * 100), + Math.round(l * 100) + ]; + }, + + /** + * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1]) + * @return {Array} + */ + getSource: function() { + return this._source; + }, + + /** + * Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1]) + * @param {Array} source + */ + setSource: function(source) { + this._source = source; + }, + + /** + * Returns color represenation in RGB format + * @return {String} ex: rgb(0-255,0-255,0-255) + */ + toRgb: function() { + var source = this.getSource(); + return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')'; + }, + + /** + * Returns color represenation in RGBA format + * @return {String} ex: rgba(0-255,0-255,0-255,0-1) + */ + toRgba: function() { + var source = this.getSource(); + return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')'; + }, + + /** + * Returns color represenation in HSL format + * @return {String} ex: hsl(0-360,0%-100%,0%-100%) + */ + toHsl: function() { + var source = this.getSource(), + hsl = this._rgbToHsl(source[0], source[1], source[2]); + + return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)'; + }, + + /** + * Returns color represenation in HSLA format + * @return {String} ex: hsla(0-360,0%-100%,0%-100%,0-1) + */ + toHsla: function() { + var source = this.getSource(), + hsl = this._rgbToHsl(source[0], source[1], source[2]); + + return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')'; + }, + + /** + * Returns color represenation in HEX format + * @return {String} ex: FF5555 + */ + toHex: function() { + var source = this.getSource(), r, g, b; + + r = source[0].toString(16); + r = (r.length === 1) ? ('0' + r) : r; + + g = source[1].toString(16); + g = (g.length === 1) ? ('0' + g) : g; + + b = source[2].toString(16); + b = (b.length === 1) ? ('0' + b) : b; + + return r.toUpperCase() + g.toUpperCase() + b.toUpperCase(); + }, + + /** + * Gets value of alpha channel for this color + * @return {Number} 0-1 + */ + getAlpha: function() { + return this.getSource()[3]; + }, + + /** + * Sets value of alpha channel for this color + * @param {Number} alpha Alpha value 0-1 + * @return {fabric.Color} thisArg + */ + setAlpha: function(alpha) { + var source = this.getSource(); + source[3] = alpha; + this.setSource(source); + return this; + }, + + /** + * Transforms color to its grayscale representation + * @return {fabric.Color} thisArg + */ + toGrayscale: function() { + var source = this.getSource(), + average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10), + currentAlpha = source[3]; + this.setSource([average, average, average, currentAlpha]); + return this; + }, + + /** + * Transforms color to its black and white representation + * @param {Number} threshold + * @return {fabric.Color} thisArg + */ + toBlackWhite: function(threshold) { + var source = this.getSource(), + average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), + currentAlpha = source[3]; + + threshold = threshold || 127; + + average = (Number(average) < Number(threshold)) ? 0 : 255; + this.setSource([average, average, average, currentAlpha]); + return this; + }, + + /** + * Overlays color with another color + * @param {String|fabric.Color} otherColor + * @return {fabric.Color} thisArg + */ + overlayWith: function(otherColor) { + if (!(otherColor instanceof Color)) { + otherColor = new Color(otherColor); + } + + var result = [], + alpha = this.getAlpha(), + otherAlpha = 0.5, + source = this.getSource(), + otherSource = otherColor.getSource(); + + for (var i = 0; i < 3; i++) { + result.push(Math.round((source[i] * (1 - otherAlpha)) + (otherSource[i] * otherAlpha))); + } + + result[3] = alpha; + this.setSource(result); + return this; + } + }; + + /** + * Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5)) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reRGBa = /^rgba?\(\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; + + /** + * Regex matching color in HSL or HSLA formats (ex: hsl(200, 80%, 10%), hsla(300, 50%, 80%, 0.5), hsla( 300 , 50% , 80% , 0.5 )) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; + + /** + * Regex matching color in HEX format (ex: #FF5555, 010155, aff) + * @static + * @field + * @memberOf fabric.Color + */ + fabric.Color.reHex = /^#?([0-9a-f]{6}|[0-9a-f]{3})$/i; + + /** + * Map of the 17 basic color names with HEX code + * @static + * @field + * @memberOf fabric.Color + * @see: http://www.w3.org/TR/CSS2/syndata.html#color-units + */ + fabric.Color.colorNameMap = { + aqua: '#00FFFF', + black: '#000000', + blue: '#0000FF', + fuchsia: '#FF00FF', + gray: '#808080', + green: '#008000', + lime: '#00FF00', + maroon: '#800000', + navy: '#000080', + olive: '#808000', + orange: '#FFA500', + purple: '#800080', + red: '#FF0000', + silver: '#C0C0C0', + teal: '#008080', + white: '#FFFFFF', + yellow: '#FFFF00' + }; + + /** + * @private + * @param {Number} p + * @param {Number} q + * @param {Number} t + * @return {Number} + */ + function hue2rgb(p, q, t){ + if (t < 0) { + t += 1; + } + if (t > 1) { + t -= 1; + } + if (t < 1/6) { + return p + (q - p) * 6 * t; + } + if (t < 1/2) { + return q; + } + if (t < 2/3) { + return p + (q - p) * (2/3 - t) * 6; + } + return p; + } + + /** + * Returns new color object, when given a color in RGB format + * @memberOf fabric.Color + * @param {String} color Color value ex: rgb(0-255,0-255,0-255) + * @return {fabric.Color} + */ + fabric.Color.fromRgb = function(color) { + return Color.fromSource(Color.sourceFromRgb(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format + * @memberOf fabric.Color + * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%) + * @return {Array} source + */ + fabric.Color.sourceFromRgb = function(color) { + var match = color.match(Color.reRGBa); + if (match) { + var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1), + g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1), + b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1); + + return [ + parseInt(r, 10), + parseInt(g, 10), + parseInt(b, 10), + match[4] ? parseFloat(match[4]) : 1 + ]; + } + }; + + /** + * Returns new color object, when given a color in RGBA format + * @static + * @function + * @memberOf fabric.Color + * @param {String} color + * @return {fabric.Color} + */ + fabric.Color.fromRgba = Color.fromRgb; + + /** + * Returns new color object, when given a color in HSL format + * @param {String} color Color value ex: hsl(0-260,0%-100%,0%-100%) + * @memberOf fabric.Color + * @return {fabric.Color} + */ + fabric.Color.fromHsl = function(color) { + return Color.fromSource(Color.sourceFromHsl(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format. + * Adapted from https://github.com/mjijackson + * @memberOf fabric.Color + * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1) + * @return {Array} source + * @see http://http://www.w3.org/TR/css3-color/#hsl-color + */ + fabric.Color.sourceFromHsl = function(color) { + var match = color.match(Color.reHSLa); + if (!match) { + return; + } + + var h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360, + s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1), + l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1), + r, g, b; + + if (s === 0) { + r = g = b = l; + } + else { + var q = l <= 0.5 ? l * (s + 1) : l + s - l * s, + p = l * 2 - q; + + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return [ + Math.round(r * 255), + Math.round(g * 255), + Math.round(b * 255), + match[4] ? parseFloat(match[4]) : 1 + ]; + }; + + /** + * Returns new color object, when given a color in HSLA format + * @static + * @function + * @memberOf fabric.Color + * @param {String} color + * @return {fabric.Color} + */ + fabric.Color.fromHsla = Color.fromHsl; + + /** + * Returns new color object, when given a color in HEX format + * @static + * @memberOf fabric.Color + * @param {String} color Color value ex: FF5555 + * @return {fabric.Color} + */ + fabric.Color.fromHex = function(color) { + return Color.fromSource(Color.sourceFromHex(color)); + }; + + /** + * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HEX format + * @static + * @memberOf fabric.Color + * @param {String} color ex: FF5555 + * @return {Array} source + */ + fabric.Color.sourceFromHex = function(color) { + if (color.match(Color.reHex)) { + var value = color.slice(color.indexOf('#') + 1), + isShortNotation = (value.length === 3), + r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2), + g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4), + b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6); + + return [ + parseInt(r, 16), + parseInt(g, 16), + parseInt(b, 16), + 1 + ]; + } + }; + + /** + * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5]) + * @static + * @memberOf fabric.Color + * @param {Array} source + * @return {fabric.Color} + */ + fabric.Color.fromSource = function(source) { + var oColor = new Color(); + oColor.setSource(source); + return oColor; + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + /* _FROM_SVG_START_ */ + function getColorStop(el) { + var style = el.getAttribute('style'), + offset = el.getAttribute('offset'), + color, colorAlpha, opacity; + + // convert percents to absolute values + offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1); + + if (style) { + var keyValuePairs = style.split(/\s*;\s*/); + + if (keyValuePairs[keyValuePairs.length - 1] === '') { + keyValuePairs.pop(); + } + + for (var i = keyValuePairs.length; i--; ) { + + var split = keyValuePairs[i].split(/\s*:\s*/), + key = split[0].trim(), + value = split[1].trim(); + + if (key === 'stop-color') { + color = value; + } + else if (key === 'stop-opacity') { + opacity = value; + } + } + } + + if (!color) { + color = el.getAttribute('stop-color') || 'rgb(0,0,0)'; + } + if (!opacity) { + opacity = el.getAttribute('stop-opacity'); + } + + color = new fabric.Color(color); + colorAlpha = color.getAlpha(); + opacity = isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity); + opacity *= colorAlpha; + + return { + offset: offset, + color: color.toRgb(), + opacity: opacity + }; + } + + function getLinearCoords(el) { + return { + x1: el.getAttribute('x1') || 0, + y1: el.getAttribute('y1') || 0, + x2: el.getAttribute('x2') || '100%', + y2: el.getAttribute('y2') || 0 + }; + } + + function getRadialCoords(el) { + return { + x1: el.getAttribute('fx') || el.getAttribute('cx') || '50%', + y1: el.getAttribute('fy') || el.getAttribute('cy') || '50%', + r1: 0, + x2: el.getAttribute('cx') || '50%', + y2: el.getAttribute('cy') || '50%', + r2: el.getAttribute('r') || '50%' + }; + } + /* _FROM_SVG_END_ */ + + /** + * Gradient class + * @class fabric.Gradient + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#gradients} + * @see {@link fabric.Gradient#initialize} for constructor definition + */ + fabric.Gradient = fabric.util.createClass(/** @lends fabric.Gradient.prototype */ { + /* + * Stores the original position of the gradient when we convert from % to fixed values, for objectBoundingBox case. + * @type Number + * @default 0 + */ + origX: 0, + + /* + * Stores the original position of the gradient when we convert from % to fixed values, for objectBoundingBox case. + * @type Number + * @default 0 + */ + origY: 0, + + /** + * Constructor + * @param {Object} [options] Options object with type, coords, gradientUnits and colorStops + * @return {fabric.Gradient} thisArg + */ + initialize: function(options) { + options || (options = { }); + + var coords = { }; + + this.id = fabric.Object.__uid++; + this.type = options.type || 'linear'; + + coords = { + x1: options.coords.x1 || 0, + y1: options.coords.y1 || 0, + x2: options.coords.x2 || 0, + y2: options.coords.y2 || 0 + }; + + if (this.type === 'radial') { + coords.r1 = options.coords.r1 || 0; + coords.r2 = options.coords.r2 || 0; + } + + this.coords = coords; + this.gradientUnits = options.gradientUnits || 'objectBoundingBox'; + this.colorStops = options.colorStops.slice(); + if (options.gradientTransform) { + this.gradientTransform = options.gradientTransform; + } + this.origX = options.left || this.origX; + this.origY = options.top || this.origY; + }, + + /** + * Adds another colorStop + * @param {Object} colorStop Object with offset and color + * @return {fabric.Gradient} thisArg + */ + addColorStop: function(colorStop) { + for (var position in colorStop) { + var color = new fabric.Color(colorStop[position]); + this.colorStops.push({ + offset: position, + color: color.toRgb(), + opacity: color.getAlpha() + }); + } + return this; + }, + + /** + * Returns object representation of a gradient + * @return {Object} + */ + toObject: function() { + return { + type: this.type, + coords: this.coords, + gradientUnits: this.gradientUnits, + colorStops: this.colorStops + }; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an gradient + * @param {Object} object Object to create a gradient for + * @param {Boolean} normalize Whether coords should be normalized + * @return {String} SVG representation of an gradient (linear/radial) + */ + toSVG: function(object, normalize) { + var coords = fabric.util.object.clone(this.coords), + markup, commonAttributes; + + // colorStops must be sorted ascending + this.colorStops.sort(function(a, b) { + return a.offset - b.offset; + }); + + if (normalize && this.gradientUnits === 'userSpaceOnUse') { + coords.x1 += object.width / 2; + coords.y1 += object.height / 2; + coords.x2 += object.width / 2; + coords.y2 += object.height / 2; + } + else if (this.gradientUnits === 'objectBoundingBox') { + _convertValuesToPercentUnits(object, coords); + } + commonAttributes = 'id="SVGID_' + this.id + + '" gradientUnits="' + this.gradientUnits + '"'; + if (this.gradientTransform) { + commonAttributes += ' gradientTransform="matrix(' + this.gradientTransform.join(' ') + ')" '; + } + if (this.type === 'linear') { + markup = [ + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ]; + } + else if (this.type === 'radial') { + markup = [ + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ]; + } + + for (var i = 0; i < this.colorStops.length; i++) { + markup.push( + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ); + } + + markup.push((this.type === 'linear' ? '\n' : '\n')); + + return markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns an instance of CanvasGradient + * @param {CanvasRenderingContext2D} ctx Context to render on + * @return {CanvasGradient} + */ + toLive: function(ctx) { + var gradient; + + if (!this.type) { + return; + } + + if (this.type === 'linear') { + gradient = ctx.createLinearGradient( + this.coords.x1, this.coords.y1, this.coords.x2, this.coords.y2); + } + else if (this.type === 'radial') { + gradient = ctx.createRadialGradient( + this.coords.x1, this.coords.y1, this.coords.r1, this.coords.x2, this.coords.y2, this.coords.r2); + } + + for (var i = 0, len = this.colorStops.length; i < len; i++) { + var color = this.colorStops[i].color, + opacity = this.colorStops[i].opacity, + offset = this.colorStops[i].offset; + + if (typeof opacity !== 'undefined') { + color = new fabric.Color(color).setAlpha(opacity).toRgba(); + } + gradient.addColorStop(parseFloat(offset), color); + } + + return gradient; + } + }); + + fabric.util.object.extend(fabric.Gradient, { + + /* _FROM_SVG_START_ */ + /** + * Returns {@link fabric.Gradient} instance from an SVG element + * @static + * @memberof fabric.Gradient + * @param {SVGGradientElement} el SVG gradient element + * @param {fabric.Object} instance + * @return {fabric.Gradient} Gradient instance + * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement + * @see http://www.w3.org/TR/SVG/pservers.html#RadialGradientElement + */ + fromElement: function(el, instance) { + + /** + * @example: + * + * + * + * + * + * + * OR + * + * + * + * + * + * + * OR + * + * + * + * + * + * + * + * OR + * + * + * + * + * + * + * + */ + + var colorStopEls = el.getElementsByTagName('stop'), + type = (el.nodeName === 'linearGradient' ? 'linear' : 'radial'), + gradientUnits = el.getAttribute('gradientUnits') || 'objectBoundingBox', + gradientTransform = el.getAttribute('gradientTransform'), + colorStops = [], + coords = { }; + + if (type === 'linear') { + coords = getLinearCoords(el); + } + else if (type === 'radial') { + coords = getRadialCoords(el); + } + + for (var i = colorStopEls.length; i--; ) { + colorStops.push(getColorStop(colorStopEls[i])); + } + + _convertPercentUnitsToValues(instance, coords); + + var gradient = new fabric.Gradient({ + type: type, + coords: coords, + gradientUnits: gradientUnits, + colorStops: colorStops + }); + + if (gradientTransform) { + gradient.gradientTransform = fabric.parseTransformAttribute(gradientTransform); + } + + return gradient; + }, + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Gradient} instance from its object representation + * @static + * @memberof fabric.Gradient + * @param {Object} obj + * @param {Object} [options] Options object + */ + forObject: function(obj, options) { + options || (options = { }); + _convertPercentUnitsToValues(obj, options); + return new fabric.Gradient(options); + } + }); + + /** + * @private + */ + function _convertPercentUnitsToValues(object, options) { + for (var prop in options) { + if (typeof options[prop] === 'string' && /^\d+%$/.test(options[prop])) { + var percents = parseFloat(options[prop], 10); + if (prop === 'x1' || prop === 'x2' || prop === 'r2') { + options[prop] = fabric.util.toFixed(object.width * percents / 100, 2) + object.left; + } + else if (prop === 'y1' || prop === 'y2') { + options[prop] = fabric.util.toFixed(object.height * percents / 100, 2) + object.top; + } + } + } + } + + /* _TO_SVG_START_ */ + /** + * @private + */ + function _convertValuesToPercentUnits(object, options) { + for (var prop in options) { + //convert to percent units + if (prop === 'x1' || prop === 'x2' || prop === 'r2') { + options[prop] = fabric.util.toFixed((options[prop] - object.fill.origX) / object.width * 100, 2) + '%'; + } + else if (prop === 'y1' || prop === 'y2') { + options[prop] = fabric.util.toFixed((options[prop] - object.fill.origY) / object.height * 100, 2) + '%'; + } + } + } + /* _TO_SVG_END_ */ + +})(); + + +/** + * Pattern class + * @class fabric.Pattern + * @see {@link http://fabricjs.com/patterns/|Pattern demo} + * @see {@link http://fabricjs.com/dynamic-patterns/|DynamicPattern demo} + * @see {@link fabric.Pattern#initialize} for constructor definition + */ +fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ { + + /** + * Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat) + * @type String + * @default + */ + repeat: 'repeat', + + /** + * Pattern horizontal offset from object's left/top corner + * @type Number + * @default + */ + offsetX: 0, + + /** + * Pattern vertical offset from object's left/top corner + * @type Number + * @default + */ + offsetY: 0, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Pattern} thisArg + */ + initialize: function(options) { + options || (options = { }); + + this.id = fabric.Object.__uid++; + + if (options.source) { + if (typeof options.source === 'string') { + // function string + if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') { + this.source = new Function(fabric.util.getFunctionBody(options.source)); + } + else { + // img src string + var _this = this; + this.source = fabric.util.createImage(); + fabric.util.loadImage(options.source, function(img) { + _this.source = img; + }); + } + } + else { + // img element + this.source = options.source; + } + } + if (options.repeat) { + this.repeat = options.repeat; + } + if (options.offsetX) { + this.offsetX = options.offsetX; + } + if (options.offsetY) { + this.offsetY = options.offsetY; + } + }, + + /** + * Returns object representation of a pattern + * @return {Object} Object representation of a pattern instance + */ + toObject: function() { + + var source; + + // callback + if (typeof this.source === 'function') { + source = String(this.source); + } + // element + else if (typeof this.source.src === 'string') { + source = this.source.src; + } + + return { + source: source, + repeat: this.repeat, + offsetX: this.offsetX, + offsetY: this.offsetY + }; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of a pattern + * @param {fabric.Object} object + * @return {String} SVG representation of a pattern + */ + toSVG: function(object) { + var patternSource = typeof this.source === 'function' ? this.source() : this.source, + patternWidth = patternSource.width / object.getWidth(), + patternHeight = patternSource.height / object.getHeight(), + patternImgSrc = ''; + + if (patternSource.src) { + patternImgSrc = patternSource.src; + } + else if (patternSource.toDataURL) { + patternImgSrc = patternSource.toDataURL(); + } + + return '' + + '' + + ''; + }, + /* _TO_SVG_END_ */ + + /** + * Returns an instance of CanvasPattern + * @param {CanvasRenderingContext2D} ctx Context to create pattern + * @return {CanvasPattern} + */ + toLive: function(ctx) { + var source = typeof this.source === 'function' + ? this.source() + : this.source; + + // if the image failed to load, return, and allow rest to continue loading + if (!source) { + return ''; + } + + // if an image + if (typeof source.src !== 'undefined') { + if (!source.complete) { + return ''; + } + if (source.naturalWidth === 0 || source.naturalHeight === 0) { + return ''; + } + } + return ctx.createPattern(source, this.repeat); + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Shadow) { + fabric.warn('fabric.Shadow is already defined.'); + return; + } + + /** + * Shadow class + * @class fabric.Shadow + * @see {@link http://fabricjs.com/shadows/|Shadow demo} + * @see {@link fabric.Shadow#initialize} for constructor definition + */ + fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ { + + /** + * Shadow color + * @type String + * @default + */ + color: 'rgb(0,0,0)', + + /** + * Shadow blur + * @type Number + */ + blur: 0, + + /** + * Shadow horizontal offset + * @type Number + * @default + */ + offsetX: 0, + + /** + * Shadow vertical offset + * @type Number + * @default + */ + offsetY: 0, + + /** + * Whether the shadow should affect stroke operations + * @type Boolean + * @default + */ + affectStroke: false, + + /** + * Indicates whether toObject should include default values + * @type Boolean + * @default + */ + includeDefaultValues: true, + + /** + * Constructor + * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetX properties or string (e.g. "rgba(0,0,0,0.2) 2px 2px 10px, "2px 2px 10px rgba(0,0,0,0.2)") + * @return {fabric.Shadow} thisArg + */ + initialize: function(options) { + + if (typeof options === 'string') { + options = this._parseShadow(options); + } + + for (var prop in options) { + this[prop] = options[prop]; + } + + this.id = fabric.Object.__uid++; + }, + + /** + * @private + * @param {String} shadow Shadow value to parse + * @return {Object} Shadow object with color, offsetX, offsetY and blur + */ + _parseShadow: function(shadow) { + var shadowStr = shadow.trim(), + offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [ ], + color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, '') || 'rgb(0,0,0)'; + + return { + color: color.trim(), + offsetX: parseInt(offsetsAndBlur[1], 10) || 0, + offsetY: parseInt(offsetsAndBlur[2], 10) || 0, + blur: parseInt(offsetsAndBlur[3], 10) || 0 + }; + }, + + /** + * Returns a string representation of an instance + * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow + * @return {String} Returns CSS3 text-shadow declaration + */ + toString: function() { + return [this.offsetX, this.offsetY, this.blur, this.color].join('px '); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of a shadow + * @param {fabric.Object} object + * @return {String} SVG representation of a shadow + */ + toSVG: function(object) { + var mode = 'SourceAlpha'; + + if (object && (object.fill === this.color || object.stroke === this.color)) { + mode = 'SourceGraphic'; + } + + return ( + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns object representation of a shadow + * @return {Object} Object representation of a shadow instance + */ + toObject: function() { + if (this.includeDefaultValues) { + return { + color: this.color, + blur: this.blur, + offsetX: this.offsetX, + offsetY: this.offsetY + }; + } + var obj = { }, proto = fabric.Shadow.prototype; + if (this.color !== proto.color) { + obj.color = this.color; + } + if (this.blur !== proto.blur) { + obj.blur = this.blur; + } + if (this.offsetX !== proto.offsetX) { + obj.offsetX = this.offsetX; + } + if (this.offsetY !== proto.offsetY) { + obj.offsetY = this.offsetY; + } + return obj; + } + }); + + /** + * Regex matching shadow offsetX, offsetY and blur (ex: "2px 2px 10px rgba(0,0,0,0.2)", "rgb(0,255,0) 2px 2px") + * @static + * @field + * @memberOf fabric.Shadow + */ + fabric.Shadow.reOffsetsAndBlur = /(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function () { + + 'use strict'; + + if (fabric.StaticCanvas) { + fabric.warn('fabric.StaticCanvas is already defined.'); + return; + } + + // aliases for faster resolution + var extend = fabric.util.object.extend, + getElementOffset = fabric.util.getElementOffset, + removeFromArray = fabric.util.removeFromArray, + + CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element'); + + /** + * Static canvas class + * @class fabric.StaticCanvas + * @mixes fabric.Collection + * @mixes fabric.Observable + * @see {@link http://fabricjs.com/static_canvas/|StaticCanvas demo} + * @see {@link fabric.StaticCanvas#initialize} for constructor definition + * @fires before:render + * @fires after:render + * @fires canvas:cleared + * @fires object:added + * @fires object:removed + */ + fabric.StaticCanvas = fabric.util.createClass(/** @lends fabric.StaticCanvas.prototype */ { + + /** + * Constructor + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(el, options) { + options || (options = { }); + + this._initStatic(el, options); + fabric.StaticCanvas.activeInstance = this; + }, + + /** + * Background color of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setBackgroundColor}. + * @type {(String|fabric.Pattern)} + * @default + */ + backgroundColor: '', + + /** + * Background image of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setBackgroundImage}. + * Backwards incompatibility note: The "backgroundImageOpacity" + * and "backgroundImageStretch" properties are deprecated since 1.3.9. + * Use {@link fabric.Image#opacity}, {@link fabric.Image#width} and {@link fabric.Image#height}. + * @type fabric.Image + * @default + */ + backgroundImage: null, + + /** + * Overlay color of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setOverlayColor} + * @since 1.3.9 + * @type {(String|fabric.Pattern)} + * @default + */ + overlayColor: '', + + /** + * Overlay image of canvas instance. + * Should be set via {@link fabric.StaticCanvas#setOverlayImage}. + * Backwards incompatibility note: The "overlayImageLeft" + * and "overlayImageTop" properties are deprecated since 1.3.9. + * Use {@link fabric.Image#left} and {@link fabric.Image#top}. + * @type fabric.Image + * @default + */ + overlayImage: null, + + /** + * Indicates whether toObject/toDatalessObject should include default values + * @type Boolean + * @default + */ + includeDefaultValues: true, + + /** + * Indicates whether objects' state should be saved + * @type Boolean + * @default + */ + stateful: true, + + /** + * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove} should also re-render canvas. + * Disabling this option could give a great performance boost when adding/removing a lot of objects to/from canvas at once + * (followed by a manual rendering after addition/deletion) + * @type Boolean + * @default + */ + renderOnAddRemove: true, + + /** + * Function that determines clipping of entire canvas area + * Being passed context as first argument. See clipping canvas area in {@link https://github.com/kangax/fabric.js/wiki/FAQ} + * @type Function + * @default + */ + clipTo: null, + + /** + * Indicates whether object controls (borders/controls) are rendered above overlay image + * @type Boolean + * @default + */ + controlsAboveOverlay: false, + + /** + * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas + * @type Boolean + * @default + */ + allowTouchScrolling: false, + + /** + * Indicates whether this canvas will use image smoothing, this is on by default in browsers + * @type Boolean + * @default + */ + imageSmoothingEnabled: true, + + /** + * The transformation (in the format of Canvas transform) which focuses the viewport + * @type Array + * @default + */ + viewportTransform: [1, 0, 0, 1, 0, 0], + + /** + * Callback; invoked right before object is about to be scaled/rotated + */ + onBeforeScaleRotate: function () { + /* NOOP */ + }, + + /** + * @private + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + */ + _initStatic: function(el, options) { + this._objects = []; + + this._createLowerCanvas(el); + this._initOptions(options); + this._setImageSmoothing(); + + if (options.overlayImage) { + this.setOverlayImage(options.overlayImage, this.renderAll.bind(this)); + } + if (options.backgroundImage) { + this.setBackgroundImage(options.backgroundImage, this.renderAll.bind(this)); + } + if (options.backgroundColor) { + this.setBackgroundColor(options.backgroundColor, this.renderAll.bind(this)); + } + if (options.overlayColor) { + this.setOverlayColor(options.overlayColor, this.renderAll.bind(this)); + } + this.calcOffset(); + }, + + /** + * Calculates canvas element offset relative to the document + * This method is also attached as "resize" event handler of window + * @return {fabric.Canvas} instance + * @chainable + */ + calcOffset: function () { + this._offset = getElementOffset(this.lowerCanvasEl); + return this; + }, + + /** + * Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas + * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set overlay to + * @param {Function} callback callback to invoke when image is loaded and set as an overlay + * @param {Object} [options] Optional options to set for the {@link fabric.Image|overlay image}. + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo} + * @example + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * // Needed to position overlayImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + * @example + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * opacity: 0.5, + * angle: 45, + * left: 400, + * top: 400, + * originX: 'left', + * originY: 'top' + * }); + * @example + * fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img) { + * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); + * canvas.setOverlayImage(img, canvas.renderAll.bind(canvas)); + * }); + * @example + * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { + * width: canvas.width, + * height: canvas.height, + * // Needed to position overlayImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + */ + setOverlayImage: function (image, callback, options) { + return this.__setBgOverlayImage('overlayImage', image, callback, options); + }, + + /** + * Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas + * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background to + * @param {Function} callback Callback to invoke when image is loaded and set as background + * @param {Object} [options] Optional options to set for the {@link fabric.Image|background image}. + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/YH9yD/|jsFiddle demo} + * @example + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * // Needed to position backgroundImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + * @example + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * opacity: 0.5, + * angle: 45, + * left: 400, + * top: 400, + * originX: 'left', + * originY: 'top' + * }); + * @example + * fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img) { + * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); + * canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas)); + * }); + * @example + * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), { + * width: canvas.width, + * height: canvas.height, + * // Needed to position backgroundImage at 0/0 + * originX: 'left', + * originY: 'top' + * }); + */ + setBackgroundImage: function (image, callback, options) { + return this.__setBgOverlayImage('backgroundImage', image, callback, options); + }, + + /** + * Sets {@link fabric.StaticCanvas#overlayColor|background color} for this canvas + * @param {(String|fabric.Pattern)} overlayColor Color or pattern to set background color to + * @param {Function} callback Callback to invoke when background color is set + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/pB55h/|jsFiddle demo} + * @example + * canvas.setOverlayColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas)); + * @example + * canvas.setOverlayColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png' + * }, canvas.renderAll.bind(canvas)); + * @example + * canvas.setOverlayColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png', + * repeat: 'repeat', + * offsetX: 200, + * offsetY: 100 + * }, canvas.renderAll.bind(canvas)); + */ + setOverlayColor: function(overlayColor, callback) { + return this.__setBgOverlayColor('overlayColor', overlayColor, callback); + }, + + /** + * Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas + * @param {(String|fabric.Pattern)} backgroundColor Color or pattern to set background color to + * @param {Function} callback Callback to invoke when background color is set + * @return {fabric.Canvas} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo} + * @example + * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas)); + * @example + * canvas.setBackgroundColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png' + * }, canvas.renderAll.bind(canvas)); + * @example + * canvas.setBackgroundColor({ + * source: 'http://fabricjs.com/assets/escheresque_ste.png', + * repeat: 'repeat', + * offsetX: 200, + * offsetY: 100 + * }, canvas.renderAll.bind(canvas)); + */ + setBackgroundColor: function(backgroundColor, callback) { + return this.__setBgOverlayColor('backgroundColor', backgroundColor, callback); + }, + + /** + * @private + * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-imagesmoothingenabled|WhatWG Canvas Standard} + */ + _setImageSmoothing: function(){ + var ctx = this.getContext(); + + ctx.imageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.webkitImageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.mozImageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.msImageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.oImageSmoothingEnabled = this.imageSmoothingEnabled; + }, + + /** + * @private + * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage} + * or {@link fabric.StaticCanvas#overlayImage|overlayImage}) + * @param {(fabric.Image|String|null)} image fabric.Image instance, URL of an image or null to set background or overlay to + * @param {Function} callback Callback to invoke when image is loaded and set as background or overlay + * @param {Object} [options] Optional options to set for the {@link fabric.Image|image}. + */ + __setBgOverlayImage: function(property, image, callback, options) { + if (typeof image === 'string') { + fabric.util.loadImage(image, function(img) { + this[property] = new fabric.Image(img, options); + callback && callback(); + }, this); + } + else { + this[property] = image; + callback && callback(); + } + + return this; + }, + + /** + * @private + * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundColor|backgroundColor} + * or {@link fabric.StaticCanvas#overlayColor|overlayColor}) + * @param {(Object|String|null)} color Object with pattern information, color value or null + * @param {Function} [callback] Callback is invoked when color is set + */ + __setBgOverlayColor: function(property, color, callback) { + if (color && color.source) { + var _this = this; + fabric.util.loadImage(color.source, function(img) { + _this[property] = new fabric.Pattern({ + source: img, + repeat: color.repeat, + offsetX: color.offsetX, + offsetY: color.offsetY + }); + callback && callback(); + }); + } + else { + this[property] = color; + callback && callback(); + } + + return this; + }, + + /** + * @private + */ + _createCanvasElement: function() { + var element = fabric.document.createElement('canvas'); + if (!element.style) { + element.style = { }; + } + if (!element) { + throw CANVAS_INIT_ERROR; + } + this._initCanvasElement(element); + return element; + }, + + /** + * @private + * @param {HTMLElement} element + */ + _initCanvasElement: function(element) { + fabric.util.createCanvasElement(element); + + if (typeof element.getContext === 'undefined') { + throw CANVAS_INIT_ERROR; + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initOptions: function (options) { + for (var prop in options) { + this[prop] = options[prop]; + } + + this.width = this.width || parseInt(this.lowerCanvasEl.width, 10) || 0; + this.height = this.height || parseInt(this.lowerCanvasEl.height, 10) || 0; + + if (!this.lowerCanvasEl.style) { + return; + } + + this.lowerCanvasEl.width = this.width; + this.lowerCanvasEl.height = this.height; + + this.lowerCanvasEl.style.width = this.width + 'px'; + this.lowerCanvasEl.style.height = this.height + 'px'; + + this.viewportTransform = this.viewportTransform.slice(); + }, + + /** + * Creates a bottom canvas + * @private + * @param {HTMLElement} [canvasEl] + */ + _createLowerCanvas: function (canvasEl) { + this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement(); + this._initCanvasElement(this.lowerCanvasEl); + + fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas'); + + if (this.interactive) { + this._applyCanvasStyle(this.lowerCanvasEl); + } + + this.contextContainer = this.lowerCanvasEl.getContext('2d'); + }, + + /** + * Returns canvas width (in px) + * @return {Number} + */ + getWidth: function () { + return this.width; + }, + + /** + * Returns canvas height (in px) + * @return {Number} + */ + getHeight: function () { + return this.height; + }, + + /** + * Sets width of this canvas instance + * @param {Number|String} value Value to set width to + * @param {Object} [options] Options object + * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions + * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions + * @return {fabric.Canvas} instance + * @chainable true + */ + setWidth: function (value, options) { + return this.setDimensions({ width: value }, options); + }, + + /** + * Sets height of this canvas instance + * @param {Number|String} value Value to set height to + * @param {Object} [options] Options object + * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions + * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions + * @return {fabric.Canvas} instance + * @chainable true + */ + setHeight: function (value, options) { + return this.setDimensions({ height: value }, options); + }, + + /** + * Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em) + * @param {Object} dimensions Object with width/height properties + * @param {Number|String} [dimensions.width] Width of canvas element + * @param {Number|String} [dimensions.height] Height of canvas element + * @param {Object} [options] Options object + * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions + * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions + * @return {fabric.Canvas} thisArg + * @chainable + */ + setDimensions: function (dimensions, options) { + var cssValue; + + options = options || {}; + + for (var prop in dimensions) { + cssValue = dimensions[prop]; + + if (!options.cssOnly) { + this._setBackstoreDimension(prop, dimensions[prop]); + cssValue += 'px'; + } + + if (!options.backstoreOnly) { + this._setCssDimension(prop, cssValue); + } + } + + if (!options.cssOnly) { + this.renderAll(); + } + + this.calcOffset(); + + return this; + }, + + /** + * Helper for setting width/height + * @private + * @param {String} prop property (width|height) + * @param {Number} value value to set property to + * @return {fabric.Canvas} instance + * @chainable true + */ + _setBackstoreDimension: function (prop, value) { + this.lowerCanvasEl[prop] = value; + + if (this.upperCanvasEl) { + this.upperCanvasEl[prop] = value; + } + + if (this.cacheCanvasEl) { + this.cacheCanvasEl[prop] = value; + } + + this[prop] = value; + + return this; + }, + + /** + * Helper for setting css width/height + * @private + * @param {String} prop property (width|height) + * @param {String} value value to set property to + * @return {fabric.Canvas} instance + * @chainable true + */ + _setCssDimension: function (prop, value) { + this.lowerCanvasEl.style[prop] = value; + + if (this.upperCanvasEl) { + this.upperCanvasEl.style[prop] = value; + } + + if (this.wrapperEl) { + this.wrapperEl.style[prop] = value; + } + + return this; + }, + + /** + * Returns canvas zoom level + * @return {Number} + */ + getZoom: function () { + return Math.sqrt(this.viewportTransform[0] * this.viewportTransform[3]); + }, + + /** + * Sets viewport transform of this canvas instance + * @param {Array} vpt the transform in the form of context.transform + * @return {fabric.Canvas} instance + * @chainable true + */ + setViewportTransform: function (vpt) { + this.viewportTransform = vpt; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + return this; + }, + + /** + * Sets zoom level of this canvas instance, zoom centered around point + * @param {fabric.Point} point to zoom with respect to + * @param {Number} value to set zoom to, less than 1 zooms out + * @return {fabric.Canvas} instance + * @chainable true + */ + zoomToPoint: function (point, value) { + // TODO: just change the scale, preserve other transformations + var before = point; + point = fabric.util.transformPoint(point, fabric.util.invertTransform(this.viewportTransform)); + this.viewportTransform[0] = value; + this.viewportTransform[3] = value; + var after = fabric.util.transformPoint(point, this.viewportTransform); + this.viewportTransform[4] += before.x - after.x; + this.viewportTransform[5] += before.y - after.y; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + return this; + }, + + /** + * Sets zoom level of this canvas instance + * @param {Number} value to set zoom to, less than 1 zooms out + * @return {fabric.Canvas} instance + * @chainable true + */ + setZoom: function (value) { + this.zoomToPoint(new fabric.Point(0, 0), value); + return this; + }, + + /** + * Pan viewport so as to place point at top left corner of canvas + * @param {fabric.Point} point to move to + * @return {fabric.Canvas} instance + * @chainable true + */ + absolutePan: function (point) { + this.viewportTransform[4] = -point.x; + this.viewportTransform[5] = -point.y; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + return this; + }, + + /** + * Pans viewpoint relatively + * @param {fabric.Point} point (position vector) to move by + * @return {fabric.Canvas} instance + * @chainable true + */ + relativePan: function (point) { + return this.absolutePan(new fabric.Point( + -point.x - this.viewportTransform[4], + -point.y - this.viewportTransform[5] + )); + }, + + /** + * Returns <canvas> element corresponding to this instance + * @return {HTMLCanvasElement} + */ + getElement: function () { + return this.lowerCanvasEl; + }, + + /** + * Returns currently selected object, if any + * @return {fabric.Object} + */ + getActiveObject: function() { + return null; + }, + + /** + * Returns currently selected group of object, if any + * @return {fabric.Group} + */ + getActiveGroup: function() { + return null; + }, + + /** + * Given a context, renders an object on that context + * @param {CanvasRenderingContext2D} ctx Context to render object on + * @param {fabric.Object} object Object to render + * @private + */ + _draw: function (ctx, object) { + if (!object) { + return; + } + + ctx.save(); + var v = this.viewportTransform; + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + object.render(ctx); + ctx.restore(); + if (!this.controlsAboveOverlay) { + object._renderControls(ctx); + } + }, + + /** + * @private + * @param {fabric.Object} obj Object that was added + */ + _onObjectAdded: function(obj) { + this.stateful && obj.setupState(); + obj.canvas = this; + obj.setCoords(); + this.fire('object:added', { target: obj }); + obj.fire('added'); + }, + + /** + * @private + * @param {fabric.Object} obj Object that was removed + */ + _onObjectRemoved: function(obj) { + // removing active object should fire "selection:cleared" events + if (this.getActiveObject() === obj) { + this.fire('before:selection:cleared', { target: obj }); + this._discardActiveObject(); + this.fire('selection:cleared'); + } + + this.fire('object:removed', { target: obj }); + obj.fire('removed'); + }, + + /** + * Clears specified context of canvas element + * @param {CanvasRenderingContext2D} ctx Context to clear + * @return {fabric.Canvas} thisArg + * @chainable + */ + clearContext: function(ctx) { + ctx.clearRect(0, 0, this.width, this.height); + return this; + }, + + /** + * Returns context of canvas where objects are drawn + * @return {CanvasRenderingContext2D} + */ + getContext: function () { + return this.contextContainer; + }, + + /** + * Clears all contexts (background, main, top) of an instance + * @return {fabric.Canvas} thisArg + * @chainable + */ + clear: function () { + this._objects.length = 0; + if (this.discardActiveGroup) { + this.discardActiveGroup(); + } + if (this.discardActiveObject) { + this.discardActiveObject(); + } + this.clearContext(this.contextContainer); + if (this.contextTop) { + this.clearContext(this.contextTop); + } + this.fire('canvas:cleared'); + this.renderAll(); + return this; + }, + + /** + * Renders both the top canvas and the secondary container canvas. + * @param {Boolean} [allOnTop] Whether we want to force all images to be rendered on the top canvas + * @return {fabric.Canvas} instance + * @chainable + */ + renderAll: function (allOnTop) { + var canvasToDrawOn = this[(allOnTop === true && this.interactive) ? 'contextTop' : 'contextContainer'], + activeGroup = this.getActiveGroup(); + + if (this.contextTop && this.selection && !this._groupSelector) { + this.clearContext(this.contextTop); + } + + if (!allOnTop) { + this.clearContext(canvasToDrawOn); + } + + this.fire('before:render'); + + if (this.clipTo) { + fabric.util.clipContext(this, canvasToDrawOn); + } + + this._renderBackground(canvasToDrawOn); + this._renderObjects(canvasToDrawOn, activeGroup); + this._renderActiveGroup(canvasToDrawOn, activeGroup); + + if (this.clipTo) { + canvasToDrawOn.restore(); + } + + this._renderOverlay(canvasToDrawOn); + + if (this.controlsAboveOverlay && this.interactive) { + this.drawControls(canvasToDrawOn); + } + + this.fire('after:render'); + + return this; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {fabric.Group} activeGroup + */ + _renderObjects: function(ctx, activeGroup) { + var i, length; + + // fast path + if (!activeGroup) { + for (i = 0, length = this._objects.length; i < length; ++i) { + this._draw(ctx, this._objects[i]); + } + } + else { + for (i = 0, length = this._objects.length; i < length; ++i) { + if (this._objects[i] && !activeGroup.contains(this._objects[i])) { + this._draw(ctx, this._objects[i]); + } + } + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {fabric.Group} activeGroup + */ + _renderActiveGroup: function(ctx, activeGroup) { + + // delegate rendering to group selection (if one exists) + if (activeGroup) { + + //Store objects in group preserving order, then replace + var sortedObjects = []; + this.forEachObject(function (object) { + if (activeGroup.contains(object)) { + sortedObjects.push(object); + } + }); + activeGroup._set('objects', sortedObjects); + this._draw(ctx, activeGroup); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderBackground: function(ctx) { + if (this.backgroundColor) { + ctx.fillStyle = this.backgroundColor.toLive + ? this.backgroundColor.toLive(ctx) + : this.backgroundColor; + + ctx.fillRect( + this.backgroundColor.offsetX || 0, + this.backgroundColor.offsetY || 0, + this.width, + this.height); + } + if (this.backgroundImage) { + this._draw(ctx, this.backgroundImage); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderOverlay: function(ctx) { + if (this.overlayColor) { + ctx.fillStyle = this.overlayColor.toLive + ? this.overlayColor.toLive(ctx) + : this.overlayColor; + + ctx.fillRect( + this.overlayColor.offsetX || 0, + this.overlayColor.offsetY || 0, + this.width, + this.height); + } + if (this.overlayImage) { + this._draw(ctx, this.overlayImage); + } + }, + + /** + * Method to render only the top canvas. + * Also used to render the group selection box. + * @return {fabric.Canvas} thisArg + * @chainable + */ + renderTop: function () { + var ctx = this.contextTop || this.contextContainer; + this.clearContext(ctx); + + // we render the top context - last object + if (this.selection && this._groupSelector) { + this._drawSelection(); + } + + // delegate rendering to group selection if one exists + // used for drawing selection borders/controls + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + activeGroup.render(ctx); + } + + this._renderOverlay(ctx); + + this.fire('after:render'); + + return this; + }, + + /** + * Returns coordinates of a center of canvas. + * Returned value is an object with top and left properties + * @return {Object} object with "top" and "left" number values + */ + getCenter: function () { + return { + top: this.getHeight() / 2, + left: this.getWidth() / 2 + }; + }, + + /** + * Centers object horizontally. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center horizontally + * @return {fabric.Canvas} thisArg + */ + centerObjectH: function (object) { + this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y)); + this.renderAll(); + return this; + }, + + /** + * Centers object vertically. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center vertically + * @return {fabric.Canvas} thisArg + * @chainable + */ + centerObjectV: function (object) { + this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top)); + this.renderAll(); + return this; + }, + + /** + * Centers object vertically and horizontally. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @param {fabric.Object} object Object to center vertically and horizontally + * @return {fabric.Canvas} thisArg + * @chainable + */ + centerObject: function(object) { + var center = this.getCenter(); + + this._centerObject(object, new fabric.Point(center.left, center.top)); + this.renderAll(); + return this; + }, + + /** + * @private + * @param {fabric.Object} object Object to center + * @param {fabric.Point} center Center point + * @return {fabric.Canvas} thisArg + * @chainable + */ + _centerObject: function(object, center) { + object.setPositionByOrigin(center, 'center', 'center'); + return this; + }, + + /** + * Returs dataless JSON representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {String} json string + */ + toDatalessJSON: function (propertiesToInclude) { + return this.toDatalessObject(propertiesToInclude); + }, + + /** + * Returns object representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function (propertiesToInclude) { + return this._toObjectMethod('toObject', propertiesToInclude); + }, + + /** + * Returns dataless object representation of canvas + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toDatalessObject: function (propertiesToInclude) { + return this._toObjectMethod('toDatalessObject', propertiesToInclude); + }, + + /** + * @private + */ + _toObjectMethod: function (methodName, propertiesToInclude) { + + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this.discardActiveGroup(); + } + + var data = { + objects: this._toObjects(methodName, propertiesToInclude) + }; + + extend(data, this.__serializeBgOverlay()); + + fabric.util.populateWithProperties(this, data, propertiesToInclude); + + if (activeGroup) { + this.setActiveGroup(new fabric.Group(activeGroup.getObjects(), { + originX: 'center', + originY: 'center' + })); + activeGroup.forEachObject(function(o) { + o.set('active', true); + }); + + if (this._currentTransform) { + this._currentTransform.target = this.getActiveGroup(); + } + } + + return data; + }, + + /** + * @private + */ + _toObjects: function(methodName, propertiesToInclude) { + return this.getObjects().map(function(instance) { + return this._toObject(instance, methodName, propertiesToInclude); + }, this); + }, + + /** + * @private + */ + _toObject: function(instance, methodName, propertiesToInclude) { + var originalValue; + + if (!this.includeDefaultValues) { + originalValue = instance.includeDefaultValues; + instance.includeDefaultValues = false; + } + var object = instance[methodName](propertiesToInclude); + if (!this.includeDefaultValues) { + instance.includeDefaultValues = originalValue; + } + return object; + }, + + /** + * @private + */ + __serializeBgOverlay: function() { + var data = { + background: (this.backgroundColor && this.backgroundColor.toObject) + ? this.backgroundColor.toObject() + : this.backgroundColor + }; + + if (this.overlayColor) { + data.overlay = this.overlayColor.toObject + ? this.overlayColor.toObject() + : this.overlayColor; + } + if (this.backgroundImage) { + data.backgroundImage = this.backgroundImage.toObject(); + } + if (this.overlayImage) { + data.overlayImage = this.overlayImage.toObject(); + } + + return data; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of canvas + * @function + * @param {Object} [options] Options object for SVG output + * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included + * @param {Object} [options.viewBox] SVG viewbox object + * @param {Number} [options.viewBox.x] x-cooridnate of viewbox + * @param {Number} [options.viewBox.y] y-coordinate of viewbox + * @param {Number} [options.viewBox.width] Width of viewbox + * @param {Number} [options.viewBox.height] Height of viewbox + * @param {String} [options.encoding=UTF-8] Encoding of SVG output + * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation. + * @return {String} SVG string + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization} + * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo} + * @example + * var svg = canvas.toSVG(); + * @example + * var svg = canvas.toSVG({suppressPreamble: true}); + * @example + * var svg = canvas.toSVG({ + * viewBox: { + * x: 100, + * y: 100, + * width: 200, + * height: 300 + * } + * }); + * @example + * var svg = canvas.toSVG({encoding: 'ISO-8859-1'}); + * @example + * var svg = canvas.toSVG(null, function(svg) { + * return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', ''); + * }); + */ + toSVG: function(options, reviver) { + options || (options = { }); + + var markup = []; + + this._setSVGPreamble(markup, options); + this._setSVGHeader(markup, options); + + this._setSVGBgOverlayColor(markup, 'backgroundColor'); + this._setSVGBgOverlayImage(markup, 'backgroundImage'); + + this._setSVGObjects(markup, reviver); + + this._setSVGBgOverlayColor(markup, 'overlayColor'); + this._setSVGBgOverlayImage(markup, 'overlayImage'); + + markup.push(''); + + return markup.join(''); + }, + + /** + * @private + */ + _setSVGPreamble: function(markup, options) { + if (!options.suppressPreamble) { + markup.push( + '', + '\n' + ); + } + }, + + /** + * @private + */ + _setSVGHeader: function(markup, options) { + markup.push( + '', + 'Created with Fabric.js ', fabric.version, '', + '', + fabric.createSVGFontFacesMarkup(this.getObjects()), + fabric.createSVGRefElementsMarkup(this), + '' + ); + }, + + /** + * @private + */ + _setSVGObjects: function(markup, reviver) { + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this.discardActiveGroup(); + } + for (var i = 0, objects = this.getObjects(), len = objects.length; i < len; i++) { + markup.push(objects[i].toSVG(reviver)); + } + if (activeGroup) { + this.setActiveGroup(new fabric.Group(activeGroup.getObjects())); + activeGroup.forEachObject(function(o) { + o.set('active', true); + }); + } + }, + + /** + * @private + */ + _setSVGBgOverlayImage: function(markup, property) { + if (this[property] && this[property].toSVG) { + markup.push(this[property].toSVG()); + } + }, + + /** + * @private + */ + _setSVGBgOverlayColor: function(markup, property) { + if (this[property] && this[property].source) { + markup.push( + '' + ); + } + else if (this[property] && property === 'overlayColor') { + markup.push( + '' + ); + } + }, + /* _TO_SVG_END_ */ + + /** + * Moves an object to the bottom of the stack of drawn objects + * @param {fabric.Object} object Object to send to back + * @return {fabric.Canvas} thisArg + * @chainable + */ + sendToBack: function (object) { + removeFromArray(this._objects, object); + this._objects.unshift(object); + return this.renderAll && this.renderAll(); + }, + + /** + * Moves an object to the top of the stack of drawn objects + * @param {fabric.Object} object Object to send + * @return {fabric.Canvas} thisArg + * @chainable + */ + bringToFront: function (object) { + removeFromArray(this._objects, object); + this._objects.push(object); + return this.renderAll && this.renderAll(); + }, + + /** + * Moves an object down in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object + * @return {fabric.Canvas} thisArg + * @chainable + */ + sendBackwards: function (object, intersecting) { + var idx = this._objects.indexOf(object); + + // if object is not on the bottom of stack + if (idx !== 0) { + var newIdx = this._findNewLowerIndex(object, idx, intersecting); + + removeFromArray(this._objects, object); + this._objects.splice(newIdx, 0, object); + this.renderAll && this.renderAll(); + } + return this; + }, + + /** + * @private + */ + _findNewLowerIndex: function(object, idx, intersecting) { + var newIdx; + + if (intersecting) { + newIdx = idx; + + // traverse down the stack looking for the nearest intersecting object + for (var i = idx - 1; i >= 0; --i) { + + var isIntersecting = object.intersectsWithObject(this._objects[i]) || + object.isContainedWithinObject(this._objects[i]) || + this._objects[i].isContainedWithinObject(object); + + if (isIntersecting) { + newIdx = i; + break; + } + } + } + else { + newIdx = idx - 1; + } + + return newIdx; + }, + + /** + * Moves an object up in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object + * @return {fabric.Canvas} thisArg + * @chainable + */ + bringForward: function (object, intersecting) { + var idx = this._objects.indexOf(object); + + // if object is not on top of stack (last item in an array) + if (idx !== this._objects.length - 1) { + var newIdx = this._findNewUpperIndex(object, idx, intersecting); + + removeFromArray(this._objects, object); + this._objects.splice(newIdx, 0, object); + this.renderAll && this.renderAll(); + } + return this; + }, + + /** + * @private + */ + _findNewUpperIndex: function(object, idx, intersecting) { + var newIdx; + + if (intersecting) { + newIdx = idx; + + // traverse up the stack looking for the nearest intersecting object + for (var i = idx + 1; i < this._objects.length; ++i) { + + var isIntersecting = object.intersectsWithObject(this._objects[i]) || + object.isContainedWithinObject(this._objects[i]) || + this._objects[i].isContainedWithinObject(object); + + if (isIntersecting) { + newIdx = i; + break; + } + } + } + else { + newIdx = idx + 1; + } + + return newIdx; + }, + + /** + * Moves an object to specified level in stack of drawn objects + * @param {fabric.Object} object Object to send + * @param {Number} index Position to move to + * @return {fabric.Canvas} thisArg + * @chainable + */ + moveTo: function (object, index) { + removeFromArray(this._objects, object); + this._objects.splice(index, 0, object); + return this.renderAll && this.renderAll(); + }, + + /** + * Clears a canvas element and removes all event listeners + * @return {fabric.Canvas} thisArg + * @chainable + */ + dispose: function () { + this.clear(); + this.interactive && this.removeListeners(); + return this; + }, + + /** + * Returns a string representation of an instance + * @return {String} string representation of an instance + */ + toString: function () { + return '#'; + } + }); + + extend(fabric.StaticCanvas.prototype, fabric.Observable); + extend(fabric.StaticCanvas.prototype, fabric.Collection); + extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter); + + extend(fabric.StaticCanvas, /** @lends fabric.StaticCanvas */ { + + /** + * @static + * @type String + * @default + */ + EMPTY_JSON: '{"objects": [], "background": "white"}', + + /** + * Provides a way to check support of some of the canvas methods + * (either those of HTMLCanvasElement itself, or rendering context) + * + * @param {String} methodName Method to check support for; + * Could be one of "getImageData", "toDataURL", "toDataURLWithQuality" or "setLineDash" + * @return {Boolean | null} `true` if method is supported (or at least exists), + * `null` if canvas element or context can not be initialized + */ + supports: function (methodName) { + var el = fabric.util.createCanvasElement(); + + if (!el || !el.getContext) { + return null; + } + + var ctx = el.getContext('2d'); + if (!ctx) { + return null; + } + + switch (methodName) { + + case 'getImageData': + return typeof ctx.getImageData !== 'undefined'; + + case 'setLineDash': + return typeof ctx.setLineDash !== 'undefined'; + + case 'toDataURL': + return typeof el.toDataURL !== 'undefined'; + + case 'toDataURLWithQuality': + try { + el.toDataURL('image/jpeg', 0); + return true; + } + catch (e) { } + return false; + + default: + return null; + } + } + }); + + /** + * Returns JSON representation of canvas + * @function + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {String} JSON string + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization} + * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo} + * @example JSON without additional properties + * var json = canvas.toJSON(); + * @example JSON with additional properties included + * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY', 'lockUniScaling']); + * @example JSON without default values + * canvas.includeDefaultValues = false; + * var json = canvas.toJSON(); + */ + fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject; + +})(); + + +/** + * BaseBrush class + * @class fabric.BaseBrush + * @see {@link http://fabricjs.com/freedrawing/|Freedrawing demo} + */ +fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ { + + /** + * Color of a brush + * @type String + * @default + */ + color: 'rgb(0, 0, 0)', + + /** + * Width of a brush + * @type Number + * @default + */ + width: 1, + + /** + * Shadow object representing shadow of this shape. + * Backwards incompatibility note: This property replaces "shadowColor" (String), "shadowOffsetX" (Number), + * "shadowOffsetY" (Number) and "shadowBlur" (Number) since v1.2.12 + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Line endings style of a brush (one of "butt", "round", "square") + * @type String + * @default + */ + strokeLineCap: 'round', + + /** + * Corner style of a brush (one of "bevil", "round", "miter") + * @type String + * @default + */ + strokeLineJoin: 'round', + + /** + * Sets shadow of an object + * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") + * @return {fabric.Object} thisArg + * @chainable + */ + setShadow: function(options) { + this.shadow = new fabric.Shadow(options); + return this; + }, + + /** + * Sets brush styles + * @private + */ + _setBrushStyles: function() { + var ctx = this.canvas.contextTop; + + ctx.strokeStyle = this.color; + ctx.lineWidth = this.width; + ctx.lineCap = this.strokeLineCap; + ctx.lineJoin = this.strokeLineJoin; + }, + + /** + * Sets brush shadow styles + * @private + */ + _setShadow: function() { + if (!this.shadow) { + return; + } + + var ctx = this.canvas.contextTop; + + ctx.shadowColor = this.shadow.color; + ctx.shadowBlur = this.shadow.blur; + ctx.shadowOffsetX = this.shadow.offsetX; + ctx.shadowOffsetY = this.shadow.offsetY; + }, + + /** + * Removes brush shadow styles + * @private + */ + _resetShadow: function() { + var ctx = this.canvas.contextTop; + + ctx.shadowColor = ''; + ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; + } +}); + + +(function() { + + var utilMin = fabric.util.array.min, + utilMax = fabric.util.array.max; + + /** + * PencilBrush class + * @class fabric.PencilBrush + * @extends fabric.BaseBrush + */ + fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.PencilBrush.prototype */ { + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.PencilBrush} Instance of a pencil brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this._points = [ ]; + }, + + /** + * Inovoked on mouse down + * @param {Object} pointer + */ + onMouseDown: function(pointer) { + this._prepareForDrawing(pointer); + // capture coordinates immediately + // this allows to draw dots (when movement never occurs) + this._captureDrawingPath(pointer); + this._render(); + }, + + /** + * Inovoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this._captureDrawingPath(pointer); + // redraw curve + // clear top canvas + this.canvas.clearContext(this.canvas.contextTop); + this._render(); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + this._finalizeAndAddPath(); + }, + + /** + * @private + * @param {Object} pointer Actual mouse position related to the canvas. + */ + _prepareForDrawing: function(pointer) { + + var p = new fabric.Point(pointer.x, pointer.y); + + this._reset(); + this._addPoint(p); + + this.canvas.contextTop.moveTo(p.x, p.y); + }, + + /** + * @private + * @param {fabric.Point} point Point to be added to points array + */ + _addPoint: function(point) { + this._points.push(point); + }, + + /** + * Clear points array and set contextTop canvas style. + * @private + */ + _reset: function() { + this._points.length = 0; + + this._setBrushStyles(); + this._setShadow(); + }, + + /** + * @private + * @param {Object} pointer Actual mouse position related to the canvas. + */ + _captureDrawingPath: function(pointer) { + var pointerPoint = new fabric.Point(pointer.x, pointer.y); + this._addPoint(pointerPoint); + }, + + /** + * Draw a smooth path on the topCanvas using quadraticCurveTo + * @private + */ + _render: function() { + var ctx = this.canvas.contextTop, + v = this.canvas.viewportTransform, + p1 = this._points[0], + p2 = this._points[1]; + + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + ctx.beginPath(); + + //if we only have 2 points in the path and they are the same + //it means that the user only clicked the canvas without moving the mouse + //then we should be drawing a dot. A path isn't drawn between two identical dots + //that's why we set them apart a bit + if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) { + p1.x -= 0.5; + p2.x += 0.5; + } + ctx.moveTo(p1.x, p1.y); + + for (var i = 1, len = this._points.length; i < len; i++) { + // we pick the point between pi + 1 & pi + 2 as the + // end point and p1 as our control point. + var midPoint = p1.midPointFrom(p2); + ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y); + + p1 = this._points[i]; + p2 = this._points[i + 1]; + } + // Draw last line as a straight line while + // we wait for the next point to be able to calculate + // the bezier control point + ctx.lineTo(p1.x, p1.y); + ctx.stroke(); + ctx.restore(); + }, + + /** + * Return an SVG path based on our captured points and their bounding box + * @private + */ + _getSVGPathData: function() { + this.box = this.getPathBoundingBox(this._points); + return this.convertPointsToSVGPath( + this._points, this.box.minX, this.box.minY); + }, + + /** + * Returns bounding box of a path based on given points + * @param {Array} points Array of points + * @return {Object} Object with minX, minY, maxX, maxY + */ + getPathBoundingBox: function(points) { + var xBounds = [], + yBounds = [], + p1 = points[0], + p2 = points[1], + startPoint = p1; + + for (var i = 1, len = points.length; i < len; i++) { + var midPoint = p1.midPointFrom(p2); + // with startPoint, p1 as control point, midpoint as end point + xBounds.push(startPoint.x); + xBounds.push(midPoint.x); + yBounds.push(startPoint.y); + yBounds.push(midPoint.y); + + p1 = points[i]; + p2 = points[i + 1]; + startPoint = midPoint; + } + + xBounds.push(p1.x); + yBounds.push(p1.y); + + return { + minX: utilMin(xBounds), + minY: utilMin(yBounds), + maxX: utilMax(xBounds), + maxY: utilMax(yBounds) + }; + }, + + /** + * Converts points to SVG path + * @param {Array} points Array of points + * @param {Number} minX + * @param {Number} minY + * @return {String} SVG path + */ + convertPointsToSVGPath: function(points, minX, minY) { + var path = [], + p1 = new fabric.Point(points[0].x - minX, points[0].y - minY), + p2 = new fabric.Point(points[1].x - minX, points[1].y - minY); + + path.push('M ', points[0].x - minX, ' ', points[0].y - minY, ' '); + for (var i = 1, len = points.length; i < len; i++) { + var midPoint = p1.midPointFrom(p2); + // p1 is our bezier control point + // midpoint is our endpoint + // start point is p(i-1) value. + path.push('Q ', p1.x, ' ', p1.y, ' ', midPoint.x, ' ', midPoint.y, ' '); + p1 = new fabric.Point(points[i].x - minX, points[i].y - minY); + if ((i + 1) < points.length) { + p2 = new fabric.Point(points[i + 1].x - minX, points[i + 1].y - minY); + } + } + path.push('L ', p1.x, ' ', p1.y, ' '); + return path; + }, + + /** + * Creates fabric.Path object to add on canvas + * @param {String} pathData Path data + * @return {fabric.Path} Path to add on canvas + */ + createPath: function(pathData) { + var path = new fabric.Path(pathData); + path.fill = null; + path.stroke = this.color; + path.strokeWidth = this.width; + path.strokeLineCap = this.strokeLineCap; + path.strokeLineJoin = this.strokeLineJoin; + + if (this.shadow) { + this.shadow.affectStroke = true; + path.setShadow(this.shadow); + } + + return path; + }, + + /** + * On mouseup after drawing the path on contextTop canvas + * we use the points captured to create an new fabric path object + * and add it to the fabric canvas. + */ + _finalizeAndAddPath: function() { + var ctx = this.canvas.contextTop; + ctx.closePath(); + + var pathData = this._getSVGPathData().join(''); + if (pathData === 'M 0 0 Q 0 0 0 0 L 0 0') { + // do not create 0 width/height paths, as they are + // rendered inconsistently across browsers + // Firefox 4, for example, renders a dot, + // whereas Chrome 10 renders nothing + this.canvas.renderAll(); + return; + } + + // set path origin coordinates based on our bounding box + var originLeft = this.box.minX + (this.box.maxX - this.box.minX) / 2, + originTop = this.box.minY + (this.box.maxY - this.box.minY) / 2; + + this.canvas.contextTop.arc(originLeft, originTop, 3, 0, Math.PI * 2, false); + + var path = this.createPath(pathData); + path.set({ + left: originLeft, + top: originTop, + originX: 'center', + originY: 'center' + }); + + this.canvas.add(path); + path.setCoords(); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderAll(); + + // fire event 'path' created + this.canvas.fire('path:created', { path: path }); + } + }); +})(); + + +/** + * CircleBrush class + * @class fabric.CircleBrush + */ +fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.CircleBrush.prototype */ { + + /** + * Width of a brush + * @type Number + * @default + */ + width: 10, + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.CircleBrush} Instance of a circle brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this.points = [ ]; + }, + /** + * Invoked inside on mouse down and mouse move + * @param {Object} pointer + */ + drawDot: function(pointer) { + var point = this.addPoint(pointer), + ctx = this.canvas.contextTop, + v = this.canvas.viewportTransform; + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + + ctx.fillStyle = point.fill; + ctx.beginPath(); + ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false); + ctx.closePath(); + ctx.fill(); + + ctx.restore(); + }, + + /** + * Invoked on mouse down + */ + onMouseDown: function(pointer) { + this.points.length = 0; + this.canvas.clearContext(this.canvas.contextTop); + this._setShadow(); + this.drawDot(pointer); + }, + + /** + * Invoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this.drawDot(pointer); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; + this.canvas.renderOnAddRemove = false; + + var circles = [ ]; + + for (var i = 0, len = this.points.length; i < len; i++) { + var point = this.points[i], + circle = new fabric.Circle({ + radius: point.radius, + left: point.x, + top: point.y, + originX: 'center', + originY: 'center', + fill: point.fill + }); + + this.shadow && circle.setShadow(this.shadow); + + circles.push(circle); + } + var group = new fabric.Group(circles, { originX: 'center', originY: 'center' }); + group.canvas = this.canvas; + + this.canvas.add(group); + this.canvas.fire('path:created', { path: group }); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderOnAddRemove = originalRenderOnAddRemove; + this.canvas.renderAll(); + }, + + /** + * @param {Object} pointer + * @return {fabric.Point} Just added pointer point + */ + addPoint: function(pointer) { + var pointerPoint = new fabric.Point(pointer.x, pointer.y), + + circleRadius = fabric.util.getRandomInt( + Math.max(0, this.width - 20), this.width + 20) / 2, + + circleColor = new fabric.Color(this.color) + .setAlpha(fabric.util.getRandomInt(0, 100) / 100) + .toRgba(); + + pointerPoint.radius = circleRadius; + pointerPoint.fill = circleColor; + + this.points.push(pointerPoint); + + return pointerPoint; + } +}); + + +/** + * SprayBrush class + * @class fabric.SprayBrush + */ +fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric.SprayBrush.prototype */ { + + /** + * Width of a spray + * @type Number + * @default + */ + width: 10, + + /** + * Density of a spray (number of dots per chunk) + * @type Number + * @default + */ + density: 20, + + /** + * Width of spray dots + * @type Number + * @default + */ + dotWidth: 1, + + /** + * Width variance of spray dots + * @type Number + * @default + */ + dotWidthVariance: 1, + + /** + * Whether opacity of a dot should be random + * @type Boolean + * @default + */ + randomOpacity: false, + + /** + * Whether overlapping dots (rectangles) should be removed (for performance reasons) + * @type Boolean + * @default + */ + optimizeOverlapping: true, + + /** + * Constructor + * @param {fabric.Canvas} canvas + * @return {fabric.SprayBrush} Instance of a spray brush + */ + initialize: function(canvas) { + this.canvas = canvas; + this.sprayChunks = [ ]; + }, + + /** + * Invoked on mouse down + * @param {Object} pointer + */ + onMouseDown: function(pointer) { + this.sprayChunks.length = 0; + this.canvas.clearContext(this.canvas.contextTop); + this._setShadow(); + + this.addSprayChunk(pointer); + this.render(); + }, + + /** + * Invoked on mouse move + * @param {Object} pointer + */ + onMouseMove: function(pointer) { + this.addSprayChunk(pointer); + this.render(); + }, + + /** + * Invoked on mouse up + */ + onMouseUp: function() { + var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; + this.canvas.renderOnAddRemove = false; + + var rects = [ ]; + + for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) { + var sprayChunk = this.sprayChunks[i]; + + for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) { + + var rect = new fabric.Rect({ + width: sprayChunk[j].width, + height: sprayChunk[j].width, + left: sprayChunk[j].x + 1, + top: sprayChunk[j].y + 1, + originX: 'center', + originY: 'center', + fill: this.color + }); + + this.shadow && rect.setShadow(this.shadow); + rects.push(rect); + } + } + + if (this.optimizeOverlapping) { + rects = this._getOptimizedRects(rects); + } + + var group = new fabric.Group(rects, { originX: 'center', originY: 'center' }); + group.canvas = this.canvas; + + this.canvas.add(group); + this.canvas.fire('path:created', { path: group }); + + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderOnAddRemove = originalRenderOnAddRemove; + this.canvas.renderAll(); + }, + + /** + * @private + * @param {Array} rects + */ + _getOptimizedRects: function(rects) { + + // avoid creating duplicate rects at the same coordinates + var uniqueRects = { }, key; + + for (var i = 0, len = rects.length; i < len; i++) { + key = rects[i].left + '' + rects[i].top; + if (!uniqueRects[key]) { + uniqueRects[key] = rects[i]; + } + } + var uniqueRectsArray = [ ]; + for (key in uniqueRects) { + uniqueRectsArray.push(uniqueRects[key]); + } + + return uniqueRectsArray; + }, + + /** + * Renders brush + */ + render: function() { + var ctx = this.canvas.contextTop; + ctx.fillStyle = this.color; + + var v = this.canvas.viewportTransform; + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + + for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) { + var point = this.sprayChunkPoints[i]; + if (typeof point.opacity !== 'undefined') { + ctx.globalAlpha = point.opacity; + } + ctx.fillRect(point.x, point.y, point.width, point.width); + } + ctx.restore(); + }, + + /** + * @param {Object} pointer + */ + addSprayChunk: function(pointer) { + this.sprayChunkPoints = [ ]; + + var x, y, width, radius = this.width / 2; + + for (var i = 0; i < this.density; i++) { + + x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius); + y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius); + + if (this.dotWidthVariance) { + width = fabric.util.getRandomInt( + // bottom clamp width to 1 + Math.max(1, this.dotWidth - this.dotWidthVariance), + this.dotWidth + this.dotWidthVariance); + } + else { + width = this.dotWidth; + } + + var point = new fabric.Point(x, y); + point.width = width; + + if (this.randomOpacity) { + point.opacity = fabric.util.getRandomInt(0, 100) / 100; + } + + this.sprayChunkPoints.push(point); + } + + this.sprayChunks.push(this.sprayChunkPoints); + } +}); + + +/** + * PatternBrush class + * @class fabric.PatternBrush + * @extends fabric.BaseBrush + */ +fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fabric.PatternBrush.prototype */ { + + getPatternSrc: function() { + + var dotWidth = 20, + dotDistance = 5, + patternCanvas = fabric.document.createElement('canvas'), + patternCtx = patternCanvas.getContext('2d'); + + patternCanvas.width = patternCanvas.height = dotWidth + dotDistance; + + patternCtx.fillStyle = this.color; + patternCtx.beginPath(); + patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); + patternCtx.closePath(); + patternCtx.fill(); + + return patternCanvas; + }, + + getPatternSrcFunction: function() { + return String(this.getPatternSrc).replace('this.color', '"' + this.color + '"'); + }, + + /** + * Creates "pattern" instance property + */ + getPattern: function() { + return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), 'repeat'); + }, + + /** + * Sets brush styles + */ + _setBrushStyles: function() { + this.callSuper('_setBrushStyles'); + this.canvas.contextTop.strokeStyle = this.getPattern(); + }, + + /** + * Creates path + */ + createPath: function(pathData) { + var path = this.callSuper('createPath', pathData); + path.stroke = new fabric.Pattern({ + source: this.source || this.getPatternSrcFunction() + }); + return path; + } +}); + + +(function() { + + var getPointer = fabric.util.getPointer, + degreesToRadians = fabric.util.degreesToRadians, + radiansToDegrees = fabric.util.radiansToDegrees, + atan2 = Math.atan2, + abs = Math.abs, + + STROKE_OFFSET = 0.5; + + /** + * Canvas class + * @class fabric.Canvas + * @extends fabric.StaticCanvas + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#canvas} + * @see {@link fabric.Canvas#initialize} for constructor definition + * + * @fires object:modified + * @fires object:rotating + * @fires object:scaling + * @fires object:moving + * @fires object:selected + * + * @fires before:selection:cleared + * @fires selection:cleared + * @fires selection:created + * + * @fires path:created + * @fires mouse:down + * @fires mouse:move + * @fires mouse:up + * @fires mouse:over + * @fires mouse:out + * + */ + fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ { + + /** + * Constructor + * @param {HTMLElement | String} el <canvas> element to initialize instance on + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(el, options) { + options || (options = { }); + + this._initStatic(el, options); + this._initInteractive(); + this._createCacheCanvas(); + + fabric.Canvas.activeInstance = this; + }, + + /** + * When true, objects can be transformed by one side (unproportionally) + * @type Boolean + * @default + */ + uniScaleTransform: false, + + /** + * When true, objects use center point as the origin of scale transformation. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredScaling: false, + + /** + * When true, objects use center point as the origin of rotate transformation. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredRotation: false, + + /** + * Indicates that canvas is interactive. This property should not be changed. + * @type Boolean + * @default + */ + interactive: true, + + /** + * Indicates whether group selection should be enabled + * @type Boolean + * @default + */ + selection: true, + + /** + * Color of selection + * @type String + * @default + */ + selectionColor: 'rgba(100, 100, 255, 0.3)', // blue + + /** + * Default dash array pattern + * If not empty the selection border is dashed + * @type Array + */ + selectionDashArray: [ ], + + /** + * Color of the border of selection (usually slightly darker than color of selection itself) + * @type String + * @default + */ + selectionBorderColor: 'rgba(255, 255, 255, 0.3)', + + /** + * Width of a line used in object/group selection + * @type Number + * @default + */ + selectionLineWidth: 1, + + /** + * Default cursor value used when hovering over an object on canvas + * @type String + * @default + */ + hoverCursor: 'move', + + /** + * Default cursor value used when moving an object on canvas + * @type String + * @default + */ + moveCursor: 'move', + + /** + * Default cursor value used for the entire canvas + * @type String + * @default + */ + defaultCursor: 'default', + + /** + * Cursor value used during free drawing + * @type String + * @default + */ + freeDrawingCursor: 'crosshair', + + /** + * Cursor value used for rotation point + * @type String + * @default + */ + rotationCursor: 'crosshair', + + /** + * Default element class that's given to wrapper (div) element of canvas + * @type String + * @default + */ + containerClass: 'canvas-container', + + /** + * When true, object detection happens on per-pixel basis rather than on per-bounding-box + * @type Boolean + * @default + */ + perPixelTargetFind: false, + + /** + * Number of pixels around target pixel to tolerate (consider active) during object detection + * @type Number + * @default + */ + targetFindTolerance: 0, + + /** + * When true, target detection is skipped when hovering over canvas. This can be used to improve performance. + * @type Boolean + * @default + */ + skipTargetFind: false, + + /** + * @private + */ + _initInteractive: function() { + this._currentTransform = null; + this._groupSelector = null; + this._initWrapperElement(); + this._createUpperCanvas(); + this._initEventListeners(); + + this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this); + + this.calcOffset(); + }, + + /** + * Resets the current transform to its original values and chooses the type of resizing based on the event + * @private + * @param {Event} e Event object fired on mousemove + */ + _resetCurrentTransform: function(e) { + var t = this._currentTransform; + + t.target.set({ + scaleX: t.original.scaleX, + scaleY: t.original.scaleY, + left: t.original.left, + top: t.original.top + }); + + if (this._shouldCenterTransform(e, t.target)) { + if (t.action === 'rotate') { + this._setOriginToCenter(t.target); + } + else { + if (t.originX !== 'center') { + if (t.originX === 'right') { + t.mouseXSign = -1; + } + else { + t.mouseXSign = 1; + } + } + if (t.originY !== 'center') { + if (t.originY === 'bottom') { + t.mouseYSign = -1; + } + else { + t.mouseYSign = 1; + } + } + + t.originX = 'center'; + t.originY = 'center'; + } + } + else { + t.originX = t.original.originX; + t.originY = t.original.originY; + } + }, + + /** + * Checks if point is contained within an area of given object + * @param {Event} e Event object + * @param {fabric.Object} target Object to test against + * @return {Boolean} true if point is contained within an area of given object + */ + containsPoint: function (e, target) { + var pointer = this.getPointer(e, true), + xy = this._normalizePointer(target, pointer); + + // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html + // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html + return (target.containsPoint(xy) || target._findTargetCorner(pointer)); + }, + + /** + * @private + */ + _normalizePointer: function (object, pointer) { + var activeGroup = this.getActiveGroup(), + x = pointer.x, + y = pointer.y, + isObjectInGroup = ( + activeGroup && + object.type !== 'group' && + activeGroup.contains(object)), + lt; + + if (isObjectInGroup) { + lt = new fabric.Point(activeGroup.left, activeGroup.top); + lt = fabric.util.transformPoint(lt, this.viewportTransform, true); + x -= lt.x; + y -= lt.y; + } + return { x: x, y: y }; + }, + + /** + * Returns true if object is transparent at a certain location + * @param {fabric.Object} target Object to check + * @param {Number} x Left coordinate + * @param {Number} y Top coordinate + * @return {Boolean} + */ + isTargetTransparent: function (target, x, y) { + var hasBorders = target.hasBorders, + transparentCorners = target.transparentCorners; + + target.hasBorders = target.transparentCorners = false; + + this._draw(this.contextCache, target); + + target.hasBorders = hasBorders; + target.transparentCorners = transparentCorners; + + var isTransparent = fabric.util.isTransparent( + this.contextCache, x, y, this.targetFindTolerance); + + this.clearContext(this.contextCache); + + return isTransparent; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _shouldClearSelection: function (e, target) { + var activeGroup = this.getActiveGroup(), + activeObject = this.getActiveObject(); + + return ( + !target + || + (target && + activeGroup && + !activeGroup.contains(target) && + activeGroup !== target && + !e.shiftKey) + || + (target && !target.evented) + || + (target && + !target.selectable && + activeObject && + activeObject !== target) + ); + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _shouldCenterTransform: function (e, target) { + if (!target) { + return; + } + + var t = this._currentTransform, + centerTransform; + + if (t.action === 'scale' || t.action === 'scaleX' || t.action === 'scaleY') { + centerTransform = this.centeredScaling || target.centeredScaling; + } + else if (t.action === 'rotate') { + centerTransform = this.centeredRotation || target.centeredRotation; + } + + return centerTransform ? !e.altKey : e.altKey; + }, + + /** + * @private + */ + _getOriginFromCorner: function(target, corner) { + var origin = { + x: target.originX, + y: target.originY + }; + + if (corner === 'ml' || corner === 'tl' || corner === 'bl') { + origin.x = 'right'; + } + else if (corner === 'mr' || corner === 'tr' || corner === 'br') { + origin.x = 'left'; + } + + if (corner === 'tl' || corner === 'mt' || corner === 'tr') { + origin.y = 'bottom'; + } + else if (corner === 'bl' || corner === 'mb' || corner === 'br') { + origin.y = 'top'; + } + + return origin; + }, + + /** + * @private + */ + _getActionFromCorner: function(target, corner) { + var action = 'drag'; + if (corner) { + action = (corner === 'ml' || corner === 'mr') + ? 'scaleX' + : (corner === 'mt' || corner === 'mb') + ? 'scaleY' + : corner === 'mtr' + ? 'rotate' + : 'scale'; + } + return action; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _setupCurrentTransform: function (e, target) { + if (!target) { + return; + } + + var pointer = this.getPointer(e), + corner = target._findTargetCorner(this.getPointer(e, true)), + action = this._getActionFromCorner(target, corner), + origin = this._getOriginFromCorner(target, corner); + + this._currentTransform = { + target: target, + action: action, + scaleX: target.scaleX, + scaleY: target.scaleY, + offsetX: pointer.x - target.left, + offsetY: pointer.y - target.top, + originX: origin.x, + originY: origin.y, + ex: pointer.x, + ey: pointer.y, + left: target.left, + top: target.top, + theta: degreesToRadians(target.angle), + width: target.width * target.scaleX, + mouseXSign: 1, + mouseYSign: 1 + }; + + this._currentTransform.original = { + left: target.left, + top: target.top, + scaleX: target.scaleX, + scaleY: target.scaleY, + originX: origin.x, + originY: origin.y + }; + + this._resetCurrentTransform(e); + }, + + /** + * Translates object by "setting" its left/top + * @private + * @param {Number} x pointer's x coordinate + * @param {Number} y pointer's y coordinate + */ + _translateObject: function (x, y) { + var target = this._currentTransform.target; + + if (!target.get('lockMovementX')) { + target.set('left', x - this._currentTransform.offsetX); + } + if (!target.get('lockMovementY')) { + target.set('top', y - this._currentTransform.offsetY); + } + }, + + /** + * Scales object by invoking its scaleX/scaleY methods + * @private + * @param {Number} x pointer's x coordinate + * @param {Number} y pointer's y coordinate + * @param {String} by Either 'x' or 'y' - specifies dimension constraint by which to scale an object. + * When not provided, an object is scaled by both dimensions equally + */ + _scaleObject: function (x, y, by) { + var t = this._currentTransform, + target = t.target, + lockScalingX = target.get('lockScalingX'), + lockScalingY = target.get('lockScalingY'), + lockScalingFlip = target.get('lockScalingFlip'); + + if (lockScalingX && lockScalingY) { + return; + } + + // Get the constraint point + var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY), + localMouse = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY); + + this._setLocalMouse(localMouse, t); + + // Actually scale the object + this._setObjectScale(localMouse, t, lockScalingX, lockScalingY, by, lockScalingFlip); + + // Make sure the constraints apply + target.setPositionByOrigin(constraintPosition, t.originX, t.originY); + }, + + /** + * @private + */ + _setObjectScale: function(localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip) { + var target = transform.target, forbidScalingX = false, forbidScalingY = false; + + transform.newScaleX = localMouse.x / (target.width + target.strokeWidth); + transform.newScaleY = localMouse.y / (target.height + target.strokeWidth); + + if (lockScalingFlip && transform.newScaleX <= 0 && transform.newScaleX < target.scaleX) { + forbidScalingX = true; + } + + if (lockScalingFlip && transform.newScaleY <= 0 && transform.newScaleY < target.scaleY) { + forbidScalingY = true; + } + + if (by === 'equally' && !lockScalingX && !lockScalingY) { + forbidScalingX || forbidScalingY || this._scaleObjectEqually(localMouse, target, transform); + } + else if (!by) { + forbidScalingX || lockScalingX || target.set('scaleX', transform.newScaleX); + forbidScalingY || lockScalingY || target.set('scaleY', transform.newScaleY); + } + else if (by === 'x' && !target.get('lockUniScaling')) { + forbidScalingX || lockScalingX || target.set('scaleX', transform.newScaleX); + } + else if (by === 'y' && !target.get('lockUniScaling')) { + forbidScalingY || lockScalingY || target.set('scaleY', transform.newScaleY); + } + + forbidScalingX || forbidScalingY || this._flipObject(transform); + + }, + + /** + * @private + */ + _scaleObjectEqually: function(localMouse, target, transform) { + + var dist = localMouse.y + localMouse.x, + lastDist = (target.height + (target.strokeWidth)) * transform.original.scaleY + + (target.width + (target.strokeWidth)) * transform.original.scaleX; + + // We use transform.scaleX/Y instead of target.scaleX/Y + // because the object may have a min scale and we'll loose the proportions + transform.newScaleX = transform.original.scaleX * dist / lastDist; + transform.newScaleY = transform.original.scaleY * dist / lastDist; + + target.set('scaleX', transform.newScaleX); + target.set('scaleY', transform.newScaleY); + }, + + /** + * @private + */ + _flipObject: function(transform) { + if (transform.newScaleX < 0) { + if (transform.originX === 'left') { + transform.originX = 'right'; + } + else if (transform.originX === 'right') { + transform.originX = 'left'; + } + } + + if (transform.newScaleY < 0) { + if (transform.originY === 'top') { + transform.originY = 'bottom'; + } + else if (transform.originY === 'bottom') { + transform.originY = 'top'; + } + } + }, + + /** + * @private + */ + _setLocalMouse: function(localMouse, t) { + var target = t.target; + + if (t.originX === 'right') { + localMouse.x *= -1; + } + else if (t.originX === 'center') { + localMouse.x *= t.mouseXSign * 2; + + if (localMouse.x < 0) { + t.mouseXSign = -t.mouseXSign; + } + } + + if (t.originY === 'bottom') { + localMouse.y *= -1; + } + else if (t.originY === 'center') { + localMouse.y *= t.mouseYSign * 2; + + if (localMouse.y < 0) { + t.mouseYSign = -t.mouseYSign; + } + } + + // adjust the mouse coordinates when dealing with padding + if (abs(localMouse.x) > target.padding) { + if (localMouse.x < 0) { + localMouse.x += target.padding; + } + else { + localMouse.x -= target.padding; + } + } + else { // mouse is within the padding, set to 0 + localMouse.x = 0; + } + + if (abs(localMouse.y) > target.padding) { + if (localMouse.y < 0) { + localMouse.y += target.padding; + } + else { + localMouse.y -= target.padding; + } + } + else { + localMouse.y = 0; + } + }, + + /** + * Rotates object by invoking its rotate method + * @private + * @param {Number} x pointer's x coordinate + * @param {Number} y pointer's y coordinate + */ + _rotateObject: function (x, y) { + + var t = this._currentTransform; + + if (t.target.get('lockRotation')) { + return; + } + + var lastAngle = atan2(t.ey - t.top, t.ex - t.left), + curAngle = atan2(y - t.top, x - t.left), + angle = radiansToDegrees(curAngle - lastAngle + t.theta); + + // normalize angle to positive value + if (angle < 0) { + angle = 360 + angle; + } + + t.target.angle = angle; + }, + + /** + * Set the cursor type of the canvas element + * @param {String} value Cursor type of the canvas element. + * @see http://www.w3.org/TR/css3-ui/#cursor + */ + setCursor: function (value) { + this.upperCanvasEl.style.cursor = value; + }, + + /** + * @private + */ + _resetObjectTransform: function (target) { + target.scaleX = 1; + target.scaleY = 1; + target.setAngle(0); + }, + + /** + * @private + */ + _drawSelection: function () { + var ctx = this.contextTop, + groupSelector = this._groupSelector, + left = groupSelector.left, + top = groupSelector.top, + aleft = abs(left), + atop = abs(top); + + ctx.fillStyle = this.selectionColor; + + ctx.fillRect( + groupSelector.ex - ((left > 0) ? 0 : -left), + groupSelector.ey - ((top > 0) ? 0 : -top), + aleft, + atop + ); + + ctx.lineWidth = this.selectionLineWidth; + ctx.strokeStyle = this.selectionBorderColor; + + // selection border + if (this.selectionDashArray.length > 1) { + + var px = groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0: aleft), + py = groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0: atop); + + ctx.beginPath(); + + fabric.util.drawDashedLine(ctx, px, py, px + aleft, py, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px, py + atop - 1, px + aleft, py + atop - 1, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px, py, px, py + atop, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px + aleft - 1, py, px + aleft - 1, py + atop, this.selectionDashArray); + + ctx.closePath(); + ctx.stroke(); + } + else { + ctx.strokeRect( + groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft), + groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop), + aleft, + atop + ); + } + }, + + /** + * @private + */ + _isLastRenderedObject: function(e) { + return ( + this.controlsAboveOverlay && + this.lastRenderedObjectWithControlsAboveOverlay && + this.lastRenderedObjectWithControlsAboveOverlay.visible && + this.containsPoint(e, this.lastRenderedObjectWithControlsAboveOverlay) && + this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e, true))); + }, + + /** + * Method that determines what object we are clicking on + * @param {Event} e mouse event + * @param {Boolean} skipGroup when true, group is skipped and only objects are traversed through + */ + findTarget: function (e, skipGroup) { + if (this.skipTargetFind) { + return; + } + + if (this._isLastRenderedObject(e)) { + return this.lastRenderedObjectWithControlsAboveOverlay; + } + + // first check current group (if one exists) + var activeGroup = this.getActiveGroup(); + if (activeGroup && !skipGroup && this.containsPoint(e, activeGroup)) { + return activeGroup; + } + + var target = this._searchPossibleTargets(e); + this._fireOverOutEvents(target); + + return target; + }, + + /** + * @private + */ + _fireOverOutEvents: function(target) { + if (target) { + if (this._hoveredTarget !== target) { + this.fire('mouse:over', { target: target }); + target.fire('mouseover'); + if (this._hoveredTarget) { + this.fire('mouse:out', { target: this._hoveredTarget }); + this._hoveredTarget.fire('mouseout'); + } + this._hoveredTarget = target; + } + } + else if (this._hoveredTarget) { + this.fire('mouse:out', { target: this._hoveredTarget }); + this._hoveredTarget.fire('mouseout'); + this._hoveredTarget = null; + } + }, + + /** + * @private + */ + _checkTarget: function(e, obj, pointer) { + if (obj && + obj.visible && + obj.evented && + this.containsPoint(e, obj)){ + if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) { + var isTransparent = this.isTargetTransparent(obj, pointer.x, pointer.y); + if (!isTransparent) { + return true; + } + } + else { + return true; + } + } + }, + + /** + * @private + */ + _searchPossibleTargets: function(e) { + + // Cache all targets where their bounding box contains point. + var target, + pointer = this.getPointer(e, true), + i = this._objects.length; + + while (i--) { + if (this._checkTarget(e, this._objects[i], pointer)){ + this.relatedTarget = this._objects[i]; + target = this._objects[i]; + break; + } + } + + return target; + }, + + /** + * Returns pointer coordinates relative to canvas. + * @param {Event} e + * @return {Object} object with "x" and "y" number values + */ + getPointer: function (e, ignoreZoom, upperCanvasEl) { + if (!upperCanvasEl) { + upperCanvasEl = this.upperCanvasEl; + } + var pointer = getPointer(e, upperCanvasEl), + bounds = upperCanvasEl.getBoundingClientRect(), + cssScale; + + this.calcOffset(); + + pointer.x = pointer.x - this._offset.left; + pointer.y = pointer.y - this._offset.top; + if (!ignoreZoom) { + pointer = fabric.util.transformPoint( + pointer, + fabric.util.invertTransform(this.viewportTransform) + ); + } + + if (bounds.width === 0 || bounds.height === 0) { + // If bounds are not available (i.e. not visible), do not apply scale. + cssScale = { width: 1, height: 1 }; + } + else { + cssScale = { + width: upperCanvasEl.width / bounds.width, + height: upperCanvasEl.height / bounds.height + }; + } + + return { + x: pointer.x * cssScale.width, + y: pointer.y * cssScale.height + }; + }, + + /** + * @private + * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized + */ + _createUpperCanvas: function () { + var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/, ''); + + this.upperCanvasEl = this._createCanvasElement(); + fabric.util.addClass(this.upperCanvasEl, 'upper-canvas ' + lowerCanvasClass); + + this.wrapperEl.appendChild(this.upperCanvasEl); + + this._copyCanvasStyle(this.lowerCanvasEl, this.upperCanvasEl); + this._applyCanvasStyle(this.upperCanvasEl); + this.contextTop = this.upperCanvasEl.getContext('2d'); + }, + + /** + * @private + */ + _createCacheCanvas: function () { + this.cacheCanvasEl = this._createCanvasElement(); + this.cacheCanvasEl.setAttribute('width', this.width); + this.cacheCanvasEl.setAttribute('height', this.height); + this.contextCache = this.cacheCanvasEl.getContext('2d'); + }, + + /** + * @private + */ + _initWrapperElement: function () { + this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', { + 'class': this.containerClass + }); + fabric.util.setStyle(this.wrapperEl, { + width: this.getWidth() + 'px', + height: this.getHeight() + 'px', + position: 'relative' + }); + fabric.util.makeElementUnselectable(this.wrapperEl); + }, + + /** + * @private + * @param {HTMLElement} element canvas element to apply styles on + */ + _applyCanvasStyle: function (element) { + var width = this.getWidth() || element.width, + height = this.getHeight() || element.height; + + fabric.util.setStyle(element, { + position: 'absolute', + width: width + 'px', + height: height + 'px', + left: 0, + top: 0 + }); + element.width = width; + element.height = height; + fabric.util.makeElementUnselectable(element); + }, + + /** + * Copys the the entire inline style from one element (fromEl) to another (toEl) + * @private + * @param {Element} fromEl Element style is copied from + * @param {Element} toEl Element copied style is applied to + */ + _copyCanvasStyle: function (fromEl, toEl) { + toEl.style.cssText = fromEl.style.cssText; + }, + + /** + * Returns context of canvas where object selection is drawn + * @return {CanvasRenderingContext2D} + */ + getSelectionContext: function() { + return this.contextTop; + }, + + /** + * Returns <canvas> element on which object selection is drawn + * @return {HTMLCanvasElement} + */ + getSelectionElement: function () { + return this.upperCanvasEl; + }, + + /** + * @private + * @param {Object} object + */ + _setActiveObject: function(object) { + if (this._activeObject) { + this._activeObject.set('active', false); + } + this._activeObject = object; + object.set('active', true); + }, + + /** + * Sets given object as the only active object on canvas + * @param {fabric.Object} object Object to set as an active one + * @param {Event} [e] Event (passed along when firing "object:selected") + * @return {fabric.Canvas} thisArg + * @chainable + */ + setActiveObject: function (object, e) { + this._setActiveObject(object); + this.renderAll(); + this.fire('object:selected', { target: object, e: e }); + object.fire('selected', { e: e }); + return this; + }, + + /** + * Returns currently active object + * @return {fabric.Object} active object + */ + getActiveObject: function () { + return this._activeObject; + }, + + /** + * @private + */ + _discardActiveObject: function() { + if (this._activeObject) { + this._activeObject.set('active', false); + } + this._activeObject = null; + }, + + /** + * Discards currently active object + * @return {fabric.Canvas} thisArg + * @chainable + */ + discardActiveObject: function (e) { + this._discardActiveObject(); + this.renderAll(); + this.fire('selection:cleared', { e: e }); + return this; + }, + + /** + * @private + * @param {fabric.Group} group + */ + _setActiveGroup: function(group) { + this._activeGroup = group; + if (group) { + group.set('active', true); + } + }, + + /** + * Sets active group to a speicified one + * @param {fabric.Group} group Group to set as a current one + * @return {fabric.Canvas} thisArg + * @chainable + */ + setActiveGroup: function (group, e) { + this._setActiveGroup(group); + if (group) { + this.fire('object:selected', { target: group, e: e }); + group.fire('selected', { e: e }); + } + return this; + }, + + /** + * Returns currently active group + * @return {fabric.Group} Current group + */ + getActiveGroup: function () { + return this._activeGroup; + }, + + /** + * @private + */ + _discardActiveGroup: function() { + var g = this.getActiveGroup(); + if (g) { + g.destroy(); + } + this.setActiveGroup(null); + }, + + /** + * Discards currently active group + * @return {fabric.Canvas} thisArg + */ + discardActiveGroup: function (e) { + this._discardActiveGroup(); + this.fire('selection:cleared', { e: e }); + return this; + }, + + /** + * Deactivates all objects on canvas, removing any active group or object + * @return {fabric.Canvas} thisArg + */ + deactivateAll: function () { + var allObjects = this.getObjects(), + i = 0, + len = allObjects.length; + for ( ; i < len; i++) { + allObjects[i].set('active', false); + } + this._discardActiveGroup(); + this._discardActiveObject(); + return this; + }, + + /** + * Deactivates all objects and dispatches appropriate events + * @return {fabric.Canvas} thisArg + */ + deactivateAllWithDispatch: function (e) { + var activeObject = this.getActiveGroup() || this.getActiveObject(); + if (activeObject) { + this.fire('before:selection:cleared', { target: activeObject, e: e }); + } + this.deactivateAll(); + if (activeObject) { + this.fire('selection:cleared', { e: e }); + } + return this; + }, + + /** + * Draws objects' controls (borders/controls) + * @param {CanvasRenderingContext2D} ctx Context to render controls on + */ + drawControls: function(ctx) { + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + this._drawGroupControls(ctx, activeGroup); + } + else { + this._drawObjectsControls(ctx); + } + }, + + /** + * @private + */ + _drawGroupControls: function(ctx, activeGroup) { + activeGroup._renderControls(ctx); + }, + + /** + * @private + */ + _drawObjectsControls: function(ctx) { + for (var i = 0, len = this._objects.length; i < len; ++i) { + if (!this._objects[i] || !this._objects[i].active) { + continue; + } + this._objects[i]._renderControls(ctx); + this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i]; + } + } + }); + + // copying static properties manually to work around Opera's bug, + // where "prototype" property is enumerable and overrides existing prototype + for (var prop in fabric.StaticCanvas) { + if (prop !== 'prototype') { + fabric.Canvas[prop] = fabric.StaticCanvas[prop]; + } + } + + if (fabric.isTouchSupported) { + /** @ignore */ + fabric.Canvas.prototype._setCursorFromEvent = function() { }; + } + + /** + * @class fabric.Element + * @alias fabric.Canvas + * @deprecated Use {@link fabric.Canvas} instead. + * @constructor + */ + fabric.Element = fabric.Canvas; +})(); + + +(function(){ + + var cursorOffset = { + mt: 0, // n + tr: 1, // ne + mr: 2, // e + br: 3, // se + mb: 4, // s + bl: 5, // sw + ml: 6, // w + tl: 7 // nw + }, + addListener = fabric.util.addListener, + removeListener = fabric.util.removeListener; + + fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ { + + /** + * Map of cursor style values for each of the object controls + * @private + */ + cursorMap: [ + 'n-resize', + 'ne-resize', + 'e-resize', + 'se-resize', + 's-resize', + 'sw-resize', + 'w-resize', + 'nw-resize' + ], + + /** + * Adds mouse listeners to canvas + * @private + */ + _initEventListeners: function () { + + this._bindEvents(); + + addListener(fabric.window, 'resize', this._onResize); + + // mouse events + addListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); + addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + addListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel); + + // touch events + addListener(this.upperCanvasEl, 'touchstart', this._onMouseDown); + addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (typeof Event !== 'undefined' && 'add' in Event) { + Event.add(this.upperCanvasEl, 'gesture', this._onGesture); + Event.add(this.upperCanvasEl, 'drag', this._onDrag); + Event.add(this.upperCanvasEl, 'orientation', this._onOrientationChange); + Event.add(this.upperCanvasEl, 'shake', this._onShake); + } + }, + + /** + * @private + */ + _bindEvents: function() { + this._onMouseDown = this._onMouseDown.bind(this); + this._onMouseMove = this._onMouseMove.bind(this); + this._onMouseUp = this._onMouseUp.bind(this); + this._onResize = this._onResize.bind(this); + this._onGesture = this._onGesture.bind(this); + this._onDrag = this._onDrag.bind(this); + this._onShake = this._onShake.bind(this); + this._onOrientationChange = this._onOrientationChange.bind(this); + this._onMouseWheel = this._onMouseWheel.bind(this); + }, + + /** + * Removes all event listeners + */ + removeListeners: function() { + removeListener(fabric.window, 'resize', this._onResize); + + removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); + removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + removeListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel); + + removeListener(this.upperCanvasEl, 'touchstart', this._onMouseDown); + removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (typeof Event !== 'undefined' && 'remove' in Event) { + Event.remove(this.upperCanvasEl, 'gesture', this._onGesture); + Event.remove(this.upperCanvasEl, 'drag', this._onDrag); + Event.remove(this.upperCanvasEl, 'orientation', this._onOrientationChange); + Event.remove(this.upperCanvasEl, 'shake', this._onShake); + } + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js gesture + * @param {Event} [self] Inner Event object + */ + _onGesture: function(e, self) { + this.__onTransformGesture && this.__onTransformGesture(e, self); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js drag + * @param {Event} [self] Inner Event object + */ + _onDrag: function(e, self) { + this.__onDrag && this.__onDrag(e, self); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js wheel event + * @param {Event} [self] Inner Event object + */ + _onMouseWheel: function(e, self) { + this.__onMouseWheel && this.__onMouseWheel(e, self); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js orientation change + * @param {Event} [self] Inner Event object + */ + _onOrientationChange: function(e,self) { + this.__onOrientationChange && this.__onOrientationChange(e,self); + }, + + /** + * @private + * @param {Event} [e] Event object fired on Event.js shake + * @param {Event} [self] Inner Event object + */ + _onShake: function(e, self) { + this.__onShake && this.__onShake(e,self); + }, + + /** + * @private + * @param {Event} e Event object fired on mousedown + */ + _onMouseDown: function (e) { + this.__onMouseDown(e); + + addListener(fabric.document, 'touchend', this._onMouseUp); + addListener(fabric.document, 'touchmove', this._onMouseMove); + + removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (e.type === 'touchstart') { + // Unbind mousedown to prevent double triggers from touch devices + removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); + } + else { + addListener(fabric.document, 'mouseup', this._onMouseUp); + addListener(fabric.document, 'mousemove', this._onMouseMove); + } + }, + + /** + * @private + * @param {Event} e Event object fired on mouseup + */ + _onMouseUp: function (e) { + this.__onMouseUp(e); + + removeListener(fabric.document, 'mouseup', this._onMouseUp); + removeListener(fabric.document, 'touchend', this._onMouseUp); + + removeListener(fabric.document, 'mousemove', this._onMouseMove); + removeListener(fabric.document, 'touchmove', this._onMouseMove); + + addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); + addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); + + if (e.type === 'touchend') { + // Wait 400ms before rebinding mousedown to prevent double triggers + // from touch devices + var _this = this; + setTimeout(function() { + addListener(_this.upperCanvasEl, 'mousedown', _this._onMouseDown); + }, 400); + } + }, + + /** + * @private + * @param {Event} e Event object fired on mousemove + */ + _onMouseMove: function (e) { + !this.allowTouchScrolling && e.preventDefault && e.preventDefault(); + this.__onMouseMove(e); + }, + + /** + * @private + */ + _onResize: function () { + this.calcOffset(); + }, + + /** + * Decides whether the canvas should be redrawn in mouseup and mousedown events. + * @private + * @param {Object} target + * @param {Object} pointer + */ + _shouldRender: function(target, pointer) { + var activeObject = this.getActiveGroup() || this.getActiveObject(); + + return !!( + (target && ( + target.isMoving || + target !== activeObject)) + || + (!target && !!activeObject) + || + (!target && !activeObject && !this._groupSelector) + || + (pointer && + this._previousPointer && + this.selection && ( + pointer.x !== this._previousPointer.x || + pointer.y !== this._previousPointer.y)) + ); + }, + + /** + * Method that defines the actions when mouse is released on canvas. + * The method resets the currentTransform parameters, store the image corner + * position in the image object and render the canvas on top. + * @private + * @param {Event} e Event object fired on mouseup + */ + __onMouseUp: function (e) { + var target; + + if (this.isDrawingMode && this._isCurrentlyDrawing) { + this._onMouseUpInDrawingMode(e); + return; + } + + if (this._currentTransform) { + this._finalizeCurrentTransform(); + target = this._currentTransform.target; + } + else { + target = this.findTarget(e, true); + } + + var shouldRender = this._shouldRender(target, this.getPointer(e)); + + this._maybeGroupObjects(e); + + if (target) { + target.isMoving = false; + } + + shouldRender && this.renderAll(); + + this._handleCursorAndEvent(e, target); + }, + + _handleCursorAndEvent: function(e, target) { + this._setCursorFromEvent(e, target); + + // TODO: why are we doing this? + var _this = this; + setTimeout(function () { + _this._setCursorFromEvent(e, target); + }, 50); + + this.fire('mouse:up', { target: target, e: e }); + target && target.fire('mouseup', { e: e }); + }, + + /** + * @private + */ + _finalizeCurrentTransform: function() { + + var transform = this._currentTransform, + target = transform.target; + + if (target._scaling) { + target._scaling = false; + } + + target.setCoords(); + + // only fire :modified event if target coordinates were changed during mousedown-mouseup + if (this.stateful && target.hasStateChanged()) { + this.fire('object:modified', { target: target }); + target.fire('modified'); + } + + this._restoreOriginXY(target); + }, + + /** + * @private + * @param {Object} target Object to restore + */ + _restoreOriginXY: function(target) { + if (this._previousOriginX && this._previousOriginY) { + + var originPoint = target.translateToOriginPoint( + target.getCenterPoint(), + this._previousOriginX, + this._previousOriginY); + + target.originX = this._previousOriginX; + target.originY = this._previousOriginY; + + target.left = originPoint.x; + target.top = originPoint.y; + + this._previousOriginX = null; + this._previousOriginY = null; + } + }, + + /** + * @private + * @param {Event} e Event object fired on mousedown + */ + _onMouseDownInDrawingMode: function(e) { + this._isCurrentlyDrawing = true; + this.discardActiveObject(e).renderAll(); + if (this.clipTo) { + fabric.util.clipContext(this, this.contextTop); + } + var ivt = fabric.util.invertTransform(this.viewportTransform), + pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt); + this.freeDrawingBrush.onMouseDown(pointer); + this.fire('mouse:down', { e: e }); + }, + + /** + * @private + * @param {Event} e Event object fired on mousemove + */ + _onMouseMoveInDrawingMode: function(e) { + if (this._isCurrentlyDrawing) { + var ivt = fabric.util.invertTransform(this.viewportTransform), + pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt); + this.freeDrawingBrush.onMouseMove(pointer); + } + this.setCursor(this.freeDrawingCursor); + this.fire('mouse:move', { e: e }); + }, + + /** + * @private + * @param {Event} e Event object fired on mouseup + */ + _onMouseUpInDrawingMode: function(e) { + this._isCurrentlyDrawing = false; + if (this.clipTo) { + this.contextTop.restore(); + } + this.freeDrawingBrush.onMouseUp(); + this.fire('mouse:up', { e: e }); + }, + + /** + * Method that defines the actions when mouse is clic ked on canvas. + * The method inits the currentTransform parameters and renders all the + * canvas so the current image can be placed on the top canvas and the rest + * in on the container one. + * @private + * @param {Event} e Event object fired on mousedown + */ + __onMouseDown: function (e) { + + // accept only left clicks + var isLeftClick = 'which' in e ? e.which === 1 : e.button === 1; + if (!isLeftClick && !fabric.isTouchSupported) { + return; + } + + if (this.isDrawingMode) { + this._onMouseDownInDrawingMode(e); + return; + } + + // ignore if some object is being transformed at this moment + if (this._currentTransform) { + return; + } + + var target = this.findTarget(e), + pointer = this.getPointer(e, true); + + // save pointer for check in __onMouseUp event + this._previousPointer = pointer; + + var shouldRender = this._shouldRender(target, pointer), + shouldGroup = this._shouldGroup(e, target); + + if (this._shouldClearSelection(e, target)) { + this._clearSelection(e, target, pointer); + } + else if (shouldGroup) { + this._handleGrouping(e, target); + target = this.getActiveGroup(); + } + + if (target && target.selectable && !shouldGroup) { + this._beforeTransform(e, target); + this._setupCurrentTransform(e, target); + } + // we must renderAll so that active image is placed on the top canvas + shouldRender && this.renderAll(); + + this.fire('mouse:down', { target: target, e: e }); + target && target.fire('mousedown', { e: e }); + }, + + /** + * @private + */ + _beforeTransform: function(e, target) { + var corner; + + this.stateful && target.saveState(); + + // determine if it's a drag or rotate case + if ((corner = target._findTargetCorner(this.getPointer(e)))) { + this.onBeforeScaleRotate(target); + } + + if (target !== this.getActiveGroup() && target !== this.getActiveObject()) { + this.deactivateAll(); + this.setActiveObject(target, e); + } + }, + + /** + * @private + */ + _clearSelection: function(e, target, pointer) { + this.deactivateAllWithDispatch(e); + + if (target && target.selectable) { + this.setActiveObject(target, e); + } + else if (this.selection) { + this._groupSelector = { + ex: pointer.x, + ey: pointer.y, + top: 0, + left: 0 + }; + } + }, + + /** + * @private + * @param {Object} target Object for that origin is set to center + */ + _setOriginToCenter: function(target) { + this._previousOriginX = this._currentTransform.target.originX; + this._previousOriginY = this._currentTransform.target.originY; + + var center = target.getCenterPoint(); + + target.originX = 'center'; + target.originY = 'center'; + + target.left = center.x; + target.top = center.y; + + this._currentTransform.left = target.left; + this._currentTransform.top = target.top; + }, + + /** + * @private + * @param {Object} target Object for that center is set to origin + */ + _setCenterToOrigin: function(target) { + var originPoint = target.translateToOriginPoint( + target.getCenterPoint(), + this._previousOriginX, + this._previousOriginY); + + target.originX = this._previousOriginX; + target.originY = this._previousOriginY; + + target.left = originPoint.x; + target.top = originPoint.y; + + this._previousOriginX = null; + this._previousOriginY = null; + }, + + /** + * Method that defines the actions when mouse is hovering the canvas. + * The currentTransform parameter will definde whether the user is rotating/scaling/translating + * an image or neither of them (only hovering). A group selection is also possible and would cancel + * all any other type of action. + * In case of an image transformation only the top canvas will be rendered. + * @private + * @param {Event} e Event object fired on mousemove + */ + __onMouseMove: function (e) { + + var target, pointer; + + if (this.isDrawingMode) { + this._onMouseMoveInDrawingMode(e); + return; + } + + var groupSelector = this._groupSelector; + + // We initially clicked in an empty area, so we draw a box for multiple selection + if (groupSelector) { + pointer = this.getPointer(e, true); + + groupSelector.left = pointer.x - groupSelector.ex; + groupSelector.top = pointer.y - groupSelector.ey; + + this.renderTop(); + } + else if (!this._currentTransform) { + + target = this.findTarget(e); + + if (!target || target && !target.selectable) { + this.setCursor(this.defaultCursor); + } + else { + this._setCursorFromEvent(e, target); + } + } + else { + this._transformObject(e); + } + + this.fire('mouse:move', { target: target, e: e }); + target && target.fire('mousemove', { e: e }); + }, + + /** + * @private + * @param {Event} e Event fired on mousemove + */ + _transformObject: function(e) { + var pointer = this.getPointer(e), + transform = this._currentTransform; + + transform.reset = false, + transform.target.isMoving = true; + + this._beforeScaleTransform(e, transform); + this._performTransformAction(e, transform, pointer); + + this.renderAll(); + }, + + /** + * @private + */ + _performTransformAction: function(e, transform, pointer) { + var x = pointer.x, + y = pointer.y, + target = transform.target, + action = transform.action; + + if (action === 'rotate') { + this._rotateObject(x, y); + this._fire('rotating', target, e); + } + else if (action === 'scale') { + this._onScale(e, transform, x, y); + this._fire('scaling', target, e); + } + else if (action === 'scaleX') { + this._scaleObject(x, y, 'x'); + this._fire('scaling', target, e); + } + else if (action === 'scaleY') { + this._scaleObject(x, y, 'y'); + this._fire('scaling', target, e); + } + else { + this._translateObject(x, y); + this._fire('moving', target, e); + this.setCursor(this.moveCursor); + } + }, + + /** + * @private + */ + _fire: function(eventName, target, e) { + this.fire('object:' + eventName, { target: target, e: e }); + target.fire(eventName, { e: e }); + }, + + /** + * @private + */ + _beforeScaleTransform: function(e, transform) { + if (transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') { + var centerTransform = this._shouldCenterTransform(e, transform.target); + + // Switch from a normal resize to center-based + if ((centerTransform && (transform.originX !== 'center' || transform.originY !== 'center')) || + // Switch from center-based resize to normal one + (!centerTransform && transform.originX === 'center' && transform.originY === 'center') + ) { + this._resetCurrentTransform(e); + transform.reset = true; + } + } + }, + + /** + * @private + */ + _onScale: function(e, transform, x, y) { + // rotate object only if shift key is not pressed + // and if it is not a group we are transforming + if ((e.shiftKey || this.uniScaleTransform) && !transform.target.get('lockUniScaling')) { + transform.currentAction = 'scale'; + this._scaleObject(x, y); + } + else { + // Switch from a normal resize to proportional + if (!transform.reset && transform.currentAction === 'scale') { + this._resetCurrentTransform(e, transform.target); + } + + transform.currentAction = 'scaleEqually'; + this._scaleObject(x, y, 'equally'); + } + }, + + /** + * Sets the cursor depending on where the canvas is being hovered. + * Note: very buggy in Opera + * @param {Event} e Event object + * @param {Object} target Object that the mouse is hovering, if so. + */ + _setCursorFromEvent: function (e, target) { + if (!target || !target.selectable) { + this.setCursor(this.defaultCursor); + return false; + } + else { + var activeGroup = this.getActiveGroup(), + // only show proper corner when group selection is not active + corner = target._findTargetCorner + && (!activeGroup || !activeGroup.contains(target)) + && target._findTargetCorner(this.getPointer(e, true)); + + if (!corner) { + this.setCursor(target.hoverCursor || this.hoverCursor); + } + else { + this._setCornerCursor(corner, target); + } + } + return true; + }, + + /** + * @private + */ + _setCornerCursor: function(corner, target) { + if (corner in cursorOffset) { + this.setCursor(this._getRotatedCornerCursor(corner, target)); + } + else if (corner === 'mtr' && target.hasRotatingPoint) { + this.setCursor(this.rotationCursor); + } + else { + this.setCursor(this.defaultCursor); + return false; + } + }, + + /** + * @private + */ + _getRotatedCornerCursor: function(corner, target) { + var n = Math.round((target.getAngle() % 360) / 45); + + if (n < 0) { + n += 8; // full circle ahead + } + n += cursorOffset[corner]; + // normalize n to be from 0 to 7 + n %= 8; + + return this.cursorMap[n]; + } + }); +})(); + + +(function(){ + + var min = Math.min, + max = Math.max; + + fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ { + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + * @return {Boolean} + */ + _shouldGroup: function(e, target) { + var activeObject = this.getActiveObject(); + return e.shiftKey && + (this.getActiveGroup() || (activeObject && activeObject !== target)) + && this.selection; + }, + + /** + * @private + * @param {Event} e Event object + * @param {fabric.Object} target + */ + _handleGrouping: function (e, target) { + + if (target === this.getActiveGroup()) { + + // if it's a group, find target again, this time skipping group + target = this.findTarget(e, true); + + // if even object is not found, bail out + if (!target || target.isType('group')) { + return; + } + } + if (this.getActiveGroup()) { + this._updateActiveGroup(target, e); + } + else { + this._createActiveGroup(target, e); + } + + if (this._activeGroup) { + this._activeGroup.saveCoords(); + } + }, + + /** + * @private + */ + _updateActiveGroup: function(target, e) { + var activeGroup = this.getActiveGroup(); + + if (activeGroup.contains(target)) { + + activeGroup.removeWithUpdate(target); + this._resetObjectTransform(activeGroup); + target.set('active', false); + + if (activeGroup.size() === 1) { + // remove group alltogether if after removal it only contains 1 object + this.discardActiveGroup(e); + // activate last remaining object + this.setActiveObject(activeGroup.item(0)); + return; + } + } + else { + activeGroup.addWithUpdate(target); + this._resetObjectTransform(activeGroup); + } + this.fire('selection:created', { target: activeGroup, e: e }); + activeGroup.set('active', true); + }, + + /** + * @private + */ + _createActiveGroup: function(target, e) { + + if (this._activeObject && target !== this._activeObject) { + + var group = this._createGroup(target); + group.addWithUpdate(); + + this.setActiveGroup(group); + this._activeObject = null; + + this.fire('selection:created', { target: group, e: e }); + } + + target.set('active', true); + }, + + /** + * @private + * @param {Object} target + */ + _createGroup: function(target) { + + var objects = this.getObjects(), + isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target), + groupObjects = isActiveLower + ? [ this._activeObject, target ] + : [ target, this._activeObject ]; + + return new fabric.Group(groupObjects, { + originX: 'center', + originY: 'center', + canvas: this + }); + }, + + /** + * @private + * @param {Event} e mouse event + */ + _groupSelectedObjects: function (e) { + + var group = this._collectObjects(); + + // do not create group for 1 element only + if (group.length === 1) { + this.setActiveObject(group[0], e); + } + else if (group.length > 1) { + group = new fabric.Group(group.reverse(), { + originX: 'center', + originY: 'center', + canvas: this + }); + group.addWithUpdate(); + this.setActiveGroup(group, e); + group.saveCoords(); + this.fire('selection:created', { target: group }); + this.renderAll(); + } + }, + + /** + * @private + */ + _collectObjects: function() { + var group = [ ], + currentObject, + x1 = this._groupSelector.ex, + y1 = this._groupSelector.ey, + x2 = x1 + this._groupSelector.left, + y2 = y1 + this._groupSelector.top, + selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)), + selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)), + isClick = x1 === x2 && y1 === y2; + + for (var i = this._objects.length; i--; ) { + currentObject = this._objects[i]; + + if (!currentObject || !currentObject.selectable || !currentObject.visible) { + continue; + } + + if (currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) || + currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) || + currentObject.containsPoint(selectionX1Y1) || + currentObject.containsPoint(selectionX2Y2) + ) { + currentObject.set('active', true); + group.push(currentObject); + + // only add one object if it's a click + if (isClick) { + break; + } + } + } + + return group; + }, + + /** + * @private + */ + _maybeGroupObjects: function(e) { + if (this.selection && this._groupSelector) { + this._groupSelectedObjects(e); + } + + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + activeGroup.setObjectsCoords().setCoords(); + activeGroup.isMoving = false; + this.setCursor(this.defaultCursor); + } + + // clear selection and current transformation + this._groupSelector = null; + this._currentTransform = null; + } + }); + +})(); + + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately + * @param {Object} [options] Options object + * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png" + * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg. + * @param {Number} [options.multiplier=1] Multiplier to scale by + * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14 + * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14 + * @param {Number} [options.width] Cropping width. Introduced in v1.2.14 + * @param {Number} [options.height] Cropping height. Introduced in v1.2.14 + * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format + * @see {@link http://jsfiddle.net/fabricjs/NfZVb/|jsFiddle demo} + * @example + * var dataURL = canvas.toDataURL({ + * format: 'jpeg', + * quality: 0.8 + * }); + * @example + * var dataURL = canvas.toDataURL({ + * format: 'png', + * left: 100, + * top: 100, + * width: 200, + * height: 200 + * }); + * @example + * var dataURL = canvas.toDataURL({ + * format: 'png', + * multiplier: 2 + * }); + */ + toDataURL: function (options) { + options || (options = { }); + + var format = options.format || 'png', + quality = options.quality || 1, + multiplier = options.multiplier || 1, + cropping = { + left: options.left, + top: options.top, + width: options.width, + height: options.height + }; + + if (multiplier !== 1) { + return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier); + } + else { + return this.__toDataURL(format, quality, cropping); + } + }, + + /** + * @private + */ + __toDataURL: function(format, quality, cropping) { + + this.renderAll(true); + + var canvasEl = this.upperCanvasEl || this.lowerCanvasEl, + croppedCanvasEl = this.__getCroppedCanvas(canvasEl, cropping); + + // to avoid common confusion https://github.com/kangax/fabric.js/issues/806 + if (format === 'jpg') { + format = 'jpeg'; + } + + var data = (fabric.StaticCanvas.supports('toDataURLWithQuality')) + ? (croppedCanvasEl || canvasEl).toDataURL('image/' + format, quality) + : (croppedCanvasEl || canvasEl).toDataURL('image/' + format); + + this.contextTop && this.clearContext(this.contextTop); + this.renderAll(); + + if (croppedCanvasEl) { + croppedCanvasEl = null; + } + + return data; + }, + + /** + * @private + */ + __getCroppedCanvas: function(canvasEl, cropping) { + + var croppedCanvasEl, + croppedCtx, + shouldCrop = 'left' in cropping || + 'top' in cropping || + 'width' in cropping || + 'height' in cropping; + + if (shouldCrop) { + + croppedCanvasEl = fabric.util.createCanvasElement(); + croppedCtx = croppedCanvasEl.getContext('2d'); + + croppedCanvasEl.width = cropping.width || this.width; + croppedCanvasEl.height = cropping.height || this.height; + + croppedCtx.drawImage(canvasEl, -cropping.left || 0, -cropping.top || 0); + } + + return croppedCanvasEl; + }, + + /** + * @private + */ + __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) { + + var origWidth = this.getWidth(), + origHeight = this.getHeight(), + scaledWidth = origWidth * multiplier, + scaledHeight = origHeight * multiplier, + activeObject = this.getActiveObject(), + activeGroup = this.getActiveGroup(), + + ctx = this.contextTop || this.contextContainer; + + if (multiplier > 1) { + this.setWidth(scaledWidth).setHeight(scaledHeight); + } + ctx.scale(multiplier, multiplier); + + if (cropping.left) { + cropping.left *= multiplier; + } + if (cropping.top) { + cropping.top *= multiplier; + } + if (cropping.width) { + cropping.width *= multiplier; + } + else if (multiplier < 1) { + cropping.width = scaledWidth; + } + if (cropping.height) { + cropping.height *= multiplier; + } + else if (multiplier < 1) { + cropping.height = scaledHeight; + } + + if (activeGroup) { + // not removing group due to complications with restoring it with correct state afterwords + this._tempRemoveBordersControlsFromGroup(activeGroup); + } + else if (activeObject && this.deactivateAll) { + this.deactivateAll(); + } + + this.renderAll(true); + + var data = this.__toDataURL(format, quality, cropping); + + // restoring width, height for `renderAll` to draw + // background properly (while context is scaled) + this.width = origWidth; + this.height = origHeight; + + ctx.scale(1 / multiplier, 1 / multiplier); + this.setWidth(origWidth).setHeight(origHeight); + + if (activeGroup) { + this._restoreBordersControlsOnGroup(activeGroup); + } + else if (activeObject && this.setActiveObject) { + this.setActiveObject(activeObject); + } + + this.contextTop && this.clearContext(this.contextTop); + this.renderAll(); + + return data; + }, + + /** + * Exports canvas element to a dataurl image (allowing to change image size via multiplier). + * @deprecated since 1.0.13 + * @param {String} format (png|jpeg) + * @param {Number} multiplier + * @param {Number} quality (0..1) + * @return {String} + */ + toDataURLWithMultiplier: function (format, multiplier, quality) { + return this.toDataURL({ + format: format, + multiplier: multiplier, + quality: quality + }); + }, + + /** + * @private + */ + _tempRemoveBordersControlsFromGroup: function(group) { + group.origHasControls = group.hasControls; + group.origBorderColor = group.borderColor; + + group.hasControls = true; + group.borderColor = 'rgba(0,0,0,0)'; + + group.forEachObject(function(o) { + o.origBorderColor = o.borderColor; + o.borderColor = 'rgba(0,0,0,0)'; + }); + }, + + /** + * @private + */ + _restoreBordersControlsOnGroup: function(group) { + group.hideControls = group.origHideControls; + group.borderColor = group.origBorderColor; + + group.forEachObject(function(o) { + o.borderColor = o.origBorderColor; + delete o.origBorderColor; + }); + } +}); + + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Populates canvas with data from the specified dataless JSON. + * JSON format must conform to the one of {@link fabric.Canvas#toDatalessJSON} + * @deprecated since 1.2.2 + * @param {String|Object} json JSON string or object + * @param {Function} callback Callback, invoked when json is parsed + * and corresponding objects (e.g: {@link fabric.Image}) + * are initialized + * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created. + * @return {fabric.Canvas} instance + * @chainable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization} + */ + loadFromDatalessJSON: function (json, callback, reviver) { + return this.loadFromJSON(json, callback, reviver); + }, + + /** + * Populates canvas with data from the specified JSON. + * JSON format must conform to the one of {@link fabric.Canvas#toJSON} + * @param {String|Object} json JSON string or object + * @param {Function} callback Callback, invoked when json is parsed + * and corresponding objects (e.g: {@link fabric.Image}) + * are initialized + * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created. + * @return {fabric.Canvas} instance + * @chainable + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization} + * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo} + * @example + * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas)); + * @example + * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) { + * // `o` = json object + * // `object` = fabric.Object instance + * // ... do some stuff ... + * }); + */ + loadFromJSON: function (json, callback, reviver) { + if (!json) { + return; + } + + // serialize if it wasn't already + var serialized = (typeof json === 'string') + ? JSON.parse(json) + : json; + + this.clear(); + + var _this = this; + this._enlivenObjects(serialized.objects, function () { + _this._setBgOverlay(serialized, callback); + }, reviver); + + return this; + }, + + /** + * @private + * @param {Object} serialized Object with background and overlay information + * @param {Function} callback Invoked after all background and overlay images/patterns loaded + */ + _setBgOverlay: function(serialized, callback) { + var _this = this, + loaded = { + backgroundColor: false, + overlayColor: false, + backgroundImage: false, + overlayImage: false + }; + + if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) { + callback && callback(); + return; + } + + var cbIfLoaded = function () { + if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) { + _this.renderAll(); + callback && callback(); + } + }; + + this.__setBgOverlay('backgroundImage', serialized.backgroundImage, loaded, cbIfLoaded); + this.__setBgOverlay('overlayImage', serialized.overlayImage, loaded, cbIfLoaded); + this.__setBgOverlay('backgroundColor', serialized.background, loaded, cbIfLoaded); + this.__setBgOverlay('overlayColor', serialized.overlay, loaded, cbIfLoaded); + + cbIfLoaded(); + }, + + /** + * @private + * @param {String} property Property to set (backgroundImage, overlayImage, backgroundColor, overlayColor) + * @param {(Object|String)} value Value to set + * @param {Object} loaded Set loaded property to true if property is set + * @param {Object} callback Callback function to invoke after property is set + */ + __setBgOverlay: function(property, value, loaded, callback) { + var _this = this; + + if (!value) { + loaded[property] = true; + return; + } + + if (property === 'backgroundImage' || property === 'overlayImage') { + fabric.Image.fromObject(value, function(img) { + _this[property] = img; + loaded[property] = true; + callback && callback(); + }); + } + else { + this['set' + fabric.util.string.capitalize(property, true)](value, function() { + loaded[property] = true; + callback && callback(); + }); + } + }, + + /** + * @private + * @param {Array} objects + * @param {Function} callback + * @param {Function} [reviver] + */ + _enlivenObjects: function (objects, callback, reviver) { + var _this = this; + + if (!objects || objects.length === 0) { + callback && callback(); + return; + } + + var renderOnAddRemove = this.renderOnAddRemove; + this.renderOnAddRemove = false; + + fabric.util.enlivenObjects(objects, function(enlivenedObjects) { + enlivenedObjects.forEach(function(obj, index) { + _this.insertAt(obj, index, true); + }); + + _this.renderOnAddRemove = renderOnAddRemove; + callback && callback(); + }, null, reviver); + }, + + /** + * @private + * @param {String} format + * @param {Function} callback + */ + _toDataURL: function (format, callback) { + this.clone(function (clone) { + callback(clone.toDataURL(format)); + }); + }, + + /** + * @private + * @param {String} format + * @param {Number} multiplier + * @param {Function} callback + */ + _toDataURLWithMultiplier: function (format, multiplier, callback) { + this.clone(function (clone) { + callback(clone.toDataURLWithMultiplier(format, multiplier)); + }); + }, + + /** + * Clones canvas instance + * @param {Object} [callback] Receives cloned instance as a first argument + * @param {Array} [properties] Array of properties to include in the cloned canvas and children + */ + clone: function (callback, properties) { + var data = JSON.stringify(this.toJSON(properties)); + this.cloneWithoutData(function(clone) { + clone.loadFromJSON(data, function() { + callback && callback(clone); + }); + }); + }, + + /** + * Clones canvas instance without cloning existing data. + * This essentially copies canvas dimensions, clipping properties, etc. + * but leaves data empty (so that you can populate it with your own) + * @param {Object} [callback] Receives cloned instance as a first argument + */ + cloneWithoutData: function(callback) { + var el = fabric.document.createElement('canvas'); + + el.width = this.getWidth(); + el.height = this.getHeight(); + + var clone = new fabric.Canvas(el); + clone.clipTo = this.clipTo; + if (this.backgroundImage) { + clone.setBackgroundImage(this.backgroundImage.src, function() { + clone.renderAll(); + callback && callback(clone); + }); + clone.backgroundImageOpacity = this.backgroundImageOpacity; + clone.backgroundImageStretch = this.backgroundImageStretch; + } + else { + callback && callback(clone); + } + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + toFixed = fabric.util.toFixed, + capitalize = fabric.util.string.capitalize, + degreesToRadians = fabric.util.degreesToRadians, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Object) { + return; + } + + /** + * Root object class from which all 2d shape classes inherit from + * @class fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#objects} + * @see {@link fabric.Object#initialize} for constructor definition + * + * @fires added + * @fires removed + * + * @fires selected + * @fires modified + * @fires rotating + * @fires scaling + * @fires moving + * + * @fires mousedown + * @fires mouseup + */ + fabric.Object = fabric.util.createClass(/** @lends fabric.Object.prototype */ { + + /** + * Retrieves object's {@link fabric.Object#clipTo|clipping function} + * @method getClipTo + * @memberOf fabric.Object.prototype + * @return {Function} + */ + + /** + * Sets object's {@link fabric.Object#clipTo|clipping function} + * @method setClipTo + * @memberOf fabric.Object.prototype + * @param {Function} clipTo Clipping function + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#transformMatrix|transformMatrix} + * @method getTransformMatrix + * @memberOf fabric.Object.prototype + * @return {Array} transformMatrix + */ + + /** + * Sets object's {@link fabric.Object#transformMatrix|transformMatrix} + * @method setTransformMatrix + * @memberOf fabric.Object.prototype + * @param {Array} transformMatrix + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#visible|visible} state + * @method getVisible + * @memberOf fabric.Object.prototype + * @return {Boolean} True if visible + */ + + /** + * Sets object's {@link fabric.Object#visible|visible} state + * @method setVisible + * @memberOf fabric.Object.prototype + * @param {Boolean} value visible value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#shadow|shadow} + * @method getShadow + * @memberOf fabric.Object.prototype + * @return {Object} Shadow instance + */ + + /** + * Retrieves object's {@link fabric.Object#stroke|stroke} + * @method getStroke + * @memberOf fabric.Object.prototype + * @return {String} stroke value + */ + + /** + * Sets object's {@link fabric.Object#stroke|stroke} + * @method setStroke + * @memberOf fabric.Object.prototype + * @param {String} value stroke value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#strokeWidth|strokeWidth} + * @method getStrokeWidth + * @memberOf fabric.Object.prototype + * @return {Number} strokeWidth value + */ + + /** + * Sets object's {@link fabric.Object#strokeWidth|strokeWidth} + * @method setStrokeWidth + * @memberOf fabric.Object.prototype + * @param {Number} value strokeWidth value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#originX|originX} + * @method getOriginX + * @memberOf fabric.Object.prototype + * @return {String} originX value + */ + + /** + * Sets object's {@link fabric.Object#originX|originX} + * @method setOriginX + * @memberOf fabric.Object.prototype + * @param {String} value originX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#originY|originY} + * @method getOriginY + * @memberOf fabric.Object.prototype + * @return {String} originY value + */ + + /** + * Sets object's {@link fabric.Object#originY|originY} + * @method setOriginY + * @memberOf fabric.Object.prototype + * @param {String} value originY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#fill|fill} + * @method getFill + * @memberOf fabric.Object.prototype + * @return {String} Fill value + */ + + /** + * Sets object's {@link fabric.Object#fill|fill} + * @method setFill + * @memberOf fabric.Object.prototype + * @param {String} value Fill value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#opacity|opacity} + * @method getOpacity + * @memberOf fabric.Object.prototype + * @return {Number} Opacity value (0-1) + */ + + /** + * Sets object's {@link fabric.Object#opacity|opacity} + * @method setOpacity + * @memberOf fabric.Object.prototype + * @param {Number} value Opacity value (0-1) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#angle|angle} (in degrees) + * @method getAngle + * @memberOf fabric.Object.prototype + * @return {Number} + */ + + /** + * Sets object's {@link fabric.Object#angle|angle} + * @method setAngle + * @memberOf fabric.Object.prototype + * @param {Number} value Angle value (in degrees) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#top|top position} + * @method getTop + * @memberOf fabric.Object.prototype + * @return {Number} Top value (in pixels) + */ + + /** + * Sets object's {@link fabric.Object#top|top position} + * @method setTop + * @memberOf fabric.Object.prototype + * @param {Number} value Top value (in pixels) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#left|left position} + * @method getLeft + * @memberOf fabric.Object.prototype + * @return {Number} Left value (in pixels) + */ + + /** + * Sets object's {@link fabric.Object#left|left position} + * @method setLeft + * @memberOf fabric.Object.prototype + * @param {Number} value Left value (in pixels) + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#scaleX|scaleX} value + * @method getScaleX + * @memberOf fabric.Object.prototype + * @return {Number} scaleX value + */ + + /** + * Sets object's {@link fabric.Object#scaleX|scaleX} value + * @method setScaleX + * @memberOf fabric.Object.prototype + * @param {Number} value scaleX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#scaleY|scaleY} value + * @method getScaleY + * @memberOf fabric.Object.prototype + * @return {Number} scaleY value + */ + + /** + * Sets object's {@link fabric.Object#scaleY|scaleY} value + * @method setScaleY + * @memberOf fabric.Object.prototype + * @param {Number} value scaleY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#flipX|flipX} value + * @method getFlipX + * @memberOf fabric.Object.prototype + * @return {Boolean} flipX value + */ + + /** + * Sets object's {@link fabric.Object#flipX|flipX} value + * @method setFlipX + * @memberOf fabric.Object.prototype + * @param {Boolean} value flipX value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Retrieves object's {@link fabric.Object#flipY|flipY} value + * @method getFlipY + * @memberOf fabric.Object.prototype + * @return {Boolean} flipY value + */ + + /** + * Sets object's {@link fabric.Object#flipY|flipY} value + * @method setFlipY + * @memberOf fabric.Object.prototype + * @param {Boolean} value flipY value + * @return {fabric.Object} thisArg + * @chainable + */ + + /** + * Type of an object (rect, circle, path, etc.) + * @type String + * @default + */ + type: 'object', + + /** + * Horizontal origin of transformation of an object (one of "left", "right", "center") + * @type String + * @default + */ + originX: 'left', + + /** + * Vertical origin of transformation of an object (one of "top", "bottom", "center") + * @type String + * @default + */ + originY: 'top', + + /** + * Top position of an object. Note that by default it's relative to object center. You can change this by setting originY={top/center/bottom} + * @type Number + * @default + */ + top: 0, + + /** + * Left position of an object. Note that by default it's relative to object center. You can change this by setting originX={left/center/right} + * @type Number + * @default + */ + left: 0, + + /** + * Object width + * @type Number + * @default + */ + width: 0, + + /** + * Object height + * @type Number + * @default + */ + height: 0, + + /** + * Object scale factor (horizontal) + * @type Number + * @default + */ + scaleX: 1, + + /** + * Object scale factor (vertical) + * @type Number + * @default + */ + scaleY: 1, + + /** + * When true, an object is rendered as flipped horizontally + * @type Boolean + * @default + */ + flipX: false, + + /** + * When true, an object is rendered as flipped vertically + * @type Boolean + * @default + */ + flipY: false, + + /** + * Opacity of an object + * @type Number + * @default + */ + opacity: 1, + + /** + * Angle of rotation of an object (in degrees) + * @type Number + * @default + */ + angle: 0, + + /** + * Size of object's controlling corners (in pixels) + * @type Number + * @default + */ + cornerSize: 12, + + /** + * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill) + * @type Boolean + * @default + */ + transparentCorners: true, + + /** + * Default cursor value used when hovering over this object on canvas + * @type String + * @default + */ + hoverCursor: null, + + /** + * Padding between object and its controlling borders (in pixels) + * @type Number + * @default + */ + padding: 0, + + /** + * Color of controlling borders of an object (when it's active) + * @type String + * @default + */ + borderColor: 'rgba(102,153,255,0.75)', + + /** + * Color of controlling corners of an object (when it's active) + * @type String + * @default + */ + cornerColor: 'rgba(102,153,255,0.5)', + + /** + * When true, this object will use center point as the origin of transformation + * when being scaled via the controls. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredScaling: false, + + /** + * When true, this object will use center point as the origin of transformation + * when being rotated via the controls. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredRotation: true, + + /** + * Color of object's fill + * @type String + * @default + */ + fill: 'rgb(0,0,0)', + + /** + * Fill rule used to fill an object + * @type String + * @default + */ + fillRule: 'source-over', + + /** + * Background color of an object. Only works with text objects at the moment. + * @type String + * @default + */ + backgroundColor: '', + + /** + * When defined, an object is rendered via stroke and this property specifies its color + * @type String + * @default + */ + stroke: null, + + /** + * Width of a stroke used to render this object + * @type Number + * @default + */ + strokeWidth: 1, + + /** + * Array specifying dash pattern of an object's stroke (stroke must be defined) + * @type Array + */ + strokeDashArray: null, + + /** + * Line endings style of an object's stroke (one of "butt", "round", "square") + * @type String + * @default + */ + strokeLineCap: 'butt', + + /** + * Corner style of an object's stroke (one of "bevil", "round", "miter") + * @type String + * @default + */ + strokeLineJoin: 'miter', + + /** + * Maximum miter length (used for strokeLineJoin = "miter") of an object's stroke + * @type Number + * @default + */ + strokeMiterLimit: 10, + + /** + * Shadow object representing shadow of this shape + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Opacity of object's controlling borders when object is active and moving + * @type Number + * @default + */ + borderOpacityWhenMoving: 0.4, + + /** + * Scale factor of object's controlling borders + * @type Number + * @default + */ + borderScaleFactor: 1, + + /** + * Transform matrix (similar to SVG's transform matrix) + * @type Array + */ + transformMatrix: null, + + /** + * Minimum allowed scale value of an object + * @type Number + * @default + */ + minScaleLimit: 0.01, + + /** + * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection). + * But events still fire on it. + * @type Boolean + * @default + */ + selectable: true, + + /** + * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4 + * @type Boolean + * @default + */ + evented: true, + + /** + * When set to `false`, an object is not rendered on canvas + * @type Boolean + * @default + */ + visible: true, + + /** + * When set to `false`, object's controls are not displayed and can not be used to manipulate object + * @type Boolean + * @default + */ + hasControls: true, + + /** + * When set to `false`, object's controlling borders are not rendered + * @type Boolean + * @default + */ + hasBorders: true, + + /** + * When set to `false`, object's controlling rotating point will not be visible or selectable + * @type Boolean + * @default + */ + hasRotatingPoint: true, + + /** + * Offset for object's controlling rotating point (when enabled via `hasRotatingPoint`) + * @type Number + * @default + */ + rotatingPointOffset: 40, + + /** + * When set to `true`, objects are "found" on canvas on per-pixel basis rather than according to bounding box + * @type Boolean + * @default + */ + perPixelTargetFind: false, + + /** + * When `false`, default object's values are not included in its serialization + * @type Boolean + * @default + */ + includeDefaultValues: true, + + /** + * Function that determines clipping of an object (context is passed as a first argument) + * Note that context origin is at the object's center point (not left/top corner) + * @type Function + */ + clipTo: null, + + /** + * When `true`, object horizontal movement is locked + * @type Boolean + * @default + */ + lockMovementX: false, + + /** + * When `true`, object vertical movement is locked + * @type Boolean + * @default + */ + lockMovementY: false, + + /** + * When `true`, object rotation is locked + * @type Boolean + * @default + */ + lockRotation: false, + + /** + * When `true`, object horizontal scaling is locked + * @type Boolean + * @default + */ + lockScalingX: false, + + /** + * When `true`, object vertical scaling is locked + * @type Boolean + * @default + */ + lockScalingY: false, + + /** + * When `true`, object non-uniform scaling is locked + * @type Boolean + * @default + */ + lockUniScaling: false, + + /** + * When `true`, object cannot be flipped by scaling into negative values + * @type Boolean + * @default + */ + + lockScalingFlip: false, + /** + * List of properties to consider when checking if state + * of an object is changed (fabric.Object#hasStateChanged) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: ( + 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' + + 'stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit ' + + 'angle opacity fill fillRule shadow clipTo visible backgroundColor' + ).split(' '), + + /** + * Constructor + * @param {Object} [options] Options object + */ + initialize: function(options) { + if (options) { + this.setOptions(options); + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initGradient: function(options) { + if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) { + this.set('fill', new fabric.Gradient(options.fill)); + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initPattern: function(options) { + if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) { + this.set('fill', new fabric.Pattern(options.fill)); + } + if (options.stroke && options.stroke.source && !(options.stroke instanceof fabric.Pattern)) { + this.set('stroke', new fabric.Pattern(options.stroke)); + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initClipping: function(options) { + if (!options.clipTo || typeof options.clipTo !== 'string') { + return; + } + + var functionBody = fabric.util.getFunctionBody(options.clipTo); + if (typeof functionBody !== 'undefined') { + this.clipTo = new Function('ctx', functionBody); + } + }, + + /** + * Sets object's properties from options + * @param {Object} [options] Options object + */ + setOptions: function(options) { + for (var prop in options) { + this.set(prop, options[prop]); + } + this._initGradient(options); + this._initPattern(options); + this._initClipping(options); + }, + + /** + * Transforms context when rendering an object + * @param {CanvasRenderingContext2D} ctx Context + * @param {Boolean} fromLeft When true, context is transformed to object's top/left corner. This is used when rendering text on Node + */ + transform: function(ctx, fromLeft) { + if (this.group) { + this.group.transform(ctx, fromLeft); + } + ctx.globalAlpha = this.opacity; + + var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint(); + ctx.translate(center.x, center.y); + ctx.rotate(degreesToRadians(this.angle)); + ctx.scale( + this.scaleX * (this.flipX ? -1 : 1), + this.scaleY * (this.flipY ? -1 : 1) + ); + }, + + /** + * Returns an object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, + + object = { + type: this.type, + originX: this.originX, + originY: this.originY, + left: toFixed(this.left, NUM_FRACTION_DIGITS), + top: toFixed(this.top, NUM_FRACTION_DIGITS), + width: toFixed(this.width, NUM_FRACTION_DIGITS), + height: toFixed(this.height, NUM_FRACTION_DIGITS), + fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill, + stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke, + strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS), + strokeDashArray: this.strokeDashArray, + strokeLineCap: this.strokeLineCap, + strokeLineJoin: this.strokeLineJoin, + strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS), + scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS), + scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS), + angle: toFixed(this.getAngle(), NUM_FRACTION_DIGITS), + flipX: this.flipX, + flipY: this.flipY, + opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS), + shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow, + visible: this.visible, + clipTo: this.clipTo && String(this.clipTo), + backgroundColor: this.backgroundColor + }; + + if (!this.includeDefaultValues) { + object = this._removeDefaultValues(object); + } + + fabric.util.populateWithProperties(this, object, propertiesToInclude); + + return object; + }, + + /** + * Returns (dataless) object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + // will be overwritten by subclasses + return this.toObject(propertiesToInclude); + }, + + /** + * @private + * @param {Object} object + */ + _removeDefaultValues: function(object) { + var prototype = fabric.util.getKlass(object.type).prototype, + stateProperties = prototype.stateProperties; + + stateProperties.forEach(function(prop) { + if (object[prop] === prototype[prop]) { + delete object[prop]; + } + }); + + return object; + }, + + /** + * Returns a string representation of an instance + * @return {String} + */ + toString: function() { + return '#'; + }, + + /** + * Basic getter + * @param {String} property Property name + * @return {Any} value of a property + */ + get: function(property) { + return this[property]; + }, + + /** + * @private + */ + _setObject: function(obj) { + for (var prop in obj) { + this._set(prop, obj[prop]); + } + }, + + /** + * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`. + * @param {String|Object} key Property name or object (if object, iterate over the object properties) + * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one) + * @return {fabric.Object} thisArg + * @chainable + */ + set: function(key, value) { + if (typeof key === 'object') { + this._setObject(key); + } + else { + if (typeof value === 'function' && key !== 'clipTo') { + this._set(key, value(this.get(key))); + } + else { + this._set(key, value); + } + } + return this; + }, + + /** + * @private + * @param {String} key + * @param {Any} value + * @return {fabric.Object} thisArg + */ + _set: function(key, value) { + var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY'); + + if (shouldConstrainValue) { + value = this._constrainScale(value); + } + if (key === 'scaleX' && value < 0) { + this.flipX = !this.flipX; + value *= -1; + } + else if (key === 'scaleY' && value < 0) { + this.flipY = !this.flipY; + value *= -1; + } + else if (key === 'width' || key === 'height') { + this.minScaleLimit = toFixed(Math.min(0.1, 1/Math.max(this.width, this.height)), 2); + } + else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) { + value = new fabric.Shadow(value); + } + + this[key] = value; + + return this; + }, + + /** + * Toggles specified property from `true` to `false` or from `false` to `true` + * @param {String} property Property to toggle + * @return {fabric.Object} thisArg + * @chainable + */ + toggle: function(property) { + var value = this.get(property); + if (typeof value === 'boolean') { + this.set(property, !value); + } + return this; + }, + + /** + * Sets sourcePath of an object + * @param {String} value Value to set sourcePath to + * @return {fabric.Object} thisArg + * @chainable + */ + setSourcePath: function(value) { + this.sourcePath = value; + return this; + }, + + /** + * Retrieves viewportTransform from Object's canvas if possible + * @method getViewportTransform + * @memberOf fabric.Object.prototype + * @return {Boolean} flipY value // TODO + */ + getViewportTransform: function() { + if (this.canvas && this.canvas.viewportTransform) { + return this.canvas.viewportTransform; + } + return [1, 0, 0, 1, 0, 0]; + }, + + /** + * Renders an object on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if width/height are zeros or object is not visible + if (this.width === 0 || this.height === 0 || !this.visible) { + return; + } + + ctx.save(); + + //setup fill rule for current object + this._setupFillRule(ctx); + + this._transform(ctx, noTransform); + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); + + if (this.group && this.group.type === 'path-group') { + ctx.translate(-this.group.width/2, -this.group.height/2); + var m = this.transformMatrix; + if (m) { + ctx.transform.apply(ctx, m); + } + } + ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + this._render(ctx, noTransform); + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + this._restoreFillRule(ctx); + + ctx.restore(); + }, + + _transform: function(ctx, noTransform) { + var m = this.transformMatrix; + + if (m && !this.group) { + ctx.setTransform.apply(ctx, m); + } + if (!noTransform) { + this.transform(ctx); + } + }, + + _setStrokeStyles: function(ctx) { + if (this.stroke) { + ctx.lineWidth = this.strokeWidth; + ctx.lineCap = this.strokeLineCap; + ctx.lineJoin = this.strokeLineJoin; + ctx.miterLimit = this.strokeMiterLimit; + ctx.strokeStyle = this.stroke.toLive + ? this.stroke.toLive(ctx) + : this.stroke; + } + }, + + _setFillStyles: function(ctx) { + if (this.fill) { + ctx.fillStyle = this.fill.toLive + ? this.fill.toLive(ctx) + : this.fill; + } + }, + + /** + * Renders controls and borders for the object + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + _renderControls: function(ctx, noTransform) { + var vpt = this.getViewportTransform(); + + ctx.save(); + if (this.active && !noTransform) { + var center; + if (this.group) { + center = fabric.util.transformPoint(this.group.getCenterPoint(), vpt); + ctx.translate(center.x, center.y); + ctx.rotate(degreesToRadians(this.group.angle)); + } + center = fabric.util.transformPoint(this.getCenterPoint(), vpt, null != this.group); + if (this.group) { + center.x *= this.group.scaleX; + center.y *= this.group.scaleY; + } + ctx.translate(center.x, center.y); + ctx.rotate(degreesToRadians(this.angle)); + this.drawBorders(ctx); + this.drawControls(ctx); + } + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _setShadow: function(ctx) { + if (!this.shadow) { + return; + } + + ctx.shadowColor = this.shadow.color; + ctx.shadowBlur = this.shadow.blur; + ctx.shadowOffsetX = this.shadow.offsetX; + ctx.shadowOffsetY = this.shadow.offsetY; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _removeShadow: function(ctx) { + if (!this.shadow) { + return; + } + + ctx.shadowColor = ''; + ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderFill: function(ctx) { + if (!this.fill) { + return; + } + + ctx.save(); + if (this.fill.toLive) { + ctx.translate( + -this.width / 2 + this.fill.offsetX || 0, + -this.height / 2 + this.fill.offsetY || 0); + } + if (this.fill.gradientTransform) { + var g = this.fill.gradientTransform; + ctx.transform.apply(ctx, g); + } + if (this.fillRule === 'destination-over') { + ctx.fill('evenodd'); + } + else { + ctx.fill(); + } + ctx.restore(); + if (this.shadow && !this.shadow.affectStroke) { + this._removeShadow(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderStroke: function(ctx) { + if (!this.stroke || this.strokeWidth === 0) { + return; + } + + ctx.save(); + if (this.strokeDashArray) { + // Spec requires the concatenation of two copies the dash list when the number of elements is odd + if (1 & this.strokeDashArray.length) { + this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); + } + + if (supportsLineDash) { + ctx.setLineDash(this.strokeDashArray); + this._stroke && this._stroke(ctx); + } + else { + this._renderDashedStroke && this._renderDashedStroke(ctx); + } + ctx.stroke(); + } + else { + if (this.stroke.gradientTransform) { + var g = this.stroke.gradientTransform; + ctx.transform.apply(ctx, g); + } + this._stroke ? this._stroke(ctx) : ctx.stroke(); + } + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * Clones an instance + * @param {Function} callback Callback is invoked with a clone as a first argument + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {fabric.Object} clone of an instance + */ + clone: function(callback, propertiesToInclude) { + if (this.constructor.fromObject) { + return this.constructor.fromObject(this.toObject(propertiesToInclude), callback); + } + return new fabric.Object(this.toObject(propertiesToInclude)); + }, + + /** + * Creates an instance of fabric.Image out of an object + * @param {Function} callback callback, invoked with an instance as a first argument + * @return {fabric.Object} thisArg + */ + cloneAsImage: function(callback) { + var dataUrl = this.toDataURL(); + fabric.util.loadImage(dataUrl, function(img) { + if (callback) { + callback(new fabric.Image(img)); + } + }); + return this; + }, + + /** + * Converts an object into a data-url-like string + * @param {Object} options Options object + * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png" + * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg. + * @param {Number} [options.multiplier=1] Multiplier to scale by + * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14 + * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14 + * @param {Number} [options.width] Cropping width. Introduced in v1.2.14 + * @param {Number} [options.height] Cropping height. Introduced in v1.2.14 + * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format + */ + toDataURL: function(options) { + options || (options = { }); + + var el = fabric.util.createCanvasElement(), + boundingRect = this.getBoundingRect(); + + el.width = boundingRect.width; + el.height = boundingRect.height; + + fabric.util.wrapElement(el, 'div'); + var canvas = new fabric.Canvas(el); + + // to avoid common confusion https://github.com/kangax/fabric.js/issues/806 + if (options.format === 'jpg') { + options.format = 'jpeg'; + } + + if (options.format === 'jpeg') { + canvas.backgroundColor = '#fff'; + } + + var origParams = { + active: this.get('active'), + left: this.getLeft(), + top: this.getTop() + }; + + this.set('active', false); + this.setPositionByOrigin(new fabric.Point(el.width / 2, el.height / 2), 'center', 'center'); + + var originalCanvas = this.canvas; + canvas.add(this); + var data = canvas.toDataURL(options); + + this.set(origParams).setCoords(); + this.canvas = originalCanvas; + + canvas.dispose(); + canvas = null; + + return data; + }, + + /** + * Returns true if specified type is identical to the type of an instance + * @param {String} type Type to check against + * @return {Boolean} + */ + isType: function(type) { + return this.type === type; + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 0; + }, + + /** + * Returns a JSON representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} JSON + */ + toJSON: function(propertiesToInclude) { + // delegate, not alias + return this.toObject(propertiesToInclude); + }, + + /** + * Sets gradient (fill or stroke) of an object + * Backwards incompatibility note: This method was named "setGradientFill" until v1.1.0 + * @param {String} property Property name 'stroke' or 'fill' + * @param {Object} [options] Options object + * @param {String} [options.type] Type of gradient 'radial' or 'linear' + * @param {Number} [options.x1=0] x-coordinate of start point + * @param {Number} [options.y1=0] y-coordinate of start point + * @param {Number} [options.x2=0] x-coordinate of end point + * @param {Number} [options.y2=0] y-coordinate of end point + * @param {Number} [options.r1=0] Radius of start point (only for radial gradients) + * @param {Number} [options.r2=0] Radius of end point (only for radial gradients) + * @param {Object} [options.colorStops] Color stops object eg. {0: 'ff0000', 1: '000000'} + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/58y8b/|jsFiddle demo} + * @example + * object.setGradient('fill', { + * type: 'linear', + * x1: -object.width / 2, + * y1: 0, + * x2: object.width / 2, + * y2: 0, + * colorStops: { + * 0: 'red', + * 0.5: '#005555', + * 1: 'rgba(0,0,255,0.5)' + * } + * }); + * canvas.renderAll(); + * @example + * object.setGradient('fill', { + * type: 'radial', + * x1: 0, + * y1: 0, + * x2: 0, + * y2: 0, + * r1: object.width / 2, + * r2: 10, + * colorStops: { + * 0: 'red', + * 0.5: '#005555', + * 1: 'rgba(0,0,255,0.5)' + * } + * }); + * canvas.renderAll(); + */ + setGradient: function(property, options) { + options || (options = { }); + + var gradient = { colorStops: [] }; + + gradient.type = options.type || (options.r1 || options.r2 ? 'radial' : 'linear'); + gradient.coords = { + x1: options.x1, + y1: options.y1, + x2: options.x2, + y2: options.y2 + }; + + if (options.r1 || options.r2) { + gradient.coords.r1 = options.r1; + gradient.coords.r2 = options.r2; + } + + for (var position in options.colorStops) { + var color = new fabric.Color(options.colorStops[position]); + gradient.colorStops.push({ + offset: position, + color: color.toRgb(), + opacity: color.getAlpha() + }); + } + + return this.set(property, fabric.Gradient.forObject(this, gradient)); + }, + + /** + * Sets pattern fill of an object + * @param {Object} options Options object + * @param {(String|HTMLImageElement)} options.source Pattern source + * @param {String} [options.repeat=repeat] Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat) + * @param {Number} [options.offsetX=0] Pattern horizontal offset from object's left/top corner + * @param {Number} [options.offsetY=0] Pattern vertical offset from object's left/top corner + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/QT3pa/|jsFiddle demo} + * @example + * fabric.util.loadImage('http://fabricjs.com/assets/escheresque_ste.png', function(img) { + * object.setPatternFill({ + * source: img, + * repeat: 'repeat' + * }); + * canvas.renderAll(); + * }); + */ + setPatternFill: function(options) { + return this.set('fill', new fabric.Pattern(options)); + }, + + /** + * Sets {@link fabric.Object#shadow|shadow} of an object + * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") + * @param {String} [options.color=rgb(0,0,0)] Shadow color + * @param {Number} [options.blur=0] Shadow blur + * @param {Number} [options.offsetX=0] Shadow horizontal offset + * @param {Number} [options.offsetY=0] Shadow vertical offset + * @return {fabric.Object} thisArg + * @chainable + * @see {@link http://jsfiddle.net/fabricjs/7gvJG/|jsFiddle demo} + * @example + * object.setShadow('2px 2px 10px rgba(0,0,0,0.2)'); + * canvas.renderAll(); + * @example + * object.setShadow({ + * color: 'red', + * blur: 10, + * offsetX: 20, + * offsetY: 20 + * }); + * canvas.renderAll(); + */ + setShadow: function(options) { + return this.set('shadow', options ? new fabric.Shadow(options) : null); + }, + + /** + * Sets "color" of an instance (alias of `set('fill', …)`) + * @param {String} color Color value + * @return {fabric.Object} thisArg + * @chainable + */ + setColor: function(color) { + this.set('fill', color); + return this; + }, + + /** + * Sets "angle" of an instance + * @param {Number} angle Angle value + * @return {fabric.Object} thisArg + * @chainable + */ + setAngle: function(angle) { + var shouldCenterOrigin = (this.originX !== 'center' || this.originY !== 'center') && this.centeredRotation; + + if (shouldCenterOrigin) { + this._setOriginToCenter(); + } + + this.set('angle', angle); + + if (shouldCenterOrigin) { + this._resetOrigin(); + } + + return this; + }, + + /** + * Centers object horizontally on canvas to which it was added last. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + centerH: function () { + this.canvas.centerObjectH(this); + return this; + }, + + /** + * Centers object vertically on canvas to which it was added last. + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + centerV: function () { + this.canvas.centerObjectV(this); + return this; + }, + + /** + * Centers object vertically and horizontally on canvas to which is was added last + * You might need to call `setCoords` on an object after centering, to update controls area. + * @return {fabric.Object} thisArg + * @chainable + */ + center: function () { + this.canvas.centerObject(this); + return this; + }, + + /** + * Removes object from canvas to which it was added last + * @return {fabric.Object} thisArg + * @chainable + */ + remove: function() { + this.canvas.remove(this); + return this; + }, + + /** + * Returns coordinates of a pointer relative to an object + * @param {Event} e Event to operate upon + * @param {Object} [pointer] Pointer to operate upon (instead of event) + * @return {Object} Coordinates of a pointer (x, y) + */ + getLocalPointer: function(e, pointer) { + pointer = pointer || this.canvas.getPointer(e); + var objectLeftTop = this.translateToOriginPoint(this.getCenterPoint(), 'left', 'top'); + return { + x: pointer.x - objectLeftTop.x, + y: pointer.y - objectLeftTop.y + }; + }, + + /** + * Sets canvas globalCompositeOperation for specific object + * custom composition operation for the particular object can be specifed using fillRule property + * @param {CanvasRenderingContext2D} ctx Rendering canvas context + */ + _setupFillRule: function (ctx) { + if (this.fillRule) { + this._prevFillRule = ctx.globalCompositeOperation; + ctx.globalCompositeOperation = this.fillRule; + } + }, + + /** + * Restores previously saved canvas globalCompositeOperation after obeject rendering + * @param {CanvasRenderingContext2D} ctx Rendering canvas context + */ + _restoreFillRule: function (ctx) { + if (this.fillRule && this._prevFillRule) { + ctx.globalCompositeOperation = this._prevFillRule; + } + } + }); + + fabric.util.createAccessors(fabric.Object); + + /** + * Alias for {@link fabric.Object.prototype.setAngle} + * @alias rotate -> setAngle + * @memberof fabric.Object + */ + fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle; + + extend(fabric.Object.prototype, fabric.Observable); + + /** + * Defines the number of fraction digits to use when serializing object values. + * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc. + * @static + * @memberof fabric.Object + * @constant + * @type Number + */ + fabric.Object.NUM_FRACTION_DIGITS = 2; + + /** + * Unique id used internally when creating SVG elements + * @static + * @memberof fabric.Object + * @type Number + */ + fabric.Object.__uid = 0; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + var degreesToRadians = fabric.util.degreesToRadians; + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Translates the coordinates from origin to center coordinates (based on the object's dimensions) + * @param {fabric.Point} point The point which corresponds to the originX and originY params + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + translateToCenterPoint: function(point, originX, originY) { + var cx = point.x, + cy = point.y, + strokeWidth = this.stroke ? this.strokeWidth : 0; + + if (originX === 'left') { + cx = point.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === 'right') { + cx = point.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + + if (originY === 'top') { + cy = point.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === 'bottom') { + cy = point.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + + // Apply the reverse rotation to the point (it's already scaled properly) + return fabric.util.rotatePoint(new fabric.Point(cx, cy), point, degreesToRadians(this.angle)); + }, + + /** + * Translates the coordinates from center to origin coordinates (based on the object's dimensions) + * @param {fabric.Point} center The point which corresponds to center of the object + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + translateToOriginPoint: function(center, originX, originY) { + var x = center.x, + y = center.y, + strokeWidth = this.stroke ? this.strokeWidth : 0; + + // Get the point coordinates + if (originX === 'left') { + x = center.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === 'right') { + x = center.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + if (originY === 'top') { + y = center.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === 'bottom') { + y = center.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + + // Apply the rotation to the point (it's already scaled properly) + return fabric.util.rotatePoint(new fabric.Point(x, y), center, degreesToRadians(this.angle)); + }, + + /** + * Returns the real center coordinates of the object + * @return {fabric.Point} + */ + getCenterPoint: function() { + var leftTop = new fabric.Point(this.left, this.top); + return this.translateToCenterPoint(leftTop, this.originX, this.originY); + }, + + /** + * Returns the coordinates of the object based on center coordinates + * @param {fabric.Point} point The point which corresponds to the originX and originY params + * @return {fabric.Point} + */ + // getOriginPoint: function(center) { + // return this.translateToOriginPoint(center, this.originX, this.originY); + // }, + + /** + * Returns the coordinates of the object as if it has a different origin + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + getPointByOrigin: function(originX, originY) { + var center = this.getCenterPoint(); + return this.translateToOriginPoint(center, originX, originY); + }, + + /** + * Returns the point in local coordinates + * @param {fabric.Point} point The point relative to the global coordinate system + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {fabric.Point} + */ + toLocalPoint: function(point, originX, originY) { + var center = this.getCenterPoint(), + strokeWidth = this.stroke ? this.strokeWidth : 0, + x, y; + + if (originX && originY) { + if (originX === 'left') { + x = center.x - (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else if (originX === 'right') { + x = center.x + (this.getWidth() + strokeWidth * this.scaleX) / 2; + } + else { + x = center.x; + } + + if (originY === 'top') { + y = center.y - (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else if (originY === 'bottom') { + y = center.y + (this.getHeight() + strokeWidth * this.scaleY) / 2; + } + else { + y = center.y; + } + } + else { + x = this.left; + y = this.top; + } + + return fabric.util.rotatePoint(new fabric.Point(point.x, point.y), center, -degreesToRadians(this.angle)) + .subtractEquals(new fabric.Point(x, y)); + }, + + /** + * Returns the point in global coordinates + * @param {fabric.Point} The point relative to the local coordinate system + * @return {fabric.Point} + */ + // toGlobalPoint: function(point) { + // return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top)); + // }, + + /** + * Sets the position of the object taking into consideration the object's origin + * @param {fabric.Point} pos The new position of the object + * @param {String} originX Horizontal origin: 'left', 'center' or 'right' + * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' + * @return {void} + */ + setPositionByOrigin: function(pos, originX, originY) { + var center = this.translateToCenterPoint(pos, originX, originY), + position = this.translateToOriginPoint(center, this.originX, this.originY); + + this.set('left', position.x); + this.set('top', position.y); + }, + + /** + * @param {String} to One of 'left', 'center', 'right' + */ + adjustPosition: function(to) { + var angle = degreesToRadians(this.angle), + hypotHalf = this.getWidth() / 2, + xHalf = Math.cos(angle) * hypotHalf, + yHalf = Math.sin(angle) * hypotHalf, + hypotFull = this.getWidth(), + xFull = Math.cos(angle) * hypotFull, + yFull = Math.sin(angle) * hypotFull; + + if (this.originX === 'center' && to === 'left' || + this.originX === 'right' && to === 'center') { + // move half left + this.left -= xHalf; + this.top -= yHalf; + } + else if (this.originX === 'left' && to === 'center' || + this.originX === 'center' && to === 'right') { + // move half right + this.left += xHalf; + this.top += yHalf; + } + else if (this.originX === 'left' && to === 'right') { + // move full right + this.left += xFull; + this.top += yFull; + } + else if (this.originX === 'right' && to === 'left') { + // move full left + this.left -= xFull; + this.top -= yFull; + } + + this.setCoords(); + this.originX = to; + }, + + /** + * Sets the origin/position of the object to it's center point + * @private + * @return {void} + */ + _setOriginToCenter: function() { + this._originalOriginX = this.originX; + this._originalOriginY = this.originY; + + var center = this.getCenterPoint(); + + this.originX = 'center'; + this.originY = 'center'; + + this.left = center.x; + this.top = center.y; + }, + + /** + * Resets the origin/position of the object to it's original origin + * @private + * @return {void} + */ + _resetOrigin: function() { + var originPoint = this.translateToOriginPoint( + this.getCenterPoint(), + this._originalOriginX, + this._originalOriginY); + + this.originX = this._originalOriginX; + this.originY = this._originalOriginY; + + this.left = originPoint.x; + this.top = originPoint.y; + + this._originalOriginX = null; + this._originalOriginY = null; + }, + + /** + * @private + */ + _getLeftTopCoords: function() { + return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'center'); + } + }); + +})(); + + +(function() { + + var degreesToRadians = fabric.util.degreesToRadians; + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Object containing coordinates of object's controls + * @type Object + * @default + */ + oCoords: null, + + /** + * Checks if object intersects with an area formed by 2 points + * @param {Object} pointTL top-left point of area + * @param {Object} pointBR bottom-right point of area + * @return {Boolean} true if object intersects with an area formed by 2 points + */ + intersectsWithRect: function(pointTL, pointBR) { + var oCoords = this.oCoords, + tl = new fabric.Point(oCoords.tl.x, oCoords.tl.y), + tr = new fabric.Point(oCoords.tr.x, oCoords.tr.y), + bl = new fabric.Point(oCoords.bl.x, oCoords.bl.y), + br = new fabric.Point(oCoords.br.x, oCoords.br.y), + intersection = fabric.Intersection.intersectPolygonRectangle( + [tl, tr, br, bl], + pointTL, + pointBR + ); + return intersection.status === 'Intersection'; + }, + + /** + * Checks if object intersects with another object + * @param {Object} other Object to test + * @return {Boolean} true if object intersects with another object + */ + intersectsWithObject: function(other) { + // extracts coords + function getCoords(oCoords) { + return { + tl: new fabric.Point(oCoords.tl.x, oCoords.tl.y), + tr: new fabric.Point(oCoords.tr.x, oCoords.tr.y), + bl: new fabric.Point(oCoords.bl.x, oCoords.bl.y), + br: new fabric.Point(oCoords.br.x, oCoords.br.y) + }; + } + var thisCoords = getCoords(this.oCoords), + otherCoords = getCoords(other.oCoords), + intersection = fabric.Intersection.intersectPolygonPolygon( + [thisCoords.tl, thisCoords.tr, thisCoords.br, thisCoords.bl], + [otherCoords.tl, otherCoords.tr, otherCoords.br, otherCoords.bl] + ); + + return intersection.status === 'Intersection'; + }, + + /** + * Checks if object is fully contained within area of another object + * @param {Object} other Object to test + * @return {Boolean} true if object is fully contained within area of another object + */ + isContainedWithinObject: function(other) { + var boundingRect = other.getBoundingRect(), + point1 = new fabric.Point(boundingRect.left, boundingRect.top), + point2 = new fabric.Point(boundingRect.left + boundingRect.width, boundingRect.top + boundingRect.height); + + return this.isContainedWithinRect(point1, point2); + }, + + /** + * Checks if object is fully contained within area formed by 2 points + * @param {Object} pointTL top-left point of area + * @param {Object} pointBR bottom-right point of area + * @return {Boolean} true if object is fully contained within area formed by 2 points + */ + isContainedWithinRect: function(pointTL, pointBR) { + var boundingRect = this.getBoundingRect(); + + return ( + boundingRect.left >= pointTL.x && + boundingRect.left + boundingRect.width <= pointBR.x && + boundingRect.top >= pointTL.y && + boundingRect.top + boundingRect.height <= pointBR.y + ); + }, + + /** + * Checks if point is inside the object + * @param {fabric.Point} point Point to check against + * @return {Boolean} true if point is inside the object + */ + containsPoint: function(point) { + var lines = this._getImageLines(this.oCoords), + xPoints = this._findCrossPoints(point, lines); + + // if xPoints is odd then point is inside the object + return (xPoints !== 0 && xPoints % 2 === 1); + }, + + /** + * Method that returns an object with the object edges in it, given the coordinates of the corners + * @private + * @param {Object} oCoords Coordinates of the object corners + */ + _getImageLines: function(oCoords) { + return { + topline: { + o: oCoords.tl, + d: oCoords.tr + }, + rightline: { + o: oCoords.tr, + d: oCoords.br + }, + bottomline: { + o: oCoords.br, + d: oCoords.bl + }, + leftline: { + o: oCoords.bl, + d: oCoords.tl + } + }; + }, + + /** + * Helper method to determine how many cross points are between the 4 object edges + * and the horizontal line determined by a point on canvas + * @private + * @param {fabric.Point} point Point to check + * @param {Object} oCoords Coordinates of the object being evaluated + */ + _findCrossPoints: function(point, oCoords) { + var b1, b2, a1, a2, xi, yi, + xcount = 0, + iLine; + + for (var lineKey in oCoords) { + iLine = oCoords[lineKey]; + // optimisation 1: line below point. no cross + if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) { + continue; + } + // optimisation 2: line above point. no cross + if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) { + continue; + } + // optimisation 3: vertical line case + if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) { + xi = iLine.o.x; + yi = point.y; + } + // calculate the intersection point + else { + b1 = 0; + b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x); + a1 = point.y - b1 * point.x; + a2 = iLine.o.y - b2 * iLine.o.x; + + xi = - (a1 - a2) / (b1 - b2); + yi = a1 + b1 * xi; + } + // dont count xi < point.x cases + if (xi >= point.x) { + xcount += 1; + } + // optimisation 4: specific for square images + if (xcount === 2) { + break; + } + } + return xcount; + }, + + /** + * Returns width of an object's bounding rectangle + * @deprecated since 1.0.4 + * @return {Number} width value + */ + getBoundingRectWidth: function() { + return this.getBoundingRect().width; + }, + + /** + * Returns height of an object's bounding rectangle + * @deprecated since 1.0.4 + * @return {Number} height value + */ + getBoundingRectHeight: function() { + return this.getBoundingRect().height; + }, + + /** + * Returns coordinates of object's bounding rectangle (left, top, width, height) + * @return {Object} Object with left, top, width, height properties + */ + getBoundingRect: function() { + this.oCoords || this.setCoords(); + + var xCoords = [this.oCoords.tl.x, this.oCoords.tr.x, this.oCoords.br.x, this.oCoords.bl.x], + minX = fabric.util.array.min(xCoords), + maxX = fabric.util.array.max(xCoords), + width = Math.abs(minX - maxX), + + yCoords = [this.oCoords.tl.y, this.oCoords.tr.y, this.oCoords.br.y, this.oCoords.bl.y], + minY = fabric.util.array.min(yCoords), + maxY = fabric.util.array.max(yCoords), + height = Math.abs(minY - maxY); + + return { + left: minX, + top: minY, + width: width, + height: height + }; + }, + + /** + * Returns width of an object + * @return {Number} width value + */ + getWidth: function() { + return this.width * this.scaleX; + }, + + /** + * Returns height of an object + * @return {Number} height value + */ + getHeight: function() { + return this.height * this.scaleY; + }, + + /** + * Makes sure the scale is valid and modifies it if necessary + * @private + * @param {Number} value + * @return {Number} + */ + _constrainScale: function(value) { + if (Math.abs(value) < this.minScaleLimit) { + if (value < 0) { + return -this.minScaleLimit; + } + else { + return this.minScaleLimit; + } + } + return value; + }, + + /** + * Scales an object (equally by x and y) + * @param {Number} value Scale factor + * @return {fabric.Object} thisArg + * @chainable + */ + scale: function(value) { + value = this._constrainScale(value); + + if (value < 0) { + this.flipX = !this.flipX; + this.flipY = !this.flipY; + value *= -1; + } + + this.scaleX = value; + this.scaleY = value; + this.setCoords(); + return this; + }, + + /** + * Scales an object to a given width, with respect to bounding box (scaling by x/y equally) + * @param {Number} value New width value + * @return {fabric.Object} thisArg + * @chainable + */ + scaleToWidth: function(value) { + // adjust to bounding rect factor so that rotated shapes would fit as well + var boundingRectFactor = this.getBoundingRectWidth() / this.getWidth(); + return this.scale(value / this.width / boundingRectFactor); + }, + + /** + * Scales an object to a given height, with respect to bounding box (scaling by x/y equally) + * @param {Number} value New height value + * @return {fabric.Object} thisArg + * @chainable + */ + scaleToHeight: function(value) { + // adjust to bounding rect factor so that rotated shapes would fit as well + var boundingRectFactor = this.getBoundingRectHeight() / this.getHeight(); + return this.scale(value / this.height / boundingRectFactor); + }, + + /** + * Sets corner position coordinates based on current angle, width and height + * @return {fabric.Object} thisArg + * @chainable + */ + setCoords: function() { + var strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, + theta = degreesToRadians(this.angle), + vpt = this.getViewportTransform(), + f = function (p) { + return fabric.util.transformPoint(p, vpt); + }, + w = this.width, + h = this.height, + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + + if (vLine) { + w = strokeWidth; + } + else if (hLine) { + h = strokeWidth; + } + if (strokeW) { + w += strokeWidth; + } + if (strokeH) { + h += strokeWidth; + } + this.currentWidth = w * this.scaleX; + this.currentHeight = h * this.scaleY; + + // If width is negative, make postive. Fixes path selection issue + if (this.currentWidth < 0) { + this.currentWidth = Math.abs(this.currentWidth); + } + + var _hypotenuse = Math.sqrt( + Math.pow(this.currentWidth / 2, 2) + + Math.pow(this.currentHeight / 2, 2)), + + _angle = Math.atan(isFinite(this.currentHeight / this.currentWidth) ? this.currentHeight / this.currentWidth : 0), + + // offset added for rotate and scale actions + offsetX = Math.cos(_angle + theta) * _hypotenuse, + offsetY = Math.sin(_angle + theta) * _hypotenuse, + sinTh = Math.sin(theta), + cosTh = Math.cos(theta), + coords = this.getCenterPoint(), + wh = new fabric.Point(this.currentWidth, this.currentHeight), + _tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY), + _tr = new fabric.Point(_tl.x + (wh.x * cosTh), _tl.y + (wh.x * sinTh)), + _bl = new fabric.Point(_tl.x - (wh.y * sinTh), _tl.y + (wh.y * cosTh)), + _mt = new fabric.Point(_tl.x + (wh.x/2 * cosTh), _tl.y + (wh.x/2 * sinTh)), + tl = f(_tl), + tr = f(_tr), + br = f(new fabric.Point(_tr.x - (wh.y * sinTh), _tr.y + (wh.y * cosTh))), + bl = f(_bl), + ml = f(new fabric.Point(_tl.x - (wh.y/2 * sinTh), _tl.y + (wh.y/2 * cosTh))), + mt = f(_mt), + mr = f(new fabric.Point(_tr.x - (wh.y/2 * sinTh), _tr.y + (wh.y/2 * cosTh))), + mb = f(new fabric.Point(_bl.x + (wh.x/2 * cosTh), _bl.y + (wh.x/2 * sinTh))), + mtr = f(new fabric.Point(_mt.x, _mt.y)), + + // padding + padX = Math.cos(_angle + theta) * this.padding * Math.sqrt(2), + padY = Math.sin(_angle + theta) * this.padding * Math.sqrt(2); + + tl = tl.add(new fabric.Point(-padX, -padY)); + tr = tr.add(new fabric.Point(padY, -padX)); + br = br.add(new fabric.Point(padX, padY)); + bl = bl.add(new fabric.Point(-padY, padX)); + ml = ml.add(new fabric.Point((-padX - padY) / 2, (-padY + padX) / 2)); + mt = mt.add(new fabric.Point((padY - padX) / 2, -(padY + padX) / 2)); + mr = mr.add(new fabric.Point((padY + padX) / 2, (padY - padX) / 2)); + mb = mb.add(new fabric.Point((padX - padY) / 2, (padX + padY) / 2)); + mtr = mtr.add(new fabric.Point((padY - padX) / 2, -(padY + padX) / 2)); + + // debugging + + // setTimeout(function() { + // canvas.contextTop.fillStyle = 'green'; + // canvas.contextTop.fillRect(mb.x, mb.y, 3, 3); + // canvas.contextTop.fillRect(bl.x, bl.y, 3, 3); + // canvas.contextTop.fillRect(br.x, br.y, 3, 3); + // canvas.contextTop.fillRect(tl.x, tl.y, 3, 3); + // canvas.contextTop.fillRect(tr.x, tr.y, 3, 3); + // canvas.contextTop.fillRect(ml.x, ml.y, 3, 3); + // canvas.contextTop.fillRect(mr.x, mr.y, 3, 3); + // canvas.contextTop.fillRect(mt.x, mt.y, 3, 3); + // }, 50); + + this.oCoords = { + // corners + tl: tl, tr: tr, br: br, bl: bl, + // middle + ml: ml, mt: mt, mr: mr, mb: mb, + // rotating point + mtr: mtr + }; + + // set coordinates of the draggable boxes in the corners used to scale/rotate the image + this._setCornerCoords && this._setCornerCoords(); + + return this; + } + }); +})(); + + +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Moves an object to the bottom of the stack of drawn objects + * @return {fabric.Object} thisArg + * @chainable + */ + sendToBack: function() { + if (this.group) { + fabric.StaticCanvas.prototype.sendToBack.call(this.group, this); + } + else { + this.canvas.sendToBack(this); + } + return this; + }, + + /** + * Moves an object to the top of the stack of drawn objects + * @return {fabric.Object} thisArg + * @chainable + */ + bringToFront: function() { + if (this.group) { + fabric.StaticCanvas.prototype.bringToFront.call(this.group, this); + } + else { + this.canvas.bringToFront(this); + } + return this; + }, + + /** + * Moves an object down in stack of drawn objects + * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object + * @return {fabric.Object} thisArg + * @chainable + */ + sendBackwards: function(intersecting) { + if (this.group) { + fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting); + } + else { + this.canvas.sendBackwards(this, intersecting); + } + return this; + }, + + /** + * Moves an object up in stack of drawn objects + * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object + * @return {fabric.Object} thisArg + * @chainable + */ + bringForward: function(intersecting) { + if (this.group) { + fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting); + } + else { + this.canvas.bringForward(this, intersecting); + } + return this; + }, + + /** + * Moves an object to specified level in stack of drawn objects + * @param {Number} index New position of object + * @return {fabric.Object} thisArg + * @chainable + */ + moveTo: function(index) { + if (this.group) { + fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index); + } + else { + this.canvas.moveTo(this, index); + } + return this; + } +}); + + +/* _TO_SVG_START_ */ +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Returns styles-string for svg-export + * @return {String} + */ + getSvgStyles: function() { + + var fill = this.fill + ? (this.fill.toLive ? 'url(#SVGID_' + this.fill.id + ')' : this.fill) + : 'none', + fillRule = (this.fillRule === 'destination-over' ? 'evenodd' : this.fillRule), + stroke = this.stroke + ? (this.stroke.toLive ? 'url(#SVGID_' + this.stroke.id + ')' : this.stroke) + : 'none', + + strokeWidth = this.strokeWidth ? this.strokeWidth : '0', + strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : '', + strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt', + strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter', + strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4', + opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1', + + visibility = this.visible ? '' : ' visibility: hidden;', + filter = this.shadow && this.type !== 'text' ? 'filter: url(#SVGID_' + this.shadow.id + ');' : ''; + + return [ + 'stroke: ', stroke, '; ', + 'stroke-width: ', strokeWidth, '; ', + 'stroke-dasharray: ', strokeDashArray, '; ', + 'stroke-linecap: ', strokeLineCap, '; ', + 'stroke-linejoin: ', strokeLineJoin, '; ', + 'stroke-miterlimit: ', strokeMiterLimit, '; ', + 'fill: ', fill, '; ', + 'fill-rule: ', fillRule, '; ', + 'opacity: ', opacity, ';', + filter, + visibility + ].join(''); + }, + + /** + * Returns transform-string for svg-export + * @return {String} + */ + getSvgTransform: function() { + if (this.group) return ''; + var toFixed = fabric.util.toFixed, + angle = this.getAngle(), + vpt = this.getViewportTransform(), + center = fabric.util.transformPoint(this.getCenterPoint(), vpt), + + NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, + + translatePart = this.type === 'path-group' ? '' : 'translate(' + + toFixed(center.x, NUM_FRACTION_DIGITS) + + ' ' + + toFixed(center.y, NUM_FRACTION_DIGITS) + + ')', + + anglePart = angle !== 0 + ? (' rotate(' + toFixed(angle, NUM_FRACTION_DIGITS) + ')') + : '', + + scalePart = (this.scaleX === 1 && this.scaleY === 1 && vpt[0] === 1 && vpt[3] === 1) + ? '' : + (' scale(' + + toFixed(this.scaleX * vpt[0], NUM_FRACTION_DIGITS) + + ' ' + + toFixed(this.scaleY * vpt[3], NUM_FRACTION_DIGITS) + + ')'), + addTranslateX = this.type === 'path-group' ? this.width * vpt[0] : 0, + flipXPart = this.flipX ? ' matrix(-1 0 0 1 ' + addTranslateX + ' 0) ' : '', + addTranslateY = this.type === 'path-group' ? this.height * vpt[3] : 0, + flipYPart = this.flipY ? ' matrix(1 0 0 -1 0 ' + addTranslateY + ')' : ''; + + return [ + translatePart, anglePart, scalePart, flipXPart, flipYPart + ].join(''); + }, + + /** + * Returns transform-string for svg-export from the transform matrix of single elements + * @return {String} + */ + getSvgTransformMatrix: function() { + return this.transformMatrix ? ' matrix(' + this.transformMatrix.join(' ') + ')' : ''; + }, + + /** + * @private + */ + _createBaseSVGMarkup: function() { + var markup = [ ]; + + if (this.fill && this.fill.toLive) { + markup.push(this.fill.toSVG(this, false)); + } + if (this.stroke && this.stroke.toLive) { + markup.push(this.stroke.toSVG(this, false)); + } + if (this.shadow) { + markup.push(this.shadow.toSVG(this)); + } + return markup; + } +}); +/* _TO_SVG_END_ */ + + +/* + Depends on `stateProperties` +*/ +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * Returns true if object state (one of its state properties) was changed + * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called + */ + hasStateChanged: function() { + return this.stateProperties.some(function(prop) { + return this.get(prop) !== this.originalState[prop]; + }, this); + }, + + /** + * Saves state of an object + * @param {Object} [options] Object with additional `stateProperties` array to include when saving state + * @return {fabric.Object} thisArg + */ + saveState: function(options) { + this.stateProperties.forEach(function(prop) { + this.originalState[prop] = this.get(prop); + }, this); + + if (options && options.stateProperties) { + options.stateProperties.forEach(function(prop) { + this.originalState[prop] = this.get(prop); + }, this); + } + + return this; + }, + + /** + * Setups state of an object + * @return {fabric.Object} thisArg + */ + setupState: function() { + this.originalState = { }; + this.saveState(); + + return this; + } +}); + + +(function(){ + + var degreesToRadians = fabric.util.degreesToRadians, + //jscs:disable requireCamelCaseOrUpperCaseIdentifiers + isVML = function() { return typeof G_vmlCanvasManager !== 'undefined'; }; + //jscs:enable requireCamelCaseOrUpperCaseIdentifiers + + fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * The object interactivity controls. + * @private + */ + _controlsVisibility: null, + + /** + * Determines which corner has been clicked + * @private + * @param {Object} pointer The pointer indicating the mouse position + * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found + */ + _findTargetCorner: function(pointer) { + if (!this.hasControls || !this.active) { + return false; + } + + var ex = pointer.x, + ey = pointer.y, + xPoints, + lines; + + for (var i in this.oCoords) { + + if (!this.isControlVisible(i)) { + continue; + } + + if (i === 'mtr' && !this.hasRotatingPoint) { + continue; + } + + if (this.get('lockUniScaling') && + (i === 'mt' || i === 'mr' || i === 'mb' || i === 'ml')) { + continue; + } + + lines = this._getImageLines(this.oCoords[i].corner); + + // debugging + + // canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2); + + // canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2); + // canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2); + + xPoints = this._findCrossPoints({ x: ex, y: ey }, lines); + if (xPoints !== 0 && xPoints % 2 === 1) { + this.__corner = i; + return i; + } + } + return false; + }, + + /** + * Sets the coordinates of the draggable boxes in the corners of + * the image used to scale/rotate it. + * @private + */ + _setCornerCoords: function() { + var coords = this.oCoords, + theta = degreesToRadians(this.angle), + newTheta = degreesToRadians(45 - this.angle), + cornerHypotenuse = Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, + cosHalfOffset = cornerHypotenuse * Math.cos(newTheta), + sinHalfOffset = cornerHypotenuse * Math.sin(newTheta), + sinTh = Math.sin(theta), + cosTh = Math.cos(theta); + + coords.tl.corner = { + tl: { + x: coords.tl.x - sinHalfOffset, + y: coords.tl.y - cosHalfOffset + }, + tr: { + x: coords.tl.x + cosHalfOffset, + y: coords.tl.y - sinHalfOffset + }, + bl: { + x: coords.tl.x - cosHalfOffset, + y: coords.tl.y + sinHalfOffset + }, + br: { + x: coords.tl.x + sinHalfOffset, + y: coords.tl.y + cosHalfOffset + } + }; + + coords.tr.corner = { + tl: { + x: coords.tr.x - sinHalfOffset, + y: coords.tr.y - cosHalfOffset + }, + tr: { + x: coords.tr.x + cosHalfOffset, + y: coords.tr.y - sinHalfOffset + }, + br: { + x: coords.tr.x + sinHalfOffset, + y: coords.tr.y + cosHalfOffset + }, + bl: { + x: coords.tr.x - cosHalfOffset, + y: coords.tr.y + sinHalfOffset + } + }; + + coords.bl.corner = { + tl: { + x: coords.bl.x - sinHalfOffset, + y: coords.bl.y - cosHalfOffset + }, + bl: { + x: coords.bl.x - cosHalfOffset, + y: coords.bl.y + sinHalfOffset + }, + br: { + x: coords.bl.x + sinHalfOffset, + y: coords.bl.y + cosHalfOffset + }, + tr: { + x: coords.bl.x + cosHalfOffset, + y: coords.bl.y - sinHalfOffset + } + }; + + coords.br.corner = { + tr: { + x: coords.br.x + cosHalfOffset, + y: coords.br.y - sinHalfOffset + }, + bl: { + x: coords.br.x - cosHalfOffset, + y: coords.br.y + sinHalfOffset + }, + br: { + x: coords.br.x + sinHalfOffset, + y: coords.br.y + cosHalfOffset + }, + tl: { + x: coords.br.x - sinHalfOffset, + y: coords.br.y - cosHalfOffset + } + }; + + coords.ml.corner = { + tl: { + x: coords.ml.x - sinHalfOffset, + y: coords.ml.y - cosHalfOffset + }, + tr: { + x: coords.ml.x + cosHalfOffset, + y: coords.ml.y - sinHalfOffset + }, + bl: { + x: coords.ml.x - cosHalfOffset, + y: coords.ml.y + sinHalfOffset + }, + br: { + x: coords.ml.x + sinHalfOffset, + y: coords.ml.y + cosHalfOffset + } + }; + + coords.mt.corner = { + tl: { + x: coords.mt.x - sinHalfOffset, + y: coords.mt.y - cosHalfOffset + }, + tr: { + x: coords.mt.x + cosHalfOffset, + y: coords.mt.y - sinHalfOffset + }, + bl: { + x: coords.mt.x - cosHalfOffset, + y: coords.mt.y + sinHalfOffset + }, + br: { + x: coords.mt.x + sinHalfOffset, + y: coords.mt.y + cosHalfOffset + } + }; + + coords.mr.corner = { + tl: { + x: coords.mr.x - sinHalfOffset, + y: coords.mr.y - cosHalfOffset + }, + tr: { + x: coords.mr.x + cosHalfOffset, + y: coords.mr.y - sinHalfOffset + }, + bl: { + x: coords.mr.x - cosHalfOffset, + y: coords.mr.y + sinHalfOffset + }, + br: { + x: coords.mr.x + sinHalfOffset, + y: coords.mr.y + cosHalfOffset + } + }; + + coords.mb.corner = { + tl: { + x: coords.mb.x - sinHalfOffset, + y: coords.mb.y - cosHalfOffset + }, + tr: { + x: coords.mb.x + cosHalfOffset, + y: coords.mb.y - sinHalfOffset + }, + bl: { + x: coords.mb.x - cosHalfOffset, + y: coords.mb.y + sinHalfOffset + }, + br: { + x: coords.mb.x + sinHalfOffset, + y: coords.mb.y + cosHalfOffset + } + }; + + coords.mtr.corner = { + tl: { + x: coords.mtr.x - sinHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y - cosHalfOffset - (cosTh * this.rotatingPointOffset) + }, + tr: { + x: coords.mtr.x + cosHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y - sinHalfOffset - (cosTh * this.rotatingPointOffset) + }, + bl: { + x: coords.mtr.x - cosHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y + sinHalfOffset - (cosTh * this.rotatingPointOffset) + }, + br: { + x: coords.mtr.x + sinHalfOffset + (sinTh * this.rotatingPointOffset), + y: coords.mtr.y + cosHalfOffset - (cosTh * this.rotatingPointOffset) + } + }; + }, + /** + * Draws borders of an object's bounding box. + * Requires public properties: width, height + * Requires public options: padding, borderColor + * @param {CanvasRenderingContext2D} ctx Context to draw on + * @return {fabric.Object} thisArg + * @chainable + */ + drawBorders: function(ctx) { + if (!this.hasBorders) { + return this; + } + + var padding = this.padding, + padding2 = padding * 2, + vpt = this.getViewportTransform(); + + ctx.save(); + + ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; + ctx.strokeStyle = this.borderColor; + + var scaleX = 1 / this._constrainScale(this.scaleX), + scaleY = 1 / this._constrainScale(this.scaleY); + + ctx.lineWidth = 1 / this.borderScaleFactor; + + var w = this.getWidth(), + h = this.getHeight(), + strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + if (vLine) { + w = strokeWidth / scaleX; + } + else if (hLine) { + h = strokeWidth / scaleY; + } + if (strokeW) { + w += strokeWidth / scaleX; + } + if (strokeH) { + h += strokeWidth / scaleY; + } + var wh = fabric.util.transformPoint(new fabric.Point(w, h), vpt, true), + width = wh.x, + height = wh.y; + if (this.group) { + width = width * this.group.scaleX; + height = height * this.group.scaleY; + } + + ctx.strokeRect( + ~~(-(width / 2) - padding) - 0.5, // offset needed to make lines look sharper + ~~(-(height / 2) - padding) - 0.5, + ~~(width + padding2) + 1, // double offset needed to make lines look sharper + ~~(height + padding2) + 1 + ); + + if (this.hasRotatingPoint && this.isControlVisible('mtr') && !this.get('lockRotation') && this.hasControls) { + + var rotateHeight = ( -height - (padding * 2)) / 2; + + ctx.beginPath(); + ctx.moveTo(0, rotateHeight); + ctx.lineTo(0, rotateHeight - this.rotatingPointOffset); + ctx.closePath(); + ctx.stroke(); + } + + ctx.restore(); + return this; + }, + + /** + * Draws corners of an object's bounding box. + * Requires public properties: width, height + * Requires public options: cornerSize, padding + * @param {CanvasRenderingContext2D} ctx Context to draw on + * @return {fabric.Object} thisArg + * @chainable + */ + drawControls: function(ctx) { + if (!this.hasControls) { + return this; + } + + var size = this.cornerSize, + size2 = size / 2, + vpt = this.getViewportTransform(), + strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, + w = this.width, + h = this.height, + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + + if (vLine) { + w = strokeWidth; + } + else if (hLine) { + h = strokeWidth; + } + if (strokeW) { + w += strokeWidth; + } + if (strokeH) { + h += strokeWidth; + } + w *= this.scaleX; + h *= this.scaleY; + + var wh = fabric.util.transformPoint(new fabric.Point(w, h), vpt, true), + width = wh.x, + height = wh.y, + left = -(width / 2), + top = -(height / 2), + padding = this.padding, + scaleOffset = size2, + scaleOffsetSize = size2 - size, + methodName = this.transparentCorners ? 'strokeRect' : 'fillRect'; + + ctx.save(); + + ctx.lineWidth = 1; + + ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; + ctx.strokeStyle = ctx.fillStyle = this.cornerColor; + + // top-left + this._drawControl('tl', ctx, methodName, + left - scaleOffset - padding, + top - scaleOffset - padding); + + // top-right + this._drawControl('tr', ctx, methodName, + left + width - scaleOffset + padding, + top - scaleOffset - padding); + + // bottom-left + this._drawControl('bl', ctx, methodName, + left - scaleOffset - padding, + top + height + scaleOffsetSize + padding); + + // bottom-right + this._drawControl('br', ctx, methodName, + left + width + scaleOffsetSize + padding, + top + height + scaleOffsetSize + padding); + + if (!this.get('lockUniScaling')) { + + // middle-top + this._drawControl('mt', ctx, methodName, + left + width/2 - scaleOffset, + top - scaleOffset - padding); + + // middle-bottom + this._drawControl('mb', ctx, methodName, + left + width/2 - scaleOffset, + top + height + scaleOffsetSize + padding); + + // middle-right + this._drawControl('mr', ctx, methodName, + left + width + scaleOffsetSize + padding, + top + height/2 - scaleOffset); + + // middle-left + this._drawControl('ml', ctx, methodName, + left - scaleOffset - padding, + top + height/2 - scaleOffset); + } + + // middle-top-rotate + if (this.hasRotatingPoint) { + this._drawControl('mtr', ctx, methodName, + left + width/2 - scaleOffset, + top - this.rotatingPointOffset - this.cornerSize/2 - padding); + } + + ctx.restore(); + + return this; + }, + + /** + * @private + */ + _drawControl: function(control, ctx, methodName, left, top) { + var size = this.cornerSize; + + if (this.isControlVisible(control)) { + isVML() || this.transparentCorners || ctx.clearRect(left, top, size, size); + ctx[methodName](left, top, size, size); + } + }, + + /** + * Returns true if the specified control is visible, false otherwise. + * @param {String} controlName The name of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'. + * @returns {Boolean} true if the specified control is visible, false otherwise + */ + isControlVisible: function(controlName) { + return this._getControlsVisibility()[controlName]; + }, + + /** + * Sets the visibility of the specified control. + * @param {String} controlName The name of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'. + * @param {Boolean} visible true to set the specified control visible, false otherwise + * @return {fabric.Object} thisArg + * @chainable + */ + setControlVisible: function(controlName, visible) { + this._getControlsVisibility()[controlName] = visible; + return this; + }, + + /** + * Sets the visibility state of object controls. + * @param {Object} [options] Options object + * @param {Boolean} [options.bl] true to enable the bottom-left control, false to disable it + * @param {Boolean} [options.br] true to enable the bottom-right control, false to disable it + * @param {Boolean} [options.mb] true to enable the middle-bottom control, false to disable it + * @param {Boolean} [options.ml] true to enable the middle-left control, false to disable it + * @param {Boolean} [options.mr] true to enable the middle-right control, false to disable it + * @param {Boolean} [options.mt] true to enable the middle-top control, false to disable it + * @param {Boolean} [options.tl] true to enable the top-left control, false to disable it + * @param {Boolean} [options.tr] true to enable the top-right control, false to disable it + * @param {Boolean} [options.mtr] true to enable the middle-top-rotate control, false to disable it + * @return {fabric.Object} thisArg + * @chainable + */ + setControlsVisibility: function(options) { + options || (options = { }); + + for (var p in options) { + this.setControlVisible(p, options[p]); + } + return this; + }, + + /** + * Returns the instance of the control visibility set for this object. + * @private + * @returns {Object} + */ + _getControlsVisibility: function() { + if (!this._controlsVisibility) { + this._controlsVisibility = { + tl: true, + tr: true, + br: true, + bl: true, + ml: true, + mt: true, + mr: true, + mb: true, + mtr: true + }; + } + return this._controlsVisibility; + } + }); +})(); + + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Animation duration (in ms) for fx* methods + * @type Number + * @default + */ + FX_DURATION: 500, + + /** + * Centers object horizontally with animation. + * @param {fabric.Object} object Object to center + * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxCenterObjectH: function (object, callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: object.get('left'), + endValue: this.getCenter().left, + duration: this.FX_DURATION, + onChange: function(value) { + object.set('left', value); + _this.renderAll(); + onChange(); + }, + onComplete: function() { + object.setCoords(); + onComplete(); + } + }); + + return this; + }, + + /** + * Centers object vertically with animation. + * @param {fabric.Object} object Object to center + * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxCenterObjectV: function (object, callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: object.get('top'), + endValue: this.getCenter().top, + duration: this.FX_DURATION, + onChange: function(value) { + object.set('top', value); + _this.renderAll(); + onChange(); + }, + onComplete: function() { + object.setCoords(); + onComplete(); + } + }); + + return this; + }, + + /** + * Same as `fabric.Canvas#remove` but animated + * @param {fabric.Object} object Object to remove + * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxRemove: function (object, callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: object.get('opacity'), + endValue: 0, + duration: this.FX_DURATION, + onStart: function() { + object.set('active', false); + }, + onChange: function(value) { + object.set('opacity', value); + _this.renderAll(); + onChange(); + }, + onComplete: function () { + _this.remove(object); + onComplete(); + } + }); + + return this; + } +}); + +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + /** + * Animates object's properties + * @param {String|Object} property Property to animate (if string) or properties to animate (if object) + * @param {Number|Object} value Value to animate property to (if string was given first) or options object + * @return {fabric.Object} thisArg + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#animation} + * @chainable + * + * As object — multiple properties + * + * object.animate({ left: ..., top: ... }); + * object.animate({ left: ..., top: ... }, { duration: ... }); + * + * As string — one property + * + * object.animate('left', ...); + * object.animate('left', { duration: ... }); + * + */ + animate: function() { + if (arguments[0] && typeof arguments[0] === 'object') { + var propsToAnimate = [ ], prop, skipCallbacks; + for (prop in arguments[0]) { + propsToAnimate.push(prop); + } + for (var i = 0, len = propsToAnimate.length; i < len; i++) { + prop = propsToAnimate[i]; + skipCallbacks = i !== len - 1; + this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks); + } + } + else { + this._animate.apply(this, arguments); + } + return this; + }, + + /** + * @private + * @param {String} property Property to animate + * @param {String} to Value to animate to + * @param {Object} [options] Options object + * @param {Boolean} [skipCallbacks] When true, callbacks like onchange and oncomplete are not invoked + */ + _animate: function(property, to, options, skipCallbacks) { + var _this = this, propPair; + + to = to.toString(); + + if (!options) { + options = { }; + } + else { + options = fabric.util.object.clone(options); + } + + if (~property.indexOf('.')) { + propPair = property.split('.'); + } + + var currentValue = propPair + ? this.get(propPair[0])[propPair[1]] + : this.get(property); + + if (!('from' in options)) { + options.from = currentValue; + } + + if (~to.indexOf('=')) { + to = currentValue + parseFloat(to.replace('=', '')); + } + else { + to = parseFloat(to); + } + + fabric.util.animate({ + startValue: options.from, + endValue: to, + byValue: options.by, + easing: options.easing, + duration: options.duration, + abort: options.abort && function() { + return options.abort.call(_this); + }, + onChange: function(value) { + if (propPair) { + _this[propPair[0]][propPair[1]] = value; + } + else { + _this.set(property, value); + } + if (skipCallbacks) { + return; + } + options.onChange && options.onChange(); + }, + onComplete: function() { + if (skipCallbacks) { + return; + } + + _this.setCoords(); + options.onComplete && options.onComplete(); + } + }); + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 }, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Line) { + fabric.warn('fabric.Line is already defined'); + return; + } + + /** + * Line class + * @class fabric.Line + * @extends fabric.Object + * @see {@link fabric.Line#initialize} for constructor definition + */ + fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'line', + + /** + * x value or first line edge + * @type Number + * @default + */ + x1: 0, + + /** + * y value or first line edge + * @type Number + * @default + */ + y1: 0, + + /** + * x value or second line edge + * @type Number + * @default + */ + x2: 0, + + /** + * y value or second line edge + * @type Number + * @default + */ + y2: 0, + + /** + * Constructor + * @param {Array} [points] Array of points + * @param {Object} [options] Options object + * @return {fabric.Line} thisArg + */ + initialize: function(points, options) { + options = options || { }; + + if (!points) { + points = [0, 0, 0, 0]; + } + + this.callSuper('initialize', options); + + this.set('x1', points[0]); + this.set('y1', points[1]); + this.set('x2', points[2]); + this.set('y2', points[3]); + + this._setWidthHeight(options); + }, + + /** + * @private + * @param {Object} [options] Options + */ + _setWidthHeight: function(options) { + options || (options = { }); + + this.width = Math.abs(this.x2 - this.x1) || 1; + this.height = Math.abs(this.y2 - this.y1) || 1; + + this.left = 'left' in options + ? options.left + : this._getLeftToOriginX(); + + this.top = 'top' in options + ? options.top + : this._getTopToOriginY(); + }, + + /** + * @private + * @param {String} key + * @param {Any} value + */ + _set: function(key, value) { + this[key] = value; + if (typeof coordProps[key] !== 'undefined') { + this._setWidthHeight(); + } + return this; + }, + + /** + * @private + * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line. + */ + _getLeftToOriginX: makeEdgeToOriginGetter( + { // property names + origin: 'originX', + axis1: 'x1', + axis2: 'x2', + dimension: 'width' + }, + { // possible values of origin + nearest: 'left', + center: 'center', + farthest: 'right' + } + ), + + /** + * @private + * @return {Number} topToOriginY Distance from top edge of canvas to originY of Line. + */ + _getTopToOriginY: makeEdgeToOriginGetter( + { // property names + origin: 'originY', + axis1: 'y1', + axis2: 'y2', + dimension: 'height' + }, + { // possible values of origin + nearest: 'top', + center: 'center', + farthest: 'bottom' + } + ), + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx, noTransform) { + ctx.beginPath(); + + if (noTransform) { + // Line coords are distances from left-top of canvas to origin of line. + // + // To render line in a path-group, we need to translate them to + // distances from center of path-group to center of line. + var cp = this.getCenterPoint(); + ctx.translate( + cp.x, + cp.y + ); + } + + if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) { + + // move from center (of virtual box) to its left/top corner + // we can't assume x1, y1 is top left and x2, y2 is bottom right + var xMult = this.x1 <= this.x2 ? -1 : 1, + yMult = this.y1 <= this.y2 ? -1 : 1; + + ctx.moveTo( + this.width === 1 ? 0 : (xMult * this.width / 2), + this.height === 1 ? 0 : (yMult * this.height / 2)); + + ctx.lineTo( + this.width === 1 ? 0 : (xMult * -1 * this.width / 2), + this.height === 1 ? 0 : (yMult * -1 * this.height / 2)); + } + + ctx.lineWidth = this.strokeWidth; + + // TODO: test this + // make sure setting "fill" changes color of a line + // (by copying fillStyle to strokeStyle, since line is stroked, not filled) + var origStrokeStyle = ctx.strokeStyle; + ctx.strokeStyle = this.stroke || ctx.fillStyle; + this.stroke && this._renderStroke(ctx); + ctx.strokeStyle = origStrokeStyle; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var + xMult = this.x1 <= this.x2 ? -1 : 1, + yMult = this.y1 <= this.y2 ? -1 : 1, + x = this.width === 1 ? 0 : xMult * this.width / 2, + y = this.height === 1 ? 0 : yMult * this.height / 2; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, -x, -y, this.strokeDashArray); + ctx.closePath(); + }, + + /** + * Returns object representation of an instance + * @methd toObject + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + x1: this.get('x1'), + y1: this.get('y1'), + x2: this.get('x2'), + y2: this.get('y2') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), addTranslate = ''; + if (!this.group) { + var x = - this.width / 2 - (this.x1 > this.x2 ? this.x2 : this.x1), + y = - this.height / 2 - (this.y1 > this.y2 ? this.y2 : this.y1); + addTranslate = 'translate(' + x + ', ' + y + ') '; + } + markup.push( + '\n' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement}) + * @static + * @memberOf fabric.Line + * @see http://www.w3.org/TR/SVG/shapes.html#LineElement + */ + fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' ')); + + /** + * Returns fabric.Line instance from an SVG element + * @static + * @memberOf fabric.Line + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Line} instance of fabric.Line + */ + fabric.Line.fromElement = function(element, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES), + points = [ + parsedAttributes.x1 || 0, + parsedAttributes.y1 || 0, + parsedAttributes.x2 || 0, + parsedAttributes.y2 || 0 + ]; + return new fabric.Line(points, extend(parsedAttributes, options)); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Line instance from an object representation + * @static + * @memberOf fabric.Line + * @param {Object} object Object to create an instance from + * @return {fabric.Line} instance of fabric.Line + */ + fabric.Line.fromObject = function(object) { + var points = [object.x1, object.y1, object.x2, object.y2]; + return new fabric.Line(points, object); + }; + + /** + * Produces a function that calculates distance from canvas edge to Line origin. + */ + function makeEdgeToOriginGetter(propertyNames, originValues) { + var origin = propertyNames.origin, + axis1 = propertyNames.axis1, + axis2 = propertyNames.axis2, + dimension = propertyNames.dimension, + nearest = originValues.nearest, + center = originValues.center, + farthest = originValues.farthest; + + return function() { + switch (this.get(origin)) { + case nearest: + return Math.min(this.get(axis1), this.get(axis2)); + case center: + return Math.min(this.get(axis1), this.get(axis2)) + (0.5 * this.get(dimension)); + case farthest: + return Math.max(this.get(axis1), this.get(axis2)); + } + }; + + } + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + piBy2 = Math.PI * 2, + extend = fabric.util.object.extend; + + if (fabric.Circle) { + fabric.warn('fabric.Circle is already defined.'); + return; + } + + /** + * Circle class + * @class fabric.Circle + * @extends fabric.Object + * @see {@link fabric.Circle#initialize} for constructor definition + */ + fabric.Circle = fabric.util.createClass(fabric.Object, /** @lends fabric.Circle.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'circle', + + /** + * Radius of this circle + * @type Number + * @default + */ + radius: 0, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Circle} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + this.set('radius', options.radius || 0); + }, + + /** + * @private + * @param {String} key + * @param {Any} value + * @return {fabric.Circle} thisArg + */ + _set: function(key, value) { + this.callSuper('_set', key, value); + + if (key === 'radius') { + this.setRadius(value); + } + + return this; + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + radius: this.get('radius') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), x = 0, y = 0; + if (this.group) { + x = this.left + this.radius; + y = this.top + this.radius; + } + markup.push( + '\n' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + _render: function(ctx, noTransform) { + ctx.beginPath(); + ctx.arc(noTransform ? this.left + this.radius : 0, noTransform ? this.top + this.radius : 0, this.radius, 0, piBy2, false); + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * Returns horizontal radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusX: function() { + return this.get('radius') * this.get('scaleX'); + }, + + /** + * Returns vertical radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusY: function() { + return this.get('radius') * this.get('scaleY'); + }, + + /** + * Sets radius of an object (and updates width accordingly) + * @return {Number} + */ + setRadius: function(value) { + this.radius = value; + this.set('width', value * 2).set('height', value * 2); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Circle.fromElement}) + * @static + * @memberOf fabric.Circle + * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement + */ + fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy r'.split(' ')); + + /** + * Returns {@link fabric.Circle} instance from an SVG element + * @static + * @memberOf fabric.Circle + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @throws {Error} If value of `r` attribute is missing or invalid + * @return {fabric.Circle} Instance of fabric.Circle + */ + fabric.Circle.fromElement = function(element, options) { + options || (options = { }); + + var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES); + + if (!isValidRadius(parsedAttributes)) { + throw new Error('value of `r` attribute is required and can not be negative'); + } + + parsedAttributes.left = parsedAttributes.left || 0; + parsedAttributes.top = parsedAttributes.top || 0; + + var obj = new fabric.Circle(extend(parsedAttributes, options)); + + obj.left -= obj.radius; + obj.top -= obj.radius; + return obj; + }; + + /** + * @private + */ + function isValidRadius(attributes) { + return (('radius' in attributes) && (attributes.radius > 0)); + } + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Circle} instance from an object representation + * @static + * @memberOf fabric.Circle + * @param {Object} object Object to create an instance from + * @return {Object} Instance of fabric.Circle + */ + fabric.Circle.fromObject = function(object) { + return new fabric.Circle(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + if (fabric.Triangle) { + fabric.warn('fabric.Triangle is already defined'); + return; + } + + /** + * Triangle class + * @class fabric.Triangle + * @extends fabric.Object + * @return {fabric.Triangle} thisArg + * @see {@link fabric.Triangle#initialize} for constructor definition + */ + fabric.Triangle = fabric.util.createClass(fabric.Object, /** @lends fabric.Triangle.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'triangle', + + /** + * Constructor + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + + this.set('width', options.width || 100) + .set('height', options.height || 100); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + var widthBy2 = this.width / 2, + heightBy2 = this.height / 2; + + ctx.beginPath(); + ctx.moveTo(-widthBy2, heightBy2); + ctx.lineTo(0, -heightBy2); + ctx.lineTo(widthBy2, heightBy2); + ctx.closePath(); + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var widthBy2 = this.width / 2, + heightBy2 = this.height / 2; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray); + ctx.closePath(); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), + widthBy2 = this.width / 2, + heightBy2 = this.height / 2, + points = [ + -widthBy2 + ' ' + heightBy2, + '0 ' + -heightBy2, + widthBy2 + ' ' + heightBy2 + ] + .join(','); + + markup.push( + '' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /** + * Returns fabric.Triangle instance from an object representation + * @static + * @memberOf fabric.Triangle + * @param {Object} object Object to create an instance from + * @return {Object} instance of Canvas.Triangle + */ + fabric.Triangle.fromObject = function(object) { + return new fabric.Triangle(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global){ + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + piBy2 = Math.PI * 2, + extend = fabric.util.object.extend; + + if (fabric.Ellipse) { + fabric.warn('fabric.Ellipse is already defined.'); + return; + } + + /** + * Ellipse class + * @class fabric.Ellipse + * @extends fabric.Object + * @return {fabric.Ellipse} thisArg + * @see {@link fabric.Ellipse#initialize} for constructor definition + */ + fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @lends fabric.Ellipse.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'ellipse', + + /** + * Horizontal radius + * @type Number + * @default + */ + rx: 0, + + /** + * Vertical radius + * @type Number + * @default + */ + ry: 0, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {fabric.Ellipse} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + + this.set('rx', options.rx || 0); + this.set('ry', options.ry || 0); + + this.set('width', this.get('rx') * 2); + this.set('height', this.get('ry') * 2); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + rx: this.get('rx'), + ry: this.get('ry') + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), x = 0, y = 0; + if (this.group) { + x = this.left + this.rx; + y = this.top + this.ry; + } + markup.push( + '\n' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + _render: function(ctx, noTransform) { + ctx.beginPath(); + ctx.save(); + ctx.transform(1, 0, 0, this.ry/this.rx, 0, 0); + ctx.arc(noTransform ? this.left + this.rx : 0, noTransform ? (this.top + this.ry) * this.rx/this.ry : 0, this.rx, 0, piBy2, false); + ctx.restore(); + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement}) + * @static + * @memberOf fabric.Ellipse + * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement + */ + fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy rx ry'.split(' ')); + + /** + * Returns {@link fabric.Ellipse} instance from an SVG element + * @static + * @memberOf fabric.Ellipse + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Ellipse} + */ + fabric.Ellipse.fromElement = function(element, options) { + options || (options = { }); + + var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES); + + parsedAttributes.left = parsedAttributes.left || 0; + parsedAttributes.top = parsedAttributes.top || 0; + + var ellipse = new fabric.Ellipse(extend(parsedAttributes, options)); + + ellipse.top -= ellipse.ry; + ellipse.left -= ellipse.rx; + return ellipse; + }; + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Ellipse} instance from an object representation + * @static + * @memberOf fabric.Ellipse + * @param {Object} object Object to create an instance from + * @return {fabric.Ellipse} + */ + fabric.Ellipse.fromObject = function(object) { + return new fabric.Ellipse(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + if (fabric.Rect) { + console.warn('fabric.Rect is already defined'); + return; + } + + var stateProperties = fabric.Object.prototype.stateProperties.concat(); + stateProperties.push('rx', 'ry', 'x', 'y'); + + /** + * Rectangle class + * @class fabric.Rect + * @extends fabric.Object + * @return {fabric.Rect} thisArg + * @see {@link fabric.Rect#initialize} for constructor definition + */ + fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ { + + /** + * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged}) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: stateProperties, + + /** + * Type of an object + * @type String + * @default + */ + type: 'rect', + + /** + * Horizontal border radius + * @type Number + * @default + */ + rx: 0, + + /** + * Vertical border radius + * @type Number + * @default + */ + ry: 0, + + + /** + * Used to specify dash pattern for stroke on this object + * @type Array + */ + strokeDashArray: null, + + /** + * Constructor + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(options) { + options = options || { }; + + this.callSuper('initialize', options); + this._initRxRy(); + + }, + + /** + * Initializes rx/ry attributes + * @private + */ + _initRxRy: function() { + if (this.rx && !this.ry) { + this.ry = this.rx; + } + else if (this.ry && !this.rx) { + this.rx = this.ry; + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx, noTransform) { + + // optimize 1x1 case (used in spray brush) + if (this.width === 1 && this.height === 1) { + ctx.fillRect(0, 0, 1, 1); + return; + } + + var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0, + ry = this.ry ? Math.min(this.ry, this.height / 2) : 0, + w = this.width, + h = this.height, + x = noTransform ? this.left : 0, + y = noTransform ? this.top : 0, + isRounded = rx !== 0 || ry !== 0, + k = 1 - 0.5522847498 /* "magic number" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */; + + ctx.beginPath(); + + if (!noTransform) { + ctx.translate(-this.width / 2, -this.height / 2); + } + + ctx.moveTo(x + rx, y); + + ctx.lineTo(x + w - rx, y); + isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry); + + ctx.lineTo(x + w, y + h - ry); + isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h); + + ctx.lineTo(x + rx, y + h); + isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry); + + ctx.lineTo(x, y + ry); + isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y); + + ctx.closePath(); + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var x = -this.width / 2, + y = -this.height / 2, + w = this.width, + h = this.height; + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray); + ctx.closePath(); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var object = extend(this.callSuper('toObject', propertiesToInclude), { + rx: this.get('rx') || 0, + ry: this.get('ry') || 0 + }); + if (!this.includeDefaultValues) { + this._removeDefaultValues(object); + } + return object; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), x = this.left, y = this.top; + if (!this.group) { + x = -this.width / 2; + y = -this.height / 2; + } + markup.push( + '\n'); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`) + * @static + * @memberOf fabric.Rect + * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement + */ + fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' ')); + + /** + * Returns {@link fabric.Rect} instance from an SVG element + * @static + * @memberOf fabric.Rect + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Rect} Instance of fabric.Rect + */ + fabric.Rect.fromElement = function(element, options) { + if (!element) { + return null; + } + options = options || { }; + + var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES); + + parsedAttributes.left = parsedAttributes.left || 0; + parsedAttributes.top = parsedAttributes.top || 0; + + return new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns {@link fabric.Rect} instance from an object representation + * @static + * @memberOf fabric.Rect + * @param {Object} object Object to create an instance from + * @return {Object} instance of fabric.Rect + */ + fabric.Rect.fromObject = function(object) { + return new fabric.Rect(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + toFixed = fabric.util.toFixed; + + if (fabric.Polyline) { + fabric.warn('fabric.Polyline is already defined'); + return; + } + + /** + * Polyline class + * @class fabric.Polyline + * @extends fabric.Object + * @see {@link fabric.Polyline#initialize} for constructor definition + */ + fabric.Polyline = fabric.util.createClass(fabric.Object, /** @lends fabric.Polyline.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'polyline', + + /** + * Points array + * @type Array + * @default + */ + points: null, + + /** + * Constructor + * @param {Array} points Array of points (where each point is an object with x and y) + * @param {Object} [options] Options object + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + * @return {fabric.Polyline} thisArg + * @example + * var poly = new fabric.Polyline([ + * { x: 10, y: 10 }, + * { x: 50, y: 30 }, + * { x: 40, y: 70 }, + * { x: 60, y: 50 }, + * { x: 100, y: 150 }, + * { x: 40, y: 100 } + * ], { + * stroke: 'red', + * left: 100, + * top: 100 + * }); + */ + initialize: function(points, options, skipOffset) { + options = options || { }; + this.set('points', points); + this.callSuper('initialize', options); + this._calcDimensions(skipOffset); + }, + + /** + * @private + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + */ + _calcDimensions: function(skipOffset) { + return fabric.Polygon.prototype._calcDimensions.call(this, skipOffset); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return fabric.Polygon.prototype.toObject.call(this, propertiesToInclude); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var points = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.points.length; i < len; i++) { + points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' '); + } + + markup.push( + '\n' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + var point; + ctx.beginPath(); + ctx.moveTo(this.points[0].x, this.points[0].y); + for (var i = 0, len = this.points.length; i < len; i++) { + point = this.points[i]; + ctx.lineTo(point.x, point.y); + } + + this._renderFill(ctx); + this._renderStroke(ctx); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var p1, p2; + + ctx.beginPath(); + for (var i = 0, len = this.points.length; i < len; i++) { + p1 = this.points[i]; + p2 = this.points[i + 1] || p1; + fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); + } + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.get('points').length; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement}) + * @static + * @memberOf fabric.Polyline + * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement + */ + fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + + /** + * Returns fabric.Polyline instance from an SVG element + * @static + * @memberOf fabric.Polyline + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Polyline} Instance of fabric.Polyline + */ + fabric.Polyline.fromElement = function(element, options) { + if (!element) { + return null; + } + options || (options = { }); + + var points = fabric.parsePointsAttribute(element.getAttribute('points')), + parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES); + + if (points === null) { + return null; + } + + return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options), true); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Polyline instance from an object representation + * @static + * @memberOf fabric.Polyline + * @param {Object} object Object to create an instance from + * @return {fabric.Polyline} Instance of fabric.Polyline + */ + fabric.Polyline.fromObject = function(object) { + var points = object.points; + return new fabric.Polyline(points, object, true); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + min = fabric.util.array.min, + max = fabric.util.array.max, + toFixed = fabric.util.toFixed; + + if (fabric.Polygon) { + fabric.warn('fabric.Polygon is already defined'); + return; + } + + /** + * Polygon class + * @class fabric.Polygon + * @extends fabric.Object + * @see {@link fabric.Polygon#initialize} for constructor definition + */ + fabric.Polygon = fabric.util.createClass(fabric.Object, /** @lends fabric.Polygon.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'polygon', + + /** + * Points array + * @type Array + * @default + */ + points: null, + + /** + * Constructor + * @param {Array} points Array of points + * @param {Object} [options] Options object + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + * @return {fabric.Polygon} thisArg + */ + initialize: function(points, options, skipOffset) { + options = options || { }; + this.points = points; + this.callSuper('initialize', options); + this._calcDimensions(skipOffset); + }, + + /** + * @private + * @param {Boolean} [skipOffset] Whether points offsetting should be skipped + */ + _calcDimensions: function(skipOffset) { + + var points = this.points, + minX = min(points, 'x'), + minY = min(points, 'y'), + maxX = max(points, 'x'), + maxY = max(points, 'y'); + + this.width = (maxX - minX) || 1; + this.height = (maxY - minY) || 1; + + this.minX = minX; + this.minY = minY; + + if (skipOffset) { + return; + } + + var halfWidth = this.width / 2 + this.minX, + halfHeight = this.height / 2 + this.minY; + + // change points to offset polygon into a bounding box + this.points.forEach(function(p) { + p.x -= halfWidth; + p.y -= halfHeight; + }, this); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + points: this.points.concat() + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var points = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.points.length; i < len; i++) { + points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' '); + } + + markup.push( + '\n' + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + var point; + ctx.beginPath(); + ctx.moveTo(this.points[0].x, this.points[0].y); + for (var i = 0, len = this.points.length; i < len; i++) { + point = this.points[i]; + ctx.lineTo(point.x, point.y); + } + this._renderFill(ctx); + if (this.stroke || this.strokeDashArray) { + ctx.closePath(); + this._renderStroke(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var p1, p2; + + ctx.beginPath(); + for (var i = 0, len = this.points.length; i < len; i++) { + p1 = this.points[i]; + p2 = this.points[i + 1] || this.points[0]; + fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); + } + ctx.closePath(); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.points.length; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`) + * @static + * @memberOf fabric.Polygon + * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement + */ + fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + + /** + * Returns {@link fabric.Polygon} instance from an SVG element + * @static + * @memberOf fabric.Polygon + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Polygon} Instance of fabric.Polygon + */ + fabric.Polygon.fromElement = function(element, options) { + if (!element) { + return null; + } + + options || (options = { }); + + var points = fabric.parsePointsAttribute(element.getAttribute('points')), + parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES); + + if (points === null) { + return null; + } + + return new fabric.Polygon(points, extend(parsedAttributes, options), true); + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Polygon instance from an object representation + * @static + * @memberOf fabric.Polygon + * @param {Object} object Object to create an instance from + * @return {fabric.Polygon} Instance of fabric.Polygon + */ + fabric.Polygon.fromObject = function(object) { + return new fabric.Polygon(object.points, object, true); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + min = fabric.util.array.min, + max = fabric.util.array.max, + extend = fabric.util.object.extend, + _toString = Object.prototype.toString, + drawArc = fabric.util.drawArc, + commandLengths = { + m: 2, + l: 2, + h: 1, + v: 1, + c: 6, + s: 4, + q: 4, + t: 2, + a: 7 + }, + repeatedCommands = { + m: 'l', + M: 'L' + }; + + if (fabric.Path) { + fabric.warn('fabric.Path is already defined'); + return; + } + + /** + * @private + */ + function getX(item) { + if (item[0] === 'H') { + return item[1]; + } + return item[item.length - 2]; + } + + /** + * @private + */ + function getY(item) { + if (item[0] === 'V') { + return item[1]; + } + return item[item.length - 1]; + } + + /** + * Path class + * @class fabric.Path + * @extends fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup} + * @see {@link fabric.Path#initialize} for constructor definition + */ + fabric.Path = fabric.util.createClass(fabric.Object, /** @lends fabric.Path.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'path', + + /** + * Array of path points + * @type Array + * @default + */ + path: null, + + /** + * Constructor + * @param {Array|String} path Path data (sequence of coordinates and corresponding "command" tokens) + * @param {Object} [options] Options object + * @return {fabric.Path} thisArg + */ + initialize: function(path, options) { + options = options || { }; + + this.setOptions(options); + + if (!path) { + throw new Error('`path` argument is required'); + } + + var fromArray = _toString.call(path) === '[object Array]'; + + this.path = fromArray + ? path + // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values) + : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi); + + if (!this.path) { + return; + } + + if (!fromArray) { + this.path = this._parsePath(); + } + this._initializePath(options); + + if (options.sourcePath) { + this.setSourcePath(options.sourcePath); + } + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initializePath: function (options) { + var isWidthSet = 'width' in options && options.width != null, + isHeightSet = 'height' in options && options.width != null, + isLeftSet = 'left' in options, + isTopSet = 'top' in options, + origLeft = isLeftSet ? this.left : 0, + origTop = isTopSet ? this.top : 0; + + if (!isWidthSet || !isHeightSet) { + extend(this, this._parseDimensions()); + if (isWidthSet) { + this.width = options.width; + } + if (isHeightSet) { + this.height = options.height; + } + } + else { //Set center location relative to given height/width if not specified + if (!isTopSet) { + this.top = this.height / 2; + } + if (!isLeftSet) { + this.left = this.width / 2; + } + } + this.pathOffset = this.pathOffset || + // Save top-left coords as offset + this._calculatePathOffset(origLeft, origTop); + }, + + /** + * @private + * @param {Number} origLeft Original left position + * @param {Number} origTop Original top position + */ + _calculatePathOffset: function (origLeft, origTop) { + return { + x: this.left - origLeft - (this.width / 2), + y: this.top - origTop - (this.height / 2) + }; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx context to render path on + */ + _render: function(ctx, noTransform) { + var current, // current instruction + previous = null, + subpathStartX = 0, + subpathStartY = 0, + x = 0, // current x + y = 0, // current y + controlX = 0, // current control point x + controlY = 0, // current control point y + tempX, + tempY, + tempControlX, + tempControlY, + l = -((this.width / 2) + this.pathOffset.x), + t = -((this.height / 2) + this.pathOffset.y); + + if (noTransform) { + l += this.width / 2; + t += this.height / 2; + } + + for (var i = 0, len = this.path.length; i < len; ++i) { + + current = this.path[i]; + + switch (current[0]) { // first letter + + case 'l': // lineto, relative + x += current[1]; + y += current[2]; + ctx.lineTo(x + l, y + t); + break; + + case 'L': // lineto, absolute + x = current[1]; + y = current[2]; + ctx.lineTo(x + l, y + t); + break; + + case 'h': // horizontal lineto, relative + x += current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'H': // horizontal lineto, absolute + x = current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'v': // vertical lineto, relative + y += current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'V': // verical lineto, absolute + y = current[1]; + ctx.lineTo(x + l, y + t); + break; + + case 'm': // moveTo, relative + x += current[1]; + y += current[2]; + subpathStartX = x; + subpathStartY = y; + ctx.moveTo(x + l, y + t); + break; + + case 'M': // moveTo, absolute + x = current[1]; + y = current[2]; + subpathStartX = x; + subpathStartY = y; + ctx.moveTo(x + l, y + t); + break; + + case 'c': // bezierCurveTo, relative + tempX = x + current[5]; + tempY = y + current[6]; + controlX = x + current[3]; + controlY = y + current[4]; + ctx.bezierCurveTo( + x + current[1] + l, // x1 + y + current[2] + t, // y1 + controlX + l, // x2 + controlY + t, // y2 + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'C': // bezierCurveTo, absolute + x = current[5]; + y = current[6]; + controlX = current[3]; + controlY = current[4]; + ctx.bezierCurveTo( + current[1] + l, + current[2] + t, + controlX + l, + controlY + t, + x + l, + y + t + ); + break; + + case 's': // shorthand cubic bezierCurveTo, relative + + // transform to absolute x,y + tempX = x + current[3]; + tempY = y + current[4]; + + // calculate reflection of previous control points + controlX = controlX ? (2 * x - controlX) : x; + controlY = controlY ? (2 * y - controlY) : y; + + ctx.bezierCurveTo( + controlX + l, + controlY + t, + x + current[1] + l, + y + current[2] + t, + tempX + l, + tempY + t + ); + // set control point to 2nd one of this command + // "... the first control point is assumed to be + // the reflection of the second control point on + // the previous command relative to the current point." + controlX = x + current[1]; + controlY = y + current[2]; + + x = tempX; + y = tempY; + break; + + case 'S': // shorthand cubic bezierCurveTo, absolute + tempX = current[3]; + tempY = current[4]; + // calculate reflection of previous control points + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + ctx.bezierCurveTo( + controlX + l, + controlY + t, + current[1] + l, + current[2] + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + + // set control point to 2nd one of this command + // "... the first control point is assumed to be + // the reflection of the second control point on + // the previous command relative to the current point." + controlX = current[1]; + controlY = current[2]; + + break; + + case 'q': // quadraticCurveTo, relative + // transform to absolute x,y + tempX = x + current[3]; + tempY = y + current[4]; + + controlX = x + current[1]; + controlY = y + current[2]; + + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'Q': // quadraticCurveTo, absolute + tempX = current[3]; + tempY = current[4]; + + ctx.quadraticCurveTo( + current[1] + l, + current[2] + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + controlX = current[1]; + controlY = current[2]; + break; + + case 't': // shorthand quadraticCurveTo, relative + + // transform to absolute x,y + tempX = x + current[1]; + tempY = y + current[2]; + + if (previous[0].match(/[QqTt]/) === null) { + // If there is no previous command or if the previous command was not a Q, q, T or t, + // assume the control point is coincident with the current point + controlX = x; + controlY = y; + } + else if (previous[0] === 't') { + // calculate reflection of previous control points for t + controlX = 2 * x - tempControlX; + controlY = 2 * y - tempControlY; + } + else if (previous[0] === 'q') { + // calculate reflection of previous control points for q + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + + tempControlX = controlX; + tempControlY = controlY; + + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + controlX = x + current[1]; + controlY = y + current[2]; + break; + + case 'T': + tempX = current[1]; + tempY = current[2]; + + // calculate reflection of previous control points + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + ctx.quadraticCurveTo( + controlX + l, + controlY + t, + tempX + l, + tempY + t + ); + x = tempX; + y = tempY; + break; + + case 'a': + // TODO: optimize this + drawArc(ctx, x + l, y + t, [ + current[1], + current[2], + current[3], + current[4], + current[5], + current[6] + x + l, + current[7] + y + t + ]); + x += current[6]; + y += current[7]; + break; + + case 'A': + // TODO: optimize this + drawArc(ctx, x + l, y + t, [ + current[1], + current[2], + current[3], + current[4], + current[5], + current[6] + l, + current[7] + t + ]); + x = current[6]; + y = current[7]; + break; + + case 'z': + case 'Z': + x = subpathStartX; + y = subpathStartY; + ctx.closePath(); + break; + } + previous = current; + } + }, + + /** + * Renders path on a specified context + * @param {CanvasRenderingContext2D} ctx context to render path on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + render: function(ctx, noTransform) { + // do not render if object is not visible + if (!this.visible) { + return; + } + + ctx.save(); + if (noTransform) { + ctx.translate(-this.width/2, -this.height/2); + } + var m = this.transformMatrix; + + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + if (!noTransform) { + this.transform(ctx); + } + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + ctx.beginPath(); + ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; + this._render(ctx, noTransform); + this._renderFill(ctx); + this._renderStroke(ctx); + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * Returns string representation of an instance + * @return {String} string representation of an instance + */ + toString: function() { + return '#'; + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var o = extend(this.callSuper('toObject', propertiesToInclude), { + path: this.path.map(function(item) { return item.slice() }), + pathOffset: this.pathOffset + }); + if (this.sourcePath) { + o.sourcePath = this.sourcePath; + } + if (this.transformMatrix) { + o.transformMatrix = this.transformMatrix; + } + return o; + }, + + /** + * Returns dataless object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + var o = this.toObject(propertiesToInclude); + if (this.sourcePath) { + o.path = this.sourcePath; + } + delete o.sourcePath; + return o; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var chunks = [], + markup = this._createBaseSVGMarkup(); + + for (var i = 0, len = this.path.length; i < len; i++) { + chunks.push(this.path[i].join(' ')); + } + var path = chunks.join(' '); + + markup.push( + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns number representation of an instance complexity + * @return {Number} complexity of this instance + */ + complexity: function() { + return this.path.length; + }, + + /** + * @private + */ + _parsePath: function() { + var result = [ ], + coords = [ ], + currentPath, + parsed, + re = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/ig, + match, + coordsStr; + + for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) { + currentPath = this.path[i]; + + coordsStr = currentPath.slice(1).trim(); + coords.length = 0; + + while ((match = re.exec(coordsStr))) { + coords.push(match[0]); + } + + coordsParsed = [ currentPath.charAt(0) ]; + + for (var j = 0, jlen = coords.length; j < jlen; j++) { + parsed = parseFloat(coords[j]); + if (!isNaN(parsed)) { + coordsParsed.push(parsed); + } + } + + var command = coordsParsed[0], + commandLength = commandLengths[command.toLowerCase()], + repeatedCommand = repeatedCommands[command] || command; + + if (coordsParsed.length - 1 > commandLength) { + for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) { + result.push([ command ].concat(coordsParsed.slice(k, k + commandLength))); + command = repeatedCommand; + } + } + else { + result.push(coordsParsed); + } + } + + return result; + }, + + /** + * @private + */ + _parseDimensions: function() { + var aX = [], + aY = [], + previous = { }; + + this.path.forEach(function(item, i) { + this._getCoordsFromCommand(item, i, aX, aY, previous); + }, this); + + var minX = min(aX), + minY = min(aY), + maxX = max(aX), + maxY = max(aY), + deltaX = maxX - minX, + deltaY = maxY - minY, + + o = { + left: this.left + (minX + deltaX / 2), + top: this.top + (minY + deltaY / 2), + width: deltaX, + height: deltaY + }; + + return o; + }, + + _getCoordsFromCommand: function(item, i, aX, aY, previous) { + var isLowerCase = false; + + if (item[0] !== 'H') { + previous.x = (i === 0) ? getX(item) : getX(this.path[i - 1]); + } + if (item[0] !== 'V') { + previous.y = (i === 0) ? getY(item) : getY(this.path[i - 1]); + } + + // lowercased letter denotes relative position; + // transform to absolute + if (item[0] === item[0].toLowerCase()) { + isLowerCase = true; + } + + var xy = this._getXY(item, isLowerCase, previous), + val; + + val = parseInt(xy.x, 10); + if (!isNaN(val)) { + aX.push(val); + } + + val = parseInt(xy.y, 10); + if (!isNaN(val)) { + aY.push(val); + } + }, + + _getXY: function(item, isLowerCase, previous) { + + // last 2 items in an array of coordinates are the actualy x/y (except H/V), collect them + // TODO (kangax): support relative h/v commands + + var x = isLowerCase + ? previous.x + getX(item) + : item[0] === 'V' + ? previous.x + : getX(item), + + y = isLowerCase + ? previous.y + getY(item) + : item[0] === 'H' + ? previous.y + : getY(item); + + return { x: x, y: y }; + } + }); + + /** + * Creates an instance of fabric.Path from an object + * @static + * @memberOf fabric.Path + * @param {Object} object + * @param {Function} callback Callback to invoke when an fabric.Path instance is created + */ + fabric.Path.fromObject = function(object, callback) { + if (typeof object.path === 'string') { + fabric.loadSVGFromURL(object.path, function (elements) { + var path = elements[0], + pathUrl = object.path; + + delete object.path; + + fabric.util.object.extend(path, object); + path.setSourcePath(pathUrl); + + callback(path); + }); + } + else { + callback(new fabric.Path(object.path, object)); + } + }; + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by `fabric.Path.fromElement`) + * @static + * @memberOf fabric.Path + * @see http://www.w3.org/TR/SVG/paths.html#PathElement + */ + fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(['d']); + + /** + * Creates an instance of fabric.Path from an SVG element + * @static + * @memberOf fabric.Path + * @param {SVGElement} element to parse + * @param {Function} callback Callback to invoke when an fabric.Path instance is created + * @param {Object} [options] Options object + */ + fabric.Path.fromElement = function(element, callback, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES); + callback && callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options))); + }; + /* _FROM_SVG_END_ */ + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.Path + * @type Boolean + * @default + */ + fabric.Path.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + invoke = fabric.util.array.invoke, + parentToObject = fabric.Object.prototype.toObject; + + if (fabric.PathGroup) { + fabric.warn('fabric.PathGroup is already defined'); + return; + } + + /** + * Path group class + * @class fabric.PathGroup + * @extends fabric.Path + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup} + * @see {@link fabric.PathGroup#initialize} for constructor definition + */ + fabric.PathGroup = fabric.util.createClass(fabric.Path, /** @lends fabric.PathGroup.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'path-group', + + /** + * Fill value + * @type String + * @default + */ + fill: '', + + /** + * Constructor + * @param {Array} paths + * @param {Object} [options] Options object + * @return {fabric.PathGroup} thisArg + */ + initialize: function(paths, options) { + + options = options || { }; + this.paths = paths || [ ]; + + for (var i = this.paths.length; i--; ) { + this.paths[i].group = this; + } + + this.setOptions(options); + + if (options.widthAttr) { + this.scaleX = options.widthAttr / options.width; + } + if (options.heightAttr) { + this.scaleY = options.heightAttr / options.height; + } + + this.setCoords(); + + if (options.sourcePath) { + this.setSourcePath(options.sourcePath); + } + }, + + /** + * Renders this group on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render this instance on + */ + render: function(ctx) { + // do not render if object is not visible + if (!this.visible) { + return; + } + + ctx.save(); + + var m = this.transformMatrix; + + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + this.transform(ctx); + + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + for (var i = 0, l = this.paths.length; i < l; ++i) { + this.paths[i].render(ctx, true); + } + this.clipTo && ctx.restore(); + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * Sets certain property to a certain value + * @param {String} prop + * @param {Any} value + * @return {fabric.PathGroup} thisArg + */ + _set: function(prop, value) { + + if (prop === 'fill' && value && this.isSameColor()) { + var i = this.paths.length; + while (i--) { + this.paths[i]._set(prop, value); + } + } + + return this.callSuper('_set', prop, value); + }, + + /** + * Returns object representation of this path group + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + var o = extend(parentToObject.call(this, propertiesToInclude), { + paths: invoke(this.getObjects(), 'toObject', propertiesToInclude) + }); + if (this.sourcePath) { + o.sourcePath = this.sourcePath; + } + return o; + }, + + /** + * Returns dataless object representation of this path group + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} dataless object representation of an instance + */ + toDatalessObject: function(propertiesToInclude) { + var o = this.toObject(propertiesToInclude); + if (this.sourcePath) { + o.paths = this.sourcePath; + } + return o; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var objects = this.getObjects(), + translatePart = 'translate(' + this.left + ' ' + this.top + ')', + markup = [ + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ]; + + for (var i = 0, len = objects.length; i < len; i++) { + markup.push(objects[i].toSVG(reviver)); + } + markup.push('\n'); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns a string representation of this path group + * @return {String} string representation of an object + */ + toString: function() { + return '#'; + }, + + /** + * Returns true if all paths in this group are of same color + * @return {Boolean} true if all paths are of the same color (`fill`) + */ + isSameColor: function() { + var firstPathFill = (this.getObjects()[0].get('fill') || '').toLowerCase(); + return this.getObjects().every(function(path) { + return (path.get('fill') || '').toLowerCase() === firstPathFill; + }); + }, + + /** + * Returns number representation of object's complexity + * @return {Number} complexity + */ + complexity: function() { + return this.paths.reduce(function(total, path) { + return total + ((path && path.complexity) ? path.complexity() : 0); + }, 0); + }, + + /** + * Returns all paths in this path group + * @return {Array} array of path objects included in this path group + */ + getObjects: function() { + return this.paths; + } + }); + + /** + * Creates fabric.PathGroup instance from an object representation + * @static + * @memberOf fabric.PathGroup + * @param {Object} object Object to create an instance from + * @param {Function} callback Callback to invoke when an fabric.PathGroup instance is created + */ + fabric.PathGroup.fromObject = function(object, callback) { + if (typeof object.paths === 'string') { + fabric.loadSVGFromURL(object.paths, function (elements) { + + var pathUrl = object.paths; + delete object.paths; + + var pathGroup = fabric.util.groupSVGElements(elements, object, pathUrl); + + callback(pathGroup); + }); + } + else { + fabric.util.enlivenObjects(object.paths, function(enlivenedObjects) { + delete object.paths; + callback(new fabric.PathGroup(enlivenedObjects, object)); + }); + } + }; + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.PathGroup + * @type Boolean + * @default + */ + fabric.PathGroup.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global){ + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + min = fabric.util.array.min, + max = fabric.util.array.max, + invoke = fabric.util.array.invoke; + + if (fabric.Group) { + return; + } + + // lock-related properties, for use in fabric.Group#get + // to enable locking behavior on group + // when one of its objects has lock-related properties set + var _lockProperties = { + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + lockUniScaling: true + }; + + /** + * Group class + * @class fabric.Group + * @extends fabric.Object + * @mixes fabric.Collection + * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#groups} + * @see {@link fabric.Group#initialize} for constructor definition + */ + fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, /** @lends fabric.Group.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'group', + + /** + * Constructor + * @param {Object} objects Group objects + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + initialize: function(objects, options) { + options = options || { }; + + this._objects = objects || []; + for (var i = this._objects.length; i--; ) { + this._objects[i].group = this; + } + + this.originalState = { }; + this.callSuper('initialize'); + + this._calcBounds(); + this._updateObjectsCoords(); + + if (options) { + extend(this, options); + } + this._setOpacityIfSame(); + + this.setCoords(); + this.saveCoords(); + }, + + /** + * @private + */ + _updateObjectsCoords: function() { + this.forEachObject(this._updateObjectCoords, this); + }, + + /** + * @private + */ + _updateObjectCoords: function(object) { + var objectLeft = object.getLeft(), + objectTop = object.getTop(); + + object.set({ + originalLeft: objectLeft, + originalTop: objectTop, + left: objectLeft - this.left, + top: objectTop - this.top + }); + + object.setCoords(); + + // do not display corners of objects enclosed in a group + object.__origHasControls = object.hasControls; + object.hasControls = false; + }, + + /** + * Returns string represenation of a group + * @return {String} + */ + toString: function() { + return '#'; + }, + + /** + * Adds an object to a group; Then recalculates group's dimension, position. + * @param {Object} object + * @return {fabric.Group} thisArg + * @chainable + */ + addWithUpdate: function(object) { + this._restoreObjectsState(); + if (object) { + this._objects.push(object); + object.group = this; + } + // since _restoreObjectsState set objects inactive + this.forEachObject(this._setObjectActive, this); + this._calcBounds(); + this._updateObjectsCoords(); + return this; + }, + + /** + * @private + */ + _setObjectActive: function(object) { + object.set('active', true); + object.group = this; + }, + + /** + * Removes an object from a group; Then recalculates group's dimension, position. + * @param {Object} object + * @return {fabric.Group} thisArg + * @chainable + */ + removeWithUpdate: function(object) { + this._moveFlippedObject(object); + this._restoreObjectsState(); + + // since _restoreObjectsState set objects inactive + this.forEachObject(this._setObjectActive, this); + + this.remove(object); + this._calcBounds(); + this._updateObjectsCoords(); + + return this; + }, + + /** + * @private + */ + _onObjectAdded: function(object) { + object.group = this; + }, + + /** + * @private + */ + _onObjectRemoved: function(object) { + delete object.group; + object.set('active', false); + }, + + /** + * Properties that are delegated to group objects when reading/writing + * @param {Object} delegatedProperties + */ + delegatedProperties: { + fill: true, + opacity: true, + fontFamily: true, + fontWeight: true, + fontSize: true, + fontStyle: true, + lineHeight: true, + textDecoration: true, + textAlign: true, + backgroundColor: true + }, + + /** + * @private + */ + _set: function(key, value) { + if (key in this.delegatedProperties) { + var i = this._objects.length; + this[key] = value; + while (i--) { + this._objects[i].set(key, value); + } + } + else { + this[key] = value; + } + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + objects: invoke(this._objects, 'toObject', propertiesToInclude) + }); + }, + + /** + * Renders instance on a given context + * @param {CanvasRenderingContext2D} ctx context to render instance on + */ + render: function(ctx) { + // do not render if object is not visible + if (!this.visible) { + return; + } + + ctx.save(); + this.clipTo && fabric.util.clipContext(this, ctx); + + // the array is now sorted in order of highest first, so start from end + for (var i = 0, len = this._objects.length; i < len; i++) { + this._renderObject(this._objects[i], ctx); + } + + this.clipTo && ctx.restore(); + + ctx.restore(); + }, + + /** + * Renders controls and borders for the object + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Boolean} [noTransform] When true, context is not transformed + */ + _renderControls: function(ctx, noTransform) { + this.callSuper('_renderControls', ctx, noTransform); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i]._renderControls(ctx); + } + }, + + /** + * @private + */ + _renderObject: function(object, ctx) { + var originalHasRotatingPoint = object.hasRotatingPoint; + + // do not render if object is not visible + if (!object.visible) { + return; + } + + object.hasRotatingPoint = false; + + object.render(ctx); + + object.hasRotatingPoint = originalHasRotatingPoint; + }, + + /** + * Retores original state of each of group objects (original state is that which was before group was created). + * @private + * @return {fabric.Group} thisArg + * @chainable + */ + _restoreObjectsState: function() { + this._objects.forEach(this._restoreObjectState, this); + return this; + }, + + /** + * Moves a flipped object to the position where it's displayed + * @private + * @param {fabric.Object} object + * @return {fabric.Group} thisArg + */ + _moveFlippedObject: function(object) { + var oldOriginX = object.get('originX'), + oldOriginY = object.get('originY'), + center = object.getCenterPoint(); + + object.set({ + originX: 'center', + originY: 'center', + left: center.x, + top: center.y + }); + + this._toggleFlipping(object); + + var newOrigin = object.getPointByOrigin(oldOriginX, oldOriginY); + + object.set({ + originX: oldOriginX, + originY: oldOriginY, + left: newOrigin.x, + top: newOrigin.y + }); + + return this; + }, + + /** + * @private + */ + _toggleFlipping: function(object) { + if (this.flipX) { + object.toggle('flipX'); + object.set('left', -object.get('left')); + object.setAngle(-object.getAngle()); + } + if (this.flipY) { + object.toggle('flipY'); + object.set('top', -object.get('top')); + object.setAngle(-object.getAngle()); + } + }, + + /** + * Restores original state of a specified object in group + * @private + * @param {fabric.Object} object + * @return {fabric.Group} thisArg + */ + _restoreObjectState: function(object) { + this._setObjectPosition(object); + + object.setCoords(); + object.hasControls = object.__origHasControls; + delete object.__origHasControls; + object.set('active', false); + object.setCoords(); + delete object.group; + + return this; + }, + + /** + * @private + */ + _setObjectPosition: function(object) { + var groupLeft = this.getLeft(), + groupTop = this.getTop(), + rotated = this._getRotatedLeftTop(object); + + object.set({ + angle: object.getAngle() + this.getAngle(), + left: groupLeft + rotated.left, + top: groupTop + rotated.top, + scaleX: object.get('scaleX') * this.get('scaleX'), + scaleY: object.get('scaleY') * this.get('scaleY') + }); + }, + + /** + * @private + */ + _getRotatedLeftTop: function(object) { + var groupAngle = this.getAngle() * (Math.PI / 180); + return { + left: (-Math.sin(groupAngle) * object.getTop() * this.get('scaleY') + + Math.cos(groupAngle) * object.getLeft() * this.get('scaleX')), + + top: (Math.cos(groupAngle) * object.getTop() * this.get('scaleY') + + Math.sin(groupAngle) * object.getLeft() * this.get('scaleX')) + }; + }, + + /** + * Destroys a group (restoring state of its objects) + * @return {fabric.Group} thisArg + * @chainable + */ + destroy: function() { + this._objects.forEach(this._moveFlippedObject, this); + return this._restoreObjectsState(); + }, + + /** + * Saves coordinates of this instance (to be used together with `hasMoved`) + * @saveCoords + * @return {fabric.Group} thisArg + * @chainable + */ + saveCoords: function() { + this._originalLeft = this.get('left'); + this._originalTop = this.get('top'); + return this; + }, + + /** + * Checks whether this group was moved (since `saveCoords` was called last) + * @return {Boolean} true if an object was moved (since fabric.Group#saveCoords was called) + */ + hasMoved: function() { + return this._originalLeft !== this.get('left') || + this._originalTop !== this.get('top'); + }, + + /** + * Sets coordinates of all group objects + * @return {fabric.Group} thisArg + * @chainable + */ + setObjectsCoords: function() { + this.forEachObject(function(object) { + object.setCoords(); + }); + return this; + }, + + /** + * @private + */ + _setOpacityIfSame: function() { + var objects = this.getObjects(), + firstValue = objects[0] ? objects[0].get('opacity') : 1, + isSameOpacity = objects.every(function(o) { + return o.get('opacity') === firstValue; + }); + + if (isSameOpacity) { + this.opacity = firstValue; + } + }, + + /** + * @private + */ + _calcBounds: function(onlyWidthHeight) { + var aX = [], + aY = [], + o; + + for (var i = 0, len = this._objects.length; i < len; ++i) { + o = this._objects[i]; + o.setCoords(); + for (var prop in o.oCoords) { + aX.push(o.oCoords[prop].x); + aY.push(o.oCoords[prop].y); + } + } + + this.set(this._getBounds(aX, aY, onlyWidthHeight)); + }, + + /** + * @private + */ + _getBounds: function(aX, aY, onlyWidthHeight) { + var ivt = fabric.util.invertTransform(this.getViewportTransform()), + minXY = fabric.util.transformPoint(new fabric.Point(min(aX), min(aY)), ivt), + maxXY = fabric.util.transformPoint(new fabric.Point(max(aX), max(aY)), ivt), + obj = { + width: (maxXY.x - minXY.x) || 0, + height: (maxXY.y - minXY.y) || 0 + }; + + if (!onlyWidthHeight) { + obj.left = (minXY.x + maxXY.x) / 2 || 0; + obj.top = (minXY.y + maxXY.y) / 2 || 0; + } + return obj; + }, + + /* _TO_SVG_START_ */ + /** + * Returns svg representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = [ + //jscs:disable validateIndentation + '\n' + //jscs:enable validateIndentation + ]; + + for (var i = 0, len = this._objects.length; i < len; i++) { + markup.push(this._objects[i].toSVG(reviver)); + } + + markup.push('\n'); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns requested property + * @param {String} prop Property to get + * @return {Any} + */ + get: function(prop) { + if (prop in _lockProperties) { + if (this[prop]) { + return this[prop]; + } + else { + for (var i = 0, len = this._objects.length; i < len; i++) { + if (this._objects[i][prop]) { + return true; + } + } + return false; + } + } + else { + if (prop in this.delegatedProperties) { + return this._objects[0] && this._objects[0].get(prop); + } + return this[prop]; + } + } + }); + + /** + * Returns {@link fabric.Group} instance from an object representation + * @static + * @memberOf fabric.Group + * @param {Object} object Object to create a group from + * @param {Function} [callback] Callback to invoke when an group instance is created + * @return {fabric.Group} An instance of fabric.Group + */ + fabric.Group.fromObject = function(object, callback) { + fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) { + delete object.objects; + callback && callback(new fabric.Group(enlivenedObjects, object)); + }); + }; + + /** + * Indicates that instances of this type are async + * @static + * @memberOf fabric.Group + * @type Boolean + * @default + */ + fabric.Group.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var extend = fabric.util.object.extend; + + if (!global.fabric) { + global.fabric = { }; + } + + if (global.fabric.Image) { + fabric.warn('fabric.Image is already defined.'); + return; + } + + /** + * Image class + * @class fabric.Image + * @extends fabric.Object + * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#images} + * @see {@link fabric.Image#initialize} for constructor definition + */ + fabric.Image = fabric.util.createClass(fabric.Object, /** @lends fabric.Image.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'image', + + /** + * crossOrigin value (one of "", "anonymous", "allow-credentials") + * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes + * @type String + * @default + */ + crossOrigin: '', + + /** + * Constructor + * @param {HTMLImageElement | String} element Image element + * @param {Object} [options] Options object + * @return {fabric.Image} thisArg + */ + initialize: function(element, options) { + options || (options = { }); + + this.filters = [ ]; + + this.callSuper('initialize', options); + + this._initElement(element, options); + this._initConfig(options); + + if (options.filters) { + this.filters = options.filters; + this.applyFilters(); + } + }, + + /** + * Returns image element which this instance if based on + * @return {HTMLImageElement} Image element + */ + getElement: function() { + return this._element; + }, + + /** + * Sets image element for this instance to a specified one. + * If filters defined they are applied to new image. + * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area. + * @param {HTMLImageElement} element + * @param {Function} [callback] Callback is invoked when all filters have been applied and new image is generated + * @return {fabric.Image} thisArg + * @chainable + */ + setElement: function(element, callback) { + this._element = element; + this._originalElement = element; + this._initConfig(); + + if (this.filters.length !== 0) { + this.applyFilters(callback); + } + + return this; + }, + + /** + * Sets crossOrigin value (on an instance and corresponding image element) + * @return {fabric.Image} thisArg + * @chainable + */ + setCrossOrigin: function(value) { + this.crossOrigin = value; + this._element.crossOrigin = value; + + return this; + }, + + /** + * Returns original size of an image + * @return {Object} Object with "width" and "height" properties + */ + getOriginalSize: function() { + var element = this.getElement(); + return { + width: element.width, + height: element.height + }; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _stroke: function(ctx) { + ctx.save(); + this._setStrokeStyles(ctx); + ctx.beginPath(); + ctx.strokeRect(-this.width / 2, -this.height / 2, this.width, this.height); + ctx.closePath(); + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderDashedStroke: function(ctx) { + var x = -this.width / 2, + y = -this.height / 2, + w = this.width, + h = this.height; + + ctx.save(); + this._setStrokeStyles(ctx); + + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray); + ctx.closePath(); + ctx.restore(); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + return extend(this.callSuper('toObject', propertiesToInclude), { + src: this._originalElement.src || this._originalElement._src, + filters: this.filters.map(function(filterObj) { + return filterObj && filterObj.toObject(); + }), + crossOrigin: this.crossOrigin + }); + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = [], x = -this.width / 2, y = -this.height / 2; + if (this.group) { + x = this.left; + y = this.top; + } + markup.push( + '\n', + '\n' + ); + + if (this.stroke || this.strokeDashArray) { + var origFill = this.fill; + this.fill = null; + markup.push( + '\n' + ); + this.fill = origFill; + } + + markup.push('\n'); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + /* _TO_SVG_END_ */ + + /** + * Returns source of an image + * @return {String} Source of an image + */ + getSrc: function() { + if (this.getElement()) { + return this.getElement().src || this.getElement()._src; + } + }, + + /** + * Returns string representation of an instance + * @return {String} String representation of an instance + */ + toString: function() { + return '#'; + }, + + /** + * Returns a clone of an instance + * @param {Function} callback Callback is invoked with a clone as a first argument + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + */ + clone: function(callback, propertiesToInclude) { + this.constructor.fromObject(this.toObject(propertiesToInclude), callback); + }, + + /** + * Applies filters assigned to this image (from "filters" array) + * @mthod applyFilters + * @param {Function} callback Callback is invoked when all filters have been applied and new image is generated + * @return {fabric.Image} thisArg + * @chainable + */ + applyFilters: function(callback) { + + if (!this._originalElement) { + return; + } + + if (this.filters.length === 0) { + this._element = this._originalElement; + callback && callback(); + return; + } + + var imgEl = this._originalElement, + canvasEl = fabric.util.createCanvasElement(), + replacement = fabric.util.createImage(), + _this = this; + + canvasEl.width = imgEl.width; + canvasEl.height = imgEl.height; + + canvasEl.getContext('2d').drawImage(imgEl, 0, 0, imgEl.width, imgEl.height); + + this.filters.forEach(function(filter) { + filter && filter.applyTo(canvasEl); + }); + + /** @ignore */ + + replacement.width = imgEl.width; + replacement.height = imgEl.height; + + if (fabric.isLikelyNode) { + replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression); + + // onload doesn't fire in some node versions, so we invoke callback manually + _this._element = replacement; + callback && callback(); + } + else { + replacement.onload = function() { + _this._element = replacement; + callback && callback(); + replacement.onload = canvasEl = imgEl = null; + }; + replacement.src = canvasEl.toDataURL('image/png'); + } + + return this; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx, noTransform) { + this._element && + ctx.drawImage( + this._element, + noTransform ? this.left : -this.width/2, + noTransform ? this.top : -this.height/2, + this.width, + this.height + ); + this._renderStroke(ctx); + }, + + /** + * @private + */ + _resetWidthHeight: function() { + var element = this.getElement(); + + this.set('width', element.width); + this.set('height', element.height); + }, + + /** + * The Image class's initialization method. This method is automatically + * called by the constructor. + * @private + * @param {HTMLImageElement|String} element The element representing the image + */ + _initElement: function(element) { + this.setElement(fabric.util.getById(element)); + fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS); + }, + + /** + * @private + * @param {Object} [options] Options object + */ + _initConfig: function(options) { + options || (options = { }); + this.setOptions(options); + this._setWidthHeight(options); + if (this._element && this.crossOrigin) { + this._element.crossOrigin = this.crossOrigin; + } + }, + + /** + * @private + * @param {Object} object Object with filters property + * @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created + */ + _initFilters: function(object, callback) { + if (object.filters && object.filters.length) { + fabric.util.enlivenObjects(object.filters, function(enlivenedObjects) { + callback && callback(enlivenedObjects); + }, 'fabric.Image.filters'); + } + else { + callback && callback(); + } + }, + + /** + * @private + * @param {Object} [options] Object with width/height properties + */ + _setWidthHeight: function(options) { + this.width = 'width' in options + ? options.width + : (this.getElement() + ? this.getElement().width || 0 + : 0); + + this.height = 'height' in options + ? options.height + : (this.getElement() + ? this.getElement().height || 0 + : 0); + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity: function() { + return 1; + } + }); + + /** + * Default CSS class name for canvas + * @static + * @type String + * @default + */ + fabric.Image.CSS_CANVAS = 'canvas-img'; + + /** + * Alias for getSrc + * @static + */ + fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc; + + /** + * Creates an instance of fabric.Image from its object representation + * @static + * @param {Object} object Object to create an instance from + * @param {Function} [callback] Callback to invoke when an image instance is created + */ + fabric.Image.fromObject = function(object, callback) { + fabric.util.loadImage(object.src, function(img) { + fabric.Image.prototype._initFilters.call(object, object, function(filters) { + object.filters = filters || [ ]; + var instance = new fabric.Image(img, object); + callback && callback(instance); + }); + }, null, object.crossOrigin); + }; + + /** + * Creates an instance of fabric.Image from an URL string + * @static + * @param {String} url URL to create an image from + * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument) + * @param {Object} [imgOptions] Options object + */ + fabric.Image.fromURL = function(url, callback, imgOptions) { + fabric.util.loadImage(url, function(img) { + callback(new fabric.Image(img, imgOptions)); + }, null, imgOptions && imgOptions.crossOrigin); + }; + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement}) + * @static + * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement} + */ + fabric.Image.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y width height xlink:href'.split(' ')); + + /** + * Returns {@link fabric.Image} instance from an SVG element + * @static + * @param {SVGElement} element Element to parse + * @param {Function} callback Callback to execute when fabric.Image object is created + * @param {Object} [options] Options object + * @return {fabric.Image} Instance of fabric.Image + */ + fabric.Image.fromElement = function(element, callback, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES); + + fabric.Image.fromURL(parsedAttributes['xlink:href'], callback, + extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + }; + /* _FROM_SVG_END_ */ + + /** + * Indicates that instances of this type are async + * @static + * @type Boolean + * @default + */ + fabric.Image.async = true; + + /** + * Indicates compression level used when generating PNG under Node (in applyFilters). Any of 0-9 + * @static + * @type Number + * @default + */ + fabric.Image.pngCompression = 1; + +})(typeof exports !== 'undefined' ? exports : this); + + +fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { + + /** + * @private + * @return {Number} angle value + */ + _getAngleValueForStraighten: function() { + var angle = this.getAngle() % 360; + if (angle > 0) { + return Math.round((angle - 1) / 90) * 90; + } + return Math.round(angle / 90) * 90; + }, + + /** + * Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer) + * @return {fabric.Object} thisArg + * @chainable + */ + straighten: function() { + this.setAngle(this._getAngleValueForStraighten()); + return this; + }, + + /** + * Same as {@link fabric.Object.prototype.straighten} but with animation + * @param {Object} callbacks Object with callback functions + * @param {Function} [callbacks.onComplete] Invoked on completion + * @param {Function} [callbacks.onChange] Invoked on every step of animation + * @return {fabric.Object} thisArg + * @chainable + */ + fxStraighten: function(callbacks) { + callbacks = callbacks || { }; + + var empty = function() { }, + onComplete = callbacks.onComplete || empty, + onChange = callbacks.onChange || empty, + _this = this; + + fabric.util.animate({ + startValue: this.get('angle'), + endValue: this._getAngleValueForStraighten(), + duration: this.FX_DURATION, + onChange: function(value) { + _this.setAngle(value); + onChange(); + }, + onComplete: function() { + _this.setCoords(); + onComplete(); + }, + onStart: function() { + _this.set('active', false); + } + }); + + return this; + } +}); + +fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { + + /** + * Straightens object, then rerenders canvas + * @param {fabric.Object} object Object to straighten + * @return {fabric.Canvas} thisArg + * @chainable + */ + straightenObject: function (object) { + object.straighten(); + this.renderAll(); + return this; + }, + + /** + * Same as {@link fabric.Canvas.prototype.straightenObject}, but animated + * @param {fabric.Object} object Object to straighten + * @return {fabric.Canvas} thisArg + * @chainable + */ + fxStraightenObject: function (object) { + object.fxStraighten({ + onChange: this.renderAll.bind(this) + }); + return this; + } +}); + + +/** + * @namespace fabric.Image.filters + * @memberOf fabric.Image + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#image_filters} + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + */ +fabric.Image.filters = fabric.Image.filters || { }; + +/** + * Root filter class from which all filter classes inherit from + * @class fabric.Image.filters.BaseFilter + * @memberOf fabric.Image.filters + */ +fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Image.filters.BaseFilter.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'BaseFilter', + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return { type: this.type }; + }, + + /** + * Returns a JSON representation of an instance + * @return {Object} JSON + */ + toJSON: function() { + // delegate, not alias + return this.toObject(); + } +}); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Brightness filter class + * @class fabric.Image.filters.Brightness + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Brightness#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Brightness({ + * brightness: 200 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Brightness = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Brightness.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Brightness', + + /** + * Constructor + * @memberOf fabric.Image.filters.Brightness.prototype + * @param {Object} [options] Options object + * @param {Number} [options.brightness=0] Value to brighten the image up (0..255) + */ + initialize: function(options) { + options = options || { }; + this.brightness = options.brightness || 0; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + brightness = this.brightness; + + for (var i = 0, len = data.length; i < len; i += 4) { + data[i] += brightness; + data[i + 1] += brightness; + data[i + 2] += brightness; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + brightness: this.brightness + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Brightness} Instance of fabric.Image.filters.Brightness + */ + fabric.Image.filters.Brightness.fromObject = function(object) { + return new fabric.Image.filters.Brightness(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Adapted from html5rocks article + * @class fabric.Image.filters.Convolute + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Convolute#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Convolute({ + * matrix: [ 0, -1, 0, + * -1, 5, -1, + * 0, -1, 0 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example + * var filter = new fabric.Image.filters.Convolute({ + * matrix: [ 1/9, 1/9, 1/9, + * 1/9, 1/9, 1/9, + * 1/9, 1/9, 1/9 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example + * var filter = new fabric.Image.filters.Convolute({ + * matrix: [ 1, 1, 1, + * 1, 0.7, -1, + * -1, -1, -1 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example + * var filter = new fabric.Image.filters.Convolute({ + * opaque: true, + * matrix: [ 1, 1, 1, + * 1, 0.7, -1, + * -1, -1, -1 ] + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Convolute = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Convolute.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Convolute', + + /** + * Constructor + * @memberOf fabric.Image.filters.Convolute.prototype + * @param {Object} [options] Options object + * @param {Boolean} [options.opaque=false] Opaque value (true/false) + * @param {Array} [options.matrix] Filter matrix + */ + initialize: function(options) { + options = options || { }; + + this.opaque = options.opaque; + this.matrix = options.matrix || [ + 0, 0, 0, + 0, 1, 0, + 0, 0, 0 + ]; + + var canvasEl = fabric.util.createCanvasElement(); + this.tmpCtx = canvasEl.getContext('2d'); + }, + + /** + * @private + */ + _createImageData: function(w, h) { + return this.tmpCtx.createImageData(w, h); + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + + var weights = this.matrix, + context = canvasEl.getContext('2d'), + pixels = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + + side = Math.round(Math.sqrt(weights.length)), + halfSide = Math.floor(side/2), + src = pixels.data, + sw = pixels.width, + sh = pixels.height, + + // pad output by the convolution matrix + w = sw, + h = sh, + output = this._createImageData(w, h), + + dst = output.data, + + // go through the destination image pixels + alphaFac = this.opaque ? 1 : 0; + + for (var y = 0; y < h; y++) { + for (var x = 0; x < w; x++) { + var sy = y, + sx = x, + dstOff = (y * w + x) * 4, + // calculate the weighed sum of the source image pixels that + // fall under the convolution matrix + r = 0, g = 0, b = 0, a = 0; + + for (var cy = 0; cy < side; cy++) { + for (var cx = 0; cx < side; cx++) { + + var scy = sy + cy - halfSide, + scx = sx + cx - halfSide; + + /* jshint maxdepth:5 */ + if (scy < 0 || scy > sh || scx < 0 || scx > sw) { + continue; + } + + var srcOff = (scy * sw + scx) * 4, + wt = weights[cy * side + cx]; + + r += src[srcOff] * wt; + g += src[srcOff + 1] * wt; + b += src[srcOff + 2] * wt; + a += src[srcOff + 3] * wt; + } + } + dst[dstOff] = r; + dst[dstOff + 1] = g; + dst[dstOff + 2] = b; + dst[dstOff + 3] = a + alphaFac * (255 - a); + } + } + + context.putImageData(output, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + opaque: this.opaque, + matrix: this.matrix + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Convolute} Instance of fabric.Image.filters.Convolute + */ + fabric.Image.filters.Convolute.fromObject = function(object) { + return new fabric.Image.filters.Convolute(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * GradientTransparency filter class + * @class fabric.Image.filters.GradientTransparency + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.GradientTransparency#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.GradientTransparency({ + * threshold: 200 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.GradientTransparency = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.GradientTransparency.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'GradientTransparency', + + /** + * Constructor + * @memberOf fabric.Image.filters.GradientTransparency.prototype + * @param {Object} [options] Options object + * @param {Number} [options.threshold=100] Threshold value + */ + initialize: function(options) { + options = options || { }; + this.threshold = options.threshold || 100; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + threshold = this.threshold, + total = data.length; + + for (var i = 0, len = data.length; i < len; i += 4) { + data[i + 3] = threshold + 255 * (total - i) / total; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + threshold: this.threshold + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.GradientTransparency} Instance of fabric.Image.filters.GradientTransparency + */ + fabric.Image.filters.GradientTransparency.fromObject = function(object) { + return new fabric.Image.filters.GradientTransparency(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Grayscale image filter class + * @class fabric.Image.filters.Grayscale + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Grayscale(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Grayscale = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Grayscale.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Grayscale', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Grayscale.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + len = imageData.width * imageData.height * 4, + index = 0, + average; + + while (index < len) { + average = (data[index] + data[index + 1] + data[index + 2]) / 3; + data[index] = average; + data[index + 1] = average; + data[index + 2] = average; + index += 4; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale + */ + fabric.Image.filters.Grayscale.fromObject = function() { + return new fabric.Image.filters.Grayscale(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Invert filter class + * @class fabric.Image.filters.Invert + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Invert(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Invert = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Invert.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Invert', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Invert.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i; + + for (i = 0; i < iLen; i+=4) { + data[i] = 255 - data[i]; + data[i + 1] = 255 - data[i + 1]; + data[i + 2] = 255 - data[i + 2]; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Invert} Instance of fabric.Image.filters.Invert + */ + fabric.Image.filters.Invert.fromObject = function() { + return new fabric.Image.filters.Invert(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Mask filter class + * See http://resources.aleph-1.com/mask/ + * @class fabric.Image.filters.Mask + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Mask#initialize} for constructor definition + */ + fabric.Image.filters.Mask = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Mask.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Mask', + + /** + * Constructor + * @memberOf fabric.Image.filters.Mask.prototype + * @param {Object} [options] Options object + * @param {fabric.Image} [options.mask] Mask image object + * @param {Number} [options.channel=0] Rgb channel (0, 1, 2 or 3) + */ + initialize: function(options) { + options = options || { }; + + this.mask = options.mask; + this.channel = [ 0, 1, 2, 3 ].indexOf(options.channel) > -1 ? options.channel : 0; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + if (!this.mask) { + return; + } + + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + maskEl = this.mask.getElement(), + maskCanvasEl = fabric.util.createCanvasElement(), + channel = this.channel, + i, + iLen = imageData.width * imageData.height * 4; + + maskCanvasEl.width = maskEl.width; + maskCanvasEl.height = maskEl.height; + + maskCanvasEl.getContext('2d').drawImage(maskEl, 0, 0, maskEl.width, maskEl.height); + + var maskImageData = maskCanvasEl.getContext('2d').getImageData(0, 0, maskEl.width, maskEl.height), + maskData = maskImageData.data; + + for (i = 0; i < iLen; i += 4) { + data[i + 3] = maskData[i + channel]; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + mask: this.mask.toObject(), + channel: this.channel + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @param {Function} [callback] Callback to invoke when a mask filter instance is created + */ + fabric.Image.filters.Mask.fromObject = function(object, callback) { + fabric.util.loadImage(object.mask.src, function(img) { + object.mask = new fabric.Image(img, object.mask); + callback && callback(new fabric.Image.filters.Mask(object)); + }); + }; + + /** + * Indicates that instances of this type are async + * @static + * @type Boolean + * @default + */ + fabric.Image.filters.Mask.async = true; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Noise filter class + * @class fabric.Image.filters.Noise + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Noise#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Noise({ + * noise: 700 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Noise = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Noise.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Noise', + + /** + * Constructor + * @memberOf fabric.Image.filters.Noise.prototype + * @param {Object} [options] Options object + * @param {Number} [options.noise=0] Noise value + */ + initialize: function(options) { + options = options || { }; + this.noise = options.noise || 0; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + noise = this.noise, rand; + + for (var i = 0, len = data.length; i < len; i += 4) { + + rand = (0.5 - Math.random()) * noise; + + data[i] += rand; + data[i + 1] += rand; + data[i + 2] += rand; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + noise: this.noise + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Noise} Instance of fabric.Image.filters.Noise + */ + fabric.Image.filters.Noise.fromObject = function(object) { + return new fabric.Image.filters.Noise(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Pixelate filter class + * @class fabric.Image.filters.Pixelate + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Pixelate#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Pixelate({ + * blocksize: 8 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Pixelate = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Pixelate.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Pixelate', + + /** + * Constructor + * @memberOf fabric.Image.filters.Pixelate.prototype + * @param {Object} [options] Options object + * @param {Number} [options.blocksize=4] Blocksize for pixelate + */ + initialize: function(options) { + options = options || { }; + this.blocksize = options.blocksize || 4; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = imageData.height, + jLen = imageData.width, + index, i, j, r, g, b, a; + + for (i = 0; i < iLen; i += this.blocksize) { + for (j = 0; j < jLen; j += this.blocksize) { + + index = (i * 4) * jLen + (j * 4); + + r = data[index]; + g = data[index + 1]; + b = data[index + 2]; + a = data[index + 3]; + + /* + blocksize: 4 + + [1,x,x,x,1] + [x,x,x,x,1] + [x,x,x,x,1] + [x,x,x,x,1] + [1,1,1,1,1] + */ + + for (var _i = i, _ilen = i + this.blocksize; _i < _ilen; _i++) { + for (var _j = j, _jlen = j + this.blocksize; _j < _jlen; _j++) { + index = (_i * 4) * jLen + (_j * 4); + data[index] = r; + data[index + 1] = g; + data[index + 2] = b; + data[index + 3] = a; + } + } + } + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + blocksize: this.blocksize + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Pixelate} Instance of fabric.Image.filters.Pixelate + */ + fabric.Image.filters.Pixelate.fromObject = function(object) { + return new fabric.Image.filters.Pixelate(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Remove white filter class + * @class fabric.Image.filters.RemoveWhite + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.RemoveWhite#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.RemoveWhite({ + * threshold: 40, + * distance: 140 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.RemoveWhite = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.RemoveWhite.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'RemoveWhite', + + /** + * Constructor + * @memberOf fabric.Image.filters.RemoveWhite.prototype + * @param {Object} [options] Options object + * @param {Number} [options.threshold=30] Threshold value + * @param {Number} [options.distance=20] Distance value + */ + initialize: function(options) { + options = options || { }; + this.threshold = options.threshold || 30; + this.distance = options.distance || 20; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + threshold = this.threshold, + distance = this.distance, + limit = 255 - threshold, + abs = Math.abs, + r, g, b; + + for (var i = 0, len = data.length; i < len; i += 4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + if (r > limit && + g > limit && + b > limit && + abs(r - g) < distance && + abs(r - b) < distance && + abs(g - b) < distance + ) { + data[i + 3] = 1; + } + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + threshold: this.threshold, + distance: this.distance + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.RemoveWhite} Instance of fabric.Image.filters.RemoveWhite + */ + fabric.Image.filters.RemoveWhite.fromObject = function(object) { + return new fabric.Image.filters.RemoveWhite(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Sepia filter class + * @class fabric.Image.filters.Sepia + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Sepia(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Sepia = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Sepia', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Sepia.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, avg; + + for (i = 0; i < iLen; i+=4) { + avg = 0.3 * data[i] + 0.59 * data[i + 1] + 0.11 * data[i + 2]; + data[i] = avg + 100; + data[i + 1] = avg + 50; + data[i + 2] = avg + 255; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Sepia} Instance of fabric.Image.filters.Sepia + */ + fabric.Image.filters.Sepia.fromObject = function() { + return new fabric.Image.filters.Sepia(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }); + + /** + * Sepia2 filter class + * @class fabric.Image.filters.Sepia2 + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Sepia2(); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Sepia2 = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia2.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Sepia2', + + /** + * Applies filter to canvas element + * @memberOf fabric.Image.filters.Sepia.prototype + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, r, g, b; + + for (i = 0; i < iLen; i+=4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + data[i] = (r * 0.393 + g * 0.769 + b * 0.189 ) / 1.351; + data[i + 1] = (r * 0.349 + g * 0.686 + b * 0.168 ) / 1.203; + data[i + 2] = (r * 0.272 + g * 0.534 + b * 0.131 ) / 2.140; + } + + context.putImageData(imageData, 0, 0); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @return {fabric.Image.filters.Sepia2} Instance of fabric.Image.filters.Sepia2 + */ + fabric.Image.filters.Sepia2.fromObject = function() { + return new fabric.Image.filters.Sepia2(); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Tint filter class + * Adapted from https://github.com/mezzoblue/PaintbrushJS + * @class fabric.Image.filters.Tint + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @see {@link fabric.Image.filters.Tint#initialize} for constructor definition + * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} + * @example + * var filter = new fabric.Image.filters.Tint({ + * color: '#3513B0', + * opacity: 0.5 + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example + * var filter = new fabric.Image.filters.Tint({ + * color: 'rgba(53, 21, 176, 0.5)' + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Tint = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Tint.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Tint', + + /** + * Constructor + * @memberOf fabric.Image.filters.Tint.prototype + * @param {Object} [options] Options object + * @param {String} [options.color=#000000] Color to tint the image with + * @param {Number} [options.opacity] Opacity value that controls the tint effect's transparency (0..1) + */ + initialize: function(options) { + options = options || { }; + + this.color = options.color || '#000000'; + this.opacity = typeof options.opacity !== 'undefined' + ? options.opacity + : new fabric.Color(this.color).getAlpha(); + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, + tintR, tintG, tintB, + r, g, b, alpha1, + source; + + source = new fabric.Color(this.color).getSource(); + + tintR = source[0] * this.opacity; + tintG = source[1] * this.opacity; + tintB = source[2] * this.opacity; + + alpha1 = 1 - this.opacity; + + for (i = 0; i < iLen; i+=4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + // alpha compositing + data[i] = tintR + r * alpha1; + data[i + 1] = tintG + g * alpha1; + data[i + 2] = tintB + b * alpha1; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + color: this.color, + opacity: this.opacity + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Tint} Instance of fabric.Image.filters.Tint + */ + fabric.Image.filters.Tint.fromObject = function(object) { + return new fabric.Image.filters.Tint(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend; + + /** + * Multiply filter class + * Adapted from http://www.laurenscorijn.com/articles/colormath-basics + * @class fabric.Image.filters.Multiply + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @example + * var filter = new fabric.Image.filters.Multiply({ + * color: '#F0F' + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + * @example + * var filter = new fabric.Image.filters.Multiply({ + * color: 'rgb(53, 21, 176)' + * }); + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Multiply = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Multiply.prototype */ { + + /** + * Filter type + * @param {String} type + * @default + */ + type: 'Multiply', + + /** + * Constructor + * @memberOf fabric.Image.filters.Multiply.prototype + * @param {Object} [options] Options object + * @param {String} [options.color=#000000] Color to multiply the image pixels with + */ + initialize: function(options) { + options = options || { }; + + this.color = options.color || '#000000'; + }, + + /** + * Applies filter to canvas element + * @param {Object} canvasEl Canvas element to apply filter to + */ + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + iLen = data.length, i, + source; + + source = new fabric.Color(this.color).getSource(); + + for (i = 0; i < iLen; i+=4) { + data[i] *= source[0] / 255; + data[i + 1] *= source[1] / 255; + data[i + 2] *= source[2] / 255; + } + + context.putImageData(imageData, 0, 0); + }, + + /** + * Returns object representation of an instance + * @return {Object} Object representation of an instance + */ + toObject: function() { + return extend(this.callSuper('toObject'), { + color: this.color + }); + } + }); + + /** + * Returns filter instance from an object representation + * @static + * @param {Object} object Object to create an instance from + * @return {fabric.Image.filters.Multiply} Instance of fabric.Image.filters.Multiply + */ + fabric.Image.filters.Multiply.fromObject = function(object) { + return new fabric.Image.filters.Multiply(object); + }; + +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global){ + 'use strict'; + + var fabric = global.fabric; + + /** + * Color Blend filter class + * @class fabric.Image.filter.Blend + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @example + * var filter = new fabric.Image.filters.Blend({ + * color: '#000', + * mode: 'multiply' + * }); + * + * var filter = new fabric.Image.filters.Blend({ + * image: fabricImageObject, + * mode: 'multiply', + * alpha: 0.5 + * }); + + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Blend = fabric.util.createClass({ + type: 'Blend', + + initialize: function(options){ + options = options || {}; + this.color = options.color || '#000'; + this.image = options.image || false; + this.mode = options.mode || 'multiply'; + this.alpha = options.alpha || 1; + }, + + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + tr, tg, tb, + r, g, b, + source, + isImage = false; + + if (this.image) { + // Blend images + isImage = true; + + var _el = fabric.util.createCanvasElement(); + _el.width = this.image.width; + _el.height = this.image.height; + + var tmpCanvas = new fabric.StaticCanvas(_el); + tmpCanvas.add(this.image); + var context2 = tmpCanvas.getContext('2d'); + source = context2.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height).data; + } + else { + // Blend color + source = new fabric.Color(this.color).getSource(); + + tr = source[0] * this.alpha; + tg = source[1] * this.alpha; + tb = source[2] * this.alpha; + } + + for (var i = 0, len = data.length; i < len; i += 4) { + + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + if (isImage) { + tr = source[i] * this.alpha; + tg = source[i + 1] * this.alpha; + tb = source[i + 2] * this.alpha; + } + + switch (this.mode) { + case 'multiply': + data[i] = r * tr / 255; + data[i + 1] = g * tg / 255; + data[i + 2] = b * tb / 255; + break; + case 'screen': + data[i] = 1 - (1 - r) * (1 - tr); + data[i + 1] = 1 - (1 - g) * (1 - tg); + data[i + 2] = 1 - (1 - b) * (1 - tb); + break; + case 'add': + data[i] = Math.min(255, r + tr); + data[i + 1] = Math.min(255, g + tg); + data[i + 2] = Math.min(255, b + tb); + break; + case 'diff': + case 'difference': + data[i] = Math.abs(r - tr); + data[i + 1] = Math.abs(g - tg); + data[i + 2] = Math.abs(b - tb); + break; + case 'subtract': + var _r = r-tr; + var _g = g-tg; + var _b = b-tb; + + data[i] = (_r < 0) ? 0 : _r; + data[i + 1] = (_g < 0) ? 0 : _g; + data[i + 2] = (_b < 0) ? 0 : _b; + break; + case 'darken': + data[i] = Math.min(r, tr); + data[i + 1] = Math.min(g, tg); + data[i + 2] = Math.min(b, tb); + break; + case 'lighten': + data[i] = Math.max(r, tr); + data[i + 1] = Math.max(g, tg); + data[i + 2] = Math.max(b, tb); + break; + } + } + + context.putImageData(imageData, 0, 0); + } + }); + + fabric.Image.filters.Blend.fromObject = function(object) { + return new fabric.Image.filters.Blend(object); + }; +})(typeof exports !== 'undefined' ? exports : this); + + +(function(global) { + + 'use strict'; + + var fabric = global.fabric || (global.fabric = { }), + extend = fabric.util.object.extend, + clone = fabric.util.object.clone, + toFixed = fabric.util.toFixed, + supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); + + if (fabric.Text) { + fabric.warn('fabric.Text is already defined'); + return; + } + + var stateProperties = fabric.Object.prototype.stateProperties.concat(); + stateProperties.push( + 'fontFamily', + 'fontWeight', + 'fontSize', + 'text', + 'textDecoration', + 'textAlign', + 'fontStyle', + 'lineHeight', + 'textBackgroundColor', + 'useNative', + 'path' + ); + + /** + * Text class + * @class fabric.Text + * @extends fabric.Object + * @return {fabric.Text} thisArg + * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#text} + * @see {@link fabric.Text#initialize} for constructor definition + */ + fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ { + + /** + * Properties which when set cause object to change dimensions + * @type Object + * @private + */ + _dimensionAffectingProps: { + fontSize: true, + fontWeight: true, + fontFamily: true, + textDecoration: true, + fontStyle: true, + lineHeight: true, + stroke: true, + strokeWidth: true, + text: true + }, + + /** + * @private + */ + _reNewline: /\r?\n/, + + /** + * Retrieves object's fontSize + * @method getFontSize + * @memberOf fabric.Text.prototype + * @return {String} Font size (in pixels) + */ + + /** + * Sets object's fontSize + * @method setFontSize + * @memberOf fabric.Text.prototype + * @param {Number} fontSize Font size (in pixels) + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontWeight + * @method getFontWeight + * @memberOf fabric.Text.prototype + * @return {(String|Number)} Font weight + */ + + /** + * Sets object's fontWeight + * @method setFontWeight + * @memberOf fabric.Text.prototype + * @param {(Number|String)} fontWeight Font weight + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontFamily + * @method getFontFamily + * @memberOf fabric.Text.prototype + * @return {String} Font family + */ + + /** + * Sets object's fontFamily + * @method setFontFamily + * @memberOf fabric.Text.prototype + * @param {String} fontFamily Font family + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's text + * @method getText + * @memberOf fabric.Text.prototype + * @return {String} text + */ + + /** + * Sets object's text + * @method setText + * @memberOf fabric.Text.prototype + * @param {String} text Text + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textDecoration + * @method getTextDecoration + * @memberOf fabric.Text.prototype + * @return {String} Text decoration + */ + + /** + * Sets object's textDecoration + * @method setTextDecoration + * @memberOf fabric.Text.prototype + * @param {String} textDecoration Text decoration + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's fontStyle + * @method getFontStyle + * @memberOf fabric.Text.prototype + * @return {String} Font style + */ + + /** + * Sets object's fontStyle + * @method setFontStyle + * @memberOf fabric.Text.prototype + * @param {String} fontStyle Font style + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's lineHeight + * @method getLineHeight + * @memberOf fabric.Text.prototype + * @return {Number} Line height + */ + + /** + * Sets object's lineHeight + * @method setLineHeight + * @memberOf fabric.Text.prototype + * @param {Number} lineHeight Line height + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textAlign + * @method getTextAlign + * @memberOf fabric.Text.prototype + * @return {String} Text alignment + */ + + /** + * Sets object's textAlign + * @method setTextAlign + * @memberOf fabric.Text.prototype + * @param {String} textAlign Text alignment + * @return {fabric.Text} + * @chainable + */ + + /** + * Retrieves object's textBackgroundColor + * @method getTextBackgroundColor + * @memberOf fabric.Text.prototype + * @return {String} Text background color + */ + + /** + * Sets object's textBackgroundColor + * @method setTextBackgroundColor + * @memberOf fabric.Text.prototype + * @param {String} textBackgroundColor Text background color + * @return {fabric.Text} + * @chainable + */ + + /** + * Type of an object + * @type String + * @default + */ + type: 'text', + + /** + * Font size (in pixels) + * @type Number + * @default + */ + fontSize: 40, + + /** + * Font weight (e.g. bold, normal, 400, 600, 800) + * @type {(Number|String)} + * @default + */ + fontWeight: 'normal', + + /** + * Font family + * @type String + * @default + */ + fontFamily: 'Times New Roman', + + /** + * Text decoration Possible values: "", "underline", "overline" or "line-through". + * @type String + * @default + */ + textDecoration: '', + + /** + * Text alignment. Possible values: "left", "center", or "right". + * @type String + * @default + */ + textAlign: 'left', + + /** + * Font style . Possible values: "", "normal", "italic" or "oblique". + * @type String + * @default + */ + fontStyle: '', + + /** + * Line height + * @type Number + * @default + */ + lineHeight: 1.3, + + /** + * Background color of text lines + * @type String + * @default + */ + textBackgroundColor: '', + + /** + * URL of a font file, when using Cufon + * @type String | null + * @default + */ + path: null, + + /** + * Indicates whether canvas native text methods should be used to render text (otherwise, Cufon is used) + * @type Boolean + * @default + */ + useNative: true, + + /** + * List of properties to consider when checking if + * state of an object is changed ({@link fabric.Object#hasStateChanged}) + * as well as for history (undo/redo) purposes + * @type Array + */ + stateProperties: stateProperties, + + /** + * When defined, an object is rendered via stroke and this property specifies its color. + * Backwards incompatibility note: This property was named "strokeStyle" until v1.1.6 + * @type String + * @default + */ + stroke: null, + + /** + * Shadow object representing shadow of this shape. + * Backwards incompatibility note: This property was named "textShadow" (String) until v1.2.11 + * @type fabric.Shadow + * @default + */ + shadow: null, + + /** + * Constructor + * @param {String} text Text string + * @param {Object} [options] Options object + * @return {fabric.Text} thisArg + */ + initialize: function(text, options) { + options = options || { }; + + this.text = text; + this.__skipDimension = true; + this.setOptions(options); + this.__skipDimension = false; + this._initDimensions(); + }, + + /** + * Renders text object on offscreen canvas, so that it would get dimensions + * @private + */ + _initDimensions: function() { + if (this.__skipDimension) { + return; + } + var canvasEl = fabric.util.createCanvasElement(); + this._render(canvasEl.getContext('2d')); + }, + + /** + * Returns string representation of an instance + * @return {String} String representation of text object + */ + toString: function() { + return '#'; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + + if (typeof Cufon === 'undefined' || this.useNative === true) { + this._renderViaNative(ctx); + } + else { + this._renderViaCufon(ctx); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderViaNative: function(ctx) { + var textLines = this.text.split(this._reNewline); + + this._setTextStyles(ctx); + + this.width = this._getTextWidth(ctx, textLines); + this.height = this._getTextHeight(ctx, textLines); + + this.clipTo && fabric.util.clipContext(this, ctx); + + this._renderTextBackground(ctx, textLines); + this._translateForTextAlign(ctx); + this._renderText(ctx, textLines); + + if (this.textAlign !== 'left' && this.textAlign !== 'justify') { + ctx.restore(); + } + + this._renderTextDecoration(ctx, textLines); + this.clipTo && ctx.restore(); + + this._setBoundaries(ctx, textLines); + this._totalLineHeight = 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderText: function(ctx, textLines) { + ctx.save(); + this._setShadow(ctx); + this._setupFillRule(ctx); + this._renderTextFill(ctx, textLines); + this._renderTextStroke(ctx, textLines); + this._restoreFillRule(ctx); + this._removeShadow(ctx); + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _translateForTextAlign: function(ctx) { + if (this.textAlign !== 'left' && this.textAlign !== 'justify') { + ctx.save(); + ctx.translate(this.textAlign === 'center' ? (this.width / 2) : this.width, 0); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _setBoundaries: function(ctx, textLines) { + this._boundaries = [ ]; + + for (var i = 0, len = textLines.length; i < len; i++) { + + var lineWidth = this._getLineWidth(ctx, textLines[i]), + lineLeftOffset = this._getLineLeftOffset(lineWidth); + + this._boundaries.push({ + height: this.fontSize * this.lineHeight, + width: lineWidth, + left: lineLeftOffset + }); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _setTextStyles: function(ctx) { + this._setFillStyles(ctx); + this._setStrokeStyles(ctx); + ctx.textBaseline = 'alphabetic'; + if (!this.skipTextAlign) { + ctx.textAlign = this.textAlign; + } + ctx.font = this._getFontDeclaration(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + * @return {Number} Height of fabric.Text object + */ + _getTextHeight: function(ctx, textLines) { + return this.fontSize * textLines.length * this.lineHeight; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + * @return {Number} Maximum width of fabric.Text object + */ + _getTextWidth: function(ctx, textLines) { + var maxWidth = ctx.measureText(textLines[0] || '|').width; + + for (var i = 1, len = textLines.length; i < len; i++) { + var currentLineWidth = ctx.measureText(textLines[i]).width; + if (currentLineWidth > maxWidth) { + maxWidth = currentLineWidth; + } + } + return maxWidth; + }, + + /** + * @private + * @param {String} method Method name ("fillText" or "strokeText") + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} chars Chars to render + * @param {Number} left Left position of text + * @param {Number} top Top position of text + */ + _renderChars: function(method, ctx, chars, left, top) { + ctx[method](chars, left, top); + }, + + /** + * @private + * @param {String} method Method name ("fillText" or "strokeText") + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Text to render + * @param {Number} left Left position of text + * @param {Number} top Top position of text + * @param {Number} lineIndex Index of a line in a text + */ + _renderTextLine: function(method, ctx, line, left, top, lineIndex) { + // lift the line by quarter of fontSize + top -= this.fontSize / 4; + + // short-circuit + if (this.textAlign !== 'justify') { + this._renderChars(method, ctx, line, left, top, lineIndex); + return; + } + + var lineWidth = ctx.measureText(line).width, + totalWidth = this.width; + + if (totalWidth > lineWidth) { + // stretch the line + var words = line.split(/\s+/), + wordsWidth = ctx.measureText(line.replace(/\s+/g, '')).width, + widthDiff = totalWidth - wordsWidth, + numSpaces = words.length - 1, + spaceWidth = widthDiff / numSpaces, + leftOffset = 0; + + for (var i = 0, len = words.length; i < len; i++) { + this._renderChars(method, ctx, words[i], left + leftOffset, top, lineIndex); + leftOffset += ctx.measureText(words[i]).width + spaceWidth; + } + } + else { + this._renderChars(method, ctx, line, left, top, lineIndex); + } + }, + + /** + * @private + * @return {Number} Left offset + */ + _getLeftOffset: function() { + if (fabric.isLikelyNode) { + return 0; + } + return -this.width / 2; + }, + + /** + * @private + * @return {Number} Top offset + */ + _getTopOffset: function() { + return -this.height / 2; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextFill: function(ctx, textLines) { + if (!this.fill && !this._skipFillStrokeCheck) { + return; + } + + this._boundaries = [ ]; + var lineHeights = 0; + + for (var i = 0, len = textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i, textLines); + lineHeights += heightOfLine; + + this._renderTextLine( + 'fillText', + ctx, + textLines[i], + this._getLeftOffset(), + this._getTopOffset() + lineHeights, + i + ); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextStroke: function(ctx, textLines) { + if ((!this.stroke || this.strokeWidth === 0) && !this._skipFillStrokeCheck) { + return; + } + + var lineHeights = 0; + + ctx.save(); + if (this.strokeDashArray) { + // Spec requires the concatenation of two copies the dash list when the number of elements is odd + if (1 & this.strokeDashArray.length) { + this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); + } + supportsLineDash && ctx.setLineDash(this.strokeDashArray); + } + + ctx.beginPath(); + for (var i = 0, len = textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i, textLines); + lineHeights += heightOfLine; + + this._renderTextLine( + 'strokeText', + ctx, + textLines[i], + this._getLeftOffset(), + this._getTopOffset() + lineHeights, + i + ); + } + ctx.closePath(); + ctx.restore(); + }, + + _getHeightOfLine: function() { + return this.fontSize * this.lineHeight; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextBackground: function(ctx, textLines) { + this._renderTextBoxBackground(ctx); + this._renderTextLinesBackground(ctx, textLines); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderTextBoxBackground: function(ctx) { + if (!this.backgroundColor) { + return; + } + + ctx.save(); + ctx.fillStyle = this.backgroundColor; + + ctx.fillRect( + this._getLeftOffset(), + this._getTopOffset(), + this.width, + this.height + ); + + ctx.restore(); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextLinesBackground: function(ctx, textLines) { + if (!this.textBackgroundColor) { + return; + } + + ctx.save(); + ctx.fillStyle = this.textBackgroundColor; + + for (var i = 0, len = textLines.length; i < len; i++) { + + if (textLines[i] !== '') { + + var lineWidth = this._getLineWidth(ctx, textLines[i]), + lineLeftOffset = this._getLineLeftOffset(lineWidth); + + ctx.fillRect( + this._getLeftOffset() + lineLeftOffset, + this._getTopOffset() + (i * this.fontSize * this.lineHeight), + lineWidth, + this.fontSize * this.lineHeight + ); + } + } + ctx.restore(); + }, + + /** + * @private + * @param {Number} lineWidth Width of text line + * @return {Number} Line left offset + */ + _getLineLeftOffset: function(lineWidth) { + if (this.textAlign === 'center') { + return (this.width - lineWidth) / 2; + } + if (this.textAlign === 'right') { + return this.width - lineWidth; + } + return 0; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Text line + * @return {Number} Line width + */ + _getLineWidth: function(ctx, line) { + return this.textAlign === 'justify' + ? this.width + : ctx.measureText(line).width; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextDecoration: function(ctx, textLines) { + if (!this.textDecoration) { + return; + } + + // var halfOfVerticalBox = this.originY === 'top' ? 0 : this._getTextHeight(ctx, textLines) / 2; + var halfOfVerticalBox = this._getTextHeight(ctx, textLines) / 2, + _this = this; + + /** @ignore */ + function renderLinesAtOffset(offset) { + for (var i = 0, len = textLines.length; i < len; i++) { + + var lineWidth = _this._getLineWidth(ctx, textLines[i]), + lineLeftOffset = _this._getLineLeftOffset(lineWidth); + + ctx.fillRect( + _this._getLeftOffset() + lineLeftOffset, + ~~((offset + (i * _this._getHeightOfLine(ctx, i, textLines))) - halfOfVerticalBox), + lineWidth, + 1); + } + } + + if (this.textDecoration.indexOf('underline') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight); + } + if (this.textDecoration.indexOf('line-through') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize / 2); + } + if (this.textDecoration.indexOf('overline') > -1) { + renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize); + } + }, + + /** + * @private + */ + _getFontDeclaration: function() { + return [ + // node-canvas needs "weight style", while browsers need "style weight" + (fabric.isLikelyNode ? this.fontWeight : this.fontStyle), + (fabric.isLikelyNode ? this.fontStyle : this.fontWeight), + this.fontSize + 'px', + (fabric.isLikelyNode ? ('"' + this.fontFamily + '"') : this.fontFamily) + ].join(' '); + }, + + /** + * Renders text instance on a specified context + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + render: function(ctx, noTransform) { + // do not render if object is not visible + if (!this.visible) { + return; + } + + ctx.save(); + this._transform(ctx, noTransform); + + var m = this.transformMatrix, + isInPathGroup = this.group && this.group.type === 'path-group'; + + if (isInPathGroup) { + ctx.translate(-this.group.width/2, -this.group.height/2); + } + if (m) { + ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + } + if (isInPathGroup) { + ctx.translate(this.left, this.top); + } + this._render(ctx); + ctx.restore(); + }, + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject: function(propertiesToInclude) { + var object = extend(this.callSuper('toObject', propertiesToInclude), { + text: this.text, + fontSize: this.fontSize, + fontWeight: this.fontWeight, + fontFamily: this.fontFamily, + fontStyle: this.fontStyle, + lineHeight: this.lineHeight, + textDecoration: this.textDecoration, + textAlign: this.textAlign, + path: this.path, + textBackgroundColor: this.textBackgroundColor, + useNative: this.useNative + }); + if (!this.includeDefaultValues) { + this._removeDefaultValues(object); + } + return object; + }, + + /* _TO_SVG_START_ */ + /** + * Returns SVG representation of an instance + * @param {Function} [reviver] Method for further parsing of svg representation. + * @return {String} svg representation of an instance + */ + toSVG: function(reviver) { + var markup = [ ], + textLines = this.text.split(this._reNewline), + offsets = this._getSVGLeftTopOffsets(textLines), + textAndBg = this._getSVGTextAndBg(offsets.lineTop, offsets.textLeft, textLines), + shadowSpans = this._getSVGShadows(offsets.lineTop, textLines); + + // move top offset by an ascent + offsets.textTop += (this._fontAscent ? ((this._fontAscent / 5) * this.lineHeight) : 0); + + this._wrapSVGTextAndBg(markup, textAndBg, shadowSpans, offsets); + + return reviver ? reviver(markup.join('')) : markup.join(''); + }, + + /** + * @private + */ + _getSVGLeftTopOffsets: function(textLines) { + var lineTop = this.useNative + ? this.fontSize * this.lineHeight + : (-this._fontAscent - ((this._fontAscent / 5) * this.lineHeight)), + + textLeft = -(this.width/2), + textTop = this.useNative + ? this.fontSize - 1 + : (this.height/2) - (textLines.length * this.fontSize) - this._totalLineHeight; + + return { + textLeft: textLeft + (this.group ? this.left : 0), + textTop: textTop + (this.group ? this.top : 0), + lineTop: lineTop + }; + }, + + /** + * @private + */ + _wrapSVGTextAndBg: function(markup, textAndBg, shadowSpans, offsets) { + markup.push( + '\n', + textAndBg.textBgRects.join(''), + '', + shadowSpans.join(''), + textAndBg.textSpans.join(''), + '\n', + '\n' + ); + }, + + /** + * @private + * @param {Number} lineHeight + * @param {Array} textLines Array of all text lines + * @return {Array} + */ + _getSVGShadows: function(lineHeight, textLines) { + var shadowSpans = [], + i, len, + lineTopOffsetMultiplier = 1; + + if (!this.shadow || !this._boundaries) { + return shadowSpans; + } + + for (i = 0, len = textLines.length; i < len; i++) { + if (textLines[i] !== '') { + var lineLeftOffset = (this._boundaries && this._boundaries[i]) ? this._boundaries[i].left : 0; + shadowSpans.push( + '', + fabric.util.string.escapeXml(textLines[i]), + ''); + lineTopOffsetMultiplier = 1; + } + else { + // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier + // prevents empty tspans + lineTopOffsetMultiplier++; + } + } + + return shadowSpans; + }, + + /** + * @private + * @param {Number} lineHeight + * @param {Number} textLeftOffset Text left offset + * @param {Array} textLines Array of all text lines + * @return {Object} + */ + _getSVGTextAndBg: function(lineHeight, textLeftOffset, textLines) { + var textSpans = [ ], + textBgRects = [ ], + lineTopOffsetMultiplier = 1; + + // bounding-box background + this._setSVGBg(textBgRects); + + // text and text-background + for (var i = 0, len = textLines.length; i < len; i++) { + if (textLines[i] !== '') { + this._setSVGTextLineText(textLines[i], i, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects); + lineTopOffsetMultiplier = 1; + } + else { + // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier + // prevents empty tspans + lineTopOffsetMultiplier++; + } + + if (!this.textBackgroundColor || !this._boundaries) { + continue; + } + + this._setSVGTextLineBg(textBgRects, i, textLeftOffset, lineHeight); + } + + return { + textSpans: textSpans, + textBgRects: textBgRects + }; + }, + + _setSVGTextLineText: function(textLine, i, textSpans, lineHeight, lineTopOffsetMultiplier) { + var lineLeftOffset = (this._boundaries && this._boundaries[i]) + ? toFixed(this._boundaries[i].left, 2) + : 0; + + textSpans.push( + ' elements since setting opacity + // on containing one doesn't work in Illustrator + this._getFillAttributes(this.fill), '>', + fabric.util.string.escapeXml(textLine), + '' + ); + }, + + _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, lineHeight) { + textBgRects.push( + '\n'); + }, + + _setSVGBg: function(textBgRects) { + if (this.backgroundColor && this._boundaries) { + textBgRects.push( + ''); + } + }, + + /** + * Adobe Illustrator (at least CS5) is unable to render rgba()-based fill values + * we work around it by "moving" alpha channel into opacity attribute and setting fill's alpha to 1 + * + * @private + * @param {Any} value + * @return {String} + */ + _getFillAttributes: function(value) { + var fillColor = (value && typeof value === 'string') ? new fabric.Color(value) : ''; + if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) { + return 'fill="' + value + '"'; + } + return 'opacity="' + fillColor.getAlpha() + '" fill="' + fillColor.setAlpha(1).toRgb() + '"'; + }, + /* _TO_SVG_END_ */ + + /** + * Sets specified property to a specified value + * @param {String} key + * @param {Any} value + * @return {fabric.Text} thisArg + * @chainable + */ + _set: function(key, value) { + if (key === 'fontFamily' && this.path) { + this.path = this.path.replace(/(.*?)([^\/]*)(\.font\.js)/, '$1' + value + '$3'); + } + this.callSuper('_set', key, value); + + if (key in this._dimensionAffectingProps) { + this._initDimensions(); + this.setCoords(); + } + }, + + /** + * Returns complexity of an instance + * @return {Number} complexity + */ + complexity: function() { + return 1; + } + }); + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement}) + * @static + * @memberOf fabric.Text + * @see: http://www.w3.org/TR/SVG/text.html#TextElement + */ + fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat( + 'x y dx dy font-family font-style font-weight font-size text-decoration text-anchor'.split(' ')); + + /** + * Default SVG font size + * @static + * @memberOf fabric.Text + */ + fabric.Text.DEFAULT_SVG_FONT_SIZE = 16; + + /** + * Returns fabric.Text instance from an SVG element (not yet implemented) + * @static + * @memberOf fabric.Text + * @param {SVGElement} element Element to parse + * @param {Object} [options] Options object + * @return {fabric.Text} Instance of fabric.Text + */ + fabric.Text.fromElement = function(element, options) { + if (!element) { + return null; + } + + var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES); + options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes); + + if ('dx' in parsedAttributes) { + options.left += parsedAttributes.dx; + } + if ('dy' in parsedAttributes) { + options.top += parsedAttributes.dy; + } + if (!('fontSize' in options)) { + options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE; + } + + if (!options.originX) { + options.originX = 'left'; + } + + var text = new fabric.Text(element.textContent, options), + /* + Adjust positioning: + x/y attributes in SVG correspond to the bottom-left corner of text bounding box + top/left properties in Fabric correspond to center point of text bounding box + */ + offX = 0; + + if (text.originX === 'left') { + offX = text.getWidth() / 2; + } + if (text.originX === 'right') { + offX = -text.getWidth() / 2; + } + text.set({ + left: text.getLeft() + offX, + top: text.getTop() - text.getHeight() / 2 + }); + + return text; + }; + /* _FROM_SVG_END_ */ + + /** + * Returns fabric.Text instance from an object representation + * @static + * @memberOf fabric.Text + * @param {Object} object Object to create an instance from + * @return {fabric.Text} Instance of fabric.Text + */ + fabric.Text.fromObject = function(object) { + return new fabric.Text(object.text, clone(object)); + }; + + fabric.util.createAccessors(fabric.Text); + +})(typeof exports !== 'undefined' ? exports : this); + + +(function() { + + var clone = fabric.util.object.clone; + + /** + * IText class (introduced in v1.4) Events are also fired with "text:" + * prefix when observing canvas. + * @class fabric.IText + * @extends fabric.Text + * @mixes fabric.Observable + * + * @fires changed + * @fires selection:changed + * @fires editing:entered + * @fires editing:exited + * + * @return {fabric.IText} thisArg + * @see {@link fabric.IText#initialize} for constructor definition + * + *

    Supported key combinations:

    + *
    +    *   Move cursor:                    left, right, up, down
    +    *   Select character:               shift + left, shift + right
    +    *   Select text vertically:         shift + up, shift + down
    +    *   Move cursor by word:            alt + left, alt + right
    +    *   Select words:                   shift + alt + left, shift + alt + right
    +    *   Move cursor to line start/end:  cmd + left, cmd + right
    +    *   Select till start/end of line:  cmd + shift + left, cmd + shift + right
    +    *   Jump to start/end of text:      cmd + up, cmd + down
    +    *   Select till start/end of text:  cmd + shift + up, cmd + shift + down
    +    *   Delete character:               backspace
    +    *   Delete word:                    alt + backspace
    +    *   Delete line:                    cmd + backspace
    +    *   Forward delete:                 delete
    +    *   Copy text:                      ctrl/cmd + c
    +    *   Paste text:                     ctrl/cmd + v
    +    *   Cut text:                       ctrl/cmd + x
    +    *   Select entire text:             ctrl/cmd + a
    +    * 
    + * + *

    Supported mouse/touch combination

    + *
    +    *   Position cursor:                click/touch
    +    *   Create selection:               click/touch & drag
    +    *   Create selection:               click & shift + click
    +    *   Select word:                    double click
    +    *   Select line:                    triple click
    +    * 
    + */ + fabric.IText = fabric.util.createClass(fabric.Text, fabric.Observable, /** @lends fabric.IText.prototype */ { + + /** + * Type of an object + * @type String + * @default + */ + type: 'i-text', + + /** + * Index where text selection starts (or where cursor is when there is no selection) + * @type Nubmer + * @default + */ + selectionStart: 0, + + /** + * Index where text selection ends + * @type Nubmer + * @default + */ + selectionEnd: 0, + + /** + * Color of text selection + * @type String + * @default + */ + selectionColor: 'rgba(17,119,255,0.3)', + + /** + * Indicates whether text is in editing mode + * @type Boolean + * @default + */ + isEditing: false, + + /** + * Indicates whether a text can be edited + * @type Boolean + * @default + */ + editable: true, + + /** + * Border color of text object while it's in editing mode + * @type String + * @default + */ + editingBorderColor: 'rgba(102,153,255,0.25)', + + /** + * Width of cursor (in px) + * @type Number + * @default + */ + cursorWidth: 2, + + /** + * Color of default cursor (when not overwritten by character style) + * @type String + * @default + */ + cursorColor: '#333', + + /** + * Delay between cursor blink (in ms) + * @type Number + * @default + */ + cursorDelay: 1000, + + /** + * Duration of cursor fadein (in ms) + * @type Number + * @default + */ + cursorDuration: 600, + + /** + * Object containing character styles + * (where top-level properties corresponds to line number and 2nd-level properties -- to char number in a line) + * @type Object + * @default + */ + styles: null, + + /** + * Indicates whether internal text char widths can be cached + * @type Boolean + * @default + */ + caching: true, + + /** + * @private + * @type Boolean + * @default + */ + _skipFillStrokeCheck: true, + + /** + * @private + */ + _reSpace: /\s|\n/, + + /** + * @private + */ + _fontSizeFraction: 4, + + /** + * @private + */ + _currentCursorOpacity: 0, + + /** + * @private + */ + _selectionDirection: null, + + /** + * @private + */ + _abortCursorAnimation: false, + + /** + * @private + */ + _charWidthsCache: { }, + + /** + * Constructor + * @param {String} text Text string + * @param {Object} [options] Options object + * @return {fabric.IText} thisArg + */ + initialize: function(text, options) { + this.styles = options ? (options.styles || { }) : { }; + this.callSuper('initialize', text, options); + this.initBehavior(); + + fabric.IText.instances.push(this); + + // caching + this.__lineWidths = { }; + this.__lineHeights = { }; + this.__lineOffsets = { }; + }, + + /** + * Returns true if object has no styling + */ + isEmptyStyles: function() { + if (!this.styles) { + return true; + } + var obj = this.styles; + + for (var p1 in obj) { + for (var p2 in obj[p1]) { + /*jshint unused:false */ + for (var p3 in obj[p1][p2]) { + return false; + } + } + } + return true; + }, + + /** + * Sets selection start (left boundary of a selection) + * @param {Number} index Index to set selection start to + */ + setSelectionStart: function(index) { + if (this.selectionStart !== index) { + this.fire('selection:changed'); + this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + } + this.selectionStart = index; + this.hiddenTextarea && (this.hiddenTextarea.selectionStart = index); + }, + + /** + * Sets selection end (right boundary of a selection) + * @param {Number} index Index to set selection end to + */ + setSelectionEnd: function(index) { + if (this.selectionEnd !== index) { + this.fire('selection:changed'); + this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + } + this.selectionEnd = index; + this.hiddenTextarea && (this.hiddenTextarea.selectionEnd = index); + }, + + /** + * Gets style of a current selection/cursor (at the start position) + * @param {Number} [startIndex] Start index to get styles at + * @param {Number} [endIndex] End index to get styles at + * @return {Object} styles Style object at a specified (or current) index + */ + getSelectionStyles: function(startIndex, endIndex) { + + if (arguments.length === 2) { + var styles = [ ]; + for (var i = startIndex; i < endIndex; i++) { + styles.push(this.getSelectionStyles(i)); + } + return styles; + } + + var loc = this.get2DCursorLocation(startIndex); + if (this.styles[loc.lineIndex]) { + return this.styles[loc.lineIndex][loc.charIndex] || { }; + } + + return { }; + }, + + /** + * Sets style of a current selection + * @param {Object} [styles] Styles object + * @return {fabric.IText} thisArg + * @chainable + */ + setSelectionStyles: function(styles) { + if (this.selectionStart === this.selectionEnd) { + this._extendStyles(this.selectionStart, styles); + } + else { + for (var i = this.selectionStart; i < this.selectionEnd; i++) { + this._extendStyles(i, styles); + } + } + return this; + }, + + /** + * @private + */ + _extendStyles: function(index, styles) { + var loc = this.get2DCursorLocation(index); + + if (!this.styles[loc.lineIndex]) { + this.styles[loc.lineIndex] = { }; + } + if (!this.styles[loc.lineIndex][loc.charIndex]) { + this.styles[loc.lineIndex][loc.charIndex] = { }; + } + + fabric.util.object.extend(this.styles[loc.lineIndex][loc.charIndex], styles); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render: function(ctx) { + this.callSuper('_render', ctx); + this.ctx = ctx; + this.isEditing && this.renderCursorOrSelection(); + }, + + /** + * Renders cursor or selection (depending on what exists) + */ + renderCursorOrSelection: function() { + if (!this.active) { + return; + } + + var chars = this.text.split(''), + boundaries; + + if (this.selectionStart === this.selectionEnd) { + boundaries = this._getCursorBoundaries(chars, 'cursor'); + this.renderCursor(boundaries); + } + else { + boundaries = this._getCursorBoundaries(chars, 'selection'); + this.renderSelection(chars, boundaries); + } + }, + + /** + * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start) + * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used. + */ + get2DCursorLocation: function(selectionStart) { + if (typeof selectionStart === 'undefined') { + selectionStart = this.selectionStart; + } + var textBeforeCursor = this.text.slice(0, selectionStart), + linesBeforeCursor = textBeforeCursor.split(this._reNewline); + + return { + lineIndex: linesBeforeCursor.length - 1, + charIndex: linesBeforeCursor[linesBeforeCursor.length - 1].length + }; + }, + + /** + * Returns complete style of char at the current cursor + * @param {Number} lineIndex Line index + * @param {Number} charIndex Char index + * @return {Object} Character style + */ + getCurrentCharStyle: function(lineIndex, charIndex) { + var style = this.styles[lineIndex] && this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)]; + + return { + fontSize: style && style.fontSize || this.fontSize, + fill: style && style.fill || this.fill, + textBackgroundColor: style && style.textBackgroundColor || this.textBackgroundColor, + textDecoration: style && style.textDecoration || this.textDecoration, + fontFamily: style && style.fontFamily || this.fontFamily, + fontWeight: style && style.fontWeight || this.fontWeight, + fontStyle: style && style.fontStyle || this.fontStyle, + stroke: style && style.stroke || this.stroke, + strokeWidth: style && style.strokeWidth || this.strokeWidth + }; + }, + + /** + * Returns fontSize of char at the current cursor + * @param {Number} lineIndex Line index + * @param {Number} charIndex Char index + * @return {Number} Character font size + */ + getCurrentCharFontSize: function(lineIndex, charIndex) { + return ( + this.styles[lineIndex] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)].fontSize) || this.fontSize; + }, + + /** + * Returns color (fill) of char at the current cursor + * @param {Number} lineIndex Line index + * @param {Number} charIndex Char index + * @return {String} Character color (fill) + */ + getCurrentCharColor: function(lineIndex, charIndex) { + return ( + this.styles[lineIndex] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)] && + this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)].fill) || this.cursorColor; + }, + + /** + * Returns cursor boundaries (left, top, leftOffset, topOffset) + * @private + * @param {Array} chars Array of characters + * @param {String} typeOfBoundaries + */ + _getCursorBoundaries: function(chars, typeOfBoundaries) { + + var cursorLocation = this.get2DCursorLocation(), + + textLines = this.text.split(this._reNewline), + + // left/top are left/top of entire text box + // leftOffset/topOffset are offset from that left/top point of a text box + + left = Math.round(this._getLeftOffset()), + top = -this.height / 2, + + offsets = this._getCursorBoundariesOffsets( + chars, typeOfBoundaries, cursorLocation, textLines); + + return { + left: left, + top: top, + leftOffset: offsets.left + offsets.lineLeft, + topOffset: offsets.top + }; + }, + + /** + * @private + */ + _getCursorBoundariesOffsets: function(chars, typeOfBoundaries, cursorLocation, textLines) { + + var lineLeftOffset = 0, + + lineIndex = 0, + charIndex = 0, + + leftOffset = 0, + topOffset = typeOfBoundaries === 'cursor' + // selection starts at the very top of the line, + // whereas cursor starts at the padding created by line height + ? (this._getHeightOfLine(this.ctx, 0) - + this.getCurrentCharFontSize(cursorLocation.lineIndex, cursorLocation.charIndex)) + : 0; + + for (var i = 0; i < this.selectionStart; i++) { + if (chars[i] === '\n') { + leftOffset = 0; + var index = lineIndex + (typeOfBoundaries === 'cursor' ? 1 : 0); + topOffset += this._getCachedLineHeight(index); + + lineIndex++; + charIndex = 0; + } + else { + leftOffset += this._getWidthOfChar(this.ctx, chars[i], lineIndex, charIndex); + charIndex++; + } + + lineLeftOffset = this._getCachedLineOffset(lineIndex, textLines); + } + + this._clearCache(); + + return { + top: topOffset, + left: leftOffset, + lineLeft: lineLeftOffset + }; + }, + + /** + * @private + */ + _clearCache: function() { + this.__lineWidths = { }; + this.__lineHeights = { }; + this.__lineOffsets = { }; + }, + + /** + * @private + */ + _getCachedLineHeight: function(index) { + return this.__lineHeights[index] || + (this.__lineHeights[index] = this._getHeightOfLine(this.ctx, index)); + }, + + /** + * @private + */ + _getCachedLineWidth: function(lineIndex, textLines) { + return this.__lineWidths[lineIndex] || + (this.__lineWidths[lineIndex] = this._getWidthOfLine(this.ctx, lineIndex, textLines)); + }, + + /** + * @private + */ + _getCachedLineOffset: function(lineIndex, textLines) { + var widthOfLine = this._getCachedLineWidth(lineIndex, textLines); + + return this.__lineOffsets[lineIndex] || + (this.__lineOffsets[lineIndex] = this._getLineLeftOffset(widthOfLine)); + }, + + /** + * Renders cursor + * @param {Object} boundaries + */ + renderCursor: function(boundaries) { + var ctx = this.ctx; + + ctx.save(); + + var cursorLocation = this.get2DCursorLocation(), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex, + charHeight = this.getCurrentCharFontSize(lineIndex, charIndex), + leftOffset = (lineIndex === 0 && charIndex === 0) + ? this._getCachedLineOffset(lineIndex, this.text.split(this._reNewline)) + : boundaries.leftOffset; + + ctx.fillStyle = this.getCurrentCharColor(lineIndex, charIndex); + ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity; + + ctx.fillRect( + boundaries.left + leftOffset, + boundaries.top + boundaries.topOffset, + this.cursorWidth / this.scaleX, + charHeight); + + ctx.restore(); + }, + + /** + * Renders text selection + * @param {Array} chars Array of characters + * @param {Object} boundaries Object with left/top/leftOffset/topOffset + */ + renderSelection: function(chars, boundaries) { + var ctx = this.ctx; + + ctx.save(); + + ctx.fillStyle = this.selectionColor; + + var start = this.get2DCursorLocation(this.selectionStart), + end = this.get2DCursorLocation(this.selectionEnd), + startLine = start.lineIndex, + endLine = end.lineIndex, + textLines = this.text.split(this._reNewline); + + for (var i = startLine; i <= endLine; i++) { + var lineOffset = this._getCachedLineOffset(i, textLines) || 0, + lineHeight = this._getCachedLineHeight(i), + boxWidth = 0; + + if (i === startLine) { + for (var j = 0, len = textLines[i].length; j < len; j++) { + if (j >= start.charIndex && (i !== endLine || j < end.charIndex)) { + boxWidth += this._getWidthOfChar(ctx, textLines[i][j], i, j); + } + if (j < start.charIndex) { + lineOffset += this._getWidthOfChar(ctx, textLines[i][j], i, j); + } + } + } + else if (i > startLine && i < endLine) { + boxWidth += this._getCachedLineWidth(i, textLines) || 5; + } + else if (i === endLine) { + for (var j2 = 0, j2len = end.charIndex; j2 < j2len; j2++) { + boxWidth += this._getWidthOfChar(ctx, textLines[i][j2], i, j2); + } + } + + ctx.fillRect( + boundaries.left + lineOffset, + boundaries.top + boundaries.topOffset, + boxWidth, + lineHeight); + + boundaries.topOffset += lineHeight; + } + ctx.restore(); + }, + + /** + * @private + * @param {String} method + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderChars: function(method, ctx, line, left, top, lineIndex) { + + if (this.isEmptyStyles()) { + return this._renderCharsFast(method, ctx, line, left, top); + } + + this.skipTextAlign = true; + + // set proper box offset + left -= this.textAlign === 'center' + ? (this.width / 2) + : (this.textAlign === 'right') + ? this.width + : 0; + + // set proper line offset + var textLines = this.text.split(this._reNewline), + lineWidth = this._getWidthOfLine(ctx, lineIndex, textLines), + lineHeight = this._getHeightOfLine(ctx, lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(lineWidth), + chars = line.split(''), + prevStyle, + charsToRender = ''; + + left += lineLeftOffset || 0; + + ctx.save(); + + for (var i = 0, len = chars.length; i <= len; i++) { + prevStyle = prevStyle || this.getCurrentCharStyle(lineIndex, i); + var thisStyle = this.getCurrentCharStyle(lineIndex, i + 1); + + if (this._hasStyleChanged(prevStyle, thisStyle) || i === len) { + this._renderChar(method, ctx, lineIndex, i - 1, charsToRender, left, top, lineHeight); + charsToRender = ''; + prevStyle = thisStyle; + } + charsToRender += chars[i]; + } + + ctx.restore(); + }, + + /** + * @private + * @param {String} method + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line Content of the line + * @param {Number} left Left coordinate + * @param {Number} top Top coordinate + */ + _renderCharsFast: function(method, ctx, line, left, top) { + this.skipTextAlign = false; + + if (method === 'fillText' && this.fill) { + this.callSuper('_renderChars', method, ctx, line, left, top); + } + if (method === 'strokeText' && this.stroke) { + this.callSuper('_renderChars', method, ctx, line, left, top); + } + }, + + /** + * @private + * @param {String} method + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Number} lineIndex + * @param {Number} i + * @param {String} _char + * @param {Number} left Left coordinate + * @param {Number} top Top coordinate + * @param {Number} lineHeight Height of the line + */ + _renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) { + var decl, charWidth, charHeight; + + if (this.styles && this.styles[lineIndex] && (decl = this.styles[lineIndex][i])) { + + var shouldStroke = decl.stroke || this.stroke, + shouldFill = decl.fill || this.fill; + + ctx.save(); + charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i, decl); + charHeight = this._getHeightOfChar(ctx, _char, lineIndex, i); + + if (shouldFill) { + ctx.fillText(_char, left, top); + } + if (shouldStroke) { + ctx.strokeText(_char, left, top); + } + + this._renderCharDecoration(ctx, decl, left, top, charWidth, lineHeight, charHeight); + ctx.restore(); + + ctx.translate(charWidth, 0); + } + else { + if (method === 'strokeText' && this.stroke) { + ctx[method](_char, left, top); + } + if (method === 'fillText' && this.fill) { + ctx[method](_char, left, top); + } + charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i); + this._renderCharDecoration(ctx, null, left, top, charWidth, lineHeight); + + ctx.translate(ctx.measureText(_char).width, 0); + } + }, + + /** + * @private + * @param {Object} prevStyle + * @param {Object} thisStyle + */ + _hasStyleChanged: function(prevStyle, thisStyle) { + return (prevStyle.fill !== thisStyle.fill || + prevStyle.fontSize !== thisStyle.fontSize || + prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor || + prevStyle.textDecoration !== thisStyle.textDecoration || + prevStyle.fontFamily !== thisStyle.fontFamily || + prevStyle.fontWeight !== thisStyle.fontWeight || + prevStyle.fontStyle !== thisStyle.fontStyle || + prevStyle.stroke !== thisStyle.stroke || + prevStyle.strokeWidth !== thisStyle.strokeWidth + ); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderCharDecoration: function(ctx, styleDeclaration, left, top, charWidth, lineHeight, charHeight) { + + var textDecoration = styleDeclaration + ? (styleDeclaration.textDecoration || this.textDecoration) + : this.textDecoration, + + fontSize = (styleDeclaration ? styleDeclaration.fontSize : null) || this.fontSize; + + if (!textDecoration) { + return; + } + + if (textDecoration.indexOf('underline') > -1) { + this._renderCharDecorationAtOffset( + ctx, + left, + top + (this.fontSize / this._fontSizeFraction), + charWidth, + 0, + this.fontSize / 20 + ); + } + if (textDecoration.indexOf('line-through') > -1) { + this._renderCharDecorationAtOffset( + ctx, + left, + top + (this.fontSize / this._fontSizeFraction), + charWidth, + charHeight / 2, + fontSize / 20 + ); + } + if (textDecoration.indexOf('overline') > -1) { + this._renderCharDecorationAtOffset( + ctx, + left, + top, + charWidth, + lineHeight - (this.fontSize / this._fontSizeFraction), + this.fontSize / 20 + ); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderCharDecorationAtOffset: function(ctx, left, top, charWidth, offset, thickness) { + ctx.fillRect(left, top - offset, charWidth, thickness); + }, + + /** + * @private + * @param {String} method + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} line + */ + _renderTextLine: function(method, ctx, line, left, top, lineIndex) { + // to "cancel" this.fontSize subtraction in fabric.Text#_renderTextLine + top += this.fontSize / 4; + this.callSuper('_renderTextLine', method, ctx, line, left, top, lineIndex); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines + */ + _renderTextDecoration: function(ctx, textLines) { + if (this.isEmptyStyles()) { + return this.callSuper('_renderTextDecoration', ctx, textLines); + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _renderTextLinesBackground: function(ctx, textLines) { + if (!this.textBackgroundColor && !this.styles) { + return; + } + + ctx.save(); + + if (this.textBackgroundColor) { + ctx.fillStyle = this.textBackgroundColor; + } + + var lineHeights = 0, + fractionOfFontSize = this.fontSize / this._fontSizeFraction; + + for (var i = 0, len = textLines.length; i < len; i++) { + + var heightOfLine = this._getHeightOfLine(ctx, i, textLines); + if (textLines[i] === '') { + lineHeights += heightOfLine; + continue; + } + + var lineWidth = this._getWidthOfLine(ctx, i, textLines), + lineLeftOffset = this._getLineLeftOffset(lineWidth); + + if (this.textBackgroundColor) { + ctx.fillStyle = this.textBackgroundColor; + + ctx.fillRect( + this._getLeftOffset() + lineLeftOffset, + this._getTopOffset() + lineHeights + fractionOfFontSize, + lineWidth, + heightOfLine + ); + } + if (this.styles[i]) { + for (var j = 0, jlen = textLines[i].length; j < jlen; j++) { + if (this.styles[i] && this.styles[i][j] && this.styles[i][j].textBackgroundColor) { + + var _char = textLines[i][j]; + + ctx.fillStyle = this.styles[i][j].textBackgroundColor; + + ctx.fillRect( + this._getLeftOffset() + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j, textLines), + this._getTopOffset() + lineHeights + fractionOfFontSize, + this._getWidthOfChar(ctx, _char, i, j, textLines) + 1, + heightOfLine + ); + } + } + } + lineHeights += heightOfLine; + } + ctx.restore(); + }, + + /** + * @private + */ + _getCacheProp: function(_char, styleDeclaration) { + return _char + + + styleDeclaration.fontFamily + + styleDeclaration.fontSize + + styleDeclaration.fontWeight + + styleDeclaration.fontStyle + + + styleDeclaration.shadow; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {String} _char + * @param {Number} lineIndex + * @param {Number} charIndex + * @param {Object} [decl] + */ + _applyCharStylesGetWidth: function(ctx, _char, lineIndex, charIndex, decl) { + var styleDeclaration = decl || + (this.styles[lineIndex] && + this.styles[lineIndex][charIndex]); + + if (styleDeclaration) { + // cloning so that original style object is not polluted with following font declarations + styleDeclaration = clone(styleDeclaration); + } + else { + styleDeclaration = { }; + } + + this._applyFontStyles(styleDeclaration); + + var cacheProp = this._getCacheProp(_char, styleDeclaration); + + // short-circuit if no styles + if (this.isEmptyStyles() && this._charWidthsCache[cacheProp] && this.caching) { + return this._charWidthsCache[cacheProp]; + } + + if (typeof styleDeclaration.shadow === 'string') { + styleDeclaration.shadow = new fabric.Shadow(styleDeclaration.shadow); + } + + var fill = styleDeclaration.fill || this.fill; + ctx.fillStyle = fill.toLive + ? fill.toLive(ctx) + : fill; + + if (styleDeclaration.stroke) { + ctx.strokeStyle = (styleDeclaration.stroke && styleDeclaration.stroke.toLive) + ? styleDeclaration.stroke.toLive(ctx) + : styleDeclaration.stroke; + } + + ctx.lineWidth = styleDeclaration.strokeWidth || this.strokeWidth; + ctx.font = this._getFontDeclaration.call(styleDeclaration); + this._setShadow.call(styleDeclaration, ctx); + + if (!this.caching) { + return ctx.measureText(_char).width; + } + + if (!this._charWidthsCache[cacheProp]) { + this._charWidthsCache[cacheProp] = ctx.measureText(_char).width; + } + + return this._charWidthsCache[cacheProp]; + }, + + /** + * @private + * @param {Object} styleDeclaration + */ + _applyFontStyles: function(styleDeclaration) { + if (!styleDeclaration.fontFamily) { + styleDeclaration.fontFamily = this.fontFamily; + } + if (!styleDeclaration.fontSize) { + styleDeclaration.fontSize = this.fontSize; + } + if (!styleDeclaration.fontWeight) { + styleDeclaration.fontWeight = this.fontWeight; + } + if (!styleDeclaration.fontStyle) { + styleDeclaration.fontStyle = this.fontStyle; + } + }, + + /** + * @private + * @param {Number} lineIndex + * @param {Number} charIndex + */ + _getStyleDeclaration: function(lineIndex, charIndex) { + return (this.styles[lineIndex] && this.styles[lineIndex][charIndex]) + ? clone(this.styles[lineIndex][charIndex]) + : { }; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfChar: function(ctx, _char, lineIndex, charIndex) { + var styleDeclaration = this._getStyleDeclaration(lineIndex, charIndex); + this._applyFontStyles(styleDeclaration); + var cacheProp = this._getCacheProp(_char, styleDeclaration); + + if (this._charWidthsCache[cacheProp] && this.caching) { + return this._charWidthsCache[cacheProp]; + } + else if (ctx) { + ctx.save(); + var width = this._applyCharStylesGetWidth(ctx, _char, lineIndex, charIndex); + ctx.restore(); + return width; + } + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getHeightOfChar: function(ctx, _char, lineIndex, charIndex) { + if (this.styles[lineIndex] && this.styles[lineIndex][charIndex]) { + return this.styles[lineIndex][charIndex].fontSize || this.fontSize; + } + return this.fontSize; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfCharAt: function(ctx, lineIndex, charIndex, lines) { + lines = lines || this.text.split(this._reNewline); + var _char = lines[lineIndex].split('')[charIndex]; + return this._getWidthOfChar(ctx, _char, lineIndex, charIndex); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getHeightOfCharAt: function(ctx, lineIndex, charIndex, lines) { + lines = lines || this.text.split(this._reNewline); + var _char = lines[lineIndex].split('')[charIndex]; + return this._getHeightOfChar(ctx, _char, lineIndex, charIndex); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfCharsAt: function(ctx, lineIndex, charIndex, lines) { + var width = 0; + for (var i = 0; i < charIndex; i++) { + width += this._getWidthOfCharAt(ctx, lineIndex, i, lines); + } + return width; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getWidthOfLine: function(ctx, lineIndex, textLines) { + // if (!this.styles[lineIndex]) { + // return this.callSuper('_getLineWidth', ctx, textLines[lineIndex]); + // } + return this._getWidthOfCharsAt(ctx, lineIndex, textLines[lineIndex].length, textLines); + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getTextWidth: function(ctx, textLines) { + + if (this.isEmptyStyles()) { + return this.callSuper('_getTextWidth', ctx, textLines); + } + + var maxWidth = this._getWidthOfLine(ctx, 0, textLines); + + for (var i = 1, len = textLines.length; i < len; i++) { + var currentLineWidth = this._getWidthOfLine(ctx, i, textLines); + if (currentLineWidth > maxWidth) { + maxWidth = currentLineWidth; + } + } + return maxWidth; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _getHeightOfLine: function(ctx, lineIndex, textLines) { + + textLines = textLines || this.text.split(this._reNewline); + + var maxHeight = this._getHeightOfChar(ctx, textLines[lineIndex][0], lineIndex, 0), + line = textLines[lineIndex], + chars = line.split(''); + + for (var i = 1, len = chars.length; i < len; i++) { + var currentCharHeight = this._getHeightOfChar(ctx, chars[i], lineIndex, i); + if (currentCharHeight > maxHeight) { + maxHeight = currentCharHeight; + } + } + + return maxHeight * this.lineHeight; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines + */ + _getTextHeight: function(ctx, textLines) { + var height = 0; + for (var i = 0, len = textLines.length; i < len; i++) { + height += this._getHeightOfLine(ctx, i, textLines); + } + return height; + }, + + /** + * @private + */ + _getTopOffset: function() { + var topOffset = fabric.Text.prototype._getTopOffset.call(this); + return topOffset - (this.fontSize / this._fontSizeFraction); + }, + + /** + * This method is overwritten to account for different top offset + * @private + */ + _renderTextBoxBackground: function(ctx) { + if (!this.backgroundColor) { + return; + } + + ctx.save(); + ctx.fillStyle = this.backgroundColor; + + ctx.fillRect( + this._getLeftOffset(), + this._getTopOffset() + (this.fontSize / this._fontSizeFraction), + this.width, + this.height + ); + + ctx.restore(); + }, + + /** + * Returns object representation of an instance + * @method toObject + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject: function(propertiesToInclude) { + return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), { + styles: clone(this.styles) + }); + } + }); + + /** + * Returns fabric.IText instance from an object representation + * @static + * @memberOf fabric.IText + * @param {Object} object Object to create an instance from + * @return {fabric.IText} instance of fabric.IText + */ + fabric.IText.fromObject = function(object) { + return new fabric.IText(object.text, clone(object)); + }; + + /** + * Contains all fabric.IText objects that have been created + * @static + * @memberof fabric.IText + * @type Array + */ + fabric.IText.instances = [ ]; + +})(); + + +(function() { + + var clone = fabric.util.object.clone; + + fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + + /** + * Initializes all the interactive behavior of IText + */ + initBehavior: function() { + this.initAddedHandler(); + this.initCursorSelectionHandlers(); + this.initDoubleClickSimulation(); + }, + + /** + * Initializes "selected" event handler + */ + initSelectedHandler: function() { + this.on('selected', function() { + + var _this = this; + setTimeout(function() { + _this.selected = true; + }, 100); + }); + }, + + /** + * Initializes "added" event handler + */ + initAddedHandler: function() { + this.on('added', function() { + if (this.canvas && !this.canvas._hasITextHandlers) { + this.canvas._hasITextHandlers = true; + this._initCanvasHandlers(); + } + }); + }, + + /** + * @private + */ + _initCanvasHandlers: function() { + this.canvas.on('selection:cleared', function() { + fabric.IText.prototype.exitEditingOnOthers.call(); + }); + + this.canvas.on('mouse:up', function() { + fabric.IText.instances.forEach(function(obj) { + obj.__isMousedown = false; + }); + }); + + this.canvas.on('object:selected', function(options) { + fabric.IText.prototype.exitEditingOnOthers.call(options.target); + }); + }, + + /** + * @private + */ + _tick: function() { + if (this._abortCursorAnimation) { + return; + } + + var _this = this; + + this.animate('_currentCursorOpacity', 1, { + + duration: this.cursorDuration, + + onComplete: function() { + _this._onTickComplete(); + }, + + onChange: function() { + _this.canvas && _this.canvas.renderAll(); + }, + + abort: function() { + return _this._abortCursorAnimation; + } + }); + }, + + /** + * @private + */ + _onTickComplete: function() { + if (this._abortCursorAnimation) { + return; + } + + var _this = this; + if (this._cursorTimeout1) { + clearTimeout(this._cursorTimeout1); + } + this._cursorTimeout1 = setTimeout(function() { + _this.animate('_currentCursorOpacity', 0, { + duration: this.cursorDuration / 2, + onComplete: function() { + _this._tick(); + }, + onChange: function() { + _this.canvas && _this.canvas.renderAll(); + }, + abort: function() { + return _this._abortCursorAnimation; + } + }); + }, 100); + }, + + /** + * Initializes delayed cursor + */ + initDelayedCursor: function(restart) { + var _this = this, + delay = restart ? 0 : this.cursorDelay; + + if (restart) { + this._abortCursorAnimation = true; + clearTimeout(this._cursorTimeout1); + this._currentCursorOpacity = 1; + this.canvas && this.canvas.renderAll(); + } + if (this._cursorTimeout2) { + clearTimeout(this._cursorTimeout2); + } + this._cursorTimeout2 = setTimeout(function() { + _this._abortCursorAnimation = false; + _this._tick(); + }, delay); + }, + + /** + * Aborts cursor animation and clears all timeouts + */ + abortCursorAnimation: function() { + this._abortCursorAnimation = true; + + clearTimeout(this._cursorTimeout1); + clearTimeout(this._cursorTimeout2); + + this._currentCursorOpacity = 0; + this.canvas && this.canvas.renderAll(); + + var _this = this; + setTimeout(function() { + _this._abortCursorAnimation = false; + }, 10); + }, + + /** + * Selects entire text + */ + selectAll: function() { + this.selectionStart = 0; + this.selectionEnd = this.text.length; + this.fire('selection:changed'); + this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + }, + + /** + * Returns selected text + * @return {String} + */ + getSelectedText: function() { + return this.text.slice(this.selectionStart, this.selectionEnd); + }, + + /** + * Find new selection index representing start of current word according to current selection index + * @param {Number} startFrom Surrent selection index + * @return {Number} New selection index + */ + findWordBoundaryLeft: function(startFrom) { + var offset = 0, index = startFrom - 1; + + // remove space before cursor first + if (this._reSpace.test(this.text.charAt(index))) { + while (this._reSpace.test(this.text.charAt(index))) { + offset++; + index--; + } + } + while (/\S/.test(this.text.charAt(index)) && index > -1) { + offset++; + index--; + } + + return startFrom - offset; + }, + + /** + * Find new selection index representing end of current word according to current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index + */ + findWordBoundaryRight: function(startFrom) { + var offset = 0, index = startFrom; + + // remove space after cursor first + if (this._reSpace.test(this.text.charAt(index))) { + while (this._reSpace.test(this.text.charAt(index))) { + offset++; + index++; + } + } + while (/\S/.test(this.text.charAt(index)) && index < this.text.length) { + offset++; + index++; + } + + return startFrom + offset; + }, + + /** + * Find new selection index representing start of current line according to current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index + */ + findLineBoundaryLeft: function(startFrom) { + var offset = 0, index = startFrom - 1; + + while (!/\n/.test(this.text.charAt(index)) && index > -1) { + offset++; + index--; + } + + return startFrom - offset; + }, + + /** + * Find new selection index representing end of current line according to current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index + */ + findLineBoundaryRight: function(startFrom) { + var offset = 0, index = startFrom; + + while (!/\n/.test(this.text.charAt(index)) && index < this.text.length) { + offset++; + index++; + } + + return startFrom + offset; + }, + + /** + * Returns number of newlines in selected text + * @return {Number} Number of newlines in selected text + */ + getNumNewLinesInSelectedText: function() { + var selectedText = this.getSelectedText(), + numNewLines = 0; + + for (var i = 0, chars = selectedText.split(''), len = chars.length; i < len; i++) { + if (chars[i] === '\n') { + numNewLines++; + } + } + return numNewLines; + }, + + /** + * Finds index corresponding to beginning or end of a word + * @param {Number} selectionStart Index of a character + * @param {Number} direction: 1 or -1 + * @return {Number} Index of the beginning or end of a word + */ + searchWordBoundary: function(selectionStart, direction) { + var index = this._reSpace.test(this.text.charAt(selectionStart)) ? selectionStart - 1 : selectionStart, + _char = this.text.charAt(index), + reNonWord = /[ \n\.,;!\?\-]/; + + while (!reNonWord.test(_char) && index > 0 && index < this.text.length) { + index += direction; + _char = this.text.charAt(index); + } + if (reNonWord.test(_char) && _char !== '\n') { + index += direction === 1 ? 0 : 1; + } + return index; + }, + + /** + * Selects a word based on the index + * @param {Number} selectionStart Index of a character + */ + selectWord: function(selectionStart) { + var newSelectionStart = this.searchWordBoundary(selectionStart, -1), /* search backwards */ + newSelectionEnd = this.searchWordBoundary(selectionStart, 1); /* search forward */ + + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionEnd); + this.initDelayedCursor(true); + }, + + /** + * Selects a line based on the index + * @param {Number} selectionStart Index of a character + */ + selectLine: function(selectionStart) { + var newSelectionStart = this.findLineBoundaryLeft(selectionStart), + newSelectionEnd = this.findLineBoundaryRight(selectionStart); + + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionEnd); + this.initDelayedCursor(true); + }, + + /** + * Enters editing state + * @return {fabric.IText} thisArg + * @chainable + */ + enterEditing: function() { + if (this.isEditing || !this.editable) { + return; + } + + this.exitEditingOnOthers(); + + this.isEditing = true; + + this.initHiddenTextarea(); + this._updateTextarea(); + this._saveEditingProps(); + this._setEditingProps(); + + this._tick(); + this.canvas && this.canvas.renderAll(); + + this.fire('editing:entered'); + this.canvas && this.canvas.fire('text:editing:entered', { target: this }); + + return this; + }, + + exitEditingOnOthers: function() { + fabric.IText.instances.forEach(function(obj) { + obj.selected = false; + if (obj.isEditing) { + obj.exitEditing(); + } + }, this); + }, + + /** + * @private + */ + _setEditingProps: function() { + this.hoverCursor = 'text'; + + if (this.canvas) { + this.canvas.defaultCursor = this.canvas.moveCursor = 'text'; + } + + this.borderColor = this.editingBorderColor; + + this.hasControls = this.selectable = false; + this.lockMovementX = this.lockMovementY = true; + }, + + /** + * @private + */ + _updateTextarea: function() { + if (!this.hiddenTextarea) { + return; + } + + this.hiddenTextarea.value = this.text; + this.hiddenTextarea.selectionStart = this.selectionStart; + }, + + /** + * @private + */ + _saveEditingProps: function() { + this._savedProps = { + hasControls: this.hasControls, + borderColor: this.borderColor, + lockMovementX: this.lockMovementX, + lockMovementY: this.lockMovementY, + hoverCursor: this.hoverCursor, + defaultCursor: this.canvas && this.canvas.defaultCursor, + moveCursor: this.canvas && this.canvas.moveCursor + }; + }, + + /** + * @private + */ + _restoreEditingProps: function() { + if (!this._savedProps) { + return; + } + + this.hoverCursor = this._savedProps.overCursor; + this.hasControls = this._savedProps.hasControls; + this.borderColor = this._savedProps.borderColor; + this.lockMovementX = this._savedProps.lockMovementX; + this.lockMovementY = this._savedProps.lockMovementY; + + if (this.canvas) { + this.canvas.defaultCursor = this._savedProps.defaultCursor; + this.canvas.moveCursor = this._savedProps.moveCursor; + } + }, + + /** + * Exits from editing state + * @return {fabric.IText} thisArg + * @chainable + */ + exitEditing: function() { + + this.selected = false; + this.isEditing = false; + this.selectable = true; + + this.selectionEnd = this.selectionStart; + this.hiddenTextarea && this.canvas && this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea); + this.hiddenTextarea = null; + + this.abortCursorAnimation(); + this._restoreEditingProps(); + this._currentCursorOpacity = 0; + + this.fire('editing:exited'); + this.canvas && this.canvas.fire('text:editing:exited', { target: this }); + + return this; + }, + + /** + * @private + */ + _removeExtraneousStyles: function() { + var textLines = this.text.split(this._reNewline); + for (var prop in this.styles) { + if (!textLines[prop]) { + delete this.styles[prop]; + } + } + }, + + /** + * @private + */ + _removeCharsFromTo: function(start, end) { + + var i = end; + while (i !== start) { + + var prevIndex = this.get2DCursorLocation(i).charIndex; + i--; + + var index = this.get2DCursorLocation(i).charIndex, + isNewline = index > prevIndex; + + if (isNewline) { + this.removeStyleObject(isNewline, i + 1); + } + else { + this.removeStyleObject(this.get2DCursorLocation(i).charIndex === 0, i); + } + + } + + this.text = this.text.slice(0, start) + + this.text.slice(end); + }, + + /** + * Inserts a character where cursor is (replacing selection if one exists) + * @param {String} _chars Characters to insert + */ + insertChars: function(_chars) { + var isEndOfLine = this.text.slice(this.selectionStart, this.selectionStart + 1) === '\n'; + + this.text = this.text.slice(0, this.selectionStart) + + _chars + + this.text.slice(this.selectionEnd); + + if (this.selectionStart === this.selectionEnd) { + this.insertStyleObjects(_chars, isEndOfLine, this.copiedStyles); + } + // else if (this.selectionEnd - this.selectionStart > 1) { + // TODO: replace styles properly + // console.log('replacing MORE than 1 char'); + // } + + this.selectionStart += _chars.length; + this.selectionEnd = this.selectionStart; + + if (this.canvas) { + // TODO: double renderAll gets rid of text box shift happenning sometimes + // need to find out what exactly causes it and fix it + this.canvas.renderAll().renderAll(); + } + + this.setCoords(); + this.fire('changed'); + this.canvas && this.canvas.fire('text:changed', { target: this }); + }, + + /** + * Inserts new style object + * @param {Number} lineIndex Index of a line + * @param {Number} charIndex Index of a char + * @param {Boolean} isEndOfLine True if it's end of line + */ + insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) { + + this.shiftLineStyles(lineIndex, +1); + + if (!this.styles[lineIndex + 1]) { + this.styles[lineIndex + 1] = { }; + } + + var currentCharStyle = this.styles[lineIndex][charIndex - 1], + newLineStyles = { }; + + // if there's nothing after cursor, + // we clone current char style onto the next (otherwise empty) line + if (isEndOfLine) { + newLineStyles[0] = clone(currentCharStyle); + this.styles[lineIndex + 1] = newLineStyles; + } + // otherwise we clone styles of all chars + // after cursor onto the next line, from the beginning + else { + for (var index in this.styles[lineIndex]) { + if (parseInt(index, 10) >= charIndex) { + newLineStyles[parseInt(index, 10) - charIndex] = this.styles[lineIndex][index]; + // remove lines from the previous line since they're on a new line now + delete this.styles[lineIndex][index]; + } + } + this.styles[lineIndex + 1] = newLineStyles; + } + }, + + /** + * Inserts style object for a given line/char index + * @param {Number} lineIndex Index of a line + * @param {Number} charIndex Index of a char + * @param {Object} [style] Style object to insert, if given + */ + insertCharStyleObject: function(lineIndex, charIndex, style) { + + var currentLineStyles = this.styles[lineIndex], + currentLineStylesCloned = clone(currentLineStyles); + + if (charIndex === 0 && !style) { + charIndex = 1; + } + + // shift all char styles by 1 forward + // 0,1,2,3 -> (charIndex=2) -> 0,1,3,4 -> (insert 2) -> 0,1,2,3,4 + for (var index in currentLineStylesCloned) { + var numericIndex = parseInt(index, 10); + if (numericIndex >= charIndex) { + currentLineStyles[numericIndex + 1] = currentLineStylesCloned[numericIndex]; + //delete currentLineStyles[index]; + } + } + + this.styles[lineIndex][charIndex] = + style || clone(currentLineStyles[charIndex - 1]); + }, + + /** + * Inserts style object(s) + * @param {String} _chars Characters at the location where style is inserted + * @param {Boolean} isEndOfLine True if it's end of line + * @param {Array} [styles] Styles to insert + */ + insertStyleObjects: function(_chars, isEndOfLine, styles) { + + // short-circuit + if (this.isEmptyStyles()) { + return; + } + + var cursorLocation = this.get2DCursorLocation(), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex; + + if (!this.styles[lineIndex]) { + this.styles[lineIndex] = { }; + } + + if (_chars === '\n') { + this.insertNewlineStyleObject(lineIndex, charIndex, isEndOfLine); + } + else { + if (styles) { + this._insertStyles(styles); + } + else { + // TODO: support multiple style insertion if _chars.length > 1 + this.insertCharStyleObject(lineIndex, charIndex); + } + } + }, + + /** + * @private + */ + _insertStyles: function(styles) { + for (var i = 0, len = styles.length; i < len; i++) { + + var cursorLocation = this.get2DCursorLocation(this.selectionStart + i), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex; + + this.insertCharStyleObject(lineIndex, charIndex, styles[i]); + } + }, + + /** + * Shifts line styles up or down + * @param {Number} lineIndex Index of a line + * @param {Number} offset Can be -1 or +1 + */ + shiftLineStyles: function(lineIndex, offset) { + // shift all line styles by 1 upward + var clonedStyles = clone(this.styles); + for (var line in this.styles) { + var numericLine = parseInt(line, 10); + if (numericLine > lineIndex) { + this.styles[numericLine + offset] = clonedStyles[numericLine]; + } + } + }, + + /** + * Removes style object + * @param {Boolean} isBeginningOfLine True if cursor is at the beginning of line + * @param {Number} [index] Optional index. When not given, current selectionStart is used. + */ + removeStyleObject: function(isBeginningOfLine, index) { + + var cursorLocation = this.get2DCursorLocation(index), + lineIndex = cursorLocation.lineIndex, + charIndex = cursorLocation.charIndex; + + if (isBeginningOfLine) { + + var textLines = this.text.split(this._reNewline), + textOnPreviousLine = textLines[lineIndex - 1], + newCharIndexOnPrevLine = textOnPreviousLine + ? textOnPreviousLine.length + : 0; + + if (!this.styles[lineIndex - 1]) { + this.styles[lineIndex - 1] = { }; + } + + for (charIndex in this.styles[lineIndex]) { + this.styles[lineIndex - 1][parseInt(charIndex, 10) + newCharIndexOnPrevLine] + = this.styles[lineIndex][charIndex]; + } + + this.shiftLineStyles(lineIndex, -1); + } + else { + var currentLineStyles = this.styles[lineIndex]; + + if (currentLineStyles) { + var offset = this.selectionStart === this.selectionEnd ? -1 : 0; + delete currentLineStyles[charIndex + offset]; + // console.log('deleting', lineIndex, charIndex + offset); + } + + var currentLineStylesCloned = clone(currentLineStyles); + + // shift all styles by 1 backwards + for (var i in currentLineStylesCloned) { + var numericIndex = parseInt(i, 10); + if (numericIndex >= charIndex && numericIndex !== 0) { + currentLineStyles[numericIndex - 1] = currentLineStylesCloned[numericIndex]; + delete currentLineStyles[numericIndex]; + } + } + } + }, + + /** + * Inserts new line + */ + insertNewline: function() { + this.insertChars('\n'); + } + }); +})(); + + +fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + /** + * Initializes "dbclick" event handler + */ + initDoubleClickSimulation: function() { + + // for double click + this.__lastClickTime = +new Date(); + + // for triple click + this.__lastLastClickTime = +new Date(); + + this.__lastPointer = { }; + + this.on('mousedown', this.onMouseDown.bind(this)); + }, + + onMouseDown: function(options) { + + this.__newClickTime = +new Date(); + var newPointer = this.canvas.getPointer(options.e); + + if (this.isTripleClick(newPointer)) { + this.fire('tripleclick', options); + this._stopEvent(options.e); + } + else if (this.isDoubleClick(newPointer)) { + this.fire('dblclick', options); + this._stopEvent(options.e); + } + + this.__lastLastClickTime = this.__lastClickTime; + this.__lastClickTime = this.__newClickTime; + this.__lastPointer = newPointer; + this.__lastIsEditing = this.isEditing; + this.__lastSelected = this.selected; + }, + + isDoubleClick: function(newPointer) { + return this.__newClickTime - this.__lastClickTime < 500 && + this.__lastPointer.x === newPointer.x && + this.__lastPointer.y === newPointer.y && this.__lastIsEditing; + }, + + isTripleClick: function(newPointer) { + return this.__newClickTime - this.__lastClickTime < 500 && + this.__lastClickTime - this.__lastLastClickTime < 500 && + this.__lastPointer.x === newPointer.x && + this.__lastPointer.y === newPointer.y; + }, + + /** + * @private + */ + _stopEvent: function(e) { + e.preventDefault && e.preventDefault(); + e.stopPropagation && e.stopPropagation(); + }, + + /** + * Initializes event handlers related to cursor or selection + */ + initCursorSelectionHandlers: function() { + this.initSelectedHandler(); + this.initMousedownHandler(); + this.initMousemoveHandler(); + this.initMouseupHandler(); + this.initClicks(); + }, + + /** + * Initializes double and triple click event handlers + */ + initClicks: function() { + this.on('dblclick', function(options) { + this.selectWord(this.getSelectionStartFromPointer(options.e)); + }); + this.on('tripleclick', function(options) { + this.selectLine(this.getSelectionStartFromPointer(options.e)); + }); + }, + + /** + * Initializes "mousedown" event handler + */ + initMousedownHandler: function() { + this.on('mousedown', function(options) { + + var pointer = this.canvas.getPointer(options.e); + + this.__mousedownX = pointer.x; + this.__mousedownY = pointer.y; + this.__isMousedown = true; + + if (this.hiddenTextarea && this.canvas) { + this.canvas.wrapperEl.appendChild(this.hiddenTextarea); + } + + if (this.selected) { + this.setCursorByClick(options.e); + } + + if (this.isEditing) { + this.__selectionStartOnMouseDown = this.selectionStart; + this.initDelayedCursor(true); + } + }); + }, + + /** + * Initializes "mousemove" event handler + */ + initMousemoveHandler: function() { + this.on('mousemove', function(options) { + if (!this.__isMousedown || !this.isEditing) { + return; + } + + var newSelectionStart = this.getSelectionStartFromPointer(options.e); + + if (newSelectionStart >= this.__selectionStartOnMouseDown) { + this.setSelectionStart(this.__selectionStartOnMouseDown); + this.setSelectionEnd(newSelectionStart); + } + else { + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(this.__selectionStartOnMouseDown); + } + }); + }, + + /** + * @private + */ + _isObjectMoved: function(e) { + var pointer = this.canvas.getPointer(e); + + return this.__mousedownX !== pointer.x || + this.__mousedownY !== pointer.y; + }, + + /** + * Initializes "mouseup" event handler + */ + initMouseupHandler: function() { + this.on('mouseup', function(options) { + this.__isMousedown = false; + if (this._isObjectMoved(options.e)) { + return; + } + + if (this.__lastSelected) { + this.enterEditing(); + this.initDelayedCursor(true); + } + this.selected = true; + }); + }, + + /** + * Changes cursor location in a text depending on passed pointer (x/y) object + * @param {Event} e Event object + */ + setCursorByClick: function(e) { + var newSelectionStart = this.getSelectionStartFromPointer(e); + + if (e.shiftKey) { + if (newSelectionStart < this.selectionStart) { + this.setSelectionEnd(this.selectionStart); + this.setSelectionStart(newSelectionStart); + } + else { + this.setSelectionEnd(newSelectionStart); + } + } + else { + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionStart); + } + }, + + /** + * @private + * @param {Event} e Event object + * @return {Object} Coordinates of a pointer (x, y) + */ + _getLocalRotatedPointer: function(e) { + var pointer = this.canvas.getPointer(e), + + pClicked = new fabric.Point(pointer.x, pointer.y), + pLeftTop = new fabric.Point(this.left, this.top), + + rotated = fabric.util.rotatePoint( + pClicked, pLeftTop, fabric.util.degreesToRadians(-this.angle)); + + return this.getLocalPointer(e, rotated); + }, + + /** + * Returns index of a character corresponding to where an object was clicked + * @param {Event} e Event object + * @return {Number} Index of a character + */ + getSelectionStartFromPointer: function(e) { + var mouseOffset = this._getLocalRotatedPointer(e), + textLines = this.text.split(this._reNewline), + prevWidth = 0, + width = 0, + height = 0, + charIndex = 0, + newSelectionStart; + + for (var i = 0, len = textLines.length; i < len; i++) { + + height += this._getHeightOfLine(this.ctx, i) * this.scaleY; + + var widthOfLine = this._getWidthOfLine(this.ctx, i, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfLine); + + width = lineLeftOffset * this.scaleX; + + if (this.flipX) { + // when oject is horizontally flipped we reverse chars + textLines[i] = textLines[i].split('').reverse().join(''); + } + + for (var j = 0, jlen = textLines[i].length; j < jlen; j++) { + + var _char = textLines[i][j]; + prevWidth = width; + + width += this._getWidthOfChar(this.ctx, _char, i, this.flipX ? jlen - j : j) * + this.scaleX; + + if (height <= mouseOffset.y || width <= mouseOffset.x) { + charIndex++; + continue; + } + + return this._getNewSelectionStartFromOffset( + mouseOffset, prevWidth, width, charIndex + i, jlen); + } + + if (mouseOffset.y < height) { + return this._getNewSelectionStartFromOffset( + mouseOffset, prevWidth, width, charIndex + i, jlen); + } + } + + // clicked somewhere after all chars, so set at the end + if (typeof newSelectionStart === 'undefined') { + return this.text.length; + } + }, + + /** + * @private + */ + _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen) { + + var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth, + distanceBtwNextCharAndCursor = width - mouseOffset.x, + offset = distanceBtwNextCharAndCursor > distanceBtwLastCharAndCursor ? 0 : 1, + newSelectionStart = index + offset; + + // if object is horizontally flipped, mirror cursor location from the end + if (this.flipX) { + newSelectionStart = jlen - newSelectionStart; + } + + if (newSelectionStart > this.text.length) { + newSelectionStart = this.text.length; + } + + return newSelectionStart; + } +}); + + +fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + + /** + * Initializes hidden textarea (needed to bring up keyboard in iOS) + */ + initHiddenTextarea: function() { + this.hiddenTextarea = fabric.document.createElement('textarea'); + + this.hiddenTextarea.setAttribute('autocapitalize', 'off'); + this.hiddenTextarea.style.cssText = 'position: absolute; top: 0; left: -9999px'; + + fabric.document.body.appendChild(this.hiddenTextarea); + + fabric.util.addListener(this.hiddenTextarea, 'keydown', this.onKeyDown.bind(this)); + fabric.util.addListener(this.hiddenTextarea, 'keypress', this.onKeyPress.bind(this)); + fabric.util.addListener(this.hiddenTextarea, 'copy', this.copy.bind(this)); + fabric.util.addListener(this.hiddenTextarea, 'paste', this.paste.bind(this)); + + if (!this._clickHandlerInitialized && this.canvas) { + fabric.util.addListener(this.canvas.upperCanvasEl, 'click', this.onClick.bind(this)); + this._clickHandlerInitialized = true; + } + }, + + /** + * @private + */ + _keysMap: { + 8: 'removeChars', + 13: 'insertNewline', + 37: 'moveCursorLeft', + 38: 'moveCursorUp', + 39: 'moveCursorRight', + 40: 'moveCursorDown', + 46: 'forwardDelete' + }, + + /** + * @private + */ + _ctrlKeysMap: { + 65: 'selectAll', + 88: 'cut' + }, + + onClick: function() { + // No need to trigger click event here, focus is enough to have the keyboard appear on Android + this.hiddenTextarea && this.hiddenTextarea.focus(); + }, + + /** + * Handles keyup event + * @param {Event} e Event object + */ + onKeyDown: function(e) { + if (!this.isEditing) { + return; + } + + if (e.keyCode in this._keysMap && e.charCode === 0) { + this[this._keysMap[e.keyCode]](e); + } + else if ((e.keyCode in this._ctrlKeysMap) && (e.ctrlKey || e.metaKey)) { + this[this._ctrlKeysMap[e.keyCode]](e); + } + else { + return; + } + + e.stopPropagation(); + + this.canvas && this.canvas.renderAll(); + }, + + /** + * Forward delete + */ + forwardDelete: function(e) { + if (this.selectionStart === this.selectionEnd) { + this.moveCursorRight(e); + } + this.removeChars(e); + }, + + /** + * Copies selected text + * @param {Event} e Event object + */ + copy: function(e) { + var selectedText = this.getSelectedText(), + clipboardData = this._getClipboardData(e); + + // Check for backward compatibility with old browsers + if (clipboardData) { + clipboardData.setData('text', selectedText); + } + + this.copiedText = selectedText; + this.copiedStyles = this.getSelectionStyles( + this.selectionStart, + this.selectionEnd); + }, + + /** + * Pastes text + * @param {Event} e Event object + */ + paste: function(e) { + var copiedText = null, + clipboardData = this._getClipboardData(e); + + // Check for backward compatibility with old browsers + if (clipboardData) { + copiedText = clipboardData.getData('text'); + } + else { + copiedText = this.copiedText; + } + + if (copiedText) { + this.insertChars(copiedText); + } + }, + + /** + * Cuts text + * @param {Event} e Event object + */ + cut: function(e) { + if (this.selectionStart === this.selectionEnd) { + return; + } + + this.copy(); + this.removeChars(e); + }, + + /** + * @private + * @param {Event} e Event object + * @return {Object} Clipboard data object + */ + _getClipboardData: function(e) { + return e && (e.clipboardData || fabric.window.clipboardData); + }, + + /** + * Handles keypress event + * @param {Event} e Event object + */ + onKeyPress: function(e) { + if (!this.isEditing || e.metaKey || e.ctrlKey || ( e.keyCode in this._keysMap && e.charCode === 0 )) { + return; + } + + this.insertChars(String.fromCharCode(e.which)); + + e.stopPropagation(); + }, + + /** + * Gets start offset of a selection + * @param {Event} e Event object + * @param {Boolean} isRight + * @return {Number} + */ + getDownCursorOffset: function(e, isRight) { + var selectionProp = isRight ? this.selectionEnd : this.selectionStart, + textLines = this.text.split(this._reNewline), + _char, + lineLeftOffset, + + textBeforeCursor = this.text.slice(0, selectionProp), + textAfterCursor = this.text.slice(selectionProp), + + textOnSameLineBeforeCursor = textBeforeCursor.slice(textBeforeCursor.lastIndexOf('\n') + 1), + textOnSameLineAfterCursor = textAfterCursor.match(/(.*)\n?/)[1], + textOnNextLine = (textAfterCursor.match(/.*\n(.*)\n?/) || { })[1] || '', + + cursorLocation = this.get2DCursorLocation(selectionProp); + + // if on last line, down cursor goes to end of line + if (cursorLocation.lineIndex === textLines.length - 1 || e.metaKey) { + + // move to the end of a text + return this.text.length - selectionProp; + } + + var widthOfSameLineBeforeCursor = this._getWidthOfLine(this.ctx, cursorLocation.lineIndex, textLines); + lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor); + + var widthOfCharsOnSameLineBeforeCursor = lineLeftOffset, + lineIndex = cursorLocation.lineIndex; + + for (var i = 0, len = textOnSameLineBeforeCursor.length; i < len; i++) { + _char = textOnSameLineBeforeCursor[i]; + widthOfCharsOnSameLineBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i); + } + + var indexOnNextLine = this._getIndexOnNextLine( + cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines); + + return textOnSameLineAfterCursor.length + 1 + indexOnNextLine; + }, + + /** + * @private + */ + _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines) { + var lineIndex = cursorLocation.lineIndex + 1, + widthOfNextLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfNextLine), + widthOfCharsOnNextLine = lineLeftOffset, + indexOnNextLine = 0, + foundMatch; + + for (var j = 0, jlen = textOnNextLine.length; j < jlen; j++) { + + var _char = textOnNextLine[j], + widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j); + + widthOfCharsOnNextLine += widthOfChar; + + if (widthOfCharsOnNextLine > widthOfCharsOnSameLineBeforeCursor) { + + foundMatch = true; + + var leftEdge = widthOfCharsOnNextLine - widthOfChar, + rightEdge = widthOfCharsOnNextLine, + offsetFromLeftEdge = Math.abs(leftEdge - widthOfCharsOnSameLineBeforeCursor), + offsetFromRightEdge = Math.abs(rightEdge - widthOfCharsOnSameLineBeforeCursor); + + indexOnNextLine = offsetFromRightEdge < offsetFromLeftEdge ? j + 1 : j; + + break; + } + } + + // reached end + if (!foundMatch) { + indexOnNextLine = textOnNextLine.length; + } + + return indexOnNextLine; + }, + + /** + * Moves cursor down + * @param {Event} e Event object + */ + moveCursorDown: function(e) { + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + var offset = this.getDownCursorOffset(e, this._selectionDirection === 'right'); + + if (e.shiftKey) { + this.moveCursorDownWithShift(offset); + } + else { + this.moveCursorDownWithoutShift(offset); + } + + this.initDelayedCursor(); + }, + + /** + * Moves cursor down without keeping selection + * @param {Number} offset + */ + moveCursorDownWithoutShift: function(offset) { + this._selectionDirection = 'right'; + this.selectionStart += offset; + + if (this.selectionStart > this.text.length) { + this.selectionStart = this.text.length; + } + this.selectionEnd = this.selectionStart; + }, + + /** + * Moves cursor down while keeping selection + * @param {Number} offset + */ + moveCursorDownWithShift: function(offset) { + if (this._selectionDirection === 'left' && (this.selectionStart !== this.selectionEnd)) { + this.selectionStart += offset; + this._selectionDirection = 'left'; + return; + } + else { + this._selectionDirection = 'right'; + this.selectionEnd += offset; + + if (this.selectionEnd > this.text.length) { + this.selectionEnd = this.text.length; + } + } + }, + + /** + * @param {Event} e Event object + * @param {Boolean} isRight + * @return {Number} + */ + getUpCursorOffset: function(e, isRight) { + var selectionProp = isRight ? this.selectionEnd : this.selectionStart, + cursorLocation = this.get2DCursorLocation(selectionProp); + + // if on first line, up cursor goes to start of line + if (cursorLocation.lineIndex === 0 || e.metaKey) { + return selectionProp; + } + + var textBeforeCursor = this.text.slice(0, selectionProp), + textOnSameLineBeforeCursor = textBeforeCursor.slice(textBeforeCursor.lastIndexOf('\n') + 1), + textOnPreviousLine = (textBeforeCursor.match(/\n?(.*)\n.*$/) || {})[1] || '', + textLines = this.text.split(this._reNewline), + _char, + widthOfSameLineBeforeCursor = this._getWidthOfLine(this.ctx, cursorLocation.lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor), + widthOfCharsOnSameLineBeforeCursor = lineLeftOffset, + lineIndex = cursorLocation.lineIndex; + + for (var i = 0, len = textOnSameLineBeforeCursor.length; i < len; i++) { + _char = textOnSameLineBeforeCursor[i]; + widthOfCharsOnSameLineBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i); + } + + var indexOnPrevLine = this._getIndexOnPrevLine( + cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor, textLines); + + return textOnPreviousLine.length - indexOnPrevLine + textOnSameLineBeforeCursor.length; + }, + + /** + * @private + */ + _getIndexOnPrevLine: function(cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor, textLines) { + + var lineIndex = cursorLocation.lineIndex - 1, + widthOfPreviousLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), + lineLeftOffset = this._getLineLeftOffset(widthOfPreviousLine), + widthOfCharsOnPreviousLine = lineLeftOffset, + indexOnPrevLine = 0, + foundMatch; + + for (var j = 0, jlen = textOnPreviousLine.length; j < jlen; j++) { + + var _char = textOnPreviousLine[j], + widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j); + + widthOfCharsOnPreviousLine += widthOfChar; + + if (widthOfCharsOnPreviousLine > widthOfCharsOnSameLineBeforeCursor) { + + foundMatch = true; + + var leftEdge = widthOfCharsOnPreviousLine - widthOfChar, + rightEdge = widthOfCharsOnPreviousLine, + offsetFromLeftEdge = Math.abs(leftEdge - widthOfCharsOnSameLineBeforeCursor), + offsetFromRightEdge = Math.abs(rightEdge - widthOfCharsOnSameLineBeforeCursor); + + indexOnPrevLine = offsetFromRightEdge < offsetFromLeftEdge ? j : (j - 1); + + break; + } + } + + // reached end + if (!foundMatch) { + indexOnPrevLine = textOnPreviousLine.length - 1; + } + + return indexOnPrevLine; + }, + + /** + * Moves cursor up + * @param {Event} e Event object + */ + moveCursorUp: function(e) { + + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + var offset = this.getUpCursorOffset(e, this._selectionDirection === 'right'); + + if (e.shiftKey) { + this.moveCursorUpWithShift(offset); + } + else { + this.moveCursorUpWithoutShift(offset); + } + + this.initDelayedCursor(); + }, + + /** + * Moves cursor up with shift + * @param {Number} offset + */ + moveCursorUpWithShift: function(offset) { + + if (this.selectionStart === this.selectionEnd) { + this.selectionStart -= offset; + } + else { + if (this._selectionDirection === 'right') { + this.selectionEnd -= offset; + this._selectionDirection = 'right'; + return; + } + else { + this.selectionStart -= offset; + } + } + + if (this.selectionStart < 0) { + this.selectionStart = 0; + } + + this._selectionDirection = 'left'; + }, + + /** + * Moves cursor up without shift + * @param {Number} offset + */ + moveCursorUpWithoutShift: function(offset) { + if (this.selectionStart === this.selectionEnd) { + this.selectionStart -= offset; + } + if (this.selectionStart < 0) { + this.selectionStart = 0; + } + this.selectionEnd = this.selectionStart; + + this._selectionDirection = 'left'; + }, + + /** + * Moves cursor left + * @param {Event} e Event object + */ + moveCursorLeft: function(e) { + if (this.selectionStart === 0 && this.selectionEnd === 0) { + return; + } + + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + if (e.shiftKey) { + this.moveCursorLeftWithShift(e); + } + else { + this.moveCursorLeftWithoutShift(e); + } + + this.initDelayedCursor(); + }, + + /** + * @private + */ + _move: function(e, prop, direction) { + if (e.altKey) { + this[prop] = this['findWordBoundary' + direction](this[prop]); + } + else if (e.metaKey) { + this[prop] = this['findLineBoundary' + direction](this[prop]); + } + else { + this[prop] += (direction === 'Left' ? -1 : 1); + } + }, + + /** + * @private + */ + _moveLeft: function(e, prop) { + this._move(e, prop, 'Left'); + }, + + /** + * @private + */ + _moveRight: function(e, prop) { + this._move(e, prop, 'Right'); + }, + + /** + * Moves cursor left without keeping selection + * @param {Event} e + */ + moveCursorLeftWithoutShift: function(e) { + this._selectionDirection = 'left'; + + // only move cursor when there is no selection, + // otherwise we discard it, and leave cursor on same place + if (this.selectionEnd === this.selectionStart) { + this._moveLeft(e, 'selectionStart'); + } + this.selectionEnd = this.selectionStart; + }, + + /** + * Moves cursor left while keeping selection + * @param {Event} e + */ + moveCursorLeftWithShift: function(e) { + if (this._selectionDirection === 'right' && this.selectionStart !== this.selectionEnd) { + this._moveLeft(e, 'selectionEnd'); + } + else { + this._selectionDirection = 'left'; + this._moveLeft(e, 'selectionStart'); + + // increase selection by one if it's a newline + if (this.text.charAt(this.selectionStart) === '\n') { + this.selectionStart--; + } + if (this.selectionStart < 0) { + this.selectionStart = 0; + } + } + }, + + /** + * Moves cursor right + * @param {Event} e Event object + */ + moveCursorRight: function(e) { + if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) { + return; + } + + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + + if (e.shiftKey) { + this.moveCursorRightWithShift(e); + } + else { + this.moveCursorRightWithoutShift(e); + } + + this.initDelayedCursor(); + }, + + /** + * Moves cursor right while keeping selection + * @param {Event} e + */ + moveCursorRightWithShift: function(e) { + if (this._selectionDirection === 'left' && this.selectionStart !== this.selectionEnd) { + this._moveRight(e, 'selectionStart'); + } + else { + this._selectionDirection = 'right'; + this._moveRight(e, 'selectionEnd'); + + // increase selection by one if it's a newline + if (this.text.charAt(this.selectionEnd - 1) === '\n') { + this.selectionEnd++; + } + if (this.selectionEnd > this.text.length) { + this.selectionEnd = this.text.length; + } + } + }, + + /** + * Moves cursor right without keeping selection + * @param {Event} e Event object + */ + moveCursorRightWithoutShift: function(e) { + this._selectionDirection = 'right'; + + if (this.selectionStart === this.selectionEnd) { + this._moveRight(e, 'selectionStart'); + this.selectionEnd = this.selectionStart; + } + else { + this.selectionEnd += this.getNumNewLinesInSelectedText(); + if (this.selectionEnd > this.text.length) { + this.selectionEnd = this.text.length; + } + this.selectionStart = this.selectionEnd; + } + }, + + /** + * Inserts a character where cursor is (replacing selection if one exists) + * @param {Event} e Event object + */ + removeChars: function(e) { + if (this.selectionStart === this.selectionEnd) { + this._removeCharsNearCursor(e); + } + else { + this._removeCharsFromTo(this.selectionStart, this.selectionEnd); + } + + this.selectionEnd = this.selectionStart; + + this._removeExtraneousStyles(); + + if (this.canvas) { + // TODO: double renderAll gets rid of text box shift happenning sometimes + // need to find out what exactly causes it and fix it + this.canvas.renderAll().renderAll(); + } + + this.setCoords(); + this.fire('changed'); + this.canvas && this.canvas.fire('text:changed', { target: this }); + }, + + /** + * @private + * @param {Event} e Event object + */ + _removeCharsNearCursor: function(e) { + if (this.selectionStart !== 0) { + + if (e.metaKey) { + // remove all till the start of current line + var leftLineBoundary = this.findLineBoundaryLeft(this.selectionStart); + + this._removeCharsFromTo(leftLineBoundary, this.selectionStart); + this.selectionStart = leftLineBoundary; + } + else if (e.altKey) { + // remove all till the start of current word + var leftWordBoundary = this.findWordBoundaryLeft(this.selectionStart); + + this._removeCharsFromTo(leftWordBoundary, this.selectionStart); + this.selectionStart = leftWordBoundary; + } + else { + var isBeginningOfLine = this.text.slice(this.selectionStart - 1, this.selectionStart) === '\n'; + this.removeStyleObject(isBeginningOfLine); + + this.selectionStart--; + this.text = this.text.slice(0, this.selectionStart) + + this.text.slice(this.selectionStart + 1); + } + } + } +}); + + +/* _TO_SVG_START_ */ +fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { + + /** + * @private + */ + _setSVGTextLineText: function(textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects) { + if (!this.styles[lineIndex]) { + this.callSuper('_setSVGTextLineText', + textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier); + } + else { + this._setSVGTextLineChars( + textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects); + } + }, + + /** + * @private + */ + _setSVGTextLineChars: function(textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects) { + + var yProp = lineIndex === 0 || this.useNative ? 'y' : 'dy', + chars = textLine.split(''), + charOffset = 0, + lineLeftOffset = this._getSVGLineLeftOffset(lineIndex), + lineTopOffset = this._getSVGLineTopOffset(lineIndex), + heightOfLine = this._getHeightOfLine(this.ctx, lineIndex); + + for (var i = 0, len = chars.length; i < len; i++) { + var styleDecl = this.styles[lineIndex][i] || { }; + + textSpans.push( + this._createTextCharSpan( + chars[i], styleDecl, lineLeftOffset, lineTopOffset, yProp, charOffset)); + + var charWidth = this._getWidthOfChar(this.ctx, chars[i], lineIndex, i); + + if (styleDecl.textBackgroundColor) { + textBgRects.push( + this._createTextCharBg( + styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset)); + } + + charOffset += charWidth; + } + }, + + /** + * @private + */ + _getSVGLineLeftOffset: function(lineIndex) { + return (this._boundaries && this._boundaries[lineIndex]) + ? fabric.util.toFixed(this._boundaries[lineIndex].left, 2) + : 0; + }, + + /** + * @private + */ + _getSVGLineTopOffset: function(lineIndex) { + var lineTopOffset = 0; + for (var j = 0; j <= lineIndex; j++) { + lineTopOffset += this._getHeightOfLine(this.ctx, j); + } + return lineTopOffset - this.height / 2; + }, + + /** + * @private + */ + _createTextCharBg: function(styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset) { + return [ + //jscs:disable validateIndentation + '' + //jscs:enable validateIndentation + ].join(''); + }, + + /** + * @private + */ + _createTextCharSpan: function(_char, styleDecl, lineLeftOffset, lineTopOffset, yProp, charOffset) { + + var fillStyles = this.getSvgStyles.call(fabric.util.object.extend({ + visible: true, + fill: this.fill, + stroke: this.stroke, + type: 'text' + }, styleDecl)); + + return [ + //jscs:disable validateIndentation + '', + + fabric.util.string.escapeXml(_char), + '' + //jscs:enable validateIndentation + ].join(''); + } +}); +/* _TO_SVG_END_ */ + + +(function() { + + if (typeof document !== 'undefined' && typeof window !== 'undefined') { + return; + } + + var DOMParser = require('xmldom').DOMParser, + URL = require('url'), + HTTP = require('http'), + HTTPS = require('https'), + + Canvas = require('canvas'), + Image = require('canvas').Image; + + /** @private */ + function request(url, encoding, callback) { + var oURL = URL.parse(url); + + // detect if http or https is used + if ( !oURL.port ) { + oURL.port = ( oURL.protocol.indexOf('https:') === 0 ) ? 443 : 80; + } + + // assign request handler based on protocol + var reqHandler = ( oURL.port === 443 ) ? HTTPS : HTTP, + req = reqHandler.request({ + hostname: oURL.hostname, + port: oURL.port, + path: oURL.path, + method: 'GET' + }, function(response) { + var body = ''; + if (encoding) { + response.setEncoding(encoding); + } + response.on('end', function () { + callback(body); + }); + response.on('data', function (chunk) { + if (response.statusCode === 200) { + body += chunk; + } + }); + }); + + req.on('error', function(err) { + if (err.errno === process.ECONNREFUSED) { + fabric.log('ECONNREFUSED: connection refused to ' + oURL.hostname + ':' + oURL.port); + } + else { + fabric.log(err.message); + } + }); + + req.end(); + } + + /** @private */ + function requestFs(path, callback){ + var fs = require('fs'); + fs.readFile(path, function (err, data) { + if (err) { + fabric.log(err); + throw err; + } + else { + callback(data); + } + }); + } + + fabric.util.loadImage = function(url, callback, context) { + function createImageAndCallBack(data) { + img.src = new Buffer(data, 'binary'); + // preserving original url, which seems to be lost in node-canvas + img._src = url; + callback && callback.call(context, img); + } + var img = new Image(); + if (url && (url instanceof Buffer || url.indexOf('data') === 0)) { + img.src = img._src = url; + callback && callback.call(context, img); + } + else if (url && url.indexOf('http') !== 0) { + requestFs(url, createImageAndCallBack); + } + else if (url) { + request(url, 'binary', createImageAndCallBack); + } + else { + callback && callback.call(context, url); + } + }; + + fabric.loadSVGFromURL = function(url, callback, reviver) { + url = url.replace(/^\n\s*/, '').replace(/\?.*$/, '').trim(); + if (url.indexOf('http') !== 0) { + requestFs(url, function(body) { + fabric.loadSVGFromString(body.toString(), callback, reviver); + }); + } + else { + request(url, '', function(body) { + fabric.loadSVGFromString(body, callback, reviver); + }); + } + }; + + fabric.loadSVGFromString = function(string, callback, reviver) { + var doc = new DOMParser().parseFromString(string); + fabric.parseSVGDocument(doc.documentElement, function(results, options) { + callback && callback(results, options); + }, reviver); + }; + + fabric.util.getScript = function(url, callback) { + request(url, '', function(body) { + eval(body); + callback && callback(); + }); + }; + + fabric.Image.fromObject = function(object, callback) { + fabric.util.loadImage(object.src, function(img) { + var oImg = new fabric.Image(img); + + oImg._initConfig(object); + oImg._initFilters(object, function(filters) { + oImg.filters = filters || [ ]; + callback && callback(oImg); + }); + }); + }; + + /** + * Only available when running fabric on node.js + * @param {Number} width Canvas width + * @param {Number} height Canvas height + * @param {Object} [options] Options to pass to FabricCanvas. + * @param {Object} [nodeCanvasOptions] Options to pass to NodeCanvas. + * @return {Object} wrapped canvas instance + */ + fabric.createCanvasForNode = function(width, height, options, nodeCanvasOptions) { + nodeCanvasOptions = nodeCanvasOptions || options; + + var canvasEl = fabric.document.createElement('canvas'), + nodeCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions); + + // jsdom doesn't create style on canvas element, so here be temp. workaround + canvasEl.style = { }; + + canvasEl.width = nodeCanvas.width; + canvasEl.height = nodeCanvas.height; + + var FabricCanvas = fabric.Canvas || fabric.StaticCanvas, + fabricCanvas = new FabricCanvas(canvasEl, options); + + fabricCanvas.contextContainer = nodeCanvas.getContext('2d'); + fabricCanvas.nodeCanvas = nodeCanvas; + fabricCanvas.Font = Canvas.Font; + + return fabricCanvas; + }; + + /** @ignore */ + fabric.StaticCanvas.prototype.createPNGStream = function() { + return this.nodeCanvas.createPNGStream(); + }; + + fabric.StaticCanvas.prototype.createJPEGStream = function(opts) { + return this.nodeCanvas.createJPEGStream(opts); + }; + + var origSetWidth = fabric.StaticCanvas.prototype.setWidth; + fabric.StaticCanvas.prototype.setWidth = function(width, options) { + origSetWidth.call(this, width, options); + this.nodeCanvas.width = width; + return this; + }; + if (fabric.Canvas) { + fabric.Canvas.prototype.setWidth = fabric.StaticCanvas.prototype.setWidth; + } + + var origSetHeight = fabric.StaticCanvas.prototype.setHeight; + fabric.StaticCanvas.prototype.setHeight = function(height, options) { + origSetHeight.call(this, height, options); + this.nodeCanvas.height = height; + return this; + }; + if (fabric.Canvas) { + fabric.Canvas.prototype.setHeight = fabric.StaticCanvas.prototype.setHeight; + } + +})(); + +/* pako 0.2.3 nodeca/pako */!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.pako=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o Array + * + * Chunks of output data, if [[Inflate#onData]] not overriden. + **/ + +/** + * Inflate.result -> Uint8Array|Array|String + * + * Uncompressed result, generated by default [[Inflate#onData]] + * and [[Inflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Inflate#push]] with `Z_FINISH` / `true` param). + **/ + +/** + * Inflate.err -> Number + * + * Error code after inflate finished. 0 (Z_OK) on success. + * Should be checked if broken data possible. + **/ + +/** + * Inflate.msg -> String + * + * Error message, if [[Inflate.err]] != 0 + **/ + + +/** + * new Inflate(options) + * - options (Object): zlib inflate options. + * + * Creates new inflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `windowBits` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw inflate + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * By default, when no options set, autodetect deflate/gzip data format via + * wrapper header. + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var inflate = new pako.Inflate({ level: 3}); + * + * inflate.push(chunk1, false); + * inflate.push(chunk2, true); // true -> last chunk + * + * if (inflate.err) { throw new Error(inflate.err); } + * + * console.log(inflate.result); + * ``` + **/ +var Inflate = function(options) { + + this.options = utils.assign({ + chunkSize: 16384, + windowBits: 0, + to: '' + }, options || {}); + + var opt = this.options; + + // Force window size for `raw` data, if not set directly, + // because we have no header for autodetect. + if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { + opt.windowBits = -opt.windowBits; + if (opt.windowBits === 0) { opt.windowBits = -15; } + } + + // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate + if ((opt.windowBits >= 0) && (opt.windowBits < 16) && + !(options && options.windowBits)) { + opt.windowBits += 32; + } + + // Gzip header has no info about windows size, we can do autodetect only + // for deflate. So, if window size not set, force it to max when gzip possible + if ((opt.windowBits > 15) && (opt.windowBits < 48)) { + // bit 3 (16) -> gzipped data + // bit 4 (32) -> autodetect gzip/deflate + if ((opt.windowBits & 15) === 0) { + opt.windowBits |= 15; + } + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new zstream(); + this.strm.avail_out = 0; + + var status = zlib_inflate.inflateInit2( + this.strm, + opt.windowBits + ); + + if (status !== c.Z_OK) { + throw new Error(msg[status]); + } + + this.header = new gzheader(); + + zlib_inflate.inflateGetHeader(this.strm, this.header); +}; + +/** + * Inflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|String): input data + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH. + * + * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with + * new output chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That flush internal pending buffers and call + * [[Inflate#onEnd]]. + * + * On fail call [[Inflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ +Inflate.prototype.push = function(data, mode) { + var strm = this.strm; + var chunkSize = this.options.chunkSize; + var status, _mode; + var next_out_utf8, tail, utf8str; + + if (this.ended) { return false; } + _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // Only binary strings can be decompressed on practice + strm.input = strings.binstring2buf(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + do { + if (strm.avail_out === 0) { + strm.output = new utils.Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + + status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); /* no bad return value */ + + if (status !== c.Z_STREAM_END && status !== c.Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + + if (strm.next_out) { + if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && _mode === c.Z_FINISH)) { + + if (this.options.to === 'string') { + + next_out_utf8 = strings.utf8border(strm.output, strm.next_out); + + tail = strm.next_out - next_out_utf8; + utf8str = strings.buf2string(strm.output, next_out_utf8); + + // move tail + strm.next_out = tail; + strm.avail_out = chunkSize - tail; + if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); } + + this.onData(utf8str); + + } else { + this.onData(utils.shrinkBuf(strm.output, strm.next_out)); + } + } + } + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== c.Z_STREAM_END); + + if (status === c.Z_STREAM_END) { + _mode = c.Z_FINISH; + } + // Finalize on the last chunk. + if (_mode === c.Z_FINISH) { + status = zlib_inflate.inflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === c.Z_OK; + } + + return true; +}; + + +/** + * Inflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): ouput data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ +Inflate.prototype.onData = function(chunk) { + this.chunks.push(chunk); +}; + + +/** + * Inflate#onEnd(status) -> Void + * - status (Number): inflate status. 0 (Z_OK) on success, + * other if not. + * + * Called once after you tell inflate that input stream complete + * or error happenned. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ +Inflate.prototype.onEnd = function(status) { + // On success - join + if (status === c.Z_OK) { + if (this.options.to === 'string') { + // Glue & convert here, until we teach pako to send + // utf8 alligned strings to onData + this.result = this.chunks.join(''); + } else { + this.result = utils.flattenChunks(this.chunks); + } + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; +}; + + +/** + * inflate(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * Decompress `data` with inflate/ungzip and `options`. Autodetect + * format via wrapper header by default. That's why we don't provide + * separate `ungzip` method. + * + * Supported options are: + * + * - windowBits + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information. + * + * Sugar (options): + * + * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify + * negative windowBits implicitly. + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , input = pako.deflate([1,2,3,4,5,6,7,8,9]) + * , output; + * + * try { + * output = pako.inflate(input); + * } catch (err) + * console.log(err); + * } + * ``` + **/ +function inflate(input, options) { + var inflator = new Inflate(options); + + inflator.push(input, true); + + // That will never happens, if you don't cheat with options :) + if (inflator.err) { throw inflator.msg; } + + return inflator.result; +} + + +/** + * inflateRaw(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * The same as [[inflate]], but creates raw data, without wrapper + * (header and adler32 crc). + **/ +function inflateRaw(input, options) { + options = options || {}; + options.raw = true; + return inflate(input, options); +} + + +/** + * ungzip(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * Just shortcut to [[inflate]], because it autodetects format + * by header.content. Done for convenience. + **/ + + +exports.Inflate = Inflate; +exports.inflate = inflate; +exports.inflateRaw = inflateRaw; +exports.ungzip = inflate; + +},{"./utils/common":2,"./utils/strings":3,"./zlib/constants":5,"./zlib/gzheader":7,"./zlib/inflate.js":9,"./zlib/messages":11,"./zlib/zstream":12}],2:[function(_dereq_,module,exports){ +'use strict'; + + +var TYPED_OK = (typeof Uint8Array !== 'undefined') && + (typeof Uint16Array !== 'undefined') && + (typeof Int32Array !== 'undefined'); + + +exports.assign = function (obj /*from1, from2, from3, ...*/) { + var sources = Array.prototype.slice.call(arguments, 1); + while (sources.length) { + var source = sources.shift(); + if (!source) { continue; } + + if (typeof(source) !== 'object') { + throw new TypeError(source + 'must be non-object'); + } + + for (var p in source) { + if (source.hasOwnProperty(p)) { + obj[p] = source[p]; + } + } + } + + return obj; +}; + + +// reduce buffer size, avoiding mem copy +exports.shrinkBuf = function (buf, size) { + if (buf.length === size) { return buf; } + if (buf.subarray) { return buf.subarray(0, size); } + buf.length = size; + return buf; +}; + + +var fnTyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + if (src.subarray && dest.subarray) { + dest.set(src.subarray(src_offs, src_offs+len), dest_offs); + return; + } + // Fallback to ordinary array + for(var i=0; i= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); +} +_utf8len[254]=_utf8len[254]=1; // Invalid sequence start + + +// convert string to array (typed, when possible) +exports.string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + buf = new utils.Buf8(buf_len); + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Helper (used in 2 places) +function buf2binstring(buf, len) { + // use fallback for big arrays to avoid stack overflow + if (len < 65537) { + if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) { + return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len)); + } + } + + var result = ''; + for(var i=0; i < len; i++) { + result += String.fromCharCode(buf[i]); + } + return result; +} + + +// Convert byte array to binary string +exports.buf2binstring = function(buf) { + return buf2binstring(buf, buf.length); +}; + + +// Convert binary string (typed, when possible) +exports.binstring2buf = function(str) { + var buf = new utils.Buf8(str.length); + for(var i=0, len=buf.length; i < len; i++) { + buf[i] = str.charCodeAt(i); + } + return buf; +}; + + +// convert array to string +exports.buf2string = function (buf, max) { + var i, out, c, c_len; + var len = max || buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + return buf2binstring(utf16buf, out); +}; + + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +exports.utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +},{"./common":2}],4:[function(_dereq_,module,exports){ +'use strict'; + +// Note: adler32 takes 12% for level 0 and 2% for level 6. +// It doesn't worth to make additional optimizationa as in original. +// Small size is preferable. + +function adler32(adler, buf, len, pos) { + var s1 = (adler & 0xffff) |0 + , s2 = ((adler >>> 16) & 0xffff) |0 + , n = 0; + + while (len !== 0) { + // Set limit ~ twice less than 5552, to keep + // s2 in 31-bits, because we force signed ints. + // in other case %= will fail. + n = len > 2000 ? 2000 : len; + len -= n; + + do { + s1 = (s1 + buf[pos++]) |0; + s2 = (s2 + s1) |0; + } while (--n); + + s1 %= 65521; + s2 %= 65521; + } + + return (s1 | (s2 << 16)) |0; +} + + +module.exports = adler32; +},{}],5:[function(_dereq_,module,exports){ +module.exports = { + + /* Allowed flush values; see deflate() and inflate() below for details */ + Z_NO_FLUSH: 0, + Z_PARTIAL_FLUSH: 1, + Z_SYNC_FLUSH: 2, + Z_FULL_FLUSH: 3, + Z_FINISH: 4, + Z_BLOCK: 5, + Z_TREES: 6, + + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + Z_OK: 0, + Z_STREAM_END: 1, + Z_NEED_DICT: 2, + Z_ERRNO: -1, + Z_STREAM_ERROR: -2, + Z_DATA_ERROR: -3, + //Z_MEM_ERROR: -4, + Z_BUF_ERROR: -5, + //Z_VERSION_ERROR: -6, + + /* compression levels */ + Z_NO_COMPRESSION: 0, + Z_BEST_SPEED: 1, + Z_BEST_COMPRESSION: 9, + Z_DEFAULT_COMPRESSION: -1, + + + Z_FILTERED: 1, + Z_HUFFMAN_ONLY: 2, + Z_RLE: 3, + Z_FIXED: 4, + Z_DEFAULT_STRATEGY: 0, + + /* Possible values of the data_type field (though see inflate()) */ + Z_BINARY: 0, + Z_TEXT: 1, + //Z_ASCII: 1, // = Z_TEXT (deprecated) + Z_UNKNOWN: 2, + + /* The deflate compression method */ + Z_DEFLATED: 8 + //Z_NULL: null // Use -1 or null inline, depending on var type +}; +},{}],6:[function(_dereq_,module,exports){ +'use strict'; + +// Note: we can't get significant speed boost here. +// So write code to minimize size - no pregenerated tables +// and array tools dependencies. + + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for(var n =0; n < 256; n++){ + c = n; + for(var k =0; k < 8; k++){ + c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable + , end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + + +module.exports = crc32; +},{}],7:[function(_dereq_,module,exports){ +'use strict'; + + +function GZheader() { + /* true if compressed data believed to be text */ + this.text = 0; + /* modification time */ + this.time = 0; + /* extra flags (not used when writing a gzip file) */ + this.xflags = 0; + /* operating system */ + this.os = 0; + /* pointer to extra field or Z_NULL if none */ + this.extra = null; + /* extra field length (valid if extra != Z_NULL) */ + this.extra_len = 0; // Actually, we don't need it in JS, + // but leave for few code modifications + + // + // Setup limits is not necessary because in js we should not preallocate memory + // for inflate use constant limit in 65536 bytes + // + + /* space at extra (only when reading header) */ + // this.extra_max = 0; + /* pointer to zero-terminated file name or Z_NULL */ + this.name = ''; + /* space at name (only when reading header) */ + // this.name_max = 0; + /* pointer to zero-terminated comment or Z_NULL */ + this.comment = ''; + /* space at comment (only when reading header) */ + // this.comm_max = 0; + /* true if there was or will be a header crc */ + this.hcrc = 0; + /* true when done reading gzip header (not used when writing a gzip file) */ + this.done = false; +} + +module.exports = GZheader; +},{}],8:[function(_dereq_,module,exports){ +'use strict'; + +// See state defs from inflate.js +var BAD = 30; /* got a data error -- remain here until reset */ +var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state.mode === LEN + strm.avail_in >= 6 + strm.avail_out >= 258 + start >= strm.avail_out + state.bits < 8 + + On return, state.mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm.avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm.avail_out >= 258 for each loop to avoid checking for + output space. + */ +module.exports = function inflate_fast(strm, start) { + var state; + var _in; /* local strm.input */ + var last; /* have enough input while in < last */ + var _out; /* local strm.output */ + var beg; /* inflate()'s initial strm.output */ + var end; /* while out < end, enough space available */ +//#ifdef INFLATE_STRICT + var dmax; /* maximum distance from zlib header */ +//#endif + var wsize; /* window size or zero if not using window */ + var whave; /* valid bytes in the window */ + var wnext; /* window write index */ + var window; /* allocated sliding window, if wsize != 0 */ + var hold; /* local strm.hold */ + var bits; /* local strm.bits */ + var lcode; /* local strm.lencode */ + var dcode; /* local strm.distcode */ + var lmask; /* mask for first level of length codes */ + var dmask; /* mask for first level of distance codes */ + var here; /* retrieved table entry */ + var op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + var len; /* match length, unused bytes */ + var dist; /* match distance */ + var from; /* where to copy match from */ + var from_source; + + + var input, output; // JS specific, because we have no pointers + + /* copy state to local variables */ + state = strm.state; + //here = state.here; + _in = strm.next_in; + input = strm.input; + last = _in + (strm.avail_in - 5); + _out = strm.next_out; + output = strm.output; + beg = _out - (start - strm.avail_out); + end = _out + (strm.avail_out - 257); +//#ifdef INFLATE_STRICT + dmax = state.dmax; +//#endif + wsize = state.wsize; + whave = state.whave; + wnext = state.wnext; + window = state.window; + hold = state.hold; + bits = state.bits; + lcode = state.lencode; + dcode = state.distcode; + lmask = (1 << state.lenbits) - 1; + dmask = (1 << state.distbits) - 1; + + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + + here = lcode[hold & lmask]; + + dolen: + for (;;) { // Goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + if (op === 0) { /* literal */ + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + output[_out++] = here & 0xffff/*here.val*/; + } + else if (op & 16) { /* length base */ + len = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & ((1 << op) - 1); + hold >>>= op; + bits -= op; + } + //Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; + + dodist: + for (;;) { // goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + + if (op & 16) { /* distance base */ + dist = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & ((1 << op) - 1); +//#ifdef INFLATE_STRICT + if (dist > dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; + } +//#endif + hold >>>= op; + bits -= op; + //Tracevv((stderr, "inflate: distance %u\n", dist)); + op = _out - beg; /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; + } + +// (!) This block is disabled in zlib defailts, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// if (len <= op - whave) { +// do { +// output[_out++] = 0; +// } while (--len); +// continue top; +// } +// len -= op - whave; +// do { +// output[_out++] = 0; +// } while (--op > whave); +// if (op === 0) { +// from = _out - dist; +// do { +// output[_out++] = output[from++]; +// } while (--len); +// continue top; +// } +//#endif + } + from = 0; // window index + from_source = window; + if (wnext === 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + output[_out++] = window[from++]; + } while (--op); + from = 0; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + output[_out++] = window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } + } + else { + from = _out - dist; /* copy direct from output */ + do { /* minimum length is three */ + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } + } + } + else if ((op & 64) === 0) { /* 2nd level distance code */ + here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dodist; + } + else { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } + else if ((op & 64) === 0) { /* 2nd level length code */ + here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dolen; + } + else if (op & 32) { /* end-of-block */ + //Tracevv((stderr, "inflate: end of block\n")); + state.mode = TYPE; + break top; + } + else { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } while (_in < last && _out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; + + /* update state and return */ + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); + strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); + state.hold = hold; + state.bits = bits; + return; +}; + +},{}],9:[function(_dereq_,module,exports){ +'use strict'; + + +var utils = _dereq_('../utils/common'); +var adler32 = _dereq_('./adler32'); +var crc32 = _dereq_('./crc32'); +var inflate_fast = _dereq_('./inffast'); +var inflate_table = _dereq_('./inftrees'); + +var CODES = 0; +var LENS = 1; +var DISTS = 2; + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + + +/* Allowed flush values; see deflate() and inflate() below for details */ +//var Z_NO_FLUSH = 0; +//var Z_PARTIAL_FLUSH = 1; +//var Z_SYNC_FLUSH = 2; +//var Z_FULL_FLUSH = 3; +var Z_FINISH = 4; +var Z_BLOCK = 5; +var Z_TREES = 6; + + +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ +var Z_OK = 0; +var Z_STREAM_END = 1; +var Z_NEED_DICT = 2; +//var Z_ERRNO = -1; +var Z_STREAM_ERROR = -2; +var Z_DATA_ERROR = -3; +var Z_MEM_ERROR = -4; +var Z_BUF_ERROR = -5; +//var Z_VERSION_ERROR = -6; + +/* The deflate compression method */ +var Z_DEFLATED = 8; + + +/* STATES ====================================================================*/ +/* ===========================================================================*/ + + +var HEAD = 1; /* i: waiting for magic header */ +var FLAGS = 2; /* i: waiting for method and flags (gzip) */ +var TIME = 3; /* i: waiting for modification time (gzip) */ +var OS = 4; /* i: waiting for extra flags and operating system (gzip) */ +var EXLEN = 5; /* i: waiting for extra length (gzip) */ +var EXTRA = 6; /* i: waiting for extra bytes (gzip) */ +var NAME = 7; /* i: waiting for end of file name (gzip) */ +var COMMENT = 8; /* i: waiting for end of comment (gzip) */ +var HCRC = 9; /* i: waiting for header crc (gzip) */ +var DICTID = 10; /* i: waiting for dictionary check value */ +var DICT = 11; /* waiting for inflateSetDictionary() call */ +var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ +var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ +var STORED = 14; /* i: waiting for stored size (length and complement) */ +var COPY_ = 15; /* i/o: same as COPY below, but only first time in */ +var COPY = 16; /* i/o: waiting for input or output to copy stored block */ +var TABLE = 17; /* i: waiting for dynamic block table lengths */ +var LENLENS = 18; /* i: waiting for code length code lengths */ +var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ +var LEN_ = 20; /* i: same as LEN below, but only first time in */ +var LEN = 21; /* i: waiting for length/lit/eob code */ +var LENEXT = 22; /* i: waiting for length extra bits */ +var DIST = 23; /* i: waiting for distance code */ +var DISTEXT = 24; /* i: waiting for distance extra bits */ +var MATCH = 25; /* o: waiting for output space to copy string */ +var LIT = 26; /* o: waiting for output space to write literal */ +var CHECK = 27; /* i: waiting for 32-bit check value */ +var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ +var DONE = 29; /* finished check, done -- remain here until reset */ +var BAD = 30; /* got a data error -- remain here until reset */ +var MEM = 31; /* got an inflate() memory error -- remain here until reset */ +var SYNC = 32; /* looking for synchronization bytes to restart inflate() */ + +/* ===========================================================================*/ + + + +var ENOUGH_LENS = 852; +var ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +var MAX_WBITS = 15; +/* 32K LZ77 window */ +var DEF_WBITS = MAX_WBITS; + + +function ZSWAP32(q) { + return (((q >>> 24) & 0xff) + + ((q >>> 8) & 0xff00) + + ((q & 0xff00) << 8) + + ((q & 0xff) << 24)); +} + + +function InflateState() { + this.mode = 0; /* current inflate mode */ + this.last = false; /* true if processing last block */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.havedict = false; /* true if dictionary provided */ + this.flags = 0; /* gzip header method and flags (0 if zlib) */ + this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ + this.check = 0; /* protected copy of check value */ + this.total = 0; /* protected copy of output count */ + // TODO: may be {} + this.head = null; /* where to save gzip header information */ + + /* sliding window */ + this.wbits = 0; /* log base 2 of requested window size */ + this.wsize = 0; /* window size or zero if not using window */ + this.whave = 0; /* valid bytes in the window */ + this.wnext = 0; /* window write index */ + this.window = null; /* allocated sliding window, if needed */ + + /* bit accumulator */ + this.hold = 0; /* input bit accumulator */ + this.bits = 0; /* number of bits in "in" */ + + /* for string and stored block copying */ + this.length = 0; /* literal or length of data to copy */ + this.offset = 0; /* distance back to copy string from */ + + /* for table and code decoding */ + this.extra = 0; /* extra bits needed */ + + /* fixed and dynamic code tables */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ + this.lenbits = 0; /* index bits for lencode */ + this.distbits = 0; /* index bits for distcode */ + + /* dynamic table building */ + this.ncode = 0; /* number of code length code lengths */ + this.nlen = 0; /* number of length code lengths */ + this.ndist = 0; /* number of distance code lengths */ + this.have = 0; /* number of code lengths in lens[] */ + this.next = null; /* next available space in codes[] */ + + this.lens = new utils.Buf16(320); /* temporary storage for code lengths */ + this.work = new utils.Buf16(288); /* work area for code table building */ + + /* + because we don't have pointers in js, we use lencode and distcode directly + as buffers so we don't need codes + */ + //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ + this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ + this.distdyn = null; /* dynamic table for distance codes (JS specific) */ + this.sane = 0; /* if false, allow invalid distance too far */ + this.back = 0; /* bits back of last unprocessed length/lit */ + this.was = 0; /* initial length of match */ +} + +function inflateResetKeep(strm) { + var state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ''; /*Z_NULL*/ + if (state.wrap) { /* to support ill-conceived Java test suite */ + strm.adler = state.wrap & 1; + } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.dmax = 32768; + state.head = null/*Z_NULL*/; + state.hold = 0; + state.bits = 0; + //state.lencode = state.distcode = state.next = state.codes; + state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS); + state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS); + + state.sane = 1; + state.back = -1; + //Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +function inflateReset(strm) { + var state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); + +} + +function inflateReset2(strm, windowBits) { + var wrap; + var state; + + /* get the state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; + if (windowBits < 48) { + windowBits &= 15; + } + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } + + /* update state and reset the rest of it */ + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); +} + +function inflateInit2(strm, windowBits) { + var ret; + var state; + + if (!strm) { return Z_STREAM_ERROR; } + //strm.msg = Z_NULL; /* in case we return an error */ + + state = new InflateState(); + + //if (state === Z_NULL) return Z_MEM_ERROR; + //Tracev((stderr, "inflate: allocated\n")); + strm.state = state; + state.window = null/*Z_NULL*/; + ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK) { + strm.state = null/*Z_NULL*/; + } + return ret; +} + +function inflateInit(strm) { + return inflateInit2(strm, DEF_WBITS); +} + + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +var virgin = true; + +var lenfix, distfix; // We have no pointers in JS, so keep tables separate + +function fixedtables(state) { + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + var sym; + + lenfix = new utils.Buf32(512); + distfix = new utils.Buf32(32); + + /* literal/length table */ + sym = 0; + while (sym < 144) { state.lens[sym++] = 8; } + while (sym < 256) { state.lens[sym++] = 9; } + while (sym < 280) { state.lens[sym++] = 7; } + while (sym < 288) { state.lens[sym++] = 8; } + + inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, {bits: 9}); + + /* distance table */ + sym = 0; + while (sym < 32) { state.lens[sym++] = 5; } + + inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, {bits: 5}); + + /* do this just once */ + virgin = false; + } + + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; +} + + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +function updatewindow(strm, src, end, copy) { + var dist; + var state = strm.state; + + /* if it hasn't been done already, allocate space for the window */ + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; + + state.window = new utils.Buf8(state.wsize); + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state.wsize) { + utils.arraySet(state.window,src, end - state.wsize, state.wsize, 0); + state.wnext = 0; + state.whave = state.wsize; + } + else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; + } + //zmemcpy(state->window + state->wnext, end - copy, dist); + utils.arraySet(state.window,src, end - copy, dist, state.wnext); + copy -= dist; + if (copy) { + //zmemcpy(state->window, end - copy, copy); + utils.arraySet(state.window,src, end - copy, copy, 0); + state.wnext = copy; + state.whave = state.wsize; + } + else { + state.wnext += dist; + if (state.wnext === state.wsize) { state.wnext = 0; } + if (state.whave < state.wsize) { state.whave += dist; } + } + } + return 0; +} + +function inflate(strm, flush) { + var state; + var input, output; // input/output buffers + var next; /* next input INDEX */ + var put; /* next output INDEX */ + var have, left; /* available input and output */ + var hold; /* bit buffer */ + var bits; /* bits in bit buffer */ + var _in, _out; /* save starting available input and output */ + var copy; /* number of stored or match bytes to copy */ + var from; /* where to copy match bytes from */ + var from_source; + var here = 0; /* current decoding table entry */ + var here_bits, here_op, here_val; // paked "here" denormalized (JS specific) + //var last; /* parent table entry */ + var last_bits, last_op, last_val; // paked "last" denormalized (JS specific) + var len; /* length to copy for repeats, bits to drop */ + var ret; /* return code */ + var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */ + var opts; + + var n; // temporary var for NEED_BITS + + var order = /* permutation of code lengths */ + [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; + + + if (!strm || !strm.state || !strm.output || + (!strm.input && strm.avail_in !== 0)) { + return Z_STREAM_ERROR; + } + + state = strm.state; + if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ + + + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + _in = have; + _out = left; + ret = Z_OK; + + inf_leave: // goto emulation + for (;;) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + //=== NEEDBITS(16); + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ + state.check = 0/*crc32(0L, Z_NULL, 0)*/; + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = FLAGS; + break; + } + state.flags = 0; /* expect zlib header */ + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { + strm.msg = 'incorrect header check'; + state.mode = BAD; + break; + } + if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + len = (hold & 0x0f)/*BITS(4)*/ + 8; + if (state.wbits === 0) { + state.wbits = len; + } + else if (len > state.wbits) { + strm.msg = 'invalid window size'; + state.mode = BAD; + break; + } + state.dmax = 1 << len; + //Tracev((stderr, "inflate: zlib header ok\n")); + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = hold & 0x200 ? DICTID : TYPE; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + break; + case FLAGS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.flags = hold; + if ((state.flags & 0xff) !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + if (state.flags & 0xe000) { + strm.msg = 'unknown header flags set'; + state.mode = BAD; + break; + } + if (state.head) { + state.head.text = ((hold >> 8) & 1); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = TIME; + /* falls through */ + case TIME: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.time = hold; + } + if (state.flags & 0x0200) { + //=== CRC4(state.check, hold) + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + hbuf[2] = (hold >>> 16) & 0xff; + hbuf[3] = (hold >>> 24) & 0xff; + state.check = crc32(state.check, hbuf, 4, 0); + //=== + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = OS; + /* falls through */ + case OS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.xflags = (hold & 0xff); + state.head.os = (hold >> 8); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 0x0400) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + else if (state.head) { + state.head.extra = null/*Z_NULL*/; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 0x0400) { + copy = state.length; + if (copy > have) { copy = have; } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + // Use untyped array for more conveniend processing later + state.head.extra = new Array(state.head.extra_len); + } + utils.arraySet( + state.head.extra, + input, + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + copy, + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + //zmemcpy(state.head.extra + len, next, + // len + copy > state.head.extra_max ? + // state.head.extra_max - len : copy); + } + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { break inf_leave; } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 0x0800) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + // TODO: 2 or 1 bytes? + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.name_max*/)) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); + + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 0x1000) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.comm_max*/)) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 0x0200) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.check & 0xffff)) { + strm.msg = 'header crc mismatch'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + if (state.head) { + state.head.hcrc = ((state.flags >> 9) & 1); + state.head.done = true; + } + strm.adler = state.check = 0 /*crc32(0L, Z_NULL, 0)*/; + state.mode = TYPE; + break; + case DICTID: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + strm.adler = state.check = ZSWAP32(hold); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + return Z_NEED_DICT; + } + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = TYPE; + /* falls through */ + case TYPE: + if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } + /* falls through */ + case TYPEDO: + if (state.last) { + //--- BYTEBITS() ---// + hold >>>= bits & 7; + bits -= bits & 7; + //---// + state.mode = CHECK; + break; + } + //=== NEEDBITS(3); */ + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.last = (hold & 0x01)/*BITS(1)*/; + //--- DROPBITS(1) ---// + hold >>>= 1; + bits -= 1; + //---// + + switch ((hold & 0x03)/*BITS(2)*/) { + case 0: /* stored block */ + //Tracev((stderr, "inflate: stored block%s\n", + // state.last ? " (last)" : "")); + state.mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + //Tracev((stderr, "inflate: fixed codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = LEN_; /* decode codes */ + if (flush === Z_TREES) { + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break inf_leave; + } + break; + case 2: /* dynamic block */ + //Tracev((stderr, "inflate: dynamic codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = TABLE; + break; + case 3: + strm.msg = 'invalid block type'; + state.mode = BAD; + } + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break; + case STORED: + //--- BYTEBITS() ---// /* go to byte boundary */ + hold >>>= bits & 7; + bits -= bits & 7; + //---// + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { + strm.msg = 'invalid stored block lengths'; + state.mode = BAD; + break; + } + state.length = hold & 0xffff; + //Tracev((stderr, "inflate: stored length %u\n", + // state.length)); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = COPY_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { copy = have; } + if (copy > left) { copy = left; } + if (copy === 0) { break inf_leave; } + //--- zmemcpy(put, next, copy); --- + utils.arraySet(output, input, next, copy, put); + //---// + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + //Tracev((stderr, "inflate: stored end\n")); + state.mode = TYPE; + break; + case TABLE: + //=== NEEDBITS(14); */ + while (bits < 14) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// +//#ifndef PKZIP_BUG_WORKAROUND + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = 'too many length or distance symbols'; + state.mode = BAD; + break; + } +//#endif + //Tracev((stderr, "inflate: table sizes ok\n")); + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + //=== NEEDBITS(3); + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + // We have separate tables & no pointers. 2 commented lines below not needed. + //state.next = state.codes; + //state.lencode = state.next; + // Switch to use dynamic table + state.lencode = state.lendyn; + state.lenbits = 7; + + opts = {bits: state.lenbits}; + ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; + + if (ret) { + strm.msg = 'invalid code lengths set'; + state.mode = BAD; + break; + } + //Tracev((stderr, "inflate: code lengths ok\n")); + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_val < 16) { + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.lens[state.have++] = here_val; + } + else { + if (here_val === 16) { + //=== NEEDBITS(here.bits + 2); + n = here_bits + 2; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + if (state.have === 0) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 0x03);//BITS(2); + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + } + else if (here_val === 17) { + //=== NEEDBITS(here.bits + 3); + n = here_bits + 3; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 3 + (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + else { + //=== NEEDBITS(here.bits + 7); + n = here_bits + 7; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 11 + (hold & 0x7f);//BITS(7); + //--- DROPBITS(7) ---// + hold >>>= 7; + bits -= 7; + //---// + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } + + /* handle error breaks in while */ + if (state.mode === BAD) { break; } + + /* check for end-of-block code (better have one) */ + if (state.lens[256] === 0) { + strm.msg = 'invalid code -- missing end-of-block'; + state.mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state.lenbits = 9; + + opts = {bits: state.lenbits}; + ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.lenbits = opts.bits; + // state.lencode = state.next; + + if (ret) { + strm.msg = 'invalid literal/lengths set'; + state.mode = BAD; + break; + } + + state.distbits = 6; + //state.distcode.copy(state.codes); + // Switch to use dynamic table + state.distcode = state.distdyn; + opts = {bits: state.distbits}; + ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.distbits = opts.bits; + // state.distcode = state.next; + + if (ret) { + strm.msg = 'invalid distances set'; + state.mode = BAD; + break; + } + //Tracev((stderr, 'inflate: codes ok\n')); + state.mode = LEN_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + inflate_fast(strm, _out); + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + if (state.mode === TYPE) { + state.back = -1; + } + break; + } + state.back = 0; + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) -1)]; /*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if (here_bits <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_op && (here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.lencode[last_val + + ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + state.mode = LIT; + break; + } + if (here_op & 32) { + //Tracevv((stderr, "inflate: end of block\n")); + state.back = -1; + state.mode = TYPE; + break; + } + if (here_op & 64) { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //Tracevv((stderr, "inflate: length %u\n", state.length)); + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (;;) { + here = state.distcode[hold & ((1 << state.distbits) -1)];/*BITS(state.distbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if ((here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.distcode[last_val + + ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + if (here_op & 64) { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break; + } + state.offset = here_val; + state.extra = (here_op) & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.offset += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } +//#ifdef INFLATE_STRICT + if (state.offset > state.dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +//#endif + //Tracevv((stderr, "inflate: distance %u\n", state.offset)); + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { break inf_leave; } + copy = _out - left; + if (state.offset > copy) { /* copy from window */ + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +// (!) This block is disabled in zlib defailts, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// Trace((stderr, "inflate.c too far\n")); +// copy -= state.whave; +// if (copy > state.length) { copy = state.length; } +// if (copy > left) { copy = left; } +// left -= copy; +// state.length -= copy; +// do { +// output[put++] = 0; +// } while (--copy); +// if (state.length === 0) { state.mode = LEN; } +// break; +//#endif + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } + else { + from = state.wnext - copy; + } + if (copy > state.length) { copy = state.length; } + from_source = state.window; + } + else { /* copy from output */ + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { copy = left; } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { state.mode = LEN; } + break; + case LIT: + if (left === 0) { break inf_leave; } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + // Use '|' insdead of '+' to make sure that result is signed + hold |= input[next++] << bits; + bits += 8; + } + //===// + _out -= left; + strm.total_out += _out; + state.total += _out; + if (_out) { + strm.adler = state.check = + /*UPDATE(state.check, put - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); + + } + _out = left; + // NB: crc32 stored as signed 32-bit int, ZSWAP32 returns signed too + if ((state.flags ? hold : ZSWAP32(hold)) !== state.check) { + strm.msg = 'incorrect data check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: check matches trailer\n")); + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.total & 0xffffffff)) { + strm.msg = 'incorrect length check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: length matches trailer\n")); + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END; + break inf_leave; + case BAD: + ret = Z_DATA_ERROR; + break inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR; + } + } + + // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + + if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && + (state.mode < CHECK || flush !== Z_FINISH))) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { + state.mode = MEM; + return Z_MEM_ERROR; + } + } + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if (state.wrap && _out) { + strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); + } + strm.data_type = state.bits + (state.last ? 64 : 0) + + (state.mode === TYPE ? 128 : 0) + + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { + ret = Z_BUF_ERROR; + } + return ret; +} + +function inflateEnd(strm) { + + if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { + return Z_STREAM_ERROR; + } + + var state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK; +} + +function inflateGetHeader(strm, head) { + var state; + + /* check state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } + + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK; +} + + +exports.inflateReset = inflateReset; +exports.inflateReset2 = inflateReset2; +exports.inflateResetKeep = inflateResetKeep; +exports.inflateInit = inflateInit; +exports.inflateInit2 = inflateInit2; +exports.inflate = inflate; +exports.inflateEnd = inflateEnd; +exports.inflateGetHeader = inflateGetHeader; +exports.inflateInfo = 'pako inflate (from Nodeca project)'; + +/* Not implemented +exports.inflateCopy = inflateCopy; +exports.inflateGetDictionary = inflateGetDictionary; +exports.inflateMark = inflateMark; +exports.inflatePrime = inflatePrime; +exports.inflateSetDictionary = inflateSetDictionary; +exports.inflateSync = inflateSync; +exports.inflateSyncPoint = inflateSyncPoint; +exports.inflateUndermine = inflateUndermine; +*/ +},{"../utils/common":2,"./adler32":4,"./crc32":6,"./inffast":8,"./inftrees":10}],10:[function(_dereq_,module,exports){ +'use strict'; + + +var utils = _dereq_('../utils/common'); + +var MAXBITS = 15; +var ENOUGH_LENS = 852; +var ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +var CODES = 0; +var LENS = 1; +var DISTS = 2; + +var lbase = [ /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 +]; + +var lext = [ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 +]; + +var dbase = [ /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0 +]; + +var dext = [ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 +]; + +module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) +{ + var bits = opts.bits; + //here = opts.here; /* table entry for duplication */ + + var len = 0; /* a code's length in bits */ + var sym = 0; /* index of code symbols */ + var min = 0, max = 0; /* minimum and maximum code lengths */ + var root = 0; /* number of index bits for root table */ + var curr = 0; /* number of index bits for current table */ + var drop = 0; /* code bits to drop for sub-table */ + var left = 0; /* number of prefix codes available */ + var used = 0; /* code entries in table used */ + var huff = 0; /* Huffman code */ + var incr; /* for incrementing code, index */ + var fill; /* index for replicating entries */ + var low; /* low bits for current root entry */ + var mask; /* mask for low root bits */ + var next; /* next available space in table */ + var base = null; /* base value table to use */ + var base_index = 0; +// var shoextra; /* extra bits table to use */ + var end; /* use base and extra for symbol > end */ + var count = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* number of codes of each length */ + var offs = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* offsets in table for each length */ + var extra = null; + var extra_index = 0; + + var here_bits, here_op, here_val; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; + } + + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { break; } + } + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + //table.bits[opts.table_index] = 1; //here.bits = (var char)1; + //table.val[opts.table_index++] = 0; //here.val = (var short)0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + + //table.op[opts.table_index] = 64; + //table.bits[opts.table_index] = 1; + //table.val[opts.table_index++] = 0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { break; } + } + if (root < min) { + root = min; + } + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } /* over-subscribed */ + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; /* incomplete set */ + } + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base_index -= 257; + extra = lext; + extra_index -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + var i=0; + /* process all codes and make table entries */ + for (;;) { + i++; + /* create table entry */ + here_bits = len - drop; + if (work[sym] < end) { + here_op = 0; + here_val = work[sym]; + } + else if (work[sym] > end) { + here_op = extra[extra_index + work[sym]]; + here_val = base[base_index + work[sym]]; + } + else { + here_op = 32 + 64; /* end of block */ + here_val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << (len - drop); + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; + } while (fill !== 0); + + /* backwards increment the len-bit code huff */ + incr = 1 << (len - 1); + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) === 0) { + if (len === max) { break; } + len = lens[lens_index + work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) !== low) { + /* if first time, transition to sub-tables */ + if (drop === 0) { + drop = root; + } + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { break; } + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1 << curr; + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + /* point entry in root table to sub-table */ + low = huff & mask; + /*table.op[low] = curr; + table.bits[low] = root; + table.val[low] = next - opts.table_index;*/ + table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff !== 0) { + //table.op[next + huff] = 64; /* invalid code marker */ + //table.bits[next + huff] = len - drop; + //table.val[next + huff] = 0; + table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; + } + + /* set return parameters */ + //opts.table_index += used; + opts.bits = root; + return 0; +}; +},{"../utils/common":2}],11:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = { + '2': 'need dictionary', /* Z_NEED_DICT 2 */ + '1': 'stream end', /* Z_STREAM_END 1 */ + '0': '', /* Z_OK 0 */ + '-1': 'file error', /* Z_ERRNO (-1) */ + '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ + '-3': 'data error', /* Z_DATA_ERROR (-3) */ + '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ + '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ + '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ +}; +},{}],12:[function(_dereq_,module,exports){ +'use strict'; + + +function ZStream() { + /* next input byte */ + this.input = null; // JS specific, because we have no pointers + this.next_in = 0; + /* number of bytes available at input */ + this.avail_in = 0; + /* total number of input bytes read so far */ + this.total_in = 0; + /* next output byte should be put there */ + this.output = null; // JS specific, because we have no pointers + this.next_out = 0; + /* remaining free space at output */ + this.avail_out = 0; + /* total number of bytes output so far */ + this.total_out = 0; + /* last error message, NULL if no error */ + this.msg = ''/*Z_NULL*/; + /* not visible by applications */ + this.state = null; + /* best guess about the data type: binary or text */ + this.data_type = 2/*Z_UNKNOWN*/; + /* adler32 value of the uncompressed data */ + this.adler = 0; +} + +module.exports = ZStream; +},{}]},{},[1]) +(1) +}); +// astroem.js: astronomy utilities compiled to js + +var Astroem = (function() { + + +var Module = { + 'noExitRuntime': true +}; + + +// The Module object: Our interface to the outside world. We import +// and export values on it, and do the work to get that through +// closure compiler if necessary. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to do an eval in order to handle the closure compiler +// case, where this code here is minified but Module was defined +// elsewhere (e.g. case 4 above). We also need to check if Module +// already exists (e.g. case 3 above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module; +if (!Module) Module = (typeof Module !== 'undefined' ? Module : null) || {}; + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. +var moduleOverrides = {}; +for (var key in Module) { + if (Module.hasOwnProperty(key)) { + moduleOverrides[key] = Module[key]; + } +} + +// The environment setup code below is customized to use Module. +// *** Environment setup code *** +var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function'; +var ENVIRONMENT_IS_WEB = typeof window === 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + +if (ENVIRONMENT_IS_NODE) { + // Expose functionality in the same simple way that the shells work + // Note that we pollute the global namespace here, otherwise we break in node + if (!Module['print']) Module['print'] = function print(x) { + process['stdout'].write(x + '\n'); + }; + if (!Module['printErr']) Module['printErr'] = function printErr(x) { + process['stderr'].write(x + '\n'); + }; + + var nodeFS = require('fs'); + var nodePath = require('path'); + + Module['read'] = function read(filename, binary) { + filename = nodePath['normalize'](filename); + var ret = nodeFS['readFileSync'](filename); + // The path is absolute if the normalized version is the same as the resolved. + if (!ret && filename != nodePath['resolve'](filename)) { + filename = path.join(__dirname, '..', 'src', filename); + ret = nodeFS['readFileSync'](filename); + } + if (ret && !binary) ret = ret.toString(); + return ret; + }; + + Module['readBinary'] = function readBinary(filename) { return Module['read'](filename, true) }; + + Module['load'] = function load(f) { + globalEval(read(f)); + }; + + Module['arguments'] = process['argv'].slice(2); + + module['exports'] = Module; +} +else if (ENVIRONMENT_IS_SHELL) { + if (!Module['print']) Module['print'] = print; + if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm + + if (typeof read != 'undefined') { + Module['read'] = read; + } else { + Module['read'] = function read() { throw 'no read() available (jsc?)' }; + } + + Module['readBinary'] = function readBinary(f) { + return read(f, 'binary'); + }; + + if (typeof scriptArgs != 'undefined') { + Module['arguments'] = scriptArgs; + } else if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + + this['Module'] = Module; + + eval("if (typeof gc === 'function' && gc.toString().indexOf('[native code]') > 0) var gc = undefined"); // wipe out the SpiderMonkey shell 'gc' function, which can confuse closure (uses it as a minified name, and it is then initted to a non-falsey value unexpectedly) +} +else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + Module['read'] = function read(url) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + }; + + if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + + if (typeof console !== 'undefined') { + if (!Module['print']) Module['print'] = function print(x) { + console.log(x); + }; + if (!Module['printErr']) Module['printErr'] = function printErr(x) { + console.log(x); + }; + } else { + // Probably a worker, and without console.log. We can do very little here... + var TRY_USE_DUMP = false; + if (!Module['print']) Module['print'] = (TRY_USE_DUMP && (typeof(dump) !== "undefined") ? (function(x) { + dump(x); + }) : (function(x) { + // self.postMessage(x); // enable this if you want stdout to be sent as messages + })); + } + + if (ENVIRONMENT_IS_WEB) { + window['Module'] = Module; + } else { + Module['load'] = importScripts; + } +} +else { + // Unreachable because SHELL is dependant on the others + throw 'Unknown runtime environment. Where are we?'; +} + +function globalEval(x) { + eval.call(null, x); +} +if (!Module['load'] == 'undefined' && Module['read']) { + Module['load'] = function load(f) { + globalEval(Module['read'](f)); + }; +} +if (!Module['print']) { + Module['print'] = function(){}; +} +if (!Module['printErr']) { + Module['printErr'] = Module['print']; +} +if (!Module['arguments']) { + Module['arguments'] = []; +} +// *** Environment setup code *** + +// Closure helpers +Module.print = Module['print']; +Module.printErr = Module['printErr']; + +// Callbacks +Module['preRun'] = []; +Module['postRun'] = []; + +// Merge back in the overrides +for (var key in moduleOverrides) { + if (moduleOverrides.hasOwnProperty(key)) { + Module[key] = moduleOverrides[key]; + } +} + + + +// === Auto-generated preamble library stuff === + +//======================================== +// Runtime code shared with compiler +//======================================== + +var Runtime = { + stackSave: function () { + return STACKTOP; + }, + stackRestore: function (stackTop) { + STACKTOP = stackTop; + }, + forceAlign: function (target, quantum) { + quantum = quantum || 4; + if (quantum == 1) return target; + if (isNumber(target) && isNumber(quantum)) { + return Math.ceil(target/quantum)*quantum; + } else if (isNumber(quantum) && isPowerOfTwo(quantum)) { + return '(((' +target + ')+' + (quantum-1) + ')&' + -quantum + ')'; + } + return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum; + }, + isNumberType: function (type) { + return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES; + }, + isPointerType: function isPointerType(type) { + return type[type.length-1] == '*'; +}, + isStructType: function isStructType(type) { + if (isPointerType(type)) return false; + if (isArrayType(type)) return true; + if (/?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types + // See comment in isStructPointerType() + return type[0] == '%'; +}, + INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0}, + FLOAT_TYPES: {"float":0,"double":0}, + or64: function (x, y) { + var l = (x | 0) | (y | 0); + var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + and64: function (x, y) { + var l = (x | 0) & (y | 0); + var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + xor64: function (x, y) { + var l = (x | 0) ^ (y | 0); + var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + getNativeTypeSize: function (type) { + switch (type) { + case 'i1': case 'i8': return 1; + case 'i16': return 2; + case 'i32': return 4; + case 'i64': return 8; + case 'float': return 4; + case 'double': return 8; + default: { + if (type[type.length-1] === '*') { + return Runtime.QUANTUM_SIZE; // A pointer + } else if (type[0] === 'i') { + var bits = parseInt(type.substr(1)); + assert(bits % 8 === 0); + return bits/8; + } else { + return 0; + } + } + } + }, + getNativeFieldSize: function (type) { + return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE); + }, + dedup: function dedup(items, ident) { + var seen = {}; + if (ident) { + return items.filter(function(item) { + if (seen[item[ident]]) return false; + seen[item[ident]] = true; + return true; + }); + } else { + return items.filter(function(item) { + if (seen[item]) return false; + seen[item] = true; + return true; + }); + } +}, + set: function set() { + var args = typeof arguments[0] === 'object' ? arguments[0] : arguments; + var ret = {}; + for (var i = 0; i < args.length; i++) { + ret[args[i]] = 0; + } + return ret; +}, + STACK_ALIGN: 8, + getAlignSize: function (type, size, vararg) { + // we align i64s and doubles on 64-bit boundaries, unlike x86 + if (!vararg && (type == 'i64' || type == 'double')) return 8; + if (!type) return Math.min(size, 8); // align structures internally to 64 bits + return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE); + }, + calculateStructAlignment: function calculateStructAlignment(type) { + type.flatSize = 0; + type.alignSize = 0; + var diffs = []; + var prev = -1; + var index = 0; + type.flatIndexes = type.fields.map(function(field) { + index++; + var size, alignSize; + if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) { + size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s. + alignSize = Runtime.getAlignSize(field, size); + } else if (Runtime.isStructType(field)) { + if (field[1] === '0') { + // this is [0 x something]. When inside another structure like here, it must be at the end, + // and it adds no size + // XXX this happens in java-nbody for example... assert(index === type.fields.length, 'zero-length in the middle!'); + size = 0; + if (Types.types[field]) { + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } else { + alignSize = type.alignSize || QUANTUM_SIZE; + } + } else { + size = Types.types[field].flatSize; + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } + } else if (field[0] == 'b') { + // bN, large number field, like a [N x i8] + size = field.substr(1)|0; + alignSize = 1; + } else if (field[0] === '<') { + // vector type + size = alignSize = Types.types[field].flatSize; // fully aligned + } else if (field[0] === 'i') { + // illegal integer field, that could not be legalized because it is an internal structure field + // it is ok to have such fields, if we just use them as markers of field size and nothing more complex + size = alignSize = parseInt(field.substr(1))/8; + assert(size % 1 === 0, 'cannot handle non-byte-size field ' + field); + } else { + assert(false, 'invalid type for calculateStructAlignment'); + } + if (type.packed) alignSize = 1; + type.alignSize = Math.max(type.alignSize, alignSize); + var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory + type.flatSize = curr + size; + if (prev >= 0) { + diffs.push(curr-prev); + } + prev = curr; + return curr; + }); + if (type.name_ && type.name_[0] === '[') { + // arrays have 2 elements, so we get the proper difference. then we scale here. that way we avoid + // allocating a potentially huge array for [999999 x i8] etc. + type.flatSize = parseInt(type.name_.substr(1))*type.flatSize/2; + } + type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize); + if (diffs.length == 0) { + type.flatFactor = type.flatSize; + } else if (Runtime.dedup(diffs).length == 1) { + type.flatFactor = diffs[0]; + } + type.needsFlattening = (type.flatFactor != 1); + return type.flatIndexes; + }, + generateStructInfo: function (struct, typeName, offset) { + var type, alignment; + if (typeName) { + offset = offset || 0; + type = (typeof Types === 'undefined' ? Runtime.typeInfo : Types.types)[typeName]; + if (!type) return null; + if (type.fields.length != struct.length) { + printErr('Number of named fields must match the type for ' + typeName + ': possibly duplicate struct names. Cannot return structInfo'); + return null; + } + alignment = type.flatIndexes; + } else { + var type = { fields: struct.map(function(item) { return item[0] }) }; + alignment = Runtime.calculateStructAlignment(type); + } + var ret = { + __size__: type.flatSize + }; + if (typeName) { + struct.forEach(function(item, i) { + if (typeof item === 'string') { + ret[item] = alignment[i] + offset; + } else { + // embedded struct + var key; + for (var k in item) key = k; + ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]); + } + }); + } else { + struct.forEach(function(item, i) { + ret[item[1]] = alignment[i]; + }); + } + return ret; + }, + dynCall: function (sig, ptr, args) { + if (args && args.length) { + if (!args.splice) args = Array.prototype.slice.call(args); + args.splice(0, 0, ptr); + return Module['dynCall_' + sig].apply(null, args); + } else { + return Module['dynCall_' + sig].call(null, ptr); + } + }, + functionPointers: [], + addFunction: function (func) { + for (var i = 0; i < Runtime.functionPointers.length; i++) { + if (!Runtime.functionPointers[i]) { + Runtime.functionPointers[i] = func; + return 2*(1 + i); + } + } + throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; + }, + removeFunction: function (index) { + Runtime.functionPointers[(index-2)/2] = null; + }, + getAsmConst: function (code, numArgs) { + // code is a constant string on the heap, so we can cache these + if (!Runtime.asmConstCache) Runtime.asmConstCache = {}; + var func = Runtime.asmConstCache[code]; + if (func) return func; + var args = []; + for (var i = 0; i < numArgs; i++) { + args.push(String.fromCharCode(36) + i); // $0, $1 etc + } + var source = Pointer_stringify(code); + if (source[0] === '"') { + // tolerate EM_ASM("..code..") even though EM_ASM(..code..) is correct + if (source.indexOf('"', 1) === source.length-1) { + source = source.substr(1, source.length-2); + } else { + // something invalid happened, e.g. EM_ASM("..code($0)..", input) + abort('invalid EM_ASM input |' + source + '|. Please use EM_ASM(..code..) (no quotes) or EM_ASM({ ..code($0).. }, input) (to input values)'); + } + } + try { + var evalled = eval('(function(' + args.join(',') + '){ ' + source + ' })'); // new Function does not allow upvars in node + } catch(e) { + Module.printErr('error in executing inline EM_ASM code: ' + e + ' on: \n\n' + source + '\n\nwith args |' + args + '| (make sure to use the right one out of EM_ASM, EM_ASM_ARGS, etc.)'); + throw e; + } + return Runtime.asmConstCache[code] = evalled; + }, + warnOnce: function (text) { + if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; + if (!Runtime.warnOnce.shown[text]) { + Runtime.warnOnce.shown[text] = 1; + Module.printErr(text); + } + }, + funcWrappers: {}, + getFuncWrapper: function (func, sig) { + assert(sig); + if (!Runtime.funcWrappers[func]) { + Runtime.funcWrappers[func] = function dynCall_wrapper() { + return Runtime.dynCall(sig, func, arguments); + }; + } + return Runtime.funcWrappers[func]; + }, + UTF8Processor: function () { + var buffer = []; + var needed = 0; + this.processCChar = function (code) { + code = code & 0xFF; + + if (buffer.length == 0) { + if ((code & 0x80) == 0x00) { // 0xxxxxxx + return String.fromCharCode(code); + } + buffer.push(code); + if ((code & 0xE0) == 0xC0) { // 110xxxxx + needed = 1; + } else if ((code & 0xF0) == 0xE0) { // 1110xxxx + needed = 2; + } else { // 11110xxx + needed = 3; + } + return ''; + } + + if (needed) { + buffer.push(code); + needed--; + if (needed > 0) return ''; + } + + var c1 = buffer[0]; + var c2 = buffer[1]; + var c3 = buffer[2]; + var c4 = buffer[3]; + var ret; + if (buffer.length == 2) { + ret = String.fromCharCode(((c1 & 0x1F) << 6) | (c2 & 0x3F)); + } else if (buffer.length == 3) { + ret = String.fromCharCode(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); + } else { + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + var codePoint = ((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) | + ((c3 & 0x3F) << 6) | (c4 & 0x3F); + ret = String.fromCharCode( + Math.floor((codePoint - 0x10000) / 0x400) + 0xD800, + (codePoint - 0x10000) % 0x400 + 0xDC00); + } + buffer.length = 0; + return ret; + } + this.processJSString = function processJSString(string) { + /* TODO: use TextEncoder when present, + var encoder = new TextEncoder(); + encoder['encoding'] = "utf-8"; + var utf8Array = encoder['encode'](aMsg.data); + */ + string = unescape(encodeURIComponent(string)); + var ret = []; + for (var i = 0; i < string.length; i++) { + ret.push(string.charCodeAt(i)); + } + return ret; + } + }, + getCompilerSetting: function (name) { + throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work'; + }, + stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = (((STACKTOP)+7)&-8); return ret; }, + staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = (((STATICTOP)+7)&-8); return ret; }, + dynamicAlloc: function (size) { var ret = DYNAMICTOP;DYNAMICTOP = (DYNAMICTOP + size)|0;DYNAMICTOP = (((DYNAMICTOP)+7)&-8); if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();; return ret; }, + alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 8))*(quantum ? quantum : 8); return ret; }, + makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+((low>>>0)))+((+((high>>>0)))*(+4294967296))) : ((+((low>>>0)))+((+((high|0)))*(+4294967296)))); return ret; }, + GLOBAL_BASE: 8, + QUANTUM_SIZE: 4, + __dummy__: 0 +} + + +Module['Runtime'] = Runtime; + + + + + + + + + +//======================================== +// Runtime essentials +//======================================== + +var __THREW__ = 0; // Used in checking for thrown exceptions. + +var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort() +var EXITSTATUS = 0; + +var undef = 0; +// tempInt is used for 32-bit signed values or smaller. tempBigInt is used +// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt +var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD, tempDouble, tempFloat; +var tempI64, tempI64b; +var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9; + +function assert(condition, text) { + if (!condition) { + abort('Assertion failed: ' + text); + } +} + +var globalScope = this; + +// C calling interface. A convenient way to call C functions (in C files, or +// defined with extern "C"). +// +// Note: LLVM optimizations can inline and remove functions, after which you will not be +// able to call them. Closure can also do so. To avoid that, add your function to +// the exports using something like +// +// -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]' +// +// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C") +// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and +// 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit). +// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType, +// except that 'array' is not possible (there is no way for us to know the length of the array) +// @param args An array of the arguments to the function, as native JS values (as in returnType) +// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack). +// @return The return value, as a native JS value (as in returnType) +function ccall(ident, returnType, argTypes, args) { + return ccallFunc(getCFunc(ident), returnType, argTypes, args); +} +Module["ccall"] = ccall; + +// Returns the C function with a specified identifier (for C++, you need to do manual name mangling) +function getCFunc(ident) { + try { + var func = Module['_' + ident]; // closure exported function + if (!func) func = eval('_' + ident); // explicit lookup + } catch(e) { + } + assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)'); + return func; +} + +// Internal function that does a C call using a function, not an identifier +function ccallFunc(func, returnType, argTypes, args) { + var stack = 0; + function toC(value, type) { + if (type == 'string') { + if (value === null || value === undefined || value === 0) return 0; // null string + value = intArrayFromString(value); + type = 'array'; + } + if (type == 'array') { + if (!stack) stack = Runtime.stackSave(); + var ret = Runtime.stackAlloc(value.length); + writeArrayToMemory(value, ret); + return ret; + } + return value; + } + function fromC(value, type) { + if (type == 'string') { + return Pointer_stringify(value); + } + assert(type != 'array'); + return value; + } + var i = 0; + var cArgs = args ? args.map(function(arg) { + return toC(arg, argTypes[i++]); + }) : []; + var ret = fromC(func.apply(null, cArgs), returnType); + if (stack) Runtime.stackRestore(stack); + return ret; +} + +// Returns a native JS wrapper for a C function. This is similar to ccall, but +// returns a function you can call repeatedly in a normal way. For example: +// +// var my_function = cwrap('my_c_function', 'number', ['number', 'number']); +// alert(my_function(5, 22)); +// alert(my_function(99, 12)); +// +function cwrap(ident, returnType, argTypes) { + var func = getCFunc(ident); + return function() { + return ccallFunc(func, returnType, argTypes, Array.prototype.slice.call(arguments)); + } +} +Module["cwrap"] = cwrap; + +// Sets a value in memory in a dynamic way at run-time. Uses the +// type data. This is the same as makeSetValue, except that +// makeSetValue is done at compile-time and generates the needed +// code then, whereas this function picks the right code at +// run-time. +// Note that setValue and getValue only do *aligned* writes and reads! +// Note that ccall uses JS types as for defining types, while setValue and +// getValue need LLVM types ('i8', 'i32') - this is a lower-level operation +function setValue(ptr, value, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': HEAP8[(ptr)]=value; break; + case 'i8': HEAP8[(ptr)]=value; break; + case 'i16': HEAP16[((ptr)>>1)]=value; break; + case 'i32': HEAP32[((ptr)>>2)]=value; break; + case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= (+1) ? (tempDouble > (+0) ? ((Math_min((+(Math_floor((tempDouble)/(+4294967296)))), (+4294967295)))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/(+4294967296))))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break; + case 'float': HEAPF32[((ptr)>>2)]=value; break; + case 'double': HEAPF64[((ptr)>>3)]=value; break; + default: abort('invalid type for setValue: ' + type); + } +} +Module['setValue'] = setValue; + +// Parallel to setValue. +function getValue(ptr, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': return HEAP8[(ptr)]; + case 'i8': return HEAP8[(ptr)]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': return HEAP32[((ptr)>>2)]; + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + default: abort('invalid type for setValue: ' + type); + } + return null; +} +Module['getValue'] = getValue; + +var ALLOC_NORMAL = 0; // Tries to use _malloc() +var ALLOC_STACK = 1; // Lives for the duration of the current function call +var ALLOC_STATIC = 2; // Cannot be freed +var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk +var ALLOC_NONE = 4; // Do not allocate +Module['ALLOC_NORMAL'] = ALLOC_NORMAL; +Module['ALLOC_STACK'] = ALLOC_STACK; +Module['ALLOC_STATIC'] = ALLOC_STATIC; +Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC; +Module['ALLOC_NONE'] = ALLOC_NONE; + +// allocate(): This is for internal use. You can use it yourself as well, but the interface +// is a little tricky (see docs right below). The reason is that it is optimized +// for multiple syntaxes to save space in generated code. So you should +// normally not use allocate(), and instead allocate memory using _malloc(), +// initialize it with setValue(), and so forth. +// @slab: An array of data, or a number. If a number, then the size of the block to allocate, +// in *bytes* (note that this is sometimes confusing: the next parameter does not +// affect this!) +// @types: Either an array of types, one for each byte (or 0 if no type at that position), +// or a single type which is used for the entire block. This only matters if there +// is initial data - if @slab is a number, then this does not matter at all and is +// ignored. +// @allocator: How to allocate memory, see ALLOC_* +function allocate(slab, types, allocator, ptr) { + var zeroinit, size; + if (typeof slab === 'number') { + zeroinit = true; + size = slab; + } else { + zeroinit = false; + size = slab.length; + } + + var singleType = typeof types === 'string' ? types : null; + + var ret; + if (allocator == ALLOC_NONE) { + ret = ptr; + } else { + ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); + } + + if (zeroinit) { + var ptr = ret, stop; + assert((ret & 3) == 0); + stop = ret + (size & ~3); + for (; ptr < stop; ptr += 4) { + HEAP32[((ptr)>>2)]=0; + } + stop = ret + size; + while (ptr < stop) { + HEAP8[((ptr++)|0)]=0; + } + return ret; + } + + if (singleType === 'i8') { + if (slab.subarray || slab.slice) { + HEAPU8.set(slab, ret); + } else { + HEAPU8.set(new Uint8Array(slab), ret); + } + return ret; + } + + var i = 0, type, typeSize, previousType; + while (i < size) { + var curr = slab[i]; + + if (typeof curr === 'function') { + curr = Runtime.getFunctionIndex(curr); + } + + type = singleType || types[i]; + if (type === 0) { + i++; + continue; + } + + if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later + + setValue(ret+i, curr, type); + + // no need to look up size unless type changes, so cache it + if (previousType !== type) { + typeSize = Runtime.getNativeTypeSize(type); + previousType = type; + } + i += typeSize; + } + + return ret; +} +Module['allocate'] = allocate; + +function Pointer_stringify(ptr, /* optional */ length) { + // TODO: use TextDecoder + // Find the length, and check for UTF while doing so + var hasUtf = false; + var t; + var i = 0; + while (1) { + t = HEAPU8[(((ptr)+(i))|0)]; + if (t >= 128) hasUtf = true; + else if (t == 0 && !length) break; + i++; + if (length && i == length) break; + } + if (!length) length = i; + + var ret = ''; + + if (!hasUtf) { + var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack + var curr; + while (length > 0) { + curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); + ret = ret ? ret + curr : curr; + ptr += MAX_CHUNK; + length -= MAX_CHUNK; + } + return ret; + } + + var utf8 = new Runtime.UTF8Processor(); + for (i = 0; i < length; i++) { + t = HEAPU8[(((ptr)+(i))|0)]; + ret += utf8.processCChar(t); + } + return ret; +} +Module['Pointer_stringify'] = Pointer_stringify; + +// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns +// a copy of that string as a Javascript String object. +function UTF16ToString(ptr) { + var i = 0; + + var str = ''; + while (1) { + var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; + if (codeUnit == 0) + return str; + ++i; + // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through. + str += String.fromCharCode(codeUnit); + } +} +Module['UTF16ToString'] = UTF16ToString; + +// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', +// null-terminated and encoded in UTF16LE form. The copy will require at most (str.length*2+1)*2 bytes of space in the HEAP. +function stringToUTF16(str, outPtr) { + for(var i = 0; i < str.length; ++i) { + // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. + var codeUnit = str.charCodeAt(i); // possibly a lead surrogate + HEAP16[(((outPtr)+(i*2))>>1)]=codeUnit; + } + // Null-terminate the pointer to the HEAP. + HEAP16[(((outPtr)+(str.length*2))>>1)]=0; +} +Module['stringToUTF16'] = stringToUTF16; + +// Given a pointer 'ptr' to a null-terminated UTF32LE-encoded string in the emscripten HEAP, returns +// a copy of that string as a Javascript String object. +function UTF32ToString(ptr) { + var i = 0; + + var str = ''; + while (1) { + var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; + if (utf32 == 0) + return str; + ++i; + // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. + if (utf32 >= 0x10000) { + var ch = utf32 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } else { + str += String.fromCharCode(utf32); + } + } +} +Module['UTF32ToString'] = UTF32ToString; + +// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', +// null-terminated and encoded in UTF32LE form. The copy will require at most (str.length+1)*4 bytes of space in the HEAP, +// but can use less, since str.length does not return the number of characters in the string, but the number of UTF-16 code units in the string. +function stringToUTF32(str, outPtr) { + var iChar = 0; + for(var iCodeUnit = 0; iCodeUnit < str.length; ++iCodeUnit) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. + var codeUnit = str.charCodeAt(iCodeUnit); // possibly a lead surrogate + if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { + var trailSurrogate = str.charCodeAt(++iCodeUnit); + codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); + } + HEAP32[(((outPtr)+(iChar*4))>>2)]=codeUnit; + ++iChar; + } + // Null-terminate the pointer to the HEAP. + HEAP32[(((outPtr)+(iChar*4))>>2)]=0; +} +Module['stringToUTF32'] = stringToUTF32; + +function demangle(func) { + var i = 3; + // params, etc. + var basicTypes = { + 'v': 'void', + 'b': 'bool', + 'c': 'char', + 's': 'short', + 'i': 'int', + 'l': 'long', + 'f': 'float', + 'd': 'double', + 'w': 'wchar_t', + 'a': 'signed char', + 'h': 'unsigned char', + 't': 'unsigned short', + 'j': 'unsigned int', + 'm': 'unsigned long', + 'x': 'long long', + 'y': 'unsigned long long', + 'z': '...' + }; + var subs = []; + var first = true; + function dump(x) { + //return; + if (x) Module.print(x); + Module.print(func); + var pre = ''; + for (var a = 0; a < i; a++) pre += ' '; + Module.print (pre + '^'); + } + function parseNested() { + i++; + if (func[i] === 'K') i++; // ignore const + var parts = []; + while (func[i] !== 'E') { + if (func[i] === 'S') { // substitution + i++; + var next = func.indexOf('_', i); + var num = func.substring(i, next) || 0; + parts.push(subs[num] || '?'); + i = next+1; + continue; + } + if (func[i] === 'C') { // constructor + parts.push(parts[parts.length-1]); + i += 2; + continue; + } + var size = parseInt(func.substr(i)); + var pre = size.toString().length; + if (!size || !pre) { i--; break; } // counter i++ below us + var curr = func.substr(i + pre, size); + parts.push(curr); + subs.push(curr); + i += pre + size; + } + i++; // skip E + return parts; + } + function parse(rawList, limit, allowVoid) { // main parser + limit = limit || Infinity; + var ret = '', list = []; + function flushList() { + return '(' + list.join(', ') + ')'; + } + var name; + if (func[i] === 'N') { + // namespaced N-E + name = parseNested().join('::'); + limit--; + if (limit === 0) return rawList ? [name] : name; + } else { + // not namespaced + if (func[i] === 'K' || (first && func[i] === 'L')) i++; // ignore const and first 'L' + var size = parseInt(func.substr(i)); + if (size) { + var pre = size.toString().length; + name = func.substr(i + pre, size); + i += pre + size; + } + } + first = false; + if (func[i] === 'I') { + i++; + var iList = parse(true); + var iRet = parse(true, 1, true); + ret += iRet[0] + ' ' + name + '<' + iList.join(', ') + '>'; + } else { + ret = name; + } + paramLoop: while (i < func.length && limit-- > 0) { + //dump('paramLoop'); + var c = func[i++]; + if (c in basicTypes) { + list.push(basicTypes[c]); + } else { + switch (c) { + case 'P': list.push(parse(true, 1, true)[0] + '*'); break; // pointer + case 'R': list.push(parse(true, 1, true)[0] + '&'); break; // reference + case 'L': { // literal + i++; // skip basic type + var end = func.indexOf('E', i); + var size = end - i; + list.push(func.substr(i, size)); + i += size + 2; // size + 'EE' + break; + } + case 'A': { // array + var size = parseInt(func.substr(i)); + i += size.toString().length; + if (func[i] !== '_') throw '?'; + i++; // skip _ + list.push(parse(true, 1, true)[0] + ' [' + size + ']'); + break; + } + case 'E': break paramLoop; + default: ret += '?' + c; break paramLoop; + } + } + } + if (!allowVoid && list.length === 1 && list[0] === 'void') list = []; // avoid (void) + if (rawList) { + if (ret) { + list.push(ret + '?'); + } + return list; + } else { + return ret + flushList(); + } + } + try { + // Special-case the entry point, since its name differs from other name mangling. + if (func == 'Object._main' || func == '_main') { + return 'main()'; + } + if (typeof func === 'number') func = Pointer_stringify(func); + if (func[0] !== '_') return func; + if (func[1] !== '_') return func; // C function + if (func[2] !== 'Z') return func; + switch (func[3]) { + case 'n': return 'operator new()'; + case 'd': return 'operator delete()'; + } + return parse(); + } catch(e) { + return func; + } +} + +function demangleAll(text) { + return text.replace(/__Z[\w\d_]+/g, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']') }); +} + +function stackTrace() { + var stack = new Error().stack; + return stack ? demangleAll(stack) : '(no stack trace available)'; // Stack trace is not available at least on IE10 and Safari 6. +} + +// Memory management + +var PAGE_SIZE = 4096; +function alignMemoryPage(x) { + return (x+4095)&-4096; +} + +var HEAP; +var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; + +var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area +var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area +var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk + +function enlargeMemory() { + abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.'); +} + +var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; +var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 67108864; +var FAST_MEMORY = Module['FAST_MEMORY'] || 2097152; + +var totalMemory = 4096; +while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) { + if (totalMemory < 16*1024*1024) { + totalMemory *= 2; + } else { + totalMemory += 16*1024*1024 + } +} +if (totalMemory !== TOTAL_MEMORY) { + Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be more reasonable'); + TOTAL_MEMORY = totalMemory; +} + +// Initialize the runtime's memory +// check for full engine support (use string 'subarray' to avoid closure compiler confusion) +assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']), + 'JS engine does not provide full typed array support'); + +var buffer = new ArrayBuffer(TOTAL_MEMORY); +HEAP8 = new Int8Array(buffer); +HEAP16 = new Int16Array(buffer); +HEAP32 = new Int32Array(buffer); +HEAPU8 = new Uint8Array(buffer); +HEAPU16 = new Uint16Array(buffer); +HEAPU32 = new Uint32Array(buffer); +HEAPF32 = new Float32Array(buffer); +HEAPF64 = new Float64Array(buffer); + +// Endianness check (note: assumes compiler arch was little-endian) +HEAP32[0] = 255; +assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system'); + +Module['HEAP'] = HEAP; +Module['HEAP8'] = HEAP8; +Module['HEAP16'] = HEAP16; +Module['HEAP32'] = HEAP32; +Module['HEAPU8'] = HEAPU8; +Module['HEAPU16'] = HEAPU16; +Module['HEAPU32'] = HEAPU32; +Module['HEAPF32'] = HEAPF32; +Module['HEAPF64'] = HEAPF64; + +function callRuntimeCallbacks(callbacks) { + while(callbacks.length > 0) { + var callback = callbacks.shift(); + if (typeof callback == 'function') { + callback(); + continue; + } + var func = callback.func; + if (typeof func === 'number') { + if (callback.arg === undefined) { + Runtime.dynCall('v', func); + } else { + Runtime.dynCall('vi', func, [callback.arg]); + } + } else { + func(callback.arg === undefined ? null : callback.arg); + } + } +} + +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATMAIN__ = []; // functions called when main() is to be run +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the runtime has exited + +var runtimeInitialized = false; + +function preRun() { + // compatibility - merge in anything from Module['preRun'] at this time + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + callRuntimeCallbacks(__ATPRERUN__); +} + +function ensureInitRuntime() { + if (runtimeInitialized) return; + runtimeInitialized = true; + callRuntimeCallbacks(__ATINIT__); +} + +function preMain() { + callRuntimeCallbacks(__ATMAIN__); +} + +function exitRuntime() { + callRuntimeCallbacks(__ATEXIT__); +} + +function postRun() { + // compatibility - merge in anything from Module['postRun'] at this time + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + callRuntimeCallbacks(__ATPOSTRUN__); +} + +function addOnPreRun(cb) { + __ATPRERUN__.unshift(cb); +} +Module['addOnPreRun'] = Module.addOnPreRun = addOnPreRun; + +function addOnInit(cb) { + __ATINIT__.unshift(cb); +} +Module['addOnInit'] = Module.addOnInit = addOnInit; + +function addOnPreMain(cb) { + __ATMAIN__.unshift(cb); +} +Module['addOnPreMain'] = Module.addOnPreMain = addOnPreMain; + +function addOnExit(cb) { + __ATEXIT__.unshift(cb); +} +Module['addOnExit'] = Module.addOnExit = addOnExit; + +function addOnPostRun(cb) { + __ATPOSTRUN__.unshift(cb); +} +Module['addOnPostRun'] = Module.addOnPostRun = addOnPostRun; + +// Tools + +// This processes a JS string into a C-line array of numbers, 0-terminated. +// For LLVM-originating strings, see parser.js:parseLLVMString function +function intArrayFromString(stringy, dontAddNull, length /* optional */) { + var ret = (new Runtime.UTF8Processor()).processJSString(stringy); + if (length) { + ret.length = length; + } + if (!dontAddNull) { + ret.push(0); + } + return ret; +} +Module['intArrayFromString'] = intArrayFromString; + +function intArrayToString(array) { + var ret = []; + for (var i = 0; i < array.length; i++) { + var chr = array[i]; + if (chr > 0xFF) { + chr &= 0xFF; + } + ret.push(String.fromCharCode(chr)); + } + return ret.join(''); +} +Module['intArrayToString'] = intArrayToString; + +// Write a Javascript array to somewhere in the heap +function writeStringToMemory(string, buffer, dontAddNull) { + var array = intArrayFromString(string, dontAddNull); + var i = 0; + while (i < array.length) { + var chr = array[i]; + HEAP8[(((buffer)+(i))|0)]=chr; + i = i + 1; + } +} +Module['writeStringToMemory'] = writeStringToMemory; + +function writeArrayToMemory(array, buffer) { + for (var i = 0; i < array.length; i++) { + HEAP8[(((buffer)+(i))|0)]=array[i]; + } +} +Module['writeArrayToMemory'] = writeArrayToMemory; + +function writeAsciiToMemory(str, buffer, dontAddNull) { + for (var i = 0; i < str.length; i++) { + HEAP8[(((buffer)+(i))|0)]=str.charCodeAt(i); + } + if (!dontAddNull) HEAP8[(((buffer)+(str.length))|0)]=0; +} +Module['writeAsciiToMemory'] = writeAsciiToMemory; + +function unSign(value, bits, ignore) { + if (value >= 0) { + return value; + } + return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts + : Math.pow(2, bits) + value; +} +function reSign(value, bits, ignore) { + if (value <= 0) { + return value; + } + var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 + : Math.pow(2, bits-1); + if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that + // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors + // TODO: In i64 mode 1, resign the two parts separately and safely + value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts + } + return value; +} + +// check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 ) +if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) { + var ah = a >>> 16; + var al = a & 0xffff; + var bh = b >>> 16; + var bl = b & 0xffff; + return (al*bl + ((ah*bl + al*bh) << 16))|0; +}; +Math.imul = Math['imul']; + + +var Math_abs = Math.abs; +var Math_cos = Math.cos; +var Math_sin = Math.sin; +var Math_tan = Math.tan; +var Math_acos = Math.acos; +var Math_asin = Math.asin; +var Math_atan = Math.atan; +var Math_atan2 = Math.atan2; +var Math_exp = Math.exp; +var Math_log = Math.log; +var Math_sqrt = Math.sqrt; +var Math_ceil = Math.ceil; +var Math_floor = Math.floor; +var Math_pow = Math.pow; +var Math_imul = Math.imul; +var Math_fround = Math.fround; +var Math_min = Math.min; + +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// PRE_RUN_ADDITIONS (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled + +function addRunDependency(id) { + runDependencies++; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } +} +Module['addRunDependency'] = addRunDependency; +function removeRunDependency(id) { + runDependencies--; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } +} +Module['removeRunDependency'] = removeRunDependency; + +Module["preloadedImages"] = {}; // maps url to image data +Module["preloadedAudios"] = {}; // maps url to audio data + + +var memoryInitializer = null; + +// === Body === + + + + + +STATIC_BASE = 8; + +STATICTOP = STATIC_BASE + Runtime.alignMemory(28211); +/* global initializers */ __ATINIT__.push(); + + +/* memory initializer */ allocate([37,46,51,102,32,37,46,51,102,0,0,0,0,0,0,0,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,0,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,0,108,105,110,101,97,114,0,0,100,101,103,114,101,101,115,0,115,101,120,97,103,101,115,105,109,97,108,0,0,0,0,0,59,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,115,40,0,0,0,0,0,37,46,54,102,44,32,37,46,54,102,0,0,0,0,0,0,37,115,44,32,37,115,0,0,112,111,108,121,103,111,110,0,44,32,37,46,54,102,44,32,37,46,54,102,0,0,0,0,44,32,37,115,44,32,37,115,0,0,0,0,0,0,0,0,44,32,37,46,50,102,34,0,44,32,37,46,54,102,39,0,44,32,37,46,54,102,100,0,98,111,120,0,0,0,0,0,101,108,108,105,112,115,101,0,44,32,37,46,51,102,0,0,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,102,32,37,102], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE); +/* memory initializer */ allocate([1,0,0,0,0,0,0,0,87,67,83,73,78,73,84,78,58,32,87,67,83,32,110,97,109,101,32,37,115,32,110,111,116,32,109,97,116,99,104,101,100,32,105,110,32,70,73,84,83,32,104,101,97,100,101,114,10,0,0,0,0,0,0,0,87,67,83,78,65,77,69,0,87,67,83,65,88,69,83,0,78,65,88,73,83,0,0,0,87,67,83,68,73,77,0,0,87,67,83,73,78,73,84,58,32,78,111,32,87,67,83,65,88,69,83,44,32,78,65,88,73,83,44,32,111,114,32,87,67,83,68,73,77,32,107,101,121,119,111,114,100,0,0,0,78,65,88,73,83,49,0,0,73,77,65,71,69,87,0,0,87,67,83,73,78,73,84,58,32,78,111,32,78,65,88,73,83,49,32,111,114,32,73,77,65,71,69,87,32,107,101,121,119,111,114,100,0,0,0,0,78,65,88,73,83,50,0,0,73,77,65,71,69,72,0,0,87,67,83,73,78,73,84,58,32,78,111,32,78,65,88,73,83,50,32,111,114,32,73,77,65,71,69,72,32,107,101,121,119,111,114,100,0,0,0,0,37,100,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,77,105,115,115,105,110,103,32,107,101,121,119,111,114,100,32,37,115,32,97,115,115,117,109,101,100,32,49,10,0,0,67,84,89,80,69,0,0,0,45,84,65,66,0,0,0,0,73,78,83,84,82,85,77,69,0,0,0,0,0,0,0,0,68,69,84,69,67,84,79,82,0,0,0,0,0,0,0,0,68,67,45,70,76,65,71,0,87,67,83,68,69,80,0,0,87,67,83,73,78,73,84,58,32,100,101,112,101,110,100,101,100,32,111,110,32,87,67,83,32,99,111,117,108,100,32,110,111,116,32,98,101,32,115,101,116,0,0,0,0,0,0,0,86,83,79,85,82,67,69,0,90,83,79,85,82,67,69,0,86,69,76,79,67,73,84,89,0,0,0,0,0,0,0,0,67,84,89,80,69,49,0,0,67,84,89,80,69,50,0,0,76,65,84,0,0,0,0,0,68,69,67,0,0,0,0,0,67,84,89,80,69,51,0,0,67,84,89,80,69,52,0,0,67,85,78,73,84,49,0,0,87,65,84,49,0,0,0,0,117,110,105,116,115,0,0,0,112,105,120,101,108,0,0,0,67,85,78,73,84,50,0,0,87,65,84,50,0,0,0,0,67,82,80,73,88,49,0,0,67,82,80,73,88,50,0,0,67,82,86,65,76,49,0,0,67,82,86,65,76,50,0,0,76,79,78,80,79,76,69,0,76,65,84,80,79,76,69,0,80,82,79,74,82,48,0,0,80,82,79,74,80,37,100,0,80,86,37,100,95,49,0,0,80,86,37,100,95,50,0,0,80,86,37,100,95,51,0,0,80,86,37,100,95,37,100,0,67,68,49,95,49,0,0,0,67,68,49,95,50,0,0,0,67,68,50,95,49,0,0,0,67,68,50,95,50,0,0,0,67,79,49,95,49,0,0,0,80,76,65,84,69,0,0,0,67,79,49,95,37,100,0,0,67,79,50,95,49,0,0,0,67,79,50,95,37,100,0,0,67,68,69,76,84,49,0,0,67,68,69,76,84,50,0,0,83,69,67,80,73,88,0,0,80,73,88,83,67,65,76,69,0,0,0,0,0,0,0,0,80,73,88,83,67,65,76,49,0,0,0,0,0,0,0,0,88,80,73,88,83,73,90,69,0,0,0,0,0,0,0,0,83,69,67,80,73,88,49,0,83,69,67,80,73,88,50,0,89,80,73,88,83,73,90,69,0,0,0,0,0,0,0,0,80,73,88,83,67,65,76,50,0,0,0,0,0,0,0,0,80,67,48,48,49,48,48,49,0,0,0,0,0,0,0,0,80,67,48,48,37,49,100,48,48,37,49,100,0,0,0,0,80,67,49,95,49,0,0,0,80,67,37,49,100,95,37,49,100,0,0,0,0,0,0,0,67,82,79,84,65,50,0,0,67,82,79,84,65,49,0,0,87,67,83,73,78,73,84,58,32,115,101,116,116,105,110,103,32,67,68,69,76,84,32,116,111,32,49,0,0,0,0,0,76,73,78,69,65,82,0,0,80,73,88,69,76,0,0,0,77,74,68,45,79,66,83,0,68,65,84,69,45,79,66,83,0,0,0,0,0,0,0,0,68,65,84,69,0,0,0,0,69,80,79,67,72,0,0,0,85,84,0,0,0,0,0,0,85,84,77,73,68,0,0,0,87,67,83,73,78,73,84,67,58,32,78,111,32,105,109,97,103,101,32,115,99,97,108,101,32,102,111,114,32,87,67,83,32,37,99,0,0,0,0,0,80,76,84,82,65,72,0,0,80,76,84,82,65,77,0,0,80,76,84,82,65,83,0,0,80,76,84,68,69,67,83,78,0,0,0,0,0,0,0,0,80,76,84,68,69,67,68,0,80,76,84,68,69,67,77,0,80,76,84,68,69,67,83,0,69,81,85,73,78,79,88,0,70,75,52,0,0,0,0,0,70,75,53,0,0,0,0,0,37,50,46,48,102,58,37,50,46,48,102,58,37,53,46,51,102,32,37,99,37,50,46,48,102,58,37,50,46,48,102,58,37,53,46,51,102,32,37,115,0,0,0,0,0,0,0,0,80,76,84,83,67,65,76,69,0,0,0,0,0,0,0,0,88,80,73,88,69,76,83,90,0,0,0,0,0,0,0,0,89,80,73,88,69,76,83,90,0,0,0,0,0,0,0,0,67,78,80,73,88,49,0,0,67,78,80,73,88,50,0,0,80,80,79,49,0,0,0,0,80,80,79,37,100,0,0,0,65,77,68,88,49,0,0,0,65,77,68,88,37,100,0,0,65,77,68,89,49,0,0,0,65,77,68,89,37,100,0,0,82,65,0,0,0,0,0,0,82,65,45,45,45,68,83,83,0,0,0,0,0,0,0,0,68,69,67,45,45,68,83,83,0,0,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,78,111,32,82,65,32,119,105,116,104,32,83,69,67,80,73,88,44,32,110,111,32,87,67,83,0,0,0,0,0,0,87,67,83,73,78,73,84,32,78,111,32,68,69,67,32,119,105,116,104,32,83,69,67,80,73,88,44,32,110,111,32,87,67,83,0,0,0,0,0,0,76,79,78,71,80,79,76,69,0,0,0,0,0,0,0,0,82,65,45,45,45,84,65,78,0,0,0,0,0,0,0,0,68,69,67,45,45,84,65,78,0,0,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,78,111,32,105,109,97,103,101,32,115,99,97,108,101,0,84,65,78,0,0,0,0,0,42,69,114,114,111,114,42,58,32,105,110,99,111,114,114,101,99,116,32,108,105,110,101,97,114,32,99,111,110,118,101,114,115,105,111,110,32,105,110,32,37,115,0,0,0,0,0,0,87,65,82,78,73,78,71,58,32,83,105,103,110,105,102,105,99,97,110,116,32,105,110,97,99,99,117,114,97,99,121,32,108,105,107,101,108,121,32,116,111,32,111,99,99,117,114,32,105,110,32,112,114,111,106,101,99,116,105,111,110,0,0,0,69,81,85,73,78,79,88,37,99,0,0,0,0,0,0,0,82,65,68,69,67,83,89,83,37,99,0,0,0,0,0,0,82,65,68,69,67,83,89,83,0,0,0,0,0,0,0,0,73,67,82,83,0,0,0,0,71,65,76,0,0,0,0,0,69,67,76,0,0,0,0,0,71,65,76,65,67,84,73,67,0,0,0,0,0,0,0,0,69,67,76,73,80,84,73,67,0,0,0,0,0,0,0,0,83,71,65,76,65,67,84,67,0,0,0,0,0,0,0,0,72,69,76,73,79,69,67,76,0,0,0,0,0,0,0,0,65,76,84,65,90,0,0,0,0,0,0,0,0,0,0,0,68,69,67,0,0,0,0,0,76,79,78,71,0,0,0,0,76,73,78,69,65,82,0,0,80,73,88,69,76,0,0,0,68,69,84,0,0,0,0,0,37,45,52,115,37,52,115,0,78,80,79,76,0,0,0,0,76,65,84,0,0,0,0,0,78,80,79,76,69,0,0,0,83,80,65,45,0,0,0,0,73,77,83,89,83,0,0,0,105,109,115,121,115,0,0,0,37,46,52,102,0,0,0,0,66,49,57,53,48,0,0,0,74,50,48,48,48,0,0,0,37,115,9,37,115,0,0,0,37,115,32,37,115,0,0,0,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,42,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,9,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,32,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,9,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,32,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,9,108,111,110,103,45,110,112,97,0,0,0,0,0,0,0,32,108,111,110,103,45,110,112,97,0,0,0,0,0,0,0,9,108,111,110,103,45,115,112,97,0,0,0,0,0,0,0,32,108,111,110,103,45,115,112,97,0,0,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,67,83,95,67,79,77,77,65,78,68,0,0,0,0,0,87,67,83,95,67,79,77,77,65,78,68,37,100,0,0,0,50,48,48,48,0,0,0,0,50,48,48,48,46,48,0,0,73,67,82,83,0,0,0,0,105,99,114,115,0,0,0,0,70,75,53,0,0,0,0,0,102,107,53,0,0,0,0,0,49,57,53,48,0,0,0,0,49,57,53,48,46,48,0,0,70,75,52,0,0,0,0,0,102,107,52,0,0,0,0,0,112,105,120,101,108,0,0,0,44,66,124,35,100,255,239,63,206,4,147,55,81,230,134,63,201,87,119,237,8,231,115,63,8,49,216,60,72,85,196,190,141,82,239,197,175,26,93,190,79,75,150,130,180,74,73,190,206,4,147,55,81,230,134,191,110,20,118,229,124,255,239,63,190,2,89,23,76,127,252,190,141,82,239,197,175,26,93,62,186,92,192,248,87,85,196,190,213,61,80,36,200,25,210,61,192,143,86,244,8,231,115,191,40,252,144,126,141,121,252,190,190,45,6,62,231,255,239,63,79,75,150,130,180,74,73,62,213,61,80,36,200,25,210,61,56,97,156,141,155,85,196,190,37,201,115,125,31,14,66,191,237,156,102,129,118,135,206,63,237,128,235,138,25,225,219,191,138,238,48,88,55,255,239,63,235,42,147,208,76,230,134,63,26,132,28,8,135,230,115,63,12,31,17,83,34,137,206,191,58,234,232,184,26,217,101,191,7,35,246,9,160,24,137,63,235,42,147,208,76,230,134,191,233,248,162,28,80,255,239,63,8,168,211,46,100,125,252,190,137,181,248,20,0,227,219,63,180,173,102,157,241,125,129,191,174,14,128,184,171,87,97,63,26,132,28,8,135,230,115,191,247,97,247,252,180,122,252,190,137,77,92,117,186,255,239,63,125,150,201,34,100,255,239,63,15,157,207,213,158,230,134,191,92,113,244,103,237,229,115,191,26,77,59,180,100,85,196,62,52,175,17,131,3,27,93,190,173,87,210,121,59,74,73,190,20,1,96,210,158,230,134,63,3,186,248,225,124,255,239,63,250,59,9,220,34,127,252,190,52,175,17,131,3,27,93,62,91,229,82,109,116,85,196,62,232,167,8,110,48,27,210,189,73,225,178,117,237,229,115,63,235,19,108,31,83,119,252,190,10,30,195,64,231,255,239,63,173,87,210,121,59,74,73,62,185,158,187,181,171,23,210,189,73,125,255,4,184,85,196,62,37,201,115,125,31,14,66,191,211,48,124,68,76,137,206,191,34,223,165,212,37,227,219,63,45,6,81,239,144,255,239,63,108,197,229,21,219,230,134,191,214,96,142,220,162,229,115,191,180,174,209,114,160,135,206,63,58,234,232,184,26,217,101,191,180,173,102,157,241,125,129,191,108,197,229,21,219,230,134,63,26,73,6,169,169,255,239,63,26,238,175,96,19,128,252,190,134,170,152,74,63,225,219,191,7,35,246,9,160,24,137,63,174,14,128,184,171,87,97,63,214,96,142,220,162,229,115,63,212,213,62,153,86,117,252,190,150,50,62,6,10,0,240,63,0,0,0,0,0,0,0,0,70,75,52,50,71,65,76,58,32,66,49,57,53,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,52,50,71,65,76,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,52,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,52,58,32,66,49,57,53,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,53,50,71,65,76,58,32,74,50,48,48,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,53,50,71,65,76,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,53,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,53,58,32,74,50,48,48,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,32,37,99,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,0,0,0,0,0,0,0,69,78,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,28,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,37,115,95,49,0,0,0,0,37,115,95,37,100,0,0,0,37,115,95,48,49,0,0,0,37,115,95,48,48,49,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,48,0,0,0,0,0,0,37,100,0,0,0,0,0,0,37,37,46,37,100,102,0,0,37,48,50,100,58,37,48,50,100,58,37,48,57,46,54,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,56,46,53,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,55,46,52,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,52,46,49,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,50,100,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,57,46,54,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,56,46,53,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,55,46,52,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,52,46,49,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,50,100,0,0,0,0,0,0,0,0,37,37,37,100,46,37,100,102,0,0,0,0,0,0,0,0,37,37,37,52,100,0,0,0,37,37,37,100,100], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+4352); +/* memory initializer */ allocate([87,65,84,49,0,0,0,0,87,65,84,50,0,0,0,0,108,111,110,103,112,111,108,101,0,0,0,0,0,0,0,0,114,111,0,0,0,0,0,0,108,110,103,99,111,114,0,0,108,97,116,99,111,114,0,0,84,78,88,95,71,83,69,86,65,76,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,10,0,0,0,0,0,0,0,84,78,88,95,71,83,68,69,82,58,32,111,114,100,101,114,32,111,102,32,100,101,114,105,118,97,116,105,118,101,115,32,99,97,110,110,111,116,32,98,101,32,60,32,48,10,0,0,84,78,88,95,71,83,68,69,82,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,32,37,100,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,120,32,111,114,100,101,114,32,37,100,10,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,121,32,111,114,100,101,114,32,37,100,10,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,120,32,114,97,110,103,101,32,37,102,45,37,102,10,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,121,32,114,97,110,103,101,32,37,102,45,37,102,10,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,32,37,100,10,0,0,87,65,84,49,0,0,0,0,87,65,84,49,95,48,48,49,61,32,39,119,116,121,112,101,61,122,112,120,32,97,120,116,121,112,101,61,114,97,32,112,114,111,106,112,48,61,48,46,32,112,114,111,106,112,49,61,49,46,32,112,114,111,106,112,50,61,48,46,32,112,114,111,106,112,51,61,51,51,55,46,55,52,32,112,114,111,106,39,87,65,84,50,95,48,48,49,61,32,39,119,116,121,112,101,61,122,112,120,32,97,120,116,121,112,101,61,100,101,99,32,112,114,111,106,112,48,61,48,46,32,112,114,111,106,112,49,61,49,46,32,112,114,111,106,112,50,61,48,46,32,112,114,111,106,112,51,61,51,51,55,46,55,52,32,112,114,111,39,0,0,0,0,0,0,0,0,87,65,84,50,0,0,0,0,108,111,110,103,112,111,108,101,0,0,0,0,0,0,0,0,114,111,0,0,0,0,0,0,112,114,111,106,112,37,100,0,108,110,103,99,111,114,0,0,108,97,116,99,111,114,0,0,10,62,32,37,115,37,115,10,10,0,0,0,0,0,0,0,78,111,116,32,101,110,111,117,103,104,32,109,101,109,111,114,121,32,102,111,114,32,0,0,112,111,108,121,32,40,49,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,84,104,101,32,100,105,109,101,110,115,105,111,110,97,108,105,116,121,32,111,102,32,116,104,101,32,112,111,108,121,110,111,109,32,40,37,100,41,32,101,120,99,101,101,100,115,32,116,104,101,32,109,97,120,105,109,117,109,10,97,108,108,111,119,101,100,32,111,110,101,32,40,37,100,41,0,0,0,0,0,42,69,114,114,111,114,42,58,32,0,0,0,0,0,0,0,112,111,108,121,45,62,103,114,111,117,112,32,40,112,111,108,121,45,62,110,100,105,109,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,112,111,108,121,45,62,100,101,103,114,101,101,32,40,112,111,108,121,45,62,110,103,114,111,117,112,32,101,108,101,109,101,110,116,115,41,32,33,0,0,42,69,114,114,111,114,42,58,32,112,111,108,121,110,111,109,105,97,108,32,71,82,79,85,80,32,111,117,116,32,111,102,32,114,97,110,103,101,0,0,0,0,0,0,0,0,0,0,84,104,101,32,100,101,103,114,101,101,32,111,102,32,116,104,101,32,112,111,108,121,110,111,109,32,40,37,100,41,32,101,120,99,101,101,100,115,32,116,104,101,32,109,97,120,105,109,117,109,10,97,108,108,111,119,101,100,32,111,110,101,32,40,37,100,41,0,0,0,0,0,112,111,108,121,45,62,98,97,115,105,115,32,40,112,111,108,121,45,62,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,112,111,108,121,45,62,99,111,101,102,102,32,40,112,111,108,121,45,62,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,42,73,110,116,101,114,110,97,108,32,69,114,114,111,114,42,58,32,79,110,101,32,111,102,32,120,32,111,114,32,101,120,116,98,97,115,105,115,32,115,104,111,117,108,100,32,98,101,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,78,85,76,76,10,105,110,32,0,0,0,0,0,0,0,0,112,111,108,121,95,102,117,110,99,40,41,0,0,0,0,0,97,108,112,104,97,32,40,109,97,116,115,105,122,101,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,98,101,116,97,32,40,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,0,0,118,109,97,116,32,40,110,42,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,119,109,97,116,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,112,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,0,0,42,69,114,114,111,114,42,58,32,78,111,116,32,101,110,111,117,103,104,32,114,111,119,115,32,102,111,114,32,115,111,108,118,105,110,103,32,116,104,101,32,115,121,115,116,101,109,32,0,0,0,0,0,0,0,0,105,110,32,115,118,100,102,105,116,40,41,0,0,0,0,0,114,118,49,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,116,109,112,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,42,69,114,114,111,114,42,58,32,78,111,32,99,111,110,118,101,114,103,101,110,99,101,32,105,110,32,49,48,48,32,83,86,68,32,105,116,101,114,97,116,105,111,110,115,32,0,0,67,85,66,69,70,65,67,69,0,0,0,0,0,0,0,0,37,46,51,115,0,0,0,0,82,65,45,45,0,0,0,0,82,65,0,0,0,0,0,0,68,69,67,45,45,37,115,0,68,69,67,45,0,0,0,0,82,65,45,45,45,37,115,0,76,79,78,0,0,0,0,0,37,99,76,79,78,0,0,0,37,99,76,65,84,0,0,0,37,115,45,37,115,0,0,0,76,65,84,0,0,0,0,0,76,78,0,0,0,0,0,0,37,99,37,99,76,78,0,0,37,99,37,99,76,84,0,0,76,84,0,0,0,0,0,0,71,76,83,0,0,0,0,0,78,67,80,0,0,0,0,0,26,0,0,0,0,0,0,0,65,90,80,0,83,90,80,0,84,65,78,0,83,84,71,0,83,73,78,0,65,82,67,0,90,80,78,0,90,69,65,0,65,73,82,0,67,89,80,0,67,69,65,0,67,65,82,0,77,69,82,0,67,79,80,0,67,79,69,0,67,79,68,0,67,79,79,0,83,70,76,0,80,65,82,0,77,79,76,0,65,73,84,0,66,79,78,0,80,67,79,0,84,83,67,0,67,83,67,0,81,83,67,0,65,90,80,0,0,0,0,0,83,90,80,0,0,0,0,0,84,65,78,0,0,0,0,0,83,84,71,0,0,0,0,0,83,73,78,0,0,0,0,0,65,82,67,0,0,0,0,0,90,80,78,0,0,0,0,0,90,69,65,0,0,0,0,0,65,73,82,0,0,0,0,0,67,89,80,0,0,0,0,0,67,69,65,0,0,0,0,0,67,65,82,0,0,0,0,0,77,69,82,0,0,0,0,0,83,70,76,0,0,0,0,0,80,65,82,0,0,0,0,0,77,79,76,0,0,0,0,0,65,73,84,0,0,0,0,0,67,79,80,0,0,0,0,0,67,79,69,0,0,0,0,0,67,79,68,0,0,0,0,0,67,79,79,0,0,0,0,0,66,79,78,0,0,0,0,0,80,67,79,0,0,0,0,0,84,83,67,0,0,0,0,0,67,83,67,0,0,0,0,0,81,83,67,0,0,0,0,0,65,95,79,82,68,69,82,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,65,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,0,65,95,37,100,95,37,100,0,66,95,79,82,68,69,82,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,66,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,0,66,95,37,100,95,37,100,0,65,80,95,79,82,68,69,82,0,0,0,0,0,0,0,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,65,80,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,65,80,95,37,100,95,37,100,0,0,0,0,0,0,0,0,66,80,95,79,82,68,69,82,0,0,0,0,0,0,0,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,66,80,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,66,80,95,37,100,95,37,100,0,0,0,0,0,0,0,0,45,83,73,80,0,0,0,0,0,0,0,0,0,0,0,0,91,99,100,108,95,122,115,99,97,108,101,93,32,37,100,120,37,100,45,37,100,32,32,99,111,110,116,61,37,103,32,111,112,116,115,122,61,37,100,32,108,101,110,61,37,100,10,0,91,99,100,108,95,122,115,99,97,108,101,93,32,122,109,105,110,61,37,103,32,122,109,97,120,61,37,103,32,108,101,102,116,61,37,103,32,109,101,100,105,97,110,61,37,103,10,0,91,99,100,108,95,122,115,99,97,108,101,93,32,109,105,110,112,105,120,61,37,100,32,110,103,114,111,119,61,37,100,32,110,103,111,111,100,112,105,120,61,37,100,10,0,0,0,0,91,99,100,108,95,122,115,99,97,108,101,93,32,122,115,108,111,112,101,61,37,103,32,99,101,110,116,101,114,95,112,105,120,61,37,100,32,122,49,61,37,103,32,122,50,61,37,103,10,0,0,0,0,0,0,0,91,115,97,109,112,108,101,73,109,97,103,101,93,32,111,112,116,95,110,112,105,120,47,108,105,110,101,61,37,100,32,99,111,108,95,115,116,101,112,61,37,100,32,110,47,108,105,110,101,61,37,100,10,0,0,0,91,115,97,109,112,108,101,73,109,97,103,101,93,32,110,108,95,105,110,95,115,97,109,112,61,37,100,47,37,100,32,111,112,116,95,110,108,47,115,97,109,112,61,37,100,32,108,115,116,101,112,61,37,100,10,0,0,0,0,0,150,48,7,119,44,97,14,238,186,81,9,153,25,196,109,7,143,244,106,112,53,165,99,233,163,149,100,158,50,136,219,14,164,184,220,121,30,233,213,224,136,217,210,151,43,76,182,9,189,124,177,126,7,45,184,231,145,29,191,144,100,16,183,29,242,32,176,106,72,113,185,243,222,65,190,132,125,212,218,26,235,228,221,109,81,181,212,244,199,133,211,131,86,152,108,19,192,168,107,100,122,249,98,253,236,201,101,138,79,92,1,20,217,108,6,99,99,61,15,250,245,13,8,141,200,32,110,59,94,16,105,76,228,65,96,213,114,113,103,162,209,228,3,60,71,212,4,75,253,133,13,210,107,181,10,165,250,168,181,53,108,152,178,66,214,201,187,219,64,249,188,172,227,108,216,50,117,92,223,69,207,13,214,220,89,61,209,171,172,48,217,38,58,0,222,81,128,81,215,200,22,97,208,191,181,244,180,33,35,196,179,86,153,149,186,207,15,165,189,184,158,184,2,40,8,136,5,95,178,217,12,198,36,233,11,177,135,124,111,47,17,76,104,88,171,29,97,193,61,45,102,182,144,65,220,118,6,113,219,1,188,32,210,152,42,16,213,239,137,133,177,113,31,181,182,6,165,228,191,159,51,212,184,232,162,201,7,120,52,249,0,15,142,168,9,150,24,152,14,225,187,13,106,127,45,61,109,8,151,108,100,145,1,92,99,230,244,81,107,107,98,97,108,28,216,48,101,133,78,0,98,242,237,149,6,108,123,165,1,27,193,244,8,130,87,196,15,245,198,217,176,101,80,233,183,18,234,184,190,139,124,136,185,252,223,29,221,98,73,45,218,21,243,124,211,140,101,76,212,251,88,97,178,77,206,81,181,58,116,0,188,163,226,48,187,212,65,165,223,74,215,149,216,61,109,196,209,164,251,244,214,211,106,233,105,67,252,217,110,52,70,136,103,173,208,184,96,218,115,45,4,68,229,29,3,51,95,76,10,170,201,124,13,221,60,113,5,80,170,65,2,39,16,16,11,190,134,32,12,201,37,181,104,87,179,133,111,32,9,212,102,185,159,228,97,206,14,249,222,94,152,201,217,41,34,152,208,176,180,168,215,199,23,61,179,89,129,13,180,46,59,92,189,183,173,108,186,192,32,131,184,237,182,179,191,154,12,226,182,3,154,210,177,116,57,71,213,234,175,119,210,157,21,38,219,4,131,22,220,115,18,11,99,227,132,59,100,148,62,106,109,13,168,90,106,122,11,207,14,228,157,255,9,147,39,174,0,10,177,158,7,125,68,147,15,240,210,163,8,135,104,242,1,30,254,194,6,105,93,87,98,247,203,103,101,128,113,54,108,25,231,6,107,110,118,27,212,254,224,43,211,137,90,122,218,16,204,74,221,103,111,223,185,249,249,239,190,142,67,190,183,23,213,142,176,96,232,163,214,214,126,147,209,161,196,194,216,56,82,242,223,79,241,103,187,209,103,87,188,166,221,6,181,63,75,54,178,72,218,43,13,216,76,27,10,175,246,74,3,54,96,122,4,65,195,239,96,223,85,223,103,168,239,142,110,49,121,190,105,70,140,179,97,203,26,131,102,188,160,210,111,37,54,226,104,82,149,119,12,204,3,71,11,187,185,22,2,34,47,38,5,85,190,59,186,197,40,11,189,178,146,90,180,43,4,106,179,92,167,255,215,194,49,207,208,181,139,158,217,44,29,174,222,91,176,194,100,155,38,242,99,236,156,163,106,117,10,147,109,2,169,6,9,156,63,54,14,235,133,103,7,114,19,87,0,5,130,74,191,149,20,122,184,226,174,43,177,123,56,27,182,12,155,142,210,146,13,190,213,229,183,239,220,124,33,223,219,11,212,210,211,134,66,226,212,241,248,179,221,104,110,131,218,31,205,22,190,129,91,38,185,246,225,119,176,111,119,71,183,24,230,90,8,136,112,106,15,255,202,59,6,102,92,11,1,17,255,158,101,143,105,174,98,248,211,255,107,97,69,207,108,22,120,226,10,160,238,210,13,215,84,131,4,78,194,179,3,57,97,38,103,167,247,22,96,208,77,71,105,73,219,119,110,62,74,106,209,174,220,90,214,217,102,11,223,64,240,59,216,55,83,174,188,169,197,158,187,222,127,207,178,71,233,255,181,48,28,242,189,189,138,194,186,202,48,147,179,83,166,163,180,36,5,54,208,186,147,6,215,205,41,87,222,84,191,103,217,35,46,122,102,179,184,74,97,196,2,27,104,93,148,43,111,42,55,190,11,180,161,142,12,195,27,223,5,90,141,239,2,45,0,0,0,0,65,49,27,25,130,98,54,50,195,83,45,43,4,197,108,100,69,244,119,125,134,167,90,86,199,150,65,79,8,138,217,200,73,187,194,209,138,232,239,250,203,217,244,227,12,79,181,172,77,126,174,181,142,45,131,158,207,28,152,135,81,18,194,74,16,35,217,83,211,112,244,120,146,65,239,97,85,215,174,46,20,230,181,55,215,181,152,28,150,132,131,5,89,152,27,130,24,169,0,155,219,250,45,176,154,203,54,169,93,93,119,230,28,108,108,255,223,63,65,212,158,14,90,205,162,36,132,149,227,21,159,140,32,70,178,167,97,119,169,190,166,225,232,241,231,208,243,232,36,131,222,195,101,178,197,218,170,174,93,93,235,159,70,68,40,204,107,111,105,253,112,118,174,107,49,57,239,90,42,32,44,9,7,11,109,56,28,18,243,54,70,223,178,7,93,198,113,84,112,237,48,101,107,244,247,243,42,187,182,194,49,162,117,145,28,137,52,160,7,144,251,188,159,23,186,141,132,14,121,222,169,37,56,239,178,60,255,121,243,115,190,72,232,106,125,27,197,65,60,42,222,88,5,79,121,240,68,126,98,233,135,45,79,194,198,28,84,219,1,138,21,148,64,187,14,141,131,232,35,166,194,217,56,191,13,197,160,56,76,244,187,33,143,167,150,10,206,150,141,19,9,0,204,92,72,49,215,69,139,98,250,110,202,83,225,119,84,93,187,186,21,108,160,163,214,63,141,136,151,14,150,145,80,152,215,222,17,169,204,199,210,250,225,236,147,203,250,245,92,215,98,114,29,230,121,107,222,181,84,64,159,132,79,89,88,18,14,22,25,35,21,15,218,112,56,36,155,65,35,61,167,107,253,101,230,90,230,124,37,9,203,87,100,56,208,78,163,174,145,1,226,159,138,24,33,204,167,51,96,253,188,42,175,225,36,173,238,208,63,180,45,131,18,159,108,178,9,134,171,36,72,201,234,21,83,208,41,70,126,251,104,119,101,226,246,121,63,47,183,72,36,54,116,27,9,29,53,42,18,4,242,188,83,75,179,141,72,82,112,222,101,121,49,239,126,96,254,243,230,231,191,194,253,254,124,145,208,213,61,160,203,204,250,54,138,131,187,7,145,154,120,84,188,177,57,101,167,168,75,152,131,59,10,169,152,34,201,250,181,9,136,203,174,16,79,93,239,95,14,108,244,70,205,63,217,109,140,14,194,116,67,18,90,243,2,35,65,234,193,112,108,193,128,65,119,216,71,215,54,151,6,230,45,142,197,181,0,165,132,132,27,188,26,138,65,113,91,187,90,104,152,232,119,67,217,217,108,90,30,79,45,21,95,126,54,12,156,45,27,39,221,28,0,62,18,0,152,185,83,49,131,160,144,98,174,139,209,83,181,146,22,197,244,221,87,244,239,196,148,167,194,239,213,150,217,246,233,188,7,174,168,141,28,183,107,222,49,156,42,239,42,133,237,121,107,202,172,72,112,211,111,27,93,248,46,42,70,225,225,54,222,102,160,7,197,127,99,84,232,84,34,101,243,77,229,243,178,2,164,194,169,27,103,145,132,48,38,160,159,41,184,174,197,228,249,159,222,253,58,204,243,214,123,253,232,207,188,107,169,128,253,90,178,153,62,9,159,178,127,56,132,171,176,36,28,44,241,21,7,53,50,70,42,30,115,119,49,7,180,225,112,72,245,208,107,81,54,131,70,122,119,178,93,99,78,215,250,203,15,230,225,210,204,181,204,249,141,132,215,224,74,18,150,175,11,35,141,182,200,112,160,157,137,65,187,132,70,93,35,3,7,108,56,26,196,63,21,49,133,14,14,40,66,152,79,103,3,169,84,126,192,250,121,85,129,203,98,76,31,197,56,129,94,244,35,152,157,167,14,179,220,150,21,170,27,0,84,229,90,49,79,252,153,98,98,215,216,83,121,206,23,79,225,73,86,126,250,80,149,45,215,123,212,28,204,98,19,138,141,45,82,187,150,52,145,232,187,31,208,217,160,6,236,243,126,94,173,194,101,71,110,145,72,108,47,160,83,117,232,54,18,58,169,7,9,35,106,84,36,8,43,101,63,17,228,121,167,150,165,72,188,143,102,27,145,164,39,42,138,189,224,188,203,242,161,141,208,235,98,222,253,192,35,239,230,217,189,225,188,20,252,208,167,13,63,131,138,38,126,178,145,63,185,36,208,112,248,21,203,105,59,70,230,66,122,119,253,91,181,107,101,220,244,90,126,197,55,9,83,238,118,56,72,247,177,174,9,184,240,159,18,161,51,204,63,138,114,253,36,147,0,0,0,0,55,106,194,1,110,212,132,3,89,190,70,2,220,168,9,7,235,194,203,6,178,124,141,4,133,22,79,5,184,81,19,14,143,59,209,15,214,133,151,13,225,239,85,12,100,249,26,9,83,147,216,8,10,45,158,10,61,71,92,11,112,163,38,28,71,201,228,29,30,119,162,31,41,29,96,30,172,11,47,27,155,97,237,26,194,223,171,24,245,181,105,25,200,242,53,18,255,152,247,19,166,38,177,17,145,76,115,16,20,90,60,21,35,48,254,20,122,142,184,22,77,228,122,23,224,70,77,56,215,44,143,57,142,146,201,59,185,248,11,58,60,238,68,63,11,132,134,62,82,58,192,60,101,80,2,61,88,23,94,54,111,125,156,55,54,195,218,53,1,169,24,52,132,191,87,49,179,213,149,48,234,107,211,50,221,1,17,51,144,229,107,36,167,143,169,37,254,49,239,39,201,91,45,38,76,77,98,35,123,39,160,34,34,153,230,32,21,243,36,33,40,180,120,42,31,222,186,43,70,96,252,41,113,10,62,40,244,28,113,45,195,118,179,44,154,200,245,46,173,162,55,47,192,141,154,112,247,231,88,113,174,89,30,115,153,51,220,114,28,37,147,119,43,79,81,118,114,241,23,116,69,155,213,117,120,220,137,126,79,182,75,127,22,8,13,125,33,98,207,124,164,116,128,121,147,30,66,120,202,160,4,122,253,202,198,123,176,46,188,108,135,68,126,109,222,250,56,111,233,144,250,110,108,134,181,107,91,236,119,106,2,82,49,104,53,56,243,105,8,127,175,98,63,21,109,99,102,171,43,97,81,193,233,96,212,215,166,101,227,189,100,100,186,3,34,102,141,105,224,103,32,203,215,72,23,161,21,73,78,31,83,75,121,117,145,74,252,99,222,79,203,9,28,78,146,183,90,76,165,221,152,77,152,154,196,70,175,240,6,71,246,78,64,69,193,36,130,68,68,50,205,65,115,88,15,64,42,230,73,66,29,140,139,67,80,104,241,84,103,2,51,85,62,188,117,87,9,214,183,86,140,192,248,83,187,170,58,82,226,20,124,80,213,126,190,81,232,57,226,90,223,83,32,91,134,237,102,89,177,135,164,88,52,145,235,93,3,251,41,92,90,69,111,94,109,47,173,95,128,27,53,225,183,113,247,224,238,207,177,226,217,165,115,227,92,179,60,230,107,217,254,231,50,103,184,229,5,13,122,228,56,74,38,239,15,32,228,238,86,158,162,236,97,244,96,237,228,226,47,232,211,136,237,233,138,54,171,235,189,92,105,234,240,184,19,253,199,210,209,252,158,108,151,254,169,6,85,255,44,16,26,250,27,122,216,251,66,196,158,249,117,174,92,248,72,233,0,243,127,131,194,242,38,61,132,240,17,87,70,241,148,65,9,244,163,43,203,245,250,149,141,247,205,255,79,246,96,93,120,217,87,55,186,216,14,137,252,218,57,227,62,219,188,245,113,222,139,159,179,223,210,33,245,221,229,75,55,220,216,12,107,215,239,102,169,214,182,216,239,212,129,178,45,213,4,164,98,208,51,206,160,209,106,112,230,211,93,26,36,210,16,254,94,197,39,148,156,196,126,42,218,198,73,64,24,199,204,86,87,194,251,60,149,195,162,130,211,193,149,232,17,192,168,175,77,203,159,197,143,202,198,123,201,200,241,17,11,201,116,7,68,204,67,109,134,205,26,211,192,207,45,185,2,206,64,150,175,145,119,252,109,144,46,66,43,146,25,40,233,147,156,62,166,150,171,84,100,151,242,234,34,149,197,128,224,148,248,199,188,159,207,173,126,158,150,19,56,156,161,121,250,157,36,111,181,152,19,5,119,153,74,187,49,155,125,209,243,154,48,53,137,141,7,95,75,140,94,225,13,142,105,139,207,143,236,157,128,138,219,247,66,139,130,73,4,137,181,35,198,136,136,100,154,131,191,14,88,130,230,176,30,128,209,218,220,129,84,204,147,132,99,166,81,133,58,24,23,135,13,114,213,134,160,208,226,169,151,186,32,168,206,4,102,170,249,110,164,171,124,120,235,174,75,18,41,175,18,172,111,173,37,198,173,172,24,129,241,167,47,235,51,166,118,85,117,164,65,63,183,165,196,41,248,160,243,67,58,161,170,253,124,163,157,151,190,162,208,115,196,181,231,25,6,180,190,167,64,182,137,205,130,183,12,219,205,178,59,177,15,179,98,15,73,177,85,101,139,176,104,34,215,187,95,72,21,186,6,246,83,184,49,156,145,185,180,138,222,188,131,224,28,189,218,94,90,191,237,52,152,190,0,0,0,0,101,103,188,184,139,200,9,170,238,175,181,18,87,151,98,143,50,240,222,55,220,95,107,37,185,56,215,157,239,40,180,197,138,79,8,125,100,224,189,111,1,135,1,215,184,191,214,74,221,216,106,242,51,119,223,224,86,16,99,88,159,87,25,80,250,48,165,232,20,159,16,250,113,248,172,66,200,192,123,223,173,167,199,103,67,8,114,117,38,111,206,205,112,127,173,149,21,24,17,45,251,183,164,63,158,208,24,135,39,232,207,26,66,143,115,162,172,32,198,176,201,71,122,8,62,175,50,160,91,200,142,24,181,103,59,10,208,0,135,178,105,56,80,47,12,95,236,151,226,240,89,133,135,151,229,61,209,135,134,101,180,224,58,221,90,79,143,207,63,40,51,119,134,16,228,234,227,119,88,82,13,216,237,64,104,191,81,248,161,248,43,240,196,159,151,72,42,48,34,90,79,87,158,226,246,111,73,127,147,8,245,199,125,167,64,213,24,192,252,109,78,208,159,53,43,183,35,141,197,24,150,159,160,127,42,39,25,71,253,186,124,32,65,2,146,143,244,16,247,232,72,168,61,88,20,155,88,63,168,35,182,144,29,49,211,247,161,137,106,207,118,20,15,168,202,172,225,7,127,190,132,96,195,6,210,112,160,94,183,23,28,230,89,184,169,244,60,223,21,76,133,231,194,209,224,128,126,105,14,47,203,123,107,72,119,195,162,15,13,203,199,104,177,115,41,199,4,97,76,160,184,217,245,152,111,68,144,255,211,252,126,80,102,238,27,55,218,86,77,39,185,14,40,64,5,182,198,239,176,164,163,136,12,28,26,176,219,129,127,215,103,57,145,120,210,43,244,31,110,147,3,247,38,59,102,144,154,131,136,63,47,145,237,88,147,41,84,96,68,180,49,7,248,12,223,168,77,30,186,207,241,166,236,223,146,254,137,184,46,70,103,23,155,84,2,112,39,236,187,72,240,113,222,47,76,201,48,128,249,219,85,231,69,99,156,160,63,107,249,199,131,211,23,104,54,193,114,15,138,121,203,55,93,228,174,80,225,92,64,255,84,78,37,152,232,246,115,136,139,174,22,239,55,22,248,64,130,4,157,39,62,188,36,31,233,33,65,120,85,153,175,215,224,139,202,176,92,51,59,182,89,237,94,209,229,85,176,126,80,71,213,25,236,255,108,33,59,98,9,70,135,218,231,233,50,200,130,142,142,112,212,158,237,40,177,249,81,144,95,86,228,130,58,49,88,58,131,9,143,167,230,110,51,31,8,193,134,13,109,166,58,181,164,225,64,189,193,134,252,5,47,41,73,23,74,78,245,175,243,118,34,50,150,17,158,138,120,190,43,152,29,217,151,32,75,201,244,120,46,174,72,192,192,1,253,210,165,102,65,106,28,94,150,247,121,57,42,79,151,150,159,93,242,241,35,229,5,25,107,77,96,126,215,245,142,209,98,231,235,182,222,95,82,142,9,194,55,233,181,122,217,70,0,104,188,33,188,208,234,49,223,136,143,86,99,48,97,249,214,34,4,158,106,154,189,166,189,7,216,193,1,191,54,110,180,173,83,9,8,21,154,78,114,29,255,41,206,165,17,134,123,183,116,225,199,15,205,217,16,146,168,190,172,42,70,17,25,56,35,118,165,128,117,102,198,216,16,1,122,96,254,174,207,114,155,201,115,202,34,241,164,87,71,150,24,239,169,57,173,253,204,94,17,69,6,238,77,118,99,137,241,206,141,38,68,220,232,65,248,100,81,121,47,249,52,30,147,65,218,177,38,83,191,214,154,235,233,198,249,179,140,161,69,11,98,14,240,25,7,105,76,161,190,81,155,60,219,54,39,132,53,153,146,150,80,254,46,46,153,185,84,38,252,222,232,158,18,113,93,140,119,22,225,52,206,46,54,169,171,73,138,17,69,230,63,3,32,129,131,187,118,145,224,227,19,246,92,91,253,89,233,73,152,62,85,241,33,6,130,108,68,97,62,212,170,206,139,198,207,169,55,126,56,65,127,214,93,38,195,110,179,137,118,124,214,238,202,196,111,214,29,89,10,177,161,225,228,30,20,243,129,121,168,75,215,105,203,19,178,14,119,171,92,161,194,185,57,198,126,1,128,254,169,156,229,153,21,36,11,54,160,54,110,81,28,142,167,22,102,134,194,113,218,62,44,222,111,44,73,185,211,148,240,129,4,9,149,230,184,177,123,73,13,163,30,46,177,27,72,62,210,67,45,89,110,251,195,246,219,233,166,145,103,81,31,169,176,204,122,206,12,116,148,97,185,102,241,6,5,222,0,0,0,0,119,7,48,150,238,14,97,44,153,9,81,186,7,109,196,25,112,106,244,143,233,99,165,53,158,100,149,163,14,219,136,50,121,220,184,164,224,213,233,30,151,210,217,136,9,182,76,43,126,177,124,189,231,184,45,7,144,191,29,145,29,183,16,100,106,176,32,242,243,185,113,72,132,190,65,222,26,218,212,125,109,221,228,235,244,212,181,81,131,211,133,199,19,108,152,86,100,107,168,192,253,98,249,122,138,101,201,236,20,1,92,79,99,6,108,217,250,15,61,99,141,8,13,245,59,110,32,200,76,105,16,94,213,96,65,228,162,103,113,114,60,3,228,209,75,4,212,71,210,13,133,253,165,10,181,107,53,181,168,250,66,178,152,108,219,187,201,214,172,188,249,64,50,216,108,227,69,223,92,117,220,214,13,207,171,209,61,89,38,217,48,172,81,222,0,58,200,215,81,128,191,208,97,22,33,180,244,181,86,179,196,35,207,186,149,153,184,189,165,15,40,2,184,158,95,5,136,8,198,12,217,178,177,11,233,36,47,111,124,135,88,104,76,17,193,97,29,171,182,102,45,61,118,220,65,144,1,219,113,6,152,210,32,188,239,213,16,42,113,177,133,137,6,182,181,31,159,191,228,165,232,184,212,51,120,7,201,162,15,0,249,52,150,9,168,142,225,14,152,24,127,106,13,187,8,109,61,45,145,100,108,151,230,99,92,1,107,107,81,244,28,108,97,98,133,101,48,216,242,98,0,78,108,6,149,237,27,1,165,123,130,8,244,193,245,15,196,87,101,176,217,198,18,183,233,80,139,190,184,234,252,185,136,124,98,221,29,223,21,218,45,73,140,211,124,243,251,212,76,101,77,178,97,88,58,181,81,206,163,188,0,116,212,187,48,226,74,223,165,65,61,216,149,215,164,209,196,109,211,214,244,251,67,105,233,106,52,110,217,252,173,103,136,70,218,96,184,208,68,4,45,115,51,3,29,229,170,10,76,95,221,13,124,201,80,5,113,60,39,2,65,170,190,11,16,16,201,12,32,134,87,104,181,37,32,111,133,179,185,102,212,9,206,97,228,159,94,222,249,14,41,217,201,152,176,208,152,34,199,215,168,180,89,179,61,23,46,180,13,129,183,189,92,59,192,186,108,173,237,184,131,32,154,191,179,182,3,182,226,12,116,177,210,154,234,213,71,57,157,210,119,175,4,219,38,21,115,220,22,131,227,99,11,18,148,100,59,132,13,109,106,62,122,106,90,168,228,14,207,11,147,9,255,157,10,0,174,39,125,7,158,177,240,15,147,68,135,8,163,210,30,1,242,104,105,6,194,254,247,98,87,93,128,101,103,203,25,108,54,113,110,107,6,231,254,212,27,118,137,211,43,224,16,218,122,90,103,221,74,204,249,185,223,111,142,190,239,249,23,183,190,67,96,176,142,213,214,214,163,232,161,209,147,126,56,216,194,196,79,223,242,82,209,187,103,241,166,188,87,103,63,181,6,221,72,178,54,75,216,13,43,218,175,10,27,76,54,3,74,246,65,4,122,96,223,96,239,195,168,103,223,85,49,110,142,239,70,105,190,121,203,97,179,140,188,102,131,26,37,111,210,160,82,104,226,54,204,12,119,149,187,11,71,3,34,2,22,185,85,5,38,47,197,186,59,190,178,189,11,40,43,180,90,146,92,179,106,4,194,215,255,167,181,208,207,49,44,217,158,139,91,222,174,29,155,100,194,176,236,99,242,38,117,106,163,156,2,109,147,10,156,9,6,169,235,14,54,63,114,7,103,133,5,0,87,19,149,191,74,130,226,184,122,20,123,177,43,174,12,182,27,56,146,210,142,155,229,213,190,13,124,220,239,183,11,219,223,33,134,211,210,212,241,212,226,66,104,221,179,248,31,218,131,110,129,190,22,205,246,185,38,91,111,176,119,225,24,183,71,119,136,8,90,230,255,15,106,112,102,6,59,202,17,1,11,92,143,101,158,255,248,98,174,105,97,107,255,211,22,108,207,69,160,10,226,120,215,13,210,238,78,4,131,84,57,3,179,194,167,103,38,97,208,96,22,247,73,105,71,77,62,110,119,219,174,209,106,74,217,214,90,220,64,223,11,102,55,216,59,240,169,188,174,83,222,187,158,197,71,178,207,127,48,181,255,233,189,189,242,28,202,186,194,138,83,179,147,48,36,180,163,166,186,208,54,5,205,215,6,147,84,222,87,41,35,217,103,191,179,102,122,46,196,97,74,184,93,104,27,2,42,111,43,148,180,11,190,55,195,12,142,161,90,5,223,27,45,2,239,141,0,0,0,0,25,27,49,65,50,54,98,130,43,45,83,195,100,108,197,4,125,119,244,69,86,90,167,134,79,65,150,199,200,217,138,8,209,194,187,73,250,239,232,138,227,244,217,203,172,181,79,12,181,174,126,77,158,131,45,142,135,152,28,207,74,194,18,81,83,217,35,16,120,244,112,211,97,239,65,146,46,174,215,85,55,181,230,20,28,152,181,215,5,131,132,150,130,27,152,89,155,0,169,24,176,45,250,219,169,54,203,154,230,119,93,93,255,108,108,28,212,65,63,223,205,90,14,158,149,132,36,162,140,159,21,227,167,178,70,32,190,169,119,97,241,232,225,166,232,243,208,231,195,222,131,36,218,197,178,101,93,93,174,170,68,70,159,235,111,107,204,40,118,112,253,105,57,49,107,174,32,42,90,239,11,7,9,44,18,28,56,109,223,70,54,243,198,93,7,178,237,112,84,113,244,107,101,48,187,42,243,247,162,49,194,182,137,28,145,117,144,7,160,52,23,159,188,251,14,132,141,186,37,169,222,121,60,178,239,56,115,243,121,255,106,232,72,190,65,197,27,125,88,222,42,60,240,121,79,5,233,98,126,68,194,79,45,135,219,84,28,198,148,21,138,1,141,14,187,64,166,35,232,131,191,56,217,194,56,160,197,13,33,187,244,76,10,150,167,143,19,141,150,206,92,204,0,9,69,215,49,72,110,250,98,139,119,225,83,202,186,187,93,84,163,160,108,21,136,141,63,214,145,150,14,151,222,215,152,80,199,204,169,17,236,225,250,210,245,250,203,147,114,98,215,92,107,121,230,29,64,84,181,222,89,79,132,159,22,14,18,88,15,21,35,25,36,56,112,218,61,35,65,155,101,253,107,167,124,230,90,230,87,203,9,37,78,208,56,100,1,145,174,163,24,138,159,226,51,167,204,33,42,188,253,96,173,36,225,175,180,63,208,238,159,18,131,45,134,9,178,108,201,72,36,171,208,83,21,234,251,126,70,41,226,101,119,104,47,63,121,246,54,36,72,183,29,9,27,116,4,18,42,53,75,83,188,242,82,72,141,179,121,101,222,112,96,126,239,49,231,230,243,254,254,253,194,191,213,208,145,124,204,203,160,61,131,138,54,250,154,145,7,187,177,188,84,120,168,167,101,57,59,131,152,75,34,152,169,10,9,181,250,201,16,174,203,136,95,239,93,79,70,244,108,14,109,217,63,205,116,194,14,140,243,90,18,67,234,65,35,2,193,108,112,193,216,119,65,128,151,54,215,71,142,45,230,6,165,0,181,197,188,27,132,132,113,65,138,26,104,90,187,91,67,119,232,152,90,108,217,217,21,45,79,30,12,54,126,95,39,27,45,156,62,0,28,221,185,152,0,18,160,131,49,83,139,174,98,144,146,181,83,209,221,244,197,22,196,239,244,87,239,194,167,148,246,217,150,213,174,7,188,233,183,28,141,168,156,49,222,107,133,42,239,42,202,107,121,237,211,112,72,172,248,93,27,111,225,70,42,46,102,222,54,225,127,197,7,160,84,232,84,99,77,243,101,34,2,178,243,229,27,169,194,164,48,132,145,103,41,159,160,38,228,197,174,184,253,222,159,249,214,243,204,58,207,232,253,123,128,169,107,188,153,178,90,253,178,159,9,62,171,132,56,127,44,28,36,176,53,7,21,241,30,42,70,50,7,49,119,115,72,112,225,180,81,107,208,245,122,70,131,54,99,93,178,119,203,250,215,78,210,225,230,15,249,204,181,204,224,215,132,141,175,150,18,74,182,141,35,11,157,160,112,200,132,187,65,137,3,35,93,70,26,56,108,7,49,21,63,196,40,14,14,133,103,79,152,66,126,84,169,3,85,121,250,192,76,98,203,129,129,56,197,31,152,35,244,94,179,14,167,157,170,21,150,220,229,84,0,27,252,79,49,90,215,98,98,153,206,121,83,216,73,225,79,23,80,250,126,86,123,215,45,149,98,204,28,212,45,141,138,19,52,150,187,82,31,187,232,145,6,160,217,208,94,126,243,236,71,101,194,173,108,72,145,110,117,83,160,47,58,18,54,232,35,9,7,169,8,36,84,106,17,63,101,43,150,167,121,228,143,188,72,165,164,145,27,102,189,138,42,39,242,203,188,224,235,208,141,161,192,253,222,98,217,230,239,35,20,188,225,189,13,167,208,252,38,138,131,63,63,145,178,126,112,208,36,185,105,203,21,248,66,230,70,59,91,253,119,122,220,101,107,181,197,126,90,244,238,83,9,55,247,72,56,118,184,9,174,177,161,18,159,240,138,63,204,51,147,36,253,114,0,0,0,0,1,194,106,55,3,132,212,110,2,70,190,89,7,9,168,220,6,203,194,235,4,141,124,178,5,79,22,133,14,19,81,184,15,209,59,143,13,151,133,214,12,85,239,225,9,26,249,100,8,216,147,83,10,158,45,10,11,92,71,61,28,38,163,112,29,228,201,71,31,162,119,30,30,96,29,41,27,47,11,172,26,237,97,155,24,171,223,194,25,105,181,245,18,53,242,200,19,247,152,255,17,177,38,166,16,115,76,145,21,60,90,20,20,254,48,35,22,184,142,122,23,122,228,77,56,77,70,224,57,143,44,215,59,201,146,142,58,11,248,185,63,68,238,60,62,134,132,11,60,192,58,82,61,2,80,101,54,94,23,88,55,156,125,111,53,218,195,54,52,24,169,1,49,87,191,132,48,149,213,179,50,211,107,234,51,17,1,221,36,107,229,144,37,169,143,167,39,239,49,254,38,45,91,201,35,98,77,76,34,160,39,123,32,230,153,34,33,36,243,21,42,120,180,40,43,186,222,31,41,252,96,70,40,62,10,113,45,113,28,244,44,179,118,195,46,245,200,154,47,55,162,173,112,154,141,192,113,88,231,247,115,30,89,174,114,220,51,153,119,147,37,28,118,81,79,43,116,23,241,114,117,213,155,69,126,137,220,120,127,75,182,79,125,13,8,22,124,207,98,33,121,128,116,164,120,66,30,147,122,4,160,202,123,198,202,253,108,188,46,176,109,126,68,135,111,56,250,222,110,250,144,233,107,181,134,108,106,119,236,91,104,49,82,2,105,243,56,53,98,175,127,8,99,109,21,63,97,43,171,102,96,233,193,81,101,166,215,212,100,100,189,227,102,34,3,186,103,224,105,141,72,215,203,32,73,21,161,23,75,83,31,78,74,145,117,121,79,222,99,252,78,28,9,203,76,90,183,146,77,152,221,165,70,196,154,152,71,6,240,175,69,64,78,246,68,130,36,193,65,205,50,68,64,15,88,115,66,73,230,42,67,139,140,29,84,241,104,80,85,51,2,103,87,117,188,62,86,183,214,9,83,248,192,140,82,58,170,187,80,124,20,226,81,190,126,213,90,226,57,232,91,32,83,223,89,102,237,134,88,164,135,177,93,235,145,52,92,41,251,3,94,111,69,90,95,173,47,109,225,53,27,128,224,247,113,183,226,177,207,238,227,115,165,217,230,60,179,92,231,254,217,107,229,184,103,50,228,122,13,5,239,38,74,56,238,228,32,15,236,162,158,86,237,96,244,97,232,47,226,228,233,237,136,211,235,171,54,138,234,105,92,189,253,19,184,240,252,209,210,199,254,151,108,158,255,85,6,169,250,26,16,44,251,216,122,27,249,158,196,66,248,92,174,117,243,0,233,72,242,194,131,127,240,132,61,38,241,70,87,17,244,9,65,148,245,203,43,163,247,141,149,250,246,79,255,205,217,120,93,96,216,186,55,87,218,252,137,14,219,62,227,57,222,113,245,188,223,179,159,139,221,245,33,210,220,55,75,229,215,107,12,216,214,169,102,239,212,239,216,182,213,45,178,129,208,98,164,4,209,160,206,51,211,230,112,106,210,36,26,93,197,94,254,16,196,156,148,39,198,218,42,126,199,24,64,73,194,87,86,204,195,149,60,251,193,211,130,162,192,17,232,149,203,77,175,168,202,143,197,159,200,201,123,198,201,11,17,241,204,68,7,116,205,134,109,67,207,192,211,26,206,2,185,45,145,175,150,64,144,109,252,119,146,43,66,46,147,233,40,25,150,166,62,156,151,100,84,171,149,34,234,242,148,224,128,197,159,188,199,248,158,126,173,207,156,56,19,150,157,250,121,161,152,181,111,36,153,119,5,19,155,49,187,74,154,243,209,125,141,137,53,48,140,75,95,7,142,13,225,94,143,207,139,105,138,128,157,236,139,66,247,219,137,4,73,130,136,198,35,181,131,154,100,136,130,88,14,191,128,30,176,230,129,220,218,209,132,147,204,84,133,81,166,99,135,23,24,58,134,213,114,13,169,226,208,160,168,32,186,151,170,102,4,206,171,164,110,249,174,235,120,124,175,41,18,75,173,111,172,18,172,173,198,37,167,241,129,24,166,51,235,47,164,117,85,118,165,183,63,65,160,248,41,196,161,58,67,243,163,124,253,170,162,190,151,157,181,196,115,208,180,6,25,231,182,64,167,190,183,130,205,137,178,205,219,12,179,15,177,59,177,73,15,98,176,139,101,85,187,215,34,104,186,21,72,95,184,83,246,6,185,145,156,49,188,222,138,180,189,28,224,131,191,90,94,218,190,152,52,237,0,0,0,0,184,188,103,101,170,9,200,139,18,181,175,238,143,98,151,87,55,222,240,50,37,107,95,220,157,215,56,185,197,180,40,239,125,8,79,138,111,189,224,100,215,1,135,1,74,214,191,184,242,106,216,221,224,223,119,51,88,99,16,86,80,25,87,159,232,165,48,250,250,16,159,20,66,172,248,113,223,123,192,200,103,199,167,173,117,114,8,67,205,206,111,38,149,173,127,112,45,17,24,21,63,164,183,251,135,24,208,158,26,207,232,39,162,115,143,66,176,198,32,172,8,122,71,201,160,50,175,62,24,142,200,91,10,59,103,181,178,135,0,208,47,80,56,105,151,236,95,12,133,89,240,226,61,229,151,135,101,134,135,209,221,58,224,180,207,143,79,90,119,51,40,63,234,228,16,134,82,88,119,227,64,237,216,13,248,81,191,104,240,43,248,161,72,151,159,196,90,34,48,42,226,158,87,79,127,73,111,246,199,245,8,147,213,64,167,125,109,252,192,24,53,159,208,78,141,35,183,43,159,150,24,197,39,42,127,160,186,253,71,25,2,65,32,124,16,244,143,146,168,72,232,247,155,20,88,61,35,168,63,88,49,29,144,182,137,161,247,211,20,118,207,106,172,202,168,15,190,127,7,225,6,195,96,132,94,160,112,210,230,28,23,183,244,169,184,89,76,21,223,60,209,194,231,133,105,126,128,224,123,203,47,14,195,119,72,107,203,13,15,162,115,177,104,199,97,4,199,41,217,184,160,76,68,111,152,245,252,211,255,144,238,102,80,126,86,218,55,27,14,185,39,77,182,5,64,40,164,176,239,198,28,12,136,163,129,219,176,26,57,103,215,127,43,210,120,145,147,110,31,244,59,38,247,3,131,154,144,102,145,47,63,136,41,147,88,237,180,68,96,84,12,248,7,49,30,77,168,223,166,241,207,186,254,146,223,236,70,46,184,137,84,155,23,103,236,39,112,2,113,240,72,187,201,76,47,222,219,249,128,48,99,69,231,85], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+10336); +/* memory initializer */ allocate([107,63,160,156,211,131,199,249,193,54,104,23,121,138,15,114,228,93,55,203,92,225,80,174,78,84,255,64,246,232,152,37,174,139,136,115,22,55,239,22,4,130,64,248,188,62,39,157,33,233,31,36,153,85,120,65,139,224,215,175,51,92,176,202,237,89,182,59,85,229,209,94,71,80,126,176,255,236,25,213,98,59,33,108,218,135,70,9,200,50,233,231,112,142,142,130,40,237,158,212,144,81,249,177,130,228,86,95,58,88,49,58,167,143,9,131,31,51,110,230,13,134,193,8,181,58,166,109,189,64,225,164,5,252,134,193,23,73,41,47,175,245,78,74,50,34,118,243,138,158,17,150,152,43,190,120,32,151,217,29,120,244,201,75,192,72,174,46,210,253,1,192,106,65,102,165,247,150,94,28,79,42,57,121,93,159,150,151,229,35,241,242,77,107,25,5,245,215,126,96,231,98,209,142,95,222,182,235,194,9,142,82,122,181,233,55,104,0,70,217,208,188,33,188,136,223,49,234,48,99,86,143,34,214,249,97,154,106,158,4,7,189,166,189,191,1,193,216,173,180,110,54,21,8,9,83,29,114,78,154,165,206,41,255,183,123,134,17,15,199,225,116,146,16,217,205,42,172,190,168,56,25,17,70,128,165,118,35,216,198,102,117,96,122,1,16,114,207,174,254,202,115,201,155,87,164,241,34,239,24,150,71,253,173,57,169,69,17,94,204,118,77,238,6,206,241,137,99,220,68,38,141,100,248,65,232,249,47,121,81,65,147,30,52,83,38,177,218,235,154,214,191,179,249,198,233,11,69,161,140,25,240,14,98,161,76,105,7,60,155,81,190,132,39,54,219,150,146,153,53,46,46,254,80,38,84,185,153,158,232,222,252,140,93,113,18,52,225,22,119,169,54,46,206,17,138,73,171,3,63,230,69,187,131,129,32,227,224,145,118,91,92,246,19,73,233,89,253,241,85,62,152,108,130,6,33,212,62,97,68,198,139,206,170,126,55,169,207,214,127,65,56,110,195,38,93,124,118,137,179,196,202,238,214,89,29,214,111,225,161,177,10,243,20,30,228,75,168,121,129,19,203,105,215,171,119,14,178,185,194,161,92,1,126,198,57,156,169,254,128,36,21,153,229,54,160,54,11,142,28,81,110,134,102,22,167,62,218,113,194,44,111,222,44,148,211,185,73,9,4,129,240,177,184,230,149,163,13,73,123,27,177,46,30,67,210,62,72,251,110,89,45,233,219,246,195,81,103,145,166,204,176,169,31,116,12,206,122,102,185,97,148,222,5,6,241,0,0,0,0,0,0,0,0,1,0,0,0,4,0,4,0,8,0,4,0,2,0,0,0,4,0,5,0,16,0,8,0,2,0,0,0,4,0,6,0,32,0,32,0,2,0,0,0,4,0,4,0,16,0,16,0,3,0,0,0,8,0,16,0,32,0,32,0,3,0,0,0,8,0,16,0,128,0,128,0,3,0,0,0,8,0,32,0,128,0,0,1,3,0,0,0,32,0,128,0,2,1,0,4,3,0,0,0,32,0,2,1,2,1,0,16,3,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,58,32,0,0,0,0,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,49,46,50,46,53,0,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,117,110,101,120,112,101,99,116,101,100,32,101,110,100,32,111,102,32,102,105,108,101,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,105,110,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,99,111,109,112,114,101,115,115,101,100,32,100,97,116,97,32,101,114,114,111,114,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,100,101,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,49,46,50,46,53,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,16,0,17,0,18,0,0,0,8,0,7,0,9,0,6,0,10,0,5,0,11,0,4,0,12,0,3,0,13,0,2,0,14,0,1,0,15,0,0,0,105,110,99,111,114,114,101,99,116,32,104,101,97,100,101,114,32,99,104,101,99,107,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,105,110,118,97,108,105,100,32,119,105,110,100,111,119,32,115,105,122,101,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,104,101,97,100,101,114,32,99,114,99,32,109,105,115,109,97,116,99,104,0,0,0,0,0,105,110,118,97,108,105,100,32,98,108,111,99,107,32,116,121,112,101,0,0,0,0,0,0,105,110,118,97,108,105,100,32,115,116,111,114,101,100,32,98,108,111,99,107,32,108,101,110,103,116,104,115,0,0,0,0,116,111,111,32,109,97,110,121,32,108,101,110,103,116,104,32,111,114,32,100,105,115,116,97,110,99,101,32,115,121,109,98,111,108,115,0,0,0,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,0,0,0,105,110,118,97,108,105,100,32,98,105,116,32,108,101,110,103,116,104,32,114,101,112,101,97,116,0,0,0,0,0,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,45,45,32,109,105,115,115,105,110,103,32,101,110,100,45,111,102,45,98,108,111,99,107,0,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,115,32,115,101,116,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,192,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,160,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,224,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,144,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,208,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,176,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,240,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,200,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,168,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,232,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,152,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,216,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,184,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,248,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,196,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,164,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,228,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,148,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,212,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,180,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,244,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,204,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,172,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,236,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,156,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,220,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,188,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,252,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,194,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,162,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,226,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,146,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,210,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,178,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,242,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,202,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,170,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,234,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,154,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,218,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,186,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,250,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,198,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,166,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,230,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,150,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,214,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,182,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,246,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,206,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,174,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,238,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,158,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,222,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,190,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,254,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,193,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,161,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,225,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,145,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,209,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,177,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,241,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,201,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,169,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,233,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,153,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,217,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,185,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,249,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,197,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,165,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,229,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,149,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,213,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,181,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,245,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,205,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,173,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,237,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,157,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,221,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,189,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,253,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,195,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,163,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,227,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,147,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,211,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,179,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,243,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,203,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,171,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,235,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,155,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,219,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,187,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,251,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,199,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,167,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,231,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,151,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,215,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,183,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,247,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,207,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,175,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,239,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,159,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,223,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,191,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,255,0,16,5,1,0,23,5,1,1,19,5,17,0,27,5,1,16,17,5,5,0,25,5,1,4,21,5,65,0,29,5,1,64,16,5,3,0,24,5,1,2,20,5,33,0,28,5,1,32,18,5,9,0,26,5,1,8,22,5,129,0,64,5,0,0,16,5,2,0,23,5,129,1,19,5,25,0,27,5,1,24,17,5,7,0,25,5,1,6,21,5,97,0,29,5,1,96,16,5,4,0,24,5,1,3,20,5,49,0,28,5,1,48,18,5,13,0,26,5,1,12,22,5,193,0,64,5,0,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,13,0,15,0,17,0,19,0,23,0,27,0,31,0,35,0,43,0,51,0,59,0,67,0,83,0,99,0,115,0,131,0,163,0,195,0,227,0,2,1,0,0,0,0,0,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,17,0,17,0,17,0,17,0,18,0,18,0,18,0,18,0,19,0,19,0,19,0,19,0,20,0,20,0,20,0,20,0,21,0,21,0,21,0,21,0,16,0,73,0,195,0,0,0,1,0,2,0,3,0,4,0,5,0,7,0,9,0,13,0,17,0,25,0,33,0,49,0,65,0,97,0,129,0,193,0,1,1,129,1,1,2,1,3,1,4,1,6,1,8,1,12,1,16,1,24,1,32,1,48,1,64,1,96,0,0,0,0,16,0,16,0,16,0,16,0,17,0,17,0,18,0,18,0,19,0,19,0,20,0,20,0,21,0,21,0,22,0,22,0,23,0,23,0,24,0,24,0,25,0,25,0,26,0,26,0,27,0,27,0,28,0,28,0,29,0,29,0,64,0,64,0,0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,0,100,0,0,248,104,0,0,1,1,0,0,30,1,0,0,15,0,0,0,0,0,0,0,128,104,0,0,232,105,0,0,0,0,0,0,30,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,240,106,0,0,0,0,0,0,19,0,0,0,7,0,0,0,0,0,0,0,12,0,8,0,140,0,8,0,76,0,8,0,204,0,8,0,44,0,8,0,172,0,8,0,108,0,8,0,236,0,8,0,28,0,8,0,156,0,8,0,92,0,8,0,220,0,8,0,60,0,8,0,188,0,8,0,124,0,8,0,252,0,8,0,2,0,8,0,130,0,8,0,66,0,8,0,194,0,8,0,34,0,8,0,162,0,8,0,98,0,8,0,226,0,8,0,18,0,8,0,146,0,8,0,82,0,8,0,210,0,8,0,50,0,8,0,178,0,8,0,114,0,8,0,242,0,8,0,10,0,8,0,138,0,8,0,74,0,8,0,202,0,8,0,42,0,8,0,170,0,8,0,106,0,8,0,234,0,8,0,26,0,8,0,154,0,8,0,90,0,8,0,218,0,8,0,58,0,8,0,186,0,8,0,122,0,8,0,250,0,8,0,6,0,8,0,134,0,8,0,70,0,8,0,198,0,8,0,38,0,8,0,166,0,8,0,102,0,8,0,230,0,8,0,22,0,8,0,150,0,8,0,86,0,8,0,214,0,8,0,54,0,8,0,182,0,8,0,118,0,8,0,246,0,8,0,14,0,8,0,142,0,8,0,78,0,8,0,206,0,8,0,46,0,8,0,174,0,8,0,110,0,8,0,238,0,8,0,30,0,8,0,158,0,8,0,94,0,8,0,222,0,8,0,62,0,8,0,190,0,8,0,126,0,8,0,254,0,8,0,1,0,8,0,129,0,8,0,65,0,8,0,193,0,8,0,33,0,8,0,161,0,8,0,97,0,8,0,225,0,8,0,17,0,8,0,145,0,8,0,81,0,8,0,209,0,8,0,49,0,8,0,177,0,8,0,113,0,8,0,241,0,8,0,9,0,8,0,137,0,8,0,73,0,8,0,201,0,8,0,41,0,8,0,169,0,8,0,105,0,8,0,233,0,8,0,25,0,8,0,153,0,8,0,89,0,8,0,217,0,8,0,57,0,8,0,185,0,8,0,121,0,8,0,249,0,8,0,5,0,8,0,133,0,8,0,69,0,8,0,197,0,8,0,37,0,8,0,165,0,8,0,101,0,8,0,229,0,8,0,21,0,8,0,149,0,8,0,85,0,8,0,213,0,8,0,53,0,8,0,181,0,8,0,117,0,8,0,245,0,8,0,13,0,8,0,141,0,8,0,77,0,8,0,205,0,8,0,45,0,8,0,173,0,8,0,109,0,8,0,237,0,8,0,29,0,8,0,157,0,8,0,93,0,8,0,221,0,8,0,61,0,8,0,189,0,8,0,125,0,8,0,253,0,8,0,19,0,9,0,19,1,9,0,147,0,9,0,147,1,9,0,83,0,9,0,83,1,9,0,211,0,9,0,211,1,9,0,51,0,9,0,51,1,9,0,179,0,9,0,179,1,9,0,115,0,9,0,115,1,9,0,243,0,9,0,243,1,9,0,11,0,9,0,11,1,9,0,139,0,9,0,139,1,9,0,75,0,9,0,75,1,9,0,203,0,9,0,203,1,9,0,43,0,9,0,43,1,9,0,171,0,9,0,171,1,9,0,107,0,9,0,107,1,9,0,235,0,9,0,235,1,9,0,27,0,9,0,27,1,9,0,155,0,9,0,155,1,9,0,91,0,9,0,91,1,9,0,219,0,9,0,219,1,9,0,59,0,9,0,59,1,9,0,187,0,9,0,187,1,9,0,123,0,9,0,123,1,9,0,251,0,9,0,251,1,9,0,7,0,9,0,7,1,9,0,135,0,9,0,135,1,9,0,71,0,9,0,71,1,9,0,199,0,9,0,199,1,9,0,39,0,9,0,39,1,9,0,167,0,9,0,167,1,9,0,103,0,9,0,103,1,9,0,231,0,9,0,231,1,9,0,23,0,9,0,23,1,9,0,151,0,9,0,151,1,9,0,87,0,9,0,87,1,9,0,215,0,9,0,215,1,9,0,55,0,9,0,55,1,9,0,183,0,9,0,183,1,9,0,119,0,9,0,119,1,9,0,247,0,9,0,247,1,9,0,15,0,9,0,15,1,9,0,143,0,9,0,143,1,9,0,79,0,9,0,79,1,9,0,207,0,9,0,207,1,9,0,47,0,9,0,47,1,9,0,175,0,9,0,175,1,9,0,111,0,9,0,111,1,9,0,239,0,9,0,239,1,9,0,31,0,9,0,31,1,9,0,159,0,9,0,159,1,9,0,95,0,9,0,95,1,9,0,223,0,9,0,223,1,9,0,63,0,9,0,63,1,9,0,191,0,9,0,191,1,9,0,127,0,9,0,127,1,9,0,255,0,9,0,255,1,9,0,0,0,7,0,64,0,7,0,32,0,7,0,96,0,7,0,16,0,7,0,80,0,7,0,48,0,7,0,112,0,7,0,8,0,7,0,72,0,7,0,40,0,7,0,104,0,7,0,24,0,7,0,88,0,7,0,56,0,7,0,120,0,7,0,4,0,7,0,68,0,7,0,36,0,7,0,100,0,7,0,20,0,7,0,84,0,7,0,52,0,7,0,116,0,7,0,3,0,8,0,131,0,8,0,67,0,8,0,195,0,8,0,35,0,8,0,163,0,8,0,99,0,8,0,227,0,8,0,0,0,5,0,16,0,5,0,8,0,5,0,24,0,5,0,4,0,5,0,20,0,5,0,12,0,5,0,28,0,5,0,2,0,5,0,18,0,5,0,10,0,5,0,26,0,5,0,6,0,5,0,22,0,5,0,14,0,5,0,30,0,5,0,1,0,5,0,17,0,5,0,9,0,5,0,25,0,5,0,5,0,5,0,21,0,5,0,13,0,5,0,29,0,5,0,3,0,5,0,19,0,5,0,11,0,5,0,27,0,5,0,7,0,5,0,23,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,8,0,0,0,10,0,0,0,12,0,0,0,14,0,0,0,16,0,0,0,20,0,0,0,24,0,0,0,28,0,0,0,32,0,0,0,40,0,0,0,48,0,0,0,56,0,0,0,64,0,0,0,80,0,0,0,96,0,0,0,112,0,0,0,128,0,0,0,160,0,0,0,192,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,6,0,0,0,6,0,0,0,7,0,0,0,7,0,0,0,8,0,0,0,8,0,0,0,9,0,0,0,9,0,0,0,10,0,0,0,10,0,0,0,11,0,0,0,11,0,0,0,12,0,0,0,12,0,0,0,13,0,0,0,13,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,0,128,0,0,0,192,0,0,0,0,1,0,0,128,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,7,0,0,0,0,0,0,0,110,101,101,100,32,100,105,99,116,105,111,110,97,114,121,0,115,116,114,101,97,109,32,101,110,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,105,108,101,32,101,114,114,111,114,0,0,0,0,0,0,115,116,114,101,97,109,32,101,114,114,111,114,0,0,0,0,100,97,116,97,32,101,114,114,111,114,0,0,0,0,0,0,105,110,115,117,102,102,105,99,105,101,110,116,32,109,101,109,111,114,121,0,0,0,0,0,98,117,102,102,101,114,32,101,114,114,111,114,0,0,0,0,105,110,99,111,109,112,97,116,105,98,108,101,32,118,101,114,115,105,111,110,0,0,0,0,64,107,0,0,80,107,0,0,96,107,0,0,104,107,0,0,120,107,0,0,136,107,0,0,152,107,0,0,176,107,0,0,192,107,0,0,96,107,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,105,110,102,105,110,105,116,121,0,0,0,0,0,0,0,0,110,97,110,0,0,0,0,0,95,112,137,0,255,9,47,15,10,0,0,0,100,0,0,0,232,3,0,0,16,39,0,0,160,134,1,0,64,66,15,0,128,150,152,0,0,225,245,5], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+20576); + + + + +var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8); + +assert(tempDoublePtr % 8 == 0); + +function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much + + HEAP8[tempDoublePtr] = HEAP8[ptr]; + + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + +} + +function copyTempDouble(ptr) { + + HEAP8[tempDoublePtr] = HEAP8[ptr]; + + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + + HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; + + HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; + + HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; + + HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; + +} + + + + + var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86}; + + var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"}; + + + var ___errno_state=0;function ___setErrNo(value) { + // For convenient setting and returning of errno. + HEAP32[((___errno_state)>>2)]=value; + return value; + } + + var PATH={splitPath:function (filename) { + var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + return splitPathRe.exec(filename).slice(1); + },normalizeArray:function (parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + 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 the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + return parts; + },normalize:function (path) { + var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.substr(-1) === '/'; + // Normalize the path + path = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), !isAbsolute).join('/'); + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + return (isAbsolute ? '/' : '') + path; + },dirname:function (path) { + var result = PATH.splitPath(path), + root = result[0], + dir = result[1]; + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + return root + dir; + },basename:function (path) { + // EMSCRIPTEN return '/'' for '/', not an empty string + if (path === '/') return '/'; + var lastSlash = path.lastIndexOf('/'); + if (lastSlash === -1) return path; + return path.substr(lastSlash+1); + },extname:function (path) { + return PATH.splitPath(path)[3]; + },join:function () { + var paths = Array.prototype.slice.call(arguments, 0); + return PATH.normalize(paths.join('/')); + },join2:function (l, r) { + return PATH.normalize(l + '/' + r); + },resolve:function () { + var resolvedPath = '', + resolvedAbsolute = false; + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : FS.cwd(); + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + },relative:function (from, to) { + from = PATH.resolve(from).substr(1); + to = PATH.resolve(to).substr(1); + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + var end = arr.length - 1; + for (; end >= 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 < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + return outputParts.join('/'); + }}; + + var TTY={ttys:[],init:function () { + // https://github.com/kripken/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // currently, FS.init does not distinguish if process.stdin is a file or TTY + // // device, it always assumes it's a TTY device. because of this, we're forcing + // // process.stdin to UTF8 encoding to at least make stdin reading compatible + // // with text files until FS.init can be refactored. + // process['stdin']['setEncoding']('utf8'); + // } + },shutdown:function () { + // https://github.com/kripken/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? + // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation + // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists? + // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle + // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call + // process['stdin']['pause'](); + // } + },register:function (dev, ops) { + TTY.ttys[dev] = { input: [], output: [], ops: ops }; + FS.registerDevice(dev, TTY.stream_ops); + },stream_ops:{open:function (stream) { + var tty = TTY.ttys[stream.node.rdev]; + if (!tty) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + stream.tty = tty; + stream.seekable = false; + },close:function (stream) { + // flush any pending line data + if (stream.tty.output.length) { + stream.tty.ops.put_char(stream.tty, 10); + } + },read:function (stream, buffer, offset, length, pos /* ignored */) { + if (!stream.tty || !stream.tty.ops.get_char) { + throw new FS.ErrnoError(ERRNO_CODES.ENXIO); + } + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = stream.tty.ops.get_char(stream.tty); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + },write:function (stream, buffer, offset, length, pos) { + if (!stream.tty || !stream.tty.ops.put_char) { + throw new FS.ErrnoError(ERRNO_CODES.ENXIO); + } + for (var i = 0; i < length; i++) { + try { + stream.tty.ops.put_char(stream.tty, buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + }},default_tty_ops:{get_char:function (tty) { + if (!tty.input.length) { + var result = null; + if (ENVIRONMENT_IS_NODE) { + result = process['stdin']['read'](); + if (!result) { + if (process['stdin']['_readableState'] && process['stdin']['_readableState']['ended']) { + return null; // EOF + } + return undefined; // no data available + } + } else if (typeof window != 'undefined' && + typeof window.prompt == 'function') { + // Browser. + result = window.prompt('Input: '); // returns null on cancel + if (result !== null) { + result += '\n'; + } + } else if (typeof readline == 'function') { + // Command line. + result = readline(); + if (result !== null) { + result += '\n'; + } + } + if (!result) { + return null; + } + tty.input = intArrayFromString(result, true); + } + return tty.input.shift(); + },put_char:function (tty, val) { + if (val === null || val === 10) { + Module['print'](tty.output.join('')); + tty.output = []; + } else { + tty.output.push(TTY.utf8.processCChar(val)); + } + }},default_tty1_ops:{put_char:function (tty, val) { + if (val === null || val === 10) { + Module['printErr'](tty.output.join('')); + tty.output = []; + } else { + tty.output.push(TTY.utf8.processCChar(val)); + } + }}}; + + var MEMFS={ops_table:null,CONTENT_OWNING:1,CONTENT_FLEXIBLE:2,CONTENT_FIXED:3,mount:function (mount) { + return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + },createNode:function (parent, name, mode, dev) { + if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { + // no supported + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (!MEMFS.ops_table) { + 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, + allocate: MEMFS.stream_ops.allocate, + mmap: MEMFS.stream_ops.mmap + } + }, + 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.contents = []; + node.contentMode = MEMFS.CONTENT_FLEXIBLE; + } 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.timestamp = Date.now(); + // add the new node to the parent + if (parent) { + parent.contents[name] = node; + } + return node; + },ensureFlexible:function (node) { + if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) { + var contents = node.contents; + node.contents = Array.prototype.slice.call(contents); + node.contentMode = MEMFS.CONTENT_FLEXIBLE; + } + },node_ops:{getattr:function (node) { + var attr = {}; + // device numbers reuse inode numbers. + 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.contents.length; + } else if (FS.isLink(node.mode)) { + attr.size = node.link.length; + } else { + attr.size = 0; + } + attr.atime = new Date(node.timestamp); + attr.mtime = new Date(node.timestamp); + attr.ctime = new Date(node.timestamp); + // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), + // but this is not required by the standard. + attr.blksize = 4096; + attr.blocks = Math.ceil(attr.size / attr.blksize); + return attr; + },setattr:function (node, attr) { + if (attr.mode !== undefined) { + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + node.timestamp = attr.timestamp; + } + if (attr.size !== undefined) { + MEMFS.ensureFlexible(node); + var contents = node.contents; + if (attr.size < contents.length) contents.length = attr.size; + else while (attr.size > contents.length) contents.push(0); + } + },lookup:function (parent, name) { + throw FS.genericErrors[ERRNO_CODES.ENOENT]; + },mknod:function (parent, name, mode, dev) { + return MEMFS.createNode(parent, name, mode, dev); + },rename:function (old_node, new_dir, new_name) { + // if we're overwriting a directory at new_name, make sure it's empty. + if (FS.isDir(old_node.mode)) { + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + } + if (new_node) { + for (var i in new_node.contents) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + } + } + // do the internal rewiring + delete old_node.parent.contents[old_node.name]; + old_node.name = new_name; + new_dir.contents[new_name] = old_node; + old_node.parent = new_dir; + },unlink:function (parent, name) { + delete parent.contents[name]; + },rmdir:function (parent, name) { + var node = FS.lookupNode(parent, name); + for (var i in node.contents) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + delete parent.contents[name]; + },readdir:function (node) { + var entries = ['.', '..'] + for (var key in node.contents) { + if (!node.contents.hasOwnProperty(key)) { + continue; + } + entries.push(key); + } + return entries; + },symlink:function (parent, newname, oldpath) { + var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0); + node.link = oldpath; + return node; + },readlink:function (node) { + if (!FS.isLink(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + return node.link; + }},stream_ops:{read:function (stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (size > 8 && contents.subarray) { // non-trivial, and typed array + buffer.set(contents.subarray(position, position + size), offset); + } else + { + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } + return size; + },write:function (stream, buffer, offset, length, position, canOwn) { + var node = stream.node; + node.timestamp = Date.now(); + var contents = node.contents; + if (length && contents.length === 0 && position === 0 && buffer.subarray) { + // just replace it with the new data + if (canOwn && offset === 0) { + node.contents = buffer; // this could be a subarray of Emscripten HEAP, or allocated from some other source. + node.contentMode = (buffer.buffer === HEAP8.buffer) ? MEMFS.CONTENT_OWNING : MEMFS.CONTENT_FIXED; + } else { + node.contents = new Uint8Array(buffer.subarray(offset, offset+length)); + node.contentMode = MEMFS.CONTENT_FIXED; + } + return length; + } + MEMFS.ensureFlexible(node); + var contents = node.contents; + while (contents.length < position) contents.push(0); + for (var i = 0; i < length; i++) { + contents[position + i] = buffer[offset + i]; + } + return length; + },llseek:function (stream, offset, whence) { + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + if (FS.isFile(stream.node.mode)) { + position += stream.node.contents.length; + } + } + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + stream.ungotten = []; + stream.position = position; + return position; + },allocate:function (stream, offset, length) { + MEMFS.ensureFlexible(stream.node); + var contents = stream.node.contents; + var limit = offset + length; + while (limit > contents.length) contents.push(0); + },mmap:function (stream, buffer, offset, length, position, prot, flags) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + var ptr; + var allocated; + var contents = stream.node.contents; + // Only make a new copy when MAP_PRIVATE is specified. + if ( !(flags & 2) && + (contents.buffer === buffer || contents.buffer === buffer.buffer) ) { + // We can't emulate MAP_SHARED when the file is not backed by the buffer + // we're mapping to (e.g. the HEAP buffer). + allocated = false; + ptr = contents.byteOffset; + } else { + // Try to avoid unnecessary slices. + if (position > 0 || position + length < contents.length) { + if (contents.subarray) { + contents = contents.subarray(position, position + length); + } else { + contents = Array.prototype.slice.call(contents, position, position + length); + } + } + allocated = true; + ptr = _malloc(length); + if (!ptr) { + throw new FS.ErrnoError(ERRNO_CODES.ENOMEM); + } + buffer.set(contents, ptr); + } + return { ptr: ptr, allocated: allocated }; + }}}; + + var IDBFS={dbs:{},indexedDB:function () { + return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + },DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:function (mount) { + // reuse all of the core MEMFS functionality + return MEMFS.mount.apply(null, arguments); + },syncfs:function (mount, populate, callback) { + IDBFS.getLocalSet(mount, function(err, local) { + if (err) return callback(err); + + IDBFS.getRemoteSet(mount, function(err, remote) { + if (err) return callback(err); + + var src = populate ? remote : local; + var dst = populate ? local : remote; + + IDBFS.reconcile(src, dst, callback); + }); + }); + },getDB:function (name, callback) { + // check the cache first + var db = IDBFS.dbs[name]; + if (db) { + return callback(null, db); + } + + var req; + try { + req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION); + } catch (e) { + return callback(e); + } + req.onupgradeneeded = function(e) { + var db = e.target.result; + var transaction = e.target.transaction; + + var fileStore; + + if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) { + fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME); + } else { + fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME); + } + + fileStore.createIndex('timestamp', 'timestamp', { unique: false }); + }; + req.onsuccess = function() { + db = req.result; + + // add to the cache + IDBFS.dbs[name] = db; + callback(null, db); + }; + req.onerror = function() { + callback(this.error); + }; + },getLocalSet:function (mount, callback) { + var entries = {}; + + function isRealDir(p) { + return p !== '.' && p !== '..'; + }; + function toAbsolute(root) { + return function(p) { + return PATH.join2(root, p); + } + }; + + var check = FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint)); + + while (check.length) { + var path = check.pop(); + var stat; + + try { + stat = FS.stat(path); + } catch (e) { + return callback(e); + } + + if (FS.isDir(stat.mode)) { + check.push.apply(check, FS.readdir(path).filter(isRealDir).map(toAbsolute(path))); + } + + entries[path] = { timestamp: stat.mtime }; + } + + return callback(null, { type: 'local', entries: entries }); + },getRemoteSet:function (mount, callback) { + var entries = {}; + + IDBFS.getDB(mount.mountpoint, function(err, db) { + if (err) return callback(err); + + var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readonly'); + transaction.onerror = function() { callback(this.error); }; + + var store = transaction.objectStore(IDBFS.DB_STORE_NAME); + var index = store.index('timestamp'); + + index.openKeyCursor().onsuccess = function(event) { + var cursor = event.target.result; + + if (!cursor) { + return callback(null, { type: 'remote', db: db, entries: entries }); + } + + entries[cursor.primaryKey] = { timestamp: cursor.key }; + + cursor.continue(); + }; + }); + },loadLocalEntry:function (path, callback) { + var stat, node; + + try { + var lookup = FS.lookupPath(path); + node = lookup.node; + stat = FS.stat(path); + } catch (e) { + return callback(e); + } + + if (FS.isDir(stat.mode)) { + return callback(null, { timestamp: stat.mtime, mode: stat.mode }); + } else if (FS.isFile(stat.mode)) { + return callback(null, { timestamp: stat.mtime, mode: stat.mode, contents: node.contents }); + } else { + return callback(new Error('node type not supported')); + } + },storeLocalEntry:function (path, entry, callback) { + try { + if (FS.isDir(entry.mode)) { + FS.mkdir(path, entry.mode); + } else if (FS.isFile(entry.mode)) { + FS.writeFile(path, entry.contents, { encoding: 'binary', canOwn: true }); + } else { + return callback(new Error('node type not supported')); + } + + FS.utime(path, entry.timestamp, entry.timestamp); + } catch (e) { + return callback(e); + } + + callback(null); + },removeLocalEntry:function (path, callback) { + try { + var lookup = FS.lookupPath(path); + var stat = FS.stat(path); + + if (FS.isDir(stat.mode)) { + FS.rmdir(path); + } else if (FS.isFile(stat.mode)) { + FS.unlink(path); + } + } catch (e) { + return callback(e); + } + + callback(null); + },loadRemoteEntry:function (store, path, callback) { + var req = store.get(path); + req.onsuccess = function(event) { callback(null, event.target.result); }; + req.onerror = function() { callback(this.error); }; + },storeRemoteEntry:function (store, path, entry, callback) { + var req = store.put(entry, path); + req.onsuccess = function() { callback(null); }; + req.onerror = function() { callback(this.error); }; + },removeRemoteEntry:function (store, path, callback) { + var req = store.delete(path); + req.onsuccess = function() { callback(null); }; + req.onerror = function() { callback(this.error); }; + },reconcile:function (src, dst, callback) { + var total = 0; + + var create = []; + Object.keys(src.entries).forEach(function (key) { + var e = src.entries[key]; + var e2 = dst.entries[key]; + if (!e2 || e.timestamp > e2.timestamp) { + create.push(key); + total++; + } + }); + + var remove = []; + Object.keys(dst.entries).forEach(function (key) { + var e = dst.entries[key]; + var e2 = src.entries[key]; + if (!e2) { + remove.push(key); + total++; + } + }); + + if (!total) { + return callback(null); + } + + var errored = false; + var completed = 0; + var db = src.type === 'remote' ? src.db : dst.db; + var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite'); + var store = transaction.objectStore(IDBFS.DB_STORE_NAME); + + function done(err) { + if (err) { + if (!done.errored) { + done.errored = true; + return callback(err); + } + return; + } + if (++completed >= total) { + return callback(null); + } + }; + + transaction.onerror = function() { done(this.error); }; + + // sort paths in ascending order so directory entries are created + // before the files inside them + create.sort().forEach(function (path) { + if (dst.type === 'local') { + IDBFS.loadRemoteEntry(store, path, function (err, entry) { + if (err) return done(err); + IDBFS.storeLocalEntry(path, entry, done); + }); + } else { + IDBFS.loadLocalEntry(path, function (err, entry) { + if (err) return done(err); + IDBFS.storeRemoteEntry(store, path, entry, done); + }); + } + }); + + // sort paths in descending order so files are deleted before their + // parent directories + remove.sort().reverse().forEach(function(path) { + if (dst.type === 'local') { + IDBFS.removeLocalEntry(path, done); + } else { + IDBFS.removeRemoteEntry(store, path, done); + } + }); + }}; + + var NODEFS={isWindows:false,staticInit:function () { + NODEFS.isWindows = !!process.platform.match(/^win/); + },mount:function (mount) { + assert(ENVIRONMENT_IS_NODE); + return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0); + },createNode:function (parent, name, mode, dev) { + if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node = FS.createNode(parent, name, mode); + node.node_ops = NODEFS.node_ops; + node.stream_ops = NODEFS.stream_ops; + return node; + },getMode:function (path) { + var stat; + try { + stat = fs.lstatSync(path); + if (NODEFS.isWindows) { + // On Windows, directories return permission bits 'rw-rw-rw-', even though they have 'rwxrwxrwx', so + // propagate write bits to execute bits. + stat.mode = stat.mode | ((stat.mode & 146) >> 1); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return stat.mode; + },realPath:function (node) { + var parts = []; + while (node.parent !== node) { + parts.push(node.name); + node = node.parent; + } + parts.push(node.mount.opts.root); + parts.reverse(); + return PATH.join.apply(null, parts); + },flagsToPermissionStringMap:{0:"r",1:"r+",2:"r+",64:"r",65:"r+",66:"r+",129:"rx+",193:"rx+",514:"w+",577:"w",578:"w+",705:"wx",706:"wx+",1024:"a",1025:"a",1026:"a+",1089:"a",1090:"a+",1153:"ax",1154:"ax+",1217:"ax",1218:"ax+",4096:"rs",4098:"rs+"},flagsToPermissionString:function (flags) { + if (flags in NODEFS.flagsToPermissionStringMap) { + return NODEFS.flagsToPermissionStringMap[flags]; + } else { + return flags; + } + },node_ops:{getattr:function (node) { + var path = NODEFS.realPath(node); + var stat; + try { + stat = fs.lstatSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + // node.js v0.10.20 doesn't report blksize and blocks on Windows. Fake them with default blksize of 4096. + // See http://support.microsoft.com/kb/140365 + if (NODEFS.isWindows && !stat.blksize) { + stat.blksize = 4096; + } + if (NODEFS.isWindows && !stat.blocks) { + stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0; + } + return { + dev: stat.dev, + ino: stat.ino, + mode: stat.mode, + nlink: stat.nlink, + uid: stat.uid, + gid: stat.gid, + rdev: stat.rdev, + size: stat.size, + atime: stat.atime, + mtime: stat.mtime, + ctime: stat.ctime, + blksize: stat.blksize, + blocks: stat.blocks + }; + },setattr:function (node, attr) { + var path = NODEFS.realPath(node); + try { + if (attr.mode !== undefined) { + fs.chmodSync(path, attr.mode); + // update the common node structure mode as well + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + var date = new Date(attr.timestamp); + fs.utimesSync(path, date, date); + } + if (attr.size !== undefined) { + fs.truncateSync(path, attr.size); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },lookup:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + var mode = NODEFS.getMode(path); + return NODEFS.createNode(parent, name, mode); + },mknod:function (parent, name, mode, dev) { + var node = NODEFS.createNode(parent, name, mode, dev); + // create the backing node for this in the fs root as well + var path = NODEFS.realPath(node); + try { + if (FS.isDir(node.mode)) { + fs.mkdirSync(path, node.mode); + } else { + fs.writeFileSync(path, '', { mode: node.mode }); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return node; + },rename:function (oldNode, newDir, newName) { + var oldPath = NODEFS.realPath(oldNode); + var newPath = PATH.join2(NODEFS.realPath(newDir), newName); + try { + fs.renameSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },unlink:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.unlinkSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },rmdir:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.rmdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },readdir:function (node) { + var path = NODEFS.realPath(node); + try { + return fs.readdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },symlink:function (parent, newName, oldPath) { + var newPath = PATH.join2(NODEFS.realPath(parent), newName); + try { + fs.symlinkSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },readlink:function (node) { + var path = NODEFS.realPath(node); + try { + return fs.readlinkSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }},stream_ops:{open:function (stream) { + var path = NODEFS.realPath(stream.node); + try { + if (FS.isFile(stream.node.mode)) { + stream.nfd = fs.openSync(path, NODEFS.flagsToPermissionString(stream.flags)); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },close:function (stream) { + try { + if (FS.isFile(stream.node.mode) && stream.nfd) { + fs.closeSync(stream.nfd); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },read:function (stream, buffer, offset, length, position) { + // FIXME this is terrible. + var nbuffer = new Buffer(length); + var res; + try { + res = fs.readSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + if (res > 0) { + for (var i = 0; i < res; i++) { + buffer[offset + i] = nbuffer[i]; + } + } + return res; + },write:function (stream, buffer, offset, length, position) { + // FIXME this is terrible. + var nbuffer = new Buffer(buffer.subarray(offset, offset + length)); + var res; + try { + res = fs.writeSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return res; + },llseek:function (stream, offset, whence) { + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + if (FS.isFile(stream.node.mode)) { + try { + var stat = fs.fstatSync(stream.nfd); + position += stat.size; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + } + } + + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + stream.position = position; + return position; + }}}; + + var _stdin=allocate(1, "i32*", ALLOC_STATIC); + + var _stdout=allocate(1, "i32*", ALLOC_STATIC); + + var _stderr=allocate(1, "i32*", ALLOC_STATIC); + + function _fflush(stream) { + // int fflush(FILE *stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fflush.html + // we don't currently perform any user-space buffering of data + }var FS={root:null,mounts:[],devices:[null],streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},handleFSError:function (e) { + if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace(); + return ___setErrNo(e.errno); + },lookupPath:function (path, opts) { + path = PATH.resolve(FS.cwd(), path); + opts = opts || {}; + + var defaults = { + follow_mount: true, + recurse_count: 0 + }; + for (var key in defaults) { + if (opts[key] === undefined) { + opts[key] = defaults[key]; + } + } + + if (opts.recurse_count > 8) { // max recursive lookup of 8 + throw new FS.ErrnoError(ERRNO_CODES.ELOOP); + } + + // split the path + var parts = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), false); + + // start at the root + var current = FS.root; + var current_path = '/'; + + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + // stop resolving + break; + } + + current = FS.lookupNode(current, parts[i]); + current_path = PATH.join2(current_path, parts[i]); + + // jump to the mount's root node if this is a mountpoint + if (FS.isMountpoint(current)) { + if (!islast || (islast && opts.follow_mount)) { + current = current.mounted.root; + } + } + + // by default, lookupPath will not follow a symlink if it is the final path component. + // setting opts.follow = true will override this behavior. + if (!islast || opts.follow) { + var count = 0; + while (FS.isLink(current.mode)) { + var link = FS.readlink(current_path); + current_path = PATH.resolve(PATH.dirname(current_path), link); + + var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count }); + current = lookup.node; + + if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX). + throw new FS.ErrnoError(ERRNO_CODES.ELOOP); + } + } + } + } + + return { path: current_path, node: current }; + },getPath:function (node) { + var path; + while (true) { + if (FS.isRoot(node)) { + var mount = node.mount.mountpoint; + if (!path) return mount; + return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path; + } + path = path ? node.name + '/' + path : node.name; + node = node.parent; + } + },hashName:function (parentid, name) { + var hash = 0; + + + for (var i = 0; i < name.length; i++) { + hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; + } + return ((parentid + hash) >>> 0) % FS.nameTable.length; + },hashAddNode:function (node) { + var hash = FS.hashName(node.parent.id, node.name); + node.name_next = FS.nameTable[hash]; + FS.nameTable[hash] = node; + },hashRemoveNode:function (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:function (parent, name) { + var err = FS.mayLookup(parent); + if (err) { + throw new FS.ErrnoError(err); + } + 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; + } + } + // if we failed to find it in the cache, call into the VFS + return FS.lookup(parent, name); + },createNode:function (parent, name, mode, rdev) { + if (!FS.FSNode) { + FS.FSNode = function(parent, name, mode, rdev) { + if (!parent) { + parent = this; // root node sets parent to itself + } + this.parent = parent; + this.mount = parent.mount; + this.mounted = null; + this.id = FS.nextInode++; + this.name = name; + this.mode = mode; + this.node_ops = {}; + this.stream_ops = {}; + this.rdev = rdev; + }; + + FS.FSNode.prototype = {}; + + // compatibility + var readMode = 292 | 73; + var writeMode = 146; + + // NOTE we must use Object.defineProperties instead of individual calls to + // Object.defineProperty in order to make closure compiler happy + Object.defineProperties(FS.FSNode.prototype, { + read: { + get: function() { return (this.mode & readMode) === readMode; }, + set: function(val) { val ? this.mode |= readMode : this.mode &= ~readMode; } + }, + write: { + get: function() { return (this.mode & writeMode) === writeMode; }, + set: function(val) { val ? this.mode |= writeMode : this.mode &= ~writeMode; } + }, + isFolder: { + get: function() { return FS.isDir(this.mode); }, + }, + isDevice: { + get: function() { return FS.isChrdev(this.mode); }, + }, + }); + } + + var node = new FS.FSNode(parent, name, mode, rdev); + + FS.hashAddNode(node); + + return node; + },destroyNode:function (node) { + FS.hashRemoveNode(node); + },isRoot:function (node) { + return node === node.parent; + },isMountpoint:function (node) { + return !!node.mounted; + },isFile:function (mode) { + return (mode & 61440) === 32768; + },isDir:function (mode) { + return (mode & 61440) === 16384; + },isLink:function (mode) { + return (mode & 61440) === 40960; + },isChrdev:function (mode) { + return (mode & 61440) === 8192; + },isBlkdev:function (mode) { + return (mode & 61440) === 24576; + },isFIFO:function (mode) { + return (mode & 61440) === 4096; + },isSocket:function (mode) { + return (mode & 49152) === 49152; + },flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function (str) { + var flags = FS.flagModes[str]; + if (typeof flags === 'undefined') { + throw new Error('Unknown file open mode: ' + str); + } + return flags; + },flagsToPermissionString:function (flag) { + var accmode = flag & 2097155; + var perms = ['r', 'w', 'rw'][accmode]; + if ((flag & 512)) { + perms += 'w'; + } + return perms; + },nodePermissions:function (node, perms) { + if (FS.ignorePermissions) { + return 0; + } + // return 0 if any user, group or owner bits are set. + if (perms.indexOf('r') !== -1 && !(node.mode & 292)) { + return ERRNO_CODES.EACCES; + } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) { + return ERRNO_CODES.EACCES; + } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) { + return ERRNO_CODES.EACCES; + } + return 0; + },mayLookup:function (dir) { + return FS.nodePermissions(dir, 'x'); + },mayCreate:function (dir, name) { + try { + var node = FS.lookupNode(dir, name); + return ERRNO_CODES.EEXIST; + } catch (e) { + } + return FS.nodePermissions(dir, 'wx'); + },mayDelete:function (dir, name, isdir) { + var node; + try { + node = FS.lookupNode(dir, name); + } catch (e) { + return e.errno; + } + var err = FS.nodePermissions(dir, 'wx'); + if (err) { + return err; + } + if (isdir) { + if (!FS.isDir(node.mode)) { + return ERRNO_CODES.ENOTDIR; + } + if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { + return ERRNO_CODES.EBUSY; + } + } else { + if (FS.isDir(node.mode)) { + return ERRNO_CODES.EISDIR; + } + } + return 0; + },mayOpen:function (node, flags) { + if (!node) { + return ERRNO_CODES.ENOENT; + } + if (FS.isLink(node.mode)) { + return ERRNO_CODES.ELOOP; + } else if (FS.isDir(node.mode)) { + if ((flags & 2097155) !== 0 || // opening for write + (flags & 512)) { + return ERRNO_CODES.EISDIR; + } + } + return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); + },MAX_OPEN_FDS:4096,nextfd:function (fd_start, fd_end) { + fd_start = fd_start || 0; + fd_end = fd_end || FS.MAX_OPEN_FDS; + for (var fd = fd_start; fd <= fd_end; fd++) { + if (!FS.streams[fd]) { + return fd; + } + } + throw new FS.ErrnoError(ERRNO_CODES.EMFILE); + },getStream:function (fd) { + return FS.streams[fd]; + },createStream:function (stream, fd_start, fd_end) { + if (!FS.FSStream) { + FS.FSStream = function(){}; + FS.FSStream.prototype = {}; + // compatibility + Object.defineProperties(FS.FSStream.prototype, { + object: { + get: function() { return this.node; }, + set: function(val) { this.node = val; } + }, + isRead: { + get: function() { return (this.flags & 2097155) !== 1; } + }, + isWrite: { + get: function() { return (this.flags & 2097155) !== 0; } + }, + isAppend: { + get: function() { return (this.flags & 1024); } + } + }); + } + // clone it, so we can return an instance of FSStream + var newStream = new FS.FSStream(); + for (var p in stream) { + newStream[p] = stream[p]; + } + stream = newStream; + var fd = FS.nextfd(fd_start, fd_end); + stream.fd = fd; + FS.streams[fd] = stream; + return stream; + },closeStream:function (fd) { + FS.streams[fd] = null; + },getStreamFromPtr:function (ptr) { + return FS.streams[ptr - 1]; + },getPtrForStream:function (stream) { + return stream ? stream.fd + 1 : 0; + },chrdev_stream_ops:{open:function (stream) { + var device = FS.getDevice(stream.node.rdev); + // override node's stream ops with the device's + stream.stream_ops = device.stream_ops; + // forward the open call + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + },llseek:function () { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + }},major:function (dev) { + return ((dev) >> 8); + },minor:function (dev) { + return ((dev) & 0xff); + },makedev:function (ma, mi) { + return ((ma) << 8 | (mi)); + },registerDevice:function (dev, ops) { + FS.devices[dev] = { stream_ops: ops }; + },getDevice:function (dev) { + return FS.devices[dev]; + },getMounts:function (mount) { + var mounts = []; + var check = [mount]; + + while (check.length) { + var m = check.pop(); + + mounts.push(m); + + check.push.apply(check, m.mounts); + } + + return mounts; + },syncfs:function (populate, callback) { + if (typeof(populate) === 'function') { + callback = populate; + populate = false; + } + + var mounts = FS.getMounts(FS.root.mount); + var completed = 0; + + function done(err) { + if (err) { + if (!done.errored) { + done.errored = true; + return callback(err); + } + return; + } + if (++completed >= mounts.length) { + callback(null); + } + }; + + // sync all mounts + mounts.forEach(function (mount) { + if (!mount.type.syncfs) { + return done(null); + } + mount.type.syncfs(mount, populate, done); + }); + },mount:function (type, opts, mountpoint) { + var root = mountpoint === '/'; + var pseudo = !mountpoint; + var node; + + if (root && FS.root) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } else if (!root && !pseudo) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + mountpoint = lookup.path; // use the absolute path + node = lookup.node; + + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + + if (!FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + } + + var mount = { + type: type, + opts: opts, + mountpoint: mountpoint, + mounts: [] + }; + + // create a root node for the fs + var mountRoot = type.mount(mount); + mountRoot.mount = mount; + mount.root = mountRoot; + + if (root) { + FS.root = mountRoot; + } else if (node) { + // set as a mountpoint + node.mounted = mount; + + // add the new mount to the current mount's children + if (node.mount) { + node.mount.mounts.push(mount); + } + } + + return mountRoot; + },unmount:function (mountpoint) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + if (!FS.isMountpoint(lookup.node)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + // destroy the nodes for this mount, and all its child mounts + var node = lookup.node; + var mount = node.mounted; + var mounts = FS.getMounts(mount); + + Object.keys(FS.nameTable).forEach(function (hash) { + var current = FS.nameTable[hash]; + + while (current) { + var next = current.name_next; + + if (mounts.indexOf(current.mount) !== -1) { + FS.destroyNode(current); + } + + current = next; + } + }); + + // no longer a mountpoint + node.mounted = null; + + // remove this mount from the child mounts + var idx = node.mount.mounts.indexOf(mount); + assert(idx !== -1); + node.mount.mounts.splice(idx, 1); + },lookup:function (parent, name) { + return parent.node_ops.lookup(parent, name); + },mknod:function (path, mode, dev) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var err = FS.mayCreate(parent, name); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.mknod) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return parent.node_ops.mknod(parent, name, mode, dev); + },create:function (path, mode) { + mode = mode !== undefined ? mode : 438 /* 0666 */; + mode &= 4095; + mode |= 32768; + return FS.mknod(path, mode, 0); + },mkdir:function (path, mode) { + mode = mode !== undefined ? mode : 511 /* 0777 */; + mode &= 511 | 512; + mode |= 16384; + return FS.mknod(path, mode, 0); + },mkdev:function (path, mode, dev) { + if (typeof(dev) === 'undefined') { + dev = mode; + mode = 438 /* 0666 */; + } + mode |= 8192; + return FS.mknod(path, mode, dev); + },symlink:function (oldpath, newpath) { + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + var newname = PATH.basename(newpath); + var err = FS.mayCreate(parent, newname); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.symlink) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return parent.node_ops.symlink(parent, newname, oldpath); + },rename:function (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); + // parents must exist + var lookup, old_dir, new_dir; + try { + lookup = FS.lookupPath(old_path, { parent: true }); + old_dir = lookup.node; + lookup = FS.lookupPath(new_path, { parent: true }); + new_dir = lookup.node; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + // need to be part of the same mount + if (old_dir.mount !== new_dir.mount) { + throw new FS.ErrnoError(ERRNO_CODES.EXDEV); + } + // source must exist + var old_node = FS.lookupNode(old_dir, old_name); + // old path should not be an ancestor of the new path + var relative = PATH.relative(old_path, new_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + // new path should not be an ancestor of the old path + relative = PATH.relative(new_path, old_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + // see if the new path already exists + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + // not fatal + } + // early out if nothing needs to change + if (old_node === new_node) { + return; + } + // we'll need to delete the old entry + var isdir = FS.isDir(old_node.mode); + var err = FS.mayDelete(old_dir, old_name, isdir); + if (err) { + throw new FS.ErrnoError(err); + } + // need delete permissions if we'll be overwriting. + // need create permissions if new doesn't already exist. + err = new_node ? + FS.mayDelete(new_dir, new_name, isdir) : + FS.mayCreate(new_dir, new_name); + if (err) { + throw new FS.ErrnoError(err); + } + if (!old_dir.node_ops.rename) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + // if we are going to change the parent, check write permissions + if (new_dir !== old_dir) { + err = FS.nodePermissions(old_dir, 'w'); + if (err) { + throw new FS.ErrnoError(err); + } + } + // remove the node from the lookup hash + FS.hashRemoveNode(old_node); + // do the underlying fs rename + try { + old_dir.node_ops.rename(old_node, new_dir, new_name); + } catch (e) { + throw e; + } finally { + // add the node back to the hash (in case node_ops.rename + // changed its name) + FS.hashAddNode(old_node); + } + },rmdir:function (path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var err = FS.mayDelete(parent, name, true); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.rmdir) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + parent.node_ops.rmdir(parent, name); + FS.destroyNode(node); + },readdir:function (path) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node.node_ops.readdir) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + return node.node_ops.readdir(node); + },unlink:function (path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var err = FS.mayDelete(parent, name, false); + if (err) { + // POSIX says unlink should set EPERM, not EISDIR + if (err === ERRNO_CODES.EISDIR) err = ERRNO_CODES.EPERM; + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.unlink) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + parent.node_ops.unlink(parent, name); + FS.destroyNode(node); + },readlink:function (path) { + var lookup = FS.lookupPath(path); + var link = lookup.node; + if (!link.node_ops.readlink) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + return link.node_ops.readlink(link); + },stat:function (path, dontFollow) { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var node = lookup.node; + if (!node.node_ops.getattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return node.node_ops.getattr(node); + },lstat:function (path) { + return FS.stat(path, true); + },chmod:function (path, mode, dontFollow) { + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + node.node_ops.setattr(node, { + mode: (mode & 4095) | (node.mode & ~4095), + timestamp: Date.now() + }); + },lchmod:function (path, mode) { + FS.chmod(path, mode, true); + },fchmod:function (fd, mode) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + FS.chmod(stream.node, mode); + },chown:function (path, uid, gid, dontFollow) { + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + node.node_ops.setattr(node, { + timestamp: Date.now() + // we ignore the uid / gid for now + }); + },lchown:function (path, uid, gid) { + FS.chown(path, uid, gid, true); + },fchown:function (fd, uid, gid) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + FS.chown(stream.node, uid, gid); + },truncate:function (path, len) { + if (len < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: true }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!FS.isFile(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var err = FS.nodePermissions(node, 'w'); + if (err) { + throw new FS.ErrnoError(err); + } + node.node_ops.setattr(node, { + size: len, + timestamp: Date.now() + }); + },ftruncate:function (fd, len) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + FS.truncate(stream.node, len); + },utime:function (path, atime, mtime) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + node.node_ops.setattr(node, { + timestamp: Math.max(atime, mtime) + }); + },open:function (path, flags, mode, fd_start, fd_end) { + flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags; + mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode; + if ((flags & 64)) { + mode = (mode & 4095) | 32768; + } else { + mode = 0; + } + var node; + if (typeof path === 'object') { + node = path; + } else { + path = PATH.normalize(path); + try { + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072) + }); + node = lookup.node; + } catch (e) { + // ignore + } + } + // perhaps we need to create the node + if ((flags & 64)) { + if (node) { + // if O_CREAT and O_EXCL are set, error out if the node already exists + if ((flags & 128)) { + throw new FS.ErrnoError(ERRNO_CODES.EEXIST); + } + } else { + // node doesn't exist, try to create it + node = FS.mknod(path, mode, 0); + } + } + if (!node) { + throw new FS.ErrnoError(ERRNO_CODES.ENOENT); + } + // can't truncate a device + if (FS.isChrdev(node.mode)) { + flags &= ~512; + } + // check permissions + var err = FS.mayOpen(node, flags); + if (err) { + throw new FS.ErrnoError(err); + } + // do truncation if necessary + if ((flags & 512)) { + FS.truncate(node, 0); + } + // we've already handled these, don't pass down to the underlying vfs + flags &= ~(128 | 512); + + // register the stream with the filesystem + var stream = FS.createStream({ + node: node, + path: FS.getPath(node), // we want the absolute path to the node + flags: flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + // used by the file family libc calls (fopen, fwrite, ferror, etc.) + ungotten: [], + error: false + }, fd_start, fd_end); + // call the new stream's open function + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + if (Module['logReadFiles'] && !(flags & 1)) { + if (!FS.readFiles) FS.readFiles = {}; + if (!(path in FS.readFiles)) { + FS.readFiles[path] = 1; + Module['printErr']('read file: ' + path); + } + } + return stream; + },close:function (stream) { + try { + if (stream.stream_ops.close) { + stream.stream_ops.close(stream); + } + } catch (e) { + throw e; + } finally { + FS.closeStream(stream.fd); + } + },llseek:function (stream, offset, whence) { + if (!stream.seekable || !stream.stream_ops.llseek) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + return stream.stream_ops.llseek(stream, offset, whence); + },read:function (stream, buffer, offset, length, position) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!stream.stream_ops.read) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var seeking = true; + if (typeof position === 'undefined') { + position = stream.position; + seeking = false; + } else if (!stream.seekable) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); + if (!seeking) stream.position += bytesRead; + return bytesRead; + },write:function (stream, buffer, offset, length, position, canOwn) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!stream.stream_ops.write) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var seeking = true; + if (typeof position === 'undefined') { + position = stream.position; + seeking = false; + } else if (!stream.seekable) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + if (stream.flags & 1024) { + // seek to the end before writing in append mode + FS.llseek(stream, 0, 2); + } + var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); + if (!seeking) stream.position += bytesWritten; + return bytesWritten; + },allocate:function (stream, offset, length) { + if (offset < 0 || length <= 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (!FS.isFile(stream.node.mode) && !FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + if (!stream.stream_ops.allocate) { + throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP); + } + stream.stream_ops.allocate(stream, offset, length); + },mmap:function (stream, buffer, offset, length, position, prot, flags) { + // TODO if PROT is PROT_WRITE, make sure we have write access + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(ERRNO_CODES.EACCES); + } + if (!stream.stream_ops.mmap) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + return stream.stream_ops.mmap(stream, buffer, offset, length, position, prot, flags); + },ioctl:function (stream, cmd, arg) { + if (!stream.stream_ops.ioctl) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTTY); + } + return stream.stream_ops.ioctl(stream, cmd, arg); + },readFile:function (path, opts) { + opts = opts || {}; + opts.flags = opts.flags || 'r'; + opts.encoding = opts.encoding || 'binary'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error('Invalid encoding type "' + opts.encoding + '"'); + } + var ret; + 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') { + ret = ''; + var utf8 = new Runtime.UTF8Processor(); + for (var i = 0; i < length; i++) { + ret += utf8.processCChar(buf[i]); + } + } else if (opts.encoding === 'binary') { + ret = buf; + } + FS.close(stream); + return ret; + },writeFile:function (path, data, opts) { + opts = opts || {}; + opts.flags = opts.flags || 'w'; + opts.encoding = opts.encoding || 'utf8'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error('Invalid encoding type "' + opts.encoding + '"'); + } + var stream = FS.open(path, opts.flags, opts.mode); + if (opts.encoding === 'utf8') { + var utf8 = new Runtime.UTF8Processor(); + var buf = new Uint8Array(utf8.processJSString(data)); + FS.write(stream, buf, 0, buf.length, 0, opts.canOwn); + } else if (opts.encoding === 'binary') { + FS.write(stream, data, 0, data.length, 0, opts.canOwn); + } + FS.close(stream); + },cwd:function () { + return FS.currentPath; + },chdir:function (path) { + var lookup = FS.lookupPath(path, { follow: true }); + if (!FS.isDir(lookup.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + var err = FS.nodePermissions(lookup.node, 'x'); + if (err) { + throw new FS.ErrnoError(err); + } + FS.currentPath = lookup.path; + },createDefaultDirectories:function () { + FS.mkdir('/tmp'); + },createDefaultDevices:function () { + // create /dev + FS.mkdir('/dev'); + // setup /dev/null + FS.registerDevice(FS.makedev(1, 3), { + read: function() { return 0; }, + write: function() { return 0; } + }); + FS.mkdev('/dev/null', FS.makedev(1, 3)); + // setup /dev/tty and /dev/tty1 + // stderr needs to print output using Module['printErr'] + // so we register a second tty just for it. + 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)); + // we're not going to emulate the actual shm device, + // just create the tmp dirs that reside in it commonly + FS.mkdir('/dev/shm'); + FS.mkdir('/dev/shm/tmp'); + },createStandardStreams:function () { + // TODO deprecate the old functionality of a single + // input / output callback and that utilizes FS.createDevice + // and instead require a unique set of stream ops + + // by default, we symlink the standard streams to the + // default tty devices. however, if the standard streams + // have been overwritten we create a unique device for + // them instead. + if (Module['stdin']) { + FS.createDevice('/dev', 'stdin', Module['stdin']); + } else { + FS.symlink('/dev/tty', '/dev/stdin'); + } + if (Module['stdout']) { + FS.createDevice('/dev', 'stdout', null, Module['stdout']); + } else { + FS.symlink('/dev/tty', '/dev/stdout'); + } + if (Module['stderr']) { + FS.createDevice('/dev', 'stderr', null, Module['stderr']); + } else { + FS.symlink('/dev/tty1', '/dev/stderr'); + } + + // open default streams for the stdin, stdout and stderr devices + var stdin = FS.open('/dev/stdin', 'r'); + HEAP32[((_stdin)>>2)]=FS.getPtrForStream(stdin); + assert(stdin.fd === 0, 'invalid handle for stdin (' + stdin.fd + ')'); + + var stdout = FS.open('/dev/stdout', 'w'); + HEAP32[((_stdout)>>2)]=FS.getPtrForStream(stdout); + assert(stdout.fd === 1, 'invalid handle for stdout (' + stdout.fd + ')'); + + var stderr = FS.open('/dev/stderr', 'w'); + HEAP32[((_stderr)>>2)]=FS.getPtrForStream(stderr); + assert(stderr.fd === 2, 'invalid handle for stderr (' + stderr.fd + ')'); + },ensureErrnoError:function () { + if (FS.ErrnoError) return; + FS.ErrnoError = function ErrnoError(errno) { + this.errno = errno; + for (var key in ERRNO_CODES) { + if (ERRNO_CODES[key] === errno) { + this.code = key; + break; + } + } + this.message = ERRNO_MESSAGES[errno]; + }; + FS.ErrnoError.prototype = new Error(); + FS.ErrnoError.prototype.constructor = FS.ErrnoError; + // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info) + [ERRNO_CODES.ENOENT].forEach(function(code) { + FS.genericErrors[code] = new FS.ErrnoError(code); + FS.genericErrors[code].stack = ''; + }); + },staticInit:function () { + FS.ensureErrnoError(); + + FS.nameTable = new Array(4096); + + FS.mount(MEMFS, {}, '/'); + + FS.createDefaultDirectories(); + FS.createDefaultDevices(); + },init:function (input, output, error) { + assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); + FS.init.initialized = true; + + FS.ensureErrnoError(); + + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + Module['stdin'] = input || Module['stdin']; + Module['stdout'] = output || Module['stdout']; + Module['stderr'] = error || Module['stderr']; + + FS.createStandardStreams(); + },quit:function () { + FS.init.initialized = false; + for (var i = 0; i < FS.streams.length; i++) { + var stream = FS.streams[i]; + if (!stream) { + continue; + } + FS.close(stream); + } + },getMode:function (canRead, canWrite) { + var mode = 0; + if (canRead) mode |= 292 | 73; + if (canWrite) mode |= 146; + return mode; + },joinPath:function (parts, forceRelative) { + var path = PATH.join.apply(null, parts); + if (forceRelative && path[0] == '/') path = path.substr(1); + return path; + },absolutePath:function (relative, base) { + return PATH.resolve(base, relative); + },standardizePath:function (path) { + return PATH.normalize(path); + },findObject:function (path, dontResolveLastLink) { + var ret = FS.analyzePath(path, dontResolveLastLink); + if (ret.exists) { + return ret.object; + } else { + ___setErrNo(ret.error); + return null; + } + },analyzePath:function (path, dontResolveLastLink) { + // operate from within the context of the symlink's target + 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; + },createFolder:function (parent, name, canRead, canWrite) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var mode = FS.getMode(canRead, canWrite); + return FS.mkdir(path, mode); + },createPath:function (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) { + // ignore EEXIST + } + parent = current; + } + return current; + },createFile:function (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:function (parent, name, data, canRead, canWrite, canOwn) { + var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(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; i < len; ++i) arr[i] = data.charCodeAt(i); + data = arr; + } + // make sure we can write to the file + FS.chmod(node, mode | 146); + var stream = FS.open(node, 'w'); + FS.write(stream, data, 0, data.length, 0, canOwn); + FS.close(stream); + FS.chmod(node, mode); + } + return node; + },createDevice:function (parent, name, input, output) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var mode = FS.getMode(!!input, !!output); + if (!FS.createDevice.major) FS.createDevice.major = 64; + var dev = FS.makedev(FS.createDevice.major++, 0); + // Create a fake device that a set of stream ops to emulate + // the old behavior. + FS.registerDevice(dev, { + open: function(stream) { + stream.seekable = false; + }, + close: function(stream) { + // flush any pending line data + if (output && output.buffer && output.buffer.length) { + output(10); + } + }, + read: function(stream, buffer, offset, length, pos /* ignored */) { + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = input(); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + }, + write: function(stream, buffer, offset, length, pos) { + for (var i = 0; i < length; i++) { + try { + output(buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + } + }); + return FS.mkdev(path, mode, dev); + },createLink:function (parent, name, target, canRead, canWrite) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + return FS.symlink(target, path); + },forceLoadFile:function (obj) { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + var success = true; + if (typeof XMLHttpRequest !== 'undefined') { + throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else if (Module['read']) { + // Command-line. + try { + // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as + // read() will try to parse UTF8. + obj.contents = intArrayFromString(Module['read'](obj.url), true); + } catch (e) { + success = false; + } + } else { + throw new Error('Cannot load without read() or XMLHttpRequest.'); + } + if (!success) ___setErrNo(ERRNO_CODES.EIO); + return success; + },createLazyFile:function (parent, name, url, canRead, canWrite) { + // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. + function LazyUint8Array() { + this.lengthKnown = false; + this.chunks = []; // Loaded chunks. Index is the chunk number + } + LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = Math.floor(idx / this.chunkSize); + return this.getter(chunkNum)[chunkOffset]; + } + LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) { + this.getter = getter; + } + LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("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 chunkSize = 1024*1024; // Chunk size in bytes + + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (function(from, to) { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + if (typeof Uint8Array != 'undefined') 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)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(xhr.response || []); + } else { + return intArrayFromString(xhr.responseText || '', true); + } + }); + var lazyArray = this; + lazyArray.setDataGetter(function(chunkNum) { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); + return lazyArray.chunks[chunkNum]; + }); + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } + if (typeof XMLHttpRequest !== 'undefined') { + if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; + var lazyArray = new LazyUint8Array(); + Object.defineProperty(lazyArray, "length", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + }); + Object.defineProperty(lazyArray, "chunkSize", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + }); + + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + + var node = FS.createFile(parent, name, properties, canRead, canWrite); + // This is a total hack, but I want to get this lazy file code out of the + // core of MEMFS. If we want to keep this lazy file concept I feel it should + // be its own thin LAZYFS proxying calls to MEMFS. + if (properties.contents) { + node.contents = properties.contents; + } else if (properties.url) { + node.contents = null; + node.url = properties.url; + } + // override each stream op with one that tries to force load the lazy file first + var stream_ops = {}; + var keys = Object.keys(node.stream_ops); + keys.forEach(function(key) { + var fn = node.stream_ops[key]; + stream_ops[key] = function forceLoadLazyFile() { + if (!FS.forceLoadFile(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + return fn.apply(null, arguments); + }; + }); + // use a custom read function + stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) { + if (!FS.forceLoadFile(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (contents.slice) { // normal array + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } else { + for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR + buffer[offset + i] = contents.get(position + i); + } + } + return size; + }; + node.stream_ops = stream_ops; + return node; + },createPreloadedFile:function (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn) { + Browser.init(); + // TODO we should allow people to just pass in a complete filename instead + // of parent and name being that we just join them anyways + var fullname = name ? PATH.resolve(PATH.join2(parent, name)) : parent; + function processData(byteArray) { + function finish(byteArray) { + if (!dontCreateFile) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + } + if (onload) onload(); + removeRunDependency('cp ' + fullname); + } + var handled = false; + Module['preloadPlugins'].forEach(function(plugin) { + if (handled) return; + if (plugin['canHandle'](fullname)) { + plugin['handle'](byteArray, fullname, finish, function() { + if (onerror) onerror(); + removeRunDependency('cp ' + fullname); + }); + handled = true; + } + }); + if (!handled) finish(byteArray); + } + addRunDependency('cp ' + fullname); + if (typeof url == 'string') { + Browser.asyncLoad(url, function(byteArray) { + processData(byteArray); + }, onerror); + } else { + processData(url); + } + },indexedDB:function () { + return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + },DB_NAME:function () { + return 'EM_FS_' + window.location.pathname; + },DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function (paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = function openRequest_onupgradeneeded() { + console.log('creating db'); + var db = openRequest.result; + db.createObjectStore(FS.DB_STORE_NAME); + }; + openRequest.onsuccess = function openRequest_onsuccess() { + var db = openRequest.result; + var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite'); + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var putRequest = files.put(FS.analyzePath(path).object.contents, path); + putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) finish() }; + putRequest.onerror = function putRequest_onerror() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + },loadFilesFromDB:function (paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = onerror; // no database to load from + openRequest.onsuccess = function openRequest_onsuccess() { + var db = openRequest.result; + try { + var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly'); + } catch(e) { + onerror(e); + return; + } + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var getRequest = files.get(path); + getRequest.onsuccess = function getRequest_onsuccess() { + if (FS.analyzePath(path).exists) { + FS.unlink(path); + } + FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true); + ok++; + if (ok + fail == total) finish(); + }; + getRequest.onerror = function getRequest_onerror() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + }};function _lseek(fildes, offset, whence) { + // off_t lseek(int fildes, off_t offset, int whence); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/lseek.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + return FS.llseek(stream, offset, whence); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + + Module["_i64Subtract"] = _i64Subtract; + + var _fabsf=Math_abs; + + + + + Module["_strlen"] = _strlen; + + function __reallyNegative(x) { + return x < 0 || (x === 0 && (1/x) === -Infinity); + }function __formatString(format, varargs) { + var textIndex = format; + var argIndex = 0; + function getNextArg(type) { + // NOTE: Explicitly ignoring type safety. Otherwise this fails: + // int x = 4; printf("%c\n", (char)x); + var ret; + if (type === 'double') { + ret = (HEAP32[((tempDoublePtr)>>2)]=HEAP32[(((varargs)+(argIndex))>>2)],HEAP32[(((tempDoublePtr)+(4))>>2)]=HEAP32[(((varargs)+((argIndex)+(4)))>>2)],(+(HEAPF64[(tempDoublePtr)>>3]))); + } else if (type == 'i64') { + ret = [HEAP32[(((varargs)+(argIndex))>>2)], + HEAP32[(((varargs)+(argIndex+4))>>2)]]; + + } else { + type = 'i32'; // varargs are always i32, i64, or double + ret = HEAP32[(((varargs)+(argIndex))>>2)]; + } + argIndex += Runtime.getNativeFieldSize(type); + return ret; + } + + var ret = []; + var curr, next, currArg; + while(1) { + var startTextIndex = textIndex; + curr = HEAP8[(textIndex)]; + if (curr === 0) break; + next = HEAP8[((textIndex+1)|0)]; + if (curr == 37) { + // Handle flags. + var flagAlwaysSigned = false; + var flagLeftAlign = false; + var flagAlternative = false; + var flagZeroPad = false; + var flagPadSign = false; + flagsLoop: while (1) { + switch (next) { + case 43: + flagAlwaysSigned = true; + break; + case 45: + flagLeftAlign = true; + break; + case 35: + flagAlternative = true; + break; + case 48: + if (flagZeroPad) { + break flagsLoop; + } else { + flagZeroPad = true; + break; + } + case 32: + flagPadSign = true; + break; + default: + break flagsLoop; + } + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } + + // Handle width. + var width = 0; + if (next == 42) { + width = getNextArg('i32'); + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } else { + while (next >= 48 && next <= 57) { + width = width * 10 + (next - 48); + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } + } + + // Handle precision. + var precisionSet = false, precision = -1; + if (next == 46) { + precision = 0; + precisionSet = true; + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + if (next == 42) { + precision = getNextArg('i32'); + textIndex++; + } else { + while(1) { + var precisionChr = HEAP8[((textIndex+1)|0)]; + if (precisionChr < 48 || + precisionChr > 57) break; + precision = precision * 10 + (precisionChr - 48); + textIndex++; + } + } + next = HEAP8[((textIndex+1)|0)]; + } + if (precision < 0) { + precision = 6; // Standard default. + precisionSet = false; + } + + // Handle integer sizes. WARNING: These assume a 32-bit architecture! + var argSize; + switch (String.fromCharCode(next)) { + case 'h': + var nextNext = HEAP8[((textIndex+2)|0)]; + if (nextNext == 104) { + textIndex++; + argSize = 1; // char (actually i32 in varargs) + } else { + argSize = 2; // short (actually i32 in varargs) + } + break; + case 'l': + var nextNext = HEAP8[((textIndex+2)|0)]; + if (nextNext == 108) { + textIndex++; + argSize = 8; // long long + } else { + argSize = 4; // long + } + break; + case 'L': // long long + case 'q': // int64_t + case 'j': // intmax_t + argSize = 8; + break; + case 'z': // size_t + case 't': // ptrdiff_t + case 'I': // signed ptrdiff_t or unsigned size_t + argSize = 4; + break; + default: + argSize = null; + } + if (argSize) textIndex++; + next = HEAP8[((textIndex+1)|0)]; + + // Handle type specifier. + switch (String.fromCharCode(next)) { + case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': case 'p': { + // Integer. + var signed = next == 100 || next == 105; + argSize = argSize || 4; + var currArg = getNextArg('i' + (argSize * 8)); + var origArg = currArg; + var argText; + // Flatten i64-1 [low, high] into a (slightly rounded) double + if (argSize == 8) { + currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == 117); + } + // Truncate to requested size. + if (argSize <= 4) { + var limit = Math.pow(256, argSize) - 1; + currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8); + } + // Format the number. + var currAbsArg = Math.abs(currArg); + var prefix = ''; + if (next == 100 || next == 105) { + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else + argText = reSign(currArg, 8 * argSize, 1).toString(10); + } else if (next == 117) { + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else + argText = unSign(currArg, 8 * argSize, 1).toString(10); + currArg = Math.abs(currArg); + } else if (next == 111) { + argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8); + } else if (next == 120 || next == 88) { + prefix = (flagAlternative && currArg != 0) ? '0x' : ''; + if (argSize == 8 && i64Math) { + if (origArg[1]) { + argText = (origArg[1]>>>0).toString(16); + var lower = (origArg[0]>>>0).toString(16); + while (lower.length < 8) lower = '0' + lower; + argText += lower; + } else { + argText = (origArg[0]>>>0).toString(16); + } + } else + if (currArg < 0) { + // Represent negative numbers in hex as 2's complement. + currArg = -currArg; + argText = (currAbsArg - 1).toString(16); + var buffer = []; + for (var i = 0; i < argText.length; i++) { + buffer.push((0xF - parseInt(argText[i], 16)).toString(16)); + } + argText = buffer.join(''); + while (argText.length < argSize * 2) argText = 'f' + argText; + } else { + argText = currAbsArg.toString(16); + } + if (next == 88) { + prefix = prefix.toUpperCase(); + argText = argText.toUpperCase(); + } + } else if (next == 112) { + if (currAbsArg === 0) { + argText = '(nil)'; + } else { + prefix = '0x'; + argText = currAbsArg.toString(16); + } + } + if (precisionSet) { + while (argText.length < precision) { + argText = '0' + argText; + } + } + + // Add sign if needed + if (currArg >= 0) { + if (flagAlwaysSigned) { + prefix = '+' + prefix; + } else if (flagPadSign) { + prefix = ' ' + prefix; + } + } + + // Move sign to prefix so we zero-pad after the sign + if (argText.charAt(0) == '-') { + prefix = '-' + prefix; + argText = argText.substr(1); + } + + // Add padding. + while (prefix.length + argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad) { + argText = '0' + argText; + } else { + prefix = ' ' + prefix; + } + } + } + + // Insert the result into the buffer. + argText = prefix + argText; + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; + } + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': { + // Float. + var currArg = getNextArg('double'); + var argText; + if (isNaN(currArg)) { + argText = 'nan'; + flagZeroPad = false; + } else if (!isFinite(currArg)) { + argText = (currArg < 0 ? '-' : '') + 'inf'; + flagZeroPad = false; + } else { + var isGeneral = false; + var effectivePrecision = Math.min(precision, 20); + + // Convert g/G to f/F or e/E, as per: + // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html + if (next == 103 || next == 71) { + isGeneral = true; + precision = precision || 1; + var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10); + if (precision > exponent && exponent >= -4) { + next = ((next == 103) ? 'f' : 'F').charCodeAt(0); + precision -= exponent + 1; + } else { + next = ((next == 103) ? 'e' : 'E').charCodeAt(0); + precision--; + } + effectivePrecision = Math.min(precision, 20); + } + + if (next == 101 || next == 69) { + argText = currArg.toExponential(effectivePrecision); + // Make sure the exponent has at least 2 digits. + if (/[eE][-+]\d$/.test(argText)) { + argText = argText.slice(0, -1) + '0' + argText.slice(-1); + } + } else if (next == 102 || next == 70) { + argText = currArg.toFixed(effectivePrecision); + if (currArg === 0 && __reallyNegative(currArg)) { + argText = '-' + argText; + } + } + + var parts = argText.split('e'); + if (isGeneral && !flagAlternative) { + // Discard trailing zeros and periods. + while (parts[0].length > 1 && parts[0].indexOf('.') != -1 && + (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) { + parts[0] = parts[0].slice(0, -1); + } + } else { + // Make sure we have a period in alternative mode. + if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.'; + // Zero pad until required precision. + while (precision > effectivePrecision++) parts[0] += '0'; + } + argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : ''); + + // Capitalize 'E' if needed. + if (next == 69) argText = argText.toUpperCase(); + + // Add sign. + if (currArg >= 0) { + if (flagAlwaysSigned) { + argText = '+' + argText; + } else if (flagPadSign) { + argText = ' ' + argText; + } + } + } + + // Add padding. + while (argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) { + argText = argText[0] + '0' + argText.slice(1); + } else { + argText = (flagZeroPad ? '0' : ' ') + argText; + } + } + } + + // Adjust case. + if (next < 97) argText = argText.toUpperCase(); + + // Insert the result into the buffer. + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; + } + case 's': { + // String. + var arg = getNextArg('i8*'); + var argLength = arg ? _strlen(arg) : '(null)'.length; + if (precisionSet) argLength = Math.min(argLength, precision); + if (!flagLeftAlign) { + while (argLength < width--) { + ret.push(32); + } + } + if (arg) { + for (var i = 0; i < argLength; i++) { + ret.push(HEAPU8[((arg++)|0)]); + } + } else { + ret = ret.concat(intArrayFromString('(null)'.substr(0, argLength), true)); + } + if (flagLeftAlign) { + while (argLength < width--) { + ret.push(32); + } + } + break; + } + case 'c': { + // Character. + if (flagLeftAlign) ret.push(getNextArg('i8')); + while (--width > 0) { + ret.push(32); + } + if (!flagLeftAlign) ret.push(getNextArg('i8')); + break; + } + case 'n': { + // Write the length written so far to the next parameter. + var ptr = getNextArg('i32*'); + HEAP32[((ptr)>>2)]=ret.length; + break; + } + case '%': { + // Literal percent sign. + ret.push(curr); + break; + } + default: { + // Unknown specifiers remain untouched. + for (var i = startTextIndex; i < textIndex + 2; i++) { + ret.push(HEAP8[(i)]); + } + } + } + textIndex += 2; + // TODO: Support a/A (hex float) and m (last error) specifiers. + // TODO: Support %1${specifier} for arg selection. + } else { + ret.push(curr); + textIndex += 1; + } + } + return ret; + } + + function _malloc(bytes) { + /* Over-allocate to make sure it is byte-aligned by 8. + * This will leak memory, but this is only the dummy + * implementation (replaced by dlmalloc normally) so + * not an issue. + */ + var ptr = Runtime.dynamicAlloc(bytes + 8); + return (ptr+8) & 0xFFFFFFF8; + } + Module["_malloc"] = _malloc;function _snprintf(s, n, format, varargs) { + // int snprintf(char *restrict s, size_t n, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var result = __formatString(format, varargs); + var limit = (n === undefined) ? result.length + : Math.min(result.length, Math.max(n - 1, 0)); + if (s < 0) { + s = -s; + var buf = _malloc(limit+1); + HEAP32[((s)>>2)]=buf; + s = buf; + } + for (var i = 0; i < limit; i++) { + HEAP8[(((s)+(i))|0)]=result[i]; + } + if (limit < n || (n === undefined)) HEAP8[(((s)+(i))|0)]=0; + return result.length; + } + + + Module["_memset"] = _memset; + + + Module["_strcat"] = _strcat; + + + function _strerror_r(errnum, strerrbuf, buflen) { + if (errnum in ERRNO_MESSAGES) { + if (ERRNO_MESSAGES[errnum].length > buflen - 1) { + return ___setErrNo(ERRNO_CODES.ERANGE); + } else { + var msg = ERRNO_MESSAGES[errnum]; + writeAsciiToMemory(msg, strerrbuf); + return 0; + } + } else { + return ___setErrNo(ERRNO_CODES.EINVAL); + } + }function _strerror(errnum) { + if (!_strerror.buffer) _strerror.buffer = _malloc(256); + _strerror_r(errnum, _strerror.buffer, 256); + return _strerror.buffer; + } + + + Module["_bitshift64Shl"] = _bitshift64Shl; + + function _abort() { + Module['abort'](); + } + + + + + + + function _mkport() { throw 'TODO' }var SOCKFS={mount:function (mount) { + return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + },createSocket:function (family, type, protocol) { + var streaming = type == 1; + if (protocol) { + assert(streaming == (protocol == 6)); // if SOCK_STREAM, must be tcp + } + + // create our internal socket structure + var sock = { + family: family, + type: type, + protocol: protocol, + server: null, + peers: {}, + pending: [], + recv_queue: [], + sock_ops: SOCKFS.websocket_sock_ops + }; + + // create the filesystem node to store the socket structure + var name = SOCKFS.nextname(); + var node = FS.createNode(SOCKFS.root, name, 49152, 0); + node.sock = sock; + + // and the wrapping stream that enables library functions such + // as read and write to indirectly interact with the socket + var stream = FS.createStream({ + path: name, + node: node, + flags: FS.modeStringToFlags('r+'), + seekable: false, + stream_ops: SOCKFS.stream_ops + }); + + // map the new stream to the socket structure (sockets have a 1:1 + // relationship with a stream) + sock.stream = stream; + + return sock; + },getSocket:function (fd) { + var stream = FS.getStream(fd); + if (!stream || !FS.isSocket(stream.node.mode)) { + return null; + } + return stream.node.sock; + },stream_ops:{poll:function (stream) { + var sock = stream.node.sock; + return sock.sock_ops.poll(sock); + },ioctl:function (stream, request, varargs) { + var sock = stream.node.sock; + return sock.sock_ops.ioctl(sock, request, varargs); + },read:function (stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + var msg = sock.sock_ops.recvmsg(sock, length); + if (!msg) { + // socket is closed + return 0; + } + buffer.set(msg.buffer, offset); + return msg.buffer.length; + },write:function (stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + return sock.sock_ops.sendmsg(sock, buffer, offset, length); + },close:function (stream) { + var sock = stream.node.sock; + sock.sock_ops.close(sock); + }},nextname:function () { + if (!SOCKFS.nextname.current) { + SOCKFS.nextname.current = 0; + } + return 'socket[' + (SOCKFS.nextname.current++) + ']'; + },websocket_sock_ops:{createPeer:function (sock, addr, port) { + var ws; + + if (typeof addr === 'object') { + ws = addr; + addr = null; + port = null; + } + + if (ws) { + // for sockets that've already connected (e.g. we're the server) + // we can inspect the _socket property for the address + if (ws._socket) { + addr = ws._socket.remoteAddress; + port = ws._socket.remotePort; + } + // if we're just now initializing a connection to the remote, + // inspect the url property + else { + var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url); + if (!result) { + throw new Error('WebSocket URL must be in the format ws(s)://address:port'); + } + addr = result[1]; + port = parseInt(result[2], 10); + } + } else { + // create the actual websocket object and connect + try { + // runtimeConfig gets set to true if WebSocket runtime configuration is available. + var runtimeConfig = (Module['websocket'] && ('object' === typeof Module['websocket'])); + + // The default value is 'ws://' the replace is needed because the compiler replaces "//" comments with '#' + // comments without checking context, so we'd end up with ws:#, the replace swaps the "#" for "//" again. + var url = 'ws:#'.replace('#', '//'); + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['url']) { + url = Module['websocket']['url']; // Fetch runtime WebSocket URL config. + } + } + + if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it. + url = url + addr + ':' + port; + } + + // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set. + var subProtocols = 'binary'; // The default value is 'binary' + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['subprotocol']) { + subProtocols = Module['websocket']['subprotocol']; // Fetch runtime WebSocket subprotocol config. + } + } + + // The regex trims the string (removes spaces at the beginning and end, then splits the string by + // , into an Array. Whitespace removal is important for Websockify and ws. + subProtocols = subProtocols.replace(/^ +| +$/g,"").split(/ *, */); + + // The node ws library API for specifying optional subprotocol is slightly different than the browser's. + var opts = ENVIRONMENT_IS_NODE ? {'protocol': subProtocols.toString()} : subProtocols; + + // If node we use the ws library. + var WebSocket = ENVIRONMENT_IS_NODE ? require('ws') : window['WebSocket']; + ws = new WebSocket(url, opts); + ws.binaryType = 'arraybuffer'; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EHOSTUNREACH); + } + } + + + var peer = { + addr: addr, + port: port, + socket: ws, + dgram_send_queue: [] + }; + + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer); + + // if this is a bound dgram socket, send the port number first to allow + // us to override the ephemeral port reported to us by remotePort on the + // remote end. + if (sock.type === 2 && typeof sock.sport !== 'undefined') { + peer.dgram_send_queue.push(new Uint8Array([ + 255, 255, 255, 255, + 'p'.charCodeAt(0), 'o'.charCodeAt(0), 'r'.charCodeAt(0), 't'.charCodeAt(0), + ((sock.sport & 0xff00) >> 8) , (sock.sport & 0xff) + ])); + } + + return peer; + },getPeer:function (sock, addr, port) { + return sock.peers[addr + ':' + port]; + },addPeer:function (sock, peer) { + sock.peers[peer.addr + ':' + peer.port] = peer; + },removePeer:function (sock, peer) { + delete sock.peers[peer.addr + ':' + peer.port]; + },handlePeerEvents:function (sock, peer) { + var first = true; + + var handleOpen = function () { + try { + var queued = peer.dgram_send_queue.shift(); + while (queued) { + peer.socket.send(queued); + queued = peer.dgram_send_queue.shift(); + } + } catch (e) { + // not much we can do here in the way of proper error handling as we've already + // lied and said this data was sent. shut it down. + peer.socket.close(); + } + }; + + function handleMessage(data) { + assert(typeof data !== 'string' && data.byteLength !== undefined); // must receive an ArrayBuffer + data = new Uint8Array(data); // make a typed array view on the array buffer + + + // if this is the port message, override the peer's port with it + var wasfirst = first; + first = false; + if (wasfirst && + data.length === 10 && + data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 && + data[4] === 'p'.charCodeAt(0) && data[5] === 'o'.charCodeAt(0) && data[6] === 'r'.charCodeAt(0) && data[7] === 't'.charCodeAt(0)) { + // update the peer's port and it's key in the peer map + var newport = ((data[8] << 8) | data[9]); + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + peer.port = newport; + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + return; + } + + sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data }); + }; + + if (ENVIRONMENT_IS_NODE) { + peer.socket.on('open', handleOpen); + peer.socket.on('message', function(data, flags) { + if (!flags.binary) { + return; + } + handleMessage((new Uint8Array(data)).buffer); // copy from node Buffer -> ArrayBuffer + }); + peer.socket.on('error', function() { + // don't throw + }); + } else { + peer.socket.onopen = handleOpen; + peer.socket.onmessage = function peer_socket_onmessage(event) { + handleMessage(event.data); + }; + } + },poll:function (sock) { + if (sock.type === 1 && sock.server) { + // listen sockets should only say they're available for reading + // if there are pending clients. + return sock.pending.length ? (64 | 1) : 0; + } + + var mask = 0; + var dest = sock.type === 1 ? // we only care about the socket state for connection-based sockets + SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) : + null; + + if (sock.recv_queue.length || + !dest || // connection-less sockets are always ready to read + (dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { // let recv return 0 once closed + mask |= (64 | 1); + } + + if (!dest || // connection-less sockets are always ready to write + (dest && dest.socket.readyState === dest.socket.OPEN)) { + mask |= 4; + } + + if ((dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { + mask |= 16; + } + + return mask; + },ioctl:function (sock, request, arg) { + switch (request) { + case 21531: + var bytes = 0; + if (sock.recv_queue.length) { + bytes = sock.recv_queue[0].data.length; + } + HEAP32[((arg)>>2)]=bytes; + return 0; + default: + return ERRNO_CODES.EINVAL; + } + },close:function (sock) { + // if we've spawned a listen server, close it + if (sock.server) { + try { + sock.server.close(); + } catch (e) { + } + sock.server = null; + } + // close any peer connections + var peers = Object.keys(sock.peers); + for (var i = 0; i < peers.length; i++) { + var peer = sock.peers[peers[i]]; + try { + peer.socket.close(); + } catch (e) { + } + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + } + return 0; + },bind:function (sock, addr, port) { + if (typeof sock.saddr !== 'undefined' || typeof sock.sport !== 'undefined') { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); // already bound + } + sock.saddr = addr; + sock.sport = port || _mkport(); + // in order to emulate dgram sockets, we need to launch a listen server when + // binding on a connection-less socket + // note: this is only required on the server side + if (sock.type === 2) { + // close the existing server if it exists + if (sock.server) { + sock.server.close(); + sock.server = null; + } + // swallow error operation not supported error that occurs when binding in the + // browser where this isn't supported + try { + sock.sock_ops.listen(sock, 0); + } catch (e) { + if (!(e instanceof FS.ErrnoError)) throw e; + if (e.errno !== ERRNO_CODES.EOPNOTSUPP) throw e; + } + } + },connect:function (sock, addr, port) { + if (sock.server) { + throw new FS.ErrnoError(ERRNO_CODS.EOPNOTSUPP); + } + + // TODO autobind + // if (!sock.addr && sock.type == 2) { + // } + + // early out if we're already connected / in the middle of connecting + if (typeof sock.daddr !== 'undefined' && typeof sock.dport !== 'undefined') { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + if (dest) { + if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(ERRNO_CODES.EALREADY); + } else { + throw new FS.ErrnoError(ERRNO_CODES.EISCONN); + } + } + } + + // add the socket to our peer list and set our + // destination address / port to match + var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + sock.daddr = peer.addr; + sock.dport = peer.port; + + // always "fail" in non-blocking mode + throw new FS.ErrnoError(ERRNO_CODES.EINPROGRESS); + },listen:function (sock, backlog) { + if (!ENVIRONMENT_IS_NODE) { + throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP); + } + if (sock.server) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); // already listening + } + var WebSocketServer = require('ws').Server; + var host = sock.saddr; + sock.server = new WebSocketServer({ + host: host, + port: sock.sport + // TODO support backlog + }); + + sock.server.on('connection', function(ws) { + if (sock.type === 1) { + var newsock = SOCKFS.createSocket(sock.family, sock.type, sock.protocol); + + // create a peer on the new socket + var peer = SOCKFS.websocket_sock_ops.createPeer(newsock, ws); + newsock.daddr = peer.addr; + newsock.dport = peer.port; + + // push to queue for accept to pick up + sock.pending.push(newsock); + } else { + // create a peer on the listen socket so calling sendto + // with the listen socket and an address will resolve + // to the correct client + SOCKFS.websocket_sock_ops.createPeer(sock, ws); + } + }); + sock.server.on('closed', function() { + sock.server = null; + }); + sock.server.on('error', function() { + // don't throw + }); + },accept:function (listensock) { + if (!listensock.server) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var newsock = listensock.pending.shift(); + newsock.stream.flags = listensock.stream.flags; + return newsock; + },getname:function (sock, peer) { + var addr, port; + if (peer) { + if (sock.daddr === undefined || sock.dport === undefined) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + addr = sock.daddr; + port = sock.dport; + } else { + // TODO saddr and sport will be set for bind()'d UDP sockets, but what + // should we be returning for TCP sockets that've been connect()'d? + addr = sock.saddr || 0; + port = sock.sport || 0; + } + return { addr: addr, port: port }; + },sendmsg:function (sock, buffer, offset, length, addr, port) { + if (sock.type === 2) { + // connection-less sockets will honor the message address, + // and otherwise fall back to the bound destination address + if (addr === undefined || port === undefined) { + addr = sock.daddr; + port = sock.dport; + } + // if there was no address to fall back to, error out + if (addr === undefined || port === undefined) { + throw new FS.ErrnoError(ERRNO_CODES.EDESTADDRREQ); + } + } else { + // connection-based sockets will only use the bound + addr = sock.daddr; + port = sock.dport; + } + + // find the peer for the destination address + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port); + + // early out if not connected with a connection-based socket + if (sock.type === 1) { + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } else if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } + + // create a copy of the incoming data to send, as the WebSocket API + // doesn't work entirely with an ArrayBufferView, it'll just send + // the entire underlying buffer + var data; + if (buffer instanceof Array || buffer instanceof ArrayBuffer) { + data = buffer.slice(offset, offset + length); + } else { // ArrayBufferView + data = buffer.buffer.slice(buffer.byteOffset + offset, buffer.byteOffset + offset + length); + } + + // if we're emulating a connection-less dgram socket and don't have + // a cached connection, queue the buffer to send upon connect and + // lie, saying the data was sent now. + if (sock.type === 2) { + if (!dest || dest.socket.readyState !== dest.socket.OPEN) { + // if we're not connected, open a new connection + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + } + dest.dgram_send_queue.push(data); + return length; + } + } + + try { + // send the actual data + dest.socket.send(data); + return length; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + },recvmsg:function (sock, length) { + // http://pubs.opengroup.org/onlinepubs/7908799/xns/recvmsg.html + if (sock.type === 1 && sock.server) { + // tcp servers should not be recv()'ing on the listen socket + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + + var queued = sock.recv_queue.shift(); + if (!queued) { + if (sock.type === 1) { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + + if (!dest) { + // if we have a destination address but are not connected, error out + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + else if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + // return null if the socket has closed + return null; + } + else { + // else, our socket is in a valid state but truly has nothing available + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } else { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } + + // queued.data will be an ArrayBuffer if it's unadulterated, but if it's + // requeued TCP data it'll be an ArrayBufferView + var queuedLength = queued.data.byteLength || queued.data.length; + var queuedOffset = queued.data.byteOffset || 0; + var queuedBuffer = queued.data.buffer || queued.data; + var bytesRead = Math.min(length, queuedLength); + var res = { + buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead), + addr: queued.addr, + port: queued.port + }; + + + // push back any unread data for TCP connections + if (sock.type === 1 && bytesRead < queuedLength) { + var bytesRemaining = queuedLength - bytesRead; + queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining); + sock.recv_queue.unshift(queued); + } + + return res; + }}};function _send(fd, buf, len, flags) { + var sock = SOCKFS.getSocket(fd); + if (!sock) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + // TODO honor flags + return _write(fd, buf, len); + } + + function _pwrite(fildes, buf, nbyte, offset) { + // ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + var slab = HEAP8; + return FS.write(stream, slab, buf, nbyte, offset); + } catch (e) { + FS.handleFSError(e); + return -1; + } + }function _write(fildes, buf, nbyte) { + // ssize_t write(int fildes, const void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + + + try { + var slab = HEAP8; + return FS.write(stream, slab, buf, nbyte); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + function _fileno(stream) { + // int fileno(FILE *stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fileno.html + stream = FS.getStreamFromPtr(stream); + if (!stream) return -1; + return stream.fd; + }function _fwrite(ptr, size, nitems, stream) { + // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fwrite.html + var bytesToWrite = nitems * size; + if (bytesToWrite == 0) return 0; + var fd = _fileno(stream); + var bytesWritten = _write(fd, ptr, bytesToWrite); + if (bytesWritten == -1) { + var streamObj = FS.getStreamFromPtr(stream); + if (streamObj) streamObj.error = true; + return 0; + } else { + return Math.floor(bytesWritten / size); + } + }function _fprintf(stream, format, varargs) { + // int fprintf(FILE *restrict stream, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var result = __formatString(format, varargs); + var stack = Runtime.stackSave(); + var ret = _fwrite(allocate(result, 'i8', ALLOC_STACK), 1, result.length, stream); + Runtime.stackRestore(stack); + return ret; + } + + function _toupper(chr) { + if (chr >= 97 && chr <= 122) { + return chr - 97 + 65; + } else { + return chr; + } + } + + function _printf(format, varargs) { + // int printf(const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var stdout = HEAP32[((_stdout)>>2)]; + return _fprintf(stdout, format, varargs); + } + + function _isdigit(chr) { + return chr >= 48 && chr <= 57; + } + + function _close(fildes) { + // int close(int fildes); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/close.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + FS.close(stream); + return 0; + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + var _tan=Math_tan; + + + + Module["_strncpy"] = _strncpy; + + var _asin=Math_asin; + + + Module["_i64Add"] = _i64Add; + + var _fabs=Math_abs; + + function _open(path, oflag, varargs) { + // int open(const char *path, int oflag, ...); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html + var mode = HEAP32[((varargs)>>2)]; + path = Pointer_stringify(path); + try { + var stream = FS.open(path, oflag, mode); + return stream.fd; + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + + function _copysign(a, b) { + return __reallyNegative(a) === __reallyNegative(b) ? a : -a; + }var _copysignl=_copysign; + + var _sqrt=Math_sqrt; + + + var Browser={mainLoop:{scheduler:null,method:"",shouldPause:false,paused:false,queue:[],pause:function () { + Browser.mainLoop.shouldPause = true; + },resume:function () { + if (Browser.mainLoop.paused) { + Browser.mainLoop.paused = false; + Browser.mainLoop.scheduler(); + } + Browser.mainLoop.shouldPause = false; + },updateStatus:function () { + if (Module['setStatus']) { + var message = Module['statusMessage'] || 'Please wait...'; + var remaining = Browser.mainLoop.remainingBlockers; + var expected = Browser.mainLoop.expectedBlockers; + if (remaining) { + if (remaining < expected) { + Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')'); + } else { + Module['setStatus'](message); + } + } else { + Module['setStatus'](''); + } + } + }},isFullScreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function () { + if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers + + if (Browser.initted || ENVIRONMENT_IS_WORKER) return; + Browser.initted = true; + + try { + new Blob(); + Browser.hasBlobConstructor = true; + } catch(e) { + Browser.hasBlobConstructor = false; + console.log("warning: no blob constructor, cannot create blobs with mimetypes"); + } + Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null)); + Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined; + if (!Module.noImageDecoding && typeof Browser.URLObject === 'undefined') { + console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."); + Module.noImageDecoding = true; + } + + // Support for plugins that can process preloaded files. You can add more of these to + // your app by creating and appending to Module.preloadPlugins. + // + // Each plugin is asked if it can handle a file based on the file's name. If it can, + // it is given the file's raw data. When it is done, it calls a callback with the file's + // (possibly modified) data. For example, a plugin might decompress a file, or it + // might create some side data structure for use later (like an Image element, etc.). + + var imagePlugin = {}; + imagePlugin['canHandle'] = function imagePlugin_canHandle(name) { + return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name); + }; + imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) { + var b = null; + if (Browser.hasBlobConstructor) { + try { + b = new Blob([byteArray], { type: Browser.getMimetype(name) }); + if (b.size !== byteArray.length) { // Safari bug #118630 + // Safari's Blob can only take an ArrayBuffer + b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) }); + } + } catch(e) { + Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder'); + } + } + if (!b) { + var bb = new Browser.BlobBuilder(); + bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range + b = bb.getBlob(); + } + var url = Browser.URLObject.createObjectURL(b); + var img = new Image(); + img.onload = function img_onload() { + assert(img.complete, 'Image ' + name + ' could not be decoded'); + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + Module["preloadedImages"][name] = canvas; + Browser.URLObject.revokeObjectURL(url); + if (onload) onload(byteArray); + }; + img.onerror = function img_onerror(event) { + console.log('Image ' + url + ' could not be decoded'); + if (onerror) onerror(); + }; + img.src = url; + }; + Module['preloadPlugins'].push(imagePlugin); + + var audioPlugin = {}; + audioPlugin['canHandle'] = function audioPlugin_canHandle(name) { + return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; + }; + audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) { + var done = false; + function finish(audio) { + if (done) return; + done = true; + Module["preloadedAudios"][name] = audio; + if (onload) onload(byteArray); + } + function fail() { + if (done) return; + done = true; + Module["preloadedAudios"][name] = new Audio(); // empty shim + if (onerror) onerror(); + } + if (Browser.hasBlobConstructor) { + try { + var b = new Blob([byteArray], { type: Browser.getMimetype(name) }); + } catch(e) { + return fail(); + } + var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! + var audio = new Audio(); + audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926 + audio.onerror = function audio_onerror(event) { + if (done) return; + console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach'); + function encode64(data) { + var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + var PAD = '='; + var ret = ''; + var leftchar = 0; + var leftbits = 0; + for (var i = 0; i < data.length; i++) { + leftchar = (leftchar << 8) | data[i]; + leftbits += 8; + while (leftbits >= 6) { + var curr = (leftchar >> (leftbits-6)) & 0x3f; + leftbits -= 6; + ret += BASE[curr]; + } + } + if (leftbits == 2) { + ret += BASE[(leftchar&3) << 4]; + ret += PAD + PAD; + } else if (leftbits == 4) { + ret += BASE[(leftchar&0xf) << 2]; + ret += PAD; + } + return ret; + } + audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray); + finish(audio); // we don't wait for confirmation this worked - but it's worth trying + }; + audio.src = url; + // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror + Browser.safeSetTimeout(function() { + finish(audio); // try to use it even though it is not necessarily ready to play + }, 10000); + } else { + return fail(); + } + }; + Module['preloadPlugins'].push(audioPlugin); + + // Canvas event setup + + var canvas = Module['canvas']; + + // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module + // Module['forcedAspectRatio'] = 4 / 3; + + canvas.requestPointerLock = canvas['requestPointerLock'] || + canvas['mozRequestPointerLock'] || + canvas['webkitRequestPointerLock'] || + canvas['msRequestPointerLock'] || + function(){}; + canvas.exitPointerLock = document['exitPointerLock'] || + document['mozExitPointerLock'] || + document['webkitExitPointerLock'] || + document['msExitPointerLock'] || + function(){}; // no-op if function does not exist + canvas.exitPointerLock = canvas.exitPointerLock.bind(document); + + function pointerLockChange() { + Browser.pointerLock = document['pointerLockElement'] === canvas || + document['mozPointerLockElement'] === canvas || + document['webkitPointerLockElement'] === canvas || + document['msPointerLockElement'] === canvas; + } + + document.addEventListener('pointerlockchange', pointerLockChange, false); + document.addEventListener('mozpointerlockchange', pointerLockChange, false); + document.addEventListener('webkitpointerlockchange', pointerLockChange, false); + document.addEventListener('mspointerlockchange', pointerLockChange, false); + + if (Module['elementPointerLock']) { + canvas.addEventListener("click", function(ev) { + if (!Browser.pointerLock && canvas.requestPointerLock) { + canvas.requestPointerLock(); + ev.preventDefault(); + } + }, false); + } + },createContext:function (canvas, useWebGL, setInModule, webGLContextAttributes) { + var ctx; + var errorInfo = '?'; + function onContextCreationError(event) { + errorInfo = event.statusMessage || errorInfo; + } + try { + if (useWebGL) { + var contextAttributes = { + antialias: false, + alpha: false + }; + + if (webGLContextAttributes) { + for (var attribute in webGLContextAttributes) { + contextAttributes[attribute] = webGLContextAttributes[attribute]; + } + } + + + canvas.addEventListener('webglcontextcreationerror', onContextCreationError, false); + try { + ['experimental-webgl', 'webgl'].some(function(webglId) { + return ctx = canvas.getContext(webglId, contextAttributes); + }); + } finally { + canvas.removeEventListener('webglcontextcreationerror', onContextCreationError, false); + } + } else { + ctx = canvas.getContext('2d'); + } + if (!ctx) throw ':('; + } catch (e) { + Module.print('Could not create canvas: ' + [errorInfo, e]); + return null; + } + if (useWebGL) { + // Set the background of the WebGL canvas to black + canvas.style.backgroundColor = "black"; + + // Warn on context loss + canvas.addEventListener('webglcontextlost', function(event) { + alert('WebGL context lost. You will need to reload the page.'); + }, false); + } + if (setInModule) { + GLctx = Module.ctx = ctx; + Module.useWebGL = useWebGL; + Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); + Browser.init(); + } + return ctx; + },destroyContext:function (canvas, useWebGL, setInModule) {},fullScreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullScreen:function (lockPointer, resizeCanvas) { + Browser.lockPointer = lockPointer; + Browser.resizeCanvas = resizeCanvas; + if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true; + if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false; + + var canvas = Module['canvas']; + function fullScreenChange() { + Browser.isFullScreen = false; + var canvasContainer = canvas.parentNode; + if ((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement'] || + document['msFullScreenElement'] || document['msFullscreenElement'] || + document['webkitCurrentFullScreenElement']) === canvasContainer) { + canvas.cancelFullScreen = document['cancelFullScreen'] || + document['mozCancelFullScreen'] || + document['webkitCancelFullScreen'] || + document['msExitFullscreen'] || + document['exitFullscreen'] || + function() {}; + canvas.cancelFullScreen = canvas.cancelFullScreen.bind(document); + if (Browser.lockPointer) canvas.requestPointerLock(); + Browser.isFullScreen = true; + if (Browser.resizeCanvas) Browser.setFullScreenCanvasSize(); + } else { + + // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen + canvasContainer.parentNode.insertBefore(canvas, canvasContainer); + canvasContainer.parentNode.removeChild(canvasContainer); + + if (Browser.resizeCanvas) Browser.setWindowedCanvasSize(); + } + if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullScreen); + Browser.updateCanvasDimensions(canvas); + } + + if (!Browser.fullScreenHandlersInstalled) { + Browser.fullScreenHandlersInstalled = true; + document.addEventListener('fullscreenchange', fullScreenChange, false); + document.addEventListener('mozfullscreenchange', fullScreenChange, false); + document.addEventListener('webkitfullscreenchange', fullScreenChange, false); + document.addEventListener('MSFullscreenChange', fullScreenChange, false); + } + + // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root + var canvasContainer = document.createElement("div"); + canvas.parentNode.insertBefore(canvasContainer, canvas); + canvasContainer.appendChild(canvas); + + // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size) + canvasContainer.requestFullScreen = canvasContainer['requestFullScreen'] || + canvasContainer['mozRequestFullScreen'] || + canvasContainer['msRequestFullscreen'] || + (canvasContainer['webkitRequestFullScreen'] ? function() { canvasContainer['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null); + canvasContainer.requestFullScreen(); + },requestAnimationFrame:function requestAnimationFrame(func) { + if (typeof window === 'undefined') { // Provide fallback to setTimeout if window is undefined (e.g. in Node.js) + setTimeout(func, 1000/60); + } else { + if (!window.requestAnimationFrame) { + window.requestAnimationFrame = window['requestAnimationFrame'] || + window['mozRequestAnimationFrame'] || + window['webkitRequestAnimationFrame'] || + window['msRequestAnimationFrame'] || + window['oRequestAnimationFrame'] || + window['setTimeout']; + } + window.requestAnimationFrame(func); + } + },safeCallback:function (func) { + return function() { + if (!ABORT) return func.apply(null, arguments); + }; + },safeRequestAnimationFrame:function (func) { + return Browser.requestAnimationFrame(function() { + if (!ABORT) func(); + }); + },safeSetTimeout:function (func, timeout) { + return setTimeout(function() { + if (!ABORT) func(); + }, timeout); + },safeSetInterval:function (func, timeout) { + return setInterval(function() { + if (!ABORT) func(); + }, timeout); + },getMimetype:function (name) { + return { + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'png': 'image/png', + 'bmp': 'image/bmp', + 'ogg': 'audio/ogg', + 'wav': 'audio/wav', + 'mp3': 'audio/mpeg' + }[name.substr(name.lastIndexOf('.')+1)]; + },getUserMedia:function (func) { + if(!window.getUserMedia) { + window.getUserMedia = navigator['getUserMedia'] || + navigator['mozGetUserMedia']; + } + window.getUserMedia(func); + },getMovementX:function (event) { + return event['movementX'] || + event['mozMovementX'] || + event['webkitMovementX'] || + 0; + },getMovementY:function (event) { + return event['movementY'] || + event['mozMovementY'] || + event['webkitMovementY'] || + 0; + },getMouseWheelDelta:function (event) { + return Math.max(-1, Math.min(1, event.type === 'DOMMouseScroll' ? event.detail : -event.wheelDelta)); + },mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function (event) { // event should be mousemove, mousedown or mouseup + if (Browser.pointerLock) { + // When the pointer is locked, calculate the coordinates + // based on the movement of the mouse. + // Workaround for Firefox bug 764498 + if (event.type != 'mousemove' && + ('mozMovementX' in event)) { + Browser.mouseMovementX = Browser.mouseMovementY = 0; + } else { + Browser.mouseMovementX = Browser.getMovementX(event); + Browser.mouseMovementY = Browser.getMovementY(event); + } + + // check if SDL is available + if (typeof SDL != "undefined") { + Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; + Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; + } else { + // just add the mouse delta to the current absolut mouse position + // FIXME: ideally this should be clamped against the canvas size and zero + Browser.mouseX += Browser.mouseMovementX; + Browser.mouseY += Browser.mouseMovementY; + } + } else { + // Otherwise, calculate the movement based on the changes + // in the coordinates. + var rect = Module["canvas"].getBoundingClientRect(); + var cw = Module["canvas"].width; + var ch = Module["canvas"].height; + + // Neither .scrollX or .pageXOffset are defined in a spec, but + // we prefer .scrollX because it is currently in a spec draft. + // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/) + var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset); + var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset); + + if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') { + var touch = event.touch; + if (touch === undefined) { + return; // the "touch" property is only defined in SDL + + } + var adjustedX = touch.pageX - (scrollX + rect.left); + var adjustedY = touch.pageY - (scrollY + rect.top); + + adjustedX = adjustedX * (cw / rect.width); + adjustedY = adjustedY * (ch / rect.height); + + var coords = { x: adjustedX, y: adjustedY }; + + if (event.type === 'touchstart') { + Browser.lastTouches[touch.identifier] = coords; + Browser.touches[touch.identifier] = coords; + } else if (event.type === 'touchend' || event.type === 'touchmove') { + Browser.lastTouches[touch.identifier] = Browser.touches[touch.identifier]; + Browser.touches[touch.identifier] = { x: adjustedX, y: adjustedY }; + } + return; + } + + var x = event.pageX - (scrollX + rect.left); + var y = event.pageY - (scrollY + rect.top); + + // the canvas might be CSS-scaled compared to its backbuffer; + // SDL-using content will want mouse coordinates in terms + // of backbuffer units. + x = x * (cw / rect.width); + y = y * (ch / rect.height); + + Browser.mouseMovementX = x - Browser.mouseX; + Browser.mouseMovementY = y - Browser.mouseY; + Browser.mouseX = x; + Browser.mouseY = y; + } + },xhrLoad:function (url, onload, onerror) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = function xhr_onload() { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + } else { + onerror(); + } + }; + xhr.onerror = onerror; + xhr.send(null); + },asyncLoad:function (url, onload, onerror, noRunDep) { + Browser.xhrLoad(url, function(arrayBuffer) { + assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).'); + onload(new Uint8Array(arrayBuffer)); + if (!noRunDep) removeRunDependency('al ' + url); + }, function(event) { + if (onerror) { + onerror(); + } else { + throw 'Loading data file "' + url + '" failed.'; + } + }); + if (!noRunDep) addRunDependency('al ' + url); + },resizeListeners:[],updateResizeListeners:function () { + var canvas = Module['canvas']; + Browser.resizeListeners.forEach(function(listener) { + listener(canvas.width, canvas.height); + }); + },setCanvasSize:function (width, height, noUpdates) { + var canvas = Module['canvas']; + Browser.updateCanvasDimensions(canvas, width, height); + if (!noUpdates) Browser.updateResizeListeners(); + },windowedWidth:0,windowedHeight:0,setFullScreenCanvasSize:function () { + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags | 0x00800000; // set SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },setWindowedCanvasSize:function () { + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },updateCanvasDimensions:function (canvas, wNative, hNative) { + if (wNative && hNative) { + canvas.widthNative = wNative; + canvas.heightNative = hNative; + } else { + wNative = canvas.widthNative; + hNative = canvas.heightNative; + } + var w = wNative; + var h = hNative; + if (Module['forcedAspectRatio'] && Module['forcedAspectRatio'] > 0) { + if (w/h < Module['forcedAspectRatio']) { + w = Math.round(h * Module['forcedAspectRatio']); + } else { + h = Math.round(w / Module['forcedAspectRatio']); + } + } + if (((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement'] || + document['msFullScreenElement'] || document['msFullscreenElement'] || + document['webkitCurrentFullScreenElement']) === canvas.parentNode) && (typeof screen != 'undefined')) { + var factor = Math.min(screen.width / w, screen.height / h); + w = Math.round(w * factor); + h = Math.round(h * factor); + } + if (Browser.resizeCanvas) { + if (canvas.width != w) canvas.width = w; + if (canvas.height != h) canvas.height = h; + if (typeof canvas.style != 'undefined') { + canvas.style.removeProperty( "width"); + canvas.style.removeProperty("height"); + } + } else { + if (canvas.width != wNative) canvas.width = wNative; + if (canvas.height != hNative) canvas.height = hNative; + if (typeof canvas.style != 'undefined') { + if (w != wNative || h != hNative) { + canvas.style.setProperty( "width", w + "px", "important"); + canvas.style.setProperty("height", h + "px", "important"); + } else { + canvas.style.removeProperty( "width"); + canvas.style.removeProperty("height"); + } + } + } + }}; + + function _sprintf(s, format, varargs) { + // int sprintf(char *restrict s, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + return _snprintf(s, undefined, format, varargs); + } + + + function __exit(status) { + // void _exit(int status); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html + Module['exit'](status); + }function _exit(status) { + __exit(status); + } + + function _isspace(chr) { + return (chr == 32) || (chr >= 9 && chr <= 13); + } + + + function _fmod(x, y) { + return x % y; + }var _fmodl=_fmod; + + function _sysconf(name) { + // long sysconf(int name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/sysconf.html + switch(name) { + case 30: return PAGE_SIZE; + case 132: + case 133: + case 12: + case 137: + case 138: + case 15: + case 235: + case 16: + case 17: + case 18: + case 19: + case 20: + case 149: + case 13: + case 10: + case 236: + case 153: + case 9: + case 21: + case 22: + case 159: + case 154: + case 14: + case 77: + case 78: + case 139: + case 80: + case 81: + case 79: + case 82: + case 68: + case 67: + case 164: + case 11: + case 29: + case 47: + case 48: + case 95: + case 52: + case 51: + case 46: + return 200809; + case 27: + case 246: + case 127: + case 128: + case 23: + case 24: + case 160: + case 161: + case 181: + case 182: + case 242: + case 183: + case 184: + case 243: + case 244: + case 245: + case 165: + case 178: + case 179: + case 49: + case 50: + case 168: + case 169: + case 175: + case 170: + case 171: + case 172: + case 97: + case 76: + case 32: + case 173: + case 35: + return -1; + case 176: + case 177: + case 7: + case 155: + case 8: + case 157: + case 125: + case 126: + case 92: + case 93: + case 129: + case 130: + case 131: + case 94: + case 91: + return 1; + case 74: + case 60: + case 69: + case 70: + case 4: + return 1024; + case 31: + case 42: + case 72: + return 32; + case 87: + case 26: + case 33: + return 2147483647; + case 34: + case 1: + return 47839; + case 38: + case 36: + return 99; + case 43: + case 37: + return 2048; + case 0: return 2097152; + case 3: return 65536; + case 28: return 32768; + case 44: return 32767; + case 75: return 16384; + case 39: return 1000; + case 89: return 700; + case 71: return 256; + case 40: return 255; + case 2: return 100; + case 180: return 64; + case 25: return 20; + case 5: return 16; + case 6: return 6; + case 73: return 4; + case 84: return 1; + } + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + + + Module["_tolower"] = _tolower; + + var _atan=Math_atan; + + + function _recv(fd, buf, len, flags) { + var sock = SOCKFS.getSocket(fd); + if (!sock) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + // TODO honor flags + return _read(fd, buf, len); + } + + function _pread(fildes, buf, nbyte, offset) { + // ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + var slab = HEAP8; + return FS.read(stream, slab, buf, nbyte, offset); + } catch (e) { + FS.handleFSError(e); + return -1; + } + }function _read(fildes, buf, nbyte) { + // ssize_t read(int fildes, void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + + + try { + var slab = HEAP8; + return FS.read(stream, slab, buf, nbyte); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + function _time(ptr) { + var ret = Math.floor(Date.now()/1000); + if (ptr) { + HEAP32[((ptr)>>2)]=ret; + } + return ret; + } + + + + + + + var _environ=allocate(1, "i32*", ALLOC_STATIC);var ___environ=_environ;function ___buildEnvironment(env) { + // WARNING: Arbitrary limit! + var MAX_ENV_VALUES = 64; + var TOTAL_ENV_SIZE = 1024; + + // Statically allocate memory for the environment. + var poolPtr; + var envPtr; + if (!___buildEnvironment.called) { + ___buildEnvironment.called = true; + // Set default values. Use string keys for Closure Compiler compatibility. + ENV['USER'] = 'root'; + ENV['PATH'] = '/'; + ENV['PWD'] = '/'; + ENV['HOME'] = '/home/emscripten'; + ENV['LANG'] = 'en_US.UTF-8'; + ENV['_'] = './this.program'; + // Allocate memory. + poolPtr = allocate(TOTAL_ENV_SIZE, 'i8', ALLOC_STATIC); + envPtr = allocate(MAX_ENV_VALUES * 4, + 'i8*', ALLOC_STATIC); + HEAP32[((envPtr)>>2)]=poolPtr; + HEAP32[((_environ)>>2)]=envPtr; + } else { + envPtr = HEAP32[((_environ)>>2)]; + poolPtr = HEAP32[((envPtr)>>2)]; + } + + // Collect key=value lines. + var strings = []; + var totalSize = 0; + for (var key in env) { + if (typeof env[key] === 'string') { + var line = key + '=' + env[key]; + strings.push(line); + totalSize += line.length; + } + } + if (totalSize > TOTAL_ENV_SIZE) { + throw new Error('Environment size exceeded TOTAL_ENV_SIZE!'); + } + + // Make new. + var ptrSize = 4; + for (var i = 0; i < strings.length; i++) { + var line = strings[i]; + writeAsciiToMemory(line, poolPtr); + HEAP32[(((envPtr)+(i * ptrSize))>>2)]=poolPtr; + poolPtr += line.length + 1; + } + HEAP32[(((envPtr)+(strings.length * ptrSize))>>2)]=0; + }var ENV={};function _getenv(name) { + // char *getenv(const char *name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html + if (name === 0) return 0; + name = Pointer_stringify(name); + if (!ENV.hasOwnProperty(name)) return 0; + + if (_getenv.ret) _free(_getenv.ret); + _getenv.ret = allocate(intArrayFromString(ENV[name]), 'i8', ALLOC_NORMAL); + return _getenv.ret; + } + + + function _emscripten_memcpy_big(dest, src, num) { + HEAPU8.set(HEAPU8.subarray(src, src+num), dest); + return dest; + } + Module["_memcpy"] = _memcpy; + + var _log=Math_log; + + var _cos=Math_cos; + + var _llvm_pow_f64=Math_pow; + + function _sbrk(bytes) { + // Implement a Linux-like 'memory area' for our 'process'. + // Changes the size of the memory area by |bytes|; returns the + // address of the previous top ('break') of the memory area + // We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP + var self = _sbrk; + if (!self.called) { + DYNAMICTOP = alignMemoryPage(DYNAMICTOP); // make sure we start out aligned + self.called = true; + assert(Runtime.dynamicAlloc); + self.alloc = Runtime.dynamicAlloc; + Runtime.dynamicAlloc = function() { abort('cannot dynamically allocate, sbrk now has control') }; + } + var ret = DYNAMICTOP; + if (bytes != 0) self.alloc(bytes); + return ret; // Previous break location. + } + + function ___errno_location() { + return ___errno_state; + } + + var _BItoD=true; + + var _sin=Math_sin; + + var _atan2=Math_atan2; + + + Module["_strcpy"] = _strcpy; + + function _llvm_bswap_i32(x) { + return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24); + } + + + + function _islower(chr) { + return chr >= 97 && chr <= 122; + } + + var _exp=Math_exp; + + var _acos=Math_acos; + + function _isupper(chr) { + return chr >= 65 && chr <= 90; + } + +FS.staticInit();__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });__ATEXIT__.push({ func: function() { FS.quit() } });Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice; +___errno_state = Runtime.staticAlloc(4); HEAP32[((___errno_state)>>2)]=0; +__ATINIT__.unshift({ func: function() { TTY.init() } });__ATEXIT__.push({ func: function() { TTY.shutdown() } });TTY.utf8 = new Runtime.UTF8Processor(); +if (ENVIRONMENT_IS_NODE) { var fs = require("fs"); NODEFS.staticInit(); } +__ATINIT__.push({ func: function() { SOCKFS.root = FS.mount(SOCKFS, {}, null); } }); +Module["requestFullScreen"] = function Module_requestFullScreen(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) }; + Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) }; + Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) }; + Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() }; + Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() }; + Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() } +___buildEnvironment(ENV); +STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP); + +staticSealed = true; // seal the static portion of memory + +STACK_MAX = STACK_BASE + 5242880; + +DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX); + +assert(DYNAMIC_BASE < TOTAL_MEMORY, "TOTAL_MEMORY not big enough for stack"); + + var ctlz_i8 = allocate([8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], "i8", ALLOC_DYNAMIC); + var cttz_i8 = allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0], "i8", ALLOC_DYNAMIC); + +var Math_min = Math.min; +function invoke_iiii(index,a1,a2,a3) { + try { + return Module["dynCall_iiii"](index,a1,a2,a3); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_iddiii(index,a1,a2,a3,a4,a5) { + try { + return Module["dynCall_iddiii"](index,a1,a2,a3,a4,a5); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_vii(index,a1,a2) { + try { + Module["dynCall_vii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_iii(index,a1,a2) { + try { + return Module["dynCall_iii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function asmPrintInt(x, y) { + Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack); +} +function asmPrintFloat(x, y) { + Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack); +} +// EMSCRIPTEN_START_ASM +var asm=(function(global,env,buffer){"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=env.cttz_i8|0;var n=env.ctlz_i8|0;var o=env._stderr|0;var p=0;var q=0;var r=0;var s=0;var t=+env.NaN,u=+env.Infinity;var v=0,w=0,x=0,y=0,z=0.0,A=0,B=0,C=0,D=0.0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=0;var M=0;var N=0;var O=global.Math.floor;var P=global.Math.abs;var Q=global.Math.sqrt;var R=global.Math.pow;var S=global.Math.cos;var T=global.Math.sin;var U=global.Math.tan;var V=global.Math.acos;var W=global.Math.asin;var X=global.Math.atan;var Y=global.Math.atan2;var Z=global.Math.exp;var _=global.Math.log;var $=global.Math.ceil;var aa=global.Math.imul;var ba=env.abort;var ca=env.assert;var da=env.asmPrintInt;var ea=env.asmPrintFloat;var fa=env.min;var ga=env.invoke_iiii;var ha=env.invoke_iddiii;var ia=env.invoke_vii;var ja=env.invoke_iii;var ka=env._fabs;var la=env._sin;var ma=env._exp;var na=env._llvm_pow_f64;var oa=env._acos;var pa=env._atan2;var qa=env._fmod;var ra=env._lseek;var sa=env.__reallyNegative;var ta=env._asin;var ua=env._atan;var va=env.___buildEnvironment;var wa=env._fflush;var xa=env._pwrite;var ya=env._strerror_r;var za=env._fprintf;var Aa=env._open;var Ba=env._fabsf;var Ca=env._sbrk;var Da=env._send;var Ea=env._snprintf;var Fa=env._llvm_bswap_i32;var Ga=env._emscripten_memcpy_big;var Ha=env._fileno;var Ia=env._sysconf;var Ja=env.___setErrNo;var Ka=env._cos;var La=env._pread;var Ma=env._printf;var Na=env._sprintf;var Oa=env._log;var Pa=env._toupper;var Qa=env._write;var Ra=env._isupper;var Sa=env.___errno_location;var Ta=env._recv;var Ua=env._tan;var Va=env._copysign;var Wa=env._getenv;var Xa=env._mkport;var Ya=env.__exit;var Za=env._read;var _a=env._abort;var $a=env._islower;var ab=env._fwrite;var bb=env._time;var cb=env._isdigit;var db=env._strerror;var eb=env.__formatString;var fb=env._isspace;var gb=env._sqrt;var hb=env._exit;var ib=env._close;var jb=0.0; +// EMSCRIPTEN_START_FUNCS +function ob(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+7&-8;return b|0}function pb(){return i|0}function qb(a){a=a|0;i=a}function rb(a,b){a=a|0;b=b|0;if((p|0)==0){p=a;q=b}}function sb(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0]}function tb(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0];a[k+4|0]=a[b+4|0];a[k+5|0]=a[b+5|0];a[k+6|0]=a[b+6|0];a[k+7|0]=a[b+7|0]}function ub(a){a=a|0;E=a}function vb(a){a=a|0;F=a}function wb(a){a=a|0;G=a}function xb(a){a=a|0;H=a}function yb(a){a=a|0;I=a}function zb(a){a=a|0;J=a}function Ab(a){a=a|0;K=a}function Bb(a){a=a|0;L=a}function Cb(a){a=a|0;M=a}function Db(a){a=a|0;N=a}function Eb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;if((d|0)>0){f=Ob(b,d)|0}else{f=Pb(b)|0}b=(f|0)==0;if(!b){Xb(f,hc(f)|0)}d=c[1086]|0;if((d|0)==0){c[1086]=10;g=gg(41040)|0;c[1088]=g;if((g|0)==0){h=-4;i=e;return h|0}else{j=10}}else{j=d}d=c[1090]|0;a:do{if((d|0)<(j|0)){k=d}else{g=j;l=c[1088]|0;while(1){m=g+10|0;c[1086]=m;n=jg(l,m*4104|0)|0;c[1088]=n;if((n|0)==0){h=-3;break}m=c[1086]|0;o=c[1090]|0;if((o|0)<(m|0)){k=o;break a}else{g=m;l=n}}i=e;return h|0}}while(0);if(b){h=-1;i=e;return h|0}c[(c[1088]|0)+(k*4104|0)>>2]=f;f=c[1088]|0;c[f+(k*4104|0)+4>>2]=0;a[f+((c[1090]|0)*4104|0)+8|0]=0;c[1090]=(c[1090]|0)+1;h=k;i=e;return h|0}function Fb(b,d,e){b=b|0;d=+d;e=+e;var f=0,g=0,h=0,j=0,k=0;f=i;g=c[1088]|0;h=c[g+(b*4104|0)>>2]|0;if((h|0)==0){j=0;i=f;return j|0}k=g+(b*4104|0)+8|0;a[k]=0;dc(h,d+-1.0,e+-1.0,k,4096)|0;j=k;i=f;return j|0}function Gb(b,d,e){b=b|0;d=+d;e=+e;var f=0,g=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+4144|0;g=f+16|0;j=f+40|0;l=f+8|0;m=f;if((b|0)>0&(c[1086]|0)>(b|0)){n=(c[1088]|0)+(b*4104|0)|0}else{n=0}b=c[n>>2]|0;if((b|0)==0){o=0;i=f;return o|0}cc(b,d,e,l,m,f+32|0);e=+h[m>>3]+1.0;h[k>>3]=+h[l>>3]+1.0;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];l=g+8|0;h[k>>3]=e;c[l>>2]=c[k>>2];c[l+4>>2]=c[k+4>>2];Ea(j|0,4095,8,g|0)|0;g=n+8|0;n=a[j]|0;a:do{if(!(n<<24>>24==0)){l=j;m=n;while(1){b=l+1|0;if((fb(m<<24>>24|0)|0)==0){break}m=a[b]|0;if(m<<24>>24==0){break a}else{l=b}}m=a[l]|0;if(!(m<<24>>24==0)){b=g;p=l;q=m;while(1){m=p+1|0;r=b+1|0;a[b]=q;s=a[m]|0;if(s<<24>>24==0){break}else{b=r;p=m;q=s}}a[r]=0;if((r|0)==(g|0)){o=g;i=f;return o|0}q=r;p=r-g|0;while(1){b=q+ -1|0;if((fb(a[b]|0)|0)==0){o=g;t=14;break}a[b]=0;l=p+ -1|0;if((l|0)==0){o=g;t=14;break}else{q=b;p=l}}if((t|0)==14){i=f;return o|0}}}}while(0);a[g]=0;o=g;i=f;return o|0}function Hb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;if((b|0)>0&(c[1086]|0)>(b|0)){f=(c[1088]|0)+(b*4104|0)|0}else{f=0}b=c[f>>2]|0;if((b|0)==0){g=0;i=e;return g|0}h=f+8|0;a[h]=0;do{if((d|0)!=0?(a[d]|0)!=0:0){if(((xg(d,24)|0)!=0?(xg(d,40)|0)!=0:0)?(xg(d,56)|0)!=0:0){if(!(+oc(d)>0.0)){break}j=c[f>>2]|0}else{j=b}Xb(j,d)}}while(0);Hg(h|0,fc(c[f>>2]|0)|0,4096)|0;if((xg(h,24)|0)==0){k=h+0|0;l=24|0;m=k+9|0;do{a[k]=a[l]|0;k=k+1|0;l=l+1|0}while((k|0)<(m|0));g=h;i=e;return g|0}if((xg(h,40)|0)==0){k=h+0|0;l=40|0;m=k+9|0;do{a[k]=a[l]|0;k=k+1|0;l=l+1|0}while((k|0)<(m|0));g=h;i=e;return g|0}l=a[h]|0;if(l<<24>>24==0){g=h;i=e;return g|0}else{n=h;o=l}while(1){if(($a(o<<24>>24|0)|0)!=0){a[n]=Pa(a[n]|0)|0}l=n+1|0;k=a[l]|0;if(k<<24>>24==0){g=h;break}else{n=l;o=k}}i=e;return g|0}function Ib(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;if((b|0)>0&(c[1086]|0)>(b|0)){f=(c[1088]|0)+(b*4104|0)|0}else{f=0}b=c[f>>2]|0;if((b|0)==0){g=0;i=e;return g|0}h=f+8|0;a[h]=0;do{if((d|0)!=0?(a[d]|0)!=0:0){if((xg(d,64)|0)==0){gc(b,1)|0;c[f+4>>2]=1;break}else{gc(b,0)|0;c[f+4>>2]=0;break}}}while(0);b=c[f+4>>2]|0;if((b|0)==1){Hg(h|0,64,4095)|0}else if((b|0)==0){Hg(h|0,72,4095)|0}b=a[h]|0;if(b<<24>>24==0){g=h;i=e;return g|0}else{j=h;k=b}while(1){if((Ra(k<<24>>24|0)|0)!=0){a[j]=Jg(a[j]|0)|0}b=j+1|0;f=a[b]|0;if(f<<24>>24==0){g=h;break}else{j=b;k=f}}i=e;return g|0}function Jb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0.0,C=0.0,D=0,E=0.0,F=0.0,G=0,H=0,I=0.0,J=0.0,K=0.0;e=i;i=i+12352|0;f=e+32|0;g=e+56|0;j=e+4152|0;l=e+8248|0;m=e+48|0;n=e+52|0;o=e+24|0;p=e;q=e+8|0;r=e+16|0;if((b|0)>0&(c[1086]|0)>(b|0)){s=(c[1088]|0)+(b*4104|0)|0}else{s=0}c[m>>2]=0;c[n>>2]=0;if((c[s>>2]|0)==0){t=0;i=e;return t|0}u=Hb(b,0)|0;if(((yg(u,24)|0)!=0?(yg(u,40)|0)!=0:0)?(yg(u,56)|0)!=0:0){v=0}else{v=1}u=s+8|0;a[u]=0;b=cg(d)|0;d=fg(b,88)|0;if((d|0)!=0){w=s+4|0;x=(v|0)==0;v=d;do{d=$f(v,32)|0;if((d|0)==0){c[m>>2]=96;y=96;z=0}else{A=d+1|0;c[m>>2]=A;a[d]=0;y=A;z=v}B=+wg(y,n);if(B!=0.0?(C=+wg(c[n>>2]|0,m),C!=0.0):0){bc(c[s>>2]|0,B,C,o,p);A=(z|0)!=0;if(A){c[f>>2]=z;Ea(g|0,4096,104,f|0)|0;dg(u,g,4095)|0}d=c[w>>2]|0;if((d|0)==0){C=+h[o>>3];if(x){Tc(j,4095,C,3)}else{Uc(j,4095,C,3)}Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,128,f|0)|0;dg(u,g,4095)|0}else if((d|0)==1){C=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];d=f+8|0;h[k>>3]=C;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];Ea(g|0,4096,112,f|0)|0;dg(u,g,4095)|0}else{C=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];d=f+8|0;h[k>>3]=C;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];Ea(g|0,4096,112,f|0)|0;dg(u,g,4095)|0}d=(yg(z,136)|0)==0;C=+wg(c[m>>2]|0,n);D=C!=0.0;a:do{if(d){if(D){if(x){B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);G=c[w>>2]|0;if((G|0)==0){Tc(j,4095,+h[o>>3],3);Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,160,f|0)|0;dg(u,g,4095)|0}else if((G|0)==1){E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}else{E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}E=+wg(c[m>>2]|0,n);if(E!=0.0){B=E}else{F=E;break}}}else{B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);G=c[w>>2]|0;if((G|0)==1){E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];H=f+8|0;h[k>>3]=E;c[H>>2]=c[k>>2];c[H+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}else if((G|0)==0){Uc(j,4095,+h[o>>3],3);Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,160,f|0)|0;dg(u,g,4095)|0}else{E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}E=+wg(c[m>>2]|0,n);if(E!=0.0){B=E}else{F=E;break}}}}else{F=C}}else{if(D){B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}I=+wg(c[m>>2]|0,n);if(!(I!=0.0)){F=B;break a}J=+wg(c[n>>2]|0,m);if(!(J!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);bc(c[s>>2]|0,I,J,q,r);J=+ec(+h[o>>3],+h[p>>3],+h[q>>3],+h[r>>3])*3600.0;do{if(!(J<=60.0)){if(!(J<=3600.0)){h[k>>3]=J/3600.0;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,192,f|0)|0;dg(u,g,4095)|0;break}else{h[k>>3]=J/60.0;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,184,f|0)|0;dg(u,g,4095)|0;break}}else{h[k>>3]=J;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,176,f|0)|0;dg(u,g,4095)|0}}while(0);J=+wg(c[m>>2]|0,n);if(J!=0.0){B=J}else{F=J;break}}}else{F=C}}}while(0);if(!((yg(z,200)|0)!=0?(yg(z,208)|0)!=0:0)){if(F<0.0){C=F;while(1){B=C+6.283185307179586;if(B<0.0){C=B}else{K=B;break}}}else{K=F}h[k>>3]=K*57.29577951308232;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,216,f|0)|0;dg(u,g,4095)|0}if(A){Ea(g|0,4096,224,f|0)|0;dg(u,g,4095)|0}Ea(g|0,4096,88,f|0)|0;dg(u,g,4095)|0}v=fg(0,88)|0}while((v|0)!=0)}if((b|0)==0){t=u;i=e;return t|0}hg(b);t=u;i=e;return t|0}function Kb(a){a=a|0;var b=0,c=0.0;b=i;c=+af(a,0);i=b;return+c}function Lb(b,d,e,f,j,l,m){b=b|0;d=d|0;e=e|0;f=f|0;j=+j;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0;n=i;i=i+4128|0;o=n;p=n+20|0;q=n+16|0;r=n+24|0;bf(b,d,e,f,p,q,j,l,m);j=+g[q>>2];h[k>>3]=+g[p>>2];c[o>>2]=c[k>>2];c[o+4>>2]=c[k+4>>2];p=o+8|0;h[k>>3]=j;c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];Ea(r|0,4095,240,o|0)|0;o=a[r]|0;a:do{if(!(o<<24>>24==0)){p=r;q=o;while(1){m=p+1|0;if((fb(q<<24>>24|0)|0)==0){break}q=a[m]|0;if(q<<24>>24==0){break a}else{p=m}}q=a[p]|0;if(!(q<<24>>24==0)){m=248;l=p;f=q;while(1){q=l+1|0;s=m+1|0;a[m]=f;e=a[q]|0;if(e<<24>>24==0){break}else{m=s;l=q;f=e}}a[s]=0;if((s|0)==248){i=n;return 248}f=s;l=s-248|0;while(1){m=f+ -1|0;if((fb(a[m]|0)|0)==0){t=11;break}a[m]=0;p=l+ -1|0;if((p|0)==0){t=11;break}else{f=m;l=p}}if((t|0)==11){i=n;return 248}}}}while(0);a[248]=0;i=n;return 248}function Mb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0.0,ha=0.0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0.0,sa=0.0,ta=0.0,ua=0,va=0.0,wa=0,xa=0,ya=0.0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0.0,La=0.0,Ma=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0;e=i;i=i+1184|0;f=e+672|0;g=e+1176|0;j=e+1144|0;l=e+1112|0;m=e+1048|0;n=e+1040|0;p=e+1024|0;q=e+1032|0;r=e+1080|0;s=e+848|0;t=e;u=e+752|0;v=e+744|0;w=e+656|0;x=e+760|0;y=e+664|0;z=e+816|0;A=e+856|0;B=e+736|0;C=e+840|0;D=e+824|0;E=e+808|0;F=e+768|0;G=e+8|0;H=e+1088|0;I=e+868|0;J=e+864|0;K=e+872|0;L=e+880|0;M=e+960|0;N=e+1104|0;O=e+832|0;P=e+800|0;Q=e+728|0;R=ig(1,9336)|0;U=a[d]|0;d=U<<24>>24==32?0:U;a[N]=d;a[R+9324|0]=d;if((Oc(b,4424,N,63,M)|0)!=0){d=ig((Dg(M|0)|0)+2|0,1)|0;c[R+9320>>2]=d;Lg(d|0,M|0)|0}d=R+3984|0;c[d>>2]=0;c[R+3956>>2]=0;c[R+3924>>2]=0;c[R+3952>>2]=-1;U=R+3268|0;c[U>>2]=0;V=R+3272|0;c[V>>2]=0;h[D>>3]=0.0;h[E>>3]=0.0;W=F+8|0;X=F+16|0;Y=F+24|0;c[F+0>>2]=0;c[F+4>>2]=0;c[F+8>>2]=0;c[F+12>>2]=0;c[F+16>>2]=0;c[F+20>>2]=0;c[F+24>>2]=0;c[F+28>>2]=0;h[G>>3]=0.0;Z=R+3300|0;c[Z>>2]=0;_=R+48|0;h[_>>3]=0.0;c[K>>2]=0;Dc(b,4432,N,K)|0;$=c[K>>2]|0;if(($|0)==0){Ec(b,4432,K)|0;ba=c[K>>2]|0;if((ba|0)==0){Ec(b,4440,K)|0;ca=c[K>>2]|0;if((ca|0)==0){Ec(b,4448,K)|0;da=c[K>>2]|0}else{da=ca}}else{da=ba}}else{da=$}if((da|0)<1){_b(4456);Tb(R);ea=0;i=e;return ea|0}if((da|0)>2){c[K>>2]=2;fa=2}else{fa=da}da=R+3316|0;c[da>>2]=fa;$=R+3320|0;c[$>>2]=fa;c[R+3960>>2]=fa;fa=R+136|0;h[fa>>3]=0.0;Lc(b,4504,fa)|0;ga=+h[fa>>3];if(ga<1.0){Lc(b,4512,fa)|0;ha=+h[fa>>3]}else{ha=ga}if(ha<1.0){_b(4520);Tb(R);ea=0;i=e;return ea|0}ba=R+144|0;h[ba>>3]=0.0;Lc(b,4560,ba)|0;if(+h[ba>>3]<1.0){Lc(b,4568,ba)|0}ca=c[K>>2]|0;if((ca|0)>1){if(+h[ba>>3]<1.0){_b(4576);Tb(R);ea=0;i=e;return ea|0}else{ia=19}}else{if((ca|0)>0){ia=19}else{ja=0}}if((ia|0)==19){ca=c[o>>2]|0;ka=0;la=0;while(1){a[H+0|0]=a[4440|0]|0;a[H+1|0]=a[4441|0]|0;a[H+2|0]=a[4442|0]|0;a[H+3|0]=a[4443|0]|0;a[H+4|0]=a[4444|0]|0;a[H+5|0]=a[4445|0]|0;ma=ka+1|0;c[f>>2]=ma;Na(L|0,4616,f|0)|0;Fg(H|0,L|0)|0;do{if((Ec(b,H,J)|0)==0){if((ka|0)==0){ha=+h[fa>>3];if(ha>1.0){c[J>>2]=~~ha;break}}else if((ka|0)==1?(ha=+h[ba>>3],ha>1.0):0){c[J>>2]=~~ha;break}c[f>>2]=H;za(ca|0,4624,f|0)|0}}while(0);a[H+0|0]=a[4664|0]|0;a[H+1|0]=a[4665|0]|0;a[H+2|0]=a[4666|0]|0;a[H+3|0]=a[4667|0]|0;a[H+4|0]=a[4668|0]|0;a[H+5|0]=a[4669|0]|0;Fg(H|0,L|0)|0;if((Pc(b,H,16,L)|0)!=0?(Qc(L,4672)|0)!=0:0){c[J>>2]=0}na=((c[J>>2]|0)>1)+la|0;if((ma|0)<(c[K>>2]|0)){ka=ma;la=na}else{ja=na;break}}}c[K>>2]=ja;c[$>>2]=ja;c[da>>2]=ja;Pc(b,4680,16,R+3336|0)|0;Ec(b,4696,R+3332|0)|0;ja=R+3324|0;c[ja>>2]=kc()|0;$=R+9328|0;c[$>>2]=0;Ec(b,4712,$)|0;$=R+832|0;Eg($|0,0,648)|0;Eg(G|0,0,648)|0;la=c[K>>2]|0;ka=(la|0)>0;if(ka){ca=0;do{h[$+((aa(la,ca)|0)+ca<<3)>>3]=1.0;ca=ca+1|0}while((ca|0)<(la|0));if(ka){ca=0;do{h[G+((aa(la,ca)|0)+ca<<3)>>3]=1.0;ca=ca+1|0}while((ca|0)<(la|0));ca=R+760|0;oa=ca+0|0;pa=oa+72|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));if(ka){ka=0;while(1){h[ca+(ka<<3)>>3]=1.0;na=ka+1|0;if((na|0)<(la|0)){ka=na}else{qa=ca;break}}}else{qa=ca}}else{ia=37}}else{ia=37}if((ia|0)==37){ca=R+760|0;oa=ca+0|0;pa=oa+72|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));qa=ca}do{if((Oc(b,4720,N,63,M)|0)==0){c[R+9312>>2]=0}else{ca=Nb(b,M)|0;a[g]=ca;if(!(ca<<24>>24==95)){ca=Mb(b,g)|0;c[R+9312>>2]=ca;if((ca|0)!=0){c[ca+9316>>2]=R;break}}else{ca=c[o>>2]|0;c[f>>2]=M;za(ca|0,4368,f|0)|0;c[R+9312>>2]=0}_b(4728);Tb(R);ea=0;i=e;return ea|0}}while(0);M=R+3224|0;g=R+3232|0;c[M+0>>2]=0;c[M+4>>2]=0;c[M+8>>2]=0;c[M+12>>2]=0;do{if((Kc(b,4776,N,M)|0)==0){if((Kc(b,4784,N,g)|0)!=0){h[M>>3]=+h[g>>3]*299792.5;break}if((Lc(b,4792,M)|0)!=0){h[g>>3]=+h[M>>3]/299792.5}}else{h[g>>3]=+h[M>>3]/299792.5}}while(0);M=R+4096|0;oa=M+0|0;pa=oa+80|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));do{if((Oc(b,4808,N,16,j)|0)==0){g=a[N]|0;if(!(g<<24>>24==32|g<<24>>24==0)){c[f>>2]=g<<24>>24;Na(L|0,5368,f|0)|0;_b(L);Tb(R);ea=0;i=e;return ea|0}if((Cc(b,5408)|0)!=0){c[R+3260>>2]=29;g=Cc(b,5408)|0;Lc(g,5408,s)|0;Lc(g,5416,t)|0;Lc(g,5424,u)|0;h[R+152>>3]=(+h[s>>3]+ +h[t>>3]/60.0+ +h[u>>3]/3600.0)*15.0*3.141592653589793/180.0;a[r]=43;Pc(g,5432,1,r)|0;ha=(a[r]|0)==45?-1.0:1.0;Lc(g,5448,v)|0;Lc(g,5456,w)|0;Lc(g,5464,x)|0;h[R+160>>3]=ha*(+h[v>>3]+ +h[w>>3]/60.0+ +h[x>>3]/3600.0)*3.141592653589793/180.0;g=R+120|0;Lc(b,5472,g)|0;Ec(b,5472,I)|0;ca=R+3764|0;ka=(c[I>>2]|0)==1950?3427142:3492678;a[ca]=ka;a[ca+1|0]=ka>>8;a[ca+2|0]=ka>>16;a[ca+3|0]=ka>>24;ka=R+128|0;h[ka>>3]=+h[g>>3];Lc(b,5344,ka)|0;ha=+h[t>>3];ga=+h[u>>3];ka=a[r]|0;ra=+h[v>>3];sa=+h[w>>3];ta=+h[x>>3];h[k>>3]=+h[s>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];g=f+8|0;h[k>>3]=ha;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];g=f+16|0;h[k>>3]=ga;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];c[f+24>>2]=ka;ka=f+28|0;h[k>>3]=ra;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];ka=f+36|0;h[k>>3]=sa;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];ka=f+44|0;h[k>>3]=ta;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];c[f+52>>2]=ca;Na(R+3892|0,5496,f|0)|0;Lc(b,5544,R+168|0)|0;Lc(b,5560,R+192|0)|0;Lc(b,5576,R+200|0)|0;Lc(b,5592,R+176|0)|0;Lc(b,5600,R+184|0)|0;ca=Cc(b,5608)|0;ka=R+208|0;c[f>>2]=1;Na(H|0,5616,f|0)|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=2;Na(H|0,5616,f|0)|0;ka=R+216|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=3;Na(H|0,5616,f|0)|0;ka=R+224|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=4;Na(H|0,5616,f|0)|0;ka=R+232|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=5;Na(H|0,5616,f|0)|0;ka=R+240|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=6;Na(H|0,5616,f|0)|0;ka=R+248|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;ka=Cc(b,5624)|0;ca=R+256|0;g=0;while(1){la=g+1|0;c[f>>2]=la;Na(H|0,5632,f|0)|0;na=ca+(g<<3)|0;h[na>>3]=0.0;Lc(ka,H,na)|0;if((la|0)==20){break}else{g=la}}g=Cc(b,5640)|0;ka=R+416|0;ca=0;while(1){ma=ca+1|0;c[f>>2]=ma;Na(H|0,5648,f|0)|0;la=ka+(ca<<3)|0;h[la>>3]=0.0;Lc(g,H,la)|0;if((ma|0)==20){break}else{ca=ma}}ca=R+3312|0;c[ca>>2]=1;g=R+3449|0;a[g+0|0]=a[5656|0]|0;a[g+1|0]=a[5657|0]|0;a[g+2|0]=a[5658|0]|0;g=R+3458|0;a[g]=4408644;a[g+1|0]=17221;a[g+2|0]=67;a[g+3|0]=0;g=R+3467|0;a[g]=5460804;a[g+1|0]=21331;a[g+2|0]=83;a[g+3|0]=0;c[R+3292>>2]=0;c[R+3288>>2]=3;oa=R+3368|0;g=5664|0;pa=oa+9|0;do{a[oa]=a[g]|0;oa=oa+1|0;g=g+1|0}while((oa|0)<(pa|0));oa=R+3377|0;g=5680|0;pa=oa+9|0;do{a[oa]=a[g]|0;oa=oa+1|0;g=g+1|0}while((oa|0)<(pa|0));ta=+h[fa>>3]*.5;g=R+616|0;h[g>>3]=ta;sa=+h[ba>>3]*.5;ka=R+624|0;h[ka>>3]=sa;h[R+16>>3]=ta;h[R+24>>3]=sa;nd(ta,sa,R,z,B)|0;sa=+h[z>>3];h[R+688>>3]=sa;ta=+h[B>>3];h[R+696>>3]=ta;h[R>>3]=sa;h[R+8>>3]=ta;nd(+h[g>>3],+h[ka>>3]+1.0,R,A,C)|0;ta=+h[C>>3]- +h[B>>3];h[R+40>>3]=ta;h[R+32>>3]=-ta;Sb(R);c[ca>>2]=1;ac(R);ta=+h[_>>3]*3.141592653589793/180.0;h[P>>3]=ta;sa=+h[g>>3]+ +S(+ta);nd(sa,+h[ka>>3]+ +T(+ta),R,A,C)|0;h[qa>>3]=-+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);ta=+h[P>>3];sa=+h[g>>3]+ +T(+ta);nd(sa,+h[ka>>3]+ +S(+ta),R,A,C)|0;ta=+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[R+768>>3]=ta;Wb(R,+h[qa>>3],ta,+h[_>>3]);ua=qa;break}if(((((Cc(b,5088)|0)==0?(Cc(b,5096)|0)==0:0)?(Cc(b,5112)|0)==0:0)?(Cc(b,5128)|0)==0:0)?(Cc(b,5144)|0)==0:0){_b(5824);Tb(R);ea=0;i=e;return ea|0}h[y>>3]=0.0;Lc(b,5088,y)|0;ta=+h[y>>3];if(ta==0.0){Lc(b,5096,y)|0;va=+h[y>>3]}else{va=ta}do{if(va==0.0){Lc(b,5144,y)|0;ta=+h[y>>3];if(ta!=0.0){h[D>>3]=-ta/3600.0;Lc(b,5152,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}Lc(b,5128,y)|0;ta=+h[y>>3];if(ta!=0.0){h[D>>3]=-ta/3600.0;Lc(b,5160,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}else{Lc(b,5112,y)|0;h[D>>3]=-+h[y>>3]/3600.0;Lc(b,5176,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}}else{ta=va/3600.0;h[E>>3]=ta;h[D>>3]=-ta}}while(0);h[P>>3]=0.0;Lc(b,5256,P)|0;if(+h[_>>3]==0.0){Lc(b,5248,P)|0}Wb(R,+h[D>>3],+h[E>>3],+h[P>>3]);ca=R+616|0;h[ca>>3]=+h[fa>>3]*.5+.5;ka=R+624|0;h[ka>>3]=+h[ba>>3]*.5+.5;if((Cc(b,4904)|0)!=0){Lc(b,4904,ca)|0;Lc(b,4912,ka)|0}h[R+16>>3]=+h[ca>>3];h[R+24>>3]=+h[ka>>3];ka=R+688|0;h[ka>>3]=-999.0;if((Hc(b,5656,ka)|0)==0){_b(5696);Tb(R);ea=0;i=e;return ea|0}ca=R+696|0;h[ca>>3]=-999.0;if((Ic(b,4832,ca)|0)==0){_b(5736);Tb(R);ea=0;i=e;return ea|0}ta=+h[ka>>3];h[R>>3]=ta;sa=+h[ca>>3];h[R+8>>3]=sa;ca=R+3304|0;c[ca>>2]=0;h[R+3992>>3]=ta;h[R+4e3>>3]=sa;ka=R+4008|0;h[ka>>3]=999.0;if((Lc(b,4936,ka)|0)==0){Lc(b,5776,ka)|0}ka=R+4016|0;h[ka>>3]=999.0;Lc(b,4944,ka)|0;do{if((Lc(b,5312,O)|0)==0){ka=R+128|0;if((Mc(b,5320,ka)|0)==0){if((Mc(b,5336,ka)|0)!=0){break}if((Lc(b,5344,ka)|0)!=0){break}h[ka>>3]=+h[R+120>>3];break}Pc(b,5320,32,m)|0;if(($f(m,84)|0)==0){if((Lc(b,5352,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744;break}if((Lc(b,5360,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744}}}else{h[R+128>>3]=(+h[O>>3]+-15019.81352)/365.242198781+1900.0}}while(0);Vb(R,5792,5808)|0;c[ca>>2]=0;a[f]=0;Rb(b,R,f);Sb(R);c[R+3292>>2]=0;c[R+3288>>2]=3;c[R+3312>>2]=1;ua=qa}else{Lg(l|0,j|0)|0;ka=(Oc(b,4816,N,16,l)|0)==0;Lg(R+3368|0,j|0)|0;Lg(R+3377|0,l|0)|0;if((Qc(l,4824)|0)==0){g=(Qc(l,4832)|0)==0;wa=g?1:2}else{wa=2}g=R+3386|0;a[g]=0;Oc(b,4840,N,9,g)|0;g=R+3395|0;a[g]=0;Oc(b,4848,N,9,g)|0;if((Vb(R,j,l)|0)!=0){Tb(R);ea=0;i=e;return ea|0}g=R+3260|0;if((c[g>>2]|0)==0){ma=R+3476|0;if((Oc(b,4856,N,16,ma)|0)==0?(Yc(b,4864,4872,16,ma)|0)==0:0){a[ma]=0}if((yg(ma,4880)|0)==0){c[g>>2]=-1}if(!ka){ka=R+3508|0;if((Oc(b,4888,N,16,ka)|0)==0?(Yc(b,4896,4872,16,ka)|0)==0:0){a[ka]=0}if((yg(ma,4880)|0)==0){c[g>>2]=-1}}}ma=R+616|0;h[ma>>3]=1.0;Kc(b,4904,N,ma)|0;ka=R+624|0;h[ka>>3]=1.0;Kc(b,4912,N,ka)|0;h[R+16>>3]=+h[ma>>3];h[R+24>>3]=+h[ka>>3];la=R+688|0;h[la>>3]=0.0;Kc(b,4920,N,la)|0;na=R+696|0;h[na>>3]=0.0;Kc(b,4928,N,na)|0;xa=c[R+3884>>2]|0;if((xa|0)==7){h[na>>3]=90.0- +h[na>>3];ia=74}else if((xa|0)==8){sa=+h[na>>3]+-90.0;h[na>>3]=sa;ya=sa}else{ia=74}if((ia|0)==74){ya=+h[na>>3]}sa=+h[la>>3];h[R>>3]=sa;h[R+8>>3]=ya;la=R+3992|0;if((c[R+3304>>2]|0)==0){h[la>>3]=sa;h[R+4e3>>3]=ya}else{h[la>>3]=ya;h[R+4e3>>3]=sa}la=R+3176|0;h[la>>3]=999.0;Kc(b,4936,N,la)|0;h[R+4008>>3]=+h[la>>3];la=R+3184|0;h[la>>3]=999.0;Kc(b,4944,N,la)|0;h[R+4016>>3]=+h[la>>3];c[R+3964>>2]=ma;c[R+3972>>2]=qa;c[R+3968>>2]=$;la=R+4088|0;h[la>>3]=0.0;Kc(b,4952,N,la)|0;c[f>>2]=0;Na(H|0,4960,f|0)|0;Kc(b,H,N,M)|0;c[f>>2]=1;Na(H|0,4960,f|0)|0;la=R+4104|0;Kc(b,H,N,la)|0;c[f>>2]=2;Na(H|0,4960,f|0)|0;na=R+4112|0;Kc(b,H,N,na)|0;c[f>>2]=3;Na(H|0,4960,f|0)|0;xa=R+4120|0;Kc(b,H,N,xa)|0;c[f>>2]=4;Na(H|0,4960,f|0)|0;Aa=R+4128|0;Kc(b,H,N,Aa)|0;c[f>>2]=5;Na(H|0,4960,f|0)|0;Ba=R+4136|0;Kc(b,H,N,Ba)|0;c[f>>2]=6;Na(H|0,4960,f|0)|0;Ca=R+4144|0;Kc(b,H,N,Ca)|0;c[f>>2]=7;Na(H|0,4960,f|0)|0;Da=R+4152|0;Kc(b,H,N,Da)|0;c[f>>2]=8;Na(H|0,4960,f|0)|0;Ea=R+4160|0;Kc(b,H,N,Ea)|0;c[f>>2]=9;Na(H|0,4960,f|0)|0;Fa=R+4168|0;Kc(b,H,N,Fa)|0;c[f>>2]=wa;Na(n|0,4968,f|0)|0;c[f>>2]=wa;Na(p|0,4976,f|0)|0;c[f>>2]=wa;Na(q|0,4984,f|0)|0;Ga=c[g>>2]|0;switch(Ga|0){case 7:{c[f>>2]=wa;c[f+4>>2]=0;Na(H|0,4992,f|0)|0;Kc(b,H,N,M)|0;c[f>>2]=wa;c[f+4>>2]=1;Na(H|0,4992,f|0)|0;Kc(b,H,N,la)|0;c[f>>2]=wa;c[f+4>>2]=2;Na(H|0,4992,f|0)|0;Kc(b,H,N,na)|0;c[f>>2]=wa;c[f+4>>2]=3;Na(H|0,4992,f|0)|0;Kc(b,H,N,xa)|0;c[f>>2]=wa;c[f+4>>2]=4;Na(H|0,4992,f|0)|0;Kc(b,H,N,Aa)|0;c[f>>2]=wa;c[f+4>>2]=5;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ba)|0;c[f>>2]=wa;c[f+4>>2]=6;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ca)|0;c[f>>2]=wa;c[f+4>>2]=7;Na(H|0,4992,f|0)|0;Kc(b,H,N,Da)|0;c[f>>2]=wa;c[f+4>>2]=8;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ea)|0;c[f>>2]=wa;c[f+4>>2]=9;Na(H|0,4992,f|0)|0;Kc(b,H,N,Fa)|0;ia=97;break};case 17:case 15:case 16:case 14:case 4:case 1:{Kc(b,n,N,R+4104|0)|0;Kc(b,p,N,R+4112|0)|0;ia=97;break};case 2:{Kc(b,n,N,R+4104|0)|0;Kc(b,p,N,R+4112|0)|0;Fa=R+4120|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=90.0}Kc(b,q,N,Fa)|0;ia=97;break};case 13:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,n,N,Fa)|0;ia=97;break};case 10:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,n,N,Fa)|0;Fa=R+4112|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,p,N,Fa)|0;ia=97;break};case 9:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=90.0}Kc(b,n,N,Fa)|0;ia=97;break};case 18:{Kc(b,n,N,R+4104|0)|0;ia=97;break};default:{Ha=Ga}}if((ia|0)==97){Ha=c[g>>2]|0}do{if((Ha|0)==31){if((dd(b,R)|0)==0){Ia=c[g>>2]|0;ia=102;break}else{a[R+3374|0]=65;a[R+3375|0]=78;a[R+3383|0]=65;a[R+3384|0]=78;c[g>>2]=3;break}}else{Ia=Ha;ia=102}}while(0);a:do{if((ia|0)==102){do{if((Ia|0)==32){if((kd(b,R)|0)==0){Ja=c[g>>2]|0;break}else{a[R+3375|0]=78;a[R+3384|0]=78;c[g>>2]=7;break a}}else{Ja=Ia}}while(0);if((Ja|0)==33){a[R+3374|0]=65;a[R+3375|0]=78;a[R+3383|0]=65;a[R+3384|0]=78;c[g>>2]=3}}}while(0);if((c[ja>>2]|0)>0){Rb(b,R,N)}Sb(R);Ye(R,b);c[U>>2]=0;c[V>>2]=0;ca=Kc(b,5e3,N,F)|0;Ga=Kc(b,5008,N,W)|0;Fa=Kc(b,5016,N,X)|0;Ea=Kc(b,5024,N,Y)|0;if((c[ja>>2]|0)!=2?(Da=Cc(b,5032)|0,(Da|0)!=0):0){c[g>>2]=30;Ca=R+3467|0;a[Ca+0|0]=a[5040|0]|0;a[Ca+1|0]=a[5041|0]|0;a[Ca+2|0]=a[5042|0]|0;a[Ca+3|0]=a[5043|0]|0;a[Ca+4|0]=a[5044|0]|0;a[Ca+5|0]=a[5045|0]|0;Ca=R+256|0;Ba=0;while(1){Aa=Ba+1|0;c[f>>2]=Aa;Na(H|0,5048,f|0)|0;xa=Ca+(Ba<<3)|0;h[xa>>3]=0.0;if((Lc(Da,H,xa)|0)!=0){c[U>>2]=Aa}if((Aa|0)==20){break}else{Ba=Aa}}Ba=Cc(b,5056)|0;Da=R+416|0;Ca=0;while(1){Aa=Ca+1|0;c[f>>2]=Aa;Na(H|0,5064,f|0)|0;xa=Da+(Ca<<3)|0;h[xa>>3]=0.0;if((Lc(Ba,H,xa)|0)!=0){c[V>>2]=Aa}if((Aa|0)==20){break}else{Ca=Aa}}bd(+h[ma>>3],+h[ka>>3],R,z,B)|0;bd(+h[ma>>3],+h[ka>>3]+1.0,R,A,C)|0;sa=+h[C>>3]- +h[B>>3];Ca=R+40|0;h[Ca>>3]=sa;Ba=R+32|0;h[Ba>>3]=-sa;c[R+3312>>2]=1;ac(R);h[P>>3]=+h[_>>3]*3.141592653589793/180.0;bd(+h[ma>>3],+h[ka>>3],R,z,B)|0;sa=+h[P>>3];ta=+h[ma>>3]+ +S(+sa);bd(ta,+h[ka>>3]+ +T(+sa),R,A,C)|0;sa=-+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[qa>>3]=sa;h[Ba>>3]=sa;sa=+h[P>>3];ta=+h[ma>>3]+ +T(+sa);bd(ta,+h[ka>>3]+ +S(+sa),R,A,C)|0;sa=+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[R+768>>3]=sa;h[Ca>>3]=sa;Ca=R+56|0;h[Ca>>3]=+h[F>>3];h[R+64>>3]=+h[W>>3];h[R+72>>3]=+h[X>>3];h[R+80>>3]=+h[Y>>3];Bd(2,Ca,R+88|0)|0}else{ia=121}do{if((ia|0)==121){if((Ga|ca|Fa|Ea|0)!=0){c[Z>>2]=1;Zb(R,F);break}if((Kc(b,5072,N,D)|0)==0){h[R+32>>3]=1.0;h[R+40>>3]=1.0;h[qa>>3]=1.0;h[R+768>>3]=1.0;h[_>>3]=0.0;c[Z>>2]=0;_b(5264);break}Kc(b,5080,N,E)|0;if(!(+h[D>>3]==0.0)){if(+h[ba>>3]>1.0){sa=+h[E>>3];if(sa==0.0){ia=127}else{Ka=sa}}else{ia=154}}else{ia=127}do{if((ia|0)==127){if(((((Cc(b,5088)|0)==0?(Cc(b,5096)|0)==0:0)?(Cc(b,5112)|0)==0:0)?(Cc(b,5128)|0)==0:0)?(Cc(b,5144)|0)==0:0){ia=154;break}h[y>>3]=0.0;Lc(b,5088,y)|0;sa=+h[y>>3];if(sa==0.0){Lc(b,5096,y)|0;La=+h[y>>3]}else{La=sa}if(!(La==0.0)){if(+h[D>>3]==0.0){h[D>>3]=-La/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}sa=La/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5144,y)|0;sa=+h[y>>3];if(sa!=0.0){if(+h[D>>3]==0.0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}Lc(b,5152,y)|0;sa=+h[y>>3]/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5128,y)|0;sa=+h[y>>3];if(sa!=0.0){if(+h[D>>3]==0.0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}Lc(b,5160,y)|0;sa=+h[y>>3]/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5112,y)|0;sa=+h[y>>3];if(sa!=0.0?+h[D>>3]==0.0:0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(sa==0.0){Lc(b,5176,y)|0;ta=+h[y>>3]/3600.0;h[E>>3]=ta;Ka=ta}else{Ka=sa}}}while(0);if((ia|0)==154){Ka=+h[E>>3]}if(Ka==0.0?+h[ba>>3]>1.0:0){h[E>>3]=-+h[D>>3]}h[R+776>>3]=1.0;h[R+784>>3]=1.0;Eg(G|0,0,648)|0;Eg($|0,0,648)|0;Ca=c[K>>2]|0;if((Ca|0)>0){Ba=0;do{h[G+((aa(Ca,Ba)|0)+Ba<<3)>>3]=1.0;Ba=Ba+1|0}while((Ba|0)<(Ca|0))}if((a[N]|0)==0?(Lc(b,5192,G)|0)!=0:0){Ca=c[K>>2]|0;if((Ca|0)>0){Ba=Ca;Ca=0;Da=0;while(1){c[J>>2]=0;Aa=Ca+1|0;if((Ba|0)>0){xa=0;na=Da;while(1){la=G+(na<<3)|0;h[la>>3]=(Ca|0)==(xa|0)?1.0:0.0;c[f>>2]=Aa;c[f+4>>2]=xa+1;Na(H|0,5208,f|0)|0;Ma=na+1|0;Lc(b,H,la)|0;la=(c[J>>2]|0)+1|0;c[J>>2]=la;Oa=c[K>>2]|0;if((la|0)<(Oa|0)){xa=la;na=Ma}else{Pa=Oa;Qa=Ma;break}}}else{Pa=Ba;Qa=Da}if((Aa|0)<(Pa|0)){Ba=Pa;Ca=Aa;Da=Qa}else{break}}}$b(R,+h[D>>3],+h[E>>3],G);break}if((Kc(b,5224,N,G)|0)==0){h[P>>3]=0.0;if((wa|0)==2){Kc(b,5248,N,P)|0}else{Kc(b,5256,N,P)|0}Wb(R,+h[D>>3],+h[E>>3],+h[P>>3]);break}Da=c[K>>2]|0;if((Da|0)>0){Ca=Da;Da=0;Ba=0;while(1){c[J>>2]=0;na=Da+1|0;if((Ca|0)>0){xa=0;Ma=Ba;while(1){Oa=G+(Ma<<3)|0;h[Oa>>3]=(Da|0)==(xa|0)?1.0:0.0;c[f>>2]=na;c[f+4>>2]=xa+1;Na(H|0,5232,f|0)|0;la=Ma+1|0;Kc(b,H,N,Oa)|0;Oa=(c[J>>2]|0)+1|0;c[J>>2]=Oa;Ra=c[K>>2]|0;if((Oa|0)<(Ra|0)){xa=Oa;Ma=la}else{Sa=Ra;Ta=la;break}}}else{Sa=Ca;Ta=Ba}if((na|0)<(Sa|0)){Ca=Sa;Da=na;Ba=Ta}else{break}}}$b(R,+h[D>>3],+h[E>>3],G)}}while(0);if((c[g>>2]|0)==3?(c[da>>2]|0)==2:0){Ea=R+3168|0;Fa=c[Ea>>2]|0;if((Fa|0)!=0){rd(Fa);c[Ea>>2]=0}Ea=R+3172|0;Fa=c[Ea>>2]|0;if((Fa|0)!=0){rd(Fa);c[Ea>>2]=0}c[R+1560>>2]=0;Ea=R+1568|0;Fa=R+4344|0;ca=0;do{h[Ea+(ca<<3)>>3]=0.0;h[Fa+(ca<<3)>>3]=0.0;ca=ca+1|0}while((ca|0)!=200);c[J>>2]=0;ca=0;g=0;while(1){c[f>>2]=1;c[f+4>>2]=g;Na(H|0,4992,f|0)|0;if((Kc(b,H,N,Ea+(c[J>>2]<<3)|0)|0)==0){Ga=c[J>>2]|0;h[Ea+(Ga<<3)>>3]=0.0;Ua=Ga;Va=ca}else{Ua=c[J>>2]|0;Va=ca+1|0}g=Ua+1|0;c[J>>2]=g;if((g|0)>=100){break}else{ca=Va}}c[J>>2]=0;ca=Va;g=0;while(1){c[f>>2]=2;c[f+4>>2]=g;Na(H|0,4992,f|0)|0;if((Kc(b,H,N,Ea+((c[J>>2]|0)+100<<3)|0)|0)==0){Ga=c[J>>2]|0;h[Ea+(Ga+100<<3)>>3]=0.0;Wa=Ga;Xa=ca}else{Wa=c[J>>2]|0;Xa=ca+1|0}g=Wa+1|0;c[J>>2]=g;if((g|0)>=100){break}else{ca=Xa}}if((Xa|0)>0){ca=R+3948|0;g=R+3944|0;Ga=100;ka=0;while(1){sa=+h[Ea+(((c[ca>>2]|0)*100|0)+Ga<<3)>>3];h[Fa+(Ga<<3)>>3]=sa;ta=+h[Ea+(((c[g>>2]|0)*100|0)+Ga<<3)>>3];h[Fa+(Ga+100<<3)>>3]=ta;if((ka|0)==0){Ya=sa!=0.0|ta!=0.0?Ga+1|0:0}else{Ya=ka}if((Ga|0)>0){Ga=Ga+ -1|0;ka=Ya}else{break}}Qb(R);c[d>>2]=0}}ka=R+3467|0;if(!((Ag(ka,5296,6)|0)!=0?(Ag(ka,5304,5)|0)!=0:0)){c[R+3292>>2]=-1;c[R+3288>>2]=5}do{if((Lc(b,5312,O)|0)==0){ka=R+128|0;if((Mc(b,5320,ka)|0)==0){if((Mc(b,5336,ka)|0)!=0){break}if((Lc(b,5344,ka)|0)!=0){break}h[ka>>3]=+h[R+120>>3];break}Pc(b,5320,32,m)|0;if(($f(m,84)|0)==0){if((Lc(b,5352,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744;break}if((Lc(b,5360,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744}}}else{h[R+128>>3]=(+h[O>>3]+-15019.81352)/365.242198781+1900.0}}while(0);c[R+3312>>2]=1;ua=qa}}while(0);c[R+3964>>2]=R+616;c[R+3972>>2]=ua;c[R+3968>>2]=$;c[R+3284>>2]=1;c[R+3296>>2]=0;c[R+3328>>2]=0;Yb(R);ea=R;i=e;return ea|0}function Nb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=i;i=i+96|0;f=e;g=e+16|0;if((d|0)==0){h=0;i=e;return h|0}j=Dg(d|0)|0;k=ig(1,j+1|0)|0;if((j|0)>0){l=0;do{m=a[d+l|0]|0;if((m+ -97<<24>>24&255)<26){a[k+l|0]=(m&255)+224}else{a[k+l|0]=m}l=l+1|0}while((l|0)!=(j|0))}a[k+j|0]=0;if((Dg(k|0)|0)==1){h=a[k]|0;i=e;return h|0}j=f;c[j>>2]=1314079575;c[j+4>>2]=4541761;a[f+8|0]=0;j=f+7|0;l=95;d=0;while(1){if((d|0)>0){n=d+64&255}else{n=0}a[j]=n;if((Pc(b,f,72,g)|0)==0){o=l}else{m=Dg(g|0)|0;p=ig(1,m+1|0)|0;if((m|0)>0){q=0;do{r=a[g+q|0]|0;if((r+ -97<<24>>24&255)<26){a[p+q|0]=(r&255)+224}else{a[p+q|0]=r}q=q+1|0}while((q|0)!=(m|0))}a[p+m|0]=0;q=(yg(p,k)|0)==0;hg(p);o=q?n:l}d=d+1|0;if((d|0)==27){break}else{l=o}}hg(k);h=o;i=e;return h|0}function Ob(b,c){b=b|0;c=c|0;var d=0,e=0;d=i;i=i+16|0;e=d;a[e]=0;Bc(b,c)|0;c=Mb(b,e)|0;i=d;return c|0}function Pb(b){b=b|0;var c=0,d=0,e=0;c=i;i=i+16|0;d=c;a[d]=0;e=Mb(b,d)|0;i=c;return e|0}function Qb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;b=i;i=i+176|0;d=b+88|0;e=b+40|0;f=b+16|0;g=b+56|0;j=b+80|0;k=b+168|0;l=b+32|0;m=b+72|0;n=b+8|0;o=b;p=j;c[p>>2]=1;c[p+4>>2]=1;p=c[a+3944>>2]|0;q=c[a+3948>>2]|0;if((c[a+3316>>2]|0)!=2){i=b;return}r=a+3928|0;if((yg(r,5848)|0)!=0){i=b;return}if(+h[a+((p*100|1)<<3)+1568>>3]==0.0?+h[a+((q*100|1)<<3)+1568>>3]==0.0:0){i=b;return}s=a+9312|0;t=c[s>>2]|0;if((t|0)==0){h[l>>3]=0.0;h[m>>3]=0.0;h[n>>3]=+h[a+136>>3];h[o>>3]=+h[a+144>>3]}else{bc(t,0.0,0.0,l,m);bc(c[s>>2]|0,+h[a+136>>3],+h[a+144>>3],n,o)}if((p|0)==0){u=+h[l>>3];v=+h[m>>3];w=v;x=+h[o>>3]-v;y=u;z=+h[n>>3]-u}else{u=+h[m>>3];v=+h[l>>3];w=v;x=+h[n>>3]-v;y=u;z=+h[o>>3]-u}u=x/11.0;x=z/11.0;o=ig(288,8)|0;n=ig(144,8)|0;l=ig(144,8)|0;z=w+.5;m=g+(q<<3)|0;h[m>>3]=z;s=f+(q<<3)|0;h[s>>3]=z;z=y+.5;t=g+(p<<3)|0;h[t>>3]=z;A=f+(p<<3)|0;h[A>>3]=z;B=a+3956|0;C=e+(p<<3)|0;p=e+(q<<3)|0;q=a+4064|0;y=z;D=11;E=l;F=n;G=o;while(1){h[A>>3]=y;H=E+96|0;I=11;J=E;K=F;L=G;while(1){if((Dd(f,B,e)|0)!=0){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}h[K>>3]=+h[C>>3];h[J>>3]=+h[p>>3];Wd(q,+h[C>>3],+h[p>>3],L,L+8|0)|0;h[A>>3]=x+ +h[A>>3];if((I|0)==0){break}else{I=I+ -1|0;J=J+8|0;K=K+8|0;L=L+16|0}}h[s>>3]=u+ +h[s>>3];if((D|0)==0){break}y=+h[t>>3];D=D+ -1|0;E=H;F=F+96|0;G=G+192|0}Dd(g,B,e)|0;h[C>>3]=+h[C>>3]+.0002777777777777778;Cd(e,B,f)|0;y=+h[A>>3]- +h[t>>3];u=+h[s>>3]- +h[m>>3];x=+Q(+(y*y+u*u))*3600.0;if(!(x!=0.0)){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}u=.04/x;c[k>>2]=1;C=0;G=1;a:while(1){if((G|0)>1){rd(C)}M=qd(j,2,k,1)|0;td(M,o,n,0,144,0);F=143;E=n;D=o;while(1){x=+sd(M,D);if(+P(+(x- +h[E>>3]))>u){break}if((F|0)==0){N=26;break a}else{F=F+ -1|0;E=E+8|0;D=D+16|0}}D=c[k>>2]|0;E=D+1|0;c[k>>2]=E;if((D|0)>8){N=28;break}else{C=M;G=E}}if((N|0)==26){c[k>>2]=(c[k>>2]|0)+1}else if((N|0)==28){_b(5904);c[a+1560>>2]=1}c[a+3168>>2]=M;c[a+5944>>2]=M;Dd(g,B,e)|0;h[p>>3]=+h[p>>3]+.0002777777777777778;Cd(e,B,f)|0;u=+h[A>>3]- +h[t>>3];x=+h[s>>3]- +h[m>>3];y=+Q(+(u*u+x*x))*3600.0;if(!(y!=0.0)){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}x=.04/y;c[k>>2]=1;d=M;M=1;b:while(1){if((M|0)>1){rd(d)}O=qd(j,2,k,1)|0;td(O,o,l,0,144,0);r=143;m=l;s=o;while(1){y=+sd(O,s);if(+P(+(y- +h[m>>3]))>x){break}if((r|0)==0){N=37;break b}else{r=r+ -1|0;m=m+8|0;s=s+16|0}}s=c[k>>2]|0;m=s+1|0;c[k>>2]=m;if((s|0)>8){N=39;break}else{d=O;M=m}}if((N|0)==37){c[k>>2]=(c[k>>2]|0)+1}else if((N|0)==39){_b(5904);c[a+1560>>2]=1}c[a+3172>>2]=O;c[a+5948>>2]=O;hg(o);hg(n);hg(l);i=b;return}function Rb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0,z=0.0,A=0,B=0,C=0;f=i;i=i+144|0;g=f+24|0;j=f+28|0;k=f+32|0;l=f+112|0;m=f+96|0;n=f+8|0;o=f+64|0;p=f;c[j>>2]=0;a[k]=0;a[l]=0;q=a[e]|0;if(q<<24>>24==0){r=n;c[r>>2]=1230328133;c[r+4>>2]=5787470;s=m+0|0;t=6e3|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0))}else{c[g>>2]=q<<24>>24;Na(n|0,5968,g|0)|0;c[g>>2]=a[e]|0;Na(m|0,5984,g|0)|0}if((Pc(b,n,31,l)|0)==0?(Pc(b,5472,31,l)|0)!=0:0){g=n;c[g>>2]=1230328133;c[g+4>>2]=5787470}if((Pc(b,m,31,k)|0)==0?(Pc(b,6e3,31,k)|0)!=0:0){s=m+0|0;t=6e3|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0))}g=a[l]|0;do{if(g<<24>>24==74){e=l+1|0;h[d+120>>3]=+ug(e);c[j>>2]=vg(e)|0;c[k>>2]=3492678;v=0;w=30}else if(!(g<<24>>24==66)){if((Ec(b,n,j)|0)!=0){Lc(b,n,d+120|0)|0;v=1;w=30;break}if((Ec(b,5344,j)|0)!=0){if((c[j>>2]|0)==0){c[j>>2]=1950;h[d+120>>3]=1950.0;v=0;w=30;break}else{Lc(b,5344,d+120|0)|0;v=1;w=30;break}}if((a[k]|0)!=0){if((Ag(k,5480,3)|0)==0){h[d+120>>3]=1950.0;c[j>>2]=1950;x=0;break}if((Ag(k,6016,4)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,5488,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,6024,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,6032,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0}else{v=0;w=30}}else{v=0;w=30}}else{e=l+1|0;h[d+120>>3]=+ug(e);c[j>>2]=~~+ug(e);c[k>>2]=3427142;v=0;w=30}}while(0);do{if((w|0)==30){if((c[j>>2]|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;l=d+3449|0;if((Ag(l,5656,2)|0)!=0?(Ag(l,4832,3)|0)!=0:0){x=v;break}c[k>>2]=3492678;x=v}else{x=v}}}while(0);v=d+128|0;do{if((Mc(b,5320,v)|0)==0){if((Mc(b,5336,v)|0)==0?(Lc(b,5344,v)|0)==0:0){y=+h[d+120>>3];h[v>>3]=y;z=y}else{w=43}}else{Pc(b,5320,32,o)|0;if(($f(o,84)|0)==0){if((Lc(b,5352,p)|0)!=0){y=+h[v>>3]+ +h[p>>3]/8765.812770744;h[v>>3]=y;z=y;break}if((Lc(b,5360,p)|0)!=0){y=+h[v>>3]+ +h[p>>3]/8765.812770744;h[v>>3]=y;z=y}else{w=43}}else{w=43}}}while(0);if((w|0)==43){z=+h[v>>3]}if(z==0.0){h[v>>3]=+h[d+120>>3]}do{if((a[k]|0)==0?(Pc(b,m,31,k)|0,(a[k]|0)==0):0){if((c[d+3884>>2]|0)!=7){v=d+3764|0;if((c[j>>2]|0)>1980){a[v]=3492678;a[v+1|0]=13643;a[v+2|0]=53;a[v+3|0]=0;break}else{a[v]=3427142;a[v+1|0]=13387;a[v+2|0]=52;a[v+3|0]=0;break}}}else{w=48}}while(0);do{if((w|0)==48?(m=d+3764|0,Lg(m|0,k|0)|0,(x|0)==0):0){if((Ag(m,5480,3)|0)==0){h[d+120>>3]=1950.0;break}if((Ag(m,5488,3)|0)==0){h[d+120>>3]=2.0e3;break}if((Ag(m,6016,4)|0)==0){h[d+120>>3]=2.0e3;break}if((Ag(m,6024,3)|0)==0?(c[j>>2]|0)==0:0){h[d+120>>3]=2.0e3}}}while(0);switch(a[d+3449|0]|0){case 71:{j=d+3764|0;s=j+0|0;t=6040|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 72:{j=d+3764|0;s=j+0|0;t=6088|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 65:{j=d+3764|0;a[j+0|0]=a[6104|0]|0;a[j+1|0]=a[6105|0]|0;a[j+2|0]=a[6106|0]|0;a[j+3|0]=a[6107|0]|0;a[j+4|0]=a[6108|0]|0;a[j+5|0]=a[6109|0]|0;A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 76:{j=d+3764|0;a[j+0|0]=a[5296|0]|0;a[j+1|0]=a[5297|0]|0;a[j+2|0]=a[5298|0]|0;a[j+3|0]=a[5299|0]|0;a[j+4|0]=a[5300|0]|0;a[j+5|0]=a[5301|0]|0;a[j+6|0]=a[5302|0]|0;A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 69:{j=d+3764|0;s=j+0|0;t=6056|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 83:{j=d+3764|0;s=j+0|0;t=6072|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};default:{A=d+3764|0;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return}}}function Sb(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0;d=i;e=b+3764|0;f=c[b+3260>>2]|0;if((a[e]|0)!=0){if((f|0)==0){g=0;j=3}else{k=f}}else{g=f;j=3}if((j|0)==3){a[e+0|0]=a[5296|0]|0;a[e+1|0]=a[5297|0]|0;a[e+2|0]=a[5298|0]|0;a[e+3|0]=a[5299|0]|0;a[e+4|0]=a[5300|0]|0;a[e+5|0]=a[5301|0]|0;a[e+6|0]=a[5302|0]|0;k=g}if((k|0)==-1){a[e+0|0]=a[5304|0]|0;a[e+1|0]=a[5305|0]|0;a[e+2|0]=a[5306|0]|0;a[e+3|0]=a[5307|0]|0;a[e+4|0]=a[5308|0]|0;a[e+5|0]=a[5309|0]|0}k=nc(e)|0;c[b+3884>>2]=k;do{if((k|0)!=2){g=b+3796|0;if((k|0)==1){a[g]=3492678;a[g+1|0]=13643;a[g+2|0]=53;a[g+3|0]=0;break}else{Lg(g|0,e|0)|0;break}}else{g=b+3796|0;a[g]=3427142;a[g+1|0]=13387;a[g+2|0]=52;a[g+3|0]=0}}while(0);c[b+3888>>2]=nc(b+3796|0)|0;k=b+120|0;h[b+3872>>3]=+h[k>>3];g=b+3828|0;Lg(g|0,e|0)|0;c[b+3880>>2]=nc(g)|0;h[b+3864>>3]=+h[k>>3];i=d;return}function Tb(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){i=b;return}if((c[a+3312>>2]|0)==0){hg(a);i=b;return}d=a+9312|0;e=c[d>>2]|0;if((e|0)!=0){Tb(e);c[d>>2]=0}Ub(a);d=c[a+9320>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3980>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3976>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3168>>2]|0;if((d|0)!=0){rd(d)}d=c[a+3172>>2]|0;if((d|0)!=0){rd(d)}hg(a);i=b;return}function Ub(a){a=a|0;var b=0,d=0;b=i;d=c[1654]|0;if((d|0)!=0){hg(d);c[1654]=0}d=c[6620>>2]|0;if((d|0)!=0){hg(d);c[6620>>2]=0}d=c[6624>>2]|0;if((d|0)!=0){hg(d);c[6624>>2]=0}d=c[6628>>2]|0;if((d|0)!=0){hg(d);c[6628>>2]=0}d=c[6632>>2]|0;if((d|0)!=0){hg(d);c[6632>>2]=0}d=c[6636>>2]|0;if((d|0)!=0){hg(d);c[6636>>2]=0}d=c[6640>>2]|0;if((d|0)!=0){hg(d);c[6640>>2]=0}d=c[6644>>2]|0;if((d|0)!=0){hg(d);c[6644>>2]=0}d=c[6648>>2]|0;if((d|0)!=0){hg(d);c[6648>>2]=0}d=c[6652>>2]|0;if((d|0)!=0){hg(d);c[6652>>2]=0}if((a|0)==0){i=b;return}if((c[a+3312>>2]|0)==0){i=b;return}d=c[a+9208>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9212>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9216>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9220>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9224>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9228>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9232>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9236>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9240>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9244>>2]|0;if((d|0)==0){i=b;return}hg(d);i=b;return}function Vb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+144|0;g=f;h=f+8|0;c[h>>2]=5130572;c[h+4>>2]=5265985;c[h+8>>2]=5266003;c[h+12>>2]=5128532;c[h+16>>2]=5130579;c[h+20>>2]=4674643;c[h+24>>2]=4411969;c[h+28>>2]=5132378;c[h+32>>2]=4277594;c[h+36>>2]=5392705;c[h+40>>2]=5265731;c[h+44>>2]=5390659;c[h+48>>2]=5391693;c[h+52>>2]=4277571;c[h+56>>2]=5263171;c[h+60>>2]=4476739;c[h+64>>2]=4542275;c[h+68>>2]=5197635;c[h+72>>2]=5132098;c[h+76>>2]=5194576;c[h+80>>2]=4998739;c[h+84>>2]=5390672;c[h+88>>2]=5523777;c[h+92>>2]=5001037;c[h+96>>2]=4412227;c[h+100>>2]=4412241;c[h+104>>2]=4412244;c[h+108>>2]=5260110;c[h+112>>2]=5459015;c[h+116>>2]=5460804;c[h+120>>2]=5524560;c[h+124>>2]=5787220;c[h+128>>2]=5787738;c[h+132>>2]=5656660;if((Ag(d,6128,4)|0)==0){a[d]=1313819736;a[d+1|0]=5132108;a[d+2|0]=20047;a[d+3|0]=78}j=b+3368|0;Lg(j|0,d|0)|0;k=b+3449|0;Lg(k|0,d|0)|0;l=b+3467|0;Lg(l|0,d|0)|0;do{if((Ag(d,6136,6)|0)!=0){if((Ag(d,6144,6)|0)==0){c[b+3260>>2]=-1;break}if((Qc(d,6152)|0)!=0){c[b+3260>>2]=-1;break}m=a[d]|0;if(!(m<<24>>24==65|m<<24>>24==68|m<<24>>24==82)?(a[d+1|0]|0)!=76:0){c[b+3260>>2]=0;i=f;return 0}a[k]=m;a[b+3450|0]=a[d+1|0]|0;m=a[d+2|0]|0;n=b+3451|0;do{if(!(m<<24>>24==45)){a[n]=m;o=a[d+3|0]|0;p=b+3452|0;if(o<<24>>24==45){a[p]=0;q=4;break}else{a[p]=o;a[b+3453|0]=0;q=4;break}}else{a[n]=0;q=3}}while(0);n=((a[d+q|0]|0)==45)+q|0;m=n+((a[d+n|0]|0)==45)|0;n=m+((a[d+m|0]|0)==45)|0;m=n+((a[d+n|0]|0)==45)|0;a[l]=a[d+m|0]|0;a[b+3468|0]=a[d+(m+1)|0]|0;a[b+3469|0]=a[d+(m+2)|0]|0;a[b+3470|0]=0;c[g>>2]=k;c[g+4>>2]=l;Na(j|0,6160,g|0)|0;if((a[j]|0)==32){a[j]=45}m=b+3369|0;if((a[m]|0)==32){a[m]=45}m=b+3370|0;if((a[m]|0)==32){a[m]=45}m=b+3371|0;if((a[m]|0)==32){a[m]=45}m=b+3372|0;if((a[m]|0)==32){a[m]=45}m=b+3373|0;if((a[m]|0)==32){a[m]=45}m=b+3374|0;if((a[m]|0)==32){a[m]=45}n=b+3375|0;if((a[n]|0)==32){a[n]=45}o=b+3260|0;c[o>>2]=0;p=0;r=1;while(1){if((Ag(l,h+(r<<2)|0,3)|0)==0){c[o>>2]=r;s=r}else{s=p}r=r+1|0;if((r|0)==34){break}else{p=s}}p=b+3324|0;r=c[p>>2]|0;if((r|0)==0){c[p>>2]=3;break}else if((r|0)==1){c[p>>2]=2}else if((r|0)!=2){break}if((s|0)==31){a[m]=65;a[n]=78;c[o>>2]=3;break}else if((s|0)==32){a[m]=80;a[n]=78;c[o>>2]=7;break}else{break}}else{c[b+3260>>2]=0}}while(0);do{if((Ag(e,6168,4)|0)!=0){if((Ag(e,6192,4)|0)==0){a[e]=a[d]|0;s=e+1|0;a[s+0|0]=a[6176|0]|0;a[s+1|0]=a[6177|0]|0;a[s+2|0]=a[6178|0]|0;c[b+3264>>2]=-90;s=b+3764|0;a[s]=4280403;a[s+1|0]=16720;a[s+2|0]=65;a[s+3|0]=0;c[b+3884>>2]=8;break}else{c[b+3264>>2]=0;break}}else{a[e]=a[d]|0;s=e+1|0;a[s+0|0]=a[6176|0]|0;a[s+1|0]=a[6177|0]|0;a[s+2|0]=a[6178|0]|0;c[b+3264>>2]=90;s=b+3764|0;a[s+0|0]=a[6184|0]|0;a[s+1|0]=a[6185|0]|0;a[s+2|0]=a[6186|0]|0;a[s+3|0]=a[6187|0]|0;a[s+4|0]=a[6188|0]|0;a[s+5|0]=a[6189|0]|0;c[b+3884>>2]=7}}while(0);s=b+3377|0;Lg(s|0,e|0)|0;h=b+3458|0;Lg(h|0,e|0)|0;do{if((Ag(e,6136,6)|0)!=0){if((Ag(e,6144,6)|0)==0){c[b+3260>>2]=-1;break}j=a[e]|0;if(!(j<<24>>24==65|j<<24>>24==68|j<<24>>24==82)?(a[e+1|0]|0)!=76:0){c[b+3260>>2]=0;break}a[h]=j;j=e+1|0;a[b+3459|0]=a[j]|0;k=a[e+2|0]|0;q=b+3460|0;do{if(!(k<<24>>24==45)){a[q]=k;r=a[e+3|0]|0;p=b+3461|0;if(r<<24>>24==45){a[p]=0;t=4;break}else{a[p]=r;a[b+3462|0]=0;t=4;break}}else{a[q]=0;t=3}}while(0);q=((a[e+t|0]|0)==45)+t|0;k=q+((a[e+q|0]|0)==45)|0;q=k+((a[e+k|0]|0)==45)|0;k=q+((a[e+q|0]|0)==45)|0;a[l]=a[e+k|0]|0;a[b+3468|0]=a[e+(k+1)|0]|0;a[b+3469|0]=a[e+(k+2)|0]|0;a[b+3470|0]=0;if((Ag(d,6120,3)|0)!=0?(Ag(d+1|0,6176,3)|0)!=0:0){c[b+3304>>2]=0}else{c[b+3304>>2]=1}if((a[j]|0)!=76?(a[e]|0)!=65:0){c[b+3292>>2]=0;c[b+3288>>2]=3}else{c[b+3292>>2]=1;c[b+3288>>2]=5}c[g>>2]=h;c[g+4>>2]=l;Na(s|0,6160,g|0)|0;if((a[s]|0)==32){a[s]=45}k=b+3378|0;if((a[k]|0)==32){a[k]=45}k=b+3379|0;if((a[k]|0)==32){a[k]=45}k=b+3380|0;if((a[k]|0)==32){a[k]=45}k=b+3381|0;if((a[k]|0)==32){a[k]=45}k=b+3382|0;if((a[k]|0)==32){a[k]=45}k=b+3383|0;if((a[k]|0)==32){a[k]=45}k=b+3384|0;if((a[k]|0)==32){a[k]=45}}else{c[b+3260>>2]=0}}while(0);$e(b,d);i=f;return 0}function Wb(a,b,d,e){a=a|0;b=+b;d=+d;e=+e;var f=0,g=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0;f=i;g=c[a+3316>>2]|0;j=a+760|0;h[j>>3]=b;k=a+768|0;l=d!=0.0?d:b;h[k>>3]=l;h[a+32>>3]=b;h[a+40>>3]=l;if((g|0)>0){m=(g|0)<2?g:2;g=0;n=a+832|0;while(1){o=0;p=n;while(1){h[p>>3]=(g|0)==(o|0)?1.0:0.0;o=o+1|0;if((o|0)==(m|0)){break}else{p=p+8|0}}g=g+1|0;if((g|0)==(m|0)){break}else{n=n+(m<<3)|0}}}c[a+3300>>2]=0;m=a+48|0;if(e<0.0){q=e+360.0}else{q=e}if(!(q>=360.0)){r=q}else{r=q+-360.0}h[m>>3]=r;q=r*3.141592653589793/180.0;r=+S(+q);if(b*d>0.0){s=-q}else{s=q}q=+T(+s);s=+h[j>>3];n=a+56|0;h[n>>3]=r*s;d=+h[k>>3];b=q*+P(+d);if(s<0.0){h[a+64>>3]=-b}else{h[a+64>>3]=b}b=q*+P(+s);if(d<0.0){h[a+72>>3]=b}else{h[a+72>>3]=-b}h[a+80>>3]=r*d;Bd(2,n,a+88|0)|0;lc(a);d=+h[j>>3];j=d<0.0;if((c[a+3304>>2]|0)!=0){if(j?+h[k>>3]>0.0:0){c[a+3256>>2]=1;r=+h[m>>3];b=r+-90.0;n=a+3200|0;if(b<-180.0){h[n>>3]=b+360.0;h[a+3208>>3]=r;h[a+3216>>3]=b+360.0;i=f;return}else{h[n>>3]=b;h[a+3208>>3]=r;h[a+3216>>3]=b;i=f;return}}do{if(d>0.0){if(!(+h[k>>3]<0.0)){if(!(+h[k>>3]>0.0)){break}c[a+3256>>2]=0;b=+h[m>>3]+90.0;n=a+3200|0;if(b>180.0){r=b+-360.0;h[n>>3]=r;h[a+3208>>3]=r;h[a+3216>>3]=b+-360.0;i=f;return}else{h[n>>3]=b;h[a+3208>>3]=b;h[a+3216>>3]=b;i=f;return}}else{c[a+3256>>2]=1;b=+h[m>>3];r=b+90.0;if(r>180.0){t=r+-360.0}else{t=r}h[a+3200>>3]=t;h[a+3208>>3]=b;r=b+-90.0;n=a+3216|0;h[n>>3]=r;if(!(r<-180.0)){i=f;return}h[n>>3]=r+360.0;i=f;return}}}while(0);if(!j){i=f;return}if(!(+h[k>>3]<0.0)){i=f;return}c[a+3256>>2]=0;t=+h[m>>3];r=t+-90.0;if(r<-180.0){u=r+360.0}else{u=r}h[a+3200>>3]=u;h[a+3208>>3]=u;u=t+90.0;n=a+3216|0;h[n>>3]=u;if(!(u>180.0)){i=f;return}h[n>>3]=u+-360.0;i=f;return}if(j?+h[k>>3]>0.0:0){c[a+3256>>2]=0;u=+h[m>>3];h[a+3200>>3]=u;t=u+90.0;if(t>180.0){v=t+-360.0}else{v=t}h[a+3208>>3]=v;v=u+180.0;n=a+3216|0;h[n>>3]=v;if(!(v>180.0)){i=f;return}h[n>>3]=v+-360.0;i=f;return}do{if(d>0.0){if(!(+h[k>>3]<0.0)){if(!(+h[k>>3]>0.0)){break}c[a+3256>>2]=1;v=+h[m>>3];h[a+3200>>3]=-v;u=90.0-v;if(u>180.0){w=u+-360.0}else{w=u}h[a+3208>>3]=w;h[a+3216>>3]=v;i=f;return}c[a+3256>>2]=0;v=+h[m>>3]+180.0;if(v>180.0){x=v+-360.0}else{x=v}h[a+3200>>3]=x;v=x+90.0;if(v>180.0){y=v+-360.0}else{y=v}h[a+3208>>3]=y;v=x+180.0;n=a+3216|0;h[n>>3]=v;if(!(v>180.0)){i=f;return}h[n>>3]=v+-360.0;i=f;return}}while(0);if(!j){i=f;return}if(!(+h[k>>3]<0.0)){i=f;return}c[a+3256>>2]=1;x=+h[m>>3];y=x+180.0;if(y>180.0){z=y+-360.0}else{z=y}h[a+3200>>3]=z;y=z+90.0;if(y>180.0){A=y+-360.0}else{A=y}h[a+3208>>3]=A;A=x+90.0;m=a+3216|0;h[m>>3]=A;if(!(A>180.0)){i=f;return}h[m>>3]=A+-360.0;i=f;return}function Xb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,o=0.0;e=i;i=i+16|0;f=e;if((b|0)==0){i=e;return}g=b+3312|0;if((c[g>>2]|0)==0){i=e;return}do{if((((d|0)!=0?(a[d]|0)!=0:0)?(yg(d,6200)|0)!=0:0)?(yg(d,6208)|0)!=0:0){j=nc(d)|0;if((j|0)<0){i=e;return}l=c[b+3884>>2]|0;if((j|0)!=(l|0)&(l+ -5|0)>>>0<2){i=e;return}else{Lg(b+3796|0,d|0)|0;h[b+3872>>3]=+oc(d);m=j;break}}else{n=7}}while(0);do{if((n|0)==7){d=c[b+3884>>2]|0;j=b+3796|0;Lg(j|0,b+3764|0)|0;o=+h[b+120>>3];h[b+3872>>3]=o;if((d|0)==1){if(!(o!=2.0e3)){a[j+0|0]=a[6232|0]|0;a[j+1|0]=a[6233|0]|0;a[j+2|0]=a[6234|0]|0;a[j+3|0]=a[6235|0]|0;a[j+4|0]=a[6236|0]|0;a[j+5|0]=a[6237|0]|0;m=1;break}a[j]=74;h[k>>3]=o;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Na(b+3797|0,6216,f|0)|0;l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)!=48){m=1;break}a[l]=0;m=1;break}else if((d|0)==2){if(!(o!=1950.0)){a[j+0|0]=a[6224|0]|0;a[j+1|0]=a[6225|0]|0;a[j+2|0]=a[6226|0]|0;a[j+3|0]=a[6227|0]|0;a[j+4|0]=a[6228|0]|0;a[j+5|0]=a[6229|0]|0;m=2;break}a[j]=66;h[k>>3]=o;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Na(b+3797|0,6216,f|0)|0;l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)!=48){m=2;break}a[l]=0;m=2;break}else{m=d;break}}}while(0);c[b+3888>>2]=m;if((c[g>>2]|0)==0){i=e;return}switch(m|0){case 5:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};case 8:case 7:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};case 9:case 4:case 3:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};default:{c[b+3292>>2]=0;c[b+3288>>2]=3;i=e;return}}}function Yb(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;d=i;i=i+32|0;e=d;f=d+8|0;if((b|0)==0){i=d;return}g=b+3312|0;if((c[g>>2]|0)==0){i=d;return}h=0;a:while(1){if((h|0)==0){j=f+0|0;k=6656|0;l=j+12|0;do{a[j]=a[k]|0;j=j+1|0;k=k+1|0}while((j|0)<(l|0))}else{c[e>>2]=h;Na(f|0,6672,e|0)|0}k=c[6616+(h<<2)>>2]|0;b:do{if((k|0)!=0){if((c[g>>2]|0)!=0?(j=Dg(k|0)|0,(j|0)>0):0){l=b+(h<<2)+9208|0;m=c[l>>2]|0;if((m|0)!=0){hg(m)}m=ig(j+2|0,1)|0;c[l>>2]=m;if((m|0)!=0){n=m;m=0;do{o=a[k+m|0]|0;a[n+m|0]=o<<24>>24==95?32:o;m=m+1|0;n=c[l>>2]|0}while((m|0)!=(j|0));a[n+j|0]=0}}}else{m=Wa(f|0)|0;if((m|0)!=0){if((c[g>>2]|0)==0){break}l=Dg(m|0)|0;if((l|0)<=0){break}o=b+(h<<2)+9208|0;p=c[o>>2]|0;if((p|0)!=0){hg(p)}p=ig(l+2|0,1)|0;c[o>>2]=p;if((p|0)==0){break}else{q=p;r=0}do{p=a[m+r|0]|0;a[q+r|0]=p<<24>>24==95?32:p;r=r+1|0;q=c[o>>2]|0}while((r|0)!=(l|0));a[q+l|0]=0;break}switch(h|0){case 4:{if((c[g>>2]|0)!=0){o=b+9224|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=112;a[m+2|0]=112;a[m+3|0]=109;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};case 2:{if((c[g>>2]|0)!=0){m=b+9216|0;o=c[m>>2]|0;if((o|0)!=0){hg(o)}o=ig(13,1)|0;c[m>>2]=o;if((o|0)==0){break b}a[o]=115;a[o+1|0]=103;a[o+2|0]=115;a[o+3|0]=99;a[o+4|0]=32;a[o+5|0]=45;a[o+6|0]=97;a[o+7|0]=104;a[o+8|0]=32;a[o+9|0]=37;a[o+10|0]=115;a[o+11|0]=0;break b}break};case 3:{if((c[g>>2]|0)!=0){o=b+9220|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=116;a[m+2|0]=121;a[m+3|0]=50;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};case 5:{if((c[g>>2]|0)!=0){m=b+9228|0;o=c[m>>2]|0;if((o|0)!=0){hg(o)}o=ig(13,1)|0;c[m>>2]=o;if((o|0)==0){break b}a[o]=115;a[o+1|0]=115;a[o+2|0]=97;a[o+3|0]=111;a[o+4|0]=32;a[o+5|0]=45;a[o+6|0]=97;a[o+7|0]=104;a[o+8|0]=32;a[o+9|0]=37;a[o+10|0]=115;a[o+11|0]=0;break b}break};case 1:{if((c[g>>2]|0)!=0){o=b+9212|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=117;a[m+2|0]=97;a[m+3|0]=50;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};default:{c[b+(h<<2)+9208>>2]=0;break b}}h=h+1|0;continue a}}while(0);h=h+1|0;if((h|0)==10){break}}i=d;return}function Zb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0.0,l=0.0;d=i;if((b|0)==0){i=d;return}c[a+3300>>2]=1;e=a+56|0;h[e>>3]=+h[b>>3];f=b+8|0;h[a+64>>3]=+h[f>>3];g=b+16|0;h[a+72>>3]=+h[g>>3];j=b+24|0;h[a+80>>3]=+h[j>>3];Bd(2,e,a+88|0)|0;k=+h[b>>3];l=+h[g>>3];b=a+32|0;h[b>>3]=+Q(+(k*k+l*l));l=+h[f>>3];k=+h[j>>3];j=a+40|0;h[j>>3]=+Q(+(l*l+k*k));if((c[a+3304>>2]|0)!=0){k=+h[f>>3];h[f>>3]=-+h[g>>3];h[g>>3]=-k}lc(a);c[a+3312>>2]=1;ac(a);h[a+760>>3]=+h[b>>3];h[a+768>>3]=+h[j>>3];i=d;return}function _b(a){a=a|0;var b=0;b=i;Lg(6536,a|0)|0;i=b;return}function $b(a,b,d,e){a=a|0;b=+b;d=+d;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;f=i;if((e|0)==0){i=f;return}g=a+3316|0;j=c[g>>2]|0;if((j+ -1|0)>>>0>8){k=c[a+3320>>2]|0;c[g>>2]=k;l=k}else{l=j}j=a+760|0;h[j>>3]=b;k=a+768|0;m=d!=0.0?d:b;h[k>>3]=m;h[a+32>>3]=b;h[a+40>>3]=m;if((l|0)>0){g=0;n=e;o=a+832|0;while(1){p=n+(l<<3)|0;q=0;r=n;s=o;while(1){h[s>>3]=+h[r>>3];q=q+1|0;if((q|0)==(l|0)){break}else{r=r+8|0;s=s+8|0}}s=g+1|0;if((s|0)==(l|0)){break}else{g=s;n=p;o=o+(l<<3)|0}}m=+h[j>>3];j=a+56|0;h[j>>3]=+h[e>>3]*m;if((l|0)>1){h[a+64>>3]=+h[e+8>>3]*m;m=+h[k>>3];h[a+72>>3]=+h[e+(l<<3)>>3]*m;h[a+80>>3]=+h[e+(l+1<<3)>>3]*m;t=j}else{u=j;v=11}}else{j=a+56|0;h[j>>3]=+h[e>>3]*b;u=j;v=11}if((v|0)==11){v=a+64|0;j=a+80|0;c[v+0>>2]=0;c[v+4>>2]=0;c[v+8>>2]=0;c[v+12>>2]=0;h[j>>3]=1.0;t=u}Bd(2,t,a+88|0)|0;c[a+3300>>2]=1;Ad(a+3956|0)|0;c[a+3312>>2]=1;ac(a);i=f;return}function ac(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;b=i;i=i+64|0;d=b+48|0;e=b+24|0;f=b+16|0;g=b+40|0;j=b;k=b+32|0;l=b+8|0;if(!(+h[a+136>>3]<1.5)?!(+h[a+144>>3]<1.5):0){if((c[a+3884>>2]|0)==6){i=b;return}m=a+32|0;h[m>>3]=+P(+(+h[m>>3]));n=a+40|0;h[n>>3]=+P(+(+h[n>>3]));o=+h[a+16>>3];p=+h[a+24>>3];bc(a,o,p,e,f);q=a+3304|0;r=+h[e>>3];if((c[q>>2]|0)==0){s=+h[f>>3];e=a+3828|0;ic(a,r+ +h[m>>3],s,e,j,l,d);ic(a,r,s+ +h[n>>3],e,g,k,d)}else{s=+h[f>>3];f=a+3828|0;ic(a,r+ +h[n>>3],s,f,j,l,d);ic(a,r,s+ +h[m>>3],f,g,k,d)}s=+Y(+(+h[k>>3]-p),+(+h[g>>3]-o))*180.0/3.141592653589793;if(s<-90.0){t=s+360.0}else{t=s}h[a+3208>>3]=t;s=+Y(+(+h[l>>3]-p),+(+h[j>>3]-o))*180.0/3.141592653589793;if(s<-90.0){u=s+360.0}else{u=s}h[a+3216>>3]=u;if(t<-90.0){s=t+270.0;h[a+3200>>3]=s;v=s}else{s=t+-90.0;h[a+3200>>3]=s;v=s}j=(c[q>>2]|0)==0;if(!j){s=v+90.0;q=a+48|0;h[q>>3]=s;if(s<0.0){o=s+360.0;h[q>>3]=o;w=o}else{w=s}}else{h[a+48>>3]=v;w=v}q=a+48|0;if(w<0.0){v=w+360.0;h[q>>3]=v;x=v}else{x=w}if(x>=360.0){h[q>>3]=x+-360.0}x=u-t;w=t-u;q=w>80.0&w<100.0?1:x<280.0&x>260.0?1:x<-80.0&x>-100.0&1;c[a+3256>>2]=q;l=(q|0)!=0;if(j){if(l){i=b;return}h[m>>3]=-+h[m>>3];i=b;return}else{if(!l){i=b;return}h[n>>3]=-+h[n>>3];i=b;return}}x=+h[a+48>>3];h[a+3200>>3]=x;h[a+3208>>3]=x+90.0;h[a+3216>>3]=x+180.0;i=b;return}function bc(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0.0,x=0.0,y=0.0;g=i;i=i+144|0;j=g+104|0;k=g+56|0;l=g+8|0;m=g+40|0;n=g+136|0;o=g;p=g+48|0;q=g+96|0;r=g+88|0;if((a|0)==0){i=g;return}if((c[a+3312>>2]|0)==0){i=g;return}h[a+576>>3]=b;h[a+584>>3]=d;h[a+592>>3]=+h[815];s=a+3308|0;c[s>>2]=0;t=c[a+9312>>2]|0;if((t|0)==0){_e(a,b,d,o,p)}else{bc(t,b,d,o,p)}t=a+3260|0;u=c[t>>2]|0;do{if((u|0)==30){if((bd(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==31){if((ed(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==32){if((ld(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==29){if((nd(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else{d=+h[o>>3];b=+h[p>>3];if((c[a+3324>>2]|0)==2|(u|0)<1){if(($c(d,b,a,q,r)|0)==0){v=24;break}c[s>>2]=1;w=0.0;x=0.0;break}h[q>>3]=0.0;h[r>>3]=0.0;h[l>>3]=d;h[l+8>>3]=b;if((u+ -24|0)>>>0<3){h[l+16>>3]=+((c[1632]|0)+1|0)}else{h[l+16>>3]=+h[815]}h[l+24>>3]=1.0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;c[k+16>>2]=0;c[k+20>>2]=0;c[k+24>>2]=0;c[k+28>>2]=0;if((zd(a+3368|0,a+3924|0,l,a+3956|0,k,a+4064|0,m,n,a+688|0,a+3984|0,j)|0)==0){h[q>>3]=+h[j+(c[a+3944>>2]<<3)>>3];h[r>>3]=+h[j+(c[a+3948>>2]<<3)>>3];v=24;break}else{c[s>>2]=1;w=0.0;x=0.0;break}}}while(0);if((v|0)==24){if((c[s>>2]|0)==0){if((c[t>>2]|0)>0){mc(c[a+3884>>2]|0,c[a+3888>>2]|0,+h[a+120>>3],+h[a+3872>>3],q,r,+h[a+128>>3])}t=c[a+3264>>2]|0;if((t|0)==90){b=90.0- +h[r>>3];h[r>>3]=b;y=b}else if((t|0)==-90){b=+h[r>>3]+-90.0;h[r>>3]=b;y=b}else{y=+h[r>>3]}b=+h[q>>3];h[a+600>>3]=b;h[a+608>>3]=y;w=y;x=b}else{w=0.0;x=0.0}}h[e>>3]=x;h[f>>3]=w;f=c[a+3888>>2]|0;if((f|0)<1){i=g;return}if((f|0)==6|(f|0)==10){i=g;return}w=+h[e>>3];if(w<0.0){h[e>>3]=w+360.0;i=g;return}if(!(w>360.0)){i=g;return}h[e>>3]=w+-360.0;i=g;return}function cc(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=d|0;e=e|0;f=f|0;var g=0;g=i;ic(a,b,c,a+3828|0,d,e,f);i=g;return}function dc(b,d,e,f,g){b=b|0;d=+d;e=+e;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+96|0;k=j+16|0;l=j+8|0;m=j;n=j+56|0;o=j+24|0;if((b|0)!=0?(c[b+3312>>2]|0)!=0:0){bc(b,d,e,l,m);if((c[b+3308>>2]|0)!=0){p=f;q=p;a[q]=543581775;a[q+1|0]=2123366;a[q+2|0]=8294;a[q+3|0]=32;q=p+4|0;a[q]=7364973;a[q+1|0]=28769;a[q+2|0]=112;a[q+3|0]=0;r=1;i=j;return r|0}q=c[b+3292>>2]|0;do{if((q|0)==0){p=b+3288|0;s=c[p>>2]|0;t=(s<<1)+18|0;if((t|0)>=(g|0)){if((c[b+3296>>2]|0)==0){Hg(f|0,6336,g|0)|0;u=0;break}else{Hg(f|0,6304,g|0)|0;u=0;break}}e=+h[l>>3];if(((c[b+3888>>2]|0)+ -1|0)>>>0<2){Tc(n,32,e,s);Uc(o,32,+h[m>>3],(c[p>>2]|0)+ -1|0)}else{Uc(n,32,e,s);Uc(o,32,+h[m>>3],c[p>>2]|0)}if((c[b+3296>>2]|0)==0){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0}u=g-t|0}else if((q|0)==1){t=b+3288|0;p=c[t>>2]|0;s=(p<<1)+9|0;if((s|0)>=(g|0)){if((c[b+3296>>2]|0)==0){Hg(f|0,6280,g|0)|0;u=0;break}else{Hg(f|0,6256,g|0)|0;u=0;break}}Vc(n,32,+h[l>>3],p);Vc(o,32,+h[m>>3],c[t>>2]|0);if((c[b+3296>>2]|0)==0){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0}u=g-s|0}else{u=g}}while(0);switch(c[b+3888>>2]|0){case 5:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(q){q=s;t=q;a[t]=1953259808;a[t+1|0]=7629921;a[t+2|0]=29804;a[t+3|0]=116;t=q+4|0;a[t]=8020269;a[t+1|0]=31329;a[t+2|0]=122;a[t+3|0]=0;r=1;i=j;return r|0}else{t=s;s=t;a[s]=1953259785;a[s+1|0]=7629921;a[s+2|0]=29804;a[s+3|0]=116;s=t+4|0;a[s]=8020269;a[s+1|0]=31329;a[s+2|0]=122;a[s+3|0]=0;r=1;i=j;return r|0}break};case 4:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;t=f+(Dg(f|0)|0)|0;if(s){v=t+0|0;w=6416|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=t+0|0;w=6400|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 9:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}t=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(t){t=s;q=t;a[q]=1634496544;a[q+1|0]=6384752;a[q+2|0]=24940;a[q+3|0]=97;q=t+4|0;a[q]=7628142;a[q+1|0]=29797;a[q+2|0]=116;a[q+3|0]=0;r=1;i=j;return r|0}else{q=s;s=q;a[s]=1634496521;a[s+1|0]=6384752;a[s+2|0]=24940;a[s+3|0]=97;s=q+4|0;a[s]=7628142;a[s+1|0]=29797;a[s+2|0]=116;a[s+3|0]=0;r=1;i=j;return r|0}break};case 8:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;q=f+(Dg(f|0)|0)|0;if(s){v=q+0|0;w=6480|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=q+0|0;w=6464|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 7:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(q){v=s+0|0;w=6448|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=s+0|0;w=6432|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 1:case 2:{s=b+3796|0;if((u|0)<=((Dg(s|0)|0)+1|0)){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;t=f+(Dg(f|0)|0)|0;p=q?32:9;a[t]=p;a[t+1|0]=p>>8;Fg(f|0,s|0)|0;r=1;i=j;return r|0};case 3:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;p=f+(Dg(f|0)|0)|0;if(s){v=p+0|0;w=6384|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=p+0|0;w=6368|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};default:{w=b+3288|0;Wc(n,+h[l>>3],0,c[w>>2]|0);Wc(o,+h[m>>3],0,c[w>>2]|0);w=Dg(n|0)|0;m=w+1+(Dg(o|0)|0)|0;l=b+3476|0;v=b+3508|0;x=(Dg(l|0)|0)+2+(Dg(v|0)|0)|0;p=b+3884|0;if(((c[p>>2]|0)==6?(c[b+3328>>2]|0)==1:0)?(s=x+m|0,(u|0)>(s|0)):0){if((a[l]|0)!=0){t=n+w|0;a[t]=32;a[t+1|0]=0;Fg(n|0,l|0)|0}if((a[v]|0)==0){y=s}else{t=o+(Dg(o|0)|0)|0;a[t]=32;a[t+1|0]=0;Fg(o|0,v|0)|0;y=s}}else{y=m}m=(c[b+3296>>2]|0)!=0;do{if((u|0)>(y|0)){if(m){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0;break}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0;break}}else{if(m){Hg(f|0,6496,u|0)|0;break}else{Hg(f|0,6280,u|0)|0;break}}}while(0);if((c[p>>2]|0)!=6){r=1;i=j;return r|0}m=b+3328|0;if((c[m>>2]|0)==1){r=1;i=j;return r|0}if((u|0)>(y+7|0)?(b=f+(Dg(f|0)|0)|0,k=b,a[k]=1852402720,a[k+1|0]=7235948,a[k+2|0]=28265,a[k+3|0]=110,k=b+4|0,a[k]=7496037,a[k+1|0]=29281,a[k+2|0]=114,a[k+3|0]=0,(c[p>>2]|0)!=6):0){r=1;i=j;return r|0}if((c[m>>2]|0)!=2){r=1;i=j;return r|0}if((u|0)<=(x+7+y|0)){r=1;i=j;return r|0}if((a[l]|0)!=0){y=f+(Dg(f|0)|0)|0;a[y]=32;a[y+1|0]=0;Fg(f|0,l|0)|0}if((a[v]|0)==0){r=1;i=j;return r|0}l=f+(Dg(f|0)|0)|0;a[l]=32;a[l+1|0]=0;Fg(f|0,v|0)|0;r=1;i=j;return r|0}}}if((g|0)<=0){r=0;i=j;return r|0}a[f]=0;r=0;i=j;return r|0}function ec(a,b,c,d){a=+a;b=+b;c=+c;d=+d;var e=0,f=0,g=0;e=i;i=i+48|0;f=e+24|0;g=e;Ac(a,b,1.0,f);Ac(c,d,1.0,g);d=+h[f>>3]- +h[g>>3];c=+h[f+8>>3]- +h[g+8>>3];b=+h[f+16>>3]- +h[g+16>>3];a=(d*d+0.0+c*c+b*b)*.25;b=a>1.0?1.0:a;a=+Y(+(+Q(+b)),+(+Q(+(1.0-b))))*2.0*180.0/3.141592653589793;i=e;return+a}function fc(a){a=a|0;var b=0;if((a|0)==0){b=0}else{b=(c[a+3312>>2]|0)!=0}return(b?a+3796|0:0)|0}function gc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;if((a|0)!=0?(c[a+3312>>2]|0)!=0:0){e=a+3292|0;f=c[e>>2]|0;c[e>>2]=b;if((b|0)==1&(f|0)==0?(e=a+3288|0,(c[e>>2]|0)==3):0){c[e>>2]=6}if((b|0)==0&(f|0)==1){b=a+3288|0;if((c[b>>2]|0)==5){c[b>>2]=3;g=1}else{g=1}}else{g=f}}else{g=0}i=d;return g|0}function hc(a){a=a|0;var b=0;if((a|0)==0){b=0}else{b=(c[a+3312>>2]|0)!=0}return(b?a+3764|0:0)|0}function ic(a,b,d,e,f,g,j){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0;k=i;i=i+32|0;l=k+24|0;m=k+16|0;n=k+8|0;o=k;if((a|0)==0){i=k;return}if((c[a+3312>>2]|0)==0){i=k;return}c[j>>2]=0;h[l>>3]=b;h[m>>3]=d;p=c[a+3264>>2]|0;if((p|0)==90){h[m>>3]=90.0-d}else if((p|0)==-90){h[m>>3]=d+-90.0}if((e|0)==0){q=+h[a+120>>3];r=c[a+3884>>2]|0}else{p=nc(e)|0;q=+oc(e);r=p}h[a+592>>3]=1.0;if((r|0)>0?!((r|0)==6|(r|0)==10):0){mc(r,c[a+3884>>2]|0,q,+h[a+120>>3],l,m,+h[a+128>>3])}r=c[a+3260>>2]|0;do{if((r|0)==32){if((md(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==30){if((cd(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==29){if((od(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==31){if((fd(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else{q=+h[l>>3];s=+h[m>>3];if((c[a+3324>>2]|0)==2|(r|0)<1){if((ad(q,s,a,n,o)|0)==0){break}c[j>>2]=1;break}else{if((jc(q,s,a,n,o)|0)==0){break}c[j>>2]=1;break}}}while(0);r=c[a+9312>>2]|0;s=+h[n>>3];q=+h[o>>3];do{if((r|0)==0){Ze(a,s,q,f,g);o=c[j>>2]|0;if((o|0)==0){t=+h[f>>3];if(!(t<.5)?(u=+h[g>>3],!(u<.5)):0){if(!(t>+h[a+136>>3]+.5)?!(u>+h[a+144>>3]+.5):0){v=0;break}c[j>>2]=2;v=2;break}c[j>>2]=2;v=2}else{v=o}}else{ic(r,s,q,0,f,g,j);v=c[j>>2]|0}}while(0);c[a+3308>>2]=v;h[a+600>>3]=b;h[a+608>>3]=d;h[a+576>>3]=+h[f>>3];h[a+584>>3]=+h[g>>3];i=k;return}function jc(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+112|0;j=g+80|0;k=g+48|0;l=g+16|0;m=g+8|0;n=g;h[e>>3]=0.0;h[f>>3]=0.0;o=d+3924|0;if((c[o>>2]|0)!=137){p=d+3368|0;if((xd(c[d+3960>>2]|0,p,o)|0)==0){q=p}else{r=1;i=g;return r|0}}else{q=d+3368|0}p=d+3944|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;c[j+16>>2]=0;c[j+20>>2]=0;c[j+24>>2]=0;c[j+28>>2]=0;h[j+(c[p>>2]<<3)>>3]=a;h[j+(c[d+3948>>2]<<3)>>3]=b;p=l+16|0;c[l+0>>2]=0;c[l+4>>2]=0;c[l+8>>2]=0;c[l+12>>2]=0;h[p>>3]=1.0;h[l+24>>3]=1.0;s=k+16|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;h[s>>3]=1.0;h[k+24>>3]=1.0;s=yd(q,o,j,d+688|0,d+3984|0,m,n,d+4064|0,k,d+3956|0,l)|0;if((s|0)!=0){r=s;i=g;return r|0}h[e>>3]=+h[l>>3];h[f>>3]=+h[l+8>>3];b=+h[p>>3];if(((c[d+3260>>2]|0)+ -24|0)>>>0<3){h[d+592>>3]=b+-1.0;r=0;i=g;return r|0}else{h[d+592>>3]=b;r=0;i=g;return r|0}return 0}function kc(){return c[1528]|0}function lc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0;b=i;d=a+3316|0;e=c[d>>2]|0;f=(e|0)>2?2:e;if((f+ -1|0)>>>0>8){e=c[a+3320>>2]|0;c[d>>2]=e;g=e}else{g=f}f=aa(g<<3,g)|0;e=a+3976|0;d=c[e>>2]|0;if((d|0)==0){j=gg(f)|0;c[e>>2]=j;if((j|0)==0){i=b;return}else{k=j}}else{k=d}d=a+3980|0;if((c[d>>2]|0)==0?(j=gg(f)|0,c[d>>2]=j,(j|0)==0):0){i=b;return}j=a+3956|0;c[j>>2]=137;if((g|0)==3){l=k+0|0;m=l+72|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));f=c[e>>2]|0;h[f>>3]=+h[a+56>>3];h[f+8>>3]=+h[a+64>>3];h[f+24>>3]=+h[a+72>>3];h[f+32>>3]=+h[a+80>>3];h[f+64>>3]=1.0;n=f}else if((g|0)==2){h[k>>3]=+h[a+56>>3];h[k+8>>3]=+h[a+64>>3];h[k+16>>3]=+h[a+72>>3];h[k+24>>3]=+h[a+80>>3];n=k}else if((g|0)==4){l=k+0|0;m=l+128|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));l=c[e>>2]|0;h[l>>3]=+h[a+56>>3];h[l+8>>3]=+h[a+64>>3];h[l+32>>3]=+h[a+72>>3];h[l+40>>3]=+h[a+80>>3];h[l+80>>3]=1.0;h[l+120>>3]=1.0;n=l}else{n=k}Bd(g,n,c[d>>2]|0)|0;c[a+3964>>2]=a+616;c[a+3972>>2]=a+760;c[a+3968>>2]=a+832;c[j>>2]=137;i=b;return}function mc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=+c;d=+d;e=e|0;f=f|0;g=+g;var j=0,k=0,l=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0,s=0,t=0.0;j=i;i=i+32|0;k=j+24|0;l=j+16|0;m=j+8|0;n=j;if(c==0.0){o=(a|0)==2?1950.0:2.0e3}else{o=c}if(d==0.0){p=(b|0)==2?1950.0:2.0e3}else{p=d}q=(b|0)==11;r=(a|0)==1&q&o==2.0e3;d=r?o:(a|0)==11&q?o:p;q=r?b:a;a=(b|0)==1;r=(q|0)==11&a&d==2.0e3;p=r?d:o;s=r?b:q;if((s|0)==(b|0)&p==d){i=j;return}q=p!=d;if(q){if((s|0)==2&p!=1950.0){xc(p,1950.0,e,f)}if((s|0)==1&p!=2.0e3){yc(p,2.0e3,e,f)}}r=(b|0)==2;do{if(r){if((s|0)==3){sc(e,f);break}else if((s|0)==4){if(g>0.0){wc(e,f,g);h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);p=g+-1950.0;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{wc(e,f,1950.0);h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);h[e>>3]=+h[e>>3]+ +h[m>>3]*0.0;h[f>>3]=+h[f>>3]+ +h[n>>3]*0.0;break}}else if((s|0)==1){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);p=g+-1950.0;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);break}}else{break}}else{if((b|0)==4){if((s|0)==1){if(g>0.0){vc(e,f,g);break}else{vc(e,f,2.0e3);break}}else if((s|0)==3){uc(e,f);if(g>0.0){vc(e,f,g);break}else{vc(e,f,2.0e3);break}}else if((s|0)==2){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);p=g+-2.0e3;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];vc(e,f,g);break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);h[e>>3]=+h[e>>3]+ +h[m>>3]*-50.0;h[f>>3]=+h[f>>3]+ +h[n>>3]*-50.0;vc(e,f,1950.0);break}}else{break}}else if((b|0)==3){if((s|0)==4){if(g>0.0){wc(e,f,g)}else{wc(e,f,2.0e3)}tc(e,f);break}else if((s|0)==2){rc(e,f);break}else if((s|0)==1){tc(e,f);break}else{break}}else if((b|0)==1){if((s|0)==3){uc(e,f);break}else if((s|0)==4){if(g>0.0){wc(e,f,g);break}else{wc(e,f,2.0e3);break}}else if((s|0)==2){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);p=g+-2.0e3;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);break}}else{break}}else{break}}}while(0);if(q){if(r&d!=1950.0){xc(1950.0,d,e,f)}if(a&d!=2.0e3){yc(2.0e3,d,e,f)}}d=+h[f>>3];do{if(!(d>90.0)){if(d<-90.0){h[f>>3]=-180.0-d;g=+h[e>>3]+180.0;h[e>>3]=g;t=g;break}else{t=+h[e>>3];break}}else{h[f>>3]=180.0-d;g=+h[e>>3]+180.0;h[e>>3]=g;t=g}}while(0);if(t>360.0){h[e>>3]=t+-360.0;i=j;return}if(!(t<0.0)){i=j;return}h[e>>3]=t+360.0;i=j;return}function nc(b){b=b|0;var c=0,d=0,e=0,f=0.0;c=i;d=a[b]|0;a:do{if((((((!(d<<24>>24==106|d<<24>>24==74)?(yg(b,6688)|0)!=0:0)?(yg(b,6696)|0)!=0:0)?(yg(b,6704)|0)!=0:0)?(yg(b,6712)|0)!=0:0)?(Ag(b,6720,3)|0)!=0:0)?(Ag(b,6728,3)|0)!=0:0){if((((!(d<<24>>24==98|d<<24>>24==66)?(yg(b,6736)|0)!=0:0)?(yg(b,6744)|0)!=0:0)?(Ag(b,6752,3)|0)!=0:0)?(Ag(b,6760,3)|0)!=0:0){switch(d<<24>>24){case 105:case 73:{e=11;break a;break};case 108:case 76:{e=6;break a;break};case 101:case 69:{e=4;break a;break};case 97:case 65:{e=5;break a;break};case 110:case 78:{e=7;break a;break};case 103:case 71:{e=3;break a;break};default:{if((zg(b,6768,5)|0)==0){e=10;break a}if(d<<24>>24==112|d<<24>>24==80){e=9;break a}if((Gc(b)|0)==0){e=-1;break a}f=+ug(b);if(f>1980.0){e=1;break a}e=f>1900.0?2:-1;break a}}}else{e=2}}else{e=1}}while(0);i=c;return e|0}function oc(b){b=b|0;var c=0,d=0,e=0.0;c=i;d=a[b]|0;if(!(d<<24>>24==98|d<<24>>24==66|d<<24>>24==106|d<<24>>24==74)){if((Ag(b,6752,3)|0)!=0?(Ag(b,6760,3)|0)!=0:0){if((((Ag(b,6720,3)|0)!=0?(Ag(b,6728,3)|0)!=0:0)?(Ag(b,6704,4)|0)!=0:0)?(Ag(b,6712,4)|0)!=0:0){if((d+ -49<<24>>24&255)<2){e=+ug(b)}else{e=0.0}}else{e=2.0e3}}else{e=1950.0}}else{e=+ug(b+1|0)}i=c;return+e}function pc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0;g=i;i=i+48|0;j=g;k=+h[a>>3]*3.141592653589793/180.0;l=+h[b>>3]*3.141592653589793/180.0;m=+h[c>>3]*36.0e4;n=+h[d>>3]*36.0e4;o=+T(+k);p=+S(+k);k=+T(+l);q=+S(+l);l=p*q;r=o*q;if(m!=0.0|n!=0.0){s=-(m*r)-n*p*k;t=m*l-n*o*k;u=n*q}else{s=0.0;t=0.0;u=0.0}v=0;do{h[j+(v<<3)>>3]=+h[6776+(v*48|0)>>3]*l+0.0+ +h[6784+(v*48|0)>>3]*r+ +h[6792+(v*48|0)>>3]*k+ +h[6800+(v*48|0)>>3]*s+ +h[6808+(v*48|0)>>3]*t+ +h[6816+(v*48|0)>>3]*u;v=v+1|0}while((v|0)!=6);u=+h[j>>3];t=+h[j+8>>3];s=+h[j+16>>3];k=+Q(+(u*u+t*t+s*s));r=u*-162557.0e-11+t*-3.1919e-7+s*-1.3843e-7;l=u*r;q=u+k*-162557.0e-11-l;o=t*r;p=t+k*-3.1919e-7-o;w=s*r;r=s+k*-1.3843e-7-w;k=+Q(+(r*r+(q*q+p*p)));p=u*.001245+t*-.00158+s*-659.0e-6;q=u+k*-162557.0e-11-l;l=t+k*-3.1919e-7-o;o=s+k*-1.3843e-7-w;w=+h[j+24>>3]+k*.001245-p*q;s=k*-.00158+ +h[j+32>>3]-p*l;t=k*-659.0e-6+ +h[j+40>>3]-p*o;p=q*q+l*l;u=+Q(+p);if(!(q==0.0&l==0.0)){r=+Y(+l,+q);if(r<0.0){x=r+6.283185307179586}else{x=r}}else{x=0.0}r=+Y(+o,+u);if(u>1.0e-30){y=(t*p-o*(q*w+l*s))/(u*(o*o+p));z=(q*s-l*w)/p}else{y=n;z=m}m=+h[e>>3];if(!(m>1.0e-30)){A=x*180.0;B=A/3.141592653589793;h[a>>3]=B;C=r*180.0;D=C/3.141592653589793;h[b>>3]=D;E=z/36.0e4;h[c>>3]=E;F=y/36.0e4;h[d>>3]=F;i=g;return}h[f>>3]=(o*t+(q*w+l*s))/(k*m*21.095);h[e>>3]=+h[e>>3]/k;A=x*180.0;B=A/3.141592653589793;h[a>>3]=B;C=r*180.0;D=C/3.141592653589793;h[b>>3]=D;E=z/36.0e4;h[c>>3]=E;F=y/36.0e4;h[d>>3]=F;i=g;return}function qc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0;g=i;i=i+48|0;j=g;k=+h[a>>3]*3.141592653589793/180.0;l=+h[b>>3]*3.141592653589793/180.0;m=+h[c>>3]*36.0e4;n=+h[d>>3]*36.0e4;o=+T(+k);p=+S(+k);k=+T(+l);q=+S(+l);l=p*q;r=o*q;s=+h[f>>3];t=+h[e>>3];u=s*21.095*t;if(!(m!=0.0|n!=0.0)?!(s!=0.0&t!=0.0):0){v=-.001245;w=.00158;x=659.0e-6}else{v=-(m*r)-n*p*k+u*l+-.001245;w=m*l-n*o*k+u*r+.00158;x=n*q+u*k+659.0e-6}u=l*-162557.0e-11+r*-3.1919e-7+k*-1.3843e-7;q=u*l+(l+162557.0e-11);o=u*r+(r+3.1919e-7);p=u*k+(k+1.3843e-7);u=l*.001245+r*-.00158+k*-659.0e-6;s=v+u*l;l=w+u*r;r=x+u*k;y=0;do{h[j+(y<<3)>>3]=+h[7064+(y*48|0)>>3]*q+0.0+ +h[7072+(y*48|0)>>3]*o+ +h[7080+(y*48|0)>>3]*p+ +h[7088+(y*48|0)>>3]*s+ +h[7096+(y*48|0)>>3]*l+ +h[7104+(y*48|0)>>3]*r;y=y+1|0}while((y|0)!=6);r=+h[j>>3];l=+h[j+8>>3];s=+h[j+16>>3];p=+h[j+24>>3];o=+h[j+32>>3];q=+h[j+40>>3];k=r*r+l*l;u=+Q(+k);x=k+s*s;w=+Q(+x);v=r*p+l*o;z=v+s*q;if(!(r==0.0&l==0.0)){A=+Y(+l,+r);if(A<0.0){B=A+6.283185307179586}else{B=A}}else{B=0.0}A=+Y(+s,+u);if(u>1.0e-30){C=(k*q-s*v)/(x*u);D=(r*o-l*p)/k}else{C=n;D=m}if(!(t>1.0e-30)){E=B*180.0;F=E/3.141592653589793;h[a>>3]=F;G=A*180.0;H=G/3.141592653589793;h[b>>3]=H;I=D/36.0e4;h[c>>3]=I;J=C/36.0e4;h[d>>3]=J;i=g;return}h[f>>3]=z/(w*t*21.095);h[e>>3]=+h[e>>3]/w;E=B*180.0;F=E/3.141592653589793;h[a>>3]=F;G=A*180.0;H=G/3.141592653589793;h[b>>3]=H;I=D/36.0e4;h[c>>3]=I;J=C/36.0e4;h[d>>3]=J;i=g;return}function rc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0,x=0,y=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.066988739415+q*-.872755765852+l*-.483538914632;n=p*.492728466075+q*-.45034695802+l*.744584633283;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.867600811151+q*-.188374601723+l*.460199784784),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}n=g/15.0;d=~~n;g=(n- +(d|0))*60.0;b=~~g;if(j<0.0){u=45;v=-j}else{u=43;v=j}w=~~v;j=(v- +(w|0))*60.0;x=~~j;y=gg(32)|0;c[f>>2]=d;c[f+4>>2]=b;d=f+8|0;h[k>>3]=(g- +(b|0))*60.0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[f+16>>2]=u;c[f+20>>2]=w;c[f+24>>2]=x;w=f+28|0;h[k>>3]=(j- +(x|0))*60.0;c[w>>2]=c[k>>2];c[w+4>>2]=c[k+4>>2];Na(y|0,7648,f|0)|0;w=y+6|0;if((a[w]|0)==32){a[w]=48}w=y+20|0;if((a[w]|0)==32){a[w]=48}w=c[o>>2]|0;c[f>>2]=y;za(w|0,7360,f|0)|0;h[k>>3]=s;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];x=f+8|0;h[k>>3]=t;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];za(w|0,7392,f|0)|0;hg(y);i=e;return}function sc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0.0,x=0,y=0,z=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.066988739415+q*.492728466075+l*-.867600811151;n=p*-.872755765852+q*-.45034695802+l*-.188374601723;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.483538914632+q*.744584633283+l*.460199784784),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}d=c[o>>2]|0;h[k>>3]=g;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];b=f+8|0;h[k>>3]=j;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];za(d|0,7432,f|0)|0;j=s/15.0;b=~~j;s=(j- +(b|0))*60.0;u=~~s;if(t<0.0){v=45;w=-t}else{v=43;w=t}x=~~w;t=(w- +(x|0))*60.0;y=~~t;z=gg(32)|0;c[f>>2]=b;c[f+4>>2]=u;b=f+8|0;h[k>>3]=(s- +(u|0))*60.0;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];c[f+16>>2]=v;c[f+20>>2]=x;c[f+24>>2]=y;x=f+28|0;h[k>>3]=(t- +(y|0))*60.0;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];Na(z|0,7648,f|0)|0;x=z+6|0;if((a[x]|0)==32){a[x]=48}x=z+20|0;if((a[x]|0)==32){a[x]=48}c[f>>2]=z;za(d|0,7472,f|0)|0;hg(z);i=e;return}function tc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0,x=0,y=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.054875539726+q*-.87343710801+l*-.483834985808;n=p*.494109453312+q*-.444829589425+l*.74698225181;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.867666135858+q*-.198076386122+l*.455983795705),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}n=g/15.0;d=~~n;g=(n- +(d|0))*60.0;b=~~g;if(j<0.0){u=45;v=-j}else{u=43;v=j}w=~~v;j=(v- +(w|0))*60.0;x=~~j;y=gg(32)|0;c[f>>2]=d;c[f+4>>2]=b;d=f+8|0;h[k>>3]=(g- +(b|0))*60.0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[f+16>>2]=u;c[f+20>>2]=w;c[f+24>>2]=x;w=f+28|0;h[k>>3]=(j- +(x|0))*60.0;c[w>>2]=c[k>>2];c[w+4>>2]=c[k+4>>2];Na(y|0,7648,f|0)|0;w=y+6|0;if((a[w]|0)==32){a[w]=48}w=y+20|0;if((a[w]|0)==32){a[w]=48}w=c[o>>2]|0;c[f>>2]=y;za(w|0,7504,f|0)|0;h[k>>3]=s;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];x=f+8|0;h[k>>3]=t;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];za(w|0,7536,f|0)|0;hg(y);i=e;return}function uc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0.0,x=0,y=0,z=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.054875539726+q*.494109453312+l*-.867666135858;n=p*-.87343710801+q*-.444829589425+l*-.198076386122;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.483834985808+q*.74698225181+l*.455983795705),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}d=c[o>>2]|0;h[k>>3]=g;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];b=f+8|0;h[k>>3]=j;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];za(d|0,7576,f|0)|0;j=s/15.0;b=~~j;s=(j- +(b|0))*60.0;u=~~s;if(t<0.0){v=45;w=-t}else{v=43;w=t}x=~~w;t=(w- +(x|0))*60.0;y=~~t;z=gg(32)|0;c[f>>2]=b;c[f+4>>2]=u;b=f+8|0;h[k>>3]=(s- +(u|0))*60.0;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];c[f+16>>2]=v;c[f+20>>2]=x;c[f+24>>2]=y;x=f+28|0;h[k>>3]=(t- +(y|0))*60.0;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];Na(z|0,7648,f|0)|0;x=z+6|0;if((a[x]|0)==32){a[x]=48}x=z+20|0;if((a[x]|0)==32){a[x]=48}c[f>>2]=z;za(d|0,7616,f|0)|0;hg(z);i=e;return}function vc(a,b,c){a=a|0;b=b|0;c=+c;var d=0,e=0,f=0.0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0;d=i;i=i+80|0;e=d;if(c!=2.0e3){yc(2.0e3,c,a,b)}f=+h[a>>3]*3.141592653589793/180.0;g=+h[b>>3]*3.141592653589793/180.0;j=+S(+g);k=+S(+f)*j;l=j*+T(+f);f=+T(+g);g=(c+-2.0e3)*.01;zc(1,(g*(g*(g*.001813+-59.0e-5)+-46.815)+84381.448)*48481368110953.0e-19,0.0,0.0,e);g=+h[e>>3]*k+0.0+ +h[e+8>>3]*l+ +h[e+16>>3]*f;c=+h[e+24>>3]*k+0.0+ +h[e+32>>3]*l+ +h[e+40>>3]*f;j=+h[e+48>>3]*k+0.0+ +h[e+56>>3]*l+ +h[e+64>>3]*f;f=+Y(+c,+g);if(f<0.0){m=f+6.283185307179586}else{m=f}if(!(m>6.283185307179586)){n=m;o=g*g;p=c*c;q=o+p;r=+Q(+q);s=+Y(+j,+r);t=n*180.0;u=t/3.141592653589793;h[a>>3]=u;v=s*180.0;w=v/3.141592653589793;h[b>>3]=w;i=d;return}n=m+-6.283185307179586;o=g*g;p=c*c;q=o+p;r=+Q(+q);s=+Y(+j,+r);t=n*180.0;u=t/3.141592653589793;h[a>>3]=u;v=s*180.0;w=v/3.141592653589793;h[b>>3]=w;i=d;return}function wc(a,b,c){a=a|0;b=b|0;c=+c;var d=0,e=0,f=0.0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0;d=i;i=i+80|0;e=d;f=+h[a>>3]*3.141592653589793/180.0;g=+h[b>>3]*3.141592653589793/180.0;j=+S(+g);k=+S(+f)*j;l=j*+T(+f);f=+T(+g);g=(c+-2.0e3)*.01;zc(1,(g*(g*(g*.001813+-59.0e-5)+-46.815)+84381.448)*48481368110953.0e-19,0.0,0.0,e);g=+h[e>>3]*k+0.0+ +h[e+24>>3]*l+ +h[e+48>>3]*f;j=+h[e+8>>3]*k+0.0+ +h[e+32>>3]*l+ +h[e+56>>3]*f;m=+Y(+j,+g);if(m<0.0){n=m+6.283185307179586}else{n=m}if(n>6.283185307179586){o=n+-6.283185307179586}else{o=n}n=+Y(+(+h[e+16>>3]*k+0.0+ +h[e+40>>3]*l+ +h[e+64>>3]*f),+(+Q(+(g*g+j*j))));h[a>>3]=o*180.0/3.141592653589793;h[b>>3]=n*180.0/3.141592653589793;if(!(c!=2.0e3)){i=d;return}yc(c,2.0e3,a,b);i=d;return}function xc(a,b,c,d){a=+a;b=+b;c=c|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;e=i;i=i+80|0;f=e;g=+h[c>>3]*3.141592653589793/180.0;j=+h[d>>3]*3.141592653589793/180.0;k=(a+-1850.0)/100.0;l=(b-a)/100.0;a=l*48481368110953.0e-19;b=k*(k*59.0e-6+1.3972)+2303.5548;m=k*365.0e-6;zc(323,-(a*(b+l*(.30242-k*269.0e-6+l*.017996))),a*(k*(-.85294-m)+2005.1125+l*(-.42647-m-l*.041802)),-(a*(b+l*(k*387.0e-6+1.09478+l*.018324))),f);l=+S(+j);k=+S(+g)*l;b=l*+T(+g);g=+T(+j);j=+h[f>>3]*k+0.0+ +h[f+8>>3]*b+ +h[f+16>>3]*g;l=+h[f+24>>3]*k+0.0+ +h[f+32>>3]*b+ +h[f+40>>3]*g;a=+h[f+48>>3]*k+0.0+ +h[f+56>>3]*b+ +h[f+64>>3]*g;g=+Y(+l,+j);if(g<0.0){n=g+6.283185307179586}else{n=g}if(!(n>6.283185307179586)){o=n;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}o=n+-6.283185307179586;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}function yc(a,b,c,d){a=+a;b=+b;c=c|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;e=i;i=i+80|0;f=e;g=+h[c>>3]*3.141592653589793/180.0;j=+h[d>>3]*3.141592653589793/180.0;k=(a+-2.0e3)/100.0;l=(b-a)/100.0;a=l*48481368110953.0e-19;b=k*(1.39656-k*139.0e-6)+2306.2181;m=k*217.0e-6;zc(323,-(a*(b+l*(.30188-k*344.0e-6+l*.017998))),a*(k*(-.8533-m)+2004.3109+l*(-.42665-m-l*.041833)),-(a*(b+l*(k*66.0e-6+1.09468+l*.018203))),f);l=+S(+j);k=+S(+g)*l;b=l*+T(+g);g=+T(+j);j=k*+h[f>>3]+0.0+b*+h[f+8>>3]+g*+h[f+16>>3];l=k*+h[f+24>>3]+0.0+b*+h[f+32>>3]+g*+h[f+40>>3];a=k*+h[f+48>>3]+0.0+b*+h[f+56>>3]+g*+h[f+64>>3];g=+Y(+l,+j);if(g<0.0){n=g+6.283185307179586}else{n=g}if(!(n>6.283185307179586)){o=n;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}o=n+-6.283185307179586;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}function zc(a,b,d,e,f){a=a|0;b=+b;d=+d;e=+e;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0,B=0.0,C=0.0,D=0,E=0.0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0,L=0.0,M=0,N=0.0;g=i;i=i+192|0;j=g+144|0;k=g+72|0;l=g;m=g+168|0;n=f+8|0;h[f>>3]=1.0;o=f+16|0;h[n>>3]=0.0;h[o>>3]=0.0;p=f+24|0;h[p>>3]=0.0;h[f+32>>3]=1.0;h[f+40>>3]=0.0;h[f+48>>3]=0.0;h[f+56>>3]=0.0;h[f+64>>3]=1.0;q=(a|0)/100|0;c[m>>2]=q;if((a|0)>99){r=(aa(q,-100)|0)+a|0;s=1}else{r=a;s=0}a=(r|0)/10|0;c[m+(s<<2)>>2]=a;if((r|0)>9){t=(aa(a,-10)|0)+r|0;u=s+1|0}else{t=r;u=s}c[m+(u<<2)>>2]=t;s=((t|0)>0)+u|0;h[j>>3]=b;h[j+8>>3]=d;h[j+16>>3]=e;if((s|0)<=0){i=g;return}u=l+32|0;t=l+40|0;r=l+56|0;a=l+64|0;q=l+16|0;v=l+48|0;w=l+8|0;x=l+24|0;y=k+8|0;e=b;b=1.0;d=0.0;z=1.0;A=0;while(1){h[l>>3]=1.0;h[l+8>>3]=0.0;h[l+16>>3]=0.0;h[l+24>>3]=0.0;h[l+32>>3]=1.0;h[l+40>>3]=0.0;h[l+48>>3]=0.0;h[l+56>>3]=0.0;h[l+64>>3]=1.0;B=+T(+e);C=+S(+e);D=c[m+(A<<2)>>2]|0;do{if((D|0)!=1){h[l>>3]=C;if((D|0)==2){h[q>>3]=-B;h[v>>3]=B;h[a>>3]=C;break}else{h[w>>3]=B;h[x>>3]=-B;h[u>>3]=C;break}}else{h[u>>3]=C;h[t>>3]=B;h[r>>3]=-B;h[a>>3]=C}}while(0);C=+h[p>>3];B=+h[n>>3];E=+h[f+32>>3];F=+h[f+56>>3];G=+h[f+16>>3];H=+h[f+40>>3];D=0;do{I=D*3|0;J=+h[l+(I<<3)>>3];K=I+1|0;L=+h[l+(K<<3)>>3];M=I+2|0;N=+h[l+(M<<3)>>3];h[k+(I<<3)>>3]=J*b+0.0+L*C+N*d;h[k+(K<<3)>>3]=J*B+0.0+L*E+N*F;h[k+(M<<3)>>3]=J*G+0.0+L*H+N*z;D=D+1|0}while((D|0)!=3);H=+h[k>>3];h[f>>3]=H;h[n>>3]=+h[y>>3];h[o>>3]=+h[k+16>>3];h[f+24>>3]=+h[k+24>>3];h[f+32>>3]=+h[k+32>>3];h[f+40>>3]=+h[k+40>>3];G=+h[k+48>>3];h[f+48>>3]=G;h[f+56>>3]=+h[k+56>>3];F=+h[k+64>>3];h[f+64>>3]=F;D=A+1|0;if((D|0)==(s|0)){break}e=+h[j+(D<<3)>>3];b=H;d=G;z=F;A=D}i=g;return}function Ac(a,b,c,d){a=+a;b=+b;c=+c;d=d|0;var e=0.0;e=a*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+a);h[d>>3]=+S(+e)*c*b;h[d+8>>3]=b*+T(+e)*c;h[d+16>>3]=+T(+a)*c;return}function Bc(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;if((b|0)>0){e=b}else{c[1922]=0;e=(Cc(a,7696)|0)+80-a|0}c[1922]=e;i=d;return e|0}function Cc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;e=i;f=c[1922]|0;g=(f|0)==0?256e3:f;if((g|0)>0){h=0}else{j=0;i=e;return j|0}while(1){f=h+1|0;if((a[b+h|0]|0)<1){k=h;break}if((f|0)<(g|0)){h=f}else{k=f;break}}h=b+k|0;g=h;if((k|0)<=0){j=0;i=e;return j|0}k=b;f=b;a:while(1){b=Rc(f,d,g-f|0)|0;if((b|0)==0){j=0;l=17;break}m=(b-k|0)%80|0;n=a[b+(Dg(d|0)|0)|0]|0;do{if((m|0)<=7){if(n<<24>>24>32?!(n<<24>>24==61|n<<24>>24==127):0){o=b+1|0;break}p=0-m|0;q=b+p|0;if((p|0)<0){p=b+1|0;r=f;s=q;while(1){t=(a[s]|0)==32?r:p;u=s+1|0;if(u>>>0>>0){r=t;s=u}else{v=t;break}}}else{v=f}if(b>>>0>>0){o=v}else{j=q;l=17;break a}}else{o=b+1|0}}while(0);if(o>>>0>>0){f=o}else{j=0;l=17;break}}if((l|0)==17){i=e;return j|0}return 0}function Dc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;i=i+16|0;g=f;if((a[d]|0)<64){h=Ec(b,c,e)|0;i=f;return h|0}else{Lg(g|0,c|0)|0;j=Dg(c|0)|0;a[g+j|0]=a[d]|0;a[g+(j+1)|0]=0;h=Ec(b,g,e)|0;i=f;return h|0}return 0}function Ec(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0.0,k=0.0;f=i;g=Fc(b,d)|0;if((g|0)==0){h=0;i=f;return h|0}d=(a[g]|0)==35?g+1|0:g;if((Dg(d|0)|0)>81){Hg(7704,d|0,81)|0;a[7785|0]=0}else{Lg(7704,d|0)|0}if((Gc(7704)|0)==2){d=$f(7704,68)|0;if((d|0)!=0){a[d]=101}d=$f(7704,100)|0;if((d|0)!=0){a[d]=101}d=$f(7704,69)|0;if((d|0)!=0){a[d]=101}}j=+ug(7704);k=j+.001;if(k>2147483647.0){c[e>>2]=2147483647;h=1;i=f;return h|0}if(j>=0.0){c[e>>2]=~~k;h=1;i=f;return h|0}k=j+-.001;if(k<-2147483648.0){c[e>>2]=-2147483648;h=1;i=f;return h|0}else{c[e>>2]=~~k;h=1;i=f;return h|0}return 0}function Fc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;e=i;i=i+208|0;f=e+194|0;g=e+8|0;h=e+2|0;j=e+4|0;k=e+196|0;l=e;m=e+6|0;n=e+112|0;o=e+12|0;a[g]=39;a[g+1|0]=0;a[h]=34;a[h+1|0]=0;a[j]=91;a[j+1|0]=0;a[m]=44;a[m+1|0]=0;a[k]=93;a[k+1|0]=0;a[l]=47;a[l+1|0]=0;Hg(n|0,d|0,80)|0;d=Dg(n|0)|0;p=Dg(j|0)|0;a:do{if((p|0)!=0){if((d|0)!=0?(q=p+ -1|0,r=a[j+q|0]|0,s=d+1-p|0,t=n+s|0,(s|0)>0):0){s=(p|0)==1;u=(p|0)<3;v=n;do{b:do{if((a[v]|0)==91){if(s){w=v;x=23;break a}if((a[v+q|0]|0)==r<<24>>24){if(u){w=v;x=23;break a}else{y=1}while(1){z=y+1|0;if((a[v+y|0]|0)!=(a[j+y|0]|0)){break b}if((z|0)<(p|0)){y=z}else{w=v;x=23;break a}}}}}while(0);v=v+1|0}while(v>>>0>>0)}t=Dg(n|0)|0;v=Dg(m|0)|0;if((v|0)!=0){if((t|0)!=0?(u=v+ -1|0,r=a[m+u|0]|0,q=t+1-v|0,t=n+q|0,(q|0)>0):0){q=(v|0)==1;s=(v|0)<3;z=n;while(1){c:do{if((a[z]|0)==44){if(q){w=z;x=23;break a}if((a[z+u|0]|0)==r<<24>>24){if(s){w=z;x=23;break a}else{A=1}while(1){B=A+1|0;if((a[z+A|0]|0)!=(a[m+A|0]|0)){break c}if((B|0)<(v|0)){A=B}else{w=z;x=23;break a}}}}}while(0);B=z+1|0;if(B>>>0>>0){z=B}else{C=0;break}}}else{C=0}}else{w=n;x=23}}else{w=n;x=23}}while(0);if((x|0)==23){a[w]=0;C=w+1|0}w=Cc(b,n)|0;if((w|0)==0){D=0;i=e;return D|0}n=o+0|0;b=n+100|0;do{a[n]=0;n=n+1|0}while((n|0)<(b|0));Hg(o|0,w|0,80)|0;w=Dg(o|0)|0;n=Dg(g|0)|0;d:do{if((n|0)!=0){if((w|0)!=0?(b=a[g]|0,A=n+ -1|0,m=a[g+A|0]|0,y=w+1-n|0,p=o+y|0,(y|0)>0):0){y=(n|0)==1;j=(n|0)<3;d=o;while(1){e:do{if((a[d]|0)==b<<24>>24){if(y){E=d;break d}if((a[d+A|0]|0)==m<<24>>24){if(j){E=d;break d}else{F=1}while(1){z=F+1|0;if((a[d+F|0]|0)!=(a[g+F|0]|0)){break e}if((z|0)<(n|0)){F=z}else{E=d;break d}}}}}while(0);z=d+1|0;if(z>>>0

    >>0){d=z}else{E=0;break}}}else{E=0}}else{E=o}}while(0);F=Dg(o|0)|0;n=Dg(l|0)|0;f:do{if((n|0)!=0){if((F|0)!=0?(w=a[l]|0,d=n+ -1|0,p=a[l+d|0]|0,j=F+1-n|0,m=o+j|0,(j|0)>0):0){j=(n|0)==1;A=(n|0)<3;y=o;while(1){g:do{if((a[y]|0)==w<<24>>24){if(j){G=y;break f}if((a[y+d|0]|0)==p<<24>>24){if(A){G=y;break f}else{H=1}while(1){b=H+1|0;if((a[y+H|0]|0)!=(a[l+H|0]|0)){break g}if((b|0)<(n|0)){H=b}else{G=y;break f}}}}}while(0);b=y+1|0;if(b>>>0>>0){y=b}else{G=0;break}}}else{G=0}}else{G=o}}while(0);h:do{if((E|0)==0){H=Dg(o|0)|0;n=Dg(h|0)|0;i:do{if((n|0)==0){I=o}else{if((H|0)==0){x=116;break h}l=a[h]|0;F=n+ -1|0;y=a[h+F|0]|0;m=H+1-n|0;A=o+m|0;if((m|0)<=0){x=116;break h}m=(n|0)==1;p=(n|0)<3;d=o;while(1){j:do{if((a[d]|0)==l<<24>>24){if(m){I=d;break i}if((a[d+F|0]|0)==y<<24>>24){if(p){I=d;break i}else{J=1}while(1){j=J+1|0;if((a[d+J|0]|0)!=(a[h+J|0]|0)){break j}if((j|0)<(n|0)){J=j}else{I=d;break i}}}}}while(0);j=d+1|0;if(j>>>0>>0){d=j}else{x=116;break h}}}}while(0);if((G|0)!=0&I>>>0>>0){n=I+1|0;H=Dg(n|0)|0;d=Dg(h|0)|0;if((d|0)==0){K=I;L=n;x=115;break}if((H|0)!=0?(A=a[h]|0,p=d+ -1|0,y=a[h+p|0]|0,F=H+1-d|0,H=I+(F+1)|0,(F|0)>0):0){F=(d|0)==1;m=(d|0)<3;l=n;while(1){k:do{if((a[l]|0)==A<<24>>24){if(F){K=I;L=l;x=115;break h}if((a[l+p|0]|0)==y<<24>>24){if(m){K=I;L=l;x=115;break h}else{M=1}while(1){n=M+1|0;if((a[l+M|0]|0)!=(a[h+M|0]|0)){break k}if((n|0)<(d|0)){M=n}else{K=I;L=l;x=115;break h}}}}}while(0);n=l+1|0;if(n>>>0>>0){l=n}else{N=G;break}}}else{N=G}while(1){l=N+ -1|0;if((a[l]|0)==32){N=l}else{K=I;L=N;x=115;break h}}}if((G|0)==0){l=I+1|0;H=Dg(l|0)|0;d=Dg(h|0)|0;if((d|0)==0){K=I;L=l;x=115}else{if((H|0)!=0?(m=a[h]|0,y=d+ -1|0,p=a[h+y|0]|0,F=H+1-d|0,H=I+(F+1)|0,(F|0)>0):0){F=(d|0)==1;A=(d|0)<3;n=l;do{l:do{if((a[n]|0)==m<<24>>24){if(F){K=I;L=n;x=115;break h}if((a[n+y|0]|0)==p<<24>>24){if(A){K=I;L=n;x=115;break h}else{O=1}while(1){l=O+1|0;if((a[n+O|0]|0)!=(a[h+O|0]|0)){break l}if((l|0)<(d|0)){O=l}else{K=I;L=n;x=115;break h}}}}}while(0);n=n+1|0}while(n>>>0>>0)}H=o+79|0;while(1){if((a[H]|0)==32){H=H+ -1|0}else{break}}K=I;L=H+1|0;x=115}}else{x=116}}else{if((G|0)!=0&E>>>0>>0){n=E+1|0;d=Dg(n|0)|0;A=Dg(g|0)|0;if((A|0)==0){K=E;L=n;x=115;break}if((d|0)!=0?(p=a[g]|0,y=A+ -1|0,F=a[g+y|0]|0,m=d+1-A|0,d=E+(m+1)|0,(m|0)>0):0){m=(A|0)==1;l=(A|0)<3;j=n;while(1){m:do{if((a[j]|0)==p<<24>>24){if(m){K=E;L=j;x=115;break h}if((a[j+y|0]|0)==F<<24>>24){if(l){K=E;L=j;x=115;break h}else{P=1}while(1){n=P+1|0;if((a[j+P|0]|0)!=(a[g+P|0]|0)){break m}if((n|0)<(A|0)){P=n}else{K=E;L=j;x=115;break h}}}}}while(0);n=j+1|0;if(n>>>0>>0){j=n}else{Q=G;break}}}else{Q=G}while(1){j=Q+ -1|0;if((a[j]|0)==32){Q=j}else{K=E;L=Q;x=115;break h}}}if((G|0)==0){j=E+1|0;d=Dg(j|0)|0;A=Dg(g|0)|0;if((A|0)==0){K=E;L=j;x=115}else{if((d|0)!=0?(l=a[g]|0,F=A+ -1|0,y=a[g+F|0]|0,m=d+1-A|0,d=E+(m+1)|0,(m|0)>0):0){m=(A|0)==1;p=(A|0)<3;H=j;do{n:do{if((a[H]|0)==l<<24>>24){if(m){K=E;L=H;x=115;break h}if((a[H+F|0]|0)==y<<24>>24){if(p){K=E;L=H;x=115;break h}else{R=1}while(1){j=R+1|0;if((a[H+R|0]|0)!=(a[g+R|0]|0)){break n}if((j|0)<(A|0)){R=j}else{K=E;L=H;x=115;break h}}}}}while(0);H=H+1|0}while(H>>>0>>0)}d=o+79|0;while(1){if((a[d]|0)==32){d=d+ -1|0}else{break}}K=E;L=d+1|0;x=115}}else{x=116}}}while(0);if((x|0)==115){S=K+1|0;T=L}else if((x|0)==116){L=Dg(o|0)|0;o:do{if((L|0)!=0?(K=o+L|0,(L|0)>0):0){E=o;while(1){if((a[E]|0)==61){U=E;break o}R=E+1|0;if(R>>>0>>0){E=R}else{U=0;break}}}else{U=0}}while(0);L=(U|0)==0?o+9|0:U+1|0;U=Dg(o|0)|0;p:do{if((U|0)!=0?(E=o+U|0,(U|0)>0):0){K=o;while(1){if((a[K]|0)==47){V=K;break p}d=K+1|0;if(d>>>0>>0){K=d}else{V=0;break}}}else{V=0}}while(0);S=L;T=(V|0)==0?o+79|0:V}if((c[1968]|0)==0){V=S;while(1){if((a[V]|0)==32&V>>>0>>0){V=V+1|0}else{W=V;break}}}else{W=S}a[T]=0;q:do{if((c[1968]|0)==0){S=T;while(1){V=S+ -1|0;o=a[V]|0;if(!(o<<24>>24==13|o<<24>>24==32)){break q}if(!(V>>>0>W>>>0)){break q}a[V]=0;S=V}}}while(0);T=(yg(W,7960)|0)==0;S=T?W+1|0:W;Lg(7880,S|0)|0;if((C|0)==0){D=7880;i=e;return D|0}W=Dg(C|0)|0;T=Dg(k|0)|0;r:do{if((T|0)!=0){if((W|0)!=0?(V=a[k]|0,o=T+ -1|0,L=a[k+o|0]|0,U=W+1-T|0,K=C+U|0,(U|0)>0):0){U=(T|0)==1;E=(T|0)<3;d=C;s:while(1){t:do{if((a[d]|0)==V<<24>>24){if(U){break s}if((a[d+o|0]|0)==L<<24>>24){if(E){break s}else{X=1}while(1){R=X+1|0;if((a[d+X|0]|0)!=(a[k+X|0]|0)){break t}if((R|0)<(T|0)){X=R}else{break s}}}}}while(0);R=d+1|0;if(R>>>0>>0){d=R}else{break r}}if((d|0)!=0){Y=d;x=144}}}else{Y=C;x=144}}while(0);if((x|0)==144){a[Y]=0}if((Gc(C)|0)==0){Y=Dg(C|0)|0;if((Y|0)>0){x=0;do{X=C+x|0;T=a[X]|0;if((T+ -65<<24>>24&255)<26){a[X]=(T&255)+32}x=x+1|0}while((x|0)!=(Y|0))}Y=_c(7880,C)|0;if((Y|0)==0){D=0;i=e;return D|0}Lg(7880,Y|0)|0;D=7880;i=e;return D|0}Y=vg(C)|0;a[f]=32;a[f+1|0]=0;if((Y|0)>0){C=1;x=S;while(1){Z=fg(x,f)|0;if((C|0)==(Y|0)){break}else{C=C+1|0;x=0}}if((Z|0)==0){D=0;i=e;return D|0}Lg(7880,Z|0)|0;D=7880;i=e;return D|0}if((Y|0)>=0){D=7880;i=e;return D|0}Z=0-Y|0;u:do{if((Z|0)<=1){if((S|0)==0){D=0;i=e;return D|0}else{_=S}}else{Y=1;x=S;while(1){C=$f(x,32)|0;if((C|0)==0){D=0;break}f=C+1|0;C=Y+1|0;if((C|0)<(Z|0)){Y=C;x=f}else{_=f;break u}}i=e;return D|0}}while(0);Lg(7880,_|0)|0;D=7880;i=e;return D|0}function Gc(b){b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;c=i;a:do{if((b|0)!=0?(d=a[b]|0,!(d<<24>>24==101|d<<24>>24==69|d<<24>>24==100|d<<24>>24==68)):0){e=Dg(b|0)|0;while(1){f=e+ -1|0;if((a[b+f|0]|0)==32){e=f}else{break}}if((e|0)>0){f=d;g=0;h=1;j=0;k=0;while(1){if(f<<24>>24==32){if((k|0)==0){l=g;m=h;n=0}else{o=0;break a}}else if(!(f<<24>>24==10)){b:do{if(!((f+ -48<<24>>24&255)<10)){switch(f<<24>>24){case 45:case 43:{break};case 101:case 100:case 69:case 68:case 58:case 46:{p=13;break b;break};default:{o=0;break a}}q=a[b+(j+1)|0]|0;if(q<<24>>24==43|q<<24>>24==45){o=0;break a}if((j|0)>0){switch(a[b+(j+ -1)|0]|0){case 32:case 58:case 101:case 69:case 100:case 68:{r=g;s=k;break};default:{o=0;break a}}}else{r=g;s=k}}else{p=13}}while(0);do{if((p|0)==13){p=0;if((f+ -47<<24>>24&255)<11){r=g;s=k+1|0;break}else{r=(f<<24>>24==58)+g|0;s=k;break}}}while(0);if(f<<24>>24==101|f<<24>>24==100|f<<24>>24==46){l=r;m=2;n=s}else{l=r;m=h;n=s}}else{t=g;u=h;v=k;break}q=j+1|0;if((q|0)>=(e|0)){t=l;u=m;v=n;break}f=a[b+q|0]|0;g=l;h=m;j=q;k=n}if((v|0)>0){o=(t|0)==0?u:3}else{o=0}}else{o=0}}else{o=0}}while(0);i=c;return o|0}function Hc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,j=0.0,k=0,l=0,m=0.0;e=i;f=Fc(b,c)|0;if((f|0)==0){g=0;i=e;return g|0}j=+Jc(f);c=Dg(f|0)|0;a:do{if((c|0)!=0?(b=f+c|0,(c|0)>0):0){k=f;while(1){if((a[k]|0)==58){break}l=k+1|0;if(l>>>0>>0){k=l}else{m=j;break a}}if((k|0)!=0){m=j*15.0}else{m=j}}else{m=j}}while(0);h[d>>3]=m;g=1;i=e;return g|0}function Ic(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;d=i;e=Fc(a,b)|0;if((e|0)==0){f=0}else{h[c>>3]=+Jc(e);f=1}i=d;return f|0}function Jc(b){b=b|0;var c=0,d=0.0,e=0,f=0,g=0,h=0,j=0.0,k=0,l=0.0,m=0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0,w=0.0,x=0.0;c=i;if((b|0)==0){d=0.0;i=c;return+d}e=a[b]|0;if(e<<24>>24==0){d=0.0;i=c;return+d}else{f=e;g=b}while(1){if(f<<24>>24==43){h=5;break}else if(f<<24>>24==45){j=-1.0;h=6;break}else if(!(f<<24>>24==32)){h=7;break}b=g+1|0;f=a[b]|0;g=b}if((h|0)==5){j=1.0;h=6}else if((h|0)==7){f=Dg(g|0)|0;if((g|0)==0){k=1;l=1.0;m=0}else{n=f;o=1.0;p=g;h=8}}if((h|0)==6){f=g+1|0;n=Dg(f|0)|0;o=j;p=f;h=8}a:do{if((h|0)==8){if((n|0)!=0?(f=p+n|0,(n|0)>0):0){g=p;while(1){if((a[g]|0)==44){break}b=g+1|0;if(b>>>0>>0){g=b}else{k=0;l=o;m=p;break a}}if((g|0)!=0){a[g]=32;k=0;l=o;m=p}else{k=0;l=o;m=p}}else{k=0;l=o;m=p}}}while(0);p=Dg(m|0)|0;while(1){n=p+ -1|0;if((a[m+n|0]|0)==32){p=n}else{break}}n=Dg(m|0)|0;b:do{if(!k){c:do{if((n|0)!=0?(f=m+n|0,(n|0)>0):0){b=m;while(1){if((a[b]|0)==58){break}e=b+1|0;if(e>>>0>>0){b=e}else{h=22;break c}}if((b|0)!=0){q=b}else{h=22}}else{h=22}}while(0);if((h|0)==22){if((p|0)==0){break}g=m+p|0;if((p|0)>0){r=m}else{break}while(1){if((a[r]|0)==32){break}f=r+1|0;if(f>>>0>>0){r=f}else{break b}}if((r|0)==0){break}else{q=r}}a[q]=0;o=+(vg(m)|0);a[q]=58;g=q+1|0;f=Dg(g|0)|0;d:do{if((f|0)!=0?(e=q+(f+1)|0,(f|0)>0):0){s=g;while(1){if((a[s]|0)==58){t=s;h=35;break d}u=s+1|0;if(u>>>0>>0){s=u}else{h=31;break}}}else{h=31}}while(0);e:do{if((h|0)==31){f=Dg(g|0)|0;if((f|0)!=0?(s=q+(f+1)|0,(f|0)>0):0){f=g;do{if((a[f]|0)==32){t=f;h=35;break e}f=f+1|0}while(f>>>0>>0)}s=Dg(g|0)|0;f:do{if((s|0)!=0?(f=q+(s+1)|0,(s|0)>0):0){e=g;while(1){if((a[e]|0)==46){break}b=e+1|0;if(b>>>0>>0){e=b}else{v=0.0;break f}}v=+ug(g)}else{v=0.0}}while(0);if((a[g]|0)==0){w=v;x=0.0}else{w=+(vg(g)|0);x=0.0}}}while(0);if((h|0)==35){a[t]=0;j=+(vg(g)|0);a[t]=58;w=j;x=+ug(t+1|0)}d=l*(o+w/60.0+x/3600.0);i=c;return+d}}while(0);if((Gc(m)|0)!=2){d=l*+(vg(m)|0);i=c;return+d}t=$f(m,68)|0;if((t|0)!=0){a[t]=101}t=$f(m,100)|0;if((t|0)!=0){a[t]=101}t=$f(m,69)|0;if((t|0)!=0){a[t]=101}d=l*+ug(m);i=c;return+d}function Kc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;i=i+16|0;g=f;if((a[d]|0)<64){h=Lc(b,c,e)|0;i=f;return h|0}else{Lg(g|0,c|0)|0;j=Dg(c|0)|0;a[g+j|0]=a[d]|0;a[g+(j+1)|0]=0;h=Lc(b,g,e)|0;i=f;return h|0}return 0}function Lc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;e=i;f=Fc(b,c)|0;if((f|0)==0){g=0;i=e;return g|0}c=(a[f]|0)==35?f+1|0:f;if((Dg(c|0)|0)>81){Hg(7704,c|0,81)|0;a[7785|0]=0}else{Lg(7704,c|0)|0}if((Gc(7704)|0)==2){c=$f(7704,68)|0;if((c|0)!=0){a[c]=101}c=$f(7704,100)|0;if((c|0)!=0){a[c]=101}c=$f(7704,69)|0;if((c|0)!=0){a[c]=101}}h[d>>3]=+ug(7704);g=1;i=e;return g|0}function Mc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0;f=i;g=Fc(b,d)|0;if((g|0)==0){j=0;i=f;return j|0}d=$f(g,47)|0;b=$f(g,45)|0;if(d>>>0>g>>>0){a[d]=0;k=~~+ug(g);a[d]=47;l=d+1|0;d=$f(l,47)|0;if((d|0)==0){m=$f(l,45)|0}else{m=d}if(!(m>>>0>g>>>0)){j=0;i=f;return j|0}a[m]=0;d=~~+ug(l);a[m]=47;l=~~+ug(m+1|0);m=(k|0)>31;n=m?k:l;o=m?l:k;if(n>>>0<50){p=n+2e3|0}else{p=(n|0)<100?n+1900|0:n}n=((p|0)%100|0|0)!=0|((p|0)%400|0|0)==0?(p&3|0)==0?29:28:28;c[7796>>2]=n;k=d+ -1|0;d=c[7792+(k<<2)>>2]|0;if((o|0)>(d|0)){q=d}else{q=(o|0)<1?1:o}r=(n|0)==28?365.0:366.0;n=q+ -1|0;if((k|0)>0){q=0;o=n;while(1){d=(c[7792+(q<<2)>>2]|0)+o|0;l=q+1|0;if((l|0)==(k|0)){s=d;break}else{q=l;o=d}}}else{s=n}h[e>>3]=+(p|0)+ +(s|0)/r;j=1;i=f;return j|0}if(!(b>>>0>g>>>0)){j=0;i=f;return j|0}a[b]=0;s=~~+ug(g);a[b]=45;p=b+1|0;b=$f(p,45)|0;do{if(b>>>0>g>>>0){a[b]=0;n=~~+ug(p);a[b]=45;o=b+1|0;q=$f(o,84)|0;if(q>>>0>g>>>0){a[q]=0;k=~~+ug(o);a[q]=84;t=k;u=n;v=q;break}else{t=~~+ug(o);u=n;v=q;break}}else{t=1;u=1;v=0}}while(0);b=(s|0)<32;p=b?t+1900|0:s;q=b?s:t;t=((p|0)%100|0|0)!=0|((p|0)%400|0|0)==0?(p&3|0)==0?29:28:28;c[7796>>2]=t;s=u+ -1|0;u=c[7792+(s<<2)>>2]|0;if((q|0)>(u|0)){w=u}else{w=(q|0)<1?1:q}r=(t|0)==28?365.0:366.0;t=w+ -1|0;if((s|0)>0){w=0;q=t;while(1){u=(c[7792+(w<<2)>>2]|0)+q|0;b=w+1|0;if((b|0)==(s|0)){x=u;break}else{w=b;q=u}}}else{x=t}h[e>>3]=+(p|0)+ +(x|0)/r;if(!(v>>>0>g>>>0)){j=1;i=f;return j|0}x=v+1|0;v=$f(x,58)|0;do{if(v>>>0>g>>>0){a[v]=0;p=~~+ug(x);a[v]=58;t=v+1|0;q=$f(t,58)|0;if(q>>>0>g>>>0){a[q]=0;w=~~+ug(t);a[q]=58;y=p;z=w;A=+ug(q+1|0);break}else{y=p;z=~~+ug(t);A=0.0;break}}else{y=0;z=0;A=0.0}}while(0);h[e>>3]=+h[e>>3]+(A+(+(y|0)*3600.0+ +(z|0)*60.0))/86400.0/r;j=1;i=f;return j|0}function Nc(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+32|0;h=g+8|0;j=g+16|0;k=g;c[h>>2]=d;Na(j|0,7840,h|0)|0;do{if((Cc(b,j)|0)==0){c[h>>2]=d;Na(j|0,7856,h|0)|0;if((Cc(b,j)|0)!=0){l=k;c[l>>2]=627012389;c[l+4>>2]=6566448;break}c[h>>2]=d;Na(j|0,7864,h|0)|0;if((Cc(b,j)|0)!=0){l=k;c[l>>2]=627012389;c[l+4>>2]=6566704;break}if((Cc(b,j)|0)==0){m=0;i=g;return m|0}else{l=k;c[l>>2]=627012389;c[l+4>>2]=6566704;break}}else{a[k+0|0]=a[7848|0]|0;a[k+1|0]=a[7849|0]|0;a[k+2|0]=a[7850|0]|0;a[k+3|0]=a[7851|0]|0;a[k+4|0]=a[7852|0]|0;a[k+5|0]=a[7853|0]|0}}while(0);c[1968]=1;l=1;n=e;e=f;while(1){c[h>>2]=d;c[h+4>>2]=l;Na(j|0,k|0,h|0)|0;o=Fc(b,j)|0;if((o|0)==0){p=l;break}q=Dg(o|0)|0;if((q|0)>=(n|0)){r=13;break}Lg(e|0,o|0)|0;s=l+1|0;if((s|0)<500){l=s;n=n-q|0;e=e+q|0}else{p=s;break}}do{if((r|0)==13){if((n|0)>1){Hg(e|0,o|0,n+ -1|0)|0;a[e+n|0]=0;p=l;break}else{a[f]=a[o]|0;p=l;break}}}while(0);c[1968]=0;m=(p|0)>1|0;i=g;return m|0}function Oc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;g=i;i=i+16|0;h=g;do{if((a[d]|0)<64){j=Fc(b,c)|0;if((j|0)!=0){if((Dg(j|0)|0)<(e|0)){Lg(f|0,j|0)|0;k=1;break}if((e|0)>1){Hg(f|0,j|0,e+ -1|0)|0;k=1;break}else{a[f]=a[j]|0;k=1;break}}else{k=0}}else{Lg(h|0,c|0)|0;j=Dg(c|0)|0;a[h+j|0]=a[d]|0;a[h+(j+1)|0]=0;j=Fc(b,h)|0;if((j|0)!=0){if((Dg(j|0)|0)<(e|0)){Lg(f|0,j|0)|0;k=1;break}if((e|0)>1){Hg(f|0,j|0,e+ -1|0)|0;k=1;break}else{a[f]=a[j]|0;k=1;break}}else{k=0}}}while(0);i=g;return k|0}function Pc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=i;g=Fc(b,c)|0;do{if((g|0)!=0){if((Dg(g|0)|0)<(d|0)){Lg(e|0,g|0)|0;h=1;break}if((d|0)>1){Hg(e|0,g|0,d+ -1|0)|0;h=1;break}else{a[e]=a[g]|0;h=1;break}}else{h=0}}while(0);i=f;return h|0}function Qc(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;d=i;e=Dg(b|0)|0;a:do{if(!((b|0)==0|(c|0)==0)){f=Dg(c|0)|0;if((f|0)!=0){if((e|0)!=0?(g=a[c]|0,h=f+ -1|0,j=a[c+h|0]|0,k=e+1-f|0,l=b+k|0,(k|0)>0):0){k=(f|0)==1;m=(f|0)<3;n=b;while(1){b:do{if((a[n]|0)==g<<24>>24){if(k){o=n;break a}if((a[n+h|0]|0)==j<<24>>24){if(m){o=n;break a}else{p=1}while(1){q=p+1|0;if((a[n+p|0]|0)!=(a[c+p|0]|0)){break b}if((q|0)<(f|0)){p=q}else{o=n;break a}}}}}while(0);q=n+1|0;if(q>>>0>>0){n=q}else{o=0;break}}}else{o=0}}else{o=b}}else{o=0}}while(0);i=d;return o|0}function Rc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;e=i;if((b|0)==0|(c|0)==0){f=0;i=e;return f|0}g=Dg(c|0)|0;if((g|0)==0){f=b;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}do{if((g|0)<3){h=a[c]|0;j=h<<24>>24;if(!((h+ -97<<24>>24&255)<26)){if((h+ -65<<24>>24&255)<26){k=j+32&255}else{k=h}}else{k=j+224&255}if((g|0)>1){j=a[c+1|0]|0;l=j<<24>>24;if((j+ -97<<24>>24&255)<26){m=h;n=j;o=k;p=l+224&255;q=0;break}if((j+ -65<<24>>24&255)<26){m=h;n=j;o=k;p=l+32&255;q=0}else{m=h;n=j;o=k;p=j;q=0}}else{m=h;n=32;o=k;p=32;q=0}}else{h=ig(g,1)|0;j=0;do{l=a[c+j|0]|0;r=l&255;do{if(!((l+ -97<<24>>24&255)<26)){if((l+ -65<<24>>24&255)<26){a[h+j|0]=r+32;break}else{a[h+j|0]=l;break}}else{a[h+j|0]=r+224}}while(0);j=j+1|0}while((j|0)!=(g|0));j=g+ -1|0;m=a[c]|0;n=a[c+j|0]|0;o=a[h]|0;p=a[h+j|0]|0;q=h}}while(0);k=d+1-g|0;d=b+k|0;a:do{if((k|0)>0){j=g+ -1|0;r=(g|0)>1;if((g|0)==2){l=b;while(1){s=a[l]|0;if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24?(s=a[l+j|0]|0,s<<24>>24==n<<24>>24|s<<24>>24==p<<24>>24):0){break}s=l+1|0;if(s>>>0>>0){l=s}else{break a}}if((q|0)==0){f=l;i=e;return f|0}hg(q);f=l;i=e;return f|0}else if((g|0)==1){h=b;while(1){s=a[h]|0;if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24){break}s=h+1|0;if(s>>>0>>0){h=s}else{break a}}if((q|0)==0){f=h;i=e;return f|0}hg(q);f=h;i=e;return f|0}else{l=b;b:while(1){s=a[l]|0;c:do{if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24?(t=a[l+j|0]|0,t<<24>>24==n<<24>>24|t<<24>>24==p<<24>>24):0){if(r){u=1}else{break b}while(1){t=a[l+u|0]|0;if(!(t<<24>>24==(a[c+u|0]|0))?!(t<<24>>24==(a[q+u|0]|0)):0){break c}u=u+1|0;if((u|0)>=(g|0)){break b}}}}while(0);s=l+1|0;if(s>>>0>>0){l=s}else{break a}}if((q|0)==0){f=l;i=e;return f|0}hg(q);f=l;i=e;return f|0}}}while(0);if((q|0)==0){f=0;i=e;return f|0}hg(q);f=0;i=e;return f|0}function Sc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;a:do{if(!((b|0)==0|(c|0)==0)){f=Dg(c|0)|0;if((f|0)!=0){if((d|0)!=0?(g=a[c]|0,h=f+ -1|0,j=a[c+h|0]|0,k=d+1-f|0,l=b+k|0,(k|0)>0):0){k=(f|0)==1;m=b;while(1){b:do{if((a[m]|0)==g<<24>>24){if(k){n=m;break a}if((a[m+h|0]|0)==j<<24>>24){if((f|0)<3){n=m;break a}else{o=1}while(1){p=o+1|0;if((a[m+o|0]|0)!=(a[c+o|0]|0)){break b}if((p|0)<(f|0)){o=p}else{n=m;break a}}}}}while(0);p=m+1|0;if(p>>>0>>0){m=p}else{n=0;break}}}else{n=0}}else{n=b}}else{n=0}}while(0);i=e;return n|0}function Tc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0;g=i;i=i+80|0;j=g;l=g+16|0;if(e<0.0){m=-e;n=-1.0}else{m=e;n=1.0}e=n*+qa(+m,360.0);if(e<0.0){o=e+360.0}else{o=e}e=o/15.0;p=~~e;o=(e- +(p|0))*60.0;q=~~o;e=(o- +(q|0))*60.0;do{if((f|0)<=5){if((f|0)>4){r=e>59.99999;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8008,j|0)|0;break}if((f|0)>3){s=e>59.9999;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,8032,j|0)|0;break}if((f|0)>2){r=e>59.999;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8056,j|0)|0;break}if((f|0)>1){s=e>59.99;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,8080,j|0)|0;break}if((f|0)>0){r=e>59.9;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8104,j|0)|0;break}else{s=~~(e+.5);r=(s|0)>59;t=(r&1)+q|0;u=(t|0)>59;c[j>>2]=((u&1)+p|0)%24|0;c[j+4>>2]=u?0:t;c[j+8>>2]=r?0:s;Na(l|0,8128,j|0)|0;break}}else{s=e>59.999999;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,7984,j|0)|0}}while(0);j=d+ -1|0;if((Dg(l|0)|0)<(j|0)){Lg(b|0,l|0)|0;i=g;return}else{Hg(b|0,l|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Uc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;g=i;i=i+96|0;j=g;l=g+24|0;if(e<0.0){m=-e;n=-1.0}else{m=e;n=1.0}e=n*+qa(+m,360.0);if(!(e<=-180.0)){o=e}else{o=e+360.0}if(o<0.0){p=-o;q=45}else{p=o;q=43}r=~~p;o=(p- +(r|0))*60.0;s=~~o;p=(o- +(s|0))*60.0;do{if((f|0)<=5){if((f|0)>4){t=p>59.99999;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8168,j|0)|0;break}if((f|0)>3){u=p>59.9999;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8192,j|0)|0;break}if((f|0)>2){t=p>59.999;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8216,j|0)|0;break}if((f|0)>1){u=p>59.99;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8240,j|0)|0;break}if((f|0)>0){t=p>59.9;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8264,j|0)|0;break}else{u=~~(p+.5);t=(u|0)>59;v=(t&1)+s|0;w=(v|0)>59;c[j>>2]=q&255;c[j+4>>2]=(w&1)+r;c[j+8>>2]=w?0:v;c[j+12>>2]=t?0:u;Na(l|0,8288,j|0)|0;break}}else{u=p>59.999999;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8144,j|0)|0}}while(0);j=d+ -1|0;if((Dg(l|0)|0)<(j|0)){Lg(b|0,l|0)|0;i=g;return}else{Hg(b|0,l|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Vc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0;g=i;i=i+80|0;j=g;l=g+72|0;m=g+8|0;if(e<0.0){n=-e;o=-1.0}else{n=e;o=1.0}e=o*+qa(+n,360.0);if(!(e<=-180.0)){p=e}else{p=e+360.0}q=f+4|0;if((f|0)>0){c[j>>2]=q;c[j+4>>2]=f;Na(l|0,8312,j|0)|0;h[k>>3]=p;c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];Na(m|0,l|0,j|0)|0}else{c[j>>2]=q;Na(l|0,8328,j|0)|0;c[j>>2]=~~p;Na(m|0,l|0,j|0)|0}j=d+ -1|0;if((Dg(m|0)|0)<(j|0)){Lg(b|0,m|0)|0;i=g;return}else{Hg(b|0,m|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Wc(a,b,d,e){a=a|0;b=+b;d=d|0;e=e|0;var f=0,g=0,j=0,l=0;f=i;i=i+16|0;g=f;j=f+8|0;l=(e|0)>0;if((d|0)>0){if(l){c[g>>2]=d;c[g+4>>2]=e;Na(j|0,8312,g|0)|0;h[k>>3]=b;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];Na(a|0,j|0,g|0)|0;i=f;return}else{c[g>>2]=d;Na(j|0,8336,g|0)|0;c[g>>2]=~~b;Na(a|0,j|0,g|0)|0;i=f;return}}else{if(l){c[g>>2]=e;Na(j|0,7976,g|0)|0;h[k>>3]=b;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];Na(a|0,j|0,g|0)|0;i=f;return}else{c[g>>2]=~~b;Na(a|0,7968,g|0)|0;i=f;return}}}function Xc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=i;i=i+32|0;e=d;f=_c(a,b)|0;if((f|0)==0){g=0;i=d;return g|0}Lg(e|0,f|0)|0;h[c>>3]=+ug(e);g=1;i=d;return g|0}function Yc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;g=i;h=gg(2e3)|0;if((Nc(b,c,2e3,h)|0)==0){hg(h);j=0;i=g;return j|0}c=_c(h,d)|0;do{if((c|0)!=0){if((Dg(c|0)|0)<(e|0)){Lg(f|0,c|0)|0;k=1;break}if((e|0)>1){Hg(f|0,c|0,e+ -1|0)|0;k=1;break}else{a[f]=a[c]|0;k=1;break}}else{k=0}}while(0);hg(h);j=k;i=g;return j|0}function Zc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=i;g=_c(b,c)|0;do{if((g|0)!=0){if((Dg(g|0)|0)<(d|0)){Lg(e|0,g|0)|0;h=1;break}if((d|0)>1){Hg(e|0,g|0,d+ -1|0)|0;h=1;break}else{a[e]=a[g]|0;h=1;break}}else{h=0}}while(0);i=f;return h|0}function _c(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=i;i=i+2032|0;e=d+2024|0;f=d+2018|0;g=d+2016|0;h=d+2e3|0;j=d;a[f]=91;a[f+1|0]=0;a[g]=93;a[g+1|0]=0;Lg(h|0,c|0)|0;c=Qc(h,f)|0;f=(c|0)!=0;if(f){a[c]=0;k=0}else{k=0}while(1){l=k+1|0;if((a[b+k|0]|0)==0){m=6;break}if((l|0)<57600){k=l}else{m=4;break}}if((m|0)==4){n=l;o=Dg(h|0)|0}else if((m|0)==6){l=Dg(h|0)|0;if((k|0)>0){n=k;o=l}else{p=0;i=d;return p|0}}l=b+n|0;n=l;k=b;while(1){q=Sc(k,h,n-k|0)|0;if((q|0)==0){p=0;m=34;break}r=a[q+o|0]|0;s=a[q+ -1|0]|0;if(!(r<<24>>24>32?!(r<<24>>24==61|r<<24>>24==127):0)){if((q|0)==(b|0)){t=b;m=14;break}if(s<<24>>24==9|s<<24>>24==32){t=q;m=14;break}}s=q+1|0;if(s>>>0>>0){k=s}else{p=0;m=34;break}}if((m|0)==14){if((t|0)==0){p=0;i=d;return p|0}k=t+o|0;while(1){o=a[k]|0;if(!(o<<24>>24==61|o<<24>>24==32)){break}k=k+1|0}if((k|0)==0){p=0;i=d;return p|0}Eg(j|0,0,2e3)|0;o=a[k]|0;a:do{if(o<<24>>24==34){t=k;l=0;while(1){b=t+1|0;n=a[b]|0;if(n<<24>>24==34|n<<24>>24==0){break a}if((l|0)>=2e3){break a}a[j+l|0]=n;t=b;l=l+1|0}}else{l=o;t=0;b=k;while(1){if(l<<24>>24==9|l<<24>>24==32){break a}if(!(l<<24>>24>0&(t|0)<2e3)){break a}n=b+1|0;a[j+t|0]=l;l=a[n]|0;t=t+1|0;b=n}}}while(0);if(!f){Lg(8344,j|0)|0;p=8344;i=d;return p|0}f=c+1|0;c=Qc(f,g)|0;if((c|0)==0){p=8344;i=d;return p|0}a[c]=0;c=vg(f)|0;if((c|0)<=0){p=8344;i=d;return p|0}a[e]=32;a[e+1|0]=44;a[e+2|0]=0;f=fg(j,e)|0;if((c|0)>1){j=1;while(1){g=fg(0,e)|0;k=j+1|0;if((k|0)==(c|0)){u=g;break}else{j=k}}}else{u=f}if((u|0)==0){p=8344;i=d;return p|0}Lg(8344,u|0)|0;p=8344;i=d;return p|0}else if((m|0)==34){i=d;return p|0}return 0}function $c(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0;g=i;j=c[d+3260>>2]|0;k=+h[d>>3];l=+h[d+8>>3];m=+h[d+32>>3];n=+h[d+40>>3];o=+h[d+48>>3]*3.141592653589793/180.0;p=+S(+o);q=+T(+o);r=a- +h[d+16>>3];a=b- +h[d+24>>3];do{if((c[d+3300>>2]|0)==0){if(m==0.0|n==0.0){h[e>>3]=0.0;h[f>>3]=0.0;s=2;i=g;return s|0}else{b=r*m;t=a*n;if(!(o!=0.0)){u=b;v=t;break}u=b*p-t*q;v=t*p+b*q;break}}else{u=r*+h[d+56>>3]+a*+h[d+64>>3];v=r*+h[d+72>>3]+a*+h[d+80>>3]}}while(0);w=(c[d+3304>>2]|0)==0;a=w?v:u;r=w?u:v;h[e>>3]=k+r;h[f>>3]=l+a;if((j|0)<1){s=0;i=g;return s|0}v=k*3.141592653589793/180.0;k=l*3.141592653589793/180.0;u=w?k:v;o=w?v:k;v=r*3.141592653589793/180.0;r=a*3.141592653589793/180.0;a=v*v;b=a+r*r;t=+S(+u);x=+T(+u);a:do{switch(j|0){case 11:{y=u+r;z=o+v;break};case 32:case 33:case 31:case 3:{if(b>1.0){s=1;i=g;return s|0}A=t-r*x;if(A==0.0){s=1;i=g;return s|0}else{B=o+ +Y(+v,+A);y=+X(+((r*t+x)*+S(+(B-o))/A));z=B;break a}break};case 6:{if(b>=9.869604401089369){s=1;i=g;return s|0}B=+Q(+b);A=+S(+B);if(B!=0.0){C=+T(+B)/B}else{C=1.0}B=x*A+r*t*C;if(B>1.0|B<-1.0){s=1;i=g;return s|0}D=A-x*B;A=t*v*C;if(D==0.0&A==0.0){s=1;i=g;return s|0}else{y=+W(+B);z=o+ +Y(+A,+D);break a}break};case 22:{D=n*p+m*q;A=(D==0.0?3.141592653589793:D*3.141592653589793)/180.0;D=k+A;B=+T(+k);E=+S(+k);F=+Q(+((E+1.0)*.5));G=+T(+D)/+Q(+((+S(+D)+1.0)*.5))-B/F;D=A/(G==0.0?1.0:G);G=m*p-n*q;A=(G==0.0?3.141592653589793:G*3.141592653589793)/180.0;G=A*.5;H=E*2.0*+T(+G);I=A*+Q(+((E*+S(+G)+1.0)*.5))/(H==0.0?1.0:H);if(!(v==0.0&r==0.0)){H=r+B*D/F;F=H/D;B=4.0-a/(I*I*4.0)-F*F;if(B>4.0|B<2.0){s=1;i=g;return s|0}F=+Q(+B)*.5;B=H*F/D;if(+P(+B)>1.0){s=1;i=g;return s|0}D=+W(+B);B=+S(+D);if(+P(+B)<1.0e-5){s=1;i=g;return s|0}H=v*F/(I*2.0*B);if(+P(+H)>1.0){s=1;i=g;return s|0}else{y=D;z=o+ +W(+H)*2.0;break a}}else{y=u;z=o}break};case 5:{H=(4.0-b)/(b+4.0);if(+P(+H)>1.0){s=1;i=g;return s|0}D=H+1.0;B=x*H+r*t*D*.5;if(+P(+B)>1.0){s=1;i=g;return s|0}H=+W(+B);B=+S(+H);if(+P(+B)<1.0e-5){s=1;i=g;return s|0}I=v*D/(B*2.0);if(+P(+I)>1.0){s=1;i=g;return s|0}D=+W(+I);I=+T(+H);F=+S(+D);G=x*I+1.0+t*B*F;if(+P(+G)<1.0e-5){s=1;i=g;return s|0}if(+P(+((t*I-x*B*F)*2.0/G-r))>1.0e-5){J=3.141592653589795-D}else{J=D}y=H;z=o+J;break};case 20:case 28:{H=u+r;if(+P(+H)>1.5707963267948974){s=1;i=g;return s|0}D=+S(+H);if(+P(+v)>D*6.28318530717959*.5){s=1;i=g;return s|0}if(D>1.0e-5){y=H;z=o+v/D}else{y=H;z=o}break};case 27:{H=t-r*x;if(H==0.0){s=1;i=g;return s|0}D=o+ +Y(+v,+H);G=+S(+(D-o));if(G==0.0){s=1;i=g;return s|0}F=H/G;if(F>1.0|F<-1.0){s=1;i=g;return s|0}G=+V(+F);if(u<0.0){y=-G;z=D}else{y=G;z=D}break};case 12:{D=n*p+m*q;G=D==0.0?1.0:D;D=(l*.5+45.0)*3.141592653589793/180.0;F=+_(+(+U(+D)));H=G*3.141592653589793/180.0/(+_(+(+U(+(G*.5*.01745329252+D))))-F);D=+S(+k);G=o+v/(!(D<=0.0)?D:1.0);if(+P(+(G-o))>6.28318530717959){s=1;i=g;return s|0}if(H!=0.0){K=(r+F*H)/H}else{K=0.0}y=+X(+(+Z(+K)))*2.0+-1.5707963267948974;z=G;break};case 4:{if(b>1.0){s=1;i=g;return s|0}G=+Q(+(1.0-b));H=r*t+x*G;if(H>1.0|H<-1.0){s=1;i=g;return s|0}F=t*G-r*x;if(F==0.0&v==0.0){s=1;i=g;return s|0}else{y=+W(+H);z=o+ +Y(+v,+F);break a}break};case 16:{F=1.0/+U(+u)-r;if(u<0.0){L=-F}else{L=F}y=+W(+((x*x*(1.0-(a+F*F))+1.0)*(1.0/(x*2.0))));z=o- +Y(+v,+L)/x;break};default:{y=0.0;z=0.0}}}while(0);if(z-o>3.141592653589795){M=z+-6.28318530717959}else{M=z}if(M-o<-3.141592653589795){N=M+6.28318530717959}else{N=M}if(N<0.0){O=N+6.28318530717959}else{O=N}h[e>>3]=O*180.0/3.141592653589793;h[f>>3]=y*180.0/3.141592653589793;s=0;i=g;return s|0}function ad(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0,N=0.0,O=0.0,R=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0;g=i;j=+h[d>>3];k=+h[d+8>>3];l=+h[d+16>>3];m=+h[d+24>>3];n=+h[d+32>>3];o=+h[d+40>>3];p=+h[d+48>>3]*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=c[d+3260>>2]|0;t=(s|0)>0;if(t){u=(c[d+3304>>2]|0)==0;v=j*3.141592653589793/180.0;w=k*3.141592653589793/180.0;x=u?w:v;y=u?v:w;w=a-(u?j:k);v=l*n;if(v>180.0|v<-180.0){if(w>360.0){z=a+-360.0}else{z=a}if(w<0.0){A=z+360.0}else{A=z}}else{if(w>180.0){B=a+-360.0}else{B=a}if(w<-180.0){A=B+360.0}else{A=B}}B=A*3.141592653589793/180.0;w=b*3.141592653589793/180.0;z=+S(+w);v=+T(+w);C=B-y;D=A;E=z;F=w;G=x;H=z*+T(+C);I=B;J=y;K=v;L=v*+T(+x)+z*+S(+x)*+S(+C)}else{D=a;E=0.0;F=0.0;G=0.0;H=0.0;I=0.0;J=0.0;K=0.0;L=0.0}a:do{switch(s|0){case 22:{a=(I-J)*.5;if(+P(+a)>1.5707963267948974){M=1;i=g;return M|0}C=o*q+n*r;x=(C==0.0?3.141592653589793:C*3.141592653589793)/180.0;C=k*3.141592653589793/180.0;z=x+C;v=+T(+C);y=+S(+C);C=+Q(+((y+1.0)*.5));B=+T(+z)/+Q(+((+S(+z)+1.0)*.5))-v/C;z=x/(B==0.0?1.0:B);B=n*q-o*r;x=(B==0.0?3.141592653589793:B*3.141592653589793)/180.0;B=x*.5;w=y*2.0*+T(+B);A=+S(+F);N=+Q(+((A*+S(+a)+1.0)*.5));if(+P(+N)<1.0e-5){M=3;i=g;return M|0}else{O=+T(+a)*A*x*+Q(+((y*+S(+B)+1.0)*.5))/(w==0.0?1.0:w)*2.0/N;R=z*+T(+F)/N-v*z/C;break a}break};case 3:case 32:case 33:case 31:{if(!(L<=0.0)){C=+T(+G);z=+S(+G);v=+S(+(I-J));N=K*C+E*z*v;O=H/N;R=(K*z-E*C*v)/N;break a}else{M=1;i=g;return M|0}break};case 16:{N=+U(+G);v=1.0/N;C=N*-2.0;z=N*N;w=N/3.0;N=C*C;B=(J-I)*+T(+G);y=F-G;x=v*(y*(C*.5+y*(z*.5+N*-.125+y*(w*.5+(z*C*-.25+C*N*.0625)+y*(z*.1875*N+(z*z*-.125-C*.25*w)-N*N*.0390625))))+1.0);N=B*B;if((c[d+3300>>2]|0)==0){W=n/+P(+n)}else{w=+h[d+56>>3];W=w/+P(+w)}O=(1.0-N/6.0)*B*x*W;R=v-(1.0-N*.5)*x;break};case 27:{if(G==0.0){M=1;i=g;return M|0}else{O=H;R=(+S(+G)-E*+S(+(I-J)))/+T(+G);break a}break};case 12:{x=o*q+n*r;N=x==0.0?1.0:x;x=(k*.5+45.0)*3.141592653589793/180.0;v=+_(+(+U(+x)));B=N*3.141592653589793/180.0/(+_(+(+U(+(N*.5*.01745329252+x))))-v);x=+S(+(k*3.141592653589793/180.0));N=+U(+(F*.5+.7853981633974487));if(N<1.0e-5){M=2;i=g;return M|0}else{O=(I-J)*(!(x<=0.0)?x:1.0);R=B*+_(+N)-v*B;break a}break};case 6:{B=+T(+G);v=+S(+G);N=+S(+(I-J));x=K*B+E*v*N;w=x<-1.0?-1.0:x;x=+V(+(w>1.0?1.0:w));if(x!=0.0){X=x/+T(+x)}else{X=1.0}O=H*X;R=(K*v-E*B*N)*X;break};case 20:case 28:{if(+P(+F)>1.5707963267948974){M=1;i=g;return M|0}if(+P(+G)>1.5707963267948974){M=1;i=g;return M|0}else{O=E*(I-J);R=F-G;break a}break};case 11:{O=I-J;R=F-G;break};case 4:{if(L<0.0){M=1;i=g;return M|0}else{O=H;R=K*+S(+G)-E*+T(+G)*+S(+(I-J));break a}break};case 5:{if(+P(+F)>1.5707963267948974){M=1;i=g;return M|0}N=+T(+G);B=+S(+G);v=+S(+(I-J));x=K*N+1.0+E*B*v;if(+P(+x)<1.0e-5){M=1;i=g;return M|0}else{w=2.0/x;O=H*w;R=(K*B-E*N*v)*w;break a}break};default:{O=H;R=0.0}}}while(0);if(t){Y=O*180.0/3.141592653589793;Z=R*180.0/3.141592653589793}else{Y=D-j;Z=b-k}t=(c[d+3304>>2]|0)==0;k=t?Z:Y;b=t?Y:Z;if((c[d+3300>>2]|0)==0){if(p!=0.0){$=q*b+r*k;aa=q*k-r*b}else{$=b;aa=k}if(n!=0.0){ba=$/n}else{ba=$}if(o!=0.0){ca=ba;da=aa/o}else{ca=ba;da=aa}}else{ca=b*+h[d+88>>3]+k*+h[d+96>>3];da=b*+h[d+104>>3]+k*+h[d+112>>3]}k=l+ca;h[e>>3]=k;do{if((s|0)==11){ca=+h[d+136>>3];if(k>ca){l=k-360.0/n;if(!(l>0.0)){break}h[e>>3]=l;break}if(k<0.0?(l=k+360.0/n,l<=ca):0){h[e>>3]=l}}}while(0);h[f>>3]=m+da;M=0;i=g;return M|0}function bd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0;g=i;j=c[d+3268>>2]|0;k=c[d+3272>>2]|0;l=a- +h[d+616>>3];a=b- +h[d+624>>3];b=l*l;m=a*a;n=l*b;o=a*m;p=b+m;q=+h[d+256>>3]+l*+h[d+264>>3]+a*+h[d+272>>3]+b*+h[d+280>>3]+m*+h[d+288>>3]+a*l*+h[d+296>>3];if((j|0)>6){r=q+n*+h[d+304>>3]+o*+h[d+312>>3];if((j|0)>8){s=p*+h[d+336>>3]+(r+a*b*+h[d+320>>3]+m*l*+h[d+328>>3])+p*l*+h[d+344>>3]+p*a*+h[d+352>>3]}else{s=r}}else{s=q}q=+h[d+416>>3]+l*+h[d+424>>3]+a*+h[d+432>>3]+b*+h[d+440>>3]+m*+h[d+448>>3]+a*l*+h[d+456>>3];if((k|0)>6){r=q+n*+h[d+464>>3]+o*+h[d+472>>3];if((k|0)>8){t=p*+h[d+496>>3]+(r+a*b*+h[d+480>>3]+l*m*+h[d+488>>3])+p*l*+h[d+504>>3]+p*a*+h[d+512>>3]}else{t=r}}else{t=q}q=t*3.141592653589793/180.0;t=+h[d+696>>3]*3.141592653589793/180.0;r=+U(+t);a=1.0-q*r;p=+Y(+(s*3.141592653589793/180.0/+S(+t)),+a);t=+h[d+688>>3]*3.141592653589793/180.0+p;if(!(t<0.0)){u=t;v=u*180.0;w=v/3.141592653589793;h[e>>3]=w;x=+S(+p);y=q+r;z=a/y;A=x/z;B=+X(+A);C=B*180.0;D=C/3.141592653589793;h[f>>3]=D;i=g;return 0}u=t+6.28318530717959;v=u*180.0;w=v/3.141592653589793;h[e>>3]=w;x=+S(+p);y=q+r;z=a/y;A=x/z;B=+X(+A);C=B*180.0;D=C/3.141592653589793;h[f>>3]=D;i=g;return 0}function cd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0,M=0,N=0,O=0,Q=0,R=0,T=0,V=0,W=0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0,va=0.0,wa=0.0,xa=0,ya=0.0,za=0.0,Aa=0.0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0;g=i;j=c[d+3268>>2]|0;k=c[d+3272>>2]|0;l=+U(+(b*3.141592653589793/180.0));b=+h[d+696>>3]*3.141592653589793/180.0;m=+U(+b);n=a*3.141592653589793/180.0- +h[d+688>>3]*3.141592653589793/180.0;a=+S(+n);o=(1.0-m*a/l)/(m+a/l);l=+S(+b)*+U(+n)*(1.0-m*o)*180.0/3.141592653589793;m=o*180.0/3.141592653589793;o=l*+h[d+88>>3]+m*+h[d+96>>3];n=l*+h[d+104>>3]+m*+h[d+112>>3];b=+h[d+256>>3];a=+h[d+264>>3];p=+h[d+272>>3];q=+h[d+280>>3];r=+h[d+288>>3];s=+h[d+296>>3];t=q*2.0;u=r*2.0;v=d+304|0;w=d+312|0;x=(j|0)>8;y=d+320|0;z=d+328|0;A=d+336|0;B=d+344|0;C=d+352|0;D=+h[d+416>>3];E=+h[d+424>>3];F=+h[d+432>>3];G=+h[d+440>>3];H=+h[d+448>>3];I=+h[d+456>>3];J=G*2.0;K=H*2.0;L=(k|0)>6;M=d+464|0;N=d+472|0;O=(k|0)>8;k=d+480|0;Q=d+488|0;R=d+496|0;T=d+504|0;V=d+512|0;a:do{if((j|0)>6){W=0;X=o;Y=n;while(1){Z=Y*X;_=X*X;$=Y*Y;aa=X*_;ba=Y*$;ca=Y*_;da=$*X;ea=$+_;fa=+h[v>>3];ga=+h[w>>3];ha=b+X*a+Y*p+_*q+$*r+Z*s+aa*fa+ba*ga;ia=a+X*t+Y*s+_*fa*3.0;fa=X*s+(p+Y*u)+$*ga*3.0;if(x){ga=+h[y>>3];ja=+h[z>>3];ka=+h[A>>3];la=+h[B>>3];ma=+h[C>>3];na=ka*2.0;oa=ha+ca*ga+da*ja+ea*ka+ea*X*la+ea*Y*ma;pa=($+_*3.0)*la+($*ja+(ia+Z*ga*2.0)+X*na)+Z*ma*2.0;qa=($*3.0+_)*ma+(fa+_*ga+Z*ja*2.0+Y*na+Z*la*2.0)}else{oa=ha;pa=ia;qa=fa}fa=D+X*E+Y*F+_*G+$*H+Z*I;ia=E+X*J+Y*I;ha=X*I+(F+Y*K);if(L){la=+h[M>>3];na=+h[N>>3];ja=fa+aa*la+ba*na;ba=ia+_*la*3.0;la=ha+$*na*3.0;if(O){na=+h[k>>3];aa=+h[Q>>3];ga=+h[R>>3];ma=+h[T>>3];ka=+h[V>>3];ra=ga*2.0;sa=ja+ca*na+da*aa+ea*ga+ea*X*ma+ea*Y*ka;ta=($+_*3.0)*ma+($*aa+(ba+Z*na*2.0)+X*ra)+Z*ka*2.0;ua=($*3.0+_)*ka+(la+_*na+Z*aa*2.0+Y*ra+Z*ma*2.0)}else{sa=ja;ta=ba;ua=la}}else{sa=fa;ta=ia;ua=ha}ha=oa-l;ia=sa-m;fa=pa*ua-qa*ta;la=(qa*ia-ha*ua)/fa;ba=(ha*ta-pa*ia)/fa;fa=X+la;ia=Y+ba;if(+P(+la)<5.0e-7?+P(+ba)<5.0e-7:0){va=fa;wa=ia;break a}xa=W+1|0;if((xa|0)<50){W=xa;X=fa;Y=ia}else{va=fa;wa=ia;break}}}else{W=0;Y=o;X=n;while(1){ia=X*Y;fa=Y*Y;ba=X*X;la=X*fa;ha=ba*Y;ja=ba+fa;ma=b+Y*a+X*p+fa*q+ba*r+ia*s;Z=a+Y*t+X*s;ra=Y*s+(p+X*u);aa=D+Y*E+X*F+fa*G+ba*H+ia*I;na=E+Y*J+X*I;_=Y*I+(F+X*K);if(L){ka=+h[M>>3];$=+h[N>>3];ea=aa+Y*fa*ka+X*ba*$;ga=na+fa*ka*3.0;ka=_+ba*$*3.0;if(O){$=+h[k>>3];da=+h[Q>>3];ca=+h[R>>3];ya=+h[T>>3];za=+h[V>>3];Aa=ca*2.0;Ba=ea+la*$+ha*da+ja*ca+ja*Y*ya+ja*X*za;Ca=(ba+fa*3.0)*ya+(ba*da+(ga+ia*$*2.0)+Y*Aa)+ia*za*2.0;Da=(ba*3.0+fa)*za+(ka+fa*$+ia*da*2.0+X*Aa+ia*ya*2.0)}else{Ba=ea;Ca=ga;Da=ka}}else{Ba=aa;Ca=na;Da=_}_=ma-l;ma=Ba-m;na=Z*Da-ra*Ca;aa=(ra*ma-_*Da)/na;ra=(_*Ca-Z*ma)/na;na=Y+aa;ma=X+ra;if(+P(+aa)<5.0e-7?+P(+ra)<5.0e-7:0){va=na;wa=ma;break a}xa=W+1|0;if((xa|0)<50){W=xa;Y=na;X=ma}else{va=na;wa=ma;break}}}}while(0);h[e>>3]=va+ +h[d+616>>3];va=wa+ +h[d+624>>3];h[f>>3]=va;wa=+h[e>>3];if(wa<.5){Ea=-1;i=g;return Ea|0}if(wa>+h[d+136>>3]+.5|va<.5){Ea=-1;i=g;return Ea|0}if(va>+h[d+144>>3]+.5){Ea=-1;i=g;return Ea|0}Ea=0;i=g;return Ea|0}function dd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0;d=i;e=gg(2e3)|0;f=gg(2e3)|0;Nc(a,10344,2e3,e)|0;Nc(a,10352,2e3,f)|0;a=gg(2e3)|0;g=gg(2e3)|0;j=b+3176|0;if((+h[j>>3]>360.0?(Xc(e,10360,j)|0)==0:0)?(Xc(f,10360,j)|0)==0:0){h[j>>3]=180.0}j=b+3192|0;if((Xc(e,10376,j)|0)==0?(Xc(f,10376,j)|0)==0:0){h[j>>3]=57.29577951308232}do{if((Zc(e,10384,2e3,a)|0)==0){if((Zc(f,10384,2e3,a)|0)==0){c[b+5960>>2]=0;break}else{c[b+5960>>2]=gd(a)|0;break}}else{c[b+5960>>2]=gd(a)|0}}while(0);do{if((Zc(f,10392,2e3,g)|0)==0){if((Zc(e,10392,2e3,g)|0)==0){c[b+5964>>2]=0;break}else{c[b+5964>>2]=gd(g)|0;break}}else{c[b+5964>>2]=gd(g)|0}}while(0);ac(b);hg(e);hg(f);hg(a);hg(g);if((c[b+5964>>2]|0)==0?(c[b+5960>>2]|0)==0:0){k=1;i=d;return k|0}k=0;i=d;return k|0}function ed(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0;g=i;j=a- +h[d+616>>3];a=b- +h[d+624>>3];if((c[d+3300>>2]|0)==0){b=+h[d+760>>3];if(b==0.0){k=2;l=0.0;m=0.0;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}n=+h[d+768>>3];if(n==0.0){k=2;l=0.0;m=0.0;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}o=j*b;b=a*n;n=+h[d+48>>3];if(n!=0.0){p=n*3.141592653589793/180.0;n=+S(+p);q=+T(+p);r=o*n-b*q;s=b*n+o*q}else{r=o;s=b}}else{r=j*+h[d+56>>3]+a*+h[d+64>>3];s=j*+h[d+72>>3]+a*+h[d+80>>3]}t=(c[d+3304>>2]|0)==0|0;a=(90.0- +h[d+(t<<3)+688>>3])*3.141592653589793/180.0;j=+S(+a);b=+T(+a);o=+h[d+3176>>3]*3.141592653589793/180.0;u=c[d+5960>>2]|0;if((u|0)==0){v=r}else{v=r+ +hd(u,r,s)}u=c[d+5964>>2]|0;if((u|0)==0){w=s}else{w=s+ +hd(u,r,s)}s=+Q(+(v*v+w*w));if(s==0.0){x=0.0}else{x=+Y(+v,+-w)}w=+Y(+(+h[d+3192>>3]),+s);s=+S(+w);v=+T(+w);r=x-o;o=+S(+r);x=+T(+r);q=j*s;n=b*v-q*o;if(+P(+n)<1.0e-5){y=q*(1.0-o)- +S(+(a+w))}else{y=n}n=s*x;if(y!=0.0|n!=-0.0){z=+Y(+-n,+y)}else{z=r+3.141592653589793}x=+h[d+((t^1)<<3)+688>>3];q=x+z*180.0/3.141592653589793;if(!(x>=0.0)){if(q>0.0){A=q+-360.0}else{A=q}}else{if(q<0.0){A=q+360.0}else{A=q}}if(!(A>360.0)){if(A<-360.0){B=A+360.0}else{B=A}}else{B=A+-360.0}if(+qa(+r,3.141592653589793)==0.0){r=(w+a*o)*180.0/3.141592653589793;if(r>90.0){C=180.0-r}else{C=r}if(!(C<-90.0)){k=0;l=C;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}k=0;l=-180.0-C;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}C=j*v+b*s*o;if(!(+P(+C)>.99)){k=0;l=+W(+C)*180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}o=+V(+(+Q(+(n*n+y*y))));if(!(C>=0.0)){k=0;l=o*-180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}else{k=0;l=o*180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}return 0}function fd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0,D=0,E=0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0,U=0.0,X=0.0,Z=0.0,_=0,$=0.0,aa=0.0,ba=0.0;g=i;j=d+3304|0;k=(c[j>>2]|0)==0|0;l=(a- +h[d+((k^1)<<3)+688>>3])*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+l);m=+T(+l);n=+S(+a);o=+T(+a);p=(90.0- +h[d+(k<<3)+688>>3])*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=+h[d+3176>>3];if(s==999.0){t=3.141592653589793}else{t=s*3.141592653589793/180.0}s=n*q;u=o*r-b*s;if(+P(+u)<1.0e-5){v=(1.0-b)*s- +S(+(a+p))}else{v=u}u=m*n;if(v!=0.0|u!=-0.0){w=+Y(+-u,+v)}else{w=l+-3.141592653589793}m=t+w;if(!(m>3.141592653589793)){if(m<-3.141592653589793){x=m+6.283185307179586}else{x=m}}else{x=m+-6.283185307179586}do{if(+qa(+l,3.141592653589793)==0.0){m=a+b*p;if(m>1.5707963267948966){y=3.141592653589793-m}else{y=m}if(y<-1.5707963267948966){z=-3.141592653589793-y}else{z=y}}else{m=o*q+b*n*r;if(!(+P(+m)>.99)){z=+W(+m);break}w=+V(+(+Q(+(u*u+v*v))));if(!(m>=0.0)){z=-w}else{z=w}}}while(0);v=+T(+z);do{if(v==0.0){A=0.0;B=0.0}else{u=+h[d+3192>>3]*+S(+z)/v;k=d+5960|0;C=c[k>>2]|0;D=d+5964|0;if((C|0)==0?(c[D>>2]|0)==0:0){E=(c[j>>2]|0)==0;r=u*+T(+x);n=-(u*+S(+x));A=E?r:n;B=E?n:r;break}r=u*+T(+x);n=u*+S(+x);E=C;C=1;u=r;b=-n;while(1){if((E|0)==0){F=u;G=1.0;H=0.0}else{q=u+ +hd(E,u,b);o=+id(c[k>>2]|0,u,b,1,0)+1.0;F=q;G=o;H=+id(c[k>>2]|0,u,b,0,1)}o=F-r;I=c[D>>2]|0;if((I|0)==0){J=b;K=0.0;L=1.0}else{q=b+ +hd(I,u,b);y=+id(c[D>>2]|0,u,b,1,0);J=q;K=y;L=+id(c[D>>2]|0,u,b,0,1)+1.0}y=n+J;q=G*L-H*K;if(q==0.0){M=u;N=b;break}p=(H*y-o*L)/q;a=(o*K-G*y)/q;q=u+p;l=b+a;I=+P(+p)>+P(+a);w=I?p:a;a=+P(+w);I=+P(+o)>+P(+y);p=I?o:y;I=a>+P(+p);if(!(!(+P(+(I?w:p))<2.8e-8)&(C|0)<500)){M=q;N=l;break}E=c[k>>2]|0;C=C+1|0;u=q;b=l}C=(c[j>>2]|0)==0;A=C?M:N;B=C?N:M}}while(0);if((c[d+3300>>2]|0)!=0){h[e>>3]=A*+h[d+88>>3]+B*+h[d+96>>3];h[f>>3]=A*+h[d+104>>3]+B*+h[d+112>>3];O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}M=+h[d+48>>3];if(M!=0.0){N=M*3.141592653589793/180.0;M=+S(+N);G=+T(+N);h[e>>3]=A*M+B*G;ba=B*M-A*G}else{h[e>>3]=A;ba=B}h[f>>3]=ba;ba=+h[d+32>>3];if(ba!=0.0){h[e>>3]=+h[e>>3]/ba}ba=+h[d+40>>3];if(!(ba!=0.0)){O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}h[f>>3]=+h[f>>3]/ba;O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}function gd(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=i;i=i+16|0;e=d;if((a[b+1|0]|0)==0){f=0;i=d;return f|0}g=gg(160)|0;c[e>>2]=b;j=b;k=b;b=g;g=0;l=20;a:while(1){if((a[k]|0)==0){break}m=+wg(j,e);n=c[e>>2]|0;o=a[n]|0;if(o<<24>>24==46){p=n+1|0;c[e>>2]=p;q=a[p]|0;r=p}else{q=o;r=n}if(q<<24>>24==0){break}n=g+1|0;if((n|0)<(l|0)){s=r;t=b;u=l}else{o=l+20|0;p=jg(b,o<<3)|0;s=c[e>>2]|0;t=p;u=o}h[t+(g<<3)>>3]=m;o=s;while(1){if((a[o]|0)==32){o=o+1|0}else{j=o;k=s;b=t;g=n;l=u;continue a}}}u=jd(b)|0;hg(b);f=(g|0)==0?0:u;i=d;return f|0}function hd(a,b,d){a=a|0;b=+b;d=+d;var e=0,f=0,g=0,j=0.0,k=0.0,l=0,m=0.0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0,F=0,G=0,H=0,I=0,J=0.0,K=0,L=0.0,M=0,N=0.0,O=0;e=i;f=c[a+32>>2]|0;if((f|0)==1){g=c[a+36>>2]|0;j=+h[a+8>>3];k=+h[a>>3];l=c[a+56>>2]|0;h[l>>3]=1.0;if(((g|0)!=1?(m=(j+b)*k,h[l+8>>3]=m,(g|0)>2):0)?(k=m*2.0,j=k*m+-1.0,h[l+16>>3]=j,(g|0)!=3):0){m=j;n=3;p=2;while(1){m=k*m- +h[l+(p+ -1<<3)>>3];h[l+(n<<3)>>3]=m;q=n+1|0;if((q|0)==(g|0)){break}else{r=n;n=q;p=r}}}p=c[a+40>>2]|0;m=+h[a+24>>3];k=+h[a+16>>3];n=c[a+60>>2]|0;h[n>>3]=1.0;if((p|0)!=1){j=(m+d)*k;h[n+8>>3]=j;if((p|0)>2){k=j*2.0;m=k*j+-1.0;h[n+16>>3]=m;if((p|0)==3){s=l;t=n;u=3;v=g;w=25}else{j=m;r=3;q=2;while(1){m=k*j- +h[n+(q+ -1<<3)>>3];h[n+(r<<3)>>3]=m;x=r+1|0;if((x|0)==(p|0)){y=g;z=p;A=l;B=n;w=26;break}else{C=r;j=m;r=x;q=C}}}}else{y=g;z=p;A=l;B=n;w=26}}else{s=l;t=n;u=1;v=g;w=25}}else if((f|0)==3){g=c[a+36>>2]|0;n=c[a+56>>2]|0;h[n>>3]=1.0;if((g|0)!=1?(h[n+8>>3]=b,(g|0)>2):0){j=b;l=2;do{j=j*b;h[n+(l<<3)>>3]=j;l=l+1|0}while((l|0)!=(g|0))}l=c[a+40>>2]|0;p=c[a+60>>2]|0;h[p>>3]=1.0;if((l|0)!=1){h[p+8>>3]=d;if((l|0)>2){j=d;q=2;while(1){k=j*d;h[p+(q<<3)>>3]=k;r=q+1|0;if((r|0)==(l|0)){y=g;z=l;A=n;B=p;w=26;break}else{j=k;q=r}}}else{y=g;z=l;A=n;B=p;w=26}}else{s=n;t=p;u=1;v=g;w=25}}else if((f|0)==2){f=c[a+36>>2]|0;j=+h[a+8>>3];k=+h[a>>3];g=c[a+56>>2]|0;h[g>>3]=1.0;if(((f|0)!=1?(m=(j+b)*k,h[g+8>>3]=m,(f|0)>2):0)?(k=(m*m*3.0+-1.0)*.5,h[g+16>>3]=k,(f|0)!=3):0){p=3;b=k;n=2;while(1){k=+(p|0);b=(b*m*(k*2.0+-1.0)- +h[g+(n+ -1<<3)>>3]*(k+-1.0))/k;h[g+(p<<3)>>3]=b;l=p+1|0;if((l|0)==(f|0)){break}else{q=p;p=l;n=q}}}n=c[a+40>>2]|0;b=+h[a+24>>3];m=+h[a+16>>3];p=c[a+60>>2]|0;h[p>>3]=1.0;if((n|0)!=1){k=(b+d)*m;h[p+8>>3]=k;if((n|0)>2){m=(k*k*3.0+-1.0)*.5;h[p+16>>3]=m;if((n|0)==3){s=g;t=p;u=3;v=f;w=25}else{q=3;d=m;l=2;while(1){m=+(q|0);b=(d*k*(m*2.0+-1.0)- +h[p+(l+ -1<<3)>>3]*(m+-1.0))/m;h[p+(q<<3)>>3]=b;r=q+1|0;if((r|0)==(n|0)){y=f;z=n;A=g;B=p;w=26;break}else{C=q;q=r;d=b;l=C}}}}else{y=f;z=n;A=g;B=p;w=26}}else{s=g;t=p;u=1;v=f;w=25}}else{ab(10400,33,1,c[o>>2]|0)|0;D=0.0;i=e;return+D}if((w|0)==25){E=(v|0)>(u|0)?v:u;F=t;G=u;H=s;I=v}else if((w|0)==26){if((z|0)>0){E=(y|0)>(z|0)?y:z;F=B;G=z;H=A;I=y}else{D=0.0;i=e;return+D}}y=c[a+44>>2]|0;A=a+52|0;if((y|0)==2){a=0;z=0;d=0.0;B=I;while(1){if((B|0)>0){w=c[A>>2]|0;k=0.0;v=z;s=0;while(1){k=k+ +h[w+(v<<3)>>3]*+h[H+(s<<3)>>3];s=s+1|0;if((s|0)==(B|0)){break}else{v=v+1|0}}J=k;K=B+z|0}else{J=0.0;K=z}b=d+J*+h[F+(a<<3)>>3];v=(((a+1+I|0)>(E|0))<<31>>31)+B|0;s=a+1|0;if((s|0)<(G|0)){a=s;z=K;d=b;B=v}else{D=b;break}}i=e;return+D}else if((y|0)==0){y=0;B=0;d=0.0;K=I;while(1){if((K|0)>0){z=c[A>>2]|0;J=0.0;a=B;E=0;while(1){J=J+ +h[z+(a<<3)>>3]*+h[H+(E<<3)>>3];E=E+1|0;if((E|0)==(K|0)){break}else{a=a+1|0}}L=J;M=K+B|0}else{L=0.0;M=B}k=d+L*+h[F+(y<<3)>>3];a=y+1|0;if((a|0)<(G|0)){y=a;B=M;d=k;K=1}else{D=k;break}}i=e;return+D}else{K=0;M=0;d=0.0;while(1){if((I|0)>0){B=c[A>>2]|0;L=0.0;y=M;a=0;while(1){L=L+ +h[B+(y<<3)>>3]*+h[H+(a<<3)>>3];a=a+1|0;if((a|0)==(I|0)){break}else{y=y+1|0}}N=L;O=I+M|0}else{N=0.0;O=M}J=d+N*+h[F+(K<<3)>>3];y=K+1|0;if((y|0)<(G|0)){K=y;M=O;d=J}else{D=J;break}}i=e;return+D}return 0.0}function id(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0.0,O=0,P=0,Q=0,S=0,T=0.0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0.0,$=0.0,ba=0.0,ca=0.0,da=0,ea=0.0,fa=0.0;g=i;i=i+16|0;j=g;if((a|0)==0){k=0.0;i=g;return+k}l=f|e;if((l|0)<0){ab(10440,46,1,c[o>>2]|0)|0;k=0.0;i=g;return+k}if((l|0)==0){k=+hd(a,b,d);i=g;return+k}l=gg(64)|0;m=a+36|0;n=c[m>>2]|0;p=n+ -1|0;q=(p|0)>(e|0)?e:p;p=a+40|0;e=c[p>>2]|0;r=e+ -1|0;s=(r|0)>(f|0)?f:r;r=c[a+32>>2]|0;t=l+32|0;c[t>>2]=r;if(!((r+ -1|0)>>>0<3)){u=c[o>>2]|0;c[j>>2]=r;za(u|0,10488,j|0)|0;k=0.0;i=g;return+k}j=c[a+44>>2]|0;u=l+44|0;c[u>>2]=j;do{if((j|0)==2){r=((n|0)>(e|0)?n:e)-s-q|0;v=n-q|0;w=(r|0)<(v|0)?r:v;v=(w|0)<1?1:w;w=l+36|0;c[w>>2]=v;x=e-s|0;y=(r|0)<(x|0)?r:x;x=(y|0)<1?1:y;y=l+40|0;c[y>>2]=x;r=(v|0)<(x|0)?v:x;z=(aa(x,v)|0)-((aa(r+ -1|0,r)|0)/2|0)|0;r=l+48|0;c[r>>2]=z;A=r;B=w;C=y;D=z;E=v;F=x}else if((j|0)==0){x=(q|0)>0;v=(s|0)>0;if(x&v){z=l+36|0;c[z>>2]=1;y=l+40|0;c[y>>2]=1;w=l+48|0;c[w>>2]=1;A=w;B=z;C=y;D=1;E=1;F=1;break}if(x){x=n-q|0;y=(x|0)<1?1:x;x=l+36|0;c[x>>2]=y;z=l+40|0;c[z>>2]=1;w=l+48|0;c[w>>2]=y;A=w;B=x;C=z;D=y;E=y;F=1;break}if(v){v=l+36|0;c[v>>2]=1;y=e-s|0;z=(y|0)<1?1:y;y=l+40|0;c[y>>2]=z;x=l+48|0;c[x>>2]=z;A=x;B=v;C=y;D=z;E=1;F=z;break}else{A=l+48|0;B=l+36|0;C=l+40|0;D=0;E=0;F=0;break}}else{z=n-q|0;y=(z|0)<1?1:z;z=l+36|0;c[z>>2]=y;v=e-s|0;x=(v|0)<1?1:v;v=l+40|0;c[v>>2]=x;w=aa(x,y)|0;r=l+48|0;c[r>>2]=w;A=r;B=z;C=v;D=w;E=y;F=x}}while(0);h[l>>3]=+h[a>>3];h[l+8>>3]=+h[a+8>>3];n=l+16|0;h[n>>3]=+h[a+16>>3];h[l+24>>3]=+h[a+24>>3];j=l+52|0;c[j>>2]=gg(D<<3)|0;D=l+56|0;c[D>>2]=gg(E<<3)|0;E=l+60|0;c[E>>2]=gg(F<<3)|0;F=a+48|0;x=c[F>>2]|0;y=x<<3;w=c[2632]|0;if((y|0)>(w|0)){if((w|0)>0){G=jg(c[2634]|0,y)|0}else{G=gg(y)|0}c[2634]=G;c[2632]=y;H=G;I=c[F>>2]|0}else{H=c[2634]|0;I=x}if((I|0)>0){x=c[a+52>>2]|0;a=0;do{h[H+(a<<3)>>3]=+h[x+(a<<3)>>3];a=a+1|0}while((a|0)!=(I|0))}a=c[u>>2]|0;a:do{if((a|0)==1){u=c[p>>2]|0;x=u+ -1|0;if((u|0)>(s|0)){u=c[m>>2]|0;F=c[B>>2]|0;G=aa(x,u)|0;y=aa((c[C>>2]|0)+ -1|0,F)|0;w=1-s|0;v=q+1|0;z=(u|0)<(v|0);r=(F|0)>0;J=0-u|0;K=1-q|0;L=x;x=H+(G<<3)|0;G=(c[j>>2]|0)+(y<<3)|0;while(1){y=w+L|0;if((L|0)>=(y|0)){M=L;while(1){if(r){N=+(M|0);O=0;do{P=x+(O+q<<3)|0;h[P>>3]=N*+h[P>>3];O=O+1|0}while((O|0)<(F|0))}if((M|0)>(y|0)){M=M+ -1|0}else{break}}}if(!z){M=u;while(1){y=K+M|0;O=M+ -1|0;if((M|0)>=(y|0)){P=x+(O<<3)|0;N=+h[P>>3];Q=M;while(1){S=Q+ -1|0;T=+(S|0)*N;if((Q|0)>(y|0)){N=T;Q=S}else{break}}h[P>>3]=T}if((M|0)>(v|0)){M=O}else{break}}}if(r){M=0;do{h[G+(M<<3)>>3]=+h[x+(M+q<<3)>>3];M=M+1|0}while((M|0)<(F|0))}if((L|0)>(s|0)){L=L+ -1|0;x=x+(J<<3)|0;G=G+(0-F<<3)|0}else{break}}}}else if((a|0)==2){F=c[m>>2]|0;G=c[p>>2]|0;J=((F|0)>(G|0)?F:G)+1|0;x=c[B>>2]|0;L=c[C>>2]|0;r=s+1|0;if((G|0)>=(r|0)){v=r+((x|0)>(L|0)?x:L)|0;L=1-s|0;K=q+1|0;u=1-q|0;z=G;G=H+(I<<3)|0;w=(c[j>>2]|0)+(c[A>>2]<<3)|0;while(1){M=J-z|0;Q=(M|0)<(F|0)?M:F;M=(Q|0)<0?0:Q;Q=v-z|0;y=(Q|0)<(x|0)?Q:x;Q=(y|0)<0?0:y;y=G+(0-M<<3)|0;S=w+(0-Q<<3)|0;U=L+z|0;if((z|0)>(U|0)){V=(Q|0)>0;W=q-M|0;X=z;do{X=X+ -1|0;if(V){N=+(X|0);Y=0;do{Z=G+(W+Y<<3)|0;h[Z>>3]=N*+h[Z>>3];Y=Y+1|0}while((Y|0)<(Q|0))}}while((X|0)>(U|0))}if((M|0)>=(K|0)){U=M;while(1){X=u+U|0;W=U+ -1|0;if((U|0)>=(X|0)){V=G+(W-M<<3)|0;N=+h[V>>3];Y=U;while(1){O=Y+ -1|0;_=+(O|0)*N;if((Y|0)>(X|0)){N=_;Y=O}else{break}}h[V>>3]=_}if((U|0)>(K|0)){U=W}else{break}}}if((Q|0)>0){U=q-M|0;Y=0;do{h[w+(Y-Q<<3)>>3]=+h[G+(U+Y<<3)>>3];Y=Y+1|0}while((Y|0)<(Q|0))}if((z|0)>(r|0)){z=z+ -1|0;G=y;w=S}else{break}}}}else{w=(q|0)>0;G=(s|0)>0;if(w&G){h[c[j>>2]>>3]=0.0;break}if(w){w=c[m>>2]|0;z=q+1|0;if((w|0)<(z|0)){break}r=1-q|0;K=w;w=(c[j>>2]|0)+((c[A>>2]|0)+ -1<<3)|0;while(1){u=r+K|0;L=K+ -1|0;x=H+(L<<3)|0;N=+h[x>>3];if((K|0)<(u|0)){$=N}else{ba=N;v=K;while(1){F=v+ -1|0;ca=ba*+(F|0);if((v|0)>(u|0)){ba=ca;v=F}else{break}}h[x>>3]=ca;$=ca}h[w>>3]=$;if((K|0)>(z|0)){K=L;w=w+ -8|0}else{break a}}}if(G){w=H+(I+ -1<<3)|0;K=c[j>>2]|0;z=c[p>>2]|0;r=s+1|0;if((z|0)<(r|0)){da=w}else{v=1-s|0;u=0-e|0;S=~f;y=((u|0)>(S|0)?u:S)+ -1|0;S=~z;u=I+ -3-(z+((y|0)>(S|0)?y:S))|0;S=z;z=w;while(1){w=v+S|0;if((S|0)>=(w|0)){ba=+h[z>>3];y=S;while(1){F=y+ -1|0;ea=+(F|0)*ba;if((y|0)>(w|0)){ba=ea;y=F}else{break}}h[z>>3]=ea}if((S|0)>(r|0)){S=S+ -1|0;z=z+ -8|0}else{break}}da=H+(u<<3)|0}z=c[A>>2]|0;if((z|0)>0){S=0;while(1){r=S+1|0;h[K+(S<<3)>>3]=+h[da+(r<<3)>>3];if((r|0)<(z|0)){S=r}else{break}}}}}}while(0);ea=+hd(l,b,d);if((c[t>>2]|0)==3){if((l|0)==0){k=ea;i=g;return+k}else{fa=ea}}else{d=+R(+(+h[l>>3]),+(+(q|0)));fa=ea*d*+R(+(+h[n>>3]),+(+(s|0)))}s=c[D>>2]|0;if((s|0)!=0){hg(s)}s=c[E>>2]|0;if((s|0)!=0){hg(s)}s=c[j>>2]|0;if((s|0)!=0){hg(s)}hg(l);k=fa;i=g;return+k}function jd(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,l=0.0,m=0.0,n=0,p=0.0,q=0.0,r=0,s=0,t=0;b=i;i=i+16|0;d=b;e=~~(+h[a+8>>3]+.5);if((e|0)<1){f=c[o>>2]|0;c[d>>2]=e;za(f|0,10544,d|0)|0;g=0;i=b;return g|0}f=~~(+h[a+16>>3]+.5);if((f|0)<1){j=c[o>>2]|0;c[d>>2]=f;za(j|0,10584,d|0)|0;g=0;i=b;return g|0}l=+h[a+32>>3];m=+h[a+40>>3];if(m<=l){j=c[o>>2]|0;h[k>>3]=l;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];n=d+8|0;h[k>>3]=m;c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];za(j|0,10624,d|0)|0;g=0;i=b;return g|0}p=+h[a+48>>3];q=+h[a+56>>3];if(q<=p){j=c[o>>2]|0;h[k>>3]=p;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];n=d+8|0;h[k>>3]=q;c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];za(j|0,10664,d|0)|0;g=0;i=b;return g|0}j=~~(+h[a>>3]+.5);if(!((j+ -1|0)>>>0<3)){n=c[o>>2]|0;c[d>>2]=j;za(n|0,10704,d|0)|0;g=0;i=b;return g|0}d=gg(64)|0;c[d+36>>2]=e;h[d>>3]=2.0/(m-l);h[d+8>>3]=(l+m)*-.5;c[d+40>>2]=f;h[d+16>>3]=2.0/(q-p);h[d+24>>3]=(p+q)*-.5;n=~~+h[a+24>>3];c[d+44>>2]=n;if((n|0)==1){r=aa(f,e)|0;c[d+48>>2]=r;s=r}else if((n|0)==2){r=(e|0)<(f|0)?e:f;t=(aa(f,e)|0)-((aa(r+ -1|0,r)|0)/2|0)|0;c[d+48>>2]=t;s=t}else if((n|0)==0){n=e+ -1+f|0;c[d+48>>2]=n;s=n}else{s=0}c[d+32>>2]=j;j=gg(s<<3)|0;c[d+52>>2]=j;if((s|0)>0){n=0;do{h[j+(n<<3)>>3]=+h[a+(n+8<<3)>>3];n=n+1|0}while((n|0)<(s|0))}c[d+56>>2]=gg(e<<3)|0;c[d+60>>2]=gg(f<<3)|0;g=d;i=b;return g|0}function kd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0;d=i;i=i+16|0;e=d;f=d+8|0;g=gg(2e3)|0;j=gg(2e3)|0;if((Nc(a,10744,2e3,g)|0)==0){k=gg((Dg(a|0)|0)+200|0)|0;Kg(k|0,10752,161)|0;Fg(k|0,a|0)|0;Nc(k,10744,2e3,g)|0;Nc(k,10920,2e3,j)|0;hg(k)}Nc(a,10920,2e3,j)|0;a=gg(2e3)|0;k=gg(2e3)|0;l=b+3176|0;if((+h[l>>3]>360.0?(Xc(g,10928,l)|0)==0:0)?(Xc(j,10928,l)|0)==0:0){h[l>>3]=180.0}l=b+3192|0;if((Xc(g,10944,l)|0)==0?(Xc(j,10944,l)|0)==0:0){h[l>>3]=57.29577951308232}l=0;do{c[e>>2]=l;Na(f|0,10952,e|0)|0;m=b+(l<<3)+4096|0;if((Xc(g,f,m)|0)==0){h[m>>3]=0.0}l=l+1|0}while((l|0)!=10);do{if((Zc(g,10960,2e3,a)|0)==0){if((Zc(j,10960,2e3,a)|0)==0){c[b+5960>>2]=0;break}else{c[b+5960>>2]=gd(a)|0;break}}else{c[b+5960>>2]=gd(a)|0}}while(0);do{if((Zc(j,10968,2e3,k)|0)==0){if((Zc(g,10968,2e3,k)|0)==0){c[b+5964>>2]=0;n=9;break}else{c[b+5964>>2]=gd(k)|0;n=9;break}}else{c[b+5964>>2]=gd(k)|0;n=9}}while(0);while(1){o=n+ -1|0;if(!(+h[b+(n<<3)+4096>>3]==0.0)){p=27;break}if((n|0)>0){n=o}else{p=25;break}}if((p|0)==25){c[b+3276>>2]=o}else if((p|0)==27?(c[b+3276>>2]=n,(n|0)>2):0){q=+h[b+4104>>3];p=1;r=0.0;while(1){s=+(p|0)*3.141592653589793/180.0;t=0.0;o=n;do{t=s*t+ +(o|0)*+h[b+(o<<3)+4096>>3];o=o+ -1|0}while((o|0)>0);o=p+1|0;if(t<=0.0){u=q;v=r;break}if((o|0)<181){q=t;p=o;r=s}else{u=t;v=s;break}}a:do{if(!(t<=0.0)){w=3.141592653589793}else{r=u;q=t;p=1;x=v;y=s;while(1){z=x-r*(y-x)/(q-r);A=0.0;o=n;do{A=z*A+ +(o|0)*+h[b+(o<<3)+4096>>3];o=o+ -1|0}while((o|0)>0);if(+P(+A)<1.0e-13){w=z;break a}o=A<0.0;l=p+1|0;if((l|0)<11){r=o?r:A;q=o?A:q;p=l;x=o?x:z;y=o?z:y}else{w=z;break}}}}while(0);if((n|0)>-1){p=n;s=0.0;while(1){v=w*s+ +h[b+(p<<3)+4096>>3];if((p|0)>0){p=p+ -1|0;s=v}else{B=v;break}}}else{B=0.0}h[b+3240>>3]=w;h[b+3248>>3]=B}ac(b);hg(g);hg(j);hg(a);hg(k);if((c[b+5964>>2]|0)==0?(c[b+5960>>2]|0)==0:0){C=1;i=d;return C|0}C=0;i=d;return C|0} + + + +function ld(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,U=0.0,X=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0;g=i;j=a- +h[d+616>>3];a=b- +h[d+624>>3];do{if((c[d+3300>>2]|0)==0){b=+h[d+760>>3];if(!(b==0.0)?(k=+h[d+768>>3],!(k==0.0)):0){l=j*b;b=a*k;k=+h[d+48>>3];if(!(k!=0.0)){m=l;n=b;break}o=k*3.141592653589793/180.0;k=+S(+o);p=+T(+o);m=l*k-b*p;n=b*k+l*p;break}h[e>>3]=0.0;h[f>>3]=0.0;q=2;i=g;return q|0}else{m=j*+h[d+56>>3]+a*+h[d+64>>3];n=j*+h[d+72>>3]+a*+h[d+80>>3]}}while(0);r=(c[d+3304>>2]|0)==0|0;s=r^1;a=(90.0- +h[d+(r<<3)+688>>3])*3.141592653589793/180.0;j=+S(+a);p=+T(+a);l=+h[d+3176>>3]*3.141592653589793/180.0;r=c[d+3276>>2]|0;t=c[d+5960>>2]|0;if((t|0)==0){u=m}else{u=m+ +hd(t,m,n)}t=c[d+5964>>2]|0;if((t|0)==0){v=n}else{v=n+ +hd(t,m,n)}n=+Q(+(u*u+v*v));m=n/+h[d+3192>>3];if((r|0)<1){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}a:do{if((r|0)==2){n=+h[d+4112>>3];k=+h[d+4104>>3];b=k*k-n*4.0*(+h[d+4096>>3]-m);if(b<0.0){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}o=+Q(+b);b=n*2.0;n=(o-k)/b;w=(-k-o)/b;b=nw?n:w}else{x=b}if(x<0.0){if(!(x<-1.0e-13)){y=0.0;break}h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if(x>3.141592653589793){if(x>3.141592653589893){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}else{y=3.141592653589793}}else{y=x}}else if((r|0)==1){y=(m- +h[d+4096>>3])/+h[d+4104>>3]}else{b=+h[d+4096>>3];w=+h[d+3240>>3];n=+h[d+3248>>3];if(m>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if(m>n){if(!(m>n+1.0e-13)){y=w;break}h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if((r|0)>-1){z=0;A=b;B=n;C=0.0;D=w}else{o=0.0-m;t=0;k=b;b=n;n=0.0;E=w;while(1){w=(b-m)/(b-k);if(!(w<.1)){if(w>.9){F=.9}else{F=w}}else{F=.1}w=E-(E-n)*F;if(m>0.0){if(m<1.0e-13){y=w;break a}else{G=0.0;H=b;I=w;J=E}}else{if(o<1.0e-13){y=w;break a}else{G=k;H=0.0;I=n;J=w}}K=t+1|0;if(!(+P(+(J-I))<1.0e-13)&(K|0)<100){t=K;k=G;b=H;n=I;E=J}else{y=w;break a}}}while(1){E=(B-m)/(B-A);if(!(E<.1)){if(E>.9){L=.9}else{L=E}}else{L=.1}E=D-(D-C)*L;t=r;n=0.0;while(1){n=E*n+ +h[d+(t<<3)+4096>>3];if((t|0)<=0){break}else{t=t+ -1|0}}if(n>3];R=U+Z*180.0/3.141592653589793;if(!(U>=0.0)){if(R>0.0){_=R+-360.0}else{_=R}}else{if(R<0.0){_=R+360.0}else{_=R}}if(!(_>360.0)){if(_<-360.0){$=_+360.0}else{$=_}}else{$=_+-360.0}do{if(+qa(+m,3.141592653589793)==0.0){_=(v+a*l)*180.0/3.141592653589793;if(_>90.0){aa=180.0-_}else{aa=_}if(aa<-90.0){ba=-180.0-aa}else{ba=aa}}else{_=j*u+p*y*l;if(!(+P(+_)>.99)){ba=+W(+_)*180.0/3.141592653589793;break}R=+V(+(+Q(+(D*D+X*X))));if(!(_>=0.0)){ba=R*-180.0/3.141592653589793;break}else{ba=R*180.0/3.141592653589793;break}}}while(0);h[e>>3]=$;h[f>>3]=ba;q=0;i=g;return q|0}function md(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0,U=0.0,X=0.0,Z=0.0,_=0,$=0.0,aa=0.0,ba=0.0;g=i;j=d+3304|0;k=(c[j>>2]|0)==0|0;l=(a- +h[d+((k^1)<<3)+688>>3])*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+l);m=+T(+l);n=+S(+a);o=+T(+a);p=(90.0- +h[d+(k<<3)+688>>3])*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=+h[d+3176>>3];if(s==999.0){t=3.141592653589793}else{t=s*3.141592653589793/180.0}s=n*q;u=o*r-b*s;if(+P(+u)<1.0e-5){v=(1.0-b)*s- +S(+(a+p))}else{v=u}u=m*n;if(v!=0.0|u!=-0.0){w=+Y(+-u,+v)}else{w=l+-3.141592653589793}m=t+w;if(!(m>3.141592653589793)){if(m<-3.141592653589793){x=m+6.283185307179586}else{x=m}}else{x=m+-6.283185307179586}do{if(+qa(+l,3.141592653589793)==0.0){m=a+b*p;if(m>1.5707963267948966){y=3.141592653589793-m}else{y=m}if(y<-1.5707963267948966){z=-3.141592653589793-y}else{z=y}}else{m=o*q+b*n*r;if(!(+P(+m)>.99)){z=+W(+m);break}w=+V(+(+Q(+(u*u+v*v))));if(!(m>=0.0)){z=-w}else{z=w}}}while(0);v=1.5707963267948966-z;z=(v*(v*(v*(v*(v*(v*(v*(v*(v*(v*0.0+ +h[d+4168>>3])+ +h[d+4160>>3])+ +h[d+4152>>3])+ +h[d+4144>>3])+ +h[d+4136>>3])+ +h[d+4128>>3])+ +h[d+4120>>3])+ +h[d+4112>>3])+ +h[d+4104>>3])+ +h[d+4096>>3])*+h[d+3192>>3];k=d+5960|0;A=c[k>>2]|0;B=d+5964|0;if((A|0)==0?(c[B>>2]|0)==0:0){C=(c[j>>2]|0)==0;v=z*+T(+x);u=-(z*+S(+x));D=C?v:u;E=C?u:v}else{v=z*+T(+x);u=z*+S(+x);C=A;A=1;x=v;z=-u;while(1){if((C|0)==0){F=x;G=1.0;H=0.0}else{r=x+ +hd(C,x,z);n=+id(c[k>>2]|0,x,z,1,0)+1.0;F=r;G=n;H=+id(c[k>>2]|0,x,z,0,1)}n=F-v;I=c[B>>2]|0;if((I|0)==0){J=z;K=0.0;L=1.0}else{r=z+ +hd(I,x,z);b=+id(c[B>>2]|0,x,z,1,0);J=r;K=b;L=+id(c[B>>2]|0,x,z,0,1)+1.0}b=u+J;r=G*L-H*K;if(r==0.0){M=x;N=z;break}q=(H*b-n*L)/r;o=(n*K-G*b)/r;r=x+q;y=z+o;I=+P(+q)>+P(+o);p=I?q:o;o=+P(+p);I=+P(+n)>+P(+b);q=I?n:b;I=o>+P(+q);if(!(!(+P(+(I?p:q))<2.8e-8)&(A|0)<500)){M=r;N=y;break}C=c[k>>2]|0;A=A+1|0;x=r;z=y}A=(c[j>>2]|0)==0;D=A?M:N;E=A?N:M}if((c[d+3300>>2]|0)!=0){h[e>>3]=D*+h[d+88>>3]+E*+h[d+96>>3];h[f>>3]=D*+h[d+104>>3]+E*+h[d+112>>3];O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}M=+h[d+48>>3];if(M!=0.0){N=M*3.141592653589793/180.0;M=+S(+N);z=+T(+N);h[e>>3]=D*M+E*z;ba=E*M-D*z}else{h[e>>3]=D;ba=E}h[f>>3]=ba;ba=+h[d+32>>3];if(ba!=0.0){h[e>>3]=+h[e>>3]/ba}ba=+h[d+40>>3];if(!(ba!=0.0)){O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}h[f>>3]=+h[f>>3]/ba;O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}function nd(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0;f=i;g=(+h[c+224>>3]-(+h[c+176>>3]+a+-1.0+.5)*+h[c+192>>3])/1.0e3;a=((+h[c+184>>3]+b+-1.0+.5)*+h[c+200>>3]- +h[c+248>>3])/1.0e3;b=g*g;j=a*a;k=g*b;l=a*j;m=b+j;n=(k*+h[c+496>>3]+(l*+h[c+472>>3]+(m*+h[c+464>>3]+(b*+h[c+456>>3]+(+h[c+432>>3]+(a*+h[c+416>>3]+g*+h[c+424>>3])+j*+h[c+440>>3]+a*g*+h[c+448>>3])))+g*j*+h[c+480>>3]+b*a*+h[c+488>>3])+m*a*+h[c+504>>3]+m*m*a*+h[c+512>>3])/206264.8062470964;o=+h[c+160>>3];p=+U(+o);q=1.0-n*p;r=+Y(+((l*+h[c+336>>3]+(k*+h[c+312>>3]+(m*+h[c+304>>3]+(j*+h[c+296>>3]+(+h[c+272>>3]+(g*+h[c+256>>3]+a*+h[c+264>>3])+b*+h[c+280>>3]+a*g*+h[c+288>>3])))+a*b*+h[c+320>>3]+j*g*+h[c+328>>3])+m*g*+h[c+344>>3]+m*m*g*+h[c+352>>3])/206264.8062470964/+S(+o)),+q);o=r+ +h[c+152>>3];if(!(o<0.0)){s=o;t=s/.01745329252;h[d>>3]=t;u=+S(+r);v=n+p;w=v/q;x=u*w;y=+X(+x);z=y/.01745329252;h[e>>3]=z;i=f;return 0}s=o+6.28318530717959;t=s/.01745329252;h[d>>3]=t;u=+S(+r);v=n+p;w=v/q;x=u*w;y=+X(+x);z=y/.01745329252;h[e>>3]=z;i=f;return 0}function od(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,Q=0.0,R=0.0,U=0.0,V=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0;f=i;h[d>>3]=0.0;h[e>>3]=0.0;g=b*3.141592653589793/180.0;b=+T(+g);j=+S(+g);k=c+160|0;g=+h[k>>3];if(g==0.0){l=+h[c+8>>3]*3.141592653589793/180.0;h[k>>3]=l;m=l}else{m=g}g=+T(+m);l=+S(+m);k=c+152|0;m=+h[k>>3];if(m==0.0){n=+h[c+8>>3]*3.141592653589793/180.0;h[k>>3]=n;o=n}else{o=m}m=a*3.141592653589793/180.0-o;o=+S(+m);a=b*g+j*l*o;if(a==0.0){p=1;i=f;return p|0}n=j*+T(+m)*206264.8062470964/a;m=(b*l-j*g*o)*206264.8062470964/a;a=+h[c+168>>3];if(a==0.0){p=1;i=f;return p|0}o=+h[c+256>>3];g=+h[c+264>>3];j=+h[c+272>>3];l=+h[c+280>>3];b=+h[c+288>>3];q=+h[c+296>>3];r=+h[c+304>>3];s=+h[c+312>>3];t=+h[c+320>>3];u=+h[c+328>>3];v=+h[c+336>>3];w=+h[c+344>>3];x=+h[c+352>>3];y=l*2.0;z=r*2.0;A=s*3.0;B=t*2.0;C=q*2.0;D=u*2.0;E=v*3.0;F=w*2.0;G=x*4.0;H=+h[c+416>>3];I=+h[c+424>>3];J=+h[c+432>>3];K=+h[c+440>>3];L=+h[c+448>>3];M=+h[c+456>>3];N=+h[c+464>>3];O=+h[c+472>>3];Q=+h[c+480>>3];R=+h[c+488>>3];U=+h[c+496>>3];V=+h[c+504>>3];W=+h[c+512>>3];X=M*2.0;Y=N*2.0;Z=R*2.0;_=U*3.0;$=V*2.0;aa=W*4.0;ba=K*2.0;ca=O*3.0;da=Q*2.0;k=0;ea=n/a;fa=m/a;do{a=fa*ea;ga=ea*ea;ha=fa*fa;ia=fa*ga;ja=ha*ea;ka=ha+ga;la=ka*ka;ma=ea*ga;na=fa*ha;oa=ga*ga;pa=ha*ha;qa=ha*ga*6.0;ra=ha*u+(fa*b+(o+ea*y)+ea*z+ga*A+a*B)+(ha+ga*3.0)*w+(pa+(oa*5.0+qa))*x;sa=g+ea*b+fa*C+fa*z+ga*t+a*D+ha*E+a*F+ka*a*G;ta=I+fa*L+ea*X+ea*Y+ha*Q+a*Z+ga*_+a*$+ka*a*aa;ua=ga*R+(ea*L+(H+fa*ba)+fa*Y+ha*ca+a*da)+(ha*3.0+ga)*V+(oa+(pa*5.0+qa))*W;qa=j+(ea*o+fa*g)+ga*l+a*b+ha*q+ka*r+ma*s+ia*t+ja*u+na*v+ka*ea*w+la*ea*x-n;pa=J+(fa*H+ea*I)+ha*K+a*L+ga*M+ka*N+na*O+ja*Q+ia*R+ma*U+ka*fa*V+la*fa*W-m;la=ra*ua-sa*ta;ka=(sa*pa-qa*ua)/la;ua=(qa*ta-ra*pa)/la;ea=ea+ka;fa=fa+ua;if(+P(+ka)<5.0e-7?+P(+ua)<5.0e-7:0){break}k=k+1|0}while((k|0)<50);m=+h[c+192>>3];if(m==0.0){p=1;i=f;return p|0}W=+h[c+200>>3];if(W==0.0){p=1;i=f;return p|0}V=(fa*1.0e3+ +h[c+248>>3])/W;h[d>>3]=(+h[c+224>>3]-ea*1.0e3)/m- +h[c+176>>3]+1.0+-.5;m=V- +h[c+184>>3]+1.0+-.5;h[e>>3]=m;V=+h[d>>3];if(V<.5){p=-1;i=f;return p|0}if(V>+h[c+136>>3]+.5|m<.5){p=-1;i=f;return p|0}if(m>+h[c+144>>3]+.5){p=-1;i=f;return p|0}p=0;i=f;return p|0}function pd(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;i=i+16|0;e=d;d=c[o>>2]|0;c[e>>2]=a;c[e+4>>2]=b;za(d|0,10976,e|0)|0;hb(-1)}function qd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;f=i;i=i+544|0;g=f;h=f+24|0;j=f+8|0;k=ig(1,28)|0;if((k|0)==0){pd(10992,11016)}c[k+16>>2]=b;if((b|0)>4){c[g>>2]=b;c[g+4>>2]=4;Na(h|0,11040,g|0)|0;pd(11120,h)}if((b|0)==0){l=k+12|0}else{m=gg(b<<2)|0;n=k+12|0;c[n>>2]=m;if((m|0)==0){pd(10992,11136)}m=a;a=b;o=c[n>>2]|0;while(1){p=a+ -1|0;c[o>>2]=(c[m>>2]|0)+ -1;if((p|0)==0){l=n;break}else{m=m+4|0;a=p;o=o+4|0}}}c[k+24>>2]=e;a:do{if((e|0)!=0){o=c[l>>2]|0;a=e<<2;m=gg(a)|0;c[k+20>>2]=m;if((m|0)==0){pd(10992,11176)}Eg(j|0,0,a|0)|0;b:do{if((b|0)>0){a=0;while(1){m=c[o+(a<<2)>>2]|0;if((m|0)>=(e|0)){break}n=j+(m<<2)|0;c[n>>2]=(c[n>>2]|0)+1;a=a+1|0;if((a|0)>=(b|0)){break b}}pd(11216,11256)}}while(0);o=k+8|0;c[o>>2]=1;if((e|0)>0){a=c[k+20>>2]|0;n=d;m=1;p=0;while(1){q=n+4|0;r=c[n>>2]|0;c[a+(p<<2)>>2]=r;if((r|0)>10){break}s=c[j+(p<<2)>>2]|0;if((r|0)==0){t=1;u=1}else{v=r;w=1;x=1;while(1){y=aa(x,v+s|0)|0;z=v+ -1|0;A=aa(w,v)|0;if((z|0)==0){t=A;u=y;break}else{v=z;w=A;x=y}}}x=aa(m,(u|0)/(t|0)|0)|0;c[o>>2]=x;w=p+1|0;if((w|0)<(e|0)){n=q;m=x;p=w}else{B=x;break a}}c[g>>2]=r;c[g+4>>2]=10;Na(h|0,11264,g|0)|0;pd(11120,h)}else{B=1}}else{c[k+8>>2]=1;B=1}}while(0);h=gg(B<<3)|0;c[k>>2]=h;if((h|0)==0){pd(10992,11336)}h=ig(B,8)|0;c[k+4>>2]=h;if((h|0)==0){pd(10992,11376)}else{i=f;return k|0}return 0}function rd(a){a=a|0;var b=0;b=i;if((a|0)==0){i=b;return}hg(c[a+4>>2]|0);hg(c[a>>2]|0);hg(c[a+20>>2]|0);hg(c[a+12>>2]|0);hg(a);i=b;return}function sd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0.0,z=0.0,A=0,B=0,C=0,D=0;d=i;i=i+80|0;e=d;f=d+60|0;g=d+40|0;j=c[a+16>>2]|0;k=c[a>>2]|0;l=c[a+4>>2]|0;m=c[a+12>>2]|0;n=c[a+20>>2]|0;if((j|0)!=0){o=j+ -1|0;if((o|0)!=0){p=o;o=f;q=e;do{q=q+8|0;h[q>>3]=1.0;o=o+4|0;c[o>>2]=0;p=p+ -1|0}while((p|0)!=0)}p=c[a+24>>2]|0;if((p|0)!=0){o=n;n=p;p=g;while(1){n=n+ -1|0;c[p>>2]=c[o>>2];if((n|0)==0){break}else{o=o+4|0;p=p+4|0}}}p=g+(c[m>>2]<<2)|0;o=c[p>>2]|0;if((o|0)!=0){c[p>>2]=o+ -1}}o=l+8|0;r=+h[l>>3];l=k+8|0;h[k>>3]=1.0;c[f>>2]=1;s=+h[b>>3];h[e>>3]=s;k=(c[a+8>>2]|0)+ -1|0;if((k|0)==0){t=r;i=d;return+t}if((j|0)>0){u=s;v=k;w=l;x=o;y=r}else{z=s;a=k;k=l;l=o;s=r;while(1){h[k>>3]=z;r=s+z*+h[l>>3];o=a+ -1|0;if((o|0)==0){t=r;break}z=+h[e>>3];a=o;k=k+8|0;l=l+8|0;s=r}i=d;return+t}while(1){l=w+8|0;h[w>>3]=u;k=x+8|0;s=y+u*+h[x>>3];a=0;o=f;p=m;n=b;q=e;while(1){A=g+(c[p>>2]<<2)|0;B=c[A>>2]|0;c[A>>2]=B+ -1;C=c[o>>2]|0;if((B|0)!=0){D=13;break}c[g+(c[p>>2]<<2)>>2]=C;c[o>>2]=0;h[q>>3]=1.0;B=a+1|0;if((B|0)>=(j|0)){break}a=B;o=o+4|0;p=p+4|0;n=n+8|0;q=q+8|0}if((D|0)==13?(D=0,c[o>>2]=C+1,z=+h[n>>3]*+h[q>>3],h[q>>3]=z,(a|0)!=0):0){p=a;B=q;do{B=B+ -8|0;p=p+ -1|0;h[B>>3]=z}while((p|0)!=0)}p=v+ -1|0;if((p|0)==0){t=s;break}u=+h[e>>3];v=p;w=l;x=k;y=s}i=d;return+t}function td(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0.0,D=0.0,E=0,F=0,G=0,H=0,I=0.0,J=0,K=0,L=0,M=0;j=i;i=i+32|0;k=j;l=(b|0)!=0;m=(g|0)==0;if(m&(l^1)){pd(11416,11496)}n=c[a+8>>2]|0;o=c[a+16>>2]|0;p=aa(n,n)|0;q=c[a>>2]|0;r=ig(p,8)|0;if((r|0)==0){pd(10992,11512)}p=ig(n,8)|0;if((p|0)==0){pd(10992,11544)}if((f|0)!=0){s=(n|0)==0;t=(o|0)>0;u=e;e=d;d=f;f=g;g=b;while(1){b=d+ -1|0;if(l){if(t){v=0;w=g;while(1){h[k+(v<<3)>>3]=+h[w>>3];v=v+1|0;if((v|0)==(o|0)){break}else{w=w+8|0}}x=g+(o<<3)|0}else{x=g}+sd(a,k);if(m|s){y=f;z=x}else{w=q;v=f;A=n;while(1){A=A+ -1|0;h[v>>3]=+h[w>>3];if((A|0)==0){break}else{w=w+8|0;v=v+8|0}}y=f+(n<<3)|0;z=x}}else{if(s){y=f;z=g}else{v=q;w=f;A=n;while(1){A=A+ -1|0;h[v>>3]=+h[w>>3];if((A|0)==0){break}else{v=v+8|0;w=w+8|0}}y=f+(n<<3)|0;z=g}}if((u|0)==0){B=0;C=1.0}else{B=u+8|0;C=+h[u>>3]}w=e+8|0;D=+h[e>>3];if(!s){v=n;A=r;E=q;F=p;while(1){G=v+ -1|0;H=E+8|0;I=C*+h[E>>3];J=F+8|0;h[F>>3]=+h[F>>3]+D*I;K=A;L=q;M=n;while(1){M=M+ -1|0;h[K>>3]=+h[K>>3]+I*+h[L>>3];if((M|0)==0){break}else{K=K+8|0;L=L+8|0}}if((G|0)==0){break}else{v=G;A=A+(n<<3)|0;E=H;F=J}}}if((b|0)==0){break}else{u=B;e=w;d=b;f=y;g=z}}}ud(r,p,n);hg(r);if((n|0)==0){hg(p);i=j;return}r=p;z=c[a+4>>2]|0;a=n;while(1){a=a+ -1|0;h[z>>3]=+h[r>>3];if((a|0)==0){break}else{r=r+8|0;z=z+8|0}}hg(p);i=j;return}function ud(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=i;if((vd(a,b,c)|0)==0){i=d;return}e=c<<3;f=gg(aa(e,c)|0)|0;if((f|0)==0){pd(10992,11576)}g=gg(e)|0;if((g|0)==0){pd(10992,11600)}wd(a,b,c,c,f,g);hg(f);hg(g);i=d;return}function vd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0;d=i;e=gg(c<<3)|0;if((e|0)==0){pd(10992,11624)}f=(c|0)>0;if(f){g=0;a:do{j=aa(g,c)|0;k=e+(g<<3)|0;if((g|0)>0){l=g;do{m=aa(l,c)|0;n=g;o=+h[a+(l+j<<3)>>3];do{n=n+ -1|0;o=o- +h[a+(n+j<<3)>>3]*+h[a+(n+m<<3)>>3]}while((n|0)>0);if((g|0)==(l|0)){if(o<=0.0){p=15;break a}h[k>>3]=+Q(+o)}else{h[a+((aa(l,c)|0)+g<<3)>>3]=o/+h[k>>3]}l=l+1|0}while((l|0)<(c|0))}else{l=g;do{q=+h[a+(l+j<<3)>>3];if((g|0)==(l|0)){if(q<=0.0){p=15;break a}h[k>>3]=+Q(+q)}else{h[a+((aa(l,c)|0)+g<<3)>>3]=q/+h[k>>3]}l=l+1|0}while((l|0)<(c|0))}g=g+1|0}while((g|0)<(c|0));if((p|0)==15){hg(e);r=-1;i=d;return r|0}if(f){p=0;do{g=b+(p<<3)|0;q=+h[g>>3];if((p|0)>0){l=aa(p,c)|0;k=p;s=q;while(1){j=k+ -1|0;t=s- +h[a+(j+l<<3)>>3]*+h[b+(j<<3)>>3];if((j|0)>0){k=j;s=t}else{u=t;break}}}else{u=q}h[g>>3]=u/+h[e+(p<<3)>>3];p=p+1|0}while((p|0)!=(c|0));if(f){f=c;while(1){p=f+ -1|0;k=b+(p<<3)|0;u=+h[k>>3];if((f|0)<(c|0)){l=f;s=u;while(1){t=+h[a+((aa(l,c)|0)+p<<3)>>3];v=s-t*+h[b+(l<<3)>>3];j=l+1|0;if((j|0)==(c|0)){w=v;break}else{l=j;s=v}}}else{w=u}h[k>>3]=w/+h[e+(p<<3)>>3];if((p|0)>0){f=p}else{break}}}}}hg(e);r=0;i=d;return r|0}function wd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0.0,B=0.0,C=0,D=0.0,E=0.0,F=0.0,G=0,H=0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,S=0.0,T=0,U=0,V=0,W=0,X=0.0,Y=0,Z=0,_=0,$=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0.0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0.0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0.0,Fa=0.0,Ga=0.0,Ha=0.0,Ia=0.0,Ja=0.0,Ka=0.0,La=0.0,Ma=0.0,Na=0.0,Oa=0.0,Pa=0,Qa=0,Ra=0.0,Sa=0,Ta=0.0,Ua=0,Va=0,Wa=0.0;g=i;if((c|0)<(d|0)){pd(11648,11704)}j=d<<3;k=gg(j)|0;if((k|0)==0){pd(10992,11720)}l=gg(j)|0;if((l|0)==0){pd(10992,11744)}j=(d|0)>0;a:do{if(j){m=c+1|0;n=0.0;o=0.0;p=0;q=0.0;while(1){r=p+1|0;s=d-r|0;t=k+(p<<3)|0;h[t>>3]=o*q;u=c-p|0;b:do{if((u|0)>0?(v=a+((aa(p,m)|0)<<3)|0,w=(p|0)==(c|0),!w):0){x=v;y=u;z=0.0;while(1){y=y+ -1|0;z=z+ +P(+(+h[x>>3]));if((y|0)==0){break}else{x=x+8|0}}if(z!=0.0){if(w){A=0.0}else{x=v;y=u;B=0.0;while(1){C=y+ -1|0;D=+h[x>>3]/z;h[x>>3]=D;E=B+D*D;if((C|0)==0){A=E;break}else{x=x+8|0;y=C;B=E}}}B=+h[v>>3];E=+P(+(+Q(+A)));if(!(B>=0.0)){F=-E}else{F=E}E=-F;D=B*E-A;h[v>>3]=B+F;if((r|0)!=(d|0)){y=s;x=a+((aa(r,c)|0)+p<<3)|0;while(1){y=y+ -1|0;c:do{if(!w){C=v;G=x;H=u;B=0.0;while(1){I=H+ -1|0;J=B+ +h[G>>3]*+h[C>>3];if((I|0)==0){break}C=C+8|0;G=G+8|0;H=I;B=J}B=J/D;if(!w){H=v;G=x;C=u;while(1){I=C+ -1|0;h[G>>3]=+h[G>>3]+B*+h[H>>3];if((I|0)==0){break c}H=H+8|0;G=G+8|0;C=I}}}}while(0);if((y|0)==0){break}else{x=x+(c<<3)|0}}}if(w){K=E;L=z}else{x=v;y=u;while(1){C=y+ -1|0;h[x>>3]=z*+h[x>>3];if((C|0)==0){K=E;L=z;break b}x=x+8|0;y=C}}}else{K=0.0;L=z}}else{K=0.0;L=0.0}}while(0);E=K*L;u=f+(p<<3)|0;h[u>>3]=E;if(!((p|0)>=(c|0)|(r|0)==(d|0))){y=aa(r,c)|0;x=a+(y+p<<3)|0;v=x;w=s;D=0.0;while(1){w=w+ -1|0;D=D+ +P(+(+h[v>>3]));if((w|0)==0){break}else{v=v+(c<<3)|0}}if(D!=0.0){v=x;w=s;B=0.0;while(1){w=w+ -1|0;M=+h[v>>3]/D;h[v>>3]=M;B=B+M*M;if((w|0)==0){break}else{v=v+(c<<3)|0}}M=+h[x>>3];N=+P(+(+Q(+B)));if(!(M>=0.0)){O=-N}else{O=N}N=-O;R=M*N-B;S=M+O;h[x>>3]=S;v=k+(r<<3)|0;M=S;w=x;C=s;G=v;while(1){H=C+ -1|0;h[G>>3]=M/R;I=w+(c<<3)|0;if((H|0)==0){break}M=+h[I>>3];w=I;C=H;G=G+8|0}if((r|0)==(c|0)){T=x;U=s}else{G=c-r|0;C=a+(y+r<<3)|0;while(1){w=G+ -1|0;H=x;I=C;V=s;M=0.0;while(1){W=V+ -1|0;X=M+ +h[I>>3]*+h[H>>3];if((W|0)==0){Y=C;Z=s;_=v;break}H=H+(c<<3)|0;I=I+(c<<3)|0;V=W;M=X}while(1){Z=Z+ -1|0;h[Y>>3]=+h[Y>>3]+X*+h[_>>3];if((Z|0)==0){break}else{Y=Y+(c<<3)|0;_=_+8|0}}if((w|0)==0){T=x;U=s;break}else{G=w;C=C+8|0}}}while(1){C=U+ -1|0;h[T>>3]=D*+h[T>>3];if((C|0)==0){break}T=T+(c<<3)|0;U=C}$=+h[u>>3];ba=N;ca=D}else{$=E;ba=0.0;ca=D}}else{$=E;ba=0.0;ca=0.0}M=+P(+$);z=M+ +P(+(+h[t>>3]));da=n>z?n:z;if((r|0)==(d|0)){break}else{n=da;o=ba;p=r;q=ca}}p=d+ -1|0;if(j){q=ba;m=p;C=0;G=d;s=0;while(1){do{if((m|0)<(p|0)){if(q!=0.0){x=a+(m+(aa(G,c)|0)<<3)|0;v=e+((aa(m,d)|0)+G<<3)|0;y=e+((aa(G,d)|0)+G<<3)|0;o=+h[x>>3];n=q*o;V=(s|0)==0;if(V){break}else{ea=o;fa=x;ga=s;ha=v}while(1){I=ga+ -1|0;h[ha>>3]=ea/n;H=fa+(c<<3)|0;if((I|0)==0){break}ea=+h[H>>3];fa=H;ga=I;ha=ha+8|0}if(V){break}else{ia=s;ja=y}while(1){ia=ia+ -1|0;w=x;I=s;n=0.0;H=ja;while(1){W=I+ -1|0;ka=n+ +h[w>>3]*+h[H>>3];if((W|0)==0){la=s;ma=v;na=ja;break}w=w+(c<<3)|0;I=W;n=ka;H=H+8|0}while(1){la=la+ -1|0;h[na>>3]=+h[na>>3]+ka*+h[ma>>3];if((la|0)==0){break}else{ma=ma+8|0;na=na+8|0}}if((ia|0)==0){break}else{ja=ja+(d<<3)|0}}}if((s|0)!=0){v=s;x=e+(m+(aa(G,d)|0)<<3)|0;y=e+((aa(m,d)|0)+G<<3)|0;while(1){v=v+ -1|0;h[y>>3]=0.0;h[x>>3]=0.0;if((v|0)==0){break}else{x=x+(d<<3)|0;y=y+8|0}}}}}while(0);h[e+((aa(m,d)|0)+m<<3)>>3]=1.0;s=d-m|0;C=C+1|0;if((C|0)==(d|0)){break}else{r=m;q=+h[k+(m<<3)>>3];m=m+ -1|0;G=r}}if(j){G=~d;m=~c;C=(G|0)>(m|0)?G:m;m=a+((aa(-2-C|0,c)|0)+ -2-C<<3)|0;G=-8-(c<<3)|0;s=(C+c<<3)+16|0;p=~C;C=d;r=0;while(1){t=m+(aa(G,r)|0)|0;u=s+(r<<3)|0;y=C+ -1|0;x=d-C|0;v=c-y|0;q=+h[f+(y<<3)>>3];V=(aa(y,c)|0)+y|0;H=a+(V<<3)|0;I=a+(V+c<<3)|0;V=(C|0)==(d|0);if(!V){w=I;W=x;while(1){W=W+ -1|0;h[w>>3]=0.0;if((W|0)==0){break}else{w=w+(c<<3)|0}}}d:do{if(q!=0.0){E=1.0/q;if(!V){w=v+ -1|0;W=(w|0)==0;oa=(y|0)==(c|0);pa=x;qa=I;while(1){pa=pa+ -1|0;if(W){ra=0.0}else{sa=w;ta=H;ua=qa;D=0.0;while(1){va=ta+8|0;wa=ua+8|0;N=D+ +h[va>>3]*+h[wa>>3];xa=sa+ -1|0;if((xa|0)==0){ra=N;break}else{sa=xa;ta=va;ua=wa;D=N}}}D=+h[H>>3];N=E*(ra/D);e:do{if(!oa){n=D;ua=H;ta=qa;sa=v;while(1){wa=sa+ -1|0;va=ua+8|0;h[ta>>3]=+h[ta>>3]+N*n;if((wa|0)==0){break e}n=+h[va>>3];ua=va;ta=ta+8|0;sa=wa}}}while(0);if((pa|0)==0){break}else{qa=qa+(c<<3)|0}}}if((y|0)!=(c|0)){qa=H;pa=v;while(1){oa=pa+ -1|0;h[qa>>3]=E*+h[qa>>3];if((oa|0)==0){break d}qa=qa+8|0;pa=oa}}}else{if((y|0)!=(c|0)){Eg(t|0,0,u|0)|0}}}while(0);h[H>>3]=+h[H>>3]+1.0;u=r+1|0;if((u|0)==(p|0)){break}else{C=y;r=u}}if(j){r=(c|0)==0;C=d;p=0;f:while(1){s=C+ -1|0;G=f+(s<<3)|0;m=C+ -2|0;u=f+(m<<3)|0;t=k+(m<<3)|0;v=k+(s<<3)|0;I=0;x=p;while(1){V=s;pa=x;while(1){if(!((V|0)>-1)){ya=pa;za=93;break}qa=V+ -1|0;if(da+ +P(+(+h[k+(V<<3)>>3]))==da){Aa=qa;break}if(da+ +P(+(+h[f+(qa<<3)>>3]))==da){ya=qa;za=93;break}else{V=qa;pa=qa}}g:do{if((za|0)==93){za=0;pa=a+((aa(ya,c)|0)<<3)|0;if((V|0)>(s|0)){Aa=ya}else{qa=a+((aa(V,c)|0)<<3)|0;oa=V;q=1.0;while(1){E=q*+h[k+(oa<<3)>>3];N=+P(+E);if(da+N==da){Aa=ya;break g}w=f+(oa<<3)|0;D=+h[w>>3];n=+P(+D);if(!(N>n)){if(D!=0.0){o=N/n;Ba=n*+Q(+(o*o+1.0))}else{Ba=0.0}}else{o=n/N;Ba=N*+Q(+(o*o+1.0))}h[w>>3]=Ba;o=1.0/Ba;N=D*o;D=-(E*o);if(!r){w=pa;W=qa;sa=c;while(1){sa=sa+ -1|0;o=+h[W>>3];E=+h[w>>3];h[w>>3]=o*D+N*E;h[W>>3]=N*o-E*D;if((sa|0)==0){break}else{w=w+8|0;W=W+8|0}}}if((oa|0)>=(s|0)){Aa=ya;break g}qa=qa+(c<<3)|0;oa=oa+1|0;q=D}}}}while(0);Ca=+h[G>>3];if((V|0)==(s|0)){za=105;break}if((I|0)==99){break f}q=+h[f+(V<<3)>>3];N=+h[u>>3];E=+h[t>>3];o=+h[v>>3];n=((N-Ca)*(Ca+N)+(E-o)*(E+o))/(N*o*2.0);E=+P(+n);if(E>1.0){z=1.0/E;Da=E*+Q(+(z*z+1.0))}else{Da=+Q(+(E*E+1.0))}E=+P(+Da);if(!(n>=0.0)){Ea=-E}else{Ea=E}E=((q-Ca)*(Ca+q)+o*(N/(n+Ea)-o))/q;if((V|0)>(m|0)){Fa=E;Ga=q}else{oa=a+((aa(V,c)|0)<<3)|0;o=1.0;n=E;qa=V;E=1.0;pa=e+((aa(V,d)|0)<<3)|0;N=q;while(1){W=qa+1|0;q=+h[k+(W<<3)>>3];z=+h[f+(W<<3)>>3];M=E*q;R=o*q;q=+P(+n);B=+P(+M);if(!(q>B)){if(M!=0.0){S=q/B;Ha=B*+Q(+(S*S+1.0))}else{Ha=0.0}}else{S=B/q;Ha=q*+Q(+(S*S+1.0))}h[k+(qa<<3)>>3]=Ha;S=n/Ha;q=M/Ha;M=N*S+R*q;B=R*S-N*q;R=z*q;Ia=z*S;w=pa+(d<<3)|0;sa=d;ta=w;ua=pa;while(1){sa=sa+ -1|0;z=+h[ta>>3];Ja=+h[ua>>3];h[ua>>3]=q*z+S*Ja;h[ta>>3]=S*z-q*Ja;if((sa|0)==0){break}else{ta=ta+8|0;ua=ua+8|0}}Ja=+P(+M);z=+P(+R);do{if(!(Ja>z)){if(R!=0.0){Ka=Ja/z;La=z*+Q(+(Ka*Ka+1.0));za=130;break}else{h[f+(qa<<3)>>3]=0.0;Ma=S;Na=q;break}}else{Ka=z/Ja;La=Ja*+Q(+(Ka*Ka+1.0));za=130}}while(0);if((za|0)==130){za=0;h[f+(qa<<3)>>3]=La;if(La!=0.0){Ja=1.0/La;Ma=M*Ja;Na=R*Ja}else{Ma=S;Na=q}}Ja=B*Ma+Ia*Na;z=Ia*Ma-B*Na;ua=oa+(c<<3)|0;if(!r){ta=ua;sa=oa;wa=c;while(1){wa=wa+ -1|0;Ka=+h[ta>>3];Oa=+h[sa>>3];h[sa>>3]=Na*Ka+Ma*Oa;h[ta>>3]=Ma*Ka-Na*Oa;if((wa|0)==0){break}else{ta=ta+8|0;sa=sa+8|0}}}if((qa|0)<(m|0)){oa=ua;o=Ma;n=Ja;qa=W;E=Na;pa=w;N=z}else{Fa=Ja;Ga=z;break}}}h[k+(V<<3)>>3]=0.0;h[v>>3]=Fa;h[G>>3]=Ga;pa=I+1|0;if((pa|0)<100){I=pa;x=m}else{Pa=m;break}}if((za|0)==105){za=0;if(Ca<0.0){h[G>>3]=-Ca;m=d;x=e+((aa(s,d)|0)<<3)|0;while(1){I=m+ -1|0;h[x>>3]=-+h[x>>3];if((I|0)==0){Pa=Aa;break}else{m=I;x=x+8|0}}}else{Pa=Aa}}if((s|0)>0){C=s;p=Pa}else{break a}}pd(11768,11704)}}}}}while(0);Pa=(d|0)==0;if(!Pa){Aa=d;za=f;Ca=0.0;while(1){Aa=Aa+ -1|0;Ga=+h[za>>3];Ca=Ga>Ca?Ga:Ca;if((Aa|0)==0){break}else{za=za+8|0}}Ga=Ca*1.0e-11;if(!Pa){za=d;Aa=f;while(1){za=za+ -1|0;if(+h[Aa>>3]>3]=0.0}if((za|0)==0){break}else{Aa=Aa+8|0}}if(!Pa){Pa=(c|0)==0;Aa=d;za=a;a=l;ya=f;while(1){Aa=Aa+ -1|0;Ga=+h[ya>>3];if(Ga!=0.0){if(Pa){Qa=za;Ra=0.0}else{f=za;ja=b;ia=c;Ca=0.0;while(1){ia=ia+ -1|0;Ca=Ca+ +h[f>>3]*+h[ja>>3];if((ia|0)==0){break}else{f=f+8|0;ja=ja+8|0}}Qa=za+(c<<3)|0;Ra=Ca}Sa=Qa;Ta=Ra/Ga}else{Sa=za+(c<<3)|0;Ta=0.0}h[a>>3]=Ta;if((Aa|0)==0){break}else{za=Sa;a=a+8|0;ya=ya+8|0}}}}}if(j){Ua=0;Va=e}else{hg(l);hg(k);i=g;return}while(1){e=d;Ta=0.0;j=l;ya=Va;while(1){a=e+ -1|0;Wa=Ta+ +h[ya>>3]*+h[j>>3];if((a|0)==0){break}e=a;Ta=Wa;j=j+8|0;ya=ya+(d<<3)|0}h[b+(Ua<<3)>>3]=Wa;Ua=Ua+1|0;if((Ua|0)==(d|0)){break}else{Va=Va+8|0}}hg(l);hg(k);i=g;return}function xd(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0;f=i;i=i+32|0;g=f+8|0;h=f;j=f+16|0;k=h;c[k>>2]=5260110;c[k+4>>2]=5459015;k=e+4|0;a[k]=0;a[j]=0;l=e+20|0;c[l>>2]=-1;m=e+24|0;c[m>>2]=-1;n=e+28|0;c[n>>2]=-1;do{if((b|0)>0){o=e+8|0;p=e+13|0;q=0;r=0;a:while(1){s=d+(q*9|0)|0;do{if((a[d+(q*9|0)+4|0]|0)!=45){if((yg(s,11816)|0)==0){if(!((c[n>>2]|0)==-1)){t=1;u=35;break a}c[n>>2]=q;v=r}else{v=r}}else{w=d+(q*9|0)+5|0;x=c[2992]|0;b:do{if((x|0)>0){y=0;while(1){z=y+1|0;if((Ag(w,11976+(y<<2)|0,3)|0)==0){A=y;break b}if((z|0)<(x|0)){y=z}else{A=z;break}}}else{A=0}}while(0);if((A|0)==(x|0)){y=0;while(1){z=y+1|0;if((Ag(w,h+(y<<2)|0,3)|0)==0){B=y;break}if((z|0)<2){y=z}else{B=z;break}}if((B|0)==2){v=r;break}}if((a[k]|0)!=0){if((Ag(s,j,8)|0)!=0|(r|0)==0){t=1;u=35;break a}c[r>>2]=q;a[j]=0;v=r;break}c[g>>2]=w;Na(k|0,11832,g|0)|0;if((Ag(s,11840,4)|0)==0){c[l>>2]=q;a[o+0|0]=a[11848|0]|0;a[o+1|0]=a[11849|0]|0;a[o+2|0]=a[11850|0]|0;a[p]=4408644;a[p+1|0]=17221;a[p+2|0]=67;a[p+3|0]=0;c[g>>2]=k;Na(j|0,11856,g|0)|0;v=m;break}if((Ag(s,11864,4)|0)==0){c[m>>2]=q;a[o+0|0]=a[11848|0]|0;a[o+1|0]=a[11849|0]|0;a[o+2|0]=a[11850|0]|0;a[p]=4408644;a[p+1|0]=17221;a[p+2|0]=67;a[p+3|0]=0;c[g>>2]=k;Na(j|0,11872,g|0)|0;v=l;break}y=d+(q*9|0)+1|0;if((Ag(y,11880,3)|0)==0){c[l>>2]=q;c[g>>2]=a[s]|0;Na(o|0,11888,g|0)|0;c[g>>2]=a[s]|0;Na(p|0,11896,g|0)|0;c[g>>2]=p;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=m;break}if((Ag(y,11912,3)|0)==0){c[m>>2]=q;c[g>>2]=a[s]|0;Na(o|0,11888,g|0)|0;c[g>>2]=a[s]|0;Na(p|0,11896,g|0)|0;c[g>>2]=o;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=l;break}x=d+(q*9|0)+2|0;if((Ag(x,11920,2)|0)==0){c[l>>2]=q;z=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=z;Na(o|0,11928,g|0)|0;z=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=z;Na(p|0,11936,g|0)|0;c[g>>2]=p;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=m;break}if((Ag(x,11944,2)|0)!=0){t=1;u=35;break a}c[m>>2]=q;x=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=x;Na(o|0,11928,g|0)|0;x=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=x;Na(p|0,11936,g|0)|0;c[g>>2]=o;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=l}}while(0);s=q+1|0;if((s|0)<(b|0)){q=s;r=v}else{u=30;break}}if((u|0)==30){if((a[j]|0)==0){break}else{t=1}i=f;return t|0}else if((u|0)==35){i=f;return t|0}}}while(0);if((Ag(k,11952,3)|0)==0){a[k]=4998739;a[k+1|0]=19526;a[k+2|0]=76;a[k+3|0]=0;C=137}else{C=(a[k]|0)==0?999:137}c[e>>2]=C;t=0;i=f;return t|0}function yd(b,d,e,f,g,j,k,l,m,n,o){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0,t=0,u=0.0,v=0,w=0.0,x=0.0;p=i;q=n+4|0;if((c[d>>2]|0)!=137?(xd(c[q>>2]|0,b,d)|0)!=0:0){r=1;i=p;return r|0}b=c[q>>2]|0;if((b|0)>0){q=c[d+20>>2]|0;s=d+24|0;t=0;do{if((t|0)!=(q|0)?(t|0)!=(c[s>>2]|0):0){h[m+(t<<3)>>3]=+h[e+(t<<3)>>3]- +h[f+(t<<3)>>3]}t=t+1|0}while((t|0)<(b|0))}do{if((c[d>>2]|0)!=999){b=d+4|0;do{if((yg(b,11960)|0)==0){t=g+16|0;if(+h[t>>3]==0.0){r=2;i=p;return r|0}else{a[b]=5130579;a[b+1|0]=20041;a[b+2|0]=78;a[b+3|0]=0;h[l+40>>3]=0.0;u=+Re(+h[t>>3]);h[l+48>>3]=u/+Se(+h[t>>3]);t=l+4|0;c[t>>2]=c[t>>2]>>31;break}}}while(0);t=d+20|0;f=c[t>>2]|0;s=d+24|0;q=c[s>>2]|0;v=Fd(b,+h[e+(f<<3)>>3],+h[e+(q<<3)>>3],g,j,k,l,m+(f<<3)|0,m+(q<<3)|0)|0;if((v|0)!=0){r=v;i=p;return r|0}v=c[d+28>>2]|0;if(!((v|0)==-1)){u=+h[l+24>>3];if(u==0.0){w=90.0}else{w=u*3.141592653589793*.5}q=m+(c[s>>2]<<3)|0;u=+h[q>>3];if(u>3]=w+u;h[m+(v<<3)>>3]=5.0;break}x=w*.5;if(u>x){h[q>>3]=u-w;h[m+(v<<3)>>3]=0.0;break}q=m+(c[t>>2]<<3)|0;u=+h[q>>3];if(u>w*2.5){h[q>>3]=u-w*3.0;h[m+(v<<3)>>3]=4.0;break}if(u>w*1.5){h[q>>3]=u-w*2.0;h[m+(v<<3)>>3]=3.0;break}if(u>x){h[q>>3]=u-w;h[m+(v<<3)>>3]=2.0;break}else{h[m+(v<<3)>>3]=1.0;break}}}}while(0);l=(Cd(m,n,o)|0)==0;r=l?0:4;i=p;return r|0}function zd(b,d,e,f,g,j,k,l,m,n,o){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0.0,t=0.0;p=i;if((c[d>>2]|0)!=137?(xd(c[f+4>>2]|0,b,d)|0)!=0:0){q=1;i=p;return q|0}if((Dd(e,f,g)|0)!=0){q=4;i=p;return q|0}e=c[f+4>>2]|0;if((e|0)>0){f=c[d+20>>2]|0;b=d+24|0;r=0;do{if((r|0)!=(f|0)?(r|0)!=(c[b>>2]|0):0){h[o+(r<<3)>>3]=+h[g+(r<<3)>>3]+ +h[m+(r<<3)>>3]}r=r+1|0}while((r|0)<(e|0))}if((c[d>>2]|0)!=999){e=c[d+28>>2]|0;a:do{if(!((e|0)==-1)){s=+h[g+(e<<3)>>3];r=~~(s+.5);if(+P(+(s- +(r|0)))>1.0e-10){q=3;i=p;return q|0}s=+h[j+24>>3];if(s==0.0){t=90.0}else{t=s*3.141592653589793*.5}switch(r|0){case 2:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t+ +h[r>>3];break a;break};case 4:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t*3.0+ +h[r>>3];break a;break};case 3:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t*2.0+ +h[r>>3];break a;break};case 0:{r=g+(c[d+24>>2]<<3)|0;h[r>>3]=t+ +h[r>>3];break a;break};case 5:{r=g+(c[d+24>>2]<<3)|0;h[r>>3]=+h[r>>3]-t;break a;break};case 1:{break a;break};default:{q=3;i=p;return q|0}}}}while(0);e=d+4|0;do{if((yg(e,11960)|0)==0){r=n+16|0;if(+h[r>>3]==0.0){q=2;i=p;return q|0}else{a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;h[j+40>>3]=0.0;t=+Re(+h[r>>3]);h[j+48>>3]=t/+Se(+h[r>>3]);r=j+4|0;c[r>>2]=c[r>>2]>>31;break}}}while(0);r=c[d+20>>2]|0;m=c[d+24>>2]|0;d=Gd(e,+h[g+(r<<3)>>3],+h[g+(m<<3)>>3],j,k,l,n,o+(r<<3)|0,o+(m<<3)|0)|0;if((d|0)!=0){q=d;i=p;return q|0}}q=0;i=p;return q|0}function Ad(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;b=i;d=c[a+4>>2]|0;e=aa(d<<3,d)|0;f=gg(e)|0;c[a+20>>2]=f;if((f|0)==0){g=1;i=b;return g|0}j=gg(e)|0;c[a+24>>2]=j;if((j|0)==0){hg(f);g=1;i=b;return g|0}if((d|0)>0){e=a+16|0;k=a+12|0;l=0;m=0;while(1){n=(c[e>>2]|0)+(l<<3)|0;o=c[k>>2]|0;p=m;q=0;while(1){h[f+(p<<3)>>3]=+h[n>>3]*+h[o+(p<<3)>>3];q=q+1|0;if((q|0)==(d|0)){break}else{p=p+1|0}}l=l+1|0;if((l|0)==(d|0)){break}else{m=d+m|0}}}if((Bd(d,f,j)|0)!=0){g=2;i=b;return g|0}c[a>>2]=137;g=0;i=b;return g|0}function Bd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0,x=0,y=0,z=0,A=0,B=0;e=i;f=a<<2;g=gg(f)|0;if((g|0)==0){j=1;i=e;return j|0}k=gg(f)|0;if((k|0)==0){hg(g);j=1;i=e;return j|0}f=a<<3;l=gg(f)|0;if((l|0)==0){hg(g);hg(k);j=1;i=e;return j|0}m=gg(aa(f,a)|0)|0;if((m|0)==0){hg(g);hg(k);hg(l);j=1;i=e;return j|0}f=(a|0)>0;if(f){n=a<<3;o=0;p=0;while(1){c[g+(o<<2)>>2]=o;q=l+(o<<3)|0;h[q>>3]=0.0;Kg(m+(p<<3)|0,b+(p<<3)|0,n|0)|0;r=0.0;s=p;t=0;while(1){u=+P(+(+h[b+(s<<3)>>3]));if(u>r){h[q>>3]=u;v=u}else{v=r}t=t+1|0;if((t|0)==(a|0)){break}else{r=v;s=s+1|0}}o=o+1|0;if(v==0.0){w=17;break}if((o|0)>=(a|0)){break}else{p=p+a|0}}if((w|0)==17){hg(g);hg(k);hg(l);hg(m);j=2;i=e;return j|0}if(f){w=0;while(1){p=aa(w,a)|0;o=m+(p+w<<3)|0;b=l+(w<<3)|0;n=w+1|0;s=(n|0)<(a|0);if(s){v=+P(+(+h[o>>3]))/+h[b>>3];t=n;q=w;while(1){r=+P(+(+h[m+((aa(t,a)|0)+w<<3)>>3]));u=r/+h[l+(t<<3)>>3];x=u>v;q=x?t:q;t=t+1|0;if((t|0)==(a|0)){break}else{v=x?u:v}}if((q|0)>(w|0)){t=0;x=p;y=aa(q,a)|0;while(1){z=m+(y<<3)|0;v=+h[z>>3];A=m+(x<<3)|0;h[z>>3]=+h[A>>3];h[A>>3]=v;t=t+1|0;if((t|0)==(a|0)){break}else{x=x+1|0;y=y+1|0}}y=l+(q<<3)|0;v=+h[y>>3];h[y>>3]=+h[b>>3];h[b>>3]=v;y=g+(q<<2)|0;x=c[y>>2]|0;t=g+(w<<2)|0;c[y>>2]=c[t>>2];c[t>>2]=x}if(s){x=n;do{t=aa(x,a)|0;y=m+(t+w<<3)|0;v=+h[y>>3];a:do{if(v!=0.0){u=v/+h[o>>3];h[y>>3]=u;r=u;A=n;while(1){z=m+(A+t<<3)|0;h[z>>3]=+h[z>>3]-r*+h[m+(A+p<<3)>>3];z=A+1|0;if((z|0)==(a|0)){break a}r=+h[y>>3];A=z}}}while(0);x=x+1|0}while((x|0)!=(a|0))}}if((n|0)==(a|0)){break}else{w=n}}if(f){w=0;do{c[k+(c[g+(w<<2)>>2]<<2)>>2]=w;w=w+1|0}while((w|0)!=(a|0));if(f){w=a<<3;x=0;p=0;while(1){Eg(d+(p<<3)|0,0,w|0)|0;x=x+1|0;if((x|0)==(a|0)){break}else{p=p+a|0}}if(f){f=0;do{p=c[k+(f<<2)>>2]|0;h[d+((aa(p,a)|0)+f<<3)>>3]=1.0;x=p+1|0;if((x|0)<(a|0)){w=x;while(1){if((p|0)<(w|0)){x=aa(w,a)|0;o=d+(x+f<<3)|0;v=+h[o>>3];s=p;do{v=v- +h[m+(s+x<<3)>>3]*+h[d+((aa(s,a)|0)+f<<3)>>3];h[o>>3]=v;s=s+1|0}while((s|0)!=(w|0))}s=w+1|0;if((s|0)==(a|0)){B=a;break}else{w=s}}}else{B=a}while(1){w=B+ -1|0;p=aa(w,a)|0;n=d+(p+f<<3)|0;if((B|0)<(a|0)){v=+h[n>>3];s=B;do{v=v- +h[m+(s+p<<3)>>3]*+h[d+((aa(s,a)|0)+f<<3)>>3];h[n>>3]=v;s=s+1|0}while((s|0)!=(a|0))}h[n>>3]=+h[n>>3]/+h[m+(p+w<<3)>>3];if((w|0)>0){B=w}else{break}}f=f+1|0}while((f|0)!=(a|0))}}}}}hg(g);hg(k);hg(l);hg(m);j=0;i=e;return j|0}function Cd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0,r=0;e=i;f=c[b+4>>2]|0;if((c[b>>2]|0)!=137?(Ad(b)|0)!=0:0){g=1;i=e;return g|0}j=(f|0)>0;if(!j){g=0;i=e;return g|0}k=b+24|0;l=0;m=0;while(1){n=d+(l<<3)|0;h[n>>3]=0.0;o=c[k>>2]|0;p=0.0;q=m;r=0;while(1){p=p+ +h[o+(q<<3)>>3]*+h[a+(r<<3)>>3];h[n>>3]=p;r=r+1|0;if((r|0)==(f|0)){break}else{q=q+1|0}}l=l+1|0;if((l|0)==(f|0)){break}else{m=f+m|0}}if(!j){g=0;i=e;return g|0}j=c[b+8>>2]|0;b=0;while(1){m=d+(b<<3)|0;h[m>>3]=+h[j+(b<<3)>>3]+ +h[m>>3];m=b+1|0;if((m|0)==(f|0)){g=0;break}else{b=m}}i=e;return g|0}function Dd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0;e=i;f=c[b+4>>2]|0;if((c[b>>2]|0)!=137?(Ad(b)|0)!=0:0){g=1;i=e;return g|0}if((f|0)<=0){g=0;i=e;return g|0}Eg(d|0,0,f<<3|0)|0;j=c[b+8>>2]|0;k=b+20|0;b=0;while(1){l=+h[a+(b<<3)>>3]- +h[j+(b<<3)>>3];m=c[k>>2]|0;n=0;o=b;while(1){p=d+(n<<3)|0;h[p>>3]=+h[p>>3]+l*+h[m+(o<<3)>>3];n=n+1|0;if((n|0)==(f|0)){break}else{o=o+f|0}}o=b+1|0;if((o|0)==(f|0)){g=0;break}else{b=o}}i=e;return g|0}function Ed(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0,C=0.0,D=0.0;e=i;if((Hd(a,d)|0)!=0){f=1;i=e;return f|0}a=b+8|0;g=b+24|0;j=+h[g>>3]==999.0;k=d+16|0;l=+h[k>>3];do{if(!(l==90.0)){m=+h[b+16>>3];if(j){h[g>>3]=m>3]);o=+Re(+h[g>>3]);p=+Se(+h[g>>3]);q=+Re(+h[k>>3]);r=+Se(+h[k>>3]);s=o*q;o=+Q(+(s*s+r*r));do{if(o==0.0){if(m!=0.0){f=1;i=e;return f|0}else{t=+h[b+32>>3];break}}else{u=m/o;if(+P(+u)>1.0){f=1;i=e;return f|0}v=+Xe(r,s);w=+Ue(u);u=v+w;if(!(u>180.0)){if(u<-180.0){x=u+360.0}else{x=u}}else{x=u+-360.0}u=v-w;if(!(u>180.0)){if(u<-180.0){y=u+360.0}else{y=u}}else{y=u+-360.0}d=b+32|0;u=+h[d>>3];if(+P(+(u-x))<+P(+(u-y))){z=+P(+x)<90.0000000001;A=z?x:y}else{z=+P(+y)<90.0000000001;A=z?y:x}h[d>>3]=A;t=A}}while(0);d=b+40|0;z=b+48|0;h[z>>3]=90.0-t;s=n*+Re(t);do{if(+P(+s)<1.0e-10){if(+P(+n)<1.0e-10){o=+h[a>>3];h[d>>3]=o;h[z>>3]=90.0- +h[k>>3];B=a;C=o;break}if(t>0.0){o=+h[a>>3]+ +h[g>>3]+-180.0;h[d>>3]=o;h[z>>3]=0.0;B=a;C=o;break}if(t<0.0){o=+h[a>>3]- +h[g>>3];h[d>>3]=o;h[z>>3]=180.0;B=a;C=o;break}else{B=a;C=+h[d>>3];break}}else{o=(r-m*+Se(t))/s;u=p*q/n;if(o==0.0&u==0.0){f=1;i=e;return f|0}else{w=+h[a>>3];v=w- +Xe(u,o);h[d>>3]=v;B=a;C=v;break}}}while(0);if(!(+h[B>>3]>=0.0)){if(!(C>0.0)){D=t;break}h[d>>3]=C+-360.0;D=t;break}else{if(!(C<0.0)){D=t;break}h[d>>3]=C+360.0;D=t;break}}else{if(j){h[g>>3]=180.0}n=+h[b+16>>3];h[b+32>>3]=n;h[b+40>>3]=+h[a>>3];h[b+48>>3]=90.0-n;D=n}}while(0);h[b+56>>3]=+h[g>>3];g=b+48|0;h[b+64>>3]=+Re(+h[g>>3]);h[b+72>>3]=+Se(+h[g>>3]);c[b>>2]=137;b=+P(+D)>90.0000000001;f=b?2:0;i=e;return f|0}function Fd(a,b,d,e,f,g,j,k,l){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;m=i;if((c[e>>2]|0)!=137?(Ed(a,e,j)|0)!=0:0){n=1;i=m;return n|0}Pe(b,d,e+40|0,f,g)|0;e=lb[c[j+1888>>2]&63](+h[f>>3],+h[g>>3],j,k,l)|0;if((e|0)==0){n=0;i=m;return n|0}n=(e|0)==1?2:3;i=m;return n|0}function Gd(a,b,d,e,f,g,j,k,l){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;m=i;if((c[j>>2]|0)!=137?(Ed(a,j,e)|0)!=0:0){n=1;i=m;return n|0}a=lb[c[e+1892>>2]&63](b,d,e,f,g)|0;if((a|0)==0){Qe(+h[f>>3],+h[g>>3],j+40|0,k,l)|0;n=0;i=m;return n|0}else{n=(a|0)==1?2:3;i=m;return n|0}return 0}function Hd(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;e=i;if((yg(b,12080)|0)==0){Id(d)|0;f=0;i=e;return f|0}if((yg(b,12088)|0)==0){Jd(d)|0;f=0;i=e;return f|0}if((yg(b,12096)|0)==0){a[d]=5128532;a[d+1|0]=20033;a[d+2|0]=78;a[d+3|0]=0;g=d+4|0;c[g>>2]=(c[g>>2]>>31&-206)+103;h[d+8>>3]=0.0;h[d+16>>3]=90.0;g=d+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}c[d+1888>>2]=1;c[d+1892>>2]=2;g=99;while(1){if(!(+h[d+(g<<3)+280>>3]==0.0)){j=g;break}k=g+ -1|0;if(!(+h[d+(g+100<<3)+280>>3]==0.0)){j=g;break}if((g|0)>0){g=k}else{j=k;break}}c[d+276>>2]=(j|0)<0?0:j;f=0;i=e;return f|0}if((yg(b,12104)|0)==0){a[d]=4674643;a[d+1|0]=18260;a[d+2|0]=71;a[d+3|0]=0;c[d+4>>2]=104;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=114.59155902616465;h[d+120>>3]=.008726646259971648}else{m=l*2.0;h[d+112>>3]=m;h[d+120>>3]=1.0/m}c[d+1888>>2]=3;c[d+1892>>2]=4;f=0;i=e;return f|0}if((yg(b,12112)|0)==0){a[d]=5130579;a[d+1|0]=20041;a[d+2|0]=78;a[d+3|0]=0;j=d+4|0;c[j>>2]=(c[j>>2]>>31&-210)+105;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;m=+h[j>>3];if(m==0.0){h[j>>3]=57.29577951308232;n=57.29577951308232}else{n=m}h[d+112>>3]=1.0/n;n=+h[d+40>>3];m=+h[d+48>>3];l=n*n+m*m;h[d+120>>3]=l;h[d+128>>3]=l+1.0;h[d+136>>3]=l+-1.0;c[d+1888>>2]=5;c[d+1892>>2]=6;f=0;i=e;return f|0}if((yg(b,12120)|0)==0){a[d]=4411969;a[d+1|0]=17234;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=106;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{m=l*3.141592653589793/180.0;h[d+112>>3]=m;h[d+120>>3]=1.0/m}c[d+1888>>2]=7;c[d+1892>>2]=8;f=0;i=e;return f|0}if((yg(b,12128)|0)==0){Kd(d)|0;f=0;i=e;return f|0}if((yg(b,12136)|0)==0){a[d]=4277594;a[d+1|0]=16709;a[d+2|0]=65;a[d+3|0]=0;c[d+4>>2]=108;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;m=+h[j>>3];if(m==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=114.59155902616465;h[d+120>>3]=.008726646259971648}else{l=m*2.0;h[d+112>>3]=l;h[d+120>>3]=1.0/l}c[d+1888>>2]=9;c[d+1892>>2]=10;f=0;i=e;return f|0}if((yg(b,12144)|0)==0){a[d]=5392705;a[d+1|0]=21065;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=109;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;o=57.29577951308232}else{o=l}l=o*2.0;j=d+112|0;h[j>>3]=l;o=+h[d+40>>3];do{if(!(o==90.0)){if(o>-90.0){m=+Re((90.0-o)*.5);n=m*m;p=+_(+m)*n/(1.0-n);h[d+120>>3]=p;n=.5-p;h[d+128>>3]=n;q=n;r=+h[j>>3];break}else{f=0;i=e;return f|0}}else{h[d+120>>3]=-.5;h[d+128>>3]=1.0;q=1.0;r=l}}while(0);h[d+136>>3]=q*r;h[d+144>>3]=1.0e-4;h[d+152>>3]=q*1.0e-4;h[d+160>>3]=57.29577951308232/q;c[d+1888>>2]=11;c[d+1892>>2]=12;f=0;i=e;return f|0}if((yg(b,12152)|0)==0){a[d]=5265731;a[d+1|0]=20569;a[d+2|0]=80;a[d+3|0]=0;c[d+4>>2]=201;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];do{if(q==0.0){h[g>>3]=57.29577951308232;r=+h[d+48>>3];h[d+112>>3]=r;if(r==0.0){f=0;i=e;return f|0}h[d+120>>3]=1.0/r;l=(r+ +h[d+40>>3])*57.29577951308232;h[d+128>>3]=l;if(l==0.0){f=0;i=e;return f|0}else{h[d+136>>3]=1.0/l;break}}else{l=+h[d+48>>3];r=q*l*3.141592653589793/180.0;h[d+112>>3]=r;if(r==0.0){f=0;i=e;return f|0}h[d+120>>3]=1.0/r;r=q*(l+ +h[d+40>>3]);h[d+128>>3]=r;if(r==0.0){f=0;i=e;return f|0}else{h[d+136>>3]=1.0/r;break}}}while(0);c[d+1888>>2]=13;c[d+1892>>2]=14;f=0;i=e;return f|0}if((yg(b,12160)|0)==0){a[d]=4277571;a[d+1|0]=16709;a[d+2|0]=65;a[d+3|0]=0;c[d+4>>2]=202;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;q=+h[j>>3];do{if(q==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;r=+h[d+40>>3];if(r<=0.0|r>1.0){f=0;i=e;return f|0}else{h[d+128>>3]=57.29577951308232/r;h[d+136>>3]=r/57.29577951308232;break}}else{h[d+112>>3]=q*3.141592653589793/180.0;h[d+120>>3]=57.29577951308232/q;r=+h[d+40>>3];if(r<=0.0|r>1.0){f=0;i=e;return f|0}else{h[d+128>>3]=q/r;h[d+136>>3]=r/q;break}}}while(0);c[d+1888>>2]=15;c[d+1892>>2]=16;f=0;i=e;return f|0}if((yg(b,12168)|0)==0){a[d]=5390659;a[d+1|0]=21057;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=203;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{r=q*3.141592653589793/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r}c[d+1888>>2]=17;c[d+1892>>2]=18;f=0;i=e;return f|0}if((yg(b,12176)|0)==0){a[d]=5391693;a[d+1|0]=21061;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=204;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;r=+h[j>>3];if(r==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{q=r*3.141592653589793/180.0;h[d+112>>3]=q;h[d+120>>3]=1.0/q}c[d+1888>>2]=19;c[d+1892>>2]=20;f=0;i=e;return f|0}if((yg(b,12184)|0)==0){a[d]=4998739;a[d+1|0]=19526;a[d+2|0]=76;a[d+3|0]=0;c[d+4>>2]=301;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{r=q*3.141592653589793/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r}c[d+1888>>2]=21;c[d+1892>>2]=22;f=0;i=e;return f|0}if((yg(b,12192)|0)==0){a[d]=5390672;a[d+1|0]=21057;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=302;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;r=+h[j>>3];if(r==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;h[d+128>>3]=180.0;h[d+136>>3]=.005555555555555556}else{q=r*3.141592653589793;r=q/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r;h[d+128>>3]=q;h[d+136>>3]=1.0/q}c[d+1888>>2]=23;c[d+1892>>2]=24;f=0;i=e;return f|0}if((yg(b,12200)|0)==0){a[d]=5001037;a[d+1|0]=19535;a[d+2|0]=76;a[d+3|0]=0;c[d+4>>2]=303;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;s=57.29577951308232}else{s=q}q=s*1.4142135623730951;h[d+112>>3]=q;h[d+120>>3]=q/90.0;h[d+128>>3]=1.0/q;h[d+136>>3]=90.0/s;h[d+144>>3]=.6366197723675814;c[d+1888>>2]=25;c[d+1892>>2]=26;f=0;i=e;return f|0}if((yg(b,12208)|0)==0){a[d]=5523777;a[d+1|0]=21577;a[d+2|0]=84;a[d+3|0]=0;c[d+4>>2]=401;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;s=+h[j>>3];if(s==0.0){h[j>>3]=57.29577951308232;t=57.29577951308232}else{t=s}s=t*2.0;q=t*s;h[d+112>>3]=q;t=1.0/(q*2.0);h[d+120>>3]=t;h[d+128>>3]=t*.25;h[d+136>>3]=1.0/s;c[d+1888>>2]=27;c[d+1892>>2]=28;f=0;i=e;return f|0}if((yg(b,12216)|0)==0){Ld(d)|0;f=0;i=e;return f|0}if((yg(b,12224)|0)==0){Md(d)|0;f=0;i=e;return f|0}if((yg(b,12232)|0)==0){Nd(d)|0;f=0;i=e;return f|0}if((yg(b,12240)|0)==0){Od(d)|0;f=0;i=e;return f|0}if((yg(b,12248)|0)==0){Pd(d)|0;f=0;i=e;return f|0}if((yg(b,12256)|0)==0){a[d]=5194576;a[d+1|0]=20291;a[d+2|0]=79;a[d+3|0]=0;c[d+4>>2]=602;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;s=+h[g>>3];if(s==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;h[d+128>>3]=114.59155902616465}else{t=s*3.141592653589793/180.0;h[d+112>>3]=t;h[d+120>>3]=1.0/t;h[d+128>>3]=s*2.0}c[d+1888>>2]=29;c[d+1892>>2]=30;f=0;i=e;return f|0}if((yg(b,12264)|0)==0){a[d]=4412244;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=701;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;s=+h[j>>3];if(s==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{t=s*3.141592653589793*.25;h[d+112>>3]=t;h[d+120>>3]=1.0/t}c[d+1888>>2]=31;c[d+1892>>2]=32;f=0;i=e;return f|0}if((yg(b,12272)|0)==0){a[d]=4412227;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=702;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;t=+h[g>>3];if(t==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{s=t*3.141592653589793*.25;h[d+112>>3]=s;h[d+120>>3]=1.0/s}c[d+1888>>2]=33;c[d+1892>>2]=34;f=0;i=e;return f|0}if((yg(b,12280)|0)!=0){f=1;i=e;return f|0}a[d]=4412241;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=703;b=d+8|0;g=d+24|0;c[b+0>>2]=0;c[b+4>>2]=0;c[b+8>>2]=0;c[b+12>>2]=0;s=+h[g>>3];if(s==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{t=s*3.141592653589793*.25;h[d+112>>3]=t;h[d+120>>3]=1.0/t}c[d+1888>>2]=35;c[d+1892>>2]=36;f=0;i=e;return f|0}function Id(b){b=b|0;var d=0,e=0,f=0.0,g=0.0,j=0,k=0,l=0,m=0.0,n=0.0;d=i;a[b]=5265985;a[b+1|0]=20570;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-202)+101;h[b+8>>3]=0.0;h[b+16>>3]=90.0;e=b+24|0;f=+h[e>>3];if(f==0.0){h[e>>3]=57.29577951308232;g=57.29577951308232}else{g=f}e=b+40|0;f=g*(+h[e>>3]+1.0);h[b+112>>3]=f;if(f==0.0){j=1;i=d;return j|0}k=b+48|0;f=+Re(+h[k>>3]);l=b+136|0;h[l>>3]=f;if(f==0.0){j=1;i=d;return j|0}h[b+128>>3]=1.0/f;f=+Se(+h[k>>3]);h[b+144>>3]=f;g=+h[l>>3];h[b+120>>3]=f/g;f=+h[e>>3];if(+P(+f)>1.0){h[b+152>>3]=+Ve(-1.0/f);m=+h[e>>3];n=+h[l>>3]}else{h[b+152>>3]=-90.0;m=f;n=g}g=m*n;h[b+160>>3]=g;l=+P(+g)<1.0;h[b+168>>3]=l?1.0:0.0;c[b+1888>>2]=37;c[b+1892>>2]=38;j=0;i=d;return j|0}function Jd(b){b=b|0;var d=0,e=0,f=0.0,g=0.0,j=0,k=0,l=0,m=0,n=0,o=0;d=i;a[b]=5266003;a[b+1|0]=20570;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-204)+102;h[b+8>>3]=0.0;h[b+16>>3]=90.0;e=b+24|0;f=+h[e>>3];if(f==0.0){h[e>>3]=57.29577951308232;g=57.29577951308232}else{g=f}h[b+112>>3]=1.0/g;j=b+40|0;g=+h[j>>3];k=b+56|0;f=g*+Se(+h[k>>3])+1.0;l=b+136|0;h[l>>3]=f;if(f==0.0){m=1;i=d;return m|0}f=+h[j>>3];g=f*+Re(+h[k>>3]);n=b+48|0;o=b+120|0;h[o>>3]=-(g*+Se(+h[n>>3]));g=+h[j>>3];f=g*+Re(+h[k>>3]);g=f*+Re(+h[n>>3]);h[b+128>>3]=g;f=+h[e>>3];h[b+144>>3]=f*+h[o>>3];h[b+152>>3]=f*g;g=+h[l>>3];h[b+160>>3]=f*g;f=g+-1.0;h[b+168>>3]=g*f+-1.0;if(+P(+f)<1.0){h[b+176>>3]=+Ve(1.0-g)}else{h[b+176>>3]=-90.0}c[b+1888>>2]=39;c[b+1892>>2]=40;m=0;i=d;return m|0}function Kd(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0.0,l=0.0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0.0,C=0.0,D=0.0;d=i;a[b]=5132378;a[b+1|0]=20048;a[b+2|0]=78;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-214)+107;f=b+8|0;h[f>>3]=0.0;g=b+16|0;h[g>>3]=90.0;j=b+24|0;k=+h[j>>3];if(k==0.0){h[j>>3]=57.29577951308232;l=57.29577951308232}else{l=k}m=9;while(1){if(!(+h[b+(m<<3)+32>>3]==0.0)){break}if((m|0)>0){m=m+ -1|0}else{n=6;break}}if((n|0)==6){a[b]=4411969;a[b+1|0]=17234;a[b+2|0]=67;a[b+3|0]=0;c[e>>2]=106;h[f>>3]=0.0;h[g>>3]=90.0;if(l==0.0){h[j>>3]=57.29577951308232;h[b+112>>3]=1.0;h[b+120>>3]=1.0}else{k=l*3.141592653589793/180.0;h[b+112>>3]=k;h[b+120>>3]=1.0/k}c[b+1888>>2]=7;c[b+1892>>2]=8;o=0;i=d;return o|0}c[b+272>>2]=m;c[b+1888>>2]=41;c[b+1892>>2]=42;if((m|0)<=2){o=0;i=d;return o|0}k=+h[b+40>>3];if(k<=0.0){o=1;i=d;return o|0}j=(m|0)>0;a:do{if(j){l=k;g=0;p=0.0;while(1){q=+(g|0)*3.141592653589793/180.0;r=0.0;f=m;do{r=q*r+ +(f|0)*+h[b+(f<<3)+32>>3];f=f+ -1|0}while((f|0)>0);f=g+1|0;if(r<=0.0){s=l;t=r;u=g;v=p;w=q;break a}if((f|0)<180){l=r;g=f;p=q}else{s=r;t=r;u=f;v=q;w=q;break}}}else{s=k;t=0.0;u=0;v=0.0;w=0.0}}while(0);b:do{if((u|0)==180){x=3.141592653589793}else{if(j){y=s;z=t;A=1;B=v;C=w}else{x=v-s*(w-v)/(t-s);break}while(1){k=B-y*(C-B)/(z-y);p=0.0;g=m;do{p=k*p+ +(g|0)*+h[b+(g<<3)+32>>3];g=g+ -1|0}while((g|0)>0);if(+P(+p)<1.0e-13){x=k;break b}g=p<0.0;f=A+1|0;if((f|0)<11){y=g?y:p;z=g?p:z;A=f;B=g?B:k;C=g?k:C}else{x=k;break}}}}while(0);if((m|0)>-1){A=m;C=0.0;while(1){B=x*C+ +h[b+(A<<3)+32>>3];if((A|0)>0){A=A+ -1|0;C=B}else{D=B;break}}}else{D=0.0}h[b+112>>3]=x;h[b+120>>3]=D;o=0;i=d;return o|0}function Ld(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0;d=i;a[b]=5263171;a[b+1|0]=20559;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-1002)+501;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+Se(f);h[b+112>>3]=j;if(j==0.0){k=1;i=d;return k|0}h[b+120>>3]=1.0/j;j=+h[g>>3];f=j*+Re(+h[b+48>>3]);g=b+136|0;h[g>>3]=f;if(f==0.0){k=1;i=d;return k|0}h[b+144>>3]=1.0/f;f=1.0/+Te(+h[e>>3]);h[b+152>>3]=f;h[b+128>>3]=f*+h[g>>3];c[b+1888>>2]=43;c[b+1892>>2]=44;k=0;i=d;return k|0}function Md(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0;d=i;a[b]=4542275;a[b+1|0]=17743;a[b+2|0]=69;a[b+3|0]=0;c[b+4>>2]=502;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+h[b+48>>3];k=f-j;l=f+j;j=+Se(k);f=(j+ +Se(l))*.5;m=b+112|0;h[m>>3]=f;if(f==0.0){n=1;i=d;return n|0}h[b+120>>3]=1.0/f;o=b+136|0;h[o>>3]=+h[g>>3]/f;f=+Se(k);k=f*+Se(l)+1.0;h[b+144>>3]=k;l=+h[m>>3]*2.0;h[b+152>>3]=l;f=+h[o>>3];h[b+160>>3]=f*f*k;h[b+168>>3]=1.0/(+h[g>>3]*2.0*f);h[b+176>>3]=f*+Q(+(k+l));h[b+128>>3]=f*+Q(+(k-l*+Se(+h[e>>3])));c[b+1888>>2]=45;c[b+1892>>2]=46;n=0;i=d;return n|0}function Nd(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0,m=0,n=0.0,o=0;d=i;a[b]=4476739;a[b+1|0]=17487;a[b+2|0]=68;a[b+3|0]=0;c[b+4>>2]=503;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;j=+h[g>>3];if(j==0.0){h[g>>3]=57.29577951308232;k=57.29577951308232}else{k=j}l=b+48|0;m=+h[l>>3]==0.0;j=k*+Se(f);if(m){f=j*3.141592653589793/180.0;h[b+112>>3]=f;n=f}else{f=j*+Se(+h[l>>3]);j=f/+h[l>>3];h[b+112>>3]=j;n=j}if(n==0.0){o=1;i=d;return o|0}h[b+120>>3]=1.0/n;n=+h[g>>3];j=n*+Re(+h[l>>3]);n=j*+Re(+h[e>>3]);j=n/+h[b+112>>3];h[b+128>>3]=j;h[b+136>>3]=j+ +h[e>>3];c[b+1888>>2]=47;c[b+1892>>2]=48;o=0;i=d;return o|0}function Od(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0;d=i;a[b]=5197635;a[b+1|0]=20303;a[b+2|0]=79;a[b+3|0]=0;c[b+4>>2]=504;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+h[b+48>>3];k=f-j;l=f+j;j=+Te((90.0-k)*.5);f=+Re(k);if(k==l){m=+Se(k);h[b+112>>3]=m;n=m}else{m=+Te((90.0-l)*.5);k=+_(+(+Re(l)/f))/+_(+(m/j));h[b+112>>3]=k;n=k}if(n==0.0){o=1;i=d;return o|0}h[b+120>>3]=1.0/n;k=+h[g>>3]*(f/n)/+R(+j,+n);g=b+136|0;h[g>>3]=k;if(k==0.0){o=1;i=d;return o|0}n=+Te((90.0- +h[e>>3])*.5);h[b+128>>3]=k*+R(+n,+(+h[b+112>>3]));h[b+144>>3]=1.0/+h[g>>3];c[b+1888>>2]=49;c[b+1892>>2]=50;o=0;i=d;return o|0}function Pd(b){b=b|0;var d=0,e=0,f=0,g=0.0,j=0.0,k=0.0,l=0,m=0;d=i;a[b]=5132098;a[b+1|0]=20047;a[b+2|0]=78;a[b+3|0]=0;c[b+4>>2]=601;e=b+8|0;f=b+24|0;c[e+0>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;g=+h[f>>3];if(g==0.0){h[f>>3]=57.29577951308232;h[b+120>>3]=1.0;f=b+40|0;j=+Re(+h[f>>3])*57.29577951308232;k=j/+Se(+h[f>>3]);h[b+128>>3]=k+ +h[f>>3];l=b+1888|0;c[l>>2]=51;m=b+1892|0;c[m>>2]=52;i=d;return 0}else{h[b+120>>3]=g*3.141592653589793/180.0;f=b+40|0;k=+Re(+h[f>>3]);j=k/+Se(+h[f>>3]);h[b+128>>3]=g*(j+ +h[f>>3]*3.141592653589793/180.0);l=b+1888|0;c[l>>2]=51;m=b+1892|0;c[m>>2]=52;i=d;return 0}return 0}function Qd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=101?(Id(d)|0)!=0:0){l=1;i=g;return l|0}m=+Re(a);n=+Re(b);o=m*+h[d+120>>3];k=d+40|0;p=+h[k>>3];q=n*o+(p+ +Se(b));if(q==0.0){l=2;i=g;return l|0}p=n*+h[d+112>>3]/q;h[e>>3]=p*+Se(a);h[f>>3]=-(m*p*+h[d+128>>3]);if((c[j>>2]|0)>0){if(+h[d+152>>3]>b){l=2;i=g;return l|0}if(+h[d+168>>3]>0.0?(p=+h[k>>3]/+Q(+(o*o+1.0)),+P(+p)<=1.0):0){m=+We(-o);o=+Ve(p);p=m-o;a=m+o+180.0;if(p>90.0){r=p+-360.0}else{r=p}if(a>90.0){s=a+-360.0}else{s=a}if((r>s?r:s)>b){l=2;i=g;return l|0}}}l=0;i=g;return l|0}function Rd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=101?(Id(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+136>>3]*b;m=+Q(+(a*a+l*l));if(m==0.0){h[e>>3]=0.0;n=90.0}else{h[e>>3]=+Xe(a,-l);l=m/(+h[d+112>>3]+ +h[d+144>>3]*b);b=l*+h[d+40>>3]/+Q(+(l*l+1.0));m=+Xe(1.0,l);if(+P(+b)>1.0){l=b<0.0?-90.0:90.0;if(+P(+l)>1.0000000000001){k=2;i=g;return k|0}else{o=l}}else{o=+Ve(b)}b=m-o;l=m+o+180.0;if(b>90.0){p=b+-360.0}else{p=b}if(l>90.0){q=l+-360.0}else{q=l}n=p>q?p:q}h[f>>3]=n;k=0;i=g;return k|0}function Sd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=102?(Jd(d)|0)!=0:0){l=1;i=g;return l|0}m=+Re(a);n=+Se(a);a=+Re(b);o=1.0- +Se(b);k=d+136|0;p=+h[k>>3]-o;if(p==0.0){l=2;i=g;return l|0}q=d+160|0;h[e>>3]=(n*a*+h[q>>3]-o*+h[d+144>>3])/p;h[f>>3]=-(m*a*+h[q>>3]+o*+h[d+152>>3])/p;if((c[j>>2]|0)>0){if(+h[d+176>>3]>b){l=2;i=g;return l|0}if(+P(+(+h[d+40>>3]))>1.0?(p=n*+h[d+120>>3]-m*+h[d+128>>3],m=1.0/+Q(+(+h[d+168>>3]+p*p)),+P(+m)<=1.0):0){n=+Xe(p,+h[k>>3]+-1.0);p=+Ve(m);m=n-p;o=n+p+180.0;if(m>90.0){r=m+-360.0}else{r=m}if(o>90.0){s=o+-360.0}else{s=o}if((r>s?r:s)>b){l=2;i=g;return l|0}}}l=0;i=g;return l|0}function Td(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=102?(Jd(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+112>>3];m=l*a;a=l*b;b=m*m+a*a;l=+h[d+136>>3];n=(m- +h[d+120>>3])/l;o=(a- +h[d+128>>3])/l;l=m*n+a*o;do{if(!(b<1.0e-10)){p=n*n+o*o;q=p+1.0;r=l-p;s=r*r-q*(p+(b-l-l)+-1.0);if(s<0.0){k=2;i=g;return k|0}p=+Q(+s);s=(p-r)/q;t=(-r-p)/q;q=s>t?s:t;if(q>1.0){if(q+-1.0<1.0e-13){u=1.0}else{u=s-1.0e-13?-1.0:u;if(q>1.0|q<-1.0){k=2;i=g;return k|0}else{h[f>>3]=+Ve(q);v=1.0-q;break}}else{h[f>>3]=90.0- +Q(+(b/(l+1.0)))*57.29577951308232;v=b*.5}}while(0);h[e>>3]=+Xe(m-n*v,-(a-o*v));k=0;i=g;return k|0}function Ud(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+16|0;k=j;l=e+4|0;m=c[l>>2]|0;if((((m|0)>-1?m:0-m|0)|0)!=103){a[e]=5128532;a[e+1|0]=20033;a[e+2|0]=78;a[e+3|0]=0;c[l>>2]=(m>>31&-206)+103;h[e+8>>3]=0.0;h[e+16>>3]=90.0;m=e+24|0;if(+h[m>>3]==0.0){h[m>>3]=57.29577951308232}c[e+1888>>2]=1;c[e+1892>>2]=2;m=99;while(1){if(!(+h[e+(m<<3)+280>>3]==0.0)){n=m;break}o=m+ -1|0;if(!(+h[e+(m+100<<3)+280>>3]==0.0)){n=m;break}if((m|0)>0){m=o}else{n=o;break}}c[e+276>>2]=(n|0)<0?0:n}p=+Se(d);if(p<=0.0){i=j;return 2}q=+h[e+24>>3];r=q*+Re(d)/p;h[k>>3]=r*+Se(b);n=k+8|0;h[n>>3]=-(r*+Re(b));m=c[e+1880>>2]|0;if((m|0)==0){s=+h[k>>3]}else{s=+sd(m,k)}h[f>>3]=s;f=c[e+1884>>2]|0;if((f|0)==0){t=+h[n>>3];h[g>>3]=t;u=c[l>>2]|0;v=(u|0)>0;w=p<0.0;x=v&w;y=x?2:0;i=j;return y|0}else{t=+sd(f,k);h[g>>3]=t;u=c[l>>2]|0;v=(u|0)>0;w=p<0.0;x=v&w;y=x?2:0;i=j;return y|0}return 0}function Vd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0;j=i;i=i+16|0;k=j+8|0;l=j;m=e+4|0;n=c[m>>2]|0;if((((n|0)>-1?n:0-n|0)|0)==103){o=c[e+276>>2]|0}else{a[e]=5128532;a[e+1|0]=20033;a[e+2|0]=78;a[e+3|0]=0;c[m>>2]=(n>>31&-206)+103;h[e+8>>3]=0.0;h[e+16>>3]=90.0;n=e+24|0;if(+h[n>>3]==0.0){h[n>>3]=57.29577951308232}c[e+1888>>2]=1;c[e+1892>>2]=2;n=99;while(1){if(!(+h[e+(n<<3)+280>>3]==0.0)){p=n;break}m=n+ -1|0;if(!(+h[e+(n+100<<3)+280>>3]==0.0)){p=n;break}if((n|0)>0){n=m}else{p=m;break}}n=(p|0)<0?0:p;c[e+276>>2]=n;o=n}if((o|0)==0){h[k>>3]=b;h[l>>3]=d;q=b;r=d}else{Wd(e,b,d,k,l)|0;q=+h[k>>3];r=+h[l>>3]}d=+Q(+(q*q+r*r));if(d==0.0){s=0.0;h[f>>3]=s;t=e+24|0;u=+h[t>>3];v=+Xe(u,d);h[g>>3]=v;i=j;return 0}s=+Xe(q,-r);h[f>>3]=s;t=e+24|0;u=+h[t>>3];v=+Xe(u,d);h[g>>3]=v;i=j;return 0}function Wd(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,P=0.0,R=0.0,S=0.0,T=0.0,U=0.0,V=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0,va=0.0,wa=0.0,xa=0.0,ya=0.0,za=0.0,Aa=0.0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0.0,Fa=0.0,Ga=0.0,Ha=0.0,Ia=0.0,Ja=0.0,Ka=0.0,La=0.0,Ma=0.0,Na=0.0,Oa=0.0,Pa=0.0;g=i;j=c[a+276>>2]|0;k=+h[a+1080>>3]+ +h[a+1088>>3]*b;l=+h[a+280>>3]+ +h[a+288>>3]*d;if((j|0)!=1){m=k+ +h[a+1096>>3]*d;n=l+ +h[a+296>>3]*b;if((j|0)!=2){o=b*b;p=d*d;q=+Q(+(o+p));r=m+q*+h[a+1104>>3];s=n+q*+h[a+304>>3];if((j|0)!=3){t=r+o*+h[a+1112>>3];u=s+p*+h[a+312>>3];if((j|0)!=4){v=b*d;w=t+v*+h[a+1120>>3];x=u+v*+h[a+320>>3];if((j|0)!=5){v=w+p*+h[a+1128>>3];y=x+o*+h[a+328>>3];if((j|0)!=6){z=o*b;A=v+z*+h[a+1136>>3];B=p*d;C=y+B*+h[a+336>>3];if((j|0)!=7){D=A+o*+h[a+1144>>3]*d;E=C+p*+h[a+344>>3]*b;if((j|0)!=8){F=D+p*+h[a+1152>>3]*b;G=E+o*+h[a+352>>3]*d;if((j|0)!=9){H=F+B*+h[a+1160>>3];I=G+z*+h[a+360>>3];if((j|0)!=10){J=q*q*q;K=H+J*+h[a+1168>>3];L=I+J*+h[a+368>>3];if((j|0)!=11){M=o*o;N=K+M*+h[a+1176>>3];O=p*p;P=L+O*+h[a+376>>3];if((j|0)!=12){R=N+z*+h[a+1184>>3]*d;S=P+B*+h[a+384>>3]*b;if((j|0)!=13){T=R+p*o*+h[a+1192>>3];U=S+p*o*+h[a+392>>3];if((j|0)!=14){V=T+B*+h[a+1200>>3]*b;W=U+z*+h[a+400>>3]*d;if((j|0)!=15){X=V+O*+h[a+1208>>3];Y=W+M*+h[a+408>>3];if((j|0)!=16){Z=M*b;_=X+Z*+h[a+1216>>3];$=O*d;aa=Y+$*+h[a+416>>3];if((j|0)!=17){ba=_+M*+h[a+1224>>3]*d;ca=aa+O*+h[a+424>>3]*b;if((j|0)!=18){da=ba+p*z*+h[a+1232>>3];ea=ca+o*B*+h[a+432>>3];if((j|0)!=19){fa=da+B*o*+h[a+1240>>3];ga=ea+z*p*+h[a+440>>3];if((j|0)!=20){ha=fa+O*+h[a+1248>>3]*b;ia=ga+M*+h[a+448>>3]*d;if((j|0)!=21){ja=ha+$*+h[a+1256>>3];ka=ia+Z*+h[a+456>>3];if((j|0)!=22){la=q*q*J;J=ja+la*+h[a+1264>>3];ma=ka+la*+h[a+464>>3];if((j|0)!=23){na=Z*b;oa=J+na*+h[a+1272>>3];pa=$*d;qa=ma+pa*+h[a+472>>3];if((j|0)!=24){ra=oa+Z*+h[a+1280>>3]*d;sa=qa+$*+h[a+480>>3]*b;if((j|0)!=25){ta=ra+p*M*+h[a+1288>>3];ua=sa+o*O*+h[a+488>>3];if((j|0)!=26){va=ta+B*z*+h[a+1296>>3];wa=ua+z*B*+h[a+496>>3];if((j|0)!=27){xa=va+O*o*+h[a+1304>>3];ya=wa+M*p*+h[a+504>>3];if((j|0)!=28){za=xa+$*+h[a+1312>>3]*b;Aa=ya+Z*+h[a+512>>3]*d;if((j|0)!=29){Ba=za+pa*+h[a+1320>>3];Ca=Aa+na*+h[a+520>>3];if((j|0)!=30){Da=na*b;Ea=Ba+Da*+h[a+1328>>3];Fa=pa*d;Ga=Ca+Fa*+h[a+528>>3];if((j|0)!=31){Ha=Ea+na*+h[a+1336>>3]*d;Ia=Ga+pa*+h[a+536>>3]*b;if((j|0)!=32){Ja=Ha+p*Z*+h[a+1344>>3];Ka=Ia+o*$*+h[a+544>>3];if((j|0)!=33){La=Ja+B*M*+h[a+1352>>3];Ma=Ka+z*O*+h[a+552>>3];if((j|0)!=34){Na=La+O*z*+h[a+1360>>3];z=Ma+M*B*+h[a+560>>3];if((j|0)!=35){B=Na+$*o*+h[a+1368>>3];o=z+Z*p*+h[a+568>>3];if((j|0)!=36){p=B+pa*+h[a+1376>>3]*b;b=o+na*+h[a+576>>3]*d;if((j|0)!=37){d=p+Fa*+h[a+1384>>3];Fa=b+Da*+h[a+584>>3];if((j|0)==38){Oa=d;Pa=Fa}else{Da=q*q*la;Oa=d+Da*+h[a+1392>>3];Pa=Fa+Da*+h[a+592>>3]}}else{Oa=p;Pa=b}}else{Oa=B;Pa=o}}else{Oa=Na;Pa=z}}else{Oa=La;Pa=Ma}}else{Oa=Ja;Pa=Ka}}else{Oa=Ha;Pa=Ia}}else{Oa=Ea;Pa=Ga}}else{Oa=Ba;Pa=Ca}}else{Oa=za;Pa=Aa}}else{Oa=xa;Pa=ya}}else{Oa=va;Pa=wa}}else{Oa=ta;Pa=ua}}else{Oa=ra;Pa=sa}}else{Oa=oa;Pa=qa}}else{Oa=J;Pa=ma}}else{Oa=ja;Pa=ka}}else{Oa=ha;Pa=ia}}else{Oa=fa;Pa=ga}}else{Oa=da;Pa=ea}}else{Oa=ba;Pa=ca}}else{Oa=_;Pa=aa}}else{Oa=X;Pa=Y}}else{Oa=V;Pa=W}}else{Oa=T;Pa=U}}else{Oa=R;Pa=S}}else{Oa=N;Pa=P}}else{Oa=K;Pa=L}}else{Oa=H;Pa=I}}else{Oa=F;Pa=G}}else{Oa=D;Pa=E}}else{Oa=A;Pa=C}}else{Oa=v;Pa=y}}else{Oa=w;Pa=x}}else{Oa=t;Pa=u}}else{Oa=r;Pa=s}}else{Oa=m;Pa=n}}else{Oa=k;Pa=l}h[e>>3]=Oa;h[f>>3]=Pa;i=g;return 0}function Xd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0,o=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=104){a[e]=4674643;a[e+1|0]=18260;a[e+2|0]=71;a[e+3|0]=0;c[k>>2]=104;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=3;c[e+1892>>2]=4}m=+Se(d)+1.0;if(m==0.0){n=2;i=j;return n|0}l=+h[e+112>>3];o=l*+Re(d)/m;h[f>>3]=o*+Se(b);h[g>>3]=-(o*+Re(b));n=0;i=j;return n|0}function Yd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=104){a[e]=4674643;a[e+1|0]=18260;a[e+2|0]=71;a[e+3|0]=0;c[k>>2]=104;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=3;c[e+1892>>2]=4}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0;h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=+We(q);s=r*2.0;t=90.0-s;h[g>>3]=t;i=j;return 0}n=+Xe(b,-d);h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=+We(q);s=r*2.0;t=90.0-s;h[g>>3]=t;i=j;return 0}function Zd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0;j=i;k=e+4|0;l=c[k>>2]|0;if((((l|0)>-1?l:0-l|0)|0)!=105){a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;c[k>>2]=(l>>31&-210)+105;h[e+8>>3]=0.0;h[e+16>>3]=90.0;l=e+24|0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;n=57.29577951308232}else{n=m}h[e+112>>3]=1.0/n;n=+h[e+40>>3];m=+h[e+48>>3];o=n*n+m*m;h[e+120>>3]=o;h[e+128>>3]=o+1.0;h[e+136>>3]=o+-1.0;c[e+1888>>2]=5;c[e+1892>>2]=6}o=(90.0- +P(+d))*3.141592653589793/180.0;if(o<1.0e-5){m=o*o*.5;if(d>0.0){p=o;q=m}else{p=o;q=2.0-m}}else{m=1.0- +Se(d);p=+Re(d);q=m}m=+Re(b);o=+Se(b);l=e+24|0;r=e+40|0;h[f>>3]=+h[l>>3]*(p*o+q*+h[r>>3]);f=e+48|0;h[g>>3]=-(+h[l>>3]*(p*m-q*+h[f>>3]));do{if((c[k>>2]|0)>0){if(+h[e+120>>3]==0.0){if(d<0.0){s=2}else{break}i=j;return s|0}else{if(d<-+We(o*+h[r>>3]-m*+h[f>>3])){s=2}else{break}i=j;return s|0}}}while(0);s=0;i=j;return s|0}function _d(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0;j=i;k=e+4|0;l=c[k>>2]|0;if((((l|0)>-1?l:0-l|0)|0)==105){m=+h[e+112>>3];n=+h[e+120>>3]}else{a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;c[k>>2]=(l>>31&-210)+105;h[e+8>>3]=0.0;h[e+16>>3]=90.0;l=e+24|0;o=+h[l>>3];if(o==0.0){h[l>>3]=57.29577951308232;p=57.29577951308232}else{p=o}o=1.0/p;h[e+112>>3]=o;p=+h[e+40>>3];q=+h[e+48>>3];r=p*p+q*q;h[e+120>>3]=r;h[e+128>>3]=r+1.0;h[e+136>>3]=r+-1.0;c[e+1888>>2]=5;c[e+1892>>2]=6;m=o;n=r}r=m*b;b=m*d;d=r*r+b*b;if(n==0.0){if(d!=0.0){s=+Xe(r,-b)}else{s=0.0}h[f>>3]=s;if(d<.5){h[g>>3]=+Ue(+Q(+d));t=0;i=j;return t|0}if(!(d<=1.0)){t=2;i=j;return t|0}h[g>>3]=+Ve(+Q(+(1.0-d)));t=0;i=j;return t|0}l=e+40|0;k=e+48|0;s=r*+h[l>>3]+b*+h[k>>3];do{if(!(d<1.0e-10)){m=+h[e+128>>3];o=s-n;q=o*o-m*(d-s-s+ +h[e+136>>3]);if(q<0.0){t=2;i=j;return t|0}p=+Q(+q);q=(p-o)/m;u=(-o-p)/m;m=q>u?q:u;if(m>1.0){if(m+-1.0<1.0e-13){v=1.0}else{v=q-1.0e-13?-1.0:v;if(m>1.0|m<-1.0){t=2;i=j;return t|0}else{h[g>>3]=+Ve(m);w=1.0-m;break}}else{h[g>>3]=90.0- +Q(+(d/(s+1.0)))*57.29577951308232;w=d*.5}}while(0);d=w*+h[k>>3]-b;b=r-w*+h[l>>3];if(d==0.0&b==0.0){h[f>>3]=0.0;t=0;i=j;return t|0}else{h[f>>3]=+Xe(b,d);t=0;i=j;return t|0}return 0}function $d(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==106){l=+h[e+112>>3];m=90.0-d;n=m*l;o=+Se(b);p=n*o;h[f>>3]=p;q=+Re(b);r=n*q;s=-r;h[g>>3]=s;i=j;return 0}a[e]=4411969;a[e+1|0]=17234;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=106;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;t=+h[k>>3];if(t==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;u=1.0}else{v=t*3.141592653589793/180.0;h[e+112>>3]=v;h[e+120>>3]=1.0/v;u=v}c[e+1888>>2]=7;c[e+1892>>2]=8;l=u;m=90.0-d;n=m*l;o=+Se(b);p=n*o;h[f>>3]=p;q=+Re(b);r=n*q;s=-r;h[g>>3]=s;i=j;return 0}function ae(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0,p=0.0,q=0.0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=106){a[e]=4411969;a[e+1|0]=17234;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=106;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0}else{m=l*3.141592653589793/180.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=7;c[e+1892>>2]=8}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0;h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=90.0-q;h[g>>3]=r;i=j;return 0}n=+Xe(b,-d);h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=90.0-q;h[g>>3]=r;i=j;return 0}function be(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=107?(Kd(d)|0)!=0:0){l=1;i=g;return l|0}m=(90.0-b)*3.141592653589793/180.0;b=(m*(m*(m*(m*(m*(m*(m*(m*(m*(m*0.0+ +h[d+104>>3])+ +h[d+96>>3])+ +h[d+88>>3])+ +h[d+80>>3])+ +h[d+72>>3])+ +h[d+64>>3])+ +h[d+56>>3])+ +h[d+48>>3])+ +h[d+40>>3])+ +h[d+32>>3])*+h[d+24>>3];h[e>>3]=b*+Se(a);h[f>>3]=-(b*+Re(a));if((c[j>>2]|0)>0?m>+h[d+112>>3]:0){l=2;i=g;return l|0}l=0;i=g;return l|0}function ce(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=107?(Kd(d)|0)!=0:0){k=1;i=g;return k|0}j=c[d+272>>2]|0;l=+Q(+(a*a+b*b));m=l/+h[d+24>>3];if((j|0)<1){k=1;i=g;return k|0}a:do{if((j|0)==2){l=+h[d+48>>3];n=+h[d+40>>3];o=n*n-l*4.0*(+h[d+32>>3]-m);if(o<0.0){k=2;i=g;return k|0}p=+Q(+o);o=l*2.0;l=(p-n)/o;q=(-n-p)/o;o=lq?l:q}else{r=o}if(r<0.0){if(r<-1.0e-13){k=2}else{s=0.0;break}i=g;return k|0}if(r>3.141592653589793){if(r>3.141592653589893){k=2;i=g;return k|0}else{s=3.141592653589793}}else{s=r}}else if((j|0)==1){s=(m- +h[d+32>>3])/+h[d+40>>3]}else{o=+h[d+32>>3];q=+h[d+112>>3];l=+h[d+120>>3];if(ml){if(m>l+1.0e-13){k=2}else{s=q;break}i=g;return k|0}if((j|0)>-1){t=0;u=o;v=l;w=0.0;x=q}else{p=0.0-m;y=0;n=o;o=l;l=0.0;z=q;while(1){q=(o-m)/(o-n);if(!(q<.1)){if(q>.9){A=.9}else{A=q}}else{A=.1}q=z-(z-l)*A;if(m>0.0){if(m<1.0e-13){s=q;break a}else{B=0.0;C=o;D=q;E=z}}else{if(p<1.0e-13){s=q;break a}else{B=n;C=0.0;D=l;E=q}}F=y+1|0;if(!(+P(+(E-D))<1.0e-13)&(F|0)<100){y=F;n=B;o=C;l=D;z=E}else{s=q;break a}}}while(1){z=(v-m)/(v-u);if(!(z<.1)){if(z>.9){G=.9}else{G=z}}else{G=.1}z=x-(x-w)*G;y=j;l=0.0;while(1){l=z*l+ +h[d+(y<<3)+32>>3];if((y|0)<=0){break}else{y=y+ -1|0}}if(l>3]=L;h[f>>3]=90.0-s*180.0/3.141592653589793;k=0;i=g;return k|0}function de(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==108){l=+h[e+112>>3]}else{a[e]=4277594;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=108;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;m=+h[k>>3];if(m==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648;n=114.59155902616465}else{o=m*2.0;h[e+112>>3]=o;h[e+120>>3]=1.0/o;n=o}c[e+1888>>2]=9;c[e+1892>>2]=10;l=n}n=l*+Se((90.0-d)*.5);h[f>>3]=n*+Se(b);h[g>>3]=-(n*+Re(b));i=j;return 0}function ee(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0;j=i;k=e+4|0;if((c[k>>2]|0)!=108){a[e]=4277594;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=108;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=9;c[e+1892>>2]=10}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0}else{n=+Xe(b,-d)}h[f>>3]=n;n=m*+h[e+120>>3];if(+P(+n)>1.0){if(+P(+(m- +h[e+112>>3]))<1.0e-12){o=-90.0}else{p=2;i=j;return p|0}}else{o=90.0- +Ve(n)*2.0}h[g>>3]=o;p=0;i=j;return p|0}function fe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=109){a[e]=5392705;a[e+1|0]=21065;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=109;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;m=57.29577951308232}else{m=l}l=m*2.0;k=e+112|0;h[k>>3]=l;m=+h[e+40>>3];do{if(!(m==90.0)){if(m>-90.0){n=+Re((90.0-m)*.5);o=n*n;p=+_(+n)*o/(1.0-o);h[e+120>>3]=p;o=.5-p;h[e+128>>3]=o;q=o;r=+h[k>>3];break}else{s=1;i=j;return s|0}}else{h[e+120>>3]=-.5;h[e+128>>3]=1.0;q=1.0;r=l}}while(0);h[e+136>>3]=q*r;h[e+144>>3]=1.0e-4;h[e+152>>3]=q*1.0e-4;h[e+160>>3]=57.29577951308232/q;c[e+1888>>2]=11;c[e+1892>>2]=12}do{if(!(d==90.0)){if(!(d>-90.0)){s=2;i=j;return s|0}q=90.0-d;r=q*.017453292519943295*.5;if(r<+h[e+144>>3]){t=r*+h[e+136>>3];break}else{r=+Re(q*.5);q=+Q(+(1.0-r*r))/r;l=+_(+r)/q;t=-(+h[e+112>>3]*(l+q*+h[e+120>>3]));break}}else{t=0.0}}while(0);h[f>>3]=t*+Se(b);h[g>>3]=-(t*+Re(b));s=0;i=j;return s|0}function ge(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0,A=0.0,B=0.0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==109){l=+h[e+112>>3]}else{a[e]=5392705;a[e+1|0]=21065;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=109;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;m=+h[k>>3];if(m==0.0){h[k>>3]=57.29577951308232;n=57.29577951308232}else{n=m}m=n*2.0;k=e+112|0;h[k>>3]=m;n=+h[e+40>>3];do{if(!(n==90.0)){if(n>-90.0){o=+Re((90.0-n)*.5);p=o*o;q=+_(+o)*p/(1.0-p);h[e+120>>3]=q;p=.5-q;h[e+128>>3]=p;r=p;s=+h[k>>3];break}else{t=1;i=j;return t|0}}else{h[e+120>>3]=-.5;h[e+128>>3]=1.0;r=1.0;s=m}}while(0);h[e+136>>3]=r*s;h[e+144>>3]=1.0e-4;h[e+152>>3]=r*1.0e-4;h[e+160>>3]=57.29577951308232/r;c[e+1888>>2]=11;c[e+1892>>2]=12;l=s}s=+Q(+(b*b+d*d))/l;if(s==0.0){u=0.0;v=0.0}else{do{if(!(s<+h[e+152>>3])){l=+h[e+120>>3];k=0;r=0.0;m=1.0;while(1){w=m*.5;n=+Q(+(1.0-w*w))/w;x=-(+_(+w)/n+n*l);y=k+1|0;if(s<=x){z=k;A=r;B=m;break}if((y|0)<30){k=y;r=x;m=w}else{z=y;A=x;B=w;break}}if((z|0)==30){t=2;i=j;return t|0}else{C=0;D=A;E=x;F=B;G=w}while(1){m=(E-s)/(E-D);if(!(m<.1)){if(m>.9){H=.9}else{H=m}}else{H=.1}I=G-(G-F)*H;m=+Q(+(1.0-I*I))/I;r=+_(+I)/m+m*l;m=-r;if(s>m){if(s+r<1.0e-12){J=C;break}else{K=m;L=E;M=I;N=G}}else{if(m-s<1.0e-12){J=C;break}else{K=D;L=m;M=F;N=I}}k=C+1|0;if((k|0)<100){C=k;D=K;E=L;F=M;G=N}else{J=k;break}}if((J|0)==100){t=2;i=j;return t|0}else{O=+Ue(I);break}}else{O=s*+h[e+160>>3]}}while(0);u=+Xe(b,-d);v=O}h[f>>3]=u;h[g>>3]=90.0-v*2.0;t=0;i=j;return t|0}function he(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==201){l=+h[e+40>>3]}else{a[e]=5265731;a[e+1|0]=20569;a[e+2|0]=80;a[e+3|0]=0;c[k>>2]=201;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;o=+h[e+48>>3];h[e+112>>3]=o;if(o==0.0){p=1;i=j;return p|0}h[e+120>>3]=1.0/o;q=+h[e+40>>3];r=(o+q)*57.29577951308232;h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=q;break}}else{q=+h[e+48>>3];r=n*q*3.141592653589793/180.0;h[e+112>>3]=r;if(r==0.0){p=1;i=j;return p|0}h[e+120>>3]=1.0/r;r=+h[e+40>>3];o=n*(q+r);h[e+128>>3]=o;if(o==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/o;s=r;break}}}while(0);c[e+1888>>2]=13;c[e+1892>>2]=14;l=s}s=l+ +Re(d);if(s==0.0){p=2;i=j;return p|0}h[f>>3]=+h[e+112>>3]*b;b=+h[e+128>>3];h[g>>3]=b*+Se(d)/s;p=0;i=j;return p|0}function ie(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==201){l=+h[e+120>>3]}else{a[e]=5265731;a[e+1|0]=20569;a[e+2|0]=80;a[e+3|0]=0;c[k>>2]=201;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;o=+h[e+48>>3];h[e+112>>3]=o;if(o==0.0){p=1;i=j;return p|0}q=1.0/o;h[e+120>>3]=q;r=(o+ +h[e+40>>3])*57.29577951308232;h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=q;break}}else{q=+h[e+48>>3];r=n*q*3.141592653589793/180.0;h[e+112>>3]=r;if(r==0.0){p=1;i=j;return p|0}o=1.0/r;h[e+120>>3]=o;r=n*(q+ +h[e+40>>3]);h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=o;break}}}while(0);c[e+1888>>2]=13;c[e+1892>>2]=14;l=s}h[f>>3]=l*b;b=+h[e+136>>3]*d;d=+Xe(b,1.0);h[g>>3]=d+ +Ve(b*+h[e+40>>3]/+Q(+(b*b+1.0)));p=0;i=j;return p|0}function je(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==202){l=+h[e+112>>3]}else{a[e]=4277571;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=202;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=+h[e+40>>3];if(o<=0.0|o>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=57.29577951308232/o;h[e+136>>3]=o/57.29577951308232;q=1.0;break}}else{o=n*3.141592653589793/180.0;h[e+112>>3]=o;h[e+120>>3]=57.29577951308232/n;r=+h[e+40>>3];if(r<=0.0|r>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=n/r;h[e+136>>3]=r/n;q=o;break}}}while(0);c[e+1888>>2]=15;c[e+1892>>2]=16;l=q}h[f>>3]=l*b;b=+h[e+128>>3];h[g>>3]=b*+Se(d);p=0;i=j;return p|0}function ke(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==202){l=+h[e+136>>3]}else{a[e]=4277571;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=202;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=+h[e+40>>3];if(o<=0.0|o>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=57.29577951308232/o;q=o/57.29577951308232;h[e+136>>3]=q;r=q;break}}else{h[e+112>>3]=n*3.141592653589793/180.0;h[e+120>>3]=57.29577951308232/n;q=+h[e+40>>3];if(q<=0.0|q>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=n/q;o=q/n;h[e+136>>3]=o;r=o;break}}}while(0);c[e+1888>>2]=15;c[e+1892>>2]=16;l=r}r=l*d;d=+P(+r);do{if(d>1.0){if(d>1.0000000000001){p=2;i=j;return p|0}else{s=r<0.0?-1.0:1.0;break}}else{s=r}}while(0);h[f>>3]=+h[e+120>>3]*b;h[g>>3]=+Ve(s);p=0;i=j;return p|0}function le(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==203){l=e+112|0;m=l;n=+h[l>>3];o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}a[e]=5390659;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=203;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;r=+h[l>>3];if(r==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;s=1.0}else{t=r*3.141592653589793/180.0;h[e+112>>3]=t;h[e+120>>3]=1.0/t;s=t}c[e+1888>>2]=17;c[e+1892>>2]=18;m=e+112|0;n=s;o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}function me(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==203){l=e+120|0;m=l;n=+h[l>>3];o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}a[e]=5390659;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=203;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;r=+h[l>>3];if(r==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;s=1.0}else{t=r*3.141592653589793/180.0;h[e+112>>3]=t;r=1.0/t;h[e+120>>3]=r;s=r}c[e+1888>>2]=17;c[e+1892>>2]=18;m=e+120|0;n=s;o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}function ne(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0;j=i;k=e+4|0;if((c[k>>2]|0)!=204){a[e]=5391693;a[e+1|0]=21061;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=204;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0}else{n=m*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=19;c[e+1892>>2]=20}if(d<=-90.0|d>=90.0){o=2;i=j;return o|0}h[f>>3]=+h[e+112>>3]*b;b=+h[e+24>>3];h[g>>3]=b*+_(+(+Te((d+90.0)*.5)));o=0;i=j;return o|0}function oe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0,o=0.0,p=0.0,q=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==204){l=e+24|0;m=+h[e+120>>3]}else{a[e]=5391693;a[e+1|0]=21061;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=204;k=e+8|0;n=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;o=+h[n>>3];if(o==0.0){h[n>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;p=1.0}else{q=o*3.141592653589793/180.0;h[e+112>>3]=q;o=1.0/q;h[e+120>>3]=o;p=o}c[e+1888>>2]=19;c[e+1892>>2]=20;l=n;m=p}h[f>>3]=m*b;h[g>>3]=+We(+Z(+(d/+h[l>>3])))*2.0+-90.0;i=j;return 0}function pe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==301){l=e+112|0;m=l;n=+h[l>>3];o=n*b;p=+Re(d);q=o*p;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;t=+h[l>>3];if(t==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;u=1.0}else{v=t*3.141592653589793/180.0;h[e+112>>3]=v;h[e+120>>3]=1.0/v;u=v}c[e+1888>>2]=21;c[e+1892>>2]=22;m=e+112|0;n=u;o=n*b;p=+Re(d);q=o*p;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}function qe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==301){l=+h[e+24>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=57.29577951308232}else{p=n*3.141592653589793/180.0;h[e+112>>3]=p;h[e+120>>3]=1.0/p;o=n}c[e+1888>>2]=21;c[e+1892>>2]=22;l=o}o=+S(+(d/l));m=e+120|0;if(o==0.0){q=0.0;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}q=+h[m>>3]*b/o;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}function re(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=302){a[e]=5390672;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=302;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=180.0;h[e+136>>3]=.005555555555555556}else{n=m*3.141592653589793;m=n/180.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m;h[e+128>>3]=n;h[e+136>>3]=1.0/n}c[e+1888>>2]=23;c[e+1892>>2]=24}n=+Se(d/3.0);h[f>>3]=+h[e+112>>3]*b*(1.0-n*n*4.0);h[g>>3]=n*+h[e+128>>3];i=j;return 0}function se(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==302){l=+h[e+136>>3]}else{a[e]=5390672;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=302;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=180.0;h[e+136>>3]=.005555555555555556;o=.005555555555555556}else{p=n*3.141592653589793;n=p/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;h[e+128>>3]=p;n=1.0/p;h[e+136>>3]=n;o=n}c[e+1888>>2]=23;c[e+1892>>2]=24;l=o}o=l*d;if(o>1.0|o<-1.0){q=2;i=j;return q|0}d=1.0-o*o*4.0;if(d==0.0){if(b==0.0){r=0.0}else{q=2;i=j;return q|0}}else{r=+h[e+120>>3]*b/d}h[f>>3]=r;h[g>>3]=+Ve(o)*3.0;q=0;i=j;return q|0}function te(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=303){a[e]=5001037;a[e+1|0]=19535;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=303;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;n=57.29577951308232}else{n=m}m=n*1.4142135623730951;h[e+112>>3]=m;h[e+120>>3]=m/90.0;h[e+128>>3]=1.0/m;h[e+136>>3]=90.0/n;h[e+144>>3]=.6366197723675814;c[e+1888>>2]=25;c[e+1892>>2]=26}if(+P(+d)==90.0){h[f>>3]=0.0;n=+P(+(+h[e+112>>3]));if(d<0.0){o=-n}else{o=n}h[g>>3]=o;i=j;return 0}if(d==0.0){h[f>>3]=+h[e+120>>3]*b;h[g>>3]=0.0;i=j;return 0}o=+Se(d)*3.141592653589793;l=0;d=o;n=-3.141592653589793;m=3.141592653589793;while(1){p=d-o+ +T(+d);if(p<0.0){if(p>-1.0e-13){q=d;break}else{r=d;s=m}}else{if(p<1.0e-13){q=d;break}else{r=n;s=d}}p=(r+s)*.5;k=l+1|0;if((k|0)<100){l=k;d=p;n=r;m=s}else{q=p;break}}s=q*.5;h[f>>3]=+h[e+120>>3]*b*+S(+s);h[g>>3]=+h[e+112>>3]*+T(+s);i=j;return 0}function ue(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==303){l=+h[e+24>>3]}else{a[e]=5001037;a[e+1|0]=19535;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=303;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;o=57.29577951308232}else{o=n}n=o*1.4142135623730951;h[e+112>>3]=n;h[e+120>>3]=n/90.0;h[e+128>>3]=1.0/n;h[e+136>>3]=90.0/o;h[e+144>>3]=.6366197723675814;c[e+1888>>2]=25;c[e+1892>>2]=26;l=o}o=d/l;l=2.0-o*o;if(l<=1.0e-12){if(l<-1.0e-12){p=2;i=j;return p|0}if(+P(+b)>1.0e-12){p=2;i=j;return p|0}else{q=0.0;r=0.0}}else{n=+Q(+l);q=n;r=+h[e+136>>3]*b/n}h[f>>3]=r;r=+h[e+128>>3]*d;d=+P(+r);do{if(d>1.0){if(d>1.000000000001){p=2;i=j;return p|0}else{s=(r<0.0?-1.0:1.0)+o*q/3.141592653589793;break}}else{n=+W(+r);s=n*+h[e+144>>3]+o*q/3.141592653589793}}while(0);q=+P(+s);do{if(q>1.0){if(q>1.000000000001){p=2;i=j;return p|0}else{t=s<0.0?-1.0:1.0;break}}else{t=s}}while(0);h[g>>3]=+Ve(t);p=0;i=j;return p|0}function ve(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==401){l=e+112|0}else{a[e]=5523777;a[e+1|0]=21577;a[e+2|0]=84;a[e+3|0]=0;c[k>>2]=401;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;o=57.29577951308232}else{o=n}n=o*2.0;p=o*n;m=e+112|0;h[m>>3]=p;o=1.0/(p*2.0);h[e+120>>3]=o;h[e+128>>3]=o*.25;h[e+136>>3]=1.0/n;c[e+1888>>2]=27;c[e+1892>>2]=28;l=m}n=+Re(d);o=+h[l>>3];p=b*.5;b=+Q(+(o/(n*+Re(p)+1.0)));h[f>>3]=+Se(p)*n*b*2.0;h[g>>3]=b*+Se(d);i=j;return 0}function we(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==401){l=+h[e+128>>3];m=+h[e+120>>3]}else{a[e]=5523777;a[e+1|0]=21577;a[e+2|0]=84;a[e+3|0]=0;c[k>>2]=401;k=e+8|0;n=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;o=+h[n>>3];if(o==0.0){h[n>>3]=57.29577951308232;p=57.29577951308232}else{p=o}o=p*2.0;q=p*o;h[e+112>>3]=q;p=1.0/(q*2.0);h[e+120>>3]=p;q=p*.25;h[e+128>>3]=q;h[e+136>>3]=1.0/o;c[e+1888>>2]=27;c[e+1892>>2]=28;l=q;m=p}p=1.0-b*b*l-d*d*m;if(p<0.0){if(p<-1.0e-13){r=2;i=j;return r|0}else{s=0.0}}else{s=p}p=+Q(+s);s=p*d/+h[e+24>>3];d=+P(+s);do{if(d>1.0){if(d>1.0000000000001){r=2;i=j;return r|0}else{t=s<0.0?-1.0:1.0;break}}else{t=s}}while(0);s=p*p*2.0+-1.0;d=p*b*+h[e+136>>3];if(s==0.0&d==0.0){u=0.0}else{u=+Xe(d,s)*2.0}h[f>>3]=u;h[g>>3]=+Ve(t);r=0;i=j;return r|0}function xe(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0,p=0.0,q=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=501?(Ld(d)|0)!=0:0){l=1;i=g;return l|0}m=b- +h[d+40>>3];b=+Re(m);if(b==0.0){l=2;i=g;return l|0}k=d+112|0;n=+h[k>>3]*a;o=d+128|0;a=+h[o>>3];p=+h[d+136>>3];q=a-p*+Se(m)/b;h[e>>3]=q*+Se(n);b=+h[o>>3];h[f>>3]=b-q*+Re(n);if((c[j>>2]|0)>0?q*+h[k>>3]<0.0:0){l=2;i=g;return l|0}l=0;i=g;return l|0}function ye(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=501?(Ld(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+128>>3]-b;b=+Q(+(a*a+l*l));j=d+40|0;if(+h[j>>3]<0.0){m=-b}else{m=b}if(m==0.0){n=0.0}else{n=+Xe(a/m,l/m)}h[e>>3]=n*+h[d+120>>3];n=+h[j>>3];h[f>>3]=n+ +We(+h[d+152>>3]-m*+h[d+144>>3]);k=0;i=g;return k|0}function ze(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0;g=i;if((c[d+4>>2]|0)!=502?(Md(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+112>>3]*a;if(b==-90.0){l=+h[d+176>>3]}else{a=+h[d+136>>3];m=+h[d+144>>3];n=+h[d+152>>3];l=a*+Q(+(m-n*+Se(b)))}h[e>>3]=l*+Se(k);b=+h[d+128>>3];h[f>>3]=b-l*+Re(k);j=0;i=g;return j|0}function Ae(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0;g=i;if((c[d+4>>2]|0)!=502?(Md(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){m=0.0}else{m=+Xe(a/l,k/l)}h[e>>3]=m*+h[d+120>>3];if(+P(+(l- +h[d+176>>3]))<1.0e-12){h[f>>3]=-90.0;j=0;i=g;return j|0}m=(+h[d+160>>3]-l*l)*+h[d+168>>3];if(!(+P(+m)>1.0)){h[f>>3]=+Ve(m);j=0;i=g;return j|0}if(+P(+(m+-1.0))<1.0e-12){h[f>>3]=90.0;j=0;i=g;return j|0}if(!(+P(+(m+1.0))<1.0e-12)){j=2;i=g;return j|0}h[f>>3]=-90.0;j=0;i=g;return j|0}function Be(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0;g=i;if((c[d+4>>2]|0)!=503?(Nd(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+112>>3]*a;a=+h[d+136>>3]-b;h[e>>3]=a*+Se(k);b=+h[d+128>>3];h[f>>3]=b-a*+Re(k);j=0;i=g;return j|0}function Ce(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0;g=i;if((c[d+4>>2]|0)!=503?(Nd(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){m=0.0}else{m=+Xe(a/l,k/l)}h[e>>3]=m*+h[d+120>>3];h[f>>3]=+h[d+136>>3]-l;j=0;i=g;return j|0}function De(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0;g=i;if((c[d+4>>2]|0)!=504?(Od(d)|0)!=0:0){j=1;i=g;return j|0}k=d+112|0;l=+h[k>>3];m=l*a;if(b==-90.0){if(l<0.0){n=0.0}else{j=2;i=g;return j|0}}else{l=+h[d+136>>3];a=+Te((90.0-b)*.5);n=l*+R(+a,+(+h[k>>3]))}h[e>>3]=n*+Se(m);a=+h[d+128>>3];h[f>>3]=a-n*+Re(m);j=0;i=g;return j|0}function Ee(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0;g=i;if((c[d+4>>2]|0)!=504?(Od(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){h[e>>3]=+h[d+120>>3]*0.0;if(+h[d+112>>3]<0.0){m=-90.0}else{j=2;i=g;return j|0}}else{b=+Xe(a/l,k/l);n=d+120|0;h[e>>3]=b*+h[n>>3];m=90.0- +We(+R(+(l*+h[d+144>>3]),+(+h[n>>3])))*2.0}h[f>>3]=m;j=0;i=g;return j|0}function Fe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0;j=i;k=e+4|0;l=c[k>>2]|0;if(!(+h[e+40>>3]==0.0)){if((l|0)!=601){Pd(e)|0}m=e+128|0;n=+h[m>>3]- +h[e+120>>3]*d;o=+h[e+24>>3]*b;p=o*+Re(d)/n;h[f>>3]=n*+Se(p);o=+h[m>>3];q=o-n*+Re(p);h[g>>3]=q;i=j;return 0}if((l|0)==301){l=e+112|0;r=l;s=+h[l>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;p=+h[l>>3];if(p==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;t=1.0}else{n=p*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;t=n}c[e+1888>>2]=21;c[e+1892>>2]=22;r=e+112|0;s=t}h[f>>3]=s*b*+Re(d);q=+h[r>>3]*d;h[g>>3]=q;i=j;return 0}function Ge(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0;j=i;k=e+40|0;l=+h[k>>3];m=e+4|0;n=c[m>>2]|0;if(l==0.0){if((n|0)==301){o=+h[e+24>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[m>>2]=301;m=e+8|0;p=e+24|0;c[m+0>>2]=0;c[m+4>>2]=0;c[m+8>>2]=0;c[m+12>>2]=0;q=+h[p>>3];if(q==0.0){h[p>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;r=57.29577951308232}else{s=q*3.141592653589793/180.0;h[e+112>>3]=s;h[e+120>>3]=1.0/s;r=q}c[e+1888>>2]=21;c[e+1892>>2]=22;o=r}r=+S(+(d/o));p=e+120|0;if(r==0.0){t=0.0}else{t=+h[p>>3]*b/r}h[f>>3]=t;h[g>>3]=+h[p>>3]*d;i=j;return 0}else{if((n|0)==601){u=l}else{Pd(e)|0;u=+h[k>>3]}k=e+128|0;l=+h[k>>3];t=l-d;d=+Q(+(b*b+t*t));if(u<0.0){v=-d}else{v=d}if(v==0.0){w=l;x=0.0}else{l=+Xe(b/v,t/v);w=+h[k>>3];x=l}l=(w-v)/+h[e+120>>3];h[g>>3]=l;w=+Re(l);if(w==0.0){y=0.0}else{y=x*(v/+h[e+24>>3])/w}h[f>>3]=y;i=j;return 0}return 0}function He(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=602){a[e]=5194576;a[e+1|0]=20291;a[e+2|0]=79;a[e+3|0]=0;c[k>>2]=602;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=114.59155902616465}else{n=m*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;h[e+128>>3]=m*2.0}c[e+1888>>2]=29;c[e+1892>>2]=30}m=+Re(d);n=+Se(d);o=n*b;if(n==0.0){h[f>>3]=+h[e+112>>3]*b;p=0.0;h[g>>3]=p;i=j;return 0}else{b=m/n;l=e+24|0;n=b*+h[l>>3];h[f>>3]=n*+Se(o);n=+h[l>>3];p=n*(d*3.141592653589793/180.0+b*(1.0- +Re(o)));h[g>>3]=p;i=j;return 0}return 0}function Ie(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0,y=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==602){l=+h[e+120>>3]}else{a[e]=5194576;a[e+1|0]=20291;a[e+2|0]=79;a[e+3|0]=0;c[k>>2]=602;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=114.59155902616465;o=1.0}else{p=n*3.141592653589793/180.0;h[e+112>>3]=p;q=1.0/p;h[e+120>>3]=q;h[e+128>>3]=n*2.0;o=q}c[e+1888>>2]=29;c[e+1892>>2]=30;l=o}o=+P(+(l*d));if(o<1.0e-12){h[f>>3]=l*b;h[g>>3]=0.0;i=j;return 0}if(+P(+(o+-90.0))<1.0e-12){h[f>>3]=0.0;h[g>>3]=d<0.0?-90.0:90.0;i=j;return 0}o=d>0.0?90.0:-90.0;l=b*b;m=e+112|0;q=d-o*+h[m>>3];k=e+128|0;n=-999.0;p=l+q*q;r=0;q=0.0;s=o;while(1){if(n<-100.0){t=(q+s)*.5}else{o=p/(p-n);if(!(o<.1)){if(o>.9){u=.9}else{u=o}}else{u=.1}t=s-(s-q)*u}h[g>>3]=t;v=d-t*+h[m>>3];w=+Te(t);o=l+v*(v- +h[k>>3]/w);if(+P(+o)<1.0e-12){break}if(+P(+(s-q))<1.0e-12){break}x=o>0.0;y=+h[g>>3];r=r+1|0;if((r|0)>=64){break}else{n=x?n:o;p=x?o:p;q=x?q:y;s=x?y:s}}s=+h[e+24>>3]-w*v;v=w*b;if(s==0.0&v==0.0){h[f>>3]=0.0;i=j;return 0}else{b=+Xe(v,s);h[f>>3]=b/+Se(+h[g>>3]);i=j;return 0}return 0}function Je(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=701){a[e]=4412244;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=701;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=31;c[e+1892>>2]=32}n=+Re(d);m=n*+Re(b);o=n*+Se(b);b=+Se(d);l=m>b;d=l?m:b;k=o>d;n=k?o:d;d=-m;p=n1.0){if(u>1.000000000001){z=2;i=j;return z|0}else{A=w<0.0?-1.0:1.0;break}}else{A=w}}while(0);w=+P(+y);do{if(w>1.0){if(w>1.000000000001){z=2;i=j;return z|0}else{B=y<0.0?-1.0:1.0;break}}else{B=y}}while(0);l=e+112|0;h[f>>3]=(v+A)*+h[l>>3];h[g>>3]=(x+B)*+h[l>>3];z=0;i=j;return z|0}function Ke(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==701){l=+h[e+120>>3]}else{a[e]=4412244;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=701;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=31;c[e+1892>>2]=32;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){o=r+-4.0;d=-1.0/+Q(+(b*b+(o*o+1.0)));s=d;t=o*d;u=-(b*d);break}if(r>1.0){d=r+-2.0;o=1.0/+Q(+(b*b+(d*d+1.0)));s=-(d*o);t=o;u=b*o;break}if(b>1.0){o=b+-2.0;d=1.0/+Q(+(o*o+(r*r+1.0)));s=-(o*d);t=r*d;u=d;break}if(b<-1.0){d=b+2.0;o=-1.0/+Q(+(d*d+(r*r+1.0)));l=-o;s=d*l;t=r*l;u=o;break}else{o=1.0/+Q(+(b*b+(r*r+1.0)));s=o;t=r*o;u=b*o;break}}else{o=r+-6.0;l=-1.0/+Q(+(b*b+(o*o+1.0)));d=-l;s=o*d;t=l;u=b*d}}while(0);if(s==0.0&t==0.0){v=0.0}else{v=+Xe(t,s)}h[f>>3]=v;h[g>>3]=+Ve(u);q=0;i=j;return q|0}function Le(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0,E=0.0,F=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=702){a[e]=4412227;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=702;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=33;c[e+1892>>2]=34}n=+Re(d);m=n*+Re(b);o=n*+Se(b);b=+Se(d);l=m>b;d=l?m:b;k=o>d;n=k?o:d;d=-m;p=n1.0e-16){A=u*u}else{A=0.0}if(w>1.0e-16){B=w*w}else{B=0.0}if(b>1.0e-16){C=u*w*.15384112298488617}else{C=0.0}b=o*(u+m*(u*(-.15959623456001282-m*(u*-.021776249632239342+.07591962069272995))+(w*(u*.004869491793215275+m*-.1316167116165161+n*(B*.10695946961641312+(A*-.1782512068748474+(u*.08097013086080551+.14118963479995728+w*-.2815285325050354+C))))+1.374848484992981)));o=y*(w+n*(w*(-.15959623456001282-n*(w*-.021776249632239342+.07591962069272995))+(u*(w*.004869491793215275+n*-.1316167116165161+m*(A*.10695946961641312+(B*-.1782512068748474+(u*-.2815285325050354+(w*.08097013086080551+.14118963479995728)+C))))+1.374848484992981)));C=+P(+b);do{if(C>1.0){if(C>1.0000001000000012){D=2;i=j;return D|0}else{E=b<0.0?-1.0:1.0;break}}else{E=b}}while(0);b=+P(+o);do{if(b>1.0){if(b>1.0000001000000012){D=2;i=j;return D|0}else{F=o<0.0?-1.0:1.0;break}}else{F=o}}while(0);l=e+112|0;h[f>>3]=(x+E)*+h[l>>3];h[g>>3]=+h[l>>3]*(z+F);D=0;i=j;return D|0}function Me(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==702){l=+h[e+120>>3]}else{a[e]=4412227;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=702;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=33;c[e+1892>>2]=34;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){s=3;t=r+-4.0;u=b;break}if(r>1.0){s=2;t=r+-2.0;u=b;break}if(b>1.0){s=0;t=r;u=b+-2.0;break}if(b<-1.0){s=5;t=r;u=b+2.0}else{s=1;t=r;u=b}}else{s=4;t=r+-6.0;u=b}}while(0);b=t*t;r=u*u;o=t;t=o+o*(1.0-b)*(b*(b*(b*(b*(b*(b*.025843750685453415+.25795793533325195)+-.6293006539344788)+.5485238432884216)+-.22797055542469025)+-.07629968971014023)+-.2729269564151764+r*(b*(b*(b*(b*(b*-.5302233695983887+1.715475082397461)+-1.7411445379257202)+.48051509261131287)+-.014715650118887424)+-.028194520622491837+r*(b*(b*(b*(b*-.8318046927452087+.9893810153007507)+.30803316831588745)+-.5680093765258789)+.27058160305023193+r*(b*(b*(b*.08693841099739075+-.9367857575416565)+1.5088008642196655)+-.6044155955314636+r*(b*(b*.3388744592666626+-1.4160192012786865)+.934120774269104+r*(r*.14381584525108337+(b*.5203223824501038+-.6391530632972717)))))));o=u;u=o+o*(1.0-r)*(r*(r*(r*(r*(r*(r*.025843750685453415+.25795793533325195)+-.6293006539344788)+.5485238432884216)+-.22797055542469025)+-.07629968971014023)+-.2729269564151764+b*(r*(r*(r*(r*(r*-.5302233695983887+1.715475082397461)+-1.7411445379257202)+.48051509261131287)+-.014715650118887424)+-.028194520622491837+b*(r*(r*(r*(r*-.8318046927452087+.9893810153007507)+.30803316831588745)+-.5680093765258789)+.27058160305023193+b*(r*(r*(r*.08693841099739075+-.9367857575416565)+1.5088008642196655)+-.6044155955314636+b*(r*(r*.3388744592666626+-1.4160192012786865)+.934120774269104+b*(r*.5203223824501038+-.6391530632972717+b*.14381584525108337))))));switch(s|0){case 1:{b=1.0/+Q(+(u*u+t*t+1.0));v=b;w=t*b;x=u*b;break};case 4:{b=-1.0/+Q(+(u*u+t*t+1.0));v=-t*b;w=b;x=-u*b;break};case 0:{b=1.0/+Q(+(u*u+t*t+1.0));v=-u*b;w=t*b;x=b;break};case 5:{b=-1.0/+Q(+(u*u+t*t+1.0));v=-u*b;w=-t*b;x=b;break};case 3:{b=-1.0/+Q(+(u*u+t*t+1.0));v=b;w=t*b;x=-u*b;break};case 2:{b=1.0/+Q(+(u*u+t*t+1.0));v=-t*b;w=b;x=u*b;break};default:{v=0.0;w=0.0;x=0.0}}if(v==0.0&w==0.0){y=0.0}else{y=+Xe(w,v)}h[f>>3]=y;h[g>>3]=+Ve(x);q=0;i=j;return q|0}function Ne(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0,t=0.0,u=0,v=0.0,w=0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=703){a[e]=4412241;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=703;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=35;c[e+1892>>2]=36}if(+P(+d)==90.0){h[f>>3]=0.0;n=+P(+(+h[e+112>>3]*2.0));if(d<0.0){o=-n}else{o=n}h[g>>3]=o;p=0;i=j;return p|0}o=+Re(d);n=o*+Re(b);m=o*+Se(b);o=+Se(d);l=n>o;q=l?n:o;k=m>q;r=k?m:q;q=-n;s=r180.0){z=y+-360.0}else{z=y}y=z*.017453292519943295;A=o;B=(v*v+y*y)*.5;C=0.0;D=m;E=0.0}else{A=o;B=x;C=0.0;D=m;E=0.0}break};case 3:{if(x<1.0e-8){y=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v<0.0){F=v+360.0}else{F=v}v=(180.0-F)*3.141592653589793/180.0;A=o;B=(y*y+v*v)*.5;C=4.0;D=r;E=0.0}else{A=o;B=x;C=4.0;D=r;E=0.0}break};case 0:{if(x<1.0e-8){r=(90.0-d)*3.141592653589793/180.0;A=q;B=r*r*.5;C=0.0;D=m;E=2.0}else{A=q;B=x;C=0.0;D=m;E=2.0}break};case 2:{if(x<1.0e-8){r=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v<-180.0){G=v+360.0}else{G=v}v=(90.0-G)*3.141592653589793/180.0;A=o;B=(r*r+v*v)*.5;C=2.0;D=q;E=0.0}else{A=o;B=x;C=2.0;D=q;E=0.0}break};case 4:{if(x<1.0e-8){q=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v>180.0){H=v+-360.0}else{H=v}v=H*((H+90.0)*3.141592653589793/180.0);A=o;B=(q*q+v*v)*.5;C=6.0;D=n;E=0.0}else{A=o;B=x;C=6.0;D=n;E=0.0}break};case 5:{if(x<1.0e-8){o=(d+90.0)*3.141592653589793/180.0;A=n;B=o*o*.5;C=0.0;D=m;E=-2.0}else{A=n;B=x;C=0.0;D=m;E=-2.0}break};default:{A=0.0;B=x;C=0.0;D=0.0;E=0.0}}do{if(!(D==0.0&A==0.0)){x=+P(+A);if(x<=-D){m=A/D;n=m*m+1.0;o=-+Q(+(B/(1.0-1.0/+Q(+(n+1.0)))));d=+We(m);I=o;J=o/15.0*(d- +Ve(m/+Q(+(n+n))));break}if(D>=x){x=A/D;n=x*x+1.0;m=+Q(+(B/(1.0-1.0/+Q(+(n+1.0)))));d=+We(x);I=m;J=m/15.0*(d- +Ve(x/+Q(+(n+n))));break}n=+P(+D);if(n<-A){x=D/A;d=x*x+1.0;m=-+Q(+(B/(1.0-1.0/+Q(+(d+1.0)))));o=+We(x);I=m/15.0*(o- +Ve(x/+Q(+(d+d))));J=m;break}if(A>n){n=D/A;m=n*n+1.0;d=+Q(+(B/(1.0-1.0/+Q(+(m+1.0)))));x=+We(n);I=d/15.0*(x- +Ve(n/+Q(+(m+m))));J=d}else{I=0.0;J=0.0}}else{I=0.0;J=0.0}}while(0);B=+P(+I);do{if(B>1.0){if(B>1.000000000001){p=2;i=j;return p|0}else{K=I<0.0?-1.0:1.0;break}}else{K=I}}while(0);I=+P(+J);do{if(I>1.0){if(I>1.000000000001){p=2;i=j;return p|0}else{L=J<0.0?-1.0:1.0;break}}else{L=J}}while(0);l=e+112|0;h[f>>3]=(C+K)*+h[l>>3];h[g>>3]=(E+L)*+h[l>>3];p=0;i=j;return p|0}function Oe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,S=0.0,T=0.0,U=0.0,V=0.0,W=0.0,X=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==703){l=+h[e+120>>3]}else{a[e]=4412241;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=703;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=35;c[e+1892>>2]=36;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){s=3;t=r+-4.0;u=b;break}if(r>1.0){s=2;t=r+-2.0;u=b;break}if(b>1.0){s=0;t=r;u=b+-2.0;break}if(b<-1.0){s=5;t=r;u=b+2.0}else{s=1;t=r;u=b}}else{s=4;t=r+-6.0;u=b}}while(0);e=+P(+t)>+P(+u);if(e){if(t==0.0){v=0.0;w=1.0;x=0.0;y=1.0;z=30}else{b=u*15.0/t;r=+Se(b);o=r/(+Re(b)+-.7071067811865475);b=o*o+1.0;A=t*t*(1.0-1.0/+Q(+(b+1.0)));B=o;C=b;z=28}}else{if(u==0.0){v=0.0;w=1.0;x=0.0;y=1.0;z=30}else{b=t*15.0/u;o=+Se(b);r=o/(+Re(b)+-.7071067811865475);b=r*r+1.0;A=u*u*(1.0-1.0/+Q(+(b+1.0)));B=r;C=b;z=28}}if((z|0)==28){b=1.0-A;if(b<-1.0){if(b<-1.000000000001){q=2;i=j;return q|0}else{D=B;E=-1.0;F=0.0}}else{v=B;w=b;x=A;y=C;z=30}}if((z|0)==30){D=v;E=w;F=+Q(+(x*(2.0-x)/y))}a:do{switch(s|0){case 2:{if(e){if(t>0.0){G=-F}else{G=F}H=G;I=E;J=-(D*G);break a}else{if(u<0.0){K=-F}else{K=F}H=-(D*K);I=E;J=K;break a}break};case 3:{y=-E;if(e){if(t>0.0){L=-F}else{L=F}H=y;I=L;J=-(D*L);break a}else{if(u<0.0){M=-F}else{M=F}H=y;I=-(D*M);J=M;break a}break};case 1:{if(e){if(t<0.0){N=-F}else{N=F}H=E;I=N;J=D*N;break a}else{if(u<0.0){O=-F}else{O=F}H=E;I=D*O;J=O;break a}break};case 5:{y=-E;if(e){if(t<0.0){R=-F}else{R=F}H=D*R;I=R;J=y;break a}else{if(u<0.0){S=-F}else{S=F}H=S;I=D*S;J=y;break a}break};case 4:{y=-E;if(e){if(t<0.0){T=-F}else{T=F}H=T;I=y;J=D*T;break a}else{if(u<0.0){U=-F}else{U=F}H=D*U;I=y;J=U;break a}break};case 0:{if(e){if(t<0.0){V=-F}else{V=F}H=-(D*V);I=V;J=E;break a}else{if(u>0.0){W=-F}else{W=F}H=W;I=-(D*W);J=E;break a}break};default:{H=0.0;I=0.0;J=0.0}}}while(0);if(H==0.0&I==0.0){X=0.0}else{X=+Xe(I,H)}h[f>>3]=X;h[g>>3]=+Ve(J);q=0;i=j;return q|0}function Pe(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;f=i;g=+Re(b);j=+Se(b);k=a- +h[c>>3];a=+Re(k);l=+Se(k);m=c+32|0;n=c+24|0;o=j*+h[m>>3]-a*g*+h[n>>3];if(+P(+o)<1.0e-5){p=+Re(+h[c+8>>3]+b);q=(1.0-a)*g*+h[n>>3]-p}else{q=o}o=g*l;if(q!=0.0|o!=-0.0){r=+Xe(-o,q)}else{r=k+-180.0}l=r+ +h[c+16>>3];h[d>>3]=l;if(!(l>180.0)){if(l<-180.0){h[d>>3]=l+360.0}}else{h[d>>3]=l+-360.0}if(+qa(+k,180.0)==0.0){k=a*+h[c+8>>3]+b;if(k>90.0){s=180.0-k}else{s=k}h[e>>3]=s;if(!(s<-90.0)){i=f;return 0}h[e>>3]=-180.0-s;i=f;return 0}s=j*+h[n>>3]+a*g*+h[m>>3];if(!(+P(+s)>.99)){h[e>>3]=+Ve(s);i=f;return 0}g=+Ue(+Q(+(o*o+q*q)));if(s<0.0){h[e>>3]=-g;i=f;return 0}else{h[e>>3]=g;i=f;return 0}return 0}function Qe(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;f=i;g=+Re(b);j=+Se(b);k=a- +h[c+16>>3];a=+Re(k);l=+Se(k);m=c+32|0;n=c+24|0;o=j*+h[m>>3]-a*g*+h[n>>3];if(+P(+o)<1.0e-5){p=+Re(+h[c+8>>3]+b);q=(1.0-a)*g*+h[n>>3]-p}else{q=o}o=g*l;if(q!=0.0|o!=-0.0){r=+Xe(-o,q)}else{r=k+180.0}l=r+ +h[c>>3];h[d>>3]=l;if(!(+h[c>>3]>=0.0)){if(l>0.0){r=l+-360.0;h[d>>3]=r;s=r}else{s=l}}else{if(l<0.0){r=l+360.0;h[d>>3]=r;s=r}else{s=l}}if(!(s>360.0)){if(s<-360.0){h[d>>3]=s+360.0}}else{h[d>>3]=s+-360.0}if(+qa(+k,180.0)==0.0){k=a*+h[c+8>>3]+b;if(k>90.0){t=180.0-k}else{t=k}h[e>>3]=t;if(!(t<-90.0)){i=f;return 0}h[e>>3]=-180.0-t;i=f;return 0}t=j*+h[n>>3]+a*g*+h[m>>3];if(!(+P(+t)>.99)){h[e>>3]=+Ve(t);i=f;return 0}g=+Ue(+Q(+(o*o+q*q)));if(t<0.0){h[e>>3]=-g;i=f;return 0}else{h[e>>3]=g;i=f;return 0}return 0}function Re(a){a=+a;var b=0,c=0.0,d=0.0,e=0.0;b=i;c=+qa(+a,360.0);d=+P(+c);if(!(c==0.0)){if(!(d==90.0)){if(!(d==180.0)){if(d==270.0){e=0.0}else{e=+S(+(a*.017453292519943295))}}else{e=-1.0}}else{e=0.0}}else{e=1.0}i=b;return+e}function Se(a){a=+a;var b=0,c=0.0,d=0.0;b=i;c=+qa(+(a+-90.0),360.0);if(!(c==0.0)){if(!(c==90.0)){if(!(c==180.0)){if(c==270.0){d=0.0}else{d=+T(+(a*.017453292519943295))}}else{d=-1.0}}else{d=0.0}}else{d=1.0}i=b;return+d}function Te(a){a=+a;var b=0,c=0.0,d=0.0;b=i;c=+qa(+a,360.0);if(!(c==0.0)?!(+P(+c)==180.0):0){if(!(c==45.0|c==225.0)){if(c==-135.0|c==-315.0){d=-1.0}else{d=+U(+(a*.017453292519943295))}}else{d=1.0}}else{d=0.0}i=b;return+d}function Ue(a){a=+a;var b=0,c=0.0,d=0;b=i;if(!(a>=1.0)){if(!(a==0.0)){if(a<=-1.0&a+1.0>-1.0e-10){c=180.0}else{d=5}}else{c=90.0}}else{if(a+-1.0<1.0e-10){c=0.0}else{d=5}}if((d|0)==5){c=+V(+a)*57.29577951308232}i=b;return+c}function Ve(a){a=+a;var b=0,c=0.0,d=0;b=i;if(!(a<=-1.0)){if(!(a==0.0)){if(a>=1.0&a+-1.0<1.0e-10){c=90.0}else{d=5}}else{c=0.0}}else{if(a+1.0>-1.0e-10){c=-90.0}else{d=5}}if((d|0)==5){c=+W(+a)*57.29577951308232}i=b;return+c}function We(a){a=+a;var b=0,c=0.0;b=i;if(!(a==-1.0)){if(!(a==0.0)){if(a==1.0){c=45.0}else{c=+X(+a)*57.29577951308232}}else{c=0.0}}else{c=-45.0}i=b;return+c}function Xe(a,b){a=+a;b=+b;var c=0,d=0.0,e=0;c=i;if(a==0.0){if(!(b>=0.0)){if(b<0.0){d=180.0}else{e=7}}else{d=0.0}}else{if(b==0.0){if(!(a>0.0)){if(a<0.0){d=-90.0}else{e=7}}else{d=90.0}}else{e=7}}if((e|0)==7){d=+Y(+a,+b)*57.29577951308232}i=c;return+d}function Ye(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;i=i+32|0;e=d;f=d+8|0;if((c[a+5968>>2]|0)!=1){i=d;return}g=a+3324|0;if((c[g>>2]|0)==2){c[g>>2]=3;c[a+5976>>2]=0;c[a+6784>>2]=0;c[a+7592>>2]=0;c[a+8400>>2]=0;i=d;return}g=a+5976|0;if((Ec(b,12288,g)|0)!=0){h=c[g>>2]|0;g=(h|0)<0;if(!g){j=(h<<3)+8|0;k=0;while(1){Eg(a+(k*80|0)+5984|0,0,j|0)|0;if((k|0)==(h|0)){break}else{k=k+1|0}}if(!g){g=h+1|0;k=0;j=g;while(1){if((h-k|0)>=0){l=0;do{c[e>>2]=k;c[e+4>>2]=l;Na(f|0,12360,e|0)|0;Lc(b,f,a+(k*80|0)+(l<<3)+5984|0)|0;l=l+1|0}while((l|0)!=(j|0))}k=k+1|0;if((k|0)==(g|0)){break}else{j=j+ -1|0}}}}}else{_b(12296)}j=a+6784|0;if((Ec(b,12368,j)|0)!=0){g=c[j>>2]|0;j=(g|0)<0;if(!j){k=(g<<3)+8|0;h=0;while(1){Eg(a+(h*80|0)+6792|0,0,k|0)|0;if((h|0)==(g|0)){break}else{h=h+1|0}}if(!j){j=g+1|0;h=0;k=j;while(1){if((g-h|0)>=0){l=0;do{c[e>>2]=h;c[e+4>>2]=l;Na(f|0,12440,e|0)|0;Lc(b,f,a+(h*80|0)+(l<<3)+6792|0)|0;l=l+1|0}while((l|0)!=(k|0))}h=h+1|0;if((h|0)==(j|0)){break}else{k=k+ -1|0}}}}}else{_b(12376)}k=a+7592|0;if((Ec(b,12448,k)|0)!=0){j=c[k>>2]|0;k=(j|0)<0;if(!k){h=(j<<3)+8|0;g=0;while(1){Eg(a+(g*80|0)+7600|0,0,h|0)|0;if((g|0)==(j|0)){break}else{g=g+1|0}}if(!k){k=j+1|0;g=0;h=k;while(1){if((j-g|0)>=0){l=0;do{c[e>>2]=g;c[e+4>>2]=l;Na(f|0,12528,e|0)|0;Lc(b,f,a+(g*80|0)+(l<<3)+7600|0)|0;l=l+1|0}while((l|0)!=(h|0))}g=g+1|0;if((g|0)==(k|0)){break}else{h=h+ -1|0}}}}}else{_b(12464)}h=a+8400|0;if((Ec(b,12544,h)|0)==0){_b(12560);i=d;return}k=c[h>>2]|0;h=(k|0)<0;if(h){i=d;return}g=(k<<3)+8|0;j=0;while(1){Eg(a+(j*80|0)+8408|0,0,g|0)|0;if((j|0)==(k|0)){break}else{j=j+1|0}}if(h){i=d;return}h=k+1|0;j=0;g=h;while(1){if((k-j|0)>=0){l=0;do{c[e>>2]=j;c[e+4>>2]=l;Na(f|0,12624,e|0)|0;Lc(b,f,a+(j*80|0)+(l<<3)+8408|0)|0;l=l+1|0}while((l|0)!=(g|0))}j=j+1|0;if((j|0)==(h|0)){break}else{g=g+ -1|0}}i=d;return}function Ze(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0,y=0.0,z=0.0;g=i;i=i+80|0;j=g;if((c[a+5968>>2]|0)!=1){h[e>>3]=b;k=d;h[f>>3]=k;i=g;return}l=c[a+7592>>2]|0;m=c[a+8400>>2]|0;n=b- +h[a+16>>3];o=d- +h[a+24>>3];if((l|0)>=0){p=0;while(1){q=l-p|0;r=+h[a+(q*80|0)+(p<<3)+7600>>3];s=j+(p<<3)|0;h[s>>3]=r;if((p|0)>0){t=p;u=r;do{t=t+ -1|0;u=o*u+ +h[a+(q*80|0)+(t<<3)+7600>>3]}while((t|0)>0);h[s>>3]=u}if((p|0)==(l|0)){break}else{p=p+1|0}}r=+h[j>>3];if((l|0)>0){p=l+1|0;t=l;v=r;while(1){w=n*v+ +h[j+(p-t<<3)>>3];l=t+ -1|0;if((l|0)>0){t=l;v=w}else{x=j;y=w;break}}}else{x=j;y=r}}else{x=j;y=0.0}h[e>>3]=y;if((m|0)>=0){t=0;while(1){p=m-t|0;y=+h[a+(p*80|0)+(t<<3)+8408>>3];l=j+(t<<3)|0;h[l>>3]=y;if((t|0)>0){q=t;r=y;do{q=q+ -1|0;r=o*r+ +h[a+(p*80|0)+(q<<3)+8408>>3]}while((q|0)>0);h[l>>3]=r}if((t|0)==(m|0)){break}else{t=t+1|0}}o=+h[x>>3];if((m|0)>0){t=m+1|0;a=m;u=o;while(1){y=n*u+ +h[j+(t-a<<3)>>3];m=a+ -1|0;if((m|0)>0){a=m;u=y}else{z=y;break}}}else{z=o}}else{z=+h[x>>3]}h[f>>3]=z;h[e>>3]=+h[e>>3]+b;k=+h[f>>3]+d;h[f>>3]=k;i=g;return}function _e(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0,y=0.0,z=0.0;g=i;i=i+80|0;j=g;if((c[a+5968>>2]|0)!=1){h[e>>3]=b;k=d;h[f>>3]=k;i=g;return}l=c[a+5976>>2]|0;m=c[a+6784>>2]|0;n=b- +h[a+16>>3];o=d- +h[a+24>>3];if((l|0)>=0){p=0;while(1){q=l-p|0;r=+h[a+(q*80|0)+(p<<3)+5984>>3];s=j+(p<<3)|0;h[s>>3]=r;if((p|0)>0){t=p;u=r;do{t=t+ -1|0;u=o*u+ +h[a+(q*80|0)+(t<<3)+5984>>3]}while((t|0)>0);h[s>>3]=u}if((p|0)==(l|0)){break}else{p=p+1|0}}r=+h[j>>3];if((l|0)>0){p=l+1|0;t=l;v=r;while(1){w=n*v+ +h[j+(p-t<<3)>>3];l=t+ -1|0;if((l|0)>0){t=l;v=w}else{x=j;y=w;break}}}else{x=j;y=r}}else{x=j;y=0.0}h[e>>3]=y;if((m|0)>=0){t=0;while(1){p=m-t|0;y=+h[a+(p*80|0)+(t<<3)+6792>>3];l=j+(t<<3)|0;h[l>>3]=y;if((t|0)>0){q=t;r=y;do{q=q+ -1|0;r=o*r+ +h[a+(p*80|0)+(q<<3)+6792>>3]}while((q|0)>0);h[l>>3]=r}if((t|0)==(m|0)){break}else{t=t+1|0}}o=+h[x>>3];if((m|0)>0){t=m+1|0;a=m;u=o;while(1){y=n*u+ +h[j+(t-a<<3)>>3];m=a+ -1|0;if((m|0)>0){a=m;u=y}else{z=y;break}}}else{z=o}}else{z=+h[x>>3]}h[f>>3]=z;h[e>>3]=+h[e>>3]+b;k=+h[f>>3]+d;h[f>>3]=k;i=g;return}function $e(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;if((Dg(b|0)|0)<9){c[a+5968>>2]=0;i=d;return}e=a+5968|0;if((Ag(b+8|0,12640,4)|0)==0){c[e>>2]=1;i=d;return}else{c[e>>2]=0;i=d;return}}function af(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0.0,k=0.0,l=0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;e=i;i=i+16|0;f=e;c[3162]=0;g=(d|0)==0;h=b;while(1){if((a[h]|0)==32){h=h+1|0}else{break}}b=g?f:d;j=+wg(h,b);d=c[b>>2]|0;if(($f(h,46)|0)!=0){c[3162]=46}f=a[d]|0;g=f<<24>>24;switch(f<<24>>24){case 32:case 58:case 100:case 104:case 109:{break};default:{k=j;i=e;return+k}}l=d;if((l-h|0)>=5){k=j;i=e;return+k}m=d+1|0;n=a[m]|0;if(!(((n<<24>>24)+ -48|0)>>>0<10)){if(!(n<<24>>24==32)){k=j;i=e;return+k}if(!(((a[d+2|0]|0)+ -48|0)>>>0<10)){k=j;i=e;return+k}}c[3162]=g;c[b>>2]=m;if((a[h]|0)==45){o=-j;p=-1.0}else{o=j;p=1.0}j=+wg(m,b);do{if(!(f<<24>>24==109)){m=c[b>>2]|0;h=a[m]|0;if(h<<24>>24==32|h<<24>>24==58|h<<24>>24==109?(m-l|0)<4:0){h=m+1|0;g=a[h]|0;if(!(((g<<24>>24)+ -48|0)>>>0<10)){if(!(g<<24>>24==32)){q=o;r=j;s=0.0;break}if(!(((a[m+2|0]|0)+ -48|0)>>>0<10)){q=o;r=j;s=0.0;break}}c[b>>2]=h;q=o;r=j;s=+wg(h,b)}else{q=o;r=j;s=0.0}}else{q=0.0;r=o;s=j}}while(0);k=p*(q+r/60.0+s/3600.0);i=e;return+k}function bf(a,b,d,e,f,j,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;j=j|0;l=+l;m=m|0;n=n|0;var o=0,p=0,q=0,r=0,s=0.0,t=0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0;o=i;i=i+48|0;p=o;q=o+36|0;r=o+32|0;s=l;c[r>>2]=0;if((c[58]|0)!=0){c[p>>2]=b;c[p+4>>2]=d;c[p+8>>2]=e;t=p+12|0;h[k>>3]=s;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];c[p+20>>2]=m;c[p+24>>2]=n;Ma(12656,p|0)|0}t=cf(a,e,r,b,d,m,n)|0;n=c[r>>2]|0;Zf(n,t,4,4);l=+g[n>>2];u=+g[n+(t+ -1<<2)>>2];r=t+1|0;if((r|0)<2){v=1}else{v=(r|0)/2|0}r=v+ -1|0;m=n+(r<<2)|0;w=+g[m>>2];if(((t|0)%2|0|0)!=1&(v|0)<(t|0)){x=(w+ +g[n+(v<<2)>>2])*.5}else{x=w}w=+(t|0);d=~~(w*.5);b=(d|0)<5?5:d;d=~~(w*.01+.5);e=(d|0)<1?1:d;d=df(n,t,o+40|0,q,2.5,e,5)|0;if((d|0)<(b|0)){g[f>>2]=l;y=u}else{w=+g[q>>2];if(s>0.0){z=w/s;g[q>>2]=z;A=z}else{A=w}w=x- +(r|0)*A;g[f>>2]=l>w?l:w;w=x+ +(t-v|0)*A;y=u>2]=y;if((c[58]|0)==0){hg(n);i=o;return}y=+g[m>>2];h[k>>3]=l;c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];m=p+8|0;h[k>>3]=u;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];m=p+16|0;h[k>>3]=y;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];m=p+24|0;h[k>>3]=x;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];Ma(12704,p|0)|0;c[p>>2]=b;c[p+4>>2]=e;c[p+8>>2]=d;Ma(12752,p|0)|0;x=+g[f>>2];y=+g[j>>2];h[k>>3]=+g[q>>2];c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];c[p+8>>2]=v;v=p+12|0;h[k>>3]=x;c[v>>2]=c[k>>2];c[v+4>>2]=c[k+4>>2];v=p+20|0;h[k>>3]=y;c[v>>2]=c[k>>2];c[v+4>>2]=c[k+4>>2];Ma(12800,p|0)|0;hg(n);i=o;return}function cf(d,e,f,j,k,l,m){d=d|0;e=e|0;f=f|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;n=i;i=i+16|0;o=n;p=(j|0)<(m|0)?j:m;q=(p|0)<1?1:p;p=j+ -1|0;r=(p+q|0)/(q|0)|0;s=(r|0)<2?2:r;r=(p+s|0)/(s|0)|0;p=(r|0)<1?1:r;if((c[58]|0)==0){t=1}else{c[o>>2]=q;c[o+4>>2]=s;c[o+8>>2]=p;Ma(12856,o|0)|0;t=(c[58]|0)==0}q=(l|0)/(m|0)|0;m=(q|0)<1?1:q;q=(l+ -1+p|0)/(p|0)|0;l=(q|0)>(k|0)?k:q;q=(m|0)>(l|0)?m:l;l=(k|0)/(q|0)|0;r=(l|0)<2?2:l;u=(k+ -1+r|0)/(r|0)|0;if(!t){c[o>>2]=m;c[o+4>>2]=q;c[o+8>>2]=r;c[o+12>>2]=u;Ma(12912,o|0)|0}o=aa(u,p)|0;u=gg(o<<2)|0;c[f>>2]=u;f=j<<2;q=gg(f)|0;m=(r+1|0)/2|0;if((m|0)>=(k|0)){v=0;hg(q);i=n;return v|0}t=(p|0)>0;w=(j|0)>0;x=j<<1;y=j<<3;if((e|0)==8){z=m;A=0;B=u;while(1){C=aa(z+ -1|0,j)|0;if(w){D=0;do{g[q+(D<<2)>>2]=+(a[d+(D+C)|0]|0);D=D+1|0}while((D|0)!=(j|0))}a:do{if(t){D=0;C=0;while(1){g[B+(D<<2)>>2]=+g[q+(C<<2)>>2];E=D+1|0;if((E|0)==(p|0)){break a}D=E;C=C+s|0}}}while(0);C=A+p|0;if((C|0)>(o|0)){v=C;F=29;break}D=z+r|0;if((D|0)<(k|0)){z=D;A=C;B=B+(p<<2)|0}else{v=C;F=29;break}}if((F|0)==29){hg(q);i=n;return v|0}}B=(aa(m+ -1|0,j)|0)<<2;A=(aa((l|0)>2?l:2,j)|0)<<2;l=j<<2;z=0;C=m;m=0;D=u;while(1){u=d+(B+(aa(A,z)|0))|0;if((e|0)==32){E=d+(aa(f,C+ -1|0)|0)|0;if(w){G=0;do{g[q+(G<<2)>>2]=+(c[E+(G<<2)>>2]|0);G=G+1|0}while((G|0)!=(j|0))}}else if((e|0)==-32){if(w){Kg(q|0,u|0,l|0)|0}}else if((e|0)==-64){G=d+(aa(y,C+ -1|0)|0)|0;if(w){E=0;do{g[q+(E<<2)>>2]=+h[G+(E<<3)>>3];E=E+1|0}while((E|0)!=(j|0))}}else if((e|0)==16?(E=d+(aa(x,C+ -1|0)|0)|0,w):0){G=0;do{g[q+(G<<2)>>2]=+(b[E+(G<<1)>>1]|0);G=G+1|0}while((G|0)!=(j|0))}b:do{if(t){G=0;E=0;while(1){g[D+(G<<2)>>2]=+g[q+(E<<2)>>2];u=G+1|0;if((u|0)==(p|0)){break b}G=u;E=E+s|0}}}while(0);E=m+p|0;if((E|0)>(o|0)){v=E;F=29;break}G=C+r|0;if((G|0)<(k|0)){z=z+1|0;C=G;m=E;D=D+(p<<2)|0}else{v=E;F=29;break}}if((F|0)==29){hg(q);i=n;return v|0}return 0}function df(b,c,d,e,f,h,j){b=b|0;c=c|0;d=d|0;e=e|0;f=+f;h=h|0;j=j|0;var k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0.0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0.0,D=0,E=0,F=0,G=0,H=0.0,I=0.0,J=0.0,K=0,L=0.0,M=0.0,N=0.0,O=0.0,P=0.0,R=0.0,S=0.0,T=0.0,U=0,V=0,W=0.0,X=0,Y=0,Z=0.0,_=0.0,$=0.0,ba=0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0,oa=0.0,pa=0.0,qa=0.0,ra=0,sa=0.0,ta=0.0;k=i;l=f;if((c|0)<1){m=0;i=k;return m|0}if((c|0)==1){g[d>>2]=+g[b+4>>2];g[e>>2]=0.0;m=1;i=k;return m|0}f=2.0/+(c+ -1|0);n=c<<2;o=gg(n)|0;p=gg(n)|0;n=ig(c,1)|0;q=0;while(1){g[p+(q<<2)>>2]=f*+(q|0)+-1.0;r=q+1|0;if((r|0)==(c|0)){s=0.0;t=0.0;u=0.0;v=0;break}else{q=r}}do{w=+g[p+(v<<2)>>2];x=+g[b+(v<<2)>>2];s=s+w*w;t=t+w*x;u=u+x;v=v+1|0}while((v|0)!=(c|0));x=+(c|0);w=u/x;y=t/s;v=~~(x*.5);q=(v|0)<5?5:v;if((j|0)>0){x=l;v=~h;r=~c;l=0.0;z=u;u=t;t=s;s=y;A=c;B=0;C=w;while(1){D=0;while(1){g[o+(D<<2)>>2]=+g[b+(D<<2)>>2]-(C+s*+g[p+(D<<2)>>2]);E=D+1|0;if((E|0)==(c|0)){F=0;G=0;H=0.0;I=0.0;break}else{D=E}}while(1){if((a[n+F|0]|0)==0){J=+g[o+(F<<2)>>2];K=G+1|0;L=H+J;M=I+J*J}else{K=G;L=H;M=I}F=F+1|0;if((F|0)==(c|0)){break}else{G=K;H=L;I=M}}if(!(K>>>0<2)){D=K+ -1|0;J=M/+(D|0)-L*L/+(aa(D,K)|0);if(J<0.0){N=0.0}else{N=+Q(+J)}}else{N=-999.0}J=x*N;O=-J;P=t;R=u;S=z;T=l;D=0;E=v;U=c;while(1){V=~((E|0)>(r|0)?E:r);if((a[n+D|0]|0)!=1){W=+g[o+(D<<2)>>2];if(WJ?(X=D-h|0,Y=(X|0)<0?0:X,X=D+h|0,(Y|0)<(((X|0)>(c|0)?c:X)|0)):0){W=P;Z=R;_=T;$=S;X=Y;Y=U;while(1){ba=n+X|0;do{if((a[ba]|0)!=1){if((X|0)>(D|0)){a[ba]=2;ca=W;da=Z;ea=$;fa=_;ga=Y;break}else{ha=+g[p+(X<<2)>>2];ia=+g[b+(X<<2)>>2];a[ba]=1;ca=W-ha*ha;da=Z-ha*ia;ea=$-ia;fa=_-ha;ga=Y+ -1|0;break}}else{ca=W;da=Z;ea=$;fa=_;ga=Y}}while(0);ba=X+1|0;if((ba|0)==(V|0)){ja=fa;ka=ca;la=da;ma=ea;na=ga;break}else{W=ca;Z=da;_=fa;$=ea;X=ba;Y=ga}}}else{ja=T;ka=P;la=R;ma=S;na=U}}else{ja=T;ka=P;la=R;ma=S;na=U+ -1|0}D=D+1|0;if((D|0)==(c|0)){break}else{P=ka;R=la;S=ma;T=ja;E=E+ -1|0;U=na}}if((na|0)>0){T=ja/ka;S=(ma-la*T)/(+(na|0)-ja*T);oa=(la-ja*S)/ka;pa=S}else{oa=s;pa=C}U=B+1|0;if((na|0)>=(q|0)&(na|0)<(A|0)&(U|0)<(j|0)){l=ja;z=ma;u=la;t=ka;s=oa;A=na;B=U;C=pa}else{qa=oa;ra=na;sa=pa;break}}}else{qa=y;ra=c;sa=w}g[d>>2]=sa-qa;sa=f*qa;g[e>>2]=sa;if(!(sa>=0.0)){ta=-sa}else{ta=sa}if(ta<.001){g[e>>2]=f*y}hg(o);hg(p);hg(n);m=ra;i=k;return m|0}function ef(a,b){a=a|0;b=b|0;return(+g[a>>2]<=+g[b>>2]?-1:1)|0}function ff(a,b,c){a=a|0;b=b|0;c=c|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0;e=i;f=a>>>16;g=a&65535;if((c|0)==1){a=(d[b]|0)+g|0;h=a>>>0>65520?a+ -65521|0:a;a=h+f|0;j=(a>>>0>65520?a+15|0:a)<<16|h;i=e;return j|0}if((b|0)==0){j=1;i=e;return j|0}if(c>>>0<16){if((c|0)==0){k=g;l=f}else{h=b;a=c;m=g;n=f;while(1){o=a+ -1|0;p=(d[h]|0)+m|0;q=p+n|0;if((o|0)==0){k=p;l=q;break}else{h=h+1|0;a=o;m=p;n=q}}}j=((l>>>0)%65521|0)<<16|(k>>>0>65520?k+ -65521|0:k);i=e;return j|0}if(c>>>0>5551){k=b;l=c;n=g;m=f;do{l=l+ -5552|0;a=k;h=n;q=347;p=m;while(1){o=(d[a]|0)+h|0;r=o+(d[a+1|0]|0)|0;s=r+(d[a+2|0]|0)|0;t=s+(d[a+3|0]|0)|0;u=t+(d[a+4|0]|0)|0;v=u+(d[a+5|0]|0)|0;w=v+(d[a+6|0]|0)|0;x=w+(d[a+7|0]|0)|0;y=x+(d[a+8|0]|0)|0;z=y+(d[a+9|0]|0)|0;A=z+(d[a+10|0]|0)|0;B=A+(d[a+11|0]|0)|0;C=B+(d[a+12|0]|0)|0;D=C+(d[a+13|0]|0)|0;E=D+(d[a+14|0]|0)|0;h=E+(d[a+15|0]|0)|0;p=o+p+r+s+t+u+v+w+x+y+z+A+B+C+D+E+h|0;q=q+ -1|0;if((q|0)==0){break}else{a=a+16|0}}k=k+5552|0;n=(h>>>0)%65521|0;m=(p>>>0)%65521|0}while(l>>>0>5551);if((l|0)!=0){if(l>>>0>15){F=l;G=k;H=n;I=m;J=15}else{K=l;L=k;M=n;N=m;J=16}}else{O=n;P=m}}else{F=c;G=b;H=g;I=f;J=15}if((J|0)==15){while(1){J=0;F=F+ -16|0;f=(d[G]|0)+H|0;g=f+(d[G+1|0]|0)|0;b=g+(d[G+2|0]|0)|0;c=b+(d[G+3|0]|0)|0;m=c+(d[G+4|0]|0)|0;n=m+(d[G+5|0]|0)|0;k=n+(d[G+6|0]|0)|0;l=k+(d[G+7|0]|0)|0;a=l+(d[G+8|0]|0)|0;q=a+(d[G+9|0]|0)|0;E=q+(d[G+10|0]|0)|0;D=E+(d[G+11|0]|0)|0;C=D+(d[G+12|0]|0)|0;B=C+(d[G+13|0]|0)|0;A=B+(d[G+14|0]|0)|0;H=A+(d[G+15|0]|0)|0;I=f+I+g+b+c+m+n+k+l+a+q+E+D+C+B+A+H|0;G=G+16|0;if(!(F>>>0>15)){break}else{J=15}}if((F|0)==0){Q=H;R=I;J=17}else{K=F;L=G;M=H;N=I;J=16}}if((J|0)==16){while(1){J=0;I=K+ -1|0;H=(d[L]|0)+M|0;G=H+N|0;if((I|0)==0){Q=H;R=G;J=17;break}else{K=I;L=L+1|0;M=H;N=G;J=16}}}if((J|0)==17){O=(Q>>>0)%65521|0;P=(R>>>0)%65521|0}j=P<<16|O;i=e;return j|0}function gf(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;f=i;if((b|0)==0){g=0;i=f;return g|0}h=~a;a:do{if((e|0)!=0){a=b;j=e;k=h;while(1){if((a&3|0)==0){break}l=c[12968+(((d[a]|0)^k&255)<<2)>>2]^k>>>8;m=j+ -1|0;if((m|0)==0){n=l;break a}else{a=a+1|0;j=m;k=l}}if(j>>>0>31){l=j;m=a;o=k;while(1){p=c[m>>2]^o;q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+4>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+8>>2];q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+12>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+16>>2];q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+20>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+24>>2];q=m+32|0;r=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+28>>2];p=c[15016+((r>>>8&255)<<2)>>2]^c[16040+((r&255)<<2)>>2]^c[13992+((r>>>16&255)<<2)>>2]^c[12968+(r>>>24<<2)>>2];r=l+ -32|0;if(r>>>0>31){l=r;m=q;o=p}else{s=r;t=q;u=p;break}}}else{s=j;t=a;u=k}if(s>>>0>3){o=s;m=t;l=u;while(1){p=m+4|0;q=c[m>>2]^l;r=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2];q=o+ -4|0;if(q>>>0>3){o=q;m=p;l=r}else{v=q;w=p;x=r;break}}}else{v=s;w=t;x=u}if((v|0)==0){n=x}else{l=w;m=v;o=x;while(1){k=c[12968+(((d[l]|0)^o&255)<<2)>>2]^o>>>8;a=m+ -1|0;if((a|0)==0){n=k;break}else{l=l+1|0;m=a;o=k}}}}else{n=h}}while(0);g=~n;i=f;return g|0}function hf(b,d,e,f,g,h,j,k){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0;l=i;if((j|0)==0){m=-6;i=l;return m|0}if(!((a[j]|0)==49&(k|0)==56)){m=-6;i=l;return m|0}if((b|0)==0){m=-2;i=l;return m|0}k=b+24|0;c[k>>2]=0;j=b+32|0;n=c[j>>2]|0;if((n|0)==0){c[j>>2]=1;c[b+40>>2]=0;o=1}else{o=n}n=b+36|0;if((c[n>>2]|0)==0){c[n>>2]=1}n=(d|0)==-1?6:d;if((f|0)<0){p=0-f|0;q=0}else{d=(f|0)>15;p=d?f+ -16|0:f;q=d?2:1}if(!((g+ -1|0)>>>0<9&(e|0)==8)){m=-2;i=l;return m|0}if((p+ -8|0)>>>0>7|n>>>0>9|h>>>0>4){m=-2;i=l;return m|0}e=(p|0)==8?9:p;p=b+40|0;d=kb[o&1](c[p>>2]|0,1,5828)|0;if((d|0)==0){m=-4;i=l;return m|0}c[b+28>>2]=d;c[d>>2]=b;c[d+24>>2]=q;c[d+28>>2]=0;c[d+48>>2]=e;q=1<>2]=q;c[d+52>>2]=q+ -1;o=g+7|0;c[d+80>>2]=o;f=1<>2]=f;c[d+84>>2]=f+ -1;c[d+88>>2]=((g+9|0)>>>0)/3|0;f=d+56|0;c[f>>2]=kb[c[j>>2]&1](c[p>>2]|0,q,2)|0;q=kb[c[j>>2]&1](c[p>>2]|0,c[e>>2]|0,2)|0;r=d+64|0;c[r>>2]=q;Eg(q|0,0,c[e>>2]<<1|0)|0;e=d+68|0;c[e>>2]=kb[c[j>>2]&1](c[p>>2]|0,c[o>>2]|0,2)|0;c[d+5824>>2]=0;o=1<>2]=o;q=kb[c[j>>2]&1](c[p>>2]|0,o,4)|0;c[d+8>>2]=q;o=c[g>>2]|0;c[d+12>>2]=o<<2;if(((c[f>>2]|0)!=0?(c[r>>2]|0)!=0:0)?!((c[e>>2]|0)==0|(q|0)==0):0){c[d+5796>>2]=q+(o>>>1<<1);c[d+5784>>2]=q+(o*3|0);c[d+132>>2]=n;c[d+136>>2]=h;a[d+36|0]=8;m=kf(b)|0;i=l;return m|0}c[d+4>>2]=666;c[k>>2]=c[27632>>2];jf(b)|0;m=-4;i=l;return m|0}function jf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;i=b;return d|0}g=c[f+4>>2]|0;switch(g|0){case 42:case 69:case 73:case 91:case 103:case 113:case 666:{break};default:{d=-2;i=b;return d|0}}h=c[f+8>>2]|0;if((h|0)==0){j=f}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);j=c[e>>2]|0}h=c[j+68>>2]|0;if((h|0)==0){k=j}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);k=c[e>>2]|0}h=c[k+64>>2]|0;if((h|0)==0){l=k}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);l=c[e>>2]|0}h=c[l+56>>2]|0;k=a+36|0;if((h|0)==0){m=a+40|0;n=l}else{l=a+40|0;mb[c[k>>2]&1](c[l>>2]|0,h);m=l;n=c[e>>2]|0}mb[c[k>>2]&1](c[m>>2]|0,n);c[e>>2]=0;d=(g|0)==113?-3:0;i=b;return d|0}function kf(a){a=a|0;var d=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;d=i;if((a|0)==0){f=-2;i=d;return f|0}g=c[a+28>>2]|0;if((g|0)==0){f=-2;i=d;return f|0}if((c[a+32>>2]|0)==0){f=-2;i=d;return f|0}if((c[a+36>>2]|0)==0){f=-2;i=d;return f|0}c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+44>>2]=2;c[g+20>>2]=0;c[g+16>>2]=c[g+8>>2];h=g+24|0;j=c[h>>2]|0;if((j|0)<0){k=0-j|0;c[h>>2]=k;l=k}else{l=j}c[g+4>>2]=(l|0)!=0?42:113;if((l|0)==2){m=gf(0,0,0)|0}else{m=ff(0,0,0)|0}c[a+48>>2]=m;c[g+40>>2]=0;Of(g);c[g+60>>2]=c[g+44>>2]<<1;m=c[g+76>>2]|0;a=c[g+68>>2]|0;b[a+(m+ -1<<1)>>1]=0;Eg(a|0,0,(m<<1)+ -2|0)|0;m=c[g+132>>2]|0;c[g+128>>2]=e[21162+(m*12|0)>>1]|0;c[g+140>>2]=e[21160+(m*12|0)>>1]|0;c[g+144>>2]=e[21164+(m*12|0)>>1]|0;c[g+124>>2]=e[21166+(m*12|0)>>1]|0;c[g+108>>2]=0;c[g+92>>2]=0;c[g+116>>2]=0;c[g+120>>2]=2;c[g+96>>2]=2;c[g+112>>2]=0;c[g+104>>2]=0;c[g+72>>2]=0;f=0;i=d;return f|0} + + + +function lf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0;g=i;if((e|0)==0){h=-2;i=g;return h|0}j=e+28|0;k=c[j>>2]|0;if((k|0)==0|f>>>0>5){h=-2;i=g;return h|0}l=e+12|0;do{if((c[l>>2]|0)!=0){if((c[e>>2]|0)==0?(c[e+4>>2]|0)!=0:0){break}m=k+4|0;n=c[m>>2]|0;o=(f|0)==4;if((n|0)!=666|o){p=e+16|0;if((c[p>>2]|0)==0){c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}c[k>>2]=e;q=k+40|0;r=c[q>>2]|0;c[q>>2]=f;do{if((n|0)==42){if((c[k+24>>2]|0)!=2){s=(c[k+48>>2]<<12)+ -30720|0;if((c[k+136>>2]|0)<=1?(t=c[k+132>>2]|0,(t|0)>=2):0){if((t|0)<6){u=64}else{u=(t|0)==6?128:192}}else{u=0}t=u|s;s=k+108|0;v=(c[s>>2]|0)==0?t:t|32;c[m>>2]=113;t=k+20|0;w=c[t>>2]|0;c[t>>2]=w+1;x=k+8|0;a[(c[x>>2]|0)+w|0]=v>>>8;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=(v|((v>>>0)%31|0))^31;v=e+48|0;if((c[s>>2]|0)!=0){s=c[v>>2]|0;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>24;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>16;s=c[v>>2]|0;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>8;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s}c[v>>2]=ff(0,0,0)|0;y=c[m>>2]|0;z=32;break}v=e+48|0;c[v>>2]=gf(0,0,0)|0;s=k+20|0;w=c[s>>2]|0;c[s>>2]=w+1;x=k+8|0;a[(c[x>>2]|0)+w|0]=31;w=c[s>>2]|0;c[s>>2]=w+1;a[(c[x>>2]|0)+w|0]=-117;w=c[s>>2]|0;c[s>>2]=w+1;a[(c[x>>2]|0)+w|0]=8;w=k+28|0;t=c[w>>2]|0;if((t|0)==0){A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[k+132>>2]|0;if((A|0)!=9){if((c[k+136>>2]|0)>1){B=4}else{B=(A|0)<2?4:0}}else{B=2}A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=B;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=3;c[m>>2]=113;break}A=(((c[t+44>>2]|0)!=0?2:0)|(c[t>>2]|0)!=0|((c[t+16>>2]|0)==0?0:4)|((c[t+28>>2]|0)==0?0:8)|((c[t+36>>2]|0)==0?0:16))&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[(c[w>>2]|0)+4>>2]&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>8&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>16&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>24&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[k+132>>2]|0;if((A|0)!=9){if((c[k+136>>2]|0)>1){C=4}else{C=(A|0)<2?4:0}}else{C=2}A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=C;A=c[(c[w>>2]|0)+12>>2]&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[w>>2]|0;if((c[A+16>>2]|0)==0){D=A}else{t=c[A+20>>2]&255;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=t;t=(c[(c[w>>2]|0)+20>>2]|0)>>>8&255;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=t;D=c[w>>2]|0}if((c[D+44>>2]|0)!=0){c[v>>2]=gf(c[v>>2]|0,c[x>>2]|0,c[s>>2]|0)|0}c[k+32>>2]=0;c[m>>2]=69;E=w;z=34}else{y=n;z=32}}while(0);if((z|0)==32){if((y|0)==69){E=k+28|0;z=34}else{F=y;z=55}}do{if((z|0)==34){n=c[E>>2]|0;if((c[n+16>>2]|0)==0){c[m>>2]=73;G=n;z=57;break}w=k+20|0;s=c[w>>2]|0;x=k+32|0;v=c[x>>2]|0;a:do{if(v>>>0<(c[n+20>>2]&65535)>>>0){t=k+12|0;A=e+48|0;H=k+8|0;I=e+20|0;J=v;K=s;L=n;M=s;while(1){if((K|0)==(c[t>>2]|0)){if((c[L+44>>2]|0)!=0&K>>>0>M>>>0){c[A>>2]=gf(c[A>>2]|0,(c[H>>2]|0)+M|0,K-M|0)|0}N=c[j>>2]|0;O=c[N+20>>2]|0;P=c[p>>2]|0;Q=O>>>0>P>>>0?P:O;if((Q|0)!=0?(Kg(c[l>>2]|0,c[N+16>>2]|0,Q|0)|0,c[l>>2]=(c[l>>2]|0)+Q,N=(c[j>>2]|0)+16|0,c[N>>2]=(c[N>>2]|0)+Q,c[I>>2]=(c[I>>2]|0)+Q,c[p>>2]=(c[p>>2]|0)-Q,N=c[j>>2]|0,O=N+20|0,P=c[O>>2]|0,c[O>>2]=P-Q,(P|0)==(Q|0)):0){c[N+16>>2]=c[N+8>>2]}R=c[w>>2]|0;if((R|0)==(c[t>>2]|0)){break}S=c[E>>2]|0;T=c[x>>2]|0;U=R;V=R}else{S=L;T=J;U=K;V=M}N=a[(c[S+16>>2]|0)+T|0]|0;c[w>>2]=U+1;a[(c[H>>2]|0)+U|0]=N;N=(c[x>>2]|0)+1|0;c[x>>2]=N;Q=c[E>>2]|0;if(!(N>>>0<(c[Q+20>>2]&65535)>>>0)){W=Q;X=V;break a}J=N;K=c[w>>2]|0;L=Q;M=V}W=c[E>>2]|0;X=R}else{W=n;X=s}}while(0);if((c[W+44>>2]|0)!=0?(s=c[w>>2]|0,s>>>0>X>>>0):0){n=e+48|0;c[n>>2]=gf(c[n>>2]|0,(c[k+8>>2]|0)+X|0,s-X|0)|0;Y=c[E>>2]|0}else{Y=W}if((c[x>>2]|0)==(c[Y+20>>2]|0)){c[x>>2]=0;c[m>>2]=73;G=Y;z=57;break}else{F=c[m>>2]|0;z=55;break}}}while(0);if((z|0)==55){if((F|0)==73){G=c[k+28>>2]|0;z=57}else{Z=F;z=76}}do{if((z|0)==57){s=k+28|0;if((c[G+28>>2]|0)==0){c[m>>2]=91;_=s;z=78;break}n=k+20|0;v=c[n>>2]|0;M=k+12|0;L=e+48|0;K=k+8|0;J=e+20|0;H=k+32|0;t=v;I=v;while(1){if((t|0)==(c[M>>2]|0)){if((c[(c[s>>2]|0)+44>>2]|0)!=0&t>>>0>I>>>0){c[L>>2]=gf(c[L>>2]|0,(c[K>>2]|0)+I|0,t-I|0)|0}v=c[j>>2]|0;A=c[v+20>>2]|0;Q=c[p>>2]|0;N=A>>>0>Q>>>0?Q:A;if((N|0)!=0?(Kg(c[l>>2]|0,c[v+16>>2]|0,N|0)|0,c[l>>2]=(c[l>>2]|0)+N,v=(c[j>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+N,c[J>>2]=(c[J>>2]|0)+N,c[p>>2]=(c[p>>2]|0)-N,v=c[j>>2]|0,A=v+20|0,Q=c[A>>2]|0,c[A>>2]=Q-N,(Q|0)==(N|0)):0){c[v+16>>2]=c[v+8>>2]}v=c[n>>2]|0;if((v|0)==(c[M>>2]|0)){$=v;aa=1;break}else{ba=v;ca=v}}else{ba=t;ca=I}v=c[H>>2]|0;c[H>>2]=v+1;da=a[(c[(c[s>>2]|0)+28>>2]|0)+v|0]|0;c[n>>2]=ba+1;a[(c[K>>2]|0)+ba|0]=da;if(da<<24>>24==0){z=68;break}t=c[n>>2]|0;I=ca}if((z|0)==68){$=ca;aa=da&255}if((c[(c[s>>2]|0)+44>>2]|0)!=0?(I=c[n>>2]|0,I>>>0>$>>>0):0){c[L>>2]=gf(c[L>>2]|0,(c[K>>2]|0)+$|0,I-$|0)|0}if((aa|0)==0){c[H>>2]=0;c[m>>2]=91;_=s;z=78;break}else{Z=c[m>>2]|0;z=76;break}}}while(0);if((z|0)==76){if((Z|0)==91){_=k+28|0;z=78}else{ea=Z;z=97}}do{if((z|0)==78){if((c[(c[_>>2]|0)+36>>2]|0)==0){c[m>>2]=103;fa=_;z=99;break}I=k+20|0;t=c[I>>2]|0;M=k+12|0;J=e+48|0;x=k+8|0;w=e+20|0;v=k+32|0;N=t;Q=t;while(1){if((N|0)==(c[M>>2]|0)){if((c[(c[_>>2]|0)+44>>2]|0)!=0&N>>>0>Q>>>0){c[J>>2]=gf(c[J>>2]|0,(c[x>>2]|0)+Q|0,N-Q|0)|0}t=c[j>>2]|0;A=c[t+20>>2]|0;P=c[p>>2]|0;O=A>>>0>P>>>0?P:A;if((O|0)!=0?(Kg(c[l>>2]|0,c[t+16>>2]|0,O|0)|0,c[l>>2]=(c[l>>2]|0)+O,t=(c[j>>2]|0)+16|0,c[t>>2]=(c[t>>2]|0)+O,c[w>>2]=(c[w>>2]|0)+O,c[p>>2]=(c[p>>2]|0)-O,t=c[j>>2]|0,A=t+20|0,P=c[A>>2]|0,c[A>>2]=P-O,(P|0)==(O|0)):0){c[t+16>>2]=c[t+8>>2]}t=c[I>>2]|0;if((t|0)==(c[M>>2]|0)){ga=t;ha=1;break}else{ia=t;ja=t}}else{ia=N;ja=Q}t=c[v>>2]|0;c[v>>2]=t+1;ka=a[(c[(c[_>>2]|0)+36>>2]|0)+t|0]|0;c[I>>2]=ia+1;a[(c[x>>2]|0)+ia|0]=ka;if(ka<<24>>24==0){z=89;break}N=c[I>>2]|0;Q=ja}if((z|0)==89){ga=ja;ha=ka&255}if((c[(c[_>>2]|0)+44>>2]|0)!=0?(Q=c[I>>2]|0,Q>>>0>ga>>>0):0){c[J>>2]=gf(c[J>>2]|0,(c[x>>2]|0)+ga|0,Q-ga|0)|0}if((ha|0)==0){c[m>>2]=103;fa=_;z=99;break}else{ea=c[m>>2]|0;z=97;break}}}while(0);if((z|0)==97?(ea|0)==103:0){fa=k+28|0;z=99}do{if((z|0)==99){if((c[(c[fa>>2]|0)+44>>2]|0)==0){c[m>>2]=113;break}Q=k+20|0;N=k+12|0;if((((c[Q>>2]|0)+2|0)>>>0>(c[N>>2]|0)>>>0?(v=c[j>>2]|0,M=c[v+20>>2]|0,w=c[p>>2]|0,s=M>>>0>w>>>0?w:M,(s|0)!=0):0)?(Kg(c[l>>2]|0,c[v+16>>2]|0,s|0)|0,c[l>>2]=(c[l>>2]|0)+s,v=(c[j>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+s,v=e+20|0,c[v>>2]=(c[v>>2]|0)+s,c[p>>2]=(c[p>>2]|0)-s,v=c[j>>2]|0,M=v+20|0,w=c[M>>2]|0,c[M>>2]=w-s,(w|0)==(s|0)):0){c[v+16>>2]=c[v+8>>2]}v=c[Q>>2]|0;if(!((v+2|0)>>>0>(c[N>>2]|0)>>>0)){N=e+48|0;s=c[N>>2]&255;c[Q>>2]=v+1;w=k+8|0;a[(c[w>>2]|0)+v|0]=s;s=(c[N>>2]|0)>>>8&255;v=c[Q>>2]|0;c[Q>>2]=v+1;a[(c[w>>2]|0)+v|0]=s;c[N>>2]=gf(0,0,0)|0;c[m>>2]=113}}}while(0);N=k+20|0;if((c[N>>2]|0)==0){if((c[e+4>>2]|0)==0?(r|0)>=(f|0)&(f|0)!=4:0){c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}}else{s=c[j>>2]|0;v=c[s+20>>2]|0;w=c[p>>2]|0;Q=v>>>0>w>>>0?w:v;if((Q|0)==0){la=w}else{Kg(c[l>>2]|0,c[s+16>>2]|0,Q|0)|0;c[l>>2]=(c[l>>2]|0)+Q;s=(c[j>>2]|0)+16|0;c[s>>2]=(c[s>>2]|0)+Q;s=e+20|0;c[s>>2]=(c[s>>2]|0)+Q;c[p>>2]=(c[p>>2]|0)-Q;s=c[j>>2]|0;w=s+20|0;v=c[w>>2]|0;c[w>>2]=v-Q;if((v|0)==(Q|0)){c[s+16>>2]=c[s+8>>2]}la=c[p>>2]|0}if((la|0)==0){c[q>>2]=-1;h=0;i=g;return h|0}}s=(c[m>>2]|0)==666;Q=(c[e+4>>2]|0)==0;if(s){if(Q){z=121}else{c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}}else{if(Q){z=121}else{z=124}}do{if((z|0)==121){if((c[k+116>>2]|0)==0){if((f|0)!=0){if(s){break}else{z=124;break}}else{h=0;i=g;return h|0}}else{z=124}}}while(0);do{if((z|0)==124){s=c[k+136>>2]|0;b:do{if((s|0)==3){r=k+116|0;Q=(f|0)==0;v=k+96|0;w=k+108|0;M=k+5792|0;H=k+5796|0;K=k+5784|0;L=k+(d[24760]<<2)+2440|0;n=k+5788|0;t=k+56|0;O=k+92|0;while(1){P=c[r>>2]|0;if(P>>>0<258){mf(k);A=c[r>>2]|0;if(A>>>0<258&Q){break b}if((A|0)==0){break}c[v>>2]=0;if(A>>>0>2){ma=A;z=151}else{na=c[w>>2]|0;z=166}}else{c[v>>2]=0;ma=P;z=151}if((z|0)==151){z=0;P=c[w>>2]|0;if((P|0)!=0){A=c[t>>2]|0;oa=a[A+(P+ -1)|0]|0;if((oa<<24>>24==(a[A+P|0]|0)?oa<<24>>24==(a[A+(P+1)|0]|0):0)?(pa=A+(P+2)|0,oa<<24>>24==(a[pa]|0)):0){qa=A+(P+258)|0;A=pa;while(1){pa=A+1|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+2|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+3|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+4|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+5|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+6|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+7|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+8|0;if(oa<<24>>24==(a[pa]|0)&pa>>>0>>0){A=pa}else{ra=pa;break}}A=ra-qa+258|0;oa=A>>>0>ma>>>0?ma:A;c[v>>2]=oa;if(oa>>>0>2){A=oa+253|0;oa=c[M>>2]|0;b[(c[H>>2]|0)+(oa<<1)>>1]=1;c[M>>2]=oa+1;a[(c[K>>2]|0)+oa|0]=A;oa=k+((d[25272+(A&255)|0]|256)+1<<2)+148|0;b[oa>>1]=(b[oa>>1]|0)+1<<16>>16;b[L>>1]=(b[L>>1]|0)+1<<16>>16;oa=(c[M>>2]|0)==((c[n>>2]|0)+ -1|0)|0;A=c[v>>2]|0;c[r>>2]=(c[r>>2]|0)-A;pa=(c[w>>2]|0)+A|0;c[w>>2]=pa;c[v>>2]=0;sa=pa;ta=oa}else{na=P;z=166}}else{na=P;z=166}}else{na=0;z=166}}if((z|0)==166){z=0;oa=a[(c[t>>2]|0)+na|0]|0;pa=c[M>>2]|0;b[(c[H>>2]|0)+(pa<<1)>>1]=0;c[M>>2]=pa+1;a[(c[K>>2]|0)+pa|0]=oa;pa=k+((oa&255)<<2)+148|0;b[pa>>1]=(b[pa>>1]|0)+1<<16>>16;pa=(c[M>>2]|0)==((c[n>>2]|0)+ -1|0)|0;c[r>>2]=(c[r>>2]|0)+ -1;oa=(c[w>>2]|0)+1|0;c[w>>2]=oa;sa=oa;ta=pa}if((ta|0)==0){continue}pa=c[O>>2]|0;if((pa|0)>-1){ua=(c[t>>2]|0)+pa|0}else{ua=0}Sf(k,ua,sa-pa|0,0);c[O>>2]=c[w>>2];pa=c[k>>2]|0;oa=pa+28|0;A=c[oa>>2]|0;va=c[A+20>>2]|0;wa=pa+16|0;xa=c[wa>>2]|0;ya=va>>>0>xa>>>0?xa:va;if((ya|0)!=0?(va=pa+12|0,Kg(c[va>>2]|0,c[A+16>>2]|0,ya|0)|0,c[va>>2]=(c[va>>2]|0)+ya,va=(c[oa>>2]|0)+16|0,c[va>>2]=(c[va>>2]|0)+ya,va=pa+20|0,c[va>>2]=(c[va>>2]|0)+ya,c[wa>>2]=(c[wa>>2]|0)-ya,wa=c[oa>>2]|0,oa=wa+20|0,va=c[oa>>2]|0,c[oa>>2]=va-ya,(va|0)==(ya|0)):0){c[wa+16>>2]=c[wa+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){break b}}r=c[O>>2]|0;if((r|0)>-1){za=(c[t>>2]|0)+r|0}else{za=0}Sf(k,za,(c[w>>2]|0)-r|0,o&1);c[O>>2]=c[w>>2];r=c[k>>2]|0;n=r+28|0;M=c[n>>2]|0;K=c[M+20>>2]|0;H=r+16|0;v=c[H>>2]|0;L=K>>>0>v>>>0?v:K;if((L|0)!=0?(K=r+12|0,Kg(c[K>>2]|0,c[M+16>>2]|0,L|0)|0,c[K>>2]=(c[K>>2]|0)+L,K=(c[n>>2]|0)+16|0,c[K>>2]=(c[K>>2]|0)+L,K=r+20|0,c[K>>2]=(c[K>>2]|0)+L,c[H>>2]=(c[H>>2]|0)-L,H=c[n>>2]|0,n=H+20|0,K=c[n>>2]|0,c[n>>2]=K-L,(K|0)==(L|0)):0){c[H+16>>2]=c[H+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){Aa=o?2:0;z=183;break}else{Aa=o?3:1;z=183;break}}else if((s|0)==2){H=k+116|0;L=k+96|0;K=k+108|0;n=k+56|0;r=k+5792|0;M=k+5796|0;v=k+5784|0;Q=k+5788|0;wa=k+92|0;while(1){if((c[H>>2]|0)==0?(mf(k),(c[H>>2]|0)==0):0){break}c[L>>2]=0;ya=a[(c[n>>2]|0)+(c[K>>2]|0)|0]|0;va=c[r>>2]|0;b[(c[M>>2]|0)+(va<<1)>>1]=0;c[r>>2]=va+1;a[(c[v>>2]|0)+va|0]=ya;va=k+((ya&255)<<2)+148|0;b[va>>1]=(b[va>>1]|0)+1<<16>>16;va=(c[r>>2]|0)==((c[Q>>2]|0)+ -1|0);c[H>>2]=(c[H>>2]|0)+ -1;ya=(c[K>>2]|0)+1|0;c[K>>2]=ya;if(!va){continue}va=c[wa>>2]|0;if((va|0)>-1){Ba=(c[n>>2]|0)+va|0}else{Ba=0}Sf(k,Ba,ya-va|0,0);c[wa>>2]=c[K>>2];va=c[k>>2]|0;ya=va+28|0;oa=c[ya>>2]|0;pa=c[oa+20>>2]|0;A=va+16|0;xa=c[A>>2]|0;Ca=pa>>>0>xa>>>0?xa:pa;if((Ca|0)!=0?(pa=va+12|0,Kg(c[pa>>2]|0,c[oa+16>>2]|0,Ca|0)|0,c[pa>>2]=(c[pa>>2]|0)+Ca,pa=(c[ya>>2]|0)+16|0,c[pa>>2]=(c[pa>>2]|0)+Ca,pa=va+20|0,c[pa>>2]=(c[pa>>2]|0)+Ca,c[A>>2]=(c[A>>2]|0)-Ca,A=c[ya>>2]|0,ya=A+20|0,pa=c[ya>>2]|0,c[ya>>2]=pa-Ca,(pa|0)==(Ca|0)):0){c[A+16>>2]=c[A+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){break b}}if((f|0)!=0){H=c[wa>>2]|0;if((H|0)>-1){Da=(c[n>>2]|0)+H|0}else{Da=0}Sf(k,Da,(c[K>>2]|0)-H|0,o&1);c[wa>>2]=c[K>>2];H=c[k>>2]|0;Q=H+28|0;r=c[Q>>2]|0;v=c[r+20>>2]|0;M=H+16|0;L=c[M>>2]|0;w=v>>>0>L>>>0?L:v;if((w|0)!=0?(v=H+12|0,Kg(c[v>>2]|0,c[r+16>>2]|0,w|0)|0,c[v>>2]=(c[v>>2]|0)+w,v=(c[Q>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+w,v=H+20|0,c[v>>2]=(c[v>>2]|0)+w,c[M>>2]=(c[M>>2]|0)-w,M=c[Q>>2]|0,Q=M+20|0,v=c[Q>>2]|0,c[Q>>2]=v-w,(v|0)==(w|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){Aa=o?2:0;z=183;break}else{Aa=o?3:1;z=183;break}}}else{Aa=nb[c[21168+((c[k+132>>2]|0)*12|0)>>2]&7](k,f)|0;z=183}}while(0);if((z|0)==183){if((Aa&-2|0)==2){c[m>>2]=666}if((Aa&-3|0)!=0){if((Aa|0)!=1){break}if((f|0)==1){Rf(k)}else if(((f|0)!=5?(Qf(k,0,0,0),(f|0)==3):0)?(s=c[k+76>>2]|0,x=c[k+68>>2]|0,b[x+(s+ -1<<1)>>1]=0,Eg(x|0,0,(s<<1)+ -2|0)|0,(c[k+116>>2]|0)==0):0){c[k+108>>2]=0;c[k+92>>2]=0}s=c[j>>2]|0;x=c[s+20>>2]|0;J=c[p>>2]|0;I=x>>>0>J>>>0?J:x;if((I|0)==0){Ea=J}else{Kg(c[l>>2]|0,c[s+16>>2]|0,I|0)|0;c[l>>2]=(c[l>>2]|0)+I;s=(c[j>>2]|0)+16|0;c[s>>2]=(c[s>>2]|0)+I;s=e+20|0;c[s>>2]=(c[s>>2]|0)+I;c[p>>2]=(c[p>>2]|0)-I;s=c[j>>2]|0;J=s+20|0;x=c[J>>2]|0;c[J>>2]=x-I;if((x|0)==(I|0)){c[s+16>>2]=c[s+8>>2]}Ea=c[p>>2]|0}if((Ea|0)!=0){break}c[q>>2]=-1;h=0;i=g;return h|0}}if((c[p>>2]|0)!=0){h=0;i=g;return h|0}c[q>>2]=-1;h=0;i=g;return h|0}}while(0);if(!o){h=0;i=g;return h|0}q=k+24|0;m=c[q>>2]|0;if((m|0)<1){h=1;i=g;return h|0}s=e+48|0;I=c[s>>2]|0;if((m|0)==2){m=c[N>>2]|0;c[N>>2]=m+1;x=k+8|0;a[(c[x>>2]|0)+m|0]=I;m=(c[s>>2]|0)>>>8&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=(c[s>>2]|0)>>>16&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=(c[s>>2]|0)>>>24&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=e+8|0;J=c[m>>2]&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>8&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>16&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>24&255;m=c[N>>2]|0;c[N>>2]=m+1;a[(c[x>>2]|0)+m|0]=J}else{J=c[N>>2]|0;c[N>>2]=J+1;m=k+8|0;a[(c[m>>2]|0)+J|0]=I>>>24;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[m>>2]|0)+J|0]=I>>>16;I=c[s>>2]|0;s=c[N>>2]|0;c[N>>2]=s+1;a[(c[m>>2]|0)+s|0]=I>>>8;s=c[N>>2]|0;c[N>>2]=s+1;a[(c[m>>2]|0)+s|0]=I}I=c[j>>2]|0;s=c[I+20>>2]|0;m=c[p>>2]|0;J=s>>>0>m>>>0?m:s;if((J|0)!=0?(Kg(c[l>>2]|0,c[I+16>>2]|0,J|0)|0,c[l>>2]=(c[l>>2]|0)+J,I=(c[j>>2]|0)+16|0,c[I>>2]=(c[I>>2]|0)+J,I=e+20|0,c[I>>2]=(c[I>>2]|0)+J,c[p>>2]=(c[p>>2]|0)-J,I=c[j>>2]|0,s=I+20|0,m=c[s>>2]|0,c[s>>2]=m-J,(m|0)==(J|0)):0){c[I+16>>2]=c[I+8>>2]}I=c[q>>2]|0;if((I|0)>0){c[q>>2]=0-I}h=(c[N>>2]|0)==0|0;i=g;return h|0}}}while(0);c[e+24>>2]=c[27624>>2];h=-2;i=g;return h|0}function mf(a){a=a|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;f=i;g=a+44|0;h=c[g>>2]|0;j=a+60|0;k=a+116|0;l=a+108|0;m=h+ -262|0;n=a+56|0;o=a+72|0;p=a+88|0;q=a+84|0;r=a+112|0;s=a+92|0;t=a+76|0;u=a+68|0;v=a+64|0;w=c[k>>2]|0;x=h;while(1){y=c[l>>2]|0;z=(c[j>>2]|0)-w-y|0;if(y>>>0<(m+x|0)>>>0){A=y;B=z}else{y=c[n>>2]|0;Kg(y|0,y+h|0,h|0)|0;c[r>>2]=(c[r>>2]|0)-h;y=(c[l>>2]|0)-h|0;c[l>>2]=y;c[s>>2]=(c[s>>2]|0)-h;C=c[t>>2]|0;D=C;E=(c[u>>2]|0)+(C<<1)|0;do{E=E+ -2|0;C=e[E>>1]|0;if(C>>>0>>0){F=0}else{F=C-h&65535}b[E>>1]=F;D=D+ -1|0}while((D|0)!=0);D=h;E=(c[v>>2]|0)+(h<<1)|0;do{E=E+ -2|0;C=e[E>>1]|0;if(C>>>0>>0){G=0}else{G=C-h&65535}b[E>>1]=G;D=D+ -1|0}while((D|0)!=0);A=y;B=z+h|0}D=c[a>>2]|0;E=D+4|0;C=c[E>>2]|0;if((C|0)==0){H=28;break}I=c[k>>2]|0;J=(c[n>>2]|0)+(I+A)|0;K=C>>>0>B>>>0?B:C;if((K|0)==0){L=0;M=I}else{c[E>>2]=C-K;C=c[(c[D+28>>2]|0)+24>>2]|0;if((C|0)==2){E=D+48|0;c[E>>2]=gf(c[E>>2]|0,c[D>>2]|0,K)|0;N=D}else if((C|0)==1){C=D+48|0;c[C>>2]=ff(c[C>>2]|0,c[D>>2]|0,K)|0;N=D}else{N=D}Kg(J|0,c[N>>2]|0,K|0)|0;c[N>>2]=(c[N>>2]|0)+K;J=D+8|0;c[J>>2]=(c[J>>2]|0)+K;L=K;M=c[k>>2]|0}O=M+L|0;c[k>>2]=O;if(O>>>0>2?(K=c[l>>2]|0,J=c[n>>2]|0,D=d[J+K|0]|0,c[o>>2]=D,c[o>>2]=((d[J+(K+1)|0]|0)^D<>2])&c[q>>2],!(O>>>0<262)):0){break}if((c[(c[a>>2]|0)+4>>2]|0)==0){break}w=O;x=c[g>>2]|0}if((H|0)==28){i=f;return}H=a+5824|0;a=c[H>>2]|0;g=c[j>>2]|0;if(!(a>>>0>>0)){i=f;return}j=O+(c[l>>2]|0)|0;if(a>>>0>>0){l=g-j|0;O=l>>>0>258?258:l;Eg((c[n>>2]|0)+j|0,0,O|0)|0;c[H>>2]=O+j;i=f;return}O=j+258|0;if(!(a>>>0>>0)){i=f;return}j=O-a|0;O=g-a|0;g=j>>>0>O>>>0?O:j;Eg((c[n>>2]|0)+a|0,0,g|0)|0;c[H>>2]=(c[H>>2]|0)+g;i=f;return}function nf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;d=i;e=(c[a+12>>2]|0)+ -5|0;f=e>>>0<65535?e:65535;e=a+116|0;g=a+108|0;h=a+92|0;j=a+44|0;k=a+56|0;while(1){l=c[e>>2]|0;if(l>>>0<2){mf(a);m=c[e>>2]|0;if((m|b|0)==0){n=0;o=28;break}if((m|0)==0){o=20;break}else{p=m}}else{p=l}l=(c[g>>2]|0)+p|0;c[g>>2]=l;c[e>>2]=0;m=c[h>>2]|0;q=m+f|0;if((l|0)!=0&l>>>0>>0){r=l;s=m}else{c[e>>2]=l-q;c[g>>2]=q;if((m|0)>-1){t=(c[k>>2]|0)+m|0}else{t=0}Sf(a,t,f,0);c[h>>2]=c[g>>2];m=c[a>>2]|0;q=m+28|0;l=c[q>>2]|0;u=c[l+20>>2]|0;v=m+16|0;w=c[v>>2]|0;x=u>>>0>w>>>0?w:u;if((x|0)!=0?(u=m+12|0,Kg(c[u>>2]|0,c[l+16>>2]|0,x|0)|0,c[u>>2]=(c[u>>2]|0)+x,u=(c[q>>2]|0)+16|0,c[u>>2]=(c[u>>2]|0)+x,u=m+20|0,c[u>>2]=(c[u>>2]|0)+x,c[v>>2]=(c[v>>2]|0)-x,v=c[q>>2]|0,q=v+20|0,u=c[q>>2]|0,c[q>>2]=u-x,(u|0)==(x|0)):0){c[v+16>>2]=c[v+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=0;o=28;break}r=c[g>>2]|0;s=c[h>>2]|0}v=r-s|0;if(v>>>0<((c[j>>2]|0)+ -262|0)>>>0){continue}if((s|0)>-1){y=(c[k>>2]|0)+s|0}else{y=0}Sf(a,y,v,0);c[h>>2]=c[g>>2];v=c[a>>2]|0;x=v+28|0;u=c[x>>2]|0;q=c[u+20>>2]|0;m=v+16|0;l=c[m>>2]|0;w=q>>>0>l>>>0?l:q;if((w|0)!=0?(q=v+12|0,Kg(c[q>>2]|0,c[u+16>>2]|0,w|0)|0,c[q>>2]=(c[q>>2]|0)+w,q=(c[x>>2]|0)+16|0,c[q>>2]=(c[q>>2]|0)+w,q=v+20|0,c[q>>2]=(c[q>>2]|0)+w,c[m>>2]=(c[m>>2]|0)-w,m=c[x>>2]|0,x=m+20|0,q=c[x>>2]|0,c[x>>2]=q-w,(q|0)==(w|0)):0){c[m+16>>2]=c[m+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=0;o=28;break}}if((o|0)==20){y=c[h>>2]|0;if((y|0)>-1){z=(c[k>>2]|0)+y|0}else{z=0}k=(b|0)==4;Sf(a,z,(c[g>>2]|0)-y|0,k&1);c[h>>2]=c[g>>2];g=c[a>>2]|0;h=g+28|0;y=c[h>>2]|0;z=c[y+20>>2]|0;b=g+16|0;s=c[b>>2]|0;j=z>>>0>s>>>0?s:z;if((j|0)!=0?(z=g+12|0,Kg(c[z>>2]|0,c[y+16>>2]|0,j|0)|0,c[z>>2]=(c[z>>2]|0)+j,z=(c[h>>2]|0)+16|0,c[z>>2]=(c[z>>2]|0)+j,z=g+20|0,c[z>>2]=(c[z>>2]|0)+j,c[b>>2]=(c[b>>2]|0)-j,b=c[h>>2]|0,h=b+20|0,z=c[h>>2]|0,c[h>>2]=z-j,(z|0)==(j|0)):0){c[b+16>>2]=c[b+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=k?2:0;i=d;return n|0}else{n=k?3:1;i=d;return n|0}}else if((o|0)==28){i=d;return n|0}return 0}function of(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0;g=i;h=e+116|0;j=(f|0)==0;k=e+72|0;l=e+88|0;m=e+108|0;n=e+56|0;o=e+84|0;p=e+68|0;q=e+52|0;r=e+64|0;s=e+44|0;t=e+96|0;u=e+112|0;v=e+5792|0;w=e+5796|0;x=e+5784|0;y=e+5788|0;z=e+128|0;A=e+92|0;while(1){if((c[h>>2]|0)>>>0<262){mf(e);B=c[h>>2]|0;if(B>>>0<262&j){C=0;D=34;break}if((B|0)==0){D=26;break}if(!(B>>>0>2)){D=9}else{D=6}}else{D=6}if((D|0)==6){D=0;B=c[m>>2]|0;E=((d[(c[n>>2]|0)+(B+2)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=E;F=(c[p>>2]|0)+(E<<1)|0;E=b[F>>1]|0;b[(c[r>>2]|0)+((c[q>>2]&B)<<1)>>1]=E;G=E&65535;b[F>>1]=B;if(!(E<<16>>16==0)?!((B-G|0)>>>0>((c[s>>2]|0)+ -262|0)>>>0):0){B=qf(e,G)|0;c[t>>2]=B;H=B}else{D=9}}if((D|0)==9){D=0;H=c[t>>2]|0}do{if(H>>>0>2){B=H+253|0;G=(c[m>>2]|0)-(c[u>>2]|0)|0;E=c[v>>2]|0;b[(c[w>>2]|0)+(E<<1)>>1]=G;c[v>>2]=E+1;a[(c[x>>2]|0)+E|0]=B;E=e+((d[25272+(B&255)|0]|0|256)+1<<2)+148|0;b[E>>1]=(b[E>>1]|0)+1<<16>>16;E=G+65535&65535;if(E>>>0<256){I=E}else{I=(E>>>7)+256|0}E=e+((d[24760+I|0]|0)<<2)+2440|0;b[E>>1]=(b[E>>1]|0)+1<<16>>16;E=(c[v>>2]|0)==((c[y>>2]|0)+ -1|0)|0;G=c[t>>2]|0;B=(c[h>>2]|0)-G|0;c[h>>2]=B;if(!(G>>>0<=(c[z>>2]|0)>>>0&B>>>0>2)){B=(c[m>>2]|0)+G|0;c[m>>2]=B;c[t>>2]=0;F=c[n>>2]|0;J=d[F+B|0]|0;c[k>>2]=J;c[k>>2]=((d[F+(B+1)|0]|0)^J<>2])&c[o>>2];K=B;L=E;break}B=G+ -1|0;c[t>>2]=B;G=c[l>>2]|0;J=c[n>>2]|0;F=c[o>>2]|0;M=c[p>>2]|0;N=c[q>>2]|0;O=c[r>>2]|0;P=B;B=c[m>>2]|0;Q=c[k>>2]|0;while(1){R=B+1|0;c[m>>2]=R;Q=((d[J+(B+3)|0]|0)^Q<>2]=Q;S=M+(Q<<1)|0;b[O+((N&R)<<1)>>1]=b[S>>1]|0;b[S>>1]=R;P=P+ -1|0;c[t>>2]=P;if((P|0)==0){break}else{B=R}}P=B+2|0;c[m>>2]=P;K=P;L=E}else{P=a[(c[n>>2]|0)+(c[m>>2]|0)|0]|0;N=c[v>>2]|0;b[(c[w>>2]|0)+(N<<1)>>1]=0;c[v>>2]=N+1;a[(c[x>>2]|0)+N|0]=P;N=e+((P&255)<<2)+148|0;b[N>>1]=(b[N>>1]|0)+1<<16>>16;N=(c[v>>2]|0)==((c[y>>2]|0)+ -1|0)|0;c[h>>2]=(c[h>>2]|0)+ -1;P=(c[m>>2]|0)+1|0;c[m>>2]=P;K=P;L=N}}while(0);if((L|0)==0){continue}N=c[A>>2]|0;if((N|0)>-1){T=(c[n>>2]|0)+N|0}else{T=0}Sf(e,T,K-N|0,0);c[A>>2]=c[m>>2];N=c[e>>2]|0;P=N+28|0;O=c[P>>2]|0;Q=c[O+20>>2]|0;M=N+16|0;F=c[M>>2]|0;G=Q>>>0>F>>>0?F:Q;if((G|0)!=0?(Q=N+12|0,Kg(c[Q>>2]|0,c[O+16>>2]|0,G|0)|0,c[Q>>2]=(c[Q>>2]|0)+G,Q=(c[P>>2]|0)+16|0,c[Q>>2]=(c[Q>>2]|0)+G,Q=N+20|0,c[Q>>2]=(c[Q>>2]|0)+G,c[M>>2]=(c[M>>2]|0)-G,M=c[P>>2]|0,P=M+20|0,Q=c[P>>2]|0,c[P>>2]=Q-G,(Q|0)==(G|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){C=0;D=34;break}}if((D|0)==26){K=c[A>>2]|0;if((K|0)>-1){U=(c[n>>2]|0)+K|0}else{U=0}n=(f|0)==4;Sf(e,U,(c[m>>2]|0)-K|0,n&1);c[A>>2]=c[m>>2];m=c[e>>2]|0;A=m+28|0;K=c[A>>2]|0;U=c[K+20>>2]|0;f=m+16|0;T=c[f>>2]|0;L=U>>>0>T>>>0?T:U;if((L|0)!=0?(U=m+12|0,Kg(c[U>>2]|0,c[K+16>>2]|0,L|0)|0,c[U>>2]=(c[U>>2]|0)+L,U=(c[A>>2]|0)+16|0,c[U>>2]=(c[U>>2]|0)+L,U=m+20|0,c[U>>2]=(c[U>>2]|0)+L,c[f>>2]=(c[f>>2]|0)-L,f=c[A>>2]|0,A=f+20|0,U=c[A>>2]|0,c[A>>2]=U-L,(U|0)==(L|0)):0){c[f+16>>2]=c[f+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){C=n?2:0;i=g;return C|0}else{C=n?3:1;i=g;return C|0}}else if((D|0)==34){i=g;return C|0}return 0}function pf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0;g=i;h=e+116|0;j=(f|0)==0;k=e+72|0;l=e+88|0;m=e+108|0;n=e+56|0;o=e+84|0;p=e+68|0;q=e+52|0;r=e+64|0;s=e+96|0;t=e+120|0;u=e+112|0;v=e+100|0;w=e+5792|0;x=e+5796|0;y=e+5784|0;z=e+5788|0;A=e+104|0;B=e+92|0;C=e+128|0;D=e+44|0;E=e+136|0;a:while(1){F=c[h>>2]|0;while(1){if(F>>>0<262){mf(e);G=c[h>>2]|0;if(G>>>0<262&j){H=0;I=50;break a}if((G|0)==0){I=40;break a}if(!(G>>>0>2)){c[t>>2]=c[s>>2];c[v>>2]=c[u>>2];c[s>>2]=2;J=2;I=16}else{I=8}}else{I=8}do{if((I|0)==8){I=0;G=c[m>>2]|0;K=((d[(c[n>>2]|0)+(G+2)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=K;L=(c[p>>2]|0)+(K<<1)|0;K=b[L>>1]|0;b[(c[r>>2]|0)+((c[q>>2]&G)<<1)>>1]=K;M=K&65535;b[L>>1]=G;G=c[s>>2]|0;c[t>>2]=G;c[v>>2]=c[u>>2];c[s>>2]=2;if(!(K<<16>>16==0)){if(G>>>0<(c[C>>2]|0)>>>0){if(!(((c[m>>2]|0)-M|0)>>>0>((c[D>>2]|0)+ -262|0)>>>0)){K=qf(e,M)|0;c[s>>2]=K;if(K>>>0<6){if((c[E>>2]|0)!=1){if((K|0)!=3){J=K;I=16;break}if(!(((c[m>>2]|0)-(c[u>>2]|0)|0)>>>0>4096)){J=3;I=16;break}}c[s>>2]=2;J=2;I=16}else{J=K;I=16}}else{J=2;I=16}}else{N=G;O=2}}else{J=2;I=16}}}while(0);if((I|0)==16){I=0;N=c[t>>2]|0;O=J}if(!(N>>>0<3|O>>>0>N>>>0)){break}if((c[A>>2]|0)==0){c[A>>2]=1;c[m>>2]=(c[m>>2]|0)+1;G=(c[h>>2]|0)+ -1|0;c[h>>2]=G;F=G;continue}G=a[(c[n>>2]|0)+((c[m>>2]|0)+ -1)|0]|0;K=c[w>>2]|0;b[(c[x>>2]|0)+(K<<1)>>1]=0;c[w>>2]=K+1;a[(c[y>>2]|0)+K|0]=G;K=e+((G&255)<<2)+148|0;b[K>>1]=(b[K>>1]|0)+1<<16>>16;if((c[w>>2]|0)==((c[z>>2]|0)+ -1|0)){K=c[B>>2]|0;if((K|0)>-1){P=(c[n>>2]|0)+K|0}else{P=0}Sf(e,P,(c[m>>2]|0)-K|0,0);c[B>>2]=c[m>>2];K=c[e>>2]|0;G=K+28|0;M=c[G>>2]|0;L=c[M+20>>2]|0;Q=K+16|0;R=c[Q>>2]|0;S=L>>>0>R>>>0?R:L;if((S|0)!=0?(L=K+12|0,Kg(c[L>>2]|0,c[M+16>>2]|0,S|0)|0,c[L>>2]=(c[L>>2]|0)+S,L=(c[G>>2]|0)+16|0,c[L>>2]=(c[L>>2]|0)+S,L=K+20|0,c[L>>2]=(c[L>>2]|0)+S,c[Q>>2]=(c[Q>>2]|0)-S,Q=c[G>>2]|0,G=Q+20|0,L=c[G>>2]|0,c[G>>2]=L-S,(L|0)==(S|0)):0){c[Q+16>>2]=c[Q+8>>2]}}c[m>>2]=(c[m>>2]|0)+1;Q=(c[h>>2]|0)+ -1|0;c[h>>2]=Q;if((c[(c[e>>2]|0)+16>>2]|0)==0){H=0;I=50;break a}else{F=Q}}F=c[m>>2]|0;Q=F+ -3+(c[h>>2]|0)|0;S=N+253|0;L=F+65535-(c[v>>2]|0)|0;F=c[w>>2]|0;b[(c[x>>2]|0)+(F<<1)>>1]=L;c[w>>2]=F+1;a[(c[y>>2]|0)+F|0]=S;F=e+((d[25272+(S&255)|0]|0|256)+1<<2)+148|0;b[F>>1]=(b[F>>1]|0)+1<<16>>16;F=L+65535&65535;if(F>>>0<256){T=F}else{T=(F>>>7)+256|0}F=e+((d[24760+T|0]|0)<<2)+2440|0;b[F>>1]=(b[F>>1]|0)+1<<16>>16;F=c[w>>2]|0;L=(c[z>>2]|0)+ -1|0;S=c[t>>2]|0;c[h>>2]=1-S+(c[h>>2]|0);G=S+ -2|0;c[t>>2]=G;S=c[m>>2]|0;K=G;while(1){G=S+1|0;c[m>>2]=G;if(!(G>>>0>Q>>>0)){M=((d[(c[n>>2]|0)+(S+3)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=M;R=(c[p>>2]|0)+(M<<1)|0;b[(c[r>>2]|0)+((c[q>>2]&G)<<1)>>1]=b[R>>1]|0;b[R>>1]=G}K=K+ -1|0;c[t>>2]=K;if((K|0)==0){break}else{S=G}}c[A>>2]=0;c[s>>2]=2;K=S+2|0;c[m>>2]=K;if((F|0)!=(L|0)){continue}Q=c[B>>2]|0;if((Q|0)>-1){U=(c[n>>2]|0)+Q|0}else{U=0}Sf(e,U,K-Q|0,0);c[B>>2]=c[m>>2];Q=c[e>>2]|0;K=Q+28|0;G=c[K>>2]|0;R=c[G+20>>2]|0;M=Q+16|0;V=c[M>>2]|0;W=R>>>0>V>>>0?V:R;if((W|0)!=0?(R=Q+12|0,Kg(c[R>>2]|0,c[G+16>>2]|0,W|0)|0,c[R>>2]=(c[R>>2]|0)+W,R=(c[K>>2]|0)+16|0,c[R>>2]=(c[R>>2]|0)+W,R=Q+20|0,c[R>>2]=(c[R>>2]|0)+W,c[M>>2]=(c[M>>2]|0)-W,M=c[K>>2]|0,K=M+20|0,R=c[K>>2]|0,c[K>>2]=R-W,(R|0)==(W|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){H=0;I=50;break}}if((I|0)==40){if((c[A>>2]|0)!=0){U=a[(c[n>>2]|0)+((c[m>>2]|0)+ -1)|0]|0;s=c[w>>2]|0;b[(c[x>>2]|0)+(s<<1)>>1]=0;c[w>>2]=s+1;a[(c[y>>2]|0)+s|0]=U;s=e+((U&255)<<2)+148|0;b[s>>1]=(b[s>>1]|0)+1<<16>>16;c[A>>2]=0}A=c[B>>2]|0;if((A|0)>-1){X=(c[n>>2]|0)+A|0}else{X=0}n=(f|0)==4;Sf(e,X,(c[m>>2]|0)-A|0,n&1);c[B>>2]=c[m>>2];m=c[e>>2]|0;B=m+28|0;A=c[B>>2]|0;X=c[A+20>>2]|0;f=m+16|0;s=c[f>>2]|0;U=X>>>0>s>>>0?s:X;if((U|0)!=0?(X=m+12|0,Kg(c[X>>2]|0,c[A+16>>2]|0,U|0)|0,c[X>>2]=(c[X>>2]|0)+U,X=(c[B>>2]|0)+16|0,c[X>>2]=(c[X>>2]|0)+U,X=m+20|0,c[X>>2]=(c[X>>2]|0)+U,c[f>>2]=(c[f>>2]|0)-U,f=c[B>>2]|0,B=f+20|0,X=c[B>>2]|0,c[B>>2]=X-U,(X|0)==(U|0)):0){c[f+16>>2]=c[f+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){H=n?2:0;i=g;return H|0}else{H=n?3:1;i=g;return H|0}}else if((I|0)==50){i=g;return H|0}return 0}function qf(b,d){b=b|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;f=i;g=c[b+124>>2]|0;h=c[b+56>>2]|0;j=c[b+108>>2]|0;k=h+j|0;l=c[b+120>>2]|0;m=c[b+144>>2]|0;n=(c[b+44>>2]|0)+ -262|0;o=j>>>0>n>>>0?j-n|0:0;n=c[b+64>>2]|0;p=c[b+52>>2]|0;q=h+(j+258)|0;r=c[b+116>>2]|0;s=m>>>0>r>>>0?r:m;m=b+112|0;t=h+(j+1)|0;u=h+(j+2)|0;v=q;w=j+257|0;x=d;d=l;y=l>>>0<(c[b+140>>2]|0)>>>0?g:g>>>2;g=a[h+(l+j)|0]|0;b=a[h+(j+ -1+l)|0]|0;while(1){l=h+x|0;if((((a[h+(x+d)|0]|0)==g<<24>>24?(a[h+(d+ -1+x)|0]|0)==b<<24>>24:0)?(a[l]|0)==(a[k]|0):0)?(a[h+(x+1)|0]|0)==(a[t]|0):0){l=h+(x+2)|0;z=u;while(1){A=z+1|0;if((a[A]|0)!=(a[l+1|0]|0)){B=A;break}A=z+2|0;if((a[A]|0)!=(a[l+2|0]|0)){B=A;break}A=z+3|0;if((a[A]|0)!=(a[l+3|0]|0)){B=A;break}A=z+4|0;if((a[A]|0)!=(a[l+4|0]|0)){B=A;break}A=z+5|0;if((a[A]|0)!=(a[l+5|0]|0)){B=A;break}A=z+6|0;if((a[A]|0)!=(a[l+6|0]|0)){B=A;break}A=z+7|0;if((a[A]|0)!=(a[l+7|0]|0)){B=A;break}A=z+8|0;C=l+8|0;if((a[A]|0)==(a[C]|0)&A>>>0>>0){l=C;z=A}else{B=A;break}}z=B-v|0;l=z+258|0;if((l|0)>(d|0)){c[m>>2]=x;if((l|0)>=(s|0)){D=l;E=20;break}F=l;G=a[h+(l+j)|0]|0;H=a[h+(w+z)|0]|0}else{F=d;G=g;H=b}}else{F=d;G=g;H=b}z=e[n+((x&p)<<1)>>1]|0;if(!(z>>>0>o>>>0)){D=F;E=20;break}l=y+ -1|0;if((l|0)==0){D=F;E=20;break}else{x=z;d=F;y=l;g=G;b=H}}if((E|0)==20){i=f;return(D>>>0>r>>>0?r:D)|0}return 0}function rf(a){a=a|0;var b=0,d=0;b=i;do{if((a|0)!=0){if((c[a>>2]|0)==7247){d=Af(a)|0;break}else{d=Ff(a)|0;break}}else{d=-2}}while(0);i=b;return d|0}function sf(a,b){a=a|0;b=b|0;var c=0,d=0;c=i;d=tf(a,-1,b)|0;i=c;return d|0}function tf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+16|0;g=f;h=gg(140)|0;if((h|0)==0){j=0;i=f;return j|0}c[h+16>>2]=0;c[h+20>>2]=8192;k=h+80|0;c[k>>2]=0;c[h>>2]=0;l=h+60|0;c[l>>2]=-1;m=h+64|0;c[m>>2]=0;n=a[e]|0;if(!(n<<24>>24==0)){o=e;e=n;n=0;a:while(1){p=e<<24>>24;b:do{if((e+ -48<<24>>24&255)<10){c[l>>2]=p+ -48;q=n}else{switch(p|0){case 70:{c[m>>2]=4;q=n;break b;break};case 43:{r=9;break a;break};case 82:{c[m>>2]=3;q=n;break b;break};case 102:{c[m>>2]=1;q=n;break b;break};case 104:{c[m>>2]=2;q=n;break b;break};case 119:{c[h>>2]=31153;q=31153;break b;break};case 97:{c[h>>2]=1;q=1;break b;break};case 114:{c[h>>2]=7247;q=7247;break b;break};default:{q=n;break b}}}}while(0);o=o+1|0;e=a[o]|0;if(e<<24>>24==0){break}else{n=q}}if((r|0)==9){hg(h);j=0;i=f;return j|0}if((q|0)!=0){q=gg((Dg(b|0)|0)+1|0)|0;r=h+8|0;c[r>>2]=q;if((q|0)==0){hg(h);j=0;i=f;return j|0}Lg(q|0,b|0)|0;if((d|0)==-1){q=c[h>>2]|0;if((q|0)==7247){s=32768}else{s=(q|0)==31153?33345:33857}c[g>>2]=438;q=Aa(b|0,s|0,g|0)|0;c[h+4>>2]=q;if((q|0)==-1){hg(c[r>>2]|0);hg(h);j=0;i=f;return j|0}else{t=q}}else{c[h+4>>2]=d;t=d}d=c[h>>2]|0;if((d|0)==1){c[h>>2]=31153}else if((d|0)==7247?(d=ra(t|0,0,1)|0,c[h+44>>2]=(d|0)==-1?0:d,(c[h>>2]|0)==7247):0){c[h+36>>2]=0;c[h+40>>2]=0;c[h+52>>2]=0;c[h+56>>2]=1}c[h+72>>2]=0;d=c[k>>2]|0;t=h+76|0;if((d|0)!=0){if(!((c[t>>2]|0)==-4)){hg(d)}c[k>>2]=0}c[t>>2]=0;c[h+12>>2]=0;c[h+88>>2]=0;j=h;i=f;return j|0}}hg(h);j=0;i=f;return j|0}function uf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;e=i;if((a|0)==0){f=-1;i=e;return f|0}g=c[a>>2]|0;if(!((g|0)==31153|(g|0)==7247)){f=-1;i=e;return f|0}h=a+76|0;if((c[h>>2]|0)!=0|d>>>0>1){f=-1;i=e;return f|0}if((d|0)!=0){d=a+72|0;if((c[d>>2]|0)==0){j=b;k=d}else{j=(c[a+68>>2]|0)+b|0;k=d}}else{j=b-(c[a+12>>2]|0)|0;k=a+72|0}c[k>>2]=0;b=(g|0)==7247;if((b?(c[a+52>>2]|0)==1:0)?(d=a+12|0,((c[d>>2]|0)+j|0)>=(c[a+48>>2]|0)):0){l=a+36|0;if((ra(c[a+4>>2]|0,j-(c[l>>2]|0)|0,1)|0)==-1){f=-1;i=e;return f|0}c[l>>2]=0;c[a+40>>2]=0;c[k>>2]=0;l=a+80|0;m=c[l>>2]|0;if((m|0)!=0){if(!((c[h>>2]|0)==-4)){hg(m)}c[l>>2]=0}c[h>>2]=0;c[a+88>>2]=0;l=(c[d>>2]|0)+j|0;c[d>>2]=l;f=l;i=e;return f|0}if((j|0)<0){if(!b){f=-1;i=e;return f|0}b=a+12|0;l=(c[b>>2]|0)+j|0;if((l|0)<0){f=-1;i=e;return f|0}if((ra(c[a+4>>2]|0,c[a+44>>2]|0,0)|0)==-1){f=-1;i=e;return f|0}d=c[a>>2]|0;if((d|0)==7247){c[a+36>>2]=0;c[a+40>>2]=0;c[a+52>>2]=0;c[a+56>>2]=1}c[k>>2]=0;m=a+80|0;n=c[m>>2]|0;if((n|0)==0){o=d}else{if((c[h>>2]|0)==-4){p=d}else{hg(n);p=c[a>>2]|0}c[m>>2]=0;o=p}c[h>>2]=0;c[b>>2]=0;c[a+88>>2]=0;q=l;r=o}else{q=j;r=g}if((r|0)==7247){r=a+36|0;g=c[r>>2]|0;j=(g|0)<0|(g|0)>(q|0)?q:g;c[r>>2]=g-j;g=a+32|0;c[g>>2]=(c[g>>2]|0)+j;g=a+12|0;c[g>>2]=j+(c[g>>2]|0);s=q-j|0}else{s=q}if((s|0)!=0){c[k>>2]=1;c[a+68>>2]=s}f=(c[a+12>>2]|0)+s|0;i=e;return f|0}function vf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;g=b+80|0;h=c[g>>2]|0;j=b+76|0;if((h|0)!=0){if(!((c[j>>2]|0)==-4)){hg(h)}c[g>>2]=0}c[j>>2]=d;if((e|0)==0){i=f;return}if((d|0)==-4){c[g>>2]=e;i=f;return}d=c[b+8>>2]|0;b=Dg(d|0)|0;h=gg(b+3+(Dg(e|0)|0)|0)|0;c[g>>2]=h;if((h|0)==0){c[j>>2]=-4;c[g>>2]=21280;i=f;return}else{Lg(h|0,d|0)|0;d=c[g>>2]|0;h=d+(Dg(d|0)|0)|0;a[h+0|0]=a[21296|0]|0;a[h+1|0]=a[21297|0]|0;a[h+2|0]=a[21298|0]|0;Fg(c[g>>2]|0,e|0)|0;i=f;return}}function wf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=uf(a,b,c)|0;i=d;return e|0}function xf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0;e=i;if((a|0)==0){f=-1;i=e;return f|0}if((c[a>>2]|0)!=7247){f=-1;i=e;return f|0}if((c[a+76>>2]|0)!=0){f=-1;i=e;return f|0}if((d|0)<0){vf(a,-5,21304);f=-1;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}g=a+72|0;a:do{if((c[g>>2]|0)!=0){c[g>>2]=0;h=c[a+68>>2]|0;j=a+36|0;k=a+40|0;l=a+88|0;m=a+32|0;n=a+12|0;if((h|0)!=0){o=a+52|0;p=a+28|0;q=a+16|0;r=a+4|0;s=a+100|0;t=a+96|0;u=h;b:while(1){c:while(1){v=c[j>>2]|0;while(1){if((v|0)!=0){break c}if((c[k>>2]|0)!=0?(c[l>>2]|0)==0:0){w=j;x=k;y=m;z=l;A=n;break a}h=c[o>>2]|0;if((h|0)!=0){B=h;break}if((zf(a)|0)==-1){f=-1;C=59;break b}h=c[j>>2]|0;if((h|0)==0){C=21;break}else{v=h}}if((C|0)==21){C=0;B=c[o>>2]|0}if((B|0)==2){c[s>>2]=c[q>>2]<<1;c[t>>2]=c[p>>2];if((yf(a)|0)==-1){f=-1;C=59;break b}else{continue}}else if((B|0)!=1){continue}h=c[p>>2]|0;D=c[q>>2]<<1;c[j>>2]=0;E=0;do{F=Za(c[r>>2]|0,h+E|0,D-E|0)|0;if((F|0)<1){C=26;break}E=(c[j>>2]|0)+F|0;c[j>>2]=E}while(E>>>0>>0);if((C|0)==26){C=0;if((F|0)<0){C=28;break b}c[k>>2]=1}c[m>>2]=c[p>>2]}D=(v|0)<0|(v|0)>(u|0)?u:v;c[j>>2]=v-D;c[m>>2]=(c[m>>2]|0)+D;c[n>>2]=(c[n>>2]|0)+D;if((u|0)==(D|0)){w=j;x=k;y=m;z=l;A=n;break a}else{u=u-D|0}}if((C|0)==28){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==59){i=e;return f|0}}else{w=j;x=k;y=m;z=l;A=n}}else{w=a+36|0;x=a+40|0;y=a+32|0;z=a+88|0;A=a+12|0}}while(0);v=a+52|0;F=a+28|0;B=a+16|0;g=a+4|0;u=a+100|0;p=a+96|0;r=b;b=d;d=0;d:while(1){q=c[w>>2]|0;e:do{if((q|0)==0){if((c[x>>2]|0)!=0?(c[z>>2]|0)==0:0){f=d;C=59;break d}t=c[v>>2]|0;if((t|0)!=0){if(b>>>0>2]<<1>>>0){G=t}else{if((t|0)==1){H=0}else{c[u>>2]=b;c[p>>2]=r;if((yf(a)|0)==-1){f=-1;C=59;break d}t=c[w>>2]|0;c[w>>2]=0;I=t;C=57;break}while(1){J=Za(c[g>>2]|0,r+H|0,b-H|0)|0;if((J|0)<1){break}t=J+H|0;if(t>>>0>>0){H=t}else{I=t;C=57;break e}}if((J|0)<0){C=54;break d}c[x>>2]=1;I=H;C=57;break}}else{if((zf(a)|0)==-1){f=-1;C=59;break d}if((c[w>>2]|0)!=0){K=r;L=b;M=d;break}G=c[v>>2]|0}if((G|0)==2){c[u>>2]=c[B>>2]<<1;c[p>>2]=c[F>>2];if((yf(a)|0)==-1){f=-1;C=59;break d}else{K=r;L=b;M=d;break}}else if((G|0)!=1){K=r;L=b;M=d;break}t=c[F>>2]|0;s=c[B>>2]<<1;c[w>>2]=0;o=0;do{N=Za(c[g>>2]|0,t+o|0,s-o|0)|0;if((N|0)<1){C=44;break}o=(c[w>>2]|0)+N|0;c[w>>2]=o}while(o>>>0>>0);if((C|0)==44){C=0;if((N|0)<0){C=46;break d}c[x>>2]=1}c[y>>2]=c[F>>2];K=r;L=b;M=d}else{s=q>>>0>b>>>0?b:q;Kg(r|0,c[y>>2]|0,s|0)|0;c[y>>2]=(c[y>>2]|0)+s;c[w>>2]=(c[w>>2]|0)-s;I=s;C=57}}while(0);if((C|0)==57){C=0;c[A>>2]=(c[A>>2]|0)+I;K=r+I|0;L=b-I|0;M=I+d|0}if((L|0)==0){f=M;C=59;break}else{r=K;b=L;d=M}}if((C|0)==46){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==54){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==59){i=e;return f|0}return 0}function yf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;b=i;i=i+16|0;d=b+4|0;e=b;f=a+84|0;g=a+100|0;h=c[g>>2]|0;j=a+88|0;k=a+76|0;l=a+40|0;m=a+24|0;n=a+16|0;o=a+4|0;p=a+84|0;while(1){if((c[j>>2]|0)==0){if((c[k>>2]|0)!=0){q=-1;r=27;break}if((c[l>>2]|0)!=0){r=12;break}s=c[m>>2]|0;t=c[n>>2]|0;c[j>>2]=0;u=0;while(1){v=Za(c[o>>2]|0,s+u|0,t-u|0)|0;if((v|0)<1){r=8;break}w=(c[j>>2]|0)+v|0;c[j>>2]=w;if(w>>>0>>0){u=w}else{x=w;break}}if((r|0)==8){r=0;if((v|0)<0){r=10;break}c[l>>2]=1;x=c[j>>2]|0}c[p>>2]=c[m>>2];if((x|0)==0){r=12;break}}u=Kf(f,0)|0;if((u|0)==-4){r=15;break}else if((u|0)==-3){r=16;break}else if((u|0)==2|(u|0)==-2){r=14;break}y=c[g>>2]|0;z=(u|0)==1;if((y|0)==0|z){r=18;break}}if((r|0)==10){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);q=-1;i=b;return q|0}else if((r|0)==12){vf(a,-3,21432);q=-1;i=b;return q|0}else if((r|0)==14){vf(a,-2,21456);q=-1;i=b;return q|0}else if((r|0)==15){vf(a,-4,21344);q=-1;i=b;return q|0}else if((r|0)==16){g=c[a+108>>2]|0;vf(a,-3,(g|0)==0?21496:g);q=-1;i=b;return q|0}else if((r|0)==18){g=h-y|0;c[a+36>>2]=g;y=(c[a+96>>2]|0)+(0-g)|0;c[a+32>>2]=y;h=a+132|0;c[h>>2]=gf(c[h>>2]|0,y,g)|0;if(!z){q=0;i=b;return q|0}if(!((Bf(a,d)|0)==-1)?!((Bf(a,e)|0)==-1):0){if((c[d>>2]|0)!=(c[h>>2]|0)){vf(a,-3,21520);q=-1;i=b;return q|0}if((c[e>>2]|0)==(c[a+104>>2]|0)){c[a+52>>2]=0;q=0;i=b;return q|0}else{vf(a,-3,21544);q=-1;i=b;return q|0}}vf(a,-3,21432);q=-1;i=b;return q|0}else if((r|0)==27){i=b;return q|0}return 0}function zf(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0;e=i;f=b+84|0;g=b+16|0;do{if((c[g>>2]|0)==0){h=c[b+20>>2]|0;j=gg(h)|0;k=b+24|0;c[k>>2]=j;l=gg(h<<1)|0;m=b+28|0;c[m>>2]=l;n=(l|0)==0;if(!((j|0)==0|n)){c[g>>2]=h;c[b+116>>2]=0;c[b+120>>2]=0;c[b+124>>2]=0;h=b+88|0;c[h>>2]=0;c[f>>2]=0;if((Jf(f,-15,21360,56)|0)==0){o=h;break}hg(c[m>>2]|0);hg(c[k>>2]|0);c[g>>2]=0;vf(b,-4,21344);p=-1;i=e;return p|0}if(n){q=j}else{hg(l);q=c[k>>2]|0}if((q|0)!=0){hg(q)}vf(b,-4,21344);p=-1;i=e;return p|0}else{o=b+88|0}}while(0);q=c[o>>2]|0;if((q|0)==0){if((c[b+76>>2]|0)!=0){p=-1;i=e;return p|0}k=b+40|0;if((c[k>>2]|0)!=0){p=0;i=e;return p|0}l=b+24|0;j=c[l>>2]|0;n=c[g>>2]|0;c[o>>2]=0;m=b+4|0;h=0;while(1){r=Za(c[m>>2]|0,j+h|0,n-h|0)|0;if((r|0)<1){s=17;break}t=(c[o>>2]|0)+r|0;c[o>>2]=t;if(t>>>0>>0){h=t}else{u=t;break}}do{if((s|0)==17){if((r|0)>=0){c[k>>2]=1;u=c[o>>2]|0;break}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);p=-1;i=e;return p|0}}while(0);c[b+84>>2]=c[l>>2];if((u|0)==0){p=0;i=e;return p|0}else{v=u}}else{v=q}q=c[f>>2]|0;if((a[q]|0)==31){u=v+ -1|0;c[o>>2]=u;l=q+1|0;c[f>>2]=l;if((u|0)==0){if((c[b+76>>2]|0)!=0){p=-1;i=e;return p|0}q=b+40|0;if((c[q>>2]|0)==0){k=b+24|0;r=c[k>>2]|0;h=c[g>>2]|0;c[o>>2]=0;n=b+4|0;j=0;while(1){w=Za(c[n>>2]|0,r+j|0,h-j|0)|0;if((w|0)<1){s=29;break}m=(c[o>>2]|0)+w|0;c[o>>2]=m;if(m>>>0>>0){j=m}else{x=m;break}}do{if((s|0)==29){if((w|0)>=0){c[q>>2]=1;x=c[o>>2]|0;break}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);p=-1;i=e;return p|0}}while(0);q=c[k>>2]|0;c[b+84>>2]=q;if((x|0)!=0){y=q;z=x;s=33}}}else{y=l;z=u;s=33}if((s|0)==33?(a[y]|0)==-117:0){u=z+ -1|0;c[o>>2]=u;z=y+1|0;c[f>>2]=z;a:do{if((u|0)==0){if((c[b+76>>2]|0)==0?(y=b+40|0,(c[y>>2]|0)==0):0){l=b+24|0;x=c[l>>2]|0;q=c[g>>2]|0;c[o>>2]=0;k=b+4|0;w=0;while(1){A=Za(c[k>>2]|0,x+w|0,q-w|0)|0;if((A|0)<1){s=40;break}j=(c[o>>2]|0)+A|0;c[o>>2]=j;if(j>>>0>>0){w=j}else{B=j;break}}do{if((s|0)==40){if((A|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break a}else{c[y>>2]=1;B=c[o>>2]|0;break}}}while(0);y=c[l>>2]|0;c[b+84>>2]=y;if((B|0)!=0){C=B;D=y;s=44}}}else{C=u;D=z;s=44}}while(0);if((s|0)==44?(z=C+ -1|0,c[o>>2]=z,C=D+1|0,c[f>>2]=C,(a[D]|0)==8):0){b:do{if((z|0)==0){if((c[b+76>>2]|0)==0?(D=b+40|0,(c[D>>2]|0)==0):0){u=b+24|0;B=c[u>>2]|0;A=c[g>>2]|0;c[o>>2]=0;y=b+4|0;w=0;while(1){E=Za(c[y>>2]|0,B+w|0,A-w|0)|0;if((E|0)<1){s=52;break}q=(c[o>>2]|0)+E|0;c[o>>2]=q;if(q>>>0>>0){w=q}else{F=q;break}}do{if((s|0)==52){if((E|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break b}else{c[D>>2]=1;F=c[o>>2]|0;break}}}while(0);D=c[u>>2]|0;c[b+84>>2]=D;if((F|0)!=0){G=F;H=D;s=56}}}else{G=z;H=C;s=56}}while(0);if((s|0)==56?(C=G+ -1|0,c[o>>2]=C,G=H+1|0,c[f>>2]=G,z=d[H]|0,(z&224|0)==0):0){c:do{if((C|0)==0){H=b+76|0;if((c[H>>2]|0)==0){F=b+40|0;if((c[F>>2]|0)==0){E=b+24|0;D=c[E>>2]|0;w=c[g>>2]|0;c[o>>2]=0;A=b+4|0;B=0;while(1){I=Za(c[A>>2]|0,D+B|0,w-B|0)|0;if((I|0)<1){s=64;break}y=(c[o>>2]|0)+I|0;c[o>>2]=y;if(y>>>0>>0){B=y}else{J=y;break}}do{if((s|0)==64){if((I|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);K=c[o>>2]|0;s=69;break c}else{c[F>>2]=1;J=c[o>>2]|0;break}}}while(0);F=c[E>>2]|0;c[b+84>>2]=F;if((J|0)!=0){L=J;M=F;s=68}else{N=H;s=71}}else{N=H;s=71}}else{s=70}}else{L=C;M=G;s=68}}while(0);if((s|0)==68){G=L+ -1|0;c[o>>2]=G;c[f>>2]=M+1;K=G;s=69}if((s|0)==69){if((K|0)==0){s=70}else{O=K;s=80}}if((s|0)==70){N=b+76|0;s=71}d:do{if((s|0)==71){if((c[N>>2]|0)==0){K=b+40|0;if((c[K>>2]|0)==0){G=b+24|0;M=c[G>>2]|0;L=c[g>>2]|0;c[o>>2]=0;C=b+4|0;J=0;while(1){P=Za(c[C>>2]|0,M+J|0,L-J|0)|0;if((P|0)<1){s=76;break}I=(c[o>>2]|0)+P|0;c[o>>2]=I;if(I>>>0>>0){J=I}else{Q=I;break}}do{if((s|0)==76){if((P|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);R=c[o>>2]|0;s=81;break d}else{c[K>>2]=1;Q=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[G>>2];if((Q|0)!=0){O=Q;s=80}else{S=N;s=83}}else{S=N;s=83}}else{s=82}}}while(0);if((s|0)==80){N=O+ -1|0;c[o>>2]=N;c[f>>2]=(c[f>>2]|0)+1;R=N;s=81}if((s|0)==81){if((R|0)==0){s=82}else{T=R;s=92}}if((s|0)==82){S=b+76|0;s=83}e:do{if((s|0)==83){if((c[S>>2]|0)==0){R=b+40|0;if((c[R>>2]|0)==0){N=b+24|0;O=c[N>>2]|0;Q=c[g>>2]|0;c[o>>2]=0;P=b+4|0;K=0;while(1){U=Za(c[P>>2]|0,O+K|0,Q-K|0)|0;if((U|0)<1){s=88;break}J=(c[o>>2]|0)+U|0;c[o>>2]=J;if(J>>>0>>0){K=J}else{V=J;break}}do{if((s|0)==88){if((U|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);W=c[o>>2]|0;s=93;break e}else{c[R>>2]=1;V=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[N>>2];if((V|0)!=0){T=V;s=92}else{X=S;s=95}}else{X=S;s=95}}else{s=94}}}while(0);if((s|0)==92){S=T+ -1|0;c[o>>2]=S;c[f>>2]=(c[f>>2]|0)+1;W=S;s=93}if((s|0)==93){if((W|0)==0){s=94}else{Y=W;s=104}}if((s|0)==94){X=b+76|0;s=95}f:do{if((s|0)==95){if((c[X>>2]|0)==0){W=b+40|0;if((c[W>>2]|0)==0){S=b+24|0;T=c[S>>2]|0;V=c[g>>2]|0;c[o>>2]=0;U=b+4|0;R=0;while(1){Z=Za(c[U>>2]|0,T+R|0,V-R|0)|0;if((Z|0)<1){s=100;break}K=(c[o>>2]|0)+Z|0;c[o>>2]=K;if(K>>>0>>0){R=K}else{_=K;break}}do{if((s|0)==100){if((Z|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);$=c[o>>2]|0;s=105;break f}else{c[W>>2]=1;_=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[S>>2];if((_|0)!=0){Y=_;s=104}else{aa=X;s=107}}else{aa=X;s=107}}else{s=106}}}while(0);if((s|0)==104){X=Y+ -1|0;c[o>>2]=X;c[f>>2]=(c[f>>2]|0)+1;$=X;s=105}if((s|0)==105){if(($|0)==0){s=106}else{ba=$;s=116}}if((s|0)==106){aa=b+76|0;s=107}g:do{if((s|0)==107){if((c[aa>>2]|0)==0){$=b+40|0;if((c[$>>2]|0)==0){X=b+24|0;Y=c[X>>2]|0;_=c[g>>2]|0;c[o>>2]=0;Z=b+4|0;W=0;while(1){ca=Za(c[Z>>2]|0,Y+W|0,_-W|0)|0;if((ca|0)<1){s=112;break}R=(c[o>>2]|0)+ca|0;c[o>>2]=R;if(R>>>0<_>>>0){W=R}else{da=R;break}}do{if((s|0)==112){if((ca|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);ea=c[o>>2]|0;s=117;break g}else{c[$>>2]=1;da=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[X>>2];if((da|0)!=0){ba=da;s=116}else{fa=aa;s=119}}else{fa=aa;s=119}}else{s=118}}}while(0);if((s|0)==116){aa=ba+ -1|0;c[o>>2]=aa;c[f>>2]=(c[f>>2]|0)+1;ea=aa;s=117}if((s|0)==117){if((ea|0)==0){s=118}else{ga=ea;s=128}}if((s|0)==118){fa=b+76|0;s=119}h:do{if(((s|0)==119?(c[fa>>2]|0)==0:0)?(ea=b+40|0,(c[ea>>2]|0)==0):0){aa=b+24|0;ba=c[aa>>2]|0;da=c[g>>2]|0;c[o>>2]=0;ca=b+4|0;$=0;while(1){ha=Za(c[ca>>2]|0,ba+$|0,da-$|0)|0;if((ha|0)<1){s=124;break}W=(c[o>>2]|0)+ha|0;c[o>>2]=W;if(W>>>0>>0){$=W}else{ia=W;break}}do{if((s|0)==124){if((ha|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break h}else{c[ea>>2]=1;ia=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[aa>>2];if((ia|0)!=0){ga=ia;s=128}}}while(0);if((s|0)==128){c[o>>2]=ga+ -1;c[f>>2]=(c[f>>2]|0)+1}i:do{if((z&4|0)!=0){ga=c[o>>2]|0;j:do{if((ga|0)==0){ia=b+76|0;if((c[ia>>2]|0)==0){ha=b+40|0;if((c[ha>>2]|0)==0){fa=b+24|0;ea=c[fa>>2]|0;$=c[g>>2]|0;c[o>>2]=0;da=b+4|0;ba=0;while(1){ja=Za(c[da>>2]|0,ea+ba|0,$-ba|0)|0;if((ja|0)<1){s=136;break}ca=(c[o>>2]|0)+ja|0;c[o>>2]=ca;if(ca>>>0<$>>>0){ba=ca}else{ka=ca;break}}do{if((s|0)==136){if((ja|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);la=-1;ma=c[o>>2]|0;s=141;break j}else{c[ha>>2]=1;ka=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[fa>>2];if((ka|0)!=0){na=ka;s=140}else{oa=ia;pa=-1;s=143}}else{oa=ia;pa=-1;s=143}}else{qa=-1;s=142}}else{na=ga;s=140}}while(0);if((s|0)==140){ga=na+ -1|0;c[o>>2]=ga;aa=c[f>>2]|0;c[f>>2]=aa+1;la=d[aa]|0;ma=ga;s=141}if((s|0)==141){if((ma|0)==0){qa=la;s=142}else{ra=ma;sa=la;s=152}}if((s|0)==142){oa=b+76|0;pa=qa;s=143}k:do{if((s|0)==143){if((c[oa>>2]|0)==0?(ga=b+40|0,(c[ga>>2]|0)==0):0){aa=b+24|0;ha=c[aa>>2]|0;ba=c[g>>2]|0;c[o>>2]=0;$=b+4|0;ea=0;while(1){ta=Za(c[$>>2]|0,ha+ea|0,ba-ea|0)|0;if((ta|0)<1){s=148;break}da=(c[o>>2]|0)+ta|0;c[o>>2]=da;if(da>>>0>>0){ea=da}else{ua=da;break}}do{if((s|0)==148){if((ta|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);va=-256;wa=pa;break k}else{c[ga>>2]=1;ua=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[aa>>2];if((ua|0)!=0){ra=ua;sa=pa;s=152}else{va=-256;wa=pa}}else{va=-256;wa=pa}}}while(0);if((s|0)==152){c[o>>2]=ra+ -1;ga=c[f>>2]|0;c[f>>2]=ga+1;va=d[ga]<<8;wa=sa}ga=va+wa|0;if((ga|0)!=0){ea=b+76|0;ba=b+40|0;ha=b+24|0;$=b+4|0;ia=b+84|0;fa=ga;ga=c[o>>2]|0;while(1){fa=fa+ -1|0;if((ga|0)==0){if((c[ea>>2]|0)!=0){break i}if((c[ba>>2]|0)!=0){break i}da=c[ha>>2]|0;ca=c[g>>2]|0;c[o>>2]=0;X=0;while(1){xa=Za(c[$>>2]|0,da+X|0,ca-X|0)|0;if((xa|0)<1){s=161;break}W=(c[o>>2]|0)+xa|0;c[o>>2]=W;if(W>>>0>>0){X=W}else{ya=W;break}}if((s|0)==161){s=0;if((xa|0)<0){break}c[ba>>2]=1;ya=c[o>>2]|0}c[ia>>2]=c[ha>>2];if((ya|0)==0){break i}else{za=ya}}else{za=ga}ga=za+ -1|0;c[o>>2]=ga;c[f>>2]=(c[f>>2]|0)+1;if((fa|0)==0){break i}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}}while(0);l:do{if((z&8|0)!=0){za=b+76|0;ya=b+40|0;xa=b+24|0;wa=b+4|0;va=b+84|0;sa=c[o>>2]|0;while(1){if((sa|0)==0){if((c[za>>2]|0)!=0){break l}if((c[ya>>2]|0)!=0){break l}ra=c[xa>>2]|0;pa=c[g>>2]|0;c[o>>2]=0;ua=0;while(1){Aa=Za(c[wa>>2]|0,ra+ua|0,pa-ua|0)|0;if((Aa|0)<1){s=174;break}ta=(c[o>>2]|0)+Aa|0;c[o>>2]=ta;if(ta>>>0>>0){ua=ta}else{Ba=ta;break}}if((s|0)==174){s=0;if((Aa|0)<0){break}c[ya>>2]=1;Ba=c[o>>2]|0}c[va>>2]=c[xa>>2];if((Ba|0)==0){break l}else{Ca=Ba}}else{Ca=sa}sa=Ca+ -1|0;c[o>>2]=sa;ua=c[f>>2]|0;c[f>>2]=ua+1;if((a[ua]|0)==0){break l}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}while(0);m:do{if((z&16|0)!=0){Ca=b+76|0;Ba=b+40|0;Aa=b+24|0;sa=b+4|0;xa=b+84|0;va=c[o>>2]|0;while(1){if((va|0)==0){if((c[Ca>>2]|0)!=0){break m}if((c[Ba>>2]|0)!=0){break m}ya=c[Aa>>2]|0;wa=c[g>>2]|0;c[o>>2]=0;za=0;while(1){Da=Za(c[sa>>2]|0,ya+za|0,wa-za|0)|0;if((Da|0)<1){s=187;break}ua=(c[o>>2]|0)+Da|0;c[o>>2]=ua;if(ua>>>0>>0){za=ua}else{Ea=ua;break}}if((s|0)==187){s=0;if((Da|0)<0){break}c[Ba>>2]=1;Ea=c[o>>2]|0}c[xa>>2]=c[Aa>>2];if((Ea|0)==0){break m}else{Fa=Ea}}else{Fa=va}va=Fa+ -1|0;c[o>>2]=va;za=c[f>>2]|0;c[f>>2]=za+1;if((a[za]|0)==0){break m}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}while(0);n:do{if((z&2|0)!=0){Fa=c[o>>2]|0;o:do{if((Fa|0)==0){Ea=b+76|0;if((c[Ea>>2]|0)==0){Da=b+40|0;if((c[Da>>2]|0)==0){va=b+24|0;Aa=c[va>>2]|0;xa=c[g>>2]|0;c[o>>2]=0;Ba=b+4|0;sa=0;while(1){Ga=Za(c[Ba>>2]|0,Aa+sa|0,xa-sa|0)|0;if((Ga|0)<1){s=199;break}Ca=(c[o>>2]|0)+Ga|0;c[o>>2]=Ca;if(Ca>>>0>>0){sa=Ca}else{Ha=Ca;break}}do{if((s|0)==199){if((Ga|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);Ia=c[o>>2]|0;s=204;break o}else{c[Da>>2]=1;Ha=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[va>>2];if((Ha|0)!=0){Ja=Ha;s=203}else{Ka=Ea;s=206}}else{Ka=Ea;s=206}}else{s=205}}else{Ja=Fa;s=203}}while(0);if((s|0)==203){Fa=Ja+ -1|0;c[o>>2]=Fa;c[f>>2]=(c[f>>2]|0)+1;Ia=Fa;s=204}if((s|0)==204){if((Ia|0)==0){s=205}else{La=Ia}}if((s|0)==205){Ka=b+76|0;s=206}if((s|0)==206){if((c[Ka>>2]|0)!=0){break}Fa=b+40|0;if((c[Fa>>2]|0)!=0){break}Da=b+24|0;sa=c[Da>>2]|0;xa=c[g>>2]|0;c[o>>2]=0;Aa=b+4|0;Ba=0;while(1){Ma=Za(c[Aa>>2]|0,sa+Ba|0,xa-Ba|0)|0;if((Ma|0)<1){s=211;break}Ca=(c[o>>2]|0)+Ma|0;c[o>>2]=Ca;if(Ca>>>0>>0){Ba=Ca}else{Na=Ca;break}}do{if((s|0)==211){if((Ma|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break n}else{c[Fa>>2]=1;Na=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[Da>>2];if((Na|0)==0){break}else{La=Na}}c[o>>2]=La+ -1;c[f>>2]=(c[f>>2]|0)+1}}while(0);Hf(f)|0;c[b+132>>2]=gf(0,0,0)|0;c[b+52>>2]=2;c[b+56>>2]=0;p=0;i=e;return p|0}vf(b,-3,21400);p=-1;i=e;return p|0}vf(b,-3,21368);p=-1;i=e;return p|0}La=b+28|0;a[c[La>>2]|0]=31;c[b+36>>2]=1;Oa=La;Pa=c[o>>2]|0}else{Oa=b+28|0;Pa=v}c[b+48>>2]=c[b+12>>2];v=c[Oa>>2]|0;c[b+32>>2]=v;if((Pa|0)!=0){Oa=b+36|0;Kg(v+(c[Oa>>2]|0)|0,c[f>>2]|0,Pa|0)|0;c[Oa>>2]=(c[Oa>>2]|0)+(c[o>>2]|0);c[o>>2]=0}c[b+52>>2]=1;c[b+56>>2]=1;p=0;i=e;return p|0}function Af(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}if((c[a>>2]|0)!=7247){d=-2;i=b;return d|0}if((c[a+16>>2]|0)!=0){Mf(a+84|0)|0;hg(c[a+28>>2]|0);hg(c[a+24>>2]|0)}vf(a,0,0);hg(c[a+8>>2]|0);e=ib(c[a+4>>2]|0)|0;hg(a);d=((e|0)!=0)<<31>>31;i=b;return d|0}function Bf(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0;e=i;f=a+84|0;g=a+88|0;h=c[g>>2]|0;a:do{if((h|0)==0){j=a+76|0;if((c[j>>2]|0)==0){k=a+40|0;if((c[k>>2]|0)==0){l=a+24|0;m=c[l>>2]|0;n=c[a+16>>2]|0;c[g>>2]=0;o=a+4|0;p=0;while(1){q=Za(c[o>>2]|0,m+p|0,n-p|0)|0;if((q|0)<1){r=7;break}s=(c[g>>2]|0)+q|0;c[g>>2]=s;if(s>>>0>>0){p=s}else{t=s;break}}do{if((r|0)==7){if((q|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);u=-1;v=c[g>>2]|0;r=12;break a}else{c[k>>2]=1;t=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[l>>2];if((t|0)!=0){w=t;r=11}else{x=j;y=-1;r=14}}else{x=j;y=-1;r=14}}else{z=-1;r=13}}else{w=h;r=11}}while(0);if((r|0)==11){h=w+ -1|0;c[g>>2]=h;w=c[f>>2]|0;c[f>>2]=w+1;u=d[w]|0;v=h;r=12}if((r|0)==12){if((v|0)==0){z=u;r=13}else{A=u;B=v;r=25}}if((r|0)==13){x=a+76|0;y=z;r=14}b:do{if((r|0)==14){if((c[x>>2]|0)!=0){C=y+ -256|0;r=27;break}z=a+40|0;if((c[z>>2]|0)==0){v=a+24|0;u=c[v>>2]|0;h=c[a+16>>2]|0;c[g>>2]=0;w=a+4|0;t=0;while(1){D=Za(c[w>>2]|0,u+t|0,h-t|0)|0;if((D|0)<1){r=20;break}q=(c[g>>2]|0)+D|0;c[g>>2]=q;if(q>>>0>>0){t=q}else{E=q;break}}do{if((r|0)==20){if((D|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);F=y;G=-256;H=c[g>>2]|0;r=26;break b}else{c[z>>2]=1;E=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[v>>2];if((E|0)!=0){A=y;B=E;r=25;break}}I=x;J=y+ -256|0;r=28}}while(0);if((r|0)==25){y=B+ -1|0;c[g>>2]=y;B=c[f>>2]|0;c[f>>2]=B+1;F=A;G=(d[B]|0)<<8;H=y;r=26}if((r|0)==26){y=G+F|0;if((H|0)==0){C=y;r=27}else{K=H;L=y;r=39}}if((r|0)==27){I=a+76|0;J=C;r=28}c:do{if((r|0)==28){if((c[I>>2]|0)!=0){M=J+ -65536|0;r=41;break}C=a+40|0;if((c[C>>2]|0)==0){y=a+24|0;H=c[y>>2]|0;F=c[a+16>>2]|0;c[g>>2]=0;G=a+4|0;B=0;while(1){N=Za(c[G>>2]|0,H+B|0,F-B|0)|0;if((N|0)<1){r=34;break}A=(c[g>>2]|0)+N|0;c[g>>2]=A;if(A>>>0>>0){B=A}else{O=A;break}}do{if((r|0)==34){if((N|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);P=J;Q=-65536;R=c[g>>2]|0;r=40;break c}else{c[C>>2]=1;O=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[y>>2];if((O|0)!=0){K=O;L=J;r=39;break}}S=I;T=J+ -65536|0;r=42}}while(0);if((r|0)==39){J=K+ -1|0;c[g>>2]=J;K=c[f>>2]|0;c[f>>2]=K+1;P=L;Q=(d[K]|0)<<16;R=J;r=40}if((r|0)==40){J=Q+P|0;if((R|0)==0){M=J;r=41}else{U=R;V=J}}if((r|0)==41){S=a+76|0;T=M;r=42}if((r|0)==42){if((c[S>>2]|0)!=0){W=-1;i=e;return W|0}S=a+40|0;if((c[S>>2]|0)!=0){W=-1;i=e;return W|0}M=a+24|0;J=c[M>>2]|0;R=c[a+16>>2]|0;c[g>>2]=0;P=a+4|0;Q=0;while(1){X=Za(c[P>>2]|0,J+Q|0,R-Q|0)|0;if((X|0)<1){r=47;break}K=(c[g>>2]|0)+X|0;c[g>>2]=K;if(K>>>0>>0){Q=K}else{Y=K;break}}do{if((r|0)==47){if((X|0)>=0){c[S>>2]=1;Y=c[g>>2]|0;break}vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);W=-1;i=e;return W|0}}while(0);c[a+84>>2]=c[M>>2];if((Y|0)==0){W=-1;i=e;return W|0}else{U=Y;V=T}}c[g>>2]=U+ -1;U=c[f>>2]|0;c[f>>2]=U+1;c[b>>2]=((d[U]|0)<<24)+V;W=0;i=e;return W|0}function Cf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=i;if((a|0)==0){f=0;i=e;return f|0}g=a+84|0;if((c[a>>2]|0)!=31153){f=0;i=e;return f|0}if((c[a+76>>2]|0)!=0){f=0;i=e;return f|0}if((d|0)<0){vf(a,-5,21568);f=0;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}h=a+16|0;if((c[h>>2]|0)==0?(Df(a)|0)==-1:0){f=0;i=e;return f|0}j=a+72|0;a:do{if((c[j>>2]|0)!=0){c[j>>2]=0;k=c[a+68>>2]|0;l=a+88|0;if((c[l>>2]|0)!=0?(Ef(a,0)|0)==-1:0){f=0;i=e;return f|0}if((k|0)!=0){m=a+24|0;n=a+12|0;o=k;k=0;while(1){p=c[h>>2]|0;q=(p|0)<0|(p|0)>(o|0)?o:p;if(!k){Eg(c[m>>2]|0,0,q|0)|0}c[l>>2]=q;c[g>>2]=c[m>>2];c[n>>2]=(c[n>>2]|0)+q;if((Ef(a,0)|0)==-1){f=0;break}if((o|0)==(q|0)){break a}o=o-q|0;k=1}i=e;return f|0}}}while(0);j=a+88|0;b:do{if(!((c[h>>2]|0)>>>0>d>>>0)){if((c[j>>2]|0)!=0?(Ef(a,0)|0)==-1:0){f=0;i=e;return f|0}c[j>>2]=d;c[g>>2]=b;k=a+12|0;c[k>>2]=(c[k>>2]|0)+d;if((Ef(a,0)|0)==-1){f=0;i=e;return f|0}}else{k=a+24|0;o=a+12|0;n=b;m=d;while(1){l=c[j>>2]|0;if((l|0)==0){q=c[k>>2]|0;c[g>>2]=q;r=q}else{r=c[g>>2]|0}q=(c[h>>2]|0)-l|0;p=q>>>0>m>>>0?m:q;Kg(r+l|0,n|0,p|0)|0;c[j>>2]=(c[j>>2]|0)+p;c[o>>2]=(c[o>>2]|0)+p;if((m|0)==(p|0)){break b}if((Ef(a,0)|0)==-1){f=0;break}n=n+p|0;m=m-p|0}i=e;return f|0}}while(0);f=d;i=e;return f|0}function Df(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;b=i;d=a+20|0;e=c[d>>2]|0;f=gg(e)|0;g=a+24|0;c[g>>2]=f;h=gg(e)|0;e=a+28|0;c[e>>2]=h;j=(h|0)==0;if(!((f|0)==0|j)){c[a+116>>2]=0;c[a+120>>2]=0;c[a+124>>2]=0;if((hf(a+84|0,c[a+60>>2]|0,8,31,8,c[a+64>>2]|0,21664,56)|0)==0){k=c[d>>2]|0;c[a+16>>2]=k;c[a+100>>2]=k;k=c[e>>2]|0;c[a+96>>2]=k;c[a+32>>2]=k;l=0;i=b;return l|0}else{hg(c[g>>2]|0);vf(a,-4,21648);l=-1;i=b;return l|0}}if(j){m=f}else{hg(h);m=c[g>>2]|0}if((m|0)!=0){hg(m)}vf(a,-4,21648);l=-1;i=b;return l|0}function Ef(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;d=i;e=a+84|0;f=a+16|0;if((c[f>>2]|0)==0?(Df(a)|0)==-1:0){g=-1;i=d;return g|0}h=a+100|0;j=a+96|0;k=a+32|0;l=a+28|0;m=a+4|0;a:do{if((b|0)==4){n=c[h>>2]|0;o=0;while(1){if((n|0)==0|(o|0)==1){p=c[j>>2]|0;q=c[k>>2]|0;r=p-q|0;if((p|0)==(q|0)){s=n}else{p=Qa(c[m>>2]|0,q|0,r|0)|0;if(!((p|0)>-1&(p|0)==(r|0))){t=30;break a}s=c[h>>2]|0}if((s|0)==0){r=c[f>>2]|0;c[h>>2]=r;p=c[l>>2]|0;c[j>>2]=p;u=p;v=r}else{u=c[j>>2]|0;v=s}c[k>>2]=u;w=v}else{w=n}r=lf(e,4)|0;if((r|0)==-2){t=36;break a}p=c[h>>2]|0;if((w|0)==(p|0)){t=38;break}else{n=p;o=r}}}else if((b|0)==0){o=c[h>>2]|0;while(1){if((o|0)==0){n=c[j>>2]|0;r=c[k>>2]|0;p=n-r|0;if((n|0)!=(r|0)){n=Qa(c[m>>2]|0,r|0,p|0)|0;if(!((n|0)>-1&(n|0)==(p|0))){t=30;break a}p=c[h>>2]|0;if((p|0)!=0){x=c[j>>2]|0;y=p}else{t=10}}else{t=10}if((t|0)==10){t=0;p=c[f>>2]|0;c[h>>2]=p;n=c[l>>2]|0;c[j>>2]=n;x=n;y=p}c[k>>2]=x;z=y}else{z=o}if((lf(e,0)|0)==-2){t=36;break a}p=c[h>>2]|0;if((z|0)==(p|0)){t=38;break}else{o=p}}}else{o=c[h>>2]|0;while(1){if((o|0)!=0&(b|0)==0){A=o}else{p=c[j>>2]|0;n=c[k>>2]|0;r=p-n|0;if((p|0)==(n|0)){B=o}else{p=Qa(c[m>>2]|0,n|0,r|0)|0;if(!((p|0)>-1&(p|0)==(r|0))){t=30;break a}B=c[h>>2]|0}if((B|0)==0){r=c[f>>2]|0;c[h>>2]=r;p=c[l>>2]|0;c[j>>2]=p;C=p;D=r}else{C=c[j>>2]|0;D=B}c[k>>2]=C;A=D}if((lf(e,b)|0)==-2){t=36;break a}r=c[h>>2]|0;if((A|0)==(r|0)){t=38;break}else{o=r}}}}while(0);if((t|0)==30){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);g=-1;i=d;return g|0}else if((t|0)==36){vf(a,-2,21608);g=-1;i=d;return g|0}else if((t|0)==38){if((b|0)!=4){g=0;i=d;return g|0}kf(e)|0;g=0;i=d;return g|0}return 0}function Ff(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}if((c[a>>2]|0)!=31153){d=-2;i=b;return d|0}e=a+72|0;a:do{if((c[e>>2]|0)!=0){c[e>>2]=0;f=c[a+68>>2]|0;g=a+88|0;if((c[g>>2]|0)!=0?(Ef(a,0)|0)==-1:0){h=-1;break}if((f|0)!=0){j=a+16|0;k=a+24|0;l=a+84|0;m=a+12|0;n=f;f=0;while(1){o=c[j>>2]|0;p=(o|0)<0|(o|0)>(n|0)?n:o;if(!f){Eg(c[k>>2]|0,0,p|0)|0}c[g>>2]=p;c[l>>2]=c[k>>2];c[m>>2]=(c[m>>2]|0)+p;if((Ef(a,0)|0)==-1){h=-1;break a}if((n|0)==(p|0)){h=0;break}else{n=n-p|0;f=1}}}else{h=0}}else{h=0}}while(0);e=(Ef(a,4)|0)+h|0;jf(a+84|0)|0;hg(c[a+28>>2]|0);hg(c[a+24>>2]|0);vf(a,0,0);hg(c[a+8>>2]|0);h=ib(c[a+4>>2]|0)|0;hg(a);d=((e|0)!=(0-h|0))<<31>>31;i=b;return d|0}function Gf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0;g=i;h=c[e+28>>2]|0;j=c[e>>2]|0;k=e+4|0;l=j+((c[k>>2]|0)+ -6)|0;m=e+12|0;n=c[m>>2]|0;o=e+16|0;p=c[o>>2]|0;q=n+(p+ -258)|0;r=c[h+44>>2]|0;s=c[h+48>>2]|0;t=c[h+52>>2]|0;u=h+56|0;v=h+60|0;w=c[h+76>>2]|0;x=c[h+80>>2]|0;y=(1<>2])+ -1|0;z=(1<>2])+ -1|0;A=n+(p+~f)|0;f=h+7104|0;p=t+ -1|0;B=(s|0)==0;C=(c[h+40>>2]|0)+ -1|0;D=C+s|0;E=s+ -1|0;F=A+ -1|0;G=A-s|0;H=c[v>>2]|0;I=c[u>>2]|0;J=j+ -1|0;j=n+ -1|0;a:while(1){if(H>>>0<15){n=J+2|0;K=H+16|0;L=((d[J+1|0]|0)<>1]|0;P=d[w+(n<<2)+1|0]|0;n=L>>>P;Q=K-P|0;do{if(!(N<<24>>24==0)){R=N&255;S=Q;T=n;P=O;while(1){if((R&16|0)!=0){break}if((R&64|0)!=0){U=55;break a}V=(T&(1<>1]|0;Y=d[w+(V<<2)+1|0]|0;Z=T>>>Y;_=S-Y|0;if(W<<24>>24==0){U=6;break}else{R=W&255;S=_;T=Z;P=X}}if((U|0)==6){U=0;$=Z;aa=_;ba=X&255;U=7;break}W=P&65535;Y=R&15;if((Y|0)==0){ca=S;da=T;ea=M;fa=W}else{if(S>>>0>>0){V=M+1|0;ga=S+8|0;ha=((d[V]|0)<>>Y;ea=ia;fa=(ha&(1<>>0<15){W=ea+2|0;ja=ca+16|0;ka=((d[ea+1|0]|0)<>1]|0;V=d[x+(W<<2)+1|0]|0;ma=ka>>>V;na=ja-V|0;V=d[x+(W<<2)|0]|0;if((V&16|0)==0){W=V;oa=ma;pa=na;qa=Y;while(1){if((W&64|0)!=0){U=52;break a}ra=(oa&(1<>1]|0;ta=d[x+(ra<<2)+1|0]|0;ua=oa>>>ta;va=pa-ta|0;ta=d[x+(ra<<2)|0]|0;if((ta&16|0)==0){W=ta;oa=ua;pa=va;qa=sa}else{wa=ua;xa=va;ya=ta;za=sa;break}}}else{wa=ma;xa=na;ya=V;za=Y}qa=za&65535;W=ya&15;if(xa>>>0>>0){P=la+1|0;sa=((d[P]|0)<>>0>>0){va=la+2|0;Aa=xa+16|0;Ba=((d[va]|0)<>>W;Ea=Aa-W|0;W=j;qa=W-A|0;if(!(P>>>0>qa>>>0)){sa=j+(0-P)|0;ta=fa;va=j;while(1){a[va+1|0]=a[sa+1|0]|0;a[va+2|0]=a[sa+2|0]|0;ua=sa+3|0;Fa=va+3|0;a[Fa]=a[ua]|0;ta=ta+ -3|0;if(!(ta>>>0>2)){break}else{sa=ua;va=Fa}}if((ta|0)==0){Ga=Ea;Ha=Da;Ia=Ca;Ja=Fa;break}Y=va+4|0;a[Y]=a[sa+4|0]|0;if(!(ta>>>0>1)){Ga=Ea;Ha=Da;Ia=Ca;Ja=Y;break}Y=va+5|0;a[Y]=a[sa+5|0]|0;Ga=Ea;Ha=Da;Ia=Ca;Ja=Y;break}Y=P-qa|0;if(Y>>>0>r>>>0?(c[f>>2]|0)!=0:0){U=22;break a}do{if(B){V=t+(C-Y)|0;if(Y>>>0>>0){na=fa-Y|0;ma=P-W|0;ua=V;ra=Y;Ka=j;do{ua=ua+1|0;Ka=Ka+1|0;a[Ka]=a[ua]|0;ra=ra+ -1|0}while((ra|0)!=0);La=j+(F+ma+(1-P))|0;Ma=na;Na=j+(A+ma)|0}else{La=V;Ma=fa;Na=j}}else{if(!(s>>>0>>0)){ra=t+(E-Y)|0;if(!(Y>>>0>>0)){La=ra;Ma=fa;Na=j;break}ua=fa-Y|0;Ka=P-W|0;Oa=ra;ra=Y;Pa=j;do{Oa=Oa+1|0;Pa=Pa+1|0;a[Pa]=a[Oa]|0;ra=ra+ -1|0}while((ra|0)!=0);La=j+(F+Ka+(1-P))|0;Ma=ua;Na=j+(A+Ka)|0;break}ra=t+(D-Y)|0;Oa=Y-s|0;if(Oa>>>0>>0){Pa=fa-Oa|0;V=P-W|0;ma=ra;na=Oa;Oa=j;do{ma=ma+1|0;Oa=Oa+1|0;a[Oa]=a[ma]|0;na=na+ -1|0}while((na|0)!=0);na=j+(G+V)|0;if(s>>>0>>0){ma=Pa-s|0;Oa=p;Ka=s;ua=na;do{Oa=Oa+1|0;ua=ua+1|0;a[ua]=a[Oa]|0;Ka=Ka+ -1|0}while((Ka|0)!=0);La=j+(F+V+(1-P))|0;Ma=ma;Na=j+(A+V)|0}else{La=p;Ma=Pa;Na=na}}else{La=ra;Ma=fa;Na=j}}}while(0);if(Ma>>>0>2){P=La;W=Ma;Y=Na;while(1){a[Y+1|0]=a[P+1|0]|0;a[Y+2|0]=a[P+2|0]|0;qa=P+3|0;sa=Y+3|0;a[sa]=a[qa]|0;va=W+ -3|0;if(va>>>0>2){P=qa;W=va;Y=sa}else{Qa=qa;Ra=va;Sa=sa;break}}}else{Qa=La;Ra=Ma;Sa=Na}if((Ra|0)!=0){Y=Sa+1|0;a[Y]=a[Qa+1|0]|0;if(Ra>>>0>1){W=Sa+2|0;a[W]=a[Qa+2|0]|0;Ga=Ea;Ha=Da;Ia=Ca;Ja=W}else{Ga=Ea;Ha=Da;Ia=Ca;Ja=Y}}else{Ga=Ea;Ha=Da;Ia=Ca;Ja=Sa}}else{$=n;aa=Q;ba=O&255;U=7}}while(0);if((U|0)==7){U=0;O=j+1|0;a[O]=ba;Ga=aa;Ha=$;Ia=M;Ja=O}if(Ia>>>0>>0&Ja>>>0>>0){H=Ga;I=Ha;J=Ia;j=Ja}else{Ta=Ga;Ua=Ha;Va=Ia;Wa=Ja;break}}do{if((U|0)==22){c[e+24>>2]=21672;c[h>>2]=29;Ta=Ea;Ua=Da;Va=Ca;Wa=j}else if((U|0)==52){c[e+24>>2]=21704;c[h>>2]=29;Ta=pa;Ua=oa;Va=la;Wa=j}else if((U|0)==55){if((R&32|0)==0){c[e+24>>2]=21728;c[h>>2]=29;Ta=S;Ua=T;Va=M;Wa=j;break}else{c[h>>2]=11;Ta=S;Ua=T;Va=M;Wa=j;break}}}while(0);j=Ta>>>3;M=Va+(0-j)|0;T=Ta-(j<<3)|0;Ta=(1<>2]=Va+(1-j);c[m>>2]=Wa+1;if(M>>>0>>0){Xa=l-M|0}else{Xa=l-M|0}c[k>>2]=Xa+5;if(Wa>>>0>>0){Ya=q-Wa|0;Za=Ya+257|0;c[o>>2]=Za;c[u>>2]=Ta;c[v>>2]=T;i=g;return}else{Ya=q-Wa|0;Za=Ya+257|0;c[o>>2]=Za;c[u>>2]=Ta;c[v>>2]=T;i=g;return}}function Hf(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=c[a+28>>2]|0;if((e|0)==0){d=-2;i=b;return d|0}c[e+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[e>>2]=0;c[e+4>>2]=0;c[e+12>>2]=0;c[e+20>>2]=32768;c[e+32>>2]=0;c[e+40>>2]=0;c[e+44>>2]=0;c[e+48>>2]=0;c[e+56>>2]=0;c[e+60>>2]=0;a=e+1328|0;c[e+108>>2]=a;c[e+80>>2]=a;c[e+76>>2]=a;c[e+7104>>2]=1;c[e+7108>>2]=-1;d=0;i=b;return d|0}function If(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;if((a|0)==0){e=-2;i=d;return e|0}f=a+28|0;g=c[f>>2]|0;if((g|0)==0){e=-2;i=d;return e|0}if((b|0)<0){h=0-b|0;j=0}else{h=(b|0)<48?b&15:b;j=(b>>4)+1|0}if((h|0)!=0&(h+ -8|0)>>>0>7){e=-2;i=d;return e|0}b=g+52|0;k=c[b>>2]|0;l=g+36|0;if((k|0)!=0?(c[l>>2]|0)!=(h|0):0){mb[c[a+36>>2]&1](c[a+40>>2]|0,k);c[b>>2]=0}c[g+8>>2]=j;c[l>>2]=h;h=c[f>>2]|0;if((h|0)==0){e=-2;i=d;return e|0}c[h+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[h>>2]=0;c[h+4>>2]=0;c[h+12>>2]=0;c[h+20>>2]=32768;c[h+32>>2]=0;c[h+40>>2]=0;c[h+44>>2]=0;c[h+48>>2]=0;c[h+56>>2]=0;c[h+60>>2]=0;a=h+1328|0;c[h+108>>2]=a;c[h+80>>2]=a;c[h+76>>2]=a;c[h+7104>>2]=1;c[h+7108>>2]=-1;e=0;i=d;return e|0}function Jf(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0;g=i;if((e|0)==0){h=-6;i=g;return h|0}if(!((a[e]|0)==49&(f|0)==56)){h=-6;i=g;return h|0}if((b|0)==0){h=-2;i=g;return h|0}c[b+24>>2]=0;f=b+32|0;e=c[f>>2]|0;if((e|0)==0){c[f>>2]=1;c[b+40>>2]=0;j=1}else{j=e}e=b+36|0;if((c[e>>2]|0)==0){c[e>>2]=1}f=b+40|0;k=kb[j&1](c[f>>2]|0,1,7116)|0;if((k|0)==0){h=-4;i=g;return h|0}j=b+28|0;c[j>>2]=k;c[k+52>>2]=0;l=If(b,d)|0;if((l|0)==0){h=0;i=g;return h|0}mb[c[e>>2]&1](c[f>>2]|0,k);c[j>>2]=0;h=l;i=g;return h|0}function Kf(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,fb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0,sc=0,tc=0,uc=0,vc=0,wc=0,xc=0,yc=0,zc=0,Ac=0,Bc=0,Cc=0,Dc=0,Ec=0,Fc=0,Gc=0,Hc=0,Ic=0,Jc=0,Kc=0,Lc=0,Mc=0,Nc=0,Oc=0,Pc=0,Qc=0,Rc=0,Sc=0,Tc=0,Uc=0,Vc=0,Wc=0,Xc=0,Yc=0,Zc=0,_c=0,$c=0,ad=0,bd=0,cd=0,dd=0,ed=0,fd=0,gd=0,hd=0,id=0,jd=0,kd=0,ld=0,md=0,nd=0,od=0,pd=0,qd=0,rd=0,sd=0,td=0,ud=0,vd=0,wd=0,xd=0,yd=0,zd=0,Ad=0,Bd=0,Cd=0,Dd=0,Ed=0,Fd=0,Gd=0,Hd=0,Id=0,Jd=0,Kd=0,Ld=0,Md=0,Nd=0,Od=0,Pd=0,Qd=0,Rd=0,Sd=0,Td=0,Ud=0,Vd=0,Wd=0,Xd=0,Yd=0,Zd=0,_d=0,$d=0,ae=0,be=0,ce=0,de=0,ee=0,fe=0,ge=0,he=0,ie=0,je=0,ke=0,le=0,me=0,ne=0,oe=0,pe=0,qe=0,re=0,se=0,te=0,ue=0,ve=0,we=0,xe=0,ye=0,ze=0,Ae=0,Be=0,Ce=0,De=0,Ee=0,Fe=0,Ge=0,He=0,Ie=0,Je=0,Ke=0,Le=0,Me=0,Ne=0,Oe=0,Pe=0,Qe=0,Re=0,Se=0,Te=0,Ue=0,Ve=0,We=0,Xe=0,Ye=0,Ze=0,_e=0,$e=0,af=0,bf=0,cf=0,df=0,ef=0,hf=0,jf=0,kf=0,lf=0,mf=0,nf=0,of=0,pf=0,qf=0,rf=0,sf=0,tf=0,uf=0,vf=0,wf=0,xf=0,yf=0,zf=0,Af=0,Bf=0,Cf=0,Df=0,Ef=0,Ff=0,Hf=0,If=0,Jf=0,Kf=0,Mf=0,Of=0,Pf=0,Qf=0,Rf=0,Sf=0,Tf=0,Uf=0,Vf=0,Wf=0,Xf=0,Yf=0,Zf=0,_f=0,$f=0,ag=0,bg=0,cg=0,dg=0,eg=0,fg=0,gg=0,hg=0,ig=0,jg=0,kg=0,lg=0,mg=0,ng=0,og=0,pg=0,qg=0,rg=0,sg=0,tg=0,ug=0,vg=0,wg=0,xg=0,yg=0,zg=0,Ag=0,Bg=0,Cg=0,Dg=0,Eg=0,Fg=0,Gg=0,Hg=0,Ig=0,Jg=0;h=i;i=i+16|0;j=h;if((f|0)==0){k=-2;i=h;return k|0}l=c[f+28>>2]|0;if((l|0)==0){k=-2;i=h;return k|0}m=f+12|0;n=c[m>>2]|0;if((n|0)==0){k=-2;i=h;return k|0}o=c[f>>2]|0;if((o|0)==0?(c[f+4>>2]|0)!=0:0){k=-2;i=h;return k|0}p=c[l>>2]|0;if((p|0)==11){c[l>>2]=12;q=12;r=c[f>>2]|0;s=c[m>>2]|0}else{q=p;r=o;s=n}n=f+16|0;o=c[n>>2]|0;p=f+4|0;t=c[p>>2]|0;u=l+56|0;v=l+60|0;w=l+8|0;x=l+24|0;y=j+1|0;z=l+16|0;A=l+32|0;B=f+24|0;C=l+36|0;D=l+20|0;E=f+48|0;F=l+64|0;G=l+12|0;H=(g+ -5|0)>>>0<2;I=l+4|0;J=l+76|0;K=l+84|0;L=l+80|0;M=l+88|0;N=(g|0)==6;O=l+7108|0;P=l+72|0;Q=l+7112|0;R=l+68|0;S=l+44|0;T=l+7104|0;U=l+48|0;V=l+52|0;W=l+40|0;X=f+20|0;Y=l+28|0;Z=l+96|0;_=l+100|0;$=l+92|0;aa=l+104|0;ba=l+1328|0;ca=l+108|0;da=l+112|0;ea=l+752|0;fa=l+624|0;ga=j+2|0;ha=j+3|0;ia=q;q=c[v>>2]|0;ja=t;ka=c[u>>2]|0;la=o;ma=r;r=o;o=s;s=0;a:while(1){b:do{switch(ia|0){case 28:{na=q;oa=ja;pa=ka;qa=la;ra=ma;sa=1;ta=285;break a;break};case 16:{if(q>>>0<14){ua=q;va=ja;wa=ka;xa=ma;while(1){if((va|0)==0){ya=ua;za=0;Aa=wa;Ba=la;Ca=xa;Da=r;Ea=s;break a}Ga=va+ -1|0;Ha=xa+1|0;Ia=(d[xa]<>>0<14){ua=Ja;va=Ga;wa=Ia;xa=Ha}else{Ka=Ja;La=Ga;Ma=Ia;Na=Ha;break}}}else{Ka=q;La=ja;Ma=ka;Na=ma}xa=(Ma&31)+257|0;c[Z>>2]=xa;wa=(Ma>>>5&31)+1|0;c[_>>2]=wa;c[$>>2]=(Ma>>>10&15)+4;va=Ma>>>14;ua=Ka+ -14|0;if(xa>>>0>286|wa>>>0>30){c[B>>2]=21992;c[l>>2]=29;Oa=ua;Pa=La;Qa=va;Ra=la;Sa=Na;Ta=r;Ua=o;Va=s;break b}else{c[aa>>2]=0;c[l>>2]=17;Wa=0;Xa=ua;Ya=La;Za=va;_a=Na;ta=154;break b}break};case 21:{$a=c[P>>2]|0;ab=q;bb=ja;cb=ka;db=ma;eb=s;ta=221;break};case 23:{fb=c[P>>2]|0;gb=q;hb=ja;ib=ka;jb=ma;kb=s;ta=240;break};case 1:{if(q>>>0<16){va=q;ua=ja;wa=ka;xa=ma;while(1){if((ua|0)==0){ya=va;za=0;Aa=wa;Ba=la;Ca=xa;Da=r;Ea=s;break a}Ha=ua+ -1|0;Ia=xa+1|0;Ga=(d[xa]<>>0<16){va=Ja;ua=Ha;wa=Ga;xa=Ia}else{lb=Ja;mb=Ha;nb=Ga;ob=Ia;break}}}else{lb=q;mb=ja;nb=ka;ob=ma}c[z>>2]=nb;if((nb&255|0)!=8){c[B>>2]=21824;c[l>>2]=29;Oa=lb;Pa=mb;Qa=nb;Ra=la;Sa=ob;Ta=r;Ua=o;Va=s;break b}if((nb&57344|0)!=0){c[B>>2]=21880;c[l>>2]=29;Oa=lb;Pa=mb;Qa=nb;Ra=la;Sa=ob;Ta=r;Ua=o;Va=s;break b}xa=c[A>>2]|0;if((xa|0)==0){pb=nb}else{c[xa>>2]=nb>>>8&1;pb=c[z>>2]|0}if((pb&512|0)!=0){a[j]=nb;a[y]=nb>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0}c[l>>2]=2;qb=0;rb=mb;sb=0;tb=ob;ta=47;break};case 22:{ub=q;vb=ja;wb=ka;xb=ma;yb=s;ta=228;break};case 10:{zb=q;Ab=ja;Bb=ka;Cb=ma;ta=121;break};case 7:{Db=q;Eb=ja;Fb=ka;Gb=ma;ta=96;break};case 5:{Hb=q;Ib=ja;Jb=ka;Kb=ma;ta=73;break};case 8:{Lb=q;Mb=ja;Nb=ka;Ob=ma;ta=109;break};case 11:{Pb=q;Qb=ja;Rb=ka;Sb=ma;ta=124;break};case 12:{Tb=q;Ub=ja;Vb=ka;Wb=ma;ta=125;break};case 13:{xa=q&7;wa=ka>>>xa;ua=q-xa|0;if(ua>>>0<32){xa=ua;va=ja;Ia=wa;Ga=ma;while(1){if((va|0)==0){ya=xa;za=0;Aa=Ia;Ba=la;Ca=Ga;Da=r;Ea=s;break a}Ha=va+ -1|0;Ja=Ga+1|0;Xb=(d[Ga]<>>0<32){xa=Yb;va=Ha;Ia=Xb;Ga=Ja}else{Zb=Yb;_b=Ha;$b=Xb;ac=Ja;break}}}else{Zb=ua;_b=ja;$b=wa;ac=ma}Ga=$b&65535;if((Ga|0)==($b>>>16^65535|0)){c[F>>2]=Ga;c[l>>2]=14;if(N){na=0;oa=_b;pa=0;qa=la;ra=ac;sa=s;ta=285;break a}else{bc=0;cc=_b;dc=0;ec=ac;ta=143;break b}}else{c[B>>2]=21960;c[l>>2]=29;Oa=Zb;Pa=_b;Qa=$b;Ra=la;Sa=ac;Ta=r;Ua=o;Va=s;break b}break};case 14:{bc=q;cc=ja;dc=ka;ec=ma;ta=143;break};case 15:{fc=q;gc=ja;hc=ka;ic=ma;ta=144;break};case 17:{Ga=c[aa>>2]|0;if(Ga>>>0<(c[$>>2]|0)>>>0){Wa=Ga;Xa=q;Ya=ja;Za=ka;_a=ma;ta=154}else{jc=Ga;kc=q;lc=ja;mc=ka;nc=ma;ta=158}break};case 0:{Ga=c[w>>2]|0;if((Ga|0)==0){c[l>>2]=12;Oa=q;Pa=ja;Qa=ka;Ra=la;Sa=ma;Ta=r;Ua=o;Va=s;break b}if(q>>>0<16){Ia=q;va=ja;xa=ka;Ja=ma;while(1){if((va|0)==0){ya=Ia;za=0;Aa=xa;Ba=la;Ca=Ja;Da=r;Ea=s;break a}Xb=va+ -1|0;Ha=Ja+1|0;Yb=(d[Ja]<>>0<16){Ia=oc;va=Xb;xa=Yb;Ja=Ha}else{pc=oc;qc=Xb;rc=Yb;sc=Ha;break}}}else{pc=q;qc=ja;rc=ka;sc=ma}if((Ga&2|0)!=0&(rc|0)==35615){c[x>>2]=gf(0,0,0)|0;a[j]=31;a[y]=-117;c[x>>2]=gf(c[x>>2]|0,j,2)|0;c[l>>2]=1;Oa=0;Pa=qc;Qa=0;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}c[z>>2]=0;Ja=c[A>>2]|0;if((Ja|0)==0){tc=Ga}else{c[Ja+48>>2]=-1;tc=c[w>>2]|0}if((tc&1|0)!=0?((((rc<<8&65280)+(rc>>>8)|0)>>>0)%31|0|0)==0:0){if((rc&15|0)!=8){c[B>>2]=21824;c[l>>2]=29;Oa=pc;Pa=qc;Qa=rc;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}Ja=rc>>>4;xa=pc+ -4|0;va=(Ja&15)+8|0;Ia=c[C>>2]|0;if((Ia|0)!=0){if(va>>>0>Ia>>>0){c[B>>2]=21856;c[l>>2]=29;Oa=xa;Pa=qc;Qa=Ja;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}}else{c[C>>2]=va}c[D>>2]=1<>2]=va;c[E>>2]=va;c[l>>2]=rc>>>12&2^11;Oa=0;Pa=qc;Qa=0;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}c[B>>2]=21800;c[l>>2]=29;Oa=pc;Pa=qc;Qa=rc;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break};case 24:{uc=q;vc=ja;wc=ka;xc=ma;yc=s;ta=246;break};case 9:{if(q>>>0<32){va=q;Ja=ja;xa=ka;Ia=ma;while(1){if((Ja|0)==0){ya=va;za=0;Aa=xa;Ba=la;Ca=Ia;Da=r;Ea=s;break a}wa=Ja+ -1|0;ua=Ia+1|0;Ha=(d[Ia]<>>0<32){va=Yb;Ja=wa;xa=Ha;Ia=ua}else{zc=wa;Ac=Ha;Bc=ua;break}}}else{zc=ja;Ac=ka;Bc=ma}Ia=Fa(Ac|0)|0;c[x>>2]=Ia;c[E>>2]=Ia;c[l>>2]=10;zb=0;Ab=zc;Bb=0;Cb=Bc;ta=121;break};case 30:{ta=299;break a;break};case 18:{Cc=c[aa>>2]|0;Dc=q;Ec=ja;Fc=ka;Gc=ma;Hc=s;ta=164;break};case 6:{Ic=q;Jc=ja;Kc=ka;Lc=ma;ta=83;break};case 29:{ya=q;za=ja;Aa=ka;Ba=la;Ca=ma;Da=r;Ea=-3;break a;break};case 19:{Mc=q;Nc=ja;Oc=ka;Pc=ma;Qc=s;ta=201;break};case 20:{Rc=q;Sc=ja;Tc=ka;Uc=ma;Vc=s;ta=202;break};case 25:{if((la|0)==0){na=q;oa=ja;pa=ka;qa=0;ra=ma;sa=s;ta=285;break a}a[o]=c[F>>2];c[l>>2]=20;Oa=q;Pa=ja;Qa=ka;Ra=la+ -1|0;Sa=ma;Ta=r;Ua=o+1|0;Va=s;break};case 26:{if((c[w>>2]|0)!=0){if(q>>>0<32){Ia=q;xa=ja;Ja=ka;va=ma;while(1){if((xa|0)==0){ya=Ia;za=0;Aa=Ja;Ba=la;Ca=va;Da=r;Ea=s;break a}Ga=xa+ -1|0;ua=va+1|0;Ha=(d[va]<>>0<32){Ia=wa;xa=Ga;Ja=Ha;va=ua}else{Wc=wa;Xc=Ga;Yc=Ha;Zc=ua;break}}}else{Wc=q;Xc=ja;Yc=ka;Zc=ma}va=r-la|0;c[X>>2]=(c[X>>2]|0)+va;c[Y>>2]=(c[Y>>2]|0)+va;if((r|0)!=(la|0)){Ja=c[x>>2]|0;xa=o+(0-va)|0;if((c[z>>2]|0)==0){_c=ff(Ja,xa,va)|0}else{_c=gf(Ja,xa,va)|0}c[x>>2]=_c;c[E>>2]=_c}if((c[z>>2]|0)==0){$c=Fa(Yc|0)|0}else{$c=Yc}if(($c|0)==(c[x>>2]|0)){ad=0;bd=Xc;cd=0;dd=Zc;ed=la}else{c[B>>2]=22280;c[l>>2]=29;Oa=Wc;Pa=Xc;Qa=Yc;Ra=la;Sa=Zc;Ta=la;Ua=o;Va=s;break b}}else{ad=q;bd=ja;cd=ka;dd=ma;ed=r}c[l>>2]=27;fd=ad;gd=bd;hd=cd;id=dd;jd=ed;ta=277;break};case 27:{fd=q;gd=ja;hd=ka;id=ma;jd=r;ta=277;break};case 2:{if(q>>>0<32){qb=q;rb=ja;sb=ka;tb=ma;ta=47}else{kd=ja;ld=ka;md=ma;ta=49}break};case 4:{nd=q;od=ja;pd=ka;qd=ma;ta=62;break};case 3:{if(q>>>0<16){rd=q;sd=ja;td=ka;ud=ma;ta=55}else{vd=ja;wd=ka;xd=ma;ta=57}break};default:{k=-2;ta=300;break a}}}while(0);if((ta|0)==47){while(1){ta=0;if((rb|0)==0){ya=qb;za=0;Aa=sb;Ba=la;Ca=tb;Da=r;Ea=s;break a}va=rb+ -1|0;xa=tb+1|0;Ja=(d[tb]<>>0<32){qb=Ia;rb=va;sb=Ja;tb=xa;ta=47}else{kd=va;ld=Ja;md=xa;ta=49;break}}}else if((ta|0)==121){ta=0;if((c[G>>2]|0)==0){ta=122;break}xa=ff(0,0,0)|0;c[x>>2]=xa;c[E>>2]=xa;c[l>>2]=11;Pb=zb;Qb=Ab;Rb=Bb;Sb=Cb;ta=124}else if((ta|0)==143){ta=0;c[l>>2]=15;fc=bc;gc=cc;hc=dc;ic=ec;ta=144}else if((ta|0)==154){while(1){ta=0;if(Xa>>>0<3){xa=Xa;Ja=Ya;va=Za;Ia=_a;while(1){if((Ja|0)==0){ya=xa;za=0;Aa=va;Ba=la;Ca=Ia;Da=r;Ea=s;break a}ua=Ja+ -1|0;Ha=Ia+1|0;Ga=(d[Ia]<>>0<3){xa=wa;Ja=ua;va=Ga;Ia=Ha}else{yd=wa;zd=ua;Ad=Ga;Bd=Ha;break}}}else{yd=Xa;zd=Ya;Ad=Za;Bd=_a}c[aa>>2]=Wa+1;b[l+(e[21760+(Wa<<1)>>1]<<1)+112>>1]=Ad&7;Ia=Ad>>>3;va=yd+ -3|0;Ja=c[aa>>2]|0;if(Ja>>>0<(c[$>>2]|0)>>>0){Wa=Ja;Xa=va;Ya=zd;Za=Ia;_a=Bd;ta=154}else{jc=Ja;kc=va;lc=zd;mc=Ia;nc=Bd;ta=158;break}}}else if((ta|0)==277){ta=0;if((c[w>>2]|0)==0){Cd=fd;Dd=gd;Ed=hd;Fd=id;ta=284;break}if((c[z>>2]|0)==0){Cd=fd;Dd=gd;Ed=hd;Fd=id;ta=284;break}if(fd>>>0<32){Ia=fd;va=gd;Ja=hd;xa=id;while(1){if((va|0)==0){ya=Ia;za=0;Aa=Ja;Ba=la;Ca=xa;Da=jd;Ea=s;break a}Ha=va+ -1|0;Ga=xa+1|0;ua=(d[xa]<>>0<32){Ia=wa;va=Ha;Ja=ua;xa=Ga}else{Gd=wa;Hd=Ha;Id=ua;Jd=Ga;break}}}else{Gd=fd;Hd=gd;Id=hd;Jd=id}if((Id|0)==(c[Y>>2]|0)){Cd=0;Dd=Hd;Ed=0;Fd=Jd;ta=284;break}c[B>>2]=22304;c[l>>2]=29;Oa=Gd;Pa=Hd;Qa=Id;Ra=la;Sa=Jd;Ta=jd;Ua=o;Va=s}do{if((ta|0)==49){ta=0;xa=c[A>>2]|0;if((xa|0)!=0){c[xa+4>>2]=ld}if((c[z>>2]&512|0)!=0){a[j]=ld;a[y]=ld>>>8;a[ga]=ld>>>16;a[ha]=ld>>>24;c[x>>2]=gf(c[x>>2]|0,j,4)|0}c[l>>2]=3;rd=0;sd=kd;td=0;ud=md;ta=55}else if((ta|0)==124){ta=0;if(H){na=Pb;oa=Qb;pa=Rb;qa=la;ra=Sb;sa=s;ta=285;break a}else{Tb=Pb;Ub=Qb;Vb=Rb;Wb=Sb;ta=125}}else if((ta|0)==144){ta=0;xa=c[F>>2]|0;if((xa|0)==0){c[l>>2]=11;Oa=fc;Pa=gc;Qa=hc;Ra=la;Sa=ic;Ta=r;Ua=o;Va=s;break}Ja=xa>>>0>gc>>>0?gc:xa;xa=Ja>>>0>la>>>0?la:Ja;if((xa|0)==0){na=fc;oa=gc;pa=hc;qa=la;ra=ic;sa=s;ta=285;break a}Kg(o|0,ic|0,xa|0)|0;c[F>>2]=(c[F>>2]|0)-xa;Oa=fc;Pa=gc-xa|0;Qa=hc;Ra=la-xa|0;Sa=ic+xa|0;Ta=r;Ua=o+xa|0;Va=s}else if((ta|0)==158){ta=0;if(jc>>>0<19){xa=jc;while(1){Ja=xa+1|0;b[l+(e[21760+(xa<<1)>>1]<<1)+112>>1]=0;if((Ja|0)==19){break}else{xa=Ja}}c[aa>>2]=19}c[ca>>2]=ba;c[J>>2]=ba;c[K>>2]=7;xa=Nf(0,da,19,ca,K,ea)|0;if((xa|0)==0){c[aa>>2]=0;c[l>>2]=18;Cc=0;Dc=kc;Ec=lc;Fc=mc;Gc=nc;Hc=0;ta=164;break}else{c[B>>2]=22032;c[l>>2]=29;Oa=kc;Pa=lc;Qa=mc;Ra=la;Sa=nc;Ta=r;Ua=o;Va=xa;break}}}while(0);c:do{if((ta|0)==55){while(1){ta=0;if((sd|0)==0){ya=rd;za=0;Aa=td;Ba=la;Ca=ud;Da=r;Ea=s;break a}xa=sd+ -1|0;Ja=ud+1|0;va=(d[ud]<>>0<16){rd=Ia;sd=xa;td=va;ud=Ja;ta=55}else{vd=xa;wd=va;xd=Ja;ta=57;break}}}else if((ta|0)==125){ta=0;if((c[I>>2]|0)!=0){Ja=Tb&7;c[l>>2]=26;Oa=Tb-Ja|0;Pa=Ub;Qa=Vb>>>Ja;Ra=la;Sa=Wb;Ta=r;Ua=o;Va=s;break}if(Tb>>>0<3){Ja=Tb;va=Ub;xa=Vb;Ia=Wb;while(1){if((va|0)==0){ya=Ja;za=0;Aa=xa;Ba=la;Ca=Ia;Da=r;Ea=s;break a}Ga=va+ -1|0;ua=Ia+1|0;Ha=(d[Ia]<>>0<3){Ja=wa;va=Ga;xa=Ha;Ia=ua}else{Kd=wa;Ld=Ga;Md=Ha;Nd=ua;break}}}else{Kd=Tb;Ld=Ub;Md=Vb;Nd=Wb}c[I>>2]=Md&1;Ia=Md>>>1&3;if((Ia|0)==0){c[l>>2]=13}else if((Ia|0)==1){c[J>>2]=22328;c[K>>2]=9;c[L>>2]=24376;c[M>>2]=5;c[l>>2]=19;if(N){ta=133;break a}}else if((Ia|0)==2){c[l>>2]=16}else if((Ia|0)==3){c[B>>2]=21936;c[l>>2]=29}Oa=Kd+ -3|0;Pa=Ld;Qa=Md>>>3;Ra=la;Sa=Nd;Ta=r;Ua=o;Va=s}else if((ta|0)==164){ta=0;Ia=c[Z>>2]|0;xa=c[_>>2]|0;do{if(Cc>>>0<(xa+Ia|0)>>>0){va=Cc;Ja=xa;ua=Ia;Ha=Dc;Ga=Ec;wa=Fc;Yb=Gc;d:while(1){Xb=(1<>2])+ -1|0;oc=Xb&wa;Od=c[J>>2]|0;Pd=d[Od+(oc<<2)+1|0]|0;if(Pd>>>0>Ha>>>0){Qd=Ha;Rd=Ga;Sd=wa;Td=Yb;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Td;Da=r;Ea=Hc;break a}Ud=Rd+ -1|0;Vd=Td+1|0;Wd=(d[Td]<>>0>Xd>>>0){Qd=Xd;Rd=Ud;Sd=Wd;Td=Vd}else{_d=Zd;$d=Yd;ae=Xd;be=Ud;ce=Wd;de=Vd;break}}}else{_d=Pd;$d=oc;ae=Ha;be=Ga;ce=wa;de=Yb}Td=b[Od+($d<<2)+2>>1]|0;e:do{if((Td&65535)<16){if(ae>>>0<_d>>>0){Sd=ae;Rd=be;Qd=ce;Xb=de;while(1){if((Rd|0)==0){ya=Sd;za=0;Aa=Qd;Ba=la;Ca=Xb;Da=r;Ea=Hc;break a}Vd=Rd+ -1|0;Wd=Xb+1|0;Ud=(d[Xb]<>>0<_d>>>0){Sd=Xd;Rd=Vd;Qd=Ud;Xb=Wd}else{ee=Xd;fe=Vd;ge=Ud;he=Wd;break}}}else{ee=ae;fe=be;ge=ce;he=de}c[aa>>2]=va+1;b[l+(va<<1)+112>>1]=Td;ie=ee-_d|0;je=fe;ke=ge>>>_d;le=he}else{if(Td<<16>>16==16){Xb=_d+2|0;if(ae>>>0>>0){Qd=ae;Rd=be;Sd=ce;Wd=de;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Wd;Da=r;Ea=Hc;break a}Ud=Rd+ -1|0;Vd=Wd+1|0;Xd=(d[Wd]<>>0>>0){Qd=Yd;Rd=Ud;Sd=Xd;Wd=Vd}else{me=Yd;ne=Ud;oe=Xd;pe=Vd;break}}}else{me=ae;ne=be;oe=ce;pe=de}qe=oe>>>_d;re=me-_d|0;if((va|0)==0){ta=181;break d}se=re+ -2|0;te=(qe&3)+3|0;ue=ne;ve=qe>>>2;we=b[l+(va+ -1<<1)+112>>1]|0;xe=pe}else if(Td<<16>>16==17){Wd=_d+3|0;if(ae>>>0>>0){Sd=ae;Rd=be;Qd=ce;Xb=de;while(1){if((Rd|0)==0){ya=Sd;za=0;Aa=Qd;Ba=la;Ca=Xb;Da=r;Ea=Hc;break a}Vd=Rd+ -1|0;Xd=Xb+1|0;Ud=(d[Xb]<>>0>>0){Sd=Yd;Rd=Vd;Qd=Ud;Xb=Xd}else{ye=Yd;ze=Vd;Ae=Ud;Be=Xd;break}}}else{ye=ae;ze=be;Ae=ce;Be=de}Xb=Ae>>>_d;se=-3-_d+ye|0;te=(Xb&7)+3|0;ue=ze;ve=Xb>>>3;we=0;xe=Be}else{Xb=_d+7|0;if(ae>>>0>>0){Qd=ae;Rd=be;Sd=ce;Wd=de;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Wd;Da=r;Ea=Hc;break a}Xd=Rd+ -1|0;Ud=Wd+1|0;Vd=(d[Wd]<>>0>>0){Qd=Yd;Rd=Xd;Sd=Vd;Wd=Ud}else{Ce=Yd;De=Xd;Ee=Vd;Fe=Ud;break}}}else{Ce=ae;De=be;Ee=ce;Fe=de}Wd=Ee>>>_d;se=-7-_d+Ce|0;te=(Wd&127)+11|0;ue=De;ve=Wd>>>7;we=0;xe=Fe}if((va+te|0)>>>0>(Ja+ua|0)>>>0){ta=190;break d}else{Ge=va;He=te}while(1){Wd=He+ -1|0;c[aa>>2]=Ge+1;b[l+(Ge<<1)+112>>1]=we;if((Wd|0)==0){ie=se;je=ue;ke=ve;le=xe;break e}Ge=c[aa>>2]|0;He=Wd}}}while(0);Td=c[aa>>2]|0;Ie=c[Z>>2]|0;Od=c[_>>2]|0;if(Td>>>0<(Od+Ie|0)>>>0){va=Td;Ja=Od;ua=Ie;Ha=ie;Ga=je;wa=ke;Yb=le}else{ta=193;break}}if((ta|0)==181){ta=0;c[B>>2]=22064;c[l>>2]=29;Oa=re;Pa=ne;Qa=qe;Ra=la;Sa=pe;Ta=r;Ua=o;Va=Hc;break c}else if((ta|0)==190){ta=0;c[B>>2]=22064;c[l>>2]=29;Oa=se;Pa=ue;Qa=ve;Ra=la;Sa=xe;Ta=r;Ua=o;Va=Hc;break c}else if((ta|0)==193){ta=0;if((c[l>>2]|0)==29){Oa=ie;Pa=je;Qa=ke;Ra=la;Sa=le;Ta=r;Ua=o;Va=Hc;break c}else{Je=Ie;Ke=ie;Le=je;Me=ke;Ne=le;break}}}else{Je=Ia;Ke=Dc;Le=Ec;Me=Fc;Ne=Gc}}while(0);if((b[fa>>1]|0)==0){c[B>>2]=22096;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Hc;break}c[ca>>2]=ba;c[J>>2]=ba;c[K>>2]=9;Ia=Nf(1,da,Je,ca,K,ea)|0;if((Ia|0)!=0){c[B>>2]=22136;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Ia;break}c[L>>2]=c[ca>>2];c[M>>2]=6;Ia=Nf(2,l+(c[Z>>2]<<1)+112|0,c[_>>2]|0,ca,M,ea)|0;if((Ia|0)==0){c[l>>2]=19;if(N){na=Ke;oa=Le;pa=Me;qa=la;ra=Ne;sa=0;ta=285;break a}else{Mc=Ke;Nc=Le;Oc=Me;Pc=Ne;Qc=0;ta=201;break}}else{c[B>>2]=22168;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Ia;break}}}while(0);if((ta|0)==57){ta=0;Ia=c[A>>2]|0;if((Ia|0)!=0){c[Ia+8>>2]=wd&255;c[Ia+12>>2]=wd>>>8}if((c[z>>2]&512|0)!=0){a[j]=wd;a[y]=wd>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0}c[l>>2]=4;nd=0;od=vd;pd=0;qd=xd;ta=62}else if((ta|0)==201){ta=0;c[l>>2]=20;Rc=Mc;Sc=Nc;Tc=Oc;Uc=Pc;Vc=Qc;ta=202}do{if((ta|0)==62){ta=0;Ia=c[z>>2]|0;if((Ia&1024|0)==0){xa=c[A>>2]|0;if((xa|0)==0){Oe=nd;Pe=od;Qe=pd;Re=qd}else{c[xa+16>>2]=0;Oe=nd;Pe=od;Qe=pd;Re=qd}}else{if(nd>>>0<16){xa=nd;Yb=od;wa=pd;Ga=qd;while(1){if((Yb|0)==0){ya=xa;za=0;Aa=wa;Ba=la;Ca=Ga;Da=r;Ea=s;break a}Ha=Yb+ -1|0;ua=Ga+1|0;Ja=(d[Ga]<>>0<16){xa=va;Yb=Ha;wa=Ja;Ga=ua}else{Se=Ha;Te=Ja;Ue=ua;break}}}else{Se=od;Te=pd;Ue=qd}c[F>>2]=Te;Ga=c[A>>2]|0;if((Ga|0)==0){Ve=Ia}else{c[Ga+20>>2]=Te;Ve=c[z>>2]|0}if((Ve&512|0)==0){Oe=0;Pe=Se;Qe=0;Re=Ue}else{a[j]=Te;a[y]=Te>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0;Oe=0;Pe=Se;Qe=0;Re=Ue}}c[l>>2]=5;Hb=Oe;Ib=Pe;Jb=Qe;Kb=Re;ta=73}else if((ta|0)==202){ta=0;if(Sc>>>0>5&la>>>0>257){c[m>>2]=o;c[n>>2]=la;c[f>>2]=Uc;c[p>>2]=Sc;c[u>>2]=Tc;c[v>>2]=Rc;Gf(f,r);Ga=c[m>>2]|0;wa=c[n>>2]|0;Yb=c[f>>2]|0;xa=c[p>>2]|0;ua=c[u>>2]|0;Ja=c[v>>2]|0;if((c[l>>2]|0)!=11){Oa=Ja;Pa=xa;Qa=ua;Ra=wa;Sa=Yb;Ta=r;Ua=Ga;Va=Vc;break}c[O>>2]=-1;Oa=Ja;Pa=xa;Qa=ua;Ra=wa;Sa=Yb;Ta=r;Ua=Ga;Va=Vc;break}c[O>>2]=0;Ga=(1<>2])+ -1|0;Yb=Ga&Tc;wa=c[J>>2]|0;ua=a[wa+(Yb<<2)+1|0]|0;xa=ua&255;if(xa>>>0>Rc>>>0){Ja=Rc;Ha=Sc;va=Tc;Od=Uc;while(1){if((Ha|0)==0){ya=Ja;za=0;Aa=va;Ba=la;Ca=Od;Da=r;Ea=Vc;break a}Td=Ha+ -1|0;oc=Od+1|0;Pd=(d[Od]<>>0>Wd>>>0){Ja=Wd;Ha=Td;va=Pd;Od=oc}else{We=Rd;Xe=Qd;Ye=Sd;Ze=Wd;_e=Td;$e=Pd;af=oc;break}}}else{We=ua;Xe=xa;Ye=Yb;Ze=Rc;_e=Sc;$e=Tc;af=Uc}Od=a[wa+(Ye<<2)|0]|0;va=b[wa+(Ye<<2)+2>>1]|0;Ha=Od&255;if(!(Od<<24>>24==0)){if((Ha&240|0)==0){Ja=va&65535;Ga=(1<>>Xe)+Ja|0;Ia=a[wa+(Ha<<2)+1|0]|0;if(((Ia&255)+Xe|0)>>>0>Ze>>>0){oc=Ze;Pd=_e;Td=$e;Wd=af;while(1){if((Pd|0)==0){ya=oc;za=0;Aa=Td;Ba=la;Ca=Wd;Da=r;Ea=Vc;break a}Sd=Pd+ -1|0;Qd=Wd+1|0;Rd=(d[Wd]<>>Xe)+Ja|0;Vd=a[wa+(Ud<<2)+1|0]|0;if(((Vd&255)+Xe|0)>>>0>Xb>>>0){oc=Xb;Pd=Sd;Td=Rd;Wd=Qd}else{bf=Ud;cf=Vd;df=Xb;ef=Sd;hf=Rd;jf=Qd;break}}}else{bf=Ha;cf=Ia;df=Ze;ef=_e;hf=$e;jf=af}Wd=b[wa+(bf<<2)+2>>1]|0;Td=a[wa+(bf<<2)|0]|0;c[O>>2]=Xe;kf=Xe;lf=df-Xe|0;mf=ef;nf=Td;of=cf;pf=Wd;qf=hf>>>Xe;rf=jf}else{kf=0;lf=Ze;mf=_e;nf=Od;of=We;pf=va;qf=$e;rf=af}}else{kf=0;lf=Ze;mf=_e;nf=0;of=We;pf=va;qf=$e;rf=af}Wd=of&255;Td=qf>>>Wd;Pd=lf-Wd|0;c[O>>2]=kf+Wd;c[F>>2]=pf&65535;Wd=nf&255;if(nf<<24>>24==0){c[l>>2]=25;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}if((Wd&32|0)!=0){c[O>>2]=-1;c[l>>2]=11;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}if((Wd&64|0)==0){oc=Wd&15;c[P>>2]=oc;c[l>>2]=21;$a=oc;ab=Pd;bb=mf;cb=Td;db=rf;eb=Vc;ta=221;break}else{c[B>>2]=22192;c[l>>2]=29;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}}}while(0);if((ta|0)==73){ta=0;Td=c[z>>2]|0;if((Td&1024|0)!=0){Pd=c[F>>2]|0;oc=Pd>>>0>Ib>>>0?Ib:Pd;if((oc|0)==0){sf=Pd;tf=Ib;uf=Kb}else{Wd=c[A>>2]|0;if((Wd|0)!=0?(Ja=c[Wd+16>>2]|0,(Ja|0)!=0):0){Ga=(c[Wd+20>>2]|0)-Pd|0;Pd=c[Wd+24>>2]|0;Kg(Ja+Ga|0,Kb|0,((Ga+oc|0)>>>0>Pd>>>0?Pd-Ga|0:oc)|0)|0;vf=c[z>>2]|0}else{vf=Td}if((vf&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Kb,oc)|0}Td=(c[F>>2]|0)-oc|0;c[F>>2]=Td;sf=Td;tf=Ib-oc|0;uf=Kb+oc|0}if((sf|0)==0){wf=tf;xf=uf}else{na=Hb;oa=tf;pa=Jb;qa=la;ra=uf;sa=s;ta=285;break}}else{wf=Ib;xf=Kb}c[F>>2]=0;c[l>>2]=6;Ic=Hb;Jc=wf;Kc=Jb;Lc=xf;ta=83}else if((ta|0)==221){ta=0;if(($a|0)==0){yf=c[F>>2]|0;zf=ab;Af=bb;Bf=cb;Cf=db}else{if(ab>>>0<$a>>>0){oc=ab;Td=bb;Ga=cb;Pd=db;while(1){if((Td|0)==0){ya=oc;za=0;Aa=Ga;Ba=la;Ca=Pd;Da=r;Ea=eb;break a}Ja=Td+ -1|0;Wd=Pd+1|0;Yb=(d[Pd]<>>0<$a>>>0){oc=xa;Td=Ja;Ga=Yb;Pd=Wd}else{Df=xa;Ef=Ja;Ff=Yb;Hf=Wd;break}}}else{Df=ab;Ef=bb;Ff=cb;Hf=db}Pd=(c[F>>2]|0)+((1<<$a)+ -1&Ff)|0;c[F>>2]=Pd;c[O>>2]=(c[O>>2]|0)+$a;yf=Pd;zf=Df-$a|0;Af=Ef;Bf=Ff>>>$a;Cf=Hf}c[Q>>2]=yf;c[l>>2]=22;ub=zf;vb=Af;wb=Bf;xb=Cf;yb=eb;ta=228}do{if((ta|0)==83){ta=0;if((c[z>>2]&2048|0)==0){Pd=c[A>>2]|0;if((Pd|0)==0){If=Jc;Jf=Lc}else{c[Pd+28>>2]=0;If=Jc;Jf=Lc}}else{if((Jc|0)==0){na=Ic;oa=0;pa=Kc;qa=la;ra=Lc;sa=s;ta=285;break a}else{Kf=0}while(1){Mf=Kf+1|0;Pd=a[Lc+Kf|0]|0;Ga=c[A>>2]|0;if(((Ga|0)!=0?(Td=c[Ga+28>>2]|0,(Td|0)!=0):0)?(oc=c[F>>2]|0,oc>>>0<(c[Ga+32>>2]|0)>>>0):0){c[F>>2]=oc+1;a[Td+oc|0]=Pd}Of=Pd<<24>>24!=0;if(Of&Mf>>>0>>0){Kf=Mf}else{break}}if((c[z>>2]&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Lc,Mf)|0}va=Jc-Mf|0;Od=Lc+Mf|0;if(Of){na=Ic;oa=va;pa=Kc;qa=la;ra=Od;sa=s;ta=285;break a}else{If=va;Jf=Od}}c[F>>2]=0;c[l>>2]=7;Db=Ic;Eb=If;Fb=Kc;Gb=Jf;ta=96}else if((ta|0)==228){ta=0;Od=(1<>2])+ -1|0;va=Od&wb;wa=c[L>>2]|0;Ia=a[wa+(va<<2)+1|0]|0;Ha=Ia&255;if(Ha>>>0>ub>>>0){Pd=ub;oc=vb;Td=wb;Ga=xb;while(1){if((oc|0)==0){ya=Pd;za=0;Aa=Td;Ba=la;Ca=Ga;Da=r;Ea=yb;break a}Wd=oc+ -1|0;Yb=Ga+1|0;Ja=(d[Ga]<>>0>xa>>>0){Pd=xa;oc=Wd;Td=Ja;Ga=Yb}else{Pf=Qd;Qf=Rd;Rf=ua;Sf=xa;Tf=Wd;Uf=Ja;Vf=Yb;break}}}else{Pf=Ia;Qf=Ha;Rf=va;Sf=ub;Tf=vb;Uf=wb;Vf=xb}Ga=a[wa+(Rf<<2)|0]|0;Td=b[wa+(Rf<<2)+2>>1]|0;oc=Ga&255;if((oc&240|0)==0){Pd=Td&65535;Od=(1<>>Qf)+Pd|0;Yb=a[wa+(oc<<2)+1|0]|0;if(((Yb&255)+Qf|0)>>>0>Sf>>>0){Ja=Sf;Wd=Tf;xa=Uf;ua=Vf;while(1){if((Wd|0)==0){ya=Ja;za=0;Aa=xa;Ba=la;Ca=ua;Da=r;Ea=yb;break a}Rd=Wd+ -1|0;Qd=ua+1|0;Sd=(d[ua]<>>Qf)+Pd|0;Ud=a[wa+(Vd<<2)+1|0]|0;if(((Ud&255)+Qf|0)>>>0>Xb>>>0){Ja=Xb;Wd=Rd;xa=Sd;ua=Qd}else{Wf=Vd;Xf=Ud;Yf=Xb;Zf=Rd;_f=Sd;$f=Qd;break}}}else{Wf=oc;Xf=Yb;Yf=Sf;Zf=Tf;_f=Uf;$f=Vf}ua=b[wa+(Wf<<2)+2>>1]|0;xa=a[wa+(Wf<<2)|0]|0;Wd=(c[O>>2]|0)+Qf|0;c[O>>2]=Wd;ag=Wd;bg=Yf-Qf|0;cg=Zf;dg=xa;eg=Xf;fg=ua;gg=_f>>>Qf;hg=$f}else{ag=c[O>>2]|0;bg=Sf;cg=Tf;dg=Ga;eg=Pf;fg=Td;gg=Uf;hg=Vf}ua=eg&255;xa=gg>>>ua;Wd=bg-ua|0;c[O>>2]=ag+ua;ua=dg&255;if((ua&64|0)==0){c[R>>2]=fg&65535;Ja=ua&15;c[P>>2]=Ja;c[l>>2]=23;fb=Ja;gb=Wd;hb=cg;ib=xa;jb=hg;kb=yb;ta=240;break}else{c[B>>2]=22224;c[l>>2]=29;Oa=Wd;Pa=cg;Qa=xa;Ra=la;Sa=hg;Ta=r;Ua=o;Va=yb;break}}}while(0);if((ta|0)==96){ta=0;if((c[z>>2]&4096|0)==0){xa=c[A>>2]|0;if((xa|0)==0){ig=Eb;jg=Gb}else{c[xa+36>>2]=0;ig=Eb;jg=Gb}}else{if((Eb|0)==0){na=Db;oa=0;pa=Fb;qa=la;ra=Gb;sa=s;ta=285;break}else{kg=0}while(1){lg=kg+1|0;xa=a[Gb+kg|0]|0;Wd=c[A>>2]|0;if(((Wd|0)!=0?(Ja=c[Wd+36>>2]|0,(Ja|0)!=0):0)?(ua=c[F>>2]|0,ua>>>0<(c[Wd+40>>2]|0)>>>0):0){c[F>>2]=ua+1;a[Ja+ua|0]=xa}mg=xa<<24>>24!=0;if(mg&lg>>>0>>0){kg=lg}else{break}}if((c[z>>2]&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Gb,lg)|0}xa=Eb-lg|0;ua=Gb+lg|0;if(mg){na=Db;oa=xa;pa=Fb;qa=la;ra=ua;sa=s;ta=285;break}else{ig=xa;jg=ua}}c[l>>2]=8;Lb=Db;Mb=ig;Nb=Fb;Ob=jg;ta=109}else if((ta|0)==240){ta=0;if((fb|0)==0){ng=gb;og=hb;pg=ib;qg=jb}else{if(gb>>>0>>0){ua=gb;xa=hb;Ja=ib;Wd=jb;while(1){if((xa|0)==0){ya=ua;za=0;Aa=Ja;Ba=la;Ca=Wd;Da=r;Ea=kb;break a}Pd=xa+ -1|0;Od=Wd+1|0;va=(d[Wd]<>>0>>0){ua=Ha;xa=Pd;Ja=va;Wd=Od}else{rg=Ha;sg=Pd;tg=va;ug=Od;break}}}else{rg=gb;sg=hb;tg=ib;ug=jb}c[R>>2]=(c[R>>2]|0)+((1<>2]=(c[O>>2]|0)+fb;ng=rg-fb|0;og=sg;pg=tg>>>fb;qg=ug}c[l>>2]=24;uc=ng;vc=og;wc=pg;xc=qg;yc=kb;ta=246}do{if((ta|0)==109){ta=0;Wd=c[z>>2]|0;if((Wd&512|0)!=0){if(Lb>>>0<16){Ja=Lb;xa=Mb;ua=Nb;Od=Ob;while(1){if((xa|0)==0){ya=Ja;za=0;Aa=ua;Ba=la;Ca=Od;Da=r;Ea=s;break a}va=xa+ -1|0;Pd=Od+1|0;Ha=(d[Od]<>>0<16){Ja=Ia;xa=va;ua=Ha;Od=Pd}else{vg=Ia;wg=va;xg=Ha;yg=Pd;break}}}else{vg=Lb;wg=Mb;xg=Nb;yg=Ob}if((xg|0)==(c[x>>2]&65535|0)){zg=0;Ag=wg;Bg=0;Cg=yg}else{c[B>>2]=21912;c[l>>2]=29;Oa=vg;Pa=wg;Qa=xg;Ra=la;Sa=yg;Ta=r;Ua=o;Va=s;break}}else{zg=Lb;Ag=Mb;Bg=Nb;Cg=Ob}Od=c[A>>2]|0;if((Od|0)!=0){c[Od+44>>2]=Wd>>>9&1;c[Od+48>>2]=1}Od=gf(0,0,0)|0;c[x>>2]=Od;c[E>>2]=Od;c[l>>2]=11;Oa=zg;Pa=Ag;Qa=Bg;Ra=la;Sa=Cg;Ta=r;Ua=o;Va=s}else if((ta|0)==246){ta=0;if((la|0)==0){na=uc;oa=vc;pa=wc;qa=0;ra=xc;sa=yc;ta=285;break a}Od=r-la|0;ua=c[R>>2]|0;if(ua>>>0>Od>>>0){xa=ua-Od|0;if(xa>>>0>(c[S>>2]|0)>>>0?(c[T>>2]|0)!=0:0){c[B>>2]=22248;c[l>>2]=29;Oa=uc;Pa=vc;Qa=wc;Ra=la;Sa=xc;Ta=r;Ua=o;Va=yc;break}Od=c[U>>2]|0;if(xa>>>0>Od>>>0){Ja=xa-Od|0;Dg=Ja;Eg=(c[V>>2]|0)+((c[W>>2]|0)-Ja)|0}else{Dg=xa;Eg=(c[V>>2]|0)+(Od-xa)|0}xa=c[F>>2]|0;Fg=xa;Gg=Dg>>>0>xa>>>0?xa:Dg;Hg=Eg}else{xa=c[F>>2]|0;Fg=xa;Gg=xa;Hg=o+(0-ua)|0}ua=Gg>>>0>la>>>0?la:Gg;c[F>>2]=Fg-ua;xa=~la;Od=~Gg;Ja=xa>>>0>Od>>>0?xa:Od;Od=ua;xa=Hg;Td=o;while(1){a[Td]=a[xa]|0;Od=Od+ -1|0;if((Od|0)==0){break}else{xa=xa+1|0;Td=Td+1|0}}Td=la-ua|0;xa=o+~Ja|0;if((c[F>>2]|0)==0){c[l>>2]=20;Oa=uc;Pa=vc;Qa=wc;Ra=Td;Sa=xc;Ta=r;Ua=xa;Va=yc}else{Oa=uc;Pa=vc;Qa=wc;Ra=Td;Sa=xc;Ta=r;Ua=xa;Va=yc}}}while(0);ia=c[l>>2]|0;q=Oa;ja=Pa;ka=Qa;la=Ra;ma=Sa;r=Ta;o=Ua;s=Va}if((ta|0)==122){c[m>>2]=o;c[n>>2]=la;c[f>>2]=Cb;c[p>>2]=Ab;c[u>>2]=Bb;c[v>>2]=zb;k=2;i=h;return k|0}else if((ta|0)==133){ya=Kd+ -3|0;za=Ld;Aa=Md>>>3;Ba=la;Ca=Nd;Da=r;Ea=s}else if((ta|0)==284){c[l>>2]=28;ya=Cd;za=Dd;Aa=Ed;Ba=la;Ca=Fd;Da=jd;Ea=1}else if((ta|0)==285){ya=na;za=oa;Aa=pa;Ba=qa;Ca=ra;Da=r;Ea=sa}else if((ta|0)==299){k=-4;i=h;return k|0}else if((ta|0)==300){i=h;return k|0}c[m>>2]=o;c[n>>2]=Ba;c[f>>2]=Ca;c[p>>2]=za;c[u>>2]=Aa;c[v>>2]=ya;if((c[W>>2]|0)==0){if((c[l>>2]|0)>>>0<26?(Da|0)!=(c[n>>2]|0):0){ta=289}}else{ta=289}if((ta|0)==289?(Lf(f,Da)|0)!=0:0){c[l>>2]=30;k=-4;i=h;return k|0}ta=c[p>>2]|0;p=c[n>>2]|0;n=Da-p|0;W=f+8|0;c[W>>2]=t-ta+(c[W>>2]|0);c[X>>2]=(c[X>>2]|0)+n;c[Y>>2]=(c[Y>>2]|0)+n;Y=(Da|0)==(p|0);if(!((c[w>>2]|0)==0|Y)){w=c[x>>2]|0;p=(c[m>>2]|0)+(0-n)|0;if((c[z>>2]|0)==0){Ig=ff(w,p,n)|0}else{Ig=gf(w,p,n)|0}c[x>>2]=Ig;c[E>>2]=Ig}Ig=c[l>>2]|0;if((Ig|0)==19){Jg=256}else{Jg=(Ig|0)==14?256:0}c[f+44>>2]=((c[I>>2]|0)!=0?64:0)+(c[v>>2]|0)+((Ig|0)==11?128:0)+Jg;k=((t|0)==(ta|0)&Y|(g|0)==4)&(Ea|0)==0?-5:Ea;i=h;return k|0}function Lf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;e=c[a+28>>2]|0;f=e+52|0;g=c[f>>2]|0;if((g|0)==0){h=kb[c[a+32>>2]&1](c[a+40>>2]|0,1<>2],1)|0;c[f>>2]=h;if((h|0)==0){j=1;i=d;return j|0}else{k=h}}else{k=g}g=e+40|0;h=c[g>>2]|0;if((h|0)==0){l=1<>2];c[g>>2]=l;c[e+48>>2]=0;c[e+44>>2]=0;m=l}else{m=h}h=b-(c[a+16>>2]|0)|0;if(!(h>>>0>>0)){Kg(k|0,(c[a+12>>2]|0)+(0-m)|0,m|0)|0;c[e+48>>2]=0;c[e+44>>2]=c[g>>2];j=0;i=d;return j|0}b=e+48|0;l=c[b>>2]|0;n=m-l|0;m=n>>>0>h>>>0?h:n;n=a+12|0;Kg(k+l|0,(c[n>>2]|0)+(0-h)|0,m|0)|0;l=h-m|0;if((h|0)!=(m|0)){Kg(c[f>>2]|0,(c[n>>2]|0)+(0-l)|0,l|0)|0;c[b>>2]=l;c[e+44>>2]=c[g>>2];j=0;i=d;return j|0}l=(c[b>>2]|0)+h|0;n=c[g>>2]|0;c[b>>2]=(l|0)==(n|0)?0:l;l=e+44|0;e=c[l>>2]|0;if(!(e>>>0>>0)){j=0;i=d;return j|0}c[l>>2]=e+h;j=0;i=d;return j|0}function Mf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;i=b;return d|0}g=a+36|0;h=c[g>>2]|0;if((h|0)==0){d=-2;i=b;return d|0}j=c[f+52>>2]|0;k=a+40|0;if((j|0)==0){l=h;m=f}else{mb[h&1](c[k>>2]|0,j);l=c[g>>2]|0;m=c[e>>2]|0}mb[l&1](c[k>>2]|0,m);c[e>>2]=0;d=0;i=b;return d|0}function Nf(d,f,g,h,j,k){d=d|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;l=i;i=i+64|0;m=l+32|0;n=l;o=m+0|0;p=o+32|0;do{b[o>>1]=0;o=o+2|0}while((o|0)<(p|0));o=(g|0)==0;if(!o){p=0;do{q=m+(e[f+(p<<1)>>1]<<1)|0;b[q>>1]=(b[q>>1]|0)+1<<16>>16;p=p+1|0}while((p|0)!=(g|0))}p=c[j>>2]|0;q=15;while(1){r=q+ -1|0;if((b[m+(q<<1)>>1]|0)!=0){break}if((r|0)==0){s=7;break}else{q=r}}if((s|0)==7){r=c[h>>2]|0;c[h>>2]=r+4;a[r]=64;a[r+1|0]=1;b[r+2>>1]=0;r=c[h>>2]|0;c[h>>2]=r+4;a[r]=64;a[r+1|0]=1;b[r+2>>1]=0;c[j>>2]=1;t=0;i=l;return t|0}r=p>>>0>q>>>0?q:p;a:do{if(q>>>0>1){p=1;while(1){u=p+1|0;if((b[m+(p<<1)>>1]|0)!=0){v=p;break a}if(u>>>0>>0){p=u}else{v=u;break}}}else{v=1}}while(0);p=r>>>0>>0?v:r;r=1;u=1;do{r=(r<<1)-(e[m+(u<<1)>>1]|0)|0;u=u+1|0;if((r|0)<0){t=-1;s=56;break}}while(u>>>0<16);if((s|0)==56){i=l;return t|0}if((r|0)>0?!((d|0)!=0&(q|0)==1):0){t=-1;i=l;return t|0}b[n+2>>1]=0;r=0;u=1;do{r=(e[m+(u<<1)>>1]|0)+(r&65535)|0;u=u+1|0;b[n+(u<<1)>>1]=r}while((u|0)!=15);if(!o){o=0;do{u=b[f+(o<<1)>>1]|0;if(!(u<<16>>16==0)){r=n+((u&65535)<<1)|0;u=b[r>>1]|0;b[r>>1]=u+1<<16>>16;b[k+((u&65535)<<1)>>1]=o}o=o+1|0}while((o|0)!=(g|0))}if((d|0)==0){w=0;x=1<>>0>851){t=1;i=l;return t|0}else{w=0;x=g;y=1;z=24504+ -514|0;A=256;B=24568+ -514|0}}else{g=1<>>0>591){t=1;i=l;return t|0}else{w=o;x=g;y=0;z=24632;A=-1;B=24696}}g=x+ -1|0;o=p&255;d=p;n=0;u=0;r=v;v=-1;C=c[h>>2]|0;D=0;E=x;b:while(1){x=1<>1]|0;L=K&65535;if((L|0)>=(A|0)){if((L|0)>(A|0)){M=b[B+(L<<1)>>1]&255;N=b[z+(L<<1)>>1]|0}else{M=96;N=0}}else{M=0;N=K}K=1<>>n;L=x;while(1){O=L-K|0;P=O+I|0;a[C+(P<<2)|0]=M;a[C+(P<<2)+1|0]=J;b[C+(P<<2)+2>>1]=N;if((L|0)==(K|0)){break}else{L=O}}L=1<>>1}}if((L|0)==0){Q=0}else{Q=(L+ -1&F)+L|0}R=H+1|0;K=m+(G<<1)|0;I=(b[K>>1]|0)+ -1<<16>>16;b[K>>1]=I;if(I<<16>>16==0){if((G|0)==(q|0)){break b}S=e[f+(e[k+(R<<1)>>1]<<1)>>1]|0}else{S=G}if(!(S>>>0>p>>>0)){F=Q;G=S;H=R;continue}T=Q&g;if((T|0)==(v|0)){F=Q;G=S;H=R}else{break}}H=(n|0)==0?p:n;G=C+(x<<2)|0;F=S-H|0;c:do{if(S>>>0>>0){I=S;K=F;O=1<>1]|0)|0;if((P|0)<1){U=K;break c}V=K+1|0;W=V+H|0;if(W>>>0>>0){I=W;K=V;O=P<<1}else{U=V;break}}}else{U=F}}while(0);F=(1<>>0>851|w&F>>>0>591){t=1;s=56;break}a[(c[h>>2]|0)+(T<<2)|0]=U;a[(c[h>>2]|0)+(T<<2)+1|0]=o;x=c[h>>2]|0;b[x+(T<<2)+2>>1]=(G-x|0)>>>2;d=U;n=H;u=Q;r=S;v=T;C=G;D=R;E=F}if((s|0)==56){i=l;return t|0}d:do{if((Q|0)!=0){s=n;R=J;D=Q;T=q;S=C;while(1){if((s|0)!=0){if((D&g|0)==(v|0)){X=s;Y=R;Z=T;_=S}else{X=0;Y=o;Z=p;_=c[h>>2]|0}}else{X=0;Y=R;Z=T;_=S}r=D>>>X;a[_+(r<<2)|0]=64;a[_+(r<<2)+1|0]=Y;b[_+(r<<2)+2>>1]=0;r=1<>>1}}if((r|0)==0){break d}D=(r+ -1&D)+r|0;if((D|0)==0){break}else{s=X;R=Y;T=Z;S=_}}}}while(0);c[h>>2]=(c[h>>2]|0)+(E<<2);c[j>>2]=p;t=0;i=l;return t|0}function Of(a){a=a|0;var d=0;d=i;c[a+2840>>2]=a+148;c[a+2848>>2]=25528;c[a+2852>>2]=a+2440;c[a+2860>>2]=25552;c[a+2864>>2]=a+2684;c[a+2872>>2]=25576;b[a+5816>>1]=0;c[a+5820>>2]=0;c[a+5812>>2]=8;Pf(a);i=d;return}function Pf(a){a=a|0;var d=0,e=0;d=i;e=0;do{b[a+(e<<2)+148>>1]=0;e=e+1|0}while((e|0)!=286);b[a+2440>>1]=0;b[a+2444>>1]=0;b[a+2448>>1]=0;b[a+2452>>1]=0;b[a+2456>>1]=0;b[a+2460>>1]=0;b[a+2464>>1]=0;b[a+2468>>1]=0;b[a+2472>>1]=0;b[a+2476>>1]=0;b[a+2480>>1]=0;b[a+2484>>1]=0;b[a+2488>>1]=0;b[a+2492>>1]=0;b[a+2496>>1]=0;b[a+2500>>1]=0;b[a+2504>>1]=0;b[a+2508>>1]=0;b[a+2512>>1]=0;b[a+2516>>1]=0;b[a+2520>>1]=0;b[a+2524>>1]=0;b[a+2528>>1]=0;b[a+2532>>1]=0;b[a+2536>>1]=0;b[a+2540>>1]=0;b[a+2544>>1]=0;b[a+2548>>1]=0;b[a+2552>>1]=0;b[a+2556>>1]=0;b[a+2684>>1]=0;b[a+2688>>1]=0;b[a+2692>>1]=0;b[a+2696>>1]=0;b[a+2700>>1]=0;b[a+2704>>1]=0;b[a+2708>>1]=0;b[a+2712>>1]=0;b[a+2716>>1]=0;b[a+2720>>1]=0;b[a+2724>>1]=0;b[a+2728>>1]=0;b[a+2732>>1]=0;b[a+2736>>1]=0;b[a+2740>>1]=0;b[a+2744>>1]=0;b[a+2748>>1]=0;b[a+2752>>1]=0;b[a+2756>>1]=0;b[a+1172>>1]=1;c[a+5804>>2]=0;c[a+5800>>2]=0;c[a+5808>>2]=0;c[a+5792>>2]=0;i=d;return}function Qf(d,f,g,h){d=d|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;j=i;k=d+5820|0;l=c[k>>2]|0;m=h&65535;h=d+5816|0;n=e[h>>1]|0|m<>1]=n;if((l|0)>13){o=d+20|0;p=c[o>>2]|0;c[o>>2]=p+1;q=d+8|0;a[(c[q>>2]|0)+p|0]=n;p=(e[h>>1]|0)>>>8&255;r=c[o>>2]|0;c[o>>2]=r+1;a[(c[q>>2]|0)+r|0]=p;p=c[k>>2]|0;r=m>>>(16-p|0);b[h>>1]=r;s=r;t=p+ -13|0}else{s=n;t=l+3|0}l=s&255;c[k>>2]=t;do{if((t|0)<=8){s=d+20|0;if((t|0)>0){n=c[s>>2]|0;c[s>>2]=n+1;p=d+8|0;a[(c[p>>2]|0)+n|0]=l;u=s;v=p;break}else{u=s;v=d+8|0;break}}else{s=d+20|0;p=c[s>>2]|0;c[s>>2]=p+1;n=d+8|0;a[(c[n>>2]|0)+p|0]=l;p=(e[h>>1]|0)>>>8&255;r=c[s>>2]|0;c[s>>2]=r+1;a[(c[n>>2]|0)+r|0]=p;u=s;v=n}}while(0);b[h>>1]=0;c[k>>2]=0;c[d+5812>>2]=8;d=c[u>>2]|0;c[u>>2]=d+1;a[(c[v>>2]|0)+d|0]=g;d=c[u>>2]|0;c[u>>2]=d+1;a[(c[v>>2]|0)+d|0]=g>>>8;d=g&65535^65535;k=c[u>>2]|0;c[u>>2]=k+1;a[(c[v>>2]|0)+k|0]=d;k=c[u>>2]|0;c[u>>2]=k+1;a[(c[v>>2]|0)+k|0]=d>>>8;if((g|0)==0){i=j;return}else{w=g;x=f}while(1){w=w+ -1|0;f=a[x]|0;g=c[u>>2]|0;c[u>>2]=g+1;a[(c[v>>2]|0)+g|0]=f;if((w|0)==0){break}else{x=x+1|0}}i=j;return}function Rf(d){d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;f=i;g=d+5820|0;h=c[g>>2]|0;j=d+5816|0;k=e[j>>1]|0|2<>1]=l;if((h|0)>13){m=d+20|0;n=c[m>>2]|0;c[m>>2]=n+1;o=d+8|0;a[(c[o>>2]|0)+n|0]=k;k=(e[j>>1]|0)>>>8&255;n=c[m>>2]|0;c[m>>2]=n+1;a[(c[o>>2]|0)+n|0]=k;k=c[g>>2]|0;n=2>>>(16-k|0)&65535;b[j>>1]=n;p=n;q=k+ -13|0}else{p=l;q=h+3|0}c[g>>2]=q;if((q|0)>9){h=d+20|0;l=c[h>>2]|0;c[h>>2]=l+1;k=d+8|0;a[(c[k>>2]|0)+l|0]=p;l=(e[j>>1]|0)>>>8&255;n=c[h>>2]|0;c[h>>2]=n+1;a[(c[k>>2]|0)+n|0]=l;b[j>>1]=0;r=(c[g>>2]|0)+ -9|0;s=0}else{r=q+7|0;s=p}c[g>>2]=r;if((r|0)!=16){if((r|0)>7){p=d+20|0;q=c[p>>2]|0;c[p>>2]=q+1;a[(c[d+8>>2]|0)+q|0]=s;q=(e[j>>1]|0)>>>8;b[j>>1]=q;p=(c[g>>2]|0)+ -8|0;c[g>>2]=p;t=p;u=q}else{t=r;u=s}}else{r=d+20|0;q=c[r>>2]|0;c[r>>2]=q+1;p=d+8|0;a[(c[p>>2]|0)+q|0]=s;s=(e[j>>1]|0)>>>8&255;q=c[r>>2]|0;c[r>>2]=q+1;a[(c[p>>2]|0)+q|0]=s;b[j>>1]=0;c[g>>2]=0;t=0;u=0}s=d+5812|0;if((11-t+(c[s>>2]|0)|0)>=9){c[s>>2]=7;i=f;return}q=u&65535|2<>1]=q;if((t|0)>13){u=d+20|0;p=c[u>>2]|0;c[u>>2]=p+1;r=d+8|0;a[(c[r>>2]|0)+p|0]=q;p=(e[j>>1]|0)>>>8&255;l=c[u>>2]|0;c[u>>2]=l+1;a[(c[r>>2]|0)+l|0]=p;p=c[g>>2]|0;l=2>>>(16-p|0);b[j>>1]=l;v=l;w=p+ -13|0}else{v=q;w=t+3|0}t=v&255;c[g>>2]=w;if((w|0)>9){v=d+20|0;q=c[v>>2]|0;c[v>>2]=q+1;p=d+8|0;a[(c[p>>2]|0)+q|0]=t;q=(e[j>>1]|0)>>>8&255;l=c[v>>2]|0;c[v>>2]=l+1;a[(c[p>>2]|0)+l|0]=q;b[j>>1]=0;x=0;y=(c[g>>2]|0)+ -9|0}else{x=t;y=w+7|0}c[g>>2]=y;if((y|0)==16){w=d+20|0;t=c[w>>2]|0;c[w>>2]=t+1;q=d+8|0;a[(c[q>>2]|0)+t|0]=x;t=(e[j>>1]|0)>>>8&255;l=c[w>>2]|0;c[w>>2]=l+1;a[(c[q>>2]|0)+l|0]=t;b[j>>1]=0;c[g>>2]=0;c[s>>2]=7;i=f;return}if((y|0)<=7){c[s>>2]=7;i=f;return}y=d+20|0;t=c[y>>2]|0;c[y>>2]=t+1;a[(c[d+8>>2]|0)+t|0]=x;b[j>>1]=(e[j>>1]|0)>>>8;c[g>>2]=(c[g>>2]|0)+ -8;c[s>>2]=7;i=f;return}function Sf(f,g,h,j){f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;k=i;if((c[f+132>>2]|0)>0){l=(c[f>>2]|0)+44|0;if((c[l>>2]|0)==2){m=-201342849;n=0;while(1){if((m&1|0)!=0?(b[f+(n<<2)+148>>1]|0)!=0:0){o=0;break}p=n+1|0;if((p|0)<32){m=m>>>1;n=p}else{q=6;break}}a:do{if((q|0)==6){if(((b[f+184>>1]|0)==0?(b[f+188>>1]|0)==0:0)?(b[f+200>>1]|0)==0:0){n=32;while(1){m=n+1|0;if((b[f+(n<<2)+148>>1]|0)!=0){o=1;break a}if((m|0)<256){n=m}else{o=0;break}}}else{o=1}}}while(0);c[l>>2]=o}Tf(f,f+2840|0);Tf(f,f+2852|0);Wf(f,f+148|0,c[f+2844>>2]|0);Wf(f,f+2440|0,c[f+2856>>2]|0);Tf(f,f+2864|0);o=18;while(1){l=o+ -1|0;if((b[f+(d[27352+o|0]<<2)+2686>>1]|0)!=0){r=o;break}if((l|0)>2){o=l}else{r=l;break}}o=f+5800|0;l=(r*3|0)+17+(c[o>>2]|0)|0;c[o>>2]=l;o=(l+10|0)>>>3;l=((c[f+5804>>2]|0)+10|0)>>>3;s=r;t=l>>>0>o>>>0?o:l;u=l}else{l=h+5|0;s=0;t=l;u=l}do{if((h+4|0)>>>0>t>>>0|(g|0)==0){l=f+5820|0;o=c[l>>2]|0;r=(o|0)>13;if((c[f+136>>2]|0)==4|(u|0)==(t|0)){q=j+2&65535;n=f+5816|0;m=e[n>>1]|q<>1]=m;if(r){p=f+20|0;v=c[p>>2]|0;c[p>>2]=v+1;w=f+8|0;a[(c[w>>2]|0)+v|0]=m;m=(e[n>>1]|0)>>>8&255;v=c[p>>2]|0;c[p>>2]=v+1;a[(c[w>>2]|0)+v|0]=m;m=c[l>>2]|0;b[n>>1]=q>>>(16-m|0);x=m+ -13|0}else{x=o+3|0}c[l>>2]=x;Uf(f,25600,26752);break}m=j+4&65535;q=f+5816|0;n=e[q>>1]|m<>1]=n;if(r){r=f+20|0;v=c[r>>2]|0;c[r>>2]=v+1;w=f+8|0;a[(c[w>>2]|0)+v|0]=n;v=(e[q>>1]|0)>>>8&255;p=c[r>>2]|0;c[r>>2]=p+1;a[(c[w>>2]|0)+p|0]=v;v=c[l>>2]|0;p=m>>>(16-v|0);b[q>>1]=p;y=p;z=v+ -13|0}else{y=n;z=o+3|0}c[l>>2]=z;o=c[f+2844>>2]|0;n=c[f+2856>>2]|0;v=o+65280&65535;p=y&65535|v<>1]=p;if((z|0)>11){m=f+20|0;w=c[m>>2]|0;c[m>>2]=w+1;r=f+8|0;a[(c[r>>2]|0)+w|0]=p;w=(e[q>>1]|0)>>>8&255;A=c[m>>2]|0;c[m>>2]=A+1;a[(c[r>>2]|0)+A|0]=w;w=c[l>>2]|0;A=v>>>(16-w|0);b[q>>1]=A;B=w+ -11|0;C=A}else{B=z+5|0;C=p}c[l>>2]=B;p=n&65535;A=p<>1]=A;if((B|0)>11){w=f+20|0;v=c[w>>2]|0;c[w>>2]=v+1;r=f+8|0;a[(c[r>>2]|0)+v|0]=A;v=(e[q>>1]|0)>>>8&255;m=c[w>>2]|0;c[w>>2]=m+1;a[(c[r>>2]|0)+m|0]=v;v=c[l>>2]|0;m=p>>>(16-v|0);b[q>>1]=m;D=v+ -11|0;E=m}else{D=B+5|0;E=A}c[l>>2]=D;A=s+65533&65535;m=A<>1]=m;if((D|0)>12){v=f+20|0;p=c[v>>2]|0;c[v>>2]=p+1;r=f+8|0;a[(c[r>>2]|0)+p|0]=m;p=(e[q>>1]|0)>>>8&255;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[r>>2]|0)+w|0]=p;p=c[l>>2]|0;w=A>>>(16-p|0);b[q>>1]=w;F=w;G=p+ -12|0}else{F=m;G=D+4|0}c[l>>2]=G;if((s|0)>-1){m=f+20|0;p=f+8|0;w=G;A=F;r=0;while(1){v=e[f+(d[27352+r|0]<<2)+2686>>1]|0;H=v<>1]=H;if((w|0)>13){I=c[m>>2]|0;c[m>>2]=I+1;a[(c[p>>2]|0)+I|0]=H;I=(e[q>>1]|0)>>>8&255;J=c[m>>2]|0;c[m>>2]=J+1;a[(c[p>>2]|0)+J|0]=I;I=c[l>>2]|0;J=v>>>(16-I|0);b[q>>1]=J;K=J;L=I+ -13|0}else{K=H;L=w+3|0}c[l>>2]=L;if((r|0)==(s|0)){break}else{w=L;A=K;r=r+1|0}}}r=f+148|0;Vf(f,r,o);A=f+2440|0;Vf(f,A,n);Uf(f,r,A)}else{Qf(f,g,h,j)}}while(0);Pf(f);if((j|0)==0){i=k;return}j=f+5820|0;h=c[j>>2]|0;if((h|0)<=8){g=f+5816|0;if((h|0)>0){h=b[g>>1]&255;K=f+20|0;L=c[K>>2]|0;c[K>>2]=L+1;a[(c[f+8>>2]|0)+L|0]=h;M=g}else{M=g}}else{g=f+5816|0;h=b[g>>1]&255;L=f+20|0;K=c[L>>2]|0;c[L>>2]=K+1;s=f+8|0;a[(c[s>>2]|0)+K|0]=h;h=(e[g>>1]|0)>>>8&255;K=c[L>>2]|0;c[L>>2]=K+1;a[(c[s>>2]|0)+K|0]=h;M=g}b[M>>1]=0;c[j>>2]=0;i=k;return}function Tf(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0;h=i;i=i+32|0;j=h;k=c[g>>2]|0;l=g+8|0;m=c[l>>2]|0;n=c[m>>2]|0;o=c[m+12>>2]|0;m=f+5200|0;c[m>>2]=0;p=f+5204|0;c[p>>2]=573;if((o|0)>0){q=-1;r=0;while(1){if((b[k+(r<<2)>>1]|0)==0){b[k+(r<<2)+2>>1]=0;s=q}else{t=(c[m>>2]|0)+1|0;c[m>>2]=t;c[f+(t<<2)+2908>>2]=r;a[f+r+5208|0]=0;s=r}r=r+1|0;if((r|0)==(o|0)){break}else{q=s}}q=c[m>>2]|0;if((q|0)<2){u=q;v=s;w=3}else{x=s}}else{u=0;v=-1;w=3}if((w|0)==3){w=f+5800|0;s=f+5804|0;if((n|0)==0){q=u;r=v;while(1){t=(r|0)<2;y=r+1|0;z=t?y:r;A=t?y:0;y=q+1|0;c[m>>2]=y;c[f+(y<<2)+2908>>2]=A;b[k+(A<<2)>>1]=1;a[f+A+5208|0]=0;c[w>>2]=(c[w>>2]|0)+ -1;A=c[m>>2]|0;if((A|0)<2){q=A;r=z}else{x=z;break}}}else{r=u;u=v;while(1){v=(u|0)<2;q=u+1|0;z=v?q:u;A=v?q:0;q=r+1|0;c[m>>2]=q;c[f+(q<<2)+2908>>2]=A;b[k+(A<<2)>>1]=1;a[f+A+5208|0]=0;c[w>>2]=(c[w>>2]|0)+ -1;c[s>>2]=(c[s>>2]|0)-(e[n+(A<<2)+2>>1]|0);A=c[m>>2]|0;if((A|0)<2){r=A;u=z}else{x=z;break}}}}u=g+4|0;c[u>>2]=x;r=c[m>>2]|0;if((r|0)>1){n=r;s=(r|0)/2|0;while(1){w=c[f+(s<<2)+2908>>2]|0;z=f+w+5208|0;A=s<<1;a:do{if((A|0)>(n|0)){B=s}else{q=k+(w<<2)|0;v=s;y=n;t=A;while(1){do{if((t|0)<(y|0)){C=t|1;D=c[f+(C<<2)+2908>>2]|0;E=b[k+(D<<2)>>1]|0;F=c[f+(t<<2)+2908>>2]|0;G=b[k+(F<<2)>>1]|0;if(!((E&65535)<(G&65535))){if(!(E<<16>>16==G<<16>>16)){H=t;break}if((d[f+D+5208|0]|0)>(d[f+F+5208|0]|0)){H=t;break}}H=C}else{H=t}}while(0);C=b[q>>1]|0;F=c[f+(H<<2)+2908>>2]|0;D=b[k+(F<<2)>>1]|0;if((C&65535)<(D&65535)){B=v;break a}if(C<<16>>16==D<<16>>16?(d[z]|0)<=(d[f+F+5208|0]|0):0){B=v;break a}c[f+(v<<2)+2908>>2]=F;F=H<<1;D=c[m>>2]|0;if((F|0)>(D|0)){B=H;break}else{v=H;y=D;t=F}}}}while(0);c[f+(B<<2)+2908>>2]=w;z=s+ -1|0;A=c[m>>2]|0;if((z|0)>0){n=A;s=z}else{I=A;break}}}else{I=r}r=f+2912|0;s=I;I=o;while(1){o=c[r>>2]|0;n=s+ -1|0;c[m>>2]=n;B=c[f+(s<<2)+2908>>2]|0;c[r>>2]=B;H=f+B+5208|0;b:do{if((s|0)<3){J=1}else{A=k+(B<<2)|0;z=1;t=n;y=2;while(1){do{if((y|0)<(t|0)){v=y|1;q=c[f+(v<<2)+2908>>2]|0;F=b[k+(q<<2)>>1]|0;D=c[f+(y<<2)+2908>>2]|0;C=b[k+(D<<2)>>1]|0;if(!((F&65535)<(C&65535))){if(!(F<<16>>16==C<<16>>16)){K=y;break}if((d[f+q+5208|0]|0)>(d[f+D+5208|0]|0)){K=y;break}}K=v}else{K=y}}while(0);v=b[A>>1]|0;D=c[f+(K<<2)+2908>>2]|0;q=b[k+(D<<2)>>1]|0;if((v&65535)<(q&65535)){J=z;break b}if(v<<16>>16==q<<16>>16?(d[H]|0)<=(d[f+D+5208|0]|0):0){J=z;break b}c[f+(z<<2)+2908>>2]=D;D=K<<1;q=c[m>>2]|0;if((D|0)>(q|0)){J=K;break}else{z=K;t=q;y=D}}}}while(0);c[f+(J<<2)+2908>>2]=B;H=c[r>>2]|0;n=(c[p>>2]|0)+ -1|0;c[p>>2]=n;c[f+(n<<2)+2908>>2]=o;n=(c[p>>2]|0)+ -1|0;c[p>>2]=n;c[f+(n<<2)+2908>>2]=H;n=k+(I<<2)|0;b[n>>1]=(e[k+(H<<2)>>1]|0)+(e[k+(o<<2)>>1]|0);w=a[f+o+5208|0]|0;y=a[f+H+5208|0]|0;t=f+I+5208|0;a[t]=(((w&255)<(y&255)?y:w)&255)+1;w=I&65535;b[k+(H<<2)+2>>1]=w;b[k+(o<<2)+2>>1]=w;w=I+1|0;c[r>>2]=I;H=c[m>>2]|0;c:do{if((H|0)<2){L=1}else{y=1;z=H;A=2;while(1){do{if((A|0)<(z|0)){D=A|1;q=c[f+(D<<2)+2908>>2]|0;v=b[k+(q<<2)>>1]|0;C=c[f+(A<<2)+2908>>2]|0;F=b[k+(C<<2)>>1]|0;if(!((v&65535)<(F&65535))){if(!(v<<16>>16==F<<16>>16)){M=A;break}if((d[f+q+5208|0]|0)>(d[f+C+5208|0]|0)){M=A;break}}M=D}else{M=A}}while(0);D=b[n>>1]|0;C=c[f+(M<<2)+2908>>2]|0;q=b[k+(C<<2)>>1]|0;if((D&65535)<(q&65535)){L=y;break c}if(D<<16>>16==q<<16>>16?(d[t]|0)<=(d[f+C+5208|0]|0):0){L=y;break c}c[f+(y<<2)+2908>>2]=C;C=M<<1;q=c[m>>2]|0;if((C|0)>(q|0)){L=M;break}else{y=M;z=q;A=C}}}}while(0);c[f+(L<<2)+2908>>2]=I;t=c[m>>2]|0;if((t|0)>1){s=t;I=w}else{break}}I=c[r>>2]|0;r=(c[p>>2]|0)+ -1|0;c[p>>2]=r;c[f+(r<<2)+2908>>2]=I;I=c[g>>2]|0;g=c[u>>2]|0;u=c[l>>2]|0;l=c[u>>2]|0;r=c[u+4>>2]|0;s=c[u+8>>2]|0;m=c[u+16>>2]|0;u=f+2876|0;L=u+32|0;do{b[u>>1]=0;u=u+2|0}while((u|0)<(L|0));u=c[p>>2]|0;b[I+(c[f+(u<<2)+2908>>2]<<2)+2>>1]=0;p=u+1|0;d:do{if((p|0)<573){u=f+5800|0;L=f+5804|0;if((l|0)==0){M=p;J=0;while(1){K=c[f+(M<<2)+2908>>2]|0;t=I+(K<<2)+2|0;n=e[I+(e[t>>1]<<2)+2>>1]|0;H=(n|0)<(m|0);o=H?n+1|0:m;n=(H&1^1)+J|0;b[t>>1]=o;if((K|0)<=(g|0)){t=f+(o<<1)+2876|0;b[t>>1]=(b[t>>1]|0)+1<<16>>16;if((K|0)<(s|0)){N=0}else{N=c[r+(K-s<<2)>>2]|0}t=aa(e[I+(K<<2)>>1]|0,N+o|0)|0;c[u>>2]=t+(c[u>>2]|0)}t=M+1|0;if((t|0)==573){O=n;break}else{M=t;J=n}}}else{J=p;M=0;while(1){w=c[f+(J<<2)+2908>>2]|0;n=I+(w<<2)+2|0;t=e[I+(e[n>>1]<<2)+2>>1]|0;o=(t|0)<(m|0);K=o?t+1|0:m;t=(o&1^1)+M|0;b[n>>1]=K;if((w|0)<=(g|0)){n=f+(K<<1)+2876|0;b[n>>1]=(b[n>>1]|0)+1<<16>>16;if((w|0)<(s|0)){P=0}else{P=c[r+(w-s<<2)>>2]|0}n=e[I+(w<<2)>>1]|0;o=aa(n,P+K|0)|0;c[u>>2]=o+(c[u>>2]|0);o=aa((e[l+(w<<2)+2>>1]|0)+P|0,n)|0;c[L>>2]=o+(c[L>>2]|0)}o=J+1|0;if((o|0)==573){O=t;break}else{J=o;M=t}}}if((O|0)!=0){M=f+(m<<1)+2876|0;J=O;do{L=m;while(1){t=L+ -1|0;Q=f+(t<<1)+2876|0;R=b[Q>>1]|0;if(R<<16>>16==0){L=t}else{break}}b[Q>>1]=R+ -1<<16>>16;t=f+(L<<1)+2876|0;b[t>>1]=(e[t>>1]|0)+2;S=(b[M>>1]|0)+ -1<<16>>16;b[M>>1]=S;J=J+ -2|0}while((J|0)>0);if((m|0)!=0){J=S;M=m;t=573;while(1){o=M&65535;if(J<<16>>16==0){T=t}else{n=t;w=J&65535;while(1){K=n;do{K=K+ -1|0;U=c[f+(K<<2)+2908>>2]|0}while((U|0)>(g|0));H=I+(U<<2)+2|0;B=e[H>>1]|0;if((B|0)!=(M|0)){A=aa(e[I+(U<<2)>>1]|0,M-B|0)|0;c[u>>2]=A+(c[u>>2]|0);b[H>>1]=o}H=w+ -1|0;if((H|0)==0){T=K;break}else{n=K;w=H}}}w=M+ -1|0;if((w|0)==0){break d}J=b[f+(w<<1)+2876>>1]|0;M=w;t=T}}}}}while(0);T=1;U=0;do{U=(e[f+(T+ -1<<1)+2876>>1]|0)+(U&65534)<<1;b[j+(T<<1)>>1]=U;T=T+1|0}while((T|0)!=16);if((x|0)<0){i=h;return}else{V=0}while(1){T=b[k+(V<<2)+2>>1]|0;U=T&65535;if(!(T<<16>>16==0)){T=j+(U<<1)|0;f=b[T>>1]|0;b[T>>1]=f+1<<16>>16;T=U;U=f&65535;f=0;while(1){W=f|U&1;T=T+ -1|0;if((T|0)<=0){break}else{U=U>>>1;f=W<<1}}b[k+(V<<2)>>1]=W}if((V|0)==(x|0)){break}else{V=V+1|0}}i=h;return}function Uf(f,g,h){f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0;j=i;k=f+5792|0;if((c[k>>2]|0)==0){l=c[f+5820>>2]|0;m=b[f+5816>>1]|0}else{n=f+5796|0;o=f+5784|0;p=f+5820|0;q=f+5816|0;r=f+20|0;s=f+8|0;t=0;while(1){u=b[(c[n>>2]|0)+(t<<1)>>1]|0;v=u&65535;w=t+1|0;x=d[(c[o>>2]|0)+t|0]|0;do{if(u<<16>>16==0){y=e[g+(x<<2)+2>>1]|0;z=c[p>>2]|0;A=e[g+(x<<2)>>1]|0;B=e[q>>1]|0|A<>1]=C;if((z|0)>(16-y|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=B;B=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=B;B=c[p>>2]|0;D=A>>>(16-B|0)&65535;b[q>>1]=D;A=y+ -16+B|0;c[p>>2]=A;E=D;F=A;break}else{A=z+y|0;c[p>>2]=A;E=C;F=A;break}}else{A=d[25272+x|0]|0;C=(A|256)+1|0;y=e[g+(C<<2)+2>>1]|0;z=c[p>>2]|0;D=e[g+(C<<2)>>1]|0;C=e[q>>1]|0|D<>1]=B;if((z|0)>(16-y|0)){G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=C;C=(e[q>>1]|0)>>>8&255;G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=C;C=c[p>>2]|0;G=D>>>(16-C|0)&65535;b[q>>1]=G;H=G;I=y+ -16+C|0}else{H=B;I=z+y|0}c[p>>2]=I;y=c[26872+(A<<2)>>2]|0;do{if((A+ -8|0)>>>0<20){z=x-(c[26992+(A<<2)>>2]|0)&65535;B=z<>1]=C;if((I|0)>(16-y|0)){G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=B;B=(e[q>>1]|0)>>>8&255;G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=B;B=c[p>>2]|0;G=z>>>(16-B|0)&65535;b[q>>1]=G;z=y+ -16+B|0;c[p>>2]=z;J=z;K=G;break}else{G=I+y|0;c[p>>2]=G;J=G;K=C;break}}else{J=I;K=H}}while(0);y=v+ -1|0;if(y>>>0<256){L=y}else{L=(y>>>7)+256|0}A=d[24760+L|0]|0;C=e[h+(A<<2)+2>>1]|0;G=e[h+(A<<2)>>1]|0;z=K&65535|G<>1]=B;if((J|0)>(16-C|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=z;z=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=z;z=c[p>>2]|0;D=G>>>(16-z|0)&65535;b[q>>1]=D;M=C+ -16+z|0;N=D}else{M=J+C|0;N=B}c[p>>2]=M;B=c[27112+(A<<2)>>2]|0;if((A+ -4|0)>>>0<26){C=y-(c[27232+(A<<2)>>2]|0)&65535;A=C<>1]=y;if((M|0)>(16-B|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=A;A=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=A;A=c[p>>2]|0;D=C>>>(16-A|0)&65535;b[q>>1]=D;C=B+ -16+A|0;c[p>>2]=C;E=D;F=C;break}else{C=M+B|0;c[p>>2]=C;E=y;F=C;break}}else{E=N;F=M}}}while(0);if(w>>>0<(c[k>>2]|0)>>>0){t=w}else{l=F;m=E;break}}}E=g+1026|0;F=e[E>>1]|0;t=f+5820|0;k=e[g+1024>>1]|0;g=f+5816|0;M=m&65535|k<>1]=M;if((l|0)>(16-F|0)){m=f+20|0;N=c[m>>2]|0;c[m>>2]=N+1;p=f+8|0;a[(c[p>>2]|0)+N|0]=M;M=(e[g>>1]|0)>>>8&255;N=c[m>>2]|0;c[m>>2]=N+1;a[(c[p>>2]|0)+N|0]=M;M=c[t>>2]|0;b[g>>1]=k>>>(16-M|0);O=F+ -16+M|0;c[t>>2]=O;P=b[E>>1]|0;Q=P&65535;R=f+5812|0;c[R>>2]=Q;i=j;return}else{O=l+F|0;c[t>>2]=O;P=b[E>>1]|0;Q=P&65535;R=f+5812|0;c[R>>2]=Q;i=j;return}}function Vf(d,f,g){d=d|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0;h=i;j=b[f+2>>1]|0;k=j<<16>>16==0;l=d+2754|0;m=d+5820|0;n=d+2752|0;o=d+5816|0;p=d+20|0;q=d+8|0;r=d+2758|0;s=d+2756|0;t=d+2750|0;u=d+2748|0;v=k?138:7;w=k?3:4;k=0;x=j&65535;j=-1;a:while(1){y=0;z=k;while(1){if((z|0)>(g|0)){break a}z=z+1|0;A=b[f+(z<<2)+2>>1]|0;B=A&65535;C=y+1|0;D=(x|0)==(B|0);if(!((C|0)<(v|0)&D)){break}else{y=C}}do{if((C|0)>=(w|0)){if((x|0)!=0){if((x|0)==(j|0)){E=b[o>>1]|0;F=c[m>>2]|0;G=C}else{H=e[d+(x<<2)+2686>>1]|0;I=c[m>>2]|0;J=e[d+(x<<2)+2684>>1]|0;K=e[o>>1]|0|J<>1]=L;if((I|0)>(16-H|0)){M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=c[m>>2]|0;M=J>>>(16-K|0)&65535;b[o>>1]=M;N=M;O=H+ -16+K|0}else{N=L;O=I+H|0}c[m>>2]=O;E=N;F=O;G=y}H=e[t>>1]|0;I=e[u>>1]|0;L=E&65535|I<>1]=L;if((F|0)>(16-H|0)){K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=L;K=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=c[m>>2]|0;M=I>>>(16-K|0);b[o>>1]=M;P=H+ -16+K|0;Q=M}else{P=F+H|0;Q=L}c[m>>2]=P;L=G+65533&65535;H=Q&65535|L<>1]=H;if((P|0)>14){M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=H;H=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=H;H=c[m>>2]|0;b[o>>1]=L>>>(16-H|0);c[m>>2]=H+ -14;break}else{c[m>>2]=P+2;break}}if((C|0)<11){H=e[l>>1]|0;L=c[m>>2]|0;M=e[n>>1]|0;K=e[o>>1]|0|M<>1]=K;if((L|0)>(16-H|0)){I=c[p>>2]|0;c[p>>2]=I+1;a[(c[q>>2]|0)+I|0]=K;I=(e[o>>1]|0)>>>8&255;J=c[p>>2]|0;c[p>>2]=J+1;a[(c[q>>2]|0)+J|0]=I;I=c[m>>2]|0;J=M>>>(16-I|0);b[o>>1]=J;R=H+ -16+I|0;S=J}else{R=L+H|0;S=K}c[m>>2]=R;K=y+65534&65535;H=S&65535|K<>1]=H;if((R|0)>13){L=c[p>>2]|0;c[p>>2]=L+1;a[(c[q>>2]|0)+L|0]=H;H=(e[o>>1]|0)>>>8&255;L=c[p>>2]|0;c[p>>2]=L+1;a[(c[q>>2]|0)+L|0]=H;H=c[m>>2]|0;b[o>>1]=K>>>(16-H|0);c[m>>2]=H+ -13;break}else{c[m>>2]=R+3;break}}else{H=e[r>>1]|0;K=c[m>>2]|0;L=e[s>>1]|0;J=e[o>>1]|0|L<>1]=J;if((K|0)>(16-H|0)){I=c[p>>2]|0;c[p>>2]=I+1;a[(c[q>>2]|0)+I|0]=J;I=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=I;I=c[m>>2]|0;M=L>>>(16-I|0);b[o>>1]=M;T=H+ -16+I|0;U=M}else{T=K+H|0;U=J}c[m>>2]=T;J=y+65526&65535;H=U&65535|J<>1]=H;if((T|0)>9){K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=H;H=(e[o>>1]|0)>>>8&255;K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=H;H=c[m>>2]|0;b[o>>1]=J>>>(16-H|0);c[m>>2]=H+ -9;break}else{c[m>>2]=T+7;break}}}else{H=d+(x<<2)+2686|0;J=d+(x<<2)+2684|0;K=c[m>>2]|0;M=b[o>>1]|0;I=C;while(1){L=e[H>>1]|0;V=e[J>>1]|0;W=M&65535|V<>1]=X;if((K|0)>(16-L|0)){Y=c[p>>2]|0;c[p>>2]=Y+1;a[(c[q>>2]|0)+Y|0]=W;W=(e[o>>1]|0)>>>8&255;Y=c[p>>2]|0;c[p>>2]=Y+1;a[(c[q>>2]|0)+Y|0]=W;W=c[m>>2]|0;Y=V>>>(16-W|0)&65535;b[o>>1]=Y;Z=Y;_=L+ -16+W|0}else{Z=X;_=K+L|0}c[m>>2]=_;I=I+ -1|0;if((I|0)==0){break}else{K=_;M=Z}}}}while(0);if(A<<16>>16==0){$=x;v=138;w=3;k=z;x=B;j=$;continue}$=x;v=D?6:7;w=D?3:4;k=z;x=B;j=$}i=h;return}function Wf(a,c,d){a=a|0;c=c|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;f=i;g=b[c+2>>1]|0;h=g<<16>>16==0;b[c+(d+1<<2)+2>>1]=-1;j=a+2752|0;k=a+2756|0;l=a+2748|0;m=h?138:7;n=h?3:4;h=0;o=g&65535;g=-1;a:while(1){p=0;q=h;do{if((q|0)>(d|0)){break a}q=q+1|0;r=b[c+(q<<2)+2>>1]|0;s=r&65535;p=p+1|0;t=(o|0)==(s|0)}while((p|0)<(m|0)&t);do{if((p|0)>=(n|0)){if((o|0)==0){if((p|0)<11){b[j>>1]=(b[j>>1]|0)+1<<16>>16;break}else{b[k>>1]=(b[k>>1]|0)+1<<16>>16;break}}else{if((o|0)!=(g|0)){u=a+(o<<2)+2684|0;b[u>>1]=(b[u>>1]|0)+1<<16>>16}b[l>>1]=(b[l>>1]|0)+1<<16>>16;break}}else{u=a+(o<<2)+2684|0;b[u>>1]=(e[u>>1]|0)+p}}while(0);if(r<<16>>16==0){v=o;m=138;n=3;h=q;o=s;g=v;continue}v=o;m=t?6:7;n=t?3:4;h=q;o=s;g=v}i=f;return}function Xf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;a=i;d=gg(aa(c,b)|0)|0;i=a;return d|0}function Yf(a,b){a=a|0;b=b|0;a=i;hg(b);i=a;return}function Zf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0;f=i;i=i+944|0;g=f+680|0;h=f+424|0;j=f+192|0;k=f;l=aa(d,b)|0;if((l|0)==0){i=f;return}b=l-d|0;c[k+4>>2]=d;c[k>>2]=d;m=d;n=d;o=2;while(1){p=m+d+n|0;c[k+(o<<2)>>2]=p;if(p>>>0>>0){q=n;n=p;o=o+1|0;m=q}else{break}}m=0-d|0;o=a+b|0;if((b|0)>0){b=(d|0)==0;n=d>>>0>256?256:d;l=(n|0)==(d|0);q=o;p=1;r=0;s=a;t=1;while(1){do{if((p&3|0)!=3){u=t+ -1|0;a:do{if((c[k+(u<<2)>>2]|0)>>>0<(q-s|0)>>>0){c[j>>2]=s;if((t|0)>1){v=t;w=s;x=s;y=1;while(1){z=w+m|0;A=v+ -2|0;B=w+(0-((c[k+(A<<2)>>2]|0)+d))|0;if((nb[e&7](x,B)|0)>-1?(nb[e&7](x,z)|0)>-1:0){C=y;break}D=y+1|0;E=j+(y<<2)|0;if((nb[e&7](B,z)|0)>-1){c[E>>2]=B;F=B;G=v+ -1|0}else{c[E>>2]=z;F=z;G=A}if((G|0)<=1){C=D;break}v=G;w=F;x=c[j>>2]|0;y=D}if((C|0)>=2?(y=j+(C<<2)|0,c[y>>2]=g,!b):0){if((C|0)>0){H=d;I=g}else{x=c[j>>2]|0;Kg(g|0,x|0,n|0)|0;if(l){break}else{J=d;K=n}while(1){J=J-K|0;K=J>>>0>256?256:J;Kg(g|0,x|0,K|0)|0;if((J|0)==(K|0)){break a}}}while(1){x=H>>>0>256?256:H;w=c[j>>2]|0;Kg(I|0,w|0,x|0)|0;v=w;w=0;while(1){D=w+1|0;A=c[j+(D<<2)>>2]|0;Kg(v|0,A|0,x|0)|0;c[j+(w<<2)>>2]=v+x;if((D|0)==(C|0)){break}else{v=A;w=D}}if((H|0)==(x|0)){break a}H=H-x|0;I=c[y>>2]|0}}}}else{_f(s,d,e,p,r,t,0,k)}}while(0);if((t|0)==1){L=p<<1;M=p>>>31|r<<1;N=0;break}else{y=u>>>0>31;w=y?0:p;v=y?t+ -33|0:u;L=w<>>(32-v|0)|(y?p:r)<>2]=s;b:do{if((t|0)>1){v=t;y=s;w=s;D=1;while(1){A=y+m|0;z=v+ -2|0;E=y+(0-((c[k+(z<<2)>>2]|0)+d))|0;if((nb[e&7](w,E)|0)>-1?(nb[e&7](w,A)|0)>-1:0){O=D;break}B=D+1|0;P=j+(D<<2)|0;if((nb[e&7](E,A)|0)>-1){c[P>>2]=E;Q=E;R=v+ -1|0}else{c[P>>2]=A;Q=A;R=z}if((R|0)<=1){O=B;break}v=R;y=Q;w=c[j>>2]|0;D=B}if((O|0)>=2?(D=j+(O<<2)|0,c[D>>2]=h,!b):0){if((O|0)>0){S=d;T=h}else{w=c[j>>2]|0;Kg(h|0,w|0,n|0)|0;if(l){break}else{U=d;V=n}while(1){U=U-V|0;V=U>>>0>256?256:U;Kg(h|0,w|0,V|0)|0;if((U|0)==(V|0)){break b}}}while(1){w=S>>>0>256?256:S;y=c[j>>2]|0;Kg(T|0,y|0,w|0)|0;v=y;y=0;while(1){B=y+1|0;z=c[j+(B<<2)>>2]|0;Kg(v|0,z|0,w|0)|0;c[j+(y<<2)>>2]=v+w;if((B|0)==(O|0)){break}else{v=z;y=B}}if((S|0)==(w|0)){break b}S=S-w|0;T=c[D>>2]|0}}}}while(0);L=p>>>2|r<<30;M=r>>>2;N=t+2|0}}while(0);u=L|1;D=s+d|0;if(D>>>0>>0){p=u;r=M;s=D;t=N}else{W=M;X=u;Y=D;Z=N;break}}}else{W=0;X=1;Y=a;Z=1}_f(Y,d,e,X,W,Z,0,k);a=X;X=W;W=Y;Y=Z;while(1){if((Y|0)==1){if((a|0)==1){if((X|0)==0){break}else{_=52}}}else{_=52}if((_|0)==52?(_=0,(Y|0)>=2):0){Z=a>>>30;N=Y+ -2|0;M=(a<<1&2147483646|Z<<31)^3;t=(Z|X<<2)>>>1;_f(W+(0-((c[k+(N<<2)>>2]|0)+d))|0,d,e,M,t,Y+ -1|0,1,k);s=t<<1|Z&1;Z=M<<1|1;M=W+m|0;_f(M,d,e,Z,s,N,1,k);a=Z;X=s;W=M;Y=N;continue}N=a+ -1|0;if((N|0)!=0){if((N&1|0)==0){M=N;N=0;do{N=N+1|0;M=M>>>1}while((M&1|0)==0);if((N|0)!=0){$=N}else{_=57}}else{_=57}if((_|0)==57){_=0;if((X|0)!=0){if((X&1|0)==0){M=X;s=0;while(1){Z=s+1|0;t=M>>>1;if((t&1|0)==0){M=t;s=Z}else{ba=Z;break}}}else{ba=0}}else{ba=32}$=(ba|0)==0?0:ba+32|0}if($>>>0>31){ca=$;_=62}else{da=$;ea=a;fa=X;ga=$}}else{ca=32;_=62}if((_|0)==62){_=0;da=ca+ -32|0;ea=X;fa=0;ga=ca}a=fa<<32-da|ea>>>da;X=fa>>>da;W=W+m|0;Y=ga+Y|0}i=f;return}function _f(a,b,d,e,f,g,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0;k=i;i=i+752|0;l=k+232|0;m=k+488|0;n=k;c[n>>2]=a;o=0-b|0;a:do{if((e|0)==1&(f|0)==0){p=a;q=g;r=h;s=1;t=18}else{u=g;v=a;w=h;x=e;y=f;z=a;A=1;while(1){B=v+(0-(c[j+(u<<2)>>2]|0))|0;if((nb[d&7](B,z)|0)<1){p=v;q=u;r=w;s=A;t=18;break a}if((w|0)==0&(u|0)>1){C=c[j+(u+ -2<<2)>>2]|0;if((nb[d&7](v+o|0,B)|0)>-1){D=v;E=u;F=A;break a}if((nb[d&7](v+(0-(C+b))|0,B)|0)>-1){D=v;E=u;F=A;break a}}C=A+1|0;c[n+(A<<2)>>2]=B;G=x+ -1|0;if((G|0)!=0){if((G&1|0)==0){H=G;G=0;do{G=G+1|0;H=H>>>1}while((H&1|0)==0);if((G|0)!=0){I=G}else{t=10}}else{t=10}if((t|0)==10){t=0;if((y|0)!=0){if((y&1|0)==0){H=y;J=0;while(1){K=J+1|0;L=H>>>1;if((L&1|0)==0){H=L;J=K}else{M=K;break}}}else{M=0}}else{M=32}I=(M|0)==0?0:M+32|0}if(I>>>0>31){N=I;t=15}else{O=I;P=x;Q=y;R=I}}else{N=32;t=15}if((t|0)==15){t=0;O=N+ -32|0;P=y;Q=0;R=N}J=Q<<32-O|P>>>O;H=Q>>>O;G=R+u|0;if((J|0)==1&(H|0)==0){D=B;E=G;F=C;break a}u=G;v=B;w=0;x=J;y=H;z=c[n>>2]|0;A=C}}}while(0);if((t|0)==18){if((r|0)==0){D=p;E=q;F=s}else{i=k;return}}b:do{if((F|0)>=2?(s=n+(F<<2)|0,c[s>>2]=l,(b|0)!=0):0){if((F|0)>0){S=b;T=l}else{q=b>>>0>256?256:b;p=c[n>>2]|0;Kg(l|0,p|0,q|0)|0;if((q|0)==(b|0)){break}else{U=b;V=q}while(1){U=U-V|0;V=U>>>0>256?256:U;Kg(l|0,p|0,V|0)|0;if((U|0)==(V|0)){break b}}}while(1){p=S>>>0>256?256:S;q=c[n>>2]|0;Kg(T|0,q|0,p|0)|0;r=q;q=0;while(1){t=q+1|0;R=c[n+(t<<2)>>2]|0;Kg(r|0,R|0,p|0)|0;c[n+(q<<2)>>2]=r+p;if((t|0)==(F|0)){break}else{r=R;q=t}}if((S|0)==(p|0)){break b}S=S-p|0;T=c[s>>2]|0}}}while(0);c[l>>2]=D;c:do{if((E|0)>1){T=E;S=D;F=D;n=1;while(1){V=S+o|0;U=T+ -2|0;s=S+(0-((c[j+(U<<2)>>2]|0)+b))|0;if((nb[d&7](F,s)|0)>-1?(nb[d&7](F,V)|0)>-1:0){W=n;break}q=n+1|0;r=l+(n<<2)|0;if((nb[d&7](s,V)|0)>-1){c[r>>2]=s;X=s;Y=T+ -1|0}else{c[r>>2]=V;X=V;Y=U}if((Y|0)<=1){W=q;break}T=Y;S=X;F=c[l>>2]|0;n=q}if((W|0)>=2?(n=l+(W<<2)|0,c[n>>2]=m,(b|0)!=0):0){if((W|0)>0){Z=b;_=m}else{F=b>>>0>256?256:b;S=c[l>>2]|0;Kg(m|0,S|0,F|0)|0;if((F|0)==(b|0)){$=m;break}else{aa=b;ba=F}while(1){F=aa-ba|0;T=F>>>0>256?256:F;Kg(m|0,S|0,T|0)|0;if((F|0)==(T|0)){$=m;break c}else{aa=F;ba=T}}}while(1){S=Z>>>0>256?256:Z;T=c[l>>2]|0;Kg(_|0,T|0,S|0)|0;F=T;T=0;while(1){q=T+1|0;U=c[l+(q<<2)>>2]|0;Kg(F|0,U|0,S|0)|0;c[l+(T<<2)>>2]=F+S;if((q|0)==(W|0)){break}else{F=U;T=q}}if((Z|0)==(S|0)){$=m;break c}Z=Z-S|0;_=c[n>>2]|0}}else{$=m}}else{$=m}}while(0);i=k;return}function $f(b,c){b=b|0;c=c|0;var d=0,e=0;d=i;e=ag(b,c)|0;i=d;return((a[e]|0)==(c&255)<<24>>24?e:0)|0}function ag(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;f=d&255;if((f|0)==0){g=b+(Dg(b|0)|0)|0;i=e;return g|0}a:do{if((b&3|0)!=0){h=d&255;j=b;while(1){k=a[j]|0;if(k<<24>>24==0){g=j;l=13;break}m=j+1|0;if(k<<24>>24==h<<24>>24){g=j;l=13;break}if((m&3|0)==0){n=m;break a}else{j=m}}if((l|0)==13){i=e;return g|0}}else{n=b}}while(0);b=aa(f,16843009)|0;f=c[n>>2]|0;b:do{if(((f&-2139062144^-2139062144)&f+ -16843009|0)==0){l=f;j=n;while(1){h=l^b;m=j+4|0;if(((h&-2139062144^-2139062144)&h+ -16843009|0)!=0){o=j;break b}h=c[m>>2]|0;if(((h&-2139062144^-2139062144)&h+ -16843009|0)==0){l=h;j=m}else{o=m;break}}}else{o=n}}while(0);n=d&255;d=o;while(1){o=a[d]|0;if(o<<24>>24==0|o<<24>>24==n<<24>>24){g=d;break}else{d=d+1|0}}i=e;return g|0}function bg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+32|0;f=e;g=a[d]|0;if(!(g<<24>>24==0)?(a[d+1|0]|0)!=0:0){c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[f+24>>2]=0;c[f+28>>2]=0;h=d;d=g;do{j=d&255;k=f+(j>>>5<<2)|0;c[k>>2]=c[k>>2]|1<<(j&31);h=h+1|0;d=a[h]|0}while(!(d<<24>>24==0));d=a[b]|0;a:do{if(d<<24>>24==0){l=b}else{h=b;j=d;while(1){k=j&255;m=h+1|0;if((c[f+(k>>>5<<2)>>2]&1<<(k&31)|0)!=0){l=h;break a}k=a[m]|0;if(k<<24>>24==0){l=m;break}else{h=m;j=k}}}}while(0);n=l-b|0;i=e;return n|0}n=(ag(b,g<<24>>24)|0)-b|0;i=e;return n|0}function cg(a){a=a|0;var b=0,c=0,d=0,e=0;b=i;c=(Dg(a|0)|0)+1|0;d=gg(c)|0;if((d|0)==0){e=0;i=b;return e|0}Kg(d|0,a|0,c|0)|0;e=d;i=b;return e|0}function dg(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;f=b+(Dg(b|0)|0)|0;a:do{if((d|0)==0){g=f}else{h=d;j=c;k=f;while(1){l=a[j]|0;if(l<<24>>24==0){g=k;break a}m=h+ -1|0;n=k+1|0;a[k]=l;if((m|0)==0){g=n;break}else{h=m;j=j+1|0;k=n}}}}while(0);a[g]=0;i=e;return b|0}function eg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e;c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[f+24>>2]=0;c[f+28>>2]=0;g=a[d]|0;if(g<<24>>24==0){h=0;i=e;return h|0}if((a[d+1|0]|0)==0){j=b;while(1){if((a[j]|0)==g<<24>>24){j=j+1|0}else{break}}h=j-b|0;i=e;return h|0}else{k=d;l=g}do{g=l&255;d=f+(g>>>5<<2)|0;c[d>>2]=c[d>>2]|1<<(g&31);k=k+1|0;l=a[k]|0}while(!(l<<24>>24==0));l=a[b]|0;a:do{if(l<<24>>24==0){m=b}else{k=b;g=l;while(1){d=g&255;j=k+1|0;if((c[f+(d>>>5<<2)>>2]&1<<(d&31)|0)==0){m=k;break a}d=a[j]|0;if(d<<24>>24==0){m=j;break}else{k=j;g=d}}}}while(0);h=m-b|0;i=e;return h|0}function fg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;e=i;if((b|0)==0){f=c[6912]|0;if((f|0)==0){g=0;i=e;return g|0}else{h=f}}else{h=b}b=eg(h,d)|0;f=h+b|0;if((a[f]|0)==0){c[6912]=0;g=0;i=e;return g|0}j=(bg(f,d)|0)+b|0;b=h+j|0;c[6912]=b;if((a[b]|0)==0){c[6912]=0;g=f;i=e;return g|0}else{c[6912]=h+(j+1);a[b]=0;g=f;i=e;return g|0}return 0} + + + +function gg(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ja=0,Ka=0,La=0,Ma=0;b=i;do{if(a>>>0<245){if(a>>>0<11){d=16}else{d=a+11&-8}e=d>>>3;f=c[6914]|0;g=f>>>e;if((g&3|0)!=0){h=(g&1^1)+e|0;j=h<<1;k=27696+(j<<2)|0;l=27696+(j+2<<2)|0;j=c[l>>2]|0;m=j+8|0;n=c[m>>2]|0;do{if((k|0)!=(n|0)){if(n>>>0<(c[27672>>2]|0)>>>0){_a()}o=n+12|0;if((c[o>>2]|0)==(j|0)){c[o>>2]=k;c[l>>2]=n;break}else{_a()}}else{c[6914]=f&~(1<>2]=n|3;l=j+(n|4)|0;c[l>>2]=c[l>>2]|1;p=m;i=b;return p|0}if(d>>>0>(c[27664>>2]|0)>>>0){if((g|0)!=0){l=2<>>12&16;k=l>>>n;l=k>>>5&8;o=k>>>l;k=o>>>2&4;q=o>>>k;o=q>>>1&2;r=q>>>o;q=r>>>1&1;s=(l|n|k|o|q)+(r>>>q)|0;q=s<<1;r=27696+(q<<2)|0;o=27696+(q+2<<2)|0;q=c[o>>2]|0;k=q+8|0;n=c[k>>2]|0;do{if((r|0)!=(n|0)){if(n>>>0<(c[27672>>2]|0)>>>0){_a()}l=n+12|0;if((c[l>>2]|0)==(q|0)){c[l>>2]=r;c[o>>2]=n;break}else{_a()}}else{c[6914]=f&~(1<>2]=d|3;o=q+d|0;c[q+(d|4)>>2]=n|1;c[q+f>>2]=n;f=c[27664>>2]|0;if((f|0)!=0){r=c[27676>>2]|0;e=f>>>3;f=e<<1;g=27696+(f<<2)|0;m=c[6914]|0;j=1<>2]|0;if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{t=e;u=h}}else{c[6914]=m|j;t=27696+(f+2<<2)|0;u=g}c[t>>2]=r;c[u+12>>2]=r;c[r+8>>2]=u;c[r+12>>2]=g}c[27664>>2]=n;c[27676>>2]=o;p=k;i=b;return p|0}o=c[27660>>2]|0;if((o|0)!=0){n=(o&0-o)+ -1|0;o=n>>>12&16;g=n>>>o;n=g>>>5&8;r=g>>>n;g=r>>>2&4;f=r>>>g;r=f>>>1&2;j=f>>>r;f=j>>>1&1;m=c[27960+((n|o|g|r|f)+(j>>>f)<<2)>>2]|0;f=(c[m+4>>2]&-8)-d|0;j=m;r=m;while(1){m=c[j+16>>2]|0;if((m|0)==0){g=c[j+20>>2]|0;if((g|0)==0){break}else{v=g}}else{v=m}m=(c[v+4>>2]&-8)-d|0;g=m>>>0>>0;f=g?m:f;j=v;r=g?v:r}j=c[27672>>2]|0;if(r>>>0>>0){_a()}k=r+d|0;if(!(r>>>0>>0)){_a()}q=c[r+24>>2]|0;s=c[r+12>>2]|0;do{if((s|0)==(r|0)){g=r+20|0;m=c[g>>2]|0;if((m|0)==0){o=r+16|0;n=c[o>>2]|0;if((n|0)==0){w=0;break}else{x=n;y=o}}else{x=m;y=g}while(1){g=x+20|0;m=c[g>>2]|0;if((m|0)!=0){x=m;y=g;continue}g=x+16|0;m=c[g>>2]|0;if((m|0)==0){break}else{x=m;y=g}}if(y>>>0>>0){_a()}else{c[y>>2]=0;w=x;break}}else{g=c[r+8>>2]|0;if(g>>>0>>0){_a()}m=g+12|0;if((c[m>>2]|0)!=(r|0)){_a()}o=s+8|0;if((c[o>>2]|0)==(r|0)){c[m>>2]=s;c[o>>2]=g;w=s;break}else{_a()}}}while(0);do{if((q|0)!=0){s=c[r+28>>2]|0;j=27960+(s<<2)|0;if((r|0)==(c[j>>2]|0)){c[j>>2]=w;if((w|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}s=q+16|0;if((c[s>>2]|0)==(r|0)){c[s>>2]=w}else{c[q+20>>2]=w}if((w|0)==0){break}}if(w>>>0<(c[27672>>2]|0)>>>0){_a()}c[w+24>>2]=q;s=c[r+16>>2]|0;do{if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+16>>2]=s;c[s+24>>2]=w;break}}}while(0);s=c[r+20>>2]|0;if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+20>>2]=s;c[s+24>>2]=w;break}}}}while(0);if(f>>>0<16){q=f+d|0;c[r+4>>2]=q|3;s=r+(q+4)|0;c[s>>2]=c[s>>2]|1}else{c[r+4>>2]=d|3;c[r+(d|4)>>2]=f|1;c[r+(f+d)>>2]=f;s=c[27664>>2]|0;if((s|0)!=0){q=c[27676>>2]|0;j=s>>>3;s=j<<1;g=27696+(s<<2)|0;o=c[6914]|0;m=1<>2]|0;if(n>>>0<(c[27672>>2]|0)>>>0){_a()}else{z=j;A=n}}else{c[6914]=o|m;z=27696+(s+2<<2)|0;A=g}c[z>>2]=q;c[A+12>>2]=q;c[q+8>>2]=A;c[q+12>>2]=g}c[27664>>2]=f;c[27676>>2]=k}p=r+8|0;i=b;return p|0}else{B=d}}else{B=d}}else{if(!(a>>>0>4294967231)){g=a+11|0;q=g&-8;s=c[27660>>2]|0;if((s|0)!=0){m=0-q|0;o=g>>>8;if((o|0)!=0){if(q>>>0>16777215){C=31}else{g=(o+1048320|0)>>>16&8;n=o<>>16&4;j=n<>>16&2;h=14-(o|g|n)+(j<>>15)|0;C=q>>>(h+7|0)&1|h<<1}}else{C=0}h=c[27960+(C<<2)>>2]|0;a:do{if((h|0)==0){D=m;E=0;F=0}else{if((C|0)==31){G=0}else{G=25-(C>>>1)|0}n=m;j=0;g=q<>2]&-8;H=l-q|0;if(H>>>0>>0){if((l|0)==(q|0)){D=H;E=o;F=o;break a}else{I=H;J=o}}else{I=n;J=e}H=c[o+20>>2]|0;l=c[o+(g>>>31<<2)+16>>2]|0;K=(H|0)==0|(H|0)==(l|0)?j:H;if((l|0)==0){D=I;E=K;F=J;break}else{n=I;j=K;g=g<<1;o=l;e=J}}}}while(0);if((E|0)==0&(F|0)==0){h=2<>>12&16;r=h>>>m;h=r>>>5&8;k=r>>>h;r=k>>>2&4;f=k>>>r;k=f>>>1&2;e=f>>>k;f=e>>>1&1;L=c[27960+((h|m|r|k|f)+(e>>>f)<<2)>>2]|0}else{L=E}if((L|0)==0){M=D;N=F}else{f=D;e=L;k=F;while(1){r=(c[e+4>>2]&-8)-q|0;m=r>>>0>>0;h=m?r:f;r=m?e:k;m=c[e+16>>2]|0;if((m|0)!=0){f=h;e=m;k=r;continue}m=c[e+20>>2]|0;if((m|0)==0){M=h;N=r;break}else{f=h;e=m;k=r}}}if((N|0)!=0?M>>>0<((c[27664>>2]|0)-q|0)>>>0:0){k=c[27672>>2]|0;if(N>>>0>>0){_a()}e=N+q|0;if(!(N>>>0>>0)){_a()}f=c[N+24>>2]|0;s=c[N+12>>2]|0;do{if((s|0)==(N|0)){r=N+20|0;m=c[r>>2]|0;if((m|0)==0){h=N+16|0;o=c[h>>2]|0;if((o|0)==0){O=0;break}else{P=o;Q=h}}else{P=m;Q=r}while(1){r=P+20|0;m=c[r>>2]|0;if((m|0)!=0){P=m;Q=r;continue}r=P+16|0;m=c[r>>2]|0;if((m|0)==0){break}else{P=m;Q=r}}if(Q>>>0>>0){_a()}else{c[Q>>2]=0;O=P;break}}else{r=c[N+8>>2]|0;if(r>>>0>>0){_a()}m=r+12|0;if((c[m>>2]|0)!=(N|0)){_a()}h=s+8|0;if((c[h>>2]|0)==(N|0)){c[m>>2]=s;c[h>>2]=r;O=s;break}else{_a()}}}while(0);do{if((f|0)!=0){s=c[N+28>>2]|0;k=27960+(s<<2)|0;if((N|0)==(c[k>>2]|0)){c[k>>2]=O;if((O|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}s=f+16|0;if((c[s>>2]|0)==(N|0)){c[s>>2]=O}else{c[f+20>>2]=O}if((O|0)==0){break}}if(O>>>0<(c[27672>>2]|0)>>>0){_a()}c[O+24>>2]=f;s=c[N+16>>2]|0;do{if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[O+16>>2]=s;c[s+24>>2]=O;break}}}while(0);s=c[N+20>>2]|0;if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[O+20>>2]=s;c[s+24>>2]=O;break}}}}while(0);b:do{if(!(M>>>0<16)){c[N+4>>2]=q|3;c[N+(q|4)>>2]=M|1;c[N+(M+q)>>2]=M;f=M>>>3;if(M>>>0<256){s=f<<1;k=27696+(s<<2)|0;r=c[6914]|0;h=1<>2]|0;if(m>>>0<(c[27672>>2]|0)>>>0){_a()}else{R=f;S=m}}else{c[6914]=r|h;R=27696+(s+2<<2)|0;S=k}c[R>>2]=e;c[S+12>>2]=e;c[N+(q+8)>>2]=S;c[N+(q+12)>>2]=k;break}k=M>>>8;if((k|0)!=0){if(M>>>0>16777215){T=31}else{s=(k+1048320|0)>>>16&8;h=k<>>16&4;r=h<>>16&2;m=14-(k|s|h)+(r<>>15)|0;T=M>>>(m+7|0)&1|m<<1}}else{T=0}m=27960+(T<<2)|0;c[N+(q+28)>>2]=T;c[N+(q+20)>>2]=0;c[N+(q+16)>>2]=0;h=c[27660>>2]|0;r=1<>2]=h|r;c[m>>2]=e;c[N+(q+24)>>2]=m;c[N+(q+12)>>2]=e;c[N+(q+8)>>2]=e;break}r=c[m>>2]|0;if((T|0)==31){U=0}else{U=25-(T>>>1)|0}c:do{if((c[r+4>>2]&-8|0)!=(M|0)){m=M<>>31<<2)+16|0;s=c[V>>2]|0;if((s|0)==0){break}if((c[s+4>>2]&-8|0)==(M|0)){W=s;break c}else{m=m<<1;h=s}}if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[V>>2]=e;c[N+(q+24)>>2]=h;c[N+(q+12)>>2]=e;c[N+(q+8)>>2]=e;break b}}else{W=r}}while(0);r=W+8|0;m=c[r>>2]|0;s=c[27672>>2]|0;if(W>>>0>>0){_a()}if(m>>>0>>0){_a()}else{c[m+12>>2]=e;c[r>>2]=e;c[N+(q+8)>>2]=m;c[N+(q+12)>>2]=W;c[N+(q+24)>>2]=0;break}}else{m=M+q|0;c[N+4>>2]=m|3;r=N+(m+4)|0;c[r>>2]=c[r>>2]|1}}while(0);p=N+8|0;i=b;return p|0}else{B=q}}else{B=q}}else{B=-1}}}while(0);N=c[27664>>2]|0;if(!(B>>>0>N>>>0)){M=N-B|0;W=c[27676>>2]|0;if(M>>>0>15){c[27676>>2]=W+B;c[27664>>2]=M;c[W+(B+4)>>2]=M|1;c[W+N>>2]=M;c[W+4>>2]=B|3}else{c[27664>>2]=0;c[27676>>2]=0;c[W+4>>2]=N|3;M=W+(N+4)|0;c[M>>2]=c[M>>2]|1}p=W+8|0;i=b;return p|0}W=c[27668>>2]|0;if(B>>>0>>0){M=W-B|0;c[27668>>2]=M;W=c[27680>>2]|0;c[27680>>2]=W+B;c[W+(B+4)>>2]=M|1;c[W+4>>2]=B|3;p=W+8|0;i=b;return p|0}do{if((c[7032]|0)==0){W=Ia(30)|0;if((W+ -1&W|0)==0){c[28136>>2]=W;c[28132>>2]=W;c[28140>>2]=-1;c[28144>>2]=-1;c[28148>>2]=0;c[28100>>2]=0;c[7032]=(bb(0)|0)&-16^1431655768;break}else{_a()}}}while(0);W=B+48|0;M=c[28136>>2]|0;N=B+47|0;V=M+N|0;U=0-M|0;M=V&U;if(!(M>>>0>B>>>0)){p=0;i=b;return p|0}T=c[28096>>2]|0;if((T|0)!=0?(S=c[28088>>2]|0,R=S+M|0,R>>>0<=S>>>0|R>>>0>T>>>0):0){p=0;i=b;return p|0}d:do{if((c[28100>>2]&4|0)==0){T=c[27680>>2]|0;e:do{if((T|0)!=0){R=28104|0;while(1){S=c[R>>2]|0;if(!(S>>>0>T>>>0)?(X=R+4|0,(S+(c[X>>2]|0)|0)>>>0>T>>>0):0){break}S=c[R+8>>2]|0;if((S|0)==0){Y=182;break e}else{R=S}}if((R|0)!=0){S=V-(c[27668>>2]|0)&U;if(S>>>0<2147483647){O=Ca(S|0)|0;P=(O|0)==((c[R>>2]|0)+(c[X>>2]|0)|0);Z=O;_=S;$=P?O:-1;aa=P?S:0;Y=191}else{ba=0}}else{Y=182}}else{Y=182}}while(0);do{if((Y|0)==182){T=Ca(0)|0;if((T|0)!=(-1|0)){q=T;S=c[28132>>2]|0;P=S+ -1|0;if((P&q|0)==0){ca=M}else{ca=M-q+(P+q&0-S)|0}S=c[28088>>2]|0;q=S+ca|0;if(ca>>>0>B>>>0&ca>>>0<2147483647){P=c[28096>>2]|0;if((P|0)!=0?q>>>0<=S>>>0|q>>>0>P>>>0:0){ba=0;break}P=Ca(ca|0)|0;q=(P|0)==(T|0);Z=P;_=ca;$=q?T:-1;aa=q?ca:0;Y=191}else{ba=0}}else{ba=0}}}while(0);f:do{if((Y|0)==191){q=0-_|0;if(($|0)!=(-1|0)){da=$;ea=aa;Y=202;break d}do{if((Z|0)!=(-1|0)&_>>>0<2147483647&_>>>0>>0?(T=c[28136>>2]|0,P=N-_+T&0-T,P>>>0<2147483647):0){if((Ca(P|0)|0)==(-1|0)){Ca(q|0)|0;ba=aa;break f}else{fa=P+_|0;break}}else{fa=_}}while(0);if((Z|0)==(-1|0)){ba=aa}else{da=Z;ea=fa;Y=202;break d}}}while(0);c[28100>>2]=c[28100>>2]|4;ga=ba;Y=199}else{ga=0;Y=199}}while(0);if((((Y|0)==199?M>>>0<2147483647:0)?(ba=Ca(M|0)|0,M=Ca(0)|0,(M|0)!=(-1|0)&(ba|0)!=(-1|0)&ba>>>0>>0):0)?(fa=M-ba|0,M=fa>>>0>(B+40|0)>>>0,M):0){da=ba;ea=M?fa:ga;Y=202}if((Y|0)==202){ga=(c[28088>>2]|0)+ea|0;c[28088>>2]=ga;if(ga>>>0>(c[28092>>2]|0)>>>0){c[28092>>2]=ga}ga=c[27680>>2]|0;g:do{if((ga|0)!=0){fa=28104|0;while(1){ha=c[fa>>2]|0;ia=fa+4|0;ja=c[ia>>2]|0;if((da|0)==(ha+ja|0)){Y=214;break}M=c[fa+8>>2]|0;if((M|0)==0){break}else{fa=M}}if(((Y|0)==214?(c[fa+12>>2]&8|0)==0:0)?ga>>>0>=ha>>>0&ga>>>0>>0:0){c[ia>>2]=ja+ea;M=(c[27668>>2]|0)+ea|0;ba=ga+8|0;if((ba&7|0)==0){ka=0}else{ka=0-ba&7}ba=M-ka|0;c[27680>>2]=ga+ka;c[27668>>2]=ba;c[ga+(ka+4)>>2]=ba|1;c[ga+(M+4)>>2]=40;c[27684>>2]=c[28144>>2];break}if(da>>>0<(c[27672>>2]|0)>>>0){c[27672>>2]=da}M=da+ea|0;ba=28104|0;while(1){if((c[ba>>2]|0)==(M|0)){Y=224;break}Z=c[ba+8>>2]|0;if((Z|0)==0){break}else{ba=Z}}if((Y|0)==224?(c[ba+12>>2]&8|0)==0:0){c[ba>>2]=da;M=ba+4|0;c[M>>2]=(c[M>>2]|0)+ea;M=da+8|0;if((M&7|0)==0){la=0}else{la=0-M&7}M=da+(ea+8)|0;if((M&7|0)==0){ma=0}else{ma=0-M&7}M=da+(ma+ea)|0;fa=la+B|0;Z=da+fa|0;aa=M-(da+la)-B|0;c[da+(la+4)>>2]=B|3;h:do{if((M|0)!=(c[27680>>2]|0)){if((M|0)==(c[27676>>2]|0)){_=(c[27664>>2]|0)+aa|0;c[27664>>2]=_;c[27676>>2]=Z;c[da+(fa+4)>>2]=_|1;c[da+(_+fa)>>2]=_;break}_=ea+4|0;N=c[da+(_+ma)>>2]|0;if((N&3|0)==1){W=N&-8;$=N>>>3;do{if(!(N>>>0<256)){ca=c[da+((ma|24)+ea)>>2]|0;X=c[da+(ea+12+ma)>>2]|0;do{if((X|0)==(M|0)){U=ma|16;V=da+(_+U)|0;q=c[V>>2]|0;if((q|0)==0){R=da+(U+ea)|0;U=c[R>>2]|0;if((U|0)==0){na=0;break}else{oa=U;pa=R}}else{oa=q;pa=V}while(1){V=oa+20|0;q=c[V>>2]|0;if((q|0)!=0){oa=q;pa=V;continue}V=oa+16|0;q=c[V>>2]|0;if((q|0)==0){break}else{oa=q;pa=V}}if(pa>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[pa>>2]=0;na=oa;break}}else{V=c[da+((ma|8)+ea)>>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}q=V+12|0;if((c[q>>2]|0)!=(M|0)){_a()}R=X+8|0;if((c[R>>2]|0)==(M|0)){c[q>>2]=X;c[R>>2]=V;na=X;break}else{_a()}}}while(0);if((ca|0)!=0){X=c[da+(ea+28+ma)>>2]|0;h=27960+(X<<2)|0;if((M|0)==(c[h>>2]|0)){c[h>>2]=na;if((na|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}X=ca+16|0;if((c[X>>2]|0)==(M|0)){c[X>>2]=na}else{c[ca+20>>2]=na}if((na|0)==0){break}}if(na>>>0<(c[27672>>2]|0)>>>0){_a()}c[na+24>>2]=ca;X=ma|16;h=c[da+(X+ea)>>2]|0;do{if((h|0)!=0){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[na+16>>2]=h;c[h+24>>2]=na;break}}}while(0);h=c[da+(_+X)>>2]|0;if((h|0)!=0){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[na+20>>2]=h;c[h+24>>2]=na;break}}}}else{h=c[da+((ma|8)+ea)>>2]|0;ca=c[da+(ea+12+ma)>>2]|0;V=27696+($<<1<<2)|0;if((h|0)!=(V|0)){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}if((c[h+12>>2]|0)!=(M|0)){_a()}}if((ca|0)==(h|0)){c[6914]=c[6914]&~(1<<$);break}if((ca|0)!=(V|0)){if(ca>>>0<(c[27672>>2]|0)>>>0){_a()}V=ca+8|0;if((c[V>>2]|0)==(M|0)){qa=V}else{_a()}}else{qa=ca+8|0}c[h+12>>2]=ca;c[qa>>2]=h}}while(0);ra=da+((W|ma)+ea)|0;sa=W+aa|0}else{ra=M;sa=aa}$=ra+4|0;c[$>>2]=c[$>>2]&-2;c[da+(fa+4)>>2]=sa|1;c[da+(sa+fa)>>2]=sa;$=sa>>>3;if(sa>>>0<256){_=$<<1;N=27696+(_<<2)|0;h=c[6914]|0;ca=1<<$;if((h&ca|0)!=0){$=27696+(_+2<<2)|0;V=c[$>>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{ta=$;ua=V}}else{c[6914]=h|ca;ta=27696+(_+2<<2)|0;ua=N}c[ta>>2]=Z;c[ua+12>>2]=Z;c[da+(fa+8)>>2]=ua;c[da+(fa+12)>>2]=N;break}N=sa>>>8;if((N|0)!=0){if(sa>>>0>16777215){va=31}else{_=(N+1048320|0)>>>16&8;ca=N<<_;N=(ca+520192|0)>>>16&4;h=ca<>>16&2;V=14-(N|_|ca)+(h<>>15)|0;va=sa>>>(V+7|0)&1|V<<1}}else{va=0}V=27960+(va<<2)|0;c[da+(fa+28)>>2]=va;c[da+(fa+20)>>2]=0;c[da+(fa+16)>>2]=0;ca=c[27660>>2]|0;h=1<>2]=ca|h;c[V>>2]=Z;c[da+(fa+24)>>2]=V;c[da+(fa+12)>>2]=Z;c[da+(fa+8)>>2]=Z;break}h=c[V>>2]|0;if((va|0)==31){wa=0}else{wa=25-(va>>>1)|0}i:do{if((c[h+4>>2]&-8|0)!=(sa|0)){V=sa<>>31<<2)+16|0;_=c[xa>>2]|0;if((_|0)==0){break}if((c[_+4>>2]&-8|0)==(sa|0)){ya=_;break i}else{V=V<<1;ca=_}}if(xa>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[xa>>2]=Z;c[da+(fa+24)>>2]=ca;c[da+(fa+12)>>2]=Z;c[da+(fa+8)>>2]=Z;break h}}else{ya=h}}while(0);h=ya+8|0;W=c[h>>2]|0;V=c[27672>>2]|0;if(ya>>>0>>0){_a()}if(W>>>0>>0){_a()}else{c[W+12>>2]=Z;c[h>>2]=Z;c[da+(fa+8)>>2]=W;c[da+(fa+12)>>2]=ya;c[da+(fa+24)>>2]=0;break}}else{W=(c[27668>>2]|0)+aa|0;c[27668>>2]=W;c[27680>>2]=Z;c[da+(fa+4)>>2]=W|1}}while(0);p=da+(la|8)|0;i=b;return p|0}fa=28104|0;while(1){za=c[fa>>2]|0;if(!(za>>>0>ga>>>0)?(Aa=c[fa+4>>2]|0,Ba=za+Aa|0,Ba>>>0>ga>>>0):0){break}fa=c[fa+8>>2]|0}fa=za+(Aa+ -39)|0;if((fa&7|0)==0){Da=0}else{Da=0-fa&7}fa=za+(Aa+ -47+Da)|0;Z=fa>>>0<(ga+16|0)>>>0?ga:fa;fa=Z+8|0;aa=da+8|0;if((aa&7|0)==0){Ea=0}else{Ea=0-aa&7}aa=ea+ -40-Ea|0;c[27680>>2]=da+Ea;c[27668>>2]=aa;c[da+(Ea+4)>>2]=aa|1;c[da+(ea+ -36)>>2]=40;c[27684>>2]=c[28144>>2];c[Z+4>>2]=27;c[fa+0>>2]=c[28104>>2];c[fa+4>>2]=c[28108>>2];c[fa+8>>2]=c[28112>>2];c[fa+12>>2]=c[28116>>2];c[28104>>2]=da;c[28108>>2]=ea;c[28116>>2]=0;c[28112>>2]=fa;fa=Z+28|0;c[fa>>2]=7;if((Z+32|0)>>>0>>0){aa=fa;while(1){fa=aa+4|0;c[fa>>2]=7;if((aa+8|0)>>>0>>0){aa=fa}else{break}}}if((Z|0)!=(ga|0)){aa=Z-ga|0;fa=ga+(aa+4)|0;c[fa>>2]=c[fa>>2]&-2;c[ga+4>>2]=aa|1;c[ga+aa>>2]=aa;fa=aa>>>3;if(aa>>>0<256){M=fa<<1;ba=27696+(M<<2)|0;W=c[6914]|0;h=1<>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{Fa=fa;Ga=V}}else{c[6914]=W|h;Fa=27696+(M+2<<2)|0;Ga=ba}c[Fa>>2]=ga;c[Ga+12>>2]=ga;c[ga+8>>2]=Ga;c[ga+12>>2]=ba;break}ba=aa>>>8;if((ba|0)!=0){if(aa>>>0>16777215){Ha=31}else{M=(ba+1048320|0)>>>16&8;h=ba<>>16&4;W=h<>>16&2;V=14-(ba|M|h)+(W<>>15)|0;Ha=aa>>>(V+7|0)&1|V<<1}}else{Ha=0}V=27960+(Ha<<2)|0;c[ga+28>>2]=Ha;c[ga+20>>2]=0;c[ga+16>>2]=0;h=c[27660>>2]|0;W=1<>2]=h|W;c[V>>2]=ga;c[ga+24>>2]=V;c[ga+12>>2]=ga;c[ga+8>>2]=ga;break}W=c[V>>2]|0;if((Ha|0)==31){Ja=0}else{Ja=25-(Ha>>>1)|0}j:do{if((c[W+4>>2]&-8|0)!=(aa|0)){V=aa<>>31<<2)+16|0;M=c[Ka>>2]|0;if((M|0)==0){break}if((c[M+4>>2]&-8|0)==(aa|0)){La=M;break j}else{V=V<<1;h=M}}if(Ka>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[Ka>>2]=ga;c[ga+24>>2]=h;c[ga+12>>2]=ga;c[ga+8>>2]=ga;break g}}else{La=W}}while(0);W=La+8|0;aa=c[W>>2]|0;Z=c[27672>>2]|0;if(La>>>0>>0){_a()}if(aa>>>0>>0){_a()}else{c[aa+12>>2]=ga;c[W>>2]=ga;c[ga+8>>2]=aa;c[ga+12>>2]=La;c[ga+24>>2]=0;break}}}else{aa=c[27672>>2]|0;if((aa|0)==0|da>>>0>>0){c[27672>>2]=da}c[28104>>2]=da;c[28108>>2]=ea;c[28116>>2]=0;c[27692>>2]=c[7032];c[27688>>2]=-1;aa=0;do{W=aa<<1;Z=27696+(W<<2)|0;c[27696+(W+3<<2)>>2]=Z;c[27696+(W+2<<2)>>2]=Z;aa=aa+1|0}while((aa|0)!=32);aa=da+8|0;if((aa&7|0)==0){Ma=0}else{Ma=0-aa&7}aa=ea+ -40-Ma|0;c[27680>>2]=da+Ma;c[27668>>2]=aa;c[da+(Ma+4)>>2]=aa|1;c[da+(ea+ -36)>>2]=40;c[27684>>2]=c[28144>>2]}}while(0);ea=c[27668>>2]|0;if(ea>>>0>B>>>0){da=ea-B|0;c[27668>>2]=da;ea=c[27680>>2]|0;c[27680>>2]=ea+B;c[ea+(B+4)>>2]=da|1;c[ea+4>>2]=B|3;p=ea+8|0;i=b;return p|0}}c[(Sa()|0)>>2]=12;p=0;i=b;return p|0}function hg(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0;b=i;if((a|0)==0){i=b;return}d=a+ -8|0;e=c[27672>>2]|0;if(d>>>0>>0){_a()}f=c[a+ -4>>2]|0;g=f&3;if((g|0)==1){_a()}h=f&-8;j=a+(h+ -8)|0;do{if((f&1|0)==0){k=c[d>>2]|0;if((g|0)==0){i=b;return}l=-8-k|0;m=a+l|0;n=k+h|0;if(m>>>0>>0){_a()}if((m|0)==(c[27676>>2]|0)){o=a+(h+ -4)|0;if((c[o>>2]&3|0)!=3){p=m;q=n;break}c[27664>>2]=n;c[o>>2]=c[o>>2]&-2;c[a+(l+4)>>2]=n|1;c[j>>2]=n;i=b;return}o=k>>>3;if(k>>>0<256){k=c[a+(l+8)>>2]|0;r=c[a+(l+12)>>2]|0;s=27696+(o<<1<<2)|0;if((k|0)!=(s|0)){if(k>>>0>>0){_a()}if((c[k+12>>2]|0)!=(m|0)){_a()}}if((r|0)==(k|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}s=r+8|0;if((c[s>>2]|0)==(m|0)){t=s}else{_a()}}else{t=r+8|0}c[k+12>>2]=r;c[t>>2]=k;p=m;q=n;break}k=c[a+(l+24)>>2]|0;r=c[a+(l+12)>>2]|0;do{if((r|0)==(m|0)){s=a+(l+20)|0;o=c[s>>2]|0;if((o|0)==0){u=a+(l+16)|0;v=c[u>>2]|0;if((v|0)==0){w=0;break}else{x=v;y=u}}else{x=o;y=s}while(1){s=x+20|0;o=c[s>>2]|0;if((o|0)!=0){x=o;y=s;continue}s=x+16|0;o=c[s>>2]|0;if((o|0)==0){break}else{x=o;y=s}}if(y>>>0>>0){_a()}else{c[y>>2]=0;w=x;break}}else{s=c[a+(l+8)>>2]|0;if(s>>>0>>0){_a()}o=s+12|0;if((c[o>>2]|0)!=(m|0)){_a()}u=r+8|0;if((c[u>>2]|0)==(m|0)){c[o>>2]=r;c[u>>2]=s;w=r;break}else{_a()}}}while(0);if((k|0)!=0){r=c[a+(l+28)>>2]|0;s=27960+(r<<2)|0;if((m|0)==(c[s>>2]|0)){c[s>>2]=w;if((w|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}r=k+16|0;if((c[r>>2]|0)==(m|0)){c[r>>2]=w}else{c[k+20>>2]=w}if((w|0)==0){p=m;q=n;break}}if(w>>>0<(c[27672>>2]|0)>>>0){_a()}c[w+24>>2]=k;r=c[a+(l+16)>>2]|0;do{if((r|0)!=0){if(r>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+16>>2]=r;c[r+24>>2]=w;break}}}while(0);r=c[a+(l+20)>>2]|0;if((r|0)!=0){if(r>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+20>>2]=r;c[r+24>>2]=w;p=m;q=n;break}}else{p=m;q=n}}else{p=m;q=n}}else{p=d;q=h}}while(0);if(!(p>>>0>>0)){_a()}d=a+(h+ -4)|0;w=c[d>>2]|0;if((w&1|0)==0){_a()}if((w&2|0)==0){if((j|0)==(c[27680>>2]|0)){e=(c[27668>>2]|0)+q|0;c[27668>>2]=e;c[27680>>2]=p;c[p+4>>2]=e|1;if((p|0)!=(c[27676>>2]|0)){i=b;return}c[27676>>2]=0;c[27664>>2]=0;i=b;return}if((j|0)==(c[27676>>2]|0)){e=(c[27664>>2]|0)+q|0;c[27664>>2]=e;c[27676>>2]=p;c[p+4>>2]=e|1;c[p+e>>2]=e;i=b;return}e=(w&-8)+q|0;x=w>>>3;do{if(!(w>>>0<256)){y=c[a+(h+16)>>2]|0;t=c[a+(h|4)>>2]|0;do{if((t|0)==(j|0)){g=a+(h+12)|0;f=c[g>>2]|0;if((f|0)==0){r=a+(h+8)|0;k=c[r>>2]|0;if((k|0)==0){z=0;break}else{A=k;B=r}}else{A=f;B=g}while(1){g=A+20|0;f=c[g>>2]|0;if((f|0)!=0){A=f;B=g;continue}g=A+16|0;f=c[g>>2]|0;if((f|0)==0){break}else{A=f;B=g}}if(B>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[B>>2]=0;z=A;break}}else{g=c[a+h>>2]|0;if(g>>>0<(c[27672>>2]|0)>>>0){_a()}f=g+12|0;if((c[f>>2]|0)!=(j|0)){_a()}r=t+8|0;if((c[r>>2]|0)==(j|0)){c[f>>2]=t;c[r>>2]=g;z=t;break}else{_a()}}}while(0);if((y|0)!=0){t=c[a+(h+20)>>2]|0;n=27960+(t<<2)|0;if((j|0)==(c[n>>2]|0)){c[n>>2]=z;if((z|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}t=y+16|0;if((c[t>>2]|0)==(j|0)){c[t>>2]=z}else{c[y+20>>2]=z}if((z|0)==0){break}}if(z>>>0<(c[27672>>2]|0)>>>0){_a()}c[z+24>>2]=y;t=c[a+(h+8)>>2]|0;do{if((t|0)!=0){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[z+16>>2]=t;c[t+24>>2]=z;break}}}while(0);t=c[a+(h+12)>>2]|0;if((t|0)!=0){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[z+20>>2]=t;c[t+24>>2]=z;break}}}}else{t=c[a+h>>2]|0;y=c[a+(h|4)>>2]|0;n=27696+(x<<1<<2)|0;if((t|0)!=(n|0)){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}if((c[t+12>>2]|0)!=(j|0)){_a()}}if((y|0)==(t|0)){c[6914]=c[6914]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}n=y+8|0;if((c[n>>2]|0)==(j|0)){C=n}else{_a()}}else{C=y+8|0}c[t+12>>2]=y;c[C>>2]=t}}while(0);c[p+4>>2]=e|1;c[p+e>>2]=e;if((p|0)==(c[27676>>2]|0)){c[27664>>2]=e;i=b;return}else{D=e}}else{c[d>>2]=w&-2;c[p+4>>2]=q|1;c[p+q>>2]=q;D=q}q=D>>>3;if(D>>>0<256){w=q<<1;d=27696+(w<<2)|0;e=c[6914]|0;C=1<>2]|0;if(j>>>0<(c[27672>>2]|0)>>>0){_a()}else{E=q;F=j}}else{c[6914]=e|C;E=27696+(w+2<<2)|0;F=d}c[E>>2]=p;c[F+12>>2]=p;c[p+8>>2]=F;c[p+12>>2]=d;i=b;return}d=D>>>8;if((d|0)!=0){if(D>>>0>16777215){G=31}else{F=(d+1048320|0)>>>16&8;E=d<>>16&4;w=E<>>16&2;C=14-(d|F|E)+(w<>>15)|0;G=D>>>(C+7|0)&1|C<<1}}else{G=0}C=27960+(G<<2)|0;c[p+28>>2]=G;c[p+20>>2]=0;c[p+16>>2]=0;E=c[27660>>2]|0;w=1<>2]|0;if((G|0)==31){H=0}else{H=25-(G>>>1)|0}b:do{if((c[F+4>>2]&-8|0)!=(D|0)){d=D<>>31<<2)+16|0;j=c[I>>2]|0;if((j|0)==0){break}if((c[j+4>>2]&-8|0)==(D|0)){J=j;break b}else{d=d<<1;e=j}}if(I>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[I>>2]=p;c[p+24>>2]=e;c[p+12>>2]=p;c[p+8>>2]=p;break a}}else{J=F}}while(0);F=J+8|0;d=c[F>>2]|0;j=c[27672>>2]|0;if(J>>>0>>0){_a()}if(d>>>0>>0){_a()}else{c[d+12>>2]=p;c[F>>2]=p;c[p+8>>2]=d;c[p+12>>2]=J;c[p+24>>2]=0;break}}else{c[27660>>2]=E|w;c[C>>2]=p;c[p+24>>2]=C;c[p+12>>2]=p;c[p+8>>2]=p}}while(0);p=(c[27688>>2]|0)+ -1|0;c[27688>>2]=p;if((p|0)==0){K=28112|0}else{i=b;return}while(1){p=c[K>>2]|0;if((p|0)==0){break}else{K=p+8|0}}c[27688>>2]=-1;i=b;return}function ig(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;if((a|0)!=0){e=aa(b,a)|0;if((b|a)>>>0>65535){f=((e>>>0)/(a>>>0)|0|0)==(b|0)?e:-1}else{f=e}}else{f=0}e=gg(f)|0;if((e|0)==0){i=d;return e|0}if((c[e+ -4>>2]&3|0)==0){i=d;return e|0}Eg(e|0,0,f|0)|0;i=d;return e|0}function jg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;do{if((a|0)!=0){if(b>>>0>4294967231){c[(Sa()|0)>>2]=12;e=0;break}if(b>>>0<11){f=16}else{f=b+11&-8}g=kg(a+ -8|0,f)|0;if((g|0)!=0){e=g+8|0;break}g=gg(b)|0;if((g|0)==0){e=0}else{h=c[a+ -4>>2]|0;j=(h&-8)-((h&3|0)==0?8:4)|0;Kg(g|0,a|0,(j>>>0>>0?j:b)|0)|0;hg(a);e=g}}else{e=gg(b)|0}}while(0);i=d;return e|0}function kg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;d=i;e=a+4|0;f=c[e>>2]|0;g=f&-8;h=a+g|0;j=c[27672>>2]|0;if(a>>>0>>0){_a()}k=f&3;if(!((k|0)!=1&a>>>0>>0)){_a()}l=a+(g|4)|0;m=c[l>>2]|0;if((m&1|0)==0){_a()}if((k|0)==0){if(b>>>0<256){n=0;i=d;return n|0}if(!(g>>>0<(b+4|0)>>>0)?!((g-b|0)>>>0>c[28136>>2]<<1>>>0):0){n=a;i=d;return n|0}n=0;i=d;return n|0}if(!(g>>>0>>0)){k=g-b|0;if(!(k>>>0>15)){n=a;i=d;return n|0}c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=k|3;c[l>>2]=c[l>>2]|1;lg(a+b|0,k);n=a;i=d;return n|0}if((h|0)==(c[27680>>2]|0)){k=(c[27668>>2]|0)+g|0;if(!(k>>>0>b>>>0)){n=0;i=d;return n|0}l=k-b|0;c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=l|1;c[27680>>2]=a+b;c[27668>>2]=l;n=a;i=d;return n|0}if((h|0)==(c[27676>>2]|0)){l=(c[27664>>2]|0)+g|0;if(l>>>0>>0){n=0;i=d;return n|0}k=l-b|0;if(k>>>0>15){c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=k|1;c[a+l>>2]=k;o=a+(l+4)|0;c[o>>2]=c[o>>2]&-2;p=a+b|0;q=k}else{c[e>>2]=f&1|l|2;f=a+(l+4)|0;c[f>>2]=c[f>>2]|1;p=0;q=0}c[27664>>2]=q;c[27676>>2]=p;n=a;i=d;return n|0}if((m&2|0)!=0){n=0;i=d;return n|0}p=(m&-8)+g|0;if(p>>>0>>0){n=0;i=d;return n|0}q=p-b|0;f=m>>>3;do{if(!(m>>>0<256)){l=c[a+(g+24)>>2]|0;k=c[a+(g+12)>>2]|0;do{if((k|0)==(h|0)){o=a+(g+20)|0;r=c[o>>2]|0;if((r|0)==0){s=a+(g+16)|0;t=c[s>>2]|0;if((t|0)==0){u=0;break}else{v=t;w=s}}else{v=r;w=o}while(1){o=v+20|0;r=c[o>>2]|0;if((r|0)!=0){v=r;w=o;continue}o=v+16|0;r=c[o>>2]|0;if((r|0)==0){break}else{v=r;w=o}}if(w>>>0>>0){_a()}else{c[w>>2]=0;u=v;break}}else{o=c[a+(g+8)>>2]|0;if(o>>>0>>0){_a()}r=o+12|0;if((c[r>>2]|0)!=(h|0)){_a()}s=k+8|0;if((c[s>>2]|0)==(h|0)){c[r>>2]=k;c[s>>2]=o;u=k;break}else{_a()}}}while(0);if((l|0)!=0){k=c[a+(g+28)>>2]|0;o=27960+(k<<2)|0;if((h|0)==(c[o>>2]|0)){c[o>>2]=u;if((u|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}k=l+16|0;if((c[k>>2]|0)==(h|0)){c[k>>2]=u}else{c[l+20>>2]=u}if((u|0)==0){break}}if(u>>>0<(c[27672>>2]|0)>>>0){_a()}c[u+24>>2]=l;k=c[a+(g+16)>>2]|0;do{if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+16>>2]=k;c[k+24>>2]=u;break}}}while(0);k=c[a+(g+20)>>2]|0;if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+20>>2]=k;c[k+24>>2]=u;break}}}}else{k=c[a+(g+8)>>2]|0;l=c[a+(g+12)>>2]|0;o=27696+(f<<1<<2)|0;if((k|0)!=(o|0)){if(k>>>0>>0){_a()}if((c[k+12>>2]|0)!=(h|0)){_a()}}if((l|0)==(k|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}o=l+8|0;if((c[o>>2]|0)==(h|0)){x=o}else{_a()}}else{x=l+8|0}c[k+12>>2]=l;c[x>>2]=k}}while(0);if(q>>>0<16){c[e>>2]=p|c[e>>2]&1|2;x=a+(p|4)|0;c[x>>2]=c[x>>2]|1;n=a;i=d;return n|0}else{c[e>>2]=c[e>>2]&1|b|2;c[a+(b+4)>>2]=q|3;e=a+(p|4)|0;c[e>>2]=c[e>>2]|1;lg(a+b|0,q);n=a;i=d;return n|0}return 0}function lg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;d=i;e=a+b|0;f=c[a+4>>2]|0;do{if((f&1|0)==0){g=c[a>>2]|0;if((f&3|0)==0){i=d;return}h=a+(0-g)|0;j=g+b|0;k=c[27672>>2]|0;if(h>>>0>>0){_a()}if((h|0)==(c[27676>>2]|0)){l=a+(b+4)|0;if((c[l>>2]&3|0)!=3){m=h;n=j;break}c[27664>>2]=j;c[l>>2]=c[l>>2]&-2;c[a+(4-g)>>2]=j|1;c[e>>2]=j;i=d;return}l=g>>>3;if(g>>>0<256){o=c[a+(8-g)>>2]|0;p=c[a+(12-g)>>2]|0;q=27696+(l<<1<<2)|0;if((o|0)!=(q|0)){if(o>>>0>>0){_a()}if((c[o+12>>2]|0)!=(h|0)){_a()}}if((p|0)==(o|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}q=p+8|0;if((c[q>>2]|0)==(h|0)){r=q}else{_a()}}else{r=p+8|0}c[o+12>>2]=p;c[r>>2]=o;m=h;n=j;break}o=c[a+(24-g)>>2]|0;p=c[a+(12-g)>>2]|0;do{if((p|0)==(h|0)){q=16-g|0;l=a+(q+4)|0;s=c[l>>2]|0;if((s|0)==0){t=a+q|0;q=c[t>>2]|0;if((q|0)==0){u=0;break}else{v=q;w=t}}else{v=s;w=l}while(1){l=v+20|0;s=c[l>>2]|0;if((s|0)!=0){v=s;w=l;continue}l=v+16|0;s=c[l>>2]|0;if((s|0)==0){break}else{v=s;w=l}}if(w>>>0>>0){_a()}else{c[w>>2]=0;u=v;break}}else{l=c[a+(8-g)>>2]|0;if(l>>>0>>0){_a()}s=l+12|0;if((c[s>>2]|0)!=(h|0)){_a()}t=p+8|0;if((c[t>>2]|0)==(h|0)){c[s>>2]=p;c[t>>2]=l;u=p;break}else{_a()}}}while(0);if((o|0)!=0){p=c[a+(28-g)>>2]|0;k=27960+(p<<2)|0;if((h|0)==(c[k>>2]|0)){c[k>>2]=u;if((u|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}p=o+16|0;if((c[p>>2]|0)==(h|0)){c[p>>2]=u}else{c[o+20>>2]=u}if((u|0)==0){m=h;n=j;break}}if(u>>>0<(c[27672>>2]|0)>>>0){_a()}c[u+24>>2]=o;p=16-g|0;k=c[a+p>>2]|0;do{if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+16>>2]=k;c[k+24>>2]=u;break}}}while(0);k=c[a+(p+4)>>2]|0;if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+20>>2]=k;c[k+24>>2]=u;m=h;n=j;break}}else{m=h;n=j}}else{m=h;n=j}}else{m=a;n=b}}while(0);u=c[27672>>2]|0;if(e>>>0>>0){_a()}v=a+(b+4)|0;w=c[v>>2]|0;if((w&2|0)==0){if((e|0)==(c[27680>>2]|0)){r=(c[27668>>2]|0)+n|0;c[27668>>2]=r;c[27680>>2]=m;c[m+4>>2]=r|1;if((m|0)!=(c[27676>>2]|0)){i=d;return}c[27676>>2]=0;c[27664>>2]=0;i=d;return}if((e|0)==(c[27676>>2]|0)){r=(c[27664>>2]|0)+n|0;c[27664>>2]=r;c[27676>>2]=m;c[m+4>>2]=r|1;c[m+r>>2]=r;i=d;return}r=(w&-8)+n|0;f=w>>>3;do{if(!(w>>>0<256)){k=c[a+(b+24)>>2]|0;g=c[a+(b+12)>>2]|0;do{if((g|0)==(e|0)){o=a+(b+20)|0;l=c[o>>2]|0;if((l|0)==0){t=a+(b+16)|0;s=c[t>>2]|0;if((s|0)==0){x=0;break}else{y=s;z=t}}else{y=l;z=o}while(1){o=y+20|0;l=c[o>>2]|0;if((l|0)!=0){y=l;z=o;continue}o=y+16|0;l=c[o>>2]|0;if((l|0)==0){break}else{y=l;z=o}}if(z>>>0>>0){_a()}else{c[z>>2]=0;x=y;break}}else{o=c[a+(b+8)>>2]|0;if(o>>>0>>0){_a()}l=o+12|0;if((c[l>>2]|0)!=(e|0)){_a()}t=g+8|0;if((c[t>>2]|0)==(e|0)){c[l>>2]=g;c[t>>2]=o;x=g;break}else{_a()}}}while(0);if((k|0)!=0){g=c[a+(b+28)>>2]|0;j=27960+(g<<2)|0;if((e|0)==(c[j>>2]|0)){c[j>>2]=x;if((x|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}g=k+16|0;if((c[g>>2]|0)==(e|0)){c[g>>2]=x}else{c[k+20>>2]=x}if((x|0)==0){break}}if(x>>>0<(c[27672>>2]|0)>>>0){_a()}c[x+24>>2]=k;g=c[a+(b+16)>>2]|0;do{if((g|0)!=0){if(g>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[x+16>>2]=g;c[g+24>>2]=x;break}}}while(0);g=c[a+(b+20)>>2]|0;if((g|0)!=0){if(g>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[x+20>>2]=g;c[g+24>>2]=x;break}}}}else{g=c[a+(b+8)>>2]|0;k=c[a+(b+12)>>2]|0;j=27696+(f<<1<<2)|0;if((g|0)!=(j|0)){if(g>>>0>>0){_a()}if((c[g+12>>2]|0)!=(e|0)){_a()}}if((k|0)==(g|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}j=k+8|0;if((c[j>>2]|0)==(e|0)){A=j}else{_a()}}else{A=k+8|0}c[g+12>>2]=k;c[A>>2]=g}}while(0);c[m+4>>2]=r|1;c[m+r>>2]=r;if((m|0)==(c[27676>>2]|0)){c[27664>>2]=r;i=d;return}else{B=r}}else{c[v>>2]=w&-2;c[m+4>>2]=n|1;c[m+n>>2]=n;B=n}n=B>>>3;if(B>>>0<256){w=n<<1;v=27696+(w<<2)|0;r=c[6914]|0;A=1<>2]|0;if(e>>>0<(c[27672>>2]|0)>>>0){_a()}else{C=n;D=e}}else{c[6914]=r|A;C=27696+(w+2<<2)|0;D=v}c[C>>2]=m;c[D+12>>2]=m;c[m+8>>2]=D;c[m+12>>2]=v;i=d;return}v=B>>>8;if((v|0)!=0){if(B>>>0>16777215){E=31}else{D=(v+1048320|0)>>>16&8;C=v<>>16&4;w=C<>>16&2;A=14-(v|D|C)+(w<>>15)|0;E=B>>>(A+7|0)&1|A<<1}}else{E=0}A=27960+(E<<2)|0;c[m+28>>2]=E;c[m+20>>2]=0;c[m+16>>2]=0;C=c[27660>>2]|0;w=1<>2]=C|w;c[A>>2]=m;c[m+24>>2]=A;c[m+12>>2]=m;c[m+8>>2]=m;i=d;return}w=c[A>>2]|0;if((E|0)==31){F=0}else{F=25-(E>>>1)|0}a:do{if((c[w+4>>2]&-8|0)==(B|0)){G=w}else{E=B<>>31<<2)+16|0;C=c[H>>2]|0;if((C|0)==0){break}if((c[C+4>>2]&-8|0)==(B|0)){G=C;break a}else{E=E<<1;A=C}}if(H>>>0<(c[27672>>2]|0)>>>0){_a()}c[H>>2]=m;c[m+24>>2]=A;c[m+12>>2]=m;c[m+8>>2]=m;i=d;return}}while(0);H=G+8|0;B=c[H>>2]|0;w=c[27672>>2]|0;if(G>>>0>>0){_a()}if(B>>>0>>0){_a()}c[B+12>>2]=m;c[H>>2]=m;c[m+8>>2]=B;c[m+12>>2]=G;c[m+24>>2]=0;i=d;return}function mg(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0.0,Q=0,R=0.0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0.0,ca=0,da=0.0,ea=0,fa=0.0,ga=0,ha=0.0,ia=0,ja=0.0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,ra=0,sa=0.0,ta=0,ua=0.0,va=0,wa=0,xa=0,ya=0,za=0.0,Aa=0,Ba=0.0,Ca=0.0,Da=0,Ea=0.0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Ta=0,Ua=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0.0,sc=0,tc=0,uc=0.0,vc=0.0,wc=0.0,xc=0.0,yc=0.0,zc=0.0,Ac=0,Bc=0,Cc=0.0,Dc=0,Ec=0.0,Fc=0,Gc=0,Hc=0,Ic=0;g=i;i=i+512|0;h=g;if((e|0)==1){j=53;k=-1074}else if((e|0)==0){j=24;k=-149}else if((e|0)==2){j=53;k=-1074}else{l=0.0;i=g;return+l}e=b+4|0;m=b+100|0;do{n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;o=d[n]|0}else{o=pg(b)|0}}while((fb(o|0)|0)!=0);do{if((o|0)==43|(o|0)==45){n=1-(((o|0)==45)<<1)|0;p=c[e>>2]|0;if(p>>>0<(c[m>>2]|0)>>>0){c[e>>2]=p+1;q=d[p]|0;r=n;break}else{q=pg(b)|0;r=n;break}}else{q=o;r=1}}while(0);o=q;q=0;while(1){if((o|32|0)!=(a[28152+q|0]|0)){s=o;v=q;break}do{if(q>>>0<7){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;w=d[n]|0;break}else{w=pg(b)|0;break}}else{w=o}}while(0);n=q+1|0;if(n>>>0<8){o=w;q=n}else{s=w;v=n;break}}do{if((v|0)==3){x=23}else if((v|0)!=8){w=(f|0)==0;if(!(v>>>0<4|w)){if((v|0)==8){break}else{x=23;break}}a:do{if((v|0)==0){q=s;o=0;while(1){if((q|32|0)!=(a[28168+o|0]|0)){y=q;z=o;break a}do{if(o>>>0<2){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;A=d[n]|0;break}else{A=pg(b)|0;break}}else{A=q}}while(0);n=o+1|0;if(n>>>0<3){q=A;o=n}else{y=A;z=n;break}}}else{y=s;z=v}}while(0);if((z|0)==0){do{if((y|0)==48){o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;B=d[o]|0}else{B=pg(b)|0}if((B|32|0)!=120){if((c[m>>2]|0)==0){C=48;break}c[e>>2]=(c[e>>2]|0)+ -1;C=48;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;D=d[o]|0;F=0}else{D=pg(b)|0;F=0}while(1){if((D|0)==46){x=70;break}else if((D|0)!=48){G=0;H=0;I=0;J=0;K=D;L=F;M=0;N=0;O=1.0;Q=0;R=0.0;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;D=d[o]|0;F=1;continue}else{D=pg(b)|0;F=1;continue}}b:do{if((x|0)==70){o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;S=d[o]|0}else{S=pg(b)|0}if((S|0)==48){o=-1;q=-1;while(1){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;T=d[n]|0}else{T=pg(b)|0}if((T|0)!=48){G=0;H=0;I=o;J=q;K=T;L=1;M=1;N=0;O=1.0;Q=0;R=0.0;break b}n=Ig(o|0,q|0,-1,-1)|0;o=n;q=E}}else{G=0;H=0;I=0;J=0;K=S;L=F;M=1;N=0;O=1.0;Q=0;R=0.0}}}while(0);c:while(1){q=K+ -48|0;do{if(!(q>>>0<10)){o=K|32;n=(K|0)==46;if(!((o+ -97|0)>>>0<6|n)){U=K;break c}if(n){if((M|0)==0){V=H;W=G;X=H;Y=G;Z=L;_=1;$=N;ba=O;ca=Q;da=R;break}else{U=46;break c}}else{ea=(K|0)>57?o+ -87|0:q;x=84;break}}else{ea=q;x=84}}while(0);if((x|0)==84){x=0;do{if(!((G|0)<0|(G|0)==0&H>>>0<8)){if((G|0)<0|(G|0)==0&H>>>0<14){fa=O*.0625;ga=N;ha=fa;ia=Q;ja=R+fa*+(ea|0);break}if((ea|0)!=0&(N|0)==0){ga=1;ha=O;ia=Q;ja=R+O*.5}else{ga=N;ha=O;ia=Q;ja=R}}else{ga=N;ha=O;ia=ea+(Q<<4)|0;ja=R}}while(0);q=Ig(H|0,G|0,1,0)|0;V=I;W=J;X=q;Y=E;Z=1;_=M;$=ga;ba=ha;ca=ia;da=ja}q=c[e>>2]|0;if(q>>>0<(c[m>>2]|0)>>>0){c[e>>2]=q+1;G=Y;H=X;I=V;J=W;K=d[q]|0;L=Z;M=_;N=$;O=ba;Q=ca;R=da;continue}else{G=Y;H=X;I=V;J=W;K=pg(b)|0;L=Z;M=_;N=$;O=ba;Q=ca;R=da;continue}}if((L|0)==0){q=(c[m>>2]|0)==0;if(!q){c[e>>2]=(c[e>>2]|0)+ -1}if(!w){if(!q?(q=c[e>>2]|0,c[e>>2]=q+ -1,(M|0)!=0):0){c[e>>2]=q+ -2}}else{og(b,0)}l=+(r|0)*0.0;i=g;return+l}q=(M|0)==0;o=q?H:I;n=q?G:J;if((G|0)<0|(G|0)==0&H>>>0<8){q=H;p=G;ka=Q;while(1){la=ka<<4;ma=Ig(q|0,p|0,1,0)|0;na=E;if((na|0)<0|(na|0)==0&ma>>>0<8){q=ma;p=na;ka=la}else{oa=la;break}}}else{oa=Q}do{if((U|32|0)==112){ka=ng(b,f)|0;p=E;if((ka|0)==0&(p|0)==-2147483648){if(w){og(b,0);l=0.0;i=g;return+l}else{if((c[m>>2]|0)==0){pa=0;ra=0;break}c[e>>2]=(c[e>>2]|0)+ -1;pa=0;ra=0;break}}else{pa=ka;ra=p}}else{if((c[m>>2]|0)==0){pa=0;ra=0}else{c[e>>2]=(c[e>>2]|0)+ -1;pa=0;ra=0}}}while(0);p=Gg(o|0,n|0,2)|0;ka=Ig(p|0,E|0,-32,-1)|0;p=Ig(ka|0,E|0,pa|0,ra|0)|0;ka=E;if((oa|0)==0){l=+(r|0)*0.0;i=g;return+l}if((ka|0)>0|(ka|0)==0&p>>>0>(0-k|0)>>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+l}q=k+ -106|0;la=((q|0)<0)<<31>>31;if((ka|0)<(la|0)|(ka|0)==(la|0)&p>>>0>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+l}if((oa|0)>-1){q=p;la=ka;na=oa;fa=R;while(1){ma=na<<1;if(!(fa>=.5)){sa=fa;ta=ma}else{sa=fa+-1.0;ta=ma|1}ua=fa+sa;ma=Ig(q|0,la|0,-1,-1)|0;va=E;if((ta|0)>-1){q=ma;la=va;na=ta;fa=ua}else{wa=ma;xa=va;ya=ta;za=ua;break}}}else{wa=p;xa=ka;ya=oa;za=R}na=Cg(32,0,k|0,((k|0)<0)<<31>>31|0)|0;la=Ig(wa|0,xa|0,na|0,E|0)|0;na=E;if(0>(na|0)|0==(na|0)&j>>>0>la>>>0){Aa=(la|0)<0?0:la}else{Aa=j}if((Aa|0)<53){fa=+(r|0);ua=+Va(+(+qg(1.0,84-Aa|0)),+fa);if((Aa|0)<32&za!=0.0){la=ya&1;Ba=fa;Ca=ua;Da=(la^1)+ya|0;Ea=(la|0)==0?0.0:za}else{Ba=fa;Ca=ua;Da=ya;Ea=za}}else{Ba=+(r|0);Ca=0.0;Da=ya;Ea=za}ua=Ba*Ea+(Ca+Ba*+(Da>>>0))-Ca;if(!(ua!=0.0)){c[(Sa()|0)>>2]=34}l=+rg(ua,wa);i=g;return+l}else{C=y}}while(0);la=k+j|0;na=0-la|0;q=C;n=0;while(1){if((q|0)==46){x=139;break}else if((q|0)!=48){Fa=q;Ga=0;Ha=0;Ia=n;Ja=0;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;q=d[o]|0;n=1;continue}else{q=pg(b)|0;n=1;continue}}d:do{if((x|0)==139){q=c[e>>2]|0;if(q>>>0<(c[m>>2]|0)>>>0){c[e>>2]=q+1;Ka=d[q]|0}else{Ka=pg(b)|0}if((Ka|0)==48){q=-1;o=-1;while(1){va=c[e>>2]|0;if(va>>>0<(c[m>>2]|0)>>>0){c[e>>2]=va+1;La=d[va]|0}else{La=pg(b)|0}if((La|0)!=48){Fa=La;Ga=q;Ha=o;Ia=1;Ja=1;break d}va=Ig(q|0,o|0,-1,-1)|0;q=va;o=E}}else{Fa=Ka;Ga=0;Ha=0;Ia=n;Ja=1}}}while(0);c[h>>2]=0;n=Fa+ -48|0;o=(Fa|0)==46;e:do{if(n>>>0<10|o){q=h+496|0;ka=Fa;p=0;va=0;ma=o;Ma=n;Na=Ga;Oa=Ha;Pa=Ia;Qa=Ja;Ra=0;Ta=0;Ua=0;while(1){do{if(ma){if((Qa|0)==0){Wa=p;Xa=va;Ya=p;Za=va;_a=Pa;$a=1;ab=Ra;bb=Ta;cb=Ua}else{db=ka;eb=Na;gb=Oa;hb=p;ib=va;jb=Pa;kb=Ra;lb=Ta;mb=Ua;break e}}else{nb=Ig(p|0,va|0,1,0)|0;ob=E;pb=(ka|0)!=48;if((Ta|0)>=125){if(!pb){Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=Pa;$a=Qa;ab=Ra;bb=Ta;cb=Ua;break}c[q>>2]=c[q>>2]|1;Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=Pa;$a=Qa;ab=Ra;bb=Ta;cb=Ua;break}qb=h+(Ta<<2)|0;if((Ra|0)==0){rb=Ma}else{rb=ka+ -48+((c[qb>>2]|0)*10|0)|0}c[qb>>2]=rb;qb=Ra+1|0;sb=(qb|0)==9;Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=1;$a=Qa;ab=sb?0:qb;bb=(sb&1)+Ta|0;cb=pb?nb:Ua}}while(0);nb=c[e>>2]|0;if(nb>>>0<(c[m>>2]|0)>>>0){c[e>>2]=nb+1;tb=d[nb]|0}else{tb=pg(b)|0}nb=tb+ -48|0;pb=(tb|0)==46;if(nb>>>0<10|pb){ka=tb;p=Ya;va=Za;ma=pb;Ma=nb;Na=Wa;Oa=Xa;Pa=_a;Qa=$a;Ra=ab;Ta=bb;Ua=cb}else{ub=tb;vb=Ya;wb=Wa;xb=Za;yb=Xa;zb=_a;Ab=$a;Bb=ab;Cb=bb;Db=cb;x=162;break}}}else{ub=Fa;vb=0;wb=Ga;xb=0;yb=Ha;zb=Ia;Ab=Ja;Bb=0;Cb=0;Db=0;x=162}}while(0);if((x|0)==162){n=(Ab|0)==0;db=ub;eb=n?vb:wb;gb=n?xb:yb;hb=vb;ib=xb;jb=zb;kb=Bb;lb=Cb;mb=Db}n=(jb|0)!=0;if(n?(db|32|0)==101:0){o=ng(b,f)|0;Ua=E;do{if((o|0)==0&(Ua|0)==-2147483648){if(w){og(b,0);l=0.0;i=g;return+l}else{if((c[m>>2]|0)==0){Eb=0;Fb=0;break}c[e>>2]=(c[e>>2]|0)+ -1;Eb=0;Fb=0;break}}else{Eb=o;Fb=Ua}}while(0);Ua=Ig(Eb|0,Fb|0,eb|0,gb|0)|0;Gb=Ua;Hb=E}else{if((db|0)>-1?(c[m>>2]|0)!=0:0){c[e>>2]=(c[e>>2]|0)+ -1;Gb=eb;Hb=gb}else{Gb=eb;Hb=gb}}if(!n){c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}Ua=c[h>>2]|0;if((Ua|0)==0){l=+(r|0)*0.0;i=g;return+l}do{if((Gb|0)==(hb|0)&(Hb|0)==(ib|0)&((ib|0)<0|(ib|0)==0&hb>>>0<10)){if(!(j>>>0>30)?(Ua>>>j|0)!=0:0){break}l=+(r|0)*+(Ua>>>0);i=g;return+l}}while(0);Ua=(k|0)/-2|0;n=((Ua|0)<0)<<31>>31;if((Hb|0)>(n|0)|(Hb|0)==(n|0)&Gb>>>0>Ua>>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+l}Ua=k+ -106|0;n=((Ua|0)<0)<<31>>31;if((Hb|0)<(n|0)|(Hb|0)==(n|0)&Gb>>>0>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+l}if((kb|0)==0){Ib=lb}else{if((kb|0)<9){Ua=h+(lb<<2)|0;n=c[Ua>>2]|0;o=kb;do{n=n*10|0;o=o+1|0}while((o|0)!=9);c[Ua>>2]=n}Ib=lb+1|0}do{if((mb|0)<9?(mb|0)<=(Gb|0)&(Gb|0)<18:0){if((Gb|0)==9){l=+(r|0)*+((c[h>>2]|0)>>>0);i=g;return+l}if((Gb|0)<9){l=+(r|0)*+((c[h>>2]|0)>>>0)/+(c[28184+(8-Gb<<2)>>2]|0);i=g;return+l}o=j+27+(aa(Gb,-3)|0)|0;Ta=c[h>>2]|0;if((o|0)<=30?(Ta>>>o|0)!=0:0){break}l=+(r|0)*+(Ta>>>0)*+(c[28184+(Gb+ -10<<2)>>2]|0);i=g;return+l}}while(0);n=(Gb|0)%9|0;if((n|0)==0){Jb=0;Kb=0;Lb=Gb;Mb=Ib}else{Ua=(Gb|0)>-1?n:n+9|0;n=c[28184+(8-Ua<<2)>>2]|0;if((Ib|0)!=0){Ta=1e9/(n|0)|0;o=0;Ra=0;Qa=0;Pa=Gb;while(1){Oa=h+(Qa<<2)|0;Na=c[Oa>>2]|0;Ma=((Na>>>0)/(n>>>0)|0)+Ra|0;c[Oa>>2]=Ma;Nb=aa((Na>>>0)%(n>>>0)|0,Ta)|0;Na=Qa+1|0;if((Qa|0)==(o|0)&(Ma|0)==0){Ob=Na&127;Pb=Pa+ -9|0}else{Ob=o;Pb=Pa}if((Na|0)==(Ib|0)){break}else{o=Ob;Ra=Nb;Qa=Na;Pa=Pb}}if((Nb|0)==0){Qb=Ob;Rb=Pb;Sb=Ib}else{c[h+(Ib<<2)>>2]=Nb;Qb=Ob;Rb=Pb;Sb=Ib+1|0}}else{Qb=0;Rb=Gb;Sb=0}Jb=Qb;Kb=0;Lb=9-Ua+Rb|0;Mb=Sb}f:while(1){Pa=h+(Jb<<2)|0;if((Lb|0)<18){Qa=Kb;Ra=Mb;while(1){o=0;Ta=Ra+127|0;n=Ra;while(1){Na=Ta&127;Ma=h+(Na<<2)|0;Oa=Gg(c[Ma>>2]|0,0,29)|0;ma=Ig(Oa|0,E|0,o|0,0)|0;Oa=E;if(Oa>>>0>0|(Oa|0)==0&ma>>>0>1e9){va=Ug(ma|0,Oa|0,1e9,0)|0;p=Vg(ma|0,Oa|0,1e9,0)|0;Tb=p;Ub=va}else{Tb=ma;Ub=0}c[Ma>>2]=Tb;Ma=(Na|0)==(Jb|0);if((Na|0)!=(n+127&127|0)|Ma){Vb=n}else{Vb=(Tb|0)==0?Na:n}if(Ma){break}else{o=Ub;Ta=Na+ -1|0;n=Vb}}n=Qa+ -29|0;if((Ub|0)==0){Qa=n;Ra=Vb}else{Wb=n;Xb=Ub;Yb=Vb;break}}}else{if((Lb|0)==18){Zb=Kb;_b=Mb}else{$b=Jb;ac=Kb;bc=Lb;cc=Mb;break}while(1){if(!((c[Pa>>2]|0)>>>0<9007199)){$b=Jb;ac=Zb;bc=18;cc=_b;break f}Ra=0;Qa=_b+127|0;n=_b;while(1){Ta=Qa&127;o=h+(Ta<<2)|0;Na=Gg(c[o>>2]|0,0,29)|0;Ma=Ig(Na|0,E|0,Ra|0,0)|0;Na=E;if(Na>>>0>0|(Na|0)==0&Ma>>>0>1e9){ma=Ug(Ma|0,Na|0,1e9,0)|0;va=Vg(Ma|0,Na|0,1e9,0)|0;dc=va;ec=ma}else{dc=Ma;ec=0}c[o>>2]=dc;o=(Ta|0)==(Jb|0);if((Ta|0)!=(n+127&127|0)|o){fc=n}else{fc=(dc|0)==0?Ta:n}if(o){break}else{Ra=ec;Qa=Ta+ -1|0;n=fc}}n=Zb+ -29|0;if((ec|0)==0){Zb=n;_b=fc}else{Wb=n;Xb=ec;Yb=fc;break}}}Pa=Jb+127&127;if((Pa|0)==(Yb|0)){n=Yb+127&127;Qa=h+((Yb+126&127)<<2)|0;c[Qa>>2]=c[Qa>>2]|c[h+(n<<2)>>2];gc=n}else{gc=Yb}c[h+(Pa<<2)>>2]=Xb;Jb=Pa;Kb=Wb;Lb=Lb+9|0;Mb=gc}g:while(1){hc=cc+1&127;Ua=h+((cc+127&127)<<2)|0;Pa=$b;n=ac;Qa=bc;while(1){Ra=(Qa|0)==18;Ta=(Qa|0)>27?9:1;ic=Pa;jc=n;while(1){o=0;while(1){Ma=o+ic&127;if((Ma|0)==(cc|0)){kc=2;break}ma=c[h+(Ma<<2)>>2]|0;Ma=c[28176+(o<<2)>>2]|0;if(ma>>>0>>0){kc=2;break}va=o+1|0;if(ma>>>0>Ma>>>0){kc=o;break}if((va|0)<2){o=va}else{kc=va;break}}if((kc|0)==2&Ra){break g}lc=Ta+jc|0;if((ic|0)==(cc|0)){ic=cc;jc=lc}else{break}}Ra=(1<>>Ta;mc=ic;nc=0;va=ic;oc=Qa;do{Ma=h+(va<<2)|0;ma=c[Ma>>2]|0;Na=(ma>>>Ta)+nc|0;c[Ma>>2]=Na;nc=aa(ma&Ra,o)|0;ma=(va|0)==(mc|0)&(Na|0)==0;va=va+1&127;oc=ma?oc+ -9|0:oc;mc=ma?va:mc}while((va|0)!=(cc|0));if((nc|0)==0){Pa=mc;n=lc;Qa=oc;continue}if((hc|0)!=(mc|0)){break}c[Ua>>2]=c[Ua>>2]|1;Pa=mc;n=lc;Qa=oc}c[h+(cc<<2)>>2]=nc;$b=mc;ac=lc;bc=oc;cc=hc}Qa=ic&127;if((Qa|0)==(cc|0)){c[h+(hc+ -1<<2)>>2]=0;pc=hc}else{pc=cc}ua=+((c[h+(Qa<<2)>>2]|0)>>>0);Qa=ic+1&127;if((Qa|0)==(pc|0)){n=pc+1&127;c[h+(n+ -1<<2)>>2]=0;qc=n}else{qc=pc}fa=+(r|0);rc=fa*(ua*1.0e9+ +((c[h+(Qa<<2)>>2]|0)>>>0));Qa=jc+53|0;n=Qa-k|0;if((n|0)<(j|0)){sc=(n|0)<0?0:n;tc=1}else{sc=j;tc=0}if((sc|0)<53){ua=+Va(+(+qg(1.0,105-sc|0)),+rc);uc=+qa(+rc,+(+qg(1.0,53-sc|0)));vc=ua;wc=uc;xc=ua+(rc-uc)}else{vc=0.0;wc=0.0;xc=rc}Pa=ic+2&127;if((Pa|0)!=(qc|0)){Ua=c[h+(Pa<<2)>>2]|0;do{if(!(Ua>>>0<5e8)){if(Ua>>>0>5e8){yc=fa*.75+wc;break}if((ic+3&127|0)==(qc|0)){yc=fa*.5+wc;break}else{yc=fa*.75+wc;break}}else{if((Ua|0)==0?(ic+3&127|0)==(qc|0):0){yc=wc;break}yc=fa*.25+wc}}while(0);if((53-sc|0)>1?!(+qa(+yc,1.0)!=0.0):0){zc=yc+1.0}else{zc=yc}}else{zc=wc}fa=xc+zc-vc;do{if((Qa&2147483647|0)>(-2-la|0)){if(!(+P(+fa)>=9007199254740992.0)){Ac=tc;Bc=jc;Cc=fa}else{Ac=(tc|0)!=0&(sc|0)==(n|0)?0:tc;Bc=jc+1|0;Cc=fa*.5}if((Bc+50|0)<=(na|0)?!((Ac|0)!=0&zc!=0.0):0){Dc=Bc;Ec=Cc;break}c[(Sa()|0)>>2]=34;Dc=Bc;Ec=Cc}else{Dc=jc;Ec=fa}}while(0);l=+rg(Ec,Dc);i=g;return+l}else if((z|0)==3){na=c[e>>2]|0;if(na>>>0<(c[m>>2]|0)>>>0){c[e>>2]=na+1;Fc=d[na]|0}else{Fc=pg(b)|0}if((Fc|0)==40){Gc=1}else{if((c[m>>2]|0)==0){l=t;i=g;return+l}c[e>>2]=(c[e>>2]|0)+ -1;l=t;i=g;return+l}while(1){na=c[e>>2]|0;if(na>>>0<(c[m>>2]|0)>>>0){c[e>>2]=na+1;Hc=d[na]|0}else{Hc=pg(b)|0}if(!((Hc+ -48|0)>>>0<10|(Hc+ -65|0)>>>0<26)?!((Hc+ -97|0)>>>0<26|(Hc|0)==95):0){break}Gc=Gc+1|0}if((Hc|0)==41){l=t;i=g;return+l}na=(c[m>>2]|0)==0;if(!na){c[e>>2]=(c[e>>2]|0)+ -1}if(w){c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}if((Gc|0)==0|na){l=t;i=g;return+l}else{Ic=Gc}while(1){na=Ic+ -1|0;c[e>>2]=(c[e>>2]|0)+ -1;if((na|0)==0){l=t;break}else{Ic=na}}i=g;return+l}else{if((c[m>>2]|0)!=0){c[e>>2]=(c[e>>2]|0)+ -1}c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}}}while(0);if((x|0)==23){x=(c[m>>2]|0)==0;if(!x){c[e>>2]=(c[e>>2]|0)+ -1}if(!(v>>>0<4|(f|0)==0|x)){x=v;do{c[e>>2]=(c[e>>2]|0)+ -1;x=x+ -1|0}while(x>>>0>3)}}l=+(r|0)*u;i=g;return+l}function ng(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;e=i;f=a+4|0;g=c[f>>2]|0;h=a+100|0;if(g>>>0<(c[h>>2]|0)>>>0){c[f>>2]=g+1;j=d[g]|0}else{j=pg(a)|0}if((j|0)==43|(j|0)==45){g=(j|0)==45|0;k=c[f>>2]|0;if(k>>>0<(c[h>>2]|0)>>>0){c[f>>2]=k+1;l=d[k]|0}else{l=pg(a)|0}if(!((l+ -48|0)>>>0<10|(b|0)==0)?(c[h>>2]|0)!=0:0){c[f>>2]=(c[f>>2]|0)+ -1;m=l;n=g}else{m=l;n=g}}else{m=j;n=0}if((m+ -48|0)>>>0>9){if((c[h>>2]|0)==0){o=-2147483648;p=0;E=o;i=e;return p|0}c[f>>2]=(c[f>>2]|0)+ -1;o=-2147483648;p=0;E=o;i=e;return p|0}else{q=m;r=0}while(1){s=q+ -48+r|0;m=c[f>>2]|0;if(m>>>0<(c[h>>2]|0)>>>0){c[f>>2]=m+1;t=d[m]|0}else{t=pg(a)|0}if(!((t+ -48|0)>>>0<10&(s|0)<214748364)){break}q=t;r=s*10|0}r=((s|0)<0)<<31>>31;if((t+ -48|0)>>>0<10){q=s;m=r;j=t;while(1){g=Tg(q|0,m|0,10,0)|0;l=E;b=Ig(j|0,((j|0)<0)<<31>>31|0,-48,-1)|0;k=Ig(b|0,E|0,g|0,l|0)|0;l=E;g=c[f>>2]|0;if(g>>>0<(c[h>>2]|0)>>>0){c[f>>2]=g+1;u=d[g]|0}else{u=pg(a)|0}if((u+ -48|0)>>>0<10&((l|0)<21474836|(l|0)==21474836&k>>>0<2061584302)){q=k;m=l;j=u}else{v=k;w=l;x=u;break}}}else{v=s;w=r;x=t}if((x+ -48|0)>>>0<10){do{x=c[f>>2]|0;if(x>>>0<(c[h>>2]|0)>>>0){c[f>>2]=x+1;y=d[x]|0}else{y=pg(a)|0}}while((y+ -48|0)>>>0<10)}if((c[h>>2]|0)!=0){c[f>>2]=(c[f>>2]|0)+ -1}f=(n|0)!=0;n=Cg(0,0,v|0,w|0)|0;o=f?E:w;p=f?n:v;E=o;i=e;return p|0}function og(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;c[a+104>>2]=b;e=c[a+8>>2]|0;f=c[a+4>>2]|0;g=e-f|0;c[a+108>>2]=g;if((b|0)!=0&(g|0)>(b|0)){c[a+100>>2]=f+b;i=d;return}else{c[a+100>>2]=e;i=d;return}}function pg(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;f=b+104|0;g=c[f>>2]|0;if(!((g|0)!=0?(c[b+108>>2]|0)>=(g|0):0)){h=3}if((h|0)==3?(h=tg(b)|0,(h|0)>=0):0){g=c[f>>2]|0;f=c[b+8>>2]|0;if((g|0)!=0?(j=c[b+4>>2]|0,k=g-(c[b+108>>2]|0)+ -1|0,(f-j|0)>(k|0)):0){c[b+100>>2]=j+k}else{c[b+100>>2]=f}k=c[b+4>>2]|0;if((f|0)!=0){j=b+108|0;c[j>>2]=f+1-k+(c[j>>2]|0)}j=k+ -1|0;if((d[j]|0|0)==(h|0)){l=h;i=e;return l|0}a[j]=h;l=h;i=e;return l|0}c[b+100>>2]=0;l=-1;i=e;return l|0}function qg(a,b){a=+a;b=b|0;var d=0,e=0.0,f=0,g=0,j=0,l=0.0;d=i;if((b|0)>1023){e=a*8.98846567431158e+307;f=b+ -1023|0;if((f|0)>1023){g=b+ -2046|0;j=(g|0)>1023?1023:g;l=e*8.98846567431158e+307}else{j=f;l=e}}else{if((b|0)<-1022){e=a*2.2250738585072014e-308;f=b+1022|0;if((f|0)<-1022){g=b+2044|0;j=(g|0)<-1022?-1022:g;l=e*2.2250738585072014e-308}else{j=f;l=e}}else{j=b;l=a}}b=Gg(j+1023|0,0,52)|0;j=E;c[k>>2]=b;c[k+4>>2]=j;a=l*+h[k>>3];i=d;return+a}function rg(a,b){a=+a;b=b|0;var c=0,d=0.0;c=i;d=+qg(a,b);i=c;return+d}function sg(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;e=b+74|0;f=a[e]|0;a[e]=f+255|f;f=b+20|0;e=b+44|0;if((c[f>>2]|0)>>>0>(c[e>>2]|0)>>>0){kb[c[b+36>>2]&1](b,0,0)|0}c[b+16>>2]=0;c[b+28>>2]=0;c[f>>2]=0;f=c[b>>2]|0;if((f&20|0)==0){g=c[e>>2]|0;c[b+8>>2]=g;c[b+4>>2]=g;h=0;i=d;return h|0}if((f&4|0)==0){h=-1;i=d;return h|0}c[b>>2]=f|32;h=-1;i=d;return h|0}function tg(a){a=a|0;var b=0,e=0,f=0;b=i;i=i+16|0;e=b;if((c[a+8>>2]|0)==0?(sg(a)|0)!=0:0){f=-1}else{if((kb[c[a+32>>2]&1](a,e,1)|0)==1){f=d[e]|0}else{f=-1}}i=b;return f|0}function ug(a){a=a|0;var b=0,c=0.0;b=i;c=+wg(a,0);i=b;return+c}function vg(b){b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;c=i;d=b;while(1){e=d+1|0;if((fb(a[d]|0)|0)==0){break}else{d=e}}b=a[d]|0;f=b<<24>>24;if((f|0)==45){g=1;h=5}else if((f|0)==43){g=0;h=5}else{j=d;k=b;l=0}if((h|0)==5){j=e;k=a[e]|0;l=g}if((cb(k<<24>>24|0)|0)==0){m=0;n=(l|0)!=0;o=0-m|0;p=n?m:o;i=c;return p|0}else{q=j;r=0}while(1){j=q+1|0;k=(r*10|0)+48-(a[q]|0)|0;if((cb(a[j]|0)|0)==0){m=k;break}else{q=j;r=k}}n=(l|0)!=0;o=0-m|0;p=n?m:o;i=c;return p|0}function wg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0.0,j=0,k=0;d=i;i=i+112|0;e=d;f=e+0|0;g=f+112|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(g|0));f=e+4|0;c[f>>2]=a;g=e+8|0;c[g>>2]=-1;c[e+44>>2]=a;c[e+76>>2]=-1;og(e,0);h=+mg(e,1,1);j=(c[f>>2]|0)-(c[g>>2]|0)+(c[e+108>>2]|0)|0;if((b|0)==0){i=d;return+h}if((j|0)==0){k=a}else{k=a+j|0}c[b>>2]=k;i=d;return+h}function xg(b,c){b=b|0;c=c|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;f=a[b]|0;a:do{if(f<<24>>24==0){g=0;h=c}else{j=f;k=f&255;l=b;m=c;while(1){n=a[m]|0;if(n<<24>>24==0){g=j;h=m;break a}if(!(j<<24>>24==n<<24>>24)?(n=Jg(k|0)|0,(n|0)!=(Jg(d[m]|0|0)|0)):0){break}n=l+1|0;o=m+1|0;p=a[n]|0;if(p<<24>>24==0){g=0;h=o;break a}else{j=p;k=p&255;l=n;m=o}}g=a[l]|0;h=m}}while(0);c=Jg(g&255|0)|0;g=c-(Jg(d[h]|0|0)|0)|0;i=e;return g|0}function yg(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;e=a[b]|0;f=a[c]|0;if(e<<24>>24!=f<<24>>24|e<<24>>24==0|f<<24>>24==0){g=e;h=f;j=g&255;k=h&255;l=j-k|0;i=d;return l|0}else{m=b;n=c}while(1){c=m+1|0;b=n+1|0;f=a[c]|0;e=a[b]|0;if(f<<24>>24!=e<<24>>24|f<<24>>24==0|e<<24>>24==0){g=f;h=e;break}else{m=c;n=b}}j=g&255;k=h&255;l=j-k|0;i=d;return l|0}function zg(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;if((e|0)==0){g=0;i=f;return g|0}h=a[b]|0;a:do{if(h<<24>>24==0){j=0;k=c}else{l=e;m=h;n=h&255;o=b;p=c;while(1){q=l+ -1|0;r=a[p]|0;if(r<<24>>24==0|(q|0)==0){j=m;k=p;break a}if(!(m<<24>>24==r<<24>>24)?(r=Jg(n|0)|0,(r|0)!=(Jg(d[p]|0|0)|0)):0){break}r=o+1|0;s=p+1|0;t=a[r]|0;if(t<<24>>24==0){j=0;k=s;break a}else{l=q;m=t;n=t&255;o=r;p=s}}j=a[o]|0;k=p}}while(0);c=Jg(j&255|0)|0;g=c-(Jg(d[k]|0|0)|0)|0;i=f;return g|0}function Ag(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;f=i;if((e|0)==0){g=0;i=f;return g|0}h=a[b]|0;a:do{if(h<<24>>24==0){j=0;k=c}else{l=e;m=h;n=b;o=c;while(1){p=l+ -1|0;q=a[o]|0;if(!((p|0)!=0&q<<24>>24!=0&m<<24>>24==q<<24>>24)){j=m;k=o;break a}q=n+1|0;r=o+1|0;s=a[q]|0;if(s<<24>>24==0){j=0;k=r;break}else{l=p;m=s;n=q;o=r}}}}while(0);g=(j&255)-(d[k]|0)|0;i=f;return g|0}function Bg(){}function Cg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=b-d>>>0;e=b-d-(c>>>0>a>>>0|0)>>>0;return(E=e,a-c>>>0|0)|0}function Dg(b){b=b|0;var c=0;c=b;while(a[c]|0){c=c+1|0}return c-b|0}function Eg(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0)>=20){d=d&255;g=b&3;h=d|d<<8|d<<16|d<<24;i=f&~3;if(g){g=b+4-g|0;while((b|0)<(g|0)){a[b]=d;b=b+1|0}}while((b|0)<(i|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b]=d;b=b+1|0}return b-e|0}function Fg(b,c){b=b|0;c=c|0;var d=0,e=0;d=b+(Dg(b)|0)|0;do{a[d+e|0]=a[c+e|0];e=e+1|0}while(a[c+(e-1)|0]|0);return b|0}function Gg(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b<>>32-c;return a<>>0;return(E=b+d+(e>>>0>>0|0)>>>0,e|0)|0}function Jg(a){a=a|0;if((a|0)<65)return a|0;if((a|0)>90)return a|0;return a-65+97|0}function Kg(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return Ga(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if((e|0)==0)return f|0;a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function Lg(b,c){b=b|0;c=c|0;var d=0;do{a[b+d|0]=a[c+d|0];d=d+1|0}while(a[c+(d-1)|0]|0);return b|0}function Mg(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b>>>c;return a>>>c|(b&(1<>>c-32|0}function Ng(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b>>c;return a>>>c|(b&(1<>c-32|0}function Og(b){b=b|0;var c=0;c=a[n+(b>>>24)|0]|0;if((c|0)<8)return c|0;c=a[n+(b>>16&255)|0]|0;if((c|0)<8)return c+8|0;c=a[n+(b>>8&255)|0]|0;if((c|0)<8)return c+16|0;return(a[n+(b&255)|0]|0)+24|0}function Pg(b){b=b|0;var c=0;c=a[m+(b&255)|0]|0;if((c|0)<8)return c|0;c=a[m+(b>>8&255)|0]|0;if((c|0)<8)return c+8|0;c=a[m+(b>>16&255)|0]|0;if((c|0)<8)return c+16|0;return(a[m+(b>>>24)|0]|0)+24|0}function Qg(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=a&65535;d=b&65535;e=aa(d,c)|0;f=a>>>16;a=(e>>>16)+(aa(d,f)|0)|0;d=b>>>16;b=aa(d,c)|0;return(E=(a>>>16)+(aa(d,f)|0)+(((a&65535)+b|0)>>>16)|0,a+b<<16|e&65535|0)|0}function Rg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;e=b>>31|((b|0)<0?-1:0)<<1;f=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;g=d>>31|((d|0)<0?-1:0)<<1;h=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;i=Cg(e^a,f^b,e,f)|0;b=E;a=g^e;e=h^f;f=Cg((Wg(i,b,Cg(g^c,h^d,g,h)|0,E,0)|0)^a,E^e,a,e)|0;return f|0}function Sg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+8|0;g=f|0;h=b>>31|((b|0)<0?-1:0)<<1;j=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;k=e>>31|((e|0)<0?-1:0)<<1;l=((e|0)<0?-1:0)>>31|((e|0)<0?-1:0)<<1;m=Cg(h^a,j^b,h,j)|0;b=E;Wg(m,b,Cg(k^d,l^e,k,l)|0,E,g)|0;l=Cg(c[g>>2]^h,c[g+4>>2]^j,h,j)|0;j=E;i=f;return(E=j,l)|0}function Tg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;a=c;c=Qg(e,a)|0;f=E;return(E=(aa(b,a)|0)+(aa(d,e)|0)+f|f&0,c|0|0)|0}function Ug(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=Wg(a,b,c,d,0)|0;return e|0}function Vg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=i;i=i+8|0;g=f|0;Wg(a,b,d,e,g)|0;i=f;return(E=c[g+4>>2]|0,c[g>>2]|0)|0}function Wg(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;g=a;h=b;i=h;j=d;k=e;l=k;if((i|0)==0){m=(f|0)!=0;if((l|0)==0){if(m){c[f>>2]=(g>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(g>>>0)/(j>>>0)>>>0;return(E=n,o)|0}else{if(!m){n=0;o=0;return(E=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;n=0;o=0;return(E=n,o)|0}}m=(l|0)==0;do{if((j|0)!=0){if(!m){p=(Og(l|0)|0)-(Og(i|0)|0)|0;if(p>>>0<=31){q=p+1|0;r=31-p|0;s=p-31>>31;t=q;u=g>>>(q>>>0)&s|i<>>(q>>>0)&s;w=0;x=g<>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return(E=n,o)|0}r=j-1|0;if((r&j|0)!=0){s=(Og(j|0)|0)+33-(Og(i|0)|0)|0;q=64-s|0;p=32-s|0;y=p>>31;z=s-32|0;A=z>>31;t=s;u=p-1>>31&i>>>(z>>>0)|(i<>>(s>>>0))&A;v=A&i>>>(s>>>0);w=g<>>(z>>>0))&y|g<>31;break}if((f|0)!=0){c[f>>2]=r&g;c[f+4>>2]=0}if((j|0)==1){n=h|b&0;o=a|0|0;return(E=n,o)|0}else{r=Pg(j|0)|0;n=i>>>(r>>>0)|0;o=i<<32-r|g>>>(r>>>0)|0;return(E=n,o)|0}}else{if(m){if((f|0)!=0){c[f>>2]=(i>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(i>>>0)/(j>>>0)>>>0;return(E=n,o)|0}if((g|0)==0){if((f|0)!=0){c[f>>2]=0;c[f+4>>2]=(i>>>0)%(l>>>0)}n=0;o=(i>>>0)/(l>>>0)>>>0;return(E=n,o)|0}r=l-1|0;if((r&l|0)==0){if((f|0)!=0){c[f>>2]=a|0;c[f+4>>2]=r&i|b&0}n=0;o=i>>>((Pg(l|0)|0)>>>0);return(E=n,o)|0}r=(Og(l|0)|0)-(Og(i|0)|0)|0;if(r>>>0<=30){s=r+1|0;p=31-r|0;t=s;u=i<>>(s>>>0);v=i>>>(s>>>0);w=0;x=g<>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return(E=n,o)|0}}while(0);if((t|0)==0){B=x;C=w;D=v;F=u;G=0;H=0}else{b=d|0|0;d=k|e&0;e=Ig(b,d,-1,-1)|0;k=E;h=x;x=w;w=v;v=u;u=t;t=0;while(1){I=x>>>31|h<<1;J=t|x<<1;a=v<<1|h>>>31|0;g=v>>>31|w<<1|0;Cg(e,k,a,g)|0;i=E;l=i>>31|((i|0)<0?-1:0)<<1;K=l&1;L=Cg(a,g,l&b,(((i|0)<0?-1:0)>>31|((i|0)<0?-1:0)<<1)&d)|0;M=E;i=u-1|0;if((i|0)==0){break}else{h=I;x=J;w=M;v=L;u=i;t=K}}B=I;C=J;D=M;F=L;G=0;H=K}K=C;C=0;if((f|0)!=0){c[f>>2]=F;c[f+4>>2]=D}n=(K|0)>>>31|(B|C)<<1|(C<<1|K>>>31)&0|G;o=(K<<1|0>>>31)&-2|H;return(E=n,o)|0}function Xg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return kb[a&1](b|0,c|0,d|0)|0}function Yg(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=d|0;e=e|0;f=f|0;return lb[a&63](+b,+c,d|0,e|0,f|0)|0}function Zg(a,b,c){a=a|0;b=b|0;c=c|0;mb[a&1](b|0,c|0)}function _g(a,b,c){a=a|0;b=b|0;c=c|0;return nb[a&7](b|0,c|0)|0}function $g(a,b,c){a=a|0;b=b|0;c=c|0;ba(0);return 0}function ah(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;ba(1);return 0}function bh(a,b){a=a|0;b=b|0;ba(2)}function ch(a,b){a=a|0;b=b|0;ba(3);return 0} + + + + +// EMSCRIPTEN_END_FUNCS +var kb=[$g,Xf];var lb=[ah,Ud,Vd,Xd,Yd,Zd,_d,$d,ae,de,ee,fe,ge,he,ie,je,ke,le,me,ne,oe,pe,qe,re,se,te,ue,ve,we,He,Ie,Je,Ke,Le,Me,Ne,Oe,Qd,Rd,Sd,Td,be,ce,xe,ye,ze,Ae,Be,Ce,De,Ee,Fe,Ge,ah,ah,ah,ah,ah,ah,ah,ah,ah,ah,ah];var mb=[bh,Yf];var nb=[ch,nf,of,pf,ef,ch,ch,ch];return{_strlen:Dg,_strcat:Fg,_gzread:xf,_wcsunits:Ib,_zscale:Lb,_initwcs:Eb,_wcssys:Hb,_pix2wcsstr:Fb,_calloc:ig,_bitshift64Shl:Gg,_gzwrite:Cf,_saostrtod:Kb,_strncpy:Hg,_memset:Eg,_memcpy:Kg,_gzclose:rf,_i64Subtract:Cg,_realloc:jg,_i64Add:Ig,_wcs2pixstr:Gb,_gzopen:sf,_gzseek:wf,_free:hg,_tolower:Jg,_malloc:gg,_reg2wcsstr:Jb,_strcpy:Lg,runPostSets:Bg,stackAlloc:ob,stackSave:pb,stackRestore:qb,setThrew:rb,setTempRet0:ub,setTempRet1:vb,setTempRet2:wb,setTempRet3:xb,setTempRet4:yb,setTempRet5:zb,setTempRet6:Ab,setTempRet7:Bb,setTempRet8:Cb,setTempRet9:Db,dynCall_iiii:Xg,dynCall_iddiii:Yg,dynCall_vii:Zg,dynCall_iii:_g}}) + + +// EMSCRIPTEN_END_ASM +({ "Math": Math, "Int8Array": Int8Array, "Int16Array": Int16Array, "Int32Array": Int32Array, "Uint8Array": Uint8Array, "Uint16Array": Uint16Array, "Uint32Array": Uint32Array, "Float32Array": Float32Array, "Float64Array": Float64Array }, { "abort": abort, "assert": assert, "asmPrintInt": asmPrintInt, "asmPrintFloat": asmPrintFloat, "min": Math_min, "invoke_iiii": invoke_iiii, "invoke_iddiii": invoke_iddiii, "invoke_vii": invoke_vii, "invoke_iii": invoke_iii, "_fabs": _fabs, "_sin": _sin, "_exp": _exp, "_llvm_pow_f64": _llvm_pow_f64, "_acos": _acos, "_atan2": _atan2, "_fmod": _fmod, "_lseek": _lseek, "__reallyNegative": __reallyNegative, "_asin": _asin, "_atan": _atan, "___buildEnvironment": ___buildEnvironment, "_fflush": _fflush, "_pwrite": _pwrite, "_strerror_r": _strerror_r, "_fprintf": _fprintf, "_open": _open, "_fabsf": _fabsf, "_sbrk": _sbrk, "_send": _send, "_snprintf": _snprintf, "_llvm_bswap_i32": _llvm_bswap_i32, "_emscripten_memcpy_big": _emscripten_memcpy_big, "_fileno": _fileno, "_sysconf": _sysconf, "___setErrNo": ___setErrNo, "_cos": _cos, "_pread": _pread, "_printf": _printf, "_sprintf": _sprintf, "_log": _log, "_toupper": _toupper, "_write": _write, "_isupper": _isupper, "___errno_location": ___errno_location, "_recv": _recv, "_tan": _tan, "_copysign": _copysign, "_getenv": _getenv, "_mkport": _mkport, "__exit": __exit, "_read": _read, "_abort": _abort, "_islower": _islower, "_fwrite": _fwrite, "_time": _time, "_isdigit": _isdigit, "_strerror": _strerror, "__formatString": __formatString, "_isspace": _isspace, "_sqrt": _sqrt, "_exit": _exit, "_close": _close, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "cttz_i8": cttz_i8, "ctlz_i8": ctlz_i8, "NaN": NaN, "Infinity": Infinity, "_stderr": _stderr }, buffer); +var _strlen = Module["_strlen"] = asm["_strlen"]; +var _strcat = Module["_strcat"] = asm["_strcat"]; +var _gzread = Module["_gzread"] = asm["_gzread"]; +var _wcsunits = Module["_wcsunits"] = asm["_wcsunits"]; +var _zscale = Module["_zscale"] = asm["_zscale"]; +var _initwcs = Module["_initwcs"] = asm["_initwcs"]; +var _wcssys = Module["_wcssys"] = asm["_wcssys"]; +var _pix2wcsstr = Module["_pix2wcsstr"] = asm["_pix2wcsstr"]; +var _calloc = Module["_calloc"] = asm["_calloc"]; +var _bitshift64Shl = Module["_bitshift64Shl"] = asm["_bitshift64Shl"]; +var _gzwrite = Module["_gzwrite"] = asm["_gzwrite"]; +var _saostrtod = Module["_saostrtod"] = asm["_saostrtod"]; +var _strncpy = Module["_strncpy"] = asm["_strncpy"]; +var _memset = Module["_memset"] = asm["_memset"]; +var _memcpy = Module["_memcpy"] = asm["_memcpy"]; +var _gzclose = Module["_gzclose"] = asm["_gzclose"]; +var _i64Subtract = Module["_i64Subtract"] = asm["_i64Subtract"]; +var _realloc = Module["_realloc"] = asm["_realloc"]; +var _i64Add = Module["_i64Add"] = asm["_i64Add"]; +var _wcs2pixstr = Module["_wcs2pixstr"] = asm["_wcs2pixstr"]; +var _gzopen = Module["_gzopen"] = asm["_gzopen"]; +var _gzseek = Module["_gzseek"] = asm["_gzseek"]; +var _free = Module["_free"] = asm["_free"]; +var _tolower = Module["_tolower"] = asm["_tolower"]; +var _malloc = Module["_malloc"] = asm["_malloc"]; +var _reg2wcsstr = Module["_reg2wcsstr"] = asm["_reg2wcsstr"]; +var _strcpy = Module["_strcpy"] = asm["_strcpy"]; +var runPostSets = Module["runPostSets"] = asm["runPostSets"]; +var dynCall_iiii = Module["dynCall_iiii"] = asm["dynCall_iiii"]; +var dynCall_iddiii = Module["dynCall_iddiii"] = asm["dynCall_iddiii"]; +var dynCall_vii = Module["dynCall_vii"] = asm["dynCall_vii"]; +var dynCall_iii = Module["dynCall_iii"] = asm["dynCall_iii"]; + +Runtime.stackAlloc = function(size) { return asm['stackAlloc'](size) }; +Runtime.stackSave = function() { return asm['stackSave']() }; +Runtime.stackRestore = function(top) { asm['stackRestore'](top) }; + + +// TODO: strip out parts of this we do not need + +//======= begin closure i64 code ======= + +// Copyright 2009 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Defines a Long class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "long". This + * implementation is derived from LongLib in GWT. + * + */ + +var i64Math = (function() { // Emscripten wrapper + var goog = { math: {} }; + + + /** + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @param {number} low The low (signed) 32 bits of the long. + * @param {number} high The high (signed) 32 bits of the long. + * @constructor + */ + goog.math.Long = function(low, high) { + /** + * @type {number} + * @private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @private + */ + this.high_ = high | 0; // force into 32 signed bits. + }; + + + // NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the + // from* methods on which they depend. + + + /** + * A cache of the Long representations of small integer values. + * @type {!Object} + * @private + */ + goog.math.Long.IntCache_ = {}; + + + /** + * Returns a Long representing the given (32-bit) integer value. + * @param {number} value The 32-bit integer in question. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = goog.math.Long.IntCache_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new goog.math.Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + goog.math.Long.IntCache_[value] = obj; + } + return obj; + }; + + + /** + * Returns a Long representing the given value, provided that it is a finite + * number. Otherwise, zero is returned. + * @param {number} value The number in question. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return goog.math.Long.ZERO; + } else if (value <= -goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MIN_VALUE; + } else if (value + 1 >= goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MAX_VALUE; + } else if (value < 0) { + return goog.math.Long.fromNumber(-value).negate(); + } else { + return new goog.math.Long( + (value % goog.math.Long.TWO_PWR_32_DBL_) | 0, + (value / goog.math.Long.TWO_PWR_32_DBL_) | 0); + } + }; + + + /** + * Returns a Long representing the 64-bit integer that comes by concatenating + * the given high and low bits. Each is assumed to use 32 bits. + * @param {number} lowBits The low 32-bits. + * @param {number} highBits The high 32-bits. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromBits = function(lowBits, highBits) { + return new goog.math.Long(lowBits, highBits); + }; + + + /** + * Returns a Long representation of the given string, written using the given + * radix. + * @param {string} str The textual representation of the Long. + * @param {number=} opt_radix The radix in which the text is written. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return goog.math.Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 8)); + + var result = goog.math.Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = goog.math.Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(goog.math.Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(goog.math.Long.fromNumber(value)); + } + } + return result; + }; + + + // NOTE: the compiler should inline these constant values below and then remove + // these variables, so there should be no runtime penalty for these. + + + /** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_16_DBL_ = 1 << 16; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_24_DBL_ = 1 << 24; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_32_DBL_ = + goog.math.Long.TWO_PWR_16_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_31_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ / 2; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_48_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_64_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_32_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_63_DBL_ = + goog.math.Long.TWO_PWR_64_DBL_ / 2; + + + /** @type {!goog.math.Long} */ + goog.math.Long.ZERO = goog.math.Long.fromInt(0); + + + /** @type {!goog.math.Long} */ + goog.math.Long.ONE = goog.math.Long.fromInt(1); + + + /** @type {!goog.math.Long} */ + goog.math.Long.NEG_ONE = goog.math.Long.fromInt(-1); + + + /** @type {!goog.math.Long} */ + goog.math.Long.MAX_VALUE = + goog.math.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + + + /** @type {!goog.math.Long} */ + goog.math.Long.MIN_VALUE = goog.math.Long.fromBits(0, 0x80000000 | 0); + + + /** + * @type {!goog.math.Long} + * @private + */ + goog.math.Long.TWO_PWR_24_ = goog.math.Long.fromInt(1 << 24); + + + /** @return {number} The value, assuming it is a 32-bit integer. */ + goog.math.Long.prototype.toInt = function() { + return this.low_; + }; + + + /** @return {number} The closest floating-point representation to this value. */ + goog.math.Long.prototype.toNumber = function() { + return this.high_ * goog.math.Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); + }; + + + /** + * @param {number=} opt_radix The radix in which the text should be written. + * @return {string} The textual representation of this value. + */ + goog.math.Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = goog.math.Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } + }; + + + /** @return {number} The high 32-bits as a signed value. */ + goog.math.Long.prototype.getHighBits = function() { + return this.high_; + }; + + + /** @return {number} The low 32-bits as a signed value. */ + goog.math.Long.prototype.getLowBits = function() { + return this.low_; + }; + + + /** @return {number} The low 32-bits as an unsigned value. */ + goog.math.Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : goog.math.Long.TWO_PWR_32_DBL_ + this.low_; + }; + + + /** + * @return {number} Returns the number of bits needed to represent the absolute + * value of this Long. + */ + goog.math.Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } + }; + + + /** @return {boolean} Whether this value is zero. */ + goog.math.Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; + }; + + + /** @return {boolean} Whether this value is negative. */ + goog.math.Long.prototype.isNegative = function() { + return this.high_ < 0; + }; + + + /** @return {boolean} Whether this value is odd. */ + goog.math.Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long equals the other. + */ + goog.math.Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long does not equal the other. + */ + goog.math.Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than the other. + */ + goog.math.Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than or equal to the other. + */ + goog.math.Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than the other. + */ + goog.math.Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than or equal to the other. + */ + goog.math.Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; + }; + + + /** + * Compares this Long with the given one. + * @param {goog.math.Long} other Long to compare against. + * @return {number} 0 if they are the same, 1 if the this is greater, and -1 + * if the given one is greater. + */ + goog.math.Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } + }; + + + /** @return {!goog.math.Long} The negation of this value. */ + goog.math.Long.prototype.negate = function() { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.MIN_VALUE; + } else { + return this.not().add(goog.math.Long.ONE); + } + }; + + + /** + * Returns the sum of this and the given Long. + * @param {goog.math.Long} other Long to add to this one. + * @return {!goog.math.Long} The sum of this and the given Long. + */ + goog.math.Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); + }; + + + /** + * Returns the difference of this and the given Long. + * @param {goog.math.Long} other Long to subtract from this. + * @return {!goog.math.Long} The difference of this and the given Long. + */ + goog.math.Long.prototype.subtract = function(other) { + return this.add(other.negate()); + }; + + + /** + * Returns the product of this and the given long. + * @param {goog.math.Long} other Long to multiply with this. + * @return {!goog.math.Long} The product of this and the other. + */ + goog.math.Long.prototype.multiply = function(other) { + if (this.isZero()) { + return goog.math.Long.ZERO; + } else if (other.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + return other.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return this.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both longs are small, use float multiplication + if (this.lessThan(goog.math.Long.TWO_PWR_24_) && + other.lessThan(goog.math.Long.TWO_PWR_24_)) { + return goog.math.Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); + }; + + + /** + * Returns this Long divided by the given one. + * @param {goog.math.Long} other Long by which to divide. + * @return {!goog.math.Long} This Long divided by the given one. + */ + goog.math.Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + if (other.equals(goog.math.Long.ONE) || + other.equals(goog.math.Long.NEG_ONE)) { + return goog.math.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(goog.math.Long.ZERO)) { + return other.isNegative() ? goog.math.Long.ONE : goog.math.Long.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = goog.math.Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = goog.math.Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = goog.math.Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = goog.math.Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; + }; + + + /** + * Returns this Long modulo the given one. + * @param {goog.math.Long} other Long by which to mod. + * @return {!goog.math.Long} This Long modulo the given one. + */ + goog.math.Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); + }; + + + /** @return {!goog.math.Long} The bitwise-NOT of this value. */ + goog.math.Long.prototype.not = function() { + return goog.math.Long.fromBits(~this.low_, ~this.high_); + }; + + + /** + * Returns the bitwise-AND of this Long and the given one. + * @param {goog.math.Long} other The Long with which to AND. + * @return {!goog.math.Long} The bitwise-AND of this and the other. + */ + goog.math.Long.prototype.and = function(other) { + return goog.math.Long.fromBits(this.low_ & other.low_, + this.high_ & other.high_); + }; + + + /** + * Returns the bitwise-OR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to OR. + * @return {!goog.math.Long} The bitwise-OR of this and the other. + */ + goog.math.Long.prototype.or = function(other) { + return goog.math.Long.fromBits(this.low_ | other.low_, + this.high_ | other.high_); + }; + + + /** + * Returns the bitwise-XOR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to XOR. + * @return {!goog.math.Long} The bitwise-XOR of this and the other. + */ + goog.math.Long.prototype.xor = function(other) { + return goog.math.Long.fromBits(this.low_ ^ other.low_, + this.high_ ^ other.high_); + }; + + + /** + * Returns this Long with bits shifted to the left by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the left by the given amount. + */ + goog.math.Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return goog.math.Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return goog.math.Long.fromBits(0, low << (numBits - 32)); + } + } + }; + + + /** + * Returns this Long with bits shifted to the right by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount. + */ + goog.math.Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return goog.math.Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } + }; + + + /** + * Returns this Long with bits shifted to the right by the given amount, with + * the new top bits matching the current sign bit. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount, with + * zeros placed into the new leading bits. + */ + goog.math.Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return goog.math.Long.fromBits(high, 0); + } else { + return goog.math.Long.fromBits(high >>> (numBits - 32), 0); + } + } + }; + + //======= begin jsbn ======= + + var navigator = { appName: 'Modern Browser' }; // polyfill a little + + // Copyright (c) 2005 Tom Wu + // All Rights Reserved. + // http://www-cs-students.stanford.edu/~tjw/jsbn/ + + /* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ + + // Basic JavaScript BN library - subset useful for RSA encryption. + + // Bits per digit + var dbits; + + // JavaScript engine analysis + var canary = 0xdeadbeefcafe; + var j_lm = ((canary&0xffffff)==0xefcafe); + + // (public) Constructor + function BigInteger(a,b,c) { + if(a != null) + if("number" == typeof a) this.fromNumber(a,b,c); + else if(b == null && "string" != typeof a) this.fromString(a,256); + else this.fromString(a,b); + } + + // return new, unset BigInteger + function nbi() { return new BigInteger(null); } + + // am: Compute w_j += (x*this_i), propagate carries, + // c is initial carry, returns final carry. + // c < 3*dvalue, x < 2*dvalue, this_i < dvalue + // We need to select the fastest one that works in this environment. + + // am1: use a single mult and divide to get the high bits, + // max digit bits should be 26 because + // max internal value = 2*dvalue^2-2*dvalue (< 2^53) + function am1(i,x,w,j,c,n) { + while(--n >= 0) { + var v = x*this[i++]+w[j]+c; + c = Math.floor(v/0x4000000); + w[j++] = v&0x3ffffff; + } + return c; + } + // am2 avoids a big mult-and-extract completely. + // Max digit bits should be <= 30 because we do bitwise ops + // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) + function am2(i,x,w,j,c,n) { + var xl = x&0x7fff, xh = x>>15; + while(--n >= 0) { + var l = this[i]&0x7fff; + var h = this[i++]>>15; + var m = xh*l+h*xl; + l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); + c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); + w[j++] = l&0x3fffffff; + } + return c; + } + // Alternately, set max digit bits to 28 since some + // browsers slow down when dealing with 32-bit numbers. + function am3(i,x,w,j,c,n) { + var xl = x&0x3fff, xh = x>>14; + while(--n >= 0) { + var l = this[i]&0x3fff; + var h = this[i++]>>14; + var m = xh*l+h*xl; + l = xl*l+((m&0x3fff)<<14)+w[j]+c; + c = (l>>28)+(m>>14)+xh*h; + w[j++] = l&0xfffffff; + } + return c; + } + if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { + BigInteger.prototype.am = am2; + dbits = 30; + } + else if(j_lm && (navigator.appName != "Netscape")) { + BigInteger.prototype.am = am1; + dbits = 26; + } + else { // Mozilla/Netscape seems to prefer am3 + BigInteger.prototype.am = am3; + dbits = 28; + } + + BigInteger.prototype.DB = dbits; + BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; + r.t = this.t; + r.s = this.s; + } + + // (protected) set from integer value x, -DV <= x < DV + function bnpFromInt(x) { + this.t = 1; + this.s = (x<0)?-1:0; + if(x > 0) this[0] = x; + else if(x < -1) this[0] = x+DV; + else this.t = 0; + } + + // return bigint initialized to value + function nbv(i) { var r = nbi(); r.fromInt(i); return r; } + + // (protected) set from string and radix + function bnpFromString(s,b) { + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 256) k = 8; // byte array + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else { this.fromRadix(s,b); return; } + this.t = 0; + this.s = 0; + var i = s.length, mi = false, sh = 0; + while(--i >= 0) { + var x = (k==8)?s[i]&0xff:intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if(sh == 0) + this[this.t++] = x; + else if(sh+k > this.DB) { + this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); + } + else + this[this.t-1] |= x<= this.DB) sh -= this.DB; + } + if(k == 8 && (s[0]&0x80) != 0) { + this.s = -1; + if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; + } + + // (public) return string representation in given radix + function bnToString(b) { + if(this.s < 0) return "-"+this.negate().toString(b); + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else return this.toRadix(b); + var km = (1< 0) { + if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } + while(i >= 0) { + if(p < k) { + d = (this[i]&((1<>(p+=this.DB-k); + } + else { + d = (this[i]>>(p-=k))&km; + if(p <= 0) { p += this.DB; --i; } + } + if(d > 0) m = true; + if(m) r += int2char(d); + } + } + return m?r:"0"; + } + + // (public) -this + function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } + + // (public) |this| + function bnAbs() { return (this.s<0)?this.negate():this; } + + // (public) return + if this > a, - if this < a, 0 if equal + function bnCompareTo(a) { + var r = this.s-a.s; + if(r != 0) return r; + var i = this.t; + r = i-a.t; + if(r != 0) return (this.s<0)?-r:r; + while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; + return 0; + } + + // returns bit length of the integer x + function nbits(x) { + var r = 1, t; + if((t=x>>>16) != 0) { x = t; r += 16; } + if((t=x>>8) != 0) { x = t; r += 8; } + if((t=x>>4) != 0) { x = t; r += 4; } + if((t=x>>2) != 0) { x = t; r += 2; } + if((t=x>>1) != 0) { x = t; r += 1; } + return r; + } + + // (public) return the number of bits in "this" + function bnBitLength() { + if(this.t <= 0) return 0; + return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); + } + + // (protected) r = this << n*DB + function bnpDLShiftTo(n,r) { + var i; + for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; + for(i = n-1; i >= 0; --i) r[i] = 0; + r.t = this.t+n; + r.s = this.s; + } + + // (protected) r = this >> n*DB + function bnpDRShiftTo(n,r) { + for(var i = n; i < this.t; ++i) r[i-n] = this[i]; + r.t = Math.max(this.t-n,0); + r.s = this.s; + } + + // (protected) r = this << n + function bnpLShiftTo(n,r) { + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<= 0; --i) { + r[i+ds+1] = (this[i]>>cbs)|c; + c = (this[i]&bm)<= 0; --i) r[i] = 0; + r[ds] = c; + r.t = this.t+ds+1; + r.s = this.s; + r.clamp(); + } + + // (protected) r = this >> n + function bnpRShiftTo(n,r) { + r.s = this.s; + var ds = Math.floor(n/this.DB); + if(ds >= this.t) { r.t = 0; return; } + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<>bs; + for(var i = ds+1; i < this.t; ++i) { + r[i-ds-1] |= (this[i]&bm)<>bs; + } + if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; + } + if(a.t < this.t) { + c -= a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c -= a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c<0)?-1:0; + if(c < -1) r[i++] = this.DV+c; + else if(c > 0) r[i++] = c; + r.t = i; + r.clamp(); + } + + // (protected) r = this * a, r != this,a (HAC 14.12) + // "this" should be the larger one if appropriate. + function bnpMultiplyTo(a,r) { + var x = this.abs(), y = a.abs(); + var i = x.t; + r.t = i+y.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); + r.s = 0; + r.clamp(); + if(this.s != a.s) BigInteger.ZERO.subTo(r,r); + } + + // (protected) r = this^2, r != this (HAC 14.16) + function bnpSquareTo(r) { + var x = this.abs(); + var i = r.t = 2*x.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < x.t-1; ++i) { + var c = x.am(i,x[i],r,2*i,0,1); + if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { + r[i+x.t] -= x.DV; + r[i+x.t+1] = 1; + } + } + if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); + r.s = 0; + r.clamp(); + } + + // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) + // r != q, this != m. q or r may be null. + function bnpDivRemTo(m,q,r) { + var pm = m.abs(); + if(pm.t <= 0) return; + var pt = this.abs(); + if(pt.t < pm.t) { + if(q != null) q.fromInt(0); + if(r != null) this.copyTo(r); + return; + } + if(r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus + if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } + else { pm.copyTo(y); pt.copyTo(r); } + var ys = y.t; + var y0 = y[ys-1]; + if(y0 == 0) return; + var yt = y0*(1<1)?y[ys-2]>>this.F2:0); + var d1 = this.FV/yt, d2 = (1<= 0) { + r[r.t++] = 1; + r.subTo(t,r); + } + BigInteger.ONE.dlShiftTo(ys,t); + t.subTo(y,y); // "negative" y so we can replace sub with am later + while(y.t < ys) y[y.t++] = 0; + while(--j >= 0) { + // Estimate quotient digit + var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); + if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out + y.dlShiftTo(j,t); + r.subTo(t,r); + while(r[i] < --qd) r.subTo(t,r); + } + } + if(q != null) { + r.drShiftTo(ys,q); + if(ts != ms) BigInteger.ZERO.subTo(q,q); + } + r.t = ys; + r.clamp(); + if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder + if(ts < 0) BigInteger.ZERO.subTo(r,r); + } + + // (public) this mod a + function bnMod(a) { + var r = nbi(); + this.abs().divRemTo(a,null,r); + if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); + return r; + } + + // Modular reduction using "classic" algorithm + function Classic(m) { this.m = m; } + function cConvert(x) { + if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; + } + function cRevert(x) { return x; } + function cReduce(x) { x.divRemTo(this.m,null,x); } + function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + Classic.prototype.convert = cConvert; + Classic.prototype.revert = cRevert; + Classic.prototype.reduce = cReduce; + Classic.prototype.mulTo = cMulTo; + Classic.prototype.sqrTo = cSqrTo; + + // (protected) return "-1/this % 2^DB"; useful for Mont. reduction + // justification: + // xy == 1 (mod m) + // xy = 1+km + // xy(2-xy) = (1+km)(1-km) + // x[y(2-xy)] = 1-k^2m^2 + // x[y(2-xy)] == 1 (mod m^2) + // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 + // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. + // JS multiply "overflows" differently from C/C++, so care is needed here. + function bnpInvDigit() { + if(this.t < 1) return 0; + var x = this[0]; + if((x&1) == 0) return 0; + var y = x&3; // y == 1/x mod 2^2 + y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 + y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 + y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y>0)?this.DV-y:-y; + } + + // Montgomery reduction + function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp&0x7fff; + this.mph = this.mp>>15; + this.um = (1<<(m.DB-15))-1; + this.mt2 = 2*m.t; + } + + // xR mod m + function montConvert(x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t,r); + r.divRemTo(this.m,null,r); + if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); + return r; + } + + // x/R mod m + function montRevert(x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + + // x = x/R mod m (HAC 14.32) + function montReduce(x) { + while(x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0; + for(var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i]&0x7fff; + var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; + // use am to combine the multiply-shift-add into one call + j = i+this.m.t; + x[j] += this.m.am(0,u0,x,i,0,this.m.t); + // propagate carry + while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } + } + x.clamp(); + x.drShiftTo(this.m.t,x); + if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); + } + + // r = "x^2/R mod m"; x != r + function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + // r = "xy/R mod m"; x,y != r + function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + + Montgomery.prototype.convert = montConvert; + Montgomery.prototype.revert = montRevert; + Montgomery.prototype.reduce = montReduce; + Montgomery.prototype.mulTo = montMulTo; + Montgomery.prototype.sqrTo = montSqrTo; + + // (protected) true iff this is even + function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } + + // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) + function bnpExp(e,z) { + if(e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; + g.copyTo(r); + while(--i >= 0) { + z.sqrTo(r,r2); + if((e&(1< 0) z.mulTo(r2,g,r); + else { var t = r; r = r2; r2 = t; } + } + return z.revert(r); + } + + // (public) this^e % m, 0 <= e < 2^32 + function bnModPowInt(e,m) { + var z; + if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e,z); + } + + // protected + BigInteger.prototype.copyTo = bnpCopyTo; + BigInteger.prototype.fromInt = bnpFromInt; + BigInteger.prototype.fromString = bnpFromString; + BigInteger.prototype.clamp = bnpClamp; + BigInteger.prototype.dlShiftTo = bnpDLShiftTo; + BigInteger.prototype.drShiftTo = bnpDRShiftTo; + BigInteger.prototype.lShiftTo = bnpLShiftTo; + BigInteger.prototype.rShiftTo = bnpRShiftTo; + BigInteger.prototype.subTo = bnpSubTo; + BigInteger.prototype.multiplyTo = bnpMultiplyTo; + BigInteger.prototype.squareTo = bnpSquareTo; + BigInteger.prototype.divRemTo = bnpDivRemTo; + BigInteger.prototype.invDigit = bnpInvDigit; + BigInteger.prototype.isEven = bnpIsEven; + BigInteger.prototype.exp = bnpExp; + + // public + BigInteger.prototype.toString = bnToString; + BigInteger.prototype.negate = bnNegate; + BigInteger.prototype.abs = bnAbs; + BigInteger.prototype.compareTo = bnCompareTo; + BigInteger.prototype.bitLength = bnBitLength; + BigInteger.prototype.mod = bnMod; + BigInteger.prototype.modPowInt = bnModPowInt; + + // "constants" + BigInteger.ZERO = nbv(0); + BigInteger.ONE = nbv(1); + + // jsbn2 stuff + + // (protected) convert from radix string + function bnpFromRadix(s,b) { + this.fromInt(0); + if(b == null) b = 10; + var cs = this.chunkSize(b); + var d = Math.pow(b,cs), mi = false, j = 0, w = 0; + for(var i = 0; i < s.length; ++i) { + var x = intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-" && this.signum() == 0) mi = true; + continue; + } + w = b*w+x; + if(++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w,0); + j = 0; + w = 0; + } + } + if(j > 0) { + this.dMultiply(Math.pow(b,j)); + this.dAddOffset(w,0); + } + if(mi) BigInteger.ZERO.subTo(this,this); + } + + // (protected) return x s.t. r^x < DV + function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } + + // (public) 0 if this == 0, 1 if this > 0 + function bnSigNum() { + if(this.s < 0) return -1; + else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; + else return 1; + } + + // (protected) this *= n, this >= 0, 1 < n < DV + function bnpDMultiply(n) { + this[this.t] = this.am(0,n-1,this,0,0,this.t); + ++this.t; + this.clamp(); + } + + // (protected) this += n << w words, this >= 0 + function bnpDAddOffset(n,w) { + if(n == 0) return; + while(this.t <= w) this[this.t++] = 0; + this[w] += n; + while(this[w] >= this.DV) { + this[w] -= this.DV; + if(++w >= this.t) this[this.t++] = 0; + ++this[w]; + } + } + + // (protected) convert to radix string + function bnpToRadix(b) { + if(b == null) b = 10; + if(this.signum() == 0 || b < 2 || b > 36) return "0"; + var cs = this.chunkSize(b); + var a = Math.pow(b,cs); + var d = nbv(a), y = nbi(), z = nbi(), r = ""; + this.divRemTo(d,y,z); + while(y.signum() > 0) { + r = (a+z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d,y,z); + } + return z.intValue().toString(b) + r; + } + + // (public) return value as integer + function bnIntValue() { + if(this.s < 0) { + if(this.t == 1) return this[0]-this.DV; + else if(this.t == 0) return -1; + } + else if(this.t == 1) return this[0]; + else if(this.t == 0) return 0; + // assumes 16 < DB < 32 + return ((this[1]&((1<<(32-this.DB))-1))<>= this.DB; + } + if(a.t < this.t) { + c += a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c += a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += a.s; + } + r.s = (c<0)?-1:0; + if(c > 0) r[i++] = c; + else if(c < -1) r[i++] = this.DV+c; + r.t = i; + r.clamp(); + } + + BigInteger.prototype.fromRadix = bnpFromRadix; + BigInteger.prototype.chunkSize = bnpChunkSize; + BigInteger.prototype.signum = bnSigNum; + BigInteger.prototype.dMultiply = bnpDMultiply; + BigInteger.prototype.dAddOffset = bnpDAddOffset; + BigInteger.prototype.toRadix = bnpToRadix; + BigInteger.prototype.intValue = bnIntValue; + BigInteger.prototype.addTo = bnpAddTo; + + //======= end jsbn ======= + + // Emscripten wrapper + var Wrapper = { + abs: function(l, h) { + var x = new goog.math.Long(l, h); + var ret; + if (x.isNegative()) { + ret = x.negate(); + } else { + ret = x; + } + HEAP32[tempDoublePtr>>2] = ret.low_; + HEAP32[tempDoublePtr+4>>2] = ret.high_; + }, + ensureTemps: function() { + if (Wrapper.ensuredTemps) return; + Wrapper.ensuredTemps = true; + Wrapper.two32 = new BigInteger(); + Wrapper.two32.fromString('4294967296', 10); + Wrapper.two64 = new BigInteger(); + Wrapper.two64.fromString('18446744073709551616', 10); + Wrapper.temp1 = new BigInteger(); + Wrapper.temp2 = new BigInteger(); + }, + lh2bignum: function(l, h) { + var a = new BigInteger(); + a.fromString(h.toString(), 10); + var b = new BigInteger(); + a.multiplyTo(Wrapper.two32, b); + var c = new BigInteger(); + c.fromString(l.toString(), 10); + var d = new BigInteger(); + c.addTo(b, d); + return d; + }, + stringify: function(l, h, unsigned) { + var ret = new goog.math.Long(l, h).toString(); + if (unsigned && ret[0] == '-') { + // unsign slowly using jsbn bignums + Wrapper.ensureTemps(); + var bignum = new BigInteger(); + bignum.fromString(ret, 10); + ret = new BigInteger(); + Wrapper.two64.addTo(bignum, ret); + ret = ret.toString(10); + } + return ret; + }, + fromString: function(str, base, min, max, unsigned) { + Wrapper.ensureTemps(); + var bignum = new BigInteger(); + bignum.fromString(str, base); + var bigmin = new BigInteger(); + bigmin.fromString(min, 10); + var bigmax = new BigInteger(); + bigmax.fromString(max, 10); + if (unsigned && bignum.compareTo(BigInteger.ZERO) < 0) { + var temp = new BigInteger(); + bignum.addTo(Wrapper.two64, temp); + bignum = temp; + } + var error = false; + if (bignum.compareTo(bigmin) < 0) { + bignum = bigmin; + error = true; + } else if (bignum.compareTo(bigmax) > 0) { + bignum = bigmax; + error = true; + } + var ret = goog.math.Long.fromString(bignum.toString()); // min-max checks should have clamped this to a range goog.math.Long can handle well + HEAP32[tempDoublePtr>>2] = ret.low_; + HEAP32[tempDoublePtr+4>>2] = ret.high_; + if (error) throw 'range error'; + } + }; + return Wrapper; +})(); + +//======= end closure i64 code ======= + + + +// === Auto-generated postamble setup entry stuff === + +if (memoryInitializer) { + if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) { + var data = Module['readBinary'](memoryInitializer); + HEAPU8.set(data, STATIC_BASE); + } else { + addRunDependency('memory initializer'); + Browser.asyncLoad(memoryInitializer, function(data) { + HEAPU8.set(data, STATIC_BASE); + removeRunDependency('memory initializer'); + }, function(data) { + throw 'could not load memory initializer ' + memoryInitializer; + }); + } +} + +function ExitStatus(status) { + this.name = "ExitStatus"; + this.message = "Program terminated with exit(" + status + ")"; + this.status = status; +}; +ExitStatus.prototype = new Error(); +ExitStatus.prototype.constructor = ExitStatus; + +var initialStackTop; +var preloadStartTime = null; +var calledMain = false; + +dependenciesFulfilled = function runCaller() { + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!Module['calledRun'] && shouldRunNow) run(); + if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled +} + +Module['callMain'] = Module.callMain = function callMain(args) { + assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)'); + assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called'); + + args = args || []; + + ensureInitRuntime(); + + var argc = args.length+1; + function pad() { + for (var i = 0; i < 4-1; i++) { + argv.push(0); + } + } + var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL) ]; + pad(); + for (var i = 0; i < argc-1; i = i + 1) { + argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL)); + pad(); + } + argv.push(0); + argv = allocate(argv, 'i32', ALLOC_NORMAL); + + initialStackTop = STACKTOP; + + try { + + var ret = Module['_main'](argc, argv, 0); + + + // if we're not running an evented main loop, it's time to exit + if (!Module['noExitRuntime']) { + exit(ret); + } + } + catch(e) { + if (e instanceof ExitStatus) { + // exit() throws this once it's done to make sure execution + // has been stopped completely + return; + } else if (e == 'SimulateInfiniteLoop') { + // running an evented main loop, don't immediately exit + Module['noExitRuntime'] = true; + return; + } else { + if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]); + throw e; + } + } finally { + calledMain = true; + } +} + + + + +function run(args) { + args = args || Module['arguments']; + + if (preloadStartTime === null) preloadStartTime = Date.now(); + + if (runDependencies > 0) { + Module.printErr('run() called, but dependencies remain, so not running'); + return; + } + + preRun(); + + if (runDependencies > 0) return; // a preRun added a dependency, run will be called later + if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame + + function doRun() { + if (Module['calledRun']) return; // run may have just been called while the async setStatus time below was happening + Module['calledRun'] = true; + + ensureInitRuntime(); + + preMain(); + + if (ENVIRONMENT_IS_WEB && preloadStartTime !== null) { + Module.printErr('pre-main prep time: ' + (Date.now() - preloadStartTime) + ' ms'); + } + + if (Module['_main'] && shouldRunNow) { + Module['callMain'](args); + } + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + if (!ABORT) doRun(); + }, 1); + } else { + doRun(); + } +} +Module['run'] = Module.run = run; + +function exit(status) { + ABORT = true; + EXITSTATUS = status; + STACKTOP = initialStackTop; + + // exit the runtime + exitRuntime(); + + // TODO We should handle this differently based on environment. + // In the browser, the best we can do is throw an exception + // to halt execution, but in node we could process.exit and + // I'd imagine SM shell would have something equivalent. + // This would let us set a proper exit status (which + // would be great for checking test exit statuses). + // https://github.com/kripken/emscripten/issues/1371 + + // throw an exception to halt the current execution + throw new ExitStatus(status); +} +Module['exit'] = Module.exit = exit; + +function abort(text) { + if (text) { + Module.print(text); + Module.printErr(text); + } + + ABORT = true; + EXITSTATUS = 1; + + var extra = '\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.'; + + throw 'abort() at ' + stackTrace() + extra; +} +Module['abort'] = Module.abort = abort; + +// {{PRE_RUN_ADDITIONS}} + +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} + +// shouldRunNow refers to calling main(), not run(). +var shouldRunNow = true; +if (Module['noInitialRun']) { + shouldRunNow = false; +} + + +run(); + +// {{POST_RUN_ADDITIONS}} + + + + + + +// {{MODULE_ADDITIONS}} + + + + + +Module['arrfile'] = function(filename, arr) { + try{ FS.unlink("/" + filename); } + catch(e){ ; } + FS.createDataFile("/", filename, arr, true, true); + return {path: filename, size: arr.byteLength}; +}; + +Module['gzcompress'] = function(data) { // TODO: Accept strings + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['output.gz', 'wb']); + var buffer = _malloc(data.length); + HEAPU8.set(data, buffer); + ccall('gzwrite', 'number', ['number', 'number', 'number'], [gzFile, buffer, data.length]); + ccall('gzclose', 'number', ['number'], [gzFile]); + _free(buffer); + var ret = new Uint8Array(FS.root.contents['output.gz'].contents); + FS.unlink('output.gz'); + return ret; +}; + +Module['gzdecompress'] = function(data) { + var BUFSIZE = 1024*1024; + FS.createDataFile('/', 'input.gz', data, true, true); + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['input.gz', 'rb']); + var buffer = _malloc(BUFSIZE); + var chunks = []; + var total = 0; + var len; + while( (len = ccall('gzread', 'number', ['number', 'number', 'number'], [gzFile, buffer, BUFSIZE])) > 0) { + chunks.push(new Uint8Array(len)); + chunks[chunks.length-1].set(HEAPU8.subarray(buffer, buffer+len)); + total += len; + } + ccall('gzclose', 'number', ['number'], [gzFile]); + FS.unlink('input.gz'); + _free(buffer); + var ret = new Uint8Array(total); + var curr = 0; + for (var i = 0; i < chunks.length; i++) { + ret.set(chunks[i], curr); + curr += chunks[i].length; + } + return ret; +}; + + + + return { + initwcs: Module.cwrap('initwcs', 'number', ['string', 'number']), + wcssys: Module.cwrap('wcssys', 'string', ['number', 'string']), + wcsunits: Module.cwrap('wcsunits', 'string', ['number', 'string']), + pix2wcs: Module.cwrap('pix2wcsstr', 'string', ['number', 'number', 'number']), + wcs2pix: Module.cwrap('wcs2pixstr', 'string', ['number', 'number', 'number']), + reg2wcs: Module.cwrap('reg2wcsstr', 'string', ['number', 'string']), + saostrtod: Module.cwrap('saostrtod', 'number', ['string']), + zscale: Module.cwrap('zscale', 'string', ['number', 'number', 'number', 'number', 'number', 'number']), + arrfile: Module["arrfile"], + gzopen: Module.cwrap('gzopen', 'number', ['string', 'string']), + gzread: Module.cwrap('gzread', 'number', ['number', 'number', 'number']), + gzwrite: Module.cwrap('gzwrite', 'number', ['number', 'number', 'number']), + gzclose: Module.cwrap('gzclose', 'number', ['number']), + gzseek: Module.cwrap('gzseek', 'number', ['number', 'number', 'number']), + compress: Module['gzcompress'], + decompress: Module['gzdecompress'] + }; +})(); + diff --git a/js9support.min.js b/js9support.min.js new file mode 100644 index 00000000..47640671 --- /dev/null +++ b/js9support.min.js @@ -0,0 +1,8105 @@ +/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="

    ",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; +if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
    Normal overlayImage with left/top = 0overlayImage with different propertiesStretched overlayImage #1 - width/height correspond to canvas width/heightStretched overlayImage #2 - width/height correspond to canvas width/heightNormal backgroundImage with left/top = 0backgroundImage with different propertiesStretched backgroundImage #1 - width/height correspond to canvas width/heightStretched backgroundImage #2 - width/height correspond to canvas width/heightNormal overlayColor - color valuefabric.Pattern used as overlayColorfabric.Pattern used as overlayColor with repeat and offsetNormal backgroundColor - color valuefabric.Pattern used as backgroundColorfabric.Pattern used as backgroundColor with repeat and offsetNormal SVG outputSVG output without preamble (without <?xml ../>)SVG output with viewBox attributeSVG output with different encoding (default: UTF-8)Modify SVG output with reviver functionGenerate jpeg dataURL with lower qualityGenerate cropped png dataURL (clipping of canvas)Generate double scaled png dataURLloadFromJSONloadFromJSON with reviverSet linear gradientSet radial gradientSet patternSet shadow with string notationSet shadow with object notationSharpen filterBlur filterEmboss filterEmboss filter with opaquenessTint filter with hex color and opacityTint filter with rgba colorMultiply filter with hex colorMultiply filter with rgb color
    a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:k.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("';window.frames["_iframe-"+ +a.id].location.replace(c)}else"ajax"==b&&this.ajax_connect(c,a);a.contentarea.datatype=b}},setupdrag:function(a){var b=dhtmlwindow,c=this._parent;b.etarget=this;a=window.event||a;a.touches&&a.touches.length?(b.initmousex=a.touches[0].clientX,b.initmousey=a.touches[0].clientY):(b.initmousex=a.clientX,b.initmousey=a.clientY);b.initx=parseInt(c.offsetLeft);b.inity=parseInt(c.offsetTop);b.width=parseInt(c.offsetWidth);b.contentheight=parseInt(c.contentarea.offsetHeight);"iframe"==c.contentarea.datatype&& +(c.style.backgroundColor="#F8F8F8",c.contentarea.style.visibility="hidden");document.onmousemove=b.getdistance;document.ontouchmove=b.getdistance;document.onmouseup=function(){"iframe"==c.contentarea.datatype&&(c.contentarea.style.backgroundColor="white",c.contentarea.style.visibility="visible");b.stop()};document.ontouchend=function(){"iframe"==c.contentarea.datatype&&(c.contentarea.style.backgroundColor="white",c.contentarea.style.visibility="visible");b.stop()};return!1},getdistance:function(a){var b= +dhtmlwindow,c=b.etarget;a=window.event||a;a.touches&&a.touches.length?(b.distancex=a.touches[0].clientX-b.initmousex,b.distancey=a.touches[0].clientY-b.initmousey):(b.distancex=a.clientX-b.initmousex,b.distancey=a.clientY-b.initmousey);"drag-handle"==c.className?b.move(c._parent,a):"drag-resizearea"==c.className&&b.resize(c._parent,a);return!1},getviewpoint:function(){var a=document.all&&!window.opera,b=document.documentElement&&parseInt(document.documentElement.clientWidth)||1E5;this.standardbody= +"CSS1Compat"==document.compatMode?document.documentElement:document.body;this.scroll_top=a?this.standardbody.scrollTop:window.pageYOffset;this.scroll_left=a?this.standardbody.scrollLeft:window.pageXOffset;this.docwidth=a?this.standardbody.clientWidth:/Safari/i.test(navigator.userAgent)?window.innerWidth:Math.min(b,window.innerWidth-16);this.docheight=a?this.standardbody.clientHeight:window.innerHeight},rememberattrs:function(a){this.getviewpoint();a.lastx=parseInt(a.style.left||a.offsetLeft)-dhtmlwindow.scroll_left; +a.lasty=parseInt(a.style.top||a.offsetTop)-dhtmlwindow.scroll_top;a.lastwidth=parseInt(a.style.width)},move:function(a){a.style.left=dhtmlwindow.distancex+dhtmlwindow.initx+"px";a.style.top=dhtmlwindow.distancey+dhtmlwindow.inity+"px"},resize:function(a){a.style.width=Math.max(dhtmlwindow.width+dhtmlwindow.distancex,150)+"px";a.contentarea.style.height=Math.max(dhtmlwindow.contentheight+dhtmlwindow.distancey,100)+"px"},enablecontrols:function(a){var b=dhtmlwindow;a=window.event?window.event.srcElement: +a.target;/Minimize/i.test(a.getAttribute("title"))?b.minimize(a,this._parent):/Restore/i.test(a.getAttribute("title"))?b.restore(a,this._parent):/Close/i.test(a.getAttribute("title"))&&b.close(this._parent);return!1},minimize:function(a,b){dhtmlwindow.rememberattrs(b);a.setAttribute("src",dhtmlwindow.imagefiles[2]);a.setAttribute("title","Restore");b.state="minimized";b.contentarea.style.display="none";b.statusarea.style.display="none";"undefined"==typeof b.minimizeorder&&(dhtmlwindow.minimizeorder++, +b.minimizeorder=dhtmlwindow.minimizeorder);b.style.left="10px";b.style.width="200px";b.style.top=dhtmlwindow.scroll_top+dhtmlwindow.docheight-b.handle.offsetHeight*b.minimizeorder-10*b.minimizeorder+"px"},restore:function(a,b){dhtmlwindow.getviewpoint();a.setAttribute("src",dhtmlwindow.imagefiles[0]);a.setAttribute("title","Minimize");b.state="fullview";b.style.display="block";b.contentarea.style.display="block";b.resizeBool&&(b.statusarea.style.display="block");b.style.left=parseInt(b.lastx)+dhtmlwindow.scroll_left+ +"px";b.style.top=parseInt(b.lasty)+dhtmlwindow.scroll_top+"px";b.style.width=parseInt(b.lastwidth)+"px"},close:function(a){try{var b=a.onclose()}catch(c){b=!0}finally{"undefined"==typeof b&&(alert('An error has occured somwhere inside your "onclose" event handler'),b=!0)}b&&("minimized"!=a.state&&dhtmlwindow.rememberattrs(a),window.frames["_iframe-"+a.id]?window.frames["_iframe-"+a.id].location.replace("about:blank"):a.contentarea.innerHTML="",a.style.display="none",a.isClosed=!0);return b},setopacity:function(a, +b){a&&(a.filters&&a.filters[0]?"number"==typeof a.filters[0].opacity?a.filters[0].opacity=100*b:a.style.filter="alpha(opacity="+100*b+")":"undefined"!=typeof a.style.MozOpacity?a.style.MozOpacity=b:"undefined"!=typeof a.style.opacity&&(a.style.opacity=b))},setfocus:function(a){this.zIndexvalue++;a.style.zIndex=this.zIndexvalue;a.isClosed=!1;this.setopacity(this.lastactivet.handle,0.5);this.setopacity(a.handle,1);this.lastactivet=a},show:function(a){a.isClosed?alert("DHTML Window has been closed, so nothing to show. Open/Create the window again."): +(a.lastx?dhtmlwindow.restore(a.controls.firstChild,a):a.style.display="block",this.setfocus(a),a.state="fullview")},hide:function(a){a.style.display="none"},ajax_connect:function(a,b){var c=!1,e="";if(window.XMLHttpRequest)c=new XMLHttpRequest;else if(window.ActiveXObject)try{c=new ActiveXObject("Msxml2.XMLHTTP")}catch(j){try{c=new ActiveXObject("Microsoft.XMLHTTP")}catch(f){}}else return!1;b.contentarea.innerHTML=this.ajaxloadinghtml;c.onreadystatechange=function(){dhtmlwindow.ajax_loadpage(c,b)}; +this.ajaxbustcache&&(e=-1!=a.indexOf("?")?"&"+(new Date).getTime():"?"+(new Date).getTime());c.open("GET",a+e,!0);c.send(null)},ajax_loadpage:function(a,b){if(4==a.readyState&&(200==a.status||-1==window.location.href.indexOf("http")))b.contentarea.innerHTML=a.responseText},stop:function(){dhtmlwindow.etarget=null;document.onmousemove=null;document.ontouchmove=null;document.onmouseup=null;document.ontouchend=null},addEvent:function(a,b,c){c=window.addEventListener?c:"on"+c;a.addEventListener?a.addEventListener(c, +b,!1):a.attachEvent&&a.attachEvent(c,b)},cleanup:function(){for(var a=0;a"),fabric.window=fabric.document.createWindow()),fabric.isTouchSupported="ontouchstart"in fabric.document.documentElement,fabric.isLikelyNode=typeof Buffer!="undefined"&&typeof window=="undefined",fabric.SHARED_ATTRIBUTES=["display","transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width"],fabric.DPI=96,function(){function e(e,t){if(!this.__eventListeners[e])return;t?fabric.util.removeFromArray(this.__eventListeners[e],t):this.__eventListeners[e].length=0}function t(e,t){this.__eventListeners||(this.__eventListeners={});if(arguments.length===1)for(var n in e)this.on(n,e[n]);else this.__eventListeners[e]||(this.__eventListeners[e]=[]),this.__eventListeners[e].push(t);return this}function n(t,n){if(!this.__eventListeners)return;if(arguments.length===0)this.__eventListeners={};else if(arguments.length===1&&typeof arguments[0]=="object")for(var r in t)e.call(this,r,t[r]);else e.call(this,t,n);return this}function r(e,t){if(!this.__eventListeners)return;var n=this.__eventListeners[e];if(!n)return;for(var r=0,i=n.length;r-1},complexity:function(){return this.getObjects().reduce(function(e,t){return e+=t.complexity?t.complexity():0,e},0)}},function(e){var t=Math.sqrt,n=Math.atan2,r=Math.PI/180;fabric.util={removeFromArray:function(e,t){var n=e.indexOf(t);return n!==-1&&e.splice(n,1),e},getRandomInt:function(e,t){return Math.floor(Math.random()*(t-e+1))+e},degreesToRadians:function(e){return e*r},radiansToDegrees:function(e){return e/r},rotatePoint:function(e,t,n){var r=Math.sin(n),i=Math.cos(n);e.subtractEquals(t);var s=e.x*i-e.y*r,o=e.x*r+e.y*i;return(new fabric.Point(s,o)).addEquals(t)},transformPoint:function(e,t,n){return n?new fabric.Point(t[0]*e.x+t[1]*e.y,t[2]*e.x+t[3]*e.y):new fabric.Point(t[0]*e.x+t[1]*e.y+t[4],t[2]*e.x+t[3]*e.y+t[5])},invertTransform:function(e){var t=e.slice(),n=1/(e[0]*e[3]-e[1]*e[2]);t=[n*e[3],-n*e[1],-n*e[2],n*e[0],0,0];var r=fabric.util.transformPoint({x:e[4],y:e[5]},t);return t[4]=-r.x,t[5]=-r.y,t},toFixed:function(e,t){return parseFloat(Number(e).toFixed(t))},parseUnit:function(e){var t=/\D{0,2}$/.exec(e),n=parseFloat(e);switch(t[0]){case"mm":return n*fabric.DPI/25.4;case"cm":return n*fabric.DPI/2.54;case"in":return n*fabric.DPI;case"pt":return n*fabric.DPI/72;case"pc":return n*fabric.DPI/72*12;default:return n}},falseFunction:function(){return!1},getKlass:function(e,t){return e=fabric.util.string.camelize(e.charAt(0).toUpperCase()+e.slice(1)),fabric.util.resolveNamespace(t)[e]},resolveNamespace:function(t){if(!t)return fabric;var n=t.split("."),r=n.length,i=e||fabric.window;for(var s=0;sr)r+=u[p++%h],r>l&&(r=l),e[d?"lineTo":"moveTo"](r,0),d=!d;e.restore()},createCanvasElement:function(e){return e||(e=fabric.document.createElement("canvas")),!e.getContext&&typeof G_vmlCanvasManager!="undefined"&&G_vmlCanvasManager.initElement(e),e},createImage:function(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")},createAccessors:function(e){var t=e.prototype;for(var n=t.stateProperties.length;n--;){var r=t.stateProperties[n],i=r.charAt(0).toUpperCase()+r.slice(1),s="set"+i,o="get"+i;t[o]||(t[o]=function(e){return new Function('return this.get("'+e+'")')}(r)),t[s]||(t[s]=function(e){return new Function("value",'return this.set("'+e+'", value)')}(r))}},clipContext:function(e,t){t.save(),t.beginPath(),e.clipTo(t),t.clip()},multiplyTransformMatrices:function(e,t){var n=[[e[0],e[2],e[4]],[e[1],e[3],e[5]],[0,0,1]],r=[[t[0],t[2],t[4]],[t[1],t[3],t[5]],[0,0,1]],i=[];for(var s=0;s<3;s++){i[s]=[];for(var o=0;o<3;o++){var u=0;for(var a=0;a<3;a++)u+=n[s][a]*r[a][o];i[s][o]=u}}return[i[0][0],i[1][0],i[0][1],i[1][1],i[0][2],i[1][2]]},getFunctionBody:function(e){return(String(e).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},isTransparent:function(e,t,n,r){r>0&&(t>r?t-=r:t=0,n>r?n-=r:n=0);var i=!0,s=e.getImageData(t,n,r*2||1,r*2||1);for(var o=3,u=s.data.length;o0?_-=2*h:f===1&&_<0&&(_+=2*h);var D=Math.ceil(Math.abs(_/(h*.5))),P=[],H=_/D,B=8/3*Math.sin(H/4)*Math.sin(H/4)/Math.sin(H/2),j=M+H;for(var F=0;F=i?s-i:2*Math.PI-(i-s)}var e={},t={},n=Array.prototype.join;fabric.util.drawArc=function(e,t,n,i){var s=i[0],o=i[1],u=i[2],a=i[3],f=i[4],l=i[5],c=i[6],h=[[],[],[],[]],p=r(l-t,c-n,s,o,a,f,u);for(var d=0;d=t})}function r(e,t){return i(e,t,function(e,t){return e>>0;if(n===0)return-1;var r=0;arguments.length>0&&(r=Number(arguments[1]),r!==r?r=0:r!==0&&r!==Number.POSITIVE_INFINITY&&r!==Number.NEGATIVE_INFINITY&&(r=(r>0||-1)*Math.floor(Math.abs(r))));if(r>=n)return-1;var i=r>=0?r:Math.max(n-Math.abs(r),0);for(;i>>0;n>>0;r>>0;n>>0;n>>0;i>>0,n=0,r;if(arguments.length>1)r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n/g,">")}String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^[\s\xA0]+/,"").replace(/[\s\xA0]+$/,"")}),fabric.util.string={camelize:e,capitalize:t,escapeXml:n}}(),function(){var e=Array.prototype.slice,t=Function.prototype.apply,n=function(){};Function.prototype.bind||(Function.prototype.bind=function(r){var i=this,s=e.call(arguments,1),o;return s.length?o=function(){return t.call(i,this instanceof n?this:r,s.concat(e.call(arguments)))}:o=function(){return t.call(i,this instanceof n?this:r,arguments)},n.prototype=this.prototype,o.prototype=new n,o})}(),function(){function i(){}function s(t){var n=this.constructor.superclass.prototype[t];return arguments.length>1?n.apply(this,e.call(arguments,1)):n.call(this)}function o(){function u(){this.initialize.apply(this,arguments)}var n=null,o=e.call(arguments,0);typeof o[0]=="function"&&(n=o.shift()),u.superclass=n,u.subclasses=[],n&&(i.prototype=n.prototype,u.prototype=new i,n.subclasses.push(u));for(var a=0,f=o.length;a-1?e.prototype[i]=function(e){return function(){var n=this.constructor.superclass;this.constructor.superclass=r;var i=t[e].apply(this,arguments);this.constructor.superclass=n;if(e!=="initialize")return i}}(i):e.prototype[i]=t[i],n&&(t.toString!==Object.prototype.toString&&(e.prototype.toString=t.toString),t.valueOf!==Object.prototype.valueOf&&(e.prototype.valueOf=t.valueOf))};fabric.util.createClass=o}(),function(){function t(e){var t=Array.prototype.slice.call(arguments,1),n,r,i=t.length;for(r=0;r-1?s(e,t.match(/opacity:\s*(\d?\.?\d*)/)[1]):e;for(var r in t)if(r==="opacity")s(e,t[r]);else{var i=r==="float"||r==="cssFloat"?typeof n.styleFloat=="undefined"?"cssFloat":"styleFloat":r;n[i]=t[r]}return e}var t=fabric.document.createElement("div"),n=typeof t.style.opacity=="string",r=typeof t.style.filter=="string",i=/alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,s=function(e){return e};n?s=function(e,t){return e.style.opacity=t,e}:r&&(s=function(e,t){var n=e.style;return e.currentStyle&&!e.currentStyle.hasLayout&&(n.zoom=1),i.test(n.filter)?(t=t>=.9999?"":"alpha(opacity="+t*100+")",n.filter=n.filter.replace(i,t)):n.filter+=" alpha(opacity="+t*100+")",e}),fabric.util.setStyle=e}(),function(){function t(e){return typeof e=="string"?fabric.document.getElementById(e):e}function s(e,t){var n=fabric.document.createElement(e);for(var r in t)r==="class"?n.className=t[r]:r==="for"?n.htmlFor=t[r]:n.setAttribute(r,t[r]);return n}function o(e,t){e&&(" "+e.className+" ").indexOf(" "+t+" ")===-1&&(e.className+=(e.className?" ":"")+t)}function u(e,t,n){return typeof t=="string"&&(t=s(t,n)),e.parentNode&&e.parentNode.replaceChild(t,e),t.appendChild(e),t}function a(e,t){var n,r,i=0,s=0,o=fabric.document.documentElement,u=fabric.document.body||{scrollLeft:0,scrollTop:0};r=e;while(e&&e.parentNode&&!n)e=e.parentNode,e!==fabric.document&&fabric.util.getElementStyle(e,"position")==="fixed"&&(n=e),e!==fabric.document&&r!==t&&fabric.util.getElementStyle(e,"position")==="absolute"?(i=0,s=0):e===fabric.document?(i=u.scrollLeft||o.scrollLeft||0,s=u.scrollTop||o.scrollTop||0):(i+=e.scrollLeft||0,s+=e.scrollTop||0);return{left:i,top:s}}function f(e){var t,n=e&&e.ownerDocument,r={left:0,top:0},i={left:0,top:0},s,o={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!n)return{left:0,top:0};for(var u in o)i[o[u]]+=parseInt(l(e,u),10)||0;return t=n.documentElement,typeof e.getBoundingClientRect!="undefined"&&(r=e.getBoundingClientRect()),s=fabric.util.getScrollLeftTop(e,null),{left:r.left+s.left-(t.clientLeft||0)+i.left,top:r.top+s.top-(t.clientTop||0)+i.top}}var e=Array.prototype.slice,n,r=function(t){return e.call(t,0)};try{n=r(fabric.document.childNodes)instanceof Array}catch(i){}n||(r=function(e){var t=new Array(e.length),n=e.length;while(n--)t[n]=e[n];return t});var l;fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle?l=function(e,t){return fabric.document.defaultView.getComputedStyle(e,null)[t]}:l=function(e,t){var n=e.style[t];return!n&&e.currentStyle&&(n=e.currentStyle[t]),n},function(){function n(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=fabric.util.falseFunction),t?e.style[t]="none":typeof e.unselectable=="string"&&(e.unselectable="on"),e}function r(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=null),t?e.style[t]="":typeof e.unselectable=="string"&&(e.unselectable=""),e}var e=fabric.document.documentElement.style,t="userSelect"in e?"userSelect":"MozUserSelect"in e?"MozUserSelect":"WebkitUserSelect"in e?"WebkitUserSelect":"KhtmlUserSelect"in e?"KhtmlUserSelect":"";fabric.util.makeElementUnselectable=n,fabric.util.makeElementSelectable=r}(),function(){function e(e,t){var n=fabric.document.getElementsByTagName("head")[0],r=fabric.document.createElement("script"),i=!0;r.onload=r.onreadystatechange=function(e){if(i){if(typeof this.readyState=="string"&&this.readyState!=="loaded"&&this.readyState!=="complete")return;i=!1,t(e||fabric.window.event),r=r.onload=r.onreadystatechange=null}},r.src=e,n.appendChild(r)}fabric.util.getScript=e}(),fabric.util.getById=t,fabric.util.toArray=r,fabric.util.makeElement=s,fabric.util.addClass=o,fabric.util.wrapElement=u,fabric.util.getScrollLeftTop=a,fabric.util.getElementOffset=f,fabric.util.getElementStyle=l}(),function(){function e(e,t){return e+(/\?/.test(e)?"&":"?")+t}function n(){}function r(r,i){i||(i={});var s=i.method?i.method.toUpperCase():"GET",o=i.onComplete||function(){},u=t(),a;return u.onreadystatechange=function(){u.readyState===4&&(o(u),u.onreadystatechange=n)},s==="GET"&&(a=null,typeof i.parameters=="string"&&(r=e(r,i.parameters))),u.open(s,r,!0),(s==="POST"||s==="PUT")&&u.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),u.send(a),u}var t=function(){var e=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0")},function(){return new XMLHttpRequest}];for(var t=e.length;t--;)try{var n=e[t]();if(n)return e[t]}catch(r){}}();fabric.util.request=r}(),fabric.log=function(){},fabric.warn=function(){},typeof console!="undefined"&&["log","warn"].forEach(function(e){typeof console[e]!="undefined"&&console[e].apply&&(fabric[e]=function(){return console[e].apply(console,arguments)})}),function(){function e(e){n(function(t){e||(e={});var r=t||+(new Date),i=e.duration||500,s=r+i,o,u=e.onChange||function(){},a=e.abort||function(){return!1},f=e.easing||function(e,t,n,r){return-n*Math.cos(e/r*(Math.PI/2))+n+t},l="startValue"in e?e.startValue:0,c="endValue"in e?e.endValue:100,h=e.byValue||c-l;e.onStart&&e.onStart(),function p(t){o=t||+(new Date);var c=o>s?i:o-r;if(a()){e.onComplete&&e.onComplete();return}u(f(c,l,h,i));if(o>s){e.onComplete&&e.onComplete();return}n(p)}(r)})}function n(){return t.apply(fabric.window,arguments)}var t=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(e){fabric.window.setTimeout(e,1e3/60)};fabric.util.animate=e,fabric.util.requestAnimFrame=n}(),function(){function e(e,t,n,r){return et[3]?t[3]:t[0];if(t[0]===1&&t[3]===1&&t[4]===0&&t[5]===0)return;var n=e.ownerDocument.createElement("g");while(e.firstChild!=null)n.appendChild(e.firstChild);n.setAttribute("transform","matrix("+t[0]+" "+t[1]+" "+t[2]+" "+t[3]+" "+t[4]+" "+t[5]+")"),e.appendChild(n)}function x(e){var n=e.objects,i=e.options;return n=n.map(function(e){return t[r(e.type)].fromObject(e)}),{objects:n,options:i}}function T(e,t,n){t[n]&&t[n].toSVG&&e.push('','')}var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.string.capitalize,i=t.util.object.clone,s=t.util.toFixed,o=t.util.parseUnit,u=t.util.multiplyTransformMatrices,a={cx:"left",x:"left",r:"radius",cy:"top",y:"top",display:"visible",visibility:"visible",transform:"transformMatrix","fill-opacity":"fillOpacity","fill-rule":"fillRule","font-family":"fontFamily","font-size":"fontSize","font-style":"fontStyle","font-weight":"fontWeight","stroke-dasharray":"strokeDashArray","stroke-linecap":"strokeLineCap","stroke-linejoin":"strokeLineJoin","stroke-miterlimit":"strokeMiterLimit","stroke-opacity":"strokeOpacity","stroke-width":"strokeWidth","text-decoration":"textDecoration","text-anchor":"originX"},f={stroke:"strokeOpacity",fill:"fillOpacity"};t.parseTransformAttribute=function(){function e(e,t){var n=t[0];e[0]=Math.cos(n),e[1]=Math.sin(n),e[2]=-Math.sin(n),e[3]=Math.cos(n)}function n(e,t){var n=t[0],r=t.length===2?t[1]:t[0];e[0]=n,e[3]=r}function r(e,t){e[2]=t[0]}function i(e,t){e[1]=t[0]}function s(e,t){e[4]=t[0],t.length===2&&(e[5]=t[1])}var o=[1,0,0,1,0,0],u="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",a="(?:\\s+,?\\s*|,\\s*)",f="(?:(skewX)\\s*\\(\\s*("+u+")\\s*\\))",l="(?:(skewY)\\s*\\(\\s*("+u+")\\s*\\))",c="(?:(rotate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+")"+a+"("+u+"))?\\s*\\))",h="(?:(scale)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",p="(?:(translate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",d="(?:(matrix)\\s*\\(\\s*("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+"\\s*\\))",v="(?:"+d+"|"+p+"|"+h+"|"+c+"|"+f+"|"+l+")",m="(?:"+v+"(?:"+a+v+")*"+")",g="^\\s*(?:"+m+"?)\\s*$",y=new RegExp(g),b=new RegExp(v,"g");return function(u){var a=o.concat(),f=[];if(!u||u&&!y.test(u))return a;u.replace(b,function(u){var l=(new RegExp(v)).exec(u).filter(function(e){return e!==""&&e!=null}),c=l[1],h=l.slice(2).map(parseFloat);switch(c){case"translate":s(a,h);break;case"rotate":h[0]=t.util.degreesToRadians(h[0]),e(a,h);break;case"scale":n(a,h);break;case"skewX":r(a,h);break;case"skewY":i(a,h);break;case"matrix":a=h}f.push(a.concat()),a=o.concat()});var l=f[0];while(f.length>1)f.shift(),l=t.util.multiplyTransformMatrices(l,f[0]);return l}}(),t.parseSVGDocument=function(){function s(e,t){while(e&&(e=e.parentNode))if(t.test(e.nodeName))return!0;return!1}var e=/^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/,n="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",r=new RegExp("^\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*"+"$");return function(n,u,a){if(!n)return;var f=new Date;w(n);var l=n.getAttribute("viewBox"),c=o(n.getAttribute("width")),h=o(n.getAttribute("height")),p,d;if(l&&(l=l.match(r))){var v=parseFloat(l[1]),m=parseFloat(l[2]),g=1,y=1;p=parseFloat(l[3]),d=parseFloat(l[4]),c&&c!==p&&(g=c/p),h&&h!==d&&(y=h/d),E(n,[g,0,0,y,g*-v,y*-m])}var b=t.util.toArray(n.getElementsByTagName("*"));if(b.length===0&&t.isLikelyNode){b=n.selectNodes('//*[name(.)!="svg"]');var S=[];for(var x=0,T=b.length;x/i,"")));if(!s||!s.documentElement)return;t.parseSVGDocument(s.documentElement,function(r,i){S.set(e,{objects:t.util.array.invoke(r,"toObject"),options:i}),n(r,i)},r)}e=e.replace(/^\n\s*/,"").trim(),S.has(e,function(r){r?S.get(e,function(e){var t=x(e);n(t.objects,t.options)}):new t.util.request(e,{method +:"get",onComplete:i})})},loadSVGFromString:function(e,n,r){e=e.trim();var i;if(typeof DOMParser!="undefined"){var s=new DOMParser;s&&s.parseFromString&&(i=s.parseFromString(e,"text/xml"))}else t.window.ActiveXObject&&(i=new ActiveXObject("Microsoft.XMLDOM"),i.async="false",i.loadXML(e.replace(//i,"")));t.parseSVGDocument(i.documentElement,function(e,t){n(e,t)},r)},createSVGFontFacesMarkup:function(e){var t="";for(var n=0,r=e.length;n',"",""].join("")),t},createSVGRefElementsMarkup:function(e){var t=[];return T(t,e,"backgroundColor"),T(t,e,"overlayColor"),t.join("")}})}(typeof exports!="undefined"?exports:this),fabric.ElementsParser=function(e,t,n,r){this.elements=e,this.callback=t,this.options=n,this.reviver=r},fabric.ElementsParser.prototype.parse=function(){this.instances=new Array(this.elements.length),this.numElements=this.elements.length,this.createObjects()},fabric.ElementsParser.prototype.createObjects=function(){for(var e=0,t=this.elements.length;ee.x&&this.y>e.y},gte:function(e){return this.x>=e.x&&this.y>=e.y},lerp:function(e,t){return new n(this.x+(e.x-this.x)*t,this.y+(e.y-this.y)*t)},distanceFrom:function(e){var t=this.x-e.x,n=this.y-e.y;return Math.sqrt(t*t+n*n)},midPointFrom:function(e){return new n(this.x+(e.x-this.x)/2,this.y+(e.y-this.y)/2)},min:function(e){return new n(Math.min(this.x,e.x),Math.min(this.y,e.y))},max:function(e){return new n(Math.max(this.x,e.x),Math.max(this.y,e.y))},toString:function(){return this.x+","+this.y},setXY:function(e,t){this.x=e,this.y=t},setFromPoint:function(e){this.x=e.x,this.y=e.y},swap:function(e){var t=this.x,n=this.y;this.x=e.x,this.y=e.y,e.x=t,e.y=n}}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function n(e){this.status=e,this.points=[]}var t=e.fabric||(e.fabric={});if(t.Intersection){t.warn("fabric.Intersection is already defined");return}t.Intersection=n,t.Intersection.prototype={appendPoint:function(e){this.points.push(e)},appendPoints:function(e){this.points=this.points.concat(e)}},t.Intersection.intersectLineLine=function(e,r,i,s){var o,u=(s.x-i.x)*(e.y-i.y)-(s.y-i.y)*(e.x-i.x),a=(r.x-e.x)*(e.y-i.y)-(r.y-e.y)*(e.x-i.x),f=(s.y-i.y)*(r.x-e.x)-(s.x-i.x)*(r.y-e.y);if(f!==0){var l=u/f,c=a/f;0<=l&&l<=1&&0<=c&&c<=1?(o=new n("Intersection"),o.points.push(new t.Point(e.x+l*(r.x-e.x),e.y+l*(r.y-e.y)))):o=new n}else u===0||a===0?o=new n("Coincident"):o=new n("Parallel");return o},t.Intersection.intersectLinePolygon=function(e,t,r){var i=new n,s=r.length;for(var o=0;o0&&(i.status="Intersection"),i},t.Intersection.intersectPolygonPolygon=function(e,t){var r=new n,i=e.length;for(var s=0;s0&&(r.status="Intersection"),r},t.Intersection.intersectPolygonRectangle=function(e,r,i){var s=r.min(i),o=r.max(i),u=new t.Point(o.x,s.y),a=new t.Point(s.x,o.y),f=n.intersectLinePolygon(s,u,e),l=n.intersectLinePolygon(u,o,e),c=n.intersectLinePolygon(o,a,e),h=n.intersectLinePolygon(a,s,e),p=new n;return p.appendPoints(f.points),p.appendPoints(l.points),p.appendPoints(c.points),p.appendPoints(h.points),p.points.length>0&&(p.status="Intersection"),p}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function n(e){e?this._tryParsingColor(e):this.setSource([0,0,0,1])}function r(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*6*n:n<.5?t:n<2/3?e+(t-e)*(2/3-n)*6:e}var t=e.fabric||(e.fabric={});if(t.Color){t.warn("fabric.Color is already defined.");return}t.Color=n,t.Color.prototype={_tryParsingColor:function(e){var t;e in n.colorNameMap&&(e=n.colorNameMap[e]);if(e==="transparent"){this.setSource([255,255,255,0]);return}t=n.sourceFromHex(e),t||(t=n.sourceFromRgb(e)),t||(t=n.sourceFromHsl(e)),t&&this.setSource(t)},_rgbToHsl:function(e,n,r){e/=255,n/=255,r/=255;var i,s,o,u=t.util.array.max([e,n,r]),a=t.util.array.min([e,n,r]);o=(u+a)/2;if(u===a)i=s=0;else{var f=u-a;s=o>.5?f/(2-u-a):f/(u+a);switch(u){case e:i=(n-r)/f+(n\n']:this.type==="radial"&&(r=["\n']);for(var o=0;o\n');return r.push(this.type==="linear"?"\n":"\n"),r.join("")},toLive:function(e){var t;if(!this.type)return;this.type==="linear"?t=e.createLinearGradient(this.coords.x1,this.coords.y1,this.coords.x2,this.coords.y2):this.type==="radial"&&(t=e.createRadialGradient(this.coords.x1,this.coords.y1,this.coords.r1,this.coords.x2,this.coords.y2,this.coords.r2));for(var n=0,r=this.colorStops.length;n'+''+""},toLive:function(e){var t=typeof this.source=="function"?this.source():this.source;if(!t)return"";if(typeof t.src!="undefined"){if(!t.complete)return"";if(t.naturalWidth===0||t.naturalHeight===0)return""}return e.createPattern(t,this.repeat)}}),function(e){"use strict";var t=e.fabric||(e.fabric={});if(t.Shadow){t.warn("fabric.Shadow is already defined.");return}t.Shadow=t.util.createClass({color:"rgb(0,0,0)",blur:0,offsetX:0,offsetY:0,affectStroke:!1,includeDefaultValues:!0,initialize:function(e){typeof e=="string"&&(e=this._parseShadow(e));for(var n in e)this[n]=e[n];this.id=t.Object.__uid++},_parseShadow:function(e){var n=e.trim(),r=t.Shadow.reOffsetsAndBlur.exec(n)||[],i=n.replace(t.Shadow.reOffsetsAndBlur,"")||"rgb(0,0,0)";return{color:i.trim(),offsetX:parseInt(r[1],10)||0,offsetY:parseInt(r[2],10)||0,blur:parseInt(r[3],10)||0}},toString:function(){return[this.offsetX,this.offsetY,this.blur,this.color].join("px ")},toSVG:function(e){var t="SourceAlpha";return e&&(e.fill===this.color||e.stroke===this.color)&&(t="SourceGraphic"),''+''+''+""+""+''+""+""},toObject:function(){if(this.includeDefaultValues)return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY};var e={},n=t.Shadow.prototype;return this.color!==n.color&&(e.color=this.color),this.blur!==n.blur&&(e.blur=this.blur),this.offsetX!==n.offsetX&&(e.offsetX=this.offsetX),this.offsetY!==n.offsetY&&(e.offsetY=this.offsetY),e}}),t.Shadow.reOffsetsAndBlur=/(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/}(typeof exports!="undefined"?exports:this),function(){"use strict";if(fabric.StaticCanvas){fabric.warn("fabric.StaticCanvas is already defined.");return}var e=fabric.util.object.extend,t=fabric.util.getElementOffset,n=fabric.util.removeFromArray,r=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass({initialize:function(e,t){t||(t={}),this._initStatic(e,t),fabric.StaticCanvas.activeInstance=this},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:!0,stateful:!0,renderOnAddRemove:!0,clipTo:null,controlsAboveOverlay:!1,allowTouchScrolling:!1,imageSmoothingEnabled:!0,viewportTransform:[1,0,0,1,0,0],onBeforeScaleRotate:function(){},_initStatic:function(e,t){this._objects=[],this._createLowerCanvas(e),this._initOptions(t),this._setImageSmoothing(),t.overlayImage&&this.setOverlayImage(t.overlayImage,this.renderAll.bind(this)),t.backgroundImage&&this.setBackgroundImage(t.backgroundImage,this.renderAll.bind(this)),t.backgroundColor&&this.setBackgroundColor(t.backgroundColor,this.renderAll.bind(this)),t.overlayColor&&this.setOverlayColor(t.overlayColor,this.renderAll.bind(this)),this.calcOffset()},calcOffset:function(){return this._offset=t(this.lowerCanvasEl),this},setOverlayImage:function(e,t,n){return this.__setBgOverlayImage("overlayImage",e,t,n)},setBackgroundImage:function(e,t,n){return this.__setBgOverlayImage("backgroundImage",e,t,n)},setOverlayColor:function(e,t){return this.__setBgOverlayColor("overlayColor",e,t)},setBackgroundColor:function(e,t){return this.__setBgOverlayColor("backgroundColor",e,t)},_setImageSmoothing:function(){var e=this.getContext();e.imageSmoothingEnabled=this.imageSmoothingEnabled,e.webkitImageSmoothingEnabled=this.imageSmoothingEnabled,e.mozImageSmoothingEnabled=this.imageSmoothingEnabled,e.msImageSmoothingEnabled=this.imageSmoothingEnabled,e.oImageSmoothingEnabled=this.imageSmoothingEnabled},__setBgOverlayImage:function(e,t,n,r){return typeof t=="string"?fabric.util.loadImage(t,function(t){this[e]=new fabric.Image(t,r),n&&n()},this):(this[e]=t,n&&n()),this},__setBgOverlayColor:function(e,t,n){if(t&&t.source){var r=this;fabric.util.loadImage(t.source,function(i){r[e]=new fabric.Pattern({source:i,repeat:t.repeat,offsetX:t.offsetX,offsetY:t.offsetY}),n&&n()})}else this[e]=t,n&&n();return this},_createCanvasElement:function(){var e=fabric.document.createElement("canvas");e.style||(e.style={});if(!e)throw r;return this._initCanvasElement(e),e},_initCanvasElement:function(e){fabric.util.createCanvasElement(e);if(typeof e.getContext=="undefined")throw r},_initOptions:function(e){for(var t in e)this[t]=e[t];this.width=this.width||parseInt(this.lowerCanvasEl.width,10)||0,this.height=this.height||parseInt(this.lowerCanvasEl.height,10)||0;if(!this.lowerCanvasEl.style)return;this.lowerCanvasEl.width=this.width,this.lowerCanvasEl.height=this.height,this.lowerCanvasEl.style.width=this.width+"px",this.lowerCanvasEl.style.height=this.height+"px",this.viewportTransform=this.viewportTransform.slice()},_createLowerCanvas:function(e){this.lowerCanvasEl=fabric.util.getById(e)||this._createCanvasElement(),this._initCanvasElement(this.lowerCanvasEl),fabric.util.addClass(this.lowerCanvasEl,"lower-canvas"),this.interactive&&this._applyCanvasStyle(this.lowerCanvasEl),this.contextContainer=this.lowerCanvasEl.getContext("2d")},getWidth:function(){return this.width},getHeight:function(){return this.height},setWidth:function(e,t){return this.setDimensions({width:e},t)},setHeight:function(e,t){return this.setDimensions({height:e},t)},setDimensions:function(e,t){var n;t=t||{};for(var r in e)n=e[r],t.cssOnly||(this._setBackstoreDimension(r,e[r]),n+="px"),t.backstoreOnly||this._setCssDimension(r,n);return t.cssOnly||this.renderAll(),this.calcOffset(),this},_setBackstoreDimension:function(e,t){return this.lowerCanvasEl[e]=t,this.upperCanvasEl&&(this.upperCanvasEl[e]=t),this.cacheCanvasEl&&(this.cacheCanvasEl[e]=t),this[e]=t,this},_setCssDimension:function(e,t){return this.lowerCanvasEl.style[e]=t,this.upperCanvasEl&&(this.upperCanvasEl.style[e]=t),this.wrapperEl&&(this.wrapperEl.style[e]=t),this},getZoom:function(){return Math.sqrt(this.viewportTransform[0]*this.viewportTransform[3])},setViewportTransform:function(e){this.viewportTransform=e,this.renderAll();for(var t=0,n=this._objects.length;t"),n.join("")},_setSVGPreamble:function(e,t){t.suppressPreamble||e.push('','\n')},_setSVGHeader:function(e,t){e.push("',"Created with Fabric.js ",fabric.version,"","",fabric.createSVGFontFacesMarkup(this.getObjects()),fabric.createSVGRefElementsMarkup(this),"")},_setSVGObjects:function(e,t){var n=this.getActiveGroup();n&&this.discardActiveGroup();for(var r=0,i=this.getObjects(),s=i.length;r"):this[t]&&t==="overlayColor"&&e.push('")},sendToBack:function(e){return n(this._objects,e),this._objects.unshift(e),this.renderAll&&this.renderAll()},bringToFront:function(e){return n(this._objects,e),this._objects.push(e),this.renderAll&&this.renderAll()},sendBackwards:function(e,t){var r=this._objects.indexOf(e);if(r!==0){var i=this._findNewLowerIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewLowerIndex:function(e,t,n){var r;if(n){r=t;for(var i=t-1;i>=0;--i){var s=e.intersectsWithObject(this._objects[i])||e.isContainedWithinObject(this._objects[i])||this._objects[i].isContainedWithinObject(e);if(s){r=i;break}}}else r=t-1;return r},bringForward:function(e,t){var r=this._objects.indexOf(e);if(r!==this._objects.length-1){var i=this._findNewUpperIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewUpperIndex:function(e,t,n){var r;if(n){r=t;for(var i=t+1;i"}}),e(fabric.StaticCanvas.prototype,fabric.Observable),e(fabric.StaticCanvas.prototype,fabric.Collection),e(fabric.StaticCanvas.prototype,fabric.DataURLExporter),e(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(e){var t=fabric.util.createCanvasElement();if(!t||!t.getContext)return null;var n=t.getContext("2d");if(!n)return null;switch(e){case"getImageData":return typeof n.getImageData!="undefined";case"setLineDash":return typeof n.setLineDash!="undefined";case"toDataURL":return typeof t.toDataURL!="undefined";case"toDataURLWithQuality":try{return t.toDataURL("image/jpeg",0),!0}catch(r){}return!1;default:return null}}}),fabric.StaticCanvas.prototype.toJSON=fabric.StaticCanvas.prototype.toObject}(),fabric.BaseBrush=fabric.util.createClass({color:"rgb(0, 0, 0)",width:1,shadow:null,strokeLineCap:"round",strokeLineJoin:"round",setShadow:function(e){return this.shadow=new fabric.Shadow(e),this},_setBrushStyles:function(){var e=this.canvas.contextTop;e.strokeStyle=this.color,e.lineWidth=this.width,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin},_setShadow:function(){if(!this.shadow)return;var e=this.canvas.contextTop;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_resetShadow:function(){var e=this.canvas.contextTop;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0}}),function(){var e=fabric.util.array.min,t=fabric.util.array.max;fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(e){this.canvas=e,this._points=[]},onMouseDown:function(e){this._prepareForDrawing(e),this._captureDrawingPath(e),this._render()},onMouseMove:function(e){this._captureDrawingPath(e),this.canvas.clearContext(this.canvas.contextTop),this._render +()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(e){var t=new fabric.Point(e.x,e.y);this._reset(),this._addPoint(t),this.canvas.contextTop.moveTo(t.x,t.y)},_addPoint:function(e){this._points.push(e)},_reset:function(){this._points.length=0,this._setBrushStyles(),this._setShadow()},_captureDrawingPath:function(e){var t=new fabric.Point(e.x,e.y);this._addPoint(t)},_render:function(){var e=this.canvas.contextTop,t=this.canvas.viewportTransform,n=this._points[0],r=this._points[1];e.save(),e.transform(t[0],t[1],t[2],t[3],t[4],t[5]),e.beginPath(),this._points.length===2&&n.x===r.x&&n.y===r.y&&(n.x-=.5,r.x+=.5),e.moveTo(n.x,n.y);for(var i=1,s=this._points.length;in.padding?e.x<0?e.x+=n.padding:e.x-=n.padding:e.x=0,i(e.y)>n.padding?e.y<0?e.y+=n.padding:e.y-=n.padding:e.y=0},_rotateObject:function(e,t){var i=this._currentTransform;if(i.target.get("lockRotation"))return;var s=r(i.ey-i.top,i.ex-i.left),o=r(t-i.top,e-i.left),u=n(o-s+i.theta);u<0&&(u=360+u),i.target.angle=u},setCursor:function(e){this.upperCanvasEl.style.cursor=e},_resetObjectTransform:function(e){e.scaleX=1,e.scaleY=1,e.setAngle(0)},_drawSelection:function(){var e=this.contextTop,t=this._groupSelector,n=t.left,r=t.top,o=i(n),u=i(r);e.fillStyle=this.selectionColor,e.fillRect(t.ex-(n>0?0:-n),t.ey-(r>0?0:-r),o,u),e.lineWidth=this.selectionLineWidth,e.strokeStyle=this.selectionBorderColor;if(this.selectionDashArray.length>1){var a=t.ex+s-(n>0?0:o),f=t.ey+s-(r>0?0:u);e.beginPath(),fabric.util.drawDashedLine(e,a,f,a+o,f,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f+u-1,a+o,f+u-1,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f,a,f+u,this.selectionDashArray),fabric.util.drawDashedLine(e,a+o-1,f,a+o-1,f+u,this.selectionDashArray),e.closePath(),e.stroke()}else e.strokeRect(t.ex+s-(n>0?0:o),t.ey+s-(r>0?0:u),o,u)},_isLastRenderedObject:function(e){return this.controlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay.visible&&this.containsPoint(e,this.lastRenderedObjectWithControlsAboveOverlay)&&this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e,!0))},findTarget:function(e,t){if(this.skipTargetFind)return;if(this._isLastRenderedObject(e))return this.lastRenderedObjectWithControlsAboveOverlay;var n=this.getActiveGroup();if(n&&!t&&this.containsPoint(e,n))return n;var r=this._searchPossibleTargets(e);return this._fireOverOutEvents(r),r},_fireOverOutEvents:function(e){e?this._hoveredTarget!==e&&(this.fire("mouse:over",{target:e}),e.fire("mouseover"),this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget}),this._hoveredTarget.fire("mouseout")),this._hoveredTarget=e):this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget}),this._hoveredTarget.fire("mouseout"),this._hoveredTarget=null)},_checkTarget:function(e,t,n){if(t&&t.visible&&t.evented&&this.containsPoint(e,t)){if(!this.perPixelTargetFind&&!t.perPixelTargetFind||!!t.isEditing)return!0;var r=this.isTargetTransparent(t,n.x,n.y);if(!r)return!0}},_searchPossibleTargets:function(e){var t,n=this.getPointer(e,!0),r=this._objects.length;while(r--)if(this._checkTarget(e,this._objects[r],n)){this.relatedTarget=this._objects[r],t=this._objects[r];break}return t},getPointer:function(t,n,r){r||(r=this.upperCanvasEl);var i=e(t,r),s=r.getBoundingClientRect(),o;return this.calcOffset(),i.x=i.x-this._offset.left,i.y=i.y-this._offset.top,n||(i=fabric.util.transformPoint(i,fabric.util.invertTransform(this.viewportTransform))),s.width===0||s.height===0?o={width:1,height:1}:o={width:r.width/s.width,height:r.height/s.height},{x:i.x*o.width,y:i.y*o.height}},_createUpperCanvas:function(){var e=this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/,"");this.upperCanvasEl=this._createCanvasElement(),fabric.util.addClass(this.upperCanvasEl,"upper-canvas "+e),this.wrapperEl.appendChild(this.upperCanvasEl),this._copyCanvasStyle(this.lowerCanvasEl,this.upperCanvasEl),this._applyCanvasStyle(this.upperCanvasEl),this.contextTop=this.upperCanvasEl.getContext("2d")},_createCacheCanvas:function(){this.cacheCanvasEl=this._createCanvasElement(),this.cacheCanvasEl.setAttribute("width",this.width),this.cacheCanvasEl.setAttribute("height",this.height),this.contextCache=this.cacheCanvasEl.getContext("2d")},_initWrapperElement:function(){this.wrapperEl=fabric.util.wrapElement(this.lowerCanvasEl,"div",{"class":this.containerClass}),fabric.util.setStyle(this.wrapperEl,{width:this.getWidth()+"px",height:this.getHeight()+"px",position:"relative"}),fabric.util.makeElementUnselectable(this.wrapperEl)},_applyCanvasStyle:function(e){var t=this.getWidth()||e.width,n=this.getHeight()||e.height;fabric.util.setStyle(e,{position:"absolute",width:t+"px",height:n+"px",left:0,top:0}),e.width=t,e.height=n,fabric.util.makeElementUnselectable(e)},_copyCanvasStyle:function(e,t){t.style.cssText=e.style.cssText},getSelectionContext:function(){return this.contextTop},getSelectionElement:function(){return this.upperCanvasEl},_setActiveObject:function(e){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=e,e.set("active",!0)},setActiveObject:function(e,t){return this._setActiveObject(e),this.renderAll(),this.fire("object:selected",{target:e,e:t}),e.fire("selected",{e:t}),this},getActiveObject:function(){return this._activeObject},_discardActiveObject:function(){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=null},discardActiveObject:function(e){return this._discardActiveObject(),this.renderAll(),this.fire("selection:cleared",{e:e}),this},_setActiveGroup:function(e){this._activeGroup=e,e&&e.set("active",!0)},setActiveGroup:function(e,t){return this._setActiveGroup(e),e&&(this.fire("object:selected",{target:e,e:t}),e.fire("selected",{e:t})),this},getActiveGroup:function(){return this._activeGroup},_discardActiveGroup:function(){var e=this.getActiveGroup();e&&e.destroy(),this.setActiveGroup(null)},discardActiveGroup:function(e){return this._discardActiveGroup(),this.fire("selection:cleared",{e:e}),this},deactivateAll:function(){var e=this.getObjects(),t=0,n=e.length;for(;t1&&(t=new fabric.Group(t.reverse(),{originX:"center",originY:"center",canvas:this}),t.addWithUpdate(),this.setActiveGroup(t,e),t.saveCoords(),this.fire("selection:created",{target:t}),this.renderAll())},_collectObjects:function(){var n=[],r,i=this._groupSelector.ex,s=this._groupSelector.ey,o=i+this._groupSelector.left,u=s+this._groupSelector.top,a=new fabric.Point(e(i,o),e(s,u)),f=new fabric.Point(t(i,o),t(s,u)),l=i===o&&s===u;for(var c=this._objects.length;c--;){r=this._objects[c];if(!r||!r.selectable||!r.visible)continue;if(r.intersectsWithRect(a,f)||r.isContainedWithinRect(a,f)||r.containsPoint(a)||r.containsPoint(f)){r.set("active",!0),n.push(r);if(l)break}}return n},_maybeGroupObjects:function(e){this.selection&&this._groupSelector&&this._groupSelectedObjects(e);var t=this.getActiveGroup();t&&(t.setObjectsCoords().setCoords(),t.isMoving=!1,this.setCursor(this.defaultCursor)),this._groupSelector=null,this._currentTransform=null}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{toDataURL:function(e){e||(e={});var t=e.format||"png",n=e.quality||1,r=e.multiplier||1,i={left:e.left,top:e.top,width:e.width,height:e.height};return r!==1?this.__toDataURLWithMultiplier(t,n,i,r):this.__toDataURL(t,n,i)},__toDataURL:function(e,t,n){this.renderAll(!0);var r=this.upperCanvasEl||this.lowerCanvasEl,i=this.__getCroppedCanvas(r,n);e==="jpg"&&(e="jpeg");var s=fabric.StaticCanvas.supports("toDataURLWithQuality")?(i||r).toDataURL("image/"+e,t):(i||r).toDataURL("image/"+e);return this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),i&&(i=null),s},__getCroppedCanvas:function(e,t){var n,r,i="left"in t||"top"in t||"width"in t||"height"in t;return i&&(n=fabric.util.createCanvasElement(),r=n.getContext("2d"),n.width=t.width||this.width,n.height=t.height||this.height,r.drawImage(e,-t.left||0,-t.top||0)),n},__toDataURLWithMultiplier:function(e,t,n,r){var i=this.getWidth(),s=this.getHeight(),o=i*r,u=s*r,a=this.getActiveObject(),f=this.getActiveGroup(),l=this.contextTop||this.contextContainer;r>1&&this.setWidth(o).setHeight(u),l.scale(r,r),n.left&&(n.left*=r),n.top&&(n.top*=r),n.width?n.width*=r:r<1&&(n.width=o),n.height?n.height*=r:r<1&&(n.height=u),f?this._tempRemoveBordersControlsFromGroup(f):a&&this.deactivateAll&&this.deactivateAll(),this.renderAll(!0);var c=this.__toDataURL(e,t,n);return this.width=i,this.height=s,l.scale(1/r,1/r),this.setWidth(i).setHeight(s),f?this._restoreBordersControlsOnGroup(f):a&&this.setActiveObject&&this.setActiveObject(a),this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),c},toDataURLWithMultiplier:function(e,t,n){return this.toDataURL({format:e,multiplier:t,quality:n})},_tempRemoveBordersControlsFromGroup:function(e){e.origHasControls=e.hasControls,e.origBorderColor=e.borderColor,e.hasControls=!0,e.borderColor="rgba(0,0,0,0)",e.forEachObject(function(e){e.origBorderColor=e.borderColor,e.borderColor="rgba(0,0,0,0)"})},_restoreBordersControlsOnGroup:function(e){e.hideControls=e.origHideControls,e.borderColor=e.origBorderColor,e.forEachObject(function(e){e.borderColor=e.origBorderColor,delete e.origBorderColor})}}),fabric.util +.object.extend(fabric.StaticCanvas.prototype,{loadFromDatalessJSON:function(e,t,n){return this.loadFromJSON(e,t,n)},loadFromJSON:function(e,t,n){if(!e)return;var r=typeof e=="string"?JSON.parse(e):e;this.clear();var i=this;return this._enlivenObjects(r.objects,function(){i._setBgOverlay(r,t)},n),this},_setBgOverlay:function(e,t){var n=this,r={backgroundColor:!1,overlayColor:!1,backgroundImage:!1,overlayImage:!1};if(!e.backgroundImage&&!e.overlayImage&&!e.background&&!e.overlay){t&&t();return}var i=function(){r.backgroundImage&&r.overlayImage&&r.backgroundColor&&r.overlayColor&&(n.renderAll(),t&&t())};this.__setBgOverlay("backgroundImage",e.backgroundImage,r,i),this.__setBgOverlay("overlayImage",e.overlayImage,r,i),this.__setBgOverlay("backgroundColor",e.background,r,i),this.__setBgOverlay("overlayColor",e.overlay,r,i),i()},__setBgOverlay:function(e,t,n,r){var i=this;if(!t){n[e]=!0;return}e==="backgroundImage"||e==="overlayImage"?fabric.Image.fromObject(t,function(t){i[e]=t,n[e]=!0,r&&r()}):this["set"+fabric.util.string.capitalize(e,!0)](t,function(){n[e]=!0,r&&r()})},_enlivenObjects:function(e,t,n){var r=this;if(!e||e.length===0){t&&t();return}var i=this.renderOnAddRemove;this.renderOnAddRemove=!1,fabric.util.enlivenObjects(e,function(e){e.forEach(function(e,t){r.insertAt(e,t,!0)}),r.renderOnAddRemove=i,t&&t()},null,n)},_toDataURL:function(e,t){this.clone(function(n){t(n.toDataURL(e))})},_toDataURLWithMultiplier:function(e,t,n){this.clone(function(r){n(r.toDataURLWithMultiplier(e,t))})},clone:function(e,t){var n=JSON.stringify(this.toJSON(t));this.cloneWithoutData(function(t){t.loadFromJSON(n,function(){e&&e(t)})})},cloneWithoutData:function(e){var t=fabric.document.createElement("canvas");t.width=this.getWidth(),t.height=this.getHeight();var n=new fabric.Canvas(t);n.clipTo=this.clipTo,this.backgroundImage?(n.setBackgroundImage(this.backgroundImage.src,function(){n.renderAll(),e&&e(n)}),n.backgroundImageOpacity=this.backgroundImageOpacity,n.backgroundImageStretch=this.backgroundImageStretch):e&&e(n)}}),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.toFixed,i=t.util.string.capitalize,s=t.util.degreesToRadians,o=t.StaticCanvas.supports("setLineDash");if(t.Object)return;t.Object=t.util.createClass({type:"object",originX:"left",originY:"top",top:0,left:0,width:0,height:0,scaleX:1,scaleY:1,flipX:!1,flipY:!1,opacity:1,angle:0,cornerSize:12,transparentCorners:!0,hoverCursor:null,padding:0,borderColor:"rgba(102,153,255,0.75)",cornerColor:"rgba(102,153,255,0.5)",centeredScaling:!1,centeredRotation:!0,fill:"rgb(0,0,0)",fillRule:"source-over",backgroundColor:"",stroke:null,strokeWidth:1,strokeDashArray:null,strokeLineCap:"butt",strokeLineJoin:"miter",strokeMiterLimit:10,shadow:null,borderOpacityWhenMoving:.4,borderScaleFactor:1,transformMatrix:null,minScaleLimit:.01,selectable:!0,evented:!0,visible:!0,hasControls:!0,hasBorders:!0,hasRotatingPoint:!0,rotatingPointOffset:40,perPixelTargetFind:!1,includeDefaultValues:!0,clipTo:null,lockMovementX:!1,lockMovementY:!1,lockRotation:!1,lockScalingX:!1,lockScalingY:!1,lockUniScaling:!1,lockScalingFlip:!1,stateProperties:"top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill fillRule shadow clipTo visible backgroundColor".split(" "),initialize:function(e){e&&this.setOptions(e)},_initGradient:function(e){e.fill&&e.fill.colorStops&&!(e.fill instanceof t.Gradient)&&this.set("fill",new t.Gradient(e.fill))},_initPattern:function(e){e.fill&&e.fill.source&&!(e.fill instanceof t.Pattern)&&this.set("fill",new t.Pattern(e.fill)),e.stroke&&e.stroke.source&&!(e.stroke instanceof t.Pattern)&&this.set("stroke",new t.Pattern(e.stroke))},_initClipping:function(e){if(!e.clipTo||typeof e.clipTo!="string")return;var n=t.util.getFunctionBody(e.clipTo);typeof n!="undefined"&&(this.clipTo=new Function("ctx",n))},setOptions:function(e){for(var t in e)this.set(t,e[t]);this._initGradient(e),this._initPattern(e),this._initClipping(e)},transform:function(e,t){this.group&&this.group.transform(e,t),e.globalAlpha=this.opacity;var n=t?this._getLeftTopCoords():this.getCenterPoint();e.translate(n.x,n.y),e.rotate(s(this.angle)),e.scale(this.scaleX*(this.flipX?-1:1),this.scaleY*(this.flipY?-1:1))},toObject:function(e){var n=t.Object.NUM_FRACTION_DIGITS,i={type:this.type,originX:this.originX,originY:this.originY,left:r(this.left,n),top:r(this.top,n),width:r(this.width,n),height:r(this.height,n),fill:this.fill&&this.fill.toObject?this.fill.toObject():this.fill,stroke:this.stroke&&this.stroke.toObject?this.stroke.toObject():this.stroke,strokeWidth:r(this.strokeWidth,n),strokeDashArray:this.strokeDashArray,strokeLineCap:this.strokeLineCap,strokeLineJoin:this.strokeLineJoin,strokeMiterLimit:r(this.strokeMiterLimit,n),scaleX:r(this.scaleX,n),scaleY:r(this.scaleY,n),angle:r(this.getAngle(),n),flipX:this.flipX,flipY:this.flipY,opacity:r(this.opacity,n),shadow:this.shadow&&this.shadow.toObject?this.shadow.toObject():this.shadow,visible:this.visible,clipTo:this.clipTo&&String(this.clipTo),backgroundColor:this.backgroundColor};return this.includeDefaultValues||(i=this._removeDefaultValues(i)),t.util.populateWithProperties(this,i,e),i},toDatalessObject:function(e){return this.toObject(e)},_removeDefaultValues:function(e){var n=t.util.getKlass(e.type).prototype,r=n.stateProperties;return r.forEach(function(t){e[t]===n[t]&&delete e[t]}),e},toString:function(){return"#"},get:function(e){return this[e]},_setObject:function(e){for(var t in e)this._set(t,e[t])},set:function(e,t){return typeof e=="object"?this._setObject(e):typeof t=="function"&&e!=="clipTo"?this._set(e,t(this.get(e))):this._set(e,t),this},_set:function(e,n){var i=e==="scaleX"||e==="scaleY";return i&&(n=this._constrainScale(n)),e==="scaleX"&&n<0?(this.flipX=!this.flipX,n*=-1):e==="scaleY"&&n<0?(this.flipY=!this.flipY,n*=-1):e==="width"||e==="height"?this.minScaleLimit=r(Math.min(.1,1/Math.max(this.width,this.height)),2):e==="shadow"&&n&&!(n instanceof t.Shadow)&&(n=new t.Shadow(n)),this[e]=n,this},toggle:function(e){var t=this.get(e);return typeof t=="boolean"&&this.set(e,!t),this},setSourcePath:function(e){return this.sourcePath=e,this},getViewportTransform:function(){return this.canvas&&this.canvas.viewportTransform?this.canvas.viewportTransform:[1,0,0,1,0,0]},render:function(e,n){if(this.width===0||this.height===0||!this.visible)return;e.save(),this._setupFillRule(e),this._transform(e,n),this._setStrokeStyles(e),this._setFillStyles(e);if(this.group&&this.group.type==="path-group"){e.translate(-this.group.width/2,-this.group.height/2);var r=this.transformMatrix;r&&e.transform.apply(e,r)}e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,this._setShadow(e),this.clipTo&&t.util.clipContext(this,e),this._render(e,n),this.clipTo&&e.restore(),this._removeShadow(e),this._restoreFillRule(e),e.restore()},_transform:function(e,t){var n=this.transformMatrix;n&&!this.group&&e.setTransform.apply(e,n),t||this.transform(e)},_setStrokeStyles:function(e){this.stroke&&(e.lineWidth=this.strokeWidth,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin,e.miterLimit=this.strokeMiterLimit,e.strokeStyle=this.stroke.toLive?this.stroke.toLive(e):this.stroke)},_setFillStyles:function(e){this.fill&&(e.fillStyle=this.fill.toLive?this.fill.toLive(e):this.fill)},_renderControls:function(e,n){var r=this.getViewportTransform();e.save();if(this.active&&!n){var i;this.group&&(i=t.util.transformPoint(this.group.getCenterPoint(),r),e.translate(i.x,i.y),e.rotate(s(this.group.angle))),i=t.util.transformPoint(this.getCenterPoint(),r,null!=this.group),this.group&&(i.x*=this.group.scaleX,i.y*=this.group.scaleY),e.translate(i.x,i.y),e.rotate(s(this.angle)),this.drawBorders(e),this.drawControls(e)}e.restore()},_setShadow:function(e){if(!this.shadow)return;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_removeShadow:function(e){if(!this.shadow)return;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0},_renderFill:function(e){if(!this.fill)return;e.save(),this.fill.toLive&&e.translate(-this.width/2+this.fill.offsetX||0,-this.height/2+this.fill.offsetY||0);if(this.fill.gradientTransform){var t=this.fill.gradientTransform;e.transform.apply(e,t)}this.fillRule==="destination-over"?e.fill("evenodd"):e.fill(),e.restore(),this.shadow&&!this.shadow.affectStroke&&this._removeShadow(e)},_renderStroke:function(e){if(!this.stroke||this.strokeWidth===0)return;e.save();if(this.strokeDashArray)1&this.strokeDashArray.length&&this.strokeDashArray.push.apply(this.strokeDashArray,this.strokeDashArray),o?(e.setLineDash(this.strokeDashArray),this._stroke&&this._stroke(e)):this._renderDashedStroke&&this._renderDashedStroke(e),e.stroke();else{if(this.stroke.gradientTransform){var t=this.stroke.gradientTransform;e.transform.apply(e,t)}this._stroke?this._stroke(e):e.stroke()}this._removeShadow(e),e.restore()},clone:function(e,n){return this.constructor.fromObject?this.constructor.fromObject(this.toObject(n),e):new t.Object(this.toObject(n))},cloneAsImage:function(e){var n=this.toDataURL();return t.util.loadImage(n,function(n){e&&e(new t.Image(n))}),this},toDataURL:function(e){e||(e={});var n=t.util.createCanvasElement(),r=this.getBoundingRect();n.width=r.width,n.height=r.height,t.util.wrapElement(n,"div");var i=new t.Canvas(n);e.format==="jpg"&&(e.format="jpeg"),e.format==="jpeg"&&(i.backgroundColor="#fff");var s={active:this.get("active"),left:this.getLeft(),top:this.getTop()};this.set("active",!1),this.setPositionByOrigin(new t.Point(n.width/2,n.height/2),"center","center");var o=this.canvas;i.add(this);var u=i.toDataURL(e);return this.set(s).setCoords(),this.canvas=o,i.dispose(),i=null,u},isType:function(e){return this.type===e},complexity:function(){return 0},toJSON:function(e){return this.toObject(e)},setGradient:function(e,n){n||(n={});var r={colorStops:[]};r.type=n.type||(n.r1||n.r2?"radial":"linear"),r.coords={x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y2};if(n.r1||n.r2)r.coords.r1=n.r1,r.coords.r2=n.r2;for(var i in n.colorStops){var s=new t.Color(n.colorStops[i]);r.colorStops.push({offset:i,color:s.toRgb(),opacity:s.getAlpha()})}return this.set(e,t.Gradient.forObject(this,r))},setPatternFill:function(e){return this.set("fill",new t.Pattern(e))},setShadow:function(e){return this.set("shadow",e?new t.Shadow(e):null)},setColor:function(e){return this.set("fill",e),this},setAngle:function(e){var t=(this.originX!=="center"||this.originY!=="center")&&this.centeredRotation;return t&&this._setOriginToCenter(),this.set("angle",e),t&&this._resetOrigin(),this},centerH:function(){return this.canvas.centerObjectH(this),this},centerV:function(){return this.canvas.centerObjectV(this),this},center:function(){return this.canvas.centerObject(this),this},remove:function(){return this.canvas.remove(this),this},getLocalPointer:function(e,t){t=t||this.canvas.getPointer(e);var n=this.translateToOriginPoint(this.getCenterPoint(),"left","top");return{x:t.x-n.x,y:t.y-n.y}},_setupFillRule:function(e){this.fillRule&&(this._prevFillRule=e.globalCompositeOperation,e.globalCompositeOperation=this.fillRule)},_restoreFillRule:function(e){this.fillRule&&this._prevFillRule&&(e.globalCompositeOperation=this._prevFillRule)}}),t.util.createAccessors(t.Object),t.Object.prototype.rotate=t.Object.prototype.setAngle,n(t.Object.prototype,t.Observable),t.Object.NUM_FRACTION_DIGITS=2,t.Object.__uid=0}(typeof exports!="undefined"?exports:this),function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{translateToCenterPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x+(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x-(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y+(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y-(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},translateToOriginPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x-(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x+(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y-(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y+(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},getCenterPoint:function(){var e=new fabric.Point(this.left,this.top);return this.translateToCenterPoint(e,this.originX,this.originY)},getPointByOrigin:function(e,t){var n=this.getCenterPoint();return this.translateToOriginPoint(n,e,t)},toLocalPoint:function(t,n,r){var i=this.getCenterPoint(),s=this.stroke?this.strokeWidth:0,o,u;return n&&r?(n==="left"?o=i.x-(this.getWidth()+s*this.scaleX)/2:n==="right"?o=i.x+(this.getWidth()+s*this.scaleX)/2:o=i.x,r==="top"?u=i.y-(this.getHeight()+s*this.scaleY)/2:r==="bottom"?u=i.y+(this.getHeight()+s*this.scaleY)/2:u=i.y):(o=this.left,u=this.top),fabric.util.rotatePoint(new fabric.Point(t.x,t.y),i,-e(this.angle)).subtractEquals(new fabric.Point(o,u))},setPositionByOrigin:function(e,t,n){var r=this.translateToCenterPoint(e,t,n),i=this.translateToOriginPoint(r,this.originX,this.originY);this.set("left",i.x),this.set("top",i.y)},adjustPosition:function(t){var n=e(this.angle),r=this.getWidth()/2,i=Math.cos(n)*r,s=Math.sin(n)*r,o=this.getWidth(),u=Math.cos(n)*o,a=Math.sin(n)*o;this.originX==="center"&&t==="left"||this.originX==="right"&&t==="center"?(this.left-=i,this.top-=s):this.originX==="left"&&t==="center"||this.originX==="center"&&t==="right"?(this.left+=i,this.top+=s):this.originX==="left"&&t==="right"?(this.left+=u,this.top+=a):this.originX==="right"&&t==="left"&&(this.left-=u,this.top-=a),this.setCoords(),this.originX=t},_setOriginToCenter:function(){this._originalOriginX=this.originX,this._originalOriginY=this.originY;var e=this.getCenterPoint();this.originX="center",this.originY="center",this.left=e.x,this.top=e.y},_resetOrigin:function(){var e=this.translateToOriginPoint(this.getCenterPoint(),this._originalOriginX,this._originalOriginY);this.originX=this._originalOriginX,this.originY=this._originalOriginY,this.left=e.x,this.top=e.y,this._originalOriginX=null,this._originalOriginY=null},_getLeftTopCoords:function(){return this.translateToOriginPoint(this.getCenterPoint(),"left","center")}})}(),function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{oCoords:null,intersectsWithRect:function(e,t){var n=this.oCoords,r=new fabric.Point(n.tl.x,n.tl.y),i=new fabric.Point(n.tr.x,n.tr.y),s=new fabric.Point(n.bl.x,n.bl.y),o=new fabric.Point(n.br.x,n.br.y),u=fabric.Intersection.intersectPolygonRectangle([r,i,o,s],e,t);return u.status==="Intersection"},intersectsWithObject:function(e){function t(e){return{tl:new fabric.Point(e.tl.x,e.tl.y),tr:new fabric.Point(e.tr.x,e.tr.y),bl:new fabric.Point(e.bl.x,e.bl.y),br:new fabric.Point(e.br.x,e.br.y)}}var n=t(this.oCoords),r=t(e.oCoords),i=fabric.Intersection.intersectPolygonPolygon([n.tl,n.tr,n.br,n.bl],[r.tl,r.tr,r.br,r.bl]);return i.status==="Intersection"},isContainedWithinObject:function(e){var t=e.getBoundingRect(),n=new fabric.Point(t.left,t.top),r=new fabric.Point(t.left+t.width,t.top+t.height);return this.isContainedWithinRect(n,r)},isContainedWithinRect:function(e,t){var n=this.getBoundingRect();return n.left>=e.x&&n.left+n.width<=t.x&&n.top>=e.y&&n.top+n.height<=t.y},containsPoint:function(e){var t=this._getImageLines(this.oCoords),n=this._findCrossPoints(e,t);return n!==0&&n%2===1},_getImageLines:function(e){return{topline:{o:e.tl,d:e.tr},rightline:{o:e.tr,d:e.br},bottomline:{o:e.br,d:e.bl},leftline:{o:e.bl,d:e.tl}}},_findCrossPoints:function(e,t){var n,r,i,s,o,u,a=0,f;for(var l in t){f=t[l];if(f.o.y=e.y&&f.d.y>=e.y)continue;f.o.x===f.d.x&&f.o.x>=e.x?(o=f.o.x,u=e.y):(n=0,r=(f.d.y-f.o.y)/(f.d.x-f.o.x),i=e.y-n*e.x,s=f.o.y-r*f.o.x,o=-(i-s)/(n-r),u=i+n*o),o>=e.x&&(a+=1);if(a===2)break}return a},getBoundingRectWidth:function(){return this.getBoundingRect().width},getBoundingRectHeight:function(){return this.getBoundingRect().height},getBoundingRect:function(){this.oCoords||this.setCoords();var e=[this.oCoords.tl.x,this.oCoords.tr.x,this.oCoords.br.x,this.oCoords.bl.x],t=fabric.util.array.min(e),n=fabric.util.array.max(e),r=Math.abs(t-n),i=[this.oCoords.tl.y,this.oCoords.tr.y,this.oCoords.br.y,this.oCoords.bl.y],s=fabric.util.array.min(i),o=fabric.util.array.max(i),u=Math.abs(s-o);return{left:t,top:s,width:r,height:u}},getWidth:function(){return this.width*this.scaleX},getHeight:function(){return this.height*this.scaleY},_constrainScale:function(e){return Math.abs(e)1?this.strokeWidth:0,n=e(this.angle),r=this.getViewportTransform(),i=function(e){return fabric.util.transformPoint(e,r)},s=this.width,o=this.height,u=this.strokeLineCap==="round"||this.strokeLineCap==="square",a=this.type==="line"&&this.width===1,f=this.type==="line"&&this.height===1,l=u&&f||this.type!=="line",c=u&&a||this.type!=="line";a?s=t:f&&(o=t),l&&(s+=t),c&&(o+=t),this.currentWidth=s*this.scaleX,this.currentHeight=o*this.scaleY,this.currentWidth<0&&(this.currentWidth=Math.abs(this.currentWidth));var h=Math.sqrt(Math.pow(this.currentWidth/2,2)+Math.pow(this.currentHeight/2,2)),p=Math.atan(isFinite(this.currentHeight/this.currentWidth)?this.currentHeight/this.currentWidth:0),d=Math.cos(p+n)*h,v=Math.sin(p+n)*h,m=Math.sin(n),g=Math.cos(n),y=this.getCenterPoint(),b=new fabric.Point(this.currentWidth,this.currentHeight),w=new fabric.Point(y.x-d,y.y-v),E=new fabric.Point(w.x+b.x*g,w.y+b.x*m),S=new fabric.Point(w.x-b.y*m,w.y+b.y*g),x=new fabric.Point(w.x+b.x/2*g,w.y+b.x/2*m),T=i(w),N=i(E),C=i(new fabric.Point(E.x-b.y*m,E.y+b.y*g)),k=i(S),L=i(new fabric.Point(w.x-b.y/2*m,w.y+b.y/2*g)),A=i(x),O=i(new fabric.Point(E.x-b.y/2*m,E.y+b.y/2*g)),M=i(new fabric.Point(S.x+b.x/2*g,S.y+b.x/2*m)),_=i(new fabric.Point(x.x,x.y)),D=Math.cos(p+n)*this.padding*Math.sqrt(2),P=Math.sin(p+n)*this.padding*Math.sqrt(2);return T=T.add(new fabric.Point(-D,-P)),N=N.add(new fabric.Point(P,-D)),C=C.add(new fabric.Point(D,P)),k=k.add(new fabric.Point(-P,D)),L=L.add(new fabric.Point((-D-P)/2,(-P+D)/2)),A=A.add(new fabric.Point((P-D)/2,-(P+D)/2)),O=O.add(new fabric.Point((P+D)/2,(P-D)/2)),M=M.add(new fabric.Point((D-P)/2,(D+P)/2)),_=_.add(new fabric.Point((P-D)/2,-(P+D)/2)),this.oCoords={tl:T,tr:N,br:C,bl:k,ml:L,mt:A,mr:O,mb:M,mtr:_},this._setCornerCoords&&this._setCornerCoords(),this}})}(),fabric.util.object.extend(fabric.Object.prototype,{sendToBack:function(){return this.group?fabric.StaticCanvas.prototype.sendToBack.call(this.group,this):this.canvas.sendToBack(this),this},bringToFront:function(){return this.group?fabric.StaticCanvas.prototype.bringToFront.call(this.group,this):this.canvas.bringToFront(this),this},sendBackwards:function(e){return this.group?fabric.StaticCanvas.prototype.sendBackwards.call(this.group,this,e):this.canvas.sendBackwards(this,e),this},bringForward:function(e){return this.group?fabric.StaticCanvas.prototype.bringForward.call(this.group,this,e):this.canvas.bringForward(this,e),this},moveTo:function(e){return this.group?fabric.StaticCanvas.prototype.moveTo.call(this.group,this,e):this.canvas.moveTo(this,e),this}}),fabric.util.object.extend(fabric.Object.prototype,{getSvgStyles:function(){var e=this.fill?this.fill.toLive?"url(#SVGID_"+this.fill.id+")":this.fill:"none",t=this.fillRule==="destination-over"?"evenodd":this.fillRule,n=this.stroke?this.stroke.toLive?"url(#SVGID_"+this.stroke.id+")":this.stroke:"none",r=this.strokeWidth?this.strokeWidth:"0",i=this.strokeDashArray?this.strokeDashArray.join(" "):"",s=this.strokeLineCap?this.strokeLineCap:"butt",o=this.strokeLineJoin?this.strokeLineJoin:"miter",u=this.strokeMiterLimit?this.strokeMiterLimit:"4",a=typeof this.opacity!="undefined"?this.opacity:"1",f=this.visible?"":" visibility: hidden;",l=this.shadow&&this.type!=="text"?"filter: url(#SVGID_"+this.shadow.id+");":"";return["stroke: ",n,"; ","stroke-width: ",r,"; ","stroke-dasharray: ",i,"; ","stroke-linecap: ",s,"; ","stroke-linejoin: ",o,"; ","stroke-miterlimit: ",u,"; ","fill: ",e,"; ","fill-rule: ",t,"; ","opacity: ",a,";",l,f].join("")},getSvgTransform:function(){if(this.group)return"";var e=fabric.util.toFixed,t=this.getAngle(),n=this.getViewportTransform(),r=fabric.util.transformPoint(this.getCenterPoint(),n),i=fabric.Object.NUM_FRACTION_DIGITS,s=this.type==="path-group"?"":"translate("+e(r.x,i)+" "+e(r.y,i)+")",o=t!==0?" rotate("+e(t,i)+")":"",u=this.scaleX===1&&this.scaleY===1&&n[0]===1&&n[3]===1?"":" scale("+e(this.scaleX*n[0],i)+" "+e(this.scaleY*n[3],i)+")",a=this.type==="path-group"?this.width*n[0]:0,f=this.flipX?" matrix(-1 0 0 1 "+a+" 0) ":"",l=this.type==="path-group"?this.height*n[3]:0,c=this.flipY?" matrix(1 0 0 -1 0 "+l+")":"";return[s,o,u,f,c].join("")},getSvgTransformMatrix:function(){return this.transformMatrix?" matrix("+this.transformMatrix.join(" ")+")":""},_createBaseSVGMarkup:function(){var e=[];return this.fill&&this.fill.toLive&&e.push(this.fill.toSVG(this,!1)),this.stroke&&this.stroke.toLive&&e.push(this.stroke.toSVG(this,!1)),this.shadow&&e.push(this.shadow.toSVG(this)),e}}),fabric.util.object.extend(fabric.Object.prototype,{hasStateChanged:function(){return this.stateProperties.some(function(e){return this.get(e)!==this.originalState[e]},this)},saveState:function(e){return this.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),e&&e.stateProperties&&e.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),this},setupState:function(){return this.originalState={},this.saveState(),this}}),function(){var e=fabric.util.degreesToRadians,t=function(){return typeof G_vmlCanvasManager!="undefined"};fabric.util.object.extend(fabric.Object.prototype,{_controlsVisibility:null,_findTargetCorner:function(e){if(!this.hasControls||!this.active)return!1;var t=e.x,n=e.y,r,i;for(var s in this.oCoords){if(!this.isControlVisible(s))continue;if(s==="mtr"&&!this.hasRotatingPoint)continue;if(!(!this.get("lockUniScaling")||s!=="mt"&&s!=="mr"&&s!=="mb"&&s!=="ml"))continue;i=this._getImageLines(this.oCoords[s].corner),r=this._findCrossPoints({x:t,y:n},i);if(r!==0&&r%2===1)return this.__corner=s,s}return!1},_setCornerCoords:function(){var t=this.oCoords,n=e(this.angle),r=e(45-this.angle),i=Math.sqrt(2*Math.pow(this.cornerSize,2))/2,s=i*Math.cos(r),o=i*Math.sin(r),u=Math.sin(n),a=Math.cos(n);t.tl.corner={tl:{x:t.tl.x-o,y:t.tl.y-s},tr:{x:t.tl.x+s,y:t.tl.y-o},bl:{x:t.tl.x-s,y:t.tl.y+o},br:{x:t.tl.x+o,y:t.tl.y+s}},t.tr.corner={tl:{x:t.tr.x-o,y:t.tr.y-s},tr:{x:t.tr.x+s,y:t.tr.y-o},br:{x:t.tr.x+o,y:t.tr.y+s},bl:{x:t.tr.x-s,y:t.tr.y+o}},t.bl.corner={tl:{x:t.bl.x-o,y:t.bl.y-s},bl:{x:t.bl.x-s,y:t.bl.y+o},br:{x:t.bl.x+o,y:t.bl.y+s},tr:{x:t.bl.x+s,y:t.bl.y-o}},t.br.corner={tr:{x:t.br.x+s,y:t.br.y-o},bl:{x:t.br.x-s,y:t.br.y+o},br:{x:t.br.x+o,y:t.br.y+s},tl:{x:t.br.x-o,y:t.br.y-s}},t.ml.corner={tl:{x:t.ml.x-o,y:t.ml.y-s},tr:{x:t.ml.x+s,y:t.ml.y-o},bl:{x:t.ml.x-s,y:t.ml.y+o},br:{x:t.ml.x+o,y:t.ml.y+s}},t.mt.corner={tl:{x:t.mt.x-o,y:t.mt.y-s},tr:{x:t.mt.x+s,y:t.mt.y-o},bl:{x:t.mt.x-s,y:t.mt.y+o},br:{x:t.mt.x+o,y:t.mt.y+s}},t.mr.corner={tl:{x:t.mr.x-o,y:t.mr.y-s},tr:{x:t.mr.x+s,y:t.mr.y-o},bl:{x:t.mr.x-s,y:t.mr.y+o},br:{x:t.mr.x+o,y:t.mr.y+s}},t.mb.corner={tl:{x:t.mb.x-o,y:t.mb.y-s},tr:{x:t.mb.x+s,y:t.mb.y-o},bl:{x:t.mb.x-s,y:t.mb.y+o},br:{x:t.mb.x+o,y:t.mb.y+s}},t.mtr.corner={tl:{x:t.mtr.x-o+u*this.rotatingPointOffset,y:t.mtr.y-s-a*this.rotatingPointOffset},tr:{x:t.mtr.x+s+u*this.rotatingPointOffset,y:t.mtr.y-o-a*this.rotatingPointOffset},bl:{x:t.mtr.x-s+u*this.rotatingPointOffset,y:t.mtr.y+o-a*this.rotatingPointOffset},br:{x:t.mtr.x+o+u*this.rotatingPointOffset,y:t.mtr.y+s-a*this.rotatingPointOffset}}},drawBorders:function(e){if(!this.hasBorders)return this;var t=this.padding,n=t*2,r=this.getViewportTransform();e.save(),e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=this.borderColor;var i=1/this._constrainScale(this.scaleX),s=1/this._constrainScale(this.scaleY);e.lineWidth=1/this.borderScaleFactor;var o=this.getWidth(),u=this.getHeight(),a=this.strokeWidth>1?this.strokeWidth:0,f=this.strokeLineCap==="round"||this.strokeLineCap==="square",l=this.type==="line"&&this.width===1,c=this.type==="line"&&this.height===1,h=f&&c||this.type!=="line",p=f&&l||this.type!=="line";l?o=a/i:c&&(u=a/s),h&&(o+=a/i),p&&(u+=a/s);var d=fabric.util.transformPoint(new fabric.Point(o,u),r,!0),v=d.x,m=d.y;this.group&&(v*=this.group.scaleX,m*=this.group.scaleY),e.strokeRect(~~(-(v/2)-t)-.5,~~(-(m/2)-t)-.5,~~(v+n)+1,~~(m+n)+1);if(this.hasRotatingPoint&&this.isControlVisible("mtr")&&!this.get("lockRotation")&&this.hasControls){var g=(-m-t*2)/2;e.beginPath(),e.moveTo(0,g),e.lineTo(0,g-this.rotatingPointOffset),e.closePath(),e.stroke()}return e.restore(),this},drawControls:function(e){if(!this.hasControls)return this;var t=this.cornerSize,n=t/2,r=this.getViewportTransform(),i=this.strokeWidth>1?this.strokeWidth:0,s=this.width,o=this.height,u=this.strokeLineCap==="round"||this.strokeLineCap==="square",a=this.type==="line"&&this.width===1,f=this.type==="line"&&this.height===1,l=u&&f||this.type!=="line",c=u&&a||this.type!=="line";a?s=i:f&&(o=i),l&&(s+=i),c&&(o+=i),s*=this.scaleX,o*=this.scaleY;var h=fabric.util.transformPoint(new fabric.Point(s,o),r,!0),p=h.x,d=h.y,v=-(p/2),m=-(d/2),g=this.padding,y=n,b=n-t,w=this.transparentCorners?"strokeRect":"fillRect";return e.save(),e.lineWidth=1,e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=e.fillStyle=this.cornerColor,this._drawControl("tl",e,w,v-y-g,m-y-g),this._drawControl("tr",e,w,v+p-y+g,m-y-g),this._drawControl("bl",e,w,v-y-g,m+d+b+g),this._drawControl("br",e,w,v+p+b+g,m+d+b+g),this.get("lockUniScaling")||(this._drawControl("mt",e,w,v+p/2-y,m-y-g),this._drawControl("mb",e,w,v+p/2-y,m+d+b+g),this._drawControl("mr",e,w,v+p+b+g,m+d/2-y),this._drawControl("ml",e,w,v-y-g,m+d/2-y)),this.hasRotatingPoint&&this._drawControl("mtr",e,w,v+p/2-y,m-this.rotatingPointOffset-this.cornerSize/2-g),e.restore(),this},_drawControl:function(e,n,r,i,s){var o=this.cornerSize;this.isControlVisible(e)&&(t()||this.transparentCorners||n.clearRect(i,s,o,o),n[r](i,s,o,o))},isControlVisible:function(e){return this._getControlsVisibility()[e]},setControlVisible:function(e,t){return this._getControlsVisibility()[e]=t,this},setControlsVisibility:function(e){e||(e={});for(var t in e)this.setControlVisible(t,e[t]);return this},_getControlsVisibility:function(){return this._controlsVisibility||(this._controlsVisibility={tl:!0,tr:!0,br:!0,bl:!0,ml:!0,mt:!0,mr:!0,mb:!0,mtr:!0}),this._controlsVisibility}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{FX_DURATION:500,fxCenterObjectH:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("left"),endValue:this.getCenter().left,duration:this.FX_DURATION,onChange:function(t){e.set("left",t),s.renderAll(),i()},onComplete:function(){e.setCoords(),r()}}),this},fxCenterObjectV:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("top"),endValue:this.getCenter().top,duration:this.FX_DURATION,onChange:function(t){e.set("top",t),s.renderAll(),i()},onComplete:function(){e.setCoords(),r()}}),this},fxRemove:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("opacity"),endValue:0,duration:this.FX_DURATION,onStart:function(){e.set("active",!1)},onChange:function(t){e.set("opacity",t),s.renderAll(),i()},onComplete:function(){s.remove(e),r()}}),this}}),fabric.util.object.extend(fabric.Object.prototype,{animate:function(){if(arguments[0]&&typeof arguments[0]=="object"){var e=[],t,n;for(t in arguments[0])e.push(t);for(var r=0,i=e.length;rthis.x2?this.x2:this.x1),i=-this.height/2-(this.y1>this.y2?this.y2:this.y1);n="translate("+r+", "+i+") "}return t.push("\n'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Line.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" ")),t.Line.fromElement=function(e,r){var i=t.parseAttributes(e,t.Line.ATTRIBUTE_NAMES),s=[i.x1||0,i.y1||0,i.x2||0,i.y2||0];return new t.Line(s,n(i,r))},t.Line.fromObject=function(e){var n=[e.x1,e.y1,e.x2,e.y2];return new t.Line(n,e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function i(e){return"radius"in e&&e.radius>0}var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Circle){t.warn("fabric.Circle is already defined.");return}t.Circle=t.util.createClass(t.Object,{type:"circle",radius:0,initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("radius",e.radius||0)},_set:function(e,t){return this.callSuper("_set",e,t),e==="radius"&&this.setRadius(t),this},toObject:function(e){return r(this.callSuper("toObject",e),{radius:this.get("radius")})},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=0,r=0;return this.group&&(n=this.left+this.radius,r=this.top+ +this.radius),t.push("\n'),e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.arc(t?this.left+this.radius:0,t?this.top+this.radius:0,this.radius,0,n,!1),this._renderFill(e),this._renderStroke(e)},getRadiusX:function(){return this.get("radius")*this.get("scaleX")},getRadiusY:function(){return this.get("radius")*this.get("scaleY")},setRadius:function(e){this.radius=e,this.set("width",e*2).set("height",e*2)},complexity:function(){return 1}}),t.Circle.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy r".split(" ")),t.Circle.fromElement=function(e,n){n||(n={});var s=t.parseAttributes(e,t.Circle.ATTRIBUTE_NAMES);if(!i(s))throw new Error("value of `r` attribute is required and can not be negative");s.left=s.left||0,s.top=s.top||0;var o=new t.Circle(r(s,n));return o.left-=o.radius,o.top-=o.radius,o},t.Circle.fromObject=function(e){return new t.Circle(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={});if(t.Triangle){t.warn("fabric.Triangle is already defined");return}t.Triangle=t.util.createClass(t.Object,{type:"triangle",initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("width",e.width||100).set("height",e.height||100)},_render:function(e){var t=this.width/2,n=this.height/2;e.beginPath(),e.moveTo(-t,n),e.lineTo(0,-n),e.lineTo(t,n),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=this.width/2,r=this.height/2;e.beginPath(),t.util.drawDashedLine(e,-n,r,0,-r,this.strokeDashArray),t.util.drawDashedLine(e,0,-r,n,r,this.strokeDashArray),t.util.drawDashedLine(e,n,r,-n,r,this.strokeDashArray),e.closePath()},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=this.width/2,r=this.height/2,i=[-n+" "+r,"0 "+ -r,n+" "+r].join(",");return t.push("'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Triangle.fromObject=function(e){return new t.Triangle(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Ellipse){t.warn("fabric.Ellipse is already defined.");return}t.Ellipse=t.util.createClass(t.Object,{type:"ellipse",rx:0,ry:0,initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("rx",e.rx||0),this.set("ry",e.ry||0),this.set("width",this.get("rx")*2),this.set("height",this.get("ry")*2)},toObject:function(e){return r(this.callSuper("toObject",e),{rx:this.get("rx"),ry:this.get("ry")})},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=0,r=0;return this.group&&(n=this.left+this.rx,r=this.top+this.ry),t.push("\n'),e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.save(),e.transform(1,0,0,this.ry/this.rx,0,0),e.arc(t?this.left+this.rx:0,t?(this.top+this.ry)*this.rx/this.ry:0,this.rx,0,n,!1),e.restore(),this._renderFill(e),this._renderStroke(e)},complexity:function(){return 1}}),t.Ellipse.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" ")),t.Ellipse.fromElement=function(e,n){n||(n={});var i=t.parseAttributes(e,t.Ellipse.ATTRIBUTE_NAMES);i.left=i.left||0,i.top=i.top||0;var s=new t.Ellipse(r(i,n));return s.top-=s.ry,s.left-=s.rx,s},t.Ellipse.fromObject=function(e){return new t.Ellipse(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;if(t.Rect){console.warn("fabric.Rect is already defined");return}var r=t.Object.prototype.stateProperties.concat();r.push("rx","ry","x","y"),t.Rect=t.util.createClass(t.Object,{stateProperties:r,type:"rect",rx:0,ry:0,strokeDashArray:null,initialize:function(e){e=e||{},this.callSuper("initialize",e),this._initRxRy()},_initRxRy:function(){this.rx&&!this.ry?this.ry=this.rx:this.ry&&!this.rx&&(this.rx=this.ry)},_render:function(e,t){if(this.width===1&&this.height===1){e.fillRect(0,0,1,1);return}var n=this.rx?Math.min(this.rx,this.width/2):0,r=this.ry?Math.min(this.ry,this.height/2):0,i=this.width,s=this.height,o=t?this.left:0,u=t?this.top:0,a=n!==0||r!==0,f=.4477152502;e.beginPath(),t||e.translate(-this.width/2,-this.height/2),e.moveTo(o+n,u),e.lineTo(o+i-n,u),a&&e.bezierCurveTo(o+i-f*n,u,o+i,u+f*r,o+i,u+r),e.lineTo(o+i,u+s-r),a&&e.bezierCurveTo(o+i,u+s-f*r,o+i-f*n,u+s,o+i-n,u+s),e.lineTo(o+n,u+s),a&&e.bezierCurveTo(o+f*n,u+s,o,u+s-f*r,o,u+s-r),e.lineTo(o,u+r),a&&e.bezierCurveTo(o,u+f*r,o+f*n,u,o+n,u),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=-this.width/2,r=-this.height/2,i=this.width,s=this.height;e.beginPath(),t.util.drawDashedLine(e,n,r,n+i,r,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r,n+i,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r+s,n,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n,r+s,n,r,this.strokeDashArray),e.closePath()},toObject:function(e){var t=n(this.callSuper("toObject",e),{rx:this.get("rx")||0,ry:this.get("ry")||0});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=this.left,r=this.top;return this.group||(n=-this.width/2,r=-this.height/2),t.push("\n'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Rect.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" ")),t.Rect.fromElement=function(e,r){if(!e)return null;r=r||{};var i=t.parseAttributes(e,t.Rect.ATTRIBUTE_NAMES);return i.left=i.left||0,i.top=i.top||0,new t.Rect(n(r?t.util.object.clone(r):{},i))},t.Rect.fromObject=function(e){return new t.Rect(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.toFixed;if(t.Polyline){t.warn("fabric.Polyline is already defined");return}t.Polyline=t.util.createClass(t.Object,{type:"polyline",points:null,initialize:function(e,t,n){t=t||{},this.set("points",e),this.callSuper("initialize",t),this._calcDimensions(n)},_calcDimensions:function(e){return t.Polygon.prototype._calcDimensions.call(this,e)},toObject:function(e){return t.Polygon.prototype.toObject.call(this,e)},toSVG:function(e){var t=[],r=this._createBaseSVGMarkup();for(var i=0,s=this.points.length;i\n'),e?e(r.join("")):r.join("")},_render:function(e){var t;e.beginPath(),e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n\n'),e?e(n.join("")):n.join("")},_render:function(e){var t;e.beginPath(),e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n"},toObject:function(e){var t=i(this.callSuper("toObject",e),{path:this.path.map(function(e){return e.slice()}),pathOffset:this.pathOffset});return this.sourcePath&&(t.sourcePath=this.sourcePath),this.transformMatrix&&(t.transformMatrix=this.transformMatrix),t},toDatalessObject:function(e){var t=this.toObject(e);return this.sourcePath&&(t.path=this.sourcePath),delete t.sourcePath,t},toSVG:function(e){var t=[],n=this._createBaseSVGMarkup();for(var r=0,i=this.path.length;r\n"),e?e(n.join("")):n.join("")},complexity:function(){return this.path.length},_parsePath:function(){var e=[],t=[],n,r,i=/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/ig,s,o;for(var f=0,l,c=this.path.length;fv)for(var g=1,y=l.length;g\n"];for(var i=0,s=t.length;i\n"),e?e(r.join("")):r.join("")},toString:function(){return"#"},isSameColor:function(){var e=(this.getObjects()[0].get("fill")||"").toLowerCase();return this.getObjects().every(function(t){return(t.get("fill")||"").toLowerCase()===e})},complexity:function(){return this.paths.reduce(function(e,t){return e+(t&&t.complexity?t.complexity():0)},0)},getObjects:function(){return this.paths}}),t.PathGroup.fromObject=function(e,n){typeof e.paths=="string"?t.loadSVGFromURL(e.paths,function(r){var i=e.paths;delete e.paths;var s=t.util.groupSVGElements(r,e,i);n(s)}):t.util.enlivenObjects(e.paths,function(r){delete e.paths,n(new t.PathGroup(r,e))})},t.PathGroup.async=!0}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.array.min,i=t.util.array.max,s=t.util.array.invoke;if(t.Group)return;var o={lockMovementX:!0,lockMovementY:!0,lockRotation:!0,lockScalingX:!0,lockScalingY:!0,lockUniScaling:!0};t.Group=t.util.createClass(t.Object,t.Collection,{type:"group",initialize:function(e,t){t=t||{},this._objects=e||[];for(var r=this._objects.length;r--;)this._objects[r].group=this;this.originalState={},this.callSuper("initialize"),this._calcBounds(),this._updateObjectsCoords(),t&&n(this,t),this._setOpacityIfSame(),this.setCoords(),this.saveCoords()},_updateObjectsCoords:function(){this.forEachObject(this._updateObjectCoords,this)},_updateObjectCoords:function(e){var t=e.getLeft(),n=e.getTop();e.set({originalLeft:t,originalTop:n,left:t-this.left,top:n-this.top}),e.setCoords(),e.__origHasControls=e.hasControls,e.hasControls=!1},toString:function(){return"#"},addWithUpdate:function(e){return this._restoreObjectsState(),e&&(this._objects.push(e),e.group=this),this.forEachObject(this._setObjectActive,this),this._calcBounds(),this._updateObjectsCoords(),this},_setObjectActive:function(e){e.set("active",!0),e.group=this},removeWithUpdate:function(e){return this._moveFlippedObject(e),this._restoreObjectsState(),this.forEachObject(this._setObjectActive,this),this.remove(e),this._calcBounds(),this._updateObjectsCoords(),this},_onObjectAdded:function(e){e.group=this},_onObjectRemoved:function(e){delete e.group,e.set("active",!1)},delegatedProperties:{fill:!0,opacity:!0,fontFamily:!0,fontWeight:!0,fontSize:!0,fontStyle:!0,lineHeight:!0,textDecoration:!0,textAlign:!0,backgroundColor:!0},_set:function(e,t){if(e in this.delegatedProperties){var n=this._objects.length;this[e]=t;while(n--)this._objects[n].set(e,t)}else this[e]=t},toObject:function(e){return n(this.callSuper("toObject",e),{objects:s(this._objects,"toObject",e)})},render:function(e){if(!this.visible)return;e.save(),this.clipTo&&t.util.clipContext(this,e);for(var n=0,r=this._objects.length;n\n'];for(var n=0,r=this._objects.length;n\n"),e?e(t.join("")):t.join("")},get:function(e){if(e in o){if(this[e])return this[e];for(var t=0,n=this._objects.length;t\n','\n");if(this.stroke||this.strokeDashArray){var i=this.fill;this.fill=null,t.push("\n'),this.fill=i}return t.push("\n"),e?e(t.join("")):t.join("")},getSrc:function(){if(this.getElement())return this.getElement().src||this.getElement()._src},toString:function(){return'#'},clone:function(e,t){this.constructor.fromObject(this.toObject(t),e)},applyFilters:function(e){if(!this._originalElement)return;if(this.filters.length===0){this._element=this._originalElement,e&&e();return}var t=this._originalElement,n=fabric.util.createCanvasElement(),r=fabric.util.createImage(),i=this;return n.width=t.width,n.height=t.height,n.getContext("2d").drawImage(t,0,0,t.width,t.height),this.filters.forEach(function(e){e&&e.applyTo(n)}),r.width=t.width,r.height=t.height,fabric.isLikelyNode?(r.src=n.toBuffer(undefined,fabric.Image.pngCompression),i._element=r,e&&e()):(r.onload=function(){i._element=r,e&&e(),r.onload=n=t=null},r.src=n.toDataURL("image/png")),this},_render:function(e,t){this._element&&e.drawImage(this._element,t?this.left:-this.width/2,t?this.top:-this.height/2,this.width,this.height),this._renderStroke(e)},_resetWidthHeight:function(){var e=this.getElement();this.set("width",e.width),this.set("height",e.height)},_initElement:function(e){this.setElement(fabric.util.getById(e)),fabric.util.addClass(this.getElement(),fabric.Image.CSS_CANVAS)},_initConfig:function(e){e||(e={}),this.setOptions(e),this._setWidthHeight(e),this._element&&this.crossOrigin&&(this._element.crossOrigin=this.crossOrigin)},_initFilters:function(e,t){e.filters&&e.filters.length?fabric.util.enlivenObjects(e.filters,function(e){t&&t(e)},"fabric.Image.filters"):t&&t()},_setWidthHeight:function(e){this.width="width"in e?e.width:this.getElement()?this.getElement().width||0:0,this.height="height"in e?e.height:this.getElement()?this.getElement().height||0:0},complexity:function(){return 1}}),fabric.Image.CSS_CANVAS="canvas-img",fabric.Image.prototype.getSvgSrc=fabric.Image.prototype.getSrc,fabric.Image.fromObject=function(e,t){fabric.util.loadImage(e.src,function(n){fabric.Image.prototype._initFilters.call(e,e,function(r){e.filters=r||[];var i=new fabric.Image(n,e);t&&t(i)})},null,e.crossOrigin)},fabric.Image.fromURL=function(e,t,n){fabric.util.loadImage(e,function(e){t(new fabric.Image(e,n))},null,n&&n.crossOrigin)},fabric.Image.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y width height xlink:href".split(" ")),fabric.Image.fromElement=function(e,n,r){var i=fabric.parseAttributes(e,fabric.Image.ATTRIBUTE_NAMES);fabric.Image.fromURL(i["xlink:href"],n,t(r?fabric.util.object.clone(r):{},i))},fabric.Image.async=!0,fabric.Image.pngCompression=1}(typeof exports!="undefined"?exports:this),fabric.util.object.extend(fabric.Object.prototype,{_getAngleValueForStraighten:function(){var e=this.getAngle()%360;return e>0?Math.round((e-1)/90)*90:Math.round(e/90)*90},straighten:function(){return this.setAngle(this._getAngleValueForStraighten()),this},fxStraighten:function(e){e=e||{};var t=function(){},n=e.onComplete||t,r=e.onChange||t,i=this;return fabric.util.animate({startValue:this.get("angle"),endValue:this._getAngleValueForStraighten(),duration:this.FX_DURATION,onChange:function(e){i.setAngle(e),r()},onComplete:function(){i.setCoords(),n()},onStart:function(){i.set("active",!1)}}),this}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{straightenObject:function(e){return e.straighten(),this.renderAll(),this},fxStraightenObject:function(e){return e.fxStraighten({onChange:this.renderAll.bind(this)}),this}}),fabric.Image.filters=fabric.Image.filters||{},fabric.Image.filters.BaseFilter=fabric.util.createClass({type:"BaseFilter",toObject:function(){return{type:this.type}},toJSON:function(){return this.toObject()}}),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;t.Image.filters.Brightness=t.util.createClass(t.Image.filters.BaseFilter,{type:"Brightness",initialize:function(e){e=e||{},this.brightness=e.brightness||0},applyTo:function(e){var t=e.getContext("2d"),n=t.getImageData(0,0,e.width,e.height),r=n.data,i=this.brightness;for(var s=0,o=r.length;sa||C<0||C>u)continue;var k=(N*u+C)*4,L=t[x*i+T];b+=o[k]*L,w+=o[k+1]*L,E+=o[k+2]*L,S+=o[k+3]*L}h[y]=b,h[y+1]=w,h[y+2]=E,h[y+3]=S+p*(255-S)}n.putImageData(c,0,0)},toObject:function(){return n(this.callSuper("toObject"),{opaque:this.opaque,matrix:this.matrix})}}),t.Image.filters.Convolute.fromObject=function(e){return new t.Image.filters.Convolute(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;t.Image.filters.GradientTransparency=t.util.createClass(t.Image.filters.BaseFilter,{type:"GradientTransparency",initialize:function(e){e=e||{},this.threshold=e.threshold||100},applyTo:function(e){var t=e.getContext("2d"),n=t.getImageData(0,0,e.width,e.height),r=n.data,i=this.threshold,s=r.length;for(var o=0,u=r.length;o-1?e.channel:0},applyTo:function(e){if(!this.mask)return;var n=e.getContext("2d"),r=n.getImageData(0,0,e.width,e.height),i=r.data,s=this.mask.getElement(),o=t.util.createCanvasElement(),u=this.channel,a,f=r.width*r.height*4;o.width=s.width,o.height=s.height,o.getContext("2d").drawImage(s,0,0,s.width,s.height);var l=o.getContext("2d").getImageData(0,0,s.width,s.height),c=l.data;for(a=0;ao&&f>o&&l>o&&u(a-f)'},_render:function(e){typeof Cufon=="undefined"||this.useNative===!0?this._renderViaNative(e):this._renderViaCufon(e)},_renderViaNative:function(e){var n=this.text.split(this._reNewline);this._setTextStyles(e),this.width=this._getTextWidth(e,n),this.height=this._getTextHeight(e,n),this.clipTo&&t.util.clipContext(this,e),this._renderTextBackground(e,n),this._translateForTextAlign(e),this._renderText(e,n),this.textAlign!=="left"&&this.textAlign!=="justify"&&e.restore(),this._renderTextDecoration(e,n),this.clipTo&&e.restore(),this._setBoundaries(e,n),this._totalLineHeight=0},_renderText:function(e,t){e.save(),this._setShadow(e),this._setupFillRule(e),this._renderTextFill(e,t),this._renderTextStroke(e,t),this._restoreFillRule(e),this._removeShadow(e),e.restore()},_translateForTextAlign:function(e){this.textAlign!=="left"&&this.textAlign!=="justify"&&(e.save(),e.translate(this.textAlign==="center"?this.width/2:this.width,0))},_setBoundaries:function(e,t){this._boundaries=[];for(var n=0,r=t.length;nn&&(n=s)}return n},_renderChars:function(e,t,n,r,i){t[e](n,r,i)},_renderTextLine:function(e,t,n,r,i,s){i-=this.fontSize/4;if(this.textAlign!=="justify"){this._renderChars(e,t,n,r,i,s);return}var o=t.measureText(n).width,u=this.width;if(u>o){var a=n.split(/\s+/),f=t.measureText(n.replace(/\s+/g,"")).width,l=u-f,c=a.length-1,h=l/c,p=0;for(var d=0,v=a.length;d-1&&i(this.fontSize*this.lineHeight),this.textDecoration.indexOf("line-through")>-1&&i(this.fontSize*this.lineHeight-this.fontSize/2),this.textDecoration.indexOf("overline")>-1&&i(this.fontSize*this.lineHeight-this.fontSize)},_getFontDeclaration:function(){return[t.isLikelyNode?this.fontWeight:this.fontStyle,t.isLikelyNode?this.fontStyle:this.fontWeight,this.fontSize+"px",t.isLikelyNode?'"'+this.fontFamily+'"':this.fontFamily].join(" ")},render:function(e,t){if(!this.visible)return;e.save(),this._transform(e,t);var n=this.transformMatrix,r=this.group&&this.group.type==="path-group";r&&e.translate(-this.group.width/2,-this.group.height/2),n&&e.transform(n[0],n[1],n[2],n[3],n[4],n[5]),r&&e.translate(this.left,this.top),this._render(e),e.restore()},toObject:function(e){var t=n(this.callSuper("toObject",e),{text:this.text,fontSize:this.fontSize,fontWeight:this.fontWeight,fontFamily:this.fontFamily,fontStyle:this.fontStyle,lineHeight:this.lineHeight,textDecoration:this.textDecoration,textAlign:this.textAlign,path:this.path,textBackgroundColor:this.textBackgroundColor,useNative:this.useNative});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=[],n=this.text.split(this._reNewline),r=this._getSVGLeftTopOffsets(n),i=this._getSVGTextAndBg(r.lineTop,r.textLeft,n),s=this._getSVGShadows(r.lineTop,n);return r.textTop+=this._fontAscent?this._fontAscent/5*this.lineHeight:0,this._wrapSVGTextAndBg(t,i,s,r),e?e(t.join("")):t.join("")},_getSVGLeftTopOffsets:function(e){var t=this.useNative?this.fontSize*this.lineHeight:-this._fontAscent-this._fontAscent/5*this.lineHeight,n=-(this.width/2),r=this.useNative?this.fontSize-1:this.height/2-e.length*this.fontSize-this._totalLineHeight;return{textLeft:n+(this.group?this.left:0),textTop:r+(this.group?this.top:0),lineTop:t}},_wrapSVGTextAndBg:function(e,t,n,r){e.push('\n',t.textBgRects.join(""),"',n.join(""),t.textSpans.join(""),"\n","\n")},_getSVGShadows:function(e,n){var r=[],s,o,u=1;if(!this.shadow||!this._boundaries)return r;for(s=0,o=n.length;s",t.util.string.escapeXml(n[s]),""),u=1}else u++;return r},_getSVGTextAndBg:function(e,t,n){var r=[],i=[],s=1;this._setSVGBg(i);for(var o=0,u=n.length;o",t.util.string.escapeXml(e),"")},_setSVGTextLineBg:function(e,t,n,r){e.push("\n')},_setSVGBg:function(e){this.backgroundColor&&this._boundaries&&e.push("')},_getFillAttributes:function(e){var n=e&&typeof e=="string"?new t.Color(e):"";return!n||!n.getSource()||n.getAlpha()===1?'fill="'+e+'"':'opacity="'+n.getAlpha()+'" fill="'+n.setAlpha(1).toRgb()+'"'},_set:function(e,t){e==="fontFamily"&&this.path&&(this.path=this.path.replace(/(.*?)([^\/]*)(\.font\.js)/,"$1"+t+"$3")),this.callSuper("_set",e,t),e in this._dimensionAffectingProps&&(this._initDimensions(),this.setCoords())},complexity:function(){return 1}}),t.Text.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size text-decoration text-anchor".split(" ")),t.Text.DEFAULT_SVG_FONT_SIZE=16,t.Text.fromElement=function(e,n){if(!e)return null;var r=t.parseAttributes(e,t.Text.ATTRIBUTE_NAMES);n=t.util.object.extend(n?t.util.object.clone(n):{},r),"dx"in r&&(n.left+=r.dx),"dy"in r&&(n.top+=r.dy),"fontSize"in n||(n.fontSize=t.Text.DEFAULT_SVG_FONT_SIZE),n.originX||(n.originX="left");var i=new t.Text(e.textContent,n),s=0;return i.originX==="left"&&(s=i.getWidth()/2),i.originX==="right"&&(s=-i.getWidth()/2),i.set({left:i.getLeft()+s,top:i.getTop()-i.getHeight()/2}),i},t.Text.fromObject=function(e){return new t.Text(e.text,r(e))},t.util.createAccessors(t.Text)}(typeof exports!="undefined"?exports:this),function(){var e=fabric.util.object.clone;fabric.IText=fabric.util.createClass(fabric.Text,fabric.Observable,{type:"i-text",selectionStart:0,selectionEnd:0,selectionColor:"rgba(17,119,255,0.3)",isEditing:!1,editable:!0,editingBorderColor:"rgba(102,153,255,0.25)",cursorWidth:2,cursorColor:"#333",cursorDelay:1e3,cursorDuration:600,styles:null,caching:!0,_skipFillStrokeCheck:!0,_reSpace:/\s|\n/,_fontSizeFraction:4,_currentCursorOpacity:0,_selectionDirection:null,_abortCursorAnimation:!1,_charWidthsCache:{},initialize:function(e,t){this.styles=t?t.styles||{}:{},this.callSuper("initialize",e,t),this.initBehavior(),fabric.IText.instances.push(this),this.__lineWidths={},this.__lineHeights={},this.__lineOffsets={}},isEmptyStyles:function(){if(!this.styles)return!0;var e=this.styles;for(var t in e)for(var n in e[t])for(var r in e[t][n])return!1;return!0},setSelectionStart:function(e){this.selectionStart!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})),this.selectionStart=e,this.hiddenTextarea&&(this.hiddenTextarea.selectionStart=e)},setSelectionEnd:function(e){this.selectionEnd!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})),this.selectionEnd=e,this.hiddenTextarea&&(this.hiddenTextarea.selectionEnd=e)},getSelectionStyles:function(e,t){if(arguments.length===2){var n=[];for(var r=e;r=r.charIndex&&(a!==o||hs&&a-1&&this._renderCharDecorationAtOffset(e,n,r+this.fontSize/this._fontSizeFraction,i,0,this.fontSize/20),u.indexOf("line-through")>-1&&this._renderCharDecorationAtOffset(e,n,r+this.fontSize/this._fontSizeFraction,i,o/2,a/20),u.indexOf("overline")>-1&&this._renderCharDecorationAtOffset(e,n,r,i,s-this.fontSize/this._fontSizeFraction,this.fontSize/20)},_renderCharDecorationAtOffset:function(e,t,n,r,i,s){e.fillRect(t,n-i,r,s)},_renderTextLine:function(e,t,n,r,i,s){i+=this.fontSize/4,this.callSuper("_renderTextLine",e,t,n,r,i,s)},_renderTextDecoration:function(e,t){if(this.isEmptyStyles())return this.callSuper("_renderTextDecoration",e,t)},_renderTextLinesBackground:function(e,t){if(!this.textBackgroundColor&&!this.styles)return;e.save(),this.textBackgroundColor&&(e.fillStyle=this.textBackgroundColor);var n=0,r=this.fontSize/this._fontSizeFraction;for(var i=0,s=t.length;in&&(n=s)}return n},_getHeightOfLine:function(e,t,n){n=n||this.text.split(this._reNewline);var r=this._getHeightOfChar(e,n[t][0],t,0),i=n[t],s=i.split("");for(var o=1,u=s.length;or&&(r=a)}return r*this.lineHeight},_getTextHeight:function(e,t){var n=0;for(var r=0,i=t.length;r-1)t++,n--;return e-t},findWordBoundaryRight:function(e){var t=0,n=e;if(this._reSpace.test(this.text.charAt(n)))while(this._reSpace.test(this.text.charAt(n)))t++,n++;while(/\S/.test(this.text.charAt(n))&&n-1)t++,n--;return e-t},findLineBoundaryRight:function(e){var t=0,n=e;while(!/\n/.test(this.text.charAt(n))&&n0&&nr;s?this.removeStyleObject(s,n+1):this.removeStyleObject(this.get2DCursorLocation(n).charIndex===0,n)}this.text=this.text.slice(0,e)+this.text.slice(t)},insertChars:function(e){var t=this.text.slice(this.selectionStart,this.selectionStart+1)==="\n";this.text=this.text.slice(0,this.selectionStart)+e+this.text.slice(this.selectionEnd),this.selectionStart===this.selectionEnd&&this.insertStyleObjects(e,t,this.copiedStyles),this.selectionStart+=e.length,this.selectionEnd=this.selectionStart,this.canvas&&this.canvas.renderAll().renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},insertNewlineStyleObject:function(t,n,r){this.shiftLineStyles(t,1),this.styles[t+1]||(this.styles[t+1]={});var i=this.styles[t][n-1],s={};if(r)s[0]=e(i),this.styles[t+1]=s;else{for(var o in this.styles[t])parseInt(o,10)>=n&&(s[parseInt(o,10)-n]=this.styles[t][o],delete this.styles[t][o]);this.styles[t+1]=s}},insertCharStyleObject:function(t,n,r){var i=this.styles[t],s=e(i);n===0&&!r&&(n=1);for(var o in s){var u=parseInt(o,10);u>=n&&(i[u+1]=s[u])}this.styles[t][n]=r||e(i[n-1])},insertStyleObjects:function(e,t,n){if(this.isEmptyStyles())return;var r=this.get2DCursorLocation(),i=r.lineIndex,s=r.charIndex;this.styles[i]||(this.styles[i]={}),e==="\n"?this.insertNewlineStyleObject(i,s,t):n?this._insertStyles(n):this.insertCharStyleObject(i,s)},_insertStyles:function(e){for(var t=0,n=e.length;tt&&(this.styles[s+n]=r[s])}},removeStyleObject:function(t,n){var r=this.get2DCursorLocation(n),i=r.lineIndex,s=r.charIndex;if(t){var o=this.text.split(this._reNewline),u=o[i-1],a=u?u.length:0;this.styles[i-1]||(this.styles[i-1]={});for(s in this.styles[i])this.styles[i-1][parseInt(s,10)+a]=this.styles[i][s];this.shiftLineStyles(i,-1)}else{var f=this.styles[i];if(f){var l=this.selectionStart===this.selectionEnd?-1:0;delete f[s+l]}var c=e(f);for(var h in c){var p=parseInt(h,10);p>=s&&p!==0&&(f[p-1]=c[p],delete f[p])}}},insertNewline:function(){this.insertChars("\n")}})}(),fabric.util.object.extend(fabric.IText.prototype,{initDoubleClickSimulation:function(){this.__lastClickTime=+(new Date),this.__lastLastClickTime=+(new Date),this.__lastPointer={},this.on("mousedown",this.onMouseDown.bind(this))},onMouseDown:function(e){this.__newClickTime=+(new Date);var t=this.canvas.getPointer(e.e);this.isTripleClick(t)?(this.fire("tripleclick",e),this._stopEvent(e.e)):this.isDoubleClick(t)&&(this.fire("dblclick",e),this._stopEvent(e.e)),this.__lastLastClickTime=this.__lastClickTime,this.__lastClickTime=this.__newClickTime,this.__lastPointer=t,this.__lastIsEditing=this.isEditing,this.__lastSelected=this.selected},isDoubleClick:function(e){return this.__newClickTime-this.__lastClickTime<500&&this.__lastPointer.x===e.x&&this.__lastPointer.y===e.y&&this.__lastIsEditing},isTripleClick:function(e){return this.__newClickTime-this.__lastClickTime<500&&this.__lastClickTime-this.__lastLastClickTime<500&&this.__lastPointer.x===e.x&&this.__lastPointer.y===e.y},_stopEvent:function(e){e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation()},initCursorSelectionHandlers:function(){this.initSelectedHandler(),this.initMousedownHandler(),this.initMousemoveHandler(),this.initMouseupHandler(),this.initClicks()},initClicks:function(){this.on("dblclick",function(e){this.selectWord(this.getSelectionStartFromPointer(e.e))}),this.on("tripleclick",function(e){this.selectLine(this.getSelectionStartFromPointer(e.e))})},initMousedownHandler:function(){this.on("mousedown",function(e){var t=this.canvas.getPointer(e.e);this.__mousedownX=t.x,this.__mousedownY=t.y,this.__isMousedown=!0,this.hiddenTextarea&&this.canvas&&this.canvas.wrapperEl.appendChild(this.hiddenTextarea),this.selected&&this.setCursorByClick(e.e),this.isEditing&&(this.__selectionStartOnMouseDown=this.selectionStart,this.initDelayedCursor(!0))})},initMousemoveHandler:function(){this.on("mousemove",function(e){if(!this.__isMousedown||!this.isEditing)return;var t=this.getSelectionStartFromPointer(e.e);t>=this.__selectionStartOnMouseDown?(this.setSelectionStart(this.__selectionStartOnMouseDown),this.setSelectionEnd(t)):(this.setSelectionStart(t),this.setSelectionEnd(this.__selectionStartOnMouseDown))})},_isObjectMoved:function(e){var t=this.canvas.getPointer(e);return this.__mousedownX!==t.x||this.__mousedownY!==t.y},initMouseupHandler:function(){this.on("mouseup",function(e){this.__isMousedown=!1;if(this._isObjectMoved(e.e))return;this.__lastSelected&&(this.enterEditing(),this.initDelayedCursor(!0)),this.selected=!0})},setCursorByClick:function(e){var t=this.getSelectionStartFromPointer(e);e.shiftKey?ts?0:1,a=r+u;return this.flipX&&(a=i-a),a>this.text.length&&(a=this.text.length),a}}),fabric.util.object.extend(fabric.IText.prototype,{initHiddenTextarea:function(){this.hiddenTextarea=fabric.document.createElement("textarea"),this.hiddenTextarea.setAttribute("autocapitalize","off"),this.hiddenTextarea.style.cssText="position: absolute; top: 0; left: -9999px",fabric.document.body.appendChild(this.hiddenTextarea),fabric.util.addListener(this.hiddenTextarea,"keydown",this.onKeyDown.bind(this)),fabric.util.addListener(this.hiddenTextarea,"keypress",this.onKeyPress.bind(this)),fabric.util.addListener(this.hiddenTextarea,"copy",this.copy.bind(this)),fabric.util.addListener(this.hiddenTextarea,"paste",this.paste.bind(this)),!this._clickHandlerInitialized&&this.canvas&&(fabric.util.addListener(this.canvas.upperCanvasEl,"click",this.onClick.bind(this)),this._clickHandlerInitialized=!0)},_keysMap:{8:"removeChars",13:"insertNewline",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown",46:"forwardDelete"},_ctrlKeysMap:{65:"selectAll",88:"cut"},onClick:function(){this.hiddenTextarea&&this.hiddenTextarea.focus()},onKeyDown:function(e){if(!this.isEditing)return;if(e.keyCode in this._keysMap&&e.charCode===0)this[this._keysMap[e.keyCode]](e);else{if(!(e.keyCode in this._ctrlKeysMap&&(e.ctrlKey||e.metaKey)))return;this[this._ctrlKeysMap[e.keyCode]](e)}e.stopPropagation(),this.canvas&&this.canvas.renderAll()},forwardDelete:function(e){this.selectionStart===this.selectionEnd&&this.moveCursorRight(e),this.removeChars(e)},copy:function(e){var t=this.getSelectedText(),n=this._getClipboardData(e);n&&n.setData("text",t),this.copiedText=t,this.copiedStyles=this.getSelectionStyles(this.selectionStart,this.selectionEnd)},paste:function(e){var t=null,n=this._getClipboardData(e);n?t=n.getData("text"):t=this.copiedText,t&&this.insertChars(t)},cut:function(e){if(this.selectionStart===this.selectionEnd)return;this.copy(),this.removeChars(e)},_getClipboardData:function(e){return e&&(e.clipboardData||fabric.window.clipboardData)},onKeyPress:function(e){if(!this.isEditing||e.metaKey||e.ctrlKey||e.keyCode in this._keysMap&&e.charCode===0)return;this.insertChars(String.fromCharCode(e.which)),e.stopPropagation()},getDownCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.text.split(this._reNewline),i,s,o=this.text.slice(0,n),u=this.text.slice(n),a=o.slice(o.lastIndexOf("\n")+1),f=u.match(/(.*)\n?/)[1],l=(u.match(/.*\n(.*)\n?/)||{})[1]||"",c=this.get2DCursorLocation(n);if(c.lineIndex===r.length-1||e.metaKey)return this.text.length-n;var h=this._getWidthOfLine(this.ctx,c.lineIndex,r);s=this._getLineLeftOffset(h);var p=s,d=c.lineIndex;for(var v=0,m=a.length;vn){f=!0;var d=u-p,v=u,m=Math.abs(d-n),g=Math.abs(v-n);a=gthis.text.length&&(this.selectionStart=this.text.length),this.selectionEnd=this.selectionStart},moveCursorDownWithShift:function(e){if(this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd){this.selectionStart+=e,this._selectionDirection="left";return}this._selectionDirection="right",this.selectionEnd+=e,this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length)},getUpCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.get2DCursorLocation(n);if(r.lineIndex===0||e.metaKey)return n;var i=this.text.slice(0,n),s=i.slice(i.lastIndexOf("\n")+1),o=(i.match(/\n?(.*)\n.*$/)||{})[1]||"",u=this.text.split(this._reNewline),a,f=this._getWidthOfLine(this.ctx,r.lineIndex,u),l=this._getLineLeftOffset(f),c=l,h=r.lineIndex;for(var p=0,d=s.length;pn){f=!0;var d=u-p,v=u,m=Math.abs(d-n),g=Math.abs(v-n);a=g=this.text.length&&this.selectionEnd>=this.text.length)return;this.abortCursorAnimation(),this._currentCursorOpacity=1,e.shiftKey?this.moveCursorRightWithShift(e):this.moveCursorRightWithoutShift(e),this.initDelayedCursor()},moveCursorRightWithShift:function(e){this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd?this._moveRight(e,"selectionStart"):(this._selectionDirection="right",this._moveRight(e,"selectionEnd"),this.text.charAt(this.selectionEnd-1)==="\n"&&this.selectionEnd++,this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length))},moveCursorRightWithoutShift:function(e){this._selectionDirection="right",this.selectionStart===this.selectionEnd?(this._moveRight(e,"selectionStart"),this.selectionEnd=this.selectionStart):(this.selectionEnd+=this.getNumNewLinesInSelectedText(),this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length),this.selectionStart=this.selectionEnd)},removeChars:function(e){this.selectionStart===this.selectionEnd?this._removeCharsNearCursor(e):this._removeCharsFromTo(this.selectionStart,this.selectionEnd),this.selectionEnd=this.selectionStart,this._removeExtraneousStyles(),this.canvas&&this.canvas.renderAll().renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},_removeCharsNearCursor:function(e){if(this.selectionStart!==0)if(e.metaKey){var t=this.findLineBoundaryLeft(this.selectionStart);this._removeCharsFromTo(t,this.selectionStart),this.selectionStart=t}else if(e.altKey){var n=this.findWordBoundaryLeft(this.selectionStart);this._removeCharsFromTo(n,this.selectionStart),this.selectionStart=n}else{var r=this.text.slice(this.selectionStart-1,this.selectionStart)==="\n";this.removeStyleObject(r),this.selectionStart--,this.text=this.text.slice(0,this.selectionStart)+this.text.slice(this.selectionStart+1)}}}),fabric.util.object.extend(fabric.IText.prototype,{_setSVGTextLineText:function(e,t,n,r,i,s){this.styles[t]?this._setSVGTextLineChars(e,t,n,r,i,s):this.callSuper("_setSVGTextLineText",e,t,n,r,i)},_setSVGTextLineChars:function(e,t,n,r,i,s){var o=t===0||this.useNative?"y":"dy",u=e.split(""),a=0,f=this._getSVGLineLeftOffset(t),l=this._getSVGLineTopOffset(t),c=this._getHeightOfLine(this.ctx,t);for(var h=0,p=u.length;h'].join("")},_createTextCharSpan:function(e,t,n,r,i,s){var o=this.getSvgStyles.call(fabric.util.object.extend({visible:!0,fill:this.fill,stroke:this.stroke,type:"text"},t));return['',fabric.util.string.escapeXml(e),""].join("")}}),function(){function request(e,t,n){var r=URL.parse(e);r.port||(r.port=r.protocol.indexOf("https:")===0?443:80);var i=r.port===443?HTTPS:HTTP,s=i.request({hostname:r.hostname,port:r.port,path:r.path,method:"GET"},function(e){var r="";t&&e.setEncoding(t),e.on("end",function(){n(r)}),e.on("data",function(t){e.statusCode===200&&(r+=t)})});s.on("error",function(e){e.errno===process.ECONNREFUSED?fabric.log("ECONNREFUSED: connection refused to "+r.hostname+":"+r.port):fabric.log(e.message)}),s.end()}function requestFs(e,t){var n=require("fs");n.readFile(e,function(e,n){if(e)throw fabric.log(e),e;t(n)})}if(typeof document!="undefined"&&typeof window!="undefined")return;var DOMParser=require("xmldom").DOMParser,URL=require("url"),HTTP=require("http"),HTTPS=require("https"),Canvas=require("canvas"),Image=require("canvas").Image;fabric.util.loadImage=function(e,t,n){function r(r){i.src=new Buffer(r,"binary"),i._src=e,t&&t.call(n,i)}var i=new Image;e&&(e instanceof Buffer||e.indexOf("data")===0)?(i.src=i._src=e,t&&t.call(n,i)):e&&e.indexOf("http")!==0?requestFs(e,r):e?request(e,"binary",r):t&&t.call(n,e)},fabric.loadSVGFromURL=function(e,t,n){e=e.replace(/^\n\s*/,"").replace(/\?.*$/,"").trim(),e.indexOf("http")!==0?requestFs(e,function(e){fabric.loadSVGFromString(e.toString(),t,n)}):request(e,"",function(e){fabric.loadSVGFromString(e,t,n)})},fabric.loadSVGFromString=function(e,t,n){var r=(new DOMParser).parseFromString(e);fabric.parseSVGDocument(r.documentElement,function(e,n){t&&t(e,n)},n)},fabric.util.getScript=function(url,callback){request(url,"",function(body){eval(body),callback&&callback()})},fabric.Image.fromObject=function(e,t){fabric.util.loadImage(e.src,function(n){var r=new fabric.Image(n);r._initConfig(e),r._initFilters(e,function(e){r.filters=e||[],t&&t(r)})})},fabric.createCanvasForNode=function(e,t,n,r){r=r||n;var i=fabric.document.createElement("canvas"),s=new Canvas(e||600,t||600,r);i.style={},i.width=s.width,i.height=s.height;var o=fabric.Canvas||fabric.StaticCanvas,u=new o(i,n);return u.contextContainer=s.getContext("2d"),u.nodeCanvas=s,u.Font=Canvas.Font,u},fabric.StaticCanvas.prototype.createPNGStream=function(){return this.nodeCanvas.createPNGStream()},fabric.StaticCanvas.prototype.createJPEGStream=function(e){return this.nodeCanvas.createJPEGStream(e)};var origSetWidth=fabric.StaticCanvas.prototype.setWidth;fabric.StaticCanvas.prototype.setWidth=function(e,t){return origSetWidth.call(this,e,t),this.nodeCanvas.width=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setWidth=fabric.StaticCanvas.prototype.setWidth);var origSetHeight=fabric.StaticCanvas.prototype.setHeight;fabric.StaticCanvas.prototype.setHeight=function(e,t){return origSetHeight.call(this,e,t),this.nodeCanvas.height=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setHeight=fabric.StaticCanvas.prototype.setHeight)}();/* pako 0.2.3 nodeca/pako */ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.pako=e()}}(function(){return function e(t,i,n){function a(s,o){if(!i[s]){if(!t[s]){var f="function"==typeof require&&require;if(!o&&f)return f(s,!0);if(r)return r(s,!0);throw new Error("Cannot find module '"+s+"'")}var l=i[s]={exports:{}};t[s][0].call(l.exports,function(e){var i=t[s][1][e];return a(i?i:e)},l,l.exports,e,t,i,n)}return i[s].exports}for(var r="function"==typeof require&&require,s=0;s=0&&t.windowBits<16&&(t.windowBits=-t.windowBits,0===t.windowBits&&(t.windowBits=-15)),!(t.windowBits>=0&&t.windowBits<16)||e&&e.windowBits||(t.windowBits+=32),t.windowBits>15&&t.windowBits<48&&0===(15&t.windowBits)&&(t.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new d,this.strm.avail_out=0;var i=r.inflateInit2(this.strm,t.windowBits);if(i!==f.Z_OK)throw new Error(l[i]);this.header=new u,r.inflateGetHeader(this.strm,this.header)};h.prototype.push=function(e,t){var i,n,a,l,d,u=this.strm,h=this.options.chunkSize;if(this.ended)return!1;n=t===~~t?t:t===!0?f.Z_FINISH:f.Z_NO_FLUSH,u.input="string"==typeof e?o.binstring2buf(e):e,u.next_in=0,u.avail_in=u.input.length;do{if(0===u.avail_out&&(u.output=new s.Buf8(h),u.next_out=0,u.avail_out=h),i=r.inflate(u,f.Z_NO_FLUSH),i!==f.Z_STREAM_END&&i!==f.Z_OK)return this.onEnd(i),this.ended=!0,!1;u.next_out&&(0===u.avail_out||i===f.Z_STREAM_END||0===u.avail_in&&n===f.Z_FINISH)&&("string"===this.options.to?(a=o.utf8border(u.output,u.next_out),l=u.next_out-a,d=o.buf2string(u.output,a),u.next_out=l,u.avail_out=h-l,l&&s.arraySet(u.output,u.output,a,l,0),this.onData(d)):this.onData(s.shrinkBuf(u.output,u.next_out)))}while((u.avail_in>0||0===u.avail_out)&&i!==f.Z_STREAM_END);return i===f.Z_STREAM_END&&(n=f.Z_FINISH),n===f.Z_FINISH?(i=r.inflateEnd(this.strm),this.onEnd(i),this.ended=!0,i===f.Z_OK):!0},h.prototype.onData=function(e){this.chunks.push(e)},h.prototype.onEnd=function(e){e===f.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):s.flattenChunks(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg},i.Inflate=h,i.inflate=n,i.inflateRaw=a,i.ungzip=n},{"./utils/common":2,"./utils/strings":3,"./zlib/constants":5,"./zlib/gzheader":7,"./zlib/inflate.js":9,"./zlib/messages":11,"./zlib/zstream":12}],2:[function(e,t,i){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;i.assign=function(e){for(var t=Array.prototype.slice.call(arguments,1);t.length;){var i=t.shift();if(i){if("object"!=typeof i)throw new TypeError(i+"must be non-object");for(var n in i)i.hasOwnProperty(n)&&(e[n]=i[n])}}return e},i.shrinkBuf=function(e,t){return e.length===t?e:e.subarray?e.subarray(0,t):(e.length=t,e)};var a={arraySet:function(e,t,i,n,a){if(t.subarray&&e.subarray)return void e.set(t.subarray(i,i+n),a);for(var r=0;n>r;r++)e[a+r]=t[i+r]},flattenChunks:function(e){var t,i,n,a,r,s;for(n=0,t=0,i=e.length;i>t;t++)n+=e[t].length;for(s=new Uint8Array(n),a=0,t=0,i=e.length;i>t;t++)r=e[t],s.set(r,a),a+=r.length;return s}},r={arraySet:function(e,t,i,n,a){for(var r=0;n>r;r++)e[a+r]=t[i+r]},flattenChunks:function(e){return[].concat.apply([],e)}};i.setTyped=function(e){e?(i.Buf8=Uint8Array,i.Buf16=Uint16Array,i.Buf32=Int32Array,i.assign(i,a)):(i.Buf8=Array,i.Buf16=Array,i.Buf32=Array,i.assign(i,r))},i.setTyped(n)},{}],3:[function(e,t,i){"use strict";function n(e,t){if(65537>t&&(e.subarray&&s||!e.subarray&&r))return String.fromCharCode.apply(null,a.shrinkBuf(e,t));for(var i="",n=0;t>n;n++)i+=String.fromCharCode(e[n]);return i}var a=e("./common"),r=!0,s=!0;try{String.fromCharCode.apply(null,[0])}catch(o){r=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(o){s=!1}for(var f=new a.Buf8(256),l=0;256>l;l++)f[l]=l>=252?6:l>=248?5:l>=240?4:l>=224?3:l>=192?2:1;f[254]=f[254]=1,i.string2buf=function(e){var t,i,n,r,s,o=e.length,f=0;for(r=0;o>r;r++)i=e.charCodeAt(r),55296===(64512&i)&&o>r+1&&(n=e.charCodeAt(r+1),56320===(64512&n)&&(i=65536+(i-55296<<10)+(n-56320),r++)),f+=128>i?1:2048>i?2:65536>i?3:4;for(t=new a.Buf8(f),s=0,r=0;f>s;r++)i=e.charCodeAt(r),55296===(64512&i)&&o>r+1&&(n=e.charCodeAt(r+1),56320===(64512&n)&&(i=65536+(i-55296<<10)+(n-56320),r++)),128>i?t[s++]=i:2048>i?(t[s++]=192|i>>>6,t[s++]=128|63&i):65536>i?(t[s++]=224|i>>>12,t[s++]=128|i>>>6&63,t[s++]=128|63&i):(t[s++]=240|i>>>18,t[s++]=128|i>>>12&63,t[s++]=128|i>>>6&63,t[s++]=128|63&i);return t},i.buf2binstring=function(e){return n(e,e.length)},i.binstring2buf=function(e){for(var t=new a.Buf8(e.length),i=0,n=t.length;n>i;i++)t[i]=e.charCodeAt(i);return t},i.buf2string=function(e,t){var i,a,r,s,o=t||e.length,l=new Array(2*o);for(a=0,i=0;o>i;)if(r=e[i++],128>r)l[a++]=r;else if(s=f[r],s>4)l[a++]=65533,i+=s-1;else{for(r&=2===s?31:3===s?15:7;s>1&&o>i;)r=r<<6|63&e[i++],s--;s>1?l[a++]=65533:65536>r?l[a++]=r:(r-=65536,l[a++]=55296|r>>10&1023,l[a++]=56320|1023&r)}return n(l,a)},i.utf8border=function(e,t){var i;for(t=t||e.length,t>e.length&&(t=e.length),i=t-1;i>=0&&128===(192&e[i]);)i--;return 0>i?t:0===i?t:i+f[e[i]]>t?i:t}},{"./common":2}],4:[function(e,t){"use strict";function i(e,t,i,n){for(var a=65535&e|0,r=e>>>16&65535|0,s=0;0!==i;){s=i>2e3?2e3:i,i-=s;do a=a+t[n++]|0,r=r+a|0;while(--s);a%=65521,r%=65521}return a|r<<16|0}t.exports=i},{}],5:[function(e,t){t.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],6:[function(e,t){"use strict";function i(){for(var e,t=[],i=0;256>i;i++){e=i;for(var n=0;8>n;n++)e=1&e?3988292384^e>>>1:e>>>1;t[i]=e}return t}function n(e,t,i,n){var r=a,s=n+i;e=-1^e;for(var o=n;s>o;o++)e=e>>>8^r[255&(e^t[o])];return-1^e}var a=i();t.exports=n},{}],7:[function(e,t){"use strict";function i(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}t.exports=i},{}],8:[function(e,t){"use strict";var i=30,n=12;t.exports=function(e,t){var a,r,s,o,f,l,d,u,h,c,b,w,m,k,g,_,v,p,x,y,S,B,E,Z,A;a=e.state,r=e.next_in,Z=e.input,s=r+(e.avail_in-5),o=e.next_out,A=e.output,f=o-(t-e.avail_out),l=o+(e.avail_out-257),d=a.dmax,u=a.wsize,h=a.whave,c=a.wnext,b=a.window,w=a.hold,m=a.bits,k=a.lencode,g=a.distcode,_=(1<m&&(w+=Z[r++]<>>24,w>>>=x,m-=x,x=p>>>16&255,0===x)A[o++]=65535&p;else{if(!(16&x)){if(0===(64&x)){p=k[(65535&p)+(w&(1<m&&(w+=Z[r++]<>>=x,m-=x),15>m&&(w+=Z[r++]<>>24,w>>>=x,m-=x,x=p>>>16&255,!(16&x)){if(0===(64&x)){p=g[(65535&p)+(w&(1<m&&(w+=Z[r++]<m&&(w+=Z[r++]<d){e.msg="invalid distance too far back",a.mode=i;break e}if(w>>>=x,m-=x,x=o-f,S>x){if(x=S-x,x>h&&a.sane){e.msg="invalid distance too far back",a.mode=i;break e}if(B=0,E=b,0===c){if(B+=u-x,y>x){y-=x;do A[o++]=b[B++];while(--x);B=o-S,E=A}}else if(x>c){if(B+=u+c-x,x-=c,y>x){y-=x;do A[o++]=b[B++];while(--x);if(B=0,y>c){x=c,y-=x;do A[o++]=b[B++];while(--x);B=o-S,E=A}}}else if(B+=c-x,y>x){y-=x;do A[o++]=b[B++];while(--x);B=o-S,E=A}for(;y>2;)A[o++]=E[B++],A[o++]=E[B++],A[o++]=E[B++],y-=3;y&&(A[o++]=E[B++],y>1&&(A[o++]=E[B++]))}else{B=o-S;do A[o++]=A[B++],A[o++]=A[B++],A[o++]=A[B++],y-=3;while(y>2);y&&(A[o++]=A[B++],y>1&&(A[o++]=A[B++]))}break}}break}}while(s>r&&l>o);y=m>>3,r-=y,m-=y<<3,w&=(1<r?5+(s-r):5-(r-s),e.avail_out=l>o?257+(l-o):257-(o-l),a.hold=w,a.bits=m}},{}],9:[function(e,t,i){"use strict";function n(e){return(e>>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function a(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new k.Buf16(320),this.work=new k.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function r(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=F,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new k.Buf32(bt),t.distcode=t.distdyn=new k.Buf32(wt),t.sane=1,t.back=-1,A):C}function s(e){var t;return e&&e.state?(t=e.state,t.wsize=0,t.whave=0,t.wnext=0,r(e)):C}function o(e,t){var i,n;return e&&e.state?(n=e.state,0>t?(i=0,t=-t):(i=(t>>4)+1,48>t&&(t&=15)),t&&(8>t||t>15)?C:(null!==n.window&&n.wbits!==t&&(n.window=null),n.wrap=i,n.wbits=t,s(e))):C}function f(e,t){var i,n;return e?(n=new a,e.state=n,n.window=null,i=o(e,t),i!==A&&(e.state=null),i):C}function l(e){return f(e,kt)}function d(e){if(gt){var t;for(w=new k.Buf32(512),m=new k.Buf32(32),t=0;144>t;)e.lens[t++]=8;for(;256>t;)e.lens[t++]=9;for(;280>t;)e.lens[t++]=7;for(;288>t;)e.lens[t++]=8;for(p(y,e.lens,0,288,w,0,e.work,{bits:9}),t=0;32>t;)e.lens[t++]=5;p(S,e.lens,0,32,m,0,e.work,{bits:5}),gt=!1}e.lencode=w,e.lenbits=9,e.distcode=m,e.distbits=5}function u(e,t,i,n){var a,r=e.state;return null===r.window&&(r.wsize=1<=r.wsize?(k.arraySet(r.window,t,i-r.wsize,r.wsize,0),r.wnext=0,r.whave=r.wsize):(a=r.wsize-r.wnext,a>n&&(a=n),k.arraySet(r.window,t,i-n,a,r.wnext),n-=a,n?(k.arraySet(r.window,t,i-n,n,0),r.wnext=n,r.whave=r.wsize):(r.wnext+=a,r.wnext===r.wsize&&(r.wnext=0),r.whavec;){if(0===f)break e;f--,h+=a[s++]<>>8&255,i.check=_(i.check,Zt,2,0),h=0,c=0,i.mode=D;break}if(i.flags=0,i.head&&(i.head.done=!1),!(1&i.wrap)||(((255&h)<<8)+(h>>8))%31){e.msg="incorrect header check",i.mode=ut;break}if((15&h)!==T){e.msg="unknown compression method",i.mode=ut;break}if(h>>>=4,c-=4,xt=(15&h)+8,0===i.wbits)i.wbits=xt;else if(xt>i.wbits){e.msg="invalid window size",i.mode=ut;break}i.dmax=1<c;){if(0===f)break e;f--,h+=a[s++]<>8&1),512&i.flags&&(Zt[0]=255&h,Zt[1]=h>>>8&255,i.check=_(i.check,Zt,2,0)),h=0,c=0,i.mode=U;case U:for(;32>c;){if(0===f)break e;f--,h+=a[s++]<>>8&255,Zt[2]=h>>>16&255,Zt[3]=h>>>24&255,i.check=_(i.check,Zt,4,0)),h=0,c=0,i.mode=L;case L:for(;16>c;){if(0===f)break e;f--,h+=a[s++]<>8),512&i.flags&&(Zt[0]=255&h,Zt[1]=h>>>8&255,i.check=_(i.check,Zt,2,0)),h=0,c=0,i.mode=H;case H:if(1024&i.flags){for(;16>c;){if(0===f)break e;f--,h+=a[s++]<>>8&255,i.check=_(i.check,Zt,2,0)),h=0,c=0}else i.head&&(i.head.extra=null);i.mode=M;case M:if(1024&i.flags&&(m=i.length,m>f&&(m=f),m&&(i.head&&(xt=i.head.extra_len-i.length,i.head.extra||(i.head.extra=new Array(i.head.extra_len)),k.arraySet(i.head.extra,a,s,m,xt)),512&i.flags&&(i.check=_(i.check,a,m,s)),f-=m,s+=m,i.length-=m),i.length))break e;i.length=0,i.mode=K;case K:if(2048&i.flags){if(0===f)break e;m=0;do xt=a[s+m++],i.head&&xt&&i.length<65536&&(i.head.name+=String.fromCharCode(xt));while(xt&&f>m);if(512&i.flags&&(i.check=_(i.check,a,m,s)),f-=m,s+=m,xt)break e}else i.head&&(i.head.name=null);i.length=0,i.mode=j;case j:if(4096&i.flags){if(0===f)break e;m=0;do xt=a[s+m++],i.head&&xt&&i.length<65536&&(i.head.comment+=String.fromCharCode(xt));while(xt&&f>m);if(512&i.flags&&(i.check=_(i.check,a,m,s)),f-=m,s+=m,xt)break e}else i.head&&(i.head.comment=null);i.mode=P;case P:if(512&i.flags){for(;16>c;){if(0===f)break e;f--,h+=a[s++]<>9&1,i.head.done=!0),e.adler=i.check=0,i.mode=G;break;case q:for(;32>c;){if(0===f)break e;f--,h+=a[s++]<>>=7&c,c-=7&c,i.mode=ft;break}for(;3>c;){if(0===f)break e;f--,h+=a[s++]<>>=1,c-=1,3&h){case 0:i.mode=W;break;case 1:if(d(i),i.mode=tt,t===Z){h>>>=2,c-=2;break e}break;case 2:i.mode=V;break;case 3:e.msg="invalid block type",i.mode=ut}h>>>=2,c-=2;break;case W:for(h>>>=7&c,c-=7&c;32>c;){if(0===f)break e;f--,h+=a[s++]<>>16^65535)){e.msg="invalid stored block lengths",i.mode=ut;break}if(i.length=65535&h,h=0,c=0,i.mode=J,t===Z)break e;case J:i.mode=Q;case Q:if(m=i.length){if(m>f&&(m=f),m>l&&(m=l),0===m)break e;k.arraySet(r,a,s,m,o),f-=m,s+=m,l-=m,o+=m,i.length-=m;break}i.mode=G;break;case V:for(;14>c;){if(0===f)break e;f--,h+=a[s++]<>>=5,c-=5,i.ndist=(31&h)+1,h>>>=5,c-=5,i.ncode=(15&h)+4,h>>>=4,c-=4,i.nlen>286||i.ndist>30){e.msg="too many length or distance symbols",i.mode=ut;break}i.have=0,i.mode=$;case $:for(;i.havec;){if(0===f)break e;f--,h+=a[s++]<>>=3,c-=3}for(;i.have<19;)i.lens[At[i.have++]]=0;if(i.lencode=i.lendyn,i.lenbits=7,St={bits:i.lenbits},yt=p(x,i.lens,0,19,i.lencode,0,i.work,St),i.lenbits=St.bits,yt){e.msg="invalid code lengths set",i.mode=ut;break}i.have=0,i.mode=et;case et:for(;i.have>>24,kt=Et>>>16&255,gt=65535&Et,!(c>=mt);){if(0===f)break e;f--,h+=a[s++]<gt)h>>>=mt,c-=mt,i.lens[i.have++]=gt;else{if(16===gt){for(Bt=mt+2;Bt>c;){if(0===f)break e;f--,h+=a[s++]<>>=mt,c-=mt,0===i.have){e.msg="invalid bit length repeat",i.mode=ut;break}xt=i.lens[i.have-1],m=3+(3&h),h>>>=2,c-=2}else if(17===gt){for(Bt=mt+3;Bt>c;){if(0===f)break e;f--,h+=a[s++]<>>=mt,c-=mt,xt=0,m=3+(7&h),h>>>=3,c-=3}else{for(Bt=mt+7;Bt>c;){if(0===f)break e;f--,h+=a[s++]<>>=mt,c-=mt,xt=0,m=11+(127&h),h>>>=7,c-=7}if(i.have+m>i.nlen+i.ndist){e.msg="invalid bit length repeat",i.mode=ut;break}for(;m--;)i.lens[i.have++]=xt}}if(i.mode===ut)break;if(0===i.lens[256]){e.msg="invalid code -- missing end-of-block",i.mode=ut;break}if(i.lenbits=9,St={bits:i.lenbits},yt=p(y,i.lens,0,i.nlen,i.lencode,0,i.work,St),i.lenbits=St.bits,yt){e.msg="invalid literal/lengths set",i.mode=ut;break}if(i.distbits=6,i.distcode=i.distdyn,St={bits:i.distbits},yt=p(S,i.lens,i.nlen,i.ndist,i.distcode,0,i.work,St),i.distbits=St.bits,yt){e.msg="invalid distances set",i.mode=ut;break}if(i.mode=tt,t===Z)break e;case tt:i.mode=it;case it:if(f>=6&&l>=258){e.next_out=o,e.avail_out=l,e.next_in=s,e.avail_in=f,i.hold=h,i.bits=c,v(e,w),o=e.next_out,r=e.output,l=e.avail_out,s=e.next_in,a=e.input,f=e.avail_in,h=i.hold,c=i.bits,i.mode===G&&(i.back=-1);break}for(i.back=0;Et=i.lencode[h&(1<>>24,kt=Et>>>16&255,gt=65535&Et,!(c>=mt);){if(0===f)break e;f--,h+=a[s++]<>_t)],mt=Et>>>24,kt=Et>>>16&255,gt=65535&Et,!(c>=_t+mt);){if(0===f)break e;f--,h+=a[s++]<>>=_t,c-=_t,i.back+=_t}if(h>>>=mt,c-=mt,i.back+=mt,i.length=gt,0===kt){i.mode=ot;break}if(32&kt){i.back=-1,i.mode=G;break}if(64&kt){e.msg="invalid literal/length code",i.mode=ut;break}i.extra=15&kt,i.mode=nt;case nt:if(i.extra){for(Bt=i.extra;Bt>c;){if(0===f)break e;f--,h+=a[s++]<>>=i.extra,c-=i.extra,i.back+=i.extra}i.was=i.length,i.mode=at;case at:for(;Et=i.distcode[h&(1<>>24,kt=Et>>>16&255,gt=65535&Et,!(c>=mt);){if(0===f)break e;f--,h+=a[s++]<>_t)],mt=Et>>>24,kt=Et>>>16&255,gt=65535&Et,!(c>=_t+mt);){if(0===f)break e;f--,h+=a[s++]<>>=_t,c-=_t,i.back+=_t}if(h>>>=mt,c-=mt,i.back+=mt,64&kt){e.msg="invalid distance code",i.mode=ut;break}i.offset=gt,i.extra=15&kt,i.mode=rt;case rt:if(i.extra){for(Bt=i.extra;Bt>c;){if(0===f)break e;f--,h+=a[s++]<>>=i.extra,c-=i.extra,i.back+=i.extra}if(i.offset>i.dmax){e.msg="invalid distance too far back",i.mode=ut;break}i.mode=st;case st:if(0===l)break e;if(m=w-l,i.offset>m){if(m=i.offset-m,m>i.whave&&i.sane){e.msg="invalid distance too far back",i.mode=ut;break}m>i.wnext?(m-=i.wnext,bt=i.wsize-m):bt=i.wnext-m,m>i.length&&(m=i.length),wt=i.window}else wt=r,bt=o-i.offset,m=i.length;m>l&&(m=l),l-=m,i.length-=m;do r[o++]=wt[bt++];while(--m);0===i.length&&(i.mode=it);break;case ot:if(0===l)break e;r[o++]=i.length,l--,i.mode=it;break;case ft:if(i.wrap){for(;32>c;){if(0===f)break e;f--,h|=a[s++]<c;){if(0===f)break e;f--,h+=a[s++]<=z;z++)M[z]=0;for(R=0;b>R;R++)M[t[c+R]]++;for(I=A,N=n;N>=1&&0===M[N];N--);if(I>N&&(I=N),0===N)return w[m++]=20971520,w[m++]=20971520,g.bits=1,0;for(C=1;N>C&&0===M[C];C++);for(C>I&&(I=C),F=1,z=1;n>=z;z++)if(F<<=1,F-=M[z],0>F)return-1;if(F>0&&(e===s||1!==N))return-1;for(K[1]=0,z=1;n>z;z++)K[z+1]=K[z]+M[z];for(R=0;b>R;R++)0!==t[c+R]&&(k[K[t[c+R]]++]=R);switch(e){case s:L=j=k,S=19;break;case o:L=l,H-=257,j=d,P-=257,S=256;break;default:L=u,j=h,S=-1}if(U=0,R=0,z=C,y=m,O=I,T=0,p=-1,D=1<a||e===f&&D>r)return 1;for(var q=0;;){q++,B=z-T,k[R]S?(E=j[P+k[R]],Z=L[H+k[R]]):(E=96,Z=0),_=1<>T)+v]=B<<24|E<<16|Z|0;while(0!==v);for(_=1<>=1;if(0!==_?(U&=_-1,U+=_):U=0,R++,0===--M[z]){if(z===N)break;z=t[c+k[R]]}if(z>I&&(U&x)!==p){for(0===T&&(T=I),y+=C,O=z-T,F=1<O+T&&(F-=M[O+T],!(0>=F));)O++,F<<=1;if(D+=1<a||e===f&&D>r)return 1;p=U&x,w[p]=I<<24|O<<16|y-m|0}}return 0!==U&&(w[y+U]=z-T<<24|64<<16|0),g.bits=I,0}},{"../utils/common":2}],11:[function(e,t){"use strict";t.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],12:[function(e,t){"use strict";function i(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}t.exports=i},{}]},{},[1])(1)}); +// astroem.js: astronomy utilities compiled to js + +var Astroem = (function() { + + +var Module = { + 'noExitRuntime': true +}; + + +// The Module object: Our interface to the outside world. We import +// and export values on it, and do the work to get that through +// closure compiler if necessary. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to do an eval in order to handle the closure compiler +// case, where this code here is minified but Module was defined +// elsewhere (e.g. case 4 above). We also need to check if Module +// already exists (e.g. case 3 above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module; +if (!Module) Module = (typeof Module !== 'undefined' ? Module : null) || {}; + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. +var moduleOverrides = {}; +for (var key in Module) { + if (Module.hasOwnProperty(key)) { + moduleOverrides[key] = Module[key]; + } +} + +// The environment setup code below is customized to use Module. +// *** Environment setup code *** +var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function'; +var ENVIRONMENT_IS_WEB = typeof window === 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + +if (ENVIRONMENT_IS_NODE) { + // Expose functionality in the same simple way that the shells work + // Note that we pollute the global namespace here, otherwise we break in node + if (!Module['print']) Module['print'] = function print(x) { + process['stdout'].write(x + '\n'); + }; + if (!Module['printErr']) Module['printErr'] = function printErr(x) { + process['stderr'].write(x + '\n'); + }; + + var nodeFS = require('fs'); + var nodePath = require('path'); + + Module['read'] = function read(filename, binary) { + filename = nodePath['normalize'](filename); + var ret = nodeFS['readFileSync'](filename); + // The path is absolute if the normalized version is the same as the resolved. + if (!ret && filename != nodePath['resolve'](filename)) { + filename = path.join(__dirname, '..', 'src', filename); + ret = nodeFS['readFileSync'](filename); + } + if (ret && !binary) ret = ret.toString(); + return ret; + }; + + Module['readBinary'] = function readBinary(filename) { return Module['read'](filename, true) }; + + Module['load'] = function load(f) { + globalEval(read(f)); + }; + + Module['arguments'] = process['argv'].slice(2); + + module['exports'] = Module; +} +else if (ENVIRONMENT_IS_SHELL) { + if (!Module['print']) Module['print'] = print; + if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm + + if (typeof read != 'undefined') { + Module['read'] = read; + } else { + Module['read'] = function read() { throw 'no read() available (jsc?)' }; + } + + Module['readBinary'] = function readBinary(f) { + return read(f, 'binary'); + }; + + if (typeof scriptArgs != 'undefined') { + Module['arguments'] = scriptArgs; + } else if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + + this['Module'] = Module; + + eval("if (typeof gc === 'function' && gc.toString().indexOf('[native code]') > 0) var gc = undefined"); // wipe out the SpiderMonkey shell 'gc' function, which can confuse closure (uses it as a minified name, and it is then initted to a non-falsey value unexpectedly) +} +else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + Module['read'] = function read(url) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + }; + + if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + + if (typeof console !== 'undefined') { + if (!Module['print']) Module['print'] = function print(x) { + console.log(x); + }; + if (!Module['printErr']) Module['printErr'] = function printErr(x) { + console.log(x); + }; + } else { + // Probably a worker, and without console.log. We can do very little here... + var TRY_USE_DUMP = false; + if (!Module['print']) Module['print'] = (TRY_USE_DUMP && (typeof(dump) !== "undefined") ? (function(x) { + dump(x); + }) : (function(x) { + // self.postMessage(x); // enable this if you want stdout to be sent as messages + })); + } + + if (ENVIRONMENT_IS_WEB) { + window['Module'] = Module; + } else { + Module['load'] = importScripts; + } +} +else { + // Unreachable because SHELL is dependant on the others + throw 'Unknown runtime environment. Where are we?'; +} + +function globalEval(x) { + eval.call(null, x); +} +if (!Module['load'] == 'undefined' && Module['read']) { + Module['load'] = function load(f) { + globalEval(Module['read'](f)); + }; +} +if (!Module['print']) { + Module['print'] = function(){}; +} +if (!Module['printErr']) { + Module['printErr'] = Module['print']; +} +if (!Module['arguments']) { + Module['arguments'] = []; +} +// *** Environment setup code *** + +// Closure helpers +Module.print = Module['print']; +Module.printErr = Module['printErr']; + +// Callbacks +Module['preRun'] = []; +Module['postRun'] = []; + +// Merge back in the overrides +for (var key in moduleOverrides) { + if (moduleOverrides.hasOwnProperty(key)) { + Module[key] = moduleOverrides[key]; + } +} + + + +// === Auto-generated preamble library stuff === + +//======================================== +// Runtime code shared with compiler +//======================================== + +var Runtime = { + stackSave: function () { + return STACKTOP; + }, + stackRestore: function (stackTop) { + STACKTOP = stackTop; + }, + forceAlign: function (target, quantum) { + quantum = quantum || 4; + if (quantum == 1) return target; + if (isNumber(target) && isNumber(quantum)) { + return Math.ceil(target/quantum)*quantum; + } else if (isNumber(quantum) && isPowerOfTwo(quantum)) { + return '(((' +target + ')+' + (quantum-1) + ')&' + -quantum + ')'; + } + return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum; + }, + isNumberType: function (type) { + return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES; + }, + isPointerType: function isPointerType(type) { + return type[type.length-1] == '*'; +}, + isStructType: function isStructType(type) { + if (isPointerType(type)) return false; + if (isArrayType(type)) return true; + if (/?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types + // See comment in isStructPointerType() + return type[0] == '%'; +}, + INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0}, + FLOAT_TYPES: {"float":0,"double":0}, + or64: function (x, y) { + var l = (x | 0) | (y | 0); + var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + and64: function (x, y) { + var l = (x | 0) & (y | 0); + var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + xor64: function (x, y) { + var l = (x | 0) ^ (y | 0); + var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296; + return l + h; + }, + getNativeTypeSize: function (type) { + switch (type) { + case 'i1': case 'i8': return 1; + case 'i16': return 2; + case 'i32': return 4; + case 'i64': return 8; + case 'float': return 4; + case 'double': return 8; + default: { + if (type[type.length-1] === '*') { + return Runtime.QUANTUM_SIZE; // A pointer + } else if (type[0] === 'i') { + var bits = parseInt(type.substr(1)); + assert(bits % 8 === 0); + return bits/8; + } else { + return 0; + } + } + } + }, + getNativeFieldSize: function (type) { + return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE); + }, + dedup: function dedup(items, ident) { + var seen = {}; + if (ident) { + return items.filter(function(item) { + if (seen[item[ident]]) return false; + seen[item[ident]] = true; + return true; + }); + } else { + return items.filter(function(item) { + if (seen[item]) return false; + seen[item] = true; + return true; + }); + } +}, + set: function set() { + var args = typeof arguments[0] === 'object' ? arguments[0] : arguments; + var ret = {}; + for (var i = 0; i < args.length; i++) { + ret[args[i]] = 0; + } + return ret; +}, + STACK_ALIGN: 8, + getAlignSize: function (type, size, vararg) { + // we align i64s and doubles on 64-bit boundaries, unlike x86 + if (!vararg && (type == 'i64' || type == 'double')) return 8; + if (!type) return Math.min(size, 8); // align structures internally to 64 bits + return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE); + }, + calculateStructAlignment: function calculateStructAlignment(type) { + type.flatSize = 0; + type.alignSize = 0; + var diffs = []; + var prev = -1; + var index = 0; + type.flatIndexes = type.fields.map(function(field) { + index++; + var size, alignSize; + if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) { + size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s. + alignSize = Runtime.getAlignSize(field, size); + } else if (Runtime.isStructType(field)) { + if (field[1] === '0') { + // this is [0 x something]. When inside another structure like here, it must be at the end, + // and it adds no size + // XXX this happens in java-nbody for example... assert(index === type.fields.length, 'zero-length in the middle!'); + size = 0; + if (Types.types[field]) { + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } else { + alignSize = type.alignSize || QUANTUM_SIZE; + } + } else { + size = Types.types[field].flatSize; + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); + } + } else if (field[0] == 'b') { + // bN, large number field, like a [N x i8] + size = field.substr(1)|0; + alignSize = 1; + } else if (field[0] === '<') { + // vector type + size = alignSize = Types.types[field].flatSize; // fully aligned + } else if (field[0] === 'i') { + // illegal integer field, that could not be legalized because it is an internal structure field + // it is ok to have such fields, if we just use them as markers of field size and nothing more complex + size = alignSize = parseInt(field.substr(1))/8; + assert(size % 1 === 0, 'cannot handle non-byte-size field ' + field); + } else { + assert(false, 'invalid type for calculateStructAlignment'); + } + if (type.packed) alignSize = 1; + type.alignSize = Math.max(type.alignSize, alignSize); + var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory + type.flatSize = curr + size; + if (prev >= 0) { + diffs.push(curr-prev); + } + prev = curr; + return curr; + }); + if (type.name_ && type.name_[0] === '[') { + // arrays have 2 elements, so we get the proper difference. then we scale here. that way we avoid + // allocating a potentially huge array for [999999 x i8] etc. + type.flatSize = parseInt(type.name_.substr(1))*type.flatSize/2; + } + type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize); + if (diffs.length == 0) { + type.flatFactor = type.flatSize; + } else if (Runtime.dedup(diffs).length == 1) { + type.flatFactor = diffs[0]; + } + type.needsFlattening = (type.flatFactor != 1); + return type.flatIndexes; + }, + generateStructInfo: function (struct, typeName, offset) { + var type, alignment; + if (typeName) { + offset = offset || 0; + type = (typeof Types === 'undefined' ? Runtime.typeInfo : Types.types)[typeName]; + if (!type) return null; + if (type.fields.length != struct.length) { + printErr('Number of named fields must match the type for ' + typeName + ': possibly duplicate struct names. Cannot return structInfo'); + return null; + } + alignment = type.flatIndexes; + } else { + var type = { fields: struct.map(function(item) { return item[0] }) }; + alignment = Runtime.calculateStructAlignment(type); + } + var ret = { + __size__: type.flatSize + }; + if (typeName) { + struct.forEach(function(item, i) { + if (typeof item === 'string') { + ret[item] = alignment[i] + offset; + } else { + // embedded struct + var key; + for (var k in item) key = k; + ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]); + } + }); + } else { + struct.forEach(function(item, i) { + ret[item[1]] = alignment[i]; + }); + } + return ret; + }, + dynCall: function (sig, ptr, args) { + if (args && args.length) { + if (!args.splice) args = Array.prototype.slice.call(args); + args.splice(0, 0, ptr); + return Module['dynCall_' + sig].apply(null, args); + } else { + return Module['dynCall_' + sig].call(null, ptr); + } + }, + functionPointers: [], + addFunction: function (func) { + for (var i = 0; i < Runtime.functionPointers.length; i++) { + if (!Runtime.functionPointers[i]) { + Runtime.functionPointers[i] = func; + return 2*(1 + i); + } + } + throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; + }, + removeFunction: function (index) { + Runtime.functionPointers[(index-2)/2] = null; + }, + getAsmConst: function (code, numArgs) { + // code is a constant string on the heap, so we can cache these + if (!Runtime.asmConstCache) Runtime.asmConstCache = {}; + var func = Runtime.asmConstCache[code]; + if (func) return func; + var args = []; + for (var i = 0; i < numArgs; i++) { + args.push(String.fromCharCode(36) + i); // $0, $1 etc + } + var source = Pointer_stringify(code); + if (source[0] === '"') { + // tolerate EM_ASM("..code..") even though EM_ASM(..code..) is correct + if (source.indexOf('"', 1) === source.length-1) { + source = source.substr(1, source.length-2); + } else { + // something invalid happened, e.g. EM_ASM("..code($0)..", input) + abort('invalid EM_ASM input |' + source + '|. Please use EM_ASM(..code..) (no quotes) or EM_ASM({ ..code($0).. }, input) (to input values)'); + } + } + try { + var evalled = eval('(function(' + args.join(',') + '){ ' + source + ' })'); // new Function does not allow upvars in node + } catch(e) { + Module.printErr('error in executing inline EM_ASM code: ' + e + ' on: \n\n' + source + '\n\nwith args |' + args + '| (make sure to use the right one out of EM_ASM, EM_ASM_ARGS, etc.)'); + throw e; + } + return Runtime.asmConstCache[code] = evalled; + }, + warnOnce: function (text) { + if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; + if (!Runtime.warnOnce.shown[text]) { + Runtime.warnOnce.shown[text] = 1; + Module.printErr(text); + } + }, + funcWrappers: {}, + getFuncWrapper: function (func, sig) { + assert(sig); + if (!Runtime.funcWrappers[func]) { + Runtime.funcWrappers[func] = function dynCall_wrapper() { + return Runtime.dynCall(sig, func, arguments); + }; + } + return Runtime.funcWrappers[func]; + }, + UTF8Processor: function () { + var buffer = []; + var needed = 0; + this.processCChar = function (code) { + code = code & 0xFF; + + if (buffer.length == 0) { + if ((code & 0x80) == 0x00) { // 0xxxxxxx + return String.fromCharCode(code); + } + buffer.push(code); + if ((code & 0xE0) == 0xC0) { // 110xxxxx + needed = 1; + } else if ((code & 0xF0) == 0xE0) { // 1110xxxx + needed = 2; + } else { // 11110xxx + needed = 3; + } + return ''; + } + + if (needed) { + buffer.push(code); + needed--; + if (needed > 0) return ''; + } + + var c1 = buffer[0]; + var c2 = buffer[1]; + var c3 = buffer[2]; + var c4 = buffer[3]; + var ret; + if (buffer.length == 2) { + ret = String.fromCharCode(((c1 & 0x1F) << 6) | (c2 & 0x3F)); + } else if (buffer.length == 3) { + ret = String.fromCharCode(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); + } else { + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + var codePoint = ((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) | + ((c3 & 0x3F) << 6) | (c4 & 0x3F); + ret = String.fromCharCode( + Math.floor((codePoint - 0x10000) / 0x400) + 0xD800, + (codePoint - 0x10000) % 0x400 + 0xDC00); + } + buffer.length = 0; + return ret; + } + this.processJSString = function processJSString(string) { + /* TODO: use TextEncoder when present, + var encoder = new TextEncoder(); + encoder['encoding'] = "utf-8"; + var utf8Array = encoder['encode'](aMsg.data); + */ + string = unescape(encodeURIComponent(string)); + var ret = []; + for (var i = 0; i < string.length; i++) { + ret.push(string.charCodeAt(i)); + } + return ret; + } + }, + getCompilerSetting: function (name) { + throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work'; + }, + stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = (((STACKTOP)+7)&-8); return ret; }, + staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = (((STATICTOP)+7)&-8); return ret; }, + dynamicAlloc: function (size) { var ret = DYNAMICTOP;DYNAMICTOP = (DYNAMICTOP + size)|0;DYNAMICTOP = (((DYNAMICTOP)+7)&-8); if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();; return ret; }, + alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 8))*(quantum ? quantum : 8); return ret; }, + makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+((low>>>0)))+((+((high>>>0)))*(+4294967296))) : ((+((low>>>0)))+((+((high|0)))*(+4294967296)))); return ret; }, + GLOBAL_BASE: 8, + QUANTUM_SIZE: 4, + __dummy__: 0 +} + + +Module['Runtime'] = Runtime; + + + + + + + + + +//======================================== +// Runtime essentials +//======================================== + +var __THREW__ = 0; // Used in checking for thrown exceptions. + +var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort() +var EXITSTATUS = 0; + +var undef = 0; +// tempInt is used for 32-bit signed values or smaller. tempBigInt is used +// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt +var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD, tempDouble, tempFloat; +var tempI64, tempI64b; +var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9; + +function assert(condition, text) { + if (!condition) { + abort('Assertion failed: ' + text); + } +} + +var globalScope = this; + +// C calling interface. A convenient way to call C functions (in C files, or +// defined with extern "C"). +// +// Note: LLVM optimizations can inline and remove functions, after which you will not be +// able to call them. Closure can also do so. To avoid that, add your function to +// the exports using something like +// +// -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]' +// +// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C") +// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and +// 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit). +// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType, +// except that 'array' is not possible (there is no way for us to know the length of the array) +// @param args An array of the arguments to the function, as native JS values (as in returnType) +// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack). +// @return The return value, as a native JS value (as in returnType) +function ccall(ident, returnType, argTypes, args) { + return ccallFunc(getCFunc(ident), returnType, argTypes, args); +} +Module["ccall"] = ccall; + +// Returns the C function with a specified identifier (for C++, you need to do manual name mangling) +function getCFunc(ident) { + try { + var func = Module['_' + ident]; // closure exported function + if (!func) func = eval('_' + ident); // explicit lookup + } catch(e) { + } + assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)'); + return func; +} + +// Internal function that does a C call using a function, not an identifier +function ccallFunc(func, returnType, argTypes, args) { + var stack = 0; + function toC(value, type) { + if (type == 'string') { + if (value === null || value === undefined || value === 0) return 0; // null string + value = intArrayFromString(value); + type = 'array'; + } + if (type == 'array') { + if (!stack) stack = Runtime.stackSave(); + var ret = Runtime.stackAlloc(value.length); + writeArrayToMemory(value, ret); + return ret; + } + return value; + } + function fromC(value, type) { + if (type == 'string') { + return Pointer_stringify(value); + } + assert(type != 'array'); + return value; + } + var i = 0; + var cArgs = args ? args.map(function(arg) { + return toC(arg, argTypes[i++]); + }) : []; + var ret = fromC(func.apply(null, cArgs), returnType); + if (stack) Runtime.stackRestore(stack); + return ret; +} + +// Returns a native JS wrapper for a C function. This is similar to ccall, but +// returns a function you can call repeatedly in a normal way. For example: +// +// var my_function = cwrap('my_c_function', 'number', ['number', 'number']); +// alert(my_function(5, 22)); +// alert(my_function(99, 12)); +// +function cwrap(ident, returnType, argTypes) { + var func = getCFunc(ident); + return function() { + return ccallFunc(func, returnType, argTypes, Array.prototype.slice.call(arguments)); + } +} +Module["cwrap"] = cwrap; + +// Sets a value in memory in a dynamic way at run-time. Uses the +// type data. This is the same as makeSetValue, except that +// makeSetValue is done at compile-time and generates the needed +// code then, whereas this function picks the right code at +// run-time. +// Note that setValue and getValue only do *aligned* writes and reads! +// Note that ccall uses JS types as for defining types, while setValue and +// getValue need LLVM types ('i8', 'i32') - this is a lower-level operation +function setValue(ptr, value, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': HEAP8[(ptr)]=value; break; + case 'i8': HEAP8[(ptr)]=value; break; + case 'i16': HEAP16[((ptr)>>1)]=value; break; + case 'i32': HEAP32[((ptr)>>2)]=value; break; + case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= (+1) ? (tempDouble > (+0) ? ((Math_min((+(Math_floor((tempDouble)/(+4294967296)))), (+4294967295)))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/(+4294967296))))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break; + case 'float': HEAPF32[((ptr)>>2)]=value; break; + case 'double': HEAPF64[((ptr)>>3)]=value; break; + default: abort('invalid type for setValue: ' + type); + } +} +Module['setValue'] = setValue; + +// Parallel to setValue. +function getValue(ptr, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + switch(type) { + case 'i1': return HEAP8[(ptr)]; + case 'i8': return HEAP8[(ptr)]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': return HEAP32[((ptr)>>2)]; + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + default: abort('invalid type for setValue: ' + type); + } + return null; +} +Module['getValue'] = getValue; + +var ALLOC_NORMAL = 0; // Tries to use _malloc() +var ALLOC_STACK = 1; // Lives for the duration of the current function call +var ALLOC_STATIC = 2; // Cannot be freed +var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk +var ALLOC_NONE = 4; // Do not allocate +Module['ALLOC_NORMAL'] = ALLOC_NORMAL; +Module['ALLOC_STACK'] = ALLOC_STACK; +Module['ALLOC_STATIC'] = ALLOC_STATIC; +Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC; +Module['ALLOC_NONE'] = ALLOC_NONE; + +// allocate(): This is for internal use. You can use it yourself as well, but the interface +// is a little tricky (see docs right below). The reason is that it is optimized +// for multiple syntaxes to save space in generated code. So you should +// normally not use allocate(), and instead allocate memory using _malloc(), +// initialize it with setValue(), and so forth. +// @slab: An array of data, or a number. If a number, then the size of the block to allocate, +// in *bytes* (note that this is sometimes confusing: the next parameter does not +// affect this!) +// @types: Either an array of types, one for each byte (or 0 if no type at that position), +// or a single type which is used for the entire block. This only matters if there +// is initial data - if @slab is a number, then this does not matter at all and is +// ignored. +// @allocator: How to allocate memory, see ALLOC_* +function allocate(slab, types, allocator, ptr) { + var zeroinit, size; + if (typeof slab === 'number') { + zeroinit = true; + size = slab; + } else { + zeroinit = false; + size = slab.length; + } + + var singleType = typeof types === 'string' ? types : null; + + var ret; + if (allocator == ALLOC_NONE) { + ret = ptr; + } else { + ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); + } + + if (zeroinit) { + var ptr = ret, stop; + assert((ret & 3) == 0); + stop = ret + (size & ~3); + for (; ptr < stop; ptr += 4) { + HEAP32[((ptr)>>2)]=0; + } + stop = ret + size; + while (ptr < stop) { + HEAP8[((ptr++)|0)]=0; + } + return ret; + } + + if (singleType === 'i8') { + if (slab.subarray || slab.slice) { + HEAPU8.set(slab, ret); + } else { + HEAPU8.set(new Uint8Array(slab), ret); + } + return ret; + } + + var i = 0, type, typeSize, previousType; + while (i < size) { + var curr = slab[i]; + + if (typeof curr === 'function') { + curr = Runtime.getFunctionIndex(curr); + } + + type = singleType || types[i]; + if (type === 0) { + i++; + continue; + } + + if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later + + setValue(ret+i, curr, type); + + // no need to look up size unless type changes, so cache it + if (previousType !== type) { + typeSize = Runtime.getNativeTypeSize(type); + previousType = type; + } + i += typeSize; + } + + return ret; +} +Module['allocate'] = allocate; + +function Pointer_stringify(ptr, /* optional */ length) { + // TODO: use TextDecoder + // Find the length, and check for UTF while doing so + var hasUtf = false; + var t; + var i = 0; + while (1) { + t = HEAPU8[(((ptr)+(i))|0)]; + if (t >= 128) hasUtf = true; + else if (t == 0 && !length) break; + i++; + if (length && i == length) break; + } + if (!length) length = i; + + var ret = ''; + + if (!hasUtf) { + var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack + var curr; + while (length > 0) { + curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); + ret = ret ? ret + curr : curr; + ptr += MAX_CHUNK; + length -= MAX_CHUNK; + } + return ret; + } + + var utf8 = new Runtime.UTF8Processor(); + for (i = 0; i < length; i++) { + t = HEAPU8[(((ptr)+(i))|0)]; + ret += utf8.processCChar(t); + } + return ret; +} +Module['Pointer_stringify'] = Pointer_stringify; + +// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns +// a copy of that string as a Javascript String object. +function UTF16ToString(ptr) { + var i = 0; + + var str = ''; + while (1) { + var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; + if (codeUnit == 0) + return str; + ++i; + // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through. + str += String.fromCharCode(codeUnit); + } +} +Module['UTF16ToString'] = UTF16ToString; + +// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', +// null-terminated and encoded in UTF16LE form. The copy will require at most (str.length*2+1)*2 bytes of space in the HEAP. +function stringToUTF16(str, outPtr) { + for(var i = 0; i < str.length; ++i) { + // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. + var codeUnit = str.charCodeAt(i); // possibly a lead surrogate + HEAP16[(((outPtr)+(i*2))>>1)]=codeUnit; + } + // Null-terminate the pointer to the HEAP. + HEAP16[(((outPtr)+(str.length*2))>>1)]=0; +} +Module['stringToUTF16'] = stringToUTF16; + +// Given a pointer 'ptr' to a null-terminated UTF32LE-encoded string in the emscripten HEAP, returns +// a copy of that string as a Javascript String object. +function UTF32ToString(ptr) { + var i = 0; + + var str = ''; + while (1) { + var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; + if (utf32 == 0) + return str; + ++i; + // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. + if (utf32 >= 0x10000) { + var ch = utf32 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } else { + str += String.fromCharCode(utf32); + } + } +} +Module['UTF32ToString'] = UTF32ToString; + +// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', +// null-terminated and encoded in UTF32LE form. The copy will require at most (str.length+1)*4 bytes of space in the HEAP, +// but can use less, since str.length does not return the number of characters in the string, but the number of UTF-16 code units in the string. +function stringToUTF32(str, outPtr) { + var iChar = 0; + for(var iCodeUnit = 0; iCodeUnit < str.length; ++iCodeUnit) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. + var codeUnit = str.charCodeAt(iCodeUnit); // possibly a lead surrogate + if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { + var trailSurrogate = str.charCodeAt(++iCodeUnit); + codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); + } + HEAP32[(((outPtr)+(iChar*4))>>2)]=codeUnit; + ++iChar; + } + // Null-terminate the pointer to the HEAP. + HEAP32[(((outPtr)+(iChar*4))>>2)]=0; +} +Module['stringToUTF32'] = stringToUTF32; + +function demangle(func) { + var i = 3; + // params, etc. + var basicTypes = { + 'v': 'void', + 'b': 'bool', + 'c': 'char', + 's': 'short', + 'i': 'int', + 'l': 'long', + 'f': 'float', + 'd': 'double', + 'w': 'wchar_t', + 'a': 'signed char', + 'h': 'unsigned char', + 't': 'unsigned short', + 'j': 'unsigned int', + 'm': 'unsigned long', + 'x': 'long long', + 'y': 'unsigned long long', + 'z': '...' + }; + var subs = []; + var first = true; + function dump(x) { + //return; + if (x) Module.print(x); + Module.print(func); + var pre = ''; + for (var a = 0; a < i; a++) pre += ' '; + Module.print (pre + '^'); + } + function parseNested() { + i++; + if (func[i] === 'K') i++; // ignore const + var parts = []; + while (func[i] !== 'E') { + if (func[i] === 'S') { // substitution + i++; + var next = func.indexOf('_', i); + var num = func.substring(i, next) || 0; + parts.push(subs[num] || '?'); + i = next+1; + continue; + } + if (func[i] === 'C') { // constructor + parts.push(parts[parts.length-1]); + i += 2; + continue; + } + var size = parseInt(func.substr(i)); + var pre = size.toString().length; + if (!size || !pre) { i--; break; } // counter i++ below us + var curr = func.substr(i + pre, size); + parts.push(curr); + subs.push(curr); + i += pre + size; + } + i++; // skip E + return parts; + } + function parse(rawList, limit, allowVoid) { // main parser + limit = limit || Infinity; + var ret = '', list = []; + function flushList() { + return '(' + list.join(', ') + ')'; + } + var name; + if (func[i] === 'N') { + // namespaced N-E + name = parseNested().join('::'); + limit--; + if (limit === 0) return rawList ? [name] : name; + } else { + // not namespaced + if (func[i] === 'K' || (first && func[i] === 'L')) i++; // ignore const and first 'L' + var size = parseInt(func.substr(i)); + if (size) { + var pre = size.toString().length; + name = func.substr(i + pre, size); + i += pre + size; + } + } + first = false; + if (func[i] === 'I') { + i++; + var iList = parse(true); + var iRet = parse(true, 1, true); + ret += iRet[0] + ' ' + name + '<' + iList.join(', ') + '>'; + } else { + ret = name; + } + paramLoop: while (i < func.length && limit-- > 0) { + //dump('paramLoop'); + var c = func[i++]; + if (c in basicTypes) { + list.push(basicTypes[c]); + } else { + switch (c) { + case 'P': list.push(parse(true, 1, true)[0] + '*'); break; // pointer + case 'R': list.push(parse(true, 1, true)[0] + '&'); break; // reference + case 'L': { // literal + i++; // skip basic type + var end = func.indexOf('E', i); + var size = end - i; + list.push(func.substr(i, size)); + i += size + 2; // size + 'EE' + break; + } + case 'A': { // array + var size = parseInt(func.substr(i)); + i += size.toString().length; + if (func[i] !== '_') throw '?'; + i++; // skip _ + list.push(parse(true, 1, true)[0] + ' [' + size + ']'); + break; + } + case 'E': break paramLoop; + default: ret += '?' + c; break paramLoop; + } + } + } + if (!allowVoid && list.length === 1 && list[0] === 'void') list = []; // avoid (void) + if (rawList) { + if (ret) { + list.push(ret + '?'); + } + return list; + } else { + return ret + flushList(); + } + } + try { + // Special-case the entry point, since its name differs from other name mangling. + if (func == 'Object._main' || func == '_main') { + return 'main()'; + } + if (typeof func === 'number') func = Pointer_stringify(func); + if (func[0] !== '_') return func; + if (func[1] !== '_') return func; // C function + if (func[2] !== 'Z') return func; + switch (func[3]) { + case 'n': return 'operator new()'; + case 'd': return 'operator delete()'; + } + return parse(); + } catch(e) { + return func; + } +} + +function demangleAll(text) { + return text.replace(/__Z[\w\d_]+/g, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']') }); +} + +function stackTrace() { + var stack = new Error().stack; + return stack ? demangleAll(stack) : '(no stack trace available)'; // Stack trace is not available at least on IE10 and Safari 6. +} + +// Memory management + +var PAGE_SIZE = 4096; +function alignMemoryPage(x) { + return (x+4095)&-4096; +} + +var HEAP; +var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; + +var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area +var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area +var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk + +function enlargeMemory() { + abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.'); +} + +var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; +var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 67108864; +var FAST_MEMORY = Module['FAST_MEMORY'] || 2097152; + +var totalMemory = 4096; +while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) { + if (totalMemory < 16*1024*1024) { + totalMemory *= 2; + } else { + totalMemory += 16*1024*1024 + } +} +if (totalMemory !== TOTAL_MEMORY) { + Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be more reasonable'); + TOTAL_MEMORY = totalMemory; +} + +// Initialize the runtime's memory +// check for full engine support (use string 'subarray' to avoid closure compiler confusion) +assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']), + 'JS engine does not provide full typed array support'); + +var buffer = new ArrayBuffer(TOTAL_MEMORY); +HEAP8 = new Int8Array(buffer); +HEAP16 = new Int16Array(buffer); +HEAP32 = new Int32Array(buffer); +HEAPU8 = new Uint8Array(buffer); +HEAPU16 = new Uint16Array(buffer); +HEAPU32 = new Uint32Array(buffer); +HEAPF32 = new Float32Array(buffer); +HEAPF64 = new Float64Array(buffer); + +// Endianness check (note: assumes compiler arch was little-endian) +HEAP32[0] = 255; +assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system'); + +Module['HEAP'] = HEAP; +Module['HEAP8'] = HEAP8; +Module['HEAP16'] = HEAP16; +Module['HEAP32'] = HEAP32; +Module['HEAPU8'] = HEAPU8; +Module['HEAPU16'] = HEAPU16; +Module['HEAPU32'] = HEAPU32; +Module['HEAPF32'] = HEAPF32; +Module['HEAPF64'] = HEAPF64; + +function callRuntimeCallbacks(callbacks) { + while(callbacks.length > 0) { + var callback = callbacks.shift(); + if (typeof callback == 'function') { + callback(); + continue; + } + var func = callback.func; + if (typeof func === 'number') { + if (callback.arg === undefined) { + Runtime.dynCall('v', func); + } else { + Runtime.dynCall('vi', func, [callback.arg]); + } + } else { + func(callback.arg === undefined ? null : callback.arg); + } + } +} + +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATMAIN__ = []; // functions called when main() is to be run +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the runtime has exited + +var runtimeInitialized = false; + +function preRun() { + // compatibility - merge in anything from Module['preRun'] at this time + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + callRuntimeCallbacks(__ATPRERUN__); +} + +function ensureInitRuntime() { + if (runtimeInitialized) return; + runtimeInitialized = true; + callRuntimeCallbacks(__ATINIT__); +} + +function preMain() { + callRuntimeCallbacks(__ATMAIN__); +} + +function exitRuntime() { + callRuntimeCallbacks(__ATEXIT__); +} + +function postRun() { + // compatibility - merge in anything from Module['postRun'] at this time + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + callRuntimeCallbacks(__ATPOSTRUN__); +} + +function addOnPreRun(cb) { + __ATPRERUN__.unshift(cb); +} +Module['addOnPreRun'] = Module.addOnPreRun = addOnPreRun; + +function addOnInit(cb) { + __ATINIT__.unshift(cb); +} +Module['addOnInit'] = Module.addOnInit = addOnInit; + +function addOnPreMain(cb) { + __ATMAIN__.unshift(cb); +} +Module['addOnPreMain'] = Module.addOnPreMain = addOnPreMain; + +function addOnExit(cb) { + __ATEXIT__.unshift(cb); +} +Module['addOnExit'] = Module.addOnExit = addOnExit; + +function addOnPostRun(cb) { + __ATPOSTRUN__.unshift(cb); +} +Module['addOnPostRun'] = Module.addOnPostRun = addOnPostRun; + +// Tools + +// This processes a JS string into a C-line array of numbers, 0-terminated. +// For LLVM-originating strings, see parser.js:parseLLVMString function +function intArrayFromString(stringy, dontAddNull, length /* optional */) { + var ret = (new Runtime.UTF8Processor()).processJSString(stringy); + if (length) { + ret.length = length; + } + if (!dontAddNull) { + ret.push(0); + } + return ret; +} +Module['intArrayFromString'] = intArrayFromString; + +function intArrayToString(array) { + var ret = []; + for (var i = 0; i < array.length; i++) { + var chr = array[i]; + if (chr > 0xFF) { + chr &= 0xFF; + } + ret.push(String.fromCharCode(chr)); + } + return ret.join(''); +} +Module['intArrayToString'] = intArrayToString; + +// Write a Javascript array to somewhere in the heap +function writeStringToMemory(string, buffer, dontAddNull) { + var array = intArrayFromString(string, dontAddNull); + var i = 0; + while (i < array.length) { + var chr = array[i]; + HEAP8[(((buffer)+(i))|0)]=chr; + i = i + 1; + } +} +Module['writeStringToMemory'] = writeStringToMemory; + +function writeArrayToMemory(array, buffer) { + for (var i = 0; i < array.length; i++) { + HEAP8[(((buffer)+(i))|0)]=array[i]; + } +} +Module['writeArrayToMemory'] = writeArrayToMemory; + +function writeAsciiToMemory(str, buffer, dontAddNull) { + for (var i = 0; i < str.length; i++) { + HEAP8[(((buffer)+(i))|0)]=str.charCodeAt(i); + } + if (!dontAddNull) HEAP8[(((buffer)+(str.length))|0)]=0; +} +Module['writeAsciiToMemory'] = writeAsciiToMemory; + +function unSign(value, bits, ignore) { + if (value >= 0) { + return value; + } + return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts + : Math.pow(2, bits) + value; +} +function reSign(value, bits, ignore) { + if (value <= 0) { + return value; + } + var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 + : Math.pow(2, bits-1); + if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that + // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors + // TODO: In i64 mode 1, resign the two parts separately and safely + value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts + } + return value; +} + +// check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 ) +if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) { + var ah = a >>> 16; + var al = a & 0xffff; + var bh = b >>> 16; + var bl = b & 0xffff; + return (al*bl + ((ah*bl + al*bh) << 16))|0; +}; +Math.imul = Math['imul']; + + +var Math_abs = Math.abs; +var Math_cos = Math.cos; +var Math_sin = Math.sin; +var Math_tan = Math.tan; +var Math_acos = Math.acos; +var Math_asin = Math.asin; +var Math_atan = Math.atan; +var Math_atan2 = Math.atan2; +var Math_exp = Math.exp; +var Math_log = Math.log; +var Math_sqrt = Math.sqrt; +var Math_ceil = Math.ceil; +var Math_floor = Math.floor; +var Math_pow = Math.pow; +var Math_imul = Math.imul; +var Math_fround = Math.fround; +var Math_min = Math.min; + +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// PRE_RUN_ADDITIONS (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled + +function addRunDependency(id) { + runDependencies++; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } +} +Module['addRunDependency'] = addRunDependency; +function removeRunDependency(id) { + runDependencies--; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } +} +Module['removeRunDependency'] = removeRunDependency; + +Module["preloadedImages"] = {}; // maps url to image data +Module["preloadedAudios"] = {}; // maps url to audio data + + +var memoryInitializer = null; + +// === Body === + + + + + +STATIC_BASE = 8; + +STATICTOP = STATIC_BASE + Runtime.alignMemory(28211); +/* global initializers */ __ATINIT__.push(); + + +/* memory initializer */ allocate([37,46,51,102,32,37,46,51,102,0,0,0,0,0,0,0,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,0,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,0,108,105,110,101,97,114,0,0,100,101,103,114,101,101,115,0,115,101,120,97,103,101,115,105,109,97,108,0,0,0,0,0,59,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,115,40,0,0,0,0,0,37,46,54,102,44,32,37,46,54,102,0,0,0,0,0,0,37,115,44,32,37,115,0,0,112,111,108,121,103,111,110,0,44,32,37,46,54,102,44,32,37,46,54,102,0,0,0,0,44,32,37,115,44,32,37,115,0,0,0,0,0,0,0,0,44,32,37,46,50,102,34,0,44,32,37,46,54,102,39,0,44,32,37,46,54,102,100,0,98,111,120,0,0,0,0,0,101,108,108,105,112,115,101,0,44,32,37,46,51,102,0,0,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,102,32,37,102], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE); +/* memory initializer */ allocate([1,0,0,0,0,0,0,0,87,67,83,73,78,73,84,78,58,32,87,67,83,32,110,97,109,101,32,37,115,32,110,111,116,32,109,97,116,99,104,101,100,32,105,110,32,70,73,84,83,32,104,101,97,100,101,114,10,0,0,0,0,0,0,0,87,67,83,78,65,77,69,0,87,67,83,65,88,69,83,0,78,65,88,73,83,0,0,0,87,67,83,68,73,77,0,0,87,67,83,73,78,73,84,58,32,78,111,32,87,67,83,65,88,69,83,44,32,78,65,88,73,83,44,32,111,114,32,87,67,83,68,73,77,32,107,101,121,119,111,114,100,0,0,0,78,65,88,73,83,49,0,0,73,77,65,71,69,87,0,0,87,67,83,73,78,73,84,58,32,78,111,32,78,65,88,73,83,49,32,111,114,32,73,77,65,71,69,87,32,107,101,121,119,111,114,100,0,0,0,0,78,65,88,73,83,50,0,0,73,77,65,71,69,72,0,0,87,67,83,73,78,73,84,58,32,78,111,32,78,65,88,73,83,50,32,111,114,32,73,77,65,71,69,72,32,107,101,121,119,111,114,100,0,0,0,0,37,100,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,77,105,115,115,105,110,103,32,107,101,121,119,111,114,100,32,37,115,32,97,115,115,117,109,101,100,32,49,10,0,0,67,84,89,80,69,0,0,0,45,84,65,66,0,0,0,0,73,78,83,84,82,85,77,69,0,0,0,0,0,0,0,0,68,69,84,69,67,84,79,82,0,0,0,0,0,0,0,0,68,67,45,70,76,65,71,0,87,67,83,68,69,80,0,0,87,67,83,73,78,73,84,58,32,100,101,112,101,110,100,101,100,32,111,110,32,87,67,83,32,99,111,117,108,100,32,110,111,116,32,98,101,32,115,101,116,0,0,0,0,0,0,0,86,83,79,85,82,67,69,0,90,83,79,85,82,67,69,0,86,69,76,79,67,73,84,89,0,0,0,0,0,0,0,0,67,84,89,80,69,49,0,0,67,84,89,80,69,50,0,0,76,65,84,0,0,0,0,0,68,69,67,0,0,0,0,0,67,84,89,80,69,51,0,0,67,84,89,80,69,52,0,0,67,85,78,73,84,49,0,0,87,65,84,49,0,0,0,0,117,110,105,116,115,0,0,0,112,105,120,101,108,0,0,0,67,85,78,73,84,50,0,0,87,65,84,50,0,0,0,0,67,82,80,73,88,49,0,0,67,82,80,73,88,50,0,0,67,82,86,65,76,49,0,0,67,82,86,65,76,50,0,0,76,79,78,80,79,76,69,0,76,65,84,80,79,76,69,0,80,82,79,74,82,48,0,0,80,82,79,74,80,37,100,0,80,86,37,100,95,49,0,0,80,86,37,100,95,50,0,0,80,86,37,100,95,51,0,0,80,86,37,100,95,37,100,0,67,68,49,95,49,0,0,0,67,68,49,95,50,0,0,0,67,68,50,95,49,0,0,0,67,68,50,95,50,0,0,0,67,79,49,95,49,0,0,0,80,76,65,84,69,0,0,0,67,79,49,95,37,100,0,0,67,79,50,95,49,0,0,0,67,79,50,95,37,100,0,0,67,68,69,76,84,49,0,0,67,68,69,76,84,50,0,0,83,69,67,80,73,88,0,0,80,73,88,83,67,65,76,69,0,0,0,0,0,0,0,0,80,73,88,83,67,65,76,49,0,0,0,0,0,0,0,0,88,80,73,88,83,73,90,69,0,0,0,0,0,0,0,0,83,69,67,80,73,88,49,0,83,69,67,80,73,88,50,0,89,80,73,88,83,73,90,69,0,0,0,0,0,0,0,0,80,73,88,83,67,65,76,50,0,0,0,0,0,0,0,0,80,67,48,48,49,48,48,49,0,0,0,0,0,0,0,0,80,67,48,48,37,49,100,48,48,37,49,100,0,0,0,0,80,67,49,95,49,0,0,0,80,67,37,49,100,95,37,49,100,0,0,0,0,0,0,0,67,82,79,84,65,50,0,0,67,82,79,84,65,49,0,0,87,67,83,73,78,73,84,58,32,115,101,116,116,105,110,103,32,67,68,69,76,84,32,116,111,32,49,0,0,0,0,0,76,73,78,69,65,82,0,0,80,73,88,69,76,0,0,0,77,74,68,45,79,66,83,0,68,65,84,69,45,79,66,83,0,0,0,0,0,0,0,0,68,65,84,69,0,0,0,0,69,80,79,67,72,0,0,0,85,84,0,0,0,0,0,0,85,84,77,73,68,0,0,0,87,67,83,73,78,73,84,67,58,32,78,111,32,105,109,97,103,101,32,115,99,97,108,101,32,102,111,114,32,87,67,83,32,37,99,0,0,0,0,0,80,76,84,82,65,72,0,0,80,76,84,82,65,77,0,0,80,76,84,82,65,83,0,0,80,76,84,68,69,67,83,78,0,0,0,0,0,0,0,0,80,76,84,68,69,67,68,0,80,76,84,68,69,67,77,0,80,76,84,68,69,67,83,0,69,81,85,73,78,79,88,0,70,75,52,0,0,0,0,0,70,75,53,0,0,0,0,0,37,50,46,48,102,58,37,50,46,48,102,58,37,53,46,51,102,32,37,99,37,50,46,48,102,58,37,50,46,48,102,58,37,53,46,51,102,32,37,115,0,0,0,0,0,0,0,0,80,76,84,83,67,65,76,69,0,0,0,0,0,0,0,0,88,80,73,88,69,76,83,90,0,0,0,0,0,0,0,0,89,80,73,88,69,76,83,90,0,0,0,0,0,0,0,0,67,78,80,73,88,49,0,0,67,78,80,73,88,50,0,0,80,80,79,49,0,0,0,0,80,80,79,37,100,0,0,0,65,77,68,88,49,0,0,0,65,77,68,88,37,100,0,0,65,77,68,89,49,0,0,0,65,77,68,89,37,100,0,0,82,65,0,0,0,0,0,0,82,65,45,45,45,68,83,83,0,0,0,0,0,0,0,0,68,69,67,45,45,68,83,83,0,0,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,78,111,32,82,65,32,119,105,116,104,32,83,69,67,80,73,88,44,32,110,111,32,87,67,83,0,0,0,0,0,0,87,67,83,73,78,73,84,32,78,111,32,68,69,67,32,119,105,116,104,32,83,69,67,80,73,88,44,32,110,111,32,87,67,83,0,0,0,0,0,0,76,79,78,71,80,79,76,69,0,0,0,0,0,0,0,0,82,65,45,45,45,84,65,78,0,0,0,0,0,0,0,0,68,69,67,45,45,84,65,78,0,0,0,0,0,0,0,0,87,67,83,73,78,73,84,58,32,78,111,32,105,109,97,103,101,32,115,99,97,108,101,0,84,65,78,0,0,0,0,0,42,69,114,114,111,114,42,58,32,105,110,99,111,114,114,101,99,116,32,108,105,110,101,97,114,32,99,111,110,118,101,114,115,105,111,110,32,105,110,32,37,115,0,0,0,0,0,0,87,65,82,78,73,78,71,58,32,83,105,103,110,105,102,105,99,97,110,116,32,105,110,97,99,99,117,114,97,99,121,32,108,105,107,101,108,121,32,116,111,32,111,99,99,117,114,32,105,110,32,112,114,111,106,101,99,116,105,111,110,0,0,0,69,81,85,73,78,79,88,37,99,0,0,0,0,0,0,0,82,65,68,69,67,83,89,83,37,99,0,0,0,0,0,0,82,65,68,69,67,83,89,83,0,0,0,0,0,0,0,0,73,67,82,83,0,0,0,0,71,65,76,0,0,0,0,0,69,67,76,0,0,0,0,0,71,65,76,65,67,84,73,67,0,0,0,0,0,0,0,0,69,67,76,73,80,84,73,67,0,0,0,0,0,0,0,0,83,71,65,76,65,67,84,67,0,0,0,0,0,0,0,0,72,69,76,73,79,69,67,76,0,0,0,0,0,0,0,0,65,76,84,65,90,0,0,0,0,0,0,0,0,0,0,0,68,69,67,0,0,0,0,0,76,79,78,71,0,0,0,0,76,73,78,69,65,82,0,0,80,73,88,69,76,0,0,0,68,69,84,0,0,0,0,0,37,45,52,115,37,52,115,0,78,80,79,76,0,0,0,0,76,65,84,0,0,0,0,0,78,80,79,76,69,0,0,0,83,80,65,45,0,0,0,0,73,77,83,89,83,0,0,0,105,109,115,121,115,0,0,0,37,46,52,102,0,0,0,0,66,49,57,53,48,0,0,0,74,50,48,48,48,0,0,0,37,115,9,37,115,0,0,0,37,115,32,37,115,0,0,0,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,42,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,9,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,32,103,97,108,97,99,116,105,99,0,0,0,0,0,0,0,9,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,32,101,99,108,105,112,116,105,99,0,0,0,0,0,0,0,9,108,111,110,103,45,110,112,97,0,0,0,0,0,0,0,32,108,111,110,103,45,110,112,97,0,0,0,0,0,0,0,9,108,111,110,103,45,115,112,97,0,0,0,0,0,0,0,32,108,111,110,103,45,115,112,97,0,0,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,9,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,67,83,95,67,79,77,77,65,78,68,0,0,0,0,0,87,67,83,95,67,79,77,77,65,78,68,37,100,0,0,0,50,48,48,48,0,0,0,0,50,48,48,48,46,48,0,0,73,67,82,83,0,0,0,0,105,99,114,115,0,0,0,0,70,75,53,0,0,0,0,0,102,107,53,0,0,0,0,0,49,57,53,48,0,0,0,0,49,57,53,48,46,48,0,0,70,75,52,0,0,0,0,0,102,107,52,0,0,0,0,0,112,105,120,101,108,0,0,0,44,66,124,35,100,255,239,63,206,4,147,55,81,230,134,63,201,87,119,237,8,231,115,63,8,49,216,60,72,85,196,190,141,82,239,197,175,26,93,190,79,75,150,130,180,74,73,190,206,4,147,55,81,230,134,191,110,20,118,229,124,255,239,63,190,2,89,23,76,127,252,190,141,82,239,197,175,26,93,62,186,92,192,248,87,85,196,190,213,61,80,36,200,25,210,61,192,143,86,244,8,231,115,191,40,252,144,126,141,121,252,190,190,45,6,62,231,255,239,63,79,75,150,130,180,74,73,62,213,61,80,36,200,25,210,61,56,97,156,141,155,85,196,190,37,201,115,125,31,14,66,191,237,156,102,129,118,135,206,63,237,128,235,138,25,225,219,191,138,238,48,88,55,255,239,63,235,42,147,208,76,230,134,63,26,132,28,8,135,230,115,63,12,31,17,83,34,137,206,191,58,234,232,184,26,217,101,191,7,35,246,9,160,24,137,63,235,42,147,208,76,230,134,191,233,248,162,28,80,255,239,63,8,168,211,46,100,125,252,190,137,181,248,20,0,227,219,63,180,173,102,157,241,125,129,191,174,14,128,184,171,87,97,63,26,132,28,8,135,230,115,191,247,97,247,252,180,122,252,190,137,77,92,117,186,255,239,63,125,150,201,34,100,255,239,63,15,157,207,213,158,230,134,191,92,113,244,103,237,229,115,191,26,77,59,180,100,85,196,62,52,175,17,131,3,27,93,190,173,87,210,121,59,74,73,190,20,1,96,210,158,230,134,63,3,186,248,225,124,255,239,63,250,59,9,220,34,127,252,190,52,175,17,131,3,27,93,62,91,229,82,109,116,85,196,62,232,167,8,110,48,27,210,189,73,225,178,117,237,229,115,63,235,19,108,31,83,119,252,190,10,30,195,64,231,255,239,63,173,87,210,121,59,74,73,62,185,158,187,181,171,23,210,189,73,125,255,4,184,85,196,62,37,201,115,125,31,14,66,191,211,48,124,68,76,137,206,191,34,223,165,212,37,227,219,63,45,6,81,239,144,255,239,63,108,197,229,21,219,230,134,191,214,96,142,220,162,229,115,191,180,174,209,114,160,135,206,63,58,234,232,184,26,217,101,191,180,173,102,157,241,125,129,191,108,197,229,21,219,230,134,63,26,73,6,169,169,255,239,63,26,238,175,96,19,128,252,190,134,170,152,74,63,225,219,191,7,35,246,9,160,24,137,63,174,14,128,184,171,87,97,63,214,96,142,220,162,229,115,63,212,213,62,153,86,117,252,190,150,50,62,6,10,0,240,63,0,0,0,0,0,0,0,0,70,75,52,50,71,65,76,58,32,66,49,57,53,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,52,50,71,65,76,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,52,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,52,58,32,66,49,57,53,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,53,50,71,65,76,58,32,74,50,48,48,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,70,75,53,50,71,65,76,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,53,58,32,108,111,110,103,32,61,32,37,46,53,102,32,108,97,116,32,61,32,37,46,53,102,10,0,0,0,0,0,0,0,0,71,65,76,50,70,75,53,58,32,74,50,48,48,48,32,82,65,44,68,101,99,61,32,37,115,10,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,32,37,99,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,0,0,0,0,0,0,0,69,78,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,28,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,30,0,0,0,31,0,0,0,37,115,95,49,0,0,0,0,37,115,95,37,100,0,0,0,37,115,95,48,49,0,0,0,37,115,95,48,48,49,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,48,0,0,0,0,0,0,37,100,0,0,0,0,0,0,37,37,46,37,100,102,0,0,37,48,50,100,58,37,48,50,100,58,37,48,57,46,54,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,56,46,53,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,55,46,52,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,52,46,49,102,0,0,0,0,0,0,0,0,37,48,50,100,58,37,48,50,100,58,37,48,50,100,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,57,46,54,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,56,46,53,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,55,46,52,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,54,46,51,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,53,46,50,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,52,46,49,102,0,0,0,0,0,0,37,99,37,48,50,100,58,37,48,50,100,58,37,48,50,100,0,0,0,0,0,0,0,0,37,37,37,100,46,37,100,102,0,0,0,0,0,0,0,0,37,37,37,52,100,0,0,0,37,37,37,100,100], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+4352); +/* memory initializer */ allocate([87,65,84,49,0,0,0,0,87,65,84,50,0,0,0,0,108,111,110,103,112,111,108,101,0,0,0,0,0,0,0,0,114,111,0,0,0,0,0,0,108,110,103,99,111,114,0,0,108,97,116,99,111,114,0,0,84,78,88,95,71,83,69,86,65,76,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,10,0,0,0,0,0,0,0,84,78,88,95,71,83,68,69,82,58,32,111,114,100,101,114,32,111,102,32,100,101,114,105,118,97,116,105,118,101,115,32,99,97,110,110,111,116,32,98,101,32,60,32,48,10,0,0,84,78,88,95,71,83,68,69,82,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,32,37,100,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,120,32,111,114,100,101,114,32,37,100,10,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,121,32,111,114,100,101,114,32,37,100,10,0,0,0,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,120,32,114,97,110,103,101,32,37,102,45,37,102,10,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,105,108,108,101,103,97,108,32,121,32,114,97,110,103,101,32,37,102,45,37,102,10,0,0,0,0,119,102,95,103,115,114,101,115,116,111,114,101,58,32,117,110,107,110,111,119,110,32,115,117,114,102,97,99,101,32,116,121,112,101,32,37,100,10,0,0,87,65,84,49,0,0,0,0,87,65,84,49,95,48,48,49,61,32,39,119,116,121,112,101,61,122,112,120,32,97,120,116,121,112,101,61,114,97,32,112,114,111,106,112,48,61,48,46,32,112,114,111,106,112,49,61,49,46,32,112,114,111,106,112,50,61,48,46,32,112,114,111,106,112,51,61,51,51,55,46,55,52,32,112,114,111,106,39,87,65,84,50,95,48,48,49,61,32,39,119,116,121,112,101,61,122,112,120,32,97,120,116,121,112,101,61,100,101,99,32,112,114,111,106,112,48,61,48,46,32,112,114,111,106,112,49,61,49,46,32,112,114,111,106,112,50,61,48,46,32,112,114,111,106,112,51,61,51,51,55,46,55,52,32,112,114,111,39,0,0,0,0,0,0,0,0,87,65,84,50,0,0,0,0,108,111,110,103,112,111,108,101,0,0,0,0,0,0,0,0,114,111,0,0,0,0,0,0,112,114,111,106,112,37,100,0,108,110,103,99,111,114,0,0,108,97,116,99,111,114,0,0,10,62,32,37,115,37,115,10,10,0,0,0,0,0,0,0,78,111,116,32,101,110,111,117,103,104,32,109,101,109,111,114,121,32,102,111,114,32,0,0,112,111,108,121,32,40,49,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,84,104,101,32,100,105,109,101,110,115,105,111,110,97,108,105,116,121,32,111,102,32,116,104,101,32,112,111,108,121,110,111,109,32,40,37,100,41,32,101,120,99,101,101,100,115,32,116,104,101,32,109,97,120,105,109,117,109,10,97,108,108,111,119,101,100,32,111,110,101,32,40,37,100,41,0,0,0,0,0,42,69,114,114,111,114,42,58,32,0,0,0,0,0,0,0,112,111,108,121,45,62,103,114,111,117,112,32,40,112,111,108,121,45,62,110,100,105,109,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,112,111,108,121,45,62,100,101,103,114,101,101,32,40,112,111,108,121,45,62,110,103,114,111,117,112,32,101,108,101,109,101,110,116,115,41,32,33,0,0,42,69,114,114,111,114,42,58,32,112,111,108,121,110,111,109,105,97,108,32,71,82,79,85,80,32,111,117,116,32,111,102,32,114,97,110,103,101,0,0,0,0,0,0,0,0,0,0,84,104,101,32,100,101,103,114,101,101,32,111,102,32,116,104,101,32,112,111,108,121,110,111,109,32,40,37,100,41,32,101,120,99,101,101,100,115,32,116,104,101,32,109,97,120,105,109,117,109,10,97,108,108,111,119,101,100,32,111,110,101,32,40,37,100,41,0,0,0,0,0,112,111,108,121,45,62,98,97,115,105,115,32,40,112,111,108,121,45,62,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,112,111,108,121,45,62,99,111,101,102,102,32,40,112,111,108,121,45,62,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,42,73,110,116,101,114,110,97,108,32,69,114,114,111,114,42,58,32,79,110,101,32,111,102,32,120,32,111,114,32,101,120,116,98,97,115,105,115,32,115,104,111,117,108,100,32,98,101,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,78,85,76,76,10,105,110,32,0,0,0,0,0,0,0,0,112,111,108,121,95,102,117,110,99,40,41,0,0,0,0,0,97,108,112,104,97,32,40,109,97,116,115,105,122,101,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,98,101,116,97,32,40,110,99,111,101,102,102,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,0,0,118,109,97,116,32,40,110,42,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,119,109,97,116,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,112,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,0,0,42,69,114,114,111,114,42,58,32,78,111,116,32,101,110,111,117,103,104,32,114,111,119,115,32,102,111,114,32,115,111,108,118,105,110,103,32,116,104,101,32,115,121,115,116,101,109,32,0,0,0,0,0,0,0,0,105,110,32,115,118,100,102,105,116,40,41,0,0,0,0,0,114,118,49,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,116,109,112,32,40,110,32,101,108,101,109,101,110,116,115,41,32,33,0,0,0,0,0,0,42,69,114,114,111,114,42,58,32,78,111,32,99,111,110,118,101,114,103,101,110,99,101,32,105,110,32,49,48,48,32,83,86,68,32,105,116,101,114,97,116,105,111,110,115,32,0,0,67,85,66,69,70,65,67,69,0,0,0,0,0,0,0,0,37,46,51,115,0,0,0,0,82,65,45,45,0,0,0,0,82,65,0,0,0,0,0,0,68,69,67,45,45,37,115,0,68,69,67,45,0,0,0,0,82,65,45,45,45,37,115,0,76,79,78,0,0,0,0,0,37,99,76,79,78,0,0,0,37,99,76,65,84,0,0,0,37,115,45,37,115,0,0,0,76,65,84,0,0,0,0,0,76,78,0,0,0,0,0,0,37,99,37,99,76,78,0,0,37,99,37,99,76,84,0,0,76,84,0,0,0,0,0,0,71,76,83,0,0,0,0,0,78,67,80,0,0,0,0,0,26,0,0,0,0,0,0,0,65,90,80,0,83,90,80,0,84,65,78,0,83,84,71,0,83,73,78,0,65,82,67,0,90,80,78,0,90,69,65,0,65,73,82,0,67,89,80,0,67,69,65,0,67,65,82,0,77,69,82,0,67,79,80,0,67,79,69,0,67,79,68,0,67,79,79,0,83,70,76,0,80,65,82,0,77,79,76,0,65,73,84,0,66,79,78,0,80,67,79,0,84,83,67,0,67,83,67,0,81,83,67,0,65,90,80,0,0,0,0,0,83,90,80,0,0,0,0,0,84,65,78,0,0,0,0,0,83,84,71,0,0,0,0,0,83,73,78,0,0,0,0,0,65,82,67,0,0,0,0,0,90,80,78,0,0,0,0,0,90,69,65,0,0,0,0,0,65,73,82,0,0,0,0,0,67,89,80,0,0,0,0,0,67,69,65,0,0,0,0,0,67,65,82,0,0,0,0,0,77,69,82,0,0,0,0,0,83,70,76,0,0,0,0,0,80,65,82,0,0,0,0,0,77,79,76,0,0,0,0,0,65,73,84,0,0,0,0,0,67,79,80,0,0,0,0,0,67,79,69,0,0,0,0,0,67,79,68,0,0,0,0,0,67,79,79,0,0,0,0,0,66,79,78,0,0,0,0,0,80,67,79,0,0,0,0,0,84,83,67,0,0,0,0,0,67,83,67,0,0,0,0,0,81,83,67,0,0,0,0,0,65,95,79,82,68,69,82,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,65,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,0,65,95,37,100,95,37,100,0,66,95,79,82,68,69,82,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,66,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,0,66,95,37,100,95,37,100,0,65,80,95,79,82,68,69,82,0,0,0,0,0,0,0,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,65,80,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,65,80,95,37,100,95,37,100,0,0,0,0,0,0,0,0,66,80,95,79,82,68,69,82,0,0,0,0,0,0,0,0,68,73,83,84,73,78,73,84,58,32,77,105,115,115,105,110,103,32,66,80,95,79,82,68,69,82,32,107,101,121,119,111,114,100,32,102,111,114,32,83,112,105,116,122,101,114,32,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,0,66,80,95,37,100,95,37,100,0,0,0,0,0,0,0,0,45,83,73,80,0,0,0,0,0,0,0,0,0,0,0,0,91,99,100,108,95,122,115,99,97,108,101,93,32,37,100,120,37,100,45,37,100,32,32,99,111,110,116,61,37,103,32,111,112,116,115,122,61,37,100,32,108,101,110,61,37,100,10,0,91,99,100,108,95,122,115,99,97,108,101,93,32,122,109,105,110,61,37,103,32,122,109,97,120,61,37,103,32,108,101,102,116,61,37,103,32,109,101,100,105,97,110,61,37,103,10,0,91,99,100,108,95,122,115,99,97,108,101,93,32,109,105,110,112,105,120,61,37,100,32,110,103,114,111,119,61,37,100,32,110,103,111,111,100,112,105,120,61,37,100,10,0,0,0,0,91,99,100,108,95,122,115,99,97,108,101,93,32,122,115,108,111,112,101,61,37,103,32,99,101,110,116,101,114,95,112,105,120,61,37,100,32,122,49,61,37,103,32,122,50,61,37,103,10,0,0,0,0,0,0,0,91,115,97,109,112,108,101,73,109,97,103,101,93,32,111,112,116,95,110,112,105,120,47,108,105,110,101,61,37,100,32,99,111,108,95,115,116,101,112,61,37,100,32,110,47,108,105,110,101,61,37,100,10,0,0,0,91,115,97,109,112,108,101,73,109,97,103,101,93,32,110,108,95,105,110,95,115,97,109,112,61,37,100,47,37,100,32,111,112,116,95,110,108,47,115,97,109,112,61,37,100,32,108,115,116,101,112,61,37,100,10,0,0,0,0,0,150,48,7,119,44,97,14,238,186,81,9,153,25,196,109,7,143,244,106,112,53,165,99,233,163,149,100,158,50,136,219,14,164,184,220,121,30,233,213,224,136,217,210,151,43,76,182,9,189,124,177,126,7,45,184,231,145,29,191,144,100,16,183,29,242,32,176,106,72,113,185,243,222,65,190,132,125,212,218,26,235,228,221,109,81,181,212,244,199,133,211,131,86,152,108,19,192,168,107,100,122,249,98,253,236,201,101,138,79,92,1,20,217,108,6,99,99,61,15,250,245,13,8,141,200,32,110,59,94,16,105,76,228,65,96,213,114,113,103,162,209,228,3,60,71,212,4,75,253,133,13,210,107,181,10,165,250,168,181,53,108,152,178,66,214,201,187,219,64,249,188,172,227,108,216,50,117,92,223,69,207,13,214,220,89,61,209,171,172,48,217,38,58,0,222,81,128,81,215,200,22,97,208,191,181,244,180,33,35,196,179,86,153,149,186,207,15,165,189,184,158,184,2,40,8,136,5,95,178,217,12,198,36,233,11,177,135,124,111,47,17,76,104,88,171,29,97,193,61,45,102,182,144,65,220,118,6,113,219,1,188,32,210,152,42,16,213,239,137,133,177,113,31,181,182,6,165,228,191,159,51,212,184,232,162,201,7,120,52,249,0,15,142,168,9,150,24,152,14,225,187,13,106,127,45,61,109,8,151,108,100,145,1,92,99,230,244,81,107,107,98,97,108,28,216,48,101,133,78,0,98,242,237,149,6,108,123,165,1,27,193,244,8,130,87,196,15,245,198,217,176,101,80,233,183,18,234,184,190,139,124,136,185,252,223,29,221,98,73,45,218,21,243,124,211,140,101,76,212,251,88,97,178,77,206,81,181,58,116,0,188,163,226,48,187,212,65,165,223,74,215,149,216,61,109,196,209,164,251,244,214,211,106,233,105,67,252,217,110,52,70,136,103,173,208,184,96,218,115,45,4,68,229,29,3,51,95,76,10,170,201,124,13,221,60,113,5,80,170,65,2,39,16,16,11,190,134,32,12,201,37,181,104,87,179,133,111,32,9,212,102,185,159,228,97,206,14,249,222,94,152,201,217,41,34,152,208,176,180,168,215,199,23,61,179,89,129,13,180,46,59,92,189,183,173,108,186,192,32,131,184,237,182,179,191,154,12,226,182,3,154,210,177,116,57,71,213,234,175,119,210,157,21,38,219,4,131,22,220,115,18,11,99,227,132,59,100,148,62,106,109,13,168,90,106,122,11,207,14,228,157,255,9,147,39,174,0,10,177,158,7,125,68,147,15,240,210,163,8,135,104,242,1,30,254,194,6,105,93,87,98,247,203,103,101,128,113,54,108,25,231,6,107,110,118,27,212,254,224,43,211,137,90,122,218,16,204,74,221,103,111,223,185,249,249,239,190,142,67,190,183,23,213,142,176,96,232,163,214,214,126,147,209,161,196,194,216,56,82,242,223,79,241,103,187,209,103,87,188,166,221,6,181,63,75,54,178,72,218,43,13,216,76,27,10,175,246,74,3,54,96,122,4,65,195,239,96,223,85,223,103,168,239,142,110,49,121,190,105,70,140,179,97,203,26,131,102,188,160,210,111,37,54,226,104,82,149,119,12,204,3,71,11,187,185,22,2,34,47,38,5,85,190,59,186,197,40,11,189,178,146,90,180,43,4,106,179,92,167,255,215,194,49,207,208,181,139,158,217,44,29,174,222,91,176,194,100,155,38,242,99,236,156,163,106,117,10,147,109,2,169,6,9,156,63,54,14,235,133,103,7,114,19,87,0,5,130,74,191,149,20,122,184,226,174,43,177,123,56,27,182,12,155,142,210,146,13,190,213,229,183,239,220,124,33,223,219,11,212,210,211,134,66,226,212,241,248,179,221,104,110,131,218,31,205,22,190,129,91,38,185,246,225,119,176,111,119,71,183,24,230,90,8,136,112,106,15,255,202,59,6,102,92,11,1,17,255,158,101,143,105,174,98,248,211,255,107,97,69,207,108,22,120,226,10,160,238,210,13,215,84,131,4,78,194,179,3,57,97,38,103,167,247,22,96,208,77,71,105,73,219,119,110,62,74,106,209,174,220,90,214,217,102,11,223,64,240,59,216,55,83,174,188,169,197,158,187,222,127,207,178,71,233,255,181,48,28,242,189,189,138,194,186,202,48,147,179,83,166,163,180,36,5,54,208,186,147,6,215,205,41,87,222,84,191,103,217,35,46,122,102,179,184,74,97,196,2,27,104,93,148,43,111,42,55,190,11,180,161,142,12,195,27,223,5,90,141,239,2,45,0,0,0,0,65,49,27,25,130,98,54,50,195,83,45,43,4,197,108,100,69,244,119,125,134,167,90,86,199,150,65,79,8,138,217,200,73,187,194,209,138,232,239,250,203,217,244,227,12,79,181,172,77,126,174,181,142,45,131,158,207,28,152,135,81,18,194,74,16,35,217,83,211,112,244,120,146,65,239,97,85,215,174,46,20,230,181,55,215,181,152,28,150,132,131,5,89,152,27,130,24,169,0,155,219,250,45,176,154,203,54,169,93,93,119,230,28,108,108,255,223,63,65,212,158,14,90,205,162,36,132,149,227,21,159,140,32,70,178,167,97,119,169,190,166,225,232,241,231,208,243,232,36,131,222,195,101,178,197,218,170,174,93,93,235,159,70,68,40,204,107,111,105,253,112,118,174,107,49,57,239,90,42,32,44,9,7,11,109,56,28,18,243,54,70,223,178,7,93,198,113,84,112,237,48,101,107,244,247,243,42,187,182,194,49,162,117,145,28,137,52,160,7,144,251,188,159,23,186,141,132,14,121,222,169,37,56,239,178,60,255,121,243,115,190,72,232,106,125,27,197,65,60,42,222,88,5,79,121,240,68,126,98,233,135,45,79,194,198,28,84,219,1,138,21,148,64,187,14,141,131,232,35,166,194,217,56,191,13,197,160,56,76,244,187,33,143,167,150,10,206,150,141,19,9,0,204,92,72,49,215,69,139,98,250,110,202,83,225,119,84,93,187,186,21,108,160,163,214,63,141,136,151,14,150,145,80,152,215,222,17,169,204,199,210,250,225,236,147,203,250,245,92,215,98,114,29,230,121,107,222,181,84,64,159,132,79,89,88,18,14,22,25,35,21,15,218,112,56,36,155,65,35,61,167,107,253,101,230,90,230,124,37,9,203,87,100,56,208,78,163,174,145,1,226,159,138,24,33,204,167,51,96,253,188,42,175,225,36,173,238,208,63,180,45,131,18,159,108,178,9,134,171,36,72,201,234,21,83,208,41,70,126,251,104,119,101,226,246,121,63,47,183,72,36,54,116,27,9,29,53,42,18,4,242,188,83,75,179,141,72,82,112,222,101,121,49,239,126,96,254,243,230,231,191,194,253,254,124,145,208,213,61,160,203,204,250,54,138,131,187,7,145,154,120,84,188,177,57,101,167,168,75,152,131,59,10,169,152,34,201,250,181,9,136,203,174,16,79,93,239,95,14,108,244,70,205,63,217,109,140,14,194,116,67,18,90,243,2,35,65,234,193,112,108,193,128,65,119,216,71,215,54,151,6,230,45,142,197,181,0,165,132,132,27,188,26,138,65,113,91,187,90,104,152,232,119,67,217,217,108,90,30,79,45,21,95,126,54,12,156,45,27,39,221,28,0,62,18,0,152,185,83,49,131,160,144,98,174,139,209,83,181,146,22,197,244,221,87,244,239,196,148,167,194,239,213,150,217,246,233,188,7,174,168,141,28,183,107,222,49,156,42,239,42,133,237,121,107,202,172,72,112,211,111,27,93,248,46,42,70,225,225,54,222,102,160,7,197,127,99,84,232,84,34,101,243,77,229,243,178,2,164,194,169,27,103,145,132,48,38,160,159,41,184,174,197,228,249,159,222,253,58,204,243,214,123,253,232,207,188,107,169,128,253,90,178,153,62,9,159,178,127,56,132,171,176,36,28,44,241,21,7,53,50,70,42,30,115,119,49,7,180,225,112,72,245,208,107,81,54,131,70,122,119,178,93,99,78,215,250,203,15,230,225,210,204,181,204,249,141,132,215,224,74,18,150,175,11,35,141,182,200,112,160,157,137,65,187,132,70,93,35,3,7,108,56,26,196,63,21,49,133,14,14,40,66,152,79,103,3,169,84,126,192,250,121,85,129,203,98,76,31,197,56,129,94,244,35,152,157,167,14,179,220,150,21,170,27,0,84,229,90,49,79,252,153,98,98,215,216,83,121,206,23,79,225,73,86,126,250,80,149,45,215,123,212,28,204,98,19,138,141,45,82,187,150,52,145,232,187,31,208,217,160,6,236,243,126,94,173,194,101,71,110,145,72,108,47,160,83,117,232,54,18,58,169,7,9,35,106,84,36,8,43,101,63,17,228,121,167,150,165,72,188,143,102,27,145,164,39,42,138,189,224,188,203,242,161,141,208,235,98,222,253,192,35,239,230,217,189,225,188,20,252,208,167,13,63,131,138,38,126,178,145,63,185,36,208,112,248,21,203,105,59,70,230,66,122,119,253,91,181,107,101,220,244,90,126,197,55,9,83,238,118,56,72,247,177,174,9,184,240,159,18,161,51,204,63,138,114,253,36,147,0,0,0,0,55,106,194,1,110,212,132,3,89,190,70,2,220,168,9,7,235,194,203,6,178,124,141,4,133,22,79,5,184,81,19,14,143,59,209,15,214,133,151,13,225,239,85,12,100,249,26,9,83,147,216,8,10,45,158,10,61,71,92,11,112,163,38,28,71,201,228,29,30,119,162,31,41,29,96,30,172,11,47,27,155,97,237,26,194,223,171,24,245,181,105,25,200,242,53,18,255,152,247,19,166,38,177,17,145,76,115,16,20,90,60,21,35,48,254,20,122,142,184,22,77,228,122,23,224,70,77,56,215,44,143,57,142,146,201,59,185,248,11,58,60,238,68,63,11,132,134,62,82,58,192,60,101,80,2,61,88,23,94,54,111,125,156,55,54,195,218,53,1,169,24,52,132,191,87,49,179,213,149,48,234,107,211,50,221,1,17,51,144,229,107,36,167,143,169,37,254,49,239,39,201,91,45,38,76,77,98,35,123,39,160,34,34,153,230,32,21,243,36,33,40,180,120,42,31,222,186,43,70,96,252,41,113,10,62,40,244,28,113,45,195,118,179,44,154,200,245,46,173,162,55,47,192,141,154,112,247,231,88,113,174,89,30,115,153,51,220,114,28,37,147,119,43,79,81,118,114,241,23,116,69,155,213,117,120,220,137,126,79,182,75,127,22,8,13,125,33,98,207,124,164,116,128,121,147,30,66,120,202,160,4,122,253,202,198,123,176,46,188,108,135,68,126,109,222,250,56,111,233,144,250,110,108,134,181,107,91,236,119,106,2,82,49,104,53,56,243,105,8,127,175,98,63,21,109,99,102,171,43,97,81,193,233,96,212,215,166,101,227,189,100,100,186,3,34,102,141,105,224,103,32,203,215,72,23,161,21,73,78,31,83,75,121,117,145,74,252,99,222,79,203,9,28,78,146,183,90,76,165,221,152,77,152,154,196,70,175,240,6,71,246,78,64,69,193,36,130,68,68,50,205,65,115,88,15,64,42,230,73,66,29,140,139,67,80,104,241,84,103,2,51,85,62,188,117,87,9,214,183,86,140,192,248,83,187,170,58,82,226,20,124,80,213,126,190,81,232,57,226,90,223,83,32,91,134,237,102,89,177,135,164,88,52,145,235,93,3,251,41,92,90,69,111,94,109,47,173,95,128,27,53,225,183,113,247,224,238,207,177,226,217,165,115,227,92,179,60,230,107,217,254,231,50,103,184,229,5,13,122,228,56,74,38,239,15,32,228,238,86,158,162,236,97,244,96,237,228,226,47,232,211,136,237,233,138,54,171,235,189,92,105,234,240,184,19,253,199,210,209,252,158,108,151,254,169,6,85,255,44,16,26,250,27,122,216,251,66,196,158,249,117,174,92,248,72,233,0,243,127,131,194,242,38,61,132,240,17,87,70,241,148,65,9,244,163,43,203,245,250,149,141,247,205,255,79,246,96,93,120,217,87,55,186,216,14,137,252,218,57,227,62,219,188,245,113,222,139,159,179,223,210,33,245,221,229,75,55,220,216,12,107,215,239,102,169,214,182,216,239,212,129,178,45,213,4,164,98,208,51,206,160,209,106,112,230,211,93,26,36,210,16,254,94,197,39,148,156,196,126,42,218,198,73,64,24,199,204,86,87,194,251,60,149,195,162,130,211,193,149,232,17,192,168,175,77,203,159,197,143,202,198,123,201,200,241,17,11,201,116,7,68,204,67,109,134,205,26,211,192,207,45,185,2,206,64,150,175,145,119,252,109,144,46,66,43,146,25,40,233,147,156,62,166,150,171,84,100,151,242,234,34,149,197,128,224,148,248,199,188,159,207,173,126,158,150,19,56,156,161,121,250,157,36,111,181,152,19,5,119,153,74,187,49,155,125,209,243,154,48,53,137,141,7,95,75,140,94,225,13,142,105,139,207,143,236,157,128,138,219,247,66,139,130,73,4,137,181,35,198,136,136,100,154,131,191,14,88,130,230,176,30,128,209,218,220,129,84,204,147,132,99,166,81,133,58,24,23,135,13,114,213,134,160,208,226,169,151,186,32,168,206,4,102,170,249,110,164,171,124,120,235,174,75,18,41,175,18,172,111,173,37,198,173,172,24,129,241,167,47,235,51,166,118,85,117,164,65,63,183,165,196,41,248,160,243,67,58,161,170,253,124,163,157,151,190,162,208,115,196,181,231,25,6,180,190,167,64,182,137,205,130,183,12,219,205,178,59,177,15,179,98,15,73,177,85,101,139,176,104,34,215,187,95,72,21,186,6,246,83,184,49,156,145,185,180,138,222,188,131,224,28,189,218,94,90,191,237,52,152,190,0,0,0,0,101,103,188,184,139,200,9,170,238,175,181,18,87,151,98,143,50,240,222,55,220,95,107,37,185,56,215,157,239,40,180,197,138,79,8,125,100,224,189,111,1,135,1,215,184,191,214,74,221,216,106,242,51,119,223,224,86,16,99,88,159,87,25,80,250,48,165,232,20,159,16,250,113,248,172,66,200,192,123,223,173,167,199,103,67,8,114,117,38,111,206,205,112,127,173,149,21,24,17,45,251,183,164,63,158,208,24,135,39,232,207,26,66,143,115,162,172,32,198,176,201,71,122,8,62,175,50,160,91,200,142,24,181,103,59,10,208,0,135,178,105,56,80,47,12,95,236,151,226,240,89,133,135,151,229,61,209,135,134,101,180,224,58,221,90,79,143,207,63,40,51,119,134,16,228,234,227,119,88,82,13,216,237,64,104,191,81,248,161,248,43,240,196,159,151,72,42,48,34,90,79,87,158,226,246,111,73,127,147,8,245,199,125,167,64,213,24,192,252,109,78,208,159,53,43,183,35,141,197,24,150,159,160,127,42,39,25,71,253,186,124,32,65,2,146,143,244,16,247,232,72,168,61,88,20,155,88,63,168,35,182,144,29,49,211,247,161,137,106,207,118,20,15,168,202,172,225,7,127,190,132,96,195,6,210,112,160,94,183,23,28,230,89,184,169,244,60,223,21,76,133,231,194,209,224,128,126,105,14,47,203,123,107,72,119,195,162,15,13,203,199,104,177,115,41,199,4,97,76,160,184,217,245,152,111,68,144,255,211,252,126,80,102,238,27,55,218,86,77,39,185,14,40,64,5,182,198,239,176,164,163,136,12,28,26,176,219,129,127,215,103,57,145,120,210,43,244,31,110,147,3,247,38,59,102,144,154,131,136,63,47,145,237,88,147,41,84,96,68,180,49,7,248,12,223,168,77,30,186,207,241,166,236,223,146,254,137,184,46,70,103,23,155,84,2,112,39,236,187,72,240,113,222,47,76,201,48,128,249,219,85,231,69,99,156,160,63,107,249,199,131,211,23,104,54,193,114,15,138,121,203,55,93,228,174,80,225,92,64,255,84,78,37,152,232,246,115,136,139,174,22,239,55,22,248,64,130,4,157,39,62,188,36,31,233,33,65,120,85,153,175,215,224,139,202,176,92,51,59,182,89,237,94,209,229,85,176,126,80,71,213,25,236,255,108,33,59,98,9,70,135,218,231,233,50,200,130,142,142,112,212,158,237,40,177,249,81,144,95,86,228,130,58,49,88,58,131,9,143,167,230,110,51,31,8,193,134,13,109,166,58,181,164,225,64,189,193,134,252,5,47,41,73,23,74,78,245,175,243,118,34,50,150,17,158,138,120,190,43,152,29,217,151,32,75,201,244,120,46,174,72,192,192,1,253,210,165,102,65,106,28,94,150,247,121,57,42,79,151,150,159,93,242,241,35,229,5,25,107,77,96,126,215,245,142,209,98,231,235,182,222,95,82,142,9,194,55,233,181,122,217,70,0,104,188,33,188,208,234,49,223,136,143,86,99,48,97,249,214,34,4,158,106,154,189,166,189,7,216,193,1,191,54,110,180,173,83,9,8,21,154,78,114,29,255,41,206,165,17,134,123,183,116,225,199,15,205,217,16,146,168,190,172,42,70,17,25,56,35,118,165,128,117,102,198,216,16,1,122,96,254,174,207,114,155,201,115,202,34,241,164,87,71,150,24,239,169,57,173,253,204,94,17,69,6,238,77,118,99,137,241,206,141,38,68,220,232,65,248,100,81,121,47,249,52,30,147,65,218,177,38,83,191,214,154,235,233,198,249,179,140,161,69,11,98,14,240,25,7,105,76,161,190,81,155,60,219,54,39,132,53,153,146,150,80,254,46,46,153,185,84,38,252,222,232,158,18,113,93,140,119,22,225,52,206,46,54,169,171,73,138,17,69,230,63,3,32,129,131,187,118,145,224,227,19,246,92,91,253,89,233,73,152,62,85,241,33,6,130,108,68,97,62,212,170,206,139,198,207,169,55,126,56,65,127,214,93,38,195,110,179,137,118,124,214,238,202,196,111,214,29,89,10,177,161,225,228,30,20,243,129,121,168,75,215,105,203,19,178,14,119,171,92,161,194,185,57,198,126,1,128,254,169,156,229,153,21,36,11,54,160,54,110,81,28,142,167,22,102,134,194,113,218,62,44,222,111,44,73,185,211,148,240,129,4,9,149,230,184,177,123,73,13,163,30,46,177,27,72,62,210,67,45,89,110,251,195,246,219,233,166,145,103,81,31,169,176,204,122,206,12,116,148,97,185,102,241,6,5,222,0,0,0,0,119,7,48,150,238,14,97,44,153,9,81,186,7,109,196,25,112,106,244,143,233,99,165,53,158,100,149,163,14,219,136,50,121,220,184,164,224,213,233,30,151,210,217,136,9,182,76,43,126,177,124,189,231,184,45,7,144,191,29,145,29,183,16,100,106,176,32,242,243,185,113,72,132,190,65,222,26,218,212,125,109,221,228,235,244,212,181,81,131,211,133,199,19,108,152,86,100,107,168,192,253,98,249,122,138,101,201,236,20,1,92,79,99,6,108,217,250,15,61,99,141,8,13,245,59,110,32,200,76,105,16,94,213,96,65,228,162,103,113,114,60,3,228,209,75,4,212,71,210,13,133,253,165,10,181,107,53,181,168,250,66,178,152,108,219,187,201,214,172,188,249,64,50,216,108,227,69,223,92,117,220,214,13,207,171,209,61,89,38,217,48,172,81,222,0,58,200,215,81,128,191,208,97,22,33,180,244,181,86,179,196,35,207,186,149,153,184,189,165,15,40,2,184,158,95,5,136,8,198,12,217,178,177,11,233,36,47,111,124,135,88,104,76,17,193,97,29,171,182,102,45,61,118,220,65,144,1,219,113,6,152,210,32,188,239,213,16,42,113,177,133,137,6,182,181,31,159,191,228,165,232,184,212,51,120,7,201,162,15,0,249,52,150,9,168,142,225,14,152,24,127,106,13,187,8,109,61,45,145,100,108,151,230,99,92,1,107,107,81,244,28,108,97,98,133,101,48,216,242,98,0,78,108,6,149,237,27,1,165,123,130,8,244,193,245,15,196,87,101,176,217,198,18,183,233,80,139,190,184,234,252,185,136,124,98,221,29,223,21,218,45,73,140,211,124,243,251,212,76,101,77,178,97,88,58,181,81,206,163,188,0,116,212,187,48,226,74,223,165,65,61,216,149,215,164,209,196,109,211,214,244,251,67,105,233,106,52,110,217,252,173,103,136,70,218,96,184,208,68,4,45,115,51,3,29,229,170,10,76,95,221,13,124,201,80,5,113,60,39,2,65,170,190,11,16,16,201,12,32,134,87,104,181,37,32,111,133,179,185,102,212,9,206,97,228,159,94,222,249,14,41,217,201,152,176,208,152,34,199,215,168,180,89,179,61,23,46,180,13,129,183,189,92,59,192,186,108,173,237,184,131,32,154,191,179,182,3,182,226,12,116,177,210,154,234,213,71,57,157,210,119,175,4,219,38,21,115,220,22,131,227,99,11,18,148,100,59,132,13,109,106,62,122,106,90,168,228,14,207,11,147,9,255,157,10,0,174,39,125,7,158,177,240,15,147,68,135,8,163,210,30,1,242,104,105,6,194,254,247,98,87,93,128,101,103,203,25,108,54,113,110,107,6,231,254,212,27,118,137,211,43,224,16,218,122,90,103,221,74,204,249,185,223,111,142,190,239,249,23,183,190,67,96,176,142,213,214,214,163,232,161,209,147,126,56,216,194,196,79,223,242,82,209,187,103,241,166,188,87,103,63,181,6,221,72,178,54,75,216,13,43,218,175,10,27,76,54,3,74,246,65,4,122,96,223,96,239,195,168,103,223,85,49,110,142,239,70,105,190,121,203,97,179,140,188,102,131,26,37,111,210,160,82,104,226,54,204,12,119,149,187,11,71,3,34,2,22,185,85,5,38,47,197,186,59,190,178,189,11,40,43,180,90,146,92,179,106,4,194,215,255,167,181,208,207,49,44,217,158,139,91,222,174,29,155,100,194,176,236,99,242,38,117,106,163,156,2,109,147,10,156,9,6,169,235,14,54,63,114,7,103,133,5,0,87,19,149,191,74,130,226,184,122,20,123,177,43,174,12,182,27,56,146,210,142,155,229,213,190,13,124,220,239,183,11,219,223,33,134,211,210,212,241,212,226,66,104,221,179,248,31,218,131,110,129,190,22,205,246,185,38,91,111,176,119,225,24,183,71,119,136,8,90,230,255,15,106,112,102,6,59,202,17,1,11,92,143,101,158,255,248,98,174,105,97,107,255,211,22,108,207,69,160,10,226,120,215,13,210,238,78,4,131,84,57,3,179,194,167,103,38,97,208,96,22,247,73,105,71,77,62,110,119,219,174,209,106,74,217,214,90,220,64,223,11,102,55,216,59,240,169,188,174,83,222,187,158,197,71,178,207,127,48,181,255,233,189,189,242,28,202,186,194,138,83,179,147,48,36,180,163,166,186,208,54,5,205,215,6,147,84,222,87,41,35,217,103,191,179,102,122,46,196,97,74,184,93,104,27,2,42,111,43,148,180,11,190,55,195,12,142,161,90,5,223,27,45,2,239,141,0,0,0,0,25,27,49,65,50,54,98,130,43,45,83,195,100,108,197,4,125,119,244,69,86,90,167,134,79,65,150,199,200,217,138,8,209,194,187,73,250,239,232,138,227,244,217,203,172,181,79,12,181,174,126,77,158,131,45,142,135,152,28,207,74,194,18,81,83,217,35,16,120,244,112,211,97,239,65,146,46,174,215,85,55,181,230,20,28,152,181,215,5,131,132,150,130,27,152,89,155,0,169,24,176,45,250,219,169,54,203,154,230,119,93,93,255,108,108,28,212,65,63,223,205,90,14,158,149,132,36,162,140,159,21,227,167,178,70,32,190,169,119,97,241,232,225,166,232,243,208,231,195,222,131,36,218,197,178,101,93,93,174,170,68,70,159,235,111,107,204,40,118,112,253,105,57,49,107,174,32,42,90,239,11,7,9,44,18,28,56,109,223,70,54,243,198,93,7,178,237,112,84,113,244,107,101,48,187,42,243,247,162,49,194,182,137,28,145,117,144,7,160,52,23,159,188,251,14,132,141,186,37,169,222,121,60,178,239,56,115,243,121,255,106,232,72,190,65,197,27,125,88,222,42,60,240,121,79,5,233,98,126,68,194,79,45,135,219,84,28,198,148,21,138,1,141,14,187,64,166,35,232,131,191,56,217,194,56,160,197,13,33,187,244,76,10,150,167,143,19,141,150,206,92,204,0,9,69,215,49,72,110,250,98,139,119,225,83,202,186,187,93,84,163,160,108,21,136,141,63,214,145,150,14,151,222,215,152,80,199,204,169,17,236,225,250,210,245,250,203,147,114,98,215,92,107,121,230,29,64,84,181,222,89,79,132,159,22,14,18,88,15,21,35,25,36,56,112,218,61,35,65,155,101,253,107,167,124,230,90,230,87,203,9,37,78,208,56,100,1,145,174,163,24,138,159,226,51,167,204,33,42,188,253,96,173,36,225,175,180,63,208,238,159,18,131,45,134,9,178,108,201,72,36,171,208,83,21,234,251,126,70,41,226,101,119,104,47,63,121,246,54,36,72,183,29,9,27,116,4,18,42,53,75,83,188,242,82,72,141,179,121,101,222,112,96,126,239,49,231,230,243,254,254,253,194,191,213,208,145,124,204,203,160,61,131,138,54,250,154,145,7,187,177,188,84,120,168,167,101,57,59,131,152,75,34,152,169,10,9,181,250,201,16,174,203,136,95,239,93,79,70,244,108,14,109,217,63,205,116,194,14,140,243,90,18,67,234,65,35,2,193,108,112,193,216,119,65,128,151,54,215,71,142,45,230,6,165,0,181,197,188,27,132,132,113,65,138,26,104,90,187,91,67,119,232,152,90,108,217,217,21,45,79,30,12,54,126,95,39,27,45,156,62,0,28,221,185,152,0,18,160,131,49,83,139,174,98,144,146,181,83,209,221,244,197,22,196,239,244,87,239,194,167,148,246,217,150,213,174,7,188,233,183,28,141,168,156,49,222,107,133,42,239,42,202,107,121,237,211,112,72,172,248,93,27,111,225,70,42,46,102,222,54,225,127,197,7,160,84,232,84,99,77,243,101,34,2,178,243,229,27,169,194,164,48,132,145,103,41,159,160,38,228,197,174,184,253,222,159,249,214,243,204,58,207,232,253,123,128,169,107,188,153,178,90,253,178,159,9,62,171,132,56,127,44,28,36,176,53,7,21,241,30,42,70,50,7,49,119,115,72,112,225,180,81,107,208,245,122,70,131,54,99,93,178,119,203,250,215,78,210,225,230,15,249,204,181,204,224,215,132,141,175,150,18,74,182,141,35,11,157,160,112,200,132,187,65,137,3,35,93,70,26,56,108,7,49,21,63,196,40,14,14,133,103,79,152,66,126,84,169,3,85,121,250,192,76,98,203,129,129,56,197,31,152,35,244,94,179,14,167,157,170,21,150,220,229,84,0,27,252,79,49,90,215,98,98,153,206,121,83,216,73,225,79,23,80,250,126,86,123,215,45,149,98,204,28,212,45,141,138,19,52,150,187,82,31,187,232,145,6,160,217,208,94,126,243,236,71,101,194,173,108,72,145,110,117,83,160,47,58,18,54,232,35,9,7,169,8,36,84,106,17,63,101,43,150,167,121,228,143,188,72,165,164,145,27,102,189,138,42,39,242,203,188,224,235,208,141,161,192,253,222,98,217,230,239,35,20,188,225,189,13,167,208,252,38,138,131,63,63,145,178,126,112,208,36,185,105,203,21,248,66,230,70,59,91,253,119,122,220,101,107,181,197,126,90,244,238,83,9,55,247,72,56,118,184,9,174,177,161,18,159,240,138,63,204,51,147,36,253,114,0,0,0,0,1,194,106,55,3,132,212,110,2,70,190,89,7,9,168,220,6,203,194,235,4,141,124,178,5,79,22,133,14,19,81,184,15,209,59,143,13,151,133,214,12,85,239,225,9,26,249,100,8,216,147,83,10,158,45,10,11,92,71,61,28,38,163,112,29,228,201,71,31,162,119,30,30,96,29,41,27,47,11,172,26,237,97,155,24,171,223,194,25,105,181,245,18,53,242,200,19,247,152,255,17,177,38,166,16,115,76,145,21,60,90,20,20,254,48,35,22,184,142,122,23,122,228,77,56,77,70,224,57,143,44,215,59,201,146,142,58,11,248,185,63,68,238,60,62,134,132,11,60,192,58,82,61,2,80,101,54,94,23,88,55,156,125,111,53,218,195,54,52,24,169,1,49,87,191,132,48,149,213,179,50,211,107,234,51,17,1,221,36,107,229,144,37,169,143,167,39,239,49,254,38,45,91,201,35,98,77,76,34,160,39,123,32,230,153,34,33,36,243,21,42,120,180,40,43,186,222,31,41,252,96,70,40,62,10,113,45,113,28,244,44,179,118,195,46,245,200,154,47,55,162,173,112,154,141,192,113,88,231,247,115,30,89,174,114,220,51,153,119,147,37,28,118,81,79,43,116,23,241,114,117,213,155,69,126,137,220,120,127,75,182,79,125,13,8,22,124,207,98,33,121,128,116,164,120,66,30,147,122,4,160,202,123,198,202,253,108,188,46,176,109,126,68,135,111,56,250,222,110,250,144,233,107,181,134,108,106,119,236,91,104,49,82,2,105,243,56,53,98,175,127,8,99,109,21,63,97,43,171,102,96,233,193,81,101,166,215,212,100,100,189,227,102,34,3,186,103,224,105,141,72,215,203,32,73,21,161,23,75,83,31,78,74,145,117,121,79,222,99,252,78,28,9,203,76,90,183,146,77,152,221,165,70,196,154,152,71,6,240,175,69,64,78,246,68,130,36,193,65,205,50,68,64,15,88,115,66,73,230,42,67,139,140,29,84,241,104,80,85,51,2,103,87,117,188,62,86,183,214,9,83,248,192,140,82,58,170,187,80,124,20,226,81,190,126,213,90,226,57,232,91,32,83,223,89,102,237,134,88,164,135,177,93,235,145,52,92,41,251,3,94,111,69,90,95,173,47,109,225,53,27,128,224,247,113,183,226,177,207,238,227,115,165,217,230,60,179,92,231,254,217,107,229,184,103,50,228,122,13,5,239,38,74,56,238,228,32,15,236,162,158,86,237,96,244,97,232,47,226,228,233,237,136,211,235,171,54,138,234,105,92,189,253,19,184,240,252,209,210,199,254,151,108,158,255,85,6,169,250,26,16,44,251,216,122,27,249,158,196,66,248,92,174,117,243,0,233,72,242,194,131,127,240,132,61,38,241,70,87,17,244,9,65,148,245,203,43,163,247,141,149,250,246,79,255,205,217,120,93,96,216,186,55,87,218,252,137,14,219,62,227,57,222,113,245,188,223,179,159,139,221,245,33,210,220,55,75,229,215,107,12,216,214,169,102,239,212,239,216,182,213,45,178,129,208,98,164,4,209,160,206,51,211,230,112,106,210,36,26,93,197,94,254,16,196,156,148,39,198,218,42,126,199,24,64,73,194,87,86,204,195,149,60,251,193,211,130,162,192,17,232,149,203,77,175,168,202,143,197,159,200,201,123,198,201,11,17,241,204,68,7,116,205,134,109,67,207,192,211,26,206,2,185,45,145,175,150,64,144,109,252,119,146,43,66,46,147,233,40,25,150,166,62,156,151,100,84,171,149,34,234,242,148,224,128,197,159,188,199,248,158,126,173,207,156,56,19,150,157,250,121,161,152,181,111,36,153,119,5,19,155,49,187,74,154,243,209,125,141,137,53,48,140,75,95,7,142,13,225,94,143,207,139,105,138,128,157,236,139,66,247,219,137,4,73,130,136,198,35,181,131,154,100,136,130,88,14,191,128,30,176,230,129,220,218,209,132,147,204,84,133,81,166,99,135,23,24,58,134,213,114,13,169,226,208,160,168,32,186,151,170,102,4,206,171,164,110,249,174,235,120,124,175,41,18,75,173,111,172,18,172,173,198,37,167,241,129,24,166,51,235,47,164,117,85,118,165,183,63,65,160,248,41,196,161,58,67,243,163,124,253,170,162,190,151,157,181,196,115,208,180,6,25,231,182,64,167,190,183,130,205,137,178,205,219,12,179,15,177,59,177,73,15,98,176,139,101,85,187,215,34,104,186,21,72,95,184,83,246,6,185,145,156,49,188,222,138,180,189,28,224,131,191,90,94,218,190,152,52,237,0,0,0,0,184,188,103,101,170,9,200,139,18,181,175,238,143,98,151,87,55,222,240,50,37,107,95,220,157,215,56,185,197,180,40,239,125,8,79,138,111,189,224,100,215,1,135,1,74,214,191,184,242,106,216,221,224,223,119,51,88,99,16,86,80,25,87,159,232,165,48,250,250,16,159,20,66,172,248,113,223,123,192,200,103,199,167,173,117,114,8,67,205,206,111,38,149,173,127,112,45,17,24,21,63,164,183,251,135,24,208,158,26,207,232,39,162,115,143,66,176,198,32,172,8,122,71,201,160,50,175,62,24,142,200,91,10,59,103,181,178,135,0,208,47,80,56,105,151,236,95,12,133,89,240,226,61,229,151,135,101,134,135,209,221,58,224,180,207,143,79,90,119,51,40,63,234,228,16,134,82,88,119,227,64,237,216,13,248,81,191,104,240,43,248,161,72,151,159,196,90,34,48,42,226,158,87,79,127,73,111,246,199,245,8,147,213,64,167,125,109,252,192,24,53,159,208,78,141,35,183,43,159,150,24,197,39,42,127,160,186,253,71,25,2,65,32,124,16,244,143,146,168,72,232,247,155,20,88,61,35,168,63,88,49,29,144,182,137,161,247,211,20,118,207,106,172,202,168,15,190,127,7,225,6,195,96,132,94,160,112,210,230,28,23,183,244,169,184,89,76,21,223,60,209,194,231,133,105,126,128,224,123,203,47,14,195,119,72,107,203,13,15,162,115,177,104,199,97,4,199,41,217,184,160,76,68,111,152,245,252,211,255,144,238,102,80,126,86,218,55,27,14,185,39,77,182,5,64,40,164,176,239,198,28,12,136,163,129,219,176,26,57,103,215,127,43,210,120,145,147,110,31,244,59,38,247,3,131,154,144,102,145,47,63,136,41,147,88,237,180,68,96,84,12,248,7,49,30,77,168,223,166,241,207,186,254,146,223,236,70,46,184,137,84,155,23,103,236,39,112,2,113,240,72,187,201,76,47,222,219,249,128,48,99,69,231,85], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+10336); +/* memory initializer */ allocate([107,63,160,156,211,131,199,249,193,54,104,23,121,138,15,114,228,93,55,203,92,225,80,174,78,84,255,64,246,232,152,37,174,139,136,115,22,55,239,22,4,130,64,248,188,62,39,157,33,233,31,36,153,85,120,65,139,224,215,175,51,92,176,202,237,89,182,59,85,229,209,94,71,80,126,176,255,236,25,213,98,59,33,108,218,135,70,9,200,50,233,231,112,142,142,130,40,237,158,212,144,81,249,177,130,228,86,95,58,88,49,58,167,143,9,131,31,51,110,230,13,134,193,8,181,58,166,109,189,64,225,164,5,252,134,193,23,73,41,47,175,245,78,74,50,34,118,243,138,158,17,150,152,43,190,120,32,151,217,29,120,244,201,75,192,72,174,46,210,253,1,192,106,65,102,165,247,150,94,28,79,42,57,121,93,159,150,151,229,35,241,242,77,107,25,5,245,215,126,96,231,98,209,142,95,222,182,235,194,9,142,82,122,181,233,55,104,0,70,217,208,188,33,188,136,223,49,234,48,99,86,143,34,214,249,97,154,106,158,4,7,189,166,189,191,1,193,216,173,180,110,54,21,8,9,83,29,114,78,154,165,206,41,255,183,123,134,17,15,199,225,116,146,16,217,205,42,172,190,168,56,25,17,70,128,165,118,35,216,198,102,117,96,122,1,16,114,207,174,254,202,115,201,155,87,164,241,34,239,24,150,71,253,173,57,169,69,17,94,204,118,77,238,6,206,241,137,99,220,68,38,141,100,248,65,232,249,47,121,81,65,147,30,52,83,38,177,218,235,154,214,191,179,249,198,233,11,69,161,140,25,240,14,98,161,76,105,7,60,155,81,190,132,39,54,219,150,146,153,53,46,46,254,80,38,84,185,153,158,232,222,252,140,93,113,18,52,225,22,119,169,54,46,206,17,138,73,171,3,63,230,69,187,131,129,32,227,224,145,118,91,92,246,19,73,233,89,253,241,85,62,152,108,130,6,33,212,62,97,68,198,139,206,170,126,55,169,207,214,127,65,56,110,195,38,93,124,118,137,179,196,202,238,214,89,29,214,111,225,161,177,10,243,20,30,228,75,168,121,129,19,203,105,215,171,119,14,178,185,194,161,92,1,126,198,57,156,169,254,128,36,21,153,229,54,160,54,11,142,28,81,110,134,102,22,167,62,218,113,194,44,111,222,44,148,211,185,73,9,4,129,240,177,184,230,149,163,13,73,123,27,177,46,30,67,210,62,72,251,110,89,45,233,219,246,195,81,103,145,166,204,176,169,31,116,12,206,122,102,185,97,148,222,5,6,241,0,0,0,0,0,0,0,0,1,0,0,0,4,0,4,0,8,0,4,0,2,0,0,0,4,0,5,0,16,0,8,0,2,0,0,0,4,0,6,0,32,0,32,0,2,0,0,0,4,0,4,0,16,0,16,0,3,0,0,0,8,0,16,0,32,0,32,0,3,0,0,0,8,0,16,0,128,0,128,0,3,0,0,0,8,0,32,0,128,0,0,1,3,0,0,0,32,0,128,0,2,1,0,4,3,0,0,0,32,0,2,1,2,1,0,16,3,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,58,32,0,0,0,0,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,49,46,50,46,53,0,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,117,110,101,120,112,101,99,116,101,100,32,101,110,100,32,111,102,32,102,105,108,101,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,105,110,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,99,111,109,112,114,101,115,115,101,100,32,100,97,116,97,32,101,114,114,111,114,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,114,101,113,117,101,115,116,101,100,32,108,101,110,103,116,104,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,105,110,116,0,0,0,0,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,100,101,102,108,97,116,101,32,115,116,114,101,97,109,32,99,111,114,114,117,112,116,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,49,46,50,46,53,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,16,0,17,0,18,0,0,0,8,0,7,0,9,0,6,0,10,0,5,0,11,0,4,0,12,0,3,0,13,0,2,0,14,0,1,0,15,0,0,0,105,110,99,111,114,114,101,99,116,32,104,101,97,100,101,114,32,99,104,101,99,107,0,0,117,110,107,110,111,119,110,32,99,111,109,112,114,101,115,115,105,111,110,32,109,101,116,104,111,100,0,0,0,0,0,0,105,110,118,97,108,105,100,32,119,105,110,100,111,119,32,115,105,122,101,0,0,0,0,0,117,110,107,110,111,119,110,32,104,101,97,100,101,114,32,102,108,97,103,115,32,115,101,116,0,0,0,0,0,0,0,0,104,101,97,100,101,114,32,99,114,99,32,109,105,115,109,97,116,99,104,0,0,0,0,0,105,110,118,97,108,105,100,32,98,108,111,99,107,32,116,121,112,101,0,0,0,0,0,0,105,110,118,97,108,105,100,32,115,116,111,114,101,100,32,98,108,111,99,107,32,108,101,110,103,116,104,115,0,0,0,0,116,111,111,32,109,97,110,121,32,108,101,110,103,116,104,32,111,114,32,100,105,115,116,97,110,99,101,32,115,121,109,98,111,108,115,0,0,0,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,0,0,0,105,110,118,97,108,105,100,32,98,105,116,32,108,101,110,103,116,104,32,114,101,112,101,97,116,0,0,0,0,0,0,0,105,110,118,97,108,105,100,32,99,111,100,101,32,45,45,32,109,105,115,115,105,110,103,32,101,110,100,45,111,102,45,98,108,111,99,107,0,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,115,32,115,101,116,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,115,32,115,101,116,0,0,0,105,110,118,97,108,105,100,32,108,105,116,101,114,97,108,47,108,101,110,103,116,104,32,99,111,100,101,0,0,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,99,111,100,101,0,0,0,105,110,118,97,108,105,100,32,100,105,115,116,97,110,99,101,32,116,111,111,32,102,97,114,32,98,97,99,107,0,0,0,105,110,99,111,114,114,101,99,116,32,100,97,116,97,32,99,104,101,99,107,0,0,0,0,105,110,99,111,114,114,101,99,116,32,108,101,110,103,116,104,32,99,104,101,99,107,0,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,192,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,160,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,224,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,144,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,208,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,176,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,240,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,200,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,168,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,232,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,152,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,216,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,184,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,248,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,196,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,164,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,228,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,148,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,212,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,180,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,244,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,204,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,172,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,236,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,156,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,220,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,188,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,252,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,194,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,162,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,226,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,146,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,210,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,178,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,242,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,202,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,170,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,234,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,154,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,218,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,186,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,250,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,198,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,166,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,230,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,150,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,214,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,182,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,246,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,206,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,174,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,238,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,158,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,222,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,190,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,254,0,96,7,0,0,0,8,80,0,0,8,16,0,20,8,115,0,18,7,31,0,0,8,112,0,0,8,48,0,0,9,193,0,16,7,10,0,0,8,96,0,0,8,32,0,0,9,161,0,0,8,0,0,0,8,128,0,0,8,64,0,0,9,225,0,16,7,6,0,0,8,88,0,0,8,24,0,0,9,145,0,19,7,59,0,0,8,120,0,0,8,56,0,0,9,209,0,17,7,17,0,0,8,104,0,0,8,40,0,0,9,177,0,0,8,8,0,0,8,136,0,0,8,72,0,0,9,241,0,16,7,4,0,0,8,84,0,0,8,20,0,21,8,227,0,19,7,43,0,0,8,116,0,0,8,52,0,0,9,201,0,17,7,13,0,0,8,100,0,0,8,36,0,0,9,169,0,0,8,4,0,0,8,132,0,0,8,68,0,0,9,233,0,16,7,8,0,0,8,92,0,0,8,28,0,0,9,153,0,20,7,83,0,0,8,124,0,0,8,60,0,0,9,217,0,18,7,23,0,0,8,108,0,0,8,44,0,0,9,185,0,0,8,12,0,0,8,140,0,0,8,76,0,0,9,249,0,16,7,3,0,0,8,82,0,0,8,18,0,21,8,163,0,19,7,35,0,0,8,114,0,0,8,50,0,0,9,197,0,17,7,11,0,0,8,98,0,0,8,34,0,0,9,165,0,0,8,2,0,0,8,130,0,0,8,66,0,0,9,229,0,16,7,7,0,0,8,90,0,0,8,26,0,0,9,149,0,20,7,67,0,0,8,122,0,0,8,58,0,0,9,213,0,18,7,19,0,0,8,106,0,0,8,42,0,0,9,181,0,0,8,10,0,0,8,138,0,0,8,74,0,0,9,245,0,16,7,5,0,0,8,86,0,0,8,22,0,64,8,0,0,19,7,51,0,0,8,118,0,0,8,54,0,0,9,205,0,17,7,15,0,0,8,102,0,0,8,38,0,0,9,173,0,0,8,6,0,0,8,134,0,0,8,70,0,0,9,237,0,16,7,9,0,0,8,94,0,0,8,30,0,0,9,157,0,20,7,99,0,0,8,126,0,0,8,62,0,0,9,221,0,18,7,27,0,0,8,110,0,0,8,46,0,0,9,189,0,0,8,14,0,0,8,142,0,0,8,78,0,0,9,253,0,96,7,0,0,0,8,81,0,0,8,17,0,21,8,131,0,18,7,31,0,0,8,113,0,0,8,49,0,0,9,195,0,16,7,10,0,0,8,97,0,0,8,33,0,0,9,163,0,0,8,1,0,0,8,129,0,0,8,65,0,0,9,227,0,16,7,6,0,0,8,89,0,0,8,25,0,0,9,147,0,19,7,59,0,0,8,121,0,0,8,57,0,0,9,211,0,17,7,17,0,0,8,105,0,0,8,41,0,0,9,179,0,0,8,9,0,0,8,137,0,0,8,73,0,0,9,243,0,16,7,4,0,0,8,85,0,0,8,21,0,16,8,2,1,19,7,43,0,0,8,117,0,0,8,53,0,0,9,203,0,17,7,13,0,0,8,101,0,0,8,37,0,0,9,171,0,0,8,5,0,0,8,133,0,0,8,69,0,0,9,235,0,16,7,8,0,0,8,93,0,0,8,29,0,0,9,155,0,20,7,83,0,0,8,125,0,0,8,61,0,0,9,219,0,18,7,23,0,0,8,109,0,0,8,45,0,0,9,187,0,0,8,13,0,0,8,141,0,0,8,77,0,0,9,251,0,16,7,3,0,0,8,83,0,0,8,19,0,21,8,195,0,19,7,35,0,0,8,115,0,0,8,51,0,0,9,199,0,17,7,11,0,0,8,99,0,0,8,35,0,0,9,167,0,0,8,3,0,0,8,131,0,0,8,67,0,0,9,231,0,16,7,7,0,0,8,91,0,0,8,27,0,0,9,151,0,20,7,67,0,0,8,123,0,0,8,59,0,0,9,215,0,18,7,19,0,0,8,107,0,0,8,43,0,0,9,183,0,0,8,11,0,0,8,139,0,0,8,75,0,0,9,247,0,16,7,5,0,0,8,87,0,0,8,23,0,64,8,0,0,19,7,51,0,0,8,119,0,0,8,55,0,0,9,207,0,17,7,15,0,0,8,103,0,0,8,39,0,0,9,175,0,0,8,7,0,0,8,135,0,0,8,71,0,0,9,239,0,16,7,9,0,0,8,95,0,0,8,31,0,0,9,159,0,20,7,99,0,0,8,127,0,0,8,63,0,0,9,223,0,18,7,27,0,0,8,111,0,0,8,47,0,0,9,191,0,0,8,15,0,0,8,143,0,0,8,79,0,0,9,255,0,16,5,1,0,23,5,1,1,19,5,17,0,27,5,1,16,17,5,5,0,25,5,1,4,21,5,65,0,29,5,1,64,16,5,3,0,24,5,1,2,20,5,33,0,28,5,1,32,18,5,9,0,26,5,1,8,22,5,129,0,64,5,0,0,16,5,2,0,23,5,129,1,19,5,25,0,27,5,1,24,17,5,7,0,25,5,1,6,21,5,97,0,29,5,1,96,16,5,4,0,24,5,1,3,20,5,49,0,28,5,1,48,18,5,13,0,26,5,1,12,22,5,193,0,64,5,0,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,13,0,15,0,17,0,19,0,23,0,27,0,31,0,35,0,43,0,51,0,59,0,67,0,83,0,99,0,115,0,131,0,163,0,195,0,227,0,2,1,0,0,0,0,0,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,17,0,17,0,17,0,17,0,18,0,18,0,18,0,18,0,19,0,19,0,19,0,19,0,20,0,20,0,20,0,20,0,21,0,21,0,21,0,21,0,16,0,73,0,195,0,0,0,1,0,2,0,3,0,4,0,5,0,7,0,9,0,13,0,17,0,25,0,33,0,49,0,65,0,97,0,129,0,193,0,1,1,129,1,1,2,1,3,1,4,1,6,1,8,1,12,1,16,1,24,1,32,1,48,1,64,1,96,0,0,0,0,16,0,16,0,16,0,16,0,17,0,17,0,18,0,18,0,19,0,19,0,20,0,20,0,21,0,21,0,22,0,22,0,23,0,23,0,24,0,24,0,25,0,25,0,26,0,26,0,27,0,27,0,28,0,28,0,29,0,29,0,64,0,64,0,0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,0,100,0,0,248,104,0,0,1,1,0,0,30,1,0,0,15,0,0,0,0,0,0,0,128,104,0,0,232,105,0,0,0,0,0,0,30,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,240,106,0,0,0,0,0,0,19,0,0,0,7,0,0,0,0,0,0,0,12,0,8,0,140,0,8,0,76,0,8,0,204,0,8,0,44,0,8,0,172,0,8,0,108,0,8,0,236,0,8,0,28,0,8,0,156,0,8,0,92,0,8,0,220,0,8,0,60,0,8,0,188,0,8,0,124,0,8,0,252,0,8,0,2,0,8,0,130,0,8,0,66,0,8,0,194,0,8,0,34,0,8,0,162,0,8,0,98,0,8,0,226,0,8,0,18,0,8,0,146,0,8,0,82,0,8,0,210,0,8,0,50,0,8,0,178,0,8,0,114,0,8,0,242,0,8,0,10,0,8,0,138,0,8,0,74,0,8,0,202,0,8,0,42,0,8,0,170,0,8,0,106,0,8,0,234,0,8,0,26,0,8,0,154,0,8,0,90,0,8,0,218,0,8,0,58,0,8,0,186,0,8,0,122,0,8,0,250,0,8,0,6,0,8,0,134,0,8,0,70,0,8,0,198,0,8,0,38,0,8,0,166,0,8,0,102,0,8,0,230,0,8,0,22,0,8,0,150,0,8,0,86,0,8,0,214,0,8,0,54,0,8,0,182,0,8,0,118,0,8,0,246,0,8,0,14,0,8,0,142,0,8,0,78,0,8,0,206,0,8,0,46,0,8,0,174,0,8,0,110,0,8,0,238,0,8,0,30,0,8,0,158,0,8,0,94,0,8,0,222,0,8,0,62,0,8,0,190,0,8,0,126,0,8,0,254,0,8,0,1,0,8,0,129,0,8,0,65,0,8,0,193,0,8,0,33,0,8,0,161,0,8,0,97,0,8,0,225,0,8,0,17,0,8,0,145,0,8,0,81,0,8,0,209,0,8,0,49,0,8,0,177,0,8,0,113,0,8,0,241,0,8,0,9,0,8,0,137,0,8,0,73,0,8,0,201,0,8,0,41,0,8,0,169,0,8,0,105,0,8,0,233,0,8,0,25,0,8,0,153,0,8,0,89,0,8,0,217,0,8,0,57,0,8,0,185,0,8,0,121,0,8,0,249,0,8,0,5,0,8,0,133,0,8,0,69,0,8,0,197,0,8,0,37,0,8,0,165,0,8,0,101,0,8,0,229,0,8,0,21,0,8,0,149,0,8,0,85,0,8,0,213,0,8,0,53,0,8,0,181,0,8,0,117,0,8,0,245,0,8,0,13,0,8,0,141,0,8,0,77,0,8,0,205,0,8,0,45,0,8,0,173,0,8,0,109,0,8,0,237,0,8,0,29,0,8,0,157,0,8,0,93,0,8,0,221,0,8,0,61,0,8,0,189,0,8,0,125,0,8,0,253,0,8,0,19,0,9,0,19,1,9,0,147,0,9,0,147,1,9,0,83,0,9,0,83,1,9,0,211,0,9,0,211,1,9,0,51,0,9,0,51,1,9,0,179,0,9,0,179,1,9,0,115,0,9,0,115,1,9,0,243,0,9,0,243,1,9,0,11,0,9,0,11,1,9,0,139,0,9,0,139,1,9,0,75,0,9,0,75,1,9,0,203,0,9,0,203,1,9,0,43,0,9,0,43,1,9,0,171,0,9,0,171,1,9,0,107,0,9,0,107,1,9,0,235,0,9,0,235,1,9,0,27,0,9,0,27,1,9,0,155,0,9,0,155,1,9,0,91,0,9,0,91,1,9,0,219,0,9,0,219,1,9,0,59,0,9,0,59,1,9,0,187,0,9,0,187,1,9,0,123,0,9,0,123,1,9,0,251,0,9,0,251,1,9,0,7,0,9,0,7,1,9,0,135,0,9,0,135,1,9,0,71,0,9,0,71,1,9,0,199,0,9,0,199,1,9,0,39,0,9,0,39,1,9,0,167,0,9,0,167,1,9,0,103,0,9,0,103,1,9,0,231,0,9,0,231,1,9,0,23,0,9,0,23,1,9,0,151,0,9,0,151,1,9,0,87,0,9,0,87,1,9,0,215,0,9,0,215,1,9,0,55,0,9,0,55,1,9,0,183,0,9,0,183,1,9,0,119,0,9,0,119,1,9,0,247,0,9,0,247,1,9,0,15,0,9,0,15,1,9,0,143,0,9,0,143,1,9,0,79,0,9,0,79,1,9,0,207,0,9,0,207,1,9,0,47,0,9,0,47,1,9,0,175,0,9,0,175,1,9,0,111,0,9,0,111,1,9,0,239,0,9,0,239,1,9,0,31,0,9,0,31,1,9,0,159,0,9,0,159,1,9,0,95,0,9,0,95,1,9,0,223,0,9,0,223,1,9,0,63,0,9,0,63,1,9,0,191,0,9,0,191,1,9,0,127,0,9,0,127,1,9,0,255,0,9,0,255,1,9,0,0,0,7,0,64,0,7,0,32,0,7,0,96,0,7,0,16,0,7,0,80,0,7,0,48,0,7,0,112,0,7,0,8,0,7,0,72,0,7,0,40,0,7,0,104,0,7,0,24,0,7,0,88,0,7,0,56,0,7,0,120,0,7,0,4,0,7,0,68,0,7,0,36,0,7,0,100,0,7,0,20,0,7,0,84,0,7,0,52,0,7,0,116,0,7,0,3,0,8,0,131,0,8,0,67,0,8,0,195,0,8,0,35,0,8,0,163,0,8,0,99,0,8,0,227,0,8,0,0,0,5,0,16,0,5,0,8,0,5,0,24,0,5,0,4,0,5,0,20,0,5,0,12,0,5,0,28,0,5,0,2,0,5,0,18,0,5,0,10,0,5,0,26,0,5,0,6,0,5,0,22,0,5,0,14,0,5,0,30,0,5,0,1,0,5,0,17,0,5,0,9,0,5,0,25,0,5,0,5,0,5,0,21,0,5,0,13,0,5,0,29,0,5,0,3,0,5,0,19,0,5,0,11,0,5,0,27,0,5,0,7,0,5,0,23,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,8,0,0,0,10,0,0,0,12,0,0,0,14,0,0,0,16,0,0,0,20,0,0,0,24,0,0,0,28,0,0,0,32,0,0,0,40,0,0,0,48,0,0,0,56,0,0,0,64,0,0,0,80,0,0,0,96,0,0,0,112,0,0,0,128,0,0,0,160,0,0,0,192,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,5,0,0,0,6,0,0,0,6,0,0,0,7,0,0,0,7,0,0,0,8,0,0,0,8,0,0,0,9,0,0,0,9,0,0,0,10,0,0,0,10,0,0,0,11,0,0,0,11,0,0,0,12,0,0,0,12,0,0,0,13,0,0,0,13,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,0,128,0,0,0,192,0,0,0,0,1,0,0,128,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,12,0,0,0,16,0,0,0,24,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,96,0,0,16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,7,0,0,0,0,0,0,0,110,101,101,100,32,100,105,99,116,105,111,110,97,114,121,0,115,116,114,101,97,109,32,101,110,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,105,108,101,32,101,114,114,111,114,0,0,0,0,0,0,115,116,114,101,97,109,32,101,114,114,111,114,0,0,0,0,100,97,116,97,32,101,114,114,111,114,0,0,0,0,0,0,105,110,115,117,102,102,105,99,105,101,110,116,32,109,101,109,111,114,121,0,0,0,0,0,98,117,102,102,101,114,32,101,114,114,111,114,0,0,0,0,105,110,99,111,109,112,97,116,105,98,108,101,32,118,101,114,115,105,111,110,0,0,0,0,64,107,0,0,80,107,0,0,96,107,0,0,104,107,0,0,120,107,0,0,136,107,0,0,152,107,0,0,176,107,0,0,192,107,0,0,96,107,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,105,110,102,105,110,105,116,121,0,0,0,0,0,0,0,0,110,97,110,0,0,0,0,0,95,112,137,0,255,9,47,15,10,0,0,0,100,0,0,0,232,3,0,0,16,39,0,0,160,134,1,0,64,66,15,0,128,150,152,0,0,225,245,5], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE+20576); + + + + +var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8); + +assert(tempDoublePtr % 8 == 0); + +function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much + + HEAP8[tempDoublePtr] = HEAP8[ptr]; + + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + +} + +function copyTempDouble(ptr) { + + HEAP8[tempDoublePtr] = HEAP8[ptr]; + + HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; + + HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; + + HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; + + HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; + + HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; + + HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; + + HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; + +} + + + + + var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86}; + + var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"}; + + + var ___errno_state=0;function ___setErrNo(value) { + // For convenient setting and returning of errno. + HEAP32[((___errno_state)>>2)]=value; + return value; + } + + var PATH={splitPath:function (filename) { + var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + return splitPathRe.exec(filename).slice(1); + },normalizeArray:function (parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + 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 the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + return parts; + },normalize:function (path) { + var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.substr(-1) === '/'; + // Normalize the path + path = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), !isAbsolute).join('/'); + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + return (isAbsolute ? '/' : '') + path; + },dirname:function (path) { + var result = PATH.splitPath(path), + root = result[0], + dir = result[1]; + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + return root + dir; + },basename:function (path) { + // EMSCRIPTEN return '/'' for '/', not an empty string + if (path === '/') return '/'; + var lastSlash = path.lastIndexOf('/'); + if (lastSlash === -1) return path; + return path.substr(lastSlash+1); + },extname:function (path) { + return PATH.splitPath(path)[3]; + },join:function () { + var paths = Array.prototype.slice.call(arguments, 0); + return PATH.normalize(paths.join('/')); + },join2:function (l, r) { + return PATH.normalize(l + '/' + r); + },resolve:function () { + var resolvedPath = '', + resolvedAbsolute = false; + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : FS.cwd(); + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + },relative:function (from, to) { + from = PATH.resolve(from).substr(1); + to = PATH.resolve(to).substr(1); + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + var end = arr.length - 1; + for (; end >= 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 < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + return outputParts.join('/'); + }}; + + var TTY={ttys:[],init:function () { + // https://github.com/kripken/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // currently, FS.init does not distinguish if process.stdin is a file or TTY + // // device, it always assumes it's a TTY device. because of this, we're forcing + // // process.stdin to UTF8 encoding to at least make stdin reading compatible + // // with text files until FS.init can be refactored. + // process['stdin']['setEncoding']('utf8'); + // } + },shutdown:function () { + // https://github.com/kripken/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? + // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation + // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists? + // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle + // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call + // process['stdin']['pause'](); + // } + },register:function (dev, ops) { + TTY.ttys[dev] = { input: [], output: [], ops: ops }; + FS.registerDevice(dev, TTY.stream_ops); + },stream_ops:{open:function (stream) { + var tty = TTY.ttys[stream.node.rdev]; + if (!tty) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + stream.tty = tty; + stream.seekable = false; + },close:function (stream) { + // flush any pending line data + if (stream.tty.output.length) { + stream.tty.ops.put_char(stream.tty, 10); + } + },read:function (stream, buffer, offset, length, pos /* ignored */) { + if (!stream.tty || !stream.tty.ops.get_char) { + throw new FS.ErrnoError(ERRNO_CODES.ENXIO); + } + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = stream.tty.ops.get_char(stream.tty); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + },write:function (stream, buffer, offset, length, pos) { + if (!stream.tty || !stream.tty.ops.put_char) { + throw new FS.ErrnoError(ERRNO_CODES.ENXIO); + } + for (var i = 0; i < length; i++) { + try { + stream.tty.ops.put_char(stream.tty, buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + }},default_tty_ops:{get_char:function (tty) { + if (!tty.input.length) { + var result = null; + if (ENVIRONMENT_IS_NODE) { + result = process['stdin']['read'](); + if (!result) { + if (process['stdin']['_readableState'] && process['stdin']['_readableState']['ended']) { + return null; // EOF + } + return undefined; // no data available + } + } else if (typeof window != 'undefined' && + typeof window.prompt == 'function') { + // Browser. + result = window.prompt('Input: '); // returns null on cancel + if (result !== null) { + result += '\n'; + } + } else if (typeof readline == 'function') { + // Command line. + result = readline(); + if (result !== null) { + result += '\n'; + } + } + if (!result) { + return null; + } + tty.input = intArrayFromString(result, true); + } + return tty.input.shift(); + },put_char:function (tty, val) { + if (val === null || val === 10) { + Module['print'](tty.output.join('')); + tty.output = []; + } else { + tty.output.push(TTY.utf8.processCChar(val)); + } + }},default_tty1_ops:{put_char:function (tty, val) { + if (val === null || val === 10) { + Module['printErr'](tty.output.join('')); + tty.output = []; + } else { + tty.output.push(TTY.utf8.processCChar(val)); + } + }}}; + + var MEMFS={ops_table:null,CONTENT_OWNING:1,CONTENT_FLEXIBLE:2,CONTENT_FIXED:3,mount:function (mount) { + return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + },createNode:function (parent, name, mode, dev) { + if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { + // no supported + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (!MEMFS.ops_table) { + 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, + allocate: MEMFS.stream_ops.allocate, + mmap: MEMFS.stream_ops.mmap + } + }, + 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.contents = []; + node.contentMode = MEMFS.CONTENT_FLEXIBLE; + } 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.timestamp = Date.now(); + // add the new node to the parent + if (parent) { + parent.contents[name] = node; + } + return node; + },ensureFlexible:function (node) { + if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) { + var contents = node.contents; + node.contents = Array.prototype.slice.call(contents); + node.contentMode = MEMFS.CONTENT_FLEXIBLE; + } + },node_ops:{getattr:function (node) { + var attr = {}; + // device numbers reuse inode numbers. + 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.contents.length; + } else if (FS.isLink(node.mode)) { + attr.size = node.link.length; + } else { + attr.size = 0; + } + attr.atime = new Date(node.timestamp); + attr.mtime = new Date(node.timestamp); + attr.ctime = new Date(node.timestamp); + // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), + // but this is not required by the standard. + attr.blksize = 4096; + attr.blocks = Math.ceil(attr.size / attr.blksize); + return attr; + },setattr:function (node, attr) { + if (attr.mode !== undefined) { + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + node.timestamp = attr.timestamp; + } + if (attr.size !== undefined) { + MEMFS.ensureFlexible(node); + var contents = node.contents; + if (attr.size < contents.length) contents.length = attr.size; + else while (attr.size > contents.length) contents.push(0); + } + },lookup:function (parent, name) { + throw FS.genericErrors[ERRNO_CODES.ENOENT]; + },mknod:function (parent, name, mode, dev) { + return MEMFS.createNode(parent, name, mode, dev); + },rename:function (old_node, new_dir, new_name) { + // if we're overwriting a directory at new_name, make sure it's empty. + if (FS.isDir(old_node.mode)) { + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + } + if (new_node) { + for (var i in new_node.contents) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + } + } + // do the internal rewiring + delete old_node.parent.contents[old_node.name]; + old_node.name = new_name; + new_dir.contents[new_name] = old_node; + old_node.parent = new_dir; + },unlink:function (parent, name) { + delete parent.contents[name]; + },rmdir:function (parent, name) { + var node = FS.lookupNode(parent, name); + for (var i in node.contents) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + delete parent.contents[name]; + },readdir:function (node) { + var entries = ['.', '..'] + for (var key in node.contents) { + if (!node.contents.hasOwnProperty(key)) { + continue; + } + entries.push(key); + } + return entries; + },symlink:function (parent, newname, oldpath) { + var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0); + node.link = oldpath; + return node; + },readlink:function (node) { + if (!FS.isLink(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + return node.link; + }},stream_ops:{read:function (stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (size > 8 && contents.subarray) { // non-trivial, and typed array + buffer.set(contents.subarray(position, position + size), offset); + } else + { + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } + return size; + },write:function (stream, buffer, offset, length, position, canOwn) { + var node = stream.node; + node.timestamp = Date.now(); + var contents = node.contents; + if (length && contents.length === 0 && position === 0 && buffer.subarray) { + // just replace it with the new data + if (canOwn && offset === 0) { + node.contents = buffer; // this could be a subarray of Emscripten HEAP, or allocated from some other source. + node.contentMode = (buffer.buffer === HEAP8.buffer) ? MEMFS.CONTENT_OWNING : MEMFS.CONTENT_FIXED; + } else { + node.contents = new Uint8Array(buffer.subarray(offset, offset+length)); + node.contentMode = MEMFS.CONTENT_FIXED; + } + return length; + } + MEMFS.ensureFlexible(node); + var contents = node.contents; + while (contents.length < position) contents.push(0); + for (var i = 0; i < length; i++) { + contents[position + i] = buffer[offset + i]; + } + return length; + },llseek:function (stream, offset, whence) { + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + if (FS.isFile(stream.node.mode)) { + position += stream.node.contents.length; + } + } + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + stream.ungotten = []; + stream.position = position; + return position; + },allocate:function (stream, offset, length) { + MEMFS.ensureFlexible(stream.node); + var contents = stream.node.contents; + var limit = offset + length; + while (limit > contents.length) contents.push(0); + },mmap:function (stream, buffer, offset, length, position, prot, flags) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + var ptr; + var allocated; + var contents = stream.node.contents; + // Only make a new copy when MAP_PRIVATE is specified. + if ( !(flags & 2) && + (contents.buffer === buffer || contents.buffer === buffer.buffer) ) { + // We can't emulate MAP_SHARED when the file is not backed by the buffer + // we're mapping to (e.g. the HEAP buffer). + allocated = false; + ptr = contents.byteOffset; + } else { + // Try to avoid unnecessary slices. + if (position > 0 || position + length < contents.length) { + if (contents.subarray) { + contents = contents.subarray(position, position + length); + } else { + contents = Array.prototype.slice.call(contents, position, position + length); + } + } + allocated = true; + ptr = _malloc(length); + if (!ptr) { + throw new FS.ErrnoError(ERRNO_CODES.ENOMEM); + } + buffer.set(contents, ptr); + } + return { ptr: ptr, allocated: allocated }; + }}}; + + var IDBFS={dbs:{},indexedDB:function () { + return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + },DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:function (mount) { + // reuse all of the core MEMFS functionality + return MEMFS.mount.apply(null, arguments); + },syncfs:function (mount, populate, callback) { + IDBFS.getLocalSet(mount, function(err, local) { + if (err) return callback(err); + + IDBFS.getRemoteSet(mount, function(err, remote) { + if (err) return callback(err); + + var src = populate ? remote : local; + var dst = populate ? local : remote; + + IDBFS.reconcile(src, dst, callback); + }); + }); + },getDB:function (name, callback) { + // check the cache first + var db = IDBFS.dbs[name]; + if (db) { + return callback(null, db); + } + + var req; + try { + req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION); + } catch (e) { + return callback(e); + } + req.onupgradeneeded = function(e) { + var db = e.target.result; + var transaction = e.target.transaction; + + var fileStore; + + if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) { + fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME); + } else { + fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME); + } + + fileStore.createIndex('timestamp', 'timestamp', { unique: false }); + }; + req.onsuccess = function() { + db = req.result; + + // add to the cache + IDBFS.dbs[name] = db; + callback(null, db); + }; + req.onerror = function() { + callback(this.error); + }; + },getLocalSet:function (mount, callback) { + var entries = {}; + + function isRealDir(p) { + return p !== '.' && p !== '..'; + }; + function toAbsolute(root) { + return function(p) { + return PATH.join2(root, p); + } + }; + + var check = FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint)); + + while (check.length) { + var path = check.pop(); + var stat; + + try { + stat = FS.stat(path); + } catch (e) { + return callback(e); + } + + if (FS.isDir(stat.mode)) { + check.push.apply(check, FS.readdir(path).filter(isRealDir).map(toAbsolute(path))); + } + + entries[path] = { timestamp: stat.mtime }; + } + + return callback(null, { type: 'local', entries: entries }); + },getRemoteSet:function (mount, callback) { + var entries = {}; + + IDBFS.getDB(mount.mountpoint, function(err, db) { + if (err) return callback(err); + + var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readonly'); + transaction.onerror = function() { callback(this.error); }; + + var store = transaction.objectStore(IDBFS.DB_STORE_NAME); + var index = store.index('timestamp'); + + index.openKeyCursor().onsuccess = function(event) { + var cursor = event.target.result; + + if (!cursor) { + return callback(null, { type: 'remote', db: db, entries: entries }); + } + + entries[cursor.primaryKey] = { timestamp: cursor.key }; + + cursor.continue(); + }; + }); + },loadLocalEntry:function (path, callback) { + var stat, node; + + try { + var lookup = FS.lookupPath(path); + node = lookup.node; + stat = FS.stat(path); + } catch (e) { + return callback(e); + } + + if (FS.isDir(stat.mode)) { + return callback(null, { timestamp: stat.mtime, mode: stat.mode }); + } else if (FS.isFile(stat.mode)) { + return callback(null, { timestamp: stat.mtime, mode: stat.mode, contents: node.contents }); + } else { + return callback(new Error('node type not supported')); + } + },storeLocalEntry:function (path, entry, callback) { + try { + if (FS.isDir(entry.mode)) { + FS.mkdir(path, entry.mode); + } else if (FS.isFile(entry.mode)) { + FS.writeFile(path, entry.contents, { encoding: 'binary', canOwn: true }); + } else { + return callback(new Error('node type not supported')); + } + + FS.utime(path, entry.timestamp, entry.timestamp); + } catch (e) { + return callback(e); + } + + callback(null); + },removeLocalEntry:function (path, callback) { + try { + var lookup = FS.lookupPath(path); + var stat = FS.stat(path); + + if (FS.isDir(stat.mode)) { + FS.rmdir(path); + } else if (FS.isFile(stat.mode)) { + FS.unlink(path); + } + } catch (e) { + return callback(e); + } + + callback(null); + },loadRemoteEntry:function (store, path, callback) { + var req = store.get(path); + req.onsuccess = function(event) { callback(null, event.target.result); }; + req.onerror = function() { callback(this.error); }; + },storeRemoteEntry:function (store, path, entry, callback) { + var req = store.put(entry, path); + req.onsuccess = function() { callback(null); }; + req.onerror = function() { callback(this.error); }; + },removeRemoteEntry:function (store, path, callback) { + var req = store.delete(path); + req.onsuccess = function() { callback(null); }; + req.onerror = function() { callback(this.error); }; + },reconcile:function (src, dst, callback) { + var total = 0; + + var create = []; + Object.keys(src.entries).forEach(function (key) { + var e = src.entries[key]; + var e2 = dst.entries[key]; + if (!e2 || e.timestamp > e2.timestamp) { + create.push(key); + total++; + } + }); + + var remove = []; + Object.keys(dst.entries).forEach(function (key) { + var e = dst.entries[key]; + var e2 = src.entries[key]; + if (!e2) { + remove.push(key); + total++; + } + }); + + if (!total) { + return callback(null); + } + + var errored = false; + var completed = 0; + var db = src.type === 'remote' ? src.db : dst.db; + var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite'); + var store = transaction.objectStore(IDBFS.DB_STORE_NAME); + + function done(err) { + if (err) { + if (!done.errored) { + done.errored = true; + return callback(err); + } + return; + } + if (++completed >= total) { + return callback(null); + } + }; + + transaction.onerror = function() { done(this.error); }; + + // sort paths in ascending order so directory entries are created + // before the files inside them + create.sort().forEach(function (path) { + if (dst.type === 'local') { + IDBFS.loadRemoteEntry(store, path, function (err, entry) { + if (err) return done(err); + IDBFS.storeLocalEntry(path, entry, done); + }); + } else { + IDBFS.loadLocalEntry(path, function (err, entry) { + if (err) return done(err); + IDBFS.storeRemoteEntry(store, path, entry, done); + }); + } + }); + + // sort paths in descending order so files are deleted before their + // parent directories + remove.sort().reverse().forEach(function(path) { + if (dst.type === 'local') { + IDBFS.removeLocalEntry(path, done); + } else { + IDBFS.removeRemoteEntry(store, path, done); + } + }); + }}; + + var NODEFS={isWindows:false,staticInit:function () { + NODEFS.isWindows = !!process.platform.match(/^win/); + },mount:function (mount) { + assert(ENVIRONMENT_IS_NODE); + return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0); + },createNode:function (parent, name, mode, dev) { + if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node = FS.createNode(parent, name, mode); + node.node_ops = NODEFS.node_ops; + node.stream_ops = NODEFS.stream_ops; + return node; + },getMode:function (path) { + var stat; + try { + stat = fs.lstatSync(path); + if (NODEFS.isWindows) { + // On Windows, directories return permission bits 'rw-rw-rw-', even though they have 'rwxrwxrwx', so + // propagate write bits to execute bits. + stat.mode = stat.mode | ((stat.mode & 146) >> 1); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return stat.mode; + },realPath:function (node) { + var parts = []; + while (node.parent !== node) { + parts.push(node.name); + node = node.parent; + } + parts.push(node.mount.opts.root); + parts.reverse(); + return PATH.join.apply(null, parts); + },flagsToPermissionStringMap:{0:"r",1:"r+",2:"r+",64:"r",65:"r+",66:"r+",129:"rx+",193:"rx+",514:"w+",577:"w",578:"w+",705:"wx",706:"wx+",1024:"a",1025:"a",1026:"a+",1089:"a",1090:"a+",1153:"ax",1154:"ax+",1217:"ax",1218:"ax+",4096:"rs",4098:"rs+"},flagsToPermissionString:function (flags) { + if (flags in NODEFS.flagsToPermissionStringMap) { + return NODEFS.flagsToPermissionStringMap[flags]; + } else { + return flags; + } + },node_ops:{getattr:function (node) { + var path = NODEFS.realPath(node); + var stat; + try { + stat = fs.lstatSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + // node.js v0.10.20 doesn't report blksize and blocks on Windows. Fake them with default blksize of 4096. + // See http://support.microsoft.com/kb/140365 + if (NODEFS.isWindows && !stat.blksize) { + stat.blksize = 4096; + } + if (NODEFS.isWindows && !stat.blocks) { + stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0; + } + return { + dev: stat.dev, + ino: stat.ino, + mode: stat.mode, + nlink: stat.nlink, + uid: stat.uid, + gid: stat.gid, + rdev: stat.rdev, + size: stat.size, + atime: stat.atime, + mtime: stat.mtime, + ctime: stat.ctime, + blksize: stat.blksize, + blocks: stat.blocks + }; + },setattr:function (node, attr) { + var path = NODEFS.realPath(node); + try { + if (attr.mode !== undefined) { + fs.chmodSync(path, attr.mode); + // update the common node structure mode as well + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + var date = new Date(attr.timestamp); + fs.utimesSync(path, date, date); + } + if (attr.size !== undefined) { + fs.truncateSync(path, attr.size); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },lookup:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + var mode = NODEFS.getMode(path); + return NODEFS.createNode(parent, name, mode); + },mknod:function (parent, name, mode, dev) { + var node = NODEFS.createNode(parent, name, mode, dev); + // create the backing node for this in the fs root as well + var path = NODEFS.realPath(node); + try { + if (FS.isDir(node.mode)) { + fs.mkdirSync(path, node.mode); + } else { + fs.writeFileSync(path, '', { mode: node.mode }); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return node; + },rename:function (oldNode, newDir, newName) { + var oldPath = NODEFS.realPath(oldNode); + var newPath = PATH.join2(NODEFS.realPath(newDir), newName); + try { + fs.renameSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },unlink:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.unlinkSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },rmdir:function (parent, name) { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.rmdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },readdir:function (node) { + var path = NODEFS.realPath(node); + try { + return fs.readdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },symlink:function (parent, newName, oldPath) { + var newPath = PATH.join2(NODEFS.realPath(parent), newName); + try { + fs.symlinkSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },readlink:function (node) { + var path = NODEFS.realPath(node); + try { + return fs.readlinkSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }},stream_ops:{open:function (stream) { + var path = NODEFS.realPath(stream.node); + try { + if (FS.isFile(stream.node.mode)) { + stream.nfd = fs.openSync(path, NODEFS.flagsToPermissionString(stream.flags)); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },close:function (stream) { + try { + if (FS.isFile(stream.node.mode) && stream.nfd) { + fs.closeSync(stream.nfd); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + },read:function (stream, buffer, offset, length, position) { + // FIXME this is terrible. + var nbuffer = new Buffer(length); + var res; + try { + res = fs.readSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + if (res > 0) { + for (var i = 0; i < res; i++) { + buffer[offset + i] = nbuffer[i]; + } + } + return res; + },write:function (stream, buffer, offset, length, position) { + // FIXME this is terrible. + var nbuffer = new Buffer(buffer.subarray(offset, offset + length)); + var res; + try { + res = fs.writeSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return res; + },llseek:function (stream, offset, whence) { + var position = offset; + if (whence === 1) { // SEEK_CUR. + position += stream.position; + } else if (whence === 2) { // SEEK_END. + if (FS.isFile(stream.node.mode)) { + try { + var stat = fs.fstatSync(stream.nfd); + position += stat.size; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + } + } + + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + stream.position = position; + return position; + }}}; + + var _stdin=allocate(1, "i32*", ALLOC_STATIC); + + var _stdout=allocate(1, "i32*", ALLOC_STATIC); + + var _stderr=allocate(1, "i32*", ALLOC_STATIC); + + function _fflush(stream) { + // int fflush(FILE *stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fflush.html + // we don't currently perform any user-space buffering of data + }var FS={root:null,mounts:[],devices:[null],streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},handleFSError:function (e) { + if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace(); + return ___setErrNo(e.errno); + },lookupPath:function (path, opts) { + path = PATH.resolve(FS.cwd(), path); + opts = opts || {}; + + var defaults = { + follow_mount: true, + recurse_count: 0 + }; + for (var key in defaults) { + if (opts[key] === undefined) { + opts[key] = defaults[key]; + } + } + + if (opts.recurse_count > 8) { // max recursive lookup of 8 + throw new FS.ErrnoError(ERRNO_CODES.ELOOP); + } + + // split the path + var parts = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), false); + + // start at the root + var current = FS.root; + var current_path = '/'; + + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + // stop resolving + break; + } + + current = FS.lookupNode(current, parts[i]); + current_path = PATH.join2(current_path, parts[i]); + + // jump to the mount's root node if this is a mountpoint + if (FS.isMountpoint(current)) { + if (!islast || (islast && opts.follow_mount)) { + current = current.mounted.root; + } + } + + // by default, lookupPath will not follow a symlink if it is the final path component. + // setting opts.follow = true will override this behavior. + if (!islast || opts.follow) { + var count = 0; + while (FS.isLink(current.mode)) { + var link = FS.readlink(current_path); + current_path = PATH.resolve(PATH.dirname(current_path), link); + + var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count }); + current = lookup.node; + + if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX). + throw new FS.ErrnoError(ERRNO_CODES.ELOOP); + } + } + } + } + + return { path: current_path, node: current }; + },getPath:function (node) { + var path; + while (true) { + if (FS.isRoot(node)) { + var mount = node.mount.mountpoint; + if (!path) return mount; + return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path; + } + path = path ? node.name + '/' + path : node.name; + node = node.parent; + } + },hashName:function (parentid, name) { + var hash = 0; + + + for (var i = 0; i < name.length; i++) { + hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; + } + return ((parentid + hash) >>> 0) % FS.nameTable.length; + },hashAddNode:function (node) { + var hash = FS.hashName(node.parent.id, node.name); + node.name_next = FS.nameTable[hash]; + FS.nameTable[hash] = node; + },hashRemoveNode:function (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:function (parent, name) { + var err = FS.mayLookup(parent); + if (err) { + throw new FS.ErrnoError(err); + } + 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; + } + } + // if we failed to find it in the cache, call into the VFS + return FS.lookup(parent, name); + },createNode:function (parent, name, mode, rdev) { + if (!FS.FSNode) { + FS.FSNode = function(parent, name, mode, rdev) { + if (!parent) { + parent = this; // root node sets parent to itself + } + this.parent = parent; + this.mount = parent.mount; + this.mounted = null; + this.id = FS.nextInode++; + this.name = name; + this.mode = mode; + this.node_ops = {}; + this.stream_ops = {}; + this.rdev = rdev; + }; + + FS.FSNode.prototype = {}; + + // compatibility + var readMode = 292 | 73; + var writeMode = 146; + + // NOTE we must use Object.defineProperties instead of individual calls to + // Object.defineProperty in order to make closure compiler happy + Object.defineProperties(FS.FSNode.prototype, { + read: { + get: function() { return (this.mode & readMode) === readMode; }, + set: function(val) { val ? this.mode |= readMode : this.mode &= ~readMode; } + }, + write: { + get: function() { return (this.mode & writeMode) === writeMode; }, + set: function(val) { val ? this.mode |= writeMode : this.mode &= ~writeMode; } + }, + isFolder: { + get: function() { return FS.isDir(this.mode); }, + }, + isDevice: { + get: function() { return FS.isChrdev(this.mode); }, + }, + }); + } + + var node = new FS.FSNode(parent, name, mode, rdev); + + FS.hashAddNode(node); + + return node; + },destroyNode:function (node) { + FS.hashRemoveNode(node); + },isRoot:function (node) { + return node === node.parent; + },isMountpoint:function (node) { + return !!node.mounted; + },isFile:function (mode) { + return (mode & 61440) === 32768; + },isDir:function (mode) { + return (mode & 61440) === 16384; + },isLink:function (mode) { + return (mode & 61440) === 40960; + },isChrdev:function (mode) { + return (mode & 61440) === 8192; + },isBlkdev:function (mode) { + return (mode & 61440) === 24576; + },isFIFO:function (mode) { + return (mode & 61440) === 4096; + },isSocket:function (mode) { + return (mode & 49152) === 49152; + },flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function (str) { + var flags = FS.flagModes[str]; + if (typeof flags === 'undefined') { + throw new Error('Unknown file open mode: ' + str); + } + return flags; + },flagsToPermissionString:function (flag) { + var accmode = flag & 2097155; + var perms = ['r', 'w', 'rw'][accmode]; + if ((flag & 512)) { + perms += 'w'; + } + return perms; + },nodePermissions:function (node, perms) { + if (FS.ignorePermissions) { + return 0; + } + // return 0 if any user, group or owner bits are set. + if (perms.indexOf('r') !== -1 && !(node.mode & 292)) { + return ERRNO_CODES.EACCES; + } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) { + return ERRNO_CODES.EACCES; + } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) { + return ERRNO_CODES.EACCES; + } + return 0; + },mayLookup:function (dir) { + return FS.nodePermissions(dir, 'x'); + },mayCreate:function (dir, name) { + try { + var node = FS.lookupNode(dir, name); + return ERRNO_CODES.EEXIST; + } catch (e) { + } + return FS.nodePermissions(dir, 'wx'); + },mayDelete:function (dir, name, isdir) { + var node; + try { + node = FS.lookupNode(dir, name); + } catch (e) { + return e.errno; + } + var err = FS.nodePermissions(dir, 'wx'); + if (err) { + return err; + } + if (isdir) { + if (!FS.isDir(node.mode)) { + return ERRNO_CODES.ENOTDIR; + } + if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { + return ERRNO_CODES.EBUSY; + } + } else { + if (FS.isDir(node.mode)) { + return ERRNO_CODES.EISDIR; + } + } + return 0; + },mayOpen:function (node, flags) { + if (!node) { + return ERRNO_CODES.ENOENT; + } + if (FS.isLink(node.mode)) { + return ERRNO_CODES.ELOOP; + } else if (FS.isDir(node.mode)) { + if ((flags & 2097155) !== 0 || // opening for write + (flags & 512)) { + return ERRNO_CODES.EISDIR; + } + } + return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); + },MAX_OPEN_FDS:4096,nextfd:function (fd_start, fd_end) { + fd_start = fd_start || 0; + fd_end = fd_end || FS.MAX_OPEN_FDS; + for (var fd = fd_start; fd <= fd_end; fd++) { + if (!FS.streams[fd]) { + return fd; + } + } + throw new FS.ErrnoError(ERRNO_CODES.EMFILE); + },getStream:function (fd) { + return FS.streams[fd]; + },createStream:function (stream, fd_start, fd_end) { + if (!FS.FSStream) { + FS.FSStream = function(){}; + FS.FSStream.prototype = {}; + // compatibility + Object.defineProperties(FS.FSStream.prototype, { + object: { + get: function() { return this.node; }, + set: function(val) { this.node = val; } + }, + isRead: { + get: function() { return (this.flags & 2097155) !== 1; } + }, + isWrite: { + get: function() { return (this.flags & 2097155) !== 0; } + }, + isAppend: { + get: function() { return (this.flags & 1024); } + } + }); + } + // clone it, so we can return an instance of FSStream + var newStream = new FS.FSStream(); + for (var p in stream) { + newStream[p] = stream[p]; + } + stream = newStream; + var fd = FS.nextfd(fd_start, fd_end); + stream.fd = fd; + FS.streams[fd] = stream; + return stream; + },closeStream:function (fd) { + FS.streams[fd] = null; + },getStreamFromPtr:function (ptr) { + return FS.streams[ptr - 1]; + },getPtrForStream:function (stream) { + return stream ? stream.fd + 1 : 0; + },chrdev_stream_ops:{open:function (stream) { + var device = FS.getDevice(stream.node.rdev); + // override node's stream ops with the device's + stream.stream_ops = device.stream_ops; + // forward the open call + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + },llseek:function () { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + }},major:function (dev) { + return ((dev) >> 8); + },minor:function (dev) { + return ((dev) & 0xff); + },makedev:function (ma, mi) { + return ((ma) << 8 | (mi)); + },registerDevice:function (dev, ops) { + FS.devices[dev] = { stream_ops: ops }; + },getDevice:function (dev) { + return FS.devices[dev]; + },getMounts:function (mount) { + var mounts = []; + var check = [mount]; + + while (check.length) { + var m = check.pop(); + + mounts.push(m); + + check.push.apply(check, m.mounts); + } + + return mounts; + },syncfs:function (populate, callback) { + if (typeof(populate) === 'function') { + callback = populate; + populate = false; + } + + var mounts = FS.getMounts(FS.root.mount); + var completed = 0; + + function done(err) { + if (err) { + if (!done.errored) { + done.errored = true; + return callback(err); + } + return; + } + if (++completed >= mounts.length) { + callback(null); + } + }; + + // sync all mounts + mounts.forEach(function (mount) { + if (!mount.type.syncfs) { + return done(null); + } + mount.type.syncfs(mount, populate, done); + }); + },mount:function (type, opts, mountpoint) { + var root = mountpoint === '/'; + var pseudo = !mountpoint; + var node; + + if (root && FS.root) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } else if (!root && !pseudo) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + mountpoint = lookup.path; // use the absolute path + node = lookup.node; + + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + + if (!FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + } + + var mount = { + type: type, + opts: opts, + mountpoint: mountpoint, + mounts: [] + }; + + // create a root node for the fs + var mountRoot = type.mount(mount); + mountRoot.mount = mount; + mount.root = mountRoot; + + if (root) { + FS.root = mountRoot; + } else if (node) { + // set as a mountpoint + node.mounted = mount; + + // add the new mount to the current mount's children + if (node.mount) { + node.mount.mounts.push(mount); + } + } + + return mountRoot; + },unmount:function (mountpoint) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + if (!FS.isMountpoint(lookup.node)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + // destroy the nodes for this mount, and all its child mounts + var node = lookup.node; + var mount = node.mounted; + var mounts = FS.getMounts(mount); + + Object.keys(FS.nameTable).forEach(function (hash) { + var current = FS.nameTable[hash]; + + while (current) { + var next = current.name_next; + + if (mounts.indexOf(current.mount) !== -1) { + FS.destroyNode(current); + } + + current = next; + } + }); + + // no longer a mountpoint + node.mounted = null; + + // remove this mount from the child mounts + var idx = node.mount.mounts.indexOf(mount); + assert(idx !== -1); + node.mount.mounts.splice(idx, 1); + },lookup:function (parent, name) { + return parent.node_ops.lookup(parent, name); + },mknod:function (path, mode, dev) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var err = FS.mayCreate(parent, name); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.mknod) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return parent.node_ops.mknod(parent, name, mode, dev); + },create:function (path, mode) { + mode = mode !== undefined ? mode : 438 /* 0666 */; + mode &= 4095; + mode |= 32768; + return FS.mknod(path, mode, 0); + },mkdir:function (path, mode) { + mode = mode !== undefined ? mode : 511 /* 0777 */; + mode &= 511 | 512; + mode |= 16384; + return FS.mknod(path, mode, 0); + },mkdev:function (path, mode, dev) { + if (typeof(dev) === 'undefined') { + dev = mode; + mode = 438 /* 0666 */; + } + mode |= 8192; + return FS.mknod(path, mode, dev); + },symlink:function (oldpath, newpath) { + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + var newname = PATH.basename(newpath); + var err = FS.mayCreate(parent, newname); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.symlink) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return parent.node_ops.symlink(parent, newname, oldpath); + },rename:function (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); + // parents must exist + var lookup, old_dir, new_dir; + try { + lookup = FS.lookupPath(old_path, { parent: true }); + old_dir = lookup.node; + lookup = FS.lookupPath(new_path, { parent: true }); + new_dir = lookup.node; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + // need to be part of the same mount + if (old_dir.mount !== new_dir.mount) { + throw new FS.ErrnoError(ERRNO_CODES.EXDEV); + } + // source must exist + var old_node = FS.lookupNode(old_dir, old_name); + // old path should not be an ancestor of the new path + var relative = PATH.relative(old_path, new_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + // new path should not be an ancestor of the old path + relative = PATH.relative(new_path, old_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY); + } + // see if the new path already exists + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + // not fatal + } + // early out if nothing needs to change + if (old_node === new_node) { + return; + } + // we'll need to delete the old entry + var isdir = FS.isDir(old_node.mode); + var err = FS.mayDelete(old_dir, old_name, isdir); + if (err) { + throw new FS.ErrnoError(err); + } + // need delete permissions if we'll be overwriting. + // need create permissions if new doesn't already exist. + err = new_node ? + FS.mayDelete(new_dir, new_name, isdir) : + FS.mayCreate(new_dir, new_name); + if (err) { + throw new FS.ErrnoError(err); + } + if (!old_dir.node_ops.rename) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + // if we are going to change the parent, check write permissions + if (new_dir !== old_dir) { + err = FS.nodePermissions(old_dir, 'w'); + if (err) { + throw new FS.ErrnoError(err); + } + } + // remove the node from the lookup hash + FS.hashRemoveNode(old_node); + // do the underlying fs rename + try { + old_dir.node_ops.rename(old_node, new_dir, new_name); + } catch (e) { + throw e; + } finally { + // add the node back to the hash (in case node_ops.rename + // changed its name) + FS.hashAddNode(old_node); + } + },rmdir:function (path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var err = FS.mayDelete(parent, name, true); + if (err) { + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.rmdir) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + parent.node_ops.rmdir(parent, name); + FS.destroyNode(node); + },readdir:function (path) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node.node_ops.readdir) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + return node.node_ops.readdir(node); + },unlink:function (path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var err = FS.mayDelete(parent, name, false); + if (err) { + // POSIX says unlink should set EPERM, not EISDIR + if (err === ERRNO_CODES.EISDIR) err = ERRNO_CODES.EPERM; + throw new FS.ErrnoError(err); + } + if (!parent.node_ops.unlink) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EBUSY); + } + parent.node_ops.unlink(parent, name); + FS.destroyNode(node); + },readlink:function (path) { + var lookup = FS.lookupPath(path); + var link = lookup.node; + if (!link.node_ops.readlink) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + return link.node_ops.readlink(link); + },stat:function (path, dontFollow) { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var node = lookup.node; + if (!node.node_ops.getattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + return node.node_ops.getattr(node); + },lstat:function (path) { + return FS.stat(path, true); + },chmod:function (path, mode, dontFollow) { + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + node.node_ops.setattr(node, { + mode: (mode & 4095) | (node.mode & ~4095), + timestamp: Date.now() + }); + },lchmod:function (path, mode) { + FS.chmod(path, mode, true); + },fchmod:function (fd, mode) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + FS.chmod(stream.node, mode); + },chown:function (path, uid, gid, dontFollow) { + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + node.node_ops.setattr(node, { + timestamp: Date.now() + // we ignore the uid / gid for now + }); + },lchown:function (path, uid, gid) { + FS.chown(path, uid, gid, true); + },fchown:function (fd, uid, gid) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + FS.chown(stream.node, uid, gid); + },truncate:function (path, len) { + if (len < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: true }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(ERRNO_CODES.EPERM); + } + if (FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!FS.isFile(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var err = FS.nodePermissions(node, 'w'); + if (err) { + throw new FS.ErrnoError(err); + } + node.node_ops.setattr(node, { + size: len, + timestamp: Date.now() + }); + },ftruncate:function (fd, len) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + FS.truncate(stream.node, len); + },utime:function (path, atime, mtime) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + node.node_ops.setattr(node, { + timestamp: Math.max(atime, mtime) + }); + },open:function (path, flags, mode, fd_start, fd_end) { + flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags; + mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode; + if ((flags & 64)) { + mode = (mode & 4095) | 32768; + } else { + mode = 0; + } + var node; + if (typeof path === 'object') { + node = path; + } else { + path = PATH.normalize(path); + try { + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072) + }); + node = lookup.node; + } catch (e) { + // ignore + } + } + // perhaps we need to create the node + if ((flags & 64)) { + if (node) { + // if O_CREAT and O_EXCL are set, error out if the node already exists + if ((flags & 128)) { + throw new FS.ErrnoError(ERRNO_CODES.EEXIST); + } + } else { + // node doesn't exist, try to create it + node = FS.mknod(path, mode, 0); + } + } + if (!node) { + throw new FS.ErrnoError(ERRNO_CODES.ENOENT); + } + // can't truncate a device + if (FS.isChrdev(node.mode)) { + flags &= ~512; + } + // check permissions + var err = FS.mayOpen(node, flags); + if (err) { + throw new FS.ErrnoError(err); + } + // do truncation if necessary + if ((flags & 512)) { + FS.truncate(node, 0); + } + // we've already handled these, don't pass down to the underlying vfs + flags &= ~(128 | 512); + + // register the stream with the filesystem + var stream = FS.createStream({ + node: node, + path: FS.getPath(node), // we want the absolute path to the node + flags: flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + // used by the file family libc calls (fopen, fwrite, ferror, etc.) + ungotten: [], + error: false + }, fd_start, fd_end); + // call the new stream's open function + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + if (Module['logReadFiles'] && !(flags & 1)) { + if (!FS.readFiles) FS.readFiles = {}; + if (!(path in FS.readFiles)) { + FS.readFiles[path] = 1; + Module['printErr']('read file: ' + path); + } + } + return stream; + },close:function (stream) { + try { + if (stream.stream_ops.close) { + stream.stream_ops.close(stream); + } + } catch (e) { + throw e; + } finally { + FS.closeStream(stream.fd); + } + },llseek:function (stream, offset, whence) { + if (!stream.seekable || !stream.stream_ops.llseek) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + return stream.stream_ops.llseek(stream, offset, whence); + },read:function (stream, buffer, offset, length, position) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!stream.stream_ops.read) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var seeking = true; + if (typeof position === 'undefined') { + position = stream.position; + seeking = false; + } else if (!stream.seekable) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); + if (!seeking) stream.position += bytesRead; + return bytesRead; + },write:function (stream, buffer, offset, length, position, canOwn) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EISDIR); + } + if (!stream.stream_ops.write) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var seeking = true; + if (typeof position === 'undefined') { + position = stream.position; + seeking = false; + } else if (!stream.seekable) { + throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); + } + if (stream.flags & 1024) { + // seek to the end before writing in append mode + FS.llseek(stream, 0, 2); + } + var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); + if (!seeking) stream.position += bytesWritten; + return bytesWritten; + },allocate:function (stream, offset, length) { + if (offset < 0 || length <= 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EBADF); + } + if (!FS.isFile(stream.node.mode) && !FS.isDir(node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + if (!stream.stream_ops.allocate) { + throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP); + } + stream.stream_ops.allocate(stream, offset, length); + },mmap:function (stream, buffer, offset, length, position, prot, flags) { + // TODO if PROT is PROT_WRITE, make sure we have write access + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(ERRNO_CODES.EACCES); + } + if (!stream.stream_ops.mmap) { + throw new FS.ErrnoError(ERRNO_CODES.ENODEV); + } + return stream.stream_ops.mmap(stream, buffer, offset, length, position, prot, flags); + },ioctl:function (stream, cmd, arg) { + if (!stream.stream_ops.ioctl) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTTY); + } + return stream.stream_ops.ioctl(stream, cmd, arg); + },readFile:function (path, opts) { + opts = opts || {}; + opts.flags = opts.flags || 'r'; + opts.encoding = opts.encoding || 'binary'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error('Invalid encoding type "' + opts.encoding + '"'); + } + var ret; + 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') { + ret = ''; + var utf8 = new Runtime.UTF8Processor(); + for (var i = 0; i < length; i++) { + ret += utf8.processCChar(buf[i]); + } + } else if (opts.encoding === 'binary') { + ret = buf; + } + FS.close(stream); + return ret; + },writeFile:function (path, data, opts) { + opts = opts || {}; + opts.flags = opts.flags || 'w'; + opts.encoding = opts.encoding || 'utf8'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error('Invalid encoding type "' + opts.encoding + '"'); + } + var stream = FS.open(path, opts.flags, opts.mode); + if (opts.encoding === 'utf8') { + var utf8 = new Runtime.UTF8Processor(); + var buf = new Uint8Array(utf8.processJSString(data)); + FS.write(stream, buf, 0, buf.length, 0, opts.canOwn); + } else if (opts.encoding === 'binary') { + FS.write(stream, data, 0, data.length, 0, opts.canOwn); + } + FS.close(stream); + },cwd:function () { + return FS.currentPath; + },chdir:function (path) { + var lookup = FS.lookupPath(path, { follow: true }); + if (!FS.isDir(lookup.node.mode)) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + var err = FS.nodePermissions(lookup.node, 'x'); + if (err) { + throw new FS.ErrnoError(err); + } + FS.currentPath = lookup.path; + },createDefaultDirectories:function () { + FS.mkdir('/tmp'); + },createDefaultDevices:function () { + // create /dev + FS.mkdir('/dev'); + // setup /dev/null + FS.registerDevice(FS.makedev(1, 3), { + read: function() { return 0; }, + write: function() { return 0; } + }); + FS.mkdev('/dev/null', FS.makedev(1, 3)); + // setup /dev/tty and /dev/tty1 + // stderr needs to print output using Module['printErr'] + // so we register a second tty just for it. + 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)); + // we're not going to emulate the actual shm device, + // just create the tmp dirs that reside in it commonly + FS.mkdir('/dev/shm'); + FS.mkdir('/dev/shm/tmp'); + },createStandardStreams:function () { + // TODO deprecate the old functionality of a single + // input / output callback and that utilizes FS.createDevice + // and instead require a unique set of stream ops + + // by default, we symlink the standard streams to the + // default tty devices. however, if the standard streams + // have been overwritten we create a unique device for + // them instead. + if (Module['stdin']) { + FS.createDevice('/dev', 'stdin', Module['stdin']); + } else { + FS.symlink('/dev/tty', '/dev/stdin'); + } + if (Module['stdout']) { + FS.createDevice('/dev', 'stdout', null, Module['stdout']); + } else { + FS.symlink('/dev/tty', '/dev/stdout'); + } + if (Module['stderr']) { + FS.createDevice('/dev', 'stderr', null, Module['stderr']); + } else { + FS.symlink('/dev/tty1', '/dev/stderr'); + } + + // open default streams for the stdin, stdout and stderr devices + var stdin = FS.open('/dev/stdin', 'r'); + HEAP32[((_stdin)>>2)]=FS.getPtrForStream(stdin); + assert(stdin.fd === 0, 'invalid handle for stdin (' + stdin.fd + ')'); + + var stdout = FS.open('/dev/stdout', 'w'); + HEAP32[((_stdout)>>2)]=FS.getPtrForStream(stdout); + assert(stdout.fd === 1, 'invalid handle for stdout (' + stdout.fd + ')'); + + var stderr = FS.open('/dev/stderr', 'w'); + HEAP32[((_stderr)>>2)]=FS.getPtrForStream(stderr); + assert(stderr.fd === 2, 'invalid handle for stderr (' + stderr.fd + ')'); + },ensureErrnoError:function () { + if (FS.ErrnoError) return; + FS.ErrnoError = function ErrnoError(errno) { + this.errno = errno; + for (var key in ERRNO_CODES) { + if (ERRNO_CODES[key] === errno) { + this.code = key; + break; + } + } + this.message = ERRNO_MESSAGES[errno]; + }; + FS.ErrnoError.prototype = new Error(); + FS.ErrnoError.prototype.constructor = FS.ErrnoError; + // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info) + [ERRNO_CODES.ENOENT].forEach(function(code) { + FS.genericErrors[code] = new FS.ErrnoError(code); + FS.genericErrors[code].stack = ''; + }); + },staticInit:function () { + FS.ensureErrnoError(); + + FS.nameTable = new Array(4096); + + FS.mount(MEMFS, {}, '/'); + + FS.createDefaultDirectories(); + FS.createDefaultDevices(); + },init:function (input, output, error) { + assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); + FS.init.initialized = true; + + FS.ensureErrnoError(); + + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + Module['stdin'] = input || Module['stdin']; + Module['stdout'] = output || Module['stdout']; + Module['stderr'] = error || Module['stderr']; + + FS.createStandardStreams(); + },quit:function () { + FS.init.initialized = false; + for (var i = 0; i < FS.streams.length; i++) { + var stream = FS.streams[i]; + if (!stream) { + continue; + } + FS.close(stream); + } + },getMode:function (canRead, canWrite) { + var mode = 0; + if (canRead) mode |= 292 | 73; + if (canWrite) mode |= 146; + return mode; + },joinPath:function (parts, forceRelative) { + var path = PATH.join.apply(null, parts); + if (forceRelative && path[0] == '/') path = path.substr(1); + return path; + },absolutePath:function (relative, base) { + return PATH.resolve(base, relative); + },standardizePath:function (path) { + return PATH.normalize(path); + },findObject:function (path, dontResolveLastLink) { + var ret = FS.analyzePath(path, dontResolveLastLink); + if (ret.exists) { + return ret.object; + } else { + ___setErrNo(ret.error); + return null; + } + },analyzePath:function (path, dontResolveLastLink) { + // operate from within the context of the symlink's target + 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; + },createFolder:function (parent, name, canRead, canWrite) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var mode = FS.getMode(canRead, canWrite); + return FS.mkdir(path, mode); + },createPath:function (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) { + // ignore EEXIST + } + parent = current; + } + return current; + },createFile:function (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:function (parent, name, data, canRead, canWrite, canOwn) { + var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(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; i < len; ++i) arr[i] = data.charCodeAt(i); + data = arr; + } + // make sure we can write to the file + FS.chmod(node, mode | 146); + var stream = FS.open(node, 'w'); + FS.write(stream, data, 0, data.length, 0, canOwn); + FS.close(stream); + FS.chmod(node, mode); + } + return node; + },createDevice:function (parent, name, input, output) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var mode = FS.getMode(!!input, !!output); + if (!FS.createDevice.major) FS.createDevice.major = 64; + var dev = FS.makedev(FS.createDevice.major++, 0); + // Create a fake device that a set of stream ops to emulate + // the old behavior. + FS.registerDevice(dev, { + open: function(stream) { + stream.seekable = false; + }, + close: function(stream) { + // flush any pending line data + if (output && output.buffer && output.buffer.length) { + output(10); + } + }, + read: function(stream, buffer, offset, length, pos /* ignored */) { + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = input(); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + }, + write: function(stream, buffer, offset, length, pos) { + for (var i = 0; i < length; i++) { + try { + output(buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + } + }); + return FS.mkdev(path, mode, dev); + },createLink:function (parent, name, target, canRead, canWrite) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); + return FS.symlink(target, path); + },forceLoadFile:function (obj) { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + var success = true; + if (typeof XMLHttpRequest !== 'undefined') { + throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else if (Module['read']) { + // Command-line. + try { + // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as + // read() will try to parse UTF8. + obj.contents = intArrayFromString(Module['read'](obj.url), true); + } catch (e) { + success = false; + } + } else { + throw new Error('Cannot load without read() or XMLHttpRequest.'); + } + if (!success) ___setErrNo(ERRNO_CODES.EIO); + return success; + },createLazyFile:function (parent, name, url, canRead, canWrite) { + // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. + function LazyUint8Array() { + this.lengthKnown = false; + this.chunks = []; // Loaded chunks. Index is the chunk number + } + LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = Math.floor(idx / this.chunkSize); + return this.getter(chunkNum)[chunkOffset]; + } + LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) { + this.getter = getter; + } + LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("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 chunkSize = 1024*1024; // Chunk size in bytes + + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (function(from, to) { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + if (typeof Uint8Array != 'undefined') 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)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(xhr.response || []); + } else { + return intArrayFromString(xhr.responseText || '', true); + } + }); + var lazyArray = this; + lazyArray.setDataGetter(function(chunkNum) { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); + return lazyArray.chunks[chunkNum]; + }); + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } + if (typeof XMLHttpRequest !== 'undefined') { + if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; + var lazyArray = new LazyUint8Array(); + Object.defineProperty(lazyArray, "length", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + }); + Object.defineProperty(lazyArray, "chunkSize", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + }); + + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + + var node = FS.createFile(parent, name, properties, canRead, canWrite); + // This is a total hack, but I want to get this lazy file code out of the + // core of MEMFS. If we want to keep this lazy file concept I feel it should + // be its own thin LAZYFS proxying calls to MEMFS. + if (properties.contents) { + node.contents = properties.contents; + } else if (properties.url) { + node.contents = null; + node.url = properties.url; + } + // override each stream op with one that tries to force load the lazy file first + var stream_ops = {}; + var keys = Object.keys(node.stream_ops); + keys.forEach(function(key) { + var fn = node.stream_ops[key]; + stream_ops[key] = function forceLoadLazyFile() { + if (!FS.forceLoadFile(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + return fn.apply(null, arguments); + }; + }); + // use a custom read function + stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) { + if (!FS.forceLoadFile(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (contents.slice) { // normal array + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } else { + for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR + buffer[offset + i] = contents.get(position + i); + } + } + return size; + }; + node.stream_ops = stream_ops; + return node; + },createPreloadedFile:function (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn) { + Browser.init(); + // TODO we should allow people to just pass in a complete filename instead + // of parent and name being that we just join them anyways + var fullname = name ? PATH.resolve(PATH.join2(parent, name)) : parent; + function processData(byteArray) { + function finish(byteArray) { + if (!dontCreateFile) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + } + if (onload) onload(); + removeRunDependency('cp ' + fullname); + } + var handled = false; + Module['preloadPlugins'].forEach(function(plugin) { + if (handled) return; + if (plugin['canHandle'](fullname)) { + plugin['handle'](byteArray, fullname, finish, function() { + if (onerror) onerror(); + removeRunDependency('cp ' + fullname); + }); + handled = true; + } + }); + if (!handled) finish(byteArray); + } + addRunDependency('cp ' + fullname); + if (typeof url == 'string') { + Browser.asyncLoad(url, function(byteArray) { + processData(byteArray); + }, onerror); + } else { + processData(url); + } + },indexedDB:function () { + return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + },DB_NAME:function () { + return 'EM_FS_' + window.location.pathname; + },DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function (paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = function openRequest_onupgradeneeded() { + console.log('creating db'); + var db = openRequest.result; + db.createObjectStore(FS.DB_STORE_NAME); + }; + openRequest.onsuccess = function openRequest_onsuccess() { + var db = openRequest.result; + var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite'); + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var putRequest = files.put(FS.analyzePath(path).object.contents, path); + putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) finish() }; + putRequest.onerror = function putRequest_onerror() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + },loadFilesFromDB:function (paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = onerror; // no database to load from + openRequest.onsuccess = function openRequest_onsuccess() { + var db = openRequest.result; + try { + var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly'); + } catch(e) { + onerror(e); + return; + } + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var getRequest = files.get(path); + getRequest.onsuccess = function getRequest_onsuccess() { + if (FS.analyzePath(path).exists) { + FS.unlink(path); + } + FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true); + ok++; + if (ok + fail == total) finish(); + }; + getRequest.onerror = function getRequest_onerror() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + }};function _lseek(fildes, offset, whence) { + // off_t lseek(int fildes, off_t offset, int whence); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/lseek.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + return FS.llseek(stream, offset, whence); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + + Module["_i64Subtract"] = _i64Subtract; + + var _fabsf=Math_abs; + + + + + Module["_strlen"] = _strlen; + + function __reallyNegative(x) { + return x < 0 || (x === 0 && (1/x) === -Infinity); + }function __formatString(format, varargs) { + var textIndex = format; + var argIndex = 0; + function getNextArg(type) { + // NOTE: Explicitly ignoring type safety. Otherwise this fails: + // int x = 4; printf("%c\n", (char)x); + var ret; + if (type === 'double') { + ret = (HEAP32[((tempDoublePtr)>>2)]=HEAP32[(((varargs)+(argIndex))>>2)],HEAP32[(((tempDoublePtr)+(4))>>2)]=HEAP32[(((varargs)+((argIndex)+(4)))>>2)],(+(HEAPF64[(tempDoublePtr)>>3]))); + } else if (type == 'i64') { + ret = [HEAP32[(((varargs)+(argIndex))>>2)], + HEAP32[(((varargs)+(argIndex+4))>>2)]]; + + } else { + type = 'i32'; // varargs are always i32, i64, or double + ret = HEAP32[(((varargs)+(argIndex))>>2)]; + } + argIndex += Runtime.getNativeFieldSize(type); + return ret; + } + + var ret = []; + var curr, next, currArg; + while(1) { + var startTextIndex = textIndex; + curr = HEAP8[(textIndex)]; + if (curr === 0) break; + next = HEAP8[((textIndex+1)|0)]; + if (curr == 37) { + // Handle flags. + var flagAlwaysSigned = false; + var flagLeftAlign = false; + var flagAlternative = false; + var flagZeroPad = false; + var flagPadSign = false; + flagsLoop: while (1) { + switch (next) { + case 43: + flagAlwaysSigned = true; + break; + case 45: + flagLeftAlign = true; + break; + case 35: + flagAlternative = true; + break; + case 48: + if (flagZeroPad) { + break flagsLoop; + } else { + flagZeroPad = true; + break; + } + case 32: + flagPadSign = true; + break; + default: + break flagsLoop; + } + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } + + // Handle width. + var width = 0; + if (next == 42) { + width = getNextArg('i32'); + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } else { + while (next >= 48 && next <= 57) { + width = width * 10 + (next - 48); + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + } + } + + // Handle precision. + var precisionSet = false, precision = -1; + if (next == 46) { + precision = 0; + precisionSet = true; + textIndex++; + next = HEAP8[((textIndex+1)|0)]; + if (next == 42) { + precision = getNextArg('i32'); + textIndex++; + } else { + while(1) { + var precisionChr = HEAP8[((textIndex+1)|0)]; + if (precisionChr < 48 || + precisionChr > 57) break; + precision = precision * 10 + (precisionChr - 48); + textIndex++; + } + } + next = HEAP8[((textIndex+1)|0)]; + } + if (precision < 0) { + precision = 6; // Standard default. + precisionSet = false; + } + + // Handle integer sizes. WARNING: These assume a 32-bit architecture! + var argSize; + switch (String.fromCharCode(next)) { + case 'h': + var nextNext = HEAP8[((textIndex+2)|0)]; + if (nextNext == 104) { + textIndex++; + argSize = 1; // char (actually i32 in varargs) + } else { + argSize = 2; // short (actually i32 in varargs) + } + break; + case 'l': + var nextNext = HEAP8[((textIndex+2)|0)]; + if (nextNext == 108) { + textIndex++; + argSize = 8; // long long + } else { + argSize = 4; // long + } + break; + case 'L': // long long + case 'q': // int64_t + case 'j': // intmax_t + argSize = 8; + break; + case 'z': // size_t + case 't': // ptrdiff_t + case 'I': // signed ptrdiff_t or unsigned size_t + argSize = 4; + break; + default: + argSize = null; + } + if (argSize) textIndex++; + next = HEAP8[((textIndex+1)|0)]; + + // Handle type specifier. + switch (String.fromCharCode(next)) { + case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': case 'p': { + // Integer. + var signed = next == 100 || next == 105; + argSize = argSize || 4; + var currArg = getNextArg('i' + (argSize * 8)); + var origArg = currArg; + var argText; + // Flatten i64-1 [low, high] into a (slightly rounded) double + if (argSize == 8) { + currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == 117); + } + // Truncate to requested size. + if (argSize <= 4) { + var limit = Math.pow(256, argSize) - 1; + currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8); + } + // Format the number. + var currAbsArg = Math.abs(currArg); + var prefix = ''; + if (next == 100 || next == 105) { + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else + argText = reSign(currArg, 8 * argSize, 1).toString(10); + } else if (next == 117) { + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else + argText = unSign(currArg, 8 * argSize, 1).toString(10); + currArg = Math.abs(currArg); + } else if (next == 111) { + argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8); + } else if (next == 120 || next == 88) { + prefix = (flagAlternative && currArg != 0) ? '0x' : ''; + if (argSize == 8 && i64Math) { + if (origArg[1]) { + argText = (origArg[1]>>>0).toString(16); + var lower = (origArg[0]>>>0).toString(16); + while (lower.length < 8) lower = '0' + lower; + argText += lower; + } else { + argText = (origArg[0]>>>0).toString(16); + } + } else + if (currArg < 0) { + // Represent negative numbers in hex as 2's complement. + currArg = -currArg; + argText = (currAbsArg - 1).toString(16); + var buffer = []; + for (var i = 0; i < argText.length; i++) { + buffer.push((0xF - parseInt(argText[i], 16)).toString(16)); + } + argText = buffer.join(''); + while (argText.length < argSize * 2) argText = 'f' + argText; + } else { + argText = currAbsArg.toString(16); + } + if (next == 88) { + prefix = prefix.toUpperCase(); + argText = argText.toUpperCase(); + } + } else if (next == 112) { + if (currAbsArg === 0) { + argText = '(nil)'; + } else { + prefix = '0x'; + argText = currAbsArg.toString(16); + } + } + if (precisionSet) { + while (argText.length < precision) { + argText = '0' + argText; + } + } + + // Add sign if needed + if (currArg >= 0) { + if (flagAlwaysSigned) { + prefix = '+' + prefix; + } else if (flagPadSign) { + prefix = ' ' + prefix; + } + } + + // Move sign to prefix so we zero-pad after the sign + if (argText.charAt(0) == '-') { + prefix = '-' + prefix; + argText = argText.substr(1); + } + + // Add padding. + while (prefix.length + argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad) { + argText = '0' + argText; + } else { + prefix = ' ' + prefix; + } + } + } + + // Insert the result into the buffer. + argText = prefix + argText; + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; + } + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': { + // Float. + var currArg = getNextArg('double'); + var argText; + if (isNaN(currArg)) { + argText = 'nan'; + flagZeroPad = false; + } else if (!isFinite(currArg)) { + argText = (currArg < 0 ? '-' : '') + 'inf'; + flagZeroPad = false; + } else { + var isGeneral = false; + var effectivePrecision = Math.min(precision, 20); + + // Convert g/G to f/F or e/E, as per: + // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html + if (next == 103 || next == 71) { + isGeneral = true; + precision = precision || 1; + var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10); + if (precision > exponent && exponent >= -4) { + next = ((next == 103) ? 'f' : 'F').charCodeAt(0); + precision -= exponent + 1; + } else { + next = ((next == 103) ? 'e' : 'E').charCodeAt(0); + precision--; + } + effectivePrecision = Math.min(precision, 20); + } + + if (next == 101 || next == 69) { + argText = currArg.toExponential(effectivePrecision); + // Make sure the exponent has at least 2 digits. + if (/[eE][-+]\d$/.test(argText)) { + argText = argText.slice(0, -1) + '0' + argText.slice(-1); + } + } else if (next == 102 || next == 70) { + argText = currArg.toFixed(effectivePrecision); + if (currArg === 0 && __reallyNegative(currArg)) { + argText = '-' + argText; + } + } + + var parts = argText.split('e'); + if (isGeneral && !flagAlternative) { + // Discard trailing zeros and periods. + while (parts[0].length > 1 && parts[0].indexOf('.') != -1 && + (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) { + parts[0] = parts[0].slice(0, -1); + } + } else { + // Make sure we have a period in alternative mode. + if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.'; + // Zero pad until required precision. + while (precision > effectivePrecision++) parts[0] += '0'; + } + argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : ''); + + // Capitalize 'E' if needed. + if (next == 69) argText = argText.toUpperCase(); + + // Add sign. + if (currArg >= 0) { + if (flagAlwaysSigned) { + argText = '+' + argText; + } else if (flagPadSign) { + argText = ' ' + argText; + } + } + } + + // Add padding. + while (argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) { + argText = argText[0] + '0' + argText.slice(1); + } else { + argText = (flagZeroPad ? '0' : ' ') + argText; + } + } + } + + // Adjust case. + if (next < 97) argText = argText.toUpperCase(); + + // Insert the result into the buffer. + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; + } + case 's': { + // String. + var arg = getNextArg('i8*'); + var argLength = arg ? _strlen(arg) : '(null)'.length; + if (precisionSet) argLength = Math.min(argLength, precision); + if (!flagLeftAlign) { + while (argLength < width--) { + ret.push(32); + } + } + if (arg) { + for (var i = 0; i < argLength; i++) { + ret.push(HEAPU8[((arg++)|0)]); + } + } else { + ret = ret.concat(intArrayFromString('(null)'.substr(0, argLength), true)); + } + if (flagLeftAlign) { + while (argLength < width--) { + ret.push(32); + } + } + break; + } + case 'c': { + // Character. + if (flagLeftAlign) ret.push(getNextArg('i8')); + while (--width > 0) { + ret.push(32); + } + if (!flagLeftAlign) ret.push(getNextArg('i8')); + break; + } + case 'n': { + // Write the length written so far to the next parameter. + var ptr = getNextArg('i32*'); + HEAP32[((ptr)>>2)]=ret.length; + break; + } + case '%': { + // Literal percent sign. + ret.push(curr); + break; + } + default: { + // Unknown specifiers remain untouched. + for (var i = startTextIndex; i < textIndex + 2; i++) { + ret.push(HEAP8[(i)]); + } + } + } + textIndex += 2; + // TODO: Support a/A (hex float) and m (last error) specifiers. + // TODO: Support %1${specifier} for arg selection. + } else { + ret.push(curr); + textIndex += 1; + } + } + return ret; + } + + function _malloc(bytes) { + /* Over-allocate to make sure it is byte-aligned by 8. + * This will leak memory, but this is only the dummy + * implementation (replaced by dlmalloc normally) so + * not an issue. + */ + var ptr = Runtime.dynamicAlloc(bytes + 8); + return (ptr+8) & 0xFFFFFFF8; + } + Module["_malloc"] = _malloc;function _snprintf(s, n, format, varargs) { + // int snprintf(char *restrict s, size_t n, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var result = __formatString(format, varargs); + var limit = (n === undefined) ? result.length + : Math.min(result.length, Math.max(n - 1, 0)); + if (s < 0) { + s = -s; + var buf = _malloc(limit+1); + HEAP32[((s)>>2)]=buf; + s = buf; + } + for (var i = 0; i < limit; i++) { + HEAP8[(((s)+(i))|0)]=result[i]; + } + if (limit < n || (n === undefined)) HEAP8[(((s)+(i))|0)]=0; + return result.length; + } + + + Module["_memset"] = _memset; + + + Module["_strcat"] = _strcat; + + + function _strerror_r(errnum, strerrbuf, buflen) { + if (errnum in ERRNO_MESSAGES) { + if (ERRNO_MESSAGES[errnum].length > buflen - 1) { + return ___setErrNo(ERRNO_CODES.ERANGE); + } else { + var msg = ERRNO_MESSAGES[errnum]; + writeAsciiToMemory(msg, strerrbuf); + return 0; + } + } else { + return ___setErrNo(ERRNO_CODES.EINVAL); + } + }function _strerror(errnum) { + if (!_strerror.buffer) _strerror.buffer = _malloc(256); + _strerror_r(errnum, _strerror.buffer, 256); + return _strerror.buffer; + } + + + Module["_bitshift64Shl"] = _bitshift64Shl; + + function _abort() { + Module['abort'](); + } + + + + + + + function _mkport() { throw 'TODO' }var SOCKFS={mount:function (mount) { + return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + },createSocket:function (family, type, protocol) { + var streaming = type == 1; + if (protocol) { + assert(streaming == (protocol == 6)); // if SOCK_STREAM, must be tcp + } + + // create our internal socket structure + var sock = { + family: family, + type: type, + protocol: protocol, + server: null, + peers: {}, + pending: [], + recv_queue: [], + sock_ops: SOCKFS.websocket_sock_ops + }; + + // create the filesystem node to store the socket structure + var name = SOCKFS.nextname(); + var node = FS.createNode(SOCKFS.root, name, 49152, 0); + node.sock = sock; + + // and the wrapping stream that enables library functions such + // as read and write to indirectly interact with the socket + var stream = FS.createStream({ + path: name, + node: node, + flags: FS.modeStringToFlags('r+'), + seekable: false, + stream_ops: SOCKFS.stream_ops + }); + + // map the new stream to the socket structure (sockets have a 1:1 + // relationship with a stream) + sock.stream = stream; + + return sock; + },getSocket:function (fd) { + var stream = FS.getStream(fd); + if (!stream || !FS.isSocket(stream.node.mode)) { + return null; + } + return stream.node.sock; + },stream_ops:{poll:function (stream) { + var sock = stream.node.sock; + return sock.sock_ops.poll(sock); + },ioctl:function (stream, request, varargs) { + var sock = stream.node.sock; + return sock.sock_ops.ioctl(sock, request, varargs); + },read:function (stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + var msg = sock.sock_ops.recvmsg(sock, length); + if (!msg) { + // socket is closed + return 0; + } + buffer.set(msg.buffer, offset); + return msg.buffer.length; + },write:function (stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + return sock.sock_ops.sendmsg(sock, buffer, offset, length); + },close:function (stream) { + var sock = stream.node.sock; + sock.sock_ops.close(sock); + }},nextname:function () { + if (!SOCKFS.nextname.current) { + SOCKFS.nextname.current = 0; + } + return 'socket[' + (SOCKFS.nextname.current++) + ']'; + },websocket_sock_ops:{createPeer:function (sock, addr, port) { + var ws; + + if (typeof addr === 'object') { + ws = addr; + addr = null; + port = null; + } + + if (ws) { + // for sockets that've already connected (e.g. we're the server) + // we can inspect the _socket property for the address + if (ws._socket) { + addr = ws._socket.remoteAddress; + port = ws._socket.remotePort; + } + // if we're just now initializing a connection to the remote, + // inspect the url property + else { + var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url); + if (!result) { + throw new Error('WebSocket URL must be in the format ws(s)://address:port'); + } + addr = result[1]; + port = parseInt(result[2], 10); + } + } else { + // create the actual websocket object and connect + try { + // runtimeConfig gets set to true if WebSocket runtime configuration is available. + var runtimeConfig = (Module['websocket'] && ('object' === typeof Module['websocket'])); + + // The default value is 'ws://' the replace is needed because the compiler replaces "//" comments with '#' + // comments without checking context, so we'd end up with ws:#, the replace swaps the "#" for "//" again. + var url = 'ws:#'.replace('#', '//'); + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['url']) { + url = Module['websocket']['url']; // Fetch runtime WebSocket URL config. + } + } + + if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it. + url = url + addr + ':' + port; + } + + // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set. + var subProtocols = 'binary'; // The default value is 'binary' + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['subprotocol']) { + subProtocols = Module['websocket']['subprotocol']; // Fetch runtime WebSocket subprotocol config. + } + } + + // The regex trims the string (removes spaces at the beginning and end, then splits the string by + // , into an Array. Whitespace removal is important for Websockify and ws. + subProtocols = subProtocols.replace(/^ +| +$/g,"").split(/ *, */); + + // The node ws library API for specifying optional subprotocol is slightly different than the browser's. + var opts = ENVIRONMENT_IS_NODE ? {'protocol': subProtocols.toString()} : subProtocols; + + // If node we use the ws library. + var WebSocket = ENVIRONMENT_IS_NODE ? require('ws') : window['WebSocket']; + ws = new WebSocket(url, opts); + ws.binaryType = 'arraybuffer'; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EHOSTUNREACH); + } + } + + + var peer = { + addr: addr, + port: port, + socket: ws, + dgram_send_queue: [] + }; + + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer); + + // if this is a bound dgram socket, send the port number first to allow + // us to override the ephemeral port reported to us by remotePort on the + // remote end. + if (sock.type === 2 && typeof sock.sport !== 'undefined') { + peer.dgram_send_queue.push(new Uint8Array([ + 255, 255, 255, 255, + 'p'.charCodeAt(0), 'o'.charCodeAt(0), 'r'.charCodeAt(0), 't'.charCodeAt(0), + ((sock.sport & 0xff00) >> 8) , (sock.sport & 0xff) + ])); + } + + return peer; + },getPeer:function (sock, addr, port) { + return sock.peers[addr + ':' + port]; + },addPeer:function (sock, peer) { + sock.peers[peer.addr + ':' + peer.port] = peer; + },removePeer:function (sock, peer) { + delete sock.peers[peer.addr + ':' + peer.port]; + },handlePeerEvents:function (sock, peer) { + var first = true; + + var handleOpen = function () { + try { + var queued = peer.dgram_send_queue.shift(); + while (queued) { + peer.socket.send(queued); + queued = peer.dgram_send_queue.shift(); + } + } catch (e) { + // not much we can do here in the way of proper error handling as we've already + // lied and said this data was sent. shut it down. + peer.socket.close(); + } + }; + + function handleMessage(data) { + assert(typeof data !== 'string' && data.byteLength !== undefined); // must receive an ArrayBuffer + data = new Uint8Array(data); // make a typed array view on the array buffer + + + // if this is the port message, override the peer's port with it + var wasfirst = first; + first = false; + if (wasfirst && + data.length === 10 && + data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 && + data[4] === 'p'.charCodeAt(0) && data[5] === 'o'.charCodeAt(0) && data[6] === 'r'.charCodeAt(0) && data[7] === 't'.charCodeAt(0)) { + // update the peer's port and it's key in the peer map + var newport = ((data[8] << 8) | data[9]); + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + peer.port = newport; + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + return; + } + + sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data }); + }; + + if (ENVIRONMENT_IS_NODE) { + peer.socket.on('open', handleOpen); + peer.socket.on('message', function(data, flags) { + if (!flags.binary) { + return; + } + handleMessage((new Uint8Array(data)).buffer); // copy from node Buffer -> ArrayBuffer + }); + peer.socket.on('error', function() { + // don't throw + }); + } else { + peer.socket.onopen = handleOpen; + peer.socket.onmessage = function peer_socket_onmessage(event) { + handleMessage(event.data); + }; + } + },poll:function (sock) { + if (sock.type === 1 && sock.server) { + // listen sockets should only say they're available for reading + // if there are pending clients. + return sock.pending.length ? (64 | 1) : 0; + } + + var mask = 0; + var dest = sock.type === 1 ? // we only care about the socket state for connection-based sockets + SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) : + null; + + if (sock.recv_queue.length || + !dest || // connection-less sockets are always ready to read + (dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { // let recv return 0 once closed + mask |= (64 | 1); + } + + if (!dest || // connection-less sockets are always ready to write + (dest && dest.socket.readyState === dest.socket.OPEN)) { + mask |= 4; + } + + if ((dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { + mask |= 16; + } + + return mask; + },ioctl:function (sock, request, arg) { + switch (request) { + case 21531: + var bytes = 0; + if (sock.recv_queue.length) { + bytes = sock.recv_queue[0].data.length; + } + HEAP32[((arg)>>2)]=bytes; + return 0; + default: + return ERRNO_CODES.EINVAL; + } + },close:function (sock) { + // if we've spawned a listen server, close it + if (sock.server) { + try { + sock.server.close(); + } catch (e) { + } + sock.server = null; + } + // close any peer connections + var peers = Object.keys(sock.peers); + for (var i = 0; i < peers.length; i++) { + var peer = sock.peers[peers[i]]; + try { + peer.socket.close(); + } catch (e) { + } + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + } + return 0; + },bind:function (sock, addr, port) { + if (typeof sock.saddr !== 'undefined' || typeof sock.sport !== 'undefined') { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); // already bound + } + sock.saddr = addr; + sock.sport = port || _mkport(); + // in order to emulate dgram sockets, we need to launch a listen server when + // binding on a connection-less socket + // note: this is only required on the server side + if (sock.type === 2) { + // close the existing server if it exists + if (sock.server) { + sock.server.close(); + sock.server = null; + } + // swallow error operation not supported error that occurs when binding in the + // browser where this isn't supported + try { + sock.sock_ops.listen(sock, 0); + } catch (e) { + if (!(e instanceof FS.ErrnoError)) throw e; + if (e.errno !== ERRNO_CODES.EOPNOTSUPP) throw e; + } + } + },connect:function (sock, addr, port) { + if (sock.server) { + throw new FS.ErrnoError(ERRNO_CODS.EOPNOTSUPP); + } + + // TODO autobind + // if (!sock.addr && sock.type == 2) { + // } + + // early out if we're already connected / in the middle of connecting + if (typeof sock.daddr !== 'undefined' && typeof sock.dport !== 'undefined') { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + if (dest) { + if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(ERRNO_CODES.EALREADY); + } else { + throw new FS.ErrnoError(ERRNO_CODES.EISCONN); + } + } + } + + // add the socket to our peer list and set our + // destination address / port to match + var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + sock.daddr = peer.addr; + sock.dport = peer.port; + + // always "fail" in non-blocking mode + throw new FS.ErrnoError(ERRNO_CODES.EINPROGRESS); + },listen:function (sock, backlog) { + if (!ENVIRONMENT_IS_NODE) { + throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP); + } + if (sock.server) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); // already listening + } + var WebSocketServer = require('ws').Server; + var host = sock.saddr; + sock.server = new WebSocketServer({ + host: host, + port: sock.sport + // TODO support backlog + }); + + sock.server.on('connection', function(ws) { + if (sock.type === 1) { + var newsock = SOCKFS.createSocket(sock.family, sock.type, sock.protocol); + + // create a peer on the new socket + var peer = SOCKFS.websocket_sock_ops.createPeer(newsock, ws); + newsock.daddr = peer.addr; + newsock.dport = peer.port; + + // push to queue for accept to pick up + sock.pending.push(newsock); + } else { + // create a peer on the listen socket so calling sendto + // with the listen socket and an address will resolve + // to the correct client + SOCKFS.websocket_sock_ops.createPeer(sock, ws); + } + }); + sock.server.on('closed', function() { + sock.server = null; + }); + sock.server.on('error', function() { + // don't throw + }); + },accept:function (listensock) { + if (!listensock.server) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var newsock = listensock.pending.shift(); + newsock.stream.flags = listensock.stream.flags; + return newsock; + },getname:function (sock, peer) { + var addr, port; + if (peer) { + if (sock.daddr === undefined || sock.dport === undefined) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + addr = sock.daddr; + port = sock.dport; + } else { + // TODO saddr and sport will be set for bind()'d UDP sockets, but what + // should we be returning for TCP sockets that've been connect()'d? + addr = sock.saddr || 0; + port = sock.sport || 0; + } + return { addr: addr, port: port }; + },sendmsg:function (sock, buffer, offset, length, addr, port) { + if (sock.type === 2) { + // connection-less sockets will honor the message address, + // and otherwise fall back to the bound destination address + if (addr === undefined || port === undefined) { + addr = sock.daddr; + port = sock.dport; + } + // if there was no address to fall back to, error out + if (addr === undefined || port === undefined) { + throw new FS.ErrnoError(ERRNO_CODES.EDESTADDRREQ); + } + } else { + // connection-based sockets will only use the bound + addr = sock.daddr; + port = sock.dport; + } + + // find the peer for the destination address + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port); + + // early out if not connected with a connection-based socket + if (sock.type === 1) { + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } else if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } + + // create a copy of the incoming data to send, as the WebSocket API + // doesn't work entirely with an ArrayBufferView, it'll just send + // the entire underlying buffer + var data; + if (buffer instanceof Array || buffer instanceof ArrayBuffer) { + data = buffer.slice(offset, offset + length); + } else { // ArrayBufferView + data = buffer.buffer.slice(buffer.byteOffset + offset, buffer.byteOffset + offset + length); + } + + // if we're emulating a connection-less dgram socket and don't have + // a cached connection, queue the buffer to send upon connect and + // lie, saying the data was sent now. + if (sock.type === 2) { + if (!dest || dest.socket.readyState !== dest.socket.OPEN) { + // if we're not connected, open a new connection + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + } + dest.dgram_send_queue.push(data); + return length; + } + } + + try { + // send the actual data + dest.socket.send(data); + return length; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + },recvmsg:function (sock, length) { + // http://pubs.opengroup.org/onlinepubs/7908799/xns/recvmsg.html + if (sock.type === 1 && sock.server) { + // tcp servers should not be recv()'ing on the listen socket + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + + var queued = sock.recv_queue.shift(); + if (!queued) { + if (sock.type === 1) { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + + if (!dest) { + // if we have a destination address but are not connected, error out + throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN); + } + else if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + // return null if the socket has closed + return null; + } + else { + // else, our socket is in a valid state but truly has nothing available + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } else { + throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); + } + } + + // queued.data will be an ArrayBuffer if it's unadulterated, but if it's + // requeued TCP data it'll be an ArrayBufferView + var queuedLength = queued.data.byteLength || queued.data.length; + var queuedOffset = queued.data.byteOffset || 0; + var queuedBuffer = queued.data.buffer || queued.data; + var bytesRead = Math.min(length, queuedLength); + var res = { + buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead), + addr: queued.addr, + port: queued.port + }; + + + // push back any unread data for TCP connections + if (sock.type === 1 && bytesRead < queuedLength) { + var bytesRemaining = queuedLength - bytesRead; + queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining); + sock.recv_queue.unshift(queued); + } + + return res; + }}};function _send(fd, buf, len, flags) { + var sock = SOCKFS.getSocket(fd); + if (!sock) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + // TODO honor flags + return _write(fd, buf, len); + } + + function _pwrite(fildes, buf, nbyte, offset) { + // ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + var slab = HEAP8; + return FS.write(stream, slab, buf, nbyte, offset); + } catch (e) { + FS.handleFSError(e); + return -1; + } + }function _write(fildes, buf, nbyte) { + // ssize_t write(int fildes, const void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + + + try { + var slab = HEAP8; + return FS.write(stream, slab, buf, nbyte); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + function _fileno(stream) { + // int fileno(FILE *stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fileno.html + stream = FS.getStreamFromPtr(stream); + if (!stream) return -1; + return stream.fd; + }function _fwrite(ptr, size, nitems, stream) { + // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/fwrite.html + var bytesToWrite = nitems * size; + if (bytesToWrite == 0) return 0; + var fd = _fileno(stream); + var bytesWritten = _write(fd, ptr, bytesToWrite); + if (bytesWritten == -1) { + var streamObj = FS.getStreamFromPtr(stream); + if (streamObj) streamObj.error = true; + return 0; + } else { + return Math.floor(bytesWritten / size); + } + }function _fprintf(stream, format, varargs) { + // int fprintf(FILE *restrict stream, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var result = __formatString(format, varargs); + var stack = Runtime.stackSave(); + var ret = _fwrite(allocate(result, 'i8', ALLOC_STACK), 1, result.length, stream); + Runtime.stackRestore(stack); + return ret; + } + + function _toupper(chr) { + if (chr >= 97 && chr <= 122) { + return chr - 97 + 65; + } else { + return chr; + } + } + + function _printf(format, varargs) { + // int printf(const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + var stdout = HEAP32[((_stdout)>>2)]; + return _fprintf(stdout, format, varargs); + } + + function _isdigit(chr) { + return chr >= 48 && chr <= 57; + } + + function _close(fildes) { + // int close(int fildes); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/close.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + FS.close(stream); + return 0; + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + var _tan=Math_tan; + + + + Module["_strncpy"] = _strncpy; + + var _asin=Math_asin; + + + Module["_i64Add"] = _i64Add; + + var _fabs=Math_abs; + + function _open(path, oflag, varargs) { + // int open(const char *path, int oflag, ...); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html + var mode = HEAP32[((varargs)>>2)]; + path = Pointer_stringify(path); + try { + var stream = FS.open(path, oflag, mode); + return stream.fd; + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + + function _copysign(a, b) { + return __reallyNegative(a) === __reallyNegative(b) ? a : -a; + }var _copysignl=_copysign; + + var _sqrt=Math_sqrt; + + + var Browser={mainLoop:{scheduler:null,method:"",shouldPause:false,paused:false,queue:[],pause:function () { + Browser.mainLoop.shouldPause = true; + },resume:function () { + if (Browser.mainLoop.paused) { + Browser.mainLoop.paused = false; + Browser.mainLoop.scheduler(); + } + Browser.mainLoop.shouldPause = false; + },updateStatus:function () { + if (Module['setStatus']) { + var message = Module['statusMessage'] || 'Please wait...'; + var remaining = Browser.mainLoop.remainingBlockers; + var expected = Browser.mainLoop.expectedBlockers; + if (remaining) { + if (remaining < expected) { + Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')'); + } else { + Module['setStatus'](message); + } + } else { + Module['setStatus'](''); + } + } + }},isFullScreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function () { + if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers + + if (Browser.initted || ENVIRONMENT_IS_WORKER) return; + Browser.initted = true; + + try { + new Blob(); + Browser.hasBlobConstructor = true; + } catch(e) { + Browser.hasBlobConstructor = false; + console.log("warning: no blob constructor, cannot create blobs with mimetypes"); + } + Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null)); + Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined; + if (!Module.noImageDecoding && typeof Browser.URLObject === 'undefined') { + console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."); + Module.noImageDecoding = true; + } + + // Support for plugins that can process preloaded files. You can add more of these to + // your app by creating and appending to Module.preloadPlugins. + // + // Each plugin is asked if it can handle a file based on the file's name. If it can, + // it is given the file's raw data. When it is done, it calls a callback with the file's + // (possibly modified) data. For example, a plugin might decompress a file, or it + // might create some side data structure for use later (like an Image element, etc.). + + var imagePlugin = {}; + imagePlugin['canHandle'] = function imagePlugin_canHandle(name) { + return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name); + }; + imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) { + var b = null; + if (Browser.hasBlobConstructor) { + try { + b = new Blob([byteArray], { type: Browser.getMimetype(name) }); + if (b.size !== byteArray.length) { // Safari bug #118630 + // Safari's Blob can only take an ArrayBuffer + b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) }); + } + } catch(e) { + Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder'); + } + } + if (!b) { + var bb = new Browser.BlobBuilder(); + bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range + b = bb.getBlob(); + } + var url = Browser.URLObject.createObjectURL(b); + var img = new Image(); + img.onload = function img_onload() { + assert(img.complete, 'Image ' + name + ' could not be decoded'); + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + Module["preloadedImages"][name] = canvas; + Browser.URLObject.revokeObjectURL(url); + if (onload) onload(byteArray); + }; + img.onerror = function img_onerror(event) { + console.log('Image ' + url + ' could not be decoded'); + if (onerror) onerror(); + }; + img.src = url; + }; + Module['preloadPlugins'].push(imagePlugin); + + var audioPlugin = {}; + audioPlugin['canHandle'] = function audioPlugin_canHandle(name) { + return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; + }; + audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) { + var done = false; + function finish(audio) { + if (done) return; + done = true; + Module["preloadedAudios"][name] = audio; + if (onload) onload(byteArray); + } + function fail() { + if (done) return; + done = true; + Module["preloadedAudios"][name] = new Audio(); // empty shim + if (onerror) onerror(); + } + if (Browser.hasBlobConstructor) { + try { + var b = new Blob([byteArray], { type: Browser.getMimetype(name) }); + } catch(e) { + return fail(); + } + var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! + var audio = new Audio(); + audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926 + audio.onerror = function audio_onerror(event) { + if (done) return; + console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach'); + function encode64(data) { + var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + var PAD = '='; + var ret = ''; + var leftchar = 0; + var leftbits = 0; + for (var i = 0; i < data.length; i++) { + leftchar = (leftchar << 8) | data[i]; + leftbits += 8; + while (leftbits >= 6) { + var curr = (leftchar >> (leftbits-6)) & 0x3f; + leftbits -= 6; + ret += BASE[curr]; + } + } + if (leftbits == 2) { + ret += BASE[(leftchar&3) << 4]; + ret += PAD + PAD; + } else if (leftbits == 4) { + ret += BASE[(leftchar&0xf) << 2]; + ret += PAD; + } + return ret; + } + audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray); + finish(audio); // we don't wait for confirmation this worked - but it's worth trying + }; + audio.src = url; + // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror + Browser.safeSetTimeout(function() { + finish(audio); // try to use it even though it is not necessarily ready to play + }, 10000); + } else { + return fail(); + } + }; + Module['preloadPlugins'].push(audioPlugin); + + // Canvas event setup + + var canvas = Module['canvas']; + + // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module + // Module['forcedAspectRatio'] = 4 / 3; + + canvas.requestPointerLock = canvas['requestPointerLock'] || + canvas['mozRequestPointerLock'] || + canvas['webkitRequestPointerLock'] || + canvas['msRequestPointerLock'] || + function(){}; + canvas.exitPointerLock = document['exitPointerLock'] || + document['mozExitPointerLock'] || + document['webkitExitPointerLock'] || + document['msExitPointerLock'] || + function(){}; // no-op if function does not exist + canvas.exitPointerLock = canvas.exitPointerLock.bind(document); + + function pointerLockChange() { + Browser.pointerLock = document['pointerLockElement'] === canvas || + document['mozPointerLockElement'] === canvas || + document['webkitPointerLockElement'] === canvas || + document['msPointerLockElement'] === canvas; + } + + document.addEventListener('pointerlockchange', pointerLockChange, false); + document.addEventListener('mozpointerlockchange', pointerLockChange, false); + document.addEventListener('webkitpointerlockchange', pointerLockChange, false); + document.addEventListener('mspointerlockchange', pointerLockChange, false); + + if (Module['elementPointerLock']) { + canvas.addEventListener("click", function(ev) { + if (!Browser.pointerLock && canvas.requestPointerLock) { + canvas.requestPointerLock(); + ev.preventDefault(); + } + }, false); + } + },createContext:function (canvas, useWebGL, setInModule, webGLContextAttributes) { + var ctx; + var errorInfo = '?'; + function onContextCreationError(event) { + errorInfo = event.statusMessage || errorInfo; + } + try { + if (useWebGL) { + var contextAttributes = { + antialias: false, + alpha: false + }; + + if (webGLContextAttributes) { + for (var attribute in webGLContextAttributes) { + contextAttributes[attribute] = webGLContextAttributes[attribute]; + } + } + + + canvas.addEventListener('webglcontextcreationerror', onContextCreationError, false); + try { + ['experimental-webgl', 'webgl'].some(function(webglId) { + return ctx = canvas.getContext(webglId, contextAttributes); + }); + } finally { + canvas.removeEventListener('webglcontextcreationerror', onContextCreationError, false); + } + } else { + ctx = canvas.getContext('2d'); + } + if (!ctx) throw ':('; + } catch (e) { + Module.print('Could not create canvas: ' + [errorInfo, e]); + return null; + } + if (useWebGL) { + // Set the background of the WebGL canvas to black + canvas.style.backgroundColor = "black"; + + // Warn on context loss + canvas.addEventListener('webglcontextlost', function(event) { + alert('WebGL context lost. You will need to reload the page.'); + }, false); + } + if (setInModule) { + GLctx = Module.ctx = ctx; + Module.useWebGL = useWebGL; + Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); + Browser.init(); + } + return ctx; + },destroyContext:function (canvas, useWebGL, setInModule) {},fullScreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullScreen:function (lockPointer, resizeCanvas) { + Browser.lockPointer = lockPointer; + Browser.resizeCanvas = resizeCanvas; + if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true; + if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false; + + var canvas = Module['canvas']; + function fullScreenChange() { + Browser.isFullScreen = false; + var canvasContainer = canvas.parentNode; + if ((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement'] || + document['msFullScreenElement'] || document['msFullscreenElement'] || + document['webkitCurrentFullScreenElement']) === canvasContainer) { + canvas.cancelFullScreen = document['cancelFullScreen'] || + document['mozCancelFullScreen'] || + document['webkitCancelFullScreen'] || + document['msExitFullscreen'] || + document['exitFullscreen'] || + function() {}; + canvas.cancelFullScreen = canvas.cancelFullScreen.bind(document); + if (Browser.lockPointer) canvas.requestPointerLock(); + Browser.isFullScreen = true; + if (Browser.resizeCanvas) Browser.setFullScreenCanvasSize(); + } else { + + // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen + canvasContainer.parentNode.insertBefore(canvas, canvasContainer); + canvasContainer.parentNode.removeChild(canvasContainer); + + if (Browser.resizeCanvas) Browser.setWindowedCanvasSize(); + } + if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullScreen); + Browser.updateCanvasDimensions(canvas); + } + + if (!Browser.fullScreenHandlersInstalled) { + Browser.fullScreenHandlersInstalled = true; + document.addEventListener('fullscreenchange', fullScreenChange, false); + document.addEventListener('mozfullscreenchange', fullScreenChange, false); + document.addEventListener('webkitfullscreenchange', fullScreenChange, false); + document.addEventListener('MSFullscreenChange', fullScreenChange, false); + } + + // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root + var canvasContainer = document.createElement("div"); + canvas.parentNode.insertBefore(canvasContainer, canvas); + canvasContainer.appendChild(canvas); + + // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size) + canvasContainer.requestFullScreen = canvasContainer['requestFullScreen'] || + canvasContainer['mozRequestFullScreen'] || + canvasContainer['msRequestFullscreen'] || + (canvasContainer['webkitRequestFullScreen'] ? function() { canvasContainer['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null); + canvasContainer.requestFullScreen(); + },requestAnimationFrame:function requestAnimationFrame(func) { + if (typeof window === 'undefined') { // Provide fallback to setTimeout if window is undefined (e.g. in Node.js) + setTimeout(func, 1000/60); + } else { + if (!window.requestAnimationFrame) { + window.requestAnimationFrame = window['requestAnimationFrame'] || + window['mozRequestAnimationFrame'] || + window['webkitRequestAnimationFrame'] || + window['msRequestAnimationFrame'] || + window['oRequestAnimationFrame'] || + window['setTimeout']; + } + window.requestAnimationFrame(func); + } + },safeCallback:function (func) { + return function() { + if (!ABORT) return func.apply(null, arguments); + }; + },safeRequestAnimationFrame:function (func) { + return Browser.requestAnimationFrame(function() { + if (!ABORT) func(); + }); + },safeSetTimeout:function (func, timeout) { + return setTimeout(function() { + if (!ABORT) func(); + }, timeout); + },safeSetInterval:function (func, timeout) { + return setInterval(function() { + if (!ABORT) func(); + }, timeout); + },getMimetype:function (name) { + return { + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'png': 'image/png', + 'bmp': 'image/bmp', + 'ogg': 'audio/ogg', + 'wav': 'audio/wav', + 'mp3': 'audio/mpeg' + }[name.substr(name.lastIndexOf('.')+1)]; + },getUserMedia:function (func) { + if(!window.getUserMedia) { + window.getUserMedia = navigator['getUserMedia'] || + navigator['mozGetUserMedia']; + } + window.getUserMedia(func); + },getMovementX:function (event) { + return event['movementX'] || + event['mozMovementX'] || + event['webkitMovementX'] || + 0; + },getMovementY:function (event) { + return event['movementY'] || + event['mozMovementY'] || + event['webkitMovementY'] || + 0; + },getMouseWheelDelta:function (event) { + return Math.max(-1, Math.min(1, event.type === 'DOMMouseScroll' ? event.detail : -event.wheelDelta)); + },mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function (event) { // event should be mousemove, mousedown or mouseup + if (Browser.pointerLock) { + // When the pointer is locked, calculate the coordinates + // based on the movement of the mouse. + // Workaround for Firefox bug 764498 + if (event.type != 'mousemove' && + ('mozMovementX' in event)) { + Browser.mouseMovementX = Browser.mouseMovementY = 0; + } else { + Browser.mouseMovementX = Browser.getMovementX(event); + Browser.mouseMovementY = Browser.getMovementY(event); + } + + // check if SDL is available + if (typeof SDL != "undefined") { + Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; + Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; + } else { + // just add the mouse delta to the current absolut mouse position + // FIXME: ideally this should be clamped against the canvas size and zero + Browser.mouseX += Browser.mouseMovementX; + Browser.mouseY += Browser.mouseMovementY; + } + } else { + // Otherwise, calculate the movement based on the changes + // in the coordinates. + var rect = Module["canvas"].getBoundingClientRect(); + var cw = Module["canvas"].width; + var ch = Module["canvas"].height; + + // Neither .scrollX or .pageXOffset are defined in a spec, but + // we prefer .scrollX because it is currently in a spec draft. + // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/) + var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset); + var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset); + + if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') { + var touch = event.touch; + if (touch === undefined) { + return; // the "touch" property is only defined in SDL + + } + var adjustedX = touch.pageX - (scrollX + rect.left); + var adjustedY = touch.pageY - (scrollY + rect.top); + + adjustedX = adjustedX * (cw / rect.width); + adjustedY = adjustedY * (ch / rect.height); + + var coords = { x: adjustedX, y: adjustedY }; + + if (event.type === 'touchstart') { + Browser.lastTouches[touch.identifier] = coords; + Browser.touches[touch.identifier] = coords; + } else if (event.type === 'touchend' || event.type === 'touchmove') { + Browser.lastTouches[touch.identifier] = Browser.touches[touch.identifier]; + Browser.touches[touch.identifier] = { x: adjustedX, y: adjustedY }; + } + return; + } + + var x = event.pageX - (scrollX + rect.left); + var y = event.pageY - (scrollY + rect.top); + + // the canvas might be CSS-scaled compared to its backbuffer; + // SDL-using content will want mouse coordinates in terms + // of backbuffer units. + x = x * (cw / rect.width); + y = y * (ch / rect.height); + + Browser.mouseMovementX = x - Browser.mouseX; + Browser.mouseMovementY = y - Browser.mouseY; + Browser.mouseX = x; + Browser.mouseY = y; + } + },xhrLoad:function (url, onload, onerror) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = function xhr_onload() { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + } else { + onerror(); + } + }; + xhr.onerror = onerror; + xhr.send(null); + },asyncLoad:function (url, onload, onerror, noRunDep) { + Browser.xhrLoad(url, function(arrayBuffer) { + assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).'); + onload(new Uint8Array(arrayBuffer)); + if (!noRunDep) removeRunDependency('al ' + url); + }, function(event) { + if (onerror) { + onerror(); + } else { + throw 'Loading data file "' + url + '" failed.'; + } + }); + if (!noRunDep) addRunDependency('al ' + url); + },resizeListeners:[],updateResizeListeners:function () { + var canvas = Module['canvas']; + Browser.resizeListeners.forEach(function(listener) { + listener(canvas.width, canvas.height); + }); + },setCanvasSize:function (width, height, noUpdates) { + var canvas = Module['canvas']; + Browser.updateCanvasDimensions(canvas, width, height); + if (!noUpdates) Browser.updateResizeListeners(); + },windowedWidth:0,windowedHeight:0,setFullScreenCanvasSize:function () { + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags | 0x00800000; // set SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },setWindowedCanvasSize:function () { + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]; + flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag + HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags + } + Browser.updateResizeListeners(); + },updateCanvasDimensions:function (canvas, wNative, hNative) { + if (wNative && hNative) { + canvas.widthNative = wNative; + canvas.heightNative = hNative; + } else { + wNative = canvas.widthNative; + hNative = canvas.heightNative; + } + var w = wNative; + var h = hNative; + if (Module['forcedAspectRatio'] && Module['forcedAspectRatio'] > 0) { + if (w/h < Module['forcedAspectRatio']) { + w = Math.round(h * Module['forcedAspectRatio']); + } else { + h = Math.round(w / Module['forcedAspectRatio']); + } + } + if (((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || + document['mozFullScreenElement'] || document['mozFullscreenElement'] || + document['fullScreenElement'] || document['fullscreenElement'] || + document['msFullScreenElement'] || document['msFullscreenElement'] || + document['webkitCurrentFullScreenElement']) === canvas.parentNode) && (typeof screen != 'undefined')) { + var factor = Math.min(screen.width / w, screen.height / h); + w = Math.round(w * factor); + h = Math.round(h * factor); + } + if (Browser.resizeCanvas) { + if (canvas.width != w) canvas.width = w; + if (canvas.height != h) canvas.height = h; + if (typeof canvas.style != 'undefined') { + canvas.style.removeProperty( "width"); + canvas.style.removeProperty("height"); + } + } else { + if (canvas.width != wNative) canvas.width = wNative; + if (canvas.height != hNative) canvas.height = hNative; + if (typeof canvas.style != 'undefined') { + if (w != wNative || h != hNative) { + canvas.style.setProperty( "width", w + "px", "important"); + canvas.style.setProperty("height", h + "px", "important"); + } else { + canvas.style.removeProperty( "width"); + canvas.style.removeProperty("height"); + } + } + } + }}; + + function _sprintf(s, format, varargs) { + // int sprintf(char *restrict s, const char *restrict format, ...); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html + return _snprintf(s, undefined, format, varargs); + } + + + function __exit(status) { + // void _exit(int status); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html + Module['exit'](status); + }function _exit(status) { + __exit(status); + } + + function _isspace(chr) { + return (chr == 32) || (chr >= 9 && chr <= 13); + } + + + function _fmod(x, y) { + return x % y; + }var _fmodl=_fmod; + + function _sysconf(name) { + // long sysconf(int name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/sysconf.html + switch(name) { + case 30: return PAGE_SIZE; + case 132: + case 133: + case 12: + case 137: + case 138: + case 15: + case 235: + case 16: + case 17: + case 18: + case 19: + case 20: + case 149: + case 13: + case 10: + case 236: + case 153: + case 9: + case 21: + case 22: + case 159: + case 154: + case 14: + case 77: + case 78: + case 139: + case 80: + case 81: + case 79: + case 82: + case 68: + case 67: + case 164: + case 11: + case 29: + case 47: + case 48: + case 95: + case 52: + case 51: + case 46: + return 200809; + case 27: + case 246: + case 127: + case 128: + case 23: + case 24: + case 160: + case 161: + case 181: + case 182: + case 242: + case 183: + case 184: + case 243: + case 244: + case 245: + case 165: + case 178: + case 179: + case 49: + case 50: + case 168: + case 169: + case 175: + case 170: + case 171: + case 172: + case 97: + case 76: + case 32: + case 173: + case 35: + return -1; + case 176: + case 177: + case 7: + case 155: + case 8: + case 157: + case 125: + case 126: + case 92: + case 93: + case 129: + case 130: + case 131: + case 94: + case 91: + return 1; + case 74: + case 60: + case 69: + case 70: + case 4: + return 1024; + case 31: + case 42: + case 72: + return 32; + case 87: + case 26: + case 33: + return 2147483647; + case 34: + case 1: + return 47839; + case 38: + case 36: + return 99; + case 43: + case 37: + return 2048; + case 0: return 2097152; + case 3: return 65536; + case 28: return 32768; + case 44: return 32767; + case 75: return 16384; + case 39: return 1000; + case 89: return 700; + case 71: return 256; + case 40: return 255; + case 2: return 100; + case 180: return 64; + case 25: return 20; + case 5: return 16; + case 6: return 6; + case 73: return 4; + case 84: return 1; + } + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + + + Module["_tolower"] = _tolower; + + var _atan=Math_atan; + + + function _recv(fd, buf, len, flags) { + var sock = SOCKFS.getSocket(fd); + if (!sock) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + // TODO honor flags + return _read(fd, buf, len); + } + + function _pread(fildes, buf, nbyte, offset) { + // ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + try { + var slab = HEAP8; + return FS.read(stream, slab, buf, nbyte, offset); + } catch (e) { + FS.handleFSError(e); + return -1; + } + }function _read(fildes, buf, nbyte) { + // ssize_t read(int fildes, void *buf, size_t nbyte); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html + var stream = FS.getStream(fildes); + if (!stream) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + + + try { + var slab = HEAP8; + return FS.read(stream, slab, buf, nbyte); + } catch (e) { + FS.handleFSError(e); + return -1; + } + } + + function _time(ptr) { + var ret = Math.floor(Date.now()/1000); + if (ptr) { + HEAP32[((ptr)>>2)]=ret; + } + return ret; + } + + + + + + + var _environ=allocate(1, "i32*", ALLOC_STATIC);var ___environ=_environ;function ___buildEnvironment(env) { + // WARNING: Arbitrary limit! + var MAX_ENV_VALUES = 64; + var TOTAL_ENV_SIZE = 1024; + + // Statically allocate memory for the environment. + var poolPtr; + var envPtr; + if (!___buildEnvironment.called) { + ___buildEnvironment.called = true; + // Set default values. Use string keys for Closure Compiler compatibility. + ENV['USER'] = 'root'; + ENV['PATH'] = '/'; + ENV['PWD'] = '/'; + ENV['HOME'] = '/home/emscripten'; + ENV['LANG'] = 'en_US.UTF-8'; + ENV['_'] = './this.program'; + // Allocate memory. + poolPtr = allocate(TOTAL_ENV_SIZE, 'i8', ALLOC_STATIC); + envPtr = allocate(MAX_ENV_VALUES * 4, + 'i8*', ALLOC_STATIC); + HEAP32[((envPtr)>>2)]=poolPtr; + HEAP32[((_environ)>>2)]=envPtr; + } else { + envPtr = HEAP32[((_environ)>>2)]; + poolPtr = HEAP32[((envPtr)>>2)]; + } + + // Collect key=value lines. + var strings = []; + var totalSize = 0; + for (var key in env) { + if (typeof env[key] === 'string') { + var line = key + '=' + env[key]; + strings.push(line); + totalSize += line.length; + } + } + if (totalSize > TOTAL_ENV_SIZE) { + throw new Error('Environment size exceeded TOTAL_ENV_SIZE!'); + } + + // Make new. + var ptrSize = 4; + for (var i = 0; i < strings.length; i++) { + var line = strings[i]; + writeAsciiToMemory(line, poolPtr); + HEAP32[(((envPtr)+(i * ptrSize))>>2)]=poolPtr; + poolPtr += line.length + 1; + } + HEAP32[(((envPtr)+(strings.length * ptrSize))>>2)]=0; + }var ENV={};function _getenv(name) { + // char *getenv(const char *name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html + if (name === 0) return 0; + name = Pointer_stringify(name); + if (!ENV.hasOwnProperty(name)) return 0; + + if (_getenv.ret) _free(_getenv.ret); + _getenv.ret = allocate(intArrayFromString(ENV[name]), 'i8', ALLOC_NORMAL); + return _getenv.ret; + } + + + function _emscripten_memcpy_big(dest, src, num) { + HEAPU8.set(HEAPU8.subarray(src, src+num), dest); + return dest; + } + Module["_memcpy"] = _memcpy; + + var _log=Math_log; + + var _cos=Math_cos; + + var _llvm_pow_f64=Math_pow; + + function _sbrk(bytes) { + // Implement a Linux-like 'memory area' for our 'process'. + // Changes the size of the memory area by |bytes|; returns the + // address of the previous top ('break') of the memory area + // We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP + var self = _sbrk; + if (!self.called) { + DYNAMICTOP = alignMemoryPage(DYNAMICTOP); // make sure we start out aligned + self.called = true; + assert(Runtime.dynamicAlloc); + self.alloc = Runtime.dynamicAlloc; + Runtime.dynamicAlloc = function() { abort('cannot dynamically allocate, sbrk now has control') }; + } + var ret = DYNAMICTOP; + if (bytes != 0) self.alloc(bytes); + return ret; // Previous break location. + } + + function ___errno_location() { + return ___errno_state; + } + + var _BItoD=true; + + var _sin=Math_sin; + + var _atan2=Math_atan2; + + + Module["_strcpy"] = _strcpy; + + function _llvm_bswap_i32(x) { + return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24); + } + + + + function _islower(chr) { + return chr >= 97 && chr <= 122; + } + + var _exp=Math_exp; + + var _acos=Math_acos; + + function _isupper(chr) { + return chr >= 65 && chr <= 90; + } + +FS.staticInit();__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });__ATEXIT__.push({ func: function() { FS.quit() } });Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice; +___errno_state = Runtime.staticAlloc(4); HEAP32[((___errno_state)>>2)]=0; +__ATINIT__.unshift({ func: function() { TTY.init() } });__ATEXIT__.push({ func: function() { TTY.shutdown() } });TTY.utf8 = new Runtime.UTF8Processor(); +if (ENVIRONMENT_IS_NODE) { var fs = require("fs"); NODEFS.staticInit(); } +__ATINIT__.push({ func: function() { SOCKFS.root = FS.mount(SOCKFS, {}, null); } }); +Module["requestFullScreen"] = function Module_requestFullScreen(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) }; + Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) }; + Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) }; + Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() }; + Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() }; + Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() } +___buildEnvironment(ENV); +STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP); + +staticSealed = true; // seal the static portion of memory + +STACK_MAX = STACK_BASE + 5242880; + +DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX); + +assert(DYNAMIC_BASE < TOTAL_MEMORY, "TOTAL_MEMORY not big enough for stack"); + + var ctlz_i8 = allocate([8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], "i8", ALLOC_DYNAMIC); + var cttz_i8 = allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0], "i8", ALLOC_DYNAMIC); + +var Math_min = Math.min; +function invoke_iiii(index,a1,a2,a3) { + try { + return Module["dynCall_iiii"](index,a1,a2,a3); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_iddiii(index,a1,a2,a3,a4,a5) { + try { + return Module["dynCall_iddiii"](index,a1,a2,a3,a4,a5); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_vii(index,a1,a2) { + try { + Module["dynCall_vii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function invoke_iii(index,a1,a2) { + try { + return Module["dynCall_iii"](index,a1,a2); + } catch(e) { + if (typeof e !== 'number' && e !== 'longjmp') throw e; + asm["setThrew"](1, 0); + } +} + +function asmPrintInt(x, y) { + Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack); +} +function asmPrintFloat(x, y) { + Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack); +} +// EMSCRIPTEN_START_ASM +var asm=(function(global,env,buffer){"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=env.cttz_i8|0;var n=env.ctlz_i8|0;var o=env._stderr|0;var p=0;var q=0;var r=0;var s=0;var t=+env.NaN,u=+env.Infinity;var v=0,w=0,x=0,y=0,z=0.0,A=0,B=0,C=0,D=0.0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=0;var M=0;var N=0;var O=global.Math.floor;var P=global.Math.abs;var Q=global.Math.sqrt;var R=global.Math.pow;var S=global.Math.cos;var T=global.Math.sin;var U=global.Math.tan;var V=global.Math.acos;var W=global.Math.asin;var X=global.Math.atan;var Y=global.Math.atan2;var Z=global.Math.exp;var _=global.Math.log;var $=global.Math.ceil;var aa=global.Math.imul;var ba=env.abort;var ca=env.assert;var da=env.asmPrintInt;var ea=env.asmPrintFloat;var fa=env.min;var ga=env.invoke_iiii;var ha=env.invoke_iddiii;var ia=env.invoke_vii;var ja=env.invoke_iii;var ka=env._fabs;var la=env._sin;var ma=env._exp;var na=env._llvm_pow_f64;var oa=env._acos;var pa=env._atan2;var qa=env._fmod;var ra=env._lseek;var sa=env.__reallyNegative;var ta=env._asin;var ua=env._atan;var va=env.___buildEnvironment;var wa=env._fflush;var xa=env._pwrite;var ya=env._strerror_r;var za=env._fprintf;var Aa=env._open;var Ba=env._fabsf;var Ca=env._sbrk;var Da=env._send;var Ea=env._snprintf;var Fa=env._llvm_bswap_i32;var Ga=env._emscripten_memcpy_big;var Ha=env._fileno;var Ia=env._sysconf;var Ja=env.___setErrNo;var Ka=env._cos;var La=env._pread;var Ma=env._printf;var Na=env._sprintf;var Oa=env._log;var Pa=env._toupper;var Qa=env._write;var Ra=env._isupper;var Sa=env.___errno_location;var Ta=env._recv;var Ua=env._tan;var Va=env._copysign;var Wa=env._getenv;var Xa=env._mkport;var Ya=env.__exit;var Za=env._read;var _a=env._abort;var $a=env._islower;var ab=env._fwrite;var bb=env._time;var cb=env._isdigit;var db=env._strerror;var eb=env.__formatString;var fb=env._isspace;var gb=env._sqrt;var hb=env._exit;var ib=env._close;var jb=0.0; +// EMSCRIPTEN_START_FUNCS +function ob(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+7&-8;return b|0}function pb(){return i|0}function qb(a){a=a|0;i=a}function rb(a,b){a=a|0;b=b|0;if((p|0)==0){p=a;q=b}}function sb(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0]}function tb(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0];a[k+4|0]=a[b+4|0];a[k+5|0]=a[b+5|0];a[k+6|0]=a[b+6|0];a[k+7|0]=a[b+7|0]}function ub(a){a=a|0;E=a}function vb(a){a=a|0;F=a}function wb(a){a=a|0;G=a}function xb(a){a=a|0;H=a}function yb(a){a=a|0;I=a}function zb(a){a=a|0;J=a}function Ab(a){a=a|0;K=a}function Bb(a){a=a|0;L=a}function Cb(a){a=a|0;M=a}function Db(a){a=a|0;N=a}function Eb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;if((d|0)>0){f=Ob(b,d)|0}else{f=Pb(b)|0}b=(f|0)==0;if(!b){Xb(f,hc(f)|0)}d=c[1086]|0;if((d|0)==0){c[1086]=10;g=gg(41040)|0;c[1088]=g;if((g|0)==0){h=-4;i=e;return h|0}else{j=10}}else{j=d}d=c[1090]|0;a:do{if((d|0)<(j|0)){k=d}else{g=j;l=c[1088]|0;while(1){m=g+10|0;c[1086]=m;n=jg(l,m*4104|0)|0;c[1088]=n;if((n|0)==0){h=-3;break}m=c[1086]|0;o=c[1090]|0;if((o|0)<(m|0)){k=o;break a}else{g=m;l=n}}i=e;return h|0}}while(0);if(b){h=-1;i=e;return h|0}c[(c[1088]|0)+(k*4104|0)>>2]=f;f=c[1088]|0;c[f+(k*4104|0)+4>>2]=0;a[f+((c[1090]|0)*4104|0)+8|0]=0;c[1090]=(c[1090]|0)+1;h=k;i=e;return h|0}function Fb(b,d,e){b=b|0;d=+d;e=+e;var f=0,g=0,h=0,j=0,k=0;f=i;g=c[1088]|0;h=c[g+(b*4104|0)>>2]|0;if((h|0)==0){j=0;i=f;return j|0}k=g+(b*4104|0)+8|0;a[k]=0;dc(h,d+-1.0,e+-1.0,k,4096)|0;j=k;i=f;return j|0}function Gb(b,d,e){b=b|0;d=+d;e=+e;var f=0,g=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+4144|0;g=f+16|0;j=f+40|0;l=f+8|0;m=f;if((b|0)>0&(c[1086]|0)>(b|0)){n=(c[1088]|0)+(b*4104|0)|0}else{n=0}b=c[n>>2]|0;if((b|0)==0){o=0;i=f;return o|0}cc(b,d,e,l,m,f+32|0);e=+h[m>>3]+1.0;h[k>>3]=+h[l>>3]+1.0;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];l=g+8|0;h[k>>3]=e;c[l>>2]=c[k>>2];c[l+4>>2]=c[k+4>>2];Ea(j|0,4095,8,g|0)|0;g=n+8|0;n=a[j]|0;a:do{if(!(n<<24>>24==0)){l=j;m=n;while(1){b=l+1|0;if((fb(m<<24>>24|0)|0)==0){break}m=a[b]|0;if(m<<24>>24==0){break a}else{l=b}}m=a[l]|0;if(!(m<<24>>24==0)){b=g;p=l;q=m;while(1){m=p+1|0;r=b+1|0;a[b]=q;s=a[m]|0;if(s<<24>>24==0){break}else{b=r;p=m;q=s}}a[r]=0;if((r|0)==(g|0)){o=g;i=f;return o|0}q=r;p=r-g|0;while(1){b=q+ -1|0;if((fb(a[b]|0)|0)==0){o=g;t=14;break}a[b]=0;l=p+ -1|0;if((l|0)==0){o=g;t=14;break}else{q=b;p=l}}if((t|0)==14){i=f;return o|0}}}}while(0);a[g]=0;o=g;i=f;return o|0}function Hb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;if((b|0)>0&(c[1086]|0)>(b|0)){f=(c[1088]|0)+(b*4104|0)|0}else{f=0}b=c[f>>2]|0;if((b|0)==0){g=0;i=e;return g|0}h=f+8|0;a[h]=0;do{if((d|0)!=0?(a[d]|0)!=0:0){if(((xg(d,24)|0)!=0?(xg(d,40)|0)!=0:0)?(xg(d,56)|0)!=0:0){if(!(+oc(d)>0.0)){break}j=c[f>>2]|0}else{j=b}Xb(j,d)}}while(0);Hg(h|0,fc(c[f>>2]|0)|0,4096)|0;if((xg(h,24)|0)==0){k=h+0|0;l=24|0;m=k+9|0;do{a[k]=a[l]|0;k=k+1|0;l=l+1|0}while((k|0)<(m|0));g=h;i=e;return g|0}if((xg(h,40)|0)==0){k=h+0|0;l=40|0;m=k+9|0;do{a[k]=a[l]|0;k=k+1|0;l=l+1|0}while((k|0)<(m|0));g=h;i=e;return g|0}l=a[h]|0;if(l<<24>>24==0){g=h;i=e;return g|0}else{n=h;o=l}while(1){if(($a(o<<24>>24|0)|0)!=0){a[n]=Pa(a[n]|0)|0}l=n+1|0;k=a[l]|0;if(k<<24>>24==0){g=h;break}else{n=l;o=k}}i=e;return g|0}function Ib(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;if((b|0)>0&(c[1086]|0)>(b|0)){f=(c[1088]|0)+(b*4104|0)|0}else{f=0}b=c[f>>2]|0;if((b|0)==0){g=0;i=e;return g|0}h=f+8|0;a[h]=0;do{if((d|0)!=0?(a[d]|0)!=0:0){if((xg(d,64)|0)==0){gc(b,1)|0;c[f+4>>2]=1;break}else{gc(b,0)|0;c[f+4>>2]=0;break}}}while(0);b=c[f+4>>2]|0;if((b|0)==1){Hg(h|0,64,4095)|0}else if((b|0)==0){Hg(h|0,72,4095)|0}b=a[h]|0;if(b<<24>>24==0){g=h;i=e;return g|0}else{j=h;k=b}while(1){if((Ra(k<<24>>24|0)|0)!=0){a[j]=Jg(a[j]|0)|0}b=j+1|0;f=a[b]|0;if(f<<24>>24==0){g=h;break}else{j=b;k=f}}i=e;return g|0}function Jb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0.0,C=0.0,D=0,E=0.0,F=0.0,G=0,H=0,I=0.0,J=0.0,K=0.0;e=i;i=i+12352|0;f=e+32|0;g=e+56|0;j=e+4152|0;l=e+8248|0;m=e+48|0;n=e+52|0;o=e+24|0;p=e;q=e+8|0;r=e+16|0;if((b|0)>0&(c[1086]|0)>(b|0)){s=(c[1088]|0)+(b*4104|0)|0}else{s=0}c[m>>2]=0;c[n>>2]=0;if((c[s>>2]|0)==0){t=0;i=e;return t|0}u=Hb(b,0)|0;if(((yg(u,24)|0)!=0?(yg(u,40)|0)!=0:0)?(yg(u,56)|0)!=0:0){v=0}else{v=1}u=s+8|0;a[u]=0;b=cg(d)|0;d=fg(b,88)|0;if((d|0)!=0){w=s+4|0;x=(v|0)==0;v=d;do{d=$f(v,32)|0;if((d|0)==0){c[m>>2]=96;y=96;z=0}else{A=d+1|0;c[m>>2]=A;a[d]=0;y=A;z=v}B=+wg(y,n);if(B!=0.0?(C=+wg(c[n>>2]|0,m),C!=0.0):0){bc(c[s>>2]|0,B,C,o,p);A=(z|0)!=0;if(A){c[f>>2]=z;Ea(g|0,4096,104,f|0)|0;dg(u,g,4095)|0}d=c[w>>2]|0;if((d|0)==0){C=+h[o>>3];if(x){Tc(j,4095,C,3)}else{Uc(j,4095,C,3)}Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,128,f|0)|0;dg(u,g,4095)|0}else if((d|0)==1){C=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];d=f+8|0;h[k>>3]=C;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];Ea(g|0,4096,112,f|0)|0;dg(u,g,4095)|0}else{C=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];d=f+8|0;h[k>>3]=C;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];Ea(g|0,4096,112,f|0)|0;dg(u,g,4095)|0}d=(yg(z,136)|0)==0;C=+wg(c[m>>2]|0,n);D=C!=0.0;a:do{if(d){if(D){if(x){B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);G=c[w>>2]|0;if((G|0)==0){Tc(j,4095,+h[o>>3],3);Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,160,f|0)|0;dg(u,g,4095)|0}else if((G|0)==1){E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}else{E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}E=+wg(c[m>>2]|0,n);if(E!=0.0){B=E}else{F=E;break}}}else{B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);G=c[w>>2]|0;if((G|0)==1){E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];H=f+8|0;h[k>>3]=E;c[H>>2]=c[k>>2];c[H+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}else if((G|0)==0){Uc(j,4095,+h[o>>3],3);Uc(l,4095,+h[p>>3],3);c[f>>2]=j;c[f+4>>2]=l;Ea(g|0,4096,160,f|0)|0;dg(u,g,4095)|0}else{E=+h[p>>3];h[k>>3]=+h[o>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];G=f+8|0;h[k>>3]=E;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];Ea(g|0,4096,144,f|0)|0;dg(u,g,4095)|0}E=+wg(c[m>>2]|0,n);if(E!=0.0){B=E}else{F=E;break}}}}else{F=C}}else{if(D){B=C;while(1){E=+wg(c[n>>2]|0,m);if(!(E!=0.0)){F=B;break a}I=+wg(c[m>>2]|0,n);if(!(I!=0.0)){F=B;break a}J=+wg(c[n>>2]|0,m);if(!(J!=0.0)){F=B;break a}bc(c[s>>2]|0,B,E,o,p);bc(c[s>>2]|0,I,J,q,r);J=+ec(+h[o>>3],+h[p>>3],+h[q>>3],+h[r>>3])*3600.0;do{if(!(J<=60.0)){if(!(J<=3600.0)){h[k>>3]=J/3600.0;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,192,f|0)|0;dg(u,g,4095)|0;break}else{h[k>>3]=J/60.0;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,184,f|0)|0;dg(u,g,4095)|0;break}}else{h[k>>3]=J;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,176,f|0)|0;dg(u,g,4095)|0}}while(0);J=+wg(c[m>>2]|0,n);if(J!=0.0){B=J}else{F=J;break}}}else{F=C}}}while(0);if(!((yg(z,200)|0)!=0?(yg(z,208)|0)!=0:0)){if(F<0.0){C=F;while(1){B=C+6.283185307179586;if(B<0.0){C=B}else{K=B;break}}}else{K=F}h[k>>3]=K*57.29577951308232;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Ea(g|0,4096,216,f|0)|0;dg(u,g,4095)|0}if(A){Ea(g|0,4096,224,f|0)|0;dg(u,g,4095)|0}Ea(g|0,4096,88,f|0)|0;dg(u,g,4095)|0}v=fg(0,88)|0}while((v|0)!=0)}if((b|0)==0){t=u;i=e;return t|0}hg(b);t=u;i=e;return t|0}function Kb(a){a=a|0;var b=0,c=0.0;b=i;c=+af(a,0);i=b;return+c}function Lb(b,d,e,f,j,l,m){b=b|0;d=d|0;e=e|0;f=f|0;j=+j;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0;n=i;i=i+4128|0;o=n;p=n+20|0;q=n+16|0;r=n+24|0;bf(b,d,e,f,p,q,j,l,m);j=+g[q>>2];h[k>>3]=+g[p>>2];c[o>>2]=c[k>>2];c[o+4>>2]=c[k+4>>2];p=o+8|0;h[k>>3]=j;c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];Ea(r|0,4095,240,o|0)|0;o=a[r]|0;a:do{if(!(o<<24>>24==0)){p=r;q=o;while(1){m=p+1|0;if((fb(q<<24>>24|0)|0)==0){break}q=a[m]|0;if(q<<24>>24==0){break a}else{p=m}}q=a[p]|0;if(!(q<<24>>24==0)){m=248;l=p;f=q;while(1){q=l+1|0;s=m+1|0;a[m]=f;e=a[q]|0;if(e<<24>>24==0){break}else{m=s;l=q;f=e}}a[s]=0;if((s|0)==248){i=n;return 248}f=s;l=s-248|0;while(1){m=f+ -1|0;if((fb(a[m]|0)|0)==0){t=11;break}a[m]=0;p=l+ -1|0;if((p|0)==0){t=11;break}else{f=m;l=p}}if((t|0)==11){i=n;return 248}}}}while(0);a[248]=0;i=n;return 248}function Mb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0.0,ha=0.0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0.0,sa=0.0,ta=0.0,ua=0,va=0.0,wa=0,xa=0,ya=0.0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0.0,La=0.0,Ma=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0;e=i;i=i+1184|0;f=e+672|0;g=e+1176|0;j=e+1144|0;l=e+1112|0;m=e+1048|0;n=e+1040|0;p=e+1024|0;q=e+1032|0;r=e+1080|0;s=e+848|0;t=e;u=e+752|0;v=e+744|0;w=e+656|0;x=e+760|0;y=e+664|0;z=e+816|0;A=e+856|0;B=e+736|0;C=e+840|0;D=e+824|0;E=e+808|0;F=e+768|0;G=e+8|0;H=e+1088|0;I=e+868|0;J=e+864|0;K=e+872|0;L=e+880|0;M=e+960|0;N=e+1104|0;O=e+832|0;P=e+800|0;Q=e+728|0;R=ig(1,9336)|0;U=a[d]|0;d=U<<24>>24==32?0:U;a[N]=d;a[R+9324|0]=d;if((Oc(b,4424,N,63,M)|0)!=0){d=ig((Dg(M|0)|0)+2|0,1)|0;c[R+9320>>2]=d;Lg(d|0,M|0)|0}d=R+3984|0;c[d>>2]=0;c[R+3956>>2]=0;c[R+3924>>2]=0;c[R+3952>>2]=-1;U=R+3268|0;c[U>>2]=0;V=R+3272|0;c[V>>2]=0;h[D>>3]=0.0;h[E>>3]=0.0;W=F+8|0;X=F+16|0;Y=F+24|0;c[F+0>>2]=0;c[F+4>>2]=0;c[F+8>>2]=0;c[F+12>>2]=0;c[F+16>>2]=0;c[F+20>>2]=0;c[F+24>>2]=0;c[F+28>>2]=0;h[G>>3]=0.0;Z=R+3300|0;c[Z>>2]=0;_=R+48|0;h[_>>3]=0.0;c[K>>2]=0;Dc(b,4432,N,K)|0;$=c[K>>2]|0;if(($|0)==0){Ec(b,4432,K)|0;ba=c[K>>2]|0;if((ba|0)==0){Ec(b,4440,K)|0;ca=c[K>>2]|0;if((ca|0)==0){Ec(b,4448,K)|0;da=c[K>>2]|0}else{da=ca}}else{da=ba}}else{da=$}if((da|0)<1){_b(4456);Tb(R);ea=0;i=e;return ea|0}if((da|0)>2){c[K>>2]=2;fa=2}else{fa=da}da=R+3316|0;c[da>>2]=fa;$=R+3320|0;c[$>>2]=fa;c[R+3960>>2]=fa;fa=R+136|0;h[fa>>3]=0.0;Lc(b,4504,fa)|0;ga=+h[fa>>3];if(ga<1.0){Lc(b,4512,fa)|0;ha=+h[fa>>3]}else{ha=ga}if(ha<1.0){_b(4520);Tb(R);ea=0;i=e;return ea|0}ba=R+144|0;h[ba>>3]=0.0;Lc(b,4560,ba)|0;if(+h[ba>>3]<1.0){Lc(b,4568,ba)|0}ca=c[K>>2]|0;if((ca|0)>1){if(+h[ba>>3]<1.0){_b(4576);Tb(R);ea=0;i=e;return ea|0}else{ia=19}}else{if((ca|0)>0){ia=19}else{ja=0}}if((ia|0)==19){ca=c[o>>2]|0;ka=0;la=0;while(1){a[H+0|0]=a[4440|0]|0;a[H+1|0]=a[4441|0]|0;a[H+2|0]=a[4442|0]|0;a[H+3|0]=a[4443|0]|0;a[H+4|0]=a[4444|0]|0;a[H+5|0]=a[4445|0]|0;ma=ka+1|0;c[f>>2]=ma;Na(L|0,4616,f|0)|0;Fg(H|0,L|0)|0;do{if((Ec(b,H,J)|0)==0){if((ka|0)==0){ha=+h[fa>>3];if(ha>1.0){c[J>>2]=~~ha;break}}else if((ka|0)==1?(ha=+h[ba>>3],ha>1.0):0){c[J>>2]=~~ha;break}c[f>>2]=H;za(ca|0,4624,f|0)|0}}while(0);a[H+0|0]=a[4664|0]|0;a[H+1|0]=a[4665|0]|0;a[H+2|0]=a[4666|0]|0;a[H+3|0]=a[4667|0]|0;a[H+4|0]=a[4668|0]|0;a[H+5|0]=a[4669|0]|0;Fg(H|0,L|0)|0;if((Pc(b,H,16,L)|0)!=0?(Qc(L,4672)|0)!=0:0){c[J>>2]=0}na=((c[J>>2]|0)>1)+la|0;if((ma|0)<(c[K>>2]|0)){ka=ma;la=na}else{ja=na;break}}}c[K>>2]=ja;c[$>>2]=ja;c[da>>2]=ja;Pc(b,4680,16,R+3336|0)|0;Ec(b,4696,R+3332|0)|0;ja=R+3324|0;c[ja>>2]=kc()|0;$=R+9328|0;c[$>>2]=0;Ec(b,4712,$)|0;$=R+832|0;Eg($|0,0,648)|0;Eg(G|0,0,648)|0;la=c[K>>2]|0;ka=(la|0)>0;if(ka){ca=0;do{h[$+((aa(la,ca)|0)+ca<<3)>>3]=1.0;ca=ca+1|0}while((ca|0)<(la|0));if(ka){ca=0;do{h[G+((aa(la,ca)|0)+ca<<3)>>3]=1.0;ca=ca+1|0}while((ca|0)<(la|0));ca=R+760|0;oa=ca+0|0;pa=oa+72|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));if(ka){ka=0;while(1){h[ca+(ka<<3)>>3]=1.0;na=ka+1|0;if((na|0)<(la|0)){ka=na}else{qa=ca;break}}}else{qa=ca}}else{ia=37}}else{ia=37}if((ia|0)==37){ca=R+760|0;oa=ca+0|0;pa=oa+72|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));qa=ca}do{if((Oc(b,4720,N,63,M)|0)==0){c[R+9312>>2]=0}else{ca=Nb(b,M)|0;a[g]=ca;if(!(ca<<24>>24==95)){ca=Mb(b,g)|0;c[R+9312>>2]=ca;if((ca|0)!=0){c[ca+9316>>2]=R;break}}else{ca=c[o>>2]|0;c[f>>2]=M;za(ca|0,4368,f|0)|0;c[R+9312>>2]=0}_b(4728);Tb(R);ea=0;i=e;return ea|0}}while(0);M=R+3224|0;g=R+3232|0;c[M+0>>2]=0;c[M+4>>2]=0;c[M+8>>2]=0;c[M+12>>2]=0;do{if((Kc(b,4776,N,M)|0)==0){if((Kc(b,4784,N,g)|0)!=0){h[M>>3]=+h[g>>3]*299792.5;break}if((Lc(b,4792,M)|0)!=0){h[g>>3]=+h[M>>3]/299792.5}}else{h[g>>3]=+h[M>>3]/299792.5}}while(0);M=R+4096|0;oa=M+0|0;pa=oa+80|0;do{c[oa>>2]=0;oa=oa+4|0}while((oa|0)<(pa|0));do{if((Oc(b,4808,N,16,j)|0)==0){g=a[N]|0;if(!(g<<24>>24==32|g<<24>>24==0)){c[f>>2]=g<<24>>24;Na(L|0,5368,f|0)|0;_b(L);Tb(R);ea=0;i=e;return ea|0}if((Cc(b,5408)|0)!=0){c[R+3260>>2]=29;g=Cc(b,5408)|0;Lc(g,5408,s)|0;Lc(g,5416,t)|0;Lc(g,5424,u)|0;h[R+152>>3]=(+h[s>>3]+ +h[t>>3]/60.0+ +h[u>>3]/3600.0)*15.0*3.141592653589793/180.0;a[r]=43;Pc(g,5432,1,r)|0;ha=(a[r]|0)==45?-1.0:1.0;Lc(g,5448,v)|0;Lc(g,5456,w)|0;Lc(g,5464,x)|0;h[R+160>>3]=ha*(+h[v>>3]+ +h[w>>3]/60.0+ +h[x>>3]/3600.0)*3.141592653589793/180.0;g=R+120|0;Lc(b,5472,g)|0;Ec(b,5472,I)|0;ca=R+3764|0;ka=(c[I>>2]|0)==1950?3427142:3492678;a[ca]=ka;a[ca+1|0]=ka>>8;a[ca+2|0]=ka>>16;a[ca+3|0]=ka>>24;ka=R+128|0;h[ka>>3]=+h[g>>3];Lc(b,5344,ka)|0;ha=+h[t>>3];ga=+h[u>>3];ka=a[r]|0;ra=+h[v>>3];sa=+h[w>>3];ta=+h[x>>3];h[k>>3]=+h[s>>3];c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];g=f+8|0;h[k>>3]=ha;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];g=f+16|0;h[k>>3]=ga;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];c[f+24>>2]=ka;ka=f+28|0;h[k>>3]=ra;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];ka=f+36|0;h[k>>3]=sa;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];ka=f+44|0;h[k>>3]=ta;c[ka>>2]=c[k>>2];c[ka+4>>2]=c[k+4>>2];c[f+52>>2]=ca;Na(R+3892|0,5496,f|0)|0;Lc(b,5544,R+168|0)|0;Lc(b,5560,R+192|0)|0;Lc(b,5576,R+200|0)|0;Lc(b,5592,R+176|0)|0;Lc(b,5600,R+184|0)|0;ca=Cc(b,5608)|0;ka=R+208|0;c[f>>2]=1;Na(H|0,5616,f|0)|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=2;Na(H|0,5616,f|0)|0;ka=R+216|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=3;Na(H|0,5616,f|0)|0;ka=R+224|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=4;Na(H|0,5616,f|0)|0;ka=R+232|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=5;Na(H|0,5616,f|0)|0;ka=R+240|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;c[f>>2]=6;Na(H|0,5616,f|0)|0;ka=R+248|0;h[ka>>3]=0.0;Lc(ca,H,ka)|0;ka=Cc(b,5624)|0;ca=R+256|0;g=0;while(1){la=g+1|0;c[f>>2]=la;Na(H|0,5632,f|0)|0;na=ca+(g<<3)|0;h[na>>3]=0.0;Lc(ka,H,na)|0;if((la|0)==20){break}else{g=la}}g=Cc(b,5640)|0;ka=R+416|0;ca=0;while(1){ma=ca+1|0;c[f>>2]=ma;Na(H|0,5648,f|0)|0;la=ka+(ca<<3)|0;h[la>>3]=0.0;Lc(g,H,la)|0;if((ma|0)==20){break}else{ca=ma}}ca=R+3312|0;c[ca>>2]=1;g=R+3449|0;a[g+0|0]=a[5656|0]|0;a[g+1|0]=a[5657|0]|0;a[g+2|0]=a[5658|0]|0;g=R+3458|0;a[g]=4408644;a[g+1|0]=17221;a[g+2|0]=67;a[g+3|0]=0;g=R+3467|0;a[g]=5460804;a[g+1|0]=21331;a[g+2|0]=83;a[g+3|0]=0;c[R+3292>>2]=0;c[R+3288>>2]=3;oa=R+3368|0;g=5664|0;pa=oa+9|0;do{a[oa]=a[g]|0;oa=oa+1|0;g=g+1|0}while((oa|0)<(pa|0));oa=R+3377|0;g=5680|0;pa=oa+9|0;do{a[oa]=a[g]|0;oa=oa+1|0;g=g+1|0}while((oa|0)<(pa|0));ta=+h[fa>>3]*.5;g=R+616|0;h[g>>3]=ta;sa=+h[ba>>3]*.5;ka=R+624|0;h[ka>>3]=sa;h[R+16>>3]=ta;h[R+24>>3]=sa;nd(ta,sa,R,z,B)|0;sa=+h[z>>3];h[R+688>>3]=sa;ta=+h[B>>3];h[R+696>>3]=ta;h[R>>3]=sa;h[R+8>>3]=ta;nd(+h[g>>3],+h[ka>>3]+1.0,R,A,C)|0;ta=+h[C>>3]- +h[B>>3];h[R+40>>3]=ta;h[R+32>>3]=-ta;Sb(R);c[ca>>2]=1;ac(R);ta=+h[_>>3]*3.141592653589793/180.0;h[P>>3]=ta;sa=+h[g>>3]+ +S(+ta);nd(sa,+h[ka>>3]+ +T(+ta),R,A,C)|0;h[qa>>3]=-+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);ta=+h[P>>3];sa=+h[g>>3]+ +T(+ta);nd(sa,+h[ka>>3]+ +S(+ta),R,A,C)|0;ta=+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[R+768>>3]=ta;Wb(R,+h[qa>>3],ta,+h[_>>3]);ua=qa;break}if(((((Cc(b,5088)|0)==0?(Cc(b,5096)|0)==0:0)?(Cc(b,5112)|0)==0:0)?(Cc(b,5128)|0)==0:0)?(Cc(b,5144)|0)==0:0){_b(5824);Tb(R);ea=0;i=e;return ea|0}h[y>>3]=0.0;Lc(b,5088,y)|0;ta=+h[y>>3];if(ta==0.0){Lc(b,5096,y)|0;va=+h[y>>3]}else{va=ta}do{if(va==0.0){Lc(b,5144,y)|0;ta=+h[y>>3];if(ta!=0.0){h[D>>3]=-ta/3600.0;Lc(b,5152,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}Lc(b,5128,y)|0;ta=+h[y>>3];if(ta!=0.0){h[D>>3]=-ta/3600.0;Lc(b,5160,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}else{Lc(b,5112,y)|0;h[D>>3]=-+h[y>>3]/3600.0;Lc(b,5176,y)|0;h[E>>3]=+h[y>>3]/3600.0;break}}else{ta=va/3600.0;h[E>>3]=ta;h[D>>3]=-ta}}while(0);h[P>>3]=0.0;Lc(b,5256,P)|0;if(+h[_>>3]==0.0){Lc(b,5248,P)|0}Wb(R,+h[D>>3],+h[E>>3],+h[P>>3]);ca=R+616|0;h[ca>>3]=+h[fa>>3]*.5+.5;ka=R+624|0;h[ka>>3]=+h[ba>>3]*.5+.5;if((Cc(b,4904)|0)!=0){Lc(b,4904,ca)|0;Lc(b,4912,ka)|0}h[R+16>>3]=+h[ca>>3];h[R+24>>3]=+h[ka>>3];ka=R+688|0;h[ka>>3]=-999.0;if((Hc(b,5656,ka)|0)==0){_b(5696);Tb(R);ea=0;i=e;return ea|0}ca=R+696|0;h[ca>>3]=-999.0;if((Ic(b,4832,ca)|0)==0){_b(5736);Tb(R);ea=0;i=e;return ea|0}ta=+h[ka>>3];h[R>>3]=ta;sa=+h[ca>>3];h[R+8>>3]=sa;ca=R+3304|0;c[ca>>2]=0;h[R+3992>>3]=ta;h[R+4e3>>3]=sa;ka=R+4008|0;h[ka>>3]=999.0;if((Lc(b,4936,ka)|0)==0){Lc(b,5776,ka)|0}ka=R+4016|0;h[ka>>3]=999.0;Lc(b,4944,ka)|0;do{if((Lc(b,5312,O)|0)==0){ka=R+128|0;if((Mc(b,5320,ka)|0)==0){if((Mc(b,5336,ka)|0)!=0){break}if((Lc(b,5344,ka)|0)!=0){break}h[ka>>3]=+h[R+120>>3];break}Pc(b,5320,32,m)|0;if(($f(m,84)|0)==0){if((Lc(b,5352,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744;break}if((Lc(b,5360,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744}}}else{h[R+128>>3]=(+h[O>>3]+-15019.81352)/365.242198781+1900.0}}while(0);Vb(R,5792,5808)|0;c[ca>>2]=0;a[f]=0;Rb(b,R,f);Sb(R);c[R+3292>>2]=0;c[R+3288>>2]=3;c[R+3312>>2]=1;ua=qa}else{Lg(l|0,j|0)|0;ka=(Oc(b,4816,N,16,l)|0)==0;Lg(R+3368|0,j|0)|0;Lg(R+3377|0,l|0)|0;if((Qc(l,4824)|0)==0){g=(Qc(l,4832)|0)==0;wa=g?1:2}else{wa=2}g=R+3386|0;a[g]=0;Oc(b,4840,N,9,g)|0;g=R+3395|0;a[g]=0;Oc(b,4848,N,9,g)|0;if((Vb(R,j,l)|0)!=0){Tb(R);ea=0;i=e;return ea|0}g=R+3260|0;if((c[g>>2]|0)==0){ma=R+3476|0;if((Oc(b,4856,N,16,ma)|0)==0?(Yc(b,4864,4872,16,ma)|0)==0:0){a[ma]=0}if((yg(ma,4880)|0)==0){c[g>>2]=-1}if(!ka){ka=R+3508|0;if((Oc(b,4888,N,16,ka)|0)==0?(Yc(b,4896,4872,16,ka)|0)==0:0){a[ka]=0}if((yg(ma,4880)|0)==0){c[g>>2]=-1}}}ma=R+616|0;h[ma>>3]=1.0;Kc(b,4904,N,ma)|0;ka=R+624|0;h[ka>>3]=1.0;Kc(b,4912,N,ka)|0;h[R+16>>3]=+h[ma>>3];h[R+24>>3]=+h[ka>>3];la=R+688|0;h[la>>3]=0.0;Kc(b,4920,N,la)|0;na=R+696|0;h[na>>3]=0.0;Kc(b,4928,N,na)|0;xa=c[R+3884>>2]|0;if((xa|0)==7){h[na>>3]=90.0- +h[na>>3];ia=74}else if((xa|0)==8){sa=+h[na>>3]+-90.0;h[na>>3]=sa;ya=sa}else{ia=74}if((ia|0)==74){ya=+h[na>>3]}sa=+h[la>>3];h[R>>3]=sa;h[R+8>>3]=ya;la=R+3992|0;if((c[R+3304>>2]|0)==0){h[la>>3]=sa;h[R+4e3>>3]=ya}else{h[la>>3]=ya;h[R+4e3>>3]=sa}la=R+3176|0;h[la>>3]=999.0;Kc(b,4936,N,la)|0;h[R+4008>>3]=+h[la>>3];la=R+3184|0;h[la>>3]=999.0;Kc(b,4944,N,la)|0;h[R+4016>>3]=+h[la>>3];c[R+3964>>2]=ma;c[R+3972>>2]=qa;c[R+3968>>2]=$;la=R+4088|0;h[la>>3]=0.0;Kc(b,4952,N,la)|0;c[f>>2]=0;Na(H|0,4960,f|0)|0;Kc(b,H,N,M)|0;c[f>>2]=1;Na(H|0,4960,f|0)|0;la=R+4104|0;Kc(b,H,N,la)|0;c[f>>2]=2;Na(H|0,4960,f|0)|0;na=R+4112|0;Kc(b,H,N,na)|0;c[f>>2]=3;Na(H|0,4960,f|0)|0;xa=R+4120|0;Kc(b,H,N,xa)|0;c[f>>2]=4;Na(H|0,4960,f|0)|0;Aa=R+4128|0;Kc(b,H,N,Aa)|0;c[f>>2]=5;Na(H|0,4960,f|0)|0;Ba=R+4136|0;Kc(b,H,N,Ba)|0;c[f>>2]=6;Na(H|0,4960,f|0)|0;Ca=R+4144|0;Kc(b,H,N,Ca)|0;c[f>>2]=7;Na(H|0,4960,f|0)|0;Da=R+4152|0;Kc(b,H,N,Da)|0;c[f>>2]=8;Na(H|0,4960,f|0)|0;Ea=R+4160|0;Kc(b,H,N,Ea)|0;c[f>>2]=9;Na(H|0,4960,f|0)|0;Fa=R+4168|0;Kc(b,H,N,Fa)|0;c[f>>2]=wa;Na(n|0,4968,f|0)|0;c[f>>2]=wa;Na(p|0,4976,f|0)|0;c[f>>2]=wa;Na(q|0,4984,f|0)|0;Ga=c[g>>2]|0;switch(Ga|0){case 7:{c[f>>2]=wa;c[f+4>>2]=0;Na(H|0,4992,f|0)|0;Kc(b,H,N,M)|0;c[f>>2]=wa;c[f+4>>2]=1;Na(H|0,4992,f|0)|0;Kc(b,H,N,la)|0;c[f>>2]=wa;c[f+4>>2]=2;Na(H|0,4992,f|0)|0;Kc(b,H,N,na)|0;c[f>>2]=wa;c[f+4>>2]=3;Na(H|0,4992,f|0)|0;Kc(b,H,N,xa)|0;c[f>>2]=wa;c[f+4>>2]=4;Na(H|0,4992,f|0)|0;Kc(b,H,N,Aa)|0;c[f>>2]=wa;c[f+4>>2]=5;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ba)|0;c[f>>2]=wa;c[f+4>>2]=6;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ca)|0;c[f>>2]=wa;c[f+4>>2]=7;Na(H|0,4992,f|0)|0;Kc(b,H,N,Da)|0;c[f>>2]=wa;c[f+4>>2]=8;Na(H|0,4992,f|0)|0;Kc(b,H,N,Ea)|0;c[f>>2]=wa;c[f+4>>2]=9;Na(H|0,4992,f|0)|0;Kc(b,H,N,Fa)|0;ia=97;break};case 17:case 15:case 16:case 14:case 4:case 1:{Kc(b,n,N,R+4104|0)|0;Kc(b,p,N,R+4112|0)|0;ia=97;break};case 2:{Kc(b,n,N,R+4104|0)|0;Kc(b,p,N,R+4112|0)|0;Fa=R+4120|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=90.0}Kc(b,q,N,Fa)|0;ia=97;break};case 13:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,n,N,Fa)|0;ia=97;break};case 10:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,n,N,Fa)|0;Fa=R+4112|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=1.0}Kc(b,p,N,Fa)|0;ia=97;break};case 9:{Fa=R+4104|0;if(+h[Fa>>3]==0.0){h[Fa>>3]=90.0}Kc(b,n,N,Fa)|0;ia=97;break};case 18:{Kc(b,n,N,R+4104|0)|0;ia=97;break};default:{Ha=Ga}}if((ia|0)==97){Ha=c[g>>2]|0}do{if((Ha|0)==31){if((dd(b,R)|0)==0){Ia=c[g>>2]|0;ia=102;break}else{a[R+3374|0]=65;a[R+3375|0]=78;a[R+3383|0]=65;a[R+3384|0]=78;c[g>>2]=3;break}}else{Ia=Ha;ia=102}}while(0);a:do{if((ia|0)==102){do{if((Ia|0)==32){if((kd(b,R)|0)==0){Ja=c[g>>2]|0;break}else{a[R+3375|0]=78;a[R+3384|0]=78;c[g>>2]=7;break a}}else{Ja=Ia}}while(0);if((Ja|0)==33){a[R+3374|0]=65;a[R+3375|0]=78;a[R+3383|0]=65;a[R+3384|0]=78;c[g>>2]=3}}}while(0);if((c[ja>>2]|0)>0){Rb(b,R,N)}Sb(R);Ye(R,b);c[U>>2]=0;c[V>>2]=0;ca=Kc(b,5e3,N,F)|0;Ga=Kc(b,5008,N,W)|0;Fa=Kc(b,5016,N,X)|0;Ea=Kc(b,5024,N,Y)|0;if((c[ja>>2]|0)!=2?(Da=Cc(b,5032)|0,(Da|0)!=0):0){c[g>>2]=30;Ca=R+3467|0;a[Ca+0|0]=a[5040|0]|0;a[Ca+1|0]=a[5041|0]|0;a[Ca+2|0]=a[5042|0]|0;a[Ca+3|0]=a[5043|0]|0;a[Ca+4|0]=a[5044|0]|0;a[Ca+5|0]=a[5045|0]|0;Ca=R+256|0;Ba=0;while(1){Aa=Ba+1|0;c[f>>2]=Aa;Na(H|0,5048,f|0)|0;xa=Ca+(Ba<<3)|0;h[xa>>3]=0.0;if((Lc(Da,H,xa)|0)!=0){c[U>>2]=Aa}if((Aa|0)==20){break}else{Ba=Aa}}Ba=Cc(b,5056)|0;Da=R+416|0;Ca=0;while(1){Aa=Ca+1|0;c[f>>2]=Aa;Na(H|0,5064,f|0)|0;xa=Da+(Ca<<3)|0;h[xa>>3]=0.0;if((Lc(Ba,H,xa)|0)!=0){c[V>>2]=Aa}if((Aa|0)==20){break}else{Ca=Aa}}bd(+h[ma>>3],+h[ka>>3],R,z,B)|0;bd(+h[ma>>3],+h[ka>>3]+1.0,R,A,C)|0;sa=+h[C>>3]- +h[B>>3];Ca=R+40|0;h[Ca>>3]=sa;Ba=R+32|0;h[Ba>>3]=-sa;c[R+3312>>2]=1;ac(R);h[P>>3]=+h[_>>3]*3.141592653589793/180.0;bd(+h[ma>>3],+h[ka>>3],R,z,B)|0;sa=+h[P>>3];ta=+h[ma>>3]+ +S(+sa);bd(ta,+h[ka>>3]+ +T(+sa),R,A,C)|0;sa=-+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[qa>>3]=sa;h[Ba>>3]=sa;sa=+h[P>>3];ta=+h[ma>>3]+ +T(+sa);bd(ta,+h[ka>>3]+ +S(+sa),R,A,C)|0;sa=+ec(+h[z>>3],+h[B>>3],+h[A>>3],+h[C>>3]);h[R+768>>3]=sa;h[Ca>>3]=sa;Ca=R+56|0;h[Ca>>3]=+h[F>>3];h[R+64>>3]=+h[W>>3];h[R+72>>3]=+h[X>>3];h[R+80>>3]=+h[Y>>3];Bd(2,Ca,R+88|0)|0}else{ia=121}do{if((ia|0)==121){if((Ga|ca|Fa|Ea|0)!=0){c[Z>>2]=1;Zb(R,F);break}if((Kc(b,5072,N,D)|0)==0){h[R+32>>3]=1.0;h[R+40>>3]=1.0;h[qa>>3]=1.0;h[R+768>>3]=1.0;h[_>>3]=0.0;c[Z>>2]=0;_b(5264);break}Kc(b,5080,N,E)|0;if(!(+h[D>>3]==0.0)){if(+h[ba>>3]>1.0){sa=+h[E>>3];if(sa==0.0){ia=127}else{Ka=sa}}else{ia=154}}else{ia=127}do{if((ia|0)==127){if(((((Cc(b,5088)|0)==0?(Cc(b,5096)|0)==0:0)?(Cc(b,5112)|0)==0:0)?(Cc(b,5128)|0)==0:0)?(Cc(b,5144)|0)==0:0){ia=154;break}h[y>>3]=0.0;Lc(b,5088,y)|0;sa=+h[y>>3];if(sa==0.0){Lc(b,5096,y)|0;La=+h[y>>3]}else{La=sa}if(!(La==0.0)){if(+h[D>>3]==0.0){h[D>>3]=-La/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}sa=La/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5144,y)|0;sa=+h[y>>3];if(sa!=0.0){if(+h[D>>3]==0.0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}Lc(b,5152,y)|0;sa=+h[y>>3]/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5128,y)|0;sa=+h[y>>3];if(sa!=0.0){if(+h[D>>3]==0.0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(!(sa==0.0)){Ka=sa;break}Lc(b,5160,y)|0;sa=+h[y>>3]/3600.0;h[E>>3]=sa;Ka=sa;break}Lc(b,5112,y)|0;sa=+h[y>>3];if(sa!=0.0?+h[D>>3]==0.0:0){h[D>>3]=-sa/3600.0}sa=+h[E>>3];if(sa==0.0){Lc(b,5176,y)|0;ta=+h[y>>3]/3600.0;h[E>>3]=ta;Ka=ta}else{Ka=sa}}}while(0);if((ia|0)==154){Ka=+h[E>>3]}if(Ka==0.0?+h[ba>>3]>1.0:0){h[E>>3]=-+h[D>>3]}h[R+776>>3]=1.0;h[R+784>>3]=1.0;Eg(G|0,0,648)|0;Eg($|0,0,648)|0;Ca=c[K>>2]|0;if((Ca|0)>0){Ba=0;do{h[G+((aa(Ca,Ba)|0)+Ba<<3)>>3]=1.0;Ba=Ba+1|0}while((Ba|0)<(Ca|0))}if((a[N]|0)==0?(Lc(b,5192,G)|0)!=0:0){Ca=c[K>>2]|0;if((Ca|0)>0){Ba=Ca;Ca=0;Da=0;while(1){c[J>>2]=0;Aa=Ca+1|0;if((Ba|0)>0){xa=0;na=Da;while(1){la=G+(na<<3)|0;h[la>>3]=(Ca|0)==(xa|0)?1.0:0.0;c[f>>2]=Aa;c[f+4>>2]=xa+1;Na(H|0,5208,f|0)|0;Ma=na+1|0;Lc(b,H,la)|0;la=(c[J>>2]|0)+1|0;c[J>>2]=la;Oa=c[K>>2]|0;if((la|0)<(Oa|0)){xa=la;na=Ma}else{Pa=Oa;Qa=Ma;break}}}else{Pa=Ba;Qa=Da}if((Aa|0)<(Pa|0)){Ba=Pa;Ca=Aa;Da=Qa}else{break}}}$b(R,+h[D>>3],+h[E>>3],G);break}if((Kc(b,5224,N,G)|0)==0){h[P>>3]=0.0;if((wa|0)==2){Kc(b,5248,N,P)|0}else{Kc(b,5256,N,P)|0}Wb(R,+h[D>>3],+h[E>>3],+h[P>>3]);break}Da=c[K>>2]|0;if((Da|0)>0){Ca=Da;Da=0;Ba=0;while(1){c[J>>2]=0;na=Da+1|0;if((Ca|0)>0){xa=0;Ma=Ba;while(1){Oa=G+(Ma<<3)|0;h[Oa>>3]=(Da|0)==(xa|0)?1.0:0.0;c[f>>2]=na;c[f+4>>2]=xa+1;Na(H|0,5232,f|0)|0;la=Ma+1|0;Kc(b,H,N,Oa)|0;Oa=(c[J>>2]|0)+1|0;c[J>>2]=Oa;Ra=c[K>>2]|0;if((Oa|0)<(Ra|0)){xa=Oa;Ma=la}else{Sa=Ra;Ta=la;break}}}else{Sa=Ca;Ta=Ba}if((na|0)<(Sa|0)){Ca=Sa;Da=na;Ba=Ta}else{break}}}$b(R,+h[D>>3],+h[E>>3],G)}}while(0);if((c[g>>2]|0)==3?(c[da>>2]|0)==2:0){Ea=R+3168|0;Fa=c[Ea>>2]|0;if((Fa|0)!=0){rd(Fa);c[Ea>>2]=0}Ea=R+3172|0;Fa=c[Ea>>2]|0;if((Fa|0)!=0){rd(Fa);c[Ea>>2]=0}c[R+1560>>2]=0;Ea=R+1568|0;Fa=R+4344|0;ca=0;do{h[Ea+(ca<<3)>>3]=0.0;h[Fa+(ca<<3)>>3]=0.0;ca=ca+1|0}while((ca|0)!=200);c[J>>2]=0;ca=0;g=0;while(1){c[f>>2]=1;c[f+4>>2]=g;Na(H|0,4992,f|0)|0;if((Kc(b,H,N,Ea+(c[J>>2]<<3)|0)|0)==0){Ga=c[J>>2]|0;h[Ea+(Ga<<3)>>3]=0.0;Ua=Ga;Va=ca}else{Ua=c[J>>2]|0;Va=ca+1|0}g=Ua+1|0;c[J>>2]=g;if((g|0)>=100){break}else{ca=Va}}c[J>>2]=0;ca=Va;g=0;while(1){c[f>>2]=2;c[f+4>>2]=g;Na(H|0,4992,f|0)|0;if((Kc(b,H,N,Ea+((c[J>>2]|0)+100<<3)|0)|0)==0){Ga=c[J>>2]|0;h[Ea+(Ga+100<<3)>>3]=0.0;Wa=Ga;Xa=ca}else{Wa=c[J>>2]|0;Xa=ca+1|0}g=Wa+1|0;c[J>>2]=g;if((g|0)>=100){break}else{ca=Xa}}if((Xa|0)>0){ca=R+3948|0;g=R+3944|0;Ga=100;ka=0;while(1){sa=+h[Ea+(((c[ca>>2]|0)*100|0)+Ga<<3)>>3];h[Fa+(Ga<<3)>>3]=sa;ta=+h[Ea+(((c[g>>2]|0)*100|0)+Ga<<3)>>3];h[Fa+(Ga+100<<3)>>3]=ta;if((ka|0)==0){Ya=sa!=0.0|ta!=0.0?Ga+1|0:0}else{Ya=ka}if((Ga|0)>0){Ga=Ga+ -1|0;ka=Ya}else{break}}Qb(R);c[d>>2]=0}}ka=R+3467|0;if(!((Ag(ka,5296,6)|0)!=0?(Ag(ka,5304,5)|0)!=0:0)){c[R+3292>>2]=-1;c[R+3288>>2]=5}do{if((Lc(b,5312,O)|0)==0){ka=R+128|0;if((Mc(b,5320,ka)|0)==0){if((Mc(b,5336,ka)|0)!=0){break}if((Lc(b,5344,ka)|0)!=0){break}h[ka>>3]=+h[R+120>>3];break}Pc(b,5320,32,m)|0;if(($f(m,84)|0)==0){if((Lc(b,5352,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744;break}if((Lc(b,5360,Q)|0)!=0){h[ka>>3]=+h[ka>>3]+ +h[Q>>3]/8765.812770744}}}else{h[R+128>>3]=(+h[O>>3]+-15019.81352)/365.242198781+1900.0}}while(0);c[R+3312>>2]=1;ua=qa}}while(0);c[R+3964>>2]=R+616;c[R+3972>>2]=ua;c[R+3968>>2]=$;c[R+3284>>2]=1;c[R+3296>>2]=0;c[R+3328>>2]=0;Yb(R);ea=R;i=e;return ea|0}function Nb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=i;i=i+96|0;f=e;g=e+16|0;if((d|0)==0){h=0;i=e;return h|0}j=Dg(d|0)|0;k=ig(1,j+1|0)|0;if((j|0)>0){l=0;do{m=a[d+l|0]|0;if((m+ -97<<24>>24&255)<26){a[k+l|0]=(m&255)+224}else{a[k+l|0]=m}l=l+1|0}while((l|0)!=(j|0))}a[k+j|0]=0;if((Dg(k|0)|0)==1){h=a[k]|0;i=e;return h|0}j=f;c[j>>2]=1314079575;c[j+4>>2]=4541761;a[f+8|0]=0;j=f+7|0;l=95;d=0;while(1){if((d|0)>0){n=d+64&255}else{n=0}a[j]=n;if((Pc(b,f,72,g)|0)==0){o=l}else{m=Dg(g|0)|0;p=ig(1,m+1|0)|0;if((m|0)>0){q=0;do{r=a[g+q|0]|0;if((r+ -97<<24>>24&255)<26){a[p+q|0]=(r&255)+224}else{a[p+q|0]=r}q=q+1|0}while((q|0)!=(m|0))}a[p+m|0]=0;q=(yg(p,k)|0)==0;hg(p);o=q?n:l}d=d+1|0;if((d|0)==27){break}else{l=o}}hg(k);h=o;i=e;return h|0}function Ob(b,c){b=b|0;c=c|0;var d=0,e=0;d=i;i=i+16|0;e=d;a[e]=0;Bc(b,c)|0;c=Mb(b,e)|0;i=d;return c|0}function Pb(b){b=b|0;var c=0,d=0,e=0;c=i;i=i+16|0;d=c;a[d]=0;e=Mb(b,d)|0;i=c;return e|0}function Qb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;b=i;i=i+176|0;d=b+88|0;e=b+40|0;f=b+16|0;g=b+56|0;j=b+80|0;k=b+168|0;l=b+32|0;m=b+72|0;n=b+8|0;o=b;p=j;c[p>>2]=1;c[p+4>>2]=1;p=c[a+3944>>2]|0;q=c[a+3948>>2]|0;if((c[a+3316>>2]|0)!=2){i=b;return}r=a+3928|0;if((yg(r,5848)|0)!=0){i=b;return}if(+h[a+((p*100|1)<<3)+1568>>3]==0.0?+h[a+((q*100|1)<<3)+1568>>3]==0.0:0){i=b;return}s=a+9312|0;t=c[s>>2]|0;if((t|0)==0){h[l>>3]=0.0;h[m>>3]=0.0;h[n>>3]=+h[a+136>>3];h[o>>3]=+h[a+144>>3]}else{bc(t,0.0,0.0,l,m);bc(c[s>>2]|0,+h[a+136>>3],+h[a+144>>3],n,o)}if((p|0)==0){u=+h[l>>3];v=+h[m>>3];w=v;x=+h[o>>3]-v;y=u;z=+h[n>>3]-u}else{u=+h[m>>3];v=+h[l>>3];w=v;x=+h[n>>3]-v;y=u;z=+h[o>>3]-u}u=x/11.0;x=z/11.0;o=ig(288,8)|0;n=ig(144,8)|0;l=ig(144,8)|0;z=w+.5;m=g+(q<<3)|0;h[m>>3]=z;s=f+(q<<3)|0;h[s>>3]=z;z=y+.5;t=g+(p<<3)|0;h[t>>3]=z;A=f+(p<<3)|0;h[A>>3]=z;B=a+3956|0;C=e+(p<<3)|0;p=e+(q<<3)|0;q=a+4064|0;y=z;D=11;E=l;F=n;G=o;while(1){h[A>>3]=y;H=E+96|0;I=11;J=E;K=F;L=G;while(1){if((Dd(f,B,e)|0)!=0){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}h[K>>3]=+h[C>>3];h[J>>3]=+h[p>>3];Wd(q,+h[C>>3],+h[p>>3],L,L+8|0)|0;h[A>>3]=x+ +h[A>>3];if((I|0)==0){break}else{I=I+ -1|0;J=J+8|0;K=K+8|0;L=L+16|0}}h[s>>3]=u+ +h[s>>3];if((D|0)==0){break}y=+h[t>>3];D=D+ -1|0;E=H;F=F+96|0;G=G+192|0}Dd(g,B,e)|0;h[C>>3]=+h[C>>3]+.0002777777777777778;Cd(e,B,f)|0;y=+h[A>>3]- +h[t>>3];u=+h[s>>3]- +h[m>>3];x=+Q(+(y*y+u*u))*3600.0;if(!(x!=0.0)){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}u=.04/x;c[k>>2]=1;C=0;G=1;a:while(1){if((G|0)>1){rd(C)}M=qd(j,2,k,1)|0;td(M,o,n,0,144,0);F=143;E=n;D=o;while(1){x=+sd(M,D);if(+P(+(x- +h[E>>3]))>u){break}if((F|0)==0){N=26;break a}else{F=F+ -1|0;E=E+8|0;D=D+16|0}}D=c[k>>2]|0;E=D+1|0;c[k>>2]=E;if((D|0)>8){N=28;break}else{C=M;G=E}}if((N|0)==26){c[k>>2]=(c[k>>2]|0)+1}else if((N|0)==28){_b(5904);c[a+1560>>2]=1}c[a+3168>>2]=M;c[a+5944>>2]=M;Dd(g,B,e)|0;h[p>>3]=+h[p>>3]+.0002777777777777778;Cd(e,B,f)|0;u=+h[A>>3]- +h[t>>3];x=+h[s>>3]- +h[m>>3];y=+Q(+(u*u+x*x))*3600.0;if(!(y!=0.0)){c[d>>2]=r;Na(d|0,5856,d|0)|0;_b(d)}x=.04/y;c[k>>2]=1;d=M;M=1;b:while(1){if((M|0)>1){rd(d)}O=qd(j,2,k,1)|0;td(O,o,l,0,144,0);r=143;m=l;s=o;while(1){y=+sd(O,s);if(+P(+(y- +h[m>>3]))>x){break}if((r|0)==0){N=37;break b}else{r=r+ -1|0;m=m+8|0;s=s+16|0}}s=c[k>>2]|0;m=s+1|0;c[k>>2]=m;if((s|0)>8){N=39;break}else{d=O;M=m}}if((N|0)==37){c[k>>2]=(c[k>>2]|0)+1}else if((N|0)==39){_b(5904);c[a+1560>>2]=1}c[a+3172>>2]=O;c[a+5948>>2]=O;hg(o);hg(n);hg(l);i=b;return}function Rb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0,z=0.0,A=0,B=0,C=0;f=i;i=i+144|0;g=f+24|0;j=f+28|0;k=f+32|0;l=f+112|0;m=f+96|0;n=f+8|0;o=f+64|0;p=f;c[j>>2]=0;a[k]=0;a[l]=0;q=a[e]|0;if(q<<24>>24==0){r=n;c[r>>2]=1230328133;c[r+4>>2]=5787470;s=m+0|0;t=6e3|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0))}else{c[g>>2]=q<<24>>24;Na(n|0,5968,g|0)|0;c[g>>2]=a[e]|0;Na(m|0,5984,g|0)|0}if((Pc(b,n,31,l)|0)==0?(Pc(b,5472,31,l)|0)!=0:0){g=n;c[g>>2]=1230328133;c[g+4>>2]=5787470}if((Pc(b,m,31,k)|0)==0?(Pc(b,6e3,31,k)|0)!=0:0){s=m+0|0;t=6e3|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0))}g=a[l]|0;do{if(g<<24>>24==74){e=l+1|0;h[d+120>>3]=+ug(e);c[j>>2]=vg(e)|0;c[k>>2]=3492678;v=0;w=30}else if(!(g<<24>>24==66)){if((Ec(b,n,j)|0)!=0){Lc(b,n,d+120|0)|0;v=1;w=30;break}if((Ec(b,5344,j)|0)!=0){if((c[j>>2]|0)==0){c[j>>2]=1950;h[d+120>>3]=1950.0;v=0;w=30;break}else{Lc(b,5344,d+120|0)|0;v=1;w=30;break}}if((a[k]|0)!=0){if((Ag(k,5480,3)|0)==0){h[d+120>>3]=1950.0;c[j>>2]=1950;x=0;break}if((Ag(k,6016,4)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,5488,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,6024,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0;break}if((Ag(k,6032,3)|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;x=0}else{v=0;w=30}}else{v=0;w=30}}else{e=l+1|0;h[d+120>>3]=+ug(e);c[j>>2]=~~+ug(e);c[k>>2]=3427142;v=0;w=30}}while(0);do{if((w|0)==30){if((c[j>>2]|0)==0){h[d+120>>3]=2.0e3;c[j>>2]=2e3;l=d+3449|0;if((Ag(l,5656,2)|0)!=0?(Ag(l,4832,3)|0)!=0:0){x=v;break}c[k>>2]=3492678;x=v}else{x=v}}}while(0);v=d+128|0;do{if((Mc(b,5320,v)|0)==0){if((Mc(b,5336,v)|0)==0?(Lc(b,5344,v)|0)==0:0){y=+h[d+120>>3];h[v>>3]=y;z=y}else{w=43}}else{Pc(b,5320,32,o)|0;if(($f(o,84)|0)==0){if((Lc(b,5352,p)|0)!=0){y=+h[v>>3]+ +h[p>>3]/8765.812770744;h[v>>3]=y;z=y;break}if((Lc(b,5360,p)|0)!=0){y=+h[v>>3]+ +h[p>>3]/8765.812770744;h[v>>3]=y;z=y}else{w=43}}else{w=43}}}while(0);if((w|0)==43){z=+h[v>>3]}if(z==0.0){h[v>>3]=+h[d+120>>3]}do{if((a[k]|0)==0?(Pc(b,m,31,k)|0,(a[k]|0)==0):0){if((c[d+3884>>2]|0)!=7){v=d+3764|0;if((c[j>>2]|0)>1980){a[v]=3492678;a[v+1|0]=13643;a[v+2|0]=53;a[v+3|0]=0;break}else{a[v]=3427142;a[v+1|0]=13387;a[v+2|0]=52;a[v+3|0]=0;break}}}else{w=48}}while(0);do{if((w|0)==48?(m=d+3764|0,Lg(m|0,k|0)|0,(x|0)==0):0){if((Ag(m,5480,3)|0)==0){h[d+120>>3]=1950.0;break}if((Ag(m,5488,3)|0)==0){h[d+120>>3]=2.0e3;break}if((Ag(m,6016,4)|0)==0){h[d+120>>3]=2.0e3;break}if((Ag(m,6024,3)|0)==0?(c[j>>2]|0)==0:0){h[d+120>>3]=2.0e3}}}while(0);switch(a[d+3449|0]|0){case 71:{j=d+3764|0;s=j+0|0;t=6040|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 72:{j=d+3764|0;s=j+0|0;t=6088|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 65:{j=d+3764|0;a[j+0|0]=a[6104|0]|0;a[j+1|0]=a[6105|0]|0;a[j+2|0]=a[6106|0]|0;a[j+3|0]=a[6107|0]|0;a[j+4|0]=a[6108|0]|0;a[j+5|0]=a[6109|0]|0;A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 76:{j=d+3764|0;a[j+0|0]=a[5296|0]|0;a[j+1|0]=a[5297|0]|0;a[j+2|0]=a[5298|0]|0;a[j+3|0]=a[5299|0]|0;a[j+4|0]=a[5300|0]|0;a[j+5|0]=a[5301|0]|0;a[j+6|0]=a[5302|0]|0;A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 69:{j=d+3764|0;s=j+0|0;t=6056|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};case 83:{j=d+3764|0;s=j+0|0;t=6072|0;u=s+9|0;do{a[s]=a[t]|0;s=s+1|0;t=t+1|0}while((s|0)<(u|0));A=j;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return};default:{A=d+3764|0;B=nc(A)|0;C=d+3884|0;c[C>>2]=B;i=f;return}}}function Sb(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0;d=i;e=b+3764|0;f=c[b+3260>>2]|0;if((a[e]|0)!=0){if((f|0)==0){g=0;j=3}else{k=f}}else{g=f;j=3}if((j|0)==3){a[e+0|0]=a[5296|0]|0;a[e+1|0]=a[5297|0]|0;a[e+2|0]=a[5298|0]|0;a[e+3|0]=a[5299|0]|0;a[e+4|0]=a[5300|0]|0;a[e+5|0]=a[5301|0]|0;a[e+6|0]=a[5302|0]|0;k=g}if((k|0)==-1){a[e+0|0]=a[5304|0]|0;a[e+1|0]=a[5305|0]|0;a[e+2|0]=a[5306|0]|0;a[e+3|0]=a[5307|0]|0;a[e+4|0]=a[5308|0]|0;a[e+5|0]=a[5309|0]|0}k=nc(e)|0;c[b+3884>>2]=k;do{if((k|0)!=2){g=b+3796|0;if((k|0)==1){a[g]=3492678;a[g+1|0]=13643;a[g+2|0]=53;a[g+3|0]=0;break}else{Lg(g|0,e|0)|0;break}}else{g=b+3796|0;a[g]=3427142;a[g+1|0]=13387;a[g+2|0]=52;a[g+3|0]=0}}while(0);c[b+3888>>2]=nc(b+3796|0)|0;k=b+120|0;h[b+3872>>3]=+h[k>>3];g=b+3828|0;Lg(g|0,e|0)|0;c[b+3880>>2]=nc(g)|0;h[b+3864>>3]=+h[k>>3];i=d;return}function Tb(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){i=b;return}if((c[a+3312>>2]|0)==0){hg(a);i=b;return}d=a+9312|0;e=c[d>>2]|0;if((e|0)!=0){Tb(e);c[d>>2]=0}Ub(a);d=c[a+9320>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3980>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3976>>2]|0;if((d|0)!=0){hg(d)}d=c[a+3168>>2]|0;if((d|0)!=0){rd(d)}d=c[a+3172>>2]|0;if((d|0)!=0){rd(d)}hg(a);i=b;return}function Ub(a){a=a|0;var b=0,d=0;b=i;d=c[1654]|0;if((d|0)!=0){hg(d);c[1654]=0}d=c[6620>>2]|0;if((d|0)!=0){hg(d);c[6620>>2]=0}d=c[6624>>2]|0;if((d|0)!=0){hg(d);c[6624>>2]=0}d=c[6628>>2]|0;if((d|0)!=0){hg(d);c[6628>>2]=0}d=c[6632>>2]|0;if((d|0)!=0){hg(d);c[6632>>2]=0}d=c[6636>>2]|0;if((d|0)!=0){hg(d);c[6636>>2]=0}d=c[6640>>2]|0;if((d|0)!=0){hg(d);c[6640>>2]=0}d=c[6644>>2]|0;if((d|0)!=0){hg(d);c[6644>>2]=0}d=c[6648>>2]|0;if((d|0)!=0){hg(d);c[6648>>2]=0}d=c[6652>>2]|0;if((d|0)!=0){hg(d);c[6652>>2]=0}if((a|0)==0){i=b;return}if((c[a+3312>>2]|0)==0){i=b;return}d=c[a+9208>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9212>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9216>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9220>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9224>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9228>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9232>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9236>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9240>>2]|0;if((d|0)!=0){hg(d)}d=c[a+9244>>2]|0;if((d|0)==0){i=b;return}hg(d);i=b;return}function Vb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+144|0;g=f;h=f+8|0;c[h>>2]=5130572;c[h+4>>2]=5265985;c[h+8>>2]=5266003;c[h+12>>2]=5128532;c[h+16>>2]=5130579;c[h+20>>2]=4674643;c[h+24>>2]=4411969;c[h+28>>2]=5132378;c[h+32>>2]=4277594;c[h+36>>2]=5392705;c[h+40>>2]=5265731;c[h+44>>2]=5390659;c[h+48>>2]=5391693;c[h+52>>2]=4277571;c[h+56>>2]=5263171;c[h+60>>2]=4476739;c[h+64>>2]=4542275;c[h+68>>2]=5197635;c[h+72>>2]=5132098;c[h+76>>2]=5194576;c[h+80>>2]=4998739;c[h+84>>2]=5390672;c[h+88>>2]=5523777;c[h+92>>2]=5001037;c[h+96>>2]=4412227;c[h+100>>2]=4412241;c[h+104>>2]=4412244;c[h+108>>2]=5260110;c[h+112>>2]=5459015;c[h+116>>2]=5460804;c[h+120>>2]=5524560;c[h+124>>2]=5787220;c[h+128>>2]=5787738;c[h+132>>2]=5656660;if((Ag(d,6128,4)|0)==0){a[d]=1313819736;a[d+1|0]=5132108;a[d+2|0]=20047;a[d+3|0]=78}j=b+3368|0;Lg(j|0,d|0)|0;k=b+3449|0;Lg(k|0,d|0)|0;l=b+3467|0;Lg(l|0,d|0)|0;do{if((Ag(d,6136,6)|0)!=0){if((Ag(d,6144,6)|0)==0){c[b+3260>>2]=-1;break}if((Qc(d,6152)|0)!=0){c[b+3260>>2]=-1;break}m=a[d]|0;if(!(m<<24>>24==65|m<<24>>24==68|m<<24>>24==82)?(a[d+1|0]|0)!=76:0){c[b+3260>>2]=0;i=f;return 0}a[k]=m;a[b+3450|0]=a[d+1|0]|0;m=a[d+2|0]|0;n=b+3451|0;do{if(!(m<<24>>24==45)){a[n]=m;o=a[d+3|0]|0;p=b+3452|0;if(o<<24>>24==45){a[p]=0;q=4;break}else{a[p]=o;a[b+3453|0]=0;q=4;break}}else{a[n]=0;q=3}}while(0);n=((a[d+q|0]|0)==45)+q|0;m=n+((a[d+n|0]|0)==45)|0;n=m+((a[d+m|0]|0)==45)|0;m=n+((a[d+n|0]|0)==45)|0;a[l]=a[d+m|0]|0;a[b+3468|0]=a[d+(m+1)|0]|0;a[b+3469|0]=a[d+(m+2)|0]|0;a[b+3470|0]=0;c[g>>2]=k;c[g+4>>2]=l;Na(j|0,6160,g|0)|0;if((a[j]|0)==32){a[j]=45}m=b+3369|0;if((a[m]|0)==32){a[m]=45}m=b+3370|0;if((a[m]|0)==32){a[m]=45}m=b+3371|0;if((a[m]|0)==32){a[m]=45}m=b+3372|0;if((a[m]|0)==32){a[m]=45}m=b+3373|0;if((a[m]|0)==32){a[m]=45}m=b+3374|0;if((a[m]|0)==32){a[m]=45}n=b+3375|0;if((a[n]|0)==32){a[n]=45}o=b+3260|0;c[o>>2]=0;p=0;r=1;while(1){if((Ag(l,h+(r<<2)|0,3)|0)==0){c[o>>2]=r;s=r}else{s=p}r=r+1|0;if((r|0)==34){break}else{p=s}}p=b+3324|0;r=c[p>>2]|0;if((r|0)==0){c[p>>2]=3;break}else if((r|0)==1){c[p>>2]=2}else if((r|0)!=2){break}if((s|0)==31){a[m]=65;a[n]=78;c[o>>2]=3;break}else if((s|0)==32){a[m]=80;a[n]=78;c[o>>2]=7;break}else{break}}else{c[b+3260>>2]=0}}while(0);do{if((Ag(e,6168,4)|0)!=0){if((Ag(e,6192,4)|0)==0){a[e]=a[d]|0;s=e+1|0;a[s+0|0]=a[6176|0]|0;a[s+1|0]=a[6177|0]|0;a[s+2|0]=a[6178|0]|0;c[b+3264>>2]=-90;s=b+3764|0;a[s]=4280403;a[s+1|0]=16720;a[s+2|0]=65;a[s+3|0]=0;c[b+3884>>2]=8;break}else{c[b+3264>>2]=0;break}}else{a[e]=a[d]|0;s=e+1|0;a[s+0|0]=a[6176|0]|0;a[s+1|0]=a[6177|0]|0;a[s+2|0]=a[6178|0]|0;c[b+3264>>2]=90;s=b+3764|0;a[s+0|0]=a[6184|0]|0;a[s+1|0]=a[6185|0]|0;a[s+2|0]=a[6186|0]|0;a[s+3|0]=a[6187|0]|0;a[s+4|0]=a[6188|0]|0;a[s+5|0]=a[6189|0]|0;c[b+3884>>2]=7}}while(0);s=b+3377|0;Lg(s|0,e|0)|0;h=b+3458|0;Lg(h|0,e|0)|0;do{if((Ag(e,6136,6)|0)!=0){if((Ag(e,6144,6)|0)==0){c[b+3260>>2]=-1;break}j=a[e]|0;if(!(j<<24>>24==65|j<<24>>24==68|j<<24>>24==82)?(a[e+1|0]|0)!=76:0){c[b+3260>>2]=0;break}a[h]=j;j=e+1|0;a[b+3459|0]=a[j]|0;k=a[e+2|0]|0;q=b+3460|0;do{if(!(k<<24>>24==45)){a[q]=k;r=a[e+3|0]|0;p=b+3461|0;if(r<<24>>24==45){a[p]=0;t=4;break}else{a[p]=r;a[b+3462|0]=0;t=4;break}}else{a[q]=0;t=3}}while(0);q=((a[e+t|0]|0)==45)+t|0;k=q+((a[e+q|0]|0)==45)|0;q=k+((a[e+k|0]|0)==45)|0;k=q+((a[e+q|0]|0)==45)|0;a[l]=a[e+k|0]|0;a[b+3468|0]=a[e+(k+1)|0]|0;a[b+3469|0]=a[e+(k+2)|0]|0;a[b+3470|0]=0;if((Ag(d,6120,3)|0)!=0?(Ag(d+1|0,6176,3)|0)!=0:0){c[b+3304>>2]=0}else{c[b+3304>>2]=1}if((a[j]|0)!=76?(a[e]|0)!=65:0){c[b+3292>>2]=0;c[b+3288>>2]=3}else{c[b+3292>>2]=1;c[b+3288>>2]=5}c[g>>2]=h;c[g+4>>2]=l;Na(s|0,6160,g|0)|0;if((a[s]|0)==32){a[s]=45}k=b+3378|0;if((a[k]|0)==32){a[k]=45}k=b+3379|0;if((a[k]|0)==32){a[k]=45}k=b+3380|0;if((a[k]|0)==32){a[k]=45}k=b+3381|0;if((a[k]|0)==32){a[k]=45}k=b+3382|0;if((a[k]|0)==32){a[k]=45}k=b+3383|0;if((a[k]|0)==32){a[k]=45}k=b+3384|0;if((a[k]|0)==32){a[k]=45}}else{c[b+3260>>2]=0}}while(0);$e(b,d);i=f;return 0}function Wb(a,b,d,e){a=a|0;b=+b;d=+d;e=+e;var f=0,g=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0;f=i;g=c[a+3316>>2]|0;j=a+760|0;h[j>>3]=b;k=a+768|0;l=d!=0.0?d:b;h[k>>3]=l;h[a+32>>3]=b;h[a+40>>3]=l;if((g|0)>0){m=(g|0)<2?g:2;g=0;n=a+832|0;while(1){o=0;p=n;while(1){h[p>>3]=(g|0)==(o|0)?1.0:0.0;o=o+1|0;if((o|0)==(m|0)){break}else{p=p+8|0}}g=g+1|0;if((g|0)==(m|0)){break}else{n=n+(m<<3)|0}}}c[a+3300>>2]=0;m=a+48|0;if(e<0.0){q=e+360.0}else{q=e}if(!(q>=360.0)){r=q}else{r=q+-360.0}h[m>>3]=r;q=r*3.141592653589793/180.0;r=+S(+q);if(b*d>0.0){s=-q}else{s=q}q=+T(+s);s=+h[j>>3];n=a+56|0;h[n>>3]=r*s;d=+h[k>>3];b=q*+P(+d);if(s<0.0){h[a+64>>3]=-b}else{h[a+64>>3]=b}b=q*+P(+s);if(d<0.0){h[a+72>>3]=b}else{h[a+72>>3]=-b}h[a+80>>3]=r*d;Bd(2,n,a+88|0)|0;lc(a);d=+h[j>>3];j=d<0.0;if((c[a+3304>>2]|0)!=0){if(j?+h[k>>3]>0.0:0){c[a+3256>>2]=1;r=+h[m>>3];b=r+-90.0;n=a+3200|0;if(b<-180.0){h[n>>3]=b+360.0;h[a+3208>>3]=r;h[a+3216>>3]=b+360.0;i=f;return}else{h[n>>3]=b;h[a+3208>>3]=r;h[a+3216>>3]=b;i=f;return}}do{if(d>0.0){if(!(+h[k>>3]<0.0)){if(!(+h[k>>3]>0.0)){break}c[a+3256>>2]=0;b=+h[m>>3]+90.0;n=a+3200|0;if(b>180.0){r=b+-360.0;h[n>>3]=r;h[a+3208>>3]=r;h[a+3216>>3]=b+-360.0;i=f;return}else{h[n>>3]=b;h[a+3208>>3]=b;h[a+3216>>3]=b;i=f;return}}else{c[a+3256>>2]=1;b=+h[m>>3];r=b+90.0;if(r>180.0){t=r+-360.0}else{t=r}h[a+3200>>3]=t;h[a+3208>>3]=b;r=b+-90.0;n=a+3216|0;h[n>>3]=r;if(!(r<-180.0)){i=f;return}h[n>>3]=r+360.0;i=f;return}}}while(0);if(!j){i=f;return}if(!(+h[k>>3]<0.0)){i=f;return}c[a+3256>>2]=0;t=+h[m>>3];r=t+-90.0;if(r<-180.0){u=r+360.0}else{u=r}h[a+3200>>3]=u;h[a+3208>>3]=u;u=t+90.0;n=a+3216|0;h[n>>3]=u;if(!(u>180.0)){i=f;return}h[n>>3]=u+-360.0;i=f;return}if(j?+h[k>>3]>0.0:0){c[a+3256>>2]=0;u=+h[m>>3];h[a+3200>>3]=u;t=u+90.0;if(t>180.0){v=t+-360.0}else{v=t}h[a+3208>>3]=v;v=u+180.0;n=a+3216|0;h[n>>3]=v;if(!(v>180.0)){i=f;return}h[n>>3]=v+-360.0;i=f;return}do{if(d>0.0){if(!(+h[k>>3]<0.0)){if(!(+h[k>>3]>0.0)){break}c[a+3256>>2]=1;v=+h[m>>3];h[a+3200>>3]=-v;u=90.0-v;if(u>180.0){w=u+-360.0}else{w=u}h[a+3208>>3]=w;h[a+3216>>3]=v;i=f;return}c[a+3256>>2]=0;v=+h[m>>3]+180.0;if(v>180.0){x=v+-360.0}else{x=v}h[a+3200>>3]=x;v=x+90.0;if(v>180.0){y=v+-360.0}else{y=v}h[a+3208>>3]=y;v=x+180.0;n=a+3216|0;h[n>>3]=v;if(!(v>180.0)){i=f;return}h[n>>3]=v+-360.0;i=f;return}}while(0);if(!j){i=f;return}if(!(+h[k>>3]<0.0)){i=f;return}c[a+3256>>2]=1;x=+h[m>>3];y=x+180.0;if(y>180.0){z=y+-360.0}else{z=y}h[a+3200>>3]=z;y=z+90.0;if(y>180.0){A=y+-360.0}else{A=y}h[a+3208>>3]=A;A=x+90.0;m=a+3216|0;h[m>>3]=A;if(!(A>180.0)){i=f;return}h[m>>3]=A+-360.0;i=f;return}function Xb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,l=0,m=0,n=0,o=0.0;e=i;i=i+16|0;f=e;if((b|0)==0){i=e;return}g=b+3312|0;if((c[g>>2]|0)==0){i=e;return}do{if((((d|0)!=0?(a[d]|0)!=0:0)?(yg(d,6200)|0)!=0:0)?(yg(d,6208)|0)!=0:0){j=nc(d)|0;if((j|0)<0){i=e;return}l=c[b+3884>>2]|0;if((j|0)!=(l|0)&(l+ -5|0)>>>0<2){i=e;return}else{Lg(b+3796|0,d|0)|0;h[b+3872>>3]=+oc(d);m=j;break}}else{n=7}}while(0);do{if((n|0)==7){d=c[b+3884>>2]|0;j=b+3796|0;Lg(j|0,b+3764|0)|0;o=+h[b+120>>3];h[b+3872>>3]=o;if((d|0)==1){if(!(o!=2.0e3)){a[j+0|0]=a[6232|0]|0;a[j+1|0]=a[6233|0]|0;a[j+2|0]=a[6234|0]|0;a[j+3|0]=a[6235|0]|0;a[j+4|0]=a[6236|0]|0;a[j+5|0]=a[6237|0]|0;m=1;break}a[j]=74;h[k>>3]=o;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Na(b+3797|0,6216,f|0)|0;l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)!=48){m=1;break}a[l]=0;m=1;break}else if((d|0)==2){if(!(o!=1950.0)){a[j+0|0]=a[6224|0]|0;a[j+1|0]=a[6225|0]|0;a[j+2|0]=a[6226|0]|0;a[j+3|0]=a[6227|0]|0;a[j+4|0]=a[6228|0]|0;a[j+5|0]=a[6229|0]|0;m=2;break}a[j]=66;h[k>>3]=o;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];Na(b+3797|0,6216,f|0)|0;l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)==48){a[l]=0}l=b+((Dg(j|0)|0)+ -1)+3796|0;if((a[l]|0)!=48){m=2;break}a[l]=0;m=2;break}else{m=d;break}}}while(0);c[b+3888>>2]=m;if((c[g>>2]|0)==0){i=e;return}switch(m|0){case 5:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};case 8:case 7:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};case 9:case 4:case 3:{c[b+3292>>2]=1;c[b+3288>>2]=5;i=e;return};default:{c[b+3292>>2]=0;c[b+3288>>2]=3;i=e;return}}}function Yb(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;d=i;i=i+32|0;e=d;f=d+8|0;if((b|0)==0){i=d;return}g=b+3312|0;if((c[g>>2]|0)==0){i=d;return}h=0;a:while(1){if((h|0)==0){j=f+0|0;k=6656|0;l=j+12|0;do{a[j]=a[k]|0;j=j+1|0;k=k+1|0}while((j|0)<(l|0))}else{c[e>>2]=h;Na(f|0,6672,e|0)|0}k=c[6616+(h<<2)>>2]|0;b:do{if((k|0)!=0){if((c[g>>2]|0)!=0?(j=Dg(k|0)|0,(j|0)>0):0){l=b+(h<<2)+9208|0;m=c[l>>2]|0;if((m|0)!=0){hg(m)}m=ig(j+2|0,1)|0;c[l>>2]=m;if((m|0)!=0){n=m;m=0;do{o=a[k+m|0]|0;a[n+m|0]=o<<24>>24==95?32:o;m=m+1|0;n=c[l>>2]|0}while((m|0)!=(j|0));a[n+j|0]=0}}}else{m=Wa(f|0)|0;if((m|0)!=0){if((c[g>>2]|0)==0){break}l=Dg(m|0)|0;if((l|0)<=0){break}o=b+(h<<2)+9208|0;p=c[o>>2]|0;if((p|0)!=0){hg(p)}p=ig(l+2|0,1)|0;c[o>>2]=p;if((p|0)==0){break}else{q=p;r=0}do{p=a[m+r|0]|0;a[q+r|0]=p<<24>>24==95?32:p;r=r+1|0;q=c[o>>2]|0}while((r|0)!=(l|0));a[q+l|0]=0;break}switch(h|0){case 4:{if((c[g>>2]|0)!=0){o=b+9224|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=112;a[m+2|0]=112;a[m+3|0]=109;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};case 2:{if((c[g>>2]|0)!=0){m=b+9216|0;o=c[m>>2]|0;if((o|0)!=0){hg(o)}o=ig(13,1)|0;c[m>>2]=o;if((o|0)==0){break b}a[o]=115;a[o+1|0]=103;a[o+2|0]=115;a[o+3|0]=99;a[o+4|0]=32;a[o+5|0]=45;a[o+6|0]=97;a[o+7|0]=104;a[o+8|0]=32;a[o+9|0]=37;a[o+10|0]=115;a[o+11|0]=0;break b}break};case 3:{if((c[g>>2]|0)!=0){o=b+9220|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=116;a[m+2|0]=121;a[m+3|0]=50;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};case 5:{if((c[g>>2]|0)!=0){m=b+9228|0;o=c[m>>2]|0;if((o|0)!=0){hg(o)}o=ig(13,1)|0;c[m>>2]=o;if((o|0)==0){break b}a[o]=115;a[o+1|0]=115;a[o+2|0]=97;a[o+3|0]=111;a[o+4|0]=32;a[o+5|0]=45;a[o+6|0]=97;a[o+7|0]=104;a[o+8|0]=32;a[o+9|0]=37;a[o+10|0]=115;a[o+11|0]=0;break b}break};case 1:{if((c[g>>2]|0)!=0){o=b+9212|0;m=c[o>>2]|0;if((m|0)!=0){hg(m)}m=ig(13,1)|0;c[o>>2]=m;if((m|0)==0){break b}a[m]=115;a[m+1|0]=117;a[m+2|0]=97;a[m+3|0]=50;a[m+4|0]=32;a[m+5|0]=45;a[m+6|0]=97;a[m+7|0]=104;a[m+8|0]=32;a[m+9|0]=37;a[m+10|0]=115;a[m+11|0]=0;break b}break};default:{c[b+(h<<2)+9208>>2]=0;break b}}h=h+1|0;continue a}}while(0);h=h+1|0;if((h|0)==10){break}}i=d;return}function Zb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0.0,l=0.0;d=i;if((b|0)==0){i=d;return}c[a+3300>>2]=1;e=a+56|0;h[e>>3]=+h[b>>3];f=b+8|0;h[a+64>>3]=+h[f>>3];g=b+16|0;h[a+72>>3]=+h[g>>3];j=b+24|0;h[a+80>>3]=+h[j>>3];Bd(2,e,a+88|0)|0;k=+h[b>>3];l=+h[g>>3];b=a+32|0;h[b>>3]=+Q(+(k*k+l*l));l=+h[f>>3];k=+h[j>>3];j=a+40|0;h[j>>3]=+Q(+(l*l+k*k));if((c[a+3304>>2]|0)!=0){k=+h[f>>3];h[f>>3]=-+h[g>>3];h[g>>3]=-k}lc(a);c[a+3312>>2]=1;ac(a);h[a+760>>3]=+h[b>>3];h[a+768>>3]=+h[j>>3];i=d;return}function _b(a){a=a|0;var b=0;b=i;Lg(6536,a|0)|0;i=b;return}function $b(a,b,d,e){a=a|0;b=+b;d=+d;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;f=i;if((e|0)==0){i=f;return}g=a+3316|0;j=c[g>>2]|0;if((j+ -1|0)>>>0>8){k=c[a+3320>>2]|0;c[g>>2]=k;l=k}else{l=j}j=a+760|0;h[j>>3]=b;k=a+768|0;m=d!=0.0?d:b;h[k>>3]=m;h[a+32>>3]=b;h[a+40>>3]=m;if((l|0)>0){g=0;n=e;o=a+832|0;while(1){p=n+(l<<3)|0;q=0;r=n;s=o;while(1){h[s>>3]=+h[r>>3];q=q+1|0;if((q|0)==(l|0)){break}else{r=r+8|0;s=s+8|0}}s=g+1|0;if((s|0)==(l|0)){break}else{g=s;n=p;o=o+(l<<3)|0}}m=+h[j>>3];j=a+56|0;h[j>>3]=+h[e>>3]*m;if((l|0)>1){h[a+64>>3]=+h[e+8>>3]*m;m=+h[k>>3];h[a+72>>3]=+h[e+(l<<3)>>3]*m;h[a+80>>3]=+h[e+(l+1<<3)>>3]*m;t=j}else{u=j;v=11}}else{j=a+56|0;h[j>>3]=+h[e>>3]*b;u=j;v=11}if((v|0)==11){v=a+64|0;j=a+80|0;c[v+0>>2]=0;c[v+4>>2]=0;c[v+8>>2]=0;c[v+12>>2]=0;h[j>>3]=1.0;t=u}Bd(2,t,a+88|0)|0;c[a+3300>>2]=1;Ad(a+3956|0)|0;c[a+3312>>2]=1;ac(a);i=f;return}function ac(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;b=i;i=i+64|0;d=b+48|0;e=b+24|0;f=b+16|0;g=b+40|0;j=b;k=b+32|0;l=b+8|0;if(!(+h[a+136>>3]<1.5)?!(+h[a+144>>3]<1.5):0){if((c[a+3884>>2]|0)==6){i=b;return}m=a+32|0;h[m>>3]=+P(+(+h[m>>3]));n=a+40|0;h[n>>3]=+P(+(+h[n>>3]));o=+h[a+16>>3];p=+h[a+24>>3];bc(a,o,p,e,f);q=a+3304|0;r=+h[e>>3];if((c[q>>2]|0)==0){s=+h[f>>3];e=a+3828|0;ic(a,r+ +h[m>>3],s,e,j,l,d);ic(a,r,s+ +h[n>>3],e,g,k,d)}else{s=+h[f>>3];f=a+3828|0;ic(a,r+ +h[n>>3],s,f,j,l,d);ic(a,r,s+ +h[m>>3],f,g,k,d)}s=+Y(+(+h[k>>3]-p),+(+h[g>>3]-o))*180.0/3.141592653589793;if(s<-90.0){t=s+360.0}else{t=s}h[a+3208>>3]=t;s=+Y(+(+h[l>>3]-p),+(+h[j>>3]-o))*180.0/3.141592653589793;if(s<-90.0){u=s+360.0}else{u=s}h[a+3216>>3]=u;if(t<-90.0){s=t+270.0;h[a+3200>>3]=s;v=s}else{s=t+-90.0;h[a+3200>>3]=s;v=s}j=(c[q>>2]|0)==0;if(!j){s=v+90.0;q=a+48|0;h[q>>3]=s;if(s<0.0){o=s+360.0;h[q>>3]=o;w=o}else{w=s}}else{h[a+48>>3]=v;w=v}q=a+48|0;if(w<0.0){v=w+360.0;h[q>>3]=v;x=v}else{x=w}if(x>=360.0){h[q>>3]=x+-360.0}x=u-t;w=t-u;q=w>80.0&w<100.0?1:x<280.0&x>260.0?1:x<-80.0&x>-100.0&1;c[a+3256>>2]=q;l=(q|0)!=0;if(j){if(l){i=b;return}h[m>>3]=-+h[m>>3];i=b;return}else{if(!l){i=b;return}h[n>>3]=-+h[n>>3];i=b;return}}x=+h[a+48>>3];h[a+3200>>3]=x;h[a+3208>>3]=x+90.0;h[a+3216>>3]=x+180.0;i=b;return}function bc(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0.0,x=0.0,y=0.0;g=i;i=i+144|0;j=g+104|0;k=g+56|0;l=g+8|0;m=g+40|0;n=g+136|0;o=g;p=g+48|0;q=g+96|0;r=g+88|0;if((a|0)==0){i=g;return}if((c[a+3312>>2]|0)==0){i=g;return}h[a+576>>3]=b;h[a+584>>3]=d;h[a+592>>3]=+h[815];s=a+3308|0;c[s>>2]=0;t=c[a+9312>>2]|0;if((t|0)==0){_e(a,b,d,o,p)}else{bc(t,b,d,o,p)}t=a+3260|0;u=c[t>>2]|0;do{if((u|0)==30){if((bd(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==31){if((ed(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==32){if((ld(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else if((u|0)==29){if((nd(+h[o>>3],+h[p>>3],a,q,r)|0)==0){v=24}else{c[s>>2]=1;w=0.0;x=0.0}}else{d=+h[o>>3];b=+h[p>>3];if((c[a+3324>>2]|0)==2|(u|0)<1){if(($c(d,b,a,q,r)|0)==0){v=24;break}c[s>>2]=1;w=0.0;x=0.0;break}h[q>>3]=0.0;h[r>>3]=0.0;h[l>>3]=d;h[l+8>>3]=b;if((u+ -24|0)>>>0<3){h[l+16>>3]=+((c[1632]|0)+1|0)}else{h[l+16>>3]=+h[815]}h[l+24>>3]=1.0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;c[k+16>>2]=0;c[k+20>>2]=0;c[k+24>>2]=0;c[k+28>>2]=0;if((zd(a+3368|0,a+3924|0,l,a+3956|0,k,a+4064|0,m,n,a+688|0,a+3984|0,j)|0)==0){h[q>>3]=+h[j+(c[a+3944>>2]<<3)>>3];h[r>>3]=+h[j+(c[a+3948>>2]<<3)>>3];v=24;break}else{c[s>>2]=1;w=0.0;x=0.0;break}}}while(0);if((v|0)==24){if((c[s>>2]|0)==0){if((c[t>>2]|0)>0){mc(c[a+3884>>2]|0,c[a+3888>>2]|0,+h[a+120>>3],+h[a+3872>>3],q,r,+h[a+128>>3])}t=c[a+3264>>2]|0;if((t|0)==90){b=90.0- +h[r>>3];h[r>>3]=b;y=b}else if((t|0)==-90){b=+h[r>>3]+-90.0;h[r>>3]=b;y=b}else{y=+h[r>>3]}b=+h[q>>3];h[a+600>>3]=b;h[a+608>>3]=y;w=y;x=b}else{w=0.0;x=0.0}}h[e>>3]=x;h[f>>3]=w;f=c[a+3888>>2]|0;if((f|0)<1){i=g;return}if((f|0)==6|(f|0)==10){i=g;return}w=+h[e>>3];if(w<0.0){h[e>>3]=w+360.0;i=g;return}if(!(w>360.0)){i=g;return}h[e>>3]=w+-360.0;i=g;return}function cc(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=d|0;e=e|0;f=f|0;var g=0;g=i;ic(a,b,c,a+3828|0,d,e,f);i=g;return}function dc(b,d,e,f,g){b=b|0;d=+d;e=+e;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+96|0;k=j+16|0;l=j+8|0;m=j;n=j+56|0;o=j+24|0;if((b|0)!=0?(c[b+3312>>2]|0)!=0:0){bc(b,d,e,l,m);if((c[b+3308>>2]|0)!=0){p=f;q=p;a[q]=543581775;a[q+1|0]=2123366;a[q+2|0]=8294;a[q+3|0]=32;q=p+4|0;a[q]=7364973;a[q+1|0]=28769;a[q+2|0]=112;a[q+3|0]=0;r=1;i=j;return r|0}q=c[b+3292>>2]|0;do{if((q|0)==0){p=b+3288|0;s=c[p>>2]|0;t=(s<<1)+18|0;if((t|0)>=(g|0)){if((c[b+3296>>2]|0)==0){Hg(f|0,6336,g|0)|0;u=0;break}else{Hg(f|0,6304,g|0)|0;u=0;break}}e=+h[l>>3];if(((c[b+3888>>2]|0)+ -1|0)>>>0<2){Tc(n,32,e,s);Uc(o,32,+h[m>>3],(c[p>>2]|0)+ -1|0)}else{Uc(n,32,e,s);Uc(o,32,+h[m>>3],c[p>>2]|0)}if((c[b+3296>>2]|0)==0){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0}u=g-t|0}else if((q|0)==1){t=b+3288|0;p=c[t>>2]|0;s=(p<<1)+9|0;if((s|0)>=(g|0)){if((c[b+3296>>2]|0)==0){Hg(f|0,6280,g|0)|0;u=0;break}else{Hg(f|0,6256,g|0)|0;u=0;break}}Vc(n,32,+h[l>>3],p);Vc(o,32,+h[m>>3],c[t>>2]|0);if((c[b+3296>>2]|0)==0){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0}u=g-s|0}else{u=g}}while(0);switch(c[b+3888>>2]|0){case 5:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(q){q=s;t=q;a[t]=1953259808;a[t+1|0]=7629921;a[t+2|0]=29804;a[t+3|0]=116;t=q+4|0;a[t]=8020269;a[t+1|0]=31329;a[t+2|0]=122;a[t+3|0]=0;r=1;i=j;return r|0}else{t=s;s=t;a[s]=1953259785;a[s+1|0]=7629921;a[s+2|0]=29804;a[s+3|0]=116;s=t+4|0;a[s]=8020269;a[s+1|0]=31329;a[s+2|0]=122;a[s+3|0]=0;r=1;i=j;return r|0}break};case 4:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;t=f+(Dg(f|0)|0)|0;if(s){v=t+0|0;w=6416|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=t+0|0;w=6400|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 9:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}t=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(t){t=s;q=t;a[q]=1634496544;a[q+1|0]=6384752;a[q+2|0]=24940;a[q+3|0]=97;q=t+4|0;a[q]=7628142;a[q+1|0]=29797;a[q+2|0]=116;a[q+3|0]=0;r=1;i=j;return r|0}else{q=s;s=q;a[s]=1634496521;a[s+1|0]=6384752;a[s+2|0]=24940;a[s+3|0]=97;s=q+4|0;a[s]=7628142;a[s+1|0]=29797;a[s+2|0]=116;a[s+3|0]=0;r=1;i=j;return r|0}break};case 8:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;q=f+(Dg(f|0)|0)|0;if(s){v=q+0|0;w=6480|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=q+0|0;w=6464|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 7:{if((u|0)<=7){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;s=f+(Dg(f|0)|0)|0;if(q){v=s+0|0;w=6448|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=s+0|0;w=6432|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};case 1:case 2:{s=b+3796|0;if((u|0)<=((Dg(s|0)|0)+1|0)){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}q=(c[b+3296>>2]|0)==0;t=f+(Dg(f|0)|0)|0;p=q?32:9;a[t]=p;a[t+1|0]=p>>8;Fg(f|0,s|0)|0;r=1;i=j;return r|0};case 3:{if((u|0)<=9){r=1;i=j;return r|0}if((c[b+3284>>2]|0)==0){r=1;i=j;return r|0}s=(c[b+3296>>2]|0)==0;p=f+(Dg(f|0)|0)|0;if(s){v=p+0|0;w=6384|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}else{v=p+0|0;w=6368|0;x=v+10|0;do{a[v]=a[w]|0;v=v+1|0;w=w+1|0}while((v|0)<(x|0));r=1;i=j;return r|0}break};default:{w=b+3288|0;Wc(n,+h[l>>3],0,c[w>>2]|0);Wc(o,+h[m>>3],0,c[w>>2]|0);w=Dg(n|0)|0;m=w+1+(Dg(o|0)|0)|0;l=b+3476|0;v=b+3508|0;x=(Dg(l|0)|0)+2+(Dg(v|0)|0)|0;p=b+3884|0;if(((c[p>>2]|0)==6?(c[b+3328>>2]|0)==1:0)?(s=x+m|0,(u|0)>(s|0)):0){if((a[l]|0)!=0){t=n+w|0;a[t]=32;a[t+1|0]=0;Fg(n|0,l|0)|0}if((a[v]|0)==0){y=s}else{t=o+(Dg(o|0)|0)|0;a[t]=32;a[t+1|0]=0;Fg(o|0,v|0)|0;y=s}}else{y=m}m=(c[b+3296>>2]|0)!=0;do{if((u|0)>(y|0)){if(m){c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6240,k|0)|0;break}else{c[k>>2]=n;c[k+4>>2]=o;Na(f|0,6248,k|0)|0;break}}else{if(m){Hg(f|0,6496,u|0)|0;break}else{Hg(f|0,6280,u|0)|0;break}}}while(0);if((c[p>>2]|0)!=6){r=1;i=j;return r|0}m=b+3328|0;if((c[m>>2]|0)==1){r=1;i=j;return r|0}if((u|0)>(y+7|0)?(b=f+(Dg(f|0)|0)|0,k=b,a[k]=1852402720,a[k+1|0]=7235948,a[k+2|0]=28265,a[k+3|0]=110,k=b+4|0,a[k]=7496037,a[k+1|0]=29281,a[k+2|0]=114,a[k+3|0]=0,(c[p>>2]|0)!=6):0){r=1;i=j;return r|0}if((c[m>>2]|0)!=2){r=1;i=j;return r|0}if((u|0)<=(x+7+y|0)){r=1;i=j;return r|0}if((a[l]|0)!=0){y=f+(Dg(f|0)|0)|0;a[y]=32;a[y+1|0]=0;Fg(f|0,l|0)|0}if((a[v]|0)==0){r=1;i=j;return r|0}l=f+(Dg(f|0)|0)|0;a[l]=32;a[l+1|0]=0;Fg(f|0,v|0)|0;r=1;i=j;return r|0}}}if((g|0)<=0){r=0;i=j;return r|0}a[f]=0;r=0;i=j;return r|0}function ec(a,b,c,d){a=+a;b=+b;c=+c;d=+d;var e=0,f=0,g=0;e=i;i=i+48|0;f=e+24|0;g=e;Ac(a,b,1.0,f);Ac(c,d,1.0,g);d=+h[f>>3]- +h[g>>3];c=+h[f+8>>3]- +h[g+8>>3];b=+h[f+16>>3]- +h[g+16>>3];a=(d*d+0.0+c*c+b*b)*.25;b=a>1.0?1.0:a;a=+Y(+(+Q(+b)),+(+Q(+(1.0-b))))*2.0*180.0/3.141592653589793;i=e;return+a}function fc(a){a=a|0;var b=0;if((a|0)==0){b=0}else{b=(c[a+3312>>2]|0)!=0}return(b?a+3796|0:0)|0}function gc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;if((a|0)!=0?(c[a+3312>>2]|0)!=0:0){e=a+3292|0;f=c[e>>2]|0;c[e>>2]=b;if((b|0)==1&(f|0)==0?(e=a+3288|0,(c[e>>2]|0)==3):0){c[e>>2]=6}if((b|0)==0&(f|0)==1){b=a+3288|0;if((c[b>>2]|0)==5){c[b>>2]=3;g=1}else{g=1}}else{g=f}}else{g=0}i=d;return g|0}function hc(a){a=a|0;var b=0;if((a|0)==0){b=0}else{b=(c[a+3312>>2]|0)!=0}return(b?a+3764|0:0)|0}function ic(a,b,d,e,f,g,j){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0;k=i;i=i+32|0;l=k+24|0;m=k+16|0;n=k+8|0;o=k;if((a|0)==0){i=k;return}if((c[a+3312>>2]|0)==0){i=k;return}c[j>>2]=0;h[l>>3]=b;h[m>>3]=d;p=c[a+3264>>2]|0;if((p|0)==90){h[m>>3]=90.0-d}else if((p|0)==-90){h[m>>3]=d+-90.0}if((e|0)==0){q=+h[a+120>>3];r=c[a+3884>>2]|0}else{p=nc(e)|0;q=+oc(e);r=p}h[a+592>>3]=1.0;if((r|0)>0?!((r|0)==6|(r|0)==10):0){mc(r,c[a+3884>>2]|0,q,+h[a+120>>3],l,m,+h[a+128>>3])}r=c[a+3260>>2]|0;do{if((r|0)==32){if((md(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==30){if((cd(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==29){if((od(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else if((r|0)==31){if((fd(+h[l>>3],+h[m>>3],a,n,o)|0)!=0){c[j>>2]=1}}else{q=+h[l>>3];s=+h[m>>3];if((c[a+3324>>2]|0)==2|(r|0)<1){if((ad(q,s,a,n,o)|0)==0){break}c[j>>2]=1;break}else{if((jc(q,s,a,n,o)|0)==0){break}c[j>>2]=1;break}}}while(0);r=c[a+9312>>2]|0;s=+h[n>>3];q=+h[o>>3];do{if((r|0)==0){Ze(a,s,q,f,g);o=c[j>>2]|0;if((o|0)==0){t=+h[f>>3];if(!(t<.5)?(u=+h[g>>3],!(u<.5)):0){if(!(t>+h[a+136>>3]+.5)?!(u>+h[a+144>>3]+.5):0){v=0;break}c[j>>2]=2;v=2;break}c[j>>2]=2;v=2}else{v=o}}else{ic(r,s,q,0,f,g,j);v=c[j>>2]|0}}while(0);c[a+3308>>2]=v;h[a+600>>3]=b;h[a+608>>3]=d;h[a+576>>3]=+h[f>>3];h[a+584>>3]=+h[g>>3];i=k;return}function jc(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+112|0;j=g+80|0;k=g+48|0;l=g+16|0;m=g+8|0;n=g;h[e>>3]=0.0;h[f>>3]=0.0;o=d+3924|0;if((c[o>>2]|0)!=137){p=d+3368|0;if((xd(c[d+3960>>2]|0,p,o)|0)==0){q=p}else{r=1;i=g;return r|0}}else{q=d+3368|0}p=d+3944|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;c[j+16>>2]=0;c[j+20>>2]=0;c[j+24>>2]=0;c[j+28>>2]=0;h[j+(c[p>>2]<<3)>>3]=a;h[j+(c[d+3948>>2]<<3)>>3]=b;p=l+16|0;c[l+0>>2]=0;c[l+4>>2]=0;c[l+8>>2]=0;c[l+12>>2]=0;h[p>>3]=1.0;h[l+24>>3]=1.0;s=k+16|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;h[s>>3]=1.0;h[k+24>>3]=1.0;s=yd(q,o,j,d+688|0,d+3984|0,m,n,d+4064|0,k,d+3956|0,l)|0;if((s|0)!=0){r=s;i=g;return r|0}h[e>>3]=+h[l>>3];h[f>>3]=+h[l+8>>3];b=+h[p>>3];if(((c[d+3260>>2]|0)+ -24|0)>>>0<3){h[d+592>>3]=b+-1.0;r=0;i=g;return r|0}else{h[d+592>>3]=b;r=0;i=g;return r|0}return 0}function kc(){return c[1528]|0}function lc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0;b=i;d=a+3316|0;e=c[d>>2]|0;f=(e|0)>2?2:e;if((f+ -1|0)>>>0>8){e=c[a+3320>>2]|0;c[d>>2]=e;g=e}else{g=f}f=aa(g<<3,g)|0;e=a+3976|0;d=c[e>>2]|0;if((d|0)==0){j=gg(f)|0;c[e>>2]=j;if((j|0)==0){i=b;return}else{k=j}}else{k=d}d=a+3980|0;if((c[d>>2]|0)==0?(j=gg(f)|0,c[d>>2]=j,(j|0)==0):0){i=b;return}j=a+3956|0;c[j>>2]=137;if((g|0)==3){l=k+0|0;m=l+72|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));f=c[e>>2]|0;h[f>>3]=+h[a+56>>3];h[f+8>>3]=+h[a+64>>3];h[f+24>>3]=+h[a+72>>3];h[f+32>>3]=+h[a+80>>3];h[f+64>>3]=1.0;n=f}else if((g|0)==2){h[k>>3]=+h[a+56>>3];h[k+8>>3]=+h[a+64>>3];h[k+16>>3]=+h[a+72>>3];h[k+24>>3]=+h[a+80>>3];n=k}else if((g|0)==4){l=k+0|0;m=l+128|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));l=c[e>>2]|0;h[l>>3]=+h[a+56>>3];h[l+8>>3]=+h[a+64>>3];h[l+32>>3]=+h[a+72>>3];h[l+40>>3]=+h[a+80>>3];h[l+80>>3]=1.0;h[l+120>>3]=1.0;n=l}else{n=k}Bd(g,n,c[d>>2]|0)|0;c[a+3964>>2]=a+616;c[a+3972>>2]=a+760;c[a+3968>>2]=a+832;c[j>>2]=137;i=b;return}function mc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=+c;d=+d;e=e|0;f=f|0;g=+g;var j=0,k=0,l=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0,s=0,t=0.0;j=i;i=i+32|0;k=j+24|0;l=j+16|0;m=j+8|0;n=j;if(c==0.0){o=(a|0)==2?1950.0:2.0e3}else{o=c}if(d==0.0){p=(b|0)==2?1950.0:2.0e3}else{p=d}q=(b|0)==11;r=(a|0)==1&q&o==2.0e3;d=r?o:(a|0)==11&q?o:p;q=r?b:a;a=(b|0)==1;r=(q|0)==11&a&d==2.0e3;p=r?d:o;s=r?b:q;if((s|0)==(b|0)&p==d){i=j;return}q=p!=d;if(q){if((s|0)==2&p!=1950.0){xc(p,1950.0,e,f)}if((s|0)==1&p!=2.0e3){yc(p,2.0e3,e,f)}}r=(b|0)==2;do{if(r){if((s|0)==3){sc(e,f);break}else if((s|0)==4){if(g>0.0){wc(e,f,g);h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);p=g+-1950.0;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{wc(e,f,1950.0);h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);h[e>>3]=+h[e>>3]+ +h[m>>3]*0.0;h[f>>3]=+h[f>>3]+ +h[n>>3]*0.0;break}}else if((s|0)==1){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);p=g+-1950.0;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;pc(e,f,m,n,k,l);break}}else{break}}else{if((b|0)==4){if((s|0)==1){if(g>0.0){vc(e,f,g);break}else{vc(e,f,2.0e3);break}}else if((s|0)==3){uc(e,f);if(g>0.0){vc(e,f,g);break}else{vc(e,f,2.0e3);break}}else if((s|0)==2){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);p=g+-2.0e3;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];vc(e,f,g);break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);h[e>>3]=+h[e>>3]+ +h[m>>3]*-50.0;h[f>>3]=+h[f>>3]+ +h[n>>3]*-50.0;vc(e,f,1950.0);break}}else{break}}else if((b|0)==3){if((s|0)==4){if(g>0.0){wc(e,f,g)}else{wc(e,f,2.0e3)}tc(e,f);break}else if((s|0)==2){rc(e,f);break}else if((s|0)==1){tc(e,f);break}else{break}}else if((b|0)==1){if((s|0)==3){uc(e,f);break}else if((s|0)==4){if(g>0.0){wc(e,f,g);break}else{wc(e,f,2.0e3);break}}else if((s|0)==2){if(g>0.0){h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);p=g+-2.0e3;h[e>>3]=+h[e>>3]+p*+h[m>>3];h[f>>3]=+h[f>>3]+p*+h[n>>3];break}else{h[m>>3]=0.0;h[n>>3]=0.0;h[k>>3]=0.0;h[l>>3]=0.0;qc(e,f,m,n,k,l);break}}else{break}}else{break}}}while(0);if(q){if(r&d!=1950.0){xc(1950.0,d,e,f)}if(a&d!=2.0e3){yc(2.0e3,d,e,f)}}d=+h[f>>3];do{if(!(d>90.0)){if(d<-90.0){h[f>>3]=-180.0-d;g=+h[e>>3]+180.0;h[e>>3]=g;t=g;break}else{t=+h[e>>3];break}}else{h[f>>3]=180.0-d;g=+h[e>>3]+180.0;h[e>>3]=g;t=g}}while(0);if(t>360.0){h[e>>3]=t+-360.0;i=j;return}if(!(t<0.0)){i=j;return}h[e>>3]=t+360.0;i=j;return}function nc(b){b=b|0;var c=0,d=0,e=0,f=0.0;c=i;d=a[b]|0;a:do{if((((((!(d<<24>>24==106|d<<24>>24==74)?(yg(b,6688)|0)!=0:0)?(yg(b,6696)|0)!=0:0)?(yg(b,6704)|0)!=0:0)?(yg(b,6712)|0)!=0:0)?(Ag(b,6720,3)|0)!=0:0)?(Ag(b,6728,3)|0)!=0:0){if((((!(d<<24>>24==98|d<<24>>24==66)?(yg(b,6736)|0)!=0:0)?(yg(b,6744)|0)!=0:0)?(Ag(b,6752,3)|0)!=0:0)?(Ag(b,6760,3)|0)!=0:0){switch(d<<24>>24){case 105:case 73:{e=11;break a;break};case 108:case 76:{e=6;break a;break};case 101:case 69:{e=4;break a;break};case 97:case 65:{e=5;break a;break};case 110:case 78:{e=7;break a;break};case 103:case 71:{e=3;break a;break};default:{if((zg(b,6768,5)|0)==0){e=10;break a}if(d<<24>>24==112|d<<24>>24==80){e=9;break a}if((Gc(b)|0)==0){e=-1;break a}f=+ug(b);if(f>1980.0){e=1;break a}e=f>1900.0?2:-1;break a}}}else{e=2}}else{e=1}}while(0);i=c;return e|0}function oc(b){b=b|0;var c=0,d=0,e=0.0;c=i;d=a[b]|0;if(!(d<<24>>24==98|d<<24>>24==66|d<<24>>24==106|d<<24>>24==74)){if((Ag(b,6752,3)|0)!=0?(Ag(b,6760,3)|0)!=0:0){if((((Ag(b,6720,3)|0)!=0?(Ag(b,6728,3)|0)!=0:0)?(Ag(b,6704,4)|0)!=0:0)?(Ag(b,6712,4)|0)!=0:0){if((d+ -49<<24>>24&255)<2){e=+ug(b)}else{e=0.0}}else{e=2.0e3}}else{e=1950.0}}else{e=+ug(b+1|0)}i=c;return+e}function pc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0;g=i;i=i+48|0;j=g;k=+h[a>>3]*3.141592653589793/180.0;l=+h[b>>3]*3.141592653589793/180.0;m=+h[c>>3]*36.0e4;n=+h[d>>3]*36.0e4;o=+T(+k);p=+S(+k);k=+T(+l);q=+S(+l);l=p*q;r=o*q;if(m!=0.0|n!=0.0){s=-(m*r)-n*p*k;t=m*l-n*o*k;u=n*q}else{s=0.0;t=0.0;u=0.0}v=0;do{h[j+(v<<3)>>3]=+h[6776+(v*48|0)>>3]*l+0.0+ +h[6784+(v*48|0)>>3]*r+ +h[6792+(v*48|0)>>3]*k+ +h[6800+(v*48|0)>>3]*s+ +h[6808+(v*48|0)>>3]*t+ +h[6816+(v*48|0)>>3]*u;v=v+1|0}while((v|0)!=6);u=+h[j>>3];t=+h[j+8>>3];s=+h[j+16>>3];k=+Q(+(u*u+t*t+s*s));r=u*-162557.0e-11+t*-3.1919e-7+s*-1.3843e-7;l=u*r;q=u+k*-162557.0e-11-l;o=t*r;p=t+k*-3.1919e-7-o;w=s*r;r=s+k*-1.3843e-7-w;k=+Q(+(r*r+(q*q+p*p)));p=u*.001245+t*-.00158+s*-659.0e-6;q=u+k*-162557.0e-11-l;l=t+k*-3.1919e-7-o;o=s+k*-1.3843e-7-w;w=+h[j+24>>3]+k*.001245-p*q;s=k*-.00158+ +h[j+32>>3]-p*l;t=k*-659.0e-6+ +h[j+40>>3]-p*o;p=q*q+l*l;u=+Q(+p);if(!(q==0.0&l==0.0)){r=+Y(+l,+q);if(r<0.0){x=r+6.283185307179586}else{x=r}}else{x=0.0}r=+Y(+o,+u);if(u>1.0e-30){y=(t*p-o*(q*w+l*s))/(u*(o*o+p));z=(q*s-l*w)/p}else{y=n;z=m}m=+h[e>>3];if(!(m>1.0e-30)){A=x*180.0;B=A/3.141592653589793;h[a>>3]=B;C=r*180.0;D=C/3.141592653589793;h[b>>3]=D;E=z/36.0e4;h[c>>3]=E;F=y/36.0e4;h[d>>3]=F;i=g;return}h[f>>3]=(o*t+(q*w+l*s))/(k*m*21.095);h[e>>3]=+h[e>>3]/k;A=x*180.0;B=A/3.141592653589793;h[a>>3]=B;C=r*180.0;D=C/3.141592653589793;h[b>>3]=D;E=z/36.0e4;h[c>>3]=E;F=y/36.0e4;h[d>>3]=F;i=g;return}function qc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0;g=i;i=i+48|0;j=g;k=+h[a>>3]*3.141592653589793/180.0;l=+h[b>>3]*3.141592653589793/180.0;m=+h[c>>3]*36.0e4;n=+h[d>>3]*36.0e4;o=+T(+k);p=+S(+k);k=+T(+l);q=+S(+l);l=p*q;r=o*q;s=+h[f>>3];t=+h[e>>3];u=s*21.095*t;if(!(m!=0.0|n!=0.0)?!(s!=0.0&t!=0.0):0){v=-.001245;w=.00158;x=659.0e-6}else{v=-(m*r)-n*p*k+u*l+-.001245;w=m*l-n*o*k+u*r+.00158;x=n*q+u*k+659.0e-6}u=l*-162557.0e-11+r*-3.1919e-7+k*-1.3843e-7;q=u*l+(l+162557.0e-11);o=u*r+(r+3.1919e-7);p=u*k+(k+1.3843e-7);u=l*.001245+r*-.00158+k*-659.0e-6;s=v+u*l;l=w+u*r;r=x+u*k;y=0;do{h[j+(y<<3)>>3]=+h[7064+(y*48|0)>>3]*q+0.0+ +h[7072+(y*48|0)>>3]*o+ +h[7080+(y*48|0)>>3]*p+ +h[7088+(y*48|0)>>3]*s+ +h[7096+(y*48|0)>>3]*l+ +h[7104+(y*48|0)>>3]*r;y=y+1|0}while((y|0)!=6);r=+h[j>>3];l=+h[j+8>>3];s=+h[j+16>>3];p=+h[j+24>>3];o=+h[j+32>>3];q=+h[j+40>>3];k=r*r+l*l;u=+Q(+k);x=k+s*s;w=+Q(+x);v=r*p+l*o;z=v+s*q;if(!(r==0.0&l==0.0)){A=+Y(+l,+r);if(A<0.0){B=A+6.283185307179586}else{B=A}}else{B=0.0}A=+Y(+s,+u);if(u>1.0e-30){C=(k*q-s*v)/(x*u);D=(r*o-l*p)/k}else{C=n;D=m}if(!(t>1.0e-30)){E=B*180.0;F=E/3.141592653589793;h[a>>3]=F;G=A*180.0;H=G/3.141592653589793;h[b>>3]=H;I=D/36.0e4;h[c>>3]=I;J=C/36.0e4;h[d>>3]=J;i=g;return}h[f>>3]=z/(w*t*21.095);h[e>>3]=+h[e>>3]/w;E=B*180.0;F=E/3.141592653589793;h[a>>3]=F;G=A*180.0;H=G/3.141592653589793;h[b>>3]=H;I=D/36.0e4;h[c>>3]=I;J=C/36.0e4;h[d>>3]=J;i=g;return}function rc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0,x=0,y=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.066988739415+q*-.872755765852+l*-.483538914632;n=p*.492728466075+q*-.45034695802+l*.744584633283;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.867600811151+q*-.188374601723+l*.460199784784),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}n=g/15.0;d=~~n;g=(n- +(d|0))*60.0;b=~~g;if(j<0.0){u=45;v=-j}else{u=43;v=j}w=~~v;j=(v- +(w|0))*60.0;x=~~j;y=gg(32)|0;c[f>>2]=d;c[f+4>>2]=b;d=f+8|0;h[k>>3]=(g- +(b|0))*60.0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[f+16>>2]=u;c[f+20>>2]=w;c[f+24>>2]=x;w=f+28|0;h[k>>3]=(j- +(x|0))*60.0;c[w>>2]=c[k>>2];c[w+4>>2]=c[k+4>>2];Na(y|0,7648,f|0)|0;w=y+6|0;if((a[w]|0)==32){a[w]=48}w=y+20|0;if((a[w]|0)==32){a[w]=48}w=c[o>>2]|0;c[f>>2]=y;za(w|0,7360,f|0)|0;h[k>>3]=s;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];x=f+8|0;h[k>>3]=t;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];za(w|0,7392,f|0)|0;hg(y);i=e;return}function sc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0.0,x=0,y=0,z=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.066988739415+q*.492728466075+l*-.867600811151;n=p*-.872755765852+q*-.45034695802+l*-.188374601723;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.483538914632+q*.744584633283+l*.460199784784),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}d=c[o>>2]|0;h[k>>3]=g;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];b=f+8|0;h[k>>3]=j;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];za(d|0,7432,f|0)|0;j=s/15.0;b=~~j;s=(j- +(b|0))*60.0;u=~~s;if(t<0.0){v=45;w=-t}else{v=43;w=t}x=~~w;t=(w- +(x|0))*60.0;y=~~t;z=gg(32)|0;c[f>>2]=b;c[f+4>>2]=u;b=f+8|0;h[k>>3]=(s- +(u|0))*60.0;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];c[f+16>>2]=v;c[f+20>>2]=x;c[f+24>>2]=y;x=f+28|0;h[k>>3]=(t- +(y|0))*60.0;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];Na(z|0,7648,f|0)|0;x=z+6|0;if((a[x]|0)==32){a[x]=48}x=z+20|0;if((a[x]|0)==32){a[x]=48}c[f>>2]=z;za(d|0,7472,f|0)|0;hg(z);i=e;return}function tc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0,x=0,y=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.054875539726+q*-.87343710801+l*-.483834985808;n=p*.494109453312+q*-.444829589425+l*.74698225181;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.867666135858+q*-.198076386122+l*.455983795705),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}n=g/15.0;d=~~n;g=(n- +(d|0))*60.0;b=~~g;if(j<0.0){u=45;v=-j}else{u=43;v=j}w=~~v;j=(v- +(w|0))*60.0;x=~~j;y=gg(32)|0;c[f>>2]=d;c[f+4>>2]=b;d=f+8|0;h[k>>3]=(g- +(b|0))*60.0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[f+16>>2]=u;c[f+20>>2]=w;c[f+24>>2]=x;w=f+28|0;h[k>>3]=(j- +(x|0))*60.0;c[w>>2]=c[k>>2];c[w+4>>2]=c[k+4>>2];Na(y|0,7648,f|0)|0;w=y+6|0;if((a[w]|0)==32){a[w]=48}w=y+20|0;if((a[w]|0)==32){a[w]=48}w=c[o>>2]|0;c[f>>2]=y;za(w|0,7504,f|0)|0;h[k>>3]=s;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];x=f+8|0;h[k>>3]=t;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];za(w|0,7536,f|0)|0;hg(y);i=e;return}function uc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,l=0.0,m=0.0,n=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0.0,x=0,y=0,z=0;e=i;i=i+48|0;f=e;g=+h[b>>3];j=+h[d>>3];l=g*3.141592653589793/180.0;m=j*3.141592653589793/180.0;n=+S(+m);p=+S(+l)*n;q=n*+T(+l);l=+T(+m);m=p*-.054875539726+q*.494109453312+l*-.867666135858;n=p*-.87343710801+q*-.444829589425+l*-.198076386122;r=+Y(+n,+m);if(r<0.0){s=r+6.283185307179586}else{s=r}if(s>6.283185307179586){t=s+-6.283185307179586}else{t=s}s=t*180.0/3.141592653589793;t=+Y(+(p*-.483834985808+q*.74698225181+l*.455983795705),+(+Q(+(m*m+n*n))))*180.0/3.141592653589793;h[b>>3]=s;h[d>>3]=t;if((c[1838]|0)==0){i=e;return}d=c[o>>2]|0;h[k>>3]=g;c[f>>2]=c[k>>2];c[f+4>>2]=c[k+4>>2];b=f+8|0;h[k>>3]=j;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];za(d|0,7576,f|0)|0;j=s/15.0;b=~~j;s=(j- +(b|0))*60.0;u=~~s;if(t<0.0){v=45;w=-t}else{v=43;w=t}x=~~w;t=(w- +(x|0))*60.0;y=~~t;z=gg(32)|0;c[f>>2]=b;c[f+4>>2]=u;b=f+8|0;h[k>>3]=(s- +(u|0))*60.0;c[b>>2]=c[k>>2];c[b+4>>2]=c[k+4>>2];c[f+16>>2]=v;c[f+20>>2]=x;c[f+24>>2]=y;x=f+28|0;h[k>>3]=(t- +(y|0))*60.0;c[x>>2]=c[k>>2];c[x+4>>2]=c[k+4>>2];Na(z|0,7648,f|0)|0;x=z+6|0;if((a[x]|0)==32){a[x]=48}x=z+20|0;if((a[x]|0)==32){a[x]=48}c[f>>2]=z;za(d|0,7616,f|0)|0;hg(z);i=e;return}function vc(a,b,c){a=a|0;b=b|0;c=+c;var d=0,e=0,f=0.0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0;d=i;i=i+80|0;e=d;if(c!=2.0e3){yc(2.0e3,c,a,b)}f=+h[a>>3]*3.141592653589793/180.0;g=+h[b>>3]*3.141592653589793/180.0;j=+S(+g);k=+S(+f)*j;l=j*+T(+f);f=+T(+g);g=(c+-2.0e3)*.01;zc(1,(g*(g*(g*.001813+-59.0e-5)+-46.815)+84381.448)*48481368110953.0e-19,0.0,0.0,e);g=+h[e>>3]*k+0.0+ +h[e+8>>3]*l+ +h[e+16>>3]*f;c=+h[e+24>>3]*k+0.0+ +h[e+32>>3]*l+ +h[e+40>>3]*f;j=+h[e+48>>3]*k+0.0+ +h[e+56>>3]*l+ +h[e+64>>3]*f;f=+Y(+c,+g);if(f<0.0){m=f+6.283185307179586}else{m=f}if(!(m>6.283185307179586)){n=m;o=g*g;p=c*c;q=o+p;r=+Q(+q);s=+Y(+j,+r);t=n*180.0;u=t/3.141592653589793;h[a>>3]=u;v=s*180.0;w=v/3.141592653589793;h[b>>3]=w;i=d;return}n=m+-6.283185307179586;o=g*g;p=c*c;q=o+p;r=+Q(+q);s=+Y(+j,+r);t=n*180.0;u=t/3.141592653589793;h[a>>3]=u;v=s*180.0;w=v/3.141592653589793;h[b>>3]=w;i=d;return}function wc(a,b,c){a=a|0;b=b|0;c=+c;var d=0,e=0,f=0.0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0;d=i;i=i+80|0;e=d;f=+h[a>>3]*3.141592653589793/180.0;g=+h[b>>3]*3.141592653589793/180.0;j=+S(+g);k=+S(+f)*j;l=j*+T(+f);f=+T(+g);g=(c+-2.0e3)*.01;zc(1,(g*(g*(g*.001813+-59.0e-5)+-46.815)+84381.448)*48481368110953.0e-19,0.0,0.0,e);g=+h[e>>3]*k+0.0+ +h[e+24>>3]*l+ +h[e+48>>3]*f;j=+h[e+8>>3]*k+0.0+ +h[e+32>>3]*l+ +h[e+56>>3]*f;m=+Y(+j,+g);if(m<0.0){n=m+6.283185307179586}else{n=m}if(n>6.283185307179586){o=n+-6.283185307179586}else{o=n}n=+Y(+(+h[e+16>>3]*k+0.0+ +h[e+40>>3]*l+ +h[e+64>>3]*f),+(+Q(+(g*g+j*j))));h[a>>3]=o*180.0/3.141592653589793;h[b>>3]=n*180.0/3.141592653589793;if(!(c!=2.0e3)){i=d;return}yc(c,2.0e3,a,b);i=d;return}function xc(a,b,c,d){a=+a;b=+b;c=c|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;e=i;i=i+80|0;f=e;g=+h[c>>3]*3.141592653589793/180.0;j=+h[d>>3]*3.141592653589793/180.0;k=(a+-1850.0)/100.0;l=(b-a)/100.0;a=l*48481368110953.0e-19;b=k*(k*59.0e-6+1.3972)+2303.5548;m=k*365.0e-6;zc(323,-(a*(b+l*(.30242-k*269.0e-6+l*.017996))),a*(k*(-.85294-m)+2005.1125+l*(-.42647-m-l*.041802)),-(a*(b+l*(k*387.0e-6+1.09478+l*.018324))),f);l=+S(+j);k=+S(+g)*l;b=l*+T(+g);g=+T(+j);j=+h[f>>3]*k+0.0+ +h[f+8>>3]*b+ +h[f+16>>3]*g;l=+h[f+24>>3]*k+0.0+ +h[f+32>>3]*b+ +h[f+40>>3]*g;a=+h[f+48>>3]*k+0.0+ +h[f+56>>3]*b+ +h[f+64>>3]*g;g=+Y(+l,+j);if(g<0.0){n=g+6.283185307179586}else{n=g}if(!(n>6.283185307179586)){o=n;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}o=n+-6.283185307179586;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}function yc(a,b,c,d){a=+a;b=+b;c=c|0;d=d|0;var e=0,f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0;e=i;i=i+80|0;f=e;g=+h[c>>3]*3.141592653589793/180.0;j=+h[d>>3]*3.141592653589793/180.0;k=(a+-2.0e3)/100.0;l=(b-a)/100.0;a=l*48481368110953.0e-19;b=k*(1.39656-k*139.0e-6)+2306.2181;m=k*217.0e-6;zc(323,-(a*(b+l*(.30188-k*344.0e-6+l*.017998))),a*(k*(-.8533-m)+2004.3109+l*(-.42665-m-l*.041833)),-(a*(b+l*(k*66.0e-6+1.09468+l*.018203))),f);l=+S(+j);k=+S(+g)*l;b=l*+T(+g);g=+T(+j);j=k*+h[f>>3]+0.0+b*+h[f+8>>3]+g*+h[f+16>>3];l=k*+h[f+24>>3]+0.0+b*+h[f+32>>3]+g*+h[f+40>>3];a=k*+h[f+48>>3]+0.0+b*+h[f+56>>3]+g*+h[f+64>>3];g=+Y(+l,+j);if(g<0.0){n=g+6.283185307179586}else{n=g}if(!(n>6.283185307179586)){o=n;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}o=n+-6.283185307179586;p=j*j;q=l*l;r=p+q;s=+Q(+r);t=+Y(+a,+s);u=o*180.0;v=u/3.141592653589793;h[c>>3]=v;w=t*180.0;x=w/3.141592653589793;h[d>>3]=x;i=e;return}function zc(a,b,d,e,f){a=a|0;b=+b;d=+d;e=+e;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0,B=0.0,C=0.0,D=0,E=0.0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0,L=0.0,M=0,N=0.0;g=i;i=i+192|0;j=g+144|0;k=g+72|0;l=g;m=g+168|0;n=f+8|0;h[f>>3]=1.0;o=f+16|0;h[n>>3]=0.0;h[o>>3]=0.0;p=f+24|0;h[p>>3]=0.0;h[f+32>>3]=1.0;h[f+40>>3]=0.0;h[f+48>>3]=0.0;h[f+56>>3]=0.0;h[f+64>>3]=1.0;q=(a|0)/100|0;c[m>>2]=q;if((a|0)>99){r=(aa(q,-100)|0)+a|0;s=1}else{r=a;s=0}a=(r|0)/10|0;c[m+(s<<2)>>2]=a;if((r|0)>9){t=(aa(a,-10)|0)+r|0;u=s+1|0}else{t=r;u=s}c[m+(u<<2)>>2]=t;s=((t|0)>0)+u|0;h[j>>3]=b;h[j+8>>3]=d;h[j+16>>3]=e;if((s|0)<=0){i=g;return}u=l+32|0;t=l+40|0;r=l+56|0;a=l+64|0;q=l+16|0;v=l+48|0;w=l+8|0;x=l+24|0;y=k+8|0;e=b;b=1.0;d=0.0;z=1.0;A=0;while(1){h[l>>3]=1.0;h[l+8>>3]=0.0;h[l+16>>3]=0.0;h[l+24>>3]=0.0;h[l+32>>3]=1.0;h[l+40>>3]=0.0;h[l+48>>3]=0.0;h[l+56>>3]=0.0;h[l+64>>3]=1.0;B=+T(+e);C=+S(+e);D=c[m+(A<<2)>>2]|0;do{if((D|0)!=1){h[l>>3]=C;if((D|0)==2){h[q>>3]=-B;h[v>>3]=B;h[a>>3]=C;break}else{h[w>>3]=B;h[x>>3]=-B;h[u>>3]=C;break}}else{h[u>>3]=C;h[t>>3]=B;h[r>>3]=-B;h[a>>3]=C}}while(0);C=+h[p>>3];B=+h[n>>3];E=+h[f+32>>3];F=+h[f+56>>3];G=+h[f+16>>3];H=+h[f+40>>3];D=0;do{I=D*3|0;J=+h[l+(I<<3)>>3];K=I+1|0;L=+h[l+(K<<3)>>3];M=I+2|0;N=+h[l+(M<<3)>>3];h[k+(I<<3)>>3]=J*b+0.0+L*C+N*d;h[k+(K<<3)>>3]=J*B+0.0+L*E+N*F;h[k+(M<<3)>>3]=J*G+0.0+L*H+N*z;D=D+1|0}while((D|0)!=3);H=+h[k>>3];h[f>>3]=H;h[n>>3]=+h[y>>3];h[o>>3]=+h[k+16>>3];h[f+24>>3]=+h[k+24>>3];h[f+32>>3]=+h[k+32>>3];h[f+40>>3]=+h[k+40>>3];G=+h[k+48>>3];h[f+48>>3]=G;h[f+56>>3]=+h[k+56>>3];F=+h[k+64>>3];h[f+64>>3]=F;D=A+1|0;if((D|0)==(s|0)){break}e=+h[j+(D<<3)>>3];b=H;d=G;z=F;A=D}i=g;return}function Ac(a,b,c,d){a=+a;b=+b;c=+c;d=d|0;var e=0.0;e=a*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+a);h[d>>3]=+S(+e)*c*b;h[d+8>>3]=b*+T(+e)*c;h[d+16>>3]=+T(+a)*c;return}function Bc(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;if((b|0)>0){e=b}else{c[1922]=0;e=(Cc(a,7696)|0)+80-a|0}c[1922]=e;i=d;return e|0}function Cc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;e=i;f=c[1922]|0;g=(f|0)==0?256e3:f;if((g|0)>0){h=0}else{j=0;i=e;return j|0}while(1){f=h+1|0;if((a[b+h|0]|0)<1){k=h;break}if((f|0)<(g|0)){h=f}else{k=f;break}}h=b+k|0;g=h;if((k|0)<=0){j=0;i=e;return j|0}k=b;f=b;a:while(1){b=Rc(f,d,g-f|0)|0;if((b|0)==0){j=0;l=17;break}m=(b-k|0)%80|0;n=a[b+(Dg(d|0)|0)|0]|0;do{if((m|0)<=7){if(n<<24>>24>32?!(n<<24>>24==61|n<<24>>24==127):0){o=b+1|0;break}p=0-m|0;q=b+p|0;if((p|0)<0){p=b+1|0;r=f;s=q;while(1){t=(a[s]|0)==32?r:p;u=s+1|0;if(u>>>0>>0){r=t;s=u}else{v=t;break}}}else{v=f}if(b>>>0>>0){o=v}else{j=q;l=17;break a}}else{o=b+1|0}}while(0);if(o>>>0>>0){f=o}else{j=0;l=17;break}}if((l|0)==17){i=e;return j|0}return 0}function Dc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;i=i+16|0;g=f;if((a[d]|0)<64){h=Ec(b,c,e)|0;i=f;return h|0}else{Lg(g|0,c|0)|0;j=Dg(c|0)|0;a[g+j|0]=a[d]|0;a[g+(j+1)|0]=0;h=Ec(b,g,e)|0;i=f;return h|0}return 0}function Ec(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0.0,k=0.0;f=i;g=Fc(b,d)|0;if((g|0)==0){h=0;i=f;return h|0}d=(a[g]|0)==35?g+1|0:g;if((Dg(d|0)|0)>81){Hg(7704,d|0,81)|0;a[7785|0]=0}else{Lg(7704,d|0)|0}if((Gc(7704)|0)==2){d=$f(7704,68)|0;if((d|0)!=0){a[d]=101}d=$f(7704,100)|0;if((d|0)!=0){a[d]=101}d=$f(7704,69)|0;if((d|0)!=0){a[d]=101}}j=+ug(7704);k=j+.001;if(k>2147483647.0){c[e>>2]=2147483647;h=1;i=f;return h|0}if(j>=0.0){c[e>>2]=~~k;h=1;i=f;return h|0}k=j+-.001;if(k<-2147483648.0){c[e>>2]=-2147483648;h=1;i=f;return h|0}else{c[e>>2]=~~k;h=1;i=f;return h|0}return 0}function Fc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;e=i;i=i+208|0;f=e+194|0;g=e+8|0;h=e+2|0;j=e+4|0;k=e+196|0;l=e;m=e+6|0;n=e+112|0;o=e+12|0;a[g]=39;a[g+1|0]=0;a[h]=34;a[h+1|0]=0;a[j]=91;a[j+1|0]=0;a[m]=44;a[m+1|0]=0;a[k]=93;a[k+1|0]=0;a[l]=47;a[l+1|0]=0;Hg(n|0,d|0,80)|0;d=Dg(n|0)|0;p=Dg(j|0)|0;a:do{if((p|0)!=0){if((d|0)!=0?(q=p+ -1|0,r=a[j+q|0]|0,s=d+1-p|0,t=n+s|0,(s|0)>0):0){s=(p|0)==1;u=(p|0)<3;v=n;do{b:do{if((a[v]|0)==91){if(s){w=v;x=23;break a}if((a[v+q|0]|0)==r<<24>>24){if(u){w=v;x=23;break a}else{y=1}while(1){z=y+1|0;if((a[v+y|0]|0)!=(a[j+y|0]|0)){break b}if((z|0)<(p|0)){y=z}else{w=v;x=23;break a}}}}}while(0);v=v+1|0}while(v>>>0>>0)}t=Dg(n|0)|0;v=Dg(m|0)|0;if((v|0)!=0){if((t|0)!=0?(u=v+ -1|0,r=a[m+u|0]|0,q=t+1-v|0,t=n+q|0,(q|0)>0):0){q=(v|0)==1;s=(v|0)<3;z=n;while(1){c:do{if((a[z]|0)==44){if(q){w=z;x=23;break a}if((a[z+u|0]|0)==r<<24>>24){if(s){w=z;x=23;break a}else{A=1}while(1){B=A+1|0;if((a[z+A|0]|0)!=(a[m+A|0]|0)){break c}if((B|0)<(v|0)){A=B}else{w=z;x=23;break a}}}}}while(0);B=z+1|0;if(B>>>0>>0){z=B}else{C=0;break}}}else{C=0}}else{w=n;x=23}}else{w=n;x=23}}while(0);if((x|0)==23){a[w]=0;C=w+1|0}w=Cc(b,n)|0;if((w|0)==0){D=0;i=e;return D|0}n=o+0|0;b=n+100|0;do{a[n]=0;n=n+1|0}while((n|0)<(b|0));Hg(o|0,w|0,80)|0;w=Dg(o|0)|0;n=Dg(g|0)|0;d:do{if((n|0)!=0){if((w|0)!=0?(b=a[g]|0,A=n+ -1|0,m=a[g+A|0]|0,y=w+1-n|0,p=o+y|0,(y|0)>0):0){y=(n|0)==1;j=(n|0)<3;d=o;while(1){e:do{if((a[d]|0)==b<<24>>24){if(y){E=d;break d}if((a[d+A|0]|0)==m<<24>>24){if(j){E=d;break d}else{F=1}while(1){z=F+1|0;if((a[d+F|0]|0)!=(a[g+F|0]|0)){break e}if((z|0)<(n|0)){F=z}else{E=d;break d}}}}}while(0);z=d+1|0;if(z>>>0

    >>0){d=z}else{E=0;break}}}else{E=0}}else{E=o}}while(0);F=Dg(o|0)|0;n=Dg(l|0)|0;f:do{if((n|0)!=0){if((F|0)!=0?(w=a[l]|0,d=n+ -1|0,p=a[l+d|0]|0,j=F+1-n|0,m=o+j|0,(j|0)>0):0){j=(n|0)==1;A=(n|0)<3;y=o;while(1){g:do{if((a[y]|0)==w<<24>>24){if(j){G=y;break f}if((a[y+d|0]|0)==p<<24>>24){if(A){G=y;break f}else{H=1}while(1){b=H+1|0;if((a[y+H|0]|0)!=(a[l+H|0]|0)){break g}if((b|0)<(n|0)){H=b}else{G=y;break f}}}}}while(0);b=y+1|0;if(b>>>0>>0){y=b}else{G=0;break}}}else{G=0}}else{G=o}}while(0);h:do{if((E|0)==0){H=Dg(o|0)|0;n=Dg(h|0)|0;i:do{if((n|0)==0){I=o}else{if((H|0)==0){x=116;break h}l=a[h]|0;F=n+ -1|0;y=a[h+F|0]|0;m=H+1-n|0;A=o+m|0;if((m|0)<=0){x=116;break h}m=(n|0)==1;p=(n|0)<3;d=o;while(1){j:do{if((a[d]|0)==l<<24>>24){if(m){I=d;break i}if((a[d+F|0]|0)==y<<24>>24){if(p){I=d;break i}else{J=1}while(1){j=J+1|0;if((a[d+J|0]|0)!=(a[h+J|0]|0)){break j}if((j|0)<(n|0)){J=j}else{I=d;break i}}}}}while(0);j=d+1|0;if(j>>>0>>0){d=j}else{x=116;break h}}}}while(0);if((G|0)!=0&I>>>0>>0){n=I+1|0;H=Dg(n|0)|0;d=Dg(h|0)|0;if((d|0)==0){K=I;L=n;x=115;break}if((H|0)!=0?(A=a[h]|0,p=d+ -1|0,y=a[h+p|0]|0,F=H+1-d|0,H=I+(F+1)|0,(F|0)>0):0){F=(d|0)==1;m=(d|0)<3;l=n;while(1){k:do{if((a[l]|0)==A<<24>>24){if(F){K=I;L=l;x=115;break h}if((a[l+p|0]|0)==y<<24>>24){if(m){K=I;L=l;x=115;break h}else{M=1}while(1){n=M+1|0;if((a[l+M|0]|0)!=(a[h+M|0]|0)){break k}if((n|0)<(d|0)){M=n}else{K=I;L=l;x=115;break h}}}}}while(0);n=l+1|0;if(n>>>0>>0){l=n}else{N=G;break}}}else{N=G}while(1){l=N+ -1|0;if((a[l]|0)==32){N=l}else{K=I;L=N;x=115;break h}}}if((G|0)==0){l=I+1|0;H=Dg(l|0)|0;d=Dg(h|0)|0;if((d|0)==0){K=I;L=l;x=115}else{if((H|0)!=0?(m=a[h]|0,y=d+ -1|0,p=a[h+y|0]|0,F=H+1-d|0,H=I+(F+1)|0,(F|0)>0):0){F=(d|0)==1;A=(d|0)<3;n=l;do{l:do{if((a[n]|0)==m<<24>>24){if(F){K=I;L=n;x=115;break h}if((a[n+y|0]|0)==p<<24>>24){if(A){K=I;L=n;x=115;break h}else{O=1}while(1){l=O+1|0;if((a[n+O|0]|0)!=(a[h+O|0]|0)){break l}if((l|0)<(d|0)){O=l}else{K=I;L=n;x=115;break h}}}}}while(0);n=n+1|0}while(n>>>0>>0)}H=o+79|0;while(1){if((a[H]|0)==32){H=H+ -1|0}else{break}}K=I;L=H+1|0;x=115}}else{x=116}}else{if((G|0)!=0&E>>>0>>0){n=E+1|0;d=Dg(n|0)|0;A=Dg(g|0)|0;if((A|0)==0){K=E;L=n;x=115;break}if((d|0)!=0?(p=a[g]|0,y=A+ -1|0,F=a[g+y|0]|0,m=d+1-A|0,d=E+(m+1)|0,(m|0)>0):0){m=(A|0)==1;l=(A|0)<3;j=n;while(1){m:do{if((a[j]|0)==p<<24>>24){if(m){K=E;L=j;x=115;break h}if((a[j+y|0]|0)==F<<24>>24){if(l){K=E;L=j;x=115;break h}else{P=1}while(1){n=P+1|0;if((a[j+P|0]|0)!=(a[g+P|0]|0)){break m}if((n|0)<(A|0)){P=n}else{K=E;L=j;x=115;break h}}}}}while(0);n=j+1|0;if(n>>>0>>0){j=n}else{Q=G;break}}}else{Q=G}while(1){j=Q+ -1|0;if((a[j]|0)==32){Q=j}else{K=E;L=Q;x=115;break h}}}if((G|0)==0){j=E+1|0;d=Dg(j|0)|0;A=Dg(g|0)|0;if((A|0)==0){K=E;L=j;x=115}else{if((d|0)!=0?(l=a[g]|0,F=A+ -1|0,y=a[g+F|0]|0,m=d+1-A|0,d=E+(m+1)|0,(m|0)>0):0){m=(A|0)==1;p=(A|0)<3;H=j;do{n:do{if((a[H]|0)==l<<24>>24){if(m){K=E;L=H;x=115;break h}if((a[H+F|0]|0)==y<<24>>24){if(p){K=E;L=H;x=115;break h}else{R=1}while(1){j=R+1|0;if((a[H+R|0]|0)!=(a[g+R|0]|0)){break n}if((j|0)<(A|0)){R=j}else{K=E;L=H;x=115;break h}}}}}while(0);H=H+1|0}while(H>>>0>>0)}d=o+79|0;while(1){if((a[d]|0)==32){d=d+ -1|0}else{break}}K=E;L=d+1|0;x=115}}else{x=116}}}while(0);if((x|0)==115){S=K+1|0;T=L}else if((x|0)==116){L=Dg(o|0)|0;o:do{if((L|0)!=0?(K=o+L|0,(L|0)>0):0){E=o;while(1){if((a[E]|0)==61){U=E;break o}R=E+1|0;if(R>>>0>>0){E=R}else{U=0;break}}}else{U=0}}while(0);L=(U|0)==0?o+9|0:U+1|0;U=Dg(o|0)|0;p:do{if((U|0)!=0?(E=o+U|0,(U|0)>0):0){K=o;while(1){if((a[K]|0)==47){V=K;break p}d=K+1|0;if(d>>>0>>0){K=d}else{V=0;break}}}else{V=0}}while(0);S=L;T=(V|0)==0?o+79|0:V}if((c[1968]|0)==0){V=S;while(1){if((a[V]|0)==32&V>>>0>>0){V=V+1|0}else{W=V;break}}}else{W=S}a[T]=0;q:do{if((c[1968]|0)==0){S=T;while(1){V=S+ -1|0;o=a[V]|0;if(!(o<<24>>24==13|o<<24>>24==32)){break q}if(!(V>>>0>W>>>0)){break q}a[V]=0;S=V}}}while(0);T=(yg(W,7960)|0)==0;S=T?W+1|0:W;Lg(7880,S|0)|0;if((C|0)==0){D=7880;i=e;return D|0}W=Dg(C|0)|0;T=Dg(k|0)|0;r:do{if((T|0)!=0){if((W|0)!=0?(V=a[k]|0,o=T+ -1|0,L=a[k+o|0]|0,U=W+1-T|0,K=C+U|0,(U|0)>0):0){U=(T|0)==1;E=(T|0)<3;d=C;s:while(1){t:do{if((a[d]|0)==V<<24>>24){if(U){break s}if((a[d+o|0]|0)==L<<24>>24){if(E){break s}else{X=1}while(1){R=X+1|0;if((a[d+X|0]|0)!=(a[k+X|0]|0)){break t}if((R|0)<(T|0)){X=R}else{break s}}}}}while(0);R=d+1|0;if(R>>>0>>0){d=R}else{break r}}if((d|0)!=0){Y=d;x=144}}}else{Y=C;x=144}}while(0);if((x|0)==144){a[Y]=0}if((Gc(C)|0)==0){Y=Dg(C|0)|0;if((Y|0)>0){x=0;do{X=C+x|0;T=a[X]|0;if((T+ -65<<24>>24&255)<26){a[X]=(T&255)+32}x=x+1|0}while((x|0)!=(Y|0))}Y=_c(7880,C)|0;if((Y|0)==0){D=0;i=e;return D|0}Lg(7880,Y|0)|0;D=7880;i=e;return D|0}Y=vg(C)|0;a[f]=32;a[f+1|0]=0;if((Y|0)>0){C=1;x=S;while(1){Z=fg(x,f)|0;if((C|0)==(Y|0)){break}else{C=C+1|0;x=0}}if((Z|0)==0){D=0;i=e;return D|0}Lg(7880,Z|0)|0;D=7880;i=e;return D|0}if((Y|0)>=0){D=7880;i=e;return D|0}Z=0-Y|0;u:do{if((Z|0)<=1){if((S|0)==0){D=0;i=e;return D|0}else{_=S}}else{Y=1;x=S;while(1){C=$f(x,32)|0;if((C|0)==0){D=0;break}f=C+1|0;C=Y+1|0;if((C|0)<(Z|0)){Y=C;x=f}else{_=f;break u}}i=e;return D|0}}while(0);Lg(7880,_|0)|0;D=7880;i=e;return D|0}function Gc(b){b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;c=i;a:do{if((b|0)!=0?(d=a[b]|0,!(d<<24>>24==101|d<<24>>24==69|d<<24>>24==100|d<<24>>24==68)):0){e=Dg(b|0)|0;while(1){f=e+ -1|0;if((a[b+f|0]|0)==32){e=f}else{break}}if((e|0)>0){f=d;g=0;h=1;j=0;k=0;while(1){if(f<<24>>24==32){if((k|0)==0){l=g;m=h;n=0}else{o=0;break a}}else if(!(f<<24>>24==10)){b:do{if(!((f+ -48<<24>>24&255)<10)){switch(f<<24>>24){case 45:case 43:{break};case 101:case 100:case 69:case 68:case 58:case 46:{p=13;break b;break};default:{o=0;break a}}q=a[b+(j+1)|0]|0;if(q<<24>>24==43|q<<24>>24==45){o=0;break a}if((j|0)>0){switch(a[b+(j+ -1)|0]|0){case 32:case 58:case 101:case 69:case 100:case 68:{r=g;s=k;break};default:{o=0;break a}}}else{r=g;s=k}}else{p=13}}while(0);do{if((p|0)==13){p=0;if((f+ -47<<24>>24&255)<11){r=g;s=k+1|0;break}else{r=(f<<24>>24==58)+g|0;s=k;break}}}while(0);if(f<<24>>24==101|f<<24>>24==100|f<<24>>24==46){l=r;m=2;n=s}else{l=r;m=h;n=s}}else{t=g;u=h;v=k;break}q=j+1|0;if((q|0)>=(e|0)){t=l;u=m;v=n;break}f=a[b+q|0]|0;g=l;h=m;j=q;k=n}if((v|0)>0){o=(t|0)==0?u:3}else{o=0}}else{o=0}}else{o=0}}while(0);i=c;return o|0}function Hc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,j=0.0,k=0,l=0,m=0.0;e=i;f=Fc(b,c)|0;if((f|0)==0){g=0;i=e;return g|0}j=+Jc(f);c=Dg(f|0)|0;a:do{if((c|0)!=0?(b=f+c|0,(c|0)>0):0){k=f;while(1){if((a[k]|0)==58){break}l=k+1|0;if(l>>>0>>0){k=l}else{m=j;break a}}if((k|0)!=0){m=j*15.0}else{m=j}}else{m=j}}while(0);h[d>>3]=m;g=1;i=e;return g|0}function Ic(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;d=i;e=Fc(a,b)|0;if((e|0)==0){f=0}else{h[c>>3]=+Jc(e);f=1}i=d;return f|0}function Jc(b){b=b|0;var c=0,d=0.0,e=0,f=0,g=0,h=0,j=0.0,k=0,l=0.0,m=0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0,w=0.0,x=0.0;c=i;if((b|0)==0){d=0.0;i=c;return+d}e=a[b]|0;if(e<<24>>24==0){d=0.0;i=c;return+d}else{f=e;g=b}while(1){if(f<<24>>24==43){h=5;break}else if(f<<24>>24==45){j=-1.0;h=6;break}else if(!(f<<24>>24==32)){h=7;break}b=g+1|0;f=a[b]|0;g=b}if((h|0)==5){j=1.0;h=6}else if((h|0)==7){f=Dg(g|0)|0;if((g|0)==0){k=1;l=1.0;m=0}else{n=f;o=1.0;p=g;h=8}}if((h|0)==6){f=g+1|0;n=Dg(f|0)|0;o=j;p=f;h=8}a:do{if((h|0)==8){if((n|0)!=0?(f=p+n|0,(n|0)>0):0){g=p;while(1){if((a[g]|0)==44){break}b=g+1|0;if(b>>>0>>0){g=b}else{k=0;l=o;m=p;break a}}if((g|0)!=0){a[g]=32;k=0;l=o;m=p}else{k=0;l=o;m=p}}else{k=0;l=o;m=p}}}while(0);p=Dg(m|0)|0;while(1){n=p+ -1|0;if((a[m+n|0]|0)==32){p=n}else{break}}n=Dg(m|0)|0;b:do{if(!k){c:do{if((n|0)!=0?(f=m+n|0,(n|0)>0):0){b=m;while(1){if((a[b]|0)==58){break}e=b+1|0;if(e>>>0>>0){b=e}else{h=22;break c}}if((b|0)!=0){q=b}else{h=22}}else{h=22}}while(0);if((h|0)==22){if((p|0)==0){break}g=m+p|0;if((p|0)>0){r=m}else{break}while(1){if((a[r]|0)==32){break}f=r+1|0;if(f>>>0>>0){r=f}else{break b}}if((r|0)==0){break}else{q=r}}a[q]=0;o=+(vg(m)|0);a[q]=58;g=q+1|0;f=Dg(g|0)|0;d:do{if((f|0)!=0?(e=q+(f+1)|0,(f|0)>0):0){s=g;while(1){if((a[s]|0)==58){t=s;h=35;break d}u=s+1|0;if(u>>>0>>0){s=u}else{h=31;break}}}else{h=31}}while(0);e:do{if((h|0)==31){f=Dg(g|0)|0;if((f|0)!=0?(s=q+(f+1)|0,(f|0)>0):0){f=g;do{if((a[f]|0)==32){t=f;h=35;break e}f=f+1|0}while(f>>>0>>0)}s=Dg(g|0)|0;f:do{if((s|0)!=0?(f=q+(s+1)|0,(s|0)>0):0){e=g;while(1){if((a[e]|0)==46){break}b=e+1|0;if(b>>>0>>0){e=b}else{v=0.0;break f}}v=+ug(g)}else{v=0.0}}while(0);if((a[g]|0)==0){w=v;x=0.0}else{w=+(vg(g)|0);x=0.0}}}while(0);if((h|0)==35){a[t]=0;j=+(vg(g)|0);a[t]=58;w=j;x=+ug(t+1|0)}d=l*(o+w/60.0+x/3600.0);i=c;return+d}}while(0);if((Gc(m)|0)!=2){d=l*+(vg(m)|0);i=c;return+d}t=$f(m,68)|0;if((t|0)!=0){a[t]=101}t=$f(m,100)|0;if((t|0)!=0){a[t]=101}t=$f(m,69)|0;if((t|0)!=0){a[t]=101}d=l*+ug(m);i=c;return+d}function Kc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;i=i+16|0;g=f;if((a[d]|0)<64){h=Lc(b,c,e)|0;i=f;return h|0}else{Lg(g|0,c|0)|0;j=Dg(c|0)|0;a[g+j|0]=a[d]|0;a[g+(j+1)|0]=0;h=Lc(b,g,e)|0;i=f;return h|0}return 0}function Lc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;e=i;f=Fc(b,c)|0;if((f|0)==0){g=0;i=e;return g|0}c=(a[f]|0)==35?f+1|0:f;if((Dg(c|0)|0)>81){Hg(7704,c|0,81)|0;a[7785|0]=0}else{Lg(7704,c|0)|0}if((Gc(7704)|0)==2){c=$f(7704,68)|0;if((c|0)!=0){a[c]=101}c=$f(7704,100)|0;if((c|0)!=0){a[c]=101}c=$f(7704,69)|0;if((c|0)!=0){a[c]=101}}h[d>>3]=+ug(7704);g=1;i=e;return g|0}function Mc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0;f=i;g=Fc(b,d)|0;if((g|0)==0){j=0;i=f;return j|0}d=$f(g,47)|0;b=$f(g,45)|0;if(d>>>0>g>>>0){a[d]=0;k=~~+ug(g);a[d]=47;l=d+1|0;d=$f(l,47)|0;if((d|0)==0){m=$f(l,45)|0}else{m=d}if(!(m>>>0>g>>>0)){j=0;i=f;return j|0}a[m]=0;d=~~+ug(l);a[m]=47;l=~~+ug(m+1|0);m=(k|0)>31;n=m?k:l;o=m?l:k;if(n>>>0<50){p=n+2e3|0}else{p=(n|0)<100?n+1900|0:n}n=((p|0)%100|0|0)!=0|((p|0)%400|0|0)==0?(p&3|0)==0?29:28:28;c[7796>>2]=n;k=d+ -1|0;d=c[7792+(k<<2)>>2]|0;if((o|0)>(d|0)){q=d}else{q=(o|0)<1?1:o}r=(n|0)==28?365.0:366.0;n=q+ -1|0;if((k|0)>0){q=0;o=n;while(1){d=(c[7792+(q<<2)>>2]|0)+o|0;l=q+1|0;if((l|0)==(k|0)){s=d;break}else{q=l;o=d}}}else{s=n}h[e>>3]=+(p|0)+ +(s|0)/r;j=1;i=f;return j|0}if(!(b>>>0>g>>>0)){j=0;i=f;return j|0}a[b]=0;s=~~+ug(g);a[b]=45;p=b+1|0;b=$f(p,45)|0;do{if(b>>>0>g>>>0){a[b]=0;n=~~+ug(p);a[b]=45;o=b+1|0;q=$f(o,84)|0;if(q>>>0>g>>>0){a[q]=0;k=~~+ug(o);a[q]=84;t=k;u=n;v=q;break}else{t=~~+ug(o);u=n;v=q;break}}else{t=1;u=1;v=0}}while(0);b=(s|0)<32;p=b?t+1900|0:s;q=b?s:t;t=((p|0)%100|0|0)!=0|((p|0)%400|0|0)==0?(p&3|0)==0?29:28:28;c[7796>>2]=t;s=u+ -1|0;u=c[7792+(s<<2)>>2]|0;if((q|0)>(u|0)){w=u}else{w=(q|0)<1?1:q}r=(t|0)==28?365.0:366.0;t=w+ -1|0;if((s|0)>0){w=0;q=t;while(1){u=(c[7792+(w<<2)>>2]|0)+q|0;b=w+1|0;if((b|0)==(s|0)){x=u;break}else{w=b;q=u}}}else{x=t}h[e>>3]=+(p|0)+ +(x|0)/r;if(!(v>>>0>g>>>0)){j=1;i=f;return j|0}x=v+1|0;v=$f(x,58)|0;do{if(v>>>0>g>>>0){a[v]=0;p=~~+ug(x);a[v]=58;t=v+1|0;q=$f(t,58)|0;if(q>>>0>g>>>0){a[q]=0;w=~~+ug(t);a[q]=58;y=p;z=w;A=+ug(q+1|0);break}else{y=p;z=~~+ug(t);A=0.0;break}}else{y=0;z=0;A=0.0}}while(0);h[e>>3]=+h[e>>3]+(A+(+(y|0)*3600.0+ +(z|0)*60.0))/86400.0/r;j=1;i=f;return j|0}function Nc(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+32|0;h=g+8|0;j=g+16|0;k=g;c[h>>2]=d;Na(j|0,7840,h|0)|0;do{if((Cc(b,j)|0)==0){c[h>>2]=d;Na(j|0,7856,h|0)|0;if((Cc(b,j)|0)!=0){l=k;c[l>>2]=627012389;c[l+4>>2]=6566448;break}c[h>>2]=d;Na(j|0,7864,h|0)|0;if((Cc(b,j)|0)!=0){l=k;c[l>>2]=627012389;c[l+4>>2]=6566704;break}if((Cc(b,j)|0)==0){m=0;i=g;return m|0}else{l=k;c[l>>2]=627012389;c[l+4>>2]=6566704;break}}else{a[k+0|0]=a[7848|0]|0;a[k+1|0]=a[7849|0]|0;a[k+2|0]=a[7850|0]|0;a[k+3|0]=a[7851|0]|0;a[k+4|0]=a[7852|0]|0;a[k+5|0]=a[7853|0]|0}}while(0);c[1968]=1;l=1;n=e;e=f;while(1){c[h>>2]=d;c[h+4>>2]=l;Na(j|0,k|0,h|0)|0;o=Fc(b,j)|0;if((o|0)==0){p=l;break}q=Dg(o|0)|0;if((q|0)>=(n|0)){r=13;break}Lg(e|0,o|0)|0;s=l+1|0;if((s|0)<500){l=s;n=n-q|0;e=e+q|0}else{p=s;break}}do{if((r|0)==13){if((n|0)>1){Hg(e|0,o|0,n+ -1|0)|0;a[e+n|0]=0;p=l;break}else{a[f]=a[o]|0;p=l;break}}}while(0);c[1968]=0;m=(p|0)>1|0;i=g;return m|0}function Oc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;g=i;i=i+16|0;h=g;do{if((a[d]|0)<64){j=Fc(b,c)|0;if((j|0)!=0){if((Dg(j|0)|0)<(e|0)){Lg(f|0,j|0)|0;k=1;break}if((e|0)>1){Hg(f|0,j|0,e+ -1|0)|0;k=1;break}else{a[f]=a[j]|0;k=1;break}}else{k=0}}else{Lg(h|0,c|0)|0;j=Dg(c|0)|0;a[h+j|0]=a[d]|0;a[h+(j+1)|0]=0;j=Fc(b,h)|0;if((j|0)!=0){if((Dg(j|0)|0)<(e|0)){Lg(f|0,j|0)|0;k=1;break}if((e|0)>1){Hg(f|0,j|0,e+ -1|0)|0;k=1;break}else{a[f]=a[j]|0;k=1;break}}else{k=0}}}while(0);i=g;return k|0}function Pc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=i;g=Fc(b,c)|0;do{if((g|0)!=0){if((Dg(g|0)|0)<(d|0)){Lg(e|0,g|0)|0;h=1;break}if((d|0)>1){Hg(e|0,g|0,d+ -1|0)|0;h=1;break}else{a[e]=a[g]|0;h=1;break}}else{h=0}}while(0);i=f;return h|0}function Qc(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;d=i;e=Dg(b|0)|0;a:do{if(!((b|0)==0|(c|0)==0)){f=Dg(c|0)|0;if((f|0)!=0){if((e|0)!=0?(g=a[c]|0,h=f+ -1|0,j=a[c+h|0]|0,k=e+1-f|0,l=b+k|0,(k|0)>0):0){k=(f|0)==1;m=(f|0)<3;n=b;while(1){b:do{if((a[n]|0)==g<<24>>24){if(k){o=n;break a}if((a[n+h|0]|0)==j<<24>>24){if(m){o=n;break a}else{p=1}while(1){q=p+1|0;if((a[n+p|0]|0)!=(a[c+p|0]|0)){break b}if((q|0)<(f|0)){p=q}else{o=n;break a}}}}}while(0);q=n+1|0;if(q>>>0>>0){n=q}else{o=0;break}}}else{o=0}}else{o=b}}else{o=0}}while(0);i=d;return o|0}function Rc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;e=i;if((b|0)==0|(c|0)==0){f=0;i=e;return f|0}g=Dg(c|0)|0;if((g|0)==0){f=b;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}do{if((g|0)<3){h=a[c]|0;j=h<<24>>24;if(!((h+ -97<<24>>24&255)<26)){if((h+ -65<<24>>24&255)<26){k=j+32&255}else{k=h}}else{k=j+224&255}if((g|0)>1){j=a[c+1|0]|0;l=j<<24>>24;if((j+ -97<<24>>24&255)<26){m=h;n=j;o=k;p=l+224&255;q=0;break}if((j+ -65<<24>>24&255)<26){m=h;n=j;o=k;p=l+32&255;q=0}else{m=h;n=j;o=k;p=j;q=0}}else{m=h;n=32;o=k;p=32;q=0}}else{h=ig(g,1)|0;j=0;do{l=a[c+j|0]|0;r=l&255;do{if(!((l+ -97<<24>>24&255)<26)){if((l+ -65<<24>>24&255)<26){a[h+j|0]=r+32;break}else{a[h+j|0]=l;break}}else{a[h+j|0]=r+224}}while(0);j=j+1|0}while((j|0)!=(g|0));j=g+ -1|0;m=a[c]|0;n=a[c+j|0]|0;o=a[h]|0;p=a[h+j|0]|0;q=h}}while(0);k=d+1-g|0;d=b+k|0;a:do{if((k|0)>0){j=g+ -1|0;r=(g|0)>1;if((g|0)==2){l=b;while(1){s=a[l]|0;if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24?(s=a[l+j|0]|0,s<<24>>24==n<<24>>24|s<<24>>24==p<<24>>24):0){break}s=l+1|0;if(s>>>0>>0){l=s}else{break a}}if((q|0)==0){f=l;i=e;return f|0}hg(q);f=l;i=e;return f|0}else if((g|0)==1){h=b;while(1){s=a[h]|0;if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24){break}s=h+1|0;if(s>>>0>>0){h=s}else{break a}}if((q|0)==0){f=h;i=e;return f|0}hg(q);f=h;i=e;return f|0}else{l=b;b:while(1){s=a[l]|0;c:do{if(s<<24>>24==m<<24>>24|s<<24>>24==o<<24>>24?(t=a[l+j|0]|0,t<<24>>24==n<<24>>24|t<<24>>24==p<<24>>24):0){if(r){u=1}else{break b}while(1){t=a[l+u|0]|0;if(!(t<<24>>24==(a[c+u|0]|0))?!(t<<24>>24==(a[q+u|0]|0)):0){break c}u=u+1|0;if((u|0)>=(g|0)){break b}}}}while(0);s=l+1|0;if(s>>>0>>0){l=s}else{break a}}if((q|0)==0){f=l;i=e;return f|0}hg(q);f=l;i=e;return f|0}}}while(0);if((q|0)==0){f=0;i=e;return f|0}hg(q);f=0;i=e;return f|0}function Sc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;a:do{if(!((b|0)==0|(c|0)==0)){f=Dg(c|0)|0;if((f|0)!=0){if((d|0)!=0?(g=a[c]|0,h=f+ -1|0,j=a[c+h|0]|0,k=d+1-f|0,l=b+k|0,(k|0)>0):0){k=(f|0)==1;m=b;while(1){b:do{if((a[m]|0)==g<<24>>24){if(k){n=m;break a}if((a[m+h|0]|0)==j<<24>>24){if((f|0)<3){n=m;break a}else{o=1}while(1){p=o+1|0;if((a[m+o|0]|0)!=(a[c+o|0]|0)){break b}if((p|0)<(f|0)){o=p}else{n=m;break a}}}}}while(0);p=m+1|0;if(p>>>0>>0){m=p}else{n=0;break}}}else{n=0}}else{n=b}}else{n=0}}while(0);i=e;return n|0}function Tc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0;g=i;i=i+80|0;j=g;l=g+16|0;if(e<0.0){m=-e;n=-1.0}else{m=e;n=1.0}e=n*+qa(+m,360.0);if(e<0.0){o=e+360.0}else{o=e}e=o/15.0;p=~~e;o=(e- +(p|0))*60.0;q=~~o;e=(o- +(q|0))*60.0;do{if((f|0)<=5){if((f|0)>4){r=e>59.99999;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8008,j|0)|0;break}if((f|0)>3){s=e>59.9999;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,8032,j|0)|0;break}if((f|0)>2){r=e>59.999;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8056,j|0)|0;break}if((f|0)>1){s=e>59.99;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,8080,j|0)|0;break}if((f|0)>0){r=e>59.9;s=(r&1)+q|0;t=(s|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:s;s=j+8|0;h[k>>3]=r?0.0:e;c[s>>2]=c[k>>2];c[s+4>>2]=c[k+4>>2];Na(l|0,8104,j|0)|0;break}else{s=~~(e+.5);r=(s|0)>59;t=(r&1)+q|0;u=(t|0)>59;c[j>>2]=((u&1)+p|0)%24|0;c[j+4>>2]=u?0:t;c[j+8>>2]=r?0:s;Na(l|0,8128,j|0)|0;break}}else{s=e>59.999999;r=(s&1)+q|0;t=(r|0)>59;c[j>>2]=((t&1)+p|0)%24|0;c[j+4>>2]=t?0:r;r=j+8|0;h[k>>3]=s?0.0:e;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];Na(l|0,7984,j|0)|0}}while(0);j=d+ -1|0;if((Dg(l|0)|0)<(j|0)){Lg(b|0,l|0)|0;i=g;return}else{Hg(b|0,l|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Uc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;g=i;i=i+96|0;j=g;l=g+24|0;if(e<0.0){m=-e;n=-1.0}else{m=e;n=1.0}e=n*+qa(+m,360.0);if(!(e<=-180.0)){o=e}else{o=e+360.0}if(o<0.0){p=-o;q=45}else{p=o;q=43}r=~~p;o=(p- +(r|0))*60.0;s=~~o;p=(o- +(s|0))*60.0;do{if((f|0)<=5){if((f|0)>4){t=p>59.99999;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8168,j|0)|0;break}if((f|0)>3){u=p>59.9999;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8192,j|0)|0;break}if((f|0)>2){t=p>59.999;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8216,j|0)|0;break}if((f|0)>1){u=p>59.99;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8240,j|0)|0;break}if((f|0)>0){t=p>59.9;u=(t&1)+s|0;v=(u|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:u;u=j+12|0;h[k>>3]=t?0.0:p;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];Na(l|0,8264,j|0)|0;break}else{u=~~(p+.5);t=(u|0)>59;v=(t&1)+s|0;w=(v|0)>59;c[j>>2]=q&255;c[j+4>>2]=(w&1)+r;c[j+8>>2]=w?0:v;c[j+12>>2]=t?0:u;Na(l|0,8288,j|0)|0;break}}else{u=p>59.999999;t=(u&1)+s|0;v=(t|0)>59;c[j>>2]=q&255;c[j+4>>2]=(v&1)+r;c[j+8>>2]=v?0:t;t=j+12|0;h[k>>3]=u?0.0:p;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];Na(l|0,8144,j|0)|0}}while(0);j=d+ -1|0;if((Dg(l|0)|0)<(j|0)){Lg(b|0,l|0)|0;i=g;return}else{Hg(b|0,l|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Vc(b,d,e,f){b=b|0;d=d|0;e=+e;f=f|0;var g=0,j=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0;g=i;i=i+80|0;j=g;l=g+72|0;m=g+8|0;if(e<0.0){n=-e;o=-1.0}else{n=e;o=1.0}e=o*+qa(+n,360.0);if(!(e<=-180.0)){p=e}else{p=e+360.0}q=f+4|0;if((f|0)>0){c[j>>2]=q;c[j+4>>2]=f;Na(l|0,8312,j|0)|0;h[k>>3]=p;c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];Na(m|0,l|0,j|0)|0}else{c[j>>2]=q;Na(l|0,8328,j|0)|0;c[j>>2]=~~p;Na(m|0,l|0,j|0)|0}j=d+ -1|0;if((Dg(m|0)|0)<(j|0)){Lg(b|0,m|0)|0;i=g;return}else{Hg(b|0,m|0,j|0)|0;a[b+j|0]=0;i=g;return}}function Wc(a,b,d,e){a=a|0;b=+b;d=d|0;e=e|0;var f=0,g=0,j=0,l=0;f=i;i=i+16|0;g=f;j=f+8|0;l=(e|0)>0;if((d|0)>0){if(l){c[g>>2]=d;c[g+4>>2]=e;Na(j|0,8312,g|0)|0;h[k>>3]=b;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];Na(a|0,j|0,g|0)|0;i=f;return}else{c[g>>2]=d;Na(j|0,8336,g|0)|0;c[g>>2]=~~b;Na(a|0,j|0,g|0)|0;i=f;return}}else{if(l){c[g>>2]=e;Na(j|0,7976,g|0)|0;h[k>>3]=b;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];Na(a|0,j|0,g|0)|0;i=f;return}else{c[g>>2]=~~b;Na(a|0,7968,g|0)|0;i=f;return}}}function Xc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=i;i=i+32|0;e=d;f=_c(a,b)|0;if((f|0)==0){g=0;i=d;return g|0}Lg(e|0,f|0)|0;h[c>>3]=+ug(e);g=1;i=d;return g|0}function Yc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;g=i;h=gg(2e3)|0;if((Nc(b,c,2e3,h)|0)==0){hg(h);j=0;i=g;return j|0}c=_c(h,d)|0;do{if((c|0)!=0){if((Dg(c|0)|0)<(e|0)){Lg(f|0,c|0)|0;k=1;break}if((e|0)>1){Hg(f|0,c|0,e+ -1|0)|0;k=1;break}else{a[f]=a[c]|0;k=1;break}}else{k=0}}while(0);hg(h);j=k;i=g;return j|0}function Zc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=i;g=_c(b,c)|0;do{if((g|0)!=0){if((Dg(g|0)|0)<(d|0)){Lg(e|0,g|0)|0;h=1;break}if((d|0)>1){Hg(e|0,g|0,d+ -1|0)|0;h=1;break}else{a[e]=a[g]|0;h=1;break}}else{h=0}}while(0);i=f;return h|0}function _c(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=i;i=i+2032|0;e=d+2024|0;f=d+2018|0;g=d+2016|0;h=d+2e3|0;j=d;a[f]=91;a[f+1|0]=0;a[g]=93;a[g+1|0]=0;Lg(h|0,c|0)|0;c=Qc(h,f)|0;f=(c|0)!=0;if(f){a[c]=0;k=0}else{k=0}while(1){l=k+1|0;if((a[b+k|0]|0)==0){m=6;break}if((l|0)<57600){k=l}else{m=4;break}}if((m|0)==4){n=l;o=Dg(h|0)|0}else if((m|0)==6){l=Dg(h|0)|0;if((k|0)>0){n=k;o=l}else{p=0;i=d;return p|0}}l=b+n|0;n=l;k=b;while(1){q=Sc(k,h,n-k|0)|0;if((q|0)==0){p=0;m=34;break}r=a[q+o|0]|0;s=a[q+ -1|0]|0;if(!(r<<24>>24>32?!(r<<24>>24==61|r<<24>>24==127):0)){if((q|0)==(b|0)){t=b;m=14;break}if(s<<24>>24==9|s<<24>>24==32){t=q;m=14;break}}s=q+1|0;if(s>>>0>>0){k=s}else{p=0;m=34;break}}if((m|0)==14){if((t|0)==0){p=0;i=d;return p|0}k=t+o|0;while(1){o=a[k]|0;if(!(o<<24>>24==61|o<<24>>24==32)){break}k=k+1|0}if((k|0)==0){p=0;i=d;return p|0}Eg(j|0,0,2e3)|0;o=a[k]|0;a:do{if(o<<24>>24==34){t=k;l=0;while(1){b=t+1|0;n=a[b]|0;if(n<<24>>24==34|n<<24>>24==0){break a}if((l|0)>=2e3){break a}a[j+l|0]=n;t=b;l=l+1|0}}else{l=o;t=0;b=k;while(1){if(l<<24>>24==9|l<<24>>24==32){break a}if(!(l<<24>>24>0&(t|0)<2e3)){break a}n=b+1|0;a[j+t|0]=l;l=a[n]|0;t=t+1|0;b=n}}}while(0);if(!f){Lg(8344,j|0)|0;p=8344;i=d;return p|0}f=c+1|0;c=Qc(f,g)|0;if((c|0)==0){p=8344;i=d;return p|0}a[c]=0;c=vg(f)|0;if((c|0)<=0){p=8344;i=d;return p|0}a[e]=32;a[e+1|0]=44;a[e+2|0]=0;f=fg(j,e)|0;if((c|0)>1){j=1;while(1){g=fg(0,e)|0;k=j+1|0;if((k|0)==(c|0)){u=g;break}else{j=k}}}else{u=f}if((u|0)==0){p=8344;i=d;return p|0}Lg(8344,u|0)|0;p=8344;i=d;return p|0}else if((m|0)==34){i=d;return p|0}return 0}function $c(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0;g=i;j=c[d+3260>>2]|0;k=+h[d>>3];l=+h[d+8>>3];m=+h[d+32>>3];n=+h[d+40>>3];o=+h[d+48>>3]*3.141592653589793/180.0;p=+S(+o);q=+T(+o);r=a- +h[d+16>>3];a=b- +h[d+24>>3];do{if((c[d+3300>>2]|0)==0){if(m==0.0|n==0.0){h[e>>3]=0.0;h[f>>3]=0.0;s=2;i=g;return s|0}else{b=r*m;t=a*n;if(!(o!=0.0)){u=b;v=t;break}u=b*p-t*q;v=t*p+b*q;break}}else{u=r*+h[d+56>>3]+a*+h[d+64>>3];v=r*+h[d+72>>3]+a*+h[d+80>>3]}}while(0);w=(c[d+3304>>2]|0)==0;a=w?v:u;r=w?u:v;h[e>>3]=k+r;h[f>>3]=l+a;if((j|0)<1){s=0;i=g;return s|0}v=k*3.141592653589793/180.0;k=l*3.141592653589793/180.0;u=w?k:v;o=w?v:k;v=r*3.141592653589793/180.0;r=a*3.141592653589793/180.0;a=v*v;b=a+r*r;t=+S(+u);x=+T(+u);a:do{switch(j|0){case 11:{y=u+r;z=o+v;break};case 32:case 33:case 31:case 3:{if(b>1.0){s=1;i=g;return s|0}A=t-r*x;if(A==0.0){s=1;i=g;return s|0}else{B=o+ +Y(+v,+A);y=+X(+((r*t+x)*+S(+(B-o))/A));z=B;break a}break};case 6:{if(b>=9.869604401089369){s=1;i=g;return s|0}B=+Q(+b);A=+S(+B);if(B!=0.0){C=+T(+B)/B}else{C=1.0}B=x*A+r*t*C;if(B>1.0|B<-1.0){s=1;i=g;return s|0}D=A-x*B;A=t*v*C;if(D==0.0&A==0.0){s=1;i=g;return s|0}else{y=+W(+B);z=o+ +Y(+A,+D);break a}break};case 22:{D=n*p+m*q;A=(D==0.0?3.141592653589793:D*3.141592653589793)/180.0;D=k+A;B=+T(+k);E=+S(+k);F=+Q(+((E+1.0)*.5));G=+T(+D)/+Q(+((+S(+D)+1.0)*.5))-B/F;D=A/(G==0.0?1.0:G);G=m*p-n*q;A=(G==0.0?3.141592653589793:G*3.141592653589793)/180.0;G=A*.5;H=E*2.0*+T(+G);I=A*+Q(+((E*+S(+G)+1.0)*.5))/(H==0.0?1.0:H);if(!(v==0.0&r==0.0)){H=r+B*D/F;F=H/D;B=4.0-a/(I*I*4.0)-F*F;if(B>4.0|B<2.0){s=1;i=g;return s|0}F=+Q(+B)*.5;B=H*F/D;if(+P(+B)>1.0){s=1;i=g;return s|0}D=+W(+B);B=+S(+D);if(+P(+B)<1.0e-5){s=1;i=g;return s|0}H=v*F/(I*2.0*B);if(+P(+H)>1.0){s=1;i=g;return s|0}else{y=D;z=o+ +W(+H)*2.0;break a}}else{y=u;z=o}break};case 5:{H=(4.0-b)/(b+4.0);if(+P(+H)>1.0){s=1;i=g;return s|0}D=H+1.0;B=x*H+r*t*D*.5;if(+P(+B)>1.0){s=1;i=g;return s|0}H=+W(+B);B=+S(+H);if(+P(+B)<1.0e-5){s=1;i=g;return s|0}I=v*D/(B*2.0);if(+P(+I)>1.0){s=1;i=g;return s|0}D=+W(+I);I=+T(+H);F=+S(+D);G=x*I+1.0+t*B*F;if(+P(+G)<1.0e-5){s=1;i=g;return s|0}if(+P(+((t*I-x*B*F)*2.0/G-r))>1.0e-5){J=3.141592653589795-D}else{J=D}y=H;z=o+J;break};case 20:case 28:{H=u+r;if(+P(+H)>1.5707963267948974){s=1;i=g;return s|0}D=+S(+H);if(+P(+v)>D*6.28318530717959*.5){s=1;i=g;return s|0}if(D>1.0e-5){y=H;z=o+v/D}else{y=H;z=o}break};case 27:{H=t-r*x;if(H==0.0){s=1;i=g;return s|0}D=o+ +Y(+v,+H);G=+S(+(D-o));if(G==0.0){s=1;i=g;return s|0}F=H/G;if(F>1.0|F<-1.0){s=1;i=g;return s|0}G=+V(+F);if(u<0.0){y=-G;z=D}else{y=G;z=D}break};case 12:{D=n*p+m*q;G=D==0.0?1.0:D;D=(l*.5+45.0)*3.141592653589793/180.0;F=+_(+(+U(+D)));H=G*3.141592653589793/180.0/(+_(+(+U(+(G*.5*.01745329252+D))))-F);D=+S(+k);G=o+v/(!(D<=0.0)?D:1.0);if(+P(+(G-o))>6.28318530717959){s=1;i=g;return s|0}if(H!=0.0){K=(r+F*H)/H}else{K=0.0}y=+X(+(+Z(+K)))*2.0+-1.5707963267948974;z=G;break};case 4:{if(b>1.0){s=1;i=g;return s|0}G=+Q(+(1.0-b));H=r*t+x*G;if(H>1.0|H<-1.0){s=1;i=g;return s|0}F=t*G-r*x;if(F==0.0&v==0.0){s=1;i=g;return s|0}else{y=+W(+H);z=o+ +Y(+v,+F);break a}break};case 16:{F=1.0/+U(+u)-r;if(u<0.0){L=-F}else{L=F}y=+W(+((x*x*(1.0-(a+F*F))+1.0)*(1.0/(x*2.0))));z=o- +Y(+v,+L)/x;break};default:{y=0.0;z=0.0}}}while(0);if(z-o>3.141592653589795){M=z+-6.28318530717959}else{M=z}if(M-o<-3.141592653589795){N=M+6.28318530717959}else{N=M}if(N<0.0){O=N+6.28318530717959}else{O=N}h[e>>3]=O*180.0/3.141592653589793;h[f>>3]=y*180.0/3.141592653589793;s=0;i=g;return s|0}function ad(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0,N=0.0,O=0.0,R=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0;g=i;j=+h[d>>3];k=+h[d+8>>3];l=+h[d+16>>3];m=+h[d+24>>3];n=+h[d+32>>3];o=+h[d+40>>3];p=+h[d+48>>3]*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=c[d+3260>>2]|0;t=(s|0)>0;if(t){u=(c[d+3304>>2]|0)==0;v=j*3.141592653589793/180.0;w=k*3.141592653589793/180.0;x=u?w:v;y=u?v:w;w=a-(u?j:k);v=l*n;if(v>180.0|v<-180.0){if(w>360.0){z=a+-360.0}else{z=a}if(w<0.0){A=z+360.0}else{A=z}}else{if(w>180.0){B=a+-360.0}else{B=a}if(w<-180.0){A=B+360.0}else{A=B}}B=A*3.141592653589793/180.0;w=b*3.141592653589793/180.0;z=+S(+w);v=+T(+w);C=B-y;D=A;E=z;F=w;G=x;H=z*+T(+C);I=B;J=y;K=v;L=v*+T(+x)+z*+S(+x)*+S(+C)}else{D=a;E=0.0;F=0.0;G=0.0;H=0.0;I=0.0;J=0.0;K=0.0;L=0.0}a:do{switch(s|0){case 22:{a=(I-J)*.5;if(+P(+a)>1.5707963267948974){M=1;i=g;return M|0}C=o*q+n*r;x=(C==0.0?3.141592653589793:C*3.141592653589793)/180.0;C=k*3.141592653589793/180.0;z=x+C;v=+T(+C);y=+S(+C);C=+Q(+((y+1.0)*.5));B=+T(+z)/+Q(+((+S(+z)+1.0)*.5))-v/C;z=x/(B==0.0?1.0:B);B=n*q-o*r;x=(B==0.0?3.141592653589793:B*3.141592653589793)/180.0;B=x*.5;w=y*2.0*+T(+B);A=+S(+F);N=+Q(+((A*+S(+a)+1.0)*.5));if(+P(+N)<1.0e-5){M=3;i=g;return M|0}else{O=+T(+a)*A*x*+Q(+((y*+S(+B)+1.0)*.5))/(w==0.0?1.0:w)*2.0/N;R=z*+T(+F)/N-v*z/C;break a}break};case 3:case 32:case 33:case 31:{if(!(L<=0.0)){C=+T(+G);z=+S(+G);v=+S(+(I-J));N=K*C+E*z*v;O=H/N;R=(K*z-E*C*v)/N;break a}else{M=1;i=g;return M|0}break};case 16:{N=+U(+G);v=1.0/N;C=N*-2.0;z=N*N;w=N/3.0;N=C*C;B=(J-I)*+T(+G);y=F-G;x=v*(y*(C*.5+y*(z*.5+N*-.125+y*(w*.5+(z*C*-.25+C*N*.0625)+y*(z*.1875*N+(z*z*-.125-C*.25*w)-N*N*.0390625))))+1.0);N=B*B;if((c[d+3300>>2]|0)==0){W=n/+P(+n)}else{w=+h[d+56>>3];W=w/+P(+w)}O=(1.0-N/6.0)*B*x*W;R=v-(1.0-N*.5)*x;break};case 27:{if(G==0.0){M=1;i=g;return M|0}else{O=H;R=(+S(+G)-E*+S(+(I-J)))/+T(+G);break a}break};case 12:{x=o*q+n*r;N=x==0.0?1.0:x;x=(k*.5+45.0)*3.141592653589793/180.0;v=+_(+(+U(+x)));B=N*3.141592653589793/180.0/(+_(+(+U(+(N*.5*.01745329252+x))))-v);x=+S(+(k*3.141592653589793/180.0));N=+U(+(F*.5+.7853981633974487));if(N<1.0e-5){M=2;i=g;return M|0}else{O=(I-J)*(!(x<=0.0)?x:1.0);R=B*+_(+N)-v*B;break a}break};case 6:{B=+T(+G);v=+S(+G);N=+S(+(I-J));x=K*B+E*v*N;w=x<-1.0?-1.0:x;x=+V(+(w>1.0?1.0:w));if(x!=0.0){X=x/+T(+x)}else{X=1.0}O=H*X;R=(K*v-E*B*N)*X;break};case 20:case 28:{if(+P(+F)>1.5707963267948974){M=1;i=g;return M|0}if(+P(+G)>1.5707963267948974){M=1;i=g;return M|0}else{O=E*(I-J);R=F-G;break a}break};case 11:{O=I-J;R=F-G;break};case 4:{if(L<0.0){M=1;i=g;return M|0}else{O=H;R=K*+S(+G)-E*+T(+G)*+S(+(I-J));break a}break};case 5:{if(+P(+F)>1.5707963267948974){M=1;i=g;return M|0}N=+T(+G);B=+S(+G);v=+S(+(I-J));x=K*N+1.0+E*B*v;if(+P(+x)<1.0e-5){M=1;i=g;return M|0}else{w=2.0/x;O=H*w;R=(K*B-E*N*v)*w;break a}break};default:{O=H;R=0.0}}}while(0);if(t){Y=O*180.0/3.141592653589793;Z=R*180.0/3.141592653589793}else{Y=D-j;Z=b-k}t=(c[d+3304>>2]|0)==0;k=t?Z:Y;b=t?Y:Z;if((c[d+3300>>2]|0)==0){if(p!=0.0){$=q*b+r*k;aa=q*k-r*b}else{$=b;aa=k}if(n!=0.0){ba=$/n}else{ba=$}if(o!=0.0){ca=ba;da=aa/o}else{ca=ba;da=aa}}else{ca=b*+h[d+88>>3]+k*+h[d+96>>3];da=b*+h[d+104>>3]+k*+h[d+112>>3]}k=l+ca;h[e>>3]=k;do{if((s|0)==11){ca=+h[d+136>>3];if(k>ca){l=k-360.0/n;if(!(l>0.0)){break}h[e>>3]=l;break}if(k<0.0?(l=k+360.0/n,l<=ca):0){h[e>>3]=l}}}while(0);h[f>>3]=m+da;M=0;i=g;return M|0}function bd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0;g=i;j=c[d+3268>>2]|0;k=c[d+3272>>2]|0;l=a- +h[d+616>>3];a=b- +h[d+624>>3];b=l*l;m=a*a;n=l*b;o=a*m;p=b+m;q=+h[d+256>>3]+l*+h[d+264>>3]+a*+h[d+272>>3]+b*+h[d+280>>3]+m*+h[d+288>>3]+a*l*+h[d+296>>3];if((j|0)>6){r=q+n*+h[d+304>>3]+o*+h[d+312>>3];if((j|0)>8){s=p*+h[d+336>>3]+(r+a*b*+h[d+320>>3]+m*l*+h[d+328>>3])+p*l*+h[d+344>>3]+p*a*+h[d+352>>3]}else{s=r}}else{s=q}q=+h[d+416>>3]+l*+h[d+424>>3]+a*+h[d+432>>3]+b*+h[d+440>>3]+m*+h[d+448>>3]+a*l*+h[d+456>>3];if((k|0)>6){r=q+n*+h[d+464>>3]+o*+h[d+472>>3];if((k|0)>8){t=p*+h[d+496>>3]+(r+a*b*+h[d+480>>3]+l*m*+h[d+488>>3])+p*l*+h[d+504>>3]+p*a*+h[d+512>>3]}else{t=r}}else{t=q}q=t*3.141592653589793/180.0;t=+h[d+696>>3]*3.141592653589793/180.0;r=+U(+t);a=1.0-q*r;p=+Y(+(s*3.141592653589793/180.0/+S(+t)),+a);t=+h[d+688>>3]*3.141592653589793/180.0+p;if(!(t<0.0)){u=t;v=u*180.0;w=v/3.141592653589793;h[e>>3]=w;x=+S(+p);y=q+r;z=a/y;A=x/z;B=+X(+A);C=B*180.0;D=C/3.141592653589793;h[f>>3]=D;i=g;return 0}u=t+6.28318530717959;v=u*180.0;w=v/3.141592653589793;h[e>>3]=w;x=+S(+p);y=q+r;z=a/y;A=x/z;B=+X(+A);C=B*180.0;D=C/3.141592653589793;h[f>>3]=D;i=g;return 0}function cd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0,M=0,N=0,O=0,Q=0,R=0,T=0,V=0,W=0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0,va=0.0,wa=0.0,xa=0,ya=0.0,za=0.0,Aa=0.0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0;g=i;j=c[d+3268>>2]|0;k=c[d+3272>>2]|0;l=+U(+(b*3.141592653589793/180.0));b=+h[d+696>>3]*3.141592653589793/180.0;m=+U(+b);n=a*3.141592653589793/180.0- +h[d+688>>3]*3.141592653589793/180.0;a=+S(+n);o=(1.0-m*a/l)/(m+a/l);l=+S(+b)*+U(+n)*(1.0-m*o)*180.0/3.141592653589793;m=o*180.0/3.141592653589793;o=l*+h[d+88>>3]+m*+h[d+96>>3];n=l*+h[d+104>>3]+m*+h[d+112>>3];b=+h[d+256>>3];a=+h[d+264>>3];p=+h[d+272>>3];q=+h[d+280>>3];r=+h[d+288>>3];s=+h[d+296>>3];t=q*2.0;u=r*2.0;v=d+304|0;w=d+312|0;x=(j|0)>8;y=d+320|0;z=d+328|0;A=d+336|0;B=d+344|0;C=d+352|0;D=+h[d+416>>3];E=+h[d+424>>3];F=+h[d+432>>3];G=+h[d+440>>3];H=+h[d+448>>3];I=+h[d+456>>3];J=G*2.0;K=H*2.0;L=(k|0)>6;M=d+464|0;N=d+472|0;O=(k|0)>8;k=d+480|0;Q=d+488|0;R=d+496|0;T=d+504|0;V=d+512|0;a:do{if((j|0)>6){W=0;X=o;Y=n;while(1){Z=Y*X;_=X*X;$=Y*Y;aa=X*_;ba=Y*$;ca=Y*_;da=$*X;ea=$+_;fa=+h[v>>3];ga=+h[w>>3];ha=b+X*a+Y*p+_*q+$*r+Z*s+aa*fa+ba*ga;ia=a+X*t+Y*s+_*fa*3.0;fa=X*s+(p+Y*u)+$*ga*3.0;if(x){ga=+h[y>>3];ja=+h[z>>3];ka=+h[A>>3];la=+h[B>>3];ma=+h[C>>3];na=ka*2.0;oa=ha+ca*ga+da*ja+ea*ka+ea*X*la+ea*Y*ma;pa=($+_*3.0)*la+($*ja+(ia+Z*ga*2.0)+X*na)+Z*ma*2.0;qa=($*3.0+_)*ma+(fa+_*ga+Z*ja*2.0+Y*na+Z*la*2.0)}else{oa=ha;pa=ia;qa=fa}fa=D+X*E+Y*F+_*G+$*H+Z*I;ia=E+X*J+Y*I;ha=X*I+(F+Y*K);if(L){la=+h[M>>3];na=+h[N>>3];ja=fa+aa*la+ba*na;ba=ia+_*la*3.0;la=ha+$*na*3.0;if(O){na=+h[k>>3];aa=+h[Q>>3];ga=+h[R>>3];ma=+h[T>>3];ka=+h[V>>3];ra=ga*2.0;sa=ja+ca*na+da*aa+ea*ga+ea*X*ma+ea*Y*ka;ta=($+_*3.0)*ma+($*aa+(ba+Z*na*2.0)+X*ra)+Z*ka*2.0;ua=($*3.0+_)*ka+(la+_*na+Z*aa*2.0+Y*ra+Z*ma*2.0)}else{sa=ja;ta=ba;ua=la}}else{sa=fa;ta=ia;ua=ha}ha=oa-l;ia=sa-m;fa=pa*ua-qa*ta;la=(qa*ia-ha*ua)/fa;ba=(ha*ta-pa*ia)/fa;fa=X+la;ia=Y+ba;if(+P(+la)<5.0e-7?+P(+ba)<5.0e-7:0){va=fa;wa=ia;break a}xa=W+1|0;if((xa|0)<50){W=xa;X=fa;Y=ia}else{va=fa;wa=ia;break}}}else{W=0;Y=o;X=n;while(1){ia=X*Y;fa=Y*Y;ba=X*X;la=X*fa;ha=ba*Y;ja=ba+fa;ma=b+Y*a+X*p+fa*q+ba*r+ia*s;Z=a+Y*t+X*s;ra=Y*s+(p+X*u);aa=D+Y*E+X*F+fa*G+ba*H+ia*I;na=E+Y*J+X*I;_=Y*I+(F+X*K);if(L){ka=+h[M>>3];$=+h[N>>3];ea=aa+Y*fa*ka+X*ba*$;ga=na+fa*ka*3.0;ka=_+ba*$*3.0;if(O){$=+h[k>>3];da=+h[Q>>3];ca=+h[R>>3];ya=+h[T>>3];za=+h[V>>3];Aa=ca*2.0;Ba=ea+la*$+ha*da+ja*ca+ja*Y*ya+ja*X*za;Ca=(ba+fa*3.0)*ya+(ba*da+(ga+ia*$*2.0)+Y*Aa)+ia*za*2.0;Da=(ba*3.0+fa)*za+(ka+fa*$+ia*da*2.0+X*Aa+ia*ya*2.0)}else{Ba=ea;Ca=ga;Da=ka}}else{Ba=aa;Ca=na;Da=_}_=ma-l;ma=Ba-m;na=Z*Da-ra*Ca;aa=(ra*ma-_*Da)/na;ra=(_*Ca-Z*ma)/na;na=Y+aa;ma=X+ra;if(+P(+aa)<5.0e-7?+P(+ra)<5.0e-7:0){va=na;wa=ma;break a}xa=W+1|0;if((xa|0)<50){W=xa;Y=na;X=ma}else{va=na;wa=ma;break}}}}while(0);h[e>>3]=va+ +h[d+616>>3];va=wa+ +h[d+624>>3];h[f>>3]=va;wa=+h[e>>3];if(wa<.5){Ea=-1;i=g;return Ea|0}if(wa>+h[d+136>>3]+.5|va<.5){Ea=-1;i=g;return Ea|0}if(va>+h[d+144>>3]+.5){Ea=-1;i=g;return Ea|0}Ea=0;i=g;return Ea|0}function dd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0;d=i;e=gg(2e3)|0;f=gg(2e3)|0;Nc(a,10344,2e3,e)|0;Nc(a,10352,2e3,f)|0;a=gg(2e3)|0;g=gg(2e3)|0;j=b+3176|0;if((+h[j>>3]>360.0?(Xc(e,10360,j)|0)==0:0)?(Xc(f,10360,j)|0)==0:0){h[j>>3]=180.0}j=b+3192|0;if((Xc(e,10376,j)|0)==0?(Xc(f,10376,j)|0)==0:0){h[j>>3]=57.29577951308232}do{if((Zc(e,10384,2e3,a)|0)==0){if((Zc(f,10384,2e3,a)|0)==0){c[b+5960>>2]=0;break}else{c[b+5960>>2]=gd(a)|0;break}}else{c[b+5960>>2]=gd(a)|0}}while(0);do{if((Zc(f,10392,2e3,g)|0)==0){if((Zc(e,10392,2e3,g)|0)==0){c[b+5964>>2]=0;break}else{c[b+5964>>2]=gd(g)|0;break}}else{c[b+5964>>2]=gd(g)|0}}while(0);ac(b);hg(e);hg(f);hg(a);hg(g);if((c[b+5964>>2]|0)==0?(c[b+5960>>2]|0)==0:0){k=1;i=d;return k|0}k=0;i=d;return k|0}function ed(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0;g=i;j=a- +h[d+616>>3];a=b- +h[d+624>>3];if((c[d+3300>>2]|0)==0){b=+h[d+760>>3];if(b==0.0){k=2;l=0.0;m=0.0;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}n=+h[d+768>>3];if(n==0.0){k=2;l=0.0;m=0.0;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}o=j*b;b=a*n;n=+h[d+48>>3];if(n!=0.0){p=n*3.141592653589793/180.0;n=+S(+p);q=+T(+p);r=o*n-b*q;s=b*n+o*q}else{r=o;s=b}}else{r=j*+h[d+56>>3]+a*+h[d+64>>3];s=j*+h[d+72>>3]+a*+h[d+80>>3]}t=(c[d+3304>>2]|0)==0|0;a=(90.0- +h[d+(t<<3)+688>>3])*3.141592653589793/180.0;j=+S(+a);b=+T(+a);o=+h[d+3176>>3]*3.141592653589793/180.0;u=c[d+5960>>2]|0;if((u|0)==0){v=r}else{v=r+ +hd(u,r,s)}u=c[d+5964>>2]|0;if((u|0)==0){w=s}else{w=s+ +hd(u,r,s)}s=+Q(+(v*v+w*w));if(s==0.0){x=0.0}else{x=+Y(+v,+-w)}w=+Y(+(+h[d+3192>>3]),+s);s=+S(+w);v=+T(+w);r=x-o;o=+S(+r);x=+T(+r);q=j*s;n=b*v-q*o;if(+P(+n)<1.0e-5){y=q*(1.0-o)- +S(+(a+w))}else{y=n}n=s*x;if(y!=0.0|n!=-0.0){z=+Y(+-n,+y)}else{z=r+3.141592653589793}x=+h[d+((t^1)<<3)+688>>3];q=x+z*180.0/3.141592653589793;if(!(x>=0.0)){if(q>0.0){A=q+-360.0}else{A=q}}else{if(q<0.0){A=q+360.0}else{A=q}}if(!(A>360.0)){if(A<-360.0){B=A+360.0}else{B=A}}else{B=A+-360.0}if(+qa(+r,3.141592653589793)==0.0){r=(w+a*o)*180.0/3.141592653589793;if(r>90.0){C=180.0-r}else{C=r}if(!(C<-90.0)){k=0;l=C;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}k=0;l=-180.0-C;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}C=j*v+b*s*o;if(!(+P(+C)>.99)){k=0;l=+W(+C)*180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}o=+V(+(+Q(+(n*n+y*y))));if(!(C>=0.0)){k=0;l=o*-180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}else{k=0;l=o*180.0/3.141592653589793;m=B;h[e>>3]=m;h[f>>3]=l;i=g;return k|0}return 0}function fd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0,D=0,E=0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0,U=0.0,X=0.0,Z=0.0,_=0,$=0.0,aa=0.0,ba=0.0;g=i;j=d+3304|0;k=(c[j>>2]|0)==0|0;l=(a- +h[d+((k^1)<<3)+688>>3])*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+l);m=+T(+l);n=+S(+a);o=+T(+a);p=(90.0- +h[d+(k<<3)+688>>3])*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=+h[d+3176>>3];if(s==999.0){t=3.141592653589793}else{t=s*3.141592653589793/180.0}s=n*q;u=o*r-b*s;if(+P(+u)<1.0e-5){v=(1.0-b)*s- +S(+(a+p))}else{v=u}u=m*n;if(v!=0.0|u!=-0.0){w=+Y(+-u,+v)}else{w=l+-3.141592653589793}m=t+w;if(!(m>3.141592653589793)){if(m<-3.141592653589793){x=m+6.283185307179586}else{x=m}}else{x=m+-6.283185307179586}do{if(+qa(+l,3.141592653589793)==0.0){m=a+b*p;if(m>1.5707963267948966){y=3.141592653589793-m}else{y=m}if(y<-1.5707963267948966){z=-3.141592653589793-y}else{z=y}}else{m=o*q+b*n*r;if(!(+P(+m)>.99)){z=+W(+m);break}w=+V(+(+Q(+(u*u+v*v))));if(!(m>=0.0)){z=-w}else{z=w}}}while(0);v=+T(+z);do{if(v==0.0){A=0.0;B=0.0}else{u=+h[d+3192>>3]*+S(+z)/v;k=d+5960|0;C=c[k>>2]|0;D=d+5964|0;if((C|0)==0?(c[D>>2]|0)==0:0){E=(c[j>>2]|0)==0;r=u*+T(+x);n=-(u*+S(+x));A=E?r:n;B=E?n:r;break}r=u*+T(+x);n=u*+S(+x);E=C;C=1;u=r;b=-n;while(1){if((E|0)==0){F=u;G=1.0;H=0.0}else{q=u+ +hd(E,u,b);o=+id(c[k>>2]|0,u,b,1,0)+1.0;F=q;G=o;H=+id(c[k>>2]|0,u,b,0,1)}o=F-r;I=c[D>>2]|0;if((I|0)==0){J=b;K=0.0;L=1.0}else{q=b+ +hd(I,u,b);y=+id(c[D>>2]|0,u,b,1,0);J=q;K=y;L=+id(c[D>>2]|0,u,b,0,1)+1.0}y=n+J;q=G*L-H*K;if(q==0.0){M=u;N=b;break}p=(H*y-o*L)/q;a=(o*K-G*y)/q;q=u+p;l=b+a;I=+P(+p)>+P(+a);w=I?p:a;a=+P(+w);I=+P(+o)>+P(+y);p=I?o:y;I=a>+P(+p);if(!(!(+P(+(I?w:p))<2.8e-8)&(C|0)<500)){M=q;N=l;break}E=c[k>>2]|0;C=C+1|0;u=q;b=l}C=(c[j>>2]|0)==0;A=C?M:N;B=C?N:M}}while(0);if((c[d+3300>>2]|0)!=0){h[e>>3]=A*+h[d+88>>3]+B*+h[d+96>>3];h[f>>3]=A*+h[d+104>>3]+B*+h[d+112>>3];O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}M=+h[d+48>>3];if(M!=0.0){N=M*3.141592653589793/180.0;M=+S(+N);G=+T(+N);h[e>>3]=A*M+B*G;ba=B*M-A*G}else{h[e>>3]=A;ba=B}h[f>>3]=ba;ba=+h[d+32>>3];if(ba!=0.0){h[e>>3]=+h[e>>3]/ba}ba=+h[d+40>>3];if(!(ba!=0.0)){O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}h[f>>3]=+h[f>>3]/ba;O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}function gd(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=i;i=i+16|0;e=d;if((a[b+1|0]|0)==0){f=0;i=d;return f|0}g=gg(160)|0;c[e>>2]=b;j=b;k=b;b=g;g=0;l=20;a:while(1){if((a[k]|0)==0){break}m=+wg(j,e);n=c[e>>2]|0;o=a[n]|0;if(o<<24>>24==46){p=n+1|0;c[e>>2]=p;q=a[p]|0;r=p}else{q=o;r=n}if(q<<24>>24==0){break}n=g+1|0;if((n|0)<(l|0)){s=r;t=b;u=l}else{o=l+20|0;p=jg(b,o<<3)|0;s=c[e>>2]|0;t=p;u=o}h[t+(g<<3)>>3]=m;o=s;while(1){if((a[o]|0)==32){o=o+1|0}else{j=o;k=s;b=t;g=n;l=u;continue a}}}u=jd(b)|0;hg(b);f=(g|0)==0?0:u;i=d;return f|0}function hd(a,b,d){a=a|0;b=+b;d=+d;var e=0,f=0,g=0,j=0.0,k=0.0,l=0,m=0.0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0,F=0,G=0,H=0,I=0,J=0.0,K=0,L=0.0,M=0,N=0.0,O=0;e=i;f=c[a+32>>2]|0;if((f|0)==1){g=c[a+36>>2]|0;j=+h[a+8>>3];k=+h[a>>3];l=c[a+56>>2]|0;h[l>>3]=1.0;if(((g|0)!=1?(m=(j+b)*k,h[l+8>>3]=m,(g|0)>2):0)?(k=m*2.0,j=k*m+-1.0,h[l+16>>3]=j,(g|0)!=3):0){m=j;n=3;p=2;while(1){m=k*m- +h[l+(p+ -1<<3)>>3];h[l+(n<<3)>>3]=m;q=n+1|0;if((q|0)==(g|0)){break}else{r=n;n=q;p=r}}}p=c[a+40>>2]|0;m=+h[a+24>>3];k=+h[a+16>>3];n=c[a+60>>2]|0;h[n>>3]=1.0;if((p|0)!=1){j=(m+d)*k;h[n+8>>3]=j;if((p|0)>2){k=j*2.0;m=k*j+-1.0;h[n+16>>3]=m;if((p|0)==3){s=l;t=n;u=3;v=g;w=25}else{j=m;r=3;q=2;while(1){m=k*j- +h[n+(q+ -1<<3)>>3];h[n+(r<<3)>>3]=m;x=r+1|0;if((x|0)==(p|0)){y=g;z=p;A=l;B=n;w=26;break}else{C=r;j=m;r=x;q=C}}}}else{y=g;z=p;A=l;B=n;w=26}}else{s=l;t=n;u=1;v=g;w=25}}else if((f|0)==3){g=c[a+36>>2]|0;n=c[a+56>>2]|0;h[n>>3]=1.0;if((g|0)!=1?(h[n+8>>3]=b,(g|0)>2):0){j=b;l=2;do{j=j*b;h[n+(l<<3)>>3]=j;l=l+1|0}while((l|0)!=(g|0))}l=c[a+40>>2]|0;p=c[a+60>>2]|0;h[p>>3]=1.0;if((l|0)!=1){h[p+8>>3]=d;if((l|0)>2){j=d;q=2;while(1){k=j*d;h[p+(q<<3)>>3]=k;r=q+1|0;if((r|0)==(l|0)){y=g;z=l;A=n;B=p;w=26;break}else{j=k;q=r}}}else{y=g;z=l;A=n;B=p;w=26}}else{s=n;t=p;u=1;v=g;w=25}}else if((f|0)==2){f=c[a+36>>2]|0;j=+h[a+8>>3];k=+h[a>>3];g=c[a+56>>2]|0;h[g>>3]=1.0;if(((f|0)!=1?(m=(j+b)*k,h[g+8>>3]=m,(f|0)>2):0)?(k=(m*m*3.0+-1.0)*.5,h[g+16>>3]=k,(f|0)!=3):0){p=3;b=k;n=2;while(1){k=+(p|0);b=(b*m*(k*2.0+-1.0)- +h[g+(n+ -1<<3)>>3]*(k+-1.0))/k;h[g+(p<<3)>>3]=b;l=p+1|0;if((l|0)==(f|0)){break}else{q=p;p=l;n=q}}}n=c[a+40>>2]|0;b=+h[a+24>>3];m=+h[a+16>>3];p=c[a+60>>2]|0;h[p>>3]=1.0;if((n|0)!=1){k=(b+d)*m;h[p+8>>3]=k;if((n|0)>2){m=(k*k*3.0+-1.0)*.5;h[p+16>>3]=m;if((n|0)==3){s=g;t=p;u=3;v=f;w=25}else{q=3;d=m;l=2;while(1){m=+(q|0);b=(d*k*(m*2.0+-1.0)- +h[p+(l+ -1<<3)>>3]*(m+-1.0))/m;h[p+(q<<3)>>3]=b;r=q+1|0;if((r|0)==(n|0)){y=f;z=n;A=g;B=p;w=26;break}else{C=q;q=r;d=b;l=C}}}}else{y=f;z=n;A=g;B=p;w=26}}else{s=g;t=p;u=1;v=f;w=25}}else{ab(10400,33,1,c[o>>2]|0)|0;D=0.0;i=e;return+D}if((w|0)==25){E=(v|0)>(u|0)?v:u;F=t;G=u;H=s;I=v}else if((w|0)==26){if((z|0)>0){E=(y|0)>(z|0)?y:z;F=B;G=z;H=A;I=y}else{D=0.0;i=e;return+D}}y=c[a+44>>2]|0;A=a+52|0;if((y|0)==2){a=0;z=0;d=0.0;B=I;while(1){if((B|0)>0){w=c[A>>2]|0;k=0.0;v=z;s=0;while(1){k=k+ +h[w+(v<<3)>>3]*+h[H+(s<<3)>>3];s=s+1|0;if((s|0)==(B|0)){break}else{v=v+1|0}}J=k;K=B+z|0}else{J=0.0;K=z}b=d+J*+h[F+(a<<3)>>3];v=(((a+1+I|0)>(E|0))<<31>>31)+B|0;s=a+1|0;if((s|0)<(G|0)){a=s;z=K;d=b;B=v}else{D=b;break}}i=e;return+D}else if((y|0)==0){y=0;B=0;d=0.0;K=I;while(1){if((K|0)>0){z=c[A>>2]|0;J=0.0;a=B;E=0;while(1){J=J+ +h[z+(a<<3)>>3]*+h[H+(E<<3)>>3];E=E+1|0;if((E|0)==(K|0)){break}else{a=a+1|0}}L=J;M=K+B|0}else{L=0.0;M=B}k=d+L*+h[F+(y<<3)>>3];a=y+1|0;if((a|0)<(G|0)){y=a;B=M;d=k;K=1}else{D=k;break}}i=e;return+D}else{K=0;M=0;d=0.0;while(1){if((I|0)>0){B=c[A>>2]|0;L=0.0;y=M;a=0;while(1){L=L+ +h[B+(y<<3)>>3]*+h[H+(a<<3)>>3];a=a+1|0;if((a|0)==(I|0)){break}else{y=y+1|0}}N=L;O=I+M|0}else{N=0.0;O=M}J=d+N*+h[F+(K<<3)>>3];y=K+1|0;if((y|0)<(G|0)){K=y;M=O;d=J}else{D=J;break}}i=e;return+D}return 0.0}function id(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0.0,O=0,P=0,Q=0,S=0,T=0.0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0.0,$=0.0,ba=0.0,ca=0.0,da=0,ea=0.0,fa=0.0;g=i;i=i+16|0;j=g;if((a|0)==0){k=0.0;i=g;return+k}l=f|e;if((l|0)<0){ab(10440,46,1,c[o>>2]|0)|0;k=0.0;i=g;return+k}if((l|0)==0){k=+hd(a,b,d);i=g;return+k}l=gg(64)|0;m=a+36|0;n=c[m>>2]|0;p=n+ -1|0;q=(p|0)>(e|0)?e:p;p=a+40|0;e=c[p>>2]|0;r=e+ -1|0;s=(r|0)>(f|0)?f:r;r=c[a+32>>2]|0;t=l+32|0;c[t>>2]=r;if(!((r+ -1|0)>>>0<3)){u=c[o>>2]|0;c[j>>2]=r;za(u|0,10488,j|0)|0;k=0.0;i=g;return+k}j=c[a+44>>2]|0;u=l+44|0;c[u>>2]=j;do{if((j|0)==2){r=((n|0)>(e|0)?n:e)-s-q|0;v=n-q|0;w=(r|0)<(v|0)?r:v;v=(w|0)<1?1:w;w=l+36|0;c[w>>2]=v;x=e-s|0;y=(r|0)<(x|0)?r:x;x=(y|0)<1?1:y;y=l+40|0;c[y>>2]=x;r=(v|0)<(x|0)?v:x;z=(aa(x,v)|0)-((aa(r+ -1|0,r)|0)/2|0)|0;r=l+48|0;c[r>>2]=z;A=r;B=w;C=y;D=z;E=v;F=x}else if((j|0)==0){x=(q|0)>0;v=(s|0)>0;if(x&v){z=l+36|0;c[z>>2]=1;y=l+40|0;c[y>>2]=1;w=l+48|0;c[w>>2]=1;A=w;B=z;C=y;D=1;E=1;F=1;break}if(x){x=n-q|0;y=(x|0)<1?1:x;x=l+36|0;c[x>>2]=y;z=l+40|0;c[z>>2]=1;w=l+48|0;c[w>>2]=y;A=w;B=x;C=z;D=y;E=y;F=1;break}if(v){v=l+36|0;c[v>>2]=1;y=e-s|0;z=(y|0)<1?1:y;y=l+40|0;c[y>>2]=z;x=l+48|0;c[x>>2]=z;A=x;B=v;C=y;D=z;E=1;F=z;break}else{A=l+48|0;B=l+36|0;C=l+40|0;D=0;E=0;F=0;break}}else{z=n-q|0;y=(z|0)<1?1:z;z=l+36|0;c[z>>2]=y;v=e-s|0;x=(v|0)<1?1:v;v=l+40|0;c[v>>2]=x;w=aa(x,y)|0;r=l+48|0;c[r>>2]=w;A=r;B=z;C=v;D=w;E=y;F=x}}while(0);h[l>>3]=+h[a>>3];h[l+8>>3]=+h[a+8>>3];n=l+16|0;h[n>>3]=+h[a+16>>3];h[l+24>>3]=+h[a+24>>3];j=l+52|0;c[j>>2]=gg(D<<3)|0;D=l+56|0;c[D>>2]=gg(E<<3)|0;E=l+60|0;c[E>>2]=gg(F<<3)|0;F=a+48|0;x=c[F>>2]|0;y=x<<3;w=c[2632]|0;if((y|0)>(w|0)){if((w|0)>0){G=jg(c[2634]|0,y)|0}else{G=gg(y)|0}c[2634]=G;c[2632]=y;H=G;I=c[F>>2]|0}else{H=c[2634]|0;I=x}if((I|0)>0){x=c[a+52>>2]|0;a=0;do{h[H+(a<<3)>>3]=+h[x+(a<<3)>>3];a=a+1|0}while((a|0)!=(I|0))}a=c[u>>2]|0;a:do{if((a|0)==1){u=c[p>>2]|0;x=u+ -1|0;if((u|0)>(s|0)){u=c[m>>2]|0;F=c[B>>2]|0;G=aa(x,u)|0;y=aa((c[C>>2]|0)+ -1|0,F)|0;w=1-s|0;v=q+1|0;z=(u|0)<(v|0);r=(F|0)>0;J=0-u|0;K=1-q|0;L=x;x=H+(G<<3)|0;G=(c[j>>2]|0)+(y<<3)|0;while(1){y=w+L|0;if((L|0)>=(y|0)){M=L;while(1){if(r){N=+(M|0);O=0;do{P=x+(O+q<<3)|0;h[P>>3]=N*+h[P>>3];O=O+1|0}while((O|0)<(F|0))}if((M|0)>(y|0)){M=M+ -1|0}else{break}}}if(!z){M=u;while(1){y=K+M|0;O=M+ -1|0;if((M|0)>=(y|0)){P=x+(O<<3)|0;N=+h[P>>3];Q=M;while(1){S=Q+ -1|0;T=+(S|0)*N;if((Q|0)>(y|0)){N=T;Q=S}else{break}}h[P>>3]=T}if((M|0)>(v|0)){M=O}else{break}}}if(r){M=0;do{h[G+(M<<3)>>3]=+h[x+(M+q<<3)>>3];M=M+1|0}while((M|0)<(F|0))}if((L|0)>(s|0)){L=L+ -1|0;x=x+(J<<3)|0;G=G+(0-F<<3)|0}else{break}}}}else if((a|0)==2){F=c[m>>2]|0;G=c[p>>2]|0;J=((F|0)>(G|0)?F:G)+1|0;x=c[B>>2]|0;L=c[C>>2]|0;r=s+1|0;if((G|0)>=(r|0)){v=r+((x|0)>(L|0)?x:L)|0;L=1-s|0;K=q+1|0;u=1-q|0;z=G;G=H+(I<<3)|0;w=(c[j>>2]|0)+(c[A>>2]<<3)|0;while(1){M=J-z|0;Q=(M|0)<(F|0)?M:F;M=(Q|0)<0?0:Q;Q=v-z|0;y=(Q|0)<(x|0)?Q:x;Q=(y|0)<0?0:y;y=G+(0-M<<3)|0;S=w+(0-Q<<3)|0;U=L+z|0;if((z|0)>(U|0)){V=(Q|0)>0;W=q-M|0;X=z;do{X=X+ -1|0;if(V){N=+(X|0);Y=0;do{Z=G+(W+Y<<3)|0;h[Z>>3]=N*+h[Z>>3];Y=Y+1|0}while((Y|0)<(Q|0))}}while((X|0)>(U|0))}if((M|0)>=(K|0)){U=M;while(1){X=u+U|0;W=U+ -1|0;if((U|0)>=(X|0)){V=G+(W-M<<3)|0;N=+h[V>>3];Y=U;while(1){O=Y+ -1|0;_=+(O|0)*N;if((Y|0)>(X|0)){N=_;Y=O}else{break}}h[V>>3]=_}if((U|0)>(K|0)){U=W}else{break}}}if((Q|0)>0){U=q-M|0;Y=0;do{h[w+(Y-Q<<3)>>3]=+h[G+(U+Y<<3)>>3];Y=Y+1|0}while((Y|0)<(Q|0))}if((z|0)>(r|0)){z=z+ -1|0;G=y;w=S}else{break}}}}else{w=(q|0)>0;G=(s|0)>0;if(w&G){h[c[j>>2]>>3]=0.0;break}if(w){w=c[m>>2]|0;z=q+1|0;if((w|0)<(z|0)){break}r=1-q|0;K=w;w=(c[j>>2]|0)+((c[A>>2]|0)+ -1<<3)|0;while(1){u=r+K|0;L=K+ -1|0;x=H+(L<<3)|0;N=+h[x>>3];if((K|0)<(u|0)){$=N}else{ba=N;v=K;while(1){F=v+ -1|0;ca=ba*+(F|0);if((v|0)>(u|0)){ba=ca;v=F}else{break}}h[x>>3]=ca;$=ca}h[w>>3]=$;if((K|0)>(z|0)){K=L;w=w+ -8|0}else{break a}}}if(G){w=H+(I+ -1<<3)|0;K=c[j>>2]|0;z=c[p>>2]|0;r=s+1|0;if((z|0)<(r|0)){da=w}else{v=1-s|0;u=0-e|0;S=~f;y=((u|0)>(S|0)?u:S)+ -1|0;S=~z;u=I+ -3-(z+((y|0)>(S|0)?y:S))|0;S=z;z=w;while(1){w=v+S|0;if((S|0)>=(w|0)){ba=+h[z>>3];y=S;while(1){F=y+ -1|0;ea=+(F|0)*ba;if((y|0)>(w|0)){ba=ea;y=F}else{break}}h[z>>3]=ea}if((S|0)>(r|0)){S=S+ -1|0;z=z+ -8|0}else{break}}da=H+(u<<3)|0}z=c[A>>2]|0;if((z|0)>0){S=0;while(1){r=S+1|0;h[K+(S<<3)>>3]=+h[da+(r<<3)>>3];if((r|0)<(z|0)){S=r}else{break}}}}}}while(0);ea=+hd(l,b,d);if((c[t>>2]|0)==3){if((l|0)==0){k=ea;i=g;return+k}else{fa=ea}}else{d=+R(+(+h[l>>3]),+(+(q|0)));fa=ea*d*+R(+(+h[n>>3]),+(+(s|0)))}s=c[D>>2]|0;if((s|0)!=0){hg(s)}s=c[E>>2]|0;if((s|0)!=0){hg(s)}s=c[j>>2]|0;if((s|0)!=0){hg(s)}hg(l);k=fa;i=g;return+k}function jd(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,l=0.0,m=0.0,n=0,p=0.0,q=0.0,r=0,s=0,t=0;b=i;i=i+16|0;d=b;e=~~(+h[a+8>>3]+.5);if((e|0)<1){f=c[o>>2]|0;c[d>>2]=e;za(f|0,10544,d|0)|0;g=0;i=b;return g|0}f=~~(+h[a+16>>3]+.5);if((f|0)<1){j=c[o>>2]|0;c[d>>2]=f;za(j|0,10584,d|0)|0;g=0;i=b;return g|0}l=+h[a+32>>3];m=+h[a+40>>3];if(m<=l){j=c[o>>2]|0;h[k>>3]=l;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];n=d+8|0;h[k>>3]=m;c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];za(j|0,10624,d|0)|0;g=0;i=b;return g|0}p=+h[a+48>>3];q=+h[a+56>>3];if(q<=p){j=c[o>>2]|0;h[k>>3]=p;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];n=d+8|0;h[k>>3]=q;c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];za(j|0,10664,d|0)|0;g=0;i=b;return g|0}j=~~(+h[a>>3]+.5);if(!((j+ -1|0)>>>0<3)){n=c[o>>2]|0;c[d>>2]=j;za(n|0,10704,d|0)|0;g=0;i=b;return g|0}d=gg(64)|0;c[d+36>>2]=e;h[d>>3]=2.0/(m-l);h[d+8>>3]=(l+m)*-.5;c[d+40>>2]=f;h[d+16>>3]=2.0/(q-p);h[d+24>>3]=(p+q)*-.5;n=~~+h[a+24>>3];c[d+44>>2]=n;if((n|0)==1){r=aa(f,e)|0;c[d+48>>2]=r;s=r}else if((n|0)==2){r=(e|0)<(f|0)?e:f;t=(aa(f,e)|0)-((aa(r+ -1|0,r)|0)/2|0)|0;c[d+48>>2]=t;s=t}else if((n|0)==0){n=e+ -1+f|0;c[d+48>>2]=n;s=n}else{s=0}c[d+32>>2]=j;j=gg(s<<3)|0;c[d+52>>2]=j;if((s|0)>0){n=0;do{h[j+(n<<3)>>3]=+h[a+(n+8<<3)>>3];n=n+1|0}while((n|0)<(s|0))}c[d+56>>2]=gg(e<<3)|0;c[d+60>>2]=gg(f<<3)|0;g=d;i=b;return g|0}function kd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0;d=i;i=i+16|0;e=d;f=d+8|0;g=gg(2e3)|0;j=gg(2e3)|0;if((Nc(a,10744,2e3,g)|0)==0){k=gg((Dg(a|0)|0)+200|0)|0;Kg(k|0,10752,161)|0;Fg(k|0,a|0)|0;Nc(k,10744,2e3,g)|0;Nc(k,10920,2e3,j)|0;hg(k)}Nc(a,10920,2e3,j)|0;a=gg(2e3)|0;k=gg(2e3)|0;l=b+3176|0;if((+h[l>>3]>360.0?(Xc(g,10928,l)|0)==0:0)?(Xc(j,10928,l)|0)==0:0){h[l>>3]=180.0}l=b+3192|0;if((Xc(g,10944,l)|0)==0?(Xc(j,10944,l)|0)==0:0){h[l>>3]=57.29577951308232}l=0;do{c[e>>2]=l;Na(f|0,10952,e|0)|0;m=b+(l<<3)+4096|0;if((Xc(g,f,m)|0)==0){h[m>>3]=0.0}l=l+1|0}while((l|0)!=10);do{if((Zc(g,10960,2e3,a)|0)==0){if((Zc(j,10960,2e3,a)|0)==0){c[b+5960>>2]=0;break}else{c[b+5960>>2]=gd(a)|0;break}}else{c[b+5960>>2]=gd(a)|0}}while(0);do{if((Zc(j,10968,2e3,k)|0)==0){if((Zc(g,10968,2e3,k)|0)==0){c[b+5964>>2]=0;n=9;break}else{c[b+5964>>2]=gd(k)|0;n=9;break}}else{c[b+5964>>2]=gd(k)|0;n=9}}while(0);while(1){o=n+ -1|0;if(!(+h[b+(n<<3)+4096>>3]==0.0)){p=27;break}if((n|0)>0){n=o}else{p=25;break}}if((p|0)==25){c[b+3276>>2]=o}else if((p|0)==27?(c[b+3276>>2]=n,(n|0)>2):0){q=+h[b+4104>>3];p=1;r=0.0;while(1){s=+(p|0)*3.141592653589793/180.0;t=0.0;o=n;do{t=s*t+ +(o|0)*+h[b+(o<<3)+4096>>3];o=o+ -1|0}while((o|0)>0);o=p+1|0;if(t<=0.0){u=q;v=r;break}if((o|0)<181){q=t;p=o;r=s}else{u=t;v=s;break}}a:do{if(!(t<=0.0)){w=3.141592653589793}else{r=u;q=t;p=1;x=v;y=s;while(1){z=x-r*(y-x)/(q-r);A=0.0;o=n;do{A=z*A+ +(o|0)*+h[b+(o<<3)+4096>>3];o=o+ -1|0}while((o|0)>0);if(+P(+A)<1.0e-13){w=z;break a}o=A<0.0;l=p+1|0;if((l|0)<11){r=o?r:A;q=o?A:q;p=l;x=o?x:z;y=o?z:y}else{w=z;break}}}}while(0);if((n|0)>-1){p=n;s=0.0;while(1){v=w*s+ +h[b+(p<<3)+4096>>3];if((p|0)>0){p=p+ -1|0;s=v}else{B=v;break}}}else{B=0.0}h[b+3240>>3]=w;h[b+3248>>3]=B}ac(b);hg(g);hg(j);hg(a);hg(k);if((c[b+5964>>2]|0)==0?(c[b+5960>>2]|0)==0:0){C=1;i=d;return C|0}C=0;i=d;return C|0} + + + +function ld(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,U=0.0,X=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0;g=i;j=a- +h[d+616>>3];a=b- +h[d+624>>3];do{if((c[d+3300>>2]|0)==0){b=+h[d+760>>3];if(!(b==0.0)?(k=+h[d+768>>3],!(k==0.0)):0){l=j*b;b=a*k;k=+h[d+48>>3];if(!(k!=0.0)){m=l;n=b;break}o=k*3.141592653589793/180.0;k=+S(+o);p=+T(+o);m=l*k-b*p;n=b*k+l*p;break}h[e>>3]=0.0;h[f>>3]=0.0;q=2;i=g;return q|0}else{m=j*+h[d+56>>3]+a*+h[d+64>>3];n=j*+h[d+72>>3]+a*+h[d+80>>3]}}while(0);r=(c[d+3304>>2]|0)==0|0;s=r^1;a=(90.0- +h[d+(r<<3)+688>>3])*3.141592653589793/180.0;j=+S(+a);p=+T(+a);l=+h[d+3176>>3]*3.141592653589793/180.0;r=c[d+3276>>2]|0;t=c[d+5960>>2]|0;if((t|0)==0){u=m}else{u=m+ +hd(t,m,n)}t=c[d+5964>>2]|0;if((t|0)==0){v=n}else{v=n+ +hd(t,m,n)}n=+Q(+(u*u+v*v));m=n/+h[d+3192>>3];if((r|0)<1){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}a:do{if((r|0)==2){n=+h[d+4112>>3];k=+h[d+4104>>3];b=k*k-n*4.0*(+h[d+4096>>3]-m);if(b<0.0){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}o=+Q(+b);b=n*2.0;n=(o-k)/b;w=(-k-o)/b;b=nw?n:w}else{x=b}if(x<0.0){if(!(x<-1.0e-13)){y=0.0;break}h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if(x>3.141592653589793){if(x>3.141592653589893){h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}else{y=3.141592653589793}}else{y=x}}else if((r|0)==1){y=(m- +h[d+4096>>3])/+h[d+4104>>3]}else{b=+h[d+4096>>3];w=+h[d+3240>>3];n=+h[d+3248>>3];if(m>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if(m>n){if(!(m>n+1.0e-13)){y=w;break}h[e>>3]=0.0;h[f>>3]=0.0;q=1;i=g;return q|0}if((r|0)>-1){z=0;A=b;B=n;C=0.0;D=w}else{o=0.0-m;t=0;k=b;b=n;n=0.0;E=w;while(1){w=(b-m)/(b-k);if(!(w<.1)){if(w>.9){F=.9}else{F=w}}else{F=.1}w=E-(E-n)*F;if(m>0.0){if(m<1.0e-13){y=w;break a}else{G=0.0;H=b;I=w;J=E}}else{if(o<1.0e-13){y=w;break a}else{G=k;H=0.0;I=n;J=w}}K=t+1|0;if(!(+P(+(J-I))<1.0e-13)&(K|0)<100){t=K;k=G;b=H;n=I;E=J}else{y=w;break a}}}while(1){E=(B-m)/(B-A);if(!(E<.1)){if(E>.9){L=.9}else{L=E}}else{L=.1}E=D-(D-C)*L;t=r;n=0.0;while(1){n=E*n+ +h[d+(t<<3)+4096>>3];if((t|0)<=0){break}else{t=t+ -1|0}}if(n>3];R=U+Z*180.0/3.141592653589793;if(!(U>=0.0)){if(R>0.0){_=R+-360.0}else{_=R}}else{if(R<0.0){_=R+360.0}else{_=R}}if(!(_>360.0)){if(_<-360.0){$=_+360.0}else{$=_}}else{$=_+-360.0}do{if(+qa(+m,3.141592653589793)==0.0){_=(v+a*l)*180.0/3.141592653589793;if(_>90.0){aa=180.0-_}else{aa=_}if(aa<-90.0){ba=-180.0-aa}else{ba=aa}}else{_=j*u+p*y*l;if(!(+P(+_)>.99)){ba=+W(+_)*180.0/3.141592653589793;break}R=+V(+(+Q(+(D*D+X*X))));if(!(_>=0.0)){ba=R*-180.0/3.141592653589793;break}else{ba=R*180.0/3.141592653589793;break}}}while(0);h[e>>3]=$;h[f>>3]=ba;q=0;i=g;return q|0}function md(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0,U=0.0,X=0.0,Z=0.0,_=0,$=0.0,aa=0.0,ba=0.0;g=i;j=d+3304|0;k=(c[j>>2]|0)==0|0;l=(a- +h[d+((k^1)<<3)+688>>3])*3.141592653589793/180.0;a=b*3.141592653589793/180.0;b=+S(+l);m=+T(+l);n=+S(+a);o=+T(+a);p=(90.0- +h[d+(k<<3)+688>>3])*3.141592653589793/180.0;q=+S(+p);r=+T(+p);s=+h[d+3176>>3];if(s==999.0){t=3.141592653589793}else{t=s*3.141592653589793/180.0}s=n*q;u=o*r-b*s;if(+P(+u)<1.0e-5){v=(1.0-b)*s- +S(+(a+p))}else{v=u}u=m*n;if(v!=0.0|u!=-0.0){w=+Y(+-u,+v)}else{w=l+-3.141592653589793}m=t+w;if(!(m>3.141592653589793)){if(m<-3.141592653589793){x=m+6.283185307179586}else{x=m}}else{x=m+-6.283185307179586}do{if(+qa(+l,3.141592653589793)==0.0){m=a+b*p;if(m>1.5707963267948966){y=3.141592653589793-m}else{y=m}if(y<-1.5707963267948966){z=-3.141592653589793-y}else{z=y}}else{m=o*q+b*n*r;if(!(+P(+m)>.99)){z=+W(+m);break}w=+V(+(+Q(+(u*u+v*v))));if(!(m>=0.0)){z=-w}else{z=w}}}while(0);v=1.5707963267948966-z;z=(v*(v*(v*(v*(v*(v*(v*(v*(v*(v*0.0+ +h[d+4168>>3])+ +h[d+4160>>3])+ +h[d+4152>>3])+ +h[d+4144>>3])+ +h[d+4136>>3])+ +h[d+4128>>3])+ +h[d+4120>>3])+ +h[d+4112>>3])+ +h[d+4104>>3])+ +h[d+4096>>3])*+h[d+3192>>3];k=d+5960|0;A=c[k>>2]|0;B=d+5964|0;if((A|0)==0?(c[B>>2]|0)==0:0){C=(c[j>>2]|0)==0;v=z*+T(+x);u=-(z*+S(+x));D=C?v:u;E=C?u:v}else{v=z*+T(+x);u=z*+S(+x);C=A;A=1;x=v;z=-u;while(1){if((C|0)==0){F=x;G=1.0;H=0.0}else{r=x+ +hd(C,x,z);n=+id(c[k>>2]|0,x,z,1,0)+1.0;F=r;G=n;H=+id(c[k>>2]|0,x,z,0,1)}n=F-v;I=c[B>>2]|0;if((I|0)==0){J=z;K=0.0;L=1.0}else{r=z+ +hd(I,x,z);b=+id(c[B>>2]|0,x,z,1,0);J=r;K=b;L=+id(c[B>>2]|0,x,z,0,1)+1.0}b=u+J;r=G*L-H*K;if(r==0.0){M=x;N=z;break}q=(H*b-n*L)/r;o=(n*K-G*b)/r;r=x+q;y=z+o;I=+P(+q)>+P(+o);p=I?q:o;o=+P(+p);I=+P(+n)>+P(+b);q=I?n:b;I=o>+P(+q);if(!(!(+P(+(I?p:q))<2.8e-8)&(A|0)<500)){M=r;N=y;break}C=c[k>>2]|0;A=A+1|0;x=r;z=y}A=(c[j>>2]|0)==0;D=A?M:N;E=A?N:M}if((c[d+3300>>2]|0)!=0){h[e>>3]=D*+h[d+88>>3]+E*+h[d+96>>3];h[f>>3]=D*+h[d+104>>3]+E*+h[d+112>>3];O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}M=+h[d+48>>3];if(M!=0.0){N=M*3.141592653589793/180.0;M=+S(+N);z=+T(+N);h[e>>3]=D*M+E*z;ba=E*M-D*z}else{h[e>>3]=D;ba=E}h[f>>3]=ba;ba=+h[d+32>>3];if(ba!=0.0){h[e>>3]=+h[e>>3]/ba}ba=+h[d+40>>3];if(!(ba!=0.0)){O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}h[f>>3]=+h[f>>3]/ba;O=+h[e>>3];R=d+16|0;U=+h[R>>3];X=O+U;h[e>>3]=X;Z=+h[f>>3];_=d+24|0;$=+h[_>>3];aa=Z+$;h[f>>3]=aa;i=g;return 0}function nd(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0;f=i;g=(+h[c+224>>3]-(+h[c+176>>3]+a+-1.0+.5)*+h[c+192>>3])/1.0e3;a=((+h[c+184>>3]+b+-1.0+.5)*+h[c+200>>3]- +h[c+248>>3])/1.0e3;b=g*g;j=a*a;k=g*b;l=a*j;m=b+j;n=(k*+h[c+496>>3]+(l*+h[c+472>>3]+(m*+h[c+464>>3]+(b*+h[c+456>>3]+(+h[c+432>>3]+(a*+h[c+416>>3]+g*+h[c+424>>3])+j*+h[c+440>>3]+a*g*+h[c+448>>3])))+g*j*+h[c+480>>3]+b*a*+h[c+488>>3])+m*a*+h[c+504>>3]+m*m*a*+h[c+512>>3])/206264.8062470964;o=+h[c+160>>3];p=+U(+o);q=1.0-n*p;r=+Y(+((l*+h[c+336>>3]+(k*+h[c+312>>3]+(m*+h[c+304>>3]+(j*+h[c+296>>3]+(+h[c+272>>3]+(g*+h[c+256>>3]+a*+h[c+264>>3])+b*+h[c+280>>3]+a*g*+h[c+288>>3])))+a*b*+h[c+320>>3]+j*g*+h[c+328>>3])+m*g*+h[c+344>>3]+m*m*g*+h[c+352>>3])/206264.8062470964/+S(+o)),+q);o=r+ +h[c+152>>3];if(!(o<0.0)){s=o;t=s/.01745329252;h[d>>3]=t;u=+S(+r);v=n+p;w=v/q;x=u*w;y=+X(+x);z=y/.01745329252;h[e>>3]=z;i=f;return 0}s=o+6.28318530717959;t=s/.01745329252;h[d>>3]=t;u=+S(+r);v=n+p;w=v/q;x=u*w;y=+X(+x);z=y/.01745329252;h[e>>3]=z;i=f;return 0}function od(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,Q=0.0,R=0.0,U=0.0,V=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0;f=i;h[d>>3]=0.0;h[e>>3]=0.0;g=b*3.141592653589793/180.0;b=+T(+g);j=+S(+g);k=c+160|0;g=+h[k>>3];if(g==0.0){l=+h[c+8>>3]*3.141592653589793/180.0;h[k>>3]=l;m=l}else{m=g}g=+T(+m);l=+S(+m);k=c+152|0;m=+h[k>>3];if(m==0.0){n=+h[c+8>>3]*3.141592653589793/180.0;h[k>>3]=n;o=n}else{o=m}m=a*3.141592653589793/180.0-o;o=+S(+m);a=b*g+j*l*o;if(a==0.0){p=1;i=f;return p|0}n=j*+T(+m)*206264.8062470964/a;m=(b*l-j*g*o)*206264.8062470964/a;a=+h[c+168>>3];if(a==0.0){p=1;i=f;return p|0}o=+h[c+256>>3];g=+h[c+264>>3];j=+h[c+272>>3];l=+h[c+280>>3];b=+h[c+288>>3];q=+h[c+296>>3];r=+h[c+304>>3];s=+h[c+312>>3];t=+h[c+320>>3];u=+h[c+328>>3];v=+h[c+336>>3];w=+h[c+344>>3];x=+h[c+352>>3];y=l*2.0;z=r*2.0;A=s*3.0;B=t*2.0;C=q*2.0;D=u*2.0;E=v*3.0;F=w*2.0;G=x*4.0;H=+h[c+416>>3];I=+h[c+424>>3];J=+h[c+432>>3];K=+h[c+440>>3];L=+h[c+448>>3];M=+h[c+456>>3];N=+h[c+464>>3];O=+h[c+472>>3];Q=+h[c+480>>3];R=+h[c+488>>3];U=+h[c+496>>3];V=+h[c+504>>3];W=+h[c+512>>3];X=M*2.0;Y=N*2.0;Z=R*2.0;_=U*3.0;$=V*2.0;aa=W*4.0;ba=K*2.0;ca=O*3.0;da=Q*2.0;k=0;ea=n/a;fa=m/a;do{a=fa*ea;ga=ea*ea;ha=fa*fa;ia=fa*ga;ja=ha*ea;ka=ha+ga;la=ka*ka;ma=ea*ga;na=fa*ha;oa=ga*ga;pa=ha*ha;qa=ha*ga*6.0;ra=ha*u+(fa*b+(o+ea*y)+ea*z+ga*A+a*B)+(ha+ga*3.0)*w+(pa+(oa*5.0+qa))*x;sa=g+ea*b+fa*C+fa*z+ga*t+a*D+ha*E+a*F+ka*a*G;ta=I+fa*L+ea*X+ea*Y+ha*Q+a*Z+ga*_+a*$+ka*a*aa;ua=ga*R+(ea*L+(H+fa*ba)+fa*Y+ha*ca+a*da)+(ha*3.0+ga)*V+(oa+(pa*5.0+qa))*W;qa=j+(ea*o+fa*g)+ga*l+a*b+ha*q+ka*r+ma*s+ia*t+ja*u+na*v+ka*ea*w+la*ea*x-n;pa=J+(fa*H+ea*I)+ha*K+a*L+ga*M+ka*N+na*O+ja*Q+ia*R+ma*U+ka*fa*V+la*fa*W-m;la=ra*ua-sa*ta;ka=(sa*pa-qa*ua)/la;ua=(qa*ta-ra*pa)/la;ea=ea+ka;fa=fa+ua;if(+P(+ka)<5.0e-7?+P(+ua)<5.0e-7:0){break}k=k+1|0}while((k|0)<50);m=+h[c+192>>3];if(m==0.0){p=1;i=f;return p|0}W=+h[c+200>>3];if(W==0.0){p=1;i=f;return p|0}V=(fa*1.0e3+ +h[c+248>>3])/W;h[d>>3]=(+h[c+224>>3]-ea*1.0e3)/m- +h[c+176>>3]+1.0+-.5;m=V- +h[c+184>>3]+1.0+-.5;h[e>>3]=m;V=+h[d>>3];if(V<.5){p=-1;i=f;return p|0}if(V>+h[c+136>>3]+.5|m<.5){p=-1;i=f;return p|0}if(m>+h[c+144>>3]+.5){p=-1;i=f;return p|0}p=0;i=f;return p|0}function pd(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;i=i+16|0;e=d;d=c[o>>2]|0;c[e>>2]=a;c[e+4>>2]=b;za(d|0,10976,e|0)|0;hb(-1)}function qd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;f=i;i=i+544|0;g=f;h=f+24|0;j=f+8|0;k=ig(1,28)|0;if((k|0)==0){pd(10992,11016)}c[k+16>>2]=b;if((b|0)>4){c[g>>2]=b;c[g+4>>2]=4;Na(h|0,11040,g|0)|0;pd(11120,h)}if((b|0)==0){l=k+12|0}else{m=gg(b<<2)|0;n=k+12|0;c[n>>2]=m;if((m|0)==0){pd(10992,11136)}m=a;a=b;o=c[n>>2]|0;while(1){p=a+ -1|0;c[o>>2]=(c[m>>2]|0)+ -1;if((p|0)==0){l=n;break}else{m=m+4|0;a=p;o=o+4|0}}}c[k+24>>2]=e;a:do{if((e|0)!=0){o=c[l>>2]|0;a=e<<2;m=gg(a)|0;c[k+20>>2]=m;if((m|0)==0){pd(10992,11176)}Eg(j|0,0,a|0)|0;b:do{if((b|0)>0){a=0;while(1){m=c[o+(a<<2)>>2]|0;if((m|0)>=(e|0)){break}n=j+(m<<2)|0;c[n>>2]=(c[n>>2]|0)+1;a=a+1|0;if((a|0)>=(b|0)){break b}}pd(11216,11256)}}while(0);o=k+8|0;c[o>>2]=1;if((e|0)>0){a=c[k+20>>2]|0;n=d;m=1;p=0;while(1){q=n+4|0;r=c[n>>2]|0;c[a+(p<<2)>>2]=r;if((r|0)>10){break}s=c[j+(p<<2)>>2]|0;if((r|0)==0){t=1;u=1}else{v=r;w=1;x=1;while(1){y=aa(x,v+s|0)|0;z=v+ -1|0;A=aa(w,v)|0;if((z|0)==0){t=A;u=y;break}else{v=z;w=A;x=y}}}x=aa(m,(u|0)/(t|0)|0)|0;c[o>>2]=x;w=p+1|0;if((w|0)<(e|0)){n=q;m=x;p=w}else{B=x;break a}}c[g>>2]=r;c[g+4>>2]=10;Na(h|0,11264,g|0)|0;pd(11120,h)}else{B=1}}else{c[k+8>>2]=1;B=1}}while(0);h=gg(B<<3)|0;c[k>>2]=h;if((h|0)==0){pd(10992,11336)}h=ig(B,8)|0;c[k+4>>2]=h;if((h|0)==0){pd(10992,11376)}else{i=f;return k|0}return 0}function rd(a){a=a|0;var b=0;b=i;if((a|0)==0){i=b;return}hg(c[a+4>>2]|0);hg(c[a>>2]|0);hg(c[a+20>>2]|0);hg(c[a+12>>2]|0);hg(a);i=b;return}function sd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0.0,z=0.0,A=0,B=0,C=0,D=0;d=i;i=i+80|0;e=d;f=d+60|0;g=d+40|0;j=c[a+16>>2]|0;k=c[a>>2]|0;l=c[a+4>>2]|0;m=c[a+12>>2]|0;n=c[a+20>>2]|0;if((j|0)!=0){o=j+ -1|0;if((o|0)!=0){p=o;o=f;q=e;do{q=q+8|0;h[q>>3]=1.0;o=o+4|0;c[o>>2]=0;p=p+ -1|0}while((p|0)!=0)}p=c[a+24>>2]|0;if((p|0)!=0){o=n;n=p;p=g;while(1){n=n+ -1|0;c[p>>2]=c[o>>2];if((n|0)==0){break}else{o=o+4|0;p=p+4|0}}}p=g+(c[m>>2]<<2)|0;o=c[p>>2]|0;if((o|0)!=0){c[p>>2]=o+ -1}}o=l+8|0;r=+h[l>>3];l=k+8|0;h[k>>3]=1.0;c[f>>2]=1;s=+h[b>>3];h[e>>3]=s;k=(c[a+8>>2]|0)+ -1|0;if((k|0)==0){t=r;i=d;return+t}if((j|0)>0){u=s;v=k;w=l;x=o;y=r}else{z=s;a=k;k=l;l=o;s=r;while(1){h[k>>3]=z;r=s+z*+h[l>>3];o=a+ -1|0;if((o|0)==0){t=r;break}z=+h[e>>3];a=o;k=k+8|0;l=l+8|0;s=r}i=d;return+t}while(1){l=w+8|0;h[w>>3]=u;k=x+8|0;s=y+u*+h[x>>3];a=0;o=f;p=m;n=b;q=e;while(1){A=g+(c[p>>2]<<2)|0;B=c[A>>2]|0;c[A>>2]=B+ -1;C=c[o>>2]|0;if((B|0)!=0){D=13;break}c[g+(c[p>>2]<<2)>>2]=C;c[o>>2]=0;h[q>>3]=1.0;B=a+1|0;if((B|0)>=(j|0)){break}a=B;o=o+4|0;p=p+4|0;n=n+8|0;q=q+8|0}if((D|0)==13?(D=0,c[o>>2]=C+1,z=+h[n>>3]*+h[q>>3],h[q>>3]=z,(a|0)!=0):0){p=a;B=q;do{B=B+ -8|0;p=p+ -1|0;h[B>>3]=z}while((p|0)!=0)}p=v+ -1|0;if((p|0)==0){t=s;break}u=+h[e>>3];v=p;w=l;x=k;y=s}i=d;return+t}function td(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0.0,D=0.0,E=0,F=0,G=0,H=0,I=0.0,J=0,K=0,L=0,M=0;j=i;i=i+32|0;k=j;l=(b|0)!=0;m=(g|0)==0;if(m&(l^1)){pd(11416,11496)}n=c[a+8>>2]|0;o=c[a+16>>2]|0;p=aa(n,n)|0;q=c[a>>2]|0;r=ig(p,8)|0;if((r|0)==0){pd(10992,11512)}p=ig(n,8)|0;if((p|0)==0){pd(10992,11544)}if((f|0)!=0){s=(n|0)==0;t=(o|0)>0;u=e;e=d;d=f;f=g;g=b;while(1){b=d+ -1|0;if(l){if(t){v=0;w=g;while(1){h[k+(v<<3)>>3]=+h[w>>3];v=v+1|0;if((v|0)==(o|0)){break}else{w=w+8|0}}x=g+(o<<3)|0}else{x=g}+sd(a,k);if(m|s){y=f;z=x}else{w=q;v=f;A=n;while(1){A=A+ -1|0;h[v>>3]=+h[w>>3];if((A|0)==0){break}else{w=w+8|0;v=v+8|0}}y=f+(n<<3)|0;z=x}}else{if(s){y=f;z=g}else{v=q;w=f;A=n;while(1){A=A+ -1|0;h[v>>3]=+h[w>>3];if((A|0)==0){break}else{v=v+8|0;w=w+8|0}}y=f+(n<<3)|0;z=g}}if((u|0)==0){B=0;C=1.0}else{B=u+8|0;C=+h[u>>3]}w=e+8|0;D=+h[e>>3];if(!s){v=n;A=r;E=q;F=p;while(1){G=v+ -1|0;H=E+8|0;I=C*+h[E>>3];J=F+8|0;h[F>>3]=+h[F>>3]+D*I;K=A;L=q;M=n;while(1){M=M+ -1|0;h[K>>3]=+h[K>>3]+I*+h[L>>3];if((M|0)==0){break}else{K=K+8|0;L=L+8|0}}if((G|0)==0){break}else{v=G;A=A+(n<<3)|0;E=H;F=J}}}if((b|0)==0){break}else{u=B;e=w;d=b;f=y;g=z}}}ud(r,p,n);hg(r);if((n|0)==0){hg(p);i=j;return}r=p;z=c[a+4>>2]|0;a=n;while(1){a=a+ -1|0;h[z>>3]=+h[r>>3];if((a|0)==0){break}else{r=r+8|0;z=z+8|0}}hg(p);i=j;return}function ud(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=i;if((vd(a,b,c)|0)==0){i=d;return}e=c<<3;f=gg(aa(e,c)|0)|0;if((f|0)==0){pd(10992,11576)}g=gg(e)|0;if((g|0)==0){pd(10992,11600)}wd(a,b,c,c,f,g);hg(f);hg(g);i=d;return}function vd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0;d=i;e=gg(c<<3)|0;if((e|0)==0){pd(10992,11624)}f=(c|0)>0;if(f){g=0;a:do{j=aa(g,c)|0;k=e+(g<<3)|0;if((g|0)>0){l=g;do{m=aa(l,c)|0;n=g;o=+h[a+(l+j<<3)>>3];do{n=n+ -1|0;o=o- +h[a+(n+j<<3)>>3]*+h[a+(n+m<<3)>>3]}while((n|0)>0);if((g|0)==(l|0)){if(o<=0.0){p=15;break a}h[k>>3]=+Q(+o)}else{h[a+((aa(l,c)|0)+g<<3)>>3]=o/+h[k>>3]}l=l+1|0}while((l|0)<(c|0))}else{l=g;do{q=+h[a+(l+j<<3)>>3];if((g|0)==(l|0)){if(q<=0.0){p=15;break a}h[k>>3]=+Q(+q)}else{h[a+((aa(l,c)|0)+g<<3)>>3]=q/+h[k>>3]}l=l+1|0}while((l|0)<(c|0))}g=g+1|0}while((g|0)<(c|0));if((p|0)==15){hg(e);r=-1;i=d;return r|0}if(f){p=0;do{g=b+(p<<3)|0;q=+h[g>>3];if((p|0)>0){l=aa(p,c)|0;k=p;s=q;while(1){j=k+ -1|0;t=s- +h[a+(j+l<<3)>>3]*+h[b+(j<<3)>>3];if((j|0)>0){k=j;s=t}else{u=t;break}}}else{u=q}h[g>>3]=u/+h[e+(p<<3)>>3];p=p+1|0}while((p|0)!=(c|0));if(f){f=c;while(1){p=f+ -1|0;k=b+(p<<3)|0;u=+h[k>>3];if((f|0)<(c|0)){l=f;s=u;while(1){t=+h[a+((aa(l,c)|0)+p<<3)>>3];v=s-t*+h[b+(l<<3)>>3];j=l+1|0;if((j|0)==(c|0)){w=v;break}else{l=j;s=v}}}else{w=u}h[k>>3]=w/+h[e+(p<<3)>>3];if((p|0)>0){f=p}else{break}}}}}hg(e);r=0;i=d;return r|0}function wd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0.0,B=0.0,C=0,D=0.0,E=0.0,F=0.0,G=0,H=0,I=0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,S=0.0,T=0,U=0,V=0,W=0,X=0.0,Y=0,Z=0,_=0,$=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0.0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0.0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0.0,Fa=0.0,Ga=0.0,Ha=0.0,Ia=0.0,Ja=0.0,Ka=0.0,La=0.0,Ma=0.0,Na=0.0,Oa=0.0,Pa=0,Qa=0,Ra=0.0,Sa=0,Ta=0.0,Ua=0,Va=0,Wa=0.0;g=i;if((c|0)<(d|0)){pd(11648,11704)}j=d<<3;k=gg(j)|0;if((k|0)==0){pd(10992,11720)}l=gg(j)|0;if((l|0)==0){pd(10992,11744)}j=(d|0)>0;a:do{if(j){m=c+1|0;n=0.0;o=0.0;p=0;q=0.0;while(1){r=p+1|0;s=d-r|0;t=k+(p<<3)|0;h[t>>3]=o*q;u=c-p|0;b:do{if((u|0)>0?(v=a+((aa(p,m)|0)<<3)|0,w=(p|0)==(c|0),!w):0){x=v;y=u;z=0.0;while(1){y=y+ -1|0;z=z+ +P(+(+h[x>>3]));if((y|0)==0){break}else{x=x+8|0}}if(z!=0.0){if(w){A=0.0}else{x=v;y=u;B=0.0;while(1){C=y+ -1|0;D=+h[x>>3]/z;h[x>>3]=D;E=B+D*D;if((C|0)==0){A=E;break}else{x=x+8|0;y=C;B=E}}}B=+h[v>>3];E=+P(+(+Q(+A)));if(!(B>=0.0)){F=-E}else{F=E}E=-F;D=B*E-A;h[v>>3]=B+F;if((r|0)!=(d|0)){y=s;x=a+((aa(r,c)|0)+p<<3)|0;while(1){y=y+ -1|0;c:do{if(!w){C=v;G=x;H=u;B=0.0;while(1){I=H+ -1|0;J=B+ +h[G>>3]*+h[C>>3];if((I|0)==0){break}C=C+8|0;G=G+8|0;H=I;B=J}B=J/D;if(!w){H=v;G=x;C=u;while(1){I=C+ -1|0;h[G>>3]=+h[G>>3]+B*+h[H>>3];if((I|0)==0){break c}H=H+8|0;G=G+8|0;C=I}}}}while(0);if((y|0)==0){break}else{x=x+(c<<3)|0}}}if(w){K=E;L=z}else{x=v;y=u;while(1){C=y+ -1|0;h[x>>3]=z*+h[x>>3];if((C|0)==0){K=E;L=z;break b}x=x+8|0;y=C}}}else{K=0.0;L=z}}else{K=0.0;L=0.0}}while(0);E=K*L;u=f+(p<<3)|0;h[u>>3]=E;if(!((p|0)>=(c|0)|(r|0)==(d|0))){y=aa(r,c)|0;x=a+(y+p<<3)|0;v=x;w=s;D=0.0;while(1){w=w+ -1|0;D=D+ +P(+(+h[v>>3]));if((w|0)==0){break}else{v=v+(c<<3)|0}}if(D!=0.0){v=x;w=s;B=0.0;while(1){w=w+ -1|0;M=+h[v>>3]/D;h[v>>3]=M;B=B+M*M;if((w|0)==0){break}else{v=v+(c<<3)|0}}M=+h[x>>3];N=+P(+(+Q(+B)));if(!(M>=0.0)){O=-N}else{O=N}N=-O;R=M*N-B;S=M+O;h[x>>3]=S;v=k+(r<<3)|0;M=S;w=x;C=s;G=v;while(1){H=C+ -1|0;h[G>>3]=M/R;I=w+(c<<3)|0;if((H|0)==0){break}M=+h[I>>3];w=I;C=H;G=G+8|0}if((r|0)==(c|0)){T=x;U=s}else{G=c-r|0;C=a+(y+r<<3)|0;while(1){w=G+ -1|0;H=x;I=C;V=s;M=0.0;while(1){W=V+ -1|0;X=M+ +h[I>>3]*+h[H>>3];if((W|0)==0){Y=C;Z=s;_=v;break}H=H+(c<<3)|0;I=I+(c<<3)|0;V=W;M=X}while(1){Z=Z+ -1|0;h[Y>>3]=+h[Y>>3]+X*+h[_>>3];if((Z|0)==0){break}else{Y=Y+(c<<3)|0;_=_+8|0}}if((w|0)==0){T=x;U=s;break}else{G=w;C=C+8|0}}}while(1){C=U+ -1|0;h[T>>3]=D*+h[T>>3];if((C|0)==0){break}T=T+(c<<3)|0;U=C}$=+h[u>>3];ba=N;ca=D}else{$=E;ba=0.0;ca=D}}else{$=E;ba=0.0;ca=0.0}M=+P(+$);z=M+ +P(+(+h[t>>3]));da=n>z?n:z;if((r|0)==(d|0)){break}else{n=da;o=ba;p=r;q=ca}}p=d+ -1|0;if(j){q=ba;m=p;C=0;G=d;s=0;while(1){do{if((m|0)<(p|0)){if(q!=0.0){x=a+(m+(aa(G,c)|0)<<3)|0;v=e+((aa(m,d)|0)+G<<3)|0;y=e+((aa(G,d)|0)+G<<3)|0;o=+h[x>>3];n=q*o;V=(s|0)==0;if(V){break}else{ea=o;fa=x;ga=s;ha=v}while(1){I=ga+ -1|0;h[ha>>3]=ea/n;H=fa+(c<<3)|0;if((I|0)==0){break}ea=+h[H>>3];fa=H;ga=I;ha=ha+8|0}if(V){break}else{ia=s;ja=y}while(1){ia=ia+ -1|0;w=x;I=s;n=0.0;H=ja;while(1){W=I+ -1|0;ka=n+ +h[w>>3]*+h[H>>3];if((W|0)==0){la=s;ma=v;na=ja;break}w=w+(c<<3)|0;I=W;n=ka;H=H+8|0}while(1){la=la+ -1|0;h[na>>3]=+h[na>>3]+ka*+h[ma>>3];if((la|0)==0){break}else{ma=ma+8|0;na=na+8|0}}if((ia|0)==0){break}else{ja=ja+(d<<3)|0}}}if((s|0)!=0){v=s;x=e+(m+(aa(G,d)|0)<<3)|0;y=e+((aa(m,d)|0)+G<<3)|0;while(1){v=v+ -1|0;h[y>>3]=0.0;h[x>>3]=0.0;if((v|0)==0){break}else{x=x+(d<<3)|0;y=y+8|0}}}}}while(0);h[e+((aa(m,d)|0)+m<<3)>>3]=1.0;s=d-m|0;C=C+1|0;if((C|0)==(d|0)){break}else{r=m;q=+h[k+(m<<3)>>3];m=m+ -1|0;G=r}}if(j){G=~d;m=~c;C=(G|0)>(m|0)?G:m;m=a+((aa(-2-C|0,c)|0)+ -2-C<<3)|0;G=-8-(c<<3)|0;s=(C+c<<3)+16|0;p=~C;C=d;r=0;while(1){t=m+(aa(G,r)|0)|0;u=s+(r<<3)|0;y=C+ -1|0;x=d-C|0;v=c-y|0;q=+h[f+(y<<3)>>3];V=(aa(y,c)|0)+y|0;H=a+(V<<3)|0;I=a+(V+c<<3)|0;V=(C|0)==(d|0);if(!V){w=I;W=x;while(1){W=W+ -1|0;h[w>>3]=0.0;if((W|0)==0){break}else{w=w+(c<<3)|0}}}d:do{if(q!=0.0){E=1.0/q;if(!V){w=v+ -1|0;W=(w|0)==0;oa=(y|0)==(c|0);pa=x;qa=I;while(1){pa=pa+ -1|0;if(W){ra=0.0}else{sa=w;ta=H;ua=qa;D=0.0;while(1){va=ta+8|0;wa=ua+8|0;N=D+ +h[va>>3]*+h[wa>>3];xa=sa+ -1|0;if((xa|0)==0){ra=N;break}else{sa=xa;ta=va;ua=wa;D=N}}}D=+h[H>>3];N=E*(ra/D);e:do{if(!oa){n=D;ua=H;ta=qa;sa=v;while(1){wa=sa+ -1|0;va=ua+8|0;h[ta>>3]=+h[ta>>3]+N*n;if((wa|0)==0){break e}n=+h[va>>3];ua=va;ta=ta+8|0;sa=wa}}}while(0);if((pa|0)==0){break}else{qa=qa+(c<<3)|0}}}if((y|0)!=(c|0)){qa=H;pa=v;while(1){oa=pa+ -1|0;h[qa>>3]=E*+h[qa>>3];if((oa|0)==0){break d}qa=qa+8|0;pa=oa}}}else{if((y|0)!=(c|0)){Eg(t|0,0,u|0)|0}}}while(0);h[H>>3]=+h[H>>3]+1.0;u=r+1|0;if((u|0)==(p|0)){break}else{C=y;r=u}}if(j){r=(c|0)==0;C=d;p=0;f:while(1){s=C+ -1|0;G=f+(s<<3)|0;m=C+ -2|0;u=f+(m<<3)|0;t=k+(m<<3)|0;v=k+(s<<3)|0;I=0;x=p;while(1){V=s;pa=x;while(1){if(!((V|0)>-1)){ya=pa;za=93;break}qa=V+ -1|0;if(da+ +P(+(+h[k+(V<<3)>>3]))==da){Aa=qa;break}if(da+ +P(+(+h[f+(qa<<3)>>3]))==da){ya=qa;za=93;break}else{V=qa;pa=qa}}g:do{if((za|0)==93){za=0;pa=a+((aa(ya,c)|0)<<3)|0;if((V|0)>(s|0)){Aa=ya}else{qa=a+((aa(V,c)|0)<<3)|0;oa=V;q=1.0;while(1){E=q*+h[k+(oa<<3)>>3];N=+P(+E);if(da+N==da){Aa=ya;break g}w=f+(oa<<3)|0;D=+h[w>>3];n=+P(+D);if(!(N>n)){if(D!=0.0){o=N/n;Ba=n*+Q(+(o*o+1.0))}else{Ba=0.0}}else{o=n/N;Ba=N*+Q(+(o*o+1.0))}h[w>>3]=Ba;o=1.0/Ba;N=D*o;D=-(E*o);if(!r){w=pa;W=qa;sa=c;while(1){sa=sa+ -1|0;o=+h[W>>3];E=+h[w>>3];h[w>>3]=o*D+N*E;h[W>>3]=N*o-E*D;if((sa|0)==0){break}else{w=w+8|0;W=W+8|0}}}if((oa|0)>=(s|0)){Aa=ya;break g}qa=qa+(c<<3)|0;oa=oa+1|0;q=D}}}}while(0);Ca=+h[G>>3];if((V|0)==(s|0)){za=105;break}if((I|0)==99){break f}q=+h[f+(V<<3)>>3];N=+h[u>>3];E=+h[t>>3];o=+h[v>>3];n=((N-Ca)*(Ca+N)+(E-o)*(E+o))/(N*o*2.0);E=+P(+n);if(E>1.0){z=1.0/E;Da=E*+Q(+(z*z+1.0))}else{Da=+Q(+(E*E+1.0))}E=+P(+Da);if(!(n>=0.0)){Ea=-E}else{Ea=E}E=((q-Ca)*(Ca+q)+o*(N/(n+Ea)-o))/q;if((V|0)>(m|0)){Fa=E;Ga=q}else{oa=a+((aa(V,c)|0)<<3)|0;o=1.0;n=E;qa=V;E=1.0;pa=e+((aa(V,d)|0)<<3)|0;N=q;while(1){W=qa+1|0;q=+h[k+(W<<3)>>3];z=+h[f+(W<<3)>>3];M=E*q;R=o*q;q=+P(+n);B=+P(+M);if(!(q>B)){if(M!=0.0){S=q/B;Ha=B*+Q(+(S*S+1.0))}else{Ha=0.0}}else{S=B/q;Ha=q*+Q(+(S*S+1.0))}h[k+(qa<<3)>>3]=Ha;S=n/Ha;q=M/Ha;M=N*S+R*q;B=R*S-N*q;R=z*q;Ia=z*S;w=pa+(d<<3)|0;sa=d;ta=w;ua=pa;while(1){sa=sa+ -1|0;z=+h[ta>>3];Ja=+h[ua>>3];h[ua>>3]=q*z+S*Ja;h[ta>>3]=S*z-q*Ja;if((sa|0)==0){break}else{ta=ta+8|0;ua=ua+8|0}}Ja=+P(+M);z=+P(+R);do{if(!(Ja>z)){if(R!=0.0){Ka=Ja/z;La=z*+Q(+(Ka*Ka+1.0));za=130;break}else{h[f+(qa<<3)>>3]=0.0;Ma=S;Na=q;break}}else{Ka=z/Ja;La=Ja*+Q(+(Ka*Ka+1.0));za=130}}while(0);if((za|0)==130){za=0;h[f+(qa<<3)>>3]=La;if(La!=0.0){Ja=1.0/La;Ma=M*Ja;Na=R*Ja}else{Ma=S;Na=q}}Ja=B*Ma+Ia*Na;z=Ia*Ma-B*Na;ua=oa+(c<<3)|0;if(!r){ta=ua;sa=oa;wa=c;while(1){wa=wa+ -1|0;Ka=+h[ta>>3];Oa=+h[sa>>3];h[sa>>3]=Na*Ka+Ma*Oa;h[ta>>3]=Ma*Ka-Na*Oa;if((wa|0)==0){break}else{ta=ta+8|0;sa=sa+8|0}}}if((qa|0)<(m|0)){oa=ua;o=Ma;n=Ja;qa=W;E=Na;pa=w;N=z}else{Fa=Ja;Ga=z;break}}}h[k+(V<<3)>>3]=0.0;h[v>>3]=Fa;h[G>>3]=Ga;pa=I+1|0;if((pa|0)<100){I=pa;x=m}else{Pa=m;break}}if((za|0)==105){za=0;if(Ca<0.0){h[G>>3]=-Ca;m=d;x=e+((aa(s,d)|0)<<3)|0;while(1){I=m+ -1|0;h[x>>3]=-+h[x>>3];if((I|0)==0){Pa=Aa;break}else{m=I;x=x+8|0}}}else{Pa=Aa}}if((s|0)>0){C=s;p=Pa}else{break a}}pd(11768,11704)}}}}}while(0);Pa=(d|0)==0;if(!Pa){Aa=d;za=f;Ca=0.0;while(1){Aa=Aa+ -1|0;Ga=+h[za>>3];Ca=Ga>Ca?Ga:Ca;if((Aa|0)==0){break}else{za=za+8|0}}Ga=Ca*1.0e-11;if(!Pa){za=d;Aa=f;while(1){za=za+ -1|0;if(+h[Aa>>3]>3]=0.0}if((za|0)==0){break}else{Aa=Aa+8|0}}if(!Pa){Pa=(c|0)==0;Aa=d;za=a;a=l;ya=f;while(1){Aa=Aa+ -1|0;Ga=+h[ya>>3];if(Ga!=0.0){if(Pa){Qa=za;Ra=0.0}else{f=za;ja=b;ia=c;Ca=0.0;while(1){ia=ia+ -1|0;Ca=Ca+ +h[f>>3]*+h[ja>>3];if((ia|0)==0){break}else{f=f+8|0;ja=ja+8|0}}Qa=za+(c<<3)|0;Ra=Ca}Sa=Qa;Ta=Ra/Ga}else{Sa=za+(c<<3)|0;Ta=0.0}h[a>>3]=Ta;if((Aa|0)==0){break}else{za=Sa;a=a+8|0;ya=ya+8|0}}}}}if(j){Ua=0;Va=e}else{hg(l);hg(k);i=g;return}while(1){e=d;Ta=0.0;j=l;ya=Va;while(1){a=e+ -1|0;Wa=Ta+ +h[ya>>3]*+h[j>>3];if((a|0)==0){break}e=a;Ta=Wa;j=j+8|0;ya=ya+(d<<3)|0}h[b+(Ua<<3)>>3]=Wa;Ua=Ua+1|0;if((Ua|0)==(d|0)){break}else{Va=Va+8|0}}hg(l);hg(k);i=g;return}function xd(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0;f=i;i=i+32|0;g=f+8|0;h=f;j=f+16|0;k=h;c[k>>2]=5260110;c[k+4>>2]=5459015;k=e+4|0;a[k]=0;a[j]=0;l=e+20|0;c[l>>2]=-1;m=e+24|0;c[m>>2]=-1;n=e+28|0;c[n>>2]=-1;do{if((b|0)>0){o=e+8|0;p=e+13|0;q=0;r=0;a:while(1){s=d+(q*9|0)|0;do{if((a[d+(q*9|0)+4|0]|0)!=45){if((yg(s,11816)|0)==0){if(!((c[n>>2]|0)==-1)){t=1;u=35;break a}c[n>>2]=q;v=r}else{v=r}}else{w=d+(q*9|0)+5|0;x=c[2992]|0;b:do{if((x|0)>0){y=0;while(1){z=y+1|0;if((Ag(w,11976+(y<<2)|0,3)|0)==0){A=y;break b}if((z|0)<(x|0)){y=z}else{A=z;break}}}else{A=0}}while(0);if((A|0)==(x|0)){y=0;while(1){z=y+1|0;if((Ag(w,h+(y<<2)|0,3)|0)==0){B=y;break}if((z|0)<2){y=z}else{B=z;break}}if((B|0)==2){v=r;break}}if((a[k]|0)!=0){if((Ag(s,j,8)|0)!=0|(r|0)==0){t=1;u=35;break a}c[r>>2]=q;a[j]=0;v=r;break}c[g>>2]=w;Na(k|0,11832,g|0)|0;if((Ag(s,11840,4)|0)==0){c[l>>2]=q;a[o+0|0]=a[11848|0]|0;a[o+1|0]=a[11849|0]|0;a[o+2|0]=a[11850|0]|0;a[p]=4408644;a[p+1|0]=17221;a[p+2|0]=67;a[p+3|0]=0;c[g>>2]=k;Na(j|0,11856,g|0)|0;v=m;break}if((Ag(s,11864,4)|0)==0){c[m>>2]=q;a[o+0|0]=a[11848|0]|0;a[o+1|0]=a[11849|0]|0;a[o+2|0]=a[11850|0]|0;a[p]=4408644;a[p+1|0]=17221;a[p+2|0]=67;a[p+3|0]=0;c[g>>2]=k;Na(j|0,11872,g|0)|0;v=l;break}y=d+(q*9|0)+1|0;if((Ag(y,11880,3)|0)==0){c[l>>2]=q;c[g>>2]=a[s]|0;Na(o|0,11888,g|0)|0;c[g>>2]=a[s]|0;Na(p|0,11896,g|0)|0;c[g>>2]=p;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=m;break}if((Ag(y,11912,3)|0)==0){c[m>>2]=q;c[g>>2]=a[s]|0;Na(o|0,11888,g|0)|0;c[g>>2]=a[s]|0;Na(p|0,11896,g|0)|0;c[g>>2]=o;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=l;break}x=d+(q*9|0)+2|0;if((Ag(x,11920,2)|0)==0){c[l>>2]=q;z=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=z;Na(o|0,11928,g|0)|0;z=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=z;Na(p|0,11936,g|0)|0;c[g>>2]=p;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=m;break}if((Ag(x,11944,2)|0)!=0){t=1;u=35;break a}c[m>>2]=q;x=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=x;Na(o|0,11928,g|0)|0;x=a[y]|0;c[g>>2]=a[s]|0;c[g+4>>2]=x;Na(p|0,11936,g|0)|0;c[g>>2]=o;c[g+4>>2]=k;Na(j|0,11904,g|0)|0;v=l}}while(0);s=q+1|0;if((s|0)<(b|0)){q=s;r=v}else{u=30;break}}if((u|0)==30){if((a[j]|0)==0){break}else{t=1}i=f;return t|0}else if((u|0)==35){i=f;return t|0}}}while(0);if((Ag(k,11952,3)|0)==0){a[k]=4998739;a[k+1|0]=19526;a[k+2|0]=76;a[k+3|0]=0;C=137}else{C=(a[k]|0)==0?999:137}c[e>>2]=C;t=0;i=f;return t|0}function yd(b,d,e,f,g,j,k,l,m,n,o){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0,t=0,u=0.0,v=0,w=0.0,x=0.0;p=i;q=n+4|0;if((c[d>>2]|0)!=137?(xd(c[q>>2]|0,b,d)|0)!=0:0){r=1;i=p;return r|0}b=c[q>>2]|0;if((b|0)>0){q=c[d+20>>2]|0;s=d+24|0;t=0;do{if((t|0)!=(q|0)?(t|0)!=(c[s>>2]|0):0){h[m+(t<<3)>>3]=+h[e+(t<<3)>>3]- +h[f+(t<<3)>>3]}t=t+1|0}while((t|0)<(b|0))}do{if((c[d>>2]|0)!=999){b=d+4|0;do{if((yg(b,11960)|0)==0){t=g+16|0;if(+h[t>>3]==0.0){r=2;i=p;return r|0}else{a[b]=5130579;a[b+1|0]=20041;a[b+2|0]=78;a[b+3|0]=0;h[l+40>>3]=0.0;u=+Re(+h[t>>3]);h[l+48>>3]=u/+Se(+h[t>>3]);t=l+4|0;c[t>>2]=c[t>>2]>>31;break}}}while(0);t=d+20|0;f=c[t>>2]|0;s=d+24|0;q=c[s>>2]|0;v=Fd(b,+h[e+(f<<3)>>3],+h[e+(q<<3)>>3],g,j,k,l,m+(f<<3)|0,m+(q<<3)|0)|0;if((v|0)!=0){r=v;i=p;return r|0}v=c[d+28>>2]|0;if(!((v|0)==-1)){u=+h[l+24>>3];if(u==0.0){w=90.0}else{w=u*3.141592653589793*.5}q=m+(c[s>>2]<<3)|0;u=+h[q>>3];if(u>3]=w+u;h[m+(v<<3)>>3]=5.0;break}x=w*.5;if(u>x){h[q>>3]=u-w;h[m+(v<<3)>>3]=0.0;break}q=m+(c[t>>2]<<3)|0;u=+h[q>>3];if(u>w*2.5){h[q>>3]=u-w*3.0;h[m+(v<<3)>>3]=4.0;break}if(u>w*1.5){h[q>>3]=u-w*2.0;h[m+(v<<3)>>3]=3.0;break}if(u>x){h[q>>3]=u-w;h[m+(v<<3)>>3]=2.0;break}else{h[m+(v<<3)>>3]=1.0;break}}}}while(0);l=(Cd(m,n,o)|0)==0;r=l?0:4;i=p;return r|0}function zd(b,d,e,f,g,j,k,l,m,n,o){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0.0,t=0.0;p=i;if((c[d>>2]|0)!=137?(xd(c[f+4>>2]|0,b,d)|0)!=0:0){q=1;i=p;return q|0}if((Dd(e,f,g)|0)!=0){q=4;i=p;return q|0}e=c[f+4>>2]|0;if((e|0)>0){f=c[d+20>>2]|0;b=d+24|0;r=0;do{if((r|0)!=(f|0)?(r|0)!=(c[b>>2]|0):0){h[o+(r<<3)>>3]=+h[g+(r<<3)>>3]+ +h[m+(r<<3)>>3]}r=r+1|0}while((r|0)<(e|0))}if((c[d>>2]|0)!=999){e=c[d+28>>2]|0;a:do{if(!((e|0)==-1)){s=+h[g+(e<<3)>>3];r=~~(s+.5);if(+P(+(s- +(r|0)))>1.0e-10){q=3;i=p;return q|0}s=+h[j+24>>3];if(s==0.0){t=90.0}else{t=s*3.141592653589793*.5}switch(r|0){case 2:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t+ +h[r>>3];break a;break};case 4:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t*3.0+ +h[r>>3];break a;break};case 3:{r=g+(c[d+20>>2]<<3)|0;h[r>>3]=t*2.0+ +h[r>>3];break a;break};case 0:{r=g+(c[d+24>>2]<<3)|0;h[r>>3]=t+ +h[r>>3];break a;break};case 5:{r=g+(c[d+24>>2]<<3)|0;h[r>>3]=+h[r>>3]-t;break a;break};case 1:{break a;break};default:{q=3;i=p;return q|0}}}}while(0);e=d+4|0;do{if((yg(e,11960)|0)==0){r=n+16|0;if(+h[r>>3]==0.0){q=2;i=p;return q|0}else{a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;h[j+40>>3]=0.0;t=+Re(+h[r>>3]);h[j+48>>3]=t/+Se(+h[r>>3]);r=j+4|0;c[r>>2]=c[r>>2]>>31;break}}}while(0);r=c[d+20>>2]|0;m=c[d+24>>2]|0;d=Gd(e,+h[g+(r<<3)>>3],+h[g+(m<<3)>>3],j,k,l,n,o+(r<<3)|0,o+(m<<3)|0)|0;if((d|0)!=0){q=d;i=p;return q|0}}q=0;i=p;return q|0}function Ad(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;b=i;d=c[a+4>>2]|0;e=aa(d<<3,d)|0;f=gg(e)|0;c[a+20>>2]=f;if((f|0)==0){g=1;i=b;return g|0}j=gg(e)|0;c[a+24>>2]=j;if((j|0)==0){hg(f);g=1;i=b;return g|0}if((d|0)>0){e=a+16|0;k=a+12|0;l=0;m=0;while(1){n=(c[e>>2]|0)+(l<<3)|0;o=c[k>>2]|0;p=m;q=0;while(1){h[f+(p<<3)>>3]=+h[n>>3]*+h[o+(p<<3)>>3];q=q+1|0;if((q|0)==(d|0)){break}else{p=p+1|0}}l=l+1|0;if((l|0)==(d|0)){break}else{m=d+m|0}}}if((Bd(d,f,j)|0)!=0){g=2;i=b;return g|0}c[a>>2]=137;g=0;i=b;return g|0}function Bd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0,x=0,y=0,z=0,A=0,B=0;e=i;f=a<<2;g=gg(f)|0;if((g|0)==0){j=1;i=e;return j|0}k=gg(f)|0;if((k|0)==0){hg(g);j=1;i=e;return j|0}f=a<<3;l=gg(f)|0;if((l|0)==0){hg(g);hg(k);j=1;i=e;return j|0}m=gg(aa(f,a)|0)|0;if((m|0)==0){hg(g);hg(k);hg(l);j=1;i=e;return j|0}f=(a|0)>0;if(f){n=a<<3;o=0;p=0;while(1){c[g+(o<<2)>>2]=o;q=l+(o<<3)|0;h[q>>3]=0.0;Kg(m+(p<<3)|0,b+(p<<3)|0,n|0)|0;r=0.0;s=p;t=0;while(1){u=+P(+(+h[b+(s<<3)>>3]));if(u>r){h[q>>3]=u;v=u}else{v=r}t=t+1|0;if((t|0)==(a|0)){break}else{r=v;s=s+1|0}}o=o+1|0;if(v==0.0){w=17;break}if((o|0)>=(a|0)){break}else{p=p+a|0}}if((w|0)==17){hg(g);hg(k);hg(l);hg(m);j=2;i=e;return j|0}if(f){w=0;while(1){p=aa(w,a)|0;o=m+(p+w<<3)|0;b=l+(w<<3)|0;n=w+1|0;s=(n|0)<(a|0);if(s){v=+P(+(+h[o>>3]))/+h[b>>3];t=n;q=w;while(1){r=+P(+(+h[m+((aa(t,a)|0)+w<<3)>>3]));u=r/+h[l+(t<<3)>>3];x=u>v;q=x?t:q;t=t+1|0;if((t|0)==(a|0)){break}else{v=x?u:v}}if((q|0)>(w|0)){t=0;x=p;y=aa(q,a)|0;while(1){z=m+(y<<3)|0;v=+h[z>>3];A=m+(x<<3)|0;h[z>>3]=+h[A>>3];h[A>>3]=v;t=t+1|0;if((t|0)==(a|0)){break}else{x=x+1|0;y=y+1|0}}y=l+(q<<3)|0;v=+h[y>>3];h[y>>3]=+h[b>>3];h[b>>3]=v;y=g+(q<<2)|0;x=c[y>>2]|0;t=g+(w<<2)|0;c[y>>2]=c[t>>2];c[t>>2]=x}if(s){x=n;do{t=aa(x,a)|0;y=m+(t+w<<3)|0;v=+h[y>>3];a:do{if(v!=0.0){u=v/+h[o>>3];h[y>>3]=u;r=u;A=n;while(1){z=m+(A+t<<3)|0;h[z>>3]=+h[z>>3]-r*+h[m+(A+p<<3)>>3];z=A+1|0;if((z|0)==(a|0)){break a}r=+h[y>>3];A=z}}}while(0);x=x+1|0}while((x|0)!=(a|0))}}if((n|0)==(a|0)){break}else{w=n}}if(f){w=0;do{c[k+(c[g+(w<<2)>>2]<<2)>>2]=w;w=w+1|0}while((w|0)!=(a|0));if(f){w=a<<3;x=0;p=0;while(1){Eg(d+(p<<3)|0,0,w|0)|0;x=x+1|0;if((x|0)==(a|0)){break}else{p=p+a|0}}if(f){f=0;do{p=c[k+(f<<2)>>2]|0;h[d+((aa(p,a)|0)+f<<3)>>3]=1.0;x=p+1|0;if((x|0)<(a|0)){w=x;while(1){if((p|0)<(w|0)){x=aa(w,a)|0;o=d+(x+f<<3)|0;v=+h[o>>3];s=p;do{v=v- +h[m+(s+x<<3)>>3]*+h[d+((aa(s,a)|0)+f<<3)>>3];h[o>>3]=v;s=s+1|0}while((s|0)!=(w|0))}s=w+1|0;if((s|0)==(a|0)){B=a;break}else{w=s}}}else{B=a}while(1){w=B+ -1|0;p=aa(w,a)|0;n=d+(p+f<<3)|0;if((B|0)<(a|0)){v=+h[n>>3];s=B;do{v=v- +h[m+(s+p<<3)>>3]*+h[d+((aa(s,a)|0)+f<<3)>>3];h[n>>3]=v;s=s+1|0}while((s|0)!=(a|0))}h[n>>3]=+h[n>>3]/+h[m+(p+w<<3)>>3];if((w|0)>0){B=w}else{break}}f=f+1|0}while((f|0)!=(a|0))}}}}}hg(g);hg(k);hg(l);hg(m);j=0;i=e;return j|0}function Cd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0,r=0;e=i;f=c[b+4>>2]|0;if((c[b>>2]|0)!=137?(Ad(b)|0)!=0:0){g=1;i=e;return g|0}j=(f|0)>0;if(!j){g=0;i=e;return g|0}k=b+24|0;l=0;m=0;while(1){n=d+(l<<3)|0;h[n>>3]=0.0;o=c[k>>2]|0;p=0.0;q=m;r=0;while(1){p=p+ +h[o+(q<<3)>>3]*+h[a+(r<<3)>>3];h[n>>3]=p;r=r+1|0;if((r|0)==(f|0)){break}else{q=q+1|0}}l=l+1|0;if((l|0)==(f|0)){break}else{m=f+m|0}}if(!j){g=0;i=e;return g|0}j=c[b+8>>2]|0;b=0;while(1){m=d+(b<<3)|0;h[m>>3]=+h[j+(b<<3)>>3]+ +h[m>>3];m=b+1|0;if((m|0)==(f|0)){g=0;break}else{b=m}}i=e;return g|0}function Dd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0;e=i;f=c[b+4>>2]|0;if((c[b>>2]|0)!=137?(Ad(b)|0)!=0:0){g=1;i=e;return g|0}if((f|0)<=0){g=0;i=e;return g|0}Eg(d|0,0,f<<3|0)|0;j=c[b+8>>2]|0;k=b+20|0;b=0;while(1){l=+h[a+(b<<3)>>3]- +h[j+(b<<3)>>3];m=c[k>>2]|0;n=0;o=b;while(1){p=d+(n<<3)|0;h[p>>3]=+h[p>>3]+l*+h[m+(o<<3)>>3];n=n+1|0;if((n|0)==(f|0)){break}else{o=o+f|0}}o=b+1|0;if((o|0)==(f|0)){g=0;break}else{b=o}}i=e;return g|0}function Ed(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0,C=0.0,D=0.0;e=i;if((Hd(a,d)|0)!=0){f=1;i=e;return f|0}a=b+8|0;g=b+24|0;j=+h[g>>3]==999.0;k=d+16|0;l=+h[k>>3];do{if(!(l==90.0)){m=+h[b+16>>3];if(j){h[g>>3]=m>3]);o=+Re(+h[g>>3]);p=+Se(+h[g>>3]);q=+Re(+h[k>>3]);r=+Se(+h[k>>3]);s=o*q;o=+Q(+(s*s+r*r));do{if(o==0.0){if(m!=0.0){f=1;i=e;return f|0}else{t=+h[b+32>>3];break}}else{u=m/o;if(+P(+u)>1.0){f=1;i=e;return f|0}v=+Xe(r,s);w=+Ue(u);u=v+w;if(!(u>180.0)){if(u<-180.0){x=u+360.0}else{x=u}}else{x=u+-360.0}u=v-w;if(!(u>180.0)){if(u<-180.0){y=u+360.0}else{y=u}}else{y=u+-360.0}d=b+32|0;u=+h[d>>3];if(+P(+(u-x))<+P(+(u-y))){z=+P(+x)<90.0000000001;A=z?x:y}else{z=+P(+y)<90.0000000001;A=z?y:x}h[d>>3]=A;t=A}}while(0);d=b+40|0;z=b+48|0;h[z>>3]=90.0-t;s=n*+Re(t);do{if(+P(+s)<1.0e-10){if(+P(+n)<1.0e-10){o=+h[a>>3];h[d>>3]=o;h[z>>3]=90.0- +h[k>>3];B=a;C=o;break}if(t>0.0){o=+h[a>>3]+ +h[g>>3]+-180.0;h[d>>3]=o;h[z>>3]=0.0;B=a;C=o;break}if(t<0.0){o=+h[a>>3]- +h[g>>3];h[d>>3]=o;h[z>>3]=180.0;B=a;C=o;break}else{B=a;C=+h[d>>3];break}}else{o=(r-m*+Se(t))/s;u=p*q/n;if(o==0.0&u==0.0){f=1;i=e;return f|0}else{w=+h[a>>3];v=w- +Xe(u,o);h[d>>3]=v;B=a;C=v;break}}}while(0);if(!(+h[B>>3]>=0.0)){if(!(C>0.0)){D=t;break}h[d>>3]=C+-360.0;D=t;break}else{if(!(C<0.0)){D=t;break}h[d>>3]=C+360.0;D=t;break}}else{if(j){h[g>>3]=180.0}n=+h[b+16>>3];h[b+32>>3]=n;h[b+40>>3]=+h[a>>3];h[b+48>>3]=90.0-n;D=n}}while(0);h[b+56>>3]=+h[g>>3];g=b+48|0;h[b+64>>3]=+Re(+h[g>>3]);h[b+72>>3]=+Se(+h[g>>3]);c[b>>2]=137;b=+P(+D)>90.0000000001;f=b?2:0;i=e;return f|0}function Fd(a,b,d,e,f,g,j,k,l){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;m=i;if((c[e>>2]|0)!=137?(Ed(a,e,j)|0)!=0:0){n=1;i=m;return n|0}Pe(b,d,e+40|0,f,g)|0;e=lb[c[j+1888>>2]&63](+h[f>>3],+h[g>>3],j,k,l)|0;if((e|0)==0){n=0;i=m;return n|0}n=(e|0)==1?2:3;i=m;return n|0}function Gd(a,b,d,e,f,g,j,k,l){a=a|0;b=+b;d=+d;e=e|0;f=f|0;g=g|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;m=i;if((c[j>>2]|0)!=137?(Ed(a,j,e)|0)!=0:0){n=1;i=m;return n|0}a=lb[c[e+1892>>2]&63](b,d,e,f,g)|0;if((a|0)==0){Qe(+h[f>>3],+h[g>>3],j+40|0,k,l)|0;n=0;i=m;return n|0}else{n=(a|0)==1?2:3;i=m;return n|0}return 0}function Hd(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;e=i;if((yg(b,12080)|0)==0){Id(d)|0;f=0;i=e;return f|0}if((yg(b,12088)|0)==0){Jd(d)|0;f=0;i=e;return f|0}if((yg(b,12096)|0)==0){a[d]=5128532;a[d+1|0]=20033;a[d+2|0]=78;a[d+3|0]=0;g=d+4|0;c[g>>2]=(c[g>>2]>>31&-206)+103;h[d+8>>3]=0.0;h[d+16>>3]=90.0;g=d+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}c[d+1888>>2]=1;c[d+1892>>2]=2;g=99;while(1){if(!(+h[d+(g<<3)+280>>3]==0.0)){j=g;break}k=g+ -1|0;if(!(+h[d+(g+100<<3)+280>>3]==0.0)){j=g;break}if((g|0)>0){g=k}else{j=k;break}}c[d+276>>2]=(j|0)<0?0:j;f=0;i=e;return f|0}if((yg(b,12104)|0)==0){a[d]=4674643;a[d+1|0]=18260;a[d+2|0]=71;a[d+3|0]=0;c[d+4>>2]=104;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=114.59155902616465;h[d+120>>3]=.008726646259971648}else{m=l*2.0;h[d+112>>3]=m;h[d+120>>3]=1.0/m}c[d+1888>>2]=3;c[d+1892>>2]=4;f=0;i=e;return f|0}if((yg(b,12112)|0)==0){a[d]=5130579;a[d+1|0]=20041;a[d+2|0]=78;a[d+3|0]=0;j=d+4|0;c[j>>2]=(c[j>>2]>>31&-210)+105;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;m=+h[j>>3];if(m==0.0){h[j>>3]=57.29577951308232;n=57.29577951308232}else{n=m}h[d+112>>3]=1.0/n;n=+h[d+40>>3];m=+h[d+48>>3];l=n*n+m*m;h[d+120>>3]=l;h[d+128>>3]=l+1.0;h[d+136>>3]=l+-1.0;c[d+1888>>2]=5;c[d+1892>>2]=6;f=0;i=e;return f|0}if((yg(b,12120)|0)==0){a[d]=4411969;a[d+1|0]=17234;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=106;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{m=l*3.141592653589793/180.0;h[d+112>>3]=m;h[d+120>>3]=1.0/m}c[d+1888>>2]=7;c[d+1892>>2]=8;f=0;i=e;return f|0}if((yg(b,12128)|0)==0){Kd(d)|0;f=0;i=e;return f|0}if((yg(b,12136)|0)==0){a[d]=4277594;a[d+1|0]=16709;a[d+2|0]=65;a[d+3|0]=0;c[d+4>>2]=108;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;m=+h[j>>3];if(m==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=114.59155902616465;h[d+120>>3]=.008726646259971648}else{l=m*2.0;h[d+112>>3]=l;h[d+120>>3]=1.0/l}c[d+1888>>2]=9;c[d+1892>>2]=10;f=0;i=e;return f|0}if((yg(b,12144)|0)==0){a[d]=5392705;a[d+1|0]=21065;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=109;h[d+8>>3]=0.0;h[d+16>>3]=90.0;j=d+24|0;l=+h[j>>3];if(l==0.0){h[j>>3]=57.29577951308232;o=57.29577951308232}else{o=l}l=o*2.0;j=d+112|0;h[j>>3]=l;o=+h[d+40>>3];do{if(!(o==90.0)){if(o>-90.0){m=+Re((90.0-o)*.5);n=m*m;p=+_(+m)*n/(1.0-n);h[d+120>>3]=p;n=.5-p;h[d+128>>3]=n;q=n;r=+h[j>>3];break}else{f=0;i=e;return f|0}}else{h[d+120>>3]=-.5;h[d+128>>3]=1.0;q=1.0;r=l}}while(0);h[d+136>>3]=q*r;h[d+144>>3]=1.0e-4;h[d+152>>3]=q*1.0e-4;h[d+160>>3]=57.29577951308232/q;c[d+1888>>2]=11;c[d+1892>>2]=12;f=0;i=e;return f|0}if((yg(b,12152)|0)==0){a[d]=5265731;a[d+1|0]=20569;a[d+2|0]=80;a[d+3|0]=0;c[d+4>>2]=201;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];do{if(q==0.0){h[g>>3]=57.29577951308232;r=+h[d+48>>3];h[d+112>>3]=r;if(r==0.0){f=0;i=e;return f|0}h[d+120>>3]=1.0/r;l=(r+ +h[d+40>>3])*57.29577951308232;h[d+128>>3]=l;if(l==0.0){f=0;i=e;return f|0}else{h[d+136>>3]=1.0/l;break}}else{l=+h[d+48>>3];r=q*l*3.141592653589793/180.0;h[d+112>>3]=r;if(r==0.0){f=0;i=e;return f|0}h[d+120>>3]=1.0/r;r=q*(l+ +h[d+40>>3]);h[d+128>>3]=r;if(r==0.0){f=0;i=e;return f|0}else{h[d+136>>3]=1.0/r;break}}}while(0);c[d+1888>>2]=13;c[d+1892>>2]=14;f=0;i=e;return f|0}if((yg(b,12160)|0)==0){a[d]=4277571;a[d+1|0]=16709;a[d+2|0]=65;a[d+3|0]=0;c[d+4>>2]=202;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;q=+h[j>>3];do{if(q==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;r=+h[d+40>>3];if(r<=0.0|r>1.0){f=0;i=e;return f|0}else{h[d+128>>3]=57.29577951308232/r;h[d+136>>3]=r/57.29577951308232;break}}else{h[d+112>>3]=q*3.141592653589793/180.0;h[d+120>>3]=57.29577951308232/q;r=+h[d+40>>3];if(r<=0.0|r>1.0){f=0;i=e;return f|0}else{h[d+128>>3]=q/r;h[d+136>>3]=r/q;break}}}while(0);c[d+1888>>2]=15;c[d+1892>>2]=16;f=0;i=e;return f|0}if((yg(b,12168)|0)==0){a[d]=5390659;a[d+1|0]=21057;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=203;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{r=q*3.141592653589793/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r}c[d+1888>>2]=17;c[d+1892>>2]=18;f=0;i=e;return f|0}if((yg(b,12176)|0)==0){a[d]=5391693;a[d+1|0]=21061;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=204;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;r=+h[j>>3];if(r==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{q=r*3.141592653589793/180.0;h[d+112>>3]=q;h[d+120>>3]=1.0/q}c[d+1888>>2]=19;c[d+1892>>2]=20;f=0;i=e;return f|0}if((yg(b,12184)|0)==0){a[d]=4998739;a[d+1|0]=19526;a[d+2|0]=76;a[d+3|0]=0;c[d+4>>2]=301;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0}else{r=q*3.141592653589793/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r}c[d+1888>>2]=21;c[d+1892>>2]=22;f=0;i=e;return f|0}if((yg(b,12192)|0)==0){a[d]=5390672;a[d+1|0]=21057;a[d+2|0]=82;a[d+3|0]=0;c[d+4>>2]=302;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;r=+h[j>>3];if(r==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;h[d+128>>3]=180.0;h[d+136>>3]=.005555555555555556}else{q=r*3.141592653589793;r=q/180.0;h[d+112>>3]=r;h[d+120>>3]=1.0/r;h[d+128>>3]=q;h[d+136>>3]=1.0/q}c[d+1888>>2]=23;c[d+1892>>2]=24;f=0;i=e;return f|0}if((yg(b,12200)|0)==0){a[d]=5001037;a[d+1|0]=19535;a[d+2|0]=76;a[d+3|0]=0;c[d+4>>2]=303;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;q=+h[g>>3];if(q==0.0){h[g>>3]=57.29577951308232;s=57.29577951308232}else{s=q}q=s*1.4142135623730951;h[d+112>>3]=q;h[d+120>>3]=q/90.0;h[d+128>>3]=1.0/q;h[d+136>>3]=90.0/s;h[d+144>>3]=.6366197723675814;c[d+1888>>2]=25;c[d+1892>>2]=26;f=0;i=e;return f|0}if((yg(b,12208)|0)==0){a[d]=5523777;a[d+1|0]=21577;a[d+2|0]=84;a[d+3|0]=0;c[d+4>>2]=401;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;s=+h[j>>3];if(s==0.0){h[j>>3]=57.29577951308232;t=57.29577951308232}else{t=s}s=t*2.0;q=t*s;h[d+112>>3]=q;t=1.0/(q*2.0);h[d+120>>3]=t;h[d+128>>3]=t*.25;h[d+136>>3]=1.0/s;c[d+1888>>2]=27;c[d+1892>>2]=28;f=0;i=e;return f|0}if((yg(b,12216)|0)==0){Ld(d)|0;f=0;i=e;return f|0}if((yg(b,12224)|0)==0){Md(d)|0;f=0;i=e;return f|0}if((yg(b,12232)|0)==0){Nd(d)|0;f=0;i=e;return f|0}if((yg(b,12240)|0)==0){Od(d)|0;f=0;i=e;return f|0}if((yg(b,12248)|0)==0){Pd(d)|0;f=0;i=e;return f|0}if((yg(b,12256)|0)==0){a[d]=5194576;a[d+1|0]=20291;a[d+2|0]=79;a[d+3|0]=0;c[d+4>>2]=602;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;s=+h[g>>3];if(s==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=1.0;h[d+120>>3]=1.0;h[d+128>>3]=114.59155902616465}else{t=s*3.141592653589793/180.0;h[d+112>>3]=t;h[d+120>>3]=1.0/t;h[d+128>>3]=s*2.0}c[d+1888>>2]=29;c[d+1892>>2]=30;f=0;i=e;return f|0}if((yg(b,12264)|0)==0){a[d]=4412244;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=701;g=d+8|0;j=d+24|0;c[g+0>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;s=+h[j>>3];if(s==0.0){h[j>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{t=s*3.141592653589793*.25;h[d+112>>3]=t;h[d+120>>3]=1.0/t}c[d+1888>>2]=31;c[d+1892>>2]=32;f=0;i=e;return f|0}if((yg(b,12272)|0)==0){a[d]=4412227;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=702;j=d+8|0;g=d+24|0;c[j+0>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;t=+h[g>>3];if(t==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{s=t*3.141592653589793*.25;h[d+112>>3]=s;h[d+120>>3]=1.0/s}c[d+1888>>2]=33;c[d+1892>>2]=34;f=0;i=e;return f|0}if((yg(b,12280)|0)!=0){f=1;i=e;return f|0}a[d]=4412241;a[d+1|0]=17235;a[d+2|0]=67;a[d+3|0]=0;c[d+4>>2]=703;b=d+8|0;g=d+24|0;c[b+0>>2]=0;c[b+4>>2]=0;c[b+8>>2]=0;c[b+12>>2]=0;s=+h[g>>3];if(s==0.0){h[g>>3]=57.29577951308232;h[d+112>>3]=45.0;h[d+120>>3]=.022222222222222223}else{t=s*3.141592653589793*.25;h[d+112>>3]=t;h[d+120>>3]=1.0/t}c[d+1888>>2]=35;c[d+1892>>2]=36;f=0;i=e;return f|0}function Id(b){b=b|0;var d=0,e=0,f=0.0,g=0.0,j=0,k=0,l=0,m=0.0,n=0.0;d=i;a[b]=5265985;a[b+1|0]=20570;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-202)+101;h[b+8>>3]=0.0;h[b+16>>3]=90.0;e=b+24|0;f=+h[e>>3];if(f==0.0){h[e>>3]=57.29577951308232;g=57.29577951308232}else{g=f}e=b+40|0;f=g*(+h[e>>3]+1.0);h[b+112>>3]=f;if(f==0.0){j=1;i=d;return j|0}k=b+48|0;f=+Re(+h[k>>3]);l=b+136|0;h[l>>3]=f;if(f==0.0){j=1;i=d;return j|0}h[b+128>>3]=1.0/f;f=+Se(+h[k>>3]);h[b+144>>3]=f;g=+h[l>>3];h[b+120>>3]=f/g;f=+h[e>>3];if(+P(+f)>1.0){h[b+152>>3]=+Ve(-1.0/f);m=+h[e>>3];n=+h[l>>3]}else{h[b+152>>3]=-90.0;m=f;n=g}g=m*n;h[b+160>>3]=g;l=+P(+g)<1.0;h[b+168>>3]=l?1.0:0.0;c[b+1888>>2]=37;c[b+1892>>2]=38;j=0;i=d;return j|0}function Jd(b){b=b|0;var d=0,e=0,f=0.0,g=0.0,j=0,k=0,l=0,m=0,n=0,o=0;d=i;a[b]=5266003;a[b+1|0]=20570;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-204)+102;h[b+8>>3]=0.0;h[b+16>>3]=90.0;e=b+24|0;f=+h[e>>3];if(f==0.0){h[e>>3]=57.29577951308232;g=57.29577951308232}else{g=f}h[b+112>>3]=1.0/g;j=b+40|0;g=+h[j>>3];k=b+56|0;f=g*+Se(+h[k>>3])+1.0;l=b+136|0;h[l>>3]=f;if(f==0.0){m=1;i=d;return m|0}f=+h[j>>3];g=f*+Re(+h[k>>3]);n=b+48|0;o=b+120|0;h[o>>3]=-(g*+Se(+h[n>>3]));g=+h[j>>3];f=g*+Re(+h[k>>3]);g=f*+Re(+h[n>>3]);h[b+128>>3]=g;f=+h[e>>3];h[b+144>>3]=f*+h[o>>3];h[b+152>>3]=f*g;g=+h[l>>3];h[b+160>>3]=f*g;f=g+-1.0;h[b+168>>3]=g*f+-1.0;if(+P(+f)<1.0){h[b+176>>3]=+Ve(1.0-g)}else{h[b+176>>3]=-90.0}c[b+1888>>2]=39;c[b+1892>>2]=40;m=0;i=d;return m|0}function Kd(b){b=b|0;var d=0,e=0,f=0,g=0,j=0,k=0.0,l=0.0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0.0,C=0.0,D=0.0;d=i;a[b]=5132378;a[b+1|0]=20048;a[b+2|0]=78;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-214)+107;f=b+8|0;h[f>>3]=0.0;g=b+16|0;h[g>>3]=90.0;j=b+24|0;k=+h[j>>3];if(k==0.0){h[j>>3]=57.29577951308232;l=57.29577951308232}else{l=k}m=9;while(1){if(!(+h[b+(m<<3)+32>>3]==0.0)){break}if((m|0)>0){m=m+ -1|0}else{n=6;break}}if((n|0)==6){a[b]=4411969;a[b+1|0]=17234;a[b+2|0]=67;a[b+3|0]=0;c[e>>2]=106;h[f>>3]=0.0;h[g>>3]=90.0;if(l==0.0){h[j>>3]=57.29577951308232;h[b+112>>3]=1.0;h[b+120>>3]=1.0}else{k=l*3.141592653589793/180.0;h[b+112>>3]=k;h[b+120>>3]=1.0/k}c[b+1888>>2]=7;c[b+1892>>2]=8;o=0;i=d;return o|0}c[b+272>>2]=m;c[b+1888>>2]=41;c[b+1892>>2]=42;if((m|0)<=2){o=0;i=d;return o|0}k=+h[b+40>>3];if(k<=0.0){o=1;i=d;return o|0}j=(m|0)>0;a:do{if(j){l=k;g=0;p=0.0;while(1){q=+(g|0)*3.141592653589793/180.0;r=0.0;f=m;do{r=q*r+ +(f|0)*+h[b+(f<<3)+32>>3];f=f+ -1|0}while((f|0)>0);f=g+1|0;if(r<=0.0){s=l;t=r;u=g;v=p;w=q;break a}if((f|0)<180){l=r;g=f;p=q}else{s=r;t=r;u=f;v=q;w=q;break}}}else{s=k;t=0.0;u=0;v=0.0;w=0.0}}while(0);b:do{if((u|0)==180){x=3.141592653589793}else{if(j){y=s;z=t;A=1;B=v;C=w}else{x=v-s*(w-v)/(t-s);break}while(1){k=B-y*(C-B)/(z-y);p=0.0;g=m;do{p=k*p+ +(g|0)*+h[b+(g<<3)+32>>3];g=g+ -1|0}while((g|0)>0);if(+P(+p)<1.0e-13){x=k;break b}g=p<0.0;f=A+1|0;if((f|0)<11){y=g?y:p;z=g?p:z;A=f;B=g?B:k;C=g?k:C}else{x=k;break}}}}while(0);if((m|0)>-1){A=m;C=0.0;while(1){B=x*C+ +h[b+(A<<3)+32>>3];if((A|0)>0){A=A+ -1|0;C=B}else{D=B;break}}}else{D=0.0}h[b+112>>3]=x;h[b+120>>3]=D;o=0;i=d;return o|0}function Ld(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0;d=i;a[b]=5263171;a[b+1|0]=20559;a[b+2|0]=80;a[b+3|0]=0;e=b+4|0;c[e>>2]=(c[e>>2]>>31&-1002)+501;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+Se(f);h[b+112>>3]=j;if(j==0.0){k=1;i=d;return k|0}h[b+120>>3]=1.0/j;j=+h[g>>3];f=j*+Re(+h[b+48>>3]);g=b+136|0;h[g>>3]=f;if(f==0.0){k=1;i=d;return k|0}h[b+144>>3]=1.0/f;f=1.0/+Te(+h[e>>3]);h[b+152>>3]=f;h[b+128>>3]=f*+h[g>>3];c[b+1888>>2]=43;c[b+1892>>2]=44;k=0;i=d;return k|0}function Md(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0;d=i;a[b]=4542275;a[b+1|0]=17743;a[b+2|0]=69;a[b+3|0]=0;c[b+4>>2]=502;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+h[b+48>>3];k=f-j;l=f+j;j=+Se(k);f=(j+ +Se(l))*.5;m=b+112|0;h[m>>3]=f;if(f==0.0){n=1;i=d;return n|0}h[b+120>>3]=1.0/f;o=b+136|0;h[o>>3]=+h[g>>3]/f;f=+Se(k);k=f*+Se(l)+1.0;h[b+144>>3]=k;l=+h[m>>3]*2.0;h[b+152>>3]=l;f=+h[o>>3];h[b+160>>3]=f*f*k;h[b+168>>3]=1.0/(+h[g>>3]*2.0*f);h[b+176>>3]=f*+Q(+(k+l));h[b+128>>3]=f*+Q(+(k-l*+Se(+h[e>>3])));c[b+1888>>2]=45;c[b+1892>>2]=46;n=0;i=d;return n|0}function Nd(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0,m=0,n=0.0,o=0;d=i;a[b]=4476739;a[b+1|0]=17487;a[b+2|0]=68;a[b+3|0]=0;c[b+4>>2]=503;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;j=+h[g>>3];if(j==0.0){h[g>>3]=57.29577951308232;k=57.29577951308232}else{k=j}l=b+48|0;m=+h[l>>3]==0.0;j=k*+Se(f);if(m){f=j*3.141592653589793/180.0;h[b+112>>3]=f;n=f}else{f=j*+Se(+h[l>>3]);j=f/+h[l>>3];h[b+112>>3]=j;n=j}if(n==0.0){o=1;i=d;return o|0}h[b+120>>3]=1.0/n;n=+h[g>>3];j=n*+Re(+h[l>>3]);n=j*+Re(+h[e>>3]);j=n/+h[b+112>>3];h[b+128>>3]=j;h[b+136>>3]=j+ +h[e>>3];c[b+1888>>2]=47;c[b+1892>>2]=48;o=0;i=d;return o|0}function Od(b){b=b|0;var d=0,e=0,f=0.0,g=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0;d=i;a[b]=5197635;a[b+1|0]=20303;a[b+2|0]=79;a[b+3|0]=0;c[b+4>>2]=504;h[b+8>>3]=0.0;e=b+40|0;f=+h[e>>3];h[b+16>>3]=f;g=b+24|0;if(+h[g>>3]==0.0){h[g>>3]=57.29577951308232}j=+h[b+48>>3];k=f-j;l=f+j;j=+Te((90.0-k)*.5);f=+Re(k);if(k==l){m=+Se(k);h[b+112>>3]=m;n=m}else{m=+Te((90.0-l)*.5);k=+_(+(+Re(l)/f))/+_(+(m/j));h[b+112>>3]=k;n=k}if(n==0.0){o=1;i=d;return o|0}h[b+120>>3]=1.0/n;k=+h[g>>3]*(f/n)/+R(+j,+n);g=b+136|0;h[g>>3]=k;if(k==0.0){o=1;i=d;return o|0}n=+Te((90.0- +h[e>>3])*.5);h[b+128>>3]=k*+R(+n,+(+h[b+112>>3]));h[b+144>>3]=1.0/+h[g>>3];c[b+1888>>2]=49;c[b+1892>>2]=50;o=0;i=d;return o|0}function Pd(b){b=b|0;var d=0,e=0,f=0,g=0.0,j=0.0,k=0.0,l=0,m=0;d=i;a[b]=5132098;a[b+1|0]=20047;a[b+2|0]=78;a[b+3|0]=0;c[b+4>>2]=601;e=b+8|0;f=b+24|0;c[e+0>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;g=+h[f>>3];if(g==0.0){h[f>>3]=57.29577951308232;h[b+120>>3]=1.0;f=b+40|0;j=+Re(+h[f>>3])*57.29577951308232;k=j/+Se(+h[f>>3]);h[b+128>>3]=k+ +h[f>>3];l=b+1888|0;c[l>>2]=51;m=b+1892|0;c[m>>2]=52;i=d;return 0}else{h[b+120>>3]=g*3.141592653589793/180.0;f=b+40|0;k=+Re(+h[f>>3]);j=k/+Se(+h[f>>3]);h[b+128>>3]=g*(j+ +h[f>>3]*3.141592653589793/180.0);l=b+1888|0;c[l>>2]=51;m=b+1892|0;c[m>>2]=52;i=d;return 0}return 0}function Qd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=101?(Id(d)|0)!=0:0){l=1;i=g;return l|0}m=+Re(a);n=+Re(b);o=m*+h[d+120>>3];k=d+40|0;p=+h[k>>3];q=n*o+(p+ +Se(b));if(q==0.0){l=2;i=g;return l|0}p=n*+h[d+112>>3]/q;h[e>>3]=p*+Se(a);h[f>>3]=-(m*p*+h[d+128>>3]);if((c[j>>2]|0)>0){if(+h[d+152>>3]>b){l=2;i=g;return l|0}if(+h[d+168>>3]>0.0?(p=+h[k>>3]/+Q(+(o*o+1.0)),+P(+p)<=1.0):0){m=+We(-o);o=+Ve(p);p=m-o;a=m+o+180.0;if(p>90.0){r=p+-360.0}else{r=p}if(a>90.0){s=a+-360.0}else{s=a}if((r>s?r:s)>b){l=2;i=g;return l|0}}}l=0;i=g;return l|0}function Rd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=101?(Id(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+136>>3]*b;m=+Q(+(a*a+l*l));if(m==0.0){h[e>>3]=0.0;n=90.0}else{h[e>>3]=+Xe(a,-l);l=m/(+h[d+112>>3]+ +h[d+144>>3]*b);b=l*+h[d+40>>3]/+Q(+(l*l+1.0));m=+Xe(1.0,l);if(+P(+b)>1.0){l=b<0.0?-90.0:90.0;if(+P(+l)>1.0000000000001){k=2;i=g;return k|0}else{o=l}}else{o=+Ve(b)}b=m-o;l=m+o+180.0;if(b>90.0){p=b+-360.0}else{p=b}if(l>90.0){q=l+-360.0}else{q=l}n=p>q?p:q}h[f>>3]=n;k=0;i=g;return k|0}function Sd(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=102?(Jd(d)|0)!=0:0){l=1;i=g;return l|0}m=+Re(a);n=+Se(a);a=+Re(b);o=1.0- +Se(b);k=d+136|0;p=+h[k>>3]-o;if(p==0.0){l=2;i=g;return l|0}q=d+160|0;h[e>>3]=(n*a*+h[q>>3]-o*+h[d+144>>3])/p;h[f>>3]=-(m*a*+h[q>>3]+o*+h[d+152>>3])/p;if((c[j>>2]|0)>0){if(+h[d+176>>3]>b){l=2;i=g;return l|0}if(+P(+(+h[d+40>>3]))>1.0?(p=n*+h[d+120>>3]-m*+h[d+128>>3],m=1.0/+Q(+(+h[d+168>>3]+p*p)),+P(+m)<=1.0):0){n=+Xe(p,+h[k>>3]+-1.0);p=+Ve(m);m=n-p;o=n+p+180.0;if(m>90.0){r=m+-360.0}else{r=m}if(o>90.0){s=o+-360.0}else{s=o}if((r>s?r:s)>b){l=2;i=g;return l|0}}}l=0;i=g;return l|0}function Td(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=102?(Jd(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+112>>3];m=l*a;a=l*b;b=m*m+a*a;l=+h[d+136>>3];n=(m- +h[d+120>>3])/l;o=(a- +h[d+128>>3])/l;l=m*n+a*o;do{if(!(b<1.0e-10)){p=n*n+o*o;q=p+1.0;r=l-p;s=r*r-q*(p+(b-l-l)+-1.0);if(s<0.0){k=2;i=g;return k|0}p=+Q(+s);s=(p-r)/q;t=(-r-p)/q;q=s>t?s:t;if(q>1.0){if(q+-1.0<1.0e-13){u=1.0}else{u=s-1.0e-13?-1.0:u;if(q>1.0|q<-1.0){k=2;i=g;return k|0}else{h[f>>3]=+Ve(q);v=1.0-q;break}}else{h[f>>3]=90.0- +Q(+(b/(l+1.0)))*57.29577951308232;v=b*.5}}while(0);h[e>>3]=+Xe(m-n*v,-(a-o*v));k=0;i=g;return k|0}function Ud(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+16|0;k=j;l=e+4|0;m=c[l>>2]|0;if((((m|0)>-1?m:0-m|0)|0)!=103){a[e]=5128532;a[e+1|0]=20033;a[e+2|0]=78;a[e+3|0]=0;c[l>>2]=(m>>31&-206)+103;h[e+8>>3]=0.0;h[e+16>>3]=90.0;m=e+24|0;if(+h[m>>3]==0.0){h[m>>3]=57.29577951308232}c[e+1888>>2]=1;c[e+1892>>2]=2;m=99;while(1){if(!(+h[e+(m<<3)+280>>3]==0.0)){n=m;break}o=m+ -1|0;if(!(+h[e+(m+100<<3)+280>>3]==0.0)){n=m;break}if((m|0)>0){m=o}else{n=o;break}}c[e+276>>2]=(n|0)<0?0:n}p=+Se(d);if(p<=0.0){i=j;return 2}q=+h[e+24>>3];r=q*+Re(d)/p;h[k>>3]=r*+Se(b);n=k+8|0;h[n>>3]=-(r*+Re(b));m=c[e+1880>>2]|0;if((m|0)==0){s=+h[k>>3]}else{s=+sd(m,k)}h[f>>3]=s;f=c[e+1884>>2]|0;if((f|0)==0){t=+h[n>>3];h[g>>3]=t;u=c[l>>2]|0;v=(u|0)>0;w=p<0.0;x=v&w;y=x?2:0;i=j;return y|0}else{t=+sd(f,k);h[g>>3]=t;u=c[l>>2]|0;v=(u|0)>0;w=p<0.0;x=v&w;y=x?2:0;i=j;return y|0}return 0}function Vd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0;j=i;i=i+16|0;k=j+8|0;l=j;m=e+4|0;n=c[m>>2]|0;if((((n|0)>-1?n:0-n|0)|0)==103){o=c[e+276>>2]|0}else{a[e]=5128532;a[e+1|0]=20033;a[e+2|0]=78;a[e+3|0]=0;c[m>>2]=(n>>31&-206)+103;h[e+8>>3]=0.0;h[e+16>>3]=90.0;n=e+24|0;if(+h[n>>3]==0.0){h[n>>3]=57.29577951308232}c[e+1888>>2]=1;c[e+1892>>2]=2;n=99;while(1){if(!(+h[e+(n<<3)+280>>3]==0.0)){p=n;break}m=n+ -1|0;if(!(+h[e+(n+100<<3)+280>>3]==0.0)){p=n;break}if((n|0)>0){n=m}else{p=m;break}}n=(p|0)<0?0:p;c[e+276>>2]=n;o=n}if((o|0)==0){h[k>>3]=b;h[l>>3]=d;q=b;r=d}else{Wd(e,b,d,k,l)|0;q=+h[k>>3];r=+h[l>>3]}d=+Q(+(q*q+r*r));if(d==0.0){s=0.0;h[f>>3]=s;t=e+24|0;u=+h[t>>3];v=+Xe(u,d);h[g>>3]=v;i=j;return 0}s=+Xe(q,-r);h[f>>3]=s;t=e+24|0;u=+h[t>>3];v=+Xe(u,d);h[g>>3]=v;i=j;return 0}function Wd(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,P=0.0,R=0.0,S=0.0,T=0.0,U=0.0,V=0.0,W=0.0,X=0.0,Y=0.0,Z=0.0,_=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0.0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0.0,oa=0.0,pa=0.0,qa=0.0,ra=0.0,sa=0.0,ta=0.0,ua=0.0,va=0.0,wa=0.0,xa=0.0,ya=0.0,za=0.0,Aa=0.0,Ba=0.0,Ca=0.0,Da=0.0,Ea=0.0,Fa=0.0,Ga=0.0,Ha=0.0,Ia=0.0,Ja=0.0,Ka=0.0,La=0.0,Ma=0.0,Na=0.0,Oa=0.0,Pa=0.0;g=i;j=c[a+276>>2]|0;k=+h[a+1080>>3]+ +h[a+1088>>3]*b;l=+h[a+280>>3]+ +h[a+288>>3]*d;if((j|0)!=1){m=k+ +h[a+1096>>3]*d;n=l+ +h[a+296>>3]*b;if((j|0)!=2){o=b*b;p=d*d;q=+Q(+(o+p));r=m+q*+h[a+1104>>3];s=n+q*+h[a+304>>3];if((j|0)!=3){t=r+o*+h[a+1112>>3];u=s+p*+h[a+312>>3];if((j|0)!=4){v=b*d;w=t+v*+h[a+1120>>3];x=u+v*+h[a+320>>3];if((j|0)!=5){v=w+p*+h[a+1128>>3];y=x+o*+h[a+328>>3];if((j|0)!=6){z=o*b;A=v+z*+h[a+1136>>3];B=p*d;C=y+B*+h[a+336>>3];if((j|0)!=7){D=A+o*+h[a+1144>>3]*d;E=C+p*+h[a+344>>3]*b;if((j|0)!=8){F=D+p*+h[a+1152>>3]*b;G=E+o*+h[a+352>>3]*d;if((j|0)!=9){H=F+B*+h[a+1160>>3];I=G+z*+h[a+360>>3];if((j|0)!=10){J=q*q*q;K=H+J*+h[a+1168>>3];L=I+J*+h[a+368>>3];if((j|0)!=11){M=o*o;N=K+M*+h[a+1176>>3];O=p*p;P=L+O*+h[a+376>>3];if((j|0)!=12){R=N+z*+h[a+1184>>3]*d;S=P+B*+h[a+384>>3]*b;if((j|0)!=13){T=R+p*o*+h[a+1192>>3];U=S+p*o*+h[a+392>>3];if((j|0)!=14){V=T+B*+h[a+1200>>3]*b;W=U+z*+h[a+400>>3]*d;if((j|0)!=15){X=V+O*+h[a+1208>>3];Y=W+M*+h[a+408>>3];if((j|0)!=16){Z=M*b;_=X+Z*+h[a+1216>>3];$=O*d;aa=Y+$*+h[a+416>>3];if((j|0)!=17){ba=_+M*+h[a+1224>>3]*d;ca=aa+O*+h[a+424>>3]*b;if((j|0)!=18){da=ba+p*z*+h[a+1232>>3];ea=ca+o*B*+h[a+432>>3];if((j|0)!=19){fa=da+B*o*+h[a+1240>>3];ga=ea+z*p*+h[a+440>>3];if((j|0)!=20){ha=fa+O*+h[a+1248>>3]*b;ia=ga+M*+h[a+448>>3]*d;if((j|0)!=21){ja=ha+$*+h[a+1256>>3];ka=ia+Z*+h[a+456>>3];if((j|0)!=22){la=q*q*J;J=ja+la*+h[a+1264>>3];ma=ka+la*+h[a+464>>3];if((j|0)!=23){na=Z*b;oa=J+na*+h[a+1272>>3];pa=$*d;qa=ma+pa*+h[a+472>>3];if((j|0)!=24){ra=oa+Z*+h[a+1280>>3]*d;sa=qa+$*+h[a+480>>3]*b;if((j|0)!=25){ta=ra+p*M*+h[a+1288>>3];ua=sa+o*O*+h[a+488>>3];if((j|0)!=26){va=ta+B*z*+h[a+1296>>3];wa=ua+z*B*+h[a+496>>3];if((j|0)!=27){xa=va+O*o*+h[a+1304>>3];ya=wa+M*p*+h[a+504>>3];if((j|0)!=28){za=xa+$*+h[a+1312>>3]*b;Aa=ya+Z*+h[a+512>>3]*d;if((j|0)!=29){Ba=za+pa*+h[a+1320>>3];Ca=Aa+na*+h[a+520>>3];if((j|0)!=30){Da=na*b;Ea=Ba+Da*+h[a+1328>>3];Fa=pa*d;Ga=Ca+Fa*+h[a+528>>3];if((j|0)!=31){Ha=Ea+na*+h[a+1336>>3]*d;Ia=Ga+pa*+h[a+536>>3]*b;if((j|0)!=32){Ja=Ha+p*Z*+h[a+1344>>3];Ka=Ia+o*$*+h[a+544>>3];if((j|0)!=33){La=Ja+B*M*+h[a+1352>>3];Ma=Ka+z*O*+h[a+552>>3];if((j|0)!=34){Na=La+O*z*+h[a+1360>>3];z=Ma+M*B*+h[a+560>>3];if((j|0)!=35){B=Na+$*o*+h[a+1368>>3];o=z+Z*p*+h[a+568>>3];if((j|0)!=36){p=B+pa*+h[a+1376>>3]*b;b=o+na*+h[a+576>>3]*d;if((j|0)!=37){d=p+Fa*+h[a+1384>>3];Fa=b+Da*+h[a+584>>3];if((j|0)==38){Oa=d;Pa=Fa}else{Da=q*q*la;Oa=d+Da*+h[a+1392>>3];Pa=Fa+Da*+h[a+592>>3]}}else{Oa=p;Pa=b}}else{Oa=B;Pa=o}}else{Oa=Na;Pa=z}}else{Oa=La;Pa=Ma}}else{Oa=Ja;Pa=Ka}}else{Oa=Ha;Pa=Ia}}else{Oa=Ea;Pa=Ga}}else{Oa=Ba;Pa=Ca}}else{Oa=za;Pa=Aa}}else{Oa=xa;Pa=ya}}else{Oa=va;Pa=wa}}else{Oa=ta;Pa=ua}}else{Oa=ra;Pa=sa}}else{Oa=oa;Pa=qa}}else{Oa=J;Pa=ma}}else{Oa=ja;Pa=ka}}else{Oa=ha;Pa=ia}}else{Oa=fa;Pa=ga}}else{Oa=da;Pa=ea}}else{Oa=ba;Pa=ca}}else{Oa=_;Pa=aa}}else{Oa=X;Pa=Y}}else{Oa=V;Pa=W}}else{Oa=T;Pa=U}}else{Oa=R;Pa=S}}else{Oa=N;Pa=P}}else{Oa=K;Pa=L}}else{Oa=H;Pa=I}}else{Oa=F;Pa=G}}else{Oa=D;Pa=E}}else{Oa=A;Pa=C}}else{Oa=v;Pa=y}}else{Oa=w;Pa=x}}else{Oa=t;Pa=u}}else{Oa=r;Pa=s}}else{Oa=m;Pa=n}}else{Oa=k;Pa=l}h[e>>3]=Oa;h[f>>3]=Pa;i=g;return 0}function Xd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0,o=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=104){a[e]=4674643;a[e+1|0]=18260;a[e+2|0]=71;a[e+3|0]=0;c[k>>2]=104;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=3;c[e+1892>>2]=4}m=+Se(d)+1.0;if(m==0.0){n=2;i=j;return n|0}l=+h[e+112>>3];o=l*+Re(d)/m;h[f>>3]=o*+Se(b);h[g>>3]=-(o*+Re(b));n=0;i=j;return n|0}function Yd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=104){a[e]=4674643;a[e+1|0]=18260;a[e+2|0]=71;a[e+3|0]=0;c[k>>2]=104;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=3;c[e+1892>>2]=4}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0;h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=+We(q);s=r*2.0;t=90.0-s;h[g>>3]=t;i=j;return 0}n=+Xe(b,-d);h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=+We(q);s=r*2.0;t=90.0-s;h[g>>3]=t;i=j;return 0}function Zd(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0;j=i;k=e+4|0;l=c[k>>2]|0;if((((l|0)>-1?l:0-l|0)|0)!=105){a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;c[k>>2]=(l>>31&-210)+105;h[e+8>>3]=0.0;h[e+16>>3]=90.0;l=e+24|0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;n=57.29577951308232}else{n=m}h[e+112>>3]=1.0/n;n=+h[e+40>>3];m=+h[e+48>>3];o=n*n+m*m;h[e+120>>3]=o;h[e+128>>3]=o+1.0;h[e+136>>3]=o+-1.0;c[e+1888>>2]=5;c[e+1892>>2]=6}o=(90.0- +P(+d))*3.141592653589793/180.0;if(o<1.0e-5){m=o*o*.5;if(d>0.0){p=o;q=m}else{p=o;q=2.0-m}}else{m=1.0- +Se(d);p=+Re(d);q=m}m=+Re(b);o=+Se(b);l=e+24|0;r=e+40|0;h[f>>3]=+h[l>>3]*(p*o+q*+h[r>>3]);f=e+48|0;h[g>>3]=-(+h[l>>3]*(p*m-q*+h[f>>3]));do{if((c[k>>2]|0)>0){if(+h[e+120>>3]==0.0){if(d<0.0){s=2}else{break}i=j;return s|0}else{if(d<-+We(o*+h[r>>3]-m*+h[f>>3])){s=2}else{break}i=j;return s|0}}}while(0);s=0;i=j;return s|0}function _d(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0;j=i;k=e+4|0;l=c[k>>2]|0;if((((l|0)>-1?l:0-l|0)|0)==105){m=+h[e+112>>3];n=+h[e+120>>3]}else{a[e]=5130579;a[e+1|0]=20041;a[e+2|0]=78;a[e+3|0]=0;c[k>>2]=(l>>31&-210)+105;h[e+8>>3]=0.0;h[e+16>>3]=90.0;l=e+24|0;o=+h[l>>3];if(o==0.0){h[l>>3]=57.29577951308232;p=57.29577951308232}else{p=o}o=1.0/p;h[e+112>>3]=o;p=+h[e+40>>3];q=+h[e+48>>3];r=p*p+q*q;h[e+120>>3]=r;h[e+128>>3]=r+1.0;h[e+136>>3]=r+-1.0;c[e+1888>>2]=5;c[e+1892>>2]=6;m=o;n=r}r=m*b;b=m*d;d=r*r+b*b;if(n==0.0){if(d!=0.0){s=+Xe(r,-b)}else{s=0.0}h[f>>3]=s;if(d<.5){h[g>>3]=+Ue(+Q(+d));t=0;i=j;return t|0}if(!(d<=1.0)){t=2;i=j;return t|0}h[g>>3]=+Ve(+Q(+(1.0-d)));t=0;i=j;return t|0}l=e+40|0;k=e+48|0;s=r*+h[l>>3]+b*+h[k>>3];do{if(!(d<1.0e-10)){m=+h[e+128>>3];o=s-n;q=o*o-m*(d-s-s+ +h[e+136>>3]);if(q<0.0){t=2;i=j;return t|0}p=+Q(+q);q=(p-o)/m;u=(-o-p)/m;m=q>u?q:u;if(m>1.0){if(m+-1.0<1.0e-13){v=1.0}else{v=q-1.0e-13?-1.0:v;if(m>1.0|m<-1.0){t=2;i=j;return t|0}else{h[g>>3]=+Ve(m);w=1.0-m;break}}else{h[g>>3]=90.0- +Q(+(d/(s+1.0)))*57.29577951308232;w=d*.5}}while(0);d=w*+h[k>>3]-b;b=r-w*+h[l>>3];if(d==0.0&b==0.0){h[f>>3]=0.0;t=0;i=j;return t|0}else{h[f>>3]=+Xe(b,d);t=0;i=j;return t|0}return 0}function $d(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==106){l=+h[e+112>>3];m=90.0-d;n=m*l;o=+Se(b);p=n*o;h[f>>3]=p;q=+Re(b);r=n*q;s=-r;h[g>>3]=s;i=j;return 0}a[e]=4411969;a[e+1|0]=17234;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=106;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;t=+h[k>>3];if(t==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;u=1.0}else{v=t*3.141592653589793/180.0;h[e+112>>3]=v;h[e+120>>3]=1.0/v;u=v}c[e+1888>>2]=7;c[e+1892>>2]=8;l=u;m=90.0-d;n=m*l;o=+Se(b);p=n*o;h[f>>3]=p;q=+Re(b);r=n*q;s=-r;h[g>>3]=s;i=j;return 0}function ae(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0,p=0.0,q=0.0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=106){a[e]=4411969;a[e+1|0]=17234;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=106;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0}else{m=l*3.141592653589793/180.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=7;c[e+1892>>2]=8}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0;h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=90.0-q;h[g>>3]=r;i=j;return 0}n=+Xe(b,-d);h[f>>3]=n;o=e+120|0;p=+h[o>>3];q=m*p;r=90.0-q;h[g>>3]=r;i=j;return 0}function be(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=107?(Kd(d)|0)!=0:0){l=1;i=g;return l|0}m=(90.0-b)*3.141592653589793/180.0;b=(m*(m*(m*(m*(m*(m*(m*(m*(m*(m*0.0+ +h[d+104>>3])+ +h[d+96>>3])+ +h[d+88>>3])+ +h[d+80>>3])+ +h[d+72>>3])+ +h[d+64>>3])+ +h[d+56>>3])+ +h[d+48>>3])+ +h[d+40>>3])+ +h[d+32>>3])*+h[d+24>>3];h[e>>3]=b*+Se(a);h[f>>3]=-(b*+Re(a));if((c[j>>2]|0)>0?m>+h[d+112>>3]:0){l=2;i=g;return l|0}l=0;i=g;return l|0}function ce(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=107?(Kd(d)|0)!=0:0){k=1;i=g;return k|0}j=c[d+272>>2]|0;l=+Q(+(a*a+b*b));m=l/+h[d+24>>3];if((j|0)<1){k=1;i=g;return k|0}a:do{if((j|0)==2){l=+h[d+48>>3];n=+h[d+40>>3];o=n*n-l*4.0*(+h[d+32>>3]-m);if(o<0.0){k=2;i=g;return k|0}p=+Q(+o);o=l*2.0;l=(p-n)/o;q=(-n-p)/o;o=lq?l:q}else{r=o}if(r<0.0){if(r<-1.0e-13){k=2}else{s=0.0;break}i=g;return k|0}if(r>3.141592653589793){if(r>3.141592653589893){k=2;i=g;return k|0}else{s=3.141592653589793}}else{s=r}}else if((j|0)==1){s=(m- +h[d+32>>3])/+h[d+40>>3]}else{o=+h[d+32>>3];q=+h[d+112>>3];l=+h[d+120>>3];if(ml){if(m>l+1.0e-13){k=2}else{s=q;break}i=g;return k|0}if((j|0)>-1){t=0;u=o;v=l;w=0.0;x=q}else{p=0.0-m;y=0;n=o;o=l;l=0.0;z=q;while(1){q=(o-m)/(o-n);if(!(q<.1)){if(q>.9){A=.9}else{A=q}}else{A=.1}q=z-(z-l)*A;if(m>0.0){if(m<1.0e-13){s=q;break a}else{B=0.0;C=o;D=q;E=z}}else{if(p<1.0e-13){s=q;break a}else{B=n;C=0.0;D=l;E=q}}F=y+1|0;if(!(+P(+(E-D))<1.0e-13)&(F|0)<100){y=F;n=B;o=C;l=D;z=E}else{s=q;break a}}}while(1){z=(v-m)/(v-u);if(!(z<.1)){if(z>.9){G=.9}else{G=z}}else{G=.1}z=x-(x-w)*G;y=j;l=0.0;while(1){l=z*l+ +h[d+(y<<3)+32>>3];if((y|0)<=0){break}else{y=y+ -1|0}}if(l>3]=L;h[f>>3]=90.0-s*180.0/3.141592653589793;k=0;i=g;return k|0}function de(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==108){l=+h[e+112>>3]}else{a[e]=4277594;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=108;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;m=+h[k>>3];if(m==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648;n=114.59155902616465}else{o=m*2.0;h[e+112>>3]=o;h[e+120>>3]=1.0/o;n=o}c[e+1888>>2]=9;c[e+1892>>2]=10;l=n}n=l*+Se((90.0-d)*.5);h[f>>3]=n*+Se(b);h[g>>3]=-(n*+Re(b));i=j;return 0}function ee(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0;j=i;k=e+4|0;if((c[k>>2]|0)!=108){a[e]=4277594;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=108;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;h[e+112>>3]=114.59155902616465;h[e+120>>3]=.008726646259971648}else{m=l*2.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m}c[e+1888>>2]=9;c[e+1892>>2]=10}m=+Q(+(b*b+d*d));if(m==0.0){n=0.0}else{n=+Xe(b,-d)}h[f>>3]=n;n=m*+h[e+120>>3];if(+P(+n)>1.0){if(+P(+(m- +h[e+112>>3]))<1.0e-12){o=-90.0}else{p=2;i=j;return p|0}}else{o=90.0- +Ve(n)*2.0}h[g>>3]=o;p=0;i=j;return p|0}function fe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=109){a[e]=5392705;a[e+1|0]=21065;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=109;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;l=+h[k>>3];if(l==0.0){h[k>>3]=57.29577951308232;m=57.29577951308232}else{m=l}l=m*2.0;k=e+112|0;h[k>>3]=l;m=+h[e+40>>3];do{if(!(m==90.0)){if(m>-90.0){n=+Re((90.0-m)*.5);o=n*n;p=+_(+n)*o/(1.0-o);h[e+120>>3]=p;o=.5-p;h[e+128>>3]=o;q=o;r=+h[k>>3];break}else{s=1;i=j;return s|0}}else{h[e+120>>3]=-.5;h[e+128>>3]=1.0;q=1.0;r=l}}while(0);h[e+136>>3]=q*r;h[e+144>>3]=1.0e-4;h[e+152>>3]=q*1.0e-4;h[e+160>>3]=57.29577951308232/q;c[e+1888>>2]=11;c[e+1892>>2]=12}do{if(!(d==90.0)){if(!(d>-90.0)){s=2;i=j;return s|0}q=90.0-d;r=q*.017453292519943295*.5;if(r<+h[e+144>>3]){t=r*+h[e+136>>3];break}else{r=+Re(q*.5);q=+Q(+(1.0-r*r))/r;l=+_(+r)/q;t=-(+h[e+112>>3]*(l+q*+h[e+120>>3]));break}}else{t=0.0}}while(0);h[f>>3]=t*+Se(b);h[g>>3]=-(t*+Re(b));s=0;i=j;return s|0}function ge(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0,A=0.0,B=0.0,C=0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==109){l=+h[e+112>>3]}else{a[e]=5392705;a[e+1|0]=21065;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=109;h[e+8>>3]=0.0;h[e+16>>3]=90.0;k=e+24|0;m=+h[k>>3];if(m==0.0){h[k>>3]=57.29577951308232;n=57.29577951308232}else{n=m}m=n*2.0;k=e+112|0;h[k>>3]=m;n=+h[e+40>>3];do{if(!(n==90.0)){if(n>-90.0){o=+Re((90.0-n)*.5);p=o*o;q=+_(+o)*p/(1.0-p);h[e+120>>3]=q;p=.5-q;h[e+128>>3]=p;r=p;s=+h[k>>3];break}else{t=1;i=j;return t|0}}else{h[e+120>>3]=-.5;h[e+128>>3]=1.0;r=1.0;s=m}}while(0);h[e+136>>3]=r*s;h[e+144>>3]=1.0e-4;h[e+152>>3]=r*1.0e-4;h[e+160>>3]=57.29577951308232/r;c[e+1888>>2]=11;c[e+1892>>2]=12;l=s}s=+Q(+(b*b+d*d))/l;if(s==0.0){u=0.0;v=0.0}else{do{if(!(s<+h[e+152>>3])){l=+h[e+120>>3];k=0;r=0.0;m=1.0;while(1){w=m*.5;n=+Q(+(1.0-w*w))/w;x=-(+_(+w)/n+n*l);y=k+1|0;if(s<=x){z=k;A=r;B=m;break}if((y|0)<30){k=y;r=x;m=w}else{z=y;A=x;B=w;break}}if((z|0)==30){t=2;i=j;return t|0}else{C=0;D=A;E=x;F=B;G=w}while(1){m=(E-s)/(E-D);if(!(m<.1)){if(m>.9){H=.9}else{H=m}}else{H=.1}I=G-(G-F)*H;m=+Q(+(1.0-I*I))/I;r=+_(+I)/m+m*l;m=-r;if(s>m){if(s+r<1.0e-12){J=C;break}else{K=m;L=E;M=I;N=G}}else{if(m-s<1.0e-12){J=C;break}else{K=D;L=m;M=F;N=I}}k=C+1|0;if((k|0)<100){C=k;D=K;E=L;F=M;G=N}else{J=k;break}}if((J|0)==100){t=2;i=j;return t|0}else{O=+Ue(I);break}}else{O=s*+h[e+160>>3]}}while(0);u=+Xe(b,-d);v=O}h[f>>3]=u;h[g>>3]=90.0-v*2.0;t=0;i=j;return t|0}function he(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==201){l=+h[e+40>>3]}else{a[e]=5265731;a[e+1|0]=20569;a[e+2|0]=80;a[e+3|0]=0;c[k>>2]=201;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;o=+h[e+48>>3];h[e+112>>3]=o;if(o==0.0){p=1;i=j;return p|0}h[e+120>>3]=1.0/o;q=+h[e+40>>3];r=(o+q)*57.29577951308232;h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=q;break}}else{q=+h[e+48>>3];r=n*q*3.141592653589793/180.0;h[e+112>>3]=r;if(r==0.0){p=1;i=j;return p|0}h[e+120>>3]=1.0/r;r=+h[e+40>>3];o=n*(q+r);h[e+128>>3]=o;if(o==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/o;s=r;break}}}while(0);c[e+1888>>2]=13;c[e+1892>>2]=14;l=s}s=l+ +Re(d);if(s==0.0){p=2;i=j;return p|0}h[f>>3]=+h[e+112>>3]*b;b=+h[e+128>>3];h[g>>3]=b*+Se(d)/s;p=0;i=j;return p|0}function ie(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==201){l=+h[e+120>>3]}else{a[e]=5265731;a[e+1|0]=20569;a[e+2|0]=80;a[e+3|0]=0;c[k>>2]=201;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;o=+h[e+48>>3];h[e+112>>3]=o;if(o==0.0){p=1;i=j;return p|0}q=1.0/o;h[e+120>>3]=q;r=(o+ +h[e+40>>3])*57.29577951308232;h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=q;break}}else{q=+h[e+48>>3];r=n*q*3.141592653589793/180.0;h[e+112>>3]=r;if(r==0.0){p=1;i=j;return p|0}o=1.0/r;h[e+120>>3]=o;r=n*(q+ +h[e+40>>3]);h[e+128>>3]=r;if(r==0.0){p=1;i=j;return p|0}else{h[e+136>>3]=1.0/r;s=o;break}}}while(0);c[e+1888>>2]=13;c[e+1892>>2]=14;l=s}h[f>>3]=l*b;b=+h[e+136>>3]*d;d=+Xe(b,1.0);h[g>>3]=d+ +Ve(b*+h[e+40>>3]/+Q(+(b*b+1.0)));p=0;i=j;return p|0}function je(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==202){l=+h[e+112>>3]}else{a[e]=4277571;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=202;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=+h[e+40>>3];if(o<=0.0|o>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=57.29577951308232/o;h[e+136>>3]=o/57.29577951308232;q=1.0;break}}else{o=n*3.141592653589793/180.0;h[e+112>>3]=o;h[e+120>>3]=57.29577951308232/n;r=+h[e+40>>3];if(r<=0.0|r>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=n/r;h[e+136>>3]=r/n;q=o;break}}}while(0);c[e+1888>>2]=15;c[e+1892>>2]=16;l=q}h[f>>3]=l*b;b=+h[e+128>>3];h[g>>3]=b*+Se(d);p=0;i=j;return p|0}function ke(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==202){l=+h[e+136>>3]}else{a[e]=4277571;a[e+1|0]=16709;a[e+2|0]=65;a[e+3|0]=0;c[k>>2]=202;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];do{if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=+h[e+40>>3];if(o<=0.0|o>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=57.29577951308232/o;q=o/57.29577951308232;h[e+136>>3]=q;r=q;break}}else{h[e+112>>3]=n*3.141592653589793/180.0;h[e+120>>3]=57.29577951308232/n;q=+h[e+40>>3];if(q<=0.0|q>1.0){p=1;i=j;return p|0}else{h[e+128>>3]=n/q;o=q/n;h[e+136>>3]=o;r=o;break}}}while(0);c[e+1888>>2]=15;c[e+1892>>2]=16;l=r}r=l*d;d=+P(+r);do{if(d>1.0){if(d>1.0000000000001){p=2;i=j;return p|0}else{s=r<0.0?-1.0:1.0;break}}else{s=r}}while(0);h[f>>3]=+h[e+120>>3]*b;h[g>>3]=+Ve(s);p=0;i=j;return p|0}function le(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==203){l=e+112|0;m=l;n=+h[l>>3];o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}a[e]=5390659;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=203;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;r=+h[l>>3];if(r==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;s=1.0}else{t=r*3.141592653589793/180.0;h[e+112>>3]=t;h[e+120>>3]=1.0/t;s=t}c[e+1888>>2]=17;c[e+1892>>2]=18;m=e+112|0;n=s;o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}function me(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==203){l=e+120|0;m=l;n=+h[l>>3];o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}a[e]=5390659;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=203;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;r=+h[l>>3];if(r==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;s=1.0}else{t=r*3.141592653589793/180.0;h[e+112>>3]=t;r=1.0/t;h[e+120>>3]=r;s=r}c[e+1888>>2]=17;c[e+1892>>2]=18;m=e+120|0;n=s;o=n*b;h[f>>3]=o;p=+h[m>>3];q=p*d;h[g>>3]=q;i=j;return 0}function ne(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0;j=i;k=e+4|0;if((c[k>>2]|0)!=204){a[e]=5391693;a[e+1|0]=21061;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=204;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0}else{n=m*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=19;c[e+1892>>2]=20}if(d<=-90.0|d>=90.0){o=2;i=j;return o|0}h[f>>3]=+h[e+112>>3]*b;b=+h[e+24>>3];h[g>>3]=b*+_(+(+Te((d+90.0)*.5)));o=0;i=j;return o|0}function oe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0,o=0.0,p=0.0,q=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==204){l=e+24|0;m=+h[e+120>>3]}else{a[e]=5391693;a[e+1|0]=21061;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=204;k=e+8|0;n=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;o=+h[n>>3];if(o==0.0){h[n>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;p=1.0}else{q=o*3.141592653589793/180.0;h[e+112>>3]=q;o=1.0/q;h[e+120>>3]=o;p=o}c[e+1888>>2]=19;c[e+1892>>2]=20;l=n;m=p}h[f>>3]=m*b;h[g>>3]=+We(+Z(+(d/+h[l>>3])))*2.0+-90.0;i=j;return 0}function pe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==301){l=e+112|0;m=l;n=+h[l>>3];o=n*b;p=+Re(d);q=o*p;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;t=+h[l>>3];if(t==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;u=1.0}else{v=t*3.141592653589793/180.0;h[e+112>>3]=v;h[e+120>>3]=1.0/v;u=v}c[e+1888>>2]=21;c[e+1892>>2]=22;m=e+112|0;n=u;o=n*b;p=+Re(d);q=o*p;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}function qe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==301){l=+h[e+24>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;o=57.29577951308232}else{p=n*3.141592653589793/180.0;h[e+112>>3]=p;h[e+120>>3]=1.0/p;o=n}c[e+1888>>2]=21;c[e+1892>>2]=22;l=o}o=+S(+(d/l));m=e+120|0;if(o==0.0){q=0.0;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}q=+h[m>>3]*b/o;h[f>>3]=q;r=+h[m>>3];s=r*d;h[g>>3]=s;i=j;return 0}function re(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=302){a[e]=5390672;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=302;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=180.0;h[e+136>>3]=.005555555555555556}else{n=m*3.141592653589793;m=n/180.0;h[e+112>>3]=m;h[e+120>>3]=1.0/m;h[e+128>>3]=n;h[e+136>>3]=1.0/n}c[e+1888>>2]=23;c[e+1892>>2]=24}n=+Se(d/3.0);h[f>>3]=+h[e+112>>3]*b*(1.0-n*n*4.0);h[g>>3]=n*+h[e+128>>3];i=j;return 0}function se(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==302){l=+h[e+136>>3]}else{a[e]=5390672;a[e+1|0]=21057;a[e+2|0]=82;a[e+3|0]=0;c[k>>2]=302;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=180.0;h[e+136>>3]=.005555555555555556;o=.005555555555555556}else{p=n*3.141592653589793;n=p/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;h[e+128>>3]=p;n=1.0/p;h[e+136>>3]=n;o=n}c[e+1888>>2]=23;c[e+1892>>2]=24;l=o}o=l*d;if(o>1.0|o<-1.0){q=2;i=j;return q|0}d=1.0-o*o*4.0;if(d==0.0){if(b==0.0){r=0.0}else{q=2;i=j;return q|0}}else{r=+h[e+120>>3]*b/d}h[f>>3]=r;h[g>>3]=+Ve(o)*3.0;q=0;i=j;return q|0}function te(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=303){a[e]=5001037;a[e+1|0]=19535;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=303;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;n=57.29577951308232}else{n=m}m=n*1.4142135623730951;h[e+112>>3]=m;h[e+120>>3]=m/90.0;h[e+128>>3]=1.0/m;h[e+136>>3]=90.0/n;h[e+144>>3]=.6366197723675814;c[e+1888>>2]=25;c[e+1892>>2]=26}if(+P(+d)==90.0){h[f>>3]=0.0;n=+P(+(+h[e+112>>3]));if(d<0.0){o=-n}else{o=n}h[g>>3]=o;i=j;return 0}if(d==0.0){h[f>>3]=+h[e+120>>3]*b;h[g>>3]=0.0;i=j;return 0}o=+Se(d)*3.141592653589793;l=0;d=o;n=-3.141592653589793;m=3.141592653589793;while(1){p=d-o+ +T(+d);if(p<0.0){if(p>-1.0e-13){q=d;break}else{r=d;s=m}}else{if(p<1.0e-13){q=d;break}else{r=n;s=d}}p=(r+s)*.5;k=l+1|0;if((k|0)<100){l=k;d=p;n=r;m=s}else{q=p;break}}s=q*.5;h[f>>3]=+h[e+120>>3]*b*+S(+s);h[g>>3]=+h[e+112>>3]*+T(+s);i=j;return 0}function ue(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==303){l=+h[e+24>>3]}else{a[e]=5001037;a[e+1|0]=19535;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=303;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;o=57.29577951308232}else{o=n}n=o*1.4142135623730951;h[e+112>>3]=n;h[e+120>>3]=n/90.0;h[e+128>>3]=1.0/n;h[e+136>>3]=90.0/o;h[e+144>>3]=.6366197723675814;c[e+1888>>2]=25;c[e+1892>>2]=26;l=o}o=d/l;l=2.0-o*o;if(l<=1.0e-12){if(l<-1.0e-12){p=2;i=j;return p|0}if(+P(+b)>1.0e-12){p=2;i=j;return p|0}else{q=0.0;r=0.0}}else{n=+Q(+l);q=n;r=+h[e+136>>3]*b/n}h[f>>3]=r;r=+h[e+128>>3]*d;d=+P(+r);do{if(d>1.0){if(d>1.000000000001){p=2;i=j;return p|0}else{s=(r<0.0?-1.0:1.0)+o*q/3.141592653589793;break}}else{n=+W(+r);s=n*+h[e+144>>3]+o*q/3.141592653589793}}while(0);q=+P(+s);do{if(q>1.0){if(q>1.000000000001){p=2;i=j;return p|0}else{t=s<0.0?-1.0:1.0;break}}else{t=s}}while(0);h[g>>3]=+Ve(t);p=0;i=j;return p|0}function ve(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==401){l=e+112|0}else{a[e]=5523777;a[e+1|0]=21577;a[e+2|0]=84;a[e+3|0]=0;c[k>>2]=401;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;o=57.29577951308232}else{o=n}n=o*2.0;p=o*n;m=e+112|0;h[m>>3]=p;o=1.0/(p*2.0);h[e+120>>3]=o;h[e+128>>3]=o*.25;h[e+136>>3]=1.0/n;c[e+1888>>2]=27;c[e+1892>>2]=28;l=m}n=+Re(d);o=+h[l>>3];p=b*.5;b=+Q(+(o/(n*+Re(p)+1.0)));h[f>>3]=+Se(p)*n*b*2.0;h[g>>3]=b*+Se(d);i=j;return 0}function we(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0.0,n=0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==401){l=+h[e+128>>3];m=+h[e+120>>3]}else{a[e]=5523777;a[e+1|0]=21577;a[e+2|0]=84;a[e+3|0]=0;c[k>>2]=401;k=e+8|0;n=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;o=+h[n>>3];if(o==0.0){h[n>>3]=57.29577951308232;p=57.29577951308232}else{p=o}o=p*2.0;q=p*o;h[e+112>>3]=q;p=1.0/(q*2.0);h[e+120>>3]=p;q=p*.25;h[e+128>>3]=q;h[e+136>>3]=1.0/o;c[e+1888>>2]=27;c[e+1892>>2]=28;l=q;m=p}p=1.0-b*b*l-d*d*m;if(p<0.0){if(p<-1.0e-13){r=2;i=j;return r|0}else{s=0.0}}else{s=p}p=+Q(+s);s=p*d/+h[e+24>>3];d=+P(+s);do{if(d>1.0){if(d>1.0000000000001){r=2;i=j;return r|0}else{t=s<0.0?-1.0:1.0;break}}else{t=s}}while(0);s=p*p*2.0+-1.0;d=p*b*+h[e+136>>3];if(s==0.0&d==0.0){u=0.0}else{u=+Xe(d,s)*2.0}h[f>>3]=u;h[g>>3]=+Ve(t);r=0;i=j;return r|0}function xe(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0,p=0.0,q=0.0;g=i;j=d+4|0;k=c[j>>2]|0;if((((k|0)>-1?k:0-k|0)|0)!=501?(Ld(d)|0)!=0:0){l=1;i=g;return l|0}m=b- +h[d+40>>3];b=+Re(m);if(b==0.0){l=2;i=g;return l|0}k=d+112|0;n=+h[k>>3]*a;o=d+128|0;a=+h[o>>3];p=+h[d+136>>3];q=a-p*+Se(m)/b;h[e>>3]=q*+Se(n);b=+h[o>>3];h[f>>3]=b-q*+Re(n);if((c[j>>2]|0)>0?q*+h[k>>3]<0.0:0){l=2;i=g;return l|0}l=0;i=g;return l|0}function ye(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0;g=i;j=c[d+4>>2]|0;if((((j|0)>-1?j:0-j|0)|0)!=501?(Ld(d)|0)!=0:0){k=1;i=g;return k|0}l=+h[d+128>>3]-b;b=+Q(+(a*a+l*l));j=d+40|0;if(+h[j>>3]<0.0){m=-b}else{m=b}if(m==0.0){n=0.0}else{n=+Xe(a/m,l/m)}h[e>>3]=n*+h[d+120>>3];n=+h[j>>3];h[f>>3]=n+ +We(+h[d+152>>3]-m*+h[d+144>>3]);k=0;i=g;return k|0}function ze(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0;g=i;if((c[d+4>>2]|0)!=502?(Md(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+112>>3]*a;if(b==-90.0){l=+h[d+176>>3]}else{a=+h[d+136>>3];m=+h[d+144>>3];n=+h[d+152>>3];l=a*+Q(+(m-n*+Se(b)))}h[e>>3]=l*+Se(k);b=+h[d+128>>3];h[f>>3]=b-l*+Re(k);j=0;i=g;return j|0}function Ae(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0;g=i;if((c[d+4>>2]|0)!=502?(Md(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){m=0.0}else{m=+Xe(a/l,k/l)}h[e>>3]=m*+h[d+120>>3];if(+P(+(l- +h[d+176>>3]))<1.0e-12){h[f>>3]=-90.0;j=0;i=g;return j|0}m=(+h[d+160>>3]-l*l)*+h[d+168>>3];if(!(+P(+m)>1.0)){h[f>>3]=+Ve(m);j=0;i=g;return j|0}if(+P(+(m+-1.0))<1.0e-12){h[f>>3]=90.0;j=0;i=g;return j|0}if(!(+P(+(m+1.0))<1.0e-12)){j=2;i=g;return j|0}h[f>>3]=-90.0;j=0;i=g;return j|0}function Be(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0;g=i;if((c[d+4>>2]|0)!=503?(Nd(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+112>>3]*a;a=+h[d+136>>3]-b;h[e>>3]=a*+Se(k);b=+h[d+128>>3];h[f>>3]=b-a*+Re(k);j=0;i=g;return j|0}function Ce(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0;g=i;if((c[d+4>>2]|0)!=503?(Nd(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){m=0.0}else{m=+Xe(a/l,k/l)}h[e>>3]=m*+h[d+120>>3];h[f>>3]=+h[d+136>>3]-l;j=0;i=g;return j|0}function De(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0,l=0.0,m=0.0,n=0.0;g=i;if((c[d+4>>2]|0)!=504?(Od(d)|0)!=0:0){j=1;i=g;return j|0}k=d+112|0;l=+h[k>>3];m=l*a;if(b==-90.0){if(l<0.0){n=0.0}else{j=2;i=g;return j|0}}else{l=+h[d+136>>3];a=+Te((90.0-b)*.5);n=l*+R(+a,+(+h[k>>3]))}h[e>>3]=n*+Se(m);a=+h[d+128>>3];h[f>>3]=a-n*+Re(m);j=0;i=g;return j|0}function Ee(a,b,d,e,f){a=+a;b=+b;d=d|0;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0.0,m=0.0,n=0;g=i;if((c[d+4>>2]|0)!=504?(Od(d)|0)!=0:0){j=1;i=g;return j|0}k=+h[d+128>>3]-b;b=+Q(+(a*a+k*k));if(+h[d+40>>3]<0.0){l=-b}else{l=b}if(l==0.0){h[e>>3]=+h[d+120>>3]*0.0;if(+h[d+112>>3]<0.0){m=-90.0}else{j=2;i=g;return j|0}}else{b=+Xe(a/l,k/l);n=d+120|0;h[e>>3]=b*+h[n>>3];m=90.0- +We(+R(+(l*+h[d+144>>3]),+(+h[n>>3])))*2.0}h[f>>3]=m;j=0;i=g;return j|0}function Fe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0;j=i;k=e+4|0;l=c[k>>2]|0;if(!(+h[e+40>>3]==0.0)){if((l|0)!=601){Pd(e)|0}m=e+128|0;n=+h[m>>3]- +h[e+120>>3]*d;o=+h[e+24>>3]*b;p=o*+Re(d)/n;h[f>>3]=n*+Se(p);o=+h[m>>3];q=o-n*+Re(p);h[g>>3]=q;i=j;return 0}if((l|0)==301){l=e+112|0;r=l;s=+h[l>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[k>>2]=301;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;p=+h[l>>3];if(p==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;t=1.0}else{n=p*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;t=n}c[e+1888>>2]=21;c[e+1892>>2]=22;r=e+112|0;s=t}h[f>>3]=s*b*+Re(d);q=+h[r>>3]*d;h[g>>3]=q;i=j;return 0}function Ge(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0;j=i;k=e+40|0;l=+h[k>>3];m=e+4|0;n=c[m>>2]|0;if(l==0.0){if((n|0)==301){o=+h[e+24>>3]}else{a[e]=4998739;a[e+1|0]=19526;a[e+2|0]=76;a[e+3|0]=0;c[m>>2]=301;m=e+8|0;p=e+24|0;c[m+0>>2]=0;c[m+4>>2]=0;c[m+8>>2]=0;c[m+12>>2]=0;q=+h[p>>3];if(q==0.0){h[p>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;r=57.29577951308232}else{s=q*3.141592653589793/180.0;h[e+112>>3]=s;h[e+120>>3]=1.0/s;r=q}c[e+1888>>2]=21;c[e+1892>>2]=22;o=r}r=+S(+(d/o));p=e+120|0;if(r==0.0){t=0.0}else{t=+h[p>>3]*b/r}h[f>>3]=t;h[g>>3]=+h[p>>3]*d;i=j;return 0}else{if((n|0)==601){u=l}else{Pd(e)|0;u=+h[k>>3]}k=e+128|0;l=+h[k>>3];t=l-d;d=+Q(+(b*b+t*t));if(u<0.0){v=-d}else{v=d}if(v==0.0){w=l;x=0.0}else{l=+Xe(b/v,t/v);w=+h[k>>3];x=l}l=(w-v)/+h[e+120>>3];h[g>>3]=l;w=+Re(l);if(w==0.0){y=0.0}else{y=x*(v/+h[e+24>>3])/w}h[f>>3]=y;i=j;return 0}return 0}function He(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=602){a[e]=5194576;a[e+1|0]=20291;a[e+2|0]=79;a[e+3|0]=0;c[k>>2]=602;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=114.59155902616465}else{n=m*3.141592653589793/180.0;h[e+112>>3]=n;h[e+120>>3]=1.0/n;h[e+128>>3]=m*2.0}c[e+1888>>2]=29;c[e+1892>>2]=30}m=+Re(d);n=+Se(d);o=n*b;if(n==0.0){h[f>>3]=+h[e+112>>3]*b;p=0.0;h[g>>3]=p;i=j;return 0}else{b=m/n;l=e+24|0;n=b*+h[l>>3];h[f>>3]=n*+Se(o);n=+h[l>>3];p=n*(d*3.141592653589793/180.0+b*(1.0- +Re(o)));h[g>>3]=p;i=j;return 0}return 0}function Ie(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0,y=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==602){l=+h[e+120>>3]}else{a[e]=5194576;a[e+1|0]=20291;a[e+2|0]=79;a[e+3|0]=0;c[k>>2]=602;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=1.0;h[e+120>>3]=1.0;h[e+128>>3]=114.59155902616465;o=1.0}else{p=n*3.141592653589793/180.0;h[e+112>>3]=p;q=1.0/p;h[e+120>>3]=q;h[e+128>>3]=n*2.0;o=q}c[e+1888>>2]=29;c[e+1892>>2]=30;l=o}o=+P(+(l*d));if(o<1.0e-12){h[f>>3]=l*b;h[g>>3]=0.0;i=j;return 0}if(+P(+(o+-90.0))<1.0e-12){h[f>>3]=0.0;h[g>>3]=d<0.0?-90.0:90.0;i=j;return 0}o=d>0.0?90.0:-90.0;l=b*b;m=e+112|0;q=d-o*+h[m>>3];k=e+128|0;n=-999.0;p=l+q*q;r=0;q=0.0;s=o;while(1){if(n<-100.0){t=(q+s)*.5}else{o=p/(p-n);if(!(o<.1)){if(o>.9){u=.9}else{u=o}}else{u=.1}t=s-(s-q)*u}h[g>>3]=t;v=d-t*+h[m>>3];w=+Te(t);o=l+v*(v- +h[k>>3]/w);if(+P(+o)<1.0e-12){break}if(+P(+(s-q))<1.0e-12){break}x=o>0.0;y=+h[g>>3];r=r+1|0;if((r|0)>=64){break}else{n=x?n:o;p=x?o:p;q=x?q:y;s=x?y:s}}s=+h[e+24>>3]-w*v;v=w*b;if(s==0.0&v==0.0){h[f>>3]=0.0;i=j;return 0}else{b=+Xe(v,s);h[f>>3]=b/+Se(+h[g>>3]);i=j;return 0}return 0}function Je(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=701){a[e]=4412244;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=701;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=31;c[e+1892>>2]=32}n=+Re(d);m=n*+Re(b);o=n*+Se(b);b=+Se(d);l=m>b;d=l?m:b;k=o>d;n=k?o:d;d=-m;p=n1.0){if(u>1.000000000001){z=2;i=j;return z|0}else{A=w<0.0?-1.0:1.0;break}}else{A=w}}while(0);w=+P(+y);do{if(w>1.0){if(w>1.000000000001){z=2;i=j;return z|0}else{B=y<0.0?-1.0:1.0;break}}else{B=y}}while(0);l=e+112|0;h[f>>3]=(v+A)*+h[l>>3];h[g>>3]=(x+B)*+h[l>>3];z=0;i=j;return z|0}function Ke(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==701){l=+h[e+120>>3]}else{a[e]=4412244;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=701;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=31;c[e+1892>>2]=32;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){o=r+-4.0;d=-1.0/+Q(+(b*b+(o*o+1.0)));s=d;t=o*d;u=-(b*d);break}if(r>1.0){d=r+-2.0;o=1.0/+Q(+(b*b+(d*d+1.0)));s=-(d*o);t=o;u=b*o;break}if(b>1.0){o=b+-2.0;d=1.0/+Q(+(o*o+(r*r+1.0)));s=-(o*d);t=r*d;u=d;break}if(b<-1.0){d=b+2.0;o=-1.0/+Q(+(d*d+(r*r+1.0)));l=-o;s=d*l;t=r*l;u=o;break}else{o=1.0/+Q(+(b*b+(r*r+1.0)));s=o;t=r*o;u=b*o;break}}else{o=r+-6.0;l=-1.0/+Q(+(b*b+(o*o+1.0)));d=-l;s=o*d;t=l;u=b*d}}while(0);if(s==0.0&t==0.0){v=0.0}else{v=+Xe(t,s)}h[f>>3]=v;h[g>>3]=+Ve(u);q=0;i=j;return q|0}function Le(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0,E=0.0,F=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=702){a[e]=4412227;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=702;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=33;c[e+1892>>2]=34}n=+Re(d);m=n*+Re(b);o=n*+Se(b);b=+Se(d);l=m>b;d=l?m:b;k=o>d;n=k?o:d;d=-m;p=n1.0e-16){A=u*u}else{A=0.0}if(w>1.0e-16){B=w*w}else{B=0.0}if(b>1.0e-16){C=u*w*.15384112298488617}else{C=0.0}b=o*(u+m*(u*(-.15959623456001282-m*(u*-.021776249632239342+.07591962069272995))+(w*(u*.004869491793215275+m*-.1316167116165161+n*(B*.10695946961641312+(A*-.1782512068748474+(u*.08097013086080551+.14118963479995728+w*-.2815285325050354+C))))+1.374848484992981)));o=y*(w+n*(w*(-.15959623456001282-n*(w*-.021776249632239342+.07591962069272995))+(u*(w*.004869491793215275+n*-.1316167116165161+m*(A*.10695946961641312+(B*-.1782512068748474+(u*-.2815285325050354+(w*.08097013086080551+.14118963479995728)+C))))+1.374848484992981)));C=+P(+b);do{if(C>1.0){if(C>1.0000001000000012){D=2;i=j;return D|0}else{E=b<0.0?-1.0:1.0;break}}else{E=b}}while(0);b=+P(+o);do{if(b>1.0){if(b>1.0000001000000012){D=2;i=j;return D|0}else{F=o<0.0?-1.0:1.0;break}}else{F=o}}while(0);l=e+112|0;h[f>>3]=(x+E)*+h[l>>3];h[g>>3]=+h[l>>3]*(z+F);D=0;i=j;return D|0}function Me(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==702){l=+h[e+120>>3]}else{a[e]=4412227;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=702;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=33;c[e+1892>>2]=34;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){s=3;t=r+-4.0;u=b;break}if(r>1.0){s=2;t=r+-2.0;u=b;break}if(b>1.0){s=0;t=r;u=b+-2.0;break}if(b<-1.0){s=5;t=r;u=b+2.0}else{s=1;t=r;u=b}}else{s=4;t=r+-6.0;u=b}}while(0);b=t*t;r=u*u;o=t;t=o+o*(1.0-b)*(b*(b*(b*(b*(b*(b*.025843750685453415+.25795793533325195)+-.6293006539344788)+.5485238432884216)+-.22797055542469025)+-.07629968971014023)+-.2729269564151764+r*(b*(b*(b*(b*(b*-.5302233695983887+1.715475082397461)+-1.7411445379257202)+.48051509261131287)+-.014715650118887424)+-.028194520622491837+r*(b*(b*(b*(b*-.8318046927452087+.9893810153007507)+.30803316831588745)+-.5680093765258789)+.27058160305023193+r*(b*(b*(b*.08693841099739075+-.9367857575416565)+1.5088008642196655)+-.6044155955314636+r*(b*(b*.3388744592666626+-1.4160192012786865)+.934120774269104+r*(r*.14381584525108337+(b*.5203223824501038+-.6391530632972717)))))));o=u;u=o+o*(1.0-r)*(r*(r*(r*(r*(r*(r*.025843750685453415+.25795793533325195)+-.6293006539344788)+.5485238432884216)+-.22797055542469025)+-.07629968971014023)+-.2729269564151764+b*(r*(r*(r*(r*(r*-.5302233695983887+1.715475082397461)+-1.7411445379257202)+.48051509261131287)+-.014715650118887424)+-.028194520622491837+b*(r*(r*(r*(r*-.8318046927452087+.9893810153007507)+.30803316831588745)+-.5680093765258789)+.27058160305023193+b*(r*(r*(r*.08693841099739075+-.9367857575416565)+1.5088008642196655)+-.6044155955314636+b*(r*(r*.3388744592666626+-1.4160192012786865)+.934120774269104+b*(r*.5203223824501038+-.6391530632972717+b*.14381584525108337))))));switch(s|0){case 1:{b=1.0/+Q(+(u*u+t*t+1.0));v=b;w=t*b;x=u*b;break};case 4:{b=-1.0/+Q(+(u*u+t*t+1.0));v=-t*b;w=b;x=-u*b;break};case 0:{b=1.0/+Q(+(u*u+t*t+1.0));v=-u*b;w=t*b;x=b;break};case 5:{b=-1.0/+Q(+(u*u+t*t+1.0));v=-u*b;w=-t*b;x=b;break};case 3:{b=-1.0/+Q(+(u*u+t*t+1.0));v=b;w=t*b;x=-u*b;break};case 2:{b=1.0/+Q(+(u*u+t*t+1.0));v=-t*b;w=b;x=u*b;break};default:{v=0.0;w=0.0;x=0.0}}if(v==0.0&w==0.0){y=0.0}else{y=+Xe(w,v)}h[f>>3]=y;h[g>>3]=+Ve(x);q=0;i=j;return q|0}function Ne(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0,t=0.0,u=0,v=0.0,w=0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0;j=i;k=e+4|0;if((c[k>>2]|0)!=703){a[e]=4412241;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=703;k=e+8|0;l=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;m=+h[l>>3];if(m==0.0){h[l>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223}else{n=m*3.141592653589793*.25;h[e+112>>3]=n;h[e+120>>3]=1.0/n}c[e+1888>>2]=35;c[e+1892>>2]=36}if(+P(+d)==90.0){h[f>>3]=0.0;n=+P(+(+h[e+112>>3]*2.0));if(d<0.0){o=-n}else{o=n}h[g>>3]=o;p=0;i=j;return p|0}o=+Re(d);n=o*+Re(b);m=o*+Se(b);o=+Se(d);l=n>o;q=l?n:o;k=m>q;r=k?m:q;q=-n;s=r180.0){z=y+-360.0}else{z=y}y=z*.017453292519943295;A=o;B=(v*v+y*y)*.5;C=0.0;D=m;E=0.0}else{A=o;B=x;C=0.0;D=m;E=0.0}break};case 3:{if(x<1.0e-8){y=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v<0.0){F=v+360.0}else{F=v}v=(180.0-F)*3.141592653589793/180.0;A=o;B=(y*y+v*v)*.5;C=4.0;D=r;E=0.0}else{A=o;B=x;C=4.0;D=r;E=0.0}break};case 0:{if(x<1.0e-8){r=(90.0-d)*3.141592653589793/180.0;A=q;B=r*r*.5;C=0.0;D=m;E=2.0}else{A=q;B=x;C=0.0;D=m;E=2.0}break};case 2:{if(x<1.0e-8){r=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v<-180.0){G=v+360.0}else{G=v}v=(90.0-G)*3.141592653589793/180.0;A=o;B=(r*r+v*v)*.5;C=2.0;D=q;E=0.0}else{A=o;B=x;C=2.0;D=q;E=0.0}break};case 4:{if(x<1.0e-8){q=d*3.141592653589793/180.0;v=+qa(+b,360.0);if(v>180.0){H=v+-360.0}else{H=v}v=H*((H+90.0)*3.141592653589793/180.0);A=o;B=(q*q+v*v)*.5;C=6.0;D=n;E=0.0}else{A=o;B=x;C=6.0;D=n;E=0.0}break};case 5:{if(x<1.0e-8){o=(d+90.0)*3.141592653589793/180.0;A=n;B=o*o*.5;C=0.0;D=m;E=-2.0}else{A=n;B=x;C=0.0;D=m;E=-2.0}break};default:{A=0.0;B=x;C=0.0;D=0.0;E=0.0}}do{if(!(D==0.0&A==0.0)){x=+P(+A);if(x<=-D){m=A/D;n=m*m+1.0;o=-+Q(+(B/(1.0-1.0/+Q(+(n+1.0)))));d=+We(m);I=o;J=o/15.0*(d- +Ve(m/+Q(+(n+n))));break}if(D>=x){x=A/D;n=x*x+1.0;m=+Q(+(B/(1.0-1.0/+Q(+(n+1.0)))));d=+We(x);I=m;J=m/15.0*(d- +Ve(x/+Q(+(n+n))));break}n=+P(+D);if(n<-A){x=D/A;d=x*x+1.0;m=-+Q(+(B/(1.0-1.0/+Q(+(d+1.0)))));o=+We(x);I=m/15.0*(o- +Ve(x/+Q(+(d+d))));J=m;break}if(A>n){n=D/A;m=n*n+1.0;d=+Q(+(B/(1.0-1.0/+Q(+(m+1.0)))));x=+We(n);I=d/15.0*(x- +Ve(n/+Q(+(m+m))));J=d}else{I=0.0;J=0.0}}else{I=0.0;J=0.0}}while(0);B=+P(+I);do{if(B>1.0){if(B>1.000000000001){p=2;i=j;return p|0}else{K=I<0.0?-1.0:1.0;break}}else{K=I}}while(0);I=+P(+J);do{if(I>1.0){if(I>1.000000000001){p=2;i=j;return p|0}else{L=J<0.0?-1.0:1.0;break}}else{L=J}}while(0);l=e+112|0;h[f>>3]=(C+K)*+h[l>>3];h[g>>3]=(E+L)*+h[l>>3];p=0;i=j;return p|0}function Oe(b,d,e,f,g){b=+b;d=+d;e=e|0;f=f|0;g=g|0;var j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0.0,N=0.0,O=0.0,R=0.0,S=0.0,T=0.0,U=0.0,V=0.0,W=0.0,X=0.0;j=i;k=e+4|0;if((c[k>>2]|0)==703){l=+h[e+120>>3]}else{a[e]=4412241;a[e+1|0]=17235;a[e+2|0]=67;a[e+3|0]=0;c[k>>2]=703;k=e+8|0;m=e+24|0;c[k+0>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;n=+h[m>>3];if(n==0.0){h[m>>3]=57.29577951308232;h[e+112>>3]=45.0;h[e+120>>3]=.022222222222222223;o=.022222222222222223}else{p=n*3.141592653589793*.25;h[e+112>>3]=p;n=1.0/p;h[e+120>>3]=n;o=n}c[e+1888>>2]=35;c[e+1892>>2]=36;l=o}o=l*b;b=l*d;d=+P(+o);if(!(d<=1.0)){if(d>7.0){q=2;i=j;return q|0}if(+P(+b)>1.0){q=2;i=j;return q|0}}else{if(+P(+b)>3.0){q=2;i=j;return q|0}}if(o<-1.0){r=o+8.0}else{r=o}do{if(!(r>5.0)){if(r>3.0){s=3;t=r+-4.0;u=b;break}if(r>1.0){s=2;t=r+-2.0;u=b;break}if(b>1.0){s=0;t=r;u=b+-2.0;break}if(b<-1.0){s=5;t=r;u=b+2.0}else{s=1;t=r;u=b}}else{s=4;t=r+-6.0;u=b}}while(0);e=+P(+t)>+P(+u);if(e){if(t==0.0){v=0.0;w=1.0;x=0.0;y=1.0;z=30}else{b=u*15.0/t;r=+Se(b);o=r/(+Re(b)+-.7071067811865475);b=o*o+1.0;A=t*t*(1.0-1.0/+Q(+(b+1.0)));B=o;C=b;z=28}}else{if(u==0.0){v=0.0;w=1.0;x=0.0;y=1.0;z=30}else{b=t*15.0/u;o=+Se(b);r=o/(+Re(b)+-.7071067811865475);b=r*r+1.0;A=u*u*(1.0-1.0/+Q(+(b+1.0)));B=r;C=b;z=28}}if((z|0)==28){b=1.0-A;if(b<-1.0){if(b<-1.000000000001){q=2;i=j;return q|0}else{D=B;E=-1.0;F=0.0}}else{v=B;w=b;x=A;y=C;z=30}}if((z|0)==30){D=v;E=w;F=+Q(+(x*(2.0-x)/y))}a:do{switch(s|0){case 2:{if(e){if(t>0.0){G=-F}else{G=F}H=G;I=E;J=-(D*G);break a}else{if(u<0.0){K=-F}else{K=F}H=-(D*K);I=E;J=K;break a}break};case 3:{y=-E;if(e){if(t>0.0){L=-F}else{L=F}H=y;I=L;J=-(D*L);break a}else{if(u<0.0){M=-F}else{M=F}H=y;I=-(D*M);J=M;break a}break};case 1:{if(e){if(t<0.0){N=-F}else{N=F}H=E;I=N;J=D*N;break a}else{if(u<0.0){O=-F}else{O=F}H=E;I=D*O;J=O;break a}break};case 5:{y=-E;if(e){if(t<0.0){R=-F}else{R=F}H=D*R;I=R;J=y;break a}else{if(u<0.0){S=-F}else{S=F}H=S;I=D*S;J=y;break a}break};case 4:{y=-E;if(e){if(t<0.0){T=-F}else{T=F}H=T;I=y;J=D*T;break a}else{if(u<0.0){U=-F}else{U=F}H=D*U;I=y;J=U;break a}break};case 0:{if(e){if(t<0.0){V=-F}else{V=F}H=-(D*V);I=V;J=E;break a}else{if(u>0.0){W=-F}else{W=F}H=W;I=-(D*W);J=E;break a}break};default:{H=0.0;I=0.0;J=0.0}}}while(0);if(H==0.0&I==0.0){X=0.0}else{X=+Xe(I,H)}h[f>>3]=X;h[g>>3]=+Ve(J);q=0;i=j;return q|0}function Pe(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;f=i;g=+Re(b);j=+Se(b);k=a- +h[c>>3];a=+Re(k);l=+Se(k);m=c+32|0;n=c+24|0;o=j*+h[m>>3]-a*g*+h[n>>3];if(+P(+o)<1.0e-5){p=+Re(+h[c+8>>3]+b);q=(1.0-a)*g*+h[n>>3]-p}else{q=o}o=g*l;if(q!=0.0|o!=-0.0){r=+Xe(-o,q)}else{r=k+-180.0}l=r+ +h[c+16>>3];h[d>>3]=l;if(!(l>180.0)){if(l<-180.0){h[d>>3]=l+360.0}}else{h[d>>3]=l+-360.0}if(+qa(+k,180.0)==0.0){k=a*+h[c+8>>3]+b;if(k>90.0){s=180.0-k}else{s=k}h[e>>3]=s;if(!(s<-90.0)){i=f;return 0}h[e>>3]=-180.0-s;i=f;return 0}s=j*+h[n>>3]+a*g*+h[m>>3];if(!(+P(+s)>.99)){h[e>>3]=+Ve(s);i=f;return 0}g=+Ue(+Q(+(o*o+q*q)));if(s<0.0){h[e>>3]=-g;i=f;return 0}else{h[e>>3]=g;i=f;return 0}return 0}function Qe(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;var f=0,g=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;f=i;g=+Re(b);j=+Se(b);k=a- +h[c+16>>3];a=+Re(k);l=+Se(k);m=c+32|0;n=c+24|0;o=j*+h[m>>3]-a*g*+h[n>>3];if(+P(+o)<1.0e-5){p=+Re(+h[c+8>>3]+b);q=(1.0-a)*g*+h[n>>3]-p}else{q=o}o=g*l;if(q!=0.0|o!=-0.0){r=+Xe(-o,q)}else{r=k+180.0}l=r+ +h[c>>3];h[d>>3]=l;if(!(+h[c>>3]>=0.0)){if(l>0.0){r=l+-360.0;h[d>>3]=r;s=r}else{s=l}}else{if(l<0.0){r=l+360.0;h[d>>3]=r;s=r}else{s=l}}if(!(s>360.0)){if(s<-360.0){h[d>>3]=s+360.0}}else{h[d>>3]=s+-360.0}if(+qa(+k,180.0)==0.0){k=a*+h[c+8>>3]+b;if(k>90.0){t=180.0-k}else{t=k}h[e>>3]=t;if(!(t<-90.0)){i=f;return 0}h[e>>3]=-180.0-t;i=f;return 0}t=j*+h[n>>3]+a*g*+h[m>>3];if(!(+P(+t)>.99)){h[e>>3]=+Ve(t);i=f;return 0}g=+Ue(+Q(+(o*o+q*q)));if(t<0.0){h[e>>3]=-g;i=f;return 0}else{h[e>>3]=g;i=f;return 0}return 0}function Re(a){a=+a;var b=0,c=0.0,d=0.0,e=0.0;b=i;c=+qa(+a,360.0);d=+P(+c);if(!(c==0.0)){if(!(d==90.0)){if(!(d==180.0)){if(d==270.0){e=0.0}else{e=+S(+(a*.017453292519943295))}}else{e=-1.0}}else{e=0.0}}else{e=1.0}i=b;return+e}function Se(a){a=+a;var b=0,c=0.0,d=0.0;b=i;c=+qa(+(a+-90.0),360.0);if(!(c==0.0)){if(!(c==90.0)){if(!(c==180.0)){if(c==270.0){d=0.0}else{d=+T(+(a*.017453292519943295))}}else{d=-1.0}}else{d=0.0}}else{d=1.0}i=b;return+d}function Te(a){a=+a;var b=0,c=0.0,d=0.0;b=i;c=+qa(+a,360.0);if(!(c==0.0)?!(+P(+c)==180.0):0){if(!(c==45.0|c==225.0)){if(c==-135.0|c==-315.0){d=-1.0}else{d=+U(+(a*.017453292519943295))}}else{d=1.0}}else{d=0.0}i=b;return+d}function Ue(a){a=+a;var b=0,c=0.0,d=0;b=i;if(!(a>=1.0)){if(!(a==0.0)){if(a<=-1.0&a+1.0>-1.0e-10){c=180.0}else{d=5}}else{c=90.0}}else{if(a+-1.0<1.0e-10){c=0.0}else{d=5}}if((d|0)==5){c=+V(+a)*57.29577951308232}i=b;return+c}function Ve(a){a=+a;var b=0,c=0.0,d=0;b=i;if(!(a<=-1.0)){if(!(a==0.0)){if(a>=1.0&a+-1.0<1.0e-10){c=90.0}else{d=5}}else{c=0.0}}else{if(a+1.0>-1.0e-10){c=-90.0}else{d=5}}if((d|0)==5){c=+W(+a)*57.29577951308232}i=b;return+c}function We(a){a=+a;var b=0,c=0.0;b=i;if(!(a==-1.0)){if(!(a==0.0)){if(a==1.0){c=45.0}else{c=+X(+a)*57.29577951308232}}else{c=0.0}}else{c=-45.0}i=b;return+c}function Xe(a,b){a=+a;b=+b;var c=0,d=0.0,e=0;c=i;if(a==0.0){if(!(b>=0.0)){if(b<0.0){d=180.0}else{e=7}}else{d=0.0}}else{if(b==0.0){if(!(a>0.0)){if(a<0.0){d=-90.0}else{e=7}}else{d=90.0}}else{e=7}}if((e|0)==7){d=+Y(+a,+b)*57.29577951308232}i=c;return+d}function Ye(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;i=i+32|0;e=d;f=d+8|0;if((c[a+5968>>2]|0)!=1){i=d;return}g=a+3324|0;if((c[g>>2]|0)==2){c[g>>2]=3;c[a+5976>>2]=0;c[a+6784>>2]=0;c[a+7592>>2]=0;c[a+8400>>2]=0;i=d;return}g=a+5976|0;if((Ec(b,12288,g)|0)!=0){h=c[g>>2]|0;g=(h|0)<0;if(!g){j=(h<<3)+8|0;k=0;while(1){Eg(a+(k*80|0)+5984|0,0,j|0)|0;if((k|0)==(h|0)){break}else{k=k+1|0}}if(!g){g=h+1|0;k=0;j=g;while(1){if((h-k|0)>=0){l=0;do{c[e>>2]=k;c[e+4>>2]=l;Na(f|0,12360,e|0)|0;Lc(b,f,a+(k*80|0)+(l<<3)+5984|0)|0;l=l+1|0}while((l|0)!=(j|0))}k=k+1|0;if((k|0)==(g|0)){break}else{j=j+ -1|0}}}}}else{_b(12296)}j=a+6784|0;if((Ec(b,12368,j)|0)!=0){g=c[j>>2]|0;j=(g|0)<0;if(!j){k=(g<<3)+8|0;h=0;while(1){Eg(a+(h*80|0)+6792|0,0,k|0)|0;if((h|0)==(g|0)){break}else{h=h+1|0}}if(!j){j=g+1|0;h=0;k=j;while(1){if((g-h|0)>=0){l=0;do{c[e>>2]=h;c[e+4>>2]=l;Na(f|0,12440,e|0)|0;Lc(b,f,a+(h*80|0)+(l<<3)+6792|0)|0;l=l+1|0}while((l|0)!=(k|0))}h=h+1|0;if((h|0)==(j|0)){break}else{k=k+ -1|0}}}}}else{_b(12376)}k=a+7592|0;if((Ec(b,12448,k)|0)!=0){j=c[k>>2]|0;k=(j|0)<0;if(!k){h=(j<<3)+8|0;g=0;while(1){Eg(a+(g*80|0)+7600|0,0,h|0)|0;if((g|0)==(j|0)){break}else{g=g+1|0}}if(!k){k=j+1|0;g=0;h=k;while(1){if((j-g|0)>=0){l=0;do{c[e>>2]=g;c[e+4>>2]=l;Na(f|0,12528,e|0)|0;Lc(b,f,a+(g*80|0)+(l<<3)+7600|0)|0;l=l+1|0}while((l|0)!=(h|0))}g=g+1|0;if((g|0)==(k|0)){break}else{h=h+ -1|0}}}}}else{_b(12464)}h=a+8400|0;if((Ec(b,12544,h)|0)==0){_b(12560);i=d;return}k=c[h>>2]|0;h=(k|0)<0;if(h){i=d;return}g=(k<<3)+8|0;j=0;while(1){Eg(a+(j*80|0)+8408|0,0,g|0)|0;if((j|0)==(k|0)){break}else{j=j+1|0}}if(h){i=d;return}h=k+1|0;j=0;g=h;while(1){if((k-j|0)>=0){l=0;do{c[e>>2]=j;c[e+4>>2]=l;Na(f|0,12624,e|0)|0;Lc(b,f,a+(j*80|0)+(l<<3)+8408|0)|0;l=l+1|0}while((l|0)!=(g|0))}j=j+1|0;if((j|0)==(h|0)){break}else{g=g+ -1|0}}i=d;return}function Ze(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0,y=0.0,z=0.0;g=i;i=i+80|0;j=g;if((c[a+5968>>2]|0)!=1){h[e>>3]=b;k=d;h[f>>3]=k;i=g;return}l=c[a+7592>>2]|0;m=c[a+8400>>2]|0;n=b- +h[a+16>>3];o=d- +h[a+24>>3];if((l|0)>=0){p=0;while(1){q=l-p|0;r=+h[a+(q*80|0)+(p<<3)+7600>>3];s=j+(p<<3)|0;h[s>>3]=r;if((p|0)>0){t=p;u=r;do{t=t+ -1|0;u=o*u+ +h[a+(q*80|0)+(t<<3)+7600>>3]}while((t|0)>0);h[s>>3]=u}if((p|0)==(l|0)){break}else{p=p+1|0}}r=+h[j>>3];if((l|0)>0){p=l+1|0;t=l;v=r;while(1){w=n*v+ +h[j+(p-t<<3)>>3];l=t+ -1|0;if((l|0)>0){t=l;v=w}else{x=j;y=w;break}}}else{x=j;y=r}}else{x=j;y=0.0}h[e>>3]=y;if((m|0)>=0){t=0;while(1){p=m-t|0;y=+h[a+(p*80|0)+(t<<3)+8408>>3];l=j+(t<<3)|0;h[l>>3]=y;if((t|0)>0){q=t;r=y;do{q=q+ -1|0;r=o*r+ +h[a+(p*80|0)+(q<<3)+8408>>3]}while((q|0)>0);h[l>>3]=r}if((t|0)==(m|0)){break}else{t=t+1|0}}o=+h[x>>3];if((m|0)>0){t=m+1|0;a=m;u=o;while(1){y=n*u+ +h[j+(t-a<<3)>>3];m=a+ -1|0;if((m|0)>0){a=m;u=y}else{z=y;break}}}else{z=o}}else{z=+h[x>>3]}h[f>>3]=z;h[e>>3]=+h[e>>3]+b;k=+h[f>>3]+d;h[f>>3]=k;i=g;return}function _e(a,b,d,e,f){a=a|0;b=+b;d=+d;e=e|0;f=f|0;var g=0,j=0,k=0.0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0,t=0,u=0.0,v=0.0,w=0.0,x=0,y=0.0,z=0.0;g=i;i=i+80|0;j=g;if((c[a+5968>>2]|0)!=1){h[e>>3]=b;k=d;h[f>>3]=k;i=g;return}l=c[a+5976>>2]|0;m=c[a+6784>>2]|0;n=b- +h[a+16>>3];o=d- +h[a+24>>3];if((l|0)>=0){p=0;while(1){q=l-p|0;r=+h[a+(q*80|0)+(p<<3)+5984>>3];s=j+(p<<3)|0;h[s>>3]=r;if((p|0)>0){t=p;u=r;do{t=t+ -1|0;u=o*u+ +h[a+(q*80|0)+(t<<3)+5984>>3]}while((t|0)>0);h[s>>3]=u}if((p|0)==(l|0)){break}else{p=p+1|0}}r=+h[j>>3];if((l|0)>0){p=l+1|0;t=l;v=r;while(1){w=n*v+ +h[j+(p-t<<3)>>3];l=t+ -1|0;if((l|0)>0){t=l;v=w}else{x=j;y=w;break}}}else{x=j;y=r}}else{x=j;y=0.0}h[e>>3]=y;if((m|0)>=0){t=0;while(1){p=m-t|0;y=+h[a+(p*80|0)+(t<<3)+6792>>3];l=j+(t<<3)|0;h[l>>3]=y;if((t|0)>0){q=t;r=y;do{q=q+ -1|0;r=o*r+ +h[a+(p*80|0)+(q<<3)+6792>>3]}while((q|0)>0);h[l>>3]=r}if((t|0)==(m|0)){break}else{t=t+1|0}}o=+h[x>>3];if((m|0)>0){t=m+1|0;a=m;u=o;while(1){y=n*u+ +h[j+(t-a<<3)>>3];m=a+ -1|0;if((m|0)>0){a=m;u=y}else{z=y;break}}}else{z=o}}else{z=+h[x>>3]}h[f>>3]=z;h[e>>3]=+h[e>>3]+b;k=+h[f>>3]+d;h[f>>3]=k;i=g;return}function $e(a,b){a=a|0;b=b|0;var d=0,e=0;d=i;if((Dg(b|0)|0)<9){c[a+5968>>2]=0;i=d;return}e=a+5968|0;if((Ag(b+8|0,12640,4)|0)==0){c[e>>2]=1;i=d;return}else{c[e>>2]=0;i=d;return}}function af(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0.0,k=0.0,l=0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0;e=i;i=i+16|0;f=e;c[3162]=0;g=(d|0)==0;h=b;while(1){if((a[h]|0)==32){h=h+1|0}else{break}}b=g?f:d;j=+wg(h,b);d=c[b>>2]|0;if(($f(h,46)|0)!=0){c[3162]=46}f=a[d]|0;g=f<<24>>24;switch(f<<24>>24){case 32:case 58:case 100:case 104:case 109:{break};default:{k=j;i=e;return+k}}l=d;if((l-h|0)>=5){k=j;i=e;return+k}m=d+1|0;n=a[m]|0;if(!(((n<<24>>24)+ -48|0)>>>0<10)){if(!(n<<24>>24==32)){k=j;i=e;return+k}if(!(((a[d+2|0]|0)+ -48|0)>>>0<10)){k=j;i=e;return+k}}c[3162]=g;c[b>>2]=m;if((a[h]|0)==45){o=-j;p=-1.0}else{o=j;p=1.0}j=+wg(m,b);do{if(!(f<<24>>24==109)){m=c[b>>2]|0;h=a[m]|0;if(h<<24>>24==32|h<<24>>24==58|h<<24>>24==109?(m-l|0)<4:0){h=m+1|0;g=a[h]|0;if(!(((g<<24>>24)+ -48|0)>>>0<10)){if(!(g<<24>>24==32)){q=o;r=j;s=0.0;break}if(!(((a[m+2|0]|0)+ -48|0)>>>0<10)){q=o;r=j;s=0.0;break}}c[b>>2]=h;q=o;r=j;s=+wg(h,b)}else{q=o;r=j;s=0.0}}else{q=0.0;r=o;s=j}}while(0);k=p*(q+r/60.0+s/3600.0);i=e;return+k}function bf(a,b,d,e,f,j,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;j=j|0;l=+l;m=m|0;n=n|0;var o=0,p=0,q=0,r=0,s=0.0,t=0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0;o=i;i=i+48|0;p=o;q=o+36|0;r=o+32|0;s=l;c[r>>2]=0;if((c[58]|0)!=0){c[p>>2]=b;c[p+4>>2]=d;c[p+8>>2]=e;t=p+12|0;h[k>>3]=s;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];c[p+20>>2]=m;c[p+24>>2]=n;Ma(12656,p|0)|0}t=cf(a,e,r,b,d,m,n)|0;n=c[r>>2]|0;Zf(n,t,4,4);l=+g[n>>2];u=+g[n+(t+ -1<<2)>>2];r=t+1|0;if((r|0)<2){v=1}else{v=(r|0)/2|0}r=v+ -1|0;m=n+(r<<2)|0;w=+g[m>>2];if(((t|0)%2|0|0)!=1&(v|0)<(t|0)){x=(w+ +g[n+(v<<2)>>2])*.5}else{x=w}w=+(t|0);d=~~(w*.5);b=(d|0)<5?5:d;d=~~(w*.01+.5);e=(d|0)<1?1:d;d=df(n,t,o+40|0,q,2.5,e,5)|0;if((d|0)<(b|0)){g[f>>2]=l;y=u}else{w=+g[q>>2];if(s>0.0){z=w/s;g[q>>2]=z;A=z}else{A=w}w=x- +(r|0)*A;g[f>>2]=l>w?l:w;w=x+ +(t-v|0)*A;y=u>2]=y;if((c[58]|0)==0){hg(n);i=o;return}y=+g[m>>2];h[k>>3]=l;c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];m=p+8|0;h[k>>3]=u;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];m=p+16|0;h[k>>3]=y;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];m=p+24|0;h[k>>3]=x;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];Ma(12704,p|0)|0;c[p>>2]=b;c[p+4>>2]=e;c[p+8>>2]=d;Ma(12752,p|0)|0;x=+g[f>>2];y=+g[j>>2];h[k>>3]=+g[q>>2];c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];c[p+8>>2]=v;v=p+12|0;h[k>>3]=x;c[v>>2]=c[k>>2];c[v+4>>2]=c[k+4>>2];v=p+20|0;h[k>>3]=y;c[v>>2]=c[k>>2];c[v+4>>2]=c[k+4>>2];Ma(12800,p|0)|0;hg(n);i=o;return}function cf(d,e,f,j,k,l,m){d=d|0;e=e|0;f=f|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;n=i;i=i+16|0;o=n;p=(j|0)<(m|0)?j:m;q=(p|0)<1?1:p;p=j+ -1|0;r=(p+q|0)/(q|0)|0;s=(r|0)<2?2:r;r=(p+s|0)/(s|0)|0;p=(r|0)<1?1:r;if((c[58]|0)==0){t=1}else{c[o>>2]=q;c[o+4>>2]=s;c[o+8>>2]=p;Ma(12856,o|0)|0;t=(c[58]|0)==0}q=(l|0)/(m|0)|0;m=(q|0)<1?1:q;q=(l+ -1+p|0)/(p|0)|0;l=(q|0)>(k|0)?k:q;q=(m|0)>(l|0)?m:l;l=(k|0)/(q|0)|0;r=(l|0)<2?2:l;u=(k+ -1+r|0)/(r|0)|0;if(!t){c[o>>2]=m;c[o+4>>2]=q;c[o+8>>2]=r;c[o+12>>2]=u;Ma(12912,o|0)|0}o=aa(u,p)|0;u=gg(o<<2)|0;c[f>>2]=u;f=j<<2;q=gg(f)|0;m=(r+1|0)/2|0;if((m|0)>=(k|0)){v=0;hg(q);i=n;return v|0}t=(p|0)>0;w=(j|0)>0;x=j<<1;y=j<<3;if((e|0)==8){z=m;A=0;B=u;while(1){C=aa(z+ -1|0,j)|0;if(w){D=0;do{g[q+(D<<2)>>2]=+(a[d+(D+C)|0]|0);D=D+1|0}while((D|0)!=(j|0))}a:do{if(t){D=0;C=0;while(1){g[B+(D<<2)>>2]=+g[q+(C<<2)>>2];E=D+1|0;if((E|0)==(p|0)){break a}D=E;C=C+s|0}}}while(0);C=A+p|0;if((C|0)>(o|0)){v=C;F=29;break}D=z+r|0;if((D|0)<(k|0)){z=D;A=C;B=B+(p<<2)|0}else{v=C;F=29;break}}if((F|0)==29){hg(q);i=n;return v|0}}B=(aa(m+ -1|0,j)|0)<<2;A=(aa((l|0)>2?l:2,j)|0)<<2;l=j<<2;z=0;C=m;m=0;D=u;while(1){u=d+(B+(aa(A,z)|0))|0;if((e|0)==32){E=d+(aa(f,C+ -1|0)|0)|0;if(w){G=0;do{g[q+(G<<2)>>2]=+(c[E+(G<<2)>>2]|0);G=G+1|0}while((G|0)!=(j|0))}}else if((e|0)==-32){if(w){Kg(q|0,u|0,l|0)|0}}else if((e|0)==-64){G=d+(aa(y,C+ -1|0)|0)|0;if(w){E=0;do{g[q+(E<<2)>>2]=+h[G+(E<<3)>>3];E=E+1|0}while((E|0)!=(j|0))}}else if((e|0)==16?(E=d+(aa(x,C+ -1|0)|0)|0,w):0){G=0;do{g[q+(G<<2)>>2]=+(b[E+(G<<1)>>1]|0);G=G+1|0}while((G|0)!=(j|0))}b:do{if(t){G=0;E=0;while(1){g[D+(G<<2)>>2]=+g[q+(E<<2)>>2];u=G+1|0;if((u|0)==(p|0)){break b}G=u;E=E+s|0}}}while(0);E=m+p|0;if((E|0)>(o|0)){v=E;F=29;break}G=C+r|0;if((G|0)<(k|0)){z=z+1|0;C=G;m=E;D=D+(p<<2)|0}else{v=E;F=29;break}}if((F|0)==29){hg(q);i=n;return v|0}return 0}function df(b,c,d,e,f,h,j){b=b|0;c=c|0;d=d|0;e=e|0;f=+f;h=h|0;j=j|0;var k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0.0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,B=0,C=0.0,D=0,E=0,F=0,G=0,H=0.0,I=0.0,J=0.0,K=0,L=0.0,M=0.0,N=0.0,O=0.0,P=0.0,R=0.0,S=0.0,T=0.0,U=0,V=0,W=0.0,X=0,Y=0,Z=0.0,_=0.0,$=0.0,ba=0,ca=0.0,da=0.0,ea=0.0,fa=0.0,ga=0,ha=0.0,ia=0.0,ja=0.0,ka=0.0,la=0.0,ma=0.0,na=0,oa=0.0,pa=0.0,qa=0.0,ra=0,sa=0.0,ta=0.0;k=i;l=f;if((c|0)<1){m=0;i=k;return m|0}if((c|0)==1){g[d>>2]=+g[b+4>>2];g[e>>2]=0.0;m=1;i=k;return m|0}f=2.0/+(c+ -1|0);n=c<<2;o=gg(n)|0;p=gg(n)|0;n=ig(c,1)|0;q=0;while(1){g[p+(q<<2)>>2]=f*+(q|0)+-1.0;r=q+1|0;if((r|0)==(c|0)){s=0.0;t=0.0;u=0.0;v=0;break}else{q=r}}do{w=+g[p+(v<<2)>>2];x=+g[b+(v<<2)>>2];s=s+w*w;t=t+w*x;u=u+x;v=v+1|0}while((v|0)!=(c|0));x=+(c|0);w=u/x;y=t/s;v=~~(x*.5);q=(v|0)<5?5:v;if((j|0)>0){x=l;v=~h;r=~c;l=0.0;z=u;u=t;t=s;s=y;A=c;B=0;C=w;while(1){D=0;while(1){g[o+(D<<2)>>2]=+g[b+(D<<2)>>2]-(C+s*+g[p+(D<<2)>>2]);E=D+1|0;if((E|0)==(c|0)){F=0;G=0;H=0.0;I=0.0;break}else{D=E}}while(1){if((a[n+F|0]|0)==0){J=+g[o+(F<<2)>>2];K=G+1|0;L=H+J;M=I+J*J}else{K=G;L=H;M=I}F=F+1|0;if((F|0)==(c|0)){break}else{G=K;H=L;I=M}}if(!(K>>>0<2)){D=K+ -1|0;J=M/+(D|0)-L*L/+(aa(D,K)|0);if(J<0.0){N=0.0}else{N=+Q(+J)}}else{N=-999.0}J=x*N;O=-J;P=t;R=u;S=z;T=l;D=0;E=v;U=c;while(1){V=~((E|0)>(r|0)?E:r);if((a[n+D|0]|0)!=1){W=+g[o+(D<<2)>>2];if(WJ?(X=D-h|0,Y=(X|0)<0?0:X,X=D+h|0,(Y|0)<(((X|0)>(c|0)?c:X)|0)):0){W=P;Z=R;_=T;$=S;X=Y;Y=U;while(1){ba=n+X|0;do{if((a[ba]|0)!=1){if((X|0)>(D|0)){a[ba]=2;ca=W;da=Z;ea=$;fa=_;ga=Y;break}else{ha=+g[p+(X<<2)>>2];ia=+g[b+(X<<2)>>2];a[ba]=1;ca=W-ha*ha;da=Z-ha*ia;ea=$-ia;fa=_-ha;ga=Y+ -1|0;break}}else{ca=W;da=Z;ea=$;fa=_;ga=Y}}while(0);ba=X+1|0;if((ba|0)==(V|0)){ja=fa;ka=ca;la=da;ma=ea;na=ga;break}else{W=ca;Z=da;_=fa;$=ea;X=ba;Y=ga}}}else{ja=T;ka=P;la=R;ma=S;na=U}}else{ja=T;ka=P;la=R;ma=S;na=U+ -1|0}D=D+1|0;if((D|0)==(c|0)){break}else{P=ka;R=la;S=ma;T=ja;E=E+ -1|0;U=na}}if((na|0)>0){T=ja/ka;S=(ma-la*T)/(+(na|0)-ja*T);oa=(la-ja*S)/ka;pa=S}else{oa=s;pa=C}U=B+1|0;if((na|0)>=(q|0)&(na|0)<(A|0)&(U|0)<(j|0)){l=ja;z=ma;u=la;t=ka;s=oa;A=na;B=U;C=pa}else{qa=oa;ra=na;sa=pa;break}}}else{qa=y;ra=c;sa=w}g[d>>2]=sa-qa;sa=f*qa;g[e>>2]=sa;if(!(sa>=0.0)){ta=-sa}else{ta=sa}if(ta<.001){g[e>>2]=f*y}hg(o);hg(p);hg(n);m=ra;i=k;return m|0}function ef(a,b){a=a|0;b=b|0;return(+g[a>>2]<=+g[b>>2]?-1:1)|0}function ff(a,b,c){a=a|0;b=b|0;c=c|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0;e=i;f=a>>>16;g=a&65535;if((c|0)==1){a=(d[b]|0)+g|0;h=a>>>0>65520?a+ -65521|0:a;a=h+f|0;j=(a>>>0>65520?a+15|0:a)<<16|h;i=e;return j|0}if((b|0)==0){j=1;i=e;return j|0}if(c>>>0<16){if((c|0)==0){k=g;l=f}else{h=b;a=c;m=g;n=f;while(1){o=a+ -1|0;p=(d[h]|0)+m|0;q=p+n|0;if((o|0)==0){k=p;l=q;break}else{h=h+1|0;a=o;m=p;n=q}}}j=((l>>>0)%65521|0)<<16|(k>>>0>65520?k+ -65521|0:k);i=e;return j|0}if(c>>>0>5551){k=b;l=c;n=g;m=f;do{l=l+ -5552|0;a=k;h=n;q=347;p=m;while(1){o=(d[a]|0)+h|0;r=o+(d[a+1|0]|0)|0;s=r+(d[a+2|0]|0)|0;t=s+(d[a+3|0]|0)|0;u=t+(d[a+4|0]|0)|0;v=u+(d[a+5|0]|0)|0;w=v+(d[a+6|0]|0)|0;x=w+(d[a+7|0]|0)|0;y=x+(d[a+8|0]|0)|0;z=y+(d[a+9|0]|0)|0;A=z+(d[a+10|0]|0)|0;B=A+(d[a+11|0]|0)|0;C=B+(d[a+12|0]|0)|0;D=C+(d[a+13|0]|0)|0;E=D+(d[a+14|0]|0)|0;h=E+(d[a+15|0]|0)|0;p=o+p+r+s+t+u+v+w+x+y+z+A+B+C+D+E+h|0;q=q+ -1|0;if((q|0)==0){break}else{a=a+16|0}}k=k+5552|0;n=(h>>>0)%65521|0;m=(p>>>0)%65521|0}while(l>>>0>5551);if((l|0)!=0){if(l>>>0>15){F=l;G=k;H=n;I=m;J=15}else{K=l;L=k;M=n;N=m;J=16}}else{O=n;P=m}}else{F=c;G=b;H=g;I=f;J=15}if((J|0)==15){while(1){J=0;F=F+ -16|0;f=(d[G]|0)+H|0;g=f+(d[G+1|0]|0)|0;b=g+(d[G+2|0]|0)|0;c=b+(d[G+3|0]|0)|0;m=c+(d[G+4|0]|0)|0;n=m+(d[G+5|0]|0)|0;k=n+(d[G+6|0]|0)|0;l=k+(d[G+7|0]|0)|0;a=l+(d[G+8|0]|0)|0;q=a+(d[G+9|0]|0)|0;E=q+(d[G+10|0]|0)|0;D=E+(d[G+11|0]|0)|0;C=D+(d[G+12|0]|0)|0;B=C+(d[G+13|0]|0)|0;A=B+(d[G+14|0]|0)|0;H=A+(d[G+15|0]|0)|0;I=f+I+g+b+c+m+n+k+l+a+q+E+D+C+B+A+H|0;G=G+16|0;if(!(F>>>0>15)){break}else{J=15}}if((F|0)==0){Q=H;R=I;J=17}else{K=F;L=G;M=H;N=I;J=16}}if((J|0)==16){while(1){J=0;I=K+ -1|0;H=(d[L]|0)+M|0;G=H+N|0;if((I|0)==0){Q=H;R=G;J=17;break}else{K=I;L=L+1|0;M=H;N=G;J=16}}}if((J|0)==17){O=(Q>>>0)%65521|0;P=(R>>>0)%65521|0}j=P<<16|O;i=e;return j|0}function gf(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;f=i;if((b|0)==0){g=0;i=f;return g|0}h=~a;a:do{if((e|0)!=0){a=b;j=e;k=h;while(1){if((a&3|0)==0){break}l=c[12968+(((d[a]|0)^k&255)<<2)>>2]^k>>>8;m=j+ -1|0;if((m|0)==0){n=l;break a}else{a=a+1|0;j=m;k=l}}if(j>>>0>31){l=j;m=a;o=k;while(1){p=c[m>>2]^o;q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+4>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+8>>2];q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+12>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+16>>2];q=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+20>>2];p=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2]^c[m+24>>2];q=m+32|0;r=c[15016+((p>>>8&255)<<2)>>2]^c[16040+((p&255)<<2)>>2]^c[13992+((p>>>16&255)<<2)>>2]^c[12968+(p>>>24<<2)>>2]^c[m+28>>2];p=c[15016+((r>>>8&255)<<2)>>2]^c[16040+((r&255)<<2)>>2]^c[13992+((r>>>16&255)<<2)>>2]^c[12968+(r>>>24<<2)>>2];r=l+ -32|0;if(r>>>0>31){l=r;m=q;o=p}else{s=r;t=q;u=p;break}}}else{s=j;t=a;u=k}if(s>>>0>3){o=s;m=t;l=u;while(1){p=m+4|0;q=c[m>>2]^l;r=c[15016+((q>>>8&255)<<2)>>2]^c[16040+((q&255)<<2)>>2]^c[13992+((q>>>16&255)<<2)>>2]^c[12968+(q>>>24<<2)>>2];q=o+ -4|0;if(q>>>0>3){o=q;m=p;l=r}else{v=q;w=p;x=r;break}}}else{v=s;w=t;x=u}if((v|0)==0){n=x}else{l=w;m=v;o=x;while(1){k=c[12968+(((d[l]|0)^o&255)<<2)>>2]^o>>>8;a=m+ -1|0;if((a|0)==0){n=k;break}else{l=l+1|0;m=a;o=k}}}}else{n=h}}while(0);g=~n;i=f;return g|0}function hf(b,d,e,f,g,h,j,k){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0;l=i;if((j|0)==0){m=-6;i=l;return m|0}if(!((a[j]|0)==49&(k|0)==56)){m=-6;i=l;return m|0}if((b|0)==0){m=-2;i=l;return m|0}k=b+24|0;c[k>>2]=0;j=b+32|0;n=c[j>>2]|0;if((n|0)==0){c[j>>2]=1;c[b+40>>2]=0;o=1}else{o=n}n=b+36|0;if((c[n>>2]|0)==0){c[n>>2]=1}n=(d|0)==-1?6:d;if((f|0)<0){p=0-f|0;q=0}else{d=(f|0)>15;p=d?f+ -16|0:f;q=d?2:1}if(!((g+ -1|0)>>>0<9&(e|0)==8)){m=-2;i=l;return m|0}if((p+ -8|0)>>>0>7|n>>>0>9|h>>>0>4){m=-2;i=l;return m|0}e=(p|0)==8?9:p;p=b+40|0;d=kb[o&1](c[p>>2]|0,1,5828)|0;if((d|0)==0){m=-4;i=l;return m|0}c[b+28>>2]=d;c[d>>2]=b;c[d+24>>2]=q;c[d+28>>2]=0;c[d+48>>2]=e;q=1<>2]=q;c[d+52>>2]=q+ -1;o=g+7|0;c[d+80>>2]=o;f=1<>2]=f;c[d+84>>2]=f+ -1;c[d+88>>2]=((g+9|0)>>>0)/3|0;f=d+56|0;c[f>>2]=kb[c[j>>2]&1](c[p>>2]|0,q,2)|0;q=kb[c[j>>2]&1](c[p>>2]|0,c[e>>2]|0,2)|0;r=d+64|0;c[r>>2]=q;Eg(q|0,0,c[e>>2]<<1|0)|0;e=d+68|0;c[e>>2]=kb[c[j>>2]&1](c[p>>2]|0,c[o>>2]|0,2)|0;c[d+5824>>2]=0;o=1<>2]=o;q=kb[c[j>>2]&1](c[p>>2]|0,o,4)|0;c[d+8>>2]=q;o=c[g>>2]|0;c[d+12>>2]=o<<2;if(((c[f>>2]|0)!=0?(c[r>>2]|0)!=0:0)?!((c[e>>2]|0)==0|(q|0)==0):0){c[d+5796>>2]=q+(o>>>1<<1);c[d+5784>>2]=q+(o*3|0);c[d+132>>2]=n;c[d+136>>2]=h;a[d+36|0]=8;m=kf(b)|0;i=l;return m|0}c[d+4>>2]=666;c[k>>2]=c[27632>>2];jf(b)|0;m=-4;i=l;return m|0}function jf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;i=b;return d|0}g=c[f+4>>2]|0;switch(g|0){case 42:case 69:case 73:case 91:case 103:case 113:case 666:{break};default:{d=-2;i=b;return d|0}}h=c[f+8>>2]|0;if((h|0)==0){j=f}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);j=c[e>>2]|0}h=c[j+68>>2]|0;if((h|0)==0){k=j}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);k=c[e>>2]|0}h=c[k+64>>2]|0;if((h|0)==0){l=k}else{mb[c[a+36>>2]&1](c[a+40>>2]|0,h);l=c[e>>2]|0}h=c[l+56>>2]|0;k=a+36|0;if((h|0)==0){m=a+40|0;n=l}else{l=a+40|0;mb[c[k>>2]&1](c[l>>2]|0,h);m=l;n=c[e>>2]|0}mb[c[k>>2]&1](c[m>>2]|0,n);c[e>>2]=0;d=(g|0)==113?-3:0;i=b;return d|0}function kf(a){a=a|0;var d=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;d=i;if((a|0)==0){f=-2;i=d;return f|0}g=c[a+28>>2]|0;if((g|0)==0){f=-2;i=d;return f|0}if((c[a+32>>2]|0)==0){f=-2;i=d;return f|0}if((c[a+36>>2]|0)==0){f=-2;i=d;return f|0}c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+44>>2]=2;c[g+20>>2]=0;c[g+16>>2]=c[g+8>>2];h=g+24|0;j=c[h>>2]|0;if((j|0)<0){k=0-j|0;c[h>>2]=k;l=k}else{l=j}c[g+4>>2]=(l|0)!=0?42:113;if((l|0)==2){m=gf(0,0,0)|0}else{m=ff(0,0,0)|0}c[a+48>>2]=m;c[g+40>>2]=0;Of(g);c[g+60>>2]=c[g+44>>2]<<1;m=c[g+76>>2]|0;a=c[g+68>>2]|0;b[a+(m+ -1<<1)>>1]=0;Eg(a|0,0,(m<<1)+ -2|0)|0;m=c[g+132>>2]|0;c[g+128>>2]=e[21162+(m*12|0)>>1]|0;c[g+140>>2]=e[21160+(m*12|0)>>1]|0;c[g+144>>2]=e[21164+(m*12|0)>>1]|0;c[g+124>>2]=e[21166+(m*12|0)>>1]|0;c[g+108>>2]=0;c[g+92>>2]=0;c[g+116>>2]=0;c[g+120>>2]=2;c[g+96>>2]=2;c[g+112>>2]=0;c[g+104>>2]=0;c[g+72>>2]=0;f=0;i=d;return f|0} + + + +function lf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0;g=i;if((e|0)==0){h=-2;i=g;return h|0}j=e+28|0;k=c[j>>2]|0;if((k|0)==0|f>>>0>5){h=-2;i=g;return h|0}l=e+12|0;do{if((c[l>>2]|0)!=0){if((c[e>>2]|0)==0?(c[e+4>>2]|0)!=0:0){break}m=k+4|0;n=c[m>>2]|0;o=(f|0)==4;if((n|0)!=666|o){p=e+16|0;if((c[p>>2]|0)==0){c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}c[k>>2]=e;q=k+40|0;r=c[q>>2]|0;c[q>>2]=f;do{if((n|0)==42){if((c[k+24>>2]|0)!=2){s=(c[k+48>>2]<<12)+ -30720|0;if((c[k+136>>2]|0)<=1?(t=c[k+132>>2]|0,(t|0)>=2):0){if((t|0)<6){u=64}else{u=(t|0)==6?128:192}}else{u=0}t=u|s;s=k+108|0;v=(c[s>>2]|0)==0?t:t|32;c[m>>2]=113;t=k+20|0;w=c[t>>2]|0;c[t>>2]=w+1;x=k+8|0;a[(c[x>>2]|0)+w|0]=v>>>8;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=(v|((v>>>0)%31|0))^31;v=e+48|0;if((c[s>>2]|0)!=0){s=c[v>>2]|0;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>24;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>16;s=c[v>>2]|0;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s>>>8;w=c[t>>2]|0;c[t>>2]=w+1;a[(c[x>>2]|0)+w|0]=s}c[v>>2]=ff(0,0,0)|0;y=c[m>>2]|0;z=32;break}v=e+48|0;c[v>>2]=gf(0,0,0)|0;s=k+20|0;w=c[s>>2]|0;c[s>>2]=w+1;x=k+8|0;a[(c[x>>2]|0)+w|0]=31;w=c[s>>2]|0;c[s>>2]=w+1;a[(c[x>>2]|0)+w|0]=-117;w=c[s>>2]|0;c[s>>2]=w+1;a[(c[x>>2]|0)+w|0]=8;w=k+28|0;t=c[w>>2]|0;if((t|0)==0){A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=0;A=c[k+132>>2]|0;if((A|0)!=9){if((c[k+136>>2]|0)>1){B=4}else{B=(A|0)<2?4:0}}else{B=2}A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=B;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=3;c[m>>2]=113;break}A=(((c[t+44>>2]|0)!=0?2:0)|(c[t>>2]|0)!=0|((c[t+16>>2]|0)==0?0:4)|((c[t+28>>2]|0)==0?0:8)|((c[t+36>>2]|0)==0?0:16))&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[(c[w>>2]|0)+4>>2]&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>8&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>16&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=(c[(c[w>>2]|0)+4>>2]|0)>>>24&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[k+132>>2]|0;if((A|0)!=9){if((c[k+136>>2]|0)>1){C=4}else{C=(A|0)<2?4:0}}else{C=2}A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=C;A=c[(c[w>>2]|0)+12>>2]&255;t=c[s>>2]|0;c[s>>2]=t+1;a[(c[x>>2]|0)+t|0]=A;A=c[w>>2]|0;if((c[A+16>>2]|0)==0){D=A}else{t=c[A+20>>2]&255;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=t;t=(c[(c[w>>2]|0)+20>>2]|0)>>>8&255;A=c[s>>2]|0;c[s>>2]=A+1;a[(c[x>>2]|0)+A|0]=t;D=c[w>>2]|0}if((c[D+44>>2]|0)!=0){c[v>>2]=gf(c[v>>2]|0,c[x>>2]|0,c[s>>2]|0)|0}c[k+32>>2]=0;c[m>>2]=69;E=w;z=34}else{y=n;z=32}}while(0);if((z|0)==32){if((y|0)==69){E=k+28|0;z=34}else{F=y;z=55}}do{if((z|0)==34){n=c[E>>2]|0;if((c[n+16>>2]|0)==0){c[m>>2]=73;G=n;z=57;break}w=k+20|0;s=c[w>>2]|0;x=k+32|0;v=c[x>>2]|0;a:do{if(v>>>0<(c[n+20>>2]&65535)>>>0){t=k+12|0;A=e+48|0;H=k+8|0;I=e+20|0;J=v;K=s;L=n;M=s;while(1){if((K|0)==(c[t>>2]|0)){if((c[L+44>>2]|0)!=0&K>>>0>M>>>0){c[A>>2]=gf(c[A>>2]|0,(c[H>>2]|0)+M|0,K-M|0)|0}N=c[j>>2]|0;O=c[N+20>>2]|0;P=c[p>>2]|0;Q=O>>>0>P>>>0?P:O;if((Q|0)!=0?(Kg(c[l>>2]|0,c[N+16>>2]|0,Q|0)|0,c[l>>2]=(c[l>>2]|0)+Q,N=(c[j>>2]|0)+16|0,c[N>>2]=(c[N>>2]|0)+Q,c[I>>2]=(c[I>>2]|0)+Q,c[p>>2]=(c[p>>2]|0)-Q,N=c[j>>2]|0,O=N+20|0,P=c[O>>2]|0,c[O>>2]=P-Q,(P|0)==(Q|0)):0){c[N+16>>2]=c[N+8>>2]}R=c[w>>2]|0;if((R|0)==(c[t>>2]|0)){break}S=c[E>>2]|0;T=c[x>>2]|0;U=R;V=R}else{S=L;T=J;U=K;V=M}N=a[(c[S+16>>2]|0)+T|0]|0;c[w>>2]=U+1;a[(c[H>>2]|0)+U|0]=N;N=(c[x>>2]|0)+1|0;c[x>>2]=N;Q=c[E>>2]|0;if(!(N>>>0<(c[Q+20>>2]&65535)>>>0)){W=Q;X=V;break a}J=N;K=c[w>>2]|0;L=Q;M=V}W=c[E>>2]|0;X=R}else{W=n;X=s}}while(0);if((c[W+44>>2]|0)!=0?(s=c[w>>2]|0,s>>>0>X>>>0):0){n=e+48|0;c[n>>2]=gf(c[n>>2]|0,(c[k+8>>2]|0)+X|0,s-X|0)|0;Y=c[E>>2]|0}else{Y=W}if((c[x>>2]|0)==(c[Y+20>>2]|0)){c[x>>2]=0;c[m>>2]=73;G=Y;z=57;break}else{F=c[m>>2]|0;z=55;break}}}while(0);if((z|0)==55){if((F|0)==73){G=c[k+28>>2]|0;z=57}else{Z=F;z=76}}do{if((z|0)==57){s=k+28|0;if((c[G+28>>2]|0)==0){c[m>>2]=91;_=s;z=78;break}n=k+20|0;v=c[n>>2]|0;M=k+12|0;L=e+48|0;K=k+8|0;J=e+20|0;H=k+32|0;t=v;I=v;while(1){if((t|0)==(c[M>>2]|0)){if((c[(c[s>>2]|0)+44>>2]|0)!=0&t>>>0>I>>>0){c[L>>2]=gf(c[L>>2]|0,(c[K>>2]|0)+I|0,t-I|0)|0}v=c[j>>2]|0;A=c[v+20>>2]|0;Q=c[p>>2]|0;N=A>>>0>Q>>>0?Q:A;if((N|0)!=0?(Kg(c[l>>2]|0,c[v+16>>2]|0,N|0)|0,c[l>>2]=(c[l>>2]|0)+N,v=(c[j>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+N,c[J>>2]=(c[J>>2]|0)+N,c[p>>2]=(c[p>>2]|0)-N,v=c[j>>2]|0,A=v+20|0,Q=c[A>>2]|0,c[A>>2]=Q-N,(Q|0)==(N|0)):0){c[v+16>>2]=c[v+8>>2]}v=c[n>>2]|0;if((v|0)==(c[M>>2]|0)){$=v;aa=1;break}else{ba=v;ca=v}}else{ba=t;ca=I}v=c[H>>2]|0;c[H>>2]=v+1;da=a[(c[(c[s>>2]|0)+28>>2]|0)+v|0]|0;c[n>>2]=ba+1;a[(c[K>>2]|0)+ba|0]=da;if(da<<24>>24==0){z=68;break}t=c[n>>2]|0;I=ca}if((z|0)==68){$=ca;aa=da&255}if((c[(c[s>>2]|0)+44>>2]|0)!=0?(I=c[n>>2]|0,I>>>0>$>>>0):0){c[L>>2]=gf(c[L>>2]|0,(c[K>>2]|0)+$|0,I-$|0)|0}if((aa|0)==0){c[H>>2]=0;c[m>>2]=91;_=s;z=78;break}else{Z=c[m>>2]|0;z=76;break}}}while(0);if((z|0)==76){if((Z|0)==91){_=k+28|0;z=78}else{ea=Z;z=97}}do{if((z|0)==78){if((c[(c[_>>2]|0)+36>>2]|0)==0){c[m>>2]=103;fa=_;z=99;break}I=k+20|0;t=c[I>>2]|0;M=k+12|0;J=e+48|0;x=k+8|0;w=e+20|0;v=k+32|0;N=t;Q=t;while(1){if((N|0)==(c[M>>2]|0)){if((c[(c[_>>2]|0)+44>>2]|0)!=0&N>>>0>Q>>>0){c[J>>2]=gf(c[J>>2]|0,(c[x>>2]|0)+Q|0,N-Q|0)|0}t=c[j>>2]|0;A=c[t+20>>2]|0;P=c[p>>2]|0;O=A>>>0>P>>>0?P:A;if((O|0)!=0?(Kg(c[l>>2]|0,c[t+16>>2]|0,O|0)|0,c[l>>2]=(c[l>>2]|0)+O,t=(c[j>>2]|0)+16|0,c[t>>2]=(c[t>>2]|0)+O,c[w>>2]=(c[w>>2]|0)+O,c[p>>2]=(c[p>>2]|0)-O,t=c[j>>2]|0,A=t+20|0,P=c[A>>2]|0,c[A>>2]=P-O,(P|0)==(O|0)):0){c[t+16>>2]=c[t+8>>2]}t=c[I>>2]|0;if((t|0)==(c[M>>2]|0)){ga=t;ha=1;break}else{ia=t;ja=t}}else{ia=N;ja=Q}t=c[v>>2]|0;c[v>>2]=t+1;ka=a[(c[(c[_>>2]|0)+36>>2]|0)+t|0]|0;c[I>>2]=ia+1;a[(c[x>>2]|0)+ia|0]=ka;if(ka<<24>>24==0){z=89;break}N=c[I>>2]|0;Q=ja}if((z|0)==89){ga=ja;ha=ka&255}if((c[(c[_>>2]|0)+44>>2]|0)!=0?(Q=c[I>>2]|0,Q>>>0>ga>>>0):0){c[J>>2]=gf(c[J>>2]|0,(c[x>>2]|0)+ga|0,Q-ga|0)|0}if((ha|0)==0){c[m>>2]=103;fa=_;z=99;break}else{ea=c[m>>2]|0;z=97;break}}}while(0);if((z|0)==97?(ea|0)==103:0){fa=k+28|0;z=99}do{if((z|0)==99){if((c[(c[fa>>2]|0)+44>>2]|0)==0){c[m>>2]=113;break}Q=k+20|0;N=k+12|0;if((((c[Q>>2]|0)+2|0)>>>0>(c[N>>2]|0)>>>0?(v=c[j>>2]|0,M=c[v+20>>2]|0,w=c[p>>2]|0,s=M>>>0>w>>>0?w:M,(s|0)!=0):0)?(Kg(c[l>>2]|0,c[v+16>>2]|0,s|0)|0,c[l>>2]=(c[l>>2]|0)+s,v=(c[j>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+s,v=e+20|0,c[v>>2]=(c[v>>2]|0)+s,c[p>>2]=(c[p>>2]|0)-s,v=c[j>>2]|0,M=v+20|0,w=c[M>>2]|0,c[M>>2]=w-s,(w|0)==(s|0)):0){c[v+16>>2]=c[v+8>>2]}v=c[Q>>2]|0;if(!((v+2|0)>>>0>(c[N>>2]|0)>>>0)){N=e+48|0;s=c[N>>2]&255;c[Q>>2]=v+1;w=k+8|0;a[(c[w>>2]|0)+v|0]=s;s=(c[N>>2]|0)>>>8&255;v=c[Q>>2]|0;c[Q>>2]=v+1;a[(c[w>>2]|0)+v|0]=s;c[N>>2]=gf(0,0,0)|0;c[m>>2]=113}}}while(0);N=k+20|0;if((c[N>>2]|0)==0){if((c[e+4>>2]|0)==0?(r|0)>=(f|0)&(f|0)!=4:0){c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}}else{s=c[j>>2]|0;v=c[s+20>>2]|0;w=c[p>>2]|0;Q=v>>>0>w>>>0?w:v;if((Q|0)==0){la=w}else{Kg(c[l>>2]|0,c[s+16>>2]|0,Q|0)|0;c[l>>2]=(c[l>>2]|0)+Q;s=(c[j>>2]|0)+16|0;c[s>>2]=(c[s>>2]|0)+Q;s=e+20|0;c[s>>2]=(c[s>>2]|0)+Q;c[p>>2]=(c[p>>2]|0)-Q;s=c[j>>2]|0;w=s+20|0;v=c[w>>2]|0;c[w>>2]=v-Q;if((v|0)==(Q|0)){c[s+16>>2]=c[s+8>>2]}la=c[p>>2]|0}if((la|0)==0){c[q>>2]=-1;h=0;i=g;return h|0}}s=(c[m>>2]|0)==666;Q=(c[e+4>>2]|0)==0;if(s){if(Q){z=121}else{c[e+24>>2]=c[27636>>2];h=-5;i=g;return h|0}}else{if(Q){z=121}else{z=124}}do{if((z|0)==121){if((c[k+116>>2]|0)==0){if((f|0)!=0){if(s){break}else{z=124;break}}else{h=0;i=g;return h|0}}else{z=124}}}while(0);do{if((z|0)==124){s=c[k+136>>2]|0;b:do{if((s|0)==3){r=k+116|0;Q=(f|0)==0;v=k+96|0;w=k+108|0;M=k+5792|0;H=k+5796|0;K=k+5784|0;L=k+(d[24760]<<2)+2440|0;n=k+5788|0;t=k+56|0;O=k+92|0;while(1){P=c[r>>2]|0;if(P>>>0<258){mf(k);A=c[r>>2]|0;if(A>>>0<258&Q){break b}if((A|0)==0){break}c[v>>2]=0;if(A>>>0>2){ma=A;z=151}else{na=c[w>>2]|0;z=166}}else{c[v>>2]=0;ma=P;z=151}if((z|0)==151){z=0;P=c[w>>2]|0;if((P|0)!=0){A=c[t>>2]|0;oa=a[A+(P+ -1)|0]|0;if((oa<<24>>24==(a[A+P|0]|0)?oa<<24>>24==(a[A+(P+1)|0]|0):0)?(pa=A+(P+2)|0,oa<<24>>24==(a[pa]|0)):0){qa=A+(P+258)|0;A=pa;while(1){pa=A+1|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+2|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+3|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+4|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+5|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+6|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+7|0;if(!(oa<<24>>24==(a[pa]|0))){ra=pa;break}pa=A+8|0;if(oa<<24>>24==(a[pa]|0)&pa>>>0>>0){A=pa}else{ra=pa;break}}A=ra-qa+258|0;oa=A>>>0>ma>>>0?ma:A;c[v>>2]=oa;if(oa>>>0>2){A=oa+253|0;oa=c[M>>2]|0;b[(c[H>>2]|0)+(oa<<1)>>1]=1;c[M>>2]=oa+1;a[(c[K>>2]|0)+oa|0]=A;oa=k+((d[25272+(A&255)|0]|256)+1<<2)+148|0;b[oa>>1]=(b[oa>>1]|0)+1<<16>>16;b[L>>1]=(b[L>>1]|0)+1<<16>>16;oa=(c[M>>2]|0)==((c[n>>2]|0)+ -1|0)|0;A=c[v>>2]|0;c[r>>2]=(c[r>>2]|0)-A;pa=(c[w>>2]|0)+A|0;c[w>>2]=pa;c[v>>2]=0;sa=pa;ta=oa}else{na=P;z=166}}else{na=P;z=166}}else{na=0;z=166}}if((z|0)==166){z=0;oa=a[(c[t>>2]|0)+na|0]|0;pa=c[M>>2]|0;b[(c[H>>2]|0)+(pa<<1)>>1]=0;c[M>>2]=pa+1;a[(c[K>>2]|0)+pa|0]=oa;pa=k+((oa&255)<<2)+148|0;b[pa>>1]=(b[pa>>1]|0)+1<<16>>16;pa=(c[M>>2]|0)==((c[n>>2]|0)+ -1|0)|0;c[r>>2]=(c[r>>2]|0)+ -1;oa=(c[w>>2]|0)+1|0;c[w>>2]=oa;sa=oa;ta=pa}if((ta|0)==0){continue}pa=c[O>>2]|0;if((pa|0)>-1){ua=(c[t>>2]|0)+pa|0}else{ua=0}Sf(k,ua,sa-pa|0,0);c[O>>2]=c[w>>2];pa=c[k>>2]|0;oa=pa+28|0;A=c[oa>>2]|0;va=c[A+20>>2]|0;wa=pa+16|0;xa=c[wa>>2]|0;ya=va>>>0>xa>>>0?xa:va;if((ya|0)!=0?(va=pa+12|0,Kg(c[va>>2]|0,c[A+16>>2]|0,ya|0)|0,c[va>>2]=(c[va>>2]|0)+ya,va=(c[oa>>2]|0)+16|0,c[va>>2]=(c[va>>2]|0)+ya,va=pa+20|0,c[va>>2]=(c[va>>2]|0)+ya,c[wa>>2]=(c[wa>>2]|0)-ya,wa=c[oa>>2]|0,oa=wa+20|0,va=c[oa>>2]|0,c[oa>>2]=va-ya,(va|0)==(ya|0)):0){c[wa+16>>2]=c[wa+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){break b}}r=c[O>>2]|0;if((r|0)>-1){za=(c[t>>2]|0)+r|0}else{za=0}Sf(k,za,(c[w>>2]|0)-r|0,o&1);c[O>>2]=c[w>>2];r=c[k>>2]|0;n=r+28|0;M=c[n>>2]|0;K=c[M+20>>2]|0;H=r+16|0;v=c[H>>2]|0;L=K>>>0>v>>>0?v:K;if((L|0)!=0?(K=r+12|0,Kg(c[K>>2]|0,c[M+16>>2]|0,L|0)|0,c[K>>2]=(c[K>>2]|0)+L,K=(c[n>>2]|0)+16|0,c[K>>2]=(c[K>>2]|0)+L,K=r+20|0,c[K>>2]=(c[K>>2]|0)+L,c[H>>2]=(c[H>>2]|0)-L,H=c[n>>2]|0,n=H+20|0,K=c[n>>2]|0,c[n>>2]=K-L,(K|0)==(L|0)):0){c[H+16>>2]=c[H+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){Aa=o?2:0;z=183;break}else{Aa=o?3:1;z=183;break}}else if((s|0)==2){H=k+116|0;L=k+96|0;K=k+108|0;n=k+56|0;r=k+5792|0;M=k+5796|0;v=k+5784|0;Q=k+5788|0;wa=k+92|0;while(1){if((c[H>>2]|0)==0?(mf(k),(c[H>>2]|0)==0):0){break}c[L>>2]=0;ya=a[(c[n>>2]|0)+(c[K>>2]|0)|0]|0;va=c[r>>2]|0;b[(c[M>>2]|0)+(va<<1)>>1]=0;c[r>>2]=va+1;a[(c[v>>2]|0)+va|0]=ya;va=k+((ya&255)<<2)+148|0;b[va>>1]=(b[va>>1]|0)+1<<16>>16;va=(c[r>>2]|0)==((c[Q>>2]|0)+ -1|0);c[H>>2]=(c[H>>2]|0)+ -1;ya=(c[K>>2]|0)+1|0;c[K>>2]=ya;if(!va){continue}va=c[wa>>2]|0;if((va|0)>-1){Ba=(c[n>>2]|0)+va|0}else{Ba=0}Sf(k,Ba,ya-va|0,0);c[wa>>2]=c[K>>2];va=c[k>>2]|0;ya=va+28|0;oa=c[ya>>2]|0;pa=c[oa+20>>2]|0;A=va+16|0;xa=c[A>>2]|0;Ca=pa>>>0>xa>>>0?xa:pa;if((Ca|0)!=0?(pa=va+12|0,Kg(c[pa>>2]|0,c[oa+16>>2]|0,Ca|0)|0,c[pa>>2]=(c[pa>>2]|0)+Ca,pa=(c[ya>>2]|0)+16|0,c[pa>>2]=(c[pa>>2]|0)+Ca,pa=va+20|0,c[pa>>2]=(c[pa>>2]|0)+Ca,c[A>>2]=(c[A>>2]|0)-Ca,A=c[ya>>2]|0,ya=A+20|0,pa=c[ya>>2]|0,c[ya>>2]=pa-Ca,(pa|0)==(Ca|0)):0){c[A+16>>2]=c[A+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){break b}}if((f|0)!=0){H=c[wa>>2]|0;if((H|0)>-1){Da=(c[n>>2]|0)+H|0}else{Da=0}Sf(k,Da,(c[K>>2]|0)-H|0,o&1);c[wa>>2]=c[K>>2];H=c[k>>2]|0;Q=H+28|0;r=c[Q>>2]|0;v=c[r+20>>2]|0;M=H+16|0;L=c[M>>2]|0;w=v>>>0>L>>>0?L:v;if((w|0)!=0?(v=H+12|0,Kg(c[v>>2]|0,c[r+16>>2]|0,w|0)|0,c[v>>2]=(c[v>>2]|0)+w,v=(c[Q>>2]|0)+16|0,c[v>>2]=(c[v>>2]|0)+w,v=H+20|0,c[v>>2]=(c[v>>2]|0)+w,c[M>>2]=(c[M>>2]|0)-w,M=c[Q>>2]|0,Q=M+20|0,v=c[Q>>2]|0,c[Q>>2]=v-w,(v|0)==(w|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[k>>2]|0)+16>>2]|0)==0){Aa=o?2:0;z=183;break}else{Aa=o?3:1;z=183;break}}}else{Aa=nb[c[21168+((c[k+132>>2]|0)*12|0)>>2]&7](k,f)|0;z=183}}while(0);if((z|0)==183){if((Aa&-2|0)==2){c[m>>2]=666}if((Aa&-3|0)!=0){if((Aa|0)!=1){break}if((f|0)==1){Rf(k)}else if(((f|0)!=5?(Qf(k,0,0,0),(f|0)==3):0)?(s=c[k+76>>2]|0,x=c[k+68>>2]|0,b[x+(s+ -1<<1)>>1]=0,Eg(x|0,0,(s<<1)+ -2|0)|0,(c[k+116>>2]|0)==0):0){c[k+108>>2]=0;c[k+92>>2]=0}s=c[j>>2]|0;x=c[s+20>>2]|0;J=c[p>>2]|0;I=x>>>0>J>>>0?J:x;if((I|0)==0){Ea=J}else{Kg(c[l>>2]|0,c[s+16>>2]|0,I|0)|0;c[l>>2]=(c[l>>2]|0)+I;s=(c[j>>2]|0)+16|0;c[s>>2]=(c[s>>2]|0)+I;s=e+20|0;c[s>>2]=(c[s>>2]|0)+I;c[p>>2]=(c[p>>2]|0)-I;s=c[j>>2]|0;J=s+20|0;x=c[J>>2]|0;c[J>>2]=x-I;if((x|0)==(I|0)){c[s+16>>2]=c[s+8>>2]}Ea=c[p>>2]|0}if((Ea|0)!=0){break}c[q>>2]=-1;h=0;i=g;return h|0}}if((c[p>>2]|0)!=0){h=0;i=g;return h|0}c[q>>2]=-1;h=0;i=g;return h|0}}while(0);if(!o){h=0;i=g;return h|0}q=k+24|0;m=c[q>>2]|0;if((m|0)<1){h=1;i=g;return h|0}s=e+48|0;I=c[s>>2]|0;if((m|0)==2){m=c[N>>2]|0;c[N>>2]=m+1;x=k+8|0;a[(c[x>>2]|0)+m|0]=I;m=(c[s>>2]|0)>>>8&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=(c[s>>2]|0)>>>16&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=(c[s>>2]|0)>>>24&255;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[x>>2]|0)+J|0]=m;m=e+8|0;J=c[m>>2]&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>8&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>16&255;M=c[N>>2]|0;c[N>>2]=M+1;a[(c[x>>2]|0)+M|0]=J;J=(c[m>>2]|0)>>>24&255;m=c[N>>2]|0;c[N>>2]=m+1;a[(c[x>>2]|0)+m|0]=J}else{J=c[N>>2]|0;c[N>>2]=J+1;m=k+8|0;a[(c[m>>2]|0)+J|0]=I>>>24;J=c[N>>2]|0;c[N>>2]=J+1;a[(c[m>>2]|0)+J|0]=I>>>16;I=c[s>>2]|0;s=c[N>>2]|0;c[N>>2]=s+1;a[(c[m>>2]|0)+s|0]=I>>>8;s=c[N>>2]|0;c[N>>2]=s+1;a[(c[m>>2]|0)+s|0]=I}I=c[j>>2]|0;s=c[I+20>>2]|0;m=c[p>>2]|0;J=s>>>0>m>>>0?m:s;if((J|0)!=0?(Kg(c[l>>2]|0,c[I+16>>2]|0,J|0)|0,c[l>>2]=(c[l>>2]|0)+J,I=(c[j>>2]|0)+16|0,c[I>>2]=(c[I>>2]|0)+J,I=e+20|0,c[I>>2]=(c[I>>2]|0)+J,c[p>>2]=(c[p>>2]|0)-J,I=c[j>>2]|0,s=I+20|0,m=c[s>>2]|0,c[s>>2]=m-J,(m|0)==(J|0)):0){c[I+16>>2]=c[I+8>>2]}I=c[q>>2]|0;if((I|0)>0){c[q>>2]=0-I}h=(c[N>>2]|0)==0|0;i=g;return h|0}}}while(0);c[e+24>>2]=c[27624>>2];h=-2;i=g;return h|0}function mf(a){a=a|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;f=i;g=a+44|0;h=c[g>>2]|0;j=a+60|0;k=a+116|0;l=a+108|0;m=h+ -262|0;n=a+56|0;o=a+72|0;p=a+88|0;q=a+84|0;r=a+112|0;s=a+92|0;t=a+76|0;u=a+68|0;v=a+64|0;w=c[k>>2]|0;x=h;while(1){y=c[l>>2]|0;z=(c[j>>2]|0)-w-y|0;if(y>>>0<(m+x|0)>>>0){A=y;B=z}else{y=c[n>>2]|0;Kg(y|0,y+h|0,h|0)|0;c[r>>2]=(c[r>>2]|0)-h;y=(c[l>>2]|0)-h|0;c[l>>2]=y;c[s>>2]=(c[s>>2]|0)-h;C=c[t>>2]|0;D=C;E=(c[u>>2]|0)+(C<<1)|0;do{E=E+ -2|0;C=e[E>>1]|0;if(C>>>0>>0){F=0}else{F=C-h&65535}b[E>>1]=F;D=D+ -1|0}while((D|0)!=0);D=h;E=(c[v>>2]|0)+(h<<1)|0;do{E=E+ -2|0;C=e[E>>1]|0;if(C>>>0>>0){G=0}else{G=C-h&65535}b[E>>1]=G;D=D+ -1|0}while((D|0)!=0);A=y;B=z+h|0}D=c[a>>2]|0;E=D+4|0;C=c[E>>2]|0;if((C|0)==0){H=28;break}I=c[k>>2]|0;J=(c[n>>2]|0)+(I+A)|0;K=C>>>0>B>>>0?B:C;if((K|0)==0){L=0;M=I}else{c[E>>2]=C-K;C=c[(c[D+28>>2]|0)+24>>2]|0;if((C|0)==2){E=D+48|0;c[E>>2]=gf(c[E>>2]|0,c[D>>2]|0,K)|0;N=D}else if((C|0)==1){C=D+48|0;c[C>>2]=ff(c[C>>2]|0,c[D>>2]|0,K)|0;N=D}else{N=D}Kg(J|0,c[N>>2]|0,K|0)|0;c[N>>2]=(c[N>>2]|0)+K;J=D+8|0;c[J>>2]=(c[J>>2]|0)+K;L=K;M=c[k>>2]|0}O=M+L|0;c[k>>2]=O;if(O>>>0>2?(K=c[l>>2]|0,J=c[n>>2]|0,D=d[J+K|0]|0,c[o>>2]=D,c[o>>2]=((d[J+(K+1)|0]|0)^D<>2])&c[q>>2],!(O>>>0<262)):0){break}if((c[(c[a>>2]|0)+4>>2]|0)==0){break}w=O;x=c[g>>2]|0}if((H|0)==28){i=f;return}H=a+5824|0;a=c[H>>2]|0;g=c[j>>2]|0;if(!(a>>>0>>0)){i=f;return}j=O+(c[l>>2]|0)|0;if(a>>>0>>0){l=g-j|0;O=l>>>0>258?258:l;Eg((c[n>>2]|0)+j|0,0,O|0)|0;c[H>>2]=O+j;i=f;return}O=j+258|0;if(!(a>>>0>>0)){i=f;return}j=O-a|0;O=g-a|0;g=j>>>0>O>>>0?O:j;Eg((c[n>>2]|0)+a|0,0,g|0)|0;c[H>>2]=(c[H>>2]|0)+g;i=f;return}function nf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;d=i;e=(c[a+12>>2]|0)+ -5|0;f=e>>>0<65535?e:65535;e=a+116|0;g=a+108|0;h=a+92|0;j=a+44|0;k=a+56|0;while(1){l=c[e>>2]|0;if(l>>>0<2){mf(a);m=c[e>>2]|0;if((m|b|0)==0){n=0;o=28;break}if((m|0)==0){o=20;break}else{p=m}}else{p=l}l=(c[g>>2]|0)+p|0;c[g>>2]=l;c[e>>2]=0;m=c[h>>2]|0;q=m+f|0;if((l|0)!=0&l>>>0>>0){r=l;s=m}else{c[e>>2]=l-q;c[g>>2]=q;if((m|0)>-1){t=(c[k>>2]|0)+m|0}else{t=0}Sf(a,t,f,0);c[h>>2]=c[g>>2];m=c[a>>2]|0;q=m+28|0;l=c[q>>2]|0;u=c[l+20>>2]|0;v=m+16|0;w=c[v>>2]|0;x=u>>>0>w>>>0?w:u;if((x|0)!=0?(u=m+12|0,Kg(c[u>>2]|0,c[l+16>>2]|0,x|0)|0,c[u>>2]=(c[u>>2]|0)+x,u=(c[q>>2]|0)+16|0,c[u>>2]=(c[u>>2]|0)+x,u=m+20|0,c[u>>2]=(c[u>>2]|0)+x,c[v>>2]=(c[v>>2]|0)-x,v=c[q>>2]|0,q=v+20|0,u=c[q>>2]|0,c[q>>2]=u-x,(u|0)==(x|0)):0){c[v+16>>2]=c[v+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=0;o=28;break}r=c[g>>2]|0;s=c[h>>2]|0}v=r-s|0;if(v>>>0<((c[j>>2]|0)+ -262|0)>>>0){continue}if((s|0)>-1){y=(c[k>>2]|0)+s|0}else{y=0}Sf(a,y,v,0);c[h>>2]=c[g>>2];v=c[a>>2]|0;x=v+28|0;u=c[x>>2]|0;q=c[u+20>>2]|0;m=v+16|0;l=c[m>>2]|0;w=q>>>0>l>>>0?l:q;if((w|0)!=0?(q=v+12|0,Kg(c[q>>2]|0,c[u+16>>2]|0,w|0)|0,c[q>>2]=(c[q>>2]|0)+w,q=(c[x>>2]|0)+16|0,c[q>>2]=(c[q>>2]|0)+w,q=v+20|0,c[q>>2]=(c[q>>2]|0)+w,c[m>>2]=(c[m>>2]|0)-w,m=c[x>>2]|0,x=m+20|0,q=c[x>>2]|0,c[x>>2]=q-w,(q|0)==(w|0)):0){c[m+16>>2]=c[m+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=0;o=28;break}}if((o|0)==20){y=c[h>>2]|0;if((y|0)>-1){z=(c[k>>2]|0)+y|0}else{z=0}k=(b|0)==4;Sf(a,z,(c[g>>2]|0)-y|0,k&1);c[h>>2]=c[g>>2];g=c[a>>2]|0;h=g+28|0;y=c[h>>2]|0;z=c[y+20>>2]|0;b=g+16|0;s=c[b>>2]|0;j=z>>>0>s>>>0?s:z;if((j|0)!=0?(z=g+12|0,Kg(c[z>>2]|0,c[y+16>>2]|0,j|0)|0,c[z>>2]=(c[z>>2]|0)+j,z=(c[h>>2]|0)+16|0,c[z>>2]=(c[z>>2]|0)+j,z=g+20|0,c[z>>2]=(c[z>>2]|0)+j,c[b>>2]=(c[b>>2]|0)-j,b=c[h>>2]|0,h=b+20|0,z=c[h>>2]|0,c[h>>2]=z-j,(z|0)==(j|0)):0){c[b+16>>2]=c[b+8>>2]}if((c[(c[a>>2]|0)+16>>2]|0)==0){n=k?2:0;i=d;return n|0}else{n=k?3:1;i=d;return n|0}}else if((o|0)==28){i=d;return n|0}return 0}function of(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0;g=i;h=e+116|0;j=(f|0)==0;k=e+72|0;l=e+88|0;m=e+108|0;n=e+56|0;o=e+84|0;p=e+68|0;q=e+52|0;r=e+64|0;s=e+44|0;t=e+96|0;u=e+112|0;v=e+5792|0;w=e+5796|0;x=e+5784|0;y=e+5788|0;z=e+128|0;A=e+92|0;while(1){if((c[h>>2]|0)>>>0<262){mf(e);B=c[h>>2]|0;if(B>>>0<262&j){C=0;D=34;break}if((B|0)==0){D=26;break}if(!(B>>>0>2)){D=9}else{D=6}}else{D=6}if((D|0)==6){D=0;B=c[m>>2]|0;E=((d[(c[n>>2]|0)+(B+2)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=E;F=(c[p>>2]|0)+(E<<1)|0;E=b[F>>1]|0;b[(c[r>>2]|0)+((c[q>>2]&B)<<1)>>1]=E;G=E&65535;b[F>>1]=B;if(!(E<<16>>16==0)?!((B-G|0)>>>0>((c[s>>2]|0)+ -262|0)>>>0):0){B=qf(e,G)|0;c[t>>2]=B;H=B}else{D=9}}if((D|0)==9){D=0;H=c[t>>2]|0}do{if(H>>>0>2){B=H+253|0;G=(c[m>>2]|0)-(c[u>>2]|0)|0;E=c[v>>2]|0;b[(c[w>>2]|0)+(E<<1)>>1]=G;c[v>>2]=E+1;a[(c[x>>2]|0)+E|0]=B;E=e+((d[25272+(B&255)|0]|0|256)+1<<2)+148|0;b[E>>1]=(b[E>>1]|0)+1<<16>>16;E=G+65535&65535;if(E>>>0<256){I=E}else{I=(E>>>7)+256|0}E=e+((d[24760+I|0]|0)<<2)+2440|0;b[E>>1]=(b[E>>1]|0)+1<<16>>16;E=(c[v>>2]|0)==((c[y>>2]|0)+ -1|0)|0;G=c[t>>2]|0;B=(c[h>>2]|0)-G|0;c[h>>2]=B;if(!(G>>>0<=(c[z>>2]|0)>>>0&B>>>0>2)){B=(c[m>>2]|0)+G|0;c[m>>2]=B;c[t>>2]=0;F=c[n>>2]|0;J=d[F+B|0]|0;c[k>>2]=J;c[k>>2]=((d[F+(B+1)|0]|0)^J<>2])&c[o>>2];K=B;L=E;break}B=G+ -1|0;c[t>>2]=B;G=c[l>>2]|0;J=c[n>>2]|0;F=c[o>>2]|0;M=c[p>>2]|0;N=c[q>>2]|0;O=c[r>>2]|0;P=B;B=c[m>>2]|0;Q=c[k>>2]|0;while(1){R=B+1|0;c[m>>2]=R;Q=((d[J+(B+3)|0]|0)^Q<>2]=Q;S=M+(Q<<1)|0;b[O+((N&R)<<1)>>1]=b[S>>1]|0;b[S>>1]=R;P=P+ -1|0;c[t>>2]=P;if((P|0)==0){break}else{B=R}}P=B+2|0;c[m>>2]=P;K=P;L=E}else{P=a[(c[n>>2]|0)+(c[m>>2]|0)|0]|0;N=c[v>>2]|0;b[(c[w>>2]|0)+(N<<1)>>1]=0;c[v>>2]=N+1;a[(c[x>>2]|0)+N|0]=P;N=e+((P&255)<<2)+148|0;b[N>>1]=(b[N>>1]|0)+1<<16>>16;N=(c[v>>2]|0)==((c[y>>2]|0)+ -1|0)|0;c[h>>2]=(c[h>>2]|0)+ -1;P=(c[m>>2]|0)+1|0;c[m>>2]=P;K=P;L=N}}while(0);if((L|0)==0){continue}N=c[A>>2]|0;if((N|0)>-1){T=(c[n>>2]|0)+N|0}else{T=0}Sf(e,T,K-N|0,0);c[A>>2]=c[m>>2];N=c[e>>2]|0;P=N+28|0;O=c[P>>2]|0;Q=c[O+20>>2]|0;M=N+16|0;F=c[M>>2]|0;G=Q>>>0>F>>>0?F:Q;if((G|0)!=0?(Q=N+12|0,Kg(c[Q>>2]|0,c[O+16>>2]|0,G|0)|0,c[Q>>2]=(c[Q>>2]|0)+G,Q=(c[P>>2]|0)+16|0,c[Q>>2]=(c[Q>>2]|0)+G,Q=N+20|0,c[Q>>2]=(c[Q>>2]|0)+G,c[M>>2]=(c[M>>2]|0)-G,M=c[P>>2]|0,P=M+20|0,Q=c[P>>2]|0,c[P>>2]=Q-G,(Q|0)==(G|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){C=0;D=34;break}}if((D|0)==26){K=c[A>>2]|0;if((K|0)>-1){U=(c[n>>2]|0)+K|0}else{U=0}n=(f|0)==4;Sf(e,U,(c[m>>2]|0)-K|0,n&1);c[A>>2]=c[m>>2];m=c[e>>2]|0;A=m+28|0;K=c[A>>2]|0;U=c[K+20>>2]|0;f=m+16|0;T=c[f>>2]|0;L=U>>>0>T>>>0?T:U;if((L|0)!=0?(U=m+12|0,Kg(c[U>>2]|0,c[K+16>>2]|0,L|0)|0,c[U>>2]=(c[U>>2]|0)+L,U=(c[A>>2]|0)+16|0,c[U>>2]=(c[U>>2]|0)+L,U=m+20|0,c[U>>2]=(c[U>>2]|0)+L,c[f>>2]=(c[f>>2]|0)-L,f=c[A>>2]|0,A=f+20|0,U=c[A>>2]|0,c[A>>2]=U-L,(U|0)==(L|0)):0){c[f+16>>2]=c[f+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){C=n?2:0;i=g;return C|0}else{C=n?3:1;i=g;return C|0}}else if((D|0)==34){i=g;return C|0}return 0}function pf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0;g=i;h=e+116|0;j=(f|0)==0;k=e+72|0;l=e+88|0;m=e+108|0;n=e+56|0;o=e+84|0;p=e+68|0;q=e+52|0;r=e+64|0;s=e+96|0;t=e+120|0;u=e+112|0;v=e+100|0;w=e+5792|0;x=e+5796|0;y=e+5784|0;z=e+5788|0;A=e+104|0;B=e+92|0;C=e+128|0;D=e+44|0;E=e+136|0;a:while(1){F=c[h>>2]|0;while(1){if(F>>>0<262){mf(e);G=c[h>>2]|0;if(G>>>0<262&j){H=0;I=50;break a}if((G|0)==0){I=40;break a}if(!(G>>>0>2)){c[t>>2]=c[s>>2];c[v>>2]=c[u>>2];c[s>>2]=2;J=2;I=16}else{I=8}}else{I=8}do{if((I|0)==8){I=0;G=c[m>>2]|0;K=((d[(c[n>>2]|0)+(G+2)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=K;L=(c[p>>2]|0)+(K<<1)|0;K=b[L>>1]|0;b[(c[r>>2]|0)+((c[q>>2]&G)<<1)>>1]=K;M=K&65535;b[L>>1]=G;G=c[s>>2]|0;c[t>>2]=G;c[v>>2]=c[u>>2];c[s>>2]=2;if(!(K<<16>>16==0)){if(G>>>0<(c[C>>2]|0)>>>0){if(!(((c[m>>2]|0)-M|0)>>>0>((c[D>>2]|0)+ -262|0)>>>0)){K=qf(e,M)|0;c[s>>2]=K;if(K>>>0<6){if((c[E>>2]|0)!=1){if((K|0)!=3){J=K;I=16;break}if(!(((c[m>>2]|0)-(c[u>>2]|0)|0)>>>0>4096)){J=3;I=16;break}}c[s>>2]=2;J=2;I=16}else{J=K;I=16}}else{J=2;I=16}}else{N=G;O=2}}else{J=2;I=16}}}while(0);if((I|0)==16){I=0;N=c[t>>2]|0;O=J}if(!(N>>>0<3|O>>>0>N>>>0)){break}if((c[A>>2]|0)==0){c[A>>2]=1;c[m>>2]=(c[m>>2]|0)+1;G=(c[h>>2]|0)+ -1|0;c[h>>2]=G;F=G;continue}G=a[(c[n>>2]|0)+((c[m>>2]|0)+ -1)|0]|0;K=c[w>>2]|0;b[(c[x>>2]|0)+(K<<1)>>1]=0;c[w>>2]=K+1;a[(c[y>>2]|0)+K|0]=G;K=e+((G&255)<<2)+148|0;b[K>>1]=(b[K>>1]|0)+1<<16>>16;if((c[w>>2]|0)==((c[z>>2]|0)+ -1|0)){K=c[B>>2]|0;if((K|0)>-1){P=(c[n>>2]|0)+K|0}else{P=0}Sf(e,P,(c[m>>2]|0)-K|0,0);c[B>>2]=c[m>>2];K=c[e>>2]|0;G=K+28|0;M=c[G>>2]|0;L=c[M+20>>2]|0;Q=K+16|0;R=c[Q>>2]|0;S=L>>>0>R>>>0?R:L;if((S|0)!=0?(L=K+12|0,Kg(c[L>>2]|0,c[M+16>>2]|0,S|0)|0,c[L>>2]=(c[L>>2]|0)+S,L=(c[G>>2]|0)+16|0,c[L>>2]=(c[L>>2]|0)+S,L=K+20|0,c[L>>2]=(c[L>>2]|0)+S,c[Q>>2]=(c[Q>>2]|0)-S,Q=c[G>>2]|0,G=Q+20|0,L=c[G>>2]|0,c[G>>2]=L-S,(L|0)==(S|0)):0){c[Q+16>>2]=c[Q+8>>2]}}c[m>>2]=(c[m>>2]|0)+1;Q=(c[h>>2]|0)+ -1|0;c[h>>2]=Q;if((c[(c[e>>2]|0)+16>>2]|0)==0){H=0;I=50;break a}else{F=Q}}F=c[m>>2]|0;Q=F+ -3+(c[h>>2]|0)|0;S=N+253|0;L=F+65535-(c[v>>2]|0)|0;F=c[w>>2]|0;b[(c[x>>2]|0)+(F<<1)>>1]=L;c[w>>2]=F+1;a[(c[y>>2]|0)+F|0]=S;F=e+((d[25272+(S&255)|0]|0|256)+1<<2)+148|0;b[F>>1]=(b[F>>1]|0)+1<<16>>16;F=L+65535&65535;if(F>>>0<256){T=F}else{T=(F>>>7)+256|0}F=e+((d[24760+T|0]|0)<<2)+2440|0;b[F>>1]=(b[F>>1]|0)+1<<16>>16;F=c[w>>2]|0;L=(c[z>>2]|0)+ -1|0;S=c[t>>2]|0;c[h>>2]=1-S+(c[h>>2]|0);G=S+ -2|0;c[t>>2]=G;S=c[m>>2]|0;K=G;while(1){G=S+1|0;c[m>>2]=G;if(!(G>>>0>Q>>>0)){M=((d[(c[n>>2]|0)+(S+3)|0]|0)^c[k>>2]<>2])&c[o>>2];c[k>>2]=M;R=(c[p>>2]|0)+(M<<1)|0;b[(c[r>>2]|0)+((c[q>>2]&G)<<1)>>1]=b[R>>1]|0;b[R>>1]=G}K=K+ -1|0;c[t>>2]=K;if((K|0)==0){break}else{S=G}}c[A>>2]=0;c[s>>2]=2;K=S+2|0;c[m>>2]=K;if((F|0)!=(L|0)){continue}Q=c[B>>2]|0;if((Q|0)>-1){U=(c[n>>2]|0)+Q|0}else{U=0}Sf(e,U,K-Q|0,0);c[B>>2]=c[m>>2];Q=c[e>>2]|0;K=Q+28|0;G=c[K>>2]|0;R=c[G+20>>2]|0;M=Q+16|0;V=c[M>>2]|0;W=R>>>0>V>>>0?V:R;if((W|0)!=0?(R=Q+12|0,Kg(c[R>>2]|0,c[G+16>>2]|0,W|0)|0,c[R>>2]=(c[R>>2]|0)+W,R=(c[K>>2]|0)+16|0,c[R>>2]=(c[R>>2]|0)+W,R=Q+20|0,c[R>>2]=(c[R>>2]|0)+W,c[M>>2]=(c[M>>2]|0)-W,M=c[K>>2]|0,K=M+20|0,R=c[K>>2]|0,c[K>>2]=R-W,(R|0)==(W|0)):0){c[M+16>>2]=c[M+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){H=0;I=50;break}}if((I|0)==40){if((c[A>>2]|0)!=0){U=a[(c[n>>2]|0)+((c[m>>2]|0)+ -1)|0]|0;s=c[w>>2]|0;b[(c[x>>2]|0)+(s<<1)>>1]=0;c[w>>2]=s+1;a[(c[y>>2]|0)+s|0]=U;s=e+((U&255)<<2)+148|0;b[s>>1]=(b[s>>1]|0)+1<<16>>16;c[A>>2]=0}A=c[B>>2]|0;if((A|0)>-1){X=(c[n>>2]|0)+A|0}else{X=0}n=(f|0)==4;Sf(e,X,(c[m>>2]|0)-A|0,n&1);c[B>>2]=c[m>>2];m=c[e>>2]|0;B=m+28|0;A=c[B>>2]|0;X=c[A+20>>2]|0;f=m+16|0;s=c[f>>2]|0;U=X>>>0>s>>>0?s:X;if((U|0)!=0?(X=m+12|0,Kg(c[X>>2]|0,c[A+16>>2]|0,U|0)|0,c[X>>2]=(c[X>>2]|0)+U,X=(c[B>>2]|0)+16|0,c[X>>2]=(c[X>>2]|0)+U,X=m+20|0,c[X>>2]=(c[X>>2]|0)+U,c[f>>2]=(c[f>>2]|0)-U,f=c[B>>2]|0,B=f+20|0,X=c[B>>2]|0,c[B>>2]=X-U,(X|0)==(U|0)):0){c[f+16>>2]=c[f+8>>2]}if((c[(c[e>>2]|0)+16>>2]|0)==0){H=n?2:0;i=g;return H|0}else{H=n?3:1;i=g;return H|0}}else if((I|0)==50){i=g;return H|0}return 0}function qf(b,d){b=b|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;f=i;g=c[b+124>>2]|0;h=c[b+56>>2]|0;j=c[b+108>>2]|0;k=h+j|0;l=c[b+120>>2]|0;m=c[b+144>>2]|0;n=(c[b+44>>2]|0)+ -262|0;o=j>>>0>n>>>0?j-n|0:0;n=c[b+64>>2]|0;p=c[b+52>>2]|0;q=h+(j+258)|0;r=c[b+116>>2]|0;s=m>>>0>r>>>0?r:m;m=b+112|0;t=h+(j+1)|0;u=h+(j+2)|0;v=q;w=j+257|0;x=d;d=l;y=l>>>0<(c[b+140>>2]|0)>>>0?g:g>>>2;g=a[h+(l+j)|0]|0;b=a[h+(j+ -1+l)|0]|0;while(1){l=h+x|0;if((((a[h+(x+d)|0]|0)==g<<24>>24?(a[h+(d+ -1+x)|0]|0)==b<<24>>24:0)?(a[l]|0)==(a[k]|0):0)?(a[h+(x+1)|0]|0)==(a[t]|0):0){l=h+(x+2)|0;z=u;while(1){A=z+1|0;if((a[A]|0)!=(a[l+1|0]|0)){B=A;break}A=z+2|0;if((a[A]|0)!=(a[l+2|0]|0)){B=A;break}A=z+3|0;if((a[A]|0)!=(a[l+3|0]|0)){B=A;break}A=z+4|0;if((a[A]|0)!=(a[l+4|0]|0)){B=A;break}A=z+5|0;if((a[A]|0)!=(a[l+5|0]|0)){B=A;break}A=z+6|0;if((a[A]|0)!=(a[l+6|0]|0)){B=A;break}A=z+7|0;if((a[A]|0)!=(a[l+7|0]|0)){B=A;break}A=z+8|0;C=l+8|0;if((a[A]|0)==(a[C]|0)&A>>>0>>0){l=C;z=A}else{B=A;break}}z=B-v|0;l=z+258|0;if((l|0)>(d|0)){c[m>>2]=x;if((l|0)>=(s|0)){D=l;E=20;break}F=l;G=a[h+(l+j)|0]|0;H=a[h+(w+z)|0]|0}else{F=d;G=g;H=b}}else{F=d;G=g;H=b}z=e[n+((x&p)<<1)>>1]|0;if(!(z>>>0>o>>>0)){D=F;E=20;break}l=y+ -1|0;if((l|0)==0){D=F;E=20;break}else{x=z;d=F;y=l;g=G;b=H}}if((E|0)==20){i=f;return(D>>>0>r>>>0?r:D)|0}return 0}function rf(a){a=a|0;var b=0,d=0;b=i;do{if((a|0)!=0){if((c[a>>2]|0)==7247){d=Af(a)|0;break}else{d=Ff(a)|0;break}}else{d=-2}}while(0);i=b;return d|0}function sf(a,b){a=a|0;b=b|0;var c=0,d=0;c=i;d=tf(a,-1,b)|0;i=c;return d|0}function tf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;i=i+16|0;g=f;h=gg(140)|0;if((h|0)==0){j=0;i=f;return j|0}c[h+16>>2]=0;c[h+20>>2]=8192;k=h+80|0;c[k>>2]=0;c[h>>2]=0;l=h+60|0;c[l>>2]=-1;m=h+64|0;c[m>>2]=0;n=a[e]|0;if(!(n<<24>>24==0)){o=e;e=n;n=0;a:while(1){p=e<<24>>24;b:do{if((e+ -48<<24>>24&255)<10){c[l>>2]=p+ -48;q=n}else{switch(p|0){case 70:{c[m>>2]=4;q=n;break b;break};case 43:{r=9;break a;break};case 82:{c[m>>2]=3;q=n;break b;break};case 102:{c[m>>2]=1;q=n;break b;break};case 104:{c[m>>2]=2;q=n;break b;break};case 119:{c[h>>2]=31153;q=31153;break b;break};case 97:{c[h>>2]=1;q=1;break b;break};case 114:{c[h>>2]=7247;q=7247;break b;break};default:{q=n;break b}}}}while(0);o=o+1|0;e=a[o]|0;if(e<<24>>24==0){break}else{n=q}}if((r|0)==9){hg(h);j=0;i=f;return j|0}if((q|0)!=0){q=gg((Dg(b|0)|0)+1|0)|0;r=h+8|0;c[r>>2]=q;if((q|0)==0){hg(h);j=0;i=f;return j|0}Lg(q|0,b|0)|0;if((d|0)==-1){q=c[h>>2]|0;if((q|0)==7247){s=32768}else{s=(q|0)==31153?33345:33857}c[g>>2]=438;q=Aa(b|0,s|0,g|0)|0;c[h+4>>2]=q;if((q|0)==-1){hg(c[r>>2]|0);hg(h);j=0;i=f;return j|0}else{t=q}}else{c[h+4>>2]=d;t=d}d=c[h>>2]|0;if((d|0)==1){c[h>>2]=31153}else if((d|0)==7247?(d=ra(t|0,0,1)|0,c[h+44>>2]=(d|0)==-1?0:d,(c[h>>2]|0)==7247):0){c[h+36>>2]=0;c[h+40>>2]=0;c[h+52>>2]=0;c[h+56>>2]=1}c[h+72>>2]=0;d=c[k>>2]|0;t=h+76|0;if((d|0)!=0){if(!((c[t>>2]|0)==-4)){hg(d)}c[k>>2]=0}c[t>>2]=0;c[h+12>>2]=0;c[h+88>>2]=0;j=h;i=f;return j|0}}hg(h);j=0;i=f;return j|0}function uf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;e=i;if((a|0)==0){f=-1;i=e;return f|0}g=c[a>>2]|0;if(!((g|0)==31153|(g|0)==7247)){f=-1;i=e;return f|0}h=a+76|0;if((c[h>>2]|0)!=0|d>>>0>1){f=-1;i=e;return f|0}if((d|0)!=0){d=a+72|0;if((c[d>>2]|0)==0){j=b;k=d}else{j=(c[a+68>>2]|0)+b|0;k=d}}else{j=b-(c[a+12>>2]|0)|0;k=a+72|0}c[k>>2]=0;b=(g|0)==7247;if((b?(c[a+52>>2]|0)==1:0)?(d=a+12|0,((c[d>>2]|0)+j|0)>=(c[a+48>>2]|0)):0){l=a+36|0;if((ra(c[a+4>>2]|0,j-(c[l>>2]|0)|0,1)|0)==-1){f=-1;i=e;return f|0}c[l>>2]=0;c[a+40>>2]=0;c[k>>2]=0;l=a+80|0;m=c[l>>2]|0;if((m|0)!=0){if(!((c[h>>2]|0)==-4)){hg(m)}c[l>>2]=0}c[h>>2]=0;c[a+88>>2]=0;l=(c[d>>2]|0)+j|0;c[d>>2]=l;f=l;i=e;return f|0}if((j|0)<0){if(!b){f=-1;i=e;return f|0}b=a+12|0;l=(c[b>>2]|0)+j|0;if((l|0)<0){f=-1;i=e;return f|0}if((ra(c[a+4>>2]|0,c[a+44>>2]|0,0)|0)==-1){f=-1;i=e;return f|0}d=c[a>>2]|0;if((d|0)==7247){c[a+36>>2]=0;c[a+40>>2]=0;c[a+52>>2]=0;c[a+56>>2]=1}c[k>>2]=0;m=a+80|0;n=c[m>>2]|0;if((n|0)==0){o=d}else{if((c[h>>2]|0)==-4){p=d}else{hg(n);p=c[a>>2]|0}c[m>>2]=0;o=p}c[h>>2]=0;c[b>>2]=0;c[a+88>>2]=0;q=l;r=o}else{q=j;r=g}if((r|0)==7247){r=a+36|0;g=c[r>>2]|0;j=(g|0)<0|(g|0)>(q|0)?q:g;c[r>>2]=g-j;g=a+32|0;c[g>>2]=(c[g>>2]|0)+j;g=a+12|0;c[g>>2]=j+(c[g>>2]|0);s=q-j|0}else{s=q}if((s|0)!=0){c[k>>2]=1;c[a+68>>2]=s}f=(c[a+12>>2]|0)+s|0;i=e;return f|0}function vf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0;f=i;g=b+80|0;h=c[g>>2]|0;j=b+76|0;if((h|0)!=0){if(!((c[j>>2]|0)==-4)){hg(h)}c[g>>2]=0}c[j>>2]=d;if((e|0)==0){i=f;return}if((d|0)==-4){c[g>>2]=e;i=f;return}d=c[b+8>>2]|0;b=Dg(d|0)|0;h=gg(b+3+(Dg(e|0)|0)|0)|0;c[g>>2]=h;if((h|0)==0){c[j>>2]=-4;c[g>>2]=21280;i=f;return}else{Lg(h|0,d|0)|0;d=c[g>>2]|0;h=d+(Dg(d|0)|0)|0;a[h+0|0]=a[21296|0]|0;a[h+1|0]=a[21297|0]|0;a[h+2|0]=a[21298|0]|0;Fg(c[g>>2]|0,e|0)|0;i=f;return}}function wf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=uf(a,b,c)|0;i=d;return e|0}function xf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0;e=i;if((a|0)==0){f=-1;i=e;return f|0}if((c[a>>2]|0)!=7247){f=-1;i=e;return f|0}if((c[a+76>>2]|0)!=0){f=-1;i=e;return f|0}if((d|0)<0){vf(a,-5,21304);f=-1;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}g=a+72|0;a:do{if((c[g>>2]|0)!=0){c[g>>2]=0;h=c[a+68>>2]|0;j=a+36|0;k=a+40|0;l=a+88|0;m=a+32|0;n=a+12|0;if((h|0)!=0){o=a+52|0;p=a+28|0;q=a+16|0;r=a+4|0;s=a+100|0;t=a+96|0;u=h;b:while(1){c:while(1){v=c[j>>2]|0;while(1){if((v|0)!=0){break c}if((c[k>>2]|0)!=0?(c[l>>2]|0)==0:0){w=j;x=k;y=m;z=l;A=n;break a}h=c[o>>2]|0;if((h|0)!=0){B=h;break}if((zf(a)|0)==-1){f=-1;C=59;break b}h=c[j>>2]|0;if((h|0)==0){C=21;break}else{v=h}}if((C|0)==21){C=0;B=c[o>>2]|0}if((B|0)==2){c[s>>2]=c[q>>2]<<1;c[t>>2]=c[p>>2];if((yf(a)|0)==-1){f=-1;C=59;break b}else{continue}}else if((B|0)!=1){continue}h=c[p>>2]|0;D=c[q>>2]<<1;c[j>>2]=0;E=0;do{F=Za(c[r>>2]|0,h+E|0,D-E|0)|0;if((F|0)<1){C=26;break}E=(c[j>>2]|0)+F|0;c[j>>2]=E}while(E>>>0>>0);if((C|0)==26){C=0;if((F|0)<0){C=28;break b}c[k>>2]=1}c[m>>2]=c[p>>2]}D=(v|0)<0|(v|0)>(u|0)?u:v;c[j>>2]=v-D;c[m>>2]=(c[m>>2]|0)+D;c[n>>2]=(c[n>>2]|0)+D;if((u|0)==(D|0)){w=j;x=k;y=m;z=l;A=n;break a}else{u=u-D|0}}if((C|0)==28){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==59){i=e;return f|0}}else{w=j;x=k;y=m;z=l;A=n}}else{w=a+36|0;x=a+40|0;y=a+32|0;z=a+88|0;A=a+12|0}}while(0);v=a+52|0;F=a+28|0;B=a+16|0;g=a+4|0;u=a+100|0;p=a+96|0;r=b;b=d;d=0;d:while(1){q=c[w>>2]|0;e:do{if((q|0)==0){if((c[x>>2]|0)!=0?(c[z>>2]|0)==0:0){f=d;C=59;break d}t=c[v>>2]|0;if((t|0)!=0){if(b>>>0>2]<<1>>>0){G=t}else{if((t|0)==1){H=0}else{c[u>>2]=b;c[p>>2]=r;if((yf(a)|0)==-1){f=-1;C=59;break d}t=c[w>>2]|0;c[w>>2]=0;I=t;C=57;break}while(1){J=Za(c[g>>2]|0,r+H|0,b-H|0)|0;if((J|0)<1){break}t=J+H|0;if(t>>>0>>0){H=t}else{I=t;C=57;break e}}if((J|0)<0){C=54;break d}c[x>>2]=1;I=H;C=57;break}}else{if((zf(a)|0)==-1){f=-1;C=59;break d}if((c[w>>2]|0)!=0){K=r;L=b;M=d;break}G=c[v>>2]|0}if((G|0)==2){c[u>>2]=c[B>>2]<<1;c[p>>2]=c[F>>2];if((yf(a)|0)==-1){f=-1;C=59;break d}else{K=r;L=b;M=d;break}}else if((G|0)!=1){K=r;L=b;M=d;break}t=c[F>>2]|0;s=c[B>>2]<<1;c[w>>2]=0;o=0;do{N=Za(c[g>>2]|0,t+o|0,s-o|0)|0;if((N|0)<1){C=44;break}o=(c[w>>2]|0)+N|0;c[w>>2]=o}while(o>>>0>>0);if((C|0)==44){C=0;if((N|0)<0){C=46;break d}c[x>>2]=1}c[y>>2]=c[F>>2];K=r;L=b;M=d}else{s=q>>>0>b>>>0?b:q;Kg(r|0,c[y>>2]|0,s|0)|0;c[y>>2]=(c[y>>2]|0)+s;c[w>>2]=(c[w>>2]|0)-s;I=s;C=57}}while(0);if((C|0)==57){C=0;c[A>>2]=(c[A>>2]|0)+I;K=r+I|0;L=b-I|0;M=I+d|0}if((L|0)==0){f=M;C=59;break}else{r=K;b=L;d=M}}if((C|0)==46){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==54){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);f=-1;i=e;return f|0}else if((C|0)==59){i=e;return f|0}return 0}function yf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;b=i;i=i+16|0;d=b+4|0;e=b;f=a+84|0;g=a+100|0;h=c[g>>2]|0;j=a+88|0;k=a+76|0;l=a+40|0;m=a+24|0;n=a+16|0;o=a+4|0;p=a+84|0;while(1){if((c[j>>2]|0)==0){if((c[k>>2]|0)!=0){q=-1;r=27;break}if((c[l>>2]|0)!=0){r=12;break}s=c[m>>2]|0;t=c[n>>2]|0;c[j>>2]=0;u=0;while(1){v=Za(c[o>>2]|0,s+u|0,t-u|0)|0;if((v|0)<1){r=8;break}w=(c[j>>2]|0)+v|0;c[j>>2]=w;if(w>>>0>>0){u=w}else{x=w;break}}if((r|0)==8){r=0;if((v|0)<0){r=10;break}c[l>>2]=1;x=c[j>>2]|0}c[p>>2]=c[m>>2];if((x|0)==0){r=12;break}}u=Kf(f,0)|0;if((u|0)==-4){r=15;break}else if((u|0)==-3){r=16;break}else if((u|0)==2|(u|0)==-2){r=14;break}y=c[g>>2]|0;z=(u|0)==1;if((y|0)==0|z){r=18;break}}if((r|0)==10){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);q=-1;i=b;return q|0}else if((r|0)==12){vf(a,-3,21432);q=-1;i=b;return q|0}else if((r|0)==14){vf(a,-2,21456);q=-1;i=b;return q|0}else if((r|0)==15){vf(a,-4,21344);q=-1;i=b;return q|0}else if((r|0)==16){g=c[a+108>>2]|0;vf(a,-3,(g|0)==0?21496:g);q=-1;i=b;return q|0}else if((r|0)==18){g=h-y|0;c[a+36>>2]=g;y=(c[a+96>>2]|0)+(0-g)|0;c[a+32>>2]=y;h=a+132|0;c[h>>2]=gf(c[h>>2]|0,y,g)|0;if(!z){q=0;i=b;return q|0}if(!((Bf(a,d)|0)==-1)?!((Bf(a,e)|0)==-1):0){if((c[d>>2]|0)!=(c[h>>2]|0)){vf(a,-3,21520);q=-1;i=b;return q|0}if((c[e>>2]|0)==(c[a+104>>2]|0)){c[a+52>>2]=0;q=0;i=b;return q|0}else{vf(a,-3,21544);q=-1;i=b;return q|0}}vf(a,-3,21432);q=-1;i=b;return q|0}else if((r|0)==27){i=b;return q|0}return 0}function zf(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0;e=i;f=b+84|0;g=b+16|0;do{if((c[g>>2]|0)==0){h=c[b+20>>2]|0;j=gg(h)|0;k=b+24|0;c[k>>2]=j;l=gg(h<<1)|0;m=b+28|0;c[m>>2]=l;n=(l|0)==0;if(!((j|0)==0|n)){c[g>>2]=h;c[b+116>>2]=0;c[b+120>>2]=0;c[b+124>>2]=0;h=b+88|0;c[h>>2]=0;c[f>>2]=0;if((Jf(f,-15,21360,56)|0)==0){o=h;break}hg(c[m>>2]|0);hg(c[k>>2]|0);c[g>>2]=0;vf(b,-4,21344);p=-1;i=e;return p|0}if(n){q=j}else{hg(l);q=c[k>>2]|0}if((q|0)!=0){hg(q)}vf(b,-4,21344);p=-1;i=e;return p|0}else{o=b+88|0}}while(0);q=c[o>>2]|0;if((q|0)==0){if((c[b+76>>2]|0)!=0){p=-1;i=e;return p|0}k=b+40|0;if((c[k>>2]|0)!=0){p=0;i=e;return p|0}l=b+24|0;j=c[l>>2]|0;n=c[g>>2]|0;c[o>>2]=0;m=b+4|0;h=0;while(1){r=Za(c[m>>2]|0,j+h|0,n-h|0)|0;if((r|0)<1){s=17;break}t=(c[o>>2]|0)+r|0;c[o>>2]=t;if(t>>>0>>0){h=t}else{u=t;break}}do{if((s|0)==17){if((r|0)>=0){c[k>>2]=1;u=c[o>>2]|0;break}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);p=-1;i=e;return p|0}}while(0);c[b+84>>2]=c[l>>2];if((u|0)==0){p=0;i=e;return p|0}else{v=u}}else{v=q}q=c[f>>2]|0;if((a[q]|0)==31){u=v+ -1|0;c[o>>2]=u;l=q+1|0;c[f>>2]=l;if((u|0)==0){if((c[b+76>>2]|0)!=0){p=-1;i=e;return p|0}q=b+40|0;if((c[q>>2]|0)==0){k=b+24|0;r=c[k>>2]|0;h=c[g>>2]|0;c[o>>2]=0;n=b+4|0;j=0;while(1){w=Za(c[n>>2]|0,r+j|0,h-j|0)|0;if((w|0)<1){s=29;break}m=(c[o>>2]|0)+w|0;c[o>>2]=m;if(m>>>0>>0){j=m}else{x=m;break}}do{if((s|0)==29){if((w|0)>=0){c[q>>2]=1;x=c[o>>2]|0;break}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);p=-1;i=e;return p|0}}while(0);q=c[k>>2]|0;c[b+84>>2]=q;if((x|0)!=0){y=q;z=x;s=33}}}else{y=l;z=u;s=33}if((s|0)==33?(a[y]|0)==-117:0){u=z+ -1|0;c[o>>2]=u;z=y+1|0;c[f>>2]=z;a:do{if((u|0)==0){if((c[b+76>>2]|0)==0?(y=b+40|0,(c[y>>2]|0)==0):0){l=b+24|0;x=c[l>>2]|0;q=c[g>>2]|0;c[o>>2]=0;k=b+4|0;w=0;while(1){A=Za(c[k>>2]|0,x+w|0,q-w|0)|0;if((A|0)<1){s=40;break}j=(c[o>>2]|0)+A|0;c[o>>2]=j;if(j>>>0>>0){w=j}else{B=j;break}}do{if((s|0)==40){if((A|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break a}else{c[y>>2]=1;B=c[o>>2]|0;break}}}while(0);y=c[l>>2]|0;c[b+84>>2]=y;if((B|0)!=0){C=B;D=y;s=44}}}else{C=u;D=z;s=44}}while(0);if((s|0)==44?(z=C+ -1|0,c[o>>2]=z,C=D+1|0,c[f>>2]=C,(a[D]|0)==8):0){b:do{if((z|0)==0){if((c[b+76>>2]|0)==0?(D=b+40|0,(c[D>>2]|0)==0):0){u=b+24|0;B=c[u>>2]|0;A=c[g>>2]|0;c[o>>2]=0;y=b+4|0;w=0;while(1){E=Za(c[y>>2]|0,B+w|0,A-w|0)|0;if((E|0)<1){s=52;break}q=(c[o>>2]|0)+E|0;c[o>>2]=q;if(q>>>0>>0){w=q}else{F=q;break}}do{if((s|0)==52){if((E|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break b}else{c[D>>2]=1;F=c[o>>2]|0;break}}}while(0);D=c[u>>2]|0;c[b+84>>2]=D;if((F|0)!=0){G=F;H=D;s=56}}}else{G=z;H=C;s=56}}while(0);if((s|0)==56?(C=G+ -1|0,c[o>>2]=C,G=H+1|0,c[f>>2]=G,z=d[H]|0,(z&224|0)==0):0){c:do{if((C|0)==0){H=b+76|0;if((c[H>>2]|0)==0){F=b+40|0;if((c[F>>2]|0)==0){E=b+24|0;D=c[E>>2]|0;w=c[g>>2]|0;c[o>>2]=0;A=b+4|0;B=0;while(1){I=Za(c[A>>2]|0,D+B|0,w-B|0)|0;if((I|0)<1){s=64;break}y=(c[o>>2]|0)+I|0;c[o>>2]=y;if(y>>>0>>0){B=y}else{J=y;break}}do{if((s|0)==64){if((I|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);K=c[o>>2]|0;s=69;break c}else{c[F>>2]=1;J=c[o>>2]|0;break}}}while(0);F=c[E>>2]|0;c[b+84>>2]=F;if((J|0)!=0){L=J;M=F;s=68}else{N=H;s=71}}else{N=H;s=71}}else{s=70}}else{L=C;M=G;s=68}}while(0);if((s|0)==68){G=L+ -1|0;c[o>>2]=G;c[f>>2]=M+1;K=G;s=69}if((s|0)==69){if((K|0)==0){s=70}else{O=K;s=80}}if((s|0)==70){N=b+76|0;s=71}d:do{if((s|0)==71){if((c[N>>2]|0)==0){K=b+40|0;if((c[K>>2]|0)==0){G=b+24|0;M=c[G>>2]|0;L=c[g>>2]|0;c[o>>2]=0;C=b+4|0;J=0;while(1){P=Za(c[C>>2]|0,M+J|0,L-J|0)|0;if((P|0)<1){s=76;break}I=(c[o>>2]|0)+P|0;c[o>>2]=I;if(I>>>0>>0){J=I}else{Q=I;break}}do{if((s|0)==76){if((P|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);R=c[o>>2]|0;s=81;break d}else{c[K>>2]=1;Q=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[G>>2];if((Q|0)!=0){O=Q;s=80}else{S=N;s=83}}else{S=N;s=83}}else{s=82}}}while(0);if((s|0)==80){N=O+ -1|0;c[o>>2]=N;c[f>>2]=(c[f>>2]|0)+1;R=N;s=81}if((s|0)==81){if((R|0)==0){s=82}else{T=R;s=92}}if((s|0)==82){S=b+76|0;s=83}e:do{if((s|0)==83){if((c[S>>2]|0)==0){R=b+40|0;if((c[R>>2]|0)==0){N=b+24|0;O=c[N>>2]|0;Q=c[g>>2]|0;c[o>>2]=0;P=b+4|0;K=0;while(1){U=Za(c[P>>2]|0,O+K|0,Q-K|0)|0;if((U|0)<1){s=88;break}J=(c[o>>2]|0)+U|0;c[o>>2]=J;if(J>>>0>>0){K=J}else{V=J;break}}do{if((s|0)==88){if((U|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);W=c[o>>2]|0;s=93;break e}else{c[R>>2]=1;V=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[N>>2];if((V|0)!=0){T=V;s=92}else{X=S;s=95}}else{X=S;s=95}}else{s=94}}}while(0);if((s|0)==92){S=T+ -1|0;c[o>>2]=S;c[f>>2]=(c[f>>2]|0)+1;W=S;s=93}if((s|0)==93){if((W|0)==0){s=94}else{Y=W;s=104}}if((s|0)==94){X=b+76|0;s=95}f:do{if((s|0)==95){if((c[X>>2]|0)==0){W=b+40|0;if((c[W>>2]|0)==0){S=b+24|0;T=c[S>>2]|0;V=c[g>>2]|0;c[o>>2]=0;U=b+4|0;R=0;while(1){Z=Za(c[U>>2]|0,T+R|0,V-R|0)|0;if((Z|0)<1){s=100;break}K=(c[o>>2]|0)+Z|0;c[o>>2]=K;if(K>>>0>>0){R=K}else{_=K;break}}do{if((s|0)==100){if((Z|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);$=c[o>>2]|0;s=105;break f}else{c[W>>2]=1;_=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[S>>2];if((_|0)!=0){Y=_;s=104}else{aa=X;s=107}}else{aa=X;s=107}}else{s=106}}}while(0);if((s|0)==104){X=Y+ -1|0;c[o>>2]=X;c[f>>2]=(c[f>>2]|0)+1;$=X;s=105}if((s|0)==105){if(($|0)==0){s=106}else{ba=$;s=116}}if((s|0)==106){aa=b+76|0;s=107}g:do{if((s|0)==107){if((c[aa>>2]|0)==0){$=b+40|0;if((c[$>>2]|0)==0){X=b+24|0;Y=c[X>>2]|0;_=c[g>>2]|0;c[o>>2]=0;Z=b+4|0;W=0;while(1){ca=Za(c[Z>>2]|0,Y+W|0,_-W|0)|0;if((ca|0)<1){s=112;break}R=(c[o>>2]|0)+ca|0;c[o>>2]=R;if(R>>>0<_>>>0){W=R}else{da=R;break}}do{if((s|0)==112){if((ca|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);ea=c[o>>2]|0;s=117;break g}else{c[$>>2]=1;da=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[X>>2];if((da|0)!=0){ba=da;s=116}else{fa=aa;s=119}}else{fa=aa;s=119}}else{s=118}}}while(0);if((s|0)==116){aa=ba+ -1|0;c[o>>2]=aa;c[f>>2]=(c[f>>2]|0)+1;ea=aa;s=117}if((s|0)==117){if((ea|0)==0){s=118}else{ga=ea;s=128}}if((s|0)==118){fa=b+76|0;s=119}h:do{if(((s|0)==119?(c[fa>>2]|0)==0:0)?(ea=b+40|0,(c[ea>>2]|0)==0):0){aa=b+24|0;ba=c[aa>>2]|0;da=c[g>>2]|0;c[o>>2]=0;ca=b+4|0;$=0;while(1){ha=Za(c[ca>>2]|0,ba+$|0,da-$|0)|0;if((ha|0)<1){s=124;break}W=(c[o>>2]|0)+ha|0;c[o>>2]=W;if(W>>>0>>0){$=W}else{ia=W;break}}do{if((s|0)==124){if((ha|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break h}else{c[ea>>2]=1;ia=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[aa>>2];if((ia|0)!=0){ga=ia;s=128}}}while(0);if((s|0)==128){c[o>>2]=ga+ -1;c[f>>2]=(c[f>>2]|0)+1}i:do{if((z&4|0)!=0){ga=c[o>>2]|0;j:do{if((ga|0)==0){ia=b+76|0;if((c[ia>>2]|0)==0){ha=b+40|0;if((c[ha>>2]|0)==0){fa=b+24|0;ea=c[fa>>2]|0;$=c[g>>2]|0;c[o>>2]=0;da=b+4|0;ba=0;while(1){ja=Za(c[da>>2]|0,ea+ba|0,$-ba|0)|0;if((ja|0)<1){s=136;break}ca=(c[o>>2]|0)+ja|0;c[o>>2]=ca;if(ca>>>0<$>>>0){ba=ca}else{ka=ca;break}}do{if((s|0)==136){if((ja|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);la=-1;ma=c[o>>2]|0;s=141;break j}else{c[ha>>2]=1;ka=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[fa>>2];if((ka|0)!=0){na=ka;s=140}else{oa=ia;pa=-1;s=143}}else{oa=ia;pa=-1;s=143}}else{qa=-1;s=142}}else{na=ga;s=140}}while(0);if((s|0)==140){ga=na+ -1|0;c[o>>2]=ga;aa=c[f>>2]|0;c[f>>2]=aa+1;la=d[aa]|0;ma=ga;s=141}if((s|0)==141){if((ma|0)==0){qa=la;s=142}else{ra=ma;sa=la;s=152}}if((s|0)==142){oa=b+76|0;pa=qa;s=143}k:do{if((s|0)==143){if((c[oa>>2]|0)==0?(ga=b+40|0,(c[ga>>2]|0)==0):0){aa=b+24|0;ha=c[aa>>2]|0;ba=c[g>>2]|0;c[o>>2]=0;$=b+4|0;ea=0;while(1){ta=Za(c[$>>2]|0,ha+ea|0,ba-ea|0)|0;if((ta|0)<1){s=148;break}da=(c[o>>2]|0)+ta|0;c[o>>2]=da;if(da>>>0>>0){ea=da}else{ua=da;break}}do{if((s|0)==148){if((ta|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);va=-256;wa=pa;break k}else{c[ga>>2]=1;ua=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[aa>>2];if((ua|0)!=0){ra=ua;sa=pa;s=152}else{va=-256;wa=pa}}else{va=-256;wa=pa}}}while(0);if((s|0)==152){c[o>>2]=ra+ -1;ga=c[f>>2]|0;c[f>>2]=ga+1;va=d[ga]<<8;wa=sa}ga=va+wa|0;if((ga|0)!=0){ea=b+76|0;ba=b+40|0;ha=b+24|0;$=b+4|0;ia=b+84|0;fa=ga;ga=c[o>>2]|0;while(1){fa=fa+ -1|0;if((ga|0)==0){if((c[ea>>2]|0)!=0){break i}if((c[ba>>2]|0)!=0){break i}da=c[ha>>2]|0;ca=c[g>>2]|0;c[o>>2]=0;X=0;while(1){xa=Za(c[$>>2]|0,da+X|0,ca-X|0)|0;if((xa|0)<1){s=161;break}W=(c[o>>2]|0)+xa|0;c[o>>2]=W;if(W>>>0>>0){X=W}else{ya=W;break}}if((s|0)==161){s=0;if((xa|0)<0){break}c[ba>>2]=1;ya=c[o>>2]|0}c[ia>>2]=c[ha>>2];if((ya|0)==0){break i}else{za=ya}}else{za=ga}ga=za+ -1|0;c[o>>2]=ga;c[f>>2]=(c[f>>2]|0)+1;if((fa|0)==0){break i}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}}while(0);l:do{if((z&8|0)!=0){za=b+76|0;ya=b+40|0;xa=b+24|0;wa=b+4|0;va=b+84|0;sa=c[o>>2]|0;while(1){if((sa|0)==0){if((c[za>>2]|0)!=0){break l}if((c[ya>>2]|0)!=0){break l}ra=c[xa>>2]|0;pa=c[g>>2]|0;c[o>>2]=0;ua=0;while(1){Aa=Za(c[wa>>2]|0,ra+ua|0,pa-ua|0)|0;if((Aa|0)<1){s=174;break}ta=(c[o>>2]|0)+Aa|0;c[o>>2]=ta;if(ta>>>0>>0){ua=ta}else{Ba=ta;break}}if((s|0)==174){s=0;if((Aa|0)<0){break}c[ya>>2]=1;Ba=c[o>>2]|0}c[va>>2]=c[xa>>2];if((Ba|0)==0){break l}else{Ca=Ba}}else{Ca=sa}sa=Ca+ -1|0;c[o>>2]=sa;ua=c[f>>2]|0;c[f>>2]=ua+1;if((a[ua]|0)==0){break l}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}while(0);m:do{if((z&16|0)!=0){Ca=b+76|0;Ba=b+40|0;Aa=b+24|0;sa=b+4|0;xa=b+84|0;va=c[o>>2]|0;while(1){if((va|0)==0){if((c[Ca>>2]|0)!=0){break m}if((c[Ba>>2]|0)!=0){break m}ya=c[Aa>>2]|0;wa=c[g>>2]|0;c[o>>2]=0;za=0;while(1){Da=Za(c[sa>>2]|0,ya+za|0,wa-za|0)|0;if((Da|0)<1){s=187;break}ua=(c[o>>2]|0)+Da|0;c[o>>2]=ua;if(ua>>>0>>0){za=ua}else{Ea=ua;break}}if((s|0)==187){s=0;if((Da|0)<0){break}c[Ba>>2]=1;Ea=c[o>>2]|0}c[xa>>2]=c[Aa>>2];if((Ea|0)==0){break m}else{Fa=Ea}}else{Fa=va}va=Fa+ -1|0;c[o>>2]=va;za=c[f>>2]|0;c[f>>2]=za+1;if((a[za]|0)==0){break m}}vf(b,-1,db(c[(Sa()|0)>>2]|0)|0)}}while(0);n:do{if((z&2|0)!=0){Fa=c[o>>2]|0;o:do{if((Fa|0)==0){Ea=b+76|0;if((c[Ea>>2]|0)==0){Da=b+40|0;if((c[Da>>2]|0)==0){va=b+24|0;Aa=c[va>>2]|0;xa=c[g>>2]|0;c[o>>2]=0;Ba=b+4|0;sa=0;while(1){Ga=Za(c[Ba>>2]|0,Aa+sa|0,xa-sa|0)|0;if((Ga|0)<1){s=199;break}Ca=(c[o>>2]|0)+Ga|0;c[o>>2]=Ca;if(Ca>>>0>>0){sa=Ca}else{Ha=Ca;break}}do{if((s|0)==199){if((Ga|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);Ia=c[o>>2]|0;s=204;break o}else{c[Da>>2]=1;Ha=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[va>>2];if((Ha|0)!=0){Ja=Ha;s=203}else{Ka=Ea;s=206}}else{Ka=Ea;s=206}}else{s=205}}else{Ja=Fa;s=203}}while(0);if((s|0)==203){Fa=Ja+ -1|0;c[o>>2]=Fa;c[f>>2]=(c[f>>2]|0)+1;Ia=Fa;s=204}if((s|0)==204){if((Ia|0)==0){s=205}else{La=Ia}}if((s|0)==205){Ka=b+76|0;s=206}if((s|0)==206){if((c[Ka>>2]|0)!=0){break}Fa=b+40|0;if((c[Fa>>2]|0)!=0){break}Da=b+24|0;sa=c[Da>>2]|0;xa=c[g>>2]|0;c[o>>2]=0;Aa=b+4|0;Ba=0;while(1){Ma=Za(c[Aa>>2]|0,sa+Ba|0,xa-Ba|0)|0;if((Ma|0)<1){s=211;break}Ca=(c[o>>2]|0)+Ma|0;c[o>>2]=Ca;if(Ca>>>0>>0){Ba=Ca}else{Na=Ca;break}}do{if((s|0)==211){if((Ma|0)<0){vf(b,-1,db(c[(Sa()|0)>>2]|0)|0);break n}else{c[Fa>>2]=1;Na=c[o>>2]|0;break}}}while(0);c[b+84>>2]=c[Da>>2];if((Na|0)==0){break}else{La=Na}}c[o>>2]=La+ -1;c[f>>2]=(c[f>>2]|0)+1}}while(0);Hf(f)|0;c[b+132>>2]=gf(0,0,0)|0;c[b+52>>2]=2;c[b+56>>2]=0;p=0;i=e;return p|0}vf(b,-3,21400);p=-1;i=e;return p|0}vf(b,-3,21368);p=-1;i=e;return p|0}La=b+28|0;a[c[La>>2]|0]=31;c[b+36>>2]=1;Oa=La;Pa=c[o>>2]|0}else{Oa=b+28|0;Pa=v}c[b+48>>2]=c[b+12>>2];v=c[Oa>>2]|0;c[b+32>>2]=v;if((Pa|0)!=0){Oa=b+36|0;Kg(v+(c[Oa>>2]|0)|0,c[f>>2]|0,Pa|0)|0;c[Oa>>2]=(c[Oa>>2]|0)+(c[o>>2]|0);c[o>>2]=0}c[b+52>>2]=1;c[b+56>>2]=1;p=0;i=e;return p|0}function Af(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}if((c[a>>2]|0)!=7247){d=-2;i=b;return d|0}if((c[a+16>>2]|0)!=0){Mf(a+84|0)|0;hg(c[a+28>>2]|0);hg(c[a+24>>2]|0)}vf(a,0,0);hg(c[a+8>>2]|0);e=ib(c[a+4>>2]|0)|0;hg(a);d=((e|0)!=0)<<31>>31;i=b;return d|0}function Bf(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0;e=i;f=a+84|0;g=a+88|0;h=c[g>>2]|0;a:do{if((h|0)==0){j=a+76|0;if((c[j>>2]|0)==0){k=a+40|0;if((c[k>>2]|0)==0){l=a+24|0;m=c[l>>2]|0;n=c[a+16>>2]|0;c[g>>2]=0;o=a+4|0;p=0;while(1){q=Za(c[o>>2]|0,m+p|0,n-p|0)|0;if((q|0)<1){r=7;break}s=(c[g>>2]|0)+q|0;c[g>>2]=s;if(s>>>0>>0){p=s}else{t=s;break}}do{if((r|0)==7){if((q|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);u=-1;v=c[g>>2]|0;r=12;break a}else{c[k>>2]=1;t=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[l>>2];if((t|0)!=0){w=t;r=11}else{x=j;y=-1;r=14}}else{x=j;y=-1;r=14}}else{z=-1;r=13}}else{w=h;r=11}}while(0);if((r|0)==11){h=w+ -1|0;c[g>>2]=h;w=c[f>>2]|0;c[f>>2]=w+1;u=d[w]|0;v=h;r=12}if((r|0)==12){if((v|0)==0){z=u;r=13}else{A=u;B=v;r=25}}if((r|0)==13){x=a+76|0;y=z;r=14}b:do{if((r|0)==14){if((c[x>>2]|0)!=0){C=y+ -256|0;r=27;break}z=a+40|0;if((c[z>>2]|0)==0){v=a+24|0;u=c[v>>2]|0;h=c[a+16>>2]|0;c[g>>2]=0;w=a+4|0;t=0;while(1){D=Za(c[w>>2]|0,u+t|0,h-t|0)|0;if((D|0)<1){r=20;break}q=(c[g>>2]|0)+D|0;c[g>>2]=q;if(q>>>0>>0){t=q}else{E=q;break}}do{if((r|0)==20){if((D|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);F=y;G=-256;H=c[g>>2]|0;r=26;break b}else{c[z>>2]=1;E=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[v>>2];if((E|0)!=0){A=y;B=E;r=25;break}}I=x;J=y+ -256|0;r=28}}while(0);if((r|0)==25){y=B+ -1|0;c[g>>2]=y;B=c[f>>2]|0;c[f>>2]=B+1;F=A;G=(d[B]|0)<<8;H=y;r=26}if((r|0)==26){y=G+F|0;if((H|0)==0){C=y;r=27}else{K=H;L=y;r=39}}if((r|0)==27){I=a+76|0;J=C;r=28}c:do{if((r|0)==28){if((c[I>>2]|0)!=0){M=J+ -65536|0;r=41;break}C=a+40|0;if((c[C>>2]|0)==0){y=a+24|0;H=c[y>>2]|0;F=c[a+16>>2]|0;c[g>>2]=0;G=a+4|0;B=0;while(1){N=Za(c[G>>2]|0,H+B|0,F-B|0)|0;if((N|0)<1){r=34;break}A=(c[g>>2]|0)+N|0;c[g>>2]=A;if(A>>>0>>0){B=A}else{O=A;break}}do{if((r|0)==34){if((N|0)<0){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);P=J;Q=-65536;R=c[g>>2]|0;r=40;break c}else{c[C>>2]=1;O=c[g>>2]|0;break}}}while(0);c[a+84>>2]=c[y>>2];if((O|0)!=0){K=O;L=J;r=39;break}}S=I;T=J+ -65536|0;r=42}}while(0);if((r|0)==39){J=K+ -1|0;c[g>>2]=J;K=c[f>>2]|0;c[f>>2]=K+1;P=L;Q=(d[K]|0)<<16;R=J;r=40}if((r|0)==40){J=Q+P|0;if((R|0)==0){M=J;r=41}else{U=R;V=J}}if((r|0)==41){S=a+76|0;T=M;r=42}if((r|0)==42){if((c[S>>2]|0)!=0){W=-1;i=e;return W|0}S=a+40|0;if((c[S>>2]|0)!=0){W=-1;i=e;return W|0}M=a+24|0;J=c[M>>2]|0;R=c[a+16>>2]|0;c[g>>2]=0;P=a+4|0;Q=0;while(1){X=Za(c[P>>2]|0,J+Q|0,R-Q|0)|0;if((X|0)<1){r=47;break}K=(c[g>>2]|0)+X|0;c[g>>2]=K;if(K>>>0>>0){Q=K}else{Y=K;break}}do{if((r|0)==47){if((X|0)>=0){c[S>>2]=1;Y=c[g>>2]|0;break}vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);W=-1;i=e;return W|0}}while(0);c[a+84>>2]=c[M>>2];if((Y|0)==0){W=-1;i=e;return W|0}else{U=Y;V=T}}c[g>>2]=U+ -1;U=c[f>>2]|0;c[f>>2]=U+1;c[b>>2]=((d[U]|0)<<24)+V;W=0;i=e;return W|0}function Cf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=i;if((a|0)==0){f=0;i=e;return f|0}g=a+84|0;if((c[a>>2]|0)!=31153){f=0;i=e;return f|0}if((c[a+76>>2]|0)!=0){f=0;i=e;return f|0}if((d|0)<0){vf(a,-5,21568);f=0;i=e;return f|0}if((d|0)==0){f=0;i=e;return f|0}h=a+16|0;if((c[h>>2]|0)==0?(Df(a)|0)==-1:0){f=0;i=e;return f|0}j=a+72|0;a:do{if((c[j>>2]|0)!=0){c[j>>2]=0;k=c[a+68>>2]|0;l=a+88|0;if((c[l>>2]|0)!=0?(Ef(a,0)|0)==-1:0){f=0;i=e;return f|0}if((k|0)!=0){m=a+24|0;n=a+12|0;o=k;k=0;while(1){p=c[h>>2]|0;q=(p|0)<0|(p|0)>(o|0)?o:p;if(!k){Eg(c[m>>2]|0,0,q|0)|0}c[l>>2]=q;c[g>>2]=c[m>>2];c[n>>2]=(c[n>>2]|0)+q;if((Ef(a,0)|0)==-1){f=0;break}if((o|0)==(q|0)){break a}o=o-q|0;k=1}i=e;return f|0}}}while(0);j=a+88|0;b:do{if(!((c[h>>2]|0)>>>0>d>>>0)){if((c[j>>2]|0)!=0?(Ef(a,0)|0)==-1:0){f=0;i=e;return f|0}c[j>>2]=d;c[g>>2]=b;k=a+12|0;c[k>>2]=(c[k>>2]|0)+d;if((Ef(a,0)|0)==-1){f=0;i=e;return f|0}}else{k=a+24|0;o=a+12|0;n=b;m=d;while(1){l=c[j>>2]|0;if((l|0)==0){q=c[k>>2]|0;c[g>>2]=q;r=q}else{r=c[g>>2]|0}q=(c[h>>2]|0)-l|0;p=q>>>0>m>>>0?m:q;Kg(r+l|0,n|0,p|0)|0;c[j>>2]=(c[j>>2]|0)+p;c[o>>2]=(c[o>>2]|0)+p;if((m|0)==(p|0)){break b}if((Ef(a,0)|0)==-1){f=0;break}n=n+p|0;m=m-p|0}i=e;return f|0}}while(0);f=d;i=e;return f|0}function Df(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;b=i;d=a+20|0;e=c[d>>2]|0;f=gg(e)|0;g=a+24|0;c[g>>2]=f;h=gg(e)|0;e=a+28|0;c[e>>2]=h;j=(h|0)==0;if(!((f|0)==0|j)){c[a+116>>2]=0;c[a+120>>2]=0;c[a+124>>2]=0;if((hf(a+84|0,c[a+60>>2]|0,8,31,8,c[a+64>>2]|0,21664,56)|0)==0){k=c[d>>2]|0;c[a+16>>2]=k;c[a+100>>2]=k;k=c[e>>2]|0;c[a+96>>2]=k;c[a+32>>2]=k;l=0;i=b;return l|0}else{hg(c[g>>2]|0);vf(a,-4,21648);l=-1;i=b;return l|0}}if(j){m=f}else{hg(h);m=c[g>>2]|0}if((m|0)!=0){hg(m)}vf(a,-4,21648);l=-1;i=b;return l|0}function Ef(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;d=i;e=a+84|0;f=a+16|0;if((c[f>>2]|0)==0?(Df(a)|0)==-1:0){g=-1;i=d;return g|0}h=a+100|0;j=a+96|0;k=a+32|0;l=a+28|0;m=a+4|0;a:do{if((b|0)==4){n=c[h>>2]|0;o=0;while(1){if((n|0)==0|(o|0)==1){p=c[j>>2]|0;q=c[k>>2]|0;r=p-q|0;if((p|0)==(q|0)){s=n}else{p=Qa(c[m>>2]|0,q|0,r|0)|0;if(!((p|0)>-1&(p|0)==(r|0))){t=30;break a}s=c[h>>2]|0}if((s|0)==0){r=c[f>>2]|0;c[h>>2]=r;p=c[l>>2]|0;c[j>>2]=p;u=p;v=r}else{u=c[j>>2]|0;v=s}c[k>>2]=u;w=v}else{w=n}r=lf(e,4)|0;if((r|0)==-2){t=36;break a}p=c[h>>2]|0;if((w|0)==(p|0)){t=38;break}else{n=p;o=r}}}else if((b|0)==0){o=c[h>>2]|0;while(1){if((o|0)==0){n=c[j>>2]|0;r=c[k>>2]|0;p=n-r|0;if((n|0)!=(r|0)){n=Qa(c[m>>2]|0,r|0,p|0)|0;if(!((n|0)>-1&(n|0)==(p|0))){t=30;break a}p=c[h>>2]|0;if((p|0)!=0){x=c[j>>2]|0;y=p}else{t=10}}else{t=10}if((t|0)==10){t=0;p=c[f>>2]|0;c[h>>2]=p;n=c[l>>2]|0;c[j>>2]=n;x=n;y=p}c[k>>2]=x;z=y}else{z=o}if((lf(e,0)|0)==-2){t=36;break a}p=c[h>>2]|0;if((z|0)==(p|0)){t=38;break}else{o=p}}}else{o=c[h>>2]|0;while(1){if((o|0)!=0&(b|0)==0){A=o}else{p=c[j>>2]|0;n=c[k>>2]|0;r=p-n|0;if((p|0)==(n|0)){B=o}else{p=Qa(c[m>>2]|0,n|0,r|0)|0;if(!((p|0)>-1&(p|0)==(r|0))){t=30;break a}B=c[h>>2]|0}if((B|0)==0){r=c[f>>2]|0;c[h>>2]=r;p=c[l>>2]|0;c[j>>2]=p;C=p;D=r}else{C=c[j>>2]|0;D=B}c[k>>2]=C;A=D}if((lf(e,b)|0)==-2){t=36;break a}r=c[h>>2]|0;if((A|0)==(r|0)){t=38;break}else{o=r}}}}while(0);if((t|0)==30){vf(a,-1,db(c[(Sa()|0)>>2]|0)|0);g=-1;i=d;return g|0}else if((t|0)==36){vf(a,-2,21608);g=-1;i=d;return g|0}else if((t|0)==38){if((b|0)!=4){g=0;i=d;return g|0}kf(e)|0;g=0;i=d;return g|0}return 0}function Ff(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}if((c[a>>2]|0)!=31153){d=-2;i=b;return d|0}e=a+72|0;a:do{if((c[e>>2]|0)!=0){c[e>>2]=0;f=c[a+68>>2]|0;g=a+88|0;if((c[g>>2]|0)!=0?(Ef(a,0)|0)==-1:0){h=-1;break}if((f|0)!=0){j=a+16|0;k=a+24|0;l=a+84|0;m=a+12|0;n=f;f=0;while(1){o=c[j>>2]|0;p=(o|0)<0|(o|0)>(n|0)?n:o;if(!f){Eg(c[k>>2]|0,0,p|0)|0}c[g>>2]=p;c[l>>2]=c[k>>2];c[m>>2]=(c[m>>2]|0)+p;if((Ef(a,0)|0)==-1){h=-1;break a}if((n|0)==(p|0)){h=0;break}else{n=n-p|0;f=1}}}else{h=0}}else{h=0}}while(0);e=(Ef(a,4)|0)+h|0;jf(a+84|0)|0;hg(c[a+28>>2]|0);hg(c[a+24>>2]|0);vf(a,0,0);hg(c[a+8>>2]|0);h=ib(c[a+4>>2]|0)|0;hg(a);d=((e|0)!=(0-h|0))<<31>>31;i=b;return d|0}function Gf(e,f){e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0;g=i;h=c[e+28>>2]|0;j=c[e>>2]|0;k=e+4|0;l=j+((c[k>>2]|0)+ -6)|0;m=e+12|0;n=c[m>>2]|0;o=e+16|0;p=c[o>>2]|0;q=n+(p+ -258)|0;r=c[h+44>>2]|0;s=c[h+48>>2]|0;t=c[h+52>>2]|0;u=h+56|0;v=h+60|0;w=c[h+76>>2]|0;x=c[h+80>>2]|0;y=(1<>2])+ -1|0;z=(1<>2])+ -1|0;A=n+(p+~f)|0;f=h+7104|0;p=t+ -1|0;B=(s|0)==0;C=(c[h+40>>2]|0)+ -1|0;D=C+s|0;E=s+ -1|0;F=A+ -1|0;G=A-s|0;H=c[v>>2]|0;I=c[u>>2]|0;J=j+ -1|0;j=n+ -1|0;a:while(1){if(H>>>0<15){n=J+2|0;K=H+16|0;L=((d[J+1|0]|0)<>1]|0;P=d[w+(n<<2)+1|0]|0;n=L>>>P;Q=K-P|0;do{if(!(N<<24>>24==0)){R=N&255;S=Q;T=n;P=O;while(1){if((R&16|0)!=0){break}if((R&64|0)!=0){U=55;break a}V=(T&(1<>1]|0;Y=d[w+(V<<2)+1|0]|0;Z=T>>>Y;_=S-Y|0;if(W<<24>>24==0){U=6;break}else{R=W&255;S=_;T=Z;P=X}}if((U|0)==6){U=0;$=Z;aa=_;ba=X&255;U=7;break}W=P&65535;Y=R&15;if((Y|0)==0){ca=S;da=T;ea=M;fa=W}else{if(S>>>0>>0){V=M+1|0;ga=S+8|0;ha=((d[V]|0)<>>Y;ea=ia;fa=(ha&(1<>>0<15){W=ea+2|0;ja=ca+16|0;ka=((d[ea+1|0]|0)<>1]|0;V=d[x+(W<<2)+1|0]|0;ma=ka>>>V;na=ja-V|0;V=d[x+(W<<2)|0]|0;if((V&16|0)==0){W=V;oa=ma;pa=na;qa=Y;while(1){if((W&64|0)!=0){U=52;break a}ra=(oa&(1<>1]|0;ta=d[x+(ra<<2)+1|0]|0;ua=oa>>>ta;va=pa-ta|0;ta=d[x+(ra<<2)|0]|0;if((ta&16|0)==0){W=ta;oa=ua;pa=va;qa=sa}else{wa=ua;xa=va;ya=ta;za=sa;break}}}else{wa=ma;xa=na;ya=V;za=Y}qa=za&65535;W=ya&15;if(xa>>>0>>0){P=la+1|0;sa=((d[P]|0)<>>0>>0){va=la+2|0;Aa=xa+16|0;Ba=((d[va]|0)<>>W;Ea=Aa-W|0;W=j;qa=W-A|0;if(!(P>>>0>qa>>>0)){sa=j+(0-P)|0;ta=fa;va=j;while(1){a[va+1|0]=a[sa+1|0]|0;a[va+2|0]=a[sa+2|0]|0;ua=sa+3|0;Fa=va+3|0;a[Fa]=a[ua]|0;ta=ta+ -3|0;if(!(ta>>>0>2)){break}else{sa=ua;va=Fa}}if((ta|0)==0){Ga=Ea;Ha=Da;Ia=Ca;Ja=Fa;break}Y=va+4|0;a[Y]=a[sa+4|0]|0;if(!(ta>>>0>1)){Ga=Ea;Ha=Da;Ia=Ca;Ja=Y;break}Y=va+5|0;a[Y]=a[sa+5|0]|0;Ga=Ea;Ha=Da;Ia=Ca;Ja=Y;break}Y=P-qa|0;if(Y>>>0>r>>>0?(c[f>>2]|0)!=0:0){U=22;break a}do{if(B){V=t+(C-Y)|0;if(Y>>>0>>0){na=fa-Y|0;ma=P-W|0;ua=V;ra=Y;Ka=j;do{ua=ua+1|0;Ka=Ka+1|0;a[Ka]=a[ua]|0;ra=ra+ -1|0}while((ra|0)!=0);La=j+(F+ma+(1-P))|0;Ma=na;Na=j+(A+ma)|0}else{La=V;Ma=fa;Na=j}}else{if(!(s>>>0>>0)){ra=t+(E-Y)|0;if(!(Y>>>0>>0)){La=ra;Ma=fa;Na=j;break}ua=fa-Y|0;Ka=P-W|0;Oa=ra;ra=Y;Pa=j;do{Oa=Oa+1|0;Pa=Pa+1|0;a[Pa]=a[Oa]|0;ra=ra+ -1|0}while((ra|0)!=0);La=j+(F+Ka+(1-P))|0;Ma=ua;Na=j+(A+Ka)|0;break}ra=t+(D-Y)|0;Oa=Y-s|0;if(Oa>>>0>>0){Pa=fa-Oa|0;V=P-W|0;ma=ra;na=Oa;Oa=j;do{ma=ma+1|0;Oa=Oa+1|0;a[Oa]=a[ma]|0;na=na+ -1|0}while((na|0)!=0);na=j+(G+V)|0;if(s>>>0>>0){ma=Pa-s|0;Oa=p;Ka=s;ua=na;do{Oa=Oa+1|0;ua=ua+1|0;a[ua]=a[Oa]|0;Ka=Ka+ -1|0}while((Ka|0)!=0);La=j+(F+V+(1-P))|0;Ma=ma;Na=j+(A+V)|0}else{La=p;Ma=Pa;Na=na}}else{La=ra;Ma=fa;Na=j}}}while(0);if(Ma>>>0>2){P=La;W=Ma;Y=Na;while(1){a[Y+1|0]=a[P+1|0]|0;a[Y+2|0]=a[P+2|0]|0;qa=P+3|0;sa=Y+3|0;a[sa]=a[qa]|0;va=W+ -3|0;if(va>>>0>2){P=qa;W=va;Y=sa}else{Qa=qa;Ra=va;Sa=sa;break}}}else{Qa=La;Ra=Ma;Sa=Na}if((Ra|0)!=0){Y=Sa+1|0;a[Y]=a[Qa+1|0]|0;if(Ra>>>0>1){W=Sa+2|0;a[W]=a[Qa+2|0]|0;Ga=Ea;Ha=Da;Ia=Ca;Ja=W}else{Ga=Ea;Ha=Da;Ia=Ca;Ja=Y}}else{Ga=Ea;Ha=Da;Ia=Ca;Ja=Sa}}else{$=n;aa=Q;ba=O&255;U=7}}while(0);if((U|0)==7){U=0;O=j+1|0;a[O]=ba;Ga=aa;Ha=$;Ia=M;Ja=O}if(Ia>>>0>>0&Ja>>>0>>0){H=Ga;I=Ha;J=Ia;j=Ja}else{Ta=Ga;Ua=Ha;Va=Ia;Wa=Ja;break}}do{if((U|0)==22){c[e+24>>2]=21672;c[h>>2]=29;Ta=Ea;Ua=Da;Va=Ca;Wa=j}else if((U|0)==52){c[e+24>>2]=21704;c[h>>2]=29;Ta=pa;Ua=oa;Va=la;Wa=j}else if((U|0)==55){if((R&32|0)==0){c[e+24>>2]=21728;c[h>>2]=29;Ta=S;Ua=T;Va=M;Wa=j;break}else{c[h>>2]=11;Ta=S;Ua=T;Va=M;Wa=j;break}}}while(0);j=Ta>>>3;M=Va+(0-j)|0;T=Ta-(j<<3)|0;Ta=(1<>2]=Va+(1-j);c[m>>2]=Wa+1;if(M>>>0>>0){Xa=l-M|0}else{Xa=l-M|0}c[k>>2]=Xa+5;if(Wa>>>0>>0){Ya=q-Wa|0;Za=Ya+257|0;c[o>>2]=Za;c[u>>2]=Ta;c[v>>2]=T;i=g;return}else{Ya=q-Wa|0;Za=Ya+257|0;c[o>>2]=Za;c[u>>2]=Ta;c[v>>2]=T;i=g;return}}function Hf(a){a=a|0;var b=0,d=0,e=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=c[a+28>>2]|0;if((e|0)==0){d=-2;i=b;return d|0}c[e+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[e>>2]=0;c[e+4>>2]=0;c[e+12>>2]=0;c[e+20>>2]=32768;c[e+32>>2]=0;c[e+40>>2]=0;c[e+44>>2]=0;c[e+48>>2]=0;c[e+56>>2]=0;c[e+60>>2]=0;a=e+1328|0;c[e+108>>2]=a;c[e+80>>2]=a;c[e+76>>2]=a;c[e+7104>>2]=1;c[e+7108>>2]=-1;d=0;i=b;return d|0}function If(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;if((a|0)==0){e=-2;i=d;return e|0}f=a+28|0;g=c[f>>2]|0;if((g|0)==0){e=-2;i=d;return e|0}if((b|0)<0){h=0-b|0;j=0}else{h=(b|0)<48?b&15:b;j=(b>>4)+1|0}if((h|0)!=0&(h+ -8|0)>>>0>7){e=-2;i=d;return e|0}b=g+52|0;k=c[b>>2]|0;l=g+36|0;if((k|0)!=0?(c[l>>2]|0)!=(h|0):0){mb[c[a+36>>2]&1](c[a+40>>2]|0,k);c[b>>2]=0}c[g+8>>2]=j;c[l>>2]=h;h=c[f>>2]|0;if((h|0)==0){e=-2;i=d;return e|0}c[h+28>>2]=0;c[a+20>>2]=0;c[a+8>>2]=0;c[a+24>>2]=0;c[a+48>>2]=1;c[h>>2]=0;c[h+4>>2]=0;c[h+12>>2]=0;c[h+20>>2]=32768;c[h+32>>2]=0;c[h+40>>2]=0;c[h+44>>2]=0;c[h+48>>2]=0;c[h+56>>2]=0;c[h+60>>2]=0;a=h+1328|0;c[h+108>>2]=a;c[h+80>>2]=a;c[h+76>>2]=a;c[h+7104>>2]=1;c[h+7108>>2]=-1;e=0;i=d;return e|0}function Jf(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0;g=i;if((e|0)==0){h=-6;i=g;return h|0}if(!((a[e]|0)==49&(f|0)==56)){h=-6;i=g;return h|0}if((b|0)==0){h=-2;i=g;return h|0}c[b+24>>2]=0;f=b+32|0;e=c[f>>2]|0;if((e|0)==0){c[f>>2]=1;c[b+40>>2]=0;j=1}else{j=e}e=b+36|0;if((c[e>>2]|0)==0){c[e>>2]=1}f=b+40|0;k=kb[j&1](c[f>>2]|0,1,7116)|0;if((k|0)==0){h=-4;i=g;return h|0}j=b+28|0;c[j>>2]=k;c[k+52>>2]=0;l=If(b,d)|0;if((l|0)==0){h=0;i=g;return h|0}mb[c[e>>2]&1](c[f>>2]|0,k);c[j>>2]=0;h=l;i=g;return h|0}function Kf(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,fb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0,sc=0,tc=0,uc=0,vc=0,wc=0,xc=0,yc=0,zc=0,Ac=0,Bc=0,Cc=0,Dc=0,Ec=0,Fc=0,Gc=0,Hc=0,Ic=0,Jc=0,Kc=0,Lc=0,Mc=0,Nc=0,Oc=0,Pc=0,Qc=0,Rc=0,Sc=0,Tc=0,Uc=0,Vc=0,Wc=0,Xc=0,Yc=0,Zc=0,_c=0,$c=0,ad=0,bd=0,cd=0,dd=0,ed=0,fd=0,gd=0,hd=0,id=0,jd=0,kd=0,ld=0,md=0,nd=0,od=0,pd=0,qd=0,rd=0,sd=0,td=0,ud=0,vd=0,wd=0,xd=0,yd=0,zd=0,Ad=0,Bd=0,Cd=0,Dd=0,Ed=0,Fd=0,Gd=0,Hd=0,Id=0,Jd=0,Kd=0,Ld=0,Md=0,Nd=0,Od=0,Pd=0,Qd=0,Rd=0,Sd=0,Td=0,Ud=0,Vd=0,Wd=0,Xd=0,Yd=0,Zd=0,_d=0,$d=0,ae=0,be=0,ce=0,de=0,ee=0,fe=0,ge=0,he=0,ie=0,je=0,ke=0,le=0,me=0,ne=0,oe=0,pe=0,qe=0,re=0,se=0,te=0,ue=0,ve=0,we=0,xe=0,ye=0,ze=0,Ae=0,Be=0,Ce=0,De=0,Ee=0,Fe=0,Ge=0,He=0,Ie=0,Je=0,Ke=0,Le=0,Me=0,Ne=0,Oe=0,Pe=0,Qe=0,Re=0,Se=0,Te=0,Ue=0,Ve=0,We=0,Xe=0,Ye=0,Ze=0,_e=0,$e=0,af=0,bf=0,cf=0,df=0,ef=0,hf=0,jf=0,kf=0,lf=0,mf=0,nf=0,of=0,pf=0,qf=0,rf=0,sf=0,tf=0,uf=0,vf=0,wf=0,xf=0,yf=0,zf=0,Af=0,Bf=0,Cf=0,Df=0,Ef=0,Ff=0,Hf=0,If=0,Jf=0,Kf=0,Mf=0,Of=0,Pf=0,Qf=0,Rf=0,Sf=0,Tf=0,Uf=0,Vf=0,Wf=0,Xf=0,Yf=0,Zf=0,_f=0,$f=0,ag=0,bg=0,cg=0,dg=0,eg=0,fg=0,gg=0,hg=0,ig=0,jg=0,kg=0,lg=0,mg=0,ng=0,og=0,pg=0,qg=0,rg=0,sg=0,tg=0,ug=0,vg=0,wg=0,xg=0,yg=0,zg=0,Ag=0,Bg=0,Cg=0,Dg=0,Eg=0,Fg=0,Gg=0,Hg=0,Ig=0,Jg=0;h=i;i=i+16|0;j=h;if((f|0)==0){k=-2;i=h;return k|0}l=c[f+28>>2]|0;if((l|0)==0){k=-2;i=h;return k|0}m=f+12|0;n=c[m>>2]|0;if((n|0)==0){k=-2;i=h;return k|0}o=c[f>>2]|0;if((o|0)==0?(c[f+4>>2]|0)!=0:0){k=-2;i=h;return k|0}p=c[l>>2]|0;if((p|0)==11){c[l>>2]=12;q=12;r=c[f>>2]|0;s=c[m>>2]|0}else{q=p;r=o;s=n}n=f+16|0;o=c[n>>2]|0;p=f+4|0;t=c[p>>2]|0;u=l+56|0;v=l+60|0;w=l+8|0;x=l+24|0;y=j+1|0;z=l+16|0;A=l+32|0;B=f+24|0;C=l+36|0;D=l+20|0;E=f+48|0;F=l+64|0;G=l+12|0;H=(g+ -5|0)>>>0<2;I=l+4|0;J=l+76|0;K=l+84|0;L=l+80|0;M=l+88|0;N=(g|0)==6;O=l+7108|0;P=l+72|0;Q=l+7112|0;R=l+68|0;S=l+44|0;T=l+7104|0;U=l+48|0;V=l+52|0;W=l+40|0;X=f+20|0;Y=l+28|0;Z=l+96|0;_=l+100|0;$=l+92|0;aa=l+104|0;ba=l+1328|0;ca=l+108|0;da=l+112|0;ea=l+752|0;fa=l+624|0;ga=j+2|0;ha=j+3|0;ia=q;q=c[v>>2]|0;ja=t;ka=c[u>>2]|0;la=o;ma=r;r=o;o=s;s=0;a:while(1){b:do{switch(ia|0){case 28:{na=q;oa=ja;pa=ka;qa=la;ra=ma;sa=1;ta=285;break a;break};case 16:{if(q>>>0<14){ua=q;va=ja;wa=ka;xa=ma;while(1){if((va|0)==0){ya=ua;za=0;Aa=wa;Ba=la;Ca=xa;Da=r;Ea=s;break a}Ga=va+ -1|0;Ha=xa+1|0;Ia=(d[xa]<>>0<14){ua=Ja;va=Ga;wa=Ia;xa=Ha}else{Ka=Ja;La=Ga;Ma=Ia;Na=Ha;break}}}else{Ka=q;La=ja;Ma=ka;Na=ma}xa=(Ma&31)+257|0;c[Z>>2]=xa;wa=(Ma>>>5&31)+1|0;c[_>>2]=wa;c[$>>2]=(Ma>>>10&15)+4;va=Ma>>>14;ua=Ka+ -14|0;if(xa>>>0>286|wa>>>0>30){c[B>>2]=21992;c[l>>2]=29;Oa=ua;Pa=La;Qa=va;Ra=la;Sa=Na;Ta=r;Ua=o;Va=s;break b}else{c[aa>>2]=0;c[l>>2]=17;Wa=0;Xa=ua;Ya=La;Za=va;_a=Na;ta=154;break b}break};case 21:{$a=c[P>>2]|0;ab=q;bb=ja;cb=ka;db=ma;eb=s;ta=221;break};case 23:{fb=c[P>>2]|0;gb=q;hb=ja;ib=ka;jb=ma;kb=s;ta=240;break};case 1:{if(q>>>0<16){va=q;ua=ja;wa=ka;xa=ma;while(1){if((ua|0)==0){ya=va;za=0;Aa=wa;Ba=la;Ca=xa;Da=r;Ea=s;break a}Ha=ua+ -1|0;Ia=xa+1|0;Ga=(d[xa]<>>0<16){va=Ja;ua=Ha;wa=Ga;xa=Ia}else{lb=Ja;mb=Ha;nb=Ga;ob=Ia;break}}}else{lb=q;mb=ja;nb=ka;ob=ma}c[z>>2]=nb;if((nb&255|0)!=8){c[B>>2]=21824;c[l>>2]=29;Oa=lb;Pa=mb;Qa=nb;Ra=la;Sa=ob;Ta=r;Ua=o;Va=s;break b}if((nb&57344|0)!=0){c[B>>2]=21880;c[l>>2]=29;Oa=lb;Pa=mb;Qa=nb;Ra=la;Sa=ob;Ta=r;Ua=o;Va=s;break b}xa=c[A>>2]|0;if((xa|0)==0){pb=nb}else{c[xa>>2]=nb>>>8&1;pb=c[z>>2]|0}if((pb&512|0)!=0){a[j]=nb;a[y]=nb>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0}c[l>>2]=2;qb=0;rb=mb;sb=0;tb=ob;ta=47;break};case 22:{ub=q;vb=ja;wb=ka;xb=ma;yb=s;ta=228;break};case 10:{zb=q;Ab=ja;Bb=ka;Cb=ma;ta=121;break};case 7:{Db=q;Eb=ja;Fb=ka;Gb=ma;ta=96;break};case 5:{Hb=q;Ib=ja;Jb=ka;Kb=ma;ta=73;break};case 8:{Lb=q;Mb=ja;Nb=ka;Ob=ma;ta=109;break};case 11:{Pb=q;Qb=ja;Rb=ka;Sb=ma;ta=124;break};case 12:{Tb=q;Ub=ja;Vb=ka;Wb=ma;ta=125;break};case 13:{xa=q&7;wa=ka>>>xa;ua=q-xa|0;if(ua>>>0<32){xa=ua;va=ja;Ia=wa;Ga=ma;while(1){if((va|0)==0){ya=xa;za=0;Aa=Ia;Ba=la;Ca=Ga;Da=r;Ea=s;break a}Ha=va+ -1|0;Ja=Ga+1|0;Xb=(d[Ga]<>>0<32){xa=Yb;va=Ha;Ia=Xb;Ga=Ja}else{Zb=Yb;_b=Ha;$b=Xb;ac=Ja;break}}}else{Zb=ua;_b=ja;$b=wa;ac=ma}Ga=$b&65535;if((Ga|0)==($b>>>16^65535|0)){c[F>>2]=Ga;c[l>>2]=14;if(N){na=0;oa=_b;pa=0;qa=la;ra=ac;sa=s;ta=285;break a}else{bc=0;cc=_b;dc=0;ec=ac;ta=143;break b}}else{c[B>>2]=21960;c[l>>2]=29;Oa=Zb;Pa=_b;Qa=$b;Ra=la;Sa=ac;Ta=r;Ua=o;Va=s;break b}break};case 14:{bc=q;cc=ja;dc=ka;ec=ma;ta=143;break};case 15:{fc=q;gc=ja;hc=ka;ic=ma;ta=144;break};case 17:{Ga=c[aa>>2]|0;if(Ga>>>0<(c[$>>2]|0)>>>0){Wa=Ga;Xa=q;Ya=ja;Za=ka;_a=ma;ta=154}else{jc=Ga;kc=q;lc=ja;mc=ka;nc=ma;ta=158}break};case 0:{Ga=c[w>>2]|0;if((Ga|0)==0){c[l>>2]=12;Oa=q;Pa=ja;Qa=ka;Ra=la;Sa=ma;Ta=r;Ua=o;Va=s;break b}if(q>>>0<16){Ia=q;va=ja;xa=ka;Ja=ma;while(1){if((va|0)==0){ya=Ia;za=0;Aa=xa;Ba=la;Ca=Ja;Da=r;Ea=s;break a}Xb=va+ -1|0;Ha=Ja+1|0;Yb=(d[Ja]<>>0<16){Ia=oc;va=Xb;xa=Yb;Ja=Ha}else{pc=oc;qc=Xb;rc=Yb;sc=Ha;break}}}else{pc=q;qc=ja;rc=ka;sc=ma}if((Ga&2|0)!=0&(rc|0)==35615){c[x>>2]=gf(0,0,0)|0;a[j]=31;a[y]=-117;c[x>>2]=gf(c[x>>2]|0,j,2)|0;c[l>>2]=1;Oa=0;Pa=qc;Qa=0;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}c[z>>2]=0;Ja=c[A>>2]|0;if((Ja|0)==0){tc=Ga}else{c[Ja+48>>2]=-1;tc=c[w>>2]|0}if((tc&1|0)!=0?((((rc<<8&65280)+(rc>>>8)|0)>>>0)%31|0|0)==0:0){if((rc&15|0)!=8){c[B>>2]=21824;c[l>>2]=29;Oa=pc;Pa=qc;Qa=rc;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}Ja=rc>>>4;xa=pc+ -4|0;va=(Ja&15)+8|0;Ia=c[C>>2]|0;if((Ia|0)!=0){if(va>>>0>Ia>>>0){c[B>>2]=21856;c[l>>2]=29;Oa=xa;Pa=qc;Qa=Ja;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}}else{c[C>>2]=va}c[D>>2]=1<>2]=va;c[E>>2]=va;c[l>>2]=rc>>>12&2^11;Oa=0;Pa=qc;Qa=0;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break b}c[B>>2]=21800;c[l>>2]=29;Oa=pc;Pa=qc;Qa=rc;Ra=la;Sa=sc;Ta=r;Ua=o;Va=s;break};case 24:{uc=q;vc=ja;wc=ka;xc=ma;yc=s;ta=246;break};case 9:{if(q>>>0<32){va=q;Ja=ja;xa=ka;Ia=ma;while(1){if((Ja|0)==0){ya=va;za=0;Aa=xa;Ba=la;Ca=Ia;Da=r;Ea=s;break a}wa=Ja+ -1|0;ua=Ia+1|0;Ha=(d[Ia]<>>0<32){va=Yb;Ja=wa;xa=Ha;Ia=ua}else{zc=wa;Ac=Ha;Bc=ua;break}}}else{zc=ja;Ac=ka;Bc=ma}Ia=Fa(Ac|0)|0;c[x>>2]=Ia;c[E>>2]=Ia;c[l>>2]=10;zb=0;Ab=zc;Bb=0;Cb=Bc;ta=121;break};case 30:{ta=299;break a;break};case 18:{Cc=c[aa>>2]|0;Dc=q;Ec=ja;Fc=ka;Gc=ma;Hc=s;ta=164;break};case 6:{Ic=q;Jc=ja;Kc=ka;Lc=ma;ta=83;break};case 29:{ya=q;za=ja;Aa=ka;Ba=la;Ca=ma;Da=r;Ea=-3;break a;break};case 19:{Mc=q;Nc=ja;Oc=ka;Pc=ma;Qc=s;ta=201;break};case 20:{Rc=q;Sc=ja;Tc=ka;Uc=ma;Vc=s;ta=202;break};case 25:{if((la|0)==0){na=q;oa=ja;pa=ka;qa=0;ra=ma;sa=s;ta=285;break a}a[o]=c[F>>2];c[l>>2]=20;Oa=q;Pa=ja;Qa=ka;Ra=la+ -1|0;Sa=ma;Ta=r;Ua=o+1|0;Va=s;break};case 26:{if((c[w>>2]|0)!=0){if(q>>>0<32){Ia=q;xa=ja;Ja=ka;va=ma;while(1){if((xa|0)==0){ya=Ia;za=0;Aa=Ja;Ba=la;Ca=va;Da=r;Ea=s;break a}Ga=xa+ -1|0;ua=va+1|0;Ha=(d[va]<>>0<32){Ia=wa;xa=Ga;Ja=Ha;va=ua}else{Wc=wa;Xc=Ga;Yc=Ha;Zc=ua;break}}}else{Wc=q;Xc=ja;Yc=ka;Zc=ma}va=r-la|0;c[X>>2]=(c[X>>2]|0)+va;c[Y>>2]=(c[Y>>2]|0)+va;if((r|0)!=(la|0)){Ja=c[x>>2]|0;xa=o+(0-va)|0;if((c[z>>2]|0)==0){_c=ff(Ja,xa,va)|0}else{_c=gf(Ja,xa,va)|0}c[x>>2]=_c;c[E>>2]=_c}if((c[z>>2]|0)==0){$c=Fa(Yc|0)|0}else{$c=Yc}if(($c|0)==(c[x>>2]|0)){ad=0;bd=Xc;cd=0;dd=Zc;ed=la}else{c[B>>2]=22280;c[l>>2]=29;Oa=Wc;Pa=Xc;Qa=Yc;Ra=la;Sa=Zc;Ta=la;Ua=o;Va=s;break b}}else{ad=q;bd=ja;cd=ka;dd=ma;ed=r}c[l>>2]=27;fd=ad;gd=bd;hd=cd;id=dd;jd=ed;ta=277;break};case 27:{fd=q;gd=ja;hd=ka;id=ma;jd=r;ta=277;break};case 2:{if(q>>>0<32){qb=q;rb=ja;sb=ka;tb=ma;ta=47}else{kd=ja;ld=ka;md=ma;ta=49}break};case 4:{nd=q;od=ja;pd=ka;qd=ma;ta=62;break};case 3:{if(q>>>0<16){rd=q;sd=ja;td=ka;ud=ma;ta=55}else{vd=ja;wd=ka;xd=ma;ta=57}break};default:{k=-2;ta=300;break a}}}while(0);if((ta|0)==47){while(1){ta=0;if((rb|0)==0){ya=qb;za=0;Aa=sb;Ba=la;Ca=tb;Da=r;Ea=s;break a}va=rb+ -1|0;xa=tb+1|0;Ja=(d[tb]<>>0<32){qb=Ia;rb=va;sb=Ja;tb=xa;ta=47}else{kd=va;ld=Ja;md=xa;ta=49;break}}}else if((ta|0)==121){ta=0;if((c[G>>2]|0)==0){ta=122;break}xa=ff(0,0,0)|0;c[x>>2]=xa;c[E>>2]=xa;c[l>>2]=11;Pb=zb;Qb=Ab;Rb=Bb;Sb=Cb;ta=124}else if((ta|0)==143){ta=0;c[l>>2]=15;fc=bc;gc=cc;hc=dc;ic=ec;ta=144}else if((ta|0)==154){while(1){ta=0;if(Xa>>>0<3){xa=Xa;Ja=Ya;va=Za;Ia=_a;while(1){if((Ja|0)==0){ya=xa;za=0;Aa=va;Ba=la;Ca=Ia;Da=r;Ea=s;break a}ua=Ja+ -1|0;Ha=Ia+1|0;Ga=(d[Ia]<>>0<3){xa=wa;Ja=ua;va=Ga;Ia=Ha}else{yd=wa;zd=ua;Ad=Ga;Bd=Ha;break}}}else{yd=Xa;zd=Ya;Ad=Za;Bd=_a}c[aa>>2]=Wa+1;b[l+(e[21760+(Wa<<1)>>1]<<1)+112>>1]=Ad&7;Ia=Ad>>>3;va=yd+ -3|0;Ja=c[aa>>2]|0;if(Ja>>>0<(c[$>>2]|0)>>>0){Wa=Ja;Xa=va;Ya=zd;Za=Ia;_a=Bd;ta=154}else{jc=Ja;kc=va;lc=zd;mc=Ia;nc=Bd;ta=158;break}}}else if((ta|0)==277){ta=0;if((c[w>>2]|0)==0){Cd=fd;Dd=gd;Ed=hd;Fd=id;ta=284;break}if((c[z>>2]|0)==0){Cd=fd;Dd=gd;Ed=hd;Fd=id;ta=284;break}if(fd>>>0<32){Ia=fd;va=gd;Ja=hd;xa=id;while(1){if((va|0)==0){ya=Ia;za=0;Aa=Ja;Ba=la;Ca=xa;Da=jd;Ea=s;break a}Ha=va+ -1|0;Ga=xa+1|0;ua=(d[xa]<>>0<32){Ia=wa;va=Ha;Ja=ua;xa=Ga}else{Gd=wa;Hd=Ha;Id=ua;Jd=Ga;break}}}else{Gd=fd;Hd=gd;Id=hd;Jd=id}if((Id|0)==(c[Y>>2]|0)){Cd=0;Dd=Hd;Ed=0;Fd=Jd;ta=284;break}c[B>>2]=22304;c[l>>2]=29;Oa=Gd;Pa=Hd;Qa=Id;Ra=la;Sa=Jd;Ta=jd;Ua=o;Va=s}do{if((ta|0)==49){ta=0;xa=c[A>>2]|0;if((xa|0)!=0){c[xa+4>>2]=ld}if((c[z>>2]&512|0)!=0){a[j]=ld;a[y]=ld>>>8;a[ga]=ld>>>16;a[ha]=ld>>>24;c[x>>2]=gf(c[x>>2]|0,j,4)|0}c[l>>2]=3;rd=0;sd=kd;td=0;ud=md;ta=55}else if((ta|0)==124){ta=0;if(H){na=Pb;oa=Qb;pa=Rb;qa=la;ra=Sb;sa=s;ta=285;break a}else{Tb=Pb;Ub=Qb;Vb=Rb;Wb=Sb;ta=125}}else if((ta|0)==144){ta=0;xa=c[F>>2]|0;if((xa|0)==0){c[l>>2]=11;Oa=fc;Pa=gc;Qa=hc;Ra=la;Sa=ic;Ta=r;Ua=o;Va=s;break}Ja=xa>>>0>gc>>>0?gc:xa;xa=Ja>>>0>la>>>0?la:Ja;if((xa|0)==0){na=fc;oa=gc;pa=hc;qa=la;ra=ic;sa=s;ta=285;break a}Kg(o|0,ic|0,xa|0)|0;c[F>>2]=(c[F>>2]|0)-xa;Oa=fc;Pa=gc-xa|0;Qa=hc;Ra=la-xa|0;Sa=ic+xa|0;Ta=r;Ua=o+xa|0;Va=s}else if((ta|0)==158){ta=0;if(jc>>>0<19){xa=jc;while(1){Ja=xa+1|0;b[l+(e[21760+(xa<<1)>>1]<<1)+112>>1]=0;if((Ja|0)==19){break}else{xa=Ja}}c[aa>>2]=19}c[ca>>2]=ba;c[J>>2]=ba;c[K>>2]=7;xa=Nf(0,da,19,ca,K,ea)|0;if((xa|0)==0){c[aa>>2]=0;c[l>>2]=18;Cc=0;Dc=kc;Ec=lc;Fc=mc;Gc=nc;Hc=0;ta=164;break}else{c[B>>2]=22032;c[l>>2]=29;Oa=kc;Pa=lc;Qa=mc;Ra=la;Sa=nc;Ta=r;Ua=o;Va=xa;break}}}while(0);c:do{if((ta|0)==55){while(1){ta=0;if((sd|0)==0){ya=rd;za=0;Aa=td;Ba=la;Ca=ud;Da=r;Ea=s;break a}xa=sd+ -1|0;Ja=ud+1|0;va=(d[ud]<>>0<16){rd=Ia;sd=xa;td=va;ud=Ja;ta=55}else{vd=xa;wd=va;xd=Ja;ta=57;break}}}else if((ta|0)==125){ta=0;if((c[I>>2]|0)!=0){Ja=Tb&7;c[l>>2]=26;Oa=Tb-Ja|0;Pa=Ub;Qa=Vb>>>Ja;Ra=la;Sa=Wb;Ta=r;Ua=o;Va=s;break}if(Tb>>>0<3){Ja=Tb;va=Ub;xa=Vb;Ia=Wb;while(1){if((va|0)==0){ya=Ja;za=0;Aa=xa;Ba=la;Ca=Ia;Da=r;Ea=s;break a}Ga=va+ -1|0;ua=Ia+1|0;Ha=(d[Ia]<>>0<3){Ja=wa;va=Ga;xa=Ha;Ia=ua}else{Kd=wa;Ld=Ga;Md=Ha;Nd=ua;break}}}else{Kd=Tb;Ld=Ub;Md=Vb;Nd=Wb}c[I>>2]=Md&1;Ia=Md>>>1&3;if((Ia|0)==0){c[l>>2]=13}else if((Ia|0)==1){c[J>>2]=22328;c[K>>2]=9;c[L>>2]=24376;c[M>>2]=5;c[l>>2]=19;if(N){ta=133;break a}}else if((Ia|0)==2){c[l>>2]=16}else if((Ia|0)==3){c[B>>2]=21936;c[l>>2]=29}Oa=Kd+ -3|0;Pa=Ld;Qa=Md>>>3;Ra=la;Sa=Nd;Ta=r;Ua=o;Va=s}else if((ta|0)==164){ta=0;Ia=c[Z>>2]|0;xa=c[_>>2]|0;do{if(Cc>>>0<(xa+Ia|0)>>>0){va=Cc;Ja=xa;ua=Ia;Ha=Dc;Ga=Ec;wa=Fc;Yb=Gc;d:while(1){Xb=(1<>2])+ -1|0;oc=Xb&wa;Od=c[J>>2]|0;Pd=d[Od+(oc<<2)+1|0]|0;if(Pd>>>0>Ha>>>0){Qd=Ha;Rd=Ga;Sd=wa;Td=Yb;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Td;Da=r;Ea=Hc;break a}Ud=Rd+ -1|0;Vd=Td+1|0;Wd=(d[Td]<>>0>Xd>>>0){Qd=Xd;Rd=Ud;Sd=Wd;Td=Vd}else{_d=Zd;$d=Yd;ae=Xd;be=Ud;ce=Wd;de=Vd;break}}}else{_d=Pd;$d=oc;ae=Ha;be=Ga;ce=wa;de=Yb}Td=b[Od+($d<<2)+2>>1]|0;e:do{if((Td&65535)<16){if(ae>>>0<_d>>>0){Sd=ae;Rd=be;Qd=ce;Xb=de;while(1){if((Rd|0)==0){ya=Sd;za=0;Aa=Qd;Ba=la;Ca=Xb;Da=r;Ea=Hc;break a}Vd=Rd+ -1|0;Wd=Xb+1|0;Ud=(d[Xb]<>>0<_d>>>0){Sd=Xd;Rd=Vd;Qd=Ud;Xb=Wd}else{ee=Xd;fe=Vd;ge=Ud;he=Wd;break}}}else{ee=ae;fe=be;ge=ce;he=de}c[aa>>2]=va+1;b[l+(va<<1)+112>>1]=Td;ie=ee-_d|0;je=fe;ke=ge>>>_d;le=he}else{if(Td<<16>>16==16){Xb=_d+2|0;if(ae>>>0>>0){Qd=ae;Rd=be;Sd=ce;Wd=de;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Wd;Da=r;Ea=Hc;break a}Ud=Rd+ -1|0;Vd=Wd+1|0;Xd=(d[Wd]<>>0>>0){Qd=Yd;Rd=Ud;Sd=Xd;Wd=Vd}else{me=Yd;ne=Ud;oe=Xd;pe=Vd;break}}}else{me=ae;ne=be;oe=ce;pe=de}qe=oe>>>_d;re=me-_d|0;if((va|0)==0){ta=181;break d}se=re+ -2|0;te=(qe&3)+3|0;ue=ne;ve=qe>>>2;we=b[l+(va+ -1<<1)+112>>1]|0;xe=pe}else if(Td<<16>>16==17){Wd=_d+3|0;if(ae>>>0>>0){Sd=ae;Rd=be;Qd=ce;Xb=de;while(1){if((Rd|0)==0){ya=Sd;za=0;Aa=Qd;Ba=la;Ca=Xb;Da=r;Ea=Hc;break a}Vd=Rd+ -1|0;Xd=Xb+1|0;Ud=(d[Xb]<>>0>>0){Sd=Yd;Rd=Vd;Qd=Ud;Xb=Xd}else{ye=Yd;ze=Vd;Ae=Ud;Be=Xd;break}}}else{ye=ae;ze=be;Ae=ce;Be=de}Xb=Ae>>>_d;se=-3-_d+ye|0;te=(Xb&7)+3|0;ue=ze;ve=Xb>>>3;we=0;xe=Be}else{Xb=_d+7|0;if(ae>>>0>>0){Qd=ae;Rd=be;Sd=ce;Wd=de;while(1){if((Rd|0)==0){ya=Qd;za=0;Aa=Sd;Ba=la;Ca=Wd;Da=r;Ea=Hc;break a}Xd=Rd+ -1|0;Ud=Wd+1|0;Vd=(d[Wd]<>>0>>0){Qd=Yd;Rd=Xd;Sd=Vd;Wd=Ud}else{Ce=Yd;De=Xd;Ee=Vd;Fe=Ud;break}}}else{Ce=ae;De=be;Ee=ce;Fe=de}Wd=Ee>>>_d;se=-7-_d+Ce|0;te=(Wd&127)+11|0;ue=De;ve=Wd>>>7;we=0;xe=Fe}if((va+te|0)>>>0>(Ja+ua|0)>>>0){ta=190;break d}else{Ge=va;He=te}while(1){Wd=He+ -1|0;c[aa>>2]=Ge+1;b[l+(Ge<<1)+112>>1]=we;if((Wd|0)==0){ie=se;je=ue;ke=ve;le=xe;break e}Ge=c[aa>>2]|0;He=Wd}}}while(0);Td=c[aa>>2]|0;Ie=c[Z>>2]|0;Od=c[_>>2]|0;if(Td>>>0<(Od+Ie|0)>>>0){va=Td;Ja=Od;ua=Ie;Ha=ie;Ga=je;wa=ke;Yb=le}else{ta=193;break}}if((ta|0)==181){ta=0;c[B>>2]=22064;c[l>>2]=29;Oa=re;Pa=ne;Qa=qe;Ra=la;Sa=pe;Ta=r;Ua=o;Va=Hc;break c}else if((ta|0)==190){ta=0;c[B>>2]=22064;c[l>>2]=29;Oa=se;Pa=ue;Qa=ve;Ra=la;Sa=xe;Ta=r;Ua=o;Va=Hc;break c}else if((ta|0)==193){ta=0;if((c[l>>2]|0)==29){Oa=ie;Pa=je;Qa=ke;Ra=la;Sa=le;Ta=r;Ua=o;Va=Hc;break c}else{Je=Ie;Ke=ie;Le=je;Me=ke;Ne=le;break}}}else{Je=Ia;Ke=Dc;Le=Ec;Me=Fc;Ne=Gc}}while(0);if((b[fa>>1]|0)==0){c[B>>2]=22096;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Hc;break}c[ca>>2]=ba;c[J>>2]=ba;c[K>>2]=9;Ia=Nf(1,da,Je,ca,K,ea)|0;if((Ia|0)!=0){c[B>>2]=22136;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Ia;break}c[L>>2]=c[ca>>2];c[M>>2]=6;Ia=Nf(2,l+(c[Z>>2]<<1)+112|0,c[_>>2]|0,ca,M,ea)|0;if((Ia|0)==0){c[l>>2]=19;if(N){na=Ke;oa=Le;pa=Me;qa=la;ra=Ne;sa=0;ta=285;break a}else{Mc=Ke;Nc=Le;Oc=Me;Pc=Ne;Qc=0;ta=201;break}}else{c[B>>2]=22168;c[l>>2]=29;Oa=Ke;Pa=Le;Qa=Me;Ra=la;Sa=Ne;Ta=r;Ua=o;Va=Ia;break}}}while(0);if((ta|0)==57){ta=0;Ia=c[A>>2]|0;if((Ia|0)!=0){c[Ia+8>>2]=wd&255;c[Ia+12>>2]=wd>>>8}if((c[z>>2]&512|0)!=0){a[j]=wd;a[y]=wd>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0}c[l>>2]=4;nd=0;od=vd;pd=0;qd=xd;ta=62}else if((ta|0)==201){ta=0;c[l>>2]=20;Rc=Mc;Sc=Nc;Tc=Oc;Uc=Pc;Vc=Qc;ta=202}do{if((ta|0)==62){ta=0;Ia=c[z>>2]|0;if((Ia&1024|0)==0){xa=c[A>>2]|0;if((xa|0)==0){Oe=nd;Pe=od;Qe=pd;Re=qd}else{c[xa+16>>2]=0;Oe=nd;Pe=od;Qe=pd;Re=qd}}else{if(nd>>>0<16){xa=nd;Yb=od;wa=pd;Ga=qd;while(1){if((Yb|0)==0){ya=xa;za=0;Aa=wa;Ba=la;Ca=Ga;Da=r;Ea=s;break a}Ha=Yb+ -1|0;ua=Ga+1|0;Ja=(d[Ga]<>>0<16){xa=va;Yb=Ha;wa=Ja;Ga=ua}else{Se=Ha;Te=Ja;Ue=ua;break}}}else{Se=od;Te=pd;Ue=qd}c[F>>2]=Te;Ga=c[A>>2]|0;if((Ga|0)==0){Ve=Ia}else{c[Ga+20>>2]=Te;Ve=c[z>>2]|0}if((Ve&512|0)==0){Oe=0;Pe=Se;Qe=0;Re=Ue}else{a[j]=Te;a[y]=Te>>>8;c[x>>2]=gf(c[x>>2]|0,j,2)|0;Oe=0;Pe=Se;Qe=0;Re=Ue}}c[l>>2]=5;Hb=Oe;Ib=Pe;Jb=Qe;Kb=Re;ta=73}else if((ta|0)==202){ta=0;if(Sc>>>0>5&la>>>0>257){c[m>>2]=o;c[n>>2]=la;c[f>>2]=Uc;c[p>>2]=Sc;c[u>>2]=Tc;c[v>>2]=Rc;Gf(f,r);Ga=c[m>>2]|0;wa=c[n>>2]|0;Yb=c[f>>2]|0;xa=c[p>>2]|0;ua=c[u>>2]|0;Ja=c[v>>2]|0;if((c[l>>2]|0)!=11){Oa=Ja;Pa=xa;Qa=ua;Ra=wa;Sa=Yb;Ta=r;Ua=Ga;Va=Vc;break}c[O>>2]=-1;Oa=Ja;Pa=xa;Qa=ua;Ra=wa;Sa=Yb;Ta=r;Ua=Ga;Va=Vc;break}c[O>>2]=0;Ga=(1<>2])+ -1|0;Yb=Ga&Tc;wa=c[J>>2]|0;ua=a[wa+(Yb<<2)+1|0]|0;xa=ua&255;if(xa>>>0>Rc>>>0){Ja=Rc;Ha=Sc;va=Tc;Od=Uc;while(1){if((Ha|0)==0){ya=Ja;za=0;Aa=va;Ba=la;Ca=Od;Da=r;Ea=Vc;break a}Td=Ha+ -1|0;oc=Od+1|0;Pd=(d[Od]<>>0>Wd>>>0){Ja=Wd;Ha=Td;va=Pd;Od=oc}else{We=Rd;Xe=Qd;Ye=Sd;Ze=Wd;_e=Td;$e=Pd;af=oc;break}}}else{We=ua;Xe=xa;Ye=Yb;Ze=Rc;_e=Sc;$e=Tc;af=Uc}Od=a[wa+(Ye<<2)|0]|0;va=b[wa+(Ye<<2)+2>>1]|0;Ha=Od&255;if(!(Od<<24>>24==0)){if((Ha&240|0)==0){Ja=va&65535;Ga=(1<>>Xe)+Ja|0;Ia=a[wa+(Ha<<2)+1|0]|0;if(((Ia&255)+Xe|0)>>>0>Ze>>>0){oc=Ze;Pd=_e;Td=$e;Wd=af;while(1){if((Pd|0)==0){ya=oc;za=0;Aa=Td;Ba=la;Ca=Wd;Da=r;Ea=Vc;break a}Sd=Pd+ -1|0;Qd=Wd+1|0;Rd=(d[Wd]<>>Xe)+Ja|0;Vd=a[wa+(Ud<<2)+1|0]|0;if(((Vd&255)+Xe|0)>>>0>Xb>>>0){oc=Xb;Pd=Sd;Td=Rd;Wd=Qd}else{bf=Ud;cf=Vd;df=Xb;ef=Sd;hf=Rd;jf=Qd;break}}}else{bf=Ha;cf=Ia;df=Ze;ef=_e;hf=$e;jf=af}Wd=b[wa+(bf<<2)+2>>1]|0;Td=a[wa+(bf<<2)|0]|0;c[O>>2]=Xe;kf=Xe;lf=df-Xe|0;mf=ef;nf=Td;of=cf;pf=Wd;qf=hf>>>Xe;rf=jf}else{kf=0;lf=Ze;mf=_e;nf=Od;of=We;pf=va;qf=$e;rf=af}}else{kf=0;lf=Ze;mf=_e;nf=0;of=We;pf=va;qf=$e;rf=af}Wd=of&255;Td=qf>>>Wd;Pd=lf-Wd|0;c[O>>2]=kf+Wd;c[F>>2]=pf&65535;Wd=nf&255;if(nf<<24>>24==0){c[l>>2]=25;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}if((Wd&32|0)!=0){c[O>>2]=-1;c[l>>2]=11;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}if((Wd&64|0)==0){oc=Wd&15;c[P>>2]=oc;c[l>>2]=21;$a=oc;ab=Pd;bb=mf;cb=Td;db=rf;eb=Vc;ta=221;break}else{c[B>>2]=22192;c[l>>2]=29;Oa=Pd;Pa=mf;Qa=Td;Ra=la;Sa=rf;Ta=r;Ua=o;Va=Vc;break}}}while(0);if((ta|0)==73){ta=0;Td=c[z>>2]|0;if((Td&1024|0)!=0){Pd=c[F>>2]|0;oc=Pd>>>0>Ib>>>0?Ib:Pd;if((oc|0)==0){sf=Pd;tf=Ib;uf=Kb}else{Wd=c[A>>2]|0;if((Wd|0)!=0?(Ja=c[Wd+16>>2]|0,(Ja|0)!=0):0){Ga=(c[Wd+20>>2]|0)-Pd|0;Pd=c[Wd+24>>2]|0;Kg(Ja+Ga|0,Kb|0,((Ga+oc|0)>>>0>Pd>>>0?Pd-Ga|0:oc)|0)|0;vf=c[z>>2]|0}else{vf=Td}if((vf&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Kb,oc)|0}Td=(c[F>>2]|0)-oc|0;c[F>>2]=Td;sf=Td;tf=Ib-oc|0;uf=Kb+oc|0}if((sf|0)==0){wf=tf;xf=uf}else{na=Hb;oa=tf;pa=Jb;qa=la;ra=uf;sa=s;ta=285;break}}else{wf=Ib;xf=Kb}c[F>>2]=0;c[l>>2]=6;Ic=Hb;Jc=wf;Kc=Jb;Lc=xf;ta=83}else if((ta|0)==221){ta=0;if(($a|0)==0){yf=c[F>>2]|0;zf=ab;Af=bb;Bf=cb;Cf=db}else{if(ab>>>0<$a>>>0){oc=ab;Td=bb;Ga=cb;Pd=db;while(1){if((Td|0)==0){ya=oc;za=0;Aa=Ga;Ba=la;Ca=Pd;Da=r;Ea=eb;break a}Ja=Td+ -1|0;Wd=Pd+1|0;Yb=(d[Pd]<>>0<$a>>>0){oc=xa;Td=Ja;Ga=Yb;Pd=Wd}else{Df=xa;Ef=Ja;Ff=Yb;Hf=Wd;break}}}else{Df=ab;Ef=bb;Ff=cb;Hf=db}Pd=(c[F>>2]|0)+((1<<$a)+ -1&Ff)|0;c[F>>2]=Pd;c[O>>2]=(c[O>>2]|0)+$a;yf=Pd;zf=Df-$a|0;Af=Ef;Bf=Ff>>>$a;Cf=Hf}c[Q>>2]=yf;c[l>>2]=22;ub=zf;vb=Af;wb=Bf;xb=Cf;yb=eb;ta=228}do{if((ta|0)==83){ta=0;if((c[z>>2]&2048|0)==0){Pd=c[A>>2]|0;if((Pd|0)==0){If=Jc;Jf=Lc}else{c[Pd+28>>2]=0;If=Jc;Jf=Lc}}else{if((Jc|0)==0){na=Ic;oa=0;pa=Kc;qa=la;ra=Lc;sa=s;ta=285;break a}else{Kf=0}while(1){Mf=Kf+1|0;Pd=a[Lc+Kf|0]|0;Ga=c[A>>2]|0;if(((Ga|0)!=0?(Td=c[Ga+28>>2]|0,(Td|0)!=0):0)?(oc=c[F>>2]|0,oc>>>0<(c[Ga+32>>2]|0)>>>0):0){c[F>>2]=oc+1;a[Td+oc|0]=Pd}Of=Pd<<24>>24!=0;if(Of&Mf>>>0>>0){Kf=Mf}else{break}}if((c[z>>2]&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Lc,Mf)|0}va=Jc-Mf|0;Od=Lc+Mf|0;if(Of){na=Ic;oa=va;pa=Kc;qa=la;ra=Od;sa=s;ta=285;break a}else{If=va;Jf=Od}}c[F>>2]=0;c[l>>2]=7;Db=Ic;Eb=If;Fb=Kc;Gb=Jf;ta=96}else if((ta|0)==228){ta=0;Od=(1<>2])+ -1|0;va=Od&wb;wa=c[L>>2]|0;Ia=a[wa+(va<<2)+1|0]|0;Ha=Ia&255;if(Ha>>>0>ub>>>0){Pd=ub;oc=vb;Td=wb;Ga=xb;while(1){if((oc|0)==0){ya=Pd;za=0;Aa=Td;Ba=la;Ca=Ga;Da=r;Ea=yb;break a}Wd=oc+ -1|0;Yb=Ga+1|0;Ja=(d[Ga]<>>0>xa>>>0){Pd=xa;oc=Wd;Td=Ja;Ga=Yb}else{Pf=Qd;Qf=Rd;Rf=ua;Sf=xa;Tf=Wd;Uf=Ja;Vf=Yb;break}}}else{Pf=Ia;Qf=Ha;Rf=va;Sf=ub;Tf=vb;Uf=wb;Vf=xb}Ga=a[wa+(Rf<<2)|0]|0;Td=b[wa+(Rf<<2)+2>>1]|0;oc=Ga&255;if((oc&240|0)==0){Pd=Td&65535;Od=(1<>>Qf)+Pd|0;Yb=a[wa+(oc<<2)+1|0]|0;if(((Yb&255)+Qf|0)>>>0>Sf>>>0){Ja=Sf;Wd=Tf;xa=Uf;ua=Vf;while(1){if((Wd|0)==0){ya=Ja;za=0;Aa=xa;Ba=la;Ca=ua;Da=r;Ea=yb;break a}Rd=Wd+ -1|0;Qd=ua+1|0;Sd=(d[ua]<>>Qf)+Pd|0;Ud=a[wa+(Vd<<2)+1|0]|0;if(((Ud&255)+Qf|0)>>>0>Xb>>>0){Ja=Xb;Wd=Rd;xa=Sd;ua=Qd}else{Wf=Vd;Xf=Ud;Yf=Xb;Zf=Rd;_f=Sd;$f=Qd;break}}}else{Wf=oc;Xf=Yb;Yf=Sf;Zf=Tf;_f=Uf;$f=Vf}ua=b[wa+(Wf<<2)+2>>1]|0;xa=a[wa+(Wf<<2)|0]|0;Wd=(c[O>>2]|0)+Qf|0;c[O>>2]=Wd;ag=Wd;bg=Yf-Qf|0;cg=Zf;dg=xa;eg=Xf;fg=ua;gg=_f>>>Qf;hg=$f}else{ag=c[O>>2]|0;bg=Sf;cg=Tf;dg=Ga;eg=Pf;fg=Td;gg=Uf;hg=Vf}ua=eg&255;xa=gg>>>ua;Wd=bg-ua|0;c[O>>2]=ag+ua;ua=dg&255;if((ua&64|0)==0){c[R>>2]=fg&65535;Ja=ua&15;c[P>>2]=Ja;c[l>>2]=23;fb=Ja;gb=Wd;hb=cg;ib=xa;jb=hg;kb=yb;ta=240;break}else{c[B>>2]=22224;c[l>>2]=29;Oa=Wd;Pa=cg;Qa=xa;Ra=la;Sa=hg;Ta=r;Ua=o;Va=yb;break}}}while(0);if((ta|0)==96){ta=0;if((c[z>>2]&4096|0)==0){xa=c[A>>2]|0;if((xa|0)==0){ig=Eb;jg=Gb}else{c[xa+36>>2]=0;ig=Eb;jg=Gb}}else{if((Eb|0)==0){na=Db;oa=0;pa=Fb;qa=la;ra=Gb;sa=s;ta=285;break}else{kg=0}while(1){lg=kg+1|0;xa=a[Gb+kg|0]|0;Wd=c[A>>2]|0;if(((Wd|0)!=0?(Ja=c[Wd+36>>2]|0,(Ja|0)!=0):0)?(ua=c[F>>2]|0,ua>>>0<(c[Wd+40>>2]|0)>>>0):0){c[F>>2]=ua+1;a[Ja+ua|0]=xa}mg=xa<<24>>24!=0;if(mg&lg>>>0>>0){kg=lg}else{break}}if((c[z>>2]&512|0)!=0){c[x>>2]=gf(c[x>>2]|0,Gb,lg)|0}xa=Eb-lg|0;ua=Gb+lg|0;if(mg){na=Db;oa=xa;pa=Fb;qa=la;ra=ua;sa=s;ta=285;break}else{ig=xa;jg=ua}}c[l>>2]=8;Lb=Db;Mb=ig;Nb=Fb;Ob=jg;ta=109}else if((ta|0)==240){ta=0;if((fb|0)==0){ng=gb;og=hb;pg=ib;qg=jb}else{if(gb>>>0>>0){ua=gb;xa=hb;Ja=ib;Wd=jb;while(1){if((xa|0)==0){ya=ua;za=0;Aa=Ja;Ba=la;Ca=Wd;Da=r;Ea=kb;break a}Pd=xa+ -1|0;Od=Wd+1|0;va=(d[Wd]<>>0>>0){ua=Ha;xa=Pd;Ja=va;Wd=Od}else{rg=Ha;sg=Pd;tg=va;ug=Od;break}}}else{rg=gb;sg=hb;tg=ib;ug=jb}c[R>>2]=(c[R>>2]|0)+((1<>2]=(c[O>>2]|0)+fb;ng=rg-fb|0;og=sg;pg=tg>>>fb;qg=ug}c[l>>2]=24;uc=ng;vc=og;wc=pg;xc=qg;yc=kb;ta=246}do{if((ta|0)==109){ta=0;Wd=c[z>>2]|0;if((Wd&512|0)!=0){if(Lb>>>0<16){Ja=Lb;xa=Mb;ua=Nb;Od=Ob;while(1){if((xa|0)==0){ya=Ja;za=0;Aa=ua;Ba=la;Ca=Od;Da=r;Ea=s;break a}va=xa+ -1|0;Pd=Od+1|0;Ha=(d[Od]<>>0<16){Ja=Ia;xa=va;ua=Ha;Od=Pd}else{vg=Ia;wg=va;xg=Ha;yg=Pd;break}}}else{vg=Lb;wg=Mb;xg=Nb;yg=Ob}if((xg|0)==(c[x>>2]&65535|0)){zg=0;Ag=wg;Bg=0;Cg=yg}else{c[B>>2]=21912;c[l>>2]=29;Oa=vg;Pa=wg;Qa=xg;Ra=la;Sa=yg;Ta=r;Ua=o;Va=s;break}}else{zg=Lb;Ag=Mb;Bg=Nb;Cg=Ob}Od=c[A>>2]|0;if((Od|0)!=0){c[Od+44>>2]=Wd>>>9&1;c[Od+48>>2]=1}Od=gf(0,0,0)|0;c[x>>2]=Od;c[E>>2]=Od;c[l>>2]=11;Oa=zg;Pa=Ag;Qa=Bg;Ra=la;Sa=Cg;Ta=r;Ua=o;Va=s}else if((ta|0)==246){ta=0;if((la|0)==0){na=uc;oa=vc;pa=wc;qa=0;ra=xc;sa=yc;ta=285;break a}Od=r-la|0;ua=c[R>>2]|0;if(ua>>>0>Od>>>0){xa=ua-Od|0;if(xa>>>0>(c[S>>2]|0)>>>0?(c[T>>2]|0)!=0:0){c[B>>2]=22248;c[l>>2]=29;Oa=uc;Pa=vc;Qa=wc;Ra=la;Sa=xc;Ta=r;Ua=o;Va=yc;break}Od=c[U>>2]|0;if(xa>>>0>Od>>>0){Ja=xa-Od|0;Dg=Ja;Eg=(c[V>>2]|0)+((c[W>>2]|0)-Ja)|0}else{Dg=xa;Eg=(c[V>>2]|0)+(Od-xa)|0}xa=c[F>>2]|0;Fg=xa;Gg=Dg>>>0>xa>>>0?xa:Dg;Hg=Eg}else{xa=c[F>>2]|0;Fg=xa;Gg=xa;Hg=o+(0-ua)|0}ua=Gg>>>0>la>>>0?la:Gg;c[F>>2]=Fg-ua;xa=~la;Od=~Gg;Ja=xa>>>0>Od>>>0?xa:Od;Od=ua;xa=Hg;Td=o;while(1){a[Td]=a[xa]|0;Od=Od+ -1|0;if((Od|0)==0){break}else{xa=xa+1|0;Td=Td+1|0}}Td=la-ua|0;xa=o+~Ja|0;if((c[F>>2]|0)==0){c[l>>2]=20;Oa=uc;Pa=vc;Qa=wc;Ra=Td;Sa=xc;Ta=r;Ua=xa;Va=yc}else{Oa=uc;Pa=vc;Qa=wc;Ra=Td;Sa=xc;Ta=r;Ua=xa;Va=yc}}}while(0);ia=c[l>>2]|0;q=Oa;ja=Pa;ka=Qa;la=Ra;ma=Sa;r=Ta;o=Ua;s=Va}if((ta|0)==122){c[m>>2]=o;c[n>>2]=la;c[f>>2]=Cb;c[p>>2]=Ab;c[u>>2]=Bb;c[v>>2]=zb;k=2;i=h;return k|0}else if((ta|0)==133){ya=Kd+ -3|0;za=Ld;Aa=Md>>>3;Ba=la;Ca=Nd;Da=r;Ea=s}else if((ta|0)==284){c[l>>2]=28;ya=Cd;za=Dd;Aa=Ed;Ba=la;Ca=Fd;Da=jd;Ea=1}else if((ta|0)==285){ya=na;za=oa;Aa=pa;Ba=qa;Ca=ra;Da=r;Ea=sa}else if((ta|0)==299){k=-4;i=h;return k|0}else if((ta|0)==300){i=h;return k|0}c[m>>2]=o;c[n>>2]=Ba;c[f>>2]=Ca;c[p>>2]=za;c[u>>2]=Aa;c[v>>2]=ya;if((c[W>>2]|0)==0){if((c[l>>2]|0)>>>0<26?(Da|0)!=(c[n>>2]|0):0){ta=289}}else{ta=289}if((ta|0)==289?(Lf(f,Da)|0)!=0:0){c[l>>2]=30;k=-4;i=h;return k|0}ta=c[p>>2]|0;p=c[n>>2]|0;n=Da-p|0;W=f+8|0;c[W>>2]=t-ta+(c[W>>2]|0);c[X>>2]=(c[X>>2]|0)+n;c[Y>>2]=(c[Y>>2]|0)+n;Y=(Da|0)==(p|0);if(!((c[w>>2]|0)==0|Y)){w=c[x>>2]|0;p=(c[m>>2]|0)+(0-n)|0;if((c[z>>2]|0)==0){Ig=ff(w,p,n)|0}else{Ig=gf(w,p,n)|0}c[x>>2]=Ig;c[E>>2]=Ig}Ig=c[l>>2]|0;if((Ig|0)==19){Jg=256}else{Jg=(Ig|0)==14?256:0}c[f+44>>2]=((c[I>>2]|0)!=0?64:0)+(c[v>>2]|0)+((Ig|0)==11?128:0)+Jg;k=((t|0)==(ta|0)&Y|(g|0)==4)&(Ea|0)==0?-5:Ea;i=h;return k|0}function Lf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;e=c[a+28>>2]|0;f=e+52|0;g=c[f>>2]|0;if((g|0)==0){h=kb[c[a+32>>2]&1](c[a+40>>2]|0,1<>2],1)|0;c[f>>2]=h;if((h|0)==0){j=1;i=d;return j|0}else{k=h}}else{k=g}g=e+40|0;h=c[g>>2]|0;if((h|0)==0){l=1<>2];c[g>>2]=l;c[e+48>>2]=0;c[e+44>>2]=0;m=l}else{m=h}h=b-(c[a+16>>2]|0)|0;if(!(h>>>0>>0)){Kg(k|0,(c[a+12>>2]|0)+(0-m)|0,m|0)|0;c[e+48>>2]=0;c[e+44>>2]=c[g>>2];j=0;i=d;return j|0}b=e+48|0;l=c[b>>2]|0;n=m-l|0;m=n>>>0>h>>>0?h:n;n=a+12|0;Kg(k+l|0,(c[n>>2]|0)+(0-h)|0,m|0)|0;l=h-m|0;if((h|0)!=(m|0)){Kg(c[f>>2]|0,(c[n>>2]|0)+(0-l)|0,l|0)|0;c[b>>2]=l;c[e+44>>2]=c[g>>2];j=0;i=d;return j|0}l=(c[b>>2]|0)+h|0;n=c[g>>2]|0;c[b>>2]=(l|0)==(n|0)?0:l;l=e+44|0;e=c[l>>2]|0;if(!(e>>>0>>0)){j=0;i=d;return j|0}c[l>>2]=e+h;j=0;i=d;return j|0}function Mf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;b=i;if((a|0)==0){d=-2;i=b;return d|0}e=a+28|0;f=c[e>>2]|0;if((f|0)==0){d=-2;i=b;return d|0}g=a+36|0;h=c[g>>2]|0;if((h|0)==0){d=-2;i=b;return d|0}j=c[f+52>>2]|0;k=a+40|0;if((j|0)==0){l=h;m=f}else{mb[h&1](c[k>>2]|0,j);l=c[g>>2]|0;m=c[e>>2]|0}mb[l&1](c[k>>2]|0,m);c[e>>2]=0;d=0;i=b;return d|0}function Nf(d,f,g,h,j,k){d=d|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;l=i;i=i+64|0;m=l+32|0;n=l;o=m+0|0;p=o+32|0;do{b[o>>1]=0;o=o+2|0}while((o|0)<(p|0));o=(g|0)==0;if(!o){p=0;do{q=m+(e[f+(p<<1)>>1]<<1)|0;b[q>>1]=(b[q>>1]|0)+1<<16>>16;p=p+1|0}while((p|0)!=(g|0))}p=c[j>>2]|0;q=15;while(1){r=q+ -1|0;if((b[m+(q<<1)>>1]|0)!=0){break}if((r|0)==0){s=7;break}else{q=r}}if((s|0)==7){r=c[h>>2]|0;c[h>>2]=r+4;a[r]=64;a[r+1|0]=1;b[r+2>>1]=0;r=c[h>>2]|0;c[h>>2]=r+4;a[r]=64;a[r+1|0]=1;b[r+2>>1]=0;c[j>>2]=1;t=0;i=l;return t|0}r=p>>>0>q>>>0?q:p;a:do{if(q>>>0>1){p=1;while(1){u=p+1|0;if((b[m+(p<<1)>>1]|0)!=0){v=p;break a}if(u>>>0>>0){p=u}else{v=u;break}}}else{v=1}}while(0);p=r>>>0>>0?v:r;r=1;u=1;do{r=(r<<1)-(e[m+(u<<1)>>1]|0)|0;u=u+1|0;if((r|0)<0){t=-1;s=56;break}}while(u>>>0<16);if((s|0)==56){i=l;return t|0}if((r|0)>0?!((d|0)!=0&(q|0)==1):0){t=-1;i=l;return t|0}b[n+2>>1]=0;r=0;u=1;do{r=(e[m+(u<<1)>>1]|0)+(r&65535)|0;u=u+1|0;b[n+(u<<1)>>1]=r}while((u|0)!=15);if(!o){o=0;do{u=b[f+(o<<1)>>1]|0;if(!(u<<16>>16==0)){r=n+((u&65535)<<1)|0;u=b[r>>1]|0;b[r>>1]=u+1<<16>>16;b[k+((u&65535)<<1)>>1]=o}o=o+1|0}while((o|0)!=(g|0))}if((d|0)==0){w=0;x=1<>>0>851){t=1;i=l;return t|0}else{w=0;x=g;y=1;z=24504+ -514|0;A=256;B=24568+ -514|0}}else{g=1<>>0>591){t=1;i=l;return t|0}else{w=o;x=g;y=0;z=24632;A=-1;B=24696}}g=x+ -1|0;o=p&255;d=p;n=0;u=0;r=v;v=-1;C=c[h>>2]|0;D=0;E=x;b:while(1){x=1<>1]|0;L=K&65535;if((L|0)>=(A|0)){if((L|0)>(A|0)){M=b[B+(L<<1)>>1]&255;N=b[z+(L<<1)>>1]|0}else{M=96;N=0}}else{M=0;N=K}K=1<>>n;L=x;while(1){O=L-K|0;P=O+I|0;a[C+(P<<2)|0]=M;a[C+(P<<2)+1|0]=J;b[C+(P<<2)+2>>1]=N;if((L|0)==(K|0)){break}else{L=O}}L=1<>>1}}if((L|0)==0){Q=0}else{Q=(L+ -1&F)+L|0}R=H+1|0;K=m+(G<<1)|0;I=(b[K>>1]|0)+ -1<<16>>16;b[K>>1]=I;if(I<<16>>16==0){if((G|0)==(q|0)){break b}S=e[f+(e[k+(R<<1)>>1]<<1)>>1]|0}else{S=G}if(!(S>>>0>p>>>0)){F=Q;G=S;H=R;continue}T=Q&g;if((T|0)==(v|0)){F=Q;G=S;H=R}else{break}}H=(n|0)==0?p:n;G=C+(x<<2)|0;F=S-H|0;c:do{if(S>>>0>>0){I=S;K=F;O=1<>1]|0)|0;if((P|0)<1){U=K;break c}V=K+1|0;W=V+H|0;if(W>>>0>>0){I=W;K=V;O=P<<1}else{U=V;break}}}else{U=F}}while(0);F=(1<>>0>851|w&F>>>0>591){t=1;s=56;break}a[(c[h>>2]|0)+(T<<2)|0]=U;a[(c[h>>2]|0)+(T<<2)+1|0]=o;x=c[h>>2]|0;b[x+(T<<2)+2>>1]=(G-x|0)>>>2;d=U;n=H;u=Q;r=S;v=T;C=G;D=R;E=F}if((s|0)==56){i=l;return t|0}d:do{if((Q|0)!=0){s=n;R=J;D=Q;T=q;S=C;while(1){if((s|0)!=0){if((D&g|0)==(v|0)){X=s;Y=R;Z=T;_=S}else{X=0;Y=o;Z=p;_=c[h>>2]|0}}else{X=0;Y=R;Z=T;_=S}r=D>>>X;a[_+(r<<2)|0]=64;a[_+(r<<2)+1|0]=Y;b[_+(r<<2)+2>>1]=0;r=1<>>1}}if((r|0)==0){break d}D=(r+ -1&D)+r|0;if((D|0)==0){break}else{s=X;R=Y;T=Z;S=_}}}}while(0);c[h>>2]=(c[h>>2]|0)+(E<<2);c[j>>2]=p;t=0;i=l;return t|0}function Of(a){a=a|0;var d=0;d=i;c[a+2840>>2]=a+148;c[a+2848>>2]=25528;c[a+2852>>2]=a+2440;c[a+2860>>2]=25552;c[a+2864>>2]=a+2684;c[a+2872>>2]=25576;b[a+5816>>1]=0;c[a+5820>>2]=0;c[a+5812>>2]=8;Pf(a);i=d;return}function Pf(a){a=a|0;var d=0,e=0;d=i;e=0;do{b[a+(e<<2)+148>>1]=0;e=e+1|0}while((e|0)!=286);b[a+2440>>1]=0;b[a+2444>>1]=0;b[a+2448>>1]=0;b[a+2452>>1]=0;b[a+2456>>1]=0;b[a+2460>>1]=0;b[a+2464>>1]=0;b[a+2468>>1]=0;b[a+2472>>1]=0;b[a+2476>>1]=0;b[a+2480>>1]=0;b[a+2484>>1]=0;b[a+2488>>1]=0;b[a+2492>>1]=0;b[a+2496>>1]=0;b[a+2500>>1]=0;b[a+2504>>1]=0;b[a+2508>>1]=0;b[a+2512>>1]=0;b[a+2516>>1]=0;b[a+2520>>1]=0;b[a+2524>>1]=0;b[a+2528>>1]=0;b[a+2532>>1]=0;b[a+2536>>1]=0;b[a+2540>>1]=0;b[a+2544>>1]=0;b[a+2548>>1]=0;b[a+2552>>1]=0;b[a+2556>>1]=0;b[a+2684>>1]=0;b[a+2688>>1]=0;b[a+2692>>1]=0;b[a+2696>>1]=0;b[a+2700>>1]=0;b[a+2704>>1]=0;b[a+2708>>1]=0;b[a+2712>>1]=0;b[a+2716>>1]=0;b[a+2720>>1]=0;b[a+2724>>1]=0;b[a+2728>>1]=0;b[a+2732>>1]=0;b[a+2736>>1]=0;b[a+2740>>1]=0;b[a+2744>>1]=0;b[a+2748>>1]=0;b[a+2752>>1]=0;b[a+2756>>1]=0;b[a+1172>>1]=1;c[a+5804>>2]=0;c[a+5800>>2]=0;c[a+5808>>2]=0;c[a+5792>>2]=0;i=d;return}function Qf(d,f,g,h){d=d|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;j=i;k=d+5820|0;l=c[k>>2]|0;m=h&65535;h=d+5816|0;n=e[h>>1]|0|m<>1]=n;if((l|0)>13){o=d+20|0;p=c[o>>2]|0;c[o>>2]=p+1;q=d+8|0;a[(c[q>>2]|0)+p|0]=n;p=(e[h>>1]|0)>>>8&255;r=c[o>>2]|0;c[o>>2]=r+1;a[(c[q>>2]|0)+r|0]=p;p=c[k>>2]|0;r=m>>>(16-p|0);b[h>>1]=r;s=r;t=p+ -13|0}else{s=n;t=l+3|0}l=s&255;c[k>>2]=t;do{if((t|0)<=8){s=d+20|0;if((t|0)>0){n=c[s>>2]|0;c[s>>2]=n+1;p=d+8|0;a[(c[p>>2]|0)+n|0]=l;u=s;v=p;break}else{u=s;v=d+8|0;break}}else{s=d+20|0;p=c[s>>2]|0;c[s>>2]=p+1;n=d+8|0;a[(c[n>>2]|0)+p|0]=l;p=(e[h>>1]|0)>>>8&255;r=c[s>>2]|0;c[s>>2]=r+1;a[(c[n>>2]|0)+r|0]=p;u=s;v=n}}while(0);b[h>>1]=0;c[k>>2]=0;c[d+5812>>2]=8;d=c[u>>2]|0;c[u>>2]=d+1;a[(c[v>>2]|0)+d|0]=g;d=c[u>>2]|0;c[u>>2]=d+1;a[(c[v>>2]|0)+d|0]=g>>>8;d=g&65535^65535;k=c[u>>2]|0;c[u>>2]=k+1;a[(c[v>>2]|0)+k|0]=d;k=c[u>>2]|0;c[u>>2]=k+1;a[(c[v>>2]|0)+k|0]=d>>>8;if((g|0)==0){i=j;return}else{w=g;x=f}while(1){w=w+ -1|0;f=a[x]|0;g=c[u>>2]|0;c[u>>2]=g+1;a[(c[v>>2]|0)+g|0]=f;if((w|0)==0){break}else{x=x+1|0}}i=j;return}function Rf(d){d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;f=i;g=d+5820|0;h=c[g>>2]|0;j=d+5816|0;k=e[j>>1]|0|2<>1]=l;if((h|0)>13){m=d+20|0;n=c[m>>2]|0;c[m>>2]=n+1;o=d+8|0;a[(c[o>>2]|0)+n|0]=k;k=(e[j>>1]|0)>>>8&255;n=c[m>>2]|0;c[m>>2]=n+1;a[(c[o>>2]|0)+n|0]=k;k=c[g>>2]|0;n=2>>>(16-k|0)&65535;b[j>>1]=n;p=n;q=k+ -13|0}else{p=l;q=h+3|0}c[g>>2]=q;if((q|0)>9){h=d+20|0;l=c[h>>2]|0;c[h>>2]=l+1;k=d+8|0;a[(c[k>>2]|0)+l|0]=p;l=(e[j>>1]|0)>>>8&255;n=c[h>>2]|0;c[h>>2]=n+1;a[(c[k>>2]|0)+n|0]=l;b[j>>1]=0;r=(c[g>>2]|0)+ -9|0;s=0}else{r=q+7|0;s=p}c[g>>2]=r;if((r|0)!=16){if((r|0)>7){p=d+20|0;q=c[p>>2]|0;c[p>>2]=q+1;a[(c[d+8>>2]|0)+q|0]=s;q=(e[j>>1]|0)>>>8;b[j>>1]=q;p=(c[g>>2]|0)+ -8|0;c[g>>2]=p;t=p;u=q}else{t=r;u=s}}else{r=d+20|0;q=c[r>>2]|0;c[r>>2]=q+1;p=d+8|0;a[(c[p>>2]|0)+q|0]=s;s=(e[j>>1]|0)>>>8&255;q=c[r>>2]|0;c[r>>2]=q+1;a[(c[p>>2]|0)+q|0]=s;b[j>>1]=0;c[g>>2]=0;t=0;u=0}s=d+5812|0;if((11-t+(c[s>>2]|0)|0)>=9){c[s>>2]=7;i=f;return}q=u&65535|2<>1]=q;if((t|0)>13){u=d+20|0;p=c[u>>2]|0;c[u>>2]=p+1;r=d+8|0;a[(c[r>>2]|0)+p|0]=q;p=(e[j>>1]|0)>>>8&255;l=c[u>>2]|0;c[u>>2]=l+1;a[(c[r>>2]|0)+l|0]=p;p=c[g>>2]|0;l=2>>>(16-p|0);b[j>>1]=l;v=l;w=p+ -13|0}else{v=q;w=t+3|0}t=v&255;c[g>>2]=w;if((w|0)>9){v=d+20|0;q=c[v>>2]|0;c[v>>2]=q+1;p=d+8|0;a[(c[p>>2]|0)+q|0]=t;q=(e[j>>1]|0)>>>8&255;l=c[v>>2]|0;c[v>>2]=l+1;a[(c[p>>2]|0)+l|0]=q;b[j>>1]=0;x=0;y=(c[g>>2]|0)+ -9|0}else{x=t;y=w+7|0}c[g>>2]=y;if((y|0)==16){w=d+20|0;t=c[w>>2]|0;c[w>>2]=t+1;q=d+8|0;a[(c[q>>2]|0)+t|0]=x;t=(e[j>>1]|0)>>>8&255;l=c[w>>2]|0;c[w>>2]=l+1;a[(c[q>>2]|0)+l|0]=t;b[j>>1]=0;c[g>>2]=0;c[s>>2]=7;i=f;return}if((y|0)<=7){c[s>>2]=7;i=f;return}y=d+20|0;t=c[y>>2]|0;c[y>>2]=t+1;a[(c[d+8>>2]|0)+t|0]=x;b[j>>1]=(e[j>>1]|0)>>>8;c[g>>2]=(c[g>>2]|0)+ -8;c[s>>2]=7;i=f;return}function Sf(f,g,h,j){f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;k=i;if((c[f+132>>2]|0)>0){l=(c[f>>2]|0)+44|0;if((c[l>>2]|0)==2){m=-201342849;n=0;while(1){if((m&1|0)!=0?(b[f+(n<<2)+148>>1]|0)!=0:0){o=0;break}p=n+1|0;if((p|0)<32){m=m>>>1;n=p}else{q=6;break}}a:do{if((q|0)==6){if(((b[f+184>>1]|0)==0?(b[f+188>>1]|0)==0:0)?(b[f+200>>1]|0)==0:0){n=32;while(1){m=n+1|0;if((b[f+(n<<2)+148>>1]|0)!=0){o=1;break a}if((m|0)<256){n=m}else{o=0;break}}}else{o=1}}}while(0);c[l>>2]=o}Tf(f,f+2840|0);Tf(f,f+2852|0);Wf(f,f+148|0,c[f+2844>>2]|0);Wf(f,f+2440|0,c[f+2856>>2]|0);Tf(f,f+2864|0);o=18;while(1){l=o+ -1|0;if((b[f+(d[27352+o|0]<<2)+2686>>1]|0)!=0){r=o;break}if((l|0)>2){o=l}else{r=l;break}}o=f+5800|0;l=(r*3|0)+17+(c[o>>2]|0)|0;c[o>>2]=l;o=(l+10|0)>>>3;l=((c[f+5804>>2]|0)+10|0)>>>3;s=r;t=l>>>0>o>>>0?o:l;u=l}else{l=h+5|0;s=0;t=l;u=l}do{if((h+4|0)>>>0>t>>>0|(g|0)==0){l=f+5820|0;o=c[l>>2]|0;r=(o|0)>13;if((c[f+136>>2]|0)==4|(u|0)==(t|0)){q=j+2&65535;n=f+5816|0;m=e[n>>1]|q<>1]=m;if(r){p=f+20|0;v=c[p>>2]|0;c[p>>2]=v+1;w=f+8|0;a[(c[w>>2]|0)+v|0]=m;m=(e[n>>1]|0)>>>8&255;v=c[p>>2]|0;c[p>>2]=v+1;a[(c[w>>2]|0)+v|0]=m;m=c[l>>2]|0;b[n>>1]=q>>>(16-m|0);x=m+ -13|0}else{x=o+3|0}c[l>>2]=x;Uf(f,25600,26752);break}m=j+4&65535;q=f+5816|0;n=e[q>>1]|m<>1]=n;if(r){r=f+20|0;v=c[r>>2]|0;c[r>>2]=v+1;w=f+8|0;a[(c[w>>2]|0)+v|0]=n;v=(e[q>>1]|0)>>>8&255;p=c[r>>2]|0;c[r>>2]=p+1;a[(c[w>>2]|0)+p|0]=v;v=c[l>>2]|0;p=m>>>(16-v|0);b[q>>1]=p;y=p;z=v+ -13|0}else{y=n;z=o+3|0}c[l>>2]=z;o=c[f+2844>>2]|0;n=c[f+2856>>2]|0;v=o+65280&65535;p=y&65535|v<>1]=p;if((z|0)>11){m=f+20|0;w=c[m>>2]|0;c[m>>2]=w+1;r=f+8|0;a[(c[r>>2]|0)+w|0]=p;w=(e[q>>1]|0)>>>8&255;A=c[m>>2]|0;c[m>>2]=A+1;a[(c[r>>2]|0)+A|0]=w;w=c[l>>2]|0;A=v>>>(16-w|0);b[q>>1]=A;B=w+ -11|0;C=A}else{B=z+5|0;C=p}c[l>>2]=B;p=n&65535;A=p<>1]=A;if((B|0)>11){w=f+20|0;v=c[w>>2]|0;c[w>>2]=v+1;r=f+8|0;a[(c[r>>2]|0)+v|0]=A;v=(e[q>>1]|0)>>>8&255;m=c[w>>2]|0;c[w>>2]=m+1;a[(c[r>>2]|0)+m|0]=v;v=c[l>>2]|0;m=p>>>(16-v|0);b[q>>1]=m;D=v+ -11|0;E=m}else{D=B+5|0;E=A}c[l>>2]=D;A=s+65533&65535;m=A<>1]=m;if((D|0)>12){v=f+20|0;p=c[v>>2]|0;c[v>>2]=p+1;r=f+8|0;a[(c[r>>2]|0)+p|0]=m;p=(e[q>>1]|0)>>>8&255;w=c[v>>2]|0;c[v>>2]=w+1;a[(c[r>>2]|0)+w|0]=p;p=c[l>>2]|0;w=A>>>(16-p|0);b[q>>1]=w;F=w;G=p+ -12|0}else{F=m;G=D+4|0}c[l>>2]=G;if((s|0)>-1){m=f+20|0;p=f+8|0;w=G;A=F;r=0;while(1){v=e[f+(d[27352+r|0]<<2)+2686>>1]|0;H=v<>1]=H;if((w|0)>13){I=c[m>>2]|0;c[m>>2]=I+1;a[(c[p>>2]|0)+I|0]=H;I=(e[q>>1]|0)>>>8&255;J=c[m>>2]|0;c[m>>2]=J+1;a[(c[p>>2]|0)+J|0]=I;I=c[l>>2]|0;J=v>>>(16-I|0);b[q>>1]=J;K=J;L=I+ -13|0}else{K=H;L=w+3|0}c[l>>2]=L;if((r|0)==(s|0)){break}else{w=L;A=K;r=r+1|0}}}r=f+148|0;Vf(f,r,o);A=f+2440|0;Vf(f,A,n);Uf(f,r,A)}else{Qf(f,g,h,j)}}while(0);Pf(f);if((j|0)==0){i=k;return}j=f+5820|0;h=c[j>>2]|0;if((h|0)<=8){g=f+5816|0;if((h|0)>0){h=b[g>>1]&255;K=f+20|0;L=c[K>>2]|0;c[K>>2]=L+1;a[(c[f+8>>2]|0)+L|0]=h;M=g}else{M=g}}else{g=f+5816|0;h=b[g>>1]&255;L=f+20|0;K=c[L>>2]|0;c[L>>2]=K+1;s=f+8|0;a[(c[s>>2]|0)+K|0]=h;h=(e[g>>1]|0)>>>8&255;K=c[L>>2]|0;c[L>>2]=K+1;a[(c[s>>2]|0)+K|0]=h;M=g}b[M>>1]=0;c[j>>2]=0;i=k;return}function Tf(f,g){f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0;h=i;i=i+32|0;j=h;k=c[g>>2]|0;l=g+8|0;m=c[l>>2]|0;n=c[m>>2]|0;o=c[m+12>>2]|0;m=f+5200|0;c[m>>2]=0;p=f+5204|0;c[p>>2]=573;if((o|0)>0){q=-1;r=0;while(1){if((b[k+(r<<2)>>1]|0)==0){b[k+(r<<2)+2>>1]=0;s=q}else{t=(c[m>>2]|0)+1|0;c[m>>2]=t;c[f+(t<<2)+2908>>2]=r;a[f+r+5208|0]=0;s=r}r=r+1|0;if((r|0)==(o|0)){break}else{q=s}}q=c[m>>2]|0;if((q|0)<2){u=q;v=s;w=3}else{x=s}}else{u=0;v=-1;w=3}if((w|0)==3){w=f+5800|0;s=f+5804|0;if((n|0)==0){q=u;r=v;while(1){t=(r|0)<2;y=r+1|0;z=t?y:r;A=t?y:0;y=q+1|0;c[m>>2]=y;c[f+(y<<2)+2908>>2]=A;b[k+(A<<2)>>1]=1;a[f+A+5208|0]=0;c[w>>2]=(c[w>>2]|0)+ -1;A=c[m>>2]|0;if((A|0)<2){q=A;r=z}else{x=z;break}}}else{r=u;u=v;while(1){v=(u|0)<2;q=u+1|0;z=v?q:u;A=v?q:0;q=r+1|0;c[m>>2]=q;c[f+(q<<2)+2908>>2]=A;b[k+(A<<2)>>1]=1;a[f+A+5208|0]=0;c[w>>2]=(c[w>>2]|0)+ -1;c[s>>2]=(c[s>>2]|0)-(e[n+(A<<2)+2>>1]|0);A=c[m>>2]|0;if((A|0)<2){r=A;u=z}else{x=z;break}}}}u=g+4|0;c[u>>2]=x;r=c[m>>2]|0;if((r|0)>1){n=r;s=(r|0)/2|0;while(1){w=c[f+(s<<2)+2908>>2]|0;z=f+w+5208|0;A=s<<1;a:do{if((A|0)>(n|0)){B=s}else{q=k+(w<<2)|0;v=s;y=n;t=A;while(1){do{if((t|0)<(y|0)){C=t|1;D=c[f+(C<<2)+2908>>2]|0;E=b[k+(D<<2)>>1]|0;F=c[f+(t<<2)+2908>>2]|0;G=b[k+(F<<2)>>1]|0;if(!((E&65535)<(G&65535))){if(!(E<<16>>16==G<<16>>16)){H=t;break}if((d[f+D+5208|0]|0)>(d[f+F+5208|0]|0)){H=t;break}}H=C}else{H=t}}while(0);C=b[q>>1]|0;F=c[f+(H<<2)+2908>>2]|0;D=b[k+(F<<2)>>1]|0;if((C&65535)<(D&65535)){B=v;break a}if(C<<16>>16==D<<16>>16?(d[z]|0)<=(d[f+F+5208|0]|0):0){B=v;break a}c[f+(v<<2)+2908>>2]=F;F=H<<1;D=c[m>>2]|0;if((F|0)>(D|0)){B=H;break}else{v=H;y=D;t=F}}}}while(0);c[f+(B<<2)+2908>>2]=w;z=s+ -1|0;A=c[m>>2]|0;if((z|0)>0){n=A;s=z}else{I=A;break}}}else{I=r}r=f+2912|0;s=I;I=o;while(1){o=c[r>>2]|0;n=s+ -1|0;c[m>>2]=n;B=c[f+(s<<2)+2908>>2]|0;c[r>>2]=B;H=f+B+5208|0;b:do{if((s|0)<3){J=1}else{A=k+(B<<2)|0;z=1;t=n;y=2;while(1){do{if((y|0)<(t|0)){v=y|1;q=c[f+(v<<2)+2908>>2]|0;F=b[k+(q<<2)>>1]|0;D=c[f+(y<<2)+2908>>2]|0;C=b[k+(D<<2)>>1]|0;if(!((F&65535)<(C&65535))){if(!(F<<16>>16==C<<16>>16)){K=y;break}if((d[f+q+5208|0]|0)>(d[f+D+5208|0]|0)){K=y;break}}K=v}else{K=y}}while(0);v=b[A>>1]|0;D=c[f+(K<<2)+2908>>2]|0;q=b[k+(D<<2)>>1]|0;if((v&65535)<(q&65535)){J=z;break b}if(v<<16>>16==q<<16>>16?(d[H]|0)<=(d[f+D+5208|0]|0):0){J=z;break b}c[f+(z<<2)+2908>>2]=D;D=K<<1;q=c[m>>2]|0;if((D|0)>(q|0)){J=K;break}else{z=K;t=q;y=D}}}}while(0);c[f+(J<<2)+2908>>2]=B;H=c[r>>2]|0;n=(c[p>>2]|0)+ -1|0;c[p>>2]=n;c[f+(n<<2)+2908>>2]=o;n=(c[p>>2]|0)+ -1|0;c[p>>2]=n;c[f+(n<<2)+2908>>2]=H;n=k+(I<<2)|0;b[n>>1]=(e[k+(H<<2)>>1]|0)+(e[k+(o<<2)>>1]|0);w=a[f+o+5208|0]|0;y=a[f+H+5208|0]|0;t=f+I+5208|0;a[t]=(((w&255)<(y&255)?y:w)&255)+1;w=I&65535;b[k+(H<<2)+2>>1]=w;b[k+(o<<2)+2>>1]=w;w=I+1|0;c[r>>2]=I;H=c[m>>2]|0;c:do{if((H|0)<2){L=1}else{y=1;z=H;A=2;while(1){do{if((A|0)<(z|0)){D=A|1;q=c[f+(D<<2)+2908>>2]|0;v=b[k+(q<<2)>>1]|0;C=c[f+(A<<2)+2908>>2]|0;F=b[k+(C<<2)>>1]|0;if(!((v&65535)<(F&65535))){if(!(v<<16>>16==F<<16>>16)){M=A;break}if((d[f+q+5208|0]|0)>(d[f+C+5208|0]|0)){M=A;break}}M=D}else{M=A}}while(0);D=b[n>>1]|0;C=c[f+(M<<2)+2908>>2]|0;q=b[k+(C<<2)>>1]|0;if((D&65535)<(q&65535)){L=y;break c}if(D<<16>>16==q<<16>>16?(d[t]|0)<=(d[f+C+5208|0]|0):0){L=y;break c}c[f+(y<<2)+2908>>2]=C;C=M<<1;q=c[m>>2]|0;if((C|0)>(q|0)){L=M;break}else{y=M;z=q;A=C}}}}while(0);c[f+(L<<2)+2908>>2]=I;t=c[m>>2]|0;if((t|0)>1){s=t;I=w}else{break}}I=c[r>>2]|0;r=(c[p>>2]|0)+ -1|0;c[p>>2]=r;c[f+(r<<2)+2908>>2]=I;I=c[g>>2]|0;g=c[u>>2]|0;u=c[l>>2]|0;l=c[u>>2]|0;r=c[u+4>>2]|0;s=c[u+8>>2]|0;m=c[u+16>>2]|0;u=f+2876|0;L=u+32|0;do{b[u>>1]=0;u=u+2|0}while((u|0)<(L|0));u=c[p>>2]|0;b[I+(c[f+(u<<2)+2908>>2]<<2)+2>>1]=0;p=u+1|0;d:do{if((p|0)<573){u=f+5800|0;L=f+5804|0;if((l|0)==0){M=p;J=0;while(1){K=c[f+(M<<2)+2908>>2]|0;t=I+(K<<2)+2|0;n=e[I+(e[t>>1]<<2)+2>>1]|0;H=(n|0)<(m|0);o=H?n+1|0:m;n=(H&1^1)+J|0;b[t>>1]=o;if((K|0)<=(g|0)){t=f+(o<<1)+2876|0;b[t>>1]=(b[t>>1]|0)+1<<16>>16;if((K|0)<(s|0)){N=0}else{N=c[r+(K-s<<2)>>2]|0}t=aa(e[I+(K<<2)>>1]|0,N+o|0)|0;c[u>>2]=t+(c[u>>2]|0)}t=M+1|0;if((t|0)==573){O=n;break}else{M=t;J=n}}}else{J=p;M=0;while(1){w=c[f+(J<<2)+2908>>2]|0;n=I+(w<<2)+2|0;t=e[I+(e[n>>1]<<2)+2>>1]|0;o=(t|0)<(m|0);K=o?t+1|0:m;t=(o&1^1)+M|0;b[n>>1]=K;if((w|0)<=(g|0)){n=f+(K<<1)+2876|0;b[n>>1]=(b[n>>1]|0)+1<<16>>16;if((w|0)<(s|0)){P=0}else{P=c[r+(w-s<<2)>>2]|0}n=e[I+(w<<2)>>1]|0;o=aa(n,P+K|0)|0;c[u>>2]=o+(c[u>>2]|0);o=aa((e[l+(w<<2)+2>>1]|0)+P|0,n)|0;c[L>>2]=o+(c[L>>2]|0)}o=J+1|0;if((o|0)==573){O=t;break}else{J=o;M=t}}}if((O|0)!=0){M=f+(m<<1)+2876|0;J=O;do{L=m;while(1){t=L+ -1|0;Q=f+(t<<1)+2876|0;R=b[Q>>1]|0;if(R<<16>>16==0){L=t}else{break}}b[Q>>1]=R+ -1<<16>>16;t=f+(L<<1)+2876|0;b[t>>1]=(e[t>>1]|0)+2;S=(b[M>>1]|0)+ -1<<16>>16;b[M>>1]=S;J=J+ -2|0}while((J|0)>0);if((m|0)!=0){J=S;M=m;t=573;while(1){o=M&65535;if(J<<16>>16==0){T=t}else{n=t;w=J&65535;while(1){K=n;do{K=K+ -1|0;U=c[f+(K<<2)+2908>>2]|0}while((U|0)>(g|0));H=I+(U<<2)+2|0;B=e[H>>1]|0;if((B|0)!=(M|0)){A=aa(e[I+(U<<2)>>1]|0,M-B|0)|0;c[u>>2]=A+(c[u>>2]|0);b[H>>1]=o}H=w+ -1|0;if((H|0)==0){T=K;break}else{n=K;w=H}}}w=M+ -1|0;if((w|0)==0){break d}J=b[f+(w<<1)+2876>>1]|0;M=w;t=T}}}}}while(0);T=1;U=0;do{U=(e[f+(T+ -1<<1)+2876>>1]|0)+(U&65534)<<1;b[j+(T<<1)>>1]=U;T=T+1|0}while((T|0)!=16);if((x|0)<0){i=h;return}else{V=0}while(1){T=b[k+(V<<2)+2>>1]|0;U=T&65535;if(!(T<<16>>16==0)){T=j+(U<<1)|0;f=b[T>>1]|0;b[T>>1]=f+1<<16>>16;T=U;U=f&65535;f=0;while(1){W=f|U&1;T=T+ -1|0;if((T|0)<=0){break}else{U=U>>>1;f=W<<1}}b[k+(V<<2)>>1]=W}if((V|0)==(x|0)){break}else{V=V+1|0}}i=h;return}function Uf(f,g,h){f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0;j=i;k=f+5792|0;if((c[k>>2]|0)==0){l=c[f+5820>>2]|0;m=b[f+5816>>1]|0}else{n=f+5796|0;o=f+5784|0;p=f+5820|0;q=f+5816|0;r=f+20|0;s=f+8|0;t=0;while(1){u=b[(c[n>>2]|0)+(t<<1)>>1]|0;v=u&65535;w=t+1|0;x=d[(c[o>>2]|0)+t|0]|0;do{if(u<<16>>16==0){y=e[g+(x<<2)+2>>1]|0;z=c[p>>2]|0;A=e[g+(x<<2)>>1]|0;B=e[q>>1]|0|A<>1]=C;if((z|0)>(16-y|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=B;B=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=B;B=c[p>>2]|0;D=A>>>(16-B|0)&65535;b[q>>1]=D;A=y+ -16+B|0;c[p>>2]=A;E=D;F=A;break}else{A=z+y|0;c[p>>2]=A;E=C;F=A;break}}else{A=d[25272+x|0]|0;C=(A|256)+1|0;y=e[g+(C<<2)+2>>1]|0;z=c[p>>2]|0;D=e[g+(C<<2)>>1]|0;C=e[q>>1]|0|D<>1]=B;if((z|0)>(16-y|0)){G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=C;C=(e[q>>1]|0)>>>8&255;G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=C;C=c[p>>2]|0;G=D>>>(16-C|0)&65535;b[q>>1]=G;H=G;I=y+ -16+C|0}else{H=B;I=z+y|0}c[p>>2]=I;y=c[26872+(A<<2)>>2]|0;do{if((A+ -8|0)>>>0<20){z=x-(c[26992+(A<<2)>>2]|0)&65535;B=z<>1]=C;if((I|0)>(16-y|0)){G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=B;B=(e[q>>1]|0)>>>8&255;G=c[r>>2]|0;c[r>>2]=G+1;a[(c[s>>2]|0)+G|0]=B;B=c[p>>2]|0;G=z>>>(16-B|0)&65535;b[q>>1]=G;z=y+ -16+B|0;c[p>>2]=z;J=z;K=G;break}else{G=I+y|0;c[p>>2]=G;J=G;K=C;break}}else{J=I;K=H}}while(0);y=v+ -1|0;if(y>>>0<256){L=y}else{L=(y>>>7)+256|0}A=d[24760+L|0]|0;C=e[h+(A<<2)+2>>1]|0;G=e[h+(A<<2)>>1]|0;z=K&65535|G<>1]=B;if((J|0)>(16-C|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=z;z=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=z;z=c[p>>2]|0;D=G>>>(16-z|0)&65535;b[q>>1]=D;M=C+ -16+z|0;N=D}else{M=J+C|0;N=B}c[p>>2]=M;B=c[27112+(A<<2)>>2]|0;if((A+ -4|0)>>>0<26){C=y-(c[27232+(A<<2)>>2]|0)&65535;A=C<>1]=y;if((M|0)>(16-B|0)){D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=A;A=(e[q>>1]|0)>>>8&255;D=c[r>>2]|0;c[r>>2]=D+1;a[(c[s>>2]|0)+D|0]=A;A=c[p>>2]|0;D=C>>>(16-A|0)&65535;b[q>>1]=D;C=B+ -16+A|0;c[p>>2]=C;E=D;F=C;break}else{C=M+B|0;c[p>>2]=C;E=y;F=C;break}}else{E=N;F=M}}}while(0);if(w>>>0<(c[k>>2]|0)>>>0){t=w}else{l=F;m=E;break}}}E=g+1026|0;F=e[E>>1]|0;t=f+5820|0;k=e[g+1024>>1]|0;g=f+5816|0;M=m&65535|k<>1]=M;if((l|0)>(16-F|0)){m=f+20|0;N=c[m>>2]|0;c[m>>2]=N+1;p=f+8|0;a[(c[p>>2]|0)+N|0]=M;M=(e[g>>1]|0)>>>8&255;N=c[m>>2]|0;c[m>>2]=N+1;a[(c[p>>2]|0)+N|0]=M;M=c[t>>2]|0;b[g>>1]=k>>>(16-M|0);O=F+ -16+M|0;c[t>>2]=O;P=b[E>>1]|0;Q=P&65535;R=f+5812|0;c[R>>2]=Q;i=j;return}else{O=l+F|0;c[t>>2]=O;P=b[E>>1]|0;Q=P&65535;R=f+5812|0;c[R>>2]=Q;i=j;return}}function Vf(d,f,g){d=d|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0;h=i;j=b[f+2>>1]|0;k=j<<16>>16==0;l=d+2754|0;m=d+5820|0;n=d+2752|0;o=d+5816|0;p=d+20|0;q=d+8|0;r=d+2758|0;s=d+2756|0;t=d+2750|0;u=d+2748|0;v=k?138:7;w=k?3:4;k=0;x=j&65535;j=-1;a:while(1){y=0;z=k;while(1){if((z|0)>(g|0)){break a}z=z+1|0;A=b[f+(z<<2)+2>>1]|0;B=A&65535;C=y+1|0;D=(x|0)==(B|0);if(!((C|0)<(v|0)&D)){break}else{y=C}}do{if((C|0)>=(w|0)){if((x|0)!=0){if((x|0)==(j|0)){E=b[o>>1]|0;F=c[m>>2]|0;G=C}else{H=e[d+(x<<2)+2686>>1]|0;I=c[m>>2]|0;J=e[d+(x<<2)+2684>>1]|0;K=e[o>>1]|0|J<>1]=L;if((I|0)>(16-H|0)){M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=c[m>>2]|0;M=J>>>(16-K|0)&65535;b[o>>1]=M;N=M;O=H+ -16+K|0}else{N=L;O=I+H|0}c[m>>2]=O;E=N;F=O;G=y}H=e[t>>1]|0;I=e[u>>1]|0;L=E&65535|I<>1]=L;if((F|0)>(16-H|0)){K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=L;K=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=K;K=c[m>>2]|0;M=I>>>(16-K|0);b[o>>1]=M;P=H+ -16+K|0;Q=M}else{P=F+H|0;Q=L}c[m>>2]=P;L=G+65533&65535;H=Q&65535|L<>1]=H;if((P|0)>14){M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=H;H=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=H;H=c[m>>2]|0;b[o>>1]=L>>>(16-H|0);c[m>>2]=H+ -14;break}else{c[m>>2]=P+2;break}}if((C|0)<11){H=e[l>>1]|0;L=c[m>>2]|0;M=e[n>>1]|0;K=e[o>>1]|0|M<>1]=K;if((L|0)>(16-H|0)){I=c[p>>2]|0;c[p>>2]=I+1;a[(c[q>>2]|0)+I|0]=K;I=(e[o>>1]|0)>>>8&255;J=c[p>>2]|0;c[p>>2]=J+1;a[(c[q>>2]|0)+J|0]=I;I=c[m>>2]|0;J=M>>>(16-I|0);b[o>>1]=J;R=H+ -16+I|0;S=J}else{R=L+H|0;S=K}c[m>>2]=R;K=y+65534&65535;H=S&65535|K<>1]=H;if((R|0)>13){L=c[p>>2]|0;c[p>>2]=L+1;a[(c[q>>2]|0)+L|0]=H;H=(e[o>>1]|0)>>>8&255;L=c[p>>2]|0;c[p>>2]=L+1;a[(c[q>>2]|0)+L|0]=H;H=c[m>>2]|0;b[o>>1]=K>>>(16-H|0);c[m>>2]=H+ -13;break}else{c[m>>2]=R+3;break}}else{H=e[r>>1]|0;K=c[m>>2]|0;L=e[s>>1]|0;J=e[o>>1]|0|L<>1]=J;if((K|0)>(16-H|0)){I=c[p>>2]|0;c[p>>2]=I+1;a[(c[q>>2]|0)+I|0]=J;I=(e[o>>1]|0)>>>8&255;M=c[p>>2]|0;c[p>>2]=M+1;a[(c[q>>2]|0)+M|0]=I;I=c[m>>2]|0;M=L>>>(16-I|0);b[o>>1]=M;T=H+ -16+I|0;U=M}else{T=K+H|0;U=J}c[m>>2]=T;J=y+65526&65535;H=U&65535|J<>1]=H;if((T|0)>9){K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=H;H=(e[o>>1]|0)>>>8&255;K=c[p>>2]|0;c[p>>2]=K+1;a[(c[q>>2]|0)+K|0]=H;H=c[m>>2]|0;b[o>>1]=J>>>(16-H|0);c[m>>2]=H+ -9;break}else{c[m>>2]=T+7;break}}}else{H=d+(x<<2)+2686|0;J=d+(x<<2)+2684|0;K=c[m>>2]|0;M=b[o>>1]|0;I=C;while(1){L=e[H>>1]|0;V=e[J>>1]|0;W=M&65535|V<>1]=X;if((K|0)>(16-L|0)){Y=c[p>>2]|0;c[p>>2]=Y+1;a[(c[q>>2]|0)+Y|0]=W;W=(e[o>>1]|0)>>>8&255;Y=c[p>>2]|0;c[p>>2]=Y+1;a[(c[q>>2]|0)+Y|0]=W;W=c[m>>2]|0;Y=V>>>(16-W|0)&65535;b[o>>1]=Y;Z=Y;_=L+ -16+W|0}else{Z=X;_=K+L|0}c[m>>2]=_;I=I+ -1|0;if((I|0)==0){break}else{K=_;M=Z}}}}while(0);if(A<<16>>16==0){$=x;v=138;w=3;k=z;x=B;j=$;continue}$=x;v=D?6:7;w=D?3:4;k=z;x=B;j=$}i=h;return}function Wf(a,c,d){a=a|0;c=c|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;f=i;g=b[c+2>>1]|0;h=g<<16>>16==0;b[c+(d+1<<2)+2>>1]=-1;j=a+2752|0;k=a+2756|0;l=a+2748|0;m=h?138:7;n=h?3:4;h=0;o=g&65535;g=-1;a:while(1){p=0;q=h;do{if((q|0)>(d|0)){break a}q=q+1|0;r=b[c+(q<<2)+2>>1]|0;s=r&65535;p=p+1|0;t=(o|0)==(s|0)}while((p|0)<(m|0)&t);do{if((p|0)>=(n|0)){if((o|0)==0){if((p|0)<11){b[j>>1]=(b[j>>1]|0)+1<<16>>16;break}else{b[k>>1]=(b[k>>1]|0)+1<<16>>16;break}}else{if((o|0)!=(g|0)){u=a+(o<<2)+2684|0;b[u>>1]=(b[u>>1]|0)+1<<16>>16}b[l>>1]=(b[l>>1]|0)+1<<16>>16;break}}else{u=a+(o<<2)+2684|0;b[u>>1]=(e[u>>1]|0)+p}}while(0);if(r<<16>>16==0){v=o;m=138;n=3;h=q;o=s;g=v;continue}v=o;m=t?6:7;n=t?3:4;h=q;o=s;g=v}i=f;return}function Xf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;a=i;d=gg(aa(c,b)|0)|0;i=a;return d|0}function Yf(a,b){a=a|0;b=b|0;a=i;hg(b);i=a;return}function Zf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0;f=i;i=i+944|0;g=f+680|0;h=f+424|0;j=f+192|0;k=f;l=aa(d,b)|0;if((l|0)==0){i=f;return}b=l-d|0;c[k+4>>2]=d;c[k>>2]=d;m=d;n=d;o=2;while(1){p=m+d+n|0;c[k+(o<<2)>>2]=p;if(p>>>0>>0){q=n;n=p;o=o+1|0;m=q}else{break}}m=0-d|0;o=a+b|0;if((b|0)>0){b=(d|0)==0;n=d>>>0>256?256:d;l=(n|0)==(d|0);q=o;p=1;r=0;s=a;t=1;while(1){do{if((p&3|0)!=3){u=t+ -1|0;a:do{if((c[k+(u<<2)>>2]|0)>>>0<(q-s|0)>>>0){c[j>>2]=s;if((t|0)>1){v=t;w=s;x=s;y=1;while(1){z=w+m|0;A=v+ -2|0;B=w+(0-((c[k+(A<<2)>>2]|0)+d))|0;if((nb[e&7](x,B)|0)>-1?(nb[e&7](x,z)|0)>-1:0){C=y;break}D=y+1|0;E=j+(y<<2)|0;if((nb[e&7](B,z)|0)>-1){c[E>>2]=B;F=B;G=v+ -1|0}else{c[E>>2]=z;F=z;G=A}if((G|0)<=1){C=D;break}v=G;w=F;x=c[j>>2]|0;y=D}if((C|0)>=2?(y=j+(C<<2)|0,c[y>>2]=g,!b):0){if((C|0)>0){H=d;I=g}else{x=c[j>>2]|0;Kg(g|0,x|0,n|0)|0;if(l){break}else{J=d;K=n}while(1){J=J-K|0;K=J>>>0>256?256:J;Kg(g|0,x|0,K|0)|0;if((J|0)==(K|0)){break a}}}while(1){x=H>>>0>256?256:H;w=c[j>>2]|0;Kg(I|0,w|0,x|0)|0;v=w;w=0;while(1){D=w+1|0;A=c[j+(D<<2)>>2]|0;Kg(v|0,A|0,x|0)|0;c[j+(w<<2)>>2]=v+x;if((D|0)==(C|0)){break}else{v=A;w=D}}if((H|0)==(x|0)){break a}H=H-x|0;I=c[y>>2]|0}}}}else{_f(s,d,e,p,r,t,0,k)}}while(0);if((t|0)==1){L=p<<1;M=p>>>31|r<<1;N=0;break}else{y=u>>>0>31;w=y?0:p;v=y?t+ -33|0:u;L=w<>>(32-v|0)|(y?p:r)<>2]=s;b:do{if((t|0)>1){v=t;y=s;w=s;D=1;while(1){A=y+m|0;z=v+ -2|0;E=y+(0-((c[k+(z<<2)>>2]|0)+d))|0;if((nb[e&7](w,E)|0)>-1?(nb[e&7](w,A)|0)>-1:0){O=D;break}B=D+1|0;P=j+(D<<2)|0;if((nb[e&7](E,A)|0)>-1){c[P>>2]=E;Q=E;R=v+ -1|0}else{c[P>>2]=A;Q=A;R=z}if((R|0)<=1){O=B;break}v=R;y=Q;w=c[j>>2]|0;D=B}if((O|0)>=2?(D=j+(O<<2)|0,c[D>>2]=h,!b):0){if((O|0)>0){S=d;T=h}else{w=c[j>>2]|0;Kg(h|0,w|0,n|0)|0;if(l){break}else{U=d;V=n}while(1){U=U-V|0;V=U>>>0>256?256:U;Kg(h|0,w|0,V|0)|0;if((U|0)==(V|0)){break b}}}while(1){w=S>>>0>256?256:S;y=c[j>>2]|0;Kg(T|0,y|0,w|0)|0;v=y;y=0;while(1){B=y+1|0;z=c[j+(B<<2)>>2]|0;Kg(v|0,z|0,w|0)|0;c[j+(y<<2)>>2]=v+w;if((B|0)==(O|0)){break}else{v=z;y=B}}if((S|0)==(w|0)){break b}S=S-w|0;T=c[D>>2]|0}}}}while(0);L=p>>>2|r<<30;M=r>>>2;N=t+2|0}}while(0);u=L|1;D=s+d|0;if(D>>>0>>0){p=u;r=M;s=D;t=N}else{W=M;X=u;Y=D;Z=N;break}}}else{W=0;X=1;Y=a;Z=1}_f(Y,d,e,X,W,Z,0,k);a=X;X=W;W=Y;Y=Z;while(1){if((Y|0)==1){if((a|0)==1){if((X|0)==0){break}else{_=52}}}else{_=52}if((_|0)==52?(_=0,(Y|0)>=2):0){Z=a>>>30;N=Y+ -2|0;M=(a<<1&2147483646|Z<<31)^3;t=(Z|X<<2)>>>1;_f(W+(0-((c[k+(N<<2)>>2]|0)+d))|0,d,e,M,t,Y+ -1|0,1,k);s=t<<1|Z&1;Z=M<<1|1;M=W+m|0;_f(M,d,e,Z,s,N,1,k);a=Z;X=s;W=M;Y=N;continue}N=a+ -1|0;if((N|0)!=0){if((N&1|0)==0){M=N;N=0;do{N=N+1|0;M=M>>>1}while((M&1|0)==0);if((N|0)!=0){$=N}else{_=57}}else{_=57}if((_|0)==57){_=0;if((X|0)!=0){if((X&1|0)==0){M=X;s=0;while(1){Z=s+1|0;t=M>>>1;if((t&1|0)==0){M=t;s=Z}else{ba=Z;break}}}else{ba=0}}else{ba=32}$=(ba|0)==0?0:ba+32|0}if($>>>0>31){ca=$;_=62}else{da=$;ea=a;fa=X;ga=$}}else{ca=32;_=62}if((_|0)==62){_=0;da=ca+ -32|0;ea=X;fa=0;ga=ca}a=fa<<32-da|ea>>>da;X=fa>>>da;W=W+m|0;Y=ga+Y|0}i=f;return}function _f(a,b,d,e,f,g,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0;k=i;i=i+752|0;l=k+232|0;m=k+488|0;n=k;c[n>>2]=a;o=0-b|0;a:do{if((e|0)==1&(f|0)==0){p=a;q=g;r=h;s=1;t=18}else{u=g;v=a;w=h;x=e;y=f;z=a;A=1;while(1){B=v+(0-(c[j+(u<<2)>>2]|0))|0;if((nb[d&7](B,z)|0)<1){p=v;q=u;r=w;s=A;t=18;break a}if((w|0)==0&(u|0)>1){C=c[j+(u+ -2<<2)>>2]|0;if((nb[d&7](v+o|0,B)|0)>-1){D=v;E=u;F=A;break a}if((nb[d&7](v+(0-(C+b))|0,B)|0)>-1){D=v;E=u;F=A;break a}}C=A+1|0;c[n+(A<<2)>>2]=B;G=x+ -1|0;if((G|0)!=0){if((G&1|0)==0){H=G;G=0;do{G=G+1|0;H=H>>>1}while((H&1|0)==0);if((G|0)!=0){I=G}else{t=10}}else{t=10}if((t|0)==10){t=0;if((y|0)!=0){if((y&1|0)==0){H=y;J=0;while(1){K=J+1|0;L=H>>>1;if((L&1|0)==0){H=L;J=K}else{M=K;break}}}else{M=0}}else{M=32}I=(M|0)==0?0:M+32|0}if(I>>>0>31){N=I;t=15}else{O=I;P=x;Q=y;R=I}}else{N=32;t=15}if((t|0)==15){t=0;O=N+ -32|0;P=y;Q=0;R=N}J=Q<<32-O|P>>>O;H=Q>>>O;G=R+u|0;if((J|0)==1&(H|0)==0){D=B;E=G;F=C;break a}u=G;v=B;w=0;x=J;y=H;z=c[n>>2]|0;A=C}}}while(0);if((t|0)==18){if((r|0)==0){D=p;E=q;F=s}else{i=k;return}}b:do{if((F|0)>=2?(s=n+(F<<2)|0,c[s>>2]=l,(b|0)!=0):0){if((F|0)>0){S=b;T=l}else{q=b>>>0>256?256:b;p=c[n>>2]|0;Kg(l|0,p|0,q|0)|0;if((q|0)==(b|0)){break}else{U=b;V=q}while(1){U=U-V|0;V=U>>>0>256?256:U;Kg(l|0,p|0,V|0)|0;if((U|0)==(V|0)){break b}}}while(1){p=S>>>0>256?256:S;q=c[n>>2]|0;Kg(T|0,q|0,p|0)|0;r=q;q=0;while(1){t=q+1|0;R=c[n+(t<<2)>>2]|0;Kg(r|0,R|0,p|0)|0;c[n+(q<<2)>>2]=r+p;if((t|0)==(F|0)){break}else{r=R;q=t}}if((S|0)==(p|0)){break b}S=S-p|0;T=c[s>>2]|0}}}while(0);c[l>>2]=D;c:do{if((E|0)>1){T=E;S=D;F=D;n=1;while(1){V=S+o|0;U=T+ -2|0;s=S+(0-((c[j+(U<<2)>>2]|0)+b))|0;if((nb[d&7](F,s)|0)>-1?(nb[d&7](F,V)|0)>-1:0){W=n;break}q=n+1|0;r=l+(n<<2)|0;if((nb[d&7](s,V)|0)>-1){c[r>>2]=s;X=s;Y=T+ -1|0}else{c[r>>2]=V;X=V;Y=U}if((Y|0)<=1){W=q;break}T=Y;S=X;F=c[l>>2]|0;n=q}if((W|0)>=2?(n=l+(W<<2)|0,c[n>>2]=m,(b|0)!=0):0){if((W|0)>0){Z=b;_=m}else{F=b>>>0>256?256:b;S=c[l>>2]|0;Kg(m|0,S|0,F|0)|0;if((F|0)==(b|0)){$=m;break}else{aa=b;ba=F}while(1){F=aa-ba|0;T=F>>>0>256?256:F;Kg(m|0,S|0,T|0)|0;if((F|0)==(T|0)){$=m;break c}else{aa=F;ba=T}}}while(1){S=Z>>>0>256?256:Z;T=c[l>>2]|0;Kg(_|0,T|0,S|0)|0;F=T;T=0;while(1){q=T+1|0;U=c[l+(q<<2)>>2]|0;Kg(F|0,U|0,S|0)|0;c[l+(T<<2)>>2]=F+S;if((q|0)==(W|0)){break}else{F=U;T=q}}if((Z|0)==(S|0)){$=m;break c}Z=Z-S|0;_=c[n>>2]|0}}else{$=m}}else{$=m}}while(0);i=k;return}function $f(b,c){b=b|0;c=c|0;var d=0,e=0;d=i;e=ag(b,c)|0;i=d;return((a[e]|0)==(c&255)<<24>>24?e:0)|0}function ag(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;f=d&255;if((f|0)==0){g=b+(Dg(b|0)|0)|0;i=e;return g|0}a:do{if((b&3|0)!=0){h=d&255;j=b;while(1){k=a[j]|0;if(k<<24>>24==0){g=j;l=13;break}m=j+1|0;if(k<<24>>24==h<<24>>24){g=j;l=13;break}if((m&3|0)==0){n=m;break a}else{j=m}}if((l|0)==13){i=e;return g|0}}else{n=b}}while(0);b=aa(f,16843009)|0;f=c[n>>2]|0;b:do{if(((f&-2139062144^-2139062144)&f+ -16843009|0)==0){l=f;j=n;while(1){h=l^b;m=j+4|0;if(((h&-2139062144^-2139062144)&h+ -16843009|0)!=0){o=j;break b}h=c[m>>2]|0;if(((h&-2139062144^-2139062144)&h+ -16843009|0)==0){l=h;j=m}else{o=m;break}}}else{o=n}}while(0);n=d&255;d=o;while(1){o=a[d]|0;if(o<<24>>24==0|o<<24>>24==n<<24>>24){g=d;break}else{d=d+1|0}}i=e;return g|0}function bg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+32|0;f=e;g=a[d]|0;if(!(g<<24>>24==0)?(a[d+1|0]|0)!=0:0){c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[f+24>>2]=0;c[f+28>>2]=0;h=d;d=g;do{j=d&255;k=f+(j>>>5<<2)|0;c[k>>2]=c[k>>2]|1<<(j&31);h=h+1|0;d=a[h]|0}while(!(d<<24>>24==0));d=a[b]|0;a:do{if(d<<24>>24==0){l=b}else{h=b;j=d;while(1){k=j&255;m=h+1|0;if((c[f+(k>>>5<<2)>>2]&1<<(k&31)|0)!=0){l=h;break a}k=a[m]|0;if(k<<24>>24==0){l=m;break}else{h=m;j=k}}}}while(0);n=l-b|0;i=e;return n|0}n=(ag(b,g<<24>>24)|0)-b|0;i=e;return n|0}function cg(a){a=a|0;var b=0,c=0,d=0,e=0;b=i;c=(Dg(a|0)|0)+1|0;d=gg(c)|0;if((d|0)==0){e=0;i=b;return e|0}Kg(d|0,a|0,c|0)|0;e=d;i=b;return e|0}function dg(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;f=b+(Dg(b|0)|0)|0;a:do{if((d|0)==0){g=f}else{h=d;j=c;k=f;while(1){l=a[j]|0;if(l<<24>>24==0){g=k;break a}m=h+ -1|0;n=k+1|0;a[k]=l;if((m|0)==0){g=n;break}else{h=m;j=j+1|0;k=n}}}}while(0);a[g]=0;i=e;return b|0}function eg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e;c[f+0>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[f+24>>2]=0;c[f+28>>2]=0;g=a[d]|0;if(g<<24>>24==0){h=0;i=e;return h|0}if((a[d+1|0]|0)==0){j=b;while(1){if((a[j]|0)==g<<24>>24){j=j+1|0}else{break}}h=j-b|0;i=e;return h|0}else{k=d;l=g}do{g=l&255;d=f+(g>>>5<<2)|0;c[d>>2]=c[d>>2]|1<<(g&31);k=k+1|0;l=a[k]|0}while(!(l<<24>>24==0));l=a[b]|0;a:do{if(l<<24>>24==0){m=b}else{k=b;g=l;while(1){d=g&255;j=k+1|0;if((c[f+(d>>>5<<2)>>2]&1<<(d&31)|0)==0){m=k;break a}d=a[j]|0;if(d<<24>>24==0){m=j;break}else{k=j;g=d}}}}while(0);h=m-b|0;i=e;return h|0}function fg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;e=i;if((b|0)==0){f=c[6912]|0;if((f|0)==0){g=0;i=e;return g|0}else{h=f}}else{h=b}b=eg(h,d)|0;f=h+b|0;if((a[f]|0)==0){c[6912]=0;g=0;i=e;return g|0}j=(bg(f,d)|0)+b|0;b=h+j|0;c[6912]=b;if((a[b]|0)==0){c[6912]=0;g=f;i=e;return g|0}else{c[6912]=h+(j+1);a[b]=0;g=f;i=e;return g|0}return 0} + + + +function gg(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ja=0,Ka=0,La=0,Ma=0;b=i;do{if(a>>>0<245){if(a>>>0<11){d=16}else{d=a+11&-8}e=d>>>3;f=c[6914]|0;g=f>>>e;if((g&3|0)!=0){h=(g&1^1)+e|0;j=h<<1;k=27696+(j<<2)|0;l=27696+(j+2<<2)|0;j=c[l>>2]|0;m=j+8|0;n=c[m>>2]|0;do{if((k|0)!=(n|0)){if(n>>>0<(c[27672>>2]|0)>>>0){_a()}o=n+12|0;if((c[o>>2]|0)==(j|0)){c[o>>2]=k;c[l>>2]=n;break}else{_a()}}else{c[6914]=f&~(1<>2]=n|3;l=j+(n|4)|0;c[l>>2]=c[l>>2]|1;p=m;i=b;return p|0}if(d>>>0>(c[27664>>2]|0)>>>0){if((g|0)!=0){l=2<>>12&16;k=l>>>n;l=k>>>5&8;o=k>>>l;k=o>>>2&4;q=o>>>k;o=q>>>1&2;r=q>>>o;q=r>>>1&1;s=(l|n|k|o|q)+(r>>>q)|0;q=s<<1;r=27696+(q<<2)|0;o=27696+(q+2<<2)|0;q=c[o>>2]|0;k=q+8|0;n=c[k>>2]|0;do{if((r|0)!=(n|0)){if(n>>>0<(c[27672>>2]|0)>>>0){_a()}l=n+12|0;if((c[l>>2]|0)==(q|0)){c[l>>2]=r;c[o>>2]=n;break}else{_a()}}else{c[6914]=f&~(1<>2]=d|3;o=q+d|0;c[q+(d|4)>>2]=n|1;c[q+f>>2]=n;f=c[27664>>2]|0;if((f|0)!=0){r=c[27676>>2]|0;e=f>>>3;f=e<<1;g=27696+(f<<2)|0;m=c[6914]|0;j=1<>2]|0;if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{t=e;u=h}}else{c[6914]=m|j;t=27696+(f+2<<2)|0;u=g}c[t>>2]=r;c[u+12>>2]=r;c[r+8>>2]=u;c[r+12>>2]=g}c[27664>>2]=n;c[27676>>2]=o;p=k;i=b;return p|0}o=c[27660>>2]|0;if((o|0)!=0){n=(o&0-o)+ -1|0;o=n>>>12&16;g=n>>>o;n=g>>>5&8;r=g>>>n;g=r>>>2&4;f=r>>>g;r=f>>>1&2;j=f>>>r;f=j>>>1&1;m=c[27960+((n|o|g|r|f)+(j>>>f)<<2)>>2]|0;f=(c[m+4>>2]&-8)-d|0;j=m;r=m;while(1){m=c[j+16>>2]|0;if((m|0)==0){g=c[j+20>>2]|0;if((g|0)==0){break}else{v=g}}else{v=m}m=(c[v+4>>2]&-8)-d|0;g=m>>>0>>0;f=g?m:f;j=v;r=g?v:r}j=c[27672>>2]|0;if(r>>>0>>0){_a()}k=r+d|0;if(!(r>>>0>>0)){_a()}q=c[r+24>>2]|0;s=c[r+12>>2]|0;do{if((s|0)==(r|0)){g=r+20|0;m=c[g>>2]|0;if((m|0)==0){o=r+16|0;n=c[o>>2]|0;if((n|0)==0){w=0;break}else{x=n;y=o}}else{x=m;y=g}while(1){g=x+20|0;m=c[g>>2]|0;if((m|0)!=0){x=m;y=g;continue}g=x+16|0;m=c[g>>2]|0;if((m|0)==0){break}else{x=m;y=g}}if(y>>>0>>0){_a()}else{c[y>>2]=0;w=x;break}}else{g=c[r+8>>2]|0;if(g>>>0>>0){_a()}m=g+12|0;if((c[m>>2]|0)!=(r|0)){_a()}o=s+8|0;if((c[o>>2]|0)==(r|0)){c[m>>2]=s;c[o>>2]=g;w=s;break}else{_a()}}}while(0);do{if((q|0)!=0){s=c[r+28>>2]|0;j=27960+(s<<2)|0;if((r|0)==(c[j>>2]|0)){c[j>>2]=w;if((w|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}s=q+16|0;if((c[s>>2]|0)==(r|0)){c[s>>2]=w}else{c[q+20>>2]=w}if((w|0)==0){break}}if(w>>>0<(c[27672>>2]|0)>>>0){_a()}c[w+24>>2]=q;s=c[r+16>>2]|0;do{if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+16>>2]=s;c[s+24>>2]=w;break}}}while(0);s=c[r+20>>2]|0;if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+20>>2]=s;c[s+24>>2]=w;break}}}}while(0);if(f>>>0<16){q=f+d|0;c[r+4>>2]=q|3;s=r+(q+4)|0;c[s>>2]=c[s>>2]|1}else{c[r+4>>2]=d|3;c[r+(d|4)>>2]=f|1;c[r+(f+d)>>2]=f;s=c[27664>>2]|0;if((s|0)!=0){q=c[27676>>2]|0;j=s>>>3;s=j<<1;g=27696+(s<<2)|0;o=c[6914]|0;m=1<>2]|0;if(n>>>0<(c[27672>>2]|0)>>>0){_a()}else{z=j;A=n}}else{c[6914]=o|m;z=27696+(s+2<<2)|0;A=g}c[z>>2]=q;c[A+12>>2]=q;c[q+8>>2]=A;c[q+12>>2]=g}c[27664>>2]=f;c[27676>>2]=k}p=r+8|0;i=b;return p|0}else{B=d}}else{B=d}}else{if(!(a>>>0>4294967231)){g=a+11|0;q=g&-8;s=c[27660>>2]|0;if((s|0)!=0){m=0-q|0;o=g>>>8;if((o|0)!=0){if(q>>>0>16777215){C=31}else{g=(o+1048320|0)>>>16&8;n=o<>>16&4;j=n<>>16&2;h=14-(o|g|n)+(j<>>15)|0;C=q>>>(h+7|0)&1|h<<1}}else{C=0}h=c[27960+(C<<2)>>2]|0;a:do{if((h|0)==0){D=m;E=0;F=0}else{if((C|0)==31){G=0}else{G=25-(C>>>1)|0}n=m;j=0;g=q<>2]&-8;H=l-q|0;if(H>>>0>>0){if((l|0)==(q|0)){D=H;E=o;F=o;break a}else{I=H;J=o}}else{I=n;J=e}H=c[o+20>>2]|0;l=c[o+(g>>>31<<2)+16>>2]|0;K=(H|0)==0|(H|0)==(l|0)?j:H;if((l|0)==0){D=I;E=K;F=J;break}else{n=I;j=K;g=g<<1;o=l;e=J}}}}while(0);if((E|0)==0&(F|0)==0){h=2<>>12&16;r=h>>>m;h=r>>>5&8;k=r>>>h;r=k>>>2&4;f=k>>>r;k=f>>>1&2;e=f>>>k;f=e>>>1&1;L=c[27960+((h|m|r|k|f)+(e>>>f)<<2)>>2]|0}else{L=E}if((L|0)==0){M=D;N=F}else{f=D;e=L;k=F;while(1){r=(c[e+4>>2]&-8)-q|0;m=r>>>0>>0;h=m?r:f;r=m?e:k;m=c[e+16>>2]|0;if((m|0)!=0){f=h;e=m;k=r;continue}m=c[e+20>>2]|0;if((m|0)==0){M=h;N=r;break}else{f=h;e=m;k=r}}}if((N|0)!=0?M>>>0<((c[27664>>2]|0)-q|0)>>>0:0){k=c[27672>>2]|0;if(N>>>0>>0){_a()}e=N+q|0;if(!(N>>>0>>0)){_a()}f=c[N+24>>2]|0;s=c[N+12>>2]|0;do{if((s|0)==(N|0)){r=N+20|0;m=c[r>>2]|0;if((m|0)==0){h=N+16|0;o=c[h>>2]|0;if((o|0)==0){O=0;break}else{P=o;Q=h}}else{P=m;Q=r}while(1){r=P+20|0;m=c[r>>2]|0;if((m|0)!=0){P=m;Q=r;continue}r=P+16|0;m=c[r>>2]|0;if((m|0)==0){break}else{P=m;Q=r}}if(Q>>>0>>0){_a()}else{c[Q>>2]=0;O=P;break}}else{r=c[N+8>>2]|0;if(r>>>0>>0){_a()}m=r+12|0;if((c[m>>2]|0)!=(N|0)){_a()}h=s+8|0;if((c[h>>2]|0)==(N|0)){c[m>>2]=s;c[h>>2]=r;O=s;break}else{_a()}}}while(0);do{if((f|0)!=0){s=c[N+28>>2]|0;k=27960+(s<<2)|0;if((N|0)==(c[k>>2]|0)){c[k>>2]=O;if((O|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}s=f+16|0;if((c[s>>2]|0)==(N|0)){c[s>>2]=O}else{c[f+20>>2]=O}if((O|0)==0){break}}if(O>>>0<(c[27672>>2]|0)>>>0){_a()}c[O+24>>2]=f;s=c[N+16>>2]|0;do{if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[O+16>>2]=s;c[s+24>>2]=O;break}}}while(0);s=c[N+20>>2]|0;if((s|0)!=0){if(s>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[O+20>>2]=s;c[s+24>>2]=O;break}}}}while(0);b:do{if(!(M>>>0<16)){c[N+4>>2]=q|3;c[N+(q|4)>>2]=M|1;c[N+(M+q)>>2]=M;f=M>>>3;if(M>>>0<256){s=f<<1;k=27696+(s<<2)|0;r=c[6914]|0;h=1<>2]|0;if(m>>>0<(c[27672>>2]|0)>>>0){_a()}else{R=f;S=m}}else{c[6914]=r|h;R=27696+(s+2<<2)|0;S=k}c[R>>2]=e;c[S+12>>2]=e;c[N+(q+8)>>2]=S;c[N+(q+12)>>2]=k;break}k=M>>>8;if((k|0)!=0){if(M>>>0>16777215){T=31}else{s=(k+1048320|0)>>>16&8;h=k<>>16&4;r=h<>>16&2;m=14-(k|s|h)+(r<>>15)|0;T=M>>>(m+7|0)&1|m<<1}}else{T=0}m=27960+(T<<2)|0;c[N+(q+28)>>2]=T;c[N+(q+20)>>2]=0;c[N+(q+16)>>2]=0;h=c[27660>>2]|0;r=1<>2]=h|r;c[m>>2]=e;c[N+(q+24)>>2]=m;c[N+(q+12)>>2]=e;c[N+(q+8)>>2]=e;break}r=c[m>>2]|0;if((T|0)==31){U=0}else{U=25-(T>>>1)|0}c:do{if((c[r+4>>2]&-8|0)!=(M|0)){m=M<>>31<<2)+16|0;s=c[V>>2]|0;if((s|0)==0){break}if((c[s+4>>2]&-8|0)==(M|0)){W=s;break c}else{m=m<<1;h=s}}if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[V>>2]=e;c[N+(q+24)>>2]=h;c[N+(q+12)>>2]=e;c[N+(q+8)>>2]=e;break b}}else{W=r}}while(0);r=W+8|0;m=c[r>>2]|0;s=c[27672>>2]|0;if(W>>>0>>0){_a()}if(m>>>0>>0){_a()}else{c[m+12>>2]=e;c[r>>2]=e;c[N+(q+8)>>2]=m;c[N+(q+12)>>2]=W;c[N+(q+24)>>2]=0;break}}else{m=M+q|0;c[N+4>>2]=m|3;r=N+(m+4)|0;c[r>>2]=c[r>>2]|1}}while(0);p=N+8|0;i=b;return p|0}else{B=q}}else{B=q}}else{B=-1}}}while(0);N=c[27664>>2]|0;if(!(B>>>0>N>>>0)){M=N-B|0;W=c[27676>>2]|0;if(M>>>0>15){c[27676>>2]=W+B;c[27664>>2]=M;c[W+(B+4)>>2]=M|1;c[W+N>>2]=M;c[W+4>>2]=B|3}else{c[27664>>2]=0;c[27676>>2]=0;c[W+4>>2]=N|3;M=W+(N+4)|0;c[M>>2]=c[M>>2]|1}p=W+8|0;i=b;return p|0}W=c[27668>>2]|0;if(B>>>0>>0){M=W-B|0;c[27668>>2]=M;W=c[27680>>2]|0;c[27680>>2]=W+B;c[W+(B+4)>>2]=M|1;c[W+4>>2]=B|3;p=W+8|0;i=b;return p|0}do{if((c[7032]|0)==0){W=Ia(30)|0;if((W+ -1&W|0)==0){c[28136>>2]=W;c[28132>>2]=W;c[28140>>2]=-1;c[28144>>2]=-1;c[28148>>2]=0;c[28100>>2]=0;c[7032]=(bb(0)|0)&-16^1431655768;break}else{_a()}}}while(0);W=B+48|0;M=c[28136>>2]|0;N=B+47|0;V=M+N|0;U=0-M|0;M=V&U;if(!(M>>>0>B>>>0)){p=0;i=b;return p|0}T=c[28096>>2]|0;if((T|0)!=0?(S=c[28088>>2]|0,R=S+M|0,R>>>0<=S>>>0|R>>>0>T>>>0):0){p=0;i=b;return p|0}d:do{if((c[28100>>2]&4|0)==0){T=c[27680>>2]|0;e:do{if((T|0)!=0){R=28104|0;while(1){S=c[R>>2]|0;if(!(S>>>0>T>>>0)?(X=R+4|0,(S+(c[X>>2]|0)|0)>>>0>T>>>0):0){break}S=c[R+8>>2]|0;if((S|0)==0){Y=182;break e}else{R=S}}if((R|0)!=0){S=V-(c[27668>>2]|0)&U;if(S>>>0<2147483647){O=Ca(S|0)|0;P=(O|0)==((c[R>>2]|0)+(c[X>>2]|0)|0);Z=O;_=S;$=P?O:-1;aa=P?S:0;Y=191}else{ba=0}}else{Y=182}}else{Y=182}}while(0);do{if((Y|0)==182){T=Ca(0)|0;if((T|0)!=(-1|0)){q=T;S=c[28132>>2]|0;P=S+ -1|0;if((P&q|0)==0){ca=M}else{ca=M-q+(P+q&0-S)|0}S=c[28088>>2]|0;q=S+ca|0;if(ca>>>0>B>>>0&ca>>>0<2147483647){P=c[28096>>2]|0;if((P|0)!=0?q>>>0<=S>>>0|q>>>0>P>>>0:0){ba=0;break}P=Ca(ca|0)|0;q=(P|0)==(T|0);Z=P;_=ca;$=q?T:-1;aa=q?ca:0;Y=191}else{ba=0}}else{ba=0}}}while(0);f:do{if((Y|0)==191){q=0-_|0;if(($|0)!=(-1|0)){da=$;ea=aa;Y=202;break d}do{if((Z|0)!=(-1|0)&_>>>0<2147483647&_>>>0>>0?(T=c[28136>>2]|0,P=N-_+T&0-T,P>>>0<2147483647):0){if((Ca(P|0)|0)==(-1|0)){Ca(q|0)|0;ba=aa;break f}else{fa=P+_|0;break}}else{fa=_}}while(0);if((Z|0)==(-1|0)){ba=aa}else{da=Z;ea=fa;Y=202;break d}}}while(0);c[28100>>2]=c[28100>>2]|4;ga=ba;Y=199}else{ga=0;Y=199}}while(0);if((((Y|0)==199?M>>>0<2147483647:0)?(ba=Ca(M|0)|0,M=Ca(0)|0,(M|0)!=(-1|0)&(ba|0)!=(-1|0)&ba>>>0>>0):0)?(fa=M-ba|0,M=fa>>>0>(B+40|0)>>>0,M):0){da=ba;ea=M?fa:ga;Y=202}if((Y|0)==202){ga=(c[28088>>2]|0)+ea|0;c[28088>>2]=ga;if(ga>>>0>(c[28092>>2]|0)>>>0){c[28092>>2]=ga}ga=c[27680>>2]|0;g:do{if((ga|0)!=0){fa=28104|0;while(1){ha=c[fa>>2]|0;ia=fa+4|0;ja=c[ia>>2]|0;if((da|0)==(ha+ja|0)){Y=214;break}M=c[fa+8>>2]|0;if((M|0)==0){break}else{fa=M}}if(((Y|0)==214?(c[fa+12>>2]&8|0)==0:0)?ga>>>0>=ha>>>0&ga>>>0>>0:0){c[ia>>2]=ja+ea;M=(c[27668>>2]|0)+ea|0;ba=ga+8|0;if((ba&7|0)==0){ka=0}else{ka=0-ba&7}ba=M-ka|0;c[27680>>2]=ga+ka;c[27668>>2]=ba;c[ga+(ka+4)>>2]=ba|1;c[ga+(M+4)>>2]=40;c[27684>>2]=c[28144>>2];break}if(da>>>0<(c[27672>>2]|0)>>>0){c[27672>>2]=da}M=da+ea|0;ba=28104|0;while(1){if((c[ba>>2]|0)==(M|0)){Y=224;break}Z=c[ba+8>>2]|0;if((Z|0)==0){break}else{ba=Z}}if((Y|0)==224?(c[ba+12>>2]&8|0)==0:0){c[ba>>2]=da;M=ba+4|0;c[M>>2]=(c[M>>2]|0)+ea;M=da+8|0;if((M&7|0)==0){la=0}else{la=0-M&7}M=da+(ea+8)|0;if((M&7|0)==0){ma=0}else{ma=0-M&7}M=da+(ma+ea)|0;fa=la+B|0;Z=da+fa|0;aa=M-(da+la)-B|0;c[da+(la+4)>>2]=B|3;h:do{if((M|0)!=(c[27680>>2]|0)){if((M|0)==(c[27676>>2]|0)){_=(c[27664>>2]|0)+aa|0;c[27664>>2]=_;c[27676>>2]=Z;c[da+(fa+4)>>2]=_|1;c[da+(_+fa)>>2]=_;break}_=ea+4|0;N=c[da+(_+ma)>>2]|0;if((N&3|0)==1){W=N&-8;$=N>>>3;do{if(!(N>>>0<256)){ca=c[da+((ma|24)+ea)>>2]|0;X=c[da+(ea+12+ma)>>2]|0;do{if((X|0)==(M|0)){U=ma|16;V=da+(_+U)|0;q=c[V>>2]|0;if((q|0)==0){R=da+(U+ea)|0;U=c[R>>2]|0;if((U|0)==0){na=0;break}else{oa=U;pa=R}}else{oa=q;pa=V}while(1){V=oa+20|0;q=c[V>>2]|0;if((q|0)!=0){oa=q;pa=V;continue}V=oa+16|0;q=c[V>>2]|0;if((q|0)==0){break}else{oa=q;pa=V}}if(pa>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[pa>>2]=0;na=oa;break}}else{V=c[da+((ma|8)+ea)>>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}q=V+12|0;if((c[q>>2]|0)!=(M|0)){_a()}R=X+8|0;if((c[R>>2]|0)==(M|0)){c[q>>2]=X;c[R>>2]=V;na=X;break}else{_a()}}}while(0);if((ca|0)!=0){X=c[da+(ea+28+ma)>>2]|0;h=27960+(X<<2)|0;if((M|0)==(c[h>>2]|0)){c[h>>2]=na;if((na|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}X=ca+16|0;if((c[X>>2]|0)==(M|0)){c[X>>2]=na}else{c[ca+20>>2]=na}if((na|0)==0){break}}if(na>>>0<(c[27672>>2]|0)>>>0){_a()}c[na+24>>2]=ca;X=ma|16;h=c[da+(X+ea)>>2]|0;do{if((h|0)!=0){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[na+16>>2]=h;c[h+24>>2]=na;break}}}while(0);h=c[da+(_+X)>>2]|0;if((h|0)!=0){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[na+20>>2]=h;c[h+24>>2]=na;break}}}}else{h=c[da+((ma|8)+ea)>>2]|0;ca=c[da+(ea+12+ma)>>2]|0;V=27696+($<<1<<2)|0;if((h|0)!=(V|0)){if(h>>>0<(c[27672>>2]|0)>>>0){_a()}if((c[h+12>>2]|0)!=(M|0)){_a()}}if((ca|0)==(h|0)){c[6914]=c[6914]&~(1<<$);break}if((ca|0)!=(V|0)){if(ca>>>0<(c[27672>>2]|0)>>>0){_a()}V=ca+8|0;if((c[V>>2]|0)==(M|0)){qa=V}else{_a()}}else{qa=ca+8|0}c[h+12>>2]=ca;c[qa>>2]=h}}while(0);ra=da+((W|ma)+ea)|0;sa=W+aa|0}else{ra=M;sa=aa}$=ra+4|0;c[$>>2]=c[$>>2]&-2;c[da+(fa+4)>>2]=sa|1;c[da+(sa+fa)>>2]=sa;$=sa>>>3;if(sa>>>0<256){_=$<<1;N=27696+(_<<2)|0;h=c[6914]|0;ca=1<<$;if((h&ca|0)!=0){$=27696+(_+2<<2)|0;V=c[$>>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{ta=$;ua=V}}else{c[6914]=h|ca;ta=27696+(_+2<<2)|0;ua=N}c[ta>>2]=Z;c[ua+12>>2]=Z;c[da+(fa+8)>>2]=ua;c[da+(fa+12)>>2]=N;break}N=sa>>>8;if((N|0)!=0){if(sa>>>0>16777215){va=31}else{_=(N+1048320|0)>>>16&8;ca=N<<_;N=(ca+520192|0)>>>16&4;h=ca<>>16&2;V=14-(N|_|ca)+(h<>>15)|0;va=sa>>>(V+7|0)&1|V<<1}}else{va=0}V=27960+(va<<2)|0;c[da+(fa+28)>>2]=va;c[da+(fa+20)>>2]=0;c[da+(fa+16)>>2]=0;ca=c[27660>>2]|0;h=1<>2]=ca|h;c[V>>2]=Z;c[da+(fa+24)>>2]=V;c[da+(fa+12)>>2]=Z;c[da+(fa+8)>>2]=Z;break}h=c[V>>2]|0;if((va|0)==31){wa=0}else{wa=25-(va>>>1)|0}i:do{if((c[h+4>>2]&-8|0)!=(sa|0)){V=sa<>>31<<2)+16|0;_=c[xa>>2]|0;if((_|0)==0){break}if((c[_+4>>2]&-8|0)==(sa|0)){ya=_;break i}else{V=V<<1;ca=_}}if(xa>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[xa>>2]=Z;c[da+(fa+24)>>2]=ca;c[da+(fa+12)>>2]=Z;c[da+(fa+8)>>2]=Z;break h}}else{ya=h}}while(0);h=ya+8|0;W=c[h>>2]|0;V=c[27672>>2]|0;if(ya>>>0>>0){_a()}if(W>>>0>>0){_a()}else{c[W+12>>2]=Z;c[h>>2]=Z;c[da+(fa+8)>>2]=W;c[da+(fa+12)>>2]=ya;c[da+(fa+24)>>2]=0;break}}else{W=(c[27668>>2]|0)+aa|0;c[27668>>2]=W;c[27680>>2]=Z;c[da+(fa+4)>>2]=W|1}}while(0);p=da+(la|8)|0;i=b;return p|0}fa=28104|0;while(1){za=c[fa>>2]|0;if(!(za>>>0>ga>>>0)?(Aa=c[fa+4>>2]|0,Ba=za+Aa|0,Ba>>>0>ga>>>0):0){break}fa=c[fa+8>>2]|0}fa=za+(Aa+ -39)|0;if((fa&7|0)==0){Da=0}else{Da=0-fa&7}fa=za+(Aa+ -47+Da)|0;Z=fa>>>0<(ga+16|0)>>>0?ga:fa;fa=Z+8|0;aa=da+8|0;if((aa&7|0)==0){Ea=0}else{Ea=0-aa&7}aa=ea+ -40-Ea|0;c[27680>>2]=da+Ea;c[27668>>2]=aa;c[da+(Ea+4)>>2]=aa|1;c[da+(ea+ -36)>>2]=40;c[27684>>2]=c[28144>>2];c[Z+4>>2]=27;c[fa+0>>2]=c[28104>>2];c[fa+4>>2]=c[28108>>2];c[fa+8>>2]=c[28112>>2];c[fa+12>>2]=c[28116>>2];c[28104>>2]=da;c[28108>>2]=ea;c[28116>>2]=0;c[28112>>2]=fa;fa=Z+28|0;c[fa>>2]=7;if((Z+32|0)>>>0>>0){aa=fa;while(1){fa=aa+4|0;c[fa>>2]=7;if((aa+8|0)>>>0>>0){aa=fa}else{break}}}if((Z|0)!=(ga|0)){aa=Z-ga|0;fa=ga+(aa+4)|0;c[fa>>2]=c[fa>>2]&-2;c[ga+4>>2]=aa|1;c[ga+aa>>2]=aa;fa=aa>>>3;if(aa>>>0<256){M=fa<<1;ba=27696+(M<<2)|0;W=c[6914]|0;h=1<>2]|0;if(V>>>0<(c[27672>>2]|0)>>>0){_a()}else{Fa=fa;Ga=V}}else{c[6914]=W|h;Fa=27696+(M+2<<2)|0;Ga=ba}c[Fa>>2]=ga;c[Ga+12>>2]=ga;c[ga+8>>2]=Ga;c[ga+12>>2]=ba;break}ba=aa>>>8;if((ba|0)!=0){if(aa>>>0>16777215){Ha=31}else{M=(ba+1048320|0)>>>16&8;h=ba<>>16&4;W=h<>>16&2;V=14-(ba|M|h)+(W<>>15)|0;Ha=aa>>>(V+7|0)&1|V<<1}}else{Ha=0}V=27960+(Ha<<2)|0;c[ga+28>>2]=Ha;c[ga+20>>2]=0;c[ga+16>>2]=0;h=c[27660>>2]|0;W=1<>2]=h|W;c[V>>2]=ga;c[ga+24>>2]=V;c[ga+12>>2]=ga;c[ga+8>>2]=ga;break}W=c[V>>2]|0;if((Ha|0)==31){Ja=0}else{Ja=25-(Ha>>>1)|0}j:do{if((c[W+4>>2]&-8|0)!=(aa|0)){V=aa<>>31<<2)+16|0;M=c[Ka>>2]|0;if((M|0)==0){break}if((c[M+4>>2]&-8|0)==(aa|0)){La=M;break j}else{V=V<<1;h=M}}if(Ka>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[Ka>>2]=ga;c[ga+24>>2]=h;c[ga+12>>2]=ga;c[ga+8>>2]=ga;break g}}else{La=W}}while(0);W=La+8|0;aa=c[W>>2]|0;Z=c[27672>>2]|0;if(La>>>0>>0){_a()}if(aa>>>0>>0){_a()}else{c[aa+12>>2]=ga;c[W>>2]=ga;c[ga+8>>2]=aa;c[ga+12>>2]=La;c[ga+24>>2]=0;break}}}else{aa=c[27672>>2]|0;if((aa|0)==0|da>>>0>>0){c[27672>>2]=da}c[28104>>2]=da;c[28108>>2]=ea;c[28116>>2]=0;c[27692>>2]=c[7032];c[27688>>2]=-1;aa=0;do{W=aa<<1;Z=27696+(W<<2)|0;c[27696+(W+3<<2)>>2]=Z;c[27696+(W+2<<2)>>2]=Z;aa=aa+1|0}while((aa|0)!=32);aa=da+8|0;if((aa&7|0)==0){Ma=0}else{Ma=0-aa&7}aa=ea+ -40-Ma|0;c[27680>>2]=da+Ma;c[27668>>2]=aa;c[da+(Ma+4)>>2]=aa|1;c[da+(ea+ -36)>>2]=40;c[27684>>2]=c[28144>>2]}}while(0);ea=c[27668>>2]|0;if(ea>>>0>B>>>0){da=ea-B|0;c[27668>>2]=da;ea=c[27680>>2]|0;c[27680>>2]=ea+B;c[ea+(B+4)>>2]=da|1;c[ea+4>>2]=B|3;p=ea+8|0;i=b;return p|0}}c[(Sa()|0)>>2]=12;p=0;i=b;return p|0}function hg(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0;b=i;if((a|0)==0){i=b;return}d=a+ -8|0;e=c[27672>>2]|0;if(d>>>0>>0){_a()}f=c[a+ -4>>2]|0;g=f&3;if((g|0)==1){_a()}h=f&-8;j=a+(h+ -8)|0;do{if((f&1|0)==0){k=c[d>>2]|0;if((g|0)==0){i=b;return}l=-8-k|0;m=a+l|0;n=k+h|0;if(m>>>0>>0){_a()}if((m|0)==(c[27676>>2]|0)){o=a+(h+ -4)|0;if((c[o>>2]&3|0)!=3){p=m;q=n;break}c[27664>>2]=n;c[o>>2]=c[o>>2]&-2;c[a+(l+4)>>2]=n|1;c[j>>2]=n;i=b;return}o=k>>>3;if(k>>>0<256){k=c[a+(l+8)>>2]|0;r=c[a+(l+12)>>2]|0;s=27696+(o<<1<<2)|0;if((k|0)!=(s|0)){if(k>>>0>>0){_a()}if((c[k+12>>2]|0)!=(m|0)){_a()}}if((r|0)==(k|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}s=r+8|0;if((c[s>>2]|0)==(m|0)){t=s}else{_a()}}else{t=r+8|0}c[k+12>>2]=r;c[t>>2]=k;p=m;q=n;break}k=c[a+(l+24)>>2]|0;r=c[a+(l+12)>>2]|0;do{if((r|0)==(m|0)){s=a+(l+20)|0;o=c[s>>2]|0;if((o|0)==0){u=a+(l+16)|0;v=c[u>>2]|0;if((v|0)==0){w=0;break}else{x=v;y=u}}else{x=o;y=s}while(1){s=x+20|0;o=c[s>>2]|0;if((o|0)!=0){x=o;y=s;continue}s=x+16|0;o=c[s>>2]|0;if((o|0)==0){break}else{x=o;y=s}}if(y>>>0>>0){_a()}else{c[y>>2]=0;w=x;break}}else{s=c[a+(l+8)>>2]|0;if(s>>>0>>0){_a()}o=s+12|0;if((c[o>>2]|0)!=(m|0)){_a()}u=r+8|0;if((c[u>>2]|0)==(m|0)){c[o>>2]=r;c[u>>2]=s;w=r;break}else{_a()}}}while(0);if((k|0)!=0){r=c[a+(l+28)>>2]|0;s=27960+(r<<2)|0;if((m|0)==(c[s>>2]|0)){c[s>>2]=w;if((w|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}r=k+16|0;if((c[r>>2]|0)==(m|0)){c[r>>2]=w}else{c[k+20>>2]=w}if((w|0)==0){p=m;q=n;break}}if(w>>>0<(c[27672>>2]|0)>>>0){_a()}c[w+24>>2]=k;r=c[a+(l+16)>>2]|0;do{if((r|0)!=0){if(r>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+16>>2]=r;c[r+24>>2]=w;break}}}while(0);r=c[a+(l+20)>>2]|0;if((r|0)!=0){if(r>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[w+20>>2]=r;c[r+24>>2]=w;p=m;q=n;break}}else{p=m;q=n}}else{p=m;q=n}}else{p=d;q=h}}while(0);if(!(p>>>0>>0)){_a()}d=a+(h+ -4)|0;w=c[d>>2]|0;if((w&1|0)==0){_a()}if((w&2|0)==0){if((j|0)==(c[27680>>2]|0)){e=(c[27668>>2]|0)+q|0;c[27668>>2]=e;c[27680>>2]=p;c[p+4>>2]=e|1;if((p|0)!=(c[27676>>2]|0)){i=b;return}c[27676>>2]=0;c[27664>>2]=0;i=b;return}if((j|0)==(c[27676>>2]|0)){e=(c[27664>>2]|0)+q|0;c[27664>>2]=e;c[27676>>2]=p;c[p+4>>2]=e|1;c[p+e>>2]=e;i=b;return}e=(w&-8)+q|0;x=w>>>3;do{if(!(w>>>0<256)){y=c[a+(h+16)>>2]|0;t=c[a+(h|4)>>2]|0;do{if((t|0)==(j|0)){g=a+(h+12)|0;f=c[g>>2]|0;if((f|0)==0){r=a+(h+8)|0;k=c[r>>2]|0;if((k|0)==0){z=0;break}else{A=k;B=r}}else{A=f;B=g}while(1){g=A+20|0;f=c[g>>2]|0;if((f|0)!=0){A=f;B=g;continue}g=A+16|0;f=c[g>>2]|0;if((f|0)==0){break}else{A=f;B=g}}if(B>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[B>>2]=0;z=A;break}}else{g=c[a+h>>2]|0;if(g>>>0<(c[27672>>2]|0)>>>0){_a()}f=g+12|0;if((c[f>>2]|0)!=(j|0)){_a()}r=t+8|0;if((c[r>>2]|0)==(j|0)){c[f>>2]=t;c[r>>2]=g;z=t;break}else{_a()}}}while(0);if((y|0)!=0){t=c[a+(h+20)>>2]|0;n=27960+(t<<2)|0;if((j|0)==(c[n>>2]|0)){c[n>>2]=z;if((z|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}t=y+16|0;if((c[t>>2]|0)==(j|0)){c[t>>2]=z}else{c[y+20>>2]=z}if((z|0)==0){break}}if(z>>>0<(c[27672>>2]|0)>>>0){_a()}c[z+24>>2]=y;t=c[a+(h+8)>>2]|0;do{if((t|0)!=0){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[z+16>>2]=t;c[t+24>>2]=z;break}}}while(0);t=c[a+(h+12)>>2]|0;if((t|0)!=0){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[z+20>>2]=t;c[t+24>>2]=z;break}}}}else{t=c[a+h>>2]|0;y=c[a+(h|4)>>2]|0;n=27696+(x<<1<<2)|0;if((t|0)!=(n|0)){if(t>>>0<(c[27672>>2]|0)>>>0){_a()}if((c[t+12>>2]|0)!=(j|0)){_a()}}if((y|0)==(t|0)){c[6914]=c[6914]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}n=y+8|0;if((c[n>>2]|0)==(j|0)){C=n}else{_a()}}else{C=y+8|0}c[t+12>>2]=y;c[C>>2]=t}}while(0);c[p+4>>2]=e|1;c[p+e>>2]=e;if((p|0)==(c[27676>>2]|0)){c[27664>>2]=e;i=b;return}else{D=e}}else{c[d>>2]=w&-2;c[p+4>>2]=q|1;c[p+q>>2]=q;D=q}q=D>>>3;if(D>>>0<256){w=q<<1;d=27696+(w<<2)|0;e=c[6914]|0;C=1<>2]|0;if(j>>>0<(c[27672>>2]|0)>>>0){_a()}else{E=q;F=j}}else{c[6914]=e|C;E=27696+(w+2<<2)|0;F=d}c[E>>2]=p;c[F+12>>2]=p;c[p+8>>2]=F;c[p+12>>2]=d;i=b;return}d=D>>>8;if((d|0)!=0){if(D>>>0>16777215){G=31}else{F=(d+1048320|0)>>>16&8;E=d<>>16&4;w=E<>>16&2;C=14-(d|F|E)+(w<>>15)|0;G=D>>>(C+7|0)&1|C<<1}}else{G=0}C=27960+(G<<2)|0;c[p+28>>2]=G;c[p+20>>2]=0;c[p+16>>2]=0;E=c[27660>>2]|0;w=1<>2]|0;if((G|0)==31){H=0}else{H=25-(G>>>1)|0}b:do{if((c[F+4>>2]&-8|0)!=(D|0)){d=D<>>31<<2)+16|0;j=c[I>>2]|0;if((j|0)==0){break}if((c[j+4>>2]&-8|0)==(D|0)){J=j;break b}else{d=d<<1;e=j}}if(I>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[I>>2]=p;c[p+24>>2]=e;c[p+12>>2]=p;c[p+8>>2]=p;break a}}else{J=F}}while(0);F=J+8|0;d=c[F>>2]|0;j=c[27672>>2]|0;if(J>>>0>>0){_a()}if(d>>>0>>0){_a()}else{c[d+12>>2]=p;c[F>>2]=p;c[p+8>>2]=d;c[p+12>>2]=J;c[p+24>>2]=0;break}}else{c[27660>>2]=E|w;c[C>>2]=p;c[p+24>>2]=C;c[p+12>>2]=p;c[p+8>>2]=p}}while(0);p=(c[27688>>2]|0)+ -1|0;c[27688>>2]=p;if((p|0)==0){K=28112|0}else{i=b;return}while(1){p=c[K>>2]|0;if((p|0)==0){break}else{K=p+8|0}}c[27688>>2]=-1;i=b;return}function ig(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;if((a|0)!=0){e=aa(b,a)|0;if((b|a)>>>0>65535){f=((e>>>0)/(a>>>0)|0|0)==(b|0)?e:-1}else{f=e}}else{f=0}e=gg(f)|0;if((e|0)==0){i=d;return e|0}if((c[e+ -4>>2]&3|0)==0){i=d;return e|0}Eg(e|0,0,f|0)|0;i=d;return e|0}function jg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;do{if((a|0)!=0){if(b>>>0>4294967231){c[(Sa()|0)>>2]=12;e=0;break}if(b>>>0<11){f=16}else{f=b+11&-8}g=kg(a+ -8|0,f)|0;if((g|0)!=0){e=g+8|0;break}g=gg(b)|0;if((g|0)==0){e=0}else{h=c[a+ -4>>2]|0;j=(h&-8)-((h&3|0)==0?8:4)|0;Kg(g|0,a|0,(j>>>0>>0?j:b)|0)|0;hg(a);e=g}}else{e=gg(b)|0}}while(0);i=d;return e|0}function kg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;d=i;e=a+4|0;f=c[e>>2]|0;g=f&-8;h=a+g|0;j=c[27672>>2]|0;if(a>>>0>>0){_a()}k=f&3;if(!((k|0)!=1&a>>>0>>0)){_a()}l=a+(g|4)|0;m=c[l>>2]|0;if((m&1|0)==0){_a()}if((k|0)==0){if(b>>>0<256){n=0;i=d;return n|0}if(!(g>>>0<(b+4|0)>>>0)?!((g-b|0)>>>0>c[28136>>2]<<1>>>0):0){n=a;i=d;return n|0}n=0;i=d;return n|0}if(!(g>>>0>>0)){k=g-b|0;if(!(k>>>0>15)){n=a;i=d;return n|0}c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=k|3;c[l>>2]=c[l>>2]|1;lg(a+b|0,k);n=a;i=d;return n|0}if((h|0)==(c[27680>>2]|0)){k=(c[27668>>2]|0)+g|0;if(!(k>>>0>b>>>0)){n=0;i=d;return n|0}l=k-b|0;c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=l|1;c[27680>>2]=a+b;c[27668>>2]=l;n=a;i=d;return n|0}if((h|0)==(c[27676>>2]|0)){l=(c[27664>>2]|0)+g|0;if(l>>>0>>0){n=0;i=d;return n|0}k=l-b|0;if(k>>>0>15){c[e>>2]=f&1|b|2;c[a+(b+4)>>2]=k|1;c[a+l>>2]=k;o=a+(l+4)|0;c[o>>2]=c[o>>2]&-2;p=a+b|0;q=k}else{c[e>>2]=f&1|l|2;f=a+(l+4)|0;c[f>>2]=c[f>>2]|1;p=0;q=0}c[27664>>2]=q;c[27676>>2]=p;n=a;i=d;return n|0}if((m&2|0)!=0){n=0;i=d;return n|0}p=(m&-8)+g|0;if(p>>>0>>0){n=0;i=d;return n|0}q=p-b|0;f=m>>>3;do{if(!(m>>>0<256)){l=c[a+(g+24)>>2]|0;k=c[a+(g+12)>>2]|0;do{if((k|0)==(h|0)){o=a+(g+20)|0;r=c[o>>2]|0;if((r|0)==0){s=a+(g+16)|0;t=c[s>>2]|0;if((t|0)==0){u=0;break}else{v=t;w=s}}else{v=r;w=o}while(1){o=v+20|0;r=c[o>>2]|0;if((r|0)!=0){v=r;w=o;continue}o=v+16|0;r=c[o>>2]|0;if((r|0)==0){break}else{v=r;w=o}}if(w>>>0>>0){_a()}else{c[w>>2]=0;u=v;break}}else{o=c[a+(g+8)>>2]|0;if(o>>>0>>0){_a()}r=o+12|0;if((c[r>>2]|0)!=(h|0)){_a()}s=k+8|0;if((c[s>>2]|0)==(h|0)){c[r>>2]=k;c[s>>2]=o;u=k;break}else{_a()}}}while(0);if((l|0)!=0){k=c[a+(g+28)>>2]|0;o=27960+(k<<2)|0;if((h|0)==(c[o>>2]|0)){c[o>>2]=u;if((u|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}k=l+16|0;if((c[k>>2]|0)==(h|0)){c[k>>2]=u}else{c[l+20>>2]=u}if((u|0)==0){break}}if(u>>>0<(c[27672>>2]|0)>>>0){_a()}c[u+24>>2]=l;k=c[a+(g+16)>>2]|0;do{if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+16>>2]=k;c[k+24>>2]=u;break}}}while(0);k=c[a+(g+20)>>2]|0;if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+20>>2]=k;c[k+24>>2]=u;break}}}}else{k=c[a+(g+8)>>2]|0;l=c[a+(g+12)>>2]|0;o=27696+(f<<1<<2)|0;if((k|0)!=(o|0)){if(k>>>0>>0){_a()}if((c[k+12>>2]|0)!=(h|0)){_a()}}if((l|0)==(k|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}o=l+8|0;if((c[o>>2]|0)==(h|0)){x=o}else{_a()}}else{x=l+8|0}c[k+12>>2]=l;c[x>>2]=k}}while(0);if(q>>>0<16){c[e>>2]=p|c[e>>2]&1|2;x=a+(p|4)|0;c[x>>2]=c[x>>2]|1;n=a;i=d;return n|0}else{c[e>>2]=c[e>>2]&1|b|2;c[a+(b+4)>>2]=q|3;e=a+(p|4)|0;c[e>>2]=c[e>>2]|1;lg(a+b|0,q);n=a;i=d;return n|0}return 0}function lg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;d=i;e=a+b|0;f=c[a+4>>2]|0;do{if((f&1|0)==0){g=c[a>>2]|0;if((f&3|0)==0){i=d;return}h=a+(0-g)|0;j=g+b|0;k=c[27672>>2]|0;if(h>>>0>>0){_a()}if((h|0)==(c[27676>>2]|0)){l=a+(b+4)|0;if((c[l>>2]&3|0)!=3){m=h;n=j;break}c[27664>>2]=j;c[l>>2]=c[l>>2]&-2;c[a+(4-g)>>2]=j|1;c[e>>2]=j;i=d;return}l=g>>>3;if(g>>>0<256){o=c[a+(8-g)>>2]|0;p=c[a+(12-g)>>2]|0;q=27696+(l<<1<<2)|0;if((o|0)!=(q|0)){if(o>>>0>>0){_a()}if((c[o+12>>2]|0)!=(h|0)){_a()}}if((p|0)==(o|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}q=p+8|0;if((c[q>>2]|0)==(h|0)){r=q}else{_a()}}else{r=p+8|0}c[o+12>>2]=p;c[r>>2]=o;m=h;n=j;break}o=c[a+(24-g)>>2]|0;p=c[a+(12-g)>>2]|0;do{if((p|0)==(h|0)){q=16-g|0;l=a+(q+4)|0;s=c[l>>2]|0;if((s|0)==0){t=a+q|0;q=c[t>>2]|0;if((q|0)==0){u=0;break}else{v=q;w=t}}else{v=s;w=l}while(1){l=v+20|0;s=c[l>>2]|0;if((s|0)!=0){v=s;w=l;continue}l=v+16|0;s=c[l>>2]|0;if((s|0)==0){break}else{v=s;w=l}}if(w>>>0>>0){_a()}else{c[w>>2]=0;u=v;break}}else{l=c[a+(8-g)>>2]|0;if(l>>>0>>0){_a()}s=l+12|0;if((c[s>>2]|0)!=(h|0)){_a()}t=p+8|0;if((c[t>>2]|0)==(h|0)){c[s>>2]=p;c[t>>2]=l;u=p;break}else{_a()}}}while(0);if((o|0)!=0){p=c[a+(28-g)>>2]|0;k=27960+(p<<2)|0;if((h|0)==(c[k>>2]|0)){c[k>>2]=u;if((u|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}p=o+16|0;if((c[p>>2]|0)==(h|0)){c[p>>2]=u}else{c[o+20>>2]=u}if((u|0)==0){m=h;n=j;break}}if(u>>>0<(c[27672>>2]|0)>>>0){_a()}c[u+24>>2]=o;p=16-g|0;k=c[a+p>>2]|0;do{if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+16>>2]=k;c[k+24>>2]=u;break}}}while(0);k=c[a+(p+4)>>2]|0;if((k|0)!=0){if(k>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[u+20>>2]=k;c[k+24>>2]=u;m=h;n=j;break}}else{m=h;n=j}}else{m=h;n=j}}else{m=a;n=b}}while(0);u=c[27672>>2]|0;if(e>>>0>>0){_a()}v=a+(b+4)|0;w=c[v>>2]|0;if((w&2|0)==0){if((e|0)==(c[27680>>2]|0)){r=(c[27668>>2]|0)+n|0;c[27668>>2]=r;c[27680>>2]=m;c[m+4>>2]=r|1;if((m|0)!=(c[27676>>2]|0)){i=d;return}c[27676>>2]=0;c[27664>>2]=0;i=d;return}if((e|0)==(c[27676>>2]|0)){r=(c[27664>>2]|0)+n|0;c[27664>>2]=r;c[27676>>2]=m;c[m+4>>2]=r|1;c[m+r>>2]=r;i=d;return}r=(w&-8)+n|0;f=w>>>3;do{if(!(w>>>0<256)){k=c[a+(b+24)>>2]|0;g=c[a+(b+12)>>2]|0;do{if((g|0)==(e|0)){o=a+(b+20)|0;l=c[o>>2]|0;if((l|0)==0){t=a+(b+16)|0;s=c[t>>2]|0;if((s|0)==0){x=0;break}else{y=s;z=t}}else{y=l;z=o}while(1){o=y+20|0;l=c[o>>2]|0;if((l|0)!=0){y=l;z=o;continue}o=y+16|0;l=c[o>>2]|0;if((l|0)==0){break}else{y=l;z=o}}if(z>>>0>>0){_a()}else{c[z>>2]=0;x=y;break}}else{o=c[a+(b+8)>>2]|0;if(o>>>0>>0){_a()}l=o+12|0;if((c[l>>2]|0)!=(e|0)){_a()}t=g+8|0;if((c[t>>2]|0)==(e|0)){c[l>>2]=g;c[t>>2]=o;x=g;break}else{_a()}}}while(0);if((k|0)!=0){g=c[a+(b+28)>>2]|0;j=27960+(g<<2)|0;if((e|0)==(c[j>>2]|0)){c[j>>2]=x;if((x|0)==0){c[27660>>2]=c[27660>>2]&~(1<>>0<(c[27672>>2]|0)>>>0){_a()}g=k+16|0;if((c[g>>2]|0)==(e|0)){c[g>>2]=x}else{c[k+20>>2]=x}if((x|0)==0){break}}if(x>>>0<(c[27672>>2]|0)>>>0){_a()}c[x+24>>2]=k;g=c[a+(b+16)>>2]|0;do{if((g|0)!=0){if(g>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[x+16>>2]=g;c[g+24>>2]=x;break}}}while(0);g=c[a+(b+20)>>2]|0;if((g|0)!=0){if(g>>>0<(c[27672>>2]|0)>>>0){_a()}else{c[x+20>>2]=g;c[g+24>>2]=x;break}}}}else{g=c[a+(b+8)>>2]|0;k=c[a+(b+12)>>2]|0;j=27696+(f<<1<<2)|0;if((g|0)!=(j|0)){if(g>>>0>>0){_a()}if((c[g+12>>2]|0)!=(e|0)){_a()}}if((k|0)==(g|0)){c[6914]=c[6914]&~(1<>>0>>0){_a()}j=k+8|0;if((c[j>>2]|0)==(e|0)){A=j}else{_a()}}else{A=k+8|0}c[g+12>>2]=k;c[A>>2]=g}}while(0);c[m+4>>2]=r|1;c[m+r>>2]=r;if((m|0)==(c[27676>>2]|0)){c[27664>>2]=r;i=d;return}else{B=r}}else{c[v>>2]=w&-2;c[m+4>>2]=n|1;c[m+n>>2]=n;B=n}n=B>>>3;if(B>>>0<256){w=n<<1;v=27696+(w<<2)|0;r=c[6914]|0;A=1<>2]|0;if(e>>>0<(c[27672>>2]|0)>>>0){_a()}else{C=n;D=e}}else{c[6914]=r|A;C=27696+(w+2<<2)|0;D=v}c[C>>2]=m;c[D+12>>2]=m;c[m+8>>2]=D;c[m+12>>2]=v;i=d;return}v=B>>>8;if((v|0)!=0){if(B>>>0>16777215){E=31}else{D=(v+1048320|0)>>>16&8;C=v<>>16&4;w=C<>>16&2;A=14-(v|D|C)+(w<>>15)|0;E=B>>>(A+7|0)&1|A<<1}}else{E=0}A=27960+(E<<2)|0;c[m+28>>2]=E;c[m+20>>2]=0;c[m+16>>2]=0;C=c[27660>>2]|0;w=1<>2]=C|w;c[A>>2]=m;c[m+24>>2]=A;c[m+12>>2]=m;c[m+8>>2]=m;i=d;return}w=c[A>>2]|0;if((E|0)==31){F=0}else{F=25-(E>>>1)|0}a:do{if((c[w+4>>2]&-8|0)==(B|0)){G=w}else{E=B<>>31<<2)+16|0;C=c[H>>2]|0;if((C|0)==0){break}if((c[C+4>>2]&-8|0)==(B|0)){G=C;break a}else{E=E<<1;A=C}}if(H>>>0<(c[27672>>2]|0)>>>0){_a()}c[H>>2]=m;c[m+24>>2]=A;c[m+12>>2]=m;c[m+8>>2]=m;i=d;return}}while(0);H=G+8|0;B=c[H>>2]|0;w=c[27672>>2]|0;if(G>>>0>>0){_a()}if(B>>>0>>0){_a()}c[B+12>>2]=m;c[H>>2]=m;c[m+8>>2]=B;c[m+12>>2]=G;c[m+24>>2]=0;i=d;return}function mg(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0.0,Q=0,R=0.0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,ba=0.0,ca=0,da=0.0,ea=0,fa=0.0,ga=0,ha=0.0,ia=0,ja=0.0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,ra=0,sa=0.0,ta=0,ua=0.0,va=0,wa=0,xa=0,ya=0,za=0.0,Aa=0,Ba=0.0,Ca=0.0,Da=0,Ea=0.0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Ta=0,Ua=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0.0,sc=0,tc=0,uc=0.0,vc=0.0,wc=0.0,xc=0.0,yc=0.0,zc=0.0,Ac=0,Bc=0,Cc=0.0,Dc=0,Ec=0.0,Fc=0,Gc=0,Hc=0,Ic=0;g=i;i=i+512|0;h=g;if((e|0)==1){j=53;k=-1074}else if((e|0)==0){j=24;k=-149}else if((e|0)==2){j=53;k=-1074}else{l=0.0;i=g;return+l}e=b+4|0;m=b+100|0;do{n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;o=d[n]|0}else{o=pg(b)|0}}while((fb(o|0)|0)!=0);do{if((o|0)==43|(o|0)==45){n=1-(((o|0)==45)<<1)|0;p=c[e>>2]|0;if(p>>>0<(c[m>>2]|0)>>>0){c[e>>2]=p+1;q=d[p]|0;r=n;break}else{q=pg(b)|0;r=n;break}}else{q=o;r=1}}while(0);o=q;q=0;while(1){if((o|32|0)!=(a[28152+q|0]|0)){s=o;v=q;break}do{if(q>>>0<7){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;w=d[n]|0;break}else{w=pg(b)|0;break}}else{w=o}}while(0);n=q+1|0;if(n>>>0<8){o=w;q=n}else{s=w;v=n;break}}do{if((v|0)==3){x=23}else if((v|0)!=8){w=(f|0)==0;if(!(v>>>0<4|w)){if((v|0)==8){break}else{x=23;break}}a:do{if((v|0)==0){q=s;o=0;while(1){if((q|32|0)!=(a[28168+o|0]|0)){y=q;z=o;break a}do{if(o>>>0<2){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;A=d[n]|0;break}else{A=pg(b)|0;break}}else{A=q}}while(0);n=o+1|0;if(n>>>0<3){q=A;o=n}else{y=A;z=n;break}}}else{y=s;z=v}}while(0);if((z|0)==0){do{if((y|0)==48){o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;B=d[o]|0}else{B=pg(b)|0}if((B|32|0)!=120){if((c[m>>2]|0)==0){C=48;break}c[e>>2]=(c[e>>2]|0)+ -1;C=48;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;D=d[o]|0;F=0}else{D=pg(b)|0;F=0}while(1){if((D|0)==46){x=70;break}else if((D|0)!=48){G=0;H=0;I=0;J=0;K=D;L=F;M=0;N=0;O=1.0;Q=0;R=0.0;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;D=d[o]|0;F=1;continue}else{D=pg(b)|0;F=1;continue}}b:do{if((x|0)==70){o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;S=d[o]|0}else{S=pg(b)|0}if((S|0)==48){o=-1;q=-1;while(1){n=c[e>>2]|0;if(n>>>0<(c[m>>2]|0)>>>0){c[e>>2]=n+1;T=d[n]|0}else{T=pg(b)|0}if((T|0)!=48){G=0;H=0;I=o;J=q;K=T;L=1;M=1;N=0;O=1.0;Q=0;R=0.0;break b}n=Ig(o|0,q|0,-1,-1)|0;o=n;q=E}}else{G=0;H=0;I=0;J=0;K=S;L=F;M=1;N=0;O=1.0;Q=0;R=0.0}}}while(0);c:while(1){q=K+ -48|0;do{if(!(q>>>0<10)){o=K|32;n=(K|0)==46;if(!((o+ -97|0)>>>0<6|n)){U=K;break c}if(n){if((M|0)==0){V=H;W=G;X=H;Y=G;Z=L;_=1;$=N;ba=O;ca=Q;da=R;break}else{U=46;break c}}else{ea=(K|0)>57?o+ -87|0:q;x=84;break}}else{ea=q;x=84}}while(0);if((x|0)==84){x=0;do{if(!((G|0)<0|(G|0)==0&H>>>0<8)){if((G|0)<0|(G|0)==0&H>>>0<14){fa=O*.0625;ga=N;ha=fa;ia=Q;ja=R+fa*+(ea|0);break}if((ea|0)!=0&(N|0)==0){ga=1;ha=O;ia=Q;ja=R+O*.5}else{ga=N;ha=O;ia=Q;ja=R}}else{ga=N;ha=O;ia=ea+(Q<<4)|0;ja=R}}while(0);q=Ig(H|0,G|0,1,0)|0;V=I;W=J;X=q;Y=E;Z=1;_=M;$=ga;ba=ha;ca=ia;da=ja}q=c[e>>2]|0;if(q>>>0<(c[m>>2]|0)>>>0){c[e>>2]=q+1;G=Y;H=X;I=V;J=W;K=d[q]|0;L=Z;M=_;N=$;O=ba;Q=ca;R=da;continue}else{G=Y;H=X;I=V;J=W;K=pg(b)|0;L=Z;M=_;N=$;O=ba;Q=ca;R=da;continue}}if((L|0)==0){q=(c[m>>2]|0)==0;if(!q){c[e>>2]=(c[e>>2]|0)+ -1}if(!w){if(!q?(q=c[e>>2]|0,c[e>>2]=q+ -1,(M|0)!=0):0){c[e>>2]=q+ -2}}else{og(b,0)}l=+(r|0)*0.0;i=g;return+l}q=(M|0)==0;o=q?H:I;n=q?G:J;if((G|0)<0|(G|0)==0&H>>>0<8){q=H;p=G;ka=Q;while(1){la=ka<<4;ma=Ig(q|0,p|0,1,0)|0;na=E;if((na|0)<0|(na|0)==0&ma>>>0<8){q=ma;p=na;ka=la}else{oa=la;break}}}else{oa=Q}do{if((U|32|0)==112){ka=ng(b,f)|0;p=E;if((ka|0)==0&(p|0)==-2147483648){if(w){og(b,0);l=0.0;i=g;return+l}else{if((c[m>>2]|0)==0){pa=0;ra=0;break}c[e>>2]=(c[e>>2]|0)+ -1;pa=0;ra=0;break}}else{pa=ka;ra=p}}else{if((c[m>>2]|0)==0){pa=0;ra=0}else{c[e>>2]=(c[e>>2]|0)+ -1;pa=0;ra=0}}}while(0);p=Gg(o|0,n|0,2)|0;ka=Ig(p|0,E|0,-32,-1)|0;p=Ig(ka|0,E|0,pa|0,ra|0)|0;ka=E;if((oa|0)==0){l=+(r|0)*0.0;i=g;return+l}if((ka|0)>0|(ka|0)==0&p>>>0>(0-k|0)>>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+l}q=k+ -106|0;la=((q|0)<0)<<31>>31;if((ka|0)<(la|0)|(ka|0)==(la|0)&p>>>0>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+l}if((oa|0)>-1){q=p;la=ka;na=oa;fa=R;while(1){ma=na<<1;if(!(fa>=.5)){sa=fa;ta=ma}else{sa=fa+-1.0;ta=ma|1}ua=fa+sa;ma=Ig(q|0,la|0,-1,-1)|0;va=E;if((ta|0)>-1){q=ma;la=va;na=ta;fa=ua}else{wa=ma;xa=va;ya=ta;za=ua;break}}}else{wa=p;xa=ka;ya=oa;za=R}na=Cg(32,0,k|0,((k|0)<0)<<31>>31|0)|0;la=Ig(wa|0,xa|0,na|0,E|0)|0;na=E;if(0>(na|0)|0==(na|0)&j>>>0>la>>>0){Aa=(la|0)<0?0:la}else{Aa=j}if((Aa|0)<53){fa=+(r|0);ua=+Va(+(+qg(1.0,84-Aa|0)),+fa);if((Aa|0)<32&za!=0.0){la=ya&1;Ba=fa;Ca=ua;Da=(la^1)+ya|0;Ea=(la|0)==0?0.0:za}else{Ba=fa;Ca=ua;Da=ya;Ea=za}}else{Ba=+(r|0);Ca=0.0;Da=ya;Ea=za}ua=Ba*Ea+(Ca+Ba*+(Da>>>0))-Ca;if(!(ua!=0.0)){c[(Sa()|0)>>2]=34}l=+rg(ua,wa);i=g;return+l}else{C=y}}while(0);la=k+j|0;na=0-la|0;q=C;n=0;while(1){if((q|0)==46){x=139;break}else if((q|0)!=48){Fa=q;Ga=0;Ha=0;Ia=n;Ja=0;break}o=c[e>>2]|0;if(o>>>0<(c[m>>2]|0)>>>0){c[e>>2]=o+1;q=d[o]|0;n=1;continue}else{q=pg(b)|0;n=1;continue}}d:do{if((x|0)==139){q=c[e>>2]|0;if(q>>>0<(c[m>>2]|0)>>>0){c[e>>2]=q+1;Ka=d[q]|0}else{Ka=pg(b)|0}if((Ka|0)==48){q=-1;o=-1;while(1){va=c[e>>2]|0;if(va>>>0<(c[m>>2]|0)>>>0){c[e>>2]=va+1;La=d[va]|0}else{La=pg(b)|0}if((La|0)!=48){Fa=La;Ga=q;Ha=o;Ia=1;Ja=1;break d}va=Ig(q|0,o|0,-1,-1)|0;q=va;o=E}}else{Fa=Ka;Ga=0;Ha=0;Ia=n;Ja=1}}}while(0);c[h>>2]=0;n=Fa+ -48|0;o=(Fa|0)==46;e:do{if(n>>>0<10|o){q=h+496|0;ka=Fa;p=0;va=0;ma=o;Ma=n;Na=Ga;Oa=Ha;Pa=Ia;Qa=Ja;Ra=0;Ta=0;Ua=0;while(1){do{if(ma){if((Qa|0)==0){Wa=p;Xa=va;Ya=p;Za=va;_a=Pa;$a=1;ab=Ra;bb=Ta;cb=Ua}else{db=ka;eb=Na;gb=Oa;hb=p;ib=va;jb=Pa;kb=Ra;lb=Ta;mb=Ua;break e}}else{nb=Ig(p|0,va|0,1,0)|0;ob=E;pb=(ka|0)!=48;if((Ta|0)>=125){if(!pb){Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=Pa;$a=Qa;ab=Ra;bb=Ta;cb=Ua;break}c[q>>2]=c[q>>2]|1;Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=Pa;$a=Qa;ab=Ra;bb=Ta;cb=Ua;break}qb=h+(Ta<<2)|0;if((Ra|0)==0){rb=Ma}else{rb=ka+ -48+((c[qb>>2]|0)*10|0)|0}c[qb>>2]=rb;qb=Ra+1|0;sb=(qb|0)==9;Wa=Na;Xa=Oa;Ya=nb;Za=ob;_a=1;$a=Qa;ab=sb?0:qb;bb=(sb&1)+Ta|0;cb=pb?nb:Ua}}while(0);nb=c[e>>2]|0;if(nb>>>0<(c[m>>2]|0)>>>0){c[e>>2]=nb+1;tb=d[nb]|0}else{tb=pg(b)|0}nb=tb+ -48|0;pb=(tb|0)==46;if(nb>>>0<10|pb){ka=tb;p=Ya;va=Za;ma=pb;Ma=nb;Na=Wa;Oa=Xa;Pa=_a;Qa=$a;Ra=ab;Ta=bb;Ua=cb}else{ub=tb;vb=Ya;wb=Wa;xb=Za;yb=Xa;zb=_a;Ab=$a;Bb=ab;Cb=bb;Db=cb;x=162;break}}}else{ub=Fa;vb=0;wb=Ga;xb=0;yb=Ha;zb=Ia;Ab=Ja;Bb=0;Cb=0;Db=0;x=162}}while(0);if((x|0)==162){n=(Ab|0)==0;db=ub;eb=n?vb:wb;gb=n?xb:yb;hb=vb;ib=xb;jb=zb;kb=Bb;lb=Cb;mb=Db}n=(jb|0)!=0;if(n?(db|32|0)==101:0){o=ng(b,f)|0;Ua=E;do{if((o|0)==0&(Ua|0)==-2147483648){if(w){og(b,0);l=0.0;i=g;return+l}else{if((c[m>>2]|0)==0){Eb=0;Fb=0;break}c[e>>2]=(c[e>>2]|0)+ -1;Eb=0;Fb=0;break}}else{Eb=o;Fb=Ua}}while(0);Ua=Ig(Eb|0,Fb|0,eb|0,gb|0)|0;Gb=Ua;Hb=E}else{if((db|0)>-1?(c[m>>2]|0)!=0:0){c[e>>2]=(c[e>>2]|0)+ -1;Gb=eb;Hb=gb}else{Gb=eb;Hb=gb}}if(!n){c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}Ua=c[h>>2]|0;if((Ua|0)==0){l=+(r|0)*0.0;i=g;return+l}do{if((Gb|0)==(hb|0)&(Hb|0)==(ib|0)&((ib|0)<0|(ib|0)==0&hb>>>0<10)){if(!(j>>>0>30)?(Ua>>>j|0)!=0:0){break}l=+(r|0)*+(Ua>>>0);i=g;return+l}}while(0);Ua=(k|0)/-2|0;n=((Ua|0)<0)<<31>>31;if((Hb|0)>(n|0)|(Hb|0)==(n|0)&Gb>>>0>Ua>>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*1.7976931348623157e+308*1.7976931348623157e+308;i=g;return+l}Ua=k+ -106|0;n=((Ua|0)<0)<<31>>31;if((Hb|0)<(n|0)|(Hb|0)==(n|0)&Gb>>>0>>0){c[(Sa()|0)>>2]=34;l=+(r|0)*2.2250738585072014e-308*2.2250738585072014e-308;i=g;return+l}if((kb|0)==0){Ib=lb}else{if((kb|0)<9){Ua=h+(lb<<2)|0;n=c[Ua>>2]|0;o=kb;do{n=n*10|0;o=o+1|0}while((o|0)!=9);c[Ua>>2]=n}Ib=lb+1|0}do{if((mb|0)<9?(mb|0)<=(Gb|0)&(Gb|0)<18:0){if((Gb|0)==9){l=+(r|0)*+((c[h>>2]|0)>>>0);i=g;return+l}if((Gb|0)<9){l=+(r|0)*+((c[h>>2]|0)>>>0)/+(c[28184+(8-Gb<<2)>>2]|0);i=g;return+l}o=j+27+(aa(Gb,-3)|0)|0;Ta=c[h>>2]|0;if((o|0)<=30?(Ta>>>o|0)!=0:0){break}l=+(r|0)*+(Ta>>>0)*+(c[28184+(Gb+ -10<<2)>>2]|0);i=g;return+l}}while(0);n=(Gb|0)%9|0;if((n|0)==0){Jb=0;Kb=0;Lb=Gb;Mb=Ib}else{Ua=(Gb|0)>-1?n:n+9|0;n=c[28184+(8-Ua<<2)>>2]|0;if((Ib|0)!=0){Ta=1e9/(n|0)|0;o=0;Ra=0;Qa=0;Pa=Gb;while(1){Oa=h+(Qa<<2)|0;Na=c[Oa>>2]|0;Ma=((Na>>>0)/(n>>>0)|0)+Ra|0;c[Oa>>2]=Ma;Nb=aa((Na>>>0)%(n>>>0)|0,Ta)|0;Na=Qa+1|0;if((Qa|0)==(o|0)&(Ma|0)==0){Ob=Na&127;Pb=Pa+ -9|0}else{Ob=o;Pb=Pa}if((Na|0)==(Ib|0)){break}else{o=Ob;Ra=Nb;Qa=Na;Pa=Pb}}if((Nb|0)==0){Qb=Ob;Rb=Pb;Sb=Ib}else{c[h+(Ib<<2)>>2]=Nb;Qb=Ob;Rb=Pb;Sb=Ib+1|0}}else{Qb=0;Rb=Gb;Sb=0}Jb=Qb;Kb=0;Lb=9-Ua+Rb|0;Mb=Sb}f:while(1){Pa=h+(Jb<<2)|0;if((Lb|0)<18){Qa=Kb;Ra=Mb;while(1){o=0;Ta=Ra+127|0;n=Ra;while(1){Na=Ta&127;Ma=h+(Na<<2)|0;Oa=Gg(c[Ma>>2]|0,0,29)|0;ma=Ig(Oa|0,E|0,o|0,0)|0;Oa=E;if(Oa>>>0>0|(Oa|0)==0&ma>>>0>1e9){va=Ug(ma|0,Oa|0,1e9,0)|0;p=Vg(ma|0,Oa|0,1e9,0)|0;Tb=p;Ub=va}else{Tb=ma;Ub=0}c[Ma>>2]=Tb;Ma=(Na|0)==(Jb|0);if((Na|0)!=(n+127&127|0)|Ma){Vb=n}else{Vb=(Tb|0)==0?Na:n}if(Ma){break}else{o=Ub;Ta=Na+ -1|0;n=Vb}}n=Qa+ -29|0;if((Ub|0)==0){Qa=n;Ra=Vb}else{Wb=n;Xb=Ub;Yb=Vb;break}}}else{if((Lb|0)==18){Zb=Kb;_b=Mb}else{$b=Jb;ac=Kb;bc=Lb;cc=Mb;break}while(1){if(!((c[Pa>>2]|0)>>>0<9007199)){$b=Jb;ac=Zb;bc=18;cc=_b;break f}Ra=0;Qa=_b+127|0;n=_b;while(1){Ta=Qa&127;o=h+(Ta<<2)|0;Na=Gg(c[o>>2]|0,0,29)|0;Ma=Ig(Na|0,E|0,Ra|0,0)|0;Na=E;if(Na>>>0>0|(Na|0)==0&Ma>>>0>1e9){ma=Ug(Ma|0,Na|0,1e9,0)|0;va=Vg(Ma|0,Na|0,1e9,0)|0;dc=va;ec=ma}else{dc=Ma;ec=0}c[o>>2]=dc;o=(Ta|0)==(Jb|0);if((Ta|0)!=(n+127&127|0)|o){fc=n}else{fc=(dc|0)==0?Ta:n}if(o){break}else{Ra=ec;Qa=Ta+ -1|0;n=fc}}n=Zb+ -29|0;if((ec|0)==0){Zb=n;_b=fc}else{Wb=n;Xb=ec;Yb=fc;break}}}Pa=Jb+127&127;if((Pa|0)==(Yb|0)){n=Yb+127&127;Qa=h+((Yb+126&127)<<2)|0;c[Qa>>2]=c[Qa>>2]|c[h+(n<<2)>>2];gc=n}else{gc=Yb}c[h+(Pa<<2)>>2]=Xb;Jb=Pa;Kb=Wb;Lb=Lb+9|0;Mb=gc}g:while(1){hc=cc+1&127;Ua=h+((cc+127&127)<<2)|0;Pa=$b;n=ac;Qa=bc;while(1){Ra=(Qa|0)==18;Ta=(Qa|0)>27?9:1;ic=Pa;jc=n;while(1){o=0;while(1){Ma=o+ic&127;if((Ma|0)==(cc|0)){kc=2;break}ma=c[h+(Ma<<2)>>2]|0;Ma=c[28176+(o<<2)>>2]|0;if(ma>>>0>>0){kc=2;break}va=o+1|0;if(ma>>>0>Ma>>>0){kc=o;break}if((va|0)<2){o=va}else{kc=va;break}}if((kc|0)==2&Ra){break g}lc=Ta+jc|0;if((ic|0)==(cc|0)){ic=cc;jc=lc}else{break}}Ra=(1<>>Ta;mc=ic;nc=0;va=ic;oc=Qa;do{Ma=h+(va<<2)|0;ma=c[Ma>>2]|0;Na=(ma>>>Ta)+nc|0;c[Ma>>2]=Na;nc=aa(ma&Ra,o)|0;ma=(va|0)==(mc|0)&(Na|0)==0;va=va+1&127;oc=ma?oc+ -9|0:oc;mc=ma?va:mc}while((va|0)!=(cc|0));if((nc|0)==0){Pa=mc;n=lc;Qa=oc;continue}if((hc|0)!=(mc|0)){break}c[Ua>>2]=c[Ua>>2]|1;Pa=mc;n=lc;Qa=oc}c[h+(cc<<2)>>2]=nc;$b=mc;ac=lc;bc=oc;cc=hc}Qa=ic&127;if((Qa|0)==(cc|0)){c[h+(hc+ -1<<2)>>2]=0;pc=hc}else{pc=cc}ua=+((c[h+(Qa<<2)>>2]|0)>>>0);Qa=ic+1&127;if((Qa|0)==(pc|0)){n=pc+1&127;c[h+(n+ -1<<2)>>2]=0;qc=n}else{qc=pc}fa=+(r|0);rc=fa*(ua*1.0e9+ +((c[h+(Qa<<2)>>2]|0)>>>0));Qa=jc+53|0;n=Qa-k|0;if((n|0)<(j|0)){sc=(n|0)<0?0:n;tc=1}else{sc=j;tc=0}if((sc|0)<53){ua=+Va(+(+qg(1.0,105-sc|0)),+rc);uc=+qa(+rc,+(+qg(1.0,53-sc|0)));vc=ua;wc=uc;xc=ua+(rc-uc)}else{vc=0.0;wc=0.0;xc=rc}Pa=ic+2&127;if((Pa|0)!=(qc|0)){Ua=c[h+(Pa<<2)>>2]|0;do{if(!(Ua>>>0<5e8)){if(Ua>>>0>5e8){yc=fa*.75+wc;break}if((ic+3&127|0)==(qc|0)){yc=fa*.5+wc;break}else{yc=fa*.75+wc;break}}else{if((Ua|0)==0?(ic+3&127|0)==(qc|0):0){yc=wc;break}yc=fa*.25+wc}}while(0);if((53-sc|0)>1?!(+qa(+yc,1.0)!=0.0):0){zc=yc+1.0}else{zc=yc}}else{zc=wc}fa=xc+zc-vc;do{if((Qa&2147483647|0)>(-2-la|0)){if(!(+P(+fa)>=9007199254740992.0)){Ac=tc;Bc=jc;Cc=fa}else{Ac=(tc|0)!=0&(sc|0)==(n|0)?0:tc;Bc=jc+1|0;Cc=fa*.5}if((Bc+50|0)<=(na|0)?!((Ac|0)!=0&zc!=0.0):0){Dc=Bc;Ec=Cc;break}c[(Sa()|0)>>2]=34;Dc=Bc;Ec=Cc}else{Dc=jc;Ec=fa}}while(0);l=+rg(Ec,Dc);i=g;return+l}else if((z|0)==3){na=c[e>>2]|0;if(na>>>0<(c[m>>2]|0)>>>0){c[e>>2]=na+1;Fc=d[na]|0}else{Fc=pg(b)|0}if((Fc|0)==40){Gc=1}else{if((c[m>>2]|0)==0){l=t;i=g;return+l}c[e>>2]=(c[e>>2]|0)+ -1;l=t;i=g;return+l}while(1){na=c[e>>2]|0;if(na>>>0<(c[m>>2]|0)>>>0){c[e>>2]=na+1;Hc=d[na]|0}else{Hc=pg(b)|0}if(!((Hc+ -48|0)>>>0<10|(Hc+ -65|0)>>>0<26)?!((Hc+ -97|0)>>>0<26|(Hc|0)==95):0){break}Gc=Gc+1|0}if((Hc|0)==41){l=t;i=g;return+l}na=(c[m>>2]|0)==0;if(!na){c[e>>2]=(c[e>>2]|0)+ -1}if(w){c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}if((Gc|0)==0|na){l=t;i=g;return+l}else{Ic=Gc}while(1){na=Ic+ -1|0;c[e>>2]=(c[e>>2]|0)+ -1;if((na|0)==0){l=t;break}else{Ic=na}}i=g;return+l}else{if((c[m>>2]|0)!=0){c[e>>2]=(c[e>>2]|0)+ -1}c[(Sa()|0)>>2]=22;og(b,0);l=0.0;i=g;return+l}}}while(0);if((x|0)==23){x=(c[m>>2]|0)==0;if(!x){c[e>>2]=(c[e>>2]|0)+ -1}if(!(v>>>0<4|(f|0)==0|x)){x=v;do{c[e>>2]=(c[e>>2]|0)+ -1;x=x+ -1|0}while(x>>>0>3)}}l=+(r|0)*u;i=g;return+l}function ng(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;e=i;f=a+4|0;g=c[f>>2]|0;h=a+100|0;if(g>>>0<(c[h>>2]|0)>>>0){c[f>>2]=g+1;j=d[g]|0}else{j=pg(a)|0}if((j|0)==43|(j|0)==45){g=(j|0)==45|0;k=c[f>>2]|0;if(k>>>0<(c[h>>2]|0)>>>0){c[f>>2]=k+1;l=d[k]|0}else{l=pg(a)|0}if(!((l+ -48|0)>>>0<10|(b|0)==0)?(c[h>>2]|0)!=0:0){c[f>>2]=(c[f>>2]|0)+ -1;m=l;n=g}else{m=l;n=g}}else{m=j;n=0}if((m+ -48|0)>>>0>9){if((c[h>>2]|0)==0){o=-2147483648;p=0;E=o;i=e;return p|0}c[f>>2]=(c[f>>2]|0)+ -1;o=-2147483648;p=0;E=o;i=e;return p|0}else{q=m;r=0}while(1){s=q+ -48+r|0;m=c[f>>2]|0;if(m>>>0<(c[h>>2]|0)>>>0){c[f>>2]=m+1;t=d[m]|0}else{t=pg(a)|0}if(!((t+ -48|0)>>>0<10&(s|0)<214748364)){break}q=t;r=s*10|0}r=((s|0)<0)<<31>>31;if((t+ -48|0)>>>0<10){q=s;m=r;j=t;while(1){g=Tg(q|0,m|0,10,0)|0;l=E;b=Ig(j|0,((j|0)<0)<<31>>31|0,-48,-1)|0;k=Ig(b|0,E|0,g|0,l|0)|0;l=E;g=c[f>>2]|0;if(g>>>0<(c[h>>2]|0)>>>0){c[f>>2]=g+1;u=d[g]|0}else{u=pg(a)|0}if((u+ -48|0)>>>0<10&((l|0)<21474836|(l|0)==21474836&k>>>0<2061584302)){q=k;m=l;j=u}else{v=k;w=l;x=u;break}}}else{v=s;w=r;x=t}if((x+ -48|0)>>>0<10){do{x=c[f>>2]|0;if(x>>>0<(c[h>>2]|0)>>>0){c[f>>2]=x+1;y=d[x]|0}else{y=pg(a)|0}}while((y+ -48|0)>>>0<10)}if((c[h>>2]|0)!=0){c[f>>2]=(c[f>>2]|0)+ -1}f=(n|0)!=0;n=Cg(0,0,v|0,w|0)|0;o=f?E:w;p=f?n:v;E=o;i=e;return p|0}function og(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;c[a+104>>2]=b;e=c[a+8>>2]|0;f=c[a+4>>2]|0;g=e-f|0;c[a+108>>2]=g;if((b|0)!=0&(g|0)>(b|0)){c[a+100>>2]=f+b;i=d;return}else{c[a+100>>2]=e;i=d;return}}function pg(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;f=b+104|0;g=c[f>>2]|0;if(!((g|0)!=0?(c[b+108>>2]|0)>=(g|0):0)){h=3}if((h|0)==3?(h=tg(b)|0,(h|0)>=0):0){g=c[f>>2]|0;f=c[b+8>>2]|0;if((g|0)!=0?(j=c[b+4>>2]|0,k=g-(c[b+108>>2]|0)+ -1|0,(f-j|0)>(k|0)):0){c[b+100>>2]=j+k}else{c[b+100>>2]=f}k=c[b+4>>2]|0;if((f|0)!=0){j=b+108|0;c[j>>2]=f+1-k+(c[j>>2]|0)}j=k+ -1|0;if((d[j]|0|0)==(h|0)){l=h;i=e;return l|0}a[j]=h;l=h;i=e;return l|0}c[b+100>>2]=0;l=-1;i=e;return l|0}function qg(a,b){a=+a;b=b|0;var d=0,e=0.0,f=0,g=0,j=0,l=0.0;d=i;if((b|0)>1023){e=a*8.98846567431158e+307;f=b+ -1023|0;if((f|0)>1023){g=b+ -2046|0;j=(g|0)>1023?1023:g;l=e*8.98846567431158e+307}else{j=f;l=e}}else{if((b|0)<-1022){e=a*2.2250738585072014e-308;f=b+1022|0;if((f|0)<-1022){g=b+2044|0;j=(g|0)<-1022?-1022:g;l=e*2.2250738585072014e-308}else{j=f;l=e}}else{j=b;l=a}}b=Gg(j+1023|0,0,52)|0;j=E;c[k>>2]=b;c[k+4>>2]=j;a=l*+h[k>>3];i=d;return+a}function rg(a,b){a=+a;b=b|0;var c=0,d=0.0;c=i;d=+qg(a,b);i=c;return+d}function sg(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;e=b+74|0;f=a[e]|0;a[e]=f+255|f;f=b+20|0;e=b+44|0;if((c[f>>2]|0)>>>0>(c[e>>2]|0)>>>0){kb[c[b+36>>2]&1](b,0,0)|0}c[b+16>>2]=0;c[b+28>>2]=0;c[f>>2]=0;f=c[b>>2]|0;if((f&20|0)==0){g=c[e>>2]|0;c[b+8>>2]=g;c[b+4>>2]=g;h=0;i=d;return h|0}if((f&4|0)==0){h=-1;i=d;return h|0}c[b>>2]=f|32;h=-1;i=d;return h|0}function tg(a){a=a|0;var b=0,e=0,f=0;b=i;i=i+16|0;e=b;if((c[a+8>>2]|0)==0?(sg(a)|0)!=0:0){f=-1}else{if((kb[c[a+32>>2]&1](a,e,1)|0)==1){f=d[e]|0}else{f=-1}}i=b;return f|0}function ug(a){a=a|0;var b=0,c=0.0;b=i;c=+wg(a,0);i=b;return+c}function vg(b){b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;c=i;d=b;while(1){e=d+1|0;if((fb(a[d]|0)|0)==0){break}else{d=e}}b=a[d]|0;f=b<<24>>24;if((f|0)==45){g=1;h=5}else if((f|0)==43){g=0;h=5}else{j=d;k=b;l=0}if((h|0)==5){j=e;k=a[e]|0;l=g}if((cb(k<<24>>24|0)|0)==0){m=0;n=(l|0)!=0;o=0-m|0;p=n?m:o;i=c;return p|0}else{q=j;r=0}while(1){j=q+1|0;k=(r*10|0)+48-(a[q]|0)|0;if((cb(a[j]|0)|0)==0){m=k;break}else{q=j;r=k}}n=(l|0)!=0;o=0-m|0;p=n?m:o;i=c;return p|0}function wg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0.0,j=0,k=0;d=i;i=i+112|0;e=d;f=e+0|0;g=f+112|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(g|0));f=e+4|0;c[f>>2]=a;g=e+8|0;c[g>>2]=-1;c[e+44>>2]=a;c[e+76>>2]=-1;og(e,0);h=+mg(e,1,1);j=(c[f>>2]|0)-(c[g>>2]|0)+(c[e+108>>2]|0)|0;if((b|0)==0){i=d;return+h}if((j|0)==0){k=a}else{k=a+j|0}c[b>>2]=k;i=d;return+h}function xg(b,c){b=b|0;c=c|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;f=a[b]|0;a:do{if(f<<24>>24==0){g=0;h=c}else{j=f;k=f&255;l=b;m=c;while(1){n=a[m]|0;if(n<<24>>24==0){g=j;h=m;break a}if(!(j<<24>>24==n<<24>>24)?(n=Jg(k|0)|0,(n|0)!=(Jg(d[m]|0|0)|0)):0){break}n=l+1|0;o=m+1|0;p=a[n]|0;if(p<<24>>24==0){g=0;h=o;break a}else{j=p;k=p&255;l=n;m=o}}g=a[l]|0;h=m}}while(0);c=Jg(g&255|0)|0;g=c-(Jg(d[h]|0|0)|0)|0;i=e;return g|0}function yg(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;e=a[b]|0;f=a[c]|0;if(e<<24>>24!=f<<24>>24|e<<24>>24==0|f<<24>>24==0){g=e;h=f;j=g&255;k=h&255;l=j-k|0;i=d;return l|0}else{m=b;n=c}while(1){c=m+1|0;b=n+1|0;f=a[c]|0;e=a[b]|0;if(f<<24>>24!=e<<24>>24|f<<24>>24==0|e<<24>>24==0){g=f;h=e;break}else{m=c;n=b}}j=g&255;k=h&255;l=j-k|0;i=d;return l|0}function zg(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=i;if((e|0)==0){g=0;i=f;return g|0}h=a[b]|0;a:do{if(h<<24>>24==0){j=0;k=c}else{l=e;m=h;n=h&255;o=b;p=c;while(1){q=l+ -1|0;r=a[p]|0;if(r<<24>>24==0|(q|0)==0){j=m;k=p;break a}if(!(m<<24>>24==r<<24>>24)?(r=Jg(n|0)|0,(r|0)!=(Jg(d[p]|0|0)|0)):0){break}r=o+1|0;s=p+1|0;t=a[r]|0;if(t<<24>>24==0){j=0;k=s;break a}else{l=q;m=t;n=t&255;o=r;p=s}}j=a[o]|0;k=p}}while(0);c=Jg(j&255|0)|0;g=c-(Jg(d[k]|0|0)|0)|0;i=f;return g|0}function Ag(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;f=i;if((e|0)==0){g=0;i=f;return g|0}h=a[b]|0;a:do{if(h<<24>>24==0){j=0;k=c}else{l=e;m=h;n=b;o=c;while(1){p=l+ -1|0;q=a[o]|0;if(!((p|0)!=0&q<<24>>24!=0&m<<24>>24==q<<24>>24)){j=m;k=o;break a}q=n+1|0;r=o+1|0;s=a[q]|0;if(s<<24>>24==0){j=0;k=r;break}else{l=p;m=s;n=q;o=r}}}}while(0);g=(j&255)-(d[k]|0)|0;i=f;return g|0}function Bg(){}function Cg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=b-d>>>0;e=b-d-(c>>>0>a>>>0|0)>>>0;return(E=e,a-c>>>0|0)|0}function Dg(b){b=b|0;var c=0;c=b;while(a[c]|0){c=c+1|0}return c-b|0}function Eg(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0)>=20){d=d&255;g=b&3;h=d|d<<8|d<<16|d<<24;i=f&~3;if(g){g=b+4-g|0;while((b|0)<(g|0)){a[b]=d;b=b+1|0}}while((b|0)<(i|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b]=d;b=b+1|0}return b-e|0}function Fg(b,c){b=b|0;c=c|0;var d=0,e=0;d=b+(Dg(b)|0)|0;do{a[d+e|0]=a[c+e|0];e=e+1|0}while(a[c+(e-1)|0]|0);return b|0}function Gg(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b<>>32-c;return a<>>0;return(E=b+d+(e>>>0>>0|0)>>>0,e|0)|0}function Jg(a){a=a|0;if((a|0)<65)return a|0;if((a|0)>90)return a|0;return a-65+97|0}function Kg(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return Ga(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if((e|0)==0)return f|0;a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function Lg(b,c){b=b|0;c=c|0;var d=0;do{a[b+d|0]=a[c+d|0];d=d+1|0}while(a[c+(d-1)|0]|0);return b|0}function Mg(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b>>>c;return a>>>c|(b&(1<>>c-32|0}function Ng(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){E=b>>c;return a>>>c|(b&(1<>c-32|0}function Og(b){b=b|0;var c=0;c=a[n+(b>>>24)|0]|0;if((c|0)<8)return c|0;c=a[n+(b>>16&255)|0]|0;if((c|0)<8)return c+8|0;c=a[n+(b>>8&255)|0]|0;if((c|0)<8)return c+16|0;return(a[n+(b&255)|0]|0)+24|0}function Pg(b){b=b|0;var c=0;c=a[m+(b&255)|0]|0;if((c|0)<8)return c|0;c=a[m+(b>>8&255)|0]|0;if((c|0)<8)return c+8|0;c=a[m+(b>>16&255)|0]|0;if((c|0)<8)return c+16|0;return(a[m+(b>>>24)|0]|0)+24|0}function Qg(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=a&65535;d=b&65535;e=aa(d,c)|0;f=a>>>16;a=(e>>>16)+(aa(d,f)|0)|0;d=b>>>16;b=aa(d,c)|0;return(E=(a>>>16)+(aa(d,f)|0)+(((a&65535)+b|0)>>>16)|0,a+b<<16|e&65535|0)|0}function Rg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;e=b>>31|((b|0)<0?-1:0)<<1;f=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;g=d>>31|((d|0)<0?-1:0)<<1;h=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;i=Cg(e^a,f^b,e,f)|0;b=E;a=g^e;e=h^f;f=Cg((Wg(i,b,Cg(g^c,h^d,g,h)|0,E,0)|0)^a,E^e,a,e)|0;return f|0}function Sg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+8|0;g=f|0;h=b>>31|((b|0)<0?-1:0)<<1;j=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;k=e>>31|((e|0)<0?-1:0)<<1;l=((e|0)<0?-1:0)>>31|((e|0)<0?-1:0)<<1;m=Cg(h^a,j^b,h,j)|0;b=E;Wg(m,b,Cg(k^d,l^e,k,l)|0,E,g)|0;l=Cg(c[g>>2]^h,c[g+4>>2]^j,h,j)|0;j=E;i=f;return(E=j,l)|0}function Tg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;a=c;c=Qg(e,a)|0;f=E;return(E=(aa(b,a)|0)+(aa(d,e)|0)+f|f&0,c|0|0)|0}function Ug(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=Wg(a,b,c,d,0)|0;return e|0}function Vg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=i;i=i+8|0;g=f|0;Wg(a,b,d,e,g)|0;i=f;return(E=c[g+4>>2]|0,c[g>>2]|0)|0}function Wg(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;g=a;h=b;i=h;j=d;k=e;l=k;if((i|0)==0){m=(f|0)!=0;if((l|0)==0){if(m){c[f>>2]=(g>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(g>>>0)/(j>>>0)>>>0;return(E=n,o)|0}else{if(!m){n=0;o=0;return(E=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;n=0;o=0;return(E=n,o)|0}}m=(l|0)==0;do{if((j|0)!=0){if(!m){p=(Og(l|0)|0)-(Og(i|0)|0)|0;if(p>>>0<=31){q=p+1|0;r=31-p|0;s=p-31>>31;t=q;u=g>>>(q>>>0)&s|i<>>(q>>>0)&s;w=0;x=g<>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return(E=n,o)|0}r=j-1|0;if((r&j|0)!=0){s=(Og(j|0)|0)+33-(Og(i|0)|0)|0;q=64-s|0;p=32-s|0;y=p>>31;z=s-32|0;A=z>>31;t=s;u=p-1>>31&i>>>(z>>>0)|(i<>>(s>>>0))&A;v=A&i>>>(s>>>0);w=g<>>(z>>>0))&y|g<>31;break}if((f|0)!=0){c[f>>2]=r&g;c[f+4>>2]=0}if((j|0)==1){n=h|b&0;o=a|0|0;return(E=n,o)|0}else{r=Pg(j|0)|0;n=i>>>(r>>>0)|0;o=i<<32-r|g>>>(r>>>0)|0;return(E=n,o)|0}}else{if(m){if((f|0)!=0){c[f>>2]=(i>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(i>>>0)/(j>>>0)>>>0;return(E=n,o)|0}if((g|0)==0){if((f|0)!=0){c[f>>2]=0;c[f+4>>2]=(i>>>0)%(l>>>0)}n=0;o=(i>>>0)/(l>>>0)>>>0;return(E=n,o)|0}r=l-1|0;if((r&l|0)==0){if((f|0)!=0){c[f>>2]=a|0;c[f+4>>2]=r&i|b&0}n=0;o=i>>>((Pg(l|0)|0)>>>0);return(E=n,o)|0}r=(Og(l|0)|0)-(Og(i|0)|0)|0;if(r>>>0<=30){s=r+1|0;p=31-r|0;t=s;u=i<>>(s>>>0);v=i>>>(s>>>0);w=0;x=g<>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return(E=n,o)|0}}while(0);if((t|0)==0){B=x;C=w;D=v;F=u;G=0;H=0}else{b=d|0|0;d=k|e&0;e=Ig(b,d,-1,-1)|0;k=E;h=x;x=w;w=v;v=u;u=t;t=0;while(1){I=x>>>31|h<<1;J=t|x<<1;a=v<<1|h>>>31|0;g=v>>>31|w<<1|0;Cg(e,k,a,g)|0;i=E;l=i>>31|((i|0)<0?-1:0)<<1;K=l&1;L=Cg(a,g,l&b,(((i|0)<0?-1:0)>>31|((i|0)<0?-1:0)<<1)&d)|0;M=E;i=u-1|0;if((i|0)==0){break}else{h=I;x=J;w=M;v=L;u=i;t=K}}B=I;C=J;D=M;F=L;G=0;H=K}K=C;C=0;if((f|0)!=0){c[f>>2]=F;c[f+4>>2]=D}n=(K|0)>>>31|(B|C)<<1|(C<<1|K>>>31)&0|G;o=(K<<1|0>>>31)&-2|H;return(E=n,o)|0}function Xg(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return kb[a&1](b|0,c|0,d|0)|0}function Yg(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=d|0;e=e|0;f=f|0;return lb[a&63](+b,+c,d|0,e|0,f|0)|0}function Zg(a,b,c){a=a|0;b=b|0;c=c|0;mb[a&1](b|0,c|0)}function _g(a,b,c){a=a|0;b=b|0;c=c|0;return nb[a&7](b|0,c|0)|0}function $g(a,b,c){a=a|0;b=b|0;c=c|0;ba(0);return 0}function ah(a,b,c,d,e){a=+a;b=+b;c=c|0;d=d|0;e=e|0;ba(1);return 0}function bh(a,b){a=a|0;b=b|0;ba(2)}function ch(a,b){a=a|0;b=b|0;ba(3);return 0} + + + + +// EMSCRIPTEN_END_FUNCS +var kb=[$g,Xf];var lb=[ah,Ud,Vd,Xd,Yd,Zd,_d,$d,ae,de,ee,fe,ge,he,ie,je,ke,le,me,ne,oe,pe,qe,re,se,te,ue,ve,we,He,Ie,Je,Ke,Le,Me,Ne,Oe,Qd,Rd,Sd,Td,be,ce,xe,ye,ze,Ae,Be,Ce,De,Ee,Fe,Ge,ah,ah,ah,ah,ah,ah,ah,ah,ah,ah,ah];var mb=[bh,Yf];var nb=[ch,nf,of,pf,ef,ch,ch,ch];return{_strlen:Dg,_strcat:Fg,_gzread:xf,_wcsunits:Ib,_zscale:Lb,_initwcs:Eb,_wcssys:Hb,_pix2wcsstr:Fb,_calloc:ig,_bitshift64Shl:Gg,_gzwrite:Cf,_saostrtod:Kb,_strncpy:Hg,_memset:Eg,_memcpy:Kg,_gzclose:rf,_i64Subtract:Cg,_realloc:jg,_i64Add:Ig,_wcs2pixstr:Gb,_gzopen:sf,_gzseek:wf,_free:hg,_tolower:Jg,_malloc:gg,_reg2wcsstr:Jb,_strcpy:Lg,runPostSets:Bg,stackAlloc:ob,stackSave:pb,stackRestore:qb,setThrew:rb,setTempRet0:ub,setTempRet1:vb,setTempRet2:wb,setTempRet3:xb,setTempRet4:yb,setTempRet5:zb,setTempRet6:Ab,setTempRet7:Bb,setTempRet8:Cb,setTempRet9:Db,dynCall_iiii:Xg,dynCall_iddiii:Yg,dynCall_vii:Zg,dynCall_iii:_g}}) + + +// EMSCRIPTEN_END_ASM +({ "Math": Math, "Int8Array": Int8Array, "Int16Array": Int16Array, "Int32Array": Int32Array, "Uint8Array": Uint8Array, "Uint16Array": Uint16Array, "Uint32Array": Uint32Array, "Float32Array": Float32Array, "Float64Array": Float64Array }, { "abort": abort, "assert": assert, "asmPrintInt": asmPrintInt, "asmPrintFloat": asmPrintFloat, "min": Math_min, "invoke_iiii": invoke_iiii, "invoke_iddiii": invoke_iddiii, "invoke_vii": invoke_vii, "invoke_iii": invoke_iii, "_fabs": _fabs, "_sin": _sin, "_exp": _exp, "_llvm_pow_f64": _llvm_pow_f64, "_acos": _acos, "_atan2": _atan2, "_fmod": _fmod, "_lseek": _lseek, "__reallyNegative": __reallyNegative, "_asin": _asin, "_atan": _atan, "___buildEnvironment": ___buildEnvironment, "_fflush": _fflush, "_pwrite": _pwrite, "_strerror_r": _strerror_r, "_fprintf": _fprintf, "_open": _open, "_fabsf": _fabsf, "_sbrk": _sbrk, "_send": _send, "_snprintf": _snprintf, "_llvm_bswap_i32": _llvm_bswap_i32, "_emscripten_memcpy_big": _emscripten_memcpy_big, "_fileno": _fileno, "_sysconf": _sysconf, "___setErrNo": ___setErrNo, "_cos": _cos, "_pread": _pread, "_printf": _printf, "_sprintf": _sprintf, "_log": _log, "_toupper": _toupper, "_write": _write, "_isupper": _isupper, "___errno_location": ___errno_location, "_recv": _recv, "_tan": _tan, "_copysign": _copysign, "_getenv": _getenv, "_mkport": _mkport, "__exit": __exit, "_read": _read, "_abort": _abort, "_islower": _islower, "_fwrite": _fwrite, "_time": _time, "_isdigit": _isdigit, "_strerror": _strerror, "__formatString": __formatString, "_isspace": _isspace, "_sqrt": _sqrt, "_exit": _exit, "_close": _close, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "cttz_i8": cttz_i8, "ctlz_i8": ctlz_i8, "NaN": NaN, "Infinity": Infinity, "_stderr": _stderr }, buffer); +var _strlen = Module["_strlen"] = asm["_strlen"]; +var _strcat = Module["_strcat"] = asm["_strcat"]; +var _gzread = Module["_gzread"] = asm["_gzread"]; +var _wcsunits = Module["_wcsunits"] = asm["_wcsunits"]; +var _zscale = Module["_zscale"] = asm["_zscale"]; +var _initwcs = Module["_initwcs"] = asm["_initwcs"]; +var _wcssys = Module["_wcssys"] = asm["_wcssys"]; +var _pix2wcsstr = Module["_pix2wcsstr"] = asm["_pix2wcsstr"]; +var _calloc = Module["_calloc"] = asm["_calloc"]; +var _bitshift64Shl = Module["_bitshift64Shl"] = asm["_bitshift64Shl"]; +var _gzwrite = Module["_gzwrite"] = asm["_gzwrite"]; +var _saostrtod = Module["_saostrtod"] = asm["_saostrtod"]; +var _strncpy = Module["_strncpy"] = asm["_strncpy"]; +var _memset = Module["_memset"] = asm["_memset"]; +var _memcpy = Module["_memcpy"] = asm["_memcpy"]; +var _gzclose = Module["_gzclose"] = asm["_gzclose"]; +var _i64Subtract = Module["_i64Subtract"] = asm["_i64Subtract"]; +var _realloc = Module["_realloc"] = asm["_realloc"]; +var _i64Add = Module["_i64Add"] = asm["_i64Add"]; +var _wcs2pixstr = Module["_wcs2pixstr"] = asm["_wcs2pixstr"]; +var _gzopen = Module["_gzopen"] = asm["_gzopen"]; +var _gzseek = Module["_gzseek"] = asm["_gzseek"]; +var _free = Module["_free"] = asm["_free"]; +var _tolower = Module["_tolower"] = asm["_tolower"]; +var _malloc = Module["_malloc"] = asm["_malloc"]; +var _reg2wcsstr = Module["_reg2wcsstr"] = asm["_reg2wcsstr"]; +var _strcpy = Module["_strcpy"] = asm["_strcpy"]; +var runPostSets = Module["runPostSets"] = asm["runPostSets"]; +var dynCall_iiii = Module["dynCall_iiii"] = asm["dynCall_iiii"]; +var dynCall_iddiii = Module["dynCall_iddiii"] = asm["dynCall_iddiii"]; +var dynCall_vii = Module["dynCall_vii"] = asm["dynCall_vii"]; +var dynCall_iii = Module["dynCall_iii"] = asm["dynCall_iii"]; + +Runtime.stackAlloc = function(size) { return asm['stackAlloc'](size) }; +Runtime.stackSave = function() { return asm['stackSave']() }; +Runtime.stackRestore = function(top) { asm['stackRestore'](top) }; + + +// TODO: strip out parts of this we do not need + +//======= begin closure i64 code ======= + +// Copyright 2009 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Defines a Long class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "long". This + * implementation is derived from LongLib in GWT. + * + */ + +var i64Math = (function() { // Emscripten wrapper + var goog = { math: {} }; + + + /** + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @param {number} low The low (signed) 32 bits of the long. + * @param {number} high The high (signed) 32 bits of the long. + * @constructor + */ + goog.math.Long = function(low, high) { + /** + * @type {number} + * @private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @private + */ + this.high_ = high | 0; // force into 32 signed bits. + }; + + + // NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the + // from* methods on which they depend. + + + /** + * A cache of the Long representations of small integer values. + * @type {!Object} + * @private + */ + goog.math.Long.IntCache_ = {}; + + + /** + * Returns a Long representing the given (32-bit) integer value. + * @param {number} value The 32-bit integer in question. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = goog.math.Long.IntCache_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new goog.math.Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + goog.math.Long.IntCache_[value] = obj; + } + return obj; + }; + + + /** + * Returns a Long representing the given value, provided that it is a finite + * number. Otherwise, zero is returned. + * @param {number} value The number in question. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return goog.math.Long.ZERO; + } else if (value <= -goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MIN_VALUE; + } else if (value + 1 >= goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MAX_VALUE; + } else if (value < 0) { + return goog.math.Long.fromNumber(-value).negate(); + } else { + return new goog.math.Long( + (value % goog.math.Long.TWO_PWR_32_DBL_) | 0, + (value / goog.math.Long.TWO_PWR_32_DBL_) | 0); + } + }; + + + /** + * Returns a Long representing the 64-bit integer that comes by concatenating + * the given high and low bits. Each is assumed to use 32 bits. + * @param {number} lowBits The low 32-bits. + * @param {number} highBits The high 32-bits. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromBits = function(lowBits, highBits) { + return new goog.math.Long(lowBits, highBits); + }; + + + /** + * Returns a Long representation of the given string, written using the given + * radix. + * @param {string} str The textual representation of the Long. + * @param {number=} opt_radix The radix in which the text is written. + * @return {!goog.math.Long} The corresponding Long value. + */ + goog.math.Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return goog.math.Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 8)); + + var result = goog.math.Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = goog.math.Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(goog.math.Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(goog.math.Long.fromNumber(value)); + } + } + return result; + }; + + + // NOTE: the compiler should inline these constant values below and then remove + // these variables, so there should be no runtime penalty for these. + + + /** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_16_DBL_ = 1 << 16; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_24_DBL_ = 1 << 24; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_32_DBL_ = + goog.math.Long.TWO_PWR_16_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_31_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ / 2; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_48_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_64_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_32_DBL_; + + + /** + * @type {number} + * @private + */ + goog.math.Long.TWO_PWR_63_DBL_ = + goog.math.Long.TWO_PWR_64_DBL_ / 2; + + + /** @type {!goog.math.Long} */ + goog.math.Long.ZERO = goog.math.Long.fromInt(0); + + + /** @type {!goog.math.Long} */ + goog.math.Long.ONE = goog.math.Long.fromInt(1); + + + /** @type {!goog.math.Long} */ + goog.math.Long.NEG_ONE = goog.math.Long.fromInt(-1); + + + /** @type {!goog.math.Long} */ + goog.math.Long.MAX_VALUE = + goog.math.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + + + /** @type {!goog.math.Long} */ + goog.math.Long.MIN_VALUE = goog.math.Long.fromBits(0, 0x80000000 | 0); + + + /** + * @type {!goog.math.Long} + * @private + */ + goog.math.Long.TWO_PWR_24_ = goog.math.Long.fromInt(1 << 24); + + + /** @return {number} The value, assuming it is a 32-bit integer. */ + goog.math.Long.prototype.toInt = function() { + return this.low_; + }; + + + /** @return {number} The closest floating-point representation to this value. */ + goog.math.Long.prototype.toNumber = function() { + return this.high_ * goog.math.Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); + }; + + + /** + * @param {number=} opt_radix The radix in which the text should be written. + * @return {string} The textual representation of this value. + */ + goog.math.Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = goog.math.Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } + }; + + + /** @return {number} The high 32-bits as a signed value. */ + goog.math.Long.prototype.getHighBits = function() { + return this.high_; + }; + + + /** @return {number} The low 32-bits as a signed value. */ + goog.math.Long.prototype.getLowBits = function() { + return this.low_; + }; + + + /** @return {number} The low 32-bits as an unsigned value. */ + goog.math.Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : goog.math.Long.TWO_PWR_32_DBL_ + this.low_; + }; + + + /** + * @return {number} Returns the number of bits needed to represent the absolute + * value of this Long. + */ + goog.math.Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } + }; + + + /** @return {boolean} Whether this value is zero. */ + goog.math.Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; + }; + + + /** @return {boolean} Whether this value is negative. */ + goog.math.Long.prototype.isNegative = function() { + return this.high_ < 0; + }; + + + /** @return {boolean} Whether this value is odd. */ + goog.math.Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long equals the other. + */ + goog.math.Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long does not equal the other. + */ + goog.math.Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than the other. + */ + goog.math.Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than or equal to the other. + */ + goog.math.Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than the other. + */ + goog.math.Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; + }; + + + /** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than or equal to the other. + */ + goog.math.Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; + }; + + + /** + * Compares this Long with the given one. + * @param {goog.math.Long} other Long to compare against. + * @return {number} 0 if they are the same, 1 if the this is greater, and -1 + * if the given one is greater. + */ + goog.math.Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } + }; + + + /** @return {!goog.math.Long} The negation of this value. */ + goog.math.Long.prototype.negate = function() { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.MIN_VALUE; + } else { + return this.not().add(goog.math.Long.ONE); + } + }; + + + /** + * Returns the sum of this and the given Long. + * @param {goog.math.Long} other Long to add to this one. + * @return {!goog.math.Long} The sum of this and the given Long. + */ + goog.math.Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); + }; + + + /** + * Returns the difference of this and the given Long. + * @param {goog.math.Long} other Long to subtract from this. + * @return {!goog.math.Long} The difference of this and the given Long. + */ + goog.math.Long.prototype.subtract = function(other) { + return this.add(other.negate()); + }; + + + /** + * Returns the product of this and the given long. + * @param {goog.math.Long} other Long to multiply with this. + * @return {!goog.math.Long} The product of this and the other. + */ + goog.math.Long.prototype.multiply = function(other) { + if (this.isZero()) { + return goog.math.Long.ZERO; + } else if (other.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + return other.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return this.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both longs are small, use float multiplication + if (this.lessThan(goog.math.Long.TWO_PWR_24_) && + other.lessThan(goog.math.Long.TWO_PWR_24_)) { + return goog.math.Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); + }; + + + /** + * Returns this Long divided by the given one. + * @param {goog.math.Long} other Long by which to divide. + * @return {!goog.math.Long} This Long divided by the given one. + */ + goog.math.Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + if (other.equals(goog.math.Long.ONE) || + other.equals(goog.math.Long.NEG_ONE)) { + return goog.math.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(goog.math.Long.ZERO)) { + return other.isNegative() ? goog.math.Long.ONE : goog.math.Long.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = goog.math.Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = goog.math.Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = goog.math.Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = goog.math.Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; + }; + + + /** + * Returns this Long modulo the given one. + * @param {goog.math.Long} other Long by which to mod. + * @return {!goog.math.Long} This Long modulo the given one. + */ + goog.math.Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); + }; + + + /** @return {!goog.math.Long} The bitwise-NOT of this value. */ + goog.math.Long.prototype.not = function() { + return goog.math.Long.fromBits(~this.low_, ~this.high_); + }; + + + /** + * Returns the bitwise-AND of this Long and the given one. + * @param {goog.math.Long} other The Long with which to AND. + * @return {!goog.math.Long} The bitwise-AND of this and the other. + */ + goog.math.Long.prototype.and = function(other) { + return goog.math.Long.fromBits(this.low_ & other.low_, + this.high_ & other.high_); + }; + + + /** + * Returns the bitwise-OR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to OR. + * @return {!goog.math.Long} The bitwise-OR of this and the other. + */ + goog.math.Long.prototype.or = function(other) { + return goog.math.Long.fromBits(this.low_ | other.low_, + this.high_ | other.high_); + }; + + + /** + * Returns the bitwise-XOR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to XOR. + * @return {!goog.math.Long} The bitwise-XOR of this and the other. + */ + goog.math.Long.prototype.xor = function(other) { + return goog.math.Long.fromBits(this.low_ ^ other.low_, + this.high_ ^ other.high_); + }; + + + /** + * Returns this Long with bits shifted to the left by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the left by the given amount. + */ + goog.math.Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return goog.math.Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return goog.math.Long.fromBits(0, low << (numBits - 32)); + } + } + }; + + + /** + * Returns this Long with bits shifted to the right by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount. + */ + goog.math.Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return goog.math.Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } + }; + + + /** + * Returns this Long with bits shifted to the right by the given amount, with + * the new top bits matching the current sign bit. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount, with + * zeros placed into the new leading bits. + */ + goog.math.Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return goog.math.Long.fromBits(high, 0); + } else { + return goog.math.Long.fromBits(high >>> (numBits - 32), 0); + } + } + }; + + //======= begin jsbn ======= + + var navigator = { appName: 'Modern Browser' }; // polyfill a little + + // Copyright (c) 2005 Tom Wu + // All Rights Reserved. + // http://www-cs-students.stanford.edu/~tjw/jsbn/ + + /* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ + + // Basic JavaScript BN library - subset useful for RSA encryption. + + // Bits per digit + var dbits; + + // JavaScript engine analysis + var canary = 0xdeadbeefcafe; + var j_lm = ((canary&0xffffff)==0xefcafe); + + // (public) Constructor + function BigInteger(a,b,c) { + if(a != null) + if("number" == typeof a) this.fromNumber(a,b,c); + else if(b == null && "string" != typeof a) this.fromString(a,256); + else this.fromString(a,b); + } + + // return new, unset BigInteger + function nbi() { return new BigInteger(null); } + + // am: Compute w_j += (x*this_i), propagate carries, + // c is initial carry, returns final carry. + // c < 3*dvalue, x < 2*dvalue, this_i < dvalue + // We need to select the fastest one that works in this environment. + + // am1: use a single mult and divide to get the high bits, + // max digit bits should be 26 because + // max internal value = 2*dvalue^2-2*dvalue (< 2^53) + function am1(i,x,w,j,c,n) { + while(--n >= 0) { + var v = x*this[i++]+w[j]+c; + c = Math.floor(v/0x4000000); + w[j++] = v&0x3ffffff; + } + return c; + } + // am2 avoids a big mult-and-extract completely. + // Max digit bits should be <= 30 because we do bitwise ops + // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) + function am2(i,x,w,j,c,n) { + var xl = x&0x7fff, xh = x>>15; + while(--n >= 0) { + var l = this[i]&0x7fff; + var h = this[i++]>>15; + var m = xh*l+h*xl; + l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); + c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); + w[j++] = l&0x3fffffff; + } + return c; + } + // Alternately, set max digit bits to 28 since some + // browsers slow down when dealing with 32-bit numbers. + function am3(i,x,w,j,c,n) { + var xl = x&0x3fff, xh = x>>14; + while(--n >= 0) { + var l = this[i]&0x3fff; + var h = this[i++]>>14; + var m = xh*l+h*xl; + l = xl*l+((m&0x3fff)<<14)+w[j]+c; + c = (l>>28)+(m>>14)+xh*h; + w[j++] = l&0xfffffff; + } + return c; + } + if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { + BigInteger.prototype.am = am2; + dbits = 30; + } + else if(j_lm && (navigator.appName != "Netscape")) { + BigInteger.prototype.am = am1; + dbits = 26; + } + else { // Mozilla/Netscape seems to prefer am3 + BigInteger.prototype.am = am3; + dbits = 28; + } + + BigInteger.prototype.DB = dbits; + BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; + r.t = this.t; + r.s = this.s; + } + + // (protected) set from integer value x, -DV <= x < DV + function bnpFromInt(x) { + this.t = 1; + this.s = (x<0)?-1:0; + if(x > 0) this[0] = x; + else if(x < -1) this[0] = x+DV; + else this.t = 0; + } + + // return bigint initialized to value + function nbv(i) { var r = nbi(); r.fromInt(i); return r; } + + // (protected) set from string and radix + function bnpFromString(s,b) { + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 256) k = 8; // byte array + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else { this.fromRadix(s,b); return; } + this.t = 0; + this.s = 0; + var i = s.length, mi = false, sh = 0; + while(--i >= 0) { + var x = (k==8)?s[i]&0xff:intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if(sh == 0) + this[this.t++] = x; + else if(sh+k > this.DB) { + this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); + } + else + this[this.t-1] |= x<= this.DB) sh -= this.DB; + } + if(k == 8 && (s[0]&0x80) != 0) { + this.s = -1; + if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; + } + + // (public) return string representation in given radix + function bnToString(b) { + if(this.s < 0) return "-"+this.negate().toString(b); + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else return this.toRadix(b); + var km = (1< 0) { + if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } + while(i >= 0) { + if(p < k) { + d = (this[i]&((1<>(p+=this.DB-k); + } + else { + d = (this[i]>>(p-=k))&km; + if(p <= 0) { p += this.DB; --i; } + } + if(d > 0) m = true; + if(m) r += int2char(d); + } + } + return m?r:"0"; + } + + // (public) -this + function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } + + // (public) |this| + function bnAbs() { return (this.s<0)?this.negate():this; } + + // (public) return + if this > a, - if this < a, 0 if equal + function bnCompareTo(a) { + var r = this.s-a.s; + if(r != 0) return r; + var i = this.t; + r = i-a.t; + if(r != 0) return (this.s<0)?-r:r; + while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; + return 0; + } + + // returns bit length of the integer x + function nbits(x) { + var r = 1, t; + if((t=x>>>16) != 0) { x = t; r += 16; } + if((t=x>>8) != 0) { x = t; r += 8; } + if((t=x>>4) != 0) { x = t; r += 4; } + if((t=x>>2) != 0) { x = t; r += 2; } + if((t=x>>1) != 0) { x = t; r += 1; } + return r; + } + + // (public) return the number of bits in "this" + function bnBitLength() { + if(this.t <= 0) return 0; + return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); + } + + // (protected) r = this << n*DB + function bnpDLShiftTo(n,r) { + var i; + for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; + for(i = n-1; i >= 0; --i) r[i] = 0; + r.t = this.t+n; + r.s = this.s; + } + + // (protected) r = this >> n*DB + function bnpDRShiftTo(n,r) { + for(var i = n; i < this.t; ++i) r[i-n] = this[i]; + r.t = Math.max(this.t-n,0); + r.s = this.s; + } + + // (protected) r = this << n + function bnpLShiftTo(n,r) { + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<= 0; --i) { + r[i+ds+1] = (this[i]>>cbs)|c; + c = (this[i]&bm)<= 0; --i) r[i] = 0; + r[ds] = c; + r.t = this.t+ds+1; + r.s = this.s; + r.clamp(); + } + + // (protected) r = this >> n + function bnpRShiftTo(n,r) { + r.s = this.s; + var ds = Math.floor(n/this.DB); + if(ds >= this.t) { r.t = 0; return; } + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<>bs; + for(var i = ds+1; i < this.t; ++i) { + r[i-ds-1] |= (this[i]&bm)<>bs; + } + if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; + } + if(a.t < this.t) { + c -= a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c -= a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c<0)?-1:0; + if(c < -1) r[i++] = this.DV+c; + else if(c > 0) r[i++] = c; + r.t = i; + r.clamp(); + } + + // (protected) r = this * a, r != this,a (HAC 14.12) + // "this" should be the larger one if appropriate. + function bnpMultiplyTo(a,r) { + var x = this.abs(), y = a.abs(); + var i = x.t; + r.t = i+y.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); + r.s = 0; + r.clamp(); + if(this.s != a.s) BigInteger.ZERO.subTo(r,r); + } + + // (protected) r = this^2, r != this (HAC 14.16) + function bnpSquareTo(r) { + var x = this.abs(); + var i = r.t = 2*x.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < x.t-1; ++i) { + var c = x.am(i,x[i],r,2*i,0,1); + if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { + r[i+x.t] -= x.DV; + r[i+x.t+1] = 1; + } + } + if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); + r.s = 0; + r.clamp(); + } + + // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) + // r != q, this != m. q or r may be null. + function bnpDivRemTo(m,q,r) { + var pm = m.abs(); + if(pm.t <= 0) return; + var pt = this.abs(); + if(pt.t < pm.t) { + if(q != null) q.fromInt(0); + if(r != null) this.copyTo(r); + return; + } + if(r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus + if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } + else { pm.copyTo(y); pt.copyTo(r); } + var ys = y.t; + var y0 = y[ys-1]; + if(y0 == 0) return; + var yt = y0*(1<1)?y[ys-2]>>this.F2:0); + var d1 = this.FV/yt, d2 = (1<= 0) { + r[r.t++] = 1; + r.subTo(t,r); + } + BigInteger.ONE.dlShiftTo(ys,t); + t.subTo(y,y); // "negative" y so we can replace sub with am later + while(y.t < ys) y[y.t++] = 0; + while(--j >= 0) { + // Estimate quotient digit + var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); + if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out + y.dlShiftTo(j,t); + r.subTo(t,r); + while(r[i] < --qd) r.subTo(t,r); + } + } + if(q != null) { + r.drShiftTo(ys,q); + if(ts != ms) BigInteger.ZERO.subTo(q,q); + } + r.t = ys; + r.clamp(); + if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder + if(ts < 0) BigInteger.ZERO.subTo(r,r); + } + + // (public) this mod a + function bnMod(a) { + var r = nbi(); + this.abs().divRemTo(a,null,r); + if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); + return r; + } + + // Modular reduction using "classic" algorithm + function Classic(m) { this.m = m; } + function cConvert(x) { + if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; + } + function cRevert(x) { return x; } + function cReduce(x) { x.divRemTo(this.m,null,x); } + function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + Classic.prototype.convert = cConvert; + Classic.prototype.revert = cRevert; + Classic.prototype.reduce = cReduce; + Classic.prototype.mulTo = cMulTo; + Classic.prototype.sqrTo = cSqrTo; + + // (protected) return "-1/this % 2^DB"; useful for Mont. reduction + // justification: + // xy == 1 (mod m) + // xy = 1+km + // xy(2-xy) = (1+km)(1-km) + // x[y(2-xy)] = 1-k^2m^2 + // x[y(2-xy)] == 1 (mod m^2) + // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 + // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. + // JS multiply "overflows" differently from C/C++, so care is needed here. + function bnpInvDigit() { + if(this.t < 1) return 0; + var x = this[0]; + if((x&1) == 0) return 0; + var y = x&3; // y == 1/x mod 2^2 + y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 + y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 + y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y>0)?this.DV-y:-y; + } + + // Montgomery reduction + function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp&0x7fff; + this.mph = this.mp>>15; + this.um = (1<<(m.DB-15))-1; + this.mt2 = 2*m.t; + } + + // xR mod m + function montConvert(x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t,r); + r.divRemTo(this.m,null,r); + if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); + return r; + } + + // x/R mod m + function montRevert(x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + + // x = x/R mod m (HAC 14.32) + function montReduce(x) { + while(x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0; + for(var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i]&0x7fff; + var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; + // use am to combine the multiply-shift-add into one call + j = i+this.m.t; + x[j] += this.m.am(0,u0,x,i,0,this.m.t); + // propagate carry + while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } + } + x.clamp(); + x.drShiftTo(this.m.t,x); + if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); + } + + // r = "x^2/R mod m"; x != r + function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + // r = "xy/R mod m"; x,y != r + function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + + Montgomery.prototype.convert = montConvert; + Montgomery.prototype.revert = montRevert; + Montgomery.prototype.reduce = montReduce; + Montgomery.prototype.mulTo = montMulTo; + Montgomery.prototype.sqrTo = montSqrTo; + + // (protected) true iff this is even + function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } + + // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) + function bnpExp(e,z) { + if(e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; + g.copyTo(r); + while(--i >= 0) { + z.sqrTo(r,r2); + if((e&(1< 0) z.mulTo(r2,g,r); + else { var t = r; r = r2; r2 = t; } + } + return z.revert(r); + } + + // (public) this^e % m, 0 <= e < 2^32 + function bnModPowInt(e,m) { + var z; + if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e,z); + } + + // protected + BigInteger.prototype.copyTo = bnpCopyTo; + BigInteger.prototype.fromInt = bnpFromInt; + BigInteger.prototype.fromString = bnpFromString; + BigInteger.prototype.clamp = bnpClamp; + BigInteger.prototype.dlShiftTo = bnpDLShiftTo; + BigInteger.prototype.drShiftTo = bnpDRShiftTo; + BigInteger.prototype.lShiftTo = bnpLShiftTo; + BigInteger.prototype.rShiftTo = bnpRShiftTo; + BigInteger.prototype.subTo = bnpSubTo; + BigInteger.prototype.multiplyTo = bnpMultiplyTo; + BigInteger.prototype.squareTo = bnpSquareTo; + BigInteger.prototype.divRemTo = bnpDivRemTo; + BigInteger.prototype.invDigit = bnpInvDigit; + BigInteger.prototype.isEven = bnpIsEven; + BigInteger.prototype.exp = bnpExp; + + // public + BigInteger.prototype.toString = bnToString; + BigInteger.prototype.negate = bnNegate; + BigInteger.prototype.abs = bnAbs; + BigInteger.prototype.compareTo = bnCompareTo; + BigInteger.prototype.bitLength = bnBitLength; + BigInteger.prototype.mod = bnMod; + BigInteger.prototype.modPowInt = bnModPowInt; + + // "constants" + BigInteger.ZERO = nbv(0); + BigInteger.ONE = nbv(1); + + // jsbn2 stuff + + // (protected) convert from radix string + function bnpFromRadix(s,b) { + this.fromInt(0); + if(b == null) b = 10; + var cs = this.chunkSize(b); + var d = Math.pow(b,cs), mi = false, j = 0, w = 0; + for(var i = 0; i < s.length; ++i) { + var x = intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-" && this.signum() == 0) mi = true; + continue; + } + w = b*w+x; + if(++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w,0); + j = 0; + w = 0; + } + } + if(j > 0) { + this.dMultiply(Math.pow(b,j)); + this.dAddOffset(w,0); + } + if(mi) BigInteger.ZERO.subTo(this,this); + } + + // (protected) return x s.t. r^x < DV + function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } + + // (public) 0 if this == 0, 1 if this > 0 + function bnSigNum() { + if(this.s < 0) return -1; + else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; + else return 1; + } + + // (protected) this *= n, this >= 0, 1 < n < DV + function bnpDMultiply(n) { + this[this.t] = this.am(0,n-1,this,0,0,this.t); + ++this.t; + this.clamp(); + } + + // (protected) this += n << w words, this >= 0 + function bnpDAddOffset(n,w) { + if(n == 0) return; + while(this.t <= w) this[this.t++] = 0; + this[w] += n; + while(this[w] >= this.DV) { + this[w] -= this.DV; + if(++w >= this.t) this[this.t++] = 0; + ++this[w]; + } + } + + // (protected) convert to radix string + function bnpToRadix(b) { + if(b == null) b = 10; + if(this.signum() == 0 || b < 2 || b > 36) return "0"; + var cs = this.chunkSize(b); + var a = Math.pow(b,cs); + var d = nbv(a), y = nbi(), z = nbi(), r = ""; + this.divRemTo(d,y,z); + while(y.signum() > 0) { + r = (a+z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d,y,z); + } + return z.intValue().toString(b) + r; + } + + // (public) return value as integer + function bnIntValue() { + if(this.s < 0) { + if(this.t == 1) return this[0]-this.DV; + else if(this.t == 0) return -1; + } + else if(this.t == 1) return this[0]; + else if(this.t == 0) return 0; + // assumes 16 < DB < 32 + return ((this[1]&((1<<(32-this.DB))-1))<>= this.DB; + } + if(a.t < this.t) { + c += a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c += a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += a.s; + } + r.s = (c<0)?-1:0; + if(c > 0) r[i++] = c; + else if(c < -1) r[i++] = this.DV+c; + r.t = i; + r.clamp(); + } + + BigInteger.prototype.fromRadix = bnpFromRadix; + BigInteger.prototype.chunkSize = bnpChunkSize; + BigInteger.prototype.signum = bnSigNum; + BigInteger.prototype.dMultiply = bnpDMultiply; + BigInteger.prototype.dAddOffset = bnpDAddOffset; + BigInteger.prototype.toRadix = bnpToRadix; + BigInteger.prototype.intValue = bnIntValue; + BigInteger.prototype.addTo = bnpAddTo; + + //======= end jsbn ======= + + // Emscripten wrapper + var Wrapper = { + abs: function(l, h) { + var x = new goog.math.Long(l, h); + var ret; + if (x.isNegative()) { + ret = x.negate(); + } else { + ret = x; + } + HEAP32[tempDoublePtr>>2] = ret.low_; + HEAP32[tempDoublePtr+4>>2] = ret.high_; + }, + ensureTemps: function() { + if (Wrapper.ensuredTemps) return; + Wrapper.ensuredTemps = true; + Wrapper.two32 = new BigInteger(); + Wrapper.two32.fromString('4294967296', 10); + Wrapper.two64 = new BigInteger(); + Wrapper.two64.fromString('18446744073709551616', 10); + Wrapper.temp1 = new BigInteger(); + Wrapper.temp2 = new BigInteger(); + }, + lh2bignum: function(l, h) { + var a = new BigInteger(); + a.fromString(h.toString(), 10); + var b = new BigInteger(); + a.multiplyTo(Wrapper.two32, b); + var c = new BigInteger(); + c.fromString(l.toString(), 10); + var d = new BigInteger(); + c.addTo(b, d); + return d; + }, + stringify: function(l, h, unsigned) { + var ret = new goog.math.Long(l, h).toString(); + if (unsigned && ret[0] == '-') { + // unsign slowly using jsbn bignums + Wrapper.ensureTemps(); + var bignum = new BigInteger(); + bignum.fromString(ret, 10); + ret = new BigInteger(); + Wrapper.two64.addTo(bignum, ret); + ret = ret.toString(10); + } + return ret; + }, + fromString: function(str, base, min, max, unsigned) { + Wrapper.ensureTemps(); + var bignum = new BigInteger(); + bignum.fromString(str, base); + var bigmin = new BigInteger(); + bigmin.fromString(min, 10); + var bigmax = new BigInteger(); + bigmax.fromString(max, 10); + if (unsigned && bignum.compareTo(BigInteger.ZERO) < 0) { + var temp = new BigInteger(); + bignum.addTo(Wrapper.two64, temp); + bignum = temp; + } + var error = false; + if (bignum.compareTo(bigmin) < 0) { + bignum = bigmin; + error = true; + } else if (bignum.compareTo(bigmax) > 0) { + bignum = bigmax; + error = true; + } + var ret = goog.math.Long.fromString(bignum.toString()); // min-max checks should have clamped this to a range goog.math.Long can handle well + HEAP32[tempDoublePtr>>2] = ret.low_; + HEAP32[tempDoublePtr+4>>2] = ret.high_; + if (error) throw 'range error'; + } + }; + return Wrapper; +})(); + +//======= end closure i64 code ======= + + + +// === Auto-generated postamble setup entry stuff === + +if (memoryInitializer) { + if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) { + var data = Module['readBinary'](memoryInitializer); + HEAPU8.set(data, STATIC_BASE); + } else { + addRunDependency('memory initializer'); + Browser.asyncLoad(memoryInitializer, function(data) { + HEAPU8.set(data, STATIC_BASE); + removeRunDependency('memory initializer'); + }, function(data) { + throw 'could not load memory initializer ' + memoryInitializer; + }); + } +} + +function ExitStatus(status) { + this.name = "ExitStatus"; + this.message = "Program terminated with exit(" + status + ")"; + this.status = status; +}; +ExitStatus.prototype = new Error(); +ExitStatus.prototype.constructor = ExitStatus; + +var initialStackTop; +var preloadStartTime = null; +var calledMain = false; + +dependenciesFulfilled = function runCaller() { + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!Module['calledRun'] && shouldRunNow) run(); + if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled +} + +Module['callMain'] = Module.callMain = function callMain(args) { + assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)'); + assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called'); + + args = args || []; + + ensureInitRuntime(); + + var argc = args.length+1; + function pad() { + for (var i = 0; i < 4-1; i++) { + argv.push(0); + } + } + var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL) ]; + pad(); + for (var i = 0; i < argc-1; i = i + 1) { + argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL)); + pad(); + } + argv.push(0); + argv = allocate(argv, 'i32', ALLOC_NORMAL); + + initialStackTop = STACKTOP; + + try { + + var ret = Module['_main'](argc, argv, 0); + + + // if we're not running an evented main loop, it's time to exit + if (!Module['noExitRuntime']) { + exit(ret); + } + } + catch(e) { + if (e instanceof ExitStatus) { + // exit() throws this once it's done to make sure execution + // has been stopped completely + return; + } else if (e == 'SimulateInfiniteLoop') { + // running an evented main loop, don't immediately exit + Module['noExitRuntime'] = true; + return; + } else { + if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]); + throw e; + } + } finally { + calledMain = true; + } +} + + + + +function run(args) { + args = args || Module['arguments']; + + if (preloadStartTime === null) preloadStartTime = Date.now(); + + if (runDependencies > 0) { + Module.printErr('run() called, but dependencies remain, so not running'); + return; + } + + preRun(); + + if (runDependencies > 0) return; // a preRun added a dependency, run will be called later + if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame + + function doRun() { + if (Module['calledRun']) return; // run may have just been called while the async setStatus time below was happening + Module['calledRun'] = true; + + ensureInitRuntime(); + + preMain(); + + if (ENVIRONMENT_IS_WEB && preloadStartTime !== null) { + Module.printErr('pre-main prep time: ' + (Date.now() - preloadStartTime) + ' ms'); + } + + if (Module['_main'] && shouldRunNow) { + Module['callMain'](args); + } + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + if (!ABORT) doRun(); + }, 1); + } else { + doRun(); + } +} +Module['run'] = Module.run = run; + +function exit(status) { + ABORT = true; + EXITSTATUS = status; + STACKTOP = initialStackTop; + + // exit the runtime + exitRuntime(); + + // TODO We should handle this differently based on environment. + // In the browser, the best we can do is throw an exception + // to halt execution, but in node we could process.exit and + // I'd imagine SM shell would have something equivalent. + // This would let us set a proper exit status (which + // would be great for checking test exit statuses). + // https://github.com/kripken/emscripten/issues/1371 + + // throw an exception to halt the current execution + throw new ExitStatus(status); +} +Module['exit'] = Module.exit = exit; + +function abort(text) { + if (text) { + Module.print(text); + Module.printErr(text); + } + + ABORT = true; + EXITSTATUS = 1; + + var extra = '\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.'; + + throw 'abort() at ' + stackTrace() + extra; +} +Module['abort'] = Module.abort = abort; + +// {{PRE_RUN_ADDITIONS}} + +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} + +// shouldRunNow refers to calling main(), not run(). +var shouldRunNow = true; +if (Module['noInitialRun']) { + shouldRunNow = false; +} + + +run(); + +// {{POST_RUN_ADDITIONS}} + + + + + + +// {{MODULE_ADDITIONS}} + + + + + +Module['arrfile'] = function(filename, arr) { + try{ FS.unlink("/" + filename); } + catch(e){ ; } + FS.createDataFile("/", filename, arr, true, true); + return {path: filename, size: arr.byteLength}; +}; + +Module['gzcompress'] = function(data) { // TODO: Accept strings + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['output.gz', 'wb']); + var buffer = _malloc(data.length); + HEAPU8.set(data, buffer); + ccall('gzwrite', 'number', ['number', 'number', 'number'], [gzFile, buffer, data.length]); + ccall('gzclose', 'number', ['number'], [gzFile]); + _free(buffer); + var ret = new Uint8Array(FS.root.contents['output.gz'].contents); + FS.unlink('output.gz'); + return ret; +}; + +Module['gzdecompress'] = function(data) { + var BUFSIZE = 1024*1024; + FS.createDataFile('/', 'input.gz', data, true, true); + var gzFile = ccall('gzopen', 'number', ['string', 'string'], ['input.gz', 'rb']); + var buffer = _malloc(BUFSIZE); + var chunks = []; + var total = 0; + var len; + while( (len = ccall('gzread', 'number', ['number', 'number', 'number'], [gzFile, buffer, BUFSIZE])) > 0) { + chunks.push(new Uint8Array(len)); + chunks[chunks.length-1].set(HEAPU8.subarray(buffer, buffer+len)); + total += len; + } + ccall('gzclose', 'number', ['number'], [gzFile]); + FS.unlink('input.gz'); + _free(buffer); + var ret = new Uint8Array(total); + var curr = 0; + for (var i = 0; i < chunks.length; i++) { + ret.set(chunks[i], curr); + curr += chunks[i].length; + } + return ret; +}; + + + + return { + initwcs: Module.cwrap('initwcs', 'number', ['string', 'number']), + wcssys: Module.cwrap('wcssys', 'string', ['number', 'string']), + wcsunits: Module.cwrap('wcsunits', 'string', ['number', 'string']), + pix2wcs: Module.cwrap('pix2wcsstr', 'string', ['number', 'number', 'number']), + wcs2pix: Module.cwrap('wcs2pixstr', 'string', ['number', 'number', 'number']), + reg2wcs: Module.cwrap('reg2wcsstr', 'string', ['number', 'string']), + saostrtod: Module.cwrap('saostrtod', 'number', ['string']), + zscale: Module.cwrap('zscale', 'string', ['number', 'number', 'number', 'number', 'number', 'number']), + arrfile: Module["arrfile"], + gzopen: Module.cwrap('gzopen', 'number', ['string', 'string']), + gzread: Module.cwrap('gzread', 'number', ['number', 'number', 'number']), + gzwrite: Module.cwrap('gzwrite', 'number', ['number', 'number', 'number']), + gzclose: Module.cwrap('gzclose', 'number', ['number']), + gzseek: Module.cwrap('gzseek', 'number', ['number', 'number', 'number']), + compress: Module['gzcompress'], + decompress: Module['gzdecompress'] + }; +})(); + diff --git a/js9support.txt b/js9support.txt new file mode 100644 index 00000000..1119bee4 --- /dev/null +++ b/js9support.txt @@ -0,0 +1,6 @@ +css files in js9support.css: +css/jquery.contextMenu.css css/dhtmlwindow.css +js files in js9support.js: +js/jquery.min.js js/jquery.contextMenu.min.js js/jquery.flot.min.js js/jquery.flot.errorbars.min.js js/jquery.flot.selection.min.js js/flot-zoom.min.js js/sprintf.min.js js/dhtmlwindow.min.js js/dhtmlwindow_blurb.js js/fabric.min.js js/pako_inflate.min.js js/astroem.js +plugin files in js9plugins.js: +plugins/archive/archive.js plugins/fitsy/binning.js plugins/imexam/imexam.js plugins/imexam/encircled.js plugins/imexam/pixtable.js plugins/imexam/radproj.js plugins/imexam/reghist.js plugins/imexam/regstat.js plugins/imexam/xyproj.js plugins/imexam/3dplot.js diff --git a/jsarchive b/jsarchive new file mode 100755 index 00000000..036e04c2 --- /dev/null +++ b/jsarchive @@ -0,0 +1,24 @@ +#!/bin/bash + +ADIR="./archive" + +D=`date +%Y%m%d` + +AD=$ADIR/$D +N=0 +while [ -d $AD ]; do + N=`expr $N + 1` + AD=$ADIR/$D-$N +done +mkdir -p $AD + +echo "archive directory: $AD" +for f in $* +do + echo " archiving $f ..." + cp -p $f $AD/. +done + +cd $ADIR +rm -f latest +ln -s `basename $AD` latest diff --git a/minify b/minify new file mode 100755 index 00000000..be6ae7ac --- /dev/null +++ b/minify @@ -0,0 +1,13 @@ +#!/bin/bash + +if [ $# -lt 1 ]; then + echo "usage: $0 ifile1 ifile2 ... ifilen" + exit +fi + +while [ x"$1" != x ]; do + IFILE="$1" + OFILE=`echo $IFILE | sed 's/\.js$/\.min\.js/'` + java -jar ./compiler/compiler.jar --js $IFILE --js_output_file $OFILE + shift +done diff --git a/mkhelper b/mkhelper new file mode 100755 index 00000000..6e40ea49 --- /dev/null +++ b/mkhelper @@ -0,0 +1,142 @@ +#!/bin/bash +# set -x + +# get helper type +if [ x"$1" != x ]; then + HELPER="$1" + shift +else + echo "no helper type specified" + exit 1 +fi + +case "$HELPER" in + +none) +# js9Prefs.json: preference file +IPREFS=js9Prefs.json +OPREFS=js9Prefs-none.json +echo "Editing $IPREFS for no helper ..." +sed 's#\("helperType" *:.*"\)[^"]*\("\)#\1none\2#' < $IPREFS > $OPREFS && mv $IPREFS{,-orig} && mv $OPREFS $IPREFS +;; + +nodejs|socket.io) +# js9Prefs.json: preference file +IPREFS=js9Prefs.json +OPREFS=js9Prefs-nodejs.json +echo "Editing $IPREFS for Node.js helper ..." +sed 's#\("helperType" *:.*"\)[^"]*\("\)#\1nodejs\2#' < $IPREFS > $OPREFS && mv $IPREFS{,-orig} && mv $OPREFS $IPREFS +;; + +get|post) +if [ x"$1" != x ]; then + CGIDIR="$1" + shift +else + echo "CGI install directory not configured" + exit 1 +fi + +if [ x"$1" != x ]; then + CGIURL="$1" + shift +fi + +if [ x"$1" != x ]; then + CGIXPATH="$1" + shift +fi + +# js9Prefs.json: preference file +IPREFS=js9Prefs.json +OPREFS=js9Prefs-cgi.json + +# js9Prefs.cgi: CGI helper script +ICGISCR="js9Helper-default.cgi" +OCGISCR="js9Helper.cgi" + +# temp +myplugins="./analysis-plugins" + +echo "Editing $IPREFS for CGI ($HELPER) helper ..." + +jroot=`egrep "WEBDIR *=" Makefile | awk '{print $3}' | sed 's/^[ ]*//;s/[ ]*$//'` +if [ x"$jroot" != x ]; then + X="$X;s#^JROOT=\".*\"#JROOT=\"$jroot\"#" +fi + +jprefix=`egrep "^prefix *=" Makefile | awk '{print $3}' | sed 's/^[ ]*//;s/[ ]*$//'` +if [ x"$jprefix" != x ]; then + jbin="$jprefix/bin" +fi +if [ x"$jbin" != x ]; then + X="$X;s#^JBIN=\".*\"#JBIN=\"$jbin\"#" +fi + +jwrappers=`egrep '"analysisWrappers" *:' js9Prefs.json | awk -F: '{print $NF}' |sed 's/"//g' | sed 's/^[ ]*//;s/[,} ]*$//'` +if [ x"$jwrappers" != x ]; then + if [ x${jwrappers:0:1} != "x/" ]; then + jwrappers="${jroot}/${jwrappers}" + fi + X="$X;s#^JWRAPPERS=\".*\"#JWRAPPERS=\"$jwrappers\"#" +fi + +jplugins=`egrep '"analysisPlugins" *:' js9Prefs.json | awk -F: '{print $NF}' | sed 's/"//g' | sed 's/^[ ]*//;s/[,} ]*$//'` +if [ x"$jplugins" != x ]; then + if [ x${jplugins:0:1} != "x/" ]; then + jplugins="${jroot}/${jplugins}" + fi + X="$X;s#^JPLUGINS=\".*\"#JPLUGINS=\"$jplugins\"#" + if [ -d "$myplugins" -a -f "$myplugins/fits2png.json" ]; then + jfits2png=`egrep '"action" *:' $myplugins/fits2png.json | awk -F: '{print $NF}' | sed 's/"//g' | sed 's/^[ ]*//;s/[,} ]*$//'` + if [ x"$jfits2png" != x ]; then + X="$X;s#^JFITS2PNG=\".*\"#JFITS2PNG=\"$jfits2png\"#" + fi + fi +fi + +jdatapath=`egrep '"dataPath" *:' js9Prefs.json | \ +awk -F: ' +{ + for(i=2; i<=NF; i++){ + if( X != "" ){ + X = X ":" + } + X = X $i + } +} +END{ + print X +}' | \ +sed 's/"//g' | sed 's/^[ ]*//;s/[,} ]*$//'` +if [ x"$jdatapath" != x ]; then + # expand $HOME so that we can specify $HOME/Desktop, etc. + jdatapath=`echo $jdatapath | sed 's#\$HOME#'$HOME'#g'` + X="$X;s#^JDATAPATH=\".*\"#JDATAPATH=\"$jdatapath\"#" +fi + +if [ x"$CGIXPATH" != x ]; then + X="$X;s#^JXPATH=\".*\"#JXPATH=\"$CGIXPATH\"#" +fi + +echo "Creating $OCGISCR ..." +sed "$X" < $ICGISCR > $OCGISCR +chmod +x $OCGISCR + +# if CGIURL was not specified or was specified as the default, use the prefs val +if [ x"$CGIURL" = x ]; then + CGIURL=`egrep '"helperCGI" *:' js9Prefs.json | awk -F: '{print $NF}' | sed 's/"//g' | sed 's/^[ ]*//;s/[,} ]*$//'` + if [ x"$CGIURL" != x ]; then + if [ x${CGIURL:0:1} != "x/" ]; then + CGIURL="${jroot}/${CGIURL}" + fi + fi +fi + +echo "Editing $IPREFS for CGI ..." +sed 's#\("helperCGI" *:.*"\)[^"]*\("\)#\1'"$CGIURL"'/js9Helper.cgi\2#;s#\("helperType":.*"\)[^"]*\("\)#\1get\2#' < $IPREFS > $OPREFS && mv $IPREFS{,-orig} && mv $OPREFS $IPREFS +;; + +esac + +exit 0 diff --git a/mkjs9 b/mkjs9 new file mode 100755 index 00000000..844880ff --- /dev/null +++ b/mkjs9 @@ -0,0 +1,27 @@ +#!/bin/bash +# set -x + +WEBDIR="" +if [ x"$1" != x ]; then + WEBDIR="$1" +fi + +# js9: message script +IMSGSCR="js9.in" +OMSGSCR="js9" + +echo "generating $OMSGSCR for js9 messaging ..." +jtype=`egrep '"helperType" *:' js9Prefs.json | awk -F: '{print $NF}' | sed 's/"//g' | sed 's/^[ ]*//;s/[,} ]*$//'` +if [ x"$jtype" != x ]; then + echo "helper type: $jtype" + X="$X;s#^JTYPE=\".*\"#JTYPE=\"$jtype\"#" +fi +jport=`egrep '"helperPort" *:' js9Prefs.json | awk -F: '{print $2}' | sed 's/"//g' | sed 's/[,} ]*$//' | sed 's/^ *//;s/ *$//'` +if [ x"$jport" != x ]; then + X="$X;s#^JPORT=\".*\"#JPORT=\"$jport\"#" +fi +X="$X;s#^WEBDIR=\".*\"#WEBDIR=\"$WEBDIR\"#" +sed "$X" < $IMSGSCR > $OMSGSCR +chmod +x $OMSGSCR + +exit 0 diff --git a/nnode b/nnode new file mode 100755 index 00000000..997f1ea2 --- /dev/null +++ b/nnode @@ -0,0 +1,54 @@ +#!/bin/sh + +# defaults +DEFPREFS="js9Prefs.json" +HELPER="./js9Helper.js" +LOG="./node.log" + +# process command line switches +while [ x"$1" != x ]; do + case $1 in + -h) HELPER="$2" + shift + shift + if [ ! -r "$HELPER" ]; then + echo "ERROR: can't find prefs file: $HELPER" + exit 1 + fi + ;; + + -l) LOG="$2" + shift + shift + ;; + + -p) PREFS="$2" + shift + shift + if [ -r "$PREFS" ]; then + if [ -f $DEFPREFS ]; then + X=`diff -q $DEFPREFS $PREFS` + if [ x"$X" != x ]; then + mv $DEFPREFS $DEFPREFS-prev + ln -s $PREFS $DEFPREFS + fi + else + ln -s $PREFS $DEFPREFS + fi + PSTR="with prefs file $PREFS" + else + echo "ERROR: can't find prefs file: $PREFS" + exit 1 + fi + ;; + + *) echo "ERROR: unknown argument: $1" + exit 1 + ;; + esac +done + +killp js9Helper.js >& /dev/null + +echo "starting node $HELPER $PSTR" +node $HELPER 2>&1 > $LOG & diff --git a/node_modules/node-uuid/.npmignore b/node_modules/node-uuid/.npmignore new file mode 100644 index 00000000..fd4f2b06 --- /dev/null +++ b/node_modules/node-uuid/.npmignore @@ -0,0 +1,2 @@ +node_modules +.DS_Store diff --git a/node_modules/node-uuid/LICENSE.md b/node_modules/node-uuid/LICENSE.md new file mode 100644 index 00000000..f039427f --- /dev/null +++ b/node_modules/node-uuid/LICENSE.md @@ -0,0 +1,2 @@ +Copyright (c) 2010-2012 Robert Kieffer +MIT License - http://opensource.org/licenses/mit-license.php diff --git a/node_modules/node-uuid/README.md b/node_modules/node-uuid/README.md new file mode 100644 index 00000000..e436a89f --- /dev/null +++ b/node_modules/node-uuid/README.md @@ -0,0 +1,207 @@ +# node-uuid + +Simple, fast generation of [RFC4122](http://www.ietf.org/rfc/rfc4122.txt) UUIDS. + +Features: + +* Generate RFC4122 version 1 or version 4 UUIDs +* Runs in node.js and all browsers. +* Registered as a [ComponentJS](https://github.com/component/component) [component](https://github.com/component/component/wiki/Components) ('broofa/node-uuid'). +* Cryptographically strong random # generation on supporting platforms +* 1.1K minified and gzip'ed (Want something smaller? Check this [crazy shit](https://gist.github.com/982883) out! ) +* [Annotated source code](http://broofa.github.com/node-uuid/docs/uuid.html) + +## Getting Started + +Install it in your browser: + +```html + +``` + +Or in node.js: + +``` +npm install node-uuid +``` + +```javascript +var uuid = require('node-uuid'); +``` + +Then create some ids ... + +```javascript +// Generate a v1 (time-based) id +uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' + +// Generate a v4 (random) id +uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1' +``` + +## API + +### uuid.v1([`options` [, `buffer` [, `offset`]]]) + +Generate and return a RFC4122 v1 (timestamp-based) UUID. + +* `options` - (Object) Optional uuid state to apply. Properties may include: + + * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomly generated ID. See note 1. + * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence. Default: An internally maintained clockseq is used. + * `msecs` - (Number | Date) Time in milliseconds since unix Epoch. Default: The current time is used. + * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2. + +* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. +* `offset` - (Number) Starting index in `buffer` at which to begin writing. + +Returns `buffer`, if specified, otherwise the string form of the UUID + +Notes: + +1. The randomly generated node id is only guaranteed to stay constant for the lifetime of the current JS runtime. (Future versions of this module may use persistent storage mechanisms to extend this guarantee.) + +Example: Generate string UUID with fully-specified options + +```javascript +uuid.v1({ + node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab], + clockseq: 0x1234, + msecs: new Date('2011-11-01').getTime(), + nsecs: 5678 +}); // -> "710b962e-041c-11e1-9234-0123456789ab" +``` + +Example: In-place generation of two binary IDs + +```javascript +// Generate two ids in an array +var arr = new Array(32); // -> [] +uuid.v1(null, arr, 0); // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15] +uuid.v1(null, arr, 16); // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15 02 a3 1c b0 14 32 11 e1 85 58 0b 48 8e 4f c1 15] + +// Optionally use uuid.unparse() to get stringify the ids +uuid.unparse(buffer); // -> '02a2ce90-1432-11e1-8558-0b488e4fc115' +uuid.unparse(buffer, 16) // -> '02a31cb0-1432-11e1-8558-0b488e4fc115' +``` + +### uuid.v4([`options` [, `buffer` [, `offset`]]]) + +Generate and return a RFC4122 v4 UUID. + +* `options` - (Object) Optional uuid state to apply. Properties may include: + + * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values + * `rng` - (Function) Random # generator to use. Set to one of the built-in generators - `uuid.mathRNG` (all platforms), `uuid.nodeRNG` (node.js only), `uuid.whatwgRNG` (WebKit only) - or a custom function that returns an array[16] of byte values. + +* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. +* `offset` - (Number) Starting index in `buffer` at which to begin writing. + +Returns `buffer`, if specified, otherwise the string form of the UUID + +Example: Generate string UUID with fully-specified options + +```javascript +uuid.v4({ + random: [ + 0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea, + 0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36 + ] +}); +// -> "109156be-c4fb-41ea-b1b4-efe1671c5836" +``` + +Example: Generate two IDs in a single buffer + +```javascript +var buffer = new Array(32); // (or 'new Buffer' in node.js) +uuid.v4(null, buffer, 0); +uuid.v4(null, buffer, 16); +``` + +### uuid.parse(id[, buffer[, offset]]) +### uuid.unparse(buffer[, offset]) + +Parse and unparse UUIDs + + * `id` - (String) UUID(-like) string + * `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. Default: A new Array or Buffer is used + * `offset` - (Number) Starting index in `buffer` at which to begin writing. Default: 0 + +Example parsing and unparsing a UUID string + +```javascript +var bytes = uuid.parse('797ff043-11eb-11e1-80d6-510998755d10'); // -> +var string = uuid.unparse(bytes); // -> '797ff043-11eb-11e1-80d6-510998755d10' +``` + +### uuid.noConflict() + +(Browsers only) Set `uuid` property back to it's previous value. + +Returns the node-uuid object. + +Example: + +```javascript +var myUuid = uuid.noConflict(); +myUuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' +``` + +## Deprecated APIs + +Support for the following v1.2 APIs is available in v1.3, but is deprecated and will be removed in the next major version. + +### uuid([format [, buffer [, offset]]]) + +uuid() has become uuid.v4(), and the `format` argument is now implicit in the `buffer` argument. (i.e. if you specify a buffer, the format is assumed to be binary). + +### uuid.BufferClass + +The class of container created when generating binary uuid data if no buffer argument is specified. This is expected to go away, with no replacement API. + +## Testing + +In node.js + +``` +> cd test +> node test.js +``` + +In Browser + +``` +open test/test.html +``` + +### Benchmarking + +Requires node.js + +``` +npm install uuid uuid-js +node benchmark/benchmark.js +``` + +For a more complete discussion of node-uuid performance, please see the `benchmark/README.md` file, and the [benchmark wiki](https://github.com/broofa/node-uuid/wiki/Benchmark) + +For browser performance [checkout the JSPerf tests](http://jsperf.com/node-uuid-performance). + +## Release notes + +### 1.4.0 + +* Improved module context detection +* Removed public RNG functions + +### 1.3.2 + +* Improve tests and handling of v1() options (Issue #24) +* Expose RNG option to allow for perf testing with different generators + +### 1.3.0 + +* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)! +* Support for node.js crypto API +* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code diff --git a/node_modules/node-uuid/benchmark/README.md b/node_modules/node-uuid/benchmark/README.md new file mode 100644 index 00000000..aaeb2ea0 --- /dev/null +++ b/node_modules/node-uuid/benchmark/README.md @@ -0,0 +1,53 @@ +# node-uuid Benchmarks + +### Results + +To see the results of our benchmarks visit https://github.com/broofa/node-uuid/wiki/Benchmark + +### Run them yourself + +node-uuid comes with some benchmarks to measure performance of generating UUIDs. These can be run using node.js. node-uuid is being benchmarked against some other uuid modules, that are available through npm namely `uuid` and `uuid-js`. + +To prepare and run the benchmark issue; + +``` +npm install uuid uuid-js +node benchmark/benchmark.js +``` + +You'll see an output like this one: + +``` +# v4 +nodeuuid.v4(): 854700 uuids/second +nodeuuid.v4('binary'): 788643 uuids/second +nodeuuid.v4('binary', buffer): 1336898 uuids/second +uuid(): 479386 uuids/second +uuid('binary'): 582072 uuids/second +uuidjs.create(4): 312304 uuids/second + +# v1 +nodeuuid.v1(): 938086 uuids/second +nodeuuid.v1('binary'): 683060 uuids/second +nodeuuid.v1('binary', buffer): 1644736 uuids/second +uuidjs.create(1): 190621 uuids/second +``` + +* The `uuid()` entries are for Nikhil Marathe's [uuid module](https://bitbucket.org/nikhilm/uuidjs) which is a wrapper around the native libuuid library. +* The `uuidjs()` entries are for Patrick Negri's [uuid-js module](https://github.com/pnegri/uuid-js) which is a pure javascript implementation based on [UUID.js](https://github.com/LiosK/UUID.js) by LiosK. + +If you want to get more reliable results you can run the benchmark multiple times and write the output into a log file: + +``` +for i in {0..9}; do node benchmark/benchmark.js >> benchmark/bench_0.4.12.log; done; +``` + +If you're interested in how performance varies between different node versions, you can issue the above command multiple times. + +You can then use the shell script `bench.sh` provided in this directory to calculate the averages over all benchmark runs and draw a nice plot: + +``` +(cd benchmark/ && ./bench.sh) +``` + +This assumes you have [gnuplot](http://www.gnuplot.info/) and [ImageMagick](http://www.imagemagick.org/) installed. You'll find a nice `bench.png` graph in the `benchmark/` directory then. diff --git a/node_modules/node-uuid/benchmark/bench.gnu b/node_modules/node-uuid/benchmark/bench.gnu new file mode 100644 index 00000000..a342fbbe --- /dev/null +++ b/node_modules/node-uuid/benchmark/bench.gnu @@ -0,0 +1,174 @@ +#!/opt/local/bin/gnuplot -persist +# +# +# G N U P L O T +# Version 4.4 patchlevel 3 +# last modified March 2011 +# System: Darwin 10.8.0 +# +# Copyright (C) 1986-1993, 1998, 2004, 2007-2010 +# Thomas Williams, Colin Kelley and many others +# +# gnuplot home: http://www.gnuplot.info +# faq, bugs, etc: type "help seeking-assistance" +# immediate help: type "help" +# plot window: hit 'h' +set terminal postscript eps noenhanced defaultplex \ + leveldefault color colortext \ + solid linewidth 1.2 butt noclip \ + palfuncparam 2000,0.003 \ + "Helvetica" 14 +set output 'bench.eps' +unset clip points +set clip one +unset clip two +set bar 1.000000 front +set border 31 front linetype -1 linewidth 1.000 +set xdata +set ydata +set zdata +set x2data +set y2data +set timefmt x "%d/%m/%y,%H:%M" +set timefmt y "%d/%m/%y,%H:%M" +set timefmt z "%d/%m/%y,%H:%M" +set timefmt x2 "%d/%m/%y,%H:%M" +set timefmt y2 "%d/%m/%y,%H:%M" +set timefmt cb "%d/%m/%y,%H:%M" +set boxwidth +set style fill empty border +set style rectangle back fc lt -3 fillstyle solid 1.00 border lt -1 +set style circle radius graph 0.02, first 0, 0 +set dummy x,y +set format x "% g" +set format y "% g" +set format x2 "% g" +set format y2 "% g" +set format z "% g" +set format cb "% g" +set angles radians +unset grid +set key title "" +set key outside left top horizontal Right noreverse enhanced autotitles columnhead nobox +set key noinvert samplen 4 spacing 1 width 0 height 0 +set key maxcolumns 2 maxrows 0 +unset label +unset arrow +set style increment default +unset style line +set style line 1 linetype 1 linewidth 2.000 pointtype 1 pointsize default pointinterval 0 +unset style arrow +set style histogram clustered gap 2 title offset character 0, 0, 0 +unset logscale +set offsets graph 0.05, 0.15, 0, 0 +set pointsize 1.5 +set pointintervalbox 1 +set encoding default +unset polar +unset parametric +unset decimalsign +set view 60, 30, 1, 1 +set samples 100, 100 +set isosamples 10, 10 +set surface +unset contour +set clabel '%8.3g' +set mapping cartesian +set datafile separator whitespace +unset hidden3d +set cntrparam order 4 +set cntrparam linear +set cntrparam levels auto 5 +set cntrparam points 5 +set size ratio 0 1,1 +set origin 0,0 +set style data points +set style function lines +set xzeroaxis linetype -2 linewidth 1.000 +set yzeroaxis linetype -2 linewidth 1.000 +set zzeroaxis linetype -2 linewidth 1.000 +set x2zeroaxis linetype -2 linewidth 1.000 +set y2zeroaxis linetype -2 linewidth 1.000 +set ticslevel 0.5 +set mxtics default +set mytics default +set mztics default +set mx2tics default +set my2tics default +set mcbtics default +set xtics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 +set xtics norangelimit +set xtics () +set ytics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 +set ytics autofreq norangelimit +set ztics border in scale 1,0.5 nomirror norotate offset character 0, 0, 0 +set ztics autofreq norangelimit +set nox2tics +set noy2tics +set cbtics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 +set cbtics autofreq norangelimit +set title "" +set title offset character 0, 0, 0 font "" norotate +set timestamp bottom +set timestamp "" +set timestamp offset character 0, 0, 0 font "" norotate +set rrange [ * : * ] noreverse nowriteback # (currently [8.98847e+307:-8.98847e+307] ) +set autoscale rfixmin +set autoscale rfixmax +set trange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] ) +set autoscale tfixmin +set autoscale tfixmax +set urange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) +set autoscale ufixmin +set autoscale ufixmax +set vrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) +set autoscale vfixmin +set autoscale vfixmax +set xlabel "" +set xlabel offset character 0, 0, 0 font "" textcolor lt -1 norotate +set x2label "" +set x2label offset character 0, 0, 0 font "" textcolor lt -1 norotate +set xrange [ * : * ] noreverse nowriteback # (currently [-0.150000:3.15000] ) +set autoscale xfixmin +set autoscale xfixmax +set x2range [ * : * ] noreverse nowriteback # (currently [0.00000:3.00000] ) +set autoscale x2fixmin +set autoscale x2fixmax +set ylabel "" +set ylabel offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270 +set y2label "" +set y2label offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270 +set yrange [ 0.00000 : 1.90000e+06 ] noreverse nowriteback # (currently [:] ) +set autoscale yfixmin +set autoscale yfixmax +set y2range [ * : * ] noreverse nowriteback # (currently [0.00000:1.90000e+06] ) +set autoscale y2fixmin +set autoscale y2fixmax +set zlabel "" +set zlabel offset character 0, 0, 0 font "" textcolor lt -1 norotate +set zrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) +set autoscale zfixmin +set autoscale zfixmax +set cblabel "" +set cblabel offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270 +set cbrange [ * : * ] noreverse nowriteback # (currently [8.98847e+307:-8.98847e+307] ) +set autoscale cbfixmin +set autoscale cbfixmax +set zero 1e-08 +set lmargin -1 +set bmargin -1 +set rmargin -1 +set tmargin -1 +set pm3d explicit at s +set pm3d scansautomatic +set pm3d interpolate 1,1 flush begin noftriangles nohidden3d corners2color mean +set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB +set palette rgbformulae 7, 5, 15 +set colorbox default +set colorbox vertical origin screen 0.9, 0.2, 0 size screen 0.05, 0.6, 0 front bdefault +set loadpath +set fontpath +set fit noerrorvariables +GNUTERM = "aqua" +plot 'bench_results.txt' using 2:xticlabel(1) w lp lw 2, '' using 3:xticlabel(1) w lp lw 2, '' using 4:xticlabel(1) w lp lw 2, '' using 5:xticlabel(1) w lp lw 2, '' using 6:xticlabel(1) w lp lw 2, '' using 7:xticlabel(1) w lp lw 2, '' using 8:xticlabel(1) w lp lw 2, '' using 9:xticlabel(1) w lp lw 2 +# EOF diff --git a/node_modules/node-uuid/benchmark/bench.sh b/node_modules/node-uuid/benchmark/bench.sh new file mode 100755 index 00000000..d870a0cb --- /dev/null +++ b/node_modules/node-uuid/benchmark/bench.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# for a given node version run: +# for i in {0..9}; do node benchmark.js >> bench_0.6.2.log; done; + +PATTERNS=('nodeuuid.v1()' "nodeuuid.v1('binary'," 'nodeuuid.v4()' "nodeuuid.v4('binary'," "uuid()" "uuid('binary')" 'uuidjs.create(1)' 'uuidjs.create(4)' '140byte') +FILES=(node_uuid_v1_string node_uuid_v1_buf node_uuid_v4_string node_uuid_v4_buf libuuid_v4_string libuuid_v4_binary uuidjs_v1_string uuidjs_v4_string 140byte_es) +INDICES=(2 3 2 3 2 2 2 2 2) +VERSIONS=$( ls bench_*.log | sed -e 's/^bench_\([0-9\.]*\)\.log/\1/' | tr "\\n" " " ) +TMPJOIN="tmp_join" +OUTPUT="bench_results.txt" + +for I in ${!FILES[*]}; do + F=${FILES[$I]} + P=${PATTERNS[$I]} + INDEX=${INDICES[$I]} + echo "version $F" > $F + for V in $VERSIONS; do + (VAL=$( grep "$P" bench_$V.log | LC_ALL=en_US awk '{ sum += $'$INDEX' } END { print sum/NR }' ); echo $V $VAL) >> $F + done + if [ $I == 0 ]; then + cat $F > $TMPJOIN + else + join $TMPJOIN $F > $OUTPUT + cp $OUTPUT $TMPJOIN + fi + rm $F +done + +rm $TMPJOIN + +gnuplot bench.gnu +convert -density 200 -resize 800x560 -flatten bench.eps bench.png +rm bench.eps diff --git a/node_modules/node-uuid/benchmark/benchmark-native.c b/node_modules/node-uuid/benchmark/benchmark-native.c new file mode 100644 index 00000000..dbfc75f6 --- /dev/null +++ b/node_modules/node-uuid/benchmark/benchmark-native.c @@ -0,0 +1,34 @@ +/* +Test performance of native C UUID generation + +To Compile: cc -luuid benchmark-native.c -o benchmark-native +*/ + +#include +#include +#include +#include + +int main() { + uuid_t myid; + char buf[36+1]; + int i; + struct timeval t; + double start, finish; + + gettimeofday(&t, NULL); + start = t.tv_sec + t.tv_usec/1e6; + + int n = 2e5; + for (i = 0; i < n; i++) { + uuid_generate(myid); + uuid_unparse(myid, buf); + } + + gettimeofday(&t, NULL); + finish = t.tv_sec + t.tv_usec/1e6; + double dur = finish - start; + + printf("%d uuids/sec", (int)(n/dur)); + return 0; +} diff --git a/node_modules/node-uuid/benchmark/benchmark.js b/node_modules/node-uuid/benchmark/benchmark.js new file mode 100644 index 00000000..40e6efbe --- /dev/null +++ b/node_modules/node-uuid/benchmark/benchmark.js @@ -0,0 +1,84 @@ +try { + var nodeuuid = require('../uuid'); +} catch (e) { + console.error('node-uuid require failed - skipping tests'); +} + +try { + var uuid = require('uuid'); +} catch (e) { + console.error('uuid require failed - skipping tests'); +} + +try { + var uuidjs = require('uuid-js'); +} catch (e) { + console.error('uuid-js require failed - skipping tests'); +} + +var N = 5e5; + +function rate(msg, t) { + console.log(msg + ': ' + + (N / (Date.now() - t) * 1e3 | 0) + + ' uuids/second'); +} + +console.log('# v4'); + +// node-uuid - string form +if (nodeuuid) { + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4(); + rate('nodeuuid.v4() - using node.js crypto RNG', t); + + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4({rng: nodeuuid.mathRNG}); + rate('nodeuuid.v4() - using Math.random() RNG', t); + + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4('binary'); + rate('nodeuuid.v4(\'binary\')', t); + + var buffer = new nodeuuid.BufferClass(16); + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4('binary', buffer); + rate('nodeuuid.v4(\'binary\', buffer)', t); +} + +// libuuid - string form +if (uuid) { + for (var i = 0, t = Date.now(); i < N; i++) uuid(); + rate('uuid()', t); + + for (var i = 0, t = Date.now(); i < N; i++) uuid('binary'); + rate('uuid(\'binary\')', t); +} + +// uuid-js - string form +if (uuidjs) { + for (var i = 0, t = Date.now(); i < N; i++) uuidjs.create(4); + rate('uuidjs.create(4)', t); +} + +// 140byte.es +for (var i = 0, t = Date.now(); i < N; i++) 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(s,r){r=Math.random()*16|0;return (s=='x'?r:r&0x3|0x8).toString(16)}); +rate('140byte.es_v4', t); + +console.log(''); +console.log('# v1'); + +// node-uuid - v1 string form +if (nodeuuid) { + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1(); + rate('nodeuuid.v1()', t); + + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1('binary'); + rate('nodeuuid.v1(\'binary\')', t); + + var buffer = new nodeuuid.BufferClass(16); + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1('binary', buffer); + rate('nodeuuid.v1(\'binary\', buffer)', t); +} + +// uuid-js - v1 string form +if (uuidjs) { + for (var i = 0, t = Date.now(); i < N; i++) uuidjs.create(1); + rate('uuidjs.create(1)', t); +} diff --git a/node_modules/node-uuid/component.json b/node_modules/node-uuid/component.json new file mode 100644 index 00000000..ace21348 --- /dev/null +++ b/node_modules/node-uuid/component.json @@ -0,0 +1,18 @@ +{ + "name": "node-uuid", + "repo": "broofa/node-uuid", + "description": "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.", + "version": "1.4.0", + "author": "Robert Kieffer ", + "contributors": [ + {"name": "Christoph Tavan ", "github": "https://github.com/ctavan"} + ], + "keywords": ["uuid", "guid", "rfc4122"], + "dependencies": {}, + "development": {}, + "main": "uuid.js", + "scripts": [ + "uuid.js" + ], + "license": "MIT" +} \ No newline at end of file diff --git a/node_modules/node-uuid/package.json b/node_modules/node-uuid/package.json new file mode 100644 index 00000000..8e7a62c7 --- /dev/null +++ b/node_modules/node-uuid/package.json @@ -0,0 +1,38 @@ +{ + "name": "node-uuid", + "description": "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.", + "url": "http://github.com/broofa/node-uuid", + "keywords": [ + "uuid", + "guid", + "rfc4122" + ], + "author": { + "name": "Robert Kieffer", + "email": "robert@broofa.com" + }, + "contributors": [ + { + "name": "Christoph Tavan", + "email": "dev@tavan.de" + } + ], + "lib": ".", + "main": "./uuid.js", + "repository": { + "type": "git", + "url": "https://github.com/broofa/node-uuid.git" + }, + "version": "1.4.1", + "readme": "# node-uuid\n\nSimple, fast generation of [RFC4122](http://www.ietf.org/rfc/rfc4122.txt) UUIDS.\n\nFeatures:\n\n* Generate RFC4122 version 1 or version 4 UUIDs\n* Runs in node.js and all browsers.\n* Registered as a [ComponentJS](https://github.com/component/component) [component](https://github.com/component/component/wiki/Components) ('broofa/node-uuid').\n* Cryptographically strong random # generation on supporting platforms\n* 1.1K minified and gzip'ed (Want something smaller? Check this [crazy shit](https://gist.github.com/982883) out! )\n* [Annotated source code](http://broofa.github.com/node-uuid/docs/uuid.html)\n\n## Getting Started\n\nInstall it in your browser:\n\n```html\n\n```\n\nOr in node.js:\n\n```\nnpm install node-uuid\n```\n\n```javascript\nvar uuid = require('node-uuid');\n```\n\nThen create some ids ...\n\n```javascript\n// Generate a v1 (time-based) id\nuuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'\n\n// Generate a v4 (random) id\nuuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'\n```\n\n## API\n\n### uuid.v1([`options` [, `buffer` [, `offset`]]])\n\nGenerate and return a RFC4122 v1 (timestamp-based) UUID.\n\n* `options` - (Object) Optional uuid state to apply. Properties may include:\n\n * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomly generated ID. See note 1.\n * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence. Default: An internally maintained clockseq is used.\n * `msecs` - (Number | Date) Time in milliseconds since unix Epoch. Default: The current time is used.\n * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2.\n\n* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.\n* `offset` - (Number) Starting index in `buffer` at which to begin writing.\n\nReturns `buffer`, if specified, otherwise the string form of the UUID\n\nNotes:\n\n1. The randomly generated node id is only guaranteed to stay constant for the lifetime of the current JS runtime. (Future versions of this module may use persistent storage mechanisms to extend this guarantee.)\n\nExample: Generate string UUID with fully-specified options\n\n```javascript\nuuid.v1({\n node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],\n clockseq: 0x1234,\n msecs: new Date('2011-11-01').getTime(),\n nsecs: 5678\n}); // -> \"710b962e-041c-11e1-9234-0123456789ab\"\n```\n\nExample: In-place generation of two binary IDs\n\n```javascript\n// Generate two ids in an array\nvar arr = new Array(32); // -> []\nuuid.v1(null, arr, 0); // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15]\nuuid.v1(null, arr, 16); // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15 02 a3 1c b0 14 32 11 e1 85 58 0b 48 8e 4f c1 15]\n\n// Optionally use uuid.unparse() to get stringify the ids\nuuid.unparse(buffer); // -> '02a2ce90-1432-11e1-8558-0b488e4fc115'\nuuid.unparse(buffer, 16) // -> '02a31cb0-1432-11e1-8558-0b488e4fc115'\n```\n\n### uuid.v4([`options` [, `buffer` [, `offset`]]])\n\nGenerate and return a RFC4122 v4 UUID.\n\n* `options` - (Object) Optional uuid state to apply. Properties may include:\n\n * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values\n * `rng` - (Function) Random # generator to use. Set to one of the built-in generators - `uuid.mathRNG` (all platforms), `uuid.nodeRNG` (node.js only), `uuid.whatwgRNG` (WebKit only) - or a custom function that returns an array[16] of byte values.\n\n* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.\n* `offset` - (Number) Starting index in `buffer` at which to begin writing.\n\nReturns `buffer`, if specified, otherwise the string form of the UUID\n\nExample: Generate string UUID with fully-specified options\n\n```javascript\nuuid.v4({\n random: [\n 0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea,\n 0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36\n ]\n});\n// -> \"109156be-c4fb-41ea-b1b4-efe1671c5836\"\n```\n\nExample: Generate two IDs in a single buffer\n\n```javascript\nvar buffer = new Array(32); // (or 'new Buffer' in node.js)\nuuid.v4(null, buffer, 0);\nuuid.v4(null, buffer, 16);\n```\n\n### uuid.parse(id[, buffer[, offset]])\n### uuid.unparse(buffer[, offset])\n\nParse and unparse UUIDs\n\n * `id` - (String) UUID(-like) string\n * `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. Default: A new Array or Buffer is used\n * `offset` - (Number) Starting index in `buffer` at which to begin writing. Default: 0\n\nExample parsing and unparsing a UUID string\n\n```javascript\nvar bytes = uuid.parse('797ff043-11eb-11e1-80d6-510998755d10'); // -> \nvar string = uuid.unparse(bytes); // -> '797ff043-11eb-11e1-80d6-510998755d10'\n```\n\n### uuid.noConflict()\n\n(Browsers only) Set `uuid` property back to it's previous value.\n\nReturns the node-uuid object.\n\nExample:\n\n```javascript\nvar myUuid = uuid.noConflict();\nmyUuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'\n```\n\n## Deprecated APIs\n\nSupport for the following v1.2 APIs is available in v1.3, but is deprecated and will be removed in the next major version.\n\n### uuid([format [, buffer [, offset]]])\n\nuuid() has become uuid.v4(), and the `format` argument is now implicit in the `buffer` argument. (i.e. if you specify a buffer, the format is assumed to be binary).\n\n### uuid.BufferClass\n\nThe class of container created when generating binary uuid data if no buffer argument is specified. This is expected to go away, with no replacement API.\n\n## Testing\n\nIn node.js\n\n```\n> cd test\n> node test.js\n```\n\nIn Browser\n\n```\nopen test/test.html\n```\n\n### Benchmarking\n\nRequires node.js\n\n```\nnpm install uuid uuid-js\nnode benchmark/benchmark.js\n```\n\nFor a more complete discussion of node-uuid performance, please see the `benchmark/README.md` file, and the [benchmark wiki](https://github.com/broofa/node-uuid/wiki/Benchmark)\n\nFor browser performance [checkout the JSPerf tests](http://jsperf.com/node-uuid-performance).\n\n## Release notes\n\n### 1.4.0\n\n* Improved module context detection\n* Removed public RNG functions\n\n### 1.3.2\n\n* Improve tests and handling of v1() options (Issue #24)\n* Expose RNG option to allow for perf testing with different generators\n\n### 1.3.0\n\n* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)!\n* Support for node.js crypto API\n* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/broofa/node-uuid/issues" + }, + "_id": "node-uuid@1.4.1", + "dist": { + "shasum": "f542a538b863ade9a3fbe6b875a4f6ed53edfe54" + }, + "_from": "node-uuid@", + "_resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz" +} diff --git a/node_modules/node-uuid/uuid.js b/node_modules/node-uuid/uuid.js new file mode 100644 index 00000000..2fac6dc4 --- /dev/null +++ b/node_modules/node-uuid/uuid.js @@ -0,0 +1,245 @@ +// uuid.js +// +// Copyright (c) 2010-2012 Robert Kieffer +// MIT License - http://opensource.org/licenses/mit-license.php + +(function() { + var _global = this; + + // Unique ID creation requires a high quality random # generator. We feature + // detect to determine the best RNG source, normalizing to a function that + // returns 128-bits of randomness, since that's what's usually required + var _rng; + + // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html + // + // Moderately fast, high quality + if (typeof(require) == 'function') { + try { + var _rb = require('crypto').randomBytes; + _rng = _rb && function() {return _rb(16);}; + } catch(e) {} + } + + if (!_rng && _global.crypto && crypto.getRandomValues) { + // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto + // + // Moderately fast, high quality + var _rnds8 = new Uint8Array(16); + _rng = function whatwgRNG() { + crypto.getRandomValues(_rnds8); + return _rnds8; + }; + } + + if (!_rng) { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var _rnds = new Array(16); + _rng = function() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return _rnds; + }; + } + + // Buffer class to use + var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array; + + // Maps for number <-> hex string conversion + var _byteToHex = []; + var _hexToByte = {}; + for (var i = 0; i < 256; i++) { + _byteToHex[i] = (i + 0x100).toString(16).substr(1); + _hexToByte[_byteToHex[i]] = i; + } + + // **`parse()` - Parse a UUID into it's component bytes** + function parse(s, buf, offset) { + var i = (buf && offset) || 0, ii = 0; + + buf = buf || []; + s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) { + if (ii < 16) { // Don't overflow! + buf[i + ii++] = _hexToByte[oct]; + } + }); + + // Zero out remaining bytes if string was short + while (ii < 16) { + buf[i + ii++] = 0; + } + + return buf; + } + + // **`unparse()` - Convert UUID byte array (ala parse()) into a string** + function unparse(buf, offset) { + var i = offset || 0, bth = _byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]]; + } + + // **`v1()` - Generate time-based UUID** + // + // Inspired by https://github.com/LiosK/UUID.js + // and http://docs.python.org/library/uuid.html + + // random #'s we need to init node and clockseq + var _seedBytes = _rng(); + + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + var _nodeId = [ + _seedBytes[0] | 0x01, + _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5] + ]; + + // Per 4.2.2, randomize (14 bit) clockseq + var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; + + // Previous uuid creation time + var _lastMSecs = 0, _lastNSecs = 0; + + // See https://github.com/broofa/node-uuid for API details + function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + + var clockseq = options.clockseq != null ? options.clockseq : _clockseq; + + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + var msecs = options.msecs != null ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq == null) { + clockseq = clockseq + 1 & 0x3fff; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { + nsecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; + + // `time_low` + var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; + + // `time_mid` + var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; + + // `time_high_and_version` + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + b[i++] = tmh >>> 16 & 0xff; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 0x80; + + // `clock_seq_low` + b[i++] = clockseq & 0xff; + + // `node` + var node = options.node || _nodeId; + for (var n = 0; n < 6; n++) { + b[i + n] = node[n]; + } + + return buf ? buf : unparse(b); + } + + // **`v4()` - Generate random UUID** + + // See https://github.com/broofa/node-uuid for API details + function v4(options, buf, offset) { + // Deprecated - 'format' argument, as supported in v1.2 + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options == 'binary' ? new BufferClass(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || _rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ii++) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || unparse(rnds); + } + + // Export public API + var uuid = v4; + uuid.v1 = v1; + uuid.v4 = v4; + uuid.parse = parse; + uuid.unparse = unparse; + uuid.BufferClass = BufferClass; + + if (typeof define === 'function' && define.amd) { + // Publish as AMD module + define(function() {return uuid;}); + } else if (typeof(module) != 'undefined' && module.exports) { + // Publish as node.js module + module.exports = uuid; + } else { + // Publish as global (in browsers) + var _previousRoot = _global.uuid; + + // **`noConflict()` - (browser only) to reset global 'uuid' var** + uuid.noConflict = function() { + _global.uuid = _previousRoot; + return uuid; + }; + + _global.uuid = uuid; + } +}).call(this); diff --git a/node_modules/socket.io/.npmignore b/node_modules/socket.io/.npmignore new file mode 100644 index 00000000..39e9864f --- /dev/null +++ b/node_modules/socket.io/.npmignore @@ -0,0 +1,3 @@ +support +test +examples diff --git a/node_modules/socket.io/.travis.yml b/node_modules/socket.io/.travis.yml new file mode 100644 index 00000000..56eca033 --- /dev/null +++ b/node_modules/socket.io/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - 0.6 + +notifications: + irc: "irc.freenode.org#socket.io" diff --git a/node_modules/socket.io/History.md b/node_modules/socket.io/History.md new file mode 100644 index 00000000..05ed0066 --- /dev/null +++ b/node_modules/socket.io/History.md @@ -0,0 +1,325 @@ + +0.9.16 / 2013-06-06 +=================== + + * transports: added tests for htmlfile escaping/unescaping + +0.9.15 / 2013-06-06 +=================== + + * transports: added escaping to htmlfile (fixes #1251) + +0.9.14 / 2013-03-29 +=================== + + * manager: fix memory leak with SSL [jpallen] + +0.9.13 / 2012-12-13 +=================== + + * package: fixed `base64id` requirement + +0.9.12 / 2012-12-13 +=================== + + * manager: fix for latest node which is returning a clone with `listeners` [viirya] + +0.9.11 / 2012-11-02 +=================== + + * package: move redis to optionalDependenices [3rd-Eden] + * bumped client + +0.9.10 / 2012-08-10 +=================== + + * Don't lowercase log messages + * Always set the HTTP response in case an error should be returned to the client + * Create or destroy the flash policy server on configuration change + * Honour configuration to disable flash policy server + * Add express 3.0 instructions on Readme.md + * Bump client + +0.9.9 / 2012-08-01 +================== + + * Fixed sync disconnect xhrs handling + * Put license text in its own file (#965) + * Add warning to .listen() to ease the migration to Express 3.x + * Restored compatibility with node 0.4.x + +0.9.8 / 2012-07-24 +================== + + * Bumped client. + +0.9.7 / 2012-07-24 +================== + + * Prevent crash when socket leaves a room twice. + * Corrects unsafe usage of for..in + * Fix for node 0.8 with `gzip compression` [vadimi] + * Update redis to support Node 0.8.x + * Made ID generation securely random + * Fix Redis Store race condition in manager onOpen unsubscribe callback + * Fix for EventEmitters always reusing the same Array instance for listeners + +0.9.6 / 2012-04-17 +================== + + * Fixed XSS in jsonp-polling. + +0.9.5 / 2012-04-05 +================== + + * Added test for polling and socket close. + * Ensure close upon request close. + * Fix disconnection reason being lost for polling transports. + * Ensure that polling transports work with Connection: close. + * Log disconnection reason. + +0.9.4 / 2012-04-01 +================== + + * Disconnecting from namespace improvement (#795) [DanielBaulig] + * Bumped client with polling reconnection loop (#438) + +0.9.3 / 2012-03-28 +================== + + * Fix "Syntax error" on FF Web Console with XHR Polling [mikito] + +0.9.2 / 2012-03-13 +================== + + * More sensible close `timeout default` (fixes disconnect issue) + +0.9.1-1 / 2012-03-02 +==================== + + * Bumped client with NPM dependency fix. + +0.9.1 / 2012-03-02 +================== + + * Changed heartbeat timeout and interval defaults (60 and 25 seconds) + * Make tests work both on 0.4 and 0.6 + * Updated client (improvements + bug fixes). + +0.9.0 / 2012-02-26 +================== + + * Make it possible to use a regexp to match the socket.io resource URL. + We need this because we have to prefix the socket.io URL with a variable ID. + * Supplemental fix to gavinuhma/authfix, it looks like the same Access-Control-Origin logic is needed in the http and xhr-polling transports + * Updated express dep for windows compatibility. + * Combine two substr calls into one in decodePayload to improve performance + * Minor documentation fix + * Minor. Conform to style of other files. + * Switching setting to 'match origin protocol' + * Revert "Fixes leaking Redis subscriptions for #663. The local flag was not getting passed through onClientDisconnect()." + * Revert "Handle leaked dispatch:[id] subscription." + * Merge pull request #667 from dshaw/patch/redis-disconnect + * Handle leaked dispatch:[id] subscription. + * Fixes leaking Redis subscriptions for #663. The local flag was not getting passed through onClientDisconnect(). + * Prevent memory leaking on uncompleted requests & add max post size limitation + * Fix for testcase + * Set Access-Control-Allow-Credentials true, regardless of cookie + * Remove assertvarnish from package as it breaks on 0.6 + * Correct irc channel + * Added proper return after reserved field error + * Fixes manager.js failure to close connection after transport error has happened + * Added implicit port 80 for origin checks. fixes #638 + * Fixed bug #432 in 0.8.7 + * Set Access-Control-Allow-Origin header to origin to enable withCredentials + * Adding configuration variable matchOriginProtocol + * Fixes location mismatch error in Safari. + * Use tty to detect if we should add colors or not by default. + * Updated the package location. + +0.8.7 / 2011-11-05 +================== + + * Fixed memory leaks in closed clients. + * Fixed memory leaks in namespaces. + * Fixed websocket handling for malformed requests from proxies. [einaros] + * Node 0.6 compatibility. [einaros] [3rd-Eden] + * Adapted tests and examples. + +0.8.6 / 2011-10-27 +================== + + * Added JSON decoding on jsonp-polling transport. + * Fixed README example. + * Major speed optimizations [3rd-Eden] [einaros] [visionmedia] + * Added decode/encode benchmarks [visionmedia] + * Added support for black-listing client sent events. + * Fixed logging options, closes #540 [3rd-Eden] + * Added vary header for gzip [3rd-Eden] + * Properly cleaned up async websocket / flashsocket tests, after patching node-websocket-client + * Patched to properly shut down when a finishClose call is made during connection establishment + * Added support for socket.io version on url and far-future Expires [3rd-Eden] [getify] + * Began IE10 compatibility [einaros] [tbranyen] + * Misc WebSocket fixes [einaros] + * Added UTF8 to respone headers for htmlfile [3rd-Eden] + +0.8.5 / 2011-10-07 +================== + + * Added websocket draft HyBi-16 support. [einaros] + * Fixed websocket continuation bugs. [einaros] + * Fixed flashsocket transport name. + * Fixed websocket tests. + * Ensured `parser#decodePayload` doesn't choke. + * Added http referrer verification to manager verifyOrigin. + * Added access control for cross domain xhr handshakes [3rd-Eden] + * Added support for automatic generation of socket.io files [3rd-Eden] + * Added websocket binary support [einaros] + * Added gzip support for socket.io.js [3rd-Eden] + * Expose socket.transport [3rd-Eden] + * Updated client. + +0.8.4 / 2011-09-06 +================== + + * Client build + +0.8.3 / 2011-09-03 +================== + + * Fixed `\n` parsing for non-JSON packets (fixes #479). + * Fixed parsing of certain unicode characters (fixes #451). + * Fixed transport message packet logging. + * Fixed emission of `error` event resulting in an uncaught exception if unhandled (fixes #476). + * Fixed; allow for falsy values as the configuration value of `log level` (fixes #491). + * Fixed repository URI in `package.json`. Fixes #504. + * Added text/plain content-type to handshake responses [einaros] + * Improved single byte writes [einaros] + * Updated socket.io-flashsocket default port from 843 to 10843 [3rd-Eden] + * Updated client. + +0.8.2 / 2011-08-29 +================== + + * Updated client. + +0.8.1 / 2011-08-29 +================== + + * Fixed utf8 bug in send framing in websocket [einaros] + * Fixed typo in docs [Znarkus] + * Fixed bug in send framing for over 64kB of data in websocket [einaros] + * Corrected ping handling in websocket transport [einaros] + +0.8.0 / 2011-08-28 +================== + + * Updated to work with two-level websocket versioning. [einaros] + * Added hybi07 support. [einaros] + * Added hybi10 support. [einaros] + * Added http referrer verification to manager.js verifyOrigin. [einaors] + +0.7.11 / 2011-08-27 +=================== + + * Updated socket.io-client. + +0.7.10 / 2011-08-27 +=================== + + * Updated socket.io-client. + +0.7.9 / 2011-08-12 +================== + + * Updated socket.io-client. + * Make sure we only do garbage collection when the server we receive is actually run. + +0.7.8 / 2011-08-08 +================== + + * Changed; make sure sio#listen passes options to both HTTP server and socket.io manager. + * Added docs for sio#listen. + * Added options parameter support for Manager constructor. + * Added memory leaks tests and test-leaks Makefile task. + * Removed auto npm-linking from make test. + * Make sure that you can disable heartbeats. [3rd-Eden] + * Fixed rooms memory leak [3rd-Eden] + * Send response once we got all POST data, not immediately [Pita] + * Fixed onLeave behavior with missing clientsk [3rd-Eden] + * Prevent duplicate references in rooms. + * Added alias for `to` to `in` and `in` to `to`. + * Fixed roomClients definition. + * Removed dependency on redis for installation without npm [3rd-Eden] + * Expose path and querystring in handshakeData [3rd-Eden] + +0.7.7 / 2011-07-12 +================== + + * Fixed double dispatch handling with emit to closed clients. + * Added test for emitting to closed clients to prevent regression. + * Fixed race condition in redis test. + * Changed Transport#end instrumentation. + * Leveraged $emit instead of emit internally. + * Made tests faster. + * Fixed double disconnect events. + * Fixed disconnect logic + * Simplified remote events handling in Socket. + * Increased testcase timeout. + * Fixed unknown room emitting (GH-291). [3rd-Eden] + * Fixed `address` in handshakeData. [3rd-Eden] + * Removed transports definition in chat example. + * Fixed room cleanup + * Fixed; make sure the client is cleaned up after booting. + * Make sure to mark the client as non-open if the connection is closed. + * Removed unneeded `buffer` declarations. + * Fixed; make sure to clear socket handlers and subscriptions upon transport close. + +0.7.6 / 2011-06-30 +================== + + * Fixed general dispatching when a client has closed. + +0.7.5 / 2011-06-30 +================== + + * Fixed dispatching to clients that are disconnected. + +0.7.4 / 2011-06-30 +================== + + * Fixed; only clear handlers if they were set. [level09] + +0.7.3 / 2011-06-30 +================== + + * Exposed handshake data to clients. + * Refactored dispatcher interface. + * Changed; Moved id generation method into the manager. + * Added sub-namespace authorization. [3rd-Eden] + * Changed; normalized SocketNamespace local eventing [dvv] + * Changed; Use packet.reason or default to 'packet' [3rd-Eden] + * Changed console.error to console.log. + * Fixed; bind both servers at the same time do that the test never times out. + * Added 304 support. + * Removed `Transport#name` for abstract interface. + * Changed; lazily require http and https module only when needed. [3rd-Eden] + +0.7.2 / 2011-06-22 +================== + + * Make sure to write a packet (of type `noop`) when closing a poll. + This solves a problem with cross-domain requests being flagged as aborted and + reconnection being triggered. + * Added `noop` message type. + +0.7.1 / 2011-06-21 +================== + + * Fixed cross-domain XHR. + * Added CORS test to xhr-polling suite. + +0.7.0 / 2010-06-21 +================== + + * http://socket.io/announcement.html diff --git a/node_modules/socket.io/LICENSE b/node_modules/socket.io/LICENSE new file mode 100644 index 00000000..0f4acd44 --- /dev/null +++ b/node_modules/socket.io/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2011 Guillermo Rauch + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/socket.io/Readme.md b/node_modules/socket.io/Readme.md new file mode 100644 index 00000000..41f21f68 --- /dev/null +++ b/node_modules/socket.io/Readme.md @@ -0,0 +1,364 @@ +# Socket.IO + +Socket.IO is a Node.JS project that makes WebSockets and realtime possible in +all browsers. It also enhances WebSockets by providing built-in multiplexing, +horizontal scalability, automatic JSON encoding/decoding, and more. + +## How to Install + +```bash +npm install socket.io +``` + +## How to use + +First, require `socket.io`: + +```js +var io = require('socket.io'); +``` + +Next, attach it to a HTTP/HTTPS server. If you're using the fantastic `express` +web framework: + +#### Express 3.x + +```js +var app = express() + , server = require('http').createServer(app) + , io = io.listen(server); + +server.listen(80); + +io.sockets.on('connection', function (socket) { + socket.emit('news', { hello: 'world' }); + socket.on('my other event', function (data) { + console.log(data); + }); +}); +``` + +#### Express 2.x + +```js +var app = express.createServer() + , io = io.listen(app); + +app.listen(80); + +io.sockets.on('connection', function (socket) { + socket.emit('news', { hello: 'world' }); + socket.on('my other event', function (data) { + console.log(data); + }); +}); +``` + +Finally, load it from the client side code: + +```html + + +``` + +For more thorough examples, look at the `examples/` directory. + +## Short recipes + +### Sending and receiving events. + +Socket.IO allows you to emit and receive custom events. +Besides `connect`, `message` and `disconnect`, you can emit custom events: + +```js +// note, io.listen() will create a http server for you +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + io.sockets.emit('this', { will: 'be received by everyone' }); + + socket.on('private message', function (from, msg) { + console.log('I received a private message by ', from, ' saying ', msg); + }); + + socket.on('disconnect', function () { + io.sockets.emit('user disconnected'); + }); +}); +``` + +### Storing data associated to a client + +Sometimes it's necessary to store data associated with a client that's +necessary for the duration of the session. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.on('set nickname', function (name) { + socket.set('nickname', name, function () { socket.emit('ready'); }); + }); + + socket.on('msg', function () { + socket.get('nickname', function (err, name) { + console.log('Chat message by ', name); + }); + }); +}); +``` + +#### Client side + +```html + +``` + +### Restricting yourself to a namespace + +If you have control over all the messages and events emitted for a particular +application, using the default `/` namespace works. + +If you want to leverage 3rd-party code, or produce code to share with others, +socket.io provides a way of namespacing a `socket`. + +This has the benefit of `multiplexing` a single connection. Instead of +socket.io using two `WebSocket` connections, it'll use one. + +The following example defines a socket that listens on '/chat' and one for +'/news': + +#### Server side + +```js +var io = require('socket.io').listen(80); + +var chat = io + .of('/chat') + .on('connection', function (socket) { + socket.emit('a message', { that: 'only', '/chat': 'will get' }); + chat.emit('a message', { everyone: 'in', '/chat': 'will get' }); + }); + +var news = io + .of('/news'); + .on('connection', function (socket) { + socket.emit('item', { news: 'item' }); + }); +``` + +#### Client side: + +```html + +``` + +### Sending volatile messages. + +Sometimes certain messages can be dropped. Let's say you have an app that +shows realtime tweets for the keyword `bieber`. + +If a certain client is not ready to receive messages (because of network slowness +or other issues, or because he's connected through long polling and is in the +middle of a request-response cycle), if he doesn't receive ALL the tweets related +to bieber your application won't suffer. + +In that case, you might want to send those messages as volatile messages. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + var tweets = setInterval(function () { + getBieberTweet(function (tweet) { + socket.volatile.emit('bieber tweet', tweet); + }); + }, 100); + + socket.on('disconnect', function () { + clearInterval(tweets); + }); +}); +``` + +#### Client side + +In the client side, messages are received the same way whether they're volatile +or not. + +### Getting acknowledgements + +Sometimes, you might want to get a callback when the client confirmed the message +reception. + +To do this, simply pass a function as the last parameter of `.send` or `.emit`. +What's more, when you use `.emit`, the acknowledgement is done by you, which +means you can also pass data along: + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.on('ferret', function (name, fn) { + fn('woot'); + }); +}); +``` + +#### Client side + +```html + +``` + +### Broadcasting messages + +To broadcast, simply add a `broadcast` flag to `emit` and `send` method calls. +Broadcasting means sending a message to everyone else except for the socket +that starts it. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.broadcast.emit('user connected'); + socket.broadcast.json.send({ a: 'message' }); +}); +``` + +### Rooms + +Sometimes you want to put certain sockets in the same room, so that it's easy +to broadcast to all of them together. + +Think of this as built-in channels for sockets. Sockets `join` and `leave` +rooms in each socket. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.join('justin bieber fans'); + socket.broadcast.to('justin bieber fans').emit('new fan'); + io.sockets.in('rammstein fans').emit('new non-fan'); +}); +``` + +### Using it just as a cross-browser WebSocket + +If you just want the WebSocket semantics, you can do that too. +Simply leverage `send` and listen on the `message` event: + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.on('message', function () { }); + socket.on('disconnect', function () { }); +}); +``` + +#### Client side + +```html + +``` + +### Changing configuration + +Configuration in socket.io is TJ-style: + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.configure(function () { + io.set('transports', ['websocket', 'flashsocket', 'xhr-polling']); +}); + +io.configure('development', function () { + io.set('transports', ['websocket', 'xhr-polling']); + io.enable('log'); +}); +``` + +## License + +(The MIT License) + +Copyright (c) 2011 Guillermo Rauch <guillermo@learnboost.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/socket.io/benchmarks/decode.bench.js b/node_modules/socket.io/benchmarks/decode.bench.js new file mode 100644 index 00000000..4855d805 --- /dev/null +++ b/node_modules/socket.io/benchmarks/decode.bench.js @@ -0,0 +1,64 @@ + +/** + * Module dependencies. + */ + +var benchmark = require('benchmark') + , colors = require('colors') + , io = require('../') + , parser = io.parser + , suite = new benchmark.Suite('Decode packet'); + +suite.add('string', function () { + parser.decodePacket('4:::"2"'); +}); + +suite.add('event', function () { + parser.decodePacket('5:::{"name":"woot"}'); +}); + +suite.add('event+ack', function () { + parser.decodePacket('5:1+::{"name":"tobi"}'); +}); + +suite.add('event+data', function () { + parser.decodePacket('5:::{"name":"edwald","args":[{"a": "b"},2,"3"]}'); +}); + +suite.add('heartbeat', function () { + parser.decodePacket('2:::'); +}); + +suite.add('error', function () { + parser.decodePacket('7:::2+0'); +}); + +var payload = parser.encodePayload([ + parser.encodePacket({ type: 'message', data: '5', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: '53d', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) +]); + +suite.add('payload', function () { + parser.decodePayload(payload); +}); + +suite.on('cycle', function (bench, details) { + console.log('\n' + suite.name.grey, details.name.white.bold); + console.log([ + details.hz.toFixed(2).cyan + ' ops/sec'.grey + , details.count.toString().white + ' times executed'.grey + , 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey + , + ].join(', '.grey)); +}); + +if (!module.parent) { + suite.run(); +} else { + module.exports = suite; +} diff --git a/node_modules/socket.io/benchmarks/encode.bench.js b/node_modules/socket.io/benchmarks/encode.bench.js new file mode 100644 index 00000000..5037702d --- /dev/null +++ b/node_modules/socket.io/benchmarks/encode.bench.js @@ -0,0 +1,90 @@ + +/** + * Module dependencies. + */ + +var benchmark = require('benchmark') + , colors = require('colors') + , io = require('../') + , parser = io.parser + , suite = new benchmark.Suite('Encode packet'); + +suite.add('string', function () { + parser.encodePacket({ + type: 'json' + , endpoint: '' + , data: '2' + }); +}); + +suite.add('event', function () { + parser.encodePacket({ + type: 'event' + , name: 'woot' + , endpoint: '' + , args: [] + }); +}); + +suite.add('event+ack', function () { + parser.encodePacket({ + type: 'json' + , id: 1 + , ack: 'data' + , endpoint: '' + , data: { a: 'b' } + }); +}); + +suite.add('event+data', function () { + parser.encodePacket({ + type: 'event' + , name: 'edwald' + , endpoint: '' + , args: [{a: 'b'}, 2, '3'] + }); +}); + +suite.add('heartbeat', function () { + parser.encodePacket({ + type: 'heartbeat' + , endpoint: '' + }) +}); + +suite.add('error', function () { + parser.encodePacket({ + type: 'error' + , reason: 'unauthorized' + , advice: 'reconnect' + , endpoint: '' + }) +}) + +suite.add('payload', function () { + parser.encodePayload([ + parser.encodePacket({ type: 'message', data: '5', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: '53d', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) + ]); +}); + +suite.on('cycle', function (bench, details) { + console.log('\n' + suite.name.grey, details.name.white.bold); + console.log([ + details.hz.toFixed(2).cyan + ' ops/sec'.grey + , details.count.toString().white + ' times executed'.grey + , 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey + , + ].join(', '.grey)); +}); + +if (!module.parent) { + suite.run(); +} else { + module.exports = suite; +} diff --git a/node_modules/socket.io/benchmarks/runner.js b/node_modules/socket.io/benchmarks/runner.js new file mode 100644 index 00000000..81e55cae --- /dev/null +++ b/node_modules/socket.io/benchmarks/runner.js @@ -0,0 +1,55 @@ +/** + * Benchmark runner dependencies + */ + +var colors = require('colors') + , path = require('path'); + +/** + * Find all the benchmarks + */ + +var benchmarks_files = process.env.BENCHMARKS.split(' ') + , all = [].concat(benchmarks_files) + , first = all.shift() + , benchmarks = {}; + +// find the benchmarks and load them all in our obj +benchmarks_files.forEach(function (file) { + benchmarks[file] = require(path.join(__dirname, '..', file)); +}); + +// setup the complete listeners +benchmarks_files.forEach(function (file) { + var benchmark = benchmarks[file] + , next_file = all.shift() + , next = benchmarks[next_file]; + + /** + * Generate a oncomplete function for the tests, either we are done or we + * have more benchmarks to process. + */ + + function complete () { + if (!next) { + console.log( + '\n\nBenchmark completed in'.grey + , (Date.now() - start).toString().green + ' ms'.grey + ); + } else { + console.log('\nStarting benchmark '.grey + next_file.yellow); + next.run(); + } + } + + // attach the listener + benchmark.on('complete', complete); +}); + +/** + * Start the benchmark + */ + +var start = Date.now(); +console.log('Starting benchmark '.grey + first.yellow); +benchmarks[first].run(); diff --git a/node_modules/socket.io/index.js b/node_modules/socket.io/index.js new file mode 100644 index 00000000..cc00c103 --- /dev/null +++ b/node_modules/socket.io/index.js @@ -0,0 +1,8 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +module.exports = require('./lib/socket.io'); diff --git a/node_modules/socket.io/lib/logger.js b/node_modules/socket.io/lib/logger.js new file mode 100644 index 00000000..49d02c98 --- /dev/null +++ b/node_modules/socket.io/lib/logger.js @@ -0,0 +1,97 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var util = require('./util') + , toArray = util.toArray; + +/** + * Log levels. + */ + +var levels = [ + 'error' + , 'warn' + , 'info' + , 'debug' +]; + +/** + * Colors for log levels. + */ + +var colors = [ + 31 + , 33 + , 36 + , 90 +]; + +/** + * Pads the nice output to the longest log level. + */ + +function pad (str) { + var max = 0; + + for (var i = 0, l = levels.length; i < l; i++) + max = Math.max(max, levels[i].length); + + if (str.length < max) + return str + new Array(max - str.length + 1).join(' '); + + return str; +}; + +/** + * Logger (console). + * + * @api public + */ + +var Logger = module.exports = function (opts) { + opts = opts || {} + this.colors = false !== opts.colors; + this.level = 3; + this.enabled = true; +}; + +/** + * Log method. + * + * @api public + */ + +Logger.prototype.log = function (type) { + var index = levels.indexOf(type); + + if (index > this.level || !this.enabled) + return this; + + console.log.apply( + console + , [this.colors + ? ' \033[' + colors[index] + 'm' + pad(type) + ' -\033[39m' + : type + ':' + ].concat(toArray(arguments).slice(1)) + ); + + return this; +}; + +/** + * Generate methods. + */ + +levels.forEach(function (name) { + Logger.prototype[name] = function () { + this.log.apply(this, [name].concat(toArray(arguments))); + }; +}); diff --git a/node_modules/socket.io/lib/manager.js b/node_modules/socket.io/lib/manager.js new file mode 100644 index 00000000..83937853 --- /dev/null +++ b/node_modules/socket.io/lib/manager.js @@ -0,0 +1,1027 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var fs = require('fs') + , url = require('url') + , tty = require('tty') + , crypto = require('crypto') + , util = require('./util') + , store = require('./store') + , client = require('socket.io-client') + , transports = require('./transports') + , Logger = require('./logger') + , Socket = require('./socket') + , MemoryStore = require('./stores/memory') + , SocketNamespace = require('./namespace') + , Static = require('./static') + , EventEmitter = process.EventEmitter; + +/** + * Export the constructor. + */ + +exports = module.exports = Manager; + +/** + * Default transports. + */ + +var defaultTransports = exports.defaultTransports = [ + 'websocket' + , 'htmlfile' + , 'xhr-polling' + , 'jsonp-polling' +]; + +/** + * Inherited defaults. + */ + +var parent = module.parent.exports + , protocol = parent.protocol + , jsonpolling_re = /^\d+$/; + +/** + * Manager constructor. + * + * @param {HTTPServer} server + * @param {Object} options, optional + * @api public + */ + +function Manager (server, options) { + this.server = server; + this.namespaces = {}; + this.sockets = this.of(''); + this.settings = { + origins: '*:*' + , log: true + , store: new MemoryStore + , logger: new Logger + , static: new Static(this) + , heartbeats: true + , resource: '/socket.io' + , transports: defaultTransports + , authorization: false + , blacklist: ['disconnect'] + , 'log level': 3 + , 'log colors': tty.isatty(process.stdout.fd) + , 'close timeout': 60 + , 'heartbeat interval': 25 + , 'heartbeat timeout': 60 + , 'polling duration': 20 + , 'flash policy server': true + , 'flash policy port': 10843 + , 'destroy upgrade': true + , 'destroy buffer size': 10E7 + , 'browser client': true + , 'browser client cache': true + , 'browser client minification': false + , 'browser client etag': false + , 'browser client expires': 315360000 + , 'browser client gzip': false + , 'browser client handler': false + , 'client store expiration': 15 + , 'match origin protocol': false + }; + + for (var i in options) { + if (options.hasOwnProperty(i)) { + this.settings[i] = options[i]; + } + } + + var self = this; + + // default error handler + server.on('error', function(err) { + self.log.warn('error raised: ' + err); + }); + + this.initStore(); + + this.on('set:store', function() { + self.initStore(); + }); + + // reset listeners + this.oldListeners = server.listeners('request').splice(0); + server.removeAllListeners('request'); + + server.on('request', function (req, res) { + self.handleRequest(req, res); + }); + + server.on('upgrade', function (req, socket, head) { + self.handleUpgrade(req, socket, head); + }); + + server.on('close', function () { + clearInterval(self.gc); + }); + + server.once('listening', function () { + self.gc = setInterval(self.garbageCollection.bind(self), 10000); + }); + + for (var i in transports) { + if (transports.hasOwnProperty(i)) { + if (transports[i].init) { + transports[i].init(this); + } + } + } + + // forward-compatibility with 1.0 + var self = this; + this.sockets.on('connection', function (conn) { + self.emit('connection', conn); + }); + + this.sequenceNumber = Date.now() | 0; + + this.log.info('socket.io started'); +}; + +Manager.prototype.__proto__ = EventEmitter.prototype + +/** + * Store accessor shortcut. + * + * @api public + */ + +Manager.prototype.__defineGetter__('store', function () { + var store = this.get('store'); + store.manager = this; + return store; +}); + +/** + * Logger accessor. + * + * @api public + */ + +Manager.prototype.__defineGetter__('log', function () { + var logger = this.get('logger'); + + logger.level = this.get('log level') || -1; + logger.colors = this.get('log colors'); + logger.enabled = this.enabled('log'); + + return logger; +}); + +/** + * Static accessor. + * + * @api public + */ + +Manager.prototype.__defineGetter__('static', function () { + return this.get('static'); +}); + +/** + * Get settings. + * + * @api public + */ + +Manager.prototype.get = function (key) { + return this.settings[key]; +}; + +/** + * Set settings + * + * @api public + */ + +Manager.prototype.set = function (key, value) { + if (arguments.length == 1) return this.get(key); + this.settings[key] = value; + this.emit('set:' + key, this.settings[key], key); + return this; +}; + +/** + * Enable a setting + * + * @api public + */ + +Manager.prototype.enable = function (key) { + this.settings[key] = true; + this.emit('set:' + key, this.settings[key], key); + return this; +}; + +/** + * Disable a setting + * + * @api public + */ + +Manager.prototype.disable = function (key) { + this.settings[key] = false; + this.emit('set:' + key, this.settings[key], key); + return this; +}; + +/** + * Checks if a setting is enabled + * + * @api public + */ + +Manager.prototype.enabled = function (key) { + return !!this.settings[key]; +}; + +/** + * Checks if a setting is disabled + * + * @api public + */ + +Manager.prototype.disabled = function (key) { + return !this.settings[key]; +}; + +/** + * Configure callbacks. + * + * @api public + */ + +Manager.prototype.configure = function (env, fn) { + if ('function' == typeof env) { + env.call(this); + } else if (env == (process.env.NODE_ENV || 'development')) { + fn.call(this); + } + + return this; +}; + +/** + * Initializes everything related to the message dispatcher. + * + * @api private + */ + +Manager.prototype.initStore = function () { + this.handshaken = {}; + this.connected = {}; + this.open = {}; + this.closed = {}; + this.rooms = {}; + this.roomClients = {}; + + var self = this; + + this.store.subscribe('handshake', function (id, data) { + self.onHandshake(id, data); + }); + + this.store.subscribe('connect', function (id) { + self.onConnect(id); + }); + + this.store.subscribe('open', function (id) { + self.onOpen(id); + }); + + this.store.subscribe('join', function (id, room) { + self.onJoin(id, room); + }); + + this.store.subscribe('leave', function (id, room) { + self.onLeave(id, room); + }); + + this.store.subscribe('close', function (id) { + self.onClose(id); + }); + + this.store.subscribe('dispatch', function (room, packet, volatile, exceptions) { + self.onDispatch(room, packet, volatile, exceptions); + }); + + this.store.subscribe('disconnect', function (id) { + self.onDisconnect(id); + }); +}; + +/** + * Called when a client handshakes. + * + * @param text + */ + +Manager.prototype.onHandshake = function (id, data) { + this.handshaken[id] = data; +}; + +/** + * Called when a client connects (ie: transport first opens) + * + * @api private + */ + +Manager.prototype.onConnect = function (id) { + this.connected[id] = true; +}; + +/** + * Called when a client opens a request in a different node. + * + * @api private + */ + +Manager.prototype.onOpen = function (id) { + this.open[id] = true; + + if (this.closed[id]) { + var self = this; + + this.store.unsubscribe('dispatch:' + id, function () { + var transport = self.transports[id]; + if (self.closed[id] && self.closed[id].length && transport) { + + // if we have buffered messages that accumulate between calling + // onOpen an this async callback, send them if the transport is + // still open, otherwise leave them buffered + if (transport.open) { + transport.payload(self.closed[id]); + self.closed[id] = []; + } + } + }); + } + + // clear the current transport + if (this.transports[id]) { + this.transports[id].discard(); + this.transports[id] = null; + } +}; + +/** + * Called when a message is sent to a namespace and/or room. + * + * @api private + */ + +Manager.prototype.onDispatch = function (room, packet, volatile, exceptions) { + if (this.rooms[room]) { + for (var i = 0, l = this.rooms[room].length; i < l; i++) { + var id = this.rooms[room][i]; + + if (!~exceptions.indexOf(id)) { + if (this.transports[id] && this.transports[id].open) { + this.transports[id].onDispatch(packet, volatile); + } else if (!volatile) { + this.onClientDispatch(id, packet); + } + } + } + } +}; + +/** + * Called when a client joins a nsp / room. + * + * @api private + */ + +Manager.prototype.onJoin = function (id, name) { + if (!this.roomClients[id]) { + this.roomClients[id] = {}; + } + + if (!this.rooms[name]) { + this.rooms[name] = []; + } + + if (!~this.rooms[name].indexOf(id)) { + this.rooms[name].push(id); + this.roomClients[id][name] = true; + } +}; + +/** + * Called when a client leaves a nsp / room. + * + * @param private + */ + +Manager.prototype.onLeave = function (id, room) { + if (this.rooms[room]) { + var index = this.rooms[room].indexOf(id); + + if (index >= 0) { + this.rooms[room].splice(index, 1); + } + + if (!this.rooms[room].length) { + delete this.rooms[room]; + } + + if (this.roomClients[id]) { + delete this.roomClients[id][room]; + } + } +}; + +/** + * Called when a client closes a request in different node. + * + * @api private + */ + +Manager.prototype.onClose = function (id) { + if (this.open[id]) { + delete this.open[id]; + } + + this.closed[id] = []; + + var self = this; + + this.store.subscribe('dispatch:' + id, function (packet, volatile) { + if (!volatile) { + self.onClientDispatch(id, packet); + } + }); +}; + +/** + * Dispatches a message for a closed client. + * + * @api private + */ + +Manager.prototype.onClientDispatch = function (id, packet) { + if (this.closed[id]) { + this.closed[id].push(packet); + } +}; + +/** + * Receives a message for a client. + * + * @api private + */ + +Manager.prototype.onClientMessage = function (id, packet) { + if (this.namespaces[packet.endpoint]) { + this.namespaces[packet.endpoint].handlePacket(id, packet); + } +}; + +/** + * Fired when a client disconnects (not triggered). + * + * @api private + */ + +Manager.prototype.onClientDisconnect = function (id, reason) { + for (var name in this.namespaces) { + if (this.namespaces.hasOwnProperty(name)) { + this.namespaces[name].handleDisconnect(id, reason, typeof this.roomClients[id] !== 'undefined' && + typeof this.roomClients[id][name] !== 'undefined'); + } + } + + this.onDisconnect(id); +}; + +/** + * Called when a client disconnects. + * + * @param text + */ + +Manager.prototype.onDisconnect = function (id, local) { + delete this.handshaken[id]; + + if (this.open[id]) { + delete this.open[id]; + } + + if (this.connected[id]) { + delete this.connected[id]; + } + + if (this.transports[id]) { + this.transports[id].discard(); + delete this.transports[id]; + } + + if (this.closed[id]) { + delete this.closed[id]; + } + + if (this.roomClients[id]) { + for (var room in this.roomClients[id]) { + if (this.roomClients[id].hasOwnProperty(room)) { + this.onLeave(id, room); + } + } + delete this.roomClients[id] + } + + this.store.destroyClient(id, this.get('client store expiration')); + + this.store.unsubscribe('dispatch:' + id); + + if (local) { + this.store.unsubscribe('message:' + id); + this.store.unsubscribe('disconnect:' + id); + } +}; + +/** + * Handles an HTTP request. + * + * @api private + */ + +Manager.prototype.handleRequest = function (req, res) { + var data = this.checkRequest(req); + + if (!data) { + for (var i = 0, l = this.oldListeners.length; i < l; i++) { + this.oldListeners[i].call(this.server, req, res); + } + + return; + } + + if (data.static || !data.transport && !data.protocol) { + if (data.static && this.enabled('browser client')) { + this.static.write(data.path, req, res); + } else { + res.writeHead(200); + res.end('Welcome to socket.io.'); + + this.log.info('unhandled socket.io url'); + } + + return; + } + + if (data.protocol != protocol) { + res.writeHead(500); + res.end('Protocol version not supported.'); + + this.log.info('client protocol version unsupported'); + } else { + if (data.id) { + this.handleHTTPRequest(data, req, res); + } else { + this.handleHandshake(data, req, res); + } + } +}; + +/** + * Handles an HTTP Upgrade. + * + * @api private + */ + +Manager.prototype.handleUpgrade = function (req, socket, head) { + var data = this.checkRequest(req) + , self = this; + + if (!data) { + if (this.enabled('destroy upgrade')) { + socket.end(); + this.log.debug('destroying non-socket.io upgrade'); + } + + return; + } + + req.head = head; + this.handleClient(data, req); + req.head = null; +}; + +/** + * Handles a normal handshaken HTTP request (eg: long-polling) + * + * @api private + */ + +Manager.prototype.handleHTTPRequest = function (data, req, res) { + req.res = res; + this.handleClient(data, req); +}; + +/** + * Intantiantes a new client. + * + * @api private + */ + +Manager.prototype.handleClient = function (data, req) { + var socket = req.socket + , store = this.store + , self = this; + + // handle sync disconnect xhrs + if (undefined != data.query.disconnect) { + if (this.transports[data.id] && this.transports[data.id].open) { + this.transports[data.id].onForcedDisconnect(); + } else { + this.store.publish('disconnect-force:' + data.id); + } + req.res.writeHead(200); + req.res.end(); + return; + } + + if (!~this.get('transports').indexOf(data.transport)) { + this.log.warn('unknown transport: "' + data.transport + '"'); + req.connection.end(); + return; + } + + var transport = new transports[data.transport](this, data, req) + , handshaken = this.handshaken[data.id]; + + if (transport.disconnected) { + // failed during transport setup + req.connection.end(); + return; + } + if (handshaken) { + if (transport.open) { + if (this.closed[data.id] && this.closed[data.id].length) { + transport.payload(this.closed[data.id]); + this.closed[data.id] = []; + } + + this.onOpen(data.id); + this.store.publish('open', data.id); + this.transports[data.id] = transport; + } + + if (!this.connected[data.id]) { + this.onConnect(data.id); + this.store.publish('connect', data.id); + + // flag as used + delete handshaken.issued; + this.onHandshake(data.id, handshaken); + this.store.publish('handshake', data.id, handshaken); + + // initialize the socket for all namespaces + for (var i in this.namespaces) { + if (this.namespaces.hasOwnProperty(i)) { + var socket = this.namespaces[i].socket(data.id, true); + + // echo back connect packet and fire connection event + if (i === '') { + this.namespaces[i].handlePacket(data.id, { type: 'connect' }); + } + } + } + + this.store.subscribe('message:' + data.id, function (packet) { + self.onClientMessage(data.id, packet); + }); + + this.store.subscribe('disconnect:' + data.id, function (reason) { + self.onClientDisconnect(data.id, reason); + }); + } + } else { + if (transport.open) { + transport.error('client not handshaken', 'reconnect'); + } + + transport.discard(); + } +}; + +/** + * Generates a session id. + * + * @api private + */ + +Manager.prototype.generateId = function () { + var rand = new Buffer(15); // multiple of 3 for base64 + if (!rand.writeInt32BE) { + return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString() + + Math.abs(Math.random() * Math.random() * Date.now() | 0).toString(); + } + this.sequenceNumber = (this.sequenceNumber + 1) | 0; + rand.writeInt32BE(this.sequenceNumber, 11); + if (crypto.randomBytes) { + crypto.randomBytes(12).copy(rand); + } else { + // not secure for node 0.4 + [0, 4, 8].forEach(function(i) { + rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i); + }); + } + return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-'); +}; + +/** + * Handles a handshake request. + * + * @api private + */ + +Manager.prototype.handleHandshake = function (data, req, res) { + var self = this + , origin = req.headers.origin + , headers = { + 'Content-Type': 'text/plain' + }; + + function writeErr (status, message) { + if (data.query.jsonp && jsonpolling_re.test(data.query.jsonp)) { + res.writeHead(200, { 'Content-Type': 'application/javascript' }); + res.end('io.j[' + data.query.jsonp + '](new Error("' + message + '"));'); + } else { + res.writeHead(status, headers); + res.end(message); + } + }; + + function error (err) { + writeErr(500, 'handshake error'); + self.log.warn('handshake error ' + err); + }; + + if (!this.verifyOrigin(req)) { + writeErr(403, 'handshake bad origin'); + return; + } + + var handshakeData = this.handshakeData(data); + + if (origin) { + // https://developer.mozilla.org/En/HTTP_Access_Control + headers['Access-Control-Allow-Origin'] = origin; + headers['Access-Control-Allow-Credentials'] = 'true'; + } + + this.authorize(handshakeData, function (err, authorized, newData) { + if (err) return error(err); + + if (authorized) { + var id = self.generateId() + , hs = [ + id + , self.enabled('heartbeats') ? self.get('heartbeat timeout') || '' : '' + , self.get('close timeout') || '' + , self.transports(data).join(',') + ].join(':'); + + if (data.query.jsonp && jsonpolling_re.test(data.query.jsonp)) { + hs = 'io.j[' + data.query.jsonp + '](' + JSON.stringify(hs) + ');'; + res.writeHead(200, { 'Content-Type': 'application/javascript' }); + } else { + res.writeHead(200, headers); + } + + res.end(hs); + + self.onHandshake(id, newData || handshakeData); + self.store.publish('handshake', id, newData || handshakeData); + + self.log.info('handshake authorized', id); + } else { + writeErr(403, 'handshake unauthorized'); + self.log.info('handshake unauthorized'); + } + }) +}; + +/** + * Gets normalized handshake data + * + * @api private + */ + +Manager.prototype.handshakeData = function (data) { + var connection = data.request.connection + , connectionAddress + , date = new Date; + + if (connection.remoteAddress) { + connectionAddress = { + address: connection.remoteAddress + , port: connection.remotePort + }; + } else if (connection.socket && connection.socket.remoteAddress) { + connectionAddress = { + address: connection.socket.remoteAddress + , port: connection.socket.remotePort + }; + } + + return { + headers: data.headers + , address: connectionAddress + , time: date.toString() + , query: data.query + , url: data.request.url + , xdomain: !!data.request.headers.origin + , secure: data.request.connection.secure + , issued: +date + }; +}; + +/** + * Verifies the origin of a request. + * + * @api private + */ + +Manager.prototype.verifyOrigin = function (request) { + var origin = request.headers.origin || request.headers.referer + , origins = this.get('origins'); + + if (origin === 'null') origin = '*'; + + if (origins.indexOf('*:*') !== -1) { + return true; + } + + if (origin) { + try { + var parts = url.parse(origin); + parts.port = parts.port || 80; + var ok = + ~origins.indexOf(parts.hostname + ':' + parts.port) || + ~origins.indexOf(parts.hostname + ':*') || + ~origins.indexOf('*:' + parts.port); + if (!ok) this.log.warn('illegal origin: ' + origin); + return ok; + } catch (ex) { + this.log.warn('error parsing origin'); + } + } + else { + this.log.warn('origin missing from handshake, yet required by config'); + } + return false; +}; + +/** + * Handles an incoming packet. + * + * @api private + */ + +Manager.prototype.handlePacket = function (sessid, packet) { + this.of(packet.endpoint || '').handlePacket(sessid, packet); +}; + +/** + * Performs authentication. + * + * @param Object client request data + * @api private + */ + +Manager.prototype.authorize = function (data, fn) { + if (this.get('authorization')) { + var self = this; + + this.get('authorization').call(this, data, function (err, authorized) { + self.log.debug('client ' + authorized ? 'authorized' : 'unauthorized'); + fn(err, authorized); + }); + } else { + this.log.debug('client authorized'); + fn(null, true); + } + + return this; +}; + +/** + * Retrieves the transports adviced to the user. + * + * @api private + */ + +Manager.prototype.transports = function (data) { + var transp = this.get('transports') + , ret = []; + + for (var i = 0, l = transp.length; i < l; i++) { + var transport = transp[i]; + + if (transport) { + if (!transport.checkClient || transport.checkClient(data)) { + ret.push(transport); + } + } + } + + return ret; +}; + +/** + * Checks whether a request is a socket.io one. + * + * @return {Object} a client request data object or `false` + * @api private + */ + +var regexp = /^\/([^\/]+)\/?([^\/]+)?\/?([^\/]+)?\/?$/ + +Manager.prototype.checkRequest = function (req) { + var resource = this.get('resource'); + + var match; + if (typeof resource === 'string') { + match = req.url.substr(0, resource.length); + if (match !== resource) match = null; + } else { + match = resource.exec(req.url); + if (match) match = match[0]; + } + + if (match) { + var uri = url.parse(req.url.substr(match.length), true) + , path = uri.pathname || '' + , pieces = path.match(regexp); + + // client request data + var data = { + query: uri.query || {} + , headers: req.headers + , request: req + , path: path + }; + + if (pieces) { + data.protocol = Number(pieces[1]); + data.transport = pieces[2]; + data.id = pieces[3]; + data.static = !!this.static.has(path); + }; + + return data; + } + + return false; +}; + +/** + * Declares a socket namespace + * + * @api public + */ + +Manager.prototype.of = function (nsp) { + if (this.namespaces[nsp]) { + return this.namespaces[nsp]; + } + + return this.namespaces[nsp] = new SocketNamespace(this, nsp); +}; + +/** + * Perform garbage collection on long living objects and properties that cannot + * be removed automatically. + * + * @api private + */ + +Manager.prototype.garbageCollection = function () { + // clean up unused handshakes + var ids = Object.keys(this.handshaken) + , i = ids.length + , now = Date.now() + , handshake; + + while (i--) { + handshake = this.handshaken[ids[i]]; + + if ('issued' in handshake && (now - handshake.issued) >= 3E4) { + this.onDisconnect(ids[i]); + } + } +}; diff --git a/node_modules/socket.io/lib/namespace.js b/node_modules/socket.io/lib/namespace.js new file mode 100644 index 00000000..6e1e1c92 --- /dev/null +++ b/node_modules/socket.io/lib/namespace.js @@ -0,0 +1,355 @@ +/** + * Module dependencies. + */ + +var Socket = require('./socket') + , EventEmitter = process.EventEmitter + , parser = require('./parser') + , util = require('./util'); + +/** + * Exports the constructor. + */ + +exports = module.exports = SocketNamespace; + +/** + * Constructor. + * + * @api public. + */ + +function SocketNamespace (mgr, name) { + this.manager = mgr; + this.name = name || ''; + this.sockets = {}; + this.auth = false; + this.setFlags(); +}; + +/** + * Inherits from EventEmitter. + */ + +SocketNamespace.prototype.__proto__ = EventEmitter.prototype; + +/** + * Copies emit since we override it. + * + * @api private + */ + +SocketNamespace.prototype.$emit = EventEmitter.prototype.emit; + +/** + * Retrieves all clients as Socket instances as an array. + * + * @api public + */ + +SocketNamespace.prototype.clients = function (room) { + var room = this.name + (room !== undefined ? + '/' + room : ''); + + if (!this.manager.rooms[room]) { + return []; + } + + return this.manager.rooms[room].map(function (id) { + return this.socket(id); + }, this); +}; + +/** + * Access logger interface. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('log', function () { + return this.manager.log; +}); + +/** + * Access store. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('store', function () { + return this.manager.store; +}); + +/** + * JSON message flag. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('json', function () { + this.flags.json = true; + return this; +}); + +/** + * Volatile message flag. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('volatile', function () { + this.flags.volatile = true; + return this; +}); + +/** + * Overrides the room to relay messages to (flag). + * + * @api public + */ + +SocketNamespace.prototype.in = SocketNamespace.prototype.to = function (room) { + this.flags.endpoint = this.name + (room ? '/' + room : ''); + return this; +}; + +/** + * Adds a session id we should prevent relaying messages to (flag). + * + * @api public + */ + +SocketNamespace.prototype.except = function (id) { + this.flags.exceptions.push(id); + return this; +}; + +/** + * Sets the default flags. + * + * @api private + */ + +SocketNamespace.prototype.setFlags = function () { + this.flags = { + endpoint: this.name + , exceptions: [] + }; + return this; +}; + +/** + * Sends out a packet. + * + * @api private + */ + +SocketNamespace.prototype.packet = function (packet) { + packet.endpoint = this.name; + + var store = this.store + , log = this.log + , volatile = this.flags.volatile + , exceptions = this.flags.exceptions + , packet = parser.encodePacket(packet); + + this.manager.onDispatch(this.flags.endpoint, packet, volatile, exceptions); + this.store.publish('dispatch', this.flags.endpoint, packet, volatile, exceptions); + + this.setFlags(); + + return this; +}; + +/** + * Sends to everyone. + * + * @api public + */ + +SocketNamespace.prototype.send = function (data) { + return this.packet({ + type: this.flags.json ? 'json' : 'message' + , data: data + }); +}; + +/** + * Emits to everyone (override). + * + * @api public + */ + +SocketNamespace.prototype.emit = function (name) { + if (name == 'newListener') { + return this.$emit.apply(this, arguments); + } + + return this.packet({ + type: 'event' + , name: name + , args: util.toArray(arguments).slice(1) + }); +}; + +/** + * Retrieves or creates a write-only socket for a client, unless specified. + * + * @param {Boolean} whether the socket will be readable when initialized + * @api public + */ + +SocketNamespace.prototype.socket = function (sid, readable) { + if (!this.sockets[sid]) { + this.sockets[sid] = new Socket(this.manager, sid, this, readable); + } + + return this.sockets[sid]; +}; + +/** + * Sets authorization for this namespace. + * + * @api public + */ + +SocketNamespace.prototype.authorization = function (fn) { + this.auth = fn; + return this; +}; + +/** + * Called when a socket disconnects entirely. + * + * @api private + */ + +SocketNamespace.prototype.handleDisconnect = function (sid, reason, raiseOnDisconnect) { + if (this.sockets[sid] && this.sockets[sid].readable) { + if (raiseOnDisconnect) this.sockets[sid].onDisconnect(reason); + delete this.sockets[sid]; + } +}; + +/** + * Performs authentication. + * + * @param Object client request data + * @api private + */ + +SocketNamespace.prototype.authorize = function (data, fn) { + if (this.auth) { + var self = this; + + this.auth.call(this, data, function (err, authorized) { + self.log.debug('client ' + + (authorized ? '' : 'un') + 'authorized for ' + self.name); + fn(err, authorized); + }); + } else { + this.log.debug('client authorized for ' + this.name); + fn(null, true); + } + + return this; +}; + +/** + * Handles a packet. + * + * @api private + */ + +SocketNamespace.prototype.handlePacket = function (sessid, packet) { + var socket = this.socket(sessid) + , dataAck = packet.ack == 'data' + , manager = this.manager + , self = this; + + function ack () { + self.log.debug('sending data ack packet'); + socket.packet({ + type: 'ack' + , args: util.toArray(arguments) + , ackId: packet.id + }); + }; + + function error (err) { + self.log.warn('handshake error ' + err + ' for ' + self.name); + socket.packet({ type: 'error', reason: err }); + }; + + function connect () { + self.manager.onJoin(sessid, self.name); + self.store.publish('join', sessid, self.name); + + // packet echo + socket.packet({ type: 'connect' }); + + // emit connection event + self.$emit('connection', socket); + }; + + switch (packet.type) { + case 'connect': + if (packet.endpoint == '') { + connect(); + } else { + var handshakeData = manager.handshaken[sessid]; + + this.authorize(handshakeData, function (err, authorized, newData) { + if (err) return error(err); + + if (authorized) { + manager.onHandshake(sessid, newData || handshakeData); + self.store.publish('handshake', sessid, newData || handshakeData); + connect(); + } else { + error('unauthorized'); + } + }); + } + break; + + case 'ack': + if (socket.acks[packet.ackId]) { + socket.acks[packet.ackId].apply(socket, packet.args); + } else { + this.log.info('unknown ack packet'); + } + break; + + case 'event': + // check if the emitted event is not blacklisted + if (-~manager.get('blacklist').indexOf(packet.name)) { + this.log.debug('ignoring blacklisted event `' + packet.name + '`'); + } else { + var params = [packet.name].concat(packet.args); + + if (dataAck) { + params.push(ack); + } + + socket.$emit.apply(socket, params); + } + break; + + case 'disconnect': + this.manager.onLeave(sessid, this.name); + this.store.publish('leave', sessid, this.name); + + socket.$emit('disconnect', packet.reason || 'packet'); + break; + + case 'json': + case 'message': + var params = ['message', packet.data]; + + if (dataAck) + params.push(ack); + + socket.$emit.apply(socket, params); + }; +}; diff --git a/node_modules/socket.io/lib/parser.js b/node_modules/socket.io/lib/parser.js new file mode 100644 index 00000000..d56b5500 --- /dev/null +++ b/node_modules/socket.io/lib/parser.js @@ -0,0 +1,249 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +/** + * Packet types. + */ + +var packets = exports.packets = { + 'disconnect': 0 + , 'connect': 1 + , 'heartbeat': 2 + , 'message': 3 + , 'json': 4 + , 'event': 5 + , 'ack': 6 + , 'error': 7 + , 'noop': 8 + } + , packetslist = Object.keys(packets); + +/** + * Errors reasons. + */ + +var reasons = exports.reasons = { + 'transport not supported': 0 + , 'client not handshaken': 1 + , 'unauthorized': 2 + } + , reasonslist = Object.keys(reasons); + +/** + * Errors advice. + */ + +var advice = exports.advice = { + 'reconnect': 0 + } + , advicelist = Object.keys(advice); + +/** + * Encodes a packet. + * + * @api private + */ + +exports.encodePacket = function (packet) { + var type = packets[packet.type] + , id = packet.id || '' + , endpoint = packet.endpoint || '' + , ack = packet.ack + , data = null; + + switch (packet.type) { + case 'message': + if (packet.data !== '') + data = packet.data; + break; + + case 'event': + var ev = { name: packet.name }; + + if (packet.args && packet.args.length) { + ev.args = packet.args; + } + + data = JSON.stringify(ev); + break; + + case 'json': + data = JSON.stringify(packet.data); + break; + + case 'ack': + data = packet.ackId + + (packet.args && packet.args.length + ? '+' + JSON.stringify(packet.args) : ''); + break; + + case 'connect': + if (packet.qs) + data = packet.qs; + break; + + case 'error': + var reason = packet.reason ? reasons[packet.reason] : '' + , adv = packet.advice ? advice[packet.advice] : '' + + if (reason !== '' || adv !== '') + data = reason + (adv !== '' ? ('+' + adv) : '') + + break; + } + + // construct packet with required fragments + var encoded = type + ':' + id + (ack == 'data' ? '+' : '') + ':' + endpoint; + + // data fragment is optional + if (data !== null && data !== undefined) + encoded += ':' + data; + + return encoded; +}; + +/** + * Encodes multiple messages (payload). + * + * @param {Array} messages + * @api private + */ + +exports.encodePayload = function (packets) { + var decoded = ''; + + if (packets.length == 1) + return packets[0]; + + for (var i = 0, l = packets.length; i < l; i++) { + var packet = packets[i]; + decoded += '\ufffd' + packet.length + '\ufffd' + packets[i] + } + + return decoded; +}; + +/** + * Decodes a packet + * + * @api private + */ + +var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/; + +/** + * Wrap the JSON.parse in a seperate function the crankshaft optimizer will + * only punish this function for the usage for try catch + * + * @api private + */ + +function parse (data) { + try { return JSON.parse(data) } + catch (e) { return false } +} + +exports.decodePacket = function (data) { + var pieces = data.match(regexp); + + if (!pieces) return {}; + + var id = pieces[2] || '' + , data = pieces[5] || '' + , packet = { + type: packetslist[pieces[1]] + , endpoint: pieces[4] || '' + }; + + // whether we need to acknowledge the packet + if (id) { + packet.id = id; + if (pieces[3]) + packet.ack = 'data'; + else + packet.ack = true; + } + + // handle different packet types + switch (packet.type) { + case 'message': + packet.data = data || ''; + break; + + case 'event': + pieces = parse(data); + if (pieces) { + packet.name = pieces.name; + packet.args = pieces.args; + } + + packet.args = packet.args || []; + break; + + case 'json': + packet.data = parse(data); + break; + + case 'connect': + packet.qs = data || ''; + break; + + case 'ack': + pieces = data.match(/^([0-9]+)(\+)?(.*)/); + if (pieces) { + packet.ackId = pieces[1]; + packet.args = []; + + if (pieces[3]) { + packet.args = parse(pieces[3]) || []; + } + } + break; + + case 'error': + pieces = data.split('+'); + packet.reason = reasonslist[pieces[0]] || ''; + packet.advice = advicelist[pieces[1]] || ''; + } + + return packet; +}; + +/** + * Decodes data payload. Detects multiple messages + * + * @return {Array} messages + * @api public + */ + +exports.decodePayload = function (data) { + if (undefined == data || null == data) { + return []; + } + + if (data[0] == '\ufffd') { + var ret = []; + + for (var i = 1, length = ''; i < data.length; i++) { + if (data[i] == '\ufffd') { + ret.push(exports.decodePacket(data.substr(i + 1, length))); + i += Number(length) + 1; + length = ''; + } else { + length += data[i]; + } + } + + return ret; + } else { + return [exports.decodePacket(data)]; + } +}; diff --git a/node_modules/socket.io/lib/socket.io.js b/node_modules/socket.io/lib/socket.io.js new file mode 100644 index 00000000..d9d1c1fd --- /dev/null +++ b/node_modules/socket.io/lib/socket.io.js @@ -0,0 +1,143 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var client = require('socket.io-client'); + +/** + * Version. + */ + +exports.version = '0.9.16'; + +/** + * Supported protocol version. + */ + +exports.protocol = 1; + +/** + * Client that we serve. + */ + +exports.clientVersion = client.version; + +/** + * Attaches a manager + * + * @param {HTTPServer/Number} a HTTP/S server or a port number to listen on. + * @param {Object} opts to be passed to Manager and/or http server + * @param {Function} callback if a port is supplied + * @api public + */ + +exports.listen = function (server, options, fn) { + if ('function' == typeof server) { + console.warn('Socket.IO\'s `listen()` method expects an `http.Server` instance\n' + + 'as its first parameter. Are you migrating from Express 2.x to 3.x?\n' + + 'If so, check out the "Socket.IO compatibility" section at:\n' + + 'https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x'); + } + + if ('function' == typeof options) { + fn = options; + options = {}; + } + + if ('undefined' == typeof server) { + // create a server that listens on port 80 + server = 80; + } + + if ('number' == typeof server) { + // if a port number is passed + var port = server; + + if (options && options.key) + server = require('https').createServer(options); + else + server = require('http').createServer(); + + // default response + server.on('request', function (req, res) { + res.writeHead(200); + res.end('Welcome to socket.io.'); + }); + + server.listen(port, fn); + } + + // otherwise assume a http/s server + return new exports.Manager(server, options); +}; + +/** + * Manager constructor. + * + * @api public + */ + +exports.Manager = require('./manager'); + +/** + * Transport constructor. + * + * @api public + */ + +exports.Transport = require('./transport'); + +/** + * Socket constructor. + * + * @api public + */ + +exports.Socket = require('./socket'); + +/** + * Static constructor. + * + * @api public + */ + +exports.Static = require('./static'); + +/** + * Store constructor. + * + * @api public + */ + +exports.Store = require('./store'); + +/** + * Memory Store constructor. + * + * @api public + */ + +exports.MemoryStore = require('./stores/memory'); + +/** + * Redis Store constructor. + * + * @api public + */ + +exports.RedisStore = require('./stores/redis'); + +/** + * Parser. + * + * @api public + */ + +exports.parser = require('./parser'); diff --git a/node_modules/socket.io/lib/socket.js b/node_modules/socket.io/lib/socket.js new file mode 100644 index 00000000..d9807f6d --- /dev/null +++ b/node_modules/socket.io/lib/socket.js @@ -0,0 +1,369 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var parser = require('./parser') + , util = require('./util') + , EventEmitter = process.EventEmitter + +/** + * Export the constructor. + */ + +exports = module.exports = Socket; + +/** + * Default error event listener to prevent uncaught exceptions. + */ + +var defaultError = function () {}; + +/** + * Socket constructor. + * + * @param {Manager} manager instance + * @param {String} session id + * @param {Namespace} namespace the socket belongs to + * @param {Boolean} whether the + * @api public + */ + +function Socket (manager, id, nsp, readable) { + this.id = id; + this.namespace = nsp; + this.manager = manager; + this.disconnected = false; + this.ackPackets = 0; + this.acks = {}; + this.setFlags(); + this.readable = readable; + this.store = this.manager.store.client(this.id); + this.on('error', defaultError); +}; + +/** + * Inherits from EventEmitter. + */ + +Socket.prototype.__proto__ = EventEmitter.prototype; + +/** + * Accessor shortcut for the handshake data + * + * @api private + */ + +Socket.prototype.__defineGetter__('handshake', function () { + return this.manager.handshaken[this.id]; +}); + +/** + * Accessor shortcut for the transport type + * + * @api private + */ + +Socket.prototype.__defineGetter__('transport', function () { + return this.manager.transports[this.id].name; +}); + +/** + * Accessor shortcut for the logger. + * + * @api private + */ + +Socket.prototype.__defineGetter__('log', function () { + return this.manager.log; +}); + +/** + * JSON message flag. + * + * @api public + */ + +Socket.prototype.__defineGetter__('json', function () { + this.flags.json = true; + return this; +}); + +/** + * Volatile message flag. + * + * @api public + */ + +Socket.prototype.__defineGetter__('volatile', function () { + this.flags.volatile = true; + return this; +}); + +/** + * Broadcast message flag. + * + * @api public + */ + +Socket.prototype.__defineGetter__('broadcast', function () { + this.flags.broadcast = true; + return this; +}); + +/** + * Overrides the room to broadcast messages to (flag) + * + * @api public + */ + +Socket.prototype.to = Socket.prototype.in = function (room) { + this.flags.room = room; + return this; +}; + +/** + * Resets flags + * + * @api private + */ + +Socket.prototype.setFlags = function () { + this.flags = { + endpoint: this.namespace.name + , room: '' + }; + return this; +}; + +/** + * Triggered on disconnect + * + * @api private + */ + +Socket.prototype.onDisconnect = function (reason) { + if (!this.disconnected) { + this.$emit('disconnect', reason); + this.disconnected = true; + } +}; + +/** + * Joins a user to a room. + * + * @api public + */ + +Socket.prototype.join = function (name, fn) { + var nsp = this.namespace.name + , name = (nsp + '/') + name; + + this.manager.onJoin(this.id, name); + this.manager.store.publish('join', this.id, name); + + if (fn) { + this.log.warn('Client#join callback is deprecated'); + fn(); + } + + return this; +}; + +/** + * Un-joins a user from a room. + * + * @api public + */ + +Socket.prototype.leave = function (name, fn) { + var nsp = this.namespace.name + , name = (nsp + '/') + name; + + this.manager.onLeave(this.id, name); + this.manager.store.publish('leave', this.id, name); + + if (fn) { + this.log.warn('Client#leave callback is deprecated'); + fn(); + } + + return this; +}; + +/** + * Transmits a packet. + * + * @api private + */ + +Socket.prototype.packet = function (packet) { + if (this.flags.broadcast) { + this.log.debug('broadcasting packet'); + this.namespace.in(this.flags.room).except(this.id).packet(packet); + } else { + packet.endpoint = this.flags.endpoint; + packet = parser.encodePacket(packet); + + this.dispatch(packet, this.flags.volatile); + } + + this.setFlags(); + + return this; +}; + +/** + * Dispatches a packet + * + * @api private + */ + +Socket.prototype.dispatch = function (packet, volatile) { + if (this.manager.transports[this.id] && this.manager.transports[this.id].open) { + this.manager.transports[this.id].onDispatch(packet, volatile); + } else { + if (!volatile) { + this.manager.onClientDispatch(this.id, packet, volatile); + } + + this.manager.store.publish('dispatch:' + this.id, packet, volatile); + } +}; + +/** + * Stores data for the client. + * + * @api public + */ + +Socket.prototype.set = function (key, value, fn) { + this.store.set(key, value, fn); + return this; +}; + +/** + * Retrieves data for the client + * + * @api public + */ + +Socket.prototype.get = function (key, fn) { + this.store.get(key, fn); + return this; +}; + +/** + * Checks data for the client + * + * @api public + */ + +Socket.prototype.has = function (key, fn) { + this.store.has(key, fn); + return this; +}; + +/** + * Deletes data for the client + * + * @api public + */ + +Socket.prototype.del = function (key, fn) { + this.store.del(key, fn); + return this; +}; + +/** + * Kicks client + * + * @api public + */ + +Socket.prototype.disconnect = function () { + if (!this.disconnected) { + this.log.info('booting client'); + + if ('' === this.namespace.name) { + if (this.manager.transports[this.id] && this.manager.transports[this.id].open) { + this.manager.transports[this.id].onForcedDisconnect(); + } else { + this.manager.onClientDisconnect(this.id); + this.manager.store.publish('disconnect:' + this.id); + } + } else { + this.packet({type: 'disconnect'}); + this.manager.onLeave(this.id, this.namespace.name); + this.$emit('disconnect', 'booted'); + } + + } + + return this; +}; + +/** + * Send a message. + * + * @api public + */ + +Socket.prototype.send = function (data, fn) { + var packet = { + type: this.flags.json ? 'json' : 'message' + , data: data + }; + + if (fn) { + packet.id = ++this.ackPackets; + packet.ack = true; + this.acks[packet.id] = fn; + } + + return this.packet(packet); +}; + +/** + * Original emit function. + * + * @api private + */ + +Socket.prototype.$emit = EventEmitter.prototype.emit; + +/** + * Emit override for custom events. + * + * @api public + */ + +Socket.prototype.emit = function (ev) { + if (ev == 'newListener') { + return this.$emit.apply(this, arguments); + } + + var args = util.toArray(arguments).slice(1) + , lastArg = args[args.length - 1] + , packet = { + type: 'event' + , name: ev + }; + + if ('function' == typeof lastArg) { + packet.id = ++this.ackPackets; + packet.ack = lastArg.length ? 'data' : true; + this.acks[packet.id] = lastArg; + args = args.slice(0, args.length - 1); + } + + packet.args = args; + + return this.packet(packet); +}; diff --git a/node_modules/socket.io/lib/static.js b/node_modules/socket.io/lib/static.js new file mode 100644 index 00000000..fe505937 --- /dev/null +++ b/node_modules/socket.io/lib/static.js @@ -0,0 +1,395 @@ + +/*! +* socket.io-node +* Copyright(c) 2011 LearnBoost +* MIT Licensed +*/ + +/** + * Module dependencies. + */ + +var client = require('socket.io-client') + , cp = require('child_process') + , fs = require('fs') + , util = require('./util'); + +/** + * File type details. + * + * @api private + */ + +var mime = { + js: { + type: 'application/javascript' + , encoding: 'utf8' + , gzip: true + } + , swf: { + type: 'application/x-shockwave-flash' + , encoding: 'binary' + , gzip: false + } +}; + +/** + * Regexp for matching custom transport patterns. Users can configure their own + * socket.io bundle based on the url structure. Different transport names are + * concatinated using the `+` char. /socket.io/socket.io+websocket.js should + * create a bundle that only contains support for the websocket. + * + * @api private + */ + +var bundle = /\+((?:\+)?[\w\-]+)*(?:\.v\d+\.\d+\.\d+)?(?:\.js)$/ + , versioning = /\.v\d+\.\d+\.\d+(?:\.js)$/; + +/** + * Export the constructor + */ + +exports = module.exports = Static; + +/** + * Static constructor + * + * @api public + */ + +function Static (manager) { + this.manager = manager; + this.cache = {}; + this.paths = {}; + + this.init(); +} + +/** + * Initialize the Static by adding default file paths. + * + * @api public + */ + +Static.prototype.init = function () { + /** + * Generates a unique id based the supplied transports array + * + * @param {Array} transports The array with transport types + * @api private + */ + function id (transports) { + var id = transports.join('').split('').map(function (char) { + return ('' + char.charCodeAt(0)).split('').pop(); + }).reduce(function (char, id) { + return char +id; + }); + + return client.version + ':' + id; + } + + /** + * Generates a socket.io-client file based on the supplied transports. + * + * @param {Array} transports The array with transport types + * @param {Function} callback Callback for the static.write + * @api private + */ + + function build (transports, callback) { + client.builder(transports, { + minify: self.manager.enabled('browser client minification') + }, function (err, content) { + callback(err, content ? new Buffer(content) : null, id(transports)); + } + ); + } + + var self = this; + + // add our default static files + this.add('/static/flashsocket/WebSocketMain.swf', { + file: client.dist + '/WebSocketMain.swf' + }); + + this.add('/static/flashsocket/WebSocketMainInsecure.swf', { + file: client.dist + '/WebSocketMainInsecure.swf' + }); + + // generates dedicated build based on the available transports + this.add('/socket.io.js', function (path, callback) { + build(self.manager.get('transports'), callback); + }); + + this.add('/socket.io.v', { mime: mime.js }, function (path, callback) { + build(self.manager.get('transports'), callback); + }); + + // allow custom builds based on url paths + this.add('/socket.io+', { mime: mime.js }, function (path, callback) { + var available = self.manager.get('transports') + , matches = path.match(bundle) + , transports = []; + + if (!matches) return callback('No valid transports'); + + // make sure they valid transports + matches[0].split('.')[0].split('+').slice(1).forEach(function (transport) { + if (!!~available.indexOf(transport)) { + transports.push(transport); + } + }); + + if (!transports.length) return callback('No valid transports'); + build(transports, callback); + }); + + // clear cache when transports change + this.manager.on('set:transports', function (key, value) { + delete self.cache['/socket.io.js']; + Object.keys(self.cache).forEach(function (key) { + if (bundle.test(key)) { + delete self.cache[key]; + } + }); + }); +}; + +/** + * Gzip compress buffers. + * + * @param {Buffer} data The buffer that needs gzip compression + * @param {Function} callback + * @api public + */ + +Static.prototype.gzip = function (data, callback) { + var gzip = cp.spawn('gzip', ['-9', '-c', '-f', '-n']) + , encoding = Buffer.isBuffer(data) ? 'binary' : 'utf8' + , buffer = [] + , err; + + gzip.stdout.on('data', function (data) { + buffer.push(data); + }); + + gzip.stderr.on('data', function (data) { + err = data +''; + buffer.length = 0; + }); + + gzip.on('close', function () { + if (err) return callback(err); + + var size = 0 + , index = 0 + , i = buffer.length + , content; + + while (i--) { + size += buffer[i].length; + } + + content = new Buffer(size); + i = buffer.length; + + buffer.forEach(function (buffer) { + var length = buffer.length; + + buffer.copy(content, index, 0, length); + index += length; + }); + + buffer.length = 0; + callback(null, content); + }); + + gzip.stdin.end(data, encoding); +}; + +/** + * Is the path a static file? + * + * @param {String} path The path that needs to be checked + * @api public + */ + +Static.prototype.has = function (path) { + // fast case + if (this.paths[path]) return this.paths[path]; + + var keys = Object.keys(this.paths) + , i = keys.length; + + while (i--) { + if (-~path.indexOf(keys[i])) return this.paths[keys[i]]; + } + + return false; +}; + +/** + * Add new paths new paths that can be served using the static provider. + * + * @param {String} path The path to respond to + * @param {Options} options Options for writing out the response + * @param {Function} [callback] Optional callback if no options.file is + * supplied this would be called instead. + * @api public + */ + +Static.prototype.add = function (path, options, callback) { + var extension = /(?:\.(\w{1,4}))$/.exec(path); + + if (!callback && typeof options == 'function') { + callback = options; + options = {}; + } + + options.mime = options.mime || (extension ? mime[extension[1]] : false); + + if (callback) options.callback = callback; + if (!(options.file || options.callback) || !options.mime) return false; + + this.paths[path] = options; + + return true; +}; + +/** + * Writes a static response. + * + * @param {String} path The path for the static content + * @param {HTTPRequest} req The request object + * @param {HTTPResponse} res The response object + * @api public + */ + +Static.prototype.write = function (path, req, res) { + /** + * Write a response without throwing errors because can throw error if the + * response is no longer writable etc. + * + * @api private + */ + + function write (status, headers, content, encoding) { + try { + res.writeHead(status, headers || undefined); + + // only write content if it's not a HEAD request and we actually have + // some content to write (304's doesn't have content). + res.end( + req.method !== 'HEAD' && content ? content : '' + , encoding || undefined + ); + } catch (e) {} + } + + /** + * Answers requests depending on the request properties and the reply object. + * + * @param {Object} reply The details and content to reply the response with + * @api private + */ + + function answer (reply) { + var cached = req.headers['if-none-match'] === reply.etag; + if (cached && self.manager.enabled('browser client etag')) { + return write(304); + } + + var accept = req.headers['accept-encoding'] || '' + , gzip = !!~accept.toLowerCase().indexOf('gzip') + , mime = reply.mime + , versioned = reply.versioned + , headers = { + 'Content-Type': mime.type + }; + + // check if we can add a etag + if (self.manager.enabled('browser client etag') && reply.etag && !versioned) { + headers['Etag'] = reply.etag; + } + + // see if we need to set Expire headers because the path is versioned + if (versioned) { + var expires = self.manager.get('browser client expires'); + headers['Cache-Control'] = 'private, x-gzip-ok="", max-age=' + expires; + headers['Date'] = new Date().toUTCString(); + headers['Expires'] = new Date(Date.now() + (expires * 1000)).toUTCString(); + } + + if (gzip && reply.gzip) { + headers['Content-Length'] = reply.gzip.length; + headers['Content-Encoding'] = 'gzip'; + headers['Vary'] = 'Accept-Encoding'; + write(200, headers, reply.gzip.content, mime.encoding); + } else { + headers['Content-Length'] = reply.length; + write(200, headers, reply.content, mime.encoding); + } + + self.manager.log.debug('served static content ' + path); + } + + var self = this + , details; + + // most common case first + if (this.manager.enabled('browser client cache') && this.cache[path]) { + return answer(this.cache[path]); + } else if (this.manager.get('browser client handler')) { + return this.manager.get('browser client handler').call(this, req, res); + } else if ((details = this.has(path))) { + /** + * A small helper function that will let us deal with fs and dynamic files + * + * @param {Object} err Optional error + * @param {Buffer} content The data + * @api private + */ + + function ready (err, content, etag) { + if (err) { + self.manager.log.warn('Unable to serve file. ' + (err.message || err)); + return write(500, null, 'Error serving static ' + path); + } + + // store the result in the cache + var reply = self.cache[path] = { + content: content + , length: content.length + , mime: details.mime + , etag: etag || client.version + , versioned: versioning.test(path) + }; + + // check if gzip is enabled + if (details.mime.gzip && self.manager.enabled('browser client gzip')) { + self.gzip(content, function (err, content) { + if (!err) { + reply.gzip = { + content: content + , length: content.length + } + } + + answer(reply); + }); + } else { + answer(reply); + } + } + + if (details.file) { + fs.readFile(details.file, ready); + } else if(details.callback) { + details.callback.call(this, path, ready); + } else { + write(404, null, 'File handle not found'); + } + } else { + write(404, null, 'File not found'); + } +}; diff --git a/node_modules/socket.io/lib/store.js b/node_modules/socket.io/lib/store.js new file mode 100644 index 00000000..06c0389a --- /dev/null +++ b/node_modules/socket.io/lib/store.js @@ -0,0 +1,98 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Expose the constructor. + */ + +exports = module.exports = Store; + +/** + * Module dependencies. + */ + +var EventEmitter = process.EventEmitter; + +/** + * Store interface + * + * @api public + */ + +function Store (options) { + this.options = options; + this.clients = {}; +}; + +/** + * Inherit from EventEmitter. + */ + +Store.prototype.__proto__ = EventEmitter.prototype; + +/** + * Initializes a client store + * + * @param {String} id + * @api public + */ + +Store.prototype.client = function (id) { + if (!this.clients[id]) { + this.clients[id] = new (this.constructor.Client)(this, id); + } + + return this.clients[id]; +}; + +/** + * Destroys a client + * + * @api {String} sid + * @param {Number} number of seconds to expire client data + * @api private + */ + +Store.prototype.destroyClient = function (id, expiration) { + if (this.clients[id]) { + this.clients[id].destroy(expiration); + delete this.clients[id]; + } + + return this; +}; + +/** + * Destroys the store + * + * @param {Number} number of seconds to expire client data + * @api private + */ + +Store.prototype.destroy = function (clientExpiration) { + var keys = Object.keys(this.clients) + , count = keys.length; + + for (var i = 0, l = count; i < l; i++) { + this.destroyClient(keys[i], clientExpiration); + } + + this.clients = {}; + + return this; +}; + +/** + * Client. + * + * @api public + */ + +Store.Client = function (store, id) { + this.store = store; + this.id = id; +}; diff --git a/node_modules/socket.io/lib/stores/memory.js b/node_modules/socket.io/lib/stores/memory.js new file mode 100644 index 00000000..8b731a79 --- /dev/null +++ b/node_modules/socket.io/lib/stores/memory.js @@ -0,0 +1,143 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var crypto = require('crypto') + , Store = require('../store'); + +/** + * Exports the constructor. + */ + +exports = module.exports = Memory; +Memory.Client = Client; + +/** + * Memory store + * + * @api public + */ + +function Memory (opts) { + Store.call(this, opts); +}; + +/** + * Inherits from Store. + */ + +Memory.prototype.__proto__ = Store.prototype; + +/** + * Publishes a message. + * + * @api private + */ + +Memory.prototype.publish = function () { }; + +/** + * Subscribes to a channel + * + * @api private + */ + +Memory.prototype.subscribe = function () { }; + +/** + * Unsubscribes + * + * @api private + */ + +Memory.prototype.unsubscribe = function () { }; + +/** + * Client constructor + * + * @api private + */ + +function Client () { + Store.Client.apply(this, arguments); + this.data = {}; +}; + +/** + * Inherits from Store.Client + */ + +Client.prototype.__proto__ = Store.Client; + +/** + * Gets a key + * + * @api public + */ + +Client.prototype.get = function (key, fn) { + fn(null, this.data[key] === undefined ? null : this.data[key]); + return this; +}; + +/** + * Sets a key + * + * @api public + */ + +Client.prototype.set = function (key, value, fn) { + this.data[key] = value; + fn && fn(null); + return this; +}; + +/** + * Has a key + * + * @api public + */ + +Client.prototype.has = function (key, fn) { + fn(null, key in this.data); +}; + +/** + * Deletes a key + * + * @api public + */ + +Client.prototype.del = function (key, fn) { + delete this.data[key]; + fn && fn(null); + return this; +}; + +/** + * Destroys the client. + * + * @param {Number} number of seconds to expire data + * @api private + */ + +Client.prototype.destroy = function (expiration) { + if ('number' != typeof expiration) { + this.data = {}; + } else { + var self = this; + + setTimeout(function () { + self.data = {}; + }, expiration * 1000); + } + + return this; +}; diff --git a/node_modules/socket.io/lib/stores/redis.js b/node_modules/socket.io/lib/stores/redis.js new file mode 100644 index 00000000..8fea235f --- /dev/null +++ b/node_modules/socket.io/lib/stores/redis.js @@ -0,0 +1,269 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var crypto = require('crypto') + , Store = require('../store') + , assert = require('assert'); + +/** + * Exports the constructor. + */ + +exports = module.exports = Redis; +Redis.Client = Client; + +/** + * Redis store. + * Options: + * - nodeId (fn) gets an id that uniquely identifies this node + * - redis (fn) redis constructor, defaults to redis + * - redisPub (object) options to pass to the pub redis client + * - redisSub (object) options to pass to the sub redis client + * - redisClient (object) options to pass to the general redis client + * - pack (fn) custom packing, defaults to JSON or msgpack if installed + * - unpack (fn) custom packing, defaults to JSON or msgpack if installed + * + * @api public + */ + +function Redis (opts) { + opts = opts || {}; + + // node id to uniquely identify this node + var nodeId = opts.nodeId || function () { + // by default, we generate a random id + return Math.abs(Math.random() * Math.random() * Date.now() | 0); + }; + + this.nodeId = nodeId(); + + // packing / unpacking mechanism + if (opts.pack) { + this.pack = opts.pack; + this.unpack = opts.unpack; + } else { + try { + var msgpack = require('msgpack'); + this.pack = msgpack.pack; + this.unpack = msgpack.unpack; + } catch (e) { + this.pack = JSON.stringify; + this.unpack = JSON.parse; + } + } + + var redis = opts.redis || require('redis') + , RedisClient = redis.RedisClient; + + // initialize a pubsub client and a regular client + if (opts.redisPub instanceof RedisClient) { + this.pub = opts.redisPub; + } else { + opts.redisPub || (opts.redisPub = {}); + this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub); + } + if (opts.redisSub instanceof RedisClient) { + this.sub = opts.redisSub; + } else { + opts.redisSub || (opts.redisSub = {}); + this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub); + } + if (opts.redisClient instanceof RedisClient) { + this.cmd = opts.redisClient; + } else { + opts.redisClient || (opts.redisClient = {}); + this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host, opts.redisClient); + } + + Store.call(this, opts); + + this.sub.setMaxListeners(0); + this.setMaxListeners(0); +}; + +/** + * Inherits from Store. + */ + +Redis.prototype.__proto__ = Store.prototype; + +/** + * Publishes a message. + * + * @api private + */ + +Redis.prototype.publish = function (name) { + var args = Array.prototype.slice.call(arguments, 1); + this.pub.publish(name, this.pack({ nodeId: this.nodeId, args: args })); + this.emit.apply(this, ['publish', name].concat(args)); +}; + +/** + * Subscribes to a channel + * + * @api private + */ + +Redis.prototype.subscribe = function (name, consumer, fn) { + this.sub.subscribe(name); + + if (consumer || fn) { + var self = this; + + self.sub.on('subscribe', function subscribe (ch) { + if (name == ch) { + function message (ch, msg) { + if (name == ch) { + msg = self.unpack(msg); + + // we check that the message consumed wasnt emitted by this node + if (self.nodeId != msg.nodeId) { + consumer.apply(null, msg.args); + } + } + }; + + self.sub.on('message', message); + + self.on('unsubscribe', function unsubscribe (ch) { + if (name == ch) { + self.sub.removeListener('message', message); + self.removeListener('unsubscribe', unsubscribe); + } + }); + + self.sub.removeListener('subscribe', subscribe); + + fn && fn(); + } + }); + } + + this.emit('subscribe', name, consumer, fn); +}; + +/** + * Unsubscribes + * + * @api private + */ + +Redis.prototype.unsubscribe = function (name, fn) { + this.sub.unsubscribe(name); + + if (fn) { + var client = this.sub; + + client.on('unsubscribe', function unsubscribe (ch) { + if (name == ch) { + fn(); + client.removeListener('unsubscribe', unsubscribe); + } + }); + } + + this.emit('unsubscribe', name, fn); +}; + +/** + * Destroys the store + * + * @api public + */ + +Redis.prototype.destroy = function () { + Store.prototype.destroy.call(this); + + this.pub.end(); + this.sub.end(); + this.cmd.end(); +}; + +/** + * Client constructor + * + * @api private + */ + +function Client (store, id) { + Store.Client.call(this, store, id); +}; + +/** + * Inherits from Store.Client + */ + +Client.prototype.__proto__ = Store.Client; + +/** + * Redis hash get + * + * @api private + */ + +Client.prototype.get = function (key, fn) { + this.store.cmd.hget(this.id, key, fn); + return this; +}; + +/** + * Redis hash set + * + * @api private + */ + +Client.prototype.set = function (key, value, fn) { + this.store.cmd.hset(this.id, key, value, fn); + return this; +}; + +/** + * Redis hash del + * + * @api private + */ + +Client.prototype.del = function (key, fn) { + this.store.cmd.hdel(this.id, key, fn); + return this; +}; + +/** + * Redis hash has + * + * @api private + */ + +Client.prototype.has = function (key, fn) { + this.store.cmd.hexists(this.id, key, function (err, has) { + if (err) return fn(err); + fn(null, !!has); + }); + return this; +}; + +/** + * Destroys client + * + * @param {Number} number of seconds to expire data + * @api private + */ + +Client.prototype.destroy = function (expiration) { + if ('number' != typeof expiration) { + this.store.cmd.del(this.id); + } else { + this.store.cmd.expire(this.id, expiration); + } + + return this; +}; diff --git a/node_modules/socket.io/lib/transport.js b/node_modules/socket.io/lib/transport.js new file mode 100644 index 00000000..2e4c08bd --- /dev/null +++ b/node_modules/socket.io/lib/transport.js @@ -0,0 +1,534 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var parser = require('./parser'); + +/** + * Expose the constructor. + */ + +exports = module.exports = Transport; + +/** + * Transport constructor. + * + * @api public + */ + +function Transport (mng, data, req) { + this.manager = mng; + this.id = data.id; + this.disconnected = false; + this.drained = true; + this.handleRequest(req); +}; + +/** + * Access the logger. + * + * @api public + */ + +Transport.prototype.__defineGetter__('log', function () { + return this.manager.log; +}); + +/** + * Access the store. + * + * @api public + */ + +Transport.prototype.__defineGetter__('store', function () { + return this.manager.store; +}); + +/** + * Handles a request when it's set. + * + * @api private + */ + +Transport.prototype.handleRequest = function (req) { + this.log.debug('setting request', req.method, req.url); + this.req = req; + + if (req.method == 'GET') { + this.socket = req.socket; + this.open = true; + this.drained = true; + this.setHeartbeatInterval(); + + this.setHandlers(); + this.onSocketConnect(); + } +}; + +/** + * Called when a connection is first set. + * + * @api private + */ + +Transport.prototype.onSocketConnect = function () { }; + +/** + * Sets transport handlers + * + * @api private + */ + +Transport.prototype.setHandlers = function () { + var self = this; + + // we need to do this in a pub/sub way since the client can POST the message + // over a different socket (ie: different Transport instance) + this.store.subscribe('heartbeat-clear:' + this.id, function () { + self.onHeartbeatClear(); + }); + + this.store.subscribe('disconnect-force:' + this.id, function () { + self.onForcedDisconnect(); + }); + + this.store.subscribe('dispatch:' + this.id, function (packet, volatile) { + self.onDispatch(packet, volatile); + }); + + this.bound = { + end: this.onSocketEnd.bind(this) + , close: this.onSocketClose.bind(this) + , error: this.onSocketError.bind(this) + , drain: this.onSocketDrain.bind(this) + }; + + this.socket.on('end', this.bound.end); + this.socket.on('close', this.bound.close); + this.socket.on('error', this.bound.error); + this.socket.on('drain', this.bound.drain); + + this.handlersSet = true; +}; + +/** + * Removes transport handlers + * + * @api private + */ + +Transport.prototype.clearHandlers = function () { + if (this.handlersSet) { + this.store.unsubscribe('disconnect-force:' + this.id); + this.store.unsubscribe('heartbeat-clear:' + this.id); + this.store.unsubscribe('dispatch:' + this.id); + + this.socket.removeListener('end', this.bound.end); + this.socket.removeListener('close', this.bound.close); + this.socket.removeListener('error', this.bound.error); + this.socket.removeListener('drain', this.bound.drain); + } +}; + +/** + * Called when the connection dies + * + * @api private + */ + +Transport.prototype.onSocketEnd = function () { + this.end('socket end'); +}; + +/** + * Called when the connection dies + * + * @api private + */ + +Transport.prototype.onSocketClose = function (error) { + this.end(error ? 'socket error' : 'socket close'); +}; + +/** + * Called when the connection has an error. + * + * @api private + */ + +Transport.prototype.onSocketError = function (err) { + if (this.open) { + this.socket.destroy(); + this.onClose(); + } + + this.log.info('socket error ' + err.stack); +}; + +/** + * Called when the connection is drained. + * + * @api private + */ + +Transport.prototype.onSocketDrain = function () { + this.drained = true; +}; + +/** + * Called upon receiving a heartbeat packet. + * + * @api private + */ + +Transport.prototype.onHeartbeatClear = function () { + this.clearHeartbeatTimeout(); + this.setHeartbeatInterval(); +}; + +/** + * Called upon a forced disconnection. + * + * @api private + */ + +Transport.prototype.onForcedDisconnect = function () { + if (!this.disconnected) { + this.log.info('transport end by forced client disconnection'); + if (this.open) { + this.packet({ type: 'disconnect' }); + } + this.end('booted'); + } +}; + +/** + * Dispatches a packet. + * + * @api private + */ + +Transport.prototype.onDispatch = function (packet, volatile) { + if (volatile) { + this.writeVolatile(packet); + } else { + this.write(packet); + } +}; + +/** + * Sets the close timeout. + */ + +Transport.prototype.setCloseTimeout = function () { + if (!this.closeTimeout) { + var self = this; + + this.closeTimeout = setTimeout(function () { + self.log.debug('fired close timeout for client', self.id); + self.closeTimeout = null; + self.end('close timeout'); + }, this.manager.get('close timeout') * 1000); + + this.log.debug('set close timeout for client', this.id); + } +}; + +/** + * Clears the close timeout. + */ + +Transport.prototype.clearCloseTimeout = function () { + if (this.closeTimeout) { + clearTimeout(this.closeTimeout); + this.closeTimeout = null; + + this.log.debug('cleared close timeout for client', this.id); + } +}; + +/** + * Sets the heartbeat timeout + */ + +Transport.prototype.setHeartbeatTimeout = function () { + if (!this.heartbeatTimeout && this.manager.enabled('heartbeats')) { + var self = this; + + this.heartbeatTimeout = setTimeout(function () { + self.log.debug('fired heartbeat timeout for client', self.id); + self.heartbeatTimeout = null; + self.end('heartbeat timeout'); + }, this.manager.get('heartbeat timeout') * 1000); + + this.log.debug('set heartbeat timeout for client', this.id); + } +}; + +/** + * Clears the heartbeat timeout + * + * @param text + */ + +Transport.prototype.clearHeartbeatTimeout = function () { + if (this.heartbeatTimeout && this.manager.enabled('heartbeats')) { + clearTimeout(this.heartbeatTimeout); + this.heartbeatTimeout = null; + this.log.debug('cleared heartbeat timeout for client', this.id); + } +}; + +/** + * Sets the heartbeat interval. To be called when a connection opens and when + * a heartbeat is received. + * + * @api private + */ + +Transport.prototype.setHeartbeatInterval = function () { + if (!this.heartbeatInterval && this.manager.enabled('heartbeats')) { + var self = this; + + this.heartbeatInterval = setTimeout(function () { + self.heartbeat(); + self.heartbeatInterval = null; + }, this.manager.get('heartbeat interval') * 1000); + + this.log.debug('set heartbeat interval for client', this.id); + } +}; + +/** + * Clears all timeouts. + * + * @api private + */ + +Transport.prototype.clearTimeouts = function () { + this.clearCloseTimeout(); + this.clearHeartbeatTimeout(); + this.clearHeartbeatInterval(); +}; + +/** + * Sends a heartbeat + * + * @api private + */ + +Transport.prototype.heartbeat = function () { + if (this.open) { + this.log.debug('emitting heartbeat for client', this.id); + this.packet({ type: 'heartbeat' }); + this.setHeartbeatTimeout(); + } + + return this; +}; + +/** + * Handles a message. + * + * @param {Object} packet object + * @api private + */ + +Transport.prototype.onMessage = function (packet) { + var current = this.manager.transports[this.id]; + + if ('heartbeat' == packet.type) { + this.log.debug('got heartbeat packet'); + + if (current && current.open) { + current.onHeartbeatClear(); + } else { + this.store.publish('heartbeat-clear:' + this.id); + } + } else { + if ('disconnect' == packet.type && packet.endpoint == '') { + this.log.debug('got disconnection packet'); + + if (current) { + current.onForcedDisconnect(); + } else { + this.store.publish('disconnect-force:' + this.id); + } + + return; + } + + if (packet.id && packet.ack != 'data') { + this.log.debug('acknowledging packet automatically'); + + var ack = parser.encodePacket({ + type: 'ack' + , ackId: packet.id + , endpoint: packet.endpoint || '' + }); + + if (current && current.open) { + current.onDispatch(ack); + } else { + this.manager.onClientDispatch(this.id, ack); + this.store.publish('dispatch:' + this.id, ack); + } + } + + // handle packet locally or publish it + if (current) { + this.manager.onClientMessage(this.id, packet); + } else { + this.store.publish('message:' + this.id, packet); + } + } +}; + +/** + * Clears the heartbeat interval + * + * @api private + */ + +Transport.prototype.clearHeartbeatInterval = function () { + if (this.heartbeatInterval && this.manager.enabled('heartbeats')) { + clearTimeout(this.heartbeatInterval); + this.heartbeatInterval = null; + this.log.debug('cleared heartbeat interval for client', this.id); + } +}; + +/** + * Finishes the connection and makes sure client doesn't reopen + * + * @api private + */ + +Transport.prototype.disconnect = function (reason) { + this.packet({ type: 'disconnect' }); + this.end(reason); + + return this; +}; + +/** + * Closes the connection. + * + * @api private + */ + +Transport.prototype.close = function () { + if (this.open) { + this.doClose(); + this.onClose(); + } +}; + +/** + * Called upon a connection close. + * + * @api private + */ + +Transport.prototype.onClose = function () { + if (this.open) { + this.setCloseTimeout(); + this.clearHandlers(); + this.open = false; + this.manager.onClose(this.id); + this.store.publish('close', this.id); + } +}; + +/** + * Cleans up the connection, considers the client disconnected. + * + * @api private + */ + +Transport.prototype.end = function (reason) { + if (!this.disconnected) { + this.log.info('transport end (' + reason + ')'); + + var local = this.manager.transports[this.id]; + + this.close(); + this.clearTimeouts(); + this.disconnected = true; + + if (local) { + this.manager.onClientDisconnect(this.id, reason, true); + } else { + this.store.publish('disconnect:' + this.id, reason); + } + } +}; + +/** + * Signals that the transport should pause and buffer data. + * + * @api public + */ + +Transport.prototype.discard = function () { + this.log.debug('discarding transport'); + this.discarded = true; + this.clearTimeouts(); + this.clearHandlers(); + + return this; +}; + +/** + * Writes an error packet with the specified reason and advice. + * + * @param {Number} advice + * @param {Number} reason + * @api public + */ + +Transport.prototype.error = function (reason, advice) { + this.packet({ + type: 'error' + , reason: reason + , advice: advice + }); + + this.log.warn(reason, advice ? ('client should ' + advice) : ''); + this.end('error'); +}; + +/** + * Write a packet. + * + * @api public + */ + +Transport.prototype.packet = function (obj) { + return this.write(parser.encodePacket(obj)); +}; + +/** + * Writes a volatile message. + * + * @api private + */ + +Transport.prototype.writeVolatile = function (msg) { + if (this.open) { + if (this.drained) { + this.write(msg); + } else { + this.log.debug('ignoring volatile packet, buffer not drained'); + } + } else { + this.log.debug('ignoring volatile packet, transport not open'); + } +}; diff --git a/node_modules/socket.io/lib/transports/flashsocket.js b/node_modules/socket.io/lib/transports/flashsocket.js new file mode 100644 index 00000000..dc2d78b4 --- /dev/null +++ b/node_modules/socket.io/lib/transports/flashsocket.js @@ -0,0 +1,129 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ +var WebSocket = require('./websocket'); + +/** + * Export the constructor. + */ + +exports = module.exports = FlashSocket; + +/** + * The FlashSocket transport is just a proxy + * for WebSocket connections. + * + * @api public + */ + +function FlashSocket (mng, data, req) { + return WebSocket.call(this, mng, data, req); +} + +/** + * Inherits from WebSocket. + */ + +FlashSocket.prototype.__proto__ = WebSocket.prototype; + +/** + * Transport name + * + * @api public + */ + +FlashSocket.prototype.name = 'flashsocket'; + +/** + * Listens for new configuration changes of the Manager + * this way we can enable and disable the flash server. + * + * @param {Manager} Manager instance. + * @api private + */ + + +FlashSocket.init = function (manager) { + var server; + function create () { + + // Drop out immediately if the user has + // disabled the flash policy server + if (!manager.get('flash policy server')) { + return; + } + + server = require('policyfile').createServer({ + log: function(msg){ + manager.log.info(msg); + } + }, manager.get('origins')); + + server.on('close', function (e) { + server = null; + }); + + server.listen(manager.get('flash policy port'), manager.server); + + manager.flashPolicyServer = server; + } + + // listen for origin changes, so we can update the server + manager.on('set:origins', function (value, key) { + if (!server) return; + + // update the origins and compile a new response buffer + server.origins = Array.isArray(value) ? value : [value]; + server.compile(); + }); + + // destory the server and create a new server + manager.on('set:flash policy port', function (value, key) { + var transports = manager.get('transports'); + if (~transports.indexOf('flashsocket')) { + if (server) { + if (server.port === value) return; + // destroy the server and rebuild it on a new port + try { + server.close(); + } + catch (e) { /* ignore exception. could e.g. be that the server isn't started yet */ } + } + create(); + } + }); + + // create or destroy the server + manager.on('set:flash policy server', function (value, key) { + var transports = manager.get('transports'); + if (~transports.indexOf('flashsocket')) { + if (server && !value) { + // destroy the server + try { + server.close(); + } + catch (e) { /* ignore exception. could e.g. be that the server isn't started yet */ } + } + } else if (!server && value) { + // create the server + create(); + } + }); + + // only start the server + manager.on('set:transports', function (value, key){ + if (!server && ~manager.get('transports').indexOf('flashsocket')) { + create(); + } + }); + // check if we need to initialize at start + if (~manager.get('transports').indexOf('flashsocket')){ + create(); + } +}; diff --git a/node_modules/socket.io/lib/transports/htmlfile.js b/node_modules/socket.io/lib/transports/htmlfile.js new file mode 100644 index 00000000..fce0c0ed --- /dev/null +++ b/node_modules/socket.io/lib/transports/htmlfile.js @@ -0,0 +1,83 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPTransport = require('./http'); + +/** + * Export the constructor. + */ + +exports = module.exports = HTMLFile; + +/** + * HTMLFile transport constructor. + * + * @api public + */ + +function HTMLFile (mng, data, req) { + HTTPTransport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +HTMLFile.prototype.__proto__ = HTTPTransport.prototype; + +/** + * Transport name + * + * @api public + */ + +HTMLFile.prototype.name = 'htmlfile'; + +/** + * Handles the request. + * + * @api private + */ + +HTMLFile.prototype.handleRequest = function (req) { + HTTPTransport.prototype.handleRequest.call(this, req); + + if (req.method == 'GET') { + req.res.writeHead(200, { + 'Content-Type': 'text/html; charset=UTF-8' + , 'Connection': 'keep-alive' + , 'Transfer-Encoding': 'chunked' + }); + + req.res.write( + '' + + '' + + new Array(174).join(' ') + ); + } +}; + +/** + * Performs the write. + * + * @api private + */ + +HTMLFile.prototype.write = function (data) { + // escape all forward slashes. see GH-1251 + data = ''; + + if (this.response.write(data)) { + this.drained = true; + } + + this.log.debug(this.name + ' writing', data); +}; diff --git a/node_modules/socket.io/lib/transports/http-polling.js b/node_modules/socket.io/lib/transports/http-polling.js new file mode 100644 index 00000000..89b7e042 --- /dev/null +++ b/node_modules/socket.io/lib/transports/http-polling.js @@ -0,0 +1,147 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPTransport = require('./http'); + +/** + * Exports the constructor. + */ + +exports = module.exports = HTTPPolling; + +/** + * HTTP polling constructor. + * + * @api public. + */ + +function HTTPPolling (mng, data, req) { + HTTPTransport.call(this, mng, data, req); +}; + +/** + * Inherits from HTTPTransport. + * + * @api public. + */ + +HTTPPolling.prototype.__proto__ = HTTPTransport.prototype; + +/** + * Transport name + * + * @api public + */ + +HTTPPolling.prototype.name = 'httppolling'; + +/** + * Override setHandlers + * + * @api private + */ + +HTTPPolling.prototype.setHandlers = function () { + HTTPTransport.prototype.setHandlers.call(this); + this.socket.removeListener('end', this.bound.end); + this.socket.removeListener('close', this.bound.close); +}; + +/** + * Removes heartbeat timeouts for polling. + */ + +HTTPPolling.prototype.setHeartbeatInterval = function () { + return this; +}; + +/** + * Handles a request + * + * @api private + */ + +HTTPPolling.prototype.handleRequest = function (req) { + HTTPTransport.prototype.handleRequest.call(this, req); + + if (req.method == 'GET') { + var self = this; + + this.pollTimeout = setTimeout(function () { + self.packet({ type: 'noop' }); + self.log.debug(self.name + ' closed due to exceeded duration'); + }, this.manager.get('polling duration') * 1000); + + this.log.debug('setting poll timeout'); + } +}; + +/** + * Clears polling timeout + * + * @api private + */ + +HTTPPolling.prototype.clearPollTimeout = function () { + if (this.pollTimeout) { + clearTimeout(this.pollTimeout); + this.pollTimeout = null; + this.log.debug('clearing poll timeout'); + } + + return this; +}; + +/** + * Override clear timeouts to clear the poll timeout + * + * @api private + */ + +HTTPPolling.prototype.clearTimeouts = function () { + HTTPTransport.prototype.clearTimeouts.call(this); + + this.clearPollTimeout(); +}; + +/** + * doWrite to clear poll timeout + * + * @api private + */ + +HTTPPolling.prototype.doWrite = function () { + this.clearPollTimeout(); +}; + +/** + * Performs a write. + * + * @api private. + */ + +HTTPPolling.prototype.write = function (data, close) { + this.doWrite(data); + this.response.end(); + this.onClose(); +}; + +/** + * Override end. + * + * @api private + */ + +HTTPPolling.prototype.end = function (reason) { + this.clearPollTimeout(); + return HTTPTransport.prototype.end.call(this, reason); +}; + diff --git a/node_modules/socket.io/lib/transports/http.js b/node_modules/socket.io/lib/transports/http.js new file mode 100644 index 00000000..28db794d --- /dev/null +++ b/node_modules/socket.io/lib/transports/http.js @@ -0,0 +1,121 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../transport') + , parser = require('../parser') + , qs = require('querystring'); + +/** + * Export the constructor. + */ + +exports = module.exports = HTTPTransport; + +/** + * HTTP interface constructor. For all non-websocket transports. + * + * @api public + */ + +function HTTPTransport (mng, data, req) { + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +HTTPTransport.prototype.__proto__ = Transport.prototype; + +/** + * Handles a request. + * + * @api private + */ + +HTTPTransport.prototype.handleRequest = function (req) { + + // Always set the response in case an error is returned to the client + this.response = req.res; + + if (req.method == 'POST') { + var buffer = '' + , res = req.res + , origin = req.headers.origin + , headers = { 'Content-Length': 1, 'Content-Type': 'text/plain; charset=UTF-8' } + , self = this; + + req.on('data', function (data) { + buffer += data; + + if (Buffer.byteLength(buffer) >= self.manager.get('destroy buffer size')) { + buffer = ''; + req.connection.destroy(); + } + }); + + req.on('end', function () { + res.writeHead(200, headers); + res.end('1'); + + self.onData(self.postEncoded ? qs.parse(buffer).d : buffer); + }); + + // prevent memory leaks for uncompleted requests + req.on('close', function () { + buffer = ''; + self.onClose(); + }); + + if (origin) { + // https://developer.mozilla.org/En/HTTP_Access_Control + headers['Access-Control-Allow-Origin'] = origin; + headers['Access-Control-Allow-Credentials'] = 'true'; + } + } else { + Transport.prototype.handleRequest.call(this, req); + } +}; + +/** + * Handles data payload. + * + * @api private + */ + +HTTPTransport.prototype.onData = function (data) { + var messages = parser.decodePayload(data); + this.log.debug(this.name + ' received data packet', data); + + for (var i = 0, l = messages.length; i < l; i++) { + this.onMessage(messages[i]); + } +}; + +/** + * Closes the request-response cycle + * + * @api private + */ + +HTTPTransport.prototype.doClose = function () { + this.response.end(); +}; + +/** + * Writes a payload of messages + * + * @api private + */ + +HTTPTransport.prototype.payload = function (msgs) { + this.write(parser.encodePayload(msgs)); +}; diff --git a/node_modules/socket.io/lib/transports/index.js b/node_modules/socket.io/lib/transports/index.js new file mode 100644 index 00000000..b8655594 --- /dev/null +++ b/node_modules/socket.io/lib/transports/index.js @@ -0,0 +1,12 @@ + +/** + * Export transports. + */ + +module.exports = { + websocket: require('./websocket') + , flashsocket: require('./flashsocket') + , htmlfile: require('./htmlfile') + , 'xhr-polling': require('./xhr-polling') + , 'jsonp-polling': require('./jsonp-polling') +}; diff --git a/node_modules/socket.io/lib/transports/jsonp-polling.js b/node_modules/socket.io/lib/transports/jsonp-polling.js new file mode 100644 index 00000000..ad7d5aff --- /dev/null +++ b/node_modules/socket.io/lib/transports/jsonp-polling.js @@ -0,0 +1,97 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPPolling = require('./http-polling'); +var jsonpolling_re = /^\d+$/ + +/** + * Export the constructor. + */ + +exports = module.exports = JSONPPolling; + +/** + * JSON-P polling transport. + * + * @api public + */ + +function JSONPPolling (mng, data, req) { + HTTPPolling.call(this, mng, data, req); + + this.head = 'io.j[0]('; + this.foot = ');'; + + if (data.query.i && jsonpolling_re.test(data.query.i)) { + this.head = 'io.j[' + data.query.i + ']('; + } +}; + +/** + * Inherits from Transport. + */ + +JSONPPolling.prototype.__proto__ = HTTPPolling.prototype; + +/** + * Transport name + * + * @api public + */ + +JSONPPolling.prototype.name = 'jsonppolling'; + +/** + * Make sure POST are decoded. + */ + +JSONPPolling.prototype.postEncoded = true; + +/** + * Handles incoming data. + * Due to a bug in \n handling by browsers, we expect a JSONified string. + * + * @api private + */ + +JSONPPolling.prototype.onData = function (data) { + try { + data = JSON.parse(data); + } catch (e) { + this.error('parse', 'reconnect'); + return; + } + + HTTPPolling.prototype.onData.call(this, data); +}; + +/** + * Performs the write. + * + * @api private + */ + +JSONPPolling.prototype.doWrite = function (data) { + HTTPPolling.prototype.doWrite.call(this); + + var data = data === undefined + ? '' : this.head + JSON.stringify(data) + this.foot; + + this.response.writeHead(200, { + 'Content-Type': 'text/javascript; charset=UTF-8' + , 'Content-Length': Buffer.byteLength(data) + , 'Connection': 'Keep-Alive' + , 'X-XSS-Protection': '0' + }); + + this.response.write(data); + this.log.debug(this.name + ' writing', data); +}; diff --git a/node_modules/socket.io/lib/transports/websocket.js b/node_modules/socket.io/lib/transports/websocket.js new file mode 100644 index 00000000..78a43043 --- /dev/null +++ b/node_modules/socket.io/lib/transports/websocket.js @@ -0,0 +1,36 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var protocolVersions = require('./websocket/'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + var transport + , version = req.headers['sec-websocket-version']; + if (typeof version !== 'undefined' && typeof protocolVersions[version] !== 'undefined') { + transport = new protocolVersions[version](mng, data, req); + } + else transport = new protocolVersions['default'](mng, data, req); + if (typeof this.name !== 'undefined') transport.name = this.name; + return transport; +}; diff --git a/node_modules/socket.io/lib/transports/websocket/default.js b/node_modules/socket.io/lib/transports/websocket/default.js new file mode 100644 index 00000000..091fdd44 --- /dev/null +++ b/node_modules/socket.io/lib/transports/websocket/default.js @@ -0,0 +1,362 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../../transport') + , EventEmitter = process.EventEmitter + , crypto = require('crypto') + , parser = require('../../parser'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + // parser + var self = this; + + this.parser = new Parser(); + this.parser.on('data', function (packet) { + self.log.debug(self.name + ' received data packet', packet); + self.onMessage(parser.decodePacket(packet)); + }); + this.parser.on('close', function () { + self.end(); + }); + this.parser.on('error', function () { + self.end(); + }); + + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +WebSocket.prototype.__proto__ = Transport.prototype; + +/** + * Transport name + * + * @api public + */ + +WebSocket.prototype.name = 'websocket'; + +/** + * Websocket draft version + * + * @api public + */ + +WebSocket.prototype.protocolVersion = 'hixie-76'; + +/** + * Called when the socket connects. + * + * @api private + */ + +WebSocket.prototype.onSocketConnect = function () { + var self = this; + + this.socket.setNoDelay(true); + + this.buffer = true; + this.buffered = []; + + if (this.req.headers.upgrade !== 'WebSocket') { + this.log.warn(this.name + ' connection invalid'); + this.end(); + return; + } + + var origin = this.req.headers['origin'] + , waitingForNonce = false; + if(this.manager.settings['match origin protocol']){ + location = (origin.indexOf('https')>-1 ? 'wss' : 'ws') + '://' + this.req.headers.host + this.req.url; + }else if(this.socket.encrypted){ + location = 'wss://' + this.req.headers.host + this.req.url; + }else{ + location = 'ws://' + this.req.headers.host + this.req.url; + } + + if (this.req.headers['sec-websocket-key1']) { + // If we don't have the nonce yet, wait for it (HAProxy compatibility). + if (! (this.req.head && this.req.head.length >= 8)) { + waitingForNonce = true; + } + + var headers = [ + 'HTTP/1.1 101 WebSocket Protocol Handshake' + , 'Upgrade: WebSocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Origin: ' + origin + , 'Sec-WebSocket-Location: ' + location + ]; + + if (this.req.headers['sec-websocket-protocol']){ + headers.push('Sec-WebSocket-Protocol: ' + + this.req.headers['sec-websocket-protocol']); + } + } else { + var headers = [ + 'HTTP/1.1 101 Web Socket Protocol Handshake' + , 'Upgrade: WebSocket' + , 'Connection: Upgrade' + , 'WebSocket-Origin: ' + origin + , 'WebSocket-Location: ' + location + ]; + } + + try { + this.socket.write(headers.concat('', '').join('\r\n')); + this.socket.setTimeout(0); + this.socket.setNoDelay(true); + this.socket.setEncoding('utf8'); + } catch (e) { + this.end(); + return; + } + + if (waitingForNonce) { + this.socket.setEncoding('binary'); + } else if (this.proveReception(headers)) { + self.flush(); + } + + var headBuffer = ''; + + this.socket.on('data', function (data) { + if (waitingForNonce) { + headBuffer += data; + + if (headBuffer.length < 8) { + return; + } + + // Restore the connection to utf8 encoding after receiving the nonce + self.socket.setEncoding('utf8'); + waitingForNonce = false; + + // Stuff the nonce into the location where it's expected to be + self.req.head = headBuffer.substr(0, 8); + headBuffer = ''; + + if (self.proveReception(headers)) { + self.flush(); + } + + return; + } + + self.parser.add(data); + }); +}; + +/** + * Writes to the socket. + * + * @api private + */ + +WebSocket.prototype.write = function (data) { + if (this.open) { + this.drained = false; + + if (this.buffer) { + this.buffered.push(data); + return this; + } + + var length = Buffer.byteLength(data) + , buffer = new Buffer(2 + length); + + buffer.write('\x00', 'binary'); + buffer.write(data, 1, 'utf8'); + buffer.write('\xff', 1 + length, 'binary'); + + try { + if (this.socket.write(buffer)) { + this.drained = true; + } + } catch (e) { + this.end(); + } + + this.log.debug(this.name + ' writing', data); + } +}; + +/** + * Flushes the internal buffer + * + * @api private + */ + +WebSocket.prototype.flush = function () { + this.buffer = false; + + for (var i = 0, l = this.buffered.length; i < l; i++) { + this.write(this.buffered.splice(0, 1)[0]); + } +}; + +/** + * Finishes the handshake. + * + * @api private + */ + +WebSocket.prototype.proveReception = function (headers) { + var self = this + , k1 = this.req.headers['sec-websocket-key1'] + , k2 = this.req.headers['sec-websocket-key2']; + + if (k1 && k2){ + var md5 = crypto.createHash('md5'); + + [k1, k2].forEach(function (k) { + var n = parseInt(k.replace(/[^\d]/g, '')) + , spaces = k.replace(/[^ ]/g, '').length; + + if (spaces === 0 || n % spaces !== 0){ + self.log.warn('Invalid ' + self.name + ' key: "' + k + '".'); + self.end(); + return false; + } + + n /= spaces; + + md5.update(String.fromCharCode( + n >> 24 & 0xFF, + n >> 16 & 0xFF, + n >> 8 & 0xFF, + n & 0xFF)); + }); + + md5.update(this.req.head.toString('binary')); + + try { + this.socket.write(md5.digest('binary'), 'binary'); + } catch (e) { + this.end(); + } + } + + return true; +}; + +/** + * Writes a payload. + * + * @api private + */ + +WebSocket.prototype.payload = function (msgs) { + for (var i = 0, l = msgs.length; i < l; i++) { + this.write(msgs[i]); + } + + return this; +}; + +/** + * Closes the connection. + * + * @api private + */ + +WebSocket.prototype.doClose = function () { + this.socket.end(); +}; + +/** + * WebSocket parser + * + * @api public + */ + +function Parser () { + this.buffer = ''; + this.i = 0; +}; + +/** + * Inherits from EventEmitter. + */ + +Parser.prototype.__proto__ = EventEmitter.prototype; + +/** + * Adds data to the buffer. + * + * @api public + */ + +Parser.prototype.add = function (data) { + this.buffer += data; + this.parse(); +}; + +/** + * Parses the buffer. + * + * @api private + */ + +Parser.prototype.parse = function () { + for (var i = this.i, chr, l = this.buffer.length; i < l; i++){ + chr = this.buffer[i]; + + if (this.buffer.length == 2 && this.buffer[1] == '\u0000') { + this.emit('close'); + this.buffer = ''; + this.i = 0; + return; + } + + if (i === 0){ + if (chr != '\u0000') + this.error('Bad framing. Expected null byte as first frame'); + else + continue; + } + + if (chr == '\ufffd'){ + this.emit('data', this.buffer.substr(1, i - 1)); + this.buffer = this.buffer.substr(i + 1); + this.i = 0; + return this.parse(); + } + } +}; + +/** + * Handles an error + * + * @api private + */ + +Parser.prototype.error = function (reason) { + this.buffer = ''; + this.i = 0; + this.emit('error', reason); + return this; +}; diff --git a/node_modules/socket.io/lib/transports/websocket/hybi-07-12.js b/node_modules/socket.io/lib/transports/websocket/hybi-07-12.js new file mode 100644 index 00000000..44f666a5 --- /dev/null +++ b/node_modules/socket.io/lib/transports/websocket/hybi-07-12.js @@ -0,0 +1,622 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../../transport') + , EventEmitter = process.EventEmitter + , crypto = require('crypto') + , url = require('url') + , parser = require('../../parser') + , util = require('../../util'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; +exports.Parser = Parser; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + // parser + var self = this; + + this.manager = mng; + this.parser = new Parser(); + this.parser.on('data', function (packet) { + self.onMessage(parser.decodePacket(packet)); + }); + this.parser.on('ping', function () { + // version 8 ping => pong + try { + self.socket.write('\u008a\u0000'); + } + catch (e) { + self.end(); + return; + } + }); + this.parser.on('close', function () { + self.end(); + }); + this.parser.on('error', function (reason) { + self.log.warn(self.name + ' parser error: ' + reason); + self.end(); + }); + + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +WebSocket.prototype.__proto__ = Transport.prototype; + +/** + * Transport name + * + * @api public + */ + +WebSocket.prototype.name = 'websocket'; + +/** + * Websocket draft version + * + * @api public + */ + +WebSocket.prototype.protocolVersion = '07-12'; + +/** + * Called when the socket connects. + * + * @api private + */ + +WebSocket.prototype.onSocketConnect = function () { + var self = this; + + if (typeof this.req.headers.upgrade === 'undefined' || + this.req.headers.upgrade.toLowerCase() !== 'websocket') { + this.log.warn(this.name + ' connection invalid'); + this.end(); + return; + } + + var origin = this.req.headers['sec-websocket-origin'] + , location = ((this.manager.settings['match origin protocol'] ? + origin.match(/^https/) : this.socket.encrypted) ? + 'wss' : 'ws') + + '://' + this.req.headers.host + this.req.url; + + if (!this.verifyOrigin(origin)) { + this.log.warn(this.name + ' connection invalid: origin mismatch'); + this.end(); + return; + } + + if (!this.req.headers['sec-websocket-key']) { + this.log.warn(this.name + ' connection invalid: received no key'); + this.end(); + return; + } + + // calc key + var key = this.req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + try { + this.socket.write(headers.concat('', '').join('\r\n')); + this.socket.setTimeout(0); + this.socket.setNoDelay(true); + } catch (e) { + this.end(); + return; + } + + this.socket.on('data', function (data) { + self.parser.add(data); + }); +}; + +/** + * Verifies the origin of a request. + * + * @api private + */ + +WebSocket.prototype.verifyOrigin = function (origin) { + var origins = this.manager.get('origins'); + + if (origin === 'null') origin = '*'; + + if (origins.indexOf('*:*') !== -1) { + return true; + } + + if (origin) { + try { + var parts = url.parse(origin); + parts.port = parts.port || 80; + var ok = + ~origins.indexOf(parts.hostname + ':' + parts.port) || + ~origins.indexOf(parts.hostname + ':*') || + ~origins.indexOf('*:' + parts.port); + if (!ok) this.log.warn('illegal origin: ' + origin); + return ok; + } catch (ex) { + this.log.warn('error parsing origin'); + } + } + else { + this.log.warn('origin missing from websocket call, yet required by config'); + } + return false; +}; + +/** + * Writes to the socket. + * + * @api private + */ + +WebSocket.prototype.write = function (data) { + if (this.open) { + var buf = this.frame(0x81, data); + try { + this.socket.write(buf, 'binary'); + } + catch (e) { + this.end(); + return; + } + this.log.debug(this.name + ' writing', data); + } +}; + +/** + * Writes a payload. + * + * @api private + */ + +WebSocket.prototype.payload = function (msgs) { + for (var i = 0, l = msgs.length; i < l; i++) { + this.write(msgs[i]); + } + + return this; +}; + +/** + * Frame server-to-client output as a text packet. + * + * @api private + */ + +WebSocket.prototype.frame = function (opcode, str) { + var dataBuffer = new Buffer(str) + , dataLength = dataBuffer.length + , startOffset = 2 + , secondByte = dataLength; + if (dataLength > 65536) { + startOffset = 10; + secondByte = 127; + } + else if (dataLength > 125) { + startOffset = 4; + secondByte = 126; + } + var outputBuffer = new Buffer(dataLength + startOffset); + outputBuffer[0] = opcode; + outputBuffer[1] = secondByte; + dataBuffer.copy(outputBuffer, startOffset); + switch (secondByte) { + case 126: + outputBuffer[2] = dataLength >>> 8; + outputBuffer[3] = dataLength % 256; + break; + case 127: + var l = dataLength; + for (var i = 1; i <= 8; ++i) { + outputBuffer[startOffset - i] = l & 0xff; + l >>>= 8; + } + } + return outputBuffer; +}; + +/** + * Closes the connection. + * + * @api private + */ + +WebSocket.prototype.doClose = function () { + this.socket.end(); +}; + +/** + * WebSocket parser + * + * @api public + */ + +function Parser () { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.overflow = null; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.currentMessage = ''; + + var self = this; + this.opcodeHandlers = { + // text + '1': function(data) { + var finish = function(mask, data) { + self.currentMessage += self.unmask(mask, data); + if (self.state.lastFragment) { + self.emit('data', self.currentMessage); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // binary + '2': function(data) { + var finish = function(mask, data) { + if (typeof self.currentMessage == 'string') self.currentMessage = []; // build a buffer list + self.currentMessage.push(self.unmask(mask, data, true)); + if (self.state.lastFragment) { + self.emit('binary', self.concatBuffers(self.currentMessage)); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // close + '8': function(data) { + self.emit('close'); + self.reset(); + }, + // ping + '9': function(data) { + if (self.state.lastFragment == false) { + self.error('fragmented ping is not supported'); + return; + } + + var finish = function(mask, data) { + self.emit('ping', self.unmask(mask, data)); + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength == 0) { + finish(null, null); + } + else if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + expectData(util.unpack(data)); + }); + } + } + } + + this.expect('Opcode', 2, this.processPacket); +}; + +/** + * Inherits from EventEmitter. + */ + +Parser.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add new data to the parser. + * + * @api public + */ + +Parser.prototype.add = function(data) { + if (this.expectBuffer == null) { + this.addToOverflow(data); + return; + } + var toRead = Math.min(data.length, this.expectBuffer.length - this.expectOffset); + data.copy(this.expectBuffer, this.expectOffset, 0, toRead); + this.expectOffset += toRead; + if (toRead < data.length) { + // at this point the overflow buffer shouldn't at all exist + this.overflow = new Buffer(data.length - toRead); + data.copy(this.overflow, 0, toRead, toRead + this.overflow.length); + } + if (this.expectOffset == this.expectBuffer.length) { + var bufferForHandler = this.expectBuffer; + this.expectBuffer = null; + this.expectOffset = 0; + this.expectHandler.call(this, bufferForHandler); + } +} + +/** + * Adds a piece of data to the overflow. + * + * @api private + */ + +Parser.prototype.addToOverflow = function(data) { + if (this.overflow == null) this.overflow = data; + else { + var prevOverflow = this.overflow; + this.overflow = new Buffer(this.overflow.length + data.length); + prevOverflow.copy(this.overflow, 0); + data.copy(this.overflow, prevOverflow.length); + } +} + +/** + * Waits for a certain amount of bytes to be available, then fires a callback. + * + * @api private + */ + +Parser.prototype.expect = function(what, length, handler) { + this.expectBuffer = new Buffer(length); + this.expectOffset = 0; + this.expectHandler = handler; + if (this.overflow != null) { + var toOverflow = this.overflow; + this.overflow = null; + this.add(toOverflow); + } +} + +/** + * Start processing a new packet. + * + * @api private + */ + +Parser.prototype.processPacket = function (data) { + if ((data[0] & 0x70) != 0) { + this.error('reserved fields must be empty'); + } + this.state.lastFragment = (data[0] & 0x80) == 0x80; + this.state.masked = (data[1] & 0x80) == 0x80; + var opcode = data[0] & 0xf; + if (opcode == 0) { + // continuation frame + this.state.opcode = this.state.activeFragmentedOperation; + if (!(this.state.opcode == 1 || this.state.opcode == 2)) { + this.error('continuation frame cannot follow current opcode') + return; + } + } + else { + this.state.opcode = opcode; + if (this.state.lastFragment === false) { + this.state.activeFragmentedOperation = opcode; + } + } + var handler = this.opcodeHandlers[this.state.opcode]; + if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode); + else handler(data); +} + +/** + * Endprocessing a packet. + * + * @api private + */ + +Parser.prototype.endPacket = function() { + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + if (this.state.lastFragment && this.state.opcode == this.state.activeFragmentedOperation) { + // end current fragmented operation + this.state.activeFragmentedOperation = null; + } + this.state.lastFragment = false; + this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0; + this.state.masked = false; + this.expect('Opcode', 2, this.processPacket); +} + +/** + * Reset the parser state. + * + * @api private + */ + +Parser.prototype.reset = function() { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.overflow = null; + this.currentMessage = ''; +} + +/** + * Unmask received data. + * + * @api private + */ + +Parser.prototype.unmask = function (mask, buf, binary) { + if (mask != null) { + for (var i = 0, ll = buf.length; i < ll; i++) { + buf[i] ^= mask[i % 4]; + } + } + if (binary) return buf; + return buf != null ? buf.toString('utf8') : ''; +} + +/** + * Concatenates a list of buffers. + * + * @api private + */ + +Parser.prototype.concatBuffers = function(buffers) { + var length = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + length += buffers[i].length; + } + var mergedBuffer = new Buffer(length); + var offset = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + buffers[i].copy(mergedBuffer, offset); + offset += buffers[i].length; + } + return mergedBuffer; +} + +/** + * Handles an error + * + * @api private + */ + +Parser.prototype.error = function (reason) { + this.reset(); + this.emit('error', reason); + return this; +}; diff --git a/node_modules/socket.io/lib/transports/websocket/hybi-16.js b/node_modules/socket.io/lib/transports/websocket/hybi-16.js new file mode 100644 index 00000000..69967dad --- /dev/null +++ b/node_modules/socket.io/lib/transports/websocket/hybi-16.js @@ -0,0 +1,622 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../../transport') + , EventEmitter = process.EventEmitter + , crypto = require('crypto') + , url = require('url') + , parser = require('../../parser') + , util = require('../../util'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; +exports.Parser = Parser; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + // parser + var self = this; + + this.manager = mng; + this.parser = new Parser(); + this.parser.on('data', function (packet) { + self.onMessage(parser.decodePacket(packet)); + }); + this.parser.on('ping', function () { + // version 8 ping => pong + try { + self.socket.write('\u008a\u0000'); + } + catch (e) { + self.end(); + return; + } + }); + this.parser.on('close', function () { + self.end(); + }); + this.parser.on('error', function (reason) { + self.log.warn(self.name + ' parser error: ' + reason); + self.end(); + }); + + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +WebSocket.prototype.__proto__ = Transport.prototype; + +/** + * Transport name + * + * @api public + */ + +WebSocket.prototype.name = 'websocket'; + +/** + * Websocket draft version + * + * @api public + */ + +WebSocket.prototype.protocolVersion = '16'; + +/** + * Called when the socket connects. + * + * @api private + */ + +WebSocket.prototype.onSocketConnect = function () { + var self = this; + + if (typeof this.req.headers.upgrade === 'undefined' || + this.req.headers.upgrade.toLowerCase() !== 'websocket') { + this.log.warn(this.name + ' connection invalid'); + this.end(); + return; + } + + var origin = this.req.headers['origin'] || '' + , location = ((this.manager.settings['match origin protocol'] ? + origin.match(/^https/) : this.socket.encrypted) ? + 'wss' : 'ws') + + '://' + this.req.headers.host + this.req.url; + + if (!this.verifyOrigin(origin)) { + this.log.warn(this.name + ' connection invalid: origin mismatch'); + this.end(); + return; + } + + if (!this.req.headers['sec-websocket-key']) { + this.log.warn(this.name + ' connection invalid: received no key'); + this.end(); + return; + } + + // calc key + var key = this.req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + try { + this.socket.write(headers.concat('', '').join('\r\n')); + this.socket.setTimeout(0); + this.socket.setNoDelay(true); + } catch (e) { + this.end(); + return; + } + + this.socket.on('data', function (data) { + self.parser.add(data); + }); +}; + +/** + * Verifies the origin of a request. + * + * @api private + */ + +WebSocket.prototype.verifyOrigin = function (origin) { + var origins = this.manager.get('origins'); + + if (origin === 'null') origin = '*'; + + if (origins.indexOf('*:*') !== -1) { + return true; + } + + if (origin) { + try { + var parts = url.parse(origin); + parts.port = parts.port || 80; + var ok = + ~origins.indexOf(parts.hostname + ':' + parts.port) || + ~origins.indexOf(parts.hostname + ':*') || + ~origins.indexOf('*:' + parts.port); + if (!ok) this.log.warn('illegal origin: ' + origin); + return ok; + } catch (ex) { + this.log.warn('error parsing origin'); + } + } + else { + this.log.warn('origin missing from websocket call, yet required by config'); + } + return false; +}; + +/** + * Writes to the socket. + * + * @api private + */ + +WebSocket.prototype.write = function (data) { + if (this.open) { + var buf = this.frame(0x81, data); + try { + this.socket.write(buf, 'binary'); + } + catch (e) { + this.end(); + return; + } + this.log.debug(this.name + ' writing', data); + } +}; + +/** + * Writes a payload. + * + * @api private + */ + +WebSocket.prototype.payload = function (msgs) { + for (var i = 0, l = msgs.length; i < l; i++) { + this.write(msgs[i]); + } + + return this; +}; + +/** + * Frame server-to-client output as a text packet. + * + * @api private + */ + +WebSocket.prototype.frame = function (opcode, str) { + var dataBuffer = new Buffer(str) + , dataLength = dataBuffer.length + , startOffset = 2 + , secondByte = dataLength; + if (dataLength > 65536) { + startOffset = 10; + secondByte = 127; + } + else if (dataLength > 125) { + startOffset = 4; + secondByte = 126; + } + var outputBuffer = new Buffer(dataLength + startOffset); + outputBuffer[0] = opcode; + outputBuffer[1] = secondByte; + dataBuffer.copy(outputBuffer, startOffset); + switch (secondByte) { + case 126: + outputBuffer[2] = dataLength >>> 8; + outputBuffer[3] = dataLength % 256; + break; + case 127: + var l = dataLength; + for (var i = 1; i <= 8; ++i) { + outputBuffer[startOffset - i] = l & 0xff; + l >>>= 8; + } + } + return outputBuffer; +}; + +/** + * Closes the connection. + * + * @api private + */ + +WebSocket.prototype.doClose = function () { + this.socket.end(); +}; + +/** + * WebSocket parser + * + * @api public + */ + +function Parser () { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.overflow = null; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.currentMessage = ''; + + var self = this; + this.opcodeHandlers = { + // text + '1': function(data) { + var finish = function(mask, data) { + self.currentMessage += self.unmask(mask, data); + if (self.state.lastFragment) { + self.emit('data', self.currentMessage); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // binary + '2': function(data) { + var finish = function(mask, data) { + if (typeof self.currentMessage == 'string') self.currentMessage = []; // build a buffer list + self.currentMessage.push(self.unmask(mask, data, true)); + if (self.state.lastFragment) { + self.emit('binary', self.concatBuffers(self.currentMessage)); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // close + '8': function(data) { + self.emit('close'); + self.reset(); + }, + // ping + '9': function(data) { + if (self.state.lastFragment == false) { + self.error('fragmented ping is not supported'); + return; + } + + var finish = function(mask, data) { + self.emit('ping', self.unmask(mask, data)); + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength == 0) { + finish(null, null); + } + else if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + expectData(util.unpack(data)); + }); + } + } + } + + this.expect('Opcode', 2, this.processPacket); +}; + +/** + * Inherits from EventEmitter. + */ + +Parser.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add new data to the parser. + * + * @api public + */ + +Parser.prototype.add = function(data) { + if (this.expectBuffer == null) { + this.addToOverflow(data); + return; + } + var toRead = Math.min(data.length, this.expectBuffer.length - this.expectOffset); + data.copy(this.expectBuffer, this.expectOffset, 0, toRead); + this.expectOffset += toRead; + if (toRead < data.length) { + // at this point the overflow buffer shouldn't at all exist + this.overflow = new Buffer(data.length - toRead); + data.copy(this.overflow, 0, toRead, toRead + this.overflow.length); + } + if (this.expectOffset == this.expectBuffer.length) { + var bufferForHandler = this.expectBuffer; + this.expectBuffer = null; + this.expectOffset = 0; + this.expectHandler.call(this, bufferForHandler); + } +} + +/** + * Adds a piece of data to the overflow. + * + * @api private + */ + +Parser.prototype.addToOverflow = function(data) { + if (this.overflow == null) this.overflow = data; + else { + var prevOverflow = this.overflow; + this.overflow = new Buffer(this.overflow.length + data.length); + prevOverflow.copy(this.overflow, 0); + data.copy(this.overflow, prevOverflow.length); + } +} + +/** + * Waits for a certain amount of bytes to be available, then fires a callback. + * + * @api private + */ + +Parser.prototype.expect = function(what, length, handler) { + this.expectBuffer = new Buffer(length); + this.expectOffset = 0; + this.expectHandler = handler; + if (this.overflow != null) { + var toOverflow = this.overflow; + this.overflow = null; + this.add(toOverflow); + } +} + +/** + * Start processing a new packet. + * + * @api private + */ + +Parser.prototype.processPacket = function (data) { + if ((data[0] & 0x70) != 0) { + this.error('reserved fields must be empty'); + return; + } + this.state.lastFragment = (data[0] & 0x80) == 0x80; + this.state.masked = (data[1] & 0x80) == 0x80; + var opcode = data[0] & 0xf; + if (opcode == 0) { + // continuation frame + this.state.opcode = this.state.activeFragmentedOperation; + if (!(this.state.opcode == 1 || this.state.opcode == 2)) { + this.error('continuation frame cannot follow current opcode') + return; + } + } + else { + this.state.opcode = opcode; + if (this.state.lastFragment === false) { + this.state.activeFragmentedOperation = opcode; + } + } + var handler = this.opcodeHandlers[this.state.opcode]; + if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode); + else handler(data); +} + +/** + * Endprocessing a packet. + * + * @api private + */ + +Parser.prototype.endPacket = function() { + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + if (this.state.lastFragment && this.state.opcode == this.state.activeFragmentedOperation) { + // end current fragmented operation + this.state.activeFragmentedOperation = null; + } + this.state.lastFragment = false; + this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0; + this.state.masked = false; + this.expect('Opcode', 2, this.processPacket); +} + +/** + * Reset the parser state. + * + * @api private + */ + +Parser.prototype.reset = function() { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.overflow = null; + this.currentMessage = ''; +} + +/** + * Unmask received data. + * + * @api private + */ + +Parser.prototype.unmask = function (mask, buf, binary) { + if (mask != null) { + for (var i = 0, ll = buf.length; i < ll; i++) { + buf[i] ^= mask[i % 4]; + } + } + if (binary) return buf; + return buf != null ? buf.toString('utf8') : ''; +} + +/** + * Concatenates a list of buffers. + * + * @api private + */ + +Parser.prototype.concatBuffers = function(buffers) { + var length = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + length += buffers[i].length; + } + var mergedBuffer = new Buffer(length); + var offset = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + buffers[i].copy(mergedBuffer, offset); + offset += buffers[i].length; + } + return mergedBuffer; +} + +/** + * Handles an error + * + * @api private + */ + +Parser.prototype.error = function (reason) { + this.reset(); + this.emit('error', reason); + return this; +}; diff --git a/node_modules/socket.io/lib/transports/websocket/index.js b/node_modules/socket.io/lib/transports/websocket/index.js new file mode 100644 index 00000000..3a952b75 --- /dev/null +++ b/node_modules/socket.io/lib/transports/websocket/index.js @@ -0,0 +1,11 @@ + +/** + * Export websocket versions. + */ + +module.exports = { + 7: require('./hybi-07-12'), + 8: require('./hybi-07-12'), + 13: require('./hybi-16'), + default: require('./default') +}; diff --git a/node_modules/socket.io/lib/transports/xhr-polling.js b/node_modules/socket.io/lib/transports/xhr-polling.js new file mode 100644 index 00000000..1db5aeee --- /dev/null +++ b/node_modules/socket.io/lib/transports/xhr-polling.js @@ -0,0 +1,69 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPPolling = require('./http-polling'); + +/** + * Export the constructor. + */ + +exports = module.exports = XHRPolling; + +/** + * Ajax polling transport. + * + * @api public + */ + +function XHRPolling (mng, data, req) { + HTTPPolling.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +XHRPolling.prototype.__proto__ = HTTPPolling.prototype; + +/** + * Transport name + * + * @api public + */ + +XHRPolling.prototype.name = 'xhr-polling'; + +/** + * Frames data prior to write. + * + * @api private + */ + +XHRPolling.prototype.doWrite = function (data) { + HTTPPolling.prototype.doWrite.call(this); + + var origin = this.req.headers.origin + , headers = { + 'Content-Type': 'text/plain; charset=UTF-8' + , 'Content-Length': data === undefined ? 0 : Buffer.byteLength(data) + , 'Connection': 'Keep-Alive' + }; + + if (origin) { + // https://developer.mozilla.org/En/HTTP_Access_Control + headers['Access-Control-Allow-Origin'] = origin; + headers['Access-Control-Allow-Credentials'] = 'true'; + } + + this.response.writeHead(200, headers); + this.response.write(data); + this.log.debug(this.name + ' writing', data); +}; diff --git a/node_modules/socket.io/lib/util.js b/node_modules/socket.io/lib/util.js new file mode 100644 index 00000000..f7d9f2b4 --- /dev/null +++ b/node_modules/socket.io/lib/util.js @@ -0,0 +1,50 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +/** + * Converts an enumerable to an array. + * + * @api public + */ + +exports.toArray = function (enu) { + var arr = []; + + for (var i = 0, l = enu.length; i < l; i++) + arr.push(enu[i]); + + return arr; +}; + +/** + * Unpacks a buffer to a number. + * + * @api public + */ + +exports.unpack = function (buffer) { + var n = 0; + for (var i = 0; i < buffer.length; ++i) { + n = (i == 0) ? buffer[i] : (n * 256) + buffer[i]; + } + return n; +} + +/** + * Left pads a string. + * + * @api public + */ + +exports.padl = function (s,n,c) { + return new Array(1 + n - s.length).join(c) + s; +} + diff --git a/node_modules/socket.io/node_modules/base64id/.npmignore b/node_modules/socket.io/node_modules/base64id/.npmignore new file mode 100644 index 00000000..39e9864f --- /dev/null +++ b/node_modules/socket.io/node_modules/base64id/.npmignore @@ -0,0 +1,3 @@ +support +test +examples diff --git a/node_modules/socket.io/node_modules/base64id/README.md b/node_modules/socket.io/node_modules/base64id/README.md new file mode 100644 index 00000000..b4361c15 --- /dev/null +++ b/node_modules/socket.io/node_modules/base64id/README.md @@ -0,0 +1,18 @@ +base64id +======== + +Node.js module that generates a base64 id. + +Uses crypto.randomBytes when available, falls back to unsafe methods for node.js <= 0.4. + +To increase performance, random bytes are buffered to minimize the number of synchronous calls to crypto.randomBytes. + +## Installation + + $ npm install mongoose + +## Usage + + var base64id = require('base64id'); + + var id = base64id.generateId(); diff --git a/node_modules/socket.io/node_modules/base64id/lib/base64id.js b/node_modules/socket.io/node_modules/base64id/lib/base64id.js new file mode 100644 index 00000000..f6881597 --- /dev/null +++ b/node_modules/socket.io/node_modules/base64id/lib/base64id.js @@ -0,0 +1,103 @@ +/*! + * base64id v0.1.0 + */ + +/** + * Module dependencies + */ + +var crypto = require('crypto'); + +/** + * Constructor + */ + +var Base64Id = function() { }; + +/** + * Get random bytes + * + * Uses a buffer if available, falls back to crypto.randomBytes + */ + +Base64Id.prototype.getRandomBytes = function(bytes) { + + var BUFFER_SIZE = 4096 + var self = this; + + bytes = bytes || 12; + + if (bytes > BUFFER_SIZE) { + return crypto.randomBytes(bytes); + } + + var bytesInBuffer = parseInt(BUFFER_SIZE/bytes); + var threshold = parseInt(bytesInBuffer*0.85); + + if (!threshold) { + return crypto.randomBytes(bytes); + } + + if (this.bytesBufferIndex == null) { + this.bytesBufferIndex = -1; + } + + if (this.bytesBufferIndex == bytesInBuffer) { + this.bytesBuffer = null; + this.bytesBufferIndex = -1; + } + + // No buffered bytes available or index above threshold + if (this.bytesBufferIndex == -1 || this.bytesBufferIndex > threshold) { + + if (!this.isGeneratingBytes) { + this.isGeneratingBytes = true; + crypto.randomBytes(BUFFER_SIZE, function(err, bytes) { + self.bytesBuffer = bytes; + self.bytesBufferIndex = 0; + self.isGeneratingBytes = false; + }); + } + + // Fall back to sync call when no buffered bytes are available + if (this.bytesBufferIndex == -1) { + return crypto.randomBytes(bytes); + } + } + + var result = this.bytesBuffer.slice(bytes*this.bytesBufferIndex, bytes*(this.bytesBufferIndex+1)); + this.bytesBufferIndex++; + + return result; +} + +/** + * Generates a base64 id + * + * (Original version from socket.io ) + */ + +Base64Id.prototype.generateId = function () { + var rand = new Buffer(15); // multiple of 3 for base64 + if (!rand.writeInt32BE) { + return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString() + + Math.abs(Math.random() * Math.random() * Date.now() | 0).toString(); + } + this.sequenceNumber = (this.sequenceNumber + 1) | 0; + rand.writeInt32BE(this.sequenceNumber, 11); + if (crypto.randomBytes) { + this.getRandomBytes(12).copy(rand); + } else { + // not secure for node 0.4 + [0, 4, 8].forEach(function(i) { + rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i); + }); + } + return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-'); +}; + +/** + * Export + */ + +exports = module.exports = new Base64Id(); diff --git a/node_modules/socket.io/node_modules/base64id/package.json b/node_modules/socket.io/node_modules/base64id/package.json new file mode 100644 index 00000000..1f4d4b83 --- /dev/null +++ b/node_modules/socket.io/node_modules/base64id/package.json @@ -0,0 +1,28 @@ +{ + "name": "base64id", + "version": "0.1.0", + "description": "Generates a base64 id", + "author": { + "name": "Kristian Faeldt", + "email": "faeldt_kristian@cyberagent.co.jp" + }, + "repository": { + "type": "git", + "url": "https://github.com/faeldt/base64id.git" + }, + "main": "./lib/base64id.js", + "engines": { + "node": ">= 0.4.0" + }, + "readme": "base64id\n========\n\nNode.js module that generates a base64 id.\n\nUses crypto.randomBytes when available, falls back to unsafe methods for node.js <= 0.4.\n\nTo increase performance, random bytes are buffered to minimize the number of synchronous calls to crypto.randomBytes.\n\n## Installation\n\n $ npm install mongoose\n\n## Usage\n\n var base64id = require('base64id');\n\n var id = base64id.generateId();\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/faeldt/base64id/issues" + }, + "_id": "base64id@0.1.0", + "dist": { + "shasum": "f883ee737fad515bad2fb9c56ccb7c957ed2a7fb" + }, + "_from": "base64id@0.1.0", + "_resolved": "https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz" +} diff --git a/node_modules/socket.io/node_modules/policyfile/.npmignore b/node_modules/socket.io/node_modules/policyfile/.npmignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/.npmignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/LICENSE b/node_modules/socket.io/node_modules/policyfile/LICENSE new file mode 100644 index 00000000..bdb8f617 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011 Arnout Kazemier,3rd-Eden + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/README.md b/node_modules/socket.io/node_modules/policyfile/README.md new file mode 100644 index 00000000..527921ee --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/README.md @@ -0,0 +1,98 @@ +## LOL, WUT? +It basically allows you to allow or disallow Flash Player sockets from accessing your site. + +## Installation + +```bash +npm install policyfile +``` +## Usage + +The server is based on the regular and know `net` and `http` server patterns. So it you can just listen +for all the events that a `net` based server emits etc. But there is one extra event, the `connect_failed` +event. This event is triggered when we are unable to listen on the supplied port number. + +### createServer +Creates a new server instance and accepts 2 optional arguments: + +- `options` **Object** Options to configure the server instance + - `log` **Boolean** Enable logging to STDOUT and STDERR (defaults to true) +- `origins` **Array** An Array of origins that are allowed by the server (defaults to *:*) + +```js +var pf = require('policyfile'); +pf.createServer(); +pf.listen(); +``` + +#### server.listen +Start listening on the server and it takes 3 optional arguments + +- `port` **Number** On which port number should we listen? (defaults to 843, which is the first port number the FlashPlayer checks) +- `server` **Server** A http server, if we are unable to accept requests or run the server we can also answer the policy requests inline over the supplied HTTP server. +- `callback` **Function** A callback function that is called when listening to the server was successful. + +```js +var pf = require('policyfile'); +pf.createServer(); +pf.listen(1337, function(){ + console.log(':3 yay') +}); +``` + +Changing port numbers can be handy if you do not want to run your server as root and have port 843 forward to a non root port number (aka a number above 1024). + +```js +var pf = require('policyfile') + , http = require('http'); + +server = http.createServer(function(q,r){r.writeHead(200);r.end('hello world')}); +server.listen(80); + +pf.createServer(); +pf.listen(1337, server, function(){ + console.log(':3 yay') +}); +``` + +Support for serving inline requests over a existing HTTP connection as the FlashPlayer will first check port 843, but if it's unable to get a response there it will send a policy file request over port 80, which is usually your http server. + +#### server.add +Adds more origins to the policy file you can add as many arguments as you like. + +```js +var pf = require('policyfile'); +pf.createServer(['google.com:80']); +pf.listen(); +pf.add('blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080'); // now has 3 origins +``` + +#### server.add +Adds more origins to the policy file you can add as many arguments as you like. + +```js +var pf = require('policyfile'); +pf.createServer(['blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080']); +pf.listen(); +pf.remove('blog.3rd-Eden.com:8080'); // only contains the :80 version now +``` + +#### server.close +Shuts down the server + +```js +var pf = require('policyfile'); +pf.createServer(); +pf.listen(); +pf.close(); // OH NVM. +``` + +## API +http://3rd-eden.com/FlashPolicyFileServer/ + +## Examples +See https://github.com/3rd-Eden/FlashPolicyFileServer/tree/master/examples for examples + +## Licence + +MIT see LICENSE file in the repository \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/doc/index.html b/node_modules/socket.io/node_modules/policyfile/doc/index.html new file mode 100644 index 00000000..743fcdaf --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/doc/index.html @@ -0,0 +1,375 @@ + + + FlashPolicyFileServer + + + + + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    FlashPolicyFileServer

    server

    lib/server.js
    +

    Module dependencies and cached references. +

    +
    +
    var slice = Array.prototype.slice
    +  , net = require('net');
    +
    +

    The server that does the Policy File severing

    + +

    Options

    + +
    • log false or a function that can output log information, defaults to console.log?
    + +

    + +
    • param: Object options Options to customize the servers functionality.

    • param: Array origins The origins that are allowed on this server, defaults to *:*.

    • api: public

    +
    +
    function Server(options, origins){
    +  var me = this;
    +  
    +  this.origins = origins || ['*:*'];
    +  this.port = 843;
    +  this.log = console.log;
    +  
    +  // merge `this` with the options
    +  Object.keys(options).forEach(function(key){
    +    me[key] &amp;&amp; (me[key] = options[key])
    +  });
    +  
    +  // create the net server
    +  this.socket = net.createServer(function createServer(socket){
    +    socket.on('error', function socketError(){ me.responder.call(me, socket) });
    +    me.responder.call(me, socket);
    +  });
    +  
    +  // Listen for errors as the port might be blocked because we do not have root priv.
    +  this.socket.on('error', function serverError(err){
    +    // Special and common case error handling
    +    if (err.errno == 13){
    +      me.log &amp;&amp; me.log(
    +        'Unable to listen to port `' + me.port + '` as your Node.js instance does not have root privileges. ' +
    +        (
    +          me.server
    +          ? 'The Flash Policy file will now be served inline over the supplied HTTP server, Flash Policy files request will suffer.'
    +          : 'No fallback server supplied.'
    +        )
    +      );
    +      
    +      me.socket.removeAllListeners();
    +      delete me.socket;
    +
    +      me.emit('connect_failed', err);
    +    } else {
    +      me.log &amp;&amp; me.log('FlashPolicyFileServer received a error event:\n' + (err.message ? err.message : err));
    +    }
    +  });
    +  
    +  this.socket.on('timeout', function serverTimeout(){});
    +  this.socket.on('close', function serverClosed(err){
    +    err &amp;&amp; me.log &amp;&amp; me.log('Server closing due to an error: \n' + (err.message ? err.message : err));
    +    
    +    if (me.server){
    +      // not online anymore
    +      delete me.server.online;
    +      
    +      // Remove the inline policy listener if we close down
    +      // but only when the server was `online` (see listen prototype)
    +      if( me.server['@'] &amp;&amp; me.server.online){
    +        me.server.removeListener('connection', me.server['@']);
    +      }
    +    }
    +    me.log &amp;&amp; me.log('Shutting down FlashPolicyFileServer');
    +  });
    +  
    +  // Compile the initial `buffer`
    +  this.compile();
    +}
    +
    +

    Start listening for requests

    + +

    + +
    • param: Number port The port number it should be listening to.

    • param: Server server A HTTP server instance, this will be used to listen for inline requests

    • param: Function cb The callback needs to be called once server is ready

    • api: public

    +
    +
    Server.prototype.listen = function listen(port, server, cb){
    +  var me = this
    +    , args = slice.call(arguments, 0)
    +    , callback;
    +  
    +  // assign the correct vars, for flexible arguments
    +  args.forEach(function args(arg){
    +    var type = typeof arg;
    +    
    +    if (type === 'number') me.port = arg;
    +    if (type === 'function') callback = arg;
    +    if (type === 'object') me.server = arg;
    +  });
    +  
    +  if (this.server){
    +    
    +    // no one in their right mind would ever create a `@` prototype, so Im just gonna store
    +    // my function on the server, so I can remove it later again once the server(s) closes
    +    this.server['@'] = function connection(socket){
    +      socket.once('data', function requestData(data){
    +        // if it's a Flash policy request, and we can write to the 
    +        if (
    +             data
    +          &amp;&amp; data[0] === 60
    +          &amp;&amp; data.toString() === '<policy-file-request/>\0'
    +          &amp;&amp; socket
    +          &amp;&amp; (socket.readyState === 'open' || socket.readyState === 'writeOnly')
    +        ){
    +          // send the buffer
    +          socket.end(me.buffer);
    +        }
    +      });
    +    };
    +    // attach it
    +    this.server.on('connection', this.server['@']);
    +  }
    +  
    +  // We add a callback method, so we can set a flag for when the server is `enabled` or `online`.
    +  // this flag is needed because if a error occurs and the we cannot boot up the server the
    +  // fallback functionality should not be removed during the `close` event
    +  this.socket.listen(this.port, function serverListening(){
    +   me.socket.online = true;
    +   
    +   if (callback) callback(), callback = undefined;
    +   
    +  });
    +  
    +  return this;
    +};
    +
    +

    Adds a new origin to the Flash Policy File.

    + +

    + +
    • param: Arguments The origins that need to be added.

    • api: public

    +
    +
    Server.prototype.add = function add(){
    +  var args = slice.call(arguments, 0)
    +    , i = args.length;
    +  
    +  // flag duplicates
    +  while (i--){
    +    if (this.origins.indexOf(args[i]) &gt;= 0){
    +      args[i] = null;
    +    }
    +  }
    +  
    +  // Add all the arguments to the array
    +  // but first we want to remove all `falsy` values from the args
    +  Array.prototype.push.apply(
    +    this.origins
    +  , args.filter(function(value){ return !!value })
    +  );
    +  
    +  this.compile();
    +  return this;
    +};
    +
    +

    Removes a origin from the Flash Policy File.

    + +

    + +
    • param: String origin The origin that needs to be removed from the server

    • api: public

    +
    +
    Server.prototype.remove = function remove(origin){
    +  var position = this.origins.indexOf(origin);
    +  
    +  // only remove and recompile if we have a match
    +  if (position &gt; 0){
    +    this.origins.splice(position,1);
    +    this.compile();
    +  }
    +  
    +  return this;
    +};
    +
    +

    Closes and cleans up the server

    + +
    • api: public

    +
    +
    Server.prototype.close = function close(){
    +  this.socket.removeAllListeners();
    +  this.socket.close();
    +  
    +  return this;
    +};
    +
    +

    Proxy the event listener requests to the created Net server +

    +
    +
    Object.keys(process.EventEmitter.prototype).forEach(function proxy(key){
    +  Server.prototype[key] = Server.prototype[key] || function (){
    +    if (this.socket) this.socket[key].apply(this.socket, arguments);
    +    return this;
    +  };
    +});
    +
    +

    Creates a new server instance.

    + +

    + +
    • param: Object options A options object to override the default config

    • param: Array origins The origins that should be allowed by the server

    • api: public

    +
    +
    exports.createServer = function createServer(options, origins){
    +  origins = Array.isArray(origins) ? origins : (Array.isArray(options) ? options : false);
    +  options = !Array.isArray(options) &amp;&amp; options ? options : {};
    +  
    +  return new Server(options, origins);
    +};
    +
    +

    Provide a hook to the original server, so it can be extended if needed. +

    +
    +
    exports.Server = Server;
    +
    +

    Module version +

    +
    +
    exports.version = '0.0.2';
    +
    +
    \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js b/node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js new file mode 100644 index 00000000..b439449a --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js @@ -0,0 +1,8 @@ +var http = require('http') + , fspfs = require('../'); + +var server = http.createServer(function(q,r){ r.writeHead(200); r.end(':3') }) + , flash = fspfs.createServer(); + +server.listen(8080); +flash.listen(8081,server); \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/examples/basic.js b/node_modules/socket.io/node_modules/policyfile/examples/basic.js new file mode 100644 index 00000000..5e2290f7 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/examples/basic.js @@ -0,0 +1,5 @@ +var http = require('http') + , fspfs = require('../'); + +var flash = fspfs.createServer(); +flash.listen(); \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/index.js b/node_modules/socket.io/node_modules/policyfile/index.js new file mode 100644 index 00000000..60cf2989 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/server.js'); \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/lib/server.js b/node_modules/socket.io/node_modules/policyfile/lib/server.js new file mode 100644 index 00000000..a525772b --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/lib/server.js @@ -0,0 +1,289 @@ +/** + * Module dependencies and cached references. + */ + +var slice = Array.prototype.slice + , net = require('net'); + +/** + * The server that does the Policy File severing + * + * Options: + * - `log` false or a function that can output log information, defaults to console.log? + * + * @param {Object} options Options to customize the servers functionality. + * @param {Array} origins The origins that are allowed on this server, defaults to `*:*`. + * @api public + */ + +function Server (options, origins) { + var me = this; + + this.origins = origins || ['*:*']; + this.port = 843; + this.log = console.log; + + // merge `this` with the options + Object.keys(options).forEach(function (key) { + me[key] && (me[key] = options[key]) + }); + + // create the net server + this.socket = net.createServer(function createServer (socket) { + socket.on('error', function socketError () { + me.responder.call(me, socket); + }); + + me.responder.call(me, socket); + }); + + // Listen for errors as the port might be blocked because we do not have root priv. + this.socket.on('error', function serverError (err) { + // Special and common case error handling + if (err.errno == 13) { + me.log && me.log( + 'Unable to listen to port `' + me.port + '` as your Node.js instance does not have root privileges. ' + + ( + me.server + ? 'The Flash Policy File requests will only be served inline over the supplied HTTP server. Inline serving is slower than a dedicated server instance.' + : 'No fallback server supplied, we will be unable to answer Flash Policy File requests.' + ) + ); + + me.emit('connect_failed', err); + me.socket.removeAllListeners(); + delete me.socket; + } else { + me.log && me.log('FlashPolicyFileServer received an error event:\n' + (err.message ? err.message : err)); + } + }); + + this.socket.on('timeout', function serverTimeout () {}); + this.socket.on('close', function serverClosed (err) { + err && me.log && me.log('Server closing due to an error: \n' + (err.message ? err.message : err)); + + if (me.server) { + // Remove the inline policy listener if we close down + // but only when the server was `online` (see listen prototype) + if (me.server['@'] && me.server.online) { + me.server.removeListener('connection', me.server['@']); + } + + // not online anymore + delete me.server.online; + } + }); + + // Compile the initial `buffer` + this.compile(); +} + +/** + * Start listening for requests + * + * @param {Number} port The port number it should be listening to. + * @param {Server} server A HTTP server instance, this will be used to listen for inline requests + * @param {Function} cb The callback needs to be called once server is ready + * @api public + */ + +Server.prototype.listen = function listen (port, server, cb){ + var me = this + , args = slice.call(arguments, 0) + , callback; + + // assign the correct vars, for flexible arguments + args.forEach(function args (arg){ + var type = typeof arg; + + if (type === 'number') me.port = arg; + if (type === 'function') callback = arg; + if (type === 'object') me.server = arg; + }); + + if (this.server) { + + // no one in their right mind would ever create a `@` prototype, so Im just gonna store + // my function on the server, so I can remove it later again once the server(s) closes + this.server['@'] = function connection (socket) { + socket.once('data', function requestData (data) { + // if it's a Flash policy request, and we can write to the + if ( + data + && data[0] === 60 + && data.toString() === '\0' + && socket + && (socket.readyState === 'open' || socket.readyState === 'writeOnly') + ){ + // send the buffer + try { + socket.end(me.buffer); + } catch (e) {} + } + }); + }; + + // attach it + this.server.on('connection', this.server['@']); + } + + // We add a callback method, so we can set a flag for when the server is `enabled` or `online`. + // this flag is needed because if a error occurs and the we cannot boot up the server the + // fallback functionality should not be removed during the `close` event + this.port >= 0 && this.socket.listen(this.port, function serverListening () { + me.socket.online = true; + if (callback) { + callback.call(me); + callback = undefined; + } + }); + + return this; +}; + +/** + * Responds to socket connects and writes the compile policy file. + * + * @param {net.Socket} socket The socket that needs to receive the message + * @api private + */ + +Server.prototype.responder = function responder (socket){ + if (socket && socket.readyState == 'open' && socket.end) { + try { + socket.end(this.buffer); + } catch (e) {} + } +}; + +/** + * Compiles the supplied origins to a Flash Policy File format and stores it in a Node.js Buffer + * this way it can be send over the wire without any performance loss. + * + * @api private + */ + +Server.prototype.compile = function compile (){ + var xml = [ + '' + , '' + , '' + ]; + + // add the allow access element + this.origins.forEach(function origin (origin){ + var parts = origin.split(':'); + xml.push(''); + }); + + xml.push(''); + + // store the result in a buffer so we don't have to re-generate it all the time + this.buffer = new Buffer(xml.join(''), 'utf8'); + + return this; +}; + +/** + * Adds a new origin to the Flash Policy File. + * + * @param {Arguments} The origins that need to be added. + * @api public + */ + +Server.prototype.add = function add(){ + var args = slice.call(arguments, 0) + , i = args.length; + + // flag duplicates + while (i--) { + if (this.origins.indexOf(args[i]) >= 0){ + args[i] = null; + } + } + + // Add all the arguments to the array + // but first we want to remove all `falsy` values from the args + Array.prototype.push.apply( + this.origins + , args.filter(function filter (value) { + return !!value; + }) + ); + + this.compile(); + return this; +}; + +/** + * Removes a origin from the Flash Policy File. + * + * @param {String} origin The origin that needs to be removed from the server + * @api public + */ + +Server.prototype.remove = function remove (origin){ + var position = this.origins.indexOf(origin); + + // only remove and recompile if we have a match + if (position > 0) { + this.origins.splice(position,1); + this.compile(); + } + + return this; +}; + +/** + * Closes and cleans up the server + * + * @api public + */ + +Server.prototype.close = function close () { + this.socket.removeAllListeners(); + this.socket.close(); + + return this; +}; + +/** + * Proxy the event listener requests to the created Net server + */ + +Object.keys(process.EventEmitter.prototype).forEach(function proxy (key){ + Server.prototype[key] = Server.prototype[key] || function () { + if (this.socket) { + this.socket[key].apply(this.socket, arguments); + } + + return this; + }; +}); + +/** + * Creates a new server instance. + * + * @param {Object} options A options object to override the default config + * @param {Array} origins The origins that should be allowed by the server + * @api public + */ + +exports.createServer = function createServer(options, origins){ + origins = Array.isArray(origins) ? origins : (Array.isArray(options) ? options : false); + options = !Array.isArray(options) && options ? options : {}; + + return new Server(options, origins); +}; + +/** + * Provide a hook to the original server, so it can be extended if needed. + */ + +exports.Server = Server; + +/** + * Module version + */ + +exports.version = '0.0.4'; diff --git a/node_modules/socket.io/node_modules/policyfile/package.json b/node_modules/socket.io/node_modules/policyfile/package.json new file mode 100644 index 00000000..5da76aec --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/package.json @@ -0,0 +1,55 @@ +{ + "name": "policyfile", + "version": "0.0.4", + "author": { + "name": "Arnout Kazemier" + }, + "description": "Flash Socket Policy File Server. A server to respond to Flash Socket Policy requests, both inline and through a dedicated server instance.", + "main": "index", + "keywords": [ + "flash", + "socket", + "policy", + "file", + "server", + "Flash Socket Policy File Server", + "cross domain" + ], + "directories": { + "lib": "./lib" + }, + "maintainers": [ + { + "name": "Arnout Kazemier", + "email": "info@3rd-Eden.com", + "url": "http://blog.3rd-Eden.com" + } + ], + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/3rd-Eden/FlashPolicyFileServer/blob/master/LICENSE" + } + ], + "repositories": [ + { + "type": "git", + "url": "https://github.com/3rd-Eden/FlashPolicyFileServer.git" + } + ], + "readme": "## LOL, WUT?\nIt basically allows you to allow or disallow Flash Player sockets from accessing your site.\n\n## Installation\n\n```bash\nnpm install policyfile\n```\n## Usage\n\nThe server is based on the regular and know `net` and `http` server patterns. So it you can just listen\nfor all the events that a `net` based server emits etc. But there is one extra event, the `connect_failed`\nevent. This event is triggered when we are unable to listen on the supplied port number.\n\n### createServer\nCreates a new server instance and accepts 2 optional arguments:\n\n- `options` **Object** Options to configure the server instance\n - `log` **Boolean** Enable logging to STDOUT and STDERR (defaults to true)\n- `origins` **Array** An Array of origins that are allowed by the server (defaults to *:*)\n\n```js\nvar pf = require('policyfile');\npf.createServer();\npf.listen();\n```\n\n#### server.listen\nStart listening on the server and it takes 3 optional arguments\n\n- `port` **Number** On which port number should we listen? (defaults to 843, which is the first port number the FlashPlayer checks)\n- `server` **Server** A http server, if we are unable to accept requests or run the server we can also answer the policy requests inline over the supplied HTTP server.\n- `callback` **Function** A callback function that is called when listening to the server was successful.\n\n```js\nvar pf = require('policyfile');\npf.createServer();\npf.listen(1337, function(){\n console.log(':3 yay')\n});\n```\n\nChanging port numbers can be handy if you do not want to run your server as root and have port 843 forward to a non root port number (aka a number above 1024).\n\n```js\nvar pf = require('policyfile')\n , http = require('http');\n\nserver = http.createServer(function(q,r){r.writeHead(200);r.end('hello world')});\nserver.listen(80);\n\npf.createServer();\npf.listen(1337, server, function(){\n console.log(':3 yay')\n});\n```\n\nSupport for serving inline requests over a existing HTTP connection as the FlashPlayer will first check port 843, but if it's unable to get a response there it will send a policy file request over port 80, which is usually your http server.\n\n#### server.add\nAdds more origins to the policy file you can add as many arguments as you like.\n\n```js\nvar pf = require('policyfile');\npf.createServer(['google.com:80']);\npf.listen();\npf.add('blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080'); // now has 3 origins\n```\n\n#### server.add\nAdds more origins to the policy file you can add as many arguments as you like.\n\n```js\nvar pf = require('policyfile');\npf.createServer(['blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080']);\npf.listen();\npf.remove('blog.3rd-Eden.com:8080'); // only contains the :80 version now\n```\n\n#### server.close\nShuts down the server\n\n```js\nvar pf = require('policyfile');\npf.createServer();\npf.listen();\npf.close(); // OH NVM.\n```\n\n## API\nhttp://3rd-eden.com/FlashPolicyFileServer/\n\n## Examples\nSee https://github.com/3rd-Eden/FlashPolicyFileServer/tree/master/examples for examples\n\n## Licence\n\nMIT see LICENSE file in the repository", + "readmeFilename": "README.md", + "repository": { + "type": "git", + "url": "https://github.com/3rd-Eden/FlashPolicyFileServer.git" + }, + "bugs": { + "url": "https://github.com/3rd-Eden/FlashPolicyFileServer/issues" + }, + "_id": "policyfile@0.0.4", + "dist": { + "shasum": "6c7dee169bc8fbf54911a7ccee51e427a93c93de" + }, + "_from": "policyfile@0.0.4", + "_resolved": "https://registry.npmjs.org/policyfile/-/policyfile-0.0.4.tgz" +} diff --git a/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt b/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt new file mode 100644 index 00000000..5883cd44 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIJAMUSOvlaeyQHMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTAxMTE2MDkzMjQ5WhcNMTMxMTE1MDkzMjQ5WjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAz+LXZOjcQCJq3+ZKUFabj71oo/ex/XsBcFqtBThjjTw9CVEVwfPQQp4X +wtPiB204vnYXwQ1/R2NdTQqCZu47l79LssL/u2a5Y9+0NEU3nQA5qdt+1FAE0c5o +exPimXOrR3GWfKz7PmZ2O0117IeCUUXPG5U8umhDe/4mDF4ZNJiKc404WthquTqg +S7rLQZHhZ6D0EnGnOkzlmxJMYPNHSOY1/6ivdNUUcC87awNEA3lgfhy25IyBK3QJ +c+aYKNTbt70Lery3bu2wWLFGtmNiGlQTS4JsxImRsECTI727ObS7/FWAQsqW+COL +0Sa5BuMFrFIpjPrEe0ih7vRRbdmXRwIDAQABo1AwTjAdBgNVHQ4EFgQUDnV4d6mD +tOnluLoCjkUHTX/n4agwHwYDVR0jBBgwFoAUDnV4d6mDtOnluLoCjkUHTX/n4agw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAFwV4MQfTo+qMv9JMiyno +IEiqfOz4RgtmBqRnXUffcjS2dhc7/z+FPZnM79Kej8eLHoVfxCyWRHFlzm93vEdv +wxOCrD13EDOi08OOZfxWyIlCa6Bg8cMAKqQzd2OvQOWqlRWBTThBJIhWflU33izX +Qn5GdmYqhfpc+9ZHHGhvXNydtRQkdxVK2dZNzLBvBlLlRmtoClU7xm3A+/5dddeP +AQHEPtyFlUw49VYtZ3ru6KqPms7MKvcRhYLsy9rwSfuuniMlx4d0bDR7TOkw0QQS +A0N8MGQRQpzl4mw4jLzyM5d5QtuGBh2P6hPGa0YQxtI3RPT/p6ENzzBiAKXiSfzo +xw== +-----END CERTIFICATE----- diff --git a/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key b/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key new file mode 100644 index 00000000..f31ff3d9 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAz+LXZOjcQCJq3+ZKUFabj71oo/ex/XsBcFqtBThjjTw9CVEV +wfPQQp4XwtPiB204vnYXwQ1/R2NdTQqCZu47l79LssL/u2a5Y9+0NEU3nQA5qdt+ +1FAE0c5oexPimXOrR3GWfKz7PmZ2O0117IeCUUXPG5U8umhDe/4mDF4ZNJiKc404 +WthquTqgS7rLQZHhZ6D0EnGnOkzlmxJMYPNHSOY1/6ivdNUUcC87awNEA3lgfhy2 +5IyBK3QJc+aYKNTbt70Lery3bu2wWLFGtmNiGlQTS4JsxImRsECTI727ObS7/FWA +QsqW+COL0Sa5BuMFrFIpjPrEe0ih7vRRbdmXRwIDAQABAoIBAGe4+9VqZfJN+dsq +8Osyuz01uQ8OmC0sAWTIqUlQgENIyf9rCJsUBlYmwR5BT6Z69XP6QhHdpSK+TiAR +XUz0EqG9HYzcxHIBaACP7j6iRoQ8R4kbbiWKo0z3WqQGIOqFjvD/mKEuQdE5mEYw +eOUCG6BnX1WY2Yr8WKd2AA/tp0/Y4d8z04u9eodMpSTbHTzYMJb5SbBN1vo6FY7q +8zSuO0BMzXlAxUsCwHsk1GQHFr8Oh3zIR7bQGtMBouI+6Lhh7sjFYsfxJboqMTBV +IKaA216M6ggHG7MU1/jeKcMGDmEfqQLQoyWp29rMK6TklUgipME2L3UD7vTyAVzz +xbVOpZkCgYEA8CXW4sZBBrSSrLR5SB+Ubu9qNTggLowOsC/kVKB2WJ4+xooc5HQo +mFhq1v/WxPQoWIxdYsfg2odlL+JclK5Qcy6vXmRSdAQ5lK9gBDKxZSYc3NwAw2HA +zyHCTK+I0n8PBYQ+yGcrxu0WqTGnlLW+Otk4CejO34WlgHwbH9bbY5UCgYEA3ZvT +C4+OoMHXlmICSt29zUrYiL33IWsR3/MaONxTEDuvgkOSXXQOl/8Ebd6Nu+3WbsSN +bjiPC/JyL1YCVmijdvFpl4gjtgvfJifs4G+QHvO6YfsYoVANk4u6g6rUuBIOwNK4 +RwYxwDc0oysp+g7tPxoSgDHReEVKJNzGBe9NGGsCgYEA4O4QP4gCEA3B9BF2J5+s +n9uPVxmiyvZUK6Iv8zP4pThTBBMIzNIf09G9AHPQ7djikU2nioY8jXKTzC3xGTHM +GJZ5m6fLsu7iH+nDvSreDSeNkTBfZqGAvoGYQ8uGE+L+ZuRfCcXYsxIOT5s6o4c3 +Dle2rVFpsuKzCY00urW796ECgYBn3go75+xEwrYGQSer6WR1nTgCV29GVYXKPooy +zmmMOT1Yw80NSkEw0pFD4cTyqVYREsTrPU0mn1sPfrOXxnGfZSVFpcR/Je9QVfQ7 +eW7GYxwfom335aqHVj10SxRqteP+UoWWnHujCPz94VRKZMakBddYCIGSan+G6YdS +7sdmwwKBgBc2qj0wvGXDF2kCLwSGfWoMf8CS1+5fIiUIdT1e/+7MfDdbmLMIFVjF +QKS3zVViXCbrG5SY6wS9hxoc57f6E2A8vcaX6zy2xkZlGHQCpWRtEM5R01OWJQaH +HsHMmQZGUQVoDm1oRkDhrTFK4K3ukc3rAxzeTZ96utOQN8/KJsTv +-----END RSA PRIVATE KEY----- diff --git a/node_modules/socket.io/node_modules/policyfile/tests/unit.test.js b/node_modules/socket.io/node_modules/policyfile/tests/unit.test.js new file mode 100644 index 00000000..932b3c14 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/tests/unit.test.js @@ -0,0 +1,231 @@ +var fspfs = require('../') + , fs = require('fs') + , http = require('http') + , https = require('https') + , net = require('net') + , should = require('should') + , assert = require('assert'); + +module.exports = { + // Library version should be Semver compatible + 'Library version': function(){ + fspfs.version.should.match(/^\d+\.\d+\.\d+$/); + } + + // Creating a server instace should not cause any problems + // either using the new Server or createServer method. +, 'Create Server instance': function(){ + var server = fspfs.createServer() + , server2 = new fspfs.Server({log:false}, ['blog.3rd-Eden.com:1337']); + + // server 2 options test + server2.log.should.be.false; + server2.origins.length.should.equal(1); + server2.origins[0].should.equal('blog.3rd-Eden.com:1337'); + + // server defaults + (typeof server.log).should.be.equal('function'); + server.origins.length.should.equal(1); + server.origins[0].should.equal('*:*'); + + // instance checking, sanity check + assert.ok(server instanceof fspfs.Server); + assert.ok(!!server.buffer); + + // more options testing + server = fspfs.createServer(['blog.3rd-Eden.com:80']); + server.origins.length.should.equal(1); + server.origins[0].should.equal('blog.3rd-Eden.com:80'); + + server = fspfs.createServer({log:false},['blog.3rd-Eden.com:80']); + server.log.should.be.false; + server.origins.length.should.equal(1); + server.origins[0].should.equal('blog.3rd-Eden.com:80'); + + } + +, 'Add origin': function(){ + var server = fspfs.createServer(); + server.add('google.com:80', 'blog.3rd-Eden.com:1337'); + + server.origins.length.should.equal(3); + server.origins.indexOf('google.com:80').should.be.above(0); + + // don't allow duplicates + server.add('google.com:80', 'google.com:80'); + + var i = server.origins.length + , count = 0; + + while(i--){ + if (server.origins[i] === 'google.com:80'){ + count++; + } + } + + count.should.equal(1); + } + +, 'Remove origin': function(){ + var server = fspfs.createServer(); + server.add('google.com:80', 'blog.3rd-Eden.com:1337'); + server.origins.length.should.equal(3); + + server.remove('google.com:80'); + server.origins.length.should.equal(2); + server.origins.indexOf('google.com:80').should.equal(-1); + } + +, 'Buffer': function(){ + var server = fspfs.createServer(); + + Buffer.isBuffer(server.buffer).should.be.true; + server.buffer.toString().indexOf('to-ports="*"').should.be.above(0); + server.buffer.toString().indexOf('domain="*"').should.be.above(0); + server.buffer.toString().indexOf('domain="google.com"').should.equal(-1); + + // The buffers should be rebuild when new origins are added + server.add('google.com:80'); + server.buffer.toString().indexOf('to-ports="80"').should.be.above(0); + server.buffer.toString().indexOf('domain="google.com"').should.be.above(0); + + server.remove('google.com:80'); + server.buffer.toString().indexOf('to-ports="80"').should.equal(-1); + server.buffer.toString().indexOf('domain="google.com"').should.equal(-1); + } + +, 'Responder': function(){ + var server = fspfs.createServer() + , calls = 0 + // dummy socket to emulate a `real` socket + , dummySocket = { + readyState: 'open' + , end: function(buffer){ + calls++; + Buffer.isBuffer(buffer).should.be.true; + buffer.toString().should.equal(server.buffer.toString()); + } + }; + + server.responder(dummySocket); + calls.should.equal(1); + } + +, 'Event proxy': function(){ + var server = fspfs.createServer() + , calls = 0; + + Object.keys(process.EventEmitter.prototype).forEach(function proxy(key){ + assert.ok(!!server[key] && typeof server[key] === 'function'); + }); + + // test if it works by calling a none default event + server.on('pew', function(){ + calls++; + }); + + server.emit('pew'); + calls.should.equal(1); + } + +, 'inline response http': function(){ + var port = 1335 + , httpserver = http.createServer(function(q,r){r.writeHead(200);r.end(':3')}) + , server = fspfs.createServer(); + + httpserver.listen(port, function(){ + server.listen(port + 1, httpserver, function(){ + var client = net.createConnection(port); + client.write('\0'); + client.on('error', function(err){ + assert.ok(!err, err) + }); + client.on('data', function(data){ + + var response = data.toString(); + console.log(response); + + response.indexOf('to-ports="*"').should.be.above(0); + response.indexOf('domain="*"').should.be.above(0); + response.indexOf('domain="google.com"').should.equal(-1); + + // clean up + client.destroy(); + server.close(); + httpserver.close(); + }); + }); + }); + } + +, 'server response': function(){ + var port = 1340 + , server = fspfs.createServer(); + + server.listen(port, function(){ + var client = net.createConnection(port); + client.write('\0'); + client.on('error', function(err){ + assert.ok(!err, err) + }); + client.on('data', function(data){ + + var response = data.toString(); + + response.indexOf('to-ports="*"').should.be.above(0); + response.indexOf('domain="*"').should.be.above(0); + response.indexOf('domain="google.com"').should.equal(-1); + + // clean up + client.destroy(); + server.close(); + }); + }); + } + +, 'inline response https': function(){ + var port = 1345 + , ssl = { + key: fs.readFileSync(__dirname + '/ssl/ssl.private.key').toString() + , cert: fs.readFileSync(__dirname + '/ssl/ssl.crt').toString() + } + , httpserver = https.createServer(ssl, function(q,r){r.writeHead(200);r.end(':3')}) + , server = fspfs.createServer(); + + httpserver.listen(port, function(){ + server.listen(port + 1, httpserver, function(){ + var client = net.createConnection(port); + client.write('\0'); + client.on('error', function(err){ + assert.ok(!err, err) + }); + client.on('data', function(data){ + + var response = data.toString(); + + response.indexOf('to-ports="*"').should.be.above(0); + response.indexOf('domain="*"').should.be.above(0); + response.indexOf('domain="google.com"').should.equal(-1); + + // clean up + client.destroy(); + server.close(); + httpserver.close(); + }); + }); + }); + } + +, 'connect_failed': function(){ + var server = fspfs.createServer(); + + server.on('connect_failed', function(){ + assert.ok(true); + }); + + server.listen(function(){ + assert.ok(false, 'Run this test without root access'); + server.close(); + }); + } +}; \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/redis/.npmignore b/node_modules/socket.io/node_modules/redis/.npmignore new file mode 100644 index 00000000..3c3629e6 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/socket.io/node_modules/redis/README.md b/node_modules/socket.io/node_modules/redis/README.md new file mode 100644 index 00000000..46e7018c --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/README.md @@ -0,0 +1,691 @@ +redis - a node.js redis client +=========================== + +This is a complete Redis client for node.js. It supports all Redis commands, including many recently added commands like EVAL from +experimental Redis server branches. + + +Install with: + + npm install redis + +Pieter Noordhuis has provided a binding to the official `hiredis` C library, which is non-blocking and fast. To use `hiredis`, do: + + npm install hiredis redis + +If `hiredis` is installed, `node_redis` will use it by default. Otherwise, a pure JavaScript parser will be used. + +If you use `hiredis`, be sure to rebuild it whenever you upgrade your version of node. There are mysterious failures that can +happen between node and native code modules after a node upgrade. + + +## Usage + +Simple example, included as `examples/simple.js`: + +```js + var redis = require("redis"), + client = redis.createClient(); + + // if you'd like to select database 3, instead of 0 (default), call + // client.select(3, function() { /* ... */ }); + + client.on("error", function (err) { + console.log("Error " + err); + }); + + client.set("string key", "string val", redis.print); + client.hset("hash key", "hashtest 1", "some value", redis.print); + client.hset(["hash key", "hashtest 2", "some other value"], redis.print); + client.hkeys("hash key", function (err, replies) { + console.log(replies.length + " replies:"); + replies.forEach(function (reply, i) { + console.log(" " + i + ": " + reply); + }); + client.quit(); + }); +``` + +This will display: + + mjr:~/work/node_redis (master)$ node example.js + Reply: OK + Reply: 0 + Reply: 0 + 2 replies: + 0: hashtest 1 + 1: hashtest 2 + mjr:~/work/node_redis (master)$ + + +## Performance + +Here are typical results of `multi_bench.js` which is similar to `redis-benchmark` from the Redis distribution. +It uses 50 concurrent connections with no pipelining. + +JavaScript parser: + + PING: 20000 ops 42283.30 ops/sec 0/5/1.182 + SET: 20000 ops 32948.93 ops/sec 1/7/1.515 + GET: 20000 ops 28694.40 ops/sec 0/9/1.740 + INCR: 20000 ops 39370.08 ops/sec 0/8/1.269 + LPUSH: 20000 ops 36429.87 ops/sec 0/8/1.370 + LRANGE (10 elements): 20000 ops 9891.20 ops/sec 1/9/5.048 + LRANGE (100 elements): 20000 ops 1384.56 ops/sec 10/91/36.072 + +hiredis parser: + + PING: 20000 ops 46189.38 ops/sec 1/4/1.082 + SET: 20000 ops 41237.11 ops/sec 0/6/1.210 + GET: 20000 ops 39682.54 ops/sec 1/7/1.257 + INCR: 20000 ops 40080.16 ops/sec 0/8/1.242 + LPUSH: 20000 ops 41152.26 ops/sec 0/3/1.212 + LRANGE (10 elements): 20000 ops 36563.07 ops/sec 1/8/1.363 + LRANGE (100 elements): 20000 ops 21834.06 ops/sec 0/9/2.287 + +The performance of `node_redis` improves dramatically with pipelining, which happens automatically in most normal programs. + + +### Sending Commands + +Each Redis command is exposed as a function on the `client` object. +All functions take either an `args` Array plus optional `callback` Function or +a variable number of individual arguments followed by an optional callback. +Here is an example of passing an array of arguments and a callback: + + client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {}); + +Here is that same call in the second style: + + client.mset("test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {}); + +Note that in either form the `callback` is optional: + + client.set("some key", "some val"); + client.set(["some other key", "some val"]); + +If the key is missing, reply will be null (probably): + + client.get("missingkey", function(err, reply) { + // reply is null when the key is missing + console.log(reply); + }); + +For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands) + +The commands can be specified in uppercase or lowercase for convenience. `client.get()` is the same as `client.GET()`. + +Minimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings, +integer replies return JavaScript Numbers, "bulk" replies return node Buffers, and "multi bulk" replies return a +JavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keyed by the hash keys. + +# API + +## Connection Events + +`client` will emit some events about the state of the connection to the Redis server. + +### "ready" + +`client` will emit `ready` a connection is established to the Redis server and the server reports +that it is ready to receive commands. Commands issued before the `ready` event are queued, +then replayed just before this event is emitted. + +### "connect" + +`client` will emit `connect` at the same time as it emits `ready` unless `client.options.no_ready_check` +is set. If this options is set, `connect` will be emitted when the stream is connected, and then +you are free to try to send commands. + +### "error" + +`client` will emit `error` when encountering an error connecting to the Redis server. + +Note that "error" is a special event type in node. If there are no listeners for an +"error" event, node will exit. This is usually what you want, but it can lead to some +cryptic error messages like this: + + mjr:~/work/node_redis (master)$ node example.js + + node.js:50 + throw e; + ^ + Error: ECONNREFUSED, Connection refused + at IOWatcher.callback (net:870:22) + at node.js:607:9 + +Not very useful in diagnosing the problem, but if your program isn't ready to handle this, +it is probably the right thing to just exit. + +`client` will also emit `error` if an exception is thrown inside of `node_redis` for whatever reason. +It would be nice to distinguish these two cases. + +### "end" + +`client` will emit `end` when an established Redis server connection has closed. + +### "drain" + +`client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now +writable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now, +you need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can +resume sending when you get `drain`. + +### "idle" + +`client` will emit `idle` when there are no outstanding commands that are awaiting a response. + +## redis.createClient(port, host, options) + +Create a new client connection. `port` defaults to `6379` and `host` defaults +to `127.0.0.1`. If you have `redis-server` running on the same computer as node, then the defaults for +port and host are probably fine. `options` in an object with the following possible properties: + +* `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed. +This may also be set to `javascript`. +* `return_buffers`: defaults to `false`. If set to `true`, then all replies will be sent to callbacks as node Buffer +objects instead of JavaScript Strings. +* `detect_buffers`: default to `false`. If set to `true`, then replies will be sent to callbacks as node Buffer objects +if any of the input arguments to the original command were Buffer objects. +This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to +every command on a client. +* `socket_nodelay`: defaults to `true`. Whether to call setNoDelay() on the TCP stream, which disables the +Nagle algorithm on the underlying socket. Setting this option to `false` can result in additional throughput at the +cost of more latency. Most applications will want this set to `true`. +* `no_ready_check`: defaults to `false`. When a connection is established to the Redis server, the server might still +be loading the database from disk. While loading, the server not respond to any commands. To work around this, +`node_redis` has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command +indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. +Setting `no_ready_check` to `true` will inhibit this check. +* `enable_offline_queue`: defaults to `true`. By default, if there is no active +connection to the redis server, commands are added to a queue and are executed +once the connection has been established. Setting `enable_offline_queue` to +`false` will disable this feature and the callback will be execute immediately +with an error, or an error will be thrown if no callback is specified. + +```js + var redis = require("redis"), + client = redis.createClient(null, null, {detect_buffers: true}); + + client.set("foo_rand000000000000", "OK"); + + // This will return a JavaScript String + client.get("foo_rand000000000000", function (err, reply) { + console.log(reply.toString()); // Will print `OK` + }); + + // This will return a Buffer since original key is specified as a Buffer + client.get(new Buffer("foo_rand000000000000"), function (err, reply) { + console.log(reply.toString()); // Will print `` + }); + client.end(); +``` + +`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here. + +## client.auth(password, callback) + +When connecting to Redis servers that require authentication, the `AUTH` command must be sent as the +first command after connecting. This can be tricky to coordinate with reconnections, the ready check, +etc. To make this easier, `client.auth()` stashes `password` and will send it after each connection, +including reconnections. `callback` is invoked only once, after the response to the very first +`AUTH` command sent. +NOTE: Your call to `client.auth()` should not be inside the ready handler. If +you are doing this wrong, `client` will emit an error that looks +something like this `Error: Ready check failed: ERR operation not permitted`. + +## client.end() + +Forcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed. +If you want to exit cleanly, call `client.quit()` to send the `QUIT` command after you have handled all replies. + +This example closes the connection to the Redis server before the replies have been read. You probably don't +want to do this: + +```js + var redis = require("redis"), + client = redis.createClient(); + + client.set("foo_rand000000000000", "some fantastic value"); + client.get("foo_rand000000000000", function (err, reply) { + console.log(reply.toString()); + }); + client.end(); +``` + +`client.end()` is useful for timeout cases where something is stuck or taking too long and you want +to start over. + +## Friendlier hash commands + +Most Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings. +When dealing with hash values, there are a couple of useful exceptions to this. + +### client.hgetall(hash) + +The reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact +with the responses using JavaScript syntax. + +Example: + + client.hmset("hosts", "mjr", "1", "another", "23", "home", "1234"); + client.hgetall("hosts", function (err, obj) { + console.dir(obj); + }); + +Output: + + { mjr: '1', another: '23', home: '1234' } + +### client.hmset(hash, obj, [callback]) + +Multiple values in a hash can be set by supplying an object: + + client.HMSET(key2, { + "0123456789": "abcdefghij", // NOTE: the key and value must both be strings + "some manner of key": "a type of value" + }); + +The properties and values of this Object will be set as keys and values in the Redis hash. + +### client.hmset(hash, key1, val1, ... keyn, valn, [callback]) + +Multiple values may also be set by supplying a list: + + client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value"); + + +## Publish / Subscribe + +Here is a simple example of the API for publish / subscribe. This program opens two +client connections, subscribes to a channel on one of them, and publishes to that +channel on the other: + +```js + var redis = require("redis"), + client1 = redis.createClient(), client2 = redis.createClient(), + msg_count = 0; + + client1.on("subscribe", function (channel, count) { + client2.publish("a nice channel", "I am sending a message."); + client2.publish("a nice channel", "I am sending a second message."); + client2.publish("a nice channel", "I am sending my last message."); + }); + + client1.on("message", function (channel, message) { + console.log("client1 channel " + channel + ": " + message); + msg_count += 1; + if (msg_count === 3) { + client1.unsubscribe(); + client1.end(); + client2.end(); + } + }); + + client1.incr("did a thing"); + client1.subscribe("a nice channel"); +``` + +When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into "pub/sub" mode. +At that point, only commands that modify the subscription set are valid. When the subscription +set is empty, the connection is put back into regular mode. + +If you need to send regular commands to Redis while in pub/sub mode, just open another connection. + +## Pub / Sub Events + +If a client has subscriptions active, it may emit these events: + +### "message" (channel, message) + +Client will emit `message` for every message received that matches an active subscription. +Listeners are passed the channel name as `channel` and the message Buffer as `message`. + +### "pmessage" (pattern, channel, message) + +Client will emit `pmessage` for every message received that matches an active subscription pattern. +Listeners are passed the original pattern used with `PSUBSCRIBE` as `pattern`, the sending channel +name as `channel`, and the message Buffer as `message`. + +### "subscribe" (channel, count) + +Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the +channel name as `channel` and the new count of subscriptions for this client as `count`. + +### "psubscribe" (pattern, count) + +Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the +original pattern as `pattern`, and the new count of subscriptions for this client as `count`. + +### "unsubscribe" (channel, count) + +Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the +channel name as `channel` and the new count of subscriptions for this client as `count`. When +`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted. + +### "punsubscribe" (pattern, count) + +Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the +channel name as `channel` and the new count of subscriptions for this client as `count`. When +`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted. + +## client.multi([commands]) + +`MULTI` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by +Redis. The interface in `node_redis` is to return an individual `Multi` object by calling `client.multi()`. + +```js + var redis = require("./index"), + client = redis.createClient(), set_size = 20; + + client.sadd("bigset", "a member"); + client.sadd("bigset", "another member"); + + while (set_size > 0) { + client.sadd("bigset", "member " + set_size); + set_size -= 1; + } + + // multi chain with an individual callback + client.multi() + .scard("bigset") + .smembers("bigset") + .keys("*", function (err, replies) { + // NOTE: code in this callback is NOT atomic + // this only happens after the the .exec call finishes. + client.mget(replies, redis.print); + }) + .dbsize() + .exec(function (err, replies) { + console.log("MULTI got " + replies.length + " replies"); + replies.forEach(function (reply, index) { + console.log("Reply " + index + ": " + reply.toString()); + }); + }); +``` + +`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects share all of the +same command methods as `client` objects do. Commands are queued up inside the `Multi` object +until `Multi.exec()` is invoked. + +You can either chain together `MULTI` commands as in the above example, or you can queue individual +commands while still sending regular client command as in this example: + +```js + var redis = require("redis"), + client = redis.createClient(), multi; + + // start a separate multi command queue + multi = client.multi(); + multi.incr("incr thing", redis.print); + multi.incr("incr other thing", redis.print); + + // runs immediately + client.mset("incr thing", 100, "incr other thing", 1, redis.print); + + // drains multi queue and runs atomically + multi.exec(function (err, replies) { + console.log(replies); // 101, 2 + }); + + // you can re-run the same transaction if you like + multi.exec(function (err, replies) { + console.log(replies); // 102, 3 + client.quit(); + }); +``` + +In addition to adding commands to the `MULTI` queue individually, you can also pass an array +of commands and arguments to the constructor: + +```js + var redis = require("redis"), + client = redis.createClient(), multi; + + client.multi([ + ["mget", "multifoo", "multibar", redis.print], + ["incr", "multifoo"], + ["incr", "multibar"] + ]).exec(function (err, replies) { + console.log(replies); + }); +``` + + +## Monitor mode + +Redis supports the `MONITOR` command, which lets you see all commands received by the Redis server +across all client connections, including from other client libraries and other computers. + +After you send the `MONITOR` command, no other commands are valid on that connection. `node_redis` +will emit a `monitor` event for every new monitor message that comes across. The callback for the +`monitor` event takes a timestamp from the Redis server and an array of command arguments. + +Here is a simple example: + +```js + var client = require("redis").createClient(), + util = require("util"); + + client.monitor(function (err, res) { + console.log("Entering monitoring mode."); + }); + + client.on("monitor", function (time, args) { + console.log(time + ": " + util.inspect(args)); + }); +``` + +# Extras + +Some other things you might like to know about. + +## client.server_info + +After the ready probe completes, the results from the INFO command are saved in the `client.server_info` +object. + +The `versions` key contains an array of the elements of the version string for easy comparison. + + > client.server_info.redis_version + '2.3.0' + > client.server_info.versions + [ 2, 3, 0 ] + +## redis.print() + +A handy callback function for displaying return values when testing. Example: + +```js + var redis = require("redis"), + client = redis.createClient(); + + client.on("connect", function () { + client.set("foo_rand000000000000", "some fantastic value", redis.print); + client.get("foo_rand000000000000", redis.print); + }); +``` + +This will print: + + Reply: OK + Reply: some fantastic value + +Note that this program will not exit cleanly because the client is still connected. + +## redis.debug_mode + +Boolean to enable debug mode and protocol tracing. + +```js + var redis = require("redis"), + client = redis.createClient(); + + redis.debug_mode = true; + + client.on("connect", function () { + client.set("foo_rand000000000000", "some fantastic value"); + }); +``` + +This will display: + + mjr:~/work/node_redis (master)$ node ~/example.js + send command: *3 + $3 + SET + $20 + foo_rand000000000000 + $20 + some fantastic value + + on_data: +OK + +`send command` is data sent into Redis and `on_data` is data received from Redis. + +## client.send_command(command_name, args, callback) + +Used internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis +Wiki have been added to the `client` object. However, if I missed any, or if new commands are introduced before +this library is updated, you can use `send_command()` to send arbitrary commands to Redis. + +All commands are sent as multi-bulk commands. `args` can either be an Array of arguments, or omitted. + +## client.connected + +Boolean tracking the state of the connection to the Redis server. + +## client.command_queue.length + +The number of commands that have been sent to the Redis server but not yet replied to. You can use this to +enforce some kind of maximum queue depth for commands while connected. + +Don't mess with `client.command_queue` though unless you really know what you are doing. + +## client.offline_queue.length + +The number of commands that have been queued up for a future connection. You can use this to enforce +some kind of maximum queue depth for pre-connection commands. + +## client.retry_delay + +Current delay in milliseconds before a connection retry will be attempted. This starts at `250`. + +## client.retry_backoff + +Multiplier for future retry timeouts. This should be larger than 1 to add more time between retries. +Defaults to 1.7. The default initial connection retry is 250, so the second retry will be 425, followed by 723.5, etc. + +### Commands with Optional and Keyword arguments + +This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation. + +Example: +```js +var args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ]; +client.zadd(args, function (err, response) { + if (err) throw err; + console.log('added '+response+' items.'); + + // -Infinity and +Infinity also work + var args1 = [ 'myzset', '+inf', '-inf' ]; + client.zrevrangebyscore(args1, function (err, response) { + if (err) throw err; + console.log('example1', response); + // write your code here + }); + + var max = 3, min = 1, offset = 1, count = 2; + var args2 = [ 'myzset', max, min, 'WITHSCORES', 'LIMIT', offset, count ]; + client.zrevrangebyscore(args2, function (err, response) { + if (err) throw err; + console.log('example2', response); + // write your code here + }); +}); +``` + +## TODO + +Better tests for auth, disconnect/reconnect, and all combinations thereof. + +Stream large set/get values into and out of Redis. Otherwise the entire value must be in node's memory. + +Performance can be better for very large values. + +I think there are more performance improvements left in there for smaller values, especially for large lists of small values. + +## How to Contribute +- open a pull request and then wait for feedback (if + [DTrejo](http://github.com/dtrejo) does not get back to you within 2 days, + comment again with indignation!) + +## Contributors +Some people have have added features and fixed bugs in `node_redis` other than me. + +Ordered by date of first contribution. +[Auto-generated](http://github.com/dtrejo/node-authors) on Wed Jul 25 2012 19:14:59 GMT-0700 (PDT). + +- [Matt Ranney aka `mranney`](https://github.com/mranney) +- [Tim-Smart aka `tim-smart`](https://github.com/tim-smart) +- [Tj Holowaychuk aka `visionmedia`](https://github.com/visionmedia) +- [rick aka `technoweenie`](https://github.com/technoweenie) +- [Orion Henry aka `orionz`](https://github.com/orionz) +- [Aivo Paas aka `aivopaas`](https://github.com/aivopaas) +- [Hank Sims aka `hanksims`](https://github.com/hanksims) +- [Paul Carey aka `paulcarey`](https://github.com/paulcarey) +- [Pieter Noordhuis aka `pietern`](https://github.com/pietern) +- [nithesh aka `nithesh`](https://github.com/nithesh) +- [Andy Ray aka `andy2ray`](https://github.com/andy2ray) +- [unknown aka `unknowdna`](https://github.com/unknowdna) +- [Dave Hoover aka `redsquirrel`](https://github.com/redsquirrel) +- [Vladimir Dronnikov aka `dvv`](https://github.com/dvv) +- [Umair Siddique aka `umairsiddique`](https://github.com/umairsiddique) +- [Louis-Philippe Perron aka `lp`](https://github.com/lp) +- [Mark Dawson aka `markdaws`](https://github.com/markdaws) +- [Ian Babrou aka `bobrik`](https://github.com/bobrik) +- [Felix Geisendörfer aka `felixge`](https://github.com/felixge) +- [Jean-Hugues Pinson aka `undefined`](https://github.com/undefined) +- [Maksim Lin aka `maks`](https://github.com/maks) +- [Owen Smith aka `orls`](https://github.com/orls) +- [Zachary Scott aka `zzak`](https://github.com/zzak) +- [TEHEK Firefox aka `TEHEK`](https://github.com/TEHEK) +- [Isaac Z. Schlueter aka `isaacs`](https://github.com/isaacs) +- [David Trejo aka `DTrejo`](https://github.com/DTrejo) +- [Brian Noguchi aka `bnoguchi`](https://github.com/bnoguchi) +- [Philip Tellis aka `bluesmoon`](https://github.com/bluesmoon) +- [Marcus Westin aka `marcuswestin2`](https://github.com/marcuswestin2) +- [Jed Schmidt aka `jed`](https://github.com/jed) +- [Dave Peticolas aka `jdavisp3`](https://github.com/jdavisp3) +- [Trae Robrock aka `trobrock`](https://github.com/trobrock) +- [Shankar Karuppiah aka `shankar0306`](https://github.com/shankar0306) +- [Ignacio Burgueño aka `ignacio`](https://github.com/ignacio) + +Thanks. + +## LICENSE - "MIT License" + +Copyright (c) 2010 Matthew Ranney, http://ranney.com/ + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +![spacer](http://ranney.com/1px.gif) diff --git a/node_modules/socket.io/node_modules/redis/benches/buffer_bench.js b/node_modules/socket.io/node_modules/redis/benches/buffer_bench.js new file mode 100644 index 00000000..a504fbc0 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/buffer_bench.js @@ -0,0 +1,89 @@ +var source = new Buffer(100), + dest = new Buffer(100), i, j, k, tmp, count = 1000000, bytes = 100; + +for (i = 99 ; i >= 0 ; i--) { + source[i] = 120; +} + +var str = "This is a nice String.", + buf = new Buffer("This is a lovely Buffer."); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (Buffer.isBuffer(str)) {} +} +var end = new Date(); +console.log("Buffer.isBuffer(str) " + (end - start) + " ms"); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (Buffer.isBuffer(buf)) {} +} +var end = new Date(); +console.log("Buffer.isBuffer(buf) " + (end - start) + " ms"); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (str instanceof Buffer) {} +} +var end = new Date(); +console.log("str instanceof Buffer " + (end - start) + " ms"); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (buf instanceof Buffer) {} +} +var end = new Date(); +console.log("buf instanceof Buffer " + (end - start) + " ms"); + +for (i = bytes ; i > 0 ; i --) { + var start = new Date(); + for (j = count ; j > 0; j--) { + tmp = source.toString("ascii", 0, bytes); + } + var end = new Date(); + console.log("toString() " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i --) { + var start = new Date(); + for (j = count ; j > 0; j--) { + tmp = ""; + for (k = 0; k <= i ; k++) { + tmp += String.fromCharCode(source[k]); + } + } + var end = new Date(); + console.log("manual string " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i--) { + var start = new Date(); + for (j = count ; j > 0 ; j--) { + for (k = i ; k > 0 ; k--) { + dest[k] = source[k]; + } + } + var end = new Date(); + console.log("Manual copy " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i--) { + var start = new Date(); + for (j = count ; j > 0 ; j--) { + for (k = i ; k > 0 ; k--) { + dest[k] = 120; + } + } + var end = new Date(); + console.log("Direct assignment " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i--) { + var start = new Date(); + for (j = count ; j > 0 ; j--) { + source.copy(dest, 0, 0, i); + } + var end = new Date(); + console.log("Buffer.copy() " + i + " bytes " + (end - start) + " ms"); +} diff --git a/node_modules/socket.io/node_modules/redis/benches/hiredis_parser.js b/node_modules/socket.io/node_modules/redis/benches/hiredis_parser.js new file mode 100644 index 00000000..f1515b11 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/hiredis_parser.js @@ -0,0 +1,38 @@ +var Parser = require('../lib/parser/hiredis').Parser; +var assert = require('assert'); + +/* +This test makes sure that exceptions thrown inside of "reply" event handlers +are not trapped and mistakenly emitted as parse errors. +*/ +(function testExecuteDoesNotCatchReplyCallbackExceptions() { + var parser = new Parser(); + var replies = [{}]; + + parser.reader = { + feed: function() {}, + get: function() { + return replies.shift(); + } + }; + + var emittedError = false; + var caughtException = false; + + parser + .on('error', function() { + emittedError = true; + }) + .on('reply', function() { + throw new Error('bad'); + }); + + try { + parser.execute(); + } catch (err) { + caughtException = true; + } + + assert.equal(caughtException, true); + assert.equal(emittedError, false); +})(); diff --git a/node_modules/socket.io/node_modules/redis/benches/re_sub_test.js b/node_modules/socket.io/node_modules/redis/benches/re_sub_test.js new file mode 100644 index 00000000..64b8f312 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/re_sub_test.js @@ -0,0 +1,14 @@ +var client = require('../index').createClient() + , client2 = require('../index').createClient() + , assert = require('assert'); + +client.once('subscribe', function (channel, count) { + client.unsubscribe('x'); + client.subscribe('x', function () { + client.quit(); + client2.quit(); + }); + client2.publish('x', 'hi'); +}); + +client.subscribe('x'); diff --git a/node_modules/socket.io/node_modules/redis/benches/reconnect_test.js b/node_modules/socket.io/node_modules/redis/benches/reconnect_test.js new file mode 100644 index 00000000..7abdd516 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/reconnect_test.js @@ -0,0 +1,29 @@ +var redis = require("../index").createClient(null, null, { +// max_attempts: 4 +}); + +redis.on("error", function (err) { + console.log("Redis says: " + err); +}); + +redis.on("ready", function () { + console.log("Redis ready."); +}); + +redis.on("reconnecting", function (arg) { + console.log("Redis reconnecting: " + JSON.stringify(arg)); +}); +redis.on("connect", function () { + console.log("Redis connected."); +}); + +setInterval(function () { + var now = Date.now(); + redis.set("now", now, function (err, res) { + if (err) { + console.log(now + " Redis reply error: " + err); + } else { + console.log(now + " Redis reply: " + res); + } + }); +}, 100); diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/codec.js b/node_modules/socket.io/node_modules/redis/benches/stress/codec.js new file mode 100644 index 00000000..7d764f60 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/codec.js @@ -0,0 +1,16 @@ +var json = { + encode: JSON.stringify, + decode: JSON.parse +}; + +var MsgPack = require('node-msgpack'); +msgpack = { + encode: MsgPack.pack, + decode: function(str) { return MsgPack.unpack(new Buffer(str)); } +}; + +bison = require('bison'); + +module.exports = json; +//module.exports = msgpack; +//module.exports = bison; diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/pub.js b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/pub.js new file mode 100644 index 00000000..0acde7a6 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/pub.js @@ -0,0 +1,38 @@ +'use strict'; + +var freemem = require('os').freemem; +var profiler = require('v8-profiler'); +var codec = require('../codec'); + +var sent = 0; + +var pub = require('redis').createClient(null, null, { + //command_queue_high_water: 5, + //command_queue_low_water: 1 +}) +.on('ready', function() { + this.emit('drain'); +}) +.on('drain', function() { + process.nextTick(exec); +}); + +var payload = '1'; for (var i = 0; i < 12; ++i) payload += payload; +console.log('Message payload length', payload.length); + +function exec() { + pub.publish('timeline', codec.encode({ foo: payload })); + ++sent; + if (!pub.should_buffer) { + process.nextTick(exec); + } +} + +profiler.takeSnapshot('s_0'); + +exec(); + +setInterval(function() { + profiler.takeSnapshot('s_' + sent); + console.error('sent', sent, 'free', freemem(), 'cmdqlen', pub.command_queue.length, 'offqlen', pub.offline_queue.length); +}, 2000); diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/run b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/run new file mode 100755 index 00000000..bd9ac392 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/run @@ -0,0 +1,10 @@ +#!/bin/sh +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node --debug pub.js diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/server.js b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/server.js new file mode 100644 index 00000000..035e6b74 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/server.js @@ -0,0 +1,23 @@ +'use strict'; + +var freemem = require('os').freemem; +var codec = require('../codec'); + +var id = Math.random(); +var recv = 0; + +var sub = require('redis').createClient() + .on('ready', function() { + this.subscribe('timeline'); + }) + .on('message', function(channel, message) { + var self = this; + if (message) { + message = codec.decode(message); + ++recv; + } + }); + +setInterval(function() { + console.error('id', id, 'received', recv, 'free', freemem()); +}, 2000); diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/pub.js b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/pub.js new file mode 100644 index 00000000..9caf1d0b --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/pub.js @@ -0,0 +1,49 @@ +'use strict'; + +var freemem = require('os').freemem; +//var profiler = require('v8-profiler'); +var codec = require('../codec'); + +var sent = 0; + +var pub = require('redis').createClient(null, null, { + //command_queue_high_water: 5, + //command_queue_low_water: 1 +}) +.on('ready', function() { + this.del('timeline'); + this.emit('drain'); +}) +.on('drain', function() { + process.nextTick(exec); +}); + +var payload = '1'; for (var i = 0; i < 12; ++i) payload += payload; +console.log('Message payload length', payload.length); + +function exec() { + pub.rpush('timeline', codec.encode({ foo: payload })); + ++sent; + if (!pub.should_buffer) { + process.nextTick(exec); + } +} + +//profiler.takeSnapshot('s_0'); + +exec(); + +setInterval(function() { + //var ss = profiler.takeSnapshot('s_' + sent); + //console.error(ss.stringify()); + pub.llen('timeline', function(err, result) { + console.error('sent', sent, 'free', freemem(), + 'cmdqlen', pub.command_queue.length, 'offqlen', pub.offline_queue.length, + 'llen', result + ); + }); +}, 2000); + +/*setTimeout(function() { + process.exit(); +}, 30000);*/ diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/run b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/run new file mode 100755 index 00000000..8045ae80 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/run @@ -0,0 +1,6 @@ +#!/bin/sh +node server.js & +#node server.js & +#node server.js & +#node server.js & +node --debug pub.js diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/server.js b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/server.js new file mode 100644 index 00000000..9cbcdd9e --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/server.js @@ -0,0 +1,30 @@ +'use strict'; + +var freemem = require('os').freemem; +var codec = require('../codec'); + +var id = Math.random(); +var recv = 0; + +var cmd = require('redis').createClient(); +var sub = require('redis').createClient() + .on('ready', function() { + this.emit('timeline'); + }) + .on('timeline', function() { + var self = this; + this.blpop('timeline', 0, function(err, result) { + var message = result[1]; + if (message) { + message = codec.decode(message); + ++recv; + } + self.emit('timeline'); + }); + }); + +setInterval(function() { + cmd.llen('timeline', function(err, result) { + console.error('id', id, 'received', recv, 'free', freemem(), 'llen', result); + }); +}, 2000); diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/speed/00 b/node_modules/socket.io/node_modules/redis/benches/stress/speed/00 new file mode 100644 index 00000000..29d7bf7c --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/speed/00 @@ -0,0 +1,13 @@ +# size JSON msgpack bison +26602 2151.0170848180414 +25542 ? 2842.589272665782 +24835 ? ? 7280.4538397469805 +6104 6985.234528557929 +5045 ? 7217.461392841478 +4341 ? ? 14261.406335354604 +4180 15864.633685636572 +4143 ? 12954.806235781925 +4141 ? ? 44650.70733912719 +75 114227.07313350472 +40 ? 30162.440062810834 +39 ? ? 119815.66013519121 diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/speed/plot b/node_modules/socket.io/node_modules/redis/benches/stress/speed/plot new file mode 100755 index 00000000..2563797c --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/speed/plot @@ -0,0 +1,13 @@ +#!/bin/sh + +gnuplot >size-rate.jpg << _EOF_ + +set terminal png nocrop enhanced font verdana 12 size 640,480 +set logscale x +set logscale y +set grid +set xlabel 'Serialized object size, octets' +set ylabel 'decode(encode(obj)) rate, 1/sec' +plot '00' using 1:2 title 'json' smooth bezier, '00' using 1:3 title 'msgpack' smooth bezier, '00' using 1:4 title 'bison' smooth bezier + +_EOF_ diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/speed/size-rate.png b/node_modules/socket.io/node_modules/redis/benches/stress/speed/size-rate.png new file mode 100644 index 00000000..c9c2bee6 Binary files /dev/null and b/node_modules/socket.io/node_modules/redis/benches/stress/speed/size-rate.png differ diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/speed/speed.js b/node_modules/socket.io/node_modules/redis/benches/stress/speed/speed.js new file mode 100644 index 00000000..8e43cbc0 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/speed/speed.js @@ -0,0 +1,84 @@ +var msgpack = require('node-msgpack'); +var bison = require('bison'); +var codec = { + JSON: { + encode: JSON.stringify, + decode: JSON.parse + }, + msgpack: { + encode: msgpack.pack, + decode: msgpack.unpack + }, + bison: bison +}; + +var obj, l; + +var s = '0'; +for (var i = 0; i < 12; ++i) s += s; + +obj = { + foo: s, + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [], + a: s, + ccc: s, + b: s + s + s +}; +for (i = 0; i < 100; ++i) obj.rand.push(Math.random()); +forObj(obj); + +obj = { + foo: s, + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [] +}; +for (i = 0; i < 100; ++i) obj.rand.push(Math.random()); +forObj(obj); + +obj = { + foo: s, + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [] +}; +forObj(obj); + +obj = { + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [] +}; +forObj(obj); + +function run(obj, codec) { + var t1 = Date.now(); + var n = 10000; + for (var i = 0; i < n; ++i) { + codec.decode(l = codec.encode(obj)); + } + var t2 = Date.now(); + //console.log('DONE', n*1000/(t2-t1), 'codecs/sec, length=', l.length); + return [n*1000/(t2-t1), l.length]; +} + +function series(obj, cname, n) { + var rate = 0; + var len = 0; + for (var i = 0; i < n; ++i) { + var r = run(obj, codec[cname]); + rate += r[0]; + len += r[1]; + } + rate /= n; + len /= n; + console.log(cname + ' ' + rate + ' ' + len); + return [rate, len]; +} + +function forObj(obj) { + var r = { + JSON: series(obj, 'JSON', 20), + msgpack: series(obj, 'msgpack', 20), + bison: series(obj, 'bison', 20) + }; + return r; +} diff --git a/node_modules/socket.io/node_modules/redis/benches/sub_quit_test.js b/node_modules/socket.io/node_modules/redis/benches/sub_quit_test.js new file mode 100644 index 00000000..ad1f4132 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/sub_quit_test.js @@ -0,0 +1,18 @@ +var client = require("redis").createClient(), + client2 = require("redis").createClient(); + +client.subscribe("something"); +client.on("subscribe", function (channel, count) { + console.log("Got sub: " + channel); + client.unsubscribe("something"); +}); + +client.on("unsubscribe", function (channel, count) { + console.log("Got unsub: " + channel + ", quitting"); + client.quit(); +}); + +// exercise unsub before sub +client2.unsubscribe("something"); +client2.subscribe("another thing"); +client2.quit(); diff --git a/node_modules/socket.io/node_modules/redis/changelog.md b/node_modules/socket.io/node_modules/redis/changelog.md new file mode 100644 index 00000000..4248288c --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/changelog.md @@ -0,0 +1,219 @@ +Changelog +========= + +## v0.7.2 - April 29, 2012 + +Many contributed fixes. Thank you, contributors. + +* [GH-190] - pub/sub mode fix (Brian Noguchi) +* [GH-165] - parser selection fix (TEHEK) +* numerous documentation and examples updates +* auth errors emit Errors instead of Strings (David Trejo) + +## v0.7.1 - November 15, 2011 + +Fix regression in reconnect logic. + +Very much need automated tests for reconnection and queue logic. + +## v0.7.0 - November 14, 2011 + +Many contributed fixes. Thanks everybody. + +* [GH-127] - properly re-initialize parser on reconnect +* [GH-136] - handle passing undefined as callback (Ian Babrou) +* [GH-139] - properly handle exceptions thrown in pub/sub event handlers (Felix Geisendörfer) +* [GH-141] - detect closing state on stream error (Felix Geisendörfer) +* [GH-142] - re-select database on reconnection (Jean-Hugues Pinson) +* [GH-146] - add sort example (Maksim Lin) + +Some more goodies: + +* Fix bugs with node 0.6 +* Performance improvements +* New version of `multi_bench.js` that tests more realistic scenarios +* [GH-140] - support optional callback for subscribe commands +* Properly flush and error out command queue when connection fails +* Initial work on reconnection thresholds + +## v0.6.7 - July 30, 2011 + +(accidentally skipped v0.6.6) + +Fix and test for [GH-123] + +Passing an Array as as the last argument should expand as users +expect. The old behavior was to coerce the arguments into Strings, +which did surprising things with Arrays. + +## v0.6.5 - July 6, 2011 + +Contributed changes: + +* Support SlowBuffers (Umair Siddique) +* Add Multi to exports (Louis-Philippe Perron) +* Fix for drain event calculation (Vladimir Dronnikov) + +Thanks! + +## v0.6.4 - June 30, 2011 + +Fix bug with optional callbacks for hmset. + +## v0.6.2 - June 30, 2011 + +Bugs fixed: + +* authentication retry while server is loading db (danmaz74) [GH-101] +* command arguments processing issue with arrays + +New features: + +* Auto update of new commands from redis.io (Dave Hoover) +* Performance improvements and backpressure controls. +* Commands now return the true/false value from the underlying socket write(s). +* Implement command_queue high water and low water for more better control of queueing. + +See `examples/backpressure_drain.js` for more information. + +## v0.6.1 - June 29, 2011 + +Add support and tests for Redis scripting through EXEC command. + +Bug fix for monitor mode. (forddg) + +Auto update of new commands from redis.io (Dave Hoover) + +## v0.6.0 - April 21, 2011 + +Lots of bugs fixed. + +* connection error did not properly trigger reconnection logic [GH-85] +* client.hmget(key, [val1, val2]) was not expanding properly [GH-66] +* client.quit() while in pub/sub mode would throw an error [GH-87] +* client.multi(['hmset', 'key', {foo: 'bar'}]) fails [GH-92] +* unsubscribe before subscribe would make things very confused [GH-88] +* Add BRPOPLPUSH [GH-79] + +## v0.5.11 - April 7, 2011 + +Added DISCARD + +I originally didn't think DISCARD would do anything here because of the clever MULTI interface, but somebody +pointed out to me that DISCARD can be used to flush the WATCH set. + +## v0.5.10 - April 6, 2011 + +Added HVALS + +## v0.5.9 - March 14, 2011 + +Fix bug with empty Array arguments - Andy Ray + +## v0.5.8 - March 14, 2011 + +Add `MONITOR` command and special monitor command reply parsing. + +## v0.5.7 - February 27, 2011 + +Add magical auth command. + +Authentication is now remembered by the client and will be automatically sent to the server +on every connection, including any reconnections. + +## v0.5.6 - February 22, 2011 + +Fix bug in ready check with `return_buffers` set to `true`. + +Thanks to Dean Mao and Austin Chau. + +## v0.5.5 - February 16, 2011 + +Add probe for server readiness. + +When a Redis server starts up, it might take a while to load the dataset into memory. +During this time, the server will accept connections, but will return errors for all non-INFO +commands. Now node_redis will send an INFO command whenever it connects to a server. +If the info command indicates that the server is not ready, the client will keep trying until +the server is ready. Once it is ready, the client will emit a "ready" event as well as the +"connect" event. The client will queue up all commands sent before the server is ready, just +like it did before. When the server is ready, all offline/non-ready commands will be replayed. +This should be backward compatible with previous versions. + +To disable this ready check behavior, set `options.no_ready_check` when creating the client. + +As a side effect of this change, the key/val params from the info command are available as +`client.server_options`. Further, the version string is decomposed into individual elements +in `client.server_options.versions`. + +## v0.5.4 - February 11, 2011 + +Fix excess memory consumption from Queue backing store. + +Thanks to Gustaf Sjöberg. + +## v0.5.3 - February 5, 2011 + +Fix multi/exec error reply callback logic. + +Thanks to Stella Laurenzo. + +## v0.5.2 - January 18, 2011 + +Fix bug where unhandled error replies confuse the parser. + +## v0.5.1 - January 18, 2011 + +Fix bug where subscribe commands would not handle redis-server startup error properly. + +## v0.5.0 - December 29, 2010 + +Some bug fixes: + +* An important bug fix in reconnection logic. Previously, reply callbacks would be invoked twice after + a reconnect. +* Changed error callback argument to be an actual Error object. + +New feature: + +* Add friendly syntax for HMSET using an object. + +## v0.4.1 - December 8, 2010 + +Remove warning about missing hiredis. You probably do want it though. + +## v0.4.0 - December 5, 2010 + +Support for multiple response parsers and hiredis C library from Pieter Noordhuis. +Return Strings instead of Buffers by default. +Empty nested mb reply bug fix. + +## v0.3.9 - November 30, 2010 + +Fix parser bug on failed EXECs. + +## v0.3.8 - November 10, 2010 + +Fix for null MULTI response when WATCH condition fails. + +## v0.3.7 - November 9, 2010 + +Add "drain" and "idle" events. + +## v0.3.6 - November 3, 2010 + +Add all known Redis commands from Redis master, even ones that are coming in 2.2 and beyond. + +Send a friendlier "error" event message on stream errors like connection refused / reset. + +## v0.3.5 - October 21, 2010 + +A few bug fixes. + +* Fixed bug with `nil` multi-bulk reply lengths that showed up with `BLPOP` timeouts. +* Only emit `end` once when connection goes away. +* Fixed bug in `test.js` where driver finished before all tests completed. + +## unversioned wasteland + +See the git history for what happened before. diff --git a/node_modules/socket.io/node_modules/redis/diff_multi_bench_output.js b/node_modules/socket.io/node_modules/redis/diff_multi_bench_output.js new file mode 100755 index 00000000..99fdf4df --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/diff_multi_bench_output.js @@ -0,0 +1,87 @@ +#!/usr/bin/env node + +var colors = require('colors'), + fs = require('fs'), + _ = require('underscore'), + metrics = require('metrics'), + + // `node diff_multi_bench_output.js before.txt after.txt` + before = process.argv[2], + after = process.argv[3]; + +if (!before || !after) { + console.log('Please supply two file arguments:'); + var n = __filename; + n = n.substring(n.lastIndexOf('/', n.length)); + console.log(' ./' + n + ' multiBenchBefore.txt multiBenchAfter.txt'); + console.log('To generate multiBenchBefore.txt, run'); + console.log(' node multi_bench.js > multiBenchBefore.txt'); + console.log('Thank you for benchmarking responsibly.'); + return; +} + +var before_lines = fs.readFileSync(before, 'utf8').split('\n'), + after_lines = fs.readFileSync(after, 'utf8').split('\n'); + +console.log('Comparing before,', before.green, '(', before_lines.length, + 'lines)', 'to after,', after.green, '(', after_lines.length, 'lines)'); + +var total_ops = new metrics.Histogram.createUniformHistogram(); + +before_lines.forEach(function(b, i) { + var a = after_lines[i]; + if (!a || !b || !b.trim() || !a.trim()) { + // console.log('#ignored#', '>'+a+'<', '>'+b+'<'); + return; + } + + b_words = b.split(' ').filter(is_whitespace); + a_words = a.split(' ').filter(is_whitespace); + + var ops = + [b_words, a_words] + .map(function(words) { + // console.log(words); + return parseInt10(words.slice(-2, -1)); + }).filter(function(num) { + var isNaN = !num && num !== 0; + return !isNaN; + }); + if (ops.length != 2) return + + var delta = ops[1] - ops[0]; + + total_ops.update(delta); + + delta = humanize_diff(delta); + console.log( + // name of test + command_name(a_words) == command_name(b_words) + ? command_name(a_words) + ':' + : '404:', + // results of test + ops.join(' -> '), 'ops/sec (∆', delta, ')'); +}); + +console.log('Mean difference in ops/sec:', humanize_diff(total_ops.mean())); + +function is_whitespace(s) { + return !!s.trim(); +} + +function parseInt10(s) { + return parseInt(s, 10); +} + +// green if greater than 0, red otherwise +function humanize_diff(num) { + if (num > 0) { + return ('+' + num).green; + } + return ('' + num).red; +} + +function command_name(words) { + var line = words.join(' '); + return line.substr(0, line.indexOf(',')); +} diff --git a/node_modules/socket.io/node_modules/redis/examples/auth.js b/node_modules/socket.io/node_modules/redis/examples/auth.js new file mode 100644 index 00000000..6c0a563c --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/auth.js @@ -0,0 +1,5 @@ +var redis = require("redis"), + client = redis.createClient(); + +// This command is magical. Client stashes the password and will issue on every connect. +client.auth("somepass"); diff --git a/node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js b/node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js new file mode 100644 index 00000000..3488ef4d --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js @@ -0,0 +1,33 @@ +var redis = require("../index"), + client = redis.createClient(null, null, { + command_queue_high_water: 5, + command_queue_low_water: 1 + }), + remaining_ops = 100000, paused = false; + +function op() { + if (remaining_ops <= 0) { + console.error("Finished."); + process.exit(0); + } + + remaining_ops--; + if (client.hset("test hash", "val " + remaining_ops, remaining_ops) === false) { + console.log("Pausing at " + remaining_ops); + paused = true; + } else { + process.nextTick(op); + } +} + +client.on("drain", function () { + if (paused) { + console.log("Resuming at " + remaining_ops); + paused = false; + process.nextTick(op); + } else { + console.log("Got drain while not paused at " + remaining_ops); + } +}); + +op(); diff --git a/node_modules/socket.io/node_modules/redis/examples/eval.js b/node_modules/socket.io/node_modules/redis/examples/eval.js new file mode 100644 index 00000000..c1fbf8a5 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/eval.js @@ -0,0 +1,9 @@ +var redis = require("./index"), + client = redis.createClient(); + +redis.debug_mode = true; + +client.eval("return 100.5", 0, function (err, res) { + console.dir(err); + console.dir(res); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/extend.js b/node_modules/socket.io/node_modules/redis/examples/extend.js new file mode 100644 index 00000000..488b8c2d --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/extend.js @@ -0,0 +1,24 @@ +var redis = require("redis"), + client = redis.createClient(); + +// Extend the RedisClient prototype to add a custom method +// This one converts the results from "INFO" into a JavaScript Object + +redis.RedisClient.prototype.parse_info = function (callback) { + this.info(function (err, res) { + var lines = res.toString().split("\r\n").sort(); + var obj = {}; + lines.forEach(function (line) { + var parts = line.split(':'); + if (parts[1]) { + obj[parts[0]] = parts[1]; + } + }); + callback(obj) + }); +}; + +client.parse_info(function (info) { + console.dir(info); + client.quit(); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/file.js b/node_modules/socket.io/node_modules/redis/examples/file.js new file mode 100644 index 00000000..4d2b5d1c --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/file.js @@ -0,0 +1,32 @@ +// Read a file from disk, store it in Redis, then read it back from Redis. + +var redis = require("redis"), + client = redis.createClient(), + fs = require("fs"), + filename = "kids_in_cart.jpg"; + +// Get the file I use for testing like this: +// curl http://ranney.com/kids_in_cart.jpg -o kids_in_cart.jpg +// or just use your own file. + +// Read a file from fs, store it in Redis, get it back from Redis, write it back to fs. +fs.readFile(filename, function (err, data) { + if (err) throw err + console.log("Read " + data.length + " bytes from filesystem."); + + client.set(filename, data, redis.print); // set entire file + client.get(filename, function (err, reply) { // get entire file + if (err) { + console.log("Get error: " + err); + } else { + fs.writeFile("duplicate_" + filename, reply, function (err) { + if (err) { + console.log("Error on write: " + err) + } else { + console.log("File written."); + } + client.end(); + }); + } + }); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/mget.js b/node_modules/socket.io/node_modules/redis/examples/mget.js new file mode 100644 index 00000000..936740d3 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/mget.js @@ -0,0 +1,5 @@ +var client = require("redis").createClient(); + +client.mget(["sessions started", "sessions started", "foo"], function (err, res) { + console.dir(res); +}); \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/redis/examples/monitor.js b/node_modules/socket.io/node_modules/redis/examples/monitor.js new file mode 100644 index 00000000..2cb6a4e1 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/monitor.js @@ -0,0 +1,10 @@ +var client = require("../index").createClient(), + util = require("util"); + +client.monitor(function (err, res) { + console.log("Entering monitoring mode."); +}); + +client.on("monitor", function (time, args) { + console.log(time + ": " + util.inspect(args)); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/multi.js b/node_modules/socket.io/node_modules/redis/examples/multi.js new file mode 100644 index 00000000..35c08e18 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/multi.js @@ -0,0 +1,46 @@ +var redis = require("redis"), + client = redis.createClient(), set_size = 20; + +client.sadd("bigset", "a member"); +client.sadd("bigset", "another member"); + +while (set_size > 0) { + client.sadd("bigset", "member " + set_size); + set_size -= 1; +} + +// multi chain with an individual callback +client.multi() + .scard("bigset") + .smembers("bigset") + .keys("*", function (err, replies) { + client.mget(replies, redis.print); + }) + .dbsize() + .exec(function (err, replies) { + console.log("MULTI got " + replies.length + " replies"); + replies.forEach(function (reply, index) { + console.log("Reply " + index + ": " + reply.toString()); + }); + }); + +client.mset("incr thing", 100, "incr other thing", 1, redis.print); + +// start a separate multi command queue +var multi = client.multi(); +multi.incr("incr thing", redis.print); +multi.incr("incr other thing", redis.print); + +// runs immediately +client.get("incr thing", redis.print); // 100 + +// drains multi queue and runs atomically +multi.exec(function (err, replies) { + console.log(replies); // 101, 2 +}); + +// you can re-run the same transaction if you like +multi.exec(function (err, replies) { + console.log(replies); // 102, 3 + client.quit(); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/multi2.js b/node_modules/socket.io/node_modules/redis/examples/multi2.js new file mode 100644 index 00000000..8be4d731 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/multi2.js @@ -0,0 +1,29 @@ +var redis = require("redis"), + client = redis.createClient(), multi; + +// start a separate command queue for multi +multi = client.multi(); +multi.incr("incr thing", redis.print); +multi.incr("incr other thing", redis.print); + +// runs immediately +client.mset("incr thing", 100, "incr other thing", 1, redis.print); + +// drains multi queue and runs atomically +multi.exec(function (err, replies) { + console.log(replies); // 101, 2 +}); + +// you can re-run the same transaction if you like +multi.exec(function (err, replies) { + console.log(replies); // 102, 3 + client.quit(); +}); + +client.multi([ + ["mget", "multifoo", "multibar", redis.print], + ["incr", "multifoo"], + ["incr", "multibar"] +]).exec(function (err, replies) { + console.log(replies.toString()); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/psubscribe.js b/node_modules/socket.io/node_modules/redis/examples/psubscribe.js new file mode 100644 index 00000000..c57117b8 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/psubscribe.js @@ -0,0 +1,33 @@ +var redis = require("redis"), + client1 = redis.createClient(), + client2 = redis.createClient(), + client3 = redis.createClient(), + client4 = redis.createClient(), + msg_count = 0; + +redis.debug_mode = false; + +client1.on("psubscribe", function (pattern, count) { + console.log("client1 psubscribed to " + pattern + ", " + count + " total subscriptions"); + client2.publish("channeltwo", "Me!"); + client3.publish("channelthree", "Me too!"); + client4.publish("channelfour", "And me too!"); +}); + +client1.on("punsubscribe", function (pattern, count) { + console.log("client1 punsubscribed from " + pattern + ", " + count + " total subscriptions"); + client4.end(); + client3.end(); + client2.end(); + client1.end(); +}); + +client1.on("pmessage", function (pattern, channel, message) { + console.log("("+ pattern +")" + " client1 received message on " + channel + ": " + message); + msg_count += 1; + if (msg_count === 3) { + client1.punsubscribe(); + } +}); + +client1.psubscribe("channel*"); diff --git a/node_modules/socket.io/node_modules/redis/examples/pub_sub.js b/node_modules/socket.io/node_modules/redis/examples/pub_sub.js new file mode 100644 index 00000000..aa508d6c --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/pub_sub.js @@ -0,0 +1,41 @@ +var redis = require("redis"), + client1 = redis.createClient(), msg_count = 0, + client2 = redis.createClient(); + +redis.debug_mode = false; + +// Most clients probably don't do much on "subscribe". This example uses it to coordinate things within one program. +client1.on("subscribe", function (channel, count) { + console.log("client1 subscribed to " + channel + ", " + count + " total subscriptions"); + if (count === 2) { + client2.publish("a nice channel", "I am sending a message."); + client2.publish("another one", "I am sending a second message."); + client2.publish("a nice channel", "I am sending my last message."); + } +}); + +client1.on("unsubscribe", function (channel, count) { + console.log("client1 unsubscribed from " + channel + ", " + count + " total subscriptions"); + if (count === 0) { + client2.end(); + client1.end(); + } +}); + +client1.on("message", function (channel, message) { + console.log("client1 channel " + channel + ": " + message); + msg_count += 1; + if (msg_count === 3) { + client1.unsubscribe(); + } +}); + +client1.on("ready", function () { + // if you need auth, do it here + client1.incr("did a thing"); + client1.subscribe("a nice channel", "another one"); +}); + +client2.on("ready", function () { + // if you need auth, do it here +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/simple.js b/node_modules/socket.io/node_modules/redis/examples/simple.js new file mode 100644 index 00000000..f1f2e320 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/simple.js @@ -0,0 +1,24 @@ +var redis = require("redis"), + client = redis.createClient(); + +client.on("error", function (err) { + console.log("error event - " + client.host + ":" + client.port + " - " + err); +}); + +client.set("string key", "string val", redis.print); +client.hset("hash key", "hashtest 1", "some value", redis.print); +client.hset(["hash key", "hashtest 2", "some other value"], redis.print); +client.hkeys("hash key", function (err, replies) { + if (err) { + return console.error("error response - " + err); + } + + console.log(replies.length + " replies:"); + replies.forEach(function (reply, i) { + console.log(" " + i + ": " + reply); + }); +}); + +client.quit(function (err, res) { + console.log("Exiting from quit command."); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/sort.js b/node_modules/socket.io/node_modules/redis/examples/sort.js new file mode 100644 index 00000000..e7c6249e --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/sort.js @@ -0,0 +1,17 @@ +var redis = require("redis"), + client = redis.createClient(); + +client.sadd("mylist", 1); +client.sadd("mylist", 2); +client.sadd("mylist", 3); + +client.set("weight_1", 5); +client.set("weight_2", 500); +client.set("weight_3", 1); + +client.set("object_1", "foo"); +client.set("object_2", "bar"); +client.set("object_3", "qux"); + +client.sort("mylist", "by", "weight_*", "get", "object_*", redis.print); +// Prints Reply: qux,foo,bar \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/redis/examples/subqueries.js b/node_modules/socket.io/node_modules/redis/examples/subqueries.js new file mode 100644 index 00000000..560db240 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/subqueries.js @@ -0,0 +1,15 @@ +// Sending commands in response to other commands. +// This example runs "type" against every key in the database +// +var client = require("redis").createClient(); + +client.keys("*", function (err, keys) { + keys.forEach(function (key, pos) { + client.type(key, function (err, keytype) { + console.log(key + " is " + keytype); + if (pos === (keys.length - 1)) { + client.quit(); + } + }); + }); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/subquery.js b/node_modules/socket.io/node_modules/redis/examples/subquery.js new file mode 100644 index 00000000..861657e1 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/subquery.js @@ -0,0 +1,19 @@ +var client = require("redis").createClient(); + +function print_results(obj) { + console.dir(obj); +} + +// build a map of all keys and their types +client.keys("*", function (err, all_keys) { + var key_types = {}; + + all_keys.forEach(function (key, pos) { // use second arg of forEach to get pos + client.type(key, function (err, type) { + key_types[key] = type; + if (pos === all_keys.length - 1) { // callbacks all run in order + print_results(key_types); + } + }); + }); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/unix_socket.js b/node_modules/socket.io/node_modules/redis/examples/unix_socket.js new file mode 100644 index 00000000..4a5e0bb0 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/unix_socket.js @@ -0,0 +1,29 @@ +var redis = require("redis"), + client = redis.createClient("/tmp/redis.sock"), + profiler = require("v8-profiler"); + +client.on("connect", function () { + console.log("Got Unix socket connection.") +}); + +client.on("error", function (err) { + console.log(err.message); +}); + +client.set("space chars", "space value"); + +setInterval(function () { + client.get("space chars"); +}, 100); + +function done() { + client.info(function (err, reply) { + console.log(reply.toString()); + client.quit(); + }); +} + +setTimeout(function () { + console.log("Taking snapshot."); + var snap = profiler.takeSnapshot(); +}, 5000); diff --git a/node_modules/socket.io/node_modules/redis/examples/web_server.js b/node_modules/socket.io/node_modules/redis/examples/web_server.js new file mode 100644 index 00000000..9fd85923 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/web_server.js @@ -0,0 +1,31 @@ +// A simple web server that generates dyanmic content based on responses from Redis + +var http = require("http"), server, + redis_client = require("redis").createClient(); + +server = http.createServer(function (request, response) { + response.writeHead(200, { + "Content-Type": "text/plain" + }); + + var redis_info, total_requests; + + redis_client.info(function (err, reply) { + redis_info = reply; // stash response in outer scope + }); + redis_client.incr("requests", function (err, reply) { + total_requests = reply; // stash response in outer scope + }); + redis_client.hincrby("ip", request.connection.remoteAddress, 1); + redis_client.hgetall("ip", function (err, reply) { + // This is the last reply, so all of the previous replies must have completed already + response.write("This page was generated after talking to redis.\n\n" + + "Redis info:\n" + redis_info + "\n" + + "Total requests: " + total_requests + "\n\n" + + "IP count: \n"); + Object.keys(reply).forEach(function (ip) { + response.write(" " + ip + ": " + reply[ip] + "\n"); + }); + response.end(); + }); +}).listen(80); diff --git a/node_modules/socket.io/node_modules/redis/generate_commands.js b/node_modules/socket.io/node_modules/redis/generate_commands.js new file mode 100644 index 00000000..e6949d3a --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/generate_commands.js @@ -0,0 +1,39 @@ +var http = require("http"), + fs = require("fs"); + +function prettyCurrentTime() { + var date = new Date(); + return date.toLocaleString(); +} + +function write_file(commands, path) { + var file_contents, out_commands; + + console.log("Writing " + Object.keys(commands).length + " commands to " + path); + + file_contents = "// This file was generated by ./generate_commands.js on " + prettyCurrentTime() + "\n"; + + out_commands = Object.keys(commands).map(function (key) { + return key.toLowerCase(); + }); + + file_contents += "module.exports = " + JSON.stringify(out_commands, null, " ") + ";\n"; + + fs.writeFile(path, file_contents); +} + +http.get({host: "redis.io", path: "/commands.json"}, function (res) { + var body = ""; + + console.log("Response from redis.io/commands.json: " + res.statusCode); + + res.on('data', function (chunk) { + body += chunk; + }); + + res.on('end', function () { + write_file(JSON.parse(body), "lib/commands.js"); + }); +}).on('error', function (e) { + console.log("Error fetching command list from redis.io: " + e.message); +}); diff --git a/node_modules/socket.io/node_modules/redis/index.js b/node_modules/socket.io/node_modules/redis/index.js new file mode 100644 index 00000000..61cb4e91 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/index.js @@ -0,0 +1,1113 @@ +/*global Buffer require exports console setTimeout */ + +var net = require("net"), + util = require("./lib/util"), + Queue = require("./lib/queue"), + to_array = require("./lib/to_array"), + events = require("events"), + crypto = require("crypto"), + parsers = [], commands, + connection_id = 0, + default_port = 6379, + default_host = "127.0.0.1"; + +// can set this to true to enable for all connections +exports.debug_mode = false; + +// hiredis might not be installed +try { + require("./lib/parser/hiredis"); + parsers.push(require("./lib/parser/hiredis")); +} catch (err) { + if (exports.debug_mode) { + console.warn("hiredis parser not installed."); + } +} + +parsers.push(require("./lib/parser/javascript")); + +function RedisClient(stream, options) { + this.stream = stream; + this.options = options = options || {}; + + this.connection_id = ++connection_id; + this.connected = false; + this.ready = false; + this.connections = 0; + if (this.options.socket_nodelay === undefined) { + this.options.socket_nodelay = true; + } + this.should_buffer = false; + this.command_queue_high_water = this.options.command_queue_high_water || 1000; + this.command_queue_low_water = this.options.command_queue_low_water || 0; + this.max_attempts = null; + if (options.max_attempts && !isNaN(options.max_attempts) && options.max_attempts > 0) { + this.max_attempts = +options.max_attempts; + } + this.command_queue = new Queue(); // holds sent commands to de-pipeline them + this.offline_queue = new Queue(); // holds commands issued but not able to be sent + this.commands_sent = 0; + this.connect_timeout = false; + if (options.connect_timeout && !isNaN(options.connect_timeout) && options.connect_timeout > 0) { + this.connect_timeout = +options.connect_timeout; + } + + this.enable_offline_queue = true; + if (typeof this.options.enable_offline_queue === "boolean") { + this.enable_offline_queue = this.options.enable_offline_queue; + } + + this.initialize_retry_vars(); + this.pub_sub_mode = false; + this.subscription_set = {}; + this.monitoring = false; + this.closing = false; + this.server_info = {}; + this.auth_pass = null; + this.parser_module = null; + this.selected_db = null; // save the selected db here, used when reconnecting + + this.old_state = null; + + var self = this; + + this.stream.on("connect", function () { + self.on_connect(); + }); + + this.stream.on("data", function (buffer_from_socket) { + self.on_data(buffer_from_socket); + }); + + this.stream.on("error", function (msg) { + self.on_error(msg.message); + }); + + this.stream.on("close", function () { + self.connection_gone("close"); + }); + + this.stream.on("end", function () { + self.connection_gone("end"); + }); + + this.stream.on("drain", function () { + self.should_buffer = false; + self.emit("drain"); + }); + + events.EventEmitter.call(this); +} +util.inherits(RedisClient, events.EventEmitter); +exports.RedisClient = RedisClient; + +RedisClient.prototype.initialize_retry_vars = function () { + this.retry_timer = null; + this.retry_totaltime = 0; + this.retry_delay = 150; + this.retry_backoff = 1.7; + this.attempts = 1; +}; + +// flush offline_queue and command_queue, erroring any items with a callback first +RedisClient.prototype.flush_and_error = function (message) { + var command_obj; + while (this.offline_queue.length > 0) { + command_obj = this.offline_queue.shift(); + if (typeof command_obj.callback === "function") { + command_obj.callback(message); + } + } + this.offline_queue = new Queue(); + + while (this.command_queue.length > 0) { + command_obj = this.command_queue.shift(); + if (typeof command_obj.callback === "function") { + command_obj.callback(message); + } + } + this.command_queue = new Queue(); +}; + +RedisClient.prototype.on_error = function (msg) { + var message = "Redis connection to " + this.host + ":" + this.port + " failed - " + msg, + self = this, command_obj; + + if (this.closing) { + return; + } + + if (exports.debug_mode) { + console.warn(message); + } + + this.flush_and_error(message); + + this.connected = false; + this.ready = false; + + this.emit("error", new Error(message)); + // "error" events get turned into exceptions if they aren't listened for. If the user handled this error + // then we should try to reconnect. + this.connection_gone("error"); +}; + +RedisClient.prototype.do_auth = function () { + var self = this; + + if (exports.debug_mode) { + console.log("Sending auth to " + self.host + ":" + self.port + " id " + self.connection_id); + } + self.send_anyway = true; + self.send_command("auth", [this.auth_pass], function (err, res) { + if (err) { + if (err.toString().match("LOADING")) { + // if redis is still loading the db, it will not authenticate and everything else will fail + console.log("Redis still loading, trying to authenticate later"); + setTimeout(function () { + self.do_auth(); + }, 2000); // TODO - magic number alert + return; + } else { + return self.emit("error", new Error("Auth error: " + err.message)); + } + } + if (res.toString() !== "OK") { + return self.emit("error", new Error("Auth failed: " + res.toString())); + } + if (exports.debug_mode) { + console.log("Auth succeeded " + self.host + ":" + self.port + " id " + self.connection_id); + } + if (self.auth_callback) { + self.auth_callback(err, res); + self.auth_callback = null; + } + + // now we are really connected + self.emit("connect"); + if (self.options.no_ready_check) { + self.on_ready(); + } else { + self.ready_check(); + } + }); + self.send_anyway = false; +}; + +RedisClient.prototype.on_connect = function () { + if (exports.debug_mode) { + console.log("Stream connected " + this.host + ":" + this.port + " id " + this.connection_id); + } + var self = this; + + this.connected = true; + this.ready = false; + this.attempts = 0; + this.connections += 1; + this.command_queue = new Queue(); + this.emitted_end = false; + this.initialize_retry_vars(); + if (this.options.socket_nodelay) { + this.stream.setNoDelay(); + } + this.stream.setTimeout(0); + + this.init_parser(); + + if (this.auth_pass) { + this.do_auth(); + } else { + this.emit("connect"); + + if (this.options.no_ready_check) { + this.on_ready(); + } else { + this.ready_check(); + } + } +}; + +RedisClient.prototype.init_parser = function () { + var self = this; + + if (this.options.parser) { + if (! parsers.some(function (parser) { + if (parser.name === self.options.parser) { + self.parser_module = parser; + if (exports.debug_mode) { + console.log("Using parser module: " + self.parser_module.name); + } + return true; + } + })) { + throw new Error("Couldn't find named parser " + self.options.parser + " on this system"); + } + } else { + if (exports.debug_mode) { + console.log("Using default parser module: " + parsers[0].name); + } + this.parser_module = parsers[0]; + } + + this.parser_module.debug_mode = exports.debug_mode; + + // return_buffers sends back Buffers from parser to callback. detect_buffers sends back Buffers from parser, but + // converts to Strings if the input arguments are not Buffers. + this.reply_parser = new this.parser_module.Parser({ + return_buffers: self.options.return_buffers || self.options.detect_buffers || false + }); + + // "reply error" is an error sent back by Redis + this.reply_parser.on("reply error", function (reply) { + self.return_error(new Error(reply)); + }); + this.reply_parser.on("reply", function (reply) { + self.return_reply(reply); + }); + // "error" is bad. Somehow the parser got confused. It'll try to reset and continue. + this.reply_parser.on("error", function (err) { + self.emit("error", new Error("Redis reply parser error: " + err.stack)); + }); +}; + +RedisClient.prototype.on_ready = function () { + var self = this; + + this.ready = true; + + if (this.old_state !== null) { + this.monitoring = this.old_state.monitoring; + this.pub_sub_mode = this.old_state.pub_sub_mode; + this.selected_db = this.old_state.selected_db; + this.old_state = null; + } + + // magically restore any modal commands from a previous connection + if (this.selected_db !== null) { + this.send_command('select', [this.selected_db]); + } + if (this.pub_sub_mode === true) { + // only emit "ready" when all subscriptions were made again + var callback_count = 0; + var callback = function() { + callback_count--; + if (callback_count == 0) { + self.emit("ready"); + } + } + Object.keys(this.subscription_set).forEach(function (key) { + var parts = key.split(" "); + if (exports.debug_mode) { + console.warn("sending pub/sub on_ready " + parts[0] + ", " + parts[1]); + } + callback_count++; + self.send_command(parts[0] + "scribe", [parts[1]], callback); + }); + return; + } else if (this.monitoring) { + this.send_command("monitor"); + } else { + this.send_offline_queue(); + } + this.emit("ready"); +}; + +RedisClient.prototype.on_info_cmd = function (err, res) { + var self = this, obj = {}, lines, retry_time; + + if (err) { + return self.emit("error", new Error("Ready check failed: " + err.message)); + } + + lines = res.toString().split("\r\n"); + + lines.forEach(function (line) { + var parts = line.split(':'); + if (parts[1]) { + obj[parts[0]] = parts[1]; + } + }); + + obj.versions = []; + obj.redis_version.split('.').forEach(function (num) { + obj.versions.push(+num); + }); + + // expose info key/vals to users + this.server_info = obj; + + if (!obj.loading || (obj.loading && obj.loading === "0")) { + if (exports.debug_mode) { + console.log("Redis server ready."); + } + this.on_ready(); + } else { + retry_time = obj.loading_eta_seconds * 1000; + if (retry_time > 1000) { + retry_time = 1000; + } + if (exports.debug_mode) { + console.log("Redis server still loading, trying again in " + retry_time); + } + setTimeout(function () { + self.ready_check(); + }, retry_time); + } +}; + +RedisClient.prototype.ready_check = function () { + var self = this; + + if (exports.debug_mode) { + console.log("checking server ready state..."); + } + + this.send_anyway = true; // secret flag to send_command to send something even if not "ready" + this.info(function (err, res) { + self.on_info_cmd(err, res); + }); + this.send_anyway = false; +}; + +RedisClient.prototype.send_offline_queue = function () { + var command_obj, buffered_writes = 0; + + while (this.offline_queue.length > 0) { + command_obj = this.offline_queue.shift(); + if (exports.debug_mode) { + console.log("Sending offline command: " + command_obj.command); + } + buffered_writes += !this.send_command(command_obj.command, command_obj.args, command_obj.callback); + } + this.offline_queue = new Queue(); + // Even though items were shifted off, Queue backing store still uses memory until next add, so just get a new Queue + + if (!buffered_writes) { + this.should_buffer = false; + this.emit("drain"); + } +}; + +RedisClient.prototype.connection_gone = function (why) { + var self = this, message; + + // If a retry is already in progress, just let that happen + if (this.retry_timer) { + return; + } + + if (exports.debug_mode) { + console.warn("Redis connection is gone from " + why + " event."); + } + this.connected = false; + this.ready = false; + + if (this.old_state === null) { + var state = { + monitoring: this.monitoring, + pub_sub_mode: this.pub_sub_mode, + selected_db: this.selected_db + }; + this.old_state = state; + this.monitoring = false; + this.pub_sub_mode = false; + this.selected_db = null; + } + + // since we are collapsing end and close, users don't expect to be called twice + if (! this.emitted_end) { + this.emit("end"); + this.emitted_end = true; + } + + this.flush_and_error("Redis connection gone from " + why + " event."); + + // If this is a requested shutdown, then don't retry + if (this.closing) { + this.retry_timer = null; + if (exports.debug_mode) { + console.warn("connection ended from quit command, not retrying."); + } + return; + } + + this.retry_delay = Math.floor(this.retry_delay * this.retry_backoff); + + if (exports.debug_mode) { + console.log("Retry connection in " + this.current_retry_delay + " ms"); + } + + if (this.max_attempts && this.attempts >= this.max_attempts) { + this.retry_timer = null; + // TODO - some people need a "Redis is Broken mode" for future commands that errors immediately, and others + // want the program to exit. Right now, we just log, which doesn't really help in either case. + console.error("node_redis: Couldn't get Redis connection after " + this.max_attempts + " attempts."); + return; + } + + this.attempts += 1; + this.emit("reconnecting", { + delay: self.retry_delay, + attempt: self.attempts + }); + this.retry_timer = setTimeout(function () { + if (exports.debug_mode) { + console.log("Retrying connection..."); + } + + self.retry_totaltime += self.current_retry_delay; + + if (self.connect_timeout && self.retry_totaltime >= self.connect_timeout) { + self.retry_timer = null; + // TODO - engage Redis is Broken mode for future commands, or whatever + console.error("node_redis: Couldn't get Redis connection after " + self.retry_totaltime + "ms."); + return; + } + + self.stream.connect(self.port, self.host); + self.retry_timer = null; + }, this.retry_delay); +}; + +RedisClient.prototype.on_data = function (data) { + if (exports.debug_mode) { + console.log("net read " + this.host + ":" + this.port + " id " + this.connection_id + ": " + data.toString()); + } + + try { + this.reply_parser.execute(data); + } catch (err) { + // This is an unexpected parser problem, an exception that came from the parser code itself. + // Parser should emit "error" events if it notices things are out of whack. + // Callbacks that throw exceptions will land in return_reply(), below. + // TODO - it might be nice to have a different "error" event for different types of errors + this.emit("error", err); + } +}; + +RedisClient.prototype.return_error = function (err) { + var command_obj = this.command_queue.shift(), queue_len = this.command_queue.getLength(); + + if (this.pub_sub_mode === false && queue_len === 0) { + this.emit("idle"); + this.command_queue = new Queue(); + } + if (this.should_buffer && queue_len <= this.command_queue_low_water) { + this.emit("drain"); + this.should_buffer = false; + } + + if (command_obj && typeof command_obj.callback === "function") { + try { + command_obj.callback(err); + } catch (callback_err) { + // if a callback throws an exception, re-throw it on a new stack so the parser can keep going + process.nextTick(function () { + throw callback_err; + }); + } + } else { + console.log("node_redis: no callback to send error: " + err.message); + // this will probably not make it anywhere useful, but we might as well throw + process.nextTick(function () { + throw err; + }); + } +}; + +// if a callback throws an exception, re-throw it on a new stack so the parser can keep going. +// put this try/catch in its own function because V8 doesn't optimize this well yet. +function try_callback(callback, reply) { + try { + callback(null, reply); + } catch (err) { + process.nextTick(function () { + throw err; + }); + } +} + +// hgetall converts its replies to an Object. If the reply is empty, null is returned. +function reply_to_object(reply) { + var obj = {}, j, jl, key, val; + + if (reply.length === 0) { + return null; + } + + for (j = 0, jl = reply.length; j < jl; j += 2) { + key = reply[j].toString(); + val = reply[j + 1]; + obj[key] = val; + } + + return obj; +} + +function reply_to_strings(reply) { + var i; + + if (Buffer.isBuffer(reply)) { + return reply.toString(); + } + + if (Array.isArray(reply)) { + for (i = 0; i < reply.length; i++) { + reply[i] = reply[i].toString(); + } + return reply; + } + + return reply; +} + +RedisClient.prototype.return_reply = function (reply) { + var command_obj, obj, i, len, type, timestamp, argindex, args, queue_len; + + command_obj = this.command_queue.shift(), + queue_len = this.command_queue.getLength(); + + if (this.pub_sub_mode === false && queue_len === 0) { + this.emit("idle"); + this.command_queue = new Queue(); // explicitly reclaim storage from old Queue + } + if (this.should_buffer && queue_len <= this.command_queue_low_water) { + this.emit("drain"); + this.should_buffer = false; + } + + if (command_obj && !command_obj.sub_command) { + if (typeof command_obj.callback === "function") { + if (this.options.detect_buffers && command_obj.buffer_args === false) { + // If detect_buffers option was specified, then the reply from the parser will be Buffers. + // If this command did not use Buffer arguments, then convert the reply to Strings here. + reply = reply_to_strings(reply); + } + + // TODO - confusing and error-prone that hgetall is special cased in two places + if (reply && 'hgetall' === command_obj.command.toLowerCase()) { + reply = reply_to_object(reply); + } + + try_callback(command_obj.callback, reply); + } else if (exports.debug_mode) { + console.log("no callback for reply: " + (reply && reply.toString && reply.toString())); + } + } else if (this.pub_sub_mode || (command_obj && command_obj.sub_command)) { + if (Array.isArray(reply)) { + type = reply[0].toString(); + + if (type === "message") { + this.emit("message", reply[1].toString(), reply[2]); // channel, message + } else if (type === "pmessage") { + this.emit("pmessage", reply[1].toString(), reply[2].toString(), reply[3]); // pattern, channel, message + } else if (type === "subscribe" || type === "unsubscribe" || type === "psubscribe" || type === "punsubscribe") { + if (reply[2] === 0) { + this.pub_sub_mode = false; + if (this.debug_mode) { + console.log("All subscriptions removed, exiting pub/sub mode"); + } + } else { + this.pub_sub_mode = true; + } + // subscribe commands take an optional callback and also emit an event, but only the first response is included in the callback + // TODO - document this or fix it so it works in a more obvious way + if (command_obj && typeof command_obj.callback === "function") { + try_callback(command_obj.callback, reply[1].toString()); + } + this.emit(type, reply[1].toString(), reply[2]); // channel, count + } else { + throw new Error("subscriptions are active but got unknown reply type " + type); + } + } else if (! this.closing) { + throw new Error("subscriptions are active but got an invalid reply: " + reply); + } + } else if (this.monitoring) { + len = reply.indexOf(" "); + timestamp = reply.slice(0, len); + argindex = reply.indexOf('"'); + args = reply.slice(argindex + 1, -1).split('" "').map(function (elem) { + return elem.replace(/\\"/g, '"'); + }); + this.emit("monitor", timestamp, args); + } else { + throw new Error("node_redis command queue state error. If you can reproduce this, please report it."); + } +}; + +// This Command constructor is ever so slightly faster than using an object literal, but more importantly, using +// a named constructor helps it show up meaningfully in the V8 CPU profiler and in heap snapshots. +function Command(command, args, sub_command, buffer_args, callback) { + this.command = command; + this.args = args; + this.sub_command = sub_command; + this.buffer_args = buffer_args; + this.callback = callback; +} + +RedisClient.prototype.send_command = function (command, args, callback) { + var arg, this_args, command_obj, i, il, elem_count, buffer_args, stream = this.stream, command_str = "", buffered_writes = 0, last_arg_type; + + if (typeof command !== "string") { + throw new Error("First argument to send_command must be the command name string, not " + typeof command); + } + + if (Array.isArray(args)) { + if (typeof callback === "function") { + // probably the fastest way: + // client.command([arg1, arg2], cb); (straight passthrough) + // send_command(command, [arg1, arg2], cb); + } else if (! callback) { + // most people find this variable argument length form more convenient, but it uses arguments, which is slower + // client.command(arg1, arg2, cb); (wraps up arguments into an array) + // send_command(command, [arg1, arg2, cb]); + // client.command(arg1, arg2); (callback is optional) + // send_command(command, [arg1, arg2]); + // client.command(arg1, arg2, undefined); (callback is undefined) + // send_command(command, [arg1, arg2, undefined]); + last_arg_type = typeof args[args.length - 1]; + if (last_arg_type === "function" || last_arg_type === "undefined") { + callback = args.pop(); + } + } else { + throw new Error("send_command: last argument must be a callback or undefined"); + } + } else { + throw new Error("send_command: second argument must be an array"); + } + + // if the last argument is an array and command is sadd, expand it out: + // client.sadd(arg1, [arg2, arg3, arg4], cb); + // converts to: + // client.sadd(arg1, arg2, arg3, arg4, cb); + if ((command === 'sadd' || command === 'SADD') && args.length > 0 && Array.isArray(args[args.length - 1])) { + args = args.slice(0, -1).concat(args[args.length - 1]); + } + + buffer_args = false; + for (i = 0, il = args.length, arg; i < il; i += 1) { + if (Buffer.isBuffer(args[i])) { + buffer_args = true; + } + } + + command_obj = new Command(command, args, false, buffer_args, callback); + + if ((!this.ready && !this.send_anyway) || !stream.writable) { + if (exports.debug_mode) { + if (!stream.writable) { + console.log("send command: stream is not writeable."); + } + } + + if (this.enable_offline_queue) { + if (exports.debug_mode) { + console.log("Queueing " + command + " for next server connection."); + } + this.offline_queue.push(command_obj); + this.should_buffer = true; + } else { + var not_writeable_error = new Error('send_command: stream not writeable. enable_offline_queue is false'); + if (command_obj.callback) { + command_obj.callback(not_writeable_error); + } else { + throw not_writeable_error; + } + } + + return false; + } + + if (command === "subscribe" || command === "psubscribe" || command === "unsubscribe" || command === "punsubscribe") { + this.pub_sub_command(command_obj); + } else if (command === "monitor") { + this.monitoring = true; + } else if (command === "quit") { + this.closing = true; + } else if (this.pub_sub_mode === true) { + throw new Error("Connection in pub/sub mode, only pub/sub commands may be used"); + } + this.command_queue.push(command_obj); + this.commands_sent += 1; + + elem_count = args.length + 1; + + // Always use "Multi bulk commands", but if passed any Buffer args, then do multiple writes, one for each arg. + // This means that using Buffers in commands is going to be slower, so use Strings if you don't already have a Buffer. + + command_str = "*" + elem_count + "\r\n$" + command.length + "\r\n" + command + "\r\n"; + + if (! buffer_args) { // Build up a string and send entire command in one write + for (i = 0, il = args.length, arg; i < il; i += 1) { + arg = args[i]; + if (typeof arg !== "string") { + arg = String(arg); + } + command_str += "$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n"; + } + if (exports.debug_mode) { + console.log("send " + this.host + ":" + this.port + " id " + this.connection_id + ": " + command_str); + } + buffered_writes += !stream.write(command_str); + } else { + if (exports.debug_mode) { + console.log("send command (" + command_str + ") has Buffer arguments"); + } + buffered_writes += !stream.write(command_str); + + for (i = 0, il = args.length, arg; i < il; i += 1) { + arg = args[i]; + if (!(Buffer.isBuffer(arg) || arg instanceof String)) { + arg = String(arg); + } + + if (Buffer.isBuffer(arg)) { + if (arg.length === 0) { + if (exports.debug_mode) { + console.log("send_command: using empty string for 0 length buffer"); + } + buffered_writes += !stream.write("$0\r\n\r\n"); + } else { + buffered_writes += !stream.write("$" + arg.length + "\r\n"); + buffered_writes += !stream.write(arg); + buffered_writes += !stream.write("\r\n"); + if (exports.debug_mode) { + console.log("send_command: buffer send " + arg.length + " bytes"); + } + } + } else { + if (exports.debug_mode) { + console.log("send_command: string send " + Buffer.byteLength(arg) + " bytes: " + arg); + } + buffered_writes += !stream.write("$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n"); + } + } + } + if (exports.debug_mode) { + console.log("send_command buffered_writes: " + buffered_writes, " should_buffer: " + this.should_buffer); + } + if (buffered_writes || this.command_queue.getLength() >= this.command_queue_high_water) { + this.should_buffer = true; + } + return !this.should_buffer; +}; + +RedisClient.prototype.pub_sub_command = function (command_obj) { + var i, key, command, args; + + if (this.pub_sub_mode === false && exports.debug_mode) { + console.log("Entering pub/sub mode from " + command_obj.command); + } + this.pub_sub_mode = true; + command_obj.sub_command = true; + + command = command_obj.command; + args = command_obj.args; + if (command === "subscribe" || command === "psubscribe") { + if (command === "subscribe") { + key = "sub"; + } else { + key = "psub"; + } + for (i = 0; i < args.length; i++) { + this.subscription_set[key + " " + args[i]] = true; + } + } else { + if (command === "unsubscribe") { + key = "sub"; + } else { + key = "psub"; + } + for (i = 0; i < args.length; i++) { + delete this.subscription_set[key + " " + args[i]]; + } + } +}; + +RedisClient.prototype.end = function () { + this.stream._events = {}; + this.connected = false; + this.ready = false; + return this.stream.end(); +}; + +function Multi(client, args) { + this.client = client; + this.queue = [["MULTI"]]; + if (Array.isArray(args)) { + this.queue = this.queue.concat(args); + } +} + +exports.Multi = Multi; + +// take 2 arrays and return the union of their elements +function set_union(seta, setb) { + var obj = {}; + + seta.forEach(function (val) { + obj[val] = true; + }); + setb.forEach(function (val) { + obj[val] = true; + }); + return Object.keys(obj); +} + +// This static list of commands is updated from time to time. ./lib/commands.js can be updated with generate_commands.js +commands = set_union(["get", "set", "setnx", "setex", "append", "strlen", "del", "exists", "setbit", "getbit", "setrange", "getrange", "substr", + "incr", "decr", "mget", "rpush", "lpush", "rpushx", "lpushx", "linsert", "rpop", "lpop", "brpop", "brpoplpush", "blpop", "llen", "lindex", + "lset", "lrange", "ltrim", "lrem", "rpoplpush", "sadd", "srem", "smove", "sismember", "scard", "spop", "srandmember", "sinter", "sinterstore", + "sunion", "sunionstore", "sdiff", "sdiffstore", "smembers", "zadd", "zincrby", "zrem", "zremrangebyscore", "zremrangebyrank", "zunionstore", + "zinterstore", "zrange", "zrangebyscore", "zrevrangebyscore", "zcount", "zrevrange", "zcard", "zscore", "zrank", "zrevrank", "hset", "hsetnx", + "hget", "hmset", "hmget", "hincrby", "hdel", "hlen", "hkeys", "hvals", "hgetall", "hexists", "incrby", "decrby", "getset", "mset", "msetnx", + "randomkey", "select", "move", "rename", "renamenx", "expire", "expireat", "keys", "dbsize", "auth", "ping", "echo", "save", "bgsave", + "bgrewriteaof", "shutdown", "lastsave", "type", "multi", "exec", "discard", "sync", "flushdb", "flushall", "sort", "info", "monitor", "ttl", + "persist", "slaveof", "debug", "config", "subscribe", "unsubscribe", "psubscribe", "punsubscribe", "publish", "watch", "unwatch", "cluster", + "restore", "migrate", "dump", "object", "client", "eval", "evalsha"], require("./lib/commands")); + +commands.forEach(function (command) { + RedisClient.prototype[command] = function (args, callback) { + if (Array.isArray(args) && typeof callback === "function") { + return this.send_command(command, args, callback); + } else { + return this.send_command(command, to_array(arguments)); + } + }; + RedisClient.prototype[command.toUpperCase()] = RedisClient.prototype[command]; + + Multi.prototype[command] = function () { + this.queue.push([command].concat(to_array(arguments))); + return this; + }; + Multi.prototype[command.toUpperCase()] = Multi.prototype[command]; +}); + +// store db in this.select_db to restore it on reconnect +RedisClient.prototype.select = function (db, callback) { + var self = this; + + this.send_command('select', [db], function (err, res) { + if (err === null) { + self.selected_db = db; + } + if (typeof(callback) === 'function') { + callback(err, res); + } + }); +}; +RedisClient.prototype.SELECT = RedisClient.prototype.select; + +// Stash auth for connect and reconnect. Send immediately if already connected. +RedisClient.prototype.auth = function () { + var args = to_array(arguments); + this.auth_pass = args[0]; + this.auth_callback = args[1]; + if (exports.debug_mode) { + console.log("Saving auth as " + this.auth_pass); + } + + if (this.connected) { + this.send_command("auth", args); + } +}; +RedisClient.prototype.AUTH = RedisClient.prototype.auth; + +RedisClient.prototype.hmget = function (arg1, arg2, arg3) { + if (Array.isArray(arg2) && typeof arg3 === "function") { + return this.send_command("hmget", [arg1].concat(arg2), arg3); + } else if (Array.isArray(arg1) && typeof arg2 === "function") { + return this.send_command("hmget", arg1, arg2); + } else { + return this.send_command("hmget", to_array(arguments)); + } +}; +RedisClient.prototype.HMGET = RedisClient.prototype.hmget; + +RedisClient.prototype.hmset = function (args, callback) { + var tmp_args, tmp_keys, i, il, key; + + if (Array.isArray(args) && typeof callback === "function") { + return this.send_command("hmset", args, callback); + } + + args = to_array(arguments); + if (typeof args[args.length - 1] === "function") { + callback = args[args.length - 1]; + args.length -= 1; + } else { + callback = null; + } + + if (args.length === 2 && typeof args[0] === "string" && typeof args[1] === "object") { + // User does: client.hmset(key, {key1: val1, key2: val2}) + tmp_args = [ args[0] ]; + tmp_keys = Object.keys(args[1]); + for (i = 0, il = tmp_keys.length; i < il ; i++) { + key = tmp_keys[i]; + tmp_args.push(key); + if (typeof args[1][key] !== "string") { + var err = new Error("hmset expected value to be a string", key, ":", args[1][key]); + if (callback) return callback(err); + else throw err; + } + tmp_args.push(args[1][key]); + } + args = tmp_args; + } + + return this.send_command("hmset", args, callback); +}; +RedisClient.prototype.HMSET = RedisClient.prototype.hmset; + +Multi.prototype.hmset = function () { + var args = to_array(arguments), tmp_args; + if (args.length >= 2 && typeof args[0] === "string" && typeof args[1] === "object") { + tmp_args = [ "hmset", args[0] ]; + Object.keys(args[1]).map(function (key) { + tmp_args.push(key); + tmp_args.push(args[1][key]); + }); + if (args[2]) { + tmp_args.push(args[2]); + } + args = tmp_args; + } else { + args.unshift("hmset"); + } + + this.queue.push(args); + return this; +}; +Multi.prototype.HMSET = Multi.prototype.hmset; + +Multi.prototype.exec = function (callback) { + var self = this; + + // drain queue, callback will catch "QUEUED" or error + // TODO - get rid of all of these anonymous functions which are elegant but slow + this.queue.forEach(function (args, index) { + var command = args[0], obj; + if (typeof args[args.length - 1] === "function") { + args = args.slice(1, -1); + } else { + args = args.slice(1); + } + if (args.length === 1 && Array.isArray(args[0])) { + args = args[0]; + } + if (command.toLowerCase() === 'hmset' && typeof args[1] === 'object') { + obj = args.pop(); + Object.keys(obj).forEach(function (key) { + args.push(key); + args.push(obj[key]); + }); + } + this.client.send_command(command, args, function (err, reply) { + if (err) { + var cur = self.queue[index]; + if (typeof cur[cur.length - 1] === "function") { + cur[cur.length - 1](err); + } else { + throw new Error(err); + } + self.queue.splice(index, 1); + } + }); + }, this); + + // TODO - make this callback part of Multi.prototype instead of creating it each time + return this.client.send_command("EXEC", [], function (err, replies) { + if (err) { + if (callback) { + callback(new Error(err)); + return; + } else { + throw new Error(err); + } + } + + var i, il, j, jl, reply, args; + + if (replies) { + for (i = 1, il = self.queue.length; i < il; i += 1) { + reply = replies[i - 1]; + args = self.queue[i]; + + // TODO - confusing and error-prone that hgetall is special cased in two places + if (reply && args[0].toLowerCase() === "hgetall") { + replies[i - 1] = reply = reply_to_object(reply); + } + + if (typeof args[args.length - 1] === "function") { + args[args.length - 1](null, reply); + } + } + } + + if (callback) { + callback(null, replies); + } + }); +}; +Multi.prototype.EXEC = Multi.prototype.exec; + +RedisClient.prototype.multi = function (args) { + return new Multi(this, args); +}; +RedisClient.prototype.MULTI = function (args) { + return new Multi(this, args); +}; + + +// stash original eval method +var eval = RedisClient.prototype.eval; +// hook eval with an attempt to evalsha for cached scripts +RedisClient.prototype.eval = +RedisClient.prototype.EVAL = function () { + var self = this, + args = to_array(arguments), + callback; + + if (typeof args[args.length - 1] === "function") { + callback = args.pop(); + } + + // replace script source with sha value + var source = args[0]; + args[0] = crypto.createHash("sha1").update(source).digest("hex"); + + self.evalsha(args, function (err, reply) { + if (err && /NOSCRIPT/.test(err.message)) { + args[0] = source; + eval.call(self, args, callback); + + } else if (callback) { + callback(err, reply); + } + }); +}; + + +exports.createClient = function (port_arg, host_arg, options) { + var port = port_arg || default_port, + host = host_arg || default_host, + redis_client, net_client; + + net_client = net.createConnection(port, host); + + redis_client = new RedisClient(net_client, options); + + redis_client.port = port; + redis_client.host = host; + + return redis_client; +}; + +exports.print = function (err, reply) { + if (err) { + console.log("Error: " + err); + } else { + console.log("Reply: " + reply); + } +}; diff --git a/node_modules/socket.io/node_modules/redis/lib/commands.js b/node_modules/socket.io/node_modules/redis/lib/commands.js new file mode 100644 index 00000000..f57cca96 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/commands.js @@ -0,0 +1,147 @@ +// This file was generated by ./generate_commands.js on Mon Aug 06 2012 15:04:06 GMT-0700 (PDT) +module.exports = [ + "append", + "auth", + "bgrewriteaof", + "bgsave", + "bitcount", + "bitop", + "blpop", + "brpop", + "brpoplpush", + "client kill", + "client list", + "config get", + "config set", + "config resetstat", + "dbsize", + "debug object", + "debug segfault", + "decr", + "decrby", + "del", + "discard", + "dump", + "echo", + "eval", + "evalsha", + "exec", + "exists", + "expire", + "expireat", + "flushall", + "flushdb", + "get", + "getbit", + "getrange", + "getset", + "hdel", + "hexists", + "hget", + "hgetall", + "hincrby", + "hincrbyfloat", + "hkeys", + "hlen", + "hmget", + "hmset", + "hset", + "hsetnx", + "hvals", + "incr", + "incrby", + "incrbyfloat", + "info", + "keys", + "lastsave", + "lindex", + "linsert", + "llen", + "lpop", + "lpush", + "lpushx", + "lrange", + "lrem", + "lset", + "ltrim", + "mget", + "migrate", + "monitor", + "move", + "mset", + "msetnx", + "multi", + "object", + "persist", + "pexpire", + "pexpireat", + "ping", + "psetex", + "psubscribe", + "pttl", + "publish", + "punsubscribe", + "quit", + "randomkey", + "rename", + "renamenx", + "restore", + "rpop", + "rpoplpush", + "rpush", + "rpushx", + "sadd", + "save", + "scard", + "script exists", + "script flush", + "script kill", + "script load", + "sdiff", + "sdiffstore", + "select", + "set", + "setbit", + "setex", + "setnx", + "setrange", + "shutdown", + "sinter", + "sinterstore", + "sismember", + "slaveof", + "slowlog", + "smembers", + "smove", + "sort", + "spop", + "srandmember", + "srem", + "strlen", + "subscribe", + "sunion", + "sunionstore", + "sync", + "time", + "ttl", + "type", + "unsubscribe", + "unwatch", + "watch", + "zadd", + "zcard", + "zcount", + "zincrby", + "zinterstore", + "zrange", + "zrangebyscore", + "zrank", + "zrem", + "zremrangebyrank", + "zremrangebyscore", + "zrevrange", + "zrevrangebyscore", + "zrevrank", + "zscore", + "zunionstore" +]; diff --git a/node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js b/node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js new file mode 100644 index 00000000..cbb15ba3 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js @@ -0,0 +1,46 @@ +/*global Buffer require exports console setTimeout */ + +var events = require("events"), + util = require("../util"), + hiredis = require("hiredis"); + +exports.debug_mode = false; +exports.name = "hiredis"; + +function HiredisReplyParser(options) { + this.name = exports.name; + this.options = options || {}; + this.reset(); + events.EventEmitter.call(this); +} + +util.inherits(HiredisReplyParser, events.EventEmitter); + +exports.Parser = HiredisReplyParser; + +HiredisReplyParser.prototype.reset = function () { + this.reader = new hiredis.Reader({ + return_buffers: this.options.return_buffers || false + }); +}; + +HiredisReplyParser.prototype.execute = function (data) { + var reply; + this.reader.feed(data); + while (true) { + try { + reply = this.reader.get(); + } catch (err) { + this.emit("error", err); + break; + } + + if (reply === undefined) break; + + if (reply && reply.constructor === Error) { + this.emit("reply error", reply); + } else { + this.emit("reply", reply); + } + } +}; diff --git a/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js b/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js new file mode 100644 index 00000000..b8f5bc68 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js @@ -0,0 +1,317 @@ +/*global Buffer require exports console setTimeout */ + +// TODO - incorporate these V8 pro tips: +// pre-allocate Arrays if length is known in advance +// do not use delete +// use numbers for parser state + +var events = require("events"), + util = require("../util"); + +exports.debug_mode = false; +exports.name = "javascript"; + +function RedisReplyParser(options) { + this.name = exports.name; + this.options = options || {}; + this.reset(); + events.EventEmitter.call(this); +} + +util.inherits(RedisReplyParser, events.EventEmitter); + +exports.Parser = RedisReplyParser; + +// Buffer.toString() is quite slow for small strings +function small_toString(buf, len) { + var tmp = "", i; + + for (i = 0; i < len; i += 1) { + tmp += String.fromCharCode(buf[i]); + } + + return tmp; +} + +// Reset parser to it's original state. +RedisReplyParser.prototype.reset = function () { + this.return_buffer = new Buffer(16384); // for holding replies, might grow + this.return_string = ""; + this.tmp_string = ""; // for holding size fields + + this.multi_bulk_length = 0; + this.multi_bulk_replies = null; + this.multi_bulk_pos = 0; + this.multi_bulk_nested_length = 0; + this.multi_bulk_nested_replies = null; + + this.states = { + TYPE: 1, + SINGLE_LINE: 2, + MULTI_BULK_COUNT: 3, + INTEGER_LINE: 4, + BULK_LENGTH: 5, + ERROR_LINE: 6, + BULK_DATA: 7, + UNKNOWN_TYPE: 8, + FINAL_CR: 9, + FINAL_LF: 10, + MULTI_BULK_COUNT_LF: 11, + BULK_LF: 12 + }; + + this.state = this.states.TYPE; +}; + +RedisReplyParser.prototype.parser_error = function (message) { + this.emit("error", message); + this.reset(); +}; + +RedisReplyParser.prototype.execute = function (incoming_buf) { + var pos = 0, bd_tmp, bd_str, i, il, states = this.states; + //, state_times = {}, start_execute = new Date(), start_switch, end_switch, old_state; + //start_switch = new Date(); + + while (pos < incoming_buf.length) { + // old_state = this.state; + // console.log("execute: " + this.state + ", " + pos + "/" + incoming_buf.length + ", " + String.fromCharCode(incoming_buf[pos])); + + switch (this.state) { + case 1: // states.TYPE + this.type = incoming_buf[pos]; + pos += 1; + + switch (this.type) { + case 43: // + + this.state = states.SINGLE_LINE; + this.return_buffer.end = 0; + this.return_string = ""; + break; + case 42: // * + this.state = states.MULTI_BULK_COUNT; + this.tmp_string = ""; + break; + case 58: // : + this.state = states.INTEGER_LINE; + this.return_buffer.end = 0; + this.return_string = ""; + break; + case 36: // $ + this.state = states.BULK_LENGTH; + this.tmp_string = ""; + break; + case 45: // - + this.state = states.ERROR_LINE; + this.return_buffer.end = 0; + this.return_string = ""; + break; + default: + this.state = states.UNKNOWN_TYPE; + } + break; + case 4: // states.INTEGER_LINE + if (incoming_buf[pos] === 13) { + this.send_reply(+small_toString(this.return_buffer, this.return_buffer.end)); + this.state = states.FINAL_LF; + } else { + this.return_buffer[this.return_buffer.end] = incoming_buf[pos]; + this.return_buffer.end += 1; + } + pos += 1; + break; + case 6: // states.ERROR_LINE + if (incoming_buf[pos] === 13) { + this.send_error(this.return_buffer.toString("ascii", 0, this.return_buffer.end)); + this.state = states.FINAL_LF; + } else { + this.return_buffer[this.return_buffer.end] = incoming_buf[pos]; + this.return_buffer.end += 1; + } + pos += 1; + break; + case 2: // states.SINGLE_LINE + if (incoming_buf[pos] === 13) { + this.send_reply(this.return_string); + this.state = states.FINAL_LF; + } else { + this.return_string += String.fromCharCode(incoming_buf[pos]); + } + pos += 1; + break; + case 3: // states.MULTI_BULK_COUNT + if (incoming_buf[pos] === 13) { // \r + this.state = states.MULTI_BULK_COUNT_LF; + } else { + this.tmp_string += String.fromCharCode(incoming_buf[pos]); + } + pos += 1; + break; + case 11: // states.MULTI_BULK_COUNT_LF + if (incoming_buf[pos] === 10) { // \n + if (this.multi_bulk_length) { // nested multi-bulk + this.multi_bulk_nested_length = this.multi_bulk_length; + this.multi_bulk_nested_replies = this.multi_bulk_replies; + this.multi_bulk_nested_pos = this.multi_bulk_pos; + } + this.multi_bulk_length = +this.tmp_string; + this.multi_bulk_pos = 0; + this.state = states.TYPE; + if (this.multi_bulk_length < 0) { + this.send_reply(null); + this.multi_bulk_length = 0; + } else if (this.multi_bulk_length === 0) { + this.multi_bulk_pos = 0; + this.multi_bulk_replies = null; + this.send_reply([]); + } else { + this.multi_bulk_replies = new Array(this.multi_bulk_length); + } + } else { + this.parser_error(new Error("didn't see LF after NL reading multi bulk count")); + return; + } + pos += 1; + break; + case 5: // states.BULK_LENGTH + if (incoming_buf[pos] === 13) { // \r + this.state = states.BULK_LF; + } else { + this.tmp_string += String.fromCharCode(incoming_buf[pos]); + } + pos += 1; + break; + case 12: // states.BULK_LF + if (incoming_buf[pos] === 10) { // \n + this.bulk_length = +this.tmp_string; + if (this.bulk_length === -1) { + this.send_reply(null); + this.state = states.TYPE; + } else if (this.bulk_length === 0) { + this.send_reply(new Buffer("")); + this.state = states.FINAL_CR; + } else { + this.state = states.BULK_DATA; + if (this.bulk_length > this.return_buffer.length) { + if (exports.debug_mode) { + console.log("Growing return_buffer from " + this.return_buffer.length + " to " + this.bulk_length); + } + this.return_buffer = new Buffer(this.bulk_length); + } + this.return_buffer.end = 0; + } + } else { + this.parser_error(new Error("didn't see LF after NL while reading bulk length")); + return; + } + pos += 1; + break; + case 7: // states.BULK_DATA + this.return_buffer[this.return_buffer.end] = incoming_buf[pos]; + this.return_buffer.end += 1; + pos += 1; + if (this.return_buffer.end === this.bulk_length) { + bd_tmp = new Buffer(this.bulk_length); + // When the response is small, Buffer.copy() is a lot slower. + if (this.bulk_length > 10) { + this.return_buffer.copy(bd_tmp, 0, 0, this.bulk_length); + } else { + for (i = 0, il = this.bulk_length; i < il; i += 1) { + bd_tmp[i] = this.return_buffer[i]; + } + } + this.send_reply(bd_tmp); + this.state = states.FINAL_CR; + } + break; + case 9: // states.FINAL_CR + if (incoming_buf[pos] === 13) { // \r + this.state = states.FINAL_LF; + pos += 1; + } else { + this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final CR")); + return; + } + break; + case 10: // states.FINAL_LF + if (incoming_buf[pos] === 10) { // \n + this.state = states.TYPE; + pos += 1; + } else { + this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final LF")); + return; + } + break; + default: + this.parser_error(new Error("invalid state " + this.state)); + } + // end_switch = new Date(); + // if (state_times[old_state] === undefined) { + // state_times[old_state] = 0; + // } + // state_times[old_state] += (end_switch - start_switch); + // start_switch = end_switch; + } + // console.log("execute ran for " + (Date.now() - start_execute) + " ms, on " + incoming_buf.length + " Bytes. "); + // Object.keys(state_times).forEach(function (state) { + // console.log(" " + state + ": " + state_times[state]); + // }); +}; + +RedisReplyParser.prototype.send_error = function (reply) { + if (this.multi_bulk_length > 0 || this.multi_bulk_nested_length > 0) { + // TODO - can this happen? Seems like maybe not. + this.add_multi_bulk_reply(reply); + } else { + this.emit("reply error", reply); + } +}; + +RedisReplyParser.prototype.send_reply = function (reply) { + if (this.multi_bulk_length > 0 || this.multi_bulk_nested_length > 0) { + if (!this.options.return_buffers && Buffer.isBuffer(reply)) { + this.add_multi_bulk_reply(reply.toString("utf8")); + } else { + this.add_multi_bulk_reply(reply); + } + } else { + if (!this.options.return_buffers && Buffer.isBuffer(reply)) { + this.emit("reply", reply.toString("utf8")); + } else { + this.emit("reply", reply); + } + } +}; + +RedisReplyParser.prototype.add_multi_bulk_reply = function (reply) { + if (this.multi_bulk_replies) { + this.multi_bulk_replies[this.multi_bulk_pos] = reply; + this.multi_bulk_pos += 1; + if (this.multi_bulk_pos < this.multi_bulk_length) { + return; + } + } else { + this.multi_bulk_replies = reply; + } + + if (this.multi_bulk_nested_length > 0) { + this.multi_bulk_nested_replies[this.multi_bulk_nested_pos] = this.multi_bulk_replies; + this.multi_bulk_nested_pos += 1; + + this.multi_bulk_length = 0; + this.multi_bulk_replies = null; + this.multi_bulk_pos = 0; + + if (this.multi_bulk_nested_length === this.multi_bulk_nested_pos) { + this.emit("reply", this.multi_bulk_nested_replies); + this.multi_bulk_nested_length = 0; + this.multi_bulk_nested_pos = 0; + this.multi_bulk_nested_replies = null; + } + } else { + this.emit("reply", this.multi_bulk_replies); + this.multi_bulk_length = 0; + this.multi_bulk_replies = null; + this.multi_bulk_pos = 0; + } +}; diff --git a/node_modules/socket.io/node_modules/redis/lib/queue.js b/node_modules/socket.io/node_modules/redis/lib/queue.js new file mode 100644 index 00000000..56254e1c --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/queue.js @@ -0,0 +1,61 @@ +var to_array = require("./to_array"); + +// Queue class adapted from Tim Caswell's pattern library +// http://github.com/creationix/pattern/blob/master/lib/pattern/queue.js + +function Queue() { + this.tail = []; + this.head = []; + this.offset = 0; +} + +Queue.prototype.shift = function () { + if (this.offset === this.head.length) { + var tmp = this.head; + tmp.length = 0; + this.head = this.tail; + this.tail = tmp; + this.offset = 0; + if (this.head.length === 0) { + return; + } + } + return this.head[this.offset++]; // sorry, JSLint +}; + +Queue.prototype.push = function (item) { + return this.tail.push(item); +}; + +Queue.prototype.forEach = function (fn, thisv) { + var array = this.head.slice(this.offset), i, il; + + array.push.apply(array, this.tail); + + if (thisv) { + for (i = 0, il = array.length; i < il; i += 1) { + fn.call(thisv, array[i], i, array); + } + } else { + for (i = 0, il = array.length; i < il; i += 1) { + fn(array[i], i, array); + } + } + + return array; +}; + +Queue.prototype.getLength = function () { + return this.head.length - this.offset + this.tail.length; +}; + +Object.defineProperty(Queue.prototype, 'length', { + get: function () { + return this.getLength(); + } +}); + + +if(typeof module !== 'undefined' && module.exports) { + module.exports = Queue; +} diff --git a/node_modules/socket.io/node_modules/redis/lib/to_array.js b/node_modules/socket.io/node_modules/redis/lib/to_array.js new file mode 100644 index 00000000..88a57e18 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/to_array.js @@ -0,0 +1,12 @@ +function to_array(args) { + var len = args.length, + arr = new Array(len), i; + + for (i = 0; i < len; i += 1) { + arr[i] = args[i]; + } + + return arr; +} + +module.exports = to_array; diff --git a/node_modules/socket.io/node_modules/redis/lib/util.js b/node_modules/socket.io/node_modules/redis/lib/util.js new file mode 100644 index 00000000..fc255ae9 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/util.js @@ -0,0 +1,11 @@ +// Support for very old versions of node where the module was called "sys". At some point, we should abandon this. + +var util; + +try { + util = require("util"); +} catch (err) { + util = require("sys"); +} + +module.exports = util; diff --git a/node_modules/socket.io/node_modules/redis/mem.js b/node_modules/socket.io/node_modules/redis/mem.js new file mode 100644 index 00000000..5144ab28 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/mem.js @@ -0,0 +1,11 @@ +var client = require("redis").createClient(); + +client.set("foo", "barvalskdjlksdjflkdsjflksdjdflkdsjflksdjflksdj", function (err, res) { + if (err) { + console.log("Got an error, please adapt somehow."); + } else { + console.log("Got a result: " + res); + } +}); + +client.quit(); diff --git a/node_modules/socket.io/node_modules/redis/multi_bench.js b/node_modules/socket.io/node_modules/redis/multi_bench.js new file mode 100644 index 00000000..5be2e564 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/multi_bench.js @@ -0,0 +1,225 @@ +var redis = require("./index"), + metrics = require("metrics"), + num_clients = parseInt(process.argv[2], 10) || 5, + num_requests = 20000, + tests = [], + versions_logged = false, + client_options = { + return_buffers: false + }, + small_str, large_str, small_buf, large_buf; + +redis.debug_mode = false; + +function lpad(input, len, chr) { + var str = input.toString(); + chr = chr || " "; + + while (str.length < len) { + str = chr + str; + } + return str; +} + +metrics.Histogram.prototype.print_line = function () { + var obj = this.printObj(); + + return lpad(obj.min, 4) + "/" + lpad(obj.max, 4) + "/" + lpad(obj.mean.toFixed(2), 7) + "/" + lpad(obj.p95.toFixed(2), 7); +}; + +function Test(args) { + var self = this; + + this.args = args; + + this.callback = null; + this.clients = []; + this.clients_ready = 0; + this.commands_sent = 0; + this.commands_completed = 0; + this.max_pipeline = this.args.pipeline || num_requests; + this.client_options = args.client_options || client_options; + + this.connect_latency = new metrics.Histogram(); + this.ready_latency = new metrics.Histogram(); + this.command_latency = new metrics.Histogram(); +} + +Test.prototype.run = function (callback) { + var self = this, i; + + this.callback = callback; + + for (i = 0; i < num_clients ; i++) { + this.new_client(i); + } +}; + +Test.prototype.new_client = function (id) { + var self = this, new_client; + + new_client = redis.createClient(6379, "127.0.0.1", this.client_options); + new_client.create_time = Date.now(); + + new_client.on("connect", function () { + self.connect_latency.update(Date.now() - new_client.create_time); + }); + + new_client.on("ready", function () { + if (! versions_logged) { + console.log("Client count: " + num_clients + ", node version: " + process.versions.node + ", server version: " + + new_client.server_info.redis_version + ", parser: " + new_client.reply_parser.name); + versions_logged = true; + } + self.ready_latency.update(Date.now() - new_client.create_time); + self.clients_ready++; + if (self.clients_ready === self.clients.length) { + self.on_clients_ready(); + } + }); + + self.clients[id] = new_client; +}; + +Test.prototype.on_clients_ready = function () { + process.stdout.write(lpad(this.args.descr, 13) + ", " + lpad(this.args.pipeline, 5) + "/" + this.clients_ready + " "); + this.test_start = Date.now(); + + this.fill_pipeline(); +}; + +Test.prototype.fill_pipeline = function () { + var pipeline = this.commands_sent - this.commands_completed; + + while (this.commands_sent < num_requests && pipeline < this.max_pipeline) { + this.commands_sent++; + pipeline++; + this.send_next(); + } + + if (this.commands_completed === num_requests) { + this.print_stats(); + this.stop_clients(); + } +}; + +Test.prototype.stop_clients = function () { + var self = this; + + this.clients.forEach(function (client, pos) { + if (pos === self.clients.length - 1) { + client.quit(function (err, res) { + self.callback(); + }); + } else { + client.quit(); + } + }); +}; + +Test.prototype.send_next = function () { + var self = this, + cur_client = this.commands_sent % this.clients.length, + command_num = this.commands_sent, + start = Date.now(); + + this.clients[cur_client][this.args.command](this.args.args, function (err, res) { + if (err) { + throw err; + } + self.commands_completed++; + self.command_latency.update(Date.now() - start); + self.fill_pipeline(); + }); +}; + +Test.prototype.print_stats = function () { + var duration = Date.now() - this.test_start; + + console.log("min/max/avg/p95: " + this.command_latency.print_line() + " " + lpad(duration, 6) + "ms total, " + + lpad((num_requests / (duration / 1000)).toFixed(2), 8) + " ops/sec"); +}; + +small_str = "1234"; +small_buf = new Buffer(small_str); +large_str = (new Array(4097).join("-")); +large_buf = new Buffer(large_str); + +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 1})); +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 50})); +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 200})); +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 20000})); + +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 1})); +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 50})); +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 200})); +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 20000})); + +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 1})); +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 50})); +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 200})); +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 20000})); + +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 1})); +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 50})); +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 200})); +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 20000})); + +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 1, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 50, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 200, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 20000, client_opts: { return_buffers: true} })); + +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 1})); +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 50})); +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 200})); +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 20000})); + +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 1})); +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 50})); +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 200})); +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 20000})); + +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 1})); +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 50})); +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 200})); +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 20000})); + +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 1, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 50, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 200, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 20000, client_opts: { return_buffers: true} })); + +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 1})); +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 50})); +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 200})); +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 20000})); + +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 1})); +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 50})); +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 200})); +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 20000})); + +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 1})); +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 50})); +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 200})); +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 20000})); + +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 1})); +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 50})); +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 200})); +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 20000})); + +function next() { + var test = tests.shift(); + if (test) { + test.run(function () { + next(); + }); + } else { + console.log("End of tests."); + process.exit(0); + } +} + +next(); diff --git a/node_modules/socket.io/node_modules/redis/package.json b/node_modules/socket.io/node_modules/redis/package.json new file mode 100644 index 00000000..d77bbc8a --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/package.json @@ -0,0 +1,38 @@ +{ + "name": "redis", + "version": "0.7.3", + "description": "Redis client library", + "author": { + "name": "Matt Ranney", + "email": "mjr@ranney.com" + }, + "maintainers": [ + { + "name": "David Trejo", + "email": "david.daniel.trejo@gmail.com", + "url": "http://dtrejo.com/" + } + ], + "main": "./index.js", + "scripts": { + "test": "node ./test.js" + }, + "devDependencies": { + "metrics": ">=0.1.5" + }, + "repository": { + "type": "git", + "url": "git://github.com/mranney/node_redis.git" + }, + "readme": "redis - a node.js redis client\n===========================\n\nThis is a complete Redis client for node.js. It supports all Redis commands, including many recently added commands like EVAL from\nexperimental Redis server branches.\n\n\nInstall with:\n\n npm install redis\n\nPieter Noordhuis has provided a binding to the official `hiredis` C library, which is non-blocking and fast. To use `hiredis`, do:\n\n npm install hiredis redis\n\nIf `hiredis` is installed, `node_redis` will use it by default. Otherwise, a pure JavaScript parser will be used.\n\nIf you use `hiredis`, be sure to rebuild it whenever you upgrade your version of node. There are mysterious failures that can\nhappen between node and native code modules after a node upgrade.\n\n\n## Usage\n\nSimple example, included as `examples/simple.js`:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n // if you'd like to select database 3, instead of 0 (default), call\n // client.select(3, function() { /* ... */ });\n\n client.on(\"error\", function (err) {\n console.log(\"Error \" + err);\n });\n\n client.set(\"string key\", \"string val\", redis.print);\n client.hset(\"hash key\", \"hashtest 1\", \"some value\", redis.print);\n client.hset([\"hash key\", \"hashtest 2\", \"some other value\"], redis.print);\n client.hkeys(\"hash key\", function (err, replies) {\n console.log(replies.length + \" replies:\");\n replies.forEach(function (reply, i) {\n console.log(\" \" + i + \": \" + reply);\n });\n client.quit();\n });\n```\n\nThis will display:\n\n mjr:~/work/node_redis (master)$ node example.js\n Reply: OK\n Reply: 0\n Reply: 0\n 2 replies:\n 0: hashtest 1\n 1: hashtest 2\n mjr:~/work/node_redis (master)$\n\n\n## Performance\n\nHere are typical results of `multi_bench.js` which is similar to `redis-benchmark` from the Redis distribution.\nIt uses 50 concurrent connections with no pipelining.\n\nJavaScript parser:\n\n PING: 20000 ops 42283.30 ops/sec 0/5/1.182\n SET: 20000 ops 32948.93 ops/sec 1/7/1.515\n GET: 20000 ops 28694.40 ops/sec 0/9/1.740\n INCR: 20000 ops 39370.08 ops/sec 0/8/1.269\n LPUSH: 20000 ops 36429.87 ops/sec 0/8/1.370\n LRANGE (10 elements): 20000 ops 9891.20 ops/sec 1/9/5.048\n LRANGE (100 elements): 20000 ops 1384.56 ops/sec 10/91/36.072\n\nhiredis parser:\n\n PING: 20000 ops 46189.38 ops/sec 1/4/1.082\n SET: 20000 ops 41237.11 ops/sec 0/6/1.210\n GET: 20000 ops 39682.54 ops/sec 1/7/1.257\n INCR: 20000 ops 40080.16 ops/sec 0/8/1.242\n LPUSH: 20000 ops 41152.26 ops/sec 0/3/1.212\n LRANGE (10 elements): 20000 ops 36563.07 ops/sec 1/8/1.363\n LRANGE (100 elements): 20000 ops 21834.06 ops/sec 0/9/2.287\n\nThe performance of `node_redis` improves dramatically with pipelining, which happens automatically in most normal programs.\n\n\n### Sending Commands\n\nEach Redis command is exposed as a function on the `client` object.\nAll functions take either an `args` Array plus optional `callback` Function or\na variable number of individual arguments followed by an optional callback.\nHere is an example of passing an array of arguments and a callback:\n\n client.mset([\"test keys 1\", \"test val 1\", \"test keys 2\", \"test val 2\"], function (err, res) {});\n\nHere is that same call in the second style:\n\n client.mset(\"test keys 1\", \"test val 1\", \"test keys 2\", \"test val 2\", function (err, res) {});\n\nNote that in either form the `callback` is optional:\n\n client.set(\"some key\", \"some val\");\n client.set([\"some other key\", \"some val\"]);\n\nIf the key is missing, reply will be null (probably):\n\n client.get(\"missingkey\", function(err, reply) {\n // reply is null when the key is missing\n console.log(reply);\n });\n\nFor a list of Redis commands, see [Redis Command Reference](http://redis.io/commands)\n\nThe commands can be specified in uppercase or lowercase for convenience. `client.get()` is the same as `client.GET()`.\n\nMinimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings,\ninteger replies return JavaScript Numbers, \"bulk\" replies return node Buffers, and \"multi bulk\" replies return a\nJavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keyed by the hash keys.\n\n# API\n\n## Connection Events\n\n`client` will emit some events about the state of the connection to the Redis server.\n\n### \"ready\"\n\n`client` will emit `ready` a connection is established to the Redis server and the server reports\nthat it is ready to receive commands. Commands issued before the `ready` event are queued,\nthen replayed just before this event is emitted.\n\n### \"connect\"\n\n`client` will emit `connect` at the same time as it emits `ready` unless `client.options.no_ready_check`\nis set. If this options is set, `connect` will be emitted when the stream is connected, and then\nyou are free to try to send commands.\n\n### \"error\"\n\n`client` will emit `error` when encountering an error connecting to the Redis server.\n\nNote that \"error\" is a special event type in node. If there are no listeners for an\n\"error\" event, node will exit. This is usually what you want, but it can lead to some\ncryptic error messages like this:\n\n mjr:~/work/node_redis (master)$ node example.js\n\n node.js:50\n throw e;\n ^\n Error: ECONNREFUSED, Connection refused\n at IOWatcher.callback (net:870:22)\n at node.js:607:9\n\nNot very useful in diagnosing the problem, but if your program isn't ready to handle this,\nit is probably the right thing to just exit.\n\n`client` will also emit `error` if an exception is thrown inside of `node_redis` for whatever reason.\nIt would be nice to distinguish these two cases.\n\n### \"end\"\n\n`client` will emit `end` when an established Redis server connection has closed.\n\n### \"drain\"\n\n`client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now\nwritable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now,\nyou need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can\nresume sending when you get `drain`.\n\n### \"idle\"\n\n`client` will emit `idle` when there are no outstanding commands that are awaiting a response.\n\n## redis.createClient(port, host, options)\n\nCreate a new client connection. `port` defaults to `6379` and `host` defaults\nto `127.0.0.1`. If you have `redis-server` running on the same computer as node, then the defaults for\nport and host are probably fine. `options` in an object with the following possible properties:\n\n* `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed.\nThis may also be set to `javascript`.\n* `return_buffers`: defaults to `false`. If set to `true`, then all replies will be sent to callbacks as node Buffer\nobjects instead of JavaScript Strings.\n* `detect_buffers`: default to `false`. If set to `true`, then replies will be sent to callbacks as node Buffer objects\nif any of the input arguments to the original command were Buffer objects.\nThis option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to\nevery command on a client.\n* `socket_nodelay`: defaults to `true`. Whether to call setNoDelay() on the TCP stream, which disables the\nNagle algorithm on the underlying socket. Setting this option to `false` can result in additional throughput at the\ncost of more latency. Most applications will want this set to `true`.\n* `no_ready_check`: defaults to `false`. When a connection is established to the Redis server, the server might still\nbe loading the database from disk. While loading, the server not respond to any commands. To work around this,\n`node_redis` has a \"ready check\" which sends the `INFO` command to the server. The response from the `INFO` command\nindicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event.\nSetting `no_ready_check` to `true` will inhibit this check.\n* `enable_offline_queue`: defaults to `true`. By default, if there is no active\nconnection to the redis server, commands are added to a queue and are executed\nonce the connection has been established. Setting `enable_offline_queue` to\n`false` will disable this feature and the callback will be execute immediately\nwith an error, or an error will be thrown if no callback is specified.\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient(null, null, {detect_buffers: true});\n\n client.set(\"foo_rand000000000000\", \"OK\");\n\n // This will return a JavaScript String\n client.get(\"foo_rand000000000000\", function (err, reply) {\n console.log(reply.toString()); // Will print `OK`\n });\n\n // This will return a Buffer since original key is specified as a Buffer\n client.get(new Buffer(\"foo_rand000000000000\"), function (err, reply) {\n console.log(reply.toString()); // Will print ``\n });\n client.end();\n```\n\n`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here.\n\n## client.auth(password, callback)\n\nWhen connecting to Redis servers that require authentication, the `AUTH` command must be sent as the\nfirst command after connecting. This can be tricky to coordinate with reconnections, the ready check,\netc. To make this easier, `client.auth()` stashes `password` and will send it after each connection,\nincluding reconnections. `callback` is invoked only once, after the response to the very first\n`AUTH` command sent.\nNOTE: Your call to `client.auth()` should not be inside the ready handler. If\nyou are doing this wrong, `client` will emit an error that looks\nsomething like this `Error: Ready check failed: ERR operation not permitted`.\n\n## client.end()\n\nForcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed.\nIf you want to exit cleanly, call `client.quit()` to send the `QUIT` command after you have handled all replies.\n\nThis example closes the connection to the Redis server before the replies have been read. You probably don't\nwant to do this:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n client.set(\"foo_rand000000000000\", \"some fantastic value\");\n client.get(\"foo_rand000000000000\", function (err, reply) {\n console.log(reply.toString());\n });\n client.end();\n```\n\n`client.end()` is useful for timeout cases where something is stuck or taking too long and you want\nto start over.\n\n## Friendlier hash commands\n\nMost Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings.\nWhen dealing with hash values, there are a couple of useful exceptions to this.\n\n### client.hgetall(hash)\n\nThe reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact\nwith the responses using JavaScript syntax.\n\nExample:\n\n client.hmset(\"hosts\", \"mjr\", \"1\", \"another\", \"23\", \"home\", \"1234\");\n client.hgetall(\"hosts\", function (err, obj) {\n console.dir(obj);\n });\n\nOutput:\n\n { mjr: '1', another: '23', home: '1234' }\n\n### client.hmset(hash, obj, [callback])\n\nMultiple values in a hash can be set by supplying an object:\n\n client.HMSET(key2, {\n \"0123456789\": \"abcdefghij\", // NOTE: the key and value must both be strings\n \"some manner of key\": \"a type of value\"\n });\n\nThe properties and values of this Object will be set as keys and values in the Redis hash.\n\n### client.hmset(hash, key1, val1, ... keyn, valn, [callback])\n\nMultiple values may also be set by supplying a list:\n\n client.HMSET(key1, \"0123456789\", \"abcdefghij\", \"some manner of key\", \"a type of value\");\n\n\n## Publish / Subscribe\n\nHere is a simple example of the API for publish / subscribe. This program opens two\nclient connections, subscribes to a channel on one of them, and publishes to that\nchannel on the other:\n\n```js\n var redis = require(\"redis\"),\n client1 = redis.createClient(), client2 = redis.createClient(),\n msg_count = 0;\n\n client1.on(\"subscribe\", function (channel, count) {\n client2.publish(\"a nice channel\", \"I am sending a message.\");\n client2.publish(\"a nice channel\", \"I am sending a second message.\");\n client2.publish(\"a nice channel\", \"I am sending my last message.\");\n });\n\n client1.on(\"message\", function (channel, message) {\n console.log(\"client1 channel \" + channel + \": \" + message);\n msg_count += 1;\n if (msg_count === 3) {\n client1.unsubscribe();\n client1.end();\n client2.end();\n }\n });\n\n client1.incr(\"did a thing\");\n client1.subscribe(\"a nice channel\");\n```\n\nWhen a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into \"pub/sub\" mode.\nAt that point, only commands that modify the subscription set are valid. When the subscription\nset is empty, the connection is put back into regular mode.\n\nIf you need to send regular commands to Redis while in pub/sub mode, just open another connection.\n\n## Pub / Sub Events\n\nIf a client has subscriptions active, it may emit these events:\n\n### \"message\" (channel, message)\n\nClient will emit `message` for every message received that matches an active subscription.\nListeners are passed the channel name as `channel` and the message Buffer as `message`.\n\n### \"pmessage\" (pattern, channel, message)\n\nClient will emit `pmessage` for every message received that matches an active subscription pattern.\nListeners are passed the original pattern used with `PSUBSCRIBE` as `pattern`, the sending channel\nname as `channel`, and the message Buffer as `message`.\n\n### \"subscribe\" (channel, count)\n\nClient will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the\nchannel name as `channel` and the new count of subscriptions for this client as `count`.\n\n### \"psubscribe\" (pattern, count)\n\nClient will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the\noriginal pattern as `pattern`, and the new count of subscriptions for this client as `count`.\n\n### \"unsubscribe\" (channel, count)\n\nClient will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the\nchannel name as `channel` and the new count of subscriptions for this client as `count`. When\n`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.\n\n### \"punsubscribe\" (pattern, count)\n\nClient will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the\nchannel name as `channel` and the new count of subscriptions for this client as `count`. When\n`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.\n\n## client.multi([commands])\n\n`MULTI` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by\nRedis. The interface in `node_redis` is to return an individual `Multi` object by calling `client.multi()`.\n\n```js\n var redis = require(\"./index\"),\n client = redis.createClient(), set_size = 20;\n\n client.sadd(\"bigset\", \"a member\");\n client.sadd(\"bigset\", \"another member\");\n\n while (set_size > 0) {\n client.sadd(\"bigset\", \"member \" + set_size);\n set_size -= 1;\n }\n\n // multi chain with an individual callback\n client.multi()\n .scard(\"bigset\")\n .smembers(\"bigset\")\n .keys(\"*\", function (err, replies) {\n // NOTE: code in this callback is NOT atomic\n // this only happens after the the .exec call finishes.\n client.mget(replies, redis.print);\n })\n .dbsize()\n .exec(function (err, replies) {\n console.log(\"MULTI got \" + replies.length + \" replies\");\n replies.forEach(function (reply, index) {\n console.log(\"Reply \" + index + \": \" + reply.toString());\n });\n });\n```\n\n`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects share all of the\nsame command methods as `client` objects do. Commands are queued up inside the `Multi` object\nuntil `Multi.exec()` is invoked.\n\nYou can either chain together `MULTI` commands as in the above example, or you can queue individual\ncommands while still sending regular client command as in this example:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient(), multi;\n\n // start a separate multi command queue\n multi = client.multi();\n multi.incr(\"incr thing\", redis.print);\n multi.incr(\"incr other thing\", redis.print);\n\n // runs immediately\n client.mset(\"incr thing\", 100, \"incr other thing\", 1, redis.print);\n\n // drains multi queue and runs atomically\n multi.exec(function (err, replies) {\n console.log(replies); // 101, 2\n });\n\n // you can re-run the same transaction if you like\n multi.exec(function (err, replies) {\n console.log(replies); // 102, 3\n client.quit();\n });\n```\n\nIn addition to adding commands to the `MULTI` queue individually, you can also pass an array\nof commands and arguments to the constructor:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient(), multi;\n\n client.multi([\n [\"mget\", \"multifoo\", \"multibar\", redis.print],\n [\"incr\", \"multifoo\"],\n [\"incr\", \"multibar\"]\n ]).exec(function (err, replies) {\n console.log(replies);\n });\n```\n\n\n## Monitor mode\n\nRedis supports the `MONITOR` command, which lets you see all commands received by the Redis server\nacross all client connections, including from other client libraries and other computers.\n\nAfter you send the `MONITOR` command, no other commands are valid on that connection. `node_redis`\nwill emit a `monitor` event for every new monitor message that comes across. The callback for the\n`monitor` event takes a timestamp from the Redis server and an array of command arguments.\n\nHere is a simple example:\n\n```js\n var client = require(\"redis\").createClient(),\n util = require(\"util\");\n\n client.monitor(function (err, res) {\n console.log(\"Entering monitoring mode.\");\n });\n\n client.on(\"monitor\", function (time, args) {\n console.log(time + \": \" + util.inspect(args));\n });\n```\n\n# Extras\n\nSome other things you might like to know about.\n\n## client.server_info\n\nAfter the ready probe completes, the results from the INFO command are saved in the `client.server_info`\nobject.\n\nThe `versions` key contains an array of the elements of the version string for easy comparison.\n\n > client.server_info.redis_version\n '2.3.0'\n > client.server_info.versions\n [ 2, 3, 0 ]\n\n## redis.print()\n\nA handy callback function for displaying return values when testing. Example:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n client.on(\"connect\", function () {\n client.set(\"foo_rand000000000000\", \"some fantastic value\", redis.print);\n client.get(\"foo_rand000000000000\", redis.print);\n });\n```\n\nThis will print:\n\n Reply: OK\n Reply: some fantastic value\n\nNote that this program will not exit cleanly because the client is still connected.\n\n## redis.debug_mode\n\nBoolean to enable debug mode and protocol tracing.\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n redis.debug_mode = true;\n\n client.on(\"connect\", function () {\n client.set(\"foo_rand000000000000\", \"some fantastic value\");\n });\n```\n\nThis will display:\n\n mjr:~/work/node_redis (master)$ node ~/example.js\n send command: *3\n $3\n SET\n $20\n foo_rand000000000000\n $20\n some fantastic value\n\n on_data: +OK\n\n`send command` is data sent into Redis and `on_data` is data received from Redis.\n\n## client.send_command(command_name, args, callback)\n\nUsed internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis\nWiki have been added to the `client` object. However, if I missed any, or if new commands are introduced before\nthis library is updated, you can use `send_command()` to send arbitrary commands to Redis.\n\nAll commands are sent as multi-bulk commands. `args` can either be an Array of arguments, or omitted.\n\n## client.connected\n\nBoolean tracking the state of the connection to the Redis server.\n\n## client.command_queue.length\n\nThe number of commands that have been sent to the Redis server but not yet replied to. You can use this to\nenforce some kind of maximum queue depth for commands while connected.\n\nDon't mess with `client.command_queue` though unless you really know what you are doing.\n\n## client.offline_queue.length\n\nThe number of commands that have been queued up for a future connection. You can use this to enforce\nsome kind of maximum queue depth for pre-connection commands.\n\n## client.retry_delay\n\nCurrent delay in milliseconds before a connection retry will be attempted. This starts at `250`.\n\n## client.retry_backoff\n\nMultiplier for future retry timeouts. This should be larger than 1 to add more time between retries.\nDefaults to 1.7. The default initial connection retry is 250, so the second retry will be 425, followed by 723.5, etc.\n\n### Commands with Optional and Keyword arguments\n\nThis applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation.\n\nExample:\n```js\nvar args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ];\nclient.zadd(args, function (err, response) {\n if (err) throw err;\n console.log('added '+response+' items.');\n\n // -Infinity and +Infinity also work\n var args1 = [ 'myzset', '+inf', '-inf' ];\n client.zrevrangebyscore(args1, function (err, response) {\n if (err) throw err;\n console.log('example1', response);\n // write your code here\n });\n\n var max = 3, min = 1, offset = 1, count = 2;\n var args2 = [ 'myzset', max, min, 'WITHSCORES', 'LIMIT', offset, count ];\n client.zrevrangebyscore(args2, function (err, response) {\n if (err) throw err;\n console.log('example2', response);\n // write your code here\n });\n});\n```\n\n## TODO\n\nBetter tests for auth, disconnect/reconnect, and all combinations thereof.\n\nStream large set/get values into and out of Redis. Otherwise the entire value must be in node's memory.\n\nPerformance can be better for very large values.\n\nI think there are more performance improvements left in there for smaller values, especially for large lists of small values.\n\n## How to Contribute\n- open a pull request and then wait for feedback (if\n [DTrejo](http://github.com/dtrejo) does not get back to you within 2 days,\n comment again with indignation!)\n\n## Contributors\nSome people have have added features and fixed bugs in `node_redis` other than me.\n\nOrdered by date of first contribution.\n[Auto-generated](http://github.com/dtrejo/node-authors) on Wed Jul 25 2012 19:14:59 GMT-0700 (PDT).\n\n- [Matt Ranney aka `mranney`](https://github.com/mranney)\n- [Tim-Smart aka `tim-smart`](https://github.com/tim-smart)\n- [Tj Holowaychuk aka `visionmedia`](https://github.com/visionmedia)\n- [rick aka `technoweenie`](https://github.com/technoweenie)\n- [Orion Henry aka `orionz`](https://github.com/orionz)\n- [Aivo Paas aka `aivopaas`](https://github.com/aivopaas)\n- [Hank Sims aka `hanksims`](https://github.com/hanksims)\n- [Paul Carey aka `paulcarey`](https://github.com/paulcarey)\n- [Pieter Noordhuis aka `pietern`](https://github.com/pietern)\n- [nithesh aka `nithesh`](https://github.com/nithesh)\n- [Andy Ray aka `andy2ray`](https://github.com/andy2ray)\n- [unknown aka `unknowdna`](https://github.com/unknowdna)\n- [Dave Hoover aka `redsquirrel`](https://github.com/redsquirrel)\n- [Vladimir Dronnikov aka `dvv`](https://github.com/dvv)\n- [Umair Siddique aka `umairsiddique`](https://github.com/umairsiddique)\n- [Louis-Philippe Perron aka `lp`](https://github.com/lp)\n- [Mark Dawson aka `markdaws`](https://github.com/markdaws)\n- [Ian Babrou aka `bobrik`](https://github.com/bobrik)\n- [Felix Geisendörfer aka `felixge`](https://github.com/felixge)\n- [Jean-Hugues Pinson aka `undefined`](https://github.com/undefined)\n- [Maksim Lin aka `maks`](https://github.com/maks)\n- [Owen Smith aka `orls`](https://github.com/orls)\n- [Zachary Scott aka `zzak`](https://github.com/zzak)\n- [TEHEK Firefox aka `TEHEK`](https://github.com/TEHEK)\n- [Isaac Z. Schlueter aka `isaacs`](https://github.com/isaacs)\n- [David Trejo aka `DTrejo`](https://github.com/DTrejo)\n- [Brian Noguchi aka `bnoguchi`](https://github.com/bnoguchi)\n- [Philip Tellis aka `bluesmoon`](https://github.com/bluesmoon)\n- [Marcus Westin aka `marcuswestin2`](https://github.com/marcuswestin2)\n- [Jed Schmidt aka `jed`](https://github.com/jed)\n- [Dave Peticolas aka `jdavisp3`](https://github.com/jdavisp3)\n- [Trae Robrock aka `trobrock`](https://github.com/trobrock)\n- [Shankar Karuppiah aka `shankar0306`](https://github.com/shankar0306)\n- [Ignacio Burgueño aka `ignacio`](https://github.com/ignacio)\n\nThanks.\n\n## LICENSE - \"MIT License\"\n\nCopyright (c) 2010 Matthew Ranney, http://ranney.com/\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n![spacer](http://ranney.com/1px.gif)\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/mranney/node_redis/issues" + }, + "_id": "redis@0.7.3", + "dist": { + "shasum": "ec6291f6df0dcbe91e33b35c5735a7871b7a0c12" + }, + "_from": "redis@0.7.3", + "_resolved": "https://registry.npmjs.org/redis/-/redis-0.7.3.tgz" +} diff --git a/node_modules/socket.io/node_modules/redis/test.js b/node_modules/socket.io/node_modules/redis/test.js new file mode 100644 index 00000000..0a03375e --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/test.js @@ -0,0 +1,1618 @@ +/*global require console setTimeout process Buffer */ +var redis = require("./index"), + client = redis.createClient(), + client2 = redis.createClient(), + client3 = redis.createClient(), + assert = require("assert"), + crypto = require("crypto"), + util = require("./lib/util"), + test_db_num = 15, // this DB will be flushed and used for testing + tests = {}, + connected = false, + ended = false, + next, cur_start, run_next_test, all_tests, all_start, test_count; + +// Set this to truthy to see the wire protocol and other debugging info +redis.debug_mode = process.argv[2]; + +function buffers_to_strings(arr) { + return arr.map(function (val) { + return val.toString(); + }); +} + +function require_number(expected, label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected " + expected + ", got error: " + err); + assert.strictEqual(expected, results, label + " " + expected + " !== " + results); + assert.strictEqual(typeof results, "number", label); + return true; + }; +} + +function require_number_any(label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected any number, got error: " + err); + assert.strictEqual(typeof results, "number", label + " " + results + " is not a number"); + return true; + }; +} + +function require_number_pos(label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected positive number, got error: " + err); + assert.strictEqual(true, (results > 0), label + " " + results + " is not a positive number"); + return true; + }; +} + +function require_string(str, label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected string '" + str + "', got error: " + err); + assert.equal(str, results, label + " " + str + " does not match " + results); + return true; + }; +} + +function require_null(label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected null, got error: " + err); + assert.strictEqual(null, results, label + ": " + results + " is not null"); + return true; + }; +} + +function require_error(label) { + return function (err, results) { + assert.notEqual(err, null, label + " err is null, but an error is expected here."); + return true; + }; +} + +function is_empty_array(obj) { + return Array.isArray(obj) && obj.length === 0; +} + +function last(name, fn) { + return function (err, results) { + fn(err, results); + next(name); + }; +} + +next = function next(name) { + console.log(" \x1b[33m" + (Date.now() - cur_start) + "\x1b[0m ms"); + run_next_test(); +}; + +// Tests are run in the order they are defined. So FLUSHDB should be stay first. + +tests.FLUSHDB = function () { + var name = "FLUSHDB"; + client.select(test_db_num, require_string("OK", name)); + client2.select(test_db_num, require_string("OK", name)); + client3.select(test_db_num, require_string("OK", name)); + client.mset("flush keys 1", "flush val 1", "flush keys 2", "flush val 2", require_string("OK", name)); + client.FLUSHDB(require_string("OK", name)); + client.dbsize(last(name, require_number(0, name))); +}; + +tests.MULTI_1 = function () { + var name = "MULTI_1", multi1, multi2; + + // Provoke an error at queue time + multi1 = client.multi(); + multi1.mset("multifoo", "10", "multibar", "20", require_string("OK", name)); + multi1.set("foo2", require_error(name)); + multi1.incr("multifoo", require_number(11, name)); + multi1.incr("multibar", require_number(21, name)); + multi1.exec(); + + // Confirm that the previous command, while containing an error, still worked. + multi2 = client.multi(); + multi2.incr("multibar", require_number(22, name)); + multi2.incr("multifoo", require_number(12, name)); + multi2.exec(function (err, replies) { + assert.strictEqual(22, replies[0]); + assert.strictEqual(12, replies[1]); + next(name); + }); +}; + +tests.MULTI_2 = function () { + var name = "MULTI_2"; + + // test nested multi-bulk replies + client.multi([ + ["mget", "multifoo", "multibar", function (err, res) { + assert.strictEqual(2, res.length, name); + assert.strictEqual("12", res[0].toString(), name); + assert.strictEqual("22", res[1].toString(), name); + }], + ["set", "foo2", require_error(name)], + ["incr", "multifoo", require_number(13, name)], + ["incr", "multibar", require_number(23, name)] + ]).exec(function (err, replies) { + assert.strictEqual(2, replies[0].length, name); + assert.strictEqual("12", replies[0][0].toString(), name); + assert.strictEqual("22", replies[0][1].toString(), name); + + assert.strictEqual("13", replies[1].toString()); + assert.strictEqual("23", replies[2].toString()); + next(name); + }); +}; + +tests.MULTI_3 = function () { + var name = "MULTI_3"; + + client.sadd("some set", "mem 1"); + client.sadd("some set", "mem 2"); + client.sadd("some set", "mem 3"); + client.sadd("some set", "mem 4"); + + // make sure empty mb reply works + client.del("some missing set"); + client.smembers("some missing set", function (err, reply) { + // make sure empty mb reply works + assert.strictEqual(true, is_empty_array(reply), name); + }); + + // test nested multi-bulk replies with empty mb elements. + client.multi([ + ["smembers", "some set"], + ["del", "some set"], + ["smembers", "some set"] + ]) + .scard("some set") + .exec(function (err, replies) { + assert.strictEqual(true, is_empty_array(replies[2]), name); + next(name); + }); +}; + +tests.MULTI_4 = function () { + var name = "MULTI_4"; + + client.multi() + .mset('some', '10', 'keys', '20') + .incr('some') + .incr('keys') + .mget('some', 'keys') + .exec(function (err, replies) { + assert.strictEqual(null, err); + assert.equal('OK', replies[0]); + assert.equal(11, replies[1]); + assert.equal(21, replies[2]); + assert.equal(11, replies[3][0].toString()); + assert.equal(21, replies[3][1].toString()); + next(name); + }); +}; + +tests.MULTI_5 = function () { + var name = "MULTI_5"; + + // test nested multi-bulk replies with nulls. + client.multi([ + ["mget", ["multifoo", "some", "random value", "keys"]], + ["incr", "multifoo"] + ]) + .exec(function (err, replies) { + assert.strictEqual(replies.length, 2, name); + assert.strictEqual(replies[0].length, 4, name); + next(name); + }); +}; + +tests.MULTI_6 = function () { + var name = "MULTI_6"; + + client.multi() + .hmset("multihash", "a", "foo", "b", 1) + .hmset("multihash", { + extra: "fancy", + things: "here" + }) + .hgetall("multihash") + .exec(function (err, replies) { + assert.strictEqual(null, err); + assert.equal("OK", replies[0]); + assert.equal(Object.keys(replies[2]).length, 4); + assert.equal("foo", replies[2].a); + assert.equal("1", replies[2].b); + assert.equal("fancy", replies[2].extra); + assert.equal("here", replies[2].things); + next(name); + }); +}; + +tests.EVAL_1 = function () { + var name = "EVAL_1"; + + if (client.server_info.versions[0] >= 2 && client.server_info.versions[1] >= 5) { + // test {EVAL - Lua integer -> Redis protocol type conversion} + client.eval("return 100.5", 0, require_number(100, name)); + // test {EVAL - Lua string -> Redis protocol type conversion} + client.eval("return 'hello world'", 0, require_string("hello world", name)); + // test {EVAL - Lua true boolean -> Redis protocol type conversion} + client.eval("return true", 0, require_number(1, name)); + // test {EVAL - Lua false boolean -> Redis protocol type conversion} + client.eval("return false", 0, require_null(name)); + // test {EVAL - Lua status code reply -> Redis protocol type conversion} + client.eval("return {ok='fine'}", 0, require_string("fine", name)); + // test {EVAL - Lua error reply -> Redis protocol type conversion} + client.eval("return {err='this is an error'}", 0, require_error(name)); + // test {EVAL - Lua table -> Redis protocol type conversion} + client.eval("return {1,2,3,'ciao',{1,2}}", 0, function (err, res) { + assert.strictEqual(5, res.length, name); + assert.strictEqual(1, res[0], name); + assert.strictEqual(2, res[1], name); + assert.strictEqual(3, res[2], name); + assert.strictEqual("ciao", res[3], name); + assert.strictEqual(2, res[4].length, name); + assert.strictEqual(1, res[4][0], name); + assert.strictEqual(2, res[4][1], name); + }); + // test {EVAL - Are the KEYS and ARGS arrays populated correctly?} + client.eval("return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", 2, "a", "b", "c", "d", function (err, res) { + assert.strictEqual(4, res.length, name); + assert.strictEqual("a", res[0], name); + assert.strictEqual("b", res[1], name); + assert.strictEqual("c", res[2], name); + assert.strictEqual("d", res[3], name); + }); + + // prepare sha sum for evalsha cache test + var source = "return redis.call('get', 'sha test')", + sha = crypto.createHash('sha1').update(source).digest('hex'); + + client.set("sha test", "eval get sha test", function (err, res) { + if (err) throw err; + // test {EVAL - is Lua able to call Redis API?} + client.eval(source, 0, function (err, res) { + require_string("eval get sha test", name)(err, res); + // test {EVALSHA - Can we call a SHA1 if already defined?} + client.evalsha(sha, 0, require_string("eval get sha test", name)); + // test {EVALSHA - Do we get an error on non defined SHA1?} + client.evalsha("ffffffffffffffffffffffffffffffffffffffff", 0, require_error(name)); + }); + }); + + // test {EVAL - Redis integer -> Lua type conversion} + client.set("incr key", 0, function (err, reply) { + if (err) throw err; + client.eval("local foo = redis.call('incr','incr key')\n" + "return {type(foo),foo}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("number", res[0], name); + assert.strictEqual(1, res[1], name); + }); + }); + + client.set("bulk reply key", "bulk reply value", function (err, res) { + // test {EVAL - Redis bulk -> Lua type conversion} + client.eval("local foo = redis.call('get','bulk reply key'); return {type(foo),foo}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("string", res[0], name); + assert.strictEqual("bulk reply value", res[1], name); + }); + }); + + // test {EVAL - Redis multi bulk -> Lua type conversion} + client.multi() + .del("mylist") + .rpush("mylist", "a") + .rpush("mylist", "b") + .rpush("mylist", "c") + .exec(function (err, replies) { + if (err) throw err; + client.eval("local foo = redis.call('lrange','mylist',0,-1); return {type(foo),foo[1],foo[2],foo[3],# foo}", 0, function (err, res) { + assert.strictEqual(5, res.length, name); + assert.strictEqual("table", res[0], name); + assert.strictEqual("a", res[1], name); + assert.strictEqual("b", res[2], name); + assert.strictEqual("c", res[3], name); + assert.strictEqual(3, res[4], name); + }); + }); + // test {EVAL - Redis status reply -> Lua type conversion} + client.eval("local foo = redis.call('set','mykey','myval'); return {type(foo),foo['ok']}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("table", res[0], name); + assert.strictEqual("OK", res[1], name); + }); + // test {EVAL - Redis error reply -> Lua type conversion} + client.set("error reply key", "error reply value", function (err, res) { + if (err) throw err; + client.eval("local foo = redis.pcall('incr','error reply key'); return {type(foo),foo['err']}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("table", res[0], name); + assert.strictEqual("ERR value is not an integer or out of range", res[1], name); + }); + }); + // test {EVAL - Redis nil bulk reply -> Lua type conversion} + client.del("nil reply key", function (err, res) { + if (err) throw err; + client.eval("local foo = redis.call('get','nil reply key'); return {type(foo),foo == false}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("boolean", res[0], name); + assert.strictEqual(1, res[1], name); + next(name); + }); + }); + } else { + console.log("Skipping " + name + " because server version isn't new enough."); + next(name); + } +}; + +tests.WATCH_MULTI = function () { + var name = 'WATCH_MULTI', multi; + + if (client.server_info.versions[0] >= 2 && client.server_info.versions[1] >= 1) { + client.watch(name); + client.incr(name); + multi = client.multi(); + multi.incr(name); + multi.exec(last(name, require_null(name))); + } else { + console.log("Skipping " + name + " because server version isn't new enough."); + next(name); + } +}; + +tests.detect_buffers = function () { + var name = "detect_buffers", detect_client = redis.createClient(null, null, {detect_buffers: true}); + + detect_client.on("ready", function () { + // single Buffer or String + detect_client.set("string key 1", "string value"); + detect_client.get("string key 1", require_string("string value", name)); + detect_client.get(new Buffer("string key 1"), function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual(true, Buffer.isBuffer(reply), name); + assert.strictEqual("", reply.inspect(), name); + }); + + detect_client.hmset("hash key 2", "key 1", "val 1", "key 2", "val 2"); + // array of Buffers or Strings + detect_client.hmget("hash key 2", "key 1", "key 2", function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual(true, Array.isArray(reply), name); + assert.strictEqual(2, reply.length, name); + assert.strictEqual("val 1", reply[0], name); + assert.strictEqual("val 2", reply[1], name); + }); + detect_client.hmget(new Buffer("hash key 2"), "key 1", "key 2", function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual(true, Array.isArray(reply)); + assert.strictEqual(2, reply.length, name); + assert.strictEqual(true, Buffer.isBuffer(reply[0])); + assert.strictEqual(true, Buffer.isBuffer(reply[1])); + assert.strictEqual("", reply[0].inspect(), name); + assert.strictEqual("", reply[1].inspect(), name); + }); + + // Object of Buffers or Strings + detect_client.hgetall("hash key 2", function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual("object", typeof reply, name); + assert.strictEqual(2, Object.keys(reply).length, name); + assert.strictEqual("val 1", reply["key 1"], name); + assert.strictEqual("val 2", reply["key 2"], name); + }); + detect_client.hgetall(new Buffer("hash key 2"), function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual("object", typeof reply, name); + assert.strictEqual(2, Object.keys(reply).length, name); + assert.strictEqual(true, Buffer.isBuffer(reply["key 1"])); + assert.strictEqual(true, Buffer.isBuffer(reply["key 2"])); + assert.strictEqual("", reply["key 1"].inspect(), name); + assert.strictEqual("", reply["key 2"].inspect(), name); + }); + + detect_client.quit(function (err, res) { + next(name); + }); + }); +}; + +tests.socket_nodelay = function () { + var name = "socket_nodelay", c1, c2, c3, ready_count = 0, quit_count = 0; + + c1 = redis.createClient(null, null, {socket_nodelay: true}); + c2 = redis.createClient(null, null, {socket_nodelay: false}); + c3 = redis.createClient(null, null); + + function quit_check() { + quit_count++; + + if (quit_count === 3) { + next(name); + } + } + + function run() { + assert.strictEqual(true, c1.options.socket_nodelay, name); + assert.strictEqual(false, c2.options.socket_nodelay, name); + assert.strictEqual(true, c3.options.socket_nodelay, name); + + c1.set(["set key 1", "set val"], require_string("OK", name)); + c1.set(["set key 2", "set val"], require_string("OK", name)); + c1.get(["set key 1"], require_string("set val", name)); + c1.get(["set key 2"], require_string("set val", name)); + + c2.set(["set key 3", "set val"], require_string("OK", name)); + c2.set(["set key 4", "set val"], require_string("OK", name)); + c2.get(["set key 3"], require_string("set val", name)); + c2.get(["set key 4"], require_string("set val", name)); + + c3.set(["set key 5", "set val"], require_string("OK", name)); + c3.set(["set key 6", "set val"], require_string("OK", name)); + c3.get(["set key 5"], require_string("set val", name)); + c3.get(["set key 6"], require_string("set val", name)); + + c1.quit(quit_check); + c2.quit(quit_check); + c3.quit(quit_check); + } + + function ready_check() { + ready_count++; + if (ready_count === 3) { + run(); + } + } + + c1.on("ready", ready_check); + c2.on("ready", ready_check); + c3.on("ready", ready_check); +}; + +tests.reconnect = function () { + var name = "reconnect"; + + client.set("recon 1", "one"); + client.set("recon 2", "two", function (err, res) { + // Do not do this in normal programs. This is to simulate the server closing on us. + // For orderly shutdown in normal programs, do client.quit() + client.stream.destroy(); + }); + + client.on("reconnecting", function on_recon(params) { + client.on("connect", function on_connect() { + client.select(test_db_num, require_string("OK", name)); + client.get("recon 1", require_string("one", name)); + client.get("recon 1", require_string("one", name)); + client.get("recon 2", require_string("two", name)); + client.get("recon 2", require_string("two", name)); + client.removeListener("connect", on_connect); + client.removeListener("reconnecting", on_recon); + next(name); + }); + }); +}; + +tests.idle = function () { + var name = "idle"; + + client.on("idle", function on_idle() { + client.removeListener("idle", on_idle); + next(name); + }); + + client.set("idle", "test"); +}; + +tests.HSET = function () { + var key = "test hash", + field1 = new Buffer("0123456789"), + value1 = new Buffer("abcdefghij"), + field2 = new Buffer(0), + value2 = new Buffer(0), + name = "HSET"; + + client.HSET(key, field1, value1, require_number(1, name)); + client.HGET(key, field1, require_string(value1.toString(), name)); + + // Empty value + client.HSET(key, field1, value2, require_number(0, name)); + client.HGET([key, field1], require_string("", name)); + + // Empty key, empty value + client.HSET([key, field2, value1], require_number(1, name)); + client.HSET(key, field2, value2, last(name, require_number(0, name))); +}; + +tests.HLEN = function () { + var key = "test hash", + field1 = new Buffer("0123456789"), + value1 = new Buffer("abcdefghij"), + field2 = new Buffer(0), + value2 = new Buffer(0), + name = "HSET", + timeout = 1000; + + client.HSET(key, field1, value1, function (err, results) { + client.HLEN(key, function (err, len) { + assert.ok(2 === +len); + next(name); + }); + }); +} + +tests.HMSET_BUFFER_AND_ARRAY = function () { + // Saving a buffer and an array to the same key should not error + var key = "test hash", + field1 = "buffer", + value1 = new Buffer("abcdefghij"), + field2 = "array", + value2 = ["array contents"], + name = "HSET"; + + client.HMSET(key, field1, value1, field2, value2, last(name, require_string("OK", name))); +}; + +// TODO - add test for HMSET with optional callbacks + +tests.HMGET = function () { + var key1 = "test hash 1", key2 = "test hash 2", name = "HMGET"; + + // redis-like hmset syntax + client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value", require_string("OK", name)); + + // fancy hmset syntax + client.HMSET(key2, { + "0123456789": "abcdefghij", + "some manner of key": "a type of value" + }, require_string("OK", name)); + + client.HMGET(key1, "0123456789", "some manner of key", function (err, reply) { + assert.strictEqual("abcdefghij", reply[0].toString(), name); + assert.strictEqual("a type of value", reply[1].toString(), name); + }); + + client.HMGET(key2, "0123456789", "some manner of key", function (err, reply) { + assert.strictEqual("abcdefghij", reply[0].toString(), name); + assert.strictEqual("a type of value", reply[1].toString(), name); + }); + + client.HMGET(key1, ["0123456789"], function (err, reply) { + assert.strictEqual("abcdefghij", reply[0], name); + }); + + client.HMGET(key1, ["0123456789", "some manner of key"], function (err, reply) { + assert.strictEqual("abcdefghij", reply[0], name); + assert.strictEqual("a type of value", reply[1], name); + }); + + client.HMGET(key1, "missing thing", "another missing thing", function (err, reply) { + assert.strictEqual(null, reply[0], name); + assert.strictEqual(null, reply[1], name); + next(name); + }); +}; + +tests.HINCRBY = function () { + var name = "HINCRBY"; + client.hset("hash incr", "value", 10, require_number(1, name)); + client.HINCRBY("hash incr", "value", 1, require_number(11, name)); + client.HINCRBY("hash incr", "value 2", 1, last(name, require_number(1, name))); +}; + +tests.SUBSCRIBE = function () { + var client1 = client, msg_count = 0, name = "SUBSCRIBE"; + + client1.on("subscribe", function (channel, count) { + if (channel === "chan1") { + client2.publish("chan1", "message 1", require_number(1, name)); + client2.publish("chan2", "message 2", require_number(1, name)); + client2.publish("chan1", "message 3", require_number(1, name)); + } + }); + + client1.on("unsubscribe", function (channel, count) { + if (count === 0) { + // make sure this connection can go into and out of pub/sub mode + client1.incr("did a thing", last(name, require_number(2, name))); + } + }); + + client1.on("message", function (channel, message) { + msg_count += 1; + assert.strictEqual("message " + msg_count, message.toString()); + if (msg_count === 3) { + client1.unsubscribe("chan1", "chan2"); + } + }); + + client1.set("did a thing", 1, require_string("OK", name)); + client1.subscribe("chan1", "chan2", function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual("chan1", results.toString(), name); + }); +}; + +tests.SUB_UNSUB_SUB = function () { + var name = "SUB_UNSUB_SUB"; + client3.subscribe('chan3'); + client3.unsubscribe('chan3'); + client3.subscribe('chan3', function (err, results) { + assert.strictEqual(null, err, "unexpected error: " + err); + client2.publish('chan3', 'foo'); + }); + client3.on('message', function (channel, message) { + assert.strictEqual(channel, 'chan3'); + assert.strictEqual(message, 'foo'); + next(name); + }); +}; + +tests.SUBSCRIBE_QUIT = function () { + var name = "SUBSCRIBE_QUIT"; + client3.on("end", function () { + next(name); + }); + client3.on("subscribe", function (channel, count) { + client3.quit(); + }); + client3.subscribe("chan3"); +}; + +tests.SUBSCRIBE_CLOSE_RESUBSCRIBE = function () { + var name = "SUBSCRIBE_CLOSE_RESUBSCRIBE"; + var c1 = redis.createClient(); + var c2 = redis.createClient(); + var count = 0; + + /* Create two clients. c1 subscribes to two channels, c2 will publish to them. + c2 publishes the first message. + c1 gets the message and drops its connection. It must resubscribe itself. + When it resubscribes, c2 publishes the second message, on the same channel + c1 gets the message and drops its connection. It must resubscribe itself, again. + When it resubscribes, c2 publishes the third message, on the second channel + c1 gets the message and drops its connection. When it reconnects, the test ends. + */ + + c1.on("message", function(channel, message) { + if (channel === "chan1") { + assert.strictEqual(message, "hi on channel 1"); + c1.stream.end(); + + } else if (channel === "chan2") { + assert.strictEqual(message, "hi on channel 2"); + c1.stream.end(); + + } else { + c1.quit(); + c2.quit(); + assert.fail("test failed"); + } + }) + + c1.subscribe("chan1", "chan2"); + + c2.once("ready", function() { + console.log("c2 is ready"); + c1.on("ready", function(err, results) { + console.log("c1 is ready", count); + + count++; + if (count == 1) { + c2.publish("chan1", "hi on channel 1"); + return; + + } else if (count == 2) { + c2.publish("chan2", "hi on channel 2"); + + } else { + c1.quit(function() { + c2.quit(function() { + next(name); + }); + }); + } + }); + + c2.publish("chan1", "hi on channel 1"); + + }); +}; + +tests.EXISTS = function () { + var name = "EXISTS"; + client.del("foo", "foo2", require_number_any(name)); + client.set("foo", "bar", require_string("OK", name)); + client.EXISTS("foo", require_number(1, name)); + client.EXISTS("foo2", last(name, require_number(0, name))); +}; + +tests.DEL = function () { + var name = "DEL"; + client.DEL("delkey", require_number_any(name)); + client.set("delkey", "delvalue", require_string("OK", name)); + client.DEL("delkey", require_number(1, name)); + client.exists("delkey", require_number(0, name)); + client.DEL("delkey", require_number(0, name)); + client.mset("delkey", "delvalue", "delkey2", "delvalue2", require_string("OK", name)); + client.DEL("delkey", "delkey2", last(name, require_number(2, name))); +}; + +tests.TYPE = function () { + var name = "TYPE"; + client.set(["string key", "should be a string"], require_string("OK", name)); + client.rpush(["list key", "should be a list"], require_number_pos(name)); + client.sadd(["set key", "should be a set"], require_number_any(name)); + client.zadd(["zset key", "10.0", "should be a zset"], require_number_any(name)); + client.hset(["hash key", "hashtest", "should be a hash"], require_number_any(0, name)); + + client.TYPE(["string key"], require_string("string", name)); + client.TYPE(["list key"], require_string("list", name)); + client.TYPE(["set key"], require_string("set", name)); + client.TYPE(["zset key"], require_string("zset", name)); + client.TYPE("not here yet", require_string("none", name)); + client.TYPE(["hash key"], last(name, require_string("hash", name))); +}; + +tests.KEYS = function () { + var name = "KEYS"; + client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], require_string("OK", name)); + client.KEYS(["test keys*"], function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(2, results.length, name); + assert.strictEqual("test keys 1", results[0].toString(), name); + assert.strictEqual("test keys 2", results[1].toString(), name); + next(name); + }); +}; + +tests.MULTIBULK_ZERO_LENGTH = function () { + var name = "MULTIBULK_ZERO_LENGTH"; + client.KEYS(['users:*'], function (err, results) { + assert.strictEqual(null, err, 'error on empty multibulk reply'); + assert.strictEqual(true, is_empty_array(results), "not an empty array"); + next(name); + }); +}; + +tests.RANDOMKEY = function () { + var name = "RANDOMKEY"; + client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], require_string("OK", name)); + client.RANDOMKEY([], function (err, results) { + assert.strictEqual(null, err, name + " result sent back unexpected error: " + err); + assert.strictEqual(true, /\w+/.test(results), name); + next(name); + }); +}; + +tests.RENAME = function () { + var name = "RENAME"; + client.set(['foo', 'bar'], require_string("OK", name)); + client.RENAME(["foo", "new foo"], require_string("OK", name)); + client.exists(["foo"], require_number(0, name)); + client.exists(["new foo"], last(name, require_number(1, name))); +}; + +tests.RENAMENX = function () { + var name = "RENAMENX"; + client.set(['foo', 'bar'], require_string("OK", name)); + client.set(['foo2', 'bar2'], require_string("OK", name)); + client.RENAMENX(["foo", "foo2"], require_number(0, name)); + client.exists(["foo"], require_number(1, name)); + client.exists(["foo2"], require_number(1, name)); + client.del(["foo2"], require_number(1, name)); + client.RENAMENX(["foo", "foo2"], require_number(1, name)); + client.exists(["foo"], require_number(0, name)); + client.exists(["foo2"], last(name, require_number(1, name))); +}; + +tests.DBSIZE = function () { + var name = "DBSIZE"; + client.set(['foo', 'bar'], require_string("OK", name)); + client.DBSIZE([], last(name, require_number_pos("DBSIZE"))); +}; + +tests.GET = function () { + var name = "GET"; + client.set(["get key", "get val"], require_string("OK", name)); + client.GET(["get key"], last(name, require_string("get val", name))); +}; + +tests.SET = function () { + var name = "SET"; + client.SET(["set key", "set val"], require_string("OK", name)); + client.get(["set key"], last(name, require_string("set val", name))); +}; + +tests.GETSET = function () { + var name = "GETSET"; + client.set(["getset key", "getset val"], require_string("OK", name)); + client.GETSET(["getset key", "new getset val"], require_string("getset val", name)); + client.get(["getset key"], last(name, require_string("new getset val", name))); +}; + +tests.MGET = function () { + var name = "MGET"; + client.mset(["mget keys 1", "mget val 1", "mget keys 2", "mget val 2", "mget keys 3", "mget val 3"], require_string("OK", name)); + client.MGET("mget keys 1", "mget keys 2", "mget keys 3", function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(3, results.length, name); + assert.strictEqual("mget val 1", results[0].toString(), name); + assert.strictEqual("mget val 2", results[1].toString(), name); + assert.strictEqual("mget val 3", results[2].toString(), name); + }); + client.MGET(["mget keys 1", "mget keys 2", "mget keys 3"], function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(3, results.length, name); + assert.strictEqual("mget val 1", results[0].toString(), name); + assert.strictEqual("mget val 2", results[1].toString(), name); + assert.strictEqual("mget val 3", results[2].toString(), name); + }); + client.MGET(["mget keys 1", "some random shit", "mget keys 2", "mget keys 3"], function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(4, results.length, name); + assert.strictEqual("mget val 1", results[0].toString(), name); + assert.strictEqual(null, results[1], name); + assert.strictEqual("mget val 2", results[2].toString(), name); + assert.strictEqual("mget val 3", results[3].toString(), name); + next(name); + }); +}; + +tests.SETNX = function () { + var name = "SETNX"; + client.set(["setnx key", "setnx value"], require_string("OK", name)); + client.SETNX(["setnx key", "new setnx value"], require_number(0, name)); + client.del(["setnx key"], require_number(1, name)); + client.exists(["setnx key"], require_number(0, name)); + client.SETNX(["setnx key", "new setnx value"], require_number(1, name)); + client.exists(["setnx key"], last(name, require_number(1, name))); +}; + +tests.SETEX = function () { + var name = "SETEX"; + client.SETEX(["setex key", "100", "setex val"], require_string("OK", name)); + client.exists(["setex key"], require_number(1, name)); + client.ttl(["setex key"], last(name, require_number_pos(name))); +}; + +tests.MSETNX = function () { + var name = "MSETNX"; + client.mset(["mset1", "val1", "mset2", "val2", "mset3", "val3"], require_string("OK", name)); + client.MSETNX(["mset3", "val3", "mset4", "val4"], require_number(0, name)); + client.del(["mset3"], require_number(1, name)); + client.MSETNX(["mset3", "val3", "mset4", "val4"], require_number(1, name)); + client.exists(["mset3"], require_number(1, name)); + client.exists(["mset4"], last(name, require_number(1, name))); +}; + +tests.HGETALL = function () { + var name = "HGETALL"; + client.hmset(["hosts", "mjr", "1", "another", "23", "home", "1234"], require_string("OK", name)); + client.HGETALL(["hosts"], function (err, obj) { + assert.strictEqual(null, err, name + " result sent back unexpected error: " + err); + assert.strictEqual(3, Object.keys(obj).length, name); + assert.strictEqual("1", obj.mjr.toString(), name); + assert.strictEqual("23", obj.another.toString(), name); + assert.strictEqual("1234", obj.home.toString(), name); + next(name); + }); +}; + +tests.HGETALL_NULL = function () { + var name = "HGETALL_NULL"; + + client.hgetall("missing", function (err, obj) { + assert.strictEqual(null, err); + assert.strictEqual(null, obj); + next(name); + }); +}; + +tests.UTF8 = function () { + var name = "UTF8", + utf8_sample = "ಠ_ಠ"; + + client.set(["utf8test", utf8_sample], require_string("OK", name)); + client.get(["utf8test"], function (err, obj) { + assert.strictEqual(null, err); + assert.strictEqual(utf8_sample, obj); + next(name); + }); +}; + +// Set tests were adapted from Brian Hammond's redis-node-client.js, which has a comprehensive test suite + +tests.SADD = function () { + var name = "SADD"; + + client.del('set0'); + client.SADD('set0', 'member0', require_number(1, name)); + client.sadd('set0', 'member0', last(name, require_number(0, name))); +}; + +tests.SADD2 = function () { + var name = "SADD2"; + + client.del("set0"); + client.sadd("set0", ["member0", "member1", "member2"], require_number(3, name)); + client.smembers("set0", function (err, res) { + assert.strictEqual(res.length, 3); + assert.strictEqual(res[0], "member0"); + assert.strictEqual(res[1], "member1"); + assert.strictEqual(res[2], "member2"); + }); + client.SADD("set1", ["member0", "member1", "member2"], require_number(3, name)); + client.smembers("set1", function (err, res) { + assert.strictEqual(res.length, 3); + assert.strictEqual(res[0], "member0"); + assert.strictEqual(res[1], "member1"); + assert.strictEqual(res[2], "member2"); + next(name); + }); +}; + +tests.SISMEMBER = function () { + var name = "SISMEMBER"; + + client.del('set0'); + client.sadd('set0', 'member0', require_number(1, name)); + client.sismember('set0', 'member0', require_number(1, name)); + client.sismember('set0', 'member1', last(name, require_number(0, name))); +}; + +tests.SCARD = function () { + var name = "SCARD"; + + client.del('set0'); + client.sadd('set0', 'member0', require_number(1, name)); + client.scard('set0', require_number(1, name)); + client.sadd('set0', 'member1', require_number(1, name)); + client.scard('set0', last(name, require_number(2, name))); +}; + +tests.SREM = function () { + var name = "SREM"; + + client.del('set0'); + client.sadd('set0', 'member0', require_number(1, name)); + client.srem('set0', 'foobar', require_number(0, name)); + client.srem('set0', 'member0', require_number(1, name)); + client.scard('set0', last(name, require_number(0, name))); +}; + +tests.SPOP = function () { + var name = "SPOP"; + + client.del('zzz'); + client.sadd('zzz', 'member0', require_number(1, name)); + client.scard('zzz', require_number(1, name)); + + client.spop('zzz', function (err, value) { + if (err) { + assert.fail(err); + } + assert.equal(value, 'member0', name); + }); + + client.scard('zzz', last(name, require_number(0, name))); +}; + +tests.SDIFF = function () { + var name = "SDIFF"; + + client.del('foo'); + client.sadd('foo', 'x', require_number(1, name)); + client.sadd('foo', 'a', require_number(1, name)); + client.sadd('foo', 'b', require_number(1, name)); + client.sadd('foo', 'c', require_number(1, name)); + + client.sadd('bar', 'c', require_number(1, name)); + + client.sadd('baz', 'a', require_number(1, name)); + client.sadd('baz', 'd', require_number(1, name)); + + client.sdiff('foo', 'bar', 'baz', function (err, values) { + if (err) { + assert.fail(err, name); + } + values.sort(); + assert.equal(values.length, 2, name); + assert.equal(values[0], 'b', name); + assert.equal(values[1], 'x', name); + next(name); + }); +}; + +tests.SDIFFSTORE = function () { + var name = "SDIFFSTORE"; + + client.del('foo'); + client.del('bar'); + client.del('baz'); + client.del('quux'); + + client.sadd('foo', 'x', require_number(1, name)); + client.sadd('foo', 'a', require_number(1, name)); + client.sadd('foo', 'b', require_number(1, name)); + client.sadd('foo', 'c', require_number(1, name)); + + client.sadd('bar', 'c', require_number(1, name)); + + client.sadd('baz', 'a', require_number(1, name)); + client.sadd('baz', 'd', require_number(1, name)); + + // NB: SDIFFSTORE returns the number of elements in the dstkey + + client.sdiffstore('quux', 'foo', 'bar', 'baz', require_number(2, name)); + + client.smembers('quux', function (err, values) { + if (err) { + assert.fail(err, name); + } + var members = buffers_to_strings(values).sort(); + + assert.deepEqual(members, [ 'b', 'x' ], name); + next(name); + }); +}; + +tests.SMEMBERS = function () { + var name = "SMEMBERS"; + + client.del('foo'); + client.sadd('foo', 'x', require_number(1, name)); + + client.smembers('foo', function (err, members) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(members), [ 'x' ], name); + }); + + client.sadd('foo', 'y', require_number(1, name)); + + client.smembers('foo', function (err, values) { + if (err) { + assert.fail(err, name); + } + assert.equal(values.length, 2, name); + var members = buffers_to_strings(values).sort(); + + assert.deepEqual(members, [ 'x', 'y' ], name); + next(name); + }); +}; + +tests.SMOVE = function () { + var name = "SMOVE"; + + client.del('foo'); + client.del('bar'); + + client.sadd('foo', 'x', require_number(1, name)); + client.smove('foo', 'bar', 'x', require_number(1, name)); + client.sismember('foo', 'x', require_number(0, name)); + client.sismember('bar', 'x', require_number(1, name)); + client.smove('foo', 'bar', 'x', last(name, require_number(0, name))); +}; + +tests.SINTER = function () { + var name = "SINTER"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sinter('sa', 'sb', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 2, name); + assert.deepEqual(buffers_to_strings(intersection).sort(), [ 'b', 'c' ], name); + }); + + client.sinter('sb', 'sc', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 2, name); + assert.deepEqual(buffers_to_strings(intersection).sort(), [ 'c', 'd' ], name); + }); + + client.sinter('sa', 'sc', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 1, name); + assert.equal(intersection[0], 'c', name); + }); + + // 3-way + + client.sinter('sa', 'sb', 'sc', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 1, name); + assert.equal(intersection[0], 'c', name); + next(name); + }); +}; + +tests.SINTERSTORE = function () { + var name = "SINTERSTORE"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + client.del('foo'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sinterstore('foo', 'sa', 'sb', 'sc', require_number(1, name)); + + client.smembers('foo', function (err, members) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(members), [ 'c' ], name); + next(name); + }); +}; + +tests.SUNION = function () { + var name = "SUNION"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sunion('sa', 'sb', 'sc', function (err, union) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(union).sort(), ['a', 'b', 'c', 'd', 'e'], name); + next(name); + }); +}; + +tests.SUNIONSTORE = function () { + var name = "SUNIONSTORE"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + client.del('foo'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sunionstore('foo', 'sa', 'sb', 'sc', function (err, cardinality) { + if (err) { + assert.fail(err, name); + } + assert.equal(cardinality, 5, name); + }); + + client.smembers('foo', function (err, members) { + if (err) { + assert.fail(err, name); + } + assert.equal(members.length, 5, name); + assert.deepEqual(buffers_to_strings(members).sort(), ['a', 'b', 'c', 'd', 'e'], name); + next(name); + }); +}; + +// SORT test adapted from Brian Hammond's redis-node-client.js, which has a comprehensive test suite + +tests.SORT = function () { + var name = "SORT"; + + client.del('y'); + client.del('x'); + + client.rpush('y', 'd', require_number(1, name)); + client.rpush('y', 'b', require_number(2, name)); + client.rpush('y', 'a', require_number(3, name)); + client.rpush('y', 'c', require_number(4, name)); + + client.rpush('x', '3', require_number(1, name)); + client.rpush('x', '9', require_number(2, name)); + client.rpush('x', '2', require_number(3, name)); + client.rpush('x', '4', require_number(4, name)); + + client.set('w3', '4', require_string("OK", name)); + client.set('w9', '5', require_string("OK", name)); + client.set('w2', '12', require_string("OK", name)); + client.set('w4', '6', require_string("OK", name)); + + client.set('o2', 'buz', require_string("OK", name)); + client.set('o3', 'foo', require_string("OK", name)); + client.set('o4', 'baz', require_string("OK", name)); + client.set('o9', 'bar', require_string("OK", name)); + + client.set('p2', 'qux', require_string("OK", name)); + client.set('p3', 'bux', require_string("OK", name)); + client.set('p4', 'lux', require_string("OK", name)); + client.set('p9', 'tux', require_string("OK", name)); + + // Now the data has been setup, we can test. + + // But first, test basic sorting. + + // y = [ d b a c ] + // sort y ascending = [ a b c d ] + // sort y descending = [ d c b a ] + + client.sort('y', 'asc', 'alpha', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['a', 'b', 'c', 'd'], name); + }); + + client.sort('y', 'desc', 'alpha', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['d', 'c', 'b', 'a'], name); + }); + + // Now try sorting numbers in a list. + // x = [ 3, 9, 2, 4 ] + + client.sort('x', 'asc', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), [2, 3, 4, 9], name); + }); + + client.sort('x', 'desc', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), [9, 4, 3, 2], name); + }); + + // Try sorting with a 'by' pattern. + + client.sort('x', 'by', 'w*', 'asc', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), [3, 9, 4, 2], name); + }); + + // Try sorting with a 'by' pattern and 1 'get' pattern. + + client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['foo', 'bar', 'baz', 'buz'], name); + }); + + // Try sorting with a 'by' pattern and 2 'get' patterns. + + client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', 'get', 'p*', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['foo', 'bux', 'bar', 'tux', 'baz', 'lux', 'buz', 'qux'], name); + }); + + // Try sorting with a 'by' pattern and 2 'get' patterns. + // Instead of getting back the sorted set/list, store the values to a list. + // Then check that the values are there in the expected order. + + client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', 'get', 'p*', 'store', 'bacon', function (err) { + if (err) { + assert.fail(err, name); + } + }); + + client.lrange('bacon', 0, -1, function (err, values) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(values), ['foo', 'bux', 'bar', 'tux', 'baz', 'lux', 'buz', 'qux'], name); + next(name); + }); + + // TODO - sort by hash value +}; + +tests.MONITOR = function () { + var name = "MONITOR", responses = [], monitor_client; + + monitor_client = redis.createClient(); + monitor_client.monitor(function (err, res) { + client.mget("some", "keys", "foo", "bar"); + client.set("json", JSON.stringify({ + foo: "123", + bar: "sdflkdfsjk", + another: false + })); + }); + monitor_client.on("monitor", function (time, args) { + // skip monitor command for Redis <= 2.4.16 + if (args[0] === "monitor") return; + + responses.push(args); + if (responses.length === 2) { + assert.strictEqual(5, responses[0].length); + assert.strictEqual("mget", responses[0][0]); + assert.strictEqual("some", responses[0][1]); + assert.strictEqual("keys", responses[0][2]); + assert.strictEqual("foo", responses[0][3]); + assert.strictEqual("bar", responses[0][4]); + assert.strictEqual(3, responses[1].length); + assert.strictEqual("set", responses[1][0]); + assert.strictEqual("json", responses[1][1]); + assert.strictEqual('{"foo":"123","bar":"sdflkdfsjk","another":false}', responses[1][2]); + monitor_client.quit(function (err, res) { + next(name); + }); + } + }); +}; + +tests.BLPOP = function () { + var name = "BLPOP"; + + client.rpush("blocking list", "initial value", function (err, res) { + client2.BLPOP("blocking list", 0, function (err, res) { + assert.strictEqual("blocking list", res[0].toString()); + assert.strictEqual("initial value", res[1].toString()); + + client.rpush("blocking list", "wait for this value"); + }); + client2.BLPOP("blocking list", 0, function (err, res) { + assert.strictEqual("blocking list", res[0].toString()); + assert.strictEqual("wait for this value", res[1].toString()); + next(name); + }); + }); +}; + +tests.BLPOP_TIMEOUT = function () { + var name = "BLPOP_TIMEOUT"; + + // try to BLPOP the list again, which should be empty. This should timeout and return null. + client2.BLPOP("blocking list", 1, function (err, res) { + if (err) { + throw err; + } + + assert.strictEqual(res, null); + next(name); + }); +}; + +tests.EXPIRE = function () { + var name = "EXPIRE"; + client.set(['expiry key', 'bar'], require_string("OK", name)); + client.EXPIRE(["expiry key", "1"], require_number_pos(name)); + setTimeout(function () { + client.exists(["expiry key"], last(name, require_number(0, name))); + }, 2000); +}; + +tests.TTL = function () { + var name = "TTL"; + client.set(["ttl key", "ttl val"], require_string("OK", name)); + client.expire(["ttl key", "100"], require_number_pos(name)); + setTimeout(function () { + client.TTL(["ttl key"], last(name, require_number_pos(0, name))); + }, 500); +}; + +tests.OPTIONAL_CALLBACK = function () { + var name = "OPTIONAL_CALLBACK"; + client.del("op_cb1"); + client.set("op_cb1", "x"); + client.get("op_cb1", last(name, require_string("x", name))); +}; + +tests.OPTIONAL_CALLBACK_UNDEFINED = function () { + var name = "OPTIONAL_CALLBACK_UNDEFINED"; + client.del("op_cb2"); + client.set("op_cb2", "y", undefined); + client.get("op_cb2", last(name, require_string("y", name))); +}; + +tests.HMSET_THROWS_ON_NON_STRINGS = function () { + var name = "HMSET_THROWS_ON_NON_STRINGS"; + var hash = name; + var data = { "a": [ "this is not a string" ] }; + + client.hmset(hash, data, cb); + function cb(e, r) { + assert(e); // should be an error! + } + + // alternative way it throws + function thrower() { + client.hmset(hash, data); + } + assert.throws(thrower); + next(name); +}; + +tests.ENABLE_OFFLINE_QUEUE_TRUE = function () { + var name = "ENABLE_OFFLINE_QUEUE_TRUE"; + var cli = redis.createClient(9999, null, { + max_attempts: 1 + // default :) + // enable_offline_queue: true + }); + cli.on('error', function(e) { + // ignore, b/c expecting a "can't connect" error + }); + return setTimeout(function() { + cli.set(name, name, function(err, result) { + assert.ifError(err); + }); + + return setTimeout(function(){ + assert.strictEqual(cli.offline_queue.length, 1); + return next(name); + }, 25); + }, 50); +}; + +tests.ENABLE_OFFLINE_QUEUE_FALSE = function () { + var name = "ENABLE_OFFLINE_QUEUE_FALSE"; + var cli = redis.createClient(9999, null, { + max_attempts: 1, + enable_offline_queue: false + }); + cli.on('error', function() { + // ignore, see above + }); + assert.throws(function () { + cli.set(name, name) + }) + assert.doesNotThrow(function () { + cli.set(name, name, function (err) { + // should callback with an error + assert.ok(err); + setTimeout(function () { + next(name); + }, 50); + }); + }); +}; + +// TODO - need a better way to test auth, maybe auto-config a local Redis server or something. +// Yes, this is the real password. Please be nice, thanks. +tests.auth = function () { + var name = "AUTH", client4, ready_count = 0; + + client4 = redis.createClient(9006, "filefish.redistogo.com"); + client4.auth("664b1b6aaf134e1ec281945a8de702a9", function (err, res) { + assert.strictEqual(null, err, name); + assert.strictEqual("OK", res.toString(), name); + }); + + // test auth, then kill the connection so it'll auto-reconnect and auto-re-auth + client4.on("ready", function () { + ready_count++; + if (ready_count === 1) { + client4.stream.destroy(); + } else { + client4.quit(function (err, res) { + next(name); + }); + } + }); +}; + +all_tests = Object.keys(tests); +all_start = new Date(); +test_count = 0; + +run_next_test = function run_next_test() { + var test_name = all_tests.shift(); + if (typeof tests[test_name] === "function") { + util.print('- \x1b[1m' + test_name.toLowerCase() + '\x1b[0m:'); + cur_start = new Date(); + test_count += 1; + tests[test_name](); + } else { + console.log('\n completed \x1b[32m%d\x1b[0m tests in \x1b[33m%d\x1b[0m ms\n', test_count, new Date() - all_start); + client.quit(); + client2.quit(); + } +}; + +client.once("ready", function start_tests() { + console.log("Connected to " + client.host + ":" + client.port + ", Redis server version " + client.server_info.redis_version + "\n"); + console.log("Using reply parser " + client.reply_parser.name); + + run_next_test(); + + connected = true; +}); + +client.on('end', function () { + ended = true; +}); + +// Exit immediately on connection failure, which triggers "exit", below, which fails the test +client.on("error", function (err) { + console.error("client: " + err.stack); + process.exit(); +}); +client2.on("error", function (err) { + console.error("client2: " + err.stack); + process.exit(); +}); +client3.on("error", function (err) { + console.error("client3: " + err.stack); + process.exit(); +}); +client.on("reconnecting", function (params) { + console.log("reconnecting: " + util.inspect(params)); +}); + +process.on('uncaughtException', function (err) { + console.error("Uncaught exception: " + err.stack); + process.exit(1); +}); + +process.on('exit', function (code) { + assert.equal(true, connected); + assert.equal(true, ended); +}); diff --git a/node_modules/socket.io/node_modules/socket.io-client/.npmignore b/node_modules/socket.io/node_modules/socket.io-client/.npmignore new file mode 100644 index 00000000..c27cb503 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/.npmignore @@ -0,0 +1,2 @@ +test/node_modules +support diff --git a/node_modules/socket.io/node_modules/socket.io-client/History.md b/node_modules/socket.io/node_modules/socket.io-client/History.md new file mode 100644 index 00000000..0867b2f3 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/History.md @@ -0,0 +1,237 @@ + +0.9.16 / 2013-06-06 +=================== + + * transports: fix escaping for tests + +0.9.15 / 2013-06-06 +=================== + + * transports: added unescaping for escaped htmlfile + * skipped 12-14 to match socket.io server version + +0.9.11 / 2012-11-02 +=================== + + * Enable use of 'xhr' transport in Node.js + * Fix the problem with disconnecting xhr-polling users + * Add should to devDependencies + * Prefer XmlHttpRequest if CORS is available + * Make client compatible with AMD loaders. + +0.9.10 / 2012-08-10 +=================== + + * fix removeAllListeners to behave as expected. + * set withCredentials to true only if xdomain. + * socket: disable disconnect on unload by default. + +0.9.9 / 2012-08-01 +================== + + * socket: fixed disconnect xhr url and made it actually sync + * *: bump xmlhttprequest dep + +0.9.8 / 2012-07-24 +================== + + * Fixed build. + +0.9.7 / 2012-07-24 +================== + + * iOS websocket crash fix. + * Fixed potential `open` collision. + * Fixed disconnectSync. + +0.9.6 / 2012-04-17 +================== + + * Don't position the jsonp form off the screen (android fix). + +0.9.5 / 2012-04-05 +================== + + * Bumped version. + +0.9.4 / 2012-04-01 +================== + + * Fixes polling loop upon reconnect advice (fixes #438). + +0.9.3 / 2012-03-28 +================== + + * Fix XHR.check, which was throwing an error transparently and causing non-IE browsers to fall back to JSONP [mikito] + * Fixed forced disconnect on window close [zzzaaa] + +0.9.2 / 2012-03-13 +================== + + * Transport order set by "options" [zzzaaa] + +0.9.1-1 / 2012-03-02 +==================== + + * Fixed active-x-obfuscator NPM dependency. + +0.9.1 / 2012-03-02 +================== + + * Misc corrections. + * Added warning within Firefox about webworker test in test runner. + * Update ws dependency [einaros] + * Implemented client side heartbeat checks. [felixge] + * Improved Firewall support with ActiveX obfuscation. [felixge] + * Fixed error handling during connection process. [Outsideris] + +0.9.0 / 2012-02-26 +================== + + * Added DS_Store to gitignore. + * Updated depedencies. + * Bumped uglify + * Tweaking code so it doesn't throw an exception when used inside a WebWorker in Firefox + * Do not rely on Array.prototype.indexOf as it breaks with pages that use the Prototype.js library. + * Windows support landed + * Use @einaros ws module instead of the old crap one + * Fix for broken closeTimeout and 'IE + xhr' goes into infinite loop on disconnection + * Disabled reconnection on error if reconnect option is set to false + * Set withCredentials to true before xhr to fix authentication + * Clears the timeout from reconnection attempt when there is a successful or failed reconnection. + This fixes the issue of setTimeout's carrying over from previous reconnection + and changing (skipping) values of self.reconnectionDelay in the newer reconnection. + * Removed decoding of parameters when chunking the query string. + This was used later on to construct the url to post to the socket.io server + for connection and if we're adding custom parameters of our own to this url + (for example for OAuth authentication) they were being sent decoded, which is wrong. + +0.8.7 / 2011-11-05 +================== + + * Bumped client + +0.8.6 / 2011-10-27 +================== + + * Added WebWorker support. + * Fixed swfobject and web_socket.js to not assume window. + * Fixed CORS detection for webworker. + * Fix `defer` for webkit in a webworker. + * Fixed io.util.request to not rely on window. + * FIxed; use global instead of window and dont rely on document. + * Fixed; JSON-P handshake if CORS is not available. + * Made underlying Transport disconnection trigger immediate socket.io disconnect. + * Fixed warning when compressing with Google Closure Compiler. + * Fixed builder's uglify utf-8 support. + * Added workaround for loading indicator in FF jsonp-polling. [3rd-Eden] + * Fixed host discovery lookup. [holic] + * Fixed close timeout when disconnected/reconnecting. [jscharlach] + * Fixed jsonp-polling feature detection. + * Fixed jsonp-polling client POSTing of \n. + * Fixed test runner on IE6/7 + +0.8.5 / 2011-10-07 +================== + + * Bumped client + +0.8.4 / 2011-09-06 +================== + + * Corrected build + +0.8.3 / 2011-09-03 +================== + + * Fixed `\n` parsing for non-JSON packets. + * Fixed; make Socket.IO XHTML doctype compatible (fixes #460 from server) + * Fixed support for Node.JS running `socket.io-client`. + * Updated repository name in `package.json`. + * Added support for different policy file ports without having to port + forward 843 on the server side [3rd-Eden] + +0.8.2 / 2011-08-29 +================== + + * Fixed flashsocket detection. + +0.8.1 / 2011-08-29 +================== + + * Bump version. + +0.8.0 / 2011-08-28 +================== + + * Added MozWebSocket support (hybi-10 doesn't require API changes) [einaros]. + +0.7.11 / 2011-08-27 +=================== + + * Corrected previous release (missing build). + +0.7.10 / 2011-08-27 +=================== + + * Fix for failing fallback in websockets + +0.7.9 / 2011-08-12 +================== + + * Added check on `Socket#onConnect` to prevent double `connect` events on the main manager. + * Fixed socket namespace connect test. Remove broken alternative namespace connect test. + * Removed test handler for removed test. + * Bumped version to match `socket.io` server. + +0.7.5 / 2011-08-08 +================== + + * Added querystring support for `connect` [3rd-Eden] + * Added partial Node.JS transports support [3rd-Eden, josephg] + * Fixed builder test. + * Changed `util.inherit` to replicate Object.create / __proto__. + * Changed and cleaned up some acceptance tests. + * Fixed race condition with a test that could not be run multiple times. + * Added test for encoding a payload. + * Added the ability to override the transport to use in acceptance test [3rd-Eden] + * Fixed multiple connect packets [DanielBaulig] + * Fixed jsonp-polling over-buffering [3rd-Eden] + * Fixed ascii preservation in minified socket.io client [3rd-Eden] + * Fixed socket.io in situations where the page is not served through utf8. + * Fixed namespaces not reconnecting after disconnect [3rd-Eden] + * Fixed default port for secure connections. + +0.7.4 / 2011-07-12 +================== + + * Added `SocketNamespace#of` shortcut. [3rd-Eden] + * Fixed a IE payload decoding bug. [3rd-Eden] + * Honor document protocol, unless overriden. [dvv] + * Fixed new builder dependencies. [3rd-Eden] + +0.7.3 / 2011-06-30 +================== + + * Fixed; acks don't depend on arity. They're automatic for `.send` and + callback based for `.emit`. [dvv] + * Added support for sub-sockets authorization. [3rd-Eden] + * Added BC support for `new io.connect`. [fat] + * Fixed double `connect` events. [3rd-Eden] + * Fixed reconnection with jsonp-polling maintaining old sessionid. [franck34] + +0.7.2 / 2011-06-22 +================== + + * Added `noop` message type. + +0.7.1 / 2011-06-21 +================== + + * Bumped socket.io dependency version for acceptance tests. + +0.7.0 / 2011-06-21 +================== + + * http://socket.io/announcement.html + diff --git a/node_modules/socket.io/node_modules/socket.io-client/README.md b/node_modules/socket.io/node_modules/socket.io-client/README.md new file mode 100644 index 00000000..cdb7715a --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/README.md @@ -0,0 +1,246 @@ +socket.io +========= + +#### Sockets for the rest of us + +The `socket.io` client is basically a simple HTTP Socket interface implementation. +It looks similar to WebSocket while providing additional features and +leveraging other transports when WebSocket is not supported by the user's +browser. + +```js +var socket = io.connect('http://domain.com'); +socket.on('connect', function () { + // socket connected +}); +socket.on('custom event', function () { + // server emitted a custom event +}); +socket.on('disconnect', function () { + // socket disconnected +}); +socket.send('hi there'); +``` + +### Recipes + +#### Utilizing namespaces (ie: multiple sockets) + +If you want to namespace all the messages and events emitted to a particular +endpoint, simply specify it as part of the `connect` uri: + +```js +var chat = io.connect('http://localhost/chat'); +chat.on('connect', function () { + // chat socket connected +}); + +var news = io.connect('/news'); // io.connect auto-detects host +news.on('connect', function () { + // news socket connected +}); +``` + +#### Emitting custom events + +To ease with the creation of applications, you can emit custom events outside +of the global `message` event. + +```js +var socket = io.connect(); +socket.emit('server custom event', { my: 'data' }); +``` + +#### Forcing disconnection + +```js +var socket = io.connect(); +socket.on('connect', function () { + socket.disconnect(); +}); +``` + +### Documentation + +#### io#connect + +```js +io.connect(uri, [options]); +``` + +##### Options: + +- *resource* + + socket.io + + The resource is what allows the `socket.io` server to identify incoming connections by `socket.io` clients. In other words, any HTTP server can implement socket.io and still serve other normal, non-realtime HTTP requests. + +- *transports* + +```js +['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling', 'jsonp-polling'] +``` + + A list of the transports to attempt to utilize (in order of preference). + +- *'connect timeout'* + +```js +5000 +``` + + The amount of milliseconds a transport has to create a connection before we consider it timed out. + +- *'try multiple transports'* + +```js +true +``` + + A boolean indicating if we should try other transports when the connectTimeout occurs. + +- *reconnect* + +```js +true +``` + + A boolean indicating if we should automatically reconnect if a connection is disconnected. + +- *'reconnection delay'* + +```js +500 +``` + + The amount of milliseconds before we try to connect to the server again. We are using a exponential back off algorithm for the following reconnections, on each reconnect attempt this value will get multiplied (500 > 1000 > 2000 > 4000 > 8000). + + +- *'max reconnection attempts'* + +```js +10 +``` + + The amount of attempts should we make using the current transport to connect to the server? After this we will do one final attempt, and re-try with all enabled transport methods before we give up. + +##### Properties: + +- *options* + + The passed in options combined with the defaults. + +- *connected* + + Whether the socket is connected or not. + +- *connecting* + + Whether the socket is connecting or not. + +- *reconnecting* + + Whether we are reconnecting or not. + +- *transport* + + The transport instance. + +##### Methods: + +- *connect(λ)* + + Establishes a connection. If λ is supplied as argument, it will be called once the connection is established. + +- *send(message)* + + A string of data to send. + +- *disconnect* + + Closes the connection. + +- *on(event, λ)* + + Adds a listener for the event *event*. + +- *once(event, λ)* + + Adds a one time listener for the event *event*. The listener is removed after the first time the event is fired. + +- *removeListener(event, λ)* + + Removes the listener λ for the event *event*. + +##### Events: + +- *connect* + + Fired when the connection is established and the handshake successful. + +- *connecting(transport_type)* + + Fired when a connection is attempted, passing the transport name. + +- *connect_failed* + + Fired when the connection timeout occurs after the last connection attempt. + This only fires if the `connectTimeout` option is set. + If the `tryTransportsOnConnectTimeout` option is set, this only fires once all + possible transports have been tried. + +- *message(message)* + + Fired when a message arrives from the server + +- *close* + + Fired when the connection is closed. Be careful with using this event, as some transports will fire it even under temporary, expected disconnections (such as XHR-Polling). + +- *disconnect* + + Fired when the connection is considered disconnected. + +- *reconnect(transport_type,reconnectionAttempts)* + + Fired when the connection has been re-established. This only fires if the `reconnect` option is set. + +- *reconnecting(reconnectionDelay,reconnectionAttempts)* + + Fired when a reconnection is attempted, passing the next delay for the next reconnection. + +- *reconnect_failed* + + Fired when all reconnection attempts have failed and we where unsuccessful in reconnecting to the server. + +### Contributors + +Guillermo Rauch <guillermo@learnboost.com> + +Arnout Kazemier <info@3rd-eden.com> + +### License + +(The MIT License) + +Copyright (c) 2010 LearnBoost <dev@learnboost.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/socket.io/node_modules/socket.io-client/bin/builder.js b/node_modules/socket.io/node_modules/socket.io-client/bin/builder.js new file mode 100755 index 00000000..7383c75a --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/bin/builder.js @@ -0,0 +1,303 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var fs = require('fs') + , socket = require('../lib/io') + , uglify = require('uglify-js') + , activeXObfuscator = require('active-x-obfuscator'); + +/** + * License headers. + * + * @api private + */ + +var template = '/*! Socket.IO.%ext% build:' + socket.version + ', %type%. Copyright(c) 2011 LearnBoost MIT Licensed */\n' + , development = template.replace('%type%', 'development').replace('%ext%', 'js') + , production = template.replace('%type%', 'production').replace('%ext%', 'min.js'); + +/** + * If statements, these allows you to create serveride & client side compatible + * code using specially designed `if` statements that remove serverside + * designed code from the source files + * + * @api private + */ + +var starttagIF = '// if node' + , endtagIF = '// end node'; + +/** + * The modules that are required to create a base build of Socket.IO. + * + * @const + * @type {Array} + * @api private + */ + +var base = [ + 'io.js' + , 'util.js' + , 'events.js' + , 'json.js' + , 'parser.js' + , 'transport.js' + , 'socket.js' + , 'namespace.js' + ]; + +/** + * The available transports for Socket.IO. These are mapped as: + * + * - `key` the name of the transport + * - `value` the dependencies for the transport + * + * @const + * @type {Object} + * @api public + */ + +var baseTransports = { + 'websocket': ['transports/websocket.js'] + , 'flashsocket': [ + 'transports/websocket.js' + , 'transports/flashsocket.js' + , 'vendor/web-socket-js/swfobject.js' + , 'vendor/web-socket-js/web_socket.js' + ] + , 'htmlfile': ['transports/xhr.js', 'transports/htmlfile.js'] + /* FIXME: re-enable me once we have multi-part support + , 'xhr-multipart': ['transports/xhr.js', 'transports/xhr-multipart.js'] */ + , 'xhr-polling': ['transports/xhr.js', 'transports/xhr-polling.js'] + , 'jsonp-polling': [ + 'transports/xhr.js' + , 'transports/xhr-polling.js' + , 'transports/jsonp-polling.js' + ] +}; + +/** + * Wrappers for client-side usage. + * This enables usage in top-level browser window, client-side CommonJS systems and AMD loaders. + * If doing a node build for server-side client, this wrapper is NOT included. + * @api private + */ +var wrapperPre = "\nvar io = ('undefined' === typeof module ? {} : module.exports);\n(function() {\n"; + +var wrapperPost = "\nif (typeof define === \"function\" && define.amd) {" + + "\n define([], function () { return io; });" + + "\n}\n})();"; + + +/** + * Builds a custom Socket.IO distribution based on the transports that you + * need. You can configure the build to create development build or production + * build (minified). + * + * @param {Array} transports The transports that needs to be bundled. + * @param {Object} [options] Options to configure the building process. + * @param {Function} callback Last argument should always be the callback + * @callback {String|Boolean} err An optional argument, if it exists than an error + * occurred during the build process. + * @callback {String} result The result of the build process. + * @api public + */ + +var builder = module.exports = function () { + var transports, options, callback, error = null + , args = Array.prototype.slice.call(arguments, 0) + , settings = { + minify: true + , node: false + , custom: [] + }; + + // Fancy pancy argument support this makes any pattern possible mainly + // because we require only one of each type + args.forEach(function (arg) { + var type = Object.prototype.toString.call(arg) + .replace(/\[object\s(\w+)\]/gi , '$1' ).toLowerCase(); + + switch (type) { + case 'array': + return transports = arg; + case 'object': + return options = arg; + case 'function': + return callback = arg; + } + }); + + // Add defaults + options = options || {}; + transports = transports || Object.keys(baseTransports); + + // Merge the data + for(var option in options) { + settings[option] = options[option]; + } + + // Start creating a dependencies chain with all the required files for the + // custom Socket.IO bundle. + var files = []; + base.forEach(function (file) { + files.push(__dirname + '/../lib/' + file); + }); + + transports.forEach(function (transport) { + var dependencies = baseTransports[transport]; + if (!dependencies) { + error = 'Unsupported transport `' + transport + '` supplied as argument.'; + return; + } + + // Add the files to the files list, but only if they are not added before + dependencies.forEach(function (file) { + var path = __dirname + '/../lib/' + file; + if (!~files.indexOf(path)) files.push(path); + }) + }); + + // check to see if the files tree compilation generated any errors. + if (error) return callback(error); + + var results = {}; + files.forEach(function (file) { + fs.readFile(file, function (err, content) { + if (err) error = err; + results[file] = content; + + // check if we are done yet, or not.. Just by checking the size of the result + // object. + if (Object.keys(results).length !== files.length) return; + + // we are done, did we error? + if (error) return callback(error); + + // start with the license header + var code = development + , ignore = 0; + + // pre-wrapper for non-server-side builds + if (!settings.node) code += wrapperPre; + + // concatenate the file contents in order + files.forEach(function (file) { + code += results[file]; + }); + + // check if we need to add custom code + if (settings.custom.length) { + settings.custom.forEach(function (content) { + code += content; + }); + } + + // post-wrapper for non-server-side builds + if (!settings.node) { + code += wrapperPost; + } + + code = activeXObfuscator(code); + + // Search for conditional code blocks that need to be removed as they + // where designed for a server side env. but only if we don't want to + // make this build node compatible. + if (!settings.node) { + code = code.split('\n').filter(function (line) { + // check if there are tags in here + var start = line.indexOf(starttagIF) >= 0 + , end = line.indexOf(endtagIF) >= 0 + , ret = ignore; + + // ignore the current line + if (start) { + ignore++; + ret = ignore; + } + + // stop ignoring the next line + if (end) { + ignore--; + } + + return ret == 0; + }).join('\n'); + } + + // check if we need to process it any further + if (settings.minify) { + var ast = uglify.parser.parse(code); + ast = uglify.uglify.ast_mangle(ast); + ast = uglify.uglify.ast_squeeze(ast); + + code = production + uglify.uglify.gen_code(ast, { ascii_only: true }); + } + + callback(error, code); + }) + }) +}; + +/** + * Builder version is also the current client version + * this way we don't have to do another include for the + * clients version number and we can just include the builder. + * + * @type {String} + * @api public + */ + +builder.version = socket.version; + +/** + * A list of all build in transport types. + * + * @type {Object} + * @api public + */ + +builder.transports = baseTransports; + +/** + * Command line support, this allows us to generate builds without having + * to load it as module. + */ + +if (!module.parent){ + // the first 2 are `node` and the path to this file, we don't need them + var args = process.argv.slice(2); + + // build a development build + builder(args.length ? args : false, { minify:false }, function (err, content) { + if (err) return console.error(err); + + fs.write( + fs.openSync(__dirname + '/../dist/socket.io.js', 'w') + , content + , 0 + , 'utf8' + ); + console.log('Successfully generated the development build: socket.io.js'); + }); + + // and build a production build + builder(args.length ? args : false, function (err, content) { + if (err) return console.error(err); + + fs.write( + fs.openSync(__dirname + '/../dist/socket.io.min.js', 'w') + , content + , 0 + , 'utf8' + ); + console.log('Successfully generated the production build: socket.io.min.js'); + }); +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/component.json b/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/component.json new file mode 100644 index 00000000..ebdf6422 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/component.json @@ -0,0 +1,14 @@ +{ + "name": "bind", + "version": "0.0.1", + "description": "function binding utility", + "keywords": [ + "bind", + "utility" + ], + "dependencies": {}, + "scripts": [ + "index.js" + ], + "repo": "https://raw.github.com/component/bind" +} \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/index.js new file mode 100644 index 00000000..9808fc06 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/index.js @@ -0,0 +1,24 @@ + +/** + * Slice reference. + */ + +var slice = [].slice; + +/** + * Bind `obj` to `fn`. + * + * @param {Object} obj + * @param {Function|String} fn or string + * @return {Function} + * @api public + */ + +module.exports = function(obj, fn){ + if ('string' == typeof fn) fn = obj[fn]; + if ('function' != typeof fn) throw new Error('bind() requires a function'); + var args = [].slice.call(arguments, 2); + return function(){ + return fn.apply(obj, args.concat(slice.call(arguments))); + } +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/component.json b/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/component.json new file mode 100644 index 00000000..0eec23b1 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/component.json @@ -0,0 +1,13 @@ +{ + "name": "emitter", + "description": "Event emitter", + "keywords": [ + "emitter", + "events" + ], + "version": "0.0.6", + "scripts": [ + "index.js" + ], + "repo": "https://raw.github.com/component/emitter" +} \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/index.js new file mode 100644 index 00000000..8cc74ae8 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/index.js @@ -0,0 +1,147 @@ + +/** + * Expose `Emitter`. + */ + +module.exports = Emitter; + +/** + * Initialize a new `Emitter`. + * + * @api public + */ + +function Emitter(obj) { + if (obj) return mixin(obj); +}; + +/** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; +} + +/** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.on = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks[event] = this._callbacks[event] || []) + .push(fn); + return this; +}; + +/** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.once = function(event, fn){ + var self = this; + this._callbacks = this._callbacks || {}; + + function on() { + self.off(event, on); + fn.apply(this, arguments); + } + + fn._off = on; + this.on(event, on); + return this; +}; + +/** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.off = function(event, fn){ + this._callbacks = this._callbacks || {}; + var callbacks = this._callbacks[event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks[event]; + return this; + } + + // remove specific handler + var i = callbacks.indexOf(fn._off || fn); + if (~i) callbacks.splice(i, 1); + return this; +}; + +/** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + +Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks[event]; + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; +}; + +/** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + +Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks[event] || []; +}; + +/** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + +Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; +}; + diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/component.json b/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/component.json new file mode 100644 index 00000000..6b35f453 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/component.json @@ -0,0 +1,15 @@ +{ + "name": "json-fallback", + "repo": "component/json", + "description": "JSON parser / stringifier fallback", + "version": "0.0.1", + "keywords": [ + "json", + "fallback" + ], + "dependencies": {}, + "development": {}, + "scripts": [ + "index.js" + ] +} \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/index.js new file mode 100644 index 00000000..5a47ca6f --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/index.js @@ -0,0 +1,486 @@ +/* + json2.js + 2011-10-19 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, regexp: true */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +var JSON = {}; + +(function () { + 'use strict'; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) + ? this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' + : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' + ? c + : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 + ? '[]' + : gap + ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' + : '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + if (typeof rep[i] === 'string') { + k = rep[i]; + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 + ? '{}' + : gap + ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' + : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ + .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') + .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' + ? walk({'': j}, '') + : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); + +module.exports = JSON \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-json/component.json b/node_modules/socket.io/node_modules/socket.io-client/components/component-json/component.json new file mode 100644 index 00000000..da7097cf --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-json/component.json @@ -0,0 +1,17 @@ +{ + "name": "json", + "repo": "component/json", + "description": "JSON parser / stringifier", + "version": "0.0.1", + "keywords": [ + "json" + ], + "dependencies": {}, + "development": {}, + "optional": { + "component/json-fallback": "*" + }, + "scripts": [ + "index.js" + ] +} \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-json/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/component-json/index.js new file mode 100644 index 00000000..c05cc28c --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-json/index.js @@ -0,0 +1,4 @@ + +module.exports = 'undefined' == typeof JSON + ? require('json-fallback') + : JSON; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/component.json b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/component.json new file mode 100644 index 00000000..b90c1f27 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/component.json @@ -0,0 +1,24 @@ +{ + "name": "engine.io", + "version": "0.4.0", + "dependencies": { + "component/emitter": "0.0.6", + "visionmedia/debug": "*" + }, + "main": "lib/index.js", + "scripts": [ + "lib/index.js", + "lib/parser.js", + "lib/socket.js", + "lib/transport.js", + "lib/emitter.js", + "lib/util.js", + "lib/transports/index.js", + "lib/transports/polling.js", + "lib/transports/polling-xhr.js", + "lib/transports/polling-jsonp.js", + "lib/transports/websocket.js", + "lib/transports/flashsocket.js" + ], + "repo": "https://raw.github.com/learnboost/engine.io-client" +} \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/emitter.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/emitter.js new file mode 100644 index 00000000..142a9bf6 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/emitter.js @@ -0,0 +1,52 @@ + +/** + * Module dependencies. + */ + +var Emitter; + +try { + Emitter = require('emitter'); +} catch(e){ + Emitter = require('emitter-component'); +} + +/** + * Module exports. + */ + +module.exports = Emitter; + +/** + * Compatibility with `WebSocket#addEventListener`. + * + * @api public + */ + +Emitter.prototype.addEventListener = Emitter.prototype.on; + +/** + * Compatibility with `WebSocket#removeEventListener`. + * + * @api public + */ + +Emitter.prototype.removeEventListener = Emitter.prototype.off; + +/** + * Node-compatible `EventEmitter#removeListener` + * + * @api public + */ + +Emitter.prototype.removeListener = Emitter.prototype.off; + +/** + * Node-compatible `EventEmitter#removeAllListeners` + * + * @api public + */ + +Emitter.prototype.removeAllListeners = function(){ + this._callbacks = {}; +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/index.js new file mode 100644 index 00000000..d463b3fb --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./socket'); diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/parser.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/parser.js new file mode 100644 index 00000000..2c2928e8 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/parser.js @@ -0,0 +1,163 @@ +/** + * Module dependencies. + */ + +var util = require('./util') + +/** + * Packet types. + */ + +var packets = exports.packets = { + open: 0 // non-ws + , close: 1 // non-ws + , ping: 2 + , pong: 3 + , message: 4 + , upgrade: 5 + , noop: 6 +}; + +var packetslist = util.keys(packets); + +/** + * Premade error packet. + */ + +var err = { type: 'error', data: 'parser error' } + +/** + * Encodes a packet. + * + * [ `:` ] + * + * Example: + * + * 5:hello world + * 3 + * 4 + * + * @api private + */ + +exports.encodePacket = function (packet) { + var encoded = packets[packet.type] + + // data fragment is optional + if (undefined !== packet.data) { + encoded += String(packet.data); + } + + return '' + encoded; +}; + +/** + * Decodes a packet. + * + * @return {Object} with `type` and `data` (if any) + * @api private + */ + +exports.decodePacket = function (data) { + var type = data.charAt(0); + + if (Number(type) != type || !packetslist[type]) { + return err; + } + + if (data.length > 1) { + return { type: packetslist[type], data: data.substring(1) }; + } else { + return { type: packetslist[type] }; + } +}; + +/** + * Encodes multiple messages (payload). + * + * :data + * + * Example: + * + * 11:hello world2:hi + * + * @param {Array} packets + * @api private + */ + +exports.encodePayload = function (packets) { + if (!packets.length) { + return '0:'; + } + + var encoded = '' + , message + + for (var i = 0, l = packets.length; i < l; i++) { + message = exports.encodePacket(packets[i]); + encoded += message.length + ':' + message; + } + + return encoded; +}; + +/* + * Decodes data when a payload is maybe expected. + * + * @param {String} data + * @return {Array} packets + * @api public + */ + +exports.decodePayload = function (data) { + if (data == '') { + // parser error - ignoring payload + return [err]; + } + + var packets = [] + , length = '' + , n, msg, packet + + for (var i = 0, l = data.length; i < l; i++) { + var chr = data.charAt(i) + + if (':' != chr) { + length += chr; + } else { + if ('' == length || (length != (n = Number(length)))) { + // parser error - ignoring payload + return [err]; + } + + msg = data.substr(i + 1, n); + + if (length != msg.length) { + // parser error - ignoring payload + return [err]; + } + + if (msg.length) { + packet = exports.decodePacket(msg); + + if (err.type == packet.type && err.data == packet.data) { + // parser error in individual packet - ignoring payload + return [err]; + } + + packets.push(packet); + } + + // advance cursor + i += n; + length = '' + } + } + + if (length != '') { + // parser error - ignoring payload + return [err]; + } + + return packets; +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/socket.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/socket.js new file mode 100644 index 00000000..ad86283b --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/socket.js @@ -0,0 +1,492 @@ +/** + * Module dependencies. + */ + +var util = require('./util') + , transports = require('./transports') + , Emitter = require('./emitter') + , debug = require('debug')('engine-client:socket'); + +/** + * Module exports. + */ + +module.exports = Socket; + +/** + * Global reference. + */ + +var global = 'undefined' != typeof window ? window : global; + +/** + * Socket constructor. + * + * @param {Object} options + * @api public + */ + +function Socket(opts){ + if (!(this instanceof Socket)) return new Socket(opts); + + if ('string' == typeof opts) { + var uri = util.parseUri(opts); + opts = arguments[1] || {}; + opts.host = uri.host; + opts.secure = uri.protocol == 'https' || uri.protocol == 'wss'; + opts.port = uri.port; + } + + opts = opts || {}; + this.secure = null != opts.secure ? opts.secure : (global.location && 'https:' == location.protocol); + this.host = opts.host || opts.hostname || (global.location ? location.hostname : 'localhost'); + this.port = opts.port || (global.location && location.port ? location.port : (this.secure ? 443 : 80)); + this.query = opts.query || {}; + this.query.uid = rnd(); + this.upgrade = false !== opts.upgrade; + this.resource = opts.resource || 'default'; + this.path = (opts.path || '/engine.io').replace(/\/$/, ''); + this.path += '/' + this.resource + '/'; + this.forceJSONP = !!opts.forceJSONP; + this.timestampParam = opts.timestampParam || 't'; + this.timestampRequests = !!opts.timestampRequests; + this.flashPath = opts.flashPath || ''; + this.transports = opts.transports || ['polling', 'websocket', 'flashsocket']; + this.readyState = ''; + this.writeBuffer = []; + this.policyPort = opts.policyPort || 843; + this.open(); + + Socket.sockets.push(this); + Socket.sockets.evs.emit('add', this); +}; + +/** + * Mix in `Emitter`. + */ + +Emitter(Socket.prototype); + +/** + * Protocol version. + * + * @api public + */ + +Socket.protocol = 1; + +/** + * Static EventEmitter. + */ + +Socket.sockets = []; +Socket.sockets.evs = new Emitter; + +/** + * Expose deps for legacy compatibility + * and standalone browser access. + */ + +Socket.Socket = Socket; +Socket.Transport = require('./transport'); +Socket.Emitter = require('./emitter'); +Socket.transports = require('./transports'); +Socket.util = require('./util'); +Socket.parser = require('./parser'); + +/** + * Creates transport of the given type. + * + * @param {String} transport name + * @return {Transport} + * @api private + */ + +Socket.prototype.createTransport = function (name) { + debug('creating transport "%s"', name); + var query = clone(this.query); + query.transport = name; + + if (this.id) { + query.sid = this.id; + } + + var transport = new transports[name]({ + host: this.host + , port: this.port + , secure: this.secure + , path: this.path + , query: query + , forceJSONP: this.forceJSONP + , timestampRequests: this.timestampRequests + , timestampParam: this.timestampParam + , flashPath: this.flashPath + , policyPort: this.policyPort + }); + + return transport; +}; + +function clone (obj) { + var o = {}; + for (var i in obj) { + if (obj.hasOwnProperty(i)) { + o[i] = obj[i]; + } + } + return o; +} + +/** + * Initializes transport to use and starts probe. + * + * @api private + */ + +Socket.prototype.open = function () { + this.readyState = 'opening'; + var transport = this.createTransport(this.transports[0]); + transport.open(); + this.setTransport(transport); +}; + +/** + * Sets the current transport. Disables the existing one (if any). + * + * @api private + */ + +Socket.prototype.setTransport = function (transport) { + var self = this; + + if (this.transport) { + debug('clearing existing transport'); + this.transport.removeAllListeners(); + } + + // set up transport + this.transport = transport; + + // set up transport listeners + transport + .on('drain', function () { + self.flush(); + }) + .on('packet', function (packet) { + self.onPacket(packet); + }) + .on('error', function (e) { + self.onError(e); + }) + .on('close', function () { + self.onClose('transport close'); + }); +}; + +/** + * Probes a transport. + * + * @param {String} transport name + * @api private + */ + +Socket.prototype.probe = function (name) { + debug('probing transport "%s"', name); + var transport = this.createTransport(name, { probe: 1 }) + , failed = false + , self = this; + + transport.once('open', function () { + if (failed) return; + + debug('probe transport "%s" opened', name); + transport.send([{ type: 'ping', data: 'probe' }]); + transport.once('packet', function (msg) { + if (failed) return; + if ('pong' == msg.type && 'probe' == msg.data) { + debug('probe transport "%s" pong', name); + self.upgrading = true; + self.emit('upgrading', transport); + + debug('pausing current transport "%s"', self.transport.name); + self.transport.pause(function () { + if (failed) return; + if ('closed' == self.readyState || 'closing' == self.readyState) { + return; + } + debug('changing transport and sending upgrade packet'); + transport.removeListener('error', onerror); + self.emit('upgrade', transport); + self.setTransport(transport); + transport.send([{ type: 'upgrade' }]); + transport = null; + self.upgrading = false; + self.flush(); + }); + } else { + debug('probe transport "%s" failed', name); + var err = new Error('probe error'); + err.transport = transport.name; + self.emit('error', err); + } + }); + }); + + transport.once('error', onerror); + function onerror(err) { + if (failed) return; + + // Any callback called by transport should be ignored since now + failed = true; + + var error = new Error('probe error: ' + err); + error.transport = transport.name; + + transport.close(); + transport = null; + + debug('probe transport "%s" failed because of error: %s', name, err); + + self.emit('error', error); + }; + + transport.open(); + + this.once('close', function () { + if (transport) { + debug('socket closed prematurely - aborting probe'); + failed = true; + transport.close(); + transport = null; + } + }); + + this.once('upgrading', function (to) { + if (transport && to.name != transport.name) { + debug('"%s" works - aborting "%s"', to.name, transport.name); + transport.close(); + transport = null; + } + }); +}; + +/** + * Called when connection is deemed open. + * + * @api public + */ + +Socket.prototype.onOpen = function () { + debug('socket open'); + this.readyState = 'open'; + this.emit('open'); + this.onopen && this.onopen.call(this); + this.flush(); + + // we check for `readyState` in case an `open` + // listener alreay closed the socket + if ('open' == this.readyState && this.upgrade && this.transport.pause) { + debug('starting upgrade probes'); + for (var i = 0, l = this.upgrades.length; i < l; i++) { + this.probe(this.upgrades[i]); + } + } +}; + +/** + * Handles a packet. + * + * @api private + */ + +Socket.prototype.onPacket = function (packet) { + if ('opening' == this.readyState || 'open' == this.readyState) { + debug('socket receive: type "%s", data "%s"', packet.type, packet.data); + + this.emit('packet', packet); + + // Socket is live - any packet counts + this.emit('heartbeat'); + + switch (packet.type) { + case 'open': + this.onHandshake(util.parseJSON(packet.data)); + break; + + case 'pong': + this.ping(); + break; + + case 'error': + var err = new Error('server error'); + err.code = packet.data; + this.emit('error', err); + break; + + case 'message': + this.emit('message', packet.data); + var event = { data: packet.data }; + event.toString = function () { + return packet.data; + }; + this.onmessage && this.onmessage.call(this, event); + break; + } + } else { + debug('packet received with socket readyState "%s"', this.readyState); + } +}; + +/** + * Called upon handshake completion. + * + * @param {Object} handshake obj + * @api private + */ + +Socket.prototype.onHandshake = function (data) { + this.emit('handshake', data); + this.id = data.sid; + this.transport.query.sid = data.sid; + this.upgrades = data.upgrades; + this.pingInterval = data.pingInterval; + this.pingTimeout = data.pingTimeout; + this.onOpen(); + this.ping(); + + // Prolong liveness of socket on heartbeat + this.removeListener('heartbeat', this.onHeartbeat); + this.on('heartbeat', this.onHeartbeat); +}; + +/** + * Resets ping timeout. + * + * @api private + */ + +Socket.prototype.onHeartbeat = function (timeout) { + clearTimeout(this.pingTimeoutTimer); + var self = this; + self.pingTimeoutTimer = setTimeout(function () { + if ('closed' == self.readyState) return; + self.onClose('ping timeout'); + }, timeout || (self.pingInterval + self.pingTimeout)); +}; + +/** + * Pings server every `this.pingInterval` and expects response + * within `this.pingTimeout` or closes connection. + * + * @api private + */ + +Socket.prototype.ping = function () { + var self = this; + clearTimeout(self.pingIntervalTimer); + self.pingIntervalTimer = setTimeout(function () { + debug('writing ping packet - expecting pong within %sms', self.pingTimeout); + self.sendPacket('ping'); + self.onHeartbeat(self.pingTimeout); + }, self.pingInterval); +}; + +/** + * Flush write buffers. + * + * @api private + */ + +Socket.prototype.flush = function () { + if ('closed' != this.readyState && this.transport.writable && + !this.upgrading && this.writeBuffer.length) { + debug('flushing %d packets in socket', this.writeBuffer.length); + this.transport.send(this.writeBuffer); + this.writeBuffer = []; + } +}; + +/** + * Sends a message. + * + * @param {String} message. + * @return {Socket} for chaining. + * @api public + */ + +Socket.prototype.write = +Socket.prototype.send = function (msg) { + this.sendPacket('message', msg); + return this; +}; + +/** + * Sends a packet. + * + * @param {String} packet type. + * @param {String} data. + * @api private + */ + +Socket.prototype.sendPacket = function (type, data) { + var packet = { type: type, data: data }; + this.emit('packetCreate', packet); + this.writeBuffer.push(packet); + this.flush(); +}; + +/** + * Closes the connection. + * + * @api private + */ + +Socket.prototype.close = function () { + if ('opening' == this.readyState || 'open' == this.readyState) { + this.onClose('forced close'); + debug('socket closing - telling transport to close'); + this.transport.close(); + this.transport.removeAllListeners(); + } + + return this; +}; + +/** + * Called upon transport error + * + * @api private + */ + +Socket.prototype.onError = function (err) { + this.emit('error', err); + this.onClose('transport error', err); +}; + +/** + * Called upon transport close. + * + * @api private + */ + +Socket.prototype.onClose = function (reason, desc) { + if ('closed' != this.readyState) { + debug('socket close with reason: "%s"', reason); + clearTimeout(this.pingIntervalTimer); + clearTimeout(this.pingTimeoutTimer); + this.readyState = 'closed'; + this.emit('close', reason, desc); + this.onclose && this.onclose.call(this); + this.id = null; + } +}; + +/** + * Generates a random uid. + * + * @api private + */ + +function rnd () { + return String(Math.random()).substr(5) + String(Math.random()).substr(5); +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transport.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transport.js new file mode 100644 index 00000000..5760f84b --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transport.js @@ -0,0 +1,141 @@ + +/** + * Module dependencies. + */ + +var util = require('./util') + , parser = require('./parser') + , Emitter = require('./emitter'); + +/** + * Module exports. + */ + +module.exports = Transport; + +/** + * Transport abstract constructor. + * + * @param {Object} options. + * @api private + */ + +function Transport (opts) { + this.path = opts.path; + this.host = opts.host; + this.port = opts.port; + this.secure = opts.secure; + this.query = opts.query; + this.timestampParam = opts.timestampParam; + this.timestampRequests = opts.timestampRequests; + this.readyState = ''; +}; + +/** + * Mix in `Emitter`. + */ + +Emitter(Transport.prototype); + +/** + * Emits an error. + * + * @param {String} str + * @return {Transport} for chaining + * @api public + */ + +Transport.prototype.onError = function (msg, desc) { + var err = new Error(msg); + err.type = 'TransportError'; + err.description = desc; + this.emit('error', err); + return this; +}; + +/** + * Opens the transport. + * + * @api public + */ + +Transport.prototype.open = function () { + if ('closed' == this.readyState || '' == this.readyState) { + this.readyState = 'opening'; + this.doOpen(); + } + + return this; +}; + +/** + * Closes the transport. + * + * @api private + */ + +Transport.prototype.close = function () { + if ('opening' == this.readyState || 'open' == this.readyState) { + this.doClose(); + this.onClose(); + } + + return this; +}; + +/** + * Sends multiple packets. + * + * @param {Array} packets + * @api private + */ + +Transport.prototype.send = function(packets){ + if ('open' == this.readyState) { + this.write(packets); + } else { + throw new Error('Transport not open'); + } +}; + +/** + * Called upon open + * + * @api private + */ + +Transport.prototype.onOpen = function () { + this.readyState = 'open'; + this.writable = true; + this.emit('open'); +}; + +/** + * Called with data. + * + * @param {String} data + * @api private + */ + +Transport.prototype.onData = function (data) { + this.onPacket(parser.decodePacket(data)); +}; + +/** + * Called with a decoded packet. + */ + +Transport.prototype.onPacket = function (packet) { + this.emit('packet', packet); +}; + +/** + * Called upon close. + * + * @api private + */ + +Transport.prototype.onClose = function () { + this.readyState = 'closed'; + this.emit('close'); +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/flashsocket.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/flashsocket.js new file mode 100644 index 00000000..9a5a1082 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/flashsocket.js @@ -0,0 +1,254 @@ + +/** + * Module dependencies. + */ + +var WS = require('./websocket') + , util = require('../util') + , debug = require('debug')('engine.io-client:flashsocket'); + +/** + * Module exports. + */ + +module.exports = FlashWS; + +/** + * Obfuscated key for Blue Coat. + */ + +var xobject = global[['Active'].concat('Object').join('X')]; + +/** + * FlashWS constructor. + * + * @api public + */ + +function FlashWS (options) { + WS.call(this, options); + this.flashPath = options.flashPath; + this.policyPort = options.policyPort; +}; + +/** + * Inherits from WebSocket. + */ + +util.inherits(FlashWS, WS); + +/** + * Transport name. + * + * @api public + */ + +FlashWS.prototype.name = 'flashsocket'; + +/** + * Opens the transport. + * + * @api public + */ + +FlashWS.prototype.doOpen = function () { + if (!this.check()) { + // let the probe timeout + return; + } + + // instrument websocketjs logging + function log (type) { + return function(){ + var str = Array.prototype.join.call(arguments, ' '); + debug('[websocketjs %s] %s', type, str); + }; + }; + + WEB_SOCKET_LOGGER = { log: log('debug'), error: log('error') }; + WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true; + WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true; + + if ('undefined' == typeof WEB_SOCKET_SWF_LOCATION) { + WEB_SOCKET_SWF_LOCATION = this.flashPath + 'WebSocketMainInsecure.swf'; + } + + // dependencies + var deps = [this.flashPath + 'web_socket.js']; + + if ('undefined' == typeof swfobject) { + deps.unshift(this.flashPath + 'swfobject.js'); + } + + var self = this; + + load(deps, function () { + self.ready(function () { + WebSocket.__addTask(function () { + WS.prototype.doOpen.call(self); + }); + }); + }); +}; + +/** + * Override to prevent closing uninitialized flashsocket. + * + * @api private + */ + +FlashWS.prototype.doClose = function () { + if (!this.socket) return; + var self = this; + WebSocket.__addTask(function() { + WS.prototype.doClose.call(self); + }); +}; + +/** + * Writes to the Flash socket. + * + * @api private + */ + +FlashWS.prototype.write = function() { + var self = this, args = arguments; + WebSocket.__addTask(function () { + WS.prototype.write.apply(self, args); + }); +}; + +/** + * Called upon dependencies are loaded. + * + * @api private + */ + +FlashWS.prototype.ready = function (fn) { + if (typeof WebSocket == 'undefined' || + !('__initialize' in WebSocket) || !swfobject) { + return; + } + + if (swfobject.getFlashPlayerVersion().major < 10) { + return; + } + + function init () { + // Only start downloading the swf file when the checked that this browser + // actually supports it + if (!FlashWS.loaded) { + if (843 != self.policyPort) { + WebSocket.loadFlashPolicyFile('xmlsocket://' + self.host + ':' + self.policyPort); + } + + WebSocket.__initialize(); + FlashWS.loaded = true; + } + + fn.call(self); + } + + var self = this; + if (document.body) { + return init(); + } + + util.load(init); +}; + +/** + * Feature detection for flashsocket. + * + * @return {Boolean} whether this transport is available. + * @api public + */ + +FlashWS.prototype.check = function () { + if ('undefined' != typeof process) { + return false; + } + + if (typeof WebSocket != 'undefined' && !('__initialize' in WebSocket)) { + return false; + } + + if (xobject) { + var control = null; + try { + control = new xobject('ShockwaveFlash.ShockwaveFlash'); + } catch (e) { } + if (control) { + return true; + } + } else { + for (var i = 0, l = navigator.plugins.length; i < l; i++) { + for (var j = 0, m = navigator.plugins[i].length; j < m; j++) { + if (navigator.plugins[i][j].description == 'Shockwave Flash') { + return true; + } + } + } + } + + return false; +}; + +/** + * Lazy loading of scripts. + * Based on $script by Dustin Diaz - MIT + */ + +var scripts = {}; + +/** + * Injects a script. Keeps tracked of injected ones. + * + * @param {String} path + * @param {Function} callback + * @api private + */ + +function create (path, fn) { + if (scripts[path]) return fn(); + + var el = document.createElement('script'); + var loaded = false; + + debug('loading "%s"', path); + el.onload = el.onreadystatechange = function () { + if (loaded || scripts[path]) return; + var rs = el.readyState; + if (!rs || 'loaded' == rs || 'complete' == rs) { + debug('loaded "%s"', path); + el.onload = el.onreadystatechange = null; + loaded = true; + scripts[path] = true; + fn(); + } + }; + + el.async = 1; + el.src = path; + + var head = document.getElementsByTagName('head')[0]; + head.insertBefore(el, head.firstChild); +}; + +/** + * Loads scripts and fires a callback. + * + * @param {Array} paths + * @param {Function} callback + */ + +function load (arr, fn) { + function process (i) { + if (!arr[i]) return fn(); + create(arr[i], function () { + process(++i); + }); + }; + + process(0); +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/index.js new file mode 100644 index 00000000..374620b0 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/index.js @@ -0,0 +1,62 @@ + +/** + * Module dependencies + */ + +var XHR = require('./polling-xhr') + , JSONP = require('./polling-jsonp') + , websocket = require('./websocket') + , flashsocket = require('./flashsocket') + , util = require('../util'); + +/** + * Export transports. + */ + +exports.polling = polling; +exports.websocket = websocket; +exports.flashsocket = flashsocket; + +/** + * Global reference. + */ + +var global = 'undefined' != typeof window ? window : global; + +/** + * Polling transport polymorphic constructor. + * Decides on xhr vs jsonp based on feature detection. + * + * @api private + */ + +function polling (opts) { + var xhr + , xd = false + , isXProtocol = false; + + if (global.location) { + var isSSL = 'https:' == location.protocol; + var port = location.port; + + // some user agents have empty `location.port` + if (Number(port) != port) { + port = isSSL ? 443 : 80; + } + + xd = opts.host != location.hostname || port != opts.port; + isXProtocol = opts.secure != isSSL; + } + + xhr = util.request(xd); + /* See #7 at http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx */ + if (isXProtocol && global.XDomainRequest && xhr instanceof global.XDomainRequest) { + return new JSONP(opts); + } + + if (xhr && !opts.forceJSONP) { + return new XHR(opts); + } else { + return new JSONP(opts); + } +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling-jsonp.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling-jsonp.js new file mode 100644 index 00000000..fde3e79e --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling-jsonp.js @@ -0,0 +1,221 @@ + +/** + * Module requirements. + */ + +var Polling = require('./polling') + , util = require('../util'); + +/** + * Module exports. + */ + +module.exports = JSONPPolling; + +/** + * Global reference. + */ + +var global = 'undefined' != typeof window ? window : global; + +/** + * Cached regular expressions. + */ + +var rNewline = /\n/g; + +/** + * Global JSONP callbacks. + */ + +var callbacks; + +/** + * Callbacks count. + */ + +var index = 0; + +/** + * Noop. + */ + +function empty () { } + +/** + * JSONP Polling constructor. + * + * @param {Object} opts. + * @api public + */ + +function JSONPPolling (opts) { + Polling.call(this, opts); + + // define global callbacks array if not present + // we do this here (lazily) to avoid unneeded global pollution + if (!callbacks) { + // we need to consider multiple engines in the same page + if (!global.___eio) global.___eio = []; + callbacks = global.___eio; + } + + // callback identifier + this.index = callbacks.length; + + // add callback to jsonp global + var self = this; + callbacks.push(function (msg) { + self.onData(msg); + }); + + // append to query string + this.query.j = this.index; +}; + +/** + * Inherits from Polling. + */ + +util.inherits(JSONPPolling, Polling); + +/** + * Opens the socket. + * + * @api private + */ + +JSONPPolling.prototype.doOpen = function () { + var self = this; + util.defer(function () { + Polling.prototype.doOpen.call(self); + }); +}; + +/** + * Closes the socket + * + * @api private + */ + +JSONPPolling.prototype.doClose = function () { + if (this.script) { + this.script.parentNode.removeChild(this.script); + this.script = null; + } + + if (this.form) { + this.form.parentNode.removeChild(this.form); + this.form = null; + } + + Polling.prototype.doClose.call(this); +}; + +/** + * Starts a poll cycle. + * + * @api private + */ + +JSONPPolling.prototype.doPoll = function () { + var script = document.createElement('script'); + + if (this.script) { + this.script.parentNode.removeChild(this.script); + this.script = null; + } + + script.async = true; + script.src = this.uri(); + + var insertAt = document.getElementsByTagName('script')[0]; + insertAt.parentNode.insertBefore(script, insertAt); + this.script = script; + + if (util.ua.gecko) { + setTimeout(function () { + var iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + document.body.removeChild(iframe); + }, 100); + } +}; + +/** + * Writes with a hidden iframe. + * + * @param {String} data to send + * @param {Function} called upon flush. + * @api private + */ + +JSONPPolling.prototype.doWrite = function (data, fn) { + var self = this; + + if (!this.form) { + var form = document.createElement('form') + , area = document.createElement('textarea') + , id = this.iframeId = 'eio_iframe_' + this.index + , iframe; + + form.className = 'socketio'; + form.style.position = 'absolute'; + form.style.top = '-1000px'; + form.style.left = '-1000px'; + form.target = id; + form.method = 'POST'; + form.setAttribute('accept-charset', 'utf-8'); + area.name = 'd'; + form.appendChild(area); + document.body.appendChild(form); + + this.form = form; + this.area = area; + } + + this.form.action = this.uri(); + + function complete () { + initIframe(); + fn(); + }; + + function initIframe () { + if (self.iframe) { + self.form.removeChild(self.iframe); + } + + try { + // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) + iframe = document.createElement(''; +html += '
    '; +html += '
    '; +html += '
    Upload File
    '; +html += '
    Want to upload multiple files at once? Please upgrade to the latest Flash Player, then reload this page. For some reason our Flash based uploader did not load, so you are currently using our single file uploader.
    '; +html += spacer(1,20) + '
    '; +var url = zero_client.targetURL; +if (url.indexOf('?') > -1) url += '&'; else url += '?'; +url += 'format=jshtml&onafter=' + escape('window.parent.upload_basic_finish(response);'); +Debug.trace('upload', "Prepping basic upload: " + url); +html += '
    '; +html += '
    '; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('page_white_get.png', 'Upload', "upload_basic_go()") + '
    '; +html += '
    '; +html += ''; +html += '
    '; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +show_popup_dialog(528, 200, html); +} +function upload_basic_go() { +$('f_upload_basic').submit(); +$('d_upload_form').hide(); +$('d_upload_progress').show(); +} +function upload_basic_finish(response) { +Debug.trace('upload', "Basic upload complete: " + dumper(response)); +setTimeout( 'upload_basic_finish_2()', 100 ); +} +function upload_basic_finish_2() { +$('i_upload_basic').src = 'blank.html'; +setTimeout( 'upload_basic_finish_3()', 100 ); +} +function upload_basic_finish_3() { +hide_popup_dialog(); +delete session.progress; +show_progress_dialog( 0, 'Finishing Upload...', true ); +fire_callback( session.upload_callback ); +} +function upload_destroy() { +if (zero_client) { +zero_client.destroy(); +delete ZeroUpload.clients[ zero_client.id ]; +zero_client = null; +} +} +function prep_upload(dom_id, url, callback, types) { +session.upload_callback = callback; +if (url) { +if (url.indexOf('?') > -1) url += '&'; else url += '?'; +url += 'session=' + session.cookie.get('effect_session_id'); +} +upload_destroy(); +zero_client = new ZeroUpload.Client(); +if (url) zero_client.setURL( url ); +zero_client.setHandCursor( true ); +if (types) zero_client.setFileTypes( types[0], types[1] ); +zero_client.addEventListener( 'queueStart', uploadQueueStart ); +zero_client.addEventListener( 'fileStart', uploadFileStart ); +zero_client.addEventListener( 'progress', uploadProgress ); +zero_client.addEventListener( 'fileComplete', uploadFileComplete ); +zero_client.addEventListener( 'queueComplete', uploadQueueComplete ); +zero_client.addEventListener( 'error', uploadError ); +zero_client.addEventListener( 'debug', function(client, eventName, args) { +Debug.trace('upload', "Caught event: " + eventName); +} ); +if (dom_id) { +Debug.trace('upload', "Gluing ZeroUpload to: " + dom_id); +zero_client.glue( dom_id ); +} +} +Class.create( 'Debug', { +__static: { +enabled: false, +categories: { all: 1 }, +buffer: [], +max_rows: 5000, +win: null, +ie: !!navigator.userAgent.match(/MSIE/), +ie6: !!navigator.userAgent.match(/MSIE\D+6/), +init: function() { +Debug.enabled = true; +Debug.trace( 'debug', 'Debug log start' ); +var html = '

    '; +if (Debug.ie) { +setTimeout( function() { +document.body.insertAdjacentHTML('beforeEnd', +'
    ' + html + '
    ' +); +}, 1000 ); +} +else { +var div = document.createElement('DIV'); +div.id = 'd_debug'; +div.setAttribute('id', 'd_debug'); +div.style.position = Debug.ie6 ? 'absolute' : 'fixed'; +div.style.zIndex = '101'; +div.style.left = '0px'; +div.style.top = '0px'; +div.style.width = '100%'; +div.innerHTML = html; +document.getElementsByTagName('body')[0].appendChild(div); +} +}, +show: function() { +if (!Debug.win || Debug.win.closed) { +Debug.trace('debug', "Opening debug window"); +Debug.win = window.open( '', 'DebugWindow', 'width=600,height=500,menubar=no,resizable=yes,scrollbars=yes,location=no,status=no,toolbar=no,directories=no' ); +if (!Debug.win) return alert("Failed to open window. Popup blocker maybe?"); +var doc = Debug.win.document; +doc.open(); +doc.writeln( 'Debug Log' ); +doc.writeln( '
    ' ); +doc.writeln( '
    ' ); +doc.writeln( '
    ' ); +doc.writeln( '' ); +doc.writeln( '' ); +doc.writeln( '
    ' ); +doc.writeln( '' ); +doc.close(); +} +Debug.win.focus(); +}, +console_execute: function() { +var cmd = Debug.win.document.getElementById('fe_command'); +if (cmd.value.length) { +Debug.trace( 'console', cmd.value ); +try { +Debug.trace( 'console', '' + eval(cmd.value) ); +} +catch (e) { +Debug.trace( 'error', 'JavaScript Interpreter Exception: ' + e.toString() ); +} +} +}, +get_time_stamp: function(now) { +var date = new Date( now * 1000 ); +var hh = date.getHours(); if (hh < 10) hh = "0" + hh; +var mi = date.getMinutes(); if (mi < 10) mi = "0" + mi; +var ss = date.getSeconds(); if (ss < 10) ss = "0" + ss; +var sss = '' + date.getMilliseconds(); while (sss.length < 3) sss = "0" + sss; +return '' + hh + ':' + mi + ':' + ss + '.' + sss; +}, +refresh_console: function() { +if (!Debug.win || Debug.win.closed) return; +var div = Debug.win.document.getElementById('d_debug_log'); +if (div) { +var row = null; +while ( row = Debug.buffer.shift() ) { +var time_stamp = Debug.get_time_stamp(row.time); +var msg = row.msg; +msg = msg.replace(/\t/g, "    "); +msg = msg.replace(//g, ">"); +msg = msg.replace(/\n/g, "
    \n"); +var html = ''; +var sty = 'float:left; font-family: Consolas, Courier, mono; font-size: 12px; cursor:default; margin-right:10px; margin-bottom:1px; padding:2px;'; +html += '
    ' + time_stamp + '
    '; +html += '
    ' + row.cat + '
    '; +html += '
    ' + msg + '
    '; +html += '
    '; +var chunk = Debug.win.document.createElement('DIV'); +chunk.style['float'] = 'none'; +chunk.innerHTML = html; +div.appendChild(chunk); +} +var cmd = Debug.win.document.getElementById('fe_command'); +cmd.focus(); +} +Debug.dirty = 0; +Debug.win.scrollTo(0, 99999); +}, +hires_time_now: function() { +var now = new Date(); +return ( now.getTime() / 1000 ); +}, +trace: function(cat, msg) { +if (arguments.length == 1) { +msg = cat; +cat = 'debug'; +} +if (Debug.categories.all || Debug.categories[cat]) { +Debug.buffer.push({ cat: cat, msg: msg, time: Debug.hires_time_now() }); +if (Debug.buffer.length > Debug.max_rows) Debug.buffer.shift(); +if (!Debug.dirty) { +Debug.dirty = 1; +setTimeout( 'Debug.refresh_console();', 1 ); +} +} +} +} +} ); +var session = { +inited: false, +api_mod_cache: {}, +query: parseQueryString( ''+location.search ), +cookie: new CookieTree({ path: '/effect/' }), +storage: {}, +storage_dirty: false, +hooks: { +keys: {} +}, +username: '', +em_width: 11, +audioResourceMatch: /\.mp3$/i, +imageResourceMatch: /\.(jpe|jpeg|jpg|png|gif)$/i, +textResourceMatch: /\.xml$/i, +movieResourceMatch: /\.(flv|mp4|mp4v|mov|3gp|3g2)$/i, +imageResourceMatchString: '\.(jpe|jpeg|jpg|png|gif)$' +}; +session.debug = session.query.debug ? true : false; +var page_manager = null; +var preload_icons = []; +var preload_images = [ +'loading.gif', +'aquaprogressbar.gif', +'aquaprogressbar_bkgnd.gif' +]; +function get_base_url() { +return protocol + '://' + location.hostname + session.config.BaseURI; +} +function effect_init() { +if (session.inited) return; +session.inited = true; +assert( window.config, "Config not loaded" ); +session.config = window.config; +Debug.trace("Starting up"); +rendering_page = false; +preload(); +window.$R = {}; +for (var key in config.RegExpShortcuts) { +$R[key] = new RegExp( config.RegExpShortcuts[key] ); +} +ww_precalc_font("body", "effect_precalc_font_finish"); +page_manager = new Effect.PageManager( config.Pages.Page ); +var session_id = session.cookie.get('effect_session_id'); +if (session_id && session_id.match(/^login/)) { +do_session_recover(); +} +else { +show_default_login_status(); +Nav.init(); +} +Blog.search({ +stag: 'sidebar_docs', +limit: 20, +title_only: true, +sort_by: 'seq', +sort_dir: -1, +target: 'd_sidebar_documents', +outer_div_class: 'sidebar_blog_row', +title_class: 'sidebar_blog_title', +after: '' +}); +Blog.search({ +stag: 'sidebar_tutorials', +limit: 5, +title_only: true, +sort_by: 'seq', +sort_dir: -1, +target: 'd_sidebar_tutorials', +outer_div_class: 'sidebar_blog_row', +title_class: 'sidebar_blog_title', +after: '' +}); +Blog.search({ +stag: 'sidebar_plugins', +limit: 5, +title_only: true, +sort_by: 'seq', +sort_dir: -1, +target: 'd_sidebar_plugins', +outer_div_class: 'sidebar_blog_row', +title_class: 'sidebar_blog_title', +after: '' +}); +$('fe_search_bar').onkeydown = delay_onChange_input_text; +user_storage_idle(); +} +function effect_precalc_font_finish(width, height) { +session.em_width = width; +} +function preload() { +for (var idx = 0, len = preload_icons.length; idx < len; idx++) { +var url = images_uri + '/icons/' + preload_icons[idx] + '.gif'; +preload_icons[idx] = new Image(); +preload_icons[idx].src = url; +} +for (var idx = 0, len = preload_images.length; idx < len; idx++) { +var url = images_uri + '/' + preload_images[idx]; +preload_images[idx] = new Image(); +preload_images[idx].src = url; +} +} +function $P(id) { +if (!id) id = page_manager.current_page_id; +var page = page_manager.find(id); +assert( !!page, "Failed to locate page: " + id ); +return page; +} +function get_pref(name) { +if (!session.user || !session.user.Preferences) return alert("ASSERT FAILURE! Tried to lookup pref " + name + " and user is not yet loaded!"); +return session.user.Preferences[name]; +} +function get_bool_pref(name) { +return (get_pref(name) == 1); +} +function set_pref(name, value) { +session.user.Preferences[name] = value; +} +function set_bool_pref(name, value) { +set_pref(name, value ? '1' : '0'); +} +function save_prefs() { +var prefs_to_save = {}; +if (arguments.length) { +for (var idx = 0, len = arguments.length; idx < len; idx++) { +var key = arguments[idx]; +prefs_to_save[key] = get_pref(key); +} +} +else prefs_to_save = session.user.Preferences; +effect_api_mod_touch('user_get'); +effect_api_send('user_update', { +Username: session.username, +Preferences: prefs_to_save +}, 'save_prefs_2'); +} +function save_prefs_2(response) { +do_message('success', 'Preferences saved.'); +} + +function get_full_name(username) { +var user = session.users[username]; +if (!user) return username; +return user.FullName; +} +function get_buddy_icon_url(username, size) { +var mod = session.api_mod_cache.get_buddy_icon || 0; +if (!size) size = 32; +var url = '/effect/api/get_buddy_icon?username='+username + '&mod=' + mod + '&size=' + size; +return url; +} +function get_buddy_icon_display(username, show_icon, show_name) { +if ((typeof(show_icon) == 'undefined') && get_bool_pref('show_user_icons')) show_icon = 1; +if ((typeof(show_name) == 'undefined') && get_bool_pref('show_user_names')) show_name = 1; +var html = ''; +if (show_icon) html += ''; +if (show_icon && show_name) html += '
    '; +if (show_name) html += username; +return html; +} +function do_session_recover() { +session.hooks.after_error = 'do_logout'; +effect_api_send('session_recover', {}, 'do_login_2', { _from_recover: 1 } ); +} +function require_login() { +if (session.user) return true; +Debug.trace('Page requires login, showing login page'); +session.nav_after_login = Nav.currentAnchor(); +setTimeout( function() { +Nav.go( 'Login' ); +}, 1 ); +return false; +} +function popup_window(url, name) { +if (!url) url = ''; +if (!name) name = ''; +var win = window.open(url, name); +if (!win) return alert('Failed to open popup window. If you have a popup blocker, please disable it for this website and try again.'); +return win; +} +function do_login_prompt() { +hide_popup_dialog(); +delete session.progress; +if (!session.temp_password) session.temp_password = ''; +if (!session.username) session.username = ''; +var temp_username = session.open_id || session.username || ''; +var html = ''; +html += '
    '; +html += '
    '; +html += '
    Effect Developer Login
    '; +html += '
    '; +html += '
    Effect Username  or  '+icon('openid', 'OpenID', 'popup_window(\'http://openid.net/\')', 'What is OpenID?')+'


    '; +html += '
    '; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "clear_login()") + ' ' + large_icon_button('check', 'Login', 'do_login()') + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ENTER_KEY] = 'do_login'; +session.hooks.keys[ESC_KEY] = 'clear_login'; +safe_focus( 'fe_username' ); +show_popup_dialog(450, 225, html); +} +function do_openid_reg(title, auto_login_button) { +hide_popup_dialog(); +delete session.progress; +if (!title) title = 'Register Account Using OpenID'; +if (typeof(auto_login_button) == 'undefined') auto_login_button = 1; +var html = ''; +html += '
    '; +html += '", x, "%x") + + "\n", y, "%y"); + t += "
    '; +html += '
    '+title+'
    '; +html += '
    '; +html += '
    '+icon('openid', 'Enter Your OpenID URL:')+'
    '; +if (auto_login_button) html += '


    '; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', title.match(/login/i) ? 'Login' : 'Register', 'do_openid_login()') + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ENTER_KEY] = 'do_openid_login'; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_username' ); +show_popup_dialog(450, 225, html); +} +function do_login_prompt_2() { +hide_popup_dialog(); +delete session.progress; +if (!session.temp_password) session.temp_password = ''; +if (!session.username) session.username = ''; +var html = ''; +html += '
    '; +html += '"; + second_cell = ""; + row = $("").attr("id", "s" + index).attr("class", "location_row").html(first_cell + second_cell); + $locationsDiv.append(row); + } + if (index === this.numSearchToDisplay) { + $locationsDiv.append(""); + return $locationsDiv.append(""); + } + }, this); + return this.geocoder.geocode({ + address: address + }, __bind(function(result, status) { + if (status !== "OK") { + $('.error_message').html(t("Search Address Failed")).fadeIn(); + return; + } + _.each(result, showResults); + $("#search_results").html($locationsDiv); + this.locationChange("search"); + this.searchResults = result; + return this.displaySearchLoc(); + }, this)); + }; + ClientsRequestView.prototype.mouseoverLocation = function(e) { + var $el, id, marker; + $el = $(e.currentTarget); + id = $el.attr("id").substring(1); + marker = this.markers[id]; + return marker.setAnimation(google.maps.Animation.BOUNCE); + }; + ClientsRequestView.prototype.mouseoutLocation = function(e) { + var $el, id, marker; + $el = $(e.currentTarget); + id = $el.attr("id").substring(1); + marker = this.markers[id]; + return marker.setAnimation(null); + }; + ClientsRequestView.prototype.searchLocation = function(e) { + e.preventDefault(); + $("#address").val($(e.currentTarget).html()); + return this.searchAddress(); + }; + ClientsRequestView.prototype.favoriteClick = function(e) { + var index, location; + e.preventDefault(); + $(".favorites").attr("href", ""); + index = $(e.currentTarget).removeAttr("href").attr("id"); + location = new google.maps.LatLng(USER.locations[index].latitude, USER.locations[index].longitude); + return this.panToLocation(location); + }; + ClientsRequestView.prototype.clickLocation = function(e) { + var id; + id = $(e.currentTarget).attr("id").substring(1); + return this.panToLocation(this.markers[id].getPosition()); + }; + ClientsRequestView.prototype.panToLocation = function(location) { + this.map.panTo(location); + this.map.setZoom(16); + return this.pickup_icon.setPosition(location); + }; + ClientsRequestView.prototype.locationLinkHandle = function(e) { + var panelName; + e.preventDefault(); + panelName = $(e.currentTarget).attr("id"); + return this.locationChange(panelName); + }; + ClientsRequestView.prototype.locationChange = function(type) { + $(".locations_link").attr("href", "").css("font-weight", "normal"); + switch (type) { + case "favorite": + $(".search_results").attr("href", ""); + $(".locations_link#favorite").removeAttr("href").css("font-weight", "bold"); + $("#search_results").hide(); + $("#favorite_results").fadeIn(); + return this.displayFavLoc(); + case "search": + $(".favorites").attr("href", ""); + $(".locations_link#search").removeAttr("href").css("font-weight", "bold"); + $("#favorite_results").hide(); + $("#search_results").fadeIn(); + return this.displaySearchLoc(); + } + }; + ClientsRequestView.prototype.rateTrip = function(e) { + var rating; + rating = $(e.currentTarget).attr("id"); + $(".stars").attr("src", "/web/img/star_inactive.png"); + return _(rating).times(function(index) { + return $(".stars#" + (index + 1)).attr("src", "/web/img/star_active.png"); + }); + }; + ClientsRequestView.prototype.pickupHandle = function(e) { + var $el, callback, message; + e.preventDefault(); + $el = $(e.currentTarget).find("span"); + switch ($el.html()) { + case t("Request Pickup"): + _.delay(this.requestRide, 3000); + $("#status_message").html(t("Sending pickup request...")); + $el.html(t("Cancel Pickup")).parent().attr("class", "button_red"); + this.pickup_icon.setDraggable(false); + this.map.panTo(this.pickup_icon.getPosition()); + return this.map.setZoom(18); + case t("Cancel Pickup"): + if (this.status === "ready") { + $el.html(t("Request Pickup")).parent().attr("class", "button_green"); + return this.pickup_icon.setDraggable(true); + } else { + callback = __bind(function(v, m, f) { + if (v) { + this.AskDispatch("PickupCanceledClient"); + return this.setStatus("ready"); + } + }, this); + message = t("Cancel Request Prompt"); + if (this.status === "arriving") { + message = 'Cancel Request Arrived Prompt'; + } + return $.prompt(message, { + buttons: { + Ok: true, + Cancel: false + }, + callback: callback + }); + } + } + }; + ClientsRequestView.prototype.requestRide = function() { + if ($("#pickupHandle").find("span").html() === t("Cancel Pickup")) { + this.AskDispatch("Pickup"); + return this.setStatus("searching"); + } + }; + ClientsRequestView.prototype.removeCabs = function() { + _.each(this.cabs, __bind(function(point) { + return point.setMap(null); + }, this)); + return this.cabs = []; + }; + ClientsRequestView.prototype.addToFavLoc = function(e) { + var $el, lat, lng, nickname; + e.preventDefault(); + $el = $(e.currentTarget); + $el.find(".error_message").html(""); + nickname = $el.find("#favLocNickname").val().toString(); + lat = $el.find("#pickupLat").val().toString(); + lng = $el.find("#pickupLng").val().toString(); + if (nickname.length < 3) { + $el.find(".error_message").html(t("Favorite Location Nickname Length Error")); + return; + } + this.ShowSpinner("submit"); + return $.ajax({ + type: 'POST', + url: API + "/locations", + dataType: 'json', + data: { + token: USER.token, + nickname: nickname, + latitude: lat, + longitude: lng + }, + success: __bind(function(data, textStatus, jqXHR) { + return $el.html(t("Favorite Location Save Succeeded")); + }, this), + error: __bind(function(jqXHR, textStatus, errorThrown) { + return $el.find(".error_message").html(t("Favorite Location Save Failed")); + }, this), + complete: __bind(function(data) { + return this.HideSpinner(); + }, this) + }); + }; + ClientsRequestView.prototype.showFavLoc = function(e) { + $(e.currentTarget).fadeOut(); + return $("#favLoc_form").fadeIn(); + }; + ClientsRequestView.prototype.selectInputText = function(e) { + e.currentTarget.focus(); + return e.currentTarget.select(); + }; + ClientsRequestView.prototype.displayFavLoc = function() { + var alphabet, bounds; + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + this.removeMarkers(); + bounds = new google.maps.LatLngBounds(); + _.each(USER.locations, __bind(function(location, index) { + var marker; + marker = new google.maps.Marker({ + position: new google.maps.LatLng(location.latitude, location.longitude), + map: this.map, + title: t("Favorite Location Title", { + id: alphabet != null ? alphabet[index] : void 0 + }), + icon: "https://www.google.com/mapfiles/marker" + alphabet[index] + ".png" + }); + this.markers.push(marker); + bounds.extend(marker.getPosition()); + return google.maps.event.addListener(marker, 'click', __bind(function() { + return this.pickup_icon.setPosition(marker.getPosition()); + }, this)); + }, this)); + this.pickup_icon.setPosition(_.first(this.markers).getPosition()); + return this.map.fitBounds(bounds); + }; + ClientsRequestView.prototype.displaySearchLoc = function() { + var alphabet; + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + this.removeMarkers(); + return _.each(this.searchResults, __bind(function(result, index) { + var marker; + if (index < this.numSearchToDisplay) { + marker = new google.maps.Marker({ + position: result.geometry.location, + map: this.map, + title: t("Search Location Title", { + id: alphabet != null ? alphabet[index] : void 0 + }), + icon: "https://www.google.com/mapfiles/marker" + alphabet[index] + ".png" + }); + this.markers.push(marker); + return this.panToLocation(result.geometry.location); + } + }, this)); + }; + ClientsRequestView.prototype.removeMarkers = function() { + _.each(this.markers, __bind(function(marker) { + return marker.setMap(null); + }, this)); + return this.markers = []; + }; + ClientsRequestView.prototype.AskDispatch = function(ask, options) { + var attrs, lowestETA, processData, showCab; + if (ask == null) { + ask = ""; + } + if (options == null) { + options = {}; + } + switch (ask) { + case "NearestCab": + attrs = { + latitude: this.pickup_icon.getPosition().lat(), + longitude: this.pickup_icon.getPosition().lng() + }; + lowestETA = 99999; + showCab = __bind(function(cab) { + var point; + point = new google.maps.Marker({ + position: new google.maps.LatLng(cab.latitude, cab.longitude), + map: this.map, + icon: this.cabMarker, + title: t("ETA Message", { + minutes: app.helpers.FormatSeconds(cab != null ? cab.eta : void 0, true) + }) + }); + if (cab.eta < lowestETA) { + lowestETA = cab.eta; + } + return this.cabs.push(point); + }, this); + processData = __bind(function(data, textStatus, jqXHR) { + if (this.status === "ready") { + this.removeCabs(); + if (data.sorry) { + $("#status_message").html(data.sorry).fadeIn(); + } else { + _.each(data.driverLocations, showCab); + $("#status_message").html(t("Nearest Cab Message", { + minutes: app.helpers.FormatSeconds(lowestETA, true) + })).fadeIn(); + } + if (Backbone.history.fragment === "!/request") { + return _.delay(this.showCabs, this.pollInterval); + } + } + }, this); + return this.AjaxCall(ask, processData, attrs); + case "StatusClient": + processData = __bind(function(data, textStatus, jqXHR) { + var bounds, cabLocation, locationSaved, point, userLocation; + if (data.messageType === "OK") { + switch (data.status) { + case "completed": + this.removeCabs(); + this.setStatus("rate"); + return this.fetchTripDetails(data.tripID); + case "open": + return this.setStatus("ready"); + case "begintrip": + this.setStatus("riding"); + cabLocation = new google.maps.LatLng(data.latitude, data.longitude); + this.removeCabs(); + this.pickup_icon.setMap(null); + point = new google.maps.Marker({ + position: cabLocation, + map: this.map, + icon: this.cabMarker + }); + this.cabs.push(point); + this.map.panTo(point.getPosition()); + $("#rideName").html(data.driverName); + $("#ridePhone").html(data.driverMobile); + $("#ride_address_wrapper").hide(); + if (Backbone.history.fragment === "!/request") { + return _.delay(this.AskDispatch, this.pollInterval, "StatusClient"); + } + break; + case "pending": + this.setStatus("searching"); + if (Backbone.history.fragment === "!/request") { + return _.delay(this.AskDispatch, this.pollInterval, "StatusClient"); + } + break; + case "accepted": + case "arrived": + if (data.status === "accepted") { + this.setStatus("waiting"); + $("#status_message").html(t("Arrival ETA Message", { + minutes: app.helpers.FormatSeconds(data.eta, true) + })); + } else { + this.setStatus("arriving"); + $("#status_message").html(t("Arriving Now Message")); + } + userLocation = new google.maps.LatLng(data.pickupLocation.latitude, data.pickupLocation.longitude); + cabLocation = new google.maps.LatLng(data.latitude, data.longitude); + this.pickup_icon.setPosition(userLocation); + this.removeCabs(); + $("#rideName").html(data.driverName); + $("#ridePhone").html(data.driverMobile); + if ($("#rideAddress").html() === "") { + locationSaved = false; + _.each(USER.locations, __bind(function(location) { + if (parseFloat(location.latitude) === parseFloat(data.pickupLocation.latitude) && parseFloat(location.longitude) === parseFloat(data.pickupLocation.longitude)) { + return locationSaved = true; + } + }, this)); + if (locationSaved) { + $("#addToFavButton").hide(); + } + $("#pickupLat").val(data.pickupLocation.latitude); + $("#pickupLng").val(data.pickupLocation.longitude); + this.geocoder.geocode({ + location: userLocation + }, __bind(function(result, status) { + $("#rideAddress").html(result[0].formatted_address); + return $("#favLocNickname").val("" + result[0].address_components[0].short_name + " " + result[0].address_components[1].short_name); + }, this)); + } + point = new google.maps.Marker({ + position: cabLocation, + map: this.map, + icon: this.cabMarker + }); + this.cabs.push(point); + bounds = bounds = new google.maps.LatLngBounds(); + bounds.extend(cabLocation); + bounds.extend(userLocation); + this.map.fitBounds(bounds); + if (Backbone.history.fragment === "!/request") { + return _.delay(this.AskDispatch, this.pollInterval, "StatusClient"); + } + } + } + }, this); + return this.AjaxCall(ask, processData); + case "Pickup": + attrs = { + latitude: this.pickup_icon.getPosition().lat(), + longitude: this.pickup_icon.getPosition().lng() + }; + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "Error") { + return $("#status_message").html(data.description); + } else { + return this.AskDispatch("StatusClient"); + } + }, this); + return this.AjaxCall(ask, processData, attrs); + case "PickupCanceledClient": + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "OK") { + return this.setStatus("ready"); + } else { + return $("#status_message").html(data.description); + } + }, this); + return this.AjaxCall(ask, processData, attrs); + case "RatingDriver": + attrs = { + rating: options.rating + }; + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "OK") { + this.setStatus("init"); + } else { + $("status_message").html(t("Rating Driver Failed")); + } + return this.HideSpinner(); + }, this); + return this.AjaxCall(ask, processData, attrs); + case "Feedback": + attrs = { + message: options.message + }; + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "OK") { + return alert("rated"); + } + }, this); + return this.AjaxCall(ask, processData, attrs); + } + }; + ClientsRequestView.prototype.AjaxCall = function(type, successCallback, attrs) { + if (attrs == null) { + attrs = {}; + } + _.extend(attrs, { + token: USER.token, + messageType: type, + app: "client", + version: "1.0.60", + device: "web" + }); + return $.ajax({ + type: 'POST', + url: DISPATCH + "/", + processData: false, + data: JSON.stringify(attrs), + success: successCallback, + dataType: 'json', + error: __bind(function(jqXHR, textStatus, errorThrown) { + $("#status_message").html(errorThrown); + return this.HideSpinner(); + }, this) + }); + }; + return ClientsRequestView; + })(); +}).call(this); +}, "views/clients/settings": function(exports, require, module) {(function() { + var clientsSettingsTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsSettingsTemplate = require('templates/clients/settings'); + exports.ClientsSettingsView = (function() { + __extends(ClientsSettingsView, UberView); + function ClientsSettingsView() { + this.render = __bind(this.render, this); + this.initialize = __bind(this.initialize, this); + ClientsSettingsView.__super__.constructor.apply(this, arguments); + } + ClientsSettingsView.prototype.id = 'settings_view'; + ClientsSettingsView.prototype.className = 'view_container'; + ClientsSettingsView.prototype.events = { + 'submit #profile_pic_form': 'processPicUpload', + 'click #submit_pic': 'processPicUpload', + 'click a.setting_change': "changeTab", + 'submit #edit_info_form': "submitInfo", + 'click #change_password': 'changePass' + }; + ClientsSettingsView.prototype.divs = { + 'info_div': "Information", + 'pic_div': "Picture" + }; + ClientsSettingsView.prototype.pageTitle = t("Settings") + " | " + t("Uber"); + ClientsSettingsView.prototype.tabTitle = { + 'info_div': t("Information"), + 'pic_div': t("Picture") + }; + ClientsSettingsView.prototype.initialize = function() { + return this.mixin(require('web-lib/mixins/i18n_phone_form').i18nPhoneForm); + }; + ClientsSettingsView.prototype.render = function(type) { + if (type == null) { + type = "info"; + } + this.RefreshUserInfo(__bind(function() { + var $el, alphabet; + this.delegateEvents(); + this.HideSpinner(); + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + $el = $(this.el); + $(this.el).html(clientsSettingsTemplate({ + type: type + })); + $el.find("#" + type + "_div").show(); + $el.find("a[href='" + type + "_div']").parent().addClass("active"); + return document.title = "" + this.tabTitle[type + '_div'] + " " + this.pageTitle; + }, this)); + this.delegateEvents(); + return this; + }; + ClientsSettingsView.prototype.changeTab = function(e) { + var $eTarget, $el, div, link, pageDiv, _i, _j, _len, _len2, _ref, _ref2; + e.preventDefault(); + $eTarget = $(e.currentTarget); + this.ClearGlobalStatus(); + $el = $(this.el); + _ref = $el.find(".setting_change"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + $(link).parent().removeClass("active"); + } + $eTarget.parent().addClass("active"); + _ref2 = _.keys(this.divs); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + div = _ref2[_j]; + $el.find("#" + div).hide(); + } + pageDiv = $eTarget.attr('href'); + $el.find("#" + pageDiv).show(); + Backbone.history.navigate("!/settings/" + (this.divs[pageDiv].toLowerCase().replace(" ", "-")), false); + document.title = "" + this.tabTitle[pageDiv] + " " + this.pageTitle; + if (pageDiv === "loc_div") { + try { + google.maps.event.trigger(this.map, 'resize'); + return this.map.fitBounds(this.bounds); + } catch (_e) {} + } + }; + ClientsSettingsView.prototype.submitInfo = function(e) { + var $e, attrs, client, options; + $('#global_status').find('.success_message').text(''); + $('#global_status').find('.error_message').text(''); + $('.error_message').text(''); + e.preventDefault(); + $e = $(e.currentTarget); + attrs = $e.serializeToJson(); + attrs['mobile_country_id'] = this.$('#mobile_country_id').val(); + if (attrs['password'] === '') { + delete attrs['password']; + } + options = { + success: __bind(function(response) { + this.ShowSuccess(t("Information Update Succeeded")); + return this.RefreshUserInfo(); + }, this), + error: __bind(function(model, data) { + var errors; + if (data.status === 406) { + errors = JSON.parse(data.responseText); + return _.each(_.keys(errors), function(field) { + return $("#" + field).parent().find('span.error_message').text(errors[field]); + }); + } else { + return this.ShowError(t("Information Update Failed")); + } + }, this), + type: "PUT" + }; + client = new app.models.client({ + id: USER.id + }); + return client.save(attrs, options); + }; + ClientsSettingsView.prototype.changePass = function(e) { + e.preventDefault(); + $(e.currentTarget).hide(); + return $("#password").show(); + }; + ClientsSettingsView.prototype.processPicUpload = function(e) { + e.preventDefault(); + this.ShowSpinner("submit"); + return $.ajaxFileUpload({ + url: API + '/user_pictures', + secureuri: false, + fileElementId: 'picture', + data: { + token: USER.token + }, + dataType: 'json', + complete: __bind(function(data, status) { + this.HideSpinner(); + if (status === 'success') { + this.ShowSuccess(t("Picture Update Succeeded")); + return this.RefreshUserInfo(__bind(function() { + return $("#settingsProfPic").attr("src", USER.picture_url + ("?" + (Math.floor(Math.random() * 1000)))); + }, this)); + } else { + if (data.error) { + return this.ShowError(data.error); + } else { + return this.ShowError("Picture Update Failed"); + } + } + }, this) + }); + }; + return ClientsSettingsView; + })(); +}).call(this); +}, "views/clients/sign_up": function(exports, require, module) {(function() { + var clientsSignUpTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsSignUpTemplate = require('templates/clients/sign_up'); + exports.ClientsSignUpView = (function() { + __extends(ClientsSignUpView, UberView); + function ClientsSignUpView() { + ClientsSignUpView.__super__.constructor.apply(this, arguments); + } + ClientsSignUpView.prototype.id = 'signup_view'; + ClientsSignUpView.prototype.className = 'view_container'; + ClientsSignUpView.prototype.initialize = function() { + this.mixin(require('web-lib/mixins/i18n_phone_form').i18nPhoneForm); + return $('#location_country').live('change', function() { + if (!$('#mobile').val()) { + return $('#mobile_country').find("option[value=" + ($(this).val()) + "]").attr('selected', 'selected').end().trigger('change'); + } + }); + }; + ClientsSignUpView.prototype.events = { + 'submit form': 'signup', + 'click button': 'signup', + 'change #card_number': 'showCardType', + 'change #location_country': 'countryChange' + }; + ClientsSignUpView.prototype.render = function(invite) { + this.HideSpinner(); + $(this.el).html(clientsSignUpTemplate({ + invite: invite + })); + return this; + }; + ClientsSignUpView.prototype.signup = function(e) { + var $el, attrs, client, error_messages, options; + e.preventDefault(); + $el = $("form"); + $el.find('#terms_error').hide(); + if (!$el.find('#signup_terms input[type=checkbox]').attr('checked')) { + $('#spinner.submit').hide(); + $el.find('#terms_error').show(); + return; + } + error_messages = $el.find('.error_message').html(""); + attrs = { + first_name: $el.find('#first_name').val(), + last_name: $el.find('#last_name').val(), + email: $el.find('#email').val(), + password: $el.find('#password').val(), + location_country: $el.find('#location_country option:selected').attr('data-iso2'), + location: $el.find('#location').val(), + language: $el.find('#language').val(), + mobile_country: $el.find('#mobile_country option:selected').attr('data-iso2'), + mobile: $el.find('#mobile').val(), + card_number: $el.find('#card_number').val(), + card_expiration_month: $el.find('#card_expiration_month').val(), + card_expiration_year: $el.find('#card_expiration_year').val(), + card_code: $el.find('#card_code').val(), + use_case: $el.find('#use_case').val(), + promotion_code: $el.find('#promotion_code').val() + }; + options = { + statusCode: { + 200: function(response) { + $.cookie('token', response.token); + amplify.store('USERjson', response); + app.refreshMenu(); + return app.routers.clients.navigate('!/dashboard', true); + }, + 406: function(e) { + var error, errors, _i, _len, _ref, _results; + errors = JSON.parse(e.responseText); + _ref = _.keys(errors); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + error = _ref[_i]; + _results.push($('#' + error).parent().find('span').html($('#' + error).parent().find('span').html() + " " + errors[error])); + } + return _results; + } + }, + complete: __bind(function(response) { + return this.HideSpinner(); + }, this) + }; + client = new app.models.client; + $('.spinner#submit').show(); + return client.save(attrs, options); + }; + ClientsSignUpView.prototype.countryChange = function(e) { + var $e; + $e = $(e.currentTarget); + return $("#mobile_country").val($e.val()).trigger('change'); + }; + ClientsSignUpView.prototype.showCardType = function(e) { + var $el, reAmerica, reDiscover, reMaster, reVisa, validCard; + reVisa = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/; + reMaster = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/; + reAmerica = /^6011-?\d{4}-?\d{4}-?\d{4}$/; + reDiscover = /^3[4,7]\d{13}$/; + $el = $("#card_logos_signup"); + validCard = false; + if (e.currentTarget.value.match(reVisa)) { + $el.find("#overlay_left").css('width', "0px"); + return $el.find("#overlay_right").css('width', "75%"); + } else if (e.currentTarget.value.match(reMaster)) { + $el.find("#overlay_left").css('width', "25%"); + return $el.find("#overlay_right").css('width', "50%"); + } else if (e.currentTarget.value.match(reAmerica)) { + $el.find("#overlay_left").css('width', "75%"); + $el.find("#overlay_right").css('width', "0px"); + return console.log("amex"); + } else if (e.currentTarget.value.match(reDiscover)) { + $el.find("#overlay_left").css('width', "50%"); + return $el.find("#overlay_right").css('width', "25%"); + } else { + $el.find("#overlay_left").css('width', "0px"); + return $el.find("#overlay_right").css('width', "0px"); + } + }; + return ClientsSignUpView; + })(); +}).call(this); +}, "views/clients/trip_detail": function(exports, require, module) {(function() { + var clientsTripDetailTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsTripDetailTemplate = require('templates/clients/trip_detail'); + exports.TripDetailView = (function() { + __extends(TripDetailView, UberView); + function TripDetailView() { + this.resendReceipt = __bind(this.resendReceipt, this); + TripDetailView.__super__.constructor.apply(this, arguments); + } + TripDetailView.prototype.id = 'trip_detail_view'; + TripDetailView.prototype.className = 'view_container'; + TripDetailView.prototype.events = { + 'click a#fare_review': 'showFareReview', + 'click #fare_review_hide': 'hideFareReview', + 'submit #form_review_form': 'submitFareReview', + 'click #submit_fare_review': 'submitFareReview', + 'click .resendReceipt': 'resendReceipt' + }; + TripDetailView.prototype.render = function(id) { + if (id == null) { + id = 'invalid'; + } + this.ReadUserInfo(); + this.HideSpinner(); + this.model = new app.models.trip({ + id: id + }); + this.model.fetch({ + data: { + relationships: 'points,driver,city.country' + }, + dataType: 'json', + success: __bind(function() { + var trip; + trip = this.model; + $(this.el).html(clientsTripDetailTemplate({ + trip: trip + })); + this.RequireMaps(__bind(function() { + var bounds, endPos, map, myOptions, path, polyline, startPos; + bounds = new google.maps.LatLngBounds(); + path = []; + _.each(this.model.get('points'), __bind(function(point) { + path.push(new google.maps.LatLng(point.lat, point.lng)); + return bounds.extend(_.last(path)); + }, this)); + myOptions = { + zoom: 12, + center: path[0], + mapTypeId: google.maps.MapTypeId.ROADMAP, + zoomControl: false, + rotateControl: false, + panControl: false, + mapTypeControl: false, + scrollwheel: false + }; + map = new google.maps.Map(document.getElementById("trip_details_map"), myOptions); + map.fitBounds(bounds); + startPos = new google.maps.Marker({ + position: _.first(path), + map: map, + title: t("Trip started here"), + icon: 'https://uber-static.s3.amazonaws.com/marker_start.png' + }); + endPos = new google.maps.Marker({ + position: _.last(path), + map: map, + title: t("Trip ended here"), + icon: 'https://uber-static.s3.amazonaws.com/marker_end.png' + }); + startPos.setMap(map); + endPos.setMap(map); + polyline = new google.maps.Polyline({ + path: path, + strokeColor: '#003F87', + strokeOpacity: 1, + strokeWeight: 5 + }); + return polyline.setMap(map); + }, this)); + return this.HideSpinner(); + }, this) + }); + this.ShowSpinner('load'); + this.delegateEvents(); + return this; + }; + TripDetailView.prototype.showFareReview = function(e) { + e.preventDefault(); + $('#fare_review_box').slideDown(); + return $('#fare_review').hide(); + }; + TripDetailView.prototype.hideFareReview = function(e) { + e.preventDefault(); + $('#fare_review_box').slideUp(); + return $('#fare_review').show(); + }; + TripDetailView.prototype.submitFareReview = function(e) { + var attrs, errorMessage, id, options; + e.preventDefault(); + errorMessage = $(".error_message"); + errorMessage.hide(); + id = $("#tripid").val(); + this.model = new app.models.trip({ + id: id + }); + attrs = { + note: $('#form_review_message').val(), + note_type: 'client_fare_review' + }; + options = { + success: __bind(function(response) { + $(".success_message").fadeIn(); + return $("#fare_review_form_wrapper").slideUp(); + }, this), + error: __bind(function(error) { + return errorMessage.fadeIn(); + }, this) + }; + return this.model.save(attrs, options); + }; + TripDetailView.prototype.resendReceipt = function(e) { + var $e; + e.preventDefault(); + $e = $(e.currentTarget); + this.$(".resendReceiptSuccess").empty().show(); + this.$(".resentReceiptError").empty().show(); + e.preventDefault(); + $('#spinner').show(); + return $.ajax('/api/trips/func/resend_receipt', { + data: { + token: $.cookie('token'), + trip_id: this.model.id + }, + type: 'POST', + complete: __bind(function(xhr) { + var response; + response = JSON.parse(xhr.responseText); + $('#spinner').hide(); + switch (xhr.status) { + case 200: + this.$(".resendReceiptSuccess").html("Receipt has been emailed"); + return this.$(".resendReceiptSuccess").fadeOut(2000); + default: + this.$(".resendReceiptError").html("Receipt has failed to be emailed"); + return this.$(".resendReceiptError").fadeOut(2000); + } + }, this) + }); + }; + return TripDetailView; + })(); +}).call(this); +}, "views/shared/menu": function(exports, require, module) {(function() { + var menuTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + menuTemplate = require('templates/shared/menu'); + exports.SharedMenuView = (function() { + __extends(SharedMenuView, Backbone.View); + function SharedMenuView() { + SharedMenuView.__super__.constructor.apply(this, arguments); + } + SharedMenuView.prototype.id = 'menu_view'; + SharedMenuView.prototype.render = function() { + var type; + if ($.cookie('token') === null) { + type = 'guest'; + } else { + type = 'client'; + } + $(this.el).html(menuTemplate({ + type: type + })); + return this; + }; + return SharedMenuView; + })(); +}).call(this); +}, "web-lib/collections/countries": function(exports, require, module) {(function() { + var UberCollection; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberCollection = require('web-lib/uber_collection').UberCollection; + exports.CountriesCollection = (function() { + __extends(CountriesCollection, UberCollection); + function CountriesCollection() { + CountriesCollection.__super__.constructor.apply(this, arguments); + } + CountriesCollection.prototype.model = app.models.country; + CountriesCollection.prototype.url = '/countries'; + return CountriesCollection; + })(); +}).call(this); +}, "web-lib/collections/vehicle_types": function(exports, require, module) {(function() { + var UberCollection, vehicleType, _ref; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberCollection = require('web-lib/uber_collection').UberCollection; + vehicleType = (typeof app !== "undefined" && app !== null ? (_ref = app.models) != null ? _ref.vehicleType : void 0 : void 0) || require('models/vehicle_type').VehicleType; + exports.VehicleTypesCollection = (function() { + __extends(VehicleTypesCollection, UberCollection); + function VehicleTypesCollection() { + VehicleTypesCollection.__super__.constructor.apply(this, arguments); + } + VehicleTypesCollection.prototype.model = vehicleType; + VehicleTypesCollection.prototype.url = '/vehicle_types'; + VehicleTypesCollection.prototype.defaultColumns = ['id', 'created_at', 'updated_at', 'deleted_at', 'created_by_user_id', 'updated_by_user_id', 'city_id', 'type', 'make', 'model', 'capacity', 'minimum_year', 'actions']; + VehicleTypesCollection.prototype.tableColumns = function(cols) { + var actions, c, capacity, city_id, columnValues, created_at, created_by_user_id, deleted_at, headerRow, id, make, minimum_year, model, type, updated_at, updated_by_user_id, _i, _len; + id = { + sTitle: 'Id' + }; + created_at = { + sTitle: 'Created At (UTC)', + 'sType': 'string' + }; + updated_at = { + sTitle: 'Updated At (UTC)', + 'sType': 'string' + }; + deleted_at = { + sTitle: 'Deleted At (UTC)', + 'sType': 'string' + }; + created_by_user_id = { + sTitle: 'Created By' + }; + updated_by_user_id = { + sTitle: 'Updated By' + }; + city_id = { + sTitle: 'City' + }; + type = { + sTitle: 'Type' + }; + make = { + sTitle: 'Make' + }; + model = { + sTitle: 'Model' + }; + capacity = { + sTitle: 'Capacity' + }; + minimum_year = { + sTitle: 'Min. Year' + }; + actions = { + sTitle: 'Actions' + }; + columnValues = { + id: id, + created_at: created_at, + updated_at: updated_at, + deleted_at: deleted_at, + created_by_user_id: created_by_user_id, + updated_by_user_id: updated_by_user_id, + city_id: city_id, + type: type, + make: make, + model: model, + capacity: capacity, + minimum_year: minimum_year, + actions: actions + }; + headerRow = []; + for (_i = 0, _len = cols.length; _i < _len; _i++) { + c = cols[_i]; + if (columnValues[c]) { + headerRow.push(columnValues[c]); + } + } + return headerRow; + }; + return VehicleTypesCollection; + })(); +}).call(this); +}, "web-lib/helpers": function(exports, require, module) {(function() { + var __indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === item) return i; + } + return -1; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + exports.helpers = { + pin: function(num, color) { + if (color == null) { + color = 'FF0000'; + } + return ""; + }, + reverseGeocode: function(latitude, longitude) { + if (latitude && longitude) { + return "" + latitude + ", " + longitude + ""; + } else { + return ''; + } + }, + linkedName: function(model) { + var first_name, id, last_name, role, url; + role = model.role || model.get('role'); + id = model.id || model.get('id'); + first_name = model.first_name || model.get('first_name'); + last_name = model.last_name || model.get('last_name'); + url = "/" + role + "s/" + id; + return "" + first_name + " " + last_name + ""; + }, + linkedVehicle: function(vehicle, vehicleType) { + return " " + (vehicleType != null ? vehicleType.get('make') : void 0) + " " + (vehicleType != null ? vehicleType.get('model') : void 0) + " " + (vehicle.get('year')) + " "; + }, + linkedUserId: function(userType, userId) { + return "" + userType + " " + userId + ""; + }, + timeDelta: function(start, end) { + var delta; + if (typeof start === 'string') { + start = this.parseDate(start); + } + if (typeof end === 'string') { + end = this.parseDate(end); + } + if (end && start) { + delta = end.getTime() - start.getTime(); + return this.formatSeconds(delta / 1000); + } else { + return '00:00'; + } + }, + formatSeconds: function(s) { + var minutes, seconds; + s = Math.floor(s); + minutes = Math.floor(s / 60); + seconds = s - minutes * 60; + return "" + (this.leadingZero(minutes)) + ":" + (this.leadingZero(seconds)); + }, + formatCurrency: function(strValue, reverseSign, currency) { + var currency_locale, lc, mf; + if (reverseSign == null) { + reverseSign = false; + } + if (currency == null) { + currency = null; + } + strValue = String(strValue); + if (reverseSign) { + strValue = ~strValue.indexOf('-') ? strValue.split('-').join('') : ['-', strValue].join(''); + } + currency_locale = i18n.currencyToLocale[currency]; + try { + if (!(currency_locale != null) || currency_locale === i18n.locale) { + return i18n.jsworld.mf.format(strValue); + } else { + lc = new jsworld.Locale(POSIX_LC[currency_locale]); + mf = new jsworld.MonetaryFormatter(lc); + return mf.format(strValue); + } + } catch (error) { + i18n.log(error); + return strValue; + } + }, + formatTripFare: function(trip, type) { + var _ref, _ref2; + if (type == null) { + type = "fare"; + } + if (!trip.get('fare')) { + return 'n/a'; + } + if (((_ref = trip.get('fare_breakdown_local')) != null ? _ref.currency : void 0) != null) { + return app.helpers.formatCurrency(trip.get("" + type + "_local"), false, (_ref2 = trip.get('fare_breakdown_local')) != null ? _ref2.currency : void 0); + } else if (trip.get("" + type + "_string") != null) { + return trip.get("" + type + "_string"); + } else if (trip.get("" + type + "_local") != null) { + return trip.get("" + type + "_local"); + } else { + return 'n/a'; + } + }, + formatPhoneNumber: function(phoneNumber, countryCode) { + if (countryCode == null) { + countryCode = "+1"; + } + if (phoneNumber != null) { + phoneNumber = String(phoneNumber); + switch (countryCode) { + case '+1': + return countryCode + ' ' + phoneNumber.substring(0, 3) + '-' + phoneNumber.substring(3, 6) + '-' + phoneNumber.substring(6, 10); + case '+33': + return countryCode + ' ' + phoneNumber.substring(0, 1) + ' ' + phoneNumber.substring(1, 3) + ' ' + phoneNumber.substring(3, 5) + ' ' + phoneNumber.substring(5, 7) + ' ' + phoneNumber.substring(7, 9); + default: + countryCode + phoneNumber; + } + } + return "" + countryCode + " " + phoneNumber; + }, + parseDate: function(d, cityTime, tz) { + var city_filter, parsed, _ref; + if (cityTime == null) { + cityTime = true; + } + if (tz == null) { + tz = null; + } + if (((_ref = !d.substr(-6, 1)) === '+' || _ref === '-') || d.length === 19) { + d += '+00:00'; + } + if (/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/.test(d)) { + parsed = d.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/); + d = new Date(); + d.setUTCFullYear(parsed[1]); + d.setUTCMonth(parsed[2] - 1); + d.setUTCDate(parsed[3]); + d.setUTCHours(parsed[4]); + d.setUTCMinutes(parsed[5]); + d.setUTCSeconds(parsed[6]); + } else { + d = Date.parse(d); + } + if (typeof d === 'number') { + d = new Date(d); + } + d = new timezoneJS.Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), 'Etc/UTC'); + if (tz) { + d.convertToTimezone(tz); + } else if (cityTime) { + city_filter = $.cookie('city_filter'); + if (city_filter) { + tz = $("#city_filter option[value=" + city_filter + "]").attr('data-timezone'); + if (tz) { + d.convertToTimezone(tz); + } + } + } + return d; + }, + dateToTimezone: function(d) { + var city_filter, tz; + d = new timezoneJS.Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), 'Etc/UTC'); + city_filter = $.cookie('city_filter'); + if (city_filter) { + tz = $("#city_filter option[value=" + city_filter + "]").attr('data-timezone'); + d.convertToTimezone(tz); + } + return d; + }, + fixAMPM: function(d, formatted) { + if (d.hours >= 12) { + return formatted.replace(/\b[AP]M\b/, 'PM'); + } else { + return formatted.replace(/\b[AP]M\b/, 'AM'); + } + }, + formatDate: function(d, time, timezone) { + var formatted; + if (time == null) { + time = true; + } + if (timezone == null) { + timezone = null; + } + d = this.parseDate(d, true, timezone); + formatted = time ? ("" + (i18n.jsworld.dtf.formatDate(d)) + " ") + this.formatTime(d, d.getTimezoneInfo()) : i18n.jsworld.dtf.formatDate(d); + return this.fixAMPM(d, formatted); + }, + formatDateLong: function(d, time, timezone) { + if (time == null) { + time = true; + } + if (timezone == null) { + timezone = null; + } + d = this.parseDate(d, true, timezone); + timezone = d.getTimezoneInfo().tzAbbr; + if (time) { + return (i18n.jsworld.dtf.formatDateTime(d)) + (" " + timezone); + } else { + return i18n.jsworld.dtf.formatDate(d); + } + }, + formatTimezoneJSDate: function(d) { + var day, hours, jsDate, minutes, month, year; + year = d.getFullYear(); + month = this.leadingZero(d.getMonth()); + day = this.leadingZero(d.getDate()); + hours = this.leadingZero(d.getHours()); + minutes = this.leadingZero(d.getMinutes()); + jsDate = new Date(year, month, day, hours, minutes, 0); + return jsDate.toDateString(); + }, + formatTime: function(d, timezone) { + var formatted; + if (timezone == null) { + timezone = null; + } + formatted = ("" + (i18n.jsworld.dtf.formatTime(d))) + (timezone != null ? " " + (timezone != null ? timezone.tzAbbr : void 0) : ""); + return this.fixAMPM(d, formatted); + }, + formatISODate: function(d) { + var pad; + pad = function(n) { + if (n < 10) { + return '0' + n; + } + return n; + }; + return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) + 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) + 'Z'; + }, + formatExpDate: function(d) { + var month, year; + d = this.parseDate(d); + year = d.getFullYear(); + month = this.leadingZero(d.getMonth() + 1); + return "" + year + "-" + month; + }, + formatLatLng: function(lat, lng, precision) { + if (precision == null) { + precision = 8; + } + return parseFloat(lat).toFixed(precision) + ',' + parseFloat(lng).toFixed(precision); + }, + leadingZero: function(num) { + if (num < 10) { + return "0" + num; + } else { + return num; + } + }, + roundNumber: function(num, dec) { + return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec); + }, + notesToHTML: function(notes) { + var i, note, notesHTML, _i, _len; + notesHTML = ''; + i = 1; + if (notes) { + for (_i = 0, _len = notes.length; _i < _len; _i++) { + note = notes[_i]; + notesHTML += "" + note['userid'] + "     " + (this.formatDate(note['created_at'])) + "

    " + note['note'] + "

    "; + notesHTML += "
    "; + } + } + return notesHTML.replace("'", '"e'); + }, + formatPhone: function(n) { + var parts, phone, regexObj; + n = "" + n; + regexObj = /^(?:\+?1[-. ]?)?(?:\(?([0-9]{3})\)?[-. ]?)?([0-9]{3})[-. ]?([0-9]{4})$/; + if (regexObj.test(n)) { + parts = n.match(regexObj); + phone = ""; + if (parts[1]) { + phone += "(" + parts[1] + ") "; + } + phone += "" + parts[2] + "-" + parts[3]; + } else { + phone = n; + } + return phone; + }, + usStates: ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'District of Columbia', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'], + onboardingPages: ['applied', 'ready_to_interview', 'pending_interview', 'interviewed', 'accepted', 'ready_to_onboard', 'pending_onboarding', 'active', 'waitlisted', 'rejected'], + driverBreadCrumb: function(loc, model) { + var onboardingPage, out, _i, _len, _ref; + out = "Drivers > "; + if (!(model != null)) { + out += ""; + } else { + out += "" + (this.onboardingUrlToName(model.get('driver_status'))) + ""; + out += " > " + (this.linkedName(model)) + " (" + (model.get('role')) + ") #" + (model.get('id')); + } + return out; + }, + onboardingUrlToName: function(url) { + return url != null ? url.replace(/_/g, " ").replace(/(^|\s)([a-z])/g, function(m, p1, p2) { + return p1 + p2.toUpperCase(); + }) : void 0; + }, + formatVehicle: function(vehicle) { + if (vehicle.get('make') && vehicle.get('model') && vehicle.get('license_plate')) { + return "" + (vehicle.get('make')) + " " + (vehicle.get('model')) + " (" + (vehicle.get('license_plate')) + ")"; + } + }, + docArbitraryFields: function(docName, cityDocs) { + var doc, field, out, _i, _j, _len, _len2, _ref; + out = ""; + for (_i = 0, _len = cityDocs.length; _i < _len; _i++) { + doc = cityDocs[_i]; + if (doc.name === docName && __indexOf.call(_.keys(doc), "metaFields") >= 0) { + _ref = doc.metaFields; + for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) { + field = _ref[_j]; + out += "" + field.label + ":
    "; + } + } + } + return out; + }, + capitaliseFirstLetter: function(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + }, + createDocUploadForm: function(docName, driverId, vehicleId, cityMeta, vehicleName, expirationRequired) { + var ddocs, expDropdowns, pdocs, vdocs; + if (driverId == null) { + driverId = "None"; + } + if (vehicleId == null) { + vehicleId = "None"; + } + if (cityMeta == null) { + cityMeta = []; + } + if (vehicleName == null) { + vehicleName = false; + } + if (expirationRequired == null) { + expirationRequired = false; + } + ddocs = cityMeta["driverRequiredDocs"] || []; + pdocs = cityMeta["partnerRequiredDocs"] || []; + vdocs = cityMeta["vehicleRequiredDocs"] || []; + expDropdowns = "Expiration Date:\n -\n"; + return " \n
    \n \n \n \n\n
    \n " + (vehicleName ? vehicleName : "") + " " + docName + "\n
    \n\n
    \n \n
    \n\n
    \n " + (expirationRequired ? expDropdowns : "") + "\n
    \n\n
    \n " + (app.helpers.docArbitraryFields(docName, _.union(ddocs, pdocs, vdocs))) + "\n
    \n\n
    \n \n
    \n\n
    \n"; + }, + countrySelector: function(name, options) { + var countries, countryCodePrefix, defaultOptions; + if (options == null) { + options = {}; + } + defaultOptions = { + selectedKey: 'telephone_code', + selectedValue: '+1', + silent: false + }; + _.extend(defaultOptions, options); + options = defaultOptions; + countries = new app.collections.countries(); + countries.fetch({ + data: { + limit: 300 + }, + success: function(countries) { + var $option, $select, country, selected, _i, _len, _ref; + selected = false; + _ref = countries.models || []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + country = _ref[_i]; + $select = $("select[name=" + name + "]"); + $option = $('').val(country.id).attr('data-iso2', country.get('iso2')).attr('data-prefix', country.get('telephone_code')).html(country.get('name')); + if (country.get(options.selectedKey) === options.selectedValue && !selected) { + selected = true; + $option.attr('selected', 'selected'); + } + $select.append($option); + } + if (selected && !options.silent) { + return $select.val(options.selected).trigger('change'); + } + } + }); + countryCodePrefix = options.countryCodePrefix ? "data-country-code-prefix='" + options.countryCodePrefix + "'" : ''; + return ""; + }, + missingDocsOnDriver: function(driver) { + var city, docsReq, documents, partnerDocs; + city = driver.get('city'); + documents = driver.get('documents'); + if ((city != null) && (documents != null)) { + docsReq = _.pluck(city != null ? city.get('meta')["driverRequiredDocs"] : void 0, "name"); + if (driver.get('role') === "partner") { + partnerDocs = _.pluck(city != null ? city.get('meta')["partnerRequiredDocs"] : void 0, "name"); + docsReq = _.union(docsReq, partnerDocs); + } + return _.reject(docsReq, __bind(function(doc) { + return __indexOf.call((documents != null ? documents.pluck("name") : void 0) || [], doc) >= 0; + }, this)); + } else { + return []; + } + } + }; +}).call(this); +}, "web-lib/i18n": function(exports, require, module) {(function() { + exports.i18n = { + defaultLocale: 'en_US', + cookieName: '_LOCALE_', + locales: { + 'en_US': "English (US)", + 'fr_FR': "Français" + }, + currencyToLocale: { + 'USD': 'en_US', + 'EUR': 'fr_FR' + }, + logglyKey: 'd2d5a9bc-7ebe-4538-a180-81e62c705b1b', + logglyHost: 'https://logs.loggly.com', + init: function() { + this.castor = new window.loggly({ + url: this.logglyHost + '/inputs/' + this.logglyKey + '?rt=1', + level: 'error' + }); + this.setLocale($.cookie(this.cookieName) || this.defaultLocale); + window.t = _.bind(this.t, this); + this.loadLocaleTranslations(this.locale); + if (!(this[this.defaultLocale] != null)) { + return this.loadLocaleTranslations(this.defaultLocale); + } + }, + loadLocaleTranslations: function(locale) { + var loadPaths, path, _i, _len, _results; + loadPaths = ['web-lib/translations/' + locale, 'web-lib/translations/' + locale.slice(0, 2), 'translations/' + locale, 'translations/' + locale.slice(0, 2)]; + _results = []; + for (_i = 0, _len = loadPaths.length; _i < _len; _i++) { + path = loadPaths[_i]; + locale = path.substring(path.lastIndexOf('/') + 1); + if (this[locale] == null) { + this[locale] = {}; + } + _results.push((function() { + try { + return _.extend(this[locale], require(path).translations); + } catch (error) { + + } + }).call(this)); + } + return _results; + }, + getLocale: function() { + return this.locale; + }, + setLocale: function(locale) { + var message, parts, _ref; + parts = locale.split('_'); + this.locale = parts[0].toLowerCase(); + if (parts.length > 1) { + this.locale += "_" + (parts[1].toUpperCase()); + } + if (this.locale) { + $.cookie(this.cookieName, this.locale, { + path: '/', + domain: '.uber.com' + }); + } + try { + ((_ref = this.jsworld) != null ? _ref : this.jsworld = {}).lc = new jsworld.Locale(POSIX_LC[this.locale]); + this.jsworld.mf = new jsworld.MonetaryFormatter(this.jsworld.lc); + this.jsworld.nf = new jsworld.NumericFormatter(this.jsworld.lc); + this.jsworld.dtf = new jsworld.DateTimeFormatter(this.jsworld.lc); + this.jsworld.np = new jsworld.NumericParser(this.jsworld.lc); + this.jsworld.mp = new jsworld.MonetaryParser(this.jsworld.lc); + return this.jsworld.dtp = new jsworld.DateTimeParser(this.jsworld.lc); + } catch (error) { + message = 'JsWorld error with locale: ' + this.locale; + return this.log({ + message: message, + error: error + }); + } + }, + getTemplate: function(id) { + var _ref, _ref2; + return ((_ref = this[this.locale]) != null ? _ref[id] : void 0) || ((_ref2 = this[this.locale.slice(0, 2)]) != null ? _ref2[id] : void 0); + }, + getTemplateDefault: function(id) { + var _ref, _ref2; + return ((_ref = this[this.defaultLocale]) != null ? _ref[id] : void 0) || ((_ref2 = this[this.defaultLocale.slice(0, 2)]) != null ? _ref2[id] : void 0); + }, + getTemplateOrDefault: function(id) { + return this.getTemplate(id) || this.getTemplateDefault(id); + }, + t: function(id, vars) { + var errStr, locale, template; + if (vars == null) { + vars = {}; + } + locale = this.getLocale(); + template = this.getTemplate(id); + if (template == null) { + if (/dev|test/.test(window.location.host)) { + template = "(?) " + id; + } else { + template = this.getTemplateDefault(id); + } + errStr = "Missing [" + locale + "] translation for [" + id + "] at [" + window.location.hash + "] - Default template is [" + template + "]"; + this.log({ + error: errStr, + locale: locale, + id: id, + defaultTemplate: template + }); + } + if (template) { + return _.template(template, vars); + } else { + return id; + } + }, + log: function(error) { + if (/dev/.test(window.location.host)) { + if ((typeof console !== "undefined" && console !== null ? console.log : void 0) != null) { + return console.log(error); + } + } else { + _.extend(error, { + host: window.location.host, + hash: window.location.hash + }); + return this.castor.error(JSON.stringify(error)); + } + } + }; +}).call(this); +}, "web-lib/mixins/i18n_phone_form": function(exports, require, module) {(function() { + exports.i18nPhoneForm = { + _events: { + 'change select[data-country-code-prefix]': 'setCountryCodePrefix' + }, + setCountryCodePrefix: function(e) { + var $el, prefix; + $el = $(e.currentTarget); + prefix = $el.find('option:selected').attr('data-prefix'); + return $("#" + ($el.attr('data-country-code-prefix'))).text(prefix); + } + }; +}).call(this); +}, "web-lib/models/country": function(exports, require, module) {(function() { + var UberModel; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberModel = require('web-lib/uber_model').UberModel; + exports.Country = (function() { + __extends(Country, UberModel); + function Country() { + Country.__super__.constructor.apply(this, arguments); + } + Country.prototype.url = function() { + if (this.id) { + return "/countries/" + this.id; + } else { + return '/countries'; + } + }; + return Country; + })(); +}).call(this); +}, "web-lib/models/vehicle_type": function(exports, require, module) {(function() { + var UberModel; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberModel = require('web-lib/uber_model').UberModel; + exports.VehicleType = (function() { + __extends(VehicleType, UberModel); + function VehicleType() { + this.toString = __bind(this.toString, this); + VehicleType.__super__.constructor.apply(this, arguments); + } + VehicleType.prototype.endpoint = 'vehicle_types'; + VehicleType.prototype.toTableRow = function(cols) { + var actions, c, capacity, city_id, columnValues, created_at, created_by_user_id, deleted_at, id, make, minimum_year, model, rows, type, updated_at, updated_by_user_id, _i, _len, _ref; + id = "" + (this.get('id')) + ""; + if (this.get('created_at')) { + created_at = app.helpers.formatDate(this.get('created_at')); + } + if (this.get('updated_at')) { + updated_at = app.helpers.formatDate(this.get('updated_at')); + } + if (this.get('deleted_at')) { + deleted_at = app.helpers.formatDate(this.get('deleted_at')); + } + created_by_user_id = "" + (this.get('created_by_user_id')) + ""; + updated_by_user_id = "" + (this.get('updated_by_user_id')) + ""; + city_id = (_ref = this.get('city')) != null ? _ref.get('display_name') : void 0; + type = this.get('type'); + make = this.get('make'); + model = this.get('model'); + capacity = this.get('capacity'); + minimum_year = this.get('minimum_year'); + actions = "Show"; + if (!this.get('deleted_at')) { + actions += " Edit"; + actions += " Delete"; + } + columnValues = { + id: id, + created_at: created_at, + updated_at: updated_at, + deleted_at: deleted_at, + created_by_user_id: created_by_user_id, + updated_by_user_id: updated_by_user_id, + city_id: city_id, + type: type, + make: make, + model: model, + capacity: capacity, + minimum_year: minimum_year, + actions: actions + }; + rows = []; + for (_i = 0, _len = cols.length; _i < _len; _i++) { + c = cols[_i]; + rows.push(columnValues[c] ? columnValues[c] : '-'); + } + return rows; + }; + VehicleType.prototype.toString = function() { + return this.get('make') + ' ' + this.get('model') + ' ' + this.get('type') + (" (" + (this.get('capacity')) + ")"); + }; + return VehicleType; + })(); +}).call(this); +}, "web-lib/templates/footer": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var locale, title, _ref; + __out.push('\n\n\n\n\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "web-lib/translations/en": function(exports, require, module) {(function() { + exports.translations = { + "Info": "Info", + "Learn More": "Learn More", + "Pricing": "Pricing", + "FAQ": "FAQ", + "Support": "Support", + "Support & FAQ": "Support & FAQ", + "Contact Us": "Contact Us", + "Jobs": "Jobs", + "Phones": "Phones", + "Text Message": "Text Message", + "iPhone": "iPhone", + "Android": "Android", + "Drivers": "Drivers", + "Apply": "Apply", + "Sign In": "Sign In", + "Social": "Social", + "Twitter": "Twitter", + "Facebook": "Facebook", + "Blog": "Blog", + "Legal": "Legal", + "Company_Footer": "Company", + "Privacy Policy": "Privacy Policy", + "Terms": "Terms", + "Copyright © Uber Technologies, Inc.": "Copyright © Uber Technologies, Inc.", + "Language:": "Language:", + "Apply to Drive": "Apply to Drive", + "Expiration": "Expiration", + "Fare": "Fare", + "Driver": "Driver ", + "Dashboard": "Dashboard", + "Forgot Password": "Forgot Password", + "Trip Details": "Trip Details", + "Save": "Save", + "Cancel": "Cancel", + "Edit": "Edit", + "Password": "Password", + "First Name": "First Name", + "Last Name": "Last Name", + "Email Address": "Email Address", + "Submit": "Submit", + "Mobile Number": "Mobile Number", + "Zip Code": "Zip Code", + "Sign Out": "Sign Out", + "Confirm Email Message": "Attempting to confirm email...", + "Upload": "Upload", + "Rating": "Rating", + "Pickup Time": "Pickup Time", + "2011": "2011", + "2012": "2012", + "2013": "2013", + "2014": "2014", + "2015": "2015", + "2016": "2016", + "2017": "2017", + "2018": "2018", + "2019": "2019", + "2020": "2020", + "2021": "2021", + "2022": "2022", + "01": "01", + "02": "02", + "03": "03", + "04": "04", + "05": "05", + "06": "06", + "07": "07", + "08": "08", + "09": "09", + "10": "10", + "11": "11", + "12": "12" + }; +}).call(this); +}, "web-lib/translations/fr": function(exports, require, module) {(function() { + exports.translations = { + "Info": "Info", + "Learn More": "En Savoir Plus", + "Pricing": "Calcul du Prix", + "Support & FAQ": "Aide & FAQ", + "Contact Us": "Contactez Nous", + "Jobs": "Emplois", + "Phones": "Téléphones", + "Text Message": "SMS", + "iPhone": "iPhone", + "Android": "Android", + "Apply to Drive": "Candidature Chauffeur", + "Sign In": "Connexion", + "Social": "Contact", + "Twitter": "Twitter", + "Facebook": "Facebook", + "Blog": "Blog", + "Privacy Policy": "Protection des Données Personelles", + "Terms": "Conditions Générales", + "Copyright © Uber Technologies, Inc.": "© Uber, Inc.", + "Language:": "Langue:", + "Forgot Password": "Mot de passe oublié", + "Company_Footer": "À Propos d'Uber", + "Expiration": "Expiration", + "Fare": "Tarif", + "Driver": "Chauffeur", + "Drivers": "Chauffeurs", + "Dashboard": "Tableau de bord", + "Forgot Password": "Mot de passe oublié", + "Forgot Password?": "Mot de passe oublié?", + "Trip Details": "Détails de la course", + "Save": "Enregistrer", + "Cancel": "Annuler", + "Edit": "Modifier", + "Password": "Mot de passe", + "First Name": "Prénom", + "Last Name": "Nom", + "Email Address": "E-mail", + "Submit": "Soumettre", + "Mobile Number": "Téléphone Portable", + "Zip Code": "Code Postal", + "Sign Out": "Se déconnecter", + "Confirm Email Message": "E-mail de confirmation", + "Upload": "Télécharger", + "Rating": "Notation", + "Pickup Time": "Heure de prise en charge", + "2011": "2011", + "2012": "2012", + "2013": "2013", + "2014": "2014", + "2015": "2015", + "2016": "2016", + "2017": "2017", + "2018": "2018", + "2019": "2019", + "2020": "2020", + "2021": "2021", + "2022": "2022", + "01": "01", + "02": "02", + "03": "03", + "04": "04", + "05": "05", + "06": "06", + "07": "07", + "08": "08", + "09": "09", + "10": "10", + "11": "11", + "12": "12" + }; +}).call(this); +}, "web-lib/uber_collection": function(exports, require, module) {(function() { + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + exports.UberCollection = (function() { + __extends(UberCollection, Backbone.Collection); + function UberCollection() { + UberCollection.__super__.constructor.apply(this, arguments); + } + UberCollection.prototype.parse = function(data) { + var model, tmp, _i, _in, _len, _out; + _in = data.resources || data; + _out = []; + if (data.meta) { + this.meta = data.meta; + } + for (_i = 0, _len = _in.length; _i < _len; _i++) { + model = _in[_i]; + tmp = new this.model; + tmp.set(tmp.parse(model)); + _out.push(tmp); + } + return _out; + }; + UberCollection.prototype.isRenderable = function() { + if (this.models.length) { + return true; + } + }; + UberCollection.prototype.toTableRows = function(cols) { + var tableRows; + tableRows = []; + _.each(this.models, function(model) { + return tableRows.push(model.toTableRow(cols)); + }); + return tableRows; + }; + return UberCollection; + })(); +}).call(this); +}, "web-lib/uber_model": function(exports, require, module) {(function() { + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === item) return i; + } + return -1; + }; + exports.UberModel = (function() { + __extends(UberModel, Backbone.Model); + function UberModel() { + this.refetch = __bind(this.refetch, this); + this.fetch = __bind(this.fetch, this); + this.save = __bind(this.save, this); + this.parse = __bind(this.parse, this); + UberModel.__super__.constructor.apply(this, arguments); + } + UberModel.prototype.endpoint = 'set_api_endpoint_in_subclass'; + UberModel.prototype.refetchOptions = {}; + UberModel.prototype.url = function(type) { + var endpoint_path; + endpoint_path = "/" + this.endpoint; + if (this.get('id')) { + return endpoint_path + ("/" + (this.get('id'))); + } else { + return endpoint_path; + } + }; + UberModel.prototype.isRenderable = function() { + var i, key, value, _ref; + i = 0; + _ref = this.attributes; + for (key in _ref) { + if (!__hasProp.call(_ref, key)) continue; + value = _ref[key]; + if (this.attributes.hasOwnProperty(key)) { + i += 1; + } + if (i > 1) { + return true; + } + } + return !(i === 1); + }; + UberModel.prototype.parse = function(response) { + var attrs, key, model, models, _i, _j, _k, _len, _len2, _len3, _ref, _ref2; + if (typeof response === 'object') { + _ref = _.intersection(_.keys(app.models), _.keys(response)); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + if (response[key]) { + attrs = this.parse(response[key]); + if (typeof attrs === 'object') { + response[key] = new app.models[key](attrs); + } + } + } + _ref2 = _.intersection(_.keys(app.collections), _.keys(response)); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + key = _ref2[_j]; + models = response[key]; + if (_.isArray(models)) { + response[key] = new app.collections[key]; + for (_k = 0, _len3 = models.length; _k < _len3; _k++) { + model = models[_k]; + attrs = app.collections[key].prototype.model.prototype.parse(model); + response[key].add(new response[key].model(attrs)); + } + } + } + } + return response; + }; + UberModel.prototype.save = function(attributes, options) { + var attr, _i, _j, _len, _len2, _ref, _ref2; + if (options == null) { + options = {}; + } + _ref = _.intersection(_.keys(app.models), _.keys(this.attributes)); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + attr = _ref[_i]; + if (typeof this.get(attr) === "object") { + this.unset(attr, { + silent: true + }); + } + } + _ref2 = _.intersection(_.keys(app.collections), _.keys(this.attributes)); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + attr = _ref2[_j]; + if (typeof this.get(attr) === "object") { + this.unset(attr, { + silent: true + }); + } + } + if ((options != null) && options.diff && (attributes != null) && attributes !== {}) { + attributes['id'] = this.get('id'); + attributes['token'] = this.get('token'); + this.clear({ + 'silent': true + }); + this.set(attributes, { + silent: true + }); + } + if (__indexOf.call(_.keys(options), "data") < 0 && __indexOf.call(_.keys(this.refetchOptions || {}), "data") >= 0) { + options.data = this.refetchOptions.data; + } + return Backbone.Model.prototype.save.call(this, attributes, options); + }; + UberModel.prototype.fetch = function(options) { + this.refetchOptions = options; + return Backbone.Model.prototype.fetch.call(this, options); + }; + UberModel.prototype.refetch = function() { + return this.fetch(this.refetchOptions); + }; + return UberModel; + })(); +}).call(this); +}, "web-lib/uber_router": function(exports, require, module) {(function() { + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + exports.UberRouter = (function() { + __extends(UberRouter, Backbone.Router); + function UberRouter() { + UberRouter.__super__.constructor.apply(this, arguments); + } + UberRouter.prototype.datePickers = function(format) { + if (format == null) { + format = "%Z-%m-%dT%H:%i:%s%:"; + } + $('.datepicker').AnyTime_noPicker(); + return $('.datepicker').AnyTime_picker({ + 'format': format, + 'formatUtcOffset': '%@' + }); + }; + UberRouter.prototype.autoGrowInput = function() { + return $('.editable input').autoGrowInput(); + }; + UberRouter.prototype.windowTitle = function(title) { + return $(document).attr('title', title); + }; + return UberRouter; + })(); +}).call(this); +}, "web-lib/uber_show_view": function(exports, require, module) {(function() { + var UberView; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + UberView = require('web-lib/uber_view').UberView; + exports.UberShowView = (function() { + __extends(UberShowView, UberView); + function UberShowView() { + UberShowView.__super__.constructor.apply(this, arguments); + } + UberShowView.prototype.view = 'show'; + UberShowView.prototype.events = { + 'click #edit': 'edit', + 'submit form': 'save', + 'click .cancel': 'cancel' + }; + UberShowView.prototype.errors = null; + UberShowView.prototype.showTemplate = null; + UberShowView.prototype.editTemplate = null; + UberShowView.prototype.initialize = function() { + if (this.init_hook) { + this.init_hook(); + } + _.bindAll(this, 'render'); + return this.model.bind('change', this.render); + }; + UberShowView.prototype.render = function() { + var $el; + $el = $(this.el); + this.selectView(); + if (this.view === 'show') { + $el.html(this.showTemplate({ + model: this.model + })); + } else if (this.view === 'edit') { + $el.html(this.editTemplate({ + model: this.model, + errors: this.errors || {}, + collections: this.collections || {} + })); + } else { + $el.html(this.newTemplate({ + model: this.model, + errors: this.errors || {}, + collections: this.collections || {} + })); + } + if (this.render_hook) { + this.render_hook(); + } + this.errors = null; + this.userIdsToLinkedNames(); + this.datePickers(); + return this.place(); + }; + UberShowView.prototype.selectView = function() { + var url; + if (this.options.urlRendering) { + url = window.location.hash; + if (url.match(/\/new/)) { + return this.view = 'new'; + } else if (url.match(/\/edit/)) { + return this.view = 'edit'; + } else { + return this.view = 'show'; + } + } + }; + UberShowView.prototype.edit = function(e) { + e.preventDefault(); + if (this.options.urlRendering) { + window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id') + '/edit'; + } else { + this.view = 'edit'; + } + return this.model.change(); + }; + UberShowView.prototype.save = function(e) { + var attributes, ele, form_attrs, _i, _len, _ref; + e.preventDefault(); + attributes = $(e.currentTarget).serializeToJson(); + form_attrs = {}; + _ref = $('input[type="radio"]'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + ele = _ref[_i]; + if ($(ele).is(':checked')) { + form_attrs[$(ele).attr('name')] = $(ele).attr('value'); + } + } + attributes = _.extend(attributes, form_attrs); + if (this.relationships) { + attributes = _.extend(attributes, { + relationships: this.relationships + }); + } + if (this.filter_attributes != null) { + this.filter_attributes(attributes); + } + return this.model.save(attributes, { + silent: true, + success: __bind(function(model) { + if (this.options.urlRendering) { + window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id'); + } else { + this.view = 'show'; + } + return this.flash('success', "Uber save!"); + }, this), + statusCode: { + 406: __bind(function(xhr) { + this.errors = JSON.parse(xhr.responseText); + return this.flash('error', 'That was not Uber.'); + }, this) + }, + error: __bind(function(model, xhr) { + var code, message, responseJSON, responseText; + code = xhr.status; + responseText = xhr.responseText; + if (responseText) { + responseJSON = JSON.parse(responseText); + } + if (responseJSON && (typeof responseJSON === 'object') && (responseJSON.hasOwnProperty('error'))) { + message = responseJSON.error; + } + return this.flash('error', (code || 'Unknown') + ' error' + (': ' + message || '')); + }, this), + complete: __bind(function() { + return this.model.change(); + }, this) + }); + }; + UberShowView.prototype.cancel = function(e) { + e.preventDefault(); + if (this.options.urlRendering) { + window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id'); + } else { + this.view = 'show'; + } + return this.model.fetch({ + silent: true, + complete: __bind(function() { + return this.model.change(); + }, this) + }); + }; + return UberShowView; + })(); +}).call(this); +}, "web-lib/uber_sync": function(exports, require, module) {(function() { + var methodType; + var __indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === item) return i; + } + return -1; + }; + methodType = { + create: 'POST', + update: 'PUT', + "delete": 'DELETE', + read: 'GET' + }; + exports.UberSync = function(method, model, options) { + var token; + options.type = methodType[method]; + options.url = _.isString(this.url) ? '/api' + this.url : '/api' + this.url(options.type); + options.data = _.extend({}, options.data); + if (__indexOf.call(_.keys(options.data), "city_id") < 0) { + if ($.cookie('city_filter')) { + _.extend(options.data, { + city_id: $.cookie('city_filter') + }); + } + } else { + delete options.data['city_id']; + } + if (options.type === 'POST' || options.type === 'PUT') { + _.extend(options.data, model.toJSON()); + } + token = $.cookie('token') ? $.cookie('token') : typeof USER !== "undefined" && USER !== null ? USER.get('token') : ""; + _.extend(options.data, { + token: token + }); + if (method === "delete") { + options.contentType = 'application/json'; + options.data = JSON.stringify(options.data); + } + return $.ajax(options); + }; +}).call(this); +}, "web-lib/uber_view": function(exports, require, module) {(function() { + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + exports.UberView = (function() { + __extends(UberView, Backbone.View); + function UberView() { + this.processDocumentUpload = __bind(this.processDocumentUpload, this); + UberView.__super__.constructor.apply(this, arguments); + } + UberView.prototype.className = 'view_container'; + UberView.prototype.hashId = function() { + return parseInt(location.hash.split('/')[2]); + }; + UberView.prototype.place = function(content) { + var $target; + $target = this.options.scope ? this.options.scope.find(this.options.selector) : $(this.options.selector); + $target[this.options.method || 'html'](content || this.el); + this.delegateEvents(); + $('#spinner').hide(); + return this; + }; + UberView.prototype.mixin = function(m, args) { + var events, self; + if (args == null) { + args = {}; + } + self = this; + events = m._events; + _.extend(this, m); + if (m.initialize) { + m.initialize(self, args); + } + return _.each(_.keys(events), function(key) { + var event, func, selector, split; + split = key.split(' '); + event = split[0]; + selector = split[1]; + func = events[key]; + return $(self.el).find(selector).live(event, function(e) { + return self[func](e); + }); + }); + }; + UberView.prototype.datePickers = function(format) { + if (format == null) { + format = "%Z-%m-%dT%H:%i:%s%:"; + } + $('.datepicker').AnyTime_noPicker(); + return $('.datepicker').AnyTime_picker({ + 'format': format, + 'formatUtcOffset': '%@' + }); + }; + UberView.prototype.dataTable = function(collection, selector, options, params, cols) { + var defaults; + if (selector == null) { + selector = 'table'; + } + if (options == null) { + options = {}; + } + if (params == null) { + params = {}; + } + if (cols == null) { + cols = []; + } + $(selector).empty(); + if (!cols.length) { + cols = collection.defaultColumns; + } + defaults = { + aoColumns: collection.tableColumns(cols), + bDestroy: true, + bSort: false, + bProcessing: true, + bFilter: false, + bServerSide: true, + bPaginate: true, + bScrollInfinite: true, + bScrollCollapse: true, + sScrollY: '600px', + iDisplayLength: 50, + fnServerData: function(source, data, callback) { + var defaultParams; + defaultParams = { + limit: data[4].value, + offset: data[3].value + }; + return collection.fetch({ + data: _.extend(defaultParams, params), + success: function() { + return callback({ + aaData: collection.toTableRows(cols), + iTotalRecords: collection.meta.count, + iTotalDisplayRecords: collection.meta.count + }); + }, + error: function() { + return new Error({ + message: 'Loading error.' + }); + } + }); + }, + fnRowCallback: function(nRow, aData, iDisplayIndex, iDisplayIndexFull) { + $('[data-tooltip]', nRow).qtip({ + content: { + attr: 'data-tooltip' + }, + style: { + classes: "ui-tooltip-light ui-tooltip-rounded ui-tooltip-shadow" + } + }); + return nRow; + } + }; + return $(this.el).find(selector).dataTable(_.extend(defaults, options)); + }; + UberView.prototype.dataTableLocal = function(collection, selector, options, params, cols) { + var $dataTable, defaults; + if (selector == null) { + selector = 'table'; + } + if (options == null) { + options = {}; + } + if (params == null) { + params = {}; + } + if (cols == null) { + cols = []; + } + $(selector).empty(); + if (!cols.length || cols.length === 0) { + cols = collection.defaultColumns; + } + defaults = { + aaData: collection.toTableRows(cols), + aoColumns: collection.tableColumns(cols), + bDestroy: true, + bSort: false, + bProcessing: true, + bFilter: false, + bScrollInfinite: true, + bScrollCollapse: true, + sScrollY: '600px', + iDisplayLength: -1 + }; + $dataTable = $(this.el).find(selector).dataTable(_.extend(defaults, options)); + _.delay(__bind(function() { + if ($dataTable && $dataTable.length > 0) { + return $dataTable.fnAdjustColumnSizing(); + } + }, this), 1); + return $dataTable; + }; + UberView.prototype.reverseGeocode = function() { + var $el; + return ''; + $el = $(this.el); + return this.requireMaps(function() { + var geocoder; + geocoder = new google.maps.Geocoder(); + return $el.find('[data-point]').each(function() { + var $this, latLng, point; + $this = $(this); + point = JSON.parse($this.attr('data-point')); + latLng = new google.maps.LatLng(point.latitude, point.longitude); + return geocoder.geocode({ + latLng: latLng + }, function(data, status) { + if (status === google.maps.GeocoderStatus.OK) { + return $this.text(data[0].formatted_address); + } + }); + }); + }); + }; + UberView.prototype.userIdsToLinkedNames = function() { + var $el; + $el = $(this.el); + return $el.find('a[data-user-id][data-user-type]').each(function() { + var $this, user, userType; + $this = $(this); + userType = $this.attr('data-user-type') === 'user' ? 'client' : $this.attr('data-user-type'); + user = new app.models[userType]({ + id: $this.attr('data-user-id') + }); + return user.fetch({ + success: function(user) { + return $this.html(app.helpers.linkedName(user)).attr('href', "!/" + user.role + "s/" + user.id); + }, + error: function() { + if ($this.attr('data-user-type') === 'user') { + user = new app.models['driver']({ + id: $this.attr('data-user-id') + }); + return user.fetch({ + success: function(user) { + return $this.html(app.helpers.linkedName(user)).attr('href', "!/driver/" + user.id); + } + }); + } + } + }); + }); + }; + UberView.prototype.selectedCity = function() { + var $selected, city, cityFilter; + cityFilter = $.cookie('city_filter'); + $selected = $("#city_filter option[value=" + cityFilter + "]"); + if (city_filter && $selected.length) { + return city = { + lat: parseFloat($selected.attr('data-lat')), + lng: parseFloat($selected.attr('data-lng')), + timezone: $selected.attr('data-timezone') + }; + } else { + return city = { + lat: 37.775, + lng: -122.45, + timezone: 'Etc/UTC' + }; + } + }; + UberView.prototype.updateModel = function(e, success) { + var $el, attrs, model, self; + e.preventDefault(); + $el = $(e.currentTarget); + self = this; + model = new this.model.__proto__.constructor({ + id: this.model.id + }); + attrs = {}; + $el.find('[name]').each(function() { + var $this; + $this = $(this); + return attrs["" + ($this.attr('name'))] = $this.val(); + }); + self.model.set(attrs); + $el.find('span.error').text(''); + return model.save(attrs, { + complete: function(xhr) { + var response; + response = JSON.parse(xhr.responseText); + switch (xhr.status) { + case 200: + self.model = model; + $el.find('[name]').val(''); + if (success) { + return success(); + } + break; + case 406: + return _.each(response, function(error, field) { + return $el.find("[name=" + field + "]").parent().find('span.error').text(error); + }); + default: + return this.unanticipatedError(response); + } + } + }); + }; + UberView.prototype.autoUpdateModel = function(e) { + var $el, arg, model, self, val; + $el = $(e.currentTarget); + val = $el.val(); + self = this; + if (val !== this.model.get($el.attr('id'))) { + arg = {}; + arg[$el.attr('id')] = $el.is(':checkbox') ? $el.is(':checked') ? 1 : 0 : val; + $('.editable span').empty(); + this.model.set(arg); + model = new this.model.__proto__.constructor({ + id: this.model.id + }); + return model.save(arg, { + complete: function(xhr) { + var key, response, _i, _len, _ref, _results; + response = JSON.parse(xhr.responseText); + switch (xhr.status) { + case 200: + self.flash('success', 'Saved!'); + return $el.blur(); + case 406: + self.flash('error', 'That was not Uber.'); + _ref = _.keys(response); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + _results.push($el.parent().find('span').html(response[key])); + } + return _results; + break; + default: + return self.unanticipatedError; + } + } + }); + } + }; + UberView.prototype.unanticipatedError = function(response) { + return self.flash('error', response); + }; + UberView.prototype.flash = function(type, text) { + var $banner; + $banner = $("." + type); + $banner.find('p').text(text).end().css('border', '1px solid #999').animate({ + top: 0 + }, 500); + return setTimeout(function() { + return $banner.animate({ + top: -$banner.outerHeight() + }, 500); + }, 3000); + }; + UberView.prototype.requireMaps = function(callback) { + if (typeof google !== 'undefined' && google.maps) { + return callback(); + } else { + return $.getScript("https://www.google.com/jsapi?key=" + CONFIG.googleJsApiKey, function() { + return google.load('maps', 3, { + callback: callback, + other_params: 'sensor=false&language=en' + }); + }); + } + }; + UberView.prototype.select_drop_down = function(model, key) { + var value; + value = model.get(key); + if (value) { + return $("select[id='" + key + "'] option[value='" + value + "']").attr('selected', 'selected'); + } + }; + UberView.prototype.processDocumentUpload = function(e) { + var $fi, $form, arbData, curDate, data, expDate, expM, expY, expiration, fileElementId, invalid; + e.preventDefault(); + $form = $(e.currentTarget); + $fi = $("input[type=file]", $form); + $(".validationError").removeClass("validationError"); + if (!$fi.val()) { + return $fi.addClass("validationError"); + } else { + fileElementId = $fi.attr('id'); + expY = $("select[name=expiration-year]", $form).val(); + expM = $("select[name=expiration-month]", $form).val(); + invalid = false; + if (expY && expM) { + expDate = new Date(expY, expM, 28); + curDate = new Date(); + if (expDate < curDate) { + invalid = true; + $(".expiration", $form).addClass("validationError"); + } + expiration = "" + expY + "-" + expM + "-28T23:59:59Z"; + } + arbData = {}; + $(".arbitraryField", $form).each(__bind(function(i, e) { + arbData[$(e).attr('name')] = $(e).val(); + if ($(e).val() === "") { + invalid = true; + return $(e).addClass("validationError"); + } + }, this)); + if (!invalid) { + data = { + token: $.cookie('token') || USER.get('token'), + name: $("input[name=fileName]", $form).val(), + meta: escape(JSON.stringify(arbData)), + user_id: $("input[name=driver_id]", $form).val(), + vehicle_id: $("input[name=vehicle_id]", $form).val() + }; + if (expiration) { + data['expiration'] = expiration; + } + $("#spinner").show(); + return $.ajaxFileUpload({ + url: '/api/documents', + secureuri: false, + fileElementId: fileElementId, + data: data, + complete: __bind(function(resp, status) { + var key, _i, _len, _ref, _results; + $("#spinner").hide(); + if (status === "success") { + if (this.model) { + this.model.refetch(); + } else { + USER.refetch(); + } + } + if (status === "error") { + _ref = _.keys(resp); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + _results.push($("*[name=" + key + "]", $form).addClass("validationError")); + } + return _results; + } + }, this) + }); + } + } + }; + return UberView; + })(); +}).call(this); +}, "web-lib/views/footer": function(exports, require, module) {(function() { + var footerTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + footerTemplate = require('web-lib/templates/footer'); + exports.SharedFooterView = (function() { + __extends(SharedFooterView, Backbone.View); + function SharedFooterView() { + SharedFooterView.__super__.constructor.apply(this, arguments); + } + SharedFooterView.prototype.id = 'footer_view'; + SharedFooterView.prototype.events = { + 'click .language': 'intl_set_cookie_locale' + }; + SharedFooterView.prototype.render = function() { + $(this.el).html(footerTemplate()); + this.delegateEvents(); + return this; + }; + SharedFooterView.prototype.intl_set_cookie_locale = function(e) { + var _ref; + i18n.setLocale(e != null ? (_ref = e.srcElement) != null ? _ref.id : void 0 : void 0); + return location.reload(); + }; + return SharedFooterView; + })(); +}).call(this); +}}); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/embed-tokens.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/embed-tokens.js new file mode 100755 index 00000000..61307eeb --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/embed-tokens.js @@ -0,0 +1,15 @@ +#! /usr/bin/env node + +global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); +var fs = require("fs"); +var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js + jsp = uglify.parser, + pro = uglify.uglify; + +var code = fs.readFileSync("embed-tokens.js", "utf8").replace(/^#.*$/mg, ""); +var ast = jsp.parse(code, null, true); + +// trololo +function fooBar() {} + +console.log(sys.inspect(ast, null, null)); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto.js new file mode 100644 index 00000000..945960c2 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto.js @@ -0,0 +1,26 @@ +function unique(arqw) { + var a = [], i, j + outer: for (i = 0; i < arqw.length; i++) { + for (j = 0; j < a.length; j++) { + if (a[j] == arqw[i]) { + continue outer + } + } + a[a.length] = arqw[i] + } + return a +} + + +function unique(arqw) { + var crap = [], i, j + outer: for (i = 0; i < arqw.length; i++) { + for (j = 0; j < crap.length; j++) { + if (crap[j] == arqw[i]) { + continue outer + } + } + crap[crap.length] = arqw[i] + } + return crap +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto2.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto2.js new file mode 100644 index 00000000..d13b2bc0 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto2.js @@ -0,0 +1,8 @@ +function q(qooo) { + var a; + foo: for(;;) { + a++; + if (something) break foo; + return qooo; + } +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/hoist.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/hoist.js new file mode 100644 index 00000000..4bf2b94d --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/hoist.js @@ -0,0 +1,33 @@ +function foo(arg1, arg2, arg3, arg4, arg5, arg6) { + var a = 5; + { + var d = 10, mak = 20, buz = 30; + var q = buz * 2; + } + if (moo) { + var a, b, c; + } + for (var arg1 = 0, d = 20; arg1 < 10; ++arg1) + console.log(arg3); + for (var i in mak) {} + for (j in d) {} + var d; + + function test() { + + }; + + //test(); + + (function moo(first, second){ + console.log(first); + })(1); + + (function moo(first, second){ + console.log(moo()); + })(1); +} + + +var foo; +var bar; diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument.js new file mode 100644 index 00000000..c6a9d798 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument.js @@ -0,0 +1,97 @@ +// sample on how to use the parser and walker API to instrument some code + +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +function instrument(code) { + var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want + // to have start/end tokens embedded in the + // statements + var w = pro.ast_walker(); + + // we're gonna need this to push elements that we're currently looking at, to avoid + // endless recursion. + var analyzing = []; + function do_stat() { + var ret; + if (this[0].start && analyzing.indexOf(this) < 0) { + // without the `analyzing' hack, w.walk(this) would re-enter here leading + // to infinite recursion + analyzing.push(this); + ret = [ "splice", // XXX: "block" is safer + [ [ "stat", + [ "call", [ "name", "trace" ], + [ [ "string", this[0].toString() ], + [ "num", this[0].start.line ], + [ "num", this[0].start.col ], + [ "num", this[0].end.line ], + [ "num", this[0].end.col ]]]], + w.walk(this) ]]; + analyzing.pop(this); + } + return ret; + }; + var new_ast = w.with_walkers({ + "stat" : do_stat, + "label" : do_stat, + "break" : do_stat, + "continue" : do_stat, + "debugger" : do_stat, + "var" : do_stat, + "const" : do_stat, + "return" : do_stat, + "throw" : do_stat, + "try" : do_stat, + "defun" : do_stat, + "if" : do_stat, + "while" : do_stat, + "do" : do_stat, + "for" : do_stat, + "for-in" : do_stat, + "switch" : do_stat, + "with" : do_stat + }, function(){ + return w.walk(ast); + }); + return pro.gen_code(new_ast, { beautify: true }); +} + + + + +////// test code follows. + +var code = instrument(test.toString()); +console.log(code); + +function test() { + // simple stats + a = 5; + c += a + b; + "foo"; + + // var + var foo = 5; + const bar = 6, baz = 7; + + // switch block. note we can't track case lines the same way. + switch ("foo") { + case "foo": + return 1; + case "bar": + return 2; + } + + // for/for in + for (var i = 0; i < 5; ++i) { + console.log("Hello " + i); + } + for (var i in [ 1, 2, 3]) { + console.log(i); + } + + // note however that the following is broken. I guess we + // should add the block brackets in this case... + for (var i = 0; i < 5; ++i) + console.log("foo"); +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument2.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument2.js new file mode 100644 index 00000000..6aee5f3f --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument2.js @@ -0,0 +1,138 @@ +// sample on how to use the parser and walker API to instrument some code + +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +function instrument(code) { + var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want + // to have start/end tokens embedded in the + // statements + var w = pro.ast_walker(); + + function trace (line, comment) { + var code = pro.gen_code(line, { beautify: true }); + var data = line[0] + + var args = [] + if (!comment) comment = "" + if (typeof data === "object") { + code = code.split(/\n/).shift() + args = [ [ "string", data.toString() ], + [ "string", code ], + [ "num", data.start.line ], + [ "num", data.start.col ], + [ "num", data.end.line ], + [ "num", data.end.col ]] + } else { + args = [ [ "string", data ], + [ "string", code ]] + + } + return [ "call", [ "name", "trace" ], args ]; + } + + // we're gonna need this to push elements that we're currently looking at, to avoid + // endless recursion. + var analyzing = []; + function do_stat() { + var ret; + if (this[0].start && analyzing.indexOf(this) < 0) { + // without the `analyzing' hack, w.walk(this) would re-enter here leading + // to infinite recursion + analyzing.push(this); + ret = [ "splice", + [ [ "stat", trace(this) ], + w.walk(this) ]]; + analyzing.pop(this); + } + return ret; + } + + function do_cond(c, t, f) { + return [ this[0], w.walk(c), + ["seq", trace(t), w.walk(t) ], + ["seq", trace(f), w.walk(f) ]]; + } + + function do_binary(c, l, r) { + if (c !== "&&" && c !== "||") { + return [this[0], c, w.walk(l), w.walk(r)]; + } + return [ this[0], c, + ["seq", trace(l), w.walk(l) ], + ["seq", trace(r), w.walk(r) ]]; + } + + var new_ast = w.with_walkers({ + "stat" : do_stat, + "label" : do_stat, + "break" : do_stat, + "continue" : do_stat, + "debugger" : do_stat, + "var" : do_stat, + "const" : do_stat, + "return" : do_stat, + "throw" : do_stat, + "try" : do_stat, + "defun" : do_stat, + "if" : do_stat, + "while" : do_stat, + "do" : do_stat, + "for" : do_stat, + "for-in" : do_stat, + "switch" : do_stat, + "with" : do_stat, + "conditional" : do_cond, + "binary" : do_binary + }, function(){ + return w.walk(ast); + }); + return pro.gen_code(new_ast, { beautify: true }); +} + + +////// test code follows. + +var code = instrument(test.toString()); +console.log(code); + +function test() { + // simple stats + a = 5; + c += a + b; + "foo"; + + // var + var foo = 5; + const bar = 6, baz = 7; + + // switch block. note we can't track case lines the same way. + switch ("foo") { + case "foo": + return 1; + case "bar": + return 2; + } + + // for/for in + for (var i = 0; i < 5; ++i) { + console.log("Hello " + i); + } + for (var i in [ 1, 2, 3]) { + console.log(i); + } + + for (var i = 0; i < 5; ++i) + console.log("foo"); + + for (var i = 0; i < 5; ++i) { + console.log("foo"); + } + + var k = plurp() ? 1 : 0; + var x = a ? doX(y) && goZoo("zoo") + : b ? blerg({ x: y }) + : null; + + var x = X || Y; +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/liftvars.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/liftvars.js new file mode 100644 index 00000000..2f4b7fe2 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/liftvars.js @@ -0,0 +1,8 @@ +var UNUSED_VAR1 = 19; + +function main() { + var unused_var2 = 20; + alert(100); +} + +main(); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/test.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/test.js new file mode 100755 index 00000000..f295fba8 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/test.js @@ -0,0 +1,30 @@ +#! /usr/bin/env node + +global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); +var fs = require("fs"); +var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js + jsp = uglify.parser, + pro = uglify.uglify; + +var code = fs.readFileSync("hoist.js", "utf8"); +var ast = jsp.parse(code); + +ast = pro.ast_lift_variables(ast); + +var w = pro.ast_walker(); +ast = w.with_walkers({ + "function": function() { + var node = w.dive(this); // walk depth first + console.log(pro.gen_code(node, { beautify: true })); + return node; + }, + "name": function(name) { + return [ this[0], "X" ]; + } +}, function(){ + return w.walk(ast); +}); + +console.log(pro.gen_code(ast, { + beautify: true +})); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs.js new file mode 100644 index 00000000..0d5b7e0e --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs.js @@ -0,0 +1,3930 @@ +/** + * @fileoverview + * + * JsWorld + * + *

    Javascript library for localised formatting and parsing of: + *

      + *
    • Numbers + *
    • Dates and times + *
    • Currency + *
    + * + *

    The library classes are configured with standard POSIX locale definitions + * derived from Unicode's Common Locale Data Repository (CLDR). + * + *

    Website: JsWorld + * + * @author Vladimir Dzhuvinov + * @version 2.5 (2011-12-23) + */ + + + +/** + * @namespace Namespace container for the JsWorld library objects. + */ +jsworld = {}; + + +/** + * @function + * + * @description Formats a JavaScript Date object as an ISO-8601 date/time + * string. + * + * @param {Date} [d] A valid JavaScript Date object. If undefined the + * current date/time will be used. + * @param {Boolean} [withTZ] Include timezone offset, default false. + * + * @returns {String} The date/time formatted as YYYY-MM-DD HH:MM:SS. + */ +jsworld.formatIsoDateTime = function(d, withTZ) { + + if (typeof d === "undefined") + d = new Date(); // now + + if (typeof withTZ === "undefined") + withTZ = false; + + var s = jsworld.formatIsoDate(d) + " " + jsworld.formatIsoTime(d); + + if (withTZ) { + + var diff = d.getHours() - d.getUTCHours(); + var hourDiff = Math.abs(diff); + + var minuteUTC = d.getUTCMinutes(); + var minute = d.getMinutes(); + + if (minute != minuteUTC && minuteUTC < 30 && diff < 0) + hourDiff--; + + if (minute != minuteUTC && minuteUTC > 30 && diff > 0) + hourDiff--; + + var minuteDiff; + if (minute != minuteUTC) + minuteDiff = ":30"; + else + minuteDiff = ":00"; + + var timezone; + if (hourDiff < 10) + timezone = "0" + hourDiff + minuteDiff; + + else + timezone = "" + hourDiff + minuteDiff; + + if (diff < 0) + timezone = "-" + timezone; + + else + timezone = "+" + timezone; + + s = s + timezone; + } + + return s; +}; + + +/** + * @function + * + * @description Formats a JavaScript Date object as an ISO-8601 date string. + * + * @param {Date} [d] A valid JavaScript Date object. If undefined the current + * date will be used. + * + * @returns {String} The date formatted as YYYY-MM-DD. + */ +jsworld.formatIsoDate = function(d) { + + if (typeof d === "undefined") + d = new Date(); // now + + var year = d.getFullYear(); + var month = d.getMonth() + 1; + var day = d.getDate(); + + return year + "-" + jsworld._zeroPad(month, 2) + "-" + jsworld._zeroPad(day, 2); +}; + + +/** + * @function + * + * @description Formats a JavaScript Date object as an ISO-8601 time string. + * + * @param {Date} [d] A valid JavaScript Date object. If undefined the current + * time will be used. + * + * @returns {String} The time formatted as HH:MM:SS. + */ +jsworld.formatIsoTime = function(d) { + + if (typeof d === "undefined") + d = new Date(); // now + + var hour = d.getHours(); + var minute = d.getMinutes(); + var second = d.getSeconds(); + + return jsworld._zeroPad(hour, 2) + ":" + jsworld._zeroPad(minute, 2) + ":" + jsworld._zeroPad(second, 2); +}; + + +/** + * @function + * + * @description Parses an ISO-8601 formatted date/time string to a JavaScript + * Date object. + * + * @param {String} isoDateTimeVal An ISO-8601 formatted date/time string. + * + *

    Accepted formats: + * + *

      + *
    • YYYY-MM-DD HH:MM:SS + *
    • YYYYMMDD HHMMSS + *
    • YYYY-MM-DD HHMMSS + *
    • YYYYMMDD HH:MM:SS + *
    + * + * @returns {Date} The corresponding Date object. + * + * @throws Error on a badly formatted date/time string or on a invalid date. + */ +jsworld.parseIsoDateTime = function(isoDateTimeVal) { + + if (typeof isoDateTimeVal != "string") + throw "Error: The parameter must be a string"; + + // First, try to match "YYYY-MM-DD HH:MM:SS" format + var matches = isoDateTimeVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/); + + // If unsuccessful, try to match "YYYYMMDD HHMMSS" format + if (matches === null) + matches = isoDateTimeVal.match(/^(\d\d\d\d)(\d\d)(\d\d)[T ](\d\d)(\d\d)(\d\d)/); + + // ... try to match "YYYY-MM-DD HHMMSS" format + if (matches === null) + matches = isoDateTimeVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d)(\d\d)(\d\d)/); + + // ... try to match "YYYYMMDD HH:MM:SS" format + if (matches === null) + matches = isoDateTimeVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/); + + // Report bad date/time string + if (matches === null) + throw "Error: Invalid ISO-8601 date/time string"; + + // Force base 10 parse int as some values may have leading zeros! + // (to avoid implicit octal base conversion) + var year = parseInt(matches[1], 10); + var month = parseInt(matches[2], 10); + var day = parseInt(matches[3], 10); + + var hour = parseInt(matches[4], 10); + var mins = parseInt(matches[5], 10); + var secs = parseInt(matches[6], 10); + + // Simple value range check, leap years not checked + // Note: the originial ISO time spec for leap hours (24:00:00) and seconds (00:00:60) is not supported + if (month < 1 || month > 12 || + day < 1 || day > 31 || + hour < 0 || hour > 23 || + mins < 0 || mins > 59 || + secs < 0 || secs > 59 ) + + throw "Error: Invalid ISO-8601 date/time value"; + + var d = new Date(year, month - 1, day, hour, mins, secs); + + // Check if the input date was valid + // (JS Date does automatic forward correction) + if (d.getDate() != day || d.getMonth() +1 != month) + throw "Error: Invalid date"; + + return d; +}; + + +/** + * @function + * + * @description Parses an ISO-8601 formatted date string to a JavaScript + * Date object. + * + * @param {String} isoDateVal An ISO-8601 formatted date string. + * + *

    Accepted formats: + * + *

      + *
    • YYYY-MM-DD + *
    • YYYYMMDD + *
    + * + * @returns {Date} The corresponding Date object. + * + * @throws Error on a badly formatted date string or on a invalid date. + */ +jsworld.parseIsoDate = function(isoDateVal) { + + if (typeof isoDateVal != "string") + throw "Error: The parameter must be a string"; + + // First, try to match "YYYY-MM-DD" format + var matches = isoDateVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)/); + + // If unsuccessful, try to match "YYYYMMDD" format + if (matches === null) + matches = isoDateVal.match(/^(\d\d\d\d)(\d\d)(\d\d)/); + + // Report bad date/time string + if (matches === null) + throw "Error: Invalid ISO-8601 date string"; + + // Force base 10 parse int as some values may have leading zeros! + // (to avoid implicit octal base conversion) + var year = parseInt(matches[1], 10); + var month = parseInt(matches[2], 10); + var day = parseInt(matches[3], 10); + + // Simple value range check, leap years not checked + if (month < 1 || month > 12 || + day < 1 || day > 31 ) + + throw "Error: Invalid ISO-8601 date value"; + + var d = new Date(year, month - 1, day); + + // Check if the input date was valid + // (JS Date does automatic forward correction) + if (d.getDate() != day || d.getMonth() +1 != month) + throw "Error: Invalid date"; + + return d; +}; + + +/** + * @function + * + * @description Parses an ISO-8601 formatted time string to a JavaScript + * Date object. + * + * @param {String} isoTimeVal An ISO-8601 formatted time string. + * + *

    Accepted formats: + * + *

      + *
    • HH:MM:SS + *
    • HHMMSS + *
    + * + * @returns {Date} The corresponding Date object, with year, month and day set + * to zero. + * + * @throws Error on a badly formatted time string. + */ +jsworld.parseIsoTime = function(isoTimeVal) { + + if (typeof isoTimeVal != "string") + throw "Error: The parameter must be a string"; + + // First, try to match "HH:MM:SS" format + var matches = isoTimeVal.match(/^(\d\d):(\d\d):(\d\d)/); + + // If unsuccessful, try to match "HHMMSS" format + if (matches === null) + matches = isoTimeVal.match(/^(\d\d)(\d\d)(\d\d)/); + + // Report bad date/time string + if (matches === null) + throw "Error: Invalid ISO-8601 date/time string"; + + // Force base 10 parse int as some values may have leading zeros! + // (to avoid implicit octal base conversion) + var hour = parseInt(matches[1], 10); + var mins = parseInt(matches[2], 10); + var secs = parseInt(matches[3], 10); + + // Simple value range check, leap years not checked + if (hour < 0 || hour > 23 || + mins < 0 || mins > 59 || + secs < 0 || secs > 59 ) + + throw "Error: Invalid ISO-8601 time value"; + + return new Date(0, 0, 0, hour, mins, secs); +}; + + +/** + * @private + * + * @description Trims leading and trailing whitespace from a string. + * + *

    Used non-regexp the method from http://blog.stevenlevithan.com/archives/faster-trim-javascript + * + * @param {String} str The string to trim. + * + * @returns {String} The trimmed string. + */ +jsworld._trim = function(str) { + + var whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000'; + + for (var i = 0; i < str.length; i++) { + + if (whitespace.indexOf(str.charAt(i)) === -1) { + str = str.substring(i); + break; + } + } + + for (i = str.length - 1; i >= 0; i--) { + if (whitespace.indexOf(str.charAt(i)) === -1) { + str = str.substring(0, i + 1); + break; + } + } + + return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''; +}; + + + +/** + * @private + * + * @description Returns true if the argument represents a decimal number. + * + * @param {Number|String} arg The argument to test. + * + * @returns {Boolean} true if the argument represents a decimal number, + * otherwise false. + */ +jsworld._isNumber = function(arg) { + + if (typeof arg == "number") + return true; + + if (typeof arg != "string") + return false; + + // ensure string + var s = arg + ""; + + return (/^-?(\d+|\d*\.\d+)$/).test(s); +}; + + +/** + * @private + * + * @description Returns true if the argument represents a decimal integer. + * + * @param {Number|String} arg The argument to test. + * + * @returns {Boolean} true if the argument represents an integer, otherwise + * false. + */ +jsworld._isInteger = function(arg) { + + if (typeof arg != "number" && typeof arg != "string") + return false; + + // convert to string + var s = arg + ""; + + return (/^-?\d+$/).test(s); +}; + + +/** + * @private + * + * @description Returns true if the argument represents a decimal float. + * + * @param {Number|String} arg The argument to test. + * + * @returns {Boolean} true if the argument represents a float, otherwise false. + */ +jsworld._isFloat = function(arg) { + + if (typeof arg != "number" && typeof arg != "string") + return false; + + // convert to string + var s = arg + ""; + + return (/^-?\.\d+?$/).test(s); +}; + + +/** + * @private + * + * @description Checks if the specified formatting option is contained + * within the options string. + * + * @param {String} option The option to search for. + * @param {String} optionsString The options string. + * + * @returns {Boolean} true if the flag is found, else false + */ +jsworld._hasOption = function(option, optionsString) { + + if (typeof option != "string" || typeof optionsString != "string") + return false; + + if (optionsString.indexOf(option) != -1) + return true; + else + return false; +}; + + +/** + * @private + * + * @description String replacement function. + * + * @param {String} s The string to work on. + * @param {String} target The string to search for. + * @param {String} replacement The replacement. + * + * @returns {String} The new string. + */ +jsworld._stringReplaceAll = function(s, target, replacement) { + + var out; + + if (target.length == 1 && replacement.length == 1) { + // simple char/char case somewhat faster + out = ""; + + for (var i = 0; i < s.length; i++) { + + if (s.charAt(i) == target.charAt(0)) + out = out + replacement.charAt(0); + else + out = out + s.charAt(i); + } + + return out; + } + else { + // longer target and replacement strings + out = s; + + var index = out.indexOf(target); + + while (index != -1) { + + out = out.replace(target, replacement); + + index = out.indexOf(target); + } + + return out; + } +}; + + +/** + * @private + * + * @description Tests if a string starts with the specified substring. + * + * @param {String} testedString The string to test. + * @param {String} sub The string to match. + * + * @returns {Boolean} true if the test succeeds. + */ +jsworld._stringStartsWith = function (testedString, sub) { + + if (testedString.length < sub.length) + return false; + + for (var i = 0; i < sub.length; i++) { + if (testedString.charAt(i) != sub.charAt(i)) + return false; + } + + return true; +}; + + +/** + * @private + * + * @description Gets the requested precision from an options string. + * + *

    Example: ".3" returns 3 decimal places precision. + * + * @param {String} optionsString The options string. + * + * @returns {integer Number} The requested precision, -1 if not specified. + */ +jsworld._getPrecision = function (optionsString) { + + if (typeof optionsString != "string") + return -1; + + var m = optionsString.match(/\.(\d)/); + if (m) + return parseInt(m[1], 10); + else + return -1; +}; + + +/** + * @private + * + * @description Takes a decimal numeric amount (optionally as string) and + * returns its integer and fractional parts packed into an object. + * + * @param {Number|String} amount The amount, e.g. "123.45" or "-56.78" + * + * @returns {object} Parsed amount object with properties: + * {String} integer : the integer part + * {String} fraction : the fraction part + */ +jsworld._splitNumber = function (amount) { + + if (typeof amount == "number") + amount = amount + ""; + + var obj = {}; + + // remove negative sign + if (amount.charAt(0) == "-") + amount = amount.substring(1); + + // split amount into integer and decimal parts + var amountParts = amount.split("."); + if (!amountParts[1]) + amountParts[1] = ""; // we need "" instead of null + + obj.integer = amountParts[0]; + obj.fraction = amountParts[1]; + + return obj; +}; + + +/** + * @private + * + * @description Formats the integer part using the specified grouping + * and thousands separator. + * + * @param {String} intPart The integer part of the amount, as string. + * @param {String} grouping The grouping definition. + * @param {String} thousandsSep The thousands separator. + * + * @returns {String} The formatted integer part. + */ +jsworld._formatIntegerPart = function (intPart, grouping, thousandsSep) { + + // empty separator string? no grouping? + // -> return immediately with no formatting! + if (thousandsSep == "" || grouping == "-1") + return intPart; + + // turn the semicolon-separated string of integers into an array + var groupSizes = grouping.split(";"); + + // the formatted output string + var out = ""; + + // the intPart string position to process next, + // start at string end, e.g. "10000000 0) { + + // get next group size (if any, otherwise keep last) + if (groupSizes.length > 0) + size = parseInt(groupSizes.shift(), 10); + + // int parse error? + if (isNaN(size)) + throw "Error: Invalid grouping"; + + // size is -1? -> no more grouping, so just copy string remainder + if (size == -1) { + out = intPart.substring(0, pos) + out; + break; + } + + pos -= size; // move to next sep. char. position + + // position underrun? -> just copy string remainder + if (pos < 1) { + out = intPart.substring(0, pos + size) + out; + break; + } + + // extract group and apply sep. char. + out = thousandsSep + intPart.substring(pos, pos + size) + out; + } + + return out; +}; + + +/** + * @private + * + * @description Formats the fractional part to the specified decimal + * precision. + * + * @param {String} fracPart The fractional part of the amount + * @param {integer Number} precision The desired decimal precision + * + * @returns {String} The formatted fractional part. + */ +jsworld._formatFractionPart = function (fracPart, precision) { + + // append zeroes up to precision if necessary + for (var i=0; fracPart.length < precision; i++) + fracPart = fracPart + "0"; + + return fracPart; +}; + + +/** + * @private + * + * @desription Converts a number to string and pad it with leading zeroes if the + * string is shorter than length. + * + * @param {integer Number} number The number value subjected to selective padding. + * @param {integer Number} length If the number has fewer digits than this length + * apply padding. + * + * @returns {String} The formatted string. + */ +jsworld._zeroPad = function(number, length) { + + // ensure string + var s = number + ""; + + while (s.length < length) + s = "0" + s; + + return s; +}; + + +/** + * @private + * @description Converts a number to string and pads it with leading spaces if + * the string is shorter than length. + * + * @param {integer Number} number The number value subjected to selective padding. + * @param {integer Number} length If the number has fewer digits than this length + * apply padding. + * + * @returns {String} The formatted string. + */ +jsworld._spacePad = function(number, length) { + + // ensure string + var s = number + ""; + + while (s.length < length) + s = " " + s; + + return s; +}; + + + +/** + * @class + * Represents a POSIX-style locale with its numeric, monetary and date/time + * properties. Also provides a set of locale helper methods. + * + *

    The locale properties follow the POSIX standards: + * + *

    + * + * @public + * @constructor + * @description Creates a new locale object (POSIX-style) with the specified + * properties. + * + * @param {object} properties An object containing the raw locale properties: + * + * @param {String} properties.decimal_point + * + * A string containing the symbol that shall be used as the decimal + * delimiter (radix character) in numeric, non-monetary formatted + * quantities. This property cannot be omitted and cannot be set to the + * empty string. + * + * + * @param {String} properties.thousands_sep + * + * A string containing the symbol that shall be used as a separator for + * groups of digits to the left of the decimal delimiter in numeric, + * non-monetary formatted monetary quantities. + * + * + * @param {String} properties.grouping + * + * Defines the size of each group of digits in formatted non-monetary + * quantities. The operand is a sequence of integers separated by + * semicolons. Each integer specifies the number of digits in each group, + * with the initial integer defining the size of the group immediately + * preceding the decimal delimiter, and the following integers defining + * the preceding groups. If the last integer is not -1, then the size of + * the previous group (if any) shall be repeatedly used for the + * remainder of the digits. If the last integer is -1, then no further + * grouping shall be performed. + * + * + * @param {String} properties.int_curr_symbol + * + * The first three letters signify the ISO-4217 currency code, + * the fourth letter is the international symbol separation character + * (normally a space). + * + * + * @param {String} properties.currency_symbol + * + * The local shorthand currency symbol, e.g. "$" for the en_US locale + * + * + * @param {String} properties.mon_decimal_point + * + * The symbol to be used as the decimal delimiter (radix character) + * + * + * @param {String} properties.mon_thousands_sep + * + * The symbol to be used as a separator for groups of digits to the + * left of the decimal delimiter. + * + * + * @param {String} properties.mon_grouping + * + * A string that defines the size of each group of digits. The + * operand is a sequence of integers separated by semicolons (";"). + * Each integer specifies the number of digits in each group, with the + * initial integer defining the size of the group preceding the + * decimal delimiter, and the following integers defining the + * preceding groups. If the last integer is not -1, then the size of + * the previous group (if any) must be repeatedly used for the + * remainder of the digits. If the last integer is -1, then no + * further grouping is to be performed. + * + * + * @param {String} properties.positive_sign + * + * The string to indicate a non-negative monetary amount. + * + * + * @param {String} properties.negative_sign + * + * The string to indicate a negative monetary amount. + * + * + * @param {integer Number} properties.frac_digits + * + * An integer representing the number of fractional digits (those to + * the right of the decimal delimiter) to be written in a formatted + * monetary quantity using currency_symbol. + * + * + * @param {integer Number} properties.int_frac_digits + * + * An integer representing the number of fractional digits (those to + * the right of the decimal delimiter) to be written in a formatted + * monetary quantity using int_curr_symbol. + * + * + * @param {integer Number} properties.p_cs_precedes + * + * An integer set to 1 if the currency_symbol precedes the value for a + * monetary quantity with a non-negative value, and set to 0 if the + * symbol succeeds the value. + * + * + * @param {integer Number} properties.n_cs_precedes + * + * An integer set to 1 if the currency_symbol precedes the value for a + * monetary quantity with a negative value, and set to 0 if the symbol + * succeeds the value. + * + * + * @param {integer Number} properties.p_sep_by_space + * + * Set to a value indicating the separation of the currency_symbol, + * the sign string, and the value for a non-negative formatted monetary + * quantity: + * + *

    0 No space separates the currency symbol and value.

    + * + *

    1 If the currency symbol and sign string are adjacent, a space + * separates them from the value; otherwise, a space separates + * the currency symbol from the value.

    + * + *

    2 If the currency symbol and sign string are adjacent, a space + * separates them; otherwise, a space separates the sign string + * from the value.

    + * + * + * @param {integer Number} properties.n_sep_by_space + * + * Set to a value indicating the separation of the currency_symbol, + * the sign string, and the value for a negative formatted monetary + * quantity. Rules same as for p_sep_by_space. + * + * + * @param {integer Number} properties.p_sign_posn + * + * An integer set to a value indicating the positioning of the + * positive_sign for a monetary quantity with a non-negative value: + * + *

    0 Parentheses enclose the quantity and the currency_symbol.

    + * + *

    1 The sign string precedes the quantity and the currency_symbol.

    + * + *

    2 The sign string succeeds the quantity and the currency_symbol.

    + * + *

    3 The sign string precedes the currency_symbol.

    + * + *

    4 The sign string succeeds the currency_symbol.

    + * + * + * @param {integer Number} properties.n_sign_posn + * + * An integer set to a value indicating the positioning of the + * negative_sign for a negative formatted monetary quantity. Rules same + * as for p_sign_posn. + * + * + * @param {integer Number} properties.int_p_cs_precedes + * + * An integer set to 1 if the int_curr_symbol precedes the value for a + * monetary quantity with a non-negative value, and set to 0 if the + * symbol succeeds the value. + * + * + * @param {integer Number} properties.int_n_cs_precedes + * + * An integer set to 1 if the int_curr_symbol precedes the value for a + * monetary quantity with a negative value, and set to 0 if the symbol + * succeeds the value. + * + * + * @param {integer Number} properties.int_p_sep_by_space + * + * Set to a value indicating the separation of the int_curr_symbol, + * the sign string, and the value for a non-negative internationally + * formatted monetary quantity. Rules same as for p_sep_by_space. + * + * + * @param {integer Number} properties.int_n_sep_by_space + * + * Set to a value indicating the separation of the int_curr_symbol, + * the sign string, and the value for a negative internationally + * formatted monetary quantity. Rules same as for p_sep_by_space. + * + * + * @param {integer Number} properties.int_p_sign_posn + * + * An integer set to a value indicating the positioning of the + * positive_sign for a positive monetary quantity formatted with the + * international format. Rules same as for p_sign_posn. + * + * + * @param {integer Number} properties.int_n_sign_posn + * + * An integer set to a value indicating the positioning of the + * negative_sign for a negative monetary quantity formatted with the + * international format. Rules same as for p_sign_posn. + * + * + * @param {String[] | String} properties.abday + * + * The abbreviated weekday names, corresponding to the %a conversion + * specification. The property must be either an array of 7 strings or + * a string consisting of 7 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the abbreviated name + * of the day corresponding to Sunday, the second the abbreviated name + * of the day corresponding to Monday, and so on. + * + * + * @param {String[] | String} properties.day + * + * The full weekday names, corresponding to the %A conversion + * specification. The property must be either an array of 7 strings or + * a string consisting of 7 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the full name of the + * day corresponding to Sunday, the second the full name of the day + * corresponding to Monday, and so on. + * + * + * @param {String[] | String} properties.abmon + * + * The abbreviated month names, corresponding to the %b conversion + * specification. The property must be either an array of 12 strings or + * a string consisting of 12 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the abbreviated name + * of the first month of the year (January), the second the abbreviated + * name of the second month, and so on. + * + * + * @param {String[] | String} properties.mon + * + * The full month names, corresponding to the %B conversion + * specification. The property must be either an array of 12 strings or + * a string consisting of 12 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the full name of the + * first month of the year (January), the second the full name of the second + * month, and so on. + * + * + * @param {String} properties.d_fmt + * + * The appropriate date representation. The string may contain any + * combination of characters and conversion specifications (%). + * + * + * @param {String} properties.t_fmt + * + * The appropriate time representation. The string may contain any + * combination of characters and conversion specifications (%). + * + * + * @param {String} properties.d_t_fmt + * + * The appropriate date and time representation. The string may contain + * any combination of characters and conversion specifications (%). + * + * + * @param {String[] | String} properties.am_pm + * + * The appropriate representation of the ante-meridiem and post-meridiem + * strings, corresponding to the %p conversion specification. The property + * must be either an array of 2 strings or a string consisting of 2 + * semicolon-separated substrings, each surrounded by double-quotes. + * The first string must represent the ante-meridiem designation, the + * last string the post-meridiem designation. + * + * + * @throws @throws Error on a undefined or invalid locale property. + */ +jsworld.Locale = function(properties) { + + + /** + * @private + * + * @description Identifies the class for internal library purposes. + */ + this._className = "jsworld.Locale"; + + + /** + * @private + * + * @description Parses a day or month name definition list, which + * could be a ready JS array, e.g. ["Mon", "Tue", "Wed"...] or + * it could be a string formatted according to the classic POSIX + * definition e.g. "Mon";"Tue";"Wed";... + * + * @param {String[] | String} namesAn array or string defining + * the week/month names. + * @param {integer Number} expectedItems The number of expected list + * items, e.g. 7 for weekdays, 12 for months. + * + * @returns {String[]} The parsed (and checked) items. + * + * @throws Error on missing definition, unexpected item count or + * missing double-quotes. + */ + this._parseList = function(names, expectedItems) { + + var array = []; + + if (names == null) { + throw "Names not defined"; + } + else if (typeof names == "object") { + // we got a ready array + array = names; + } + else if (typeof names == "string") { + // we got the names in the classic POSIX form, do parse + array = names.split(";", expectedItems); + + for (var i = 0; i < array.length; i++) { + // check for and strip double quotes + if (array[i][0] == "\"" && array[i][array[i].length - 1] == "\"") + array[i] = array[i].slice(1, -1); + else + throw "Missing double quotes"; + } + } + else { + throw "Names must be an array or a string"; + } + + if (array.length != expectedItems) + throw "Expected " + expectedItems + " items, got " + array.length; + + return array; + }; + + + /** + * @private + * + * @description Validates a date/time format string, such as "H:%M:%S". + * Checks that the argument is of type "string" and is not empty. + * + * @param {String} formatString The format string. + * + * @returns {String} The validated string. + * + * @throws Error on null or empty string. + */ + this._validateFormatString = function(formatString) { + + if (typeof formatString == "string" && formatString.length > 0) + return formatString; + else + throw "Empty or no string"; + }; + + + // LC_NUMERIC + + if (properties == null || typeof properties != "object") + throw "Error: Invalid/missing locale properties"; + + + if (typeof properties.decimal_point != "string") + throw "Error: Invalid/missing decimal_point property"; + + this.decimal_point = properties.decimal_point; + + + if (typeof properties.thousands_sep != "string") + throw "Error: Invalid/missing thousands_sep property"; + + this.thousands_sep = properties.thousands_sep; + + + if (typeof properties.grouping != "string") + throw "Error: Invalid/missing grouping property"; + + this.grouping = properties.grouping; + + + // LC_MONETARY + + if (typeof properties.int_curr_symbol != "string") + throw "Error: Invalid/missing int_curr_symbol property"; + + if (! /[A-Za-z]{3}.?/.test(properties.int_curr_symbol)) + throw "Error: Invalid int_curr_symbol property"; + + this.int_curr_symbol = properties.int_curr_symbol; + + + if (typeof properties.currency_symbol != "string") + throw "Error: Invalid/missing currency_symbol property"; + + this.currency_symbol = properties.currency_symbol; + + + if (typeof properties.frac_digits != "number" && properties.frac_digits < 0) + throw "Error: Invalid/missing frac_digits property"; + + this.frac_digits = properties.frac_digits; + + + // may be empty string/null for currencies with no fractional part + if (properties.mon_decimal_point === null || properties.mon_decimal_point == "") { + + if (this.frac_digits > 0) + throw "Error: Undefined mon_decimal_point property"; + else + properties.mon_decimal_point = ""; + } + + if (typeof properties.mon_decimal_point != "string") + throw "Error: Invalid/missing mon_decimal_point property"; + + this.mon_decimal_point = properties.mon_decimal_point; + + + if (typeof properties.mon_thousands_sep != "string") + throw "Error: Invalid/missing mon_thousands_sep property"; + + this.mon_thousands_sep = properties.mon_thousands_sep; + + + if (typeof properties.mon_grouping != "string") + throw "Error: Invalid/missing mon_grouping property"; + + this.mon_grouping = properties.mon_grouping; + + + if (typeof properties.positive_sign != "string") + throw "Error: Invalid/missing positive_sign property"; + + this.positive_sign = properties.positive_sign; + + + if (typeof properties.negative_sign != "string") + throw "Error: Invalid/missing negative_sign property"; + + this.negative_sign = properties.negative_sign; + + + + if (properties.p_cs_precedes !== 0 && properties.p_cs_precedes !== 1) + throw "Error: Invalid/missing p_cs_precedes property, must be 0 or 1"; + + this.p_cs_precedes = properties.p_cs_precedes; + + + if (properties.n_cs_precedes !== 0 && properties.n_cs_precedes !== 1) + throw "Error: Invalid/missing n_cs_precedes, must be 0 or 1"; + + this.n_cs_precedes = properties.n_cs_precedes; + + + if (properties.p_sep_by_space !== 0 && + properties.p_sep_by_space !== 1 && + properties.p_sep_by_space !== 2) + throw "Error: Invalid/missing p_sep_by_space property, must be 0, 1 or 2"; + + this.p_sep_by_space = properties.p_sep_by_space; + + + if (properties.n_sep_by_space !== 0 && + properties.n_sep_by_space !== 1 && + properties.n_sep_by_space !== 2) + throw "Error: Invalid/missing n_sep_by_space property, must be 0, 1, or 2"; + + this.n_sep_by_space = properties.n_sep_by_space; + + + if (properties.p_sign_posn !== 0 && + properties.p_sign_posn !== 1 && + properties.p_sign_posn !== 2 && + properties.p_sign_posn !== 3 && + properties.p_sign_posn !== 4) + throw "Error: Invalid/missing p_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.p_sign_posn = properties.p_sign_posn; + + + if (properties.n_sign_posn !== 0 && + properties.n_sign_posn !== 1 && + properties.n_sign_posn !== 2 && + properties.n_sign_posn !== 3 && + properties.n_sign_posn !== 4) + throw "Error: Invalid/missing n_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.n_sign_posn = properties.n_sign_posn; + + + if (typeof properties.int_frac_digits != "number" && properties.int_frac_digits < 0) + throw "Error: Invalid/missing int_frac_digits property"; + + this.int_frac_digits = properties.int_frac_digits; + + + if (properties.int_p_cs_precedes !== 0 && properties.int_p_cs_precedes !== 1) + throw "Error: Invalid/missing int_p_cs_precedes property, must be 0 or 1"; + + this.int_p_cs_precedes = properties.int_p_cs_precedes; + + + if (properties.int_n_cs_precedes !== 0 && properties.int_n_cs_precedes !== 1) + throw "Error: Invalid/missing int_n_cs_precedes property, must be 0 or 1"; + + this.int_n_cs_precedes = properties.int_n_cs_precedes; + + + if (properties.int_p_sep_by_space !== 0 && + properties.int_p_sep_by_space !== 1 && + properties.int_p_sep_by_space !== 2) + throw "Error: Invalid/missing int_p_sep_by_spacev, must be 0, 1 or 2"; + + this.int_p_sep_by_space = properties.int_p_sep_by_space; + + + if (properties.int_n_sep_by_space !== 0 && + properties.int_n_sep_by_space !== 1 && + properties.int_n_sep_by_space !== 2) + throw "Error: Invalid/missing int_n_sep_by_space property, must be 0, 1, or 2"; + + this.int_n_sep_by_space = properties.int_n_sep_by_space; + + + if (properties.int_p_sign_posn !== 0 && + properties.int_p_sign_posn !== 1 && + properties.int_p_sign_posn !== 2 && + properties.int_p_sign_posn !== 3 && + properties.int_p_sign_posn !== 4) + throw "Error: Invalid/missing int_p_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.int_p_sign_posn = properties.int_p_sign_posn; + + + if (properties.int_n_sign_posn !== 0 && + properties.int_n_sign_posn !== 1 && + properties.int_n_sign_posn !== 2 && + properties.int_n_sign_posn !== 3 && + properties.int_n_sign_posn !== 4) + throw "Error: Invalid/missing int_n_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.int_n_sign_posn = properties.int_n_sign_posn; + + + // LC_TIME + + if (properties == null || typeof properties != "object") + throw "Error: Invalid/missing time locale properties"; + + + // parse the supported POSIX LC_TIME properties + + // abday + try { + this.abday = this._parseList(properties.abday, 7); + } + catch (error) { + throw "Error: Invalid abday property: " + error; + } + + // day + try { + this.day = this._parseList(properties.day, 7); + } + catch (error) { + throw "Error: Invalid day property: " + error; + } + + // abmon + try { + this.abmon = this._parseList(properties.abmon, 12); + } catch (error) { + throw "Error: Invalid abmon property: " + error; + } + + // mon + try { + this.mon = this._parseList(properties.mon, 12); + } catch (error) { + throw "Error: Invalid mon property: " + error; + } + + // d_fmt + try { + this.d_fmt = this._validateFormatString(properties.d_fmt); + } catch (error) { + throw "Error: Invalid d_fmt property: " + error; + } + + // t_fmt + try { + this.t_fmt = this._validateFormatString(properties.t_fmt); + } catch (error) { + throw "Error: Invalid t_fmt property: " + error; + } + + // d_t_fmt + try { + this.d_t_fmt = this._validateFormatString(properties.d_t_fmt); + } catch (error) { + throw "Error: Invalid d_t_fmt property: " + error; + } + + // am_pm + try { + var am_pm_strings = this._parseList(properties.am_pm, 2); + this.am = am_pm_strings[0]; + this.pm = am_pm_strings[1]; + } catch (error) { + // ignore empty/null string errors + this.am = ""; + this.pm = ""; + } + + + /** + * @public + * + * @description Returns the abbreviated name of the specified weekday. + * + * @param {integer Number} [weekdayNum] An integer between 0 and 6. Zero + * corresponds to Sunday, one to Monday, etc. If omitted the + * method will return an array of all abbreviated weekday + * names. + * + * @returns {String | String[]} The abbreviated name of the specified weekday + * or an array of all abbreviated weekday names. + * + * @throws Error on invalid argument. + */ + this.getAbbreviatedWeekdayName = function(weekdayNum) { + + if (typeof weekdayNum == "undefined" || weekdayNum === null) + return this.abday; + + if (! jsworld._isInteger(weekdayNum) || weekdayNum < 0 || weekdayNum > 6) + throw "Error: Invalid weekday argument, must be an integer [0..6]"; + + return this.abday[weekdayNum]; + }; + + + /** + * @public + * + * @description Returns the name of the specified weekday. + * + * @param {integer Number} [weekdayNum] An integer between 0 and 6. Zero + * corresponds to Sunday, one to Monday, etc. If omitted the + * method will return an array of all weekday names. + * + * @returns {String | String[]} The name of the specified weekday or an + * array of all weekday names. + * + * @throws Error on invalid argument. + */ + this.getWeekdayName = function(weekdayNum) { + + if (typeof weekdayNum == "undefined" || weekdayNum === null) + return this.day; + + if (! jsworld._isInteger(weekdayNum) || weekdayNum < 0 || weekdayNum > 6) + throw "Error: Invalid weekday argument, must be an integer [0..6]"; + + return this.day[weekdayNum]; + }; + + + /** + * @public + * + * @description Returns the abbreviated name of the specified month. + * + * @param {integer Number} [monthNum] An integer between 0 and 11. Zero + * corresponds to January, one to February, etc. If omitted the + * method will return an array of all abbreviated month names. + * + * @returns {String | String[]} The abbreviated name of the specified month + * or an array of all abbreviated month names. + * + * @throws Error on invalid argument. + */ + this.getAbbreviatedMonthName = function(monthNum) { + + if (typeof monthNum == "undefined" || monthNum === null) + return this.abmon; + + if (! jsworld._isInteger(monthNum) || monthNum < 0 || monthNum > 11) + throw "Error: Invalid month argument, must be an integer [0..11]"; + + return this.abmon[monthNum]; + }; + + + /** + * @public + * + * @description Returns the name of the specified month. + * + * @param {integer Number} [monthNum] An integer between 0 and 11. Zero + * corresponds to January, one to February, etc. If omitted the + * method will return an array of all month names. + * + * @returns {String | String[]} The name of the specified month or an array + * of all month names. + * + * @throws Error on invalid argument. + */ + this.getMonthName = function(monthNum) { + + if (typeof monthNum == "undefined" || monthNum === null) + return this.mon; + + if (! jsworld._isInteger(monthNum) || monthNum < 0 || monthNum > 11) + throw "Error: Invalid month argument, must be an integer [0..11]"; + + return this.mon[monthNum]; + }; + + + + /** + * @public + * + * @description Gets the decimal delimiter (radix) character for + * numeric quantities. + * + * @returns {String} The radix character. + */ + this.getDecimalPoint = function() { + + return this.decimal_point; + }; + + + /** + * @public + * + * @description Gets the local shorthand currency symbol. + * + * @returns {String} The currency symbol. + */ + this.getCurrencySymbol = function() { + + return this.currency_symbol; + }; + + + /** + * @public + * + * @description Gets the internaltion currency symbol (ISO-4217 code). + * + * @returns {String} The international currency symbol. + */ + this.getIntCurrencySymbol = function() { + + return this.int_curr_symbol.substring(0,3); + }; + + + /** + * @public + * + * @description Gets the position of the local (shorthand) currency + * symbol relative to the amount. Assumes a non-negative amount. + * + * @returns {Boolean} True if the symbol precedes the amount, false if + * the symbol succeeds the amount. + */ + this.currencySymbolPrecedes = function() { + + if (this.p_cs_precedes == 1) + return true; + else + return false; + }; + + + /** + * @public + * + * @description Gets the position of the international (ISO-4217 code) + * currency symbol relative to the amount. Assumes a non-negative + * amount. + * + * @returns {Boolean} True if the symbol precedes the amount, false if + * the symbol succeeds the amount. + */ + this.intCurrencySymbolPrecedes = function() { + + if (this.int_p_cs_precedes == 1) + return true; + else + return false; + + }; + + + /** + * @public + * + * @description Gets the decimal delimiter (radix) for monetary + * quantities. + * + * @returns {String} The radix character. + */ + this.getMonetaryDecimalPoint = function() { + + return this.mon_decimal_point; + }; + + + /** + * @public + * + * @description Gets the number of fractional digits for local + * (shorthand) symbol formatting. + * + * @returns {integer Number} The number of fractional digits. + */ + this.getFractionalDigits = function() { + + return this.frac_digits; + }; + + + /** + * @public + * + * @description Gets the number of fractional digits for + * international (ISO-4217 code) formatting. + * + * @returns {integer Number} The number of fractional digits. + */ + this.getIntFractionalDigits = function() { + + return this.int_frac_digits; + }; +}; + + + +/** + * @class + * Class for localised formatting of numbers. + * + *

    See: + * POSIX LC_NUMERIC. + * + * + * @public + * @constructor + * @description Creates a new numeric formatter for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_NUMERIC formatting properties. + * + * @throws Error on constructor failure. + */ +jsworld.NumericFormatter = function(locale) { + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance"; + + this.lc = locale; + + + /** + * @public + * + * @description Formats a decimal numeric value according to the preset + * locale. + * + * @param {Number|String} number The number to format. + * @param {String} [options] Options to modify the formatted output: + *

      + *
    • "^" suppress grouping + *
    • "+" force positive sign for positive amounts + *
    • "~" suppress positive/negative sign + *
    • ".n" specify decimal precision 'n' + *
    + * + * @returns {String} The formatted number. + * + * @throws "Error: Invalid input" on bad input. + */ + this.format = function(number, options) { + + if (typeof number == "string") + number = jsworld._trim(number); + + if (! jsworld._isNumber(number)) + throw "Error: The input is not a number"; + + var floatAmount = parseFloat(number, 10); + + // get the required precision + var reqPrecision = jsworld._getPrecision(options); + + // round to required precision + if (reqPrecision != -1) + floatAmount = Math.round(floatAmount * Math.pow(10, reqPrecision)) / Math.pow(10, reqPrecision); + + + // convert the float number to string and parse into + // object with properties integer and fraction + var parsedAmount = jsworld._splitNumber(String(floatAmount)); + + // format integer part with grouping chars + var formattedIntegerPart; + + if (floatAmount === 0) + formattedIntegerPart = "0"; + else + formattedIntegerPart = jsworld._hasOption("^", options) ? + parsedAmount.integer : + jsworld._formatIntegerPart(parsedAmount.integer, + this.lc.grouping, + this.lc.thousands_sep); + + // format the fractional part + var formattedFractionPart = + reqPrecision != -1 ? + jsworld._formatFractionPart(parsedAmount.fraction, reqPrecision) : + parsedAmount.fraction; + + + // join the integer and fraction parts using the decimal_point property + var formattedAmount = + formattedFractionPart.length ? + formattedIntegerPart + this.lc.decimal_point + formattedFractionPart : + formattedIntegerPart; + + // prepend sign? + if (jsworld._hasOption("~", options) || floatAmount === 0) { + // suppress both '+' and '-' signs, i.e. return abs value + return formattedAmount; + } + else { + if (jsworld._hasOption("+", options) || floatAmount < 0) { + if (floatAmount > 0) + // force '+' sign for positive amounts + return "+" + formattedAmount; + else if (floatAmount < 0) + // prepend '-' sign + return "-" + formattedAmount; + else + // zero case + return formattedAmount; + } + else { + // positive amount with no '+' sign + return formattedAmount; + } + } + }; +}; + + +/** + * @class + * Class for localised formatting of dates and times. + * + *

    See: + * POSIX LC_TIME. + * + * @public + * @constructor + * @description Creates a new date/time formatter for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_TIME formatting properties. + * + * @throws Error on constructor failure. + */ +jsworld.DateTimeFormatter = function(locale) { + + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance."; + + this.lc = locale; + + + /** + * @public + * + * @description Formats a date according to the preset locale. + * + * @param {Date|String} date A valid Date object instance or a string + * containing a valid ISO-8601 formatted date, e.g. "2010-31-03" + * or "2010-03-31 23:59:59". + * + * @returns {String} The formatted date + * + * @throws Error on invalid date argument + */ + this.formatDate = function(date) { + + var d = null; + + if (typeof date == "string") { + // assume ISO-8601 date string + try { + d = jsworld.parseIsoDate(date); + } catch (error) { + // try full ISO-8601 date/time string + d = jsworld.parseIsoDateTime(date); + } + } + else if (date !== null && typeof date == "object") { + // assume ready Date object + d = date; + } + else { + throw "Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"; + } + + return this._applyFormatting(d, this.lc.d_fmt); + }; + + + /** + * @public + * + * @description Formats a time according to the preset locale. + * + * @param {Date|String} date A valid Date object instance or a string + * containing a valid ISO-8601 formatted time, e.g. "23:59:59" + * or "2010-03-31 23:59:59". + * + * @returns {String} The formatted time. + * + * @throws Error on invalid date argument. + */ + this.formatTime = function(date) { + + var d = null; + + if (typeof date == "string") { + // assume ISO-8601 time string + try { + d = jsworld.parseIsoTime(date); + } catch (error) { + // try full ISO-8601 date/time string + d = jsworld.parseIsoDateTime(date); + } + } + else if (date !== null && typeof date == "object") { + // assume ready Date object + d = date; + } + else { + throw "Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"; + } + + return this._applyFormatting(d, this.lc.t_fmt); + }; + + + /** + * @public + * + * @description Formats a date/time value according to the preset + * locale. + * + * @param {Date|String} date A valid Date object instance or a string + * containing a valid ISO-8601 formatted date/time, e.g. + * "2010-03-31 23:59:59". + * + * @returns {String} The formatted time. + * + * @throws Error on invalid argument. + */ + this.formatDateTime = function(date) { + + var d = null; + + if (typeof date == "string") { + // assume ISO-8601 format + d = jsworld.parseIsoDateTime(date); + } + else if (date !== null && typeof date == "object") { + // assume ready Date object + d = date; + } + else { + throw "Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"; + } + + return this._applyFormatting(d, this.lc.d_t_fmt); + }; + + + /** + * @private + * + * @description Apples formatting to the Date object according to the + * format string. + * + * @param {Date} d A valid Date instance. + * @param {String} s The formatting string with '%' placeholders. + * + * @returns {String} The formatted string. + */ + this._applyFormatting = function(d, s) { + + s = s.replace(/%%/g, '%'); + s = s.replace(/%a/g, this.lc.abday[d.getDay()]); + s = s.replace(/%A/g, this.lc.day[d.getDay()]); + s = s.replace(/%b/g, this.lc.abmon[d.getMonth()]); + s = s.replace(/%B/g, this.lc.mon[d.getMonth()]); + s = s.replace(/%d/g, jsworld._zeroPad(d.getDate(), 2)); + s = s.replace(/%e/g, jsworld._spacePad(d.getDate(), 2)); + s = s.replace(/%F/g, d.getFullYear() + + "-" + + jsworld._zeroPad(d.getMonth()+1, 2) + + "-" + + jsworld._zeroPad(d.getDate(), 2)); + s = s.replace(/%h/g, this.lc.abmon[d.getMonth()]); // same as %b + s = s.replace(/%H/g, jsworld._zeroPad(d.getHours(), 2)); + s = s.replace(/%I/g, jsworld._zeroPad(this._hours12(d.getHours()), 2)); + s = s.replace(/%k/g, d.getHours()); + s = s.replace(/%l/g, this._hours12(d.getHours())); + s = s.replace(/%m/g, jsworld._zeroPad(d.getMonth()+1, 2)); + s = s.replace(/%n/g, "\n"); + s = s.replace(/%M/g, jsworld._zeroPad(d.getMinutes(), 2)); + s = s.replace(/%p/g, this._getAmPm(d.getHours())); + s = s.replace(/%P/g, this._getAmPm(d.getHours()).toLocaleLowerCase()); // safe? + s = s.replace(/%R/g, jsworld._zeroPad(d.getHours(), 2) + + ":" + + jsworld._zeroPad(d.getMinutes(), 2)); + s = s.replace(/%S/g, jsworld._zeroPad(d.getSeconds(), 2)); + s = s.replace(/%T/g, jsworld._zeroPad(d.getHours(), 2) + + ":" + + jsworld._zeroPad(d.getMinutes(), 2) + + ":" + + jsworld._zeroPad(d.getSeconds(), 2)); + s = s.replace(/%w/g, this.lc.day[d.getDay()]); + s = s.replace(/%y/g, new String(d.getFullYear()).substring(2)); + s = s.replace(/%Y/g, d.getFullYear()); + + s = s.replace(/%Z/g, ""); // to do: ignored until a reliable TMZ method found + + s = s.replace(/%[a-zA-Z]/g, ""); // ignore all other % sequences + + return s; + }; + + + /** + * @private + * + * @description Does 24 to 12 hour conversion. + * + * @param {integer Number} hour24 Hour [0..23]. + * + * @returns {integer Number} Corresponding hour [1..12]. + */ + this._hours12 = function(hour24) { + + if (hour24 === 0) + return 12; // 00h is 12AM + + else if (hour24 > 12) + return hour24 - 12; // 1PM to 11PM + + else + return hour24; // 1AM to 12PM + }; + + + /** + * @private + * + * @description Gets the appropriate localised AM or PM string depending + * on the day hour. Special cases: midnight is 12AM, noon is 12PM. + * + * @param {integer Number} hour24 Hour [0..23]. + * + * @returns {String} The corresponding localised AM or PM string. + */ + this._getAmPm = function(hour24) { + + if (hour24 < 12) + return this.lc.am; + else + return this.lc.pm; + }; +}; + + + +/** + * @class Class for localised formatting of currency amounts. + * + *

    See: + * POSIX LC_MONETARY. + * + * @public + * @constructor + * @description Creates a new monetary formatter for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_MONETARY formatting properties. + * @param {String} [currencyCode] Set the currency explicitly by + * passing its international ISO-4217 code, e.g. "USD", "EUR", "GBP". + * Use this optional parameter to override the default local currency + * @param {String} [altIntSymbol] Non-local currencies are formatted + * with their international ISO-4217 code to prevent ambiguity. + * Use this optional argument to force a different symbol, such as the + * currency's shorthand sign. This is mostly useful when the shorthand + * sign is both internationally recognised and identifies the currency + * uniquely (e.g. the Euro sign). + * + * @throws Error on constructor failure. + */ +jsworld.MonetaryFormatter = function(locale, currencyCode, altIntSymbol) { + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance"; + + this.lc = locale; + + /** + * @private + * @description Lookup table to determine the fraction digits for a + * specific currency; most currencies subdivide at 1/100 (2 fractional + * digits), so we store only those that deviate from the default. + * + *

    The data is from Unicode's CLDR version 1.7.0. The two currencies + * with non-decimal subunits (MGA and MRO) are marked as having no + * fractional digits as well as all currencies that have no subunits + * in circulation. + * + *

    It is "hard-wired" for referential convenience and is only looked + * up when an overriding currencyCode parameter is supplied. + */ + this.currencyFractionDigits = { + "AFN" : 0, "ALL" : 0, "AMD" : 0, "BHD" : 3, "BIF" : 0, + "BYR" : 0, "CLF" : 0, "CLP" : 0, "COP" : 0, "CRC" : 0, + "DJF" : 0, "GNF" : 0, "GYD" : 0, "HUF" : 0, "IDR" : 0, + "IQD" : 0, "IRR" : 0, "ISK" : 0, "JOD" : 3, "JPY" : 0, + "KMF" : 0, "KRW" : 0, "KWD" : 3, "LAK" : 0, "LBP" : 0, + "LYD" : 3, "MGA" : 0, "MMK" : 0, "MNT" : 0, "MRO" : 0, + "MUR" : 0, "OMR" : 3, "PKR" : 0, "PYG" : 0, "RSD" : 0, + "RWF" : 0, "SLL" : 0, "SOS" : 0, "STD" : 0, "SYP" : 0, + "TND" : 3, "TWD" : 0, "TZS" : 0, "UGX" : 0, "UZS" : 0, + "VND" : 0, "VUV" : 0, "XAF" : 0, "XOF" : 0, "XPF" : 0, + "YER" : 0, "ZMK" : 0 + }; + + + // optional currencyCode argument? + if (typeof currencyCode == "string") { + // user wanted to override the local currency + this.currencyCode = currencyCode.toUpperCase(); + + // must override the frac digits too, for some + // currencies have 0, 2 or 3! + var numDigits = this.currencyFractionDigits[this.currencyCode]; + if (typeof numDigits != "number") + numDigits = 2; // default for most currencies + this.lc.frac_digits = numDigits; + this.lc.int_frac_digits = numDigits; + } + else { + // use local currency + this.currencyCode = this.lc.int_curr_symbol.substring(0,3).toUpperCase(); + } + + // extract intl. currency separator + this.intSep = this.lc.int_curr_symbol.charAt(3); + + // flag local or intl. sign formatting? + if (this.currencyCode == this.lc.int_curr_symbol.substring(0,3)) { + // currency matches the local one? -> + // formatting with local symbol and parameters + this.internationalFormatting = false; + this.curSym = this.lc.currency_symbol; + } + else { + // currency doesn't match the local -> + + // do we have an overriding currency symbol? + if (typeof altIntSymbol == "string") { + // -> force formatting with local parameters, using alt symbol + this.curSym = altIntSymbol; + this.internationalFormatting = false; + } + else { + // -> force formatting with intl. sign and parameters + this.internationalFormatting = true; + } + } + + + /** + * @public + * + * @description Gets the currency symbol used in formatting. + * + * @returns {String} The currency symbol. + */ + this.getCurrencySymbol = function() { + + return this.curSym; + }; + + + /** + * @public + * + * @description Gets the position of the currency symbol relative to + * the amount. Assumes a non-negative amount and local formatting. + * + * @param {String} intFlag Optional flag to force international + * formatting by passing the string "i". + * + * @returns {Boolean} True if the symbol precedes the amount, false if + * the symbol succeeds the amount. + */ + this.currencySymbolPrecedes = function(intFlag) { + + if (typeof intFlag == "string" && intFlag == "i") { + // international formatting was forced + if (this.lc.int_p_cs_precedes == 1) + return true; + else + return false; + + } + else { + // check whether local formatting is on or off + if (this.internationalFormatting) { + if (this.lc.int_p_cs_precedes == 1) + return true; + else + return false; + } + else { + if (this.lc.p_cs_precedes == 1) + return true; + else + return false; + } + } + }; + + + /** + * @public + * + * @description Gets the decimal delimiter (radix) used in formatting. + * + * @returns {String} The radix character. + */ + this.getDecimalPoint = function() { + + return this.lc.mon_decimal_point; + }; + + + /** + * @public + * + * @description Gets the number of fractional digits. Assumes local + * formatting. + * + * @param {String} intFlag Optional flag to force international + * formatting by passing the string "i". + * + * @returns {integer Number} The number of fractional digits. + */ + this.getFractionalDigits = function(intFlag) { + + if (typeof intFlag == "string" && intFlag == "i") { + // international formatting was forced + return this.lc.int_frac_digits; + } + else { + // check whether local formatting is on or off + if (this.internationalFormatting) + return this.lc.int_frac_digits; + else + return this.lc.frac_digits; + } + }; + + + /** + * @public + * + * @description Formats a monetary amount according to the preset + * locale. + * + *

    +	 * For local currencies the native shorthand symbol will be used for
    +	 * formatting.
    +	 * Example:
    +	 *        locale is en_US
    +	 *        currency is USD
    +	 *        -> the "$" symbol will be used, e.g. $123.45
    +	 *        
    +	 * For non-local currencies the international ISO-4217 code will be
    +	 * used for formatting.
    +	 * Example:
    +	 *       locale is en_US (which has USD as currency)
    +	 *       currency is EUR
    +	 *       -> the ISO three-letter code will be used, e.g. EUR 123.45
    +	 *
    +	 * If the currency is non-local, but an alternative currency symbol was
    +	 * provided, this will be used instead.
    +	 * Example
    +	 *       locale is en_US (which has USD as currency)
    +	 *       currency is EUR
    +	 *       an alternative symbol is provided - "€"
    +	 *       -> the alternative symbol will be used, e.g. €123.45
    +	 * 
    + * + * @param {Number|String} amount The amount to format as currency. + * @param {String} [options] Options to modify the formatted output: + *
    '; +html += '
    Enter Your Password
    '; +html += '
    '; +html += '
    Password:


    '; +html += '
    '; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "clear_login()") + ' ' + large_icon_button('check', 'Login', 'do_effect_login()') + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ENTER_KEY] = 'do_effect_login'; +session.hooks.keys[ESC_KEY] = 'clear_login'; +safe_focus( 'fe_lp_password' ); +show_popup_dialog(450, 225, html); +} +function clear_login() { +hide_popup_dialog(); +Nav.prev(); +} +function do_login() { +if ($('fe_username').value.match(/^\w+$/)) { +session.username = $('fe_username').value; +session.auto_login = $('fe_auto_login').checked; +do_login_prompt_2(); +return; +} +else { +do_openid_login(); +} +} +function do_openid_login() { +if (!$('fe_username').value) return; +session.openid_win = popup_window(''); +if (!session.openid_win) return; +session.open_id = $('fe_username').value; +session.auto_login = $('fe_auto_login') && $('fe_auto_login').checked; +hide_popup_dialog(); +show_progress_dialog(1, "Logging in..."); +session.hooks.before_error = 'close_openid_window'; +session.hooks.after_error = 'do_login_prompt'; +effect_api_send('openid_login', { +OpenID: session.open_id, +Infinite: session.auto_login ? 1 : 0 +}, 'do_openid_login_2'); +} +function close_openid_window() { +if (session.openid_win) { +session.openid_win.close(); +delete session.openid_win; +} +} +function do_openid_login_2(response) { +if (response.CheckURL) { +Debug.trace('openid', "Redirecting popup window to OpenID Check URL: " + response.CheckURL); +show_progress_dialog(1, "Waiting for popup window...", false, ['x', 'Cancel', 'do_login_prompt()']); +session.openid_win.location = response.CheckURL; +session.openid_win.focus(); +} +} +function receive_openid_response(iframe_response) { +var response = deep_copy_object(iframe_response); +Debug.trace('openid', "Received OpenID Response: " + dumper(response)); +hide_popup_dialog(); +if (response.Code) { +close_openid_window(); +return do_error( response.Description ); +} +delete session.hooks.before_error; +delete session.hooks.after_error; +if (response.SessionID) { +session.cookie.set( 'effect_session_id', response.SessionID ); +session.cookie.save(); +} +switch (response.Action) { +case 'popup': +show_progress_dialog(1, "Waiting for popup window...", false, ['x', 'Cancel', 'do_login_prompt()']); +Debug.trace('openid', "Redirecting popup window to OpenID Setup URL: " + response.SetupURL); +session.openid_win.location = response.SetupURL; +session.openid_win.focus(); +break; +case 'login': +close_openid_window(); +do_login_2(response); +break; +case 'register': +if (!response.Info) response.Info = {}; +close_openid_window(); +Debug.trace('openid', 'Original OpenID: ' + response.OpenID_Login); +Debug.trace('openid', 'Clean OpenID: ' + response.OpenID_Unique); +Debug.trace('openid', 'Registration Info: ' + dumper(response.Info)); +session.prereg = response.Info; +session.prereg.open_id_login = response.OpenID_Login; +session.prereg.open_id = response.OpenID_Unique; +if (session.user) { +if (!session.user.OpenIDs) session.user.OpenIDs = {}; +if (!session.user.OpenIDs.OpenID) session.user.OpenIDs.OpenID = []; +var dupe = find_object( session.user.OpenIDs.OpenID, { Unique: session.prereg.open_id } ); +if (dupe) return do_error("That OpenID is already registered and attached to your account. No need to add it again."); +session.user.OpenIDs.OpenID.push({ +Login: session.prereg.open_id_login, +Unique: session.prereg.open_id +}); +setTimeout( function() { +Nav.go('MyAccount', true); +do_message('success', 'Added new OpenID URL to account.'); +}, 1 ); +} +else { +setTimeout( function() { Nav.go('CreateAccount', true); }, 1 ); +} +break; +} +} +function do_effect_login() { +var password = $('fe_lp_password').value; +session.auto_login = $('fe_auto_login').checked; +hide_popup_dialog(); +show_progress_dialog(1, "Logging in..."); +session.hooks.after_error = 'do_login_prompt'; +effect_api_send('user_login', { +Username: session.username, +Password: password, +Infinite: session.auto_login ? 1 : 0 +}, 'do_login_2'); +} +function do_logout() { +effect_api_send('user_logout', {}, 'do_logout_2'); +} +function do_logout_2(response) { +hide_popup_dialog(); +show_default_login_status(); +delete session.hooks.after_error; +delete session.cookie.tree.effect_session_id; +session.cookie.save(); +session.storage = {}; +session.storage_dirty = false; +delete session.user; +delete session.first_login; +var old_username = session.username; +session.username = ''; +if (Nav.inited) { +Nav.go('Main'); +if (old_username) $GR.growl('success', "Logged out of account: " + old_username); +} +else { +Nav.init(); +} +} +function do_login_2(response, tx) { +if (response.FirstLogin) session.first_login = 1; +if (response.User.UserStorage) { +Debug.trace('Recovering site storage blob: session.storage = ' + response.User.UserStorage + ';'); +try { +eval( 'session.storage = ' + response.User.UserStorage + ';' ); +} +catch (e) { +Debug.trace("SITE STORAGE RECOVERY FAILED: " + e); +session.storage = {}; +} +delete response.User.UserStorage; +session.storage_dirty = false; +} +session.user = response.User; +session.username = session.user.Username; +hide_popup_dialog(); +delete session.hooks.after_error; +update_header(); +if (!tx || !tx._from_recover) $GR.growl('success', "Logged in as: " + session.username); +if (session.nav_after_login) { +Nav.go( session.nav_after_login ); +delete session.nav_after_login; +} +else if (Nav.currentAnchor().match(/^Login/)) { +Nav.go('Home'); +} +else { +Nav.refresh(); +} +Nav.init(); +} +function user_storage_mark() { +Debug.trace("Marking user storage as dirty"); +session.storage_dirty = true; +} +function user_storage_idle() { +if (session.storage_dirty && !session.mouseIsDown) { +user_storage_save(); +session.storage_dirty = false; +} +setTimeout( 'user_storage_idle()', 5000 ); +} +function user_storage_save() { +if (session.user) { +Debug.trace("Committing user storage blob"); +effect_api_send('update_user_storage', { Data: serialize(session.storage) }, 'user_storage_save_finish', { _silent: 1 } ); +} +} +function user_storage_save_finish(response, tx) { +} +function show_default_login_status() { +$('d_sidebar_wrapper_recent_games').hide(); +$('d_login_status').innerHTML = '
    ' + +'
    ' + +large_icon_button('key', "Login", '#Home') + '' + spacer(1,1) + '' + +'' + large_icon_button('user_add.png', "Signup", '#CreateAccount') + '
    ' + +'
    '; +$('d_tagline').innerHTML = +'Login' + ' | ' + +'Create Account'; +} +function update_header() { +var html = ''; +html += '
    '; +html += ''; +html += ''; +html += ''; +html += ''+spacer(2,2)+''; +html += session.user.FullName + '
    '; +html += spacer(1,5) + '
    '; +html += 'My Home  |  '; +html += 'Logout'; +html += '
    '; +$('d_login_status').innerHTML = html; +$('d_tagline').innerHTML = +'Welcome '+session.user.FirstName+'' + ' | ' + +'My Home' + ' | ' + +'Logout'; +effect_api_get( 'get_user_games', { limit:5, offset:0 }, 'receive_sidebar_recent_games', { } ); +} +function receive_sidebar_recent_games(response, tx) { +var html = ''; +if (response.Rows && response.Rows.Row) { +var games = always_array( response.Rows.Row ); +for (var idx = 0, len = games.length; idx < len; idx++) { +var game = games[idx]; +html += ''; +} +html += ''; +$('d_sidebar_recent_games').innerHTML = html; +$('d_sidebar_wrapper_recent_games').show(); +} +else { +$('d_sidebar_wrapper_recent_games').hide(); +} +} +function check_privilege(key) { +if (!session.user) return false; +if (session.user.Privileges.admin == 1) return true; +if (!key.toString().match(/^\//)) key = '/' + key; +var value = lookup_path(key, session.user.Privileges); +return( value && (value != 0) ); +} +function is_admin() { +return check_privilege('admin'); +} +function upgrade_flash_error() { +return alert("Sorry, file upload requires Adobe Flash Player 9 or higher."); +} +function cancel_user_image_manager() { +upload_destroy(); +hide_popup_dialog(); +delete session.hooks.keys[DELETE_KEY]; +} +function do_user_image_manager(callback) { +if (callback) session.uim_callback = callback; +else session.uim_callback = null; +session.temp_last_user_img = null; +session.temp_last_user_image_filename = ''; +var html = '
    '; +html += '
    Image Manager
    '; +html += '
    '; +html += ''; +html += '
    '; +html += '
    '; +html += ''; +html += ''; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', 'cancel_user_image_manager()') + ' ' + large_icon_button('bullet_upload.png', 'Upload Files...', 'upload_basic()', 'b_upload_user_image') + ' ' + large_icon_button('check', 'Choose', 'do_choose_user_image()', 'btn_choose_user_image', '', 'disabled') + '
    '; +html += '
    '; +session.hooks.keys[ENTER_KEY] = 'do_choose_user_image'; +session.hooks.keys[ESC_KEY] = 'cancel_user_image_manager'; +session.hooks.keys[DELETE_KEY] = 'do_delete_selected_user_image'; +show_popup_dialog(500, 300, html); +var self = this; +setTimeout( function() { +prep_upload('b_upload_user_image', '/effect/api/upload_user_image', [self, 'do_upload_user_image_2'], ['Image Files', '*.jpg;*.jpe;*.jpeg;*.gif;*.png']); +}, 1 ); +var args = { +limit: 50, +offset: 0, +random: Math.random() +}; +effect_api_get( 'user_images_get', args, 'uim_populate_images', { } ); +} +function do_upload_user_image_2() { +effect_api_mod_touch('user_images_get'); +effect_api_send('user_get', { +Username: session.username +}, [this, 'do_upload_user_image_3']); +} +function do_upload_user_image_3(response) { +if (response.User.LastUploadError) return do_error( "Failed to upload image: " + response.User.LastUploadError ); +do_user_image_manager( session.uim_callback ); +} +function uim_populate_images(response, tx) { +var html = ''; +var base_url = '/effect/api/view/users/' + session.username + '/images'; +if (response.Rows && response.Rows.Row) { +var imgs = always_array( response.Rows.Row ); +for (var idx = 0, len = imgs.length; idx < len; idx++) { +var img = imgs[idx]; +var class_name = ((img.Filename == session.temp_last_user_image_filename) ? 'choose_item_selected' : 'choose_item'); +html += ''; +} +} +else { +html = ''; +} +$('d_user_image_list').innerHTML = html; +} +function do_select_user_image(img, filename) { +if (session.temp_last_user_img) session.temp_last_user_img.className = 'choose_item'; +img.className = 'choose_item_selected'; +$('btn_choose_user_image').removeClass('disabled'); +session.temp_last_user_img = img; +session.temp_last_user_image_filename = filename; +} +function do_delete_selected_user_image() { +if (session.temp_last_user_image_filename) { +effect_api_send('user_image_delete', { Filename: session.temp_last_user_image_filename }, 'do_delete_selected_user_image_finish', {}); +} +} +function do_delete_selected_user_image_finish(response, tx) { +try { $('d_user_image_list').removeChild( session.temp_last_user_img ); } catch(e) {;} +session.temp_last_user_img = null; +session.temp_last_user_image_filename = null; +} +function do_choose_user_image() { +if (!session.temp_last_user_image_filename) return; +if (session.uim_callback) { +fire_callback( session.uim_callback, session.temp_last_user_image_filename ); +} +cancel_user_image_manager(); +} +function user_image_thumbnail(filename, width, height, attribs) { +var username = session.username; +if (filename.match(/^(\w+)\/(.+)$/)) { +username = RegExp.$1; +filename = RegExp.$2; +} +var url = '/effect/api/view/users/' + username + '/images/' + filename.replace(/\.(\w+)$/, '_thumb.jpg'); +return ''; +} +function get_user_display(username, full_name, base_url) { +if (!base_url) base_url = ''; +return icon('user', full_name || username, base_url + '#User/' + username); +} +function get_game_tab_bar(game_id, cur_page_name) { +return tab_bar([ +['#Game/' + game_id, 'Game', 'controller.png'], +['#GameDisplay/' + game_id, 'Display', 'monitor.png'], +['#GameAssets/' + game_id, 'Assets', 'folder_page_white.png'], +['#GameObjects/' + game_id, 'Objects', 'bricks.png'], +['#GameAudio/' + game_id, 'Audio', 'sound.gif'], +['#GameKeys/' + game_id, 'Keyboard', 'keyboard.png'], +['#GameLevels/' + game_id, 'Levels', 'world.png'], +['#GamePublisher/' + game_id, 'Publish', 'cd.png'] +], cur_page_name); +} +function get_user_tab_bar(cur_page_name) { +var tabs = [ +['#Home', 'My Home', 'house.png'] +]; +tabs.push( ['#MyAccount', 'Edit Account', 'user_edit.png'] ); +tabs.push( ['#ArticleEdit', 'Post Article', 'page_white_edit.png'] ); +if (config.ProEnabled) { +tabs.push( ['#UserPayments', 'Payments', 'money.png'] ); +} +tabs.push( ['#UserLog', 'Security Log', 'application_view_detail.png'] ); +return tab_bar(tabs, cur_page_name); +} +function get_admin_tab_bar(cur_page_name) { +var tabs = []; +tabs.push( ['#Admin', 'Admin', 'lock.png'] ); +tabs.push( ['#TicketSearch/bugs', 'Bug Tracker', 'bug.png'] ); +tabs.push( ['#TicketSearch/helpdesk', 'Help Desk', 'telephone.png'] ); +tabs.push( ['#AdminReport', 'Reports', 'chart_pie.png'] ); +return tab_bar(tabs, cur_page_name); +} +function get_string(path, args) { +assert(window.config, "get_string() called before config loaded"); +if (!args) args = {}; +args.config = config; +args.session = session; +args.query = session.query; +var value = lookup_path(path, config.Strings); +return (typeof(value) == 'string') ? substitute(value, args) : value; +} +function normalize_dir_path(path) { +if (!path.match(/^\//)) path = '/' + path; +if (!path.match(/\/$/)) path += '/'; +return path; +} +function textedit_window_save(storage_key, filename, content, callback) { +if (!callback) callback = null; +effect_api_mod_touch('textedit'); +if (storage_key.match(/^\/games\/([a-z0-9][a-z0-9\-]*[a-z0-9])\/assets(.+)$/)) { +var game_id = RegExp.$1; +var path = RegExp.$2; +show_progress_dialog(1, "Saving file..."); +effect_api_send('asset_save_file_contents', { +GameID: game_id, +Path: path, +Filename: filename, +Content: content +}, 'textedit_window_save_finish', { _mode: 'asset', _game_id: game_id, _filename: filename, _callback: callback } ); +} +else { +show_progress_dialog(1, "Saving data..."); +effect_api_send('admin_save_file_contents', { +Path: storage_key, +Filename: filename, +Content: content +}, 'textedit_window_save_finish', { _mode: 'admin', _storage_key: storage_key, _filename: filename, _callback: callback } ); +} +} +function textedit_window_save_finish(response, tx) { +hide_progress_dialog(); +if (tx._mode == 'asset') { +do_message('success', "Saved asset: \""+tx._filename+"\""); +show_glog_widget(); +} +else { +do_message('success', "Saved data: \""+tx._storage_key+'/'+tx._filename+"\""); +} +if (tx._callback) tx._callback(); +} +function do_buy(args) { +$P().hide(); +$('d_page_loading').show(); +effect_api_send('create_order', args, 'do_buy_redirect', { _buy_args: args } ); +} +function do_buy_redirect(response, tx) { +var args = tx._buy_args; +$('fe_gco_title').value = args.Title || ''; +$('fe_gco_desc').value = args.Desc || ''; +$('fe_gco_price').value = args.Price || ''; +$('fe_gco_after').value = args.After || ''; +$('fe_gco_unique_id').value = response.OrderID; +Debug.trace('payment', "Redirecting to Google Checkout"); +setTimeout( function() { $('BB_BuyButtonForm').submit(); }, 1 ); +} +function show_glog_widget(game_id) { +if (!game_id) game_id = session.glog_game_id; +if (!game_id) { +$('glog_widget').hide(); +return; +} +if (game_id != session.glog_game_id) { +$('glog_widget').hide(); +session.glog_game_id = game_id; +update_glog_widget(game_id); +} +else { +$('glog_widget').show(); +setTimeout( function() { update_glog_widget(game_id); }, 500 ); +} +} +function update_glog_widget(game_id) { +effect_api_get('game_get_log', { +id: game_id, +offset: 0, +limit: 1, +rand: Math.random() +}, 'receive_glog_data', { _game_id: game_id }); +} +function receive_glog_data(response, tx) { +var game_id = tx._game_id; +if (response && response.Rows && response.Rows.Row) { +var rows = always_array( response.Rows.Row ); +var row = rows[0]; +var html = ''; +html += '
    '; +html += '
    Latest Game Activity
    '; +html += ''; +html += ''; +html += '
    '; +html += '
    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + get_buddy_icon_display(row.Username, 1, 0) + ''; +html += '
    ' + icon( get_icon_for_glog_type(row.Type), ''+row.Message+'' ) + '
    '; +html += '
    ' + get_relative_date(row.Date, true) + '
    '; +html += '
    '; +$('glog_widget').innerHTML = html; +$('glog_widget').show(); +} +} +function show_glog_post_dialog(game_id) { +hide_popup_dialog(); +delete session.progress; +var html = ''; +html += '
    '; +html += '\n \n \n \n'); + }; + __out.push('\n\n'); + __out.push(require('templates/clients/modules/sub_header').call(this, { + heading: t("Ride Request") + })); + __out.push('\n\n\n
    \n
    \n
    \n
    \n \n \n \n \n
    \n\n
    '; +html += '
    Post Game Log Message
    '; +html += '
    '; +html += ''; +html += '
    Enter your log message here. Plain text only please.
    '; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', 'Post Message', "glog_post('"+game_id+"')") + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_glog_body' ); +show_popup_dialog(500, 175, html); +} +function glog_post(game_id) { +var msg = trim( $('fe_glog_body').value ); +if (msg) { +hide_popup_dialog(); +effect_api_send('game_post_log', { +GameID: game_id, +Message: msg +}, [this, 'glog_post_finish'], { _game_id: game_id }); +} +} +function glog_post_finish(response, tx) { +show_glog_widget( tx._game_id ); +} +function hide_glog_widget() { +$('glog_widget').hide(); +} +function get_icon_for_glog_type(type) { +var icon = 'page_white.png'; +switch (type) { +case 'asset': icon = 'folder_page_white.png'; break; +case 'game': icon = 'controller.png'; break; +case 'member': icon = 'user'; break; +case 'comment': icon = 'comment.png'; break; +case 'level': icon = 'world.png'; break; +case 'sprite': icon = 'cog.png'; break; +case 'tile': icon = 'brick.png'; break; +case 'tileset': icon = 'color_swatch.png'; break; +case 'rev': icon = 'cd.png'; break; +case 'revision': icon = 'cd.png'; break; +case 'font': icon = 'style.png'; break; +case 'key': icon = 'keyboard.png'; break; +case 'audio': icon = 'sound'; break; +case 'payment': icon = 'money.png'; break; +case 'env': icon = 'weather.png'; break; +case 'environment': icon = 'weather.png'; break; +} +return icon; +} +function effect_load_script(url) { +Debug.trace('api', 'Loading script: ' + url); +load_script(url); +} +function effect_api_get_ie(cmd, params, userData) { +if (!session.api_state_ie) session.api_state_ie = {}; +var unique_id = get_unique_id(); +session.api_state_ie[unique_id] = userData; +params.format = 'js'; +params.onafter = 'effect_api_response_ie(' + unique_id + ', response);'; +var url = '/effect/api/' + cmd + composeQueryString(params); +Debug.trace('api', "Sending MSIE HTTP GET: " + url); +load_script(url); +} +function effect_api_response_ie(unique_id, tree) { +Debug.trace('api', "Got response from MSIE HTTP GET"); +var tx = session.api_state_ie[unique_id]; +delete session.api_state_ie[unique_id]; +if (tree.Code == 'session') { +do_logout_2(); +return; +} +if (tree.Code == 'access') { +do_notice("Access Denied", tree.Description, 'do_not_pass_go'); +return; +} +if (tree.Code != 0) { +if (tx._on_error) return fire_callback( tx._on_error, tree, tx ); +return do_error( tree.Description ); +} +if (tree.SessionID) { +if (tree.SessionID == '_DELETE_') { +delete session.cookie.tree.effect_session_id; +} +else { +session.cookie.set( 'effect_session_id', tree.SessionID ); +} +session.cookie.save(); +} +if (tx._api_callback) { +fire_callback( tx._api_callback, tree, tx ); +} +} +function effect_api_get(cmd, params, callback, userData) { +if (!userData) userData = {}; +userData._api_callback = callback; +if (!session.api_mod_cache[cmd] && session.username) session.api_mod_cache[cmd] = hires_time_now(); +if (!params.mod && session.api_mod_cache[cmd]) params.mod = session.api_mod_cache[cmd]; +if (ie) return effect_api_get_ie(cmd, params, userData); +var url = '/effect/api/' + cmd + composeQueryString(params); +Debug.trace('api', "Sending HTTP GET: " + url); +ajax.get( url, 'effect_api_response', userData ); +} +function effect_api_send(cmd, xml, callback, userData) { +if (!userData) userData = {}; +userData._api_callback = callback; +var data = compose_xml('EffectRequest', xml); +Debug.trace('api', "Sending API Command: " + cmd + ": " + data); +ajax.send({ +method: 'POST', +url: '/effect/api/' + cmd, +data: data, +headers: { 'Content-Type': 'text/xml' } +}, 'effect_api_response', userData); +} +function effect_api_response(tx) { +Debug.trace('api', "HTTP " + tx.response.code + ": " + tx.response.data); +if (tx.response.code == 999) { +if (tx.request._auto_retry) { +session.net_error = false; +show_progress_dialog(1, "Trying to reestablish connection..."); +session.net_error = true; +setTimeout( function() { ajax.send(tx.request); }, 1000 ); +return; +} +else return do_error( "HTTP ERROR: " + tx.response.code + ": " + tx.response.data + ' (URL: ' + tx.request.url + ')' ); +} +if (session.net_error) { +hide_progress_dialog(); +session.net_error = false; +} +if (tx.response.code != 200) { +if (tx._silent) return; +else return do_error( "HTTP ERROR: " + tx.response.code + ": " + tx.response.data + ' (URL: ' + tx.request.url + ')' ); +} +var tree = null; +if (!tx._raw) { +var parser = new XML({ +preserveAttributes: true, +text: tx.response.data +}); +if (parser.getLastError()) return do_error("XML PARSE ERROR: " + parser.getLastError()); +tree = parser.getTree(); +if (tree.Code == 'session') { +do_logout_2(); +return; +} +if (tree.Code == 'access') { +do_notice("Access Denied", tree.Description, 'do_not_pass_go'); +return; +} +if (tree.Code != 0) { +if (tx._on_error) return fire_callback( tx._on_error, tree, tx ); +return do_error( tree.Description ); +} +if (tree.SessionID) { +if (tree.SessionID == '_DELETE_') { +delete session.cookie.tree.effect_session_id; +} +else { +session.cookie.set( 'effect_session_id', tree.SessionID ); +} +session.cookie.save(); +} +} +if (tx._api_callback) { +fire_callback( tx._api_callback, tree, tx ); +} +} +function effect_api_mod_touch() { +for (var idx = 0, len = arguments.length; idx < len; idx++) { +session.api_mod_cache[ arguments[idx] ] = hires_time_now(); +} +} +function do_not_pass_go() { +Nav.go('Main'); +} +var Nav = { +loc: '', +old_loc: '', +inited: false, +nodes: [], +init: function() { +if (!this.inited) { +this.inited = true; +this.loc = 'init'; +this.monitor(); +} +}, +monitor: function() { +var parts = window.location.href.split(/\#/); +var anchor = parts[1]; +if (!anchor) anchor = 'Main'; +var full_anchor = '' + anchor; +var sub_anchor = ''; +anchor = anchor.replace(/\%7C/, '|'); +if (anchor.match(/\|(\w+)$/)) { +sub_anchor = RegExp.$1.toLowerCase(); +anchor = anchor.replace(/\|(\w+)$/, ''); +} +if ((anchor != this.loc) && !anchor.match(/^_/)) { +Debug.trace('nav', "Caught navigation anchor: " + full_anchor); +var page_name = ''; +var page_args = null; +if (full_anchor.match(/^\w+\?.+/)) { +parts = full_anchor.split(/\?/); +page_name = parts[0]; +page_args = parseQueryString( parts[1] ); +} +else if (full_anchor.match(/^(\w+)\/(.*)$/)) { +page_name = RegExp.$1; +page_args = RegExp.$2; +} +else { +parts = full_anchor.split(/\//); +page_name = parts[0]; +page_args = parts.slice(1); +} +Debug.trace('nav', "Calling page: " + page_name + ": " + serialize(page_args)); +hide_popup_dialog(); +var result = page_manager.click( page_name, page_args ); +if (result) { +if (window.pageTracker && (this.loc != 'init')) { +setTimeout( function() { pageTracker._trackPageview('/effect/' + anchor); }, 1000 ); +} +this.old_loc = this.loc; +if (this.old_loc == 'init') this.old_loc = 'Main'; +this.loc = anchor; +} +else { +this.go( this.loc ); +} +} +else if (sub_anchor != this.sub_anchor) { +Debug.trace('nav', "Caught sub-anchor: " + sub_anchor); +$P().gosub( sub_anchor ); +} +this.sub_anchor = sub_anchor; +setTimeout( 'Nav.monitor()', 100 ); +}, +go: function(anchor, force) { +anchor = anchor.replace(/^\#/, ''); +if (force) this.loc = 'init'; +window.location.href = '#' + anchor; +}, +prev: function() { +this.go( this.old_loc || 'Main' ); +}, +refresh: function() { +this.loc = 'refresh'; +}, +bar: function() { +var nodes = arguments; +var html = ''; +for (var idx = 0, len = nodes.length; idx < len; idx++) { +var node = nodes[idx]; +if (node) this.nodes[idx] = node; +else node = this.nodes[idx]; +if (node != '_ignore_') { +html += ''; +} +} +html += '
    '; +$('d_nav_bar').innerHTML = html; +}, +title: function(name) { +if (name) document.title = name + ' | EffectGames.com'; +else document.title = 'EffectGames.com'; +}, +currentAnchor: function() { +var parts = window.location.href.split(/\#/); +var anchor = parts[1] || ''; +var sub_anchor = ''; +anchor = anchor.replace(/\%7C/, '|'); +if (anchor.match(/\|(\w+)$/)) { +sub_anchor = RegExp.$1.toLowerCase(); +anchor = anchor.replace(/\|(\w+)$/, ''); +} +return anchor; +} +}; +var Blog = { +edit_caption: '
    *Bold*  |Italic|  {monospace}  [http://link]  Formatting Guide...
    ', +search: function(args) { +if (!args.mode) args.mode = 'and'; +if (!args.offset) args.offset = 0; +if (!args.limit) args.limit = 10; +if (!args.format) args.format = 'xml'; +var query_args = copy_object( args ); +delete query_args.callback; +effect_api_get( 'article_search', query_args, [this, 'search_response'], { _search_args: args } ); +}, +get_article_preview: function(row, args) { +var html = ''; +Debug.trace('blog', 'Row: ' + dumper(row)); +html += '
    '; +var ext_article_url = 'http://' + location.hostname + '/effect/article.psp.html' + row.Path + '/' + row.ArticleID; +var article_url = '#Article' + row.Path + '/' + row.ArticleID; +html += ''; +if (!args.title_only) { +html += '
    '; +html += row.Preview; +html += '  ' + (args.link_title || 'Read Full Story...') + ''; +html += '
    '; +html += ''; +html += '
    '; +var elem_class = args.footer_element_class || 'blog_preview_footer_element'; +if ((session.username == row.Username) || is_admin()) { +html += '
    ' + +icon('page_white_edit.png', "Edit", '#ArticleEdit?path=' + row.Path + '&id=' + row.ArticleID) + '
    '; +} +html += '
    ' + get_user_display(row.Username) + '
    '; +html += '
    ' + icon('calendar', get_short_date_time(row.Published)) + '
    '; +html += '
    ' + icon('talk', row.Comments) + '
    '; +if (0 && row.Tags) html += '
    ' + icon('note.png', make_tag_links(row.Tags, 3)) + '
    '; +html += '
    ' + icon('facebook.png', 'Facebook', "window.open('http://www.facebook.com/sharer.php?u="+encodeURIComponent(ext_article_url)+'&t='+encodeURIComponent(row.Title)+"','sharer','toolbar=0,status=0,width=626,height=436')", "Share on Facebook") + '
    '; +html += '
    ' + icon('twitter.png', 'Twitter', "window.open('http://twitter.com/home?status=Reading%20" + encodeURIComponent(row.Title) + "%3A%20" + encodeURIComponent(ext_article_url)+"')", "Share on Twitter") + '
    '; +html += '
    '; +html += '
    '; +html += '
    '; +} +html += '
    '; +return html; +}, +search_response: function(response, tx) { +var args = tx._search_args; +if (args.callback) return fire_callback(args.callback, response, args); +var div = $(args.target); +assert(div, "Could not find target DIV: " + args.target); +var html = ''; +if (response.Rows && response.Rows.Row) { +var rows = always_array( response.Rows.Row ); +for (var idx = 0, len = rows.length; idx < len; idx++) { +var row = rows[idx]; +html += this.get_article_preview( row, args ); +} +if (args.more && (rows.length == args.limit)) { +html += large_icon_button('page_white_put.png', 'More...', "Blog.more(this, "+encode_object(args)+")") + '
    '; +html += spacer(1,15) + '
    '; +} +if (args.after) html += args.after; +} +else if (response.Code != 0) { +html = 'Search Error: ' . response.Code + ': ' + response.Description; +} +else { +html = args.none_found_msg || 'No articles found.'; +} +div.innerHTML = html; +}, +more: function(div, args) { +args.offset += args.limit; +Debug.trace('blog', "More Args: " + dumper(args)); +div.innerHTML = ''; +effect_api_get( 'article_search', args, [this, 'more_response'], { _search_args: args, _div: div } ); +}, +more_response: function(response, tx) { +var args = tx._search_args; +var button = tx._div; +var html = ''; +if (response.Rows && response.Rows.Row) { +var rows = always_array( response.Rows.Row ); +for (var idx = 0, len = rows.length; idx < len; idx++) { +var row = rows[idx]; +html += this.get_article_preview( row, args ); +} +if (args.more && (rows.length == args.limit)) { +html += large_icon_button('page_white_put.png', 'More...', "Blog.more(this, "+encode_object(args)+")") + '
    '; +html += spacer(1,15) + '
    '; +} +} +else if (response.Code != 0) { +html = 'Search Error: ' . response.Code + ': ' + response.Description; +} +else { +html = args.none_found_msg || 'No more articles found.'; +} +var div = document.createElement('div'); +div.innerHTML = html; +button.parentNode.replaceChild( div, button ); +} +}; +function make_tag_links(csv, max, base_url) { +if (!base_url) base_url = ''; +var tags = csv.split(/\,\s*/); +var append = ''; +if (max && (tags.length > max)) { +tags.length = max; +append = '...'; +} +var html = ''; +for (var idx = 0, len = tags.length; idx < len; idx++) { +html += ''+tags[idx]+''; +if (idx < len - 1) html += ', '; +} +html += append; +return html; +} +function get_url_friendly_title(title) { +title = title.toString().replace(/\W+/g, '_'); +if (title.length > 40) title = title.substring(0, 40); +title = title.replace(/^_+/, ''); +title = title.replace(/_+$/, ''); +return title; +} +function get_full_url(url) { +if (url.match(/^\#/)) { +var parts = window.location.href.split(/\#/); +url = parts[0] + url; +} +return url; +} +var Comments = { +comments_per_page: 10, +get: function(page_id) { +var html = ''; +html += '
    '; +html += '
    Comments'; +html += '
    '; +html += '
    '; +html += '
    '; +setTimeout( function() { Comments.search({ page_id: page_id }); }, 1 ); +return html; +}, +search: function(args) { +if (!args.limit) args.limit = this.comments_per_page; +if (!args.offset) args.offset = 0; +assert(args.page_id, "Comments.search: No page_id specified"); +args.format = 'xml'; +this.last_search = args; +effect_api_get( 'comments_get', args, [this, 'search_response'], { _search_args: args } ); +}, +research: function(offset) { +var args = this.last_search; +if (!args) return; +args.offset = offset; +effect_api_get( 'comments_get', args, [this, 'search_response'], { _search_args: args } ); +}, +search_response: function(response, tx) { +this.comments = []; +var args = tx._search_args; +if (args.callback) return fire_callback(args.callback, response, args); +var html = ''; +html += '
    ' + +large_icon_button( 'comment_edit.png', 'Post Comment...', "Comments.add('"+args.page_id+"')" ) + '
    '; +if (args.page_id.match(/^Article\//)) { +html += '
    ' + icon('feed.png', 'RSS', '/effect/api/comment_feed/' + args.page_id + '.rss', 'Comments RSS Feed') + '
    '; +} +if (response.Items && response.Items.Item && response.List && response.List.length) { +html += ''; +html += '
    '; +var items = this.comments = always_array( response.Items.Item ); +for (var idx = 0, len = items.length; idx < len; idx++) { +var item = items[idx]; +var extra_classes = (args.highlight && (args.highlight == item.ID)) ? ' highlight' : ''; +html += '
    '; +html += '
    '; +if (item.Username) html += ''; +html += '' + item.Name.toString().toUpperCase() + ''; +if (item.Username) html += ''; +html += ', ' + get_short_date_time(item.Date) + '
    '; +html += '
    '; +html += this.get_comment_controls( args.page_id, item ); +html += '
    '; +html += '
    '; +html += '
    ' + item.Comment + '
    '; +html += '
    '; +html += ''; +if (item.LastReply && ((item.LastReply >= time_now() - (86400 * 7)) || (session.username && (session.username == item.Username)))) { +setTimeout( "Comments.show_replies('"+args.page_id+"','"+item.ID+"')", 1 ); +} +} +} +else { +} +$( 'd_comments_' + args.page_id ).innerHTML = html; +}, +get_control: function(icon, code, text, status_text) { +if (!icon.match(/\.\w+$/)) icon += '.gif'; +return '' + code_link(code, text, status_text) + ''; +}, +get_comment_controls: function(page_id, comment) { +var html = ''; +var spacer_txt = '  |  '; +if (session.user) { +html += this.get_control('comment', "Comments.reply('"+page_id+"','"+comment.ID+"')", 'Reply') + spacer_txt; +} +if (comment.Replies) { +if (comment._replies_visible) html += this.get_control('magnify_minus', "Comments.hide_replies('"+page_id+"','"+comment.ID+"')", 'Hide Replies'); +else html += this.get_control('magnify_plus', "Comments.show_replies('"+page_id+"','"+comment.ID+"')", 'Show Replies ('+comment.Replies+')'); +if (session.user) html += spacer_txt; +} +if (session.user) { +html += this.get_control( +'star', +"Comments.like('"+page_id+"','"+comment.ID+"')", +'Like' + (comment.Like ? (' ('+comment.Like+')') : ''), +comment.Like ? (comment.Like + ' ' + ((comment.Like == 1) ? 'person likes this' : 'people like this')) : 'I like this comment' +) + spacer_txt; +if (is_admin()) html += this.get_control('trash', "Comments._delete('"+page_id+"','"+comment.ID+"')", 'Delete') + spacer_txt; +html += this.get_control('warning', "Comments.report('"+page_id+"','"+comment.ID+"')", 'Report Abuse'); +} +return html; +}, +reply: function(page_id, comment_id) { +hide_popup_dialog(); +delete session.progress; +var comment = find_object( this.comments, { ID: comment_id } ); +var html = ''; +html += '
    '; +html += '\n \n \n \n \n \n \n \n \n \n '); + }, this); + __out.push('\n\n
    \n
    '; +html += '
    Reply to Comment by "'+comment.Name+'"
    '; +html += '
    '; +var name = this.get_name(); +html += '

    Posted by: ' + name; +if (!session.user) html += ' → Create Account'; +html += '


    '; +html += ''; +html += Blog.edit_caption; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', 'Post Reply', "Comments.post_reply('"+page_id+"','"+comment_id+"')") + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_comment_body' ); +show_popup_dialog(600, 300, html); +}, +post_reply: function(page_id, comment_id) { +var value = $('fe_comment_body').value; +if (!value) return; +hide_popup_dialog(); +show_progress_dialog(1, "Posting reply..."); +var name = this.get_name(); +effect_api_mod_touch('comment_replies_get'); +effect_api_send('comment_post_reply', { +PageID: page_id, +CommentID: comment_id, +Username: session.username || '', +Name: name, +Comment: value, +PageURL: location.href +}, [this, 'post_reply_finish'], { _page_id: page_id, _comment_id: comment_id } ); +}, +post_reply_finish: function(response, tx) { +hide_popup_dialog(); +var page_id = tx._page_id; +var comment_id = tx._comment_id; +var comment = find_object( this.comments, { ID: comment_id } ); +do_message('success', "Comment reply posted successfully."); +this.show_replies(page_id, comment_id); +if (!comment.Replies) comment.Replies = 1; else comment.Replies++; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +}, +show_replies: function(page_id, comment_id) { +var comment = find_object( this.comments, { ID: comment_id } ); +if (!comment._replies_visible) { +$('d_comment_replies_' + comment_id).show().innerHTML = ''; +} +var args = { page_id: page_id, comment_id: comment_id, offset: 0, limit: 100 }; +effect_api_get( 'comment_replies_get', args, [this, 'receive_replies_response'], { _search_args: args } ); +}, +receive_replies_response: function(response, tx) { +var page_id = tx._search_args.page_id; +var comment_id = tx._search_args.comment_id; +var comment = find_object( this.comments, { ID: comment_id } ); +var html = ''; +var replies = always_array( response.Items.Item ); +for (var idx = 0, len = replies.length; idx < len; idx++) { +var reply = replies[idx]; +html += get_chat_balloon( +(reply.Username == session.username) ? 'blue' : 'grey', +reply.Username, +reply.Comment.replace(/^]*?>(.+)<\/div>$/i, '$1') +); +} +$('d_comment_replies_' + comment_id).innerHTML = html; +if (!comment._replies_visible) { +$('d_comment_replies_' + comment_id).hide(); +animate_div_visibility( 'd_comment_replies_' + comment_id, true ); +} +comment._replies_visible = true; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +}, +hide_replies: function(page_id, comment_id) { +var comment = find_object( this.comments, { ID: comment_id } ); +if (comment._replies_visible) { +animate_div_visibility( 'd_comment_replies_' + comment_id, false ); +comment._replies_visible = false; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +} +}, +like: function(page_id, comment_id) { +effect_api_mod_touch('comments_get'); +effect_api_send('comment_like', { +PageID: page_id, +CommentID: comment_id +}, [this, 'like_finish'], { _page_id: page_id, _comment_id: comment_id, _on_error: [this, 'like_error'] } ); +}, +like_error: function(response, tx) { +if (response.Code == 'comment_already_like') do_message('error', "You already like this comment."); +else do_error( response.Description ); +}, +like_finish: function(resopnse, tx) { +var page_id = tx._page_id; +var comment_id = tx._comment_id; +var comment = find_object( this.comments, { ID: comment_id } ); +do_message('success', "You now like this comment."); +if (!comment.Like) comment.Like = 1; else comment.Like++; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +}, +add: function(page_id) { +hide_popup_dialog(); +delete session.progress; +var html = ''; +html += '
    '; +html += '", "" ], + legend: [ 1, "
    ", "
    " ], + thead: [ 1, "
    '; +html += '
    Post New Comment
    '; +html += '
    '; +var name = this.get_name(); +html += '

    Posted by: ' + name; +if (!session.user) html += ' → Create Account'; +html += '


    '; +html += ''; +html += Blog.edit_caption; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', 'Post Comment', "Comments.post('"+page_id+"')") + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_comment_body' ); +show_popup_dialog(600, 300, html); +}, +report: function(page_id, comment_id) { +if (confirm('Are you sure you want to report this comment to the site administrators as abusive and/or spam?')) { +effect_api_send('comment_report_abuse', { +PageID: page_id, +CommentID: comment_id +}, [this, 'report_finish'], { _page_id: page_id, _comment_id: comment_id } ); +} +}, +report_finish: function(response, tx) { +do_message('success', 'Your abuse report has been received, and will be evaluated by the site administrators.'); +}, +_delete: function(page_id, comment_id) { +if (confirm('Are you sure you want to permanently delete this comment?')) { +effect_api_mod_touch('comments_get'); +effect_api_send('comment_delete', { +PageID: page_id, +CommentID: comment_id +}, [this, 'delete_finish'], { _page_id: page_id, _comment_id: comment_id } ); +} +}, +delete_finish: function(response, tx) { +do_message('success', 'The comment was deleted successfully.'); +var page_id = tx._page_id; +this.search({ page_id: page_id }); +}, +get_name: function() { +var name = '(Anonymous)'; +if (session.user) { +if (get_bool_pref('public_profile')) name = session.user.FullName; +else name = session.username; +} +return name; +}, +post: function(page_id) { +var value = $('fe_comment_body').value; +if (!value) return; +hide_popup_dialog(); +show_progress_dialog(1, "Posting comment..."); +var name = this.get_name(); +effect_api_mod_touch('comments_get'); +effect_api_send('comment_post', { +PageID: page_id, +Username: session.username || '', +Name: name, +Comment: value +}, [this, 'post_finish'], { _page_id: page_id } ); +}, +post_finish: function(response, tx) { +hide_popup_dialog(); +var comment_id = response.CommentID; +var page_id = tx._page_id; +this.search({ page_id: page_id, highlight: comment_id }); +} +}; +Class.create( 'Menu', { +id: '', +menu: null, +__construct: function(id) { +this.id = id; +}, +load: function() { +if (!this.menu) { +this.menu = $(this.id); +assert( !!this.menu, "Could not locate DOM element: " + this.id ); +} +}, +get_value: function() { +this.load(); +return this.menu.options[this.menu.selectedIndex].value; +}, +set_value: function(value, auto_add) { +value = str_value(value); +this.load(); +for (var idx = 0, len = this.menu.options.length; idx < len; idx++) { +if (this.menu.options[idx].value == value) { +this.menu.selectedIndex = idx; +return true; +} +} +if (auto_add) { +this.menu.options[this.menu.options.length] = new Option(value, value); +this.menu.selectedIndex = this.menu.options.length - 1; +return true; +} +return false; +}, +disable: function() { +this.load(); +this.menu.disabled = true; +this.menu.setAttribute( 'disabled', 'disabled' ); +}, +enable: function() { +this.load(); +this.menu.setAttribute( 'disabled', '' ); +this.menu.disabled = false; +}, +populate: function(items, sel_value) { +this.load(); +this.menu.options.length = 0; +for (var idx = 0, len = items.length; idx < len; idx++) { +var item = items[idx]; +var item_name = ''; +var item_value = ''; +if (isa_hash(item)) { +item_name = item.label; +item_value = item.data; +} +else if (isa_array(item)) { +item_name = item[0]; +item_value = item[1]; +} +else { +item_name = item_value = item; +} +this.menu.options[ this.menu.options.length ] = new Option( item_name, item_value ); +if (item_value == sel_value) this.menu.selectedIndex = idx; +} +} +} ); +Class.subclass( Menu, 'MultiMenu', { +__static: { +toggle_type: function(id) { +var menu = $(id); +assert(menu, "Could not find menu in DOM: " + id); +if (menu.disabled) return; +var obj = MenuManager.find(id); +assert(obj, "Could not find menu in MenuManager: " + id); +var div = $( 'd_inner_' + id ); +var ic = $( 'ic_' + id ); +var is_multiple = (ic.src.indexOf('contract') > -1); +obj.multi = !is_multiple; +var multiple_tag = !is_multiple ? +' multiple="multiple" size=5' : ''; +var items = []; +for (var idx = 0; idx < menu.options.length; idx++) { +var option = menu.options[idx]; +array_push( items, { +value: option.value, +text: option.text, +selected: option.selected +}); +} +var html = ''; +html += ''; +div.innerHTML = html; +ic.src = images_uri + '/menu_' + (is_multiple ? 'expand' : 'contract') + '.gif'; +obj.menu = null; +} +}, +attribs: null, +multi: false, +toggle: true, +__construct: function(id, attribs) { +this.id = id; +if (attribs) this.attribs = attribs; +}, +get_html: function(items, selected_csv, attribs) { +if (!items) items = []; +if (!selected_csv) selected_csv = ''; +if (attribs) this.attribs = attribs; +var selected = csv_to_hash(selected_csv); +this.menu = null; +if (num_keys(selected) > 1) this.multi = true; +var html = '
    '; +html += ''; +html += ''; +html += ''; +if (this.toggle) html += ''; +html += '
    ' + spacer(1,1) + '
    '+spacer(1,2)+'
    '; +html += '
    '; +return html; +}, +get_value: function() { +this.load(); +var value = ''; +for (var idx = 0; idx < this.menu.options.length; idx++) { +var option = this.menu.options[idx]; +if (option.selected && option.value.length) { +if (value.length > 0) value += ','; +value += option.value; +} +} +return value; +}, +set_value: function(value, auto_add) { +value = '' + value; +this.load(); +if (!value) { +value = ''; +for (var idx = 0; idx < this.menu.options.length; idx++) { +var option = this.menu.options[idx]; +option.selected = (option.value == value); +} +return; +} +var selected = csv_to_hash(value); +if ((num_keys(selected) > 1) && !this.multi) { +MultiMenu.toggle_type(this.id); +var self = this; +setTimeout( function() { +self.set_value(value, auto_add); +}, 1 ); +return; +} +for (var idx = 0; idx < this.menu.options.length; idx++) { +var option = this.menu.options[idx]; +option.selected = selected[option.value] ? true : false; +} +}, +populate: function(items, value) { +this.load(); +this.menu.options.length = 0; +if (!value) value = ''; +var selected = csv_to_hash(value); +for (var idx = 0, len = items.length; idx < len; idx++) { +var item = items[idx]; +var item_name = ''; +var item_value = ''; +if (isa_hash(item)) { +item_name = item.label; +item_value = item.data; +} +else if (isa_array(item)) { +item_name = item[0]; +item_value = item[1]; +} +else { +item_name = item_value = item; +} +var opt = new Option( item_name, item_value ); +this.menu.options[ this.menu.options.length ] = opt; +opt.selected = selected[item_value] ? true : false; +} +}, +collapse: function() { +if (this.multi) MultiMenu.toggle_type(this.id); +}, +expand: function() { +if (!this.multi) MultiMenu.toggle_type(this.id); +} +} ); +Class.create( 'MenuManager', { +__static: { +menus: {}, +register: function(menu) { +this.menus[ menu.id ] = menu; +return menu; +}, +find: function(id) { +return this.menus[id]; +} +} +} ); +Class.create( 'GrowlManager', { +lifetime: 10, +marginRight: 0, +marginTop: 0, +__construct: function() { +this.growls = []; +}, +growl: function(type, msg) { +if (find_object(this.growls, { type: type, msg: msg })) return; +var div = $(document.createElement('div')); +div.className = 'growl_message ' + type; +div.setOpacity(0.0); +div.innerHTML = '
    ' + msg + '
    ' + spacer(1,5) + '
    '; +$('d_growl_wrapper').insertBefore( div, $('d_growl_top').nextSibling ); +var growl = { id:get_unique_id(), type: type, msg: msg, opacity:0.0, start:hires_time_now(), div:div }; +this.growls.push(growl); +this.handle_resize(); +this.animate(growl); +var self = this; +div.onclick = function() { +delete_object(self.growls, { id: growl.id }); +$('d_growl_wrapper').removeChild( div ); +}; +}, +animate: function(growl) { +if (growl.deleted) return; +var now = hires_time_now(); +var div = growl.div; +if (now - growl.start <= 0.5) { +div.setOpacity( tweenFrame(0.0, 1.0, (now - growl.start) * 2, 'EaseOut', 'Quadratic') ); +} +else if (now - growl.start <= this.lifetime) { +if (!growl._fully_opaque) { +div.setOpacity( 1.0 ); +growl._fully_opaque = true; +} +} +else if (now - growl.start <= this.lifetime + 1.0) { +div.setOpacity( tweenFrame(1.0, 0.0, (now - growl.start) - this.lifetime, 'EaseOut', 'Quadratic') ); +} +else { +delete_object(this.growls, { id: growl.id }); +$('d_growl_wrapper').removeChild( div ); +return; +} +var self = this; +setTimeout( function() { self.animate(growl); }, 33 ); +}, +handle_resize: function() { +var div = $('d_growl_wrapper'); +if (this.growls.length) { +var size = getInnerWindowSize(); +div.style.top = '' + (10 + this.marginTop) + 'px'; +div.style.left = '' + Math.floor((size.width - 310) - this.marginRight) + 'px'; +} +else { +div.style.left = '-2000px'; +} +} +} ); +window.$GR = new GrowlManager(); +if (window.addEventListener) { +window.addEventListener( "resize", function() { +$GR.handle_resize(); +}, false ); +} +else if (window.attachEvent && !ie6) { +window.attachEvent("onresize", function() { +$GR.handle_resize(); +}); +} +Class.create( 'Effect.Page', { +ID: '', +data: null, +active: false, +__construct: function(config) { +if (!config) return; +this.data = {}; +if (!config) config = {}; +for (var key in config) this[key] = config[key]; +this.div = $('page_' + this.ID); +assert(this.div, "Cannot find page div: page_" + this.ID); +}, +onInit: function() { +}, +onActivate: function() { +return true; +}, +onDeactivate: function() { +return true; +}, +show: function() { +this.div.show(); +}, +hide: function() { +this.div.hide(); +}, +gosub: function(anchor) { +} +} ); +Class.require( 'Effect.Page' ); +Class.create( 'Effect.PageManager', { +pages: null, +current_page_id: '', +on_demand: {}, +__construct: function(page_list) { +this.pages = []; +this.page_list = page_list; +for (var idx = 0, len = page_list.length; idx < len; idx++) { +Debug.trace( 'page', "Initializing page: " + page_list[idx].ID ); +if (Effect.Page[ page_list[idx].ID ]) { +var page = new Effect.Page[ page_list[idx].ID ]( page_list[idx] ); +page.onInit(); +this.pages.push(page); +} +else { +Debug.trace( 'page', 'Page ' + page_list[idx].ID + ' will be loaded on-demand' ); +} +} +}, +find: function(id) { +var page = find_object( this.pages, { ID: id } ); +if (!page) Debug.trace('PageManager', "Could not find page: " + id); +return page; +}, +notify_load: function(file, id) { +for (var idx = 0, len = this.page_list.length; idx < len; idx++) { +var page_config = this.page_list[idx]; +if (page_config.File == file) { +Debug.trace( 'page', "Initializing page on-demand: " + page_config.ID ); +var page = new Effect.Page[ page_config.ID ]( page_config ); +page.onInit(); +this.pages.push(page); +} +} +var self = this; +setTimeout( function() { +var result = self.activate(id, self.temp_args); +delete self.temp_args; +$('d_page_loading').hide(); +if (!result) { +$('page_'+id).hide(); +self.current_page_id = ''; +} +}, 1 ); +}, +activate: function(id, args) { +if (!find_object( this.pages, { ID: id } )) { +var page_config = find_object( this.page_list, { ID: id } ); +assert(!!page_config, "Page config not found: " + id ); +Debug.trace('page', "Loading file on-demand: " + page_config.File + " for page: " + id); +var url = '/effect/api/load_page/' + page_config.File + '?onafter=' + escape('page_manager.notify_load(\''+page_config.File+'\',\''+id+'\')'); +if (page_config.Requires) { +var files = page_config.Requires.split(/\,\s*/); +for (var idx = 0, len = files.length; idx < len; idx++) { +var filename = files[idx]; +if (!this.on_demand[filename]) { +Debug.trace('page', "Also loading file: " + filename); +url += '&file=' + filename; +this.on_demand[filename] = 1; +} +} +} +$('d_page_loading').show(); +this.temp_args = args; +load_script( url ); +return true; +} +$('page_'+id).show(); +var page = this.find(id); +page.active = true; +if (!args) args = []; +if (!isa_array(args)) args = [ args ]; +var result = page.onActivate.apply(page, args); +if (typeof(result) == 'boolean') return result; +else return alert("Page " + id + " onActivate did not return a boolean!"); +}, +deactivate: function(id, new_id) { +var page = this.find(id); +var result = page.onDeactivate(new_id); +if (result) { +$('page_'+id).hide(); +page.active = false; +} +return result; +}, +click: function(id, args) { +Debug.trace('page', "Switching pages to: " + id); +var old_id = this.current_page_id; +if (this.current_page_id) { +var result = this.deactivate( this.current_page_id, id ); +if (!result) return false; +} +this.current_page_id = id; +this.old_page_id = old_id; +window.scrollTo( 0, 0 ); +var result = this.activate(id, args); +if (!result) { +$('page_'+id).hide(); +this.current_page_id = ''; +} +return true; +} +} ); +Class.subclass( Effect.Page, "Effect.Page.Main", { +inited: false, +onActivate: function() { +Nav.bar( ['Main', 'EffectGames.com'] ); +Nav.title(''); +$('d_blog_news').innerHTML = loading_image(); +$('d_blog_community').innerHTML = loading_image(); +$('d_blog_featured').innerHTML = loading_image(); +Blog.search({ +stag: 'featured_game', +limit: 4, +full: 1, +callback: [this, 'receive_featured_games'] +}); +effect_api_get( 'get_site_info', { cat: 'pop_pub_games' }, [this, 'receive_pop_pub_games'], { } ); +Blog.search({ +stag: 'front_page', +limit: 5, +target: 'd_blog_news', +more: 1 +}); +Blog.search({ +path: '/community', +limit: 5, +target: 'd_blog_community', +more: 1 +}); +if (!this.inited) { +this.inited = true; +config.Strings.MainSlideshow.Slide = always_array( config.Strings.MainSlideshow.Slide ); +this.slide_idx = 0; +this.num_slides = config.Strings.MainSlideshow.Slide.length; +this.slide_div_num = 0; +this.slide_dir = 1; +this.bk_pos = -340; +this.bk_pos_target = -340; +this.slide_images = []; +for (var idx = 0, len = this.num_slides; idx < len; idx++) { +var url = images_uri + '/' + config.Strings.MainSlideshow.Slide[idx].Photo; +this.slide_images[idx] = new Image(); +this.slide_images[idx].src = png(url, true); +} +} +this.height_target = 470; +this.height_start = $('d_header').offsetHeight; +this.time_start = hires_time_now(); +this.duration = 0.75; +if (!this.timer) this.timer = setTimeout( '$P("Main").animate_mhs()', 33 ); +if (session.user) $('d_blurb_main').hide(); +else { +$('d_blurb_main').innerHTML = get_string('/Main/Blurb'); +$('d_blurb_main').show(); +} +return true; +}, +receive_pop_pub_games: function(response, tx) { +var html = ''; +if (response.Data && response.Data.Games && response.Data.Games.Game) { +var games = always_array( response.Data.Games.Game ); +for (var idx = 0, len = Math.min(games.length, 16); idx < len; idx++) { +var game = games[idx]; +html += '
    ' + +(game.Logo ? +user_image_thumbnail(game.Logo, 80, 60) : +'' +) + '
    ' + ww_fit_box(game.Title, 80, 2, session.em_width, 1) + '
    '; +} +html += '
    '; +} +else { +html += 'No active public games found! Why not create a new one?'; +} +$('d_main_pop_pub_games').innerHTML = html; +}, +receive_featured_games: function(response, tx) { +var html = ''; +if (response.Rows && response.Rows.Row) { +html += ''; +var rows = always_array( response.Rows.Row ); +for (var idx = 0, len = rows.length; idx < len; idx++) { +var row = rows[idx]; +var image_url = row.Params.featured_image; +if (image_url && image_url.match(/^(\w+)\/(\w+\.\w+)$/)) { +image_url = '/effect/api/view/users/' + RegExp.$1 + '/images/' + RegExp.$2; +} +if (idx % 2 == 0) html += ''; +html += ''; +if (idx % 2 == 1) html += ''; +} +if (rows.length % 2 == 1) { +html += ''; +html += ''; +} +html += '
    '; +html += ''; +html += ''; +html += ''; +html += ''; +html += ''; +html += '
    '; +html += ''; +html += '' + spacer(10,1) + ''; +html += ''; +html += ''; +html += '' + spacer(15,1) + '
    '; +html += spacer(1,20); +html += '
    '; +} +$('d_blog_featured').innerHTML = html; +}, +animate_mhs: function() { +var now = hires_time_now(); +if (now - this.time_start >= this.duration) { +$('d_header').style.height = '' + this.height_target + 'px'; +$('d_shadow').style.height = '' + this.height_target + 'px'; +delete this.timer; +} +else { +var height = tweenFrame(this.height_start, this.height_target, (now - this.time_start) / this.duration, 'EaseOut', 'Circular'); +$('d_header').style.height = '' + height + 'px'; +$('d_shadow').style.height = '' + height + 'px'; +this.timer = setTimeout( '$P("Main").animate_mhs()', 33 ); +} +}, +onDeactivate: function() { +$('d_blog_news').innerHTML = ''; +$('d_blog_community').innerHTML = ''; +this.height_target = 75; +this.height_start = $('d_header').offsetHeight; +this.time_start = hires_time_now(); +if (!this.timer) this.timer = setTimeout( '$P("Main").animate_mhs()', 33 ); +return true; +}, +draw_slide: function() { +if (this.slide_timer) return; +var slide = config.Strings.MainSlideshow.Slide[ this.slide_idx ]; +this.old_photo = $('d_header_slideshow_photo_' + this.slide_div_num); +this.old_text = $('d_header_slideshow_text_' + this.slide_div_num); +this.slide_div_num = 1 - this.slide_div_num; +this.new_photo = $('d_header_slideshow_photo_' + this.slide_div_num); +this.new_text = $('d_header_slideshow_text_' + this.slide_div_num); +this.new_photo.style.backgroundImage = 'url('+png(images_uri+'/'+slide.Photo, true)+')'; +this.new_photo.setOpacity(0.0); +var html = ''; +html += slide.Text; +this.slide_width = this.new_text.offsetWidth; +this.new_text.innerHTML = html; +if (this.slide_dir == 1) this.new_text.style.left = '' + this.slide_width + 'px'; +else this.new_text.style.left = '-' + this.slide_width + 'px'; +this.slide_time_start = hires_time_now(); +this.slide_timer = setTimeout( '$P("Main").animate_mhs_slide()', 33 ); +}, +animate_mhs_slide: function() { +var now = hires_time_now(); +if (now - this.slide_time_start >= this.duration) { +this.new_text.style.left = '0px'; +this.old_text.style.left = '-' + this.slide_width + 'px'; +this.new_photo.setOpacity( 1.0 ); +this.old_photo.setOpacity( 0.0 ); +delete this.slide_timer; +this.bk_pos = this.bk_pos_target; +} +else { +var value = tweenFrame(0.0, 1.0, (now - this.slide_time_start) / this.duration, 'EaseOut', 'Circular'); +if (this.slide_dir == 1) { +this.new_text.style.left = '' + Math.floor( this.slide_width - (this.slide_width * value) ) + 'px'; +this.old_text.style.left = '-' + Math.floor( this.slide_width * value ) + 'px'; +} +else { +this.new_text.style.left = '-' + Math.floor( this.slide_width - (this.slide_width * value) ) + 'px'; +this.old_text.style.left = '' + Math.floor( this.slide_width * value ) + 'px'; +} +this.new_photo.setOpacity( value ); +this.old_photo.setOpacity( 1.0 - value ); +var bkp = Math.floor( this.bk_pos + ((this.bk_pos_target - this.bk_pos) * value) ); +$('d_header').style.backgroundPosition = '' + bkp + 'px 0px'; +this.slide_timer = setTimeout( '$P("Main").animate_mhs_slide()', 33 ); +} +}, +prev_slide: function() { +this.bk_pos_target += 200; +this.slide_idx--; +if (this.slide_idx < 0) this.slide_idx += this.num_slides; +this.slide_dir = -1; +this.draw_slide(); +}, +next_slide: function() { +this.bk_pos_target -= 200; +this.slide_idx++; +if (this.slide_idx >= this.num_slides) this.slide_idx -= this.num_slides; +this.slide_dir = 1; +this.draw_slide(); +} +} ); +Class.subclass( Effect.Page, "Effect.Page.PublicGameList", { +onActivate: function() { +Nav.bar( +['Main', 'EffectGames.com'], +['PublicGameList', "All Public Games"] +); +Nav.title( "List of All Public Game Projects" ); +effect_api_get( 'get_site_info', { cat: 'all_pub_games' }, [this, 'receive_all_pub_games'], { } ); +this.div.innerHTML = loading_image(); +return true; +}, +onDeactivate: function() { +this.div.innerHTML = ''; +return true; +}, +receive_all_pub_games: function(response, tx) { +var html = ''; +html += '

    List of All Public Game Projects

    '; +html += '
    This is the complete list of public games currently being built by our users, presented in alphabetical order. Maybe they could use some help! Check out the game project pages and see (requires user account).
    '; +if (response.Data && response.Data.Games && response.Data.Games.Game) { +var games = always_array( response.Data.Games.Game ); +for (var idx = 0, len = games.length; idx < len; idx++) { +var game = games[idx]; +html += '
    ' + +(game.Logo ? +user_image_thumbnail(game.Logo, 80, 60) : +'' +) + '
    ' + ww_fit_box(game.Title, 80, 2, session.em_width, 1) + '
    '; +} +html += '
    '; +} +else { +html += 'No public games found! Why not create a new one?'; +} +this.div.innerHTML = html; +} +} ); +Class.subclass( Effect.Page, "Effect.Page.Search", { +onActivate: function(args) { +if (!args) args = {}; +var search_text = args.q; +var start = args.s || 0; +if (!start) start = 0; +var title = 'Search results for "'+search_text+'"'; +Nav.bar( +['Main', 'EffectGames.com'], +['Search?q=' + escape(search_text), "Search Results"] +); +Nav.title( title ); +this.last_search_text = search_text; +$('d_article_search').innerHTML = loading_image(); +load_script( 'http://www.google.com/uds/GwebSearch?callback=receive_google_search_results&context=0&lstkp=0&rsz=large&hl=en&source=gsc&gss=.com&sig=&q='+escape(search_text)+'%20site%3Ahttp%3A%2F%2Fwww.effectgames.com%2F&key=notsupplied&v=1.0&start='+start+'&nocache=' + (new Date()).getTime() ); +$('h_article_search').innerHTML = title; +return true; +}, +onDeactivate: function(new_page) { +$('fe_search_bar').value = ''; +$('d_article_search').innerHTML = ''; +return true; +} +} ); +function do_search_bar() { +var search_text = $('fe_search_bar').value; +if (search_text.length) { +Nav.go('Search?q=' + escape(search_text)); +} +} +function receive_google_search_results(context, response) { +var html = ''; +html += '
    Powered by
    '; +if (response.results.length) { +for (var idx = 0, len = response.results.length; idx < len; idx++) { +var row = response.results[idx]; +var url = row.unescapedUrl.replace(/^.+article\.psp\.html/, '#Article'); +html += '
    '; +html += ''; +html += '
    ' + row.content + '
    '; +html += '
    '; +} +} +else { +html += 'No results found.'; +} +if (response.cursor.pages) { +html += '
    Page: '; +for (var idx = 0, len = response.cursor.pages.length; idx < len; idx++) { +html += ''; +var page = response.cursor.pages[idx]; +var url = '#Search?q=' + escape($P('Search').last_search_text) + '&s=' + page.start; +if (response.cursor.currentPageIndex != idx) html += ''; +else html += ''; +html += page.label; +if (response.cursor.currentPageIndex != idx) html += ''; +else html += ''; +html += ''; +} +html += '
    '; +} +$('d_article_search').innerHTML = html; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/index.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/index.js new file mode 100644 index 00000000..8b164a42 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/index.js @@ -0,0 +1 @@ +exports.ZeParser = require('./ZeParser').ZeParser; diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/package.json b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/package.json new file mode 100644 index 00000000..030892ad --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/package.json @@ -0,0 +1,31 @@ +{ + "author": { + "name": "Peter van der Zee", + "url": "http://qfox.nl/" + }, + "name": "zeparser", + "description": "My JavaScript parser", + "version": "0.0.5", + "homepage": "https://github.com/qfox/ZeParser/", + "repository": { + "type": "git", + "url": "git://github.com/qfox/ZeParser.git" + }, + "main": "./index", + "engines": { + "node": "*" + }, + "dependencies": {}, + "devDependencies": {}, + "readme": "This is a JavaScript parser.\nhttp://github.com/qfox/ZeParser\n(c) Peter van der Zee\nhttp://qfox.nl\n\n\nBenchmark\nhttp://qfox.github.com/ZeParser/benchmark.html\n\nThe Tokenizer is used by the parser. The parser tells the tokenizer whether the next token may be a regular expression or not. Without the parser, the tokenizer will fail if regular expression literals are used in the input.\n\nUsage:\nZeParser.parse(input);\n\nReturns a \"parse tree\" which is a tree of an array of arrays with tokens (regular objects) as leafs. Meta information embedded as properties (of the arrays and the tokens).\n\nZeParser.createParser(input);\n\nReturns a new ZeParser instance which has already parsed the input. Amongst others, the ZeParser instance will have the properties .tree, .wtree and .btree.\n\n.tree is the parse tree mentioned above.\n.wtree (\"white\" tree) is a regular array with all the tokens encountered (including whitespace, line terminators and comments)\n.btree (\"black\" tree) is just like .wtree but without the whitespace, line terminators and comments. This is what the specification would call the \"token stream\".\n\nI'm aware that the naming convention is a bit awkward. It's a tradeoff between short and descriptive. The streams are used quite often in the analysis.\n\nTokens are regular objects with several properties. Amongst them are .tokposw and .tokposw, they correspond with their own position in the .wtree and .btree.\n\nThe parser has two modes for parsing: simple and extended. Simple mode is mainly for just parsing and returning the streams and a simple parse tree. There's not so much meta information here and this mode is mainly built for speed. The other mode has everything required for Zeon to do its job. This mode is toggled by the instance property .ast, which is true by default :)\n\nNon-factory example:\n\nvar input = \"foo\";\nvar tree = []; // this should probably be refactored away some day\nvar tokenizer = new Tokenizer(input); // dito\nvar parser = new ZeParser(input, tokenizer, tree);\nparser.parse(); // returns tree..., should never throw errors\n", + "readmeFilename": "README", + "bugs": { + "url": "https://github.com/qfox/ZeParser/issues" + }, + "_id": "zeparser@0.0.5", + "dist": { + "shasum": "dd541e280c9ce8e83e41e3adc3f22fbe52747554" + }, + "_from": "zeparser@0.0.5", + "_resolved": "https://registry.npmjs.org/zeparser/-/zeparser-0.0.5.tgz" +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-parser.html b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-parser.html new file mode 100755 index 00000000..1ff5ff43 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-parser.html @@ -0,0 +1,26 @@ + + + + Parser Test Suite Page + + + + (c) qfox.nl
    + Parser test suite
    +
    Running...
    + + + + + + + \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-tokenizer.html b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-tokenizer.html new file mode 100755 index 00000000..0e0d1b1a --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-tokenizer.html @@ -0,0 +1,23 @@ + + + + Tokenizer Test Suite Page + + + + (c) qfox.nl
    + + + + + + \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/tests.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/tests.js new file mode 100644 index 00000000..8a4138be --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/tests.js @@ -0,0 +1,478 @@ +// tests for both the tokenizer and parser. Parser test results could be checked tighter. +// api: [input, token-output-count, ?regex-hints, desc] +// regex-hints are for tokenizer, will tell for each token whether it might parse regex or not (parser's job) +var Tests = [ + +["var abc;", 4, "Variable Declaration"], +["var abc = 5;", 8, "Variable Declaration, Assignment"], +["/* */", 1, "Block Comment"], +["/** **/", 1, "JSDoc-style Comment"], +["var f = function(){;};", 13, "Assignment, Function Expression"], +["hi; // moo", 4, "Trailing Line Comment"], +["hi; // moo\n;", 6, "Trailing Line Comment, Linefeed, `;`"], +["var varwithfunction;", 4, "Variable Declaration, Identifier Containing Reserved Words, `;`"], +["a + b;", 6, "Addition/Concatenation"], + +["'a'", 1, "Single-Quoted String"], +["'a';", 2, "Single-Quoted String, `;`"], // Taken from the parser test suite. + +["'a\\n'", 1, "Single-Quoted String With Escaped Linefeed"], +["'a\\n';", 2, "Single-Quoted String With Escaped Linefeed, `;`"], // Taken from the parser test suite. + +["\"a\"", 1, "Double-Quoted String"], +["\"a\";", 2, "Double-Quoted String, `;`"], // Taken from the parser test suite. + +["\"a\\n\"", 1, "Double-Quoted String With Escaped Linefeed"], +["\"a\\n\";", 2, "Double-Quoted String With Escaped Linefeed, `;`"], // Taken from the parser test suite. + +["500", 1, "Integer"], +["500;", 2, "Integer, `;`"], // Taken from the parser test suite. + +["500.", 1, "Double With Trailing Decimal Point"], +["500.;", 2, "Double With Trailing Decimal Point"], // Taken from the parser test suite. + +["500.432", 1, "Double With Decimal Component"], +["500.432;", 2, "Double With Decimal Component, `;`"], // Taken from the parser test suite. + +[".432432", 1, "Number, 0 < Double < 1"], +[".432432;", 2, "Number, 0 < Double < 1, `;`"], // Taken from the parser test suite. + +["(a,b,c)", 7, "Parentheses, Comma-separated identifiers"], +["(a,b,c);", 8, "Parentheses, Comma-separated identifiers, `;`"], // Taken from the parser test suite. + +["[1,2,abc]", 7, "Array literal"], +["[1,2,abc];", 8, "Array literal, `;`"], // Taken from the parser test suite. + +["{a:1,\"b\":2,c:c}", 13, "Object literal"], +["var o = {a:1,\"b\":2,c:c};", 20, "Assignment, Object Literal, `;`"], // Taken from the parser test suite. + +["var x;\nvar y;", 9, "2 Variable Declarations, Multiple lines"], +["var x;\nfunction n(){ }", 13, "Variable, Linefeed, Function Declaration"], +["var x;\nfunction n(abc){ }", 14, "Variable, Linefeed, Function Declaration With One Argument"], +["var x;\nfunction n(abc, def){ }", 17, "Variable, Linefeed, Function Declaration With Multiple Arguments"], +["function n(){ \"hello\"; }", 11, "Function Declaration, Body"], + +["/a/;", 2, [true, false], "RegExp Literal, `;`"], +["/a/b;", 2, [true, true], "RegExp Literal, Flags, `;`"], +["++x;", 3, "Unary Increment, Prefix, `;`"], +[" / /;", 3, [true, true, false], "RegExp, Leading Whitespace, `;`"], +["/ / / / /", 5, [true, false, false, false, true], "RegExp Containing One Space, Space, Division, Space, RegExp Containing One Space"], + +// Taken from the parser test suite. + +["\"var\";", 2, "Keyword String, `;`"], +["\"variable\";", 2, "String Beginning With Keyword, `;`"], +["\"somevariable\";", 2, "String Containing Keyword, `;`"], +["\"somevar\";", 2, "String Ending With Keyword, `;`"], + +["var varwithfunction;", 4, "Keywords should not be matched in identifiers"], + +["var o = {a:1};", 12, "Object Literal With Unquoted Property"], +["var o = {\"b\":2};", 12, "Object Literal With Quoted Property"], +["var o = {c:c};", 12, "Object Literal With Equivalent Property Name and Identifier"], + +["/a/ / /b/;", 6, [true, true, false, false, true, false], "RegExp, Division, RegExp, `;`"], +["a/b/c;", 6, "Triple Division (Identifier / Identifier / Identifier)"], + +["+function(){/regex/;};", 9, [false, false, false, false, false, true, false, false, false], "Unary `+` Operator, Function Expression Containing RegExp and Semicolon, `;`"], + +// Line Terminators. +["\r\n", 1, "CRLF Line Ending = 1 Linefeed"], +["\r", 1, "CR Line Ending = 1 Linefeed"], +["\n", 1, "LF Line Ending = 1 Linefeed"], +["\r\n\n\u2028\u2029\r", 5, "Various Line Terminators"], + +// Whitespace. +["a \t\u000b\u000c\u00a0\uFFFFb", 8, "Whitespace"], + +// Comments. +["//foo!@#^&$1234\nbar;", 4, "Line Comment, Linefeed, Identifier, `;`"], +["/* abcd!@#@$* { } && null*/;", 2, "Single-Line Block Comment, `;`"], +["/*foo\nbar*/;", 2, "Multi-Line Block Comment, `;`"], +["/*x*x*/;", 2, "Block Comment With Asterisks, `;`"], +["/**/;", 2, "Empty Comment, `;`"], + +// Identifiers. +["x;", 2, "Single-Character Identifier, `;`"], +["_x;", 2, "Identifier With Leading `_`, `;`"], +["xyz;", 2, "Identifier With Letters Only, `;`"], +["$x;", 2, "Identifier With Leading `$`, `;`"], +["x5;", 2, "Identifier With Number As Second Character, `;`"], +["x_y;", 2, "Identifier Containing `_`, `;`"], +["x+5;", 4, "Identifier, Binary `+` Operator, Identifier, `;`"], +["xyz123;", 2, "Alphanumeric Identifier, `;`"], +["x1y1z1;", 2, "Alternating Alphanumeric Identifier, `;`"], +["foo\\u00d8bar;", 2, "Identifier With Unicode Escape Sequence (`\\uXXXX`), `;`"], +["f\u00d8\u00d8bar;", 2, "Identifier With Embedded Unicode Character"], + +// Numbers. +["5;", 2, "Integer, `;`"], +["5.5;", 2, "Double, `;`"], +["0;", 2, "Integer Zero, `;`"], +["0.0;", 2, "Double Zero, `;`"], +["0.001;", 2, "0 < Decimalized Double < 1, `;`"], +["1.e2;", 2, "Integer With Decimal and Exponential Component (`e`), `;`"], +["1.e-2;", 2, "Integer With Decimal and Negative Exponential Component, `;`"], +["1.E2;", 2, "Integer With Decimal and Uppercase Exponential Component (`E`), `;`"], +["1.E-2;", 2, "Integer With Decimal and Uppercase Negative Exponential Component, `;`"], +[".5;", 2, "0 < Double < 1, `;`"], +[".5e3;", 2, "(0 < Double < 1) With Exponential Component"], +[".5e-3;", 2, "(0 < Double < 1) With Negative Exponential Component"], +["0.5e3;", 2, "(0 < Decimalized Double < 1) With Exponential Component"], +["55;", 2, "Two-Digit Integer, `;`"], +["123;", 2, "Three-Digit Integer, `;`"], +["55.55;", 2, "Two-Digit Double, `;`"], +["55.55e10;", 2, "Two-Digit Double With Exponential Component, `;`"], +["123.456;", 2, "Three-Digit Double, `;`"], +["1+e;", 4, "Additive Expression, `;`"], +["0x01;", 2, "Hexadecimal `1` With 1 Leading Zero, `;`"], +["0xcafe;", 2, "Hexadecimal `51966`, `;`"], +["0x12345678;", 2, "Hexadecimal `305419896`, `;`"], +["0x1234ABCD;", 2, "Hexadecimal `305441741` With Uppercase Letters, `;`"], +["0x0001;", 2, "Hexadecimal `1` with 3 Leading Zeros, `;`"], + +// Strings. +["\"foo\";", 2, "Multi-Character Double-Quoted String, `;`"], +["\"a\\n\";", 2, "Double-Quoted String Containing Linefeed, `;`"], +["\'foo\';", 2, "Single-Quoted String, `;`"], +["'a\\n';", 2, "Single-Quoted String Containing Linefeed, `;`"], +["\"x\";", 2, "Single-Character Double-Quoted String, `;`"], +["'';", 2, "Empty Single-Quoted String, `;`"], +["\"foo\\tbar\";", 2, "Double-Quoted String With Tab Character, `;`"], +["\"!@#$%^&*()_+{}[]\";", 2, "Double-Quoted String Containing Punctuators, `;`"], +["\"/*test*/\";", 2, "Double-Quoted String Containing Block Comment, `;`"], +["\"//test\";", 2, "Double-Quoted String Containing Line Comment, `;`"], +["\"\\\\\";", 2, "Double-Quoted String Containing Reverse Solidus, `;`"], +["\"\\u0001\";", 2, "Double-Quoted String Containing Numeric Unicode Escape Sequence, `;`"], +["\"\\uFEFF\";", 2, "Double-Quoted String Containing Alphanumeric Unicode Escape Sequence, `;`"], +["\"\\u10002\";", 2, "Double-Quoted String Containing 5-Digit Unicode Escape Sequence, `;`"], +["\"\\x55\";", 2, "Double-Quoted String Containing Hex Escape Sequence, `;`"], +["\"\\x55a\";", 2, "Double-Quoted String Containing Hex Escape Sequence and Additional Character, `;`"], +["\"a\\\\nb\";", 2, "Double-Quoted String Containing Escaped Linefeed, `;`"], +["\";\"", 1, "Double-Quoted String Containing `;`"], +["\"a\\\nb\";", 2, "Double-Quoted String Containing Reverse Solidus and Linefeed, `;`"], +["'\\\\'+ ''", 4, "Single-Quoted String Containing Reverse Solidus, `+`, Empty Single-Quoted String"], + +// `null`, `true`, and `false`. +["null;", 2, "`null`, `;`"], +["true;", 2, "`true`, `;`"], +["false;", 2, "`false`, `;`"], + +// RegExps +["/a/;", 2, [true, true], "Single-Character RegExp, `;`"], +["/abc/;", 2, [true, true], "Multi-Character RegExp, `;`"], +["/abc[a-z]*def/g;", 2, [true, true], "RegExp Containing Character Range and Quantifier, `;`"], +["/\\b/;", 2, [true, true], "RegExp Containing Control Character, `;`"], +["/[a-zA-Z]/;", 2, [true, true], "RegExp Containing Extended Character Range, `;`"], +["/foo(.*)/g;", 2, [true, false], "RegExp Containing Capturing Group and Quantifier, `;`"], + +// Array Literals. +["[];", 3, "Empty Array, `;`"], +["[\b\n\f\r\t\x20];", 9, "Array Containing Whitespace, `;`"], +["[1];", 4, "Array Containing 1 Element, `;`"], +["[1,2];", 6, "Array Containing 2 Elements, `;`"], +["[1,2,,];", 8, "Array Containing 2 Elisions, `;`"], +["[1,2,3];", 8, "Array Containing 3 Elements, `;`"], +["[1,2,3,,,];", 11, "Array Containing 3 Elisions, `;`"], + +// Object Literals. +["({x:5});", 8, "Object Literal Containing 1 Member; `;`"], +["({x:5,y:6});", 12, "Object Literal Containing 2 Members, `;`"], +["({x:5,});", 9, "Object Literal Containing 1 Member and Trailing Comma, `;`"], +["({if:5});", 8, "Object Literal Containing Reserved Word Property Name, `;`"], +["({ get x() {42;} });", 17, "Object Literal Containing Getter, `;`"], +["({ set y(a) {1;} });", 18, "Object Literal Containing Setter, `;`"], + +// Member Expressions. +["o.m;", 4, "Dot Member Accessor, `;`"], +["o['m'];", 5, "Square Bracket Member Accessor, `;`"], +["o['n']['m'];", 8, "Nested Square Bracket Member Accessor, `;`"], +["o.n.m;", 6, "Nested Dot Member Accessor, `;`"], +["o.if;", 4, "Dot Reserved Property Name Accessor, `;`"], + +// Function Calls. +["f();", 4, "Function Call Operator, `;`"], +["f(x);", 5, "Function Call Operator With 1 Argument, `;`"], +["f(x,y);", 7, "Function Call Operator With Multiple Arguments, `;`"], +["o.m();", 6, "Dot Member Accessor, Function Call, `;`"], +["o['m']();", 7, "Square Bracket Member Accessor, Function Call, `;`"], +["o.m(x);", 7, "Dot Member Accessor, Function Call With 1 Argument, `;`"], +["o['m'](x);", 8, "Square Bracket Member Accessor, Function Call With 1 Argument, `;`"], +["o.m(x,y);", 9, "Dot Member Accessor, Function Call With 2 Arguments, `;`"], +["o['m'](x,y);", 10, "Square Bracket Member Accessor, Function Call With 2 Arguments, `;`"], +["f(x)(y);", 8, "Nested Function Call With 1 Argument Each, `;`"], +["f().x;", 6, "Function Call, Dot Member Accessor, `;`"], + +// `eval` Function. +["eval('x');", 5, "`eval` Invocation With 1 Argument, `;`"], +["(eval)('x');", 7, "Direct `eval` Call Example, `;`"], +["(1,eval)('x');", 9, "Indirect `eval` Call Example, `;`"], +["eval(x,y);", 7, "`eval` Invocation With 2 Arguments, `;`"], + +// `new` Operator. +["new f();", 6, "`new` Operator, Function Call, `;`"], +["new o;", 4, "`new` Operator, Identifier, `;`"], +["new o.m;", 6, "`new` Operator, Dot Member Accessor, `;`"], +["new o.m(x);", 9, "`new` Operator, Dot Member Accessor, Function Call With 1 Argument, `;`"], +["new o.m(x,y);", 11, "``new` Operator, Dot Member Accessor, Function Call With 2 Arguments , `;`"], + +// Prefix and Postfix Increment. +["++x;", 3, "Prefix Increment, Identifier, `;`"], +["x++;", 3, "Identifier, Postfix Increment, `;`"], +["--x;", 3, "Prefix Decrement, Identifier, `;`"], +["x--;", 3, "Postfix Decrement, Identifier, `;`"], +["x ++;", 4, "Identifier, Space, Postfix Increment, `;`"], +["x /* comment */ ++;", 6, "Identifier, Block Comment, Postfix Increment, `;`"], +["++ /* comment */ x;", 6, "Prefix Increment, Block Comment, Identifier, `;`"], + +// Unary Operators. +["delete x;", 4, "`delete` Operator, Space, Identifier, `;`"], +["void x;", 4, "`void` Operator, Space, Identifier, `;`"], +["typeof x;", 4, "`typeof` Operator, Space, Identifier, `;`"], +["+x;", 3, "Unary `+` Operator, Identifier, `;`"], +["-x;", 3, "Unary Negation Operator, Identifier, `;`"], +["~x;", 3, "Bitwise NOT Operator, Identifier, `;`"], +["!x;", 3, "Logical NOT Operator, Identifier, `;`"], + +// Comma Operator. +["x, y;", 5, "Comma Operator"], + +// Miscellaneous. +["new Date++;", 5, "`new` Operator, Identifier, Postfix Increment, `;`"], +["+x++;", 4, "Unary `+`, Identifier, Postfix Increment, `;`"], + +// Expressions. +["1 * 2;", 6, "Integer, Multiplication, Integer, `;`"], +["1 / 2;", 6, "Integer, Division, Integer, `;`"], +["1 % 2;", 6, "Integer, Modulus, Integer, `;`"], +["1 + 2;", 6, "Integer, Addition, Integer, `;`"], +["1 - 2;", 6, "Integer, Subtraction, Integer, `;`"], +["1 << 2;", 6, "Integer, Bitwise Left Shift, Integer, `;`"], +["1 >>> 2;", 6, "Integer, Bitwise Zero-fill Right Shift, Integer, `;`"], +["1 >> 2;", 6, "Integer, Bitwise Sign-Propagating Right Shift, Integer, `;`"], +["1 * 2 + 3;", 10, "Order-of-Operations Expression, `;`"], +["(1+2)*3;", 8, "Parenthesized Additive Expression, Multiplication, `;`"], +["1*(2+3);", 8, "Multiplication, Parenthesized Additive Expression, `;`"], +["xy;", 4, "Greater-Than Relational Operator, `;`"], +["x<=y;", 4, "Less-Than-or-Equal-To Relational Operator, `;`"], +["x>=y;", 4, "Greater-Than-or-Equal-To Relational Operator, `;`"], +["x instanceof y;", 6, "`instanceof` Operator, `;`"], +["x in y;", 6, "`in` Operator, `;`"], +["x&y;", 4, "Bitwise AND Operator, `;`"], +["x^y;", 4, "Bitwise XOR Operator, `;`"], +["x|y;", 4, "Bitwise OR Operator, `;`"], +["x+y>>= y;", 6, "Bitwise Zero-Fill Right Shift Assignment, `;`"], +["x <<= y;", 6, "Bitwise Left Shift Assignment, `;`"], +["x += y;", 6, "Additive Assignment, `;`"], +["x -= y;", 6, "Subtractive Assignment, `;`"], +["x *= y;", 6, "Multiplicative Assignment, `;`"], +["x /= y;", 6, "Divisive Assignment, `;`"], +["x %= y;", 6, "Modulus Assignment, `;`"], +["x >>= y;", 6, "Bitwise Sign-Propagating Right Shift Assignment, `;`"], +["x &= y;", 6, "Bitwise AND Assignment, `;`"], +["x ^= y;", 6, "Bitwise XOR Assignment, `;`"], +["x |= y;", 6, "Bitwise OR Assignment, `;`"], + +// Blocks. +["{};", 3, "Empty Block, `;`"], +["{x;};", 5, "Block Containing 1 Identifier, `;`"], +["{x;y;};", 7, "Block Containing 2 Identifiers, `;`"], + +// Variable Declarations. +["var abc;", 4, "Variable Declaration"], +["var x,y;", 6, "Comma-Separated Variable Declarations, `;`"], +["var x=1,y=2;", 10, "Comma-Separated Variable Initializations, `;`"], +["var x,y=2;", 8, "Variable Declaration, Variable Initialization, `;`"], + +// Empty Statements. +[";", 1, "Empty Statement"], +["\n;", 2, "Linefeed, `;`"], + +// Expression Statements. +["x;", 2, "Identifier, `;`"], +["5;", 2, "Integer, `;`"], +["1+2;", 4, "Additive Statement, `;`"], + +// `if...else` Statements. +["if (c) x; else y;", 13, "Space-Delimited `if...else` Statement"], +["if (c) x;", 8, "Space-Delimited `if` Statement, `;`"], +["if (c) {} else {};", 14, "Empty Block-Delimited `if...else` Statement"], +["if (c1) if (c2) s1; else s2;", 19, "Nested `if...else` Statement Without Dangling `else`"], + +// `while` and `do...while` Loops. +["do s; while (e);", 11, "Space-Delimited `do...while` Loop"], +["do { s; } while (e);", 15, "Block-Delimited `do...while` Loop"], +["while (e) s;", 8, "Space-Delimited `while` Loop"], +["while (e) { s; };", 13, "Block-Delimited `while` Loop"], + +// `for` and `for...in` Loops. +["for (;;) ;", 8, "Infinite Space-Delimited `for` Loop"], +["for (;c;x++) x;", 12, "`for` Loop: Empty Initialization Condition; Space-Delimited Body"], +["for (i;i foo(new window[(['Active'].concat('Object').join('X'))])\n```\n\n## License\n\nLicensed under the MIT license.\n\n[socket.io]: http://socket.io/\n", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/felixge/node-active-x-obfuscator/issues" + }, + "_id": "active-x-obfuscator@0.0.1", + "dist": { + "shasum": "06f16304a68f8a979be41c6391ccdf7ffe8a21e8" + }, + "_from": "active-x-obfuscator@0.0.1", + "_resolved": "https://registry.npmjs.org/active-x-obfuscator/-/active-x-obfuscator-0.0.1.tgz" +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/test.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/test.js new file mode 100644 index 00000000..e8fc807f --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/test.js @@ -0,0 +1,53 @@ +var activeXObfuscator = require('./index'); +var assert = require('assert'); + +var OBFUSCATED_ACTIVE_X_OBJECT = activeXObfuscator.OBFUSCATED_ACTIVE_X_OBJECT; +var OBFUSCATED_ACTIVE_X = activeXObfuscator.OBFUSCATED_ACTIVE_X; + +var input = + "foo(new ActiveXObject('Microsoft.XMLHTTP'))"; +var expected = + "foo(new window[" + OBFUSCATED_ACTIVE_X_OBJECT + "]('Microsoft.XMLHTTP'))"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo = 'ActiveXObject';"; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X_OBJECT + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + 'var foo = "ActiveXObject";'; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X_OBJECT + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + 'var foo = o.ActiveXObject;'; +var expected = + "var foo = o[" + OBFUSCATED_ACTIVE_X_OBJECT + "];"; +assert.equal(activeXObfuscator(input), expected); + +var input = + 'var foo = "ActiveX";'; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo = 'ActiveX';"; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo; // ActiveX is cool"; +var expected = + "var foo; // Ac...eX is cool"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo = 'ActiveX is cool';"; +assert.throws(function() { + activeXObfuscator(input); +}, /Unknown ActiveX occurence/); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/.npmignore b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/.npmignore new file mode 100644 index 00000000..d97eaa09 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/.npmignore @@ -0,0 +1,4 @@ +.DS_Store +.tmp*~ +*.local.* +.pinf-* \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.html b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.html new file mode 100644 index 00000000..5f37ac0f --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.html @@ -0,0 +1,981 @@ + + + + +UglifyJS – a JavaScript parser/compressor/beautifier + + + + + + + + + + + + + +
    + +
    + +
    +

    UglifyJS – a JavaScript parser/compressor/beautifier

    + + + + +
    +

    1 UglifyJS — a JavaScript parser/compressor/beautifier

    +
    + + +

    +This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on NodeJS, but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the exports.* lines from UglifyJS sources). +

    +

    +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in parse-js.js and it's a +port to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke. +

    +

    +( See cl-uglify-js if you're looking for the Common Lisp version of +UglifyJS. ) +

    +

    +The second part of this package, implemented in process.js, inspects and +manipulates the AST generated by the parser to provide the following: +

    +
      +
    • ability to re-generate JavaScript code from the AST. Optionally + indented—you can use this if you want to “beautify†a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +
    • +
    • shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with eval() calls or with{} statements. In short, if eval() or + with{} are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +
    • +
    • various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + +
        +
      • foo["bar"] ==> foo.bar + +
      • +
      • remove block brackets {} + +
      • +
      • join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + +
      • +
      • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + +
      • +
      • consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + +
      • +
      • various optimizations for IF statements: + +
          +
        • if (foo) bar(); else baz(); ==> foo?bar():baz(); +
        • +
        • if (!foo) bar(); else baz(); ==> foo?baz():bar(); +
        • +
        • if (foo) bar(); ==> foo&&bar(); +
        • +
        • if (!foo) bar(); ==> foo||bar(); +
        • +
        • if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); +
        • +
        • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + +
        • +
        + +
      • +
      • remove some unreachable code and warn about it (code that follows a + return, throw, break or continue statement, except + function/variable declarations). + +
      • +
      • act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. +
      • +
      + +
    • +
    + + + +
    + +
    +

    1.1 Unsafe transformations

    +
    + + +

    +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +--unsafe flag. +

    + +
    + +
    +

    1.1.1 Calls involving the global Array constructor

    +
    + + +

    +The following transformations occur: +

    + + + +
    new Array(1, 2, 3, 4)  => [1,2,3,4]
    +Array(a, b, c)         => [a,b,c]
    +new Array(5)           => Array(5)
    +new Array(a)           => Array(a)
    +
    + + +

    +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. +

    +

    +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a function or var declaration. Therefore, in the +following cases UglifyJS doesn't touch calls or instantiations of Array: +

    + + + +
    // case 1.  globally declared variable
    +  var Array;
    +  new Array(1, 2, 3);
    +  Array(a, b);
    +
    +  // or (can be declared later)
    +  new Array(1, 2, 3);
    +  var Array;
    +
    +  // or (can be a function)
    +  new Array(1, 2, 3);
    +  function Array() { ... }
    +
    +// case 2.  declared in a function
    +  (function(){
    +    a = new Array(1, 2, 3);
    +    b = Array(5, 6);
    +    var Array;
    +  })();
    +
    +  // or
    +  (function(Array){
    +    return Array(5, 6, 7);
    +  })();
    +
    +  // or
    +  (function(){
    +    return new Array(1, 2, 3, 4);
    +    function Array() { ... }
    +  })();
    +
    +  // etc.
    +
    + + +
    + +
    + +
    +

    1.1.2 obj.toString() ==> obj+“â€

    +
    + + +
    +
    + +
    + +
    +

    1.2 Install (NPM)

    +
    + + +

    +UglifyJS is now available through NPM — npm install uglify-js should do +the job. +

    +
    + +
    + +
    +

    1.3 Install latest code from GitHub

    +
    + + + + + +
    ## clone the repository
    +mkdir -p /where/you/wanna/put/it
    +cd /where/you/wanna/put/it
    +git clone git://github.com/mishoo/UglifyJS.git
    +
    +## make the module available to Node
    +mkdir -p ~/.node_libraries/
    +cd ~/.node_libraries/
    +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js
    +
    +## and if you want the CLI script too:
    +mkdir -p ~/bin
    +cd ~/bin
    +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs
    +  # (then add ~/bin to your $PATH if it's not there already)
    +
    + + +
    + +
    + +
    +

    1.4 Usage

    +
    + + +

    +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: +

    + + + +
    uglifyjs [ options... ] [ filename ]
    +
    + + +

    +filename should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. +

    +

    +Supported options: +

    +
      +
    • -b or --beautify — output indented code; when passed, additional + options control the beautifier: + +
        +
      • -i N or --indent N — indentation level (number of spaces) + +
      • +
      • -q or --quote-keys — quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +
      • +
      + +
    • +
    • --ascii — pass this argument to encode non-ASCII characters as + \uXXXX sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +
    • +
    • -nm or --no-mangle — don't mangle names. + +
    • +
    • -nmf or --no-mangle-functions – in case you want to mangle variable + names, but not touch function names. + +
    • +
    • -ns or --no-squeeze — don't call ast_squeeze() (which does various + optimizations that result in smaller, less readable code). + +
    • +
    • -mt or --mangle-toplevel — mangle names in the toplevel scope too + (by default we don't do this). + +
    • +
    • --no-seqs — when ast_squeeze() is called (thus, unless you pass + --no-squeeze) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass --no-seqs to disable it. + +
    • +
    • --no-dead-code — by default, UglifyJS will remove code that is + obviously unreachable (code that follows a return, throw, break or + continue statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +
    • +
    • -nc or --no-copyright — by default, uglifyjs will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +
    • +
    • -o filename or --output filename — put the result in filename. If + this isn't given, the result goes to standard output (or see next one). + +
    • +
    • --overwrite — if the code is read from a file (not from STDIN) and you + pass --overwrite then the output will be written in the same file. + +
    • +
    • --ast — pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +
    • +
    • -v or --verbose — output some notes on STDERR (for now just how long + each operation takes). + +
    • +
    • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value true, or you can specify a numeric value (such as + 1024), a quoted string value (such as ="object"= or + ='https://github.com'), or the name of another symbol or keyword (such as =null or document). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of conditional compilation + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + --define-from-module more suitable for use. + +
    • +
    • -define-from-module SOMEMODULE — will load the named module (as + per the NodeJS require() function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the --define option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of --define + options. + +
    • +
    • --unsafe — enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + +
        +
      • foo.toString() ==> foo+"" +
      • +
      • new Array(x,…) ==> [x,…] +
      • +
      • new Array(x) ==> Array(x) + +
      • +
      + +
    • +
    • --max-line-len (default 32K characters) — add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass –max-line-len 0 to disable this + safety feature. + +
    • +
    • --reserved-names — some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names require and $super + intact you'd specify –reserved-names "require,$super". + +
    • +
    • --inline-script – when you want to include the output literally in an + HTML <script> tag you can use this option to prevent </script from + showing up in the output. + +
    • +
    • --lift-vars – when you pass this, UglifyJS will apply the following + transformations (see the notes in API, ast_lift_variables): + +
        +
      • put all var declarations at the start of the scope +
      • +
      • make sure a variable is declared only once +
      • +
      • discard unused function arguments +
      • +
      • discard unused inner (named) functions +
      • +
      • finally, try to merge assignments into that one var declaration, if + possible. +
      • +
      + +
    • +
    + + + +
    + +
    +

    1.4.1 API

    +
    + + +

    +To use the library from JavaScript, you'd do the following (example for +NodeJS): +

    + + + +
    var jsp = require("uglify-js").parser;
    +var pro = require("uglify-js").uglify;
    +
    +var orig_code = "... JS code here";
    +var ast = jsp.parse(orig_code); // parse code and get the initial AST
    +ast = pro.ast_mangle(ast); // get a new AST with mangled names
    +ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
    +var final_code = pro.gen_code(ast); // compressed code here
    +
    + + +

    +The above performs the full compression that is possible right now. As you +can see, there are a sequence of steps which you can apply. For example if +you want compressed output but for some reason you don't want to mangle +variable names, you would simply skip the line that calls +pro.ast_mangle(ast). +

    +

    +Some of these functions take optional arguments. Here's a description: +

    +
      +
    • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST. + strict_semicolons is optional and defaults to false. If you pass + true then the parser will throw an error when it expects a semicolon and + it doesn't find it. For most JS code you don't want that, but it's useful + if you want to strictly sanitize your code. + +
    • +
    • pro.ast_lift_variables(ast) – merge and move var declarations to the + scop of the scope; discard unused function arguments or variables; discard + unused (named) inner functions. It also tries to merge assignments + following the var declaration into it. + +

      + If your code is very hand-optimized concerning var declarations, this + lifting variable declarations might actually increase size. For me it + helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also + note that (since it's not enabled by default) this operation isn't yet + heavily tested (please report if you find issues!). +

      +

      + Note that although it might increase the image size (on jQuery it gains + 865 bytes, 243 after gzip) it's technically more correct: in certain + situations, dead code removal might drop variable declarations, which + would not happen if the variables are lifted in advance. +

      +

      + Here's an example of what it does: +

    • +
    + + + + + +
    function f(a, b, c, d, e) {
    +    var q;
    +    var w;
    +    w = 10;
    +    q = 20;
    +    for (var i = 1; i < 10; ++i) {
    +        var boo = foo(a);
    +    }
    +    for (var i = 0; i < 1; ++i) {
    +        var boo = bar(c);
    +    }
    +    function foo(){ ... }
    +    function bar(){ ... }
    +    function baz(){ ... }
    +}
    +
    +// transforms into ==>
    +
    +function f(a, b, c) {
    +    var i, boo, w = 10, q = 20;
    +    for (i = 1; i < 10; ++i) {
    +        boo = foo(a);
    +    }
    +    for (i = 0; i < 1; ++i) {
    +        boo = bar(c);
    +    }
    +    function foo() { ... }
    +    function bar() { ... }
    +}
    +
    + + +
      +
    • pro.ast_mangle(ast, options) – generates a new AST containing mangled + (compressed) variable and function names. It supports the following + options: + +
        +
      • toplevel – mangle toplevel names (by default we don't touch them). +
      • +
      • except – an array of names to exclude from compression. +
      • +
      • defines – an object with properties named after symbols to + replace (see the --define option for the script) and the values + representing the AST replacement value. + +
      • +
      + +
    • +
    • pro.ast_squeeze(ast, options) – employs further optimizations designed + to reduce the size of the code that gen_code would generate from the + AST. Returns a new AST. options can be a hash; the supported options + are: + +
        +
      • make_seqs (default true) which will cause consecutive statements in a + block to be merged using the "sequence" (comma) operator + +
      • +
      • dead_code (default true) which will remove unreachable code. + +
      • +
      + +
    • +
    • pro.gen_code(ast, options) – generates JS code from the AST. By + default it's minified, but using the options argument you can get nicely + formatted output. options is, well, optional :-) and if you pass it it + must be an object and supports the following properties (below you can see + the default values): + +
        +
      • beautify: false – pass true if you want indented output +
      • +
      • indent_start: 0 (only applies when beautify is true) – initial + indentation in spaces +
      • +
      • indent_level: 4 (only applies when beautify is true) -- + indentation level, in spaces (pass an even number) +
      • +
      • quote_keys: false – if you pass true it will quote all keys in + literal objects +
      • +
      • space_colon: false (only applies when beautify is true) – wether + to put a space before the colon in object literals +
      • +
      • ascii_only: false – pass true if you want to encode non-ASCII + characters as \uXXXX. +
      • +
      • inline_script: false – pass true to escape occurrences of + </script in strings +
      • +
      + +
    • +
    + + +
    + +
    + +
    +

    1.4.2 Beautifier shortcoming – no more comments

    +
    + + +

    +The beautifier can be used as a general purpose indentation tool. It's +useful when you want to make a minified file readable. One limitation, +though, is that it discards all comments, so you don't really want to use it +to reformat your code, unless you don't have, or don't care about, comments. +

    +

    +In fact it's not the beautifier who discards comments — they are dumped at +the parsing stage, when we build the initial AST. Comments don't really +make sense in the AST, and while we could add nodes for them, it would be +inconvenient because we'd have to add special rules to ignore them at all +the processing stages. +

    +
    + +
    + +
    +

    1.4.3 Use as a code pre-processor

    +
    + + +

    +The --define option can be used, particularly when combined with the +constant folding logic, as a form of pre-processor to enable or remove +particular constructions, such as might be used for instrumenting +development code, or to produce variations aimed at a specific +platform. +

    +

    +The code below illustrates the way this can be done, and how the +symbol replacement is performed. +

    + + + +
    CLAUSE1: if (typeof DEVMODE === 'undefined') {
    +    DEVMODE = true;
    +}
    +
    +CLAUSE2: function init() {
    +    if (DEVMODE) {
    +        console.log("init() called");
    +    }
    +    ....
    +    DEVMODE &amp;&amp; console.log("init() complete");
    +}
    +
    +CLAUSE3: function reportDeviceStatus(device) {
    +    var DEVMODE = device.mode, DEVNAME = device.name;
    +    if (DEVMODE === 'open') {
    +        ....
    +    }
    +}
    +
    + + +

    +When the above code is normally executed, the undeclared global +variable DEVMODE will be assigned the value true (see CLAUSE1) +and so the init() function (CLAUSE2) will write messages to the +console log when executed, but in CLAUSE3 a locally declared +variable will mask access to the DEVMODE global symbol. +

    +

    +If the above code is processed by UglifyJS with an argument of +--define DEVMODE=false then UglifyJS will replace DEVMODE with the +boolean constant value false within CLAUSE1 and CLAUSE2, but it +will leave CLAUSE3 as it stands because there DEVMODE resolves to +a validly declared variable. +

    +

    +And more so, the constant-folding features of UglifyJS will recognise +that the if condition of CLAUSE1 is thus always false, and so will +remove the test and body of CLAUSE1 altogether (including the +otherwise slightly problematical statement false = true; which it +will have formed by replacing DEVMODE in the body). Similarly, +within CLAUSE2 both calls to console.log() will be removed +altogether. +

    +

    +In this way you can mimic, to a limited degree, the functionality of +the C/C++ pre-processor to enable or completely remove blocks +depending on how certain symbols are defined - perhaps using UglifyJS +to generate different versions of source aimed at different +environments +

    +

    +It is recommmended (but not made mandatory) that symbols designed for +this purpose are given names consisting of UPPER_CASE_LETTERS to +distinguish them from other (normal) symbols and avoid the sort of +clash that CLAUSE3 above illustrates. +

    +
    +
    + +
    + +
    +

    1.5 Compression – how good is it?

    +
    + + +

    +Here are updated statistics. (I also updated my Google Closure and YUI +installations). +

    +

    +We're still a lot better than YUI in terms of compression, though slightly +slower. We're still a lot faster than Closure, and compression after gzip +is comparable. +

    + + ++ + + + + + + + + + +
    FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
    jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
    paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
    prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
    thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
    + + +
    + +
    + +
    +

    1.6 Bugs?

    +
    + + +

    +Unfortunately, for the time being there is no automated test suite. But I +ran the compressor manually on non-trivial code, and then I tested that the +generated code works as expected. A few hundred times. +

    +

    +DynarchLIB was started in times when there was no good JS minifier. +Therefore I was quite religious about trying to write short code manually, +and as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a += 10 : b = 20â€, though the more readable version would clearly be to use +“if/elseâ€. +

    +

    +Since the parser/compressor runs fine on DL and jQuery, I'm quite confident +that it's solid enough for production use. If you can identify any bugs, +I'd love to hear about them (use the Google Group or email me directly). +

    +
    + +
    + +
    +

    1.7 Links

    +
    + + + + + +
    + +
    + +
    +

    1.8 License

    +
    + + +

    +UglifyJS is released under the BSD license: +

    + + + +
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
    +Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
    +
    +Redistribution and use in source and binary forms, with or without
    +modification, are permitted provided that the following conditions
    +are met:
    +
    +    * Redistributions of source code must retain the above
    +      copyright notice, this list of conditions and the following
    +      disclaimer.
    +
    +    * Redistributions in binary form must reproduce the above
    +      copyright notice, this list of conditions and the following
    +      disclaimer in the documentation and/or other materials
    +      provided with the distribution.
    +
    +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS†AND ANY
    +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
    +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
    +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
    +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    +SUCH DAMAGE.
    +
    + + +
    +

    Footnotes:

    +
    +

    1 I even reported a few bugs and suggested some fixes in the original + parse-js library, and Marijn pushed fixes literally in minutes. +

    +
    +
    + +
    +
    +
    + +
    +

    Date: 2011-12-09 14:59:08 EET

    +

    Author: Mihai Bazon

    +

    Org version 7.7 with Emacs version 23

    +Validate XHTML 1.0 + +
    + + diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.org b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.org new file mode 100644 index 00000000..4d01fdfd --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.org @@ -0,0 +1,574 @@ +#+TITLE: UglifyJS -- a JavaScript parser/compressor/beautifier +#+KEYWORDS: javascript, js, parser, compiler, compressor, mangle, minify, minifier +#+DESCRIPTION: a JavaScript parser/compressor/beautifier in JavaScript +#+STYLE: +#+AUTHOR: Mihai Bazon +#+EMAIL: mihai.bazon@gmail.com + +* UglifyJS --- a JavaScript parser/compressor/beautifier + +This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on [[http://nodejs.org/][NodeJS]], but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the =exports.*= lines from UglifyJS sources). + +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in [[../lib/parse-js.js][parse-js.js]] and it's a +port to JavaScript of the excellent [[http://marijn.haverbeke.nl/parse-js/][parse-js]] Common Lisp library from [[http://marijn.haverbeke.nl/][Marijn +Haverbeke]]. + +( See [[http://github.com/mishoo/cl-uglify-js][cl-uglify-js]] if you're looking for the Common Lisp version of +UglifyJS. ) + +The second part of this package, implemented in [[../lib/process.js][process.js]], inspects and +manipulates the AST generated by the parser to provide the following: + +- ability to re-generate JavaScript code from the AST. Optionally + indented---you can use this if you want to “beautify†a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +- shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with =eval()= calls or =with{}= statements. In short, if =eval()= or + =with{}= are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +- various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + + - foo["bar"] ==> foo.bar + + - remove block brackets ={}= + + - join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + + - resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + + - consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + + - various optimizations for IF statements: + + - if (foo) bar(); else baz(); ==> foo?bar():baz(); + - if (!foo) bar(); else baz(); ==> foo?baz():bar(); + - if (foo) bar(); ==> foo&&bar(); + - if (!foo) bar(); ==> foo||bar(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + + - remove some unreachable code and warn about it (code that follows a + =return=, =throw=, =break= or =continue= statement, except + function/variable declarations). + + - act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. + +** <> + +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +=--unsafe= flag. + +*** Calls involving the global Array constructor + +The following transformations occur: + +#+BEGIN_SRC js +new Array(1, 2, 3, 4) => [1,2,3,4] +Array(a, b, c) => [a,b,c] +new Array(5) => Array(5) +new Array(a) => Array(a) +#+END_SRC + +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. + +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a =function= or =var= declaration. Therefore, in the +following cases UglifyJS *doesn't touch* calls or instantiations of Array: + +#+BEGIN_SRC js +// case 1. globally declared variable + var Array; + new Array(1, 2, 3); + Array(a, b); + + // or (can be declared later) + new Array(1, 2, 3); + var Array; + + // or (can be a function) + new Array(1, 2, 3); + function Array() { ... } + +// case 2. declared in a function + (function(){ + a = new Array(1, 2, 3); + b = Array(5, 6); + var Array; + })(); + + // or + (function(Array){ + return Array(5, 6, 7); + })(); + + // or + (function(){ + return new Array(1, 2, 3, 4); + function Array() { ... } + })(); + + // etc. +#+END_SRC + +*** =obj.toString()= ==> =obj+“â€= + +** Install (NPM) + +UglifyJS is now available through NPM --- =npm install uglify-js= should do +the job. + +** Install latest code from GitHub + +#+BEGIN_SRC sh +## clone the repository +mkdir -p /where/you/wanna/put/it +cd /where/you/wanna/put/it +git clone git://github.com/mishoo/UglifyJS.git + +## make the module available to Node +mkdir -p ~/.node_libraries/ +cd ~/.node_libraries/ +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js + +## and if you want the CLI script too: +mkdir -p ~/bin +cd ~/bin +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs + # (then add ~/bin to your $PATH if it's not there already) +#+END_SRC + +** Usage + +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: + +#+BEGIN_SRC sh +uglifyjs [ options... ] [ filename ] +#+END_SRC + +=filename= should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. + +Supported options: + +- =-b= or =--beautify= --- output indented code; when passed, additional + options control the beautifier: + + - =-i N= or =--indent N= --- indentation level (number of spaces) + + - =-q= or =--quote-keys= --- quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +- =--ascii= --- pass this argument to encode non-ASCII characters as + =\uXXXX= sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +- =-nm= or =--no-mangle= --- don't mangle names. + +- =-nmf= or =--no-mangle-functions= -- in case you want to mangle variable + names, but not touch function names. + +- =-ns= or =--no-squeeze= --- don't call =ast_squeeze()= (which does various + optimizations that result in smaller, less readable code). + +- =-mt= or =--mangle-toplevel= --- mangle names in the toplevel scope too + (by default we don't do this). + +- =--no-seqs= --- when =ast_squeeze()= is called (thus, unless you pass + =--no-squeeze=) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass =--no-seqs= to disable it. + +- =--no-dead-code= --- by default, UglifyJS will remove code that is + obviously unreachable (code that follows a =return=, =throw=, =break= or + =continue= statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +- =-nc= or =--no-copyright= --- by default, =uglifyjs= will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +- =-o filename= or =--output filename= --- put the result in =filename=. If + this isn't given, the result goes to standard output (or see next one). + +- =--overwrite= --- if the code is read from a file (not from STDIN) and you + pass =--overwrite= then the output will be written in the same file. + +- =--ast= --- pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +- =-v= or =--verbose= --- output some notes on STDERR (for now just how long + each operation takes). + +- =-d SYMBOL[=VALUE]= or =--define SYMBOL[=VALUE]= --- will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value =true=, or you can specify a numeric value (such as + =1024=), a quoted string value (such as ="object"= or + ='https://github.com'=), or the name of another symbol or keyword + (such as =null= or =document=). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of *conditional compilation* + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + =--define-from-module= more suitable for use. + +- =-define-from-module SOMEMODULE= --- will load the named module (as + per the NodeJS =require()= function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the =--define= option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of =--define= + options. + +- =--unsafe= --- enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + + - foo.toString() ==> foo+"" + - new Array(x,...) ==> [x,...] + - new Array(x) ==> Array(x) + +- =--max-line-len= (default 32K characters) --- add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass --max-line-len 0 to disable this + safety feature. + +- =--reserved-names= --- some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names =require= and =$super= + intact you'd specify --reserved-names "require,$super". + +- =--inline-script= -- when you want to include the output literally in an + HTML =\n\n\n\n\n
    \n\n
    \n\n
    \n

    UglifyJS – a JavaScript parser/compressor/beautifier

    \n\n\n\n\n
    \n

    1 UglifyJS — a JavaScript parser/compressor/beautifier

    \n
    \n\n\n

    \nThis package implements a general-purpose JavaScript\nparser/compressor/beautifier toolkit. It is developed on NodeJS, but it\nshould work on any JavaScript platform supporting the CommonJS module system\n(and if your platform of choice doesn't support CommonJS, you can easily\nimplement it, or discard the exports.* lines from UglifyJS sources).\n

    \n

    \nThe tokenizer/parser generates an abstract syntax tree from JS code. You\ncan then traverse the AST to learn more about the code, or do various\nmanipulations on it. This part is implemented in parse-js.js and it's a\nport to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke.\n

    \n

    \n( See cl-uglify-js if you're looking for the Common Lisp version of\nUglifyJS. )\n

    \n

    \nThe second part of this package, implemented in process.js, inspects and\nmanipulates the AST generated by the parser to provide the following:\n

    \n
      \n
    • ability to re-generate JavaScript code from the AST. Optionally\n indented—you can use this if you want to “beautify†a program that has\n been compressed, so that you can inspect the source. But you can also run\n our code generator to print out an AST without any whitespace, so you\n achieve compression as well.\n\n
    • \n
    • shorten variable names (usually to single characters). Our mangler will\n analyze the code and generate proper variable names, depending on scope\n and usage, and is smart enough to deal with globals defined elsewhere, or\n with eval() calls or with{} statements. In short, if eval() or\n with{} are used in some scope, then all variables in that scope and any\n variables in the parent scopes will remain unmangled, and any references\n to such variables remain unmangled as well.\n\n
    • \n
    • various small optimizations that may lead to faster code but certainly\n lead to smaller code. Where possible, we do the following:\n\n
        \n
      • foo[\"bar\"] ==> foo.bar\n\n
      • \n
      • remove block brackets {}\n\n
      • \n
      • join consecutive var declarations:\n var a = 10; var b = 20; ==> var a=10,b=20;\n\n
      • \n
      • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the\n replacement if the result occupies less bytes; for example 1/3 would\n translate to 0.333333333333, so in this case we don't replace it.\n\n
      • \n
      • consecutive statements in blocks are merged into a sequence; in many\n cases, this leaves blocks with a single statement, so then we can remove\n the block brackets.\n\n
      • \n
      • various optimizations for IF statements:\n\n
          \n
        • if (foo) bar(); else baz(); ==> foo?bar():baz();\n
        • \n
        • if (!foo) bar(); else baz(); ==> foo?baz():bar();\n
        • \n
        • if (foo) bar(); ==> foo&&bar();\n
        • \n
        • if (!foo) bar(); ==> foo||bar();\n
        • \n
        • if (foo) return bar(); else return baz(); ==> return foo?bar():baz();\n
        • \n
        • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}\n\n
        • \n
        \n\n
      • \n
      • remove some unreachable code and warn about it (code that follows a\n return, throw, break or continue statement, except\n function/variable declarations).\n\n
      • \n
      • act a limited version of a pre-processor (c.f. the pre-processor of\n C/C++) to allow you to safely replace selected global symbols with\n specified values. When combined with the optimisations above this can\n make UglifyJS operate slightly more like a compilation process, in\n that when certain symbols are replaced by constant values, entire code\n blocks may be optimised away as unreachable.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    1.1 Unsafe transformations

    \n
    \n\n\n

    \nThe following transformations can in theory break code, although they're\nprobably safe in most practical cases. To enable them you need to pass the\n--unsafe flag.\n

    \n\n
    \n\n
    \n

    1.1.1 Calls involving the global Array constructor

    \n
    \n\n\n

    \nThe following transformations occur:\n

    \n\n\n\n
    new Array(1, 2, 3, 4)  => [1,2,3,4]\nArray(a, b, c)         => [a,b,c]\nnew Array(5)           => Array(5)\nnew Array(a)           => Array(a)\n
    \n\n\n

    \nThese are all safe if the Array name isn't redefined. JavaScript does allow\none to globally redefine Array (and pretty much everything, in fact) but I\npersonally don't see why would anyone do that.\n

    \n

    \nUglifyJS does handle the case where Array is redefined locally, or even\nglobally but with a function or var declaration. Therefore, in the\nfollowing cases UglifyJS doesn't touch calls or instantiations of Array:\n

    \n\n\n\n
    // case 1.  globally declared variable\n  var Array;\n  new Array(1, 2, 3);\n  Array(a, b);\n\n  // or (can be declared later)\n  new Array(1, 2, 3);\n  var Array;\n\n  // or (can be a function)\n  new Array(1, 2, 3);\n  function Array() { ... }\n\n// case 2.  declared in a function\n  (function(){\n    a = new Array(1, 2, 3);\n    b = Array(5, 6);\n    var Array;\n  })();\n\n  // or\n  (function(Array){\n    return Array(5, 6, 7);\n  })();\n\n  // or\n  (function(){\n    return new Array(1, 2, 3, 4);\n    function Array() { ... }\n  })();\n\n  // etc.\n
    \n\n\n
    \n\n
    \n\n
    \n

    1.1.2 obj.toString() ==> obj+“â€

    \n
    \n\n\n
    \n
    \n\n
    \n\n
    \n

    1.2 Install (NPM)

    \n
    \n\n\n

    \nUglifyJS is now available through NPM — npm install uglify-js should do\nthe job.\n

    \n
    \n\n
    \n\n
    \n

    1.3 Install latest code from GitHub

    \n
    \n\n\n\n\n\n
    ## clone the repository\nmkdir -p /where/you/wanna/put/it\ncd /where/you/wanna/put/it\ngit clone git://github.com/mishoo/UglifyJS.git\n\n## make the module available to Node\nmkdir -p ~/.node_libraries/\ncd ~/.node_libraries/\nln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js\n\n## and if you want the CLI script too:\nmkdir -p ~/bin\ncd ~/bin\nln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs\n  # (then add ~/bin to your $PATH if it's not there already)\n
    \n\n\n
    \n\n
    \n\n
    \n

    1.4 Usage

    \n
    \n\n\n

    \nThere is a command-line tool that exposes the functionality of this library\nfor your shell-scripting needs:\n

    \n\n\n\n
    uglifyjs [ options... ] [ filename ]\n
    \n\n\n

    \nfilename should be the last argument and should name the file from which\nto read the JavaScript code. If you don't specify it, it will read code\nfrom STDIN.\n

    \n

    \nSupported options:\n

    \n
      \n
    • -b or --beautify — output indented code; when passed, additional\n options control the beautifier:\n\n
        \n
      • -i N or --indent N — indentation level (number of spaces)\n\n
      • \n
      • -q or --quote-keys — quote keys in literal objects (by default,\n only keys that cannot be identifier names will be quotes).\n\n
      • \n
      \n\n
    • \n
    • --ascii — pass this argument to encode non-ASCII characters as\n \\uXXXX sequences. By default UglifyJS won't bother to do it and will\n output Unicode characters instead. (the output is always encoded in UTF8,\n but if you pass this option you'll only get ASCII).\n\n
    • \n
    • -nm or --no-mangle — don't mangle names.\n\n
    • \n
    • -nmf or --no-mangle-functions – in case you want to mangle variable\n names, but not touch function names.\n\n
    • \n
    • -ns or --no-squeeze — don't call ast_squeeze() (which does various\n optimizations that result in smaller, less readable code).\n\n
    • \n
    • -mt or --mangle-toplevel — mangle names in the toplevel scope too\n (by default we don't do this).\n\n
    • \n
    • --no-seqs — when ast_squeeze() is called (thus, unless you pass\n --no-squeeze) it will reduce consecutive statements in blocks into a\n sequence. For example, \"a = 10; b = 20; foo();\" will be written as\n \"a=10,b=20,foo();\". In various occasions, this allows us to discard the\n block brackets (since the block becomes a single statement). This is ON\n by default because it seems safe and saves a few hundred bytes on some\n libs that I tested it on, but pass --no-seqs to disable it.\n\n
    • \n
    • --no-dead-code — by default, UglifyJS will remove code that is\n obviously unreachable (code that follows a return, throw, break or\n continue statement and is not a function/variable declaration). Pass\n this option to disable this optimization.\n\n
    • \n
    • -nc or --no-copyright — by default, uglifyjs will keep the initial\n comment tokens in the generated code (assumed to be copyright information\n etc.). If you pass this it will discard it.\n\n
    • \n
    • -o filename or --output filename — put the result in filename. If\n this isn't given, the result goes to standard output (or see next one).\n\n
    • \n
    • --overwrite — if the code is read from a file (not from STDIN) and you\n pass --overwrite then the output will be written in the same file.\n\n
    • \n
    • --ast — pass this if you want to get the Abstract Syntax Tree instead\n of JavaScript as output. Useful for debugging or learning more about the\n internals.\n\n
    • \n
    • -v or --verbose — output some notes on STDERR (for now just how long\n each operation takes).\n\n
    • \n
    • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace\n all instances of the specified symbol where used as an identifier\n (except where symbol has properly declared by a var declaration or\n use as function parameter or similar) with the specified value. This\n argument may be specified multiple times to define multiple\n symbols - if no value is specified the symbol will be replaced with\n the value true, or you can specify a numeric value (such as\n 1024), a quoted string value (such as =\"object\"= or\n ='https://github.com'), or the name of another symbol or keyword (such as =null or document).\n This allows you, for example, to assign meaningful names to key\n constant values but discard the symbolic names in the uglified\n version for brevity/efficiency, or when used wth care, allows\n UglifyJS to operate as a form of conditional compilation\n whereby defining appropriate values may, by dint of the constant\n folding and dead code removal features above, remove entire\n superfluous code blocks (e.g. completely remove instrumentation or\n trace code for production use).\n Where string values are being defined, the handling of quotes are\n likely to be subject to the specifics of your command shell\n environment, so you may need to experiment with quoting styles\n depending on your platform, or you may find the option\n --define-from-module more suitable for use.\n\n
    • \n
    • -define-from-module SOMEMODULE — will load the named module (as\n per the NodeJS require() function) and iterate all the exported\n properties of the module defining them as symbol names to be defined\n (as if by the --define option) per the name of each property\n (i.e. without the module name prefix) and given the value of the\n property. This is a much easier way to handle and document groups of\n symbols to be defined rather than a large number of --define\n options.\n\n
    • \n
    • --unsafe — enable other additional optimizations that are known to be\n unsafe in some contrived situations, but could still be generally useful.\n For now only these:\n\n
        \n
      • foo.toString() ==> foo+\"\"\n
      • \n
      • new Array(x,…) ==> [x,…]\n
      • \n
      • new Array(x) ==> Array(x)\n\n
      • \n
      \n\n
    • \n
    • --max-line-len (default 32K characters) — add a newline after around\n 32K characters. I've seen both FF and Chrome croak when all the code was\n on a single line of around 670K. Pass –max-line-len 0 to disable this\n safety feature.\n\n
    • \n
    • --reserved-names — some libraries rely on certain names to be used, as\n pointed out in issue #92 and #81, so this option allow you to exclude such\n names from the mangler. For example, to keep names require and $super\n intact you'd specify –reserved-names \"require,$super\".\n\n
    • \n
    • --inline-script – when you want to include the output literally in an\n HTML <script> tag you can use this option to prevent </script from\n showing up in the output.\n\n
    • \n
    • --lift-vars – when you pass this, UglifyJS will apply the following\n transformations (see the notes in API, ast_lift_variables):\n\n
        \n
      • put all var declarations at the start of the scope\n
      • \n
      • make sure a variable is declared only once\n
      • \n
      • discard unused function arguments\n
      • \n
      • discard unused inner (named) functions\n
      • \n
      • finally, try to merge assignments into that one var declaration, if\n possible.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    1.4.1 API

    \n
    \n\n\n

    \nTo use the library from JavaScript, you'd do the following (example for\nNodeJS):\n

    \n\n\n\n
    var jsp = require(\"uglify-js\").parser;\nvar pro = require(\"uglify-js\").uglify;\n\nvar orig_code = \"... JS code here\";\nvar ast = jsp.parse(orig_code); // parse code and get the initial AST\nast = pro.ast_mangle(ast); // get a new AST with mangled names\nast = pro.ast_squeeze(ast); // get an AST with compression optimizations\nvar final_code = pro.gen_code(ast); // compressed code here\n
    \n\n\n

    \nThe above performs the full compression that is possible right now. As you\ncan see, there are a sequence of steps which you can apply. For example if\nyou want compressed output but for some reason you don't want to mangle\nvariable names, you would simply skip the line that calls\npro.ast_mangle(ast).\n

    \n

    \nSome of these functions take optional arguments. Here's a description:\n

    \n
      \n
    • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST.\n strict_semicolons is optional and defaults to false. If you pass\n true then the parser will throw an error when it expects a semicolon and\n it doesn't find it. For most JS code you don't want that, but it's useful\n if you want to strictly sanitize your code.\n\n
    • \n
    • pro.ast_lift_variables(ast) – merge and move var declarations to the\n scop of the scope; discard unused function arguments or variables; discard\n unused (named) inner functions. It also tries to merge assignments\n following the var declaration into it.\n\n

      \n If your code is very hand-optimized concerning var declarations, this\n lifting variable declarations might actually increase size. For me it\n helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also\n note that (since it's not enabled by default) this operation isn't yet\n heavily tested (please report if you find issues!).\n

      \n

      \n Note that although it might increase the image size (on jQuery it gains\n 865 bytes, 243 after gzip) it's technically more correct: in certain\n situations, dead code removal might drop variable declarations, which\n would not happen if the variables are lifted in advance.\n

      \n

      \n Here's an example of what it does:\n

    • \n
    \n\n\n\n\n\n
    function f(a, b, c, d, e) {\n    var q;\n    var w;\n    w = 10;\n    q = 20;\n    for (var i = 1; i < 10; ++i) {\n        var boo = foo(a);\n    }\n    for (var i = 0; i < 1; ++i) {\n        var boo = bar(c);\n    }\n    function foo(){ ... }\n    function bar(){ ... }\n    function baz(){ ... }\n}\n\n// transforms into ==>\n\nfunction f(a, b, c) {\n    var i, boo, w = 10, q = 20;\n    for (i = 1; i < 10; ++i) {\n        boo = foo(a);\n    }\n    for (i = 0; i < 1; ++i) {\n        boo = bar(c);\n    }\n    function foo() { ... }\n    function bar() { ... }\n}\n
    \n\n\n
      \n
    • pro.ast_mangle(ast, options) – generates a new AST containing mangled\n (compressed) variable and function names. It supports the following\n options:\n\n
        \n
      • toplevel – mangle toplevel names (by default we don't touch them).\n
      • \n
      • except – an array of names to exclude from compression.\n
      • \n
      • defines – an object with properties named after symbols to\n replace (see the --define option for the script) and the values\n representing the AST replacement value.\n\n
      • \n
      \n\n
    • \n
    • pro.ast_squeeze(ast, options) – employs further optimizations designed\n to reduce the size of the code that gen_code would generate from the\n AST. Returns a new AST. options can be a hash; the supported options\n are:\n\n
        \n
      • make_seqs (default true) which will cause consecutive statements in a\n block to be merged using the \"sequence\" (comma) operator\n\n
      • \n
      • dead_code (default true) which will remove unreachable code.\n\n
      • \n
      \n\n
    • \n
    • pro.gen_code(ast, options) – generates JS code from the AST. By\n default it's minified, but using the options argument you can get nicely\n formatted output. options is, well, optional :-) and if you pass it it\n must be an object and supports the following properties (below you can see\n the default values):\n\n
        \n
      • beautify: false – pass true if you want indented output\n
      • \n
      • indent_start: 0 (only applies when beautify is true) – initial\n indentation in spaces\n
      • \n
      • indent_level: 4 (only applies when beautify is true) --\n indentation level, in spaces (pass an even number)\n
      • \n
      • quote_keys: false – if you pass true it will quote all keys in\n literal objects\n
      • \n
      • space_colon: false (only applies when beautify is true) – wether\n to put a space before the colon in object literals\n
      • \n
      • ascii_only: false – pass true if you want to encode non-ASCII\n characters as \\uXXXX.\n
      • \n
      • inline_script: false – pass true to escape occurrences of\n </script in strings\n
      • \n
      \n\n
    • \n
    \n\n\n
    \n\n
    \n\n
    \n

    1.4.2 Beautifier shortcoming – no more comments

    \n
    \n\n\n

    \nThe beautifier can be used as a general purpose indentation tool. It's\nuseful when you want to make a minified file readable. One limitation,\nthough, is that it discards all comments, so you don't really want to use it\nto reformat your code, unless you don't have, or don't care about, comments.\n

    \n

    \nIn fact it's not the beautifier who discards comments — they are dumped at\nthe parsing stage, when we build the initial AST. Comments don't really\nmake sense in the AST, and while we could add nodes for them, it would be\ninconvenient because we'd have to add special rules to ignore them at all\nthe processing stages.\n

    \n
    \n\n
    \n\n
    \n

    1.4.3 Use as a code pre-processor

    \n
    \n\n\n

    \nThe --define option can be used, particularly when combined with the\nconstant folding logic, as a form of pre-processor to enable or remove\nparticular constructions, such as might be used for instrumenting\ndevelopment code, or to produce variations aimed at a specific\nplatform.\n

    \n

    \nThe code below illustrates the way this can be done, and how the\nsymbol replacement is performed.\n

    \n\n\n\n
    CLAUSE1: if (typeof DEVMODE === 'undefined') {\n    DEVMODE = true;\n}\n\nCLAUSE2: function init() {\n    if (DEVMODE) {\n        console.log(\"init() called\");\n    }\n    ....\n    DEVMODE &amp;&amp; console.log(\"init() complete\");\n}\n\nCLAUSE3: function reportDeviceStatus(device) {\n    var DEVMODE = device.mode, DEVNAME = device.name;\n    if (DEVMODE === 'open') {\n        ....\n    }\n}\n
    \n\n\n

    \nWhen the above code is normally executed, the undeclared global\nvariable DEVMODE will be assigned the value true (see CLAUSE1)\nand so the init() function (CLAUSE2) will write messages to the\nconsole log when executed, but in CLAUSE3 a locally declared\nvariable will mask access to the DEVMODE global symbol.\n

    \n

    \nIf the above code is processed by UglifyJS with an argument of\n--define DEVMODE=false then UglifyJS will replace DEVMODE with the\nboolean constant value false within CLAUSE1 and CLAUSE2, but it\nwill leave CLAUSE3 as it stands because there DEVMODE resolves to\na validly declared variable.\n

    \n

    \nAnd more so, the constant-folding features of UglifyJS will recognise\nthat the if condition of CLAUSE1 is thus always false, and so will\nremove the test and body of CLAUSE1 altogether (including the\notherwise slightly problematical statement false = true; which it\nwill have formed by replacing DEVMODE in the body). Similarly,\nwithin CLAUSE2 both calls to console.log() will be removed\naltogether.\n

    \n

    \nIn this way you can mimic, to a limited degree, the functionality of\nthe C/C++ pre-processor to enable or completely remove blocks\ndepending on how certain symbols are defined - perhaps using UglifyJS\nto generate different versions of source aimed at different\nenvironments\n

    \n

    \nIt is recommmended (but not made mandatory) that symbols designed for\nthis purpose are given names consisting of UPPER_CASE_LETTERS to\ndistinguish them from other (normal) symbols and avoid the sort of\nclash that CLAUSE3 above illustrates.\n

    \n
    \n
    \n\n
    \n\n
    \n

    1.5 Compression – how good is it?

    \n
    \n\n\n

    \nHere are updated statistics. (I also updated my Google Closure and YUI\ninstallations).\n

    \n

    \nWe're still a lot better than YUI in terms of compression, though slightly\nslower. We're still a lot faster than Closure, and compression after gzip\nis comparable.\n

    \n\n\n\n\n\n\n\n\n\n\n\n\n\n
    FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
    jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
    paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
    prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
    thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
    \n\n\n
    \n\n
    \n\n
    \n

    1.6 Bugs?

    \n
    \n\n\n

    \nUnfortunately, for the time being there is no automated test suite. But I\nran the compressor manually on non-trivial code, and then I tested that the\ngenerated code works as expected. A few hundred times.\n

    \n

    \nDynarchLIB was started in times when there was no good JS minifier.\nTherefore I was quite religious about trying to write short code manually,\nand as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a\n= 10 : b = 20â€, though the more readable version would clearly be to use\n“if/elseâ€.\n

    \n

    \nSince the parser/compressor runs fine on DL and jQuery, I'm quite confident\nthat it's solid enough for production use. If you can identify any bugs,\nI'd love to hear about them (use the Google Group or email me directly).\n

    \n
    \n\n
    \n\n
    \n

    1.7 Links

    \n
    \n\n\n\n\n\n
    \n\n
    \n\n
    \n

    1.8 License

    \n
    \n\n\n

    \nUglifyJS is released under the BSD license:\n

    \n\n\n\n
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\nBased on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n    * Redistributions of source code must retain the above\n      copyright notice, this list of conditions and the following\n      disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials\n      provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS†AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n
    \n\n\n
    \n

    Footnotes:

    \n
    \n

    1 I even reported a few bugs and suggested some fixes in the original\n parse-js library, and Marijn pushed fixes literally in minutes.\n

    \n
    \n
    \n\n
    \n
    \n
    \n\n
    \n

    Date: 2011-12-09 14:59:08 EET

    \n

    Author: Mihai Bazon

    \n

    Org version 7.7 with Emacs version 23

    \nValidate XHTML 1.0\n\n
    \n\n\n", + "readmeFilename": "README.html", + "bugs": { + "url": "https://github.com/mishoo/UglifyJS/issues" + }, + "_id": "uglify-js@1.2.5", + "dist": { + "shasum": "903eb33b7e6c7337fda90dfab0a9bb424cab11be" + }, + "_from": "uglify-js@1.2.5", + "_resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.2.5.tgz" +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/269.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/269.js new file mode 100644 index 00000000..256ad1c9 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/269.js @@ -0,0 +1,13 @@ +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +var test_code = "var JSON;JSON||(JSON={});"; + +var ast = jsp.parse(test_code, false, false); +var nonembed_token_code = pro.gen_code(ast); +ast = jsp.parse(test_code, false, true); +var embed_token_code = pro.gen_code(ast); + +console.log("original: " + test_code); +console.log("no token: " + nonembed_token_code); +console.log(" token: " + embed_token_code); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/app.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/app.js new file mode 100644 index 00000000..2c6257eb --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/app.js @@ -0,0 +1,22315 @@ +/* Modernizr 2.0.6 (Custom Build) | MIT & BSD + * Build: http://www.modernizr.com/download/#-iepp + */ +;window.Modernizr=function(a,b,c){function w(a,b){return!!~(""+a).indexOf(b)}function v(a,b){return typeof a===b}function u(a,b){return t(prefixes.join(a+";")+(b||""))}function t(a){j.cssText=a}var d="2.0.6",e={},f=b.documentElement,g=b.head||b.getElementsByTagName("head")[0],h="modernizr",i=b.createElement(h),j=i.style,k,l=Object.prototype.toString,m={},n={},o={},p=[],q,r={}.hasOwnProperty,s;!v(r,c)&&!v(r.call,c)?s=function(a,b){return r.call(a,b)}:s=function(a,b){return b in a&&v(a.constructor.prototype[b],c)};for(var x in m)s(m,x)&&(q=x.toLowerCase(),e[q]=m[x](),p.push((e[q]?"":"no-")+q));t(""),i=k=null,a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="";return a.childNodes.length!==1}()&&function(a,b){function s(a){var b=-1;while(++b to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.6.3", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery._Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return (new Function( "return " + data ))(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( !array ) { + return -1; + } + + if ( indexOf ) { + return indexOf.call( array, elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +var // Promise methods + promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), + // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + always: function() { + return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + pipe: function( fnDone, fnFail ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + }); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + } +}); + + + +jQuery.support = (function() { + + var div = document.createElement( "div" ), + documentElement = document.documentElement, + all, + a, + select, + opt, + input, + marginDiv, + support, + fragment, + body, + testElementParent, + testElement, + testElementStyle, + tds, + events, + eventName, + i, + isSupported; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
    a"; + + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName( "tbody" ).length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName( "link" ).length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains it's value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + div.innerHTML = ""; + + // Figure out if the W3C box model works as expected + div.style.width = div.style.paddingLeft = "1px"; + + body = document.getElementsByTagName( "body" )[ 0 ]; + // We use our own, invisible, body unless the body is already present + // in which case we use a div (#9239) + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0, + background: "none" + }; + if ( body ) { + jQuery.extend( testElementStyle, { + position: "absolute", + left: "-1000px", + top: "-1000px" + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
    "; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.innerHTML = "
    t
    "; + tds = div.getElementsByTagName( "td" ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Remove the body element we added + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + } ) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + // Null connected elements to avoid leaks in IE + testElement = fragment = select = opt = body = marginDiv = div = input = null; + + return support; +})(); + +// Keep track of boxModel +jQuery.boxModel = jQuery.support.boxModel; + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([a-z])([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && (cache[ id ] && !cache[ id ][ internalKey ]))) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + + // Support interoperable removal of hyphenated or camelcased keys + if ( !thisCache[ name ] ) { + name = jQuery.camelCase( name ); + } + + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery.data( elem, deferDataKey, undefined, true ); + if ( defer && + ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && + ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery.data( elem, queueDataKey, undefined, true ) && + !jQuery.data( elem, markDataKey, undefined, true ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.resolve(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = (type || "fx") + "mark"; + jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); + if ( count ) { + jQuery.data( elem, key, count, true ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + if ( elem ) { + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type, undefined, true ); + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data), true ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + defer; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { + count++; + tmp.done( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + nodeHook, boolHook; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = (value || "").split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return undefined; + } + + var isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attrFix: { + // Always normalize to ensure hook usage + tabindex: "tabIndex" + }, + + attr: function( elem, name, value, pass ) { + var nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Normalize the name if needed + if ( notxml ) { + name = jQuery.attrFix[ name ] || name; + + hooks = jQuery.attrHooks[ name ]; + + if ( !hooks ) { + // Use boolHook for boolean attributes + if ( rboolean.test( name ) ) { + hooks = boolHook; + + // Use nodeHook if available( IE6/7 ) + } else if ( nodeHook ) { + hooks = nodeHook; + } + } + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, name ) { + var propName; + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + jQuery.attr( elem, name, "" ); + elem.removeAttribute( name ); + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { + elem[ propName ] = false; + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return (elem[ name ] = value); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabindex propHook to attrHooks for back-compat +jQuery.attrHooks.tabIndex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode; + return jQuery.prop( elem, name ) === true || ( attrNode = elem.getAttributeNode( name ) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !jQuery.support.getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + // Return undefined if nodeValue is empty string + return ret && ret.nodeValue !== "" ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return (ret.nodeValue = value + ""); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return (elem.style.cssText = "" + value); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); + } + } + }); +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspaces = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Event object or event type + var type = event.type || event, + namespaces = [], + exclusive; + + if ( type.indexOf("!") >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.exclusive = exclusive; + event.namespace = namespaces.join("."); + event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + // triggerHandler() and global events don't bubble or run the default action + if ( onlyHandlers || !elem ) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle a global trigger + if ( !elem ) { + // TODO: Stop taunting the data cache; remove global events and always attach to document + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + return; + } + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + event.target = elem; + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + var cur = elem, + // IE doesn't like method names with a colon (#3533, #8272) + ontype = type.indexOf(":") < 0 ? "on" + type : ""; + + // Fire event on the current element, then bubble up the DOM tree + do { + var handle = jQuery._data( cur, "handle" ); + + event.currentTarget = cur; + if ( handle ) { + handle.apply( cur, data ); + } + + // Trigger an inline bound script + if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + event.result = false; + event.preventDefault(); + } + + // Bubble up to document, then to window + cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; + } while ( cur && !event.isPropagationStopped() ); + + // If nobody prevented the default action, do it now + if ( !event.isDefaultPrevented() ) { + var old, + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction)() check here because IE6/7 fails that test. + // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. + try { + if ( ontype && elem[ type ] ) { + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + jQuery.event.triggered = type; + elem[ type ](); + } + } catch ( ieError ) {} + + if ( old ) { + elem[ ontype ] = old; + } + + jQuery.event.triggered = undefined; + } + } + + return event.result; + }, + + handle: function( event ) { + event = jQuery.event.fix( event || window.event ); + // Snapshot the handlers list since a called handler may add/remove events. + var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), + run_all = !event.exclusive && !event.namespace, + args = Array.prototype.slice.call( arguments, 0 ); + + // Use the fix-ed Event rather than the (read-only) native event + args[0] = event; + event.currentTarget = this; + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Triggered event must 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event. + if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var eventDocument = event.target.ownerDocument || document, + doc = eventDocument.documentElement, + body = eventDocument.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + + // Check if mouse(over|out) are still within the same parent element + var related = event.relatedTarget, + inside = false, + eventType = event.type; + + event.type = event.data; + + if ( related !== this ) { + + if ( related ) { + inside = jQuery.contains( this, related ); + } + + if ( !inside ) { + + jQuery.event.handle.apply( this, arguments ); + + event.type = eventType; + } + } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( !jQuery.nodeName( this, "form" ) ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = jQuery.nodeName( elem, "input" ) ? elem.type : "", + val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( jQuery.nodeName( elem, "select" ) ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); + e.type = fix; + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + + // Make sure not to accidentally match a child element with the same selector + if ( related && jQuery.contains( elem, related ) ) { + related = elem; + } + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( typeof selector === "string" ? + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[ selector ] ) { + matches[ selector ] = POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[ selector ]; + + if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /
    ", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + col: [ 2, "", "
    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + + + */ + +(function() { + this.loggly = function(opts) { + this.user_agent = get_agent(); + this.browser_size = get_size(); + log_methods = {'error': 5, 'warn': 4, 'info': 3, 'debug': 2, 'log': 1}; + if (!opts.url) throw new Error("Please include a Loggly HTTP URL."); + if (!opts.level) { + this.level = log_methods['info']; + } else { + this.level = log_methods[opts.level]; + } + this.log = function(data) { + if (log_methods['log'] == this.level) { + opts.data = data; + janky(opts); + } + }; + this.debug = function(data) { + if (log_methods['debug'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + this.info = function(data) { + if (log_methods['info'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + this.warn = function(data) { + if (log_methods['warn'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + this.error = function(data) { + if (log_methods['error'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + }; + this.janky = function(opts) { + janky._form(function(iframe, form) { + form.setAttribute("action", opts.url); + form.setAttribute("method", "post"); + janky._input(iframe, form, opts.data); + form.submit(); + setTimeout(function(){ + document.body.removeChild(iframe); + }, 2000); + }); + }; + this.janky._form = function(cb) { + var iframe = document.createElement("iframe"); + document.body.appendChild(iframe); + iframe.style.display = "none"; + setTimeout(function() { + var form = iframe.contentWindow.document.createElement("form"); + iframe.contentWindow.document.body.appendChild(form); + cb(iframe, form); + }, 0); + }; + this.janky._input = function(iframe, form, data) { + var inp = iframe.contentWindow.document.createElement("input"); + inp.setAttribute("type", "hidden"); + inp.setAttribute("name", "source"); + inp.value = "castor " + data; + form.appendChild(inp); + }; + this.get_agent = function () { + return navigator.appCodeName + navigator.appName + navigator.appVersion; + }; + this.get_size = function () { + var width = 0; var height = 0; + if( typeof( window.innerWidth ) == 'number' ) { + width = window.innerWidth; height = window.innerHeight; + } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { + width = document.documentElement.clientWidth; height = document.documentElement.clientHeight; + } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { + width = document.body.clientWidth; height = document.body.clientHeight; + } + return {'height': height, 'width': width}; + }; +})(); + + +jsworld={};jsworld.formatIsoDateTime=function(a,b){if(typeof a==="undefined")a=new Date;if(typeof b==="undefined")b=false;var c=jsworld.formatIsoDate(a)+" "+jsworld.formatIsoTime(a);if(b){var d=a.getHours()-a.getUTCHours();var e=Math.abs(d);var f=a.getUTCMinutes();var g=a.getMinutes();if(g!=f&&f<30&&d<0)e--;if(g!=f&&f>30&&d>0)e--;var h;if(g!=f)h=":30";else h=":00";var i;if(e<10)i="0"+e+h;else i=""+e+h;if(d<0)i="-"+i;else i="+"+i;c=c+i}return c};jsworld.formatIsoDate=function(a){if(typeof a==="undefined")a=new Date;var b=a.getFullYear();var c=a.getMonth()+1;var d=a.getDate();return b+"-"+jsworld._zeroPad(c,2)+"-"+jsworld._zeroPad(d,2)};jsworld.formatIsoTime=function(a){if(typeof a==="undefined")a=new Date;var b=a.getHours();var c=a.getMinutes();var d=a.getSeconds();return jsworld._zeroPad(b,2)+":"+jsworld._zeroPad(c,2)+":"+jsworld._zeroPad(d,2)};jsworld.parseIsoDateTime=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)(\d\d)(\d\d)[T ](\d\d)(\d\d)(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d)(\d\d)(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date/time string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);var f=parseInt(b[4],10);var g=parseInt(b[5],10);var h=parseInt(b[6],10);if(d<1||d>12||e<1||e>31||f<0||f>23||g<0||g>59||h<0||h>59)throw"Error: Invalid ISO-8601 date/time value";var i=new Date(c,d-1,e,f,g,h);if(i.getDate()!=e||i.getMonth()+1!=d)throw"Error: Invalid date";return i};jsworld.parseIsoDate=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)(\d\d)(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);if(d<1||d>12||e<1||e>31)throw"Error: Invalid ISO-8601 date value";var f=new Date(c,d-1,e);if(f.getDate()!=e||f.getMonth()+1!=d)throw"Error: Invalid date";return f};jsworld.parseIsoTime=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d):(\d\d):(\d\d)/);if(b===null)b=a.match(/^(\d\d)(\d\d)(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date/time string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);if(c<0||c>23||d<0||d>59||e<0||e>59)throw"Error: Invalid ISO-8601 time value";return new Date(0,0,0,c,d,e)};jsworld._trim=function(a){var b=" \n\r\t\f \u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";for(var c=0;c=0;c--){if(b.indexOf(a.charAt(c))===-1){a=a.substring(0,c+1);break}}return b.indexOf(a.charAt(0))===-1?a:""};jsworld._isNumber=function(a){if(typeof a=="number")return true;if(typeof a!="string")return false;var b=a+"";return/^-?(\d+|\d*\.\d+)$/.test(b)};jsworld._isInteger=function(a){if(typeof a!="number"&&typeof a!="string")return false;var b=a+"";return/^-?\d+$/.test(b)};jsworld._isFloat=function(a){if(typeof a!="number"&&typeof a!="string")return false;var b=a+"";return/^-?\.\d+?$/.test(b)};jsworld._hasOption=function(a,b){if(typeof a!="string"||typeof b!="string")return false;if(b.indexOf(a)!=-1)return true;else return false};jsworld._stringReplaceAll=function(a,b,c){var d;if(b.length==1&&c.length==1){d="";for(var e=0;e0){if(d.length>0)g=parseInt(d.shift(),10);if(isNaN(g))throw"Error: Invalid grouping";if(g==-1){e=a.substring(0,f)+e;break}f-=g;if(f<1){e=a.substring(0,f+g)+e;break}e=c+a.substring(f,f+g)+e}return e};jsworld._formatFractionPart=function(a,b){for(var c=0;a.length0)return a;else throw"Empty or no string"};if(a==null||typeof a!="object")throw"Error: Invalid/missing locale properties";if(typeof a.decimal_point!="string")throw"Error: Invalid/missing decimal_point property";this.decimal_point=a.decimal_point;if(typeof a.thousands_sep!="string")throw"Error: Invalid/missing thousands_sep property";this.thousands_sep=a.thousands_sep;if(typeof a.grouping!="string")throw"Error: Invalid/missing grouping property";this.grouping=a.grouping;if(typeof a.int_curr_symbol!="string")throw"Error: Invalid/missing int_curr_symbol property";if(!/[A-Za-z]{3}.?/.test(a.int_curr_symbol))throw"Error: Invalid int_curr_symbol property";this.int_curr_symbol=a.int_curr_symbol;if(typeof a.currency_symbol!="string")throw"Error: Invalid/missing currency_symbol property";this.currency_symbol=a.currency_symbol;if(typeof a.frac_digits!="number"&&a.frac_digits<0)throw"Error: Invalid/missing frac_digits property";this.frac_digits=a.frac_digits;if(a.mon_decimal_point===null||a.mon_decimal_point==""){if(this.frac_digits>0)throw"Error: Undefined mon_decimal_point property";else a.mon_decimal_point=""}if(typeof a.mon_decimal_point!="string")throw"Error: Invalid/missing mon_decimal_point property";this.mon_decimal_point=a.mon_decimal_point;if(typeof a.mon_thousands_sep!="string")throw"Error: Invalid/missing mon_thousands_sep property";this.mon_thousands_sep=a.mon_thousands_sep;if(typeof a.mon_grouping!="string")throw"Error: Invalid/missing mon_grouping property";this.mon_grouping=a.mon_grouping;if(typeof a.positive_sign!="string")throw"Error: Invalid/missing positive_sign property";this.positive_sign=a.positive_sign;if(typeof a.negative_sign!="string")throw"Error: Invalid/missing negative_sign property";this.negative_sign=a.negative_sign;if(a.p_cs_precedes!==0&&a.p_cs_precedes!==1)throw"Error: Invalid/missing p_cs_precedes property, must be 0 or 1";this.p_cs_precedes=a.p_cs_precedes;if(a.n_cs_precedes!==0&&a.n_cs_precedes!==1)throw"Error: Invalid/missing n_cs_precedes, must be 0 or 1";this.n_cs_precedes=a.n_cs_precedes;if(a.p_sep_by_space!==0&&a.p_sep_by_space!==1&&a.p_sep_by_space!==2)throw"Error: Invalid/missing p_sep_by_space property, must be 0, 1 or 2";this.p_sep_by_space=a.p_sep_by_space;if(a.n_sep_by_space!==0&&a.n_sep_by_space!==1&&a.n_sep_by_space!==2)throw"Error: Invalid/missing n_sep_by_space property, must be 0, 1, or 2";this.n_sep_by_space=a.n_sep_by_space;if(a.p_sign_posn!==0&&a.p_sign_posn!==1&&a.p_sign_posn!==2&&a.p_sign_posn!==3&&a.p_sign_posn!==4)throw"Error: Invalid/missing p_sign_posn property, must be 0, 1, 2, 3 or 4";this.p_sign_posn=a.p_sign_posn;if(a.n_sign_posn!==0&&a.n_sign_posn!==1&&a.n_sign_posn!==2&&a.n_sign_posn!==3&&a.n_sign_posn!==4)throw"Error: Invalid/missing n_sign_posn property, must be 0, 1, 2, 3 or 4";this.n_sign_posn=a.n_sign_posn;if(typeof a.int_frac_digits!="number"&&a.int_frac_digits<0)throw"Error: Invalid/missing int_frac_digits property";this.int_frac_digits=a.int_frac_digits;if(a.int_p_cs_precedes!==0&&a.int_p_cs_precedes!==1)throw"Error: Invalid/missing int_p_cs_precedes property, must be 0 or 1";this.int_p_cs_precedes=a.int_p_cs_precedes;if(a.int_n_cs_precedes!==0&&a.int_n_cs_precedes!==1)throw"Error: Invalid/missing int_n_cs_precedes property, must be 0 or 1";this.int_n_cs_precedes=a.int_n_cs_precedes;if(a.int_p_sep_by_space!==0&&a.int_p_sep_by_space!==1&&a.int_p_sep_by_space!==2)throw"Error: Invalid/missing int_p_sep_by_spacev, must be 0, 1 or 2";this.int_p_sep_by_space=a.int_p_sep_by_space;if(a.int_n_sep_by_space!==0&&a.int_n_sep_by_space!==1&&a.int_n_sep_by_space!==2)throw"Error: Invalid/missing int_n_sep_by_space property, must be 0, 1, or 2";this.int_n_sep_by_space=a.int_n_sep_by_space;if(a.int_p_sign_posn!==0&&a.int_p_sign_posn!==1&&a.int_p_sign_posn!==2&&a.int_p_sign_posn!==3&&a.int_p_sign_posn!==4)throw"Error: Invalid/missing int_p_sign_posn property, must be 0, 1, 2, 3 or 4";this.int_p_sign_posn=a.int_p_sign_posn;if(a.int_n_sign_posn!==0&&a.int_n_sign_posn!==1&&a.int_n_sign_posn!==2&&a.int_n_sign_posn!==3&&a.int_n_sign_posn!==4)throw"Error: Invalid/missing int_n_sign_posn property, must be 0, 1, 2, 3 or 4";this.int_n_sign_posn=a.int_n_sign_posn;if(a==null||typeof a!="object")throw"Error: Invalid/missing time locale properties";try{this.abday=this._parseList(a.abday,7)}catch(b){throw"Error: Invalid abday property: "+b}try{this.day=this._parseList(a.day,7)}catch(b){throw"Error: Invalid day property: "+b}try{this.abmon=this._parseList(a.abmon,12)}catch(b){throw"Error: Invalid abmon property: "+b}try{this.mon=this._parseList(a.mon,12)}catch(b){throw"Error: Invalid mon property: "+b}try{this.d_fmt=this._validateFormatString(a.d_fmt)}catch(b){throw"Error: Invalid d_fmt property: "+b}try{this.t_fmt=this._validateFormatString(a.t_fmt)}catch(b){throw"Error: Invalid t_fmt property: "+b}try{this.d_t_fmt=this._validateFormatString(a.d_t_fmt)}catch(b){throw"Error: Invalid d_t_fmt property: "+b}try{var c=this._parseList(a.am_pm,2);this.am=c[0];this.pm=c[1]}catch(b){this.am="";this.pm=""}this.getAbbreviatedWeekdayName=function(a){if(typeof a=="undefined"||a===null)return this.abday;if(!jsworld._isInteger(a)||a<0||a>6)throw"Error: Invalid weekday argument, must be an integer [0..6]";return this.abday[a]};this.getWeekdayName=function(a){if(typeof a=="undefined"||a===null)return this.day;if(!jsworld._isInteger(a)||a<0||a>6)throw"Error: Invalid weekday argument, must be an integer [0..6]";return this.day[a]};this.getAbbreviatedMonthName=function(a){if(typeof a=="undefined"||a===null)return this.abmon;if(!jsworld._isInteger(a)||a<0||a>11)throw"Error: Invalid month argument, must be an integer [0..11]";return this.abmon[a]};this.getMonthName=function(a){if(typeof a=="undefined"||a===null)return this.mon;if(!jsworld._isInteger(a)||a<0||a>11)throw"Error: Invalid month argument, must be an integer [0..11]";return this.mon[a]};this.getDecimalPoint=function(){return this.decimal_point};this.getCurrencySymbol=function(){return this.currency_symbol};this.getIntCurrencySymbol=function(){return this.int_curr_symbol.substring(0,3)};this.currencySymbolPrecedes=function(){if(this.p_cs_precedes==1)return true;else return false};this.intCurrencySymbolPrecedes=function(){if(this.int_p_cs_precedes==1)return true;else return false};this.getMonetaryDecimalPoint=function(){return this.mon_decimal_point};this.getFractionalDigits=function(){return this.frac_digits};this.getIntFractionalDigits=function(){return this.int_frac_digits}};jsworld.NumericFormatter=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.format=function(a,b){if(typeof a=="string")a=jsworld._trim(a);if(!jsworld._isNumber(a))throw"Error: The input is not a number";var c=parseFloat(a,10);var d=jsworld._getPrecision(b);if(d!=-1)c=Math.round(c*Math.pow(10,d))/Math.pow(10,d);var e=jsworld._splitNumber(String(c));var f;if(c===0)f="0";else f=jsworld._hasOption("^",b)?e.integer:jsworld._formatIntegerPart(e.integer,this.lc.grouping,this.lc.thousands_sep);var g=d!=-1?jsworld._formatFractionPart(e.fraction,d):e.fraction;var h=g.length?f+this.lc.decimal_point+g:f;if(jsworld._hasOption("~",b)||c===0){return h}else{if(jsworld._hasOption("+",b)||c<0){if(c>0)return"+"+h;else if(c<0)return"-"+h;else return h}else{return h}}}};jsworld.DateTimeFormatter=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance.";this.lc=a;this.formatDate=function(a){var b=null;if(typeof a=="string"){try{b=jsworld.parseIsoDate(a)}catch(c){b=jsworld.parseIsoDateTime(a)}}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.d_fmt)};this.formatTime=function(a){var b=null;if(typeof a=="string"){try{b=jsworld.parseIsoTime(a)}catch(c){b=jsworld.parseIsoDateTime(a)}}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.t_fmt)};this.formatDateTime=function(a){var b=null;if(typeof a=="string"){b=jsworld.parseIsoDateTime(a)}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.d_t_fmt)};this._applyFormatting=function(a,b){b=b.replace(/%%/g,"%");b=b.replace(/%a/g,this.lc.abday[a.getDay()]);b=b.replace(/%A/g,this.lc.day[a.getDay()]);b=b.replace(/%b/g,this.lc.abmon[a.getMonth()]);b=b.replace(/%B/g,this.lc.mon[a.getMonth()]);b=b.replace(/%d/g,jsworld._zeroPad(a.getDate(),2));b=b.replace(/%e/g,jsworld._spacePad(a.getDate(),2));b=b.replace(/%F/g,a.getFullYear()+"-"+jsworld._zeroPad(a.getMonth()+1,2)+"-"+jsworld._zeroPad(a.getDate(),2));b=b.replace(/%h/g,this.lc.abmon[a.getMonth()]);b=b.replace(/%H/g,jsworld._zeroPad(a.getHours(),2));b=b.replace(/%I/g,jsworld._zeroPad(this._hours12(a.getHours()),2));b=b.replace(/%k/g,a.getHours());b=b.replace(/%l/g,this._hours12(a.getHours()));b=b.replace(/%m/g,jsworld._zeroPad(a.getMonth()+1,2));b=b.replace(/%n/g,"\n");b=b.replace(/%M/g,jsworld._zeroPad(a.getMinutes(),2));b=b.replace(/%p/g,this._getAmPm(a.getHours()));b=b.replace(/%P/g,this._getAmPm(a.getHours()).toLocaleLowerCase());b=b.replace(/%R/g,jsworld._zeroPad(a.getHours(),2)+":"+jsworld._zeroPad(a.getMinutes(),2));b=b.replace(/%S/g,jsworld._zeroPad(a.getSeconds(),2));b=b.replace(/%T/g,jsworld._zeroPad(a.getHours(),2)+":"+jsworld._zeroPad(a.getMinutes(),2)+":"+jsworld._zeroPad(a.getSeconds(),2));b=b.replace(/%w/g,this.lc.day[a.getDay()]);b=b.replace(/%y/g,(new String(a.getFullYear())).substring(2));b=b.replace(/%Y/g,a.getFullYear());b=b.replace(/%Z/g,"");b=b.replace(/%[a-zA-Z]/g,"");return b};this._hours12=function(a){if(a===0)return 12;else if(a>12)return a-12;else return a};this._getAmPm=function(a){if(a===0||a>12)return this.lc.pm;else return this.lc.am}};jsworld.MonetaryFormatter=function(a,b,c){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.currencyFractionDigits={AFN:0,ALL:0,AMD:0,BHD:3,BIF:0,BYR:0,CLF:0,CLP:0,COP:0,CRC:0,DJF:0,GNF:0,GYD:0,HUF:0,IDR:0,IQD:0,IRR:0,ISK:0,JOD:3,JPY:0,KMF:0,KRW:0,KWD:3,LAK:0,LBP:0,LYD:3,MGA:0,MMK:0,MNT:0,MRO:0,MUR:0,OMR:3,PKR:0,PYG:0,RSD:0,RWF:0,SLL:0,SOS:0,STD:0,SYP:0,TND:3,TWD:0,TZS:0,UGX:0,UZS:0,VND:0,VUV:0,XAF:0,XOF:0,XPF:0,YER:0,ZMK:0};if(typeof b=="string"){this.currencyCode=b.toUpperCase();var d=this.currencyFractionDigits[this.currencyCode];if(typeof d!="number")d=2;this.lc.frac_digits=d;this.lc.int_frac_digits=d}else{this.currencyCode=this.lc.int_curr_symbol.substring(0,3).toUpperCase()}this.intSep=this.lc.int_curr_symbol.charAt(3);if(this.currencyCode==this.lc.int_curr_symbol.substring(0,3)){this.internationalFormatting=false;this.curSym=this.lc.currency_symbol}else{if(typeof c=="string"){this.curSym=c;this.internationalFormatting=false}else{this.internationalFormatting=true}}this.getCurrencySymbol=function(){return this.curSym};this.currencySymbolPrecedes=function(a){if(typeof a=="string"&&a=="i"){if(this.lc.int_p_cs_precedes==1)return true;else return false}else{if(this.internationalFormatting){if(this.lc.int_p_cs_precedes==1)return true;else return false}else{if(this.lc.p_cs_precedes==1)return true;else return false}}};this.getDecimalPoint=function(){return this.lc.mon_decimal_point};this.getFractionalDigits=function(a){if(typeof a=="string"&&a=="i"){return this.lc.int_frac_digits}else{if(this.internationalFormatting)return this.lc.int_frac_digits;else return this.lc.frac_digits}};this.format=function(a,b){var c;if(typeof a=="string"){a=jsworld._trim(a);c=parseFloat(a);if(typeof c!="number"||isNaN(c))throw"Error: Amount string not a number"}else if(typeof a=="number"){c=a}else{throw"Error: Amount not a number"}var d=jsworld._getPrecision(b);if(d==-1){if(this.internationalFormatting||jsworld._hasOption("i",b))d=this.lc.int_frac_digits;else d=this.lc.frac_digits}c=Math.round(c*Math.pow(10,d))/Math.pow(10,d);var e=jsworld._splitNumber(String(c));var f;if(c===0)f="0";else f=jsworld._hasOption("^",b)?e.integer:jsworld._formatIntegerPart(e.integer,this.lc.mon_grouping,this.lc.mon_thousands_sep);var g;if(d==-1){if(this.internationalFormatting||jsworld._hasOption("i",b))g=jsworld._formatFractionPart(e.fraction,this.lc.int_frac_digits);else g=jsworld._formatFractionPart(e.fraction,this.lc.frac_digits)}else{g=jsworld._formatFractionPart(e.fraction,d)}var h;if(this.lc.frac_digits>0||g.length)h=f+this.lc.mon_decimal_point+g;else h=f;if(jsworld._hasOption("~",b)){return h}else{var i=jsworld._hasOption("!",b)?true:false;var j=c<0?"-":"+";if(this.internationalFormatting||jsworld._hasOption("i",b)){if(i)return this._formatAsInternationalCurrencyWithNoSym(j,h);else return this._formatAsInternationalCurrency(j,h)}else{if(i)return this._formatAsLocalCurrencyWithNoSym(j,h);else return this._formatAsLocalCurrency(j,h)}}};this._formatAsLocalCurrency=function(a,b){if(a=="+"){if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return"("+b+this.curSym+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return"("+this.curSym+b+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return"("+b+" "+this.curSym+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return"("+this.curSym+" "+b+")"}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b+" "+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+" "+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+" "+b+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+this.curSym+b}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.curSym+b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.curSym+" "+b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.curSym+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.curSym+b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+" "+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign+" "+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+this.curSym+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.curSym+this.lc.positive_sign+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.curSym+this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.curSym+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.curSym+" "+this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return"("+b+this.curSym+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return"("+this.curSym+b+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return"("+b+" "+this.curSym+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return"("+this.curSym+" "+b+")"}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b+" "+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+" "+b+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+this.curSym+b}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.curSym+b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.curSym+" "+b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.curSym+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.curSym+b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+" "+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign+" "+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+this.curSym+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.curSym+this.lc.negative_sign+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.curSym+this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.curSym+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.curSym+" "+this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsInternationalCurrency=function(a,b){if(a=="+"){if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return"("+b+this.currencyCode+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return"("+this.currencyCode+b+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return"("+b+this.intSep+this.currencyCode+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return"("+this.currencyCode+this.intSep+b+")"}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b+this.intSep+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+this.intSep+b+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.currencyCode+b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.intSep+b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.currencyCode+b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign+this.intSep+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.intSep+this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return"("+b+this.currencyCode+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return"("+this.currencyCode+b+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return"("+b+this.intSep+this.currencyCode+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return"("+this.currencyCode+this.intSep+b+")"}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b+this.intSep+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+this.intSep+b+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.currencyCode+b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.intSep+b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.currencyCode+b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign+this.intSep+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.intSep+this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsLocalCurrencyWithNoSym=function(a,b){if(a=="+"){if(this.lc.p_sign_posn===0){return"("+b+")"}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.n_sign_posn===0){return"("+b+")"}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsInternationalCurrencyWithNoSym=function(a,b){if(a=="+"){if(this.lc.int_p_sign_posn===0){return"("+b+")"}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.int_n_sign_posn===0){return"("+b+")"}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC_MONETARY definition"}};jsworld.NumericParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.parse=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=jsworld._trim(a);b=jsworld._stringReplaceAll(a,this.lc.thousands_sep,"");b=jsworld._stringReplaceAll(b,this.lc.decimal_point,".");if(jsworld._isNumber(b))return parseFloat(b,10);else throw"Parse error: Invalid number string"}};jsworld.DateTimeParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance.";this.lc=a;this.parseTime=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.t_fmt,a);var c=false;if(b.hour!==null&&b.minute!==null&&b.second!==null){c=true}else if(b.hourAmPm!==null&&b.am!==null&&b.minute!==null&&b.second!==null){if(b.am){b.hour=parseInt(b.hourAmPm,10)}else{if(b.hourAmPm==12)b.hour=0;else b.hour=parseInt(b.hourAmPm,10)+12}c=true}if(c)return jsworld._zeroPad(b.hour,2)+":"+jsworld._zeroPad(b.minute,2)+":"+jsworld._zeroPad(b.second,2);else throw"Parse error: Invalid/ambiguous time string"};this.parseDate=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.d_fmt,a);var c=false;if(b.year!==null&&b.month!==null&&b.day!==null){c=true}if(c)return jsworld._zeroPad(b.year,4)+"-"+jsworld._zeroPad(b.month,2)+"-"+jsworld._zeroPad(b.day,2);else throw"Parse error: Invalid date string"};this.parseDateTime=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.d_t_fmt,a);var c=false;var d=false;if(b.hour!==null&&b.minute!==null&&b.second!==null){c=true}else if(b.hourAmPm!==null&&b.am!==null&&b.minute!==null&&b.second!==null){if(b.am){b.hour=parseInt(b.hourAmPm,10)}else{if(b.hourAmPm==12)b.hour=0;else b.hour=parseInt(b.hourAmPm,10)+12}c=true}if(b.year!==null&&b.month!==null&&b.day!==null){d=true}if(d&&c)return jsworld._zeroPad(b.year,4)+"-"+jsworld._zeroPad(b.month,2)+"-"+jsworld._zeroPad(b.day,2)+" "+jsworld._zeroPad(b.hour,2)+":"+jsworld._zeroPad(b.minute,2)+":"+jsworld._zeroPad(b.second,2);else throw"Parse error: Invalid/ambiguous date/time string"};this._extractTokens=function(a,b){var c={year:null,month:null,day:null,hour:null,hourAmPm:null,am:null,minute:null,second:null,weekday:null};while(a.length>0){if(a.charAt(0)=="%"&&a.charAt(1)!=""){var d=a.substring(0,2);if(d=="%%"){b=b.substring(1)}else if(d=="%a"){for(var e=0;e31)throw"Parse error: Unrecognised day of the month (%e)";b=b.substring(f.length)}else if(d=="%F"){if(/^\d\d\d\d/.test(b)){c.year=parseInt(b.substring(0,4),10);b=b.substring(4)}else{throw"Parse error: Unrecognised date (%F)"}if(jsworld._stringStartsWith(b,"-"))b=b.substring(1);else throw"Parse error: Unrecognised date (%F)";if(/^0[1-9]|1[0-2]/.test(b)){c.month=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised date (%F)";if(jsworld._stringStartsWith(b,"-"))b=b.substring(1);else throw"Parse error: Unrecognised date (%F)";if(/^0[1-9]|[1-2][0-9]|3[0-1]/.test(b)){c.day=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised date (%F)"}else if(d=="%H"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised hour (%H)"}else if(d=="%I"){if(/^0[1-9]|1[0-2]/.test(b)){c.hourAmPm=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised hour (%I)"}else if(d=="%k"){var g=b.match(/^(\d{1,2})/);c.hour=parseInt(g,10);if(isNaN(c.hour)||c.hour<0||c.hour>23)throw"Parse error: Unrecognised hour (%k)";b=b.substring(g.length)}else if(d=="%l"){var g=b.match(/^(\d{1,2})/);c.hourAmPm=parseInt(g,10);if(isNaN(c.hourAmPm)||c.hourAmPm<1||c.hourAmPm>12)throw"Parse error: Unrecognised hour (%l)";b=b.substring(g.length)}else if(d=="%m"){if(/^0[1-9]|1[0-2]/.test(b)){c.month=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised month (%m)"}else if(d=="%M"){if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised minute (%M)"}else if(d=="%n"){if(b.charAt(0)=="\n")b=b.substring(1);else throw"Parse error: Unrecognised new line (%n)"}else if(d=="%p"){if(jsworld._stringStartsWith(b,this.lc.am)){c.am=true;b=b.substring(this.lc.am.length)}else if(jsworld._stringStartsWith(b,this.lc.pm)){c.am=false;b=b.substring(this.lc.pm.length)}else throw"Parse error: Unrecognised AM/PM value (%p)"}else if(d=="%P"){if(jsworld._stringStartsWith(b,this.lc.am.toLowerCase())){c.am=true;b=b.substring(this.lc.am.length)}else if(jsworld._stringStartsWith(b,this.lc.pm.toLowerCase())){c.am=false;b=b.substring(this.lc.pm.length)}else throw"Parse error: Unrecognised AM/PM value (%P)"}else if(d=="%R"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%R)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%R)";if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%R)"}else if(d=="%S"){if(/^[0-5][0-9]/.test(b)){c.second=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised second (%S)"}else if(d=="%T"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%T)";if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%T)";if(/^[0-5][0-9]/.test(b)){c.second=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)"}else if(d=="%w"){if(/^\d/.test(b)){c.weekday=parseInt(b.substring(0,1),10);b=b.substring(1)}else throw"Parse error: Unrecognised weekday number (%w)"}else if(d=="%y"){if(/^\d\d/.test(b)){var h=parseInt(b.substring(0,2),10);if(h>50)c.year=1900+h;else c.year=2e3+h;b=b.substring(2)}else throw"Parse error: Unrecognised year (%y)"}else if(d=="%Y"){if(/^\d\d\d\d/.test(b)){c.year=parseInt(b.substring(0,4),10);b=b.substring(4)}else throw"Parse error: Unrecognised year (%Y)"}else if(d=="%Z"){if(a.length===0)break}a=a.substring(2)}else{if(a.charAt(0)!=b.charAt(0))throw'Parse error: Unexpected symbol "'+b.charAt(0)+'" in date/time string';a=a.substring(1);b=b.substring(1)}}return c}};jsworld.MonetaryParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.parse=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._detectCurrencySymbolType(a);var c,d;if(b=="local"){c="local";d=a.replace(this.lc.getCurrencySymbol(),"")}else if(b=="int"){c="int";d=a.replace(this.lc.getIntCurrencySymbol(),"")}else if(b=="none"){c="local";d=a}else throw"Parse error: Internal assert failure";d=jsworld._stringReplaceAll(d,this.lc.mon_thousands_sep,"");d=d.replace(this.lc.mon_decimal_point,".");d=d.replace(/\s*/g,"");d=this._removeLocalNonNegativeSign(d,c);d=this._normaliseNegativeSign(d,c);if(jsworld._isNumber(d))return parseFloat(d,10);else throw"Parse error: Invalid currency amount string"};this._detectCurrencySymbolType=function(a){if(this.lc.getCurrencySymbol().length>this.lc.getIntCurrencySymbol().length){if(a.indexOf(this.lc.getCurrencySymbol())!=-1)return"local";else if(a.indexOf(this.lc.getIntCurrencySymbol())!=-1)return"int";else return"none"}else{if(a.indexOf(this.lc.getIntCurrencySymbol())!=-1)return"int";else if(a.indexOf(this.lc.getCurrencySymbol())!=-1)return"local";else return"none"}};this._removeLocalNonNegativeSign=function(a,b){a=a.replace(this.lc.positive_sign,"");if((b=="local"&&this.lc.p_sign_posn===0||b=="int"&&this.lc.int_p_sign_posn===0)&&/\(\d+\.?\d*\)/.test(a)){a=a.replace("(","");a=a.replace(")","")}return a};this._normaliseNegativeSign=function(a,b){a=a.replace(this.lc.negative_sign,"-");if(b=="local"&&this.lc.n_sign_posn===0||b=="int"&&this.lc.int_n_sign_posn===0){if(/^\(\d+\.?\d*\)$/.test(a)){a=a.replace("(","");a=a.replace(")","");return"-"+a}}if(b=="local"&&this.lc.n_sign_posn==2||b=="int"&&this.lc.int_n_sign_posn==2){if(/^\d+\.?\d*-$/.test(a)){a=a.replace("-","");return"-"+a}}if(b=="local"&&this.lc.n_cs_precedes===0&&this.lc.n_sign_posn==3||b=="local"&&this.lc.n_cs_precedes===0&&this.lc.n_sign_posn==4||b=="int"&&this.lc.int_n_cs_precedes===0&&this.lc.int_n_sign_posn==3||b=="int"&&this.lc.int_n_cs_precedes===0&&this.lc.int_n_sign_posn==4){if(/^\d+\.?\d*-$/.test(a)){a=a.replace("-","");return"-"+a}}return a}} + + +if(typeof POSIX_LC == "undefined") var POSIX_LC = {}; + +POSIX_LC.en_US = { + "decimal_point" : ".", + "thousands_sep" : ",", + "grouping" : "3", + "abday" : ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"], + "day" : ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], + "abmon" : ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], + "mon" : ["January","February","March","April","May","June","July","August","September","October","November","December"], + "d_fmt" : "%m/%e/%y", + "t_fmt" : "%I:%M:%S %p", + "d_t_fmt" : "%B %e, %Y %I:%M:%S %p %Z", + "am_pm" : ["AM","PM"], + "int_curr_symbol" : "USD ", + "currency_symbol" : "\u0024", + "mon_decimal_point" : ".", + "mon_thousands_sep" : ",", + "mon_grouping" : "3", + "positive_sign" : "", + "negative_sign" : "-", + "int_frac_digits" : 2, + "frac_digits" : 2, + "p_cs_precedes" : 1, + "n_cs_precedes" : 1, + "p_sep_by_space" : 0, + "n_sep_by_space" : 0, + "p_sign_posn" : 1, + "n_sign_posn" : 1, + "int_p_cs_precedes" : 1, + "int_n_cs_precedes" : 1, + "int_p_sep_by_space" : 0, + "int_n_sep_by_space" : 0, + "int_p_sign_posn" : 1, + "int_n_sign_posn" : 1 +} + +if(typeof POSIX_LC == "undefined") var POSIX_LC = {}; + +POSIX_LC.fr_FR = { + "decimal_point" : ",", + "thousands_sep" : "\u00a0", + "grouping" : "3", + "abday" : ["dim.","lun.","mar.", + "mer.","jeu.","ven.", + "sam."], + "day" : ["dimanche","lundi","mardi", + "mercredi","jeudi","vendredi", + "samedi"], + "abmon" : ["janv.","f\u00e9vr.","mars", + "avr.","mai","juin", + "juil.","ao\u00fbt","sept.", + "oct.","nov.","d\u00e9c."], + "mon" : ["janvier","f\u00e9vrier","mars", + "avril","mai","juin", + "juillet","ao\u00fbt","septembre", + "octobre","novembre","d\u00e9cembre"], + "d_fmt" : "%d/%m/%y", + "t_fmt" : "%H:%M:%S", + "d_t_fmt" : "%e %B %Y %H:%M:%S %Z", + "am_pm" : ["AM","PM"], + "int_curr_symbol" : "EUR ", + "currency_symbol" : "\u20ac", + "mon_decimal_point" : ",", + "mon_thousands_sep" : "\u00a0", + "mon_grouping" : "3", + "positive_sign" : "", + "negative_sign" : "-", + "int_frac_digits" : 2, + "frac_digits" : 2, + "p_cs_precedes" : 0, + "n_cs_precedes" : 0, + "p_sep_by_space" : 1, + "n_sep_by_space" : 1, + "p_sign_posn" : 1, + "n_sign_posn" : 1, + "int_p_cs_precedes" : 0, + "int_n_cs_precedes" : 0, + "int_p_sep_by_space" : 1, + "int_n_sep_by_space" : 1, + "int_p_sign_posn" : 1, + "int_n_sign_posn" : 1 +}; + +/** https://github.com/csnover/js-iso8601 */(function(n,f){var u=n.parse,c=[1,4,5,6,7,10,11];n.parse=function(t){var i,o,a=0;if(o=/^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(t)){for(var v=0,r;r=c[v];++v)o[r]=+o[r]||0;o[2]=(+o[2]||1)-1,o[3]=+o[3]||1,o[8]!=="Z"&&o[9]!==f&&(a=o[10]*60+o[11],o[9]==="+"&&(a=0-a)),i=n.UTC(o[1],o[2],o[3],o[4],o[5]+a,o[6],o[7])}else i=u?u(t):NaN;return i}})(Date) + +/*! + * geo-location-javascript v0.4.3 + * http://code.google.com/p/geo-location-javascript/ + * + * Copyright (c) 2009 Stan Wiechers + * Licensed under the MIT licenses. + * + * Revision: $Rev: 68 $: + * Author: $Author: whoisstan $: + * Date: $Date: 2010-02-15 13:42:19 +0100 (Mon, 15 Feb 2010) $: + */ +var geo_position_js=function() { + + var pub = {}; + var provider=null; + + pub.getCurrentPosition = function(successCallback,errorCallback,options) + { + provider.getCurrentPosition(successCallback, errorCallback,options); + } + + pub.init = function() + { + try + { + if (typeof(geo_position_js_simulator)!="undefined") + { + provider=geo_position_js_simulator; + } + else if (typeof(bondi)!="undefined" && typeof(bondi.geolocation)!="undefined") + { + provider=bondi.geolocation; + } + else if (typeof(navigator.geolocation)!="undefined") + { + provider=navigator.geolocation; + pub.getCurrentPosition = function(successCallback, errorCallback, options) + { + function _successCallback(p) + { + //for mozilla geode,it returns the coordinates slightly differently + if(typeof(p.latitude)!="undefined") + { + successCallback({timestamp:p.timestamp, coords: {latitude:p.latitude,longitude:p.longitude}}); + } + else + { + successCallback(p); + } + } + provider.getCurrentPosition(_successCallback,errorCallback,options); + } + } + else if(typeof(window.google)!="undefined" && typeof(google.gears)!="undefined") + { + provider=google.gears.factory.create('beta.geolocation'); + } + else if ( typeof(Mojo) !="undefined" && typeof(Mojo.Service.Request)!="Mojo.Service.Request") + { + provider=true; + pub.getCurrentPosition = function(successCallback, errorCallback, options) + { + + parameters={}; + if(options) + { + //http://developer.palm.com/index.php?option=com_content&view=article&id=1673#GPS-getCurrentPosition + if (options.enableHighAccuracy && options.enableHighAccuracy==true) + { + parameters.accuracy=1; + } + if (options.maximumAge) + { + parameters.maximumAge=options.maximumAge; + } + if (options.responseTime) + { + if(options.responseTime<5) + { + parameters.responseTime=1; + } + else if (options.responseTime<20) + { + parameters.responseTime=2; + } + else + { + parameters.timeout=3; + } + } + } + + + r=new Mojo.Service.Request('palm://com.palm.location', { + method:"getCurrentPosition", + parameters:parameters, + onSuccess: function(p){successCallback({timestamp:p.timestamp, coords: {latitude:p.latitude, longitude:p.longitude,heading:p.heading}});}, + onFailure: function(e){ + if (e.errorCode==1) + { + errorCallback({code:3,message:"Timeout"}); + } + else if (e.errorCode==2) + { + errorCallback({code:2,message:"Position Unavailable"}); + } + else + { + errorCallback({code:0,message:"Unknown Error: webOS-code"+errorCode}); + } + } + }); + } + + } + else if (typeof(device)!="undefined" && typeof(device.getServiceObject)!="undefined") + { + provider=device.getServiceObject("Service.Location", "ILocation"); + + //override default method implementation + pub.getCurrentPosition = function(successCallback, errorCallback, options) + { + function callback(transId, eventCode, result) { + if (eventCode == 4) + { + errorCallback({message:"Position unavailable", code:2}); + } + else + { + //no timestamp of location given? + successCallback({timestamp:null, coords: {latitude:result.ReturnValue.Latitude, longitude:result.ReturnValue.Longitude, altitude:result.ReturnValue.Altitude,heading:result.ReturnValue.Heading}}); + } + } + //location criteria + var criteria = new Object(); + criteria.LocationInformationClass = "BasicLocationInformation"; + //make the call + provider.ILocation.GetLocation(criteria,callback); + } + } + } + catch (e){ + alert("error="+e); + if(typeof(console)!="undefined") + { + console.log(e); + } + return false; + } + return provider!=null; + } + + + return pub; +}(); +// Couldn't get unminified version to work , go here for docs => https://github.com/iamnoah/writeCapture +(function(E,a){var j=a.document;function A(Q){var Z=j.createElement("div");j.body.insertBefore(Z,null);E.replaceWith(Z,'\n
    \n
    \n
    \n \n\n
    \n
    \n \n
    \n

    '); + __out.push(__sanitize(t('Invite Link'))); + __out.push(' '); + __out.push(__sanitize(USER.referral_url)); + __out.push('

    \n\n \n\n
    \n\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/login": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + __out.push('
    \n\t

    '); + __out.push(__sanitize(t('Sign In'))); + __out.push('

    \n\t
    \n\t\t
    \n\n\t\t\t
    \n\t\t\t\t\n\t\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t
    \n\n\t\t\t
    \n\n\t\t\t
    \n\t\t\t\t\n\t\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t
    \n\n\t\t\t
    \n\n
    \n\n

    '); + __out.push(__sanitize(t('Forgot Password?'))); + __out.push('

    \n\n\t\t
    \n\t
    \n
    \n\n
    \n
    \n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/modules/credit_card": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var printCard; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + if (this.cards === "new") { + __out.push('\n
    \n
    \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n \n
    \n
    \n
    \n'); + } else { + __out.push('\n '); + printCard = __bind(function(card, index) { + var exp, style; + __out.push('\n
    \n '); + style = "background-position:-173px"; + __out.push('\n '); + if (card.get("card_type") === "Visa") { + style = "background-position:0px"; + } + __out.push('\n '); + if (card.get("card_type") === "MasterCard") { + style = "background-position:-42px"; + } + __out.push('\n '); + if (card.get("card_type") === "American Express") { + style = "background-position:-130px"; + } + __out.push('\n '); + if (card.get("card_type") === "Discover Card") { + style = "background-position:-85px"; + } + __out.push('\n
    \n
    \n ****'); + __out.push(__sanitize(card.get("card_number"))); + __out.push('\n \n '); + if (card.get("card_expiration")) { + __out.push('\n '); + __out.push(__sanitize(t('Expiry'))); + __out.push('\n '); + exp = card.get('card_expiration').split('-'); + __out.push('\n '); + __out.push(__sanitize("" + exp[0] + "-" + exp[1])); + __out.push('\n '); + } + __out.push('\n \n \n \n '); + if (card.get("default")) { + __out.push('\n ('); + __out.push(__sanitize(t('default card'))); + __out.push(')\n '); + } + __out.push('\n '); + if (this.cards.length > 1 && !card.get("default")) { + __out.push('\n '); + __out.push(__sanitize(t('make default'))); + __out.push('\n '); + } + __out.push('\n \n '); + __out.push(__sanitize(t('Edit'))); + __out.push('\n \n '); + if (this.cards.length > 1) { + __out.push('\n '); + __out.push(__sanitize(t('Delete'))); + __out.push('\n '); + } + __out.push('\n
    \n '); + _.each(this.cards.models, printCard); + __out.push('\n
    \n
    \n\n'); + } + __out.push('\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/modules/sub_header": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + __out.push('
    \n
    '); + __out.push(__sanitize(this.heading)); + __out.push('
    \n
    \n '); + if (window.USER.first_name) { + __out.push('\n '); + __out.push(__sanitize(t('Hello Greeting', { + name: USER.first_name + }))); + __out.push('\n '); + } + __out.push('\n
    \n
    \n
    \n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/promotions": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var promo, _i, _len, _ref; + __out.push(require('templates/clients/modules/sub_header').call(this, { + heading: t("Promotions") + })); + __out.push('\n\n
    \n
    \n
    \n \n \n
    \n
    \n \n \n\n \n
    \n '); + if (this.promos.length > 0) { + __out.push('\n
    \n

    '); + __out.push(__sanitize(t('Your Available Promotions'))); + __out.push('

    \n \n \n\n \n \n \n \n \n \n \n \n '); + _ref = this.promos; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + promo = _ref[_i]; + __out.push('\n \n \n \n \n \n \n '); + } + __out.push('\n \n
    '); + __out.push(__sanitize(t('Code'))); + __out.push(''); + __out.push(__sanitize(t('Details'))); + __out.push(''); + __out.push(__sanitize(t('Starts'))); + __out.push(''); + __out.push(__sanitize(t('Expires'))); + __out.push('
    '); + __out.push(__sanitize(promo.code)); + __out.push(''); + __out.push(__sanitize(promo.description)); + __out.push(''); + __out.push(__sanitize(app.helpers.formatDate(promo.starts_at, true, "America/Los_Angeles"))); + __out.push(''); + __out.push(__sanitize(app.helpers.formatDate(promo.ends_at, true, "America/Los_Angeles"))); + __out.push('
    \n
    \n '); + } else { + __out.push('\n\n

    '); + __out.push(__sanitize(t('No Active Promotions'))); + __out.push('

    \n '); + } + __out.push('\n\n
    \n
    \n
    \n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/request": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var showFavoriteLocation; + showFavoriteLocation = function(location, index) { + var alphabet; + __out.push('\n '); + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + __out.push('\n
    \n '); + __out.push(__sanitize(location.nickname)); + return __out.push('\n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n

    '); + __out.push(__sanitize(t('Driver Name:'))); + __out.push('

    \n

    \n
    \n

    '); + __out.push(__sanitize(t('Driver #:'))); + __out.push('

    \n

    \n
    \n

    '); + __out.push(__sanitize(t('Pickup Address:'))); + __out.push('

    \n

    \n
    \n ');
+      __out.push(__sanitize(t('Add to Favorite Locations')));
+      __out.push('\n
    \n
    \n

    \n '); + __out.push(__sanitize(t('Nickname:'))); + __out.push('\n \n \n \n \n
    \n
    \n
    \n
    \n

    '); + __out.push(__sanitize(t('Your last trip'))); + __out.push('

    \n
    \n \n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n \n \n
    \n \n
    \n \n
    \n \n
    \n \n\n
    \n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/shared/menu": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + __out.push('\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "translations/en": function(exports, require, module) {(function() { + exports.translations = { + "Uber": "Uber", + "Sign Up": "Sign Up", + "Ride Request": "Ride Request", + "Invite Friends": "Invite Friends", + "Promotions": "Promotions", + "Billing": "Billing", + "Settings": "Settings", + "Forgot Password?": "Forgot Password?", + "Password Recovery": "Password Recovery", + "Login": "Login", + "Trip Detail": "Trip Detail", + "Password Reset": "Password Reset", + "Confirm Email": "Confirm Email", + "Request Ride": "Request Ride", + "Credit Card Number": "Credit Card Number", + "month": "month", + "01-Jan": "01-Jan", + "02-Feb": "02-Feb", + "03-Mar": "03-Mar", + "04-Apr": "04-Apr", + "05-May": "05-May", + "06-Jun": "06-Jun", + "07-Jul": "07-Jul", + "08-Aug": "08-Aug", + "09-Sep": "09-Sep", + "10-Oct": "10-Oct", + "11-Nov": "11-Nov", + "12-Dec": "12-Dec", + "year": "year", + "CVV": "CVV", + "Category": "Category", + "personal": "personal", + "business": "business", + "Default Credit Card": "Default Credit Card", + "Add Credit Card": "Add Credit Card", + "Expiry": "Expiry", + "default card": "default card", + "make default": "make default", + "Edit": "Edit", + "Delete": "Delete", + "Expiry Month": "Expiry Month", + "Expiry Year": "Expiry Year", + "Unable to Verify Card": "Unable to verify card at this time. Please try again later.", + "Credit Card Update Succeeded": "Your card has been successfully updated!", + "Credit Card Update Failed": "We couldn't save your changes. Please try again in a few minutes.", + "Credit Card Delete Succeeded": "Your card has been deleted!", + "Credit Card Delete Failed": "We were unable to delete your card. Please try again later.", + "Credit Card Update Category Succeeded": "Successfully changed card category!", + "Credit Card Update Category Failed": "We couldn't change your card category. Please try again in a few minutes.", + "Credit Card Update Default Succeeded": "Successfully changed default card!", + "Credit Card Update Default Failed": "We couldn't change your default card. Please try again in a few minutes.", + "Hello Greeting": "Hello, <%= name %>", + "Card Ending in": "Card Ending in", + "Trip Map": "Trip Map", + "Amount": "Amount: <%= amount %>", + "Last Attempt to Bill": "Last Attempt to Bill: <%= date %>", + "Charge": "Charge", + "Uber Credit Balance Note": "Your account has an UberCredit balance of <%= amount %>. When billing for trips, we'll deplete your UberCredit balance before applying charges to your credit card.", + "Please Add Credit Card": "Please add a credit card to bill your outstanding charges.", + "Credit Cards": "Credit Cards", + "add a new credit card": "add a new credit card", + "Account Balance": "Account Balance", + "Arrears": "Arrears", + "Billing Succeeded": "Your card was successfully billed.", + "Confirm Email Succeeded": "Successfully confirmed email token, redirecting to log in page...", + "Confirm Email Failed": "Unable to confirm email. Please contact support@uber.com if this problem persists.", + "Email Already Confirmed": "Your email address has already been confirmed, redirecting to log in page...", + "Credit Card Added": "Credit Card Added", + "No Credit Card": "No Credit Card", + "Mobile Number Confirmed": "Mobile Number Confirmed", + "No Confirmed Mobile": "No Confirmed Mobile", + "E-mail Address Confirmed": "E-mail Address Confirmed", + "No Confirmed E-mail": "No Confirmed E-mail", + 'Reply to sign up text': 'Reply "GO" to the text message you received at sign up.', + "Resend text message": "Resend text message", + "Click sign up link": "Click the link in the email you received at sign up.", + "Resend email": "Resend email", + "Add a credit card to ride": "Add a credit card and you'll be ready to ride Uber.", + "Your Most Recent Trip": "Your Most Recent Trip", + "details": "details", + "Your Trip History ": "Your Trip History ", + "Status": "Status", + "Here's how it works:": "Here's how it works:", + "Show all trips": "Show all trips", + "Set your location:": "Set your location:", + "App search for address": "iPhone/Android app: fix the pin or search for an address", + "SMS text address": "SMS: text your address to UBRCAB (827222)", + "Confirm pickup request": "Confirm your pickup request", + "Uber sends ETA": "Uber will send you an ETA (usually within 5-10 minutes)", + "Car arrives": "When your car is arriving, Uber will inform you again.", + "Ride to destination": "Hop in the car and tell the driver your destination.", + "Thank your driver": "That’s it! Please thank your driver but remember that your tip is included and no cash is necessary.", + "Trip started here": "Trip started here", + "Trip ended here": "Trip ended here", + "Sending Email": "Sending email...", + "Resend Email Succeeded": "We just sent the email. Please click on the confirmation link you recieve.", + "Resend Email Failed": "There was an error sending the email. Please contact support if the problem persists.", + "Resend Text Succeeded": 'We just sent the text message. Please reply "GO" to the message you recieve. It may take a few minutes for the message to reach you phone.', + "Resend Text Failed": "There was an error sending the text message. Please contact support if the problem persists.", + "Password Reset Error": "There was an error processing your password reset request.", + "New Password": "New Password", + "Forgot Password": "Forgot Password", + "Forgot Password Error": "Your email address could not be found. Please make sure to use the same email address you used when you signed up.", + "Forgot Password Success": "Please check your email for a link to reset your password.", + "Forgot Password Enter Email": 'Enter your email address and Uber will send you a link to reset your password. If you remember your password, you can sign in here.', + "Invite friends": "Invite friends", + "Give $ Get $": "Give $10, Get $10", + "Give $ Get $ Description": "Every friend you invite to Uber gets $10 of Uber credit. After someone you’ve invited takes his/her first ride, you get $10 of Uber credits too!", + "What are you waiting for?": "So, what are you waiting for? Invite away!", + "Tweet": "Tweet", + "Invite Link": "Email or IM this link to your friends:", + "Email Address": "Email Address", + "Reset Password": "Reset Password", + "Enter Promotion Code": "If you have a promotion code, enter it here:", + "Your Active Promotions": "Your Active Promotions", + "Code": "Code", + "Details": "Details", + "Trips Remaining": "Trips Remaining", + "Expires": "Expires", + "No Active Promotions": "There are no active promotions on your account.", + "Your Available Promotions": "Your Available Promotions", + "Where do you want us to pick you up?": "Where do you want us to pick you up?", + "Address to search": "Address to search", + "Search": "Search", + "Driver Name:": "Driver Name:", + "Driver #:": "Driver #:", + "Pickup Address:": "Pickup Address:", + "Add to Favorite Locations": "Add to Favorite Locations", + "Star": "Star", + "Nickname:": "Nickname:", + "Add": "Add", + "Your last trip": "Your last trip", + "Please rate your driver:": "Please rate your driver:", + "Comments: (optional)": "Comments: (optional)", + "Rate Trip": "Rate Trip", + "Pickup time:": "Pickup time:", + "Miles:": "Miles:", + "Trip time:": "Trip time:", + "Fare:": "Fare:", + "Favorite Locations": "Favorite Locations", + "Search Results": "Search Results", + "You have no favorite locations saved.": "You have no favorite locations saved.", + "Loading...": "Loading...", + "Request Pickup": "Request Pickup", + "Cancel Pickup": "Cancel Pickup", + "Requesting Closest Driver": "Requesting the closest driver to pick you up...", + "En Route": "You are currently en route...", + "Rate Last Trip": "Please rate your trip to make another request", + "Rate Before Submitting": "Please rate your trip before submitting the form", + "Address too short": "Address too short", + "or did you mean": "or did you mean", + "Search Address Failed": "Unable to find the given address. Please enter another address close to your location.", + "Sending pickup request...": "Sending pickup request...", + "Cancel Request Prompt": "Are you sure you want to cancel your request?", + "Cancel Request Arrived Prompt": 'Are you sure you want to cancel your request? Your driver has arrived so there is a $10 cancellation fee. It may help to call your driver now', + "Favorite Location Nickname Length Error": "Nickname has to be atleast 3 characters", + "Favorite Location Save Succeeded": "Location Saved!", + "Favorite Location Save Failed": "Unable to save your location. Please try again later.", + "Favorite Location Title": "Favorite Location <%= id %>", + "Search Location Title": "Search Location <%= id %>", + "ETA Message": "ETA: Around <%= minutes %> Minutes", + "Nearest Cab Message": "The closest driver is approximately <%= minutes %> minute(s) away", + "Arrival ETA Message": "Your Uber will arrive in about <%= minutes %> minute(s)", + "Arriving Now Message": "Your Uber is arriving now...", + "Rating Driver Failed": "Unable to contact server. Please try again later or email support if this issue persists.", + "Account Information": "Account Information", + "Mobile Phone Information": "Mobile Phone Information", + "settings": "settings", + "Information": "Information", + "Picture": "Picture", + "Change password": "Change password", + "Your current Picture": "Your current Picture", + "Your Favorite Locations": "Your Favorite Locations", + "You have no favorite locations saved.": "You have no favorite locations saved.", + "Purpose of Mobile": "We send text messages to your mobile phone to tell you when your driver is arriving. You can also request trips using text messages.", + "Country": "Country", + "Mobile Number": "Mobile Number", + "Submit": "Submit", + "Favorite Location": "Favorite Location", + "No Approximate Address": "Could not find an approximate address", + "Address:": "Address:", + "Information Update Succeeded": "Your information has been updated!", + "Information Update Failed": "We couldn't update your information. Please try again in few minutes or contact support if the problem persists.", + "Location Delete Succeeded": "Location deleted!", + "Location Delete Failed": "We were unable to delete your favorite location. Please try again later or contact support of the issue persists.", + "Location Edit Succeeded": "Changes Saved!", + "Location Edit Failed": "We couldn't save your changes. Please try again in a few minutes.", + "Picture Update Succeeded": "Your picture has been updated!", + "Picture Update Failed": "We couldn't change your picture. Please try again in a few minutes.", + "Personal Information": "Personal Information", + "Mobile Phone Number": "Mobile Phone Number", + "Payment Information": "Payment Information", + "Purpose of Credit Card": "We keep your credit card on file so that your trip go as fast as possible. You will not be charged until you take a trip.", + "Your card will not be charged until you take a trip.": "Your card will not be charged until you take a trip.", + "Credit Card Number": "Credit Card Number", + "Expiration Date": "Expiration Date", + "Promotion Code": "Promotion Code", + "Enter Promo Here": "If you have a code for a promotion, invitation or group deal, you can enter it here.", + "Promotion Code Input Label": "Promotion, Invite or Groupon Code (optional)", + "Terms and Conditions": "Terms and Conditions", + "HELP": "HELP", + "STOP": "STOP", + "Legal Information": "Legal Information", + "Sign Up Agreement": "By signing up, I agree to the Uber <%= terms_link %> and <%= privacy_link %> and understand that Uber is a request tool, not a transportation carrier.", + "Sign Up Agreement Error": "You must agree to the Uber Terms and Conditions and Privacy Policy to continue.", + "Message and Data Rates Disclosure": "Message and Data Rates May Apply. Reply <%= help_string %> to 827-222 for help. Reply <%= stop_string %> to 827-222 to stop texts. For additional assistance, visit support.uber.com or call (866) 576-1039. Supported Carriers: AT&T, Sprint, Verizon, and T-Mobile.", + "I Agree": "I agree to the Terms & Conditions and Privacy Policy", + "Security Code": "Security Code", + "Type of Card": "Type of Card", + "Personal": "Personal", + "Business": "Business", + "Code": "Code", + "Zip or Postal Code": "Zip or Postal Code", + "Your Trip": "Your Trip", + "Trip Info": "Trip Info", + "Request a fare review": "Request a fare review", + "Fare Review Submitted": "Your fare review has been submitted. We'll get back to you soon about your request. Sorry for any inconvenience this may have caused!", + "Fair Price Consideration": "We're committed to delivering Uber service at a fair price. Before requesting a fare review, please consider:", + "Your Fare Calculation": "Your Fare Calculation", + "Charges": "Charges", + "Discounts": "Discounts", + "Total Charge": "Total Charge", + "Uber pricing information": "Uber pricing information", + "Uber Pricing Information Message": "<%= learn_link %> is published on our website.", + "GPS Point Capture Disclosure": "Due to a finite number of GPS point captures, corners on your trip map may appear cut off or rounded. These minor inaccuracies result in a shorter measured distance, which always results in a cheaper trip.", + "Fare Review Note": "Please elaborate on why this trip requires a fare review. Your comments below will help us better establish the correct price for your trip:", + "Fare Review Error": "There was an error submitting the review. Please ensure that you have a message.", + "Sign In": "Sign In" + }; +}).call(this); +}, "translations/fr": function(exports, require, module) {(function() { + exports.translations = { + "Uber": "Uber", + "Sign Up": "Inscription", + "Ride Request": "Passer une Commande", + "Invite Friends": "Inviter vos Amis", + "Promotions": "Promotions", + "Billing": "Paiement", + "Settings": "Paramètres", + "Forgot Password?": "Mot de passe oublié ?", + "Password Recovery": "Récupération du mot de passe", + "Login": "Connexion", + "Trip Detail": "Détail de la Course", + "Password Reset": "Réinitialisation du mot de passe", + "Confirm Email": "Confirmation de l’e-mail", + "Request Ride": "Passer une Commande", + "Credit Card Number": "Numéro de Carte de Crédit", + "month": "mois", + "01-Jan": "01-Jan", + "02-Feb": "02-Fév", + "03-Mar": "03-Mar", + "04-Apr": "04-Avr", + "05-May": "05-Mai", + "06-Jun": "06-Juin", + "07-Jul": "07-Jui", + "08-Aug": "08-Aoû", + "09-Sep": "09-Sep", + "10-Oct": "10-Oct", + "11-Nov": "11-Nov", + "12-Dec": "12-Déc", + "year": "année", + "CVV": "Code de Sécurité", + "Category": "Type", + "personal": "personnel", + "business": "entreprise", + "Default Credit Card": "Carte par Défaut", + "Add Credit Card": "Ajouter une Carte", + "Expiry": "Expire", + "default card": "carte par défaut", + "make default": "choisir par défaut", + "Edit": "Modifier", + "Delete": "Supprimer", + "Expiry Month": "Mois d’Expiration", + "Expiry Year": "Année d’Expiration", + "Unable to Verify Card": "Impossible de vérifier la carte pour le moment. Merci de réessayer un peu plus tard.", + "Credit Card Update Succeeded": "Votre carte a été mise à jour avec succès !", + "Credit Card Update Failed": "Nous ne pouvons enregistrer vos changements. Merci de réessayer dans quelques minutes.", + "Credit Card Delete Succeeded": "Votre carte a été supprimée !", + "Credit Card Delete Failed": "Nous n’avons pas été en mesure de supprimer votre carte. Merci de réessayer plus tard.", + "Credit Card Update Category Succeeded": "Changement de catégorie de carte réussi !", + "Credit Card Update Category Failed": "Nous ne pouvons pas changer la catégorie de votre carte. Merci de réessayer dans quelques minutes.", + "Credit Card Update Default Succeeded": "Carte par défaut changée avec succès !", + "Credit Card Update Default Failed": "Nous ne pouvons pas changer votre carte par défaut. Merci de réessayer dans quelques minutes.", + "Hello Greeting": "Bonjour, <%= name %>", + "Card Ending in": "La carte expire dans", + "Trip Map": "Carte des Courses", + "Amount": "Montant: <%= amount %>", + "Last Attempt to Bill": "Dernière tentative de prélèvement : <%= date %>", + "Charge": "Débit", + "Uber Credit Balance Note": "Votre compte a un solde de <%= amount %> UberCredits. Lorsque nous facturons des courses, nous réduirons votre solde d’UberCredits avant de prélever votre carte de crédit.", + "Please Add Credit Card": "Merci d’ajouter une carte de crédit pour que nous puissions vous facturer.", + "Credit Cards": "Cartes de crédit", + "add a new credit card": "Ajouter une nouvelle carte de crédit", + "Account Balance": "Solde du compte", + "Arrears": "Arriérés", + "Billing Succeeded": "Votre carte a été correctement débitée.", + "Confirm Email Succeeded": "L’adresse e-mail a bien été validée, vous êtes redirigé vers le tableau de bord...", + "Confirm Email Failed": "Impossible de confirmer l’adresse e-mail. Merci de contacter support@uber.com si le problème persiste.", + "Credit Card Added": "Carte de crédit ajoutée", + "No Credit Card": "Pas de carte de crédit", + "Mobile Number Confirmed": "Numéro de téléphone confirmé", + "No Confirmed Mobile": "Pas de numéro de téléphone confirmé", + "E-mail Address Confirmed": "Adresse e-mail confirmée", + "No Confirmed E-mail": "Pas d’adresse e-mail confirmée", + 'Reply to sign up text': 'Répondre "GO" au SMS que vous avez reçu à l’inscription.', + "Resend text message": "Renvoyer le SMS", + "Click sign up link": "Cliquez sur le lien contenu dans l’e-mail reçu à l’inscription.", + "Resend email": "Renvoyer l’e-mail", + "Add a credit card to ride": "Ajouter une carte de crédit et vous serez prêt à voyager avec Uber.", + "Your Most Recent Trip": "Votre course la plus récente", + "details": "détails", + "Your Trip History": "Historique de votre trajet", + "Status": "Statut", + "Here's how it works:": "Voici comment ça marche :", + "Show all trips": "Montrer toutes les courses", + "Set your location:": "Définir votre position :", + "App search for address": "Application iPhone/Android : positionner la punaise ou rechercher une adresse", + "SMS text address": "SMS : envoyez votre adresse à UBRCAB (827222)", + "Confirm pickup request": "Validez la commande", + "Uber sends ETA": "Uber envoie un temps d’attente estimé (habituellement entre 5 et 10 minutes)", + "Car arrives": "Lorsque votre voiture arrive, Uber vous en informera encore..", + "Ride to destination": "Montez dans la voiture et donnez votre destination au chauffeur.", + "Thank your driver": "C’est tout ! Remerciez le chauffeur mais souvenez-vous que les pourboires sont compris et qu’il n’est pas nécessaire d’avoir du liquide sur soi.", + "Trip started here": "La course a commencé ici.", + "Trip ended here": "La course s’est terminée ici.", + "Sending Email": "Envoi de l’e-mail...", + "Resend Email Succeeded": "Nous venons d’envoyer l’e-mail. Merci de cliquer sur le lien de confirmation que vous avez reçu.", + "Resend Email Failed": "Il y a eu un problème lors de l’envoi de l’email. Merci de contacter le support si le problème persiste.", + "Resend Text Succeeded": 'Nous venons d’envoyer le SMS. Merci de répondre "GO" au message que vous avez reçu. Il se peut que cela prenne quelques minutes pour que le message arrive sur votre téléphone.', + "Resend Text Failed": "Il y a eu un problème lors de l’envoi du SMS. Merci de contacter le support si le problème persiste.", + "Password Reset Error": "Il y a eu une error lors de la réinitialisation de votre mot de passe.", + "New Password:": "Nouveau mot de passe:", + "Forgot Password Error": "Votre nom d’utilisateur / adresse email ne peut être trouvé. Merci d’utiliser la même qu’à l’inscription.", + "Forgot Password Success": "Merci de consulter votre boîte mail pour suivre la demande de ‘réinitialisation de mot de passe.", + "Forgot Password Enter Email": "Merci de saisir votre adresse email et nous vous enverrons un lien vous permettant de réinitialiser votre mot de passe :", + "Invite friends": "Inviter vos amis", + "Give $ Get $": "Donnez $10, Recevez $10", + "Give $ Get $ Description": "Chaque ami que vous invitez à Uber recevra $10 de crédits Uber. Dès lors qu’une personne que vous aurez invité aura utilisé Uber pour la première, vous recevrez $10 de crédits Uber également !", + "What are you waiting for?": "N’attendez plus ! Lancez les invitations !", + "Tweet": "Tweeter", + "Invite Link": "Envoyez ce lien par email ou messagerie instantanée à vos amis :", + "Enter Promotion Code": "Si vous avez un code promo, saisissez-le ici:", + "Your Active Promotions": "Vos Codes Promos Actifs", + "Code": "Code", + "Details": "Détails", + "Trips Remaining": "Courses restantes", + "Expires": "Expire", + "No Active Promotions": "Vous n’avez pas de code promo actif.", + "Your Available Promotions": "Votres Promos Disponibles", + "Where do you want us to pick you up?": "Où souhaitez-vous que nous vous prenions en charge ?", + "Address to search": "Adresse à rechercher", + "Search": "Chercher", + "Driver Name:": "Nom du chauffeur:", + "Driver #:": "# Chauffeur:", + "Pickup Address:": "Lieu de prise en charge:", + "Add to Favorite Locations": "Ajoutez aux Lieux Favoris", + "Star": "Étoiles", + "Nickname:": "Pseudo", + "Add": "Ajouter", + "Your last trip": "Votre dernière course", + "Please rate your driver:": "Merci de noter votre chauffeur :", + "Comments: (optional)": "Commentaires: (optionnel)", + "Rate Trip": "Notez votre course", + "Pickup time:": "Heure de Prise en Charge :", + "Miles:": "Kilomètres :", + "Trip time:": "Temps de course :", + "Fare:": "Tarif :", + "Favorite Locations": "Lieux Favoris", + "Search Results": "Résultats", + "You have no favorite locations saved.": "Vous n’avez pas de lieux de prise en charge favoris.", + "Loading...": "Chargement...", + "Request Pickup": "Commander ici", + "Cancel Pickup": "Annuler", + "Requesting Closest Driver": "Nous demandons au chauffeur le plus proche de vous prendre en charge...", + "En Route": "Vous êtes actuellement en route...", + "Rate Last Trip": "Merci de noter votre précédent trajet pour faire une autre course.", + "Rate Before Submitting": "Merci de noter votre trajet avant de le valider.", + "Address too short": "L’adresse est trop courte", + "or did you mean": "ou vouliez-vous dire", + "Search Address Failed": "Impossible de trouver l’adresse spécifiée. Merci de saisir une autre adresse proche de l’endroit où vous vous trouvez.", + "Sending pickup request...": "Envoi de la demande de prise en charge...", + "Cancel Request Prompt": "Voulez-vous vraiment annuler votre demande ?", + "Cancel Request Arrived Prompt": 'Voulez-vous vraiment annuler votre demande ? Votre chauffeur est arrivé, vous serez donc facturé de $10 de frais d’annulation. Il pourrait être utile que vous appeliez votre chauffeur maintenant.', + "Favorite Location Nickname Length Error": "Le pseudo doit faire au moins 3 caractères de long", + "Favorite Location Save Succeeded": "Adresse enregistrée !", + "Favorite Location Save Failed": "Impossible d’enregistrer votre adresse. Merci de réessayer ultérieurement.", + "Favorite Location Title": "Adresse favorie <%= id %>", + "Search Location Title": "Recherche d’adresse <%= id %>", + "ETA Message": "Temps d’attente estimé: environ <%= minutes %> minutes", + "Nearest Cab Message": "Le chauffeur le plus proche sera là dans <%= minutes %> minute(s)", + "Arrival ETA Message": "Votre chauffeur arrivera dans <%= minutes %> minute(s)", + "Arriving Now Message": "Votre chauffeur est en approche...", + "Rating Driver Failed": "Impossible de contacter le serveur. Merci de réessayer ultérieurement ou de contacter le support si le problème persiste.", + "settings": "Paramètres", + "Information": "Information", + "Picture": "Photo", + "Change password": "Modifier votre mot de passe", + "Your current Picture": "Votre photo", + "Your Favorite Locations": "Vos lieux favoris", + "You have no favorite locations saved.": "Vous n’avez pas de lieu favori", + "Account Information": "Informations Personnelles", + "Mobile Phone Information": "Informations de Mobile", + "Change Your Password": "Changez votre mot de passe.", + "Country": "Pays", + "Language": "Langue", + "Favorite Location": "Lieu favori", + "No Approximate Address": "Impossible de trouver une adresse même approximative", + "Address:": "Adresse :", + "Information Update Succeeded": "Vos informations ont été mises à jour !", + "Information Update Failed": "Nous n’avons pas pu mettre à jour vos informations. Merci de réessayer dans quelques instants ou de contacter le support si le problème persiste.", + "Location Delete Succeeded": "Adresse supprimée !", + "Location Delete Failed": "Nous n’avons pas pu supprimée votre adresse favorie. Merci de réessayer plus tard ou de contacter le support si le problème persiste.", + "Location Edit Succeeded": "Modifications sauvegardées !", + "Location Edit Failed": "Nous n’avons pas pu sauvegarder vos modifications. Merci de réessayer dans quelques minutes.", + "Picture Update Succeeded": "Votre photo a été mise à jour !", + "Picture Update Failed": "Nous n’avons pas pu mettre à jour votre photo. Merci de réessayer dans quelques instants.", + "Personal Information": "Informations Personnelles", + "Mobile Phone Number": "Numéro de Téléphone Portable", + "Payment Information": "Informations de Facturation", + "Your card will not be charged until you take a trip.": "Votre carte ne sera pas débitée avant votre premier trajet.", + "Card Number": "Numéro de Carte", + "Promotion Code Input Label": "Code promo, code d’invitation ou “deal†acheté en ligne (optionnel)", + "Terms and Conditions": "Conditions Générales", + "HELP": "HELP", + "STOP": "STOP", + "Sign Up Agreement": "En souscrivant, j’accepte les <%= terms_link %> et <%= privacy_link %> et comprends qu’Uber est un outil de commande de chauffeur, et non un transporteur.", + "Sign Up Agreement Error": "Vous devez accepter les Conditions Générales d’utilisation d’Uber Terms and Conditions et la Politique de Confidentialité pour continuer.", + "Message and Data Rates Disclosure": "Les frais d’envoi de SMS et de consommation de données peuvent s’appliquer. Répondez <%= help_string %> au 827-222 pour obtenir de l’aide. Répondez <%= stop_string %> au 827-222 pour ne plus recevoir de SMS. Pour plus d’aide, visitez support.uber.com ou appelez le (866) 576-1039. Opérateurs supportés: AT&T, Sprint, Verizon, T-Mobile, Orange, SFR et Bouygues Telecom.", + "Zip/Postal Code": "Code Postal", + "Expiration Date": "Date D'expiration", + "Security Code": "Code de Sécurité", + "Type of Card": "Type", + "Personal": "Personnel", + "Business": "Entreprise", + "Promotion Code": "Code Promo", + "Legal Information": "Mentions Légales", + "I Agree": "J'accepte.", + "Your Trip": "Votre Course", + "Trip Info": "Informations de la Course", + "Request a fare review": "Demander un contrôle du tarif", + "Fare Review Submitted": "Votre demande de contrôle du tarif a été soumis. Nous reviendrons vers vous rapidement concernant cette demande. Nous nous excusons pour les dérangements éventuellement occasionnés !", + "Fair Price Consideration": "Nous nous engageons à proposer Uber à un tarif juste. Avant de demander un contrôle du tarif, merci de prendre en compte :", + "Your Fare Calculation": "Calcul du Prix", + "Charges": "Coûts", + "Discounts": "Réductions", + "Total Charge": "Coût total", + "Uber pricing information": "Information sur les prix d’Uber", + "Uber Pricing Information Message": "<%= learn_link %> est disponible sur notre site web.", + "GPS Point Capture Disclosure": "A cause d’un nombre limité de coordonnées GPS sauvegardées, les angles de votre trajet sur la carte peuvent apparaître coupés ou arrondis. Ces légères incohérences débouchent sur des distances mesurées plus courtes, ce qui implique toujours un prix du trajet moins élevé.", + "Fare Review Note": "Merci de nous expliquer pourquoi le tarif de cette course nécessite d’être contrôlé. Vos commentaires ci-dessous nous aideront à établir un prix plus juste si nécessaire :", + "Fare Review Error": "Il y a eu une erreur lors de l’envoi de la demande. Assurez-vous d’avoir bien ajouté une description à votre demande." + }; +}).call(this); +}, "views/clients/billing": function(exports, require, module) {(function() { + var clientsBillingTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsBillingTemplate = require('templates/clients/billing'); + exports.ClientsBillingView = (function() { + __extends(ClientsBillingView, UberView); + function ClientsBillingView() { + ClientsBillingView.__super__.constructor.apply(this, arguments); + } + ClientsBillingView.prototype.id = 'billing_view'; + ClientsBillingView.prototype.className = 'view_container'; + ClientsBillingView.prototype.events = { + 'click a#add_card': 'addCard', + 'click .charge_arrear': 'chargeArrear' + }; + ClientsBillingView.prototype.render = function() { + this.RefreshUserInfo(__bind(function() { + var cards, newForm; + this.HideSpinner(); + $(this.el).html(clientsBillingTemplate()); + if (USER.payment_gateway.payment_profiles.length === 0) { + newForm = new app.views.clients.modules.creditcard; + $(this.el).find("#add_card_wrapper").html(newForm.render(0).el); + } else { + cards = new app.views.clients.modules.creditcard; + $("#cards").html(cards.render("all").el); + } + return this.delegateEvents(); + }, this)); + return this; + }; + ClientsBillingView.prototype.addCard = function(e) { + var newCard; + e.preventDefault(); + newCard = new app.views.clients.modules.creditcard; + $('#cards').append(newCard.render("new").el); + return $("a#add_card").hide(); + }; + ClientsBillingView.prototype.chargeArrear = function(e) { + var $el, arrearId, attrs, cardId, options, tryCharge; + e.preventDefault(); + $(".error_message").text(""); + $el = $(e.currentTarget); + arrearId = $el.attr('id'); + cardId = $el.parent().find('#card_to_charge').val(); + this.ShowSpinner('submit'); + tryCharge = new app.models.clientbills({ + id: arrearId + }); + attrs = { + payment_profile_id: cardId, + dataType: 'json' + }; + options = { + success: __bind(function(data, textStatus, jqXHR) { + $el.parent().find(".success_message").text(t("Billing Succeeded")); + $el.hide(); + return $el.parent().find('#card_to_charge').hide(); + }, this), + error: __bind(function(jqXHR, status, errorThrown) { + return $el.parent().find(".error_message").text(JSON.parse(status.responseText).error); + }, this), + complete: __bind(function() { + return this.HideSpinner(); + }, this) + }; + return tryCharge.save(attrs, options); + }; + return ClientsBillingView; + })(); +}).call(this); +}, "views/clients/confirm_email": function(exports, require, module) {(function() { + var clientsConfirmEmailTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsConfirmEmailTemplate = require('templates/clients/confirm_email'); + exports.ClientsConfirmEmailView = (function() { + __extends(ClientsConfirmEmailView, UberView); + function ClientsConfirmEmailView() { + ClientsConfirmEmailView.__super__.constructor.apply(this, arguments); + } + ClientsConfirmEmailView.prototype.id = 'confirm_email_view'; + ClientsConfirmEmailView.prototype.className = 'view_container'; + ClientsConfirmEmailView.prototype.render = function(token) { + var attrs; + $(this.el).html(clientsConfirmEmailTemplate()); + attrs = { + data: { + email_token: token + }, + success: __bind(function(data, textStatus, jqXHR) { + var show_dashboard; + this.HideSpinner(); + show_dashboard = function() { + return app.routers.clients.navigate('!/dashboard', true); + }; + if (data.status === 'OK') { + $('.success_message').show(); + return _.delay(show_dashboard, 3000); + } else if (data.status === 'ALREADY_COMFIRMED') { + $('.already_confirmed_message').show(); + return _.delay(show_dashboard, 3000); + } else { + return $('.error_message').show(); + } + }, this), + error: __bind(function(e) { + this.HideSpinner(); + return $('.error_message').show(); + }, this), + complete: function(status) { + return $('#attempt_text').hide(); + }, + dataType: 'json', + type: 'PUT', + url: "" + API + "/users/self" + }; + $.ajax(attrs); + this.ShowSpinner('submit'); + return this; + }; + return ClientsConfirmEmailView; + })(); +}).call(this); +}, "views/clients/dashboard": function(exports, require, module) {(function() { + var clientsDashboardTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsDashboardTemplate = require('templates/clients/dashboard'); + exports.ClientsDashboardView = (function() { + var displayFirstTrip; + __extends(ClientsDashboardView, UberView); + function ClientsDashboardView() { + this.showAllTrips = __bind(this.showAllTrips, this); + this.render = __bind(this.render, this); + ClientsDashboardView.__super__.constructor.apply(this, arguments); + } + ClientsDashboardView.prototype.id = 'dashboard_view'; + ClientsDashboardView.prototype.className = 'view_container'; + ClientsDashboardView.prototype.events = { + 'click a.confirmation': 'confirmationClick', + 'click #resend_email': 'resendEmail', + 'click #resend_mobile': 'resendMobile', + 'click #show_all_trips': 'showAllTrips' + }; + ClientsDashboardView.prototype.render = function() { + var displayPage, downloadTrips; + this.HideSpinner(); + displayPage = __bind(function() { + $(this.el).html(clientsDashboardTemplate()); + this.confirmationsSetup(); + return this.RequireMaps(__bind(function() { + if (USER.trips.models[0]) { + if (!USER.trips.models[0].get("points")) { + return USER.trips.models[0].fetch({ + data: { + relationships: 'points' + }, + success: __bind(function() { + this.CacheData("USERtrips", USER.trips); + return displayFirstTrip(); + }, this) + }); + } else { + return displayFirstTrip(); + } + } + }, this)); + }, this); + downloadTrips = __bind(function() { + return this.DownloadUserTrips(displayPage, false, 10); + }, this); + this.RefreshUserInfo(downloadTrips); + return this; + }; + displayFirstTrip = __bind(function() { + var bounds, endPos, map, myOptions, path, polyline, startPos; + myOptions = { + zoom: 12, + mapTypeId: google.maps.MapTypeId.ROADMAP, + zoomControl: false, + rotateControl: false, + panControl: false, + mapTypeControl: false, + scrollwheel: false + }; + if (USER.trips.length === 10) { + $("#show_all_trips").show(); + } + if (USER.trips.length > 0) { + map = new google.maps.Map(document.getElementById("trip_details_map"), myOptions); + bounds = new google.maps.LatLngBounds(); + path = []; + _.each(USER.trips.models[0].get('points'), __bind(function(point) { + path.push(new google.maps.LatLng(point.lat, point.lng)); + return bounds.extend(_.last(path)); + }, this)); + map.fitBounds(bounds); + startPos = new google.maps.Marker({ + position: _.first(path), + map: map, + title: t('Trip started here'), + icon: 'https://uber-static.s3.amazonaws.com/marker_start.png' + }); + endPos = new google.maps.Marker({ + position: _.last(path), + map: map, + title: t('Trip ended here'), + icon: 'https://uber-static.s3.amazonaws.com/marker_end.png' + }); + polyline = new google.maps.Polyline({ + path: path, + strokeColor: '#003F87', + strokeOpacity: 1, + strokeWeight: 5 + }); + return polyline.setMap(map); + } + }, ClientsDashboardView); + ClientsDashboardView.prototype.confirmationsSetup = function() { + var blink, cardForm, element, _ref, _ref2, _ref3, _ref4, _ref5; + blink = function(element) { + var opacity; + opacity = 0.5; + if (element.css('opacity') === "0.5") { + opacity = 1.0; + } + return element.fadeTo(2000, opacity, function() { + return blink(element); + }); + }; + if (((_ref = window.USER) != null ? (_ref2 = _ref.payment_gateway) != null ? (_ref3 = _ref2.payment_profiles) != null ? _ref3.length : void 0 : void 0 : void 0) === 0) { + element = $('#confirmed_credit_card'); + cardForm = new app.views.clients.modules.creditcard; + $('#card.info').append(cardForm.render().el); + blink(element); + } + if (((_ref4 = window.USER) != null ? _ref4.confirm_email : void 0) === false) { + element = $('#confirmed_email'); + blink(element); + } + if ((((_ref5 = window.USER) != null ? _ref5.confirm_mobile : void 0) != null) === false) { + element = $('#confirmed_mobile'); + return blink(element); + } + }; + ClientsDashboardView.prototype.confirmationClick = function(e) { + e.preventDefault(); + $('.info').hide(); + $('#more_info').show(); + switch (e.currentTarget.id) { + case "card": + return $('#card.info').slideToggle(); + case "mobile": + return $('#mobile.info').slideToggle(); + case "email": + return $('#email.info').slideToggle(); + } + }; + ClientsDashboardView.prototype.resendEmail = function(e) { + var $el; + e.preventDefault(); + $el = $(e.currentTarget); + $el.removeAttr('href').prop({ + disabled: true + }); + $el.html(t("Sending Email")); + return $.ajax({ + type: 'GET', + url: API + '/users/request_confirm_email', + data: { + token: USER.token + }, + dataType: 'json', + success: __bind(function(data, textStatus, jqXHR) { + return $el.html(t("Resend Email Succeeded")); + }, this), + error: __bind(function(jqXHR, textStatus, errorThrown) { + return $el.html(t("Resend Email Failed")); + }, this) + }); + }; + ClientsDashboardView.prototype.resendMobile = function(e) { + var $el; + e.preventDefault(); + $el = $(e.currentTarget); + $el.removeAttr('href').prop({ + disabled: true + }); + $el.html("Sending message..."); + return $.ajax({ + type: 'GET', + url: API + '/users/request_confirm_mobile', + data: { + token: USER.token + }, + dataType: 'json', + success: __bind(function(data, textStatus, jqXHR) { + return $el.html(t("Resend Text Succeeded")); + }, this), + error: __bind(function(jqXHR, textStatus, errorThrown) { + return $el.html(t("Resend Text Failed")); + }, this) + }); + }; + ClientsDashboardView.prototype.showAllTrips = function(e) { + e.preventDefault(); + $(e.currentTarget).hide(); + return this.DownloadUserTrips(this.render, true, 1000); + }; + return ClientsDashboardView; + }).call(this); +}).call(this); +}, "views/clients/forgot_password": function(exports, require, module) {(function() { + var clientsForgotPasswordTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsForgotPasswordTemplate = require('templates/clients/forgot_password'); + exports.ClientsForgotPasswordView = (function() { + __extends(ClientsForgotPasswordView, UberView); + function ClientsForgotPasswordView() { + ClientsForgotPasswordView.__super__.constructor.apply(this, arguments); + } + ClientsForgotPasswordView.prototype.id = 'forgotpassword_view'; + ClientsForgotPasswordView.prototype.className = 'view_container modal_view_container'; + ClientsForgotPasswordView.prototype.events = { + "submit #password_reset": "passwordReset", + "click #password_reset_submit": "passwordReset", + "submit #forgot_password": "forgotPassword", + "click #forgot_password_submit": "forgotPassword" + }; + ClientsForgotPasswordView.prototype.render = function(token) { + this.HideSpinner(); + $(this.el).html(clientsForgotPasswordTemplate({ + token: token + })); + this.delegateEvents(); + return this; + }; + ClientsForgotPasswordView.prototype.forgotPassword = function(e) { + var attrs; + e.preventDefault(); + $('.success_message').hide(); + $(".error_message").hide(); + attrs = { + data: { + login: $("#login").val() + }, + success: __bind(function(data, textStatus, jqXHR) { + this.HideSpinner(); + $('.success_message').show(); + return $("#forgot_password").hide(); + }, this), + error: __bind(function(e) { + this.HideSpinner(); + return $('.error_message').show(); + }, this), + dataType: 'json', + type: 'PUT', + url: "" + API + "/users/forgot_password" + }; + $.ajax(attrs); + return this.ShowSpinner('submit'); + }; + ClientsForgotPasswordView.prototype.passwordReset = function(e) { + var attrs; + e.preventDefault(); + attrs = { + data: { + email_token: $("#token").val(), + password: $("#password").val() + }, + success: __bind(function(data, textStatus, jqXHR) { + this.HideSpinner(); + $.cookie('token', data.token); + amplify.store('USERjson', data); + app.refreshMenu(); + return location.hash = '!/dashboard'; + }, this), + error: __bind(function(e) { + this.HideSpinner(); + return $('#error_reset').show(); + }, this), + dataType: 'json', + type: 'PUT', + url: "" + API + "/users/self" + }; + $.ajax(attrs); + return this.ShowSpinner('submit'); + }; + return ClientsForgotPasswordView; + })(); +}).call(this); +}, "views/clients/invite": function(exports, require, module) {(function() { + var clientsInviteTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsInviteTemplate = require('templates/clients/invite'); + exports.ClientsInviteView = (function() { + __extends(ClientsInviteView, UberView); + function ClientsInviteView() { + ClientsInviteView.__super__.constructor.apply(this, arguments); + } + ClientsInviteView.prototype.id = 'invite_view'; + ClientsInviteView.prototype.className = 'view_container'; + ClientsInviteView.prototype.render = function() { + this.ReadUserInfo(); + this.HideSpinner(); + $(this.el).html(clientsInviteTemplate()); + console.log(screen); + return this; + }; + return ClientsInviteView; + })(); +}).call(this); +}, "views/clients/login": function(exports, require, module) {(function() { + var clientsLoginTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsLoginTemplate = require('templates/clients/login'); + exports.ClientsLoginView = (function() { + __extends(ClientsLoginView, UberView); + function ClientsLoginView() { + ClientsLoginView.__super__.constructor.apply(this, arguments); + } + ClientsLoginView.prototype.id = 'login_view'; + ClientsLoginView.prototype.className = 'view_container modal_view_container'; + ClientsLoginView.prototype.events = { + 'submit form': 'authenticate', + 'click button': 'authenticate' + }; + ClientsLoginView.prototype.initialize = function() { + _.bindAll(this, 'render'); + return this.render(); + }; + ClientsLoginView.prototype.render = function() { + this.HideSpinner(); + $(this.el).html(clientsLoginTemplate()); + this.delegateEvents(); + return this.place(); + }; + ClientsLoginView.prototype.authenticate = function(e) { + e.preventDefault(); + return $.ajax({ + type: 'POST', + url: API + '/auth/web_login/client', + data: { + login: $("#login").val(), + password: $("#password").val() + }, + dataType: 'json', + success: function(data, textStatus, jqXHR) { + $.cookie('user', JSON.stringify(data)); + $.cookie('token', data.token); + amplify.store('USERjson', data); + $('header').html(app.views.shared.menu.render().el); + return app.routers.clients.navigate('!/dashboard', true); + }, + error: function(jqXHR, textStatus, errorThrown) { + $.cookie('user', null); + $.cookie('token', null); + if (jqXHR.status === 403) { + $.cookie('redirected_user', JSON.stringify(JSON.parse(jqXHR.responseText).error_obj), { + domain: '.uber.com' + }); + window.location = 'http://partners.uber.com/'; + } + return $('.error_message').html(JSON.parse(jqXHR.responseText).error).hide().fadeIn(); + } + }); + }; + return ClientsLoginView; + })(); +}).call(this); +}, "views/clients/modules/credit_card": function(exports, require, module) {(function() { + var creditCardTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + creditCardTemplate = require('templates/clients/modules/credit_card'); + exports.CreditCardView = (function() { + __extends(CreditCardView, UberView); + function CreditCardView() { + CreditCardView.__super__.constructor.apply(this, arguments); + } + CreditCardView.prototype.id = 'creditcard_view'; + CreditCardView.prototype.className = 'module_container'; + CreditCardView.prototype.events = { + 'submit #credit_card_form': 'processNewCard', + 'click #new_card': 'processNewCard', + 'change #card_number': 'showCardType', + 'click .edit_card_show': 'showEditCard', + 'click .edit_card': 'editCard', + 'click .delete_card': 'deleteCard', + 'click .make_default': 'makeDefault', + 'change .use_case': 'saveUseCase' + }; + CreditCardView.prototype.initialize = function() { + return app.collections.paymentprofiles.bind("refresh", __bind(function() { + return this.RefreshUserInfo(__bind(function() { + this.render("all"); + return this.HideSpinner(); + }, this)); + }, this)); + }; + CreditCardView.prototype.render = function(cards) { + if (cards == null) { + cards = "new"; + } + if (cards === "all") { + app.collections.paymentprofiles.reset(USER.payment_gateway.payment_profiles); + cards = app.collections.paymentprofiles; + } + $(this.el).html(creditCardTemplate({ + cards: cards + })); + return this; + }; + CreditCardView.prototype.processNewCard = function(e) { + var $el, attrs, model, options; + e.preventDefault(); + this.ClearGlobalStatus(); + $el = $("#credit_card_form"); + $el.find('.error_message').html(""); + attrs = { + card_number: $el.find('#card_number').val(), + card_code: $el.find('#card_code').val(), + card_expiration_month: $el.find('#card_expiration_month').val(), + card_expiration_year: $el.find('#card_expiration_year').val(), + use_case: $el.find('#use_case').val(), + "default": $el.find('#default_check').prop("checked") + }; + options = { + statusCode: { + 200: __bind(function(e) { + this.HideSpinner(); + $('#cc_form_wrapper').hide(); + app.collections.paymentprofiles.trigger("refresh"); + $(this.el).remove(); + $("a#add_card").show(); + return $('section').html(app.views.clients.billing.render().el); + }, this), + 406: __bind(function(e) { + var error, errors, _i, _len, _ref, _results; + this.HideSpinner(); + errors = JSON.parse(e.responseText); + _ref = _.keys(errors); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + error = _ref[_i]; + _results.push(error === "top_of_form" ? $("#top_of_form").html(errors[error]) : $("#credit_card_form").find("#" + error).parent().find(".error_message").html(errors[error])); + } + return _results; + }, this), + 420: __bind(function(e) { + this.HideSpinner(); + return $("#top_of_form").html(t("Unable to Verify Card")); + }, this) + } + }; + this.ShowSpinner("submit"); + model = new app.models.paymentprofile; + model.save(attrs, options); + return app.collections.paymentprofiles.add(model); + }; + CreditCardView.prototype.showCardType = function(e) { + var $el, reAmerica, reDiscover, reMaster, reVisa, validCard; + reVisa = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/; + reMaster = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/; + reAmerica = /^6011-?\d{4}-?\d{4}-?\d{4}$/; + reDiscover = /^3[4,7]\d{13}$/; + $el = $("#card_logos"); + validCard = false; + if (e.currentTarget.value.match(reVisa)) { + validCard = true; + } else if (e.currentTarget.value.match(reMaster)) { + $el.css('background-position', "-60px"); + validCard = true; + } else if (e.currentTarget.value.match(reAmerica)) { + $el.css('background-position', "-120px"); + validCard = true; + } else if (e.currentTarget.value.match(reDiscover)) { + $el.css('background-position', "-180px"); + validCard = true; + } + if (validCard) { + $el.css('width', "60px"); + return $el.css('margin-left', "180px"); + } else { + $el.css('width', "250px"); + return $el.css('margin-left', "80px"); + } + }; + CreditCardView.prototype.showEditCard = function(e) { + var $el, id; + e.preventDefault(); + $el = $(e.currentTarget); + if ($el.html() === t("Edit")) { + id = $el.html(t("Cancel")).parents("tr").attr("id").substring(1); + return $("#e" + id).show(); + } else { + id = $el.html(t("Edit")).parents("tr").attr("id").substring(1); + return $("#e" + id).hide(); + } + }; + CreditCardView.prototype.editCard = function(e) { + var $el, attrs, id, options; + e.preventDefault(); + this.ClearGlobalStatus(); + $el = $(e.currentTarget).parents("td"); + id = $el.parents("tr").attr("id").substring(1); + $el.attr('disabled', 'disabled'); + this.ShowSpinner('submit'); + attrs = { + card_expiration_month: $el.find('#card_expiration_month').val(), + card_expiration_year: $el.find('#card_expiration_year').val(), + card_code: $el.find('#card_code').val() + }; + options = { + success: __bind(function(response) { + this.HideSpinner(); + this.ShowSuccess(t("Credit Card Update Succeeded")); + $("#e" + id).hide(); + $("#d" + id).find(".edit_card_show").html(t("Edit")); + return app.collections.paymentprofiles.trigger("refresh"); + }, this), + error: __bind(function(e) { + this.HideSpinner(); + this.ShowError(t("Credit Card Update Failed")); + return $el.removeAttr('disabled'); + }, this) + }; + app.collections.paymentprofiles.models[id].set(attrs); + return app.collections.paymentprofiles.models[id].save({}, options); + }; + CreditCardView.prototype.deleteCard = function(e) { + var $el, id, options; + e.preventDefault(); + $el = $(e.currentTarget).parents("td"); + id = $el.parents("tr").attr("id").substring(1); + this.ClearGlobalStatus(); + this.ShowSpinner('submit'); + options = { + success: __bind(function(response) { + this.ShowSuccess(t("Credit Card Delete Succeeded")); + $("form").hide(); + app.collections.paymentprofiles.trigger("refresh"); + return $('section').html(app.views.clients.billing.render().el); + }, this), + error: __bind(function(xhr, e) { + this.HideSpinner(); + return this.ShowError(t("Credit Card Delete Failed")); + }, this) + }; + return app.collections.paymentprofiles.models[id].destroy(options); + }; + CreditCardView.prototype.saveUseCase = function(e) { + var $el, attrs, id, options, use_case; + this.ClearGlobalStatus(); + $el = $(e.currentTarget); + use_case = $el.val(); + id = $el.parents("tr").attr("id").substring(1); + attrs = { + use_case: use_case + }; + options = { + success: __bind(function(response) { + return this.ShowSuccess(t("Credit Card Update Category Succeeded")); + }, this), + error: __bind(function(e) { + return this.ShowError(t("Credit Card Update Category Failed")); + }, this) + }; + app.collections.paymentprofiles.models[id].set(attrs); + return app.collections.paymentprofiles.models[id].save({}, options); + }; + CreditCardView.prototype.makeDefault = function(e) { + var $el, attrs, id, options; + e.preventDefault(); + this.ClearGlobalStatus(); + $el = $(e.currentTarget).parents("td"); + id = $el.parents("tr").attr("id").substring(1); + attrs = { + "default": true + }; + options = { + success: __bind(function(response) { + this.ShowSuccess(t("Credit Card Update Default Succeeded")); + return app.collections.paymentprofiles.trigger("refresh"); + }, this), + error: __bind(function(e) { + return this.ShowError(t("Credit Card Update Default Failed")); + }, this) + }; + app.collections.paymentprofiles.models[id].set(attrs); + return app.collections.paymentprofiles.models[id].save({}, options); + }; + return CreditCardView; + })(); +}).call(this); +}, "views/clients/promotions": function(exports, require, module) {(function() { + var clientsPromotionsTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsPromotionsTemplate = require('templates/clients/promotions'); + exports.ClientsPromotionsView = (function() { + __extends(ClientsPromotionsView, UberView); + function ClientsPromotionsView() { + this.render = __bind(this.render, this); + ClientsPromotionsView.__super__.constructor.apply(this, arguments); + } + ClientsPromotionsView.prototype.id = 'promotions_view'; + ClientsPromotionsView.prototype.className = 'view_container'; + ClientsPromotionsView.prototype.events = { + 'submit form': 'submitPromo', + 'click button': 'submitPromo' + }; + ClientsPromotionsView.prototype.initialize = function() { + if (this.model) { + return this.RefreshUserInfo(this.render); + } + }; + ClientsPromotionsView.prototype.render = function() { + var renderTemplate; + this.ReadUserInfo(); + renderTemplate = __bind(function() { + $(this.el).html(clientsPromotionsTemplate({ + promos: window.USER.unexpired_client_promotions || [] + })); + return this.HideSpinner(); + }, this); + this.DownloadUserPromotions(renderTemplate); + return this; + }; + ClientsPromotionsView.prototype.submitPromo = function(e) { + var attrs, model, options, refreshTable; + e.preventDefault(); + this.ClearGlobalStatus(); + refreshTable = __bind(function() { + $('section').html(this.render().el); + return this.HideSpinner(); + }, this); + attrs = { + code: $('#code').val() + }; + options = { + success: __bind(function(response) { + this.HideSpinner(); + if (response.get('first_name')) { + return this.ShowSuccess("Your promotion has been applied in the form of an account credit. Click here to check your balance."); + } else { + this.ShowSuccess("Your promotion has successfully been applied"); + return this.RefreshUserInfo(this.render, true); + } + }, this), + statusCode: { + 400: __bind(function(e) { + this.ShowError(JSON.parse(e.responseText).error); + return this.HideSpinner(); + }, this) + } + }; + this.ShowSpinner("submit"); + model = new app.models.promotions; + return model.save(attrs, options); + }; + return ClientsPromotionsView; + })(); +}).call(this); +}, "views/clients/request": function(exports, require, module) {(function() { + var clientsRequestTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsRequestTemplate = require('templates/clients/request'); + exports.ClientsRequestView = (function() { + __extends(ClientsRequestView, UberView); + function ClientsRequestView() { + this.AjaxCall = __bind(this.AjaxCall, this); + this.AskDispatch = __bind(this.AskDispatch, this); + this.removeMarkers = __bind(this.removeMarkers, this); + this.displaySearchLoc = __bind(this.displaySearchLoc, this); + this.displayFavLoc = __bind(this.displayFavLoc, this); + this.showFavLoc = __bind(this.showFavLoc, this); + this.addToFavLoc = __bind(this.addToFavLoc, this); + this.removeCabs = __bind(this.removeCabs, this); + this.requestRide = __bind(this.requestRide, this); + this.rateTrip = __bind(this.rateTrip, this); + this.locationChange = __bind(this.locationChange, this); + this.panToLocation = __bind(this.panToLocation, this); + this.clickLocation = __bind(this.clickLocation, this); + this.searchLocation = __bind(this.searchLocation, this); + this.mouseoutLocation = __bind(this.mouseoutLocation, this); + this.mouseoverLocation = __bind(this.mouseoverLocation, this); + this.fetchTripDetails = __bind(this.fetchTripDetails, this); + this.submitRating = __bind(this.submitRating, this); + this.setStatus = __bind(this.setStatus, this); + this.initialize = __bind(this.initialize, this); + ClientsRequestView.__super__.constructor.apply(this, arguments); + } + ClientsRequestView.prototype.id = 'request_view'; + ClientsRequestView.prototype.className = 'view_container'; + ClientsRequestView.prototype.pollInterval = 2 * 1000; + ClientsRequestView.prototype.events = { + "submit #search_form": "searchAddress", + "click .locations_link": "locationLinkHandle", + "mouseover .location_row": "mouseoverLocation", + "mouseout .location_row": "mouseoutLocation", + "click .location_row": "clickLocation", + "click #search_location": "searchLocation", + "click #pickupHandle": "pickupHandle", + "click .stars": "rateTrip", + "submit #rating_form": "submitRating", + "click #addToFavButton": "showFavLoc", + "click #favLocNickname": "selectInputText", + "submit #favLoc_form": "addToFavLoc" + }; + ClientsRequestView.prototype.status = ""; + ClientsRequestView.prototype.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker.png"; + ClientsRequestView.prototype.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker.png"; + ClientsRequestView.prototype.initialize = function() { + var displayCabs; + displayCabs = __bind(function() { + return this.AskDispatch("NearestCab"); + }, this); + this.showCabs = _.throttle(displayCabs, this.pollInterval); + return this.numSearchToDisplay = 1; + }; + ClientsRequestView.prototype.setStatus = function(status) { + var autocomplete; + if (this.status === status) { + return; + } + try { + google.maps.event.trigger(this.map, 'resize'); + } catch (_e) {} + switch (status) { + case "init": + this.AskDispatch("StatusClient"); + this.status = "init"; + return this.ShowSpinner("load"); + case "ready": + this.HideSpinner(); + $(".panel").hide(); + $("#top_bar").fadeIn(); + $("#location_panel").fadeIn(); + $("#location_panel_control").fadeIn(); + $("#pickupHandle").attr("class", "button_green").fadeIn().find("span").html(t("Request Pickup")); + this.pickup_icon.setDraggable(true); + this.map.panTo(this.pickup_icon.getPosition()); + this.showCabs(); + try { + this.pickup_icon.setMap(this.map); + this.displayFavLoc(); + autocomplete = new google.maps.places.Autocomplete(document.getElementById('address'), { + types: ['geocode'] + }); + autocomplete.bindTo('bounds', this.map); + } catch (_e) {} + return this.status = "ready"; + case "searching": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#status_message").html(t("Requesting Closest Driver")); + $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup")); + this.pickup_icon.setDraggable(false); + this.pickup_icon.setMap(this.map); + return this.status = "searching"; + case "waiting": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup")); + $("#waiting_riding").fadeIn(); + this.pickup_icon.setDraggable(false); + this.pickup_icon.setMap(this.map); + return this.status = "waiting"; + case "arriving": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup")); + $("#waiting_riding").fadeIn(); + this.pickup_icon.setDraggable(false); + this.pickup_icon.setMap(this.map); + return this.status = "arriving"; + case "riding": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#pickupHandle").fadeIn().attr("class", "button_red").find("span").html(t("Cancel Pickup")); + $("#waiting_riding").fadeIn(); + this.pickup_icon.setDraggable(false); + this.status = "riding"; + return $("#status_message").html(t("En Route")); + case "rate": + this.HideSpinner(); + $(".panel").hide(); + $("#pickupHandle").fadeOut(); + $("#trip_completed_panel").fadeIn(); + $('#status_message').html(t("Rate Last Trip")); + return this.status = "rate"; + } + }; + ClientsRequestView.prototype.render = function() { + this.ReadUserInfo(); + this.HideSpinner(); + this.ShowSpinner("load"); + $(this.el).html(clientsRequestTemplate()); + this.cabs = []; + this.RequireMaps(__bind(function() { + var center, myOptions, streetViewPano; + center = new google.maps.LatLng(37.7749295, -122.4194155); + this.markers = []; + this.pickup_icon = new google.maps.Marker({ + position: center, + draggable: true, + clickable: true, + icon: this.pickupMarker + }); + this.geocoder = new google.maps.Geocoder(); + myOptions = { + zoom: 12, + center: center, + mapTypeId: google.maps.MapTypeId.ROADMAP, + rotateControl: false, + rotateControl: false, + panControl: false + }; + this.map = new google.maps.Map($(this.el).find("#map_wrapper_right")[0], myOptions); + if (this.status === "ready") { + this.pickup_icon.setMap(this.map); + } + if (geo_position_js.init()) { + geo_position_js.getCurrentPosition(__bind(function(data) { + var location; + location = new google.maps.LatLng(data.coords.latitude, data.coords.longitude); + this.pickup_icon.setPosition(location); + this.map.panTo(location); + return this.map.setZoom(16); + }, this)); + } + this.setStatus("init"); + streetViewPano = this.map.getStreetView(); + google.maps.event.addListener(streetViewPano, 'visible_changed', __bind(function() { + if (streetViewPano.getVisible()) { + this.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker_large.png"; + this.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker_large.png"; + } else { + this.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker.png"; + this.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker.png"; + } + this.pickup_icon.setIcon(this.pickupMarker); + return _.each(this.cabs, __bind(function(cab) { + return cab.setIcon(this.cabMarker); + }, this)); + }, this)); + if (this.status === "ready") { + return this.displayFavLoc(); + } + }, this)); + return this; + }; + ClientsRequestView.prototype.submitRating = function(e) { + var $el, message, rating; + e.preventDefault(); + $el = $(e.currentTarget); + rating = 0; + _(5).times(function(num) { + if ($el.find(".stars#" + (num + 1)).attr("src") === "/web/img/star_active.png") { + return rating = num + 1; + } + }); + if (rating === 0) { + $("#status_message").html("").html(t("Rate Before Submitting")); + } else { + this.ShowSpinner("submit"); + this.AskDispatch("RatingDriver", { + rating: rating + }); + } + message = $el.find("#comments").val().toString(); + if (message.length > 5) { + return this.AskDispatch("Feedback", { + message: message + }); + } + }; + ClientsRequestView.prototype.fetchTripDetails = function(id) { + var trip; + trip = new app.models.trip({ + id: id + }); + return trip.fetch({ + data: { + relationships: 'points,driver,city' + }, + dataType: 'json', + success: __bind(function() { + var bounds, endPos, path, polyline, startPos; + bounds = new google.maps.LatLngBounds(); + path = []; + _.each(trip.get('points'), __bind(function(point) { + path.push(new google.maps.LatLng(point.lat, point.lng)); + return bounds.extend(_.last(path)); + }, this)); + startPos = new google.maps.Marker({ + position: _.first(path), + map: this.map, + title: t("Trip started here"), + icon: 'https://uber-static.s3.amazonaws.com/carstart.png' + }); + endPos = new google.maps.Marker({ + position: _.last(path), + map: this.map, + title: t("Trip ended here"), + icon: 'https://uber-static.s3.amazonaws.com/carstop.png' + }); + polyline = new google.maps.Polyline({ + path: path, + strokeColor: '#003F87', + strokeOpacity: 1, + strokeWeight: 5 + }); + polyline.setMap(this.map); + this.map.fitBounds(bounds); + $("#tripTime").html(app.helpers.parseDateTime(trip.get('pickup_local_time'), trip.get('city.timezone'))); + $("#tripDist").html(app.helpers.RoundNumber(trip.get('distance'), 2)); + $("#tripDur").html(app.helpers.FormatSeconds(trip.get('duration'))); + return $("#tripFare").html(app.helpers.FormatCurrency(trip.get('fare'))); + }, this) + }); + }; + ClientsRequestView.prototype.searchAddress = function(e) { + var $locationsDiv, address, alphabet, bounds, showResults; + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + try { + e.preventDefault(); + } catch (_e) {} + $('.error_message').html(""); + $locationsDiv = $("
    "); + address = $('#address').val(); + bounds = new google.maps.LatLngBounds(); + if (address.length < 5) { + $('#status_message').html(t("Address too short")).fadeIn(); + return false; + } + showResults = __bind(function(address, index) { + var first_cell, row, second_cell; + if (index < this.numSearchToDisplay) { + first_cell = "
    " + address.formatted_address + "
    " + (t('or did you mean')) + "
    " + address.formatted_address + "
    \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
    Bin Factor  
    Center 
    Image Size 
    Filter  
        
      
    \ + '); + +// click doesn't work on localhost on a Mac using Chrome/Safari, but mouseup does! +// $(div).find(".rebin-image").on("click", function () { reBinImage(div, display); }); +// $(div).find(".close-image").on("click", function () { if( win ){ win.close(); } }); + $(div).find(".rebin-image").on("mouseup", function () { reBinImage(div, display); }); + $(div).find(".close-image").on("mouseup", function () { if( win ){ win.close(); } }); + + if ( im ) { + getBinParams(div, display); + } + } + + JS9.RegisterPlugin("Fits", "Binning", binningInit, { + menu: "view", + + winTitle: "FITS Binary Table Binning", + winResize: true, + + menuItem: "Binning", + + onimageload: binningInit, + onimagedisplay: binningInit, + + help: "fitsy/binning.html", + + winDims: [400, 180], + }); +}()); diff --git a/plugins/fitsy/bzip2.js b/plugins/fitsy/bzip2.js new file mode 100644 index 00000000..f23d9234 --- /dev/null +++ b/plugins/fitsy/bzip2.js @@ -0,0 +1,283 @@ +/* + bzip2.js - a small bzip2 decompression implementation + + Copyright 2011 by antimatter15 (antimatter15@gmail.com) + + Based on micro-bunzip by Rob Landley (rob@landley.net). + + Copyright (c) 2011 by antimatter15 (antimatter15@gmail.com). + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH + THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +var bzip2 = {}; + +bzip2.array = function(bytes){ + var bit = 0, byte = 0; + var BITMASK = [0, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF ]; + return function(n){ + var result = 0; + while(n > 0){ + var left = 8 - bit; + if(n >= left){ + result <<= left; + result |= (BITMASK[left] & bytes[byte++]); + bit = 0; + n -= left; + }else{ + result <<= n; + result |= ((bytes[byte] & (BITMASK[n] << (8 - n - bit))) >> (8 - n - bit)); + bit += n; + n = 0; + } + } + return result + } +} + +bzip2.simple = function(bits){ + var size = bzip2.header(bits); + var all = [], chunk = [] + do{ + all = all.concat(all, chunk); + chunk = bzip2.decompress(bits, size); + }while(chunk != -1); + return all; +} + +bzip2.header = function(bits){ + if(bits(8*3) != 4348520) throw "No magic number found"; + var i = bits(8) - 48; + if(i < 1 || i > 9) throw "Not a BZIP archive"; + return i; +}; + + +//takes a function for reading the block data (starting with 0x314159265359) +//a block size (0-9) (optional, defaults to 9) +//a length at which to stop decompressing and return the output +bzip2.decompress = function(bits, size, len){ + var MAX_HUFCODE_BITS = 20; + var MAX_SYMBOLS = 258; + var SYMBOL_RUNA = 0; + var SYMBOL_RUNB = 1; + var GROUP_SIZE = 50; + + var bufsize = 100000 * size; + for(var h = '', i = 0; i < 6; i++) h += bits(8).toString(16); + if(h == "177245385090") return -1; //last block + if(h != "314159265359") throw "eek not valid bzip data"; + bits(32); //ignore CRC codes + if(bits(1)) throw "unsupported obsolete version"; + var origPtr = bits(24); + if(origPtr > bufsize) throw "Initial position larger than buffer size"; + var t = bits(16); + var symToByte = new Uint8Array(256), + symTotal = 0; + for (i = 0; i < 16; i++) { + if(t & (1 << (15 - i))) { + var k = bits(16); + for(j = 0; j < 16; j++){ + if(k & (1 << (15 - j))){ + symToByte[symTotal++] = (16 * i) + j; + } + } + } + } + + var groupCount = bits(3); + if(groupCount < 2 || groupCount > 6) throw "another error"; + var nSelectors = bits(15); + if(nSelectors == 0) throw "meh"; + var mtfSymbol = []; //TODO: possibly replace JS array with typed arrays + for(var i = 0; i < groupCount; i++) mtfSymbol[i] = i; + var selectors = new Uint8Array(32768); + + for(var i = 0; i < nSelectors; i++){ + for(var j = 0; bits(1); j++) if(j >= groupCount) throw "whoops another error"; + var uc = mtfSymbol[j]; + mtfSymbol.splice(j, 1); //this is a probably inefficient MTF transform + mtfSymbol.splice(0, 0, uc); + selectors[i] = uc; + } + + var symCount = symTotal + 2; + var groups = []; + for(var j = 0; j < groupCount; j++){ + var length = new Uint8Array(MAX_SYMBOLS), + temp = new Uint8Array(MAX_HUFCODE_BITS+1); + t = bits(5); //lengths + for(var i = 0; i < symCount; i++){ + while(true){ + if (t < 1 || t > MAX_HUFCODE_BITS) throw "I gave up a while ago on writing error messages"; + if(!bits(1)) break; + if(!bits(1)) t++; + else t--; + } + length[i] = t; + } + var minLen, maxLen; + minLen = maxLen = length[0]; + for(var i = 1; i < symCount; i++){ + if(length[i] > maxLen) maxLen = length[i]; + else if(length[i] < minLen) minLen = length[i]; + } + var hufGroup; + hufGroup = groups[j] = {}; + hufGroup.permute = new Uint32Array(MAX_SYMBOLS); + hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 1); + hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); + hufGroup.minLen = minLen; + hufGroup.maxLen = maxLen; + var base = hufGroup.base.subarray(1); + var limit = hufGroup.limit.subarray(1); + var pp = 0; + for(var i = minLen; i <= maxLen; i++) + for(var t = 0; t < symCount; t++) + if(length[t] == i) hufGroup.permute[pp++] = t; + for(i = minLen; i <= maxLen; i++) temp[i] = limit[i] = 0; + for(i = 0; i < symCount; i++) temp[length[i]]++; + pp = t = 0; + for(i = minLen; i < maxLen; i++) { + pp += temp[i]; + limit[i] = pp - 1; + pp <<= 1; + base[i+1] = pp - (t += temp[i]); + } + limit[maxLen]=pp+temp[maxLen]-1; + base[minLen]=0; + } + var byteCount = new Uint32Array(256); + for(var i = 0; i < 256; i++) mtfSymbol[i] = i; + var runPos, count, symCount, selector; + runPos = count = symCount = selector = 0; + var buf = new Uint32Array(bufsize); + while(true){ + if(!(symCount--)){ + symCount = GROUP_SIZE - 1; + if(selector >= nSelectors) throw "meow i'm a kitty, that's an error"; + hufGroup = groups[selectors[selector++]]; + base = hufGroup.base.subarray(1); + limit = hufGroup.limit.subarray(1); + } + i = hufGroup.minLen; + j = bits(i); + while(true){ + if(i > hufGroup.maxLen) throw "rawr i'm a dinosaur"; + if(j <= limit[i]) break; + i++; + j = (j << 1) | bits(1); + } + j -= base[i]; + if(j < 0 || j >= MAX_SYMBOLS) throw "moo i'm a cow"; + var nextSym = hufGroup.permute[j]; + if (nextSym == SYMBOL_RUNA || nextSym == SYMBOL_RUNB) { + if(!runPos){ + runPos = 1; + t = 0; + } + if(nextSym == SYMBOL_RUNA) t += runPos; + else t += 2 * runPos; + runPos <<= 1; + continue; + } + if(runPos){ + runPos = 0; + if(count + t >= bufsize) throw "Boom."; + uc = symToByte[mtfSymbol[0]]; + byteCount[uc] += t; + while(t--) buf[count++] = uc; + } + if(nextSym > symTotal) break; + if(count >= bufsize) throw "I can't think of anything. Error"; + i = nextSym -1; + uc = mtfSymbol[i]; + mtfSymbol.splice(i, 1); + mtfSymbol.splice(0, 0, uc); + uc = symToByte[uc]; + byteCount[uc]++; + buf[count++] = uc; + } + if(origPtr < 0 || origPtr >= count) throw "I'm a monkey and I'm throwing something at someone, namely you"; + var j = 0; + for(var i = 0; i < 256; i++){ + k = j + byteCount[i]; + byteCount[i] = j; + j = k; + } + for(var i = 0; i < count; i++){ + uc = buf[i] & 0xff; + buf[byteCount[uc]] |= (i << 8); + byteCount[uc]++; + } + var pos = 0, current = 0, run = 0; + if(count) { + pos = buf[origPtr]; + current = (pos & 0xff); + pos >>= 8; + run = -1; + } + count = count; + + var maxindex = 10000000; + var output = []; + var bindex = maxindex + 1; + var outbuf; + + var copies, previous, outbyte; + if(!len) len = Infinity; + while(count){ + count--; + previous = current; + pos = buf[pos]; + current = pos & 0xff; + pos >>= 8; + if(run++ == 3){ + copies = current; + outbyte = previous; + current = -1; + }else{ + copies = 1; + outbyte = current; + } + while(copies--){ + if ( bindex >= maxindex ) { + if ( outbuf !== undefined ) { + output.push(outbuf); + } + outbuf = new Uint8Array(maxindex); + bindex = 0; + } + + outbuf[bindex++] = outbyte; + + if(!--len) { + outbuf = outbuf.subarray(0, bindex); + output.push(outbuf); + return output; + } + } + if(current != previous) run = 0; + + } + + outbuf = outbuf.subarray(0, bindex); + output.push(outbuf); + return output; +} diff --git a/plugins/fitsy/fitsy.js b/plugins/fitsy/fitsy.js new file mode 100644 index 00000000..54bcb01d --- /dev/null +++ b/plugins/fitsy/fitsy.js @@ -0,0 +1,1238 @@ +/*jslint evil: true, white: true, vars: true, plusplus: true, nomen: true, unparam: true, regexp: true, bitwise: true */ +/*jshint node: true, -W099: true, laxbreak:true, laxcomma:true, multistr:true, smarttabs:true */ +/*global $, alert, XMLHttpRequest + , Uint8Array, Int8Array, Uint16Array, Int16Array, Int32Array, Uint32Array, Float32Array, Float64Array, DataView, ArrayBuffer + , FileReader, Blob, Image, window, document + , Zee, Astroem, Module, pako, LZMA, bzip2 + */ + +"use strict"; + +var Fitsy; +if( Fitsy && (typeof Fitsy !== "object" || Fitsy.NAME) ){ + throw new Error("Namespace 'Fitsy' already exists"); +} + +// Create our namespace, and specify some meta-information +Fitsy = {}; +Fitsy.NAME = "Fitsy"; // The name of this namespace +Fitsy.VERSION = "1.0"; // The version of this namespace + +Fitsy.clone = function (obj) { + var copy, i, len, attr; + + // Handle the 3 simple types, and null or undefined + if (null === obj || "object" !== typeof obj) { return obj; } + + // Handle Date + if (obj instanceof Date) { + copy = new Date(); + copy.setTime(obj.getTime()); + return copy; + } + + // Handle Array + if (obj instanceof Array) { + copy = []; + for ( i = 0, len = obj.length; i < len; i++ ) { + copy[i] = Fitsy.clone(obj[i]); + } + return copy; + } + + // Handle Object + if (obj instanceof Object) { + copy = {}; + for ( attr in obj ) { + if ( obj.hasOwnProperty(attr) ) { copy[attr] = Fitsy.clone(obj[attr]); } + } + return copy; + } + + throw new Error("Unable to copy obj! Its type isn't supported."); +}; + +Fitsy.strrepeat = function (pattern, count) { + if ( count < 1 ) { return ''; } + var result = ''; + while ( count > 1 ) { + if (count & 1) { result += pattern; } + + count >>= 1; + pattern += pattern; + } + return result + pattern; +}; + +// ArrayBuffer slice not yet available everywhere ... but it should be +if (!ArrayBuffer.prototype.slice) { + ArrayBuffer.prototype.slice = function(start, end) { + var i, result, resultArray; + var that = new Uint8Array(this); + if(end === undefined){ + end = that.length; + } + result = new ArrayBuffer(end - start); + resultArray = new Uint8Array(result); + for(i = 0; i < resultArray.length; i++){ + resultArray[i] = that[i + start]; + } + return result; + }; +} + +// hostEndian: 'true' means little-endian (for use in typed array calls) +Fitsy.hostEndian = (function(){ + return new Int8Array(new Int32Array([1]).buffer)[0] === 1; +}()); + +// copy memory from one arraybuffer to another +Fitsy.memcpy = function(dst, dstOffset, src, srcOffset, length) { + var dstU8 = new Uint8Array(dst, dstOffset, length); + var srcU8 = new Uint8Array(src, srcOffset, length); + dstU8.set(srcU8); +}; + +// getDataSlice -- get a slice of data from a File reader or an Arraybuffer +// memory optimization leads to not slicing arrays, but marking the limits +Fitsy.getDataSlice = function(fits, dtype, lo, hi, func, err){ + var chunk, totalget, totalgot, maxget, get, got, left, ptr, heapptr; + var args = Array.prototype.slice.call(arguments, 6); + switch(fits.ftype){ + case "file": + if( func ){ + fits.read.onloadend = function(){ + // convert to binary string, if necessary + if( dtype === "asString" ){ + fits.result = Fitsy.getBinaryString(fits.read.result); + } else { + fits.result = fits.read.result; + } + func.apply(null, args); + }; + } + if( err ){ + fits.read.onerror = function(){ err.apply(null, args); }; + } + if( lo || hi ){ + chunk = Fitsy.getFileSlice(fits.file, lo, hi); + } else { + chunk = fits.file; + } + // always readAsArraybuffer because readAsBinaryString is not in IE11 + // binary string will be made, if necessary, after load is done + fits.read.readAsArrayBuffer(chunk); + break; + case "array": + if( dtype === "asString" ){ + // for a binary string, a slice is OK (assumed to be small) + if( lo || hi ){ + chunk = fits.file.slice(lo, hi); + } else { + // shouldn't happen! + chunk = fits.file; + } + // mimick readAsBinaryString conversion + fits.result = Fitsy.getBinaryString(chunk); + } else { + // we pass along the whole array + fits.result = fits.file; + if( lo && hi ){ + // avoid a new array.slice, it uses extra memory needlessly + // instead just mark the limits and let func use these limits + fits.rlo = lo; + fits.rhi = hi; + } else { + delete fits.rlo; + delete fits.rhi; + } + } + if( func ){ + func.apply(null, args); + } + break; + case "gzarray": + // seek to desired location + if( lo !== fits.gz.here ){ + Astroem.gzseek(fits.gz.fd, lo, 0); + fits.gz.here = lo; + } + // total number of bytes to retrieve + totalget = hi - lo; + // allocate space for retrieved data + try{ chunk = new Uint8Array(totalget); } + catch(e){ Fitsy.error("can't allocate enough memory to slice this FITS file", e); } + // max we will retrieve at any one time (minimize precious heap space) + maxget = Math.min(totalget, Fitsy.options.gzheapsize); + // allocate space on emscripten heap + ptr = Module._malloc(maxget); + // pointer into heap space to pass into routine + heapptr= new Uint8Array(Module.HEAPU8.buffer, ptr, maxget); + // this is how much we have left to retrieve + left = totalget; + // nothing retrieved yet + totalgot = 0; + // processing loop ... + while( left ){ + // how much to retrieve on this iteration + get = Math.min(left, maxget); + // try to uncompress that amount + got = Astroem.gzread(fits.gz.fd, heapptr.byteOffset, get); + // if we got anything ... + if( got > 0 ){ + // copy new data in output buffer + Fitsy.memcpy(chunk.buffer, totalgot, + Module.HEAPU8.buffer, ptr, got); + totalgot += got; + left -= got; + } else { + // we're done + left = 0; + } + } + // free up heap space + Module._free(heapptr.byteOffset); + // mark where we are in the gzip file + fits.gz.here = lo + totalgot; + // see if we got anything + if( totalgot > 0 ){ + // convert to string + if( dtype === "asString" ){ + fits.result = Fitsy.getBinaryString(chunk); + } else { + // return raw data buffer + fits.result = chunk.buffer; + } + } else { + // handle eof + fits.eof = true; + } + // call handler + if( func ){ + func.apply(null, args); + } + break; + } +}; + +// convert arraybuffer into binary string +// akin to file.readAsBinaryString for ArrayBuffers +// but also used as a replacement for readAsBinaryString (it's not in IE11) +Fitsy.getBinaryString = function(buf){ + var s = String.fromCharCode.apply(null, new Uint8Array(buf)); + return s; +}; + +// generate a table column filter from a funtools-style expression +Fitsy.tableFilter = function(hdu, filter){ + var ft1=filter; + // convert ranges: + // pi = 100:200 -> (pi >= 100 && pi <= 200) + ft1 = ft1.replace(/([a-zA-Z][a-zA-Z0-9_]*) *= *([\-]?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+\-]?[0-9]+)?) *: *([\-]?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+\-]?[0-9]+)?)/g, "($1 >= $2 && $1 <= $3)"); + // pi = 100: -> pi >= 100 + ft1 = ft1.replace(/([a-zA-Z][a-zA-Z0-9_]*) *= *([\-]?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+\-]?[0-9]+)?) *:/g, "$1 >= $2"); + // pi = :100 -> pi <= 100 + ft1 = ft1.replace(/([a-zA-Z][a-zA-Z0-9_]*) *= *:([\-]?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+\-]?[0-9]+)?)/g, "$1 <= $2"); + // lookup columns and return generated filter string + return ft1.replace(/([ (&|+\-\/*%<>=]|^)?([a-zA-Z][a-zA-Z0-9_]*)([ )&|+\-\/*%<>=]|$)/g, function (m, delim1, key, delim2) { + var s = key; + var t = key.toUpperCase(); + delim1 = delim1 || ""; + delim2 = delim2 || ""; + if ( hdu.table[s] !== undefined ) { + s = delim1 + "view.get" + hdu.table[s].type + "(vstart + i * {{table.width}} + " + hdu.table[s].offs + ")" + delim2; + } else if ( hdu.table[t] !== undefined ) { + s = delim1 + "view.get" + hdu.table[t].type + "(vstart + i * {{table.width}} + " + hdu.table[t].offs + ")" + delim2; + } else { + // couldn't find column -- that's bad + Fitsy.error("the requested column '" + key + "' is missing from this FITS table"); + } + return s; + }); +}; + +// there are different versions of file slicing ... with different syntax +Fitsy.getFileSlice = function(file, start, end){ + var blob; + if( file.slice ){ + blob = file.slice(start, end); + } else if( file.mozSlice ){ + blob = file.mozSlice(start, end); + } else if( file.webkitSlice ){ + blob = file.webkitSlice(start, end); + } + return blob; +}; + +// return true if its a number (int or float) +Fitsy.isNumber = function(s) { + return !isNaN(parseFloat(s)) && isFinite(s); +}; + +Fitsy.xtypeof = function(obj) { + return Object.prototype.toString.call(obj).slice(8, -1); +}; + +Fitsy.cardpars = function(card){ + var name, value; + if ( card[8] !== "=" ){ + return undefined; + } + name = card.slice(0, 8).trim(); + value = card.slice(10).replace(/\'/g, " ").replace(/\/.*/, "").trim(); + if( value === "T" ){ + value = true; + } else if( value === "F" ){ + value = false; + } else if( Fitsy.isNumber(value) ){ + value = parseFloat(value); + } + + return [name, value]; +}; + +Fitsy.readImageHDUDataConverter = function(fits, hdu, options, handler){ + var dv, getfunc, setfunc, tval, i, off, scale, zero, memerr; + var rstart = 0; + var littleEndian; + hdu.dmin = Number.MAX_VALUE; + hdu.dmax = Number.MIN_VALUE; + hdu.filename = fits.name; + + switch(fits.ftype){ + case "array": + if( fits.rlo ){ + // mark offsets into ArrayBuffer where this slice starts + rstart = fits.rlo; + } + break; + } + + switch( hdu.bitpix ) { + case 8: + getfunc = DataView.prototype.getUint8; + setfunc = DataView.prototype.setUint8; + try{ hdu.filedata = new Uint8Array(fits.result, rstart); } + catch(e){memerr = true;} + break; + case -16: + getfunc = DataView.prototype.getUint16; + setfunc = DataView.prototype.setUint16; + try{hdu.filedata = new Uint16Array(fits.result, rstart);} + catch(e){memerr = true;} + break; + case 16: + if ( hdu.bzero && hdu.bzero === 32768 ) { + getfunc = DataView.prototype.getInt16; + setfunc = DataView.prototype.setUint16; + try{hdu.filedata = new Uint16Array(fits.result, rstart);} + catch(e){memerr = true;} + hdu.bitpix = -16; + } else { + getfunc = DataView.prototype.getInt16; + setfunc = DataView.prototype.setInt16; + try{hdu.filedata = new Int16Array(fits.result, rstart);} + catch(e){memerr = true;} + } + break; + case 32: + getfunc = DataView.prototype.getInt32; + setfunc = DataView.prototype.setInt32; + try{hdu.filedata = new Int32Array(fits.result, rstart);} + catch(e){memerr = true;} + break; + case -32: + getfunc = DataView.prototype.getFloat32; + setfunc = DataView.prototype.setFloat32; + try{hdu.filedata = new Float32Array(fits.result, rstart);} + catch(e){memerr = true;} + break; + case -64: + getfunc = DataView.prototype.getFloat64; + setfunc = DataView.prototype.setFloat64; + try{hdu.filedata = new Float64Array(fits.result, rstart);} + catch(e){memerr = true;} + break; + default: + Fitsy.error("unsupported FITS BITPIX value: " + hdu.bitpix); + break; + } + // process memory allocation errors + if( memerr ){ + Fitsy.error("can't allocate enough memory for this FITS image"); + } + // this is where the caller (e.g. JS9) sees the data + hdu.image = hdu.filedata; + + zero = hdu.bzero || 0; + scale = hdu.bscale || 1; + + // Convert raw bytes to image data using the appropriate data view + // + dv = new DataView(fits.result); + littleEndian = hdu.converted ? Fitsy.hostEndian : false; + for(i=0, off=rstart; i < hdu.datapixls; i++, off += hdu.pixlbytes) { + tval = getfunc.call(dv, off, littleEndian) * scale + zero; + if ( !isNaN(tval) ) { + hdu.dmin = Math.min(hdu.dmin, tval); + hdu.dmax = Math.max(hdu.dmax, tval); + } + if( !hdu.converted ){ + setfunc.call(dv, off, tval, Fitsy.hostEndian); + } + } + hdu.converted = true; + + handler(hdu, options); +}; + +Fitsy.readImageHDUData = function(fits, hdu, options, handler) { + // fits.read.onloadend = function() { Fitsy.readImageHDUDataConverter(fits, hdu, options, handler); }; + // fits.read.readAsArrayBuffer(Fitsy.getFileSlice(fits.file, hdu.dataseek, hdu.dataseek + hdu.databloks*2880)); + Fitsy.getDataSlice(fits, "asArray", + hdu.dataseek, hdu.dataseek + hdu.databloks*2880, + Fitsy.readImageHDUDataConverter, Fitsy.readError, + fits, hdu, options, handler); + +}; + +var TableTFORM = { + L: { type: "UChar", size: 1 } + , X: { type: "BITS", size: 1 } + , B: { type: "UChar", size: 1 } + , I: { type: "Int16", size: 2 } + , J: { type: "Int32", size: 4 } + , K: { type: "Int64", size: 8 } + , A: { type: "Char", size: 1 } + , E: { type: "Float32", size: 4 } + , D: { type: "Float64", size: 8 } + , C: { type: "Complex64", size: 8 } + , M: { type: "Complex128", size:16 } + , P: { type: "Pointer32", size: 8 } + , Q: { type: "Pointer64", size:16 } +}; + +Fitsy.readError = function(e) { + Fitsy.error("an error occurred while reading the FITS file. (Often this is due to the browser running out of memory.)", e); +}; + +// signal waiting or done waiting +Fitsy.waiting = function(mode){ + if( Fitsy.options.waiting ){ + Fitsy.options.waiting(mode); + } +}; + +// error handler +Fitsy.error = function(s, e) { + Fitsy.waiting(false); + if( Fitsy.options.error ){ + Fitsy.options.error(s, e); + } else { + throw new Error(s); + } +}; + +Fitsy.readForDeCompress = function(fits) { + + var data = new Uint8Array(fits.result); + + if ( data[0] === 0xfd && data[1] === 0x37 && data[2] === 0x7a && data[3] === 0x58 ) { // lzip + if ( window.LZMA !== undefined ) { + + LZMA.decompress(data, function(result) { + fits.file = new Blob([result]); + + // fits.read.onloadend = function(){ Fitsy.readHeaderBlock(fits); }; + // fits.read.onerror = function(){ Fitsy.readError(fits); }; + // fits.read.readAsBinaryString(Fitsy.getFileSlice(fits.file, 0, 2880)); + Fitsy.getDataSlice(fits, "asString", 0, 2880, + Fitsy.readHeaderBlock, Fitsy.readError, + fits); + + + }); + + return; + } + + Fitsy.error("lzip support not available"); + } else if ( data[0] === 0x42 && data[1] === 0x5a ) { // bzip2 + if ( window.bzip2 !== undefined ) { + data = bzip2.simple(bzip2.array(data)); + fits.file = new Blob(data); + } else { + Fitsy.error("bzip2 support not available"); + } + } else if ( data[0] === 0x1f && data[1] === 0x8B ) { // gzip + // we are done with these ... so tell garbage collector + delete fits.file; + delete fits.hdu; + fits.hdu = []; + if ( window.hasOwnProperty("Astroem") ) { + if( data.buffer.byteLength > Fitsy.options.gzfilesize ) { + // new gzip array object + fits.ftype = "gzarray"; + fits.gz = {}; + // temp file in the emscripten file system mapped to the data + fits.gz.arrfile = Astroem.arrfile(fits.name, data); + // open the gzip'ed file + fits.gz.fd = Astroem.gzopen(fits.gz.arrfile.path, "rb"); + // reset file position + fits.gz.here = 0; + // don't know file size, we'll rely on eof + fits.size = -1; + fits.eof = false; + } else { + data = Astroem.decompress(data); + // fits.file = new Blob([data]); + fits.ftype = "array"; + fits.file = data.buffer; + fits.size = fits.file.byteLength; + } + } else if ( window.hasOwnProperty("Zee") ) { + data = Zee.decompress(data); + // fits.file = new Blob([data]); + fits.ftype = "array"; + fits.file = data.buffer; + fits.size = fits.file.byteLength; + } else if ( window.hasOwnProperty("pako") ) { + data = pako.inflate(data); + // fits.file = new Blob([data]); + fits.ftype = "array"; + fits.file = data.buffer; + fits.size = fits.file.byteLength; + } else { + Fitsy.error("gzip support not available"); + } + } else { + + Fitsy.error("not a recognized FITS file (compressed or otherwise): " + fits.name); + + } + + // fits.read.onloadend = function(){ Fitsy.readHeaderBlock(fits); }; + // fits.read.onerror = function(){ Fitsy.readError(fits); }; + // fits.read.readAsBinaryString(Fitsy.getFileSlice(fits.file, 0, 2880)); + Fitsy.getDataSlice(fits, "asString", 0, 2880, + Fitsy.readHeaderBlock, Fitsy.readError, + fits); +}; + +Fitsy.readHeaderBlock = function(fits) { + var i, off, card, pars; + var end = 0; + + // if we hit EOF on last read (usually a gzip'ed file), call the handler + if( fits.eof ){ + // call handler + Fitsy.waiting(false); + fits.handler(fits); + } + + if( !fits.hdu[fits.nhdu] ){ + fits.hdu[fits.nhdu] = {}; + } + var hdu = fits.hdu[fits.nhdu]; + if ( ! hdu.card ) { + // Mark offset in file where header starts. + hdu.headseek = fits.here; + hdu.card = []; + hdu.head = {}; + hdu.ncard = 0; + + hdu.fits = fits; + hdu.nth = fits.nhdu; + + if ( fits.here === 0 && fits.result.slice(0, 6) !== "SIMPLE" ) { + // fits.read.onloadend=function(){ Fitsy.readForDeCompress(fits); }; + // fits.read.readAsArrayBuffer(fits.file); + + // read entire compressed file and ready it for decompression + Fitsy.waiting(true); + // OMG: a delay is required to ensure cursor gets set to waiting + setTimeout(function() { + Fitsy.getDataSlice(fits, "asArray", null, null, + Fitsy.readForDeCompress, Fitsy.readError, + fits); + }, Fitsy.options.wtimeout); + + return; + } + } + if ( fits.here === 0 ) { + if ( fits.result.slice(0, 6) !== "SIMPLE" ) { + return; + } + } else { + if ( hdu.ncard === 0 && fits.result.slice(0, 8) !== "XTENSION" ) { + return; + } + } + + // Read the block advance the file pointer. + fits.here += 2880; + for ( off=0; off < 2880; hdu.ncard++, off += 80 ) { + card = fits.result.slice(off, off+80); + hdu.card[hdu.ncard] = card; + if ( card.slice(0, 8) === "END " ) { + end = 1; + break; + } + pars = Fitsy.cardpars(card); + if ( pars !== undefined ) { + hdu.head[pars[0]] = pars[1]; + } + } + if ( end ) { + hdu.axis = []; + hdu.dataseek = fits.here; // Mark offset in file where data starts. + hdu.naxis = hdu.head.NAXIS; + hdu.bitpix = hdu.head.BITPIX; + hdu.bscale = hdu.head.BSCALE; + hdu.bzero = hdu.head.BZERO; + hdu.pixlbytes = Math.abs(hdu.bitpix)/8; + + if ( hdu.naxis !== 0 ) { + hdu.datapixls = 1; + } else { + hdu.datapixls = 0; + } + + for(i=1; i <= hdu.naxis; i++){ + hdu.axis[i] = hdu.head["NAXIS" + i]; + hdu.datapixls *= hdu.axis[i]; + } + hdu.databytes = hdu.datapixls * hdu.pixlbytes; + hdu.databloks = ((hdu.databytes+(2880-1))/2880) | 0; // |0 is truncate. + fits.here += hdu.databloks * 2880; + fits.nhdu++; + + hdu.type = "image"; + + hdu.filehead = hdu.head; + hdu.filecard = hdu.card; + + if ( hdu.head.XTENSION === "BINTABLE" + || hdu.head.XTENSION === "A3DTABLE" + || hdu.head.XTENSION === "3DTABLE" ) { + + hdu.type = "table"; + + hdu.table = {}; + + hdu.width = hdu.axis[1]; + hdu.length = hdu.axis[2]; + + var form, rept, type, size, width, offs = 0; + + for ( i = 1; i <= hdu.head.TFIELDS; i++ ) { + form = hdu.head["TFORM"+i].match(/([0-9]*)([LXBIJKAEDCMPQ])/); + + rept = form[0] === "" ? 1 : +form[1]; + type = TableTFORM[form[2]].type; + size = TableTFORM[form[2]].size; + width = rept * size; + + hdu.table[hdu.head["TTYPE"+i]] = { + type: type + , size: size, width: width , rept: rept, offs: offs + , unit: hdu.head["TUNIT"+i], disp: hdu.head["TDISP"+i] + , zero: hdu.head["TZERO"+i], scale: hdu.head["TSCAL"+i] + + , min: hdu.head["TDMIN"+i] || hdu.head["TLMIN"+i] + , max: hdu.head["TDMAX"+i] || hdu.head["TLMAX"+i] + , ith: i + }; + offs += width; + } + } + } + if ( (fits.here >= fits.size) && (fits.size !== -1) ) { // EOF? hand the fits file to the handler function + Fitsy.waiting(false); + fits.handler(fits); + } else { // Or, read the next header block + // fits.read.readAsBinaryString(Fitsy.getFileSlice(fits.file, + // fits.here, + // fits.here+2880)); + Fitsy.getDataSlice(fits, "asString", fits.here, fits.here + 2880, + Fitsy.readHeaderBlock, Fitsy.readError, + fits); + } +}; + +Fitsy.fitsopen = function(file, handler) { + var fits = {}; + fits.hdu = []; + fits.read = new FileReader(); + fits.handler = handler; // User callback to complete delivery of FITS data. + if( !file ){ + Fitsy.readError(null); + } + fits.name = file.name; + fits.size = file.size; + fits.file = file; + fits.ftype = "file"; + fits.nhdu = 0; + fits.here = 0; + + // fits.read.onloadend = function(){ Fitsy.readHeaderBlock(fits); }; + // fits.read.readAsBinaryString(Fitsy.getFileSlice(fits.file, 0, 2880)); + Fitsy.getDataSlice(fits, "asString", 0, 2880, + Fitsy.readHeaderBlock, Fitsy.readError, + fits); +}; + + +Fitsy.template = function (str, data) { + + return str.replace(/\{\{([a-zA-Z0-9_.]+)(%([sfd])(\.([0-9]+))?)?\}\}/g, + function (m,key, x, type, y, prec) { + var i, val = data; + + key = key.split("."); + + for ( i = 0; i < key.length; i++ ) { + if ( val.hasOwnProperty(key[i]) ) { val = val[key[i]]; + } else { return ""; } + } + + switch ( type ) { + case "s": break; + case "f": val = val.toFixed(prec); break; + case "d": val = val.toFixed(0); break; + } + + return val; + } + ); +}; + +Fitsy.BinTableTemplate = " \n\ + return function (view, vstart, image, length) { \n\ + var i, x, y; \n\ + \n\ + var xoff = ((-( {{table.x.range}}/2 + ({{table.cx}}-{{table.x.range}}/2 )) {{BinText}}) | 0)\n\ + + (( {{image.nx}}/2 ) | 0); \n\ + var yoff = ((-( {{table.y.range}}/2 + ({{table.cy}}-{{table.x.range}}/2 )) {{BinText}}) | 0)\n\ + + (( {{image.ny}}/2 ) | 0); \n\ + \n\ + for (i = 0; i < length; i++) { \n\ + if( {{FilterText}} ){ \n\ + x = view.get{{table.x.type}}(vstart + i * {{table.width}} + {{table.x.offs}}); \n\ + y = view.get{{table.y.type}}(vstart + i * {{table.width}} + {{table.y.offs}}); \n\ + \n\ + x = (((x - {{table.x.min}}) {{BinText}}) | 0) + xoff; \n\ + y = (((y - {{table.y.min}}) {{BinText}}) | 0) + yoff; \n\ + \n\ + if (x >= 0 && x < {{image.nx}} && y >= 0 && y < {{image.ny}}) { \n\ + image.data[y * {{image.width}} + x] += 1; \n\ + } \n\ + } \n\ + } \n\ +}"; + +Fitsy.readTableHDUDataBinner = function (fits, hdu, nev, options, handler) { + var i, binner, BinText, FilterTemplate; + var FilterText = "true"; + var vstart = 0; + var opttable = options.table || Fitsy.options.table; + + if( !hdu.nev ){ + + hdu.filename = fits.name; + + if( hdu.image && (hdu.image.length >= (opttable.nx * opttable.ny)) ){ + for(i=0; i 0 ) { + if ( hdu.head.SIMPLE || hdu.head.XTENSION === "IMAGE" ) { + Fitsy.readImageHDUData(fits, hdu, options, handler); + break; + } + if ( hdu.table && hdu.head.EXTNAME === events ) { + Fitsy.readTableHDUData(fits, hdu, options, handler); + break; + } + } + } +}; + +Fitsy.handleFITSFile = function(file, options, handler) { // Read the headers. + + if ( options === undefined ) { options = Fitsy.options; } + if ( handler === undefined ) { handler = Fitsy.handler; } + + Fitsy.fitsopen(file, function (fits) { Fitsy.defaultDispatchFITS(fits, options, handler); }); +}; + + +// set default handler for data handler +// +Fitsy.datahandler = function(handler) { Fitsy.handler = handler; }; +Fitsy.dataoptions = function(options) { Fitsy.options = options; }; + +Fitsy.dragenter = function(id, e) { e.stopPropagation(); e.preventDefault(); }; +Fitsy.dragover = function(id, e) { e.stopPropagation(); e.preventDefault(); }; +Fitsy.dragexit = function(id, e) { e.stopPropagation(); e.preventDefault(); }; +Fitsy.dragdrop = function(id, e) { e.stopPropagation(); e.preventDefault(); + + Fitsy.onFile(e.target.files || e.dataTransfer.files, { display: id }); +}; + + +Fitsy.onFile = function(files, options, handler) { + var i; + + for ( i = 0; i < files.length; i++ ) { + if ( files[i].type !== "image/fits" && files[i].type.indexOf("image/") !== -1 ) { + Fitsy.handleImageFile(files[i], options, handler); + } else { + try{ Fitsy.handleFITSFile(files[i], options, handler); } + catch(e){ Fitsy.error("could not load FITS file: " + + files[i].name); } + } + } +}; + + +Fitsy.options = { + maxev: 20480, + gzfilesize: 100 * 1024 * 1024, + gzheapsize: 4 * 1024 * 1024, + xtimeout: 10000, + wtimeout: 100, + table: { nx: 1024, ny: 1024, bin: 1 + , xcol: [ "X", "x" ] + , ycol: [ "Y", "y" ] } +}; + +Fitsy.fetchURL = function(name, url, options, handler) { + var xhr = new XMLHttpRequest(); + + if ( url === undefined ) { + url = name; + name = /([^\\\/]+)$/.exec(url)[1]; + } + options = options || Fitsy.options; + + xhr.open('GET', url, true); + xhr.responseType = 'blob'; + + xhr.onload = function(e) { + var blob; + if ( this.readyState === 4 ) { + if ( this.status === 200 || this.status === 0 ) { + blob = new Blob([this.response]); + blob.name = name; + + if ( options.messages ) { options.messages(""); } + + Fitsy.onFile([blob], options, handler); + } else if( this.status === 404 ) { + Fitsy.error("could not find " + url); + } else { + Fitsy.error("can't load " + url + " (" + this.status + ")"); + } + } + }; + + xhr.onerror = function(e) { + Fitsy.error("can't load " + url); + }; + + xhr.onreadystatechange=function() { + // any response from the server will do + if( xhr.xtimeout ){ + clearTimeout(xhr.xtimeout); + delete xhr.xtimeout; + } + }; + + if ( options.messages ){ + xhr.addEventListener("progress", function(e) { options.messages("progress " + e.loaded.toString()); }); + xhr.addEventListener("error" , function(e) { options.messages("error loading FITS file"); }); + xhr.addEventListener("abort" , function(e) { options.messages("abort while loading FITS file"); }); + } + + try{ xhr.send(); } + catch(e){ Fitsy.error("request to load " + url + " failed", e); } + + // set a timeout to catch when Mac ignores the connect request entirely + xhr.xtimeout=setTimeout(function(){ + Fitsy.error("timeout while waiting for response from server; " + + url + " might not exist"); + }, Fitsy.options.xtimeout); +}; + +Fitsy.handleImageFile = function (file, options, handler) { + if ( options === undefined ) { options = Fitsy.options; } + if ( handler === undefined ) { handler = Fitsy.handler; } + + var reader = new FileReader(); + reader.onload = function ( ev ) { + var img = new Image(); + img.src = ev.target.result; + img.onload = function() { + var x, y, i = 0, brightness; + + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + var h = img.height; + var w = img.width; + + canvas.width = w; + canvas.height = h; + + ctx.drawImage(img, 0, 0); + + var data = ctx.getImageData(0, 0, w, h).data; + var gray = new Float32Array(h*w); + + for ( y = 0; y < h; y++ ) { + for ( x = 0; x < w; x++ ) { + brightness = 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2]; // NTSC + + gray[(h-y)*w+x] = brightness; + i += 4; + } + } + + var hdu = { head: {}, name: file.name + , filedata: gray, image: gray, naxis: 2, axis: [0, w, h], bitpix: -32 }; + + hdu.dmin = Number.MAX_VALUE; + hdu.dmax = Number.MIN_VALUE; + + for ( i = 0; i < h*w; i++ ) { + hdu.dmin = Math.min(hdu.dmin, hdu.image[i]); + hdu.dmax = Math.max(hdu.dmax, hdu.image[i]); + } + + handler(hdu, options); + }; + }; + reader.readAsDataURL(file); +}; + diff --git a/plugins/fitsy/lzma_worker.js b/plugins/fitsy/lzma_worker.js new file mode 100644 index 00000000..0720dd3f --- /dev/null +++ b/plugins/fitsy/lzma_worker.js @@ -0,0 +1,3934 @@ +var LZMA = (function () { + var action_compress = 1, + action_decompress = 2, + action_progress = 3; + + function update_progress(percent, callback_num) { + ///TODO: Calculate ETA. + postMessage({ + action: action_progress, + callback_num: callback_num, + result: percent + }); + } + + var $moduleName, $moduleBase; + + var _, + N8000000000000000_longLit = [0, -9223372036854775808], + N1_longLit = [4294967295, -4294967296], + P0_longLit = [0, 0], + P1_longLit = [1, 0], + P4_longLit = [4, 0], + P1000_longLit = [4096, 0], + Pffffff_longLit = [16777215, 0], + P1000000_longLit = [16777216, 0], + Pff000000_longLit = [4278190080, 0], + Pffffffff_longLit = [4294967295, 0], + P7fffffffffffffff_longLit = [4294967295, 9223372032559808512]; + + function getClass_18() { + return Ljava_lang_Object_2_classLit; + } + + function Object_0() { + } + + _ = Object_0.prototype = {}; + _.getClass$ = getClass_18; + _.typeMarker$ = nullMethod; + _.typeId$ = 1; + function getClass_22() { + return Ljava_lang_Throwable_2_classLit; + } + + function Throwable() { + } + + _ = Throwable.prototype = new Object_0(); + _.getClass$ = getClass_22; + _.typeId$ = 3; + _.detailMessage = null; + function getClass_13() { + return Ljava_lang_Exception_2_classLit; + } + + function Exception() { + } + + _ = Exception.prototype = new Throwable(); + _.getClass$ = getClass_13; + _.typeId$ = 4; + function $RuntimeException(this$static, message) { + this$static.detailMessage = message; + return this$static; + } + + function getClass_19() { + return Ljava_lang_RuntimeException_2_classLit; + } + + function RuntimeException() { + } + + _ = RuntimeException.prototype = new Exception(); + _.getClass$ = getClass_19; + _.typeId$ = 5; + function $JavaScriptException(this$static, e) { + return this$static; + } + + function getClass_0() { + return Lcom_google_gwt_core_client_JavaScriptException_2_classLit; + } + + function JavaScriptException() { + } + + _ = JavaScriptException.prototype = new RuntimeException(); + _.getClass$ = getClass_0; + _.typeId$ = 6; + function $append(a, x) { + a[a.explicitLength++] = x; + } + + function $appendNonNull(a, x) { + a[a.explicitLength++] = x; + } + + function $toString(a) { + var s_0, s; + s_0 = (s = a.join('') , a.length = a.explicitLength = 0 , s); + a[a.explicitLength++] = s_0; + return s_0; + } + + function createFromSeed(seedType, length_0) { + var array = new Array(length_0); + if (seedType > 0) { + var value = [null, 0, false, [0, 0]][seedType]; + for (var i = 0; i < length_0; ++i) { + array[i] = value; + } + } + return array; + } + + function getClass_2() { + return this.arrayClass$; + } + + function initDim(arrayClass, typeId, queryId, length_0, seedType) { + var result; + result = createFromSeed(seedType, length_0); + $clinit_4(); + wrapArray(result, expandoNames_0, expandoValues_0); + result.arrayClass$ = arrayClass; + result.typeId$ = typeId; + result.queryId$ = queryId; + return result; + } + + function initValues(arrayClass, typeId, queryId, array) { + $clinit_4(); + wrapArray(array, expandoNames_0, expandoValues_0); + array.arrayClass$ = arrayClass; + array.typeId$ = typeId; + array.queryId$ = queryId; + return array; + } + + function setCheck(array, index, value) { + if (value != null) { + if (array.queryId$ > 0 && !canCastUnsafe(value.typeId$, array.queryId$)) { + throw new ArrayStoreException(); + } + if (array.queryId$ < 0 && (value.typeMarker$ == nullMethod || value.typeId$ == 2)) { + throw new ArrayStoreException(); + } + } + return array[index] = value; + } + + function Array_0() { + } + + _ = Array_0.prototype = new Object_0(); + _.getClass$ = getClass_2; + _.typeId$ = 0; + _.arrayClass$ = null; + _.length = 0; + _.queryId$ = 0; + function $clinit_4() { + $clinit_4 = nullMethod; + expandoNames_0 = []; + expandoValues_0 = []; + initExpandos(new Array_0(), expandoNames_0, expandoValues_0); + } + + function initExpandos(protoType, expandoNames, expandoValues) { + var i = 0, value; + for (var name_0 in protoType) { + if (value = protoType[name_0]) { + expandoNames[i] = name_0; + expandoValues[i] = value; + ++i; + } + } + } + + function wrapArray(array, expandoNames, expandoValues) { + $clinit_4(); + for (var i = 0, c = expandoNames.length; i < c; ++i) { + array[expandoNames[i]] = expandoValues[i]; + } + } + + var expandoNames_0, expandoValues_0; + function canCast(srcId, dstId) { + return srcId && !!typeIdArray[srcId][dstId]; + } + + function canCastUnsafe(srcId, dstId) { + return srcId && typeIdArray[srcId][dstId]; + } + + function dynamicCast(src, dstId) { + if (src != null && !canCastUnsafe(src.typeId$, dstId)) { + throw new ClassCastException(); + } + return src; + } + + function instanceOf(src, dstId) { + return src != null && canCast(src.typeId$, dstId); + } + + function round_int(x) { + return ~~Math.max(Math.min(x, 2147483647), -2147483648); + } + + var typeIdArray = [ + {}, + {}, + {1:1}, + {2:1}, + {2:1}, + {2:1}, + {2:1}, + {2:1, 10:1}, + {2:1}, + {2:1}, + {2:1}, + {2:1}, + {2:1}, + {2:1, 11:1}, + {2:1}, + {2:1}, + {2:1}, + {4:1}, + {5:1}, + {6:1}, + {7:1}, + {8:1}, + {9:1} + ]; + + function caught(e) { + if (e != null && canCast(e.typeId$, 2)) { + return e; + } + return $JavaScriptException(new JavaScriptException(), e); + } + + function add(a, b) { + var newHigh, newLow; + newHigh = a[1] + b[1]; + newLow = a[0] + b[0]; + return create(newLow, newHigh); + } + + function addTimes(accum, a, b) { + if (a == 0) { + return accum; + } + if (b == 0) { + return accum; + } + return add(accum, create(a * b, 0)); + } + + function and(a, b) { + return makeFromBits(~~Math.max(Math.min(a[1] / 4294967296, 2147483647), -2147483648) & ~~Math.max(Math.min(b[1] / 4294967296, 2147483647), -2147483648), lowBits_0(a) & lowBits_0(b)); + } + + function compare(a, b) { + var nega, negb; + if (a[0] == b[0] && a[1] == b[1]) { + return 0; + } + nega = a[1] < 0; + negb = b[1] < 0; + if (nega && !negb) { + return -1; + } + if (!nega && negb) { + return 1; + } + if (sub(a, b)[1] < 0) { + return -1; + } + else { + return 1; + } + } + + function create(valueLow, valueHigh) { + var diffHigh, diffLow; + valueHigh %= 1.8446744073709552E19; + valueLow %= 1.8446744073709552E19; + diffHigh = valueHigh % 4294967296; + diffLow = Math.floor(valueLow / 4294967296) * 4294967296; + valueHigh = valueHigh - diffHigh + diffLow; + valueLow = valueLow - diffLow + diffHigh; + while (valueLow < 0) { + valueLow += 4294967296; + valueHigh -= 4294967296; + } + while (valueLow > 4294967295) { + valueLow -= 4294967296; + valueHigh += 4294967296; + } + valueHigh = valueHigh % 1.8446744073709552E19; + while (valueHigh > 9223372032559808512) { + valueHigh -= 1.8446744073709552E19; + } + while (valueHigh < -9223372036854775808) { + valueHigh += 1.8446744073709552E19; + } + return [valueLow, valueHigh]; + } + + function div(a, b) { + var approx, deltaRem, deltaResult, halfa, rem, result; + if (b[0] == 0 && b[1] == 0) { + throw $ArithmeticException(new ArithmeticException(), '/ by zero'); + } + if (a[0] == 0 && a[1] == 0) { + return $clinit_10() , ZERO; + } + if (eq(a, ($clinit_10() , MIN_VALUE))) { + if (eq(b, ONE) || eq(b, NEG_ONE)) { + return MIN_VALUE; + } + halfa = shr(a, 1); + approx = shl(div(halfa, b), 1); + rem = sub(a, mul(b, approx)); + return add(approx, div(rem, b)); + } + if (eq(b, MIN_VALUE)) { + return ZERO; + } + if (a[1] < 0) { + if (b[1] < 0) { + return div(neg(a), neg(b)); + } else { + return neg(div(neg(a), b)); + } + } + if (b[1] < 0) { + return neg(div(a, neg(b))); + } + result = ZERO; + rem = a; + while (compare(rem, b) >= 0) { + deltaResult = fromDouble(Math.floor(toDoubleRoundDown(rem) / toDoubleRoundUp(b))); + if (deltaResult[0] == 0 && deltaResult[1] == 0) { + deltaResult = ONE; + } + deltaRem = mul(deltaResult, b); + result = add(result, deltaResult); + rem = sub(rem, deltaRem); + } + return result; + } + + function eq(a, b) { + return a[0] == b[0] && a[1] == b[1]; + } + + function fromDouble(value) { + if (isNaN(value)) { + return $clinit_10() , ZERO; + } + if (value < -9223372036854775808) { + return $clinit_10() , MIN_VALUE; + } + if (value >= 9223372036854775807) { + return $clinit_10() , MAX_VALUE; + } + if (value > 0) { + return create(Math.floor(value), 0); + } else { + return create(Math.ceil(value), 0); + } + } + + function fromInt(value) { + var rebase, result; + if (value > -129 && value < 128) { + rebase = value + 128; + result = ($clinit_9() , boxedValues)[rebase]; + if (result == null) { + result = boxedValues[rebase] = internalFromInt(value); + } + return result; + } + return internalFromInt(value); + } + + function internalFromInt(value) { + if (value >= 0) { + return [value, 0]; + } else { + return [value + 4294967296, -4294967296]; + } + } + + function lowBits_0(a) { + if (a[0] >= 2147483648) { + return ~~Math.max(Math.min(a[0] - 4294967296, 2147483647), -2147483648); + } else { + return ~~Math.max(Math.min(a[0], 2147483647), -2147483648); + } + } + + function makeFromBits(highBits, lowBits) { + var high, low; + high = highBits * 4294967296; + low = lowBits; + if (lowBits < 0) { + low += 4294967296; + } + return [low, high]; + } + + function mul(a, b) { + var a1, a2, a3, a4, b1, b2, b3, b4, res; + if (a[0] == 0 && a[1] == 0) { + return $clinit_10() , ZERO; + } + if (b[0] == 0 && b[1] == 0) { + return $clinit_10() , ZERO; + } + if (eq(a, ($clinit_10() , MIN_VALUE))) { + return multByMinValue(b); + } + if (eq(b, MIN_VALUE)) { + return multByMinValue(a); + } + if (a[1] < 0) { + if (b[1] < 0) { + return mul(neg(a), neg(b)); + } else { + return neg(mul(neg(a), b)); + } + } + if (b[1] < 0) { + return neg(mul(a, neg(b))); + } + if (compare(a, TWO_PWR_24) < 0 && compare(b, TWO_PWR_24) < 0) { + return create((a[1] + a[0]) * (b[1] + b[0]), 0); + } + a3 = a[1] % 281474976710656; + a4 = a[1] - a3; + a1 = a[0] % 65536; + a2 = a[0] - a1; + b3 = b[1] % 281474976710656; + b4 = b[1] - b3; + b1 = b[0] % 65536; + b2 = b[0] - b1; + res = ZERO; + res = addTimes(res, a4, b1); + res = addTimes(res, a3, b2); + res = addTimes(res, a3, b1); + res = addTimes(res, a2, b3); + res = addTimes(res, a2, b2); + res = addTimes(res, a2, b1); + res = addTimes(res, a1, b4); + res = addTimes(res, a1, b3); + res = addTimes(res, a1, b2); + res = addTimes(res, a1, b1); + return res; + } + + function multByMinValue(a) { + if ((lowBits_0(a) & 1) == 1) { + return $clinit_10() , MIN_VALUE; + } else { + return $clinit_10() , ZERO; + } + } + + function neg(a) { + var newHigh, newLow; + if (eq(a, ($clinit_10() , MIN_VALUE))) { + return MIN_VALUE; + } + newHigh = -a[1]; + newLow = -a[0]; + if (newLow > 4294967295) { + newLow -= 4294967296; + newHigh += 4294967296; + } + if (newLow < 0) { + newLow += 4294967296; + newHigh -= 4294967296; + } + return [newLow, newHigh]; + } + + function pwrAsDouble(n) { + if (n <= 30) { + return 1 << n; + } else { + return pwrAsDouble(30) * pwrAsDouble(n - 30); + } + } + + function shl(a, n) { + var diff, newHigh, newLow, twoToN; + n &= 63; + if (eq(a, ($clinit_10() , MIN_VALUE))) { + if (n == 0) { + return a; + } else { + return ZERO; + } + } + if (a[1] < 0) { + return neg(shl(neg(a), n)); + } + twoToN = pwrAsDouble(n); + newHigh = a[1] * twoToN % 1.8446744073709552E19; + newLow = a[0] * twoToN; + diff = newLow - newLow % 4294967296; + newHigh += diff; + newLow -= diff; + if (newHigh >= 9223372036854775807) { + newHigh -= 1.8446744073709552E19; + } + return [newLow, newHigh]; + } + + function shr(a, n) { + var newHigh, newLow, shiftFact; + n &= 63; + shiftFact = pwrAsDouble(n); + newHigh = a[1] / shiftFact; + newLow = Math.floor(a[0] / shiftFact); + return create(newLow, newHigh); + } + + function shru(a, n) { + var sr; + n &= 63; + sr = shr(a, n); + if (a[1] < 0) { + sr = add(sr, shl(($clinit_10() , TWO), 63 - n)); + } + return sr; + } + + function sub(a, b) { + var newHigh, newLow; + newHigh = a[1] - b[1]; + newLow = a[0] - b[0]; + return create(newLow, newHigh); + } + + function toDoubleRoundDown(a) { + var diff, magnitute, toSubtract; + magnitute = round_int(Math.log(a[1]) / ($clinit_10() , LN_2)); + if (magnitute <= 48) { + return a[1] + a[0]; + } else { + diff = magnitute - 48; + toSubtract = (1 << diff) - 1; + return a[1] + (a[0] - toSubtract); + } + } + + function toDoubleRoundUp(a) { + var diff, magnitute, toAdd; + magnitute = round_int(Math.log(a[1]) / ($clinit_10() , LN_2)); + if (magnitute <= 48) { + return a[1] + a[0]; + } else { + diff = magnitute - 48; + toAdd = (1 << diff) - 1; + return a[1] + (a[0] + toAdd); + } + } + + function toString_0(a) { + var digits, rem, remDivTenPower, res, tenPowerLong, zeroesNeeded; + if (a[0] == 0 && a[1] == 0) { + return '0'; + } + if (eq(a, ($clinit_10() , MIN_VALUE))) { + return '-9223372036854775808'; + } + if (a[1] < 0) { + return '-' + toString_0(neg(a)); + } + rem = a; + res = ''; + while (!(rem[0] == 0 && rem[1] == 0)) { + tenPowerLong = fromInt(1000000000); + remDivTenPower = div(rem, tenPowerLong); + digits = '' + lowBits_0(sub(rem, mul(remDivTenPower, tenPowerLong))); + rem = remDivTenPower; + if (!(rem[0] == 0 && rem[1] == 0)) { + zeroesNeeded = 9 - digits.length; + for (; zeroesNeeded > 0; --zeroesNeeded) { + digits = '0' + digits; + } + } + res = digits + res; + } + return res; + } + + function $clinit_9() { + $clinit_9 = nullMethod; + boxedValues = initDim(_3_3D_classLit, 0, 9, 256, 0); + } + + var boxedValues; + function $clinit_10() { + $clinit_10 = nullMethod; + LN_2 = Math.log(2); + MAX_VALUE = P7fffffffffffffff_longLit; + MIN_VALUE = N8000000000000000_longLit; + NEG_ONE = fromInt(-1); + ONE = fromInt(1); + TWO = fromInt(2); + TWO_PWR_24 = P1000000_longLit; + ZERO = fromInt(0); + } + + var LN_2, MAX_VALUE, MIN_VALUE, NEG_ONE, ONE, TWO, TWO_PWR_24, ZERO; + function getClass_6() { + return Ljava_io_InputStream_2_classLit; + } + + function InputStream() { + } + + _ = InputStream.prototype = new Object_0(); + _.getClass$ = getClass_6; + _.typeId$ = 0; + function $ByteArrayInputStream(this$static, buf) { + $ByteArrayInputStream_0(this$static, buf, 0, buf.length); + return this$static; + } + + function $ByteArrayInputStream_0(this$static, buf, off, len) { + this$static.buf = buf; + this$static.pos = off; + this$static.count = off + len; + if (this$static.count > buf.length) + this$static.count = buf.length; + return this$static; + } + + function $read(this$static) { + if (this$static.pos >= this$static.count) + return -1; + return this$static.buf[this$static.pos++] & 255; + } + + function $read_0(this$static, buf, off, len) { + if (this$static.pos >= this$static.count) + return -1; + len = min(len, this$static.count - this$static.pos); + arraycopy(this$static.buf, this$static.pos, buf, off, len); + this$static.pos += len; + return len; + } + + function getClass_3() { + return Ljava_io_ByteArrayInputStream_2_classLit; + } + + function ByteArrayInputStream() { + } + + _ = ByteArrayInputStream.prototype = new InputStream(); + _.getClass$ = getClass_3; + _.typeId$ = 0; + _.buf = null; + _.count = 0; + _.pos = 0; + function getClass_7() { + return Ljava_io_OutputStream_2_classLit; + } + + function OutputStream() { + } + + _ = OutputStream.prototype = new Object_0(); + _.getClass$ = getClass_7; + _.typeId$ = 0; + function $ByteArrayOutputStream(this$static) { + this$static.buf = initDim(_3B_classLit, 0, -1, 32, 1); + return this$static; + } + + function $ensureCapacity(this$static, len) { + var newbuf; + if (len <= this$static.buf.length) + return; + len = max(len, this$static.buf.length * 2); + newbuf = initDim(_3B_classLit, 0, -1, len, 1); + arraycopy(this$static.buf, 0, newbuf, 0, this$static.buf.length); + this$static.buf = newbuf; + } + + function $toByteArray(this$static) { + var data; + data = initDim(_3B_classLit, 0, -1, this$static.count, 1); + arraycopy(this$static.buf, 0, data, 0, this$static.count); + return data; + } + + function $write(this$static, b) { + $ensureCapacity(this$static, this$static.count + 1); + this$static.buf[this$static.count++] = b << 24 >> 24; + } + + function $write_0(this$static, buf, off, len) { + $ensureCapacity(this$static, this$static.count + len); + arraycopy(buf, off, this$static.buf, this$static.count, len); + this$static.count += len; + } + + function getClass_4() { + return Ljava_io_ByteArrayOutputStream_2_classLit; + } + + function ByteArrayOutputStream() { + } + + _ = ByteArrayOutputStream.prototype = new OutputStream(); + _.getClass$ = getClass_4; + _.typeId$ = 0; + _.buf = null; + _.count = 0; + function $IOException(this$static, message) { + this$static.detailMessage = message; + return this$static; + } + + function getClass_5() { + return Ljava_io_IOException_2_classLit; + } + + function IOException() { + } + + _ = IOException.prototype = new Exception(); + _.getClass$ = getClass_5; + _.typeId$ = 7; + function $ArithmeticException(this$static, explanation) { + this$static.detailMessage = explanation; + return this$static; + } + + function getClass_8() { + return Ljava_lang_ArithmeticException_2_classLit; + } + + function ArithmeticException() { + } + + _ = ArithmeticException.prototype = new RuntimeException(); + _.getClass$ = getClass_8; + _.typeId$ = 8; + function $ArrayStoreException(this$static, message) { + this$static.detailMessage = message; + return this$static; + } + + function getClass_9() { + return Ljava_lang_ArrayStoreException_2_classLit; + } + + function ArrayStoreException() { + } + + _ = ArrayStoreException.prototype = new RuntimeException(); + _.getClass$ = getClass_9; + _.typeId$ = 9; + function createForArray(packageName, className) { + var clazz; + clazz = new Class(); + clazz.typeName = packageName + className; + return clazz; + } + + function createForClass(packageName, className) { + var clazz; + clazz = new Class(); + clazz.typeName = packageName + className; + return clazz; + } + + function createForEnum(packageName, className) { + var clazz; + clazz = new Class(); + clazz.typeName = packageName + className; + return clazz; + } + + function getClass_11() { + return Ljava_lang_Class_2_classLit; + } + + function Class() { + } + + _ = Class.prototype = new Object_0(); + _.getClass$ = getClass_11; + _.typeId$ = 0; + _.typeName = null; + function getClass_10() { + return Ljava_lang_ClassCastException_2_classLit; + } + + function ClassCastException() { + } + + _ = ClassCastException.prototype = new RuntimeException(); + _.getClass$ = getClass_10; + _.typeId$ = 12; + function getClass_12() { + return Ljava_lang_Enum_2_classLit; + } + + function Enum() { + } + + _ = Enum.prototype = new Object_0(); + _.getClass$ = getClass_12; + _.typeId$ = 0; + function $IllegalArgumentException(this$static, message) { + this$static.detailMessage = message; + return this$static; + } + + function getClass_14() { + return Ljava_lang_IllegalArgumentException_2_classLit; + } + + function IllegalArgumentException() { + } + + _ = IllegalArgumentException.prototype = new RuntimeException(); + _.getClass$ = getClass_14; + _.typeId$ = 13; + function getClass_15() { + return Ljava_lang_IllegalStateException_2_classLit; + } + + function IllegalStateException() { + } + + _ = IllegalStateException.prototype = new RuntimeException(); + _.getClass$ = getClass_15; + _.typeId$ = 14; + function getClass_16() { + return Ljava_lang_IndexOutOfBoundsException_2_classLit; + } + + function IndexOutOfBoundsException() { + } + + _ = IndexOutOfBoundsException.prototype = new RuntimeException(); + _.getClass$ = getClass_16; + _.typeId$ = 15; + function max(x, y) { + return x > y?x:y; + } + + function min(x, y) { + return x < y?x:y; + } + + function getClass_17() { + return Ljava_lang_NullPointerException_2_classLit; + } + + function NullPointerException() { + } + + _ = NullPointerException.prototype = new RuntimeException(); + _.getClass$ = getClass_17; + _.typeId$ = 16; + function $equals(this$static, other) { + if (other == null) { + return false; + } + return String(this$static) == other; + } + + function $getChars(this$static, srcBegin, srcEnd, dst, dstBegin) { + var srcIdx; + for (srcIdx = srcBegin; srcIdx < srcEnd; ++srcIdx) { + dst[dstBegin++] = this$static.charCodeAt(srcIdx); + } + } + + function getClass_21() { + return Ljava_lang_String_2_classLit; + } + + _ = String.prototype; + _.getClass$ = getClass_21; + _.typeId$ = 2; + function $StringBuilder(this$static) { + var array; + this$static.data = (array = [] , array.explicitLength = 0 , array); + return this$static; + } + + function getClass_20() { + return Ljava_lang_StringBuilder_2_classLit; + } + + function StringBuilder() { + } + + _ = StringBuilder.prototype = new Object_0(); + _.getClass$ = getClass_20; + _.typeId$ = 0; + function arraycopy(src, srcOfs, dest, destOfs, len) { + var destArray, destEnd, destTypeName, destlen, i, srcArray, srcTypeName, srclen; + + if (src == null || dest == null) { + throw new NullPointerException(); + } + + srcTypeName = (src.typeMarker$ == nullMethod || src.typeId$ == 2 ? src.getClass$() : Lcom_google_gwt_core_client_JavaScriptObject_2_classLit).typeName; + destTypeName = (dest.typeMarker$ == nullMethod || dest.typeId$ == 2 ? dest.getClass$() : Lcom_google_gwt_core_client_JavaScriptObject_2_classLit).typeName; + + if (srcTypeName.charCodeAt(0) != 91 || destTypeName.charCodeAt(0) != 91) { + throw $ArrayStoreException(new ArrayStoreException(), 'Must be array types'); + } + if (srcTypeName.charCodeAt(1) != destTypeName.charCodeAt(1)) { + throw $ArrayStoreException(new ArrayStoreException(), 'Array types must match'); + } + + srclen = src.length; + destlen = dest.length; + if (srcOfs < 0 || destOfs < 0 || len < 0 || srcOfs + len > srclen || destOfs + len > destlen) { + throw new IndexOutOfBoundsException(); + } + if ((srcTypeName.charCodeAt(1) == 76 || srcTypeName.charCodeAt(1) == 91) && !$equals(srcTypeName, destTypeName)) { + srcArray = dynamicCast(src, 3); + destArray = dynamicCast(dest, 3); + if ((src == null ? null : src) === (dest == null ? null : dest) && srcOfs < destOfs) { + srcOfs += len; + for (destEnd = destOfs + len; destEnd-- > destOfs;) { + setCheck(destArray, destEnd, srcArray[--srcOfs]); + } + } else { + for (destEnd = destOfs + len; destOfs < destEnd;) { + setCheck(destArray, destOfs++, srcArray[srcOfs++]); + } + } + } else { + for (i = 0; i < len; ++i) { + dest[destOfs + i] = src[srcOfs + i] + } + } + } + + + function $configure(this$static, encoder) { + if (!$SetDictionarySize_0(encoder, 1 << this$static.dictionarySize)) + throw $RuntimeException(new RuntimeException(), 'unexpected failure'); + if (!$SetNumFastBytes(encoder, this$static.fb)) + throw $RuntimeException(new RuntimeException(), 'unexpected failure'); + if (!$SetMatchFinder(encoder, this$static.matchFinder)) + throw $RuntimeException(new RuntimeException(), 'unexpected failure'); + if (!$SetLcLpPb_0(encoder, this$static.lc, this$static.lp, this$static.pb)) + throw $RuntimeException(new RuntimeException(), 'unexpected failure'); + } + + function getClass_23() { + return Lorg_dellroad_lzma_client_CompressionMode_2_classLit; + } + + function CompressionMode() { + } + + _ = CompressionMode.prototype = new Enum(); + _.getClass$ = getClass_23; + _.typeId$ = 0; + _.dictionarySize = 0; + _.fb = 0; + _.lc = 0; + _.lp = 0; + _.matchFinder = 0; + _.pb = 0; + + function $execute(this$static) { + var $e0; + try { + return $processChunk(this$static.chunker); + } + catch ($e0) { + $e0 = caught($e0); + if (instanceOf($e0, 10)) { + return false; + } else { + throw $e0; + } + } + } + + function $init(this$static, input, output, length_0, mode) { + var encoder, i; + if (!mode) + throw $IllegalArgumentException(new IllegalArgumentException(), 'null mode'); + if (compare(length_0, N1_longLit) < 0) + throw $IllegalArgumentException(new IllegalArgumentException(), 'invalid length ' + toString_0(length_0)); + this$static.length_0 = length_0; + encoder = $Encoder(new Encoder()); + $configure(mode, encoder); + encoder._writeEndMark = true; + $WriteCoderProperties(encoder, output); + for (i = 0; i < 64; i += 8) + $write(output, lowBits_0(shr(length_0, i)) & 255); + this$static.chunker = (encoder._needReleaseMFStream = false , (encoder._inStream = input , encoder._finished = false , $Create_2(encoder) , encoder._rangeEncoder.Stream = output , $Init_4(encoder) , $FillDistancesPrices(encoder) , $FillAlignPrices(encoder) , encoder._lenEncoder._tableSize = encoder._numFastBytes + 1 - 2 , $UpdateTables(encoder._lenEncoder, 1 << encoder._posStateBits) , encoder._repMatchLenEncoder._tableSize = encoder._numFastBytes + 1 - 2 , $UpdateTables(encoder._repMatchLenEncoder, 1 << encoder._posStateBits) , encoder.nowPos64 = P0_longLit , undefined) , $Chunker_0(new Chunker(), encoder)); + } + + function getClass_26() { + return Lorg_dellroad_lzma_client_LZMACompressor_2_classLit; + } + + function LZMACompressor() { + } + + _ = LZMACompressor.prototype = new Object_0(); + _.getClass$ = getClass_26; + _.typeId$ = 0; + _.chunker = null; + + function $LZMAByteArrayCompressor(this$static, data, mode) { + var $e0; + this$static.output = $ByteArrayOutputStream(new ByteArrayOutputStream()); + try { + $init(this$static, $ByteArrayInputStream(new ByteArrayInputStream(), data), this$static.output, fromInt(data.length), mode); + } catch ($e0) { + $e0 = caught($e0); + if (instanceOf($e0, 10)) { + throw $RuntimeException(new RuntimeException(), 'impossible exception'); + } else { + throw $e0; + } + } + return this$static; + } + + function getClass_24() { + return Lorg_dellroad_lzma_client_LZMAByteArrayCompressor_2_classLit; + } + + function LZMAByteArrayCompressor() { + } + + _ = LZMAByteArrayCompressor.prototype = new LZMACompressor(); + _.getClass$ = getClass_24; + _.typeId$ = 0; + _.output = null; + function $execute_0(this$static) { + var $e0, e; + try { + return $processChunk(this$static.chunker); + } + catch ($e0) { + $e0 = caught($e0); + if (instanceOf($e0, 10)) { + e = $e0; + this$static.exception = e; + return false; + } else { + throw $e0; + } + } + } + + function $init_0(this$static, input, output) { + var decoder, + hex_length = "", + i, + properties, + r, + tmp_length; + + properties = initDim(_3B_classLit, 0, -1, 5, 1); + for (i = 0; i < properties.length; ++i) { + r = $read(input); + if (r == -1) + throw $IOException(new IOException(), 'truncated input'); + properties[i] = r << 24 >> 24; + } + decoder = $Decoder(new Decoder()); + if (!$SetDecoderProperties(decoder, properties)) + throw $IOException(new IOException(), 'corrupted input'); + + for (i = 0; i < 64; i += 8) { + r = $read(input); + if (r == -1) + throw $IOException(new IOException(), 'truncated input'); + r = r.toString(16); + if (r.length == 1) r = "0" + r; + hex_length = r + "" + hex_length; + } + + /// Was the length set in the header (if it was compressed from a stream, the length is all f's). + if (/^0+$|^f+$/i.test(hex_length)) { + /// The length is unknown, so set to -1. + this$static.length_0 = N1_longLit; + } else { + ///NOTE: If there is a problem with the decoder because of the length, you can always set the length to -1 (N1_longLit) which means unknown. + tmp_length = parseInt(hex_length, 16); + /// If the length is too long to handle, just set it to unknown. + if (tmp_length > 4294967295) { + this$static.length_0 = N1_longLit; + } else { + this$static.length_0 = fromDouble(tmp_length); + } + } + + this$static.chunker = $CodeInChunks(decoder, input, output, this$static.length_0); + } + + function getClass_27() { + return Lorg_dellroad_lzma_client_LZMADecompressor_2_classLit; + } + + function LZMADecompressor() { + } + + _ = LZMADecompressor.prototype = new Object_0(); + _.getClass$ = getClass_27; + _.typeId$ = 0; + _.chunker = null; + _.exception = null; + _.length_0 = P0_longLit; + function $LZMAByteArrayDecompressor(this$static, data) { + this$static.output = $ByteArrayOutputStream(new ByteArrayOutputStream()); + $init_0(this$static, $ByteArrayInputStream(new ByteArrayInputStream(), data), this$static.output); + return this$static; + } + + function getClass_25() { + return Lorg_dellroad_lzma_client_LZMAByteArrayDecompressor_2_classLit; + } + + function LZMAByteArrayDecompressor() { + } + + _ = LZMAByteArrayDecompressor.prototype = new LZMADecompressor(); + _.getClass$ = getClass_25; + _.typeId$ = 0; + _.output = null; + function $Create_4(this$static, keepSizeBefore, keepSizeAfter, keepSizeReserv) { + var blockSize; + this$static._keepSizeBefore = keepSizeBefore; + this$static._keepSizeAfter = keepSizeAfter; + blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; + if (this$static._bufferBase == null || this$static._blockSize != blockSize) { + this$static._bufferBase = null; + this$static._blockSize = blockSize; + this$static._bufferBase = initDim(_3B_classLit, 0, -1, this$static._blockSize, 1); + } + this$static._pointerToLastSafePosition = this$static._blockSize - keepSizeAfter; + } + + function $GetIndexByte(this$static, index) { + return this$static._bufferBase[this$static._bufferOffset + this$static._pos + index]; + } + + function $GetMatchLen(this$static, index, distance, limit) { + var i, pby; + if (this$static._streamEndWasReached) { + if (this$static._pos + index + limit > this$static._streamPos) { + limit = this$static._streamPos - (this$static._pos + index); + } + } + ++distance; + pby = this$static._bufferOffset + this$static._pos + index; + for (i = 0; i < limit && this$static._bufferBase[pby + i] == this$static._bufferBase[pby + i - distance]; ++i) { + } + return i; + } + + function $GetNumAvailableBytes(this$static) { + return this$static._streamPos - this$static._pos; + } + + function $MoveBlock(this$static) { + var i, numBytes, offset; + offset = this$static._bufferOffset + this$static._pos - this$static._keepSizeBefore; + if (offset > 0) { + --offset; + } + numBytes = this$static._bufferOffset + this$static._streamPos - offset; + for (i = 0; i < numBytes; ++i) { + this$static._bufferBase[i] = this$static._bufferBase[offset + i]; + } + this$static._bufferOffset -= offset; + } + + function $MovePos_1(this$static) { + var pointerToPostion; + ++this$static._pos; + if (this$static._pos > this$static._posLimit) { + pointerToPostion = this$static._bufferOffset + this$static._pos; + if (pointerToPostion > this$static._pointerToLastSafePosition) { + $MoveBlock(this$static); + } + $ReadBlock(this$static); + } + } + + function $ReadBlock(this$static) { + var numReadBytes, pointerToPostion, size; + if (this$static._streamEndWasReached) + return; + while (true) { + size = -this$static._bufferOffset + this$static._blockSize - this$static._streamPos; + if (size == 0) + return; + numReadBytes = $read_0(this$static._stream, this$static._bufferBase, this$static._bufferOffset + this$static._streamPos, size); + if (numReadBytes == -1) { + this$static._posLimit = this$static._streamPos; + pointerToPostion = this$static._bufferOffset + this$static._posLimit; + if (pointerToPostion > this$static._pointerToLastSafePosition) { + this$static._posLimit = this$static._pointerToLastSafePosition - this$static._bufferOffset; + } + this$static._streamEndWasReached = true; + return; + } + this$static._streamPos += numReadBytes; + if (this$static._streamPos >= this$static._pos + this$static._keepSizeAfter) { + this$static._posLimit = this$static._streamPos - this$static._keepSizeAfter; + } + } + } + + function $ReduceOffsets(this$static, subValue) { + this$static._bufferOffset += subValue; + this$static._posLimit -= subValue; + this$static._pos -= subValue; + this$static._streamPos -= subValue; + } + + function getClass_40() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZ_InWindow_2_classLit; + } + + function InWindow() { + } + + _ = InWindow.prototype = new Object_0(); + _.getClass$ = getClass_40; + _.typeId$ = 0; + _._blockSize = 0; + _._bufferBase = null; + _._bufferOffset = 0; + _._keepSizeAfter = 0; + _._keepSizeBefore = 0; + _._pointerToLastSafePosition = 0; + _._pos = 0; + _._posLimit = 0; + _._stream = null; + _._streamEndWasReached = false; + _._streamPos = 0; + function $clinit_60() { + $clinit_60 = nullMethod; + var i, j, r; + CrcTable = initDim(_3I_classLit, 0, -1, 256, 1); + for (i = 0; i < 256; ++i) { + r = i; + for (j = 0; j < 8; ++j) + if ((r & 1) != 0) { + r = r >>> 1 ^ -306674912; + } else { + r >>>= 1; + } + CrcTable[i] = r; + } + } + + function $Create_3(this$static, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter) { + var cyclicBufferSize, hs, windowReservSize; + if (historySize > 1073741567) { + return false; + } + + this$static._cutValue = 16 + (matchMaxLen >> 1); + windowReservSize = ~~((historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2) + 256; + $Create_4(this$static, historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); + this$static._matchMaxLen = matchMaxLen; + cyclicBufferSize = historySize + 1; + if (this$static._cyclicBufferSize != cyclicBufferSize) { + this$static._son = initDim(_3I_classLit, 0, -1, (this$static._cyclicBufferSize = cyclicBufferSize) * 2, 1); + } + + hs = 65536; + if (this$static.HASH_ARRAY) { + hs = historySize - 1; + hs |= hs >> 1; + hs |= hs >> 2; + hs |= hs >> 4; + hs |= hs >> 8; + hs >>= 1; + hs |= 65535; + if (hs > 16777216) + hs >>= 1; + this$static._hashMask = hs; + ++hs; + hs += this$static.kFixHashSize; + } + + if (hs != this$static._hashSizeSum) { + this$static._hash = initDim(_3I_classLit, 0, -1, this$static._hashSizeSum = hs, 1); + } + return true; + } + + function $GetMatches(this$static, distances) { + var count, cur, curMatch, curMatch2, curMatch3, cyclicPos, delta, hash2Value, hash3Value, hashValue, len, len0, len1, lenLimit, matchMinPos, maxLen, offset, pby1, ptr0, ptr1, temp; + if (this$static._pos + this$static._matchMaxLen <= this$static._streamPos) { + lenLimit = this$static._matchMaxLen; + } else { + lenLimit = this$static._streamPos - this$static._pos; + if (lenLimit < this$static.kMinMatchCheck) { + $MovePos_0(this$static); + return 0; + } + } + offset = 0; + matchMinPos = this$static._pos > this$static._cyclicBufferSize?this$static._pos - this$static._cyclicBufferSize:0; + cur = this$static._bufferOffset + this$static._pos; + maxLen = 1; + hash2Value = 0; + hash3Value = 0; + if (this$static.HASH_ARRAY) { + temp = CrcTable[this$static._bufferBase[cur] & 255] ^ this$static._bufferBase[cur + 1] & 255; + hash2Value = temp & 1023; + temp ^= (this$static._bufferBase[cur + 2] & 255) << 8; + hash3Value = temp & 65535; + hashValue = (temp ^ CrcTable[this$static._bufferBase[cur + 3] & 255] << 5) & this$static._hashMask; + } else { + hashValue = this$static._bufferBase[cur] & 255 ^ (this$static._bufferBase[cur + 1] & 255) << 8; + } + + curMatch = this$static._hash[this$static.kFixHashSize + hashValue]; + if (this$static.HASH_ARRAY) { + curMatch2 = this$static._hash[hash2Value]; + curMatch3 = this$static._hash[1024 + hash3Value]; + this$static._hash[hash2Value] = this$static._pos; + this$static._hash[1024 + hash3Value] = this$static._pos; + if (curMatch2 > matchMinPos) { + if (this$static._bufferBase[this$static._bufferOffset + curMatch2] == this$static._bufferBase[cur]) { + distances[offset++] = maxLen = 2; + distances[offset++] = this$static._pos - curMatch2 - 1; + } + } + if (curMatch3 > matchMinPos) { + if (this$static._bufferBase[this$static._bufferOffset + curMatch3] == this$static._bufferBase[cur]) { + if (curMatch3 == curMatch2) { + offset -= 2; + } + distances[offset++] = maxLen = 3; + distances[offset++] = this$static._pos - curMatch3 - 1; + curMatch2 = curMatch3; + } + } + if (offset != 0 && curMatch2 == curMatch) { + offset -= 2; + maxLen = 1; + } + } + this$static._hash[this$static.kFixHashSize + hashValue] = this$static._pos; + ptr0 = (this$static._cyclicBufferPos << 1) + 1; + ptr1 = this$static._cyclicBufferPos << 1; + len0 = len1 = this$static.kNumHashDirectBytes; + if (this$static.kNumHashDirectBytes != 0) { + if (curMatch > matchMinPos) { + if (this$static._bufferBase[this$static._bufferOffset + curMatch + this$static.kNumHashDirectBytes] != this$static._bufferBase[cur + this$static.kNumHashDirectBytes]) { + distances[offset++] = maxLen = this$static.kNumHashDirectBytes; + distances[offset++] = this$static._pos - curMatch - 1; + } + } + } + count = this$static._cutValue; + while (true) { + if (curMatch <= matchMinPos || count-- == 0) { + this$static._son[ptr0] = this$static._son[ptr1] = 0; + break; + } + delta = this$static._pos - curMatch; + cyclicPos = (delta <= this$static._cyclicBufferPos?this$static._cyclicBufferPos - delta:this$static._cyclicBufferPos - delta + this$static._cyclicBufferSize) << 1; + pby1 = this$static._bufferOffset + curMatch; + len = len0 < len1?len0:len1; + if (this$static._bufferBase[pby1 + len] == this$static._bufferBase[cur + len]) { + while (++len != lenLimit) { + if (this$static._bufferBase[pby1 + len] != this$static._bufferBase[cur + len]) { + break; + } + } + if (maxLen < len) { + distances[offset++] = maxLen = len; + distances[offset++] = delta - 1; + if (len == lenLimit) { + this$static._son[ptr1] = this$static._son[cyclicPos]; + this$static._son[ptr0] = this$static._son[cyclicPos + 1]; + break; + } + } + } + if ((this$static._bufferBase[pby1 + len] & 255) < (this$static._bufferBase[cur + len] & 255)) { + this$static._son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = this$static._son[ptr1]; + len1 = len; + } else { + this$static._son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = this$static._son[ptr0]; + len0 = len; + } + } + $MovePos_0(this$static); + return offset; + } + + function $Init_5(this$static) { + var i; + this$static._bufferOffset = 0; + this$static._pos = 0; + this$static._streamPos = 0; + this$static._streamEndWasReached = false; + $ReadBlock(this$static); + for (i = 0; i < this$static._hashSizeSum; ++i) { + this$static._hash[i] = 0; + } + this$static._cyclicBufferPos = 0; + $ReduceOffsets(this$static, -1); + } + + function $MovePos_0(this$static) { + var subValue; + if (++this$static._cyclicBufferPos >= this$static._cyclicBufferSize) { + this$static._cyclicBufferPos = 0; + } + $MovePos_1(this$static); + if (this$static._pos == 1073741823) { + subValue = this$static._pos - this$static._cyclicBufferSize; + $NormalizeLinks(this$static._son, this$static._cyclicBufferSize * 2, subValue); + $NormalizeLinks(this$static._hash, this$static._hashSizeSum, subValue); + $ReduceOffsets(this$static, subValue); + } + } + + function $NormalizeLinks(items, numItems, subValue) { + var i, value; + for (i = 0; i < numItems; ++i) { + value = items[i]; + if (value <= subValue) { + value = 0; + } else { + value -= subValue; + } + items[i] = value; + } + } + + function $SetType(this$static, numHashBytes) { + this$static.HASH_ARRAY = numHashBytes > 2; + if (this$static.HASH_ARRAY) { + this$static.kNumHashDirectBytes = 0; + this$static.kMinMatchCheck = 4; + this$static.kFixHashSize = 66560; + } else { + this$static.kNumHashDirectBytes = 2; + this$static.kMinMatchCheck = 3; + this$static.kFixHashSize = 0; + } + } + + function $Skip(this$static, num) { + var count, cur, curMatch, cyclicPos, delta, hash2Value, hash3Value, hashValue, len, len0, len1, lenLimit, matchMinPos, pby1, ptr0, ptr1, temp; + do { + if (this$static._pos + this$static._matchMaxLen <= this$static._streamPos) { + lenLimit = this$static._matchMaxLen; + } else { + lenLimit = this$static._streamPos - this$static._pos; + if (lenLimit < this$static.kMinMatchCheck) { + $MovePos_0(this$static); + continue; + } + } + matchMinPos = this$static._pos > this$static._cyclicBufferSize?this$static._pos - this$static._cyclicBufferSize:0; + cur = this$static._bufferOffset + this$static._pos; + if (this$static.HASH_ARRAY) { + temp = CrcTable[this$static._bufferBase[cur] & 255] ^ this$static._bufferBase[cur + 1] & 255; + hash2Value = temp & 1023; + this$static._hash[hash2Value] = this$static._pos; + temp ^= (this$static._bufferBase[cur + 2] & 255) << 8; + hash3Value = temp & 65535; + this$static._hash[1024 + hash3Value] = this$static._pos; + hashValue = (temp ^ CrcTable[this$static._bufferBase[cur + 3] & 255] << 5) & this$static._hashMask; + } else { + hashValue = this$static._bufferBase[cur] & 255 ^ (this$static._bufferBase[cur + 1] & 255) << 8; + } + curMatch = this$static._hash[this$static.kFixHashSize + hashValue]; + this$static._hash[this$static.kFixHashSize + hashValue] = this$static._pos; + ptr0 = (this$static._cyclicBufferPos << 1) + 1; + ptr1 = this$static._cyclicBufferPos << 1; + len0 = len1 = this$static.kNumHashDirectBytes; + count = this$static._cutValue; + while (true) { + if (curMatch <= matchMinPos || count-- == 0) { + this$static._son[ptr0] = this$static._son[ptr1] = 0; + break; + } + delta = this$static._pos - curMatch; + cyclicPos = (delta <= this$static._cyclicBufferPos?this$static._cyclicBufferPos - delta:this$static._cyclicBufferPos - delta + this$static._cyclicBufferSize) << 1; + pby1 = this$static._bufferOffset + curMatch; + len = len0 < len1?len0:len1; + if (this$static._bufferBase[pby1 + len] == this$static._bufferBase[cur + len]) { + while (++len != lenLimit) { + if (this$static._bufferBase[pby1 + len] != this$static._bufferBase[cur + len]) { + break; + } + } + if (len == lenLimit) { + this$static._son[ptr1] = this$static._son[cyclicPos]; + this$static._son[ptr0] = this$static._son[cyclicPos + 1]; + break; + } + } + if ((this$static._bufferBase[pby1 + len] & 255) < (this$static._bufferBase[cur + len] & 255)) { + this$static._son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = this$static._son[ptr1]; + len1 = len; + } else { + this$static._son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = this$static._son[ptr0]; + len0 = len; + } + } + $MovePos_0(this$static); + } + while (--num != 0); + } + + function getClass_39() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZ_BinTree_2_classLit; + } + + function BinTree() { + } + + _ = BinTree.prototype = new InWindow(); + _.getClass$ = getClass_39; + _.typeId$ = 0; + _.HASH_ARRAY = true; + _._cutValue = 255; + _._cyclicBufferPos = 0; + _._cyclicBufferSize = 0; + _._hash = null; + _._hashMask = 0; + _._hashSizeSum = 0; + _._matchMaxLen = 0; + _._son = null; + _.kFixHashSize = 66560; + _.kMinMatchCheck = 4; + _.kNumHashDirectBytes = 0; + var CrcTable; + function $CopyBlock(this$static, distance, len) { + var pos; + pos = this$static._pos - distance - 1; + if (pos < 0) { + pos += this$static._windowSize; + } + for (; len != 0; --len) { + if (pos >= this$static._windowSize) { + pos = 0; + } + this$static._buffer[this$static._pos++] = this$static._buffer[pos++]; + if (this$static._pos >= this$static._windowSize) { + $Flush_0(this$static); + } + } + } + + function $Create_5(this$static, windowSize) { + if (this$static._buffer == null || this$static._windowSize != windowSize) { + this$static._buffer = initDim(_3B_classLit, 0, -1, windowSize, 1); + } + this$static._windowSize = windowSize; + this$static._pos = 0; + this$static._streamPos = 0; + } + + function $Flush_0(this$static) { + var size; + size = this$static._pos - this$static._streamPos; + if (size == 0) { + return; + } + $write_0(this$static._stream, this$static._buffer, this$static._streamPos, size); + if (this$static._pos >= this$static._windowSize) { + this$static._pos = 0; + } + this$static._streamPos = this$static._pos; + } + + function $GetByte(this$static, distance) { + var pos; + pos = this$static._pos - distance - 1; + if (pos < 0) { + pos += this$static._windowSize; + } + return this$static._buffer[pos]; + } + + function $Init_7(this$static, solid) { + if (!solid) { + this$static._streamPos = 0; + this$static._pos = 0; + } + } + + function $PutByte(this$static, b) { + this$static._buffer[this$static._pos++] = b; + if (this$static._pos >= this$static._windowSize) { + $Flush_0(this$static); + } + } + + function $ReleaseStream(this$static) { + $Flush_0(this$static); + this$static._stream = null; + } + + function $SetStream_0(this$static, stream) { + $Flush_0(this$static); + this$static._stream = null; + this$static._stream = stream; + } + + function getClass_41() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZ_OutWindow_2_classLit; + } + + function OutWindow() { + } + + _ = OutWindow.prototype = new Object_0(); + _.getClass$ = getClass_41; + _.typeId$ = 0; + _._buffer = null; + _._pos = 0; + _._stream = null; + _._streamPos = 0; + _._windowSize = 0; + function GetLenToPosState(len) { + len -= 2; + if (len < 4) { + return len; + } + return 3; + } + + function StateUpdateChar(index) { + if (index < 4) { + return 0; + } + if (index < 10) { + return index - 3; + } + return index - 6; + } + + function $Chunker_0(this$static, encoder) { + this$static.encoder = encoder; + this$static.decoder = null; + this$static.alive = true; + return this$static; + } + + function $Chunker(this$static, decoder) { + this$static.decoder = decoder; + this$static.encoder = null; + this$static.alive = true; + return this$static; + } + + function $processChunk(this$static) { + var exception; + if (!this$static.alive) { + throw new IllegalStateException(); + } + exception = true; + try { + if (this$static.encoder) { + $processEncoderChunk(this$static); + } else { + $processDecoderChunk(this$static); + } + exception = false; + return this$static.alive; + } finally { + if (exception) { + this$static.alive = false; + } + } + } + + function $processDecoderChunk(this$static) { + var result; + result = $CodeOneChunk(this$static.decoder); + if (result == -1) { + throw $IOException(new IOException(), 'corrupted input'); + } + this$static.inBytesProcessed = N1_longLit; + this$static.outBytesProcessed = this$static.decoder.nowPos64; + if (result == 1 || compare(this$static.decoder.outSize, P0_longLit) >= 0 && compare(this$static.decoder.nowPos64, this$static.decoder.outSize) >= 0) { + $CodeFinish(this$static.decoder); + this$static.alive = false; + } + } + + function $processEncoderChunk(this$static) { + $CodeOneBlock(this$static.encoder, this$static.encoder.processedInSize, this$static.encoder.processedOutSize, this$static.encoder.finished); + this$static.inBytesProcessed = this$static.encoder.processedInSize[0]; + if (this$static.encoder.finished[0]) { + $ReleaseStreams(this$static.encoder); + this$static.alive = false; + } + } + + function getClass_28() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Chunker_2_classLit; + } + + function Chunker() { + } + + _ = Chunker.prototype = new Object_0(); + _.getClass$ = getClass_28; + _.typeId$ = 0; + _.alive = false; + _.decoder = null; + _.encoder = null; + function $CodeFinish(this$static) { + $Flush_0(this$static.m_OutWindow); + $ReleaseStream(this$static.m_OutWindow); + this$static.m_RangeDecoder.Stream = null; + } + + function $CodeInChunks(this$static, inStream, outStream, outSize) { + this$static.m_RangeDecoder.Stream = inStream; + $SetStream_0(this$static.m_OutWindow, outStream); + $Init_1(this$static); + this$static.state = 0; + this$static.rep0 = 0; + this$static.rep1 = 0; + this$static.rep2 = 0; + this$static.rep3 = 0; + this$static.outSize = outSize; + this$static.nowPos64 = P0_longLit; + this$static.prevByte = 0; + return $Chunker(new Chunker(), this$static); + } + + function $CodeOneChunk(this$static) { + var decoder2, distance, len, numDirectBits, posSlot, posState; + posState = lowBits_0(this$static.nowPos64) & this$static.m_PosStateMask; + if ($DecodeBit(this$static.m_RangeDecoder, this$static.m_IsMatchDecoders, (this$static.state << 4) + posState) == 0) { + decoder2 = $GetDecoder(this$static.m_LiteralDecoder, lowBits_0(this$static.nowPos64), this$static.prevByte); + if (this$static.state < 7) { + this$static.prevByte = $DecodeNormal(decoder2, this$static.m_RangeDecoder); + } + else { + this$static.prevByte = $DecodeWithMatchByte(decoder2, this$static.m_RangeDecoder, $GetByte(this$static.m_OutWindow, this$static.rep0)); + } + $PutByte(this$static.m_OutWindow, this$static.prevByte); + this$static.state = StateUpdateChar(this$static.state); + this$static.nowPos64 = add(this$static.nowPos64, P1_longLit); + } else { + if ($DecodeBit(this$static.m_RangeDecoder, this$static.m_IsRepDecoders, this$static.state) == 1) { + len = 0; + if ($DecodeBit(this$static.m_RangeDecoder, this$static.m_IsRepG0Decoders, this$static.state) == 0) { + if ($DecodeBit(this$static.m_RangeDecoder, this$static.m_IsRep0LongDecoders, (this$static.state << 4) + posState) == 0) { + this$static.state = this$static.state < 7?9:11; + len = 1; + } + } else { + if ($DecodeBit(this$static.m_RangeDecoder, this$static.m_IsRepG1Decoders, this$static.state) == 0) { + distance = this$static.rep1; + } else { + if ($DecodeBit(this$static.m_RangeDecoder, this$static.m_IsRepG2Decoders, this$static.state) == 0) { + distance = this$static.rep2; + } else { + distance = this$static.rep3; + this$static.rep3 = this$static.rep2; + } + this$static.rep2 = this$static.rep1; + } + this$static.rep1 = this$static.rep0; + this$static.rep0 = distance; + } + if (len == 0) { + len = $Decode(this$static.m_RepLenDecoder, this$static.m_RangeDecoder, posState) + 2; + this$static.state = this$static.state < 7?8:11; + } + } else { + this$static.rep3 = this$static.rep2; + this$static.rep2 = this$static.rep1; + this$static.rep1 = this$static.rep0; + len = 2 + $Decode(this$static.m_LenDecoder, this$static.m_RangeDecoder, posState); + this$static.state = this$static.state < 7?7:10; + posSlot = $Decode_0(this$static.m_PosSlotDecoder[GetLenToPosState(len)], this$static.m_RangeDecoder); + if (posSlot >= 4) { + numDirectBits = (posSlot >> 1) - 1; + this$static.rep0 = (2 | posSlot & 1) << numDirectBits; + if (posSlot < 14) { + this$static.rep0 += ReverseDecode(this$static.m_PosDecoders, this$static.rep0 - posSlot - 1, this$static.m_RangeDecoder, numDirectBits); + } else { + this$static.rep0 += $DecodeDirectBits(this$static.m_RangeDecoder, numDirectBits - 4) << 4; + this$static.rep0 += $ReverseDecode(this$static.m_PosAlignDecoder, this$static.m_RangeDecoder); + if (this$static.rep0 < 0) { + if (this$static.rep0 == -1) { + return 1; + } + return -1; + } + } + } else + this$static.rep0 = posSlot; + } + if (compare(fromInt(this$static.rep0), this$static.nowPos64) >= 0 || this$static.rep0 >= this$static.m_DictionarySizeCheck) { + return -1; + } + $CopyBlock(this$static.m_OutWindow, this$static.rep0, len); + this$static.nowPos64 = add(this$static.nowPos64, fromInt(len)); + this$static.prevByte = $GetByte(this$static.m_OutWindow, 0); + } + return 0; + } + + function $Decoder(this$static) { + var i; + this$static.m_OutWindow = new OutWindow(); + this$static.m_RangeDecoder = new Decoder_0(); + this$static.m_IsMatchDecoders = initDim(_3S_classLit, 0, -1, 192, 1); + this$static.m_IsRepDecoders = initDim(_3S_classLit, 0, -1, 12, 1); + this$static.m_IsRepG0Decoders = initDim(_3S_classLit, 0, -1, 12, 1); + this$static.m_IsRepG1Decoders = initDim(_3S_classLit, 0, -1, 12, 1); + this$static.m_IsRepG2Decoders = initDim(_3S_classLit, 0, -1, 12, 1); + this$static.m_IsRep0LongDecoders = initDim(_3S_classLit, 0, -1, 192, 1); + this$static.m_PosSlotDecoder = initDim(_3Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeDecoder_2_classLit, 0, 7, 4, 0); + this$static.m_PosDecoders = initDim(_3S_classLit, 0, -1, 114, 1); + this$static.m_PosAlignDecoder = $BitTreeDecoder(new BitTreeDecoder(), 4); + this$static.m_LenDecoder = $Decoder$LenDecoder(new Decoder$LenDecoder()); + this$static.m_RepLenDecoder = $Decoder$LenDecoder(new Decoder$LenDecoder()); + this$static.m_LiteralDecoder = new Decoder$LiteralDecoder(); + for (i = 0; i < 4; ++i) { + this$static.m_PosSlotDecoder[i] = $BitTreeDecoder(new BitTreeDecoder(), 6); + } + return this$static; + } + + function $Init_1(this$static) { + var i; + $Init_7(this$static.m_OutWindow, false); + InitBitModels(this$static.m_IsMatchDecoders); + InitBitModels(this$static.m_IsRep0LongDecoders); + InitBitModels(this$static.m_IsRepDecoders); + InitBitModels(this$static.m_IsRepG0Decoders); + InitBitModels(this$static.m_IsRepG1Decoders); + InitBitModels(this$static.m_IsRepG2Decoders); + InitBitModels(this$static.m_PosDecoders); + $Init_0(this$static.m_LiteralDecoder); + for (i = 0; i < 4; ++i) { + InitBitModels(this$static.m_PosSlotDecoder[i].Models); + } + $Init(this$static.m_LenDecoder); + $Init(this$static.m_RepLenDecoder); + InitBitModels(this$static.m_PosAlignDecoder.Models); + $Init_8(this$static.m_RangeDecoder); + } + + function $SetDecoderProperties(this$static, properties) { + var dictionarySize, i, lc, lp, pb, remainder, val; + if (properties.length < 5) + return false; + val = properties[0] & 255; + lc = val % 9; + remainder = ~~(val / 9); + lp = remainder % 5; + pb = ~~(remainder / 5); + dictionarySize = 0; + for (i = 0; i < 4; ++i) { + dictionarySize += (properties[1 + i] & 255) << i * 8; + } + if (!$SetLcLpPb(this$static, lc, lp, pb)) { + return false; + } + return $SetDictionarySize(this$static, dictionarySize); + } + + function $SetDictionarySize(this$static, dictionarySize) { + if (dictionarySize < 0) { + return false; + } + if (this$static.m_DictionarySize != dictionarySize) { + this$static.m_DictionarySize = dictionarySize; + this$static.m_DictionarySizeCheck = max(this$static.m_DictionarySize, 1); + $Create_5(this$static.m_OutWindow, max(this$static.m_DictionarySizeCheck, 4096)); + } + return true; + } + + function $SetLcLpPb(this$static, lc, lp, pb) { + var numPosStates; + if (lc > 8 || lp > 4 || pb > 4) { + return false; + } + $Create_0(this$static.m_LiteralDecoder, lp, lc); + numPosStates = 1 << pb; + $Create(this$static.m_LenDecoder, numPosStates); + $Create(this$static.m_RepLenDecoder, numPosStates); + this$static.m_PosStateMask = numPosStates - 1; + return true; + } + + function getClass_32() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Decoder_2_classLit; + } + + function Decoder() { + } + + _ = Decoder.prototype = new Object_0(); + _.getClass$ = getClass_32; + _.typeId$ = 0; + _.m_DictionarySize = -1; + _.m_DictionarySizeCheck = -1; + _.m_PosStateMask = 0; + _.nowPos64 = P0_longLit; + _.outSize = P0_longLit; + _.prevByte = 0; + _.rep0 = 0; + _.rep1 = 0; + _.rep2 = 0; + _.rep3 = 0; + _.state = 0; + function $Create(this$static, numPosStates) { + for (; this$static.m_NumPosStates < numPosStates; ++this$static.m_NumPosStates) { + this$static.m_LowCoder[this$static.m_NumPosStates] = $BitTreeDecoder(new BitTreeDecoder(), 3); + this$static.m_MidCoder[this$static.m_NumPosStates] = $BitTreeDecoder(new BitTreeDecoder(), 3); + } + } + + function $Decode(this$static, rangeDecoder, posState) { + var symbol; + if ($DecodeBit(rangeDecoder, this$static.m_Choice, 0) == 0) { + return $Decode_0(this$static.m_LowCoder[posState], rangeDecoder); + } + symbol = 8; + if ($DecodeBit(rangeDecoder, this$static.m_Choice, 1) == 0) { + symbol += $Decode_0(this$static.m_MidCoder[posState], rangeDecoder); + } else { + symbol += 8 + $Decode_0(this$static.m_HighCoder, rangeDecoder); + } + return symbol; + } + + function $Decoder$LenDecoder(this$static) { + this$static.m_Choice = initDim(_3S_classLit, 0, -1, 2, 1); + this$static.m_LowCoder = initDim(_3Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeDecoder_2_classLit, 0, 7, 16, 0); + this$static.m_MidCoder = initDim(_3Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeDecoder_2_classLit, 0, 7, 16, 0); + this$static.m_HighCoder = $BitTreeDecoder(new BitTreeDecoder(), 8); + return this$static; + } + + function $Init(this$static) { + var posState; + InitBitModels(this$static.m_Choice); + for (posState = 0; posState < this$static.m_NumPosStates; ++posState) { + InitBitModels(this$static.m_LowCoder[posState].Models); + InitBitModels(this$static.m_MidCoder[posState].Models); + } + InitBitModels(this$static.m_HighCoder.Models); + } + + function getClass_29() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Decoder$LenDecoder_2_classLit; + } + + function Decoder$LenDecoder() { + } + + _ = Decoder$LenDecoder.prototype = new Object_0(); + _.getClass$ = getClass_29; + _.typeId$ = 0; + _.m_NumPosStates = 0; + function $Create_0(this$static, numPosBits, numPrevBits) { + var i, numStates; + if (this$static.m_Coders != null && this$static.m_NumPrevBits == numPrevBits && this$static.m_NumPosBits == numPosBits) + return; + this$static.m_NumPosBits = numPosBits; + this$static.m_PosMask = (1 << numPosBits) - 1; + this$static.m_NumPrevBits = numPrevBits; + numStates = 1 << this$static.m_NumPrevBits + this$static.m_NumPosBits; + this$static.m_Coders = initDim(_3Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Decoder$LiteralDecoder$Decoder2_2_classLit, 0, 4, numStates, 0); + for (i = 0; i < numStates; ++i) + this$static.m_Coders[i] = $Decoder$LiteralDecoder$Decoder2(new Decoder$LiteralDecoder$Decoder2()); + } + + function $GetDecoder(this$static, pos, prevByte) { + return this$static.m_Coders[((pos & this$static.m_PosMask) << this$static.m_NumPrevBits) + ((prevByte & 255) >>> 8 - this$static.m_NumPrevBits)]; + } + + function $Init_0(this$static) { + var i, numStates; + numStates = 1 << this$static.m_NumPrevBits + this$static.m_NumPosBits; + for (i = 0; i < numStates; ++i) { + InitBitModels(this$static.m_Coders[i].m_Decoders); + } + } + + function getClass_31() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Decoder$LiteralDecoder_2_classLit; + } + + function Decoder$LiteralDecoder() { + } + + _ = Decoder$LiteralDecoder.prototype = new Object_0(); + _.getClass$ = getClass_31; + _.typeId$ = 0; + _.m_Coders = null; + _.m_NumPosBits = 0; + _.m_NumPrevBits = 0; + _.m_PosMask = 0; + function $DecodeNormal(this$static, rangeDecoder) { + var symbol; + symbol = 1; + do { + symbol = symbol << 1 | $DecodeBit(rangeDecoder, this$static.m_Decoders, symbol); + } while (symbol < 256); + return symbol << 24 >> 24; + } + + function $DecodeWithMatchByte(this$static, rangeDecoder, matchByte) { + var bit, matchBit, symbol; + symbol = 1; + do { + matchBit = matchByte >> 7 & 1; + matchByte <<= 1; + bit = $DecodeBit(rangeDecoder, this$static.m_Decoders, (1 + matchBit << 8) + symbol); + symbol = symbol << 1 | bit; + if (matchBit != bit) { + while (symbol < 256) { + symbol = symbol << 1 | $DecodeBit(rangeDecoder, this$static.m_Decoders, symbol); + } + break; + } + } while (symbol < 256); + return symbol << 24 >> 24; + } + + function $Decoder$LiteralDecoder$Decoder2(this$static) { + this$static.m_Decoders = initDim(_3S_classLit, 0, -1, 768, 1); + return this$static; + } + + function getClass_30() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Decoder$LiteralDecoder$Decoder2_2_classLit; + } + + function Decoder$LiteralDecoder$Decoder2() { + } + + _ = Decoder$LiteralDecoder$Decoder2.prototype = new Object_0(); + _.getClass$ = getClass_30; + _.typeId$ = 17; + function $clinit_59() { + $clinit_59 = nullMethod; + var c, j, k, slotFast; + g_FastPos = initDim(_3B_classLit, 0, -1, 2048, 1); + c = 2; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + for (slotFast = 2; slotFast < 22; ++slotFast) { + k = 1 << (slotFast >> 1) - 1; + for (j = 0; j < k; ++j , ++c) + g_FastPos[c] = slotFast << 24 >> 24; + } + } + + function $Backward(this$static, cur) { + var backCur, backMem, posMem, posPrev; + this$static._optimumEndIndex = cur; + posMem = this$static._optimum[cur].PosPrev; + backMem = this$static._optimum[cur].BackPrev; + do { + if (this$static._optimum[cur].Prev1IsChar) { + $MakeAsChar(this$static._optimum[posMem]); + this$static._optimum[posMem].PosPrev = posMem - 1; + if (this$static._optimum[cur].Prev2) { + this$static._optimum[posMem - 1].Prev1IsChar = false; + this$static._optimum[posMem - 1].PosPrev = this$static._optimum[cur].PosPrev2; + this$static._optimum[posMem - 1].BackPrev = this$static._optimum[cur].BackPrev2; + } + } + posPrev = posMem; + backCur = backMem; + backMem = this$static._optimum[posPrev].BackPrev; + posMem = this$static._optimum[posPrev].PosPrev; + this$static._optimum[posPrev].BackPrev = backCur; + this$static._optimum[posPrev].PosPrev = cur; + cur = posPrev; + } while (cur > 0); + this$static.backRes = this$static._optimum[0].BackPrev; + this$static._optimumCurrentIndex = this$static._optimum[0].PosPrev; + return this$static._optimumCurrentIndex; + } + + function $BaseInit(this$static) { + var i; + this$static._state = 0; + this$static._previousByte = 0; + for (i = 0; i < 4; ++i) { + this$static._repDistances[i] = 0; + } + } + + function $CodeOneBlock(this$static, inSize, outSize, finished) { + var baseVal, complexState, curByte, distance, footerBits, i, len, lenToPosState, matchByte, pos, posReduced, posSlot, posState, progressPosValuePrev, subCoder; + inSize[0] = P0_longLit; + outSize[0] = P0_longLit; + finished[0] = true; + if (this$static._inStream) { + this$static._matchFinder._stream = this$static._inStream; + $Init_5(this$static._matchFinder); + this$static._needReleaseMFStream = true; + this$static._inStream = null; + } + if (this$static._finished) { + return; + } + this$static._finished = true; + progressPosValuePrev = this$static.nowPos64; + if (eq(this$static.nowPos64, P0_longLit)) { + if ($GetNumAvailableBytes(this$static._matchFinder) == 0) { + $Flush(this$static, lowBits_0(this$static.nowPos64)); + return; + } + $ReadMatchDistances(this$static); + posState = lowBits_0(this$static.nowPos64) & this$static._posStateMask; + $Encode_3(this$static._rangeEncoder, this$static._isMatch, (this$static._state << 4) + posState, 0); + this$static._state = StateUpdateChar(this$static._state); + curByte = $GetIndexByte(this$static._matchFinder, -this$static._additionalOffset); + $Encode_1($GetSubCoder(this$static._literalEncoder, lowBits_0(this$static.nowPos64), this$static._previousByte), this$static._rangeEncoder, curByte); + this$static._previousByte = curByte; + --this$static._additionalOffset; + this$static.nowPos64 = add(this$static.nowPos64, P1_longLit); + } + if ($GetNumAvailableBytes(this$static._matchFinder) == 0) { + $Flush(this$static, lowBits_0(this$static.nowPos64)); + return; + } + while (true) { + len = $GetOptimum(this$static, lowBits_0(this$static.nowPos64)); + pos = this$static.backRes; + posState = lowBits_0(this$static.nowPos64) & this$static._posStateMask; + complexState = (this$static._state << 4) + posState; + if (len == 1 && pos == -1) { + $Encode_3(this$static._rangeEncoder, this$static._isMatch, complexState, 0); + curByte = $GetIndexByte(this$static._matchFinder, -this$static._additionalOffset); + subCoder = $GetSubCoder(this$static._literalEncoder, lowBits_0(this$static.nowPos64), this$static._previousByte); + if (this$static._state < 7) { + $Encode_1(subCoder, this$static._rangeEncoder, curByte); + } else { + matchByte = $GetIndexByte(this$static._matchFinder, -this$static._repDistances[0] - 1 - this$static._additionalOffset); + $EncodeMatched(subCoder, this$static._rangeEncoder, matchByte, curByte); + } + this$static._previousByte = curByte; + this$static._state = StateUpdateChar(this$static._state); + } else { + $Encode_3(this$static._rangeEncoder, this$static._isMatch, complexState, 1); + if (pos < 4) { + $Encode_3(this$static._rangeEncoder, this$static._isRep, this$static._state, 1); + if (pos == 0) { + $Encode_3(this$static._rangeEncoder, this$static._isRepG0, this$static._state, 0); + if (len == 1) { + $Encode_3(this$static._rangeEncoder, this$static._isRep0Long, complexState, 0); + } else { + $Encode_3(this$static._rangeEncoder, this$static._isRep0Long, complexState, 1); + } + } else { + $Encode_3(this$static._rangeEncoder, this$static._isRepG0, this$static._state, 1); + if (pos == 1) { + $Encode_3(this$static._rangeEncoder, this$static._isRepG1, this$static._state, 0); + } else { + $Encode_3(this$static._rangeEncoder, this$static._isRepG1, this$static._state, 1); + $Encode_3(this$static._rangeEncoder, this$static._isRepG2, this$static._state, pos - 2); + } + } + if (len == 1) { + this$static._state = this$static._state < 7?9:11; + } else { + $Encode_0(this$static._repMatchLenEncoder, this$static._rangeEncoder, len - 2, posState); + this$static._state = this$static._state < 7?8:11; + } + distance = this$static._repDistances[pos]; + if (pos != 0) { + for (i = pos; i >= 1; --i) { + this$static._repDistances[i] = this$static._repDistances[i - 1]; + } + this$static._repDistances[0] = distance; + } + } else { + $Encode_3(this$static._rangeEncoder, this$static._isRep, this$static._state, 0); + this$static._state = this$static._state < 7?7:10; + $Encode_0(this$static._lenEncoder, this$static._rangeEncoder, len - 2, posState); + pos -= 4; + posSlot = GetPosSlot(pos); + lenToPosState = GetLenToPosState(len); + $Encode_2(this$static._posSlotEncoder[lenToPosState], this$static._rangeEncoder, posSlot); + if (posSlot >= 4) { + footerBits = (posSlot >> 1) - 1; + baseVal = (2 | posSlot & 1) << footerBits; + posReduced = pos - baseVal; + if (posSlot < 14) { + ReverseEncode(this$static._posEncoders, baseVal - posSlot - 1, this$static._rangeEncoder, footerBits, posReduced); + } else { + $EncodeDirectBits(this$static._rangeEncoder, posReduced >> 4, footerBits - 4); + $ReverseEncode(this$static._posAlignEncoder, this$static._rangeEncoder, posReduced & 15); + ++this$static._alignPriceCount; + } + } + distance = pos; + for (i = 3; i >= 1; --i) { + this$static._repDistances[i] = this$static._repDistances[i - 1]; + } + this$static._repDistances[0] = distance; + ++this$static._matchPriceCount; + } + this$static._previousByte = $GetIndexByte(this$static._matchFinder, len - 1 - this$static._additionalOffset); + } + this$static._additionalOffset -= len; + this$static.nowPos64 = add(this$static.nowPos64, fromInt(len)); + if (this$static._additionalOffset == 0) { + if (this$static._matchPriceCount >= 128) { + $FillDistancesPrices(this$static); + } + if (this$static._alignPriceCount >= 16) { + $FillAlignPrices(this$static); + } + inSize[0] = this$static.nowPos64; + outSize[0] = $GetProcessedSizeAdd(this$static._rangeEncoder); + if ($GetNumAvailableBytes(this$static._matchFinder) == 0) { + $Flush(this$static, lowBits_0(this$static.nowPos64)); + return; + } + if (compare(sub(this$static.nowPos64, progressPosValuePrev), P1000_longLit) >= 0) { + this$static._finished = false; + finished[0] = false; + return; + } + } + } + } + + function $Create_2(this$static) { + var bt, numHashBytes; + if (!this$static._matchFinder) { + bt = ($clinit_60() , new BinTree()); + numHashBytes = 4; + if (this$static._matchFinderType == 0) { + numHashBytes = 2; + } + $SetType(bt, numHashBytes); + this$static._matchFinder = bt; + } + $Create_1(this$static._literalEncoder, this$static._numLiteralPosStateBits, this$static._numLiteralContextBits); + if (this$static._dictionarySize == this$static._dictionarySizePrev && this$static._numFastBytesPrev == this$static._numFastBytes) { + return; + } + $Create_3(this$static._matchFinder, this$static._dictionarySize, 4096, this$static._numFastBytes, 274); + this$static._dictionarySizePrev = this$static._dictionarySize; + this$static._numFastBytesPrev = this$static._numFastBytes; + } + + function $Encoder(this$static) { + var i; + $clinit_59(); + this$static._repDistances = initDim(_3I_classLit, 0, -1, 4, 1); + this$static._optimum = initDim(_3Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$Optimal_2_classLit, 0, 6, 4096, 0); + this$static._rangeEncoder = ($clinit_66() , new Encoder_0()); + this$static._isMatch = initDim(_3S_classLit, 0, -1, 192, 1); + this$static._isRep = initDim(_3S_classLit, 0, -1, 12, 1); + this$static._isRepG0 = initDim(_3S_classLit, 0, -1, 12, 1); + this$static._isRepG1 = initDim(_3S_classLit, 0, -1, 12, 1); + this$static._isRepG2 = initDim(_3S_classLit, 0, -1, 12, 1); + this$static._isRep0Long = initDim(_3S_classLit, 0, -1, 192, 1); + this$static._posSlotEncoder = initDim(_3Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeEncoder_2_classLit, 0, 8, 4, 0); + this$static._posEncoders = initDim(_3S_classLit, 0, -1, 114, 1); + this$static._posAlignEncoder = $BitTreeEncoder(new BitTreeEncoder(), 4); + this$static._lenEncoder = $Encoder$LenPriceTableEncoder(new Encoder$LenPriceTableEncoder()); + this$static._repMatchLenEncoder = $Encoder$LenPriceTableEncoder(new Encoder$LenPriceTableEncoder()); + this$static._literalEncoder = new Encoder$LiteralEncoder(); + this$static._matchDistances = initDim(_3I_classLit, 0, -1, 548, 1); + this$static._posSlotPrices = initDim(_3I_classLit, 0, -1, 256, 1); + this$static._distancesPrices = initDim(_3I_classLit, 0, -1, 512, 1); + this$static._alignPrices = initDim(_3I_classLit, 0, -1, 16, 1); + this$static.reps = initDim(_3I_classLit, 0, -1, 4, 1); + this$static.repLens = initDim(_3I_classLit, 0, -1, 4, 1); + this$static.processedInSize = initDim(_3J_classLit, 0, -1, 1, 3); + this$static.processedOutSize = initDim(_3J_classLit, 0, -1, 1, 3); + this$static.finished = initDim(_3Z_classLit, 0, -1, 1, 2); + this$static.properties = initDim(_3B_classLit, 0, -1, 5, 1); + this$static.tempPrices = initDim(_3I_classLit, 0, -1, 128, 1); + for (i = 0; i < 4096; ++i) { + this$static._optimum[i] = new Encoder$Optimal(); + } + for (i = 0; i < 4; ++i) { + this$static._posSlotEncoder[i] = $BitTreeEncoder(new BitTreeEncoder(), 6); + } + return this$static; + } + + function $FillAlignPrices(this$static) { + var i; + for (i = 0; i < 16; ++i) { + this$static._alignPrices[i] = $ReverseGetPrice(this$static._posAlignEncoder, i); + } + this$static._alignPriceCount = 0; + } + + function $FillDistancesPrices(this$static) { + var baseVal, encoder, footerBits, i, lenToPosState, posSlot, st, st2; + for (i = 4; i < 128; ++i) { + posSlot = GetPosSlot(i); + footerBits = (posSlot >> 1) - 1; + baseVal = (2 | posSlot & 1) << footerBits; + this$static.tempPrices[i] = ReverseGetPrice(this$static._posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); + } + for (lenToPosState = 0; lenToPosState < 4; ++lenToPosState) { + encoder = this$static._posSlotEncoder[lenToPosState]; + st = lenToPosState << 6; + for (posSlot = 0; posSlot < this$static._distTableSize; ++posSlot) { + this$static._posSlotPrices[st + posSlot] = $GetPrice_1(encoder, posSlot); + } + for (posSlot = 14; posSlot < this$static._distTableSize; ++posSlot) { + this$static._posSlotPrices[st + posSlot] += (posSlot >> 1) - 1 - 4 << 6; + } + st2 = lenToPosState * 128; + for (i = 0; i < 4; ++i) { + this$static._distancesPrices[st2 + i] = this$static._posSlotPrices[st + i]; + } + for (; i < 128; ++i) { + this$static._distancesPrices[st2 + i] = this$static._posSlotPrices[st + GetPosSlot(i)] + this$static.tempPrices[i]; + } + } + this$static._matchPriceCount = 0; + } + + function $Flush(this$static, nowPos) { + $ReleaseMFStream(this$static); + $WriteEndMarker(this$static, nowPos & this$static._posStateMask); + $FlushData(this$static._rangeEncoder); + } + + function $GetOptimum(this$static, position) { + var cur, curAnd1Price, curAndLenCharPrice, curAndLenPrice, curBack, curPrice, currentByte, distance, i, len, lenEnd, lenMain, lenRes, lenTest, lenTest2, lenTestTemp, matchByte, matchPrice, newLen, nextIsChar, nextMatchPrice, nextOptimum, nextRepMatchPrice, normalMatchPrice, numAvailableBytes, numAvailableBytesFull, numDistancePairs, offs, offset, opt, optimum, pos, posPrev, posState, posStateNext, price_4, repIndex, repLen, repMatchPrice, repMaxIndex, shortRepPrice, startLen, state, state2, t, price, price_0, price_1, price_2, price_3; + if (this$static._optimumEndIndex != this$static._optimumCurrentIndex) { + lenRes = this$static._optimum[this$static._optimumCurrentIndex].PosPrev - this$static._optimumCurrentIndex; + this$static.backRes = this$static._optimum[this$static._optimumCurrentIndex].BackPrev; + this$static._optimumCurrentIndex = this$static._optimum[this$static._optimumCurrentIndex].PosPrev; + return lenRes; + } + this$static._optimumCurrentIndex = this$static._optimumEndIndex = 0; + if (this$static._longestMatchWasFound) { + lenMain = this$static._longestMatchLength; + this$static._longestMatchWasFound = false; + } else { + lenMain = $ReadMatchDistances(this$static); + } + numDistancePairs = this$static._numDistancePairs; + numAvailableBytes = $GetNumAvailableBytes(this$static._matchFinder) + 1; + if (numAvailableBytes < 2) { + this$static.backRes = -1; + return 1; + } + if (numAvailableBytes > 273) { + numAvailableBytes = 273; + } + repMaxIndex = 0; + for (i = 0; i < 4; ++i) { + this$static.reps[i] = this$static._repDistances[i]; + this$static.repLens[i] = $GetMatchLen(this$static._matchFinder, -1, this$static.reps[i], 273); + if (this$static.repLens[i] > this$static.repLens[repMaxIndex]) { + repMaxIndex = i; + } + } + if (this$static.repLens[repMaxIndex] >= this$static._numFastBytes) { + this$static.backRes = repMaxIndex; + lenRes = this$static.repLens[repMaxIndex]; + $MovePos(this$static, lenRes - 1); + return lenRes; + } + if (lenMain >= this$static._numFastBytes) { + this$static.backRes = this$static._matchDistances[numDistancePairs - 1] + 4; + $MovePos(this$static, lenMain - 1); + return lenMain; + } + currentByte = $GetIndexByte(this$static._matchFinder, -1); + matchByte = $GetIndexByte(this$static._matchFinder, -this$static._repDistances[0] - 1 - 1); + if (lenMain < 2 && currentByte != matchByte && this$static.repLens[repMaxIndex] < 2) { + this$static.backRes = -1; + return 1; + } + this$static._optimum[0].State = this$static._state; + posState = position & this$static._posStateMask; + this$static._optimum[1].Price = ($clinit_66() , ProbPrices[this$static._isMatch[(this$static._state << 4) + posState] >>> 2]) + $GetPrice_0($GetSubCoder(this$static._literalEncoder, position, this$static._previousByte), this$static._state >= 7, matchByte, currentByte); + $MakeAsChar(this$static._optimum[1]); + matchPrice = ProbPrices[2048 - this$static._isMatch[(this$static._state << 4) + posState] >>> 2]; + repMatchPrice = matchPrice + ProbPrices[2048 - this$static._isRep[this$static._state] >>> 2]; + if (matchByte == currentByte) { + shortRepPrice = repMatchPrice + $GetRepLen1Price(this$static, this$static._state, posState); + if (shortRepPrice < this$static._optimum[1].Price) { + this$static._optimum[1].Price = shortRepPrice; + $MakeAsShortRep(this$static._optimum[1]); + } + } + lenEnd = lenMain >= this$static.repLens[repMaxIndex]?lenMain:this$static.repLens[repMaxIndex]; + if (lenEnd < 2) { + this$static.backRes = this$static._optimum[1].BackPrev; + return 1; + } + this$static._optimum[1].PosPrev = 0; + this$static._optimum[0].Backs0 = this$static.reps[0]; + this$static._optimum[0].Backs1 = this$static.reps[1]; + this$static._optimum[0].Backs2 = this$static.reps[2]; + this$static._optimum[0].Backs3 = this$static.reps[3]; + len = lenEnd; + do { + this$static._optimum[len--].Price = 268435455; + } while (len >= 2); + for (i = 0; i < 4; ++i) { + repLen = this$static.repLens[i]; + if (repLen < 2) { + continue; + } + price_4 = repMatchPrice + $GetPureRepPrice(this$static, i, this$static._state, posState); + do { + curAndLenPrice = price_4 + $GetPrice(this$static._repMatchLenEncoder, repLen - 2, posState); + optimum = this$static._optimum[repLen]; + if (curAndLenPrice < optimum.Price) { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = i; + optimum.Prev1IsChar = false; + } + } while (--repLen >= 2); + } + normalMatchPrice = matchPrice + ProbPrices[this$static._isRep[this$static._state] >>> 2]; + len = this$static.repLens[0] >= 2?this$static.repLens[0] + 1:2; + if (len <= lenMain) { + offs = 0; + while (len > this$static._matchDistances[offs]) { + offs += 2; + } + for (;; ++len) { + distance = this$static._matchDistances[offs + 1]; + curAndLenPrice = normalMatchPrice + $GetPosLenPrice(this$static, distance, len, posState); + optimum = this$static._optimum[len]; + if (curAndLenPrice < optimum.Price) { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = distance + 4; + optimum.Prev1IsChar = false; + } + if (len == this$static._matchDistances[offs]) { + offs += 2; + if (offs == numDistancePairs) { + break; + } + } + } + } + cur = 0; + while (true) { + ++cur; + if (cur == lenEnd) { + return $Backward(this$static, cur); + } + newLen = $ReadMatchDistances(this$static); + numDistancePairs = this$static._numDistancePairs; + if (newLen >= this$static._numFastBytes) { + this$static._longestMatchLength = newLen; + this$static._longestMatchWasFound = true; + return $Backward(this$static, cur); + } + ++position; + posPrev = this$static._optimum[cur].PosPrev; + if (this$static._optimum[cur].Prev1IsChar) { + --posPrev; + if (this$static._optimum[cur].Prev2) { + state = this$static._optimum[this$static._optimum[cur].PosPrev2].State; + if (this$static._optimum[cur].BackPrev2 < 4) { + state = (state < 7) ? 8 : 11; + } else { + state = (state < 7) ? 7 : 10; + } + } else { + state = this$static._optimum[posPrev].State; + } + state = StateUpdateChar(state); + } else { + state = this$static._optimum[posPrev].State; + } + if (posPrev == cur - 1) { + if (this$static._optimum[cur].BackPrev == 0) { + state = state < 7?9:11; + } else { + state = StateUpdateChar(state); + } + } else { + if (this$static._optimum[cur].Prev1IsChar && this$static._optimum[cur].Prev2) { + posPrev = this$static._optimum[cur].PosPrev2; + pos = this$static._optimum[cur].BackPrev2; + state = state < 7?8:11; + } else { + pos = this$static._optimum[cur].BackPrev; + if (pos < 4) { + state = state < 7?8:11; + } else { + state = state < 7?7:10; + } + } + opt = this$static._optimum[posPrev]; + if (pos < 4) { + if (pos == 0) { + this$static.reps[0] = opt.Backs0; + this$static.reps[1] = opt.Backs1; + this$static.reps[2] = opt.Backs2; + this$static.reps[3] = opt.Backs3; + } else if (pos == 1) { + this$static.reps[0] = opt.Backs1; + this$static.reps[1] = opt.Backs0; + this$static.reps[2] = opt.Backs2; + this$static.reps[3] = opt.Backs3; + } else if (pos == 2) { + this$static.reps[0] = opt.Backs2; + this$static.reps[1] = opt.Backs0; + this$static.reps[2] = opt.Backs1; + this$static.reps[3] = opt.Backs3; + } else { + this$static.reps[0] = opt.Backs3; + this$static.reps[1] = opt.Backs0; + this$static.reps[2] = opt.Backs1; + this$static.reps[3] = opt.Backs2; + } + } else { + this$static.reps[0] = pos - 4; + this$static.reps[1] = opt.Backs0; + this$static.reps[2] = opt.Backs1; + this$static.reps[3] = opt.Backs2; + } + } + this$static._optimum[cur].State = state; + this$static._optimum[cur].Backs0 = this$static.reps[0]; + this$static._optimum[cur].Backs1 = this$static.reps[1]; + this$static._optimum[cur].Backs2 = this$static.reps[2]; + this$static._optimum[cur].Backs3 = this$static.reps[3]; + curPrice = this$static._optimum[cur].Price; + currentByte = $GetIndexByte(this$static._matchFinder, -1); + matchByte = $GetIndexByte(this$static._matchFinder, -this$static.reps[0] - 1 - 1); + posState = position & this$static._posStateMask; + curAnd1Price = curPrice + ProbPrices[this$static._isMatch[(state << 4) + posState] >>> 2] + $GetPrice_0($GetSubCoder(this$static._literalEncoder, position, $GetIndexByte(this$static._matchFinder, -2)), state >= 7, matchByte, currentByte); + nextOptimum = this$static._optimum[cur + 1]; + nextIsChar = false; + if (curAnd1Price < nextOptimum.Price) { + nextOptimum.Price = curAnd1Price; + nextOptimum.PosPrev = cur; + nextOptimum.BackPrev = -1; + nextOptimum.Prev1IsChar = false; + nextIsChar = true; + } + matchPrice = curPrice + ProbPrices[2048 - this$static._isMatch[(state << 4) + posState] >>> 2]; + repMatchPrice = matchPrice + ProbPrices[2048 - this$static._isRep[state] >>> 2]; + if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { + shortRepPrice = repMatchPrice + (ProbPrices[this$static._isRepG0[state] >>> 2] + ProbPrices[this$static._isRep0Long[(state << 4) + posState] >>> 2]); + if (shortRepPrice <= nextOptimum.Price) { + nextOptimum.Price = shortRepPrice; + nextOptimum.PosPrev = cur; + nextOptimum.BackPrev = 0; + nextOptimum.Prev1IsChar = false; + nextIsChar = true; + } + } + numAvailableBytesFull = $GetNumAvailableBytes(this$static._matchFinder) + 1; + numAvailableBytesFull = 4095 - cur < numAvailableBytesFull?4095 - cur:numAvailableBytesFull; + numAvailableBytes = numAvailableBytesFull; + if (numAvailableBytes < 2) { + continue; + } + if (numAvailableBytes > this$static._numFastBytes) { + numAvailableBytes = this$static._numFastBytes; + } + if (!nextIsChar && matchByte != currentByte) { + t = min(numAvailableBytesFull - 1, this$static._numFastBytes); + lenTest2 = $GetMatchLen(this$static._matchFinder, 0, this$static.reps[0], t); + if (lenTest2 >= 2) { + state2 = StateUpdateChar(state); + posStateNext = position + 1 & this$static._posStateMask; + nextRepMatchPrice = curAnd1Price + ProbPrices[2048 - this$static._isMatch[(state2 << 4) + posStateNext] >>> 2] + ProbPrices[2048 - this$static._isRep[state2] >>> 2]; + offset = cur + 1 + lenTest2; + while (lenEnd < offset) { + this$static._optimum[++lenEnd].Price = 268435455; + } + curAndLenPrice = nextRepMatchPrice + (price = $GetPrice(this$static._repMatchLenEncoder, lenTest2 - 2, posStateNext) , price + $GetPureRepPrice(this$static, 0, state2, posStateNext)); + optimum = this$static._optimum[offset]; + if (curAndLenPrice < optimum.Price) { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = false; + } + } + } + startLen = 2; + for (repIndex = 0; repIndex < 4; ++repIndex) { + lenTest = $GetMatchLen(this$static._matchFinder, -1, this$static.reps[repIndex], numAvailableBytes); + if (lenTest < 2) { + continue; + } + lenTestTemp = lenTest; + do { + while (lenEnd < cur + lenTest) { + this$static._optimum[++lenEnd].Price = 268435455; + } + curAndLenPrice = repMatchPrice + (price_0 = $GetPrice(this$static._repMatchLenEncoder, lenTest - 2, posState) , price_0 + $GetPureRepPrice(this$static, repIndex, state, posState)); + optimum = this$static._optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = repIndex; + optimum.Prev1IsChar = false; + } + } while (--lenTest >= 2); + lenTest = lenTestTemp; + if (repIndex == 0) { + startLen = lenTest + 1; + } + if (lenTest < numAvailableBytesFull) { + t = min(numAvailableBytesFull - 1 - lenTest, this$static._numFastBytes); + lenTest2 = $GetMatchLen(this$static._matchFinder, lenTest, this$static.reps[repIndex], t); + if (lenTest2 >= 2) { + state2 = state < 7?8:11; + posStateNext = position + lenTest & this$static._posStateMask; + curAndLenCharPrice = repMatchPrice + (price_1 = $GetPrice(this$static._repMatchLenEncoder, lenTest - 2, posState) , price_1 + $GetPureRepPrice(this$static, repIndex, state, posState)) + ProbPrices[this$static._isMatch[(state2 << 4) + posStateNext] >>> 2] + $GetPrice_0($GetSubCoder(this$static._literalEncoder, position + lenTest, $GetIndexByte(this$static._matchFinder, lenTest - 1 - 1)), true, $GetIndexByte(this$static._matchFinder, lenTest - 1 - (this$static.reps[repIndex] + 1)), $GetIndexByte(this$static._matchFinder, lenTest - 1)); + state2 = StateUpdateChar(state2); + posStateNext = position + lenTest + 1 & this$static._posStateMask; + nextMatchPrice = curAndLenCharPrice + ProbPrices[2048 - this$static._isMatch[(state2 << 4) + posStateNext] >>> 2]; + nextRepMatchPrice = nextMatchPrice + ProbPrices[2048 - this$static._isRep[state2] >>> 2]; + offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) { + this$static._optimum[++lenEnd].Price = 268435455; + } + curAndLenPrice = nextRepMatchPrice + (price_2 = $GetPrice(this$static._repMatchLenEncoder, lenTest2 - 2, posStateNext) , price_2 + $GetPureRepPrice(this$static, 0, state2, posStateNext)); + optimum = this$static._optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = repIndex; + } + } + } + } + if (newLen > numAvailableBytes) { + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > this$static._matchDistances[numDistancePairs]; numDistancePairs += 2) { + } + this$static._matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) { + normalMatchPrice = matchPrice + ProbPrices[this$static._isRep[state] >>> 2]; + while (lenEnd < cur + newLen) { + this$static._optimum[++lenEnd].Price = 268435455; + } + offs = 0; + while (startLen > this$static._matchDistances[offs]) { + offs += 2; + } + for (lenTest = startLen;; ++lenTest) { + curBack = this$static._matchDistances[offs + 1]; + curAndLenPrice = normalMatchPrice + $GetPosLenPrice(this$static, curBack, lenTest, posState); + optimum = this$static._optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = curBack + 4; + optimum.Prev1IsChar = false; + } + if (lenTest == this$static._matchDistances[offs]) { + if (lenTest < numAvailableBytesFull) { + t = min(numAvailableBytesFull - 1 - lenTest, this$static._numFastBytes); + lenTest2 = $GetMatchLen(this$static._matchFinder, lenTest, curBack, t); + if (lenTest2 >= 2) { + state2 = state < 7?7:10; + posStateNext = position + lenTest & this$static._posStateMask; + curAndLenCharPrice = curAndLenPrice + ProbPrices[this$static._isMatch[(state2 << 4) + posStateNext] >>> 2] + $GetPrice_0($GetSubCoder(this$static._literalEncoder, position + lenTest, $GetIndexByte(this$static._matchFinder, lenTest - 1 - 1)), true, $GetIndexByte(this$static._matchFinder, lenTest - (curBack + 1) - 1), $GetIndexByte(this$static._matchFinder, lenTest - 1)); + state2 = StateUpdateChar(state2); + posStateNext = position + lenTest + 1 & this$static._posStateMask; + nextMatchPrice = curAndLenCharPrice + ProbPrices[2048 - this$static._isMatch[(state2 << 4) + posStateNext] >>> 2]; + nextRepMatchPrice = nextMatchPrice + ProbPrices[2048 - this$static._isRep[state2] >>> 2]; + offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) { + this$static._optimum[++lenEnd].Price = 268435455; + } + curAndLenPrice = nextRepMatchPrice + (price_3 = $GetPrice(this$static._repMatchLenEncoder, lenTest2 - 2, posStateNext) , price_3 + $GetPureRepPrice(this$static, 0, state2, posStateNext)); + optimum = this$static._optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = curBack + 4; + } + } + } + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + } + } + + function $GetPosLenPrice(this$static, pos, len, posState) { + var lenToPosState, price; + lenToPosState = GetLenToPosState(len); + if (pos < 128) { + price = this$static._distancesPrices[lenToPosState * 128 + pos]; + } else { + price = this$static._posSlotPrices[(lenToPosState << 6) + GetPosSlot2(pos)] + this$static._alignPrices[pos & 15]; + } + return price + $GetPrice(this$static._lenEncoder, len - 2, posState); + } + + function $GetPureRepPrice(this$static, repIndex, state, posState) { + var price; + if (repIndex == 0) { + price = ($clinit_66() , ProbPrices[this$static._isRepG0[state] >>> 2]); + price += ProbPrices[2048 - this$static._isRep0Long[(state << 4) + posState] >>> 2]; + } else { + price = ($clinit_66() , ProbPrices[2048 - this$static._isRepG0[state] >>> 2]); + if (repIndex == 1) { + price += ProbPrices[this$static._isRepG1[state] >>> 2]; + } else { + price += ProbPrices[2048 - this$static._isRepG1[state] >>> 2]; + price += GetPrice(this$static._isRepG2[state], repIndex - 2); + } + } + return price; + } + + function $GetRepLen1Price(this$static, state, posState) { + return ($clinit_66() , ProbPrices[this$static._isRepG0[state] >>> 2]) + ProbPrices[this$static._isRep0Long[(state << 4) + posState] >>> 2]; + } + + function $Init_4(this$static) { + var i; + $BaseInit(this$static); + $Init_9(this$static._rangeEncoder); + InitBitModels_0(this$static._isMatch); + InitBitModels_0(this$static._isRep0Long); + InitBitModels_0(this$static._isRep); + InitBitModels_0(this$static._isRepG0); + InitBitModels_0(this$static._isRepG1); + InitBitModels_0(this$static._isRepG2); + InitBitModels_0(this$static._posEncoders); + $Init_3(this$static._literalEncoder); + for (i = 0; i < 4; ++i) { + InitBitModels(this$static._posSlotEncoder[i].Models); + } + $Init_2(this$static._lenEncoder, 1 << this$static._posStateBits); + $Init_2(this$static._repMatchLenEncoder, 1 << this$static._posStateBits); + InitBitModels(this$static._posAlignEncoder.Models); + this$static._longestMatchWasFound = false; + this$static._optimumEndIndex = 0; + this$static._optimumCurrentIndex = 0; + this$static._additionalOffset = 0; + } + + function $MovePos(this$static, num) { + if (num > 0) { + $Skip(this$static._matchFinder, num); + this$static._additionalOffset += num; + } + } + + function $ReadMatchDistances(this$static) { + var lenRes; + lenRes = 0; + this$static._numDistancePairs = $GetMatches(this$static._matchFinder, this$static._matchDistances); + if (this$static._numDistancePairs > 0) { + lenRes = this$static._matchDistances[this$static._numDistancePairs - 2]; + if (lenRes == this$static._numFastBytes) + lenRes += $GetMatchLen(this$static._matchFinder, lenRes - 1, this$static._matchDistances[this$static._numDistancePairs - 1], 273 - lenRes); + } + ++this$static._additionalOffset; + return lenRes; + } + + function $ReleaseMFStream(this$static) { + if (!!this$static._matchFinder && this$static._needReleaseMFStream) { + this$static._matchFinder._stream = null; + this$static._needReleaseMFStream = false; + } + } + + function $ReleaseStreams(this$static) { + $ReleaseMFStream(this$static); + this$static._rangeEncoder.Stream = null; + } + + function $SetDictionarySize_0(this$static, dictionarySize) { + var dicLogSize; + if (dictionarySize < 1 || dictionarySize > 536870912) { + return false; + } + this$static._dictionarySize = dictionarySize; + for (dicLogSize = 0; dictionarySize > 1 << dicLogSize; ++dicLogSize) { + } + this$static._distTableSize = dicLogSize * 2; + return true; + } + + function $SetLcLpPb_0(this$static, lc, lp, pb) { + if (lp < 0 || lp > 4 || lc < 0 || lc > 8 || pb < 0 || pb > 4) { + return false; + } + this$static._numLiteralPosStateBits = lp; + this$static._numLiteralContextBits = lc; + this$static._posStateBits = pb; + this$static._posStateMask = (1 << this$static._posStateBits) - 1; + return true; + } + + function $SetMatchFinder(this$static, matchFinderIndex) { + var matchFinderIndexPrev; + if (matchFinderIndex < 0 || matchFinderIndex > 2) { + return false; + } + matchFinderIndexPrev = this$static._matchFinderType; + this$static._matchFinderType = matchFinderIndex; + if (!!this$static._matchFinder && matchFinderIndexPrev != this$static._matchFinderType) { + this$static._dictionarySizePrev = -1; + this$static._matchFinder = null; + } + return true; + } + + function $SetNumFastBytes(this$static, numFastBytes) { + if (numFastBytes < 5 || numFastBytes > 273) { + return false; + } + this$static._numFastBytes = numFastBytes; + return true; + } + + function $WriteCoderProperties(this$static, outStream) { + var i; + this$static.properties[0] = (this$static._posStateBits * 5 + this$static._numLiteralPosStateBits) * 9 + this$static._numLiteralContextBits << 24 >> 24; + for (i = 0; i < 4; ++i) { + this$static.properties[1 + i] = this$static._dictionarySize >> 8 * i << 24 >> 24; + } + $write_0(outStream, this$static.properties, 0, 5); + } + + function $WriteEndMarker(this$static, posState) { + var lenToPosState; + if (!this$static._writeEndMark) { + return; + } + $Encode_3(this$static._rangeEncoder, this$static._isMatch, (this$static._state << 4) + posState, 1); + $Encode_3(this$static._rangeEncoder, this$static._isRep, this$static._state, 0); + this$static._state = this$static._state < 7?7:10; + $Encode_0(this$static._lenEncoder, this$static._rangeEncoder, 0, posState); + lenToPosState = GetLenToPosState(2); + $Encode_2(this$static._posSlotEncoder[lenToPosState], this$static._rangeEncoder, 63); + $EncodeDirectBits(this$static._rangeEncoder, 67108863, 26); + $ReverseEncode(this$static._posAlignEncoder, this$static._rangeEncoder, 15); + } + + function GetPosSlot(pos) { + if (pos < 2048) { + return g_FastPos[pos]; + } + if (pos < 2097152) { + return g_FastPos[pos >> 10] + 20; + } + return g_FastPos[pos >> 20] + 40; + } + + function GetPosSlot2(pos) { + if (pos < 131072) { + return g_FastPos[pos >> 6] + 12; + } + if (pos < 134217728) { + return g_FastPos[pos >> 16] + 32; + } + return g_FastPos[pos >> 26] + 52; + } + + function getClass_38() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder_2_classLit; + } + + function Encoder() { + } + + _ = Encoder.prototype = new Object_0(); + _.getClass$ = getClass_38; + _.typeId$ = 0; + _._additionalOffset = 0; + _._alignPriceCount = 0; + _._dictionarySize = 4194304; + _._dictionarySizePrev = -1; + _._distTableSize = 44; + _._finished = false; + _._inStream = null; + _._longestMatchLength = 0; + _._longestMatchWasFound = false; + _._matchFinder = null; + _._matchFinderType = 1; + _._matchPriceCount = 0; + _._needReleaseMFStream = false; + _._numDistancePairs = 0; + _._numFastBytes = 32; + _._numFastBytesPrev = -1; + _._numLiteralContextBits = 3; + _._numLiteralPosStateBits = 0; + _._optimumCurrentIndex = 0; + _._optimumEndIndex = 0; + _._posStateBits = 2; + _._posStateMask = 3; + _._previousByte = 0; + _._state = 0; + _._writeEndMark = false; + _.backRes = 0; + _.nowPos64 = P0_longLit; + var g_FastPos; + function $Encode(this$static, rangeEncoder, symbol, posState) { + if (symbol < 8) { + $Encode_3(rangeEncoder, this$static._choice, 0, 0); + $Encode_2(this$static._lowCoder[posState], rangeEncoder, symbol); + } else { + symbol -= 8; + $Encode_3(rangeEncoder, this$static._choice, 0, 1); + if (symbol < 8) { + $Encode_3(rangeEncoder, this$static._choice, 1, 0); + $Encode_2(this$static._midCoder[posState], rangeEncoder, symbol); + } else { + $Encode_3(rangeEncoder, this$static._choice, 1, 1); + $Encode_2(this$static._highCoder, rangeEncoder, symbol - 8); + } + } + } + + function $Encoder$LenEncoder(this$static) { + var posState; + this$static._choice = initDim(_3S_classLit, 0, -1, 2, 1); + this$static._lowCoder = initDim(_3Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeEncoder_2_classLit, 0, 8, 16, 0); + this$static._midCoder = initDim(_3Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeEncoder_2_classLit, 0, 8, 16, 0); + this$static._highCoder = $BitTreeEncoder(new BitTreeEncoder(), 8); + for (posState = 0; posState < 16; ++posState) { + this$static._lowCoder[posState] = $BitTreeEncoder(new BitTreeEncoder(), 3); + this$static._midCoder[posState] = $BitTreeEncoder(new BitTreeEncoder(), 3); + } + return this$static; + } + + function $Init_2(this$static, numPosStates) { + var posState; + InitBitModels_0(this$static._choice); + for (posState = 0; posState < numPosStates; ++posState) { + InitBitModels(this$static._lowCoder[posState].Models); + InitBitModels(this$static._midCoder[posState].Models); + } + InitBitModels(this$static._highCoder.Models); + } + + function $SetPrices(this$static, posState, numSymbols, prices, st) { + var a0, a1, b0, b1, i; + a0 = ($clinit_66() , ProbPrices[this$static._choice[0] >>> 2]); + a1 = ProbPrices[2048 - this$static._choice[0] >>> 2]; + b0 = a1 + ProbPrices[this$static._choice[1] >>> 2]; + b1 = a1 + ProbPrices[2048 - this$static._choice[1] >>> 2]; + i = 0; + for (i = 0; i < 8; ++i) { + if (i >= numSymbols) + return; + prices[st + i] = a0 + $GetPrice_1(this$static._lowCoder[posState], i); + } + for (; i < 16; ++i) { + if (i >= numSymbols) + return; + prices[st + i] = b0 + $GetPrice_1(this$static._midCoder[posState], i - 8); + } + for (; i < numSymbols; ++i) { + prices[st + i] = b1 + $GetPrice_1(this$static._highCoder, i - 8 - 8); + } + } + + function getClass_33() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$LenEncoder_2_classLit; + } + + function Encoder$LenEncoder() { + } + + _ = Encoder$LenEncoder.prototype = new Object_0(); + _.getClass$ = getClass_33; + _.typeId$ = 0; + function $Encode_0(this$static, rangeEncoder, symbol, posState) { + $Encode(this$static, rangeEncoder, symbol, posState); + if (--this$static._counters[posState] == 0) { + $SetPrices(this$static, posState, this$static._tableSize, this$static._prices, posState * 272); + this$static._counters[posState] = this$static._tableSize; + } + } + + function $Encoder$LenPriceTableEncoder(this$static) { + $Encoder$LenEncoder(this$static); + this$static._prices = initDim(_3I_classLit, 0, -1, 4352, 1); + this$static._counters = initDim(_3I_classLit, 0, -1, 16, 1); + return this$static; + } + + function $GetPrice(this$static, symbol, posState) { + return this$static._prices[posState * 272 + symbol]; + } + + function $UpdateTables(this$static, numPosStates) { + var posState; + for (posState = 0; posState < numPosStates; ++posState) { + $SetPrices(this$static, posState, this$static._tableSize, this$static._prices, posState * 272); + this$static._counters[posState] = this$static._tableSize; + } + } + + function getClass_34() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$LenPriceTableEncoder_2_classLit; + } + + function Encoder$LenPriceTableEncoder() { + } + + _ = Encoder$LenPriceTableEncoder.prototype = new Encoder$LenEncoder(); + _.getClass$ = getClass_34; + _.typeId$ = 0; + _._tableSize = 0; + function $Create_1(this$static, numPosBits, numPrevBits) { + var i, numStates; + if (this$static.m_Coders != null && this$static.m_NumPrevBits == numPrevBits && this$static.m_NumPosBits == numPosBits) { + return; + } + this$static.m_NumPosBits = numPosBits; + this$static.m_PosMask = (1 << numPosBits) - 1; + this$static.m_NumPrevBits = numPrevBits; + numStates = 1 << this$static.m_NumPrevBits + this$static.m_NumPosBits; + this$static.m_Coders = initDim(_3Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$LiteralEncoder$Encoder2_2_classLit, 0, 5, numStates, 0); + for (i = 0; i < numStates; ++i) { + this$static.m_Coders[i] = $Encoder$LiteralEncoder$Encoder2(new Encoder$LiteralEncoder$Encoder2()); + } + } + + function $GetSubCoder(this$static, pos, prevByte) { + return this$static.m_Coders[((pos & this$static.m_PosMask) << this$static.m_NumPrevBits) + ((prevByte & 255) >>> 8 - this$static.m_NumPrevBits)]; + } + + function $Init_3(this$static) { + var i, numStates; + numStates = 1 << this$static.m_NumPrevBits + this$static.m_NumPosBits; + for (i = 0; i < numStates; ++i) { + InitBitModels_0(this$static.m_Coders[i].m_Encoders); + } + } + + function getClass_36() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$LiteralEncoder_2_classLit; + } + + function Encoder$LiteralEncoder() { + } + + _ = Encoder$LiteralEncoder.prototype = new Object_0(); + _.getClass$ = getClass_36; + _.typeId$ = 0; + _.m_Coders = null; + _.m_NumPosBits = 0; + _.m_NumPrevBits = 0; + _.m_PosMask = 0; + function $Encode_1(this$static, rangeEncoder, symbol) { + var bit, context, i; + context = 1; + for (i = 7; i >= 0; --i) { + bit = symbol >> i & 1; + $Encode_3(rangeEncoder, this$static.m_Encoders, context, bit); + context = context << 1 | bit; + } + } + + function $EncodeMatched(this$static, rangeEncoder, matchByte, symbol) { + var bit, context, i, matchBit, same, state; + context = 1; + same = true; + for (i = 7; i >= 0; --i) { + bit = symbol >> i & 1; + state = context; + if (same) { + matchBit = matchByte >> i & 1; + state += 1 + matchBit << 8; + same = matchBit == bit; + } + $Encode_3(rangeEncoder, this$static.m_Encoders, state, bit); + context = context << 1 | bit; + } + } + + function $Encoder$LiteralEncoder$Encoder2(this$static) { + this$static.m_Encoders = initDim(_3S_classLit, 0, -1, 768, 1); + return this$static; + } + + function $GetPrice_0(this$static, matchMode, matchByte, symbol) { + var bit, context, i, matchBit, price; + price = 0; + context = 1; + i = 7; + if (matchMode) { + for (; i >= 0; --i) { + matchBit = matchByte >> i & 1; + bit = symbol >> i & 1; + price += GetPrice(this$static.m_Encoders[(1 + matchBit << 8) + context], bit); + context = context << 1 | bit; + if (matchBit != bit) { + --i; + break; + } + } + } + for (; i >= 0; --i) { + bit = symbol >> i & 1; + price += GetPrice(this$static.m_Encoders[context], bit); + context = context << 1 | bit; + } + return price; + } + + function getClass_35() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$LiteralEncoder$Encoder2_2_classLit; + } + + function Encoder$LiteralEncoder$Encoder2() { + } + + _ = Encoder$LiteralEncoder$Encoder2.prototype = new Object_0(); + _.getClass$ = getClass_35; + _.typeId$ = 18; + function $MakeAsChar(this$static) { + this$static.BackPrev = -1; + this$static.Prev1IsChar = false; + } + + function $MakeAsShortRep(this$static) { + this$static.BackPrev = 0; + this$static.Prev1IsChar = false; + } + + function getClass_37() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$Optimal_2_classLit; + } + + function Encoder$Optimal() { + } + + _ = Encoder$Optimal.prototype = new Object_0(); + _.getClass$ = getClass_37; + _.typeId$ = 19; + _.BackPrev = 0; + _.BackPrev2 = 0; + _.Backs0 = 0; + _.Backs1 = 0; + _.Backs2 = 0; + _.Backs3 = 0; + _.PosPrev = 0; + _.PosPrev2 = 0; + _.Prev1IsChar = false; + _.Prev2 = false; + _.Price = 0; + _.State = 0; + function $BitTreeDecoder(this$static, numBitLevels) { + this$static.NumBitLevels = numBitLevels; + this$static.Models = initDim(_3S_classLit, 0, -1, 1 << numBitLevels, 1); + return this$static; + } + + function $Decode_0(this$static, rangeDecoder) { + var bitIndex, m; + m = 1; + for (bitIndex = this$static.NumBitLevels; bitIndex != 0; --bitIndex) { + m = (m << 1) + $DecodeBit(rangeDecoder, this$static.Models, m); + } + return m - (1 << this$static.NumBitLevels); + } + + function $ReverseDecode(this$static, rangeDecoder) { + var bit, bitIndex, m, symbol; + m = 1; + symbol = 0; + for (bitIndex = 0; bitIndex < this$static.NumBitLevels; ++bitIndex) { + bit = $DecodeBit(rangeDecoder, this$static.Models, m); + m <<= 1; + m += bit; + symbol |= bit << bitIndex; + } + return symbol; + } + + function ReverseDecode(Models, startIndex, rangeDecoder, NumBitLevels) { + var bit, bitIndex, m, symbol; + m = 1; + symbol = 0; + for (bitIndex = 0; bitIndex < NumBitLevels; ++bitIndex) { + bit = $DecodeBit(rangeDecoder, Models, startIndex + m); + m <<= 1; + m += bit; + symbol |= bit << bitIndex; + } + return symbol; + } + + function getClass_42() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeDecoder_2_classLit; + } + + function BitTreeDecoder() { + } + + _ = BitTreeDecoder.prototype = new Object_0(); + _.getClass$ = getClass_42; + _.typeId$ = 20; + _.Models = null; + _.NumBitLevels = 0; + function $BitTreeEncoder(this$static, numBitLevels) { + this$static.NumBitLevels = numBitLevels; + this$static.Models = initDim(_3S_classLit, 0, -1, 1 << numBitLevels, 1); + return this$static; + } + + function $Encode_2(this$static, rangeEncoder, symbol) { + var bit, bitIndex, m; + m = 1; + for (bitIndex = this$static.NumBitLevels; bitIndex != 0;) { + --bitIndex; + bit = symbol >>> bitIndex & 1; + $Encode_3(rangeEncoder, this$static.Models, m, bit); + m = m << 1 | bit; + } + } + + function $GetPrice_1(this$static, symbol) { + var bit, bitIndex, m, price; + price = 0; + m = 1; + for (bitIndex = this$static.NumBitLevels; bitIndex != 0;) { + --bitIndex; + bit = symbol >>> bitIndex & 1; + price += GetPrice(this$static.Models[m], bit); + m = (m << 1) + bit; + } + return price; + } + + function $ReverseEncode(this$static, rangeEncoder, symbol) { + var bit, i, m; + m = 1; + for (i = 0; i < this$static.NumBitLevels; ++i) { + bit = symbol & 1; + $Encode_3(rangeEncoder, this$static.Models, m, bit); + m = m << 1 | bit; + symbol >>= 1; + } + } + + function $ReverseGetPrice(this$static, symbol) { + var bit, i, m, price; + price = 0; + m = 1; + for (i = this$static.NumBitLevels; i != 0; --i) { + bit = symbol & 1; + symbol >>>= 1; + price += GetPrice(this$static.Models[m], bit); + m = m << 1 | bit; + } + return price; + } + + function ReverseEncode(Models, startIndex, rangeEncoder, NumBitLevels, symbol) { + var bit, i, m; + m = 1; + for (i = 0; i < NumBitLevels; ++i) { + bit = symbol & 1; + $Encode_3(rangeEncoder, Models, startIndex + m, bit); + m = m << 1 | bit; + symbol >>= 1; + } + } + + function ReverseGetPrice(Models, startIndex, NumBitLevels, symbol) { + var bit, i, m, price; + price = 0; + m = 1; + for (i = NumBitLevels; i != 0; --i) { + bit = symbol & 1; + symbol >>>= 1; + price += ($clinit_66() , ProbPrices[((Models[startIndex + m] - bit ^ -bit) & 2047) >>> 2]); + m = m << 1 | bit; + } + return price; + } + + function getClass_43() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeEncoder_2_classLit; + } + + function BitTreeEncoder() { + } + + _ = BitTreeEncoder.prototype = new Object_0(); + _.getClass$ = getClass_43; + _.typeId$ = 21; + _.Models = null; + _.NumBitLevels = 0; + function $DecodeBit(this$static, probs, index) { + var newBound, prob; + prob = probs[index]; + newBound = (this$static.Range >>> 11) * prob; + if ((this$static.Code ^ -2147483648) < (newBound ^ -2147483648)) { + this$static.Range = newBound; + probs[index] = prob + (2048 - prob >>> 5) << 16 >> 16; + if ((this$static.Range & -16777216) == 0) { + this$static.Code = this$static.Code << 8 | $read(this$static.Stream); + this$static.Range <<= 8; + } + return 0; + } else { + this$static.Range -= newBound; + this$static.Code -= newBound; + probs[index] = prob - (prob >>> 5) << 16 >> 16; + if ((this$static.Range & -16777216) == 0) { + this$static.Code = this$static.Code << 8 | $read(this$static.Stream); + this$static.Range <<= 8; + } + return 1; + } + } + + function $DecodeDirectBits(this$static, numTotalBits) { + var i, result, t; + result = 0; + for (i = numTotalBits; i != 0; --i) { + this$static.Range >>>= 1; + t = this$static.Code - this$static.Range >>> 31; + this$static.Code -= this$static.Range & t - 1; + result = result << 1 | 1 - t; + if ((this$static.Range & -16777216) == 0) { + this$static.Code = this$static.Code << 8 | $read(this$static.Stream); + this$static.Range <<= 8; + } + } + return result; + } + + function $Init_8(this$static) { + var i; + this$static.Code = 0; + this$static.Range = -1; + for (i = 0; i < 5; ++i) { + this$static.Code = this$static.Code << 8 | $read(this$static.Stream); + } + } + + function InitBitModels(probs) { + var i; + for (i = 0; i < probs.length; ++i) { + probs[i] = 1024; + } + } + + function getClass_44() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_Decoder_2_classLit; + } + + function Decoder_0() { + } + + _ = Decoder_0.prototype = new Object_0(); + _.getClass$ = getClass_44; + _.typeId$ = 0; + _.Code = 0; + _.Range = 0; + _.Stream = null; + function $clinit_66() { + $clinit_66 = nullMethod; + var end, i, j, start; + ProbPrices = initDim(_3I_classLit, 0, -1, 512, 1); + for (i = 8; i >= 0; --i) { + start = 1 << 9 - i - 1; + end = 1 << 9 - i; + for (j = start; j < end; ++j) { + ProbPrices[j] = (i << 6) + (end - j << 6 >>> 9 - i - 1); + } + } + } + + function $Encode_3(this$static, probs, index, symbol) { + var newBound, prob; + prob = probs[index]; + newBound = (this$static.Range >>> 11) * prob; + if (symbol == 0) { + this$static.Range = newBound; + probs[index] = prob + (2048 - prob >>> 5) << 16 >> 16; + } else { + this$static.Low = add(this$static.Low, and(fromInt(newBound), Pffffffff_longLit)); + this$static.Range -= newBound; + probs[index] = prob - (prob >>> 5) << 16 >> 16; + } + if ((this$static.Range & -16777216) == 0) { + this$static.Range <<= 8; + $ShiftLow(this$static); + } + } + + function $EncodeDirectBits(this$static, v, numTotalBits) { + var i; + for (i = numTotalBits - 1; i >= 0; --i) { + this$static.Range >>>= 1; + if ((v >>> i & 1) == 1) { + this$static.Low = add(this$static.Low, fromInt(this$static.Range)); + } + if ((this$static.Range & -16777216) == 0) { + this$static.Range <<= 8; + $ShiftLow(this$static); + } + } + } + + function $FlushData(this$static) { + var i; + for (i = 0; i < 5; ++i) { + $ShiftLow(this$static); + } + } + + function $GetProcessedSizeAdd(this$static) { + return add(add(fromInt(this$static._cacheSize), this$static._position), P4_longLit); + } + + function $Init_9(this$static) { + this$static._position = P0_longLit; + this$static.Low = P0_longLit; + this$static.Range = -1; + this$static._cacheSize = 1; + this$static._cache = 0; + } + + function $ShiftLow(this$static) { + var LowHi, temp; + LowHi = lowBits_0(shru(this$static.Low, 32)); + if (LowHi != 0 || compare(this$static.Low, Pff000000_longLit) < 0) { + this$static._position = add(this$static._position, fromInt(this$static._cacheSize)); + temp = this$static._cache; + do { + $write(this$static.Stream, temp + LowHi); + temp = 255; + } while (--this$static._cacheSize != 0); + this$static._cache = lowBits_0(this$static.Low) >>> 24; + } + ++this$static._cacheSize; + this$static.Low = shl(and(this$static.Low, Pffffff_longLit), 8); + } + + function GetPrice(Prob, symbol) { + $clinit_66(); + return ProbPrices[((Prob - symbol ^ -symbol) & 2047) >>> 2]; + } + + function InitBitModels_0(probs) { + $clinit_66(); + var i; + for (i = 0; i < probs.length; ++i) { + probs[i] = 1024; + } + } + + function getClass_45() { + return Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_Encoder_2_classLit; + } + + function convert_binary_arr(arr) + { + var i; + + for (i = arr.length - 1; i >= 0; i -= 1) { + if (arr[i] < 0) { + arr[i] = 256 + arr[i]; + } + } + + return arr; + } + + function Encoder_0() { + } + + _ = Encoder_0.prototype = new Object_0(); + _.getClass$ = getClass_45; + _.typeId$ = 0; + _.Low = P0_longLit; + _.Range = 0; + _.Stream = null; + _._cache = 0; + _._cacheSize = 0; + _._position = P0_longLit; + var ProbPrices; + function decode(utf) { + var buf, i, x, y, z; + buf = $StringBuilder(new StringBuilder()); + for (i = 0; i < utf.length; ++i) { + x = utf[i] & 255; + if ((x & 128) == 0) { + if (x == 0) { + /// It appears that this is binary data, so it can't be converted to a string, so just send it back. + return convert_binary_arr(utf); + } + $appendNonNull(buf.data, String.fromCharCode(x & 65535)); + } else if ((x & 224) == 192) { + if (i + 1 >= utf.length) { + /// It appears that this is binary data, so it can't be converted to a string, so just send it back. + return convert_binary_arr(utf); + } + y = utf[++i] & 255; + if ((y & 192) != 128) { + /// It appears that this is binary data, so it can't be converted to a string, so just send it back. + return convert_binary_arr(utf); + } + $append(buf.data, String.fromCharCode((x & 31) << 6 & 65535 | y & 63)); + } else if ((x & 240) == 224) { + if (i + 2 >= utf.length) { + /// It appears that this is binary data, so it can't be converted to a string, so just send it back. + return convert_binary_arr(utf); + } + y = utf[++i] & 255; + if ((y & 192) != 128) { + /// It appears that this is binary data, so it can't be converted to a string, so just send it back. + return convert_binary_arr(utf); + } + z = utf[++i] & 255; + if ((z & 192) != 128) { + /// It appears that this is binary data, so it can't be converted to a string, so just send it back. + return convert_binary_arr(utf); + } + $appendNonNull(buf.data, String.fromCharCode(((x & 15) << 12 | (y & 63) << 6 | z & 63) & 65535)); + } else { + /// It appears that this is binary data, so it can't be converted to a string, so just send it back. + return convert_binary_arr(utf); + } + } + return $toString(buf.data); + } + + function encode(s) { + var ch, chars, data, elen, i, charArr, n; + chars = (n = s.length , charArr = initDim(_3C_classLit, 0, -1, n, 1) , $getChars(s, 0, n, charArr, 0) , charArr); + elen = 0; + for (i = 0; i < s.length; ++i) { + ch = chars[i]; + if (ch >= 1 && ch <= 127) { + ++elen; + } else if (ch == 0 || ch >= 128 && ch <= 2047) { + elen += 2; + } else { + elen += 3; + } + } + data = initDim(_3B_classLit, 0, -1, elen, 1); + elen = 0; + for (i = 0; i < s.length; ++i) { + ch = chars[i]; + if (ch >= 1 && ch <= 127) { + data[elen++] = ch << 24 >> 24; + } else if (ch == 0 || ch >= 128 && ch <= 2047) { + data[elen++] = (192 | ch >> 6 & 31) << 24 >> 24; + data[elen++] = (128 | ch & 63) << 24 >> 24; + } else { + data[elen++] = (224 | ch >> 12 & 15) << 24 >> 24; + data[elen++] = (128 | ch >> 6 & 63) << 24 >> 24; + data[elen++] = (128 | ch & 63) << 24 >> 24; + } + } + return data; + } + + function $LZMADemo(this$static) { + return this$static; + } + function toDouble(a) { + return a[1] + a[0]; + } + + function compress() { + var this$static = $LZMADemo(new LZMADemo()), + percent, + start, + /// Arguments + str = arguments[0], + mode = arguments[1], + callback_num, + on_finish, + on_progress; + + if (typeof arguments[2] === "function") { + on_finish = arguments[2]; + if (typeof arguments[3] === "function") { + on_progress = arguments[3]; + } + } else { + callback_num = arguments[2]; + } + + this$static.mode = get_mode_obj(mode); + + this$static.c = $LZMAByteArrayCompressor(new LZMAByteArrayCompressor(), encode(str), this$static.mode); + + if (on_progress) { + on_progress(0); + } else if (typeof callback_num !== "undefined") { + update_progress(0, callback_num); + } + + function do_action() { + var res; + start = (new Date).getTime(); + while ($execute(this$static.c)) { + percent = toDouble(this$static.c.chunker.inBytesProcessed) / toDouble(this$static.c.length_0); + /// If about 200 miliseconds have passed, update the progress. + if ((new Date).getTime() - start > 200) { + if (on_progress) { + on_progress(percent); + } else if (typeof callback_num !== "undefined") { + update_progress(percent, callback_num); + } + setTimeout(do_action, 0); + return false; + } + } + + if (on_progress) { + on_progress(1); + } else if (typeof callback_num !== "undefined") { + update_progress(1, callback_num); + } + + /// .slice(0) is required for Firefox 4.0 (because I think arrays are now passed by reference, which is not allowed when sending messages to or from web workers). + /// .slice(0) simply returns the entire array by value. + res = $toByteArray(this$static.c.output).slice(0); + + if (on_finish) { + on_finish(res); + } else if (typeof callback_num !== "undefined") { + postMessage({ + action: action_compress, + callback_num: callback_num, + result: res + }); + } + } + + setTimeout(do_action, 1); + } + + function decompress() { + var this$static = $LZMADemo(new LZMADemo()), + percent, + data, + start, + text, + /// Arguments + byte_arr = arguments[0], + callback_num, + on_finish, + on_progress, + sent_unknown, + has_progress; + + if (typeof arguments[1] === "function") { + on_finish = arguments[1]; + if (typeof arguments[2] === "function") { + on_progress = arguments[2]; + } + } else { + callback_num = arguments[1]; + } + + data = initValues(_3B_classLit, 0, -1, byte_arr); + + this$static.d = $LZMAByteArrayDecompressor(new LZMAByteArrayDecompressor(), data); + + if (on_progress) { + on_progress(0); + } else if (typeof callback_num !== "undefined") { + update_progress(0, callback_num); + } + + function do_action() { + var res; + + start = (new Date).getTime(); + + while ($execute_0(this$static.d)) { + if ((new Date).getTime() - start > 200) { + if (has_progress) { + percent = toDouble(this$static.d.chunker.decoder.nowPos64) / toDouble(this$static.d.length_0); + /// If about 200 miliseconds have passed, update the progress. + if (on_progress) { + on_progress(percent); + } else if (typeof callback_num !== "undefined") { + update_progress(percent, callback_num); + } + } else if (!sent_unknown) { + update_progress(-1, callback_num); + sent_unknown = true; + } + setTimeout(do_action, 0); + return false; + } + } + + if (on_progress) { + on_progress(1); + } else if (typeof callback_num !== "undefined") { + update_progress(1, callback_num); + } + + res = decode($toByteArray(this$static.d.output)); + + if (on_finish) { + on_finish(res); + } else if (typeof callback_num !== "undefined") { + postMessage({ + action: action_decompress, + callback_num: callback_num, + /// If the result is an array of integers (because it is binary), we need to use slice to make a copy of the data before it is returned from the Web Worker. + result: (typeof res !== "string" ? res.slice(0) : res) + }); + } + } + + has_progress = toDouble(this$static.d.length_0) > -1; + + setTimeout(do_action, 0); + } + + function $onModuleLoad(this$static) { + compress(this$static); + decompress(this$static); + } + + function getClass_46() { + return Lorg_dellroad_lzma_demo_client_LZMADemo_2_classLit; + } + + function LZMADemo () {} + + _ = LZMADemo.prototype = new Object_0(); + _.getClass$ = getClass_46; + _.typeId$ = 0; + _.c = null; + _.d = null; + var DEFAULT_COMPRESSION_MODE; + function init() { + !!$stats && $stats({moduleName:$moduleName, subSystem:'startup', evtGroup:'moduleStartup', millis:(new Date()).getTime(), type:'onModuleLoadStart', className:'org.dellroad.lzma.demo.client.LZMADemo'}); + } + + function gwtOnLoad(errFn, modName, modBase) { + $moduleName = modName; + $moduleBase = modBase; + if (errFn) { + try { + init(); + } + catch (e) { + errFn(modName); + } + } else { + init(); + } + } + + function nullMethod() { + } + + var Ljava_lang_Object_2_classLit = createForClass('java.lang.', 'Object'), + Ljava_lang_Throwable_2_classLit = createForClass('java.lang.', 'Throwable'), + Ljava_lang_Exception_2_classLit = createForClass('java.lang.', 'Exception'), + Ljava_lang_RuntimeException_2_classLit = createForClass('java.lang.', 'RuntimeException'), + Lcom_google_gwt_core_client_JavaScriptException_2_classLit = createForClass('com.google.gwt.core.client.', 'JavaScriptException'), + Lcom_google_gwt_core_client_JavaScriptObject_2_classLit = createForClass('com.google.gwt.core.client.', 'JavaScriptObject$'), _3_3D_classLit = createForArray('', '[[D'), + Ljava_io_InputStream_2_classLit = createForClass('java.io.', 'InputStream'), + Ljava_io_ByteArrayInputStream_2_classLit = createForClass('java.io.', 'ByteArrayInputStream'), _3B_classLit = createForArray('', '[B'), + Ljava_io_OutputStream_2_classLit = createForClass('java.io.', 'OutputStream'), + Ljava_io_ByteArrayOutputStream_2_classLit = createForClass('java.io.', 'ByteArrayOutputStream'), + Ljava_io_IOException_2_classLit = createForClass('java.io.', 'IOException'), + Ljava_lang_Enum_2_classLit = createForClass('java.lang.', 'Enum'), + Ljava_lang_ArithmeticException_2_classLit = createForClass('java.lang.', 'ArithmeticException'), + Ljava_lang_ArrayStoreException_2_classLit = createForClass('java.lang.', 'ArrayStoreException'), _3C_classLit = createForArray('', '[C'), + Ljava_lang_Class_2_classLit = createForClass('java.lang.', 'Class'), + Ljava_lang_ClassCastException_2_classLit = createForClass('java.lang.', 'ClassCastException'), + Ljava_lang_IllegalArgumentException_2_classLit = createForClass('java.lang.', 'IllegalArgumentException'), + Ljava_lang_IllegalStateException_2_classLit = createForClass('java.lang.', 'IllegalStateException'), + Ljava_lang_IndexOutOfBoundsException_2_classLit = createForClass('java.lang.', 'IndexOutOfBoundsException'), _3I_classLit = createForArray('', '[I'), + Ljava_lang_NullPointerException_2_classLit = createForClass('java.lang.', 'NullPointerException'), + Ljava_lang_String_2_classLit = createForClass('java.lang.', 'String'), + Ljava_lang_StringBuilder_2_classLit = createForClass('java.lang.', 'StringBuilder'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZ_InWindow_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZ.', 'InWindow'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZ_BinTree_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZ.', 'BinTree'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZ_OutWindow_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZ.', 'OutWindow'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Chunker_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Chunker'), _3S_classLit = createForArray('', '[S'), _3Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeDecoder_2_classLit = createForArray('[Lorg.dellroad.lzma.client.SevenZip.Compression.RangeCoder.', 'BitTreeDecoder;'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Decoder_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Decoder'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Decoder$LenDecoder_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Decoder$LenDecoder'), _3Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Decoder$LiteralDecoder$Decoder2_2_classLit = createForArray('[Lorg.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Decoder$LiteralDecoder$Decoder2;'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Decoder$LiteralDecoder_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Decoder$LiteralDecoder'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Decoder$LiteralDecoder$Decoder2_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Decoder$LiteralDecoder$Decoder2'), _3Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$Optimal_2_classLit = createForArray('[Lorg.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Encoder$Optimal;'), _3Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeEncoder_2_classLit = createForArray('[Lorg.dellroad.lzma.client.SevenZip.Compression.RangeCoder.', 'BitTreeEncoder;'), _3J_classLit = createForArray('', '[J'), _3Z_classLit = createForArray('', '[Z'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Encoder'), _3Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$LiteralEncoder$Encoder2_2_classLit = createForArray('[Lorg.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Encoder$LiteralEncoder$Encoder2;'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$LiteralEncoder_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Encoder$LiteralEncoder'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$LiteralEncoder$Encoder2_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Encoder$LiteralEncoder$Encoder2'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$LenEncoder_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Encoder$LenEncoder'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$LenPriceTableEncoder_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Encoder$LenPriceTableEncoder'), + Lorg_dellroad_lzma_client_SevenZip_Compression_LZMA_Encoder$Optimal_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.LZMA.', 'Encoder$Optimal'), + Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeDecoder_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.RangeCoder.', 'BitTreeDecoder'), + Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_BitTreeEncoder_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.RangeCoder.', 'BitTreeEncoder'), + Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_Decoder_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.RangeCoder.', 'Decoder'), + Lorg_dellroad_lzma_client_SevenZip_Compression_RangeCoder_Encoder_2_classLit = createForClass('org.dellroad.lzma.client.SevenZip.Compression.RangeCoder.', 'Encoder'), + Lorg_dellroad_lzma_client_CompressionMode_2_classLit = createForEnum('org.dellroad.lzma.client.', 'CompressionMode'), + Lorg_dellroad_lzma_client_LZMACompressor_2_classLit = createForClass('org.dellroad.lzma.client.', 'LZMACompressor'), + Lorg_dellroad_lzma_client_LZMAByteArrayCompressor_2_classLit = createForClass('org.dellroad.lzma.client.', 'LZMAByteArrayCompressor'), + Lorg_dellroad_lzma_client_LZMADecompressor_2_classLit = createForClass('org.dellroad.lzma.client.', 'LZMADecompressor'), + Lorg_dellroad_lzma_client_LZMAByteArrayDecompressor_2_classLit = createForClass('org.dellroad.lzma.client.', 'LZMAByteArrayDecompressor'), + Lorg_dellroad_lzma_demo_client_LZMADemo_2_classLit = createForClass('org.dellroad.lzma.demo.client.', 'LZMADemo'); + + gwtOnLoad(function() {},'lzma_demo',''); + + + var get_mode_obj = (function () { + var modes = [ + {dictionarySize: 16, fb: 64, matchFinder: 0, lc: 3, lp: 0, pb: 2}, + {dictionarySize: 20, fb: 64, matchFinder: 0, lc: 3, lp: 0, pb: 2}, + {dictionarySize: 19, fb: 64, matchFinder: 1, lc: 3, lp: 0, pb: 2}, + {dictionarySize: 20, fb: 64, matchFinder: 1, lc: 3, lp: 0, pb: 2}, + {dictionarySize: 21, fb: 128, matchFinder: 1, lc: 3, lp: 0, pb: 2}, + {dictionarySize: 22, fb: 128, matchFinder: 1, lc: 3, lp: 0, pb: 2}, + {dictionarySize: 23, fb: 128, matchFinder: 1, lc: 3, lp: 0, pb: 2}, + {dictionarySize: 24, fb: 255, matchFinder: 1, lc: 3, lp: 0, pb: 2}, + {dictionarySize: 25, fb: 255, matchFinder: 1, lc: 3, lp: 0, pb: 2} + ]; + + function isNumber(n) { + return !isNaN(parseFloat(n)) && isFinite(n); + } + + return function (mode) { + if (!isNumber(mode)) { + mode = 1; + } else { + if (mode < 1) { + mode = 1; + } else if (mode > 9) { + mode = 9; + } + } + + return modes[mode - 1]; + } + }()); + + /// Are we in a Web Worker? + /// This seems to be the most reliable way to detect this. + if (typeof onmessage !== "undefined" && (typeof window === "undefined" || typeof window.document === "undefined")) { + (function create_onmessage() { + /// Create the global onmessage function. + onmessage = function (e) { + if (e && e.data) { + if (e.data.action === action_compress) { + LZMA.compress(e.data.data, e.data.mode, e.data.callback_num); + } else if (e.data.action === action_decompress) { + LZMA.decompress(e.data.data, e.data.callback_num); + } + } + } + }()); + } + + return { + compress: compress, + decompress: decompress + }; +}()); + +/// Allow Node.js to be able to access this directly if it is included directly. +this.LZMA = LZMA; + +/// This is used by browsers that do not support web workers. +this.LZMA_WORKER = LZMA; diff --git a/plugins/fitsy/pako_inflate.min.js b/plugins/fitsy/pako_inflate.min.js new file mode 100644 index 00000000..0abc5cf5 --- /dev/null +++ b/plugins/fitsy/pako_inflate.min.js @@ -0,0 +1,2 @@ +/* pako 0.1.1 nodeca/pako */ +!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.pako=e()}}(function(){return function e(t,i,n){function a(r,o){if(!i[r]){if(!t[r]){var d="function"==typeof require&&require;if(!o&&d)return d(r,!0);if(s)return s(r,!0);throw new Error("Cannot find module '"+r+"'")}var f=i[r]={exports:{}};t[r][0].call(f.exports,function(e){var i=t[r][1][e];return a(i?i:e)},f,f.exports,e,t,i,n)}return i[r].exports}for(var s="function"==typeof require&&require,r=0;r=0&&t.windowBits<16&&(t.windowBits=-t.windowBits,0===t.windowBits&&(t.windowBits=-15)),!(t.windowBits>=0&&t.windowBits<16)||e&&e.windowBits||(t.windowBits+=32),t.windowBits>15&&t.windowBits<48&&0===(15&t.windowBits)&&(t.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new f;var i=s.inflateInit2(this.strm,t.windowBits);if(i!==o.Z_OK)throw new Error(d[i])};l.prototype.push=function(e,t){var i,n,a=this.strm,d=this.options.chunkSize;if(this.ended)return!1;n=o.Z_NO_FLUSH,a.next_in=e,a.next_in_index=0,a.avail_in=a.next_in.length,a.next_out=new r.Buf8(d);do{if(a.avail_out=this.options.chunkSize,a.next_out_index=0,i=s.inflate(a,n),i!==o.Z_STREAM_END&&i!==o.Z_OK)return this.onEnd(i),this.ended=!0,!1;a.next_out_index&&(this.onData(r.shrinkBuf(a.next_out,a.next_out_index)),(a.avail_in>0||0===a.avail_out)&&(a.next_out=new r.Buf8(this.options.chunkSize)))}while(a.avail_in>0||0===a.avail_out);return n=t===~~t?t:t===!0?o.Z_FINISH:o.Z_NO_FLUSH,n===o.Z_FINISH?(i=s.inflateEnd(this.strm),this.onEnd(i),this.ended=!0,i===o.Z_OK):!0},l.prototype.onData=function(e){this.chunks.push(e)},l.prototype.onEnd=function(e){e===o.Z_OK&&(this.result=r.flattenChunks(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg},i.Inflate=l,i.inflate=n,i.inflateRaw=a},{"./zlib/constants":3,"./zlib/inflate.js":6,"./zlib/messages":8,"./zlib/utils":9,"./zlib/zstream":10}],2:[function(e,t){"use strict";function i(e,t,i,n){for(var a=65535&e|0,s=e>>>16&65535|0,r=0;0!==i;){r=i>2e3?2e3:i,i-=r;do a=a+t[n++]|0,s=s+a|0;while(--r);a%=65521,s%=65521}return a|s<<16|0}t.exports=i},{}],3:[function(e,t){t.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],4:[function(e,t){"use strict";function i(){for(var e,t=[],i=0;256>i;i++){e=i;for(var n=0;8>n;n++)e=1&e?3988292384^e>>>1:e>>>1;t[i]=e}return t}function n(e,t,i,n){var s=a,r=n+i;e=-1^e;for(var o=n;r>o;o++)e=e>>>8^s[255&(e^t[o])];return-1^e}var a=i();t.exports=n},{}],5:[function(e,t){"use strict";var i=30,n=12;t.exports=function(e,t){var a,s,r,o,d,f,l,c,h,u,w,b,_,k,m,x,v,g,p,y,B,E,S,Z,z;a=e.state,s=e.next_in_index,Z=e.next_in,r=s+(e.avail_in-5),o=e.next_out_index,z=e.next_out,d=o-(t-e.avail_out),f=o+(e.avail_out-257),l=a.dmax,c=a.wsize,h=a.whave,u=a.wnext,w=a.window,b=a.hold,_=a.bits,k=a.lencode,m=a.distcode,x=(1<_&&(b+=Z[s++]<<_,_+=8,b+=Z[s++]<<_,_+=8),g=k[b&x];t:for(;;){if(p=g>>>24,b>>>=p,_-=p,p=g>>>16&255,0===p)z[o++]=65535&g;else{if(!(16&p)){if(0===(64&p)){g=k[(65535&g)+(b&(1<_&&(b+=Z[s++]<<_,_+=8),y+=b&(1<>>=p,_-=p),15>_&&(b+=Z[s++]<<_,_+=8,b+=Z[s++]<<_,_+=8),g=m[b&v];i:for(;;){if(p=g>>>24,b>>>=p,_-=p,p=g>>>16&255,!(16&p)){if(0===(64&p)){g=m[(65535&g)+(b&(1<_&&(b+=Z[s++]<<_,_+=8,p>_&&(b+=Z[s++]<<_,_+=8)),B+=b&(1<l){e.msg="invalid distance too far back",a.mode=i;break e}if(b>>>=p,_-=p,p=o-d,B>p){if(p=B-p,p>h&&a.sane){e.msg="invalid distance too far back",a.mode=i;break e}if(E=0,S=w,0===u){if(E+=c-p,y>p){y-=p;do z[o++]=w[E++];while(--p);E=o-B,S=z}}else if(p>u){if(E+=c+u-p,p-=u,y>p){y-=p;do z[o++]=w[E++];while(--p);if(E=0,y>u){p=u,y-=p;do z[o++]=w[E++];while(--p);E=o-B,S=z}}}else if(E+=u-p,y>p){y-=p;do z[o++]=w[E++];while(--p);E=o-B,S=z}for(;y>2;)z[o++]=S[E++],z[o++]=S[E++],z[o++]=S[E++],y-=3;y&&(z[o++]=S[E++],y>1&&(z[o++]=S[E++]))}else{E=o-B;do z[o++]=z[E++],z[o++]=z[E++],z[o++]=z[E++],y-=3;while(y>2);y&&(z[o++]=z[E++],y>1&&(z[o++]=z[E++]))}break}}break}}while(r>s&&f>o);y=_>>3,s-=y,_-=y<<3,b&=(1<<_)-1,e.next_in_index=s,e.next_out_index=o,e.avail_in=r>s?5+(r-s):5-(s-r),e.avail_out=f>o?257+(f-o):257-(o-f),a.hold=b,a.bits=_}},{}],6:[function(e,t,i){"use strict";function n(e){return(e>>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function a(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.next_index=0,this.lens=new m.Buf16(320),this.work=new m.Buf16(288),this.codes=new m.Buf32(kt),this.sane=0,this.back=0,this.was=0}function s(e,t,i,n,a,s,r,o){this.type=e,this.lens=t,this.lens_index=i,this.codes=n,this.table=a,this.table_index=s,this.bits=r,this.work=o}function r(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,t.wrap&&(e.adler=1&t.wrap),t.mode=L,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=new m.Buf32(kt),t.distcode=new m.Buf32(kt),t.sane=1,t.back=-1,R):N}function o(e){var t;return e&&e.state?(t=e.state,t.wsize=0,t.whave=0,t.wnext=0,r(e)):N}function d(e,t){var i,n;return e&&e.state?(n=e.state,0>t?(i=0,t=-t):(i=(t>>4)+1,48>t&&(t&=15)),t&&(8>t||t>15)?N:(null!==n.window&&n.wbits!==t&&(n.window=null),n.wrap=i,n.wbits=t,o(e))):N}function f(e,t){var i,n;return e?(n=new a,e.state=n,n.window=null,i=d(e,t),i!==R&&(e.state=null),i):N}function l(e){return f(e,xt)}function c(e,t,i){var n;return e&&e.state?(n=e.state,0>t?(n.hold=0,n.bits=0,R):t>16||n.bits+t>32?N:(i&=(1<t;)e.lens[t++]=8;for(;256>t;)e.lens[t++]=9;for(;280>t;)e.lens[t++]=7;for(;288>t;)e.lens[t++]=8;for(i=9,p(new s(B,e.lens,0,288,_,0,i,e.work)),t=0;32>t;)e.lens[t++]=5;i=5,p(new s(E,e.lens,0,32,k,0,i,e.work)),vt=!1}e.lencode=_,e.lenbits=9,e.distcode=k,e.distbits=5}function u(e,t,i,n){var a,s=e.state;return null===s.window&&(s.wsize=1<=s.wsize?(m.arraySet(s.window,t,i-s.wsize,s.wsize,0),s.wnext=0,s.whave=s.wsize):(a=s.wsize-s.wnext,a>n&&(a=n),m.arraySet(s.window,t,i-n,a,s.wnext),n-=a,n?(m.arraySet(s.window,t,i-n,n,0),s.wnext=n,s.whave=s.wsize):(s.wnext+=a,s.wnext===s.wsize&&(s.wnext=0),s.whavew;){if(0===f)break e;f--,c+=a[o++]<>>8&255,i.check=v(i.check,zt,2,0),c=0,w=0,i.mode=D;break}if(i.flags=0,i.head&&(i.head.done=-1),!(1&i.wrap)||(((255&c)<<8)+(c>>8))%31){e.msg="incorrect header check",i.mode=ht;break}if((15&c)!==U){e.msg="unknown compression method",i.mode=ht;break}if(c>>>=4,w-=4,yt=(15&c)+8,0===i.wbits)i.wbits=yt;else if(yt>i.wbits){e.msg="invalid window size",i.mode=ht;break}i.dmax=1<w;){if(0===f)break e;f--,c+=a[o++]<>8&1),512&i.flags&&(zt[0]=255&c,zt[1]=c>>>8&255,i.check=v(i.check,zt,2,0)),c=0,w=0,i.mode=C;case C:for(;32>w;){if(0===f)break e;f--,c+=a[o++]<>>8&255,zt[2]=c>>>16&255,zt[3]=c>>>24&255,i.check=v(i.check,zt,4,0)),c=0,w=0,i.mode=H;case H:for(;16>w;){if(0===f)break e;f--,c+=a[o++]<>8),512&i.flags&&(zt[0]=255&c,zt[1]=c>>>8&255,i.check=v(i.check,zt,2,0)),c=0,w=0,i.mode=K;case K:if(1024&i.flags){for(;16>w;){if(0===f)break e;f--,c+=a[o++]<>>8&255,i.check=v(i.check,zt,2,0)),c=0,w=0}else i.head&&(i.head.extra=null);i.mode=M;case M:if(1024&i.flags){if(k=i.length,k>f&&(k=f),k){if(i.head&&i.head.extra)throw yt=i.head.extra_len-i.length,"Review & implement right";512&i.flags&&(i.check=v(i.check,a,k,o)),f-=k,o+=k,i.length-=k}if(i.length)break e}i.length=0,i.mode=P;case P:if(2048&i.flags){if(0===f)break e;k=0;do yt=a[o+k++],i.head&&i.head.name&&i.lengthk);if(512&i.flags&&(i.check=v(i.check,a,k,o)),f-=k,o+=k,yt)break e}else i.head&&(i.head.name=null);i.length=0,i.mode=j;case j:if(4096&i.flags){if(0===f)break e;k=0;do yt=a[o+k++],i.head&&i.head.comment&&i.lengthk);if(512&i.flags&&(i.check=v(i.check,a,k,o)),f-=k,o+=k,yt)break e}else i.head&&(i.head.comment=null);i.mode=q;case q:if(512&i.flags){for(;16>w;){if(0===f)break e;f--,c+=a[o++]<>9&1,i.head.done=1),e.adler=i.check=0,i.mode=G;break;case Y:for(;32>w;){if(0===f)break e;f--,c+=a[o++]<>>=7&w,w-=7&w,i.mode=ft;break}for(;3>w;){if(0===f)break e;f--,c+=a[o++]<>>=1,w-=1,3&c){case 0:i.mode=J;break;case 1:if(h(i),i.mode=it,t===z){c>>>=2,w-=2;break e}break;case 2:i.mode=$;break;case 3:e.msg="invalid block type",i.mode=ht}c>>>=2,w-=2;break;case J:for(c>>>=7&w,w-=7&w;32>w;){if(0===f)break e;f--,c+=a[o++]<>>16^65535)){e.msg="invalid stored block lengths",i.mode=ht;break}if(i.length=65535&c,c=0,w=0,i.mode=Q,t===z)break e;case Q:i.mode=V;case V:if(k=i.length){if(k>f&&(k=f),k>l&&(k=l),0===k)break e;m.arraySet(r,a,o,k,d),f-=k,o+=k,l-=k,d+=k,i.length-=k;break}i.mode=G;break;case $:for(;14>w;){if(0===f)break e;f--,c+=a[o++]<>>=5,w-=5,i.ndist=(31&c)+1,c>>>=5,w-=5,i.ncode=(15&c)+4,c>>>=4,w-=4,i.nlen>286||i.ndist>30){e.msg="too many length or distance symbols",i.mode=ht;break}i.have=0,i.mode=et;case et:for(;i.havew;){if(0===f)break e;f--,c+=a[o++]<>>=3,w-=3}for(;i.have<19;)i.lens[Rt[i.have++]]=0;if(m.arraySet(i.lencode,i.codes,0,i.codes.length,0),i.lenbits=7,Et=new s(y,i.lens,0,19,i.lencode,0,i.lenbits,i.work),Bt=p(Et),i.lenbits=Et.bits,Bt){e.msg="invalid code lengths set",i.mode=ht;break}i.have=0,i.mode=tt;case tt:for(;i.have>>24,mt=Zt>>>16&255,xt=65535&Zt,!(w>=kt);){if(0===f)break e;f--,c+=a[o++]<xt)c>>>=kt,w-=kt,i.lens[i.have++]=xt;else{if(16===xt){for(St=kt+2;St>w;){if(0===f)break e;f--,c+=a[o++]<>>=kt,w-=kt,0===i.have){e.msg="invalid bit length repeat",i.mode=ht;break}yt=i.lens[i.have-1],k=3+(3&c),c>>>=2,w-=2}else if(17===xt){for(St=kt+3;St>w;){if(0===f)break e;f--,c+=a[o++]<>>=kt,w-=kt,yt=0,k=3+(7&c),c>>>=3,w-=3}else{for(St=kt+7;St>w;){if(0===f)break e;f--,c+=a[o++]<>>=kt,w-=kt,yt=0,k=11+(127&c),c>>>=7,w-=7}if(i.have+k>i.nlen+i.ndist){e.msg="invalid bit length repeat",i.mode=ht;break}for(;k--;)i.lens[i.have++]=yt}}if(i.mode===ht)break;if(0===i.lens[256]){e.msg="invalid code -- missing end-of-block",i.mode=ht;break}if(m.arraySet(i.lencode,i.codes,0,i.codes.length,0),i.lenbits=9,Et=new s(B,i.lens,0,i.nlen,i.lencode,0,i.lenbits,i.work),Bt=p(Et),i.lenbits=Et.bits,Bt){e.msg="invalid literal/lengths set",i.mode=ht;break}if(i.distbits=6,m.arraySet(i.distcode,i.codes,0,i.codes.length,0),Et=new s(E,i.lens,i.nlen,i.ndist,i.distcode,0,i.distbits,i.work),Bt=p(Et),i.distbits=Et.bits,Bt){e.msg="invalid distances set",i.mode=ht;break}if(i.mode=it,t===z)break e;case it:i.mode=nt;case nt:if(f>=6&&l>=258){e.next_out_index=d,e.avail_out=l,e.next_in_index=o,e.avail_in=f,i.hold=c,i.bits=w,g(e,_),d=e.next_out_index,r=e.next_out,l=e.avail_out,o=e.next_in_index,a=e.next_in,f=e.avail_in,c=i.hold,w=i.bits,i.mode===G&&(i.back=-1);break}for(i.back=0;Zt=i.lencode[c&(1<>>24,mt=Zt>>>16&255,xt=65535&Zt,!(w>=kt);){if(0===f)break e;f--,c+=a[o++]<>vt)],kt=Zt>>>24,mt=Zt>>>16&255,xt=65535&Zt,!(w>=vt+kt);){if(0===f)break e;f--,c+=a[o++]<>>=vt,w-=vt,i.back+=vt}if(c>>>=kt,w-=kt,i.back+=kt,i.length=xt,0===mt){i.mode=dt;break}if(32&mt){i.back=-1,i.mode=G;break}if(64&mt){e.msg="invalid literal/length code",i.mode=ht;break}i.extra=15&mt,i.mode=at;case at:if(i.extra){for(St=i.extra;St>w;){if(0===f)break e;f--,c+=a[o++]<>>=i.extra,w-=i.extra,i.back+=i.extra}i.was=i.length,i.mode=st;case st:for(;Zt=i.distcode[c&(1<>>24,mt=Zt>>>16&255,xt=65535&Zt,!(w>=kt);){if(0===f)break e;f--,c+=a[o++]<>vt)],kt=Zt>>>24,mt=Zt>>>16&255,xt=65535&Zt,!(w>=vt+kt);){if(0===f)break e;f--,c+=a[o++]<>>=vt,w-=vt,i.back+=vt}if(c>>>=kt,w-=kt,i.back+=kt,64&mt){e.msg="invalid distance code",i.mode=ht;break}i.offset=xt,i.extra=15&mt,i.mode=rt;case rt:if(i.extra){for(St=i.extra;St>w;){if(0===f)break e;f--,c+=a[o++]<>>=i.extra,w-=i.extra,i.back+=i.extra}if(i.offset>i.dmax){e.msg="invalid distance too far back",i.mode=ht;break}i.mode=ot;case ot:if(0===l)break e;if(k=_-l,i.offset>k){if(k=i.offset-k,k>i.whave&&i.sane){e.msg="invalid distance too far back",i.mode=ht;break}k>i.wnext?(k-=i.wnext,bt=i.wsize-k):bt=i.wnext-k,k>i.length&&(k=i.length),_t=i.window}else _t=r,bt=d-i.offset,k=i.length;k>l&&(k=l),l-=k,i.length-=k;do r[d++]=_t[bt++];while(--k);0===i.length&&(i.mode=nt);break;case dt:if(0===l)break e;r[d++]=i.length,l--,i.mode=nt;break;case ft:if(i.wrap){for(;32>w;){if(0===f)break e;f--,c|=a[o++]<w;){if(0===f)break e;f--,c+=a[o++]<=Z;Z++)C[Z]=0;for(z=0;y>z;z++)C[p[e.lens_index+z]]++;for(O=E,A=n;A>=1&&0===C[A];A--);if(O>A&&(O=A),0===A)return B[e.table_index++]=20971520,B[e.table_index++]=20971520,e.bits=1,0;for(R=1;A>R&&0===C[R];R++);for(R>O&&(O=R),T=1,Z=1;n>=Z;Z++)if(T<<=1,T-=C[Z],0>T)return-1;if(T>0&&(g===r||1!==A))return-1;for(H[1]=0,Z=1;n>Z;Z++)H[Z+1]=H[Z]+C[Z];for(z=0;y>z;z++)0!==p[e.lens_index+z]&&(S[H[p[e.lens_index+z]]++]=z);switch(g){case r:L=K=S,k=19;break;case o:L=f,D-=257,K=l,M-=257,k=256;break;default:L=c,K=h,k=-1}if(U=0,z=0,Z=R,_=e.table_index,N=O,I=0,w=-1,F=1<a||g===d&&F>s)return 1;for(var P=0;;){P++,m=Z-I,S[z]k?(x=K[M+S[z]],v=L[D+S[z]]):(x=96,v=0),t=1<>I)+u]=m<<24|x<<16|v|0;while(0!==u);for(t=1<>=1;if(0!==t?(U&=t-1,U+=t):U=0,z++,0===--C[Z]){if(Z===A)break;Z=p[e.lens_index+S[z]]}if(Z>O&&(U&b)!==w){for(0===I&&(I=O),_+=R,N=Z-I,T=1<N+I&&(T-=C[N+I],!(0>=T));)N++,T<<=1;if(F+=1<a||g===d&&F>s)return 1;w=U&b,B[w]=O<<24|N<<16|_-e.table_index}}return 0!==U&&(B[_+U]=Z-I<<24|64<<16|0),e.table_index+=F,e.bits=O,0}},{"./utils":9}],8:[function(e,t){"use strict";t.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],9:[function(e,t,i){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;i.assign=function(e){for(var t=Array.prototype.slice.call(arguments,1);t.length;){var i=t.shift();if(i){if("object"!=typeof i)throw new TypeError(i+"must be non-object");for(var n in i)i.hasOwnProperty(n)&&(e[n]=i[n])}}return e},i.shrinkBuf=function(e,t){return e.length===t?e:e.subarray?e.subarray(0,t):(e.length=t,e)};var a={arraySet:function(e,t,i,n,a){if(t.subarray)return void e.set(t.subarray(i,i+n),a);for(var s=0;n>s;s++)e[a+s]=t[i+s]},flattenChunks:function(e){var t,i,n,a,s,r;for(n=0,t=0,i=e.length;i>t;t++)n+=e[t].length;for(r=new Uint8Array(n),a=0,t=0,i=e.length;i>t;t++)s=e[t],r.set(s,a),a+=s.length;return r}},s={arraySet:function(e,t,i,n,a){for(var s=0;n>s;s++)e[a+s]=t[i+s]},flattenChunks:function(e){return[].concat.apply([],e)}};i.setTyped=function(e){e?(i.Buf8=Uint8Array,i.Buf16=Uint16Array,i.Buf32=Int32Array,i.assign(i,a)):(i.Buf8=Array,i.Buf16=Array,i.Buf32=Array,i.assign(i,s))},i.setTyped(n)},{}],10:[function(e,t){"use strict";function i(){this.next_in=null,this.next_in_index=0,this.avail_in=0,this.total_in=0,this.next_out=null,this.next_out_index=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}t.exports=i},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/plugins/help/plugintest.html b/plugins/help/plugintest.html new file mode 100644 index 00000000..07353c8c --- /dev/null +++ b/plugins/help/plugintest.html @@ -0,0 +1,15 @@ + + + + + +

    The plugin help page

    + +

    +Not much to say ... it's a plugin test, after all! See the page source for +implementation details. +

    +See also: +Adding Local Analysis Tasks (Plugins) to JS9 + + diff --git a/plugins/imexam/3dplot.js b/plugins/imexam/3dplot.js new file mode 100644 index 00000000..52bf235c --- /dev/null +++ b/plugins/imexam/3dplot.js @@ -0,0 +1,1486 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o"); + } + + JS9.RegisterPlugin("ImExam", "3dPlot", pluginInit, { + menu: "analysis", + + menuItem: "3dPlot", + winTitle: "3dPlot", + help: "imexam/imexam.html#3dplot", + + toolbarSeparate: true, + + onregionschange: pluginUpdate, + winDims: [250, 250], + }); +}()); + +},{"./JSSurfacePlot-V1.7/javascript/ColourGradient":2,"./JSSurfacePlot-V1.7/javascript/SurfacePlot":3}],2:[function(require,module,exports){ +/* + * ColourGradient.js + * + * + * Copyright (c) 2011 Greg Ross + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the project's author nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * Class that is used to define a path through RGB space. + * @author Greg Ross + * @constructor + * @param minValue the value that will return the first colour on the path in RGB space + * @param maxValue the value that will return the last colour on the path in RGB space + * @param rgbColourArray the set of colours that defines the dirctional path through RGB space. + * The length of the array must be greater than two. + */ +greg.ross.visualisation.ColourGradient = function(minValue, maxValue, rgbColourArray) +{ + function RGB2HTML(red, green, blue) + { + var decColor = red + 256 * green + 65536 * blue; + return decColor.toString(16); + } + + /** + * Return a colour from a position on the path in RGB space that is proportioal to + * the number specified in relation to the minimum and maximum values from which the + * bounds of the path are derived. + * @member greg.ross.visualisation.ColourGradient + * @param value + */ + this.getColour = function(value) + { + if ( isNaN(value) || value < minValue || value > maxValue || rgbColourArray.length == 1) + { + var colr = { + red: rgbColourArray[0].red, + green:rgbColourArray[0].green, + blue:rgbColourArray[0].blue + }; + + return colr; + } + + var scaledValue = mapValueToZeroOneInterval(value, minValue, maxValue); + + return getPointOnColourRamp(scaledValue); + } + + function getPointOnColourRamp(value) + { + var numberOfColours = rgbColourArray.length; + var scaleWidth = 1 / (numberOfColours - 1); + var index = (value / scaleWidth); + var index = parseInt(index + ""); + + index = index >= (numberOfColours - 1) ? (numberOfColours - 2): index; + + var rgb1 = rgbColourArray[index]; + var rgb2 = rgbColourArray[index + 1]; + + var closestToOrigin, furthestFromOrigin; + + if (distanceFromRgbOrigin(rgb1) > distanceFromRgbOrigin(rgb2)) + { + closestToOrigin = rgb2; + furthestFromOrigin = rgb1; + } + else + { + closestToOrigin = rgb1; + furthestFromOrigin = rgb2; + } + + var t; + + if (closestToOrigin == rgb2) + t = 1 - mapValueToZeroOneInterval(value, index * scaleWidth, (index + 1) * scaleWidth); + else + t = mapValueToZeroOneInterval(value, index * scaleWidth, (index + 1) * scaleWidth); + + var diff = [ + t * (furthestFromOrigin.red - closestToOrigin.red), + t * (furthestFromOrigin.green - closestToOrigin.green), + t * (furthestFromOrigin.blue - closestToOrigin.blue)]; + + var r = closestToOrigin.red + diff[0]; + var g = closestToOrigin.green + diff[1]; + var b = closestToOrigin.blue + diff[2]; + + r = parseInt(r); + g = parseInt(g); + b = parseInt(b); + + var colr = { + red:r, + green:g, + blue:b + }; + + return colr; + } + + function distanceFromRgbOrigin(rgb) + { + return (rgb.red * rgb.red) + (rgb.green * rgb.green) + (rgb.blue * rgb.blue); + } + + function mapValueToZeroOneInterval(value, minValue, maxValue) + { + if (minValue == maxValue) return 0; + + var factor = (value - minValue) / (maxValue - minValue); + return factor; + } +} + + +},{}],3:[function(require,module,exports){ +/* + * SurfacePlot.js + * + * + * Copyright (c) 2011 Greg Ross + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the project's author nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * Register the name space + * *********************** + */ +function registerNameSpace(ns){ + var nsParts = ns.split("."); + var root = window; + var n = nsParts.length; + + for (var i = 0; i < n; i++) { + if (typeof root[nsParts[i]] == "undefined") + root[nsParts[i]] = new Object(); + + root = root[nsParts[i]]; + } +} + +registerNameSpace("greg.ross.visualisation"); + +/* + * This is the main class and entry point of the tool + * and represents the Google viz API. + * *************************************************** + */ +greg.ross.visualisation.SurfacePlot = function(container){ + this.containerElement = container; +} + +greg.ross.visualisation.SurfacePlot.prototype.draw = function(data, options) { + var xPos = options.xPos; + var yPos = options.yPos; + var w = options.width; + var h = options.height; + var colourGradient = options.colourGradient; + var fillPolygons = options.fillPolygons; + var tooltips = options.tooltips; + var xTitle = options.xTitle; + var yTitle = options.yTitle; + var zTitle = options.zTitle; + var restrictXRotation = options.restrictXRotation; + + if (this.surfacePlot == undefined) + this.surfacePlot = new greg.ross.visualisation.JSSurfacePlot(xPos, yPos, w, h, colourGradient, this.containerElement, tooltips, fillPolygons, xTitle, yTitle, zTitle, restrictXRotation); + + this.surfacePlot.redraw(data); +} + +/* + * This class does most of the work. + * ********************************* + */ +greg.ross.visualisation.JSSurfacePlot = function(x, y, width, height, colourGradient, targetElement, tooltips, fillRegions, xTitle, yTitle, zTitle, restrictXRotation){ + this.targetDiv; + var id = allocateId(); + var canvas; + var canvasContext = null; + + var scale = greg.ross.visualisation.JSSurfacePlot.DEFAULT_SCALE; + + var currentZAngle = greg.ross.visualisation.JSSurfacePlot.DEFAULT_Z_ANGLE; + var currentXAngle = greg.ross.visualisation.JSSurfacePlot.DEFAULT_X_ANGLE; + + this.data = null; + var canvas_support_checked = false; + var canvas_supported = true; + var data3ds = null; + var displayValues = null; + var numXPoints; + var numYPoints; + var transformation; + var cameraPosition; + var colourGradient; + var colourGradientObject; + var renderPoints = false; + + var mouseDown1 = false; + var mouseDown3 = false; + var mousePosX = null; + var mousePosY = null; + var lastMousePos = new greg.ross.visualisation.Point(0, 0); + var mouseButton1Up = null; + var mouseButton3Up = null; + var mouseButton1Down = new greg.ross.visualisation.Point(0, 0); + var mouseButton3Down = new greg.ross.visualisation.Point(0, 0); + var closestPointToMouse = null; + var xAxisHeader = ""; + var yAxisHeader = ""; + var zAxisHeader = ""; + var xAxisTitleLabel = new greg.ross.visualisation.Tooltip(true); + var yAxisTitleLabel = new greg.ross.visualisation.Tooltip(true); + var zAxisTitleLabel = new greg.ross.visualisation.Tooltip(true); + var tTip = new greg.ross.visualisation.Tooltip(false); + + function init(){ + transformation = new greg.ross.visualisation.Th3dtran(); + + createTargetDiv(); + + if (!targetDiv) + return; + + createCanvas(); + } + + function hideTooltip(){ + tTip.hide(); + } + + function displayTooltip(e){ + var position = new greg.ross.visualisation.Point(e.x, e.y); + tTip.show(tooltips[closestPointToMouse], 200); + } + + function render(data){ + canvasContext.clearRect(0, 0, canvas.width, canvas.height); + canvasContext.fillStyle = '#000'; + canvasContext.fillRect(0, 0, canvas.width, canvas.height); + this.data = data; + + var canvasWidth = width; + var canvasHeight = height; + + var minMargin = 20; + var drawingDim = canvasWidth - minMargin * 2; + var marginX = minMargin; + var marginY = minMargin; + + transformation.init(); + transformation.rotate(currentXAngle, 0.0, currentZAngle); + transformation.scale(scale); + transformation.translate(drawingDim / 2.0 + marginX, (drawingDim / 3.0*2) + marginY, 0.0); + + cameraPosition = new greg.ross.visualisation.Point3D(drawingDim / 2.0 + marginX, drawingDim / 2.0 + marginY, -1000.0); + + if (renderPoints) { + for (i = 0; i < data3ds.length; i++) { + var point3d = data3ds[i]; + canvasContext.fillStyle = '#ff2222'; + var transformedPoint = transformation.ChangeObjectPoint(point3d); + transformedPoint.dist = distance(transformedPoint, cameraPosition); + + var x = transformedPoint.ax; + var y = transformedPoint.ay; + + canvasContext.beginPath(); + var dotSize = greg.ross.visualisation.JSSurfacePlot.DATA_DOT_SIZE; + + canvasContext.arc((x - (dotSize / 2)), (y - (dotSize / 2)), 1, 0, self.Math.PI * 2, true); + canvasContext.fill(); + } + } + + var axes = createAxes(); + var polygons = createPolygons(data3ds); + + for (i = 0; i < axes.length; i++) { + polygons[polygons.length] = axes[i]; + } + + // Sort the polygons so that the closest ones are rendered last + // and therefore are not occluded by those behind them. + // This is really Painter's algorithm. + polygons.sort(greg.ross.visualisation.PolygonComaparator); + //polygons = sort(polygons); + + canvasContext.lineWidth = 1; + canvasContext.strokeStyle = '#888'; + canvasContext.lineJoin = "round"; + + for (i = 0; i < polygons.length; i++) { + var polygon = polygons[i]; + + if (polygon.isAnAxis()) { + var p1 = polygon.getPoint(0); + var p2 = polygon.getPoint(1); + + canvasContext.beginPath(); + canvasContext.moveTo(p1.ax, p1.ay); + canvasContext.lineTo(p2.ax, p2.ay); + canvasContext.stroke(); + } + else { + var p1 = polygon.getPoint(0); + var p2 = polygon.getPoint(1); + var p3 = polygon.getPoint(2); + var p4 = polygon.getPoint(3); + + var colourValue = (p1.lz * 1.0 + p2.lz * 1.0 + p3.lz * 1.0 + p4.lz * 1.0) / 4.0; + + // if (colourValue < 0) + // colourValue *= -1; + + var rgbColour = colourGradientObject.getColour(colourValue); + var colr = "rgb(" + rgbColour.red + "," + rgbColour.green + "," + rgbColour.blue + ")"; + canvasContext.fillStyle = colr; + + canvasContext.beginPath(); + canvasContext.moveTo(p1.ax, p1.ay); + canvasContext.lineTo(p2.ax, p2.ay); + canvasContext.lineTo(p3.ax, p3.ay); + canvasContext.lineTo(p4.ax, p4.ay); + canvasContext.lineTo(p1.ax, p1.ay); + + if (fillRegions) + canvasContext.fill(); + else + canvasContext.stroke(); + } + } + + canvasContext.stroke(); + + if (supports_canvas()) + renderAxisText(axes); + } + + function renderAxisText(axes){ + var xLabelPoint = new greg.ross.visualisation.Point3D(0.0, 0.5, 0.0); + var yLabelPoint = new greg.ross.visualisation.Point3D(-0.5, 0.0, 0.0); + var zLabelPoint = new greg.ross.visualisation.Point3D(-0.5, 0.5, 0.5); + + var transformedxLabelPoint = transformation.ChangeObjectPoint(xLabelPoint); + var transformedyLabelPoint = transformation.ChangeObjectPoint(yLabelPoint); + var transformedzLabelPoint = transformation.ChangeObjectPoint(zLabelPoint); + + var xAxis = axes[0]; + var yAxis = axes[1]; + var zAxis = axes[2]; + + canvasContext.fillStyle = '#fff'; + + if (xAxis.distanceFromCamera > yAxis.distanceFromCamera) { + var xAxisLabelPosX = transformedxLabelPoint.ax; + var xAxisLabelPosY = transformedxLabelPoint.ay; + canvasContext.fillText(xTitle, xAxisLabelPosX, xAxisLabelPosY); + } + + if (xAxis.distanceFromCamera < yAxis.distanceFromCamera) { + var yAxisLabelPosX = transformedyLabelPoint.ax; + var yAxisLabelPosY = transformedyLabelPoint.ay; + canvasContext.fillText(yTitle, yAxisLabelPosX, yAxisLabelPosY); + } + + if (xAxis.distanceFromCamera < zAxis.distanceFromCamera) { + var zAxisLabelPosX = transformedzLabelPoint.ax; + var zAxisLabelPosY = transformedzLabelPoint.ay; + canvasContext.fillText(zTitle, zAxisLabelPosX, zAxisLabelPosY); + } + } + + var sort = function(array){ + var len = array.length; + + if (len < 2) { + return array; + } + + var pivot = Math.ceil(len / 2); + return merge(sort(array.slice(0, pivot)), sort(array.slice(pivot))); + } + + var merge = function(left, right){ + var result = []; + while ((left.length > 0) && (right.length > 0)) { + if (left[0].distanceFromCamera < right[0].distanceFromCamera) { + result.push(left.shift()); + } + else { + result.push(right.shift()); + } + } + + result = result.concat(left, right); + return result; + } + + + function createAxes(){ + var axisOrigin = new greg.ross.visualisation.Point3D(-0.5, 0.5, 0); + var xAxisEndPoint = new greg.ross.visualisation.Point3D(0.5, 0.5, 0); + var yAxisEndPoint = new greg.ross.visualisation.Point3D(-0.5, -0.5, 0); + var zAxisEndPoint = new greg.ross.visualisation.Point3D(-0.5, 0.5, 1); + + var transformedAxisOrigin = transformation.ChangeObjectPoint(axisOrigin); + var transformedXAxisEndPoint = transformation.ChangeObjectPoint(xAxisEndPoint); + var transformedYAxisEndPoint = transformation.ChangeObjectPoint(yAxisEndPoint); + var transformedZAxisEndPoint = transformation.ChangeObjectPoint(zAxisEndPoint); + + var axes = new Array(); + + var xAxis = new greg.ross.visualisation.Polygon(cameraPosition, true); + xAxis.addPoint(transformedAxisOrigin); + xAxis.addPoint(transformedXAxisEndPoint); + xAxis.calculateCentroid(); + xAxis.calculateDistance(); + axes[axes.length] = xAxis; + + var yAxis = new greg.ross.visualisation.Polygon(cameraPosition, true); + yAxis.addPoint(transformedAxisOrigin); + yAxis.addPoint(transformedYAxisEndPoint); + yAxis.calculateCentroid(); + yAxis.calculateDistance(); + axes[axes.length] = yAxis; + + var zAxis = new greg.ross.visualisation.Polygon(cameraPosition, true); + zAxis.addPoint(transformedAxisOrigin); + zAxis.addPoint(transformedZAxisEndPoint); + zAxis.calculateCentroid(); + zAxis.calculateDistance(); + axes[axes.length] = zAxis; + + return axes; + } + + function createPolygons(data3D){ + var i; + var j; + var polygons = new Array(); + var index = 0; + + for (i = 0; i < numXPoints - 1; i++) { + for (j = 0; j < numYPoints - 1; j++) { + var polygon = new greg.ross.visualisation.Polygon(cameraPosition, false); + + var p1 = transformation.ChangeObjectPoint(data3D[j + (i * numYPoints)]); + var p2 = transformation.ChangeObjectPoint(data3D[j + (i * numYPoints) + numYPoints]); + var p3 = transformation.ChangeObjectPoint(data3D[j + (i * numYPoints) + numYPoints + 1]); + var p4 = transformation.ChangeObjectPoint(data3D[j + (i * numYPoints) + 1]); + + polygon.addPoint(p1); + polygon.addPoint(p2); + polygon.addPoint(p3); + polygon.addPoint(p4); + polygon.calculateCentroid(); + polygon.calculateDistance(); + + polygons[index] = polygon; + index++; + } + } + + return polygons; + } + + function getDefaultColourRamp(){ + var colour1 = { + red: 0, + green: 0, + blue: 255 + }; + var colour2 = { + red: 0, + green: 255, + blue: 255 + }; + var colour3 = { + red: 0, + green: 255, + blue: 0 + }; + var colour4 = { + red: 255, + green: 255, + blue: 0 + }; + var colour5 = { + red: 255, + green: 0, + blue: 0 + }; + return [colour1, colour2, colour3, colour4, colour5]; + } + + this.redraw = function(data){ + numXPoints = data.getNumberOfRows() * 1.0; + numYPoints = data.getNumberOfColumns() * 1.0; + + var minZValue = Number.MAX_VALUE; + var maxZValue = Number.MIN_VALUE; + + for (var i = 0; i < numXPoints; i++) { + for (var j = 0; j < numYPoints; j++) { + var value = data.getFormattedValue(i, j) * 1.0; + + if (value < minZValue) + minZValue = value; + + if (value > maxZValue) + maxZValue = value; + } + } + + var cGradient; + + if (colourGradient) + cGradient = colourGradient; + else + cGradient = getDefaultColourRamp(); + + // if (minZValue < 0 && (minZValue*-1) > maxZValue) + // maxZValue = minZValue*-1; + + colourGradientObject = new greg.ross.visualisation.ColourGradient(minZValue, maxZValue, cGradient); + + var canvasWidth = width; + var canvasHeight = height; + + var minMargin = 20; + var drawingDim = canvasWidth - minMargin * 2; + var marginX = minMargin; + var marginY = minMargin; + + if (canvasWidth > canvasHeight) { + drawingDim = canvasHeight - minMargin * 2; + marginX = (canvasWidth - drawingDim) / 2; + } + else + if (canvasWidth < canvasHeight) { + drawingDim = canvasWidth - minMargin * 2; + marginY = (canvasHeight - drawingDim) / 2; + } + + var xDivision = 1 / (numXPoints - 1); + var yDivision = 1 / (numYPoints - 1); + var xPos, yPos; + var i, j; + var numPoints = numXPoints * numYPoints; + data3ds = new Array(); + var index = 0; + + // Calculate 3D points. + for (i = 0, xPos = -0.5; i < numXPoints; i++, xPos += xDivision) { + for (j = 0, yPos = 0.5; j < numYPoints; j++, yPos -= yDivision) { + var x = xPos; + var y = yPos; + + data3ds[index] = new greg.ross.visualisation.Point3D(x, y, data.getFormattedValue(i, j)); + index++; + } + } + + render(data); + } + + function allocateId(){ + var count = 0; + var name = "surfacePlot"; + + do { + count++; + } + while (document.getElementById(name + count)) + + return name + count; + } + + function createTargetDiv(){ + this.targetDiv = document.createElement("div"); + this.targetDiv.id = id; + this.targetDiv.className = "surfaceplot"; + this.targetDiv.style.background = '#ffffff' + this.targetDiv.style.position = 'absolute'; + + if (!targetElement) + document.body.appendChild(this.targetDiv); + else { + this.targetDiv.style.position = 'relative'; + targetElement.appendChild(this.targetDiv); + } + + this.targetDiv.style.left = x + "px"; + this.targetDiv.style.top = y + "px"; + } + + function getInternetExplorerVersion() // Returns the version of Internet Explorer or a -1 + // (indicating the use of another browser). + { + var rv = -1; // Return value assumes failure. + if (navigator.appName == 'Microsoft Internet Explorer') { + var ua = navigator.userAgent; + var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) != null) + rv = parseFloat(RegExp.$1); + } + return rv; + } + + function supports_canvas(){ + if (canvas_support_checked) return canvas_supported; + + canvas_support_checked = true; + canvas_supported = !!document.createElement('canvas').getContext; + return canvas_supported; + } + + function createCanvas(){ + canvas = document.createElement("canvas"); + + if (!supports_canvas()) { + G_vmlCanvasManager.initElement(canvas); + canvas.style.width = width; + canvas.style.height = height; + } + + canvas.className = "surfacePlotCanvas"; + canvas.setAttribute("width", width); + canvas.setAttribute("height", height); + canvas.style.left = '0px'; + canvas.style.top = '0px'; + + targetDiv.appendChild(canvas); + + canvasContext = canvas.getContext("2d"); + canvasContext.font = "bold 18px sans-serif"; + canvasContext.clearRect(0, 0, canvas.width, canvas.height); + + canvasContext.fillStyle = '#000'; + + canvasContext.fillRect(0, 0, canvas.width, canvas.height); + + canvasContext.beginPath(); + canvasContext.rect(0, 0, canvas.width, canvas.height); + canvasContext.strokeStyle = '#888'; + canvasContext.stroke(); + + canvas.onmousemove = mouseIsMoving; + canvas.onmouseout = hideTooltip; + canvas.onmousedown = mouseDownd; + canvas.onmouseup = mouseUpd; + + //added by edupont + canvas.addEventListener("touchstart", mouseDownd, false); + canvas.addEventListener("touchmove", mouseIsMoving, false); + canvas.addEventListener("touchend", mouseUpd, false); + canvas.addEventListener("touchcancel", hideTooltip, false); + } + + function mouseDownd(e){ + if (isShiftPressed(e)) { + mouseDown3 = true; + mouseButton3Down = getMousePositionFromEvent(e); + } + else { + mouseDown1 = true; + mouseButton1Down = getMousePositionFromEvent(e); + } + } + + function mouseUpd(e){ + if (mouseDown1) { + mouseButton1Up = lastMousePos; + } + else + if (mouseDown3) { + mouseButton3Up = lastMousePos; + } + + mouseDown1 = false; + mouseDown3 = false; + } + + function mouseIsMoving(e){ + var currentPos = getMousePositionFromEvent(e); + + if (mouseDown1) { + hideTooltip(); + calculateRotation(currentPos); + } + else + if (mouseDown3) { + hideTooltip(); + calculateScale(currentPos); + } + else { + closestPointToMouse = null; + var closestDist = Number.MAX_VALUE; + + for (var i = 0; i < data3ds.length; i++) { + var point = data3ds[i]; + var dist = distance({ + x: point.ax, + y: point.ay + }, currentPos); + + if (dist < closestDist) { + closestDist = dist; + closestPointToMouse = i; + } + } + + if (closestDist > 16) { + hideTooltip(); + return; + } + + displayTooltip(currentPos); + } + + return false; + } + + function isShiftPressed(e){ + var shiftPressed = 0; + + if (parseInt(navigator.appVersion) > 3) { + var evt = navigator.appName == "Netscape" ? e : event; + + if (navigator.appName == "Netscape" && parseInt(navigator.appVersion) == 4) { + // NETSCAPE 4 CODE + var mString = (e.modifiers + 32).toString(2).substring(3, 6); + shiftPressed = (mString.charAt(0) == "1"); + } + else { + // NEWER BROWSERS [CROSS-PLATFORM] + shiftPressed = evt.shiftKey; + } + + if (shiftPressed) + return true; + } + + return false; + } + + function getMousePositionFromEvent(e){ + if (getInternetExplorerVersion() > -1) { + var e = window.event; + + if (e.srcElement.getAttribute('Stroked') == true) { + if (mousePosX == null || mousePosY == null) + return; + } + else { + mousePosX = e.offsetX; + mousePosY = e.offsetY; + } + } + else + if (e.layerX || e.layerX == 0) // Firefox + { + mousePosX = e.layerX; + mousePosY = e.layerY; + } + else if (e.offsetX || e.offsetX == 0) // Opera + { + mousePosX = e.offsetX; + mousePosY = e.offsetY; + } + else if (e.touches[0].pageX || e.touches[0].pageX == 0) //touch events + { + mousePosX = e.touches[0].pageX; + mousePosY = e.touches[0].pageY; + } + + var currentPos = new greg.ross.visualisation.Point(mousePosX, mousePosY); + + return currentPos; + } + + function calculateRotation(e){ + lastMousePos = new greg.ross.visualisation.Point(greg.ross.visualisation.JSSurfacePlot.DEFAULT_Z_ANGLE, greg.ross.visualisation.JSSurfacePlot.DEFAULT_X_ANGLE); + + if (mouseButton1Up == null) { + mouseButton1Up = new greg.ross.visualisation.Point(greg.ross.visualisation.JSSurfacePlot.DEFAULT_Z_ANGLE, greg.ross.visualisation.JSSurfacePlot.DEFAULT_X_ANGLE); + } + + if (mouseButton1Down != null) { + lastMousePos = new greg.ross.visualisation.Point(mouseButton1Up.x + (mouseButton1Down.x - e.x),// + mouseButton1Up.y + (mouseButton1Down.y - e.y)); + } + + currentZAngle = lastMousePos.x % 360; + currentXAngle = lastMousePos.y % 360; + + if (restrictXRotation) { + + if (currentXAngle < 0) + currentXAngle = 0; + else + if (currentXAngle > 90) + currentXAngle = 90; + + } + + closestPointToMouse = null; + render(data); + } + + function calculateScale(e){ + lastMousePos = new greg.ross.visualisation.Point(0, greg.ross.visualisation.JSSurfacePlot.DEFAULT_SCALE / greg.ross.visualisation.JSSurfacePlot.SCALE_FACTOR); + + if (mouseButton3Up == null) { + mouseButton3Up = new greg.ross.visualisation.Point(0, greg.ross.visualisation.JSSurfacePlot.DEFAULT_SCALE / greg.ross.visualisation.JSSurfacePlot.SCALE_FACTOR); + } + + if (mouseButton3Down != null) { + lastMousePos = new greg.ross.visualisation.Point(mouseButton3Up.x + (mouseButton3Down.x - e.x),// + mouseButton3Up.y + (mouseButton3Down.y - e.y)); + } + + scale = lastMousePos.y * greg.ross.visualisation.JSSurfacePlot.SCALE_FACTOR; + + if (scale < greg.ross.visualisation.JSSurfacePlot.MIN_SCALE) + scale = greg.ross.visualisation.JSSurfacePlot.MIN_SCALE + 1; + else + if (scale > greg.ross.visualisation.JSSurfacePlot.MAX_SCALE) + scale = greg.ross.visualisation.JSSurfacePlot.MAX_SCALE - 1; + + lastMousePos.y = scale / greg.ross.visualisation.JSSurfacePlot.SCALE_FACTOR; + + closestPointToMouse = null; + render(data); + } + + init(); +} + +/** + * Given two coordinates, return the Euclidean distance + * between them + */ +function distance(p1, p2){ + return Math.sqrt(((p1.x - p2.x) * + (p1.x - + p2.x)) + + ((p1.y - p2.y) * (p1.y - p2.y))); +} + +/* + * Matrix3d: This class represents a 3D matrix. + * ******************************************** + */ +greg.ross.visualisation.Matrix3d = function(){ + this.matrix = new Array(); + this.numRows = 4; + this.numCols = 4; + + this.init = function(){ + this.matrix = new Array(); + + for (var i = 0; i < this.numRows; i++) { + this.matrix[i] = new Array(); + } + } + + this.getMatrix = function(){ + return this.matrix; + } + + this.matrixReset = function(){ + for (var i = 0; i < this.numRows; i++) { + for (var j = 0; j < this.numCols; j++) { + this.matrix[i][j] = 0; + } + } + } + + this.matrixIdentity = function(){ + this.matrixReset(); + this.matrix[0][0] = this.matrix[1][1] = this.matrix[2][2] = this.matrix[3][3] = 1; + } + + this.matrixCopy = function(newM){ + var temp = new greg.ross.visualisation.Matrix3d(); + var i, j; + + for (i = 0; i < this.numRows; i++) { + for (j = 0; j < this.numCols; j++) { + temp.getMatrix()[i][j] = (this.matrix[i][0] * newM.getMatrix()[0][j]) + (this.matrix[i][1] * newM.getMatrix()[1][j]) + (this.matrix[i][2] * newM.getMatrix()[2][j]) + (this.matrix[i][3] * newM.getMatrix()[3][j]); + } + } + + for (i = 0; i < this.numRows; i++) { + this.matrix[i][0] = temp.getMatrix()[i][0]; + this.matrix[i][1] = temp.getMatrix()[i][1]; + this.matrix[i][2] = temp.getMatrix()[i][2]; + this.matrix[i][3] = temp.getMatrix()[i][3]; + } + } + + this.matrixMult = function(m1, m2){ + var temp = new greg.ross.visualisation.Matrix3d(); + var i, j; + + for (i = 0; i < this.numRows; i++) { + for (j = 0; j < this.numCols; j++) { + temp.getMatrix()[i][j] = (m2.getMatrix()[i][0] * m1.getMatrix()[0][j]) + (m2.getMatrix()[i][1] * m1.getMatrix()[1][j]) + (m2.getMatrix()[i][2] * m1.getMatrix()[2][j]) + (m2.getMatrix()[i][3] * m1.getMatrix()[3][j]); + } + } + + for (i = 0; i < this.numRows; i++) { + m1.getMatrix()[i][0] = temp.getMatrix()[i][0]; + m1.getMatrix()[i][1] = temp.getMatrix()[i][1]; + m1.getMatrix()[i][2] = temp.getMatrix()[i][2]; + m1.getMatrix()[i][3] = temp.getMatrix()[i][3]; + } + } + + this.init(); +} + +/* + * Point3D: This class represents a 3D point. + * ****************************************** + */ +greg.ross.visualisation.Point3D = function(x, y, z){ + this.displayValue = ""; + + this.lx; + this.ly; + this.lz; + this.lt; + + this.wx; + this.wy; + this.wz; + this.wt; + + this.ax; + this.ay; + this.az; + this.at; + + this.dist; + + this.initPoint = function(){ + this.lx = this.ly = this.lz = this.ax = this.ay = this.az = this.at = this.wx = this.wy = this.wz = 0; + this.lt = this.wt = 1; + } + + this.init = function(x, y, z){ + this.initPoint(); + this.lx = x; + this.ly = y; + this.lz = z; + + this.ax = this.lx; + this.ay = this.ly; + this.az = this.lz; + } + + function multiply(p){ + var Temp = new Point3D(); + Temp.lx = this.lx * p.lx; + Temp.ly = this.ly * p.ly; + Temp.lz = this.lz * p.lz; + return Temp; + } + + function getDisplayValue(){ + return displayValue; + } + + function setDisplayValue(displayValue){ + this.displayValue = displayValue; + } + + this.init(x, y, z); +} + +/* + * Polygon: This class represents a polygon on the surface plot. + * ************************************************************ + */ +greg.ross.visualisation.Polygon = function(cameraPosition, isAxis){ + this.points = new Array(); + this.cameraPosition = cameraPosition; + this.isAxis = isAxis; + this.centroid = null; + this.distanceFromCamera = null; + + this.isAnAxis = function(){ + return this.isAxis; + } + + this.addPoint = function(point){ + this.points[this.points.length] = point; + } + + this.distance = function(){ + return this.distance2(this.cameraPosition, this.centroid); + } + + this.calculateDistance = function(){ + this.distanceFromCamera = this.distance(); + } + + this.calculateCentroid = function(){ + var xCentre = 0; + var yCentre = 0; + var zCentre = 0; + + var numPoints = this.points.length * 1.0; + + for (var i = 0; i < numPoints; i++) { + xCentre += this.points[i].ax; + yCentre += this.points[i].ay; + zCentre += this.points[i].az; + } + + xCentre /= numPoints; + yCentre /= numPoints; + zCentre /= numPoints; + + this.centroid = new greg.ross.visualisation.Point3D(xCentre, yCentre, zCentre); + } + + this.distance2 = function(p1, p2){ + return ((p1.ax - p2.ax) * (p1.ax - p2.ax)) + ((p1.ay - p2.ay) * (p1.ay - p2.ay)) + ((p1.az - p2.az) * (p1.az - p2.az)); + } + + this.getPoint = function(i){ + return this.points[i]; + } +} + +/* + * PolygonComaparator: Class used to sort arrays of polygons. + * ************************************************************ + */ +greg.ross.visualisation.PolygonComaparator = function(p1, p2){ + var diff = p1.distanceFromCamera - p2.distanceFromCamera; + + if (diff == 0) + return 0; + else + if (diff < 0) + return -1; + else + if (diff > 0) + return 1; + + return 0; +} + +/* + * Th3dtran: Class for matrix manipuation. + * ************************************************************ + */ +greg.ross.visualisation.Th3dtran = function(){ + this.matrix; + this.rMat; + this.rMatrix; + this.objectMatrix; + this.local = true; + + this.init = function(){ + this.matrix = new greg.ross.visualisation.Matrix3d(); + this.rMat = new greg.ross.visualisation.Matrix3d(); + this.rMatrix = new greg.ross.visualisation.Matrix3d(); + this.objectMatrix = new greg.ross.visualisation.Matrix3d(); + + this.initMatrix(); + } + + this.initMatrix = function(){ + this.matrix.matrixIdentity(); + this.objectMatrix.matrixIdentity(); + } + + this.translate = function(x, y, z){ + this.rMat.matrixIdentity(); + this.rMat.getMatrix()[3][0] = x; + this.rMat.getMatrix()[3][1] = y; + this.rMat.getMatrix()[3][2] = z; + + if (this.local) { + this.objectMatrix.matrixCopy(this.rMat); + } + else { + this.matrix.matrixCopy(this.rMat); + } + } + + this.rotate = function(x, y, z){ + var rx = x * (Math.PI / 180.0); + var ry = y * (Math.PI / 180.0); + var rz = z * (Math.PI / 180.0); + + this.rMatrix.matrixIdentity(); + this.rMat.matrixIdentity(); + this.rMat.getMatrix()[1][1] = Math.cos(rx); + this.rMat.getMatrix()[1][2] = Math.sin(rx); + this.rMat.getMatrix()[2][1] = -(Math.sin(rx)); + this.rMat.getMatrix()[2][2] = Math.cos(rx); + this.rMatrix.matrixMult(this.rMatrix, this.rMat); + + this.rMat.matrixIdentity(); + this.rMat.getMatrix()[0][0] = Math.cos(ry); + this.rMat.getMatrix()[0][2] = -(Math.sin(ry)); + this.rMat.getMatrix()[2][0] = Math.sin(ry); + this.rMat.getMatrix()[2][2] = Math.cos(ry); + this.rMat.matrixMult(this.rMatrix, this.rMat); + + this.rMat.matrixIdentity(); + this.rMat.getMatrix()[0][0] = Math.cos(rz); + this.rMat.getMatrix()[0][1] = Math.sin(rz); + this.rMat.getMatrix()[1][0] = -(Math.sin(rz)); + this.rMat.getMatrix()[1][1] = Math.cos(rz); + this.rMat.matrixMult(this.rMatrix, this.rMat); + + if (this.local) { + this.objectMatrix.matrixCopy(this.rMatrix); + } + else { + this.matrix.matrixCopy(this.rMatrix); + } + } + + this.scale = function(scale){ + this.rMat.matrixIdentity(); + this.rMat.getMatrix()[0][0] = scale; + this.rMat.getMatrix()[1][1] = scale; + this.rMat.getMatrix()[2][2] = scale; + + if (this.local) { + this.objectMatrix.matrixCopy(this.rMat); + } + else { + this.matrix.matrixCopy(this.rMat); + } + } + + this.changeLocalObject = function(p){ + p.wx = (p.ax * this.matrix.getMatrix()[0][0] + p.ay * this.matrix.getMatrix()[1][0] + p.az * this.matrix.getMatrix()[2][0] + this.matrix.getMatrix()[3][0]); + p.wy = (p.ax * this.matrix.getMatrix()[0][1] + p.ay * this.matrix.getMatrix()[1][1] + p.az * this.matrix.getMatrix()[2][1] + this.matrix.getMatrix()[3][1]); + p.wz = (p.ax * this.matrix.getMatrix()[0][2] + p.ay * this.matrix.getMatrix()[1][2] + p.az * this.matrix.getMatrix()[2][2] + this.matrix.getMatrix()[3][2]); + + return p; + } + + this.ChangeObjectPoint = function(p){ + p.ax = (p.lx * this.objectMatrix.getMatrix()[0][0] + p.ly * this.objectMatrix.getMatrix()[1][0] + p.lz * this.objectMatrix.getMatrix()[2][0] + this.objectMatrix.getMatrix()[3][0]); + p.ay = (p.lx * this.objectMatrix.getMatrix()[0][1] + p.ly * this.objectMatrix.getMatrix()[1][1] + p.lz * this.objectMatrix.getMatrix()[2][1] + this.objectMatrix.getMatrix()[3][1]); + p.az = (p.lx * this.objectMatrix.getMatrix()[0][2] + p.ly * this.objectMatrix.getMatrix()[1][2] + p.lz * this.objectMatrix.getMatrix()[2][2] + this.objectMatrix.getMatrix()[3][2]); + + return p; + } + + this.init(); +} + +/* + * Point: A simple 2D point. + * ************************************************************ + */ +greg.ross.visualisation.Point = function(x, y){ + this.x = x; + this.y = y; +} + +/* + * This function displays tooltips and was adapted from original code by Michael Leigeber. + * See http://www.leigeber.com/ + */ +greg.ross.visualisation.Tooltip = function(useExplicitPositions){ + var top = 3; + var left = 3; + var maxw = 300; + var speed = 10; + var timer = 20; + var endalpha = 95; + var alpha = 0; + var tt, t, c, b, h; + var ie = document.all ? true : false; + + this.show = function(v, w){ + if (tt == null) { + tt = document.createElement('div'); + tt.style.color = "#fff"; + + tt.style.position = 'absolute'; + tt.style.display = 'block'; + + t = document.createElement('div'); + + t.style.display = 'block'; + t.style.height = '5px'; + t.style.marginleft = '5px'; + t.style.overflow = 'hidden'; + + c = document.createElement('div'); + + b = document.createElement('div'); + + tt.appendChild(t); + tt.appendChild(c); + tt.appendChild(b); + document.body.appendChild(tt); + + if (!ie) { + tt.style.opacity = 0; + tt.style.filter = 'alpha(opacity=0)'; + } + else + tt.style.opacity = 1; + + + } + + if (!useExplicitPositions) + document.onmousemove = this.pos; + + tt.style.display = 'block'; + c.innerHTML = '' + v + ''; + tt.style.width = w ? w + 'px' : 'auto'; + + if (!w && ie) { + t.style.display = 'none'; + b.style.display = 'none'; + tt.style.width = tt.offsetWidth; + t.style.display = 'block'; + b.style.display = 'block'; + } + + if (tt.offsetWidth > maxw) { + tt.style.width = maxw + 'px'; + } + + h = parseInt(tt.offsetHeight) + top; + + if (!ie) { + clearInterval(tt.timer); + tt.timer = setInterval(function(){ + fade(1) + }, timer); + } + } + + this.setPos = function(e){ + tt.style.top = e.y + 'px'; + tt.style.left = e.x + 'px'; + } + + this.pos = function(e){ + var u = ie ? event.clientY + document.documentElement.scrollTop : e.pageY; + var l = ie ? event.clientX + document.documentElement.scrollLeft : e.pageX; + tt.style.top = (u - h) + 'px'; + tt.style.left = (l + left) + 'px'; + } + + function fade(d){ + var a = alpha; + + if ((a != endalpha && d == 1) || (a != 0 && d == -1)) { + var i = speed; + + if (endalpha - a < speed && d == 1) { + i = endalpha - a; + } + else + if (alpha < speed && d == -1) { + i = a; + } + + alpha = a + (i * d); + tt.style.opacity = alpha * .01; + tt.style.filter = 'alpha(opacity=' + alpha + ')'; + } + else { + clearInterval(tt.timer); + + if (d == -1) { + tt.style.display = 'none'; + } + } + } + + this.hide = function(){ + if (tt == null) + return; + + if (!ie) { + clearInterval(tt.timer); + tt.timer = setInterval(function(){ + fade(-1) + }, timer); + } + else { + tt.style.display = 'none'; + } + } +} + +greg.ross.visualisation.JSSurfacePlot.DEFAULT_X_ANGLE = 47; +greg.ross.visualisation.JSSurfacePlot.DEFAULT_Z_ANGLE = 47; +greg.ross.visualisation.JSSurfacePlot.DATA_DOT_SIZE = 3; +greg.ross.visualisation.JSSurfacePlot.DEFAULT_SCALE = 350; +greg.ross.visualisation.JSSurfacePlot.MIN_SCALE = 50; +greg.ross.visualisation.JSSurfacePlot.MAX_SCALE = 1100; +greg.ross.visualisation.JSSurfacePlot.SCALE_FACTOR = 1.4; + + +},{}]},{},[1]) diff --git a/plugins/imexam/4arrow.png b/plugins/imexam/4arrow.png new file mode 100644 index 00000000..36b875ad Binary files /dev/null and b/plugins/imexam/4arrow.png differ diff --git a/plugins/imexam/README b/plugins/imexam/README new file mode 100644 index 00000000..f54c5cf9 --- /dev/null +++ b/plugins/imexam/README @@ -0,0 +1 @@ +original source: https://github.com/jbroll/js9imexam diff --git a/plugins/imexam/contour.js b/plugins/imexam/contour.js new file mode 100644 index 00000000..18b83f04 --- /dev/null +++ b/plugins/imexam/contour.js @@ -0,0 +1,1036 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0 && i+k < ny ) { + xdat.data[j*nx + i] += kern[k+nk/2|0] * data.data[j*nx+i+k]; + } + } + } + } + for ( j = 0; j < ny; j++ ) { + for ( i = 0; i < nx; i++ ) { + for ( k = -nk/2|0; k < nk/2|0; k++ ) { + if ( j+k >= 0 && j+k < ny ) { + ydat.data[j*nx + i] += kern[k+nk/2|0] * xdat.data[(j+k)*nx+i]; + } + } + } + } + + return ydat; + }; + +}()); + +},{}],2:[function(require,module,exports){ +/** + * Copyright (c) 2010, Jason Davies. + * + * All rights reserved. This code is based on Bradley White's Java version, + * which is in turn based on Nicholas Yue's C++ version, which in turn is based + * on Paul D. Bourke's original Fortran version. See below for the respective + * copyright notices. + * + * See http://paulbourke.net/papers/conrec for the original + * paper by Paul D. Bourke. + * + * The vector conversion code is based on http://apptree.net/conrec.htm by + * Graham Cox. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996-1997 Nicholas Yue + * + * This software is copyrighted by Nicholas Yue. This code is based on Paul D. + * Bourke's CONREC.F routine. + * + * The authors hereby grant permission to use, copy, and distribute this + * software and its documentation for any purpose, provided that existing + * copyright notices are retained in all copies and that this notice is + * included verbatim in any distributions. Additionally, the authors grant + * permission to modify this software and its documentation for any purpose, + * provided that such modifications are not distributed without the explicit + * consent of the authors and that existing copyright notices are retained in + * all copies. Some of the algorithms implemented by this software are + * patented, observe all applicable patent law. + * + * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, + * EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS + * PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + * MODIFICATIONS. + */ + +var Conrec = (function() { + var EPSILON = 1e-20; + + var pointsEqual = function(a, b) { + var x = a.x - b.x, y = a.y - b.y; + return x * x + y * y < EPSILON; + } + + var reverseList = function(list) { + var pp = list.head; + + while (pp) { + // swap prev/next pointers + var temp = pp.next; + pp.next = pp.prev; + pp.prev = temp; + + // continue through the list + pp = temp; + } + + // swap head/tail pointers + var temp = list.head; + list.head = list.tail; + list.tail = temp; + } + + var ContourBuilder = function(level) { + this.count = 0; + this.level = level; + this.s = null; + this.count = 0; + } + ContourBuilder.prototype.remove_seq = function(list) { + // if list is the first item, static ptr s is updated + if (list.prev) { + list.prev.next = list.next; + } else { + this.s = list.next; + } + + if (list.next) { + list.next.prev = list.prev; + } + --this.count; + } + ContourBuilder.prototype.addSegment = function(a, b) { + var ss = this.s; + var ma = null; + var mb = null; + var prependA = false; + var prependB = false; + + if ( this.count++ > 100000 ) { + throw new Error("Too many calls to coutour AddSegment"); + } + + while (ss) { + if (ma == null) { + // no match for a yet + if (pointsEqual(a, ss.head.p)) { + ma = ss; + prependA = true; + } else if (pointsEqual(a, ss.tail.p)) { + ma = ss; + } + } + if (mb == null) { + // no match for b yet + if (pointsEqual(b, ss.head.p)) { + mb = ss; + prependB = true; + } else if (pointsEqual(b, ss.tail.p)) { + mb = ss; + } + } + // if we matched both no need to continue searching + if (mb != null && ma != null) { + break; + } else { + ss = ss.next; + } + } + + // c is the case selector based on which of ma and/or mb are set + var c = ((ma != null) ? 1 : 0) | ((mb != null) ? 2 : 0); + + switch(c) { + case 0: // both unmatched, add as new sequence + var aa = {p: a, prev: null}; + var bb = {p: b, next: null}; + aa.next = bb; + bb.prev = aa; + + // create sequence element and push onto head of main list. The order + // of items in this list is unimportant + ma = {head: aa, tail: bb, next: this.s, prev: null, closed: false}; + if (this.s) { + this.s.prev = ma; + } + this.s = ma; + + ++this.count; // not essential - tracks number of unmerged sequences + break; + + case 1: // a matched, b did not - thus b extends sequence ma + var pp = {p: b}; + + if (prependA) { + pp.next = ma.head; + pp.prev = null; + ma.head.prev = pp; + ma.head = pp; + } else { + pp.next = null; + pp.prev = ma.tail; + ma.tail.next = pp; + ma.tail = pp; + } + break; + + case 2: // b matched, a did not - thus a extends sequence mb + var pp = {p: a}; + + if (prependB) { + pp.next = mb.head; + pp.prev = null; + mb.head.prev = pp; + mb.head = pp; + } else { + pp.next = null; + pp.prev = mb.tail; + mb.tail.next = pp; + mb.tail = pp; + } + break; + + case 3: // both matched, can merge sequences + // if the sequences are the same, do nothing, as we are simply closing this path (could set a flag) + + if (ma === mb) { + var pp = {p: ma.tail.p, next: ma.head, prev: null}; + ma.head.prev = pp; + ma.head = pp; + ma.closed = true; + break; + } + + // there are 4 ways the sequence pair can be joined. The current setting of prependA and + // prependB will tell us which type of join is needed. For head/head and tail/tail joins + // one sequence needs to be reversed + switch((prependA ? 1 : 0) | (prependB ? 2 : 0)) { + case 0: // tail-tail + // reverse ma and append to mb + reverseList(ma); + // fall through to head/tail case + case 1: // head-tail + // ma is appended to mb and ma discarded + mb.tail.next = ma.head; + ma.head.prev = mb.tail; + mb.tail = ma.tail; + + //discard ma sequence record + this.remove_seq(ma); + break; + + case 3: // head-head + // reverse ma and append mb to it + reverseList(ma); + // fall through to tail/head case + case 2: // tail-head + // mb is appended to ma and mb is discarded + ma.tail.next = mb.head; + mb.head.prev = ma.tail; + ma.tail = mb.tail; + + //discard mb sequence record + this.remove_seq(mb); + break; + } + } + } + + /** + * Implements CONREC. + * + * @param {function} drawContour function for drawing contour. Defaults to a + * custom "contour builder", which populates the + * contours property. + */ + var Conrec = function(drawContour) { + if (!drawContour) { + var c = this; + c.contours = {}; + /** + * drawContour - interface for implementing the user supplied method to + * render the countours. + * + * Draws a line between the start and end coordinates. + * + * @param startX - start coordinate for X + * @param startY - start coordinate for Y + * @param endX - end coordinate for X + * @param endY - end coordinate for Y + * @param contourLevel - Contour level for line. + */ + this.drawContour = function(startY, startX, endY, endX, contourLevel, k) { + var cb = c.contours[k]; + if (!cb) { + cb = c.contours[k] = new ContourBuilder(contourLevel); + } + cb.addSegment({x: startX, y: startY}, {x: endX, y: endY}); + } + this.contourList = function() { + var l = []; + var a = c.contours; + for (var k in a) { + var s = a[k].s; + var level = a[k].level; + while (s) { + var h = s.head; + var l2 = []; + l2.level = level; + l2.k = k; + while (h && h.p) { + l2.push(h.p); + h = h.next; + } + l.push(l2); + s = s.next; + } + } + l.sort(function(a, b) { return b.k - a.k }); + return l; + } + } else { + this.drawContour = drawContour; + } + this.h = new Array(5); + this.sh = new Array(5); + this.xh = new Array(5); + this.yh = new Array(5); + } + + /** + * contour is a contouring subroutine for rectangularily spaced data + * + * It emits calls to a line drawing subroutine supplied by the user which + * draws a contour map corresponding to real*4data on a randomly spaced + * rectangular grid. The coordinates emitted are in the same units given in + * the x() and y() arrays. + * + * Any number of contour levels may be specified but they must be in order of + * increasing value. + * + * + * @param {number[][]} d - matrix of data to contour + * @param {number} ilb,iub,jlb,jub - index bounds of data matrix + * + * The following two, one dimensional arrays (x and y) contain + * the horizontal and vertical coordinates of each sample points. + * @param {number[]} x - data matrix column coordinates + * @param {number[]} y - data matrix row coordinates + * @param {number} nc - number of contour levels + * @param {number[]} z - contour levels in increasing order. + */ + Conrec.prototype.contour = function(d, ilb, iub, jlb, jub, x, y, nc, z) { + var h = this.h, sh = this.sh, xh = this.xh, yh = this.yh; + var drawContour = this.drawContour; + this.contours = {}; + + /** private */ + var xsect = function(p1, p2){ + return (h[p2]*xh[p1]-h[p1]*xh[p2])/(h[p2]-h[p1]); + } + + var ysect = function(p1, p2){ + return (h[p2]*yh[p1]-h[p1]*yh[p2])/(h[p2]-h[p1]); + } + var m1; + var m2; + var m3; + var case_value; + var dmin; + var dmax; + var x1 = 0.0; + var x2 = 0.0; + var y1 = 0.0; + var y2 = 0.0; + + // The indexing of im and jm should be noted as it has to start from zero + // unlike the fortran counter part + var im = [0, 1, 1, 0]; + var jm = [0, 0, 1, 1]; + + // Note that castab is arranged differently from the FORTRAN code because + // Fortran and C/C++ arrays are transposed of each other, in this case + // it is more tricky as castab is in 3 dimensions + var castab = [ + [ + [0, 0, 8], [0, 2, 5], [7, 6, 9] + ], + [ + [0, 3, 4], [1, 3, 1], [4, 3, 0] + ], + [ + [9, 6, 7], [5, 2, 0], [8, 0, 0] + ] + ]; + + + for (var j=(jub-1);j>=jlb;j--) { + for (var i=ilb;i<=iub-1;i++) { + var temp1, temp2; + temp1 = Math.min(d.get(i, j), d.get(i, j+1)); + temp2 = Math.min(d.get(i+1, j), d.get(i+1, j+1)); + + dmin = Math.min(temp1,temp2); + temp1 = Math.max(d.get(i, j), d.get(i, j+1)); + + temp2 = Math.max(d.get(i+1, j),d.get(i+1, j+1)); + dmax = Math.max(temp1,temp2); + + if (dmax>=z[0]&&dmin<=z[nc-1]) { + for (var k=0;k=dmin&&z[k]<=dmax) { + for (var m=4;m>=0;m--) { + if (m>0) { + // The indexing of im and jm should be noted as it has to + // start from zero + h[m] = d.get(i+im[m-1], j+jm[m-1])-z[k]; + xh[m] = x[i+im[m-1]]; + yh[m] = y[j+jm[m-1]]; + } else { + h[0] = 0.25*(h[1]+h[2]+h[3]+h[4]); + xh[0]=0.5*(x[i]+x[i+1]); + yh[0]=0.5*(y[j]+y[j+1]); + } + if (h[m]>0.0) { + sh[m] = 1; + } else if (h[m]<0.0) { + sh[m] = -1; + } else + sh[m] = 0; + } + // + // Note: at this stage the relative heights of the corners and the + // centre are in the h array, and the corresponding coordinates are + // in the xh and yh arrays. The centre of the box is indexed by 0 + // and the 4 corners by 1 to 4 as shown below. + // Each triangle is then indexed by the parameter m, and the 3 + // vertices of each triangle are indexed by parameters m1,m2,and + // m3. + // It is assumed that the centre of the box is always vertex 2 + // though this isimportant only when all 3 vertices lie exactly on + // the same contour level, in which case only the side of the box + // is drawn. + // + // + // vertex 4 +-------------------+ vertex 3 + // | \ / | + // | \ m-3 / | + // | \ / | + // | \ / | + // | m=2 X m=2 | the centre is vertex 0 + // | / \ | + // | / \ | + // | / m=1 \ | + // | / \ | + // vertex 1 +-------------------+ vertex 2 + // + // + // + // Scan each triangle in the box + // + for (m=1;m<=4;m++) { + m1 = m; + m2 = 0; + if (m!=4) { + m3 = m+1; + } else { + m3 = 1; + } + case_value = castab[sh[m1]+1][sh[m2]+1][sh[m3]+1]; + if (case_value!=0) { + switch (case_value) { + case 1: // Line between vertices 1 and 2 + x1=xh[m1]; + y1=yh[m1]; + x2=xh[m2]; + y2=yh[m2]; + break; + case 2: // Line between vertices 2 and 3 + x1=xh[m2]; + y1=yh[m2]; + x2=xh[m3]; + y2=yh[m3]; + break; + case 3: // Line between vertices 3 and 1 + x1=xh[m3]; + y1=yh[m3]; + x2=xh[m1]; + y2=yh[m1]; + break; + case 4: // Line between vertex 1 and side 2-3 + x1=xh[m1]; + y1=yh[m1]; + x2=xsect(m2,m3); + y2=ysect(m2,m3); + break; + case 5: // Line between vertex 2 and side 3-1 + x1=xh[m2]; + y1=yh[m2]; + x2=xsect(m3,m1); + y2=ysect(m3,m1); + break; + case 6: // Line between vertex 3 and side 1-2 + x1=xh[m3]; + y1=yh[m3]; + x2=xsect(m1,m2); + y2=ysect(m1,m2); + break; + case 7: // Line between sides 1-2 and 2-3 + x1=xsect(m1,m2); + y1=ysect(m1,m2); + x2=xsect(m2,m3); + y2=ysect(m2,m3); + break; + case 8: // Line between sides 2-3 and 3-1 + x1=xsect(m2,m3); + y1=ysect(m2,m3); + x2=xsect(m3,m1); + y2=ysect(m3,m1); + break; + case 9: // Line between sides 3-1 and 1-2 + x1=xsect(m3,m1); + y1=ysect(m3,m1); + x2=xsect(m1,m2); + y2=ysect(m1,m2); + break; + default: + break; + } + // Put your processing code here and comment out the printf + //printf("%f %f %f %f %f\n",x1,y1,x2,y2,z[k]); + + //console.log(x1,y1,x2,y2,z[k],k); + drawContour(x1,y1,x2,y2,z[k],k); + } + } + } + } + } + } + } + } + return Conrec; +})(); +if (typeof exports !== "undefined") { + exports.Conrec = Conrec; +} + +},{}],3:[function(require,module,exports){ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true, evil: true, regexp: true, bitwise: true */ +/*globals typed, Int8Array */ + +"use strict"; + +(function() { + + var top = 0; + var right = 1; + var bottom = 2; + var left = 3; + var none = 4; + + function contour (levels, xdim, ydim, image, draw) + { + var c; + var level; + + var used = new Uint8Array(xdim*ydim); + var ii,jj; + + + for ( c=0; c < levels.length; c++ ) { + level = levels[c]; + + for ( ii=0; ii < xdim*ydim; ii++) { + used[ii] = 0; + } + + // Search outer edges + // + // Search top + for ( jj=0, ii=0; ii < xdim-1; ii++ ) { + if ( image[jj*xdim + ii] < level && level <= image[jj*xdim + ii+1]) { + trace(xdim, ydim, level, ii , jj , top, image, used, draw); + } + } + + // Search right + for (jj=0; jj < ydim-1; jj++) { + if ( image[jj*xdim + ii] < level && level <= image[(jj+1)*xdim + ii]) { + trace(xdim, ydim, level, ii-1, jj , right, image, used, draw); + } + } + + // Search Bottom + for (ii--; ii >= 0; ii--) { + if ( image[jj*xdim + ii+1]= 0; jj--) { + if ( image[(jj+1)*xdim + ii] < level && level <= image[jj*xdim + ii] ) { + trace(xdim, ydim, level, ii , jj , left, image, used, draw); + } + } + + // Search each row of the image + for (jj=1; jj < ydim-1; jj++) { + for (ii=0; ii < xdim-1; ii++) { + if ( !used[jj*xdim + ii] && image[jj*xdim + ii] < level && level <= image[jj*xdim + ii+1]) { + trace(xdim, ydim, level, ii, jj , top, image, used, draw); + } + } + } + } + } + + function trace (xdim, ydim, level, xCell, yCell, side, image, used, draw) + { + var ii = xCell; + var jj = yCell; + var origSide = side; + + var init = 1; + var done = (ii<0 || ii>=xdim-1 || jj<0 && jj>=ydim-1); + + var flag; + var a, b, c, d; + var X, Y; + + while ( !done ) { + flag = 0; + + a = image[ jj *xdim + ii]; + b = image[ jj *xdim + ii+1]; + c = image[(jj+1)*xdim + ii+1]; + d = image[(jj+1)*xdim + ii]; + + if (init) { + init = 0; + switch (side) { + case top: + X = (level-a) / (b-a) + ii; + Y = jj; + break; + case right: + X = ii+1; + Y = (level-b) / (c-b) + jj; + break; + case bottom: + X = (level-c) / (d-c) + ii; + Y = jj+1; + break; + case left: + X = ii; + Y = (level-a) / (d-a) + jj; + break; + } + + } + else { + if ( side==top ) { used[jj*xdim + ii] = 1; } + + do { + if ( ++side == none ) { side = top; } + + switch (side) { + case top: + if (a>=level && level>b) { + flag = 1; + X = (level-a) / (b-a) + ii; + Y = jj; + jj--; + } + break; + case right: + if( b>=level && level>c ) { + flag = 1; + X = ii+1; + Y = (level-b) / (c-b) + jj; + ii++; + } + break; + case bottom: + if( c>=level && level>d ) { + flag = 1; + X = (level-d) / (c-d) + ii; + Y = jj+1; + jj++; + } + break; + case left: + if( d>=level && level>a ) { + flag = 1; + X = ii; + Y = (level-a) / (d-a) + jj; + ii--; + } + break; + } + } while ( !flag ); + + if ( ++side === none ) { side = top; } + if ( ++side === none ) { side = top; } + + if (ii==xCell && jj==yCell && side==origSide) { done = 1; } + if (ii<0 || ii>=xdim-1 || jj<0 || jj>=ydim-1) { done = 1; } + } + + draw(X+.5 ,Y+.5, level); + + if (done) { draw(0, 0, undefined); } + } + } + + module.exports = contour; +}()); + + +},{}],4:[function(require,module,exports){ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ +/*globals $, JS9, imexam, alert */ + + +(function() { + "use strict"; + + var imexam = require("./imexam"); + var conrec = require("./conrec"); + var contfv = require("./contfv"); + + var binner = require("./bin"); + + + function drawContours(div, display) { + var im = JS9.GetImage({display: display}); + var form = $(div).find(".contour-form")[0]; + + var data = imexam.ndops.ndarray(im.raw.data, [im.raw.height, im.raw.width]); + + var levelString = form.level.value; + var binning = $(form).find("#binning").val();; + var smooth = $(form).find("#smooth").val();; + var quality = $(form).find("input[type=radio]:checked").val(); + + + if ( binning === "None" ) { + binning = 1; + } else { + data = binner.bin2d(data, parseInt(binning)); + } + + var level = JSON.parse("[" + levelString.trim().split(/\s+/).join(",") + "]").map(function(x) { return x*binning*binning; }); + + if ( smooth !== "None" ) { + data = binner.smooth_gaussian2d(data, parseFloat(smooth)); + } + + var contours; + + JS9.waiting(true); + setTimeout(function() { + try { + var fudge = 0 + + if ( binning > 1 ) { + fudge = 1; + } + + if ( quality === "better" ) { + var c = new conrec.Conrec(); + + try { + var xcoord = imexam.ndops.iota(0, data.shape[0]-1).map(function(x) { return x*binning+(binning-1)/2 +1.0 }) + var ycoord = imexam.ndops.iota(0, data.shape[1]-1).map(function(x) { return x*binning+(binning-1)/2 +1.0 }) + + //var xcoord = imexam.ndops.iota(1, data.shape[0]).map(function(x) { return (x-(binning-1)/2) * binning + fudge }) + //var ycoord = imexam.ndops.iota(1, data.shape[1]).map(function(x) { return (x-(binning-1)/2) * binning + fudge }) + + c.contour(data + , 0, data.shape[0]-1, 0, data.shape[1]-1 , xcoord, ycoord + , level.length, level); + } catch (e) { + alert("Too many coutour segments: Check your coutour levels.\n\nAre you trying to coutour the background levels of an image?"); + return; + } + + contours = c.contourList().map(function(contour) { + return { shape: "polygon", pts: contour }; + }); + } else { + var points = []; + contours = []; + + contours.push({ shape: "polygon", pts: points }); + + contfv(level, data.shape[0], data.shape[1], data.data + , function(x, y, level) { + if ( level === undefined ) { + points = []; + contours.push({ shape: "polygon", pts: points }); + } else { + //points.push({ x: (x+0.5-(binning-1)/2) * binning + fudge, y: (y+0.5-(binning-1)/2) * binning + fudge }); + points.push({ x: x*binning + 0.5, y: y*binning + 0.5 }); + } + }); + contours.length = contours.length-1; + } + + + JS9.NewShapeLayer("contour", JS9.Catalogs.opts, {display: im}); + JS9.RemoveShapes("contour", {display: im}); + JS9.AddShapes("contour", contours, {color: "yellow"}, {display: im}); + } + finally { + JS9.waiting(false); + } + }, 200); + } + + function getMinMax(div, display) { + var im = JS9.GetImage({display: display}); + + if ( im ) { + var form = $(div).find(".contour-form")[0]; + var data = imexam.ndops.ndarray(im.raw.data, [im.raw.width, im.raw.height]); + + form.min.value = imexam.ndops.minvalue(data).toFixed(2); + form.max.value = imexam.ndops.maxvalue(data).toFixed(2); + } + } + + function makeLevel(div, display) { + var i; + var im = JS9.GetImage({display: display}); + + if ( im ) { + var form = $(div).find(".contour-form")[0]; + + var n = Number(form.nlevel.value); + var level = imexam.ndops.ndarray(imexam.ndops.iota(1, n)); + + var min = Number(form.min.value); + var max = Number(form.max.value); + + imexam.ndops.divs(level, level, n+1); // Try n levels from min to max. + imexam.ndops.muls(level, level, max-min); + imexam.ndops.adds(level, level, min); + + var levText = []; + for ( i = 0; i < level.shape[0]; i++ ) { + levText.push(level.data[i].toFixed(2)); + } + + form.level.value = levText.join("\n"); + } + } + + function contInit() { + var im = JS9.GetImage({display: this.display}); + var div = this.div; + + div.innerHTML = '

    \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
    N
    Min
    Max
    Levels: \ +

    \ + Binning \ + \ + pix \ +
    \ + Smooth \ + \ + pix \ +

    Quality: \ +
     Faster \ +
     Better \ +
    \ +

    \ +

    '; + + var display = this.display; + + $(div).find(".drw-contour").on("mouseup", function () { drawContours(div, display); }); + $(div).find(".get-min-max").on("mouseup", function () { getMinMax(div, display); }); + $(div).find(".make-levels").on("mouseup", function () { makeLevel(div, display); }); + + + if ( im !== undefined ) { + getMinMax(div, display); + makeLevel(div, display); + } + + imexam.fixupDiv(this); + } + + JS9.RegisterPlugin("ImExam", "Contours", contInit, { + menu: "view", + + winTitle: "Contours", + menuItem: "Contours", + help: "imexam/contours.html", + + toolbarSeparate: true, + + winDims: [325, 300], + }); +}()); + + + + +},{"./bin":1,"./conrec":2,"./contfv":3}]},{},[4]) + diff --git a/plugins/imexam/contours.html b/plugins/imexam/contours.html new file mode 100644 index 00000000..72d5f5e4 --- /dev/null +++ b/plugins/imexam/contours.html @@ -0,0 +1,41 @@ +

    + +

    Contours

    + +Contours levels can be overlaid on the displayed image. + +

    +The N entry box controls the number of contours levels to draw. + +

    +Pressing the Draw Contours button will draw contours at the image levels +currently listed in the Levels: list. + +

    +Pressing the Set Min/Max button will fill in the min and max entry boxes +from the minimum and maximum values of the image. + +

    +Pressing the Make Levels will fill in the levels list with an evenly +spaced list of level values from min to max excluding the min and max values +themselves. + +

    +The Binning option allows the image data to be binned before +the contours are computed. Contours will be computed more quickly for +binned images. However, binning will cause the positions of the contours +to be less accurate. + +

    +The Smooth option causes the image data to be smoothed by a Gaussian kernel +with the specified sigma number of pixels before the contours are computed. +This technique often is necessary to achieve good results for sparse data +(e.g. event files). However, it can affect the accuracy of the contours. + +

    +The Quality radio button chooses between one of two contouring methods. +The faster option selects contours with up to 4 points per pixel. The quality +option selects contours with up to 8 points to pixel. + + + diff --git a/plugins/imexam/encircled.js b/plugins/imexam/encircled.js new file mode 100644 index 00000000..77a5b356 --- /dev/null +++ b/plugins/imexam/encircled.js @@ -0,0 +1,69 @@ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ +/*globals $, JS9 */ + +"use strict"; + + +(function() { + var imexam = require("./imexam"); + + var encen_template = " \ +

    \ + \ + \ + \ +
    ee50{ee50%.2f}
    ee80{ee80%.2f}
    \ +
    "; + + function energUpdate(im, xreg) { + var div = this.div; + + var imag = imexam.getRegionData(im, xreg); + + var backgr = imexam.imops.backgr(imag, 4).value; + var data = imexam.ndops.assign(imexam.ndops.zeros(imag.shape), imag); + + imexam.ndops.subs(data, imag, backgr); + + var qcenter = imexam.ndops.qcenter(data); + var centroid = imexam.ndops.centroid(data, qcenter); + + var encen = imexam.imops.encen(data, [centroid.ceny, centroid.cenx]); + + var stat = {}; + stat.ee80 = imexam.ndops.indexof(encen, 0.80); + stat.ee50 = imexam.ndops.indexof(encen, 0.50); + + var edata = []; + var i; + + for ( i = 0; i < encen.shape[0]; i++ ) { + edata[i] = [i, encen.get(i)]; + } + + $(div).empty(); + var plot = $.plot(div, [edata] + , { selection: { mode: "xy" } }); + + $(div).append(imexam.template(encen_template, stat)); + } + + function energInit() { + imexam.fixupDiv(this); + $(this.div).append("Create a region to see encircled energy
    "); + } + + JS9.RegisterPlugin("ImExam", "EncEnergy", energInit, { + menu: "analysis", + + menuItem: "Encircled Energy", + winTitle: "Encircled Energy", + help: "imexam/imexam.html#enener", + + toolbarSeparate: true, + + onregionschange: energUpdate, + winDims: [250, 250], + }); + +}()); diff --git a/plugins/imexam/imcnts.js b/plugins/imexam/imcnts.js new file mode 100644 index 00000000..4069d7ae --- /dev/null +++ b/plugins/imexam/imcnts.js @@ -0,0 +1,133 @@ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ +/*globals $, JS9, imexam, Int32Array */ + +"use strict"; + + +(function() { + var imexam = require("./imexam"); + var template = imexam.template; + var mask = imexam.ndops.mask; + + function runImCnts(im, xreg) { + var i; + var div = this.div; + var text = $(div).find(".imcnts-result")[0]; + + var data = imexam.ndops.ndarray(im.raw.data, [im.raw.height, im.raw.width]); + + var regs = JS9.GetRegions({display: im}); + var mimg = imexam.ndops.zeros(data.shape, Int32Array); + + var list = mask.listRegions(regs); + mask.drawRegions(list, mimg.data, mimg.shape[0]); + + var cnts = imexam.ndops.imcnts(data, mimg, list.length+1); + + var backgr_cnts = 0, backgr_area = 0; + + var back = []; + var srce = []; + var net, regno; + + for ( i = 0; i < list.length; i++ ) { + if ( mask.hasTag(list[i], "background") ) { + regno = list[i].regno; + + backgr_cnts += cnts.cnts.get(regno); + backgr_area += cnts.area.get(regno); + + back.push({ regno: regno, cnts: cnts.cnts.get(regno), area: cnts.area.get(regno) }); + } + } + + for ( i = 0; i < list.length; i++ ) { + if ( mask.hasTag(list[i], "source") && !mask.hasTag(list[i], "exclude") ) { + regno = list[i].regno; + + if ( backgr_area > 0 ) { + net = cnts.cnts.get(regno) - (backgr_cnts * (cnts.area.get(regno)/backgr_area)); + } else { + net = cnts.cnts.get(regno); + } + + srce.push({ regno: regno, net: net, cnts: cnts.cnts.get(regno), area: cnts.area.get(regno) }); + } + } + + $(text).html("Source\n" + + "regno counts area net\n" + + "----- ------ ---- ---\n" + + srce.map(function(x, i) { return template("{regno%5d} {cnts%14.3f} {area%10.3f} {net%14.3f}", x); }).join("\n") + + "\n\nBackground\n" + + "regno counts area\n" + + "----- ------ ----\n" + + back.map(function(x, i) { return template("{regno%5d} {cnts%14.3f} {area%10.3f}", x); }).join("\n")); + } + +/* + function getRegions(div, display) { + var im = JS9.GetImage({display: display}); + + if ( im ) { + var data = imexam.ndops.ndarray(im.raw.data); + var form = $(div).find(".imcnts-form")[0]; + + form.min.value = imexam.ndops.minvalue(data).toFixed(2); + form.max.value = imexam.ndops.maxvalue(data).toFixed(2); + } + } + */ + + function imcntsInit() { + var div = this.div; + +/* + div.innerHTML = '
    \ + \ + \ + \ + \ + \ + \ +
    SourceBackground
    \ + \ +
    Results
    \ +
    \ +

    \ +

    '; + */ + + div.innerHTML = '
    \ + \ + \ + \ +
    Counts in Regions
    \ +
    \ +

    \ +

    '; + + //var display = this.display; + //$(div).find(".run-imcnts").on("mouseup", function () { runImCnts (div, display); }); + //$(div).find(".get-regions").on("mouseup", function () { getRegions(div, display); }); + + imexam.fixupDiv(this); + } + + JS9.RegisterPlugin("ImExam", "ImCnts", imcntsInit, { + menu: "analysis", + + winTitle: "ImCounts", + menuItem: "ImCounts", + help: "imexam/imcnts.html", + + toolbarSeparate: true, + + onregionschange: runImCnts, + winDims: [600, 250], + }); +}()); diff --git a/plugins/imexam/imexam.html b/plugins/imexam/imexam.html new file mode 100644 index 00000000..29db790f --- /dev/null +++ b/plugins/imexam/imexam.html @@ -0,0 +1,110 @@ +

    + +

    Region Statistics

    + +A rectangular box of image pixels is selected and some statical values +are computed from the data. The selected box may be rotated for box and +ellipse regions. + +

    +N.B.: Currently the region shape is ignored and the values reflect a rectangular section of image pixels. +

    + +

    +

    Notes

    + +
      +
    • Background and Noise +

      + The background and noise are obtained from the outer 4 pixel-wide + perimeter of the selected region. The background value is the median + value of this area and the noise value is the RMS. +

    • +
    • Centroid +

      + The centroid is obtained by locating the brightest 9 pixel box and + computing the centroid of the background subtracted data about this point. +

    • +
    • FWHM +

      + The FWHM is estimated from the image moments about the centroid, assuming + a Gaussian distribution. +

    • +
    + +

    + +

    X and Y Projection Plot

    + +A rectangular box of image pixels is selected and the projection along the +region's X or Y axis is plotted. The sum, average or median of the projected +pixels may be selected. The selected box may be rotated for box and ellipse +regions. + + +

    + +

    Radial Profile

    + +A rectangular box of image pixels is selected and the pixels values are +plotted against their respective radii. A Gaussian is fit to the radial profile +data and the result is also plotted. The fitted results of the 4 parameter fit +are displayed with the plot. The selected box may be rotated for box and +ellipse regions. + +

    +The center pixel from which the radii are computed is determined from the +background subtracted centroid taken about the brightest 9 pixels in the data +(same centroid as is displayed in the region stats plugin). + + +

    + +

    Pixel Value Histogram

    + +A rectangular box of image pixels is selected and a histogram of the values +is plotted. The selected box may be rotated for box and +ellipse regions. + +The selected pixels are binned into 250 bins between the minimum and maximum value +found in the selected region. + +

    + +

    Encircled Energy

    + +A rectangular box of image pixels is selected and background subtracted. The +analysis radius is determined from the region as follows: + +
      +
    • circle: region radius
    • +
    • annulus: max annulus radius
    • +
    • box: half the average height an width
    • +
    • ellipse: average axis radius
    • +
    • polygon: half the average of the height and width of polygon bounding box
    • +
    + +The values within the analysis radius are binned in 1 pixel radial bins. The +bins are normalized by the sum of all pixels and the result is plotted. + +

    +The background is obtained as the median from the outer 4 pixel wide perimeter of the +selected region. + +

    +The center pixel from which the encircled energy is computed is determined from +the background subtracted centroid taken about the brightest 9 pixels in the +data (same centroid as is displayed in the region stats plugin). + +

    +The 50 and 80 percent encircled energy points are displayed over the plot. + +

    + +

    3d Surface Plot

    + +A rectangular box of image pixels is selected and plotted as a surface. +The selected box may be rotated for box and ellipse regions. + + + diff --git a/plugins/imexam/imexam.js b/plugins/imexam/imexam.js new file mode 100644 index 00000000..a824ae8a --- /dev/null +++ b/plugins/imexam/imexam.js @@ -0,0 +1,2523 @@ +require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 17 ) { break;} + } + console.log(line); + } else { + for ( y = a.shape[0]-1; y >= 0; --y ) { + line = ""; + for ( x = 0; x < a.shape[1]; ++x ) { + line += a.get(y, x).toFixed(prec) + " "; + } + + console.log(line); + } + console.log("\n"); + } +}; + +ndops._hist = typed(function (a, width , min, max) { + var size = (max-min) / width; + var h = new Int32Array(size+1); + + // ----- + var bin = Math.max(0, Math.min(size, Math.round((a-min)/width))) | 0; // | is truncate + h[bin]++; + + // ----- + + return h; +}); + + + +ndops.hist = function(a, width, min, max) { + var hist = {}; + var reply; + + if ( min === undefined ) { + min = ndops.minvalue(a); + } + if ( max === undefined ) { + max = ndops.maxvalue(a); + } + if ( width === undefined ) { + width = Math.max(1, (max-min) / 250); + } + + hist.raw = a; + + hist.min = min; + hist.max = max; + hist.width = width; + + reply = ndops._hist(a, width, min, max); + hist.data = ndops.ndarray(reply, [reply.length]); + + return hist; +}; + +ndops.proj = function(a, axis) { + var sect; + var i; + + //var proj = ndops.ndarray(ndops._proj(a, axis, new Float32Array(a.shape[axis === 0 ? 1 : 0]), [a.shape[axis === 0 ? 1 : 0]])); + + var proj = {}; + proj.n = a.shape[axis === 1 ? 0 : 1]; + proj.x = a.shape[axis]; + + proj.sum = []; + proj.avg = []; + proj.med = []; + + var copy = ndops.assign(ndops.zeros(a.shape), a); + + for ( i = 0; i < proj.n; i++ ) { + if ( axis === 0 ) { + sect = ndops.section(copy, [[i, i+1], [0, proj.x]]); + } else { + sect = ndops.section(copy, [[0, proj.x], [i, i+1]]); + } + + proj.sum[i] = ndops.sum(sect); + proj.avg[i] = ndops.sum(sect)/proj.n; + proj.med[i] = ndops.median(sect); + } + + return proj; +}; + +ndops.qcenter = typed(function (a) { + var start = [], end = []; + var max = Number.MIN_VALUE; + var idx; + var iX = 0, iY = 0; + + start[0]++; + start[1]++; + end[0]--; + end[1]--; + + // ---- + var sum = + + a[iY-1][iX-1] + + a[iY-1][iX ] + + a[iY-1][iX+1] + + a[iY ][iX-1] + + a[iY ][iX ] + + a[iY ][iX+1] + + a[iY+1][iX-1] + + a[iY+1][iX ] + + a[iY+1][iX+1]; + + if ( max < sum ) { + max = sum; + idx = [iX, iY]; + } + // ---- + + return idx; +}); + +ndops._imcnts = typed({ consider: { c: false } }, function (c, a, b) { c[b] += a; }); + +ndops.imcnts = function (a, b, n) { + var reply = {}; + reply.cnts = ndops.ndarray(ndops._imcnts(new Float32Array(n), a, b)); + reply.area = ndops.hist(b, 1, 0, n-1).data; + + return reply; +}; + + +ndops._centroid = typed(function (a, nx, ny) { + var sum = 0; + var sumx = 0; + var sumy = 0; + var sumxx = 0; + var sumyy = 0; + + var r = nx*nx+ny*ny; + + var iX = 0, iY = 0; + + // ---- + if ( a > 0 && iX*iX + iY*iY < r ) { + sum += a; + sumx += a * iX; + sumxx += a * iX * iX; + sumy += a * iY; + sumyy += a * iY * iY; + } + + // ---- + + var reply = {}; + + reply.sum = sum; + reply.cenx = sumx/sum; + reply.ceny = sumy/sum; + + reply.rmom = ( sumxx - sumx * sumx / sum + sumyy - sumy * sumy / sum ) / sum; + + if ( reply.rmom <= 0 ) { + reply.fwhm = -1.0; + } else { + reply.fwhm = Math.sqrt(reply.rmom) * 2.354 / Math.sqrt(2.0); + } + + return reply; +}); + +ndops.centroid = function(a) { + var reply = ndops._centroid(a, a.shape[0], a.shape[1]); + + return reply; +}; + +ndops.flatten = function() { + var size = 0; + var i, n, a; + + for ( i = 0; i < arguments.length; i++ ) { + size += arguments[i].size; + } + + var reply = ndops.zeros([size]); + var off = 0; + + for ( n = 0; n < arguments.length; n++ ) { + a = arguments[n]; + + ndops.assign(ndops.ndarray(reply.data, a.shape, undefined, off), a); + + off += a.size; + } + + return reply; +}; + +ndops.median = function(a) { + var data = ndops.assign(ndops.zeros(a.shape), a); + + Array.prototype.sort.call(data.data, function(a, b) { return a-b; }); + + var reply = data.data[Math.round((data.size-1)/2.0)]; + + return reply; +}; + + +ndops.rms = typed(function (a) { + var sum = 0; + var squ = 0; + // ---- + sum += a; + squ += a*a; + // ---- + + var mean = sum/a.size; + + return Math.sqrt((squ - 2*mean*sum + a.size*mean*mean)/(a.size-1)); +}); + +ndops.rmsClipped = typed(function (a, min, max) { + var n = 0; + var sum = 0; + var squ = 0; + // ---- + if ( (min === null || a > min) && (max === null || a < max) ) { + n++; + sum += a; + squ += a*a; + } + // ---- + + var mean = sum/n; + + return Math.sqrt((squ - 2*mean*sum + n*mean*mean)/(n-1)); +}); + +ndops.meanClipped = typed(function (a, min, max) { + var n = 0; + var sum = 0; + // ---- + if ( (min === null || a > min) && (max === null || a < max) ) { + n++; + sum += a; + } + // ---- + + return sum/n; +}); + +imops.backgr = function(data, width) { + var back = {}; + + var pixels = ndops.flatten( + ndops.section(data, [[0, width], [0, data.shape[1]]]) + , ndops.section(data, [[data.shape[0]-width, data.shape[0]], [0, data.shape[1]]]) + , ndops.section(data, [[width, data.shape[0]-width], [0, width]]) + , ndops.section(data, [[width, data.shape[0]-width], [data.shape[1]-width, data.shape[1]]])); + + + back.noise = ndops.rms(pixels); + back.value = ndops.median(pixels); + + return back; +}; + +imops.mksection = function(x, y, w, h) { + return [[x-(w/2), x+(w/2)], [y-(h/2), y+(h/2)]]; +}; + +imops._rproj = typed(function(a, cx, cy, radius, length) { + var rad = new Float32Array(length); + var val = new Float32Array(length); + var r = Math.sqrt(radius*radius); + var i = 0; + + var iX = 0, iY = 0; + + // ---- + var d = Math.sqrt((iY-cy)*(iY-cy) + (iX-cx)*(iX-cx)); + + if ( d <= r ) { + rad[i] = d; + val[i] = a; + + i++; + } + // ---- + + return { rad: rad.subarray(0, i), val: val.subarray(0, i), n: i }; +}); + +function sortArrays(a, b) { + var indexed; + + indexed = Array.prototype.map.call(a, function(itm, i){ return [itm, i, b[i]]; }); + + indexed.sort(function(a, b){ return a[0]-b[0]; }); + + indexed.map(function(itm, i) { + a[i] = itm[0]; + b[i] = itm[2]; + }); +} + +imops.rproj = function(im, center) { + var radius = (im.shape[0]/2 + im.shape[1]/2) / 2; + var data = imops._rproj(im, center[1], center[0], radius, im.size); + + sortArrays(data.rad, data.val); + + return { radi: ndops.ndarray(data.rad, [data.rad.length]) + , data: ndops.ndarray(data.val, [data.rad.length]), radius: radius }; +}; + + +imops._encen = typed(function (a, cx, cy, radius) { + var reply = new Float32Array(radius); + var sum = 0; + var RSq = radius*radius; + + var tot = 0; + var i; + + var iX = 0, iY = 0; + + // ---- + var x = iX - cx; + var y = iY - cy; + + var rsq = x*x+y*y; + + if ( a > 0 && rsq < RSq ) { + reply[Math.round(Math.sqrt(rsq))] += a; + sum += a; + } + // ---- + + + for ( i = 0; i < radius; i++ ) { + tot += reply[i]; + + reply[i] = tot / sum; + } + + return reply; +}); + + + +imops.encen = function(im, center) { + var radius = (im.shape[0]/2 + im.shape[1]/2) / 2; + + var reply = imops._encen(im, center[1], center[0], radius); + + return ndops.ndarray(reply, [reply.length]); +}; + +ndops.indexof = function(a, x) { + var i; + + for ( i = 0; i < a.shape[0]; i++ ) { + + if ( x < a.get(i) ) { break; } + } + + if ( i === 0 ) { return 0; } + if ( i === a.shape[0] ) { return a.shape[0]; } + + return i + (x - a.get(i))/(a.get(i) - a.get(i-1)); +}; + +ndops.gauss1d = function(radi, x0) { + var reply = ndops.zeros(radi.shape); + + var a = x0[0]; + var b = 0; // x0[1]; + var c = x0[1]; + var d = x0[2]; + + ndops.fill(reply, function(i) { + var x = radi.data[i]-b; + + return a * Math.pow(2.71828, - x*x / (2*c*c)) + d; + }); + + return reply; +}; + +ndops.gsfit1d = function(radi, data, x0) { + + var reply = typed.uncmin(function(x) { + var modl = ndops.gauss1d(radi, x); + + ndops.sub(modl, modl, data); + ndops.mul(modl, modl, modl); + ndops.fill(modl, function(i) { + return modl.get(i)/(radi.get(i)*radi.get(i)); + }); + + var sum = ndops.sum(modl); + + return Math.sqrt(sum/radi.shape[0]); + + }, x0, 0.000001); + + console.log(reply.message); + + return reply.solution; +}; + +function reg2section(xreg) { + + switch ( xreg.shape ) { + + case "annulus": + xreg.width = xreg.radii[xreg.radii.length-1]*2; + xreg.height = xreg.radii[xreg.radii.length-1]*2; + + break; + + case "circle": + xreg.width = xreg.radius*2; + xreg.height = xreg.radius*2; + + break; + + case "ellipse": + xreg.width = xreg.r1*2; + xreg.height = xreg.r2*2; + + break; + + case "polygon": + var i, xx = 0, yy = 0, minx = 1000000, maxx = 0, miny = 1000000, maxy = 0; + + for ( i = 0; i < xreg.pts.length; i++ ) { + xx += xreg.pts[i].x; + yy += xreg.pts[i].y; + + if ( xreg.pts[i].x > maxx ) { maxx = xreg.pts[i].x; } + if ( xreg.pts[i].x < minx ) { minx = xreg.pts[i].x; } + if ( xreg.pts[i].y > maxy ) { maxy = xreg.pts[i].y; } + if ( xreg.pts[i].y < miny ) { miny = xreg.pts[i].y; } + } + + xreg.x = xx/xreg.pts.length; + xreg.y = yy/xreg.pts.length; + + xreg.width = maxx - minx; + xreg.height = maxy - miny; + + break; + + default: + } + + return imops.mksection(xreg.x, xreg.y, xreg.width, xreg.height); +} + +exports.getRegionData = function (im, xreg) { + var section = reg2section(xreg); + var im_2d = ndops.ndarray(im.raw.data, [im.raw.height, im.raw.width]); + var imag; + + if ( xreg.angle && xreg.angle !== 0 ) { + imag = ndops.zeros([xreg.width, xreg.height]); + + ndops.rotate(imag, im_2d, xreg.angle/57.29577951, xreg.y, xreg.x); + } else { + imag = ndops.section(im_2d, section); + } + + return imag; +}; + +exports.convolve1d = typed(function(kernel, data, output) { + var i, j, x; + var half = Math.round(kernel.shape[0]/2.0); + + for ( i = 0; i < data.shape[0]; i++ ) { + for ( j = 0; j < kernel.shape[0]; j++ ) { + x = i+j-half; + + if ( x >= 0 && x < data.shape[0] ) { + output[i] += kernel[j] * data[x]; + } + } + } +}); + +exports.convolve2dSep = function(kernel, data, output) { + var x, y, i, xx, yy; + + var nx = data.shape[1]; + var ny = data.shape[0]; + var nk = kernel.shape[0]; + + var half = Math.floor(nk/2.0); + + // Run the kernel 1d over each row + // + for ( y = 0; y < ny; y++ ) { + for ( x = 0; x < nx; x++ ) { + output[y][x] = 0; + + for ( i = 0; i < nk; i++ ) { + xx = x+i-half; + + if ( xx > 0 && xx < nx ) { + output[y][x] += data[y][xx]*kernel[i]; + } + } + } + } + + // Run the kernel 1d over each column + // + for ( x = 0; x < nx; x++ ) { + for ( y = 0; y < ny; y++ ) { + + for ( i = 0; i < nk; i++ ) { + yy = y+i-half; + + if ( yy > 0 && yy < ny ) { + output[y][x] += data[y+i][x]*kernel[i]; + } + } + } + } +}; + + +exports.reg2section = reg2section; +exports.template = template; + +exports.ndops = ndops; +exports.typed = ndops; +exports.imops = imops; + + +},{"./mask.js":3,"./template":11,"typed-array-function":4,"typed-array-ops":5,"typed-array-rotate":6,"typed-numeric-uncmin":9}],"./imexam":[function(require,module,exports){ +module.exports=require('Ll8vMw'); +},{}],3:[function(require,module,exports){ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ +/*globals $ */ + +"use strict"; + +// source +// background +// exclude + +(function() { + var raster = require("./raster"); + + function hasTag(reg, tag) { + var i; + + for ( i = 0; i < reg.tags.length; i++ ) { + if ( reg.tags[i] === tag ) { return true; } + } + + return false; + } + exports.hasTag = hasTag; + + exports.listRegions = function (regs) { + var i, j; + var reg, regno = 1; + + var reply = []; + + for ( i = 0; i < regs.length; i++ ) { + reg = regs[i]; + + switch ( reg.shape ) { + case "annulus": + for ( j = 0; j < reg.radii.length; j++ ) { + if ( reg.radii[j] !== 0.0 ) { + reply[regno-1] = $.extend($.extend({}, reg), { regno: regno++, shape: "circle", radius: reg.radii[j] }); + } + } + break; + default: + reply[regno-1] = $.extend({ regno: regno++ }, reg); + break; + } + } + + return reply; + }; + + exports.drawRegions = function (regs, buffer, width) { + var reg, t, i; + + var type = [ "include", "exclude" ]; + + for ( t = 0; t < 2; t++ ) { + for ( i = regs.length - 1; i >= 0; i-- ) { + reg = regs[i]; + + if ( hasTag(reg, type[t]) ) { + switch ( reg.shape ) { + case "polygon": raster.drawPolygon(buffer, width, reg.pts, reg.regno); break; + case "circle": raster.drawCircle( buffer, width, reg.x, reg.y, reg.radius, reg.regno); break; + case "box": raster.drawBox( buffer, width, reg.x, reg.y, reg.width, reg.height, reg.angle, reg.regno); break; + case "ellipse": raster.drawEllipse(buffer, width, reg.x, reg.y, reg.r1, reg.r2, reg.angle, reg.regno); break; + } + } + } + } + }; +}()); + + +},{"./raster":10}],4:[function(require,module,exports){ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true, evil: true, regexp: true, bitwise: true */ +/*jshint node: true, -W099: true, laxbreak:true, laxcomma:true, multistr:true, smarttabs:true */ +/*globals typed, Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array */ + +"use strict"; + +(function() { + var ndarray = require("ndarray-nobuffer"); + + var types = { + int8 : Int8Array + , uint8 : Uint8Array + , int16 : Int16Array + , uint16: Uint16Array + , int32: Int32Array + , uint32: Uint32Array + , float32: Float32Array + , float64: Float64Array + }; + + function dim(x) { + if ( x.shape ) { return x.shape; } + + var ret = []; + while( typeof x === "object" ) { + ret.push(x.length); + x = x[0]; + } + + return ret; + } + + function rep(s,v,k) { + if ( v === undefined ) { v = 0; } + if ( k === undefined ) { k = 0; } + var n = s[k], ret = [], i; + if(k === s.length-1) { + for(i=n-2;i>=0;i-=2) { ret[i+1] = v; ret[i] = v; } + if(i===-1) { ret[0] = v; } + return ret; + } + for(i=n-1;i>=0;i--) { ret[i] = rep(s,v,k+1); } + return ret; + } + + function repeat(pattern, count) { + if (count < 1) { return ''; } + + var result = ''; + while (count > 0) { + if ( count & 1 ) { result += pattern; } + + count >>= 1; pattern += pattern; + } + return result; + } + + + + + function replaceIdentifierRefs(str, func) { + var reply = ""; + + var state = -1, match, index, first, i = 0, x; + + while ( i < str.length ) { + match = str.match(/[a-zA-Z_][a-zA-Z0-9_]*/); // Find an identifier in the string. + + if ( !match ) { break; } + + reply += str.substr(i, match.index); + + index = []; + i = match.index + match[0].length; + + x = true; + while ( x && i < str.length ) { + while ( str[i] === ' ' ) { i++; } + + switch ( str[i] ) { + case "[": + state = 1; + first = i+1; + i++; + + while ( state ) { + if ( str[i] === ']' ) { + if ( state === 1 ) { index.push(str.substring(first, i)); } + state--; + } + if ( str[i] === '[' ) { state++; } + i++; + } + break; + case "." : + first = i; + i++; + while ( str[i] === ' ' ) { i++; } + while ( str[i].match(/[ a-zA-Z0-9_]/) !== null ) { i++; } + + index.push(str.substring(first, i)); + + break; + default: + x = false; + break; + } + } + + reply += func(match[0], index); + str = str.substr(i); + i = 0; + } + + return reply + str.substr(i); + } + + + function typedArrayFunctionConstructor() { + var actuals = arguments; + var i, j; + var args; + var text; + var hash = {}; + + var body; + + if ( this.cache === undefined ) { + if ( typeof this.func === "string" ) { + text = this.func; + } else { + text = this.func.toString(); + } + this.text = text; + + var x = text.match(/function [A-Za-z0-9_]*\(([^()]*)\)[^{]*\{([\S\s]*)\}[\S\s]*/); // } + + args = x[1].split(",").map(function(s) { return s.trim(); }); + this.args = args; + + this.prep = ""; + this.post = ""; + + body = x[2].split(/\/\/ ----+/); + + if ( body.length > 1 ) { + this.prep = body[0]; + this.post = body[2]; + this.body = body[1]; + } else { + this.body = body[0]; + } + if ( this.post === "" || this.post === undefined ) { + this.post = "\nreturn " + args[0] + ";"; + } + } + args = this.args; + text = this.text; + + var opts = this.opts; + + if ( opts === undefined ) { opts = {}; } + + var type = ""; + var dime = 0; + var func; + + for ( i = 0; i < args.length; i++ ) { + if ( actuals[i] !== null && actuals[i] !== undefined && typeof actuals[i] === "object" + && (opts.consider === undefined || ( typeof opts.consider === "object" && opts.consider[args[i]] !== false )) ) { + + hash[args[i]] = actuals[i]; + + if ( !actuals[i].shape ) { + actuals[i].shape = dim(actuals[i]); + } + + dime = Math.max(actuals[i].shape.length, dime); + + if ( actuals[i].data ) { + type += " " + actuals[i].dtype + " " + actuals[i].offset + " " + " " + actuals[i].stride; + } else { + type += " O"; + } + + } else { + type += " X"; + } + } + type = dime + type; + + if ( this.cache ) { + func = this.cache[type]; + + if ( func ) { return func; } + } + + var prep = this.prep; + body = this.body; + var post = this.post; + var dims = []; + + var indicies = [ "iW", "iV", "iU", "iZ", "iY", "iX" ]; + var hasIndex = false; + + // Match each source code identifier and any associated array indexing. Extract + // the indicies and recursivly replace them also. + // + function replaceArrayRefs(text) { + + return replaceIdentifierRefs(text, function (id, indx) { + var k, offset, reply; + + if ( id === "index" ) { hasIndex = true; } + + for ( k = 0; k < indx.length; k++ ) { + indx[k] = replaceArrayRefs(indx[k]); + } + + var arg = hash[id]; + var dimen; + var joinStr, bracket, fixindx; + + + if ( arg !== undefined && typeof arg === "object" ) { + + if ( indx.length >= 1 && indx[indx.length-1].trim() === ".length" ) { + indx[0] = ".shape"; + indx[1] = indx.length-1; + indx.length = 2; + } + + if ( indx.length >= 1 && indx[0][0] === "." ) { + if ( indx.length >= 2 && indx[0].trim() === ".shape" ) { + if ( arg.data ) { + reply = id + ".shape[" + indx[1] + "]"; + } else { + reply = id + repeat("[0]", indx[1]) + ".length"; + } + } else { + reply = id + indx[0].trim(); + } + } else { + if ( arg.data ) { + dimen = arg.dimension; + + + if ( indx.length !== 0 && indx.length < arg.dimension ) { + id = id + ".data.subarray"; + bracket = "()"; + fixindx = indx.length; + } else { + id = id + ".data"; + bracket = "[]"; + fixindx = arg.dimension; + } + + joinStr = " + "; + } else { + dimen = arg.shape.length; + joinStr = "]["; + offset = ""; + bracket = "[]"; + } + + var indi = indicies.slice(6-dimen); + + if ( ( opts.loops === undefined || opts.loops === true ) && ( indx.length === 0 || dimen === indx.length ) ) { + for ( i = 0; i < dimen; i++ ) { + if ( indx[i] === undefined ) { indx[i] = indi[i]; } + if ( dims[i] === undefined ) { dims[i] = 0; } + + dims[i] = Math.max(dims[i], arg.shape[i]); + } + } + + if ( arg.data ) { + for ( i = 0; i < fixindx; i++ ) { + if ( arg.stride[i] !== 1 ) { indx[i] = "(" + indx[i] + ")*" + arg.stride[i]; } + } + + if ( arg.offset !== 0 ) { offset = arg.offset + " + "; + } else { offset = ""; } + } + + if ( indx.length ) { + reply = id + bracket[0] + offset + indx.join(joinStr) + bracket[1] + " "; + } else { + reply = id; + } + } + } else { + reply = id; + + for ( i = 0; i < indx.length; i++ ) { + if ( indx[i][0] === "." ) { + reply += indx[i].trim(); + } else { + reply += "[" + indx[i].trim() + "]"; + } + } + reply += " "; + } + + return reply; + }); + } + + body = replaceArrayRefs(body); + + var indx = indicies.slice(6-dims.length); + var indi = indicies.slice(6-dims.length).reverse(); + dims.reverse(); + + var init = "\n"; + var setp = "\n"; + + var indxZero = ""; + var indxIncr = ""; + + if ( opts.loops === undefined || opts.loops === true ) { + init += " var index = [" + rep([dims.length], 0).join(",") + "];\n"; + init += " var start = [" + rep([dims.length], 0).join(",") + "];\n"; + init += " var end = [" + rep([dims.length], 0).join(",") + "];\n\n"; + + for ( i = 0; i < dims.length; i++ ) { + + for ( j = 0; j < args.length; j++ ) { + if ( hash[args[j]] && actuals[j] !== undefined && typeof actuals[j] === "object" ) { + init += " end[" + i + "] = " + args[j] + ".shape[" + i + "];\n"; + break; + } + } + } + init += "\n"; + + for ( i = 0; i < dims.length; i++ ) { + setp += " var " + indx[i] + "start = start[" + i + "];\n"; + setp += " var " + indx[i] + "end = end[" + i + "];\n"; + + } + setp += "\n"; + for ( i = 0; i < dims.length; i++ ) { + if ( hasIndex ) { + indxZero = "index[" + (dims.length - i - 1) + "] = 0;\n"; + indxIncr = " index[" + (dims.length - i - 1) + "]++\n"; + } + + body = indxZero + "for ( var " + indi[i] + " = " + indi[i] + "start; " + indi[i] + " < " + indi[i] + "end; " + indi[i] + "++ ) {\n " + body + "\n" + indxIncr + "\n }"; + } + } + + func = "// Array optimized funciton\n"; + func += "// " + type + "\n"; + func += "return function (" + args.join(",") + ") {\n'use strict';\n\n" + init + prep + setp + body + post + "\n}"; + + if ( typed.debug ) { console.log(func); } + + if ( this.cache === undefined ) { this.cache = {}; } + + func = new Function(func)(); + this.cache[type] = func; + + return func; + } + + + function typedArrayFunctionExecute() { + var func = typedArrayFunctionConstructor.apply(this, arguments); + + var reply = func.apply(typed, arguments); + + return reply; + } + + function typed(opts, func) { + if ( func === undefined ) { + func = opts; + opts = undefined; + } + + var objst = { func: func, opts: opts }; + var reply = typedArrayFunctionExecute.bind(objst); + + reply.baked = typedArrayFunctionConstructor.bind(objst); + + return reply; + } + + var size = typed(function (a) { + var prd = 1; + // ---- + prd *= a; + // ---- + return prd; + }); + + function array(shape, DType, value) { + var reply; + var i, n; + + if ( typeof value !== "number" ) { + value = 0; + } + + if ( DType && DType.dtype ) { DType = DType.dtype; } + if ( typeof DType === "string" ) { DType = types[DType]; } + + if ( typeof DType === "function" ) { + n = size(shape); + reply = ndarray(new DType(n), shape); + + for ( i = 0; i < n; i++ ) { reply.data[i] = value; } + } else { + reply = rep(shape, value); + } + + reply.shape = shape; + + return reply; + } + + function clone (x) { + return typed.assign(typed.array(typed.dim(x), x), x); + } + + function iota(i, n) { + if ( n === undefined ) { + n = i; + i = 0; + } + var j, result = []; + for ( j = 0; j 17 ) { break;} + } + console.log(line); + } else { + for ( y = a.shape[0]-1; y >= 0; --y ) { + line = ""; + for ( x = 0; x < a.shape[1]; ++x ) { + line += a.get(y, x).toFixed(prec) + " "; + } + + console.log(line); + } + console.log("\n"); + } + } + + function section(a, sect) { + var x1 = sect[0][0]; + var x2 = sect[0][1]; + var y1 = sect[1][0]; + var y2 = sect[1][1]; + + return a.lo(y1, x1).hi(y2-y1, x2-x1); + } + + module.exports = typed; + module.exports.ndarray = ndarray; + module.exports.section = section; + module.exports.extend = extend; + module.exports.array = array; + module.exports.clone = clone; + module.exports.print = print; + module.exports.iota = iota; + module.exports.rep = rep; + module.exports.dim = dim; + + module.exports.epsilon = 2.220446049250313e-16; +}()); + + +},{"ndarray-nobuffer":13}],5:[function(require,module,exports){ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true, evil: true, regexp: true */ +/*globals */ + +"use strict"; + +(function () { + var i; + var typed = require("typed-array-function"); + + var ops = {}, opname, op; + module.exports = ops; + + function twofourthr(ops) { // Allocate an output array as needed + var dima, dimb, shape; + + return function (a, b, c) { + if ( c === undefined ) { + dima = typed.dim(a); + dimb = typed.dim(b); + + if ( dima.length > dimb.length ) { + shape = dima; + } else { + shape = dimb; + } + c = b; b = a; a = typed.array(shape, b); + } + + return ops(a, b, c); + }; + } + function onefourtwo(ops) { // Allocate an output array as needed + return function (a, b) { + if ( b === undefined ) { b = a; a = typed.array(typed.dim(b), b); } + + return ops(a, b); + }; + } + + function twofourthr_bake(op) { + return function(a, b, c) { + if ( c === undefined ) { return twofourthr(op.baked(a, b, c)); } + + return op.baked(a, b, c); + }; + } + function onefourtwo_bake(op) { + return function(a, b) { + if ( b === undefined ) { return onefourtwo(op.baked(a, b)); } + + return op.baked(a, b); + }; + } + + + var assign_ops = { add: "+", sub: "-", mul: "*", div: "/", + mod: "%", band: "&", bor: "|", bxor: "^", + lshift: "<<", rshift: ">>", rrshift: ">>>" + }; + + for(opname in assign_ops) { + if ( assign_ops.hasOwnProperty(opname) ) { + op = assign_ops[opname]; + + ops[opname + "3"] = typed("function (a, b, c) { a = b " + op + " c; }"); + ops[opname + "_mask"] = typed("function (a, b, c, m) { if ( m ) { a = b " + op + " c; } }"); + ops[opname + "eq"] = typed("function (a, b ) { a " + op + "= b; } "); + ops[opname + "eq_mask"] = typed("function (a, b , m) { if ( m ) { a " + op + "= b; } }"); + + ops[opname] = twofourthr (ops[opname + "3"]); + ops[opname].baked = twofourthr_bake(ops[opname + "3"]); + + ops[opname + "s"] = ops[opname]; + ops[opname + "seq"] = ops[opname + "eq"]; + } + } + + var binary_ops = { and: "&&", or: "||", + eq: "===", neq: "!==", lt: "<", + gt: ">", leq: "<=", geq: ">=" }; + + for(opname in binary_ops) { + if ( binary_ops.hasOwnProperty(opname) ) { + op = binary_ops[opname]; + + ops[opname + "3"] = typed("function (a, b, c) { a = b " + op + " c; }"); + ops[opname + "_mask"] = typed("function (a, b, c, m) { if ( m ) { a = b " + op + " c; } }"); + ops[opname + "eq"] = typed("function (a, b ) { a = a " + op + " b; } "); + ops[opname + "eq_mask"] = typed("function (a, b , m) { if ( m ) { a = a " + op + " b; } }"); + + ops[opname] = twofourthr (ops[opname + "3"]); + ops[opname].baked = twofourthr_bake(ops[opname + "3"]); + + ops[opname + "s"] = ops[opname]; + ops[opname + "seq"] = ops[opname + "eq"]; + } + } + + + var unary_ops = { not: "!", bnot: "~", neg: "-", recip: "1.0/" }; + + for(opname in unary_ops) { + if ( unary_ops.hasOwnProperty(opname) ) { + op = unary_ops[opname]; + + ops[opname + "2"] = typed("function (a, b ) { a = " + op + " b; }"); + ops[opname + "_mask"] = typed("function (a, b , m) { if ( m ) { a = " + op + " b; } }"); + ops[opname + "eq"] = typed("function (a ) { a = " + op + " a; }"); + ops[opname + "eq" + "_mask"] = typed("function (a , m) { if ( m ) { a = " + op + " a; } }"); + + ops[opname] = onefourtwo (ops[opname + "2"]); + ops[opname].baked = onefourtwo_bake(ops[opname + "2"]); + } + } + + var math_unary = [ "Math.abs", "Math.exp", "Math.floor", "Math.log", "Math.round", "Math.sqrt" + , "Math.acos", "Math.asin", "Math.atan", "Math.ceil", "Math.cos", "Math.sin", "Math.tan" + , "isFinite", "isNaN" ]; + + for( i = 0; i < math_unary.length; i++ ) { + op = math_unary[i]; + + opname = op.split(".") + + if ( opname.length == 2 ) { + opname = opname[1] + } else { + opname = opname[0] + } + + ops[opname + "2"] = typed("function (a, b ) { a = " + op + "(b); }"); + ops[opname + "_mask"] = typed("function (a, b , m) { if ( m ) { a = " + op + "(b); } }"); + ops[opname + "eq"] = typed("function (a ) { a = " + op + "(a); }"); + ops[opname + "eq" + "_mask"] = typed("function (a , m) { if ( m ) { a = " + op + "(a); } }"); + + ops[opname] = onefourtwo (ops[opname + "2"]); + ops[opname].baked = onefourtwo_bake(ops[opname + "2"]); + } + + var math_comm = [ "max", "min" ]; + + for( i = 0; i < math_comm.length; i++ ) { + opname = op = math_comm[i]; + + ops[opname + "3"] = typed("function (a, b, c) { a = Math." + op + "(b, c); }"); + ops[opname + "_mask"] = typed("function (a, b, c, m) { if ( m ) { a = Math." + op + "(b, c); } }"); + + ops[opname] = twofourthr (ops[opname + "3"]); + ops[opname].baked = twofourthr_bake(ops[opname + "3"]); + + ops[opname + "s"] = ops[opname]; + ops[opname + "s" + "eq"] = ops[opname]; + } + + var math_noncomm = [ "atan2", "pow" ]; + + for( i = 0; i < math_noncomm.length; i++ ) { + opname = op = math_noncomm[i]; + + ops[opname + "3"] = typed("function (a, b, c) { a = Math." + op + "(b, c); }"); + ops[opname + "_mask"] = typed("function (a, b, c, m) { if ( m ) { a = Math." + op + "(b, c); } }"); + + ops[opname] = twofourthr (ops[opname + "3"]); + ops[opname].baked = twofourthr_bake(ops[opname + "3"]); + + ops[opname + "s"] = ops[opname]; + ops[opname + "s" + "eq"] = ops[opname]; + } + + ops.assign = typed(function (a, b) { a = b; }); + ops.equals = typed(function (a, b) { if ( a !== b ) { return false; } }); + ops.any = typed(function (a) { if ( a ) { return true; } }); + ops.all = typed(function (a) { if (!a ) { return false; } }); + ops.random = typed(function (a) { a = Math.random(); }); + ops.sum = typed(function (a) { + var sum = 0; + // ---- + sum += a; + // ---- + return sum; + }); + ops.prod = typed(function (a) { + var prd = 1; + // ---- + prd *= a; + // ---- + return prd; + }); + + ops.inf = typed(function (a) { + var inf = Infinity; + // ---- + if ( a < inf ) { inf = a; } + // ---- + return inf; + }); + ops.sup = typed(function (a) { + var sup = -Infinity; + // ---- + if ( a > sup ) { sup = a; } + // ---- + return sup; + }); + + + ops.norm2Squared = typed(function (a) { + var norm2 = 0; + // ---- + norm2 += a*a; + // ---- + return norm2; + }); + ops.norm2 = function (a) { return Math.sqrt(ops.norm2Squared(a)); }; + + //norm1 + //norminf + + //argmin + //argmax + +}()); + + +},{"typed-array-function":4}],6:[function(require,module,exports){ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true, bitwise: true */ + +"use strict"; + +var warp = require("typed-array-warp"); + + +function rotateImage(out, inp, theta, iX, iY, oX, oY) { + var c = Math.cos(theta); + var s = Math.sin(-theta); + iX = iX || inp.shape[0]/2.0; + iY = iY || inp.shape[1]/2.0; + oX = oX || out.shape[0]/2.0; + oY = oY || out.shape[1]/2.0; + var a = iX - c * oX + s * oY; + var b = iY - s * oX - c * oY; + warp(out, inp, function(y,x) { + y[0] = c * x[0] - s * x[1] + a; + y[1] = s * x[0] + c * x[1] + b; + }); + return out; +} + +module.exports = rotateImage; + +},{"typed-array-warp":7}],7:[function(require,module,exports){ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true, bitwise: true */ + +"use strict"; + +var interp = require("ndarray-linear-interpolate"); +var typed = require("typed-array-function"); + +var do_warp = typed(function (dest, func, interp) { + var warped = dest.shape.slice(0); + + var iX = 0, iY = 0, iZ = 0; + + // ---- + func(warped, [iX, iY, iZ]); + dest = interp.apply(undefined, warped); + // ---- +}); + +var do_warp_1 = typed(function (dest, func, interp, src) { + var warped = [0]; + var SRC = src; + + var iX = 0; + + // ---- + func(warped, [iX]); + dest = interp(SRC, warped[0]); + // ---- +}); + +var do_warp_2 = typed(function (dest, func, interp, src) { + var warped = [0, 0]; + var SRC = src; + + var iX = 0, iY = 0; + + // ---- + func(warped, [iY, iX]); + dest = interp(SRC, warped[0], warped[1]); + // ---- +}); + +var do_warp_3 = typed(function (dest, func, interp, src) { + var warped = [0, 0, 0]; + var SRC = src; + + var iX = 0, iY = 0, iZ = 0; + + // ---- + func(warped, [iZ, iY, iX]); + dest = interp(SRC, warped[0], warped[1], warped[2]); + // ---- +}); + +module.exports = function warp(dest, src, func) { + switch(src.shape.length) { + case 1: + do_warp_1(dest, func, interp.d1, src); + break; + case 2: + do_warp_2(dest, func, interp.d2, src); + break; + case 3: + do_warp_3(dest, func, interp.d3, src); + break; + default: + do_warp(dest, func, interp.bind(undefined, src)); + break; + } + return dest; +}; + +},{"ndarray-linear-interpolate":12,"typed-array-function":4}],8:[function(require,module,exports){ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true, evil: true, regexp: true, bitwise: true */ +/*jshint node: true, -W099: true, laxbreak:true, laxcomma:true, multistr:true, smarttabs:true */ +/*globals */ + +"use strict"; + +var typed = require("typed-array-function"); +var numeric = typed; + + +typed.dot = function dot(x,y) { + var d = numeric.dim; + + var dimx = d(x); + var dimy = d(y); + + switch(d(x).length*1000+d(y).length) { + case 2002: return numeric.dotMM(numeric.array([dimx[0], dimy[1]], x.dtype), x,y); + case 2001: return numeric.dotMV(x,y); + case 1002: return numeric.dotVM(x,y); + case 1001: return numeric.dotVV(x,y); + case 1000: return numeric.mulVS(x,y); + case 1: return numeric.mulSV(x,y); + case 0: return x*y; + default: throw new Error('numeric.dot only works on vectors and matrices'); + } +}; + +numeric.dotVV = function dotVV(x,y) { + var i,n=x.length,i1,ret = x[n-1]*y[n-1]; + + for(i=n-2;i>=1;i-=2) { + i1 = i-1; + ret += x[i]*y[i] + x[i1]*y[i1]; + } + if(i===0) { ret += x[0]*y[0]; } + + return ret; +}; + +numeric.dotMV = function dotMV(x,y) { + var i, p = x.length; + var ret = this.array([p], x.dtype), dotVV = this.dotVV; + for(i=p-1;i>=0;i--) { ret[i] = dotVV(x[i],y); } + return ret; +}; + +numeric.dotVM = function dotVM(x,y) { + var j,k,p,q,ret,woo,i0; + p = x.length; q = y[0].length; + ret = numeric.array([q], x.dtype); + for(k=q-1;k>=0;k--) { + woo = x[p-1]*y[p-1][k]; + for(j=p-2;j>=1;j-=2) { + i0 = j-1; + woo += x[j]*y[j][k] + x[i0]*y[i0][k]; + } + if(j===0) { woo += x[0]*y[0][k]; } + ret[k] = woo; + } + return ret; +}; + +numeric.dotMM = function dotMM(reply,x,y) { + var i,j,k,r=reply.shape[1],foo,bar,woo,i0; + + var p = x.length; + var q = y.length; + + for(i=p-1;i>=0;i--) { + foo = reply[i]; + bar = x[i]; + + for(k=r-1;k>=0;k--) { + woo = bar[q-1]*y[q-1][k]; + for(j=q-2;j>=1;j-=2) { + i0 = j-1; + woo += bar[j]*y[j][k] + bar[i0]*y[i0][k]; + } + if(j===0) { woo += bar[0]*y[0][k]; } + foo[k] = woo; + } + //ret[i] = foo; + } +}; + +numeric.diag = function diag(d) { + var i,i1,j,n = d.length, A = this.array([n, n], d.dtype), Ai; + for(i=n-1;i>=0;i--) { + Ai = A[i]; + i1 = i+2; + for(j=n-1;j>=i1;j-=2) { + Ai[j] = 0; + Ai[j-1] = 0; + } + if(j>i) { Ai[j] = 0; } + Ai[i] = d[i]; + for(j=i-1;j>=1;j-=2) { + Ai[j] = 0; + Ai[j-1] = 0; + } + if(j===0) { Ai[0] = 0; } + //A[i] = Ai; + } + return A; +}; +numeric.identity = function identity(n, type) { return this.diag(this.array([n],type,1)); }; + +numeric.tensorXX = function tensor(A,x,y) { + var m = x.length, n = y.length, Ai, i,j,xi; + + + for(i=m-1;i>=0;i--) { + Ai = A[i]; + xi = x[i]; + for(j=n-1;j>=3;--j) { + Ai[j] = xi * y[j]; + --j; + Ai[j] = xi * y[j]; + --j; + Ai[j] = xi * y[j]; + --j; + Ai[j] = xi * y[j]; + } + while(j>=0) { Ai[j] = xi * y[j]; --j; } + } + + //console.log(x, y, A[0], A[1]); +}; +numeric.tensorXX = typed({ loops: false }, numeric.tensorXX); +numeric.tensor = function tensor(x,y) { + + if(typeof x === "number" || typeof y === "number") { return numeric.mul(x,y); } + var s1 = numeric.dim(x); + var s2 = numeric.dim(y); + if(s1.length !== 1 || s2.length !== 1) { + throw new Error('numeric: tensor product is only defined for vectors'); + } + + return numeric.tensorXX(numeric.array([s1[0], s2[0]], x.dtype), x, y); +}; + + +numeric.dotVV = typed({ loops: false }, numeric.dotVV); +numeric.dotVM = typed({ loops: false }, numeric.dotVM); +numeric.dotMV = typed({ loops: false }, numeric.dotMV); +numeric.dotMM = typed({ loops: false }, numeric.dotMM); +numeric.diag = typed({ loops: false }, numeric.diag); + + +},{"typed-array-function":4}],9:[function(require,module,exports){ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true, evil: true, regexp: true, bitwise: true, continue:true */ + +"use strict"; + +var numeric = require("typed-array-function"); + numeric = numeric.extend(numeric, require("typed-array-ops")); + numeric = numeric.extend(numeric, require("typed-matrix-ops")); + +//9. Unconstrained optimization +exports.gradient = function gradient(f,x) { + var n = x.length; + var f0 = f(x); + if(isNaN(f0)) { throw new Error('gradient: f(x) is a NaN!'); } + var i,x0 = numeric.clone(x),f1,f2, J = new [].constructor(n); + var errest,max = Math.max,eps = 1e-3,abs = Math.abs, min = Math.min; + var t0,t1,t2,it=0,d1,d2,N,h; + for(i=0;i20) { throw new Error("Numerical gradient fails"); } + x0[i] = x[i]+h; + f1 = f(x0); + x0[i] = x[i]-h; + f2 = f(x0); + x0[i] = x[i]; + if(isNaN(f1) || isNaN(f2)) { h/=16; continue; } + J[i] = (f1-f2)/(2*h); + t0 = x[i]-h; + t1 = x[i]; + t2 = x[i]+h; + d1 = (f1-f0)/h; + d2 = (f0-f2)/h; + N = max(abs(J[i]),abs(f0),abs(f1),abs(f2),abs(t0),abs(t1),abs(t2),1e-8); + errest = min(max(abs(d1-J[i]),abs(d2-J[i]),abs(d1-d2))/N,h/N); + if(errest>eps) { h/=16; + } else { break; } + } + } + return J; +}; +exports.uncmin = function uncmin(f,x0,tol,gradient,maxit,callback,options) { + var grad = exports.gradient; + if(options === undefined) { options = {}; } + if(tol === undefined) { tol = 1e-8; } + if(gradient === undefined) { gradient = function(x) { return grad(f,x); }; } + if(maxit === undefined) { maxit = 1000; } + x0 = numeric.clone(x0); + var n = x0.length; + var f0 = f(x0),f1,df0; + if(isNaN(f0)) { throw new Error('uncmin: f(x0) is a NaN!'); } + var max = Math.max, norm2 = numeric.norm2; + tol = max(tol,numeric.epsilon); + var step,g0,g1,H1 = options.Hinv || numeric.identity(n); + var dot = numeric.dot, sub = numeric.sub, add = numeric.add, ten = numeric.tensor, div = numeric.div, mul = numeric.mul; + + var all = numeric.all, isfinite = numeric.isFinite, neg = numeric.neg; + var it=0,s,x1,y,Hy,ys,t,nstep; + var msg = ""; + g0 = gradient(x0); + while(it= 0.1*t*df0 || isNaN(f1)) { + t *= 0.5; + ++it; + continue; + } + break; + } + if(t*nstep < tol) { msg = "Line search step size smaller than tol"; break; } + if(it === maxit) { msg = "maxit reached during line search"; break; } + g1 = gradient(x1); + + y = sub(g1,g0); + ys = dot(y,s); + Hy = dot(H1,y); + + H1 = sub(add(H1, + mul( + (ys+dot(y,Hy))/(ys*ys), + ten(s,s) )), + div(add(ten(Hy,s),ten(s,Hy)),ys)); + x0 = x1; + f0 = f1; + g0 = g1; + ++it; + + } + return {solution: x0, f: f0, gradient: g0, invHessian: H1, iterations:it, message: msg}; +}; + +},{"typed-array-function":4,"typed-array-ops":5,"typed-matrix-ops":8}],10:[function(require,module,exports){ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ +/*globals */ + +"use strict"; + +(function() { + + // http://cogsandlevers.blogspot.com/2013/11/scanline-based-filled-polygons.html + // + function drawHLine(buffer, width, x1, x2, y, k, rop) { + + if ( x1 < 0 ) { x1 = 0; } + if ( x2 > width ) { x2 = width; } + + var ofs = x1 + y * width; // calculate the offset into the buffer + var x; + + switch ( rop ) { // draw all of the pixels + case undefined: + case "set": for (x = x1; x < x2; x++) { buffer[ofs++] = k; } break; + case "add": for (x = x1; x < x2; x++) { buffer[ofs++] += k; } break; + } + } + + function scanline(x1, y1, x2, y2, miny, edges) { + var x, y, xi; + + if (y1 > y2) { // flip the points if need be + y = y1; y1 = y2; y2 = y; + x = x1; x1 = x2; x2 = x; + } + + y1 = Math.floor(y1)+1; + y2 = Math.floor(y2); + + //if ( y2 < y1 ) { y2++ } + + x = x1; // start at the start + var dx = (x2 - x1) / (y2 - y1); // change in x over change in y will give us the gradient + var ofs = Math.round(y1 - miny); // the offset the start writing at (into the array) + + for ( y = y1; y <= y2; y++ ) { // cover all y co-ordinates in the line + + xi = Math.floor(x) + 1; + + // check if we've gone over/under the max/min + // + if ( edges[ofs].minx > xi ) { edges[ofs].minx = xi; } + if ( edges[ofs].maxx < xi ) { edges[ofs].maxx = xi; } + + x += dx; // move along the gradient + ofs ++; // move along the buffer + + } + } + + function _drawPolygon(buffer, width, points, color, rop) { + var i; + var miny = points[0].y-1; // work out the minimum and maximum y values + var maxy = points[0].y-1; + + for ( i = 1; i < points.length; i++ ) { + if ( points[i].y-1 < miny) { miny = points[i].y-1; } + if ( points[i].y-1 > maxy) { maxy = points[i].y-1; } + } + + var h = maxy - miny; // the height is the size of our edges array + var edges = []; + + for ( i = 0; i <= h+1; i++ ) { // build the array with unreasonable limits + edges.push({ minx: 1000000, maxx: -1000000 }); + } + + for ( i = 0; i < points.length-1; i++ ) { // process each line in the polygon + scanline(points[i ].x-1, points[i ].y-1 + , points[i+1].x-1, points[i+1].y-1, miny, edges); + } + scanline(points[i].x-1, points[i].y-1, points[0].x-1, points[0].y-1, miny, edges); + + // draw each horizontal line + for ( i = 0; i < edges.length; i++ ) { + drawHLine( buffer, width + , Math.floor(edges[i].minx) + , Math.floor(edges[i].maxx) + , Math.floor(i + miny), color, rop); + } + } + + function d2r(d) { return d * (Math.PI / 180); } + + function rotPoints(points, angle, about) { + var x, y, i; + var reply = []; + + angle = d2r(angle); + + var sin = Math.sin(angle); + var cos = Math.cos(angle); + + for ( i = 0; i < points.length; i++ ) { + x = about.x + (((points[i].x-about.x) * cos) - ((points[i].y-about.y) * sin)); + y = about.y + (((points[i].x-about.x) * sin) + ((points[i].y-about.y) * cos)); + + reply.push({ x: x, y: y }); + } + + return reply; + } + + function polyEllipse(x, y, w, h) { + var ex, ey, i; + var reply = []; + + for ( i = 0; i < 2 * Math.PI; i += 0.01 ) { + ex = x + w*Math.cos(i); + ey = y + h*Math.sin(i); + + reply.push({ x: ex, y: ey }); + } + + return reply; + } + + function polyBox(x, y, w, h) { + return [ { x: x-w/2, y: y-h/2 } + , { x: x-w/2, y: y+h/2 } + , { x: x+w/2, y: y+h/2 } + , { x: x+w/2, y: y-h/2 } ]; + } + + exports.drawPolygon = function (buffer, width, points, color, rop) { _drawPolygon(buffer, width, points, color, rop); }; + exports.drawCircle = function (buffer, width, x, y, rad, color, rop) { _drawPolygon(buffer, width, polyEllipse(x, y, rad, rad), color, rop); }; + exports.drawEllipse = function (buffer, width, x, y, h, w, rot, color, rop) { _drawPolygon(buffer, width, rotPoints(polyEllipse(x, y, h, w), rot, { x: x, y: y }), color, rop); }; + exports.drawBox = function (buffer, width, x, y, h, w, rot, color, rop) { _drawPolygon(buffer, width, rotPoints(polyBox (x, y, h, w), rot, { x: x, y: y }), color, rop); }; +}()); + +},{}],11:[function(require,module,exports){ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ + +"use strict"; + + + function strrep(str, n) { + var i, s = ''; + + for ( i = 0; i < n; i++ ) { s += str; } + + return s; + } + +function template(text,data) { + return text.replace(/\{([a-zA-Z0-9_.%]*)\}/g, + function(m,key){ + var type, prec, widt = 0, fmt, i; + var val = data; + + key = key.split("%"); + + if ( key.length <= 1 ) { + fmt = "%s"; + } else { + fmt = key[1]; + } + + key = key[0]; + key = key.split("."); + + for ( i = 0; i < key.length; i++ ) { + if ( val.hasOwnProperty(key[i]) ) { + val = val[key[i]]; + } else { + return ""; + } + } + + type = fmt.substring(fmt.length-1); + prec = fmt.substring(0, fmt.length-1); + + prec = prec.split("."); + + widt = prec[0] | 0; + prec = prec[1] | 0; + + switch ( type ) { + case "s": + val = val.toString(); + break; + case "f": + val = val.toFixed(prec); + break; + case "d": + val = val.toFixed(0); + break; + } + + if ( widt !== 0 && widt > val.length ) { + if ( widt > 0 ) { + val = strrep(" ", widt-val.length) + val; + } else { + val = val + strrep(" ", widt-val.length); + } + } + + return val; + } + ); +} + +module.exports = template; + +},{}],12:[function(require,module,exports){ +"use strict" + +function interp1d(arr, x) { + var ix = Math.floor(x) + , fx = x - ix + , s0 = 0 <= ix && ix < arr.shape[0] + , s1 = 0 <= ix+1 && ix+1 < arr.shape[0] + , w0 = s0 ? +arr.get(ix) : 0.0 + , w1 = s1 ? +arr.get(ix+1) : 0.0 + return (1.0-fx)*w0 + fx*w1 +} + +function interp2d(arr, x, y) { + var ix = Math.floor(x) + , fx = x - ix + , s0 = 0 <= ix && ix < arr.shape[0] + , s1 = 0 <= ix+1 && ix+1 < arr.shape[0] + , iy = Math.floor(y) + , fy = y - iy + , t0 = 0 <= iy && iy < arr.shape[1] + , t1 = 0 <= iy+1 && iy+1 < arr.shape[1] + , w00 = s0&&t0 ? arr.get(ix ,iy ) : 0.0 + , w01 = s0&&t1 ? arr.get(ix ,iy+1) : 0.0 + , w10 = s1&&t0 ? arr.get(ix+1,iy ) : 0.0 + , w11 = s1&&t1 ? arr.get(ix+1,iy+1) : 0.0 + return (1.0-fy) * ((1.0-fx)*w00 + fx*w10) + fy * ((1.0-fx)*w01 + fx*w11) +} + +function interp3d(arr, x, y, z) { + var ix = Math.floor(x) + , fx = x - ix + , s0 = 0 <= ix && ix < arr.shape[0] + , s1 = 0 <= ix+1 && ix+1 < arr.shape[0] + , iy = Math.floor(y) + , fy = y - iy + , t0 = 0 <= iy && iy < arr.shape[1] + , t1 = 0 <= iy+1 && iy+1 < arr.shape[1] + , iz = Math.floor(z) + , fz = z - iz + , u0 = 0 <= iz && iz < arr.shape[2] + , u1 = 0 <= iz+1 && iz+1 < arr.shape[2] + , w000 = s0&&t0&&u0 ? arr.get(ix,iy,iz) : 0.0 + , w010 = s0&&t1&&u0 ? arr.get(ix,iy+1,iz) : 0.0 + , w100 = s1&&t0&&u0 ? arr.get(ix+1,iy,iz) : 0.0 + , w110 = s1&&t1&&u0 ? arr.get(ix+1,iy+1,iz) : 0.0 + , w001 = s0&&t0&&u1 ? arr.get(ix,iy,iz+1) : 0.0 + , w011 = s0&&t1&&u1 ? arr.get(ix,iy+1,iz+1) : 0.0 + , w101 = s1&&t0&&u1 ? arr.get(ix+1,iy,iz+1) : 0.0 + , w111 = s1&&t1&&u1 ? arr.get(ix+1,iy+1,iz+1) : 0.0 + return (1.0-fz) * ((1.0-fy) * ((1.0-fx)*w000 + fx*w100) + fy * ((1.0-fx)*w010 + fx*w110)) + fz * ((1.0-fy) * ((1.0-fx)*w001 + fx*w101) + fy * ((1.0-fx)*w011 + fx*w111)) +} + +function interpNd(arr) { + var d = arr.shape.length|0 + , ix = new Array(d) + , fx = new Array(d) + , s0 = new Array(d) + , s1 = new Array(d) + , i, t + for(i=0; iMath.abs(this._stride1))?[1,0]:[0,1]}})") + } else if(dimension === 3) { + code.push( +"var s0=Math.abs(this._stride0),s1=Math.abs(this._stride1),s2=Math.abs(this._stride2);\ +if(s0>s1){\ +if(s1>s2){\ +return [2,1,0];\ +}else if(s0>s2){\ +return [1,2,0];\ +}else{\ +return [1,0,2];\ +}\ +}else if(s0>s2){\ +return [2,0,1];\ +}else if(s2>s1){\ +return [0,1,2];\ +}else{\ +return [0,2,1];\ +}}})") + } + } else { + code.push("ORDER})") + } + } + + //view.set(i0, ..., v): + code.push([ +"proto.set=function ",className,"_set(", args.join(","), ",v){"].join("")) + if(useGetters) { + code.push(["return this.data.set(", index_str, ",v)}"].join("")) + } else { + code.push(["return this.data[", index_str, "]=v}"].join("")) + } + + //view.get(i0, ...): + code.push(["proto.get=function ",className,"_get(", args.join(","), "){"].join("")) + if(useGetters) { + code.push(["return this.data.get(", index_str, ")}"].join("")) + } else { + code.push(["return this.data[", index_str, "]}"].join("")) + } + + //view.index: + code.push([ + "proto.index=function ", + className, + "_index(", args.join(), "){return ", + index_str, "}"].join("")) + + //view.hi(): + code.push(["proto.hi=function ",className,"_hi(",args.join(","),"){return new ", className, "(this.data,", + indices.map(function(i) { + return ["(typeof i",i,"!=='number'||i",i,"<0)?this._shape", i, ":i", i,"|0"].join("") + }).join(","), ",", + indices.map(function(i) { + return "this._stride"+i + }).join(","), ",this.offset)}"].join("")) + + //view.lo(): + var a_vars = indices.map(function(i) { return "a"+i+"=this._shape"+i }) + var c_vars = indices.map(function(i) { return "c"+i+"=this._stride"+i }) + code.push(["proto.lo=function ",className,"_lo(",args.join(","),"){var b=this.offset,d=0,", a_vars.join(","), ",", c_vars.join(",")].join("")) + for(var i=0; i=0){\ +d=i",i,"|0;\ +b+=c",i,"*d;\ +a",i,"-=d}"].join("")) + } + code.push(["return new ", className, "(this.data,", + indices.map(function(i) { + return "a"+i + }).join(","),",", + indices.map(function(i) { + return "c"+i + }).join(","), ",b)}"].join("")) + + //view.step(): + code.push(["proto.step=function ",className,"_step(",args.join(","),"){var ", + indices.map(function(i) { + return "a"+i+"=this._shape"+i + }).join(","), ",", + indices.map(function(i) { + return "b"+i+"=this._stride"+i + }).join(","),",c=this.offset,d=0,ceil=Math.ceil"].join("")) + for(var i=0; i=0){c=(c+this._stride",i,"*i",i,")|0}else{a.push(this._shape",i,");b.push(this._stride",i,")}"].join("")) + } + code.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}") + + //Add return statement + code.push(["return function construct_",className,"(data,shape,stride,offset){return new ", className,"(data,", + indices.map(function(i) { + return "shape["+i+"]" + }).join(","), ",", + indices.map(function(i) { + return "stride["+i+"]" + }).join(","), ",offset)}"].join("")) + + //Compile procedure + var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n")) + return procedure(CACHED_CONSTRUCTORS[dtype], order) +} + +function arrayDType(data) { + if(data instanceof Float64Array) { + return "float64"; + } else if(data instanceof Float32Array) { + return "float32" + } else if(data instanceof Int32Array) { + return "int32" + } else if(data instanceof Uint32Array) { + return "uint32" + } else if(data instanceof Uint8Array) { + return "uint8" + } else if(data instanceof Uint16Array) { + return "uint16" + } else if(data instanceof Int16Array) { + return "int16" + } else if(data instanceof Int8Array) { + return "int8" + } else if(data instanceof Uint8ClampedArray) { + return "uint8_clamped" + } else if(data instanceof Array) { + return "array" + } + return "generic" +} + +var CACHED_CONSTRUCTORS = { + "float32":[], + "float64":[], + "int8":[], + "int16":[], + "int32":[], + "uint8":[], + "uint16":[], + "uint32":[], + "array":[], + "uint8_clamped":[], + "generic":[] +} + +;(function() { + for(var id in CACHED_CONSTRUCTORS) { + CACHED_CONSTRUCTORS[id].push(compileConstructor(id, -1)) + } +}); + +function wrappedNDArrayCtor(data, shape, stride, offset) { + if(data === undefined) { + var ctor = CACHED_CONSTRUCTORS.array[0] + return ctor([]) + } else if(typeof data === "number") { + data = [data] + } + if(shape === undefined) { + shape = [ data.length ] + } + var d = shape.length + if(stride === undefined) { + stride = new Array(d) + for(var i=d-1, sz=1; i>=0; --i) { + stride[i] = sz + sz *= shape[i] + } + } + if(offset === undefined) { + offset = 0 + for(var i=0; i" + + strrep("
    "; + + return t; + } + + + // $(this).css({"font-size" : newFontSize, "line-height" : newFontSize/1.2 + "px"}); + + function pxtablUpdate(im, point) { + var im_2d = imexam.ndops.ndarray(im.raw.data, [im.raw.height, im.raw.width]); + var i = 0, j = 0; + var x, y; + + + var pxtabl = $(this.div).find(".pxtabl")[0]; + + pxtabl["cell" + j + "." + i].value = "col\\row"; + + j = 0; + for ( i = 1; i < 10; i++ ) { + x = point.x + i - 5; + + if ( x > 0 && x <= im.raw.width ) { + pxtabl["cell" + j + "." + i].value = x.toFixed(0); + } else { + pxtabl["cell" + j + "." + i].value = ""; + } + } + + i = 0; + for ( j = 1; j < 10; j++ ) { + y = point.y + j - 5; + + if ( y > 0 && y <= im.raw.height ) { + pxtabl["cell" + (10-j) + "." + i].value = y.toFixed(0); + } else { + pxtabl["cell" + (10-j) + "." + i].value = ""; + } + } + + for ( j = 1; j < 10; j++ ) { + for ( i = 1; i < 10; i++ ) { + x = (point.x + i - 5 - 0.5)|0; + y = (point.y + j - 5 - 0.5)|0; + + if ( x >= 0 && x < im.raw.width && y >= 0 && y < im.raw.height ) { + pxtabl["cell" + (10-j) + "." + i].value = im_2d.get(y, x).toPrecision(4); + } else { + pxtabl["cell" + (10-j) + "." + i].value = ""; + } + } + } + } + + function pxtablInit() { + imexam.fixupDiv(this); + + $(this.div).html("
    " + htmlTable(10, 10) + "
    "); + $(this.div).find(".row5").css("background", "lightblue"); + $(this.div).find(".col5").css("background", "lightblue"); + $(this.div).find(":input").css("font-size", "11"); + } + + JS9.RegisterPlugin("ImExam", "PxTabl", pxtablInit, { + menu: "view", + + menuItem: "Pixel Table", + winTitle: "Pixel Table", + winResize: true, + + toolbarSeparate: true, + + onmousemove: pxtablUpdate, + winDims: [625, 240], + }); +}()); + diff --git a/plugins/imexam/radproj.js b/plugins/imexam/radproj.js new file mode 100644 index 00000000..85cb7a69 --- /dev/null +++ b/plugins/imexam/radproj.js @@ -0,0 +1,82 @@ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ +/*globals $, JS9 */ + +"use strict"; + + +(function() { + var imexam = require("./imexam"); + + var rproj_template = "
    \ + \ + \ + \ + \ +
    peak {a%.2f}
    sigma {c%.2f}
    bias {d%.2f}
    \ +
    "; + + function rprojUpdate(im, xreg) { + var div = this.div; + + var imag = imexam.getRegionData(im, xreg); + + var max = imexam.ndops.maxvalue(imag); + var backgr = imexam.imops.backgr(imag, 4).value; + var data = imexam.ndops.assign(imexam.ndops.zeros(imag.shape), imag); + + imexam.ndops.subs(data, imag, backgr); + + var qcenter = imexam.ndops.qcenter(data); + var centroid = imexam.ndops.centroid(data, qcenter); + + var rproj = imexam.imops.rproj(imag, [centroid.ceny, centroid.cenx]); + + var fit = imexam.ndops.gsfit1d(rproj.radi, rproj.data, [max, centroid.fwhm/2.355, backgr]); + + var fitv = { a: fit[0], b: 0, c: fit[1], d: fit[2] }; + + var rdata = []; + var rfdat = []; + var r; + + for ( r = 0; r < rproj.radi.shape[0]; r++ ) { + rdata[r] = [rproj.radi.get(r), rproj.data.get(r)]; + } + + rproj.samp = imexam.ndops.zeros([div.offsetWidth/2]); + + imexam.ndops.fill(rproj.samp, function(r) { return rproj.radius*r/(div.offsetWidth/2); }); + + + rproj.modl = imexam.ndops.gauss1d(rproj.samp, fit); + + for ( r = 0; r < rproj.modl.shape[0]; r++ ) { + rfdat[r] = [rproj.samp.get(r), rproj.modl.get(r)]; + } + + $(div).empty(); + var plot = $.plot(div, [{ data: rdata, points: { radius: 1, show: true } }, { data: rfdat }] + , { zoomStack: true, selection: { mode: "xy" } }); + + $(div).append(imexam.template(rproj_template, fitv)); + } + + function rprojInit() { + imexam.fixupDiv(this); + $(this.div).append("Create a region to see radial projection
    "); + } + + JS9.RegisterPlugin("ImExam", "RadialProj", rprojInit, { + menu: "analysis", + + menuItem: "Radial Proj", + winTitle: "Radial Proj", + help: "imexam/imexam.html#r_proj", + + toolbarSeparate: true, + + onregionschange: rprojUpdate, + winDims: [250, 250], + }); + +}()); diff --git a/plugins/imexam/reghist.js b/plugins/imexam/reghist.js new file mode 100644 index 00000000..50e761aa --- /dev/null +++ b/plugins/imexam/reghist.js @@ -0,0 +1,91 @@ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ +/*globals $, JS9 */ + +"use strict"; + + +(function() { + var imexam = require("./imexam"); + + var reghistemplate = "
    \ + \ + \ + \ +
    rms {rms%.2f}
    mean {mean%.2f}
    \ +
    "; + + function histStats(div, plot, range) { + var i, j = 0; + var axes = plot.getAxes(); + + var xmin = axes.xaxis.options.min; + var xmax = axes.xaxis.options.max; + var hist = $(div).data("hist"); + var data = hist.raw; + + var rms = imexam.ndops.rmsClipped( data, xmin, xmax); + var mean = imexam.ndops.meanClipped(data, xmin, xmax); + + $(div).find(".annotation").empty(); + + $(div).append(imexam.template(reghistemplate, { rms: rms, mean: mean })); + } + + function histUpdate(im, xreg) { + var div = this.div; + + var imag = imexam.getRegionData(im, xreg); + + var hist = imexam.ndops.hist(imag); + hist.sum = imexam.ndops.sum(hist.data); + + $(div).data("hist", hist); + + var n = 0; + var skip = hist.sum * 0.001; + var h = 0, i, value; + + $(div).empty(); + + var hdata = []; + + for ( i = 0; i < hist.data.shape[0]; i++ ) { + n += hist.data.get(i); + + if ( n > skip && n < hist.sum - skip ) { + value = hist.data.get(i); + + hdata[h] = [i*hist.width+hist.min, value]; + h++; + } + } + + var plot = $.plot(div, [hdata], { zoomStack: true, zoomFunc: histStats, selection: { mode: "x" } }); + + histStats(div, plot, undefined); + +// $.plot.zoomStackIn(plot, undefined, { xaxis: { from: xmin , to: xmax } +// , yaxis: { from: axes.yaxis.min , to: axes.yaxis.max } } +// , histStats); + } + + function histInit() { + imexam.fixupDiv(this); + $(this.div).append("Create a region to see histogram
    "); + } + + JS9.RegisterPlugin("ImExam", "Histogram", histInit, { + menu: "analysis", + + menuItem: "Histogram", + winTitle: "Histogram", + help: "imexam/imexam.html#rghist", + + toolbarSeparate: true, + toolbarHTML: " ", + + onregionschange: histUpdate, + winDims: [250, 250], + }); + +}()); diff --git a/plugins/imexam/regstat.js b/plugins/imexam/regstat.js new file mode 100644 index 00000000..caf3f1a2 --- /dev/null +++ b/plugins/imexam/regstat.js @@ -0,0 +1,71 @@ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ +/*globals $, JS9 */ + +"use strict"; + + +(function() { + var imexam = require("./imexam"); + + + var statTemplate = " \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
    Position x {reg.x%.2f} y {reg.y%.2f}
    width {reg.width%.2f} height {reg.height%.2f}
    min {min%.2f} max {max%.2f}
    counts {centroid.sum%.2f}
    bkgrnd {backgr.value%.2f} noise {backgr.noise%.2f}
    Centroid x {centroid.cenx%.2f} y {centroid.ceny%.2f}
    FWHM {centroid.fwhm%.2f} {centroid.rms%.2f}
    "; + + function statUpdate(im, xreg) { + var div = this.div; + + var section = imexam.reg2section(xreg); + var imag = imexam.getRegionData(im, xreg); + + var data = imexam.ndops.assign(imexam.ndops.zeros(imag.shape), imag); + + var stat = {}; + + stat.reg = xreg; + stat.min = imexam.ndops.minvalue(imag); + stat.max = imexam.ndops.maxvalue(imag); + stat.backgr = imexam.imops.backgr(imag, 4); + + imexam.ndops.subs(data, imag, stat.backgr.value); + + stat.qcenter = imexam.ndops.qcenter(data); + stat.centroid = imexam.ndops.centroid(data, imexam.ndops.qcenter(data)); + + stat.centroid.cenx += section[0][0]; + stat.centroid.ceny += section[1][0]; + + $(div).html(imexam.template(statTemplate, stat)); + } + + function statInit() { + imexam.fixupDiv(this); + $(this.div).append("Create a region to see stats
    "); + } + + JS9.RegisterPlugin("ImExam", "RegionStats", statInit, { + menu: "analysis", + + winTitle: "Region Stats", + menuItem: "Region Stats", + help: "imexam/imexam.html#rgstat", + + toolbarSeparate: true, + + onregionschange: statUpdate, + winDims: [250, 250], + }); +}()); diff --git a/plugins/imexam/rghxrg.js b/plugins/imexam/rghxrg.js new file mode 100644 index 00000000..f5ae2df2 --- /dev/null +++ b/plugins/imexam/rghxrg.js @@ -0,0 +1,71 @@ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ +/*globals $, JS9, Fitsy, imexam */ + +"use strict"; + + +(function() { + + function hxrgReadPixelStack(fits, n, index, deliver, data) { + var last, i; + + if ( n === 0 ) { + data = []; + } else { + data[n-1] = fits.pixel; + } + + n += 1; + + if ( n >= fits.nhdu ) { + last = data[0]; + + for ( i = 1; i < n; i++ ) { + data[i-1] = data[i]; + } + + data[n-1] = last; + + deliver(data); + + return; + } + + Fitsy.readPixel(fits, fits.hdu[n], index, function() { hxrgReadPixelStack(fits, n, index, deliver, data); }); + } + + function pixtUpdate(im, xreg) { + var hxrg = [], i; + var div = this.div; + + hxrgReadPixelStack(im.raw.hdu.fits, 0, [xreg.pos.y, xreg.pos.x], function(data) { + + for ( i = 0; i < data.length; i++ ) { + hxrg[i] = [i, data[i]]; + } + + $(div).empty(); + $.plot(div, [hxrg]); + }); + } + + function pixtInit() { + imexam.fixupDiv(this); + $(this.div).append("Create a region to see the pixel stack
    "); + } + + JS9.RegisterPlugin("HxRG", "PixelStack", pixtInit, { + menu: "analysis", + + menuItem: "Pixel Stack", + winTitle: "Pixel Stack", + help: "imexam/imexam.html#rghxrg", + + toolbarSeparate: true, + toolbarHTML: " ", + + onregionschange: pixtUpdate, + winDims: [250, 250], + }); + +}()); diff --git a/plugins/imexam/xyproj.js b/plugins/imexam/xyproj.js new file mode 100644 index 00000000..a14f1409 --- /dev/null +++ b/plugins/imexam/xyproj.js @@ -0,0 +1,112 @@ +/*jslint white: true, vars: true, plusplus: true, nomen: true, unparam: true */ +/*globals $, JS9 */ + +"use strict"; + + +(function() { + var imexam = require("./imexam"); + + + var projToolbar = " \ +
    \ + \ +
    "; + + + // fit \ + + function projUpdate(im, xreg) { + var div, proj, menx, chek; + + if ( im === undefined ) { + div = xreg.div; + proj = xreg.proj; + menx = xreg.menu; + chek = xreg.chek; + } else { + div = this.div; + menx = this.outerdivjq.find(".proj_menu")[0]; + chek = this.outerdivjq.find(".proj_chek")[0]; + + proj = imexam.ndops.proj(imexam.getRegionData(im, xreg), this.plugin.opts.xyproj); + + $(menx).change(function (event) { + projUpdate(undefined, { div: div, proj: proj, menu: menx, chek: chek }); + }); + $(chek).change(function (event) { + projUpdate(undefined, { div: div, proj: proj, menu: menx, chek: chek }); + }); + } + + + var xdata = []; + var data; + var x; + + var proj_type = menx.options[menx.selectedIndex].value; + + + $(div).empty(); + + if ( proj_type === "sum" ) { + data = proj.sum; + } + if ( proj_type === "avg" ) { + data = proj.avg; + } + if ( proj_type === "med" ) { + data = proj.med; + } + + + for ( x = 0; x < data.length; x++ ) { + xdata[x] = [x, data[x]]; + } + + $.plot(div, [xdata], { zoomStack: true, selection: { mode: "xy" } }); + } + + function projInit() { + imexam.fixupDiv(this); + $(this.div).append("Create a region to see projection
    "); + } + + JS9.RegisterPlugin("ImExam", "XProj", projInit, { + menu: "analysis", + + menuItem: "X Projection", + winTitle: "X Projection", + help: "imexam/imexam.html#xyproj", + + toolbarSeparate: true, + toolbarHTML: projToolbar, + + onregionschange: projUpdate, + + winDims: [250, 250], + + xyproj: 0 + }); + + JS9.RegisterPlugin("ImExam", "YProj", projInit, { + menu: "analysis", + + menuItem: "Y Projection", + winTitle: "Y Projection", + help: "imexam/imexam.html#xyproj", + + toolbarSeparate: true, + toolbarHTML: projToolbar, + + onregionschange: projUpdate, + + winDims: [250, 250], + + xyproj: 1 + }); +}()); diff --git a/plugins/plugintest.css b/plugins/plugintest.css new file mode 100644 index 00000000..94b4c94c --- /dev/null +++ b/plugins/plugintest.css @@ -0,0 +1,18 @@ +div.PLUGINtest{ + /* relative pos top/left for container, Flanagan's JavaScript, p 357 */ + position: relative; + top: 0px; + left: 0px; + display: block; + padding: 10px; + border-width: 0px; + border-color: blue; + border-style: solid; + background: lightblue; +} + +div.PLUGINmessage{ + height: 30px; + width: 512px; + padding: 2px; +} diff --git a/plugins/plugintest.js b/plugins/plugintest.js new file mode 100644 index 00000000..a24a6c62 --- /dev/null +++ b/plugins/plugintest.js @@ -0,0 +1,176 @@ +/* + * PLUGIN test module (January 26 2014) + */ + +/*jslint bitwise: true, plusplus: true, sloppy: true, vars: true, white: true, browser: true, devel: true, continue: true, unparam: true, regexp: true */ +/*global $, jQuery, JS9, sprintf */ + +// To specify the JS9 display instance to link to a given PLUGIN div, +// use the HTML5 dataset syntax: +//
    + +// make a module so as not to pollute the global namespace +var PLUGIN; +if( PLUGIN && (typeof PLUGIN !== "object" || PLUGIN.CLASS) ){ + throw new Error("Namespace 'PLUGIN' already exists"); +} + +// create our namespace, and specify some meta-information and params +PLUGIN = {}; +PLUGIN.CLASS = "PLUGIN"; // class of plugins (1st part of div class) +PLUGIN.NAME = "test"; // name of this plugin (2nd part of div class) +PLUGIN.NDIV = 4; // number of div message areas +PLUGIN.WIDTH = 512; // width of light window +PLUGIN.HEIGHT = 150; // height of light window + +// constructor: it's here that you add HTML elements to the container div +// But you don't have to do so: you can put the HTML elements right into +// the Web page, in which case this routine can be empty. +// Obviously, you must use the contructor to add your HTML elements if you +// want to support your plugin from the View menu. +// +// The examaple below splits the difference: it allows the container div to +// be empty or filled with the inner canvas, and thus support the view menu. +PLUGIN.Test = function(){ + var i; + // on entry, these elements have already been defined: + // this.div: the DOM element representing the div for this plugin + // this.divjq: the jquery object representing the div for this plugin + // this.id: the id ofthe div (or the plugin name as a default) + // this.display: the display object associated with this plugin + // this.dispMode: display mode (for internal use) + // set width and height on div + // + // create message divs + for(i=0; i") + .addClass(PLUGIN.CLASS + "message") + .attr("id", "message" + i) + .html(" ") + .appendTo(this.divjq); + } +}; + +// write a row of text in message area associated with a given plugin +PLUGIN.Test.prototype.message = function(message, row) { + this.divjq.children("#message" + row).html(message); +}; + +// callback when mouse is pressed +// im: image handle +// ipos: image position; origin at 1,1 (FITS convention) +// evt: the event passed to the callback +PLUGIN.mousedown = function(im, ipos, evt){ + var t = sprintf("mouseDown: ipos=%s,%s", ipos.x, ipos.y); + this.message(t, 0); +}; + +// callback when mouse is released +PLUGIN.mouseup = function(im, ipos, evt){ + var t = sprintf("mouseUp: ipos=%s,%s", ipos.x, ipos.y); + this.message(t, 0); +}; + +// callback when mouse (or one-finger touch) moves (without a mouse press) +// image value: we need 0-indexed positions, so subtract 1 +// but add 0.5 before rounding since x.0 is in the middle of the pixel +PLUGIN.mousemove = function(im, ipos, evt){ + var v, t; + v = im.raw.data[Math.floor(ipos.y-0.5) * im.raw.width + + Math.floor(ipos.x-0.5)]; + t = sprintf("mouseMove: ipos=%s,%s val=%s", ipos.x, ipos.y, v); + this.message(t, 0); +}; + +// callback when mouse moves over the image +PLUGIN.mouseover = function(im, ipos, evt){ + var t = sprintf("mouseOver: ipos=%s,%s", ipos.x, ipos.y); + this.message(t, 0); +}; + +// callback when mouse moves out of the image +PLUGIN.mouseout = function(im, ipos, evt){ + var t = sprintf("mouseOut: ipos=%s,%s", ipos.x, ipos.y); + this.message(t, 0); +}; + +// callback when key is pressed +PLUGIN.keypress = function(im, ipos, evt){ + var charCode = evt.which || evt.keyCode; + var charStr = String.fromCharCode(charCode); + var t = sprintf("keyPress: %s -> %s", charCode, charStr); + this.message(t, 2); +}; + +// callback when regions change +PLUGIN.regionschange = function(im, xreg){ + var i; + var mode = xreg.mode.substring(0,1).toUpperCase()+xreg.mode.substring(1); + var t = sprintf("%s%s: ", xreg.shape, mode); + switch(xreg.shape){ + case "annulus": + t += sprintf("ipos=%.2f,%.2f radii=", xreg.x, xreg.y); + for(i=0; i +#include +#include +#include +#include + +#define PNG_DEBUG 3 +#include + +void abort_(const char * s, ...) +{ + va_list args; + va_start(args, s); + vfprintf(stderr, s, args); + fprintf(stderr, "\n"); + va_end(args); + abort(); +} + +int x, y; + +int width, height, rowbytes; +png_byte channels; +png_byte color_type; +png_byte bit_depth; + +png_structp png_ptr; +png_infop info_ptr; +int number_of_passes; +png_bytep * row_pointers; + +void read_png_file(char* file_name) +{ + unsigned char header[8]; // 8 is the maximum size that can be checked + + /* open file and test for it being a png */ + FILE *fp = fopen(file_name, "rb"); + if (!fp) + abort_("[read_png_file] File %s could not be opened for reading", file_name); + fread(header, 1, 8, fp); + if (png_sig_cmp(header, 0, 8)) + abort_("[read_png_file] File %s is not recognized as a PNG file", file_name); + + + /* initialize stuff */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png_ptr) + abort_("[read_png_file] png_create_read_struct failed"); + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + abort_("[read_png_file] png_create_info_struct failed"); + + if (setjmp(png_jmpbuf(png_ptr))) + abort_("[read_png_file] Error during init_io"); + + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + + png_read_info(png_ptr, info_ptr); + + width = png_get_image_width(png_ptr, info_ptr); + height = png_get_image_height(png_ptr, info_ptr); + channels = png_get_channels(png_ptr, info_ptr); + color_type = png_get_color_type(png_ptr, info_ptr); + bit_depth = png_get_bit_depth(png_ptr, info_ptr); + + printf("width=%d height=%d color=%d channels=%d bitdepth=%d\n\n", + width, height, color_type, channels, bit_depth); + + number_of_passes = png_set_interlace_handling(png_ptr); + png_read_update_info(png_ptr, info_ptr); + + /* read file */ + if (setjmp(png_jmpbuf(png_ptr))) + abort_("[read_png_file] Error during read_image"); + + row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); + + if (bit_depth == 16) + rowbytes = width*channels*2; + else + rowbytes = width*channels; + + for (y=0; y"); + + read_png_file(argv[1]); + process_file(); + + return 0; +} diff --git a/saoconfig b/saoconfig new file mode 100755 index 00000000..f931143f --- /dev/null +++ b/saoconfig @@ -0,0 +1,124 @@ +#!/bin/sh +# set -x +rm -rf ./config.cache + +if [ x"$1" = x ]; then + name=`uname -n` +else + if [ x"$1" = x"--" ]; then + name=`uname -n` + else + name="$1" + fi + shift +fi + +if [ x"$CFLAGS" = x ]; then + CFLAGS="-g" + export CFLAGS +fi +if [ x"$LDFLAGS" = x ]; then + LDFLAGS="-g" + export LDFLAGS +fi + +GCCFLAGS="-W -Wall -Wno-implicit-int" +STRICTFLAGS="-pedantic -Wall -Wpointer-arith -Wcast-align -Wstrict-prototypes -Wredundant-decls -Wnested-externs -Wconversion -Wno-implicit-int" +CF="--config-cache" + +echo "configure for: " $name + +case $name in + strict) + ./configure $CF \ + CC=gcc CFLAGS="$CFLAGS $STRICTFLAGS" $* + ;; + + bokhara*) + ./configure $CF \ + --prefix=/soft/saord \ + --with-webdir=/home/mred/public_html/htdocs/js9 \ + --with-helper=get \ + --with-funtools=/soft/saord \ + --with-png=/proj/rd/linux64 \ + --with-cgidir=/home/mred/public_html/cgi-bin/js9 \ + --with-cgiurl=./cgi-bin/js9 \ + --with-cgixpath=/soft/saord/bin \ + CC=gcc CFLAGS="$CFLAGS $GCCFLAGS" \ + $* + ;; + + mred*) + ./configure $CF \ + --prefix=/export/eric \ + --with-webdir=/home/mred/public_html/htdocs/js9 \ + --with-helper="nodejs" \ + --with-funtools=/home/mred/pub/usr/local \ + CC=gcc CFLAGS="$CFLAGS $GCCFLAGS" \ + $* + ;; + + smartx*) + ./configure $CF \ + --prefix=/smartx \ + --with-webdir=/smartx/www/html/js9 \ + --with-helper=nodejs \ + --with-funtools=/smartx \ + --with-png=/smartx \ + CC=gcc CFLAGS="$CFLAGS $GCCFLAGS" \ + $* + ;; + + baba.local|baba-nodejs) + ./configure $CF \ + --prefix=$HOME \ + --with-webdir=/Users/eric/Sites/js9 \ + --with-helper="socket.io" \ + --with-funtools=/usr/local \ + --with-png=/usr/local \ + --with-saodir=/Users/eric/Sites \ + CC=gcc CFLAGS="$CFLAGS $GCCFLAGS" $* + ;; + + baba-cgi) + ./configure $CF \ + --prefix=$HOME \ + --with-webdir=/Users/eric/Sites/js9 \ + --with-helper=get \ + --with-funtools=/usr/local \ + --with-png=/usr/local \ + --with-cgidir=/Users/eric/Sites/cgi-bin \ + --with-cgiurl="~eric/cgi-bin" \ + --with-cgixpath=/usr/local/bin \ + --with-saodir=/Users/eric/Sites \ + CC=gcc CFLAGS="$CFLAGS $GCCFLAGS" $* + ;; + + baba-none) + ./configure $CF --with-webdir=/Users/eric/Sites/js9 + ;; + + hopper*) + ./configure $CF \ + --prefix=$HOME \ + --with-webdir=$HOME/http/js9 \ + --with-helper=nodejs \ + --with-funtools=$HOME \ + --with-saodir=$HOME/http \ + CC=gcc CFLAGS="$CFLAGS $GCCFLAGS" $* + ;; + + ascpub*) + ASCPUB=/proj/web-chandra/htdocs/edu/stop/js9 + ./configure $CF \ + --with-webdir=$ASCPUB \ + --with-helper=none \ + CC=gcc CFLAGS="$CFLAGS $GCCFLAGS" \ + $* + ;; + + *) + ./configure $CF $* + ;; + +esac diff --git a/saoprefs.sed b/saoprefs.sed new file mode 100644 index 00000000..27a0483b --- /dev/null +++ b/saoprefs.sed @@ -0,0 +1,3 @@ +s#\("scale" *:.*"\)[^"]*\("\)#\1log\2# +s#\("pngisfits" *: *\)false\(.*\)#\1true\2# +s#\("fits2png" *: *\)false\(.*\)#\1true\2# diff --git a/tpos.c b/tpos.c new file mode 100644 index 00000000..f1df9a44 --- /dev/null +++ b/tpos.c @@ -0,0 +1,425 @@ +#include +#include +#include + +#if HAVE_CONFIG_H +#include +#endif +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_STRING_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_MALLOC_H +#include +#endif +#if HAVE_GETOPT_H +#include +#else +extern char *optarg; +extern int optind; +#endif + +#define ABS(x) ((x)<0?(-x):(x)) + +/* NB: if you change the format of the png file, update the version number: + * update major version number for an incompatible change + * update minor version number for a backwards-compatible change + */ +#define JS9_PROTOCOL "1.0" +/* endian: little or big */ +#define JS9_ENDIAN "little" +/* 3 bytes per png pixel. NB: RGBA is bad because of precalculated alpha */ +#define MY_PNG_COLOR_TYPE PNG_COLOR_TYPE_RGB +/* NB: channels has to match color type above, i.e. RGB==3, RGBA==4 */ +#define COLOR_CHANNELS 3 +/* bytes/channel */ +#define MY_BIT_DEPTH 8 +/* totally arbitrary */ +#define MAX_TEXT 10 + +/* text info structure */ +typedef struct optinforec{ + char *fitsname; + char *fitsheader; +} *Optinfo, OptinfoRec; + +/* writePNG can be made funtools-clean by unsetting this variable */ +#define GIO_IN_PNG 1 + +/* scat -- append a string onto another, reallocating space as needed */ +static void scat(char *str, char **ostr) +{ + static int olen=0; + int blen; + int slen; + + if( (str == NULL) || (*str == '\0') ) + return; + else + slen = strlen(str) + 1; + + if( (*ostr == NULL) || (**ostr == '\0') ) + blen = 0; + else + blen = strlen(*ostr); + + while( (blen + slen) >= olen ){ + olen += SZ_LINE; + } + if( blen == 0 ) + *ostr = (char *)xcalloc(olen, sizeof(char)); + else + *ostr = (char *)xrealloc(*ostr, olen); + strcat(*ostr, str); +} + +/* generate JS9-specific parameters to add to header */ +static char *_js9Params=NULL; +static char *js9Params() +{ + char tbuf[SZ_LINE]; + snprintf(tbuf, SZ_LINE-1, "\"js9Protocol\":%s, ", JS9_PROTOCOL); + scat(tbuf, &_js9Params); + snprintf(tbuf, SZ_LINE-1, "\"js9Endian\":\"%s\", ", JS9_ENDIAN); + scat(tbuf, &_js9Params); + return _js9Params; +} + + +/* + * image is width x height buffer containing int data of size COLOR_CHANNELS + * + * image should be in little-endian format, so that low pixel values go into + * the red channel (instead of alpha channel). + * + */ +int writePNG(FILE *ofp, void *image, int width, int height, Optinfo optinfo) +{ + int k; + int ntext = 0; + png_structp png_ptr; + png_infop info_ptr; + png_bytep imptr; + png_bytep row_pointers[height]; + png_text texts[MAX_TEXT]; + + /* set up row pointers for image data */ + imptr = (png_bytep)image; + for(k=0; kfitsname && *optinfo->fitsname ){ + if( ntext < MAX_TEXT ){ + texts[ntext].compression = PNG_TEXT_COMPRESSION_NONE; + texts[ntext].key = "fitsfile"; + texts[ntext].text = optinfo->fitsname; + ntext++; + } + } + if( optinfo->fitsheader && *optinfo->fitsheader ){ + if( ntext < MAX_TEXT ){ + /* texts[ntext].compression = PNG_TEXT_COMPRESSION_NONE; */ + texts[ntext].compression = PNG_TEXT_COMPRESSION_zTXt; + texts[ntext].key = "fitsheader"; + texts[ntext].text = optinfo->fitsheader; + ntext++; + } + } + png_set_text(png_ptr, info_ptr, texts, ntext); + + /* Write the file header information. REQUIRED */ + png_write_info(png_ptr, info_ptr); + + /* Now you can write the image data. The simplest way to do this + is in one function call. If you have the whole image in memory, + you can just call png_write_image() and libpng will write the + image. You will need to pass in an array of pointers to each + row. */ + png_write_image(png_ptr, row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + return 0; +} + +int main(int argc, char **argv) +{ + int c, i, j, got, dtype, args, bitpix, jsonlen, len, istart; + int idim1, idim2, odim1, odim2, pad; + size_t totbytes; + int verbose=0; + char *buf=NULL; + char *s; + char tbuf[SZ_LINE]; + char tbuf2[SZ_LINE]; + char tbuf3[SZ_LINE]; + char tbuf4[SZ_LINE]; + char *jsonheader=NULL; + char *iname=NULL, *oname=NULL; + Fun ifun=NULL, tfun=NULL; + FILE *ofp=NULL; + Optinfo optinfo; + + /* exit on gio errors */ + setgerror(2); + + /* we want the args in the same order in which they arrived, and + gnu getopt sometimes changes things without this */ + putenv("POSIXLY_CORRECT=true"); + + /* process switch arguments */ + while ((c = getopt(argc, argv, "v")) != -1){ + switch(c){ + case 'v': + verbose++; + break; + } + } + + /* check for required arguments */ + args = argc - optind; + if( args < 2 ) + gerror(stderr, "usage: %s iname oname\n", argv[0]); + iname = argv[optind++]; + oname = argv[optind++]; + + /* optional info */ + if( !(optinfo = (Optinfo)xcalloc(sizeof(OptinfoRec), 1)) ){ + gerror(stderr, "can't allocate optional info rec\n"); + } + + /* open the input FITS file */ + if( !(ifun = FunOpen(iname, "r", NULL)) ){ + gerror(stderr, "could not open input FITS file: %s (%s)\n", + iname, strerror(errno)); + } + + /* save the input filename in the png file */ + optinfo->fitsname = iname; + + /* open the output PGN file */ + if( !strcmp(oname, "-") || !strcmp(oname, "stdout") ){ + ofp = stdout; + } else if( !(ofp = fopen(oname, "w")) ){ + gerror(stderr, "could not create output PNG file: %s (%s)\n", + oname, strerror(errno)); + } + + /* copy the input fits header into a FITS image header */ + if( !(tfun = (Fun)xcalloc(1, sizeof(FunRec))) ){ + gerror(stderr, "could not create tfun struct\n"); + } + _FunCopy2ImageHeader(ifun, tfun); + /* and save for storage in the png file */ + optinfo->fitsheader = (char *)tfun->header->cards; + + /* get image parameters. its safe to do this before callingimage get + so long as we don't change bitpix before that call */ + FunInfoGet(ifun, + FUN_SECT_BITPIX, &bitpix, + FUN_SECT_DIM1, &idim1, + FUN_SECT_DIM2, &idim2, + 0); + + /* convert FITS header into a json string */ + for(*tbuf3='\0', i=1; ;i++){ + if( (s = FunParamGets(tfun, NULL, i, NULL, &dtype)) ){ + snprintf(tbuf, SZ_LINE-1, "%8.8s", s); + nowhite(tbuf, tbuf); + nowhite((char *)ft_cardget((FITSCard)s), tbuf2); + len = strlen(tbuf2); + /* pre-processing of values */ + switch(dtype){ + case 'l': + if( strchr(tbuf2, 'F') ){ + strcpy(tbuf2, "false"); + } else { + strcpy(tbuf2, "true"); + } + break; + case 'r': + if( tbuf2[len-1] == '.' ){ + strcat(tbuf2, "0"); + } + break; + case 's': + /* change single quotes to double quotes */ + if( *tbuf2 == '\'' ){ + *tbuf2 = '"'; + } + if( tbuf[len-1] == '\'' ){ + tbuf[len-1] = '"'; + } + break; + default: + break; + } + /* skip some repeating keywords */ + if( dtype != 'c' && + strncmp(tbuf, " ", 8) && + (*tbuf2 != '\0') ){ + if( *tbuf3 == '\0' ){ + snprintf(tbuf4, SZ_LINE, "{%s", js9Params()); + scat(tbuf4, &jsonheader); + } else { + scat(", ", &jsonheader); + } + /* format key/value pair */ + switch(dtype){ + case 's': + snprintf(tbuf3, SZ_LINE, "\"%s\":\"%s\"", tbuf, tbuf2); + break; + default: + snprintf(tbuf3, SZ_LINE, "\"%s\":%s", tbuf, tbuf2); + break; + } + scat(tbuf3, &jsonheader); + } + xfree(s); + } + else{ + /* end of input */ + scat("}", &jsonheader); + break; + } + } + + /* we want the image buffer to start on an 8-byte boundary, + so make jsonheader + null byte end on one */ + pad = 8 - (strlen(jsonheader) % 8) - 1; + for(i=0; i odim=%d,%d [%d]\n", + idim1, idim2, bitpix, jsonlen, istart, JS9_ENDIAN, totbytes, + odim1, odim2, odim1 * odim2 * COLOR_CHANNELS); + } + + /* extract and bin the data section into an image buffer */ + if( !FunImageGet(ifun, &buf[istart], NULL) ){ + gerror(stderr, "could not FunImageGet: %s\n", iname); + } + + /* might have to swap to preferred endian for png creation */ + if( (!strncmp(JS9_ENDIAN, "l", 1) && is_bigendian()) || + (!strncmp(JS9_ENDIAN, "b", 1) && !is_bigendian()) ){ + swap_data(&buf[istart], idim1 * idim2, bitpix/8); + } + + /* debugging output to check against javascript input */ + if( verbose > 1 ){ + fprintf(stderr, "jsonheader: %s\n", jsonheader); + for(j=0; j<4; j++){ + fprintf(stderr, "data #%d: ", j); + for(i=0; i